Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .opencode/agent/triage.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mode: primary
hidden: true
model: opencode/claude-haiku-4-5
color: "#44BA81"
variant: "high"
tools:
"*": false
"github-triage": true
Expand Down
2 changes: 2 additions & 0 deletions packages/opencode/src/agent/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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 ?? {}))
}
Expand Down
4 changes: 3 additions & 1 deletion packages/opencode/src/cli/cmd/tui/component/dialog-agent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
}
}),
)
Expand Down
6 changes: 3 additions & 3 deletions packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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(() => {
Expand Down Expand Up @@ -944,7 +944,7 @@ export function Prompt(props: PromptProps) {
<Show when={showVariant()}>
<text fg={theme.textMuted}>·</text>
<text>
<span style={{ fg: theme.warning, bold: true }}>{local.model.variant.current()}</span>
<span style={{ fg: theme.warning, bold: true }}>{local.model.variant.effective()}</span>
</text>
</Show>
</box>
Expand Down
8 changes: 6 additions & 2 deletions packages/opencode/src/cli/cmd/tui/context/local.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 []
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions packages/opencode/src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand All @@ -493,6 +494,7 @@ export namespace Config {
"color",
"steps",
"maxSteps",
"variant",
"options",
"permission",
"disable",
Expand Down
4 changes: 2 additions & 2 deletions packages/opencode/src/session/llm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
1 change: 1 addition & 0 deletions packages/opencode/src/tool/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions packages/sdk/js/src/v2/gen/types.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1930,6 +1934,7 @@ export type Agent = {
[key: string]: unknown
}
steps?: number
variant?: string
}

export type McpStatusConnected = {
Expand Down