fix(agent-manager): align modal model resolution

This commit is contained in:
marius-kilocode
2026-08-03 11:57:15 +02:00
parent 20d1648e7a
commit 76e34bdcf0
6 changed files with 63 additions and 12 deletions
@@ -3,6 +3,7 @@ import {
type ModelStore,
type ResolveEnv,
applyModel,
getAgentModel,
getSessionModel,
getSelected,
} from "../../webview-ui/src/context/session-model-store"
@@ -149,14 +150,20 @@ describe("per-session model selection", () => {
})
describe("per-mode model memory", () => {
it("resolves a specific mode's remembered model without a session", () => {
let store = emptyStore()
const e = env()
it("uses remembered model selections for modes without configured models", () => {
const store = { ...emptyStore(), modelSelections: { ask: gpt } }
const result = applyModel(store, "ask", gpt, undefined)
store = { ...store, ...result }
expect(getAgentModel(store, env(), "ask")).toEqual(gpt)
})
expect(getSelected(store, e, undefined, "ask")).toEqual(gpt)
it("ignores stale remembered selections when a configured mode model is user-set", () => {
const configured: ResolveEnv = {
...env(),
getModeModel: (name) => (name === "code" ? claude : null),
}
const store = { ...emptyStore(), modelSelections: { code: gpt } }
expect(getAgentModel(store, configured, "code", true)).toEqual(claude)
})
it("applyModel in a session writes only to sessionOverrides", () => {
@@ -1,6 +1,7 @@
import { describe, expect, it } from "bun:test"
import {
cycleVariant,
getAgentVariant,
getVariant,
sessionVariantKeys,
sessionVariants,
@@ -43,6 +44,13 @@ describe("per-session variant selection", () => {
expect(getVariant(store, model, variants, "ask")).toBe("high")
})
it("resolves the effective variant for a mode and model", () => {
const store: Record<string, string> = {}
store[variantKey(model, "ask")] = "high"
expect(getAgentVariant(store, model, { variants: { low: {}, high: {} } }, "ask")).toBe("high")
})
it("carries the pre-submit agent variant into a newly created session", () => {
const store: Record<string, string> = {}
@@ -107,7 +107,7 @@ export const NewWorktreeDialog: Component<{
const [prompt, setPrompt] = createSignal((cached?.advancedDialogPrompt as string) ?? "")
const [versions, setVersions] = createSignal<VersionCount>(1)
const initialAgent = session.selectedAgent()
const initialModel = session.configModelForAgent(initialAgent)
const initialModel = session.modelForAgent(initialAgent)
const [model, setModel] = createSignal<{ providerID: string; modelID: string } | null>(initialModel)
const [compareMode, setCompareMode] = createSignal(false)
const [modelAllocations, setModelAllocations] = createSignal<ModelAllocations>(new Map())
@@ -78,6 +78,17 @@ export function getSelected(
return resolveModel(env, agentName, store.modelSelections[agentName], store.recentModels)
}
/** Returns the effective model for a mode outside a session scope. */
export function getAgentModel(
store: ModelStore,
env: ResolveEnv,
agentName: string,
userSet = false,
): ModelSelection | null {
const override = env.getModeModel(agentName) && userSet ? null : store.modelSelections[agentName]
return resolveModel(env, agentName, override, store.recentModels)
}
export interface ApplyResult {
modelSelections: Record<string, ModelSelection | null>
sessionOverrides: Record<string, ModelSelection>
@@ -24,6 +24,16 @@ export function getVariant(
return stored && variants.includes(stored) ? stored : variants[0]
}
export function getAgentVariant(
store: Record<string, string>,
sel: ModelSelection,
model: { variants?: Record<string, unknown> } | undefined,
agent: string,
) {
if (!model?.variants) return undefined
return getVariant(store, sel, Object.keys(model.variants), agent)
}
/**
* Next variant in the list, wrapping back to the first after the last.
* An unknown or missing current value starts at the first variant.
@@ -67,12 +67,13 @@ import {
} from "./session-utils"
import { Identifier } from "../utils/id"
import { resolveModelSelection } from "./model-selection"
import { getAgentModel } from "./session-model-store"
import { resolveMessagePrefs } from "./session-preferences"
import { errorIDs } from "./session-errors"
import { PartStash } from "./part-stash"
import { mergeParts, sameParts } from "./session-parts"
import { state as todoState } from "./todo-revert"
import { getVariant, sessionVariantKeys, transferVariants, variantKey } from "./session-variant-store"
import { getAgentVariant, getVariant, sessionVariantKeys, transferVariants, variantKey } from "./session-variant-store"
import { KILO_AUTO, KILO_PROVIDER_ID, parseModelString } from "../../../src/shared/provider-model"
import { reviewMetadata, type ReviewMessageData } from "../../../src/shared/review-comments"
import { visibleMessages as filterVisibleMessages } from "./session-queue"
@@ -739,8 +740,23 @@ export const SessionProvider: ParentComponent = (props) => {
}
function modelForAgent(agentName: string): ModelSelection | null {
const override = shouldClearModeModelSelection(agentName) ? null : store.modelSelections[agentName]
return resolveModel(agentName, override)
return getAgentModel(
{
modelSelections: store.modelSelections,
sessionOverrides: store.sessionOverrides,
agentSelections: store.agentSelections,
recentModels: store.recentModels,
},
{
providers: provider.providers(),
connected: provider.connected(),
getModeModel,
getGlobalModel,
fallback: KILO_AUTO,
},
agentName,
userSetAgents()[agentName] === true,
)
}
function configModelForAgent(agentName: string): ModelSelection | null {
@@ -893,8 +909,7 @@ export const SessionProvider: ParentComponent = (props) => {
function variantForAgent(agentName: string, sel: ModelSelection | null) {
if (!sel) return undefined
const model = provider.findModel(sel)
if (!model?.variants) return undefined
return getVariant(store.variantSelections, sel, Object.keys(model.variants), agentName)
return getAgentVariant(store.variantSelections, sel, model, agentName)
}
const currentVariant = (sessionID?: string) => {