diff --git a/apps/server/src/provider/ProviderRegistry.test.ts b/apps/server/src/provider/ProviderRegistry.test.ts index be043bae0f847..c42d78b237d42 100644 --- a/apps/server/src/provider/ProviderRegistry.test.ts +++ b/apps/server/src/provider/ProviderRegistry.test.ts @@ -1309,7 +1309,7 @@ it.layer( ); }); - it("retains stale OpenCode models when a refresh fails", () => { + it("retains stale OpenCode models when a refresh fails or lists none", () => { const previousProvider = { instanceId: ProviderInstanceId.make("opencode"), driver: ProviderDriverKind.make("opencode"), @@ -1359,6 +1359,21 @@ it.layer( ProviderRegistry.mergeProviderSnapshot(previousProvider, refreshedProvider).skills, previousProvider.skills, ); + + const emptyCatalogProvider = { + ...refreshedProvider, + status: "warning", + message: "OpenCode 2 is running, but it did not list any models yet.", + slashCommands: [], + skills: [], + } satisfies ServerProvider; + const mergedEmptyCatalog = ProviderRegistry.mergeProviderSnapshot( + previousProvider, + emptyCatalogProvider, + ); + assert.deepStrictEqual(mergedEmptyCatalog.models, [...previousProvider.models]); + assert.deepStrictEqual(mergedEmptyCatalog.slashCommands, previousProvider.slashCommands); + assert.deepStrictEqual(mergedEmptyCatalog.skills, previousProvider.skills); }); describe("Pi model inventories", () => { diff --git a/apps/server/src/provider/ProviderRegistry.ts b/apps/server/src/provider/ProviderRegistry.ts index ba9ce9b2b6af7..8a7ff0ac7fd37 100644 --- a/apps/server/src/provider/ProviderRegistry.ts +++ b/apps/server/src/provider/ProviderRegistry.ts @@ -220,7 +220,8 @@ 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")) { + const isOpenCode = provider.driver === ProviderDriverKind.make("opencode"); + if (!isAntigravity && !isCodex && !isOpenCode) { return true; } @@ -236,9 +237,10 @@ const shouldRetainMissingProviderModels = (provider: ServerProvider): boolean => isAntigravity && provider.status === "warning" && provider.auth.status === "unknown"; const isPendingInitialProbe = provider.enabled && !provider.installed && provider.status === "warning"; + // A cold OpenCode server can finish its probe as a warning before it lists any models. const isIncompleteInstalledProbe = provider.installed && - (provider.status === "error" || (isCodex && provider.status === "warning")); + (provider.status === "error" || ((isCodex || isOpenCode) && provider.status === "warning")); return isPendingAntigravityAuthentication || isPendingInitialProbe || isIncompleteInstalledProbe; };