@namzu/sdk 34.2.0 → 36.0.0

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 (669) hide show
  1. package/CHANGELOG.md +171 -0
  2. package/README.md +2 -6
  3. package/dist/agents/PipelineAgent.d.ts.map +1 -1
  4. package/dist/agents/PipelineAgent.js +118 -100
  5. package/dist/agents/PipelineAgent.js.map +1 -1
  6. package/dist/agents/ReactiveAgent.d.ts.map +1 -1
  7. package/dist/agents/ReactiveAgent.js +2 -0
  8. package/dist/agents/ReactiveAgent.js.map +1 -1
  9. package/dist/agents/RouterAgent.d.ts.map +1 -1
  10. package/dist/agents/RouterAgent.js +105 -61
  11. package/dist/agents/RouterAgent.js.map +1 -1
  12. package/dist/agents/SupervisorAgent.d.ts.map +1 -1
  13. package/dist/agents/SupervisorAgent.js +8 -4
  14. package/dist/agents/SupervisorAgent.js.map +1 -1
  15. package/dist/agents/budget.d.ts +6 -0
  16. package/dist/agents/budget.d.ts.map +1 -0
  17. package/dist/agents/budget.js +33 -0
  18. package/dist/agents/budget.js.map +1 -0
  19. package/dist/agents/explore.d.ts +20 -0
  20. package/dist/agents/explore.d.ts.map +1 -0
  21. package/dist/agents/explore.js +26 -0
  22. package/dist/agents/explore.js.map +1 -0
  23. package/dist/agents/file-definitions.d.ts +80 -0
  24. package/dist/agents/file-definitions.d.ts.map +1 -0
  25. package/dist/agents/file-definitions.js +179 -0
  26. package/dist/agents/file-definitions.js.map +1 -0
  27. package/dist/agents/index.d.ts +3 -0
  28. package/dist/agents/index.d.ts.map +1 -1
  29. package/dist/agents/index.js +2 -0
  30. package/dist/agents/index.js.map +1 -1
  31. package/dist/bridge/a2a/mapper.d.ts.map +1 -1
  32. package/dist/bridge/a2a/mapper.js +6 -0
  33. package/dist/bridge/a2a/mapper.js.map +1 -1
  34. package/dist/bridge/sse/mapper.d.ts.map +1 -1
  35. package/dist/bridge/sse/mapper.js +22 -0
  36. package/dist/bridge/sse/mapper.js.map +1 -1
  37. package/dist/bus/lock.d.ts.map +1 -1
  38. package/dist/bus/lock.js +1 -10
  39. package/dist/bus/lock.js.map +1 -1
  40. package/dist/compaction/consolidation.d.ts +31 -0
  41. package/dist/compaction/consolidation.d.ts.map +1 -0
  42. package/dist/compaction/consolidation.js +63 -0
  43. package/dist/compaction/consolidation.js.map +1 -0
  44. package/dist/compaction/factory.d.ts.map +1 -1
  45. package/dist/compaction/factory.js +3 -0
  46. package/dist/compaction/factory.js.map +1 -1
  47. package/dist/compaction/index.d.ts +6 -1
  48. package/dist/compaction/index.d.ts.map +1 -1
  49. package/dist/compaction/index.js +6 -0
  50. package/dist/compaction/index.js.map +1 -1
  51. package/dist/compaction/manager.d.ts +7 -0
  52. package/dist/compaction/manager.d.ts.map +1 -1
  53. package/dist/compaction/manager.js +31 -0
  54. package/dist/compaction/manager.js.map +1 -1
  55. package/dist/compaction/plan.d.ts +23 -0
  56. package/dist/compaction/plan.d.ts.map +1 -1
  57. package/dist/compaction/plan.js +41 -24
  58. package/dist/compaction/plan.js.map +1 -1
  59. package/dist/compaction/salience/bm25.d.ts +26 -0
  60. package/dist/compaction/salience/bm25.d.ts.map +1 -0
  61. package/dist/compaction/salience/bm25.js +56 -0
  62. package/dist/compaction/salience/bm25.js.map +1 -0
  63. package/dist/compaction/salience/goal.d.ts +21 -0
  64. package/dist/compaction/salience/goal.d.ts.map +1 -0
  65. package/dist/compaction/salience/goal.js +32 -0
  66. package/dist/compaction/salience/goal.js.map +1 -0
  67. package/dist/compaction/salience/index.d.ts +4 -0
  68. package/dist/compaction/salience/index.d.ts.map +1 -0
  69. package/dist/compaction/salience/index.js +4 -0
  70. package/dist/compaction/salience/index.js.map +1 -0
  71. package/dist/compaction/salience/minhash.d.ts +17 -0
  72. package/dist/compaction/salience/minhash.d.ts.map +1 -0
  73. package/dist/compaction/salience/minhash.js +54 -0
  74. package/dist/compaction/salience/minhash.js.map +1 -0
  75. package/dist/compaction/salience/score.d.ts +64 -0
  76. package/dist/compaction/salience/score.d.ts.map +1 -0
  77. package/dist/compaction/salience/score.js +256 -0
  78. package/dist/compaction/salience/score.js.map +1 -0
  79. package/dist/compaction/salience/tokenize.d.ts +20 -0
  80. package/dist/compaction/salience/tokenize.d.ts.map +1 -0
  81. package/dist/compaction/salience/tokenize.js +92 -0
  82. package/dist/compaction/salience/tokenize.js.map +1 -0
  83. package/dist/compaction/salience/working-set.d.ts +59 -0
  84. package/dist/compaction/salience/working-set.d.ts.map +1 -0
  85. package/dist/compaction/salience/working-set.js +137 -0
  86. package/dist/compaction/salience/working-set.js.map +1 -0
  87. package/dist/compaction/serializer.d.ts +2 -0
  88. package/dist/compaction/serializer.d.ts.map +1 -1
  89. package/dist/compaction/serializer.js +15 -0
  90. package/dist/compaction/serializer.js.map +1 -1
  91. package/dist/compaction/token-estimate.d.ts +13 -0
  92. package/dist/compaction/token-estimate.d.ts.map +1 -0
  93. package/dist/compaction/token-estimate.js +58 -0
  94. package/dist/compaction/token-estimate.js.map +1 -0
  95. package/dist/compaction/tool-result-editing.d.ts +10 -2
  96. package/dist/compaction/tool-result-editing.d.ts.map +1 -1
  97. package/dist/compaction/tool-result-editing.js +22 -24
  98. package/dist/compaction/tool-result-editing.js.map +1 -1
  99. package/dist/compaction/types.d.ts +22 -1
  100. package/dist/compaction/types.d.ts.map +1 -1
  101. package/dist/compaction/wire.d.ts +3 -1
  102. package/dist/compaction/wire.d.ts.map +1 -1
  103. package/dist/compaction/wire.js +2 -0
  104. package/dist/compaction/wire.js.map +1 -1
  105. package/dist/config/runtime.d.ts +58 -28
  106. package/dist/config/runtime.d.ts.map +1 -1
  107. package/dist/config/runtime.js +13 -1
  108. package/dist/config/runtime.js.map +1 -1
  109. package/dist/connector/builtins/http.d.ts.map +1 -1
  110. package/dist/connector/builtins/http.js +2 -8
  111. package/dist/connector/builtins/http.js.map +1 -1
  112. package/dist/connector/builtins/webhook.js +2 -2
  113. package/dist/connector/builtins/webhook.js.map +1 -1
  114. package/dist/connector/mcp/adapter.d.ts +2 -0
  115. package/dist/connector/mcp/adapter.d.ts.map +1 -1
  116. package/dist/connector/mcp/adapter.js +30 -0
  117. package/dist/connector/mcp/adapter.js.map +1 -1
  118. package/dist/connector/tools/adapter.js +2 -2
  119. package/dist/connector/tools/adapter.js.map +1 -1
  120. package/dist/connector/tools/definitions.js +2 -2
  121. package/dist/connector/tools/definitions.js.map +1 -1
  122. package/dist/constants/compaction/index.d.ts +1 -0
  123. package/dist/constants/compaction/index.d.ts.map +1 -1
  124. package/dist/constants/compaction/index.js +1 -0
  125. package/dist/constants/compaction/index.js.map +1 -1
  126. package/dist/constants/telemetry/index.d.ts +0 -1
  127. package/dist/constants/telemetry/index.d.ts.map +1 -1
  128. package/dist/constants/telemetry/index.js +0 -1
  129. package/dist/constants/telemetry/index.js.map +1 -1
  130. package/dist/contracts/a2a.d.ts +5 -5
  131. package/dist/contracts/api.d.ts +4 -2
  132. package/dist/contracts/api.d.ts.map +1 -1
  133. package/dist/contracts/schemas.d.ts +1 -15
  134. package/dist/contracts/schemas.d.ts.map +1 -1
  135. package/dist/contracts/schemas.js +5 -20
  136. package/dist/contracts/schemas.js.map +1 -1
  137. package/dist/invariants/index.d.ts +1 -1
  138. package/dist/manager/agent/lifecycle.d.ts +2 -18
  139. package/dist/manager/agent/lifecycle.d.ts.map +1 -1
  140. package/dist/manager/agent/lifecycle.js +373 -340
  141. package/dist/manager/agent/lifecycle.js.map +1 -1
  142. package/dist/manager/run/persistence.d.ts +3 -0
  143. package/dist/manager/run/persistence.d.ts.map +1 -1
  144. package/dist/manager/run/persistence.js +35 -5
  145. package/dist/manager/run/persistence.js.map +1 -1
  146. package/dist/plugin/index.d.ts +2 -0
  147. package/dist/plugin/index.d.ts.map +1 -1
  148. package/dist/plugin/index.js +1 -0
  149. package/dist/plugin/index.js.map +1 -1
  150. package/dist/plugin/shell-hook.d.ts +128 -0
  151. package/dist/plugin/shell-hook.d.ts.map +1 -0
  152. package/dist/plugin/shell-hook.js +299 -0
  153. package/dist/plugin/shell-hook.js.map +1 -0
  154. package/dist/prompt/coding-agent-doctrine.d.ts +63 -0
  155. package/dist/prompt/coding-agent-doctrine.d.ts.map +1 -0
  156. package/dist/prompt/coding-agent-doctrine.js +100 -0
  157. package/dist/prompt/coding-agent-doctrine.js.map +1 -0
  158. package/dist/prompt/index.d.ts +2 -0
  159. package/dist/prompt/index.d.ts.map +1 -1
  160. package/dist/prompt/index.js +1 -0
  161. package/dist/prompt/index.js.map +1 -1
  162. package/dist/provider/errors.d.ts +1 -1
  163. package/dist/provider/errors.js +1 -1
  164. package/dist/provider/fallback.d.ts +2 -0
  165. package/dist/provider/fallback.d.ts.map +1 -1
  166. package/dist/provider/fallback.js +3 -1
  167. package/dist/provider/fallback.js.map +1 -1
  168. package/dist/provider/retry.d.ts +2 -0
  169. package/dist/provider/retry.d.ts.map +1 -1
  170. package/dist/provider/retry.js +3 -1
  171. package/dist/provider/retry.js.map +1 -1
  172. package/dist/provider/token-budget.d.ts +13 -0
  173. package/dist/provider/token-budget.d.ts.map +1 -0
  174. package/dist/provider/token-budget.js +150 -0
  175. package/dist/provider/token-budget.js.map +1 -0
  176. package/dist/public-runtime.d.ts +14 -14
  177. package/dist/public-runtime.d.ts.map +1 -1
  178. package/dist/public-runtime.js +15 -10
  179. package/dist/public-runtime.js.map +1 -1
  180. package/dist/public-tools.d.ts +2 -0
  181. package/dist/public-tools.d.ts.map +1 -1
  182. package/dist/public-tools.js +2 -0
  183. package/dist/public-tools.js.map +1 -1
  184. package/dist/public-types.d.ts +12 -2
  185. package/dist/public-types.d.ts.map +1 -1
  186. package/dist/registry/command/kernel-commands.d.ts.map +1 -1
  187. package/dist/registry/command/kernel-commands.js +18 -6
  188. package/dist/registry/command/kernel-commands.js.map +1 -1
  189. package/dist/registry/tool/execute.d.ts.map +1 -1
  190. package/dist/registry/tool/execute.js +4 -1
  191. package/dist/registry/tool/execute.js.map +1 -1
  192. package/dist/run/LimitChecker.js +1 -1
  193. package/dist/run/LimitChecker.js.map +1 -1
  194. package/dist/run/drain.js +1 -1
  195. package/dist/run/reporter.d.ts.map +1 -1
  196. package/dist/run/reporter.js +15 -0
  197. package/dist/run/reporter.js.map +1 -1
  198. package/dist/run/token-budget.d.ts +108 -0
  199. package/dist/run/token-budget.d.ts.map +1 -0
  200. package/dist/run/token-budget.js +591 -0
  201. package/dist/run/token-budget.js.map +1 -0
  202. package/dist/runtime/jobs/registry.d.ts +29 -0
  203. package/dist/runtime/jobs/registry.d.ts.map +1 -1
  204. package/dist/runtime/jobs/registry.js +98 -18
  205. package/dist/runtime/jobs/registry.js.map +1 -1
  206. package/dist/runtime/query/checkpoint.d.ts.map +1 -1
  207. package/dist/runtime/query/checkpoint.js +10 -3
  208. package/dist/runtime/query/checkpoint.js.map +1 -1
  209. package/dist/runtime/query/context.d.ts +2 -26
  210. package/dist/runtime/query/context.d.ts.map +1 -1
  211. package/dist/runtime/query/context.js +1 -29
  212. package/dist/runtime/query/context.js.map +1 -1
  213. package/dist/runtime/query/executor.d.ts +13 -9
  214. package/dist/runtime/query/executor.d.ts.map +1 -1
  215. package/dist/runtime/query/executor.js +144 -55
  216. package/dist/runtime/query/executor.js.map +1 -1
  217. package/dist/runtime/query/guard.d.ts.map +1 -1
  218. package/dist/runtime/query/guard.js +8 -0
  219. package/dist/runtime/query/guard.js.map +1 -1
  220. package/dist/runtime/query/index.d.ts +42 -4
  221. package/dist/runtime/query/index.d.ts.map +1 -1
  222. package/dist/runtime/query/index.js +153 -52
  223. package/dist/runtime/query/index.js.map +1 -1
  224. package/dist/runtime/query/iteration/index.d.ts +3 -3
  225. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  226. package/dist/runtime/query/iteration/index.js +47 -11
  227. package/dist/runtime/query/iteration/index.js.map +1 -1
  228. package/dist/runtime/query/iteration/phases/compaction.d.ts.map +1 -1
  229. package/dist/runtime/query/iteration/phases/compaction.js +98 -30
  230. package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
  231. package/dist/runtime/query/iteration/phases/context.d.ts +4 -0
  232. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  233. package/dist/runtime/query/iteration/phases/context.js.map +1 -1
  234. package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
  235. package/dist/runtime/query/iteration/phases/tool-review.js +29 -7
  236. package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
  237. package/dist/runtime/query/iteration/phases/working-memory.d.ts.map +1 -1
  238. package/dist/runtime/query/iteration/phases/working-memory.js +25 -15
  239. package/dist/runtime/query/iteration/phases/working-memory.js.map +1 -1
  240. package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
  241. package/dist/runtime/query/iteration/stream-turn.js +10 -5
  242. package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
  243. package/dist/runtime/query/plugin-hooks.d.ts +1 -1
  244. package/dist/runtime/query/plugin-hooks.d.ts.map +1 -1
  245. package/dist/runtime/query/plugin-hooks.js +20 -1
  246. package/dist/runtime/query/plugin-hooks.js.map +1 -1
  247. package/dist/runtime/query/prompt.d.ts.map +1 -1
  248. package/dist/runtime/query/prompt.js +14 -4
  249. package/dist/runtime/query/prompt.js.map +1 -1
  250. package/dist/runtime/query/repeat-call.d.ts +20 -2
  251. package/dist/runtime/query/repeat-call.d.ts.map +1 -1
  252. package/dist/runtime/query/repeat-call.js +35 -7
  253. package/dist/runtime/query/repeat-call.js.map +1 -1
  254. package/dist/runtime/query/result.d.ts.map +1 -1
  255. package/dist/runtime/query/result.js +9 -0
  256. package/dist/runtime/query/result.js.map +1 -1
  257. package/dist/runtime/query/review-policy.d.ts +142 -0
  258. package/dist/runtime/query/review-policy.d.ts.map +1 -0
  259. package/dist/runtime/query/review-policy.js +144 -0
  260. package/dist/runtime/query/review-policy.js.map +1 -0
  261. package/dist/runtime/query/run-state.d.ts.map +1 -1
  262. package/dist/runtime/query/run-state.js +4 -0
  263. package/dist/runtime/query/run-state.js.map +1 -1
  264. package/dist/runtime/query/steering.d.ts +4 -0
  265. package/dist/runtime/query/steering.d.ts.map +1 -1
  266. package/dist/runtime/query/steering.js +29 -0
  267. package/dist/runtime/query/steering.js.map +1 -1
  268. package/dist/runtime/query/token-budget.d.ts +7 -0
  269. package/dist/runtime/query/token-budget.d.ts.map +1 -0
  270. package/dist/runtime/query/token-budget.js +101 -0
  271. package/dist/runtime/query/token-budget.js.map +1 -0
  272. package/dist/runtime/query/tool-output-budget.d.ts +2 -0
  273. package/dist/runtime/query/tool-output-budget.d.ts.map +1 -1
  274. package/dist/runtime/query/tool-output-budget.js +29 -11
  275. package/dist/runtime/query/tool-output-budget.js.map +1 -1
  276. package/dist/runtime/query/tool-pause.d.ts.map +1 -1
  277. package/dist/runtime/query/tool-pause.js +4 -2
  278. package/dist/runtime/query/tool-pause.js.map +1 -1
  279. package/dist/runtime/query/tooling.d.ts +4 -0
  280. package/dist/runtime/query/tooling.d.ts.map +1 -1
  281. package/dist/runtime/query/tooling.js +4 -0
  282. package/dist/runtime/query/tooling.js.map +1 -1
  283. package/dist/sandbox/file-walk-program.d.ts +3 -0
  284. package/dist/sandbox/file-walk-program.d.ts.map +1 -0
  285. package/dist/sandbox/file-walk-program.js +94 -0
  286. package/dist/sandbox/file-walk-program.js.map +1 -0
  287. package/dist/sandbox/file-walk.d.ts +12 -0
  288. package/dist/sandbox/file-walk.d.ts.map +1 -0
  289. package/dist/sandbox/file-walk.js +429 -0
  290. package/dist/sandbox/file-walk.js.map +1 -0
  291. package/dist/sandbox/index.d.ts +2 -0
  292. package/dist/sandbox/index.d.ts.map +1 -1
  293. package/dist/sandbox/index.js +1 -0
  294. package/dist/sandbox/index.js.map +1 -1
  295. package/dist/sandbox/provider/local.d.ts +3 -1
  296. package/dist/sandbox/provider/local.d.ts.map +1 -1
  297. package/dist/sandbox/provider/local.js +121 -12
  298. package/dist/sandbox/provider/local.js.map +1 -1
  299. package/dist/scheduler/completion-inbox.d.ts +3 -2
  300. package/dist/scheduler/completion-inbox.d.ts.map +1 -1
  301. package/dist/scheduler/completion-inbox.js +29 -15
  302. package/dist/scheduler/completion-inbox.js.map +1 -1
  303. package/dist/scheduler/delegating.d.ts +1 -0
  304. package/dist/scheduler/delegating.d.ts.map +1 -1
  305. package/dist/scheduler/delegating.js +29 -12
  306. package/dist/scheduler/delegating.js.map +1 -1
  307. package/dist/scheduler/local.d.ts +1 -0
  308. package/dist/scheduler/local.d.ts.map +1 -1
  309. package/dist/scheduler/local.js +4 -7
  310. package/dist/scheduler/local.js.map +1 -1
  311. package/dist/session/index.d.ts +0 -1
  312. package/dist/session/index.d.ts.map +1 -1
  313. package/dist/session/index.js +0 -1
  314. package/dist/session/index.js.map +1 -1
  315. package/dist/session/workspace/path-builder.d.ts.map +1 -1
  316. package/dist/session/workspace/path-builder.js +5 -4
  317. package/dist/session/workspace/path-builder.js.map +1 -1
  318. package/dist/store/feedback/disk.d.ts.map +1 -1
  319. package/dist/store/feedback/disk.js +4 -6
  320. package/dist/store/feedback/disk.js.map +1 -1
  321. package/dist/store/index.d.ts +2 -0
  322. package/dist/store/index.d.ts.map +1 -1
  323. package/dist/store/index.js +1 -0
  324. package/dist/store/index.js.map +1 -1
  325. package/dist/store/memory/disk.d.ts.map +1 -1
  326. package/dist/store/memory/disk.js +3 -12
  327. package/dist/store/memory/disk.js.map +1 -1
  328. package/dist/store/run/checkpoint-disk.d.ts +3 -3
  329. package/dist/store/run/checkpoint-disk.d.ts.map +1 -1
  330. package/dist/store/run/checkpoint-disk.js +14 -26
  331. package/dist/store/run/checkpoint-disk.js.map +1 -1
  332. package/dist/store/run/claim-disk.js +1 -1
  333. package/dist/store/run/conformance.d.ts +1 -1
  334. package/dist/store/run/conformance.d.ts.map +1 -1
  335. package/dist/store/run/conformance.js +41 -33
  336. package/dist/store/run/conformance.js.map +1 -1
  337. package/dist/store/run/disk.d.ts.map +1 -1
  338. package/dist/store/run/disk.js +20 -4
  339. package/dist/store/run/disk.js.map +1 -1
  340. package/dist/store/run/token-budget-disk.d.ts +37 -0
  341. package/dist/store/run/token-budget-disk.d.ts.map +1 -0
  342. package/dist/store/run/token-budget-disk.js +208 -0
  343. package/dist/store/run/token-budget-disk.js.map +1 -0
  344. package/dist/store/session/disk.d.ts +4 -13
  345. package/dist/store/session/disk.d.ts.map +1 -1
  346. package/dist/store/session/disk.js +34 -31
  347. package/dist/store/session/disk.js.map +1 -1
  348. package/dist/store/session/memory.d.ts +2 -0
  349. package/dist/store/session/memory.d.ts.map +1 -1
  350. package/dist/store/session/memory.js +41 -2
  351. package/dist/store/session/memory.js.map +1 -1
  352. package/dist/store/task/disk.d.ts.map +1 -1
  353. package/dist/store/task/disk.js +7 -8
  354. package/dist/store/task/disk.js.map +1 -1
  355. package/dist/store/topic/memory.d.ts +2 -0
  356. package/dist/store/topic/memory.d.ts.map +1 -1
  357. package/dist/store/topic/memory.js +13 -1
  358. package/dist/store/topic/memory.js.map +1 -1
  359. package/dist/test-support/ids.d.ts +4 -19
  360. package/dist/test-support/ids.d.ts.map +1 -1
  361. package/dist/test-support/ids.js +51 -59
  362. package/dist/test-support/ids.js.map +1 -1
  363. package/dist/tools/advisory/index.d.ts.map +1 -1
  364. package/dist/tools/advisory/index.js +3 -1
  365. package/dist/tools/advisory/index.js.map +1 -1
  366. package/dist/tools/builtins/bash.d.ts +2 -0
  367. package/dist/tools/builtins/bash.d.ts.map +1 -1
  368. package/dist/tools/builtins/bash.js +224 -70
  369. package/dist/tools/builtins/bash.js.map +1 -1
  370. package/dist/tools/builtins/computer-use.d.ts +2 -2
  371. package/dist/tools/builtins/computer-use.d.ts.map +1 -1
  372. package/dist/tools/builtins/computer-use.js +4 -2
  373. package/dist/tools/builtins/computer-use.js.map +1 -1
  374. package/dist/tools/builtins/edit.js +2 -2
  375. package/dist/tools/builtins/edit.js.map +1 -1
  376. package/dist/tools/builtins/glob.d.ts +2 -1
  377. package/dist/tools/builtins/glob.d.ts.map +1 -1
  378. package/dist/tools/builtins/glob.js +95 -103
  379. package/dist/tools/builtins/glob.js.map +1 -1
  380. package/dist/tools/builtins/grep.d.ts.map +1 -1
  381. package/dist/tools/builtins/grep.js +155 -111
  382. package/dist/tools/builtins/grep.js.map +1 -1
  383. package/dist/tools/builtins/ls.js +4 -4
  384. package/dist/tools/builtins/ls.js.map +1 -1
  385. package/dist/tools/builtins/lsp.js +2 -2
  386. package/dist/tools/builtins/lsp.js.map +1 -1
  387. package/dist/tools/builtins/read-file.js +2 -2
  388. package/dist/tools/builtins/read-file.js.map +1 -1
  389. package/dist/tools/builtins/write-file.js +2 -2
  390. package/dist/tools/builtins/write-file.js.map +1 -1
  391. package/dist/tools/coordinator/ask-user-question.d.ts +33 -0
  392. package/dist/tools/coordinator/ask-user-question.d.ts.map +1 -0
  393. package/dist/tools/coordinator/ask-user-question.js +237 -0
  394. package/dist/tools/coordinator/ask-user-question.js.map +1 -0
  395. package/dist/tools/coordinator/index.d.ts +1 -2
  396. package/dist/tools/coordinator/index.d.ts.map +1 -1
  397. package/dist/tools/coordinator/index.js +4 -220
  398. package/dist/tools/coordinator/index.js.map +1 -1
  399. package/dist/tools/memory/read.d.ts.map +1 -1
  400. package/dist/tools/memory/read.js +2 -4
  401. package/dist/tools/memory/read.js.map +1 -1
  402. package/dist/tools/paths.d.ts +13 -0
  403. package/dist/tools/paths.d.ts.map +1 -1
  404. package/dist/tools/paths.js +53 -0
  405. package/dist/tools/paths.js.map +1 -1
  406. package/dist/tools/roster.d.ts +27 -0
  407. package/dist/tools/roster.d.ts.map +1 -0
  408. package/dist/tools/roster.js +42 -0
  409. package/dist/tools/roster.js.map +1 -0
  410. package/dist/types/agent/base.d.ts +5 -0
  411. package/dist/types/agent/base.d.ts.map +1 -1
  412. package/dist/types/agent/pipeline.d.ts +3 -0
  413. package/dist/types/agent/pipeline.d.ts.map +1 -1
  414. package/dist/types/agent/router.d.ts +2 -3
  415. package/dist/types/agent/router.d.ts.map +1 -1
  416. package/dist/types/agent/scheduler.d.ts +3 -0
  417. package/dist/types/agent/scheduler.d.ts.map +1 -1
  418. package/dist/types/agent/task.d.ts +5 -16
  419. package/dist/types/agent/task.d.ts.map +1 -1
  420. package/dist/types/agent/task.js.map +1 -1
  421. package/dist/types/common/index.d.ts.map +1 -1
  422. package/dist/types/common/index.js +3 -0
  423. package/dist/types/common/index.js.map +1 -1
  424. package/dist/types/computer-use/index.d.ts +8 -0
  425. package/dist/types/computer-use/index.d.ts.map +1 -1
  426. package/dist/types/computer-use/index.js.map +1 -1
  427. package/dist/types/hitl/index.d.ts +5 -0
  428. package/dist/types/hitl/index.d.ts.map +1 -1
  429. package/dist/types/hitl/index.js.map +1 -1
  430. package/dist/types/ids/brand.d.ts +5 -47
  431. package/dist/types/ids/brand.d.ts.map +1 -1
  432. package/dist/types/ids/brand.js +2 -39
  433. package/dist/types/ids/brand.js.map +1 -1
  434. package/dist/types/ids/index.d.ts +59 -69
  435. package/dist/types/ids/index.d.ts.map +1 -1
  436. package/dist/types/ids/index.js +12 -10
  437. package/dist/types/ids/index.js.map +1 -1
  438. package/dist/types/permission/index.d.ts +9 -0
  439. package/dist/types/permission/index.d.ts.map +1 -1
  440. package/dist/types/permission/index.js +9 -1
  441. package/dist/types/permission/index.js.map +1 -1
  442. package/dist/types/plugin/index.d.ts +45 -4
  443. package/dist/types/plugin/index.d.ts.map +1 -1
  444. package/dist/types/plugin/index.js +7 -0
  445. package/dist/types/plugin/index.js.map +1 -1
  446. package/dist/types/run/config.d.ts +3 -0
  447. package/dist/types/run/config.d.ts.map +1 -1
  448. package/dist/types/run/emergency.d.ts +5 -0
  449. package/dist/types/run/emergency.d.ts.map +1 -1
  450. package/dist/types/run/emergency.js.map +1 -1
  451. package/dist/types/run/entity.d.ts +6 -2
  452. package/dist/types/run/entity.d.ts.map +1 -1
  453. package/dist/types/run/events.d.ts +35 -0
  454. package/dist/types/run/events.d.ts.map +1 -1
  455. package/dist/types/run/events.js.map +1 -1
  456. package/dist/types/run/index.d.ts +1 -0
  457. package/dist/types/run/index.d.ts.map +1 -1
  458. package/dist/types/run/index.js +1 -0
  459. package/dist/types/run/index.js.map +1 -1
  460. package/dist/types/run/state.d.ts +16 -15
  461. package/dist/types/run/state.d.ts.map +1 -1
  462. package/dist/types/run/state.js +41 -22
  463. package/dist/types/run/state.js.map +1 -1
  464. package/dist/types/run/stop-reason.d.ts +3 -14
  465. package/dist/types/run/stop-reason.d.ts.map +1 -1
  466. package/dist/types/run/token-budget-store.d.ts +29 -0
  467. package/dist/types/run/token-budget-store.d.ts.map +1 -0
  468. package/dist/types/run/token-budget-store.js +25 -0
  469. package/dist/types/run/token-budget-store.js.map +1 -0
  470. package/dist/types/sandbox/index.d.ts +47 -2
  471. package/dist/types/sandbox/index.d.ts.map +1 -1
  472. package/dist/types/sandbox/index.js.map +1 -1
  473. package/dist/types/session/store.d.ts +8 -0
  474. package/dist/types/session/store.d.ts.map +1 -1
  475. package/dist/types/tool/index.d.ts +15 -0
  476. package/dist/types/tool/index.d.ts.map +1 -1
  477. package/dist/types/tool/index.js.map +1 -1
  478. package/dist/utils/frontmatter.d.ts +1 -1
  479. package/dist/utils/frontmatter.js +1 -1
  480. package/dist/utils/id-format.d.ts +3 -0
  481. package/dist/utils/id-format.d.ts.map +1 -0
  482. package/dist/utils/id-format.js +9 -0
  483. package/dist/utils/id-format.js.map +1 -0
  484. package/dist/utils/id.d.ts +65 -32
  485. package/dist/utils/id.d.ts.map +1 -1
  486. package/dist/utils/id.js +168 -148
  487. package/dist/utils/id.js.map +1 -1
  488. package/dist/utils/log/exception.js +1 -1
  489. package/dist/utils/log/exception.js.map +1 -1
  490. package/dist/utils/log/index.d.ts.map +1 -1
  491. package/dist/utils/log/index.js +1 -2
  492. package/dist/utils/log/index.js.map +1 -1
  493. package/dist/utils/log/templates.d.ts.map +1 -1
  494. package/dist/utils/log/templates.js +0 -1
  495. package/dist/utils/log/templates.js.map +1 -1
  496. package/package.json +6 -1
  497. package/src/agents/AGENTS.md +1 -1
  498. package/src/agents/PipelineAgent.ts +129 -109
  499. package/src/agents/ReactiveAgent.ts +2 -0
  500. package/src/agents/RouterAgent.ts +120 -73
  501. package/src/agents/SupervisorAgent.ts +12 -4
  502. package/src/agents/budget.ts +42 -0
  503. package/src/agents/explore.ts +29 -0
  504. package/src/agents/file-definitions.ts +237 -0
  505. package/src/agents/index.ts +15 -0
  506. package/src/bridge/a2a/mapper.ts +6 -0
  507. package/src/bridge/sse/mapper.ts +22 -0
  508. package/src/bus/lock.ts +1 -10
  509. package/src/compaction/consolidation.ts +79 -0
  510. package/src/compaction/factory.ts +3 -0
  511. package/src/compaction/index.ts +34 -4
  512. package/src/compaction/manager.ts +39 -1
  513. package/src/compaction/plan.ts +52 -21
  514. package/src/compaction/salience/bm25.ts +72 -0
  515. package/src/compaction/salience/goal.ts +44 -0
  516. package/src/compaction/salience/index.ts +19 -0
  517. package/src/compaction/salience/minhash.ts +53 -0
  518. package/src/compaction/salience/score.ts +305 -0
  519. package/src/compaction/salience/tokenize.ts +89 -0
  520. package/src/compaction/salience/working-set.ts +187 -0
  521. package/src/compaction/serializer.ts +16 -0
  522. package/src/compaction/token-estimate.ts +57 -0
  523. package/src/compaction/tool-result-editing.ts +28 -26
  524. package/src/compaction/types.ts +24 -1
  525. package/src/compaction/wire.ts +5 -1
  526. package/src/config/runtime.ts +13 -1
  527. package/src/connector/builtins/http.ts +2 -8
  528. package/src/connector/builtins/webhook.ts +2 -2
  529. package/src/connector/mcp/adapter.ts +32 -0
  530. package/src/connector/tools/adapter.ts +2 -2
  531. package/src/connector/tools/definitions.ts +2 -2
  532. package/src/constants/compaction/index.ts +1 -0
  533. package/src/constants/telemetry/index.ts +0 -1
  534. package/src/contracts/api.ts +5 -1
  535. package/src/contracts/schemas.ts +6 -20
  536. package/src/invariants/index.ts +1 -1
  537. package/src/manager/agent/lifecycle.ts +380 -352
  538. package/src/manager/run/persistence.ts +35 -5
  539. package/src/plugin/index.ts +19 -0
  540. package/src/plugin/shell-hook.ts +403 -0
  541. package/src/prompt/coding-agent-doctrine.ts +118 -0
  542. package/src/prompt/index.ts +8 -0
  543. package/src/provider/errors.ts +1 -1
  544. package/src/provider/fallback.ts +4 -1
  545. package/src/provider/retry.ts +4 -1
  546. package/src/provider/token-budget.ts +158 -0
  547. package/src/public-runtime.ts +56 -28
  548. package/src/public-tools.ts +5 -0
  549. package/src/public-types.ts +65 -0
  550. package/src/registry/command/kernel-commands.ts +16 -6
  551. package/src/registry/tool/execute.ts +4 -1
  552. package/src/run/LimitChecker.ts +1 -1
  553. package/src/run/drain.ts +1 -1
  554. package/src/run/reporter.ts +15 -0
  555. package/src/run/token-budget.ts +692 -0
  556. package/src/runtime/jobs/registry.ts +123 -17
  557. package/src/runtime/query/checkpoint.ts +10 -3
  558. package/src/runtime/query/context.ts +3 -57
  559. package/src/runtime/query/executor.ts +181 -71
  560. package/src/runtime/query/guard.ts +8 -0
  561. package/src/runtime/query/index.ts +209 -62
  562. package/src/runtime/query/iteration/index.ts +53 -15
  563. package/src/runtime/query/iteration/phases/compaction.ts +130 -31
  564. package/src/runtime/query/iteration/phases/context.ts +4 -0
  565. package/src/runtime/query/iteration/phases/tool-review.ts +39 -7
  566. package/src/runtime/query/iteration/phases/working-memory.ts +23 -14
  567. package/src/runtime/query/iteration/stream-turn.ts +9 -5
  568. package/src/runtime/query/plugin-hooks.ts +24 -2
  569. package/src/runtime/query/prompt.ts +21 -4
  570. package/src/runtime/query/repeat-call.ts +42 -7
  571. package/src/runtime/query/result.ts +9 -0
  572. package/src/runtime/query/review-policy.ts +231 -0
  573. package/src/runtime/query/run-state.ts +4 -0
  574. package/src/runtime/query/steering.ts +32 -0
  575. package/src/runtime/query/token-budget.ts +127 -0
  576. package/src/runtime/query/tool-output-budget.ts +33 -10
  577. package/src/runtime/query/tool-pause.ts +4 -2
  578. package/src/runtime/query/tooling.ts +8 -0
  579. package/src/sandbox/file-walk-program.ts +93 -0
  580. package/src/sandbox/file-walk.ts +463 -0
  581. package/src/sandbox/index.ts +2 -0
  582. package/src/sandbox/provider/local.ts +136 -13
  583. package/src/scheduler/completion-inbox.ts +29 -19
  584. package/src/scheduler/delegating.ts +35 -13
  585. package/src/scheduler/local.ts +5 -7
  586. package/src/session/index.ts +0 -1
  587. package/src/session/workspace/path-builder.ts +5 -4
  588. package/src/store/feedback/disk.ts +4 -6
  589. package/src/store/index.ts +2 -0
  590. package/src/store/memory/disk.ts +3 -11
  591. package/src/store/run/checkpoint-disk.ts +14 -27
  592. package/src/store/run/claim-disk.ts +1 -1
  593. package/src/store/run/conformance.ts +55 -39
  594. package/src/store/run/disk.ts +19 -4
  595. package/src/store/run/token-budget-disk.ts +247 -0
  596. package/src/store/session/disk.ts +36 -29
  597. package/src/store/session/memory.ts +38 -1
  598. package/src/store/task/disk.ts +7 -8
  599. package/src/store/topic/memory.ts +13 -1
  600. package/src/test-support/ids.ts +62 -59
  601. package/src/tools/advisory/index.ts +3 -1
  602. package/src/tools/builtins/bash.ts +241 -70
  603. package/src/tools/builtins/computer-use.ts +6 -2
  604. package/src/tools/builtins/edit.ts +2 -2
  605. package/src/tools/builtins/glob.ts +104 -122
  606. package/src/tools/builtins/grep.ts +166 -132
  607. package/src/tools/builtins/ls.ts +4 -4
  608. package/src/tools/builtins/lsp.ts +2 -2
  609. package/src/tools/builtins/read-file.ts +2 -2
  610. package/src/tools/builtins/write-file.ts +2 -2
  611. package/src/tools/coordinator/ask-user-question.ts +284 -0
  612. package/src/tools/coordinator/index.ts +5 -248
  613. package/src/tools/memory/read.ts +2 -4
  614. package/src/tools/paths.ts +64 -0
  615. package/src/tools/roster.ts +46 -0
  616. package/src/types/agent/base.ts +6 -0
  617. package/src/types/agent/pipeline.ts +3 -0
  618. package/src/types/agent/router.ts +2 -3
  619. package/src/types/agent/scheduler.ts +4 -0
  620. package/src/types/agent/task.ts +5 -18
  621. package/src/types/common/index.ts +3 -0
  622. package/src/types/computer-use/index.ts +8 -0
  623. package/src/types/hitl/index.ts +5 -0
  624. package/src/types/ids/brand.ts +5 -48
  625. package/src/types/ids/index.ts +66 -75
  626. package/src/types/permission/index.ts +11 -0
  627. package/src/types/plugin/index.ts +49 -1
  628. package/src/types/run/config.ts +3 -0
  629. package/src/types/run/emergency.ts +5 -0
  630. package/src/types/run/entity.ts +6 -2
  631. package/src/types/run/events.ts +37 -0
  632. package/src/types/run/index.ts +1 -0
  633. package/src/types/run/state.ts +58 -30
  634. package/src/types/run/stop-reason.ts +3 -14
  635. package/src/types/run/token-budget-store.ts +54 -0
  636. package/src/types/sandbox/index.ts +53 -0
  637. package/src/types/session/store.ts +8 -0
  638. package/src/types/tool/index.ts +15 -0
  639. package/src/utils/frontmatter.ts +1 -1
  640. package/src/utils/id-format.ts +9 -0
  641. package/src/utils/id.ts +222 -181
  642. package/src/utils/log/exception.ts +1 -1
  643. package/src/utils/log/index.ts +1 -2
  644. package/src/utils/log/templates.ts +0 -1
  645. package/dist/session/migration/errors.d.ts +0 -26
  646. package/dist/session/migration/errors.d.ts.map +0 -1
  647. package/dist/session/migration/errors.js +0 -22
  648. package/dist/session/migration/errors.js.map +0 -1
  649. package/dist/session/migration/filesystem.d.ts +0 -122
  650. package/dist/session/migration/filesystem.d.ts.map +0 -1
  651. package/dist/session/migration/filesystem.js +0 -379
  652. package/dist/session/migration/filesystem.js.map +0 -1
  653. package/dist/session/migration/id-prefix.d.ts +0 -113
  654. package/dist/session/migration/id-prefix.d.ts.map +0 -1
  655. package/dist/session/migration/id-prefix.js +0 -132
  656. package/dist/session/migration/id-prefix.js.map +0 -1
  657. package/dist/session/migration/index.d.ts +0 -12
  658. package/dist/session/migration/index.d.ts.map +0 -1
  659. package/dist/session/migration/index.js +0 -12
  660. package/dist/session/migration/index.js.map +0 -1
  661. package/dist/session/migration/marker.d.ts +0 -57
  662. package/dist/session/migration/marker.d.ts.map +0 -1
  663. package/dist/session/migration/marker.js +0 -123
  664. package/dist/session/migration/marker.js.map +0 -1
  665. package/src/session/migration/errors.ts +0 -23
  666. package/src/session/migration/filesystem.ts +0 -468
  667. package/src/session/migration/id-prefix.ts +0 -166
  668. package/src/session/migration/index.ts +0 -41
  669. package/src/session/migration/marker.ts +0 -142
@@ -0,0 +1,692 @@
1
+ import { randomUUID } from 'node:crypto'
2
+ import { EMPTY_TOKEN_USAGE } from '../constants/limits.js'
3
+ import { type TokenUsage, accumulateTokenUsage } from '../types/common/index.js'
4
+ import type { RunId } from '../types/ids/index.js'
5
+ import type { TokenBudgetBinding, TokenBudgetScope } from '../types/run/token-budget-store.js'
6
+ import { isEntityId } from '../utils/id.js'
7
+
8
+ export interface TokenBudgetAccountSnapshot {
9
+ id: string
10
+ parentId?: string
11
+ limit: number
12
+ settled: boolean
13
+ runId?: RunId
14
+ /** Cumulative own usage per run; descendants never appear in this map. */
15
+ usage: Record<string, TokenUsage>
16
+ }
17
+
18
+ export interface TokenBudgetRequestSnapshot {
19
+ id: string
20
+ accountId: string
21
+ runId: RunId
22
+ /** Cumulative request usage already charged to the owning run. */
23
+ usage?: TokenUsage
24
+ }
25
+
26
+ /** Durable authority independent of a message checkpoint's cadence. */
27
+ export interface TokenBudgetSnapshot {
28
+ version: 1
29
+ rootAccountId: string
30
+ rootRunId: RunId
31
+ accounts: TokenBudgetAccountSnapshot[]
32
+ requests: TokenBudgetRequestSnapshot[]
33
+ /** Durable receipts make repeated completion delivery a no-op. */
34
+ completedRequests: TokenBudgetRequestSnapshot[]
35
+ poisoned?: boolean
36
+ }
37
+
38
+ export interface TokenBudgetPersistence {
39
+ save(snapshot: TokenBudgetSnapshot): Promise<void>
40
+ readonly scope?: TokenBudgetScope
41
+ }
42
+
43
+ export interface TokenBudgetSummary {
44
+ limit: number
45
+ ownTokens: number
46
+ treeTokens: number
47
+ reservedTokens: number
48
+ /** null means unlimited; unlike Infinity this survives JSON serialization. */
49
+ remainingTokens: number | null
50
+ inFlightRequests: number
51
+ unsettledChildren: number
52
+ /** An unresolved provider call or failed ledger write prevents admission. */
53
+ poisoned: boolean
54
+ }
55
+
56
+ interface SharedLedger {
57
+ rootAccountId: string
58
+ rootRunId: RunId
59
+ accounts: Map<string, TokenBudgetAccountSnapshot>
60
+ requests: Map<string, TokenBudgetRequestSnapshot>
61
+ finishedRequests: Map<string, TokenBudgetRequestSnapshot>
62
+ poisoned: boolean
63
+ persistence?: TokenBudgetPersistence
64
+ writes: Promise<void>
65
+ persistenceError?: unknown
66
+ }
67
+
68
+ interface AccountTotals {
69
+ own: number
70
+ tree: number
71
+ reserved: number
72
+ closed: boolean
73
+ }
74
+
75
+ function count(value: unknown, name: string): number {
76
+ if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0) {
77
+ throw new Error(`Invalid token budget ${name}: expected a nonnegative safe integer`)
78
+ }
79
+ return value
80
+ }
81
+
82
+ function object(value: unknown, name: string): Record<string, unknown> {
83
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
84
+ throw new Error(`Invalid token budget ${name}: expected an object`)
85
+ }
86
+ return value as Record<string, unknown>
87
+ }
88
+
89
+ function id(value: unknown, name: string): string {
90
+ if (!isEntityId(value, 'run')) throw new Error(`Invalid token budget ${name}: expected a UUID`)
91
+ return value
92
+ }
93
+
94
+ function usageValue(value: unknown): TokenUsage {
95
+ const source = object(value, 'usage')
96
+ const usage: TokenUsage = {
97
+ promptTokens: count(source.promptTokens, 'promptTokens'),
98
+ completionTokens: count(source.completionTokens, 'completionTokens'),
99
+ totalTokens: count(source.totalTokens, 'totalTokens'),
100
+ cachedTokens: count(source.cachedTokens, 'cachedTokens'),
101
+ cacheWriteTokens: count(source.cacheWriteTokens, 'cacheWriteTokens'),
102
+ ...(source.reasoningTokens === undefined
103
+ ? {}
104
+ : { reasoningTokens: count(source.reasoningTokens, 'reasoningTokens') }),
105
+ }
106
+ // A partial usage frame may understate its total; never lose a component.
107
+ usage.totalTokens = Math.max(
108
+ usage.totalTokens,
109
+ count(usage.promptTokens + usage.completionTokens, 'usage component sum'),
110
+ )
111
+ return usage
112
+ }
113
+
114
+ function addUsage(left: TokenUsage, right: TokenUsage): TokenUsage {
115
+ return usageValue(accumulateTokenUsage(left, right))
116
+ }
117
+
118
+ function maxUsage(left: TokenUsage, right: TokenUsage): TokenUsage {
119
+ return usageValue({
120
+ promptTokens: Math.max(left.promptTokens, right.promptTokens),
121
+ completionTokens: Math.max(left.completionTokens, right.completionTokens),
122
+ totalTokens: Math.max(left.totalTokens, right.totalTokens),
123
+ cachedTokens: Math.max(left.cachedTokens, right.cachedTokens),
124
+ cacheWriteTokens: Math.max(left.cacheWriteTokens, right.cacheWriteTokens),
125
+ ...(left.reasoningTokens === undefined && right.reasoningTokens === undefined
126
+ ? {}
127
+ : { reasoningTokens: Math.max(left.reasoningTokens ?? 0, right.reasoningTokens ?? 0) }),
128
+ })
129
+ }
130
+
131
+ /** Validate the whole tree, then return a defensive, JSON-safe snapshot. */
132
+ export function validateTokenBudgetSnapshot(value: unknown): TokenBudgetSnapshot {
133
+ const source = object(value, 'snapshot')
134
+ if (source.version !== 1) throw new Error('Unsupported token budget snapshot version')
135
+ const rootAccountId = id(source.rootAccountId, 'rootAccountId')
136
+ if (!isEntityId(source.rootRunId, 'run')) throw new Error('Invalid token budget rootRunId')
137
+ if (
138
+ !Array.isArray(source.accounts) ||
139
+ !Array.isArray(source.requests) ||
140
+ !Array.isArray(source.completedRequests)
141
+ ) {
142
+ throw new Error('Invalid token budget accounts or requests')
143
+ }
144
+ if (source.poisoned !== undefined && typeof source.poisoned !== 'boolean') {
145
+ throw new Error('Invalid token budget poisoned flag')
146
+ }
147
+ const runOwners = new Map<string, string>()
148
+ const accounts = source.accounts.map((raw): TokenBudgetAccountSnapshot => {
149
+ const account = object(raw, 'account')
150
+ const accountId = id(account.id, 'account id')
151
+ if (typeof account.settled !== 'boolean') throw new Error('Invalid token budget settled flag')
152
+ const limit = count(account.limit, 'limit')
153
+ if (accountId !== rootAccountId && limit === 0) {
154
+ throw new Error('A child token budget must have a positive limit')
155
+ }
156
+ const usage: Record<string, TokenUsage> = {}
157
+ for (const [runId, rawUsage] of Object.entries(object(account.usage, 'account usage'))) {
158
+ id(runId, 'usage run id')
159
+ if (runOwners.has(runId)) throw new Error('A run belongs to more than one token budget')
160
+ runOwners.set(runId, accountId)
161
+ usage[runId] = usageValue(rawUsage)
162
+ }
163
+ if (account.runId !== undefined) {
164
+ const runId = id(account.runId, 'bound run id')
165
+ if (!Object.hasOwn(usage, runId) || Object.keys(usage).length !== 1) {
166
+ throw new Error('Bound token budget run has no usage watermark')
167
+ }
168
+ } else if (Object.keys(usage).length !== 0) {
169
+ throw new Error('Unbound token budget cannot contain usage')
170
+ }
171
+ return {
172
+ id: accountId,
173
+ ...(account.parentId === undefined ? {} : { parentId: id(account.parentId, 'parent id') }),
174
+ limit,
175
+ settled: account.settled,
176
+ ...(account.runId === undefined ? {} : { runId: account.runId as RunId }),
177
+ usage,
178
+ }
179
+ })
180
+ const byId = new Map(accounts.map((account) => [account.id, account]))
181
+ if (byId.size !== accounts.length) throw new Error('Duplicate token budget account')
182
+ const root = byId.get(rootAccountId)
183
+ if (!root || root.parentId !== undefined || !Object.hasOwn(root.usage, source.rootRunId)) {
184
+ throw new Error('Invalid token budget root account')
185
+ }
186
+ for (const account of accounts) {
187
+ const visited = new Set<string>()
188
+ let cursor: TokenBudgetAccountSnapshot | undefined = account
189
+ while (cursor.id !== rootAccountId) {
190
+ if (visited.has(cursor.id)) throw new Error('Cycle in token budget accounts')
191
+ visited.add(cursor.id)
192
+ cursor = cursor.parentId === undefined ? undefined : byId.get(cursor.parentId)
193
+ if (!cursor) throw new Error('Disconnected token budget account')
194
+ }
195
+ }
196
+ const requestIds = new Set<string>()
197
+ const parseRequest = (raw: unknown): TokenBudgetRequestSnapshot => {
198
+ const request = object(raw, 'request')
199
+ const requestId = id(request.id, 'request id')
200
+ const accountId = id(request.accountId, 'request account id')
201
+ if (!isEntityId(request.runId, 'run')) throw new Error('Invalid token budget request run id')
202
+ if (requestIds.has(requestId)) throw new Error('Duplicate token budget request')
203
+ requestIds.add(requestId)
204
+ if (!byId.has(accountId) || runOwners.get(request.runId) !== accountId) {
205
+ throw new Error('Token budget request has no owning run')
206
+ }
207
+ return {
208
+ id: requestId,
209
+ accountId,
210
+ runId: request.runId,
211
+ ...(request.usage === undefined ? {} : { usage: usageValue(request.usage) }),
212
+ }
213
+ }
214
+ const requests = source.requests.map(parseRequest)
215
+ const completedRequests = source.completedRequests.map(parseRequest)
216
+ const requestAccounts = new Set<string>()
217
+ for (const request of requests) {
218
+ if (requestAccounts.has(request.accountId))
219
+ throw new Error('Multiple requests on one token budget account')
220
+ requestAccounts.add(request.accountId)
221
+ }
222
+ const measuredByRun = new Map<string, TokenUsage>()
223
+ for (const request of [...requests, ...completedRequests]) {
224
+ if (request.usage === undefined) continue
225
+ const measured = addUsage(
226
+ measuredByRun.get(request.runId) ?? { ...EMPTY_TOKEN_USAGE },
227
+ request.usage,
228
+ )
229
+ measuredByRun.set(request.runId, measured)
230
+ const account = byId.get(request.accountId)
231
+ const own = account?.usage[request.runId]
232
+ if (
233
+ !own ||
234
+ measured.totalTokens > own.totalTokens ||
235
+ measured.promptTokens > own.promptTokens ||
236
+ measured.completionTokens > own.completionTokens
237
+ ) {
238
+ throw new Error('Request usage exceeds its owning run watermark')
239
+ }
240
+ }
241
+ // Account sums must also remain representable, including malicious snapshots
242
+ // with individually valid counters whose sum exceeds safe integer arithmetic.
243
+ let aggregate = { ...EMPTY_TOKEN_USAGE }
244
+ for (const account of accounts) {
245
+ for (const usage of Object.values(account.usage)) aggregate = addUsage(aggregate, usage)
246
+ }
247
+ const children = new Map<string, TokenBudgetAccountSnapshot[]>()
248
+ for (const account of accounts) {
249
+ if (account.parentId === undefined) continue
250
+ const siblings = children.get(account.parentId) ?? []
251
+ siblings.push(account)
252
+ children.set(account.parentId, siblings)
253
+ }
254
+ function checkReservations(account: TokenBudgetAccountSnapshot): {
255
+ tree: number
256
+ closed: boolean
257
+ } {
258
+ const descendants = (children.get(account.id) ?? []).map((child) => ({
259
+ child,
260
+ measured: checkReservations(child),
261
+ }))
262
+ count(
263
+ descendants.reduce(
264
+ (sum, { child, measured }) =>
265
+ sum + (measured.closed ? 0 : Math.max(0, child.limit - measured.tree)),
266
+ 0,
267
+ ),
268
+ 'reserved allowance',
269
+ )
270
+ return {
271
+ tree:
272
+ Object.values(account.usage).reduce((sum, usage) => sum + usage.totalTokens, 0) +
273
+ descendants.reduce((sum, { measured }) => sum + measured.tree, 0),
274
+ closed:
275
+ account.settled &&
276
+ !requestAccounts.has(account.id) &&
277
+ descendants.every(({ measured }) => measured.closed),
278
+ }
279
+ }
280
+ checkReservations(root)
281
+ return {
282
+ version: 1,
283
+ rootAccountId,
284
+ rootRunId: source.rootRunId,
285
+ accounts,
286
+ requests,
287
+ completedRequests,
288
+ ...(source.poisoned === undefined ? {} : { poisoned: source.poisoned }),
289
+ }
290
+ }
291
+
292
+ /**
293
+ * One conserved authority for a run and all of its descendants.
294
+ *
295
+ * A child's unused reservation is unavailable to its parent and siblings.
296
+ * Measured spend replaces that reservation, including overshoot debt. Provider
297
+ * usage is known after a request: this enforces admission, not an exact upper
298
+ * bound on the tokens an already admitted request can report.
299
+ */
300
+ export class TokenBudget {
301
+ private constructor(
302
+ private readonly ledger: SharedLedger,
303
+ readonly accountId: string,
304
+ ) {}
305
+
306
+ static create(
307
+ limit: number,
308
+ rootRunId: RunId,
309
+ persistence?: TokenBudgetPersistence,
310
+ ): TokenBudget {
311
+ count(limit, 'limit')
312
+ id(rootRunId, 'root run id')
313
+ const accountId = randomUUID()
314
+ const budget = new TokenBudget(
315
+ {
316
+ rootAccountId: accountId,
317
+ rootRunId,
318
+ accounts: new Map([
319
+ [
320
+ accountId,
321
+ {
322
+ id: accountId,
323
+ limit,
324
+ settled: false,
325
+ runId: rootRunId,
326
+ usage: { [rootRunId]: { ...EMPTY_TOKEN_USAGE } },
327
+ },
328
+ ],
329
+ ]),
330
+ requests: new Map(),
331
+ finishedRequests: new Map(),
332
+ poisoned: false,
333
+ persistence,
334
+ writes: Promise.resolve(),
335
+ },
336
+ accountId,
337
+ )
338
+ budget.persist()
339
+ return budget
340
+ }
341
+
342
+ static restore(snapshot: TokenBudgetSnapshot, persistence?: TokenBudgetPersistence): TokenBudget {
343
+ const state = validateTokenBudgetSnapshot(snapshot)
344
+ return new TokenBudget(
345
+ {
346
+ rootAccountId: state.rootAccountId,
347
+ rootRunId: state.rootRunId,
348
+ accounts: new Map(state.accounts.map((account) => [account.id, account])),
349
+ requests: new Map(state.requests.map((request) => [request.id, request])),
350
+ finishedRequests: new Map(state.completedRequests.map((request) => [request.id, request])),
351
+ poisoned: state.poisoned === true || state.requests.length > 0,
352
+ persistence,
353
+ writes: Promise.resolve(),
354
+ },
355
+ state.rootAccountId,
356
+ )
357
+ }
358
+
359
+ get limit(): number {
360
+ return this.node.limit
361
+ }
362
+ get runId(): RunId | undefined {
363
+ return this.node.runId
364
+ }
365
+ get rootRunId(): RunId {
366
+ return this.ledger.rootRunId
367
+ }
368
+ get binding(): TokenBudgetBinding | undefined {
369
+ const scope = this.ledger.persistence?.scope
370
+ return scope ? { scope: { ...scope }, accountId: this.accountId } : undefined
371
+ }
372
+ get ownUsage(): TokenUsage {
373
+ return Object.values(this.node.usage).reduce(addUsage, { ...EMPTY_TOKEN_USAGE })
374
+ }
375
+ get ownTokens(): number {
376
+ return this.ownUsage.totalTokens
377
+ }
378
+ get treeTokens(): number {
379
+ return this.totals(this.node).tree
380
+ }
381
+
382
+ get remaining(): number {
383
+ if (this.ledger.poisoned || this.node.settled) return 0
384
+ let cursor = this.node
385
+ let available = this.free(cursor)
386
+ while (cursor.parentId !== undefined) {
387
+ const branch = this.totals(cursor)
388
+ const held = branch.closed ? 0 : Math.max(0, cursor.limit - branch.tree)
389
+ cursor = this.requireAccount(cursor.parentId)
390
+ // A sibling's overshoot reduces this branch's promise. A parent's
391
+ // zero unreserved space alone does not exhaust its reserved child.
392
+ available = Math.min(available, this.free(cursor) + held)
393
+ }
394
+ return Math.max(0, available)
395
+ }
396
+
397
+ account(accountId: string): TokenBudget {
398
+ if (!this.descendants(this.node).has(accountId))
399
+ throw new Error('Token budget account is outside this subtree')
400
+ return new TokenBudget(this.ledger, accountId)
401
+ }
402
+
403
+ findRun(runId: RunId): TokenBudget | undefined {
404
+ const descendants = this.descendants(this.node)
405
+ const account = [...this.ledger.accounts.values()].find(
406
+ (node) => descendants.has(node.id) && Object.hasOwn(node.usage, runId),
407
+ )
408
+ return account ? this.account(account.id) : undefined
409
+ }
410
+
411
+ bindRun(runId: RunId): void {
412
+ id(runId, 'bound run id')
413
+ const owner = [...this.ledger.accounts.values()].find((node) =>
414
+ Object.hasOwn(node.usage, runId),
415
+ )
416
+ if (owner && owner.id !== this.accountId)
417
+ throw new Error('Run already belongs to another token budget')
418
+ if (this.node.runId !== undefined && this.node.runId !== runId)
419
+ throw new Error('Token budget run binding is immutable')
420
+ if (this.node.settled && this.node.runId !== runId) throw new Error('Token budget is settled')
421
+ this.node.runId = runId
422
+ this.node.usage[runId] ??= { ...EMPTY_TOKEN_USAGE }
423
+ this.persist()
424
+ }
425
+
426
+ reserve(tokens: number): TokenBudget {
427
+ count(tokens, 'reservation')
428
+ if (this.hasRequest(this.node)) throw new Error('Token budget has an in-flight request')
429
+ if (tokens === 0 || tokens > this.remaining)
430
+ throw new Error('Token budget cannot reserve the requested tokens')
431
+ count(this.totals(this.node).reserved + tokens, 'reserved allowance')
432
+ const accountId = randomUUID()
433
+ this.ledger.accounts.set(accountId, {
434
+ id: accountId,
435
+ parentId: this.accountId,
436
+ limit: tokens,
437
+ settled: false,
438
+ usage: {},
439
+ })
440
+ this.persist()
441
+ return this.account(accountId)
442
+ }
443
+
444
+ /** Narrow the entire subtree; already measured spend and reservations remain. */
445
+ narrow(limit: number): void {
446
+ count(limit, 'limit')
447
+ // Numeric run configuration uses zero for "no additional limit". It
448
+ // cannot remove an inherited finite authority.
449
+ if (limit === 0 || limit === this.limit) return
450
+ if (this.limit !== 0 && limit > this.limit)
451
+ throw new Error('Token budget cannot widen its limit')
452
+ this.node.limit = limit
453
+ this.persist()
454
+ }
455
+
456
+ /** Reconcile a cumulative OWN run counter; a completion is not another spend. */
457
+ recordUsage(usage: TokenUsage, runId: RunId | undefined = this.runId): void {
458
+ const previous = this.requireOwnUsage(runId)
459
+ const next = maxUsage(previous, usageValue(usage))
460
+ this.checkAggregateReplacement(previous, next)
461
+ if (runId === undefined) throw new Error('Token budget run is not bound')
462
+ this.node.usage[runId] = next
463
+ this.persist()
464
+ }
465
+
466
+ async beginRequest(): Promise<string> {
467
+ if (this.ledger.poisoned) throw new Error('Token budget has unresolved spend')
468
+ if (this.node.settled) throw new Error('Token budget is settled')
469
+ if (this.remaining <= 0) throw new Error('Token budget is exhausted')
470
+ const runId = this.runId
471
+ if (runId === undefined) throw new Error('Token budget run is not bound')
472
+ // Requests on different child scopes may run concurrently. The same
473
+ // account cannot promise its unmeasured allowance twice.
474
+ if (this.hasRequest(this.node)) throw new Error('Token budget has an in-flight request')
475
+ const requestId = randomUUID()
476
+ this.ledger.requests.set(requestId, { id: requestId, accountId: this.accountId, runId })
477
+ this.persist()
478
+ await this.flush()
479
+ return requestId
480
+ }
481
+
482
+ async finishRequest(requestId: string, usage: TokenUsage): Promise<void> {
483
+ if (this.hasReceipt(requestId)) return this.flush()
484
+ const request = this.requireRequest(requestId)
485
+ try {
486
+ this.recordRequestUsage(request, usage)
487
+ } catch (error) {
488
+ this.ledger.poisoned = true
489
+ this.persist()
490
+ await this.flush()
491
+ throw error
492
+ }
493
+ this.ledger.requests.delete(requestId)
494
+ this.ledger.finishedRequests.set(requestId, request)
495
+ this.persist()
496
+ await this.flush()
497
+ }
498
+
499
+ /** Unknown spend cannot be converted into a refund, even after cancellation. */
500
+ async failRequest(requestId: string, usage?: TokenUsage): Promise<void> {
501
+ if (this.hasReceipt(requestId)) return this.flush()
502
+ const request = this.requireRequest(requestId)
503
+ this.ledger.poisoned = true
504
+ try {
505
+ if (usage !== undefined) this.recordRequestUsage(request, usage)
506
+ } catch (error) {
507
+ this.persist()
508
+ await this.flush()
509
+ throw error
510
+ }
511
+ this.persist()
512
+ await this.flush()
513
+ }
514
+
515
+ /**
516
+ * Explicit host recovery after obtaining the provider's final usage receipt.
517
+ * Ordinary completion never reopens an uncertain ledger. Reconciliation can
518
+ * do so only after every outstanding request has a measured receipt and all
519
+ * accounting writes succeeded; it never resets usage or settled accounts.
520
+ */
521
+ async reconcileRequest(requestId: string, usage: TokenUsage): Promise<void> {
522
+ const measured = usageValue(usage)
523
+ if (this.hasReceipt(requestId)) {
524
+ const receipt = this.ledger.finishedRequests.get(requestId)
525
+ if (!receipt) throw new Error('Unknown token budget receipt')
526
+ // A recovered receipt may contain more usage than an earlier report.
527
+ // Preserve that evidence even though ordinary duplicate completion is
528
+ // a no-op. Repeating this same receipt still charges nothing twice.
529
+ this.recordRequestUsage(receipt, measured)
530
+ this.persist()
531
+ await this.flush()
532
+ } else {
533
+ await this.finishRequest(requestId, measured)
534
+ }
535
+ if (this.ledger.requests.size === 0 && this.ledger.persistenceError === undefined) {
536
+ this.ledger.poisoned = false
537
+ this.persist()
538
+ await this.flush()
539
+ }
540
+ }
541
+
542
+ settle(ownTotalTokens?: number): void {
543
+ if (ownTotalTokens !== undefined) {
544
+ count(ownTotalTokens, 'settled own tokens')
545
+ if (ownTotalTokens > this.ownTokens) {
546
+ if (this.runId === undefined)
547
+ throw new Error('Unbound token budget cannot settle nonzero usage')
548
+ const previous = this.requireOwnUsage(this.runId)
549
+ this.recordUsage({
550
+ ...previous,
551
+ totalTokens: previous.totalTokens + ownTotalTokens - this.ownTokens,
552
+ })
553
+ }
554
+ }
555
+ this.node.settled = true
556
+ this.persist()
557
+ }
558
+
559
+ summary(): TokenBudgetSummary {
560
+ const totals = this.totals(this.node)
561
+ const descendants = this.descendants(this.node)
562
+ return {
563
+ limit: this.limit,
564
+ ownTokens: totals.own,
565
+ treeTokens: totals.tree,
566
+ reservedTokens: totals.reserved,
567
+ remainingTokens: Number.isFinite(this.remaining) ? this.remaining : null,
568
+ inFlightRequests: [...this.ledger.requests.values()].filter((request) =>
569
+ descendants.has(request.accountId),
570
+ ).length,
571
+ unsettledChildren: this.children(this.node).filter((child) => !this.totals(child).closed)
572
+ .length,
573
+ poisoned: this.ledger.poisoned,
574
+ }
575
+ }
576
+
577
+ snapshot(): TokenBudgetSnapshot {
578
+ return structuredClone({
579
+ version: 1,
580
+ rootAccountId: this.ledger.rootAccountId,
581
+ rootRunId: this.rootRunId,
582
+ accounts: [...this.ledger.accounts.values()],
583
+ requests: [...this.ledger.requests.values()],
584
+ completedRequests: [...this.ledger.finishedRequests.values()],
585
+ ...(this.ledger.poisoned ? { poisoned: true } : {}),
586
+ })
587
+ }
588
+
589
+ async flush(): Promise<void> {
590
+ await this.ledger.writes
591
+ if (this.ledger.persistenceError !== undefined) throw this.ledger.persistenceError
592
+ }
593
+
594
+ private get node(): TokenBudgetAccountSnapshot {
595
+ return this.requireAccount(this.accountId)
596
+ }
597
+ private requireAccount(accountId: string): TokenBudgetAccountSnapshot {
598
+ const account = this.ledger.accounts.get(accountId)
599
+ if (!account) throw new Error('Unknown token budget account')
600
+ return account
601
+ }
602
+ private requireOwnUsage(runId: RunId | undefined): TokenUsage {
603
+ const usage = runId === undefined ? undefined : this.node.usage[runId]
604
+ if (!usage) throw new Error('Token budget run is not bound')
605
+ return usage
606
+ }
607
+ private hasReceipt(requestId: string): boolean {
608
+ const receipt = this.ledger.finishedRequests.get(requestId)
609
+ if (receipt && receipt.accountId !== this.accountId)
610
+ throw new Error('Token budget receipt belongs to another account')
611
+ return receipt !== undefined
612
+ }
613
+ private recordRequestUsage(request: TokenBudgetRequestSnapshot, usage: TokenUsage): void {
614
+ const observed = request.usage ?? { ...EMPTY_TOKEN_USAGE }
615
+ const measured = maxUsage(observed, usageValue(usage))
616
+ const delta: TokenUsage = {
617
+ promptTokens: measured.promptTokens - observed.promptTokens,
618
+ completionTokens: measured.completionTokens - observed.completionTokens,
619
+ totalTokens: measured.totalTokens - observed.totalTokens,
620
+ cachedTokens: measured.cachedTokens - observed.cachedTokens,
621
+ cacheWriteTokens: measured.cacheWriteTokens - observed.cacheWriteTokens,
622
+ ...(measured.reasoningTokens === undefined
623
+ ? {}
624
+ : { reasoningTokens: measured.reasoningTokens - (observed.reasoningTokens ?? 0) }),
625
+ }
626
+ const previous = this.requireOwnUsage(request.runId)
627
+ const next = addUsage(previous, delta)
628
+ this.checkAggregateReplacement(previous, next)
629
+ this.node.usage[request.runId] = next
630
+ request.usage = measured
631
+ }
632
+ private children(node: TokenBudgetAccountSnapshot): TokenBudgetAccountSnapshot[] {
633
+ return [...this.ledger.accounts.values()].filter((account) => account.parentId === node.id)
634
+ }
635
+ private descendants(node: TokenBudgetAccountSnapshot): Set<string> {
636
+ return new Set([
637
+ node.id,
638
+ ...this.children(node).flatMap((child) => [...this.descendants(child)]),
639
+ ])
640
+ }
641
+ private hasRequest(node: TokenBudgetAccountSnapshot): boolean {
642
+ return [...this.ledger.requests.values()].some((request) => request.accountId === node.id)
643
+ }
644
+ private totals(node: TokenBudgetAccountSnapshot): AccountTotals {
645
+ const children = this.children(node).map((child) => ({ child, totals: this.totals(child) }))
646
+ const own = Object.values(node.usage).reduce((sum, usage) => sum + usage.totalTokens, 0)
647
+ return {
648
+ own,
649
+ tree: own + children.reduce((sum, { totals }) => sum + totals.tree, 0),
650
+ reserved: children.reduce(
651
+ (sum, { child, totals }) =>
652
+ sum + (totals.closed ? 0 : Math.max(0, child.limit - totals.tree)),
653
+ 0,
654
+ ),
655
+ closed:
656
+ node.settled && !this.hasRequest(node) && children.every(({ totals }) => totals.closed),
657
+ }
658
+ }
659
+ private free(node: TokenBudgetAccountSnapshot): number {
660
+ if (node.limit === 0) return Number.POSITIVE_INFINITY
661
+ const totals = this.totals(node)
662
+ return node.limit - totals.tree - totals.reserved
663
+ }
664
+ private requireRequest(requestId: string): TokenBudgetRequestSnapshot {
665
+ const request = this.ledger.requests.get(requestId)
666
+ if (!request || request.accountId !== this.accountId)
667
+ throw new Error('Unknown token budget request')
668
+ return request
669
+ }
670
+ private checkAggregateReplacement(previous: TokenUsage, next: TokenUsage): void {
671
+ count(
672
+ this.totals(this.requireAccount(this.ledger.rootAccountId)).tree -
673
+ previous.totalTokens +
674
+ next.totalTokens,
675
+ 'tree usage',
676
+ )
677
+ }
678
+ private persist(): void {
679
+ if (!this.ledger.persistence) return
680
+ const snapshot = this.snapshot()
681
+ const persistence = this.ledger.persistence
682
+ this.ledger.writes = this.ledger.writes.then(async () => {
683
+ if (this.ledger.persistenceError !== undefined) return
684
+ try {
685
+ await persistence.save(snapshot)
686
+ } catch (error) {
687
+ this.ledger.persistenceError = error ?? new Error('Token budget persistence failed')
688
+ this.ledger.poisoned = true
689
+ }
690
+ })
691
+ }
692
+ }