@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
@@ -8,6 +8,7 @@ import {
8
8
  } from '../../advisory/index.js'
9
9
  import { drainQueuedMessages } from '../../agents/handle.js'
10
10
  import { AuthorizationGate } from '../../authorization/gate.js'
11
+ import { consolidationEntry } from '../../compaction/consolidation.js'
11
12
  import {
12
13
  type ToolHistoryRepairReport,
13
14
  repairToolMessageHistory,
@@ -18,12 +19,12 @@ import { WorkingStateManager } from '../../compaction/manager.js'
18
19
  import type { ContextReducer } from '../../compaction/reducer.js'
19
20
  import { serializeState as serializeWorkingState } from '../../compaction/serializer.js'
20
21
  import { restoreWorkingState, snapshotWorkingState } from '../../compaction/wire.js'
21
- import type { CompactionConfig } from '../../config/runtime.js'
22
- import { BOOT_EVENT_NAMES } from '../../constants/telemetry/index.js'
22
+ import { type CompactionConfig, CompactionConfigSchema } from '../../config/runtime.js'
23
23
  import { TOOL_OUTPUT_DIR_NAME } from '../../constants/tools/index.js'
24
24
  import { EmergencySaveManager } from '../../manager/run/emergency.js'
25
25
  import type { RunPersistence } from '../../manager/run/persistence.js'
26
26
  import { resolveModelPricing } from '../../pricing/index.js'
27
+ import { PromptContributionRegistry } from '../../prompt/contributions.js'
27
28
  import { resolveProviderCapabilities } from '../../provider/capabilities.js'
28
29
  import { isCallerAbortError } from '../../provider/errors.js'
29
30
  import {
@@ -33,7 +34,8 @@ import {
33
34
  } from '../../provider/fallback.js'
34
35
  import { resolveStreamIdleTimeoutMs, withStreamIdleTimeout } from '../../provider/idle-timeout.js'
35
36
  import { type ProviderRetryConfig, withProviderRetry } from '../../provider/retry.js'
36
- import { DefaultFilesystemMigrator, loggingMigrationSink } from '../../session/migration/index.js'
37
+ import { withTokenBudget } from '../../provider/token-budget.js'
38
+ import type { TokenBudget } from '../../run/token-budget.js'
37
39
  import type { PathBuilder } from '../../session/workspace/path-builder.js'
38
40
  import { resolveAttachments } from '../../store/attachment/index.js'
39
41
  import {
@@ -61,13 +63,13 @@ import type { AuthorizationGateConfig } from '../../types/authorization/index.js
61
63
  import { NamzuError } from '../../types/errors/index.js'
62
64
  import type { InputGuardrailSpec, OutputGuardrailSpec } from '../../types/guardrail/index.js'
63
65
  import {
64
- type CheckpointId,
65
66
  type HITLResumeDecision,
66
67
  type ResumeHandler,
67
68
  autoApproveHandler,
68
69
  } from '../../types/hitl/index.js'
69
- import type { RunId, SessionId, TenantId } from '../../types/ids/index.js'
70
+ import type { CheckpointId, PlanId, RunId, SessionId, TenantId } from '../../types/ids/index.js'
70
71
  import type { InvocationState } from '../../types/invocation/index.js'
72
+ import type { MemoryStore } from '../../types/memory/index.js'
71
73
  import {
72
74
  type AssistantMessage,
73
75
  type Message,
@@ -96,6 +98,7 @@ import type { PromoteMemory } from '../../types/run/memory-promotion.js'
96
98
  import { memoryCandidateFor } from '../../types/run/memory-promotion.js'
97
99
  import type { RunState } from '../../types/run/state.js'
98
100
  import type { RunStore } from '../../types/run/store.js'
101
+ import type { TokenBudgetStore } from '../../types/run/token-budget-store.js'
99
102
  import type { Sandbox, SandboxProvider } from '../../types/sandbox/index.js'
100
103
  import type { ProjectId, TopicId } from '../../types/session/ids.js'
101
104
  import type { Skill } from '../../types/skills/index.js'
@@ -106,9 +109,8 @@ import type { RepairToolCall } from '../../types/tool/repair.js'
106
109
  import type { BackoffPolicy } from '../../utils/backoff.js'
107
110
  import type { ModelPricing } from '../../utils/cost.js'
108
111
  import { toErrorMessage } from '../../utils/error.js'
109
- import { generateRunId } from '../../utils/id.js'
112
+ import { generateCheckpointId, generateRunId } from '../../utils/id.js'
110
113
  import { errorAttributes } from '../../utils/log/exception.js'
111
- import { EVENT_NAME_ATTRIBUTE } from '../../utils/log/types.js'
112
114
  import type { Logger } from '../../utils/logger.js'
113
115
  import type { BackgroundJobRegistry } from '../jobs/registry.js'
114
116
  import { AUTO_APPROVE_POLICY_NAME, createRunApprovalPolicy } from './approval-policy.js'
@@ -147,12 +149,17 @@ import {
147
149
  resolveSandboxTeardownTimeoutMs,
148
150
  teardownSandbox,
149
151
  } from './sandbox-lifecycle.js'
150
- import type { SteeringChannel } from './steering.js'
152
+ import { SteeringBinding, type SteeringChannel } from './steering.js'
153
+ import { resolveQueryBudget } from './token-budget.js'
151
154
  import { ToolGrantSet } from './tool-grants.js'
152
155
  import { createToolPause } from './tool-pause.js'
153
156
  import { ToolingBootstrap } from './tooling.js'
154
157
 
155
158
  export interface QueryParams {
159
+ /** One account shared with the task scheduler and descendant runs. */
160
+ budget?: TokenBudget
161
+ /** Canonical tree ledger; defaults to disk beside the root run. */
162
+ tokenBudgetStore?: TokenBudgetStore
156
163
  /**
157
164
  * Notice when the model issues the identical tool call repeatedly, and
158
165
  * say so on the next `tool_result`. Defaults on.
@@ -274,6 +281,16 @@ export interface QueryParams {
274
281
  * background execution is refused rather than silently bypassing the sandbox.
275
282
  */
276
283
  backgroundJobs?: BackgroundJobRegistry
284
+ /**
285
+ * Which owner the run's background jobs belong to. Absent, the run id:
286
+ * jobs are stopped when the run ends. A host that wants a job to
287
+ * outlive the turn that started it — a dev server started in one turn
288
+ * and read in the next — passes its session id here and calls
289
+ * `backgroundJobs.killOwner(sessionId)` when the session ends; the run
290
+ * then stops nothing at its end and still tells the model when a job
291
+ * finishes.
292
+ */
293
+ backgroundJobOwner?: string
277
294
 
278
295
  /**
279
296
  * What else goes in this run's prompt.
@@ -469,6 +486,12 @@ export interface QueryParams {
469
486
  agentId: string
470
487
  agentName: string
471
488
  workingDirectory?: string
489
+ /**
490
+ * Directories besides the working directory the file tools may reach,
491
+ * absolute; a sandboxed run binds each read-write. See
492
+ * `ToolContext.additionalDirectories`.
493
+ */
494
+ additionalDirectories?: readonly string[]
472
495
  pricing?: ModelPricing
473
496
  enableActivityTracking?: boolean
474
497
  messages: Message[]
@@ -648,6 +671,13 @@ export interface QueryParams {
648
671
  * started. See `BaseAgentConfig.inboundMessages` for what it closes.
649
672
  */
650
673
  inboundMessages?: () => import('../../types/message/index.js').Message[]
674
+ /**
675
+ * Wake a background-task hold when operator input is available, without draining it.
676
+ * Resolve immediately if input is already pending. Otherwise wait for its arrival;
677
+ * the supplied signal ends the wait and must release any listeners. Messages are
678
+ * still consumed only through `inboundMessages` at a provider-valid boundary.
679
+ */
680
+ waitForInbound?: (signal: AbortSignal) => Promise<void>
651
681
 
652
682
  /**
653
683
  * Live project policy for this run. Unlike `inboundMessages`, snapshot
@@ -715,6 +745,15 @@ export interface QueryParams {
715
745
 
716
746
  compactionConfig?: CompactionConfig
717
747
 
748
+ /**
749
+ * Where what the run learned is written when it ends: its decisions,
750
+ * discoveries and failures, as one entry tagged `learning`. Episodic
751
+ * memory (the working state) dies with the run; this is the bridge to
752
+ * the semantic store a later run searches. Absent means nothing is
753
+ * written. A store that fails is logged and never fails the run.
754
+ */
755
+ consolidateInto?: MemoryStore
756
+
718
757
  /**
719
758
  * Optional neutral working-memory seam. When set, the iteration loop
720
759
  * re-renders the provider's string into a single pinned leading system
@@ -1022,6 +1061,7 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
1022
1061
  // generating it twice would silently hand the log and the run two
1023
1062
  // different ids.
1024
1063
  const runId = params.runId ?? generateRunId()
1064
+ const budget = await resolveQueryBudget(params, runId, selectedResumeState)
1025
1065
  const log = RunContextFactory.buildLogger({
1026
1066
  agentName: params.agentName,
1027
1067
  runConfig,
@@ -1033,44 +1073,6 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
1033
1073
  tenantId: params.tenantId,
1034
1074
  })
1035
1075
 
1036
- // Boot-time filesystem migration (session-hierarchy.md §13.4.1). First
1037
- // call per process per root actually runs; subsequent calls short-circuit
1038
- // via the in-memory guard in `context.ts`. Kept here rather than inside
1039
- // the synchronous `RunContextFactory.build` so the factory signature stays
1040
- // sync for tests / non-async call sites.
1041
- //
1042
- // The migrator built here — not `ensureMigrated`'s own default — is what
1043
- // turns the migration facts `DefaultFilesystemMigrator` already computes
1044
- // into a `namzu.migration.completed` record instead of discarding them.
1045
- // `ensureMigrated`'s default parameter stays
1046
- // `NOOP_FILESYSTEM_MIGRATION_SINK` (see `context.ts`), so any other path
1047
- // that reaches `ensureMigrated` keeps today's silent behaviour.
1048
- const cwdForMigration = params.workingDirectory ?? process.cwd()
1049
- const migrationRoot = params.pathBuilder?.rootDir() ?? join(cwdForMigration, '.namzu')
1050
- const migrationResult = await RunContextFactory.ensureMigrated(
1051
- migrationRoot,
1052
- new DefaultFilesystemMigrator(loggingMigrationSink(log)),
1053
- )
1054
- // `loggingMigrationSink` only ever hears about `kind: 'migrated'` — the
1055
- // only outcome `DefaultFilesystemMigrator` ever hands its sink (see the
1056
- // module doc on `FilesystemMigrationSink`). The other two are logged
1057
- // here, straight off the resolved result, rather than by widening
1058
- // `FilesystemMigrationEvent` to carry them: a wider union would need a
1059
- // new arm in every exhaustive switch already written over it — a major —
1060
- // for two outcomes `migrationResult.kind` already fully describes.
1061
- if (migrationResult.kind !== 'migrated') {
1062
- log.debug('filesystem migration: nothing to do', {
1063
- [EVENT_NAME_ATTRIBUTE]: BOOT_EVENT_NAMES.MIGRATION_COMPLETED,
1064
- // `namzu.migration.*`, matching `loggingMigrationSink` — the OTHER
1065
- // emitter of this same event name. Two emitters of one event writing
1066
- // two namespaces for the same fact is precisely the collision the
1067
- // namespaced-key rule exists to stop, and a per-module derivation is
1068
- // how it would be reintroduced.
1069
- 'namzu.migration.kind': migrationResult.kind,
1070
- 'namzu.migration.marker_path': migrationResult.markerPath,
1071
- })
1072
- }
1073
-
1074
1076
  // Every model call in the run — the loop's turns, the forced-final
1075
1077
  // summary, advisory and compaction side calls — goes through this one
1076
1078
  // wrapped provider, so the retry policy cannot be bypassed by a code
@@ -1102,9 +1104,14 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
1102
1104
  idleTimeoutMs: streamIdleTimeoutMs,
1103
1105
  log,
1104
1106
  })
1107
+ const metered = withTokenBudget(withIdleBound, budget)
1105
1108
  return params.retry === false
1106
- ? withIdleBound
1107
- : withProviderRetry(withIdleBound, { config: params.retry, log })
1109
+ ? metered
1110
+ : withProviderRetry(metered, {
1111
+ config: params.retry,
1112
+ log,
1113
+ canRetry: () => budget.remaining > 0,
1114
+ })
1108
1115
  }
1109
1116
  // Who is serving right now, for the run RECORD rather than for the request.
1110
1117
  //
@@ -1123,6 +1130,7 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
1123
1130
  })),
1124
1131
  {
1125
1132
  log,
1133
+ canFallback: () => budget.remaining > 0,
1126
1134
  onSwap: (to) => {
1127
1135
  serving.current = to
1128
1136
  // `ctx` is declared below and is initialized before anything can
@@ -1278,6 +1286,7 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
1278
1286
  }
1279
1287
 
1280
1288
  const ctx = RunContextFactory.build({
1289
+ budget,
1281
1290
  ...(topicState ? { topicPermissionMode: topicState.permissionMode } : {}),
1282
1291
  ...(params.permissionModeRef ? { permissionModeRef: params.permissionModeRef } : {}),
1283
1292
  agentId: params.agentId,
@@ -1329,13 +1338,19 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
1329
1338
  emit: (event) => eventTranslator.emitEvent(event),
1330
1339
  })
1331
1340
 
1341
+ const planApprovalIds = new Map<PlanId, CheckpointId>()
1332
1342
  ctx.planManager.setApprovalHandler(async (request) => {
1343
+ let checkpointId = planApprovalIds.get(request.planId)
1344
+ if (!checkpointId) {
1345
+ checkpointId = generateCheckpointId()
1346
+ planApprovalIds.set(request.planId, checkpointId)
1347
+ }
1333
1348
  // `.current.handler`, never a captured `params.resumeHandler`. That
1334
1349
  // capture is what made changing the policy mean ending the run.
1335
1350
  const decision = await approvalPolicy.current.handler({
1336
1351
  type: 'plan_approval',
1337
1352
  runId: ctx.runId,
1338
- checkpointId: `cp_plan_${request.planId}` as import('../../types/ids/index.js').CheckpointId,
1353
+ checkpointId,
1339
1354
  plan: {
1340
1355
  planId: request.planId,
1341
1356
  title: request.title,
@@ -1683,6 +1698,9 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
1683
1698
  tools: params.tools,
1684
1699
  runId: ctx.runId,
1685
1700
  workingDirectory: ctx.cwd,
1701
+ ...(params.additionalDirectories?.length
1702
+ ? { additionalDirectories: params.additionalDirectories }
1703
+ : {}),
1686
1704
  permissionMode: () => ctx.permissionMode.current,
1687
1705
  env: runConfig.env ?? {},
1688
1706
  abortSignal: ctx.abortController.signal,
@@ -1690,6 +1708,7 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
1690
1708
  invocationState: params.invocationState,
1691
1709
  pluginManager: params.pluginManager,
1692
1710
  ...(params.backgroundJobs ? { backgroundJobs: params.backgroundJobs } : {}),
1711
+ ...(params.backgroundJobOwner ? { backgroundJobOwner: params.backgroundJobOwner } : {}),
1693
1712
  // The `skill` tool's registry. Threaded from the run rather than
1694
1713
  // held by the tool, because a tool that reached for a module-level
1695
1714
  // registry would answer about whatever the last run configured.
@@ -1734,12 +1753,52 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
1734
1753
  ctx.log,
1735
1754
  )
1736
1755
 
1756
+ // A background job's exit reaches the model as a notice on its next tool
1757
+ // result, and the host as an event — without either polling. Subscribed
1758
+ // for the owner the run's jobs are bound to, so a session-owned job that
1759
+ // ends during this run is reported here too.
1760
+ const jobOwner = params.backgroundJobOwner ?? ctx.runId
1761
+ const jobNotices = params.backgroundJobs ? new SteeringBinding() : undefined
1762
+ const unsubscribeJobExits = params.backgroundJobs?.onExit((job) => {
1763
+ if (job.owner !== jobOwner) return
1764
+ const outcome =
1765
+ job.status === 'killed'
1766
+ ? 'was stopped'
1767
+ : `exited with code ${job.exitCode ?? 'unknown'}${job.signal ? ` (${job.signal})` : ''}`
1768
+ jobNotices?.steer(
1769
+ `Background job ${job.id} (${job.command}) ${outcome}. Read its output with the job tool if you need it.`,
1770
+ )
1771
+ void eventTranslator
1772
+ .emitEvent({
1773
+ type: 'background_job_exited',
1774
+ runId: ctx.runId,
1775
+ jobId: job.id,
1776
+ command: job.command,
1777
+ status: job.status === 'killed' ? 'killed' : 'exited',
1778
+ ...(job.exitCode !== undefined ? { exitCode: job.exitCode } : {}),
1779
+ ...(job.signal ? { signal: job.signal } : {}),
1780
+ })
1781
+ .catch(() => {})
1782
+ })
1737
1783
  let workingStateManager: WorkingStateManager | undefined
1738
- if (params.compactionConfig && params.compactionConfig.strategy !== 'disabled') {
1739
- workingStateManager = new WorkingStateManager(params.compactionConfig)
1784
+ // Normalised once, defaults applied. A host that passes a partial
1785
+ // object a strategy and a window, nothing else — used to reach the
1786
+ // phase with `triggerThreshold` undefined, and `usage < undefined` is
1787
+ // false: the pass ran on every iteration and the salience strategy fell
1788
+ // through to the stale-result clearing it exists to replace. The eval
1789
+ // suite that passed exactly that object found it.
1790
+ const compactionConfig = params.compactionConfig
1791
+ ? CompactionConfigSchema.parse(params.compactionConfig)
1792
+ : undefined
1793
+ if (compactionConfig && compactionConfig.strategy !== 'disabled') {
1794
+ workingStateManager = new WorkingStateManager(compactionConfig)
1740
1795
  toolExecutor.setWorkingStateManager(workingStateManager)
1741
1796
  }
1742
1797
 
1798
+ // The run's own registry when the host passed none, so a hook's
1799
+ // annotation has somewhere to land.
1800
+ const promptContributions = params.promptContributions ?? new PromptContributionRegistry()
1801
+
1743
1802
  const promptBuilder = new PromptBuilder({
1744
1803
  systemPrompt: params.systemPrompt,
1745
1804
  persona: params.persona,
@@ -1748,7 +1807,7 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
1748
1807
  tools: params.tools,
1749
1808
  allowedTools: effectiveAllowedTools,
1750
1809
  runtimeContext: params.runtimeContext,
1751
- ...(params.promptContributions ? { contributions: params.promptContributions } : {}),
1810
+ contributions: promptContributions,
1752
1811
  })
1753
1812
 
1754
1813
  const guard = new GuardCoordinator({
@@ -1800,10 +1859,13 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
1800
1859
  // explicitly chosen provider/cancellation policy.
1801
1860
  const boundedAdvisors = params.advisory.advisors.map((advisor) => ({
1802
1861
  ...advisor,
1803
- provider: withStreamIdleTimeout(advisor.provider, {
1804
- idleTimeoutMs: streamIdleTimeoutMs,
1805
- log: ctx.log,
1806
- }),
1862
+ provider: withTokenBudget(
1863
+ withStreamIdleTimeout(advisor.provider, {
1864
+ idleTimeoutMs: streamIdleTimeoutMs,
1865
+ log: ctx.log,
1866
+ }),
1867
+ budget,
1868
+ ),
1807
1869
  }))
1808
1870
  const advisorRegistry = new AdvisorRegistry(boundedAdvisors, params.advisory.defaultAdvisorId)
1809
1871
  // A budget the runtime cannot measure is refused here rather than
@@ -1891,8 +1953,9 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
1891
1953
  // question rather than the next run.
1892
1954
  resumeHandler: (request) => approvalPolicy.current.handler(request),
1893
1955
  takeApprovalPolicyChange: () => approvalPolicy.takeUnannouncedChange(),
1894
- ...(params.promptContributions ? { promptContributions: params.promptContributions } : {}),
1956
+ promptContributions,
1895
1957
  ...(params.steering ? { steering: params.steering } : {}),
1958
+ ...(jobNotices ? { jobNotices } : {}),
1896
1959
  checkpointMgr,
1897
1960
  planManager: ctx.planManager,
1898
1961
  taskGateway: taskScheduler,
@@ -1905,8 +1968,9 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
1905
1968
  // run is a claim about work nobody repeated, and a module-level map
1906
1969
  // would leak exactly that way.
1907
1970
  ...(params.repeatCallAdvisory === false ? {} : { repeatCalls: new RepeatCallTracker() }),
1908
- compactionConfig: params.compactionConfig,
1971
+ compactionConfig,
1909
1972
  ...(params.inboundMessages ? { inboundMessages: params.inboundMessages } : {}),
1973
+ ...(params.waitForInbound ? { waitForInbound: params.waitForInbound } : {}),
1910
1974
  ...(params.projectInstructionContext
1911
1975
  ? { projectInstructionContext: params.projectInstructionContext }
1912
1976
  : {}),
@@ -2069,6 +2133,32 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
2069
2133
  'namzu.runtime.resume_from_checkpoint': params.resumeFromCheckpoint ?? null,
2070
2134
  })
2071
2135
 
2136
+ // The operator's prompt, before the model sees it. A hook may
2137
+ // refuse it — the run ends here, before a prompt is built — or add
2138
+ // to what the model is told; the addition rides the prompt as a
2139
+ // dynamic contribution so every iteration of the run carries it.
2140
+ if (params.pluginManager) {
2141
+ const hookResults = await params.pluginManager.executeHooks(
2142
+ 'user_prompt_submit',
2143
+ {
2144
+ runId: ctx.runId,
2145
+ sessionId: params.sessionId,
2146
+ prompt: lastUserPrompt(initialMessages),
2147
+ signal: ctx.abortController.signal,
2148
+ },
2149
+ eventTranslator.emitEvent,
2150
+ )
2151
+ const annotations = applyLifecycleHookResults('user_prompt_submit', hookResults)
2152
+ if (annotations.length > 0) {
2153
+ promptContributions.replace({
2154
+ id: 'hooks:user_prompt_submit',
2155
+ placement: 'dynamic',
2156
+ render: () => `Context from the operator's hooks:\n\n${annotations.join('\n\n')}`,
2157
+ })
2158
+ }
2159
+ yield* eventTranslator.drainPending()
2160
+ }
2161
+
2072
2162
  const contextLevel = params.contextLevel ?? 'full'
2073
2163
  const cacheInput = {
2074
2164
  systemPrompt: params.systemPrompt,
@@ -2078,7 +2168,7 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
2078
2168
  tools: params.tools,
2079
2169
  allowedTools: effectiveAllowedTools,
2080
2170
  runtimeContext: params.runtimeContext,
2081
- ...(params.promptContributions ? { contributions: params.promptContributions } : {}),
2171
+ contributions: promptContributions,
2082
2172
  }
2083
2173
 
2084
2174
  const segments: PromptSegments = promptCache
@@ -2132,8 +2222,8 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
2132
2222
  // would drop it and replace it with a summary covering only
2133
2223
  // what happened after the resume, silently losing the run's
2134
2224
  // first hour.
2135
- if (workingStateManager && checkpoint.workingState && params.compactionConfig) {
2136
- const revived = restoreWorkingState(checkpoint.workingState, params.compactionConfig)
2225
+ if (workingStateManager && checkpoint.workingState && compactionConfig) {
2226
+ const revived = restoreWorkingState(checkpoint.workingState, compactionConfig)
2137
2227
  workingStateManager.replaceState(revived.getState())
2138
2228
  ctx.log.info('Restored compaction working state from checkpoint', {
2139
2229
  [NAMZU.RUN_ID]: ctx.runMgr.id,
@@ -2412,6 +2502,9 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
2412
2502
  provider: params.sandboxProvider,
2413
2503
  config: {
2414
2504
  ...(rootAtCwd ? { workingDirectory: ctx.cwd } : {}),
2505
+ ...(rootAtCwd && params.additionalDirectories?.length
2506
+ ? { additionalDirectories: params.additionalDirectories }
2507
+ : {}),
2415
2508
  timeoutMs: runConfig.sandbox?.timeoutMs,
2416
2509
  memoryLimitMb: runConfig.sandbox?.memoryLimitMb,
2417
2510
  maxProcesses: runConfig.sandbox?.maxProcesses,
@@ -2580,6 +2673,22 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
2580
2673
  )
2581
2674
  applyLifecycleHookResults('run_end', hookResults)
2582
2675
  yield* eventTranslator.drainPending()
2676
+ // A delegated run says so once more, by name, so a hook that
2677
+ // only cares when a subagent finishes need not read parent ids
2678
+ // off every run_end.
2679
+ if (params.parentRunId !== undefined) {
2680
+ const stopResults = await params.pluginManager.executeHooks(
2681
+ 'subagent_stop',
2682
+ {
2683
+ runId: ctx.runId,
2684
+ parentRunId: params.parentRunId,
2685
+ signal: ctx.abortController.signal,
2686
+ },
2687
+ eventTranslator.emitEvent,
2688
+ )
2689
+ applyLifecycleHookResults('subagent_stop', stopResults)
2690
+ yield* eventTranslator.drainPending()
2691
+ }
2583
2692
  }
2584
2693
 
2585
2694
  // Hand the step record to the run before it settles, so the
@@ -2638,6 +2747,32 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
2638
2747
  }
2639
2748
  }
2640
2749
 
2750
+ if (params.consolidateInto && workingStateManager) {
2751
+ const entry = consolidationEntry(workingStateManager.getState(), {
2752
+ runId: ctx.runId,
2753
+ at: Date.now(),
2754
+ })
2755
+ if (entry) {
2756
+ try {
2757
+ const { entry: saved } = await params.consolidateInto.create(entry)
2758
+ await eventTranslator.emitEvent({
2759
+ type: 'memory_consolidated',
2760
+ runId: ctx.runId,
2761
+ memoryId: saved.id,
2762
+ title: entry.title,
2763
+ decisions: workingStateManager.getState().decisions.length,
2764
+ discoveries: workingStateManager.getState().discoveries.length,
2765
+ failures: workingStateManager.getState().failures.length,
2766
+ })
2767
+ yield* eventTranslator.drainPending()
2768
+ } catch (error) {
2769
+ ctx.log.warn('consolidation into the memory store failed', {
2770
+ [NAMZU.RUN_ID]: ctx.runId,
2771
+ 'namzu.memory.error': toErrorMessage(error),
2772
+ })
2773
+ }
2774
+ }
2775
+ }
2641
2776
  yield* resultAssembler.completeRun(rootSpan)
2642
2777
  } catch (err) {
2643
2778
  // A failed run still spent its steps; report them.
@@ -2659,7 +2794,10 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
2659
2794
  //
2660
2795
  // Awaited, and its failure swallowed. A job that would not die is
2661
2796
  // worth a log line, and is not worth retracting a run's answer.
2662
- if (params.backgroundJobs) {
2797
+ unsubscribeJobExits?.()
2798
+ // Only jobs bound to this run. Jobs a host bound to its session are
2799
+ // the host's to stop, when the session ends.
2800
+ if (params.backgroundJobs && (params.backgroundJobOwner ?? ctx.runId) === ctx.runId) {
2663
2801
  try {
2664
2802
  const stopped = await params.backgroundJobs.killOwner(ctx.runId)
2665
2803
  if (stopped.length > 0) {
@@ -2743,6 +2881,15 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
2743
2881
  * either way — a stale cursor belongs to the client, and must not be able to
2744
2882
  * stop the work.
2745
2883
  */
2884
+ /** The text of the newest user turn, which is what a prompt hook is asked about. */
2885
+ function lastUserPrompt(messages: readonly Message[]): string {
2886
+ for (let i = messages.length - 1; i >= 0; i--) {
2887
+ const m = messages[i]
2888
+ if (m?.role === 'user' && typeof m.content === 'string') return m.content
2889
+ }
2890
+ return ''
2891
+ }
2892
+
2746
2893
  async function* catchUpFromCursor(
2747
2894
  runMgr: RunPersistence,
2748
2895
  cursor: RunEventCursor,
@@ -312,8 +312,9 @@ export class IterationOrchestrator {
312
312
  'namzu.runtime.input_tokens': runMgr.tokenUsage.promptTokens,
313
313
  'namzu.runtime.output_tokens': runMgr.tokenUsage.completionTokens,
314
314
  })
315
- await this.requestFinalResponse(model, stopReason)
316
- yield* this.ctx.drainPending()
315
+ // A hard stop has no budget left for another model request.
316
+ // Closing prose is requested at the warning threshold while
317
+ // headroom remains; the completed work is already in history.
317
318
  runMgr.setStopReason(stopReason)
318
319
  break
319
320
  }
@@ -788,6 +789,7 @@ export class IterationOrchestrator {
788
789
  type: 'token_usage_updated',
789
790
  runId: runMgr.id,
790
791
  usage: runMgr.tokenUsage,
792
+ budget: runMgr.budget?.summary(),
791
793
  cost: runMgr.costInfo,
792
794
  ...contextFigures,
793
795
  })
@@ -1079,12 +1081,13 @@ export class IterationOrchestrator {
1079
1081
  continue
1080
1082
  }
1081
1083
 
1084
+ let closingStopReason: StopReason | undefined
1082
1085
  if (!hasContent && !forceFinalize) {
1083
1086
  this.ctx.log.warn('Empty completion detected — requesting final summary', {
1084
1087
  [NAMZU.ITERATION]: iterationNum,
1085
1088
  'namzu.runtime.finish_reason': response.finishReason,
1086
1089
  })
1087
- await this.requestFinalResponse(model, 'end_turn')
1090
+ closingStopReason = await this.requestFinalResponse(model, 'end_turn')
1088
1091
  yield* this.ctx.drainPending()
1089
1092
  }
1090
1093
 
@@ -1115,7 +1118,10 @@ export class IterationOrchestrator {
1115
1118
  // also settle as `end_turn`, and there the deferred predicate
1116
1119
  // is not why the run ended: those decided the answer
1117
1120
  // themselves.
1118
- runMgr.setStopReason(stopWasDeferredForOutstandingWork ? 'stop_condition' : 'end_turn')
1121
+ runMgr.setStopReason(
1122
+ closingStopReason ??
1123
+ (stopWasDeferredForOutstandingWork ? 'stop_condition' : 'end_turn'),
1124
+ )
1119
1125
  break
1120
1126
  }
1121
1127
 
@@ -1444,9 +1450,9 @@ export class IterationOrchestrator {
1444
1450
  /**
1445
1451
  * Hold the run open for a worker that has not finished, and deliver it.
1446
1452
  *
1447
- * Returns whether a completion arrived and was put in the transcript — the
1448
- * caller continues the loop on `true`, so the model gets a turn in which to
1449
- * USE the result. That turn is the entire justification for waiting, which
1453
+ * Returns whether a completion or operator message entered the transcript —
1454
+ * the caller continues on `true`, so the model gets a turn to respond.
1455
+ * That turn is the entire justification for waiting, which
1450
1456
  * is why only the exits that can still take one call this.
1451
1457
  *
1452
1458
  * Bounded by `settleGraceMs` and by `maxIterations`, so a worker that never
@@ -1467,14 +1473,34 @@ export class IterationOrchestrator {
1467
1473
  [NAMZU.ITERATION]: iterationNum,
1468
1474
  'namzu.runtime.grace_ms': graceMs,
1469
1475
  })
1470
- await this.ctx.completionInbox.waitForArrival(graceMs)
1476
+ // User input releases this wait without cancelling any child. Both waits
1477
+ // share a disposable signal so the losing arrival listener cannot leak.
1478
+ const waiting = new AbortController()
1479
+ const runSignal = this.ctx.abortController.signal
1480
+ const cancelWait = () => waiting.abort(runSignal.reason)
1481
+ runSignal.addEventListener('abort', cancelWait, { once: true })
1482
+ if (runSignal.aborted) cancelWait()
1483
+ try {
1484
+ await Promise.race([
1485
+ this.ctx.completionInbox.waitForArrival(graceMs, waiting.signal),
1486
+ ...(this.ctx.waitForInbound ? [this.ctx.waitForInbound(waiting.signal)] : []),
1487
+ ])
1488
+ } catch (error) {
1489
+ if (!runSignal.aborted) throw error
1490
+ } finally {
1491
+ waiting.abort()
1492
+ runSignal.removeEventListener('abort', cancelWait)
1493
+ }
1494
+ runSignal.throwIfAborted()
1471
1495
 
1472
1496
  const arrived = this.ctx.completionInbox.drain()
1473
- if (arrived.length === 0) return false
1474
-
1475
- this.ctx.runMgr.pushMessage(
1476
- createRuntimeContextMessage(formatCompletionNotification(arrived), 'task-completion'),
1477
- )
1497
+ if (arrived.length > 0) {
1498
+ this.ctx.runMgr.pushMessage(
1499
+ createRuntimeContextMessage(formatCompletionNotification(arrived), 'task-completion'),
1500
+ )
1501
+ }
1502
+ const inbound = this.deliverInbound()
1503
+ if (arrived.length === 0 && inbound === 0) return false
1478
1504
  await this.ctx.emitEvent({
1479
1505
  type: 'iteration_completed',
1480
1506
  runId: this.ctx.runMgr.id,
@@ -2029,7 +2055,10 @@ export class IterationOrchestrator {
2029
2055
  })
2030
2056
  }
2031
2057
 
2032
- private async requestFinalResponse(model: string, reason: StopReason): Promise<void> {
2058
+ private async requestFinalResponse(
2059
+ model: string,
2060
+ reason: StopReason,
2061
+ ): Promise<StopReason | undefined> {
2033
2062
  const lastAssistant = [...this.ctx.runMgr.messages]
2034
2063
  .reverse()
2035
2064
  .find((m) => m.role === 'assistant')
@@ -2040,8 +2069,16 @@ export class IterationOrchestrator {
2040
2069
  lastAssistant.content.length > 0
2041
2070
 
2042
2071
  if (hasResult) return
2072
+ // An empty completion may itself have exhausted the run. This fallback
2073
+ // is another billed request, so it must pass the same hard limits as
2074
+ // the next normal iteration and preserve their unfinished stop reason.
2075
+ const guardResult = this.ctx.guard.beforeIteration(
2076
+ this.ctx.runMgr,
2077
+ this.ctx.abortController.signal,
2078
+ )
2079
+ if (guardResult.shouldStop) return guardResult.stopReason
2043
2080
 
2044
- this.ctx.log.info('Requesting final response before limit enforcement', {
2081
+ this.ctx.log.info('Requesting final response after empty completion', {
2045
2082
  'namzu.runtime.reason': reason,
2046
2083
  })
2047
2084
 
@@ -2145,6 +2182,7 @@ export class IterationOrchestrator {
2145
2182
  'exception.message': toErrorMessage(err),
2146
2183
  })
2147
2184
  }
2185
+ return undefined
2148
2186
  }
2149
2187
  }
2150
2188