@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
@@ -3,7 +3,7 @@ import { z } from 'zod'
3
3
  import type { CodeNavigationProvider } from '../../types/code-navigation/index.js'
4
4
  import type { ToolResult } from '../../types/tool/index.js'
5
5
  import { defineTool } from '../defineTool.js'
6
- import { resolveWithinReal } from '../paths.js'
6
+ import { resolveWithinAnyReal, toolRoots } from '../paths.js'
7
7
 
8
8
  /**
9
9
  * Symbol navigation, for the questions `grep` answers wrongly.
@@ -97,7 +97,7 @@ export const LspTool = defineTool({
97
97
  let absolute: string | undefined
98
98
  if (input.path !== undefined) {
99
99
  try {
100
- absolute = await resolveWithinReal(context.workingDirectory, input.path)
100
+ absolute = await resolveWithinAnyReal(toolRoots(context), input.path)
101
101
  } catch (err) {
102
102
  return {
103
103
  success: false,
@@ -2,7 +2,7 @@ import { readFile } from 'node:fs/promises'
2
2
  import { extname } from 'node:path'
3
3
  import { z } from 'zod'
4
4
  import { defineTool } from '../defineTool.js'
5
- import { resolveWithinReal } from '../paths.js'
5
+ import { resolveWithinAnyReal, toolRoots } from '../paths.js'
6
6
 
7
7
  const inputSchema = z.object({
8
8
  path: z.string().describe('Path to the file to read (absolute or relative)'),
@@ -75,7 +75,7 @@ export const ReadFileTool = defineTool({
75
75
  }
76
76
  }
77
77
 
78
- const filePath = await resolveWithinReal(context.workingDirectory, input.path)
78
+ const filePath = await resolveWithinAnyReal(toolRoots(context), input.path)
79
79
  const buffer = await readFile(filePath)
80
80
  const binaryGuidance = describeStructuredBinaryRead(filePath, buffer)
81
81
  if (binaryGuidance) {
@@ -3,7 +3,7 @@ import { dirname } from 'node:path'
3
3
  import { z } from 'zod'
4
4
  import type { ToolContext, ToolResult } from '../../types/tool/index.js'
5
5
  import { defineTool } from '../defineTool.js'
6
- import { resolveWithinReal } from '../paths.js'
6
+ import { resolveWithinAnyReal, toolRoots } from '../paths.js'
7
7
  import { atomicWriteFile } from './atomic-write-file.js'
8
8
  import { fingerprintContent, staleFileError } from './content-fingerprint.js'
9
9
  import { withFileMutationLock } from './file-mutation-lock.js'
@@ -137,7 +137,7 @@ export const WriteFileTool = defineTool({
137
137
  // machine and answers it with whatever happens to exist there.
138
138
  const filePath = context.sandbox
139
139
  ? undefined
140
- : await resolveWithinReal(context.workingDirectory, valid.path)
140
+ : await resolveWithinAnyReal(toolRoots(context), valid.path)
141
141
  // The exists-check and the write are a check-then-act pair. Unlocked,
142
142
  // two writers both see "absent", both skip the read-before-overwrite
143
143
  // guard, and the second silently discards the first.
@@ -0,0 +1,284 @@
1
+ /**
2
+ * The one tool that turns a run around to face the human.
3
+ *
4
+ * It used to be built inside `buildCoordinatorTools`, which needs a gateway,
5
+ * a scheduler and a roster the question has no use for — so a host that
6
+ * wanted only this tool (an interactive terminal with no delegation) had to
7
+ * assemble the whole coordinator set and fish the question out of it, and
8
+ * had to invent a run id at build time because the builder demanded one.
9
+ * This builder needs the park handler and nothing else; the run id is read
10
+ * from the calling `ToolContext` unless the host pins one.
11
+ */
12
+
13
+ import { z } from 'zod'
14
+ import type { PendingAnswers, QuestionParkRecorder } from '../../runtime/query/question-park.js'
15
+ import type { ResumeHandler, UserQuestionOption } from '../../types/hitl/index.js'
16
+ import type { RunId } from '../../types/ids/index.js'
17
+ import type { ToolDefinition } from '../../types/tool/index.js'
18
+ import { generateCheckpointId } from '../../utils/id.js'
19
+ import { defineTool } from '../defineTool.js'
20
+
21
+ /** Internal identity shared by the builder and the agent authority boundary. */
22
+ export const ASK_USER_QUESTION_TOOL_NAME = 'ask_user_question' as const
23
+
24
+ /**
25
+ * The single closed shape a capable provider constrains this call to.
26
+ *
27
+ * `options` arriving as a STRING is the failure this exists for: a model that
28
+ * serializes the array once tends to keep doing it, and the parse error it
29
+ * gets back never says the array was the problem.
30
+ * `additionalProperties: false` turns that into a refusal at generation time
31
+ * rather than a rejection after the fact.
32
+ */
33
+ const askUserQuestionModelInputSchema: Record<string, unknown> = {
34
+ type: 'object',
35
+ properties: {
36
+ question: {
37
+ type: 'string',
38
+ description: 'Full question text — clear, specific, and ending with a question mark.',
39
+ },
40
+ header: {
41
+ type: 'string',
42
+ description: 'Optional very short topic label, no more than 24 characters.',
43
+ },
44
+ options: {
45
+ type: 'array',
46
+ description: 'A JSON array of 2-4 genuinely distinct, context-derived option objects.',
47
+ items: {
48
+ type: 'object',
49
+ properties: {
50
+ label: {
51
+ type: 'string',
52
+ description:
53
+ 'Concise option label. Put the recommended option first and append " (Recommended)".',
54
+ },
55
+ description: {
56
+ type: 'string',
57
+ description: 'Optional one-line explanation of what changes if selected.',
58
+ },
59
+ },
60
+ required: ['label'],
61
+ additionalProperties: false,
62
+ },
63
+ },
64
+ multiSelect: {
65
+ type: 'boolean',
66
+ description: 'True only when several options can apply at once.',
67
+ },
68
+ allowFreeText: {
69
+ type: 'boolean',
70
+ description: 'Whether the user may answer in their own words.',
71
+ },
72
+ },
73
+ required: ['question', 'options'],
74
+ additionalProperties: false,
75
+ }
76
+
77
+ export interface AskUserQuestionToolOptions {
78
+ /** Where the question goes; the run parks on it until an answer comes back. */
79
+ resumeHandler: ResumeHandler
80
+ /**
81
+ * The run the park is recorded against. Omit it and the tool uses the
82
+ * `runId` of the call that asked, which is the right run in every case
83
+ * but a host that answers questions for a run other than the one it drives.
84
+ */
85
+ runId?: RunId
86
+ /** See the same field on `CoordinatorToolsOptions`. */
87
+ questionParks?: QuestionParkRecorder
88
+ /** See the same field on `CoordinatorToolsOptions`. */
89
+ pendingAnswers?: PendingAnswers
90
+ }
91
+
92
+ export function buildAskUserQuestionTool(config: AskUserQuestionToolOptions): ToolDefinition {
93
+ const parkHandler = config.resumeHandler
94
+ const { questionParks, pendingAnswers } = config
95
+ return defineTool({
96
+ name: ASK_USER_QUESTION_TOOL_NAME,
97
+ description:
98
+ 'Ask the user ONE question ONLY when you are blocked on a decision that is genuinely theirs to make — one you cannot resolve from their request, your tools, the files you can read, or sensible defaults. The question must be the genuinely undecidable thing in THIS task. Never ask for information a tool can discover (do not ask what you can read, list, or search), never re-ask what the conversation already answers, and never ask meta-questions like "Shall I proceed?" — plan ratification goes through approve_plan. Provide 2-4 genuinely distinct options derived from the actual context — concrete paths, never generic placeholders (for example, asked to prepare a presentation, ask "Who is the audience?" with options like Board / Engineering team / Customer); keep labels short (1-5 words) and give each option a one-line description of what practically changes if it is chosen. Put your recommended option FIRST and append " (Recommended)" to its label. Set multiSelect: true only when several options can apply at once. A free-text "Something else" escape hatch is always shown automatically — do not add your own "Other" option. Ask ONE question per call and prefer at most one question per assistant turn; if several decisions block you, ask only the ones that materially change your next actions, in sequence — most work needs at most 2-3 questions, so prefer proceeding on stated defaults over interrogating the user. Never invent answers or synthetic content on the user\'s behalf unless they explicitly asked for a random/test scenario. The answer arrives as this tool\'s result; if the result says the user did not answer, do not ask this or any other question again — proceed on your best judgment without assuming consent.',
99
+ inputSchema: z
100
+ .object({
101
+ question: z
102
+ .string()
103
+ .min(1)
104
+ .describe('Full question text — clear, specific, ends with a question mark.'),
105
+ header: z
106
+ .string()
107
+ .max(24)
108
+ .optional()
109
+ .describe('Very short topic label for the question (e.g. "Audience", "Auth method").'),
110
+ options: z
111
+ .array(
112
+ z
113
+ .object({
114
+ label: z
115
+ .string()
116
+ .min(1)
117
+ .max(80)
118
+ .describe(
119
+ 'Concise option label (1-5 words). Recommended option goes first with " (Recommended)" appended.',
120
+ ),
121
+ description: z
122
+ .string()
123
+ .max(300)
124
+ .optional()
125
+ .describe('One line on what practically changes if this option is chosen.'),
126
+ })
127
+ .strict(),
128
+ )
129
+ .min(2)
130
+ .max(4)
131
+ .describe('2-4 genuinely distinct, context-derived options.'),
132
+ multiSelect: z
133
+ .boolean()
134
+ .optional()
135
+ .default(false)
136
+ .describe('True only when several options can apply at once.'),
137
+ allowFreeText: z
138
+ .boolean()
139
+ .optional()
140
+ .default(true)
141
+ .describe('Whether the user may answer in their own words.'),
142
+ })
143
+ .strict(),
144
+ modelInputSchema: structuredClone(askUserQuestionModelInputSchema),
145
+ enforceModelInput: true,
146
+ validationErrorHint:
147
+ 'Required shape: {"question":"...?","options":[{"label":"First (Recommended)","description":"What changes"},{"label":"Second","description":"What changes"}]}. "options" must be a JSON array of 2-4 objects, never a string.',
148
+ category: 'custom',
149
+ permissions: [],
150
+ readOnly: true,
151
+ destructive: false,
152
+ // MUST stay false: the executor serializes non-concurrency-safe
153
+ // tools in a single chain, so N question blocks in one assistant
154
+ // turn park strictly one-at-a-time. Hosts key their park/resolve
155
+ // registries by runId — concurrent parks on one run clobber each
156
+ // other and the first promise never resolves (run hangs to TTL).
157
+ concurrencySafe: false,
158
+ async execute({ question, header, options, multiSelect, allowFreeText }, context) {
159
+ const toolUseId = context.toolUseId
160
+ if (!toolUseId) {
161
+ // Without the executing tool_use_id the question has no
162
+ // stable identity: the host could never merge the awaiting
163
+ // card with its resolution, and answers could not be matched
164
+ // back. Hard-fail instead of parking an unmergeable id.
165
+ return {
166
+ success: false,
167
+ output: '',
168
+ error:
169
+ 'ask_user_question requires an executor that threads ToolContext.toolUseId; the question cannot be tracked without it.',
170
+ }
171
+ }
172
+
173
+ const questionOptions: UserQuestionOption[] = options.map((opt, i) => ({
174
+ id: `opt_${i + 1}`,
175
+ label: opt.label,
176
+ ...(opt.description !== undefined ? { description: opt.description } : {}),
177
+ }))
178
+
179
+ const questionData = {
180
+ questionId: toolUseId,
181
+ question,
182
+ ...(header !== undefined ? { header } : {}),
183
+ options: questionOptions,
184
+ multiSelect,
185
+ allowFreeText,
186
+ }
187
+
188
+ // An answer carried in from a resumed run. Checked before the
189
+ // park, because re-entering this tool is HOW the answer gets
190
+ // delivered: the batch is re-executed, and without this the
191
+ // re-execution would ask the user something they already
192
+ // answered — or, headless, auto-answer with the no-consent
193
+ // sentinel and throw the real answer away.
194
+ const carried = pendingAnswers?.take(toolUseId)
195
+
196
+ // A real checkpoint, not a synthetic id nothing ever wrote.
197
+ // Skipped when an answer is already in hand: parking a
198
+ // question that is answered would leave an outstanding record
199
+ // for a decision that has been made.
200
+ const parkedAt =
201
+ carried === undefined && questionParks ? await questionParks.record(questionData) : null
202
+
203
+ const decision =
204
+ carried ??
205
+ (await parkHandler({
206
+ type: 'user_question',
207
+ runId: config.runId ?? context.runId,
208
+ // Provider correlation ids remain verbatim in questionData;
209
+ // an unpersisted park gets its own safe checkpoint identifier.
210
+ checkpointId: parkedAt ?? generateCheckpointId(),
211
+ question: questionData,
212
+ }))
213
+
214
+ // Clear the park once the answer is in, so an approval queue
215
+ // stops serving a question that has been answered.
216
+ if (parkedAt !== null && questionParks) {
217
+ await questionParks.resolve(parkedAt, decision)
218
+ }
219
+
220
+ // The no-answer sentinel (explicitly NOT consent — fixes the
221
+ // "empty answer reads as approval" ambiguity): used for empty
222
+ // answers, misdirected legacy decisions (e.g. a stale replica
223
+ // resolving with approve/continue verbs), and answers that
224
+ // carry a different question's id.
225
+ const noAnswer = {
226
+ success: true,
227
+ output:
228
+ 'The user did not answer this question. Do not assume a choice or consent; proceed on your best judgment or continue without this information.',
229
+ data: { question, answered: false },
230
+ }
231
+
232
+ if (decision.action === 'abort') {
233
+ return {
234
+ success: false,
235
+ output:
236
+ 'The user declined to answer and asked to stop. Acknowledge briefly and end your turn.',
237
+ data: { question, answered: false, declined: true },
238
+ }
239
+ }
240
+
241
+ if (decision.action !== 'answer_question') return noAnswer
242
+ if (decision.questionId !== undefined && decision.questionId !== toolUseId) {
243
+ // Misdirection guard: this answer was meant for a different
244
+ // question parked under the same run (stale client). Never
245
+ // fabricate a selection against the wrong question.
246
+ return noAnswer
247
+ }
248
+
249
+ const stripRecommended = (label: string) =>
250
+ label.replace(/\s*\(recommended\)\s*$/i, '').trim()
251
+
252
+ const selected = decision.selectedOptionIds
253
+ .map((id) => questionOptions.find((opt) => opt.id === id))
254
+ .filter((opt): opt is UserQuestionOption => opt !== undefined)
255
+ .map((opt) => ({ id: opt.id, label: stripRecommended(opt.label) }))
256
+
257
+ const freeText = decision.freeText?.trim() ?? ''
258
+
259
+ if (selected.length === 0 && !freeText) return noAnswer
260
+
261
+ let output: string
262
+ if (selected.length > 0) {
263
+ const joined = selected.map((s) => `"${s.label}"`).join(', ')
264
+ output = `User answered "${question}": ${joined}`
265
+ if (freeText) {
266
+ output += `\nAdditional note from the user: "${freeText}"`
267
+ }
268
+ } else {
269
+ output = `User answered "${question}" in their own words: "${freeText}"`
270
+ }
271
+
272
+ return {
273
+ success: true,
274
+ output,
275
+ data: {
276
+ question,
277
+ selected,
278
+ ...(freeText ? { freeText } : {}),
279
+ answered: true,
280
+ },
281
+ }
282
+ },
283
+ })
284
+ }
@@ -4,15 +4,17 @@ import type { PendingAnswers, QuestionParkRecorder } from '../../runtime/query/q
4
4
  import type { CompletionInbox } from '../../scheduler/completion-inbox.js'
5
5
  import type { AgentRuntimeContext } from '../../types/agent/base.js'
6
6
  import type { TaskScheduler } from '../../types/agent/scheduler.js'
7
- import type { ResumeHandler, UserQuestionOption } from '../../types/hitl/index.js'
7
+ import type { ResumeHandler } from '../../types/hitl/index.js'
8
8
  import type { RunId, TaskId } from '../../types/ids/index.js'
9
9
  import type { TaskStore } from '../../types/task/index.js'
10
10
  import type { ToolDefinition } from '../../types/tool/index.js'
11
11
  import { toErrorMessage } from '../../utils/error.js'
12
- import { asCheckpointId, asTaskId } from '../../utils/id.js'
12
+ import { asTaskId } from '../../utils/id.js'
13
13
  import { defineTool } from '../defineTool.js'
14
14
  import { wrapUntrusted } from '../untrusted-envelope.js'
15
+ import { buildAskUserQuestionTool } from './ask-user-question.js'
15
16
  import { failureLabel, taskSucceeded } from './outcome.js'
17
+ export { ASK_USER_QUESTION_TOOL_NAME } from './ask-user-question.js'
16
18
  import { resolvePlanDependencies } from './plan-dependencies.js'
17
19
  import { describeWaitTimeout, waitForTaskWithBounds } from './wait-with-idle-bound.js'
18
20
 
@@ -107,9 +109,6 @@ export interface CoordinatorToolsOptions {
107
109
  pendingAnswers?: PendingAnswers
108
110
  }
109
111
 
110
- /** Internal identity shared by the builder and the agent authority boundary. */
111
- export const ASK_USER_QUESTION_TOOL_NAME = 'ask_user_question' as const
112
-
113
112
  const approvePlanStepSchema = z.object({
114
113
  description: z.string().describe('What this step does'),
115
114
  agent_id: z
@@ -119,59 +118,6 @@ const approvePlanStepSchema = z.object({
119
118
  depends_on: z.array(z.string()).optional().describe('Step descriptions this depends on'),
120
119
  })
121
120
 
122
- /**
123
- * The single closed shape a capable provider constrains this call to.
124
- *
125
- * `options` arriving as a STRING is the failure this exists for: a model that
126
- * serializes the array once tends to keep doing it, and the parse error it
127
- * gets back never says the array was the problem.
128
- * `additionalProperties: false` turns that into a refusal at generation time
129
- * rather than a rejection after the fact.
130
- */
131
- const askUserQuestionModelInputSchema: Record<string, unknown> = {
132
- type: 'object',
133
- properties: {
134
- question: {
135
- type: 'string',
136
- description: 'Full question text — clear, specific, and ending with a question mark.',
137
- },
138
- header: {
139
- type: 'string',
140
- description: 'Optional very short topic label, no more than 24 characters.',
141
- },
142
- options: {
143
- type: 'array',
144
- description: 'A JSON array of 2-4 genuinely distinct, context-derived option objects.',
145
- items: {
146
- type: 'object',
147
- properties: {
148
- label: {
149
- type: 'string',
150
- description:
151
- 'Concise option label. Put the recommended option first and append " (Recommended)".',
152
- },
153
- description: {
154
- type: 'string',
155
- description: 'Optional one-line explanation of what changes if selected.',
156
- },
157
- },
158
- required: ['label'],
159
- additionalProperties: false,
160
- },
161
- },
162
- multiSelect: {
163
- type: 'boolean',
164
- description: 'True only when several options can apply at once.',
165
- },
166
- allowFreeText: {
167
- type: 'boolean',
168
- description: 'Whether the user may answer in their own words.',
169
- },
170
- },
171
- required: ['question', 'options'],
172
- additionalProperties: false,
173
- }
174
-
175
121
  /** One well-formed tag token: `<step>`, `</step>`, `<a href="…">`, `<br/>`. */
176
122
  const TAG_TOKEN = /<\/?[A-Za-z][\w-]*(?:\s[^<>]*)?\/?>/g
177
123
  const DESCRIPTION_BLOCK = /<description>([\s\S]*?)<\/description>/gi
@@ -1472,196 +1418,7 @@ export function buildCoordinatorTools(opts: CoordinatorToolsOptions): ToolDefini
1472
1418
  }
1473
1419
 
1474
1420
  if (resumeHandler && runId) {
1475
- const parkRunId = runId
1476
- const parkHandler = resumeHandler
1477
- const askUserQuestion = defineTool({
1478
- name: ASK_USER_QUESTION_TOOL_NAME,
1479
- description:
1480
- 'Ask the user ONE question ONLY when you are blocked on a decision that is genuinely theirs to make — one you cannot resolve from their request, your tools, the files you can read, or sensible defaults. The question must be the genuinely undecidable thing in THIS task. Never ask for information a tool can discover (do not ask what you can read, list, or search), never re-ask what the conversation already answers, and never ask meta-questions like "Shall I proceed?" — plan ratification goes through approve_plan. Provide 2-4 genuinely distinct options derived from the actual context — concrete paths, never generic placeholders (for example, asked to prepare a presentation, ask "Who is the audience?" with options like Board / Engineering team / Customer); keep labels short (1-5 words) and give each option a one-line description of what practically changes if it is chosen. Put your recommended option FIRST and append " (Recommended)" to its label. Set multiSelect: true only when several options can apply at once. A free-text "Something else" escape hatch is always shown automatically — do not add your own "Other" option. Ask ONE question per call and prefer at most one question per assistant turn; if several decisions block you, ask only the ones that materially change your next actions, in sequence — most work needs at most 2-3 questions, so prefer proceeding on stated defaults over interrogating the user. Never invent answers or synthetic content on the user\'s behalf unless they explicitly asked for a random/test scenario. The answer arrives as this tool\'s result; if the result says the user did not answer, do not ask this or any other question again — proceed on your best judgment without assuming consent.',
1481
- inputSchema: z
1482
- .object({
1483
- question: z
1484
- .string()
1485
- .min(1)
1486
- .describe('Full question text — clear, specific, ends with a question mark.'),
1487
- header: z
1488
- .string()
1489
- .max(24)
1490
- .optional()
1491
- .describe('Very short topic label for the question (e.g. "Audience", "Auth method").'),
1492
- options: z
1493
- .array(
1494
- z
1495
- .object({
1496
- label: z
1497
- .string()
1498
- .min(1)
1499
- .max(80)
1500
- .describe(
1501
- 'Concise option label (1-5 words). Recommended option goes first with " (Recommended)" appended.',
1502
- ),
1503
- description: z
1504
- .string()
1505
- .max(300)
1506
- .optional()
1507
- .describe('One line on what practically changes if this option is chosen.'),
1508
- })
1509
- .strict(),
1510
- )
1511
- .min(2)
1512
- .max(4)
1513
- .describe('2-4 genuinely distinct, context-derived options.'),
1514
- multiSelect: z
1515
- .boolean()
1516
- .optional()
1517
- .default(false)
1518
- .describe('True only when several options can apply at once.'),
1519
- allowFreeText: z
1520
- .boolean()
1521
- .optional()
1522
- .default(true)
1523
- .describe('Whether the user may answer in their own words.'),
1524
- })
1525
- .strict(),
1526
- modelInputSchema: structuredClone(askUserQuestionModelInputSchema),
1527
- enforceModelInput: true,
1528
- validationErrorHint:
1529
- 'Required shape: {"question":"...?","options":[{"label":"First (Recommended)","description":"What changes"},{"label":"Second","description":"What changes"}]}. "options" must be a JSON array of 2-4 objects, never a string.',
1530
- category: 'custom',
1531
- permissions: [],
1532
- readOnly: true,
1533
- destructive: false,
1534
- // MUST stay false: the executor serializes non-concurrency-safe
1535
- // tools in a single chain, so N question blocks in one assistant
1536
- // turn park strictly one-at-a-time. Hosts key their park/resolve
1537
- // registries by runId — concurrent parks on one run clobber each
1538
- // other and the first promise never resolves (run hangs to TTL).
1539
- concurrencySafe: false,
1540
- async execute({ question, header, options, multiSelect, allowFreeText }, context) {
1541
- const toolUseId = context.toolUseId
1542
- if (!toolUseId) {
1543
- // Without the executing tool_use_id the question has no
1544
- // stable identity: the host could never merge the awaiting
1545
- // card with its resolution, and answers could not be matched
1546
- // back. Hard-fail instead of parking an unmergeable id.
1547
- return {
1548
- success: false,
1549
- output: '',
1550
- error:
1551
- 'ask_user_question requires an executor that threads ToolContext.toolUseId; the question cannot be tracked without it.',
1552
- }
1553
- }
1554
-
1555
- const questionOptions: UserQuestionOption[] = options.map((opt, i) => ({
1556
- id: `opt_${i + 1}`,
1557
- label: opt.label,
1558
- ...(opt.description !== undefined ? { description: opt.description } : {}),
1559
- }))
1560
-
1561
- const questionData = {
1562
- questionId: toolUseId,
1563
- question,
1564
- ...(header !== undefined ? { header } : {}),
1565
- options: questionOptions,
1566
- multiSelect,
1567
- allowFreeText,
1568
- }
1569
-
1570
- // An answer carried in from a resumed run. Checked before the
1571
- // park, because re-entering this tool is HOW the answer gets
1572
- // delivered: the batch is re-executed, and without this the
1573
- // re-execution would ask the user something they already
1574
- // answered — or, headless, auto-answer with the no-consent
1575
- // sentinel and throw the real answer away.
1576
- const carried = pendingAnswers?.take(toolUseId)
1577
-
1578
- // A real checkpoint, not a synthetic id nothing ever wrote.
1579
- // Skipped when an answer is already in hand: parking a
1580
- // question that is answered would leave an outstanding record
1581
- // for a decision that has been made.
1582
- const parkedAt =
1583
- carried === undefined && questionParks ? await questionParks.record(questionData) : null
1584
-
1585
- const decision =
1586
- carried ??
1587
- (await parkHandler({
1588
- type: 'user_question',
1589
- runId: parkRunId,
1590
- checkpointId: parkedAt ?? asCheckpointId(`cp_question_${toolUseId}`),
1591
- question: questionData,
1592
- }))
1593
-
1594
- // Clear the park once the answer is in, so an approval queue
1595
- // stops serving a question that has been answered.
1596
- if (parkedAt !== null && questionParks) {
1597
- await questionParks.resolve(parkedAt, decision)
1598
- }
1599
-
1600
- // The no-answer sentinel (explicitly NOT consent — fixes the
1601
- // "empty answer reads as approval" ambiguity): used for empty
1602
- // answers, misdirected legacy decisions (e.g. a stale replica
1603
- // resolving with approve/continue verbs), and answers that
1604
- // carry a different question's id.
1605
- const noAnswer = {
1606
- success: true,
1607
- output:
1608
- 'The user did not answer this question. Do not assume a choice or consent; proceed on your best judgment or continue without this information.',
1609
- data: { question, answered: false },
1610
- }
1611
-
1612
- if (decision.action === 'abort') {
1613
- return {
1614
- success: false,
1615
- output:
1616
- 'The user declined to answer and asked to stop. Acknowledge briefly and end your turn.',
1617
- data: { question, answered: false, declined: true },
1618
- }
1619
- }
1620
-
1621
- if (decision.action !== 'answer_question') return noAnswer
1622
- if (decision.questionId !== undefined && decision.questionId !== toolUseId) {
1623
- // Misdirection guard: this answer was meant for a different
1624
- // question parked under the same run (stale client). Never
1625
- // fabricate a selection against the wrong question.
1626
- return noAnswer
1627
- }
1628
-
1629
- const stripRecommended = (label: string) =>
1630
- label.replace(/\s*\(recommended\)\s*$/i, '').trim()
1631
-
1632
- const selected = decision.selectedOptionIds
1633
- .map((id) => questionOptions.find((opt) => opt.id === id))
1634
- .filter((opt): opt is UserQuestionOption => opt !== undefined)
1635
- .map((opt) => ({ id: opt.id, label: stripRecommended(opt.label) }))
1636
-
1637
- const freeText = decision.freeText?.trim() ?? ''
1638
-
1639
- if (selected.length === 0 && !freeText) return noAnswer
1640
-
1641
- let output: string
1642
- if (selected.length > 0) {
1643
- const joined = selected.map((s) => `"${s.label}"`).join(', ')
1644
- output = `User answered "${question}": ${joined}`
1645
- if (freeText) {
1646
- output += `\nAdditional note from the user: "${freeText}"`
1647
- }
1648
- } else {
1649
- output = `User answered "${question}" in their own words: "${freeText}"`
1650
- }
1651
-
1652
- return {
1653
- success: true,
1654
- output,
1655
- data: {
1656
- question,
1657
- selected,
1658
- ...(freeText ? { freeText } : {}),
1659
- answered: true,
1660
- },
1661
- }
1662
- },
1663
- })
1664
- tools.push(askUserQuestion)
1421
+ tools.push(buildAskUserQuestionTool({ resumeHandler, runId, questionParks, pendingAnswers }))
1665
1422
  }
1666
1423
 
1667
1424
  return tools
@@ -9,7 +9,7 @@ export function buildReadMemoryTool(store: MemoryStore): ToolDefinition {
9
9
  name: 'read_memory',
10
10
  description: 'Read the full content of a specific memory by its ID.',
11
11
  inputSchema: z.object({
12
- id: z.string().describe('Memory ID (mem_xxx format)'),
12
+ id: z.string().describe('Opaque memory ID returned by a memory search or save'),
13
13
  }),
14
14
  category: 'analysis',
15
15
  permissions: [],
@@ -17,9 +17,7 @@ export function buildReadMemoryTool(store: MemoryStore): ToolDefinition {
17
17
  destructive: false,
18
18
  concurrencySafe: true,
19
19
  async execute({ id }) {
20
- // Checked, not cast. `id` is model-authored and becomes a store key
21
- // on the next line; nothing downstream re-examines it, so this is
22
- // the only place a `ses_`-shaped value can be stopped.
20
+ // Validate model-authored input before using it as a store key.
23
21
  const memoryId = asMemoryId(id)
24
22
  const content = await store.get(memoryId)
25
23