@caupulican/pi-adaptative 0.85.8 → 0.86.1

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 (232) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/core/agent-paths.d.ts +3 -3
  3. package/dist/core/agent-paths.d.ts.map +1 -1
  4. package/dist/core/agent-paths.js +3 -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/models/runtime-process.d.ts.map +1 -1
  90. package/dist/core/models/runtime-process.js +5 -18
  91. package/dist/core/models/runtime-process.js.map +1 -1
  92. package/dist/core/orchestration/bounded-string-array.d.ts +11 -0
  93. package/dist/core/orchestration/bounded-string-array.d.ts.map +1 -0
  94. package/dist/core/orchestration/bounded-string-array.js +17 -0
  95. package/dist/core/orchestration/bounded-string-array.js.map +1 -0
  96. package/dist/core/orchestration/capability-gateway.d.ts +16 -0
  97. package/dist/core/orchestration/capability-gateway.d.ts.map +1 -1
  98. package/dist/core/orchestration/capability-gateway.js +38 -0
  99. package/dist/core/orchestration/capability-gateway.js.map +1 -1
  100. package/dist/core/orchestration/contracts.d.ts +11 -3
  101. package/dist/core/orchestration/contracts.d.ts.map +1 -1
  102. package/dist/core/orchestration/contracts.js +0 -1
  103. package/dist/core/orchestration/contracts.js.map +1 -1
  104. package/dist/core/orchestration/delegation-ledger.d.ts +1 -0
  105. package/dist/core/orchestration/delegation-ledger.d.ts.map +1 -1
  106. package/dist/core/orchestration/delegation-ledger.js +3 -0
  107. package/dist/core/orchestration/delegation-ledger.js.map +1 -1
  108. package/dist/core/orchestration/event-store.d.ts +12 -10
  109. package/dist/core/orchestration/event-store.d.ts.map +1 -1
  110. package/dist/core/orchestration/event-store.js +94 -104
  111. package/dist/core/orchestration/event-store.js.map +1 -1
  112. package/dist/core/orchestration/lane-tool-manifests.d.ts +2 -2
  113. package/dist/core/orchestration/lane-tool-manifests.d.ts.map +1 -1
  114. package/dist/core/orchestration/lane-tool-manifests.js +4 -1
  115. package/dist/core/orchestration/lane-tool-manifests.js.map +1 -1
  116. package/dist/core/orchestration/policy-compiler.d.ts.map +1 -1
  117. package/dist/core/orchestration/policy-compiler.js +8 -9
  118. package/dist/core/orchestration/policy-compiler.js.map +1 -1
  119. package/dist/core/orchestration/profile-registry.d.ts.map +1 -1
  120. package/dist/core/orchestration/profile-registry.js +4 -10
  121. package/dist/core/orchestration/profile-registry.js.map +1 -1
  122. package/dist/core/orchestration/task-runtime.d.ts +1 -0
  123. package/dist/core/orchestration/task-runtime.d.ts.map +1 -1
  124. package/dist/core/orchestration/task-runtime.js +58 -3
  125. package/dist/core/orchestration/task-runtime.js.map +1 -1
  126. package/dist/core/orchestration/worker-execution-contract.d.ts.map +1 -1
  127. package/dist/core/orchestration/worker-execution-contract.js +10 -17
  128. package/dist/core/orchestration/worker-execution-contract.js.map +1 -1
  129. package/dist/core/risk-classifier.js +3 -3
  130. package/dist/core/risk-classifier.js.map +1 -1
  131. package/dist/core/runtime-builder.d.ts +4 -1
  132. package/dist/core/runtime-builder.d.ts.map +1 -1
  133. package/dist/core/runtime-builder.js +34 -15
  134. package/dist/core/runtime-builder.js.map +1 -1
  135. package/dist/core/secrets/bitwarden-credential-storage.d.ts +51 -0
  136. package/dist/core/secrets/bitwarden-credential-storage.d.ts.map +1 -0
  137. package/dist/core/secrets/bitwarden-credential-storage.js +345 -0
  138. package/dist/core/secrets/bitwarden-credential-storage.js.map +1 -0
  139. package/dist/core/secrets/credential-exposure-guard.d.ts +8 -4
  140. package/dist/core/secrets/credential-exposure-guard.d.ts.map +1 -1
  141. package/dist/core/secrets/credential-exposure-guard.js +31 -29
  142. package/dist/core/secrets/credential-exposure-guard.js.map +1 -1
  143. package/dist/core/secrets/credential-manager.d.ts +109 -0
  144. package/dist/core/secrets/credential-manager.d.ts.map +1 -0
  145. package/dist/core/secrets/credential-manager.js +384 -0
  146. package/dist/core/secrets/credential-manager.js.map +1 -0
  147. package/dist/core/secrets/credential-project.d.ts +4 -0
  148. package/dist/core/secrets/credential-project.d.ts.map +1 -0
  149. package/dist/core/secrets/credential-project.js +145 -0
  150. package/dist/core/secrets/credential-project.js.map +1 -0
  151. package/dist/core/secrets/secret-dotenv.d.ts +1 -1
  152. package/dist/core/secrets/secret-dotenv.js +1 -1
  153. package/dist/core/secrets/secret-dotenv.js.map +1 -1
  154. package/dist/core/settings-manager.d.ts +4 -2
  155. package/dist/core/settings-manager.d.ts.map +1 -1
  156. package/dist/core/settings-manager.js +9 -5
  157. package/dist/core/settings-manager.js.map +1 -1
  158. package/dist/core/slash-commands.d.ts.map +1 -1
  159. package/dist/core/slash-commands.js +1 -0
  160. package/dist/core/slash-commands.js.map +1 -1
  161. package/dist/core/system-prompt.js +1 -1
  162. package/dist/core/system-prompt.js.map +1 -1
  163. package/dist/core/tool-capability-policy.js +2 -2
  164. package/dist/core/tool-capability-policy.js.map +1 -1
  165. package/dist/core/tools/delegate.d.ts +29 -1
  166. package/dist/core/tools/delegate.d.ts.map +1 -1
  167. package/dist/core/tools/delegate.js +179 -28
  168. package/dist/core/tools/delegate.js.map +1 -1
  169. package/dist/core/tools/git-filter.d.ts +1 -0
  170. package/dist/core/tools/git-filter.d.ts.map +1 -1
  171. package/dist/core/tools/git-filter.js +1 -1
  172. package/dist/core/tools/git-filter.js.map +1 -1
  173. package/dist/core/tools/profile-writer.js +3 -3
  174. package/dist/core/tools/profile-writer.js.map +1 -1
  175. package/dist/core/tools/python.d.ts +2 -0
  176. package/dist/core/tools/python.d.ts.map +1 -1
  177. package/dist/core/tools/python.js +17 -12
  178. package/dist/core/tools/python.js.map +1 -1
  179. package/dist/core/tools/run-process.d.ts +2 -0
  180. package/dist/core/tools/run-process.d.ts.map +1 -1
  181. package/dist/core/tools/run-process.js +7 -3
  182. package/dist/core/tools/run-process.js.map +1 -1
  183. package/dist/core/tools/secret-store.d.ts +8 -18
  184. package/dist/core/tools/secret-store.d.ts.map +1 -1
  185. package/dist/core/tools/secret-store.js +83 -348
  186. package/dist/core/tools/secret-store.js.map +1 -1
  187. package/dist/index.d.ts +3 -1
  188. package/dist/index.d.ts.map +1 -1
  189. package/dist/index.js +3 -1
  190. package/dist/index.js.map +1 -1
  191. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  192. package/dist/modes/interactive/components/settings-selector.js +35 -14
  193. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  194. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  195. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  196. package/dist/modes/interactive/interactive-mode.js +26 -3
  197. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  198. package/dist/modes/interactive/secret-menu-controller.d.ts +21 -0
  199. package/dist/modes/interactive/secret-menu-controller.d.ts.map +1 -0
  200. package/dist/modes/interactive/secret-menu-controller.js +276 -0
  201. package/dist/modes/interactive/secret-menu-controller.js.map +1 -0
  202. package/dist/utils/tools-manager.d.ts +2 -1
  203. package/dist/utils/tools-manager.d.ts.map +1 -1
  204. package/dist/utils/tools-manager.js +43 -48
  205. package/dist/utils/tools-manager.js.map +1 -1
  206. package/dist/utils/zip-extractor.d.ts +8 -0
  207. package/dist/utils/zip-extractor.d.ts.map +1 -0
  208. package/dist/utils/zip-extractor.js +275 -0
  209. package/dist/utils/zip-extractor.js.map +1 -0
  210. package/docs/harness-architecture.md +34 -22
  211. package/docs/index.md +1 -1
  212. package/docs/resources.md +1 -1
  213. package/docs/settings.md +39 -103
  214. package/docs/usage.md +7 -5
  215. package/docs/worker-profiles.md +9 -7
  216. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  217. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  218. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  219. package/examples/extensions/sandbox/package-lock.json +2 -2
  220. package/examples/extensions/sandbox/package.json +1 -1
  221. package/examples/extensions/with-deps/package-lock.json +2 -2
  222. package/examples/extensions/with-deps/package.json +1 -1
  223. package/npm-shrinkwrap.json +12 -12
  224. package/package.json +4 -4
  225. package/dist/core/secrets/secret-vault-format.d.ts +0 -112
  226. package/dist/core/secrets/secret-vault-format.d.ts.map +0 -1
  227. package/dist/core/secrets/secret-vault-format.js +0 -396
  228. package/dist/core/secrets/secret-vault-format.js.map +0 -1
  229. package/dist/core/secrets/secret-vault.d.ts +0 -72
  230. package/dist/core/secrets/secret-vault.d.ts.map +0 -1
  231. package/dist/core/secrets/secret-vault.js +0 -663
  232. 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"]}
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-process.d.ts","sourceRoot":"","sources":["../../../src/core/models/runtime-process.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtime-process.d.ts","sourceRoot":"","sources":["../../../src/core/models/runtime-process.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,7 @@ import { join } from "node:path";
4
4
  import { pipeline } from "node:stream/promises";
5
5
  import { spawnProcess, spawnProcessSync, waitForChildProcessWithTermination } from "../../utils/child-process.js";
6
6
  import { sleep } from "../../utils/sleep.js";
7
+ import { extractZipFile } from "../../utils/zip-extractor.js";
7
8
  import { createRollingOutputBuffer } from "../exec.js";
8
9
  const DEFAULT_RUNTIME_OUTPUT_UNITS = 1024 * 1024;
9
10
  /**
@@ -158,26 +159,12 @@ export async function extractZipArchive(options) {
158
159
  const zipPath = join(options.destDir, "..", `${options.tempPrefix}-${process.pid}-${Date.now()}.zip`);
159
160
  try {
160
161
  await pipeline(options.input, createWriteStream(zipPath));
161
- const extractCommand = options.platform() === "win32" && options.hasCommand("tar") ? "tar" : "unzip";
162
- const args = extractCommand === "tar" ? ["-xf", zipPath, "-C", options.destDir] : ["-q", zipPath, "-d", options.destDir];
163
- const proc = spawnProcess(extractCommand, args, {
164
- detached: process.platform !== "win32",
165
- stdio: "ignore",
166
- });
167
- const terminal = await waitForChildProcessWithTermination(proc, {
168
- timeoutMs: options.timeoutMs,
169
- killGraceMs: options.killGraceMs,
170
- });
171
- if (terminal.reason === "timeout" || terminal.code !== 0) {
172
- return {
173
- ok: false,
174
- error: terminal.reason === "timeout"
175
- ? `extract-fail: ${extractCommand} timed out after ${options.timeoutMs}ms`
176
- : `extract-fail: ${extractCommand} exited with code ${terminal.code ?? "unknown"}`,
177
- };
178
- }
162
+ await extractZipFile(zipPath, options.destDir);
179
163
  return { ok: true };
180
164
  }
165
+ catch (error) {
166
+ return { ok: false, error: `extract-fail: ${error instanceof Error ? error.message : String(error)}` };
167
+ }
181
168
  finally {
182
169
  removePartialDownload(zipPath);
183
170
  }
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-process.js","sourceRoot":"","sources":["../../../src/core/models/runtime-process.ts"],"names":[],"mappings":"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","sourcesContent":["import { type ChildProcess, spawn } from \"node:child_process\";\nimport { createWriteStream, existsSync, mkdirSync, rmSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Readable, Transform, Writable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport { spawnProcess, spawnProcessSync, waitForChildProcessWithTermination } from \"../../utils/child-process.ts\";\nimport { sleep } from \"../../utils/sleep.ts\";\nimport { createRollingOutputBuffer } from \"../exec.ts\";\n\nexport interface RuntimeCommandResult {\n\tok: boolean;\n\tstdout: string;\n\tstderr: string;\n\tcode?: number | null;\n\terror?: string;\n}\n\nexport interface RuntimeCommandOptions {\n\tenv?: NodeJS.ProcessEnv;\n\tonOutput?: (chunk: string) => void;\n}\n\nexport type RuntimeCommandRunner = (\n\tcommand: string,\n\targs: string[],\n\toptions?: RuntimeCommandOptions,\n) => Promise<RuntimeCommandResult>;\n\nexport interface RuntimeCommandRunnerLimits {\n\ttimeoutMs: number;\n\tkillGraceMs: number;\n\tmaxOutputUnits?: number;\n}\n\nconst DEFAULT_RUNTIME_OUTPUT_UNITS = 1024 * 1024;\n\n/**\n * Build a runtime-management command runner with one bounded process lifecycle.\n * Output is retained as chunk tails and flattened once, after the child reaches a terminal state.\n */\nexport function createRuntimeCommandRunner(limits: RuntimeCommandRunnerLimits): RuntimeCommandRunner {\n\tconst requestedOutputUnits = limits.maxOutputUnits ?? DEFAULT_RUNTIME_OUTPUT_UNITS;\n\tconst maxOutputUnits =\n\t\tNumber.isFinite(requestedOutputUnits) && requestedOutputUnits > 0\n\t\t\t? Math.floor(requestedOutputUnits)\n\t\t\t: DEFAULT_RUNTIME_OUTPUT_UNITS;\n\treturn async (command, args, options = {}) => {\n\t\ttry {\n\t\t\tconst proc = spawnProcess(command, args, {\n\t\t\t\tdetached: process.platform !== \"win32\",\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\t\tenv: options.env ? { ...process.env, ...options.env } : process.env,\n\t\t\t});\n\t\t\tconst stdout = createRollingOutputBuffer(maxOutputUnits);\n\t\t\tconst stderr = createRollingOutputBuffer(maxOutputUnits);\n\t\t\tproc.stdout.setEncoding(\"utf8\");\n\t\t\tproc.stderr.setEncoding(\"utf8\");\n\t\t\tproc.stdout.on(\"data\", (chunk: string) => {\n\t\t\t\tstdout.push(chunk);\n\t\t\t\toptions.onOutput?.(chunk);\n\t\t\t});\n\t\t\tproc.stderr.on(\"data\", (chunk: string) => {\n\t\t\t\tstderr.push(chunk);\n\t\t\t\toptions.onOutput?.(chunk);\n\t\t\t});\n\t\t\tconst terminal = await waitForChildProcessWithTermination(proc, {\n\t\t\t\ttimeoutMs: limits.timeoutMs,\n\t\t\t\tkillGraceMs: limits.killGraceMs,\n\t\t\t});\n\t\t\tconst stdoutText = stdout.text();\n\t\t\tconst stderrText = stderr.text();\n\t\t\treturn {\n\t\t\t\tok: terminal.code === 0,\n\t\t\t\tstdout: stdoutText,\n\t\t\t\tstderr: stderrText,\n\t\t\t\tcode: terminal.code,\n\t\t\t\t...(terminal.code === 0\n\t\t\t\t\t? {}\n\t\t\t\t\t: {\n\t\t\t\t\t\t\terror:\n\t\t\t\t\t\t\t\tterminal.reason === \"timeout\"\n\t\t\t\t\t\t\t\t\t? `${command} timed out after ${limits.timeoutMs}ms`\n\t\t\t\t\t\t\t\t\t: stderrText.trim() || stdoutText.trim() || `exit code ${terminal.code ?? \"unknown\"}`,\n\t\t\t\t\t\t}),\n\t\t\t};\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tstdout: \"\",\n\t\t\t\tstderr: \"\",\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t};\n\t\t}\n\t};\n}\n\ntype RuntimeCommandProbe = (\n\tcommand: string,\n\targs: string[],\n\toptions: { encoding: \"utf8\"; timeout: number },\n) => { error?: unknown };\n\nexport function runtimeCommandAvailable(command: string, probe: RuntimeCommandProbe = spawnProcessSync): boolean {\n\t// Node returns `undefined` on success; cross-spawn normalizes that field to `null` on Windows.\n\t// Both are the absence of an error. A strict undefined check made every Windows probe fail.\n\treturn probe(command, [\"--version\"], { encoding: \"utf8\", timeout: 5_000 }).error == null;\n}\n\nexport function runtimeSleep(ms: number): Promise<void> {\n\treturn sleep(ms);\n}\n\nexport type ManagedRuntimeChild = Pick<ChildProcess, \"pid\" | \"kill\" | \"unref\" | \"on\">;\nexport interface ManagedRuntimeSpawnOptions {\n\tdetached?: boolean;\n\tstdio?: \"ignore\";\n\tenv: NodeJS.ProcessEnv;\n}\nexport type ManagedRuntimeSpawn = (\n\tcommand: string,\n\targs: string[],\n\toptions: ManagedRuntimeSpawnOptions,\n) => ManagedRuntimeChild;\n\nexport function spawnManagedRuntime(\n\tcommand: string,\n\targs: string[],\n\toptions: ManagedRuntimeSpawnOptions,\n): ManagedRuntimeChild {\n\treturn spawn(command, args, { ...options, stdio: \"ignore\" });\n}\n\nexport interface RuntimeLifecycleDependencyOverrides {\n\tfetchFn?: typeof fetch;\n\tspawnFn?: ManagedRuntimeSpawn;\n\texistsFn?: (path: string) => boolean;\n\tsleepFn?: (ms: number) => Promise<void>;\n}\n\nexport type RuntimeLifecycleDependencies = readonly [\n\tfetchFn: typeof fetch,\n\tspawnFn: ManagedRuntimeSpawn,\n\texistsFn: (path: string) => boolean,\n\tsleepFn: (ms: number) => Promise<void>,\n];\n\n/** Resolve the common runtime lifecycle boundary once, during construction. */\nexport function resolveRuntimeLifecycleDependencies(\n\toverrides?: RuntimeLifecycleDependencyOverrides,\n): RuntimeLifecycleDependencies {\n\treturn [\n\t\toverrides?.fetchFn ?? fetch,\n\t\toverrides?.spawnFn ?? spawnManagedRuntime,\n\t\toverrides?.existsFn ?? existsSync,\n\t\toverrides?.sleepFn ?? runtimeSleep,\n\t];\n}\n\nexport type RuntimeDownloadResult =\n\t| { ok: true; response: Response; body: ReadableStream<Uint8Array> }\n\t| { ok: false; error: string };\n\ntype RuntimeFetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;\n\n/** Validate a runtime download without consuming, decoding, or copying its response body. */\nexport async function fetchRuntimeDownload(\n\tfetchFn: RuntimeFetch,\n\turl: string,\n\tinit?: RequestInit,\n): Promise<RuntimeDownloadResult> {\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetchFn(url, init);\n\t} catch (error) {\n\t\treturn { ok: false, error: `download-fail: ${error instanceof Error ? error.message : String(error)}` };\n\t}\n\tif (!response.ok || !response.body) return { ok: false, error: `download-fail: HTTP ${response.status}` };\n\treturn { ok: true, response, body: response.body };\n}\n\n/** Download and extract a runtime archive without materializing or copying its body. */\nexport async function installRuntimeArchive<TInput extends NodeJS.ReadableStream, TKind extends string>(\n\tfetchFn: RuntimeFetch,\n\tdownloadUrl: string,\n\tdestDir: string,\n\tasset: { name: string; kind: TKind },\n\textractArchive: (input: TInput, destDir: string, kind: TKind) => Promise<{ ok: boolean; error?: string }>,\n\tonProgress?: (status: string) => void,\n): Promise<{ ok: boolean; error?: string }> {\n\tonProgress?.(`Downloading ${asset.name}…`);\n\tconst download = await fetchRuntimeDownload(fetchFn, downloadUrl);\n\tif (!download.ok) return download;\n\tmkdirSync(destDir, { recursive: true });\n\tonProgress?.(`Extracting ${asset.name}…`);\n\treturn extractArchive(download.body as unknown as TInput, destDir, asset.kind);\n}\n\nexport function tryFileSizeBytes(path: string): number | undefined {\n\ttry {\n\t\treturn statSync(path).size;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function removePartialDownload(path: string): void {\n\ttry {\n\t\trmSync(path, { force: true });\n\t} catch {\n\t\t// best-effort cleanup\n\t}\n}\n\n/** Wait for a failed pipeline's file descriptor to close before deleting its partial output. */\nexport function waitForWritableClosed(stream: Writable & { closed?: boolean }): Promise<void> {\n\tif (stream.closed) return Promise.resolve();\n\treturn new Promise((resolve) => {\n\t\tstream.once(\"close\", resolve);\n\t\tstream.destroy();\n\t});\n}\n\n/** Stream a runtime payload to disk, closing and deleting partial output on any failure. */\nexport async function writeRuntimeDownload(\n\tinput: Readable,\n\tdestPath: string,\n\ttransform?: Transform,\n): Promise<{ ok: true } | { ok: false; error: string }> {\n\tconst writeStream = createWriteStream(destPath);\n\ttry {\n\t\tif (transform) await pipeline(input, transform, writeStream);\n\t\telse await pipeline(input, writeStream);\n\t\treturn { ok: true };\n\t} catch (error) {\n\t\tawait waitForWritableClosed(writeStream);\n\t\tremovePartialDownload(destPath);\n\t\treturn { ok: false, error: `download-fail: ${error instanceof Error ? error.message : String(error)}` };\n\t}\n}\n\nexport function requireRuntimeStdin(proc: ChildProcess, label: string): Writable {\n\tif (!proc.stdin) throw new Error(`${label}: no stdin pipe`);\n\treturn proc.stdin;\n}\n\nexport interface ExtractZipArchiveOptions {\n\tinput: Readable;\n\tdestDir: string;\n\ttempPrefix: string;\n\tplatform: () => string;\n\thasCommand: (command: string) => boolean;\n\ttimeoutMs: number;\n\tkillGraceMs: number;\n}\n\n/** Shared seekable-file extraction path for managed runtime zip archives. */\nexport async function extractZipArchive(options: ExtractZipArchiveOptions): Promise<{ ok: boolean; error?: string }> {\n\tconst zipPath = join(options.destDir, \"..\", `${options.tempPrefix}-${process.pid}-${Date.now()}.zip`);\n\ttry {\n\t\tawait pipeline(options.input, createWriteStream(zipPath));\n\t\tconst extractCommand = options.platform() === \"win32\" && options.hasCommand(\"tar\") ? \"tar\" : \"unzip\";\n\t\tconst args =\n\t\t\textractCommand === \"tar\" ? [\"-xf\", zipPath, \"-C\", options.destDir] : [\"-q\", zipPath, \"-d\", options.destDir];\n\t\tconst proc = spawnProcess(extractCommand, args, {\n\t\t\tdetached: process.platform !== \"win32\",\n\t\t\tstdio: \"ignore\",\n\t\t});\n\t\tconst terminal = await waitForChildProcessWithTermination(proc, {\n\t\t\ttimeoutMs: options.timeoutMs,\n\t\t\tkillGraceMs: options.killGraceMs,\n\t\t});\n\t\tif (terminal.reason === \"timeout\" || terminal.code !== 0) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror:\n\t\t\t\t\tterminal.reason === \"timeout\"\n\t\t\t\t\t\t? `extract-fail: ${extractCommand} timed out after ${options.timeoutMs}ms`\n\t\t\t\t\t\t: `extract-fail: ${extractCommand} exited with code ${terminal.code ?? \"unknown\"}`,\n\t\t\t};\n\t\t}\n\t\treturn { ok: true };\n\t} finally {\n\t\tremovePartialDownload(zipPath);\n\t}\n}\n"]}
1
+ {"version":3,"file":"runtime-process.js","sourceRoot":"","sources":["../../../src/core/models/runtime-process.ts"],"names":[],"mappings":"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","sourcesContent":["import { type ChildProcess, spawn } from \"node:child_process\";\nimport { createWriteStream, existsSync, mkdirSync, rmSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Readable, Transform, Writable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport { spawnProcess, spawnProcessSync, waitForChildProcessWithTermination } from \"../../utils/child-process.ts\";\nimport { sleep } from \"../../utils/sleep.ts\";\nimport { extractZipFile } from \"../../utils/zip-extractor.ts\";\nimport { createRollingOutputBuffer } from \"../exec.ts\";\n\nexport interface RuntimeCommandResult {\n\tok: boolean;\n\tstdout: string;\n\tstderr: string;\n\tcode?: number | null;\n\terror?: string;\n}\n\nexport interface RuntimeCommandOptions {\n\tenv?: NodeJS.ProcessEnv;\n\tonOutput?: (chunk: string) => void;\n}\n\nexport type RuntimeCommandRunner = (\n\tcommand: string,\n\targs: string[],\n\toptions?: RuntimeCommandOptions,\n) => Promise<RuntimeCommandResult>;\n\nexport interface RuntimeCommandRunnerLimits {\n\ttimeoutMs: number;\n\tkillGraceMs: number;\n\tmaxOutputUnits?: number;\n}\n\nconst DEFAULT_RUNTIME_OUTPUT_UNITS = 1024 * 1024;\n\n/**\n * Build a runtime-management command runner with one bounded process lifecycle.\n * Output is retained as chunk tails and flattened once, after the child reaches a terminal state.\n */\nexport function createRuntimeCommandRunner(limits: RuntimeCommandRunnerLimits): RuntimeCommandRunner {\n\tconst requestedOutputUnits = limits.maxOutputUnits ?? DEFAULT_RUNTIME_OUTPUT_UNITS;\n\tconst maxOutputUnits =\n\t\tNumber.isFinite(requestedOutputUnits) && requestedOutputUnits > 0\n\t\t\t? Math.floor(requestedOutputUnits)\n\t\t\t: DEFAULT_RUNTIME_OUTPUT_UNITS;\n\treturn async (command, args, options = {}) => {\n\t\ttry {\n\t\t\tconst proc = spawnProcess(command, args, {\n\t\t\t\tdetached: process.platform !== \"win32\",\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\t\tenv: options.env ? { ...process.env, ...options.env } : process.env,\n\t\t\t});\n\t\t\tconst stdout = createRollingOutputBuffer(maxOutputUnits);\n\t\t\tconst stderr = createRollingOutputBuffer(maxOutputUnits);\n\t\t\tproc.stdout.setEncoding(\"utf8\");\n\t\t\tproc.stderr.setEncoding(\"utf8\");\n\t\t\tproc.stdout.on(\"data\", (chunk: string) => {\n\t\t\t\tstdout.push(chunk);\n\t\t\t\toptions.onOutput?.(chunk);\n\t\t\t});\n\t\t\tproc.stderr.on(\"data\", (chunk: string) => {\n\t\t\t\tstderr.push(chunk);\n\t\t\t\toptions.onOutput?.(chunk);\n\t\t\t});\n\t\t\tconst terminal = await waitForChildProcessWithTermination(proc, {\n\t\t\t\ttimeoutMs: limits.timeoutMs,\n\t\t\t\tkillGraceMs: limits.killGraceMs,\n\t\t\t});\n\t\t\tconst stdoutText = stdout.text();\n\t\t\tconst stderrText = stderr.text();\n\t\t\treturn {\n\t\t\t\tok: terminal.code === 0,\n\t\t\t\tstdout: stdoutText,\n\t\t\t\tstderr: stderrText,\n\t\t\t\tcode: terminal.code,\n\t\t\t\t...(terminal.code === 0\n\t\t\t\t\t? {}\n\t\t\t\t\t: {\n\t\t\t\t\t\t\terror:\n\t\t\t\t\t\t\t\tterminal.reason === \"timeout\"\n\t\t\t\t\t\t\t\t\t? `${command} timed out after ${limits.timeoutMs}ms`\n\t\t\t\t\t\t\t\t\t: stderrText.trim() || stdoutText.trim() || `exit code ${terminal.code ?? \"unknown\"}`,\n\t\t\t\t\t\t}),\n\t\t\t};\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tstdout: \"\",\n\t\t\t\tstderr: \"\",\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t};\n\t\t}\n\t};\n}\n\ntype RuntimeCommandProbe = (\n\tcommand: string,\n\targs: string[],\n\toptions: { encoding: \"utf8\"; timeout: number },\n) => { error?: unknown };\n\nexport function runtimeCommandAvailable(command: string, probe: RuntimeCommandProbe = spawnProcessSync): boolean {\n\t// Node returns `undefined` on success; cross-spawn normalizes that field to `null` on Windows.\n\t// Both are the absence of an error. A strict undefined check made every Windows probe fail.\n\treturn probe(command, [\"--version\"], { encoding: \"utf8\", timeout: 5_000 }).error == null;\n}\n\nexport function runtimeSleep(ms: number): Promise<void> {\n\treturn sleep(ms);\n}\n\nexport type ManagedRuntimeChild = Pick<ChildProcess, \"pid\" | \"kill\" | \"unref\" | \"on\">;\nexport interface ManagedRuntimeSpawnOptions {\n\tdetached?: boolean;\n\tstdio?: \"ignore\";\n\tenv: NodeJS.ProcessEnv;\n}\nexport type ManagedRuntimeSpawn = (\n\tcommand: string,\n\targs: string[],\n\toptions: ManagedRuntimeSpawnOptions,\n) => ManagedRuntimeChild;\n\nexport function spawnManagedRuntime(\n\tcommand: string,\n\targs: string[],\n\toptions: ManagedRuntimeSpawnOptions,\n): ManagedRuntimeChild {\n\treturn spawn(command, args, { ...options, stdio: \"ignore\" });\n}\n\nexport interface RuntimeLifecycleDependencyOverrides {\n\tfetchFn?: typeof fetch;\n\tspawnFn?: ManagedRuntimeSpawn;\n\texistsFn?: (path: string) => boolean;\n\tsleepFn?: (ms: number) => Promise<void>;\n}\n\nexport type RuntimeLifecycleDependencies = readonly [\n\tfetchFn: typeof fetch,\n\tspawnFn: ManagedRuntimeSpawn,\n\texistsFn: (path: string) => boolean,\n\tsleepFn: (ms: number) => Promise<void>,\n];\n\n/** Resolve the common runtime lifecycle boundary once, during construction. */\nexport function resolveRuntimeLifecycleDependencies(\n\toverrides?: RuntimeLifecycleDependencyOverrides,\n): RuntimeLifecycleDependencies {\n\treturn [\n\t\toverrides?.fetchFn ?? fetch,\n\t\toverrides?.spawnFn ?? spawnManagedRuntime,\n\t\toverrides?.existsFn ?? existsSync,\n\t\toverrides?.sleepFn ?? runtimeSleep,\n\t];\n}\n\nexport type RuntimeDownloadResult =\n\t| { ok: true; response: Response; body: ReadableStream<Uint8Array> }\n\t| { ok: false; error: string };\n\ntype RuntimeFetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;\n\n/** Validate a runtime download without consuming, decoding, or copying its response body. */\nexport async function fetchRuntimeDownload(\n\tfetchFn: RuntimeFetch,\n\turl: string,\n\tinit?: RequestInit,\n): Promise<RuntimeDownloadResult> {\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetchFn(url, init);\n\t} catch (error) {\n\t\treturn { ok: false, error: `download-fail: ${error instanceof Error ? error.message : String(error)}` };\n\t}\n\tif (!response.ok || !response.body) return { ok: false, error: `download-fail: HTTP ${response.status}` };\n\treturn { ok: true, response, body: response.body };\n}\n\n/** Download and extract a runtime archive without materializing or copying its body. */\nexport async function installRuntimeArchive<TInput extends NodeJS.ReadableStream, TKind extends string>(\n\tfetchFn: RuntimeFetch,\n\tdownloadUrl: string,\n\tdestDir: string,\n\tasset: { name: string; kind: TKind },\n\textractArchive: (input: TInput, destDir: string, kind: TKind) => Promise<{ ok: boolean; error?: string }>,\n\tonProgress?: (status: string) => void,\n): Promise<{ ok: boolean; error?: string }> {\n\tonProgress?.(`Downloading ${asset.name}…`);\n\tconst download = await fetchRuntimeDownload(fetchFn, downloadUrl);\n\tif (!download.ok) return download;\n\tmkdirSync(destDir, { recursive: true });\n\tonProgress?.(`Extracting ${asset.name}…`);\n\treturn extractArchive(download.body as unknown as TInput, destDir, asset.kind);\n}\n\nexport function tryFileSizeBytes(path: string): number | undefined {\n\ttry {\n\t\treturn statSync(path).size;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function removePartialDownload(path: string): void {\n\ttry {\n\t\trmSync(path, { force: true });\n\t} catch {\n\t\t// best-effort cleanup\n\t}\n}\n\n/** Wait for a failed pipeline's file descriptor to close before deleting its partial output. */\nexport function waitForWritableClosed(stream: Writable & { closed?: boolean }): Promise<void> {\n\tif (stream.closed) return Promise.resolve();\n\treturn new Promise((resolve) => {\n\t\tstream.once(\"close\", resolve);\n\t\tstream.destroy();\n\t});\n}\n\n/** Stream a runtime payload to disk, closing and deleting partial output on any failure. */\nexport async function writeRuntimeDownload(\n\tinput: Readable,\n\tdestPath: string,\n\ttransform?: Transform,\n): Promise<{ ok: true } | { ok: false; error: string }> {\n\tconst writeStream = createWriteStream(destPath);\n\ttry {\n\t\tif (transform) await pipeline(input, transform, writeStream);\n\t\telse await pipeline(input, writeStream);\n\t\treturn { ok: true };\n\t} catch (error) {\n\t\tawait waitForWritableClosed(writeStream);\n\t\tremovePartialDownload(destPath);\n\t\treturn { ok: false, error: `download-fail: ${error instanceof Error ? error.message : String(error)}` };\n\t}\n}\n\nexport function requireRuntimeStdin(proc: ChildProcess, label: string): Writable {\n\tif (!proc.stdin) throw new Error(`${label}: no stdin pipe`);\n\treturn proc.stdin;\n}\n\nexport interface ExtractZipArchiveOptions {\n\tinput: Readable;\n\tdestDir: string;\n\ttempPrefix: string;\n\tplatform: () => string;\n\thasCommand: (command: string) => boolean;\n\ttimeoutMs: number;\n\tkillGraceMs: number;\n}\n\n/** Shared seekable-file extraction path for managed runtime zip archives. */\nexport async function extractZipArchive(options: ExtractZipArchiveOptions): Promise<{ ok: boolean; error?: string }> {\n\tconst zipPath = join(options.destDir, \"..\", `${options.tempPrefix}-${process.pid}-${Date.now()}.zip`);\n\ttry {\n\t\tawait pipeline(options.input, createWriteStream(zipPath));\n\t\tawait extractZipFile(zipPath, options.destDir);\n\t\treturn { ok: true };\n\t} catch (error) {\n\t\treturn { ok: false, error: `extract-fail: ${error instanceof Error ? error.message : String(error)}` };\n\t} finally {\n\t\tremovePartialDownload(zipPath);\n\t}\n}\n"]}
@@ -0,0 +1,11 @@
1
+ export interface BoundedStringArrayOptions {
2
+ maxEntries?: number;
3
+ maxLength?: number;
4
+ trim?: boolean;
5
+ invalidMessage: string;
6
+ duplicateMessage: string;
7
+ createError(message: string): Error;
8
+ }
9
+ /** Mandatory parser for unique string collections crossing the orchestration trust boundary. */
10
+ export declare function parseBoundedStringArray(value: unknown, options: BoundedStringArrayOptions): string[];
11
+ //# sourceMappingURL=bounded-string-array.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounded-string-array.d.ts","sourceRoot":"","sources":["../../../src/core/orchestration/bounded-string-array.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,yBAAyB;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC;CACpC;AAED,gGAAgG;AAChG,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,yBAAyB,GAAG,MAAM,EAAE,CAYpG"}
@@ -0,0 +1,17 @@
1
+ import { MAX_ORCHESTRATION_COLLECTION_LENGTH, MAX_ORCHESTRATION_IDENTIFIER_LENGTH } from "./contracts.js";
2
+ /** Mandatory parser for unique string collections crossing the orchestration trust boundary. */
3
+ export function parseBoundedStringArray(value, options) {
4
+ const maxEntries = options.maxEntries ?? MAX_ORCHESTRATION_COLLECTION_LENGTH;
5
+ const maxLength = options.maxLength ?? MAX_ORCHESTRATION_IDENTIFIER_LENGTH;
6
+ if (!Array.isArray(value) || value.length > maxEntries || !value.every((entry) => typeof entry === "string")) {
7
+ throw options.createError(options.invalidMessage);
8
+ }
9
+ const strings = value.map((entry) => (options.trim ? entry.trim() : entry));
10
+ if (strings.some((entry) => entry.length === 0 || entry.length > maxLength)) {
11
+ throw options.createError(options.invalidMessage);
12
+ }
13
+ if (new Set(strings).size !== strings.length)
14
+ throw options.createError(options.duplicateMessage);
15
+ return strings;
16
+ }
17
+ //# sourceMappingURL=bounded-string-array.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounded-string-array.js","sourceRoot":"","sources":["../../../src/core/orchestration/bounded-string-array.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mCAAmC,EAAE,mCAAmC,EAAE,MAAM,gBAAgB,CAAC;AAW1G,gGAAgG;AAChG,MAAM,UAAU,uBAAuB,CAAC,KAAc,EAAE,OAAkC;IACzF,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,mCAAmC,CAAC;IAC7E,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,mCAAmC,CAAC;IAC3E,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,UAAU,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,EAAE,CAAC;QAC9G,MAAM,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACnD,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5E,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,CAAC;QAC7E,MAAM,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM;QAAE,MAAM,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAClG,OAAO,OAAO,CAAC;AAChB,CAAC","sourcesContent":["import { MAX_ORCHESTRATION_COLLECTION_LENGTH, MAX_ORCHESTRATION_IDENTIFIER_LENGTH } from \"./contracts.ts\";\n\nexport interface BoundedStringArrayOptions {\n\tmaxEntries?: number;\n\tmaxLength?: number;\n\ttrim?: boolean;\n\tinvalidMessage: string;\n\tduplicateMessage: string;\n\tcreateError(message: string): Error;\n}\n\n/** Mandatory parser for unique string collections crossing the orchestration trust boundary. */\nexport function parseBoundedStringArray(value: unknown, options: BoundedStringArrayOptions): string[] {\n\tconst maxEntries = options.maxEntries ?? MAX_ORCHESTRATION_COLLECTION_LENGTH;\n\tconst maxLength = options.maxLength ?? MAX_ORCHESTRATION_IDENTIFIER_LENGTH;\n\tif (!Array.isArray(value) || value.length > maxEntries || !value.every((entry) => typeof entry === \"string\")) {\n\t\tthrow options.createError(options.invalidMessage);\n\t}\n\tconst strings = value.map((entry) => (options.trim ? entry.trim() : entry));\n\tif (strings.some((entry) => entry.length === 0 || entry.length > maxLength)) {\n\t\tthrow options.createError(options.invalidMessage);\n\t}\n\tif (new Set(strings).size !== strings.length) throw options.createError(options.duplicateMessage);\n\treturn strings;\n}\n"]}
@@ -15,6 +15,8 @@ export interface CapabilityGatewayOptions {
15
15
  initialUsage?: GatewayInitialUsage;
16
16
  now?: () => number;
17
17
  onAudit?: (record: GatewayAuditRecord) => void;
18
+ /** Session-tree cumulative budget owner. Per-attempt grants remain independently enforced. */
19
+ sharedBudget?: SharedCapabilityBudget;
18
20
  }
19
21
  export interface GatewayUsageDelta {
20
22
  inputTokens?: number;
@@ -35,6 +37,16 @@ export interface GatewayUsageSnapshot {
35
37
  costUsd: number;
36
38
  wallClockMs: number;
37
39
  }
40
+ export interface ProviderBudgetReservation {
41
+ maxTokens: number;
42
+ release(): void;
43
+ }
44
+ export interface SharedCapabilityBudget {
45
+ assertBudgetAvailable(subject: string): void;
46
+ recordAttemptUsage(usage: GatewayUsageSnapshot): void;
47
+ remainingTokens(): number | undefined;
48
+ reserveProviderBudget(requestedMaxTokens: number, subject: string, signal?: AbortSignal): Promise<ProviderBudgetReservation>;
49
+ }
38
50
  /** Persistable cumulative usage from a prior active segment; excludes restart downtime. */
39
51
  export type GatewayInitialUsage = AttemptUsageSnapshot;
40
52
  export declare class CapabilityGatewayDeniedError extends Error {
@@ -51,6 +63,7 @@ export declare class CapabilityGateway {
51
63
  private readonly cwd;
52
64
  private readonly now;
53
65
  private readonly onAudit?;
66
+ private readonly sharedBudget?;
54
67
  private readonly startedAt;
55
68
  private readonly initialWallClockMs;
56
69
  private toolCalls;
@@ -67,6 +80,9 @@ export declare class CapabilityGateway {
67
80
  recordUsage(delta: GatewayUsageDelta): void;
68
81
  /** Enforce resumed cumulative budgets before a provider request that has no tool-call boundary. */
69
82
  assertBudgetAvailable(subject?: string): void;
83
+ reserveProviderBudget(requestedMaxTokens: number, subject?: string, signal?: AbortSignal): Promise<ProviderBudgetReservation>;
84
+ remainingAttemptTokenBudget(): number | undefined;
85
+ remainingTokenBudget(): number | undefined;
70
86
  getUsage(): GatewayUsageSnapshot;
71
87
  private authorize;
72
88
  private enforceBudget;
@@ -1 +1 @@
1
- {"version":3,"file":"capability-gateway.d.ts","sourceRoot":"","sources":["../../../src/core/orchestration/capability-gateway.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,cAAc,EAAqB,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAEtH,MAAM,MAAM,mBAAmB,GAC5B,SAAS,GACT,eAAe,GACf,kBAAkB,GAClB,wBAAwB,GACxB,wBAAwB,GACxB,wBAAwB,GACxB,oBAAoB,GACpB,4BAA4B,GAC5B,wBAAwB,GACxB,uBAAuB,GACvB,6BAA6B,CAAC;AAEjC,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC;IAC1B,UAAU,EAAE,mBAAmB,CAAC;IAChC,EAAE,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,wBAAwB;IACxC,KAAK,EAAE,cAAc,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,qFAAqF;IACrF,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC/C;AAED,MAAM,WAAW,iBAAiB;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,2FAA2F;AAC3F,MAAM,MAAM,mBAAmB,GAAG,oBAAoB,CAAC;AAEvD,qBAAa,4BAA6B,SAAQ,KAAK;IACtD,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;IAEzC,YAAY,UAAU,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAI3D;CACD;AA4DD;;;;GAIG;AACH,qBAAa,iBAAiB;IAC7B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAuC;IAChE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAC5C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAS;IAExB,YAAY,OAAO,EAAE,wBAAwB,EAyB5C;IAEK,OAAO,CAAC,CAAC,EACd,QAAQ,EAAE,sBAAsB,EAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAC1B,OAAO,CAAC,CAAC,CAAC,CAGZ;IAED,8FAA8F;IAC9F,iBAAiB,CAAC,QAAQ,EAAE,sBAAsB,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAU3F;IAED,WAAW,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAwB1C;IAED,mGAAmG;IACnG,qBAAqB,CAAC,OAAO,SAAa,GAAG,IAAI,CAEhD;IAED,QAAQ,IAAI,oBAAoB,CAW/B;IAED,OAAO,CAAC,SAAS;IAqCjB,OAAO,CAAC,aAAa;IAgBrB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,IAAI;IAKZ,OAAO,CAAC,KAAK;CAUb"}
1
+ {"version":3,"file":"capability-gateway.d.ts","sourceRoot":"","sources":["../../../src/core/orchestration/capability-gateway.ts"],"names":[],"mappings":"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"}
@@ -79,6 +79,7 @@ export class CapabilityGateway {
79
79
  this.cwd = options.cwd;
80
80
  this.now = options.now ?? Date.now;
81
81
  this.onAudit = options.onAudit;
82
+ this.sharedBudget = options.sharedBudget;
82
83
  this.startedAt = this.currentTime();
83
84
  this.initialWallClockMs = initialUsage.activeWallClockMs;
84
85
  this.toolCalls = initialUsage.toolCalls;
@@ -88,6 +89,7 @@ export class CapabilityGateway {
88
89
  this.cacheWriteTokens = initialUsage.cacheWriteTokens;
89
90
  this.totalTokens = initialUsage.totalTokens;
90
91
  this.costUsd = initialUsage.costUsd;
92
+ this.sharedBudget?.recordAttemptUsage(this.getUsage());
91
93
  }
92
94
  async execute(manifest, toolName, params, invoke) {
93
95
  this.authorizeToolCall(manifest, toolName, params);
@@ -103,6 +105,7 @@ export class CapabilityGateway {
103
105
  throw new Error("CapabilityGateway: tool-call count would exceed safe cumulative usage bounds.");
104
106
  }
105
107
  this.toolCalls = toolCalls;
108
+ this.sharedBudget?.recordAttemptUsage(this.getUsage());
106
109
  this.audit(toolName, "allow", "allowed");
107
110
  }
108
111
  recordUsage(delta) {
@@ -127,10 +130,44 @@ export class CapabilityGateway {
127
130
  this.cacheWriteTokens = cacheWriteTokens;
128
131
  this.totalTokens = totalTokens;
129
132
  this.costUsd = costUsd;
133
+ this.sharedBudget?.recordAttemptUsage(this.getUsage());
130
134
  }
131
135
  /** Enforce resumed cumulative budgets before a provider request that has no tool-call boundary. */
132
136
  assertBudgetAvailable(subject = "provider") {
133
137
  this.enforceBudget(subject, this.wallClockMsAt(this.currentTime()));
138
+ this.sharedBudget?.assertBudgetAvailable(subject);
139
+ }
140
+ async reserveProviderBudget(requestedMaxTokens, subject = "provider", signal) {
141
+ if (!Number.isSafeInteger(requestedMaxTokens) || requestedMaxTokens <= 0) {
142
+ throw new Error("CapabilityGateway: provider token reservation must be a positive safe integer.");
143
+ }
144
+ this.assertBudgetAvailable(subject);
145
+ const localRemaining = this.remainingAttemptTokenBudget();
146
+ const maxTokens = Math.min(requestedMaxTokens, localRemaining ?? requestedMaxTokens);
147
+ if (maxTokens <= 0) {
148
+ this.deny(subject, "token_budget_exhausted", "Token budget exhausted.");
149
+ }
150
+ if (this.sharedBudget)
151
+ return this.sharedBudget.reserveProviderBudget(maxTokens, subject, signal);
152
+ if (signal?.aborted)
153
+ throw signal.reason;
154
+ return {
155
+ maxTokens,
156
+ release: () => undefined,
157
+ };
158
+ }
159
+ remainingAttemptTokenBudget() {
160
+ const maximum = this.grant.budget.maxTokens;
161
+ return maximum === undefined ? undefined : Math.max(0, maximum - this.totalTokens);
162
+ }
163
+ remainingTokenBudget() {
164
+ const localRemaining = this.remainingAttemptTokenBudget();
165
+ const sharedRemaining = this.sharedBudget?.remainingTokens();
166
+ if (localRemaining === undefined)
167
+ return sharedRemaining;
168
+ if (sharedRemaining === undefined)
169
+ return localRemaining;
170
+ return Math.min(localRemaining, sharedRemaining);
134
171
  }
135
172
  getUsage() {
136
173
  return {
@@ -158,6 +195,7 @@ export class CapabilityGateway {
158
195
  this.deny(toolName, "capability_not_granted", `Tool '${toolName}' requires an ungranted capability.`);
159
196
  }
160
197
  this.enforceBudget(toolName, wallClockMs);
198
+ this.sharedBudget?.assertBudgetAvailable(toolName);
161
199
  if (manifest.capabilities.some((capability) => PATH_CAPABILITIES.has(capability))) {
162
200
  const allowedPaths = manifest.capabilities.some((capability) => WRITE_CAPABILITIES.has(capability))
163
201
  ? this.grant.writePaths