Skip to content
Merged
15 changes: 13 additions & 2 deletions packages/cli/src/ui/hooks/useProviderUpdates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ describe('useProviderUpdates', () => {
);
});

it('dismisses without persisting when user chooses "later"', async () => {
it('persists a cooldown (not a full update) when user chooses "later"', async () => {
(mockSettings.merged[PROVIDER_METADATA_NS] as Record<string, unknown>)[
METADATA_KEY
] = {
Expand Down Expand Up @@ -483,7 +483,18 @@ describe('useProviderUpdates', () => {
await waitFor(() => {
expect(result.current.providerUpdateRequest).toBeUndefined();
});
expect(mockSettings.setValue).not.toHaveBeenCalled();
// "later" persists a postponement cooldown so the prompt does not reappear
// on every launch, but it must not apply the update.
expect(mockSettings.setValue).toHaveBeenCalledWith(
'User',
`providerMetadata.${METADATA_KEY}.postponedVersion`,
expect.any(String),
);
expect(mockSettings.setValue).toHaveBeenCalledWith(
'User',
`providerMetadata.${METADATA_KEY}.postponedAt`,
expect.any(Number),
);
expect(mockConfig.reloadModelProvidersConfig).not.toHaveBeenCalled();
});

Expand Down
32 changes: 32 additions & 0 deletions packages/cli/src/ui/hooks/useProviderUpdates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,15 @@ interface ProviderMetadata {
version?: string;
baseUrl?: string;
ignoredVersion?: string;
postponedVersion?: string;
postponedAt?: number;
}

// "Later" suppresses re-prompting for the same version for this long, so a
// user who defers is not nagged on every launch. A new model-list version
// still re-prompts immediately (postponedVersion no longer matches).
const LATER_COOLDOWN_MS = 24 * 60 * 60 * 1000; // 24h

function getProviderMetadata(
settings: LoadedSettings,
metadataKey: string,
Expand Down Expand Up @@ -203,6 +210,16 @@ function findAllPendingUpdates(
if (metadata.version === currentVersion) continue;
if (metadata.ignoredVersion === currentVersion) continue;

// A "later" choice suppresses re-prompting for the same version while the
// cooldown is active. A new version (postponedVersion mismatch) re-prompts.
if (
metadata.postponedVersion === currentVersion &&
typeof metadata.postponedAt === 'number' &&
Date.now() - metadata.postponedAt < LATER_COOLDOWN_MS
) {
continue;
}

const existingModelIds = getInstalledOwnedModelIds(settings, provider);
const newModelIds = provider.models!.map((s) => s.id);
const diff = computeModelDiff(existingModelIds, newModelIds, currentModel);
Expand Down Expand Up @@ -368,6 +385,21 @@ export function useProviderUpdates(
p.currentVersion,
);
}
} else if (choice === 'later') {
// Persist a cooldown so "later" does not re-prompt on every launch.
Comment thread
yiliang114 marked this conversation as resolved.
Resolved
const persistScope = getPersistScopeForModelSelection(settings);
for (const p of pendingList) {
settings.setValue(
persistScope,
`${PROVIDER_METADATA_NS}.${p.metadataKey}.postponedVersion`,
p.currentVersion,
);
settings.setValue(
persistScope,
`${PROVIDER_METADATA_NS}.${p.metadataKey}.postponedAt`,
Date.now(),
);
}
}
},
});
Expand Down
Loading