pi-cache-optimizer 2.8.5 → 2.8.6

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 +90 -18
  2. package/package.json +1 -1
package/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
2
  import { chmod, copyFile, lstat, mkdir, readFile, readdir, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
3
- import { constants as fsConstants, readFileSync, watch } from "node:fs";
3
+ import { constants as fsConstants, readFileSync, statSync, watch } from "node:fs";
4
4
  import { homedir } from "node:os";
5
5
  import { dirname, join } from "node:path";
6
6
  import {
@@ -1057,9 +1057,10 @@ function isRoutedFallbackModel(model: PiModel | undefined): boolean {
1057
1057
  function applyConfiguredTransportToModel(model: PiModel, config: unknown): PiModel {
1058
1058
  const providers = asRecord(asRecord(config)?.providers);
1059
1059
  const provider = asRecord(providers?.[model.provider]);
1060
- const customModel = Array.isArray(provider?.models)
1061
- ? asRecord(provider.models.find((entry: unknown) => asRecord(entry)?.id === model.id))
1062
- : undefined;
1060
+ const customModel = findLastExactModelDefinition(
1061
+ Array.isArray(provider?.models) ? provider.models : undefined,
1062
+ model.id,
1063
+ );
1063
1064
  const configuredApi = customModel?.api ?? provider?.api;
1064
1065
  const configuredBaseUrl = customModel?.baseUrl ?? provider?.baseUrl;
1065
1066
  const api = isNonEmptyString(model.api)
@@ -1172,6 +1173,21 @@ const NESTED_COMPAT_KEYS = [
1172
1173
  "chatTemplateArgs",
1173
1174
  ] as const;
1174
1175
 
1176
+ function findLastExactModelDefinition(
1177
+ models: unknown[] | undefined,
1178
+ modelId: string,
1179
+ ): UnknownRecord | undefined {
1180
+ if (!models) return undefined;
1181
+ // Pi's provider composer processes definitions in array order. If a malformed
1182
+ // or hand-edited config repeats an id, the last definition replaces earlier
1183
+ // definitions, so effective resolution must use the same deterministic rule.
1184
+ for (let index = models.length - 1; index >= 0; index--) {
1185
+ const candidate = asRecord(models[index]);
1186
+ if (candidate?.id === modelId) return candidate;
1187
+ }
1188
+ return undefined;
1189
+ }
1190
+
1175
1191
  function mergeCacheCompat(...sources: Array<UnknownRecord | undefined>): CacheCompat {
1176
1192
  const merged: CacheCompat = {};
1177
1193
  for (const source of sources) {
@@ -1196,9 +1212,10 @@ function getEffectiveCompatSources(model: PiModel, config: unknown): Array<{ sou
1196
1212
  const providers = asRecord(root?.providers);
1197
1213
  const provider = asRecord(providers?.[model.provider]);
1198
1214
  const providerCompat = asRecord(provider?.compat);
1199
- const customModel = Array.isArray(provider?.models)
1200
- ? provider.models.find((entry: unknown) => asRecord(entry)?.id === model.id)
1201
- : undefined;
1215
+ const customModel = findLastExactModelDefinition(
1216
+ Array.isArray(provider?.models) ? provider.models : undefined,
1217
+ model.id,
1218
+ );
1202
1219
  const customModelCompat = asRecord(asRecord(customModel)?.compat);
1203
1220
  const runtimeCompat = asRecord(model.compat);
1204
1221
  const modelOverride = asRecord(asRecord(provider?.modelOverrides)?.[model.id]);
@@ -1357,6 +1374,10 @@ function isValidCompatRecord(value: unknown): boolean {
1357
1374
  );
1358
1375
  }
1359
1376
 
1377
+ // Credential-blind fail-closed subset of Pi's models.json validation. This
1378
+ // intentionally covers only fields consumed by compat diagnostics, transport
1379
+ // recovery, and exact route fallback; it is not a replacement for Pi's full
1380
+ // schema and must stay conservative when the file is malformed.
1360
1381
  function isValidModelsConfigForEffectiveCompat(value: unknown): boolean {
1361
1382
  const root = asRecord(value);
1362
1383
  const providers = asRecord(root?.providers);
@@ -1376,13 +1397,42 @@ function isValidModelsConfigForEffectiveCompat(value: unknown): boolean {
1376
1397
  return true;
1377
1398
  }
1378
1399
 
1379
- function readEffectiveCompatConfig(): unknown | undefined {
1400
+ type ModelsConfigCache = {
1401
+ signature: string;
1402
+ value: unknown | undefined;
1403
+ };
1404
+
1405
+ let modelsConfigCache: ModelsConfigCache | undefined;
1406
+
1407
+ function invalidateModelsConfigCache(): void {
1408
+ modelsConfigCache = undefined;
1409
+ }
1410
+
1411
+ function getModelsConfigSignature(): string {
1380
1412
  try {
1381
- const parsed = parseJsonc(readFileSync(MODELS_JSON_PATH, "utf8"));
1382
- return isValidModelsConfigForEffectiveCompat(parsed) ? parsed : undefined;
1413
+ const info = statSync(MODELS_JSON_PATH);
1414
+ return `${info.dev}:${info.ino}:${info.size}:${info.mtimeMs}:${info.ctimeMs}`;
1383
1415
  } catch {
1384
- return undefined;
1416
+ return "missing";
1417
+ }
1418
+ }
1419
+
1420
+ function readEffectiveCompatConfig(): unknown | undefined {
1421
+ const signature = getModelsConfigSignature();
1422
+ if (modelsConfigCache?.signature === signature) return modelsConfigCache.value;
1423
+
1424
+ let value: unknown | undefined;
1425
+ if (signature !== "missing") {
1426
+ try {
1427
+ const parsed = parseJsonc(readFileSync(MODELS_JSON_PATH, "utf8"));
1428
+ value = isValidModelsConfigForEffectiveCompat(parsed) ? parsed : undefined;
1429
+ } catch {
1430
+ value = undefined;
1431
+ }
1385
1432
  }
1433
+
1434
+ modelsConfigCache = { signature, value };
1435
+ return value;
1386
1436
  }
1387
1437
 
1388
1438
  function getCompat(model: PiModel | undefined): CacheCompat {
@@ -6083,12 +6133,13 @@ function resolveExplicitCompatValue(
6083
6133
  return { source: "modelOverride", value: overrideCompat[compatKey] };
6084
6134
  }
6085
6135
 
6086
- if (Array.isArray(provider.models)) {
6087
- const model = provider.models.find((entry: unknown) => asRecord(entry)?.id === modelId);
6088
- const modelCompat = asRecord(asRecord(model)?.compat);
6089
- if (modelCompat && Object.prototype.hasOwnProperty.call(modelCompat, compatKey)) {
6090
- return { source: "model", value: modelCompat[compatKey] };
6091
- }
6136
+ const model = findLastExactModelDefinition(
6137
+ Array.isArray(provider.models) ? provider.models : undefined,
6138
+ modelId,
6139
+ );
6140
+ const modelCompat = asRecord(model?.compat);
6141
+ if (modelCompat && Object.prototype.hasOwnProperty.call(modelCompat, compatKey)) {
6142
+ return { source: "model", value: modelCompat[compatKey] };
6092
6143
  }
6093
6144
 
6094
6145
  const providerCompat = asRecord(provider.compat);
@@ -6332,9 +6383,14 @@ function locateModelInJsonc(
6332
6383
  allModelIds.push(elementId);
6333
6384
  }
6334
6385
 
6335
- if (elementId === modelId && modelBrace < 0) {
6386
+ if (elementId === modelId) {
6387
+ // Match Pi's provider composer: later duplicate definitions replace
6388
+ // earlier ones. The effective/fix target is therefore the last exact id.
6336
6389
  modelBrace = elementBrace;
6337
6390
  modelEndBrace = elementEnd;
6391
+ compatKeyStartClean = -1;
6392
+ compatBrace = -1;
6393
+ compatEndBrace = -1;
6338
6394
 
6339
6395
  const compatKey = findJsonObjectKey(clean, modelBrace, "compat");
6340
6396
  if (compatKey && compatKey.keyStart < modelEndBrace) {
@@ -7606,6 +7662,7 @@ export const __internals_for_tests = {
7606
7662
  mergeCacheCompat,
7607
7663
  resolveEffectiveCompatFromConfig,
7608
7664
  getEffectiveCompatValueSource,
7665
+ findLastExactModelDefinition,
7609
7666
  isValidModelsConfigForEffectiveCompat,
7610
7667
  addEffectiveSessionAffinityHeaders,
7611
7668
  getCompat,
@@ -9081,6 +9138,20 @@ export default function (pi: ExtensionAPI) {
9081
9138
  return;
9082
9139
  }
9083
9140
 
9141
+ const duplicateTargetDefinitions = location.allModelIds.filter(
9142
+ (configuredModelId) => configuredModelId === suggestion.modelId,
9143
+ ).length;
9144
+ if (duplicateTargetDefinitions > 1) {
9145
+ cmdCtx.ui.notify(
9146
+ `❌ ${getModelsJsonDisplayPath()} contains ${duplicateTargetDefinitions} custom model definitions ` +
9147
+ `with the exact id "${suggestion.modelId}" under providers["${suggestion.providerLabel}"].\n` +
9148
+ `Pi uses the last definition, but /cache-optimizer fix refuses an ambiguous duplicate-id edit. ` +
9149
+ `Remove or consolidate the duplicates, then run the command again.`,
9150
+ "error",
9151
+ );
9152
+ return;
9153
+ }
9154
+
9084
9155
  // Compose the modified text — observed runtime failures are always
9085
9156
  // model-scoped; ordinary compat fixes use the safety-based placement.
9086
9157
  const decision = chooseFixPlacement(
@@ -9179,6 +9250,7 @@ export default function (pi: ExtensionAPI) {
9179
9250
  return;
9180
9251
  }
9181
9252
 
9253
+ invalidateModelsConfigCache();
9182
9254
  cmdCtx.ui.notify(
9183
9255
  `✅ Fix applied to ${getModelsJsonDisplayPath()}.\n` +
9184
9256
  `Backup saved to: ${backupPath}\n` +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-cache-optimizer",
3
- "version": "2.8.5",
3
+ "version": "2.8.6",
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",