fix(opencode): settle empty catalog hydration

This commit is contained in:
777genius 2026-05-20 15:31:20 +03:00
parent d7f82e54d1
commit 16c1e4b47d
4 changed files with 85 additions and 2 deletions

View file

@ -116,7 +116,7 @@ export function isOpenCodeCatalogHydrating(
return false;
}
if (provider.modelCatalog?.providerId === 'opencode' && provider.modelCatalog.models.length > 0) {
if (provider.modelCatalog?.providerId === 'opencode') {
return false;
}

View file

@ -98,7 +98,11 @@ function isOpenCodeSummaryOnlyCatalogStatus(provider: CliProviderStatus | undefi
return false;
}
if (provider.modelCatalog?.providerId === 'opencode' && provider.modelCatalog.models.length > 0) {
if (provider.modelCatalog?.providerId === 'opencode') {
return false;
}
if (provider.modelCatalogRefreshState === 'error') {
return false;
}

View file

@ -271,6 +271,26 @@ describe('providerConnectionUi', () => {
modelCatalogRefreshState: 'error',
})
).toBe(false);
expect(
isOpenCodeCatalogHydrating({
...provider,
modelCatalog: {
schemaVersion: 1,
providerId: 'opencode',
source: 'app-server',
status: 'ready',
fetchedAt: '2026-05-20T00:00:00.000Z',
staleAt: '2026-05-20T00:10:00.000Z',
defaultModelId: null,
defaultLaunchModel: null,
models: [],
diagnostics: {
configReadState: 'ready',
appServerState: 'healthy',
},
},
})
).toBe(false);
});
it('does not describe Anthropic API key mode as subscription connected when the key is missing', () => {

View file

@ -259,6 +259,65 @@ describe('cliInstallerSlice', () => {
expect(getModelOnlyFallbackProviderIds(status)).toEqual([]);
});
it('treats an empty OpenCode model catalog as hydrated', () => {
const status = createMultimodelStatus([
createMultimodelProvider({
providerId: 'opencode',
displayName: 'OpenCode',
authenticated: false,
authMethod: null,
models: [],
backend: { kind: 'opencode-cli', label: 'OpenCode CLI' },
modelCatalogRefreshState: 'ready',
modelCatalog: {
schemaVersion: 1,
providerId: 'opencode',
source: 'app-server',
status: 'ready',
fetchedAt: '2026-05-20T00:00:00.000Z',
staleAt: '2026-05-20T00:10:00.000Z',
defaultModelId: null,
defaultLaunchModel: null,
models: [],
diagnostics: {
configReadState: 'ready',
appServerState: 'healthy',
},
},
runtimeCapabilities: {
modelCatalog: {
dynamic: true,
source: 'app-server',
},
},
}),
]);
expect(getIncompleteMultimodelProviderIds(status)).toEqual([]);
});
it('does not keep OpenCode catalog errors marked as incomplete', () => {
const status = createMultimodelStatus([
createMultimodelProvider({
providerId: 'opencode',
displayName: 'OpenCode',
verificationState: 'error',
statusMessage: 'Catalog hydration failed',
models: [],
modelCatalog: null,
modelCatalogRefreshState: 'error',
runtimeCapabilities: {
modelCatalog: {
dynamic: true,
source: 'app-server',
},
},
}),
]);
expect(getIncompleteMultimodelProviderIds(status)).toEqual([]);
});
it('keeps connection-enriched checking placeholders incomplete until provider hydration finishes', () => {
const status = createMultimodelStatus([
createMultimodelProvider({