From fb139a7a0126bbc2f8a9caa17e7ed563668fcbfe Mon Sep 17 00:00:00 2001 From: edxeth Date: Wed, 18 Feb 2026 20:14:47 +0100 Subject: [PATCH] fix(custom-agents): preserve summary flags during description merge --- src/plugin-handlers/config-handler.test.ts | 62 ++++++++++++++++++++++ src/plugin-handlers/custom-agent-utils.ts | 18 ++++--- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/src/plugin-handlers/config-handler.test.ts b/src/plugin-handlers/config-handler.test.ts index c91752df..264460f1 100644 --- a/src/plugin-handlers/config-handler.test.ts +++ b/src/plugin-handlers/config-handler.test.ts @@ -351,6 +351,68 @@ describe("custom agent overrides", () => { expect(agentsConfig[pKey].prompt).toContain("translator") expect(agentsConfig[pKey].prompt).not.toContain("ghostwriter") }) + + test("custom agent summary merge preserves flags when custom_agents adds description", async () => { + // #given + ;(agentLoader.loadUserAgents as any).mockReturnValue({ + translator: { + name: "translator", + mode: "subagent", + description: "", + hidden: true, + disabled: true, + enabled: false, + prompt: "Translate content", + }, + }) + const createBuiltinAgentsMock = agents.createBuiltinAgents as unknown as { + mock: { calls: unknown[][] } + } + + const pluginConfig: OhMyOpenCodeConfig = { + custom_agents: { + translator: { + description: "Translate and localize locale files", + }, + }, + sisyphus_agent: { + planner_enabled: true, + }, + } + const config: Record = { + model: "anthropic/claude-opus-4-6", + agent: {}, + } + + const handler = createConfigHandler({ + ctx: { directory: "/tmp" }, + pluginConfig, + modelCacheState: { + anthropicContext1MEnabled: false, + modelContextLimitsCache: new Map(), + }, + }) + + // #when + await handler(config) + + // #then + const firstCallArgs = createBuiltinAgentsMock.mock.calls[0] + const summaries = firstCallArgs[7] as Array<{ + name: string + description: string + hidden?: boolean + disabled?: boolean + enabled?: boolean + }> + const translatorSummary = summaries.find((summary) => summary.name === "translator") + + expect(translatorSummary).toBeDefined() + expect(translatorSummary?.description).toBe("Translate and localize locale files") + expect(translatorSummary?.hidden).toBe(true) + expect(translatorSummary?.disabled).toBe(true) + expect(translatorSummary?.enabled).toBe(false) + }) }) describe("Plan agent demote behavior", () => { diff --git a/src/plugin-handlers/custom-agent-utils.ts b/src/plugin-handlers/custom-agent-utils.ts index de96ad90..eb056872 100644 --- a/src/plugin-handlers/custom-agent-utils.ts +++ b/src/plugin-handlers/custom-agent-utils.ts @@ -74,9 +74,9 @@ export function collectCustomAgentSummariesFromRecord( summaries.push({ name, description, - hidden: agentValue.hidden === true, - disabled: agentValue.disabled === true, - enabled: agentValue.enabled === false ? false : true, + hidden: typeof agentValue.hidden === "boolean" ? agentValue.hidden : undefined, + disabled: typeof agentValue.disabled === "boolean" ? agentValue.disabled : undefined, + enabled: typeof agentValue.enabled === "boolean" ? agentValue.enabled : undefined, }); } @@ -99,9 +99,15 @@ export function mergeCustomAgentSummaries(...summaryGroups: AgentSummary[][]): A const existingDescription = existing.description.trim(); const incomingDescription = summary.description.trim(); - if (!existingDescription && incomingDescription) { - merged.set(key, summary); - } + + merged.set(key, { + ...existing, + ...summary, + hidden: summary.hidden ?? existing.hidden, + disabled: summary.disabled ?? existing.disabled, + enabled: summary.enabled ?? existing.enabled, + description: incomingDescription || existingDescription, + }); } }