diff --git a/src/agents/atlas.ts b/src/agents/atlas.ts index ec0881da9..2ca08b7a4 100644 --- a/src/agents/atlas.ts +++ b/src/agents/atlas.ts @@ -1,5 +1,7 @@ import type { AgentConfig } from "@opencode-ai/sdk" -import type { AgentPromptMetadata } from "./types" +import type { AgentMode, AgentPromptMetadata } from "./types" + +const MODE: AgentMode = "primary" import type { AvailableAgent, AvailableSkill, AvailableCategory } from "./dynamic-agent-prompt-builder" import { buildCategorySkillsDelegationGuide } from "./dynamic-agent-prompt-builder" import type { CategoryConfig } from "../config/schema" @@ -530,7 +532,7 @@ export function createAtlasAgent(ctx: OrchestratorContext): AgentConfig { return { description: "Orchestrates work via delegate_task() to complete ALL tasks in a todo list until fully done. (Atlas - OhMyOpenCode)", - mode: "primary" as const, + mode: MODE, ...(ctx.model ? { model: ctx.model } : {}), temperature: 0.1, prompt: buildDynamicOrchestratorPrompt(ctx), @@ -539,6 +541,7 @@ export function createAtlasAgent(ctx: OrchestratorContext): AgentConfig { ...restrictions, } as AgentConfig } +createAtlasAgent.mode = MODE export const atlasPromptMetadata: AgentPromptMetadata = { category: "advisor", diff --git a/src/agents/explore.ts b/src/agents/explore.ts index 28b6b8714..0e01e279f 100644 --- a/src/agents/explore.ts +++ b/src/agents/explore.ts @@ -1,7 +1,9 @@ import type { AgentConfig } from "@opencode-ai/sdk" -import type { AgentPromptMetadata } from "./types" +import type { AgentMode, AgentPromptMetadata } from "./types" import { createAgentToolRestrictions } from "../shared/permission-compat" +const MODE: AgentMode = "subagent" + export const EXPLORE_PROMPT_METADATA: AgentPromptMetadata = { category: "exploration", cost: "FREE", @@ -34,7 +36,7 @@ export function createExploreAgent(model: string): AgentConfig { return { description: 'Contextual grep for codebases. Answers "Where is X?", "Which file has Y?", "Find the code that does Z". Fire multiple in parallel for broad searches. Specify thoroughness: "quick" for basic, "medium" for moderate, "very thorough" for comprehensive analysis. (Explore - OhMyOpenCode)', - mode: "subagent" as const, + mode: MODE, model, temperature: 0.1, ...restrictions, @@ -119,4 +121,4 @@ Use the right tool for the job: Flood with parallel calls. Cross-validate findings across multiple tools.`, } } - +createExploreAgent.mode = MODE diff --git a/src/agents/librarian.ts b/src/agents/librarian.ts index 1638680d6..1588cfb3c 100644 --- a/src/agents/librarian.ts +++ b/src/agents/librarian.ts @@ -325,4 +325,4 @@ grep_app_searchGitHub(query: "useQuery") `, } } - +createLibrarianAgent.mode = MODE diff --git a/src/agents/metis.ts b/src/agents/metis.ts index 81a8e44aa..88ae6b014 100644 --- a/src/agents/metis.ts +++ b/src/agents/metis.ts @@ -1,7 +1,9 @@ import type { AgentConfig } from "@opencode-ai/sdk" -import type { AgentPromptMetadata } from "./types" +import type { AgentMode, AgentPromptMetadata } from "./types" import { createAgentToolRestrictions } from "../shared/permission-compat" +const MODE: AgentMode = "subagent" + /** * Metis - Plan Consultant Agent * @@ -311,7 +313,7 @@ export function createMetisAgent(model: string): AgentConfig { return { description: "Pre-planning consultant that analyzes requests to identify hidden intentions, ambiguities, and AI failure points. (Metis - OhMyOpenCode)", - mode: "subagent" as const, + mode: MODE, model, temperature: 0.3, ...metisRestrictions, @@ -319,7 +321,7 @@ export function createMetisAgent(model: string): AgentConfig { thinking: { type: "enabled", budgetTokens: 32000 }, } as AgentConfig } - +createMetisAgent.mode = MODE export const metisPromptMetadata: AgentPromptMetadata = { category: "advisor", diff --git a/src/agents/momus.ts b/src/agents/momus.ts index afa5b6731..7ec1f070a 100644 --- a/src/agents/momus.ts +++ b/src/agents/momus.ts @@ -1,8 +1,10 @@ import type { AgentConfig } from "@opencode-ai/sdk" -import type { AgentPromptMetadata } from "./types" +import type { AgentMode, AgentPromptMetadata } from "./types" import { isGptModel } from "./types" import { createAgentToolRestrictions } from "../shared/permission-compat" +const MODE: AgentMode = "subagent" + /** * Momus - Plan Reviewer Agent * @@ -400,7 +402,7 @@ export function createMomusAgent(model: string): AgentConfig { const base = { description: "Expert reviewer for evaluating work plans against rigorous clarity, verifiability, and completeness standards. (Momus - OhMyOpenCode)", - mode: "subagent" as const, + mode: MODE, model, temperature: 0.1, ...restrictions, @@ -413,7 +415,7 @@ export function createMomusAgent(model: string): AgentConfig { return { ...base, thinking: { type: "enabled", budgetTokens: 32000 } } as AgentConfig } - +createMomusAgent.mode = MODE export const momusPromptMetadata: AgentPromptMetadata = { category: "advisor", diff --git a/src/agents/multimodal-looker.ts b/src/agents/multimodal-looker.ts index 9793b83af..b6fe79fe4 100644 --- a/src/agents/multimodal-looker.ts +++ b/src/agents/multimodal-looker.ts @@ -1,7 +1,9 @@ import type { AgentConfig } from "@opencode-ai/sdk" -import type { AgentPromptMetadata } from "./types" +import type { AgentMode, AgentPromptMetadata } from "./types" import { createAgentToolAllowlist } from "../shared/permission-compat" +const MODE: AgentMode = "subagent" + export const MULTIMODAL_LOOKER_PROMPT_METADATA: AgentPromptMetadata = { category: "utility", cost: "CHEAP", @@ -15,7 +17,7 @@ export function createMultimodalLookerAgent(model: string): AgentConfig { return { description: "Analyze media files (PDFs, images, diagrams) that require interpretation beyond raw text. Extracts specific information or summaries from documents, describes visual content. Use when you need analyzed/extracted data rather than literal file contents. (Multimodal-Looker - OhMyOpenCode)", - mode: "subagent" as const, + mode: MODE, model, temperature: 0.1, ...restrictions, @@ -53,4 +55,4 @@ Response rules: Your output goes straight to the main agent for continued work.`, } } - +createMultimodalLookerAgent.mode = MODE diff --git a/src/agents/sisyphus.ts b/src/agents/sisyphus.ts index ed87ad2f1..37c276c8e 100644 --- a/src/agents/sisyphus.ts +++ b/src/agents/sisyphus.ts @@ -1,5 +1,8 @@ import type { AgentConfig } from "@opencode-ai/sdk" +import type { AgentMode } from "./types" import { isGptModel } from "./types" + +const MODE: AgentMode = "primary" import type { AvailableAgent, AvailableTool, AvailableSkill, AvailableCategory } from "./dynamic-agent-prompt-builder" import { buildKeyTriggersSection, @@ -434,7 +437,7 @@ export function createSisyphusAgent( const base = { description: "Powerful AI orchestrator. Plans obsessively with todos, assesses search complexity before exploration, delegates strategically via category+skills combinations. Uses explore for internal code (parallel-friendly), librarian for external docs. (Sisyphus - OhMyOpenCode)", - mode: "primary" as const, + mode: MODE, model, maxTokens: 64000, prompt, @@ -448,3 +451,4 @@ export function createSisyphusAgent( return { ...base, thinking: { type: "enabled", budgetTokens: 32000 } } } +createSisyphusAgent.mode = MODE diff --git a/src/agents/types.ts b/src/agents/types.ts index 5c21c3320..6692162b2 100644 --- a/src/agents/types.ts +++ b/src/agents/types.ts @@ -1,6 +1,20 @@ import type { AgentConfig } from "@opencode-ai/sdk" -export type AgentFactory = (model: string) => AgentConfig +/** + * Agent mode determines UI model selection behavior: + * - "primary": Respects user's UI-selected model (sisyphus, atlas) + * - "subagent": Uses own fallback chain, ignores UI selection (oracle, explore, etc.) + * - "all": Available in both contexts (OpenCode compatibility) + */ +export type AgentMode = "primary" | "subagent" | "all" + +/** + * Agent factory function with static mode property. + * Mode is exposed as static property for pre-instantiation access. + */ +export type AgentFactory = ((model: string) => AgentConfig) & { + mode: AgentMode +} /** * Agent category for grouping in Sisyphus prompt sections diff --git a/src/agents/utils.ts b/src/agents/utils.ts index 7e9f6169d..acc848130 100644 --- a/src/agents/utils.ts +++ b/src/agents/utils.ts @@ -225,8 +225,10 @@ export async function createBuiltinAgents( const override = findCaseInsensitive(agentOverrides, agentName) const requirement = AGENT_MODEL_REQUIREMENTS[agentName] + const isPrimaryAgent = isFactory(source) && source.mode === "primary" + const resolution = resolveModelWithFallback({ - uiSelectedModel, + uiSelectedModel: isPrimaryAgent ? uiSelectedModel : undefined, userModel: override?.model, fallbackChain: requirement?.fallbackChain, availableModels,