From d1c49a6765988b8e4e9c853071f315e694402d30 Mon Sep 17 00:00:00 2001 From: Matthias Claw Date: Mon, 26 Oct 2026 10:32:16 +0100 Subject: [PATCH 1/2] fix(web): keep the default instance's draft model off custom instances A custom provider instance with no draft of its own fell back to the draft stored under its driver kind, which belongs to the default instance. Only Antigravity was exempt. An OpenCode instance limited to one provider (for example a Kimi-only instance) then showed a model from the default OpenCode instance: same label, but a slug missing from its own catalog. The composer treated it as unavailable, hid the reasoning control, and would have sent the foreign slug to that instance's server. Apply the default-instance check to every driver. --- apps/web/src/composerDraftStore.ts | 3 ++- apps/web/src/modelSelection.test.ts | 31 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/apps/web/src/composerDraftStore.ts b/apps/web/src/composerDraftStore.ts index 59188ac8d7958..38712e0187ded 100644 --- a/apps/web/src/composerDraftStore.ts +++ b/apps/web/src/composerDraftStore.ts @@ -1114,8 +1114,9 @@ export function deriveEffectiveComposerModelState(input: { const instanceSelection = input.selectedInstanceId ? input.draft?.modelSelectionByProvider?.[input.selectedInstanceId] : undefined; + // Driver-keyed drafts predate instances and belong to the default instance; custom instances + // (an OpenCode instance limited to one provider, another Antigravity account) have other catalogs. const legacySelection = - input.selectedProvider === "antigravity" && input.selectedInstanceId && input.selectedInstanceId !== defaultInstanceIdForDriver(input.selectedProvider) ? undefined diff --git a/apps/web/src/modelSelection.test.ts b/apps/web/src/modelSelection.test.ts index 05a7e76b6b25b..e803a14c4116f 100644 --- a/apps/web/src/modelSelection.test.ts +++ b/apps/web/src/modelSelection.test.ts @@ -604,6 +604,37 @@ describe("instance-scoped model selection", () => { ).toEqual(createModelSelection(instanceId, "openai/gpt-5.5")); }); + it("keeps the default instance's draft model off a custom instance of the same driver", () => { + const driver = ProviderDriverKind.make("opencode"); + const defaultInstanceId = ProviderInstanceId.make("opencode"); + const kimiInstanceId = ProviderInstanceId.make("kimi_api"); + const kimiModel = "kimi-code-plan-global/k3.1-pro"; + const providers = [ + provider({ + provider: driver, + instanceId: defaultInstanceId, + models: ["opencode-go/kimi-k3.1-pro"], + }), + provider({ provider: driver, instanceId: kimiInstanceId, models: [kimiModel] }), + ]; + const state = deriveEffectiveComposerModelState({ + draft: { + activeProvider: kimiInstanceId, + modelSelectionByProvider: { + [defaultInstanceId]: createModelSelection(defaultInstanceId, "opencode-go/kimi-k3.1-pro"), + }, + }, + providers, + selectedProvider: driver, + selectedInstanceId: kimiInstanceId, + threadModelSelection: null, + projectModelSelection: null, + settings: DEFAULT_UNIFIED_SETTINGS, + }); + + expect(state.selectedModel).toBe(kimiModel); + }); + it("self-heals a persisted selection pointing at a text-generation-incapable instance", () => { const providers = [ provider({ From be8420b97ac98d9c72b6781d04269055846c6a5f Mon Sep 17 00:00:00 2001 From: maria-rcks Date: Tue, 27 Oct 2026 00:39:03 +0000 Subject: [PATCH 2/2] refactor(web): clarify legacy draft ownership --- apps/web/src/composerDraftStore.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/web/src/composerDraftStore.ts b/apps/web/src/composerDraftStore.ts index 0264652b8bf9b..bb5071be46079 100644 --- a/apps/web/src/composerDraftStore.ts +++ b/apps/web/src/composerDraftStore.ts @@ -1121,8 +1121,7 @@ export function deriveEffectiveComposerModelState(input: { const instanceSelection = input.selectedInstanceId ? input.draft?.modelSelectionByProvider?.[input.selectedInstanceId] : undefined; - // Driver-keyed drafts predate instances and belong to the default instance; custom instances - // (an OpenCode instance limited to one provider, another Antigravity account) have other catalogs. + // Legacy driver-keyed drafts belong to the default instance. const legacySelection = input.selectedInstanceId && input.selectedInstanceId !== defaultInstanceIdForDriver(input.selectedProvider)