@draht/agent-core 2026.9.5-1 → 2026.10.4-2

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 (456) hide show
  1. package/dist/agent-loop.d.ts +27 -2
  2. package/dist/agent-loop.d.ts.map +1 -1
  3. package/dist/agent-loop.js +167 -62
  4. package/dist/agent-loop.js.map +1 -1
  5. package/dist/agent.d.ts +14 -4
  6. package/dist/agent.d.ts.map +1 -1
  7. package/dist/agent.js +65 -19
  8. package/dist/agent.js.map +1 -1
  9. package/dist/harness/agent-harness.d.ts +713 -91
  10. package/dist/harness/agent-harness.d.ts.map +1 -1
  11. package/dist/harness/agent-harness.js +5 -950
  12. package/dist/harness/agent-harness.js.map +1 -1
  13. package/dist/harness/compaction/branch-summarization.d.ts +23 -10
  14. package/dist/harness/compaction/branch-summarization.d.ts.map +1 -1
  15. package/dist/harness/compaction/branch-summarization.js +39 -36
  16. package/dist/harness/compaction/branch-summarization.js.map +1 -1
  17. package/dist/harness/compaction/compaction.d.ts +37 -18
  18. package/dist/harness/compaction/compaction.d.ts.map +1 -1
  19. package/dist/harness/compaction/compaction.js +74 -97
  20. package/dist/harness/compaction/compaction.js.map +1 -1
  21. package/dist/harness/config.d.ts +9 -0
  22. package/dist/harness/config.d.ts.map +1 -0
  23. package/dist/harness/config.js +35 -0
  24. package/dist/harness/config.js.map +1 -0
  25. package/dist/harness/context.d.ts +9 -0
  26. package/dist/harness/context.d.ts.map +1 -0
  27. package/dist/harness/context.js +13 -0
  28. package/dist/harness/context.js.map +1 -0
  29. package/dist/harness/env/nodejs.d.ts +25 -27
  30. package/dist/harness/env/nodejs.d.ts.map +1 -1
  31. package/dist/harness/env/nodejs.js +336 -103
  32. package/dist/harness/env/nodejs.js.map +1 -1
  33. package/dist/harness/events.d.ts +24 -0
  34. package/dist/harness/events.d.ts.map +1 -0
  35. package/dist/harness/events.js +233 -0
  36. package/dist/harness/events.js.map +1 -0
  37. package/dist/harness/execution/assistant.d.ts +42 -0
  38. package/dist/harness/execution/assistant.d.ts.map +1 -0
  39. package/dist/harness/execution/assistant.js +82 -0
  40. package/dist/harness/execution/assistant.js.map +1 -0
  41. package/dist/harness/execution/effect-gate.d.ts +22 -0
  42. package/dist/harness/execution/effect-gate.d.ts.map +1 -0
  43. package/dist/harness/execution/effect-gate.js +49 -0
  44. package/dist/harness/execution/effect-gate.js.map +1 -0
  45. package/dist/harness/execution/tools.d.ts +67 -0
  46. package/dist/harness/execution/tools.d.ts.map +1 -0
  47. package/dist/harness/execution/tools.js +119 -0
  48. package/dist/harness/execution/tools.js.map +1 -0
  49. package/dist/harness/hooks.d.ts +38 -0
  50. package/dist/harness/hooks.d.ts.map +1 -0
  51. package/dist/harness/hooks.js +406 -0
  52. package/dist/harness/hooks.js.map +1 -0
  53. package/dist/harness/messages.d.ts +4 -4
  54. package/dist/harness/messages.d.ts.map +1 -1
  55. package/dist/harness/messages.js +4 -3
  56. package/dist/harness/messages.js.map +1 -1
  57. package/dist/harness/pico3/bash.d.ts +10 -0
  58. package/dist/harness/pico3/bash.d.ts.map +1 -0
  59. package/dist/harness/pico3/bash.js +25 -0
  60. package/dist/harness/pico3/bash.js.map +1 -0
  61. package/dist/harness/pico3/bounded.d.ts +21 -0
  62. package/dist/harness/pico3/bounded.d.ts.map +1 -0
  63. package/dist/harness/pico3/bounded.js +98 -0
  64. package/dist/harness/pico3/bounded.js.map +1 -0
  65. package/dist/harness/pico3/chord.d.ts +41 -0
  66. package/dist/harness/pico3/chord.d.ts.map +1 -0
  67. package/dist/harness/pico3/chord.js +147 -0
  68. package/dist/harness/pico3/chord.js.map +1 -0
  69. package/dist/harness/pico3/context.d.ts +16 -0
  70. package/dist/harness/pico3/context.d.ts.map +1 -0
  71. package/dist/harness/pico3/context.js +88 -0
  72. package/dist/harness/pico3/context.js.map +1 -0
  73. package/dist/harness/pico3/harness.d.ts +198 -0
  74. package/dist/harness/pico3/harness.d.ts.map +1 -0
  75. package/dist/harness/pico3/harness.js +654 -0
  76. package/dist/harness/pico3/harness.js.map +1 -0
  77. package/dist/harness/pico3/hooks.d.ts +10 -0
  78. package/dist/harness/pico3/hooks.d.ts.map +1 -0
  79. package/dist/harness/pico3/hooks.js +33 -0
  80. package/dist/harness/pico3/hooks.js.map +1 -0
  81. package/dist/harness/pico3/index.d.ts +19 -0
  82. package/dist/harness/pico3/index.d.ts.map +1 -0
  83. package/dist/harness/pico3/index.js +15 -0
  84. package/dist/harness/pico3/index.js.map +1 -0
  85. package/dist/harness/pico3/jsonl.d.ts +58 -0
  86. package/dist/harness/pico3/jsonl.d.ts.map +1 -0
  87. package/dist/harness/pico3/jsonl.js +325 -0
  88. package/dist/harness/pico3/jsonl.js.map +1 -0
  89. package/dist/harness/pico3/kinds/collapse.d.ts +49 -0
  90. package/dist/harness/pico3/kinds/collapse.d.ts.map +1 -0
  91. package/dist/harness/pico3/kinds/collapse.js +191 -0
  92. package/dist/harness/pico3/kinds/collapse.js.map +1 -0
  93. package/dist/harness/pico3/kinds/entries.d.ts +78 -0
  94. package/dist/harness/pico3/kinds/entries.d.ts.map +1 -0
  95. package/dist/harness/pico3/kinds/entries.js +13 -0
  96. package/dist/harness/pico3/kinds/entries.js.map +1 -0
  97. package/dist/harness/pico3/kinds/frames.d.ts +9 -0
  98. package/dist/harness/pico3/kinds/frames.d.ts.map +1 -0
  99. package/dist/harness/pico3/kinds/frames.js +75 -0
  100. package/dist/harness/pico3/kinds/frames.js.map +1 -0
  101. package/dist/harness/pico3/kinds/generation.d.ts +94 -0
  102. package/dist/harness/pico3/kinds/generation.d.ts.map +1 -0
  103. package/dist/harness/pico3/kinds/generation.js +504 -0
  104. package/dist/harness/pico3/kinds/generation.js.map +1 -0
  105. package/dist/harness/pico3/kinds/job.d.ts +44 -0
  106. package/dist/harness/pico3/kinds/job.d.ts.map +1 -0
  107. package/dist/harness/pico3/kinds/job.js +143 -0
  108. package/dist/harness/pico3/kinds/job.js.map +1 -0
  109. package/dist/harness/pico3/kinds/plugin.d.ts +15 -0
  110. package/dist/harness/pico3/kinds/plugin.d.ts.map +1 -0
  111. package/dist/harness/pico3/kinds/plugin.js +35 -0
  112. package/dist/harness/pico3/kinds/plugin.js.map +1 -0
  113. package/dist/harness/pico3/kinds/post-tools.d.ts +22 -0
  114. package/dist/harness/pico3/kinds/post-tools.d.ts.map +1 -0
  115. package/dist/harness/pico3/kinds/post-tools.js +145 -0
  116. package/dist/harness/pico3/kinds/post-tools.js.map +1 -0
  117. package/dist/harness/pico3/kinds/task-api.d.ts +3 -0
  118. package/dist/harness/pico3/kinds/task-api.d.ts.map +1 -0
  119. package/dist/harness/pico3/kinds/task-api.js +45 -0
  120. package/dist/harness/pico3/kinds/task-api.js.map +1 -0
  121. package/dist/harness/pico3/kinds/tool.d.ts +43 -0
  122. package/dist/harness/pico3/kinds/tool.d.ts.map +1 -0
  123. package/dist/harness/pico3/kinds/tool.js +373 -0
  124. package/dist/harness/pico3/kinds/tool.js.map +1 -0
  125. package/dist/harness/pico3/legacy-tracker.d.ts +11 -0
  126. package/dist/harness/pico3/legacy-tracker.d.ts.map +1 -0
  127. package/dist/harness/pico3/legacy-tracker.js +41 -0
  128. package/dist/harness/pico3/legacy-tracker.js.map +1 -0
  129. package/dist/harness/pico3/membrane.d.ts +23 -0
  130. package/dist/harness/pico3/membrane.d.ts.map +1 -0
  131. package/dist/harness/pico3/membrane.js +141 -0
  132. package/dist/harness/pico3/membrane.js.map +1 -0
  133. package/dist/harness/pico3/memory.d.ts +53 -0
  134. package/dist/harness/pico3/memory.d.ts.map +1 -0
  135. package/dist/harness/pico3/memory.js +264 -0
  136. package/dist/harness/pico3/memory.js.map +1 -0
  137. package/dist/harness/pico3/scheduler.d.ts +49 -0
  138. package/dist/harness/pico3/scheduler.d.ts.map +1 -0
  139. package/dist/harness/pico3/scheduler.js +438 -0
  140. package/dist/harness/pico3/scheduler.js.map +1 -0
  141. package/dist/harness/pico3/session.d.ts +264 -0
  142. package/dist/harness/pico3/session.d.ts.map +1 -0
  143. package/dist/harness/pico3/session.js +1348 -0
  144. package/dist/harness/pico3/session.js.map +1 -0
  145. package/dist/harness/pico3/system.d.ts +126 -0
  146. package/dist/harness/pico3/system.d.ts.map +1 -0
  147. package/dist/harness/pico3/system.js +244 -0
  148. package/dist/harness/pico3/system.js.map +1 -0
  149. package/dist/harness/pico3/types.d.ts +973 -0
  150. package/dist/harness/pico3/types.d.ts.map +1 -0
  151. package/dist/harness/pico3/types.js +106 -0
  152. package/dist/harness/pico3/types.js.map +1 -0
  153. package/dist/harness/pico3/view.d.ts +34 -0
  154. package/dist/harness/pico3/view.d.ts.map +1 -0
  155. package/dist/harness/pico3/view.js +411 -0
  156. package/dist/harness/pico3/view.js.map +1 -0
  157. package/dist/harness/prompt-templates.d.ts +3 -2
  158. package/dist/harness/prompt-templates.d.ts.map +1 -1
  159. package/dist/harness/prompt-templates.js +18 -23
  160. package/dist/harness/prompt-templates.js.map +1 -1
  161. package/dist/harness/result.d.ts +133 -0
  162. package/dist/harness/result.d.ts.map +1 -0
  163. package/dist/harness/result.js +81 -0
  164. package/dist/harness/result.js.map +1 -0
  165. package/dist/harness/runtime/drive/boundary.d.ts +28 -0
  166. package/dist/harness/runtime/drive/boundary.d.ts.map +1 -0
  167. package/dist/harness/runtime/drive/boundary.js +173 -0
  168. package/dist/harness/runtime/drive/boundary.js.map +1 -0
  169. package/dist/harness/runtime/drive/checkpoint.d.ts +8 -0
  170. package/dist/harness/runtime/drive/checkpoint.d.ts.map +1 -0
  171. package/dist/harness/runtime/drive/checkpoint.js +133 -0
  172. package/dist/harness/runtime/drive/checkpoint.js.map +1 -0
  173. package/dist/harness/runtime/drive/deferred.d.ts +15 -0
  174. package/dist/harness/runtime/drive/deferred.d.ts.map +1 -0
  175. package/dist/harness/runtime/drive/deferred.js +179 -0
  176. package/dist/harness/runtime/drive/deferred.js.map +1 -0
  177. package/dist/harness/runtime/drive/generation.d.ts +8 -0
  178. package/dist/harness/runtime/drive/generation.d.ts.map +1 -0
  179. package/dist/harness/runtime/drive/generation.js +205 -0
  180. package/dist/harness/runtime/drive/generation.js.map +1 -0
  181. package/dist/harness/runtime/drive/reconcile.d.ts +5 -0
  182. package/dist/harness/runtime/drive/reconcile.d.ts.map +1 -0
  183. package/dist/harness/runtime/drive/reconcile.js +140 -0
  184. package/dist/harness/runtime/drive/reconcile.js.map +1 -0
  185. package/dist/harness/runtime/drive/recovery.d.ts +8 -0
  186. package/dist/harness/runtime/drive/recovery.d.ts.map +1 -0
  187. package/dist/harness/runtime/drive/recovery.js +85 -0
  188. package/dist/harness/runtime/drive/recovery.js.map +1 -0
  189. package/dist/harness/runtime/drive/response.d.ts +23 -0
  190. package/dist/harness/runtime/drive/response.d.ts.map +1 -0
  191. package/dist/harness/runtime/drive/response.js +394 -0
  192. package/dist/harness/runtime/drive/response.js.map +1 -0
  193. package/dist/harness/runtime/drive/retry.d.ts +4 -0
  194. package/dist/harness/runtime/drive/retry.d.ts.map +1 -0
  195. package/dist/harness/runtime/drive/retry.js +34 -0
  196. package/dist/harness/runtime/drive/retry.js.map +1 -0
  197. package/dist/harness/runtime/drive/structural.d.ts +32 -0
  198. package/dist/harness/runtime/drive/structural.d.ts.map +1 -0
  199. package/dist/harness/runtime/drive/structural.js +929 -0
  200. package/dist/harness/runtime/drive/structural.js.map +1 -0
  201. package/dist/harness/runtime/drive/terminal.d.ts +7 -0
  202. package/dist/harness/runtime/drive/terminal.d.ts.map +1 -0
  203. package/dist/harness/runtime/drive/terminal.js +49 -0
  204. package/dist/harness/runtime/drive/terminal.js.map +1 -0
  205. package/dist/harness/runtime/drive/tool-placement.d.ts +14 -0
  206. package/dist/harness/runtime/drive/tool-placement.d.ts.map +1 -0
  207. package/dist/harness/runtime/drive/tool-placement.js +219 -0
  208. package/dist/harness/runtime/drive/tool-placement.js.map +1 -0
  209. package/dist/harness/runtime/drive/tools.d.ts +6 -0
  210. package/dist/harness/runtime/drive/tools.d.ts.map +1 -0
  211. package/dist/harness/runtime/drive/tools.js +449 -0
  212. package/dist/harness/runtime/drive/tools.js.map +1 -0
  213. package/dist/harness/runtime/drive.d.ts +6 -0
  214. package/dist/harness/runtime/drive.d.ts.map +1 -0
  215. package/dist/harness/runtime/drive.js +93 -0
  216. package/dist/harness/runtime/drive.js.map +1 -0
  217. package/dist/harness/runtime/harness.d.ts +59 -0
  218. package/dist/harness/runtime/harness.d.ts.map +1 -0
  219. package/dist/harness/runtime/harness.js +311 -0
  220. package/dist/harness/runtime/harness.js.map +1 -0
  221. package/dist/harness/runtime/index.d.ts +2 -0
  222. package/dist/harness/runtime/index.d.ts.map +1 -0
  223. package/dist/harness/runtime/index.js +2 -0
  224. package/dist/harness/runtime/index.js.map +1 -0
  225. package/dist/harness/runtime/lane.d.ts +118 -0
  226. package/dist/harness/runtime/lane.d.ts.map +1 -0
  227. package/dist/harness/runtime/lane.js +1575 -0
  228. package/dist/harness/runtime/lane.js.map +1 -0
  229. package/dist/harness/runtime/progress.d.ts +15 -0
  230. package/dist/harness/runtime/progress.d.ts.map +1 -0
  231. package/dist/harness/runtime/progress.js +66 -0
  232. package/dist/harness/runtime/progress.js.map +1 -0
  233. package/dist/harness/runtime/reducer.d.ts +5 -0
  234. package/dist/harness/runtime/reducer.d.ts.map +1 -0
  235. package/dist/harness/runtime/reducer.js +240 -0
  236. package/dist/harness/runtime/reducer.js.map +1 -0
  237. package/dist/harness/runtime/restore.d.ts +24 -0
  238. package/dist/harness/runtime/restore.d.ts.map +1 -0
  239. package/dist/harness/runtime/restore.js +117 -0
  240. package/dist/harness/runtime/restore.js.map +1 -0
  241. package/dist/harness/runtime/transcript.d.ts +21 -0
  242. package/dist/harness/runtime/transcript.d.ts.map +1 -0
  243. package/dist/harness/runtime/transcript.js +72 -0
  244. package/dist/harness/runtime/transcript.js.map +1 -0
  245. package/dist/harness/runtime/types.d.ts +105 -0
  246. package/dist/harness/runtime/types.d.ts.map +1 -0
  247. package/dist/harness/runtime/types.js +61 -0
  248. package/dist/harness/runtime/types.js.map +1 -0
  249. package/dist/harness/session/commit.d.ts +53 -0
  250. package/dist/harness/session/commit.d.ts.map +1 -0
  251. package/dist/harness/session/commit.js +57 -0
  252. package/dist/harness/session/commit.js.map +1 -0
  253. package/dist/harness/session/context.d.ts +10 -0
  254. package/dist/harness/session/context.d.ts.map +1 -0
  255. package/dist/harness/session/context.js +49 -0
  256. package/dist/harness/session/context.js.map +1 -0
  257. package/dist/harness/session/fork-policy.d.ts +21 -0
  258. package/dist/harness/session/fork-policy.d.ts.map +1 -0
  259. package/dist/harness/session/fork-policy.js +55 -0
  260. package/dist/harness/session/fork-policy.js.map +1 -0
  261. package/dist/harness/session/fork.d.ts +16 -0
  262. package/dist/harness/session/fork.d.ts.map +1 -0
  263. package/dist/harness/session/fork.js +79 -0
  264. package/dist/harness/session/fork.js.map +1 -0
  265. package/dist/harness/session/in-memory-storage-state.d.ts +39 -0
  266. package/dist/harness/session/in-memory-storage-state.d.ts.map +1 -0
  267. package/dist/harness/session/in-memory-storage-state.js +276 -0
  268. package/dist/harness/session/in-memory-storage-state.js.map +1 -0
  269. package/dist/harness/session/index.d.ts +11 -0
  270. package/dist/harness/session/index.d.ts.map +1 -0
  271. package/dist/harness/session/index.js +9 -0
  272. package/dist/harness/session/index.js.map +1 -0
  273. package/dist/harness/session/jsonl/codec.d.ts +21 -0
  274. package/dist/harness/session/jsonl/codec.d.ts.map +1 -0
  275. package/dist/harness/session/jsonl/codec.js +45 -0
  276. package/dist/harness/session/jsonl/codec.js.map +1 -0
  277. package/dist/harness/session/jsonl/fork.d.ts +38 -0
  278. package/dist/harness/session/jsonl/fork.d.ts.map +1 -0
  279. package/dist/harness/session/jsonl/fork.js +264 -0
  280. package/dist/harness/session/jsonl/fork.js.map +1 -0
  281. package/dist/harness/session/jsonl/index.d.ts +4 -0
  282. package/dist/harness/session/jsonl/index.d.ts.map +1 -0
  283. package/dist/harness/session/jsonl/index.js +4 -0
  284. package/dist/harness/session/jsonl/index.js.map +1 -0
  285. package/dist/harness/session/jsonl/io.d.ts +14 -0
  286. package/dist/harness/session/jsonl/io.d.ts.map +1 -0
  287. package/dist/harness/session/jsonl/io.js +86 -0
  288. package/dist/harness/session/jsonl/io.js.map +1 -0
  289. package/dist/harness/session/jsonl/legacy-v3.d.ts +44 -0
  290. package/dist/harness/session/jsonl/legacy-v3.d.ts.map +1 -0
  291. package/dist/harness/session/jsonl/legacy-v3.js +462 -0
  292. package/dist/harness/session/jsonl/legacy-v3.js.map +1 -0
  293. package/dist/harness/session/jsonl/repo.d.ts +35 -0
  294. package/dist/harness/session/jsonl/repo.d.ts.map +1 -0
  295. package/dist/harness/session/jsonl/repo.js +301 -0
  296. package/dist/harness/session/jsonl/repo.js.map +1 -0
  297. package/dist/harness/session/jsonl/storage.d.ts +41 -0
  298. package/dist/harness/session/jsonl/storage.d.ts.map +1 -0
  299. package/dist/harness/session/jsonl/storage.js +200 -0
  300. package/dist/harness/session/jsonl/storage.js.map +1 -0
  301. package/dist/harness/session/jsonl/types.d.ts +39 -0
  302. package/dist/harness/session/jsonl/types.d.ts.map +1 -0
  303. package/dist/harness/session/jsonl/types.js +3 -0
  304. package/dist/harness/session/jsonl/types.js.map +1 -0
  305. package/dist/harness/session/memory.d.ts +48 -0
  306. package/dist/harness/session/memory.d.ts.map +1 -0
  307. package/dist/harness/session/memory.js +369 -0
  308. package/dist/harness/session/memory.js.map +1 -0
  309. package/dist/harness/session/mutation-line.d.ts +8 -0
  310. package/dist/harness/session/mutation-line.d.ts.map +1 -0
  311. package/dist/harness/session/mutation-line.js +21 -0
  312. package/dist/harness/session/mutation-line.js.map +1 -0
  313. package/dist/harness/session/session.d.ts +79 -46
  314. package/dist/harness/session/session.d.ts.map +1 -1
  315. package/dist/harness/session/session.js +320 -220
  316. package/dist/harness/session/session.js.map +1 -1
  317. package/dist/harness/session/testing/benchmark/datasets.d.ts +12 -0
  318. package/dist/harness/session/testing/benchmark/datasets.d.ts.map +1 -0
  319. package/dist/harness/session/testing/benchmark/datasets.js +24 -0
  320. package/dist/harness/session/testing/benchmark/datasets.js.map +1 -0
  321. package/dist/harness/session/testing/benchmark/session-repo.d.ts +42 -0
  322. package/dist/harness/session/testing/benchmark/session-repo.d.ts.map +1 -0
  323. package/dist/harness/session/testing/benchmark/session-repo.js +127 -0
  324. package/dist/harness/session/testing/benchmark/session-repo.js.map +1 -0
  325. package/dist/harness/session/testing/benchmark/storage.d.ts +25 -0
  326. package/dist/harness/session/testing/benchmark/storage.d.ts.map +1 -0
  327. package/dist/harness/session/testing/benchmark/storage.js +114 -0
  328. package/dist/harness/session/testing/benchmark/storage.js.map +1 -0
  329. package/dist/harness/session/testing/conformance/session-repo.d.ts +23 -0
  330. package/dist/harness/session/testing/conformance/session-repo.d.ts.map +1 -0
  331. package/dist/harness/session/testing/conformance/session-repo.js +809 -0
  332. package/dist/harness/session/testing/conformance/session-repo.js.map +1 -0
  333. package/dist/harness/session/testing/conformance/storage.d.ts +4 -0
  334. package/dist/harness/session/testing/conformance/storage.d.ts.map +1 -0
  335. package/dist/harness/session/testing/conformance/storage.js +600 -0
  336. package/dist/harness/session/testing/conformance/storage.js.map +1 -0
  337. package/dist/harness/session/testing/gating-storage.d.ts +26 -0
  338. package/dist/harness/session/testing/gating-storage.d.ts.map +1 -0
  339. package/dist/harness/session/testing/gating-storage.js +100 -0
  340. package/dist/harness/session/testing/gating-storage.js.map +1 -0
  341. package/dist/harness/session/testing/index.d.ts +10 -0
  342. package/dist/harness/session/testing/index.d.ts.map +1 -0
  343. package/dist/harness/session/testing/index.js +9 -0
  344. package/dist/harness/session/testing/index.js.map +1 -0
  345. package/dist/harness/session/testing/instrumented-storage.d.ts +11 -0
  346. package/dist/harness/session/testing/instrumented-storage.d.ts.map +1 -0
  347. package/dist/harness/session/testing/instrumented-storage.js +16 -0
  348. package/dist/harness/session/testing/instrumented-storage.js.map +1 -0
  349. package/dist/harness/session/testing/storage-decorator.d.ts +20 -0
  350. package/dist/harness/session/testing/storage-decorator.d.ts.map +1 -0
  351. package/dist/harness/session/testing/storage-decorator.js +41 -0
  352. package/dist/harness/session/testing/storage-decorator.js.map +1 -0
  353. package/dist/harness/session/testing/types.d.ts +12 -0
  354. package/dist/harness/session/testing/types.d.ts.map +1 -0
  355. package/dist/harness/session/testing/types.js +2 -0
  356. package/dist/harness/session/testing/types.js.map +1 -0
  357. package/dist/harness/session/types.d.ts +512 -0
  358. package/dist/harness/session/types.d.ts.map +1 -0
  359. package/dist/harness/session/types.js +9 -0
  360. package/dist/harness/session/types.js.map +1 -0
  361. package/dist/harness/session/values.d.ts +95 -0
  362. package/dist/harness/session/values.d.ts.map +1 -0
  363. package/dist/harness/session/values.js +81 -0
  364. package/dist/harness/session/values.js.map +1 -0
  365. package/dist/harness/skills.d.ts +6 -4
  366. package/dist/harness/skills.d.ts.map +1 -1
  367. package/dist/harness/skills.js +59 -44
  368. package/dist/harness/skills.js.map +1 -1
  369. package/dist/harness/telemetry.d.ts +1242 -0
  370. package/dist/harness/telemetry.d.ts.map +1 -0
  371. package/dist/harness/telemetry.js +527 -0
  372. package/dist/harness/telemetry.js.map +1 -0
  373. package/dist/harness/tools/bash.d.ts +4 -4
  374. package/dist/harness/tools/bash.d.ts.map +1 -1
  375. package/dist/harness/tools/bash.js +66 -93
  376. package/dist/harness/tools/bash.js.map +1 -1
  377. package/dist/harness/tools/edit.d.ts.map +1 -1
  378. package/dist/harness/tools/edit.js +10 -10
  379. package/dist/harness/tools/edit.js.map +1 -1
  380. package/dist/harness/tools/file-mutation-queue.d.ts +2 -1
  381. package/dist/harness/tools/file-mutation-queue.d.ts.map +1 -1
  382. package/dist/harness/tools/file-mutation-queue.js +5 -5
  383. package/dist/harness/tools/file-mutation-queue.js.map +1 -1
  384. package/dist/harness/tools/image.js +1 -1
  385. package/dist/harness/tools/image.js.map +1 -1
  386. package/dist/harness/tools/path-utils.d.ts +3 -2
  387. package/dist/harness/tools/path-utils.d.ts.map +1 -1
  388. package/dist/harness/tools/path-utils.js +5 -5
  389. package/dist/harness/tools/path-utils.js.map +1 -1
  390. package/dist/harness/tools/read.d.ts +2 -1
  391. package/dist/harness/tools/read.d.ts.map +1 -1
  392. package/dist/harness/tools/read.js +4 -6
  393. package/dist/harness/tools/read.js.map +1 -1
  394. package/dist/harness/tools/write.d.ts.map +1 -1
  395. package/dist/harness/tools/write.js +7 -7
  396. package/dist/harness/tools/write.js.map +1 -1
  397. package/dist/harness/types.d.ts +126 -502
  398. package/dist/harness/types.d.ts.map +1 -1
  399. package/dist/harness/types.js +10 -16
  400. package/dist/harness/types.js.map +1 -1
  401. package/dist/harness/utils/adaptive-publisher.d.ts +24 -0
  402. package/dist/harness/utils/adaptive-publisher.d.ts.map +1 -0
  403. package/dist/harness/utils/adaptive-publisher.js +79 -0
  404. package/dist/harness/utils/adaptive-publisher.js.map +1 -0
  405. package/dist/harness/utils/output-capture.d.ts +31 -0
  406. package/dist/harness/utils/output-capture.d.ts.map +1 -0
  407. package/dist/harness/utils/output-capture.js +217 -0
  408. package/dist/harness/utils/output-capture.js.map +1 -0
  409. package/dist/harness/utils/shell-output.d.ts +12 -5
  410. package/dist/harness/utils/shell-output.d.ts.map +1 -1
  411. package/dist/harness/utils/shell-output.js +64 -174
  412. package/dist/harness/utils/shell-output.js.map +1 -1
  413. package/dist/harness/utils/truncate.d.ts +1 -0
  414. package/dist/harness/utils/truncate.d.ts.map +1 -1
  415. package/dist/harness/utils/truncate.js +1 -1
  416. package/dist/harness/utils/truncate.js.map +1 -1
  417. package/dist/harness/utils/usage.d.ts +4 -0
  418. package/dist/harness/utils/usage.d.ts.map +1 -0
  419. package/dist/harness/utils/usage.js +33 -0
  420. package/dist/harness/utils/usage.js.map +1 -0
  421. package/dist/index.d.ts +13 -9
  422. package/dist/index.d.ts.map +1 -1
  423. package/dist/index.js +9 -13
  424. package/dist/index.js.map +1 -1
  425. package/dist/proxy.d.ts +6 -3
  426. package/dist/proxy.d.ts.map +1 -1
  427. package/dist/proxy.js +8 -0
  428. package/dist/proxy.js.map +1 -1
  429. package/dist/search/index.d.ts +29 -0
  430. package/dist/search/index.d.ts.map +1 -0
  431. package/dist/search/index.js +2 -0
  432. package/dist/search/index.js.map +1 -0
  433. package/dist/types.d.ts +107 -31
  434. package/dist/types.d.ts.map +1 -1
  435. package/dist/types.js.map +1 -1
  436. package/package.json +50 -4
  437. package/dist/harness/session/jsonl-repo.d.ts +0 -26
  438. package/dist/harness/session/jsonl-repo.d.ts.map +0 -1
  439. package/dist/harness/session/jsonl-repo.js +0 -100
  440. package/dist/harness/session/jsonl-repo.js.map +0 -1
  441. package/dist/harness/session/jsonl-storage.d.ts +0 -42
  442. package/dist/harness/session/jsonl-storage.d.ts.map +0 -1
  443. package/dist/harness/session/jsonl-storage.js +0 -286
  444. package/dist/harness/session/jsonl-storage.js.map +0 -1
  445. package/dist/harness/session/memory-repo.d.ts +0 -18
  446. package/dist/harness/session/memory-repo.d.ts.map +0 -1
  447. package/dist/harness/session/memory-repo.js +0 -44
  448. package/dist/harness/session/memory-repo.js.map +0 -1
  449. package/dist/harness/session/memory-storage.d.ts +0 -33
  450. package/dist/harness/session/memory-storage.d.ts.map +0 -1
  451. package/dist/harness/session/memory-storage.js +0 -163
  452. package/dist/harness/session/memory-storage.js.map +0 -1
  453. package/dist/harness/session/repo-utils.d.ts +0 -11
  454. package/dist/harness/session/repo-utils.d.ts.map +0 -1
  455. package/dist/harness/session/repo-utils.js +0 -39
  456. package/dist/harness/session/repo-utils.js.map +0 -1
@@ -2,8 +2,8 @@
2
2
  * Agent loop that works with AgentMessage throughout.
3
3
  * Transforms to Message[] only at the LLM call boundary.
4
4
  */
5
- import { EventStream } from "@draht/ai";
6
- import type { AgentContext, AgentEvent, AgentLoopConfig, AgentMessage, StreamFn } from "./types.ts";
5
+ import { type AssistantMessage, EventStream } from "@draht/ai";
6
+ import type { AgentContext, AgentEvent, AgentLoopConfig, AgentMessage, AgentTool, AgentToolCall, AgentToolCallOutcome, AgentToolResult, StreamFn } from "./types.ts";
7
7
  export type AgentEventSink = (event: AgentEvent) => Promise<void> | void;
8
8
  /**
9
9
  * Start an agent loop with a new prompt message.
@@ -21,4 +21,29 @@ export declare function agentLoop(prompts: AgentMessage[], context: AgentContext
21
21
  export declare function agentLoopContinue(context: AgentContext, config: AgentLoopConfig, signal: AbortSignal | undefined, streamFn: StreamFn): EventStream<AgentEvent, AgentMessage[]>;
22
22
  export declare function runAgentLoop(prompts: AgentMessage[], context: AgentContext, config: AgentLoopConfig, emit: AgentEventSink, signal: AbortSignal | undefined, streamFn: StreamFn): Promise<AgentMessage[]>;
23
23
  export declare function runAgentLoopContinue(context: AgentContext, config: AgentLoopConfig, emit: AgentEventSink, signal: AbortSignal | undefined, streamFn: StreamFn): Promise<AgentMessage[]>;
24
+ /** The `beforeToolCall` and `afterToolCall` hooks of {@link AgentLoopConfig}. */
25
+ export type ToolCallHooks = Pick<AgentLoopConfig, "beforeToolCall" | "afterToolCall">;
26
+ type ToolUpdateSink = (partialResult: AgentToolResult<any>) => Promise<void> | void;
27
+ /** Options for {@link runToolCall}. */
28
+ export interface RunToolCallOptions extends ToolCallHooks {
29
+ /** Tools the call resolves against. */
30
+ tools: readonly AgentTool<any>[];
31
+ /** Passed to the hooks as the message that issued the call. */
32
+ assistantMessage: AssistantMessage;
33
+ /** Passed to the hooks as the current agent context. */
34
+ context: AgentContext;
35
+ signal?: AbortSignal;
36
+ onUpdate?: ToolUpdateSink;
37
+ }
38
+ /**
39
+ * Run one tool call through the same steps as a model-issued call: argument preparation, schema
40
+ * validation, `beforeToolCall`, execution, and `afterToolCall`. Emits no events and adds no
41
+ * messages. Tools that call other tools use this so the hooks (for example permission checks)
42
+ * apply to those calls too.
43
+ *
44
+ * Never rejects for tool failures: unknown tools, validation errors, blocked calls, and thrown
45
+ * errors come back as `isError: true`.
46
+ */
47
+ export declare function runToolCall(toolCall: AgentToolCall, options: RunToolCallOptions): Promise<AgentToolCallOutcome>;
48
+ export {};
24
49
  //# sourceMappingURL=agent-loop.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent-loop.d.ts","sourceRoot":"","sources":["../src/agent-loop.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAGN,WAAW,EAGX,MAAM,WAAW,CAAC;AAEnB,OAAO,KAAK,EACX,YAAY,EACZ,UAAU,EACV,eAAe,EACf,YAAY,EAIZ,QAAQ,EACR,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEzE;;;GAGG;AACH,wBAAgB,SAAS,CACxB,OAAO,EAAE,YAAY,EAAE,EACvB,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,QAAQ,GAChB,WAAW,CAAC,UAAU,EAAE,YAAY,EAAE,CAAC,CAiBzC;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAChC,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,QAAQ,GAChB,WAAW,CAAC,UAAU,EAAE,YAAY,EAAE,CAAC,CAwBzC;AAED,wBAAsB,YAAY,CACjC,OAAO,EAAE,YAAY,EAAE,EACvB,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,QAAQ,GAChB,OAAO,CAAC,YAAY,EAAE,CAAC,CAgBzB;AAED,wBAAsB,oBAAoB,CACzC,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,QAAQ,GAChB,OAAO,CAAC,YAAY,EAAE,CAAC,CAiBzB"}
1
+ {"version":3,"file":"agent-loop.d.ts","sourceRoot":"","sources":["../src/agent-loop.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,KAAK,gBAAgB,EACrB,WAAW,EASX,MAAM,WAAW,CAAC;AAEnB,OAAO,KAAK,EACX,YAAY,EACZ,UAAU,EACV,eAAe,EACf,YAAY,EACZ,SAAS,EACT,aAAa,EACb,oBAAoB,EACpB,eAAe,EAEf,QAAQ,EACR,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEzE;;;GAGG;AACH,wBAAgB,SAAS,CACxB,OAAO,EAAE,YAAY,EAAE,EACvB,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,QAAQ,GAChB,WAAW,CAAC,UAAU,EAAE,YAAY,EAAE,CAAC,CAiBzC;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAChC,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,QAAQ,GAChB,WAAW,CAAC,UAAU,EAAE,YAAY,EAAE,CAAC,CAwBzC;AAED,wBAAsB,YAAY,CACjC,OAAO,EAAE,YAAY,EAAE,EACvB,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,QAAQ,GAChB,OAAO,CAAC,YAAY,EAAE,CAAC,CAiBzB;AAED,wBAAsB,oBAAoB,CACzC,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,QAAQ,GAChB,OAAO,CAAC,YAAY,EAAE,CAAC,CAiBzB;AAmhBD,iFAAiF;AACjF,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,EAAE,gBAAgB,GAAG,eAAe,CAAC,CAAC;AAEtF,KAAK,cAAc,GAAG,CAAC,aAAa,EAAE,eAAe,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAwGpF,uCAAuC;AACvC,MAAM,WAAW,kBAAmB,SAAQ,aAAa;IACxD,uCAAuC;IACvC,KAAK,EAAE,SAAS,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;IACjC,+DAA+D;IAC/D,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,wDAAwD;IACxD,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAQrH"}
@@ -2,7 +2,7 @@
2
2
  * Agent loop that works with AgentMessage throughout.
3
3
  * Transforms to Message[] only at the LLM call boundary.
4
4
  */
5
- import { EventStream, validateToolArguments, } from "@draht/ai";
5
+ import { EventStream, getCurrentTools, getToolStateChanges, normalizeContext, toToolDeclaration, validateToolArguments, } from "@draht/ai";
6
6
  import { getDefaultStreamFn } from "./stream-fn.js";
7
7
  /**
8
8
  * Start an agent loop with a new prompt message.
@@ -41,16 +41,17 @@ export function agentLoopContinue(context, config, signal, streamFn) {
41
41
  return stream;
42
42
  }
43
43
  export async function runAgentLoop(prompts, context, config, emit, signal, streamFn) {
44
- const newMessages = [...prompts];
44
+ const initialMessages = declareToolChanges(context, prompts);
45
+ const newMessages = [...initialMessages];
45
46
  const currentContext = {
46
47
  ...context,
47
- messages: [...context.messages, ...prompts],
48
+ messages: [...context.messages, ...initialMessages],
48
49
  };
49
50
  await emit({ type: "agent_start" });
50
51
  await emit({ type: "turn_start" });
51
- for (const prompt of prompts) {
52
- await emit({ type: "message_start", message: prompt });
53
- await emit({ type: "message_end", message: prompt });
52
+ for (const message of initialMessages) {
53
+ await emit({ type: "message_start", message });
54
+ await emit({ type: "message_end", message });
54
55
  }
55
56
  await runLoop(currentContext, newMessages, config, signal, emit, streamFn ?? getDefaultStreamFn());
56
57
  return newMessages;
@@ -78,7 +79,8 @@ function createAgentStream() {
78
79
  async function runLoop(initialContext, newMessages, initialConfig, signal, emit, streamFunction) {
79
80
  let currentContext = initialContext;
80
81
  let config = initialConfig;
81
- let firstTurn = true;
82
+ let lastCompletedTurn;
83
+ let explicitContinuation = false;
82
84
  // Check for steering messages at start (user may have typed while waiting)
83
85
  let pendingMessages = (await config.getSteeringMessages?.()) || [];
84
86
  // Outer loop: continues when queued follow-up messages arrive after agent would stop
@@ -86,26 +88,66 @@ async function runLoop(initialContext, newMessages, initialConfig, signal, emit,
86
88
  let hasMoreToolCalls = true;
87
89
  // Inner loop: process tool calls and steering messages
88
90
  while (hasMoreToolCalls || pendingMessages.length > 0) {
89
- if (!firstTurn) {
91
+ let preparedMessages = [];
92
+ if (lastCompletedTurn) {
93
+ const nextTurnSnapshot = await config.prepareNextTurn?.(lastCompletedTurn);
94
+ if (nextTurnSnapshot) {
95
+ currentContext = nextTurnSnapshot.context ?? currentContext;
96
+ preparedMessages = nextTurnSnapshot.messages ?? [];
97
+ config = {
98
+ ...config,
99
+ model: nextTurnSnapshot.model ?? config.model,
100
+ reasoning: nextTurnSnapshot.thinkingLevel === undefined
101
+ ? config.reasoning
102
+ : nextTurnSnapshot.thinkingLevel === "off"
103
+ ? undefined
104
+ : nextTurnSnapshot.thinkingLevel,
105
+ };
106
+ }
107
+ // Preparation can be long-running (for example, compaction). Pick up steering
108
+ // queued while it ran. Only poll again if the earlier poll returned nothing;
109
+ // otherwise one-at-a-time mode would deliver two messages in this turn.
110
+ if (pendingMessages.length === 0) {
111
+ pendingMessages = (await config.getSteeringMessages?.()) || [];
112
+ }
90
113
  await emit({ type: "turn_start" });
91
114
  }
92
- else {
93
- firstTurn = false;
115
+ // Process prepared and queued messages before the next assistant response.
116
+ for (const message of declareToolChanges(currentContext, [...preparedMessages, ...pendingMessages])) {
117
+ await emit({ type: "message_start", message });
118
+ await emit({ type: "message_end", message });
119
+ currentContext.messages.push(message);
120
+ newMessages.push(message);
94
121
  }
95
- // Process pending messages (inject before next assistant response)
96
- if (pendingMessages.length > 0) {
97
- for (const message of pendingMessages) {
98
- await emit({ type: "message_start", message });
99
- await emit({ type: "message_end", message });
100
- currentContext.messages.push(message);
101
- newMessages.push(message);
102
- }
103
- pendingMessages = [];
122
+ pendingMessages = [];
123
+ const requestUpdate = await config.prepareRequest?.({
124
+ context: currentContext,
125
+ model: config.model,
126
+ thinkingLevel: config.reasoning ?? "off",
127
+ }, signal);
128
+ if (requestUpdate) {
129
+ currentContext = requestUpdate.context ?? currentContext;
130
+ config = {
131
+ ...config,
132
+ model: requestUpdate.model ?? config.model,
133
+ reasoning: requestUpdate.thinkingLevel === undefined
134
+ ? config.reasoning
135
+ : requestUpdate.thinkingLevel === "off"
136
+ ? undefined
137
+ : requestUpdate.thinkingLevel,
138
+ };
104
139
  }
105
140
  // Stream assistant response
106
141
  const message = await streamAssistantResponse(currentContext, config, signal, emit, streamFunction);
107
142
  newMessages.push(message);
108
143
  if (message.stopReason === "error" || message.stopReason === "aborted") {
144
+ lastCompletedTurn = {
145
+ message,
146
+ toolResults: [],
147
+ context: currentContext,
148
+ newMessages,
149
+ };
150
+ await config.finishTurn?.(lastCompletedTurn, signal);
109
151
  await emit({ type: "turn_end", message, toolResults: [] });
110
152
  await emit({ type: "agent_end", messages: newMessages });
111
153
  return;
@@ -128,49 +170,89 @@ async function runLoop(initialContext, newMessages, initialConfig, signal, emit,
128
170
  newMessages.push(result);
129
171
  }
130
172
  }
131
- await emit({ type: "turn_end", message, toolResults });
132
- const nextTurnContext = {
173
+ lastCompletedTurn = {
133
174
  message,
134
175
  toolResults,
135
176
  context: currentContext,
136
177
  newMessages,
137
178
  };
138
- const nextTurnSnapshot = await config.prepareNextTurn?.(nextTurnContext);
139
- if (nextTurnSnapshot) {
140
- currentContext = nextTurnSnapshot.context ?? currentContext;
141
- config = {
142
- ...config,
143
- model: nextTurnSnapshot.model ?? config.model,
144
- reasoning: nextTurnSnapshot.thinkingLevel === undefined
145
- ? config.reasoning
146
- : nextTurnSnapshot.thinkingLevel === "off"
147
- ? undefined
148
- : nextTurnSnapshot.thinkingLevel,
149
- };
150
- }
151
- if (await config.shouldStopAfterTurn?.({
152
- message,
153
- toolResults,
154
- context: currentContext,
155
- newMessages,
156
- })) {
179
+ const decision = await config.finishTurn?.(lastCompletedTurn, signal);
180
+ await emit({ type: "turn_end", message, toolResults });
181
+ if (decision?.action === "end") {
157
182
  await emit({ type: "agent_end", messages: newMessages });
158
183
  return;
159
184
  }
185
+ explicitContinuation = decision?.action === "continue";
160
186
  pendingMessages = (await config.getSteeringMessages?.()) || [];
187
+ if (hasMoreToolCalls || pendingMessages.length > 0) {
188
+ explicitContinuation = false;
189
+ }
161
190
  }
162
191
  // Agent would stop here. Check for follow-up messages.
163
192
  const followUpMessages = (await config.getFollowUpMessages?.()) || [];
164
193
  if (followUpMessages.length > 0) {
165
194
  // Set as pending so inner loop processes them
195
+ explicitContinuation = false;
166
196
  pendingMessages = followUpMessages;
167
197
  continue;
168
198
  }
199
+ // No natural request was selected, so fulfill the continuation decision with one context-only turn.
200
+ if (explicitContinuation) {
201
+ explicitContinuation = false;
202
+ continue;
203
+ }
169
204
  // No more messages, exit
170
205
  break;
171
206
  }
172
207
  await emit({ type: "agent_end", messages: newMessages });
173
208
  }
209
+ /**
210
+ * Declare tool loadout changes to the model.
211
+ *
212
+ * `context.tools` is what the runtime can execute; the transcript's system messages declare
213
+ * what the model may call. Before each request the difference becomes `toolsAdded` and
214
+ * `toolsRemoved` on a system message. When a pending system message exists, its tool fields
215
+ * are treated as intent and replaced with the delta between the committed transcript and
216
+ * the executable set, so replay always yields exactly `context.tools`. Otherwise a new
217
+ * system message is inserted before the first non-system pending message.
218
+ */
219
+ function declareToolChanges(context, pendingMessages) {
220
+ let systemIndex = -1;
221
+ for (let i = pendingMessages.length - 1; i >= 0; i--) {
222
+ if (pendingMessages[i].role === "system") {
223
+ systemIndex = i;
224
+ break;
225
+ }
226
+ }
227
+ const pending = pendingMessages[systemIndex];
228
+ const baseline = pending
229
+ ? pendingMessages.map((message, index) => index === systemIndex ? withToolChanges(pending, NO_CHANGES) : message)
230
+ : pendingMessages;
231
+ const changes = getToolStateChanges(getCurrentTools([...context.messages, ...baseline]), (context.tools ?? []).map(toToolDeclaration));
232
+ const unchanged = changes.toolsAdded.length === 0 && changes.toolsRemoved.length === 0;
233
+ if (pending) {
234
+ // Keep the caller's message object when it already declares no tool changes.
235
+ if (unchanged && !pending.toolsAdded?.length && !pending.toolsRemoved?.length)
236
+ return pendingMessages;
237
+ return baseline.map((message, index) => (index === systemIndex ? withToolChanges(pending, changes) : message));
238
+ }
239
+ if (unchanged)
240
+ return pendingMessages;
241
+ const update = withToolChanges({ role: "system", content: "", timestamp: Date.now() }, changes);
242
+ const insertIndex = pendingMessages.findIndex((message) => message.role !== "system");
243
+ const index = insertIndex === -1 ? pendingMessages.length : insertIndex;
244
+ return [...pendingMessages.slice(0, index), update, ...pendingMessages.slice(index)];
245
+ }
246
+ const NO_CHANGES = { toolsAdded: [], toolsRemoved: [] };
247
+ /** Copy a system message with its tool fields replaced by `changes`; empty lists omit the field. */
248
+ function withToolChanges(message, { toolsAdded, toolsRemoved }) {
249
+ const { toolsAdded: _added, toolsRemoved: _removed, ...rest } = message;
250
+ return {
251
+ ...rest,
252
+ ...(toolsAdded.length > 0 ? { toolsAdded } : {}),
253
+ ...(toolsRemoved.length > 0 ? { toolsRemoved } : {}),
254
+ };
255
+ }
174
256
  /**
175
257
  * Stream an assistant response from the LLM.
176
258
  * This is where AgentMessage[] gets transformed to Message[] for the LLM.
@@ -183,12 +265,7 @@ async function streamAssistantResponse(context, config, signal, emit, streamFunc
183
265
  }
184
266
  // Convert to LLM-compatible messages (AgentMessage[] → Message[])
185
267
  const llmMessages = await config.convertToLlm(messages);
186
- // Build LLM context
187
- const llmContext = {
188
- systemPrompt: context.systemPrompt,
189
- messages: llmMessages,
190
- tools: context.tools,
191
- };
268
+ const llmContext = normalizeContext({ messages: llmMessages });
192
269
  // Resolve API key (important for expiring tokens)
193
270
  const resolvedApiKey = (config.getApiKey ? await config.getApiKey(config.model.provider) : undefined) || config.apiKey;
194
271
  const response = await streamFunction(config.model, llmContext, {
@@ -196,6 +273,8 @@ async function streamAssistantResponse(context, config, signal, emit, streamFunc
196
273
  apiKey: resolvedApiKey,
197
274
  signal,
198
275
  });
276
+ // Record the requested level, whichever stream function answered.
277
+ const result = async () => Object.assign(await response.result(), { thinkingLevel: config.reasoning ?? "off" });
199
278
  let partialMessage = null;
200
279
  let addedPartial = false;
201
280
  for await (const event of response) {
@@ -227,7 +306,7 @@ async function streamAssistantResponse(context, config, signal, emit, streamFunc
227
306
  break;
228
307
  case "done":
229
308
  case "error": {
230
- const finalMessage = await response.result();
309
+ const finalMessage = await result();
231
310
  if (addedPartial) {
232
311
  context.messages[context.messages.length - 1] = finalMessage;
233
312
  }
@@ -242,7 +321,7 @@ async function streamAssistantResponse(context, config, signal, emit, streamFunc
242
321
  }
243
322
  }
244
323
  }
245
- const finalMessage = await response.result();
324
+ const finalMessage = await result();
246
325
  if (addedPartial) {
247
326
  context.messages[context.messages.length - 1] = finalMessage;
248
327
  }
@@ -312,7 +391,7 @@ async function executeToolCallsSequential(currentContext, assistantMessage, tool
312
391
  };
313
392
  }
314
393
  else {
315
- const executed = await executePreparedToolCall(preparation, signal, emit);
394
+ const executed = await executePreparedToolCall(preparation, signal, emitToolExecutionUpdate(toolCall, emit));
316
395
  finalized = await finalizeExecutedToolCall(currentContext, assistantMessage, preparation, executed, config, signal);
317
396
  }
318
397
  await emitToolExecutionEnd(finalized, emit);
@@ -362,7 +441,7 @@ async function executeToolCallsParallel(currentContext, assistantMessage, toolCa
362
441
  await emitToolExecutionEnd(finalized, emit);
363
442
  return finalized;
364
443
  }
365
- const executed = await executePreparedToolCall(preparation, signal, emit);
444
+ const executed = await executePreparedToolCall(preparation, signal, emitToolExecutionUpdate(toolCall, emit));
366
445
  const finalized = await finalizeExecutedToolCall(currentContext, assistantMessage, preparation, executed, config, signal);
367
446
  await emitToolExecutionEnd(finalized, emit);
368
447
  return finalized;
@@ -399,8 +478,8 @@ function prepareToolCallArguments(tool, toolCall) {
399
478
  arguments: preparedArguments,
400
479
  };
401
480
  }
402
- async function prepareToolCall(currentContext, assistantMessage, toolCall, config, signal) {
403
- const tool = currentContext.tools?.find((t) => t.name === toolCall.name);
481
+ async function prepareToolCall(currentContext, assistantMessage, toolCall, config, signal, tools = currentContext.tools ?? []) {
482
+ const tool = tools.find((t) => t.name === toolCall.name);
404
483
  if (!tool) {
405
484
  return {
406
485
  kind: "immediate",
@@ -459,24 +538,45 @@ async function prepareToolCall(currentContext, assistantMessage, toolCall, confi
459
538
  };
460
539
  }
461
540
  }
462
- async function executePreparedToolCall(prepared, signal, emit) {
541
+ function emitToolExecutionUpdate(toolCall, emit) {
542
+ return (partialResult) => emit({
543
+ type: "tool_execution_update",
544
+ toolCallId: toolCall.id,
545
+ toolName: toolCall.name,
546
+ args: toolCall.arguments,
547
+ partialResult,
548
+ });
549
+ }
550
+ /**
551
+ * Run one tool call through the same steps as a model-issued call: argument preparation, schema
552
+ * validation, `beforeToolCall`, execution, and `afterToolCall`. Emits no events and adds no
553
+ * messages. Tools that call other tools use this so the hooks (for example permission checks)
554
+ * apply to those calls too.
555
+ *
556
+ * Never rejects for tool failures: unknown tools, validation errors, blocked calls, and thrown
557
+ * errors come back as `isError: true`.
558
+ */
559
+ export async function runToolCall(toolCall, options) {
560
+ const { assistantMessage, context, signal } = options;
561
+ const preparation = await prepareToolCall(context, assistantMessage, toolCall, options, signal, options.tools);
562
+ if (preparation.kind === "immediate") {
563
+ return { toolCall, result: preparation.result, isError: preparation.isError };
564
+ }
565
+ const executed = await executePreparedToolCall(preparation, signal, options.onUpdate ?? (() => { }));
566
+ return finalizeExecutedToolCall(context, assistantMessage, preparation, executed, options, signal);
567
+ }
568
+ async function executePreparedToolCall(prepared, signal, onUpdate) {
463
569
  const updateEvents = [];
464
570
  let acceptingUpdates = true;
465
571
  try {
466
572
  const result = await prepared.tool.execute(prepared.toolCall.id, prepared.args, signal, (partialResult) => {
467
573
  if (!acceptingUpdates)
468
574
  return;
469
- updateEvents.push(Promise.resolve(emit({
470
- type: "tool_execution_update",
471
- toolCallId: prepared.toolCall.id,
472
- toolName: prepared.toolCall.name,
473
- args: prepared.toolCall.arguments,
474
- partialResult,
475
- })));
575
+ updateEvents.push(Promise.resolve(onUpdate(partialResult)));
476
576
  });
477
577
  acceptingUpdates = false;
478
578
  await Promise.all(updateEvents);
479
- return { result, isError: false };
579
+ return { result, isError: result.isError === true };
480
580
  }
481
581
  catch (error) {
482
582
  acceptingUpdates = false;
@@ -504,6 +604,8 @@ async function finalizeExecutedToolCall(currentContext, assistantMessage, prepar
504
604
  context: currentContext,
505
605
  }, signal);
506
606
  if (afterResult) {
607
+ // Structured content not replaced along with the content may no longer match it.
608
+ const structuredContent = afterResult.structuredContent ?? (afterResult.content ? undefined : result.structuredContent);
507
609
  result = {
508
610
  ...result,
509
611
  content: afterResult.content ?? result.content,
@@ -511,6 +613,10 @@ async function finalizeExecutedToolCall(currentContext, assistantMessage, prepar
511
613
  usage: afterResult.usage ?? result.usage,
512
614
  terminate: afterResult.terminate ?? result.terminate,
513
615
  };
616
+ if (structuredContent === undefined)
617
+ delete result.structuredContent;
618
+ else
619
+ result.structuredContent = structuredContent;
514
620
  isError = afterResult.isError ?? isError;
515
621
  }
516
622
  }
@@ -550,7 +656,6 @@ function createToolResultMessage(finalized) {
550
656
  content: finalized.result.content ?? [],
551
657
  details: finalized.result.details,
552
658
  usage: finalized.result.usage,
553
- ...(finalized.result.addedToolNames?.length ? { addedToolNames: finalized.result.addedToolNames } : {}),
554
659
  isError: finalized.isError,
555
660
  timestamp: Date.now(),
556
661
  };