@caupulican/pi-adaptative 0.85.8 → 0.86.2

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 (239) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/core/agent-paths.d.ts +6 -3
  3. package/dist/core/agent-paths.d.ts.map +1 -1
  4. package/dist/core/agent-paths.js +10 -3
  5. package/dist/core/agent-paths.js.map +1 -1
  6. package/dist/core/agent-session.d.ts +5 -2
  7. package/dist/core/agent-session.d.ts.map +1 -1
  8. package/dist/core/agent-session.js +7 -1
  9. package/dist/core/agent-session.js.map +1 -1
  10. package/dist/core/autonomy/bounded-completion.d.ts.map +1 -1
  11. package/dist/core/autonomy/bounded-completion.js +19 -8
  12. package/dist/core/autonomy/bounded-completion.js.map +1 -1
  13. package/dist/core/autonomy/lane-tool-surface.d.ts +11 -5
  14. package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
  15. package/dist/core/autonomy/lane-tool-surface.js +34 -8
  16. package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
  17. package/dist/core/autonomy/subagent-prompt.d.ts +3 -3
  18. package/dist/core/autonomy/subagent-prompt.js +9 -9
  19. package/dist/core/autonomy/subagent-prompt.js.map +1 -1
  20. package/dist/core/background-lane-controller.d.ts +10 -8
  21. package/dist/core/background-lane-controller.d.ts.map +1 -1
  22. package/dist/core/background-lane-controller.js +23 -13
  23. package/dist/core/background-lane-controller.js.map +1 -1
  24. package/dist/core/bash-execution-controller.d.ts +4 -0
  25. package/dist/core/bash-execution-controller.d.ts.map +1 -1
  26. package/dist/core/bash-execution-controller.js +11 -4
  27. package/dist/core/bash-execution-controller.js.map +1 -1
  28. package/dist/core/bash-executor.d.ts +2 -0
  29. package/dist/core/bash-executor.d.ts.map +1 -1
  30. package/dist/core/bash-executor.js +2 -1
  31. package/dist/core/bash-executor.js.map +1 -1
  32. package/dist/core/capability-contract.d.ts +1 -1
  33. package/dist/core/capability-contract.d.ts.map +1 -1
  34. package/dist/core/capability-contract.js +0 -1
  35. package/dist/core/capability-contract.js.map +1 -1
  36. package/dist/core/default-tool-surface.d.ts +1 -0
  37. package/dist/core/default-tool-surface.d.ts.map +1 -1
  38. package/dist/core/default-tool-surface.js +3 -2
  39. package/dist/core/default-tool-surface.js.map +1 -1
  40. package/dist/core/delegation/worker-agent-control-coordinator.d.ts +27 -8
  41. package/dist/core/delegation/worker-agent-control-coordinator.d.ts.map +1 -1
  42. package/dist/core/delegation/worker-agent-control-coordinator.js +191 -33
  43. package/dist/core/delegation/worker-agent-control-coordinator.js.map +1 -1
  44. package/dist/core/delegation/worker-agent-control.d.ts +45 -6
  45. package/dist/core/delegation/worker-agent-control.d.ts.map +1 -1
  46. package/dist/core/delegation/worker-agent-control.js +110 -13
  47. package/dist/core/delegation/worker-agent-control.js.map +1 -1
  48. package/dist/core/delegation/worker-attempt-executor.d.ts.map +1 -1
  49. package/dist/core/delegation/worker-attempt-executor.js +177 -158
  50. package/dist/core/delegation/worker-attempt-executor.js.map +1 -1
  51. package/dist/core/delegation/worker-authority-resolver.d.ts +23 -0
  52. package/dist/core/delegation/worker-authority-resolver.d.ts.map +1 -0
  53. package/dist/core/delegation/worker-authority-resolver.js +128 -0
  54. package/dist/core/delegation/worker-authority-resolver.js.map +1 -0
  55. package/dist/core/delegation/worker-conversation-store.d.ts.map +1 -1
  56. package/dist/core/delegation/worker-conversation-store.js +1 -1
  57. package/dist/core/delegation/worker-conversation-store.js.map +1 -1
  58. package/dist/core/delegation/worker-delegation-controller.d.ts +7 -1
  59. package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
  60. package/dist/core/delegation/worker-delegation-controller.js +260 -87
  61. package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
  62. package/dist/core/delegation/worker-delegation-request.d.ts +25 -4
  63. package/dist/core/delegation/worker-delegation-request.d.ts.map +1 -1
  64. package/dist/core/delegation/worker-delegation-request.js +90 -1
  65. package/dist/core/delegation/worker-delegation-request.js.map +1 -1
  66. package/dist/core/delegation/worker-execution-policy.d.ts +2 -0
  67. package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -1
  68. package/dist/core/delegation/worker-execution-policy.js +22 -12
  69. package/dist/core/delegation/worker-execution-policy.js.map +1 -1
  70. package/dist/core/delegation/worker-lifecycle.d.ts +1 -0
  71. package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -1
  72. package/dist/core/delegation/worker-lifecycle.js +4 -2
  73. package/dist/core/delegation/worker-lifecycle.js.map +1 -1
  74. package/dist/core/delegation/worker-profile-resolver.d.ts +0 -2
  75. package/dist/core/delegation/worker-profile-resolver.d.ts.map +1 -1
  76. package/dist/core/delegation/worker-profile-resolver.js +8 -35
  77. package/dist/core/delegation/worker-profile-resolver.js.map +1 -1
  78. package/dist/core/delegation/worker-recovery-coordinator.d.ts.map +1 -1
  79. package/dist/core/delegation/worker-recovery-coordinator.js +1 -0
  80. package/dist/core/delegation/worker-recovery-coordinator.js.map +1 -1
  81. package/dist/core/delegation/worker-runner.d.ts +6 -1
  82. package/dist/core/delegation/worker-runner.d.ts.map +1 -1
  83. package/dist/core/delegation/worker-runner.js +20 -6
  84. package/dist/core/delegation/worker-runner.js.map +1 -1
  85. package/dist/core/delegation/worker-tree-budget-coordinator.d.ts +47 -0
  86. package/dist/core/delegation/worker-tree-budget-coordinator.d.ts.map +1 -0
  87. package/dist/core/delegation/worker-tree-budget-coordinator.js +210 -0
  88. package/dist/core/delegation/worker-tree-budget-coordinator.js.map +1 -0
  89. package/dist/core/memory/providers/file-store.d.ts +2 -0
  90. package/dist/core/memory/providers/file-store.d.ts.map +1 -1
  91. package/dist/core/memory/providers/file-store.js +22 -20
  92. package/dist/core/memory/providers/file-store.js.map +1 -1
  93. package/dist/core/models/runtime-process.d.ts.map +1 -1
  94. package/dist/core/models/runtime-process.js +5 -18
  95. package/dist/core/models/runtime-process.js.map +1 -1
  96. package/dist/core/orchestration/bounded-string-array.d.ts +11 -0
  97. package/dist/core/orchestration/bounded-string-array.d.ts.map +1 -0
  98. package/dist/core/orchestration/bounded-string-array.js +17 -0
  99. package/dist/core/orchestration/bounded-string-array.js.map +1 -0
  100. package/dist/core/orchestration/capability-gateway.d.ts +16 -0
  101. package/dist/core/orchestration/capability-gateway.d.ts.map +1 -1
  102. package/dist/core/orchestration/capability-gateway.js +38 -0
  103. package/dist/core/orchestration/capability-gateway.js.map +1 -1
  104. package/dist/core/orchestration/contracts.d.ts +11 -3
  105. package/dist/core/orchestration/contracts.d.ts.map +1 -1
  106. package/dist/core/orchestration/contracts.js +0 -1
  107. package/dist/core/orchestration/contracts.js.map +1 -1
  108. package/dist/core/orchestration/delegation-ledger.d.ts +1 -0
  109. package/dist/core/orchestration/delegation-ledger.d.ts.map +1 -1
  110. package/dist/core/orchestration/delegation-ledger.js +3 -0
  111. package/dist/core/orchestration/delegation-ledger.js.map +1 -1
  112. package/dist/core/orchestration/event-store.d.ts +12 -10
  113. package/dist/core/orchestration/event-store.d.ts.map +1 -1
  114. package/dist/core/orchestration/event-store.js +94 -104
  115. package/dist/core/orchestration/event-store.js.map +1 -1
  116. package/dist/core/orchestration/lane-tool-manifests.d.ts +2 -2
  117. package/dist/core/orchestration/lane-tool-manifests.d.ts.map +1 -1
  118. package/dist/core/orchestration/lane-tool-manifests.js +4 -1
  119. package/dist/core/orchestration/lane-tool-manifests.js.map +1 -1
  120. package/dist/core/orchestration/policy-compiler.d.ts.map +1 -1
  121. package/dist/core/orchestration/policy-compiler.js +8 -9
  122. package/dist/core/orchestration/policy-compiler.js.map +1 -1
  123. package/dist/core/orchestration/profile-registry.d.ts.map +1 -1
  124. package/dist/core/orchestration/profile-registry.js +4 -10
  125. package/dist/core/orchestration/profile-registry.js.map +1 -1
  126. package/dist/core/orchestration/task-runtime.d.ts +1 -0
  127. package/dist/core/orchestration/task-runtime.d.ts.map +1 -1
  128. package/dist/core/orchestration/task-runtime.js +58 -3
  129. package/dist/core/orchestration/task-runtime.js.map +1 -1
  130. package/dist/core/orchestration/worker-execution-contract.d.ts.map +1 -1
  131. package/dist/core/orchestration/worker-execution-contract.js +10 -17
  132. package/dist/core/orchestration/worker-execution-contract.js.map +1 -1
  133. package/dist/core/risk-classifier.js +3 -3
  134. package/dist/core/risk-classifier.js.map +1 -1
  135. package/dist/core/runtime-builder.d.ts +4 -1
  136. package/dist/core/runtime-builder.d.ts.map +1 -1
  137. package/dist/core/runtime-builder.js +34 -15
  138. package/dist/core/runtime-builder.js.map +1 -1
  139. package/dist/core/secrets/bitwarden-credential-storage.d.ts +51 -0
  140. package/dist/core/secrets/bitwarden-credential-storage.d.ts.map +1 -0
  141. package/dist/core/secrets/bitwarden-credential-storage.js +345 -0
  142. package/dist/core/secrets/bitwarden-credential-storage.js.map +1 -0
  143. package/dist/core/secrets/credential-exposure-guard.d.ts +8 -4
  144. package/dist/core/secrets/credential-exposure-guard.d.ts.map +1 -1
  145. package/dist/core/secrets/credential-exposure-guard.js +30 -31
  146. package/dist/core/secrets/credential-exposure-guard.js.map +1 -1
  147. package/dist/core/secrets/credential-manager.d.ts +109 -0
  148. package/dist/core/secrets/credential-manager.d.ts.map +1 -0
  149. package/dist/core/secrets/credential-manager.js +384 -0
  150. package/dist/core/secrets/credential-manager.js.map +1 -0
  151. package/dist/core/secrets/credential-project.d.ts +4 -0
  152. package/dist/core/secrets/credential-project.d.ts.map +1 -0
  153. package/dist/core/secrets/credential-project.js +145 -0
  154. package/dist/core/secrets/credential-project.js.map +1 -0
  155. package/dist/core/secrets/secret-dotenv.d.ts +1 -1
  156. package/dist/core/secrets/secret-dotenv.js +1 -1
  157. package/dist/core/secrets/secret-dotenv.js.map +1 -1
  158. package/dist/core/settings-manager.d.ts +4 -2
  159. package/dist/core/settings-manager.d.ts.map +1 -1
  160. package/dist/core/settings-manager.js +9 -5
  161. package/dist/core/settings-manager.js.map +1 -1
  162. package/dist/core/slash-commands.d.ts.map +1 -1
  163. package/dist/core/slash-commands.js +1 -0
  164. package/dist/core/slash-commands.js.map +1 -1
  165. package/dist/core/system-prompt.js +1 -1
  166. package/dist/core/system-prompt.js.map +1 -1
  167. package/dist/core/tool-capability-policy.js +2 -2
  168. package/dist/core/tool-capability-policy.js.map +1 -1
  169. package/dist/core/tools/delegate.d.ts +29 -1
  170. package/dist/core/tools/delegate.d.ts.map +1 -1
  171. package/dist/core/tools/delegate.js +179 -28
  172. package/dist/core/tools/delegate.js.map +1 -1
  173. package/dist/core/tools/git-filter.d.ts +1 -0
  174. package/dist/core/tools/git-filter.d.ts.map +1 -1
  175. package/dist/core/tools/git-filter.js +1 -1
  176. package/dist/core/tools/git-filter.js.map +1 -1
  177. package/dist/core/tools/profile-writer.js +3 -3
  178. package/dist/core/tools/profile-writer.js.map +1 -1
  179. package/dist/core/tools/python.d.ts +2 -0
  180. package/dist/core/tools/python.d.ts.map +1 -1
  181. package/dist/core/tools/python.js +17 -12
  182. package/dist/core/tools/python.js.map +1 -1
  183. package/dist/core/tools/run-process.d.ts +2 -0
  184. package/dist/core/tools/run-process.d.ts.map +1 -1
  185. package/dist/core/tools/run-process.js +7 -3
  186. package/dist/core/tools/run-process.js.map +1 -1
  187. package/dist/core/tools/secret-store.d.ts +8 -18
  188. package/dist/core/tools/secret-store.d.ts.map +1 -1
  189. package/dist/core/tools/secret-store.js +83 -348
  190. package/dist/core/tools/secret-store.js.map +1 -1
  191. package/dist/index.d.ts +3 -1
  192. package/dist/index.d.ts.map +1 -1
  193. package/dist/index.js +3 -1
  194. package/dist/index.js.map +1 -1
  195. package/dist/migrations.d.ts.map +1 -1
  196. package/dist/migrations.js +38 -1
  197. package/dist/migrations.js.map +1 -1
  198. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  199. package/dist/modes/interactive/components/settings-selector.js +35 -14
  200. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  201. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  202. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  203. package/dist/modes/interactive/interactive-mode.js +26 -3
  204. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  205. package/dist/modes/interactive/secret-menu-controller.d.ts +21 -0
  206. package/dist/modes/interactive/secret-menu-controller.d.ts.map +1 -0
  207. package/dist/modes/interactive/secret-menu-controller.js +276 -0
  208. package/dist/modes/interactive/secret-menu-controller.js.map +1 -0
  209. package/dist/utils/tools-manager.d.ts +2 -1
  210. package/dist/utils/tools-manager.d.ts.map +1 -1
  211. package/dist/utils/tools-manager.js +43 -48
  212. package/dist/utils/tools-manager.js.map +1 -1
  213. package/dist/utils/zip-extractor.d.ts +8 -0
  214. package/dist/utils/zip-extractor.d.ts.map +1 -0
  215. package/dist/utils/zip-extractor.js +275 -0
  216. package/dist/utils/zip-extractor.js.map +1 -0
  217. package/docs/harness-architecture.md +34 -22
  218. package/docs/index.md +1 -1
  219. package/docs/resources.md +1 -1
  220. package/docs/settings.md +39 -103
  221. package/docs/usage.md +7 -5
  222. package/docs/worker-profiles.md +9 -7
  223. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  224. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  225. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  226. package/examples/extensions/sandbox/package-lock.json +2 -2
  227. package/examples/extensions/sandbox/package.json +1 -1
  228. package/examples/extensions/with-deps/package-lock.json +2 -2
  229. package/examples/extensions/with-deps/package.json +1 -1
  230. package/npm-shrinkwrap.json +12 -12
  231. package/package.json +4 -4
  232. package/dist/core/secrets/secret-vault-format.d.ts +0 -112
  233. package/dist/core/secrets/secret-vault-format.d.ts.map +0 -1
  234. package/dist/core/secrets/secret-vault-format.js +0 -396
  235. package/dist/core/secrets/secret-vault-format.js.map +0 -1
  236. package/dist/core/secrets/secret-vault.d.ts +0 -72
  237. package/dist/core/secrets/secret-vault.d.ts.map +0 -1
  238. package/dist/core/secrets/secret-vault.js +0 -663
  239. package/dist/core/secrets/secret-vault.js.map +0 -1
@@ -0,0 +1,47 @@
1
+ import type { SharedCapabilityBudget } from "../orchestration/capability-gateway.ts";
2
+ import type { AttemptUsageSnapshot, RiskBudget } from "../orchestration/contracts.ts";
3
+ export declare class WorkerTreeBudgetExceededError extends Error {
4
+ readonly field: "maxTokens" | "maxCostUsd" | "maxToolCalls" | "maxWallClockMs" | "maxAttempts";
5
+ constructor(field: WorkerTreeBudgetExceededError["field"], subject: string);
6
+ }
7
+ export interface WorkerTreeBudgetSeed {
8
+ attemptId: string;
9
+ usage: AttemptUsageSnapshot;
10
+ }
11
+ export interface WorkerTreeBudgetProjection {
12
+ agents: Readonly<Record<string, {
13
+ rootAgentId: string;
14
+ }>>;
15
+ attempts: Readonly<Record<string, {
16
+ attemptId: string;
17
+ agentId?: string;
18
+ dispatch: {
19
+ logicalLaneId?: string;
20
+ };
21
+ checkpointIds: readonly string[];
22
+ }>>;
23
+ checkpoints: Readonly<Record<string, {
24
+ usage?: AttemptUsageSnapshot;
25
+ }>>;
26
+ }
27
+ /** Rebuild every durable tree attempt, including attempts with no usage checkpoint yet. */
28
+ export declare function collectWorkerTreeBudgetSeeds(snapshot: WorkerTreeBudgetProjection, rootAgentId: string): WorkerTreeBudgetSeed[];
29
+ /** One in-memory aggregate reconstructed from durable checkpoints whenever a root is first used. */
30
+ export declare class WorkerTreeBudgetCoordinator {
31
+ private readonly trees;
32
+ createPort(args: {
33
+ rootAgentId: string;
34
+ attemptId: string;
35
+ budget: RiskBudget;
36
+ seeds: readonly WorkerTreeBudgetSeed[];
37
+ initialUsage: AttemptUsageSnapshot;
38
+ }): SharedCapabilityBudget;
39
+ private recordAttemptUsage;
40
+ private reserveProviderBudget;
41
+ private drainWaiters;
42
+ private detachAbort;
43
+ private totalTokens;
44
+ private reservedTokens;
45
+ private assertAvailable;
46
+ }
47
+ //# sourceMappingURL=worker-tree-budget-coordinator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-tree-budget-coordinator.d.ts","sourceRoot":"","sources":["../../../src/core/delegation/worker-tree-budget-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGX,sBAAsB,EACtB,MAAM,wCAAwC,CAAC;AAChD,OAAO,KAAK,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAGtF,qBAAa,6BAA8B,SAAQ,KAAK;IACvD,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY,GAAG,cAAc,GAAG,gBAAgB,GAAG,aAAa,CAAC;IAE/F,YAAY,KAAK,EAAE,6BAA6B,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,EAIzE;CACD;AAmBD,MAAM,WAAW,oBAAoB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,oBAAoB,CAAC;CAC5B;AAED,MAAM,WAAW,0BAA0B;IAC1C,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IAC1D,QAAQ,EAAE,QAAQ,CACjB,MAAM,CACL,MAAM,EACN;QACC,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE;YAAE,aAAa,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACrC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;KACjC,CACD,CACD,CAAC;IACF,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,CAAC,EAAE,oBAAoB,CAAA;KAAE,CAAC,CAAC,CAAC;CACxE;AAaD,2FAA2F;AAC3F,wBAAgB,4BAA4B,CAC3C,QAAQ,EAAE,0BAA0B,EACpC,WAAW,EAAE,MAAM,GACjB,oBAAoB,EAAE,CAYxB;AAiCD,oGAAoG;AACpG,qBAAa,2BAA2B;IACvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAsC;IAE5D,UAAU,CAAC,IAAI,EAAE;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,UAAU,CAAC;QACnB,KAAK,EAAE,SAAS,oBAAoB,EAAE,CAAC;QACvC,YAAY,EAAE,oBAAoB,CAAC;KACnC,GAAG,sBAAsB,CA4BzB;IAED,OAAO,CAAC,kBAAkB;IAa1B,OAAO,CAAC,qBAAqB;IAmC7B,OAAO,CAAC,YAAY;IA4CpB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,eAAe;CA2BvB"}
@@ -0,0 +1,210 @@
1
+ import { intersectRiskBudgets } from "../orchestration/risk-budget.js";
2
+ export class WorkerTreeBudgetExceededError extends Error {
3
+ constructor(field, subject) {
4
+ super(`Worker orchestration tree budget '${field}' is exhausted before ${subject}.`);
5
+ this.name = "WorkerTreeBudgetExceededError";
6
+ this.field = field;
7
+ }
8
+ }
9
+ const EMPTY_ATTEMPT_USAGE = {
10
+ toolCalls: 0,
11
+ inputTokens: 0,
12
+ outputTokens: 0,
13
+ cacheReadTokens: 0,
14
+ cacheWriteTokens: 0,
15
+ totalTokens: 0,
16
+ costUsd: 0,
17
+ activeWallClockMs: 0,
18
+ };
19
+ /** Rebuild every durable tree attempt, including attempts with no usage checkpoint yet. */
20
+ export function collectWorkerTreeBudgetSeeds(snapshot, rootAgentId) {
21
+ const seeds = [];
22
+ for (const attempt of Object.values(snapshot.attempts)) {
23
+ const attemptAgentId = attempt.agentId ?? attempt.dispatch.logicalLaneId;
24
+ if (!attemptAgentId || snapshot.agents[attemptAgentId]?.rootAgentId !== rootAgentId)
25
+ continue;
26
+ const usage = [...attempt.checkpointIds]
27
+ .reverse()
28
+ .map((checkpointId) => snapshot.checkpoints[checkpointId]?.usage)
29
+ .find((candidate) => candidate !== undefined);
30
+ seeds.push({ attemptId: attempt.attemptId, usage: usage ?? EMPTY_ATTEMPT_USAGE });
31
+ }
32
+ return seeds;
33
+ }
34
+ function gatewayUsage(usage) {
35
+ return {
36
+ toolCalls: usage.toolCalls,
37
+ inputTokens: usage.inputTokens,
38
+ outputTokens: usage.outputTokens,
39
+ cacheReadTokens: usage.cacheReadTokens,
40
+ cacheWriteTokens: usage.cacheWriteTokens,
41
+ totalTokens: usage.totalTokens,
42
+ costUsd: usage.costUsd,
43
+ wallClockMs: usage.activeWallClockMs,
44
+ };
45
+ }
46
+ function mergeUsage(current, incoming) {
47
+ if (!current)
48
+ return structuredClone(incoming);
49
+ return {
50
+ toolCalls: Math.max(current.toolCalls, incoming.toolCalls),
51
+ inputTokens: Math.max(current.inputTokens, incoming.inputTokens),
52
+ outputTokens: Math.max(current.outputTokens, incoming.outputTokens),
53
+ cacheReadTokens: Math.max(current.cacheReadTokens, incoming.cacheReadTokens),
54
+ cacheWriteTokens: Math.max(current.cacheWriteTokens, incoming.cacheWriteTokens),
55
+ totalTokens: Math.max(current.totalTokens, incoming.totalTokens),
56
+ costUsd: Math.max(current.costUsd, incoming.costUsd),
57
+ wallClockMs: Math.max(current.wallClockMs, incoming.wallClockMs),
58
+ };
59
+ }
60
+ function abortReason(signal) {
61
+ return signal.reason ?? new Error("Worker provider budget reservation was aborted.");
62
+ }
63
+ /** One in-memory aggregate reconstructed from durable checkpoints whenever a root is first used. */
64
+ export class WorkerTreeBudgetCoordinator {
65
+ constructor() {
66
+ this.trees = new Map();
67
+ }
68
+ createPort(args) {
69
+ let state = this.trees.get(args.rootAgentId);
70
+ if (!state) {
71
+ state = { budget: structuredClone(args.budget), attempts: new Map(), reservations: new Map(), waiters: [] };
72
+ this.trees.set(args.rootAgentId, state);
73
+ }
74
+ else {
75
+ state.budget = intersectRiskBudgets(state.budget, args.budget);
76
+ }
77
+ for (const seed of args.seeds) {
78
+ state.attempts.set(seed.attemptId, mergeUsage(state.attempts.get(seed.attemptId), gatewayUsage(seed.usage)));
79
+ }
80
+ state.attempts.set(args.attemptId, mergeUsage(state.attempts.get(args.attemptId), gatewayUsage(args.initialUsage)));
81
+ const tree = state;
82
+ return {
83
+ assertBudgetAvailable: (subject) => this.assertAvailable(tree, subject),
84
+ recordAttemptUsage: (usage) => this.recordAttemptUsage(tree, args.attemptId, usage),
85
+ remainingTokens: () => {
86
+ const maximum = tree.budget.maxTokens;
87
+ return maximum === undefined
88
+ ? undefined
89
+ : Math.max(0, maximum - this.totalTokens(tree) - this.reservedTokens(tree));
90
+ },
91
+ reserveProviderBudget: (requestedMaxTokens, subject, signal) => this.reserveProviderBudget(tree, args.attemptId, requestedMaxTokens, subject, signal),
92
+ };
93
+ }
94
+ recordAttemptUsage(state, attemptId, usage) {
95
+ const previous = state.attempts.get(attemptId);
96
+ const merged = mergeUsage(previous, usage);
97
+ state.attempts.set(attemptId, merged);
98
+ const reservation = state.reservations.get(attemptId);
99
+ if (reservation && previous) {
100
+ reservation.maxTokens = Math.max(0, reservation.maxTokens - Math.max(0, merged.totalTokens - previous.totalTokens));
101
+ }
102
+ }
103
+ reserveProviderBudget(state, attemptId, requestedMaxTokens, subject, signal) {
104
+ if (!Number.isSafeInteger(requestedMaxTokens) || requestedMaxTokens <= 0) {
105
+ return Promise.reject(new Error("Worker provider token reservation must be a positive safe integer."));
106
+ }
107
+ if (signal?.aborted)
108
+ return Promise.reject(abortReason(signal));
109
+ return new Promise((resolve, reject) => {
110
+ const waiter = {
111
+ attemptId,
112
+ requestedMaxTokens,
113
+ subject,
114
+ ...(signal ? { signal } : {}),
115
+ resolve,
116
+ reject,
117
+ };
118
+ if (signal) {
119
+ waiter.onAbort = () => {
120
+ const index = state.waiters.indexOf(waiter);
121
+ if (index < 0)
122
+ return;
123
+ state.waiters.splice(index, 1);
124
+ reject(abortReason(signal));
125
+ this.drainWaiters(state);
126
+ };
127
+ signal.addEventListener("abort", waiter.onAbort, { once: true });
128
+ }
129
+ state.waiters.push(waiter);
130
+ this.drainWaiters(state);
131
+ });
132
+ }
133
+ drainWaiters(state) {
134
+ while (state.waiters.length > 0) {
135
+ const waiter = state.waiters[0];
136
+ if (!waiter)
137
+ return;
138
+ try {
139
+ this.assertAvailable(state, waiter.subject);
140
+ }
141
+ catch (error) {
142
+ state.waiters.shift();
143
+ this.detachAbort(waiter);
144
+ waiter.reject(error);
145
+ continue;
146
+ }
147
+ if (state.reservations.has(waiter.attemptId))
148
+ return;
149
+ if ((state.budget.maxCostUsd !== undefined || state.budget.maxWallClockMs !== undefined) &&
150
+ state.reservations.size > 0) {
151
+ return;
152
+ }
153
+ const availableTokens = state.budget.maxTokens === undefined
154
+ ? waiter.requestedMaxTokens
155
+ : Math.max(0, state.budget.maxTokens - this.totalTokens(state) - this.reservedTokens(state));
156
+ if (availableTokens <= 0)
157
+ return;
158
+ const maxTokens = Math.min(waiter.requestedMaxTokens, availableTokens);
159
+ state.waiters.shift();
160
+ this.detachAbort(waiter);
161
+ const reservationState = { maxTokens };
162
+ state.reservations.set(waiter.attemptId, reservationState);
163
+ let released = false;
164
+ waiter.resolve({
165
+ maxTokens,
166
+ release: () => {
167
+ if (released)
168
+ return;
169
+ released = true;
170
+ if (state.reservations.get(waiter.attemptId) === reservationState) {
171
+ state.reservations.delete(waiter.attemptId);
172
+ }
173
+ this.drainWaiters(state);
174
+ },
175
+ });
176
+ }
177
+ }
178
+ detachAbort(waiter) {
179
+ if (waiter.signal && waiter.onAbort)
180
+ waiter.signal.removeEventListener("abort", waiter.onAbort);
181
+ }
182
+ totalTokens(state) {
183
+ return [...state.attempts.values()].reduce((total, usage) => total + usage.totalTokens, 0);
184
+ }
185
+ reservedTokens(state) {
186
+ return [...state.reservations.values()].reduce((total, reservation) => total + reservation.maxTokens, 0);
187
+ }
188
+ assertAvailable(state, subject) {
189
+ const usages = [...state.attempts.values()];
190
+ if (state.budget.maxAttempts !== undefined && usages.length > state.budget.maxAttempts) {
191
+ throw new WorkerTreeBudgetExceededError("maxAttempts", subject);
192
+ }
193
+ if (state.budget.maxTokens !== undefined && this.totalTokens(state) >= state.budget.maxTokens) {
194
+ throw new WorkerTreeBudgetExceededError("maxTokens", subject);
195
+ }
196
+ if (state.budget.maxCostUsd !== undefined &&
197
+ usages.reduce((total, usage) => total + usage.costUsd, 0) >= state.budget.maxCostUsd) {
198
+ throw new WorkerTreeBudgetExceededError("maxCostUsd", subject);
199
+ }
200
+ if (state.budget.maxToolCalls !== undefined &&
201
+ usages.reduce((total, usage) => total + usage.toolCalls, 0) >= state.budget.maxToolCalls) {
202
+ throw new WorkerTreeBudgetExceededError("maxToolCalls", subject);
203
+ }
204
+ if (state.budget.maxWallClockMs !== undefined &&
205
+ usages.reduce((total, usage) => total + usage.wallClockMs, 0) >= state.budget.maxWallClockMs) {
206
+ throw new WorkerTreeBudgetExceededError("maxWallClockMs", subject);
207
+ }
208
+ }
209
+ }
210
+ //# sourceMappingURL=worker-tree-budget-coordinator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-tree-budget-coordinator.js","sourceRoot":"","sources":["../../../src/core/delegation/worker-tree-budget-coordinator.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tGatewayUsageSnapshot,\n\tProviderBudgetReservation,\n\tSharedCapabilityBudget,\n} from \"../orchestration/capability-gateway.ts\";\nimport type { AttemptUsageSnapshot, RiskBudget } from \"../orchestration/contracts.ts\";\nimport { intersectRiskBudgets } from \"../orchestration/risk-budget.ts\";\n\nexport class WorkerTreeBudgetExceededError extends Error {\n\treadonly field: \"maxTokens\" | \"maxCostUsd\" | \"maxToolCalls\" | \"maxWallClockMs\" | \"maxAttempts\";\n\n\tconstructor(field: WorkerTreeBudgetExceededError[\"field\"], subject: string) {\n\t\tsuper(`Worker orchestration tree budget '${field}' is exhausted before ${subject}.`);\n\t\tthis.name = \"WorkerTreeBudgetExceededError\";\n\t\tthis.field = field;\n\t}\n}\n\ninterface TreeBudgetState {\n\tbudget: RiskBudget;\n\tattempts: Map<string, GatewayUsageSnapshot>;\n\treservations: Map<string, { maxTokens: number }>;\n\twaiters: ProviderBudgetWaiter[];\n}\n\ninterface ProviderBudgetWaiter {\n\tattemptId: string;\n\trequestedMaxTokens: number;\n\tsubject: string;\n\tsignal?: AbortSignal;\n\tresolve(reservation: ProviderBudgetReservation): void;\n\treject(error: unknown): void;\n\tonAbort?: () => void;\n}\n\nexport interface WorkerTreeBudgetSeed {\n\tattemptId: string;\n\tusage: AttemptUsageSnapshot;\n}\n\nexport interface WorkerTreeBudgetProjection {\n\tagents: Readonly<Record<string, { rootAgentId: string }>>;\n\tattempts: Readonly<\n\t\tRecord<\n\t\t\tstring,\n\t\t\t{\n\t\t\t\tattemptId: string;\n\t\t\t\tagentId?: string;\n\t\t\t\tdispatch: { logicalLaneId?: string };\n\t\t\t\tcheckpointIds: readonly string[];\n\t\t\t}\n\t\t>\n\t>;\n\tcheckpoints: Readonly<Record<string, { usage?: AttemptUsageSnapshot }>>;\n}\n\nconst EMPTY_ATTEMPT_USAGE: AttemptUsageSnapshot = {\n\ttoolCalls: 0,\n\tinputTokens: 0,\n\toutputTokens: 0,\n\tcacheReadTokens: 0,\n\tcacheWriteTokens: 0,\n\ttotalTokens: 0,\n\tcostUsd: 0,\n\tactiveWallClockMs: 0,\n};\n\n/** Rebuild every durable tree attempt, including attempts with no usage checkpoint yet. */\nexport function collectWorkerTreeBudgetSeeds(\n\tsnapshot: WorkerTreeBudgetProjection,\n\trootAgentId: string,\n): WorkerTreeBudgetSeed[] {\n\tconst seeds: WorkerTreeBudgetSeed[] = [];\n\tfor (const attempt of Object.values(snapshot.attempts)) {\n\t\tconst attemptAgentId = attempt.agentId ?? attempt.dispatch.logicalLaneId;\n\t\tif (!attemptAgentId || snapshot.agents[attemptAgentId]?.rootAgentId !== rootAgentId) continue;\n\t\tconst usage = [...attempt.checkpointIds]\n\t\t\t.reverse()\n\t\t\t.map((checkpointId) => snapshot.checkpoints[checkpointId]?.usage)\n\t\t\t.find((candidate): candidate is AttemptUsageSnapshot => candidate !== undefined);\n\t\tseeds.push({ attemptId: attempt.attemptId, usage: usage ?? EMPTY_ATTEMPT_USAGE });\n\t}\n\treturn seeds;\n}\n\nfunction gatewayUsage(usage: AttemptUsageSnapshot): GatewayUsageSnapshot {\n\treturn {\n\t\ttoolCalls: usage.toolCalls,\n\t\tinputTokens: usage.inputTokens,\n\t\toutputTokens: usage.outputTokens,\n\t\tcacheReadTokens: usage.cacheReadTokens,\n\t\tcacheWriteTokens: usage.cacheWriteTokens,\n\t\ttotalTokens: usage.totalTokens,\n\t\tcostUsd: usage.costUsd,\n\t\twallClockMs: usage.activeWallClockMs,\n\t};\n}\n\nfunction mergeUsage(current: GatewayUsageSnapshot | undefined, incoming: GatewayUsageSnapshot): GatewayUsageSnapshot {\n\tif (!current) return structuredClone(incoming);\n\treturn {\n\t\ttoolCalls: Math.max(current.toolCalls, incoming.toolCalls),\n\t\tinputTokens: Math.max(current.inputTokens, incoming.inputTokens),\n\t\toutputTokens: Math.max(current.outputTokens, incoming.outputTokens),\n\t\tcacheReadTokens: Math.max(current.cacheReadTokens, incoming.cacheReadTokens),\n\t\tcacheWriteTokens: Math.max(current.cacheWriteTokens, incoming.cacheWriteTokens),\n\t\ttotalTokens: Math.max(current.totalTokens, incoming.totalTokens),\n\t\tcostUsd: Math.max(current.costUsd, incoming.costUsd),\n\t\twallClockMs: Math.max(current.wallClockMs, incoming.wallClockMs),\n\t};\n}\n\nfunction abortReason(signal: AbortSignal): unknown {\n\treturn signal.reason ?? new Error(\"Worker provider budget reservation was aborted.\");\n}\n\n/** One in-memory aggregate reconstructed from durable checkpoints whenever a root is first used. */\nexport class WorkerTreeBudgetCoordinator {\n\tprivate readonly trees = new Map<string, TreeBudgetState>();\n\n\tcreatePort(args: {\n\t\trootAgentId: string;\n\t\tattemptId: string;\n\t\tbudget: RiskBudget;\n\t\tseeds: readonly WorkerTreeBudgetSeed[];\n\t\tinitialUsage: AttemptUsageSnapshot;\n\t}): SharedCapabilityBudget {\n\t\tlet state = this.trees.get(args.rootAgentId);\n\t\tif (!state) {\n\t\t\tstate = { budget: structuredClone(args.budget), attempts: new Map(), reservations: new Map(), waiters: [] };\n\t\t\tthis.trees.set(args.rootAgentId, state);\n\t\t} else {\n\t\t\tstate.budget = intersectRiskBudgets(state.budget, args.budget);\n\t\t}\n\t\tfor (const seed of args.seeds) {\n\t\t\tstate.attempts.set(seed.attemptId, mergeUsage(state.attempts.get(seed.attemptId), gatewayUsage(seed.usage)));\n\t\t}\n\t\tstate.attempts.set(\n\t\t\targs.attemptId,\n\t\t\tmergeUsage(state.attempts.get(args.attemptId), gatewayUsage(args.initialUsage)),\n\t\t);\n\t\tconst tree = state;\n\t\treturn {\n\t\t\tassertBudgetAvailable: (subject) => this.assertAvailable(tree, subject),\n\t\t\trecordAttemptUsage: (usage) => this.recordAttemptUsage(tree, args.attemptId, usage),\n\t\t\tremainingTokens: () => {\n\t\t\t\tconst maximum = tree.budget.maxTokens;\n\t\t\t\treturn maximum === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: Math.max(0, maximum - this.totalTokens(tree) - this.reservedTokens(tree));\n\t\t\t},\n\t\t\treserveProviderBudget: (requestedMaxTokens, subject, signal) =>\n\t\t\t\tthis.reserveProviderBudget(tree, args.attemptId, requestedMaxTokens, subject, signal),\n\t\t};\n\t}\n\n\tprivate recordAttemptUsage(state: TreeBudgetState, attemptId: string, usage: GatewayUsageSnapshot): void {\n\t\tconst previous = state.attempts.get(attemptId);\n\t\tconst merged = mergeUsage(previous, usage);\n\t\tstate.attempts.set(attemptId, merged);\n\t\tconst reservation = state.reservations.get(attemptId);\n\t\tif (reservation && previous) {\n\t\t\treservation.maxTokens = Math.max(\n\t\t\t\t0,\n\t\t\t\treservation.maxTokens - Math.max(0, merged.totalTokens - previous.totalTokens),\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate reserveProviderBudget(\n\t\tstate: TreeBudgetState,\n\t\tattemptId: string,\n\t\trequestedMaxTokens: number,\n\t\tsubject: string,\n\t\tsignal?: AbortSignal,\n\t): Promise<ProviderBudgetReservation> {\n\t\tif (!Number.isSafeInteger(requestedMaxTokens) || requestedMaxTokens <= 0) {\n\t\t\treturn Promise.reject(new Error(\"Worker provider token reservation must be a positive safe integer.\"));\n\t\t}\n\t\tif (signal?.aborted) return Promise.reject(abortReason(signal));\n\t\treturn new Promise<ProviderBudgetReservation>((resolve, reject) => {\n\t\t\tconst waiter: ProviderBudgetWaiter = {\n\t\t\t\tattemptId,\n\t\t\t\trequestedMaxTokens,\n\t\t\t\tsubject,\n\t\t\t\t...(signal ? { signal } : {}),\n\t\t\t\tresolve,\n\t\t\t\treject,\n\t\t\t};\n\t\t\tif (signal) {\n\t\t\t\twaiter.onAbort = () => {\n\t\t\t\t\tconst index = state.waiters.indexOf(waiter);\n\t\t\t\t\tif (index < 0) return;\n\t\t\t\t\tstate.waiters.splice(index, 1);\n\t\t\t\t\treject(abortReason(signal));\n\t\t\t\t\tthis.drainWaiters(state);\n\t\t\t\t};\n\t\t\t\tsignal.addEventListener(\"abort\", waiter.onAbort, { once: true });\n\t\t\t}\n\t\t\tstate.waiters.push(waiter);\n\t\t\tthis.drainWaiters(state);\n\t\t});\n\t}\n\n\tprivate drainWaiters(state: TreeBudgetState): void {\n\t\twhile (state.waiters.length > 0) {\n\t\t\tconst waiter = state.waiters[0];\n\t\t\tif (!waiter) return;\n\t\t\ttry {\n\t\t\t\tthis.assertAvailable(state, waiter.subject);\n\t\t\t} catch (error) {\n\t\t\t\tstate.waiters.shift();\n\t\t\t\tthis.detachAbort(waiter);\n\t\t\t\twaiter.reject(error);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (state.reservations.has(waiter.attemptId)) return;\n\t\t\tif (\n\t\t\t\t(state.budget.maxCostUsd !== undefined || state.budget.maxWallClockMs !== undefined) &&\n\t\t\t\tstate.reservations.size > 0\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst availableTokens =\n\t\t\t\tstate.budget.maxTokens === undefined\n\t\t\t\t\t? waiter.requestedMaxTokens\n\t\t\t\t\t: Math.max(0, state.budget.maxTokens - this.totalTokens(state) - this.reservedTokens(state));\n\t\t\tif (availableTokens <= 0) return;\n\t\t\tconst maxTokens = Math.min(waiter.requestedMaxTokens, availableTokens);\n\t\t\tstate.waiters.shift();\n\t\t\tthis.detachAbort(waiter);\n\t\t\tconst reservationState = { maxTokens };\n\t\t\tstate.reservations.set(waiter.attemptId, reservationState);\n\t\t\tlet released = false;\n\t\t\twaiter.resolve({\n\t\t\t\tmaxTokens,\n\t\t\t\trelease: () => {\n\t\t\t\t\tif (released) return;\n\t\t\t\t\treleased = true;\n\t\t\t\t\tif (state.reservations.get(waiter.attemptId) === reservationState) {\n\t\t\t\t\t\tstate.reservations.delete(waiter.attemptId);\n\t\t\t\t\t}\n\t\t\t\t\tthis.drainWaiters(state);\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate detachAbort(waiter: ProviderBudgetWaiter): void {\n\t\tif (waiter.signal && waiter.onAbort) waiter.signal.removeEventListener(\"abort\", waiter.onAbort);\n\t}\n\n\tprivate totalTokens(state: TreeBudgetState): number {\n\t\treturn [...state.attempts.values()].reduce((total, usage) => total + usage.totalTokens, 0);\n\t}\n\n\tprivate reservedTokens(state: TreeBudgetState): number {\n\t\treturn [...state.reservations.values()].reduce((total, reservation) => total + reservation.maxTokens, 0);\n\t}\n\n\tprivate assertAvailable(state: TreeBudgetState, subject: string): void {\n\t\tconst usages = [...state.attempts.values()];\n\t\tif (state.budget.maxAttempts !== undefined && usages.length > state.budget.maxAttempts) {\n\t\t\tthrow new WorkerTreeBudgetExceededError(\"maxAttempts\", subject);\n\t\t}\n\t\tif (state.budget.maxTokens !== undefined && this.totalTokens(state) >= state.budget.maxTokens) {\n\t\t\tthrow new WorkerTreeBudgetExceededError(\"maxTokens\", subject);\n\t\t}\n\t\tif (\n\t\t\tstate.budget.maxCostUsd !== undefined &&\n\t\t\tusages.reduce((total, usage) => total + usage.costUsd, 0) >= state.budget.maxCostUsd\n\t\t) {\n\t\t\tthrow new WorkerTreeBudgetExceededError(\"maxCostUsd\", subject);\n\t\t}\n\t\tif (\n\t\t\tstate.budget.maxToolCalls !== undefined &&\n\t\t\tusages.reduce((total, usage) => total + usage.toolCalls, 0) >= state.budget.maxToolCalls\n\t\t) {\n\t\t\tthrow new WorkerTreeBudgetExceededError(\"maxToolCalls\", subject);\n\t\t}\n\t\tif (\n\t\t\tstate.budget.maxWallClockMs !== undefined &&\n\t\t\tusages.reduce((total, usage) => total + usage.wallClockMs, 0) >= state.budget.maxWallClockMs\n\t\t) {\n\t\t\tthrow new WorkerTreeBudgetExceededError(\"maxWallClockMs\", subject);\n\t\t}\n\t}\n}\n"]}
@@ -17,6 +17,8 @@ export declare class FileStoreProvider implements MemoryProvider {
17
17
  private ctx?;
18
18
  private memoryFilePath;
19
19
  private userFilePath;
20
+ private memoryStatePath;
21
+ private userStatePath;
20
22
  private lastWrittenMemory;
21
23
  private lastWrittenUser;
22
24
  private userArchive?;
@@ -1 +1 @@
1
- {"version":3,"file":"file-store.d.ts","sourceRoot":"","sources":["../../../../src/core/memory/providers/file-store.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAChF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAQhE,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGpF;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsB3F;AAiBD,MAAM,WAAW,wBAAwB;IACxC,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;CACpC;AAED,eAAO,MAAM,6BAA6B,0LAC8I,CAAC;AAgHzL,qBAAa,iBAAkB,YAAW,cAAc;IACvD,SAAgB,IAAI,gBAAgB;IACpC,SAAgB,MAAM,WAAW;IAEjC,OAAO,CAAC,GAAG,CAAC,CAAyB;IACrC,OAAO,CAAC,cAAc,CAAM;IAC5B,OAAO,CAAC,YAAY,CAAM;IAE1B,OAAO,CAAC,iBAAiB,CAAM;IAC/B,OAAO,CAAC,eAAe,CAAM;IAC7B,OAAO,CAAC,WAAW,CAAC,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IAGnD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAQ;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAQ;IAE3C,YAAY,OAAO,GAAE,wBAA6B,EAEjD;IAEM,WAAW,IAAI,OAAO,CAE5B;IAEM,eAAe;QACZ,QAAQ;MACjB;IAEY,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAWtF;YAEa,qBAAqB;IAkC5B,iBAAiB,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,MAAM,CAyC5D;IAEY,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGrD;IAEY,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAErC;IAEM,iBAAiB,IAAI,MAAM,EAAE,CAEnC;IAEM,kBAAkB,IAAI,cAAc,EAAE,CAmN5C;CACD"}
1
+ {"version":3,"file":"file-store.d.ts","sourceRoot":"","sources":["../../../../src/core/memory/providers/file-store.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAChF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAQhE,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGpF;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsB3F;AAiBD,MAAM,WAAW,wBAAwB;IACxC,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;CACpC;AAED,eAAO,MAAM,6BAA6B,0LAC8I,CAAC;AA4GzL,qBAAa,iBAAkB,YAAW,cAAc;IACvD,SAAgB,IAAI,gBAAgB;IACpC,SAAgB,MAAM,WAAW;IAEjC,OAAO,CAAC,GAAG,CAAC,CAAyB;IACrC,OAAO,CAAC,cAAc,CAAM;IAC5B,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,eAAe,CAAM;IAC7B,OAAO,CAAC,aAAa,CAAM;IAE3B,OAAO,CAAC,iBAAiB,CAAM;IAC/B,OAAO,CAAC,eAAe,CAAM;IAC7B,OAAO,CAAC,WAAW,CAAC,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IAGnD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAQ;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAQ;IAE3C,YAAY,OAAO,GAAE,wBAA6B,EAEjD;IAEM,WAAW,IAAI,OAAO,CAE5B;IAEM,eAAe;QACZ,QAAQ;MACjB;IAEY,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAatF;YAEa,qBAAqB;IA8B5B,iBAAiB,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,MAAM,CAyC5D;IAEY,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGrD;IAEY,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAErC;IAEM,iBAAiB,IAAI,MAAM,EAAE,CAEnC;IAEM,kBAAkB,IAAI,cAAc,EAAE,CAoN5C;CACD"}
@@ -1,7 +1,7 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
2
  import { promises as fs } from "node:fs";
3
3
  import { Type } from "typebox";
4
- import { configFile } from "../../agent-paths.js";
4
+ import { configFile, managedMemoryStateFile } from "../../agent-paths.js";
5
5
  import { hasInvisibleUnicode, scanContextFileThreats, stripInvisibleUnicode, } from "../../security/context-threat-scanner.js";
6
6
  import { jaccard, tokenize } from "../../tools/skill-audit.js";
7
7
  import { withFileLock, writeFileAtomic } from "../../util/atomic-file.js";
@@ -49,9 +49,6 @@ const memorySchema = Type.Object({
49
49
  oldContent: Type.Optional(Type.String({ description: "Exact substring to replace or remove (required for 'replace' or 'remove')" })),
50
50
  });
51
51
  export const FILE_STORE_MEMORY_SYSTEM_NOTE = "[System Note: Below is a snapshot of persistent memory. Proactively record verified reusable project facts and user preferences with the 'memory' tool; never store transient noise.]";
52
- function managedMemoryStatePath(filePath) {
53
- return `${filePath}.pi-managed.json`;
54
- }
55
52
  function contentDigest(content) {
56
53
  return createHash("sha256").update(content, "utf8").digest("hex");
57
54
  }
@@ -79,9 +76,9 @@ function parseManagedMemoryState(raw) {
79
76
  ...(typeof record.pendingDigest === "string" ? { pendingDigest: record.pendingDigest } : {}),
80
77
  };
81
78
  }
82
- async function readManagedMemoryState(filePath) {
79
+ async function readManagedMemoryState(statePath) {
83
80
  try {
84
- const raw = await fs.readFile(managedMemoryStatePath(filePath), "utf8");
81
+ const raw = await fs.readFile(statePath, "utf8");
85
82
  const state = parseManagedMemoryState(raw);
86
83
  return state ? { status: "valid", state } : { status: "invalid", raw };
87
84
  }
@@ -94,8 +91,8 @@ async function readManagedMemoryState(filePath) {
94
91
  function serializeManagedMemoryState(state) {
95
92
  return `${JSON.stringify(state)}\n`;
96
93
  }
97
- async function writeManagedMemoryState(filePath, state) {
98
- await writeFileAtomic(managedMemoryStatePath(filePath), serializeManagedMemoryState(state), { mode: 0o600 });
94
+ async function writeManagedMemoryState(statePath, state) {
95
+ await writeFileAtomic(statePath, serializeManagedMemoryState(state), { mode: 0o600 });
99
96
  }
100
97
  function reconcileManagedMemoryState(currentDigest, state) {
101
98
  if (currentDigest === state.committedDigest) {
@@ -160,6 +157,8 @@ export class FileStoreProvider {
160
157
  this.egress = "local";
161
158
  this.memoryFilePath = "";
162
159
  this.userFilePath = "";
160
+ this.memoryStatePath = "";
161
+ this.userStatePath = "";
163
162
  this.lastWrittenMemory = "";
164
163
  this.lastWrittenUser = "";
165
164
  this.options = options;
@@ -174,14 +173,16 @@ export class FileStoreProvider {
174
173
  this.ctx = ctx;
175
174
  this.memoryFilePath = configFile(ctx.agentDir, "MEMORY.md");
176
175
  this.userFilePath = configFile(ctx.agentDir, "USER.md");
176
+ this.memoryStatePath = managedMemoryStateFile(ctx.agentDir, "MEMORY.md");
177
+ this.userStatePath = managedMemoryStateFile(ctx.agentDir, "USER.md");
177
178
  this.userArchive = new UserMemoryArchive(ctx.agentDir);
178
179
  await fs.mkdir(ctx.agentDir, { recursive: true });
179
180
  [this.lastWrittenMemory, this.lastWrittenUser] = await Promise.all([
180
- this.initializeManagedFile(this.memoryFilePath),
181
- this.initializeManagedFile(this.userFilePath),
181
+ this.initializeManagedFile(this.memoryFilePath, this.memoryStatePath),
182
+ this.initializeManagedFile(this.userFilePath, this.userStatePath),
182
183
  ]);
183
184
  }
184
- async initializeManagedFile(filePath) {
185
+ async initializeManagedFile(filePath, statePath) {
185
186
  return withFileLock(filePath, async () => {
186
187
  let current = "";
187
188
  try {
@@ -193,19 +194,19 @@ export class FileStoreProvider {
193
194
  await writeFileAtomic(filePath, "", { mode: 0o600 });
194
195
  }
195
196
  const currentDigest = contentDigest(current);
196
- const stateRead = await readManagedMemoryState(filePath);
197
+ const stateRead = await readManagedMemoryState(statePath);
197
198
  if (stateRead.status === "missing") {
198
- await writeManagedMemoryState(filePath, { version: 1, committedDigest: currentDigest });
199
+ await writeManagedMemoryState(statePath, { version: 1, committedDigest: currentDigest });
199
200
  return current;
200
201
  }
201
202
  if (stateRead.status === "invalid") {
202
- await writeFileAtomic(`${managedMemoryStatePath(filePath)}.bak.${Date.now()}.${randomUUID()}`, stateRead.raw, { mode: 0o600 });
203
- await writeManagedMemoryState(filePath, { version: 1, committedDigest: currentDigest });
203
+ await writeFileAtomic(`${statePath}.bak.${Date.now()}.${randomUUID()}`, stateRead.raw, { mode: 0o600 });
204
+ await writeManagedMemoryState(statePath, { version: 1, committedDigest: currentDigest });
204
205
  return current;
205
206
  }
206
207
  const reconciled = reconcileManagedMemoryState(currentDigest, stateRead.state);
207
208
  if (reconciled.recognized && reconciled.changed) {
208
- await writeManagedMemoryState(filePath, reconciled.state);
209
+ await writeManagedMemoryState(statePath, reconciled.state);
209
210
  }
210
211
  return current;
211
212
  });
@@ -308,19 +309,20 @@ export class FileStoreProvider {
308
309
  }
309
310
  }
310
311
  const filePath = target === "memory" ? this.memoryFilePath : this.userFilePath;
312
+ const statePath = target === "memory" ? this.memoryStatePath : this.userStatePath;
311
313
  const budget = target === "memory" ? FileStoreProvider.BUDGET_MEMORY : FileStoreProvider.BUDGET_USER;
312
314
  try {
313
315
  return await withFileLock(filePath, async () => {
314
316
  const currentOnDisk = await fs.readFile(filePath, "utf8");
315
317
  const currentDigest = contentDigest(currentOnDisk);
316
- const stateRead = await readManagedMemoryState(filePath);
318
+ const stateRead = await readManagedMemoryState(statePath);
317
319
  let managedState;
318
320
  if (stateRead.status === "valid") {
319
321
  const reconciled = reconcileManagedMemoryState(currentDigest, stateRead.state);
320
322
  if (reconciled.recognized) {
321
323
  managedState = reconciled.state;
322
324
  if (reconciled.changed)
323
- await writeManagedMemoryState(filePath, reconciled.state);
325
+ await writeManagedMemoryState(statePath, reconciled.state);
324
326
  }
325
327
  }
326
328
  if (!managedState) {
@@ -416,13 +418,13 @@ export class FileStoreProvider {
416
418
  }
417
419
  if (newContent !== currentOnDisk) {
418
420
  const newDigest = contentDigest(newContent);
419
- await writeManagedMemoryState(filePath, {
421
+ await writeManagedMemoryState(statePath, {
420
422
  version: 1,
421
423
  committedDigest: managedState.committedDigest,
422
424
  pendingDigest: newDigest,
423
425
  });
424
426
  await writeFileAtomic(filePath, newContent, { mode: 0o600 });
425
- await writeManagedMemoryState(filePath, { version: 1, committedDigest: newDigest });
427
+ await writeManagedMemoryState(statePath, { version: 1, committedDigest: newDigest });
426
428
  }
427
429
  if (target === "memory")
428
430
  this.lastWrittenMemory = newContent;