From afa48c64ca74caaa53e1fd31ecb56cb6b70f1825 Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Thu, 21 May 2026 10:52:37 -0300 Subject: [PATCH] fix(settings): append Global System Prompt after provider/agent instructions (#2468) --- open-sse/services/systemPrompt.ts | 13 ++++++++----- tests/unit/system-prompt.test.ts | 18 ++++++++++-------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/open-sse/services/systemPrompt.ts b/open-sse/services/systemPrompt.ts index f584a011aa..95dce9100a 100644 --- a/open-sse/services/systemPrompt.ts +++ b/open-sse/services/systemPrompt.ts @@ -44,21 +44,24 @@ export function injectSystemPrompt(body, promptText = null) { const sysIdx = result.messages.findIndex((m) => m.role === "system" || m.role === "developer"); result.messages = [...result.messages]; if (sysIdx >= 0) { - // Prepend to existing system message + // Append after existing system content so the global prompt is the FINAL + // instruction — provider/agent system blocks (Kiro, OpenCode, Hermes, etc.) + // are injected into the system message later, and recency bias means the + // user's global prompt must come after them to take priority (#2468). const msg = { ...result.messages[sysIdx] }; - msg.content = text + "\n\n" + (msg.content || ""); + msg.content = (msg.content || "") + "\n\n" + text; result.messages[sysIdx] = msg; } else { result.messages = [{ role: "system", content: text }, ...result.messages]; } } - // Claude format (system field) + // Claude format (system field) — append for the same reason as above (#2468). if (result.system !== undefined) { if (typeof result.system === "string") { - result.system = text + "\n\n" + result.system; + result.system = result.system + "\n\n" + text; } else if (Array.isArray(result.system)) { - result.system = [{ type: "text", text }, ...result.system]; + result.system = [...result.system, { type: "text", text }]; } } diff --git a/tests/unit/system-prompt.test.ts b/tests/unit/system-prompt.test.ts index a90ff52bdd..fa53470988 100644 --- a/tests/unit/system-prompt.test.ts +++ b/tests/unit/system-prompt.test.ts @@ -30,7 +30,7 @@ test("injectSystemPrompt: adds system message when none exists", () => { assert.equal(result.messages.length, 2); }); -test("injectSystemPrompt: prepends to existing system message", () => { +test("injectSystemPrompt: appends after existing system message (#2468)", () => { setSystemPromptConfig({ enabled: true, prompt: "GLOBAL:" }); const body = { messages: [ @@ -39,23 +39,24 @@ test("injectSystemPrompt: prepends to existing system message", () => { ], }; const result = injectSystemPrompt(body); - assert.ok(result.messages[0].content.startsWith("GLOBAL:")); - assert.ok(result.messages[0].content.includes("Original prompt")); + // Global prompt must be the FINAL instruction so it wins over provider/agent blocks. + assert.ok(result.messages[0].content.startsWith("Original prompt")); + assert.ok(result.messages[0].content.trimEnd().endsWith("GLOBAL:")); assert.equal(result.messages.length, 2); }); -test("injectSystemPrompt: Claude body.system field", () => { +test("injectSystemPrompt: Claude body.system field appends global last (#2468)", () => { setSystemPromptConfig({ enabled: true, prompt: "GLOBAL:" }); const body = { system: "Claude prompt", messages: [{ role: "user", content: "hi" }], }; const result = injectSystemPrompt(body); - assert.ok(result.system.startsWith("GLOBAL:")); - assert.ok(result.system.includes("Claude prompt")); + assert.ok(result.system.startsWith("Claude prompt")); + assert.ok(result.system.trimEnd().endsWith("GLOBAL:")); }); -test("injectSystemPrompt: Claude array system field", () => { +test("injectSystemPrompt: Claude array system field appends global last (#2468)", () => { setSystemPromptConfig({ enabled: true, prompt: "GLOBAL:" }); const body = { system: [{ type: "text", text: "Claude prompt" }], @@ -63,7 +64,8 @@ test("injectSystemPrompt: Claude array system field", () => { }; const result = injectSystemPrompt(body); assert.ok(Array.isArray(result.system)); - assert.equal(result.system[0].text, "GLOBAL:"); + assert.equal(result.system[0].text, "Claude prompt"); + assert.equal(result.system[result.system.length - 1].text, "GLOBAL:"); assert.equal(result.system.length, 2); });