Linux execve limits arguments to 128KB, causing Paperclip to fail with spawn E2BIG on large prompts. Adds runtime patch to write prompt to /tmp/hermes-prompt-*.txt and pass via Hermes native --query-file flag, while cleaning up file after execution and filtering oversized env vars.
95 lines
3.8 KiB
JavaScript
95 lines
3.8 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
console.log('[Patch PaperClip] Starting runtime patches...');
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// 1. Fix Hermes E2BIG: Write prompt to --query-file instead of passing in argv
|
|
// ---------------------------------------------------------------------------
|
|
const hermesExecutePath = '/app/packages/adapters/hermes/src/server/execute.ts';
|
|
if (fs.existsSync(hermesExecutePath)) {
|
|
let content = fs.readFileSync(hermesExecutePath, 'utf8');
|
|
|
|
// Replace "-q", prompt with --query-file
|
|
const oldArgs = 'const args: string[] = ["chat", "-q", prompt];';
|
|
const newArgs = `const promptFile = path.join("/tmp", \`hermes-prompt-\${ctx.runId || Date.now()}.txt\`);
|
|
await fs.writeFile(promptFile, prompt, "utf-8");
|
|
const args: string[] = ["chat", "--query-file", promptFile];`;
|
|
|
|
if (content.includes(oldArgs)) {
|
|
content = content.replace(oldArgs, newArgs);
|
|
|
|
// Add cleanup in finally block
|
|
const oldRun = ` const result = await runChildProcess(ctx.runId, hermesCmd, args, {
|
|
cwd,
|
|
env,
|
|
timeoutSec,
|
|
graceSec,
|
|
onLog: wrappedOnLog,
|
|
onSpawn: ctx.onSpawn,
|
|
});`;
|
|
|
|
const newRun = ` let result;
|
|
try {
|
|
result = await runChildProcess(ctx.runId, hermesCmd, args, {
|
|
cwd,
|
|
env,
|
|
timeoutSec,
|
|
graceSec,
|
|
onLog: wrappedOnLog,
|
|
onSpawn: ctx.onSpawn,
|
|
});
|
|
} finally {
|
|
await fs.unlink(promptFile).catch(() => {});
|
|
}`;
|
|
|
|
if (content.includes(oldRun)) {
|
|
content = content.replace(oldRun, newRun);
|
|
}
|
|
|
|
fs.writeFileSync(hermesExecutePath, content, 'utf8');
|
|
console.log('[Patch PaperClip] Successfully patched hermes execute.ts for --query-file (fixes spawn E2BIG)!');
|
|
} else {
|
|
console.log('[Patch PaperClip] hermes execute.ts already patched or target pattern not found.');
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// 2. Fix server-utils E2BIG: filter monster environment variables (>32KB)
|
|
// ---------------------------------------------------------------------------
|
|
const serverUtilsPath = '/app/packages/adapter-utils/src/server-utils.ts';
|
|
if (fs.existsSync(serverUtilsPath)) {
|
|
let content = fs.readFileSync(serverUtilsPath, 'utf8');
|
|
const oldEnvLoop = ` for (const [key, value] of Object.entries(childEnv)) {
|
|
if (value === undefined) delete childEnv[key];
|
|
}`;
|
|
const newEnvLoop = ` for (const [key, value] of Object.entries(childEnv)) {
|
|
if (value === undefined || (typeof value === "string" && value.length > 32768)) delete childEnv[key];
|
|
}`;
|
|
|
|
if (content.includes(oldEnvLoop)) {
|
|
content = content.replace(oldEnvLoop, newEnvLoop);
|
|
fs.writeFileSync(serverUtilsPath, content, 'utf8');
|
|
console.log('[Patch PaperClip] Successfully patched server-utils.ts to guard against env E2BIG!');
|
|
} else {
|
|
console.log('[Patch PaperClip] server-utils.ts already patched or target pattern not found.');
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// 3. Fix AI Connection endpoint for OpenRouter / custom base URLs
|
|
// ---------------------------------------------------------------------------
|
|
const aiConnPath = '/app/server/dist/routes/ai-connections.js';
|
|
if (fs.existsSync(aiConnPath)) {
|
|
let content = fs.readFileSync(aiConnPath, 'utf8');
|
|
const target = '"https://api.openai.com/v1/models"';
|
|
const replacement = 'process.env.OPENAI_BASE_URL ? process.env.OPENAI_BASE_URL + "/models" : "https://api.openai.com/v1/models"';
|
|
if (content.includes(target)) {
|
|
content = content.split(target).join(replacement);
|
|
fs.writeFileSync(aiConnPath, content, 'utf8');
|
|
console.log('[Patch PaperClip] Successfully patched ai-connections.js for OPENAI_BASE_URL!');
|
|
}
|
|
}
|
|
|
|
console.log('[Patch PaperClip] All patches completed.');
|