fix: Forward full systemPrompt preset options from _meta (#591)

Closes #581

Pass through object-based systemPrompt options from _meta while
forcing the claude_code preset, and add tests for defaulting,
string replacement, option forwarding, and override protection.
This commit is contained in:
Ben Brandt
2026-04-24 16:08:04 +02:00
committed by GitHub
parent e09f1486f1
commit b3ddfc3b86
2 changed files with 98 additions and 3 deletions

View File

@@ -1582,10 +1582,16 @@ export class ClaudeAcpAgent implements Agent {
systemPrompt = customPrompt;
} else if (
typeof customPrompt === "object" &&
"append" in customPrompt &&
typeof customPrompt.append === "string"
customPrompt !== null &&
!Array.isArray(customPrompt)
) {
systemPrompt.append = customPrompt.append;
// Forward all preset options (append, excludeDynamicSections, and
// anything the SDK adds later) while locking type/preset.
systemPrompt = {
...(customPrompt as object),
type: "preset",
preset: "claude_code",
} as Options["systemPrompt"];
}
}

View File

@@ -253,6 +253,95 @@ describe("createSession options merging", () => {
expect(capturedOptions!.tools).toEqual([]);
});
describe("systemPrompt via _meta", () => {
it("defaults to the claude_code preset when not provided", async () => {
await agent.newSession({ cwd: "/test", mcpServers: [] });
expect(capturedOptions!.systemPrompt).toEqual({
type: "preset",
preset: "claude_code",
});
});
it("replaces the preset when a string is provided", async () => {
await agent.newSession({
cwd: "/test",
mcpServers: [],
_meta: { systemPrompt: "custom prompt" },
});
expect(capturedOptions!.systemPrompt).toBe("custom prompt");
});
it("forwards append", async () => {
await agent.newSession({
cwd: "/test",
mcpServers: [],
_meta: { systemPrompt: { append: "extra instructions" } },
});
expect(capturedOptions!.systemPrompt).toEqual({
type: "preset",
preset: "claude_code",
append: "extra instructions",
});
});
it("forwards excludeDynamicSections", async () => {
await agent.newSession({
cwd: "/test",
mcpServers: [],
_meta: { systemPrompt: { excludeDynamicSections: true } },
});
expect(capturedOptions!.systemPrompt).toEqual({
type: "preset",
preset: "claude_code",
excludeDynamicSections: true,
});
});
it("forwards append and excludeDynamicSections together", async () => {
await agent.newSession({
cwd: "/test",
mcpServers: [],
_meta: {
systemPrompt: {
append: "extra instructions",
excludeDynamicSections: true,
},
},
});
expect(capturedOptions!.systemPrompt).toEqual({
type: "preset",
preset: "claude_code",
append: "extra instructions",
excludeDynamicSections: true,
});
});
it("ignores caller-provided type/preset overrides", async () => {
await agent.newSession({
cwd: "/test",
mcpServers: [],
_meta: {
systemPrompt: {
type: "something-else",
preset: "other-preset",
append: "extra",
},
},
});
expect(capturedOptions!.systemPrompt).toEqual({
type: "preset",
preset: "claude_code",
append: "extra",
});
});
});
describe("CLAUDE_MODEL_CONFIG", () => {
let originalModelConfig: string | undefined;