@agimon-ai/doompi-cache 0.0.1-alpha.7 → 0.0.1-alpha.71

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 (158) hide show
  1. package/README.md +7 -1
  2. package/dist/apiContracts.cjs +17 -0
  3. package/dist/apiContracts.cjs.map +1 -0
  4. package/dist/apiContracts.d.mts +53 -0
  5. package/dist/apiContracts.d.mts.map +1 -0
  6. package/dist/apiContracts.mjs +13 -0
  7. package/dist/apiContracts.mjs.map +1 -0
  8. package/dist/env.cjs +7 -1
  9. package/dist/env.d.mts +1 -1
  10. package/dist/env.mjs +2 -1
  11. package/dist/extensions/mcp.cjs +26 -0
  12. package/dist/extensions/mcp.cjs.map +1 -0
  13. package/dist/extensions/mcp.d.mts +5 -0
  14. package/dist/extensions/mcp.d.mts.map +1 -0
  15. package/dist/extensions/mcp.mjs +21 -0
  16. package/dist/extensions/mcp.mjs.map +1 -0
  17. package/dist/extensions/pi.cjs +458 -1
  18. package/dist/extensions/pi.cjs.map +1 -1
  19. package/dist/extensions/pi.d.mts +3 -4
  20. package/dist/extensions/pi.d.mts.map +1 -1
  21. package/dist/extensions/pi.mjs +453 -1
  22. package/dist/extensions/pi.mjs.map +1 -1
  23. package/dist/extensions/server.cjs +24 -0
  24. package/dist/extensions/server.cjs.map +1 -0
  25. package/dist/extensions/server.d.mts +5 -0
  26. package/dist/extensions/server.d.mts.map +1 -0
  27. package/dist/extensions/server.mjs +19 -0
  28. package/dist/extensions/server.mjs.map +1 -0
  29. package/dist/index.cjs +22 -1
  30. package/dist/index.d.mts +7 -7
  31. package/dist/index.mjs +7 -1
  32. package/dist/pi-cache-optimizer-5NIMHAtT.cjs +8579 -0
  33. package/dist/pi-cache-optimizer-5NIMHAtT.cjs.map +1 -0
  34. package/dist/pi-cache-optimizer-EMbP1t9X.mjs +8578 -0
  35. package/dist/pi-cache-optimizer-EMbP1t9X.mjs.map +1 -0
  36. package/dist/src/constants/environment.cjs +14 -0
  37. package/dist/src/constants/environment.cjs.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.mts → src/models/promptCacheTelemetry.d.mts} +3 -4
  57. package/dist/src/models/promptCacheTelemetry.d.mts.map +1 -0
  58. package/dist/src/models/promptCacheTelemetry.mjs +45 -0
  59. package/dist/src/models/promptCacheTelemetry.mjs.map +1 -0
  60. package/dist/src/services/canonical/index.cjs +28 -0
  61. package/dist/src/services/canonical/index.cjs.map +1 -0
  62. package/dist/src/services/canonical/index.d.mts +9 -0
  63. package/dist/src/services/canonical/index.d.mts.map +1 -0
  64. package/dist/src/services/canonical/index.mjs +27 -0
  65. package/dist/src/services/canonical/index.mjs.map +1 -0
  66. package/dist/src/services/digest/index.cjs +9 -0
  67. package/dist/src/services/digest/index.cjs.map +1 -0
  68. package/dist/src/services/digest/index.d.mts +4 -0
  69. package/dist/src/services/digest/index.d.mts.map +1 -0
  70. package/dist/src/services/digest/index.mjs +9 -0
  71. package/dist/src/services/digest/index.mjs.map +1 -0
  72. package/dist/src/services/namespace/index.cjs +78 -0
  73. package/dist/src/services/namespace/index.cjs.map +1 -0
  74. package/dist/src/services/namespace/index.d.mts +9 -0
  75. package/dist/src/services/namespace/index.d.mts.map +1 -0
  76. package/dist/src/services/namespace/index.mjs +74 -0
  77. package/dist/src/services/namespace/index.mjs.map +1 -0
  78. package/dist/src/services/promptCacheTelemetry/index.cjs +22 -0
  79. package/dist/src/services/promptCacheTelemetry/index.cjs.map +1 -0
  80. package/dist/src/services/promptCacheTelemetry/index.d.mts +17 -0
  81. package/dist/src/services/promptCacheTelemetry/index.d.mts.map +1 -0
  82. package/dist/src/services/promptCacheTelemetry/index.mjs +20 -0
  83. package/dist/src/services/promptCacheTelemetry/index.mjs.map +1 -0
  84. package/dist/src/services/providerPolicy/index.cjs +43 -0
  85. package/dist/src/services/providerPolicy/index.cjs.map +1 -0
  86. package/dist/src/services/providerPolicy/index.d.mts +7 -0
  87. package/dist/src/services/providerPolicy/index.d.mts.map +1 -0
  88. package/dist/src/services/providerPolicy/index.mjs +41 -0
  89. package/dist/src/services/providerPolicy/index.mjs.map +1 -0
  90. package/dist/{types → src/types}/cache.d.mts +11 -12
  91. package/dist/src/types/cache.d.mts.map +1 -0
  92. package/package.json +40 -14
  93. package/dist/adapters/node/digest.cjs +0 -2
  94. package/dist/adapters/node/digest.cjs.map +0 -1
  95. package/dist/adapters/node/digest.d.cts +0 -5
  96. package/dist/adapters/node/digest.d.cts.map +0 -1
  97. package/dist/adapters/node/digest.d.mts +0 -5
  98. package/dist/adapters/node/digest.d.mts.map +0 -1
  99. package/dist/adapters/node/digest.mjs +0 -2
  100. package/dist/adapters/node/digest.mjs.map +0 -1
  101. package/dist/env.d.cts +0 -2
  102. package/dist/extensions/pi.d.cts +0 -43
  103. package/dist/extensions/pi.d.cts.map +0 -1
  104. package/dist/index.d.cts +0 -8
  105. package/dist/pi-cache-optimizer-B7B911Pz.cjs +0 -54
  106. package/dist/pi-cache-optimizer-B7B911Pz.cjs.map +0 -1
  107. package/dist/pi-cache-optimizer-CjPVk06Q.mjs +0 -54
  108. package/dist/pi-cache-optimizer-CjPVk06Q.mjs.map +0 -1
  109. package/dist/providers/promptCacheTelemetry.cjs +0 -2
  110. package/dist/providers/promptCacheTelemetry.cjs.map +0 -1
  111. package/dist/providers/promptCacheTelemetry.d.cts +0 -18
  112. package/dist/providers/promptCacheTelemetry.d.cts.map +0 -1
  113. package/dist/providers/promptCacheTelemetry.d.mts +0 -18
  114. package/dist/providers/promptCacheTelemetry.d.mts.map +0 -1
  115. package/dist/providers/promptCacheTelemetry.mjs +0 -2
  116. package/dist/providers/promptCacheTelemetry.mjs.map +0 -1
  117. package/dist/services/canonical.cjs +0 -2
  118. package/dist/services/canonical.cjs.map +0 -1
  119. package/dist/services/canonical.d.cts +0 -10
  120. package/dist/services/canonical.d.cts.map +0 -1
  121. package/dist/services/canonical.d.mts +0 -10
  122. package/dist/services/canonical.d.mts.map +0 -1
  123. package/dist/services/canonical.mjs +0 -2
  124. package/dist/services/canonical.mjs.map +0 -1
  125. package/dist/services/namespace.cjs +0 -2
  126. package/dist/services/namespace.cjs.map +0 -1
  127. package/dist/services/namespace.d.cts +0 -10
  128. package/dist/services/namespace.d.cts.map +0 -1
  129. package/dist/services/namespace.d.mts +0 -10
  130. package/dist/services/namespace.d.mts.map +0 -1
  131. package/dist/services/namespace.mjs +0 -2
  132. package/dist/services/namespace.mjs.map +0 -1
  133. package/dist/services/providerPolicy.cjs +0 -2
  134. package/dist/services/providerPolicy.cjs.map +0 -1
  135. package/dist/services/providerPolicy.d.cts +0 -8
  136. package/dist/services/providerPolicy.d.cts.map +0 -1
  137. package/dist/services/providerPolicy.d.mts +0 -8
  138. package/dist/services/providerPolicy.d.mts.map +0 -1
  139. package/dist/services/providerPolicy.mjs +0 -2
  140. package/dist/services/providerPolicy.mjs.map +0 -1
  141. package/dist/services/telemetry.cjs +0 -2
  142. package/dist/services/telemetry.cjs.map +0 -1
  143. package/dist/services/telemetry.d.cts +0 -13
  144. package/dist/services/telemetry.d.cts.map +0 -1
  145. package/dist/services/telemetry.d.mts.map +0 -1
  146. package/dist/services/telemetry.mjs +0 -2
  147. package/dist/services/telemetry.mjs.map +0 -1
  148. package/dist/types/cache.d.cts +0 -68
  149. package/dist/types/cache.d.cts.map +0 -1
  150. package/dist/types/cache.d.mts.map +0 -1
  151. package/dist/types/environment.cjs +0 -2
  152. package/dist/types/environment.cjs.map +0 -1
  153. package/dist/types/environment.d.cts +0 -9
  154. package/dist/types/environment.d.cts.map +0 -1
  155. package/dist/types/environment.d.mts +0 -9
  156. package/dist/types/environment.d.mts.map +0 -1
  157. package/dist/types/environment.mjs +0 -2
  158. package/dist/types/environment.mjs.map +0 -1
@@ -1,4 +1,3 @@
1
- import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
1
  //#region src/types/cache.d.ts
3
2
  type PromptCacheCapabilityClass = 'key-and-long-retention' | 'key-only' | 'marker-only' | 'automatic' | 'unknown';
4
3
  interface PromptCacheUsage {
@@ -36,8 +35,8 @@ interface CacheExtensionDependencies {
36
35
  readonly now: () => number;
37
36
  }
38
37
  //#endregion
39
- //#region src/adapters/pi/extension.d.ts
40
- declare function activateCacheExtension(pi: ExtensionAPI, dependencies?: CacheExtensionDependencies): Promise<void>;
38
+ //#region generated/pi.d.ts
39
+ export declare const extension: import("@agimon-ai/doompi-core/runtimePiExtension").DefinedPiExtension<CacheExtensionDependencies>;
41
40
  //#endregion
42
- export { activateCacheExtension, activateCacheExtension as default };
41
+ export { extension as default };
43
42
  //# sourceMappingURL=pi.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pi.d.mts","names":[],"sources":["../../src/types/cache.ts","../../src/types/extension.ts","../../src/adapters/pi/extension.ts"],"mappings":";;KAAY;UA+CK;WACN;WACA;WACA;;UAGM,+BAA+B;WACrC;WACA;WACA;;UAGM;WACN,YAAY;WACZ;WACA;WACA;WACA;;UAGM,qCAAqC;WAC3C;WACA,uBAAuB;WACvB,kBAAkB;;UAGZ;EACf,aAAa,QAAQ;EACrB,QAAQ,OAAO,kBAAkB;EACjC,YAAY;EACZ;;;;UC3Ee;WACN,WAAW;WACX;;;;iBC2MW,uBACpB,IAAI,cACJ,eAAc,6BACb"}
1
+ {"version":3,"file":"pi.d.mts","names":[],"sources":["../../src/types/cache.ts","../../src/types/extension.ts","../../generated/pi.ts"],"mappings":";KAAY;UA+CK;WACN;WACA;WACA;;UAGM,+BAA+B;WACrC;WACA;WACA;;UAGM;WACN,YAAY;WACZ;WACA;WACA;WACA;;UAGM,qCAAqC;WAC3C;WACA,uBAAuB;WACvB,kBAAkB;;UAGZ;EACf,aAAa,QAAQ;EACrB,QAAQ,OAAO,kBAAkB;EACjC,YAAY;EACZ;;;;UC3Ee;WACN,WAAW;WACX;;;;qBCaE,+DAAS,mBAAT"}
@@ -1,2 +1,454 @@
1
- import{getHarnessState as e}from"@agimon-ai/doompi-config/harnessStore";import{connectDoomCordisHost as t}from"@agimon-ai/doompi-extension-contracts/cordis-host";import{DOOM_HELP_SERVICE as n,requireDoomHelpService as r}from"@agimon-ai/doompi-extension-contracts/help";import{DOOM_MINOR_MODE_CATALOG_SERVICE as i,readMinorModeCatalog as a}from"@agimon-ai/doompi-extension-contracts/mode";import{createHash as o}from"node:crypto";import{Service as s}from"@deepseek-ai/cordis";var c=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 l(e={}){return{telemetry:e.telemetry??new c,now:e.now??Date.now}}var u=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 d(e){return o(`sha256`).update(e).digest(`base64url`)}var f=class extends s{telemetry;constructor(e,t){super(e,`doom/prompt-cache-telemetry`),this.telemetry=t}snapshot(){return this.telemetry.snapshot()}};function p(e){if(!Number.isFinite(e))throw Error(`Prompt cache identity cannot contain a non-finite number.`);return Object.is(e,-0)?0:e}function m(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 p(e);if(Array.isArray(e))return e.map(e=>m(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`)]=m(r))}return n}function h(e){return JSON.stringify(m(e))}function g(e,t,n){return`${e}${n(h(t))}`}function _(e){return e?.trim().replaceAll(`\\`,`/`)||void 0}function v(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 y(e,t){return g(`dpr1_`,{version:1,rootSessionId:e},t)}function b(e,t){return g(`dpn1_`,{version:1,rootSession:y(e.rootSessionId,t),compositionFingerprint:e.compositionFingerprint??null,majorMode:e.majorMode,domains:[...e.domains],profile:e.profile??null,persona:_(e.persona)??null,minorModes:v(e.minorModes)},t)}function x(e,t){return g(`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 S(e,t,n,r,i){return g(`dpc1_`,{version:1,parentNamespace:e,scope:t,childProjection:i??null,modelFingerprint:n},r)}function C(e){let t=e.__internals_for_tests;return typeof t?.isRuntimeOptimizerEnabled==`function`&&typeof t.shouldInjectOpenAIPromptCacheKey==`function`&&t.isRuntimeOptimizerEnabled()&&t.shouldInjectOpenAIPromptCacheKey()}const w=new Set([`openai-completions`,`openai-responses`,`openai-codex-responses`,`azure-openai-responses`]),T=new Set([`anthropic-messages`,`bedrock-converse-stream`]),E=new Set([`google-generative-ai`,`google-vertex`,`google-vertex-anthropic`]);function D(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function O(e){return e.api===`openai-responses`||e.api===`openai-completions`?e.virtualProvider===`openai`?`key-and-long-retention`:`key-only`:e.api&&w.has(e.api)?`key-only`:e.api&&T.has(e.api)?`marker-only`:e.api&&E.has(e.api)?`automatic`:`unknown`}function k(e,t,n,r){if(!r||!t||!w.has(t)||!D(e))return;let i=e.prompt_cache_key;if(!(typeof i!=`string`||!i.trim()||i===n))return{...e,prompt_cache_key:n}}function A(e){if(!D(e))return;let t=e.prompt_cache_retention;return typeof t==`string`&&t.trim()?t.trim():void 0}function j(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:void 0}function M(e){return typeof e==`number`&&Number.isFinite(e)&&e>=0?e:void 0}function N(...e){for(let t of e){let e=M(t);if(e!==void 0)return e}}function P(e){let t=M(e.cacheRead),n=M(e.cacheWrite);if(t===void 0&&n===void 0)return;let r=M(e.input)??0;return{cacheRead:t??0,cacheWrite:n??0,totalInput:r+(t??0)+(n??0)}}function F(e){let t=j(e.prompt_tokens_details)??j(e.promptTokensDetails),n=j(e.input_tokens_details)??j(e.inputTokensDetails),r=N(t?.cached_tokens,t?.cachedTokens,n?.cached_tokens,n?.cachedTokens),i=N(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=N(e.prompt_tokens,e.promptTokens,e.input_tokens,e.inputTokens);return{cacheRead:r??0,cacheWrite:i??0,totalInput:Math.max(o??a,a)}}function I(e){let t=N(e.cache_read_input_tokens,e.cacheReadInputTokens),n=N(e.cache_creation_input_tokens,e.cacheCreationInputTokens);if(t===void 0&&n===void 0)return;let r=N(e.input_tokens,e.inputTokens)??0;return{cacheRead:t??0,cacheWrite:n??0,totalInput:r+(t??0)+(n??0)}}function L(e){let t=j(e.usage_metadata)??j(e.usageMetadata)??e,n=N(t.cachedContentTokenCount,t.cached_content_token_count);if(n===void 0)return;let r=N(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 R(e){let t=j(j(e)?.usage);if(t)return P(t)??F(t)??I(t)??L(t)}const z=`DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE`,B=`@agimon-ai/doompi-cache`;function V(e){return typeof e==`string`&&e.trim()?e.trim():void 0}function H(e){return typeof e==`object`&&e&&!Array.isArray(e)?e:void 0}function U(e){let t=e.state;return{source:e.descriptor.source,id:e.descriptor.id,activation:t.activation,...t.modelContextVariant?{modelContextVariant:t.modelContextVariant}:{}}}function W(e,t){let n=H(e.model),r=H(t);return{virtualProvider:V(n?.provider),virtualModel:V(n?.id),api:V(n?.api),baseUrl:V(n?.baseUrl),wireModel:V(r?.model)}}function G(e){let t=H(e);return t?.stopReason===`error`||t?.stopReason===`aborted`}function K(e){return A(e)??(process.env.PI_CACHE_RETENTION===`long`?`long`:void 0)}function q(t,n,r,o){let s=new u(z),c=new u(`DOOMPI_PROMPT_CACHE_ROOT_SESSION`),l=V(process.env[z]),f=V(process.env.DOOMPI_PROMPT_CACHE_CHILD_PROJECTION),p=!!(l&&f),m,h=l,g=[],_=()=>{if(p)return h;if(!m)return;let t=e();return h=b({rootSessionId:m,compositionFingerprint:t.compositionFingerprint,majorMode:t.majorMode,domains:t.domains,profile:t.profile,persona:t.personaFile,minorModes:g},d),s.set(h),c.set(y(m,d)),h};return t.inject([i],e=>{if(p)return;let t=a(e);if(!t)return;let n=()=>{g=t.getSnapshot().modes.map(U),_()};return n(),t.subscribe(n)}),n.on(`session_start`,(e,t)=>{p||(m=V(t.sessionManager.getSessionId()),_())}),n.on(`before_provider_request`,(e,t)=>{let n=p?l:_();if(!n)return;let i=W(t,e.payload),a=x(i,d),s=S(n,p?`child`:`parent`,a,d,f),c=k(e.payload,i.api,s,C(o));return r.telemetry.beginRequest({capability:O(i),namespace:n,modelFingerprint:a,requestedRetention:K(c??e.payload),...c?{keySuffix:s.slice(-8)}:{}}),c}),n.on(`message_end`,e=>{if(G(e.message))return;let t=R(e.message);t&&r.telemetry.observe(t,r.now())}),()=>{s.restore(),c.restore(),r.telemetry.reset()}}function J(e,t){e.inject([n],e=>{let t=r(e).register({source:B,moduleUrl:import.meta.url,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 f(e,t.dependencies.telemetry),yield q(e,t.pi,t.dependencies,t.optimizer)},B)}async function Y(e,n=l()){let r=await import(`../pi-cache-optimizer-CjPVk06Q.mjs`);if(typeof r.default!=`function`)throw Error(`Pi Cache Optimizer does not export an extension factory.`);await r.default(e);let i=await t(e,B),a=i.root.plugin(J,{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()}})())}export{Y as activateCacheExtension,Y as default};
1
+ import { definePiExtension } from "@agimon-ai/doompi-core/piExtension";
2
+ import { composeRootHooks, defineResource, defineRoot } from "@agimon-ai/doompi-core/extensionFile";
3
+ import { getHarnessState } from "@agimon-ai/doompi-config/harnessStore";
4
+ import { DOOM_MINOR_MODE_CATALOG_SERVICE, readMinorModeCatalog } from "@agimon-ai/doompi-minor-mode";
5
+ import { createHash } from "node:crypto";
6
+ import { Service } from "@deepseek-ai/cordis";
7
+ //#region src/models/promptCacheTelemetry.ts
8
+ const DEFAULT_OBSERVATION_LIMIT = 64;
9
+ var PromptCacheTelemetry = class {
10
+ #limit;
11
+ #request = { capability: "unknown" };
12
+ #observations = [];
13
+ constructor(limit = DEFAULT_OBSERVATION_LIMIT) {
14
+ if (!Number.isInteger(limit) || limit < 1) throw new Error("Prompt cache telemetry limit must be a positive integer.");
15
+ this.#limit = limit;
16
+ }
17
+ beginRequest(status) {
18
+ this.#request = { ...status };
19
+ }
20
+ observe(usage, observedAt) {
21
+ const namespace = this.#request.namespace;
22
+ const modelFingerprint = this.#request.modelFingerprint;
23
+ if (!namespace || !modelFingerprint) return;
24
+ this.#observations.push({
25
+ namespace,
26
+ modelFingerprint,
27
+ cacheRead: usage.cacheRead,
28
+ cacheWrite: usage.cacheWrite,
29
+ totalInput: usage.totalInput,
30
+ observedAt
31
+ });
32
+ if (this.#observations.length > this.#limit) this.#observations.splice(0, this.#observations.length - this.#limit);
33
+ }
34
+ snapshot() {
35
+ const observations = [...this.#observations];
36
+ return {
37
+ ...this.#request,
38
+ residency: "unknown",
39
+ observations,
40
+ ...observations.length > 0 ? { lastObservation: observations.at(-1) } : {}
41
+ };
42
+ }
43
+ reset() {
44
+ this.#request = { capability: "unknown" };
45
+ this.#observations = [];
46
+ }
47
+ };
48
+ //#endregion
49
+ //#region src/constants/cache.ts
50
+ const PACKAGE_SOURCE = "@agimon-ai/doompi-cache";
51
+ const CACHE_HELP_SKILL = {
52
+ name: "doompi-use-cache",
53
+ description: "Inspect DoomPi provider prompt cache policy, routing identity, and provider-observed usage."
54
+ };
55
+ //#endregion
56
+ //#region src/constants/environment.ts
57
+ const DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV = "DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE";
58
+ const DOOMPI_PROMPT_CACHE_ROOT_SESSION_ENV = "DOOMPI_PROMPT_CACHE_ROOT_SESSION";
59
+ const DOOMPI_PROMPT_CACHE_CHILD_PROJECTION_ENV = "DOOMPI_PROMPT_CACHE_CHILD_PROJECTION";
60
+ //#endregion
61
+ //#region src/services/digest/index.ts
62
+ function sha256Base64Url(value) {
63
+ return createHash("sha256").update(value).digest("base64url");
64
+ }
65
+ //#endregion
66
+ //#region src/services/environment/index.ts
67
+ var OwnedEnvironmentValue = class {
68
+ #environment;
69
+ #name;
70
+ #baseline;
71
+ #ownedValue;
72
+ constructor(name, environment = process.env) {
73
+ this.#name = name;
74
+ this.#environment = environment;
75
+ this.#baseline = {
76
+ present: Object.hasOwn(environment, name),
77
+ value: environment[name]
78
+ };
79
+ }
80
+ set(value) {
81
+ this.#environment[this.#name] = value;
82
+ this.#ownedValue = value;
83
+ }
84
+ restore() {
85
+ if (this.#ownedValue === void 0 || this.#environment[this.#name] !== this.#ownedValue) return;
86
+ if (this.#baseline.present) this.#environment[this.#name] = this.#baseline.value;
87
+ else delete this.#environment[this.#name];
88
+ this.#ownedValue = void 0;
89
+ }
90
+ };
91
+ //#endregion
92
+ //#region src/services/canonical/index.ts
93
+ function canonicalNumber(value) {
94
+ if (!Number.isFinite(value)) throw new Error("Prompt cache identity cannot contain a non-finite number.");
95
+ return Object.is(value, -0) ? 0 : value;
96
+ }
97
+ function canonicalValue(value) {
98
+ if (value === null) return null;
99
+ if (typeof value === "string") return value.normalize("NFC");
100
+ if (typeof value === "boolean") return value;
101
+ if (typeof value === "number") return canonicalNumber(value);
102
+ if (Array.isArray(value)) return value.map((entry) => canonicalValue(entry));
103
+ if (typeof value !== "object") throw new Error(`Unsupported prompt cache identity value: ${typeof value}.`);
104
+ const record = value;
105
+ const result = {};
106
+ for (const key of Object.keys(record).sort((left, right) => left.localeCompare(right))) {
107
+ const entry = record[key];
108
+ if (entry !== void 0) result[key.normalize("NFC")] = canonicalValue(entry);
109
+ }
110
+ return result;
111
+ }
112
+ function canonicalJson(value) {
113
+ return JSON.stringify(canonicalValue(value));
114
+ }
115
+ //#endregion
116
+ //#region src/services/namespace/index.ts
117
+ const KEY_PREFIX = "dpc1_";
118
+ const PARENT_PREFIX = "dpn1_";
119
+ const ROOT_PREFIX = "dpr1_";
120
+ const MODEL_PREFIX = "dpm1_";
121
+ function digestIdentity(prefix, value, digest) {
122
+ return `${prefix}${digest(canonicalJson(value))}`;
123
+ }
124
+ function normalizedPersona(value) {
125
+ return value?.trim().replaceAll("\\", "/") || void 0;
126
+ }
127
+ function activeMinorModes(modes) {
128
+ return modes.filter(({ activation }) => activation === "active" || activation === "activating").map(({ source, id, modelContextVariant }) => ({
129
+ source,
130
+ id,
131
+ ...modelContextVariant ? { modelContextVariant } : {}
132
+ })).sort((left, right) => left.source.localeCompare(right.source) || left.id.localeCompare(right.id));
133
+ }
134
+ function createRootSessionIdentity(rootSessionId, digest) {
135
+ return digestIdentity(ROOT_PREFIX, {
136
+ version: 1,
137
+ rootSessionId
138
+ }, digest);
139
+ }
140
+ function createParentPromptCacheNamespace(state, digest) {
141
+ return digestIdentity(PARENT_PREFIX, {
142
+ version: 1,
143
+ rootSession: createRootSessionIdentity(state.rootSessionId, digest),
144
+ compositionFingerprint: state.compositionFingerprint ?? null,
145
+ majorMode: state.majorMode,
146
+ domains: [...state.domains],
147
+ profile: state.profile ?? null,
148
+ persona: normalizedPersona(state.persona) ?? null,
149
+ minorModes: activeMinorModes(state.minorModes)
150
+ }, digest);
151
+ }
152
+ function createPromptCacheModelFingerprint(model, digest) {
153
+ return digestIdentity(MODEL_PREFIX, {
154
+ version: 1,
155
+ virtualProvider: model.virtualProvider ?? null,
156
+ virtualModel: model.virtualModel ?? null,
157
+ api: model.api ?? null,
158
+ baseUrl: model.baseUrl ?? null,
159
+ wireModel: model.wireModel ?? null
160
+ }, digest);
161
+ }
162
+ function createPromptCacheKey(parentNamespace, scope, modelFingerprint, digest, childProjection) {
163
+ return digestIdentity(KEY_PREFIX, {
164
+ version: 1,
165
+ parentNamespace,
166
+ scope,
167
+ childProjection: childProjection ?? null,
168
+ modelFingerprint
169
+ }, digest);
170
+ }
171
+ //#endregion
172
+ //#region src/services/optimizerPolicy/index.ts
173
+ /** Fail closed unless the pinned optimizer confirms both runtime and key routing are enabled. */
174
+ function optimizerAllowsPromptCacheKey(optimizer) {
175
+ const internals = optimizer.__internals_for_tests;
176
+ return typeof internals?.isRuntimeOptimizerEnabled === "function" && typeof internals.shouldInjectOpenAIPromptCacheKey === "function" && internals.isRuntimeOptimizerEnabled() && internals.shouldInjectOpenAIPromptCacheKey();
177
+ }
178
+ //#endregion
179
+ //#region src/services/promptCacheUsage/index.ts
180
+ function recordValue$1(value) {
181
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
182
+ }
183
+ function nonNegativeNumber(value) {
184
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
185
+ }
186
+ function firstNumber(...values) {
187
+ for (const value of values) {
188
+ const number = nonNegativeNumber(value);
189
+ if (number !== void 0) return number;
190
+ }
191
+ }
192
+ function normalizedUsage(usage) {
193
+ const cacheRead = nonNegativeNumber(usage.cacheRead);
194
+ const cacheWrite = nonNegativeNumber(usage.cacheWrite);
195
+ if (cacheRead === void 0 && cacheWrite === void 0) return void 0;
196
+ const input = nonNegativeNumber(usage.input) ?? 0;
197
+ return {
198
+ cacheRead: cacheRead ?? 0,
199
+ cacheWrite: cacheWrite ?? 0,
200
+ totalInput: input + (cacheRead ?? 0) + (cacheWrite ?? 0)
201
+ };
202
+ }
203
+ function openAiUsage(usage) {
204
+ const promptDetails = recordValue$1(usage.prompt_tokens_details) ?? recordValue$1(usage.promptTokensDetails);
205
+ const inputDetails = recordValue$1(usage.input_tokens_details) ?? recordValue$1(usage.inputTokensDetails);
206
+ const cacheRead = firstNumber(promptDetails?.cached_tokens, promptDetails?.cachedTokens, inputDetails?.cached_tokens, inputDetails?.cachedTokens);
207
+ const cacheWrite = firstNumber(promptDetails?.cache_write_tokens, promptDetails?.cacheWriteTokens, inputDetails?.cache_write_tokens, inputDetails?.cacheWriteTokens);
208
+ if (cacheRead === void 0 && cacheWrite === void 0) return void 0;
209
+ const floor = (cacheRead ?? 0) + (cacheWrite ?? 0);
210
+ const reportedTotal = firstNumber(usage.prompt_tokens, usage.promptTokens, usage.input_tokens, usage.inputTokens);
211
+ return {
212
+ cacheRead: cacheRead ?? 0,
213
+ cacheWrite: cacheWrite ?? 0,
214
+ totalInput: Math.max(reportedTotal ?? floor, floor)
215
+ };
216
+ }
217
+ function anthropicUsage(usage) {
218
+ const cacheRead = firstNumber(usage.cache_read_input_tokens, usage.cacheReadInputTokens);
219
+ const cacheWrite = firstNumber(usage.cache_creation_input_tokens, usage.cacheCreationInputTokens);
220
+ if (cacheRead === void 0 && cacheWrite === void 0) return void 0;
221
+ const input = firstNumber(usage.input_tokens, usage.inputTokens) ?? 0;
222
+ return {
223
+ cacheRead: cacheRead ?? 0,
224
+ cacheWrite: cacheWrite ?? 0,
225
+ totalInput: input + (cacheRead ?? 0) + (cacheWrite ?? 0)
226
+ };
227
+ }
228
+ function geminiUsage(usage) {
229
+ const metadata = recordValue$1(usage.usage_metadata) ?? recordValue$1(usage.usageMetadata) ?? usage;
230
+ const cacheRead = firstNumber(metadata.cachedContentTokenCount, metadata.cached_content_token_count);
231
+ if (cacheRead === void 0) return void 0;
232
+ const totalInput = firstNumber(metadata.promptTokenCount, metadata.prompt_token_count, usage.input_tokens, usage.inputTokens, usage.prompt_tokens, usage.promptTokens);
233
+ return {
234
+ cacheRead,
235
+ cacheWrite: 0,
236
+ totalInput: Math.max(totalInput ?? cacheRead, cacheRead)
237
+ };
238
+ }
239
+ /** Normalize only usage values carried by a provider-produced assistant message. */
240
+ function normalizePromptCacheUsage(message) {
241
+ const usage = recordValue$1(recordValue$1(message)?.usage);
242
+ if (!usage) return void 0;
243
+ return normalizedUsage(usage) ?? openAiUsage(usage) ?? anthropicUsage(usage) ?? geminiUsage(usage);
244
+ }
245
+ //#endregion
246
+ //#region src/services/providerPolicy/index.ts
247
+ const ROUTING_KEY_APIS = /* @__PURE__ */ new Set([
248
+ "openai-completions",
249
+ "openai-responses",
250
+ "openai-codex-responses",
251
+ "azure-openai-responses"
252
+ ]);
253
+ const MARKER_APIS = /* @__PURE__ */ new Set(["anthropic-messages", "bedrock-converse-stream"]);
254
+ const AUTOMATIC_APIS = /* @__PURE__ */ new Set([
255
+ "google-generative-ai",
256
+ "google-vertex",
257
+ "google-vertex-anthropic"
258
+ ]);
259
+ function isRecord(value) {
260
+ return typeof value === "object" && value !== null && !Array.isArray(value);
261
+ }
262
+ function classifyPromptCacheCapability(model) {
263
+ if (model.api === "openai-responses" || model.api === "openai-completions") return model.virtualProvider === "openai" ? "key-and-long-retention" : "key-only";
264
+ if (model.api && ROUTING_KEY_APIS.has(model.api)) return "key-only";
265
+ if (model.api && MARKER_APIS.has(model.api)) return "marker-only";
266
+ if (model.api && AUTOMATIC_APIS.has(model.api)) return "automatic";
267
+ return "unknown";
268
+ }
269
+ function rewritePromptCacheKey(payload, api, key, enabled) {
270
+ if (!enabled || !api || !ROUTING_KEY_APIS.has(api) || !isRecord(payload)) return void 0;
271
+ const current = payload.prompt_cache_key;
272
+ if (typeof current !== "string" || !current.trim() || current === key) return void 0;
273
+ return {
274
+ ...payload,
275
+ prompt_cache_key: key
276
+ };
277
+ }
278
+ function requestedPromptCacheRetention(payload) {
279
+ if (!isRecord(payload)) return void 0;
280
+ const retention = payload.prompt_cache_retention;
281
+ return typeof retention === "string" && retention.trim() ? retention.trim() : void 0;
282
+ }
283
+ //#endregion
284
+ //#region src/services/cacheRuntime/index.ts
285
+ function stringValue(value) {
286
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
287
+ }
288
+ function recordValue(value) {
289
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
290
+ }
291
+ function minorModeState(record) {
292
+ const state = record.state;
293
+ return {
294
+ source: record.descriptor.source,
295
+ id: record.descriptor.id,
296
+ activation: state.activation,
297
+ ...state.modelContextVariant ? { modelContextVariant: state.modelContextVariant } : {}
298
+ };
299
+ }
300
+ function modelIdentity(ctx, payload) {
301
+ const model = recordValue(ctx.model);
302
+ const request = recordValue(payload);
303
+ return {
304
+ virtualProvider: stringValue(model?.provider),
305
+ virtualModel: stringValue(model?.id),
306
+ api: stringValue(model?.api),
307
+ baseUrl: stringValue(model?.baseUrl),
308
+ wireModel: stringValue(request?.model)
309
+ };
310
+ }
311
+ function isErrorMessage(message) {
312
+ const record = recordValue(message);
313
+ return record?.stopReason === "error" || record?.stopReason === "aborted";
314
+ }
315
+ function requestedRetention(payload) {
316
+ return requestedPromptCacheRetention(payload) ?? (process.env["PI_CACHE_RETENTION"] === "long" ? "long" : void 0);
317
+ }
318
+ function createCacheRuntime(dependencies, optimizer) {
319
+ const parentNamespaceEnvironment = new OwnedEnvironmentValue(DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV);
320
+ const rootSessionEnvironment = new OwnedEnvironmentValue(DOOMPI_PROMPT_CACHE_ROOT_SESSION_ENV);
321
+ const projectedParentNamespace = stringValue(process.env[DOOMPI_PROMPT_CACHE_PARENT_NAMESPACE_ENV]);
322
+ const childProjection = stringValue(process.env[DOOMPI_PROMPT_CACHE_CHILD_PROJECTION_ENV]);
323
+ const isProjectedChild = Boolean(projectedParentNamespace && childProjection);
324
+ let rootSessionId;
325
+ let parentNamespace = projectedParentNamespace;
326
+ let minorModes = [];
327
+ const refreshParentNamespace = () => {
328
+ if (isProjectedChild) return parentNamespace;
329
+ if (!rootSessionId) return void 0;
330
+ const harness = getHarnessState();
331
+ parentNamespace = createParentPromptCacheNamespace({
332
+ rootSessionId,
333
+ compositionFingerprint: harness.compositionFingerprint,
334
+ majorMode: harness.majorMode,
335
+ domains: harness.domains,
336
+ profile: harness.profile,
337
+ persona: harness.personaFile,
338
+ minorModes
339
+ }, sha256Base64Url);
340
+ parentNamespaceEnvironment.set(parentNamespace);
341
+ rootSessionEnvironment.set(createRootSessionIdentity(rootSessionId, sha256Base64Url));
342
+ return parentNamespace;
343
+ };
344
+ const plugin = (cordis) => {
345
+ cordis.inject([DOOM_MINOR_MODE_CATALOG_SERVICE], (context) => {
346
+ if (isProjectedChild) return void 0;
347
+ const catalog = readMinorModeCatalog(context);
348
+ if (!catalog) return void 0;
349
+ const refreshModes = () => {
350
+ minorModes = catalog.getSnapshot().modes.map(minorModeState);
351
+ refreshParentNamespace();
352
+ };
353
+ refreshModes();
354
+ return catalog.subscribe(refreshModes);
355
+ });
356
+ };
357
+ return {
358
+ plugin,
359
+ events: {
360
+ session_start: (_event, ctx) => {
361
+ if (!isProjectedChild) {
362
+ rootSessionId = stringValue(ctx.sessionManager.getSessionId());
363
+ refreshParentNamespace();
364
+ }
365
+ },
366
+ before_provider_request: (event, ctx) => {
367
+ const namespace = isProjectedChild ? projectedParentNamespace : refreshParentNamespace();
368
+ if (!namespace) return void 0;
369
+ const identity = modelIdentity(ctx, event.payload);
370
+ const modelFingerprint = createPromptCacheModelFingerprint(identity, sha256Base64Url);
371
+ const key = createPromptCacheKey(namespace, isProjectedChild ? "child" : "parent", modelFingerprint, sha256Base64Url, childProjection);
372
+ const rewritten = rewritePromptCacheKey(event.payload, identity.api, key, optimizerAllowsPromptCacheKey(optimizer));
373
+ dependencies.telemetry.beginRequest({
374
+ capability: classifyPromptCacheCapability(identity),
375
+ namespace,
376
+ modelFingerprint,
377
+ requestedRetention: requestedRetention(rewritten ?? event.payload),
378
+ ...rewritten ? { keySuffix: key.slice(-8) } : {}
379
+ });
380
+ return rewritten;
381
+ },
382
+ message_end: (event) => {
383
+ if (isErrorMessage(event.message)) return;
384
+ const usage = normalizePromptCacheUsage(event.message);
385
+ if (usage) dependencies.telemetry.observe(usage, dependencies.now());
386
+ }
387
+ },
388
+ dispose: () => {
389
+ parentNamespaceEnvironment.restore();
390
+ rootSessionEnvironment.restore();
391
+ dependencies.telemetry.reset();
392
+ }
393
+ };
394
+ }
395
+ //#endregion
396
+ //#region src/services/promptCacheTelemetry/index.ts
397
+ const DOOM_PROMPT_CACHE_TELEMETRY_SERVICE = "doom/prompt-cache-telemetry";
398
+ var PromptCacheTelemetryService = class extends Service {
399
+ telemetry;
400
+ constructor(context, telemetry) {
401
+ super(context, DOOM_PROMPT_CACHE_TELEMETRY_SERVICE);
402
+ this.telemetry = telemetry;
403
+ }
404
+ snapshot() {
405
+ return this.telemetry.snapshot();
406
+ }
407
+ };
408
+ //#endregion
409
+ //#region src/extensions/workspaces/sessions/(backend)/root.cli.ts
410
+ var root_cli_default = defineRoot(async ({ pi, options }) => {
411
+ const dependencies = options ?? {
412
+ telemetry: new PromptCacheTelemetry(),
413
+ now: Date.now
414
+ };
415
+ const optimizer = await import("../pi-cache-optimizer-EMbP1t9X.mjs");
416
+ if (typeof optimizer.default !== "function") throw new Error("Pi Cache Optimizer does not provide an extension factory.");
417
+ await optimizer.default(pi);
418
+ const runtime = createCacheRuntime(dependencies, optimizer);
419
+ return {
420
+ value: runtime,
421
+ services: [(context) => {
422
+ new PromptCacheTelemetryService(context, dependencies.telemetry);
423
+ }, runtime.plugin],
424
+ onDispose: () => runtime.dispose()
425
+ };
426
+ });
427
+ //#endregion
428
+ //#region src/extensions/workspaces/sessions/(backend)/resource/doompi-use-cache.cli.ts
429
+ var doompi_use_cache_cli_default = defineResource({
430
+ source: PACKAGE_SOURCE,
431
+ moduleUrl: import.meta.url,
432
+ skills: [CACHE_HELP_SKILL]
433
+ });
434
+ //#endregion
435
+ //#region generated/pi.ts
436
+ const at = (value, context) => typeof value === "function" ? value(context) : value;
437
+ const extension = definePiExtension("@agimon-ai/doompi-cache", async (context) => {
438
+ const scopeSession = await root_cli_default(context);
439
+ const contextSession = {
440
+ ...context,
441
+ root: scopeSession.value
442
+ };
443
+ return {
444
+ ...composeRootHooks(scopeSession),
445
+ get resources() {
446
+ return [at(doompi_use_cache_cli_default, contextSession)];
447
+ },
448
+ services: [...scopeSession.services ?? []]
449
+ };
450
+ });
451
+ //#endregion
452
+ export { extension as default, extension };
453
+
2
454
  //# sourceMappingURL=pi.mjs.map