pi-cache-optimizer 2.6.2 → 2.6.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.
Files changed (2) hide show
  1. package/index.ts +47 -8
  2. package/package.json +1 -1
package/index.ts CHANGED
@@ -1381,6 +1381,34 @@ function modelKey(model: PiModel): string {
1381
1381
  return `${model.provider}/${model.id}`;
1382
1382
  }
1383
1383
 
1384
+ function isRouterModel(model: PiModel | undefined): boolean {
1385
+ return lower(model?.provider) === "router";
1386
+ }
1387
+
1388
+ function modelFromAssistantMessage(message: unknown, fallback: PiModel | undefined): PiModel | undefined {
1389
+ const record = getAssistantRecord(message);
1390
+ if (!record) return fallback;
1391
+
1392
+ const id = lower(record.responseModel) || lower(record.model) || fallback?.id;
1393
+ const provider = lower(record.provider) || fallback?.provider;
1394
+ const api = lower(record.api) || fallback?.api;
1395
+ if (!id || !provider || !api) return fallback;
1396
+
1397
+ return {
1398
+ ...(fallback ?? {}),
1399
+ id,
1400
+ name: id,
1401
+ provider,
1402
+ api,
1403
+ baseUrl: fallback?.baseUrl ?? "",
1404
+ reasoning: fallback?.reasoning ?? false,
1405
+ input: fallback?.input ?? ["text"],
1406
+ cost: fallback?.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
1407
+ contextWindow: fallback?.contextWindow ?? 0,
1408
+ maxTokens: fallback?.maxTokens ?? 0,
1409
+ } as PiModel;
1410
+ }
1411
+
1384
1412
  function keyForModelExt(model: { provider: string; id: string }): string {
1385
1413
  return `${model.provider}/${model.id}`;
1386
1414
  }
@@ -2835,7 +2863,8 @@ function selectAdapterForModel(model: PiModel | undefined): CacheProviderAdapter
2835
2863
  }
2836
2864
 
2837
2865
  function selectAdapterForAssistantMessage(message: unknown, model: PiModel | undefined): CacheProviderAdapter | undefined {
2838
- return CACHE_PROVIDER_ADAPTERS.find((adapter) => adapter.matchesAssistantMessage(message, model));
2866
+ const responseModel = isRouterModel(model) ? modelFromAssistantMessage(message, model) : model;
2867
+ return CACHE_PROVIDER_ADAPTERS.find((adapter) => adapter.matchesAssistantMessage(message, responseModel));
2839
2868
  }
2840
2869
 
2841
2870
  function notifyCacheCompatIfNeeded(
@@ -5141,6 +5170,14 @@ export default function (pi: ExtensionAPI) {
5141
5170
 
5142
5171
  const adapter = selectAdapterForModel(model);
5143
5172
  let statusText: string | undefined;
5173
+ if (!adapter && isRouterModel(model)) {
5174
+ // router/auto has no stable target family before the first successful
5175
+ // routed response. Keep the existing cache footer visible instead of
5176
+ // clearing it on model_select; message_end will switch to the real
5177
+ // upstream model/provider after pi-router relays the response metadata.
5178
+ return;
5179
+ }
5180
+
5144
5181
  if (adapter) {
5145
5182
  // Display session-scoped stats. A model that has never been used
5146
5183
  // in this session shows 0/0. The message_end hook populates
@@ -5322,9 +5359,11 @@ export default function (pi: ExtensionAPI) {
5322
5359
 
5323
5360
  const usage = adapter.normalizeUsage(event.message);
5324
5361
 
5362
+ const statsModel = isRouterModel(ctx.model) ? modelFromAssistantMessage(event.message, ctx.model) : ctx.model;
5363
+
5325
5364
  // Record recent sample (even when usage is missing, for trend diagnosis)
5326
- if (ctx.model) {
5327
- const sk = sessionModelKey(ctx.model);
5365
+ if (statsModel) {
5366
+ const sk = sessionModelKey(statsModel);
5328
5367
  const missingFields = usage === undefined || (usage.cacheRead === 0 && usage.cacheWrite === 0 && usage.totalInput === 0)
5329
5368
  ? true
5330
5369
  : hasMissingUsageFields(event.message, adapter);
@@ -5335,17 +5374,17 @@ export default function (pi: ExtensionAPI) {
5335
5374
 
5336
5375
  await rollOverStatsIfNeeded(ctx);
5337
5376
 
5338
- // Update stats scoped to current session + active model.
5339
- // Falls back to legacy family when ctx.model is undefined.
5340
- if (ctx.model) {
5341
- const sk = sessionModelKey(ctx.model);
5377
+ // Update stats scoped to current session + actual routed model.
5378
+ // Falls back to legacy family when no model is available.
5379
+ if (statsModel) {
5380
+ const sk = sessionModelKey(statsModel);
5342
5381
  addUsageToCacheStats(getOrCreateStatsByModelKey(sk), usage);
5343
5382
  } else {
5344
5383
  addUsageToCacheStats(getStatsForModel(undefined, adapter), usage);
5345
5384
  }
5346
5385
 
5347
5386
  schedulePersistCacheStats(ctx);
5348
- await publishStatus(ctx);
5387
+ await publishStatus(ctx, statsModel);
5349
5388
  });
5350
5389
 
5351
5390
  // ────────────────────────────────────────────────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-cache-optimizer",
3
- "version": "2.6.2",
3
+ "version": "2.6.3",
4
4
  "description": "Improve Pi prompt/KV cache hit rates with stable prompts, OpenAI-compatible cache keys, proxy compat warnings, and footer cache stats.",
5
5
  "keywords": [
6
6
  "pi-package",