@agimon-ai/po-cache 0.0.0-alpha.2 → 0.0.0-alpha.4
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.
- package/dist/env.mjs +1 -2
- package/dist/extensions/mcp.cjs.map +1 -1
- package/dist/extensions/mcp.d.mts +1 -1
- package/dist/extensions/mcp.mjs.map +1 -1
- package/dist/extensions/server.cjs +117 -97
- package/dist/extensions/server.cjs.map +1 -1
- package/dist/extensions/server.d.mts +1 -1
- package/dist/extensions/server.mjs +119 -99
- package/dist/extensions/server.mjs.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -2
- package/dist/{promptCacheTelemetry-BU1fIhb8.cjs → promptCacheTelemetry-DeN4LdSo.cjs} +6 -6
- package/dist/promptCacheTelemetry-DeN4LdSo.cjs.map +1 -0
- package/dist/{promptCacheTelemetry-CguL1ZqT.mjs → promptCacheTelemetry-LM1cAPk8.mjs} +5 -5
- package/dist/promptCacheTelemetry-LM1cAPk8.mjs.map +1 -0
- package/package.json +11 -11
- package/dist/promptCacheTelemetry-BU1fIhb8.cjs.map +0 -1
- package/dist/promptCacheTelemetry-CguL1ZqT.mjs.map +0 -1
package/dist/env.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { PI_CACHE_RETENTION_ENV, PI_CACHE_RETENTION_LONG, PO_PROMPT_CACHE_CHILD_PROJECTION_ENV, PO_PROMPT_CACHE_PARENT_NAMESPACE_ENV, PO_PROMPT_CACHE_ROOT_SESSION_ENV };
|
|
1
|
+
export { t as PI_CACHE_RETENTION_ENV, n as PI_CACHE_RETENTION_LONG, r as PO_PROMPT_CACHE_CHILD_PROJECTION_ENV, i as PO_PROMPT_CACHE_PARENT_NAMESPACE_ENV, a as PO_PROMPT_CACHE_ROOT_SESSION_ENV } from "./environment-vyw-n84h.mjs";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.cjs","names":["defineMcpSkill","readPackageResource","defineMcpPlugin","skillPoUseCache"],"sources":["../../src/extensions/workspaces/sessions/(backend)/skill/po-use-cache.mcp.ts","../../generated/mcp.ts"],"sourcesContent":["import { defineMcpSkill } from '@agimon-ai/po-core/mcpFacet';\nimport { readPackageResource } from '@agimon-ai/po-core/serverFacet';\n\nexport default defineMcpSkill({\n name: 'po-use-cache',\n description: 'Inspect Po provider prompt cache policy, routing identity, and provider-observed usage.',\n read: () => readPackageResource(import.meta.url, 'src/prompts/po-use-cache/SKILL.md'),\n});\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineMcpPlugin, type
|
|
1
|
+
{"version":3,"file":"mcp.cjs","names":["defineMcpSkill","readPackageResource","defineMcpPlugin","skillPoUseCache"],"sources":["../../src/extensions/workspaces/sessions/(backend)/skill/po-use-cache.mcp.ts","../../generated/mcp.ts"],"sourcesContent":["import { defineMcpSkill } from '@agimon-ai/po-core/mcpFacet';\nimport { readPackageResource } from '@agimon-ai/po-core/serverFacet';\n\nexport default defineMcpSkill({\n name: 'po-use-cache',\n description: 'Inspect Po provider prompt cache policy, routing identity, and provider-observed usage.',\n read: () => readPackageResource(import.meta.url, 'src/prompts/po-use-cache/SKILL.md'),\n});\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineMcpPlugin, type PoMcpSessionPlugin } from '@agimon-ai/po-core/mcpFacet';\n\nimport skillPoUseCache from '../src/extensions/workspaces/sessions/(backend)/skill/po-use-cache.mcp';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\n\nexport const mcp = defineMcpPlugin({\n name: '@agimon-ai/po-cache',\n session: (context) => ({\n get skills(): PoMcpSessionPlugin['skills'] { return [at(skillPoUseCache, context)]; },\n }) satisfies PoMcpSessionPlugin,\n});\n\nexport default mcp;\n"],"mappings":";;;;;;;AAGA,IAAA,4BAAA,GAAeA,4BAAAA,eAAAA,CAAe;CAC5B,MAAM;CACN,aAAa;CACb,aAAA,GAAYC,+BAAAA,oBAAAA,CAAAA,QAAAA,KAAAA,CAAAA,CAAAA,cAAAA,UAAAA,CAAAA,CAAAA,MAAqC,mCAAmC;AACtF,CAAC;;;ACDD,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AAEpE,MAAa,OAAA,GAAMC,4BAAAA,gBAAAA,CAAgB;CACjC,MAAM;CACN,UAAU,aAAa,EACrB,IAAI,SAAuC;EAAE,OAAO,CAAC,GAAGC,0BAAiB,OAAO,CAAC;CAAG,EACtF;AACF,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region generated/mcp.d.ts
|
|
2
|
-
export declare const mcp: import("@agimon-ai/po-core/mcpFacet").
|
|
2
|
+
export declare const mcp: import("@agimon-ai/po-core/mcpFacet").PoMcpPluginDefinition;
|
|
3
3
|
//#endregion
|
|
4
4
|
export { mcp as default };
|
|
5
5
|
//# sourceMappingURL=mcp.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.mjs","names":["skillPoUseCache"],"sources":["../../src/extensions/workspaces/sessions/(backend)/skill/po-use-cache.mcp.ts","../../generated/mcp.ts"],"sourcesContent":["import { defineMcpSkill } from '@agimon-ai/po-core/mcpFacet';\nimport { readPackageResource } from '@agimon-ai/po-core/serverFacet';\n\nexport default defineMcpSkill({\n name: 'po-use-cache',\n description: 'Inspect Po provider prompt cache policy, routing identity, and provider-observed usage.',\n read: () => readPackageResource(import.meta.url, 'src/prompts/po-use-cache/SKILL.md'),\n});\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineMcpPlugin, type
|
|
1
|
+
{"version":3,"file":"mcp.mjs","names":["skillPoUseCache"],"sources":["../../src/extensions/workspaces/sessions/(backend)/skill/po-use-cache.mcp.ts","../../generated/mcp.ts"],"sourcesContent":["import { defineMcpSkill } from '@agimon-ai/po-core/mcpFacet';\nimport { readPackageResource } from '@agimon-ai/po-core/serverFacet';\n\nexport default defineMcpSkill({\n name: 'po-use-cache',\n description: 'Inspect Po provider prompt cache policy, routing identity, and provider-observed usage.',\n read: () => readPackageResource(import.meta.url, 'src/prompts/po-use-cache/SKILL.md'),\n});\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineMcpPlugin, type PoMcpSessionPlugin } from '@agimon-ai/po-core/mcpFacet';\n\nimport skillPoUseCache from '../src/extensions/workspaces/sessions/(backend)/skill/po-use-cache.mcp';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\n\nexport const mcp = defineMcpPlugin({\n name: '@agimon-ai/po-cache',\n session: (context) => ({\n get skills(): PoMcpSessionPlugin['skills'] { return [at(skillPoUseCache, context)]; },\n }) satisfies PoMcpSessionPlugin,\n});\n\nexport default mcp;\n"],"mappings":";;;AAGA,IAAA,2BAAe,eAAe;CAC5B,MAAM;CACN,aAAa;CACb,YAAY,oBAAoB,YAAY,KAAK,mCAAmC;AACtF,CAAC;;;ACDD,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AAEpE,MAAa,MAAM,gBAAgB;CACjC,MAAM;CACN,UAAU,aAAa,EACrB,IAAI,SAAuC;EAAE,OAAO,CAAC,GAAGA,0BAAiB,OAAO,CAAC;CAAG,EACtF;AACF,CAAC"}
|
|
@@ -3,17 +3,15 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_environment = require("../environment-CRhmV8ze.cjs");
|
|
6
|
-
const require_promptCacheTelemetry = require("../promptCacheTelemetry-
|
|
6
|
+
const require_promptCacheTelemetry = require("../promptCacheTelemetry-DeN4LdSo.cjs");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
let _agimon_ai_po_core_serverFacet = require("@agimon-ai/po-core/serverFacet");
|
|
9
9
|
let _agimon_ai_po_core_extensionFile = require("@agimon-ai/po-core/extensionFile");
|
|
10
|
+
let _agimon_ai_po_core_platform = require("@agimon-ai/po-core/platform");
|
|
10
11
|
let _agimon_ai_po_config_harnessStore = require("@agimon-ai/po-config/harnessStore");
|
|
11
12
|
let _agimon_ai_po_minor_mode = require("@agimon-ai/po-minor-mode");
|
|
12
13
|
let node_path = require("node:path");
|
|
13
14
|
let _earendil_works_pi_coding_agent = require("@earendil-works/pi-coding-agent");
|
|
14
|
-
let node_fs = require("node:fs");
|
|
15
|
-
let node_fs_promises = require("node:fs/promises");
|
|
16
|
-
let node_os = require("node:os");
|
|
17
15
|
//#region src/services/environment/index.ts
|
|
18
16
|
const environmentLeases = /* @__PURE__ */ new WeakMap();
|
|
19
17
|
/** Same-value session leases restore only after the final owner leaves. External writes win. */
|
|
@@ -181,7 +179,7 @@ function createCacheRuntime(dependencies, environment) {
|
|
|
181
179
|
return parentNamespace;
|
|
182
180
|
};
|
|
183
181
|
const plugin = (cordis) => {
|
|
184
|
-
cordis.inject([_agimon_ai_po_minor_mode.
|
|
182
|
+
cordis.inject([_agimon_ai_po_minor_mode.PO_MINOR_MODE_CATALOG_SERVICE], (context) => {
|
|
185
183
|
if (isProjectedChild) return void 0;
|
|
186
184
|
const catalog = (0, _agimon_ai_po_minor_mode.readMinorModeCatalog)(context);
|
|
187
185
|
if (!catalog) return void 0;
|
|
@@ -216,8 +214,19 @@ function createCacheRuntime(dependencies, environment) {
|
|
|
216
214
|
};
|
|
217
215
|
}
|
|
218
216
|
//#endregion
|
|
217
|
+
//#region src/services/agentDirectory/index.ts
|
|
218
|
+
/** Pi's agent directory, where the optimizer keeps its state; the edge build swaps in `index.edge.ts`. */
|
|
219
|
+
function defaultAgentDirectory() {
|
|
220
|
+
return (0, _earendil_works_pi_coding_agent.getAgentDir)();
|
|
221
|
+
}
|
|
222
|
+
//#endregion
|
|
219
223
|
//#region src/services/optimizerSupport/index.ts
|
|
220
|
-
|
|
224
|
+
/**
|
|
225
|
+
* Optimizer state under `STATE_DIR`, read and written through the injected file system. Synchronous
|
|
226
|
+
* readers (`getCompat`, `footerStatsMode`) use the files as of the last `refreshFileConfig()`.
|
|
227
|
+
*/
|
|
228
|
+
function createOptimizerSupport(STATE_DIR, environment, fs) {
|
|
229
|
+
const io = _agimon_ai_po_core_platform.BACKGROUND_CONTEXT;
|
|
221
230
|
const MODELS_JSON_PATH = (0, node_path.join)(STATE_DIR, "models.json");
|
|
222
231
|
function isVirtualRoutingModel(model) {
|
|
223
232
|
return !!model && (isNativeVirtualModel(model) || model.provider.toLowerCase() === "router");
|
|
@@ -496,21 +505,20 @@ function createOptimizerSupport(STATE_DIR, environment) {
|
|
|
496
505
|
}
|
|
497
506
|
return true;
|
|
498
507
|
}
|
|
508
|
+
/** Keyed by the file text, so an unchanged models.json is not parsed again. */
|
|
499
509
|
let modelsConfigCache;
|
|
500
|
-
function
|
|
510
|
+
async function refreshModelsConfig() {
|
|
511
|
+
let text;
|
|
501
512
|
try {
|
|
502
|
-
|
|
503
|
-
return `${info.dev}:${info.ino}:${info.size}:${info.mtimeMs}:${info.ctimeMs}`;
|
|
513
|
+
text = await (0, _agimon_ai_po_core_platform.readTextIfExists)(fs, MODELS_JSON_PATH, io);
|
|
504
514
|
} catch {
|
|
505
|
-
|
|
515
|
+
text = void 0;
|
|
506
516
|
}
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
const signature = getModelsConfigSignature();
|
|
510
|
-
if (modelsConfigCache?.signature === signature) return modelsConfigCache.value;
|
|
517
|
+
const signature = text ?? "missing";
|
|
518
|
+
if (modelsConfigCache?.signature === signature) return;
|
|
511
519
|
let value;
|
|
512
|
-
if (
|
|
513
|
-
const parsed = parseJsonc(
|
|
520
|
+
if (text !== void 0) try {
|
|
521
|
+
const parsed = parseJsonc(text);
|
|
514
522
|
value = isValidModelsConfigForEffectiveCompat(parsed) ? parsed : void 0;
|
|
515
523
|
} catch {
|
|
516
524
|
value = void 0;
|
|
@@ -519,17 +527,24 @@ function createOptimizerSupport(STATE_DIR, environment) {
|
|
|
519
527
|
signature,
|
|
520
528
|
value
|
|
521
529
|
};
|
|
522
|
-
|
|
530
|
+
}
|
|
531
|
+
/** The models.json compat config as of the last refresh. */
|
|
532
|
+
function effectiveCompatConfig() {
|
|
533
|
+
return modelsConfigCache?.value;
|
|
534
|
+
}
|
|
535
|
+
async function readEffectiveCompatConfig() {
|
|
536
|
+
await refreshModelsConfig();
|
|
537
|
+
return effectiveCompatConfig();
|
|
523
538
|
}
|
|
524
539
|
function getCompat(model) {
|
|
525
540
|
if (!model) return {};
|
|
526
|
-
return resolveEffectiveCompatFromConfig(model,
|
|
541
|
+
return resolveEffectiveCompatFromConfig(model, effectiveCompatConfig());
|
|
527
542
|
}
|
|
528
543
|
function joinDisplayPath(base, child, platform = process.platform) {
|
|
529
544
|
const sep = platform.startsWith("win") ? "\\" : "/";
|
|
530
545
|
return `${base.replace(/[\\/]+$/, "")}${sep}${child}`;
|
|
531
546
|
}
|
|
532
|
-
function getAgentDirDisplayPath(platform = process.platform, agentDir = STATE_DIR, homeDir =
|
|
547
|
+
function getAgentDirDisplayPath(platform = process.platform, agentDir = STATE_DIR, homeDir = _agimon_ai_po_core_platform.nodeHost.homeDirectory()) {
|
|
533
548
|
const sep = platform.startsWith("win") ? "\\" : "/";
|
|
534
549
|
const normalizedAgentDir = agentDir.replace(/[\\/]+/g, sep);
|
|
535
550
|
const normalizedHomeDir = homeDir.replace(/[\\/]+/g, sep).replace(/[\\/]+$/, "");
|
|
@@ -541,7 +556,7 @@ function createOptimizerSupport(STATE_DIR, environment) {
|
|
|
541
556
|
}
|
|
542
557
|
return normalizedAgentDir;
|
|
543
558
|
}
|
|
544
|
-
function getModelsJsonDisplayPath(platform = process.platform, agentDir = STATE_DIR, homeDir =
|
|
559
|
+
function getModelsJsonDisplayPath(platform = process.platform, agentDir = STATE_DIR, homeDir = _agimon_ai_po_core_platform.nodeHost.homeDirectory()) {
|
|
545
560
|
return joinDisplayPath(getAgentDirDisplayPath(platform, agentDir, homeDir), "models.json", platform);
|
|
546
561
|
}
|
|
547
562
|
function parseFooterStatsMode(value) {
|
|
@@ -605,11 +620,13 @@ function createOptimizerSupport(STATE_DIR, environment) {
|
|
|
605
620
|
...features ? { features } : {}
|
|
606
621
|
};
|
|
607
622
|
}
|
|
608
|
-
function readPersistedCacheOptimizerConfig(configPath = CONFIG_FILE_PATH) {
|
|
623
|
+
async function readPersistedCacheOptimizerConfig(configPath = CONFIG_FILE_PATH) {
|
|
609
624
|
try {
|
|
610
|
-
|
|
625
|
+
const text = await (0, _agimon_ai_po_core_platform.readTextIfExists)(fs, configPath, io);
|
|
626
|
+
if (text === void 0) return { version: 2 };
|
|
627
|
+
return normalizePersistedCacheOptimizerConfig(parsePersistedCacheOptimizerConfig(JSON.parse(text)));
|
|
611
628
|
} catch (error) {
|
|
612
|
-
|
|
629
|
+
console.warn(`${LOG_PREFIX}: failed to read optimizer config; using defaults`, error);
|
|
613
630
|
return { version: 2 };
|
|
614
631
|
}
|
|
615
632
|
}
|
|
@@ -630,7 +647,17 @@ function createOptimizerSupport(STATE_DIR, environment) {
|
|
|
630
647
|
function footerStatsMode(env = environment, configuredMode = persistedFooterStatsMode) {
|
|
631
648
|
return resolveFooterStatsMode(configuredMode, env).mode;
|
|
632
649
|
}
|
|
633
|
-
|
|
650
|
+
/** Read once, on the first refresh, like the original read at construction. */
|
|
651
|
+
let persistedConfigLoaded = false;
|
|
652
|
+
let persistedFooterStatsMode;
|
|
653
|
+
/** Loads the persisted optimizer config once and rereads models.json; call before the synchronous readers. */
|
|
654
|
+
async function refreshFileConfig() {
|
|
655
|
+
if (!persistedConfigLoaded) {
|
|
656
|
+
persistedConfigLoaded = true;
|
|
657
|
+
persistedFooterStatsMode = (await readPersistedCacheOptimizerConfig()).footerMode;
|
|
658
|
+
}
|
|
659
|
+
await refreshModelsConfig();
|
|
660
|
+
}
|
|
634
661
|
function isAssistantMessage(message) {
|
|
635
662
|
return asRecord(message)?.role === "assistant";
|
|
636
663
|
}
|
|
@@ -1258,7 +1285,7 @@ function createOptimizerSupport(STATE_DIR, environment) {
|
|
|
1258
1285
|
baseUrl: "",
|
|
1259
1286
|
[ROUTED_FALLBACK_MODEL_SYMBOL]: true
|
|
1260
1287
|
};
|
|
1261
|
-
const provider = asRecord(asRecord(asRecord(
|
|
1288
|
+
const provider = asRecord(asRecord(asRecord(effectiveCompatConfig())?.providers)?.[model.provider]);
|
|
1262
1289
|
const customModel = findLastExactModelDefinition(Array.isArray(provider?.models) ? provider.models : void 0, model.id);
|
|
1263
1290
|
const configuredApi = customModel?.api ?? provider?.api;
|
|
1264
1291
|
const configuredBaseUrl = customModel?.baseUrl ?? provider?.baseUrl;
|
|
@@ -2783,14 +2810,6 @@ function createOptimizerSupport(STATE_DIR, environment) {
|
|
|
2783
2810
|
stats: best.stats
|
|
2784
2811
|
} : void 0;
|
|
2785
2812
|
}
|
|
2786
|
-
function createSerializedAsyncRunner() {
|
|
2787
|
-
let tail = Promise.resolve();
|
|
2788
|
-
return (operation) => {
|
|
2789
|
-
const result = tail.then(operation);
|
|
2790
|
-
tail = result.catch(() => void 0);
|
|
2791
|
-
return result;
|
|
2792
|
-
};
|
|
2793
|
-
}
|
|
2794
2813
|
function modelEpochPath(modelKeyValue) {
|
|
2795
2814
|
return (0, node_path.join)(SHARD_MODEL_EPOCH_DIR, `${(0, node_crypto.createHash)("sha256").update(modelKeyValue).digest("hex")}.json`);
|
|
2796
2815
|
}
|
|
@@ -2803,7 +2822,7 @@ function createOptimizerSupport(STATE_DIR, environment) {
|
|
|
2803
2822
|
}
|
|
2804
2823
|
async function readEpochFile(path, fallback) {
|
|
2805
2824
|
try {
|
|
2806
|
-
return parseEpochRecord(JSON.parse(
|
|
2825
|
+
return parseEpochRecord(JSON.parse((0, _agimon_ai_po_core_platform.getOrThrow)(await fs.readTextFile(path, io)))) ?? fallback;
|
|
2807
2826
|
} catch {
|
|
2808
2827
|
return fallback;
|
|
2809
2828
|
}
|
|
@@ -2815,14 +2834,11 @@ function createOptimizerSupport(STATE_DIR, environment) {
|
|
|
2815
2834
|
return readEpochFile(modelEpochPath(modelKeyValue), initialEpoch(`model:${modelKeyValue}`));
|
|
2816
2835
|
}
|
|
2817
2836
|
async function writeStatsEpoch(path, epoch) {
|
|
2818
|
-
await (0,
|
|
2819
|
-
const tempPath = `${path}.${process.pid}.${Date.now()}.${(0, node_crypto.randomUUID)()}.tmp`;
|
|
2820
|
-
await (0, node_fs_promises.writeFile)(tempPath, JSON.stringify({
|
|
2837
|
+
await (0, _agimon_ai_po_core_platform.writeFileAtomic)(fs, path, JSON.stringify({
|
|
2821
2838
|
version: 1,
|
|
2822
2839
|
epoch,
|
|
2823
2840
|
createdAt: Date.now()
|
|
2824
|
-
}, null, 2) + "\n",
|
|
2825
|
-
await (0, node_fs_promises.rename)(tempPath, path);
|
|
2841
|
+
}, null, 2) + "\n", io);
|
|
2826
2842
|
}
|
|
2827
2843
|
async function advanceGlobalStatsEpoch() {
|
|
2828
2844
|
const epoch = `${Date.now()}-${(0, node_crypto.randomUUID)()}`;
|
|
@@ -2878,27 +2894,34 @@ function createOptimizerSupport(STATE_DIR, environment) {
|
|
|
2878
2894
|
};
|
|
2879
2895
|
}
|
|
2880
2896
|
async function writeStatsShardV7(path, shard) {
|
|
2881
|
-
await (0,
|
|
2882
|
-
const tempPath = `${path}.${process.pid}.${Date.now()}.${(0, node_crypto.randomUUID)()}.tmp`;
|
|
2883
|
-
await (0, node_fs_promises.writeFile)(tempPath, JSON.stringify(shard, null, 2) + "\n", "utf8");
|
|
2884
|
-
await (0, node_fs_promises.rename)(tempPath, path);
|
|
2897
|
+
await (0, _agimon_ai_po_core_platform.writeFileAtomic)(fs, path, JSON.stringify(shard, null, 2) + "\n", io);
|
|
2885
2898
|
}
|
|
2886
|
-
|
|
2887
|
-
|
|
2899
|
+
/** Entries of `directory`, or undefined when it does not exist. Entries removed while listing are skipped. */
|
|
2900
|
+
async function listDirectoryEntries(directory) {
|
|
2901
|
+
const opened = await fs.openDirReader(directory, io);
|
|
2902
|
+
if (!opened.ok && opened.error.code === "not_found") return void 0;
|
|
2903
|
+
const reader = (0, _agimon_ai_po_core_platform.getOrThrow)(opened);
|
|
2888
2904
|
try {
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2905
|
+
const entries = [];
|
|
2906
|
+
for (;;) {
|
|
2907
|
+
const page = (0, _agimon_ai_po_core_platform.getOrThrow)(await reader.next(256, io));
|
|
2908
|
+
entries.push(...page.entries);
|
|
2909
|
+
if (page.done) return entries;
|
|
2910
|
+
}
|
|
2911
|
+
} finally {
|
|
2912
|
+
await reader.close(io);
|
|
2893
2913
|
}
|
|
2914
|
+
}
|
|
2915
|
+
async function readValidStatsShardsV7(directory = SHARD_FILES_DIR) {
|
|
2916
|
+
const entries = await listDirectoryEntries(directory);
|
|
2917
|
+
if (!entries) return [];
|
|
2894
2918
|
const shards = [];
|
|
2895
|
-
for (const name of
|
|
2919
|
+
for (const { name, kind } of entries) {
|
|
2896
2920
|
if (!/^[0-9a-f-]+\.json$/i.test(name)) continue;
|
|
2897
2921
|
const path = (0, node_path.join)(directory, name);
|
|
2898
2922
|
try {
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
const parsed = parsePersistedStatsShardV7(JSON.parse(await (0, node_fs_promises.readFile)(path, "utf8")));
|
|
2923
|
+
if (kind !== "file") continue;
|
|
2924
|
+
const parsed = parsePersistedStatsShardV7(JSON.parse((0, _agimon_ai_po_core_platform.getOrThrow)(await fs.readTextFile(path, io))));
|
|
2902
2925
|
const filenameInstanceId = name.slice(0, -5);
|
|
2903
2926
|
if (parsed && parsed.instanceId === filenameInstanceId) shards.push(parsed);
|
|
2904
2927
|
} catch {}
|
|
@@ -2969,73 +2992,63 @@ function createOptimizerSupport(STATE_DIR, environment) {
|
|
|
2969
2992
|
}
|
|
2970
2993
|
}
|
|
2971
2994
|
async function removeLegacyStatsFiles() {
|
|
2972
|
-
for (const path of [STATE_FILE_PATH, LEGACY_STATE_FILE_PATH])
|
|
2973
|
-
await (
|
|
2974
|
-
|
|
2975
|
-
if (getErrorCode(error) !== "ENOENT") console.warn(`${LOG_PREFIX}: failed to remove obsolete stats file ${path}`, error);
|
|
2995
|
+
for (const path of [STATE_FILE_PATH, LEGACY_STATE_FILE_PATH]) {
|
|
2996
|
+
const removed = await fs.remove(path, { force: true }, io);
|
|
2997
|
+
if (!removed.ok) console.warn(`${LOG_PREFIX}: failed to remove obsolete stats file ${path}`, removed.error);
|
|
2976
2998
|
}
|
|
2977
2999
|
}
|
|
2978
3000
|
async function cleanupStatsShardsV7(now = Date.now(), directory = SHARD_FILES_DIR) {
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
names = await (0, node_fs_promises.readdir)(directory);
|
|
2982
|
-
} catch (error) {
|
|
2983
|
-
return getErrorCode(error) === "ENOENT" ? 0 : Promise.reject(error);
|
|
2984
|
-
}
|
|
3001
|
+
const entries = await listDirectoryEntries(directory);
|
|
3002
|
+
if (!entries) return 0;
|
|
2985
3003
|
const today = currentLocalDay();
|
|
2986
3004
|
let removed = 0;
|
|
2987
|
-
for (const
|
|
3005
|
+
for (const info of entries) {
|
|
3006
|
+
const { name } = info;
|
|
2988
3007
|
const isShard = /^[0-9a-f-]+\.json$/i.test(name);
|
|
2989
3008
|
const isTemp = name.endsWith(".tmp");
|
|
2990
3009
|
if (!isShard && !isTemp) continue;
|
|
2991
3010
|
const path = (0, node_path.join)(directory, name);
|
|
2992
3011
|
try {
|
|
2993
|
-
|
|
2994
|
-
if (!info.isFile() || info.isSymbolicLink()) continue;
|
|
3012
|
+
if (info.kind !== "file") continue;
|
|
2995
3013
|
if (isTemp) {
|
|
2996
3014
|
if (now - info.mtimeMs < SHARD_TEMP_RETENTION_MS) continue;
|
|
2997
3015
|
} else {
|
|
2998
|
-
const parsed = parsePersistedStatsShardV7(JSON.parse(
|
|
3016
|
+
const parsed = parsePersistedStatsShardV7(JSON.parse((0, _agimon_ai_po_core_platform.getOrThrow)(await fs.readTextFile(path, io))));
|
|
2999
3017
|
if (parsed?.day === today) continue;
|
|
3000
3018
|
if (now - (parsed?.lifecycle.updatedAt ?? info.mtimeMs) < SHARD_RETENTION_MS) continue;
|
|
3001
3019
|
if (parsed?.lifecycle.state === "active" && isProcessAlive(parsed.process.pid)) continue;
|
|
3002
3020
|
}
|
|
3003
|
-
|
|
3021
|
+
(0, _agimon_ai_po_core_platform.getOrThrow)(await fs.remove(path, void 0, io));
|
|
3004
3022
|
removed += 1;
|
|
3005
3023
|
} catch {}
|
|
3006
3024
|
}
|
|
3007
3025
|
return removed;
|
|
3008
3026
|
}
|
|
3027
|
+
/**
|
|
3028
|
+
* Best-effort cross-process maintenance. A non-recursive `createDir` claims the cleanup lock; if two
|
|
3029
|
+
* cleanups ever overlap, each only removes expired shards, so the lock bounds work rather than guarding
|
|
3030
|
+
* correctness.
|
|
3031
|
+
*/
|
|
3009
3032
|
async function maybeCleanupStatsShardsV7(now = Date.now()) {
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
}
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
await (0, node_fs_promises.rm)(SHARD_CLEANUP_LOCK_PATH, {
|
|
3021
|
-
recursive: true,
|
|
3022
|
-
force: true
|
|
3023
|
-
});
|
|
3024
|
-
await (0, node_fs_promises.mkdir)(SHARD_CLEANUP_LOCK_PATH);
|
|
3025
|
-
} catch {
|
|
3026
|
-
return;
|
|
3027
|
-
}
|
|
3033
|
+
(0, _agimon_ai_po_core_platform.getOrThrow)(await fs.createDir(SHARD_MAINTENANCE_DIR, { recursive: true }, io));
|
|
3034
|
+
const marker = await fs.fileInfo(SHARD_CLEANUP_MARKER_PATH, io);
|
|
3035
|
+
if (marker.ok && now - marker.value.mtimeMs < SHARD_CLEANUP_INTERVAL_MS) return;
|
|
3036
|
+
if (!(await fs.createDir(SHARD_CLEANUP_LOCK_PATH, { recursive: false }, io)).ok) {
|
|
3037
|
+
const lock = await fs.fileInfo(SHARD_CLEANUP_LOCK_PATH, io);
|
|
3038
|
+
if (!lock.ok || now - lock.value.mtimeMs <= SHARD_CLEANUP_LOCK_STALE_MS) return;
|
|
3039
|
+
if (!(await fs.remove(SHARD_CLEANUP_LOCK_PATH, {
|
|
3040
|
+
recursive: true,
|
|
3041
|
+
force: true
|
|
3042
|
+
}, io)).ok || !(await fs.createDir(SHARD_CLEANUP_LOCK_PATH, { recursive: false }, io)).ok) return;
|
|
3028
3043
|
}
|
|
3029
3044
|
try {
|
|
3030
3045
|
await cleanupStatsShardsV7(now);
|
|
3031
|
-
|
|
3032
|
-
await (0, node_fs_promises.writeFile)(tempPath, `${now}\n`, "utf8");
|
|
3033
|
-
await (0, node_fs_promises.rename)(tempPath, SHARD_CLEANUP_MARKER_PATH);
|
|
3046
|
+
await (0, _agimon_ai_po_core_platform.writeFileAtomic)(fs, SHARD_CLEANUP_MARKER_PATH, `${now}\n`, io);
|
|
3034
3047
|
} finally {
|
|
3035
|
-
|
|
3048
|
+
(0, _agimon_ai_po_core_platform.getOrThrow)(await fs.remove(SHARD_CLEANUP_LOCK_PATH, {
|
|
3036
3049
|
recursive: true,
|
|
3037
3050
|
force: true
|
|
3038
|
-
});
|
|
3051
|
+
}, io));
|
|
3039
3052
|
}
|
|
3040
3053
|
}
|
|
3041
3054
|
function isExplicitPromptCacheRetentionUnsupportedApplicable(model) {
|
|
@@ -3186,7 +3199,7 @@ function createOptimizerSupport(STATE_DIR, environment) {
|
|
|
3186
3199
|
advanceModelStatsEpoch,
|
|
3187
3200
|
maybeCleanupStatsShardsV7,
|
|
3188
3201
|
removeLegacyStatsFiles,
|
|
3189
|
-
createSerializedAsyncRunner,
|
|
3202
|
+
createSerializedAsyncRunner: _agimon_ai_po_core_platform.createSerialRunner,
|
|
3190
3203
|
hasReasoningProtocolRejectionErrorMessage,
|
|
3191
3204
|
isReasoningProtocolRejectionForModel,
|
|
3192
3205
|
hasPromptCacheKeyUnsupportedErrorMessage,
|
|
@@ -3205,6 +3218,7 @@ function createOptimizerSupport(STATE_DIR, environment) {
|
|
|
3205
3218
|
parsePersistedStatsShardV7,
|
|
3206
3219
|
cleanupStatsShardsV7,
|
|
3207
3220
|
readEffectiveCompatConfig,
|
|
3221
|
+
refreshFileConfig,
|
|
3208
3222
|
getCompat,
|
|
3209
3223
|
SHARD_FILES_DIR,
|
|
3210
3224
|
LOG_PREFIX
|
|
@@ -3224,8 +3238,8 @@ function asModel(model) {
|
|
|
3224
3238
|
} : void 0;
|
|
3225
3239
|
}
|
|
3226
3240
|
/** One native session owner. Only V7 counters, never payloads or credentials, reach disk. */
|
|
3227
|
-
function createNativeOptimizer(initial, stateDir = (
|
|
3228
|
-
const support = createOptimizerSupport(stateDir, initial.environment);
|
|
3241
|
+
function createNativeOptimizer(initial, fs, stateDir = defaultAgentDirectory()) {
|
|
3242
|
+
const support = createOptimizerSupport(stateDir, initial.environment, fs);
|
|
3229
3243
|
const serialized = support.createSerializedAsyncRunner();
|
|
3230
3244
|
const instanceId = (0, node_crypto.randomUUID)();
|
|
3231
3245
|
const instanceStartedAt = Date.now();
|
|
@@ -3509,6 +3523,7 @@ function createNativeOptimizer(initial, stateDir = (0, _earendil_works_pi_coding
|
|
|
3509
3523
|
if (started || closed) return;
|
|
3510
3524
|
started = true;
|
|
3511
3525
|
releaseRetention = acquireEnvironmentValue("PI_CACHE_RETENTION", "long");
|
|
3526
|
+
await support.refreshFileConfig();
|
|
3512
3527
|
currentGlobalEpoch = await support.readGlobalStatsEpoch();
|
|
3513
3528
|
await support.removeLegacyStatsFiles();
|
|
3514
3529
|
await refresh();
|
|
@@ -3523,6 +3538,7 @@ function createNativeOptimizer(initial, stateDir = (0, _earendil_works_pi_coding
|
|
|
3523
3538
|
handle: (event, context) => serialized(async () => {
|
|
3524
3539
|
if (typeof event.parentToolCallId === "string" && event.parentToolCallId.trim()) return;
|
|
3525
3540
|
if (started && !closed) {
|
|
3541
|
+
await support.refreshFileConfig();
|
|
3526
3542
|
await refresh();
|
|
3527
3543
|
await publish(context);
|
|
3528
3544
|
}
|
|
@@ -3532,6 +3548,7 @@ function createNativeOptimizer(initial, stateDir = (0, _earendil_works_pi_coding
|
|
|
3532
3548
|
event: "agent_settled",
|
|
3533
3549
|
handle: (_event, context) => serialized(async () => {
|
|
3534
3550
|
if (started && !closed) {
|
|
3551
|
+
await support.refreshFileConfig();
|
|
3535
3552
|
await refresh();
|
|
3536
3553
|
await publish(context);
|
|
3537
3554
|
}
|
|
@@ -3541,6 +3558,7 @@ function createNativeOptimizer(initial, stateDir = (0, _earendil_works_pi_coding
|
|
|
3541
3558
|
event: "model_select",
|
|
3542
3559
|
handle: (_event, context) => serialized(async () => {
|
|
3543
3560
|
if (!started || closed) return;
|
|
3561
|
+
await support.refreshFileConfig();
|
|
3544
3562
|
const model = selectedModel(context);
|
|
3545
3563
|
support.notifyCacheCompatIfNeeded(model, (text) => notify(context, text), warnedModels);
|
|
3546
3564
|
await refresh();
|
|
@@ -3550,7 +3568,9 @@ function createNativeOptimizer(initial, stateDir = (0, _earendil_works_pi_coding
|
|
|
3550
3568
|
{
|
|
3551
3569
|
event: "message_end",
|
|
3552
3570
|
handle: (event, context) => serialized(async () => {
|
|
3553
|
-
if (started
|
|
3571
|
+
if (!started || closed) return;
|
|
3572
|
+
await support.refreshFileConfig();
|
|
3573
|
+
await observe(event.message, context);
|
|
3554
3574
|
})
|
|
3555
3575
|
},
|
|
3556
3576
|
{
|
|
@@ -3570,14 +3590,14 @@ function createNativeOptimizer(initial, stateDir = (0, _earendil_works_pi_coding
|
|
|
3570
3590
|
}
|
|
3571
3591
|
//#endregion
|
|
3572
3592
|
//#region src/extensions/workspaces/sessions/(backend)/root.server.ts
|
|
3573
|
-
var root_server_default = (0, _agimon_ai_po_core_extensionFile.defineRoot)(({ agent }) => {
|
|
3593
|
+
var root_server_default = (0, _agimon_ai_po_core_extensionFile.defineRoot)(({ agent, context: root }) => {
|
|
3574
3594
|
if (!agent) throw new Error("Cache statistics require the native session host.");
|
|
3575
3595
|
const telemetry = new require_promptCacheTelemetry.PromptCacheTelemetry();
|
|
3576
3596
|
const runtime = createCacheRuntime({
|
|
3577
3597
|
telemetry,
|
|
3578
3598
|
now: Date.now
|
|
3579
3599
|
}, agent.context.environment);
|
|
3580
|
-
const optimizer = createNativeOptimizer(agent.context);
|
|
3600
|
+
const optimizer = createNativeOptimizer(agent.context, (0, _agimon_ai_po_core_platform.requirePoFs)(root));
|
|
3581
3601
|
return {
|
|
3582
3602
|
value: { hooks: optimizer.hooks.map((hook) => {
|
|
3583
3603
|
if (hook.event === "session_start") return {
|