open-multi-agent-kit 0.98.4 → 0.98.5

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 (252) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +3 -2
  3. package/dist/commands/run-command.d.ts +2 -1
  4. package/dist/commands/run-command.d.ts.map +1 -1
  5. package/dist/commands/run-command.js +9 -1
  6. package/dist/commands/run-command.js.map +1 -1
  7. package/dist/commands/verified-run-cli.d.ts +6 -0
  8. package/dist/commands/verified-run-cli.d.ts.map +1 -0
  9. package/dist/commands/verified-run-cli.js +190 -0
  10. package/dist/commands/verified-run-cli.js.map +1 -0
  11. package/dist/core/agent-session-services.d.ts +8 -1
  12. package/dist/core/agent-session-services.d.ts.map +1 -1
  13. package/dist/core/agent-session-services.js +41 -0
  14. package/dist/core/agent-session-services.js.map +1 -1
  15. package/dist/core/agent-session.d.ts +7 -8
  16. package/dist/core/agent-session.d.ts.map +1 -1
  17. package/dist/core/agent-session.js +61 -41
  18. package/dist/core/agent-session.js.map +1 -1
  19. package/dist/core/prompt-settlement.d.ts +4 -3
  20. package/dist/core/prompt-settlement.d.ts.map +1 -1
  21. package/dist/core/prompt-settlement.js.map +1 -1
  22. package/dist/core/run-budget-policy.d.ts +18 -0
  23. package/dist/core/run-budget-policy.d.ts.map +1 -0
  24. package/dist/core/run-budget-policy.js +52 -0
  25. package/dist/core/run-budget-policy.js.map +1 -0
  26. package/dist/core/run-budget.d.ts +33 -0
  27. package/dist/core/run-budget.d.ts.map +1 -0
  28. package/dist/core/run-budget.js +89 -0
  29. package/dist/core/run-budget.js.map +1 -0
  30. package/dist/core/run-execution-api.d.ts +15 -0
  31. package/dist/core/run-execution-api.d.ts.map +1 -0
  32. package/dist/core/run-execution-api.js +7 -0
  33. package/dist/core/run-execution-api.js.map +1 -0
  34. package/dist/core/run-journal.d.ts.map +1 -1
  35. package/dist/core/run-journal.js +30 -208
  36. package/dist/core/run-journal.js.map +1 -1
  37. package/dist/core/session-bash-service.d.ts +2 -2
  38. package/dist/core/session-bash-service.d.ts.map +1 -1
  39. package/dist/core/session-bash-service.js +21 -9
  40. package/dist/core/session-bash-service.js.map +1 -1
  41. package/dist/core/session-failure-cause.d.ts.map +1 -1
  42. package/dist/core/session-failure-cause.js +5 -0
  43. package/dist/core/session-failure-cause.js.map +1 -1
  44. package/dist/core/session-prompt-lifecycle.d.ts +25 -0
  45. package/dist/core/session-prompt-lifecycle.d.ts.map +1 -0
  46. package/dist/core/session-prompt-lifecycle.js +87 -0
  47. package/dist/core/session-prompt-lifecycle.js.map +1 -0
  48. package/dist/core/session-run-budget.d.ts +28 -0
  49. package/dist/core/session-run-budget.d.ts.map +1 -0
  50. package/dist/core/session-run-budget.js +127 -0
  51. package/dist/core/session-run-budget.js.map +1 -0
  52. package/dist/core/session-run-termination.d.ts.map +1 -1
  53. package/dist/core/session-run-termination.js +14 -3
  54. package/dist/core/session-run-termination.js.map +1 -1
  55. package/dist/core/session-termination-types.d.ts +97 -0
  56. package/dist/core/session-termination-types.d.ts.map +1 -0
  57. package/dist/core/session-termination-types.js +26 -0
  58. package/dist/core/session-termination-types.js.map +1 -0
  59. package/dist/core/session-termination.d.ts +3 -97
  60. package/dist/core/session-termination.d.ts.map +1 -1
  61. package/dist/core/session-termination.js +24 -28
  62. package/dist/core/session-termination.js.map +1 -1
  63. package/dist/core/slash-commands.d.ts.map +1 -1
  64. package/dist/core/slash-commands.js +1 -0
  65. package/dist/core/slash-commands.js.map +1 -1
  66. package/dist/core/subagent-lane-launcher.d.ts +3 -2
  67. package/dist/core/subagent-lane-launcher.d.ts.map +1 -1
  68. package/dist/core/subagent-lane-launcher.js +24 -13
  69. package/dist/core/subagent-lane-launcher.js.map +1 -1
  70. package/dist/core/verified-run/broker.d.ts +26 -0
  71. package/dist/core/verified-run/broker.d.ts.map +1 -0
  72. package/dist/core/verified-run/broker.js +210 -0
  73. package/dist/core/verified-run/broker.js.map +1 -0
  74. package/dist/core/verified-run/candidate.d.ts +24 -0
  75. package/dist/core/verified-run/candidate.d.ts.map +1 -0
  76. package/dist/core/verified-run/candidate.js +167 -0
  77. package/dist/core/verified-run/candidate.js.map +1 -0
  78. package/dist/core/verified-run/check-receipt.d.ts +18 -0
  79. package/dist/core/verified-run/check-receipt.d.ts.map +1 -0
  80. package/dist/core/verified-run/check-receipt.js +92 -0
  81. package/dist/core/verified-run/check-receipt.js.map +1 -0
  82. package/dist/core/verified-run/coordinator.d.ts +39 -0
  83. package/dist/core/verified-run/coordinator.d.ts.map +1 -0
  84. package/dist/core/verified-run/coordinator.js +190 -0
  85. package/dist/core/verified-run/coordinator.js.map +1 -0
  86. package/dist/core/verified-run/dag-candidates.d.ts +8 -0
  87. package/dist/core/verified-run/dag-candidates.d.ts.map +1 -0
  88. package/dist/core/verified-run/dag-candidates.js +65 -0
  89. package/dist/core/verified-run/dag-candidates.js.map +1 -0
  90. package/dist/core/verified-run/dag-phase.d.ts +7 -0
  91. package/dist/core/verified-run/dag-phase.d.ts.map +1 -0
  92. package/dist/core/verified-run/dag-phase.js +92 -0
  93. package/dist/core/verified-run/dag-phase.js.map +1 -0
  94. package/dist/core/verified-run/dag-projection.d.ts +7 -0
  95. package/dist/core/verified-run/dag-projection.d.ts.map +1 -0
  96. package/dist/core/verified-run/dag-projection.js +90 -0
  97. package/dist/core/verified-run/dag-projection.js.map +1 -0
  98. package/dist/core/verified-run/dag-recovery.d.ts +13 -0
  99. package/dist/core/verified-run/dag-recovery.d.ts.map +1 -0
  100. package/dist/core/verified-run/dag-recovery.js +98 -0
  101. package/dist/core/verified-run/dag-recovery.js.map +1 -0
  102. package/dist/core/verified-run/dag-retry-projection.d.ts +9 -0
  103. package/dist/core/verified-run/dag-retry-projection.d.ts.map +1 -0
  104. package/dist/core/verified-run/dag-retry-projection.js +43 -0
  105. package/dist/core/verified-run/dag-retry-projection.js.map +1 -0
  106. package/dist/core/verified-run/dag-types.d.ts +47 -0
  107. package/dist/core/verified-run/dag-types.d.ts.map +1 -0
  108. package/dist/core/verified-run/dag-types.js +2 -0
  109. package/dist/core/verified-run/dag-types.js.map +1 -0
  110. package/dist/core/verified-run/event-parser.d.ts +3 -0
  111. package/dist/core/verified-run/event-parser.d.ts.map +1 -0
  112. package/dist/core/verified-run/event-parser.js +153 -0
  113. package/dist/core/verified-run/event-parser.js.map +1 -0
  114. package/dist/core/verified-run/events.d.ts +4 -0
  115. package/dist/core/verified-run/events.d.ts.map +1 -0
  116. package/dist/core/verified-run/events.js +3 -0
  117. package/dist/core/verified-run/events.js.map +1 -0
  118. package/dist/core/verified-run/evidence-binding.d.ts +18 -0
  119. package/dist/core/verified-run/evidence-binding.d.ts.map +1 -0
  120. package/dist/core/verified-run/evidence-binding.js +81 -0
  121. package/dist/core/verified-run/evidence-binding.js.map +1 -0
  122. package/dist/core/verified-run/evidence.d.ts +27 -0
  123. package/dist/core/verified-run/evidence.d.ts.map +1 -0
  124. package/dist/core/verified-run/evidence.js +100 -0
  125. package/dist/core/verified-run/evidence.js.map +1 -0
  126. package/dist/core/verified-run/journal.d.ts +32 -0
  127. package/dist/core/verified-run/journal.d.ts.map +1 -0
  128. package/dist/core/verified-run/journal.js +103 -0
  129. package/dist/core/verified-run/journal.js.map +1 -0
  130. package/dist/core/verified-run/namespace-identity.d.ts +11 -0
  131. package/dist/core/verified-run/namespace-identity.d.ts.map +1 -0
  132. package/dist/core/verified-run/namespace-identity.js +77 -0
  133. package/dist/core/verified-run/namespace-identity.js.map +1 -0
  134. package/dist/core/verified-run/owned-execution.d.ts +21 -0
  135. package/dist/core/verified-run/owned-execution.d.ts.map +1 -0
  136. package/dist/core/verified-run/owned-execution.js +43 -0
  137. package/dist/core/verified-run/owned-execution.js.map +1 -0
  138. package/dist/core/verified-run/phase-context.d.ts +9 -0
  139. package/dist/core/verified-run/phase-context.d.ts.map +1 -0
  140. package/dist/core/verified-run/phase-context.js +2 -0
  141. package/dist/core/verified-run/phase-context.js.map +1 -0
  142. package/dist/core/verified-run/process-gate.d.ts +5 -0
  143. package/dist/core/verified-run/process-gate.d.ts.map +1 -0
  144. package/dist/core/verified-run/process-gate.js +31 -0
  145. package/dist/core/verified-run/process-gate.js.map +1 -0
  146. package/dist/core/verified-run/projection.d.ts +4 -0
  147. package/dist/core/verified-run/projection.d.ts.map +1 -0
  148. package/dist/core/verified-run/projection.js +219 -0
  149. package/dist/core/verified-run/projection.js.map +1 -0
  150. package/dist/core/verified-run/recovery-clock.d.ts +19 -0
  151. package/dist/core/verified-run/recovery-clock.d.ts.map +1 -0
  152. package/dist/core/verified-run/recovery-clock.js +69 -0
  153. package/dist/core/verified-run/recovery-clock.js.map +1 -0
  154. package/dist/core/verified-run/recovery-command.d.ts +11 -0
  155. package/dist/core/verified-run/recovery-command.d.ts.map +1 -0
  156. package/dist/core/verified-run/recovery-command.js +73 -0
  157. package/dist/core/verified-run/recovery-command.js.map +1 -0
  158. package/dist/core/verified-run/recovery-projection.d.ts +12 -0
  159. package/dist/core/verified-run/recovery-projection.d.ts.map +1 -0
  160. package/dist/core/verified-run/recovery-projection.js +88 -0
  161. package/dist/core/verified-run/recovery-projection.js.map +1 -0
  162. package/dist/core/verified-run/recovery.d.ts +12 -0
  163. package/dist/core/verified-run/recovery.d.ts.map +1 -0
  164. package/dist/core/verified-run/recovery.js +115 -0
  165. package/dist/core/verified-run/recovery.js.map +1 -0
  166. package/dist/core/verified-run/run-types.d.ts +103 -0
  167. package/dist/core/verified-run/run-types.d.ts.map +1 -0
  168. package/dist/core/verified-run/run-types.js +2 -0
  169. package/dist/core/verified-run/run-types.js.map +1 -0
  170. package/dist/core/verified-run/scripted-writer.d.ts +15 -0
  171. package/dist/core/verified-run/scripted-writer.d.ts.map +1 -0
  172. package/dist/core/verified-run/scripted-writer.js +94 -0
  173. package/dist/core/verified-run/scripted-writer.js.map +1 -0
  174. package/dist/core/verified-run/session-port.d.ts +27 -0
  175. package/dist/core/verified-run/session-port.d.ts.map +1 -0
  176. package/dist/core/verified-run/session-port.js +2 -0
  177. package/dist/core/verified-run/session-port.js.map +1 -0
  178. package/dist/core/verified-run/storage.d.ts +15 -0
  179. package/dist/core/verified-run/storage.d.ts.map +1 -0
  180. package/dist/core/verified-run/storage.js +96 -0
  181. package/dist/core/verified-run/storage.js.map +1 -0
  182. package/dist/core/verified-run/verification-phase.d.ts +5 -0
  183. package/dist/core/verified-run/verification-phase.d.ts.map +1 -0
  184. package/dist/core/verified-run/verification-phase.js +56 -0
  185. package/dist/core/verified-run/verification-phase.js.map +1 -0
  186. package/dist/core/verified-run/work-recovery.d.ts +8 -0
  187. package/dist/core/verified-run/work-recovery.d.ts.map +1 -0
  188. package/dist/core/verified-run/work-recovery.js +44 -0
  189. package/dist/core/verified-run/work-recovery.js.map +1 -0
  190. package/dist/core/verified-run/writer-completion.d.ts +4 -0
  191. package/dist/core/verified-run/writer-completion.d.ts.map +1 -0
  192. package/dist/core/verified-run/writer-completion.js +27 -0
  193. package/dist/core/verified-run/writer-completion.js.map +1 -0
  194. package/dist/core/verified-run/writer-phase.d.ts +8 -0
  195. package/dist/core/verified-run/writer-phase.d.ts.map +1 -0
  196. package/dist/core/verified-run/writer-phase.js +76 -0
  197. package/dist/core/verified-run/writer-phase.js.map +1 -0
  198. package/dist/core/verified-run/writer-projection.d.ts +11 -0
  199. package/dist/core/verified-run/writer-projection.d.ts.map +1 -0
  200. package/dist/core/verified-run/writer-projection.js +70 -0
  201. package/dist/core/verified-run/writer-projection.js.map +1 -0
  202. package/dist/core/verified-run/writer-recovery.d.ts +16 -0
  203. package/dist/core/verified-run/writer-recovery.d.ts.map +1 -0
  204. package/dist/core/verified-run/writer-recovery.js +107 -0
  205. package/dist/core/verified-run/writer-recovery.js.map +1 -0
  206. package/dist/core/workload-permit-pool.d.ts +1 -3
  207. package/dist/core/workload-permit-pool.d.ts.map +1 -1
  208. package/dist/core/workload-permit-pool.js +11 -11
  209. package/dist/core/workload-permit-pool.js.map +1 -1
  210. package/dist/index.d.ts +3 -2
  211. package/dist/index.d.ts.map +1 -1
  212. package/dist/index.js +2 -2
  213. package/dist/index.js.map +1 -1
  214. package/dist/main.d.ts.map +1 -1
  215. package/dist/main.js +2 -8
  216. package/dist/main.js.map +1 -1
  217. package/dist/modes/interactive/components/session-failure.d.ts +13 -0
  218. package/dist/modes/interactive/components/session-failure.d.ts.map +1 -0
  219. package/dist/modes/interactive/components/session-failure.js +81 -0
  220. package/dist/modes/interactive/components/session-failure.js.map +1 -0
  221. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  222. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  223. package/dist/modes/interactive/interactive-mode.js +45 -31
  224. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  225. package/dist/modes/interactive/tui-diagnostics.d.ts +36 -0
  226. package/dist/modes/interactive/tui-diagnostics.d.ts.map +1 -0
  227. package/dist/modes/interactive/tui-diagnostics.js +105 -0
  228. package/dist/modes/interactive/tui-diagnostics.js.map +1 -0
  229. package/dist/modes/interactive/tui-runtime-info.d.ts +20 -0
  230. package/dist/modes/interactive/tui-runtime-info.d.ts.map +1 -0
  231. package/dist/modes/interactive/tui-runtime-info.js +76 -0
  232. package/dist/modes/interactive/tui-runtime-info.js.map +1 -0
  233. package/docs/development.md +10 -0
  234. package/docs/keybindings.md +1 -1
  235. package/docs/release-audit-0.98.5.md +84 -0
  236. package/docs/run-protocol.md +33 -1
  237. package/docs/runtime-algorithms.md +26 -0
  238. package/docs/sdk.md +193 -0
  239. package/docs/usage.md +54 -0
  240. package/docs/verified-run-testing.md +417 -0
  241. package/docs/verified-run.md +388 -0
  242. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  243. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  244. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  245. package/examples/extensions/gondolin/package-lock.json +2 -2
  246. package/examples/extensions/gondolin/package.json +1 -1
  247. package/examples/extensions/sandbox/package-lock.json +2 -2
  248. package/examples/extensions/sandbox/package.json +1 -1
  249. package/examples/extensions/with-deps/package-lock.json +2 -2
  250. package/examples/extensions/with-deps/package.json +1 -1
  251. package/npm-shrinkwrap.json +18 -18
  252. package/package.json +6 -6
@@ -9,9 +9,10 @@ import type { SessionTerminationKind } from "./session-termination.ts";
9
9
  * M4 completion sound, notifications) must treat it as a UX signal, never a
10
10
  * correctness signal (§3 non-goals).
11
11
  *
12
- * The reducer is a pure function over immutable state (§16.5). Shard and child
13
- * counters are reserved in the contract, but no production signal call sites
14
- * wire them yet; any future live M5/M6 path must add those calls before use.
12
+ * This counter reducer remains a compatibility projection, not execution
13
+ * ownership authority. AgentSession uses SessionPromptLifecycle to retain actual
14
+ * tool-promise identities and seal the root producer before projecting an event.
15
+ * Detached children and shards still require an explicit ownership/join adapter.
15
16
  */
16
17
  export type PromptSettlementOutcome = "completed" | "failed" | "aborted";
17
18
  /** §16.2 prompt run identity. */
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-settlement.d.ts","sourceRoot":"","sources":["../../src/core/prompt-settlement.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SessionTerminationKind } from \"./session-termination.ts\";\n\n/**\n * Prompt settlement coordinator (OMK v0.97.x roadmap §16, M4/PR6).\n *\n * `agent_end` is NOT final (§16.1): provider retries, compaction retries,\n * durable-goal continuations, steering/follow-up queues, shards, and child\n * subagents may still run. `prompt_settled` fires only when the reducer's\n * §16.4 conditions all hold, exactly once per promptRunId. Consumers (the\n * M4 completion sound, notifications) must treat it as a UX signal, never a\n * correctness signal (§3 non-goals).\n *\n * The reducer is a pure function over immutable state (§16.5). Shard and child\n * counters are reserved in the contract, but no production signal call sites\n * wire them yet; any future live M5/M6 path must add those calls before use.\n */\n\nexport type PromptSettlementOutcome = \"completed\" | \"failed\" | \"aborted\";\n\n/** §16.2 prompt run identity. */\nexport interface PromptRunRef {\n\treadonly promptRunId: string;\n\treadonly sessionId: string;\n\treadonly startedAt: string;\n\treadonly lineageId?: string;\n}\n\n/** §16.3 settlement contract. */\nexport interface PromptSettledEvent {\n\treadonly type: \"prompt_settled\";\n\treadonly promptRunId: string;\n\treadonly outcome: PromptSettlementOutcome;\n\treadonly durationMs: number;\n\treadonly terminationKind?: string;\n}\n\n/** §16.5 coordinator state. */\nexport interface PromptSettlementState {\n\treadonly promptRunId: string;\n\treadonly startedAtEpochMs: number;\n\treadonly activeProviderAttempts: number;\n\treadonly activeTools: number;\n\treadonly activeShards: number;\n\treadonly activeChildren: number;\n\treadonly queuedContinuations: number;\n\treadonly terminal?: {\n\t\treadonly outcome: PromptSettlementOutcome;\n\t\treadonly terminationKind?: string;\n\t};\n\treadonly emitted: boolean;\n}\n\nexport type PromptSettlementSignal =\n\t| { readonly kind: \"provider_attempt\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"tool\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"shard\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"child\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"continuation\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"terminal\"; readonly outcome: PromptSettlementOutcome; readonly terminationKind?: string }\n\t| { readonly kind: \"emitted\" };\n\n/** Map the final typed termination onto the prompt UX outcome. */\nexport function resolvePromptSettlementOutcome(\n\tfallback: PromptSettlementOutcome,\n\tterminationKind: SessionTerminationKind | undefined,\n): PromptSettlementOutcome {\n\tif (terminationKind === \"user_abort\" || terminationKind === \"provider_abort\") return \"aborted\";\n\tif (fallback !== \"completed\") return fallback;\n\tif (terminationKind === undefined || terminationKind === \"completed\") return \"completed\";\n\treturn \"failed\";\n}\n\nexport function createPromptSettlementState(promptRunId: string, startedAtEpochMs: number): PromptSettlementState {\n\treturn {\n\t\tpromptRunId,\n\t\tstartedAtEpochMs,\n\t\tactiveProviderAttempts: 0,\n\t\tactiveTools: 0,\n\t\tactiveShards: 0,\n\t\tactiveChildren: 0,\n\t\tqueuedContinuations: 0,\n\t\temitted: false,\n\t};\n}\n\n/** Pure reducer (§16.5). Counters clamp at zero; terminal and emitted are latching. */\nexport function reducePromptSettlement(\n\tstate: PromptSettlementState,\n\tsignal: PromptSettlementSignal,\n): PromptSettlementState {\n\tswitch (signal.kind) {\n\t\tcase \"provider_attempt\":\n\t\t\treturn { ...state, activeProviderAttempts: clampCount(state.activeProviderAttempts + signal.delta) };\n\t\tcase \"tool\":\n\t\t\treturn { ...state, activeTools: clampCount(state.activeTools + signal.delta) };\n\t\tcase \"shard\":\n\t\t\treturn { ...state, activeShards: clampCount(state.activeShards + signal.delta) };\n\t\tcase \"child\":\n\t\t\treturn { ...state, activeChildren: clampCount(state.activeChildren + signal.delta) };\n\t\tcase \"continuation\":\n\t\t\treturn { ...state, queuedContinuations: clampCount(state.queuedContinuations + signal.delta) };\n\t\tcase \"terminal\":\n\t\t\t// First terminal outcome wins; later reclassification never flips it (§15.3).\n\t\t\tif (state.terminal !== undefined) {\n\t\t\t\treturn state;\n\t\t\t}\n\t\t\treturn { ...state, terminal: { outcome: signal.outcome, terminationKind: signal.terminationKind } };\n\t\tcase \"emitted\":\n\t\t\treturn { ...state, emitted: true };\n\t\tdefault: {\n\t\t\tconst exhaustive: never = signal;\n\t\t\treturn exhaustive;\n\t\t}\n\t}\n}\n\n/** §16.4: every condition must hold before `prompt_settled` may emit. */\nexport function shouldEmitPromptSettled(state: PromptSettlementState): boolean {\n\treturn (\n\t\tstate.terminal !== undefined &&\n\t\t!state.emitted &&\n\t\tstate.activeProviderAttempts === 0 &&\n\t\tstate.activeTools === 0 &&\n\t\tstate.activeShards === 0 &&\n\t\tstate.activeChildren === 0 &&\n\t\tstate.queuedContinuations === 0\n\t);\n}\n\n/**\n * Build the event when (and only when) §16.4 holds, marking the state\n * emitted so the same sequence can never yield a second event.\n */\nexport function settlePromptIfReady(\n\tstate: PromptSettlementState,\n\tnowEpochMs: number,\n): { readonly state: PromptSettlementState; readonly event: PromptSettledEvent | null } {\n\tif (!shouldEmitPromptSettled(state) || state.terminal === undefined) {\n\t\treturn { state, event: null };\n\t}\n\tconst event: PromptSettledEvent = {\n\t\ttype: \"prompt_settled\",\n\t\tpromptRunId: state.promptRunId,\n\t\toutcome: state.terminal.outcome,\n\t\tdurationMs: Math.max(0, nowEpochMs - state.startedAtEpochMs),\n\t\t...(state.terminal.terminationKind !== undefined ? { terminationKind: state.terminal.terminationKind } : {}),\n\t};\n\treturn { state: reducePromptSettlement(state, { kind: \"emitted\" }), event };\n}\n\nfunction clampCount(value: number): number {\n\treturn Math.max(0, value);\n}\n"]}
1
+ {"version":3,"file":"prompt-settlement.d.ts","sourceRoot":"","sources":["../../src/core/prompt-settlement.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEvE;;;;;;;;;;;;;;GAcG;AAEH,MAAM,MAAM,uBAAuB,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEzE,kCAAiC;AACjC,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,kCAAiC;AACjC,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,uBAAuB,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,gCAA+B;AAC/B,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE;QACnB,QAAQ,CAAC,OAAO,EAAE,uBAAuB,CAAC;QAC1C,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;KAClC,CAAC;IACF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,MAAM,sBAAsB,GAC/B;IAAE,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;CAAE,GAC7D;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;CAAE,GACjD;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;CAAE,GAClD;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;CAAE,GAClD;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;CAAE,GACzD;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,uBAAuB,CAAC;IAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3G;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAEhC,kEAAkE;AAClE,wBAAgB,8BAA8B,CAC7C,QAAQ,EAAE,uBAAuB,EACjC,eAAe,EAAE,sBAAsB,GAAG,SAAS,GACjD,uBAAuB,CAKzB;AAED,wBAAgB,2BAA2B,CAAC,WAAW,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,qBAAqB,CAWhH;AAED,wFAAuF;AACvF,wBAAgB,sBAAsB,CACrC,KAAK,EAAE,qBAAqB,EAC5B,MAAM,EAAE,sBAAsB,GAC5B,qBAAqB,CAyBvB;AAED,0EAAyE;AACzE,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAU7E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAClC,KAAK,EAAE,qBAAqB,EAC5B,UAAU,EAAE,MAAM,GAChB;IAAE,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAAA;CAAE,CAYtF","sourcesContent":["import type { SessionTerminationKind } from \"./session-termination.ts\";\n\n/**\n * Prompt settlement coordinator (OMK v0.97.x roadmap §16, M4/PR6).\n *\n * `agent_end` is NOT final (§16.1): provider retries, compaction retries,\n * durable-goal continuations, steering/follow-up queues, shards, and child\n * subagents may still run. `prompt_settled` fires only when the reducer's\n * §16.4 conditions all hold, exactly once per promptRunId. Consumers (the\n * M4 completion sound, notifications) must treat it as a UX signal, never a\n * correctness signal (§3 non-goals).\n *\n * This counter reducer remains a compatibility projection, not execution\n * ownership authority. AgentSession uses SessionPromptLifecycle to retain actual\n * tool-promise identities and seal the root producer before projecting an event.\n * Detached children and shards still require an explicit ownership/join adapter.\n */\n\nexport type PromptSettlementOutcome = \"completed\" | \"failed\" | \"aborted\";\n\n/** §16.2 prompt run identity. */\nexport interface PromptRunRef {\n\treadonly promptRunId: string;\n\treadonly sessionId: string;\n\treadonly startedAt: string;\n\treadonly lineageId?: string;\n}\n\n/** §16.3 settlement contract. */\nexport interface PromptSettledEvent {\n\treadonly type: \"prompt_settled\";\n\treadonly promptRunId: string;\n\treadonly outcome: PromptSettlementOutcome;\n\treadonly durationMs: number;\n\treadonly terminationKind?: string;\n}\n\n/** §16.5 coordinator state. */\nexport interface PromptSettlementState {\n\treadonly promptRunId: string;\n\treadonly startedAtEpochMs: number;\n\treadonly activeProviderAttempts: number;\n\treadonly activeTools: number;\n\treadonly activeShards: number;\n\treadonly activeChildren: number;\n\treadonly queuedContinuations: number;\n\treadonly terminal?: {\n\t\treadonly outcome: PromptSettlementOutcome;\n\t\treadonly terminationKind?: string;\n\t};\n\treadonly emitted: boolean;\n}\n\nexport type PromptSettlementSignal =\n\t| { readonly kind: \"provider_attempt\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"tool\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"shard\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"child\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"continuation\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"terminal\"; readonly outcome: PromptSettlementOutcome; readonly terminationKind?: string }\n\t| { readonly kind: \"emitted\" };\n\n/** Map the final typed termination onto the prompt UX outcome. */\nexport function resolvePromptSettlementOutcome(\n\tfallback: PromptSettlementOutcome,\n\tterminationKind: SessionTerminationKind | undefined,\n): PromptSettlementOutcome {\n\tif (terminationKind === \"user_abort\" || terminationKind === \"provider_abort\") return \"aborted\";\n\tif (fallback !== \"completed\") return fallback;\n\tif (terminationKind === undefined || terminationKind === \"completed\") return \"completed\";\n\treturn \"failed\";\n}\n\nexport function createPromptSettlementState(promptRunId: string, startedAtEpochMs: number): PromptSettlementState {\n\treturn {\n\t\tpromptRunId,\n\t\tstartedAtEpochMs,\n\t\tactiveProviderAttempts: 0,\n\t\tactiveTools: 0,\n\t\tactiveShards: 0,\n\t\tactiveChildren: 0,\n\t\tqueuedContinuations: 0,\n\t\temitted: false,\n\t};\n}\n\n/** Pure reducer (§16.5). Counters clamp at zero; terminal and emitted are latching. */\nexport function reducePromptSettlement(\n\tstate: PromptSettlementState,\n\tsignal: PromptSettlementSignal,\n): PromptSettlementState {\n\tswitch (signal.kind) {\n\t\tcase \"provider_attempt\":\n\t\t\treturn { ...state, activeProviderAttempts: clampCount(state.activeProviderAttempts + signal.delta) };\n\t\tcase \"tool\":\n\t\t\treturn { ...state, activeTools: clampCount(state.activeTools + signal.delta) };\n\t\tcase \"shard\":\n\t\t\treturn { ...state, activeShards: clampCount(state.activeShards + signal.delta) };\n\t\tcase \"child\":\n\t\t\treturn { ...state, activeChildren: clampCount(state.activeChildren + signal.delta) };\n\t\tcase \"continuation\":\n\t\t\treturn { ...state, queuedContinuations: clampCount(state.queuedContinuations + signal.delta) };\n\t\tcase \"terminal\":\n\t\t\t// First terminal outcome wins; later reclassification never flips it (§15.3).\n\t\t\tif (state.terminal !== undefined) {\n\t\t\t\treturn state;\n\t\t\t}\n\t\t\treturn { ...state, terminal: { outcome: signal.outcome, terminationKind: signal.terminationKind } };\n\t\tcase \"emitted\":\n\t\t\treturn { ...state, emitted: true };\n\t\tdefault: {\n\t\t\tconst exhaustive: never = signal;\n\t\t\treturn exhaustive;\n\t\t}\n\t}\n}\n\n/** §16.4: every condition must hold before `prompt_settled` may emit. */\nexport function shouldEmitPromptSettled(state: PromptSettlementState): boolean {\n\treturn (\n\t\tstate.terminal !== undefined &&\n\t\t!state.emitted &&\n\t\tstate.activeProviderAttempts === 0 &&\n\t\tstate.activeTools === 0 &&\n\t\tstate.activeShards === 0 &&\n\t\tstate.activeChildren === 0 &&\n\t\tstate.queuedContinuations === 0\n\t);\n}\n\n/**\n * Build the event when (and only when) §16.4 holds, marking the state\n * emitted so the same sequence can never yield a second event.\n */\nexport function settlePromptIfReady(\n\tstate: PromptSettlementState,\n\tnowEpochMs: number,\n): { readonly state: PromptSettlementState; readonly event: PromptSettledEvent | null } {\n\tif (!shouldEmitPromptSettled(state) || state.terminal === undefined) {\n\t\treturn { state, event: null };\n\t}\n\tconst event: PromptSettledEvent = {\n\t\ttype: \"prompt_settled\",\n\t\tpromptRunId: state.promptRunId,\n\t\toutcome: state.terminal.outcome,\n\t\tdurationMs: Math.max(0, nowEpochMs - state.startedAtEpochMs),\n\t\t...(state.terminal.terminationKind !== undefined ? { terminationKind: state.terminal.terminationKind } : {}),\n\t};\n\treturn { state: reducePromptSettlement(state, { kind: \"emitted\" }), event };\n}\n\nfunction clampCount(value: number): number {\n\treturn Math.max(0, value);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-settlement.js","sourceRoot":"","sources":["../../src/core/prompt-settlement.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SessionTerminationKind } from \"./session-termination.ts\";\n\n/**\n * Prompt settlement coordinator (OMK v0.97.x roadmap §16, M4/PR6).\n *\n * `agent_end` is NOT final (§16.1): provider retries, compaction retries,\n * durable-goal continuations, steering/follow-up queues, shards, and child\n * subagents may still run. `prompt_settled` fires only when the reducer's\n * §16.4 conditions all hold, exactly once per promptRunId. Consumers (the\n * M4 completion sound, notifications) must treat it as a UX signal, never a\n * correctness signal (§3 non-goals).\n *\n * The reducer is a pure function over immutable state (§16.5). Shard and child\n * counters are reserved in the contract, but no production signal call sites\n * wire them yet; any future live M5/M6 path must add those calls before use.\n */\n\nexport type PromptSettlementOutcome = \"completed\" | \"failed\" | \"aborted\";\n\n/** §16.2 prompt run identity. */\nexport interface PromptRunRef {\n\treadonly promptRunId: string;\n\treadonly sessionId: string;\n\treadonly startedAt: string;\n\treadonly lineageId?: string;\n}\n\n/** §16.3 settlement contract. */\nexport interface PromptSettledEvent {\n\treadonly type: \"prompt_settled\";\n\treadonly promptRunId: string;\n\treadonly outcome: PromptSettlementOutcome;\n\treadonly durationMs: number;\n\treadonly terminationKind?: string;\n}\n\n/** §16.5 coordinator state. */\nexport interface PromptSettlementState {\n\treadonly promptRunId: string;\n\treadonly startedAtEpochMs: number;\n\treadonly activeProviderAttempts: number;\n\treadonly activeTools: number;\n\treadonly activeShards: number;\n\treadonly activeChildren: number;\n\treadonly queuedContinuations: number;\n\treadonly terminal?: {\n\t\treadonly outcome: PromptSettlementOutcome;\n\t\treadonly terminationKind?: string;\n\t};\n\treadonly emitted: boolean;\n}\n\nexport type PromptSettlementSignal =\n\t| { readonly kind: \"provider_attempt\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"tool\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"shard\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"child\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"continuation\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"terminal\"; readonly outcome: PromptSettlementOutcome; readonly terminationKind?: string }\n\t| { readonly kind: \"emitted\" };\n\n/** Map the final typed termination onto the prompt UX outcome. */\nexport function resolvePromptSettlementOutcome(\n\tfallback: PromptSettlementOutcome,\n\tterminationKind: SessionTerminationKind | undefined,\n): PromptSettlementOutcome {\n\tif (terminationKind === \"user_abort\" || terminationKind === \"provider_abort\") return \"aborted\";\n\tif (fallback !== \"completed\") return fallback;\n\tif (terminationKind === undefined || terminationKind === \"completed\") return \"completed\";\n\treturn \"failed\";\n}\n\nexport function createPromptSettlementState(promptRunId: string, startedAtEpochMs: number): PromptSettlementState {\n\treturn {\n\t\tpromptRunId,\n\t\tstartedAtEpochMs,\n\t\tactiveProviderAttempts: 0,\n\t\tactiveTools: 0,\n\t\tactiveShards: 0,\n\t\tactiveChildren: 0,\n\t\tqueuedContinuations: 0,\n\t\temitted: false,\n\t};\n}\n\n/** Pure reducer (§16.5). Counters clamp at zero; terminal and emitted are latching. */\nexport function reducePromptSettlement(\n\tstate: PromptSettlementState,\n\tsignal: PromptSettlementSignal,\n): PromptSettlementState {\n\tswitch (signal.kind) {\n\t\tcase \"provider_attempt\":\n\t\t\treturn { ...state, activeProviderAttempts: clampCount(state.activeProviderAttempts + signal.delta) };\n\t\tcase \"tool\":\n\t\t\treturn { ...state, activeTools: clampCount(state.activeTools + signal.delta) };\n\t\tcase \"shard\":\n\t\t\treturn { ...state, activeShards: clampCount(state.activeShards + signal.delta) };\n\t\tcase \"child\":\n\t\t\treturn { ...state, activeChildren: clampCount(state.activeChildren + signal.delta) };\n\t\tcase \"continuation\":\n\t\t\treturn { ...state, queuedContinuations: clampCount(state.queuedContinuations + signal.delta) };\n\t\tcase \"terminal\":\n\t\t\t// First terminal outcome wins; later reclassification never flips it (§15.3).\n\t\t\tif (state.terminal !== undefined) {\n\t\t\t\treturn state;\n\t\t\t}\n\t\t\treturn { ...state, terminal: { outcome: signal.outcome, terminationKind: signal.terminationKind } };\n\t\tcase \"emitted\":\n\t\t\treturn { ...state, emitted: true };\n\t\tdefault: {\n\t\t\tconst exhaustive: never = signal;\n\t\t\treturn exhaustive;\n\t\t}\n\t}\n}\n\n/** §16.4: every condition must hold before `prompt_settled` may emit. */\nexport function shouldEmitPromptSettled(state: PromptSettlementState): boolean {\n\treturn (\n\t\tstate.terminal !== undefined &&\n\t\t!state.emitted &&\n\t\tstate.activeProviderAttempts === 0 &&\n\t\tstate.activeTools === 0 &&\n\t\tstate.activeShards === 0 &&\n\t\tstate.activeChildren === 0 &&\n\t\tstate.queuedContinuations === 0\n\t);\n}\n\n/**\n * Build the event when (and only when) §16.4 holds, marking the state\n * emitted so the same sequence can never yield a second event.\n */\nexport function settlePromptIfReady(\n\tstate: PromptSettlementState,\n\tnowEpochMs: number,\n): { readonly state: PromptSettlementState; readonly event: PromptSettledEvent | null } {\n\tif (!shouldEmitPromptSettled(state) || state.terminal === undefined) {\n\t\treturn { state, event: null };\n\t}\n\tconst event: PromptSettledEvent = {\n\t\ttype: \"prompt_settled\",\n\t\tpromptRunId: state.promptRunId,\n\t\toutcome: state.terminal.outcome,\n\t\tdurationMs: Math.max(0, nowEpochMs - state.startedAtEpochMs),\n\t\t...(state.terminal.terminationKind !== undefined ? { terminationKind: state.terminal.terminationKind } : {}),\n\t};\n\treturn { state: reducePromptSettlement(state, { kind: \"emitted\" }), event };\n}\n\nfunction clampCount(value: number): number {\n\treturn Math.max(0, value);\n}\n"]}
1
+ {"version":3,"file":"prompt-settlement.js","sourceRoot":"","sources":["../../src/core/prompt-settlement.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SessionTerminationKind } from \"./session-termination.ts\";\n\n/**\n * Prompt settlement coordinator (OMK v0.97.x roadmap §16, M4/PR6).\n *\n * `agent_end` is NOT final (§16.1): provider retries, compaction retries,\n * durable-goal continuations, steering/follow-up queues, shards, and child\n * subagents may still run. `prompt_settled` fires only when the reducer's\n * §16.4 conditions all hold, exactly once per promptRunId. Consumers (the\n * M4 completion sound, notifications) must treat it as a UX signal, never a\n * correctness signal (§3 non-goals).\n *\n * This counter reducer remains a compatibility projection, not execution\n * ownership authority. AgentSession uses SessionPromptLifecycle to retain actual\n * tool-promise identities and seal the root producer before projecting an event.\n * Detached children and shards still require an explicit ownership/join adapter.\n */\n\nexport type PromptSettlementOutcome = \"completed\" | \"failed\" | \"aborted\";\n\n/** §16.2 prompt run identity. */\nexport interface PromptRunRef {\n\treadonly promptRunId: string;\n\treadonly sessionId: string;\n\treadonly startedAt: string;\n\treadonly lineageId?: string;\n}\n\n/** §16.3 settlement contract. */\nexport interface PromptSettledEvent {\n\treadonly type: \"prompt_settled\";\n\treadonly promptRunId: string;\n\treadonly outcome: PromptSettlementOutcome;\n\treadonly durationMs: number;\n\treadonly terminationKind?: string;\n}\n\n/** §16.5 coordinator state. */\nexport interface PromptSettlementState {\n\treadonly promptRunId: string;\n\treadonly startedAtEpochMs: number;\n\treadonly activeProviderAttempts: number;\n\treadonly activeTools: number;\n\treadonly activeShards: number;\n\treadonly activeChildren: number;\n\treadonly queuedContinuations: number;\n\treadonly terminal?: {\n\t\treadonly outcome: PromptSettlementOutcome;\n\t\treadonly terminationKind?: string;\n\t};\n\treadonly emitted: boolean;\n}\n\nexport type PromptSettlementSignal =\n\t| { readonly kind: \"provider_attempt\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"tool\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"shard\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"child\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"continuation\"; readonly delta: 1 | -1 }\n\t| { readonly kind: \"terminal\"; readonly outcome: PromptSettlementOutcome; readonly terminationKind?: string }\n\t| { readonly kind: \"emitted\" };\n\n/** Map the final typed termination onto the prompt UX outcome. */\nexport function resolvePromptSettlementOutcome(\n\tfallback: PromptSettlementOutcome,\n\tterminationKind: SessionTerminationKind | undefined,\n): PromptSettlementOutcome {\n\tif (terminationKind === \"user_abort\" || terminationKind === \"provider_abort\") return \"aborted\";\n\tif (fallback !== \"completed\") return fallback;\n\tif (terminationKind === undefined || terminationKind === \"completed\") return \"completed\";\n\treturn \"failed\";\n}\n\nexport function createPromptSettlementState(promptRunId: string, startedAtEpochMs: number): PromptSettlementState {\n\treturn {\n\t\tpromptRunId,\n\t\tstartedAtEpochMs,\n\t\tactiveProviderAttempts: 0,\n\t\tactiveTools: 0,\n\t\tactiveShards: 0,\n\t\tactiveChildren: 0,\n\t\tqueuedContinuations: 0,\n\t\temitted: false,\n\t};\n}\n\n/** Pure reducer (§16.5). Counters clamp at zero; terminal and emitted are latching. */\nexport function reducePromptSettlement(\n\tstate: PromptSettlementState,\n\tsignal: PromptSettlementSignal,\n): PromptSettlementState {\n\tswitch (signal.kind) {\n\t\tcase \"provider_attempt\":\n\t\t\treturn { ...state, activeProviderAttempts: clampCount(state.activeProviderAttempts + signal.delta) };\n\t\tcase \"tool\":\n\t\t\treturn { ...state, activeTools: clampCount(state.activeTools + signal.delta) };\n\t\tcase \"shard\":\n\t\t\treturn { ...state, activeShards: clampCount(state.activeShards + signal.delta) };\n\t\tcase \"child\":\n\t\t\treturn { ...state, activeChildren: clampCount(state.activeChildren + signal.delta) };\n\t\tcase \"continuation\":\n\t\t\treturn { ...state, queuedContinuations: clampCount(state.queuedContinuations + signal.delta) };\n\t\tcase \"terminal\":\n\t\t\t// First terminal outcome wins; later reclassification never flips it (§15.3).\n\t\t\tif (state.terminal !== undefined) {\n\t\t\t\treturn state;\n\t\t\t}\n\t\t\treturn { ...state, terminal: { outcome: signal.outcome, terminationKind: signal.terminationKind } };\n\t\tcase \"emitted\":\n\t\t\treturn { ...state, emitted: true };\n\t\tdefault: {\n\t\t\tconst exhaustive: never = signal;\n\t\t\treturn exhaustive;\n\t\t}\n\t}\n}\n\n/** §16.4: every condition must hold before `prompt_settled` may emit. */\nexport function shouldEmitPromptSettled(state: PromptSettlementState): boolean {\n\treturn (\n\t\tstate.terminal !== undefined &&\n\t\t!state.emitted &&\n\t\tstate.activeProviderAttempts === 0 &&\n\t\tstate.activeTools === 0 &&\n\t\tstate.activeShards === 0 &&\n\t\tstate.activeChildren === 0 &&\n\t\tstate.queuedContinuations === 0\n\t);\n}\n\n/**\n * Build the event when (and only when) §16.4 holds, marking the state\n * emitted so the same sequence can never yield a second event.\n */\nexport function settlePromptIfReady(\n\tstate: PromptSettlementState,\n\tnowEpochMs: number,\n): { readonly state: PromptSettlementState; readonly event: PromptSettledEvent | null } {\n\tif (!shouldEmitPromptSettled(state) || state.terminal === undefined) {\n\t\treturn { state, event: null };\n\t}\n\tconst event: PromptSettledEvent = {\n\t\ttype: \"prompt_settled\",\n\t\tpromptRunId: state.promptRunId,\n\t\toutcome: state.terminal.outcome,\n\t\tdurationMs: Math.max(0, nowEpochMs - state.startedAtEpochMs),\n\t\t...(state.terminal.terminationKind !== undefined ? { terminationKind: state.terminal.terminationKind } : {}),\n\t};\n\treturn { state: reducePromptSettlement(state, { kind: \"emitted\" }), event };\n}\n\nfunction clampCount(value: number): number {\n\treturn Math.max(0, value);\n}\n"]}
@@ -0,0 +1,18 @@
1
+ /** Logical stream-dispatch limits for one explicit prompt, not provider billing limits. */
2
+ export interface RunBudgetLimits {
3
+ readonly timeoutMs?: number;
4
+ readonly maxRequests?: number;
5
+ readonly maxConcurrentRequests?: number;
6
+ }
7
+ export declare const RUN_BUDGET_STOP_CODES: readonly ["deadline", "requests", "concurrency", "closed"];
8
+ export type RunBudgetStopCode = (typeof RUN_BUDGET_STOP_CODES)[number];
9
+ export declare class RunBudgetExceededError extends Error {
10
+ readonly code: RunBudgetStopCode;
11
+ constructor(code: RunBudgetStopCode);
12
+ }
13
+ export declare class RunBudgetPolicyError extends Error {
14
+ constructor();
15
+ }
16
+ /** Copy the flat policy without executing accessors or accepting inherited limits. */
17
+ export declare function snapshotRunBudgetLimits(input: unknown): RunBudgetLimits;
18
+ //# sourceMappingURL=run-budget-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-budget-policy.d.ts","sourceRoot":"","sources":["../../src/core/run-budget-policy.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;CACxC;AAED,eAAO,MAAM,qBAAqB,4DAA6D,CAAC;AAChG,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvE,qBAAa,sBAAuB,SAAQ,KAAK;IAChD,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,YAAY,IAAI,EAAE,iBAAiB,EAIlC;CACD;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAC9C,cAGC;CACD;AAED,sFAAsF;AACtF,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAsCvE","sourcesContent":["/** Logical stream-dispatch limits for one explicit prompt, not provider billing limits. */\nexport interface RunBudgetLimits {\n\treadonly timeoutMs?: number;\n\treadonly maxRequests?: number;\n\treadonly maxConcurrentRequests?: number;\n}\n\nexport const RUN_BUDGET_STOP_CODES = [\"deadline\", \"requests\", \"concurrency\", \"closed\"] as const;\nexport type RunBudgetStopCode = (typeof RUN_BUDGET_STOP_CODES)[number];\n\nexport class RunBudgetExceededError extends Error {\n\treadonly code: RunBudgetStopCode;\n\tconstructor(code: RunBudgetStopCode) {\n\t\tsuper(`Run budget exhausted: ${code}`);\n\t\tthis.name = \"RunBudgetExceededError\";\n\t\tthis.code = code;\n\t}\n}\n\nexport class RunBudgetPolicyError extends Error {\n\tconstructor() {\n\t\tsuper(\"Invalid run budget: use non-negative integer limits and a timeout no greater than 2147483647ms\");\n\t\tthis.name = \"RunBudgetPolicyError\";\n\t}\n}\n\n/** Copy the flat policy without executing accessors or accepting inherited limits. */\nexport function snapshotRunBudgetLimits(input: unknown): RunBudgetLimits {\n\tif (typeof input !== \"object\" || input === null || Array.isArray(input)) throw new RunBudgetPolicyError();\n\tconst prototype = Object.getPrototypeOf(input);\n\tif (prototype !== Object.prototype && prototype !== null) throw new RunBudgetPolicyError();\n\tconst keys = Reflect.ownKeys(input);\n\tif (\n\t\tkeys.length === 0 ||\n\t\tkeys.some(\n\t\t\t(key) =>\n\t\t\t\t![\"timeoutMs\", \"maxRequests\", \"maxConcurrentRequests\"].includes(String(key)) || typeof key !== \"string\",\n\t\t)\n\t) {\n\t\tthrow new RunBudgetPolicyError();\n\t}\n\tconst descriptors = Object.getOwnPropertyDescriptors(input);\n\tconst readLimit = (key: keyof RunBudgetLimits): number | undefined => {\n\t\tconst descriptor = descriptors[key];\n\t\tif (descriptor === undefined) return undefined;\n\t\tconst value: unknown = descriptor.value;\n\t\tif (\n\t\t\t!(\"value\" in descriptor) ||\n\t\t\ttypeof value !== \"number\" ||\n\t\t\t!Number.isSafeInteger(value) ||\n\t\t\tvalue < 0 ||\n\t\t\t(key === \"timeoutMs\" && value > 2147483647)\n\t\t) {\n\t\t\tthrow new RunBudgetPolicyError();\n\t\t}\n\t\treturn value;\n\t};\n\tconst timeoutMs = readLimit(\"timeoutMs\");\n\tconst maxRequests = readLimit(\"maxRequests\");\n\tconst maxConcurrentRequests = readLimit(\"maxConcurrentRequests\");\n\treturn Object.freeze({\n\t\t...(timeoutMs === undefined ? {} : { timeoutMs }),\n\t\t...(maxRequests === undefined ? {} : { maxRequests }),\n\t\t...(maxConcurrentRequests === undefined ? {} : { maxConcurrentRequests }),\n\t});\n}\n"]}
@@ -0,0 +1,52 @@
1
+ export const RUN_BUDGET_STOP_CODES = ["deadline", "requests", "concurrency", "closed"];
2
+ export class RunBudgetExceededError extends Error {
3
+ code;
4
+ constructor(code) {
5
+ super(`Run budget exhausted: ${code}`);
6
+ this.name = "RunBudgetExceededError";
7
+ this.code = code;
8
+ }
9
+ }
10
+ export class RunBudgetPolicyError extends Error {
11
+ constructor() {
12
+ super("Invalid run budget: use non-negative integer limits and a timeout no greater than 2147483647ms");
13
+ this.name = "RunBudgetPolicyError";
14
+ }
15
+ }
16
+ /** Copy the flat policy without executing accessors or accepting inherited limits. */
17
+ export function snapshotRunBudgetLimits(input) {
18
+ if (typeof input !== "object" || input === null || Array.isArray(input))
19
+ throw new RunBudgetPolicyError();
20
+ const prototype = Object.getPrototypeOf(input);
21
+ if (prototype !== Object.prototype && prototype !== null)
22
+ throw new RunBudgetPolicyError();
23
+ const keys = Reflect.ownKeys(input);
24
+ if (keys.length === 0 ||
25
+ keys.some((key) => !["timeoutMs", "maxRequests", "maxConcurrentRequests"].includes(String(key)) || typeof key !== "string")) {
26
+ throw new RunBudgetPolicyError();
27
+ }
28
+ const descriptors = Object.getOwnPropertyDescriptors(input);
29
+ const readLimit = (key) => {
30
+ const descriptor = descriptors[key];
31
+ if (descriptor === undefined)
32
+ return undefined;
33
+ const value = descriptor.value;
34
+ if (!("value" in descriptor) ||
35
+ typeof value !== "number" ||
36
+ !Number.isSafeInteger(value) ||
37
+ value < 0 ||
38
+ (key === "timeoutMs" && value > 2147483647)) {
39
+ throw new RunBudgetPolicyError();
40
+ }
41
+ return value;
42
+ };
43
+ const timeoutMs = readLimit("timeoutMs");
44
+ const maxRequests = readLimit("maxRequests");
45
+ const maxConcurrentRequests = readLimit("maxConcurrentRequests");
46
+ return Object.freeze({
47
+ ...(timeoutMs === undefined ? {} : { timeoutMs }),
48
+ ...(maxRequests === undefined ? {} : { maxRequests }),
49
+ ...(maxConcurrentRequests === undefined ? {} : { maxConcurrentRequests }),
50
+ });
51
+ }
52
+ //# sourceMappingURL=run-budget-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-budget-policy.js","sourceRoot":"","sources":["../../src/core/run-budget-policy.ts"],"names":[],"mappings":"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","sourcesContent":["/** Logical stream-dispatch limits for one explicit prompt, not provider billing limits. */\nexport interface RunBudgetLimits {\n\treadonly timeoutMs?: number;\n\treadonly maxRequests?: number;\n\treadonly maxConcurrentRequests?: number;\n}\n\nexport const RUN_BUDGET_STOP_CODES = [\"deadline\", \"requests\", \"concurrency\", \"closed\"] as const;\nexport type RunBudgetStopCode = (typeof RUN_BUDGET_STOP_CODES)[number];\n\nexport class RunBudgetExceededError extends Error {\n\treadonly code: RunBudgetStopCode;\n\tconstructor(code: RunBudgetStopCode) {\n\t\tsuper(`Run budget exhausted: ${code}`);\n\t\tthis.name = \"RunBudgetExceededError\";\n\t\tthis.code = code;\n\t}\n}\n\nexport class RunBudgetPolicyError extends Error {\n\tconstructor() {\n\t\tsuper(\"Invalid run budget: use non-negative integer limits and a timeout no greater than 2147483647ms\");\n\t\tthis.name = \"RunBudgetPolicyError\";\n\t}\n}\n\n/** Copy the flat policy without executing accessors or accepting inherited limits. */\nexport function snapshotRunBudgetLimits(input: unknown): RunBudgetLimits {\n\tif (typeof input !== \"object\" || input === null || Array.isArray(input)) throw new RunBudgetPolicyError();\n\tconst prototype = Object.getPrototypeOf(input);\n\tif (prototype !== Object.prototype && prototype !== null) throw new RunBudgetPolicyError();\n\tconst keys = Reflect.ownKeys(input);\n\tif (\n\t\tkeys.length === 0 ||\n\t\tkeys.some(\n\t\t\t(key) =>\n\t\t\t\t![\"timeoutMs\", \"maxRequests\", \"maxConcurrentRequests\"].includes(String(key)) || typeof key !== \"string\",\n\t\t)\n\t) {\n\t\tthrow new RunBudgetPolicyError();\n\t}\n\tconst descriptors = Object.getOwnPropertyDescriptors(input);\n\tconst readLimit = (key: keyof RunBudgetLimits): number | undefined => {\n\t\tconst descriptor = descriptors[key];\n\t\tif (descriptor === undefined) return undefined;\n\t\tconst value: unknown = descriptor.value;\n\t\tif (\n\t\t\t!(\"value\" in descriptor) ||\n\t\t\ttypeof value !== \"number\" ||\n\t\t\t!Number.isSafeInteger(value) ||\n\t\t\tvalue < 0 ||\n\t\t\t(key === \"timeoutMs\" && value > 2147483647)\n\t\t) {\n\t\t\tthrow new RunBudgetPolicyError();\n\t\t}\n\t\treturn value;\n\t};\n\tconst timeoutMs = readLimit(\"timeoutMs\");\n\tconst maxRequests = readLimit(\"maxRequests\");\n\tconst maxConcurrentRequests = readLimit(\"maxConcurrentRequests\");\n\treturn Object.freeze({\n\t\t...(timeoutMs === undefined ? {} : { timeoutMs }),\n\t\t...(maxRequests === undefined ? {} : { maxRequests }),\n\t\t...(maxConcurrentRequests === undefined ? {} : { maxConcurrentRequests }),\n\t});\n}\n"]}
@@ -0,0 +1,33 @@
1
+ import { RunBudgetExceededError, type RunBudgetLimits, type RunBudgetStopCode } from "./run-budget-policy.ts";
2
+ export interface RunBudgetSnapshot {
3
+ readonly limits: RunBudgetLimits;
4
+ readonly requestsStarted: number;
5
+ readonly activeRequests: number;
6
+ readonly remainingMs?: number;
7
+ readonly closed: boolean;
8
+ readonly exhaustedBy?: RunBudgetStopCode;
9
+ }
10
+ /** One in-memory, monotonic budget shared by every dispatch in a prompt. */
11
+ export declare class RunBudget {
12
+ readonly limits: RunBudgetLimits;
13
+ private readonly controller;
14
+ private readonly deadline;
15
+ private readonly onExhausted;
16
+ private readonly active;
17
+ private timer;
18
+ private issued;
19
+ private closed;
20
+ private exhausted;
21
+ constructor(limits: RunBudgetLimits, onExhausted: (error: RunBudgetExceededError) => void);
22
+ get signal(): AbortSignal;
23
+ get failure(): RunBudgetExceededError | undefined;
24
+ get remainingMs(): number | undefined;
25
+ assertActive(): void;
26
+ assertAdmission(): void;
27
+ admit(): () => void;
28
+ snapshot(): RunBudgetSnapshot;
29
+ close(): void;
30
+ private exhaust;
31
+ private armDeadline;
32
+ }
33
+ //# sourceMappingURL=run-budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-budget.d.ts","sourceRoot":"","sources":["../../src/core/run-budget.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,sBAAsB,EACtB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EAEtB,MAAM,wBAAwB,CAAC;AAEhC,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,iBAAiB,CAAC;CACzC;AAED,4EAA4E;AAC5E,qBAAa,SAAS;IACrB,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0C;IACtE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,KAAK,CAA4C;IACzD,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAqC;IAEtD,YAAY,MAAM,EAAE,eAAe,EAAE,WAAW,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,EAKxF;IAED,IAAI,MAAM,IAAI,WAAW,CAExB;IACD,IAAI,OAAO,IAAI,sBAAsB,GAAG,SAAS,CAEhD;IACD,IAAI,WAAW,IAAI,MAAM,GAAG,SAAS,CAEpC;IAED,YAAY,IAAI,IAAI,CAInB;IAED,eAAe,IAAI,IAAI,CAItB;IAED,KAAK,IAAI,MAAM,IAAI,CAQlB;IAED,QAAQ,IAAI,iBAAiB,CAS5B;IAED,KAAK,IAAI,IAAI,CAIZ;IAED,OAAO,CAAC,OAAO;IAUf,OAAO,CAAC,WAAW;CAOnB","sourcesContent":["import {\n\tRunBudgetExceededError,\n\ttype RunBudgetLimits,\n\ttype RunBudgetStopCode,\n\tsnapshotRunBudgetLimits,\n} from \"./run-budget-policy.ts\";\n\nexport interface RunBudgetSnapshot {\n\treadonly limits: RunBudgetLimits;\n\treadonly requestsStarted: number;\n\treadonly activeRequests: number;\n\treadonly remainingMs?: number;\n\treadonly closed: boolean;\n\treadonly exhaustedBy?: RunBudgetStopCode;\n}\n\n/** One in-memory, monotonic budget shared by every dispatch in a prompt. */\nexport class RunBudget {\n\treadonly limits: RunBudgetLimits;\n\tprivate readonly controller = new AbortController();\n\tprivate readonly deadline: number | undefined;\n\tprivate readonly onExhausted: (error: RunBudgetExceededError) => void;\n\tprivate readonly active = new Set<symbol>();\n\tprivate timer: ReturnType<typeof setTimeout> | undefined;\n\tprivate issued = 0;\n\tprivate closed = false;\n\tprivate exhausted: RunBudgetExceededError | undefined;\n\n\tconstructor(limits: RunBudgetLimits, onExhausted: (error: RunBudgetExceededError) => void) {\n\t\tthis.limits = snapshotRunBudgetLimits(limits);\n\t\tthis.onExhausted = onExhausted;\n\t\tthis.deadline = this.limits.timeoutMs === undefined ? undefined : performance.now() + this.limits.timeoutMs;\n\t\tif (this.deadline !== undefined) this.armDeadline();\n\t}\n\n\tget signal(): AbortSignal {\n\t\treturn this.controller.signal;\n\t}\n\tget failure(): RunBudgetExceededError | undefined {\n\t\treturn this.exhausted;\n\t}\n\tget remainingMs(): number | undefined {\n\t\treturn this.deadline === undefined ? undefined : Math.max(0, Math.ceil(this.deadline - performance.now()));\n\t}\n\n\tassertActive(): void {\n\t\tif (this.closed) throw new RunBudgetExceededError(\"closed\");\n\t\tif (this.exhausted) throw this.exhausted;\n\t\tif (this.deadline !== undefined && performance.now() >= this.deadline) throw this.exhaust(\"deadline\");\n\t}\n\n\tassertAdmission(): void {\n\t\tthis.assertActive();\n\t\tif (this.issued >= (this.limits.maxRequests ?? Infinity)) throw this.exhaust(\"requests\");\n\t\tif (this.active.size >= (this.limits.maxConcurrentRequests ?? Infinity)) throw this.exhaust(\"concurrency\");\n\t}\n\n\tadmit(): () => void {\n\t\tthis.assertAdmission();\n\t\tconst request = Symbol();\n\t\tthis.issued += 1;\n\t\tthis.active.add(request);\n\t\treturn () => {\n\t\t\tthis.active.delete(request);\n\t\t};\n\t}\n\n\tsnapshot(): RunBudgetSnapshot {\n\t\treturn Object.freeze({\n\t\t\tlimits: this.limits,\n\t\t\trequestsStarted: this.issued,\n\t\t\tactiveRequests: this.active.size,\n\t\t\tremainingMs: this.remainingMs,\n\t\t\tclosed: this.closed,\n\t\t\t...(this.exhausted ? { exhaustedBy: this.exhausted.code } : {}),\n\t\t});\n\t}\n\n\tclose(): void {\n\t\tthis.closed = true;\n\t\tclearTimeout(this.timer);\n\t\tthis.controller.abort(new RunBudgetExceededError(\"closed\"));\n\t}\n\n\tprivate exhaust(code: RunBudgetStopCode): RunBudgetExceededError {\n\t\tif (this.exhausted) return this.exhausted;\n\t\tconst error = new RunBudgetExceededError(code);\n\t\tthis.exhausted = error;\n\t\tclearTimeout(this.timer);\n\t\tthis.controller.abort(error);\n\t\tthis.onExhausted(error);\n\t\treturn error;\n\t}\n\n\tprivate armDeadline(): void {\n\t\tthis.timer = setTimeout(() => {\n\t\t\tif (this.closed) return;\n\t\t\tif (this.remainingMs === 0) this.exhaust(\"deadline\");\n\t\t\telse this.armDeadline();\n\t\t}, this.remainingMs);\n\t}\n}\n"]}
@@ -0,0 +1,89 @@
1
+ import { RunBudgetExceededError, snapshotRunBudgetLimits, } from "./run-budget-policy.js";
2
+ /** One in-memory, monotonic budget shared by every dispatch in a prompt. */
3
+ export class RunBudget {
4
+ limits;
5
+ controller = new AbortController();
6
+ deadline;
7
+ onExhausted;
8
+ active = new Set();
9
+ timer;
10
+ issued = 0;
11
+ closed = false;
12
+ exhausted;
13
+ constructor(limits, onExhausted) {
14
+ this.limits = snapshotRunBudgetLimits(limits);
15
+ this.onExhausted = onExhausted;
16
+ this.deadline = this.limits.timeoutMs === undefined ? undefined : performance.now() + this.limits.timeoutMs;
17
+ if (this.deadline !== undefined)
18
+ this.armDeadline();
19
+ }
20
+ get signal() {
21
+ return this.controller.signal;
22
+ }
23
+ get failure() {
24
+ return this.exhausted;
25
+ }
26
+ get remainingMs() {
27
+ return this.deadline === undefined ? undefined : Math.max(0, Math.ceil(this.deadline - performance.now()));
28
+ }
29
+ assertActive() {
30
+ if (this.closed)
31
+ throw new RunBudgetExceededError("closed");
32
+ if (this.exhausted)
33
+ throw this.exhausted;
34
+ if (this.deadline !== undefined && performance.now() >= this.deadline)
35
+ throw this.exhaust("deadline");
36
+ }
37
+ assertAdmission() {
38
+ this.assertActive();
39
+ if (this.issued >= (this.limits.maxRequests ?? Infinity))
40
+ throw this.exhaust("requests");
41
+ if (this.active.size >= (this.limits.maxConcurrentRequests ?? Infinity))
42
+ throw this.exhaust("concurrency");
43
+ }
44
+ admit() {
45
+ this.assertAdmission();
46
+ const request = Symbol();
47
+ this.issued += 1;
48
+ this.active.add(request);
49
+ return () => {
50
+ this.active.delete(request);
51
+ };
52
+ }
53
+ snapshot() {
54
+ return Object.freeze({
55
+ limits: this.limits,
56
+ requestsStarted: this.issued,
57
+ activeRequests: this.active.size,
58
+ remainingMs: this.remainingMs,
59
+ closed: this.closed,
60
+ ...(this.exhausted ? { exhaustedBy: this.exhausted.code } : {}),
61
+ });
62
+ }
63
+ close() {
64
+ this.closed = true;
65
+ clearTimeout(this.timer);
66
+ this.controller.abort(new RunBudgetExceededError("closed"));
67
+ }
68
+ exhaust(code) {
69
+ if (this.exhausted)
70
+ return this.exhausted;
71
+ const error = new RunBudgetExceededError(code);
72
+ this.exhausted = error;
73
+ clearTimeout(this.timer);
74
+ this.controller.abort(error);
75
+ this.onExhausted(error);
76
+ return error;
77
+ }
78
+ armDeadline() {
79
+ this.timer = setTimeout(() => {
80
+ if (this.closed)
81
+ return;
82
+ if (this.remainingMs === 0)
83
+ this.exhaust("deadline");
84
+ else
85
+ this.armDeadline();
86
+ }, this.remainingMs);
87
+ }
88
+ }
89
+ //# sourceMappingURL=run-budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-budget.js","sourceRoot":"","sources":["../../src/core/run-budget.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tRunBudgetExceededError,\n\ttype RunBudgetLimits,\n\ttype RunBudgetStopCode,\n\tsnapshotRunBudgetLimits,\n} from \"./run-budget-policy.ts\";\n\nexport interface RunBudgetSnapshot {\n\treadonly limits: RunBudgetLimits;\n\treadonly requestsStarted: number;\n\treadonly activeRequests: number;\n\treadonly remainingMs?: number;\n\treadonly closed: boolean;\n\treadonly exhaustedBy?: RunBudgetStopCode;\n}\n\n/** One in-memory, monotonic budget shared by every dispatch in a prompt. */\nexport class RunBudget {\n\treadonly limits: RunBudgetLimits;\n\tprivate readonly controller = new AbortController();\n\tprivate readonly deadline: number | undefined;\n\tprivate readonly onExhausted: (error: RunBudgetExceededError) => void;\n\tprivate readonly active = new Set<symbol>();\n\tprivate timer: ReturnType<typeof setTimeout> | undefined;\n\tprivate issued = 0;\n\tprivate closed = false;\n\tprivate exhausted: RunBudgetExceededError | undefined;\n\n\tconstructor(limits: RunBudgetLimits, onExhausted: (error: RunBudgetExceededError) => void) {\n\t\tthis.limits = snapshotRunBudgetLimits(limits);\n\t\tthis.onExhausted = onExhausted;\n\t\tthis.deadline = this.limits.timeoutMs === undefined ? undefined : performance.now() + this.limits.timeoutMs;\n\t\tif (this.deadline !== undefined) this.armDeadline();\n\t}\n\n\tget signal(): AbortSignal {\n\t\treturn this.controller.signal;\n\t}\n\tget failure(): RunBudgetExceededError | undefined {\n\t\treturn this.exhausted;\n\t}\n\tget remainingMs(): number | undefined {\n\t\treturn this.deadline === undefined ? undefined : Math.max(0, Math.ceil(this.deadline - performance.now()));\n\t}\n\n\tassertActive(): void {\n\t\tif (this.closed) throw new RunBudgetExceededError(\"closed\");\n\t\tif (this.exhausted) throw this.exhausted;\n\t\tif (this.deadline !== undefined && performance.now() >= this.deadline) throw this.exhaust(\"deadline\");\n\t}\n\n\tassertAdmission(): void {\n\t\tthis.assertActive();\n\t\tif (this.issued >= (this.limits.maxRequests ?? Infinity)) throw this.exhaust(\"requests\");\n\t\tif (this.active.size >= (this.limits.maxConcurrentRequests ?? Infinity)) throw this.exhaust(\"concurrency\");\n\t}\n\n\tadmit(): () => void {\n\t\tthis.assertAdmission();\n\t\tconst request = Symbol();\n\t\tthis.issued += 1;\n\t\tthis.active.add(request);\n\t\treturn () => {\n\t\t\tthis.active.delete(request);\n\t\t};\n\t}\n\n\tsnapshot(): RunBudgetSnapshot {\n\t\treturn Object.freeze({\n\t\t\tlimits: this.limits,\n\t\t\trequestsStarted: this.issued,\n\t\t\tactiveRequests: this.active.size,\n\t\t\tremainingMs: this.remainingMs,\n\t\t\tclosed: this.closed,\n\t\t\t...(this.exhausted ? { exhaustedBy: this.exhausted.code } : {}),\n\t\t});\n\t}\n\n\tclose(): void {\n\t\tthis.closed = true;\n\t\tclearTimeout(this.timer);\n\t\tthis.controller.abort(new RunBudgetExceededError(\"closed\"));\n\t}\n\n\tprivate exhaust(code: RunBudgetStopCode): RunBudgetExceededError {\n\t\tif (this.exhausted) return this.exhausted;\n\t\tconst error = new RunBudgetExceededError(code);\n\t\tthis.exhausted = error;\n\t\tclearTimeout(this.timer);\n\t\tthis.controller.abort(error);\n\t\tthis.onExhausted(error);\n\t\treturn error;\n\t}\n\n\tprivate armDeadline(): void {\n\t\tthis.timer = setTimeout(() => {\n\t\t\tif (this.closed) return;\n\t\t\tif (this.remainingMs === 0) this.exhaust(\"deadline\");\n\t\t\telse this.armDeadline();\n\t\t}, this.remainingMs);\n\t}\n}\n"]}
@@ -0,0 +1,15 @@
1
+ /** Public run-budget, journal, and termination contracts. */
2
+ export type { RunBudgetSnapshot } from "./run-budget.ts";
3
+ export { RunBudgetExceededError, type RunBudgetLimits, RunBudgetPolicyError } from "./run-budget-policy.ts";
4
+ export { appendRunJournalRecordDurably, type OpenRunJournalStoreOptions, type RunJournalQuarantineReport, RunJournalStore, RunJournalStoreCorruptionError, writeQuarantineBytesDurably, } from "./run-journal-store.ts";
5
+ export { classifySessionTermination, formatSessionTermination, type SessionTermination, type SessionTerminationCause, SessionTerminationError, type SessionTerminationKind, } from "./session-termination.ts";
6
+ export { planVerifiedRun, RunCoordinator, type VerifiedRunApproval, type VerifiedRunPlan, } from "./verified-run/coordinator.ts";
7
+ export type { TaskRecoveryInspection } from "./verified-run/dag-recovery.ts";
8
+ export type { RunTaskCheckpoint, RunTaskProjection } from "./verified-run/dag-types.ts";
9
+ export type { RunProjection } from "./verified-run/events.ts";
10
+ export type { VerifiedRunEvidence } from "./verified-run/evidence.ts";
11
+ export type { RecoveryInspection } from "./verified-run/recovery.ts";
12
+ export type { RecoveryBudget } from "./verified-run/recovery-clock.ts";
13
+ export { VerifiedRunError } from "./verified-run/storage.ts";
14
+ export type { WriterRecoveryInspection } from "./verified-run/writer-recovery.ts";
15
+ //# sourceMappingURL=run-execution-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-execution-api.d.ts","sourceRoot":"","sources":["../../src/core/run-execution-api.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAE7D,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,KAAK,eAAe,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC5G,OAAO,EACN,6BAA6B,EAC7B,KAAK,0BAA0B,EAC/B,KAAK,0BAA0B,EAC/B,eAAe,EACf,8BAA8B,EAC9B,2BAA2B,GAC3B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACN,0BAA0B,EAC1B,wBAAwB,EACxB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,uBAAuB,EACvB,KAAK,sBAAsB,GAC3B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACN,eAAe,EACf,cAAc,EACd,KAAK,mBAAmB,EACxB,KAAK,eAAe,GACpB,MAAM,+BAA+B,CAAC;AACvC,YAAY,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAC7E,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AACxF,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,YAAY,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,YAAY,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,YAAY,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,YAAY,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAC","sourcesContent":["/** Public run-budget, journal, and termination contracts. */\n\nexport type { RunBudgetSnapshot } from \"./run-budget.ts\";\nexport { RunBudgetExceededError, type RunBudgetLimits, RunBudgetPolicyError } from \"./run-budget-policy.ts\";\nexport {\n\tappendRunJournalRecordDurably,\n\ttype OpenRunJournalStoreOptions,\n\ttype RunJournalQuarantineReport,\n\tRunJournalStore,\n\tRunJournalStoreCorruptionError,\n\twriteQuarantineBytesDurably,\n} from \"./run-journal-store.ts\";\nexport {\n\tclassifySessionTermination,\n\tformatSessionTermination,\n\ttype SessionTermination,\n\ttype SessionTerminationCause,\n\tSessionTerminationError,\n\ttype SessionTerminationKind,\n} from \"./session-termination.ts\";\nexport {\n\tplanVerifiedRun,\n\tRunCoordinator,\n\ttype VerifiedRunApproval,\n\ttype VerifiedRunPlan,\n} from \"./verified-run/coordinator.ts\";\nexport type { TaskRecoveryInspection } from \"./verified-run/dag-recovery.ts\";\nexport type { RunTaskCheckpoint, RunTaskProjection } from \"./verified-run/dag-types.ts\";\nexport type { RunProjection } from \"./verified-run/events.ts\";\nexport type { VerifiedRunEvidence } from \"./verified-run/evidence.ts\";\nexport type { RecoveryInspection } from \"./verified-run/recovery.ts\";\nexport type { RecoveryBudget } from \"./verified-run/recovery-clock.ts\";\nexport { VerifiedRunError } from \"./verified-run/storage.ts\";\nexport type { WriterRecoveryInspection } from \"./verified-run/writer-recovery.ts\";\n"]}
@@ -0,0 +1,7 @@
1
+ /** Public run-budget, journal, and termination contracts. */
2
+ export { RunBudgetExceededError, RunBudgetPolicyError } from "./run-budget-policy.js";
3
+ export { appendRunJournalRecordDurably, RunJournalStore, RunJournalStoreCorruptionError, writeQuarantineBytesDurably, } from "./run-journal-store.js";
4
+ export { classifySessionTermination, formatSessionTermination, SessionTerminationError, } from "./session-termination.js";
5
+ export { planVerifiedRun, RunCoordinator, } from "./verified-run/coordinator.js";
6
+ export { VerifiedRunError } from "./verified-run/storage.js";
7
+ //# sourceMappingURL=run-execution-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-execution-api.js","sourceRoot":"","sources":["../../src/core/run-execution-api.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAG7D,OAAO,EAAE,sBAAsB,EAAwB,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC5G,OAAO,EACN,6BAA6B,EAG7B,eAAe,EACf,8BAA8B,EAC9B,2BAA2B,GAC3B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACN,0BAA0B,EAC1B,wBAAwB,EAGxB,uBAAuB,GAEvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACN,eAAe,EACf,cAAc,GAGd,MAAM,+BAA+B,CAAC;AAOvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC","sourcesContent":["/** Public run-budget, journal, and termination contracts. */\n\nexport type { RunBudgetSnapshot } from \"./run-budget.ts\";\nexport { RunBudgetExceededError, type RunBudgetLimits, RunBudgetPolicyError } from \"./run-budget-policy.ts\";\nexport {\n\tappendRunJournalRecordDurably,\n\ttype OpenRunJournalStoreOptions,\n\ttype RunJournalQuarantineReport,\n\tRunJournalStore,\n\tRunJournalStoreCorruptionError,\n\twriteQuarantineBytesDurably,\n} from \"./run-journal-store.ts\";\nexport {\n\tclassifySessionTermination,\n\tformatSessionTermination,\n\ttype SessionTermination,\n\ttype SessionTerminationCause,\n\tSessionTerminationError,\n\ttype SessionTerminationKind,\n} from \"./session-termination.ts\";\nexport {\n\tplanVerifiedRun,\n\tRunCoordinator,\n\ttype VerifiedRunApproval,\n\ttype VerifiedRunPlan,\n} from \"./verified-run/coordinator.ts\";\nexport type { TaskRecoveryInspection } from \"./verified-run/dag-recovery.ts\";\nexport type { RunTaskCheckpoint, RunTaskProjection } from \"./verified-run/dag-types.ts\";\nexport type { RunProjection } from \"./verified-run/events.ts\";\nexport type { VerifiedRunEvidence } from \"./verified-run/evidence.ts\";\nexport type { RecoveryInspection } from \"./verified-run/recovery.ts\";\nexport type { RecoveryBudget } from \"./verified-run/recovery-clock.ts\";\nexport { VerifiedRunError } from \"./verified-run/storage.ts\";\nexport type { WriterRecoveryInspection } from \"./verified-run/writer-recovery.ts\";\n"]}