@agimon-ai/doompi-cache 0.0.1-alpha.81 → 0.0.1-alpha.83

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.
@@ -4,7 +4,7 @@ let node_fs = require("node:fs");
4
4
  let node_os = require("node:os");
5
5
  let node_path = require("node:path");
6
6
  let _earendil_works_pi_coding_agent = require("@earendil-works/pi-coding-agent");
7
- //#region ../../../node_modules/.pnpm/pi-cache-optimizer@2.8.11_@earendil-works+pi-coding-agent@1.0.2_@aws-sdk+credential-pro_d92cfe1c8329e9bda023a760e3edd654/node_modules/pi-cache-optimizer/index.ts
7
+ //#region ../../../node_modules/.pnpm/pi-cache-optimizer@2.8.16_@earendil-works+pi-coding-agent@1.0.2_@aws-sdk+credential-pro_336a3137387524f540927fd810e3b800/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");
@@ -91,6 +91,7 @@ const NO_OPENAI_CACHE_KEY_ENV = "PI_CACHE_OPTIMIZER_NO_OPENAI_CACHE_KEY";
91
91
  const OPENAI_PROMPT_CACHE_KEY_MAX_LENGTH = 64;
92
92
  const NO_SKILL_COMPRESSION_ENV = "PI_CACHE_OPTIMIZER_NO_SKILL_COMPRESSION";
93
93
  const NO_PROMPT_REWRITE_ENV = "PI_CACHE_OPTIMIZER_NO_PROMPT_REWRITE";
94
+ const VIRTUAL_REWRITE_ENV = "PI_CACHE_OPTIMIZER_VIRTUAL_REWRITE";
94
95
  const TOOL_ORDER_ENV = "PI_CACHE_OPTIMIZER_TOOL_ORDER";
95
96
  const FOOTER_MODE_ENV = "PI_CACHE_OPTIMIZER_FOOTER_MODE";
96
97
  const RECEIPT_COMPAT_KEYS = /* @__PURE__ */ new Set([
@@ -104,6 +105,7 @@ const RECEIPT_COMPAT_KEYS = /* @__PURE__ */ new Set([
104
105
  ]);
105
106
  const PI_ROUTING_REGISTRY_SYMBOL = Symbol.for("pi.routing.registry.v1");
106
107
  const PI_CACHE_HINTS_SYMBOL = Symbol.for("pi.cache.hints.v1");
108
+ const PI_VIRTUAL_MODEL_API = "pi-virtual";
107
109
  const PI_CACHE_HINTS_OWNER_SYMBOL = Symbol.for("pi.cache.optimizer.hints-owner.v1");
108
110
  const ANTHROPIC_TTL_FALLBACK_SYMBOL = Symbol.for("pi.cache.optimizer.anthropic-ttl-fallback.v1");
109
111
  const REASONING_PROTOCOL_FALLBACK_SYMBOL = Symbol.for("pi.cache.optimizer.reasoning-protocol-fallback.v1");
@@ -437,7 +439,7 @@ function formatSkillsForPromptCompressed(skills) {
437
439
  * than mangle.
438
440
  */
439
441
  function compressSkillsInSystemPrompt(prompt, opts) {
440
- if (isEnabledEnv(process.env[NO_SKILL_COMPRESSION_ENV])) return prompt;
442
+ if (!featureEnabled("skillCompression", NO_SKILL_COMPRESSION_ENV, true)) return prompt;
441
443
  if (!opts.skills || opts.skills.length === 0) return prompt;
442
444
  if (opts.skills.filter((skill) => !skill.disableModelInvocation).length < SKILL_COMPRESSION_MIN_COUNT) return prompt;
443
445
  const verbose = formatSkillsForPrompt(opts.skills);
@@ -692,7 +694,7 @@ function parseRouteSnapshot(value, fallbackVirtualProvider, fallbackVirtualModel
692
694
  };
693
695
  }
694
696
  function resolveActiveRouteSnapshot(model, ctx) {
695
- if (!model) return void 0;
697
+ if (!model || isNativeVirtualModel(model)) return void 0;
696
698
  const hint = ctx ? { sessionIdHash: sessionHashFromContext(ctx) } : void 0;
697
699
  const adapter = getRoutingRegistry()?.getRouter(model.provider);
698
700
  if (adapter) try {
@@ -713,6 +715,31 @@ function resolveActiveRouteSnapshot(model, ctx) {
713
715
  return;
714
716
  }
715
717
  }
718
+ function resolveNativeVirtualCandidateModels(model, ctx) {
719
+ if (!isNativeVirtualModel(model)) return void 0;
720
+ const adapter = model ? getRoutingRegistry()?.getRouter(model.provider) : void 0;
721
+ if (!adapter?.resolveCandidateRoutes) return void 0;
722
+ try {
723
+ const rawSnapshots = adapter.resolveCandidateRoutes(model.id);
724
+ if (!Array.isArray(rawSnapshots) || rawSnapshots.length === 0) return void 0;
725
+ const candidates = [];
726
+ for (const rawSnapshot of rawSnapshots) {
727
+ const snapshot = parseRouteSnapshot(rawSnapshot, model.provider, model.id);
728
+ if (!snapshot) return void 0;
729
+ const candidate = findModelInRegistry(ctx?.modelRegistry, snapshot.provider, snapshot.modelId) ?? routeSnapshotToPiModel(snapshot, model);
730
+ if (!isNonEmptyString(candidate.api)) return void 0;
731
+ candidates.push(candidate);
732
+ }
733
+ return candidates;
734
+ } catch {
735
+ return;
736
+ }
737
+ }
738
+ function canRewriteNativeVirtualPrompt(model, ctx) {
739
+ if (!isNativeVirtualModel(model) || !featureEnabled("virtualRewrite", VIRTUAL_REWRITE_ENV, false)) return false;
740
+ const candidates = resolveNativeVirtualCandidateModels(model, ctx);
741
+ return !!candidates?.length && candidates.every((candidate) => candidate.api === "openai-completions" || candidate.api === "anthropic-messages") && candidates.every((candidate) => !isResponsesPromptRewriteBypassApi(candidate.api));
742
+ }
716
743
  function routeSnapshotToPiModel(snapshot, fallback) {
717
744
  const sameIdentity = fallback?.provider === snapshot.provider && fallback?.id === snapshot.modelId;
718
745
  return {
@@ -769,13 +796,151 @@ function applyConfiguredTransportToModel(model, config) {
769
796
  };
770
797
  }
771
798
  function resolveRouteModel(model, ctx) {
799
+ const nativeVirtualRoute = resolveNativeVirtualRouteModel(model, ctx);
800
+ if (nativeVirtualRoute) return nativeVirtualRoute;
772
801
  const snapshot = resolveActiveRouteSnapshot(model, ctx);
773
802
  if (!snapshot) return void 0;
774
803
  return applyConfiguredTransportToModel(findModelInRegistry(ctx?.modelRegistry, snapshot.provider, snapshot.modelId) ?? routeSnapshotToPiModel(snapshot, model), readEffectiveCompatConfig());
775
804
  }
776
805
  function isVirtualRoutingModel(model, ctx) {
777
806
  if (!model) return false;
778
- return isRouterModel(model) || !!getRoutingRegistry()?.getRouter(model.provider) || !!resolveActiveRouteSnapshot(model, ctx);
807
+ return isNativeVirtualModel(model) || isRouterModel(model) || !!getRoutingRegistry()?.getRouter(model.provider) || !!resolveActiveRouteSnapshot(model, ctx);
808
+ }
809
+ function isNativeVirtualModel(model) {
810
+ return model?.api === PI_VIRTUAL_MODEL_API;
811
+ }
812
+ function readSessionBranch(ctx) {
813
+ try {
814
+ const manager = ctx?.sessionManager;
815
+ if (typeof manager?.getBranch !== "function") return [];
816
+ const branch = manager.getBranch();
817
+ return Array.isArray(branch) ? branch : [];
818
+ } catch {
819
+ return [];
820
+ }
821
+ }
822
+ /**
823
+ * Physical models that answered on the current session branch, newest first:
824
+ * the latest successful response (Pi's `request.previous`) and the latest
825
+ * response of any outcome (a failed attempt that a retry may reuse). The
826
+ * catalog id in `message.model` is preferred over the echoed `responseModel`
827
+ * because it is the id Pi dispatched and the registry knows.
828
+ */
829
+ function findNativeVirtualDispatches(ctx) {
830
+ const branch = readSessionBranch(ctx);
831
+ let latestSuccessful;
832
+ let latestAny;
833
+ for (let index = branch.length - 1; index >= 0 && !latestSuccessful; index--) {
834
+ const entry = asRecord(branch[index]);
835
+ if (entry?.type !== "message") continue;
836
+ const message = getAssistantRecord(entry.message);
837
+ if (!message || isNativeVirtualModel(message)) continue;
838
+ const dispatch = nativeVirtualDispatchFromMessage(message);
839
+ if (!dispatch) continue;
840
+ latestAny ??= dispatch;
841
+ if (message.stopReason !== "error" && message.stopReason !== "aborted") latestSuccessful = dispatch;
842
+ }
843
+ return {
844
+ latestSuccessful,
845
+ latestAny
846
+ };
847
+ }
848
+ function nativeVirtualDispatchFromMessage(message) {
849
+ const record = getAssistantRecord(message);
850
+ if (!record || isNativeVirtualModel(record)) return void 0;
851
+ const provider = firstNonEmptyString(record.provider);
852
+ const id = firstNonEmptyString(record.model, record.responseModel);
853
+ return provider && id ? {
854
+ provider,
855
+ id,
856
+ api: firstNonEmptyString(record.api) ?? ""
857
+ } : void 0;
858
+ }
859
+ function nativeVirtualDispatchToModel(dispatch, ctx) {
860
+ const registered = findModelInRegistry(ctx?.modelRegistry, dispatch.provider, dispatch.id);
861
+ return applyConfiguredTransportToModel(registered && !isNativeVirtualModel(registered) ? registered : {
862
+ provider: dispatch.provider,
863
+ id: dispatch.id,
864
+ name: dispatch.id,
865
+ api: dispatch.api,
866
+ baseUrl: "",
867
+ reasoning: false,
868
+ input: ["text"],
869
+ cost: {
870
+ input: 0,
871
+ output: 0,
872
+ cacheRead: 0,
873
+ cacheWrite: 0
874
+ },
875
+ contextWindow: 0,
876
+ maxTokens: 0,
877
+ [ROUTED_FALLBACK_MODEL_SYMBOL]: true
878
+ }, readEffectiveCompatConfig());
879
+ }
880
+ /**
881
+ * Physical model behind a native virtual selection for pre-request UX (footer,
882
+ * doctor, compat, stats, reset, fix): the model that answered last on this
883
+ * session branch, matching Pi's own routed-model display and context limits.
884
+ */
885
+ function resolveNativeVirtualRouteModel(model, ctx) {
886
+ if (!isNativeVirtualModel(model)) return void 0;
887
+ const { latestSuccessful, latestAny } = findNativeVirtualDispatches(ctx);
888
+ const dispatch = latestSuccessful ?? latestAny;
889
+ return dispatch ? nativeVirtualDispatchToModel(dispatch, ctx) : void 0;
890
+ }
891
+ function getProviderPayloadModelId(payload) {
892
+ const record = asRecord(payload);
893
+ return firstNonEmptyString(record?.model, record?.modelId);
894
+ }
895
+ function physicalModelsWithId(candidates, id) {
896
+ return (candidates ?? []).filter((candidate) => candidate.id === id && !isNativeVirtualModel(candidate) && !isRouterModel(candidate) && !getRoutingRegistry()?.getRouter(candidate.provider));
897
+ }
898
+ /**
899
+ * Physical model of one native-virtual request. `before_provider_request`
900
+ * carries only the payload and `ctx.model` stays virtual, so the payload's
901
+ * dispatched model id is matched against credentialed physical models (a
902
+ * router may only route to those). A unique provider match wins. An id shared
903
+ * by several credentialed providers is used only when every candidate gets the
904
+ * same request treatment (`requestPolicyKey`); the identity then stays
905
+ * ambiguous so response evidence is never pinned to a guessed provider.
906
+ * Differing policies return undefined so identity-dependent request mutations
907
+ * fail closed. Without a credentialed match, the sticky branch candidates and
908
+ * then the full catalog are consulted.
909
+ */
910
+ function resolveNativeVirtualRequestModel(model, payload, ctx, requestPolicyKey) {
911
+ if (!isNativeVirtualModel(model)) return void 0;
912
+ const payloadModelId = getProviderPayloadModelId(payload);
913
+ if (!payloadModelId) return void 0;
914
+ const config = readEffectiveCompatConfig();
915
+ const pick = (matches) => {
916
+ if (matches.length === 0) return null;
917
+ const configured = matches.map((candidate) => applyConfiguredTransportToModel(candidate, config));
918
+ if (new Set(configured.map((candidate) => candidate.provider)).size === 1) return {
919
+ model: configured[0],
920
+ identityAmbiguous: false
921
+ };
922
+ return (requestPolicyKey ? new Set(configured.map(requestPolicyKey)) : void 0)?.size === 1 ? {
923
+ model: configured[0],
924
+ identityAmbiguous: true
925
+ } : void 0;
926
+ };
927
+ try {
928
+ const credentialed = pick(physicalModelsWithId(ctx?.modelRegistry?.getAvailable?.(), payloadModelId));
929
+ if (credentialed !== null) return credentialed;
930
+ const { latestSuccessful, latestAny } = findNativeVirtualDispatches(ctx);
931
+ for (const dispatch of [latestSuccessful, latestAny]) if (dispatch?.id === payloadModelId) return {
932
+ model: nativeVirtualDispatchToModel(dispatch, ctx),
933
+ identityAmbiguous: false
934
+ };
935
+ return pick(physicalModelsWithId(ctx?.modelRegistry?.getAll?.(), payloadModelId)) ?? void 0;
936
+ } catch {
937
+ return;
938
+ }
939
+ }
940
+ function describeNativeVirtualRouteNote(selected, effective) {
941
+ if (!selected || !isNativeVirtualModel(selected)) return void 0;
942
+ if (!effective || isNativeVirtualModel(effective)) return void 0;
943
+ return `🔀 Native virtual model ${modelKey(selected)} → latest routed physical model ${modelKey(effective)}. The diagnostics below apply to that physical model; Pi may route later requests elsewhere.`;
779
944
  }
780
945
  function isCacheHintsServiceV1(value) {
781
946
  const record = asRecord(value);
@@ -1152,8 +1317,15 @@ function isEnabledEnv(value) {
1152
1317
  const normalized = value.trim().toLowerCase();
1153
1318
  return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
1154
1319
  }
1320
+ function featureEnabled(feature, envName, defaultValue, env = process.env, config = persistedCacheOptimizerConfig) {
1321
+ const configured = config.features?.[feature];
1322
+ if (configured !== void 0) return configured;
1323
+ if (feature === "virtualRewrite") return isEnabledEnv(env[envName]);
1324
+ if (feature === "promptRewrite" || feature === "skillCompression" || feature === "openAICacheKey") return !isEnabledEnv(env[envName]);
1325
+ return isEnabledEnv(env[envName]) || defaultValue;
1326
+ }
1155
1327
  function isToolOrderEnabled(env = process.env) {
1156
- return runtimeOptimizerEnabled && isEnabledEnv(env[TOOL_ORDER_ENV]);
1328
+ return runtimeOptimizerEnabled && featureEnabled("toolOrder", TOOL_ORDER_ENV, false);
1157
1329
  }
1158
1330
  function parseFooterStatsMode(value) {
1159
1331
  if (typeof value !== "string") return void 0;
@@ -1171,12 +1343,35 @@ const CACHE_OPTIMIZER_COMMANDS = [
1171
1343
  "fix",
1172
1344
  "rollback"
1173
1345
  ];
1174
- const CACHE_OPTIMIZER_CONFIG_ARGUMENTS = ["footer-mode"];
1346
+ const CACHE_OPTIMIZER_CONFIG_ARGUMENTS = [
1347
+ "footer-mode",
1348
+ "prompt-rewrite",
1349
+ "virtual-rewrite",
1350
+ "skill-compression",
1351
+ "openai-cache-key",
1352
+ "tool-order",
1353
+ "reset"
1354
+ ];
1355
+ const CACHE_OPTIMIZER_FEATURE_COMMANDS = [
1356
+ "prompt-rewrite",
1357
+ "virtual-rewrite",
1358
+ "skill-compression",
1359
+ "openai-cache-key",
1360
+ "tool-order"
1361
+ ];
1362
+ const CACHE_OPTIMIZER_FEATURE_VALUES = ["on", "off"];
1175
1363
  const CACHE_OPTIMIZER_FOOTER_MODES = [
1176
1364
  "total",
1177
1365
  "session",
1178
1366
  "process"
1179
1367
  ];
1368
+ const FEATURE_COMMAND_MAP = {
1369
+ "prompt-rewrite": "promptRewrite",
1370
+ "virtual-rewrite": "virtualRewrite",
1371
+ "skill-compression": "skillCompression",
1372
+ "openai-cache-key": "openAICacheKey",
1373
+ "tool-order": "toolOrder"
1374
+ };
1180
1375
  const CACHE_OPTIMIZER_STATS_ARGUMENTS = ["all", "contributors"];
1181
1376
  const CACHE_OPTIMIZER_FIX_ARGUMENTS = ["prompt-cache-key"];
1182
1377
  function filterCommandCompletionItems(values, prefix, argumentPath = "") {
@@ -1210,15 +1405,21 @@ function getCacheOptimizerArgumentCompletions(argumentPrefix) {
1210
1405
  return filterCommandCompletionItems(CACHE_OPTIMIZER_CONFIG_ARGUMENTS, parts[1], "config");
1211
1406
  }
1212
1407
  if (parts.length === 3 && parts[1].toLowerCase() === "footer-mode") return filterCommandCompletionItems(CACHE_OPTIMIZER_FOOTER_MODES, parts[2], "config footer-mode");
1408
+ if (parts.length === 3 && CACHE_OPTIMIZER_FEATURE_COMMANDS.includes(parts[1])) return filterCommandCompletionItems(CACHE_OPTIMIZER_FEATURE_VALUES, parts[2], `config ${parts[1]}`);
1213
1409
  return null;
1214
1410
  }
1215
1411
  function parsePersistedCacheOptimizerConfig(value) {
1216
1412
  const record = asRecord(value);
1217
- if (!record || record.version !== 1 && record.version !== 2) return void 0;
1218
- const allowedTopLevel = new Set(record.version === 1 ? ["version", "footerMode"] : [
1413
+ if (!record || record.version !== 1 && record.version !== 2 && record.version !== 3) return void 0;
1414
+ const allowedTopLevel = new Set(record.version === 1 ? ["version", "footerMode"] : record.version === 2 ? [
1219
1415
  "version",
1220
1416
  "footerMode",
1221
1417
  "promptCacheKey"
1418
+ ] : [
1419
+ "version",
1420
+ "footerMode",
1421
+ "promptCacheKey",
1422
+ "features"
1222
1423
  ]);
1223
1424
  if (Object.keys(record).some((key) => !allowedTopLevel.has(key))) return void 0;
1224
1425
  const footerMode = parseFooterStatsMode(record.footerMode);
@@ -1227,6 +1428,17 @@ function parsePersistedCacheOptimizerConfig(value) {
1227
1428
  version: 1,
1228
1429
  ...footerMode ? { footerMode } : {}
1229
1430
  };
1431
+ const rawFeatures = record.version === 3 ? record.features : void 0;
1432
+ if (rawFeatures !== void 0 && !asRecord(rawFeatures)) return void 0;
1433
+ const featuresRecord = asRecord(rawFeatures);
1434
+ const featureNames = /* @__PURE__ */ new Set([
1435
+ "promptRewrite",
1436
+ "virtualRewrite",
1437
+ "skillCompression",
1438
+ "openAICacheKey",
1439
+ "toolOrder"
1440
+ ]);
1441
+ if (featuresRecord && Object.keys(featuresRecord).some((key) => !featureNames.has(key) || typeof featuresRecord[key] !== "boolean")) return void 0;
1230
1442
  const rawPromptCacheKey = record.promptCacheKey;
1231
1443
  if (rawPromptCacheKey !== void 0 && !asRecord(rawPromptCacheKey)) return void 0;
1232
1444
  const promptCacheKey = asRecord(rawPromptCacheKey);
@@ -1236,16 +1448,20 @@ function parsePersistedCacheOptimizerConfig(value) {
1236
1448
  const stringOmit = omit;
1237
1449
  const uniqueOmit = stringOmit ? [...new Set(stringOmit.map((value) => value.trim()))].sort() : void 0;
1238
1450
  return {
1239
- version: 2,
1451
+ version: record.version === 3 ? 3 : 2,
1240
1452
  ...footerMode ? { footerMode } : {},
1241
- ...uniqueOmit && uniqueOmit.length > 0 ? { promptCacheKey: { omit: uniqueOmit } } : {}
1453
+ ...uniqueOmit && uniqueOmit.length > 0 ? { promptCacheKey: { omit: uniqueOmit } } : {},
1454
+ ...featuresRecord ? { features: Object.fromEntries(Object.entries(featuresRecord)) } : {}
1242
1455
  };
1243
1456
  }
1244
1457
  function normalizePersistedCacheOptimizerConfig(value) {
1245
1458
  if (!value) return { version: 2 };
1246
- return value.version === 2 ? value : {
1247
- version: 2,
1248
- ...value.footerMode ? { footerMode: value.footerMode } : {}
1459
+ const features = value.version === 3 ? value.features : void 0;
1460
+ return {
1461
+ version: features ? 3 : 2,
1462
+ ...value.footerMode ? { footerMode: value.footerMode } : {},
1463
+ ...value.version !== 1 && value.promptCacheKey ? { promptCacheKey: value.promptCacheKey } : {},
1464
+ ...features ? { features } : {}
1249
1465
  };
1250
1466
  }
1251
1467
  function readPersistedCacheOptimizerConfig(configPath = CONFIG_FILE_PATH) {
@@ -1295,7 +1511,7 @@ async function writePersistedFooterModeUnlocked(mode, configPath) {
1295
1511
  raw = parsePersistedCacheOptimizerConfig(JSON.parse((0, node_fs.readFileSync)(configPath, "utf8")));
1296
1512
  targetExists = true;
1297
1513
  if (!raw) throw new Error("invalid footer config schema");
1298
- version = raw.version === 2 ? 2 : 1;
1514
+ version = raw.version === 3 ? 3 : raw.version === 2 ? 2 : 1;
1299
1515
  } catch (error) {
1300
1516
  if (getErrorCode(error) !== "ENOENT") throw new Error("invalid footer config schema");
1301
1517
  }
@@ -1320,13 +1536,25 @@ async function writePersistedFooterModeUnlocked(mode, configPath) {
1320
1536
  }
1321
1537
  await writePersistedCacheOptimizerConfigUnlocked({
1322
1538
  ...current,
1323
- version: 2,
1539
+ version: 3,
1324
1540
  footerMode: mode
1325
1541
  }, configPath);
1326
1542
  }
1327
1543
  async function writePersistedFooterMode(mode, configPath = CONFIG_FILE_PATH) {
1328
1544
  await withModelsJsonTransactionLock(() => writePersistedFooterModeUnlocked(mode, configPath));
1329
1545
  }
1546
+ async function writePersistedFeature(feature, enabled) {
1547
+ const current = readPersistedCacheOptimizerConfig();
1548
+ await writePersistedCacheOptimizerConfig({
1549
+ ...current,
1550
+ version: 3,
1551
+ features: {
1552
+ ...current.features ?? {},
1553
+ [feature]: enabled
1554
+ }
1555
+ });
1556
+ setPersistedCacheOptimizerConfig(readPersistedCacheOptimizerConfig());
1557
+ }
1330
1558
  function configReceiptBackupPath(receipt, receiptPath = CONFIG_RECEIPT_PATH) {
1331
1559
  return (0, node_path.join)((0, node_path.dirname)(receiptPath), receipt.backupFile);
1332
1560
  }
@@ -1706,7 +1934,7 @@ function isDisabledEnv(value) {
1706
1934
  }
1707
1935
  function shouldInjectOpenAIPromptCacheKey() {
1708
1936
  if (!runtimeOptimizerEnabled) return false;
1709
- if (isEnabledEnv(process.env[NO_OPENAI_CACHE_KEY_ENV])) return false;
1937
+ if (!featureEnabled("openAICacheKey", NO_OPENAI_CACHE_KEY_ENV, true)) return false;
1710
1938
  if (isDisabledEnv(process.env[OPENAI_CACHE_KEY_ENV])) return false;
1711
1939
  return true;
1712
1940
  }
@@ -1722,16 +1950,60 @@ function getOptimizerRuntimeModeLines() {
1722
1950
  const state = runtimeOptimizerEnabled ? "enabled" : "disabled";
1723
1951
  const lines = [];
1724
1952
  lines.push(`Runtime state: ${state}`);
1725
- lines.push(`• Prompt rewrite: ${runtimeOptimizerEnabled && !isEnabledEnv(process.env[NO_PROMPT_REWRITE_ENV]) ? "on" : "off"}`);
1953
+ lines.push(`• Prompt rewrite: ${runtimeOptimizerEnabled && featureEnabled("promptRewrite", NO_PROMPT_REWRITE_ENV, true) ? "on" : "off"}`);
1954
+ lines.push(`• Native virtual rewrite: ${featureEnabled("virtualRewrite", VIRTUAL_REWRITE_ENV, false) ? "opt-in" : "off"}`);
1955
+ lines.push(`• Skill compression: ${featureEnabled("skillCompression", NO_SKILL_COMPRESSION_ENV, true) ? "on" : "off"}`);
1726
1956
  lines.push(`• Deterministic tool ordering: ${isToolOrderEnabled() ? "on (verified built-in payloads, opt-in)" : "off"}`);
1727
1957
  lines.push(`• OpenAI prompt_cache_key fallback: ${shouldInjectOpenAIPromptCacheKey() ? "on" : "off"}`);
1728
1958
  lines.push(`• Footer cache stats: on${runtimeOptimizerEnabled ? "" : " (comparison mode)"}`);
1729
1959
  lines.push(`• Compat warnings: ${runtimeOptimizerEnabled ? "on" : "off"}`);
1730
1960
  lines.push(`• ${PI_CACHE_RETENTION_ENV}: ${process.env[PI_CACHE_RETENTION_ENV] ?? "(unset)"}`);
1961
+ lines.push(`• Persistent feature overrides: ${Object.keys(persistedCacheOptimizerConfig.features ?? {}).length > 0 ? "configured" : "none"}`);
1731
1962
  if (!runtimeOptimizerEnabled) lines.push("This is a current-process switch. Run /reload or restart Pi to return to startup behavior.");
1732
- else if (isEnabledEnv(process.env[NO_PROMPT_REWRITE_ENV]) || !shouldInjectOpenAIPromptCacheKey()) lines.push("Some features are still disabled by environment variables.");
1963
+ else if (!featureEnabled("promptRewrite", NO_PROMPT_REWRITE_ENV, true) || !shouldInjectOpenAIPromptCacheKey()) lines.push("Some features are still disabled by environment variables.");
1733
1964
  return lines;
1734
1965
  }
1966
+ function formatPersistentFeatureConfig() {
1967
+ const features = persistedCacheOptimizerConfig.features ?? {};
1968
+ const lines = ["Persistent feature configuration:"];
1969
+ const entries = [
1970
+ [
1971
+ "Prompt rewrite",
1972
+ "promptRewrite",
1973
+ NO_PROMPT_REWRITE_ENV,
1974
+ true
1975
+ ],
1976
+ [
1977
+ "Native virtual rewrite",
1978
+ "virtualRewrite",
1979
+ VIRTUAL_REWRITE_ENV,
1980
+ false
1981
+ ],
1982
+ [
1983
+ "Skill compression",
1984
+ "skillCompression",
1985
+ NO_SKILL_COMPRESSION_ENV,
1986
+ true
1987
+ ],
1988
+ [
1989
+ "OpenAI cache key",
1990
+ "openAICacheKey",
1991
+ NO_OPENAI_CACHE_KEY_ENV,
1992
+ true
1993
+ ],
1994
+ [
1995
+ "Tool ordering",
1996
+ "toolOrder",
1997
+ TOOL_ORDER_ENV,
1998
+ false
1999
+ ]
2000
+ ];
2001
+ for (const [label, feature, envName, defaultValue] of entries) {
2002
+ const source = features[feature] !== void 0 ? "config" : process.env[envName] !== void 0 ? "env" : "default";
2003
+ lines.push(`• ${label}: ${featureEnabled(feature, envName, defaultValue) ? "on" : "off"} (${source})`);
2004
+ }
2005
+ return lines.join("\n");
2006
+ }
1735
2007
  function formatOptimizerRuntimeMode() {
1736
2008
  return getOptimizerRuntimeModeLines().join("\n");
1737
2009
  }
@@ -1776,14 +2048,14 @@ function isOpenAICompatibleProxyApi(api) {
1776
2048
  function isPiBuiltInLlamaCppModel(model) {
1777
2049
  if (lower(model?.provider) !== "llama.cpp" || !isOpenAICompatibleProxyApi(model?.api)) return false;
1778
2050
  const compat = getCompat(model);
1779
- return compat.supportsStore === false && compat.supportsDeveloperRole === false && compat.supportsReasoningEffort === false && compat.supportsUsageInStreaming === false && compat.supportsStrictMode === false && compat.maxTokensField === "max_tokens" && compat.sendSessionAffinityHeaders === void 0 && compat.sessionAffinityFormat === void 0 && compat.supportsLongCacheRetention === void 0;
2051
+ return compat.supportsStore === false && compat.supportsDeveloperRole === false && compat.supportsReasoningEffort === false && compat.supportsStrictMode === false && compat.maxTokensField === "max_tokens" && compat.sendSessionAffinityHeaders === void 0 && compat.sessionAffinityFormat === void 0 && compat.supportsLongCacheRetention === void 0;
1780
2052
  }
1781
2053
  function shouldInjectOpenAIPromptCacheKeyForModel(model) {
1782
2054
  return isOpenAICompatibleApi(model?.api);
1783
2055
  }
1784
2056
  function isPromptCacheKeyOmittedForModel(model, config = persistedCacheOptimizerConfig) {
1785
2057
  if (!model || !isOpenAICompatibleApi(model.api)) return false;
1786
- return config.promptCacheKey?.omit?.includes(modelKey(model)) === true;
2058
+ return "promptCacheKey" in config && config.promptCacheKey?.omit?.includes(modelKey(model)) === true;
1787
2059
  }
1788
2060
  function setPersistedCacheOptimizerConfig(config) {
1789
2061
  persistedCacheOptimizerConfig = normalizePersistedCacheOptimizerConfig(config);
@@ -2512,6 +2784,13 @@ function snapshotProviderRequestModel(model) {
2512
2784
  maxTokens: model.maxTokens ?? 0
2513
2785
  };
2514
2786
  }
2787
+ const MAX_PROVIDER_REQUEST_STATES = 32;
2788
+ function pruneProviderRequestStates(states, max = MAX_PROVIDER_REQUEST_STATES) {
2789
+ while (states.length > max) {
2790
+ const completed = states.findIndex((state) => state.responseReceived);
2791
+ states.splice(completed >= 0 ? completed : 0, 1);
2792
+ }
2793
+ }
2515
2794
  function keyForModelExt(model) {
2516
2795
  return `${model.provider}/${model.id}`;
2517
2796
  }
@@ -3998,6 +4277,7 @@ const CACHE_PROVIDER_ADAPTERS = [
3998
4277
  }
3999
4278
  ];
4000
4279
  function selectAdapterForModel(model) {
4280
+ if (isNativeVirtualModel(model)) return void 0;
4001
4281
  return CACHE_PROVIDER_ADAPTERS.find((adapter) => adapter.matchesModel(model));
4002
4282
  }
4003
4283
  function selectAdapterForAssistantMessage(message, model) {
@@ -4959,6 +5239,7 @@ function describeRouterChannelDiagnostics(model) {
4959
5239
  }
4960
5240
  function getCompatCheckNotApplicableLines(model) {
4961
5241
  const api = lower(model.api);
5242
+ if (isNativeVirtualModel(model)) return ["ℹ️ Compat check not applicable for this model.", " Native virtual model: Pi routes each request to a physical model and none has answered on this session branch yet. Send a prompt, then rerun to diagnose the physical model that answered."];
4962
5243
  if (isMistralConversationsApi(api)) return ["ℹ️ Compat check not applicable for this model.", " Native Mistral `mistral-conversations` uses provider-native transport; OpenAI-compatible proxy compat flags do not apply."];
4963
5244
  if (api === "azure-openai-responses") return ["ℹ️ Compat check not applicable for this model.", " Native Azure OpenAI Responses uses the Responses transport; OpenAI-compatible proxy compat flags do not apply."];
4964
5245
  if (api === "openai-codex-responses" || api === "openai-responses" && isOfficialOpenAIBaseUrl(model)) return ["ℹ️ Compat check not applicable for this model.", " Native Responses transports already use Pi core request handling; OpenAI-compatible proxy compat flags do not apply."];
@@ -7135,6 +7416,8 @@ const __internals_for_tests = {
7135
7416
  SKILL_COMPRESSION_MIN_COUNT,
7136
7417
  NO_PROMPT_REWRITE_ENV,
7137
7418
  isEnabledEnv,
7419
+ featureEnabled,
7420
+ writePersistedFeature,
7138
7421
  addOpenAIPromptCacheKey,
7139
7422
  clampPromptCacheKey,
7140
7423
  hasEffectivePromptCacheKey,
@@ -7152,6 +7435,8 @@ const __internals_for_tests = {
7152
7435
  normalizeAnthropicCacheControlTtlOrder,
7153
7436
  isPiBuiltInLlamaCppModel,
7154
7437
  isResponsesPromptRewriteBypassApi,
7438
+ canRewriteNativeVirtualPrompt,
7439
+ VIRTUAL_REWRITE_ENV,
7155
7440
  isMistralConversationsApi,
7156
7441
  isOpenAIFamilyModel,
7157
7442
  isOpenAIFamilyAssistantMessage,
@@ -7392,6 +7677,16 @@ const __internals_for_tests = {
7392
7677
  applyConfiguredTransportToModel,
7393
7678
  resolveRouteModel,
7394
7679
  isVirtualRoutingModel,
7680
+ PI_VIRTUAL_MODEL_API,
7681
+ isNativeVirtualModel,
7682
+ findNativeVirtualDispatches,
7683
+ resolveNativeVirtualRouteModel,
7684
+ resolveNativeVirtualRequestModel,
7685
+ getProviderPayloadModelId,
7686
+ getCompatCheckNotApplicableLines,
7687
+ describeNativeVirtualRouteNote,
7688
+ pruneProviderRequestStates,
7689
+ MAX_PROVIDER_REQUEST_STATES,
7395
7690
  installCacheHintsService,
7396
7691
  getCacheHintsService,
7397
7692
  markOptimizerOwnedCacheHintsService,
@@ -7895,6 +8190,23 @@ function pi_cache_optimizer_default(pi) {
7895
8190
  function hasExplicitLongRetentionOptIn(model) {
7896
8191
  return hasExplicitLongRetentionOptInFromConfig(readEffectiveCompatConfig(), model.provider, model.id);
7897
8192
  }
8193
+ /**
8194
+ * Request treatment that before_provider_request derives from a model's
8195
+ * identity. A native virtual request whose dispatched id matches several
8196
+ * credentialed providers is resolved only when this key agrees for all of
8197
+ * them, so no provider-specific decision is applied on a guess.
8198
+ */
8199
+ function requestPolicyKey(model) {
8200
+ const key = modelKey(model);
8201
+ return JSON.stringify([
8202
+ model.api ?? "",
8203
+ isOfficialOpenAIBaseUrl(model),
8204
+ hasExplicitLongRetentionOptIn(model),
8205
+ promptCacheRetention400Models.has(key),
8206
+ anthropicTtlOrderErrorModels.has(key),
8207
+ isPromptCacheKeyOmittedForModel(model)
8208
+ ]);
8209
+ }
7898
8210
  pi.on("session_start", async (event, ctx) => {
7899
8211
  if (runtimeOptimizerEnabled) requestLongCacheRetention();
7900
8212
  await restoreCacheStats(event.reason, ctx);
@@ -7904,7 +8216,8 @@ function pi_cache_optimizer_default(pi) {
7904
8216
  } catch {}
7905
8217
  await publishStatus(ctx);
7906
8218
  });
7907
- pi.on("tool_execution_end", async (_event, ctx) => {
8219
+ pi.on("tool_execution_end", async (event, ctx) => {
8220
+ if (isNonEmptyString(event?.parentToolCallId)) return;
7908
8221
  await refreshShardAggregate();
7909
8222
  await publishStatus(ctx);
7910
8223
  });
@@ -7938,8 +8251,9 @@ function pi_cache_optimizer_default(pi) {
7938
8251
  const routeSnapshot = resolveActiveRouteSnapshot(_ctx.model, _ctx);
7939
8252
  const model = (routeSnapshot ? findModelInRegistry(_ctx.modelRegistry, routeSnapshot.provider, routeSnapshot.modelId) ?? routeSnapshotToPiModel(routeSnapshot, _ctx.model) : void 0) ?? _ctx.model;
7940
8253
  if (model && isResponsesPromptRewriteBypassApi(model.api)) return {};
8254
+ if (isNativeVirtualModel(_ctx.model) && !canRewriteNativeVirtualPrompt(_ctx.model, _ctx)) return {};
7941
8255
  if (!runtimeOptimizerEnabled) return {};
7942
- if (isEnabledEnv(process.env[NO_PROMPT_REWRITE_ENV])) return {};
8256
+ if (!featureEnabled("promptRewrite", NO_PROMPT_REWRITE_ENV, true)) return {};
7943
8257
  const strippedPrompt = stripSessionOverviewChurn(event.systemPrompt);
7944
8258
  const compressedPrompt = compressSkillsInSystemPrompt(strippedPrompt, event.systemPromptOptions);
7945
8259
  const optimized = optimizeSystemPrompt(compressedPrompt, event.systemPromptOptions);
@@ -7978,17 +8292,23 @@ function pi_cache_optimizer_default(pi) {
7978
8292
  return {};
7979
8293
  });
7980
8294
  pi.on("before_provider_headers", (event, ctx) => {
8295
+ if (isNativeVirtualModel(ctx.model)) return;
7981
8296
  const requestModel = resolveRouteModel(ctx.model, ctx) ?? ctx.model;
7982
8297
  addEffectiveSessionAffinityHeaders(event.headers, requestModel, ctx.sessionManager.getSessionId());
7983
8298
  });
7984
8299
  pi.on("before_provider_request", (event, ctx) => {
7985
- const requestModel = resolveRouteModel(ctx.model, ctx) ?? ctx.model;
8300
+ const nativeVirtualRequest = resolveNativeVirtualRequestModel(ctx.model, event.payload, ctx, requestPolicyKey);
8301
+ const requestModel = isNativeVirtualModel(ctx.model) ? nativeVirtualRequest?.model ?? ctx.model : resolveRouteModel(ctx.model, ctx) ?? ctx.model;
7986
8302
  const snapshot = snapshotProviderRequestModel(requestModel);
7987
- if (snapshot) providerRequestStates.push({
7988
- model: snapshot,
7989
- responseReceived: false,
7990
- correlationAmbiguous: false
7991
- });
8303
+ if (snapshot) {
8304
+ providerRequestStates.push({
8305
+ model: snapshot,
8306
+ responseReceived: false,
8307
+ correlationAmbiguous: false,
8308
+ identityAmbiguous: isNativeVirtualModel(ctx.model) && (!nativeVirtualRequest || nativeVirtualRequest.identityAmbiguous)
8309
+ });
8310
+ pruneProviderRequestStates(providerRequestStates);
8311
+ }
7992
8312
  let requestPayload = event.payload;
7993
8313
  let toolOrderChanged = false;
7994
8314
  if (isToolOrderEnabled() && isToolOrderingEligibleModel(requestModel)) {
@@ -8021,7 +8341,7 @@ function pi_cache_optimizer_default(pi) {
8021
8341
  else for (const state of pendingStates) state.correlationAmbiguous = true;
8022
8342
  }
8023
8343
  if (responseState) responseState.responseReceived = true;
8024
- const model = responseState?.model ?? (pendingStates.length === 0 ? resolveRouteModel(ctx.model, ctx) ?? ctx.model : void 0);
8344
+ const model = responseState ? responseState.identityAmbiguous ? void 0 : responseState.model : pendingStates.length === 0 && !isNativeVirtualModel(ctx.model) ? resolveRouteModel(ctx.model, ctx) ?? ctx.model : void 0;
8025
8345
  if (!runtimeOptimizerEnabled || !model) return;
8026
8346
  if (isReasoningProtocolRejectionSignalApplicable(model) && event.status === 400 && hasReasoningProtocolRejectionSignal(event.headers)) await notifyReasoningProtocolObservation(model, ctx, reasoningProtocolRejectedModels, warnedReasoningProtocolRejectedModels);
8027
8347
  if (event.status === 400 && isPromptCacheKeyUnsupportedApplicable(model) && hasPromptCacheKeyUnsupportedSignal(event.headers)) {
@@ -8073,9 +8393,10 @@ function pi_cache_optimizer_default(pi) {
8073
8393
  model: void 0,
8074
8394
  ambiguous: false
8075
8395
  };
8396
+ const ambiguous = (state.correlationAmbiguous || state.identityAmbiguous === true) && explicitIndex < 0;
8076
8397
  return {
8077
- model: state.correlationAmbiguous && explicitIndex < 0 ? void 0 : state.model,
8078
- ambiguous: state.correlationAmbiguous && explicitIndex < 0
8398
+ model: ambiguous ? void 0 : state.model,
8399
+ ambiguous
8079
8400
  };
8080
8401
  })() : {
8081
8402
  model: void 0,
@@ -8127,12 +8448,15 @@ function pi_cache_optimizer_default(pi) {
8127
8448
  }
8128
8449
  }
8129
8450
  }
8130
- const adapter = selectAdapterForAssistantMessage(event.message, ctx.model);
8451
+ const nativeVirtualDispatch = isNativeVirtualModel(ctx.model) ? nativeVirtualDispatchFromMessage(event.message) : void 0;
8452
+ const nativeVirtualMessageModel = nativeVirtualDispatch ? nativeVirtualDispatchToModel(nativeVirtualDispatch, ctx) : void 0;
8453
+ const adapter = selectAdapterForAssistantMessage(event.message, nativeVirtualMessageModel ?? ctx.model);
8131
8454
  if (!adapter) return;
8132
8455
  if (msgRecord?.stopReason === "error" || msgRecord?.stopReason === "aborted") return;
8133
8456
  const usage = adapter.normalizeUsage(event.message);
8134
8457
  let statsModel = modelFromAssistantMessage(event.message, ctx.model) ?? ctx.model;
8135
8458
  statsModel = consolidateDirectProviderStatsModel(statsModel, ctx.model, ctx);
8459
+ if (nativeVirtualMessageModel) statsModel = nativeVirtualMessageModel;
8136
8460
  let routedModelChanged = false;
8137
8461
  if (isVirtualRoutingModel(ctx.model, ctx) && statsModel && !isVirtualRoutingModel(statsModel, ctx)) {
8138
8462
  const nextRoutedModel = {
@@ -8217,7 +8541,11 @@ function pi_cache_optimizer_default(pi) {
8217
8541
  const adapter = selectAdapterForModel(model);
8218
8542
  const sk = model ? sessionModelKey(model) : void 0;
8219
8543
  const lowHitLines = buildLowHitDiagnosis(model, adapter, model ? cacheStatsTotalsByModel[modelKey(model)] : void 0, sk ? getRecentSamples(sk) : []);
8220
- const fullDiagnosis = lowHitLines.length > 0 ? diagnosis + "\n" + lowHitLines.join("\n") : diagnosis;
8544
+ const fullDiagnosis = [
8545
+ describeNativeVirtualRouteNote(selectedModel, model),
8546
+ diagnosis,
8547
+ ...lowHitLines
8548
+ ].filter((line) => line !== void 0).join("\n");
8221
8549
  cmdCtx.ui.notify(fullDiagnosis, "info");
8222
8550
  } else if (subcommand === "stats") {
8223
8551
  const aggregate = await refreshShardAggregate();
@@ -8232,13 +8560,48 @@ function pi_cache_optimizer_default(pi) {
8232
8560
  } else if (subcommand === "config") {
8233
8561
  const configKey = commandParts[1];
8234
8562
  const requestedMode = commandParts[2];
8563
+ const feature = configKey ? FEATURE_COMMAND_MAP[configKey] : void 0;
8564
+ if (feature && (requestedMode === "on" || requestedMode === "off")) {
8565
+ try {
8566
+ await writePersistedFeature(feature, requestedMode === "on");
8567
+ lastStatusText = void 0;
8568
+ await publishStatus(cmdCtx, model);
8569
+ cmdCtx.ui.notify(`✅ ${configKey} set to ${requestedMode}. Persistent config overrides its environment variable.`, "info");
8570
+ } catch (error) {
8571
+ cmdCtx.ui.notify(`❌ Could not update ${configKey}: ${error instanceof Error ? error.message : String(error)}`, "error");
8572
+ }
8573
+ return;
8574
+ }
8575
+ if (configKey === "reset") {
8576
+ try {
8577
+ await writePersistedCacheOptimizerConfig({
8578
+ version: 2,
8579
+ footerMode: persistedFooterStatsMode,
8580
+ promptCacheKey: persistedCacheOptimizerConfig.promptCacheKey
8581
+ });
8582
+ setPersistedCacheOptimizerConfig(readPersistedCacheOptimizerConfig());
8583
+ cmdCtx.ui.notify("✅ Feature configuration reset. Environment variables now apply again.", "info");
8584
+ } catch (error) {
8585
+ cmdCtx.ui.notify(`❌ Could not reset feature configuration: ${error instanceof Error ? error.message : String(error)}`, "error");
8586
+ }
8587
+ return;
8588
+ }
8589
+ if (!configKey) {
8590
+ cmdCtx.ui.notify(formatPersistentFeatureConfig() + `\n• Footer mode: ${resolveFooterStatsMode(persistedFooterStatsMode).mode}
8591
+
8592
+ Usage: /cache-optimizer config <feature> on|off | footer-mode total|session|process | reset`, "info");
8593
+ return;
8594
+ }
8235
8595
  if (configKey !== "footer-mode" || !requestedMode || ![
8236
8596
  "session",
8237
8597
  "total",
8238
8598
  "process"
8239
8599
  ].includes(requestedMode)) {
8240
8600
  const resolved = resolveFooterStatsMode(persistedFooterStatsMode);
8241
- cmdCtx.ui.notify(`Usage: /cache-optimizer config footer-mode total|session|process\nCurrent footer mode: ${resolved.mode} (${resolved.source})`, "info");
8601
+ cmdCtx.ui.notify(`Usage: /cache-optimizer config footer-mode total|session|process
8602
+ /cache-optimizer config prompt-rewrite|virtual-rewrite|skill-compression|openai-cache-key|tool-order on|off
8603
+ /cache-optimizer config reset
8604
+ Current footer mode: ${resolved.mode} (${resolved.source})`, "info");
8242
8605
  return;
8243
8606
  }
8244
8607
  const nextMode = requestedMode;
@@ -8258,8 +8621,10 @@ function pi_cache_optimizer_default(pi) {
8258
8621
  return;
8259
8622
  }
8260
8623
  const compatResult = buildCompatDiagnosis(model);
8261
- if (compatResult) cmdCtx.ui.notify(compatResult, "warning");
8262
- else cmdCtx.ui.notify(isAdaptiveThinkingCompatApplicable(model) || isDeepSeekCompatCheckApplicable(model) || isCompatCheckApplicable(model) ? "✅ Compat fully configured." : getCompatCheckNotApplicableLines(model).join("\n"), "info");
8624
+ const compatRouteNote = describeNativeVirtualRouteNote(selectedModel, model);
8625
+ const withRouteNote = (text) => compatRouteNote ? `${compatRouteNote}\n${text}` : text;
8626
+ if (compatResult) cmdCtx.ui.notify(withRouteNote(compatResult), "warning");
8627
+ else cmdCtx.ui.notify(withRouteNote(isAdaptiveThinkingCompatApplicable(model) || isDeepSeekCompatCheckApplicable(model) || isCompatCheckApplicable(model) ? "✅ Compat fully configured." : getCompatCheckNotApplicableLines(model).join("\n")), "info");
8263
8628
  } else if (subcommand === "rollback") {
8264
8629
  if (!model) {
8265
8630
  cmdCtx.ui.notify("No active model selected. Select a model first with /model or pi --model.", "warning");
@@ -8677,7 +9042,9 @@ Run /cache-optimizer fix prompt-cache-key in Pi's interactive UI for ${modelKey(
8677
9042
  diagnosis.push(" stats all — Show detailed totals for every model across all local sessions");
8678
9043
  diagnosis.push(" stats contributors — Show per-session contributors for the active model");
8679
9044
  diagnosis.push(" compat — Show compat suggestion with edit location");
9045
+ diagnosis.push(" config prompt-rewrite|virtual-rewrite|skill-compression|openai-cache-key|tool-order on|off — Persist feature settings");
8680
9046
  diagnosis.push(" config footer-mode total|session|process — Persist the footer stats mode");
9047
+ diagnosis.push(" config reset — Remove persistent feature overrides");
8681
9048
  diagnosis.push(" fix — Auto-fix compat issues (writes models.json or extension config, requires UI)");
8682
9049
  diagnosis.push(" fix prompt-cache-key — Explicitly omit prompt_cache_key for the active model");
8683
9050
  diagnosis.push(" rollback — Undo the latest confirmed fix (requires UI confirmation)");
@@ -8713,4 +9080,4 @@ Run /cache-optimizer fix prompt-cache-key in Pi's interactive UI for ${modelKey(
8713
9080
  exports.__internals_for_tests = __internals_for_tests;
8714
9081
  exports.default = pi_cache_optimizer_default;
8715
9082
 
8716
- //# sourceMappingURL=pi-cache-optimizer-VJG1vKKU.cjs.map
9083
+ //# sourceMappingURL=pi-cache-optimizer-DSED41mZ.cjs.map