From 9d217b05b8fd6b709e1104e0330b2628d39454b4 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Tue, 3 Feb 2026 13:37:57 +0900 Subject: [PATCH] fix(config-handler): preserve plan prompt when demoted (#1416) --- src/plugin-handlers/config-handler.test.ts | 111 +++++++++++++++++++++ src/plugin-handlers/config-handler.ts | 7 +- 2 files changed, 115 insertions(+), 3 deletions(-) diff --git a/src/plugin-handlers/config-handler.test.ts b/src/plugin-handlers/config-handler.test.ts index 7c095101..62a4b0d0 100644 --- a/src/plugin-handlers/config-handler.test.ts +++ b/src/plugin-handlers/config-handler.test.ts @@ -184,6 +184,117 @@ describe("Plan agent demote behavior", () => { expect(agents.plan.prompt).not.toBe(agents.prometheus?.prompt) }) + test("plan agent should not be demoted when replacePlan is false", async () => { + // given + const pluginConfig: OhMyOpenCodeConfig = { + sisyphus_agent: { + planner_enabled: true, + replace_plan: false, + }, + } + const config: Record = { + model: "anthropic/claude-opus-4-5", + agent: { + plan: { + name: "plan", + mode: "primary", + prompt: "original plan prompt", + }, + }, + } + const handler = createConfigHandler({ + ctx: { directory: "/tmp" }, + pluginConfig, + modelCacheState: { + anthropicContext1MEnabled: false, + modelContextLimitsCache: new Map(), + }, + }) + + // when + await handler(config) + + // then + const agents = config.agent as Record + expect(agents.plan).toBeDefined() + expect(agents.plan.mode).toBe("primary") + expect(agents.plan.name).toBe("plan") + expect(agents.plan.prompt).toBe("original plan prompt") + }) + + test("plan agent should not be demoted when planner is disabled", async () => { + // given + const pluginConfig: OhMyOpenCodeConfig = { + sisyphus_agent: { + planner_enabled: false, + replace_plan: true, + }, + } + const config: Record = { + model: "anthropic/claude-opus-4-5", + agent: { + plan: { + name: "plan", + mode: "primary", + prompt: "original plan prompt", + }, + }, + } + const handler = createConfigHandler({ + ctx: { directory: "/tmp" }, + pluginConfig, + modelCacheState: { + anthropicContext1MEnabled: false, + modelContextLimitsCache: new Map(), + }, + }) + + // when + await handler(config) + + // then + const agents = config.agent as Record + expect(agents.prometheus).toBeUndefined() + expect(agents.plan).toBeDefined() + expect(agents.plan.mode).toBe("primary") + }) + + test("preserves empty plan prompt when demoting", async () => { + // given + const pluginConfig: OhMyOpenCodeConfig = { + sisyphus_agent: { + planner_enabled: true, + replace_plan: true, + }, + } + const config: Record = { + model: "anthropic/claude-opus-4-5", + agent: { + plan: { + name: "plan", + mode: "primary", + prompt: "", + }, + }, + } + const handler = createConfigHandler({ + ctx: { directory: "/tmp" }, + pluginConfig, + modelCacheState: { + anthropicContext1MEnabled: false, + modelContextLimitsCache: new Map(), + }, + }) + + // when + await handler(config) + + // then + const agents = config.agent as Record + expect(agents.plan).toBeDefined() + expect(agents.plan.prompt).toBe("") + }) + test("prometheus should have mode 'all' to be callable via delegate_task", async () => { // given const pluginConfig: OhMyOpenCodeConfig = { diff --git a/src/plugin-handlers/config-handler.ts b/src/plugin-handlers/config-handler.ts index 15dc7732..ce0390ce 100644 --- a/src/plugin-handlers/config-handler.ts +++ b/src/plugin-handlers/config-handler.ts @@ -195,6 +195,7 @@ export function createConfigHandler(deps: ConfigHandlerDeps) { const plannerEnabled = pluginConfig.sisyphus_agent?.planner_enabled ?? true; const replacePlan = pluginConfig.sisyphus_agent?.replace_plan ?? true; + const shouldReplacePlan = plannerEnabled && replacePlan; type AgentConfig = Record< string, @@ -344,7 +345,7 @@ export function createConfigHandler(deps: ConfigHandlerDeps) { Object.entries(configAgent) .filter(([key]) => { if (key === "build") return false; - if (key === "plan" && replacePlan) return false; + if (key === "plan" && shouldReplacePlan) return false; // Filter out agents that oh-my-opencode provides to prevent // OpenCode defaults from overwriting user config in oh-my-opencode.json // See: https://github.com/code-yeongyu/oh-my-opencode/issues/472 @@ -362,12 +363,12 @@ export function createConfigHandler(deps: ConfigHandlerDeps) { ? migrateAgentConfig(configAgent.build as Record) : {}; - const planDemoteConfig = replacePlan && agentConfig["prometheus"] + const planDemoteConfig = shouldReplacePlan && agentConfig["prometheus"] ? { ...agentConfig["prometheus"], name: "plan", mode: "subagent" as const, - ...(planPrompt ? { prompt: planPrompt } : {}), + ...(typeof planPrompt === "string" ? { prompt: planPrompt } : {}), } : undefined;