@oni.bot/core 1.0.0 → 1.0.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 (511) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/SECURITY.md +2 -2
  3. package/dist/agents/context.d.ts +0 -2
  4. package/dist/agents/context.d.ts.map +1 -1
  5. package/dist/agents/context.js +1 -3
  6. package/dist/agents/context.js.map +1 -1
  7. package/dist/agents/define-agent.d.ts.map +1 -1
  8. package/dist/agents/define-agent.js +92 -39
  9. package/dist/agents/define-agent.js.map +1 -1
  10. package/dist/agents/functional-agent.d.ts.map +1 -1
  11. package/dist/agents/functional-agent.js +0 -7
  12. package/dist/agents/functional-agent.js.map +1 -1
  13. package/dist/agents/types.d.ts +0 -2
  14. package/dist/agents/types.d.ts.map +1 -1
  15. package/dist/checkpointers/postgres.js +4 -4
  16. package/dist/checkpointers/postgres.js.map +1 -1
  17. package/dist/checkpointers/sqlite.js +4 -4
  18. package/dist/checkpointers/sqlite.js.map +1 -1
  19. package/dist/cli/router.js +1 -1
  20. package/dist/config/loader.d.ts.map +1 -1
  21. package/dist/config/loader.js +23 -1
  22. package/dist/config/loader.js.map +1 -1
  23. package/dist/context.d.ts +20 -0
  24. package/dist/context.d.ts.map +1 -1
  25. package/dist/context.js.map +1 -1
  26. package/dist/coordination/request-reply.d.ts +1 -0
  27. package/dist/coordination/request-reply.d.ts.map +1 -1
  28. package/dist/coordination/request-reply.js +13 -1
  29. package/dist/coordination/request-reply.js.map +1 -1
  30. package/dist/graph.d.ts.map +1 -1
  31. package/dist/graph.js +17 -2
  32. package/dist/graph.js.map +1 -1
  33. package/dist/index.js +1 -1
  34. package/dist/mcp/client.js +1 -1
  35. package/dist/pregel.d.ts +2 -0
  36. package/dist/pregel.d.ts.map +1 -1
  37. package/dist/pregel.js +415 -341
  38. package/dist/pregel.js.map +1 -1
  39. package/dist/store/index.d.ts +1 -1
  40. package/dist/store/index.d.ts.map +1 -1
  41. package/dist/store/index.js +28 -5
  42. package/dist/store/index.js.map +1 -1
  43. package/dist/streaming.d.ts +5 -2
  44. package/dist/streaming.d.ts.map +1 -1
  45. package/dist/streaming.js +9 -8
  46. package/dist/streaming.js.map +1 -1
  47. package/dist/swarm/graph.d.ts +1 -0
  48. package/dist/swarm/graph.d.ts.map +1 -1
  49. package/dist/swarm/graph.js +162 -40
  50. package/dist/swarm/graph.js.map +1 -1
  51. package/dist/swarm/pool.d.ts.map +1 -1
  52. package/dist/swarm/pool.js +12 -4
  53. package/dist/swarm/pool.js.map +1 -1
  54. package/dist/tools/define.d.ts.map +1 -1
  55. package/dist/tools/define.js +1 -0
  56. package/dist/tools/define.js.map +1 -1
  57. package/dist/tools/types.d.ts +2 -0
  58. package/dist/tools/types.d.ts.map +1 -1
  59. package/package.json +7 -1
  60. package/dist/oni-code/agent-registry.d.ts +0 -73
  61. package/dist/oni-code/agent-registry.d.ts.map +0 -1
  62. package/dist/oni-code/agent-registry.js +0 -151
  63. package/dist/oni-code/agent-registry.js.map +0 -1
  64. package/dist/oni-code/bin.d.ts +0 -18
  65. package/dist/oni-code/bin.d.ts.map +0 -1
  66. package/dist/oni-code/bin.js +0 -78
  67. package/dist/oni-code/bin.js.map +0 -1
  68. package/dist/oni-code/change-tracking.d.ts +0 -28
  69. package/dist/oni-code/change-tracking.d.ts.map +0 -1
  70. package/dist/oni-code/change-tracking.js +0 -77
  71. package/dist/oni-code/change-tracking.js.map +0 -1
  72. package/dist/oni-code/cli.d.ts +0 -6
  73. package/dist/oni-code/cli.d.ts.map +0 -1
  74. package/dist/oni-code/cli.js +0 -30
  75. package/dist/oni-code/cli.js.map +0 -1
  76. package/dist/oni-code/conductor.d.ts +0 -203
  77. package/dist/oni-code/conductor.d.ts.map +0 -1
  78. package/dist/oni-code/conductor.js +0 -1547
  79. package/dist/oni-code/conductor.js.map +0 -1
  80. package/dist/oni-code/config.d.ts +0 -130
  81. package/dist/oni-code/config.d.ts.map +0 -1
  82. package/dist/oni-code/config.js +0 -264
  83. package/dist/oni-code/config.js.map +0 -1
  84. package/dist/oni-code/context-files.d.ts +0 -22
  85. package/dist/oni-code/context-files.d.ts.map +0 -1
  86. package/dist/oni-code/context-files.js +0 -156
  87. package/dist/oni-code/context-files.js.map +0 -1
  88. package/dist/oni-code/cron/humanize.d.ts +0 -26
  89. package/dist/oni-code/cron/humanize.d.ts.map +0 -1
  90. package/dist/oni-code/cron/humanize.js +0 -83
  91. package/dist/oni-code/cron/humanize.js.map +0 -1
  92. package/dist/oni-code/cron/index.d.ts +0 -10
  93. package/dist/oni-code/cron/index.d.ts.map +0 -1
  94. package/dist/oni-code/cron/index.js +0 -7
  95. package/dist/oni-code/cron/index.js.map +0 -1
  96. package/dist/oni-code/cron/matcher.d.ts +0 -29
  97. package/dist/oni-code/cron/matcher.d.ts.map +0 -1
  98. package/dist/oni-code/cron/matcher.js +0 -73
  99. package/dist/oni-code/cron/matcher.js.map +0 -1
  100. package/dist/oni-code/cron/parser.d.ts +0 -27
  101. package/dist/oni-code/cron/parser.d.ts.map +0 -1
  102. package/dist/oni-code/cron/parser.js +0 -149
  103. package/dist/oni-code/cron/parser.js.map +0 -1
  104. package/dist/oni-code/cron/persistence.d.ts +0 -21
  105. package/dist/oni-code/cron/persistence.d.ts.map +0 -1
  106. package/dist/oni-code/cron/persistence.js +0 -58
  107. package/dist/oni-code/cron/persistence.js.map +0 -1
  108. package/dist/oni-code/cron/scheduler.d.ts +0 -64
  109. package/dist/oni-code/cron/scheduler.d.ts.map +0 -1
  110. package/dist/oni-code/cron/scheduler.js +0 -188
  111. package/dist/oni-code/cron/scheduler.js.map +0 -1
  112. package/dist/oni-code/cron/store.d.ts +0 -46
  113. package/dist/oni-code/cron/store.d.ts.map +0 -1
  114. package/dist/oni-code/cron/store.js +0 -68
  115. package/dist/oni-code/cron/store.js.map +0 -1
  116. package/dist/oni-code/env.d.ts +0 -17
  117. package/dist/oni-code/env.d.ts.map +0 -1
  118. package/dist/oni-code/env.js +0 -51
  119. package/dist/oni-code/env.js.map +0 -1
  120. package/dist/oni-code/file-reader.d.ts +0 -28
  121. package/dist/oni-code/file-reader.d.ts.map +0 -1
  122. package/dist/oni-code/file-reader.js +0 -368
  123. package/dist/oni-code/file-reader.js.map +0 -1
  124. package/dist/oni-code/file-watcher.d.ts +0 -66
  125. package/dist/oni-code/file-watcher.d.ts.map +0 -1
  126. package/dist/oni-code/file-watcher.js +0 -167
  127. package/dist/oni-code/file-watcher.js.map +0 -1
  128. package/dist/oni-code/loop-detector.d.ts +0 -64
  129. package/dist/oni-code/loop-detector.d.ts.map +0 -1
  130. package/dist/oni-code/loop-detector.js +0 -163
  131. package/dist/oni-code/loop-detector.js.map +0 -1
  132. package/dist/oni-code/permissions.d.ts +0 -43
  133. package/dist/oni-code/permissions.d.ts.map +0 -1
  134. package/dist/oni-code/permissions.js +0 -98
  135. package/dist/oni-code/permissions.js.map +0 -1
  136. package/dist/oni-code/planner.d.ts +0 -26
  137. package/dist/oni-code/planner.d.ts.map +0 -1
  138. package/dist/oni-code/planner.js +0 -86
  139. package/dist/oni-code/planner.js.map +0 -1
  140. package/dist/oni-code/plugin-loader.d.ts +0 -103
  141. package/dist/oni-code/plugin-loader.d.ts.map +0 -1
  142. package/dist/oni-code/plugin-loader.js +0 -171
  143. package/dist/oni-code/plugin-loader.js.map +0 -1
  144. package/dist/oni-code/process-tree.d.ts +0 -44
  145. package/dist/oni-code/process-tree.d.ts.map +0 -1
  146. package/dist/oni-code/process-tree.js +0 -107
  147. package/dist/oni-code/process-tree.js.map +0 -1
  148. package/dist/oni-code/progress-tracker.d.ts +0 -40
  149. package/dist/oni-code/progress-tracker.d.ts.map +0 -1
  150. package/dist/oni-code/progress-tracker.js +0 -375
  151. package/dist/oni-code/progress-tracker.js.map +0 -1
  152. package/dist/oni-code/scheduler.d.ts +0 -56
  153. package/dist/oni-code/scheduler.d.ts.map +0 -1
  154. package/dist/oni-code/scheduler.js +0 -105
  155. package/dist/oni-code/scheduler.js.map +0 -1
  156. package/dist/oni-code/session-fork.d.ts +0 -146
  157. package/dist/oni-code/session-fork.d.ts.map +0 -1
  158. package/dist/oni-code/session-fork.js +0 -238
  159. package/dist/oni-code/session-fork.js.map +0 -1
  160. package/dist/oni-code/session-stats.d.ts +0 -72
  161. package/dist/oni-code/session-stats.d.ts.map +0 -1
  162. package/dist/oni-code/session-stats.js +0 -141
  163. package/dist/oni-code/session-stats.js.map +0 -1
  164. package/dist/oni-code/session-title.d.ts +0 -25
  165. package/dist/oni-code/session-title.d.ts.map +0 -1
  166. package/dist/oni-code/session-title.js +0 -67
  167. package/dist/oni-code/session-title.js.map +0 -1
  168. package/dist/oni-code/shell-parser.d.ts +0 -112
  169. package/dist/oni-code/shell-parser.d.ts.map +0 -1
  170. package/dist/oni-code/shell-parser.js +0 -657
  171. package/dist/oni-code/shell-parser.js.map +0 -1
  172. package/dist/oni-code/summarizer.d.ts +0 -27
  173. package/dist/oni-code/summarizer.d.ts.map +0 -1
  174. package/dist/oni-code/summarizer.js +0 -70
  175. package/dist/oni-code/summarizer.js.map +0 -1
  176. package/dist/oni-code/swarm-checkpoint.d.ts +0 -52
  177. package/dist/oni-code/swarm-checkpoint.d.ts.map +0 -1
  178. package/dist/oni-code/swarm-checkpoint.js +0 -71
  179. package/dist/oni-code/swarm-checkpoint.js.map +0 -1
  180. package/dist/oni-code/swarm-runner.d.ts +0 -173
  181. package/dist/oni-code/swarm-runner.d.ts.map +0 -1
  182. package/dist/oni-code/swarm-runner.js +0 -873
  183. package/dist/oni-code/swarm-runner.js.map +0 -1
  184. package/dist/oni-code/system-prompt.d.ts +0 -13
  185. package/dist/oni-code/system-prompt.d.ts.map +0 -1
  186. package/dist/oni-code/system-prompt.js +0 -64
  187. package/dist/oni-code/system-prompt.js.map +0 -1
  188. package/dist/oni-code/task-evaluator.d.ts +0 -73
  189. package/dist/oni-code/task-evaluator.d.ts.map +0 -1
  190. package/dist/oni-code/task-evaluator.js +0 -172
  191. package/dist/oni-code/task-evaluator.js.map +0 -1
  192. package/dist/oni-code/tools/batch.d.ts +0 -12
  193. package/dist/oni-code/tools/batch.d.ts.map +0 -1
  194. package/dist/oni-code/tools/batch.js +0 -116
  195. package/dist/oni-code/tools/batch.js.map +0 -1
  196. package/dist/oni-code/tools/coding.d.ts +0 -10
  197. package/dist/oni-code/tools/coding.d.ts.map +0 -1
  198. package/dist/oni-code/tools/coding.js +0 -557
  199. package/dist/oni-code/tools/coding.js.map +0 -1
  200. package/dist/oni-code/tools/cron.d.ts +0 -4
  201. package/dist/oni-code/tools/cron.d.ts.map +0 -1
  202. package/dist/oni-code/tools/cron.js +0 -120
  203. package/dist/oni-code/tools/cron.js.map +0 -1
  204. package/dist/oni-code/tools/custom.d.ts +0 -43
  205. package/dist/oni-code/tools/custom.d.ts.map +0 -1
  206. package/dist/oni-code/tools/custom.js +0 -115
  207. package/dist/oni-code/tools/custom.js.map +0 -1
  208. package/dist/oni-code/tools/patch.d.ts +0 -58
  209. package/dist/oni-code/tools/patch.d.ts.map +0 -1
  210. package/dist/oni-code/tools/patch.js +0 -247
  211. package/dist/oni-code/tools/patch.js.map +0 -1
  212. package/dist/oni-code/tools/plan.d.ts +0 -17
  213. package/dist/oni-code/tools/plan.d.ts.map +0 -1
  214. package/dist/oni-code/tools/plan.js +0 -48
  215. package/dist/oni-code/tools/plan.js.map +0 -1
  216. package/dist/oni-code/tools/question.d.ts +0 -17
  217. package/dist/oni-code/tools/question.d.ts.map +0 -1
  218. package/dist/oni-code/tools/question.js +0 -46
  219. package/dist/oni-code/tools/question.js.map +0 -1
  220. package/dist/oni-code/tools/skill.d.ts +0 -36
  221. package/dist/oni-code/tools/skill.d.ts.map +0 -1
  222. package/dist/oni-code/tools/skill.js +0 -132
  223. package/dist/oni-code/tools/skill.js.map +0 -1
  224. package/dist/oni-code/tools/spawn-agents.d.ts +0 -37
  225. package/dist/oni-code/tools/spawn-agents.d.ts.map +0 -1
  226. package/dist/oni-code/tools/spawn-agents.js +0 -91
  227. package/dist/oni-code/tools/spawn-agents.js.map +0 -1
  228. package/dist/oni-code/tools/spawn-swarm.d.ts +0 -70
  229. package/dist/oni-code/tools/spawn-swarm.d.ts.map +0 -1
  230. package/dist/oni-code/tools/spawn-swarm.js +0 -129
  231. package/dist/oni-code/tools/spawn-swarm.js.map +0 -1
  232. package/dist/oni-code/tools/web.d.ts +0 -11
  233. package/dist/oni-code/tools/web.d.ts.map +0 -1
  234. package/dist/oni-code/tools/web.js +0 -375
  235. package/dist/oni-code/tools/web.js.map +0 -1
  236. package/dist/oni-code/topology-agent-builder.d.ts +0 -22
  237. package/dist/oni-code/topology-agent-builder.d.ts.map +0 -1
  238. package/dist/oni-code/topology-agent-builder.js +0 -220
  239. package/dist/oni-code/topology-agent-builder.js.map +0 -1
  240. package/dist/oni-code/topology-selector.d.ts +0 -85
  241. package/dist/oni-code/topology-selector.d.ts.map +0 -1
  242. package/dist/oni-code/topology-selector.js +0 -338
  243. package/dist/oni-code/topology-selector.js.map +0 -1
  244. package/dist/oni-code/ui/App.d.ts +0 -10
  245. package/dist/oni-code/ui/App.d.ts.map +0 -1
  246. package/dist/oni-code/ui/App.js +0 -395
  247. package/dist/oni-code/ui/App.js.map +0 -1
  248. package/dist/oni-code/ui/FooterPanel.d.ts +0 -16
  249. package/dist/oni-code/ui/FooterPanel.d.ts.map +0 -1
  250. package/dist/oni-code/ui/FooterPanel.js +0 -56
  251. package/dist/oni-code/ui/FooterPanel.js.map +0 -1
  252. package/dist/oni-code/ui/Header.d.ts +0 -21
  253. package/dist/oni-code/ui/Header.d.ts.map +0 -1
  254. package/dist/oni-code/ui/Header.js +0 -105
  255. package/dist/oni-code/ui/Header.js.map +0 -1
  256. package/dist/oni-code/ui/InputArea.d.ts +0 -11
  257. package/dist/oni-code/ui/InputArea.d.ts.map +0 -1
  258. package/dist/oni-code/ui/InputArea.js +0 -82
  259. package/dist/oni-code/ui/InputArea.js.map +0 -1
  260. package/dist/oni-code/ui/MessageBlock.d.ts +0 -11
  261. package/dist/oni-code/ui/MessageBlock.d.ts.map +0 -1
  262. package/dist/oni-code/ui/MessageBlock.js +0 -103
  263. package/dist/oni-code/ui/MessageBlock.js.map +0 -1
  264. package/dist/oni-code/ui/OutputPane.d.ts +0 -12
  265. package/dist/oni-code/ui/OutputPane.d.ts.map +0 -1
  266. package/dist/oni-code/ui/OutputPane.js +0 -8
  267. package/dist/oni-code/ui/OutputPane.js.map +0 -1
  268. package/dist/oni-code/ui/PermissionPrompt.d.ts +0 -11
  269. package/dist/oni-code/ui/PermissionPrompt.d.ts.map +0 -1
  270. package/dist/oni-code/ui/PermissionPrompt.js +0 -48
  271. package/dist/oni-code/ui/PermissionPrompt.js.map +0 -1
  272. package/dist/oni-code/ui/QuestionPrompt.d.ts +0 -8
  273. package/dist/oni-code/ui/QuestionPrompt.d.ts.map +0 -1
  274. package/dist/oni-code/ui/QuestionPrompt.js +0 -9
  275. package/dist/oni-code/ui/QuestionPrompt.js.map +0 -1
  276. package/dist/oni-code/ui/StatusLine.d.ts +0 -14
  277. package/dist/oni-code/ui/StatusLine.d.ts.map +0 -1
  278. package/dist/oni-code/ui/StatusLine.js +0 -23
  279. package/dist/oni-code/ui/StatusLine.js.map +0 -1
  280. package/dist/oni-code/ui/SwarmPanel.d.ts +0 -9
  281. package/dist/oni-code/ui/SwarmPanel.d.ts.map +0 -1
  282. package/dist/oni-code/ui/SwarmPanel.js +0 -52
  283. package/dist/oni-code/ui/SwarmPanel.js.map +0 -1
  284. package/dist/oni-code/ui/ToolCallBlock.d.ts +0 -10
  285. package/dist/oni-code/ui/ToolCallBlock.d.ts.map +0 -1
  286. package/dist/oni-code/ui/ToolCallBlock.js +0 -21
  287. package/dist/oni-code/ui/ToolCallBlock.js.map +0 -1
  288. package/dist/oni-code/ui/Toolbar.d.ts +0 -8
  289. package/dist/oni-code/ui/Toolbar.d.ts.map +0 -1
  290. package/dist/oni-code/ui/Toolbar.js +0 -11
  291. package/dist/oni-code/ui/Toolbar.js.map +0 -1
  292. package/dist/oni-code/ui/WelcomeBanner.d.ts +0 -12
  293. package/dist/oni-code/ui/WelcomeBanner.d.ts.map +0 -1
  294. package/dist/oni-code/ui/WelcomeBanner.js +0 -24
  295. package/dist/oni-code/ui/WelcomeBanner.js.map +0 -1
  296. package/dist/oni-code/ui/activity.d.ts +0 -15
  297. package/dist/oni-code/ui/activity.d.ts.map +0 -1
  298. package/dist/oni-code/ui/activity.js +0 -252
  299. package/dist/oni-code/ui/activity.js.map +0 -1
  300. package/dist/oni-code/ui/banner.d.ts +0 -16
  301. package/dist/oni-code/ui/banner.d.ts.map +0 -1
  302. package/dist/oni-code/ui/banner.js +0 -132
  303. package/dist/oni-code/ui/banner.js.map +0 -1
  304. package/dist/oni-code/ui/command-menu.d.ts +0 -7
  305. package/dist/oni-code/ui/command-menu.d.ts.map +0 -1
  306. package/dist/oni-code/ui/command-menu.js +0 -20
  307. package/dist/oni-code/ui/command-menu.js.map +0 -1
  308. package/dist/oni-code/ui/diff.d.ts +0 -17
  309. package/dist/oni-code/ui/diff.d.ts.map +0 -1
  310. package/dist/oni-code/ui/diff.js +0 -37
  311. package/dist/oni-code/ui/diff.js.map +0 -1
  312. package/dist/oni-code/ui/format.d.ts +0 -41
  313. package/dist/oni-code/ui/format.d.ts.map +0 -1
  314. package/dist/oni-code/ui/format.js +0 -223
  315. package/dist/oni-code/ui/format.js.map +0 -1
  316. package/dist/oni-code/ui/input.d.ts +0 -28
  317. package/dist/oni-code/ui/input.d.ts.map +0 -1
  318. package/dist/oni-code/ui/input.js +0 -216
  319. package/dist/oni-code/ui/input.js.map +0 -1
  320. package/dist/oni-code/ui/insights.d.ts +0 -39
  321. package/dist/oni-code/ui/insights.d.ts.map +0 -1
  322. package/dist/oni-code/ui/insights.js +0 -193
  323. package/dist/oni-code/ui/insights.js.map +0 -1
  324. package/dist/oni-code/ui/markdown.d.ts +0 -9
  325. package/dist/oni-code/ui/markdown.d.ts.map +0 -1
  326. package/dist/oni-code/ui/markdown.js +0 -44
  327. package/dist/oni-code/ui/markdown.js.map +0 -1
  328. package/dist/oni-code/ui/panels.d.ts +0 -39
  329. package/dist/oni-code/ui/panels.d.ts.map +0 -1
  330. package/dist/oni-code/ui/panels.js +0 -209
  331. package/dist/oni-code/ui/panels.js.map +0 -1
  332. package/dist/oni-code/ui/paste.d.ts +0 -17
  333. package/dist/oni-code/ui/paste.d.ts.map +0 -1
  334. package/dist/oni-code/ui/paste.js +0 -45
  335. package/dist/oni-code/ui/paste.js.map +0 -1
  336. package/dist/oni-code/ui/raw-spinner.d.ts +0 -37
  337. package/dist/oni-code/ui/raw-spinner.d.ts.map +0 -1
  338. package/dist/oni-code/ui/raw-spinner.js +0 -121
  339. package/dist/oni-code/ui/raw-spinner.js.map +0 -1
  340. package/dist/oni-code/ui/session.d.ts +0 -44
  341. package/dist/oni-code/ui/session.d.ts.map +0 -1
  342. package/dist/oni-code/ui/session.js +0 -93
  343. package/dist/oni-code/ui/session.js.map +0 -1
  344. package/dist/oni-code/ui/spinner.d.ts +0 -7
  345. package/dist/oni-code/ui/spinner.d.ts.map +0 -1
  346. package/dist/oni-code/ui/spinner.js +0 -20
  347. package/dist/oni-code/ui/spinner.js.map +0 -1
  348. package/dist/oni-code/ui/swarm-activity.d.ts +0 -50
  349. package/dist/oni-code/ui/swarm-activity.d.ts.map +0 -1
  350. package/dist/oni-code/ui/swarm-activity.js +0 -233
  351. package/dist/oni-code/ui/swarm-activity.js.map +0 -1
  352. package/dist/oni-code/ui/terminal-size.d.ts +0 -18
  353. package/dist/oni-code/ui/terminal-size.d.ts.map +0 -1
  354. package/dist/oni-code/ui/terminal-size.js +0 -45
  355. package/dist/oni-code/ui/terminal-size.js.map +0 -1
  356. package/dist/oni-code/ui/theme.d.ts +0 -82
  357. package/dist/oni-code/ui/theme.d.ts.map +0 -1
  358. package/dist/oni-code/ui/theme.js +0 -101
  359. package/dist/oni-code/ui/theme.js.map +0 -1
  360. package/dist/oni-code/ui/tool-utils.d.ts +0 -10
  361. package/dist/oni-code/ui/tool-utils.d.ts.map +0 -1
  362. package/dist/oni-code/ui/tool-utils.js +0 -82
  363. package/dist/oni-code/ui/tool-utils.js.map +0 -1
  364. package/dist/oni-code/ui/useTerminalSize.d.ts +0 -3
  365. package/dist/oni-code/ui/useTerminalSize.d.ts.map +0 -1
  366. package/dist/oni-code/ui/useTerminalSize.js +0 -16
  367. package/dist/oni-code/ui/useTerminalSize.js.map +0 -1
  368. package/dist/oni-code/workspace/change-tracker.d.ts +0 -18
  369. package/dist/oni-code/workspace/change-tracker.d.ts.map +0 -1
  370. package/dist/oni-code/workspace/change-tracker.js +0 -67
  371. package/dist/oni-code/workspace/change-tracker.js.map +0 -1
  372. package/dist/oni-code/workspace/conflict-detector.d.ts +0 -12
  373. package/dist/oni-code/workspace/conflict-detector.d.ts.map +0 -1
  374. package/dist/oni-code/workspace/conflict-detector.js +0 -24
  375. package/dist/oni-code/workspace/conflict-detector.js.map +0 -1
  376. package/dist/oni-code/workspace/file-snapshots.d.ts +0 -39
  377. package/dist/oni-code/workspace/file-snapshots.d.ts.map +0 -1
  378. package/dist/oni-code/workspace/file-snapshots.js +0 -77
  379. package/dist/oni-code/workspace/file-snapshots.js.map +0 -1
  380. package/dist/oni-code/workspace/index.d.ts +0 -5
  381. package/dist/oni-code/workspace/index.d.ts.map +0 -1
  382. package/dist/oni-code/workspace/index.js +0 -5
  383. package/dist/oni-code/workspace/index.js.map +0 -1
  384. package/dist/oni-code/workspace/project-map.d.ts +0 -14
  385. package/dist/oni-code/workspace/project-map.d.ts.map +0 -1
  386. package/dist/oni-code/workspace/project-map.js +0 -91
  387. package/dist/oni-code/workspace/project-map.js.map +0 -1
  388. package/dist/sentinel/config/index.d.ts +0 -2
  389. package/dist/sentinel/config/index.d.ts.map +0 -1
  390. package/dist/sentinel/config/index.js +0 -2
  391. package/dist/sentinel/config/index.js.map +0 -1
  392. package/dist/sentinel/config/schema.d.ts +0 -4
  393. package/dist/sentinel/config/schema.d.ts.map +0 -1
  394. package/dist/sentinel/config/schema.js +0 -42
  395. package/dist/sentinel/config/schema.js.map +0 -1
  396. package/dist/sentinel/debate/index.d.ts +0 -6
  397. package/dist/sentinel/debate/index.d.ts.map +0 -1
  398. package/dist/sentinel/debate/index.js +0 -64
  399. package/dist/sentinel/debate/index.js.map +0 -1
  400. package/dist/sentinel/debate/prompts.d.ts +0 -4
  401. package/dist/sentinel/debate/prompts.d.ts.map +0 -1
  402. package/dist/sentinel/debate/prompts.js +0 -13
  403. package/dist/sentinel/debate/prompts.js.map +0 -1
  404. package/dist/sentinel/fix/index.d.ts +0 -6
  405. package/dist/sentinel/fix/index.d.ts.map +0 -1
  406. package/dist/sentinel/fix/index.js +0 -27
  407. package/dist/sentinel/fix/index.js.map +0 -1
  408. package/dist/sentinel/fix/strategies.d.ts +0 -9
  409. package/dist/sentinel/fix/strategies.d.ts.map +0 -1
  410. package/dist/sentinel/fix/strategies.js +0 -40
  411. package/dist/sentinel/fix/strategies.js.map +0 -1
  412. package/dist/sentinel/index.d.ts +0 -14
  413. package/dist/sentinel/index.d.ts.map +0 -1
  414. package/dist/sentinel/index.js +0 -22
  415. package/dist/sentinel/index.js.map +0 -1
  416. package/dist/sentinel/integrations/cli.d.ts +0 -10
  417. package/dist/sentinel/integrations/cli.d.ts.map +0 -1
  418. package/dist/sentinel/integrations/cli.js +0 -24
  419. package/dist/sentinel/integrations/cli.js.map +0 -1
  420. package/dist/sentinel/integrations/index.d.ts +0 -2
  421. package/dist/sentinel/integrations/index.d.ts.map +0 -1
  422. package/dist/sentinel/integrations/index.js +0 -2
  423. package/dist/sentinel/integrations/index.js.map +0 -1
  424. package/dist/sentinel/memory/index.d.ts +0 -16
  425. package/dist/sentinel/memory/index.d.ts.map +0 -1
  426. package/dist/sentinel/memory/index.js +0 -60
  427. package/dist/sentinel/memory/index.js.map +0 -1
  428. package/dist/sentinel/report/console.d.ts +0 -3
  429. package/dist/sentinel/report/console.d.ts.map +0 -1
  430. package/dist/sentinel/report/console.js +0 -27
  431. package/dist/sentinel/report/console.js.map +0 -1
  432. package/dist/sentinel/report/github.d.ts +0 -3
  433. package/dist/sentinel/report/github.d.ts.map +0 -1
  434. package/dist/sentinel/report/github.js +0 -36
  435. package/dist/sentinel/report/github.js.map +0 -1
  436. package/dist/sentinel/report/index.d.ts +0 -6
  437. package/dist/sentinel/report/index.d.ts.map +0 -1
  438. package/dist/sentinel/report/index.js +0 -15
  439. package/dist/sentinel/report/index.js.map +0 -1
  440. package/dist/sentinel/report/sarif.d.ts +0 -3
  441. package/dist/sentinel/report/sarif.d.ts.map +0 -1
  442. package/dist/sentinel/report/sarif.js +0 -29
  443. package/dist/sentinel/report/sarif.js.map +0 -1
  444. package/dist/sentinel/sentinel.d.ts +0 -17
  445. package/dist/sentinel/sentinel.d.ts.map +0 -1
  446. package/dist/sentinel/sentinel.js +0 -111
  447. package/dist/sentinel/sentinel.js.map +0 -1
  448. package/dist/sentinel/swarm/agents.d.ts +0 -6
  449. package/dist/sentinel/swarm/agents.d.ts.map +0 -1
  450. package/dist/sentinel/swarm/agents.js +0 -36
  451. package/dist/sentinel/swarm/agents.js.map +0 -1
  452. package/dist/sentinel/swarm/index.d.ts +0 -8
  453. package/dist/sentinel/swarm/index.d.ts.map +0 -1
  454. package/dist/sentinel/swarm/index.js +0 -74
  455. package/dist/sentinel/swarm/index.js.map +0 -1
  456. package/dist/sentinel/swarm/prompts.d.ts +0 -2
  457. package/dist/sentinel/swarm/prompts.d.ts.map +0 -1
  458. package/dist/sentinel/swarm/prompts.js +0 -24
  459. package/dist/sentinel/swarm/prompts.js.map +0 -1
  460. package/dist/sentinel/swarm/topology.d.ts +0 -10
  461. package/dist/sentinel/swarm/topology.d.ts.map +0 -1
  462. package/dist/sentinel/swarm/topology.js +0 -38
  463. package/dist/sentinel/swarm/topology.js.map +0 -1
  464. package/dist/sentinel/triage/analyzers/complexity-analyzer.d.ts +0 -7
  465. package/dist/sentinel/triage/analyzers/complexity-analyzer.d.ts.map +0 -1
  466. package/dist/sentinel/triage/analyzers/complexity-analyzer.js +0 -94
  467. package/dist/sentinel/triage/analyzers/complexity-analyzer.js.map +0 -1
  468. package/dist/sentinel/triage/analyzers/custom-analyzer.d.ts +0 -19
  469. package/dist/sentinel/triage/analyzers/custom-analyzer.d.ts.map +0 -1
  470. package/dist/sentinel/triage/analyzers/custom-analyzer.js +0 -268
  471. package/dist/sentinel/triage/analyzers/custom-analyzer.js.map +0 -1
  472. package/dist/sentinel/triage/analyzers/dependency-analyzer.d.ts +0 -26
  473. package/dist/sentinel/triage/analyzers/dependency-analyzer.d.ts.map +0 -1
  474. package/dist/sentinel/triage/analyzers/dependency-analyzer.js +0 -220
  475. package/dist/sentinel/triage/analyzers/dependency-analyzer.js.map +0 -1
  476. package/dist/sentinel/triage/analyzers/diff-analyzer.d.ts +0 -12
  477. package/dist/sentinel/triage/analyzers/diff-analyzer.d.ts.map +0 -1
  478. package/dist/sentinel/triage/analyzers/diff-analyzer.js +0 -19
  479. package/dist/sentinel/triage/analyzers/diff-analyzer.js.map +0 -1
  480. package/dist/sentinel/triage/analyzers/index.d.ts +0 -14
  481. package/dist/sentinel/triage/analyzers/index.d.ts.map +0 -1
  482. package/dist/sentinel/triage/analyzers/index.js +0 -25
  483. package/dist/sentinel/triage/analyzers/index.js.map +0 -1
  484. package/dist/sentinel/triage/analyzers/pattern-analyzer.d.ts +0 -7
  485. package/dist/sentinel/triage/analyzers/pattern-analyzer.d.ts.map +0 -1
  486. package/dist/sentinel/triage/analyzers/pattern-analyzer.js +0 -180
  487. package/dist/sentinel/triage/analyzers/pattern-analyzer.js.map +0 -1
  488. package/dist/sentinel/triage/analyzers/security-analyzer.d.ts +0 -7
  489. package/dist/sentinel/triage/analyzers/security-analyzer.d.ts.map +0 -1
  490. package/dist/sentinel/triage/analyzers/security-analyzer.js +0 -96
  491. package/dist/sentinel/triage/analyzers/security-analyzer.js.map +0 -1
  492. package/dist/sentinel/triage/analyzers/ts-parser.d.ts +0 -71
  493. package/dist/sentinel/triage/analyzers/ts-parser.d.ts.map +0 -1
  494. package/dist/sentinel/triage/analyzers/ts-parser.js +0 -323
  495. package/dist/sentinel/triage/analyzers/ts-parser.js.map +0 -1
  496. package/dist/sentinel/triage/analyzers/typescript-analyzer.d.ts +0 -7
  497. package/dist/sentinel/triage/analyzers/typescript-analyzer.d.ts.map +0 -1
  498. package/dist/sentinel/triage/analyzers/typescript-analyzer.js +0 -68
  499. package/dist/sentinel/triage/analyzers/typescript-analyzer.js.map +0 -1
  500. package/dist/sentinel/triage/index.d.ts +0 -10
  501. package/dist/sentinel/triage/index.d.ts.map +0 -1
  502. package/dist/sentinel/triage/index.js +0 -39
  503. package/dist/sentinel/triage/index.js.map +0 -1
  504. package/dist/sentinel/triage/scorer.d.ts +0 -9
  505. package/dist/sentinel/triage/scorer.d.ts.map +0 -1
  506. package/dist/sentinel/triage/scorer.js +0 -28
  507. package/dist/sentinel/triage/scorer.js.map +0 -1
  508. package/dist/sentinel/types.d.ts +0 -125
  509. package/dist/sentinel/types.d.ts.map +0 -1
  510. package/dist/sentinel/types.js +0 -6
  511. package/dist/sentinel/types.js.map +0 -1
package/dist/pregel.js CHANGED
@@ -3,16 +3,17 @@
3
3
  // New: interrupt() context management, HITL resume, token streaming
4
4
  // ============================================================
5
5
  import { START, END, Send, Command, } from "./types.js";
6
- import { RecursionLimitError, NodeNotFoundError, ONIInterrupt, NodeTimeoutError, ONIError, NodeExecutionError } from "./errors.js";
6
+ import { RecursionLimitError, NodeNotFoundError, ONIInterrupt, NodeTimeoutError, ONIError, NodeExecutionError, CircuitBreakerOpenError } from "./errors.js";
7
7
  import { CircuitBreaker } from "./circuit-breaker.js";
8
8
  import { withRetry } from "./retry.js";
9
9
  import { NamespacedCheckpointer } from "./checkpointers/namespaced.js";
10
10
  import { _runWithContext } from "./context.js";
11
- import { StreamWriterImpl, _installTokenHandler, _clearTokenHandler } from "./streaming.js";
11
+ import { StreamWriterImpl, _withTokenHandler } from "./streaming.js";
12
12
  import { NodeInterruptSignal, HITLInterruptException, HITLSessionStore, _installInterruptContext, _clearInterruptContext, } from "./hitl/index.js";
13
13
  import { EventBus } from "./events/bus.js";
14
14
  import { AuditLog } from "./guardrails/audit.js";
15
15
  import { BudgetTracker } from "./guardrails/budget.js";
16
+ import { runFilters } from "./guardrails/filters.js";
16
17
  import { ONITracer } from "./telemetry.js";
17
18
  const DEFAULT_RECURSION_LIMIT = 25;
18
19
  export class ONIPregelRunner {
@@ -34,6 +35,8 @@ export class ONIPregelRunner {
34
35
  eventBus;
35
36
  auditLog;
36
37
  budgetTracker;
38
+ contentFilters;
39
+ toolPermissions;
37
40
  tracer;
38
41
  /** Pre-indexed edges by source node — O(1) lookup instead of O(n) filter */
39
42
  _edgesBySource;
@@ -51,6 +54,8 @@ export class ONIPregelRunner {
51
54
  this.eventBus = new EventBus(listeners);
52
55
  this.auditLog = guardrails?.audit ? new AuditLog() : null;
53
56
  this.budgetTracker = guardrails?.budget ? new BudgetTracker(guardrails.budget) : null;
57
+ this.contentFilters = guardrails?.filters ?? [];
58
+ this.toolPermissions = guardrails?.toolPermissions;
54
59
  this.tracer = new ONITracer(tracer ?? null);
55
60
  // Pre-index edges by source for O(1) lookups in getNextNodes
56
61
  this._edgesBySource = new Map();
@@ -143,6 +148,7 @@ export class ONIPregelRunner {
143
148
  this.nodeCache.delete(cacheKey);
144
149
  }
145
150
  }
151
+ const _tid = config?.threadId ?? "unknown";
146
152
  const ctx = {
147
153
  config: config ?? {},
148
154
  store: this.store,
@@ -152,6 +158,16 @@ export class ONIPregelRunner {
152
158
  parentUpdates: [],
153
159
  step: step ?? 0,
154
160
  recursionLimit: recursionLimit ?? DEFAULT_RECURSION_LIMIT,
161
+ toolPermissions: this.toolPermissions,
162
+ _recordUsage: (agentName, modelId, usage) => {
163
+ if (!this.budgetTracker)
164
+ return;
165
+ const entries = this.budgetTracker.record(agentName, modelId, usage);
166
+ for (const e of entries)
167
+ this.auditLog?.record(_tid, e);
168
+ },
169
+ _emitEvent: (event) => this.eventBus.emit(event),
170
+ _auditRecord: (entry) => this.auditLog?.record(_tid, entry),
155
171
  };
156
172
  return _runWithContext(ctx, async () => {
157
173
  _installInterruptContext({
@@ -160,6 +176,24 @@ export class ONIPregelRunner {
160
176
  hasResume: hasResume ?? false,
161
177
  });
162
178
  try {
179
+ // Content filter — input direction
180
+ if (this.contentFilters.length > 0) {
181
+ const inputStr = JSON.stringify(state);
182
+ const inputCheck = runFilters(this.contentFilters, inputStr, "input");
183
+ if (!inputCheck.passed) {
184
+ const threadId = config?.threadId ?? "unknown";
185
+ this.eventBus.emit({ type: "filter.blocked", filter: inputCheck.blockedBy, agent: nodeDef.name, direction: "input", reason: inputCheck.reason, timestamp: Date.now() });
186
+ this.auditLog?.record(threadId, { timestamp: Date.now(), agent: nodeDef.name, action: "filter.blocked", data: { filter: inputCheck.blockedBy, direction: "input", reason: inputCheck.reason } });
187
+ throw new Error(`Content blocked by filter "${inputCheck.blockedBy}" on input to node "${nodeDef.name}": ${inputCheck.reason}`);
188
+ }
189
+ // Apply redaction if content was rewritten by a redacting filter
190
+ if (inputCheck.content !== inputStr) {
191
+ try {
192
+ state = JSON.parse(inputCheck.content);
193
+ }
194
+ catch { /* leave state unchanged on parse failure */ }
195
+ }
196
+ }
163
197
  const run = () => Promise.resolve(nodeDef.fn(state, config));
164
198
  // Core execute call: retry-aware
165
199
  const executeCall = async () => {
@@ -204,12 +238,36 @@ export class ONIPregelRunner {
204
238
  // Pass through interrupt signals (thrown by interrupt() inside nodes)
205
239
  if (err instanceof NodeInterruptSignal)
206
240
  throw err;
207
- // Pass through structured ONI errors (NodeExecutionError from retry, NodeTimeoutError, etc.)
208
- if (err instanceof ONIError)
209
- throw err;
210
- // Wrap raw errors and non-Error throws in NodeExecutionError
211
- const cause = err instanceof Error ? err : new Error(String(err));
212
- throw new NodeExecutionError(nodeDef.name, cause);
241
+ // Circuit breaker open invoke user fallback with real state + error
242
+ if (err instanceof CircuitBreakerOpenError && nodeDef.circuitBreaker?.fallback) {
243
+ result = nodeDef.circuitBreaker.fallback(state, err);
244
+ }
245
+ else {
246
+ // Pass through structured ONI errors (NodeExecutionError from retry, NodeTimeoutError, etc.)
247
+ if (err instanceof ONIError)
248
+ throw err;
249
+ // Wrap raw errors and non-Error throws in NodeExecutionError
250
+ const cause = err instanceof Error ? err : new Error(String(err));
251
+ throw new NodeExecutionError(nodeDef.name, cause);
252
+ }
253
+ }
254
+ // Content filter — output direction
255
+ if (this.contentFilters.length > 0 && result != null) {
256
+ const outputStr = JSON.stringify(result);
257
+ const outputCheck = runFilters(this.contentFilters, outputStr, "output");
258
+ if (!outputCheck.passed) {
259
+ const threadId = config?.threadId ?? "unknown";
260
+ this.eventBus.emit({ type: "filter.blocked", filter: outputCheck.blockedBy, agent: nodeDef.name, direction: "output", reason: outputCheck.reason, timestamp: Date.now() });
261
+ this.auditLog?.record(threadId, { timestamp: Date.now(), agent: nodeDef.name, action: "filter.blocked", data: { filter: outputCheck.blockedBy, direction: "output", reason: outputCheck.reason } });
262
+ throw new Error(`Content blocked by filter "${outputCheck.blockedBy}" on output of node "${nodeDef.name}": ${outputCheck.reason}`);
263
+ }
264
+ // Apply redaction if content was rewritten by a redacting filter
265
+ if (outputCheck.content !== outputStr) {
266
+ try {
267
+ result = JSON.parse(outputCheck.content);
268
+ }
269
+ catch { /* leave result unchanged on parse failure */ }
270
+ }
213
271
  }
214
272
  // Store in cache (reuse key computed above)
215
273
  if (nodeDef.cache && cacheKey) {
@@ -253,20 +311,28 @@ export class ONIPregelRunner {
253
311
  const modeMessages = modes.has("messages");
254
312
  // Telemetry: graph-level span
255
313
  const graphSpan = this.tracer.startGraphSpan("invoke", { threadId, agentId });
256
- // Load resume values from config (set by resume() call)
257
- const resumeMap = config?.__resumeValues ?? {};
258
- // Load or init state
259
- let state;
260
- let step = 0;
261
- let pendingNodes = [];
262
- let pendingSends = [];
263
- if (this.checkpointer && config?.threadId) {
264
- const cp = await this.checkpointer.get(threadId);
265
- if (cp) {
266
- state = this.applyUpdate(cp.state, input);
267
- step = cp.step;
268
- pendingNodes = cp.nextNodes;
269
- pendingSends = cp.pendingSends ?? [];
314
+ let step = 0; // declared before try so finally can read it for setAttribute
315
+ try {
316
+ // Load resume values from config (set by resume() call)
317
+ const resumeMap = config?.__resumeValues ?? {};
318
+ // Load or init state
319
+ let state;
320
+ let pendingNodes = [];
321
+ let pendingSends = [];
322
+ if (this.checkpointer && config?.threadId) {
323
+ const cp = await this.checkpointer.get(threadId);
324
+ if (cp) {
325
+ state = this.applyUpdate(cp.state, input);
326
+ step = cp.step;
327
+ pendingNodes = cp.nextNodes;
328
+ pendingSends = cp.pendingSends ?? [];
329
+ }
330
+ else {
331
+ state = this.applyUpdate(this.buildInitialState(), input);
332
+ const init = this.getNextNodes(START, state, config);
333
+ pendingNodes = init.nodes;
334
+ pendingSends = init.sends;
335
+ }
270
336
  }
271
337
  else {
272
338
  state = this.applyUpdate(this.buildInitialState(), input);
@@ -274,58 +340,278 @@ export class ONIPregelRunner {
274
340
  pendingNodes = init.nodes;
275
341
  pendingSends = init.sends;
276
342
  }
277
- }
278
- else {
279
- state = this.applyUpdate(this.buildInitialState(), input);
280
- const init = this.getNextNodes(START, state, config);
281
- pendingNodes = init.nodes;
282
- pendingSends = init.sends;
283
- }
284
- if (modeValues)
285
- yield tag(this.evt("state_update", state, step, agentId), "values");
286
- // ---- Main superstep loop ----
287
- while (true) {
288
- const nextNodes = [];
289
- const nextSends = [];
290
- state = this.resetEphemeral(state);
291
- // Drain sends group by target node for parallel fan-out execution
292
- const sendGroups = new Map();
293
- for (const send of pendingSends) {
294
- if (!sendGroups.has(send.node))
295
- sendGroups.set(send.node, []);
296
- sendGroups.get(send.node).push(send);
297
- if (modeDebug)
298
- yield tag(this.evt("send", send, step, agentId, send.node), "debug");
299
- }
300
- // Execute fan-out sends (each Send → separate node execution with its own state)
301
- if (sendGroups.size > 0) {
302
- // Build promises directly — avoids spread+flatMap intermediate arrays
303
- const sendPromises = [];
304
- for (const [node, sends] of sendGroups) {
305
- const nodeDef = this.nodes.get(node);
343
+ if (modeValues)
344
+ yield tag(this.evt("state_update", state, step, agentId), "values");
345
+ // ---- Main superstep loop ----
346
+ while (true) {
347
+ const nextNodes = [];
348
+ const nextSends = [];
349
+ state = this.resetEphemeral(state);
350
+ // Drain sends — group by target node for parallel fan-out execution
351
+ const sendGroups = new Map();
352
+ for (const send of pendingSends) {
353
+ if (!sendGroups.has(send.node))
354
+ sendGroups.set(send.node, []);
355
+ sendGroups.get(send.node).push(send);
356
+ if (modeDebug)
357
+ yield tag(this.evt("send", send, step, agentId, send.node), "debug");
358
+ }
359
+ // Execute fan-out sends (each Send separate node execution with its own state)
360
+ if (sendGroups.size > 0) {
361
+ // Build promises directly — avoids spread+flatMap intermediate arrays
362
+ const sendPromises = [];
363
+ for (const [node, sends] of sendGroups) {
364
+ const nodeDef = this.nodes.get(node);
365
+ if (!nodeDef)
366
+ throw new NodeNotFoundError(node);
367
+ for (const send of sends) {
368
+ sendPromises.push((async () => {
369
+ const sendState = this.applyUpdate(state, send.args);
370
+ const result = await this.executeNode(nodeDef, sendState, config, undefined, undefined, undefined, step, recursionLimit);
371
+ return { name: node, result };
372
+ })());
373
+ }
374
+ }
375
+ const sendResults = await Promise.all(sendPromises);
376
+ // Reduce all send results through channels
377
+ for (const { name, result } of sendResults) {
378
+ if (result instanceof Command) {
379
+ if (result.update)
380
+ state = this.applyUpdate(state, result.update);
381
+ const gotos = result.goto
382
+ ? (Array.isArray(result.goto) ? result.goto : [result.goto])
383
+ : this.getNextNodes(name, state, config).nodes;
384
+ nextNodes.push(...gotos);
385
+ }
386
+ else if (result && typeof result === "object") {
387
+ state = this.applyUpdate(state, result);
388
+ const { nodes, sends } = this.getNextNodes(name, state, config);
389
+ nextNodes.push(...nodes);
390
+ nextSends.push(...sends);
391
+ }
392
+ else {
393
+ const { nodes, sends } = this.getNextNodes(name, state, config);
394
+ nextNodes.push(...nodes);
395
+ nextSends.push(...sends);
396
+ }
397
+ if (modeUpdates || modeDebug) {
398
+ const delta = result instanceof Command ? (result.update ?? {}) : (result ?? {});
399
+ if (modeUpdates)
400
+ yield tag(this.evt("node_end", delta, step, agentId, name), "updates");
401
+ if (modeDebug)
402
+ yield tag(this.evt("node_end", delta, step, agentId, name), "debug");
403
+ }
404
+ }
405
+ }
406
+ pendingSends = [];
407
+ // Filter executable nodes (non-END), excluding nodes already handled by sends
408
+ const executableNodes = pendingNodes.filter((n) => n !== END && !sendGroups.has(n));
409
+ if (executableNodes.length === 0 && sendGroups.size === 0)
410
+ break;
411
+ if (step >= recursionLimit)
412
+ throw new RecursionLimitError(recursionLimit);
413
+ // Emit debug node_start events before parallel execution
414
+ if (modeDebug) {
415
+ for (const nodeName of executableNodes) {
416
+ const name = nodeName;
417
+ if (!this.nodes.has(name))
418
+ throw new NodeNotFoundError(name);
419
+ // Static interrupt BEFORE (check before emitting start)
420
+ if (this.interruptConfig.interruptBefore?.includes(name))
421
+ throw new ONIInterrupt(name, "before", state);
422
+ this.checkDynamicInterrupt(name, "before", state, config);
423
+ yield tag(this.evt("node_start", {}, step, agentId, name), "debug");
424
+ }
425
+ }
426
+ // Execute all active nodes in parallel
427
+ const allCustomEvents = [];
428
+ const allMessageEvents = [];
429
+ const allSubgraphEvents = [];
430
+ const nodeWriters = new Map();
431
+ const nodeResults = await Promise.all(executableNodes.map(async (nodeName) => {
432
+ const name = nodeName;
433
+ const nodeDef = this.nodes.get(name);
306
434
  if (!nodeDef)
307
- throw new NodeNotFoundError(node);
308
- for (const send of sends) {
309
- sendPromises.push((async () => {
310
- const sendState = this.applyUpdate(state, send.args);
311
- const result = await this.executeNode(nodeDef, sendState, config, undefined, undefined, undefined, step, recursionLimit);
312
- return { name: node, result };
313
- })());
435
+ throw new NodeNotFoundError(name);
436
+ // Static interrupt BEFORE (non-debug mode)
437
+ if (!modeDebug) {
438
+ if (this.interruptConfig.interruptBefore?.includes(name))
439
+ throw new ONIInterrupt(name, "before", state);
440
+ this.checkDynamicInterrupt(name, "before", state, config);
441
+ }
442
+ // Create a StreamWriter for this node
443
+ const messageId = `msg-${threadId}-${step}-${name}`;
444
+ const customEvents = [];
445
+ const messageEvents = [];
446
+ const writerImpl = new StreamWriterImpl((evt) => customEvents.push(evt), (token) => { }, (evt) => messageEvents.push(evt), name, step, messageId, agentId);
447
+ nodeWriters.set(name, writerImpl);
448
+ // Check if this node has a pending resume value
449
+ const resumeValue = resumeMap[name];
450
+ const hasResume = name in resumeMap;
451
+ // Emit agent.start lifecycle event
452
+ const nodeStartTime = Date.now();
453
+ this.eventBus.emit({ type: "agent.start", agent: name, timestamp: nodeStartTime, step });
454
+ // Telemetry: node-level span
455
+ const nodeSpan = this.tracer.startNodeSpan(name, { threadId, step, agentId });
456
+ let result;
457
+ let subParentUpdates = [];
458
+ try {
459
+ // Scope emitToken to this node's async context via ALS — parallel nodes each
460
+ // get their own handler so tokens are never dropped or misrouted.
461
+ result = await _withTokenHandler((token) => writerImpl.token(token), async () => {
462
+ if (nodeDef.subgraph) {
463
+ // Mark child runner as a subgraph so Command.PARENT works
464
+ const childRunner = nodeDef.subgraph._runner;
465
+ if (childRunner) {
466
+ childRunner._isSubgraph = true;
467
+ childRunner._parentUpdates = [];
468
+ }
469
+ // Save original checkpointer before potentially overwriting
470
+ const savedChildCheckpointer = childRunner ? childRunner.checkpointer : undefined;
471
+ // Namespace the subgraph's checkpointer for isolation
472
+ if (this.checkpointer && childRunner) {
473
+ childRunner.checkpointer = new NamespacedCheckpointer(this.checkpointer, name);
474
+ }
475
+ // Stream the subgraph — always restore child runner state, even on throw/interrupt
476
+ let subFinalState;
477
+ try {
478
+ const childStreamMode = ["debug", "values"];
479
+ for await (const evt of nodeDef.subgraph.stream(state, {
480
+ ...config,
481
+ parentRunId: config?.threadId,
482
+ streamMode: childStreamMode,
483
+ })) {
484
+ // Namespace-prefix the node name
485
+ allSubgraphEvents.push({
486
+ ...evt,
487
+ node: evt.node ? `${name}:${evt.node}` : name,
488
+ });
489
+ // Track the last state_update as the final subgraph state
490
+ if (evt.event === "state_update") {
491
+ subFinalState = evt.data;
492
+ }
493
+ }
494
+ if (childRunner) {
495
+ subParentUpdates = childRunner._parentUpdates;
496
+ }
497
+ }
498
+ finally {
499
+ // Restore regardless of success, throw, or interrupt
500
+ if (childRunner) {
501
+ childRunner._isSubgraph = false;
502
+ childRunner._parentUpdates = [];
503
+ childRunner.checkpointer = savedChildCheckpointer;
504
+ }
505
+ }
506
+ return subFinalState ?? {};
507
+ }
508
+ else {
509
+ return this.executeNode(nodeDef, state, config, resumeValue, hasResume, writerImpl, step, recursionLimit);
510
+ }
511
+ });
512
+ }
513
+ catch (err) {
514
+ // Catch interrupt() signals thrown from inside nodes
515
+ if (err instanceof NodeInterruptSignal) {
516
+ const iv = {
517
+ value: err.value,
518
+ node: name,
519
+ resumeId: err.resumeId,
520
+ timestamp: Date.now(),
521
+ };
522
+ // Save checkpoint before surfacing interrupt
523
+ await this.saveCheckpoint(threadId, step, state, [name], pendingSends, agentId, config?.metadata);
524
+ // Record HITL session if checkpointer exists
525
+ if (this.checkpointer) {
526
+ const cp = await this.checkpointer.get(threadId);
527
+ if (cp)
528
+ this.hitlStore.record(threadId, iv, cp);
529
+ }
530
+ throw new HITLInterruptException(threadId, iv, state);
531
+ }
532
+ // Record to DLQ before re-throwing — use original cause if wrapped
533
+ if (this.dlq && err instanceof Error) {
534
+ const dlqErr = (err instanceof NodeExecutionError && err.cause instanceof Error) ? err.cause : err;
535
+ this.dlq.record(threadId, name, state, dlqErr, nodeDef.retry?.maxAttempts ?? 1);
536
+ }
537
+ // Telemetry: record error on node span — use original cause if wrapped
538
+ if (err instanceof Error) {
539
+ const telErr = (err instanceof NodeExecutionError && err.cause instanceof Error) ? err.cause : err;
540
+ this.tracer.recordError(nodeSpan, telErr);
541
+ }
542
+ this.tracer.endSpan(nodeSpan);
543
+ // Lifecycle event: emit error for non-interrupt failures
544
+ if (err instanceof Error) {
545
+ this.eventBus.emit({ type: "error", agent: name, error: err, timestamp: Date.now() });
546
+ }
547
+ throw err;
548
+ }
549
+ // Telemetry: end node span
550
+ this.tracer.endSpan(nodeSpan);
551
+ // Emit agent.end lifecycle event
552
+ this.eventBus.emit({ type: "agent.end", agent: name, timestamp: Date.now(), step, duration: Date.now() - nodeStartTime });
553
+ // Collect events for yielding after parallel execution
554
+ allCustomEvents.push(...customEvents);
555
+ allMessageEvents.push(...messageEvents);
556
+ return { name, result, subParentUpdates };
557
+ }));
558
+ // Yield buffered subgraph events — filtered by parent's active modes
559
+ for (const evt of allSubgraphEvents) {
560
+ const e = evt;
561
+ if (modeDebug) {
562
+ yield tag(e, "debug");
563
+ }
564
+ else if (modeUpdates && (e.event === "node_end")) {
565
+ yield tag(e, "updates");
566
+ }
567
+ else if (modeValues && e.event === "state_update") {
568
+ yield tag(e, "values");
569
+ }
570
+ // Custom and message events from subgraphs are forwarded if those modes are active
571
+ if (modeCustom && e.event === "custom") {
572
+ yield tag(e, "custom");
573
+ }
574
+ if (modeMessages && (e.event === "messages" || e.event === "messages/complete")) {
575
+ yield tag(e, "messages");
314
576
  }
315
577
  }
316
- const sendResults = await Promise.all(sendPromises);
317
- // Reduce all send results through channels
318
- for (const { name, result } of sendResults) {
578
+ // Apply results
579
+ const stepWrites = [];
580
+ for (const { name, result, subParentUpdates: parentUpdates } of nodeResults) {
319
581
  if (result instanceof Command) {
320
- if (result.update)
321
- state = this.applyUpdate(state, result.update);
322
- const gotos = result.goto
323
- ? (Array.isArray(result.goto) ? result.goto : [result.goto])
324
- : this.getNextNodes(name, state, config).nodes;
325
- nextNodes.push(...gotos);
582
+ if (result.graph === Command.PARENT) {
583
+ // Push update to parent — do NOT apply locally
584
+ if (!this._isSubgraph) {
585
+ throw new Error("Command.PARENT used but graph is not running as a subgraph");
586
+ }
587
+ if (result.update)
588
+ this._parentUpdates.push(result.update);
589
+ // Still resolve next nodes normally
590
+ const { nodes, sends } = this.getNextNodes(name, state, config);
591
+ nextNodes.push(...nodes);
592
+ nextSends.push(...sends);
593
+ }
594
+ else {
595
+ if (result.update) {
596
+ state = this.applyUpdate(state, result.update);
597
+ if (Object.keys(result.update).length > 0) {
598
+ stepWrites.push({ nodeId: name, writes: result.update });
599
+ }
600
+ }
601
+ const gotos = result.goto
602
+ ? (Array.isArray(result.goto) ? result.goto : [result.goto])
603
+ : this.getNextNodes(name, state, config).nodes;
604
+ nextNodes.push(...gotos);
605
+ if (result.send)
606
+ nextSends.push(...result.send.map((s) => ({ node: s.node, args: s.args })));
607
+ }
326
608
  }
327
609
  else if (result && typeof result === "object") {
328
610
  state = this.applyUpdate(state, result);
611
+ const writes = result;
612
+ if (Object.keys(writes).length > 0) {
613
+ stepWrites.push({ nodeId: name, writes });
614
+ }
329
615
  const { nodes, sends } = this.getNextNodes(name, state, config);
330
616
  nextNodes.push(...nodes);
331
617
  nextSends.push(...sends);
@@ -335,6 +621,10 @@ export class ONIPregelRunner {
335
621
  nextNodes.push(...nodes);
336
622
  nextSends.push(...sends);
337
623
  }
624
+ // Apply parent updates from subgraph Command.PARENT (after normal result)
625
+ for (const pu of parentUpdates) {
626
+ state = this.applyUpdate(state, pu);
627
+ }
338
628
  if (modeUpdates || modeDebug) {
339
629
  const delta = result instanceof Command ? (result.update ?? {}) : (result ?? {});
340
630
  if (modeUpdates)
@@ -342,286 +632,69 @@ export class ONIPregelRunner {
342
632
  if (modeDebug)
343
633
  yield tag(this.evt("node_end", delta, step, agentId, name), "debug");
344
634
  }
345
- }
346
- }
347
- pendingSends = [];
348
- // Filter executable nodes (non-END), excluding nodes already handled by sends
349
- const executableNodes = pendingNodes.filter((n) => n !== END && !sendGroups.has(n));
350
- if (executableNodes.length === 0 && sendGroups.size === 0)
351
- break;
352
- if (step >= recursionLimit)
353
- throw new RecursionLimitError(recursionLimit);
354
- // Emit debug node_start events before parallel execution
355
- if (modeDebug) {
356
- for (const nodeName of executableNodes) {
357
- const name = nodeName;
358
- if (!this.nodes.has(name))
359
- throw new NodeNotFoundError(name);
360
- // Static interrupt BEFORE (check before emitting start)
361
- if (this.interruptConfig.interruptBefore?.includes(name))
362
- throw new ONIInterrupt(name, "before", state);
363
- this.checkDynamicInterrupt(name, "before", state, config);
364
- yield tag(this.evt("node_start", {}, step, agentId, name), "debug");
365
- }
366
- }
367
- // Execute all active nodes in parallel
368
- const allCustomEvents = [];
369
- const allMessageEvents = [];
370
- const allSubgraphEvents = [];
371
- const nodeWriters = new Map();
372
- const nodeResults = await Promise.all(executableNodes.map(async (nodeName) => {
373
- const name = nodeName;
374
- const nodeDef = this.nodes.get(name);
375
- if (!nodeDef)
376
- throw new NodeNotFoundError(name);
377
- // Static interrupt BEFORE (non-debug mode)
378
- if (!modeDebug) {
379
- if (this.interruptConfig.interruptBefore?.includes(name))
380
- throw new ONIInterrupt(name, "before", state);
381
- this.checkDynamicInterrupt(name, "before", state, config);
382
- }
383
- // Create a StreamWriter for this node
384
- const messageId = `msg-${threadId}-${step}-${name}`;
385
- const customEvents = [];
386
- const messageEvents = [];
387
- const writerImpl = new StreamWriterImpl((evt) => customEvents.push(evt), (token) => { }, (evt) => messageEvents.push(evt), name, step, messageId, agentId);
388
- nodeWriters.set(name, writerImpl);
389
- // Install global emitToken handler so emitToken() routes to this node's writer
390
- _installTokenHandler((token) => writerImpl.token(token));
391
- // Check if this node has a pending resume value
392
- const resumeValue = resumeMap[name];
393
- const hasResume = name in resumeMap;
394
- // Emit agent.start lifecycle event
395
- const nodeStartTime = Date.now();
396
- this.eventBus.emit({ type: "agent.start", agent: name, timestamp: nodeStartTime, step });
397
- // Telemetry: node-level span
398
- const nodeSpan = this.tracer.startNodeSpan(name, { threadId, step, agentId });
399
- let result;
400
- let subParentUpdates = [];
401
- try {
402
- if (nodeDef.subgraph) {
403
- // Mark child runner as a subgraph so Command.PARENT works
404
- const childRunner = nodeDef.subgraph._runner;
405
- if (childRunner) {
406
- childRunner._isSubgraph = true;
407
- childRunner._parentUpdates = [];
408
- }
409
- // Namespace the subgraph's checkpointer for isolation
410
- if (this.checkpointer && childRunner) {
411
- childRunner.checkpointer = new NamespacedCheckpointer(this.checkpointer, name);
412
- }
413
- // Stream the subgraph instead of invoke — buffer events for yielding after Promise.all
414
- // Use debug+values so we capture ALL event types AND state_update for final state
415
- let subFinalState;
416
- const childStreamMode = ["debug", "values"];
417
- for await (const evt of nodeDef.subgraph.stream(state, {
418
- ...config,
419
- parentRunId: config?.threadId,
420
- streamMode: childStreamMode,
421
- })) {
422
- // Namespace-prefix the node name
423
- allSubgraphEvents.push({
424
- ...evt,
425
- node: evt.node ? `${name}:${evt.node}` : name,
426
- });
427
- // Track the last state_update as the final subgraph state
428
- if (evt.event === "state_update") {
429
- subFinalState = evt.data;
430
- }
431
- }
432
- // Collect parent updates from child
433
- if (childRunner) {
434
- subParentUpdates = childRunner._parentUpdates;
435
- childRunner._isSubgraph = false;
436
- childRunner._parentUpdates = [];
437
- }
438
- result = subFinalState ?? {};
439
- }
440
- else {
441
- result = await this.executeNode(nodeDef, state, config, resumeValue, hasResume, writerImpl, step, recursionLimit);
635
+ // Static interrupt AFTER
636
+ if (this.interruptConfig.interruptAfter?.includes(name)) {
637
+ await this.saveCheckpoint(threadId, step, state, nextNodes, nextSends, agentId, config?.metadata);
638
+ throw new ONIInterrupt(name, "after", state);
442
639
  }
640
+ this.checkDynamicInterrupt(name, "after", state, config);
443
641
  }
444
- catch (err) {
445
- // Catch interrupt() signals thrown from inside nodes
446
- if (err instanceof NodeInterruptSignal) {
447
- const iv = {
448
- value: err.value,
449
- node: name,
450
- resumeId: err.resumeId,
451
- timestamp: Date.now(),
452
- };
453
- // Save checkpoint before surfacing interrupt
454
- await this.saveCheckpoint(threadId, step, state, [name], pendingSends, agentId, config?.metadata);
455
- // Record HITL session if checkpointer exists
456
- if (this.checkpointer) {
457
- const cp = await this.checkpointer.get(threadId);
458
- if (cp)
459
- this.hitlStore.record(threadId, iv, cp);
460
- }
461
- throw new HITLInterruptException(threadId, iv, state);
462
- }
463
- // Record to DLQ before re-throwing — use original cause if wrapped
464
- if (this.dlq && err instanceof Error) {
465
- const dlqErr = (err instanceof NodeExecutionError && err.cause instanceof Error) ? err.cause : err;
466
- this.dlq.record(threadId, name, state, dlqErr, nodeDef.retry?.maxAttempts ?? 1);
467
- }
468
- // Telemetry: record error on node span — use original cause if wrapped
469
- if (err instanceof Error) {
470
- const telErr = (err instanceof NodeExecutionError && err.cause instanceof Error) ? err.cause : err;
471
- this.tracer.recordError(nodeSpan, telErr);
642
+ // Yield buffered custom/message events based on stream mode
643
+ if (modeCustom || modeDebug) {
644
+ for (const evt of allCustomEvents) {
645
+ if (modeCustom)
646
+ yield tag(evt, "custom");
647
+ if (modeDebug)
648
+ yield tag(evt, "debug");
472
649
  }
473
- this.tracer.endSpan(nodeSpan);
474
- _clearTokenHandler();
475
- throw err;
476
- }
477
- // Clear emitToken handler after node completes
478
- _clearTokenHandler();
479
- // Telemetry: end node span
480
- this.tracer.endSpan(nodeSpan);
481
- // Emit agent.end lifecycle event
482
- this.eventBus.emit({ type: "agent.end", agent: name, timestamp: Date.now(), step, duration: Date.now() - nodeStartTime });
483
- // Collect events for yielding after parallel execution
484
- allCustomEvents.push(...customEvents);
485
- allMessageEvents.push(...messageEvents);
486
- return { name, result, subParentUpdates };
487
- }));
488
- // Yield buffered subgraph events — filtered by parent's active modes
489
- for (const evt of allSubgraphEvents) {
490
- const e = evt;
491
- if (modeDebug) {
492
- yield tag(e, "debug");
493
- }
494
- else if (modeUpdates && (e.event === "node_end")) {
495
- yield tag(e, "updates");
496
650
  }
497
- else if (modeValues && e.event === "state_update") {
498
- yield tag(e, "values");
499
- }
500
- // Custom and message events from subgraphs are forwarded if those modes are active
501
- if (modeCustom && e.event === "custom") {
502
- yield tag(e, "custom");
503
- }
504
- if (modeMessages && (e.event === "messages" || e.event === "messages/complete")) {
505
- yield tag(e, "messages");
506
- }
507
- }
508
- // Apply results
509
- const stepWrites = [];
510
- for (const { name, result, subParentUpdates: parentUpdates } of nodeResults) {
511
- if (result instanceof Command) {
512
- if (result.graph === Command.PARENT) {
513
- // Push update to parent — do NOT apply locally
514
- if (!this._isSubgraph) {
515
- throw new Error("Command.PARENT used but graph is not running as a subgraph");
516
- }
517
- if (result.update)
518
- this._parentUpdates.push(result.update);
519
- // Still resolve next nodes normally
520
- const { nodes, sends } = this.getNextNodes(name, state, config);
521
- nextNodes.push(...nodes);
522
- nextSends.push(...sends);
651
+ if (modeMessages || modeDebug) {
652
+ for (const evt of allMessageEvents) {
653
+ if (modeMessages)
654
+ yield tag(evt, "messages");
655
+ if (modeDebug)
656
+ yield tag(evt, "debug");
523
657
  }
524
- else {
525
- if (result.update) {
526
- state = this.applyUpdate(state, result.update);
527
- if (Object.keys(result.update).length > 0) {
528
- stepWrites.push({ nodeId: name, writes: result.update });
529
- }
658
+ // Emit messages/complete for each node that produced tokens
659
+ for (const [, writer] of nodeWriters) {
660
+ const complete = writer._complete();
661
+ if (complete) {
662
+ if (modeMessages)
663
+ yield tag(complete, "messages");
664
+ if (modeDebug)
665
+ yield tag(complete, "debug");
530
666
  }
531
- const gotos = result.goto
532
- ? (Array.isArray(result.goto) ? result.goto : [result.goto])
533
- : this.getNextNodes(name, state, config).nodes;
534
- nextNodes.push(...gotos);
535
- if (result.send)
536
- nextSends.push(...result.send.map((s) => ({ node: s.node, args: s.args })));
537
667
  }
538
668
  }
539
- else if (result && typeof result === "object") {
540
- state = this.applyUpdate(state, result);
541
- const writes = result;
542
- if (Object.keys(writes).length > 0) {
543
- stepWrites.push({ nodeId: name, writes });
544
- }
545
- const { nodes, sends } = this.getNextNodes(name, state, config);
546
- nextNodes.push(...nodes);
547
- nextSends.push(...sends);
669
+ if (modeValues)
670
+ yield tag(this.evt("state_update", state, step, agentId), "values");
671
+ // Deduplicate nextNodes — avoid Set+spread when no dupes (common case)
672
+ if (nextNodes.length <= 1) {
673
+ pendingNodes = nextNodes;
548
674
  }
549
675
  else {
550
- const { nodes, sends } = this.getNextNodes(name, state, config);
551
- nextNodes.push(...nodes);
552
- nextSends.push(...sends);
553
- }
554
- // Apply parent updates from subgraph Command.PARENT (after normal result)
555
- for (const pu of parentUpdates) {
556
- state = this.applyUpdate(state, pu);
557
- }
558
- if (modeUpdates || modeDebug) {
559
- const delta = result instanceof Command ? (result.update ?? {}) : (result ?? {});
560
- if (modeUpdates)
561
- yield tag(this.evt("node_end", delta, step, agentId, name), "updates");
562
- if (modeDebug)
563
- yield tag(this.evt("node_end", delta, step, agentId, name), "debug");
564
- }
565
- // Static interrupt AFTER
566
- if (this.interruptConfig.interruptAfter?.includes(name)) {
567
- await this.saveCheckpoint(threadId, step, state, nextNodes, nextSends, agentId, config?.metadata);
568
- throw new ONIInterrupt(name, "after", state);
569
- }
570
- this.checkDynamicInterrupt(name, "after", state, config);
571
- }
572
- // Yield buffered custom/message events based on stream mode
573
- if (modeCustom || modeDebug) {
574
- for (const evt of allCustomEvents) {
575
- if (modeCustom)
576
- yield tag(evt, "custom");
577
- if (modeDebug)
578
- yield tag(evt, "debug");
579
- }
580
- }
581
- if (modeMessages || modeDebug) {
582
- for (const evt of allMessageEvents) {
583
- if (modeMessages)
584
- yield tag(evt, "messages");
585
- if (modeDebug)
586
- yield tag(evt, "debug");
587
- }
588
- // Emit messages/complete for each node that produced tokens
589
- for (const [, writer] of nodeWriters) {
590
- const complete = writer._complete();
591
- if (complete) {
592
- if (modeMessages)
593
- yield tag(complete, "messages");
594
- if (modeDebug)
595
- yield tag(complete, "debug");
676
+ const seen = new Set();
677
+ pendingNodes = [];
678
+ for (const n of nextNodes) {
679
+ const key = n;
680
+ if (!seen.has(key)) {
681
+ seen.add(key);
682
+ pendingNodes.push(n);
683
+ }
596
684
  }
597
685
  }
686
+ pendingSends = nextSends;
687
+ step++;
688
+ await this.saveCheckpoint(threadId, step, state, pendingNodes, pendingSends, agentId, config?.metadata, stepWrites);
598
689
  }
599
690
  if (modeValues)
600
691
  yield tag(this.evt("state_update", state, step, agentId), "values");
601
- // Deduplicate nextNodes — avoid Set+spread when no dupes (common case)
602
- if (nextNodes.length <= 1) {
603
- pendingNodes = nextNodes;
604
- }
605
- else {
606
- const seen = new Set();
607
- pendingNodes = [];
608
- for (const n of nextNodes) {
609
- const key = n;
610
- if (!seen.has(key)) {
611
- seen.add(key);
612
- pendingNodes.push(n);
613
- }
614
- }
615
- }
616
- pendingSends = nextSends;
617
- step++;
618
- await this.saveCheckpoint(threadId, step, state, pendingNodes, pendingSends, agentId, config?.metadata, stepWrites);
619
692
  }
620
- if (modeValues)
621
- yield tag(this.evt("state_update", state, step, agentId), "values");
622
- // Telemetry: end graph span
623
- graphSpan.setAttribute("oni.steps", step);
624
- this.tracer.endSpan(graphSpan);
693
+ finally {
694
+ // Telemetry: end graph span — always runs, even on error or interrupt
695
+ graphSpan.setAttribute("oni.steps", step);
696
+ this.tracer.endSpan(graphSpan);
697
+ }
625
698
  }
626
699
  // ----------------------------------------------------------------
627
700
  // Public API
@@ -699,9 +772,6 @@ export class ONIPregelRunner {
699
772
  cb = new CircuitBreaker({
700
773
  threshold: nodeDef.circuitBreaker.threshold,
701
774
  resetAfter: nodeDef.circuitBreaker.resetAfter,
702
- fallback: nodeDef.circuitBreaker.fallback
703
- ? () => nodeDef.circuitBreaker.fallback(undefined, undefined)
704
- : undefined,
705
775
  }, nodeDef.name);
706
776
  this.circuitBreakers.set(nodeDef.name, cb);
707
777
  }
@@ -716,13 +786,17 @@ export class ONIPregelRunner {
716
786
  if (!this.checkpointer)
717
787
  return;
718
788
  const cpSpan = this.tracer.startCheckpointSpan("put", { threadId });
719
- await this.checkpointer.put({
720
- threadId, step, state, agentId, metadata, pendingWrites,
721
- nextNodes: nextNodes.map(String),
722
- pendingSends: pendingSends,
723
- timestamp: Date.now(),
724
- });
725
- this.tracer.endSpan(cpSpan);
789
+ try {
790
+ await this.checkpointer.put({
791
+ threadId, step, state, agentId, metadata, pendingWrites,
792
+ nextNodes: nextNodes.map(String),
793
+ pendingSends: pendingSends,
794
+ timestamp: Date.now(),
795
+ });
796
+ }
797
+ finally {
798
+ this.tracer.endSpan(cpSpan);
799
+ }
726
800
  }
727
801
  evt(event, data, step, agentId, node) {
728
802
  return { event, data, step, timestamp: Date.now(), agentId, node };