@agimon-ai/doompi-cache 0.0.1-alpha.4 → 0.0.1-alpha.42

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 (174) hide show
  1. package/README.md +35 -12
  2. package/dist/api-contracts.cjs +7 -0
  3. package/dist/api-contracts.d.cts +2 -0
  4. package/dist/api-contracts.d.mts +2 -0
  5. package/dist/api-contracts.mjs +2 -0
  6. package/dist/env.cjs +7 -1
  7. package/dist/env.d.cts +1 -1
  8. package/dist/env.d.mts +1 -1
  9. package/dist/env.mjs +2 -1
  10. package/dist/extensions/pi.cjs +458 -1
  11. package/dist/extensions/pi.cjs.map +1 -1
  12. package/dist/extensions/pi.d.cts +3 -4
  13. package/dist/extensions/pi.d.cts.map +1 -1
  14. package/dist/extensions/pi.d.mts +3 -4
  15. package/dist/extensions/pi.d.mts.map +1 -1
  16. package/dist/extensions/pi.mjs +453 -1
  17. package/dist/extensions/pi.mjs.map +1 -1
  18. package/dist/extensions/server.cjs +24 -0
  19. package/dist/extensions/server.cjs.map +1 -0
  20. package/dist/extensions/server.d.cts +5 -0
  21. package/dist/extensions/server.d.cts.map +1 -0
  22. package/dist/extensions/server.d.mts +5 -0
  23. package/dist/extensions/server.d.mts.map +1 -0
  24. package/dist/extensions/server.mjs +19 -0
  25. package/dist/extensions/server.mjs.map +1 -0
  26. package/dist/index.cjs +22 -1
  27. package/dist/index.d.cts +7 -7
  28. package/dist/index.d.mts +7 -7
  29. package/dist/index.mjs +7 -1
  30. package/dist/pi-cache-optimizer-BBOw28o_.cjs +7915 -0
  31. package/dist/pi-cache-optimizer-BBOw28o_.cjs.map +1 -0
  32. package/dist/pi-cache-optimizer-CxvTRl0J.mjs +7914 -0
  33. package/dist/pi-cache-optimizer-CxvTRl0J.mjs.map +1 -0
  34. package/dist/src/constants/environment.cjs +14 -0
  35. package/dist/src/constants/environment.cjs.map +1 -0
  36. package/dist/src/constants/environment.d.cts +8 -0
  37. package/dist/src/constants/environment.d.cts.map +1 -0
  38. package/dist/src/constants/environment.d.mts +8 -0
  39. package/dist/src/constants/environment.d.mts.map +1 -0
  40. package/dist/src/constants/environment.mjs +10 -0
  41. package/dist/src/constants/environment.mjs.map +1 -0
  42. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/cacheHooks.cjs +47 -0
  43. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/cacheHooks.cjs.map +1 -0
  44. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/cacheHooks.mjs +47 -0
  45. package/dist/src/extensions/workspaces/sessions/(backend)/_lib/cacheHooks.mjs.map +1 -0
  46. package/dist/src/extensions/workspaces/sessions/(backend)/hook/before-provider-request.server.cjs +7 -0
  47. package/dist/src/extensions/workspaces/sessions/(backend)/hook/before-provider-request.server.cjs.map +1 -0
  48. package/dist/src/extensions/workspaces/sessions/(backend)/hook/before-provider-request.server.mjs +8 -0
  49. package/dist/src/extensions/workspaces/sessions/(backend)/hook/before-provider-request.server.mjs.map +1 -0
  50. package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.cjs +7 -0
  51. package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.cjs.map +1 -0
  52. package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.mjs +8 -0
  53. package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.mjs.map +1 -0
  54. package/dist/src/models/promptCacheTelemetry.cjs +45 -0
  55. package/dist/src/models/promptCacheTelemetry.cjs.map +1 -0
  56. package/dist/{services/telemetry.d.cts → src/models/promptCacheTelemetry.d.cts} +3 -4
  57. package/dist/src/models/promptCacheTelemetry.d.cts.map +1 -0
  58. package/dist/{services/telemetry.d.mts → src/models/promptCacheTelemetry.d.mts} +3 -4
  59. package/dist/src/models/promptCacheTelemetry.d.mts.map +1 -0
  60. package/dist/src/models/promptCacheTelemetry.mjs +45 -0
  61. package/dist/src/models/promptCacheTelemetry.mjs.map +1 -0
  62. package/dist/src/schemas/apiContracts.cjs +13 -0
  63. package/dist/src/schemas/apiContracts.cjs.map +1 -0
  64. package/dist/src/schemas/apiContracts.d.cts +53 -0
  65. package/dist/src/schemas/apiContracts.d.cts.map +1 -0
  66. package/dist/src/schemas/apiContracts.d.mts +53 -0
  67. package/dist/src/schemas/apiContracts.d.mts.map +1 -0
  68. package/dist/src/schemas/apiContracts.mjs +13 -0
  69. package/dist/src/schemas/apiContracts.mjs.map +1 -0
  70. package/dist/src/services/canonical/index.cjs +28 -0
  71. package/dist/src/services/canonical/index.cjs.map +1 -0
  72. package/dist/src/services/canonical/index.d.cts +9 -0
  73. package/dist/src/services/canonical/index.d.cts.map +1 -0
  74. package/dist/src/services/canonical/index.d.mts +9 -0
  75. package/dist/src/services/canonical/index.d.mts.map +1 -0
  76. package/dist/src/services/canonical/index.mjs +27 -0
  77. package/dist/src/services/canonical/index.mjs.map +1 -0
  78. package/dist/src/services/digest/index.cjs +9 -0
  79. package/dist/src/services/digest/index.cjs.map +1 -0
  80. package/dist/src/services/digest/index.d.cts +4 -0
  81. package/dist/src/services/digest/index.d.cts.map +1 -0
  82. package/dist/src/services/digest/index.d.mts +4 -0
  83. package/dist/src/services/digest/index.d.mts.map +1 -0
  84. package/dist/src/services/digest/index.mjs +9 -0
  85. package/dist/src/services/digest/index.mjs.map +1 -0
  86. package/dist/src/services/namespace/index.cjs +78 -0
  87. package/dist/src/services/namespace/index.cjs.map +1 -0
  88. package/dist/src/services/namespace/index.d.cts +9 -0
  89. package/dist/src/services/namespace/index.d.cts.map +1 -0
  90. package/dist/src/services/namespace/index.d.mts +9 -0
  91. package/dist/src/services/namespace/index.d.mts.map +1 -0
  92. package/dist/src/services/namespace/index.mjs +74 -0
  93. package/dist/src/services/namespace/index.mjs.map +1 -0
  94. package/dist/src/services/promptCacheTelemetry/index.cjs +22 -0
  95. package/dist/src/services/promptCacheTelemetry/index.cjs.map +1 -0
  96. package/dist/src/services/promptCacheTelemetry/index.d.cts +17 -0
  97. package/dist/src/services/promptCacheTelemetry/index.d.cts.map +1 -0
  98. package/dist/src/services/promptCacheTelemetry/index.d.mts +17 -0
  99. package/dist/src/services/promptCacheTelemetry/index.d.mts.map +1 -0
  100. package/dist/src/services/promptCacheTelemetry/index.mjs +20 -0
  101. package/dist/src/services/promptCacheTelemetry/index.mjs.map +1 -0
  102. package/dist/src/services/providerPolicy/index.cjs +43 -0
  103. package/dist/src/services/providerPolicy/index.cjs.map +1 -0
  104. package/dist/src/services/providerPolicy/index.d.cts +7 -0
  105. package/dist/src/services/providerPolicy/index.d.cts.map +1 -0
  106. package/dist/src/services/providerPolicy/index.d.mts +7 -0
  107. package/dist/src/services/providerPolicy/index.d.mts.map +1 -0
  108. package/dist/src/services/providerPolicy/index.mjs +41 -0
  109. package/dist/src/services/providerPolicy/index.mjs.map +1 -0
  110. package/dist/{types → src/types}/cache.d.cts +11 -12
  111. package/dist/src/types/cache.d.cts.map +1 -0
  112. package/dist/{types → src/types}/cache.d.mts +11 -12
  113. package/dist/src/types/cache.d.mts.map +1 -0
  114. package/package.json +31 -13
  115. package/dist/adapters/node/digest.cjs +0 -2
  116. package/dist/adapters/node/digest.cjs.map +0 -1
  117. package/dist/adapters/node/digest.d.cts +0 -5
  118. package/dist/adapters/node/digest.d.cts.map +0 -1
  119. package/dist/adapters/node/digest.d.mts +0 -5
  120. package/dist/adapters/node/digest.d.mts.map +0 -1
  121. package/dist/adapters/node/digest.mjs +0 -2
  122. package/dist/adapters/node/digest.mjs.map +0 -1
  123. package/dist/pi-cache-optimizer-B7B911Pz.cjs +0 -54
  124. package/dist/pi-cache-optimizer-B7B911Pz.cjs.map +0 -1
  125. package/dist/pi-cache-optimizer-CjPVk06Q.mjs +0 -54
  126. package/dist/pi-cache-optimizer-CjPVk06Q.mjs.map +0 -1
  127. package/dist/providers/promptCacheTelemetry.cjs +0 -2
  128. package/dist/providers/promptCacheTelemetry.cjs.map +0 -1
  129. package/dist/providers/promptCacheTelemetry.d.cts +0 -18
  130. package/dist/providers/promptCacheTelemetry.d.cts.map +0 -1
  131. package/dist/providers/promptCacheTelemetry.d.mts +0 -18
  132. package/dist/providers/promptCacheTelemetry.d.mts.map +0 -1
  133. package/dist/providers/promptCacheTelemetry.mjs +0 -2
  134. package/dist/providers/promptCacheTelemetry.mjs.map +0 -1
  135. package/dist/services/canonical.cjs +0 -2
  136. package/dist/services/canonical.cjs.map +0 -1
  137. package/dist/services/canonical.d.cts +0 -10
  138. package/dist/services/canonical.d.cts.map +0 -1
  139. package/dist/services/canonical.d.mts +0 -10
  140. package/dist/services/canonical.d.mts.map +0 -1
  141. package/dist/services/canonical.mjs +0 -2
  142. package/dist/services/canonical.mjs.map +0 -1
  143. package/dist/services/namespace.cjs +0 -2
  144. package/dist/services/namespace.cjs.map +0 -1
  145. package/dist/services/namespace.d.cts +0 -10
  146. package/dist/services/namespace.d.cts.map +0 -1
  147. package/dist/services/namespace.d.mts +0 -10
  148. package/dist/services/namespace.d.mts.map +0 -1
  149. package/dist/services/namespace.mjs +0 -2
  150. package/dist/services/namespace.mjs.map +0 -1
  151. package/dist/services/providerPolicy.cjs +0 -2
  152. package/dist/services/providerPolicy.cjs.map +0 -1
  153. package/dist/services/providerPolicy.d.cts +0 -8
  154. package/dist/services/providerPolicy.d.cts.map +0 -1
  155. package/dist/services/providerPolicy.d.mts +0 -8
  156. package/dist/services/providerPolicy.d.mts.map +0 -1
  157. package/dist/services/providerPolicy.mjs +0 -2
  158. package/dist/services/providerPolicy.mjs.map +0 -1
  159. package/dist/services/telemetry.cjs +0 -2
  160. package/dist/services/telemetry.cjs.map +0 -1
  161. package/dist/services/telemetry.d.cts.map +0 -1
  162. package/dist/services/telemetry.d.mts.map +0 -1
  163. package/dist/services/telemetry.mjs +0 -2
  164. package/dist/services/telemetry.mjs.map +0 -1
  165. package/dist/types/cache.d.cts.map +0 -1
  166. package/dist/types/cache.d.mts.map +0 -1
  167. package/dist/types/environment.cjs +0 -2
  168. package/dist/types/environment.cjs.map +0 -1
  169. package/dist/types/environment.d.cts +0 -9
  170. package/dist/types/environment.d.cts.map +0 -1
  171. package/dist/types/environment.d.mts +0 -9
  172. package/dist/types/environment.d.mts.map +0 -1
  173. package/dist/types/environment.mjs +0 -2
  174. package/dist/types/environment.mjs.map +0 -1
package/README.md CHANGED
@@ -1,35 +1,50 @@
1
1
  # @agimon-ai/doompi-cache
2
2
 
3
- Provider prompt cache policy and deterministic routing for DoomPi
3
+ Provider prompt-cache policy and deterministic routing for DoomPi.
4
4
 
5
- This package is a composable [DoomPi](https://www.npmjs.com/package/@agimon-ai/doompi) subsystem. Use it with the distribution or install it independently in [Pi](https://www.npmjs.com/package/@earendil-works/pi-coding-agent).
5
+ DoomPi loads this package as fixed core. It derives stable provider cache keys from the active
6
+ session composition and applies them only to supported provider requests. The package can also run
7
+ as a standalone [Pi](https://www.npmjs.com/package/@earendil-works/pi-coding-agent) extension.
8
+
9
+ > **Alpha:** cache routing and provider integration may change between releases.
6
10
 
7
11
  ## Requirements
8
12
 
9
13
  - Node.js 22.19.0 or newer
10
- - `@earendil-works/pi-coding-agent` 0.84.2
14
+ - Pi 0.85.0 for standalone extension use
11
15
 
12
16
  ## Install
13
17
 
18
+ A DoomPi installation already includes this package. Do not add it to `.doom/modes.yaml`.
19
+
20
+ To load it directly in Pi:
21
+
14
22
  ```bash
15
23
  pi install npm:@agimon-ai/doompi-cache
16
24
  ```
17
25
 
18
- The package declares its Pi extension entry, so Pi loads it after installation. DoomPi users can include the package through their normal profile and domain composition instead.
26
+ Pi reads the extension entry from `package.json.pi.extensions` and loads it after installation.
19
27
 
20
28
  ## Package behavior
21
29
 
22
- DoomPi derives an opaque provider cache key from stable model-visible state, including the composition fingerprint, ordered domains, profile, persona, active minor modes, effective model, and child prompt projection. Returning to equivalent state restores the same key, but provider expiry or eviction can still make that namespace cold.
30
+ DoomPi derives an opaque provider cache key from stable model-visible state: the composition
31
+ fingerprint, ordered domains, profile, persona, active minor modes, effective model, and child prompt
32
+ projection. Returning to equivalent state restores the same key. Provider expiry or eviction can
33
+ still make the cache cold.
23
34
 
24
- The Pi extension rewrites only a nonblank cache key already emitted for an allowlisted OpenAI-family wire API. It preserves supported retention and provider cache markers, avoids adding unsupported fields to proxies, and reports only provider-observed token usage. Telemetry always reports current provider residency as `unknown`.
35
+ The Pi extension rewrites only a nonblank cache key already emitted for an allowlisted OpenAI-family
36
+ wire API. It preserves supported retention and provider cache markers, does not add unsupported
37
+ fields to proxies, and reports only provider-observed token usage. Telemetry reports current
38
+ provider residency as `unknown`.
25
39
 
26
40
  ## Help
27
41
 
28
- The published package includes `llms.txt` and the package-owned `src/prompts/doompi-use-cache/SKILL.md`. When the DoomPi Help minor mode is active, the extension contributes `doompi-use-cache` to its live Help catalog. The contribution follows Help provider replacement and is withdrawn when the extension shuts down.
29
-
30
- Help remains optional. Loading the standalone Pi extension does not require DoomPi Help or any other DoomPi runtime service.
42
+ The published package includes `llms.txt` and `src/prompts/doompi-use-cache/SKILL.md`. While DoomPi
43
+ Help is active, the extension adds `doompi-use-cache` to the live Help catalog. The contribution
44
+ follows Help provider replacement and is removed when the extension shuts down.
31
45
 
32
- To add another package-owned Help prompt, use the `scaffold-doom-prompt` feature with a `doompi-author-*` or `doompi-use-*` name and a concise description. Then link the generated `SKILL.md` from `llms.txt` and register a matching descriptor through the optional `DOOM_HELP_SERVICE` injection in the Pi adapter. Keep prompts as published resources under `src/prompts`; do not export them or copy them into `dist`.
46
+ Help is optional. The standalone Pi extension does not require DoomPi Help or another DoomPi runtime
47
+ service.
33
48
 
34
49
  ## Public API
35
50
 
@@ -46,7 +61,8 @@ import {
46
61
  } from '@agimon-ai/doompi-cache/env';
47
62
  ```
48
63
 
49
- The Pi host entry is available at `@agimon-ai/doompi-cache/extensions/pi`. The root API has no import-time extension side effects.
64
+ The Pi host entry is `@agimon-ai/doompi-cache/extensions/pi`. Importing the root API does not install
65
+ the extension.
50
66
 
51
67
  ## Development
52
68
 
@@ -59,7 +75,8 @@ pnpm exec vibe-lint check .
59
75
  npm pack --dry-run
60
76
  ```
61
77
 
62
- The official OpenAI canary is opt-in and reports provider `cached_tokens` without treating a cold result as a deterministic failure:
78
+ The live OpenAI canary is opt-in. It reports provider `cached_tokens`; a cold result does not fail
79
+ the test deterministically:
63
80
 
64
81
  ```bash
65
82
  DOOMPI_CACHE_LIVE_OPENAI=1 \
@@ -73,3 +90,9 @@ Maintained by [Agimon](https://agimon.ai/about).
73
90
  ## License
74
91
 
75
92
  MIT
93
+
94
+ ## Extension lifecycle and source layout
95
+
96
+ `src/extensions/pi.ts` awaits the upstream optimizer before mounting Cache so its provider hook runs after the optimizer. The named declaration contributes the telemetry service, optional mode-catalog subscription, events, and Help resource. `onDispose` restores owned environment values and resets telemetry after registrations are removed.
97
+
98
+ `src/extensions/server.ts` declares session hooks and resources from `controllers/cacheHooks.ts`. Shared policy and runtime logic live in `services/<name>/`, telemetry state lives in `models/`, and environment keys live in `constants/`. Flat `src/exports/` files publish reusable capabilities. The server plugin is exported only through `extensions/server`.
@@ -0,0 +1,7 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ const require_apiContracts = require("./src/schemas/apiContracts.cjs");
6
+ exports.apiContracts = require_apiContracts.apiContracts;
7
+ exports.default = require_apiContracts.apiContracts;
@@ -0,0 +1,2 @@
1
+ import { apiContracts } from "./src/schemas/apiContracts.cjs";
2
+ export { apiContracts, apiContracts as default };
@@ -0,0 +1,2 @@
1
+ import { apiContracts } from "./src/schemas/apiContracts.mjs";
2
+ export { apiContracts, apiContracts as default };
@@ -0,0 +1,2 @@
1
+ import { apiContracts } from "./src/schemas/apiContracts.mjs";
2
+ export { apiContracts, apiContracts as default };
package/dist/env.cjs CHANGED
@@ -1 +1,7 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./types/environment.cjs");exports.DOOMPI_PROMPT_CACHE_CHILD_PROJECTION_ENV=e.DOOMPI_PROMPT_CACHE_CHILD_PROJECTION_ENV,exports.DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV=e.DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV,exports.DOOMPI_PROMPT_CACHE_ROOT_SESSION_ENV=e.DOOMPI_PROMPT_CACHE_ROOT_SESSION_ENV,exports.PI_CACHE_RETENTION_ENV=e.PI_CACHE_RETENTION_ENV,exports.PI_CACHE_RETENTION_LONG=e.PI_CACHE_RETENTION_LONG;
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_environment = require("./src/constants/environment.cjs");
3
+ exports.DOOMPI_PROMPT_CACHE_CHILD_PROJECTION_ENV = require_environment.DOOMPI_PROMPT_CACHE_CHILD_PROJECTION_ENV;
4
+ exports.DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV = require_environment.DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV;
5
+ exports.DOOMPI_PROMPT_CACHE_ROOT_SESSION_ENV = require_environment.DOOMPI_PROMPT_CACHE_ROOT_SESSION_ENV;
6
+ exports.PI_CACHE_RETENTION_ENV = require_environment.PI_CACHE_RETENTION_ENV;
7
+ exports.PI_CACHE_RETENTION_LONG = require_environment.PI_CACHE_RETENTION_LONG;
package/dist/env.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { DOOMPI_PROMPT_CACHE_CHILD_PROJECTION_ENV, DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV, DOOMPI_PROMPT_CACHE_ROOT_SESSION_ENV, PI_CACHE_RETENTION_ENV, PI_CACHE_RETENTION_LONG } from "./types/environment.cjs";
1
+ import { DOOMPI_PROMPT_CACHE_CHILD_PROJECTION_ENV, DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV, DOOMPI_PROMPT_CACHE_ROOT_SESSION_ENV, PI_CACHE_RETENTION_ENV, PI_CACHE_RETENTION_LONG } from "./src/constants/environment.cjs";
2
2
  export { DOOMPI_PROMPT_CACHE_CHILD_PROJECTION_ENV, DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV, DOOMPI_PROMPT_CACHE_ROOT_SESSION_ENV, PI_CACHE_RETENTION_ENV, PI_CACHE_RETENTION_LONG };
package/dist/env.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { DOOMPI_PROMPT_CACHE_CHILD_PROJECTION_ENV, DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV, DOOMPI_PROMPT_CACHE_ROOT_SESSION_ENV, PI_CACHE_RETENTION_ENV, PI_CACHE_RETENTION_LONG } from "./types/environment.mjs";
1
+ import { DOOMPI_PROMPT_CACHE_CHILD_PROJECTION_ENV, DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV, DOOMPI_PROMPT_CACHE_ROOT_SESSION_ENV, PI_CACHE_RETENTION_ENV, PI_CACHE_RETENTION_LONG } from "./src/constants/environment.mjs";
2
2
  export { DOOMPI_PROMPT_CACHE_CHILD_PROJECTION_ENV, DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV, DOOMPI_PROMPT_CACHE_ROOT_SESSION_ENV, PI_CACHE_RETENTION_ENV, PI_CACHE_RETENTION_LONG };
package/dist/env.mjs CHANGED
@@ -1 +1,2 @@
1
- import{DOOMPI_PROMPT_CACHE_CHILD_PROJECTION_ENV as e,DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV as t,DOOMPI_PROMPT_CACHE_ROOT_SESSION_ENV as n,PI_CACHE_RETENTION_ENV as r,PI_CACHE_RETENTION_LONG as i}from"./types/environment.mjs";export{e as DOOMPI_PROMPT_CACHE_CHILD_PROJECTION_ENV,t as DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV,n as DOOMPI_PROMPT_CACHE_ROOT_SESSION_ENV,r as PI_CACHE_RETENTION_ENV,i as PI_CACHE_RETENTION_LONG};
1
+ import { DOOMPI_PROMPT_CACHE_CHILD_PROJECTION_ENV, DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV, DOOMPI_PROMPT_CACHE_ROOT_SESSION_ENV, PI_CACHE_RETENTION_ENV, PI_CACHE_RETENTION_LONG } from "./src/constants/environment.mjs";
2
+ export { DOOMPI_PROMPT_CACHE_CHILD_PROJECTION_ENV, DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV, DOOMPI_PROMPT_CACHE_ROOT_SESSION_ENV, PI_CACHE_RETENTION_ENV, PI_CACHE_RETENTION_LONG };
@@ -1,2 +1,459 @@
1
- Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});let e=require("@agimon-ai/doompi-config/harnessStore"),t=require("@agimon-ai/doompi-extension-contracts/cordis-host"),n=require("@agimon-ai/doompi-extension-contracts/help"),r=require("@agimon-ai/doompi-extension-contracts/mode"),i=require("node:crypto"),a=require("@deepseek-ai/cordis");var o=class{#e;#t={capability:`unknown`};#n=[];constructor(e=64){if(!Number.isInteger(e)||e<1)throw Error(`Prompt cache telemetry limit must be a positive integer.`);this.#e=e}beginRequest(e){this.#t={...e}}observe(e,t){let n=this.#t.namespace,r=this.#t.modelFingerprint;!n||!r||(this.#n.push({namespace:n,modelFingerprint:r,cacheRead:e.cacheRead,cacheWrite:e.cacheWrite,totalInput:e.totalInput,observedAt:t}),this.#n.length>this.#e&&this.#n.splice(0,this.#n.length-this.#e))}snapshot(){let e=[...this.#n];return{...this.#t,residency:`unknown`,observations:e,...e.length>0?{lastObservation:e.at(-1)}:{}}}reset(){this.#t={capability:`unknown`},this.#n=[]}};function s(e={}){return{telemetry:e.telemetry??new o,now:e.now??Date.now}}var c=class{#e;#t;#n;#r;constructor(e,t=process.env){this.#t=e,this.#e=t,this.#n={present:Object.hasOwn(t,e),value:t[e]}}set(e){this.#e[this.#t]=e,this.#r=e}restore(){this.#r!==void 0&&this.#e[this.#t]===this.#r&&(this.#n.present?this.#e[this.#t]=this.#n.value:delete this.#e[this.#t],this.#r=void 0)}};function l(e){return(0,i.createHash)(`sha256`).update(e).digest(`base64url`)}var u=class extends a.Service{telemetry;constructor(e,t){super(e,`doom/prompt-cache-telemetry`),this.telemetry=t}snapshot(){return this.telemetry.snapshot()}};function d(e){if(!Number.isFinite(e))throw Error(`Prompt cache identity cannot contain a non-finite number.`);return Object.is(e,-0)?0:e}function f(e){if(e===null)return null;if(typeof e==`string`)return e.normalize(`NFC`);if(typeof e==`boolean`)return e;if(typeof e==`number`)return d(e);if(Array.isArray(e))return e.map(e=>f(e));if(typeof e!=`object`)throw Error(`Unsupported prompt cache identity value: ${typeof e}.`);let t=e,n={};for(let e of Object.keys(t).sort((e,t)=>e.localeCompare(t))){let r=t[e];r!==void 0&&(n[e.normalize(`NFC`)]=f(r))}return n}function p(e){return JSON.stringify(f(e))}function m(e,t,n){return`${e}${n(p(t))}`}function h(e){return e?.trim().replaceAll(`\\`,`/`)||void 0}function g(e){return e.filter(({activation:e})=>e===`active`||e===`activating`).map(({source:e,id:t,modelContextVariant:n})=>({source:e,id:t,...n?{modelContextVariant:n}:{}})).sort((e,t)=>e.source.localeCompare(t.source)||e.id.localeCompare(t.id))}function _(e,t){return m(`dpr1_`,{version:1,rootSessionId:e},t)}function v(e,t){return m(`dpn1_`,{version:1,rootSession:_(e.rootSessionId,t),compositionFingerprint:e.compositionFingerprint??null,majorMode:e.majorMode,domains:[...e.domains],profile:e.profile??null,persona:h(e.persona)??null,minorModes:g(e.minorModes)},t)}function y(e,t){return m(`dpm1_`,{version:1,virtualProvider:e.virtualProvider??null,virtualModel:e.virtualModel??null,api:e.api??null,baseUrl:e.baseUrl??null,wireModel:e.wireModel??null},t)}function b(e,t,n,r,i){return m(`dpc1_`,{version:1,parentNamespace:e,scope:t,childProjection:i??null,modelFingerprint:n},r)}function x(e){let t=e.__internals_for_tests;return typeof t?.isRuntimeOptimizerEnabled==`function`&&typeof t.shouldInjectOpenAIPromptCacheKey==`function`&&t.isRuntimeOptimizerEnabled()&&t.shouldInjectOpenAIPromptCacheKey()}const S=new Set([`openai-completions`,`openai-responses`,`openai-codex-responses`,`azure-openai-responses`]),C=new Set([`anthropic-messages`,`bedrock-converse-stream`]),w=new Set([`google-generative-ai`,`google-vertex`,`google-vertex-anthropic`]);function T(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function E(e){return e.api===`openai-responses`||e.api===`openai-completions`?e.virtualProvider===`openai`?`key-and-long-retention`:`key-only`:e.api&&S.has(e.api)?`key-only`:e.api&&C.has(e.api)?`marker-only`:e.api&&w.has(e.api)?`automatic`:`unknown`}function D(e,t,n,r){if(!r||!t||!S.has(t)||!T(e))return;let i=e.prompt_cache_key;if(!(typeof i!=`string`||!i.trim()||i===n))return{...e,prompt_cache_key:n}}function O(e){if(!T(e))return;let t=e.prompt_cache_retention;return typeof t==`string`&&t.trim()?t.trim():void 0}function k(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:void 0}function A(e){return typeof e==`number`&&Number.isFinite(e)&&e>=0?e:void 0}function j(...e){for(let t of e){let e=A(t);if(e!==void 0)return e}}function M(e){let t=A(e.cacheRead),n=A(e.cacheWrite);if(t===void 0&&n===void 0)return;let r=A(e.input)??0;return{cacheRead:t??0,cacheWrite:n??0,totalInput:r+(t??0)+(n??0)}}function N(e){let t=k(e.prompt_tokens_details)??k(e.promptTokensDetails),n=k(e.input_tokens_details)??k(e.inputTokensDetails),r=j(t?.cached_tokens,t?.cachedTokens,n?.cached_tokens,n?.cachedTokens),i=j(t?.cache_write_tokens,t?.cacheWriteTokens,n?.cache_write_tokens,n?.cacheWriteTokens);if(r===void 0&&i===void 0)return;let a=(r??0)+(i??0),o=j(e.prompt_tokens,e.promptTokens,e.input_tokens,e.inputTokens);return{cacheRead:r??0,cacheWrite:i??0,totalInput:Math.max(o??a,a)}}function P(e){let t=j(e.cache_read_input_tokens,e.cacheReadInputTokens),n=j(e.cache_creation_input_tokens,e.cacheCreationInputTokens);if(t===void 0&&n===void 0)return;let r=j(e.input_tokens,e.inputTokens)??0;return{cacheRead:t??0,cacheWrite:n??0,totalInput:r+(t??0)+(n??0)}}function F(e){let t=k(e.usage_metadata)??k(e.usageMetadata)??e,n=j(t.cachedContentTokenCount,t.cached_content_token_count);if(n===void 0)return;let r=j(t.promptTokenCount,t.prompt_token_count,e.input_tokens,e.inputTokens,e.prompt_tokens,e.promptTokens);return{cacheRead:n,cacheWrite:0,totalInput:Math.max(r??n,n)}}function I(e){let t=k(k(e)?.usage);if(t)return M(t)??N(t)??P(t)??F(t)}const L=`DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE`,R=`@agimon-ai/doompi-cache`;function z(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function B(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:void 0}function V(e){let t=e.state;return{source:e.descriptor.source,id:e.descriptor.id,activation:t.activation,...t.modelContextVariant?{modelContextVariant:t.modelContextVariant}:{}}}function H(e,t){let n=B(e.model),r=B(t);return{virtualProvider:z(n?.provider),virtualModel:z(n?.id),api:z(n?.api),baseUrl:z(n?.baseUrl),wireModel:z(r?.model)}}function U(e){let t=B(e);return t?.stopReason===`error`||t?.stopReason===`aborted`}function W(e){return O(e)??(process.env.PI_CACHE_RETENTION===`long`?`long`:void 0)}function G(t,n,i,a){let o=new c(L),s=new c(`DOOMPI_PROMPT_CACHE_ROOT_SESSION`),u=z(process.env[L]),d=z(process.env.DOOMPI_PROMPT_CACHE_CHILD_PROJECTION),f=!!(u&&d),p,m=u,h=[],g=()=>{if(f)return m;if(!p)return;let t=(0,e.getHarnessState)();return m=v({rootSessionId:p,compositionFingerprint:t.compositionFingerprint,majorMode:t.majorMode,domains:t.domains,profile:t.profile,persona:t.personaFile,minorModes:h},l),o.set(m),s.set(_(p,l)),m};return t.inject([r.DOOM_MINOR_MODE_CATALOG_SERVICE],e=>{if(f)return;let t=(0,r.readMinorModeCatalog)(e);if(!t)return;let n=()=>{h=t.getSnapshot().modes.map(V),g()};return n(),t.subscribe(n)}),n.on(`session_start`,(e,t)=>{f||(p=z(t.sessionManager.getSessionId()),g())}),n.on(`before_provider_request`,(e,t)=>{let n=f?u:g();if(!n)return;let r=H(t,e.payload),o=y(r,l),s=b(n,f?`child`:`parent`,o,l,d),c=D(e.payload,r.api,s,x(a));return i.telemetry.beginRequest({capability:E(r),namespace:n,modelFingerprint:o,requestedRetention:W(c??e.payload),...c?{keySuffix:s.slice(-8)}:{}}),c}),n.on(`message_end`,e=>{if(U(e.message))return;let t=I(e.message);t&&i.telemetry.observe(t,i.now())}),()=>{o.restore(),s.restore(),i.telemetry.reset()}}function K(e,t){e.inject([n.DOOM_HELP_SERVICE],e=>{let t=(0,n.requireDoomHelpService)(e).register({source:R,moduleUrl:require("url").pathToFileURL(__filename).href,skills:[{name:`doompi-use-cache`,description:`Inspect DoomPi provider prompt cache policy, routing identity, and provider-observed usage.`}]});return()=>t.dispose()}),e.effect(function*(){new u(e,t.dependencies.telemetry),yield G(e,t.pi,t.dependencies,t.optimizer)},R)}async function q(e,n=s()){let r=await Promise.resolve().then(()=>require("../pi-cache-optimizer-B7B911Pz.cjs"));if(typeof r.default!=`function`)throw Error(`Pi Cache Optimizer does not export an extension factory.`);await r.default(e);let i=await(0,t.connectDoomCordisHost)(e,R),a=i.root.plugin(K,{pi:e,dependencies:n,optimizer:r});try{await a}catch(e){try{await a.dispose()}finally{await i.dispose()}throw e}let o;e.on(`session_shutdown`,()=>o??=(async()=>{try{await a.dispose()}finally{await i.dispose()}})())}exports.activateCacheExtension=q,exports.default=q;
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ let _agimon_ai_doompi_core_pi_extension = require("@agimon-ai/doompi-core/pi-extension");
6
+ let _agimon_ai_doompi_core_extension_file = require("@agimon-ai/doompi-core/extension-file");
7
+ let _agimon_ai_doompi_config_harnessStore = require("@agimon-ai/doompi-config/harnessStore");
8
+ let _agimon_ai_doompi_minor_mode = require("@agimon-ai/doompi-minor-mode");
9
+ let node_crypto = require("node:crypto");
10
+ let _deepseek_ai_cordis = require("@deepseek-ai/cordis");
11
+ //#region src/models/promptCacheTelemetry.ts
12
+ const DEFAULT_OBSERVATION_LIMIT = 64;
13
+ var PromptCacheTelemetry = class {
14
+ #limit;
15
+ #request = { capability: "unknown" };
16
+ #observations = [];
17
+ constructor(limit = DEFAULT_OBSERVATION_LIMIT) {
18
+ if (!Number.isInteger(limit) || limit < 1) throw new Error("Prompt cache telemetry limit must be a positive integer.");
19
+ this.#limit = limit;
20
+ }
21
+ beginRequest(status) {
22
+ this.#request = { ...status };
23
+ }
24
+ observe(usage, observedAt) {
25
+ const namespace = this.#request.namespace;
26
+ const modelFingerprint = this.#request.modelFingerprint;
27
+ if (!namespace || !modelFingerprint) return;
28
+ this.#observations.push({
29
+ namespace,
30
+ modelFingerprint,
31
+ cacheRead: usage.cacheRead,
32
+ cacheWrite: usage.cacheWrite,
33
+ totalInput: usage.totalInput,
34
+ observedAt
35
+ });
36
+ if (this.#observations.length > this.#limit) this.#observations.splice(0, this.#observations.length - this.#limit);
37
+ }
38
+ snapshot() {
39
+ const observations = [...this.#observations];
40
+ return {
41
+ ...this.#request,
42
+ residency: "unknown",
43
+ observations,
44
+ ...observations.length > 0 ? { lastObservation: observations.at(-1) } : {}
45
+ };
46
+ }
47
+ reset() {
48
+ this.#request = { capability: "unknown" };
49
+ this.#observations = [];
50
+ }
51
+ };
52
+ //#endregion
53
+ //#region src/constants/cache.ts
54
+ const PACKAGE_SOURCE = "@agimon-ai/doompi-cache";
55
+ const CACHE_HELP_SKILL = {
56
+ name: "doompi-use-cache",
57
+ description: "Inspect DoomPi provider prompt cache policy, routing identity, and provider-observed usage."
58
+ };
59
+ //#endregion
60
+ //#region src/constants/environment.ts
61
+ const DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV = "DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE";
62
+ const DOOMPI_PROMPT_CACHE_ROOT_SESSION_ENV = "DOOMPI_PROMPT_CACHE_ROOT_SESSION";
63
+ const DOOMPI_PROMPT_CACHE_CHILD_PROJECTION_ENV = "DOOMPI_PROMPT_CACHE_CHILD_PROJECTION";
64
+ //#endregion
65
+ //#region src/services/digest/index.ts
66
+ function sha256Base64Url(value) {
67
+ return (0, node_crypto.createHash)("sha256").update(value).digest("base64url");
68
+ }
69
+ //#endregion
70
+ //#region src/services/environment/index.ts
71
+ var OwnedEnvironmentValue = class {
72
+ #environment;
73
+ #name;
74
+ #baseline;
75
+ #ownedValue;
76
+ constructor(name, environment = process.env) {
77
+ this.#name = name;
78
+ this.#environment = environment;
79
+ this.#baseline = {
80
+ present: Object.hasOwn(environment, name),
81
+ value: environment[name]
82
+ };
83
+ }
84
+ set(value) {
85
+ this.#environment[this.#name] = value;
86
+ this.#ownedValue = value;
87
+ }
88
+ restore() {
89
+ if (this.#ownedValue === void 0 || this.#environment[this.#name] !== this.#ownedValue) return;
90
+ if (this.#baseline.present) this.#environment[this.#name] = this.#baseline.value;
91
+ else delete this.#environment[this.#name];
92
+ this.#ownedValue = void 0;
93
+ }
94
+ };
95
+ //#endregion
96
+ //#region src/services/canonical/index.ts
97
+ function canonicalNumber(value) {
98
+ if (!Number.isFinite(value)) throw new Error("Prompt cache identity cannot contain a non-finite number.");
99
+ return Object.is(value, -0) ? 0 : value;
100
+ }
101
+ function canonicalValue(value) {
102
+ if (value === null) return null;
103
+ if (typeof value === "string") return value.normalize("NFC");
104
+ if (typeof value === "boolean") return value;
105
+ if (typeof value === "number") return canonicalNumber(value);
106
+ if (Array.isArray(value)) return value.map((entry) => canonicalValue(entry));
107
+ if (typeof value !== "object") throw new Error(`Unsupported prompt cache identity value: ${typeof value}.`);
108
+ const record = value;
109
+ const result = {};
110
+ for (const key of Object.keys(record).sort((left, right) => left.localeCompare(right))) {
111
+ const entry = record[key];
112
+ if (entry !== void 0) result[key.normalize("NFC")] = canonicalValue(entry);
113
+ }
114
+ return result;
115
+ }
116
+ function canonicalJson(value) {
117
+ return JSON.stringify(canonicalValue(value));
118
+ }
119
+ //#endregion
120
+ //#region src/services/namespace/index.ts
121
+ const KEY_PREFIX = "dpc1_";
122
+ const PARENT_PREFIX = "dpn1_";
123
+ const ROOT_PREFIX = "dpr1_";
124
+ const MODEL_PREFIX = "dpm1_";
125
+ function digestIdentity(prefix, value, digest) {
126
+ return `${prefix}${digest(canonicalJson(value))}`;
127
+ }
128
+ function normalizedPersona(value) {
129
+ return value?.trim().replaceAll("\\", "/") || void 0;
130
+ }
131
+ function activeMinorModes(modes) {
132
+ return modes.filter(({ activation }) => activation === "active" || activation === "activating").map(({ source, id, modelContextVariant }) => ({
133
+ source,
134
+ id,
135
+ ...modelContextVariant ? { modelContextVariant } : {}
136
+ })).sort((left, right) => left.source.localeCompare(right.source) || left.id.localeCompare(right.id));
137
+ }
138
+ function createRootSessionIdentity(rootSessionId, digest) {
139
+ return digestIdentity(ROOT_PREFIX, {
140
+ version: 1,
141
+ rootSessionId
142
+ }, digest);
143
+ }
144
+ function createParentPromptCacheNamespace(state, digest) {
145
+ return digestIdentity(PARENT_PREFIX, {
146
+ version: 1,
147
+ rootSession: createRootSessionIdentity(state.rootSessionId, digest),
148
+ compositionFingerprint: state.compositionFingerprint ?? null,
149
+ majorMode: state.majorMode,
150
+ domains: [...state.domains],
151
+ profile: state.profile ?? null,
152
+ persona: normalizedPersona(state.persona) ?? null,
153
+ minorModes: activeMinorModes(state.minorModes)
154
+ }, digest);
155
+ }
156
+ function createPromptCacheModelFingerprint(model, digest) {
157
+ return digestIdentity(MODEL_PREFIX, {
158
+ version: 1,
159
+ virtualProvider: model.virtualProvider ?? null,
160
+ virtualModel: model.virtualModel ?? null,
161
+ api: model.api ?? null,
162
+ baseUrl: model.baseUrl ?? null,
163
+ wireModel: model.wireModel ?? null
164
+ }, digest);
165
+ }
166
+ function createPromptCacheKey(parentNamespace, scope, modelFingerprint, digest, childProjection) {
167
+ return digestIdentity(KEY_PREFIX, {
168
+ version: 1,
169
+ parentNamespace,
170
+ scope,
171
+ childProjection: childProjection ?? null,
172
+ modelFingerprint
173
+ }, digest);
174
+ }
175
+ //#endregion
176
+ //#region src/services/optimizerPolicy/index.ts
177
+ /** Fail closed unless the pinned optimizer confirms both runtime and key routing are enabled. */
178
+ function optimizerAllowsPromptCacheKey(optimizer) {
179
+ const internals = optimizer.__internals_for_tests;
180
+ return typeof internals?.isRuntimeOptimizerEnabled === "function" && typeof internals.shouldInjectOpenAIPromptCacheKey === "function" && internals.isRuntimeOptimizerEnabled() && internals.shouldInjectOpenAIPromptCacheKey();
181
+ }
182
+ //#endregion
183
+ //#region src/services/promptCacheUsage/index.ts
184
+ function recordValue$1(value) {
185
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
186
+ }
187
+ function nonNegativeNumber(value) {
188
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
189
+ }
190
+ function firstNumber(...values) {
191
+ for (const value of values) {
192
+ const number = nonNegativeNumber(value);
193
+ if (number !== void 0) return number;
194
+ }
195
+ }
196
+ function normalizedUsage(usage) {
197
+ const cacheRead = nonNegativeNumber(usage.cacheRead);
198
+ const cacheWrite = nonNegativeNumber(usage.cacheWrite);
199
+ if (cacheRead === void 0 && cacheWrite === void 0) return void 0;
200
+ const input = nonNegativeNumber(usage.input) ?? 0;
201
+ return {
202
+ cacheRead: cacheRead ?? 0,
203
+ cacheWrite: cacheWrite ?? 0,
204
+ totalInput: input + (cacheRead ?? 0) + (cacheWrite ?? 0)
205
+ };
206
+ }
207
+ function openAiUsage(usage) {
208
+ const promptDetails = recordValue$1(usage.prompt_tokens_details) ?? recordValue$1(usage.promptTokensDetails);
209
+ const inputDetails = recordValue$1(usage.input_tokens_details) ?? recordValue$1(usage.inputTokensDetails);
210
+ const cacheRead = firstNumber(promptDetails?.cached_tokens, promptDetails?.cachedTokens, inputDetails?.cached_tokens, inputDetails?.cachedTokens);
211
+ const cacheWrite = firstNumber(promptDetails?.cache_write_tokens, promptDetails?.cacheWriteTokens, inputDetails?.cache_write_tokens, inputDetails?.cacheWriteTokens);
212
+ if (cacheRead === void 0 && cacheWrite === void 0) return void 0;
213
+ const floor = (cacheRead ?? 0) + (cacheWrite ?? 0);
214
+ const reportedTotal = firstNumber(usage.prompt_tokens, usage.promptTokens, usage.input_tokens, usage.inputTokens);
215
+ return {
216
+ cacheRead: cacheRead ?? 0,
217
+ cacheWrite: cacheWrite ?? 0,
218
+ totalInput: Math.max(reportedTotal ?? floor, floor)
219
+ };
220
+ }
221
+ function anthropicUsage(usage) {
222
+ const cacheRead = firstNumber(usage.cache_read_input_tokens, usage.cacheReadInputTokens);
223
+ const cacheWrite = firstNumber(usage.cache_creation_input_tokens, usage.cacheCreationInputTokens);
224
+ if (cacheRead === void 0 && cacheWrite === void 0) return void 0;
225
+ const input = firstNumber(usage.input_tokens, usage.inputTokens) ?? 0;
226
+ return {
227
+ cacheRead: cacheRead ?? 0,
228
+ cacheWrite: cacheWrite ?? 0,
229
+ totalInput: input + (cacheRead ?? 0) + (cacheWrite ?? 0)
230
+ };
231
+ }
232
+ function geminiUsage(usage) {
233
+ const metadata = recordValue$1(usage.usage_metadata) ?? recordValue$1(usage.usageMetadata) ?? usage;
234
+ const cacheRead = firstNumber(metadata.cachedContentTokenCount, metadata.cached_content_token_count);
235
+ if (cacheRead === void 0) return void 0;
236
+ const totalInput = firstNumber(metadata.promptTokenCount, metadata.prompt_token_count, usage.input_tokens, usage.inputTokens, usage.prompt_tokens, usage.promptTokens);
237
+ return {
238
+ cacheRead,
239
+ cacheWrite: 0,
240
+ totalInput: Math.max(totalInput ?? cacheRead, cacheRead)
241
+ };
242
+ }
243
+ /** Normalize only usage values carried by a provider-produced assistant message. */
244
+ function normalizePromptCacheUsage(message) {
245
+ const usage = recordValue$1(recordValue$1(message)?.usage);
246
+ if (!usage) return void 0;
247
+ return normalizedUsage(usage) ?? openAiUsage(usage) ?? anthropicUsage(usage) ?? geminiUsage(usage);
248
+ }
249
+ //#endregion
250
+ //#region src/services/providerPolicy/index.ts
251
+ const ROUTING_KEY_APIS = /* @__PURE__ */ new Set([
252
+ "openai-completions",
253
+ "openai-responses",
254
+ "openai-codex-responses",
255
+ "azure-openai-responses"
256
+ ]);
257
+ const MARKER_APIS = /* @__PURE__ */ new Set(["anthropic-messages", "bedrock-converse-stream"]);
258
+ const AUTOMATIC_APIS = /* @__PURE__ */ new Set([
259
+ "google-generative-ai",
260
+ "google-vertex",
261
+ "google-vertex-anthropic"
262
+ ]);
263
+ function isRecord(value) {
264
+ return typeof value === "object" && value !== null && !Array.isArray(value);
265
+ }
266
+ function classifyPromptCacheCapability(model) {
267
+ if (model.api === "openai-responses" || model.api === "openai-completions") return model.virtualProvider === "openai" ? "key-and-long-retention" : "key-only";
268
+ if (model.api && ROUTING_KEY_APIS.has(model.api)) return "key-only";
269
+ if (model.api && MARKER_APIS.has(model.api)) return "marker-only";
270
+ if (model.api && AUTOMATIC_APIS.has(model.api)) return "automatic";
271
+ return "unknown";
272
+ }
273
+ function rewritePromptCacheKey(payload, api, key, enabled) {
274
+ if (!enabled || !api || !ROUTING_KEY_APIS.has(api) || !isRecord(payload)) return void 0;
275
+ const current = payload.prompt_cache_key;
276
+ if (typeof current !== "string" || !current.trim() || current === key) return void 0;
277
+ return {
278
+ ...payload,
279
+ prompt_cache_key: key
280
+ };
281
+ }
282
+ function requestedPromptCacheRetention(payload) {
283
+ if (!isRecord(payload)) return void 0;
284
+ const retention = payload.prompt_cache_retention;
285
+ return typeof retention === "string" && retention.trim() ? retention.trim() : void 0;
286
+ }
287
+ //#endregion
288
+ //#region src/services/cacheRuntime/index.ts
289
+ function stringValue(value) {
290
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
291
+ }
292
+ function recordValue(value) {
293
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
294
+ }
295
+ function minorModeState(record) {
296
+ const state = record.state;
297
+ return {
298
+ source: record.descriptor.source,
299
+ id: record.descriptor.id,
300
+ activation: state.activation,
301
+ ...state.modelContextVariant ? { modelContextVariant: state.modelContextVariant } : {}
302
+ };
303
+ }
304
+ function modelIdentity(ctx, payload) {
305
+ const model = recordValue(ctx.model);
306
+ const request = recordValue(payload);
307
+ return {
308
+ virtualProvider: stringValue(model?.provider),
309
+ virtualModel: stringValue(model?.id),
310
+ api: stringValue(model?.api),
311
+ baseUrl: stringValue(model?.baseUrl),
312
+ wireModel: stringValue(request?.model)
313
+ };
314
+ }
315
+ function isErrorMessage(message) {
316
+ const record = recordValue(message);
317
+ return record?.stopReason === "error" || record?.stopReason === "aborted";
318
+ }
319
+ function requestedRetention(payload) {
320
+ return requestedPromptCacheRetention(payload) ?? (process.env["PI_CACHE_RETENTION"] === "long" ? "long" : void 0);
321
+ }
322
+ function createCacheRuntime(dependencies, optimizer) {
323
+ const parentNamespaceEnvironment = new OwnedEnvironmentValue(DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV);
324
+ const rootSessionEnvironment = new OwnedEnvironmentValue(DOOMPI_PROMPT_CACHE_ROOT_SESSION_ENV);
325
+ const projectedParentNamespace = stringValue(process.env[DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV]);
326
+ const childProjection = stringValue(process.env[DOOMPI_PROMPT_CACHE_CHILD_PROJECTION_ENV]);
327
+ const isProjectedChild = Boolean(projectedParentNamespace && childProjection);
328
+ let rootSessionId;
329
+ let parentNamespace = projectedParentNamespace;
330
+ let minorModes = [];
331
+ const refreshParentNamespace = () => {
332
+ if (isProjectedChild) return parentNamespace;
333
+ if (!rootSessionId) return void 0;
334
+ const harness = (0, _agimon_ai_doompi_config_harnessStore.getHarnessState)();
335
+ parentNamespace = createParentPromptCacheNamespace({
336
+ rootSessionId,
337
+ compositionFingerprint: harness.compositionFingerprint,
338
+ majorMode: harness.majorMode,
339
+ domains: harness.domains,
340
+ profile: harness.profile,
341
+ persona: harness.personaFile,
342
+ minorModes
343
+ }, sha256Base64Url);
344
+ parentNamespaceEnvironment.set(parentNamespace);
345
+ rootSessionEnvironment.set(createRootSessionIdentity(rootSessionId, sha256Base64Url));
346
+ return parentNamespace;
347
+ };
348
+ const plugin = (cordis) => {
349
+ cordis.inject([_agimon_ai_doompi_minor_mode.DOOM_MINOR_MODE_CATALOG_SERVICE], (context) => {
350
+ if (isProjectedChild) return void 0;
351
+ const catalog = (0, _agimon_ai_doompi_minor_mode.readMinorModeCatalog)(context);
352
+ if (!catalog) return void 0;
353
+ const refreshModes = () => {
354
+ minorModes = catalog.getSnapshot().modes.map(minorModeState);
355
+ refreshParentNamespace();
356
+ };
357
+ refreshModes();
358
+ return catalog.subscribe(refreshModes);
359
+ });
360
+ };
361
+ return {
362
+ plugin,
363
+ events: {
364
+ session_start: (_event, ctx) => {
365
+ if (!isProjectedChild) {
366
+ rootSessionId = stringValue(ctx.sessionManager.getSessionId());
367
+ refreshParentNamespace();
368
+ }
369
+ },
370
+ before_provider_request: (event, ctx) => {
371
+ const namespace = isProjectedChild ? projectedParentNamespace : refreshParentNamespace();
372
+ if (!namespace) return void 0;
373
+ const identity = modelIdentity(ctx, event.payload);
374
+ const modelFingerprint = createPromptCacheModelFingerprint(identity, sha256Base64Url);
375
+ const key = createPromptCacheKey(namespace, isProjectedChild ? "child" : "parent", modelFingerprint, sha256Base64Url, childProjection);
376
+ const rewritten = rewritePromptCacheKey(event.payload, identity.api, key, optimizerAllowsPromptCacheKey(optimizer));
377
+ dependencies.telemetry.beginRequest({
378
+ capability: classifyPromptCacheCapability(identity),
379
+ namespace,
380
+ modelFingerprint,
381
+ requestedRetention: requestedRetention(rewritten ?? event.payload),
382
+ ...rewritten ? { keySuffix: key.slice(-8) } : {}
383
+ });
384
+ return rewritten;
385
+ },
386
+ message_end: (event) => {
387
+ if (isErrorMessage(event.message)) return;
388
+ const usage = normalizePromptCacheUsage(event.message);
389
+ if (usage) dependencies.telemetry.observe(usage, dependencies.now());
390
+ }
391
+ },
392
+ dispose: () => {
393
+ parentNamespaceEnvironment.restore();
394
+ rootSessionEnvironment.restore();
395
+ dependencies.telemetry.reset();
396
+ }
397
+ };
398
+ }
399
+ //#endregion
400
+ //#region src/services/promptCacheTelemetry/index.ts
401
+ const DOOM_PROMPT_CACHE_TELEMETRY_SERVICE = "doom/prompt-cache-telemetry";
402
+ var PromptCacheTelemetryService = class extends _deepseek_ai_cordis.Service {
403
+ telemetry;
404
+ constructor(context, telemetry) {
405
+ super(context, DOOM_PROMPT_CACHE_TELEMETRY_SERVICE);
406
+ this.telemetry = telemetry;
407
+ }
408
+ snapshot() {
409
+ return this.telemetry.snapshot();
410
+ }
411
+ };
412
+ //#endregion
413
+ //#region src/extensions/workspaces/sessions/(backend)/root.cli.ts
414
+ var root_cli_default = (0, _agimon_ai_doompi_core_extension_file.defineRoot)(async ({ pi, options }) => {
415
+ const dependencies = options ?? {
416
+ telemetry: new PromptCacheTelemetry(),
417
+ now: Date.now
418
+ };
419
+ const optimizer = await Promise.resolve().then(() => require("../pi-cache-optimizer-BBOw28o_.cjs"));
420
+ if (typeof optimizer.default !== "function") throw new Error("Pi Cache Optimizer does not provide an extension factory.");
421
+ await optimizer.default(pi);
422
+ const runtime = createCacheRuntime(dependencies, optimizer);
423
+ return {
424
+ value: runtime,
425
+ services: [(context) => {
426
+ new PromptCacheTelemetryService(context, dependencies.telemetry);
427
+ }, runtime.plugin],
428
+ onDispose: () => runtime.dispose()
429
+ };
430
+ });
431
+ //#endregion
432
+ //#region src/extensions/workspaces/sessions/(backend)/resource/doompi-use-cache.cli.ts
433
+ var doompi_use_cache_cli_default = (0, _agimon_ai_doompi_core_extension_file.defineResource)({
434
+ source: PACKAGE_SOURCE,
435
+ moduleUrl: require("url").pathToFileURL(__filename).href,
436
+ skills: [CACHE_HELP_SKILL]
437
+ });
438
+ //#endregion
439
+ //#region generated/pi.ts
440
+ const at = (value, context) => typeof value === "function" ? value(context) : value;
441
+ const extension = (0, _agimon_ai_doompi_core_pi_extension.definePiExtension)("@agimon-ai/doompi-cache", async (context) => {
442
+ const scopeSession = await root_cli_default(context);
443
+ const contextSession = {
444
+ ...context,
445
+ root: scopeSession.value
446
+ };
447
+ return {
448
+ ...(0, _agimon_ai_doompi_core_extension_file.composeRootHooks)(scopeSession),
449
+ get resources() {
450
+ return [at(doompi_use_cache_cli_default, contextSession)];
451
+ },
452
+ services: [...scopeSession.services ?? []]
453
+ };
454
+ });
455
+ //#endregion
456
+ exports.default = extension;
457
+ exports.extension = extension;
458
+
2
459
  //# sourceMappingURL=pi.cjs.map