Files
PaperClip/services/paperclip/patch_paperclip.js
T
Jannik ee101b4a73 fix: Resolve spawn E2BIG by passing Hermes prompt via --query-file
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.
2026-10-02 07:10:06 +02:00

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.');