@oh-my-pi/pi-catalog 18.11.2 → 18.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -260,11 +260,14 @@ export async function resolveProviderModels<TApi extends Api = Api, TModelsDevPa
260
260
  const staticModels = options.staticModels
261
261
  ? materializeStaticModels<TApi>(options.staticModels)
262
262
  : (getBundledModels(options.providerId as GeneratedProvider) as Model<TApi>[]);
263
- const additiveStaticModelIds =
263
+ const modelsDevAdditiveStaticModelIds =
264
264
  options.modelsDev?.additiveOnly && staticModels.length > 0
265
265
  ? new Set(staticModels.map(model => model.id))
266
266
  : undefined;
267
267
  const cache = readModelCache<TApi>(cacheProviderId, ttlMs, now, dbPath);
268
+ const dynamicModelsAuthoritative = options.dynamicModelsAuthoritative ?? false;
269
+ const isAuthoritativeDynamicCache = dynamicModelsAuthoritative && (cache?.authoritative ?? false);
270
+ const cacheAdditiveStaticModelIds = isAuthoritativeDynamicCache ? undefined : modelsDevAdditiveStaticModelIds;
268
271
  const restoredCache = restoreCachedModelHeaders(
269
272
  cache?.models ?? [],
270
273
  staticModels,
@@ -276,7 +279,6 @@ export async function resolveProviderModels<TApi extends Api = Api, TModelsDevPa
276
279
  );
277
280
  const usableCachedModels = restoredCache.models.filter(model => !restoredCache.unresolvedModelIds.has(model.id));
278
281
  const cacheHasUnresolvedHeaders = restoredCache.unresolvedModelIds.size > 0;
279
- const dynamicModelsAuthoritative = options.dynamicModelsAuthoritative ?? false;
280
282
  const mergeAuthority: DynamicMergeAuthority = {
281
283
  input: options.dynamicInputAuthoritative ?? false,
282
284
  reasoning: options.dynamicReasoningAuthoritative ?? false,
@@ -322,10 +324,10 @@ export async function resolveProviderModels<TApi extends Api = Api, TModelsDevPa
322
324
  cacheFingerprintMatches &&
323
325
  !cacheHasUnresolvedHeaders
324
326
  ) {
325
- const cacheContribution = additiveStaticModelIds
326
- ? restoredCache.models.filter(model => !additiveStaticModelIds.has(model.id))
327
+ const cacheContribution = cacheAdditiveStaticModelIds
328
+ ? restoredCache.models.filter(model => !cacheAdditiveStaticModelIds.has(model.id))
327
329
  : restoredCache.models;
328
- const cachedModels = additiveStaticModelIds
330
+ const cachedModels = cacheAdditiveStaticModelIds
329
331
  ? mergeCatalogMetrics(
330
332
  mergeDynamicModels(staticModels, cacheContribution, mergeAuthority),
331
333
  restoredCache.models,
@@ -345,8 +347,8 @@ export async function resolveProviderModels<TApi extends Api = Api, TModelsDevPa
345
347
  : [null, null];
346
348
  const modelsDevFetchSucceeded = fetchedModelsDevModels !== null;
347
349
  const normalizedModelsDevModels = fetchedModelsDevModels?.models ?? [];
348
- const modelsDevModels = additiveStaticModelIds
349
- ? normalizedModelsDevModels.filter(model => !additiveStaticModelIds.has(model.id))
350
+ const modelsDevModels = modelsDevAdditiveStaticModelIds
351
+ ? normalizedModelsDevModels.filter(model => !modelsDevAdditiveStaticModelIds.has(model.id))
350
352
  : normalizedModelsDevModels;
351
353
  const shouldUseFreshCacheAsAuthoritative =
352
354
  strategy === "online-if-uncached" && hasUsableFreshCache && hasAuthoritativeCache;
@@ -366,10 +368,8 @@ export async function resolveProviderModels<TApi extends Api = Api, TModelsDevPa
366
368
  cacheFingerprintMatches,
367
369
  options.dropCachedModelIdsOnStaticMismatch,
368
370
  );
369
- // Additive shared-catalog rows may only introduce IDs. Apply that boundary
370
- // to cache fallback too, including snapshots written by an older binary.
371
- const cacheModels = additiveStaticModelIds
372
- ? preparedCacheModels.filter(model => !additiveStaticModelIds.has(model.id))
371
+ const cacheModels = cacheAdditiveStaticModelIds
372
+ ? preparedCacheModels.filter(model => !cacheAdditiveStaticModelIds.has(model.id))
373
373
  : preparedCacheModels;
374
374
  const dynamicModels = fetchedDynamicModels?.models ?? [];
375
375
  // A successful empty endpoint result stays authoritative for THIS cycle (so an
@@ -390,7 +390,9 @@ export async function resolveProviderModels<TApi extends Api = Api, TModelsDevPa
390
390
  fetchedModelsDevModels?.explicitKindModels,
391
391
  );
392
392
  const catalogMetricsSource = modelsDevFetchSucceeded ? normalizedModelsDevModels : preparedCacheModels;
393
- const mergedWithCatalogMetrics = additiveStaticModelIds
393
+ const mergedWithCatalogMetrics = (
394
+ modelsDevFetchSucceeded ? modelsDevAdditiveStaticModelIds : cacheAdditiveStaticModelIds
395
+ )
394
396
  ? mergeCatalogMetrics(mergedWithModelsDev, catalogMetricsSource)
395
397
  : mergedWithModelsDev;
396
398
  const mergedModels = mergeDynamicModels(
@@ -400,7 +402,11 @@ export async function resolveProviderModels<TApi extends Api = Api, TModelsDevPa
400
402
  fetchedDynamicModels?.explicitKindModels,
401
403
  );
402
404
  const models = collapseBuiltVariants(
403
- authoritativeDynamicFetchSucceeded ? retainModelIds(mergedModels, dynamicModels) : mergedModels,
405
+ authoritativeDynamicFetchSucceeded
406
+ ? retainModelIds(mergedModels, dynamicModels)
407
+ : !dynamicFetchSucceeded && isAuthoritativeDynamicCache && usableCachedModels.length > 0
408
+ ? retainModelIds(mergedModels, usableCachedModels)
409
+ : mergedModels,
404
410
  );
405
411
  const resolutionAuthoritative = !hasRemoteFetcher || remoteResolutionComplete || shouldUseFreshCacheAsAuthoritative;
406
412
  const remoteUpdatedAt = anyRemoteFetchSucceeded ? now() : undefined;
@@ -445,15 +451,18 @@ export async function resolveProviderModels<TApi extends Api = Api, TModelsDevPa
445
451
  cacheFingerprintMatches,
446
452
  options.dropCachedModelIdsOnStaticMismatch,
447
453
  );
448
- const latestCacheModels = additiveStaticModelIds
449
- ? preparedLatestCacheModels.filter(model => !additiveStaticModelIds.has(model.id))
454
+ const latestCacheModels = cacheAdditiveStaticModelIds
455
+ ? preparedLatestCacheModels.filter(model => !cacheAdditiveStaticModelIds.has(model.id))
450
456
  : preparedLatestCacheModels;
457
+ const mergedFallbackModels = mergeDynamicModels(
458
+ mergeDynamicModels(staticModels, latestCacheModels, mergeAuthority),
459
+ modelsDevModels,
460
+ mergeAuthority,
461
+ );
451
462
  const fallbackSnapshotModels = collapseBuiltVariants(
452
- mergeDynamicModels(
453
- mergeDynamicModels(staticModels, latestCacheModels, mergeAuthority),
454
- modelsDevModels,
455
- mergeAuthority,
456
- ),
463
+ isAuthoritativeDynamicCache && latestUsableCacheModels.length > 0
464
+ ? retainModelIds(mergedFallbackModels, latestUsableCacheModels)
465
+ : mergedFallbackModels,
457
466
  );
458
467
  if (fallbackSnapshotModels.length > 0 || latestCache !== null || cache !== null) {
459
468
  writeModelCache(