@agimon-ai/doompi-cache 0.0.1-alpha.76 → 0.0.1-alpha.77

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.
@@ -416,7 +416,7 @@ var root_cli_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoot)(asyn
416
416
  telemetry: new PromptCacheTelemetry(),
417
417
  now: Date.now
418
418
  };
419
- const optimizer = await Promise.resolve().then(() => require("../pi-cache-optimizer-0QTIQ3WS.cjs"));
419
+ const optimizer = await Promise.resolve().then(() => require("../pi-cache-optimizer-OLTjpxH3.cjs"));
420
420
  if (typeof optimizer.default !== "function") throw new Error("Pi Cache Optimizer does not provide an extension factory.");
421
421
  await optimizer.default(pi);
422
422
  const runtime = createCacheRuntime(dependencies, optimizer);
@@ -1 +1 @@
1
- {"version":3,"file":"pi.d.mts","names":[],"sources":["../../src/types/cache.ts","../../src/types/extension.ts","../../generated/pi.ts"],"mappings":";KAAY;UA+CK;WACN;WACA;WACA;;UAGM,+BAA+B;WACrC;WACA;WACA;;UAGM;WACN,YAAY;WACZ;WACA;WACA;WACA;;UAGM,qCAAqC;WAC3C;WACA,uBAAuB;WACvB,kBAAkB;;UAGZ;EACf,aAAa,QAAQ;EACrB,QAAQ,OAAO,kBAAkB;EACjC,YAAY;EACZ;;;;UC3Ee;WACN,WAAW;WACX;;;;qBCaE,+DAAS,mBAAT"}
1
+ {"version":3,"file":"pi.d.mts","names":["_$___src_types_extension0.CacheExtensionDependencies"],"sources":["../../src/types/cache.ts","../../src/types/extension.ts","../../generated/pi.ts"],"mappings":";KAAY;UA+CK;WACN;WACA;WACA;;UAGM,+BAA+B;WACrC;WACA;WACA;;UAGM;WACN,YAAY;WACZ;WACA;WACA;WACA;;UAGM,qCAAqC;WAC3C;WACA,uBAAuB;WACvB,kBAAkB;;UAGZ;EACf,aAAa,QAAQ;EACrB,QAAQ,OAAO,kBAAkB;EACjC,YAAY;EACZ;;;;UC3Ee;WACN,WAAW;WACX;;;;qBCaE,+DAAS,mBAATA"}
@@ -412,7 +412,7 @@ var root_cli_default = defineRoot(async ({ pi, options }) => {
412
412
  telemetry: new PromptCacheTelemetry(),
413
413
  now: Date.now
414
414
  };
415
- const optimizer = await import("../pi-cache-optimizer-CBJnmxEY.mjs");
415
+ const optimizer = await import("../pi-cache-optimizer-DsNTCoBj.mjs");
416
416
  if (typeof optimizer.default !== "function") throw new Error("Pi Cache Optimizer does not provide an extension factory.");
417
417
  await optimizer.default(pi);
418
418
  const runtime = createCacheRuntime(dependencies, optimizer);
@@ -4,7 +4,7 @@ import { constants, readFileSync, statSync, watch } from "node:fs";
4
4
  import { homedir } from "node:os";
5
5
  import { basename, dirname, join } from "node:path";
6
6
  import { getAgentDir } from "@earendil-works/pi-coding-agent";
7
- //#region ../../../node_modules/.pnpm/pi-cache-optimizer@2.8.10_@earendil-works+pi-coding-agent@1.0.0_@aws-sdk+credential-pro_e6a616769ceba02485c856d1cac3f060/node_modules/pi-cache-optimizer/index.ts
7
+ //#region ../../../node_modules/.pnpm/pi-cache-optimizer@2.8.11_@earendil-works+pi-coding-agent@1.0.0_@aws-sdk+credential-pro_0ecfb3ce13205c80fe5b3070d67cc50f/node_modules/pi-cache-optimizer/index.ts
8
8
  const PI_CACHE_RETENTION_ENV = "PI_CACHE_RETENTION";
9
9
  const LONG_CACHE_RETENTION_VALUE = "long";
10
10
  const PI_CACHE_RETENTION_BASELINE_SYMBOL = Symbol.for("pi.cache.optimizer.retention-baseline.v1");
@@ -2970,7 +2970,7 @@ function buildOpenAIProxyCompatWarningText(key, missing) {
2970
2970
  const modelsJsonPath = getModelsJsonDisplayPath();
2971
2971
  const lines = [
2972
2972
  `💡 pi-cache-optimizer: ${key} is a third-party OpenAI-compatible proxy but merged compat lacks ${missing.join(" and ")}.`,
2973
- `Edit ${modelsJsonPath} -> providers["${providerLabel}"] -> compat (at the same level as baseUrl/api/apiKey/models).`,
2973
+ `Run /cache-optimizer fix to preview a confirmed repair (or edit ${modelsJsonPath} -> providers["${providerLabel}"] -> compat manually).`,
2974
2974
  ``
2975
2975
  ];
2976
2976
  appendOpenAIProxyCompatAdviceLines(lines, missing, {
@@ -4019,7 +4019,7 @@ function notifyCacheCompatIfNeeded(model, ctx, warnedModels) {
4019
4019
  const adapter = selectAdapterForModel(model);
4020
4020
  const text = adapter?.warningText?.(model);
4021
4021
  if (!adapter || !text) return;
4022
- const key = `${adapter.id}:${modelKey(model)}`;
4022
+ const key = adapter.warningText !== void 0 && describeMissingOpenAICompatibleProxyCompat(model).length === 1 && describeMissingCacheCompatForModel(model).length === 1 ? `proxy-affinity:${model.provider}` : `${adapter.id}:${modelKey(model)}`;
4023
4023
  if (warnedModels.has(key)) return;
4024
4024
  warnedModels.add(key);
4025
4025
  ctx.ui.notify(text, "warning");
@@ -5473,6 +5473,46 @@ function resolveExplicitCompatValue(config, providerLabel, modelId, compatKey) {
5473
5473
  function hasExplicitLongRetentionOptInFromConfig(config, providerLabel, modelId) {
5474
5474
  return resolveExplicitCompatValue(config, providerLabel, modelId, "supportsLongCacheRetention")?.value === true;
5475
5475
  }
5476
+ /** Locate a unique provider and its direct compat object without requiring models[]. */
5477
+ function locateProviderCompatInJsonc(text, providerLabel) {
5478
+ const clean = stripJsoncComments(text);
5479
+ const rootBrace = skipJsonWhitespace(clean, 0);
5480
+ if (clean[rootBrace] !== "{") return void 0;
5481
+ const providersKey = findJsonObjectKey(clean, rootBrace, "providers");
5482
+ if (!providersKey || providersKey.count !== 1) return void 0;
5483
+ const providersBrace = skipJsonWhitespace(clean, providersKey.valueStart);
5484
+ if (clean[providersBrace] !== "{") return void 0;
5485
+ const providersEnd = findMatchingBracket(clean, providersBrace);
5486
+ if (providersEnd === void 0) return void 0;
5487
+ const providerKey = findJsonObjectKey(clean, providersBrace, providerLabel);
5488
+ if (!providerKey || providerKey.count !== 1 || providerKey.keyStart > providersEnd) return void 0;
5489
+ const providerObjectBrace = skipJsonWhitespace(clean, providerKey.valueStart);
5490
+ if (clean[providerObjectBrace] !== "{") return void 0;
5491
+ const providerObjectEnd = findMatchingBracket(clean, providerObjectBrace);
5492
+ if (providerObjectEnd === void 0 || providerObjectEnd > providersEnd) return void 0;
5493
+ for (const key of ["models", "modelOverrides"]) {
5494
+ const child = findJsonObjectKey(clean, providerObjectBrace, key);
5495
+ if (child?.count && child.count > 1) return void 0;
5496
+ }
5497
+ const compatKey = findJsonObjectKey(clean, providerObjectBrace, "compat");
5498
+ if (compatKey?.count && compatKey.count > 1) return void 0;
5499
+ if (!compatKey) return {
5500
+ providerObjectBrace,
5501
+ providerObjectEnd,
5502
+ providerCompatBrace: -1,
5503
+ providerCompatEnd: -1
5504
+ };
5505
+ const providerCompatBrace = skipJsonWhitespace(clean, compatKey.valueStart);
5506
+ if (clean[providerCompatBrace] !== "{") return void 0;
5507
+ const providerCompatEnd = findMatchingBracket(clean, providerCompatBrace);
5508
+ if (providerCompatEnd === void 0 || providerCompatEnd > providerObjectEnd) return void 0;
5509
+ return {
5510
+ providerObjectBrace,
5511
+ providerObjectEnd,
5512
+ providerCompatBrace,
5513
+ providerCompatEnd
5514
+ };
5515
+ }
5476
5516
  /** Locate a provider and optional modelOverrides entry without requiring models[]. */
5477
5517
  function locateModelOverrideInJsonc(text, providerLabel, modelId) {
5478
5518
  const clean = stripJsoncComments(text);
@@ -6148,6 +6188,24 @@ function chooseFixPlacement(original, location, compatKeys, providerLabel, force
6148
6188
  };
6149
6189
  return decision;
6150
6190
  }
6191
+ function composeProviderAffinityInsertion(original, providerLabel) {
6192
+ const location = locateProviderCompatInJsonc(original, providerLabel);
6193
+ if (!location) return void 0;
6194
+ return {
6195
+ modifiedText: composeFixInsertion(original, {
6196
+ modelObjectBrace: -1,
6197
+ compatObjectBrace: -1,
6198
+ compatObjectEnd: -1,
6199
+ providerObjectBrace: location.providerObjectBrace,
6200
+ providerCompatBrace: location.providerCompatBrace,
6201
+ providerCompatEnd: location.providerCompatEnd,
6202
+ modelOverrideObjectBrace: -1,
6203
+ modelOverrideCompatBrace: -1,
6204
+ modelOverrideCompatEnd: -1
6205
+ }, { sendSessionAffinityHeaders: true }, "provider"),
6206
+ placementLabel: `providers["${providerLabel}"] -> compat (provider level)`
6207
+ };
6208
+ }
6151
6209
  function composeFixInsertion(original, location, compatKeys, placement = "model") {
6152
6210
  const targetCompatBrace = placement === "provider" ? location.providerCompatBrace : placement === "modelOverride" ? location.modelOverrideCompatBrace : location.compatObjectBrace;
6153
6211
  const targetCompatEnd = placement === "provider" ? location.providerCompatEnd : placement === "modelOverride" ? location.modelOverrideCompatEnd : location.compatObjectEnd;
@@ -6798,15 +6856,23 @@ function locateReceiptCompatTarget(text, provider, modelId, placement) {
6798
6856
  compatEnd: location.modelOverrideCompatEnd
6799
6857
  };
6800
6858
  }
6859
+ if (placement === "provider") {
6860
+ const location = locateProviderCompatInJsonc(text, provider);
6861
+ if (!location) return void 0;
6862
+ return {
6863
+ targetExists: true,
6864
+ compatBrace: location.providerCompatBrace,
6865
+ compatEnd: location.providerCompatEnd
6866
+ };
6867
+ }
6801
6868
  const location = locateModelInJsonc(text, provider, modelId);
6802
6869
  if (!location || location.providerKeyCount !== 1) return void 0;
6803
6870
  if (location.allModelIds.filter((id) => id === modelId).length !== 1) return void 0;
6804
- if (placement === "provider" && location.providerCompatKeyCount > 1) return void 0;
6805
- if (placement === "model" && location.modelCompatKeyCount > 1) return void 0;
6871
+ if (location.modelCompatKeyCount > 1) return void 0;
6806
6872
  return {
6807
6873
  targetExists: location.modelObjectBrace >= 0,
6808
- compatBrace: placement === "provider" ? location.providerCompatBrace : location.compatObjectBrace,
6809
- compatEnd: placement === "provider" ? location.providerCompatEnd : location.compatObjectEnd
6874
+ compatBrace: location.compatObjectBrace,
6875
+ compatEnd: location.compatObjectEnd
6810
6876
  };
6811
6877
  }
6812
6878
  function readReceiptCompatScalarState(text, target, key) {
@@ -7366,11 +7432,13 @@ const __internals_for_tests = {
7366
7432
  hasExplicitLongRetentionOptInFromConfig,
7367
7433
  locateModelInJsonc,
7368
7434
  locateModelOverrideInJsonc,
7435
+ locateProviderCompatInJsonc,
7369
7436
  composeFixInsertion,
7370
7437
  selfCheckFix,
7371
7438
  analyzeModelsJsonForMissingEntry,
7372
7439
  composeMissingEntryInsertion,
7373
7440
  composeModelOverrideInsertion,
7441
+ composeProviderAffinityInsertion,
7374
7442
  selfCheckMissingEntryInsertion,
7375
7443
  decideFixPlacement,
7376
7444
  chooseFixPlacement,
@@ -7462,7 +7530,8 @@ function pi_cache_optimizer_default(pi) {
7462
7530
  if (isSessionAffinity403Applicable(model) && sendSessionAffinityHeaders403Models.has(key)) return {
7463
7531
  providerLabel,
7464
7532
  modelId: model.id,
7465
- compatKeys: { sendSessionAffinityHeaders: false }
7533
+ compatKeys: { sendSessionAffinityHeaders: false },
7534
+ forceModelLevel: true
7466
7535
  };
7467
7536
  }
7468
7537
  function buildCommandFixSuggestion(model) {
@@ -8199,7 +8268,7 @@ function pi_cache_optimizer_default(pi) {
8199
8268
  const configReceiptSnapshot = await readPromptCacheKeyConfigReceiptSnapshot();
8200
8269
  const configReceipt = configReceiptSnapshot?.receipt;
8201
8270
  const modelsReceipt = await readModelsJsonFixReceipt();
8202
- if (isActionablePromptCacheKeyConfigReceipt(configReceipt) && configReceipt.provider === model.provider && configReceipt.modelId === model.id && (!isActionableModelsJsonFixReceipt(modelsReceipt) || modelsReceipt.provider !== model.provider || modelsReceipt.modelId !== model.id || configReceipt.appliedAt >= modelsReceipt.appliedAt)) {
8271
+ if (isActionablePromptCacheKeyConfigReceipt(configReceipt) && configReceipt.provider === model.provider && configReceipt.modelId === model.id && (!isActionableModelsJsonFixReceipt(modelsReceipt) || modelsReceipt.provider !== model.provider || modelsReceipt.placement !== "provider" && modelsReceipt.modelId !== model.id || configReceipt.appliedAt >= modelsReceipt.appliedAt)) {
8203
8272
  if (!cmdCtx.hasUI) {
8204
8273
  cmdCtx.ui.notify("❌ Rollback requires interactive confirmation. No changes were made.\nRun /cache-optimizer rollback in Pi's interactive UI to restore the prompt-cache-key setting.", "warning");
8205
8274
  return;
@@ -8231,7 +8300,7 @@ Run /cache-optimizer rollback in Pi's interactive UI.${backupHint} Then run /rel
8231
8300
  cmdCtx.ui.notify("ℹ️ No unapplied /cache-optimizer fix receipt was found.", "info");
8232
8301
  return;
8233
8302
  }
8234
- if (receipt.provider !== model.provider || receipt.modelId !== model.id) {
8303
+ if (receipt.provider !== model.provider || receipt.placement !== "provider" && receipt.modelId !== model.id) {
8235
8304
  cmdCtx.ui.notify(`ℹ️ The latest fix receipt is for ${receipt.provider}/${receipt.modelId}, not the active model ${model.provider}/${model.id}. Switch to the matching model before running rollback. No changes were made.`, "warning");
8236
8305
  return;
8237
8306
  }
@@ -8367,6 +8436,74 @@ Run /cache-optimizer fix prompt-cache-key in Pi's interactive UI for ${modelKey(
8367
8436
  const location = locateModelInJsonc(originalText, suggestion.providerLabel, suggestion.modelId);
8368
8437
  if (!location) {
8369
8438
  const diagnosis = analyzeModelsJsonForMissingEntry(originalText, suggestion.providerLabel, suggestion.modelId);
8439
+ const parsedOriginal = (() => {
8440
+ try {
8441
+ return parseJsonc(originalText);
8442
+ } catch {
8443
+ return;
8444
+ }
8445
+ })();
8446
+ const provider = asRecord(asRecord(parsedOriginal)?.providers)?.[suggestion.providerLabel];
8447
+ const explicit = resolveExplicitCompatValue(parsedOriginal, suggestion.providerLabel, suggestion.modelId, "sendSessionAffinityHeaders");
8448
+ const hasTargetOverride = (locateModelOverrideInJsonc(originalText, suggestion.providerLabel, suggestion.modelId)?.modelOverrideObjectBrace ?? -1) >= 0;
8449
+ const providerPlan = diagnosis && diagnosis.scenario !== "provider_missing" && isValidModelsConfigForEffectiveCompat(parsedOriginal) && asRecord(provider) && Object.keys(suggestion.compatKeys).length === 1 && suggestion.compatKeys.sendSessionAffinityHeaders === true && !suggestion.forceModelLevel && !hasTargetOverride && explicit === void 0 && getEffectiveCompatValueSource(model, parsedOriginal, "sendSessionAffinityHeaders") === void 0 ? composeProviderAffinityInsertion(originalText, suggestion.providerLabel) : void 0;
8450
+ if (providerPlan) {
8451
+ const checkProvider = (writtenText) => {
8452
+ try {
8453
+ const changed = parseJsonc(writtenText);
8454
+ if (!isValidModelsConfigForEffectiveCompat(changed)) return "provider config is invalid";
8455
+ if (resolveEffectiveCompatFromConfig(model, changed).sendSessionAffinityHeaders !== true) return "affinity flag is not effective";
8456
+ const reverted = JSON.parse(JSON.stringify(changed));
8457
+ const target = asRecord(asRecord(reverted.providers)?.[suggestion.providerLabel]);
8458
+ const compat = asRecord(target?.compat);
8459
+ if (!target || !compat || compat.sendSessionAffinityHeaders !== true) return "provider affinity key is missing";
8460
+ delete compat.sendSessionAffinityHeaders;
8461
+ if (!asRecord(asRecord(provider)?.compat)) delete target.compat;
8462
+ return JSON.stringify(reverted) === JSON.stringify(parsedOriginal) ? null : "unrelated configuration was altered";
8463
+ } catch {
8464
+ return "invalid provider JSONC";
8465
+ }
8466
+ };
8467
+ const checkError = checkProvider(providerPlan.modifiedText);
8468
+ if (checkError) {
8469
+ cmdCtx.ui.notify(`❌ Provider-level self-check failed: ${checkError}. No changes were made.`, "error");
8470
+ return;
8471
+ }
8472
+ const backupPath = `${MODELS_JSON_PATH}.backup-cache-optimizer-${backupTimestamp()}`;
8473
+ if (!await cmdCtx.ui.confirm("Cache Optimizer — Fix provider affinity", [
8474
+ `📝 Preview of changes to ${getModelsJsonDisplayPath()}:`,
8475
+ `Location: ${providerPlan.placementLabel}`,
8476
+ `Compat JSON to write: ${JSON.stringify(suggestion.compatKeys)}`,
8477
+ `⚠️ This affects all models using this provider across all sessions; model-level overrides remain authoritative.`,
8478
+ `A timestamped backup will be written to: ${backupPath}`,
8479
+ "Run /reload or restart Pi for the change to take effect.",
8480
+ "Apply these changes?"
8481
+ ].join("\n"))) {
8482
+ cmdCtx.ui.notify("No changes were made. Canceled by user.", "info");
8483
+ return;
8484
+ }
8485
+ const receipt = createModelsJsonFixReceipt(originalText, providerPlan.modifiedText, suggestion.providerLabel, suggestion.modelId, "provider", suggestion.compatKeys, true, backupPath);
8486
+ if (!receipt) {
8487
+ cmdCtx.ui.notify("❌ Could not create a privacy-safe fix receipt. No changes were made.", "error");
8488
+ return;
8489
+ }
8490
+ try {
8491
+ const result = await applyModelsJsonFixTransaction(providerPlan.modifiedText, backupPath, checkProvider, {
8492
+ expectedCurrentHash: hashText(originalText),
8493
+ purpose: "fix",
8494
+ onCommitted: async () => writeModelsJsonFixReceipt(receipt)
8495
+ });
8496
+ if ("postCheckError" in result) {
8497
+ cmdCtx.ui.notify(`❌ Post-write self-check failed: ${result.postCheckError}. Backup restored.`, "error");
8498
+ return;
8499
+ }
8500
+ invalidateModelsConfigCache();
8501
+ cmdCtx.ui.notify(`✅ Fix applied to ${getModelsJsonDisplayPath()}.\nBackup saved to: ${backupPath}\nRun /reload or restart Pi.`, "info");
8502
+ } catch (error) {
8503
+ cmdCtx.ui.notify(`❌ Write failed: ${error instanceof Error ? error.message : String(error)}. Backup may be at: ${backupPath}`, "error");
8504
+ }
8505
+ return;
8506
+ }
8370
8507
  if (diagnosis && cmdCtx.hasUI) {
8371
8508
  const repairsExistingOverride = (locateModelOverrideInJsonc(originalText, suggestion.providerLabel, suggestion.modelId)?.modelOverrideObjectBrace ?? -1) >= 0;
8372
8509
  const plan = composeModelOverrideInsertion(originalText, suggestion.providerLabel, suggestion.modelId, suggestion.compatKeys);
@@ -8575,4 +8712,4 @@ Run /cache-optimizer fix prompt-cache-key in Pi's interactive UI for ${modelKey(
8575
8712
  //#endregion
8576
8713
  export { __internals_for_tests, pi_cache_optimizer_default as default };
8577
8714
 
8578
- //# sourceMappingURL=pi-cache-optimizer-CBJnmxEY.mjs.map
8715
+ //# sourceMappingURL=pi-cache-optimizer-DsNTCoBj.mjs.map