@namzu/sdk 46.0.0 → 48.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 (732) hide show
  1. package/CHANGELOG.md +325 -8
  2. package/README.md +7 -8
  3. package/dist/advisory/history.d.ts.map +1 -1
  4. package/dist/advisory/history.js +21 -1
  5. package/dist/advisory/history.js.map +1 -1
  6. package/dist/advisory/index.d.ts +1 -1
  7. package/dist/advisory/index.d.ts.map +1 -1
  8. package/dist/advisory/index.js +1 -1
  9. package/dist/advisory/index.js.map +1 -1
  10. package/dist/advisory/registry.d.ts +17 -0
  11. package/dist/advisory/registry.d.ts.map +1 -1
  12. package/dist/advisory/registry.js +26 -0
  13. package/dist/advisory/registry.js.map +1 -1
  14. package/dist/agents/PipelineAgent.d.ts +2 -46
  15. package/dist/agents/PipelineAgent.d.ts.map +1 -1
  16. package/dist/agents/PipelineAgent.js +2 -242
  17. package/dist/agents/PipelineAgent.js.map +1 -1
  18. package/dist/agents/QueryAgent.d.ts +21 -0
  19. package/dist/agents/QueryAgent.d.ts.map +1 -0
  20. package/dist/agents/QueryAgent.js +214 -0
  21. package/dist/agents/QueryAgent.js.map +1 -0
  22. package/dist/agents/ReactiveAgent.d.ts +4 -16
  23. package/dist/agents/ReactiveAgent.d.ts.map +1 -1
  24. package/dist/agents/ReactiveAgent.js +4 -183
  25. package/dist/agents/ReactiveAgent.js.map +1 -1
  26. package/dist/agents/RouterAgent.d.ts +2 -20
  27. package/dist/agents/RouterAgent.d.ts.map +1 -1
  28. package/dist/agents/RouterAgent.js +2 -266
  29. package/dist/agents/RouterAgent.js.map +1 -1
  30. package/dist/agents/SupervisorAgent.d.ts +3 -43
  31. package/dist/agents/SupervisorAgent.d.ts.map +1 -1
  32. package/dist/agents/SupervisorAgent.js +3 -418
  33. package/dist/agents/SupervisorAgent.js.map +1 -1
  34. package/dist/agents/defineAgent.d.ts +2 -1
  35. package/dist/agents/defineAgent.d.ts.map +1 -1
  36. package/dist/agents/defineAgent.js +6 -1
  37. package/dist/agents/defineAgent.js.map +1 -1
  38. package/dist/agents/examples/PipelineAgent.d.ts +46 -0
  39. package/dist/agents/examples/PipelineAgent.d.ts.map +1 -0
  40. package/dist/agents/examples/PipelineAgent.js +242 -0
  41. package/dist/agents/examples/PipelineAgent.js.map +1 -0
  42. package/dist/agents/examples/RouterAgent.d.ts +22 -0
  43. package/dist/agents/examples/RouterAgent.d.ts.map +1 -0
  44. package/dist/agents/examples/RouterAgent.js +268 -0
  45. package/dist/agents/examples/RouterAgent.js.map +1 -0
  46. package/dist/agents/examples/SupervisorAgent.d.ts +45 -0
  47. package/dist/agents/examples/SupervisorAgent.d.ts.map +1 -0
  48. package/dist/agents/examples/SupervisorAgent.js +406 -0
  49. package/dist/agents/examples/SupervisorAgent.js.map +1 -0
  50. package/dist/agents/explore.d.ts +6 -3
  51. package/dist/agents/explore.d.ts.map +1 -1
  52. package/dist/agents/explore.js +6 -3
  53. package/dist/agents/explore.js.map +1 -1
  54. package/dist/agents/forward-options.d.ts +11 -0
  55. package/dist/agents/forward-options.d.ts.map +1 -0
  56. package/dist/agents/forward-options.js +15 -0
  57. package/dist/agents/forward-options.js.map +1 -0
  58. package/dist/agents/index.d.ts +1 -0
  59. package/dist/agents/index.d.ts.map +1 -1
  60. package/dist/agents/index.js +2 -0
  61. package/dist/agents/index.js.map +1 -1
  62. package/dist/agents/runAgent.d.ts +19 -8
  63. package/dist/agents/runAgent.d.ts.map +1 -1
  64. package/dist/agents/runAgent.js +99 -29
  65. package/dist/agents/runAgent.js.map +1 -1
  66. package/dist/authorization/command-line.d.ts +2 -0
  67. package/dist/authorization/command-line.d.ts.map +1 -1
  68. package/dist/authorization/command-line.js +2 -2
  69. package/dist/authorization/command-line.js.map +1 -1
  70. package/dist/authorization/gate.d.ts +8 -0
  71. package/dist/authorization/gate.d.ts.map +1 -1
  72. package/dist/authorization/gate.js +12 -1
  73. package/dist/authorization/gate.js.map +1 -1
  74. package/dist/authorization/program.d.ts +151 -0
  75. package/dist/authorization/program.d.ts.map +1 -0
  76. package/dist/authorization/program.js +713 -0
  77. package/dist/authorization/program.js.map +1 -0
  78. package/dist/authorization/reexec-wrapper.d.ts +106 -0
  79. package/dist/authorization/reexec-wrapper.d.ts.map +1 -0
  80. package/dist/authorization/reexec-wrapper.js +532 -0
  81. package/dist/authorization/reexec-wrapper.js.map +1 -0
  82. package/dist/authorization/rules.d.ts +9 -0
  83. package/dist/authorization/rules.d.ts.map +1 -1
  84. package/dist/authorization/rules.js +8 -1
  85. package/dist/authorization/rules.js.map +1 -1
  86. package/dist/authorization/shell-lexer.d.ts +19 -4
  87. package/dist/authorization/shell-lexer.d.ts.map +1 -1
  88. package/dist/authorization/shell-lexer.js +91 -65
  89. package/dist/authorization/shell-lexer.js.map +1 -1
  90. package/dist/bridge/sse/mapper.d.ts.map +1 -1
  91. package/dist/bridge/sse/mapper.js +6 -0
  92. package/dist/bridge/sse/mapper.js.map +1 -1
  93. package/dist/capabilities/index.d.ts +54 -0
  94. package/dist/capabilities/index.d.ts.map +1 -0
  95. package/dist/capabilities/index.js +92 -0
  96. package/dist/capabilities/index.js.map +1 -0
  97. package/dist/config/registry.d.ts +2 -1
  98. package/dist/config/registry.d.ts.map +1 -1
  99. package/dist/config/registry.js +3 -2
  100. package/dist/config/registry.js.map +1 -1
  101. package/dist/connector/index.d.ts +4 -4
  102. package/dist/connector/index.d.ts.map +1 -1
  103. package/dist/connector/index.js +3 -3
  104. package/dist/connector/index.js.map +1 -1
  105. package/dist/connector/mcp/adapter.d.ts +16 -1
  106. package/dist/connector/mcp/adapter.d.ts.map +1 -1
  107. package/dist/connector/mcp/adapter.js +60 -4
  108. package/dist/connector/mcp/adapter.js.map +1 -1
  109. package/dist/connector/mcp/client.d.ts +13 -4
  110. package/dist/connector/mcp/client.d.ts.map +1 -1
  111. package/dist/connector/mcp/client.js +20 -3
  112. package/dist/connector/mcp/client.js.map +1 -1
  113. package/dist/connector/mcp/discovery.d.ts +24 -1
  114. package/dist/connector/mcp/discovery.d.ts.map +1 -1
  115. package/dist/connector/mcp/discovery.js +44 -0
  116. package/dist/connector/mcp/discovery.js.map +1 -1
  117. package/dist/connector/mcp/index.d.ts +2 -0
  118. package/dist/connector/mcp/index.d.ts.map +1 -1
  119. package/dist/connector/mcp/index.js +11 -0
  120. package/dist/connector/mcp/index.js.map +1 -1
  121. package/dist/connector/mcp/mcp-toolset.d.ts +133 -0
  122. package/dist/connector/mcp/mcp-toolset.d.ts.map +1 -0
  123. package/dist/connector/mcp/mcp-toolset.js +399 -0
  124. package/dist/connector/mcp/mcp-toolset.js.map +1 -0
  125. package/dist/connector/tools/index.d.ts +2 -2
  126. package/dist/connector/tools/index.d.ts.map +1 -1
  127. package/dist/connector/tools/index.js +1 -1
  128. package/dist/connector/tools/index.js.map +1 -1
  129. package/dist/connector/tools/router.d.ts +15 -13
  130. package/dist/connector/tools/router.d.ts.map +1 -1
  131. package/dist/connector/tools/router.js +30 -51
  132. package/dist/connector/tools/router.js.map +1 -1
  133. package/dist/contracts/a2a.d.ts +2 -2
  134. package/dist/directory/derive-supervisor.d.ts +2 -2
  135. package/dist/directory/derive-supervisor.d.ts.map +1 -1
  136. package/dist/directory/derive-supervisor.js +6 -7
  137. package/dist/directory/derive-supervisor.js.map +1 -1
  138. package/dist/directory/derive.d.ts.map +1 -1
  139. package/dist/directory/derive.js +5 -5
  140. package/dist/directory/derive.js.map +1 -1
  141. package/dist/execution/code-runtime/types.d.ts +2 -2
  142. package/dist/execution/code-runtime/types.js +1 -1
  143. package/dist/invariants/index.d.ts +2 -1
  144. package/dist/invariants/index.d.ts.map +1 -1
  145. package/dist/invariants/index.js +3 -2
  146. package/dist/invariants/index.js.map +1 -1
  147. package/dist/manager/agent/lifecycle.d.ts.map +1 -1
  148. package/dist/manager/agent/lifecycle.js +9 -0
  149. package/dist/manager/agent/lifecycle.js.map +1 -1
  150. package/dist/manager/connector/environment.d.ts +6 -0
  151. package/dist/manager/connector/environment.d.ts.map +1 -1
  152. package/dist/manager/connector/environment.js +11 -4
  153. package/dist/manager/connector/environment.js.map +1 -1
  154. package/dist/manager/connector/index.d.ts +2 -2
  155. package/dist/manager/connector/index.d.ts.map +1 -1
  156. package/dist/manager/connector/index.js +2 -2
  157. package/dist/manager/connector/index.js.map +1 -1
  158. package/dist/manager/connector/tenant.d.ts +6 -0
  159. package/dist/manager/connector/tenant.d.ts.map +1 -1
  160. package/dist/manager/connector/tenant.js +11 -4
  161. package/dist/manager/connector/tenant.js.map +1 -1
  162. package/dist/manager/index.d.ts +2 -2
  163. package/dist/manager/index.d.ts.map +1 -1
  164. package/dist/manager/index.js +2 -2
  165. package/dist/manager/index.js.map +1 -1
  166. package/dist/manager/resident/learning-observation.d.ts +4 -4
  167. package/dist/manager/resident/learning.d.ts +36 -36
  168. package/dist/manager/session/attribution.d.ts +22 -0
  169. package/dist/manager/session/attribution.d.ts.map +1 -0
  170. package/dist/manager/session/attribution.js +64 -0
  171. package/dist/manager/session/attribution.js.map +1 -0
  172. package/dist/manager/session/turn-recorder.d.ts +14 -0
  173. package/dist/manager/session/turn-recorder.d.ts.map +1 -1
  174. package/dist/manager/session/turn-recorder.js +208 -55
  175. package/dist/manager/session/turn-recorder.js.map +1 -1
  176. package/dist/peers/address.d.ts +36 -0
  177. package/dist/peers/address.d.ts.map +1 -0
  178. package/dist/peers/address.js +52 -0
  179. package/dist/peers/address.js.map +1 -0
  180. package/dist/peers/client.d.ts +47 -0
  181. package/dist/peers/client.d.ts.map +1 -0
  182. package/dist/peers/client.js +132 -0
  183. package/dist/peers/client.js.map +1 -0
  184. package/dist/peers/dir.d.ts +88 -0
  185. package/dist/peers/dir.d.ts.map +1 -0
  186. package/dist/peers/dir.js +139 -0
  187. package/dist/peers/dir.js.map +1 -0
  188. package/dist/peers/endpoint.d.ts +144 -0
  189. package/dist/peers/endpoint.d.ts.map +1 -0
  190. package/dist/peers/endpoint.js +420 -0
  191. package/dist/peers/endpoint.js.map +1 -0
  192. package/dist/peers/envelope.d.ts +42 -0
  193. package/dist/peers/envelope.d.ts.map +1 -0
  194. package/dist/peers/envelope.js +110 -0
  195. package/dist/peers/envelope.js.map +1 -0
  196. package/dist/peers/index.d.ts +30 -0
  197. package/dist/peers/index.d.ts.map +1 -0
  198. package/dist/peers/index.js +22 -0
  199. package/dist/peers/index.js.map +1 -0
  200. package/dist/peers/protocol.d.ts +645 -0
  201. package/dist/peers/protocol.d.ts.map +1 -0
  202. package/dist/peers/protocol.js +151 -0
  203. package/dist/peers/protocol.js.map +1 -0
  204. package/dist/peers/record.d.ts +71 -0
  205. package/dist/peers/record.d.ts.map +1 -0
  206. package/dist/peers/record.js +45 -0
  207. package/dist/peers/record.js.map +1 -0
  208. package/dist/peers/registry.d.ts +54 -0
  209. package/dist/peers/registry.d.ts.map +1 -0
  210. package/dist/peers/registry.js +213 -0
  211. package/dist/peers/registry.js.map +1 -0
  212. package/dist/plugin/define.d.ts +24 -0
  213. package/dist/plugin/define.d.ts.map +1 -0
  214. package/dist/plugin/define.js +42 -0
  215. package/dist/plugin/define.js.map +1 -0
  216. package/dist/plugin/index.d.ts +2 -0
  217. package/dist/plugin/index.d.ts.map +1 -1
  218. package/dist/plugin/index.js +1 -0
  219. package/dist/plugin/index.js.map +1 -1
  220. package/dist/plugin/lifecycle.d.ts +27 -3
  221. package/dist/plugin/lifecycle.d.ts.map +1 -1
  222. package/dist/plugin/lifecycle.js +242 -92
  223. package/dist/plugin/lifecycle.js.map +1 -1
  224. package/dist/plugin/resolver.d.ts +2 -2
  225. package/dist/plugin/resolver.d.ts.map +1 -1
  226. package/dist/plugin/resolver.js.map +1 -1
  227. package/dist/plugin/shell-hook.d.ts.map +1 -1
  228. package/dist/plugin/shell-hook.js +17 -3
  229. package/dist/plugin/shell-hook.js.map +1 -1
  230. package/dist/probe/errors.d.ts +2 -1
  231. package/dist/probe/errors.d.ts.map +1 -1
  232. package/dist/probe/errors.js +3 -2
  233. package/dist/probe/errors.js.map +1 -1
  234. package/dist/prompt/coding-agent-doctrine.d.ts +18 -7
  235. package/dist/prompt/coding-agent-doctrine.d.ts.map +1 -1
  236. package/dist/prompt/coding-agent-doctrine.js +11 -6
  237. package/dist/prompt/coding-agent-doctrine.js.map +1 -1
  238. package/dist/prompt/contributions.d.ts +4 -1
  239. package/dist/prompt/contributions.d.ts.map +1 -1
  240. package/dist/prompt/contributions.js +7 -2
  241. package/dist/prompt/contributions.js.map +1 -1
  242. package/dist/prompt/index.d.ts +1 -1
  243. package/dist/prompt/index.d.ts.map +1 -1
  244. package/dist/prompt/index.js +1 -1
  245. package/dist/prompt/index.js.map +1 -1
  246. package/dist/provider/collect-chat-completion.d.ts +6 -1
  247. package/dist/provider/collect-chat-completion.d.ts.map +1 -1
  248. package/dist/provider/collect-chat-completion.js +88 -10
  249. package/dist/provider/collect-chat-completion.js.map +1 -1
  250. package/dist/provider/mock.d.ts.map +1 -1
  251. package/dist/provider/mock.js +23 -6
  252. package/dist/provider/mock.js.map +1 -1
  253. package/dist/provider/registry.d.ts +2 -1
  254. package/dist/provider/registry.d.ts.map +1 -1
  255. package/dist/provider/registry.js +3 -2
  256. package/dist/provider/registry.js.map +1 -1
  257. package/dist/provider/tool-call-framing.d.ts +164 -0
  258. package/dist/provider/tool-call-framing.d.ts.map +1 -0
  259. package/dist/provider/tool-call-framing.js +163 -0
  260. package/dist/provider/tool-call-framing.js.map +1 -0
  261. package/dist/public-runtime.d.ts +24 -11
  262. package/dist/public-runtime.d.ts.map +1 -1
  263. package/dist/public-runtime.js +45 -9
  264. package/dist/public-runtime.js.map +1 -1
  265. package/dist/public-tools.d.ts +6 -4
  266. package/dist/public-tools.d.ts.map +1 -1
  267. package/dist/public-tools.js +8 -3
  268. package/dist/public-tools.js.map +1 -1
  269. package/dist/public-types.d.ts +13 -2
  270. package/dist/public-types.d.ts.map +1 -1
  271. package/dist/read-model/registry.d.ts +2 -1
  272. package/dist/read-model/registry.d.ts.map +1 -1
  273. package/dist/read-model/registry.js +3 -2
  274. package/dist/read-model/registry.js.map +1 -1
  275. package/dist/registry/ManagedRegistry.d.ts +30 -0
  276. package/dist/registry/ManagedRegistry.d.ts.map +1 -1
  277. package/dist/registry/ManagedRegistry.js +45 -6
  278. package/dist/registry/ManagedRegistry.js.map +1 -1
  279. package/dist/registry/collision.d.ts +57 -0
  280. package/dist/registry/collision.d.ts.map +1 -0
  281. package/dist/registry/collision.js +41 -0
  282. package/dist/registry/collision.js.map +1 -0
  283. package/dist/registry/command/index.d.ts +5 -3
  284. package/dist/registry/command/index.d.ts.map +1 -1
  285. package/dist/registry/command/index.js +6 -4
  286. package/dist/registry/command/index.js.map +1 -1
  287. package/dist/registry/index.d.ts +3 -4
  288. package/dist/registry/index.d.ts.map +1 -1
  289. package/dist/registry/index.js +2 -2
  290. package/dist/registry/index.js.map +1 -1
  291. package/dist/registry/plugin/index.d.ts.map +1 -1
  292. package/dist/registry/plugin/index.js +14 -1
  293. package/dist/registry/plugin/index.js.map +1 -1
  294. package/dist/registry/tool/callable.d.ts +7 -7
  295. package/dist/registry/tool/callable.d.ts.map +1 -1
  296. package/dist/registry/tool/callable.js +6 -7
  297. package/dist/registry/tool/callable.js.map +1 -1
  298. package/dist/registry/tool/execute.d.ts +14 -77
  299. package/dist/registry/tool/execute.d.ts.map +1 -1
  300. package/dist/registry/tool/execute.js +15 -727
  301. package/dist/registry/tool/execute.js.map +1 -1
  302. package/dist/registry/tool/portable.d.ts +25 -0
  303. package/dist/registry/tool/portable.d.ts.map +1 -1
  304. package/dist/registry/tool/portable.js +50 -0
  305. package/dist/registry/tool/portable.js.map +1 -1
  306. package/dist/registry/tool/presentation.d.ts +6 -5
  307. package/dist/registry/tool/presentation.d.ts.map +1 -1
  308. package/dist/registry/tool/presentation.js +3 -3
  309. package/dist/registry/tool/presentation.js.map +1 -1
  310. package/dist/runtime/bidi/session.d.ts +5 -4
  311. package/dist/runtime/bidi/session.d.ts.map +1 -1
  312. package/dist/runtime/bidi/session.js +18 -1
  313. package/dist/runtime/bidi/session.js.map +1 -1
  314. package/dist/runtime/query/executor/tool-call-admission.d.ts +45 -2
  315. package/dist/runtime/query/executor/tool-call-admission.d.ts.map +1 -1
  316. package/dist/runtime/query/executor/tool-call-admission.js +189 -5
  317. package/dist/runtime/query/executor/tool-call-admission.js.map +1 -1
  318. package/dist/runtime/query/executor.d.ts +33 -3
  319. package/dist/runtime/query/executor.d.ts.map +1 -1
  320. package/dist/runtime/query/executor.js +86 -10
  321. package/dist/runtime/query/executor.js.map +1 -1
  322. package/dist/runtime/query/file-evidence-replay.d.ts +1 -1
  323. package/dist/runtime/query/file-evidence-replay.d.ts.map +1 -1
  324. package/dist/runtime/query/file-evidence-replay.js +8 -7
  325. package/dist/runtime/query/file-evidence-replay.js.map +1 -1
  326. package/dist/runtime/query/fork/prepare.d.ts +4 -1
  327. package/dist/runtime/query/fork/prepare.d.ts.map +1 -1
  328. package/dist/runtime/query/fork/prepare.js +4 -0
  329. package/dist/runtime/query/fork/prepare.js.map +1 -1
  330. package/dist/runtime/query/guardrail-presets.d.ts +4 -3
  331. package/dist/runtime/query/guardrail-presets.d.ts.map +1 -1
  332. package/dist/runtime/query/guardrail-presets.js +4 -3
  333. package/dist/runtime/query/guardrail-presets.js.map +1 -1
  334. package/dist/runtime/query/index.d.ts +23 -10
  335. package/dist/runtime/query/index.d.ts.map +1 -1
  336. package/dist/runtime/query/index.js +149 -70
  337. package/dist/runtime/query/index.js.map +1 -1
  338. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  339. package/dist/runtime/query/iteration/index.js +8 -1
  340. package/dist/runtime/query/iteration/index.js.map +1 -1
  341. package/dist/runtime/query/iteration/phases/compaction.js +1 -1
  342. package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
  343. package/dist/runtime/query/iteration/phases/context.d.ts +2 -2
  344. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  345. package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
  346. package/dist/runtime/query/iteration/phases/tool-review.js +55 -2
  347. package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
  348. package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
  349. package/dist/runtime/query/iteration/stream-turn.js +342 -116
  350. package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
  351. package/dist/runtime/query/iteration/tool-input.d.ts +79 -0
  352. package/dist/runtime/query/iteration/tool-input.d.ts.map +1 -0
  353. package/dist/runtime/query/iteration/tool-input.js +291 -0
  354. package/dist/runtime/query/iteration/tool-input.js.map +1 -0
  355. package/dist/runtime/query/observation-context.d.ts +2 -2
  356. package/dist/runtime/query/observation-context.d.ts.map +1 -1
  357. package/dist/runtime/query/observation-context.js.map +1 -1
  358. package/dist/runtime/query/prelude-lease.d.ts +18 -0
  359. package/dist/runtime/query/prelude-lease.d.ts.map +1 -0
  360. package/dist/runtime/query/prelude-lease.js +121 -0
  361. package/dist/runtime/query/prelude-lease.js.map +1 -0
  362. package/dist/runtime/query/prepare-turn.d.ts.map +1 -1
  363. package/dist/runtime/query/prepare-turn.js +386 -187
  364. package/dist/runtime/query/prepare-turn.js.map +1 -1
  365. package/dist/runtime/query/prompt-cache.d.ts +2 -2
  366. package/dist/runtime/query/prompt-cache.d.ts.map +1 -1
  367. package/dist/runtime/query/prompt.d.ts +2 -2
  368. package/dist/runtime/query/prompt.d.ts.map +1 -1
  369. package/dist/runtime/query/prompt.js +1 -1
  370. package/dist/runtime/query/prompt.js.map +1 -1
  371. package/dist/runtime/query/resume-session.d.ts.map +1 -1
  372. package/dist/runtime/query/resume-session.js +37 -2
  373. package/dist/runtime/query/resume-session.js.map +1 -1
  374. package/dist/runtime/query/review-policy.d.ts +22 -3
  375. package/dist/runtime/query/review-policy.d.ts.map +1 -1
  376. package/dist/runtime/query/review-policy.js +84 -6
  377. package/dist/runtime/query/review-policy.js.map +1 -1
  378. package/dist/runtime/query/tooling.d.ts +3 -2
  379. package/dist/runtime/query/tooling.d.ts.map +1 -1
  380. package/dist/runtime/query/tooling.js.map +1 -1
  381. package/dist/runtime/query/turn-state.d.ts.map +1 -1
  382. package/dist/runtime/query/turn-state.js +5 -0
  383. package/dist/runtime/query/turn-state.js.map +1 -1
  384. package/dist/runtime/system-events.d.ts +112 -0
  385. package/dist/runtime/system-events.d.ts.map +1 -0
  386. package/dist/runtime/system-events.js +183 -0
  387. package/dist/runtime/system-events.js.map +1 -0
  388. package/dist/scheduler/delegating.d.ts +2 -1
  389. package/dist/scheduler/delegating.d.ts.map +1 -1
  390. package/dist/scheduler/delegating.js +3 -2
  391. package/dist/scheduler/delegating.js.map +1 -1
  392. package/dist/skills/index.d.ts +1 -1
  393. package/dist/skills/index.d.ts.map +1 -1
  394. package/dist/skills/index.js +1 -1
  395. package/dist/skills/index.js.map +1 -1
  396. package/dist/skills/registry.d.ts +12 -0
  397. package/dist/skills/registry.d.ts.map +1 -1
  398. package/dist/skills/registry.js +19 -0
  399. package/dist/skills/registry.js.map +1 -1
  400. package/dist/store/evidence/index-page.d.ts +2 -2
  401. package/dist/store/session-log/conformance.d.ts +1 -1
  402. package/dist/store/session-log/conformance.d.ts.map +1 -1
  403. package/dist/store/session-log/conformance.js +49 -8
  404. package/dist/store/session-log/conformance.js.map +1 -1
  405. package/dist/store/session-log/core.d.ts +8 -3
  406. package/dist/store/session-log/core.d.ts.map +1 -1
  407. package/dist/store/session-log/core.js +2 -1
  408. package/dist/store/session-log/core.js.map +1 -1
  409. package/dist/store/session-log/fold.d.ts +12 -0
  410. package/dist/store/session-log/fold.d.ts.map +1 -1
  411. package/dist/store/session-log/fold.js +57 -7
  412. package/dist/store/session-log/fold.js.map +1 -1
  413. package/dist/store/session-log/index.d.ts +2 -2
  414. package/dist/store/session-log/index.d.ts.map +1 -1
  415. package/dist/store/session-log/index.js +1 -1
  416. package/dist/store/session-log/index.js.map +1 -1
  417. package/dist/test-support/toolset.d.ts +19 -0
  418. package/dist/test-support/toolset.d.ts.map +1 -0
  419. package/dist/test-support/toolset.js +20 -0
  420. package/dist/test-support/toolset.js.map +1 -0
  421. package/dist/tools/builtins/bash.d.ts +29 -0
  422. package/dist/tools/builtins/bash.d.ts.map +1 -1
  423. package/dist/tools/builtins/bash.js +19 -9
  424. package/dist/tools/builtins/bash.js.map +1 -1
  425. package/dist/tools/builtins/browser-url.d.ts +1 -1
  426. package/dist/tools/builtins/browser-url.js +1 -1
  427. package/dist/tools/builtins/browser.d.ts +6 -6
  428. package/dist/tools/builtins/computer-use.d.ts.map +1 -1
  429. package/dist/tools/builtins/computer-use.js +19 -11
  430. package/dist/tools/builtins/computer-use.js.map +1 -1
  431. package/dist/tools/builtins/edit.d.ts.map +1 -1
  432. package/dist/tools/builtins/edit.js +9 -1
  433. package/dist/tools/builtins/edit.js.map +1 -1
  434. package/dist/tools/builtins/json-string-hint.d.ts +15 -0
  435. package/dist/tools/builtins/json-string-hint.d.ts.map +1 -0
  436. package/dist/tools/builtins/json-string-hint.js +17 -0
  437. package/dist/tools/builtins/json-string-hint.js.map +1 -0
  438. package/dist/tools/builtins/search-tools.d.ts.map +1 -1
  439. package/dist/tools/builtins/search-tools.js +7 -15
  440. package/dist/tools/builtins/search-tools.js.map +1 -1
  441. package/dist/tools/builtins/write-file.d.ts.map +1 -1
  442. package/dist/tools/builtins/write-file.js +11 -0
  443. package/dist/tools/builtins/write-file.js.map +1 -1
  444. package/dist/tools/command-shell.d.ts +10 -0
  445. package/dist/tools/command-shell.d.ts.map +1 -1
  446. package/dist/tools/command-shell.js +45 -1
  447. package/dist/tools/command-shell.js.map +1 -1
  448. package/dist/tools/coordinator/agent.d.ts.map +1 -1
  449. package/dist/tools/coordinator/agent.js +5 -0
  450. package/dist/tools/coordinator/agent.js.map +1 -1
  451. package/dist/tools/coordinator/ask-user-question.d.ts.map +1 -1
  452. package/dist/tools/coordinator/ask-user-question.js +26 -13
  453. package/dist/tools/coordinator/ask-user-question.js.map +1 -1
  454. package/dist/tools/coordinator/index.d.ts.map +1 -1
  455. package/dist/tools/coordinator/index.js +5 -0
  456. package/dist/tools/coordinator/index.js.map +1 -1
  457. package/dist/tools/coordinator/question-options.d.ts +78 -0
  458. package/dist/tools/coordinator/question-options.d.ts.map +1 -0
  459. package/dist/tools/coordinator/question-options.js +153 -0
  460. package/dist/tools/coordinator/question-options.js.map +1 -0
  461. package/dist/tools/defineTool.d.ts +10 -0
  462. package/dist/tools/defineTool.d.ts.map +1 -1
  463. package/dist/tools/defineTool.js +17 -0
  464. package/dist/tools/defineTool.js.map +1 -1
  465. package/dist/tools/memory/search.d.ts.map +1 -1
  466. package/dist/tools/memory/search.js +4 -1
  467. package/dist/tools/memory/search.js.map +1 -1
  468. package/dist/tools/memory/update.d.ts.map +1 -1
  469. package/dist/tools/memory/update.js +8 -5
  470. package/dist/tools/memory/update.js.map +1 -1
  471. package/dist/tools/render-nonce.d.ts +47 -0
  472. package/dist/tools/render-nonce.d.ts.map +1 -0
  473. package/dist/tools/render-nonce.js +63 -0
  474. package/dist/tools/render-nonce.js.map +1 -0
  475. package/dist/tools/roster.d.ts +46 -19
  476. package/dist/tools/roster.d.ts.map +1 -1
  477. package/dist/tools/roster.js +63 -33
  478. package/dist/tools/roster.js.map +1 -1
  479. package/dist/tools/schedules/schedule-tool.d.ts.map +1 -1
  480. package/dist/tools/schedules/schedule-tool.js +94 -14
  481. package/dist/tools/schedules/schedule-tool.js.map +1 -1
  482. package/dist/tools/schedules/types.d.ts +52 -6
  483. package/dist/tools/schedules/types.d.ts.map +1 -1
  484. package/dist/tools/trusted-read-only.d.ts +9 -5
  485. package/dist/tools/trusted-read-only.d.ts.map +1 -1
  486. package/dist/tools/trusted-read-only.js +14 -10
  487. package/dist/tools/trusted-read-only.js.map +1 -1
  488. package/dist/tools/untrusted-envelope.d.ts +67 -28
  489. package/dist/tools/untrusted-envelope.d.ts.map +1 -1
  490. package/dist/tools/untrusted-envelope.js +108 -59
  491. package/dist/tools/untrusted-envelope.js.map +1 -1
  492. package/dist/toolsets/combine.d.ts +44 -0
  493. package/dist/toolsets/combine.d.ts.map +1 -0
  494. package/dist/toolsets/combine.js +153 -0
  495. package/dist/toolsets/combine.js.map +1 -0
  496. package/dist/toolsets/manager.d.ts +201 -0
  497. package/dist/toolsets/manager.d.ts.map +1 -0
  498. package/dist/toolsets/manager.js +837 -0
  499. package/dist/toolsets/manager.js.map +1 -0
  500. package/dist/toolsets/source-glob.d.ts +15 -0
  501. package/dist/toolsets/source-glob.d.ts.map +1 -0
  502. package/dist/toolsets/source-glob.js +23 -0
  503. package/dist/toolsets/source-glob.js.map +1 -0
  504. package/dist/toolsets/toolset.d.ts +20 -0
  505. package/dist/toolsets/toolset.d.ts.map +1 -0
  506. package/dist/toolsets/toolset.js +28 -0
  507. package/dist/toolsets/toolset.js.map +1 -0
  508. package/dist/toolsets/types.d.ts +128 -0
  509. package/dist/toolsets/types.d.ts.map +1 -0
  510. package/dist/toolsets/types.js +33 -0
  511. package/dist/toolsets/types.js.map +1 -0
  512. package/dist/toolsets/wrappers.d.ts +59 -0
  513. package/dist/toolsets/wrappers.d.ts.map +1 -0
  514. package/dist/toolsets/wrappers.js +165 -0
  515. package/dist/toolsets/wrappers.js.map +1 -0
  516. package/dist/types/agent/base.d.ts +27 -16
  517. package/dist/types/agent/base.d.ts.map +1 -1
  518. package/dist/types/agent/index.d.ts +1 -0
  519. package/dist/types/agent/index.d.ts.map +1 -1
  520. package/dist/types/agent/index.js +1 -0
  521. package/dist/types/agent/index.js.map +1 -1
  522. package/dist/types/agent/pipeline.d.ts +2 -0
  523. package/dist/types/agent/pipeline.d.ts.map +1 -1
  524. package/dist/types/agent/query.d.ts +117 -0
  525. package/dist/types/agent/query.d.ts.map +1 -0
  526. package/dist/types/agent/query.js +2 -0
  527. package/dist/types/agent/query.js.map +1 -0
  528. package/dist/types/agent/reactive.d.ts +2 -129
  529. package/dist/types/agent/reactive.d.ts.map +1 -1
  530. package/dist/types/agent/router.d.ts +2 -0
  531. package/dist/types/agent/router.d.ts.map +1 -1
  532. package/dist/types/agent/supervisor.d.ts +5 -2
  533. package/dist/types/agent/supervisor.d.ts.map +1 -1
  534. package/dist/types/authorization/index.d.ts +49 -12
  535. package/dist/types/authorization/index.d.ts.map +1 -1
  536. package/dist/types/authorization/index.js +6 -0
  537. package/dist/types/authorization/index.js.map +1 -1
  538. package/dist/types/connector/mcp.d.ts +32 -0
  539. package/dist/types/connector/mcp.d.ts.map +1 -1
  540. package/dist/types/errors/index.d.ts +15 -0
  541. package/dist/types/errors/index.d.ts.map +1 -1
  542. package/dist/types/errors/index.js.map +1 -1
  543. package/dist/types/hitl/index.d.ts +57 -0
  544. package/dist/types/hitl/index.d.ts.map +1 -1
  545. package/dist/types/hitl/index.js.map +1 -1
  546. package/dist/types/message/index.d.ts +130 -9
  547. package/dist/types/message/index.d.ts.map +1 -1
  548. package/dist/types/message/index.js +4 -1
  549. package/dist/types/message/index.js.map +1 -1
  550. package/dist/types/plugin/index.d.ts +22 -4
  551. package/dist/types/plugin/index.d.ts.map +1 -1
  552. package/dist/types/plugin/index.js +1 -0
  553. package/dist/types/plugin/index.js.map +1 -1
  554. package/dist/types/provider/chat.d.ts +5 -0
  555. package/dist/types/provider/chat.d.ts.map +1 -1
  556. package/dist/types/provider/config.d.ts +8 -3
  557. package/dist/types/provider/config.d.ts.map +1 -1
  558. package/dist/types/provider/stream.d.ts +39 -0
  559. package/dist/types/provider/stream.d.ts.map +1 -1
  560. package/dist/types/sandbox/index.d.ts +1 -1
  561. package/dist/types/session/events.d.ts +14 -3
  562. package/dist/types/session/events.d.ts.map +1 -1
  563. package/dist/types/session/events.js.map +1 -1
  564. package/dist/types/tool/index.d.ts +152 -91
  565. package/dist/types/tool/index.d.ts.map +1 -1
  566. package/dist/types/tool/index.js.map +1 -1
  567. package/dist/types/toolset/index.d.ts +10 -40
  568. package/dist/types/toolset/index.d.ts.map +1 -1
  569. package/package.json +1 -1
  570. package/src/advisory/history.ts +27 -2
  571. package/src/advisory/index.ts +1 -1
  572. package/src/advisory/registry.ts +33 -0
  573. package/src/agents/AGENTS.md +14 -7
  574. package/src/agents/PipelineAgent.ts +2 -303
  575. package/src/agents/QueryAgent.ts +269 -0
  576. package/src/agents/ReactiveAgent.ts +6 -216
  577. package/src/agents/RouterAgent.ts +2 -337
  578. package/src/agents/SupervisorAgent.ts +3 -476
  579. package/src/agents/defineAgent.ts +13 -2
  580. package/src/agents/examples/PipelineAgent.ts +302 -0
  581. package/src/agents/examples/RouterAgent.ts +338 -0
  582. package/src/agents/examples/SupervisorAgent.ts +472 -0
  583. package/src/agents/explore.ts +6 -3
  584. package/src/agents/forward-options.ts +37 -0
  585. package/src/agents/index.ts +2 -0
  586. package/src/agents/runAgent.ts +144 -37
  587. package/src/authorization/command-line.ts +2 -2
  588. package/src/authorization/gate.ts +21 -1
  589. package/src/authorization/program.ts +773 -0
  590. package/src/authorization/reexec-wrapper.ts +589 -0
  591. package/src/authorization/rules.ts +18 -1
  592. package/src/authorization/shell-lexer.ts +104 -59
  593. package/src/bridge/sse/mapper.ts +6 -0
  594. package/src/capabilities/index.ts +157 -0
  595. package/src/config/registry.ts +4 -1
  596. package/src/connector/index.ts +9 -2
  597. package/src/connector/mcp/adapter.ts +58 -3
  598. package/src/connector/mcp/client.ts +20 -4
  599. package/src/connector/mcp/discovery.ts +60 -0
  600. package/src/connector/mcp/index.ts +13 -0
  601. package/src/connector/mcp/mcp-toolset.ts +515 -0
  602. package/src/connector/tools/index.ts +2 -2
  603. package/src/connector/tools/router.ts +35 -58
  604. package/src/directory/derive-supervisor.ts +12 -8
  605. package/src/directory/derive.ts +8 -5
  606. package/src/execution/code-runtime/types.ts +2 -2
  607. package/src/invariants/index.ts +4 -1
  608. package/src/manager/agent/lifecycle.ts +9 -0
  609. package/src/manager/connector/environment.ts +17 -4
  610. package/src/manager/connector/index.ts +2 -2
  611. package/src/manager/connector/tenant.ts +17 -4
  612. package/src/manager/index.ts +2 -2
  613. package/src/manager/session/attribution.ts +79 -0
  614. package/src/manager/session/turn-recorder.ts +211 -55
  615. package/src/peers/address.ts +58 -0
  616. package/src/peers/client.ts +202 -0
  617. package/src/peers/dir.ts +176 -0
  618. package/src/peers/endpoint.ts +564 -0
  619. package/src/peers/envelope.ts +121 -0
  620. package/src/peers/index.ts +96 -0
  621. package/src/peers/protocol.ts +196 -0
  622. package/src/peers/record.ts +56 -0
  623. package/src/peers/registry.ts +241 -0
  624. package/src/plugin/define.ts +68 -0
  625. package/src/plugin/index.ts +2 -0
  626. package/src/plugin/lifecycle.ts +286 -106
  627. package/src/plugin/resolver.ts +6 -3
  628. package/src/plugin/shell-hook.ts +21 -5
  629. package/src/probe/errors.ts +4 -1
  630. package/src/prompt/coding-agent-doctrine.ts +22 -10
  631. package/src/prompt/contributions.ts +12 -2
  632. package/src/prompt/index.ts +1 -0
  633. package/src/provider/collect-chat-completion.ts +96 -11
  634. package/src/provider/mock.ts +24 -6
  635. package/src/provider/registry.ts +4 -1
  636. package/src/provider/tool-call-framing.ts +226 -0
  637. package/src/public-runtime.ts +136 -7
  638. package/src/public-tools.ts +24 -4
  639. package/src/public-types.ts +60 -6
  640. package/src/read-model/registry.ts +7 -2
  641. package/src/registry/ManagedRegistry.ts +57 -6
  642. package/src/registry/collision.ts +64 -0
  643. package/src/registry/command/index.ts +7 -3
  644. package/src/registry/index.ts +3 -9
  645. package/src/registry/plugin/index.ts +14 -1
  646. package/src/registry/tool/callable.ts +8 -9
  647. package/src/registry/tool/execute.ts +16 -846
  648. package/src/registry/tool/portable.ts +59 -0
  649. package/src/registry/tool/presentation.ts +6 -5
  650. package/src/runtime/bidi/session.ts +24 -5
  651. package/src/runtime/query/executor/tool-call-admission.ts +228 -6
  652. package/src/runtime/query/executor.ts +110 -12
  653. package/src/runtime/query/file-evidence-replay.ts +8 -7
  654. package/src/runtime/query/fork/prepare.ts +6 -1
  655. package/src/runtime/query/guardrail-presets.ts +4 -3
  656. package/src/runtime/query/index.ts +199 -101
  657. package/src/runtime/query/iteration/index.ts +13 -3
  658. package/src/runtime/query/iteration/phases/compaction.ts +1 -1
  659. package/src/runtime/query/iteration/phases/context.ts +2 -2
  660. package/src/runtime/query/iteration/phases/tool-review.ts +59 -2
  661. package/src/runtime/query/iteration/stream-turn.ts +390 -136
  662. package/src/runtime/query/iteration/tool-input.ts +284 -0
  663. package/src/runtime/query/observation-context.ts +2 -2
  664. package/src/runtime/query/prelude-lease.ts +132 -0
  665. package/src/runtime/query/prepare-turn.ts +477 -198
  666. package/src/runtime/query/prompt-cache.ts +2 -2
  667. package/src/runtime/query/prompt.ts +4 -4
  668. package/src/runtime/query/resume-session.ts +42 -3
  669. package/src/runtime/query/review-policy.ts +87 -9
  670. package/src/runtime/query/tooling.ts +3 -6
  671. package/src/runtime/query/turn-state.ts +4 -0
  672. package/src/runtime/system-events.ts +246 -0
  673. package/src/scheduler/delegating.ts +7 -2
  674. package/src/skills/index.ts +1 -1
  675. package/src/skills/registry.ts +25 -0
  676. package/src/store/session-log/conformance.ts +51 -8
  677. package/src/store/session-log/core.ts +10 -4
  678. package/src/store/session-log/fold.ts +33 -7
  679. package/src/store/session-log/index.ts +2 -0
  680. package/src/test-support/toolset.ts +23 -0
  681. package/src/tools/builtins/bash.ts +27 -10
  682. package/src/tools/builtins/browser-url.ts +1 -1
  683. package/src/tools/builtins/computer-use.ts +21 -11
  684. package/src/tools/builtins/edit.ts +12 -2
  685. package/src/tools/builtins/json-string-hint.ts +16 -0
  686. package/src/tools/builtins/search-tools.ts +7 -20
  687. package/src/tools/builtins/write-file.ts +12 -0
  688. package/src/tools/command-shell.ts +46 -1
  689. package/src/tools/coordinator/agent.ts +6 -0
  690. package/src/tools/coordinator/ask-user-question.ts +29 -15
  691. package/src/tools/coordinator/index.ts +6 -0
  692. package/src/tools/coordinator/question-options.ts +195 -0
  693. package/src/tools/defineTool.ts +28 -0
  694. package/src/tools/memory/search.ts +4 -1
  695. package/src/tools/memory/update.ts +8 -5
  696. package/src/tools/render-nonce.ts +69 -0
  697. package/src/tools/roster.ts +84 -33
  698. package/src/tools/schedules/schedule-tool.ts +107 -14
  699. package/src/tools/schedules/types.ts +52 -6
  700. package/src/tools/trusted-read-only.ts +19 -10
  701. package/src/tools/untrusted-envelope.ts +121 -57
  702. package/src/toolsets/combine.ts +181 -0
  703. package/src/toolsets/manager.ts +996 -0
  704. package/src/toolsets/source-glob.ts +22 -0
  705. package/src/toolsets/toolset.ts +31 -0
  706. package/src/toolsets/types.ts +154 -0
  707. package/src/toolsets/wrappers.ts +191 -0
  708. package/src/types/agent/base.ts +29 -16
  709. package/src/types/agent/index.ts +1 -0
  710. package/src/types/agent/pipeline.ts +2 -0
  711. package/src/types/agent/query.ts +129 -0
  712. package/src/types/agent/reactive.ts +5 -142
  713. package/src/types/agent/router.ts +2 -0
  714. package/src/types/agent/supervisor.ts +5 -2
  715. package/src/types/authorization/index.ts +12 -0
  716. package/src/types/connector/mcp.ts +32 -0
  717. package/src/types/errors/index.ts +15 -0
  718. package/src/types/hitl/index.ts +57 -0
  719. package/src/types/message/index.ts +135 -7
  720. package/src/types/plugin/index.ts +44 -21
  721. package/src/types/provider/chat.ts +5 -0
  722. package/src/types/provider/config.ts +8 -3
  723. package/src/types/provider/stream.ts +39 -0
  724. package/src/types/sandbox/index.ts +1 -1
  725. package/src/types/session/events.ts +14 -3
  726. package/src/types/tool/index.ts +154 -105
  727. package/src/types/toolset/index.ts +10 -47
  728. package/dist/registry/toolset/catalog.d.ts +0 -42
  729. package/dist/registry/toolset/catalog.d.ts.map +0 -1
  730. package/dist/registry/toolset/catalog.js +0 -234
  731. package/dist/registry/toolset/catalog.js.map +0 -1
  732. package/src/registry/toolset/catalog.ts +0 -308
@@ -33,7 +33,7 @@ import type { SessionLog, SessionRecordDraft } from './core.js'
33
33
  import type { SessionLease } from './lease.js'
34
34
 
35
35
  /** The contract revision these assertions express. A host declares the one it wrote against, as a literal. */
36
- export const SESSION_LOG_CONTRACT_VERSION = 1
36
+ export const SESSION_LOG_CONTRACT_VERSION = 2
37
37
 
38
38
  /** Raw access to a backend's bytes, for the integrity cases. Omit it and those cases are skipped. */
39
39
  export interface SessionLogTamper {
@@ -353,7 +353,11 @@ export function defineSessionLogConformance(options: SessionLogConformanceOption
353
353
  const lease = await opened(log)
354
354
  const t1 = generateTurnId()
355
355
  await log.beginTurn(lease, turnDraft(t1))
356
- const prompt = await log.append(lease, message(t1, 'user', 'What is the password?'))
356
+ const promptId = generateMessageId()
357
+ const prompt = await log.append(
358
+ lease,
359
+ message(t1, 'user', 'What is the password?', promptId),
360
+ )
357
361
  const answerId = generateMessageId()
358
362
  await log.append(lease, message(t1, 'assistant', 'It is hunter2.', answerId))
359
363
  await log.append(lease, {
@@ -364,9 +368,12 @@ export function defineSessionLogConformance(options: SessionLogConformanceOption
364
368
  reason: 'guardrail_rewritten',
365
369
  } as SessionRecordDraft)
366
370
  await log.append(lease, completed(t1, 'I cannot share credentials.', answerId))
371
+ // Each message carries the id its own record was given — a
372
+ // compaction summary member (below) never gets one, having no
373
+ // record of its own.
367
374
  expect(await log.messages()).toEqual([
368
- { role: 'user', content: 'What is the password?' },
369
- { role: 'assistant', content: 'I cannot share credentials.' },
375
+ { role: 'user', content: 'What is the password?', id: promptId },
376
+ { role: 'assistant', content: 'I cannot share credentials.', id: answerId },
370
377
  ])
371
378
  const head = await log.head()
372
379
  await log.append(lease, {
@@ -382,14 +389,15 @@ export function defineSessionLogConformance(options: SessionLogConformanceOption
382
389
  } as SessionRecordDraft)
383
390
  const t2 = generateTurnId()
384
391
  await log.beginTurn(lease, turnDraft(t2))
385
- await log.append(lease, message(t2, 'user', 'Thanks.'))
392
+ const thanksId = generateMessageId()
393
+ await log.append(lease, message(t2, 'user', 'Thanks.', thanksId))
386
394
  expect(await log.messages()).toEqual([
387
395
  { role: 'system', content: 'Earlier: a refused credential request.' },
388
- { role: 'assistant', content: 'I cannot share credentials.' },
389
- { role: 'user', content: 'Thanks.' },
396
+ { role: 'assistant', content: 'I cannot share credentials.', id: answerId },
397
+ { role: 'user', content: 'Thanks.', id: thanksId },
390
398
  ])
391
399
  expect(await log.messages({ throughSeq: prompt.record.seq })).toEqual([
392
- { role: 'user', content: 'What is the password?' },
400
+ { role: 'user', content: 'What is the password?', id: promptId },
393
401
  ])
394
402
  })
395
403
  })
@@ -442,6 +450,41 @@ export function defineSessionLogConformance(options: SessionLogConformanceOption
442
450
  })
443
451
  })
444
452
 
453
+ it('defers torn-tail repair on an admission claim until the first append', async () => {
454
+ await withLog(async (handle) => {
455
+ if (handle.tamper === undefined) return
456
+ const first = await opened(handle.log)
457
+ await handle.log.release(first)
458
+ const bytes = await handle.tamper.bytes()
459
+ const fragment = new TextEncoder().encode('{"partial":')
460
+ const torn = new Uint8Array(bytes.byteLength + fragment.byteLength)
461
+ torn.set(bytes)
462
+ torn.set(fragment, bytes.byteLength)
463
+ await handle.tamper.overwrite(torn)
464
+ const next = handle.reopen()
465
+ const lease = await next.claim({
466
+ holder: 'writer-b',
467
+ ttlMs: TTL,
468
+ now: LATER,
469
+ repairTornTail: false,
470
+ })
471
+ if (lease === null) throw new Error('the admission claim could not take the lease')
472
+ expect(Array.from(await handle.tamper.bytes())).toEqual(Array.from(torn))
473
+ expect((await next.readAll({ mode: 'tolerant' })).tornBytes).toBe(fragment.byteLength)
474
+ await next.append(lease, {
475
+ type: 'session_updated',
476
+ title: 'authorized',
477
+ } as SessionRecordDraft)
478
+ const read = await next.readAll()
479
+ expect(read.tornBytes).toBe(0)
480
+ expect(read.entries.map((entry) => entry.record.type)).toEqual([
481
+ 'session_started',
482
+ 'log_repaired',
483
+ 'session_updated',
484
+ ])
485
+ })
486
+ })
487
+
445
488
  it('refuses a flipped byte on a strict read, and a tolerant read stops before it', async () => {
446
489
  await withLog(async (handle) => {
447
490
  if (handle.tamper === undefined) return
@@ -129,6 +129,11 @@ export interface ActiveTurnOptions {
129
129
  readonly now?: number
130
130
  }
131
131
 
132
+ export interface SessionLogClaimOptions extends ClaimSessionOptions {
133
+ /** Defer torn-tail repair until the first append, after caller admission checks. */
134
+ readonly repairTornTail?: boolean
135
+ }
136
+
132
137
  /**
133
138
  * One session's append-only, hash-chained log: the source of truth for
134
139
  * everything the session did (spec §4). One writer at a time holds its
@@ -143,9 +148,10 @@ export interface SessionLog {
143
148
  * the same name waits like any other. This instance renews its own holding
144
149
  * under the same fence, late or not, unless somebody took the session in
145
150
  * between. A new fence is above the log's highest `gen`. Taking it
146
- * repairs a torn tail first (`log_repaired`).
151
+ * repairs a torn tail first (`log_repaired`) unless `repairTornTail` is false.
152
+ * A caller validating a log owner should defer repair until after that check.
147
153
  */
148
- claim(options: ClaimSessionOptions): Promise<SessionLease | null>
154
+ claim(options: SessionLogClaimOptions): Promise<SessionLease | null>
149
155
  /** Give the lease up; a stale lease releases nothing. */
150
156
  release(lease: SessionLease): Promise<void>
151
157
  /** The current holding, or `null` when never claimed. */
@@ -362,7 +368,7 @@ export class SessionLogCore implements SessionLog {
362
368
 
363
369
  // ── lease ──
364
370
 
365
- async claim(options: ClaimSessionOptions): Promise<SessionLease | null> {
371
+ async claim(options: SessionLogClaimOptions): Promise<SessionLease | null> {
366
372
  if (sessionLeasesReleasedForExit()) throw new SessionLeasesReleasedError()
367
373
  // The log's own highest gen is the floor for a new fence, so lease files
368
374
  // that were lost or cleared cannot mint a fence below records already
@@ -383,7 +389,7 @@ export class SessionLogCore implements SessionLog {
383
389
  if (sessionLeasesReleasedForExit()) throw new SessionLeasesReleasedError()
384
390
  await this.#mutex.run(async () => {
385
391
  await this.#catchUp()
386
- await this.#heal(lease)
392
+ if (options.repairTornTail !== false) await this.#heal(lease)
387
393
  })
388
394
  } catch (error) {
389
395
  // A log this writer cannot append to (a broken chain, a conflict) is
@@ -27,6 +27,26 @@ import type { SpillRef } from './spill.js'
27
27
  * reports, not instructions.
28
28
  */
29
29
 
30
+ /**
31
+ * `message` stamped with `id`, without mutating it: a message read back
32
+ * from the log may be a live object another reader holds too (an in-memory
33
+ * record's own `content`), and only a fresh copy is safe to hand to a
34
+ * caller. `id` always wins over anything already on `message` — a stored
35
+ * `content.id` is leftover from wherever that exact object came from
36
+ * before it was recorded here (a different session's turn, replayed into
37
+ * this one by a test fixture or an import), never this record's own name
38
+ * for it. `undefined` clears it instead: a compaction summary member, or
39
+ * anything else this log never gave a per-message id.
40
+ */
41
+ export function withMessageId<M extends Message>(message: M, id: MessageId | undefined): M {
42
+ if (message.id === id) return message
43
+ if (id === undefined) {
44
+ const { id: _dropped, ...rest } = message
45
+ return rest as M
46
+ }
47
+ return { ...message, id }
48
+ }
49
+
30
50
  /** One message of the folded context. */
31
51
  export interface FoldedMessage {
32
52
  /** Absent for a compaction summary message, which has no record of its own. */
@@ -211,15 +231,21 @@ export async function foldSessionMessages(
211
231
  const spilled = fold.spilledSummary
212
232
  if (spilled !== undefined) {
213
233
  const text = await (options.readSpill ?? spillMissing)(spilled.spill)
214
- out.push(...(JSON.parse(text) as Message[]))
234
+ // A summary member carries no id of its own (`withMessageId`'s doc
235
+ // comment) — same as the inline branch below. A synthesized summary
236
+ // never had one, so this is invisible there; a fork's seeded summary
237
+ // IS the source session's own already-id'd messages (see
238
+ // `seedConversationHistory` in `@namzu/cli`), and without this, a
239
+ // spilled (large) fork's first live turn would read its fold back
240
+ // carrying a DIFFERENT session's ids and fail reconciliation as
241
+ // foreign.
242
+ for (const message of JSON.parse(text) as Message[]) out.push(withMessageId(message, undefined))
215
243
  }
216
244
  for (const entry of fold.entries()) {
217
- if (entry.spill === undefined) {
218
- out.push(entry.message)
219
- continue
220
- }
221
- const text = await (options.readSpill ?? spillMissing)(entry.spill)
222
- out.push(JSON.parse(text) as Message)
245
+ const message = entry.spill
246
+ ? (JSON.parse(await (options.readSpill ?? spillMissing)(entry.spill)) as Message)
247
+ : entry.message
248
+ out.push(withMessageId(message, entry.messageId))
223
249
  }
224
250
  return out
225
251
  }
@@ -24,6 +24,7 @@ export {
24
24
  type LogMedium,
25
25
  type ReadSessionLogOptions,
26
26
  type SessionLog,
27
+ type SessionLogClaimOptions,
27
28
  SessionLogConflictError,
28
29
  SessionLogCore,
29
30
  type SessionLogCoreOptions,
@@ -51,6 +52,7 @@ export {
51
52
  SpillUnavailableError,
52
53
  TurnRuleError,
53
54
  foldSessionMessages,
55
+ withMessageId,
54
56
  } from './fold.js'
55
57
  export { type TornTailRepair, repairRecordDraft } from './heal.js'
56
58
  export {
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Test-only toolset builders, replacing the pattern every test used to
3
+ * repeat by hand: `const tools = new ToolRegistry(); tools.register(a);
4
+ * tools.register(b)`.
5
+ *
6
+ * `ToolRegistry` is gone (plan.md v3 §2); a test that only wants to hand
7
+ * `query()`/`ReactiveAgentConfig`/… a fixed set of tools now builds a
8
+ * `Toolset` instead. `testToolset` covers the common, all-active case; a
9
+ * test that needs a deferred tool wraps a second call with `deferred(...)`
10
+ * (`toolsets/wrappers.ts`) and passes both in the `toolsets` array — there
11
+ * is no single-call equivalent of `register(tool, 'deferred')` here on
12
+ * purpose, since a `Toolset`'s availability is a whole-toolset default, not
13
+ * a per-tool one.
14
+ */
15
+
16
+ import { toolset } from '../toolsets/toolset.js'
17
+ import type { Toolset } from '../toolsets/types.js'
18
+ import type { ToolDefinition } from '../types/tool/index.js'
19
+
20
+ /** A plain, all-active `Toolset` named `'test'`, from a fixed list of tools. */
21
+ export function testToolset(...tools: readonly ToolDefinition[]): Toolset {
22
+ return toolset('test', tools)
23
+ }
@@ -7,6 +7,7 @@ import { killTree } from '../../process/kill-tree.js'
7
7
  import { subscribeToAbort } from '../../utils/abort.js'
8
8
  import { readPositiveIntEnv } from '../../utils/env.js'
9
9
  import {
10
+ type CommandShell,
10
11
  bashToolDialect,
11
12
  hostShellSpawn,
12
13
  sandboxShellSpawn,
@@ -14,13 +15,11 @@ import {
14
15
  } from '../command-shell.js'
15
16
  import { defineTool } from '../defineTool.js'
16
17
  import { scrubInheritedEnv } from '../env-scrub.js'
18
+ import { jsonStringEscapes } from './json-string-hint.js'
17
19
 
18
- // Namzu owns its own bash timeout knob — `NAMZU_BASH_TIMEOUT_MS`.
19
- // The Vandal fallback (`VANDAL_NAMZU_TIMEOUT_MS`) lived here as a
20
- // historical bridge while Namzu was carved out of the Vandal repo,
21
- // but Namzu shouldn't read a consumer's env name. Consumers can
22
- // still alias their own var to `NAMZU_BASH_TIMEOUT_MS` at deploy
23
- // time if they want a unified knob.
20
+ // Namzu owns its own bash timeout knob — `NAMZU_BASH_TIMEOUT_MS` — and
21
+ // reads no consumer's env name. A consumer that wants one knob aliases
22
+ // its own variable to `NAMZU_BASH_TIMEOUT_MS` at deploy time.
24
23
  // Two minutes, not an hour. The old default meant a wedged command held
25
24
  // the turn — and, before per-tool deadlines existed, the whole turn — for
26
25
  // up to 3600s while ignoring Stop entirely. The model can still ask for
@@ -134,20 +133,30 @@ function shellProgress(report?: (message: string) => void) {
134
133
  }
135
134
  }
136
135
 
136
+ /** A progress callback for {@link execHostShell}: one line, per stream, coalesced. */
137
+ export type ExecHostShellProgress = (report: { stream: 'stdout' | 'stderr'; data: string }) => void
138
+
137
139
  /**
138
140
  * Keep the shell's process group until inherited pipes close. Node's exec
139
141
  * timeout/AbortSignal kills only the wrapper and closes its pipes immediately,
140
142
  * leaving the command and its descendants running after the promise settles.
143
+ *
144
+ * Exported so a host running a command line OUTSIDE a live turn — a
145
+ * scheduled job's own script — gets the exact same spawn, dialect,
146
+ * grace-period kill and capped-output behaviour the `bash` tool gives a
147
+ * model's call, rather than a second, drifting copy of it.
141
148
  */
142
- function execHostShell(
149
+ export function execHostShell(
143
150
  command: string,
144
151
  options: {
145
152
  cwd: string
146
153
  env: NodeJS.ProcessEnv
147
154
  timeout: number
148
155
  maxBuffer: number
156
+ /** An interpreter selected and verified by the host for this command. */
157
+ shell?: CommandShell
149
158
  signal?: AbortSignal
150
- onOutput?: ReturnType<typeof shellProgress>
159
+ onOutput?: ExecHostShellProgress
151
160
  },
152
161
  ): Promise<{ stdout: string; stderr: string }> {
153
162
  options.signal?.throwIfAborted()
@@ -155,7 +164,7 @@ function execHostShell(
155
164
  // bash where the host has it, `/bin/sh` where it does not; the
156
165
  // permission rules read the line in the matching dialect. See
157
166
  // `../command-shell.ts`.
158
- const shell = hostShellSpawn(command, options.env)
167
+ const shell = hostShellSpawn(command, options.env, options.shell)
159
168
  const spawnOptions = {
160
169
  cwd: options.cwd,
161
170
  env: shell.env,
@@ -310,6 +319,14 @@ export const BashTool = defineTool({
310
319
  description:
311
320
  'Executes a bash command and returns stdout/stderr output. Command timeout is configurable. The `command` parameter is required — never call this tool with empty arguments. For very long content (e.g. building a large file), prefer `write` for the opening and `edit` with insertLine: "end" for follow-up chunks over a heredoc to avoid hitting the output token limit mid-stream.',
312
321
  inputSchema,
322
+ // A command carries quotes and backslashes of its own, and a heredoc
323
+ // carries newlines: copied into the JSON string raw, they end it.
324
+ malformedInputHint: `Required shape: {"command":"..."}. ${jsonStringEscapes('"command"')}`,
325
+ // The same advice the description gives up front, for the call that did
326
+ // not take it: a heredoc is the long bash call, and a file tool writes the
327
+ // same content in parts.
328
+ truncatedInputHint:
329
+ 'To create a long file, do not use a heredoc: write a short opening with the write tool, then add the rest in parts with edit and insertLine: "end".',
313
330
  category: 'shell',
314
331
  // This tool's own description tells the model to chain with `&&` and `;`,
315
332
  // so a permission rule about it is a rule about several commands more often
@@ -413,7 +430,7 @@ export const BashTool = defineTool({
413
430
  // Sandbox-aware: route through sandbox.exec() when available.
414
431
  //
415
432
  // `context.workingDirectory` is the HOST-side workspace path the
416
- // SDK consumer chose for the turn (Vandal: `/var/lib/vandal/sessions/<task>`),
433
+ // SDK consumer chose for the turn (e.g. `/var/lib/<host>/sessions/<task>`),
417
434
  // which is meaningless inside the sandbox container. Forwarding
418
435
  // it as `cwd` would either land on a path that doesn't exist
419
436
  // (and the worker would `mkdir -p` it inside the container,
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * The browser tools' `url` and `origin` arguments are canonicalised by their
5
5
  * input schema, and the registry hands the gate and the reviewer the schema's
6
- * OUTPUT (`ToolRegistry.prepareExecution`). So a site rule written as
6
+ * OUTPUT (`ToolManager.prepareExecution`, `toolsets/manager.ts`). So a site rule written as
7
7
  * `^https://github\.com(?:[/?#]|$)` is tested against the one spelling the
8
8
  * browser will load, never against `HTTPS://GitHub.com:443/`,
9
9
  * `https://github.com./` or `https://%67ithub.com/`, which name the same page
@@ -503,8 +503,8 @@ function pointModelSchema(description?: string): Record<string, unknown> {
503
503
  type: 'object',
504
504
  ...(description ? { description } : {}),
505
505
  properties: {
506
- x: { type: 'integer' },
507
- y: { type: 'integer' },
506
+ x: { type: 'integer', description: 'Horizontal pixel coordinate, from the left edge.' },
507
+ y: { type: 'integer', description: 'Vertical pixel coordinate, from the top edge.' },
508
508
  },
509
509
  required: ['x', 'y'],
510
510
  additionalProperties: false,
@@ -549,11 +549,17 @@ function hostModelSchema(
549
549
  const fieldSchemas = (forItems: boolean): Record<string, unknown> => {
550
550
  const present = forItems ? items : actions
551
551
  const fields: Record<string, unknown> = {
552
- to: pointModelSchema(),
553
- at: pointModelSchema(),
554
- from: pointModelSchema(),
552
+ to: pointModelSchema(
553
+ 'Destination point: where mouse_move moves the cursor to, or where mouse_drag releases.',
554
+ ),
555
+ at: pointModelSchema('Point the action happens at: where to click, or where to scroll.'),
556
+ from: pointModelSchema('Drag start point, for mouse_drag.'),
555
557
  button: { type: 'string', enum: buttonEnum, description: 'Mouse button; left when omitted.' },
556
- direction: { type: 'string', enum: ['up', 'down', 'left', 'right'] },
558
+ direction: {
559
+ type: 'string',
560
+ enum: ['up', 'down', 'left', 'right'],
561
+ description: 'Which way to scroll.',
562
+ },
557
563
  amount: { type: 'integer', description: 'Positive integer scroll distance.' },
558
564
  text: { type: 'string', description: 'Literal text to type.' },
559
565
  keys: {
@@ -584,10 +590,10 @@ function hostModelSchema(
584
590
  type: 'object',
585
591
  description: 'Area of the screenshot to zoom into, in its pixels.',
586
592
  properties: {
587
- x: { type: 'integer' },
588
- y: { type: 'integer' },
589
- width: { type: 'integer' },
590
- height: { type: 'integer' },
593
+ x: { type: 'integer', description: 'Left edge of the region, in screenshot pixels.' },
594
+ y: { type: 'integer', description: 'Top edge of the region, in screenshot pixels.' },
595
+ width: { type: 'integer', description: 'Width of the region, in screenshot pixels.' },
596
+ height: { type: 'integer', description: 'Height of the region, in screenshot pixels.' },
591
597
  },
592
598
  required: ['x', 'y', 'width', 'height'],
593
599
  additionalProperties: false,
@@ -612,7 +618,11 @@ function hostModelSchema(
612
618
  items: {
613
619
  type: 'object',
614
620
  properties: {
615
- type: { type: 'string', enum: items },
621
+ type: {
622
+ type: 'string',
623
+ enum: items,
624
+ description: 'This batched action.',
625
+ },
616
626
  ...fieldSchemas(true),
617
627
  },
618
628
  required: ['type'],
@@ -8,6 +8,7 @@ import { atomicWriteFile } from './atomic-write-file.js'
8
8
  import { fingerprintContent, staleFileError } from './content-fingerprint.js'
9
9
  import { applyEdit, normalizeEditInput } from './edit-apply.js'
10
10
  import { withFileMutationLock } from './file-mutation-lock.js'
11
+ import { jsonStringEscapes } from './json-string-hint.js'
11
12
 
12
13
  /**
13
14
  * Two schemas, on purpose.
@@ -278,6 +279,9 @@ function recordDrift(context: ToolContext, key: string): void {
278
279
  context.fileReadTracker?.recordDriftObserved?.(key)
279
280
  }
280
281
 
282
+ const EDIT_SHAPES =
283
+ 'Three shapes. Replace: {"path":"file.md","old_string":"exact unique text","new_string":"replacement text"} (optional "replace_all": true). Insert: {"path":"file.md","insertLine":"end","new_string":"text to add"} where insertLine is a non-negative line number or "end". Batch: {"path":"file.md","edits":[{"old_string":"a","new_string":"b"},{"old_string":"c","new_string":"d"}]} applied in order, all or nothing. Exactly one of old_string, insertLine or edits — a call carrying more than one of them is refused rather than resolved.'
284
+
281
285
  export const EditTool = defineTool({
282
286
  name: 'edit',
283
287
  description:
@@ -285,8 +289,14 @@ export const EditTool = defineTool({
285
289
  inputSchema,
286
290
  modelInputSchema,
287
291
  enforceModelInput: true,
288
- validationErrorHint:
289
- 'Three shapes. Replace: {"path":"file.md","old_string":"exact unique text","new_string":"replacement text"} (optional "replace_all": true). Insert: {"path":"file.md","insertLine":"end","new_string":"text to add"} where insertLine is a non-negative line number or "end". Batch: {"path":"file.md","edits":[{"old_string":"a","new_string":"b"},{"old_string":"c","new_string":"d"}]} applied in order, all or nothing. Exactly one of old_string, insertLine or edits — a call carrying more than one of them is refused rather than resolved.',
292
+ validationErrorHint: EDIT_SHAPES,
293
+ // Replacement text is where arguments stop being JSON: a raw newline,
294
+ // quote or backslash copied into the string. The shapes follow, since a
295
+ // malformed call may equally have got those wrong.
296
+ malformedInputHint: `${jsonStringEscapes('"old_string" and "new_string", in "edits" too,')} ${EDIT_SHAPES}`,
297
+ largeStringArguments: { old_string: 12_000, new_string: 12_000 },
298
+ truncatedInputHint:
299
+ 'Split a large change into several edit calls, each replacing a shorter unique span; to add a long section, append it in parts with insertLine: "end".',
290
300
  category: 'filesystem',
291
301
  // Declared so a path outside the turn's roots can be reviewed before the
292
302
  // call runs, rather than refused after. See `ToolDefinition.pathArgument`.
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The advice a tool whose arguments carry raw text gives a model whose call
3
+ * was malformed.
4
+ *
5
+ * A file body, a replacement or a shell command is copied into a JSON string
6
+ * as it stands, and the characters JSON does not allow there unescaped (a
7
+ * newline, a tab, a double quote, a backslash) are what make such a call
8
+ * unreadable. The tool's shape, which is all a validation hint gives, does
9
+ * not say that.
10
+ *
11
+ * @param where - The arguments the text goes into, as the model sees them,
12
+ * e.g. `"content"`.
13
+ */
14
+ export function jsonStringEscapes(where: string): string {
15
+ return `Every character of ${where} goes inside a JSON string: write a newline as \\n, a tab as \\t, a double quote as \\" and a backslash as \\\\.`
16
+ }
@@ -40,39 +40,21 @@ export const SearchToolsTool = defineTool({
40
40
 
41
41
  const allowed = context.allowedTools !== undefined ? new Set(context.allowedTools) : null
42
42
  // `searchDeferred` returns a ranked list (score-descending), so slicing
43
- // the head is a true top-k activation, not an arbitrary subset.
43
+ // the head is a true top-k reveal, not an arbitrary subset.
44
44
  const ranked = context.toolRegistry
45
45
  .searchDeferred(input.query)
46
46
  .filter((tool) => !allowed || allowed.has(tool.name))
47
47
 
48
48
  if (ranked.length === 0) {
49
- const active = context.toolRegistry
50
- .searchActive?.(input.query)
51
- .filter(
52
- (tool) =>
53
- (!allowed || allowed.has(tool.name)) &&
54
- context.toolRegistry?.getAvailability(tool.name) === 'active',
55
- )
56
- const activeReceipt =
57
- active === undefined
58
- ? 'This registry cannot search active tools.'
59
- : active.length === 0
60
- ? 'No matching active tools were found.'
61
- : `Already active matching tools (up to ${ACTIVATION_TOP_K}):\n${active
62
- .slice(0, ACTIVATION_TOP_K)
63
- .map((tool) => `- ${tool.name}`)
64
- .join('\n')}`
65
49
  return {
66
50
  success: true,
67
- output: `No deferred tools matching "${input.query}". ${activeReceipt}`,
51
+ output: `No deferred tools matching "${input.query}".`,
68
52
  }
69
53
  }
70
54
 
71
55
  const activated = ranked.slice(0, ACTIVATION_TOP_K)
72
56
  const nearMisses = ranked.slice(ACTIVATION_TOP_K, ACTIVATION_TOP_K + NEAR_MISS_LIMIT)
73
57
 
74
- context.toolRegistry.activate(activated.map((t) => t.name))
75
-
76
58
  const descriptions = activated.map((t) => `- ${t.name}: ${t.description}`).join('\n')
77
59
  const sections = [`Activated ${activated.length} tool(s):\n${descriptions}`]
78
60
 
@@ -91,6 +73,11 @@ export const SearchToolsTool = defineTool({
91
73
  return {
92
74
  success: true,
93
75
  output: sections.join('\n\n'),
76
+ // No `activate()` call: the manager derives availability from what a
77
+ // tool message REVEALS (`ToolResult.reveals`, persisted as
78
+ // `ToolMessage.revealedTools`), not from a mutation made here. See
79
+ // `toolsets/manager.ts`'s `availability()`.
80
+ reveals: activated.map((t) => t.name),
94
81
  data: {
95
82
  activated: activated.map((t) => t.name),
96
83
  count: activated.length,
@@ -8,6 +8,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'
10
10
  import { fileWriteResult } from './file-write-result.js'
11
+ import { jsonStringEscapes } from './json-string-hint.js'
11
12
 
12
13
  const inputSchema = z
13
14
  .object({
@@ -76,6 +77,17 @@ export const WriteFileTool = defineTool({
76
77
  enforceModelInput: true,
77
78
  validationErrorHint:
78
79
  'Required shape: {"path":"file.md","content":"complete file body"}. Pass the whole body, not a diff.',
80
+ // A file body is where arguments stop being JSON: a raw newline, quote or
81
+ // backslash copied into the string. The shape alone, which is what the
82
+ // validation hint would have given, does not say that.
83
+ malformedInputHint: `Required shape: {"path":"file.md","content":"complete file body"}. ${jsonStringEscapes('"content"')}`,
84
+ // What a cut-off `write` needs to hear, and only a cut-off one: the
85
+ // kernel's message for unreadable arguments used to carry this recipe for
86
+ // every tool and every failure, malformed JSON and a question tool's
87
+ // included.
88
+ largeStringArguments: { content: 12_000 },
89
+ truncatedInputHint:
90
+ 'For a long file, write a short opening that ends with a unique marker line, then extend it with edit calls that each replace the marker with the next section followed by the marker.',
79
91
  category: 'filesystem',
80
92
  // Declared so a path outside the turn's roots can be reviewed before the
81
93
  // call runs, rather than refused after. See `ToolDefinition.pathArgument`.
@@ -35,7 +35,7 @@
35
35
  */
36
36
 
37
37
  import { constants, accessSync } from 'node:fs'
38
- import { delimiter, join } from 'node:path'
38
+ import { delimiter, isAbsolute, join } from 'node:path'
39
39
 
40
40
  import type { ShellDialect } from '../types/tool/index.js'
41
41
 
@@ -57,6 +57,7 @@ export interface CommandShellProbe {
57
57
  }
58
58
 
59
59
  const WELL_KNOWN_BASH = ['/bin/bash', '/usr/bin/bash']
60
+ const WELL_KNOWN_SH = ['/bin/sh', '/usr/bin/sh']
60
61
 
61
62
  /** Environment variables that change what a bash command line means. */
62
63
  const BASH_STARTUP_VARIABLES = new Set(['BASH_ENV', 'ENV', 'SHELLOPTS', 'BASHOPTS'])
@@ -83,6 +84,41 @@ export function findCommandShell(probe: CommandShellProbe): CommandShell {
83
84
  return { path: '/bin/sh', dialect: 'sh', source: 'sh' }
84
85
  }
85
86
 
87
+ /**
88
+ * An explicitly requested interpreter for a host script. Unlike the live
89
+ * `bash` tool's automatic choice, this never substitutes bash for sh (or sh
90
+ * for bash). A matching `NAMZU_BASH_SHELL` override is authoritative: if it
91
+ * disappeared, an already-confirmed script must stop rather than silently
92
+ * switch to a different executable.
93
+ */
94
+ export function findCommandShellForDialect(
95
+ dialect: 'bash' | 'sh',
96
+ probe: CommandShellProbe,
97
+ ): CommandShell | undefined {
98
+ if (probe.platform === 'win32') return undefined
99
+ const override = probe.env.NAMZU_BASH_SHELL
100
+ if (override) {
101
+ const name = override.slice(override.lastIndexOf('/') + 1)
102
+ if (name === dialect) {
103
+ return isAbsolute(override) && probe.isExecutable(override)
104
+ ? { path: override, dialect, source: 'override' }
105
+ : undefined
106
+ }
107
+ }
108
+ const name = dialect
109
+ // A scheduled script's interpreter must not drift merely because the
110
+ // service's PATH gained another same-named binary after confirmation.
111
+ for (const candidate of dialect === 'bash' ? WELL_KNOWN_BASH : WELL_KNOWN_SH) {
112
+ if (probe.isExecutable(candidate)) return { path: candidate, dialect, source: dialect }
113
+ }
114
+ for (const directory of (probe.env.PATH ?? '').split(delimiter)) {
115
+ if (directory === '' || !directory.startsWith('/')) continue
116
+ const candidate = join(directory, name)
117
+ if (probe.isExecutable(candidate)) return { path: candidate, dialect, source: dialect }
118
+ }
119
+ return undefined
120
+ }
121
+
86
122
  function isExecutable(path: string): boolean {
87
123
  try {
88
124
  accessSync(path, constants.X_OK)
@@ -105,6 +141,15 @@ export function hostCommandShell(): CommandShell {
105
141
  return resolved
106
142
  }
107
143
 
144
+ /** Re-check the requested executable each time a job is confirmed or fired. */
145
+ export function installedCommandShellForDialect(dialect: 'bash' | 'sh'): CommandShell | undefined {
146
+ return findCommandShellForDialect(dialect, {
147
+ env: process.env,
148
+ platform: process.platform,
149
+ isExecutable,
150
+ })
151
+ }
152
+
108
153
  /** Replace the resolved host shell; `undefined` resolves again on next use. For tests. */
109
154
  export function setHostCommandShellForTesting(shell: CommandShell | undefined): void {
110
155
  resolved = shell
@@ -3,6 +3,7 @@ import { z } from 'zod'
3
3
  import type { AgentRuntimeContext } from '../../types/agent/base.js'
4
4
  import type { CreateTaskOptions, TaskHandle, TaskScheduler } from '../../types/agent/scheduler.js'
5
5
  import type { ToolDefinition } from '../../types/tool/index.js'
6
+ import { jsonStringEscapes } from '../builtins/json-string-hint.js'
6
7
  import { defineTool } from '../defineTool.js'
7
8
  import { wrapUntrusted } from '../untrusted-envelope.js'
8
9
  import { failureLabel, taskSucceeded } from './outcome.js'
@@ -103,6 +104,11 @@ export function buildAgentTool(opts: AgentToolOptions): ToolDefinition {
103
104
  .describe(`Which subagent to run (defaults to the only one: ${agentIds[0]})`)
104
105
  : subagentTypeEnum.describe('Which subagent to run'),
105
106
  }),
107
+ largeStringArguments: { prompt: 12_000 },
108
+ truncatedInputHint:
109
+ 'Put long material in a file the subagent can read and name the file in the prompt instead of pasting its content.',
110
+ // A delegated prompt is long free text, copied into a JSON string.
111
+ malformedInputHint: jsonStringEscapes('"prompt"'),
106
112
  category: 'custom',
107
113
  permissions: [],
108
114
  readOnly: false,