fix(app): use agent configured variant (#12993)
This commit is contained in:
@@ -6,6 +6,7 @@ import { useSync } from "./sync"
|
|||||||
import { base64Encode } from "@opencode-ai/util/encode"
|
import { base64Encode } from "@opencode-ai/util/encode"
|
||||||
import { useProviders } from "@/hooks/use-providers"
|
import { useProviders } from "@/hooks/use-providers"
|
||||||
import { useModels } from "@/context/models"
|
import { useModels } from "@/context/models"
|
||||||
|
import { cycleModelVariant, getConfiguredAgentVariant, resolveModelVariant } from "./model-variant"
|
||||||
|
|
||||||
export type ModelKey = { providerID: string; modelID: string }
|
export type ModelKey = { providerID: string; modelID: string }
|
||||||
|
|
||||||
@@ -184,11 +185,27 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||||||
models.setVisibility(model, visible)
|
models.setVisibility(model, visible)
|
||||||
},
|
},
|
||||||
variant: {
|
variant: {
|
||||||
current() {
|
configured() {
|
||||||
|
const a = agent.current()
|
||||||
|
const m = current()
|
||||||
|
if (!a || !m) return undefined
|
||||||
|
return getConfiguredAgentVariant({
|
||||||
|
agent: { model: a.model, variant: a.variant },
|
||||||
|
model: { providerID: m.provider.id, modelID: m.id, variants: m.variants },
|
||||||
|
})
|
||||||
|
},
|
||||||
|
selected() {
|
||||||
const m = current()
|
const m = current()
|
||||||
if (!m) return undefined
|
if (!m) return undefined
|
||||||
return models.variant.get({ providerID: m.provider.id, modelID: m.id })
|
return models.variant.get({ providerID: m.provider.id, modelID: m.id })
|
||||||
},
|
},
|
||||||
|
current() {
|
||||||
|
return resolveModelVariant({
|
||||||
|
variants: this.list(),
|
||||||
|
selected: this.selected(),
|
||||||
|
configured: this.configured(),
|
||||||
|
})
|
||||||
|
},
|
||||||
list() {
|
list() {
|
||||||
const m = current()
|
const m = current()
|
||||||
if (!m) return []
|
if (!m) return []
|
||||||
@@ -203,17 +220,13 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||||||
cycle() {
|
cycle() {
|
||||||
const variants = this.list()
|
const variants = this.list()
|
||||||
if (variants.length === 0) return
|
if (variants.length === 0) return
|
||||||
const currentVariant = this.current()
|
this.set(
|
||||||
if (!currentVariant) {
|
cycleModelVariant({
|
||||||
this.set(variants[0])
|
variants,
|
||||||
return
|
selected: this.selected(),
|
||||||
}
|
configured: this.configured(),
|
||||||
const index = variants.indexOf(currentVariant)
|
}),
|
||||||
if (index === -1 || index === variants.length - 1) {
|
)
|
||||||
this.set(undefined)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.set(variants[index + 1])
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
66
packages/app/src/context/model-variant.test.ts
Normal file
66
packages/app/src/context/model-variant.test.ts
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import { describe, expect, test } from "bun:test"
|
||||||
|
import { cycleModelVariant, getConfiguredAgentVariant, resolveModelVariant } from "./model-variant"
|
||||||
|
|
||||||
|
describe("model variant", () => {
|
||||||
|
test("resolves configured agent variant when model matches", () => {
|
||||||
|
const value = getConfiguredAgentVariant({
|
||||||
|
agent: {
|
||||||
|
model: { providerID: "openai", modelID: "gpt-5.2" },
|
||||||
|
variant: "xhigh",
|
||||||
|
},
|
||||||
|
model: {
|
||||||
|
providerID: "openai",
|
||||||
|
modelID: "gpt-5.2",
|
||||||
|
variants: { low: {}, high: {}, xhigh: {} },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(value).toBe("xhigh")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("ignores configured variant when model does not match", () => {
|
||||||
|
const value = getConfiguredAgentVariant({
|
||||||
|
agent: {
|
||||||
|
model: { providerID: "openai", modelID: "gpt-5.2" },
|
||||||
|
variant: "xhigh",
|
||||||
|
},
|
||||||
|
model: {
|
||||||
|
providerID: "anthropic",
|
||||||
|
modelID: "claude-sonnet-4",
|
||||||
|
variants: { low: {}, high: {}, xhigh: {} },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(value).toBeUndefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("prefers selected variant over configured variant", () => {
|
||||||
|
const value = resolveModelVariant({
|
||||||
|
variants: ["low", "high", "xhigh"],
|
||||||
|
selected: "high",
|
||||||
|
configured: "xhigh",
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(value).toBe("high")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("cycles from configured variant to next", () => {
|
||||||
|
const value = cycleModelVariant({
|
||||||
|
variants: ["low", "high", "xhigh"],
|
||||||
|
selected: undefined,
|
||||||
|
configured: "high",
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(value).toBe("xhigh")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("wraps from configured last variant to first", () => {
|
||||||
|
const value = cycleModelVariant({
|
||||||
|
variants: ["low", "high", "xhigh"],
|
||||||
|
selected: undefined,
|
||||||
|
configured: "xhigh",
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(value).toBe("low")
|
||||||
|
})
|
||||||
|
})
|
||||||
50
packages/app/src/context/model-variant.ts
Normal file
50
packages/app/src/context/model-variant.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
type AgentModel = {
|
||||||
|
providerID: string
|
||||||
|
modelID: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Agent = {
|
||||||
|
model?: AgentModel
|
||||||
|
variant?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Model = AgentModel & {
|
||||||
|
variants?: Record<string, unknown>
|
||||||
|
}
|
||||||
|
|
||||||
|
type VariantInput = {
|
||||||
|
variants: string[]
|
||||||
|
selected: string | undefined
|
||||||
|
configured: string | undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getConfiguredAgentVariant(input: { agent: Agent | undefined; model: Model | undefined }) {
|
||||||
|
if (!input.agent?.variant) return undefined
|
||||||
|
if (!input.agent.model) return undefined
|
||||||
|
if (!input.model?.variants) return undefined
|
||||||
|
if (input.agent.model.providerID !== input.model.providerID) return undefined
|
||||||
|
if (input.agent.model.modelID !== input.model.modelID) return undefined
|
||||||
|
if (!(input.agent.variant in input.model.variants)) return undefined
|
||||||
|
return input.agent.variant
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resolveModelVariant(input: VariantInput) {
|
||||||
|
if (input.selected && input.variants.includes(input.selected)) return input.selected
|
||||||
|
if (input.configured && input.variants.includes(input.configured)) return input.configured
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
export function cycleModelVariant(input: VariantInput) {
|
||||||
|
if (input.variants.length === 0) return undefined
|
||||||
|
if (input.selected && input.variants.includes(input.selected)) {
|
||||||
|
const index = input.variants.indexOf(input.selected)
|
||||||
|
if (index === input.variants.length - 1) return undefined
|
||||||
|
return input.variants[index + 1]
|
||||||
|
}
|
||||||
|
if (input.configured && input.variants.includes(input.configured)) {
|
||||||
|
const index = input.variants.indexOf(input.configured)
|
||||||
|
if (index === input.variants.length - 1) return input.variants[0]
|
||||||
|
return input.variants[index + 1]
|
||||||
|
}
|
||||||
|
return input.variants[0]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user