Skip to content
Merged
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
22 changes: 19 additions & 3 deletions packages/core/src/config/plugin/model-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -443,14 +443,21 @@ export function expand(
const requested = ref.variant ?? inheritedVariant
// A pinned variant is producible natively or through the target's remap table, matching
// routeVariants and the resolver: a remap the model can produce wins, else the native
// variant, else the leaf is pruned.
// variant, else the leaf is pruned. A variant the door's catalog exposes as a
// suffixed model id ("<model>-<variant>") also counts as producible: proxy
// catalogs enumerate effort levels that way (Antigravity's gemini-4-argon-high,
// claude-sonnet-5-5-high), and their definition-stage model info carries no
// variant list, so the native check alone silently pruned every pinned leaf
// on those providers (#985).
const producible = (candidate: string) =>
model.variants.some((item) => item.id === candidate) || (doorModels?.has(`${id}-${candidate}`) ?? false)
const remapped = requested ? spec.variants?.[requested] : undefined
const variant =
requested === undefined
? undefined
: remapped !== undefined && model.variants.some((item) => item.id === remapped)
: remapped !== undefined && producible(remapped)
? Model.VariantID.make(remapped)
: model.variants.some((item) => item.id === requested)
: producible(requested)
? requested
: undefined
if (requested && !variant) continue
Expand Down Expand Up @@ -594,6 +601,15 @@ export function retargetDefinition(
const model = editor.get(providerID, Model.ID.make(id))
if (model) merged.set(String(id), model)
}
// The editor does not enumerate every model it holds (a proxy catalog lists
// effort levels as suffixed ids, not the base model), so a definition-stage
// entry the editor never names would keep its pre-transform shape — no
// variants, stale limits — and the re-expansion below would judge targets
// against it. Refresh every surviving entry from the editor by its own id.
for (const id of merged.keys()) {
const model = editor.get(providerID, Model.ID.make(id))
if (model) merged.set(id, model)
}
definitions.set(providerID, merged)
}
const { leaves, nodes } = expand(String(current.id), routes, definitions, windows)
Expand Down
47 changes: 47 additions & 0 deletions packages/core/test/model-route-transform-models.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,3 +309,50 @@ it.effect("Model.Editor.ids lists current ids without drafting, including transf
expect(seen.after).toEqual(["chat", "deployment-1"])
}),
)


describe("retargetDefinition editor refresh (#985)", () => {
test("a definition-stage model the editor completes later retargets with its variants", () => {
// The definition-stage catalog holds the base model with no variants, so
// the stored expansion of a variant-pinned target is empty. The editor's
// current version of the same model carries the variants, but the editor
// does not enumerate the base id (a proxy catalog lists suffixed ids), so
// only a refresh by the definition's own ids can complete it.
const catalogOnly = new Map<string, Model.Info>([["base", info("base")]])
const completed = {
...info("base"),
variants: [{ id: Model.VariantID.make("high") }],
}
const awareEditor = {
provider: {
list: () => [{ provider: Provider.Info.empty(azure), models: catalogOnly }],
get: () => undefined,
},
ids: () => [],
get: (providerID: Provider.ID, modelID: Model.ID) =>
String(modelID) === "base" ? completed : undefined,
} as unknown as Parameters<typeof retargetDefinition>[2]
const routeMap = new Map<string, ConfigModelRoutes.Route>([
[
"r",
{
targets: [{ model: { providerID: "azure", model: "base", variant: "high" } }],
} as unknown as ConfigModelRoutes.Route,
],
])
const definitions = new Map<Provider.ID, ReadonlyMap<string, Model.Info>>([[azure, catalogOnly]])
expect(expand("r", routeMap, definitions).leaves).toEqual([])
const before = {
id: Model.ID.make("r"),
targets: [],
targetVariants: [],
health: ModelRoute.policy(),
budgets: [],
nodes: [],
} as unknown as ModelRoute.Definition
const next = retargetDefinition(before, routeMap, awareEditor)
expect(next?.definition?.targets.map((target) => `${target.providerID}/${target.id}#${target.variant}`)).toEqual([
"azure/base#high",
])
})
})
48 changes: 48 additions & 0 deletions packages/core/test/model-routes-expand.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -771,3 +771,51 @@ describe("door-set targets (#637)", () => {
])
})
})


describe("pinned variants on suffixed-catalog providers (#985)", () => {
const proxy = Provider.ID.make("proxy")
// Definition-stage shape for proxy providers (Antigravity, Open Design): the
// base model carries no variant list; its effort levels exist in the catalog
// only as suffixed model ids.
const defs = new Map<Provider.ID, ReadonlyMap<string, Model.Info>>([
[
proxy,
new Map([
["m", Model.Info.default(proxy, Model.ID.make("m"))],
["m-high", Model.Info.default(proxy, Model.ID.make("m-high"))],
]),
],
])
const raw = (entries: [string, unknown][]) =>
new Map(entries as [string, ConfigModelRoutes.Route][])

test("a pinned variant the catalog exposes as a suffixed model does not prune the leaf", () => {
const routes = raw([
["r", { targets: [{ model: { providerID: "proxy", model: "m", variant: "high" } }] }],
])
const { leaves } = expand("r", routes, defs)
expect(leaves.map((leaf) => `${leaf.ref.providerID}/${leaf.ref.id}#${leaf.ref.variant}`)).toEqual([
"proxy/m#high",
])
})

test("a variant inherited through a nested route does not prune the leaf either", () => {
const routes = raw([
["pool", { targets: [{ model: { providerID: "proxy", model: "m" } }] }],
["r", { targets: [{ model: { providerID: "opencode-route", model: "pool", variant: "high" } }] }],
])
const { leaves } = expand("r", routes, defs)
expect(leaves.map((leaf) => `${leaf.ref.providerID}/${leaf.ref.id}#${leaf.ref.variant}`)).toEqual([
"proxy/m#high",
])
})

test("a pinned variant with no native, remapped, or suffixed evidence still prunes", () => {
const routes = raw([
["r", { targets: [{ model: { providerID: "proxy", model: "m", variant: "ultra" } }] }],
])
const { leaves } = expand("r", routes, defs)
expect(leaves).toEqual([])
})
})