diff --git a/.opencode/agent/triage.md b/.opencode/agent/triage.md index 539be154917..000947e5a4c 100644 --- a/.opencode/agent/triage.md +++ b/.opencode/agent/triage.md @@ -3,6 +3,7 @@ mode: primary hidden: true model: opencode/claude-haiku-4-5 color: "#44BA81" +variant: "high" tools: "*": false "github-triage": true diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index 21859186659..57993ca64ef 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -34,6 +34,7 @@ export namespace Agent { prompt: z.string().optional(), options: z.record(z.string(), z.any()), steps: z.number().int().positive().optional(), + variant: z.string().optional(), }) .meta({ ref: "Agent", @@ -190,6 +191,7 @@ export namespace Agent { item.color = value.color ?? item.color item.name = value.name ?? item.name item.steps = value.steps ?? item.steps + item.variant = value.variant ?? item.variant item.options = mergeDeep(item.options, value.options ?? {}) item.permission = PermissionNext.merge(item.permission, PermissionNext.fromConfig(value.permission ?? {})) } diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx index 365a22445b4..d5312bd44b4 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx @@ -9,10 +9,12 @@ export function DialogAgent() { const options = createMemo(() => local.agent.list().map((item) => { + const desc = item.native ? "native" : item.description + const variant = item.variant ? ` (${item.variant})` : "" return { value: item.name, title: item.name, - description: item.native ? "native" : item.description, + description: desc ? desc + variant : variant.trim(), } }), ) diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx index 4558914cb7e..b8eeb8b9f59 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx @@ -697,8 +697,8 @@ export function Prompt(props: PromptProps) { const showVariant = createMemo(() => { const variants = local.model.variant.list() if (variants.length === 0) return false - const current = local.model.variant.current() - return !!current + const effective = local.model.variant.effective() + return !!effective }) const spinnerDef = createMemo(() => { @@ -944,7 +944,7 @@ export function Prompt(props: PromptProps) { ยท - {local.model.variant.current()} + {local.model.variant.effective()} diff --git a/packages/opencode/src/cli/cmd/tui/context/local.tsx b/packages/opencode/src/cli/cmd/tui/context/local.tsx index b60a775b375..b36232fa323 100644 --- a/packages/opencode/src/cli/cmd/tui/context/local.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/local.tsx @@ -313,6 +313,9 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ const key = `${m.providerID}/${m.modelID}` return modelStore.variant[key] }, + effective() { + return this.current() ?? agent.current().variant + }, list() { const m = currentModel() if (!m) return [] @@ -332,11 +335,12 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ const variants = this.list() if (variants.length === 0) return const current = this.current() - if (!current) { + const effective = this.effective() + if (!effective) { this.set(variants[0]) return } - const index = variants.indexOf(current) + const index = variants.indexOf(effective) if (index === -1 || index === variants.length - 1) { this.set(undefined) return diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 130031f020e..c2e5939a34b 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -478,6 +478,7 @@ export namespace Config { .optional() .describe("Maximum number of agentic iterations before forcing text-only response"), maxSteps: z.number().int().positive().optional().describe("@deprecated Use 'steps' field instead."), + variant: z.string().optional().describe("Default model variant for this agent (e.g., 'high', 'low', 'max')"), permission: Permission.optional(), }) .catchall(z.any()) @@ -493,6 +494,7 @@ export namespace Config { "color", "steps", "maxSteps", + "variant", "options", "permission", "disable", diff --git a/packages/opencode/src/session/llm.ts b/packages/opencode/src/session/llm.ts index 7e2967e31ba..a06d9ba5ec0 100644 --- a/packages/opencode/src/session/llm.ts +++ b/packages/opencode/src/session/llm.ts @@ -83,8 +83,8 @@ export namespace LLM { const provider = await Provider.getProvider(input.model.providerID) const small = input.small ? ProviderTransform.smallOptions(input.model) : {} - const variant = - !input.small && input.model.variants && input.user.variant ? input.model.variants[input.user.variant] : {} + const variantKey = input.user.variant ?? input.agent.variant + const variant = !input.small && input.model.variants && variantKey ? input.model.variants[variantKey] : {} const options = pipe( ProviderTransform.options(input.model, input.sessionID, provider.options), mergeDeep(small), diff --git a/packages/opencode/src/tool/task.ts b/packages/opencode/src/tool/task.ts index 3489f3bf7fb..d3a7d8e9fee 100644 --- a/packages/opencode/src/tool/task.ts +++ b/packages/opencode/src/tool/task.ts @@ -132,6 +132,7 @@ export const TaskTool = Tool.define("task", async () => { providerID: model.providerID, }, agent: agent.name, + variant: agent.variant, tools: { todowrite: false, todoread: false, diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index fb3be8208ac..2a390d0ccbe 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -1274,6 +1274,10 @@ export type AgentConfig = { * @deprecated Use 'steps' field instead. */ maxSteps?: number + /** + * Default model variant for this agent (e.g., 'high', 'low', 'max') + */ + variant?: string permission?: PermissionConfig [key: string]: | unknown @@ -1930,6 +1934,7 @@ export type Agent = { [key: string]: unknown } steps?: number + variant?: string } export type McpStatusConnected = {