fix: let server decide model when no user selection exists (#37)

Registry defaults unreliable for deployed models; return null so server uses its configured model. Fixes #35.
This commit is contained in:
Den
2026-06-22 01:15:13 -07:00
committed by GitHub
parent 669618b7b7
commit f92f995b48
2 changed files with 28 additions and 24 deletions

View File

@@ -5,7 +5,7 @@ import { chooseModelSelection } from "./model-selection.ts"
const providers = [
{
id: "azure",
models: [{ id: "gpt-5.4" }, { id: "gpt-5.2" }],
models: [{ id: "gpt-5.4" }, { id: "gpt-5.2" }, { id: "claude-sonnet-4-6" }],
},
]
@@ -14,29 +14,31 @@ test("keeps existing selection when still available", () => {
providers,
defaults: { azure: "gpt-5.4" },
existing: { providerID: "azure", modelID: "gpt-5.2" },
agentModel: { providerID: "azure", modelID: "claude-sonnet-4-6" },
agentModel: null,
})
assert.deepEqual(selected, { providerID: "azure", modelID: "gpt-5.2" })
})
test("prefers provider default over unavailable agent model", () => {
test("returns null when no existing selection (let server decide)", () => {
// Even though defaults and providers exist, we return null to let
// the server use its own configured model from opencode.json
const selected = chooseModelSelection({
providers,
defaults: { azure: "gpt-5.4" },
defaults: { azure: "claude-sonnet-4-6" },
existing: null,
agentModel: { providerID: "azure", modelID: "claude-sonnet-4-6" },
})
assert.deepEqual(selected, { providerID: "azure", modelID: "gpt-5.4" })
assert.equal(selected, null)
})
test("falls back to first connected provider model when default missing", () => {
test("returns null when existing selection no longer available", () => {
const selected = chooseModelSelection({
providers,
defaults: {},
existing: null,
defaults: { azure: "gpt-5.4" },
existing: { providerID: "azure", modelID: "nonexistent-model" },
agentModel: null,
})
assert.deepEqual(selected, { providerID: "azure", modelID: "gpt-5.4" })
assert.equal(selected, null)
})
test("returns null when no connected providers", () => {

View File

@@ -22,29 +22,31 @@ export function isModelAvailable(
return provider.models.some((m) => m.id === selection.modelID)
}
/**
* Chooses a model selection for the session.
*
* Returns `null` when there is no prior user-explicit choice. A null model
* means the server's configured default (opencode.json `"model"` field) will
* be used — which is the correct behavior for first-launch and CI where the
* provider registry's "default" model may not be deployed on the user's
* resource.
*
* Only returns a non-null value when the user previously made an explicit
* selection that is still valid (model available on a connected provider).
*/
export function chooseModelSelection(params: {
providers: ProviderRef[]
defaults: Record<string, string>
existing: ModelSelection | null
agentModel: ModelSelection | null
}): ModelSelection | null {
const { providers, defaults, existing, agentModel } = params
const { providers, existing } = params
// Keep existing user-chosen selection if it's still reachable
if (isModelAvailable(providers, existing)) return existing
for (const provider of providers) {
const defaultModelID = defaults[provider.id]
if (!defaultModelID) continue
if (provider.models.some((m) => m.id === defaultModelID)) {
return { providerID: provider.id, modelID: defaultModelID }
}
}
if (providers.length > 0 && providers[0].models.length > 0) {
return { providerID: providers[0].id, modelID: providers[0].models[0].id }
}
if (isModelAvailable(providers, agentModel)) return agentModel
// Otherwise return null — let the server decide via its own config.
// The provider registry's "defaults" map is unreliable (it lists the
// upstream registry default, not what's deployed on the user's resource).
return null
}