@linxiraos/pi-catalog 1.1.13 → 1.1.15

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.
Files changed (43) hide show
  1. package/CHANGELOG.md +2 -69
  2. package/README.md +20 -0
  3. package/dist/types/compat/auth-ids.d.ts +2 -2
  4. package/dist/types/models.d.ts +10 -6
  5. package/dist/types/pricing.d.ts +5 -0
  6. package/dist/types/provider-models/descriptor-types.d.ts +15 -0
  7. package/dist/types/provider-models/descriptors.d.ts +20 -0
  8. package/dist/types/provider-models/openai-compat.d.ts +44 -0
  9. package/dist/types/types.d.ts +43 -2
  10. package/dist/types/wire/charm-hyper.d.ts +21 -0
  11. package/dist/types/wire/github-copilot.d.ts +19 -0
  12. package/package.json +4 -4
  13. package/src/build.ts +16 -2
  14. package/src/compat/auth-ids.ts +4 -0
  15. package/src/compat/axes.ts +9 -0
  16. package/src/compat/resolve.ts +18 -4
  17. package/src/compat/rules/README.md +37 -0
  18. package/src/compat/rules/auth/_order.kdl +1 -1
  19. package/src/compat/rules/auth/charm-hyper.kdl +19 -0
  20. package/src/compat/rules/auth/commandcode.kdl +13 -0
  21. package/src/compat/rules/classes/anthropic.kdl +41 -0
  22. package/src/compat/rules/classes/deepseek.kdl +11 -0
  23. package/src/compat/rules/classes/minimax.kdl +4 -2
  24. package/src/compat/rules/providers/amazon-bedrock.kdl +7 -0
  25. package/src/compat/rules/providers/anthropic.kdl +8 -0
  26. package/src/compat/rules/providers/charm-hyper.kdl +82 -0
  27. package/src/compat/rules/providers/commandcode.kdl +601 -0
  28. package/src/compat/rules/providers/deepseek.kdl +83 -1
  29. package/src/compat/rules/providers/opencode-go.kdl +22 -0
  30. package/src/compat/rules/providers/opencode-zen.kdl +12 -0
  31. package/src/compat/rules/runtime/behavior.kdl +5 -0
  32. package/src/compat/rules.json +2143 -131
  33. package/src/model-manager.ts +27 -13
  34. package/src/models.json +12953 -5481
  35. package/src/models.ts +93 -19
  36. package/src/pricing.ts +136 -0
  37. package/src/provider-models/cache-provider-id.ts +28 -4
  38. package/src/provider-models/descriptor-types.ts +15 -0
  39. package/src/provider-models/descriptors.ts +36 -0
  40. package/src/provider-models/openai-compat.ts +297 -3
  41. package/src/types.ts +46 -1
  42. package/src/wire/charm-hyper.ts +26 -0
  43. package/src/wire/github-copilot.ts +26 -0
@@ -3,6 +3,7 @@ import { collapseBuiltVariants } from "./compat/collapse";
3
3
  import { applyCatalogMetrics, CatalogMetricsIndex } from "./identity/metrics";
4
4
  import { readModelCache, writeModelCache } from "./model-cache";
5
5
  import { type GeneratedProvider, getBundledModels } from "./models";
6
+ import { isTimeBasedCost } from "./pricing";
6
7
  import type { Api, Model, ModelCost, ModelSpec, Provider, TokenCost } from "./types";
7
8
  import { isRecord } from "./utils";
8
9
 
@@ -336,8 +337,15 @@ export async function resolveProviderModels<TApi extends Api = Api, TModelsDevPa
336
337
  restorableHeaderFallback,
337
338
  );
338
339
  } else {
339
- // Remote fetch failed — update cache with a non-authoritative snapshot so
340
- // stale state remains visible while retry backoff still applies.
340
+ // Remote fetch failed. Re-persist any prior catalog as a
341
+ // non-authoritative snapshot so stale state stays visible while the
342
+ // retry backoff applies. When there is no prior cache and nothing to
343
+ // preserve (a discovery-only provider on its first failed fetch), leave
344
+ // the row absent rather than writing an empty snapshot: an empty
345
+ // non-authoritative row reads back as a fresh catalog and suppresses
346
+ // refetch for NON_AUTHORITATIVE_RETRY_MS, hiding every discovery-only
347
+ // model until it ages out. Writing nothing lets the next launch retry
348
+ // immediately (#10964).
341
349
  const latestCache = readModelCache<TApi>(cacheProviderId, ttlMs, now, dbPath);
342
350
  const latestRestoredCache = restoreCachedModelHeaders(
343
351
  latestCache?.models ?? cache?.models ?? [],
@@ -362,16 +370,18 @@ export async function resolveProviderModels<TApi extends Api = Api, TModelsDevPa
362
370
  const fallbackSnapshotModels = collapseBuiltVariants(
363
371
  mergeDynamicModels(mergeDynamicModels(staticModels, latestCacheModels), modelsDevModels),
364
372
  );
365
- writeModelCache(
366
- cacheProviderId,
367
- now(),
368
- fallbackSnapshotModels,
369
- false,
370
- staticFingerprint,
371
- dbPath,
372
- staticModels,
373
- restorableHeaderFallback,
374
- );
373
+ if (fallbackSnapshotModels.length > 0 || latestCache !== null || cache !== null) {
374
+ writeModelCache(
375
+ cacheProviderId,
376
+ now(),
377
+ fallbackSnapshotModels,
378
+ false,
379
+ staticFingerprint,
380
+ dbPath,
381
+ staticModels,
382
+ restorableHeaderFallback,
383
+ );
384
+ }
375
385
  }
376
386
  }
377
387
  const cacheContributed = cacheModels.length > 0;
@@ -573,6 +583,7 @@ function mergeDynamicModel<TApi extends Api>(existingModel: Model<TApi>, dynamic
573
583
  ? dynamicModel.reasoning
574
584
  : existingModel.reasoning || dynamicModel.reasoning;
575
585
  const longContextCost = dynamicModel.cost.longContext ?? existingModel.cost.longContext;
586
+ const timeBasedCost = dynamicModel.cost.timeBased ?? existingModel.cost.timeBased;
576
587
  // Re-build from spec stage: sparse compat comes from `compatConfig` (the
577
588
  // verbatim override vocabulary), never the resolved `compat` record.
578
589
  return buildModel({
@@ -587,6 +598,7 @@ function mergeDynamicModel<TApi extends Api>(existingModel: Model<TApi>, dynamic
587
598
  cacheRead: preferDiscoveryCost(dynamicModel.cost.cacheRead, existingModel.cost.cacheRead),
588
599
  cacheWrite: preferDiscoveryCost(dynamicModel.cost.cacheWrite, existingModel.cost.cacheWrite),
589
600
  ...(longContextCost ? { longContext: longContextCost } : {}),
601
+ ...(timeBasedCost ? { timeBased: timeBasedCost } : {}),
590
602
  },
591
603
  contextWindow: preferDiscoveryLimit(dynamicModel.contextWindow, existingModel.contextWindow),
592
604
  maxTokens: preferDiscoveryLimit(dynamicModel.maxTokens, existingModel.maxTokens),
@@ -737,7 +749,9 @@ function isTokenCost(value: unknown): value is TokenCost {
737
749
 
738
750
  function isModelCost(value: unknown): value is ModelCost {
739
751
  if (!isTokenCost(value)) return false;
740
- const longContext = (value as TokenCost & { longContext?: unknown }).longContext;
752
+ const cost = value as TokenCost & { longContext?: unknown; timeBased?: unknown };
753
+ if (cost.timeBased !== undefined && !isTimeBasedCost(cost.timeBased)) return false;
754
+ const longContext = cost.longContext;
741
755
  if (longContext === undefined) return true;
742
756
  if (!isTokenCost(longContext) || !isRecord(longContext)) return false;
743
757
  const threshold = longContext.inputThreshold;