@namzu/sdk 0.6.0 → 1.1.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 (429) hide show
  1. package/CHANGELOG.md +529 -0
  2. package/dist/advisory/executor.d.ts.map +1 -1
  3. package/dist/advisory/executor.js +9 -2
  4. package/dist/advisory/executor.js.map +1 -1
  5. package/dist/advisory/executor.test.d.ts +2 -1
  6. package/dist/advisory/executor.test.d.ts.map +1 -1
  7. package/dist/advisory/executor.test.js +7 -4
  8. package/dist/advisory/executor.test.js.map +1 -1
  9. package/dist/agents/ReactiveAgent.d.ts.map +1 -1
  10. package/dist/agents/ReactiveAgent.js +7 -0
  11. package/dist/agents/ReactiveAgent.js.map +1 -1
  12. package/dist/agents/SupervisorAgent.d.ts +22 -1
  13. package/dist/agents/SupervisorAgent.d.ts.map +1 -1
  14. package/dist/agents/SupervisorAgent.js +54 -14
  15. package/dist/agents/SupervisorAgent.js.map +1 -1
  16. package/dist/agents/__tests__/supervisor-ledger.test.d.ts +2 -0
  17. package/dist/agents/__tests__/supervisor-ledger.test.d.ts.map +1 -0
  18. package/dist/agents/__tests__/supervisor-ledger.test.js +131 -0
  19. package/dist/agents/__tests__/supervisor-ledger.test.js.map +1 -0
  20. package/dist/bridge/sse/mapper.test.js +2 -2
  21. package/dist/config/runtime.d.ts +24 -0
  22. package/dist/config/runtime.d.ts.map +1 -1
  23. package/dist/config/runtime.js +9 -0
  24. package/dist/config/runtime.js.map +1 -1
  25. package/dist/connector/builtins/webhook.test.js +17 -0
  26. package/dist/connector/builtins/webhook.test.js.map +1 -1
  27. package/dist/connector/index.d.ts +1 -0
  28. package/dist/connector/index.d.ts.map +1 -1
  29. package/dist/connector/index.js +1 -0
  30. package/dist/connector/index.js.map +1 -1
  31. package/dist/connector/mcp/client.d.ts.map +1 -1
  32. package/dist/connector/mcp/client.js +4 -0
  33. package/dist/connector/mcp/client.js.map +1 -1
  34. package/dist/connector/mcp/index.d.ts +1 -0
  35. package/dist/connector/mcp/index.d.ts.map +1 -1
  36. package/dist/connector/mcp/index.js +1 -0
  37. package/dist/connector/mcp/index.js.map +1 -1
  38. package/dist/connector/mcp/streamable-http.d.ts +22 -0
  39. package/dist/connector/mcp/streamable-http.d.ts.map +1 -0
  40. package/dist/connector/mcp/streamable-http.js +128 -0
  41. package/dist/connector/mcp/streamable-http.js.map +1 -0
  42. package/dist/connector/mcp/streamable-http.test.d.ts +2 -0
  43. package/dist/connector/mcp/streamable-http.test.d.ts.map +1 -0
  44. package/dist/connector/mcp/streamable-http.test.js +132 -0
  45. package/dist/connector/mcp/streamable-http.test.js.map +1 -0
  46. package/dist/constants/compaction/index.d.ts.map +1 -1
  47. package/dist/constants/compaction/index.js +8 -3
  48. package/dist/constants/compaction/index.js.map +1 -1
  49. package/dist/constants/sandbox/index.d.ts +21 -0
  50. package/dist/constants/sandbox/index.d.ts.map +1 -1
  51. package/dist/constants/sandbox/index.js +30 -0
  52. package/dist/constants/sandbox/index.js.map +1 -1
  53. package/dist/constants/tools/index.d.ts.map +1 -1
  54. package/dist/constants/tools/index.js +33 -2
  55. package/dist/constants/tools/index.js.map +1 -1
  56. package/dist/manager/run/persistence.d.ts.map +1 -1
  57. package/dist/manager/run/persistence.js +35 -5
  58. package/dist/manager/run/persistence.js.map +1 -1
  59. package/dist/persona/assembler.d.ts +1 -0
  60. package/dist/persona/assembler.d.ts.map +1 -1
  61. package/dist/persona/assembler.js +37 -6
  62. package/dist/persona/assembler.js.map +1 -1
  63. package/dist/provider/collect.d.ts.map +1 -1
  64. package/dist/provider/collect.js +4 -1
  65. package/dist/provider/collect.js.map +1 -1
  66. package/dist/provider/collect.test.js +2 -2
  67. package/dist/public-runtime.d.ts +6 -5
  68. package/dist/public-runtime.d.ts.map +1 -1
  69. package/dist/public-runtime.js +6 -5
  70. package/dist/public-runtime.js.map +1 -1
  71. package/dist/public-tools.d.ts +2 -0
  72. package/dist/public-tools.d.ts.map +1 -1
  73. package/dist/public-tools.js +2 -0
  74. package/dist/public-tools.js.map +1 -1
  75. package/dist/public-types.d.ts +3 -0
  76. package/dist/public-types.d.ts.map +1 -1
  77. package/dist/registry/index.d.ts +2 -0
  78. package/dist/registry/index.d.ts.map +1 -1
  79. package/dist/registry/index.js +1 -0
  80. package/dist/registry/index.js.map +1 -1
  81. package/dist/registry/tool/execute.d.ts +27 -0
  82. package/dist/registry/tool/execute.d.ts.map +1 -1
  83. package/dist/registry/tool/execute.js +192 -7
  84. package/dist/registry/tool/execute.js.map +1 -1
  85. package/dist/registry/tool/execute.test.d.ts +9 -4
  86. package/dist/registry/tool/execute.test.d.ts.map +1 -1
  87. package/dist/registry/tool/execute.test.js +178 -7
  88. package/dist/registry/tool/execute.test.js.map +1 -1
  89. package/dist/registry/toolset/catalog.d.ts +42 -0
  90. package/dist/registry/toolset/catalog.d.ts.map +1 -0
  91. package/dist/registry/toolset/catalog.js +217 -0
  92. package/dist/registry/toolset/catalog.js.map +1 -0
  93. package/dist/registry/toolset/catalog.test.d.ts +2 -0
  94. package/dist/registry/toolset/catalog.test.d.ts.map +1 -0
  95. package/dist/registry/toolset/catalog.test.js +147 -0
  96. package/dist/registry/toolset/catalog.test.js.map +1 -0
  97. package/dist/runtime/query/__tests__/deferred-tools.test.d.ts +2 -0
  98. package/dist/runtime/query/__tests__/deferred-tools.test.d.ts.map +1 -0
  99. package/dist/runtime/query/__tests__/deferred-tools.test.js +185 -0
  100. package/dist/runtime/query/__tests__/deferred-tools.test.js.map +1 -0
  101. package/dist/runtime/query/__tests__/executor-concurrency.test.d.ts +2 -0
  102. package/dist/runtime/query/__tests__/executor-concurrency.test.d.ts.map +1 -0
  103. package/dist/runtime/query/__tests__/executor-concurrency.test.js +98 -0
  104. package/dist/runtime/query/__tests__/executor-concurrency.test.js.map +1 -0
  105. package/dist/runtime/query/__tests__/executor-plugin-hooks.test.js +38 -3
  106. package/dist/runtime/query/__tests__/executor-plugin-hooks.test.js.map +1 -1
  107. package/dist/runtime/query/__tests__/long-document-flow.test.d.ts +2 -0
  108. package/dist/runtime/query/__tests__/long-document-flow.test.d.ts.map +1 -0
  109. package/dist/runtime/query/__tests__/long-document-flow.test.js +154 -0
  110. package/dist/runtime/query/__tests__/long-document-flow.test.js.map +1 -0
  111. package/dist/runtime/query/__tests__/prompt.test.js +51 -2
  112. package/dist/runtime/query/__tests__/prompt.test.js.map +1 -1
  113. package/dist/runtime/query/__tests__/stream-recovery.test.d.ts +2 -0
  114. package/dist/runtime/query/__tests__/stream-recovery.test.d.ts.map +1 -0
  115. package/dist/runtime/query/__tests__/stream-recovery.test.js +126 -0
  116. package/dist/runtime/query/__tests__/stream-recovery.test.js.map +1 -0
  117. package/dist/runtime/query/continuation.d.ts +16 -0
  118. package/dist/runtime/query/continuation.d.ts.map +1 -0
  119. package/dist/runtime/query/continuation.js +16 -0
  120. package/dist/runtime/query/continuation.js.map +1 -0
  121. package/dist/runtime/query/executor.d.ts +3 -0
  122. package/dist/runtime/query/executor.d.ts.map +1 -1
  123. package/dist/runtime/query/executor.js +71 -3
  124. package/dist/runtime/query/executor.js.map +1 -1
  125. package/dist/runtime/query/index.d.ts +9 -0
  126. package/dist/runtime/query/index.d.ts.map +1 -1
  127. package/dist/runtime/query/index.js +42 -5
  128. package/dist/runtime/query/index.js.map +1 -1
  129. package/dist/runtime/query/iteration/index.d.ts +24 -0
  130. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  131. package/dist/runtime/query/iteration/index.js +326 -66
  132. package/dist/runtime/query/iteration/index.js.map +1 -1
  133. package/dist/runtime/query/iteration/phases/checkpoint.d.ts.map +1 -1
  134. package/dist/runtime/query/iteration/phases/checkpoint.js +2 -2
  135. package/dist/runtime/query/iteration/phases/checkpoint.js.map +1 -1
  136. package/dist/runtime/query/iteration/phases/compaction.d.ts +8 -0
  137. package/dist/runtime/query/iteration/phases/compaction.d.ts.map +1 -1
  138. package/dist/runtime/query/iteration/phases/compaction.js +84 -3
  139. package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
  140. package/dist/runtime/query/iteration/phases/context.d.ts +22 -0
  141. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  142. package/dist/runtime/query/iteration/phases/context.js +53 -0
  143. package/dist/runtime/query/iteration/phases/context.js.map +1 -1
  144. package/dist/runtime/query/iteration/phases/hitl-abort-race.test.d.ts +2 -0
  145. package/dist/runtime/query/iteration/phases/hitl-abort-race.test.d.ts.map +1 -0
  146. package/dist/runtime/query/iteration/phases/hitl-abort-race.test.js +73 -0
  147. package/dist/runtime/query/iteration/phases/hitl-abort-race.test.js.map +1 -0
  148. package/dist/runtime/query/iteration/phases/hitl-answer-question.test.d.ts +2 -0
  149. package/dist/runtime/query/iteration/phases/hitl-answer-question.test.d.ts.map +1 -0
  150. package/dist/runtime/query/iteration/phases/hitl-answer-question.test.js +120 -0
  151. package/dist/runtime/query/iteration/phases/hitl-answer-question.test.js.map +1 -0
  152. package/dist/runtime/query/iteration/phases/tool-review.d.ts +1 -1
  153. package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
  154. package/dist/runtime/query/iteration/phases/tool-review.js +7 -2
  155. package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
  156. package/dist/runtime/query/iteration/phases/working-memory-compaction.test.d.ts +19 -0
  157. package/dist/runtime/query/iteration/phases/working-memory-compaction.test.d.ts.map +1 -0
  158. package/dist/runtime/query/iteration/phases/working-memory-compaction.test.js +177 -0
  159. package/dist/runtime/query/iteration/phases/working-memory-compaction.test.js.map +1 -0
  160. package/dist/runtime/query/iteration/phases/working-memory.d.ts +31 -0
  161. package/dist/runtime/query/iteration/phases/working-memory.d.ts.map +1 -0
  162. package/dist/runtime/query/iteration/phases/working-memory.js +81 -0
  163. package/dist/runtime/query/iteration/phases/working-memory.js.map +1 -0
  164. package/dist/runtime/query/prompt.d.ts.map +1 -1
  165. package/dist/runtime/query/prompt.js +21 -1
  166. package/dist/runtime/query/prompt.js.map +1 -1
  167. package/dist/runtime/query/tooling.d.ts +1 -0
  168. package/dist/runtime/query/tooling.d.ts.map +1 -1
  169. package/dist/runtime/query/tooling.js +1 -0
  170. package/dist/runtime/query/tooling.js.map +1 -1
  171. package/dist/sandbox/provider/local.d.ts.map +1 -1
  172. package/dist/sandbox/provider/local.js +32 -1
  173. package/dist/sandbox/provider/local.js.map +1 -1
  174. package/dist/session/workspace/__tests__/shared-run.test.d.ts +2 -0
  175. package/dist/session/workspace/__tests__/shared-run.test.d.ts.map +1 -0
  176. package/dist/session/workspace/__tests__/shared-run.test.js +147 -0
  177. package/dist/session/workspace/__tests__/shared-run.test.js.map +1 -0
  178. package/dist/session/workspace/index.d.ts +2 -0
  179. package/dist/session/workspace/index.d.ts.map +1 -1
  180. package/dist/session/workspace/index.js +1 -0
  181. package/dist/session/workspace/index.js.map +1 -1
  182. package/dist/session/workspace/shared-run.d.ts +81 -0
  183. package/dist/session/workspace/shared-run.d.ts.map +1 -0
  184. package/dist/session/workspace/shared-run.js +252 -0
  185. package/dist/session/workspace/shared-run.js.map +1 -0
  186. package/dist/skills/loader.d.ts.map +1 -1
  187. package/dist/skills/loader.js +36 -6
  188. package/dist/skills/loader.js.map +1 -1
  189. package/dist/skills/loader.test.d.ts +2 -0
  190. package/dist/skills/loader.test.d.ts.map +1 -0
  191. package/dist/skills/loader.test.js +65 -0
  192. package/dist/skills/loader.test.js.map +1 -0
  193. package/dist/streaming/coalesce.test.js +1 -1
  194. package/dist/streaming/coalesce.test.js.map +1 -1
  195. package/dist/tools/builtins/__tests__/edit.test.d.ts +2 -0
  196. package/dist/tools/builtins/__tests__/edit.test.d.ts.map +1 -0
  197. package/dist/tools/builtins/__tests__/edit.test.js +38 -0
  198. package/dist/tools/builtins/__tests__/edit.test.js.map +1 -0
  199. package/dist/tools/builtins/__tests__/payload-budget.test.d.ts +2 -0
  200. package/dist/tools/builtins/__tests__/payload-budget.test.d.ts.map +1 -0
  201. package/dist/tools/builtins/__tests__/payload-budget.test.js +70 -0
  202. package/dist/tools/builtins/__tests__/payload-budget.test.js.map +1 -0
  203. package/dist/tools/builtins/__tests__/read-file.test.d.ts +2 -0
  204. package/dist/tools/builtins/__tests__/read-file.test.d.ts.map +1 -0
  205. package/dist/tools/builtins/__tests__/read-file.test.js +33 -0
  206. package/dist/tools/builtins/__tests__/read-file.test.js.map +1 -0
  207. package/dist/tools/builtins/__tests__/verify-outputs.test.d.ts +2 -0
  208. package/dist/tools/builtins/__tests__/verify-outputs.test.d.ts.map +1 -0
  209. package/dist/tools/builtins/__tests__/verify-outputs.test.js +52 -0
  210. package/dist/tools/builtins/__tests__/verify-outputs.test.js.map +1 -0
  211. package/dist/tools/builtins/__tests__/write-file.test.d.ts +2 -0
  212. package/dist/tools/builtins/__tests__/write-file.test.d.ts.map +1 -0
  213. package/dist/tools/builtins/__tests__/write-file.test.js +74 -0
  214. package/dist/tools/builtins/__tests__/write-file.test.js.map +1 -0
  215. package/dist/tools/builtins/bash.d.ts.map +1 -1
  216. package/dist/tools/builtins/bash.js +40 -7
  217. package/dist/tools/builtins/bash.js.map +1 -1
  218. package/dist/tools/builtins/edit.d.ts +5 -2
  219. package/dist/tools/builtins/edit.d.ts.map +1 -1
  220. package/dist/tools/builtins/edit.js +114 -18
  221. package/dist/tools/builtins/edit.js.map +1 -1
  222. package/dist/tools/builtins/index.d.ts +1 -0
  223. package/dist/tools/builtins/index.d.ts.map +1 -1
  224. package/dist/tools/builtins/index.js +13 -13
  225. package/dist/tools/builtins/index.js.map +1 -1
  226. package/dist/tools/builtins/read-file.d.ts +1 -0
  227. package/dist/tools/builtins/read-file.d.ts.map +1 -1
  228. package/dist/tools/builtins/read-file.js +73 -10
  229. package/dist/tools/builtins/read-file.js.map +1 -1
  230. package/dist/tools/builtins/search-tools.d.ts.map +1 -1
  231. package/dist/tools/builtins/search-tools.js +35 -7
  232. package/dist/tools/builtins/search-tools.js.map +1 -1
  233. package/dist/tools/builtins/verify-outputs.d.ts +5 -0
  234. package/dist/tools/builtins/verify-outputs.d.ts.map +1 -0
  235. package/dist/tools/builtins/verify-outputs.js +103 -0
  236. package/dist/tools/builtins/verify-outputs.js.map +1 -0
  237. package/dist/tools/builtins/write-file.d.ts +3 -2
  238. package/dist/tools/builtins/write-file.d.ts.map +1 -1
  239. package/dist/tools/builtins/write-file.js +72 -12
  240. package/dist/tools/builtins/write-file.js.map +1 -1
  241. package/dist/tools/coordinator/__tests__/agent.test.d.ts +15 -0
  242. package/dist/tools/coordinator/__tests__/agent.test.d.ts.map +1 -0
  243. package/dist/tools/coordinator/__tests__/agent.test.js +142 -0
  244. package/dist/tools/coordinator/__tests__/agent.test.js.map +1 -0
  245. package/dist/tools/coordinator/__tests__/approve-plan.test.d.ts +2 -0
  246. package/dist/tools/coordinator/__tests__/approve-plan.test.d.ts.map +1 -0
  247. package/dist/tools/coordinator/__tests__/approve-plan.test.js +114 -0
  248. package/dist/tools/coordinator/__tests__/approve-plan.test.js.map +1 -0
  249. package/dist/tools/coordinator/__tests__/ask-user-question.test.d.ts +2 -0
  250. package/dist/tools/coordinator/__tests__/ask-user-question.test.d.ts.map +1 -0
  251. package/dist/tools/coordinator/__tests__/ask-user-question.test.js +309 -0
  252. package/dist/tools/coordinator/__tests__/ask-user-question.test.js.map +1 -0
  253. package/dist/tools/coordinator/__tests__/task-list.test.d.ts +13 -0
  254. package/dist/tools/coordinator/__tests__/task-list.test.d.ts.map +1 -0
  255. package/dist/tools/coordinator/__tests__/task-list.test.js +162 -0
  256. package/dist/tools/coordinator/__tests__/task-list.test.js.map +1 -0
  257. package/dist/tools/coordinator/agent.d.ts +34 -0
  258. package/dist/tools/coordinator/agent.d.ts.map +1 -0
  259. package/dist/tools/coordinator/agent.js +107 -0
  260. package/dist/tools/coordinator/agent.js.map +1 -0
  261. package/dist/tools/coordinator/index.d.ts +15 -0
  262. package/dist/tools/coordinator/index.d.ts.map +1 -1
  263. package/dist/tools/coordinator/index.js +305 -35
  264. package/dist/tools/coordinator/index.js.map +1 -1
  265. package/dist/types/agent/base.d.ts +8 -0
  266. package/dist/types/agent/base.d.ts.map +1 -1
  267. package/dist/types/agent/index.d.ts +1 -0
  268. package/dist/types/agent/index.d.ts.map +1 -1
  269. package/dist/types/agent/index.js +1 -0
  270. package/dist/types/agent/index.js.map +1 -1
  271. package/dist/types/agent/reactive.d.ts +38 -0
  272. package/dist/types/agent/reactive.d.ts.map +1 -1
  273. package/dist/types/agent/supervisor.d.ts +32 -0
  274. package/dist/types/agent/supervisor.d.ts.map +1 -1
  275. package/dist/types/agent/working-memory.d.ts +29 -0
  276. package/dist/types/agent/working-memory.d.ts.map +1 -0
  277. package/dist/types/agent/working-memory.js +2 -0
  278. package/dist/types/agent/working-memory.js.map +1 -0
  279. package/dist/types/common/index.d.ts +10 -0
  280. package/dist/types/common/index.d.ts.map +1 -1
  281. package/dist/types/common/index.js +18 -0
  282. package/dist/types/common/index.js.map +1 -1
  283. package/dist/types/common/usage-merge.test.d.ts +2 -0
  284. package/dist/types/common/usage-merge.test.d.ts.map +1 -0
  285. package/dist/types/common/usage-merge.test.js +48 -0
  286. package/dist/types/common/usage-merge.test.js.map +1 -0
  287. package/dist/types/connector/mcp.d.ts +9 -2
  288. package/dist/types/connector/mcp.d.ts.map +1 -1
  289. package/dist/types/hitl/index.d.ts +42 -0
  290. package/dist/types/hitl/index.d.ts.map +1 -1
  291. package/dist/types/hitl/index.js +11 -0
  292. package/dist/types/hitl/index.js.map +1 -1
  293. package/dist/types/message/index.d.ts +22 -1
  294. package/dist/types/message/index.d.ts.map +1 -1
  295. package/dist/types/message/index.js +7 -2
  296. package/dist/types/message/index.js.map +1 -1
  297. package/dist/types/provider/chat.d.ts +11 -9
  298. package/dist/types/provider/chat.d.ts.map +1 -1
  299. package/dist/types/run/events.d.ts +6 -0
  300. package/dist/types/run/events.d.ts.map +1 -1
  301. package/dist/types/run/events.js.map +1 -1
  302. package/dist/types/sandbox/index.d.ts +193 -0
  303. package/dist/types/sandbox/index.d.ts.map +1 -1
  304. package/dist/types/sandbox/index.js.map +1 -1
  305. package/dist/types/skills/index.d.ts +2 -0
  306. package/dist/types/skills/index.d.ts.map +1 -1
  307. package/dist/types/tool/index.d.ts +22 -0
  308. package/dist/types/tool/index.d.ts.map +1 -1
  309. package/dist/types/toolset/index.d.ts +71 -0
  310. package/dist/types/toolset/index.d.ts.map +1 -0
  311. package/dist/types/toolset/index.js +2 -0
  312. package/dist/types/toolset/index.js.map +1 -0
  313. package/dist/types/workspace/index.d.ts +1 -0
  314. package/dist/types/workspace/index.d.ts.map +1 -1
  315. package/dist/types/workspace/shared-run.d.ts +61 -0
  316. package/dist/types/workspace/shared-run.d.ts.map +1 -0
  317. package/dist/types/workspace/shared-run.js +2 -0
  318. package/dist/types/workspace/shared-run.js.map +1 -0
  319. package/dist/verification/index.d.ts +1 -0
  320. package/dist/verification/index.d.ts.map +1 -1
  321. package/dist/verification/index.js +1 -0
  322. package/dist/verification/index.js.map +1 -1
  323. package/dist/verification/presets.d.ts +53 -0
  324. package/dist/verification/presets.d.ts.map +1 -0
  325. package/dist/verification/presets.js +70 -0
  326. package/dist/verification/presets.js.map +1 -0
  327. package/dist/verification/presets.test.d.ts +16 -0
  328. package/dist/verification/presets.test.d.ts.map +1 -0
  329. package/dist/verification/presets.test.js +79 -0
  330. package/dist/verification/presets.test.js.map +1 -0
  331. package/dist/version.d.ts.map +1 -1
  332. package/dist/version.js +25 -4
  333. package/dist/version.js.map +1 -1
  334. package/package.json +3 -2
  335. package/src/advisory/executor.test.ts +7 -4
  336. package/src/advisory/executor.ts +11 -2
  337. package/src/agents/ReactiveAgent.ts +7 -0
  338. package/src/agents/SupervisorAgent.ts +63 -16
  339. package/src/agents/__tests__/supervisor-ledger.test.ts +185 -0
  340. package/src/bridge/sse/mapper.test.ts +2 -2
  341. package/src/config/runtime.ts +9 -0
  342. package/src/connector/builtins/webhook.test.ts +21 -0
  343. package/src/connector/index.ts +1 -0
  344. package/src/connector/mcp/client.ts +4 -0
  345. package/src/connector/mcp/index.ts +1 -0
  346. package/src/connector/mcp/streamable-http.test.ts +169 -0
  347. package/src/connector/mcp/streamable-http.ts +152 -0
  348. package/src/constants/compaction/index.ts +8 -3
  349. package/src/constants/sandbox/index.ts +37 -0
  350. package/src/constants/tools/index.ts +33 -2
  351. package/src/manager/run/persistence.ts +34 -6
  352. package/src/persona/assembler.ts +43 -8
  353. package/src/provider/collect.test.ts +2 -2
  354. package/src/provider/collect.ts +4 -1
  355. package/src/public-runtime.ts +15 -1
  356. package/src/public-tools.ts +2 -0
  357. package/src/public-types.ts +7 -0
  358. package/src/registry/index.ts +7 -0
  359. package/src/registry/tool/execute.test.ts +211 -7
  360. package/src/registry/tool/execute.ts +199 -11
  361. package/src/registry/toolset/catalog.test.ts +165 -0
  362. package/src/registry/toolset/catalog.ts +283 -0
  363. package/src/runtime/query/__tests__/deferred-tools.test.ts +230 -0
  364. package/src/runtime/query/__tests__/executor-concurrency.test.ts +122 -0
  365. package/src/runtime/query/__tests__/executor-plugin-hooks.test.ts +48 -3
  366. package/src/runtime/query/__tests__/long-document-flow.test.ts +180 -0
  367. package/src/runtime/query/__tests__/prompt.test.ts +55 -2
  368. package/src/runtime/query/__tests__/stream-recovery.test.ts +156 -0
  369. package/src/runtime/query/continuation.ts +16 -0
  370. package/src/runtime/query/executor.ts +82 -13
  371. package/src/runtime/query/index.ts +58 -5
  372. package/src/runtime/query/iteration/index.ts +361 -74
  373. package/src/runtime/query/iteration/phases/checkpoint.ts +7 -2
  374. package/src/runtime/query/iteration/phases/compaction.ts +89 -3
  375. package/src/runtime/query/iteration/phases/context.ts +68 -0
  376. package/src/runtime/query/iteration/phases/hitl-abort-race.test.ts +86 -0
  377. package/src/runtime/query/iteration/phases/hitl-answer-question.test.ts +139 -0
  378. package/src/runtime/query/iteration/phases/tool-review.ts +7 -3
  379. package/src/runtime/query/iteration/phases/working-memory-compaction.test.ts +215 -0
  380. package/src/runtime/query/iteration/phases/working-memory.ts +86 -0
  381. package/src/runtime/query/prompt.ts +17 -1
  382. package/src/runtime/query/tooling.ts +2 -0
  383. package/src/sandbox/provider/local.ts +33 -0
  384. package/src/session/workspace/__tests__/shared-run.test.ts +181 -0
  385. package/src/session/workspace/index.ts +6 -0
  386. package/src/session/workspace/shared-run.ts +317 -0
  387. package/src/skills/loader.test.ts +89 -0
  388. package/src/skills/loader.ts +37 -6
  389. package/src/streaming/coalesce.test.ts +4 -4
  390. package/src/tools/builtins/__tests__/edit.test.ts +57 -0
  391. package/src/tools/builtins/__tests__/payload-budget.test.ts +92 -0
  392. package/src/tools/builtins/__tests__/read-file.test.ts +43 -0
  393. package/src/tools/builtins/__tests__/verify-outputs.test.ts +71 -0
  394. package/src/tools/builtins/__tests__/write-file.test.ts +97 -0
  395. package/src/tools/builtins/bash.ts +48 -7
  396. package/src/tools/builtins/edit.ts +162 -27
  397. package/src/tools/builtins/index.ts +13 -13
  398. package/src/tools/builtins/read-file.ts +81 -10
  399. package/src/tools/builtins/search-tools.ts +42 -7
  400. package/src/tools/builtins/verify-outputs.ts +126 -0
  401. package/src/tools/builtins/write-file.ts +83 -14
  402. package/src/tools/coordinator/__tests__/agent.test.ts +172 -0
  403. package/src/tools/coordinator/__tests__/approve-plan.test.ts +139 -0
  404. package/src/tools/coordinator/__tests__/ask-user-question.test.ts +370 -0
  405. package/src/tools/coordinator/__tests__/task-list.test.ts +182 -0
  406. package/src/tools/coordinator/agent.ts +157 -0
  407. package/src/tools/coordinator/index.ts +355 -39
  408. package/src/types/agent/base.ts +8 -0
  409. package/src/types/agent/index.ts +1 -0
  410. package/src/types/agent/reactive.ts +42 -0
  411. package/src/types/agent/supervisor.ts +36 -0
  412. package/src/types/agent/working-memory.ts +29 -0
  413. package/src/types/common/index.ts +19 -0
  414. package/src/types/common/usage-merge.test.ts +53 -0
  415. package/src/types/connector/mcp.ts +14 -2
  416. package/src/types/hitl/index.ts +52 -1
  417. package/src/types/message/index.ts +32 -2
  418. package/src/types/provider/chat.ts +12 -9
  419. package/src/types/run/events.ts +6 -0
  420. package/src/types/sandbox/index.ts +219 -0
  421. package/src/types/skills/index.ts +4 -0
  422. package/src/types/tool/index.ts +24 -0
  423. package/src/types/toolset/index.ts +86 -0
  424. package/src/types/workspace/index.ts +9 -0
  425. package/src/types/workspace/shared-run.ts +65 -0
  426. package/src/verification/index.ts +1 -0
  427. package/src/verification/presets.test.ts +112 -0
  428. package/src/verification/presets.ts +72 -0
  429. package/src/version.ts +26 -4
@@ -0,0 +1,122 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest'
2
+ import { ActivityStore } from '../../../store/activity/memory.js'
3
+ import type { RunId } from '../../../types/ids/index.js'
4
+ import type { ChatCompletionResponse } from '../../../types/provider/index.js'
5
+ import type { RunEvent } from '../../../types/run/index.js'
6
+ import type { ToolRegistryContract } from '../../../types/tool/index.js'
7
+ import type { Logger } from '../../../utils/logger.js'
8
+ import { ToolExecutor } from '../executor.js'
9
+
10
+ const mockRunId = 'run_test' as RunId
11
+
12
+ function makeLogger(): Logger {
13
+ const stub = { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() }
14
+ return { ...stub, child: vi.fn(() => ({ ...stub, child: vi.fn() })) } as unknown as Logger
15
+ }
16
+
17
+ const delay = (ms: number) => new Promise((r) => setTimeout(r, ms))
18
+
19
+ /** Two tool calls in one assistant message (one batch). */
20
+ function twoCallResponse(name: string, a: object, b: object): ChatCompletionResponse {
21
+ return {
22
+ message: {
23
+ role: 'assistant',
24
+ content: null,
25
+ toolCalls: [
26
+ { id: 'c1', type: 'function', function: { name, arguments: JSON.stringify(a) } },
27
+ { id: 'c2', type: 'function', function: { name, arguments: JSON.stringify(b) } },
28
+ ],
29
+ },
30
+ finishReason: 'tool_calls',
31
+ usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
32
+ } as ChatCompletionResponse
33
+ }
34
+
35
+ describe('ToolExecutor — concurrencySafe batching', () => {
36
+ let activityStore: ActivityStore
37
+ let emitEvent: (e: RunEvent) => Promise<void>
38
+
39
+ beforeEach(() => {
40
+ activityStore = new ActivityStore(mockRunId, {
41
+ enabled: true,
42
+ trackToolCalls: true,
43
+ trackLlmTurns: true,
44
+ })
45
+ emitEvent = async () => {}
46
+ })
47
+
48
+ it('serializes concurrency-unsafe tools so read-modify-write does not race', async () => {
49
+ // Shared mutable state, mutated via read → await → write (like `edit`).
50
+ let file = 'A'
51
+ const execute = vi.fn(async (_name: string, input: unknown) => {
52
+ const current = file // read
53
+ await delay(10) // window a parallel run would exploit
54
+ file = current + (input as { add: string }).add // write
55
+ return { success: true, output: 'ok' }
56
+ })
57
+ const tools = {
58
+ register: vi.fn(),
59
+ unregister: vi.fn(),
60
+ execute,
61
+ // edit/write/bash declare concurrencySafe:false → isConcurrencySafe()=>false
62
+ get: vi.fn(() => ({ isConcurrencySafe: () => false })),
63
+ has: vi.fn(() => true),
64
+ listNames: vi.fn(() => []),
65
+ getAvailability: vi.fn(),
66
+ } as unknown as ToolRegistryContract
67
+
68
+ const exec = new ToolExecutor(
69
+ {
70
+ tools,
71
+ runId: mockRunId,
72
+ workingDirectory: '/tmp',
73
+ permissionMode: 'auto',
74
+ env: {},
75
+ abortSignal: new AbortController().signal,
76
+ },
77
+ activityStore,
78
+ emitEvent,
79
+ makeLogger(),
80
+ )
81
+ await exec.executeBatch(twoCallResponse('edit', { add: 'B' }, { add: 'C' }))
82
+ // Serialized: A→AB→ABC. A racing run would lose one append (e.g. 'AC').
83
+ expect(file).toBe('ABC')
84
+ })
85
+
86
+ it('runs concurrency-safe tools in parallel', async () => {
87
+ let active = 0
88
+ let maxActive = 0
89
+ const execute = vi.fn(async () => {
90
+ active++
91
+ maxActive = Math.max(maxActive, active)
92
+ await delay(10)
93
+ active--
94
+ return { success: true, output: 'ok' }
95
+ })
96
+ const tools = {
97
+ register: vi.fn(),
98
+ unregister: vi.fn(),
99
+ execute,
100
+ get: vi.fn(() => ({ isConcurrencySafe: () => true })),
101
+ has: vi.fn(() => true),
102
+ listNames: vi.fn(() => []),
103
+ getAvailability: vi.fn(),
104
+ } as unknown as ToolRegistryContract
105
+
106
+ const exec = new ToolExecutor(
107
+ {
108
+ tools,
109
+ runId: mockRunId,
110
+ workingDirectory: '/tmp',
111
+ permissionMode: 'auto',
112
+ env: {},
113
+ abortSignal: new AbortController().signal,
114
+ },
115
+ activityStore,
116
+ emitEvent,
117
+ makeLogger(),
118
+ )
119
+ await exec.executeBatch(twoCallResponse('grep', { p: '1' }, { p: '2' }))
120
+ expect(maxActive).toBe(2) // both ran at once
121
+ })
122
+ })
@@ -18,7 +18,10 @@ function makeLogger(): Logger {
18
18
  error: vi.fn(),
19
19
  debug: vi.fn(),
20
20
  }
21
- return { ...stub, child: vi.fn(() => ({ ...stub, child: vi.fn() })) } as unknown as Logger
21
+ return {
22
+ ...stub,
23
+ child: vi.fn(() => ({ ...stub, child: vi.fn() })),
24
+ } as unknown as Logger
22
25
  }
23
26
 
24
27
  function makeToolRegistry(execute: ToolRegistryContract['execute']): ToolRegistryContract {
@@ -93,6 +96,42 @@ describe('ToolExecutor plugin hooks', () => {
93
96
  expect(batch.results[0]?.output).toBe('ok')
94
97
  })
95
98
 
99
+ it('preserves tool stdout/stderr when a tool exits unsuccessfully', async () => {
100
+ const tools = makeToolRegistry(
101
+ vi.fn(async () => ({
102
+ success: false,
103
+ output: 'STDOUT:\npartial result\n\nSTDERR:\nboom',
104
+ error: 'Command exited with code 1',
105
+ })),
106
+ )
107
+ const exec = new ToolExecutor(
108
+ {
109
+ tools,
110
+ runId: mockRunId,
111
+ workingDirectory: '/tmp',
112
+ permissionMode: 'auto',
113
+ env: {},
114
+ abortSignal: new AbortController().signal,
115
+ },
116
+ activityStore,
117
+ emitEvent,
118
+ makeLogger(),
119
+ )
120
+
121
+ const batch = await exec.executeBatch(buildResponse('bash', { command: 'false' }))
122
+ expect(batch.results[0]?.output).toContain('STDOUT:\npartial result')
123
+ expect(batch.results[0]?.output).toContain('STDERR:\nboom')
124
+ expect(batch.results[0]?.output).toContain('Error: Command exited with code 1')
125
+
126
+ const completed = emitted.find((e) => e.type === 'tool_completed')
127
+ expect(completed).toMatchObject({
128
+ type: 'tool_completed',
129
+ toolName: 'bash',
130
+ result: expect.stringContaining('STDOUT:\npartial result'),
131
+ isError: true,
132
+ })
133
+ })
134
+
96
135
  it('replaces input on pre_tool_use modify', async () => {
97
136
  const executeMock = vi.fn(async () => ({ success: true, output: 'ok' }))
98
137
  const tools = makeToolRegistry(executeMock)
@@ -120,7 +159,10 @@ describe('ToolExecutor plugin hooks', () => {
120
159
  })
121
160
 
122
161
  it('skips registry execution and synthesizes output on pre_tool_use skip', async () => {
123
- const executeMock = vi.fn(async () => ({ success: true, output: 'should-not-run' }))
162
+ const executeMock = vi.fn(async () => ({
163
+ success: true,
164
+ output: 'should-not-run',
165
+ }))
124
166
  const tools = makeToolRegistry(executeMock)
125
167
  const pluginManager = makePluginManager(async (event) =>
126
168
  event === 'pre_tool_use'
@@ -223,7 +265,10 @@ describe('ToolExecutor plugin hooks', () => {
223
265
  })
224
266
 
225
267
  it('carries modified input into synthetic skip outcome (modify -> skip chain)', async () => {
226
- const executeMock = vi.fn(async () => ({ success: true, output: 'should-not-run' }))
268
+ const executeMock = vi.fn(async () => ({
269
+ success: true,
270
+ output: 'should-not-run',
271
+ }))
227
272
  const tools = makeToolRegistry(executeMock)
228
273
  const { PluginLifecycleManager } = await import('../../../plugin/lifecycle.js')
229
274
  const realManager = new PluginLifecycleManager({
@@ -0,0 +1,180 @@
1
+ import { readFile, rm } from 'node:fs/promises'
2
+ import { mkdtemp } from 'node:fs/promises'
3
+ import { tmpdir } from 'node:os'
4
+ import { join } from 'node:path'
5
+ import { afterEach, describe, expect, it } from 'vitest'
6
+
7
+ import { ToolRegistry } from '../../../registry/tool/execute.js'
8
+ import { EditTool, WriteFileTool } from '../../../tools/builtins/index.js'
9
+ import type { SessionId, TenantId } from '../../../types/ids/index.js'
10
+ import { createUserMessage } from '../../../types/message/index.js'
11
+ import type { LLMProvider, StreamChunk } from '../../../types/provider/index.js'
12
+ import type { RunEvent } from '../../../types/run/index.js'
13
+ import type { ProjectId, ThreadId } from '../../../types/session/ids.js'
14
+ import { drainQuery } from '../index.js'
15
+
16
+ const ZERO_USAGE = {
17
+ promptTokens: 0,
18
+ completionTokens: 0,
19
+ totalTokens: 0,
20
+ cachedTokens: 0,
21
+ cacheWriteTokens: 0,
22
+ }
23
+
24
+ interface ToolStep {
25
+ readonly name: string
26
+ readonly input: Record<string, unknown>
27
+ }
28
+
29
+ class ScriptedLongDocumentProvider implements LLMProvider {
30
+ readonly id = 'scripted-long-document'
31
+ readonly name = 'Scripted Long Document Provider'
32
+ calls = 0
33
+
34
+ constructor(private readonly steps: readonly ToolStep[]) {}
35
+
36
+ async *chatStream(): AsyncIterable<StreamChunk> {
37
+ const step = this.steps[this.calls]
38
+ this.calls += 1
39
+
40
+ if (!step) {
41
+ yield {
42
+ id: 'msg_done',
43
+ delta: { content: 'Long document created and verified.' },
44
+ finishReason: 'stop',
45
+ usage: ZERO_USAGE,
46
+ }
47
+ return
48
+ }
49
+
50
+ yield {
51
+ id: `msg_${this.calls}`,
52
+ delta: {
53
+ toolCalls: [
54
+ {
55
+ index: 0,
56
+ id: `toolu_${this.calls}`,
57
+ type: 'function',
58
+ function: { name: step.name },
59
+ },
60
+ ],
61
+ },
62
+ }
63
+ yield {
64
+ id: `msg_${this.calls}`,
65
+ delta: {
66
+ toolCalls: [
67
+ {
68
+ index: 0,
69
+ id: `toolu_${this.calls}`,
70
+ function: { arguments: JSON.stringify(step.input) },
71
+ },
72
+ ],
73
+ },
74
+ }
75
+ yield {
76
+ id: `msg_${this.calls}`,
77
+ delta: {},
78
+ finishReason: 'tool_calls',
79
+ usage: ZERO_USAGE,
80
+ }
81
+ }
82
+ }
83
+
84
+ describe('query long-document tool flow', () => {
85
+ const workdirs: string[] = []
86
+
87
+ afterEach(async () => {
88
+ await Promise.all(workdirs.map((dir) => rm(dir, { recursive: true, force: true })))
89
+ workdirs.length = 0
90
+ })
91
+
92
+ it('executes the canonical write skeleton plus bounded edit chunks flow end to end', async () => {
93
+ const workingDirectory = await mkdtemp(join(tmpdir(), 'namzu-query-long-doc-'))
94
+ workdirs.push(workingDirectory)
95
+
96
+ const chunks = Array.from({ length: 4 }, (_, sectionIndex) => {
97
+ const lines = Array.from({ length: 40 }, (_, lineIndex) => {
98
+ return `Section ${sectionIndex + 1}.${lineIndex + 1}: this content is intentionally long enough to require repeated bounded edit calls.`
99
+ })
100
+ const chunk = [`## Section ${sectionIndex + 1}`, ...lines, ''].join('\n')
101
+ expect(chunk.length).toBeLessThan(12_000)
102
+ return chunk
103
+ })
104
+
105
+ const provider = new ScriptedLongDocumentProvider([
106
+ {
107
+ name: 'write',
108
+ input: {
109
+ path: 'outputs/long-document-flow.md',
110
+ content: '# Long document flow\n\n{{BODY}}\n',
111
+ },
112
+ },
113
+ {
114
+ name: 'edit',
115
+ input: {
116
+ path: 'outputs/long-document-flow.md',
117
+ oldStr: '{{BODY}}',
118
+ newStr: chunks[0],
119
+ replace_all: false,
120
+ },
121
+ },
122
+ ...chunks.slice(1).map((chunk) => ({
123
+ name: 'edit',
124
+ input: {
125
+ path: 'outputs/long-document-flow.md',
126
+ insertLine: 'end',
127
+ newStr: chunk,
128
+ replace_all: false,
129
+ },
130
+ })),
131
+ ])
132
+ const tools = new ToolRegistry()
133
+ tools.register(WriteFileTool)
134
+ tools.register(EditTool)
135
+ const events: RunEvent[] = []
136
+
137
+ const run = await drainQuery(
138
+ {
139
+ provider,
140
+ tools,
141
+ runConfig: {
142
+ model: 'mock-model',
143
+ timeoutMs: 5_000,
144
+ tokenBudget: 100_000,
145
+ maxIterations: 8,
146
+ maxResponseTokens: 256,
147
+ },
148
+ agentId: 'agent_long_doc',
149
+ agentName: 'Long Document Agent',
150
+ messages: [createUserMessage('create a long document')],
151
+ workingDirectory,
152
+ sessionId: 'ses_long_document_flow' as SessionId,
153
+ threadId: 'thd_long_document_flow' as ThreadId,
154
+ projectId: 'prj_long_document_flow' as ProjectId,
155
+ tenantId: 'tnt_long_document_flow' as TenantId,
156
+ },
157
+ (event) => {
158
+ events.push(event)
159
+ },
160
+ )
161
+
162
+ const final = await readFile(join(workingDirectory, 'outputs/long-document-flow.md'), 'utf-8')
163
+ const executingTools = events
164
+ .filter(
165
+ (event): event is Extract<RunEvent, { type: 'tool_executing' }> =>
166
+ event.type === 'tool_executing',
167
+ )
168
+ .map((event) => event.toolName)
169
+
170
+ expect(run.status).toBe('completed')
171
+ expect(run.result).toBe('Long document created and verified.')
172
+ expect(provider.calls).toBe(6)
173
+ expect(executingTools).toEqual(['write', 'edit', 'edit', 'edit', 'edit'])
174
+ expect(final).not.toContain('{{BODY}}')
175
+ expect(final.split('\n').length).toBeGreaterThan(160)
176
+ expect(final).toContain('## Section 1')
177
+ expect(final).toContain('## Section 4')
178
+ expect(final).toContain('Section 4.40')
179
+ })
180
+ })
@@ -25,7 +25,7 @@ describe('PromptBuilder runtime context', () => {
25
25
  label: 'test runtime',
26
26
  outputDirectory: 'outputs/',
27
27
  outputFileMarker: 'OUTPUT_FILE: <filename> - <description>',
28
- notes: ['Mirror generated files after the turn.'],
28
+ notes: ['Register generated files after the turn.'],
29
29
  },
30
30
  }).build('full', '/tmp/work')
31
31
 
@@ -33,6 +33,59 @@ describe('PromptBuilder runtime context', () => {
33
33
  expect(prompt).toContain('Working directory: /tmp/work')
34
34
  expect(prompt).toContain('Output directory: outputs/')
35
35
  expect(prompt).toContain('OUTPUT_FILE: <filename> - <description>')
36
- expect(prompt).toContain('Mirror generated files after the turn.')
36
+ expect(prompt).toContain('Register generated files after the turn.')
37
+ })
38
+
39
+ it('discloses available skills even when the host supplies a systemPrompt', () => {
40
+ const prompt = new PromptBuilder({
41
+ systemPrompt: 'You are a project assistant.',
42
+ tools: makeToolRegistry(),
43
+ skills: [
44
+ {
45
+ metadata: {
46
+ name: 'delivery-briefing',
47
+ description: 'Draft and edit delivery briefings from grounded inputs.',
48
+ },
49
+ dirPath: '/repo/.agents/skills/delivery-briefing',
50
+ },
51
+ ],
52
+ }).build('full', '/tmp/work')
53
+
54
+ expect(prompt).toContain('You are a project assistant.')
55
+ expect(prompt).toContain('## Available Skills')
56
+ expect(prompt).toContain('<available_skills>')
57
+ expect(prompt).toContain('delivery-briefing')
58
+ expect(prompt).toContain('Draft and edit delivery briefings')
59
+ expect(prompt).toContain('<location>/repo/.agents/skills/delivery-briefing/SKILL.md</location>')
60
+ expect(prompt).toContain('The following block is a manifest')
61
+ expect(prompt).not.toContain('## Loaded Skills')
62
+ })
63
+
64
+ it('includes loaded skill bodies with systemPrompt while preserving the metadata catalogue', () => {
65
+ const prompt = new PromptBuilder({
66
+ systemPrompt: 'You are a cowork supervisor.',
67
+ tools: makeToolRegistry(),
68
+ skills: [
69
+ {
70
+ metadata: {
71
+ name: 'structured-file-authoring',
72
+ description: 'Create structured files with bounded edit chunks.',
73
+ license: 'MIT',
74
+ compatibility: 'Requires file tools',
75
+ allowedTools: 'read write edit',
76
+ },
77
+ body: 'Use skeleton-first writes and bounded edit chunks.',
78
+ dirPath: '/repo/.agents/skills/structured-file-authoring',
79
+ },
80
+ ],
81
+ }).build('full', '/tmp/work')
82
+
83
+ expect(prompt).toContain('## Available Skills')
84
+ expect(prompt).toContain('<license>MIT</license>')
85
+ expect(prompt).toContain('<compatibility>Requires file tools</compatibility>')
86
+ expect(prompt).toContain('<allowed_tools>read write edit</allowed_tools>')
87
+ expect(prompt).toContain('read the SKILL.md at its <location> before writing code')
88
+ expect(prompt).toContain('## Loaded Skills')
89
+ expect(prompt).toContain('Use skeleton-first writes')
37
90
  })
38
91
  })
@@ -0,0 +1,156 @@
1
+ import { mkdtemp, rm } from 'node:fs/promises'
2
+ import { tmpdir } from 'node:os'
3
+ import { join } from 'node:path'
4
+ import { afterEach, describe, expect, it, vi } from 'vitest'
5
+ import { z } from 'zod'
6
+
7
+ import { ToolRegistry } from '../../../registry/tool/execute.js'
8
+ import type { SessionId, TenantId } from '../../../types/ids/index.js'
9
+ import { createUserMessage } from '../../../types/message/index.js'
10
+ import type { LLMProvider, StreamChunk } from '../../../types/provider/index.js'
11
+ import type { RunEvent } from '../../../types/run/index.js'
12
+ import type { ProjectId, ThreadId } from '../../../types/session/ids.js'
13
+ import { drainQuery } from '../index.js'
14
+
15
+ const ZERO_USAGE = {
16
+ promptTokens: 0,
17
+ completionTokens: 0,
18
+ totalTokens: 0,
19
+ cachedTokens: 0,
20
+ cacheWriteTokens: 0,
21
+ }
22
+
23
+ class IdleDuringToolInputProvider implements LLMProvider {
24
+ readonly id = 'idle-during-tool-input'
25
+ readonly name = 'Idle During Tool Input Provider'
26
+ calls = 0
27
+
28
+ async *chatStream(): AsyncIterable<StreamChunk> {
29
+ this.calls += 1
30
+
31
+ if (this.calls === 1) {
32
+ yield {
33
+ id: 'msg_1',
34
+ delta: {
35
+ toolCalls: [
36
+ {
37
+ index: 0,
38
+ id: 'toolu_write_1',
39
+ type: 'function',
40
+ function: { name: 'write_file' },
41
+ },
42
+ ],
43
+ },
44
+ }
45
+ yield {
46
+ id: 'msg_1',
47
+ delta: {
48
+ toolCalls: [
49
+ {
50
+ index: 0,
51
+ id: 'toolu_write_1',
52
+ function: {
53
+ arguments: '{"path":"/tmp/out.md","content":"partial',
54
+ },
55
+ },
56
+ ],
57
+ },
58
+ }
59
+ throw new Error('Anthropic stream idle for 90s')
60
+ }
61
+
62
+ yield {
63
+ id: 'msg_2',
64
+ delta: { content: 'Recovered after retry guidance.' },
65
+ }
66
+ yield {
67
+ id: 'msg_2',
68
+ delta: {},
69
+ finishReason: 'stop',
70
+ usage: ZERO_USAGE,
71
+ }
72
+ }
73
+ }
74
+
75
+ describe('query stream recovery', () => {
76
+ let workdirs: string[] = []
77
+
78
+ afterEach(async () => {
79
+ await Promise.all(workdirs.map((dir) => rm(dir, { recursive: true, force: true })))
80
+ workdirs = []
81
+ })
82
+
83
+ it('turns an idle stream with partial tool JSON into retryable tool feedback', async () => {
84
+ const provider = new IdleDuringToolInputProvider()
85
+ const actualWrite = vi.fn(async () => ({ success: true, output: 'should not run' }))
86
+ const tools = new ToolRegistry()
87
+ tools.register({
88
+ name: 'write_file',
89
+ description: 'write a file',
90
+ inputSchema: z.object({
91
+ path: z.string(),
92
+ content: z.string(),
93
+ }),
94
+ execute: actualWrite,
95
+ })
96
+ const workingDirectory = await mkdtemp(join(tmpdir(), 'namzu-stream-recovery-'))
97
+ workdirs.push(workingDirectory)
98
+ const events: RunEvent[] = []
99
+
100
+ const run = await drainQuery(
101
+ {
102
+ provider,
103
+ tools,
104
+ runConfig: {
105
+ model: 'mock-model',
106
+ timeoutMs: 5_000,
107
+ tokenBudget: 100_000,
108
+ maxIterations: 3,
109
+ maxResponseTokens: 256,
110
+ },
111
+ agentId: 'agent_test',
112
+ agentName: 'Test Agent',
113
+ messages: [createUserMessage('write the file')],
114
+ workingDirectory,
115
+ sessionId: 'ses_stream_recovery' as SessionId,
116
+ threadId: 'thd_stream_recovery' as ThreadId,
117
+ projectId: 'prj_stream_recovery' as ProjectId,
118
+ tenantId: 'tnt_stream_recovery' as TenantId,
119
+ },
120
+ (event) => {
121
+ events.push(event)
122
+ },
123
+ )
124
+
125
+ expect(run.status).toBe('completed')
126
+ expect(run.result).toBe('Recovered after retry guidance.')
127
+ expect(provider.calls).toBe(2)
128
+ expect(actualWrite).not.toHaveBeenCalled()
129
+
130
+ expect(events.some((event) => event.type === 'run_failed')).toBe(false)
131
+ expect(
132
+ events.some(
133
+ (event) =>
134
+ event.type === 'tool_input_completed' &&
135
+ event.inputTruncated === true &&
136
+ JSON.stringify(event.input) === '{}',
137
+ ),
138
+ ).toBe(true)
139
+ expect(JSON.stringify(events)).not.toContain('__namzuTruncated')
140
+
141
+ const completedTool = events.find(
142
+ (event) => event.type === 'tool_completed' && event.toolUseId === 'toolu_write_1',
143
+ )
144
+ expect(completedTool).toMatchObject({
145
+ type: 'tool_completed',
146
+ toolName: 'write_file',
147
+ isError: true,
148
+ })
149
+ expect(completedTool?.type === 'tool_completed' ? completedTool.result : '').toContain(
150
+ 'call was cut off',
151
+ )
152
+ expect(completedTool?.type === 'tool_completed' ? completedTool.result : '').toContain(
153
+ 'extend it with edit using insertLine',
154
+ )
155
+ })
156
+ })
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Synthetic user prompt injected by the iteration loop when a turn
3
+ * ends with `stop_reason: max_tokens` AND no tool_use. Mirrors
4
+ * Claude.ai's "Continue" affordance: the loop pushes this message
5
+ * back into the conversation and fires another iteration, letting
6
+ * the model pick up where it was cut off.
7
+ *
8
+ * The exact string is the marker used by `resolveResult` (in
9
+ * `manager/run/persistence.ts`) to detect auto-continuation
10
+ * boundaries: when walking the message tail it skips user messages
11
+ * that match this constant verbatim, so the run's `result` field
12
+ * concatenates the full multi-turn assistant output instead of only
13
+ * surfacing the trailing continuation chunk.
14
+ */
15
+ export const AUTO_CONTINUATION_USER_MESSAGE =
16
+ 'Continue exactly where you left off. Do not repeat content you already wrote — pick up at the next token.'