From b9150f2b46bd882a28b3f61e72bc821229c0659f Mon Sep 17 00:00:00 2001 From: duffyduck Date: Fri, 10 Jul 2026 20:43:36 +0200 Subject: [PATCH] prep(proxy): System-Prompt fuer echten CLI-Kanal separat bereitstellen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vorbereitung fuer die saubere Variante: ARIA-Persona ueber den ECHTEN System-Prompt-Kanal der Claude-CLI (--append-system-prompt) zustellen statt als -getaggten User-Content (den das Modell als Prompt-Injection wertet und der ARIA aus der Rolle wirft — siehe a0e8c23). - openai-to-cli.js: extractSystemPrompt() (System-Messages + Tool-Block als roher Text, ohne -Tags) und conversationToPrompt() (nur Verlauf). openaiToCli() liefert jetzt zusaetzlich systemPrompt + conversationPrompt. - routes.js: reicht systemPrompt an subprocess.start(..) durch. BEWUSST rueckwaertskompatibel/no-op: prompt bleibt unveraendert (System-Inhalt noch drin), die Extra-Option wird von einem ungepatchten manager.js ignoriert. Der letzte Schritt (manager.js: --append-system-prompt beim Spawn + prompt auf conversationPrompt umstellen) folgt, sobald die echte manager.js-Struktur vorliegt — die npm-Datei liegt nicht im Repo und ein Fehlpatch legt den kompletten Proxy lahm. Co-Authored-By: Claude Opus 4.8 (1M context) --- proxy-patches/openai-to-cli.js | 71 ++++++++++++++++++++++++++++++++++ proxy-patches/routes.js | 6 +++ 2 files changed, 77 insertions(+) diff --git a/proxy-patches/openai-to-cli.js b/proxy-patches/openai-to-cli.js index 86cd8ac..82151ea 100644 --- a/proxy-patches/openai-to-cli.js +++ b/proxy-patches/openai-to-cli.js @@ -150,9 +150,80 @@ export function messagesToPrompt(messages, tools) { return parts.join("\n").trim(); } +/** + * Extrahiert NUR den System-Anteil (System-Messages + Tool-Use-Block) als + * rohen Text — OHNE -Tags. Fuer den ECHTEN System-Prompt-Kanal der + * Claude-CLI (--append-system-prompt), damit die ARIA-Persona nicht als + * -getaggter User-Content ankommt (den das Modell als Injection wertet), + * sondern als genuine System-Instruktion. + * Reihenfolge: erst der Tool-Use-Block (Format-Anweisung), dann die + * System-Messages in Original-Reihenfolge. + */ +export function extractSystemPrompt(messages, tools) { + const chunks = []; + const toolsBlock = _toolsBlock(tools); + if (toolsBlock) chunks.push(toolsBlock); + for (const msg of messages || []) { + if (msg && msg.role === "system") { + const t = _text(msg.content).trim(); + if (t) chunks.push(t); + } + } + return chunks.join("\n\n").trim(); +} + +/** + * Wie messagesToPrompt, aber OHNE System-Messages und OHNE Tool-Block — nur der + * eigentliche Verlauf (user/assistant/tool). Fuer den Modus, in dem der + * System-Prompt ueber --append-system-prompt separat zugestellt wird. + */ +export function conversationToPrompt(messages) { + const parts = []; + for (const msg of messages || []) { + if (!msg) continue; + switch (msg.role) { + case "system": + break; // geht ueber --append-system-prompt + case "user": + parts.push(_text(msg.content)); + break; + case "assistant": { + const txt = _text(msg.content); + const tcs = Array.isArray(msg.tool_calls) ? msg.tool_calls : []; + const tcParts = tcs.map((tc) => { + const name = tc?.function?.name || tc?.name || ""; + let args = tc?.function?.arguments ?? tc?.arguments ?? "{}"; + if (typeof args !== "string") { + try { args = JSON.stringify(args); } catch (_) { args = "{}"; } + } + return `${args}`; + }).join("\n"); + const combined = [txt, tcParts].filter(Boolean).join("\n").trim(); + if (combined) parts.push(`\n${combined}\n\n`); + break; + } + case "tool": { + const name = msg.name || ""; + const id = msg.tool_call_id || ""; + parts.push( + `\n${_text(msg.content)}\n\n` + ); + break; + } + } + } + return parts.join("\n").trim(); +} + export function openaiToCli(request) { return { + // prompt: solange manager.js --append-system-prompt noch NICHT nutzt, + // bleibt der System-Inhalt zusaetzlich im Prompt (messagesToPrompt), sonst + // ginge die Persona verloren. Sobald der echte Kanal steht: hier auf + // conversationPrompt umstellen. prompt: messagesToPrompt(request.messages, request.tools), + systemPrompt: extractSystemPrompt(request.messages, request.tools), + conversationPrompt: conversationToPrompt(request.messages), model: extractModel(request.model), sessionId: request.user, }; diff --git a/proxy-patches/routes.js b/proxy-patches/routes.js index 35f9d96..2542188 100644 --- a/proxy-patches/routes.js +++ b/proxy-patches/routes.js @@ -355,6 +355,10 @@ async function handleStreamingResponse(req, res, subprocess, cliInput, requestId subprocess.start(cliInput.prompt, { model: cliInput.model, sessionId: cliInput.sessionId, + // ARIA: echter System-Prompt-Kanal — manager.js reicht das (sobald + // gepatcht) als --append-system-prompt an die CLI. Aktuell ignoriert + // ein ungepatchter manager diese Extra-Option gefahrlos. + systemPrompt: cliInput.systemPrompt, }).catch((err) => { console.error("[Streaming] Subprocess start error:", err); reject(err); @@ -422,6 +426,8 @@ async function handleNonStreamingResponse(res, subprocess, cliInput, requestId) .start(cliInput.prompt, { model: cliInput.model, sessionId: cliInput.sessionId, + // ARIA: echter System-Prompt-Kanal (siehe Streaming-Branch). + systemPrompt: cliInput.systemPrompt, }) .catch((error) => { res.status(500).json({