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

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
@@ -0,0 +1,654 @@
1
+ import { withAbortSignal } from "@draht/chord/context";
2
+ import { createHookRunners } from "./hooks.js";
3
+ import { chooseThrough, collapse } from "./kinds/collapse.js";
4
+ import { entries as builtinEntries } from "./kinds/entries.js";
5
+ import { generation } from "./kinds/generation.js";
6
+ import { job } from "./kinds/job.js";
7
+ import { plugin } from "./kinds/plugin.js";
8
+ import { postTools } from "./kinds/post-tools.js";
9
+ import { tool } from "./kinds/tool.js";
10
+ import { Scheduler } from "./scheduler.js";
11
+ import { isCoreKind, Session } from "./session.js";
12
+ import { systemSections } from "./system.js";
13
+ import { Forbidden, } from "./types.js";
14
+ import { ViewManager } from "./view.js";
15
+ const KERNEL = { type: "kernel" };
16
+ export class Harness {
17
+ session;
18
+ scheduler;
19
+ views;
20
+ kinds;
21
+ namespaces = new Map();
22
+ tools = new Map();
23
+ sectionMap = new Map();
24
+ entryKinds = new Map();
25
+ revisions = { sections: 0, tools: 0 };
26
+ plugins;
27
+ hookRegistrations = [];
28
+ conversationListeners = new Set();
29
+ onReport;
30
+ now;
31
+ ctx;
32
+ options;
33
+ resumed = false;
34
+ suspended = false;
35
+ static async open(storage, options, ctx) {
36
+ const h = new Harness(storage, options, ctx);
37
+ await h.init();
38
+ return h;
39
+ }
40
+ constructor(storage, options, ctx) {
41
+ this.ctx = ctx;
42
+ this.options = options;
43
+ this.now = options.now ?? Date.now;
44
+ this.onReport = (error) => {
45
+ try {
46
+ options.onReport?.(error);
47
+ }
48
+ catch { }
49
+ };
50
+ // Fixed core, installed internally. User kinds may not replace or shadow a built-in.
51
+ const builtins = [generation, tool, postTools, collapse, job, plugin];
52
+ this.kinds = new Map(builtins.map((k) => [k.name, k]));
53
+ for (const k of options.taskKinds ?? []) {
54
+ if (k.name.startsWith("pi."))
55
+ throw new Error(`task kind "${k.name}": names beginning with "pi." are reserved`);
56
+ if (this.kinds.has(k.name))
57
+ throw new Error(`task kind "${k.name}" registered twice`);
58
+ this.kinds.set(k.name, k);
59
+ }
60
+ for (const t of options.tools ?? [])
61
+ this.registerTool(t, "open");
62
+ for (const s of Object.values(systemSections))
63
+ this.sectionMap.set(s.key, s);
64
+ for (const s of options.sections ?? [])
65
+ this.registerSection(s, "open");
66
+ for (const e of Object.values(builtinEntries))
67
+ this.entryKinds.set(e.kind, e);
68
+ this.plugins = new Map(Object.entries(options.plugins ?? {}));
69
+ this.session = new Session(storage, this.kinds, this.namespaces, this.now); // throws if the Storage already has an owner; validates config disjointness
70
+ this.session.onReport = this.onReport;
71
+ this.views = new ViewManager(this.session, this.onReport);
72
+ this.session.lineListeners.add((result) => this.views.update(result));
73
+ this.session.listeners.add((result) => {
74
+ this.views.deliver();
75
+ for (const conversation of result.changes.conversations)
76
+ this.notifyConversation(conversation);
77
+ });
78
+ const self = this;
79
+ const hooksFor = createHookRunners(() => this.hookRegistrations, (c) => this.session.index.ancestors(c), this.onReport);
80
+ this.scheduler = new Scheduler({
81
+ session: this.session,
82
+ kinds: this.kinds,
83
+ onReport: this.onReport,
84
+ ctx,
85
+ runtime(task, invoker, _ictx) {
86
+ return {
87
+ taskId: task.id,
88
+ conversationId: task.conversationId,
89
+ kind: invoker.kind,
90
+ commit: (fn, c) => {
91
+ const owns = self.session.liveTasks.get(task.id)?.owns ?? [];
92
+ const docs = owns.flatMap((id) => [
93
+ { doc: "rewindable", conversationId: id },
94
+ { doc: "sticky", conversationId: id },
95
+ ]);
96
+ return self.session
97
+ .commit(invoker, (tx, lineCtx) => fn(tx, self.session.liveTasks.get(task.id), lineCtx), c, {
98
+ docs,
99
+ })
100
+ .then((r) => r.value);
101
+ },
102
+ hooks: hooksFor(invoker.kind, { taskId: task.id, conversationId: task.conversationId }),
103
+ models: options.models,
104
+ tools: self.tools,
105
+ registries: {
106
+ sections: {
107
+ map: self.sectionMap,
108
+ get revision() {
109
+ return self.revisions.sections;
110
+ },
111
+ },
112
+ tools: {
113
+ map: self.tools,
114
+ get revision() {
115
+ return self.revisions.tools;
116
+ },
117
+ },
118
+ },
119
+ kinds: self.kinds,
120
+ processHost: options.processHost,
121
+ plugins: self.plugins,
122
+ now: self.now,
123
+ sleep: (untilMs, c) => new Promise((resolve, reject) => {
124
+ const ms = Math.max(0, untilMs - Date.now());
125
+ const t = setTimeout(() => {
126
+ c.abortSignal?.removeEventListener("abort", onAbort);
127
+ resolve();
128
+ }, ms);
129
+ const onAbort = () => {
130
+ clearTimeout(t);
131
+ reject(c.abortSignal?.reason ?? new Error("aborted"));
132
+ };
133
+ c.abortSignal?.addEventListener("abort", onAbort, { once: true });
134
+ }),
135
+ waitForInput: (id, c) => self.scheduler.waitForInput(id, c),
136
+ waitForTask: (id, c) => self.scheduler.waitForTask(id, c),
137
+ abortTask: async (id, c) => {
138
+ await self.session.onLine(async (lineCtx) => {
139
+ self.assertInvocation(invoker);
140
+ const target = self.session.liveTasks.get(id) ?? (await self.session.storage.task(id, lineCtx));
141
+ if (target === undefined)
142
+ throw new Error(`task ${id} not found`);
143
+ self.assertTaskConversationScope(task.id, target.conversationId);
144
+ }, c);
145
+ return self.scheduler.abortTask(id, c);
146
+ },
147
+ abortConversation: async (id, c) => {
148
+ await self.session.onLine(() => {
149
+ self.assertInvocation(invoker);
150
+ self.assertOwnedConversation(task.id, id);
151
+ }, c);
152
+ const h = await self.conversation(id, c);
153
+ if (h)
154
+ await h.abort(c);
155
+ },
156
+ createOwnedConversation: (spec, c) => self.session
157
+ .commit(KERNEL, (tx) => {
158
+ self.assertInvocation(invoker);
159
+ return tx.createOwnedConversation(task.id, task.conversationId, spec);
160
+ }, c)
161
+ .then((result) => result.value),
162
+ sendOwned: (id, input, c) => self.session
163
+ .commit(KERNEL, (tx) => {
164
+ self.assertInvocation(invoker);
165
+ self.assertOwnedConversation(task.id, id);
166
+ return tx.send(id, input);
167
+ }, c, {
168
+ docs: [
169
+ { doc: "rewindable", conversationId: id },
170
+ { doc: "sticky", conversationId: id },
171
+ ],
172
+ })
173
+ .then((r) => r.value),
174
+ context: (c, at, cx) => self.session.commit(invoker, (tx) => tx.context(c, at), cx).then((r) => r.value),
175
+ newestEntry: (c, opts, cx) => self.session.commit(invoker, (tx) => tx.newestEntry(c, opts), cx).then((r) => r.value),
176
+ rewindable: (c, cx) => self.session
177
+ .commit(invoker, (tx) => tx.snapshot({ doc: "rewindable", conversationId: c }), cx, {
178
+ docs: [{ doc: "rewindable", conversationId: c }],
179
+ })
180
+ .then((r) => r.value),
181
+ sticky: (c, cx) => self.session
182
+ .commit(invoker, (tx) => tx.snapshot({ doc: "sticky", conversationId: c }), cx, {
183
+ docs: [{ doc: "sticky", conversationId: c }],
184
+ })
185
+ .then((r) => r.value),
186
+ rewindableAsOf: (c, at, cx) => self.session.commit(invoker, (tx) => tx.rewindableAsOf(c, at), cx).then((r) => r.value),
187
+ };
188
+ },
189
+ });
190
+ }
191
+ notifyConversation(conversation) {
192
+ if (this.conversationListeners.size === 0)
193
+ return;
194
+ const handle = this.handle(conversation);
195
+ for (const listener of [...this.conversationListeners]) {
196
+ try {
197
+ listener(handle);
198
+ }
199
+ catch (error) {
200
+ this.onReport(error);
201
+ }
202
+ }
203
+ }
204
+ assertInvocation(invoker) {
205
+ if (!invoker.token.alive)
206
+ throw new Forbidden("operation from a finished invocation");
207
+ const live = this.session.liveTasks.get(invoker.id);
208
+ if (live === undefined)
209
+ throw new Forbidden("operation from a task that is not live");
210
+ if (invoker.mode === "run" && live.abort === true)
211
+ throw new Forbidden("operation from a marked run invocation");
212
+ }
213
+ assertTaskConversationScope(taskId, conversationId) {
214
+ const task = this.session.liveTasks.get(taskId);
215
+ if (task?.conversationId === conversationId)
216
+ return;
217
+ if (task?.owns.some((root) => this.session.index.subtree(root).has(conversationId)))
218
+ return;
219
+ throw new Forbidden(`conversation ${conversationId} is outside task ${taskId}'s subtree`);
220
+ }
221
+ assertOwnedConversation(taskId, conversationId) {
222
+ const task = this.session.liveTasks.get(taskId);
223
+ if (task === undefined || !task.owns.some((root) => this.session.index.subtree(root).has(conversationId))) {
224
+ throw new Forbidden(`conversation ${conversationId} is not owned by task ${taskId}`);
225
+ }
226
+ }
227
+ async init() {
228
+ const { session } = this;
229
+ const convs = await session.read((s, ctx) => s.conversations(ctx), this.ctx);
230
+ for (const c of convs)
231
+ session.conversationRecords.set(c.id, c);
232
+ const live = await session.read((s, ctx) => s.scanTasks({ status: ["pending", "running"] }, ctx), this.ctx);
233
+ for (const task of live)
234
+ session.liveTasks.set(task.id, task);
235
+ // Owner tasks that are terminal but still own existing conversations: needed for ancestry.
236
+ const owners = new Set(convs.map((c) => c.owner).filter((o) => o !== undefined));
237
+ for (const id of owners)
238
+ if (!session.liveTasks.has(id)) {
239
+ const t = await session.read((s, ctx) => s.task(id, ctx), this.ctx);
240
+ if (t)
241
+ session.ownerTaskCache.set(id, t);
242
+ }
243
+ if (convs.length === 0) {
244
+ await session.commit(KERNEL, (tx) => tx.createConversation({ rewindable: this.options.root?.rewindable, sticky: this.options.root?.sticky }), this.ctx);
245
+ }
246
+ }
247
+ resume() {
248
+ if (this.suspended)
249
+ throw new Error("cannot resume a suspended harness; reopen storage with a new harness");
250
+ if (this.resumed)
251
+ return;
252
+ this.resumed = true;
253
+ void this.reconcileOrphans()
254
+ .then(() => {
255
+ if (!this.suspended)
256
+ this.scheduler.resume();
257
+ })
258
+ .catch((error) => this.onReport(error));
259
+ }
260
+ async reconcileOrphans() {
261
+ const orphaned = [...this.session.liveTasks.values()].filter((task) => !this.kinds.has(task.kind));
262
+ if (orphaned.length === 0)
263
+ return;
264
+ const docs = [...new Set(orphaned.map((task) => task.conversationId))].map((conversationId) => ({ doc: "sticky", conversationId }));
265
+ await this.session.commit(KERNEL, (tx) => {
266
+ for (const task of orphaned)
267
+ tx.setTask({ ...task, status: "terminal", outcome: { status: "orphaned" } });
268
+ }, this.ctx, { docs });
269
+ }
270
+ quiescent() {
271
+ return this.scheduler.quiescent();
272
+ }
273
+ hold() {
274
+ if (!this.scheduler.quiescent())
275
+ throw new Error("cannot hold a non-quiescent harness; suspend it instead");
276
+ return this.scheduler.hold();
277
+ }
278
+ /** Cancel and join in-process invocations, clear transient waits, then close without terminalizing tasks. */
279
+ async suspend(ctx) {
280
+ if (this.suspended)
281
+ return;
282
+ this.suspended = true;
283
+ await this.scheduler.joinAll();
284
+ const tools = [...this.session.liveTasks.values()].filter((task) => task.kind === "pi.tool");
285
+ if (tools.length > 0) {
286
+ const docs = [...new Set(tools.map((task) => task.conversationId))].map((conversationId) => ({ doc: "sticky", conversationId }));
287
+ await this.session.commit(KERNEL, (tx) => {
288
+ for (const task of tools) {
289
+ const index = task.input.index;
290
+ const slot = tx.sticky(task.conversationId).turn.tools[index];
291
+ if (slot?.waitingOn !== undefined)
292
+ delete slot.waitingOn;
293
+ }
294
+ }, ctx, { docs });
295
+ }
296
+ this.views.close();
297
+ await this.session.close(ctx);
298
+ }
299
+ // --- registries --------------------------------------------------------------
300
+ registerTaskKind(kind) {
301
+ if (kind.name.startsWith("pi."))
302
+ throw new Error(`task kind "${kind.name}": names beginning with "pi." are reserved`);
303
+ if (this.kinds.has(kind.name))
304
+ throw new Error(`task kind "${kind.name}" already registered`);
305
+ this.session.defaults.register(kind);
306
+ this.kinds.set(kind.name, kind);
307
+ this.scheduler.kick();
308
+ return () => {
309
+ if (this.kinds.get(kind.name) !== kind)
310
+ return;
311
+ this.kinds.delete(kind.name);
312
+ this.session.defaults.unregister(kind);
313
+ };
314
+ }
315
+ namespace(id, defaults, opts = {}) {
316
+ if (!/^[a-z][a-z0-9_.-]*$/i.test(id) || id.startsWith("pi."))
317
+ throw new Error(`invalid namespace "${id}"`);
318
+ if (this.namespaces.has(id))
319
+ throw new Error(`namespace "${id}" already registered`);
320
+ const stored = JSON.parse(JSON.stringify(defaults));
321
+ const routes = new Map();
322
+ for (const doc of ["rewindable", "sticky", "session"]) {
323
+ for (const key of Object.keys(stored[doc] ?? {})) {
324
+ if (routes.has(key))
325
+ throw new Error(`namespace "${id}" key "${key}" is declared in more than one document`);
326
+ routes.set(key, doc);
327
+ }
328
+ }
329
+ let token;
330
+ token = {
331
+ id,
332
+ unregister: () => {
333
+ if (this.namespaces.get(id)?.token !== token)
334
+ return;
335
+ this.namespaces.delete(id);
336
+ for (let index = this.hookRegistrations.length - 1; index >= 0; index--) {
337
+ if (this.hookRegistrations[index].namespace === token)
338
+ this.hookRegistrations.splice(index, 1);
339
+ }
340
+ },
341
+ };
342
+ const registration = {
343
+ token,
344
+ defaults: {
345
+ rewindable: stored.rewindable ?? {},
346
+ sticky: stored.sticky ?? {},
347
+ session: stored.session ?? {},
348
+ },
349
+ routes,
350
+ project: opts.view === undefined ? undefined : (slice) => opts.view(slice),
351
+ };
352
+ this.namespaces.set(id, registration);
353
+ return token;
354
+ }
355
+ /** Register a tool. A duplicate name rejects. Unregister removes only this exact declaration; idempotent. */
356
+ registerTool(tool, at = "runtime") {
357
+ if (this.tools.has(tool.name))
358
+ throw new Error(`tool "${tool.name}" already registered`);
359
+ this.tools.set(tool.name, tool);
360
+ this.revisions.tools++;
361
+ void at;
362
+ return () => {
363
+ if (this.tools.get(tool.name) === tool) {
364
+ this.tools.delete(tool.name);
365
+ this.revisions.tools++;
366
+ }
367
+ };
368
+ }
369
+ registerSection(section, at = "runtime") {
370
+ if (this.sectionMap.has(section.key))
371
+ throw new Error(`section "${section.key}" already registered`);
372
+ this.sectionMap.set(section.key, section);
373
+ this.revisions.sections++;
374
+ void at;
375
+ return () => {
376
+ if (this.sectionMap.get(section.key) === section) {
377
+ this.sectionMap.delete(section.key);
378
+ this.revisions.sections++;
379
+ }
380
+ };
381
+ }
382
+ registerEntryKind(kind) {
383
+ if (kind.kind.startsWith("pi."))
384
+ throw new Error(`entry kind "${kind.kind}": names beginning with "pi." are reserved`);
385
+ if (this.entryKinds.has(kind.kind))
386
+ throw new Error(`entry kind "${kind.kind}" already registered`);
387
+ this.entryKinds.set(kind.kind, kind);
388
+ return () => {
389
+ if (this.entryKinds.get(kind.kind) === kind)
390
+ this.entryKinds.delete(kind.kind);
391
+ };
392
+ }
393
+ /** Register namespace-bound handlers for one kind's hook points, harness-wide. Both tokens must be current. */
394
+ hooks(namespace, kind, handlers, _opts) {
395
+ return this.addHooks({ namespace: this.checkNamespace(namespace), kind: this.checkKind(kind), handlers });
396
+ }
397
+ checkKind(kind) {
398
+ if (this.kinds.get(kind.name) !== kind)
399
+ throw new Error(`kind "${kind.name}" is not the registered token`);
400
+ return kind;
401
+ }
402
+ checkNamespace(namespace) {
403
+ if (this.namespaces.get(namespace.id)?.token !== namespace)
404
+ throw new Forbidden(`namespace "${namespace.id}" is stale`);
405
+ return namespace;
406
+ }
407
+ addHooks(reg) {
408
+ this.hookRegistrations.push(reg);
409
+ let done = false;
410
+ return () => {
411
+ if (done)
412
+ return;
413
+ done = true;
414
+ const index = this.hookRegistrations.indexOf(reg);
415
+ if (index >= 0)
416
+ this.hookRegistrations.splice(index, 1);
417
+ };
418
+ }
419
+ // --- conversations -------------------------------------------------------------
420
+ async root(ctx) {
421
+ return this.conversation(1, ctx).then((c) => c);
422
+ }
423
+ onConversation(listener) {
424
+ this.conversationListeners.add(listener);
425
+ for (const conversation of this.session.conversationRecords.values()) {
426
+ try {
427
+ listener(this.handle(conversation));
428
+ }
429
+ catch (error) {
430
+ this.onReport(error);
431
+ }
432
+ }
433
+ return () => this.conversationListeners.delete(listener);
434
+ }
435
+ async conversation(id, ctx) {
436
+ const c = await this.session.read((s, lineCtx) => s.conversation(id, lineCtx), ctx);
437
+ return c === undefined ? undefined : this.handle(c);
438
+ }
439
+ async createConversation(spec, ctx) {
440
+ const { input, ...rest } = spec;
441
+ const id = await this.session
442
+ .commit(KERNEL, async (tx) => {
443
+ const id = tx.createConversation(rest);
444
+ if (input !== undefined)
445
+ await tx.send(id, { content: input });
446
+ return id;
447
+ }, ctx)
448
+ .then((r) => r.value);
449
+ return (await this.conversation(id, ctx));
450
+ }
451
+ entries(scan, ctx) {
452
+ return this.session.read((s, lineCtx) => s.scanEntries(scan, lineCtx), ctx);
453
+ }
454
+ getTask(id, ctx) {
455
+ return this.session.read((s, lineCtx) => s.task(id, lineCtx), ctx);
456
+ }
457
+ async abortInput(id, ctx, conversationId) {
458
+ if (conversationId !== undefined) {
459
+ const input = await this.session.read((storage, lineCtx) => storage.input(id, lineCtx), ctx);
460
+ if (input !== undefined && input.conversationId !== conversationId)
461
+ throw new Forbidden(`input ${id} is outside conversation ${conversationId}`);
462
+ }
463
+ return this.inputHandle(id).abort(ctx);
464
+ }
465
+ abortTask(id, ctx) {
466
+ return this.scheduler.abortTask(id, ctx);
467
+ }
468
+ /** Durably mark a task for abort without signalling its invocation; the scheduler aborts it when it next drains. */
469
+ markTask(id, ctx) {
470
+ return this.session
471
+ .commit(KERNEL, async (tx) => {
472
+ const t = await tx.task(id);
473
+ if (t === undefined)
474
+ throw new Error(`task ${id} not found`);
475
+ if (t.status === "terminal")
476
+ return "terminal";
477
+ tx.markTask(id);
478
+ return "marked";
479
+ }, ctx)
480
+ .then((r) => r.value);
481
+ }
482
+ waitForIdle(ctx) {
483
+ return this.scheduler.waitForIdle(undefined, ctx);
484
+ }
485
+ waitForTask(id, ctx) {
486
+ return this.scheduler.waitForTask(id, ctx);
487
+ }
488
+ /** Signals every invocation, waits for them, closes storage. Writes nothing. */
489
+ async close(ctx) {
490
+ await this.suspend(ctx);
491
+ }
492
+ handle(c) {
493
+ const self = this;
494
+ const docs = [
495
+ { doc: "rewindable", conversationId: c.id },
496
+ { doc: "sticky", conversationId: c.id },
497
+ ];
498
+ const hostInvoker = { type: "host", conversationId: c.id };
499
+ const kernelInvoker = { type: "kernel", conversationId: c.id };
500
+ const host = (fn, ctx) => self.session.commit(hostInvoker, (tx, lineCtx) => fn(tx, lineCtx), ctx, { docs }).then((r) => r.value);
501
+ const kernel = (fn, ctx) => self.session.commit(kernelInvoker, fn, ctx, { docs }).then((r) => r.value);
502
+ const config = {
503
+ get: (ctx) => host((tx) => {
504
+ const cfg = tx.config(c.id);
505
+ const out = {};
506
+ for (const key of self.session.defaults.route.keys())
507
+ out[key] = cfg.get(key);
508
+ return out;
509
+ }, ctx),
510
+ set: (patch, ctx) => host((tx) => {
511
+ const cfg = tx.config(c.id);
512
+ for (const [key, value] of Object.entries(patch)) {
513
+ if (value === undefined)
514
+ throw new Error(`config.set(${key}): use config.reset()`);
515
+ cfg.set(key, value);
516
+ }
517
+ }, ctx),
518
+ reset: (keys, ctx) => host((tx) => {
519
+ const cfg = tx.config(c.id);
520
+ for (const key of keys)
521
+ cfg.reset(String(key));
522
+ }, ctx),
523
+ };
524
+ return {
525
+ id: c.id,
526
+ config,
527
+ async send(input, ctx) {
528
+ const id = await kernel((tx) => tx.send(c.id, input), ctx);
529
+ return self.inputHandle(id);
530
+ },
531
+ write: (entry, ctx) => host((tx) => tx.write(c.id, entry), ctx),
532
+ commit: host,
533
+ rewindable: (ctx) => host((tx) => tx.snapshot({ doc: "rewindable", conversationId: c.id }), ctx),
534
+ sticky: (ctx) => host((tx) => tx.snapshot({ doc: "sticky", conversationId: c.id }), ctx),
535
+ context: (ctx) => host((tx) => tx.context(c.id), ctx),
536
+ async fork(at, spec, ctx) {
537
+ const id = await self.session.fork(c.id, at, spec, ctx);
538
+ return (await self.conversation(id, ctx));
539
+ },
540
+ collapse: (instructions, ctx) => kernel(async (tx) => {
541
+ const { entries } = await tx.context(c.id);
542
+ const state = tx.rewindable(c.id);
543
+ const through = chooseThrough(entries, state.keepRecent);
544
+ if (through === undefined)
545
+ throw new Error("nothing to collapse");
546
+ return tx.createTask({
547
+ kind: "pi.collapse",
548
+ conversationId: c.id,
549
+ background: true,
550
+ input: { reason: "manual", through, ...(instructions === undefined ? {} : { instructions }) },
551
+ });
552
+ }, ctx),
553
+ reset: async (handoff, ctx) => {
554
+ await kernel((tx) => tx.write(c.id, handoff === undefined
555
+ ? { kind: "pi.reset", head: "self" }
556
+ : {
557
+ kind: "pi.handoff",
558
+ head: "self",
559
+ model: [{ role: "user", content: handoff, timestamp: self.now() }],
560
+ }), ctx);
561
+ },
562
+ async abort(ctx) {
563
+ const owned = [];
564
+ const marked = await kernel(async (tx) => {
565
+ const s = tx.sticky(c.id);
566
+ const withdrawn = s.inbox.filter((q) => q.mode !== "write").map((q) => q.id);
567
+ for (let i = s.inbox.length - 1; i >= 0; i--)
568
+ if (s.inbox[i].mode !== "write")
569
+ s.inbox.splice(i, 1);
570
+ await tx.resolveInputs(withdrawn, { status: "unanswered", reason: "aborted" });
571
+ for (const input of withdrawn)
572
+ tx.emit({ type: "input.aborted", input });
573
+ const ids = [];
574
+ for (const t of [...self.session.liveTasks.values()]) {
575
+ if (t.conversationId !== c.id || t.background)
576
+ continue;
577
+ for (const o of t.owns)
578
+ owned.push(o);
579
+ if (t.abort !== true)
580
+ tx.markTask(t.id);
581
+ ids.push(t.id);
582
+ }
583
+ return ids;
584
+ }, ctx);
585
+ for (const id of marked)
586
+ await self.scheduler.abortTask(id, ctx);
587
+ await self.scheduler.waitForIdle(c.id, ctx);
588
+ await Promise.all(owned.map((o) => self.scheduler.waitForIdle(o, ctx)));
589
+ },
590
+ waitForIdle: (ctx) => self.scheduler.waitForIdle(c.id, ctx),
591
+ hooks: (namespace, kind, handlers, opts) => self.addHooks({
592
+ namespace: self.checkNamespace(namespace),
593
+ kind: self.checkKind(kind),
594
+ handlers,
595
+ conversationId: c.id,
596
+ subtree: opts?.subtree,
597
+ }),
598
+ watch: (ctx) => self.watch(c, ctx),
599
+ };
600
+ }
601
+ /** Capture and subscribe in one line operation. */
602
+ async watch(conversation, ctx) {
603
+ return this.session
604
+ .commit({ type: "host", conversationId: conversation.id }, async (tx) => {
605
+ const entries = await captureActiveTranscript((scan) => tx.scanEntries(scan), conversation.id);
606
+ return this.views.watch(conversation, entries);
607
+ }, ctx, {
608
+ docs: [
609
+ { doc: "rewindable", conversationId: conversation.id },
610
+ { doc: "sticky", conversationId: conversation.id },
611
+ ],
612
+ })
613
+ .then((result) => result.value);
614
+ }
615
+ inputHandle(id) {
616
+ return {
617
+ id,
618
+ result: (ctx) => this.session.read((s, lineCtx) => s.input(id, lineCtx), ctx),
619
+ wait: (ctx) => this.scheduler.waitForInput(id, ctx),
620
+ abort: (ctx) => this.session.commit(KERNEL, (tx) => tx.withdrawInput(id), ctx, { docs: [] }).then((r) => r.value),
621
+ };
622
+ }
623
+ }
624
+ /**
625
+ * §9: H = newest fork-visible entry with a head. Active transcript = H plus every fork-visible entry
626
+ * with id ≥ H.head, chronological, nothing dropped inside the range; the whole transcript if no head.
627
+ */
628
+ export async function captureActiveTranscript(scan, conversationId) {
629
+ const [h] = await scan({ conversationId, withHead: true, limit: 1 });
630
+ const from = h?.head;
631
+ const out = [];
632
+ let before;
633
+ for (;;) {
634
+ const page = await scan({ conversationId, ...(before === undefined ? {} : { before }), limit: 256 });
635
+ let done = page.length < 256;
636
+ for (const e of page) {
637
+ if (from !== undefined && e.id < from) {
638
+ done = true;
639
+ break;
640
+ }
641
+ out.push(e);
642
+ }
643
+ if (done)
644
+ break;
645
+ before = page[page.length - 1].id;
646
+ }
647
+ return out.reverse();
648
+ }
649
+ export { withAbortSignal, isCoreKind };
650
+ export { applyEnvelope, WATCH_CAPACITY } from "./view.js";
651
+ /** The built-in kinds, as typed witnesses for `api.task`, `waitForTask`, and `hooks(kind, …)`. */
652
+ export const kinds = { generation, tool, postTools, collapse, job, plugin };
653
+ export const entries = builtinEntries;
654
+ //# sourceMappingURL=harness.js.map