fix(opencode): scope agent variant to model (#11410)

This commit is contained in:
neavo
2026-02-02 04:12:30 +08:00
committed by GitHub
parent 16145af480
commit f15755684f
5 changed files with 111 additions and 2 deletions

View File

@@ -37,6 +37,7 @@ export namespace Agent {
providerID: z.string(),
})
.optional(),
variant: z.string().optional(),
prompt: z.string().optional(),
options: z.record(z.string(), z.any()),
steps: z.number().int().positive().optional(),
@@ -214,6 +215,7 @@ export namespace Agent {
native: false,
}
if (value.model) item.model = Provider.parseModel(value.model)
item.variant = value.variant ?? item.variant
item.prompt = value.prompt ?? item.prompt
item.description = value.description ?? item.description
item.temperature = value.temperature ?? item.temperature

View File

@@ -593,6 +593,10 @@ export namespace Config {
export const Agent = z
.object({
model: z.string().optional(),
variant: z
.string()
.optional()
.describe("Default model variant for this agent (applies only when using the agent's configured model)."),
temperature: z.number().optional(),
top_p: z.number().optional(),
prompt: z.string().optional(),
@@ -624,6 +628,7 @@ export namespace Config {
const knownKeys = new Set([
"name",
"model",
"variant",
"prompt",
"description",
"temperature",

View File

@@ -827,6 +827,17 @@ export namespace SessionPrompt {
async function createUserMessage(input: PromptInput) {
const agent = await Agent.get(input.agent ?? (await Agent.defaultAgent()))
const model = input.model ?? agent.model ?? (await lastModel(input.sessionID))
const variant =
input.variant ??
(agent.variant &&
agent.model &&
model.providerID === agent.model.providerID &&
model.modelID === agent.model.modelID
? agent.variant
: undefined)
const info: MessageV2.Info = {
id: input.messageID ?? Identifier.ascending("message"),
role: "user",
@@ -836,9 +847,9 @@ export namespace SessionPrompt {
},
tools: input.tools,
agent: agent.name,
model: input.model ?? agent.model ?? (await lastModel(input.sessionID)),
model,
system: input.system,
variant: input.variant,
variant,
}
using _ = defer(() => InstructionPrompt.clear(info.id))

View File

@@ -255,6 +255,37 @@ test("handles agent configuration", async () => {
})
})
test("treats agent variant as model-scoped setting (not provider option)", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await writeConfig(dir, {
$schema: "https://opencode.ai/config.json",
agent: {
test_agent: {
model: "openai/gpt-5.2",
variant: "xhigh",
max_tokens: 123,
},
},
})
},
})
await Instance.provide({
directory: tmp.path,
fn: async () => {
const config = await Config.get()
const agent = config.agent?.["test_agent"]
expect(agent?.variant).toBe("xhigh")
expect(agent?.options).toMatchObject({
max_tokens: 123,
})
expect(agent?.options).not.toHaveProperty("variant")
},
})
})
test("handles command configuration", async () => {
await using tmp = await tmpdir({
init: async (dir) => {

View File

@@ -0,0 +1,60 @@
import { describe, expect, test } from "bun:test"
import { Instance } from "../../src/project/instance"
import { Session } from "../../src/session"
import { SessionPrompt } from "../../src/session/prompt"
import { tmpdir } from "../fixture/fixture"
describe("session.prompt agent variant", () => {
test("applies agent variant only when using agent model", async () => {
await using tmp = await tmpdir({
git: true,
config: {
agent: {
build: {
model: "openai/gpt-5.2",
variant: "xhigh",
},
},
},
})
await Instance.provide({
directory: tmp.path,
fn: async () => {
const session = await Session.create({})
const other = await SessionPrompt.prompt({
sessionID: session.id,
agent: "build",
model: { providerID: "opencode", modelID: "kimi-k2.5-free" },
noReply: true,
parts: [{ type: "text", text: "hello" }],
})
if (other.info.role !== "user") throw new Error("expected user message")
expect(other.info.variant).toBeUndefined()
const match = await SessionPrompt.prompt({
sessionID: session.id,
agent: "build",
noReply: true,
parts: [{ type: "text", text: "hello again" }],
})
if (match.info.role !== "user") throw new Error("expected user message")
expect(match.info.model).toEqual({ providerID: "openai", modelID: "gpt-5.2" })
expect(match.info.variant).toBe("xhigh")
const override = await SessionPrompt.prompt({
sessionID: session.id,
agent: "build",
noReply: true,
variant: "high",
parts: [{ type: "text", text: "hello third" }],
})
if (override.info.role !== "user") throw new Error("expected user message")
expect(override.info.variant).toBe("high")
await Session.remove(session.id)
},
})
})
})