diff --git a/apps/server/src/provider/Layers/ProviderRegistry.test.ts b/apps/server/src/provider/Layers/ProviderRegistry.test.ts index ee1a23573277..390b04d0bd43 100644 --- a/apps/server/src/provider/Layers/ProviderRegistry.test.ts +++ b/apps/server/src/provider/Layers/ProviderRegistry.test.ts @@ -909,6 +909,45 @@ it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsModule.layerTest(), Te assert.deepStrictEqual(afterFailure.models, [authoritativeProvider.models[0]!]); }); + it("drops Claude models the installed CLI is too old for once the probe finishes", () => { + const supportedModel = { + slug: "claude-supported", + name: "Supported", + isCustom: false, + capabilities: null, + } as const; + const pendingProvider = { + instanceId: ProviderInstanceId.make("claudeAgent"), + driver: ProviderDriverKind.make("claudeAgent"), + status: "warning", + enabled: true, + installed: false, + auth: { status: "unknown" }, + checkedAt: "2026-09-28T00:00:00.000Z", + version: null, + models: [ + supportedModel, + { slug: "claude-needs-newer-cli", name: "Newer", isCustom: false, capabilities: null }, + ], + slashCommands: [], + skills: [], + } as const satisfies ServerProvider; + const readyProvider = { + ...pendingProvider, + status: "ready", + installed: true, + auth: { status: "authenticated" }, + checkedAt: "2026-09-28T00:01:00.000Z", + version: "2.1.0", + models: [supportedModel], + } satisfies ServerProvider; + + assert.deepStrictEqual( + mergeProviderSnapshot(pendingProvider, readyProvider).models, + readyProvider.models, + ); + }); + describe("Codex model inventories", () => { const cachedProvider = { instanceId: ProviderInstanceId.make("codex-personal"), diff --git a/apps/server/src/provider/Layers/ProviderRegistry.ts b/apps/server/src/provider/Layers/ProviderRegistry.ts index a65bc66edf32..5bc9c02d6816 100644 --- a/apps/server/src/provider/Layers/ProviderRegistry.ts +++ b/apps/server/src/provider/Layers/ProviderRegistry.ts @@ -105,7 +105,12 @@ export function upsertProviderWorkspaceSnapshot( const shouldRetainMissingProviderModels = (provider: ServerProvider): boolean => { const isAntigravity = provider.driver === ProviderDriverKind.make("antigravity"); const isCodex = provider.driver === ProviderDriverKind.make("codex"); - if (!isAntigravity && !isCodex && provider.driver !== ProviderDriverKind.make("opencode")) { + if ( + !isAntigravity && + !isCodex && + provider.driver !== ProviderDriverKind.make("opencode") && + provider.driver !== ProviderDriverKind.make("claudeAgent") + ) { return true; } @@ -117,6 +122,7 @@ const shouldRetainMissingProviderModels = (provider: ServerProvider): boolean => } // Successful discovery replaces these inventories so cached retired models disappear. + // Claude's probe also drops models the installed CLI is too old for. // Antigravity's local health check does not authenticate or discover models. const isPendingAntigravityAuthentication = isAntigravity && provider.status === "warning" && provider.auth.status === "unknown";