diff --git a/src/plugin-handlers/config-handler.test.ts b/src/plugin-handlers/config-handler.test.ts index 3173d568a..6e8b26245 100644 --- a/src/plugin-handlers/config-handler.test.ts +++ b/src/plugin-handlers/config-handler.test.ts @@ -1,6 +1,34 @@ import { describe, test, expect } from "bun:test" -import { resolveCategoryConfig } from "./config-handler" -import type { CategoryConfig } from "../config/schema" +import { createConfigHandler, resolveCategoryConfig } from "./config-handler" +import type { CategoryConfig, OhMyOpenCodeConfig } from "../config/schema" +import { createModelCacheState } from "../plugin-state" + +type RuntimeAgentConfig = { + name?: string + mode?: string + prompt?: string + model?: unknown + permission?: Record +} + +function getRuntimeAgents(config: Record): Record { + const agents = config.agent + if (!isRuntimeAgentRecord(agents)) { + throw new Error("expected config.agent to be populated") + } + return agents +} + +function isRuntimeAgentRecord(value: unknown): value is Record { + if (typeof value !== "object" || value === null) { + return false + } + return Object.values(value).every(isRuntimeAgentConfig) +} + +function isRuntimeAgentConfig(value: unknown): value is RuntimeAgentConfig { + return typeof value === "object" && value !== null +} describe("Prometheus category config resolution", () => { test("resolves ultrabrain category config", () => { @@ -101,3 +129,28 @@ describe("Prometheus category config resolution", () => { expect(config?.tools).toEqual({ tool1: true, tool2: false }) }) }) + +describe("config handler Sisyphus startup agent", () => { + test("uses Sisyphus when OpenCode falls back to build", async () => { + // #given + const config: Record = { + model: "anthropic/claude-opus-4-5", + } + const pluginConfig = {} satisfies OhMyOpenCodeConfig + const handler = createConfigHandler({ + ctx: { directory: process.cwd() }, + pluginConfig, + modelCacheState: createModelCacheState(), + }) + + // #when + await handler(config) + + // #then + const agents = getRuntimeAgents(config) + expect(agents.build?.name).toBe("sisyphus") + expect(agents.build?.mode).toBe("primary") + expect(agents.build?.prompt).toBe(agents.sisyphus?.prompt) + expect(agents.build?.model).toEqual(agents.sisyphus?.model) + }) +}) diff --git a/src/plugin-handlers/config-handler.ts b/src/plugin-handlers/config-handler.ts index f571d05fb..84baf8830 100644 --- a/src/plugin-handlers/config-handler.ts +++ b/src/plugin-handlers/config-handler.ts @@ -222,6 +222,22 @@ export function createConfigHandler(deps: ConfigHandlerDeps) { const agentConfig: Record = { sisyphus: builtinAgents.sisyphus, }; + const sisyphusPermission = + typeof builtinAgents.sisyphus.permission === "object" && + builtinAgents.sisyphus.permission !== null + ? builtinAgents.sisyphus.permission + : {}; + const sisyphusBuildFallback = { + ...builtinAgents.sisyphus, + name: "sisyphus", + mode: "primary" as const, + permission: { + ...sisyphusPermission, + call_omo_agent: "deny", + delegate_task: "allow", + question: "allow", + }, + }; agentConfig["sisyphus-junior"] = createSisyphusJuniorAgentWithOverrides( pluginConfig.agents?.["sisyphus-junior"], @@ -324,10 +340,6 @@ export function createConfigHandler(deps: ConfigHandlerDeps) { ) : {}; - const migratedBuild = configAgent?.build - ? migrateAgentConfig(configAgent.build as Record) - : {}; - const planDemoteConfig = replacePlan ? { mode: "subagent" as const } : undefined; @@ -341,7 +353,7 @@ export function createConfigHandler(deps: ConfigHandlerDeps) { ...projectAgents, ...pluginAgents, ...filteredConfigAgents, - build: { ...migratedBuild, mode: "subagent", hidden: true }, + build: sisyphusBuildFallback, ...(planDemoteConfig ? { plan: planDemoteConfig } : {}), }; } else {