pulseed 0.5.2 → 0.5.4

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 (824) hide show
  1. package/dist/base/state/state-manager-goal-state.d.ts +40 -0
  2. package/dist/base/state/state-manager-goal-state.d.ts.map +1 -0
  3. package/dist/base/state/state-manager-goal-state.js +235 -0
  4. package/dist/base/state/state-manager-goal-state.js.map +1 -0
  5. package/dist/base/state/state-manager.d.ts +0 -5
  6. package/dist/base/state/state-manager.d.ts.map +1 -1
  7. package/dist/base/state/state-manager.js +27 -273
  8. package/dist/base/state/state-manager.js.map +1 -1
  9. package/dist/base/types/goal-activation.d.ts +25 -0
  10. package/dist/base/types/goal-activation.d.ts.map +1 -0
  11. package/dist/base/types/goal-activation.js +9 -0
  12. package/dist/base/types/goal-activation.js.map +1 -0
  13. package/dist/index.d.ts +2 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +1 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/interface/chat/chat-event-state.d.ts +10 -0
  18. package/dist/interface/chat/chat-event-state.d.ts.map +1 -1
  19. package/dist/interface/chat/chat-event-state.js +184 -9
  20. package/dist/interface/chat/chat-event-state.js.map +1 -1
  21. package/dist/interface/chat/chat-events.d.ts +3 -1
  22. package/dist/interface/chat/chat-events.d.ts.map +1 -1
  23. package/dist/interface/chat/chat-history.d.ts +129 -0
  24. package/dist/interface/chat/chat-history.d.ts.map +1 -1
  25. package/dist/interface/chat/chat-history.js +135 -0
  26. package/dist/interface/chat/chat-history.js.map +1 -1
  27. package/dist/interface/chat/chat-runner-command-helpers.d.ts +50 -0
  28. package/dist/interface/chat/chat-runner-command-helpers.d.ts.map +1 -0
  29. package/dist/interface/chat/chat-runner-command-helpers.js +189 -0
  30. package/dist/interface/chat/chat-runner-command-helpers.js.map +1 -0
  31. package/dist/interface/chat/chat-runner-commands.d.ts +76 -0
  32. package/dist/interface/chat/chat-runner-commands.d.ts.map +1 -0
  33. package/dist/interface/chat/chat-runner-commands.js +814 -0
  34. package/dist/interface/chat/chat-runner-commands.js.map +1 -0
  35. package/dist/interface/chat/chat-runner-event-bridge.d.ts +53 -0
  36. package/dist/interface/chat/chat-runner-event-bridge.d.ts.map +1 -0
  37. package/dist/interface/chat/chat-runner-event-bridge.js +311 -0
  38. package/dist/interface/chat/chat-runner-event-bridge.js.map +1 -0
  39. package/dist/interface/chat/chat-runner-routes.d.ts +67 -0
  40. package/dist/interface/chat/chat-runner-routes.d.ts.map +1 -0
  41. package/dist/interface/chat/chat-runner-routes.js +594 -0
  42. package/dist/interface/chat/chat-runner-routes.js.map +1 -0
  43. package/dist/interface/chat/chat-runner-runtime.d.ts +37 -0
  44. package/dist/interface/chat/chat-runner-runtime.d.ts.map +1 -0
  45. package/dist/interface/chat/chat-runner-runtime.js +236 -0
  46. package/dist/interface/chat/chat-runner-runtime.js.map +1 -0
  47. package/dist/interface/chat/chat-runner-state.d.ts +20 -0
  48. package/dist/interface/chat/chat-runner-state.d.ts.map +1 -0
  49. package/dist/interface/chat/chat-runner-state.js +157 -0
  50. package/dist/interface/chat/chat-runner-state.js.map +1 -0
  51. package/dist/interface/chat/chat-runner-support.d.ts +15 -0
  52. package/dist/interface/chat/chat-runner-support.d.ts.map +1 -0
  53. package/dist/interface/chat/chat-runner-support.js +116 -0
  54. package/dist/interface/chat/chat-runner-support.js.map +1 -0
  55. package/dist/interface/chat/chat-runner.d.ts +13 -133
  56. package/dist/interface/chat/chat-runner.d.ts.map +1 -1
  57. package/dist/interface/chat/chat-runner.js +242 -1974
  58. package/dist/interface/chat/chat-runner.js.map +1 -1
  59. package/dist/interface/chat/chat-session-store.d.ts +32 -0
  60. package/dist/interface/chat/chat-session-store.d.ts.map +1 -1
  61. package/dist/interface/chat/chat-session-store.js +100 -10
  62. package/dist/interface/chat/chat-session-store.js.map +1 -1
  63. package/dist/interface/chat/chat-verifier.d.ts +3 -1
  64. package/dist/interface/chat/chat-verifier.d.ts.map +1 -1
  65. package/dist/interface/chat/chat-verifier.js +2 -2
  66. package/dist/interface/chat/chat-verifier.js.map +1 -1
  67. package/dist/interface/chat/cross-platform-session.d.ts +1 -0
  68. package/dist/interface/chat/cross-platform-session.d.ts.map +1 -1
  69. package/dist/interface/chat/cross-platform-session.js +23 -2
  70. package/dist/interface/chat/cross-platform-session.js.map +1 -1
  71. package/dist/interface/chat/event-subscriber.d.ts.map +1 -1
  72. package/dist/interface/chat/event-subscriber.js +41 -0
  73. package/dist/interface/chat/event-subscriber.js.map +1 -1
  74. package/dist/interface/chat/failure-recovery.d.ts +11 -0
  75. package/dist/interface/chat/failure-recovery.d.ts.map +1 -0
  76. package/dist/interface/chat/failure-recovery.js +115 -0
  77. package/dist/interface/chat/failure-recovery.js.map +1 -0
  78. package/dist/interface/chat/ingress-router.d.ts +0 -16
  79. package/dist/interface/chat/ingress-router.d.ts.map +1 -1
  80. package/dist/interface/chat/ingress-router.js +12 -51
  81. package/dist/interface/chat/ingress-router.js.map +1 -1
  82. package/dist/interface/chat/tend-command.d.ts +8 -0
  83. package/dist/interface/chat/tend-command.d.ts.map +1 -1
  84. package/dist/interface/chat/tend-command.js +82 -4
  85. package/dist/interface/chat/tend-command.js.map +1 -1
  86. package/dist/interface/cli/cli-command-registry.d.ts.map +1 -1
  87. package/dist/interface/cli/cli-command-registry.js +4 -0
  88. package/dist/interface/cli/cli-command-registry.js.map +1 -1
  89. package/dist/interface/cli/commands/daemon-shared.d.ts +32 -0
  90. package/dist/interface/cli/commands/daemon-shared.d.ts.map +1 -0
  91. package/dist/interface/cli/commands/daemon-shared.js +120 -0
  92. package/dist/interface/cli/commands/daemon-shared.js.map +1 -0
  93. package/dist/interface/cli/commands/daemon.d.ts +2 -2
  94. package/dist/interface/cli/commands/daemon.d.ts.map +1 -1
  95. package/dist/interface/cli/commands/daemon.js +4 -120
  96. package/dist/interface/cli/commands/daemon.js.map +1 -1
  97. package/dist/interface/cli/commands/runtime.d.ts +3 -0
  98. package/dist/interface/cli/commands/runtime.d.ts.map +1 -0
  99. package/dist/interface/cli/commands/runtime.js +231 -0
  100. package/dist/interface/cli/commands/runtime.js.map +1 -0
  101. package/dist/interface/cli/commands/schedule/history.d.ts.map +1 -1
  102. package/dist/interface/cli/commands/schedule/history.js +5 -1
  103. package/dist/interface/cli/commands/schedule/history.js.map +1 -1
  104. package/dist/interface/cli/commands/schedule.js +34 -4
  105. package/dist/interface/cli/commands/schedule.js.map +1 -1
  106. package/dist/interface/cli/utils.d.ts.map +1 -1
  107. package/dist/interface/cli/utils.js +4 -0
  108. package/dist/interface/cli/utils.js.map +1 -1
  109. package/dist/interface/tui/app.d.ts.map +1 -1
  110. package/dist/interface/tui/app.js +35 -1
  111. package/dist/interface/tui/app.js.map +1 -1
  112. package/dist/interface/tui/chat/scroll.d.ts +3 -0
  113. package/dist/interface/tui/chat/scroll.d.ts.map +1 -1
  114. package/dist/interface/tui/chat/scroll.js +15 -0
  115. package/dist/interface/tui/chat/scroll.js.map +1 -1
  116. package/dist/interface/tui/chat/suggestions.d.ts.map +1 -1
  117. package/dist/interface/tui/chat/suggestions.js +118 -4
  118. package/dist/interface/tui/chat/suggestions.js.map +1 -1
  119. package/dist/interface/tui/chat/types.d.ts +1 -1
  120. package/dist/interface/tui/chat/types.d.ts.map +1 -1
  121. package/dist/interface/tui/chat/viewport.d.ts.map +1 -1
  122. package/dist/interface/tui/chat/viewport.js +8 -2
  123. package/dist/interface/tui/chat/viewport.js.map +1 -1
  124. package/dist/interface/tui/chat-surface.d.ts +2 -0
  125. package/dist/interface/tui/chat-surface.d.ts.map +1 -1
  126. package/dist/interface/tui/chat-surface.js +11 -0
  127. package/dist/interface/tui/chat-surface.js.map +1 -1
  128. package/dist/interface/tui/chat.d.ts.map +1 -1
  129. package/dist/interface/tui/chat.js +15 -7
  130. package/dist/interface/tui/chat.js.map +1 -1
  131. package/dist/interface/tui/clipboard.d.ts +6 -1
  132. package/dist/interface/tui/clipboard.d.ts.map +1 -1
  133. package/dist/interface/tui/clipboard.js +24 -5
  134. package/dist/interface/tui/clipboard.js.map +1 -1
  135. package/dist/interface/tui/entry-approval.d.ts +8 -0
  136. package/dist/interface/tui/entry-approval.d.ts.map +1 -0
  137. package/dist/interface/tui/entry-approval.js +59 -0
  138. package/dist/interface/tui/entry-approval.js.map +1 -0
  139. package/dist/interface/tui/entry-daemon.d.ts +12 -0
  140. package/dist/interface/tui/entry-daemon.d.ts.map +1 -0
  141. package/dist/interface/tui/entry-daemon.js +74 -0
  142. package/dist/interface/tui/entry-daemon.js.map +1 -0
  143. package/dist/interface/tui/entry-deps.d.ts +22 -0
  144. package/dist/interface/tui/entry-deps.d.ts.map +1 -0
  145. package/dist/interface/tui/entry-deps.js +409 -0
  146. package/dist/interface/tui/entry-deps.js.map +1 -0
  147. package/dist/interface/tui/entry.d.ts +2 -4
  148. package/dist/interface/tui/entry.d.ts.map +1 -1
  149. package/dist/interface/tui/entry.js +15 -550
  150. package/dist/interface/tui/entry.js.map +1 -1
  151. package/dist/interface/tui/flicker/MouseTracking.d.ts +1 -1
  152. package/dist/interface/tui/flicker/MouseTracking.d.ts.map +1 -1
  153. package/dist/interface/tui/flicker/MouseTracking.js +8 -4
  154. package/dist/interface/tui/flicker/MouseTracking.js.map +1 -1
  155. package/dist/interface/tui/fullscreen-chat-render.d.ts +127 -0
  156. package/dist/interface/tui/fullscreen-chat-render.d.ts.map +1 -0
  157. package/dist/interface/tui/fullscreen-chat-render.js +667 -0
  158. package/dist/interface/tui/fullscreen-chat-render.js.map +1 -0
  159. package/dist/interface/tui/fullscreen-chat.d.ts +1 -29
  160. package/dist/interface/tui/fullscreen-chat.d.ts.map +1 -1
  161. package/dist/interface/tui/fullscreen-chat.js +306 -411
  162. package/dist/interface/tui/fullscreen-chat.js.map +1 -1
  163. package/dist/interface/tui/help-overlay.d.ts.map +1 -1
  164. package/dist/interface/tui/help-overlay.js +1 -1
  165. package/dist/interface/tui/help-overlay.js.map +1 -1
  166. package/dist/interface/tui/intent-recognizer.js +2 -2
  167. package/dist/interface/tui/intent-recognizer.js.map +1 -1
  168. package/dist/interface/tui/markdown-renderer.d.ts.map +1 -1
  169. package/dist/interface/tui/markdown-renderer.js +40 -12
  170. package/dist/interface/tui/markdown-renderer.js.map +1 -1
  171. package/dist/interface/tui/test-entry.js +1 -1
  172. package/dist/interface/tui/test-entry.js.map +1 -1
  173. package/dist/orchestrator/execution/agent-loop/agent-loop-context-assembler.d.ts.map +1 -1
  174. package/dist/orchestrator/execution/agent-loop/agent-loop-context-assembler.js +1 -0
  175. package/dist/orchestrator/execution/agent-loop/agent-loop-context-assembler.js.map +1 -1
  176. package/dist/orchestrator/execution/agent-loop/agent-loop-default-profile.d.ts.map +1 -1
  177. package/dist/orchestrator/execution/agent-loop/agent-loop-default-profile.js +35 -13
  178. package/dist/orchestrator/execution/agent-loop/agent-loop-default-profile.js.map +1 -1
  179. package/dist/orchestrator/execution/agent-loop/agent-loop-dogfood-benchmark.d.ts.map +1 -1
  180. package/dist/orchestrator/execution/agent-loop/agent-loop-dogfood-benchmark.js +7 -4
  181. package/dist/orchestrator/execution/agent-loop/agent-loop-dogfood-benchmark.js.map +1 -1
  182. package/dist/orchestrator/execution/agent-loop/agent-loop-tool-router.d.ts.map +1 -1
  183. package/dist/orchestrator/execution/agent-loop/agent-loop-tool-router.js +2 -1
  184. package/dist/orchestrator/execution/agent-loop/agent-loop-tool-router.js.map +1 -1
  185. package/dist/orchestrator/execution/agent-loop/agent-loop-tool-runtime.d.ts +2 -0
  186. package/dist/orchestrator/execution/agent-loop/agent-loop-tool-runtime.d.ts.map +1 -1
  187. package/dist/orchestrator/execution/agent-loop/agent-loop-tool-runtime.js +31 -0
  188. package/dist/orchestrator/execution/agent-loop/agent-loop-tool-runtime.js.map +1 -1
  189. package/dist/orchestrator/execution/agent-loop/agent-loop-turn-context.d.ts +1 -0
  190. package/dist/orchestrator/execution/agent-loop/agent-loop-turn-context.d.ts.map +1 -1
  191. package/dist/orchestrator/execution/agent-loop/agent-loop-turn-context.js.map +1 -1
  192. package/dist/orchestrator/execution/agent-loop/bounded-agent-loop-runner.d.ts +1 -0
  193. package/dist/orchestrator/execution/agent-loop/bounded-agent-loop-runner.d.ts.map +1 -1
  194. package/dist/orchestrator/execution/agent-loop/bounded-agent-loop-runner.js +42 -2
  195. package/dist/orchestrator/execution/agent-loop/bounded-agent-loop-runner.js.map +1 -1
  196. package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.d.ts +1 -0
  197. package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.d.ts.map +1 -1
  198. package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.js +3 -1
  199. package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.js.map +1 -1
  200. package/dist/orchestrator/execution/agent-loop/core-loop-control-tools.d.ts +19 -0
  201. package/dist/orchestrator/execution/agent-loop/core-loop-control-tools.d.ts.map +1 -1
  202. package/dist/orchestrator/execution/agent-loop/core-loop-control-tools.js +164 -14
  203. package/dist/orchestrator/execution/agent-loop/core-loop-control-tools.js.map +1 -1
  204. package/dist/orchestrator/execution/agent-loop/index.d.ts +1 -0
  205. package/dist/orchestrator/execution/agent-loop/index.d.ts.map +1 -1
  206. package/dist/orchestrator/execution/agent-loop/index.js +1 -0
  207. package/dist/orchestrator/execution/agent-loop/index.js.map +1 -1
  208. package/dist/orchestrator/execution/agent-loop/kaggle-training-benchmark.d.ts +34 -0
  209. package/dist/orchestrator/execution/agent-loop/kaggle-training-benchmark.d.ts.map +1 -0
  210. package/dist/orchestrator/execution/agent-loop/kaggle-training-benchmark.js +54 -0
  211. package/dist/orchestrator/execution/agent-loop/kaggle-training-benchmark.js.map +1 -0
  212. package/dist/orchestrator/execution/reflection-generator.d.ts +1 -0
  213. package/dist/orchestrator/execution/reflection-generator.d.ts.map +1 -1
  214. package/dist/orchestrator/execution/reflection-generator.js +10 -1
  215. package/dist/orchestrator/execution/reflection-generator.js.map +1 -1
  216. package/dist/orchestrator/execution/task/task-context-enricher.d.ts +2 -0
  217. package/dist/orchestrator/execution/task/task-context-enricher.d.ts.map +1 -1
  218. package/dist/orchestrator/execution/task/task-context-enricher.js +9 -4
  219. package/dist/orchestrator/execution/task/task-context-enricher.js.map +1 -1
  220. package/dist/orchestrator/execution/task/task-execution-helpers-internal.d.ts +5 -0
  221. package/dist/orchestrator/execution/task/task-execution-helpers-internal.d.ts.map +1 -0
  222. package/dist/orchestrator/execution/task/task-execution-helpers-internal.js +6 -0
  223. package/dist/orchestrator/execution/task/task-execution-helpers-internal.js.map +1 -0
  224. package/dist/orchestrator/execution/task/task-generation.d.ts.map +1 -1
  225. package/dist/orchestrator/execution/task/task-generation.js +8 -3
  226. package/dist/orchestrator/execution/task/task-generation.js.map +1 -1
  227. package/dist/orchestrator/execution/task/task-lifecycle-runner.d.ts +73 -0
  228. package/dist/orchestrator/execution/task/task-lifecycle-runner.d.ts.map +1 -0
  229. package/dist/orchestrator/execution/task/task-lifecycle-runner.js +184 -0
  230. package/dist/orchestrator/execution/task/task-lifecycle-runner.js.map +1 -0
  231. package/dist/orchestrator/execution/task/task-lifecycle.d.ts +7 -7
  232. package/dist/orchestrator/execution/task/task-lifecycle.d.ts.map +1 -1
  233. package/dist/orchestrator/execution/task/task-lifecycle.js +37 -181
  234. package/dist/orchestrator/execution/task/task-lifecycle.js.map +1 -1
  235. package/dist/orchestrator/execution/task/task-verifier-internal.d.ts +2 -0
  236. package/dist/orchestrator/execution/task/task-verifier-internal.d.ts.map +1 -0
  237. package/dist/orchestrator/execution/task/task-verifier-internal.js +2 -0
  238. package/dist/orchestrator/execution/task/task-verifier-internal.js.map +1 -0
  239. package/dist/orchestrator/goal/goal-negotiator.d.ts.map +1 -1
  240. package/dist/orchestrator/goal/goal-negotiator.js +23 -3
  241. package/dist/orchestrator/goal/goal-negotiator.js.map +1 -1
  242. package/dist/orchestrator/loop/core-loop/contracts.d.ts +1 -0
  243. package/dist/orchestrator/loop/core-loop/contracts.d.ts.map +1 -1
  244. package/dist/orchestrator/loop/core-loop/contracts.js.map +1 -1
  245. package/dist/orchestrator/loop/core-loop/iteration-kernel-knowledge.d.ts +7 -0
  246. package/dist/orchestrator/loop/core-loop/iteration-kernel-knowledge.d.ts.map +1 -0
  247. package/dist/orchestrator/loop/core-loop/iteration-kernel-knowledge.js +43 -0
  248. package/dist/orchestrator/loop/core-loop/iteration-kernel-knowledge.js.map +1 -0
  249. package/dist/orchestrator/loop/core-loop/iteration-kernel-wait.d.ts +14 -0
  250. package/dist/orchestrator/loop/core-loop/iteration-kernel-wait.d.ts.map +1 -0
  251. package/dist/orchestrator/loop/core-loop/iteration-kernel-wait.js +41 -0
  252. package/dist/orchestrator/loop/core-loop/iteration-kernel-wait.js.map +1 -0
  253. package/dist/orchestrator/loop/core-loop/iteration-kernel.d.ts +3 -2
  254. package/dist/orchestrator/loop/core-loop/iteration-kernel.d.ts.map +1 -1
  255. package/dist/orchestrator/loop/core-loop/iteration-kernel.js +16 -87
  256. package/dist/orchestrator/loop/core-loop/iteration-kernel.js.map +1 -1
  257. package/dist/orchestrator/loop/core-loop/phase-policy.d.ts.map +1 -1
  258. package/dist/orchestrator/loop/core-loop/phase-policy.js +8 -5
  259. package/dist/orchestrator/loop/core-loop/phase-policy.js.map +1 -1
  260. package/dist/orchestrator/loop/core-loop/task-cycle-stall.d.ts +9 -0
  261. package/dist/orchestrator/loop/core-loop/task-cycle-stall.d.ts.map +1 -0
  262. package/dist/orchestrator/loop/core-loop/task-cycle-stall.js +297 -0
  263. package/dist/orchestrator/loop/core-loop/task-cycle-stall.js.map +1 -0
  264. package/dist/orchestrator/loop/core-loop/task-cycle-wait.d.ts +11 -0
  265. package/dist/orchestrator/loop/core-loop/task-cycle-wait.d.ts.map +1 -0
  266. package/dist/orchestrator/loop/core-loop/task-cycle-wait.js +176 -0
  267. package/dist/orchestrator/loop/core-loop/task-cycle-wait.js.map +1 -0
  268. package/dist/orchestrator/loop/core-loop/task-cycle.d.ts +3 -15
  269. package/dist/orchestrator/loop/core-loop/task-cycle.d.ts.map +1 -1
  270. package/dist/orchestrator/loop/core-loop/task-cycle.js +10 -444
  271. package/dist/orchestrator/loop/core-loop/task-cycle.js.map +1 -1
  272. package/dist/orchestrator/loop/core-loop.d.ts +3 -0
  273. package/dist/orchestrator/loop/core-loop.d.ts.map +1 -1
  274. package/dist/orchestrator/loop/core-loop.js +4 -0
  275. package/dist/orchestrator/loop/core-loop.js.map +1 -1
  276. package/dist/orchestrator/strategy/portfolio-manager.d.ts +3 -2
  277. package/dist/orchestrator/strategy/portfolio-manager.d.ts.map +1 -1
  278. package/dist/orchestrator/strategy/portfolio-manager.js +16 -11
  279. package/dist/orchestrator/strategy/portfolio-manager.js.map +1 -1
  280. package/dist/orchestrator/strategy/portfolio-rebalance.d.ts +1 -1
  281. package/dist/orchestrator/strategy/portfolio-rebalance.d.ts.map +1 -1
  282. package/dist/orchestrator/strategy/portfolio-rebalance.js +31 -9
  283. package/dist/orchestrator/strategy/portfolio-rebalance.js.map +1 -1
  284. package/dist/orchestrator/strategy/strategy-manager-base.d.ts +12 -2
  285. package/dist/orchestrator/strategy/strategy-manager-base.d.ts.map +1 -1
  286. package/dist/orchestrator/strategy/strategy-manager-base.js +23 -7
  287. package/dist/orchestrator/strategy/strategy-manager-base.js.map +1 -1
  288. package/dist/orchestrator/strategy/strategy-manager.d.ts +1 -11
  289. package/dist/orchestrator/strategy/strategy-manager.d.ts.map +1 -1
  290. package/dist/orchestrator/strategy/strategy-manager.js +78 -19
  291. package/dist/orchestrator/strategy/strategy-manager.js.map +1 -1
  292. package/dist/platform/code-search/candidate-normalizer.d.ts +3 -0
  293. package/dist/platform/code-search/candidate-normalizer.d.ts.map +1 -0
  294. package/dist/platform/code-search/candidate-normalizer.js +61 -0
  295. package/dist/platform/code-search/candidate-normalizer.js.map +1 -0
  296. package/dist/platform/code-search/candidate.d.ts +25 -0
  297. package/dist/platform/code-search/candidate.d.ts.map +1 -0
  298. package/dist/platform/code-search/candidate.js +61 -0
  299. package/dist/platform/code-search/candidate.js.map +1 -0
  300. package/dist/platform/code-search/contracts.d.ts +275 -0
  301. package/dist/platform/code-search/contracts.d.ts.map +1 -0
  302. package/dist/platform/code-search/contracts.js +22 -0
  303. package/dist/platform/code-search/contracts.js.map +1 -0
  304. package/dist/platform/code-search/eval/fixtures.d.ts +14 -0
  305. package/dist/platform/code-search/eval/fixtures.d.ts.map +1 -0
  306. package/dist/platform/code-search/eval/fixtures.js +24 -0
  307. package/dist/platform/code-search/eval/fixtures.js.map +1 -0
  308. package/dist/platform/code-search/eval/metrics.d.ts +10 -0
  309. package/dist/platform/code-search/eval/metrics.d.ts.map +1 -0
  310. package/dist/platform/code-search/eval/metrics.js +20 -0
  311. package/dist/platform/code-search/eval/metrics.js.map +1 -0
  312. package/dist/platform/code-search/eval/runner.d.ts +3 -0
  313. package/dist/platform/code-search/eval/runner.d.ts.map +1 -0
  314. package/dist/platform/code-search/eval/runner.js +13 -0
  315. package/dist/platform/code-search/eval/runner.js.map +1 -0
  316. package/dist/platform/code-search/fusion.d.ts +6 -0
  317. package/dist/platform/code-search/fusion.d.ts.map +1 -0
  318. package/dist/platform/code-search/fusion.js +12 -0
  319. package/dist/platform/code-search/fusion.js.map +1 -0
  320. package/dist/platform/code-search/generated-detector.d.ts +15 -0
  321. package/dist/platform/code-search/generated-detector.d.ts.map +1 -0
  322. package/dist/platform/code-search/generated-detector.js +42 -0
  323. package/dist/platform/code-search/generated-detector.js.map +1 -0
  324. package/dist/platform/code-search/indexes/call-graph.d.ts +3 -0
  325. package/dist/platform/code-search/indexes/call-graph.d.ts.map +1 -0
  326. package/dist/platform/code-search/indexes/call-graph.js +13 -0
  327. package/dist/platform/code-search/indexes/call-graph.js.map +1 -0
  328. package/dist/platform/code-search/indexes/config-index.d.ts +3 -0
  329. package/dist/platform/code-search/indexes/config-index.d.ts.map +1 -0
  330. package/dist/platform/code-search/indexes/config-index.js +7 -0
  331. package/dist/platform/code-search/indexes/config-index.js.map +1 -0
  332. package/dist/platform/code-search/indexes/file-index.d.ts +5 -0
  333. package/dist/platform/code-search/indexes/file-index.d.ts.map +1 -0
  334. package/dist/platform/code-search/indexes/file-index.js +106 -0
  335. package/dist/platform/code-search/indexes/file-index.js.map +1 -0
  336. package/dist/platform/code-search/indexes/index-store.d.ts +6 -0
  337. package/dist/platform/code-search/indexes/index-store.d.ts.map +1 -0
  338. package/dist/platform/code-search/indexes/index-store.js +14 -0
  339. package/dist/platform/code-search/indexes/index-store.js.map +1 -0
  340. package/dist/platform/code-search/indexes/indexer.d.ts +3 -0
  341. package/dist/platform/code-search/indexes/indexer.d.ts.map +1 -0
  342. package/dist/platform/code-search/indexes/indexer.js +27 -0
  343. package/dist/platform/code-search/indexes/indexer.js.map +1 -0
  344. package/dist/platform/code-search/indexes/package-graph.d.ts +3 -0
  345. package/dist/platform/code-search/indexes/package-graph.d.ts.map +1 -0
  346. package/dist/platform/code-search/indexes/package-graph.js +26 -0
  347. package/dist/platform/code-search/indexes/package-graph.js.map +1 -0
  348. package/dist/platform/code-search/indexes/repo-map-index.d.ts +3 -0
  349. package/dist/platform/code-search/indexes/repo-map-index.d.ts.map +1 -0
  350. package/dist/platform/code-search/indexes/repo-map-index.js +26 -0
  351. package/dist/platform/code-search/indexes/repo-map-index.js.map +1 -0
  352. package/dist/platform/code-search/indexes/semantic-index.d.ts +3 -0
  353. package/dist/platform/code-search/indexes/semantic-index.d.ts.map +1 -0
  354. package/dist/platform/code-search/indexes/semantic-index.js +4 -0
  355. package/dist/platform/code-search/indexes/semantic-index.js.map +1 -0
  356. package/dist/platform/code-search/indexes/symbol-index.d.ts +3 -0
  357. package/dist/platform/code-search/indexes/symbol-index.d.ts.map +1 -0
  358. package/dist/platform/code-search/indexes/symbol-index.js +84 -0
  359. package/dist/platform/code-search/indexes/symbol-index.js.map +1 -0
  360. package/dist/platform/code-search/indexes/test-index.d.ts +3 -0
  361. package/dist/platform/code-search/indexes/test-index.d.ts.map +1 -0
  362. package/dist/platform/code-search/indexes/test-index.js +22 -0
  363. package/dist/platform/code-search/indexes/test-index.js.map +1 -0
  364. package/dist/platform/code-search/orchestrator.d.ts +9 -0
  365. package/dist/platform/code-search/orchestrator.d.ts.map +1 -0
  366. package/dist/platform/code-search/orchestrator.js +81 -0
  367. package/dist/platform/code-search/orchestrator.js.map +1 -0
  368. package/dist/platform/code-search/path-policy.d.ts +6 -0
  369. package/dist/platform/code-search/path-policy.d.ts.map +1 -0
  370. package/dist/platform/code-search/path-policy.js +60 -0
  371. package/dist/platform/code-search/path-policy.js.map +1 -0
  372. package/dist/platform/code-search/progressive-reader.d.ts +8 -0
  373. package/dist/platform/code-search/progressive-reader.d.ts.map +1 -0
  374. package/dist/platform/code-search/progressive-reader.js +173 -0
  375. package/dist/platform/code-search/progressive-reader.js.map +1 -0
  376. package/dist/platform/code-search/query-planner.d.ts +4 -0
  377. package/dist/platform/code-search/query-planner.d.ts.map +1 -0
  378. package/dist/platform/code-search/query-planner.js +107 -0
  379. package/dist/platform/code-search/query-planner.js.map +1 -0
  380. package/dist/platform/code-search/reranker.d.ts +4 -0
  381. package/dist/platform/code-search/reranker.d.ts.map +1 -0
  382. package/dist/platform/code-search/reranker.js +57 -0
  383. package/dist/platform/code-search/reranker.js.map +1 -0
  384. package/dist/platform/code-search/retrievers/callgraph-retriever.d.ts +6 -0
  385. package/dist/platform/code-search/retrievers/callgraph-retriever.d.ts.map +1 -0
  386. package/dist/platform/code-search/retrievers/callgraph-retriever.js +31 -0
  387. package/dist/platform/code-search/retrievers/callgraph-retriever.js.map +1 -0
  388. package/dist/platform/code-search/retrievers/config-retriever.d.ts +6 -0
  389. package/dist/platform/code-search/retrievers/config-retriever.d.ts.map +1 -0
  390. package/dist/platform/code-search/retrievers/config-retriever.js +23 -0
  391. package/dist/platform/code-search/retrievers/config-retriever.js.map +1 -0
  392. package/dist/platform/code-search/retrievers/lexical-retriever.d.ts +6 -0
  393. package/dist/platform/code-search/retrievers/lexical-retriever.d.ts.map +1 -0
  394. package/dist/platform/code-search/retrievers/lexical-retriever.js +49 -0
  395. package/dist/platform/code-search/retrievers/lexical-retriever.js.map +1 -0
  396. package/dist/platform/code-search/retrievers/package-retriever.d.ts +6 -0
  397. package/dist/platform/code-search/retrievers/package-retriever.d.ts.map +1 -0
  398. package/dist/platform/code-search/retrievers/package-retriever.js +29 -0
  399. package/dist/platform/code-search/retrievers/package-retriever.js.map +1 -0
  400. package/dist/platform/code-search/retrievers/repo-map-retriever.d.ts +6 -0
  401. package/dist/platform/code-search/retrievers/repo-map-retriever.d.ts.map +1 -0
  402. package/dist/platform/code-search/retrievers/repo-map-retriever.js +30 -0
  403. package/dist/platform/code-search/retrievers/repo-map-retriever.js.map +1 -0
  404. package/dist/platform/code-search/retrievers/semantic-retriever.d.ts +6 -0
  405. package/dist/platform/code-search/retrievers/semantic-retriever.d.ts.map +1 -0
  406. package/dist/platform/code-search/retrievers/semantic-retriever.js +18 -0
  407. package/dist/platform/code-search/retrievers/semantic-retriever.js.map +1 -0
  408. package/dist/platform/code-search/retrievers/stacktrace-retriever.d.ts +6 -0
  409. package/dist/platform/code-search/retrievers/stacktrace-retriever.d.ts.map +1 -0
  410. package/dist/platform/code-search/retrievers/stacktrace-retriever.js +30 -0
  411. package/dist/platform/code-search/retrievers/stacktrace-retriever.js.map +1 -0
  412. package/dist/platform/code-search/retrievers/symbol-retriever.d.ts +6 -0
  413. package/dist/platform/code-search/retrievers/symbol-retriever.d.ts.map +1 -0
  414. package/dist/platform/code-search/retrievers/symbol-retriever.js +32 -0
  415. package/dist/platform/code-search/retrievers/symbol-retriever.js.map +1 -0
  416. package/dist/platform/code-search/retrievers/test-retriever.d.ts +6 -0
  417. package/dist/platform/code-search/retrievers/test-retriever.d.ts.map +1 -0
  418. package/dist/platform/code-search/retrievers/test-retriever.js +30 -0
  419. package/dist/platform/code-search/retrievers/test-retriever.js.map +1 -0
  420. package/dist/platform/code-search/session-store.d.ts +11 -0
  421. package/dist/platform/code-search/session-store.d.ts.map +1 -0
  422. package/dist/platform/code-search/session-store.js +41 -0
  423. package/dist/platform/code-search/session-store.js.map +1 -0
  424. package/dist/platform/code-search/trace.d.ts +9 -0
  425. package/dist/platform/code-search/trace.d.ts.map +1 -0
  426. package/dist/platform/code-search/trace.js +25 -0
  427. package/dist/platform/code-search/trace.js.map +1 -0
  428. package/dist/platform/code-search/verification-retrieval.d.ts +3 -0
  429. package/dist/platform/code-search/verification-retrieval.d.ts.map +1 -0
  430. package/dist/platform/code-search/verification-retrieval.js +33 -0
  431. package/dist/platform/code-search/verification-retrieval.js.map +1 -0
  432. package/dist/platform/dream/dream-consolidator/fs-metrics.d.ts +18 -0
  433. package/dist/platform/dream/dream-consolidator/fs-metrics.d.ts.map +1 -0
  434. package/dist/platform/dream/dream-consolidator/fs-metrics.js +130 -0
  435. package/dist/platform/dream/dream-consolidator/fs-metrics.js.map +1 -0
  436. package/dist/platform/dream/dream-consolidator.d.ts +4 -14
  437. package/dist/platform/dream/dream-consolidator.d.ts.map +1 -1
  438. package/dist/platform/dream/dream-consolidator.js +46 -166
  439. package/dist/platform/dream/dream-consolidator.js.map +1 -1
  440. package/dist/platform/dream/dream-soil-sync.d.ts +1 -0
  441. package/dist/platform/dream/dream-soil-sync.d.ts.map +1 -1
  442. package/dist/platform/dream/dream-soil-sync.js +8 -1
  443. package/dist/platform/dream/dream-soil-sync.js.map +1 -1
  444. package/dist/platform/dream/dream-types.d.ts +5 -0
  445. package/dist/platform/dream/dream-types.d.ts.map +1 -1
  446. package/dist/platform/dream/dream-types.js +1 -0
  447. package/dist/platform/dream/dream-types.js.map +1 -1
  448. package/dist/platform/dream/playbook-memory.d.ts +4 -4
  449. package/dist/platform/drive/stall-detector/analysis.d.ts +5 -0
  450. package/dist/platform/drive/stall-detector/analysis.d.ts.map +1 -0
  451. package/dist/platform/drive/stall-detector/analysis.js +55 -0
  452. package/dist/platform/drive/stall-detector/analysis.js.map +1 -0
  453. package/dist/platform/drive/stall-detector/repetitive.d.ts +3 -0
  454. package/dist/platform/drive/stall-detector/repetitive.d.ts.map +1 -0
  455. package/dist/platform/drive/stall-detector/repetitive.js +72 -0
  456. package/dist/platform/drive/stall-detector/repetitive.js.map +1 -0
  457. package/dist/platform/drive/stall-detector/thresholds.d.ts +10 -0
  458. package/dist/platform/drive/stall-detector/thresholds.d.ts.map +1 -0
  459. package/dist/platform/drive/stall-detector/thresholds.js +61 -0
  460. package/dist/platform/drive/stall-detector/thresholds.js.map +1 -0
  461. package/dist/platform/drive/stall-detector.d.ts +2 -20
  462. package/dist/platform/drive/stall-detector.d.ts.map +1 -1
  463. package/dist/platform/drive/stall-detector.js +9 -202
  464. package/dist/platform/drive/stall-detector.js.map +1 -1
  465. package/dist/platform/knowledge/knowledge-manager-agent-memory.d.ts +55 -0
  466. package/dist/platform/knowledge/knowledge-manager-agent-memory.d.ts.map +1 -0
  467. package/dist/platform/knowledge/knowledge-manager-agent-memory.js +232 -0
  468. package/dist/platform/knowledge/knowledge-manager-agent-memory.js.map +1 -0
  469. package/dist/platform/knowledge/knowledge-manager-internals.d.ts +10 -0
  470. package/dist/platform/knowledge/knowledge-manager-internals.d.ts.map +1 -0
  471. package/dist/platform/knowledge/knowledge-manager-internals.js +43 -0
  472. package/dist/platform/knowledge/knowledge-manager-internals.js.map +1 -0
  473. package/dist/platform/knowledge/knowledge-manager-store.d.ts +13 -0
  474. package/dist/platform/knowledge/knowledge-manager-store.d.ts.map +1 -0
  475. package/dist/platform/knowledge/knowledge-manager-store.js +67 -0
  476. package/dist/platform/knowledge/knowledge-manager-store.js.map +1 -0
  477. package/dist/platform/knowledge/knowledge-manager.d.ts +6 -2
  478. package/dist/platform/knowledge/knowledge-manager.d.ts.map +1 -1
  479. package/dist/platform/knowledge/knowledge-manager.js +43 -344
  480. package/dist/platform/knowledge/knowledge-manager.js.map +1 -1
  481. package/dist/platform/knowledge/memory/memory-lifecycle-storage.d.ts +4 -0
  482. package/dist/platform/knowledge/memory/memory-lifecycle-storage.d.ts.map +1 -0
  483. package/dist/platform/knowledge/memory/memory-lifecycle-storage.js +106 -0
  484. package/dist/platform/knowledge/memory/memory-lifecycle-storage.js.map +1 -0
  485. package/dist/platform/knowledge/memory/memory-lifecycle.d.ts.map +1 -1
  486. package/dist/platform/knowledge/memory/memory-lifecycle.js +6 -112
  487. package/dist/platform/knowledge/memory/memory-lifecycle.js.map +1 -1
  488. package/dist/platform/observation/capability-detector/prompts.d.ts +18 -0
  489. package/dist/platform/observation/capability-detector/prompts.d.ts.map +1 -0
  490. package/dist/platform/observation/capability-detector/prompts.js +80 -0
  491. package/dist/platform/observation/capability-detector/prompts.js.map +1 -0
  492. package/dist/platform/observation/capability-detector/recommendations.d.ts +5 -0
  493. package/dist/platform/observation/capability-detector/recommendations.d.ts.map +1 -0
  494. package/dist/platform/observation/capability-detector/recommendations.js +76 -0
  495. package/dist/platform/observation/capability-detector/recommendations.js.map +1 -0
  496. package/dist/platform/observation/capability-detector/types.d.ts +112 -0
  497. package/dist/platform/observation/capability-detector/types.d.ts.map +1 -0
  498. package/dist/platform/observation/capability-detector/types.js +75 -0
  499. package/dist/platform/observation/capability-detector/types.js.map +1 -0
  500. package/dist/platform/observation/capability-detector.d.ts +4 -9
  501. package/dist/platform/observation/capability-detector.d.ts.map +1 -1
  502. package/dist/platform/observation/capability-detector.js +12 -212
  503. package/dist/platform/observation/capability-detector.js.map +1 -1
  504. package/dist/platform/observation/context-provider/collector.d.ts +13 -0
  505. package/dist/platform/observation/context-provider/collector.d.ts.map +1 -0
  506. package/dist/platform/observation/context-provider/collector.js +259 -0
  507. package/dist/platform/observation/context-provider/collector.js.map +1 -0
  508. package/dist/platform/observation/context-provider/search-terms.d.ts +2 -0
  509. package/dist/platform/observation/context-provider/search-terms.d.ts.map +1 -0
  510. package/dist/platform/observation/context-provider/search-terms.js +24 -0
  511. package/dist/platform/observation/context-provider/search-terms.js.map +1 -0
  512. package/dist/platform/observation/context-provider/shared.d.ts +17 -0
  513. package/dist/platform/observation/context-provider/shared.d.ts.map +1 -0
  514. package/dist/platform/observation/context-provider/shared.js +87 -0
  515. package/dist/platform/observation/context-provider/shared.js.map +1 -0
  516. package/dist/platform/observation/context-provider.d.ts +3 -28
  517. package/dist/platform/observation/context-provider.d.ts.map +1 -1
  518. package/dist/platform/observation/context-provider.js +7 -358
  519. package/dist/platform/observation/context-provider.js.map +1 -1
  520. package/dist/platform/observation/workspace-context.d.ts.map +1 -1
  521. package/dist/platform/observation/workspace-context.js +27 -0
  522. package/dist/platform/observation/workspace-context.js.map +1 -1
  523. package/dist/platform/soil/compiled-memory-projections.d.ts +2 -0
  524. package/dist/platform/soil/compiled-memory-projections.d.ts.map +1 -1
  525. package/dist/platform/soil/compiled-memory-projections.js +59 -0
  526. package/dist/platform/soil/compiled-memory-projections.js.map +1 -1
  527. package/dist/platform/soil/contracts.d.ts +2 -2
  528. package/dist/platform/soil/retriever.d.ts +25 -0
  529. package/dist/platform/soil/retriever.d.ts.map +1 -1
  530. package/dist/platform/soil/retriever.js +94 -5
  531. package/dist/platform/soil/retriever.js.map +1 -1
  532. package/dist/platform/soil/sqlite-repository-helpers.d.ts +80 -0
  533. package/dist/platform/soil/sqlite-repository-helpers.d.ts.map +1 -0
  534. package/dist/platform/soil/sqlite-repository-helpers.js +143 -0
  535. package/dist/platform/soil/sqlite-repository-helpers.js.map +1 -0
  536. package/dist/platform/soil/sqlite-repository-search.d.ts +8 -0
  537. package/dist/platform/soil/sqlite-repository-search.d.ts.map +1 -0
  538. package/dist/platform/soil/sqlite-repository-search.js +367 -0
  539. package/dist/platform/soil/sqlite-repository-search.js.map +1 -0
  540. package/dist/platform/soil/sqlite-repository-storage.d.ts +8 -0
  541. package/dist/platform/soil/sqlite-repository-storage.d.ts.map +1 -0
  542. package/dist/platform/soil/sqlite-repository-storage.js +278 -0
  543. package/dist/platform/soil/sqlite-repository-storage.js.map +1 -0
  544. package/dist/platform/soil/sqlite-repository.d.ts +1 -4
  545. package/dist/platform/soil/sqlite-repository.d.ts.map +1 -1
  546. package/dist/platform/soil/sqlite-repository.js +26 -820
  547. package/dist/platform/soil/sqlite-repository.js.map +1 -1
  548. package/dist/runtime/daemon/client.d.ts +13 -1
  549. package/dist/runtime/daemon/client.d.ts.map +1 -1
  550. package/dist/runtime/daemon/client.js +2 -2
  551. package/dist/runtime/daemon/client.js.map +1 -1
  552. package/dist/runtime/daemon/index.d.ts +1 -1
  553. package/dist/runtime/daemon/index.d.ts.map +1 -1
  554. package/dist/runtime/daemon/index.js +1 -1
  555. package/dist/runtime/daemon/index.js.map +1 -1
  556. package/dist/runtime/daemon/maintenance.d.ts +2 -10
  557. package/dist/runtime/daemon/maintenance.d.ts.map +1 -1
  558. package/dist/runtime/daemon/maintenance.js +14 -45
  559. package/dist/runtime/daemon/maintenance.js.map +1 -1
  560. package/dist/runtime/daemon/runner-bootstrap.d.ts +25 -0
  561. package/dist/runtime/daemon/runner-bootstrap.d.ts.map +1 -0
  562. package/dist/runtime/daemon/runner-bootstrap.js +77 -0
  563. package/dist/runtime/daemon/runner-bootstrap.js.map +1 -0
  564. package/dist/runtime/daemon/runner-commands.d.ts +14 -6
  565. package/dist/runtime/daemon/runner-commands.d.ts.map +1 -1
  566. package/dist/runtime/daemon/runner-commands.js +63 -17
  567. package/dist/runtime/daemon/runner-commands.js.map +1 -1
  568. package/dist/runtime/daemon/runner-goal-cycle.d.ts.map +1 -1
  569. package/dist/runtime/daemon/runner-goal-cycle.js +3 -5
  570. package/dist/runtime/daemon/runner-goal-cycle.js.map +1 -1
  571. package/dist/runtime/daemon/runner-resident-curiosity.d.ts +12 -0
  572. package/dist/runtime/daemon/runner-resident-curiosity.d.ts.map +1 -0
  573. package/dist/runtime/daemon/runner-resident-curiosity.js +155 -0
  574. package/dist/runtime/daemon/runner-resident-curiosity.js.map +1 -0
  575. package/dist/runtime/daemon/runner-resident-dream.d.ts +20 -0
  576. package/dist/runtime/daemon/runner-resident-dream.d.ts.map +1 -0
  577. package/dist/runtime/daemon/runner-resident-dream.js +148 -0
  578. package/dist/runtime/daemon/runner-resident-dream.js.map +1 -0
  579. package/dist/runtime/daemon/runner-resident-proactive.d.ts +4 -0
  580. package/dist/runtime/daemon/runner-resident-proactive.d.ts.map +1 -0
  581. package/dist/runtime/daemon/runner-resident-proactive.js +113 -0
  582. package/dist/runtime/daemon/runner-resident-proactive.js.map +1 -0
  583. package/dist/runtime/daemon/runner-resident-shared.d.ts +40 -0
  584. package/dist/runtime/daemon/runner-resident-shared.d.ts.map +1 -0
  585. package/dist/runtime/daemon/runner-resident-shared.js +101 -0
  586. package/dist/runtime/daemon/runner-resident-shared.js.map +1 -0
  587. package/dist/runtime/daemon/runner-resident.d.ts +4 -68
  588. package/dist/runtime/daemon/runner-resident.d.ts.map +1 -1
  589. package/dist/runtime/daemon/runner-resident.js +4 -506
  590. package/dist/runtime/daemon/runner-resident.js.map +1 -1
  591. package/dist/runtime/daemon/runner-runtime.d.ts +12 -0
  592. package/dist/runtime/daemon/runner-runtime.d.ts.map +1 -0
  593. package/dist/runtime/daemon/runner-runtime.js +43 -0
  594. package/dist/runtime/daemon/runner-runtime.js.map +1 -0
  595. package/dist/runtime/daemon/runner-startup.d.ts.map +1 -1
  596. package/dist/runtime/daemon/runner-startup.js +23 -3
  597. package/dist/runtime/daemon/runner-startup.js.map +1 -1
  598. package/dist/runtime/daemon/runner.d.ts +10 -23
  599. package/dist/runtime/daemon/runner.d.ts.map +1 -1
  600. package/dist/runtime/daemon/runner.js +29 -111
  601. package/dist/runtime/daemon/runner.js.map +1 -1
  602. package/dist/runtime/daemon/runtime-root.d.ts +5 -0
  603. package/dist/runtime/daemon/runtime-root.d.ts.map +1 -0
  604. package/dist/runtime/daemon/runtime-root.js +60 -0
  605. package/dist/runtime/daemon/runtime-root.js.map +1 -0
  606. package/dist/runtime/daemon/wait-deadline-resolver.d.ts +5 -2
  607. package/dist/runtime/daemon/wait-deadline-resolver.d.ts.map +1 -1
  608. package/dist/runtime/daemon/wait-deadline-resolver.js +55 -35
  609. package/dist/runtime/daemon/wait-deadline-resolver.js.map +1 -1
  610. package/dist/runtime/event/dispatcher.d.ts +0 -2
  611. package/dist/runtime/event/dispatcher.d.ts.map +1 -1
  612. package/dist/runtime/event/dispatcher.js +0 -4
  613. package/dist/runtime/event/dispatcher.js.map +1 -1
  614. package/dist/runtime/event/server-command-handler.d.ts.map +1 -1
  615. package/dist/runtime/event/server-command-handler.js +47 -3
  616. package/dist/runtime/event/server-command-handler.js.map +1 -1
  617. package/dist/runtime/executor/goal-worker.d.ts +3 -1
  618. package/dist/runtime/executor/goal-worker.d.ts.map +1 -1
  619. package/dist/runtime/executor/goal-worker.js +3 -1
  620. package/dist/runtime/executor/goal-worker.js.map +1 -1
  621. package/dist/runtime/executor/loop-supervisor.d.ts +27 -1
  622. package/dist/runtime/executor/loop-supervisor.d.ts.map +1 -1
  623. package/dist/runtime/executor/loop-supervisor.js +218 -13
  624. package/dist/runtime/executor/loop-supervisor.js.map +1 -1
  625. package/dist/runtime/gateway/telegram-gateway-adapter.d.ts.map +1 -1
  626. package/dist/runtime/gateway/telegram-gateway-adapter.js +2 -1
  627. package/dist/runtime/gateway/telegram-gateway-adapter.js.map +1 -1
  628. package/dist/runtime/schedule/engine-cron-reflection.d.ts +31 -0
  629. package/dist/runtime/schedule/engine-cron-reflection.d.ts.map +1 -0
  630. package/dist/runtime/schedule/engine-cron-reflection.js +229 -0
  631. package/dist/runtime/schedule/engine-cron-reflection.js.map +1 -0
  632. package/dist/runtime/schedule/engine-execution.d.ts +47 -0
  633. package/dist/runtime/schedule/engine-execution.d.ts.map +1 -0
  634. package/dist/runtime/schedule/engine-execution.js +424 -0
  635. package/dist/runtime/schedule/engine-execution.js.map +1 -0
  636. package/dist/runtime/schedule/engine-heartbeat.d.ts +5 -0
  637. package/dist/runtime/schedule/engine-heartbeat.d.ts.map +1 -0
  638. package/dist/runtime/schedule/engine-heartbeat.js +104 -0
  639. package/dist/runtime/schedule/engine-heartbeat.js.map +1 -0
  640. package/dist/runtime/schedule/engine-layers.d.ts +2 -0
  641. package/dist/runtime/schedule/engine-layers.d.ts.map +1 -1
  642. package/dist/runtime/schedule/engine-layers.js +12 -228
  643. package/dist/runtime/schedule/engine-layers.js.map +1 -1
  644. package/dist/runtime/schedule/engine-mutations.d.ts +37 -0
  645. package/dist/runtime/schedule/engine-mutations.d.ts.map +1 -0
  646. package/dist/runtime/schedule/engine-mutations.js +263 -0
  647. package/dist/runtime/schedule/engine-mutations.js.map +1 -0
  648. package/dist/runtime/schedule/engine.d.ts +11 -38
  649. package/dist/runtime/schedule/engine.d.ts.map +1 -1
  650. package/dist/runtime/schedule/engine.js +65 -810
  651. package/dist/runtime/schedule/engine.js.map +1 -1
  652. package/dist/runtime/schedule/history.d.ts +16 -0
  653. package/dist/runtime/schedule/history.d.ts.map +1 -1
  654. package/dist/runtime/schedule/history.js +8 -0
  655. package/dist/runtime/schedule/history.js.map +1 -1
  656. package/dist/runtime/schedule/index.d.ts +1 -0
  657. package/dist/runtime/schedule/index.d.ts.map +1 -1
  658. package/dist/runtime/schedule/index.js +1 -0
  659. package/dist/runtime/schedule/index.js.map +1 -1
  660. package/dist/runtime/schedule/legacy-cron-migration.d.ts +9 -0
  661. package/dist/runtime/schedule/legacy-cron-migration.d.ts.map +1 -0
  662. package/dist/runtime/schedule/legacy-cron-migration.js +89 -0
  663. package/dist/runtime/schedule/legacy-cron-migration.js.map +1 -0
  664. package/dist/runtime/schedule/wait-projection.d.ts +6 -0
  665. package/dist/runtime/schedule/wait-projection.d.ts.map +1 -0
  666. package/dist/runtime/schedule/wait-projection.js +102 -0
  667. package/dist/runtime/schedule/wait-projection.js.map +1 -0
  668. package/dist/runtime/session-registry/index.d.ts +3 -0
  669. package/dist/runtime/session-registry/index.d.ts.map +1 -0
  670. package/dist/runtime/session-registry/index.js +3 -0
  671. package/dist/runtime/session-registry/index.js.map +1 -0
  672. package/dist/runtime/session-registry/registry-helpers.d.ts +34 -0
  673. package/dist/runtime/session-registry/registry-helpers.d.ts.map +1 -0
  674. package/dist/runtime/session-registry/registry-helpers.js +241 -0
  675. package/dist/runtime/session-registry/registry-helpers.js.map +1 -0
  676. package/dist/runtime/session-registry/registry.d.ts +39 -0
  677. package/dist/runtime/session-registry/registry.d.ts.map +1 -0
  678. package/dist/runtime/session-registry/registry.js +532 -0
  679. package/dist/runtime/session-registry/registry.js.map +1 -0
  680. package/dist/runtime/session-registry/types.d.ts +985 -0
  681. package/dist/runtime/session-registry/types.d.ts.map +1 -0
  682. package/dist/runtime/session-registry/types.js +108 -0
  683. package/dist/runtime/session-registry/types.js.map +1 -0
  684. package/dist/runtime/store/background-run-store.d.ts +75 -0
  685. package/dist/runtime/store/background-run-store.d.ts.map +1 -0
  686. package/dist/runtime/store/background-run-store.js +157 -0
  687. package/dist/runtime/store/background-run-store.js.map +1 -0
  688. package/dist/runtime/store/index.d.ts +2 -0
  689. package/dist/runtime/store/index.d.ts.map +1 -1
  690. package/dist/runtime/store/index.js +1 -0
  691. package/dist/runtime/store/index.js.map +1 -1
  692. package/dist/runtime/store/runtime-operation-schemas.d.ts +12 -12
  693. package/dist/runtime/store/runtime-paths.d.ts +2 -0
  694. package/dist/runtime/store/runtime-paths.d.ts.map +1 -1
  695. package/dist/runtime/store/runtime-paths.js +6 -0
  696. package/dist/runtime/store/runtime-paths.js.map +1 -1
  697. package/dist/runtime/store/runtime-schemas.d.ts +2 -2
  698. package/dist/runtime/types/daemon.d.ts +13 -0
  699. package/dist/runtime/types/daemon.d.ts.map +1 -1
  700. package/dist/runtime/types/daemon.js +3 -0
  701. package/dist/runtime/types/daemon.js.map +1 -1
  702. package/dist/runtime/types/schedule.d.ts +65 -0
  703. package/dist/runtime/types/schedule.d.ts.map +1 -1
  704. package/dist/runtime/types/schedule.js +5 -0
  705. package/dist/runtime/types/schedule.js.map +1 -1
  706. package/dist/tools/builtin/exports.d.ts +5 -0
  707. package/dist/tools/builtin/exports.d.ts.map +1 -1
  708. package/dist/tools/builtin/exports.js +5 -0
  709. package/dist/tools/builtin/exports.js.map +1 -1
  710. package/dist/tools/builtin/factory.d.ts +2 -0
  711. package/dist/tools/builtin/factory.d.ts.map +1 -1
  712. package/dist/tools/builtin/factory.js +26 -1
  713. package/dist/tools/builtin/factory.js.map +1 -1
  714. package/dist/tools/fs/FileValidationTool/protected-path-policy.d.ts +1 -0
  715. package/dist/tools/fs/FileValidationTool/protected-path-policy.d.ts.map +1 -1
  716. package/dist/tools/fs/FileValidationTool/protected-path-policy.js +17 -4
  717. package/dist/tools/fs/FileValidationTool/protected-path-policy.js.map +1 -1
  718. package/dist/tools/fs/GlobTool/GlobTool.js +2 -2
  719. package/dist/tools/fs/GlobTool/GlobTool.js.map +1 -1
  720. package/dist/tools/fs/GrepTool/GrepTool.js +2 -2
  721. package/dist/tools/fs/GrepTool/GrepTool.js.map +1 -1
  722. package/dist/tools/fs/ListDirTool/ListDirTool.js +1 -1
  723. package/dist/tools/fs/ListDirTool/ListDirTool.js.map +1 -1
  724. package/dist/tools/fs/ReadTool/ReadTool.js +2 -2
  725. package/dist/tools/fs/ReadTool/ReadTool.js.map +1 -1
  726. package/dist/tools/kaggle/KaggleExperimentTools.d.ts +395 -0
  727. package/dist/tools/kaggle/KaggleExperimentTools.d.ts.map +1 -0
  728. package/dist/tools/kaggle/KaggleExperimentTools.js +923 -0
  729. package/dist/tools/kaggle/KaggleExperimentTools.js.map +1 -0
  730. package/dist/tools/kaggle/KaggleSubmissionTools.d.ts +241 -0
  731. package/dist/tools/kaggle/KaggleSubmissionTools.d.ts.map +1 -0
  732. package/dist/tools/kaggle/KaggleSubmissionTools.js +558 -0
  733. package/dist/tools/kaggle/KaggleSubmissionTools.js.map +1 -0
  734. package/dist/tools/kaggle/KaggleWorkspacePrepareTool.d.ts +105 -0
  735. package/dist/tools/kaggle/KaggleWorkspacePrepareTool.d.ts.map +1 -0
  736. package/dist/tools/kaggle/KaggleWorkspacePrepareTool.js +135 -0
  737. package/dist/tools/kaggle/KaggleWorkspacePrepareTool.js.map +1 -0
  738. package/dist/tools/kaggle/index.d.ts +6 -0
  739. package/dist/tools/kaggle/index.d.ts.map +1 -0
  740. package/dist/tools/kaggle/index.js +6 -0
  741. package/dist/tools/kaggle/index.js.map +1 -0
  742. package/dist/tools/kaggle/metrics.d.ts +89 -0
  743. package/dist/tools/kaggle/metrics.d.ts.map +1 -0
  744. package/dist/tools/kaggle/metrics.js +51 -0
  745. package/dist/tools/kaggle/metrics.js.map +1 -0
  746. package/dist/tools/kaggle/paths.d.ts +15 -0
  747. package/dist/tools/kaggle/paths.d.ts.map +1 -0
  748. package/dist/tools/kaggle/paths.js +142 -0
  749. package/dist/tools/kaggle/paths.js.map +1 -0
  750. package/dist/tools/network/GitHubCliTool/GitHubCliTool.d.ts +2 -2
  751. package/dist/tools/query/CodeReadContextTool/CodeReadContextTool.d.ts +801 -0
  752. package/dist/tools/query/CodeReadContextTool/CodeReadContextTool.d.ts.map +1 -0
  753. package/dist/tools/query/CodeReadContextTool/CodeReadContextTool.js +147 -0
  754. package/dist/tools/query/CodeReadContextTool/CodeReadContextTool.js.map +1 -0
  755. package/dist/tools/query/CodeReadContextTool/constants.d.ts +5 -0
  756. package/dist/tools/query/CodeReadContextTool/constants.d.ts.map +1 -0
  757. package/dist/tools/query/CodeReadContextTool/constants.js +5 -0
  758. package/dist/tools/query/CodeReadContextTool/constants.js.map +1 -0
  759. package/dist/tools/query/CodeReadContextTool/prompt.d.ts +2 -0
  760. package/dist/tools/query/CodeReadContextTool/prompt.d.ts.map +1 -0
  761. package/dist/tools/query/CodeReadContextTool/prompt.js +6 -0
  762. package/dist/tools/query/CodeReadContextTool/prompt.js.map +1 -0
  763. package/dist/tools/query/CodeSearchRepairTool/CodeSearchRepairTool.d.ts +125 -0
  764. package/dist/tools/query/CodeSearchRepairTool/CodeSearchRepairTool.d.ts.map +1 -0
  765. package/dist/tools/query/CodeSearchRepairTool/CodeSearchRepairTool.js +118 -0
  766. package/dist/tools/query/CodeSearchRepairTool/CodeSearchRepairTool.js.map +1 -0
  767. package/dist/tools/query/CodeSearchRepairTool/constants.d.ts +5 -0
  768. package/dist/tools/query/CodeSearchRepairTool/constants.d.ts.map +1 -0
  769. package/dist/tools/query/CodeSearchRepairTool/constants.js +5 -0
  770. package/dist/tools/query/CodeSearchRepairTool/constants.js.map +1 -0
  771. package/dist/tools/query/CodeSearchRepairTool/prompt.d.ts +2 -0
  772. package/dist/tools/query/CodeSearchRepairTool/prompt.d.ts.map +1 -0
  773. package/dist/tools/query/CodeSearchRepairTool/prompt.js +5 -0
  774. package/dist/tools/query/CodeSearchRepairTool/prompt.js.map +1 -0
  775. package/dist/tools/query/CodeSearchTool/CodeSearchTool.d.ts +123 -0
  776. package/dist/tools/query/CodeSearchTool/CodeSearchTool.d.ts.map +1 -0
  777. package/dist/tools/query/CodeSearchTool/CodeSearchTool.js +117 -0
  778. package/dist/tools/query/CodeSearchTool/CodeSearchTool.js.map +1 -0
  779. package/dist/tools/query/CodeSearchTool/constants.d.ts +5 -0
  780. package/dist/tools/query/CodeSearchTool/constants.d.ts.map +1 -0
  781. package/dist/tools/query/CodeSearchTool/constants.js +5 -0
  782. package/dist/tools/query/CodeSearchTool/constants.js.map +1 -0
  783. package/dist/tools/query/CodeSearchTool/prompt.d.ts +2 -0
  784. package/dist/tools/query/CodeSearchTool/prompt.d.ts.map +1 -0
  785. package/dist/tools/query/CodeSearchTool/prompt.js +6 -0
  786. package/dist/tools/query/CodeSearchTool/prompt.js.map +1 -0
  787. package/dist/tools/query/SoilQueryTool/SoilQueryTool.d.ts.map +1 -1
  788. package/dist/tools/query/SoilQueryTool/SoilQueryTool.js +43 -9
  789. package/dist/tools/query/SoilQueryTool/SoilQueryTool.js.map +1 -1
  790. package/dist/tools/query/code-search-root.d.ts +8 -0
  791. package/dist/tools/query/code-search-root.d.ts.map +1 -0
  792. package/dist/tools/query/code-search-root.js +41 -0
  793. package/dist/tools/query/code-search-root.js.map +1 -0
  794. package/dist/tools/query/runtime-session-tools.d.ts +560 -0
  795. package/dist/tools/query/runtime-session-tools.d.ts.map +1 -0
  796. package/dist/tools/query/runtime-session-tools.js +1015 -0
  797. package/dist/tools/query/runtime-session-tools.js.map +1 -0
  798. package/dist/tools/runtime/LongRunningRuntimeTools.d.ts +821 -0
  799. package/dist/tools/runtime/LongRunningRuntimeTools.d.ts.map +1 -0
  800. package/dist/tools/runtime/LongRunningRuntimeTools.js +845 -0
  801. package/dist/tools/runtime/LongRunningRuntimeTools.js.map +1 -0
  802. package/dist/tools/system/ProcessSessionTool/ProcessSessionTool.d.ts +1 -0
  803. package/dist/tools/system/ProcessSessionTool/ProcessSessionTool.d.ts.map +1 -1
  804. package/dist/tools/system/ProcessSessionTool/ProcessSessionTool.js +11 -0
  805. package/dist/tools/system/ProcessSessionTool/ProcessSessionTool.js.map +1 -1
  806. package/dist/tools/system/ShellTool/ShellTool.d.ts.map +1 -1
  807. package/dist/tools/system/ShellTool/ShellTool.js +2 -1
  808. package/dist/tools/system/ShellTool/ShellTool.js.map +1 -1
  809. package/dist/tools/types.d.ts +2 -0
  810. package/dist/tools/types.d.ts.map +1 -1
  811. package/dist/tools/types.js.map +1 -1
  812. package/package.json +2 -1
  813. package/dist/base/types/cron.d.ts +0 -2
  814. package/dist/base/types/cron.d.ts.map +0 -1
  815. package/dist/base/types/cron.js +0 -3
  816. package/dist/base/types/cron.js.map +0 -1
  817. package/dist/runtime/cron-scheduler.d.ts +0 -13
  818. package/dist/runtime/cron-scheduler.d.ts.map +0 -1
  819. package/dist/runtime/cron-scheduler.js +0 -90
  820. package/dist/runtime/cron-scheduler.js.map +0 -1
  821. package/dist/runtime/types/cron.d.ts +0 -59
  822. package/dist/runtime/types/cron.d.ts.map +0 -1
  823. package/dist/runtime/types/cron.js +0 -13
  824. package/dist/runtime/types/cron.js.map +0 -1
@@ -2,81 +2,36 @@
2
2
  //
3
3
  // Central coordinator for 1-shot chat execution (Tier 1).
4
4
  // Bypasses TaskLifecycle — calls adapter.execute() directly.
5
- import { execFile } from "node:child_process";
6
- import * as fsp from "node:fs/promises";
7
- import * as path from "node:path";
8
5
  import { getPulseedDirPath } from "../../base/utils/paths.js";
9
6
  import { getSelfIdentityResponseForBaseDir } from "../../base/config/identity-loader.js";
10
- import { loadProviderConfig } from "../../base/llm/provider-config.js";
11
- import { TaskSchema } from "../../base/types/task.js";
12
7
  import { ChatHistory } from "./chat-history.js";
13
8
  import { ChatSessionCatalog, ChatSessionSelectorError, } from "./chat-session-store.js";
14
9
  import { buildChatContext, resolveGitRoot } from "../../platform/observation/context-provider.js";
15
10
  import { buildChatAgentLoopSystemPrompt, buildStaticSystemPrompt, createChatGroundingGateway } from "./grounding.js";
16
- import { verifyChatAction } from "./chat-verifier.js";
17
- import { toToolDefinitionsFiltered } from "../../tools/tool-definition-adapter.js";
18
- import { TendCommand } from "./tend-command.js";
19
- import { EventSubscriber } from "./event-subscriber.js";
20
- import { buildPromptedToolProtocolSystemPrompt, extractPromptedToolCalls, } from "../../orchestrator/execution/agent-loop/prompted-tool-protocol.js";
21
- import { resolveExecutionPolicy, summarizeExecutionPolicy, withExecutionPolicyOverrides, } from "../../orchestrator/execution/agent-loop/execution-policy.js";
22
- import { buildStandaloneIngressMessage, createIngressRouter, } from "./ingress-router.js";
11
+ import { createIngressRouter, } from "./ingress-router.js";
12
+ import { classifyInterruptRedirect, collectGitDiffArtifact, previewActivityText } from "./chat-runner-support.js";
13
+ import { COMMAND_HELP, ChatRunnerCommandHandler, } from "./chat-runner-commands.js";
14
+ import { ChatRunnerEventBridge } from "./chat-runner-event-bridge.js";
15
+ import { buildRuntimeControlContextFromIngress, buildStandaloneIngressMessageFromContext, formatRoute, getRouteCapabilities, loadedSessionToChatSession, resolveChatResumeSelector, } from "./chat-runner-runtime.js";
16
+ import { executeAdapterRoute, executeAgentLoopRoute, executeRuntimeControlRoute, executeToolLoopRoute, resolveSessionExecutionPolicy, } from "./chat-runner-routes.js";
23
17
  const DEFAULT_TIMEOUT_MS = 120_000;
24
- const MAX_VERIFY_RETRIES = 2;
25
- const MAX_TOOL_LOOPS = 5;
26
- const ACTIVITY_PREVIEW_CHARS = 40;
27
- const standaloneIngressRouter = createIngressRouter();
28
- // ─── Command help text ───
29
- const COMMAND_HELP = `Available commands:
30
- Session
31
- /help Show this help message
32
- /clear Clear conversation history
33
- /sessions List prior chat sessions
34
- /history [id|title] Show saved chat history
35
- /title <title> Rename the current session
36
- /resume [id|title] Resume native agentloop state for the current or selected session
37
- /cleanup [--dry-run] Clean up stale chat sessions
38
- /compact Summarize older chat turns and keep the latest turns
39
- /exit Exit chat mode
40
-
41
- Goals and tasks
42
- /status [goal-id] Show active goal status, or one goal when an id is provided
43
- /goals List goals
44
- /tasks [goal-id] List tasks for a goal; uses the only active goal when unambiguous
45
- /task <task-id> [goal-id]
46
- Show one task; searches goals when no goal id is provided
47
- /track Promote session to Tier 2 goal pursuit (not yet implemented)
48
- /tend Generate a goal from chat history and start autonomous daemon execution
49
-
50
- Configuration
51
- /config Show provider configuration with secrets masked
52
- /model Show the active provider/model/adapter
53
- /permissions [args] Show or update session execution policy
54
- /plugins List installed plugins when plugin metadata is available
55
- /usage [scope] Show usage summary (session, goal <id>, daemon <goal-id>, schedule [7d|24h|2w])
56
-
57
- Review and branching
58
- /review Show current diff summary and verification context
59
- /fork [title] Fork the current chat session into a new session
60
- /undo Remove the latest chat turn from session history
61
-
62
- Deferred
63
- /retry is intentionally not supported yet.`;
64
- // ─── Helpers ───
65
- function checkGitChanges(cwd) {
66
- return new Promise((resolve) => {
67
- execFile("git", ["diff", "HEAD", "--stat"], { cwd, timeout: 5_000 }, (err, stdout, stderr) => {
68
- resolve(err ? null : (stdout + stderr).trim());
69
- });
70
- });
71
- }
72
- function previewActivityText(value, maxChars = ACTIVITY_PREVIEW_CHARS) {
73
- const normalized = value.replace(/\s+/g, " ").trim();
74
- return normalized.length > maxChars ? `${normalized.slice(0, maxChars)}...` : normalized;
75
- }
76
- function formatToolActivity(action, toolName, detail) {
77
- const preview = detail ? previewActivityText(detail) : "";
78
- return preview ? `${action} tool: ${toolName} - ${preview}` : `${action} tool: ${toolName}`;
18
+ function normalizePinnedReplyTarget(replyTarget) {
19
+ if (!replyTarget)
20
+ return null;
21
+ const channel = replyTarget.channel ?? replyTarget.surface;
22
+ if (!channel)
23
+ return null;
24
+ return {
25
+ channel,
26
+ target_id: replyTarget.conversation_id ?? replyTarget.identity_key ?? replyTarget.response_channel ?? null,
27
+ thread_id: replyTarget.message_id ?? null,
28
+ metadata: {
29
+ ...replyTarget,
30
+ ...(replyTarget.metadata ?? {}),
31
+ },
32
+ };
79
33
  }
34
+ const standaloneIngressRouter = createIngressRouter();
80
35
  function resolveSelfIdentityResponse(input, baseDir) {
81
36
  const normalized = input.trim().toLowerCase().replace(/\s+/g, "");
82
37
  if (!normalized)
@@ -91,43 +46,52 @@ function resolveSelfIdentityResponse(input, baseDir) {
91
46
  return null;
92
47
  return getSelfIdentityResponseForBaseDir(baseDir, isEnglishIdentityQuestion ? "en" : "ja");
93
48
  }
94
- // ─── ChatRunner ───
95
49
  export class ChatRunner {
96
50
  deps;
97
51
  groundingGateway;
52
+ eventBridge;
53
+ commandHandler;
98
54
  history = null;
99
55
  sessionCwd = null;
100
- /** True when startSession() has been called — enables session persistence across execute() calls. */
101
56
  sessionActive = false;
102
- /** Deferred tools activated by ToolSearch results — included in tool definitions for subsequent turns. */
103
57
  activatedTools = new Set();
104
- /** Cached static system prompt — reused across turns; dynamic context is rebuilt each turn. */
105
58
  cachedStaticSystemPrompt = null;
106
- /** Pending /tend state awaiting user confirmation (Y/n). */
107
59
  pendingTend = null;
108
- /** Active EventSubscriber instances keyed by goalId. */
109
60
  activeSubscribers = new Map();
110
- /**
111
- * Callback invoked when a /tend daemon notification arrives.
112
- * Can be set after construction (e.g. from a React component via useEffect).
113
- */
114
61
  onNotification = undefined;
115
62
  onEvent = undefined;
116
63
  nativeAgentLoopStatePath = null;
117
64
  runtimeControlContext = null;
118
65
  sessionExecutionPolicy = null;
66
+ lastSelectedRoute = null;
119
67
  constructor(deps) {
120
68
  this.deps = deps;
121
69
  this.groundingGateway = createChatGroundingGateway({
122
70
  stateManager: deps.stateManager,
123
71
  pluginLoader: deps.pluginLoader,
124
72
  });
73
+ this.eventBridge = new ChatRunnerEventBridge(() => this.onEvent ?? this.deps.onEvent);
74
+ this.commandHandler = new ChatRunnerCommandHandler({
75
+ deps: this.deps,
76
+ onNotification: this.onNotification,
77
+ getHistory: () => this.history,
78
+ setHistory: (history) => { this.history = history; },
79
+ getSessionCwd: () => this.sessionCwd,
80
+ setSessionCwd: (cwd) => { this.sessionCwd = cwd; },
81
+ setSessionActive: (active) => { this.sessionActive = active; },
82
+ getNativeAgentLoopStatePath: () => this.nativeAgentLoopStatePath,
83
+ setNativeAgentLoopStatePath: (path) => { this.nativeAgentLoopStatePath = path; },
84
+ getRuntimeControlContext: () => this.runtimeControlContext,
85
+ getPendingTend: () => this.pendingTend,
86
+ setPendingTend: (value) => { this.pendingTend = value; },
87
+ getLastSelectedRoute: () => this.lastSelectedRoute,
88
+ getSessionExecutionPolicy: () => this.getSessionExecutionPolicy(),
89
+ emitEvent: (event) => this.eventBridge.emitEvent(event),
90
+ getActiveSubscribers: () => this.activeSubscribers,
91
+ setSessionExecutionPolicy: (policy) => { this.sessionExecutionPolicy = policy; },
92
+ resetSessionExecutionPolicy: () => { this.sessionExecutionPolicy = null; },
93
+ });
125
94
  }
126
- /**
127
- * Initialize a persistent session for interactive (multi-turn) mode.
128
- * Must be called before the first execute() to share history across turns.
129
- * If not called, execute() auto-creates a new session per call (Phase 1a behavior).
130
- */
131
95
  startSession(cwd) {
132
96
  const gitRoot = resolveGitRoot(cwd);
133
97
  const sessionId = crypto.randomUUID();
@@ -135,13 +99,13 @@ export class ChatRunner {
135
99
  this.sessionCwd = gitRoot;
136
100
  this.sessionActive = true;
137
101
  this.nativeAgentLoopStatePath = `chat/agentloop/${sessionId}.state.json`;
138
- this.history.setAgentLoopStatePath(this.nativeAgentLoopStatePath);
102
+ this.history.resetAgentLoopState(this.nativeAgentLoopStatePath);
139
103
  this.sessionExecutionPolicy = null;
140
104
  }
141
105
  startSessionFromLoadedSession(session) {
142
- const chatSession = this.loadedSessionToChatSession(session);
106
+ const chatSession = loadedSessionToChatSession(session);
143
107
  this.history = ChatHistory.fromSession(this.deps.stateManager, chatSession);
144
- this.sessionCwd = session.cwd;
108
+ this.sessionCwd = resolveGitRoot(session.cwd);
145
109
  this.sessionActive = true;
146
110
  this.nativeAgentLoopStatePath = session.agentLoopStatePath ?? `chat/agentloop/${session.id}.state.json`;
147
111
  this.history.setAgentLoopStatePath(this.nativeAgentLoopStatePath);
@@ -153,6 +117,65 @@ export class ChatRunner {
153
117
  getCurrentSessionMessages() {
154
118
  return this.history?.getMessages() ?? [];
155
119
  }
120
+ hasActiveTurn() {
121
+ return this.eventBridge.hasActiveTurn();
122
+ }
123
+ async interruptAndRedirect(input, cwd, timeoutMs = DEFAULT_TIMEOUT_MS) {
124
+ const activeTurn = this.eventBridge.getActiveTurn();
125
+ if (!activeTurn) {
126
+ return this.execute(input, cwd, timeoutMs);
127
+ }
128
+ const start = Date.now();
129
+ const redirect = classifyInterruptRedirect(input);
130
+ if (redirect === "background") {
131
+ return this.eventBridge.emitEphemeralAssistantResult(input, [
132
+ "Continuing this same turn in the background is not available yet.",
133
+ "",
134
+ "The active turn is still running in the foreground.",
135
+ "Use /tend for daemon-backed work, or send a narrower follow-up request.",
136
+ ].join("\n"), true, start);
137
+ }
138
+ activeTurn.interruptRequested = true;
139
+ if (!activeTurn.abortController.signal.aborted) {
140
+ activeTurn.abortController.abort();
141
+ }
142
+ this.eventBridge.emitCheckpoint("Interrupt requested", `Redirect: ${previewActivityText(input, 120)}`, activeTurn.context, "interrupt");
143
+ const stopped = await this.eventBridge.waitForActiveTurn(activeTurn, 2_000);
144
+ if (!stopped) {
145
+ return this.eventBridge.emitEphemeralAssistantResult(input, "Interrupt requested. The active turn will stop at the next safe point.", false, start);
146
+ }
147
+ let output;
148
+ if (redirect === "diff") {
149
+ const diff = await collectGitDiffArtifact(activeTurn.cwd);
150
+ if (diff) {
151
+ const context = this.eventBridge.createEventContext();
152
+ this.eventBridge.emitDiffArtifact(diff, context);
153
+ output = "Interrupted the active turn. Current diff is shown above.";
154
+ }
155
+ else {
156
+ output = "Interrupted the active turn. No working-tree changes were detected.";
157
+ }
158
+ }
159
+ else if (redirect === "review") {
160
+ const review = await this.commandHandler.handleCommand("/review", activeTurn.cwd);
161
+ output = `Interrupted the active turn and switched to review-only mode.\n\n${review?.output ?? "Review unavailable."}`;
162
+ }
163
+ else {
164
+ output = [
165
+ "Interrupted the active turn.",
166
+ "",
167
+ "Recent activity",
168
+ ...(activeTurn.recentEvents.length > 0
169
+ ? activeTurn.recentEvents.slice(-6).map((event) => `- ${event}`)
170
+ : ["- No activity was captured before the interrupt."]),
171
+ "",
172
+ "Next actions",
173
+ "- Ask for the exact continuation you want.",
174
+ "- Ask to show diff or switch to review if files may have changed.",
175
+ ].join("\n");
176
+ }
177
+ return this.eventBridge.emitEphemeralAssistantResult(input, output, true, start);
178
+ }
156
179
  setRuntimeControlContext(context) {
157
180
  this.runtimeControlContext = context;
158
181
  }
@@ -160,1142 +183,77 @@ export class ChatRunner {
160
183
  if (!selectedRoute) {
161
184
  throw new Error("executeIngressMessage requires selectedRoute; use CrossPlatformChatSessionManager for ingress route selection.");
162
185
  }
163
- const runtimeControlContext = this.buildRuntimeControlContextFromIngress(ingress);
186
+ const runtimeControlContext = buildRuntimeControlContextFromIngress(ingress, this.runtimeControlContext, this.deps);
164
187
  return this.execute(ingress.text, cwd, timeoutMs, {
165
188
  selectedRoute,
166
189
  runtimeControlContext,
167
190
  goalId: ingress.goal_id,
168
191
  });
169
192
  }
170
- resolveRouteFromIngress(ingress) {
171
- return standaloneIngressRouter.selectRoute(ingress, this.getRouteCapabilities());
172
- }
173
- resolveRouteFromInput(input, runtimeControlContext) {
174
- return this.resolveRouteFromIngress(this.buildStandaloneIngressMessage(input, runtimeControlContext));
175
- }
176
- getRouteCapabilities() {
177
- return {
178
- hasLightweightLlm: this.deps.llmClient !== undefined,
179
- hasAgentLoop: this.deps.chatAgentLoopRunner !== undefined,
180
- hasToolLoop: this.deps.llmClient !== undefined,
181
- hasRuntimeControlService: this.deps.runtimeControlService !== undefined,
182
- };
183
- }
184
- buildStandaloneIngressMessage(input, runtimeControlContext) {
185
- const channel = runtimeControlContext?.replyTarget?.surface === "tui"
186
- ? "tui"
187
- : runtimeControlContext?.replyTarget?.surface === "cli"
188
- ? "cli"
189
- : runtimeControlContext?.replyTarget?.surface === "gateway"
190
- ? "plugin_gateway"
191
- : "cli";
192
- const runtimeApprovalFn = runtimeControlContext?.approvalFn
193
- ?? this.deps.runtimeControlApprovalFn
194
- ?? this.deps.approvalFn;
195
- const replyTarget = runtimeControlContext?.replyTarget ?? this.deps.runtimeReplyTarget;
196
- const replyTargetInput = replyTarget
197
- ? {
198
- ...(replyTarget.surface ? { surface: replyTarget.surface } : {}),
199
- channel,
200
- ...(replyTarget.platform ? { platform: replyTarget.platform } : {}),
201
- ...(replyTarget.conversation_id ? { conversation_id: replyTarget.conversation_id } : {}),
202
- ...(replyTarget.message_id ? { message_id: replyTarget.message_id } : {}),
203
- ...(replyTarget.response_channel ? { response_channel: replyTarget.response_channel } : {}),
204
- ...(replyTarget.outbox_topic ? { outbox_topic: replyTarget.outbox_topic } : {}),
205
- ...(replyTarget.identity_key ? { identity_key: replyTarget.identity_key } : {}),
206
- ...(replyTarget.user_id ? { user_id: replyTarget.user_id } : {}),
207
- ...(replyTarget.deliveryMode === "reply" || replyTarget.deliveryMode === "notify" || replyTarget.deliveryMode === "thread_reply"
208
- ? { deliveryMode: replyTarget.deliveryMode }
209
- : {}),
210
- ...(replyTarget.metadata ? { metadata: replyTarget.metadata } : {}),
211
- }
212
- : undefined;
213
- return buildStandaloneIngressMessage({
214
- text: input,
215
- channel,
216
- platform: runtimeControlContext?.replyTarget?.platform ?? this.deps.runtimeReplyTarget?.platform,
217
- identity_key: runtimeControlContext?.replyTarget?.identity_key ?? this.deps.runtimeReplyTarget?.identity_key,
218
- conversation_id: runtimeControlContext?.replyTarget?.conversation_id ?? this.deps.runtimeReplyTarget?.conversation_id,
219
- user_id: runtimeControlContext?.replyTarget?.user_id ?? this.deps.runtimeReplyTarget?.user_id,
220
- actor: runtimeControlContext?.actor ?? this.deps.runtimeControlActor,
221
- replyTarget: replyTargetInput,
222
- runtimeControl: {
223
- allowed: true,
224
- approvalMode: "interactive",
225
- },
226
- });
227
- }
228
- buildRuntimeControlContextFromIngress(ingress) {
229
- if (!ingress.actor && !ingress.replyTarget)
230
- return null;
231
- const interactiveApproval = this.runtimeControlContext?.approvalFn
232
- ?? this.deps.runtimeControlApprovalFn
233
- ?? this.deps.approvalFn;
234
- return {
235
- actor: ingress.actor,
236
- replyTarget: ingress.replyTarget,
237
- approvalFn: ingress.runtimeControl.approvalMode === "preapproved"
238
- ? async () => true
239
- : ingress.runtimeControl.approvalMode === "interactive"
240
- ? interactiveApproval
241
- : undefined,
242
- };
243
- }
244
- loadedSessionToChatSession(session) {
245
- return {
246
- id: session.id,
247
- cwd: session.cwd,
248
- createdAt: session.createdAt,
249
- updatedAt: session.updatedAt,
250
- messages: [...session.messages],
251
- ...(session.compactionSummary ? { compactionSummary: session.compactionSummary } : {}),
252
- ...(session.title ? { title: session.title } : {}),
253
- ...(session.agentLoopStatePath ? { agentLoopStatePath: session.agentLoopStatePath } : {}),
254
- ...(session.agentLoopStatus === "running" || session.agentLoopStatus === "completed" || session.agentLoopStatus === "failed"
255
- ? { agentLoopStatus: session.agentLoopStatus }
256
- : {}),
257
- ...(session.agentLoopResumable ? { agentLoopResumable: true } : {}),
258
- ...(session.agentLoopUpdatedAt ? { agentLoopUpdatedAt: session.agentLoopUpdatedAt } : {}),
259
- ...(session.agentLoop ? { agentLoop: session.agentLoop } : {}),
260
- };
261
- }
262
- formatSessionsList(entries) {
263
- if (entries.length === 0)
264
- return "No chat sessions found.";
265
- const lines = entries.map((entry) => {
266
- const title = entry.title ? ` "${entry.title}"` : "";
267
- const resumable = entry.agentLoopResumable ? " resumable" : "";
268
- return `${entry.id}${title} - ${entry.messageCount} message(s), updated ${entry.updatedAt}, cwd ${entry.cwd}${resumable}`;
269
- });
270
- return `Chat sessions:\n${lines.join("\n")}`;
271
- }
272
- formatHistory(session) {
273
- const title = session.title ? ` "${session.title}"` : "";
274
- if (session.messages.length === 0) {
275
- return `Session ${session.id}${title} has no messages.`;
276
- }
277
- const lines = session.messages.map((message) => {
278
- const role = message.role === "assistant" ? "Assistant" : "User";
279
- return `${role}: ${message.content}`;
280
- });
281
- return `Session ${session.id}${title} (${session.cwd})\n${lines.join("\n")}`;
282
- }
283
- async loadGoals() {
284
- const goalIds = await this.deps.stateManager.listGoalIds();
285
- const goals = await Promise.all(goalIds.map((id) => this.deps.stateManager.loadGoal(id)));
286
- return goals.filter((goal) => goal !== null);
287
- }
288
- async listAllGoalIds() {
289
- const activeIds = await this.deps.stateManager.listGoalIds();
290
- const archivedIds = await this.deps.stateManager.listArchivedGoals();
291
- const recoverableArchivedIds = await this.listRecoverableArchivedGoalIds();
292
- return [...new Set([...activeIds, ...archivedIds, ...recoverableArchivedIds])];
293
- }
294
- resolveStatePath(baseDir, ...segments) {
295
- const base = path.resolve(baseDir);
296
- const resolved = path.resolve(base, ...segments);
297
- if (!resolved.startsWith(base + path.sep))
298
- return null;
299
- return resolved;
300
- }
301
- async listRecoverableArchivedGoalIds() {
302
- const stateManager = this.deps.stateManager;
303
- if (typeof stateManager.getBaseDir !== "function")
304
- return [];
305
- const archiveDir = this.resolveStatePath(stateManager.getBaseDir(), "archive");
306
- if (archiveDir === null)
307
- return [];
308
- let entries = [];
309
- try {
310
- entries = await fsp.readdir(archiveDir, { withFileTypes: true });
311
- }
312
- catch {
313
- return [];
314
- }
315
- const goalIds = [];
316
- for (const entry of entries) {
317
- if (!entry.isDirectory() || entry.name === ".staging")
318
- continue;
319
- try {
320
- await fsp.access(path.join(archiveDir, entry.name, "goal", "goal.json"));
321
- goalIds.push(entry.name);
322
- }
323
- catch {
324
- continue;
325
- }
326
- }
327
- return goalIds;
328
- }
329
- activeGoals(goals) {
330
- return goals.filter((goal) => goal.status === "active" || goal.status === "waiting" || goal.loop_status === "running");
331
- }
332
- formatGoalLine(goal) {
333
- const dimensions = goal.dimensions.length === 0
334
- ? "no dimensions"
335
- : goal.dimensions
336
- .slice(0, 3)
337
- .map((dimension) => `${dimension.name}: ${String(dimension.current_value)} target ${JSON.stringify(dimension.threshold)}`)
338
- .join("; ");
339
- return `${goal.id} - ${goal.title} [${goal.status}, loop ${goal.loop_status}] ${dimensions}`;
340
- }
341
- async handleStatus(args, start) {
342
- if (args) {
343
- const goal = await this.deps.stateManager.loadGoal(args);
344
- if (!goal) {
345
- return { success: false, output: `Goal not found: ${args}`, elapsed_ms: Date.now() - start };
346
- }
347
- const lines = [
348
- `Goal status: ${goal.title}`,
349
- `ID: ${goal.id}`,
350
- `Status: ${goal.status}`,
351
- `Loop: ${goal.loop_status}`,
352
- `Updated: ${goal.updated_at}`,
353
- `Children: ${goal.children_ids.length}`,
354
- `Dimensions:`,
355
- ...goal.dimensions.map((dimension) => `- ${dimension.name}: current=${String(dimension.current_value)}, threshold=${JSON.stringify(dimension.threshold)}, confidence=${dimension.confidence}`),
356
- ];
357
- return { success: true, output: lines.join("\n"), elapsed_ms: Date.now() - start };
358
- }
359
- const goals = await this.loadGoals();
360
- const active = this.activeGoals(goals);
361
- if (active.length === 0) {
362
- return { success: true, output: "No active goals found.", elapsed_ms: Date.now() - start };
363
- }
364
- return {
365
- success: true,
366
- output: `Active goals:\n${active.map((goal) => this.formatGoalLine(goal)).join("\n")}`,
367
- elapsed_ms: Date.now() - start,
368
- };
369
- }
370
- async handleGoals(start) {
371
- const goals = await this.loadGoals();
372
- if (goals.length === 0) {
373
- return { success: true, output: "No goals found.", elapsed_ms: Date.now() - start };
374
- }
375
- return {
376
- success: true,
377
- output: `Goals:\n${goals.map((goal) => this.formatGoalLine(goal)).join("\n")}`,
378
- elapsed_ms: Date.now() - start,
379
- };
380
- }
381
- async readTasksFromDir(tasksDir) {
382
- let entries = [];
383
- try {
384
- entries = await fsp.readdir(tasksDir);
385
- }
386
- catch {
387
- return [];
388
- }
389
- const tasks = [];
390
- for (const entry of entries) {
391
- if (!entry.endsWith(".json") || entry === "task-history.json" || entry === "last-failure-context.json")
392
- continue;
393
- let raw;
394
- try {
395
- raw = JSON.parse(await fsp.readFile(path.join(tasksDir, entry), "utf-8"));
396
- }
397
- catch {
398
- continue;
399
- }
400
- const parsed = TaskSchema.safeParse(raw);
401
- if (parsed.success)
402
- tasks.push(parsed.data);
403
- }
404
- return tasks.sort((a, b) => (a.created_at < b.created_at ? 1 : -1));
405
- }
406
- async readTasksForGoal(goalId) {
407
- const stateManager = this.deps.stateManager;
408
- if (typeof stateManager.getBaseDir !== "function")
409
- return [];
410
- const baseDir = stateManager.getBaseDir();
411
- const activeTasksDir = this.resolveStatePath(baseDir, "tasks", goalId);
412
- const archiveTasksDir = this.resolveStatePath(baseDir, "archive", goalId, "tasks");
413
- if (activeTasksDir === null || archiveTasksDir === null)
414
- return [];
415
- const activeTasks = await this.readTasksFromDir(activeTasksDir);
416
- if (activeTasks.length > 0)
417
- return activeTasks;
418
- return this.readTasksFromDir(archiveTasksDir);
419
- }
420
- async resolveGoalForTasks(selector) {
421
- if (selector)
422
- return { goalId: selector };
423
- const active = this.activeGoals(await this.loadGoals());
424
- if (active.length === 1)
425
- return { goalId: active[0].id };
426
- if (active.length === 0)
427
- return { error: "No active goals found. Use /tasks <goal-id>." };
428
- return { error: "Multiple active goals found. Use /tasks <goal-id>." };
429
- }
430
- formatTaskLine(task) {
431
- const verdict = task.verification_verdict ? `, verdict ${task.verification_verdict}` : "";
432
- return `${task.id} - ${task.status}${verdict}: ${task.work_description}`;
433
- }
434
- async handleTasks(args, start) {
435
- const resolved = await this.resolveGoalForTasks(args);
436
- if (resolved.error || !resolved.goalId) {
437
- return { success: false, output: resolved.error ?? "Usage: /tasks <goal-id>", elapsed_ms: Date.now() - start };
438
- }
439
- const tasks = await this.readTasksForGoal(resolved.goalId);
440
- if (tasks.length === 0) {
441
- return { success: true, output: `No tasks found for goal "${resolved.goalId}".`, elapsed_ms: Date.now() - start };
442
- }
443
- return {
444
- success: true,
445
- output: `Tasks for goal ${resolved.goalId}:\n${tasks.map((task) => this.formatTaskLine(task)).join("\n")}`,
446
- elapsed_ms: Date.now() - start,
447
- };
448
- }
449
- parseTaskArgs(args) {
450
- const parts = args.split(/\s+/).filter(Boolean);
451
- const goalFlagIndex = parts.indexOf("--goal");
452
- if (goalFlagIndex >= 0) {
453
- const goalId = parts[goalFlagIndex + 1];
454
- parts.splice(goalFlagIndex, goalId ? 2 : 1);
455
- return { taskId: parts[0], goalId };
456
- }
457
- return { taskId: parts[0], goalId: parts[1] };
458
- }
459
- async findTask(taskId, goalId) {
460
- const goalIds = goalId ? [goalId] : await this.listAllGoalIds();
461
- const matches = [];
462
- for (const candidateGoalId of goalIds) {
463
- let raw = null;
464
- try {
465
- raw = await this.deps.stateManager.readRaw(`tasks/${candidateGoalId}/${taskId}.json`);
466
- }
467
- catch {
468
- raw = null;
469
- }
470
- if (!raw) {
471
- const tasks = await this.readTasksForGoal(candidateGoalId);
472
- const matched = tasks.find((task) => task.id === taskId || task.id.startsWith(taskId));
473
- if (matched)
474
- matches.push({ goalId: candidateGoalId, task: matched });
475
- continue;
476
- }
477
- const parsed = TaskSchema.safeParse(raw);
478
- if (parsed.success)
479
- matches.push({ goalId: candidateGoalId, task: parsed.data });
480
- }
481
- return { task: matches.length === 1 ? matches[0].task : undefined, matches };
482
- }
483
- formatTask(task) {
484
- const lines = [
485
- `Task: ${task.id}`,
486
- `Goal: ${task.goal_id}`,
487
- `Status: ${task.status}`,
488
- `Category: ${task.task_category}`,
489
- `Created: ${task.created_at}`,
490
- `Work: ${task.work_description}`,
491
- `Approach: ${task.approach}`,
492
- ];
493
- if (task.started_at)
494
- lines.push(`Started: ${task.started_at}`);
495
- if (task.completed_at)
496
- lines.push(`Completed: ${task.completed_at}`);
497
- if (task.verification_verdict)
498
- lines.push(`Verification: ${task.verification_verdict}`);
499
- if (task.verification_evidence?.length)
500
- lines.push(`Evidence: ${task.verification_evidence.join("; ")}`);
501
- if (task.success_criteria.length > 0) {
502
- lines.push("Success criteria:");
503
- lines.push(...task.success_criteria.map((criterion) => `- ${criterion.description}`));
504
- }
505
- return lines.join("\n");
506
- }
507
- async handleTask(args, start) {
508
- const { taskId, goalId } = this.parseTaskArgs(args);
509
- if (!taskId) {
510
- return { success: false, output: "Usage: /task <task-id> [goal-id]", elapsed_ms: Date.now() - start };
511
- }
512
- const found = await this.findTask(taskId, goalId);
513
- if (found.matches.length > 1) {
514
- return {
515
- success: false,
516
- output: `Task selector "${taskId}" matched multiple goals. Use /task ${taskId} <goal-id>.\n${found.matches.map((match) => `- ${match.goalId}`).join("\n")}`,
517
- elapsed_ms: Date.now() - start,
518
- };
519
- }
520
- if (!found.task) {
521
- const suffix = goalId ? ` for goal "${goalId}"` : "";
522
- return { success: false, output: `Task not found: ${taskId}${suffix}`, elapsed_ms: Date.now() - start };
523
- }
524
- return { success: true, output: this.formatTask(found.task), elapsed_ms: Date.now() - start };
525
- }
526
- providerConfigBaseDir() {
527
- const stateManager = this.deps.stateManager;
528
- return typeof stateManager.getBaseDir === "function" ? stateManager.getBaseDir() : getPulseedDirPath();
529
- }
530
- async readProviderConfigSummary() {
531
- const config = await loadProviderConfig({
532
- baseDir: this.providerConfigBaseDir(),
533
- saveMigration: false,
534
- });
535
- return {
536
- provider: config.provider,
537
- model: config.model,
538
- adapter: config.adapter,
539
- light_model: config.light_model,
540
- base_url: config.base_url,
541
- codex_cli_path: config.codex_cli_path,
542
- has_api_key: Boolean(config.api_key),
543
- };
544
- }
545
- formatConfig(config) {
546
- return Object.entries(config)
547
- .filter(([, value]) => value !== undefined)
548
- .map(([key, value]) => `${key}: ${typeof value === "string" && /key|token|secret/i.test(key) ? "[masked]" : String(value)}`)
549
- .join("\n");
550
- }
551
- async handleConfig(start) {
552
- const config = await this.readProviderConfigSummary();
553
- return { success: true, output: `Provider configuration:\n${this.formatConfig(config)}`, elapsed_ms: Date.now() - start };
554
- }
555
- async handleModel(start) {
556
- const config = await this.readProviderConfigSummary();
557
- return {
558
- success: true,
559
- output: `Model: ${config.model}\nProvider: ${config.provider}\nAdapter: ${config.adapter}`,
560
- elapsed_ms: Date.now() - start,
561
- };
562
- }
563
- async handlePlugins(start) {
564
- if (!this.deps.pluginLoader) {
565
- return { success: true, output: "Plugin information is not available in this chat session.", elapsed_ms: Date.now() - start };
566
- }
567
- try {
568
- const plugins = await this.deps.pluginLoader.loadAll();
569
- if (plugins.length === 0) {
570
- return { success: true, output: "No plugins found.", elapsed_ms: Date.now() - start };
571
- }
572
- return {
573
- success: true,
574
- output: `Plugins:\n${plugins.map((plugin) => `${plugin.name} - ${plugin.type ?? "unknown"} - ${plugin.enabled === false ? "disabled" : "enabled"}`).join("\n")}`,
575
- elapsed_ms: Date.now() - start,
576
- };
577
- }
578
- catch (err) {
579
- const message = err instanceof Error ? err.message : String(err);
580
- return { success: true, output: `Plugin information is unavailable: ${message}`, elapsed_ms: Date.now() - start };
581
- }
582
- }
583
- zeroUsageCounter() {
584
- return { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
585
- }
586
- normalizeUsageCounter(usage) {
587
- const inputTokens = Number.isFinite(usage.inputTokens) ? Math.max(0, Math.floor(usage.inputTokens)) : 0;
588
- const outputTokens = Number.isFinite(usage.outputTokens) ? Math.max(0, Math.floor(usage.outputTokens)) : 0;
589
- const totalTokens = Number.isFinite(usage.totalTokens)
590
- ? Math.max(0, Math.floor(usage.totalTokens))
591
- : inputTokens + outputTokens;
592
- return { inputTokens, outputTokens, totalTokens };
593
- }
594
- usageFromLLMResponse(response) {
595
- const inputTokens = response.usage?.input_tokens ?? 0;
596
- const outputTokens = response.usage?.output_tokens ?? 0;
597
- return {
598
- inputTokens,
599
- outputTokens,
600
- totalTokens: inputTokens + outputTokens,
601
- };
602
- }
603
- addUsageCounter(target, delta) {
604
- const normalizedDelta = this.normalizeUsageCounter(delta);
605
- target.inputTokens += normalizedDelta.inputTokens;
606
- target.outputTokens += normalizedDelta.outputTokens;
607
- target.totalTokens += normalizedDelta.totalTokens;
608
- }
609
- hasUsage(usage) {
610
- return usage.totalTokens > 0 || usage.inputTokens > 0 || usage.outputTokens > 0;
611
- }
612
- formatUsageCounter(prefix, usage) {
613
- return [
614
- `${prefix} input tokens: ${usage.inputTokens}`,
615
- `${prefix} output tokens: ${usage.outputTokens}`,
616
- `${prefix} total tokens: ${usage.totalTokens}`,
617
- ];
618
- }
619
- parseUsagePeriodMs(period) {
620
- const match = /^(\d+)([dhw])$/i.exec(period.trim());
621
- if (!match) {
622
- throw new Error("period must be one of 24h, 7d, 2w");
623
- }
624
- const value = Number(match[1]);
625
- const unit = match[2]?.toLowerCase();
626
- if (!Number.isFinite(value) || value <= 0) {
627
- throw new Error("period value must be positive");
628
- }
629
- if (unit === "h")
630
- return value * 60 * 60 * 1000;
631
- if (unit === "w")
632
- return value * 7 * 24 * 60 * 60 * 1000;
633
- return value * 24 * 60 * 60 * 1000;
634
- }
635
- async collectGoalUsage(goalId) {
636
- const baseDir = this.deps.stateManager.getBaseDir();
637
- const ledgerDir = path.join(baseDir, "tasks", goalId, "ledger");
638
- let entries = [];
639
- try {
640
- entries = await fsp.readdir(ledgerDir);
641
- }
642
- catch (err) {
643
- if (err.code !== "ENOENT")
644
- throw err;
645
- return { goalId, totalTokens: 0, taskCount: 0, terminalTaskCount: 0 };
646
- }
647
- let totalTokens = 0;
648
- let taskCount = 0;
649
- let terminalTaskCount = 0;
650
- for (const entry of entries) {
651
- if (!entry.endsWith(".json"))
652
- continue;
653
- taskCount += 1;
654
- try {
655
- const raw = await fsp.readFile(path.join(ledgerDir, entry), "utf-8");
656
- const parsed = JSON.parse(raw);
657
- if (typeof parsed.summary?.tokens_used === "number") {
658
- totalTokens += parsed.summary.tokens_used;
659
- }
660
- if (parsed.summary?.latest_event_type === "succeeded"
661
- || parsed.summary?.latest_event_type === "failed"
662
- || parsed.summary?.latest_event_type === "abandoned") {
663
- terminalTaskCount += 1;
664
- }
665
- }
666
- catch {
667
- // Ignore malformed records.
668
- }
669
- }
670
- return { goalId, totalTokens, taskCount, terminalTaskCount };
671
- }
672
- async collectScheduleUsage(period) {
673
- const periodMs = this.parseUsagePeriodMs(period);
674
- const since = Date.now() - periodMs;
675
- const historyPath = path.join(this.deps.stateManager.getBaseDir(), "schedule-history.json");
676
- let raw;
677
- try {
678
- raw = JSON.parse(await fsp.readFile(historyPath, "utf-8"));
679
- }
680
- catch (err) {
681
- if (err.code === "ENOENT") {
682
- return { period, runs: 0, totalTokens: 0 };
683
- }
684
- throw err;
685
- }
686
- if (!Array.isArray(raw)) {
687
- return { period, runs: 0, totalTokens: 0 };
688
- }
689
- let runs = 0;
690
- let totalTokens = 0;
691
- for (const record of raw) {
692
- if (!record || typeof record !== "object")
693
- continue;
694
- const finishedAt = record["finished_at"];
695
- const firedAt = typeof finishedAt === "string" ? Date.parse(finishedAt) : Number.NaN;
696
- if (!Number.isFinite(firedAt) || firedAt < since)
697
- continue;
698
- runs += 1;
699
- const tokensUsed = record["tokens_used"];
700
- if (typeof tokensUsed === "number" && Number.isFinite(tokensUsed)) {
701
- totalTokens += tokensUsed;
702
- }
703
- }
704
- return { period, runs, totalTokens };
705
- }
706
- async handleUsage(args, start) {
707
- const tokens = args.trim().split(/\s+/).filter(Boolean);
708
- const scope = tokens[0]?.toLowerCase();
709
- if (!scope || scope === "session") {
710
- if (!this.history) {
711
- return { success: false, output: "No active chat session. Start a session and run work before /usage.", elapsed_ms: Date.now() - start };
712
- }
713
- const session = this.history.getSessionData();
714
- const totals = this.normalizeUsageCounter(session.usage?.totals ?? this.zeroUsageCounter());
715
- const lines = [
716
- `Usage summary (session ${session.id})`,
717
- ...this.formatUsageCounter("Session", totals),
718
- ];
719
- const phaseEntries = Object.entries(session.usage?.byPhase ?? {})
720
- .map(([phase, usage]) => ({ phase, usage: this.normalizeUsageCounter(usage) }))
721
- .filter((entry) => this.hasUsage(entry.usage))
722
- .sort((left, right) => right.usage.totalTokens - left.usage.totalTokens);
723
- if (phaseEntries.length > 0) {
724
- lines.push("");
725
- lines.push("By phase:");
726
- for (const entry of phaseEntries) {
727
- lines.push(`- ${entry.phase}: ${entry.usage.totalTokens} (in=${entry.usage.inputTokens}, out=${entry.usage.outputTokens})`);
728
- }
729
- }
730
- return { success: true, output: lines.join("\n"), elapsed_ms: Date.now() - start };
731
- }
732
- if (scope === "goal" || scope === "daemon") {
733
- const goalId = tokens[1] ?? this.deps.goalId;
734
- if (!goalId) {
735
- return { success: false, output: "Usage: /usage goal <goal-id>", elapsed_ms: Date.now() - start };
736
- }
737
- const summary = await this.collectGoalUsage(goalId);
738
- const lines = [
739
- `Usage summary (${scope} scope)`,
740
- `Goal: ${summary.goalId}`,
741
- `Tasks observed: ${summary.taskCount}`,
742
- `Terminal tasks: ${summary.terminalTaskCount}`,
743
- `Total tokens: ${summary.totalTokens}`,
744
- ];
745
- return { success: true, output: lines.join("\n"), elapsed_ms: Date.now() - start };
746
- }
747
- if (scope === "schedule") {
748
- const period = tokens[1] ?? "7d";
749
- try {
750
- const summary = await this.collectScheduleUsage(period);
751
- const lines = [
752
- `Usage summary (schedule, ${summary.period})`,
753
- `Runs: ${summary.runs}`,
754
- `Total tokens: ${summary.totalTokens}`,
755
- ];
756
- return { success: true, output: lines.join("\n"), elapsed_ms: Date.now() - start };
757
- }
758
- catch (err) {
759
- const message = err instanceof Error ? err.message : String(err);
760
- return { success: false, output: `Usage: /usage schedule [24h|7d|2w]\nError: ${message}`, elapsed_ms: Date.now() - start };
761
- }
762
- }
763
- return {
764
- success: false,
765
- output: "Usage: /usage [session|goal <goal-id>|daemon <goal-id>|schedule [24h|7d|2w]]",
766
- elapsed_ms: Date.now() - start,
767
- };
768
- }
769
- deterministicChatSummary(messages) {
770
- const lines = messages.map((message) => `${message.role}: ${message.content.replace(/\s+/g, " ").trim()}`);
771
- return lines.join("\n").slice(0, 4_000);
772
- }
773
- async summarizeChatForCompaction(messages, existingSummary) {
774
- const content = [
775
- existingSummary ? `Previous summary:\n${existingSummary}` : "",
776
- `Messages to summarize:\n${messages.map((message) => `${message.role}: ${message.content}`).join("\n")}`,
777
- ].filter(Boolean).join("\n\n");
778
- if (this.deps.llmClient) {
779
- try {
780
- const response = await this.deps.llmClient.sendMessage([
781
- { role: "user", content: `Summarize this chat history for later continuation. Preserve decisions, open tasks, constraints, and user preferences. Keep it concise.\n\n${content}` },
782
- ], { max_tokens: 700, model_tier: "light" });
783
- if (response.content.trim())
784
- return { summary: response.content.trim(), usedLlm: true };
785
- }
786
- catch {
787
- // Fall back to deterministic summary below.
788
- }
789
- }
790
- const fallback = [
791
- existingSummary ? `Previous summary:\n${existingSummary}` : "",
792
- "Extractive summary:",
793
- this.deterministicChatSummary(messages),
794
- ].filter(Boolean).join("\n\n");
795
- return { summary: fallback, usedLlm: false };
796
- }
797
- async handleCompact(start) {
798
- if (!this.history) {
799
- return { success: false, output: "No active chat session to compact.", elapsed_ms: Date.now() - start };
800
- }
801
- const session = this.history.getSessionData();
802
- if (session.messages.length <= 4) {
803
- return { success: true, output: "Chat history is already compact. No messages were removed.", elapsed_ms: Date.now() - start };
804
- }
805
- const olderMessages = session.messages.slice(0, -4);
806
- const { summary, usedLlm } = await this.summarizeChatForCompaction(olderMessages, session.compactionSummary);
807
- const { before, after } = await this.history.compact(summary, 4);
808
- const method = usedLlm ? "LLM summary" : "deterministic summary";
809
- return {
810
- success: true,
811
- output: `Compacted chat history with ${method}. Persisted ${before} message(s) down to ${after}; the latest user/assistant turns were kept.`,
812
- elapsed_ms: Date.now() - start,
813
- };
814
- }
815
- async handleCommand(input) {
816
- const trimmed = input.trim();
817
- if (!trimmed.startsWith("/"))
818
- return null;
819
- const cmd = trimmed.toLowerCase().split(/\s+/)[0];
820
- const start = Date.now();
821
- if (cmd === "/help") {
822
- return { success: true, output: COMMAND_HELP, elapsed_ms: Date.now() - start };
823
- }
824
- if (cmd === "/clear") {
825
- await this.history?.clear();
826
- return { success: true, output: "Conversation history cleared.", elapsed_ms: Date.now() - start };
827
- }
828
- if (cmd === "/sessions") {
829
- const catalog = new ChatSessionCatalog(this.deps.stateManager);
830
- const sessions = await catalog.listSessions();
831
- return { success: true, output: this.formatSessionsList(sessions), elapsed_ms: Date.now() - start };
832
- }
833
- if (cmd === "/history") {
834
- const catalog = new ChatSessionCatalog(this.deps.stateManager);
835
- const selector = trimmed.slice("/history".length).trim();
836
- const session = selector
837
- ? await catalog.loadSessionBySelector(selector)
838
- : this.history
839
- ? await catalog.loadSession(this.history.getSessionId())
840
- : null;
841
- if (!session) {
842
- return { success: false, output: "No chat session history found.", elapsed_ms: Date.now() - start };
843
- }
844
- return { success: true, output: this.formatHistory(session), elapsed_ms: Date.now() - start };
845
- }
846
- if (cmd === "/title") {
847
- const title = trimmed.slice("/title".length).trim();
848
- if (!title) {
849
- return { success: false, output: "Usage: /title <title>", elapsed_ms: Date.now() - start };
850
- }
851
- if (!this.history) {
852
- return { success: false, output: "No active chat session to rename.", elapsed_ms: Date.now() - start };
853
- }
854
- const catalog = new ChatSessionCatalog(this.deps.stateManager);
855
- this.history.setTitle(title);
856
- await this.history.persist();
857
- await catalog.renameSession(this.history.getSessionId(), title);
858
- return { success: true, output: `Renamed chat session to "${title}".`, elapsed_ms: Date.now() - start };
859
- }
860
- if (cmd === "/cleanup") {
861
- const catalog = new ChatSessionCatalog(this.deps.stateManager);
862
- const dryRun = trimmed.includes("--dry-run");
863
- const report = await catalog.cleanupSessions({
864
- dryRun,
865
- activeSessionId: this.history?.getSessionId(),
866
- });
867
- const verb = dryRun ? "would remove" : "removed";
868
- return {
869
- success: true,
870
- output: `Chat session cleanup ${verb} ${report.removedSessionIds.length} session(s).`,
871
- elapsed_ms: Date.now() - start,
872
- };
873
- }
874
- if (cmd === "/compact") {
875
- return this.handleCompact(start);
876
- }
877
- if (cmd === "/status") {
878
- return this.handleStatus(trimmed.slice("/status".length).trim(), start);
879
- }
880
- if (cmd === "/goals") {
881
- return this.handleGoals(start);
882
- }
883
- if (cmd === "/tasks") {
884
- return this.handleTasks(trimmed.slice("/tasks".length).trim(), start);
885
- }
886
- if (cmd === "/task") {
887
- return this.handleTask(trimmed.slice("/task".length).trim(), start);
888
- }
889
- if (cmd === "/config") {
890
- return this.handleConfig(start);
891
- }
892
- if (cmd === "/model") {
893
- return this.handleModel(start);
894
- }
895
- if (cmd === "/permissions") {
896
- return this.handlePermissions(trimmed.slice("/permissions".length).trim(), start);
897
- }
898
- if (cmd === "/plugins") {
899
- return this.handlePlugins(start);
900
- }
901
- if (cmd === "/usage") {
902
- return this.handleUsage(trimmed.slice("/usage".length).trim(), start);
903
- }
904
- if (cmd === "/review") {
905
- return this.handleReview(start);
906
- }
907
- if (cmd === "/fork") {
908
- return this.handleFork(trimmed.slice("/fork".length).trim(), start);
909
- }
910
- if (cmd === "/undo") {
911
- return this.handleUndo(start);
912
- }
913
- if (cmd === "/exit") {
914
- return { success: true, output: "Exiting chat mode.", elapsed_ms: Date.now() - start };
915
- }
916
- if (cmd === "/track") {
917
- return this.handleTrack(start);
918
- }
919
- if (cmd === "/tend") {
920
- const args = trimmed.slice("/tend".length).trim();
921
- return this.handleTend(args, start);
922
- }
923
- // Check if this is a confirmation response for a pending /tend
924
- if (this.pendingTend !== null) {
925
- return this.handleTendConfirmation(trimmed, start);
926
- }
927
- return {
928
- success: false,
929
- output: `Unknown command: ${input.trim()}. Type /help for available commands.`,
930
- elapsed_ms: Date.now() - start,
931
- };
932
- }
933
- async handleTrack(start) {
934
- if (!this.deps.escalationHandler) {
935
- return {
936
- success: false,
937
- output: "Escalation not available — missing LLM configuration",
938
- elapsed_ms: Date.now() - start,
939
- };
940
- }
941
- if (!this.history || this.history.getMessages().length === 0) {
942
- return {
943
- success: false,
944
- output: "No conversation to escalate. Chat first, then /track.",
945
- elapsed_ms: Date.now() - start,
946
- };
947
- }
948
- try {
949
- const result = await this.deps.escalationHandler.escalateToGoal(this.history);
950
- return {
951
- success: true,
952
- output: `Goal created: ${result.title} (ID: ${result.goalId})\nRun: pulseed run --goal ${result.goalId} --yes`,
953
- elapsed_ms: Date.now() - start,
954
- };
955
- }
956
- catch (err) {
957
- const message = err instanceof Error ? err.message : String(err);
958
- return {
959
- success: false,
960
- output: `Escalation failed: ${message}`,
961
- elapsed_ms: Date.now() - start,
962
- };
963
- }
964
- }
965
- async handlePermissions(args, start) {
966
- const policy = await this.getSessionExecutionPolicy();
967
- if (!args) {
968
- return {
969
- success: true,
970
- output: summarizeExecutionPolicy(policy),
971
- elapsed_ms: Date.now() - start,
972
- };
973
- }
974
- const tokens = args.toLowerCase().split(/\s+/).filter(Boolean);
975
- let nextPolicy = policy;
976
- for (let index = 0; index < tokens.length; index++) {
977
- const token = tokens[index];
978
- if (token === "read-only" || token === "readonly" || token === "read_only") {
979
- nextPolicy = withExecutionPolicyOverrides(nextPolicy, { sandboxMode: "read_only" });
980
- continue;
981
- }
982
- if (token === "workspace-write" || token === "workspace_write") {
983
- nextPolicy = withExecutionPolicyOverrides(nextPolicy, { sandboxMode: "workspace_write" });
984
- continue;
985
- }
986
- if (token === "full-access" || token === "danger-full-access" || token === "danger_full_access") {
987
- nextPolicy = withExecutionPolicyOverrides(nextPolicy, { sandboxMode: "danger_full_access" });
988
- continue;
989
- }
990
- if (token === "network" && tokens[index + 1]) {
991
- nextPolicy = withExecutionPolicyOverrides(nextPolicy, { networkAccess: tokens[index + 1] === "on" });
992
- index += 1;
993
- continue;
994
- }
995
- if (token === "approval" && tokens[index + 1]) {
996
- const approvalPolicy = tokens[index + 1];
997
- if (approvalPolicy === "never" || approvalPolicy === "on_request" || approvalPolicy === "untrusted") {
998
- nextPolicy = withExecutionPolicyOverrides(nextPolicy, { approvalPolicy });
999
- index += 1;
1000
- continue;
1001
- }
1002
- }
1003
- return {
1004
- success: false,
1005
- output: "Usage: /permissions [read-only|workspace-write|full-access] [network on|off] [approval on_request|never|untrusted]",
1006
- elapsed_ms: Date.now() - start,
1007
- };
1008
- }
1009
- this.sessionExecutionPolicy = nextPolicy;
1010
- return {
1011
- success: true,
1012
- output: summarizeExecutionPolicy(nextPolicy),
1013
- elapsed_ms: Date.now() - start,
1014
- };
1015
- }
1016
- async handleReview(start) {
1017
- const cwd = this.sessionCwd ?? process.cwd();
1018
- const diffStat = await checkGitChanges(cwd);
1019
- const reviewPolicy = withExecutionPolicyOverrides(await this.getSessionExecutionPolicy(), {
1020
- sandboxMode: "read_only",
1021
- approvalPolicy: "never",
1022
- });
1023
- if (this.deps.reviewAgentLoopRunner) {
1024
- const review = await this.deps.reviewAgentLoopRunner.execute({
1025
- cwd,
1026
- diffStat,
1027
- executionPolicy: reviewPolicy,
1028
- });
1029
- return { success: review.success, output: review.output, elapsed_ms: Date.now() - start };
1030
- }
1031
- const output = [
1032
- "Review summary",
1033
- diffStat ? diffStat : "No uncommitted changes detected.",
1034
- "",
1035
- "Execution policy",
1036
- summarizeExecutionPolicy(reviewPolicy),
1037
- ].join("\n");
1038
- return { success: true, output, elapsed_ms: Date.now() - start };
1039
- }
1040
- async handleFork(title, start) {
1041
- const cwd = this.sessionCwd ?? process.cwd();
1042
- const sessionId = crypto.randomUUID();
1043
- const baseSession = this.history?.getSessionData() ?? {
1044
- id: sessionId,
1045
- cwd,
1046
- createdAt: new Date().toISOString(),
1047
- updatedAt: new Date().toISOString(),
1048
- messages: [],
1049
- };
1050
- const now = new Date().toISOString();
1051
- const forkedSession = {
1052
- ...baseSession,
1053
- id: sessionId,
1054
- createdAt: now,
1055
- updatedAt: now,
1056
- title: title || (baseSession.title ? `${baseSession.title} (fork)` : "Forked session"),
1057
- };
1058
- this.history = ChatHistory.fromSession(this.deps.stateManager, forkedSession);
1059
- this.sessionCwd = cwd;
1060
- this.sessionActive = true;
1061
- this.nativeAgentLoopStatePath = `chat/agentloop/${sessionId}.state.json`;
1062
- this.history.setAgentLoopStatePath(this.nativeAgentLoopStatePath);
1063
- await this.history.persist();
1064
- return {
1065
- success: true,
1066
- output: `Forked chat session as ${sessionId}.`,
1067
- elapsed_ms: Date.now() - start,
1068
- };
1069
- }
1070
- async handleUndo(start) {
1071
- if (!this.history) {
1072
- return { success: false, output: "No active chat session to undo.", elapsed_ms: Date.now() - start };
1073
- }
1074
- const removed = await this.history.removeLastTurn();
1075
- if (removed === 0) {
1076
- return { success: false, output: "No chat turn to undo.", elapsed_ms: Date.now() - start };
1077
- }
1078
- return {
1079
- success: true,
1080
- output: `Removed ${removed} message(s) from chat history. File changes were not reverted.`,
1081
- elapsed_ms: Date.now() - start,
1082
- };
1083
- }
1084
- async handleTend(args, start) {
1085
- if (!this.deps.llmClient) {
1086
- return {
1087
- success: false,
1088
- output: "Tend not available — missing LLM configuration",
1089
- elapsed_ms: Date.now() - start,
1090
- };
1091
- }
1092
- if (!this.deps.goalNegotiator) {
1093
- return {
1094
- success: false,
1095
- output: "Tend not available — missing goal negotiator",
1096
- elapsed_ms: Date.now() - start,
1097
- };
1098
- }
1099
- if (!this.deps.daemonClient) {
1100
- return {
1101
- success: false,
1102
- output: "Tend not available — daemon client not configured. Start the daemon with 'pulseed daemon start' first.",
1103
- elapsed_ms: Date.now() - start,
1104
- };
1105
- }
1106
- const history = this.history?.getMessages() ?? [];
1107
- const tendDeps = {
1108
- llmClient: this.deps.llmClient,
1109
- goalNegotiator: this.deps.goalNegotiator,
1110
- daemonClient: this.deps.daemonClient,
1111
- stateManager: this.deps.stateManager,
1112
- chatHistory: history,
1113
- };
1114
- const tendCommand = new TendCommand();
1115
- const result = await tendCommand.execute(args, tendDeps);
1116
- if (result.needsConfirmation && result.goalId) {
1117
- this.pendingTend = { goalId: result.goalId, maxIterations: result.maxIterations };
1118
- return {
1119
- success: true,
1120
- output: result.confirmation ?? result.message,
1121
- elapsed_ms: Date.now() - start,
1122
- };
1123
- }
1124
- return {
1125
- success: result.success,
1126
- output: result.message,
1127
- elapsed_ms: Date.now() - start,
1128
- };
1129
- }
1130
- async handleTendConfirmation(input, start) {
1131
- const pending = this.pendingTend;
1132
- this.pendingTend = null;
1133
- const normalized = input.trim().toLowerCase();
1134
- const confirmed = normalized === "" || normalized === "y" || normalized === "yes";
1135
- if (!confirmed) {
1136
- // Bug 2: treat any non-y/yes/empty/n/no input as cancellation too
1137
- return {
1138
- success: true,
1139
- output: "Tend cancelled. Continue chatting to refine your goal, then try /tend again.",
1140
- elapsed_ms: Date.now() - start,
1141
- };
1142
- }
1143
- if (!this.deps.daemonClient) {
1144
- return {
1145
- success: false,
1146
- output: "Daemon client not available.",
1147
- elapsed_ms: Date.now() - start,
1148
- };
1149
- }
1150
- const { goalId, maxIterations } = pending;
1151
- let subscriber = null;
1152
- if (this.deps.daemonBaseUrl && !this.activeSubscribers.has(goalId)) {
1153
- subscriber = new EventSubscriber(this.deps.daemonBaseUrl, goalId, "normal");
1154
- this.activeSubscribers.set(goalId, subscriber);
1155
- subscriber.on("notification", (notification) => {
1156
- const n = notification;
1157
- this.deps.onNotification?.(n.message);
1158
- this.onNotification?.(n.message);
1159
- });
1160
- subscriber.on("chat_event", (event) => {
1161
- this.emitEvent(event);
1162
- });
1163
- try {
1164
- await subscriber.subscribeReady();
1165
- }
1166
- catch (err) {
1167
- subscriber.unsubscribe();
1168
- this.activeSubscribers.delete(goalId);
1169
- const msg = err instanceof Error ? err.message : String(err);
1170
- return {
1171
- success: false,
1172
- output: `Daemon event stream unavailable: ${msg}. Goal was not started.`,
1173
- elapsed_ms: Date.now() - start,
1174
- };
1175
- }
1176
- }
1177
- try {
1178
- await this.deps.daemonClient.startGoal(goalId);
1179
- }
1180
- catch (err) {
1181
- if (subscriber) {
1182
- subscriber.unsubscribe();
1183
- this.activeSubscribers.delete(goalId);
1184
- }
1185
- const msg = err instanceof Error ? err.message : String(err);
1186
- return {
1187
- success: false,
1188
- output: `Daemon unavailable: ${msg}. Start the daemon with 'pulseed daemon start' first.`,
1189
- elapsed_ms: Date.now() - start,
1190
- };
1191
- }
1192
- const iterNote = maxIterations !== undefined ? ` (max ${maxIterations} iterations)` : "";
1193
- const shortId = goalId.length > 12 ? goalId.slice(0, 12) : goalId;
1194
- return {
1195
- success: true,
1196
- output: `[tend] ${shortId}: Started — daemon is now tending your goal${iterNote}.\nRun 'pulseed status' to check progress.`,
1197
- elapsed_ms: Date.now() - start,
1198
- };
1199
- }
1200
- /**
1201
- * Execute a single chat turn.
1202
- *
1203
- * Flow:
1204
- * 1. Intercept slash commands before adapter dispatch
1205
- * 2. Resolve git root → create ChatHistory
1206
- * 3. Build chat context and assemble prompt
1207
- * 4. Persist user message BEFORE calling adapter (crash-safe)
1208
- * 5. Execute via adapter
1209
- * 6. Verify changes (git diff + tests); retry up to MAX_VERIFY_RETRIES if tests fail
1210
- * 7. Persist assistant response only after the final assistant text is complete
1211
- */
1212
193
  async execute(input, cwd, timeoutMs = DEFAULT_TIMEOUT_MS, options = {}) {
1213
- const eventContext = this.createEventContext();
1214
- const resumeCommand = this.parseResumeCommand(input);
194
+ const eventContext = this.eventBridge.createEventContext();
195
+ const resolvedCwd = resolveGitRoot(cwd);
196
+ const activeTurn = this.eventBridge.beginActiveTurn(eventContext, resolvedCwd);
197
+ const resumeCommand = this.commandHandler.parseResumeCommand(input);
1215
198
  const resumeOnly = resumeCommand !== null;
1216
199
  const runtimeControlContext = options.runtimeControlContext ?? this.runtimeControlContext;
1217
200
  const executionGoalId = options.goalId ?? this.deps.goalId;
1218
- // Intercept commands before any adapter call
1219
- const commandResult = resumeOnly ? null : await this.handleCommand(input);
201
+ const commandResult = resumeOnly ? null : await this.commandHandler.handleCommand(input, resolvedCwd);
1220
202
  if (commandResult !== null) {
1221
- if (commandResult.output) {
1222
- this.emitEvent({
1223
- type: "assistant_final",
1224
- text: commandResult.output,
1225
- persisted: false,
1226
- ...this.eventBase(eventContext),
1227
- });
1228
- }
1229
- this.emitLifecycleEndEvent(commandResult.success ? "completed" : "error", commandResult.elapsed_ms, eventContext, false);
1230
- return commandResult;
203
+ return this.finalizeNonPersistentResult(commandResult, eventContext);
1231
204
  }
1232
- // Intercept plain Y/n responses (and any other input) when a /tend confirmation is pending
1233
205
  if (this.pendingTend !== null && !resumeOnly) {
1234
- const confirmationResult = await this.handleTendConfirmation(input.trim(), Date.now());
1235
- if (confirmationResult.output) {
1236
- this.emitEvent({
1237
- type: "assistant_final",
1238
- text: confirmationResult.output,
1239
- persisted: false,
1240
- ...this.eventBase(eventContext),
1241
- });
1242
- }
1243
- this.emitLifecycleEndEvent(confirmationResult.success ? "completed" : "error", confirmationResult.elapsed_ms, eventContext, false);
1244
- return confirmationResult;
206
+ const confirmationResult = await this.commandHandler.handleTendConfirmation(input.trim(), Date.now());
207
+ return this.finalizeNonPersistentResult(confirmationResult, eventContext);
1245
208
  }
1246
209
  if (resumeOnly && resumeCommand.selector) {
1247
210
  try {
211
+ const selectorResolution = await resolveChatResumeSelector(resumeCommand.selector, this.deps);
212
+ if (selectorResolution.nonResumableMessage) {
213
+ return this.finalizeNonPersistentResult({
214
+ success: false,
215
+ output: selectorResolution.nonResumableMessage,
216
+ elapsed_ms: 0,
217
+ }, eventContext);
218
+ }
1248
219
  const catalog = new ChatSessionCatalog(this.deps.stateManager);
1249
- const session = await catalog.loadSessionBySelector(resumeCommand.selector);
220
+ const session = await catalog.loadSessionBySelector(selectorResolution.chatSelector);
1250
221
  if (!session) {
1251
- const elapsed_ms = 0;
1252
- const output = `No chat session matched selector "${resumeCommand.selector}".`;
1253
- this.emitEvent({
1254
- type: "assistant_final",
1255
- text: output,
1256
- persisted: false,
1257
- ...this.eventBase(eventContext),
1258
- });
1259
- this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
1260
- return { success: false, output, elapsed_ms };
222
+ return this.finalizeNonPersistentResult({
223
+ success: false,
224
+ output: `No chat session matched selector "${selectorResolution.chatSelector}".`,
225
+ elapsed_ms: 0,
226
+ }, eventContext);
1261
227
  }
1262
228
  this.startSessionFromLoadedSession(session);
1263
229
  }
1264
230
  catch (err) {
1265
- const elapsed_ms = 0;
1266
231
  const output = err instanceof ChatSessionSelectorError ? err.message : `Failed to load chat session: ${err instanceof Error ? err.message : String(err)}`;
1267
- this.emitEvent({
1268
- type: "assistant_final",
1269
- text: output,
1270
- persisted: false,
1271
- ...this.eventBase(eventContext),
1272
- });
1273
- this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
1274
- return { success: false, output, elapsed_ms };
232
+ return this.finalizeNonPersistentResult({ success: false, output, elapsed_ms: 0 }, eventContext);
1275
233
  }
1276
234
  }
1277
- // Reuse session (interactive mode) or create a fresh one per call (1-shot mode)
1278
235
  if (!this.sessionActive) {
1279
- const gitRoot = resolveGitRoot(cwd);
1280
236
  const sessionId = crypto.randomUUID();
1281
- this.history = new ChatHistory(this.deps.stateManager, sessionId, gitRoot);
237
+ this.history = new ChatHistory(this.deps.stateManager, sessionId, resolvedCwd);
1282
238
  this.nativeAgentLoopStatePath = `chat/agentloop/${sessionId}.state.json`;
1283
- this.history.setAgentLoopStatePath(this.nativeAgentLoopStatePath);
239
+ this.history.resetAgentLoopState(this.nativeAgentLoopStatePath);
1284
240
  }
1285
- const executionCwd = this.sessionCwd ?? cwd;
1286
- const gitRoot = this.sessionCwd ?? resolveGitRoot(cwd);
1287
- // history is always assigned by this point (either by startSession or the block above)
241
+ const executionCwd = this.sessionCwd ?? resolvedCwd;
242
+ const gitRoot = this.sessionCwd ?? resolvedCwd;
243
+ activeTurn.cwd = gitRoot;
1288
244
  const history = this.history;
1289
- this.emitEvent({
245
+ const pinnedReplyTarget = normalizePinnedReplyTarget(runtimeControlContext?.replyTarget ?? this.deps.runtimeReplyTarget ?? null);
246
+ if (pinnedReplyTarget) {
247
+ history.setNotificationReplyTarget(pinnedReplyTarget);
248
+ }
249
+ this.eventBridge.emitEvent({
1290
250
  type: "lifecycle_start",
1291
251
  input,
1292
- ...this.eventBase(eventContext),
252
+ ...this.eventBridge.eventBase(eventContext),
1293
253
  });
1294
- // Persist-before-execute: user message written to disk before model or adapter execution.
1295
254
  if (!resumeOnly) {
1296
255
  await history.appendUserMessage(input);
1297
256
  }
1298
- // Build static grounding once per session; dynamic context is rebuilt each turn.
1299
257
  if (this.cachedStaticSystemPrompt === null) {
1300
258
  try {
1301
259
  this.cachedStaticSystemPrompt = buildStaticSystemPrompt(this.providerConfigBaseDir());
@@ -1304,11 +262,9 @@ export class ChatRunner {
1304
262
  this.cachedStaticSystemPrompt = "";
1305
263
  }
1306
264
  }
1307
- // Build conversation history from prior turns (last 10), including any manual compaction summary.
1308
265
  const messages = history.getMessages();
1309
266
  const compactionSummary = history.getSessionData().compactionSummary;
1310
267
  const priorTurns = resumeOnly ? messages.slice(-10) : messages.slice(0, -1).slice(-10);
1311
- let historyBlock = "";
1312
268
  const historySections = [];
1313
269
  if (compactionSummary) {
1314
270
  historySections.push(`Compacted previous conversation summary:\n${compactionSummary}`);
@@ -1317,28 +273,26 @@ export class ChatRunner {
1317
273
  const lines = priorTurns.map((m) => `${m.role === "user" ? "User" : "Assistant"}: ${m.content}`).join("\n");
1318
274
  historySections.push(`Previous conversation:\n${lines}`);
1319
275
  }
1320
- if (historySections.length > 0) {
1321
- historyBlock = `${historySections.join("\n\n")}\n\nCurrent message:\n`;
1322
- }
276
+ const historyBlock = historySections.length > 0 ? `${historySections.join("\n\n")}\n\nCurrent message:\n` : "";
1323
277
  const selectedRoute = resumeOnly
1324
278
  ? null
1325
279
  : (options.selectedRoute ?? this.resolveRouteFromInput(input, runtimeControlContext));
1326
- const directPrompt = historyBlock ? `${historyBlock}${input}` : input;
280
+ this.lastSelectedRoute = selectedRoute;
281
+ this.eventBridge.emitIntent(input, selectedRoute, eventContext);
1327
282
  const start = Date.now();
1328
283
  const assistantBuffer = { text: "" };
1329
- const turnUsage = this.zeroUsageCounter();
1330
284
  const identityResponse = resumeOnly ? null : resolveSelfIdentityResponse(input, this.providerConfigBaseDir());
1331
285
  if (identityResponse !== null) {
1332
286
  const elapsed_ms = Date.now() - start;
1333
287
  await history.appendAssistantMessage(identityResponse);
1334
- this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
1335
- this.emitEvent({
288
+ this.eventBridge.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
289
+ this.eventBridge.emitEvent({
1336
290
  type: "assistant_final",
1337
291
  text: identityResponse,
1338
292
  persisted: true,
1339
- ...this.eventBase(eventContext),
293
+ ...this.eventBridge.eventBase(eventContext),
1340
294
  });
1341
- this.emitLifecycleEndEvent("completed", elapsed_ms, eventContext, true);
295
+ this.eventBridge.emitLifecycleEndEvent("completed", elapsed_ms, eventContext, true);
1342
296
  return {
1343
297
  success: true,
1344
298
  output: identityResponse,
@@ -1346,78 +300,26 @@ export class ChatRunner {
1346
300
  };
1347
301
  }
1348
302
  if (selectedRoute?.kind === "runtime_control") {
1349
- const runtimeControlResult = await this.executeRuntimeControlRoute(selectedRoute, runtimeControlContext, executionCwd, start);
303
+ this.eventBridge.emitCheckpoint("Runtime control selected", `${selectedRoute.intent.kind} request recognized.`, eventContext, "route");
304
+ const runtimeControlResult = await executeRuntimeControlRoute(this.routeHost(), selectedRoute, runtimeControlContext, executionCwd, start);
1350
305
  if (runtimeControlResult.success) {
1351
306
  await history.appendAssistantMessage(runtimeControlResult.output);
1352
- this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
1353
- this.emitEvent({
307
+ this.eventBridge.emitCheckpoint("Runtime control completed", "The runtime-control operation produced a result.", eventContext, "complete");
308
+ this.eventBridge.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
309
+ this.eventBridge.emitEvent({
1354
310
  type: "assistant_final",
1355
311
  text: runtimeControlResult.output,
1356
312
  persisted: true,
1357
- ...this.eventBase(eventContext),
313
+ ...this.eventBridge.eventBase(eventContext),
1358
314
  });
1359
- this.emitLifecycleEndEvent("completed", runtimeControlResult.elapsed_ms, eventContext, true);
315
+ this.eventBridge.emitLifecycleEndEvent("completed", runtimeControlResult.elapsed_ms, eventContext, true);
1360
316
  }
1361
317
  else {
1362
- this.emitLifecycleErrorEvent(runtimeControlResult.output, assistantBuffer.text, eventContext);
1363
- this.emitLifecycleEndEvent("error", runtimeControlResult.elapsed_ms, eventContext, false);
318
+ runtimeControlResult.output = this.eventBridge.emitLifecycleErrorEvent(runtimeControlResult.output, assistantBuffer.text, eventContext);
319
+ this.eventBridge.emitLifecycleEndEvent("error", runtimeControlResult.elapsed_ms, eventContext, false);
1364
320
  }
1365
321
  return runtimeControlResult;
1366
322
  }
1367
- if (selectedRoute?.kind === "direct_answer") {
1368
- try {
1369
- this.emitActivity("lifecycle", "Calling model...", eventContext, "lifecycle:model");
1370
- const directResponse = await this.sendLLMMessage(this.deps.llmClient, [{ role: "user", content: directPrompt }], {
1371
- ...(this.cachedStaticSystemPrompt ? { system: this.cachedStaticSystemPrompt } : {}),
1372
- model_tier: selectedRoute.modelTier,
1373
- max_tokens: selectedRoute.maxTokens,
1374
- }, assistantBuffer, eventContext);
1375
- this.addUsageCounter(turnUsage, this.usageFromLLMResponse(directResponse));
1376
- const elapsed_ms = Date.now() - start;
1377
- const output = assistantBuffer.text || directResponse.content || "(no response)";
1378
- if (this.hasUsage(turnUsage)) {
1379
- history.recordUsage("execution", turnUsage);
1380
- }
1381
- await history.appendAssistantMessage(output);
1382
- this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
1383
- this.emitEvent({
1384
- type: "assistant_final",
1385
- text: output,
1386
- persisted: true,
1387
- ...this.eventBase(eventContext),
1388
- });
1389
- this.emitLifecycleEndEvent("completed", elapsed_ms, eventContext, true);
1390
- return {
1391
- success: true,
1392
- output,
1393
- elapsed_ms,
1394
- diagnostics: {
1395
- route: "direct",
1396
- reason: selectedRoute.reason,
1397
- modelTier: selectedRoute.modelTier,
1398
- maxTokens: selectedRoute.maxTokens,
1399
- },
1400
- };
1401
- }
1402
- catch (err) {
1403
- const message = err instanceof Error ? err.message : String(err);
1404
- this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
1405
- this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
1406
- return {
1407
- success: false,
1408
- output: assistantBuffer.text
1409
- ? `${assistantBuffer.text}\n\n[interrupted: ${message}]`
1410
- : `Error: ${message}`,
1411
- elapsed_ms: Date.now() - start,
1412
- diagnostics: {
1413
- route: "direct",
1414
- reason: selectedRoute.reason,
1415
- modelTier: selectedRoute.modelTier,
1416
- maxTokens: selectedRoute.maxTokens,
1417
- },
1418
- };
1419
- }
1420
- }
1421
323
  const usesNativeAgentLoop = resumeOnly || selectedRoute?.kind === "agent_loop";
1422
324
  const groundingWorkspaceContext = !resumeOnly && usesNativeAgentLoop
1423
325
  ? await buildChatContext(input, executionCwd)
@@ -1425,7 +327,7 @@ export class ChatRunner {
1425
327
  let systemPrompt = this.cachedStaticSystemPrompt ?? "";
1426
328
  if (!resumeOnly) {
1427
329
  try {
1428
- this.emitActivity("lifecycle", "Preparing context...", eventContext, "lifecycle:context");
330
+ this.eventBridge.emitActivity("lifecycle", "Preparing context...", eventContext, "lifecycle:context");
1429
331
  if (usesNativeAgentLoop) {
1430
332
  systemPrompt = await buildChatAgentLoopSystemPrompt({
1431
333
  stateManager: this.deps.stateManager,
@@ -1453,6 +355,9 @@ export class ChatRunner {
1453
355
  catch {
1454
356
  systemPrompt = this.cachedStaticSystemPrompt ?? "";
1455
357
  }
358
+ this.eventBridge.emitCheckpoint("Context gathered", usesNativeAgentLoop
359
+ ? "Workspace and agent-loop grounding are ready."
360
+ : "Workspace grounding is ready.", eventContext, "context");
1456
361
  }
1457
362
  const agentLoopSystemPrompt = [
1458
363
  systemPrompt,
@@ -1466,745 +371,108 @@ export class ChatRunner {
1466
371
  const prompt = historyBlock ? `${historyBlock}${basePrompt}` : basePrompt;
1467
372
  if (resumeOnly && !this.deps.chatAgentLoopRunner) {
1468
373
  const elapsed_ms = Date.now() - start;
1469
- const output = "Resume requires the native chat agentloop runtime.";
1470
- this.emitEvent({
1471
- type: "assistant_final",
1472
- text: output,
1473
- persisted: false,
1474
- ...this.eventBase(eventContext),
1475
- });
1476
- this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
1477
- return {
1478
- success: false,
1479
- output,
1480
- elapsed_ms,
1481
- };
374
+ const output = this.eventBridge.emitLifecycleErrorEvent("Resume requires the native chat agentloop runtime.", assistantBuffer.text, eventContext);
375
+ this.eventBridge.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
376
+ return { success: false, output, elapsed_ms };
1482
377
  }
1483
- const chatAgentLoopRunner = this.deps.chatAgentLoopRunner;
1484
378
  if (resumeOnly || selectedRoute?.kind === "agent_loop") {
1485
- try {
1486
- const resumeState = resumeOnly ? await this.loadResumableAgentLoopState() : null;
1487
- if (resumeOnly && !resumeState) {
1488
- const elapsed_ms = Date.now() - start;
1489
- const output = "No resumable native agentloop state found.";
1490
- this.emitEvent({
1491
- type: "assistant_final",
1492
- text: output,
1493
- persisted: false,
1494
- ...this.eventBase(eventContext),
1495
- });
1496
- this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
1497
- return {
1498
- success: false,
1499
- output,
1500
- elapsed_ms,
1501
- };
1502
- }
1503
- this.emitActivity("lifecycle", "Calling model...", eventContext, "lifecycle:model");
1504
- const result = await chatAgentLoopRunner.execute({
1505
- message: basePrompt,
1506
- cwd: executionCwd,
1507
- goalId: executionGoalId,
1508
- history: priorTurns.map((m) => ({
1509
- role: m.role === "assistant" ? "assistant" : "user",
1510
- content: m.content,
1511
- })),
1512
- eventSink: this.createAgentLoopEventSink(eventContext),
1513
- approvalFn: async (request) => {
1514
- if (this.deps.approvalFn) {
1515
- return this.deps.approvalFn(request.reason);
1516
- }
1517
- return false;
1518
- },
1519
- toolCallContext: {
1520
- executionPolicy: await this.getSessionExecutionPolicy(),
1521
- },
1522
- ...(this.nativeAgentLoopStatePath ? { resumeStatePath: this.nativeAgentLoopStatePath } : {}),
1523
- ...(resumeState ? { resumeState } : {}),
1524
- ...(resumeOnly ? { resumeOnly: true } : {}),
1525
- ...(agentLoopSystemPrompt ? { systemPrompt: agentLoopSystemPrompt } : {}),
1526
- });
1527
- const elapsed_ms = Date.now() - start;
1528
- const agentLoopUsage = result.agentLoop?.usage
1529
- ? this.normalizeUsageCounter(result.agentLoop.usage)
1530
- : this.zeroUsageCounter();
1531
- if (this.hasUsage(agentLoopUsage)) {
1532
- history.recordUsage("agentloop", agentLoopUsage);
1533
- }
1534
- if (result.output) {
1535
- this.pushAssistantDelta(result.output, assistantBuffer, eventContext);
1536
- }
1537
- if (result.success) {
1538
- await history.appendAssistantMessage(result.output);
1539
- this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
1540
- this.emitEvent({
1541
- type: "assistant_final",
1542
- text: result.output,
1543
- persisted: true,
1544
- ...this.eventBase(eventContext),
1545
- });
1546
- this.emitLifecycleEndEvent("completed", elapsed_ms, eventContext, true);
1547
- }
1548
- else {
1549
- this.emitLifecycleErrorEvent(result.output || result.error || "Unknown error", assistantBuffer.text, eventContext);
1550
- this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
1551
- }
1552
- return {
1553
- success: result.success,
1554
- output: result.output,
1555
- elapsed_ms,
1556
- };
1557
- }
1558
- catch (err) {
1559
- const message = err instanceof Error ? err.message : String(err);
1560
- this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
1561
- this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
1562
- return {
1563
- success: false,
1564
- output: assistantBuffer.text
1565
- ? `${assistantBuffer.text}\n\n[interrupted: ${message}]`
1566
- : `Error: ${message}`,
1567
- elapsed_ms: Date.now() - start,
1568
- };
1569
- }
379
+ return executeAgentLoopRoute(this.routeHost(), {
380
+ resumeOnly,
381
+ executionCwd,
382
+ executionGoalId,
383
+ basePrompt,
384
+ priorTurns,
385
+ agentLoopSystemPrompt,
386
+ assistantBuffer,
387
+ eventContext,
388
+ history,
389
+ gitRoot,
390
+ activeAbortSignal: activeTurn.abortController.signal,
391
+ start,
392
+ });
1570
393
  }
1571
- // Prefer the local LLM/tool loop over the external adapter fallback whenever a client is available.
1572
394
  if (selectedRoute?.kind === "tool_loop") {
1573
- try {
1574
- const toolResult = await this.executeWithTools(prompt, eventContext, assistantBuffer, systemPrompt || undefined, executionGoalId);
1575
- const elapsed_ms = Date.now() - start;
1576
- if (this.hasUsage(toolResult.usage)) {
1577
- history.recordUsage("execution", toolResult.usage);
1578
- }
1579
- await history.appendAssistantMessage(toolResult.output);
1580
- this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
1581
- this.emitEvent({
1582
- type: "assistant_final",
1583
- text: toolResult.output,
1584
- persisted: true,
1585
- ...this.eventBase(eventContext),
1586
- });
1587
- this.emitLifecycleEndEvent("completed", elapsed_ms, eventContext, true);
1588
- return { success: true, output: toolResult.output, elapsed_ms };
1589
- }
1590
- catch (err) {
1591
- const message = err instanceof Error ? err.message : String(err);
1592
- this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
1593
- this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
1594
- return {
1595
- success: false,
1596
- output: assistantBuffer.text
1597
- ? `${assistantBuffer.text}\n\n[interrupted: ${message}]`
1598
- : `Error: ${message}`,
1599
- elapsed_ms: Date.now() - start,
1600
- };
1601
- }
395
+ return executeToolLoopRoute(this.routeHost(), {
396
+ prompt,
397
+ eventContext,
398
+ assistantBuffer,
399
+ systemPrompt: systemPrompt || undefined,
400
+ executionGoalId,
401
+ history,
402
+ gitRoot,
403
+ start,
404
+ });
1602
405
  }
1603
406
  if (!resumeOnly && selectedRoute && selectedRoute.kind !== "adapter") {
1604
407
  const elapsed_ms = Date.now() - start;
1605
- const output = `Unsupported chat route: ${selectedRoute.kind}`;
1606
- this.emitLifecycleErrorEvent(output, assistantBuffer.text, eventContext);
1607
- this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
1608
- return {
1609
- success: false,
1610
- output,
1611
- elapsed_ms,
1612
- };
408
+ const output = this.eventBridge.emitLifecycleErrorEvent(`Unsupported chat route: ${selectedRoute.kind}`, assistantBuffer.text, eventContext);
409
+ this.eventBridge.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
410
+ return { success: false, output, elapsed_ms };
1613
411
  }
1614
- const task = {
412
+ return executeAdapterRoute(this.routeHost(), {
1615
413
  prompt,
1616
- timeout_ms: timeoutMs,
1617
- adapter_type: this.deps.adapter.adapterType,
1618
414
  cwd,
1619
- ...(systemPrompt ? { system_prompt: systemPrompt } : {}),
1620
- };
1621
- const resolvedTimeoutMs = task.timeout_ms ?? DEFAULT_TIMEOUT_MS;
1622
- this.emitActivity("lifecycle", "Calling adapter...", eventContext, "lifecycle:adapter");
1623
- const adapterPromise = this.deps.adapter.execute(task);
1624
- const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error(`Chat adapter timed out after ${resolvedTimeoutMs}ms`)), resolvedTimeoutMs));
1625
- let result = await Promise.race([adapterPromise, timeoutPromise]);
1626
- // Surface adapter errors into output when output is empty
1627
- if (!result.output && result.error) {
1628
- result = { ...result, output: `Error: ${result.error}` };
1629
- }
1630
- const elapsed_ms = Date.now() - start;
1631
- if (result.output) {
1632
- this.pushAssistantDelta(result.output, assistantBuffer, eventContext);
1633
- }
1634
- // Verification loop: check if git has uncommitted changes; if so, run tests
1635
- const gitChanges = await checkGitChanges(gitRoot);
1636
- if (gitChanges !== null && gitChanges !== "") {
1637
- let retries = 0;
1638
- const VERIFY_TIMEOUT_MS = 30_000;
1639
- this.emitActivity("lifecycle", "Checking result...", eventContext, "lifecycle:checking");
1640
- let verification = await Promise.race([
1641
- verifyChatAction(gitRoot, this.deps.toolExecutor),
1642
- new Promise((resolve) => setTimeout(() => resolve({ passed: true }), VERIFY_TIMEOUT_MS)),
1643
- ]);
1644
- while (!verification.passed && retries < MAX_VERIFY_RETRIES) {
1645
- retries++;
1646
- const retryPrompt = `The previous changes caused test failures. Please fix them.\n\nTest output:\n${verification.testOutput ?? verification.errors.join("\n")}`;
1647
- const retryTask = { ...task, prompt: retryPrompt };
1648
- result = await this.deps.adapter.execute(retryTask);
1649
- verification = await verifyChatAction(gitRoot, this.deps.toolExecutor);
1650
- }
1651
- if (!verification.passed) {
1652
- this.emitLifecycleErrorEvent(`Changes applied but tests are still failing after ${MAX_VERIFY_RETRIES} retries.`, assistantBuffer.text, eventContext);
1653
- this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
1654
- return {
1655
- success: false,
1656
- output: `${assistantBuffer.text}\n\n[interrupted: tests are still failing after ${MAX_VERIFY_RETRIES} retries]\n\nTest output:\n${verification.testOutput ?? verification.errors.join("\n")}`.trim(),
1657
- elapsed_ms: Date.now() - start,
1658
- };
1659
- }
1660
- }
1661
- if (result.success) {
1662
- await history.appendAssistantMessage(result.output);
1663
- this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
1664
- this.emitEvent({
1665
- type: "assistant_final",
1666
- text: result.output,
1667
- persisted: true,
1668
- ...this.eventBase(eventContext),
1669
- });
1670
- this.emitLifecycleEndEvent("completed", elapsed_ms, eventContext, true);
1671
- }
1672
- else {
1673
- const partialText = assistantBuffer.text !== result.output ? assistantBuffer.text : "";
1674
- this.emitLifecycleErrorEvent(result.output || result.error || "Unknown error", partialText, eventContext);
1675
- this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
1676
- }
1677
- return {
1678
- success: result.success,
1679
- output: result.output,
1680
- elapsed_ms,
1681
- };
1682
- }
1683
- async executeRuntimeControlRoute(route, runtimeControlContext, cwd, start) {
1684
- if (!this.deps.runtimeControlService) {
1685
- return {
1686
- success: false,
1687
- output: "Runtime control is not available in this chat surface yet.",
1688
- elapsed_ms: Date.now() - start,
1689
- };
1690
- }
1691
- const replyTarget = runtimeControlContext?.replyTarget ?? this.deps.runtimeReplyTarget;
1692
- const actor = runtimeControlContext?.actor ?? this.deps.runtimeControlActor;
1693
- const result = await this.deps.runtimeControlService.request({
1694
- intent: route.intent,
1695
- cwd,
1696
- requestedBy: actor ?? {
1697
- surface: replyTarget?.surface ?? "chat",
1698
- platform: replyTarget?.platform,
1699
- conversation_id: replyTarget?.conversation_id,
1700
- identity_key: replyTarget?.identity_key,
1701
- user_id: replyTarget?.user_id,
1702
- },
1703
- replyTarget: replyTarget ?? { surface: "chat" },
1704
- approvalFn: runtimeControlContext?.approvalFn
1705
- ?? this.deps.runtimeControlApprovalFn
1706
- ?? this.deps.approvalFn,
415
+ timeoutMs,
416
+ systemPrompt: systemPrompt || undefined,
417
+ eventContext,
418
+ assistantBuffer,
419
+ gitRoot,
420
+ start,
421
+ history,
1707
422
  });
1708
- return {
1709
- success: result.success,
1710
- output: result.message,
1711
- elapsed_ms: Date.now() - start,
1712
- };
1713
423
  }
1714
- /**
1715
- * Execute a chat turn using llmClient with self-knowledge tools (function calling).
1716
- * Loops up to MAX_TOOL_LOOPS times to resolve tool calls, then returns final text.
1717
- */
1718
- async executeWithTools(prompt, eventContext, assistantBuffer, systemPrompt, goalId) {
1719
- const llmClient = this.deps.llmClient;
1720
- const messages = [{ role: "user", content: prompt }];
1721
- const toolCallContext = await this.buildToolCallContext(goalId);
1722
- const usage = this.zeroUsageCounter();
1723
- for (let loop = 0; loop < MAX_TOOL_LOOPS; loop++) {
1724
- // Recompute tools each iteration so newly activated deferred tools are included
1725
- const tools = this.deps.registry
1726
- ? toToolDefinitionsFiltered(this.deps.registry.listAll(), { activatedTools: this.activatedTools })
1727
- : [];
1728
- const supportsNativeToolCalling = llmClient.supportsToolCalling?.() !== false;
1729
- let response;
1730
- try {
1731
- this.emitActivity("lifecycle", "Calling model...", eventContext, "lifecycle:model");
1732
- response = await this.sendLLMMessage(llmClient, messages, {
1733
- ...(supportsNativeToolCalling
1734
- ? { tools, ...(systemPrompt ? { system: systemPrompt } : {}) }
1735
- : { system: buildPromptedToolProtocolSystemPrompt({ systemPrompt, tools }) }),
1736
- }, assistantBuffer, eventContext);
1737
- }
1738
- catch (err) {
1739
- console.error("[chat-runner] executeWithTools error:", err);
1740
- const hint = err instanceof Error ? `: ${err.message}` : "";
1741
- throw new Error(`Sorry, I encountered an error processing your request${hint}.`);
1742
- }
1743
- this.addUsageCounter(usage, this.usageFromLLMResponse(response));
1744
- const toolCalls = response.tool_calls?.length
1745
- ? response.tool_calls
1746
- : supportsNativeToolCalling
1747
- ? []
1748
- : extractPromptedToolCalls({
1749
- content: response.content,
1750
- tools,
1751
- createId: () => `prompted-${loop}-${crypto.randomUUID()}`,
1752
- }).map((call) => ({
1753
- id: call.id,
1754
- type: "function",
1755
- function: {
1756
- name: call.name,
1757
- arguments: JSON.stringify(call.input ?? {}),
1758
- },
1759
- }));
1760
- if (!supportsNativeToolCalling && toolCalls.length > 0) {
1761
- assistantBuffer.text = "";
1762
- }
1763
- // No tool calls — return the text content
1764
- if (toolCalls.length === 0) {
1765
- return {
1766
- output: assistantBuffer.text || response.content || "(no response)",
1767
- usage,
1768
- };
1769
- }
1770
- // Append assistant message, then process tool calls
1771
- messages.push({ role: "assistant", content: response.content || "" });
1772
- for (const tc of toolCalls) {
1773
- let args = {};
1774
- try {
1775
- args = JSON.parse(tc.function.arguments || "{}");
1776
- }
1777
- catch {
1778
- // ignore parse errors, use empty args
1779
- }
1780
- const toolResult = await this.dispatchToolCall(tc.id, tc.function.name, args, toolCallContext, eventContext);
1781
- // When ToolSearch returns results, activate deferred tools for subsequent turns
1782
- if (tc.function.name === "tool_search") {
1783
- this.activateToolSearchResults(toolResult);
1784
- }
1785
- messages.push({ role: "user", content: `Tool result for ${tc.function.name}:\n${toolResult}` });
1786
- }
1787
- }
1788
- // Max loops reached — return last assistant content or fallback
1789
- const lastAssistant = [...messages].reverse().find(m => m.role === "assistant");
1790
- return {
1791
- output: lastAssistant?.content || "I was unable to complete the request within the allowed tool call limit.",
1792
- usage,
1793
- };
1794
- }
1795
- /**
1796
- * Parse ToolSearch result JSON and activate any deferred tools found.
1797
- * Called after each tool_search execution so the LLM can call found tools on the next turn.
1798
- */
1799
- activateToolSearchResults(toolResult) {
1800
- try {
1801
- const parsed = JSON.parse(toolResult);
1802
- const results = Array.isArray(parsed) ? parsed : null;
1803
- if (results) {
1804
- for (const item of results) {
1805
- if (item && typeof item === "object" && typeof item["name"] === "string") {
1806
- this.activatedTools.add(item["name"]);
1807
- }
1808
- }
1809
- }
1810
- }
1811
- catch {
1812
- // Non-JSON result or unexpected shape — ignore
1813
- }
1814
- }
1815
- createAgentLoopEventSink(eventContext) {
1816
- return {
1817
- emit: async (event) => {
1818
- if (event.type === "tool_call_started") {
1819
- const detail = event.inputPreview ? previewActivityText(event.inputPreview) : undefined;
1820
- this.emitActivity("tool", formatToolActivity("Running", event.toolName, detail), eventContext, event.callId);
1821
- this.emitEvent({
1822
- type: "tool_start",
1823
- toolCallId: event.callId,
1824
- toolName: event.toolName,
1825
- args: this.parseAgentLoopPreview(event.inputPreview),
1826
- ...this.eventBase(eventContext),
1827
- });
1828
- this.emitEvent({
1829
- type: "tool_update",
1830
- toolCallId: event.callId,
1831
- toolName: event.toolName,
1832
- status: "running",
1833
- message: "started",
1834
- ...this.eventBase(eventContext),
1835
- });
1836
- return;
1837
- }
1838
- if (event.type === "tool_call_finished") {
1839
- this.emitActivity("tool", formatToolActivity(event.success ? "Finished" : "Failed", event.toolName, event.outputPreview), eventContext, event.callId);
1840
- this.emitEvent({
1841
- type: "tool_end",
1842
- toolCallId: event.callId,
1843
- toolName: event.toolName,
1844
- success: event.success,
1845
- summary: event.outputPreview,
1846
- durationMs: event.durationMs,
1847
- ...this.eventBase(eventContext),
1848
- });
1849
- return;
1850
- }
1851
- if (event.type === "assistant_message" && event.phase === "commentary" && event.contentPreview) {
1852
- this.emitActivity("commentary", previewActivityText(event.contentPreview, 120), eventContext, `commentary:${event.eventId}`);
1853
- return;
1854
- }
1855
- if (event.type === "plan_update") {
1856
- this.emitActivity("tool", `Updated plan: ${previewActivityText(event.summary)}`, eventContext, `plan:${event.turnId}`);
1857
- this.emitEvent({
1858
- type: "tool_update",
1859
- toolCallId: `plan:${event.turnId}:${event.createdAt}`,
1860
- toolName: "update_plan",
1861
- status: "result",
1862
- message: event.summary,
1863
- ...this.eventBase(eventContext),
1864
- });
1865
- return;
1866
- }
1867
- if (event.type === "approval_request") {
1868
- this.emitActivity("tool", formatToolActivity("Running", event.toolName, `awaiting approval: ${event.reason}`), eventContext, event.callId);
1869
- this.emitEvent({
1870
- type: "tool_update",
1871
- toolCallId: event.callId,
1872
- toolName: event.toolName,
1873
- status: "awaiting_approval",
1874
- message: event.reason,
1875
- ...this.eventBase(eventContext),
1876
- });
1877
- return;
1878
- }
1879
- if (event.type === "approval") {
1880
- this.emitActivity("tool", formatToolActivity("Finished", event.toolName, `approval ${event.status}: ${event.reason}`), eventContext);
1881
- this.emitEvent({
1882
- type: "tool_update",
1883
- toolCallId: `approval:${event.turnId}:${event.createdAt}`,
1884
- toolName: event.toolName,
1885
- status: "result",
1886
- message: `approval ${event.status}: ${event.reason}`,
1887
- ...this.eventBase(eventContext),
1888
- });
1889
- return;
1890
- }
1891
- if (event.type === "resumed") {
1892
- this.emitEvent({
1893
- type: "tool_update",
1894
- toolCallId: `resume:${event.turnId}:${event.createdAt}`,
1895
- toolName: "agentloop_resume",
1896
- status: "result",
1897
- message: `resumed ${event.restoredMessages} message(s) from ${event.fromUpdatedAt}`,
1898
- ...this.eventBase(eventContext),
1899
- });
1900
- return;
1901
- }
1902
- if (event.type === "context_compaction") {
1903
- this.emitEvent({
1904
- type: "tool_update",
1905
- toolCallId: `compaction:${event.turnId}:${event.createdAt}`,
1906
- toolName: "context_compaction",
1907
- status: "result",
1908
- message: `${event.phase} ${event.reason}: ${event.inputMessages} -> ${event.outputMessages}`,
1909
- ...this.eventBase(eventContext),
1910
- });
1911
- }
1912
- },
1913
- };
424
+ getSessionCwd() {
425
+ return this.sessionCwd;
1914
426
  }
1915
- parseAgentLoopPreview(preview) {
1916
- try {
1917
- const parsed = JSON.parse(preview);
1918
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
1919
- return parsed;
1920
- }
1921
- }
1922
- catch {
1923
- // fall through
1924
- }
1925
- return preview ? { preview } : {};
427
+ getNativeAgentLoopStatePath() {
428
+ return this.nativeAgentLoopStatePath;
1926
429
  }
1927
- parseResumeCommand(input) {
1928
- const trimmed = input.trim();
1929
- const match = /^\/resume(?:\s+(.+))?$/i.exec(trimmed);
1930
- if (!match)
1931
- return null;
1932
- const selector = match[1]?.trim();
1933
- return selector ? { selector } : {};
430
+ setSessionExecutionPolicy(policy) {
431
+ this.sessionExecutionPolicy = policy;
1934
432
  }
1935
- async loadResumableAgentLoopState() {
1936
- if (!this.nativeAgentLoopStatePath)
1937
- return null;
1938
- const raw = await this.deps.stateManager.readRaw(this.nativeAgentLoopStatePath);
1939
- if (!this.isAgentLoopSessionState(raw))
1940
- return null;
1941
- if (raw.status === "completed")
1942
- return null;
1943
- return {
1944
- ...raw,
1945
- messages: [...raw.messages],
1946
- calledTools: [...raw.calledTools],
1947
- };
433
+ async getSessionExecutionPolicy() {
434
+ const policy = await resolveSessionExecutionPolicy(this.sessionExecutionPolicy, this.sessionCwd);
435
+ this.sessionExecutionPolicy = policy;
436
+ return policy;
1948
437
  }
1949
- isAgentLoopSessionState(value) {
1950
- if (!value || typeof value !== "object")
1951
- return false;
1952
- const candidate = value;
1953
- return typeof candidate["sessionId"] === "string"
1954
- && typeof candidate["traceId"] === "string"
1955
- && typeof candidate["turnId"] === "string"
1956
- && typeof candidate["goalId"] === "string"
1957
- && typeof candidate["cwd"] === "string"
1958
- && typeof candidate["modelRef"] === "string"
1959
- && Array.isArray(candidate["messages"])
1960
- && Array.isArray(candidate["calledTools"])
1961
- && typeof candidate["status"] === "string";
438
+ resolveRouteFromIngress(ingress) {
439
+ return standaloneIngressRouter.selectRoute(ingress, getRouteCapabilities(this.deps));
1962
440
  }
1963
- /** Dispatch a tool call through the registry. */
1964
- async dispatchToolCall(toolCallId, name, args, context, eventContext) {
1965
- if (!this.deps.registry) {
1966
- this.emitActivity("tool", formatToolActivity("Failed", name, "No tool registry configured"), eventContext, toolCallId);
1967
- return JSON.stringify({ error: `No tool registry configured` });
1968
- }
1969
- const tool = this.deps.registry.get(name);
1970
- if (!tool) {
1971
- this.emitActivity("tool", formatToolActivity("Failed", name, `Unknown tool: ${name}`), eventContext, toolCallId);
1972
- return JSON.stringify({ error: `Unknown tool: ${name}` });
1973
- }
1974
- const startTime = Date.now();
1975
- try {
1976
- const parsed = tool.inputSchema.safeParse(args);
1977
- if (!parsed.success) {
1978
- this.emitActivity("tool", formatToolActivity("Failed", name, `Invalid input: ${parsed.error.message}`), eventContext, toolCallId);
1979
- this.emitEvent({
1980
- type: "tool_end",
1981
- toolCallId,
1982
- toolName: name,
1983
- success: false,
1984
- summary: `Invalid input: ${parsed.error.message}`,
1985
- durationMs: Date.now() - startTime,
1986
- ...this.eventBase(eventContext),
1987
- });
1988
- return JSON.stringify({ error: `Invalid input: ${parsed.error.message}` });
1989
- }
1990
- this.emitEvent({
1991
- type: "tool_start",
1992
- toolCallId,
1993
- toolName: name,
1994
- args,
1995
- ...this.eventBase(eventContext),
1996
- });
1997
- this.emitActivity("tool", formatToolActivity("Running", name, JSON.stringify(args)), eventContext, toolCallId);
1998
- let result;
1999
- if (this.deps.toolExecutor) {
2000
- this.emitEvent({
2001
- type: "tool_update",
2002
- toolCallId,
2003
- toolName: name,
2004
- status: "running",
2005
- message: "running",
2006
- ...this.eventBase(eventContext),
2007
- });
2008
- this.deps.onToolStart?.(name, args);
2009
- result = await this.deps.toolExecutor.execute(name, parsed.data, context);
2010
- }
2011
- else {
2012
- // Gate: check permissions before execution
2013
- const permResult = await tool.checkPermissions(parsed.data, context);
2014
- if (permResult.status === "denied") {
2015
- this.emitEvent({
2016
- type: "tool_end",
2017
- toolCallId,
2018
- toolName: name,
2019
- success: false,
2020
- summary: permResult.reason,
2021
- durationMs: Date.now() - startTime,
2022
- ...this.eventBase(eventContext),
2023
- });
2024
- return `Tool ${name} denied: ${permResult.reason}`;
2025
- }
2026
- if (permResult.status === "needs_approval") {
2027
- this.emitActivity("tool", formatToolActivity("Running", name, `awaiting approval: ${permResult.reason}`), eventContext, toolCallId);
2028
- this.emitEvent({
2029
- type: "tool_update",
2030
- toolCallId,
2031
- toolName: name,
2032
- status: "awaiting_approval",
2033
- message: permResult.reason,
2034
- ...this.eventBase(eventContext),
2035
- });
2036
- const approved = await context.approvalFn({
2037
- toolName: name,
2038
- input: parsed.data,
2039
- reason: permResult.reason,
2040
- permissionLevel: tool.metadata.permissionLevel,
2041
- isDestructive: tool.metadata.isDestructive,
2042
- reversibility: "unknown",
2043
- });
2044
- if (!approved) {
2045
- this.emitEvent({
2046
- type: "tool_end",
2047
- toolCallId,
2048
- toolName: name,
2049
- success: false,
2050
- summary: `Not approved: ${permResult.reason}`,
2051
- durationMs: Date.now() - startTime,
2052
- ...this.eventBase(eventContext),
2053
- });
2054
- return `Tool ${name} not approved: ${permResult.reason}`;
2055
- }
2056
- }
2057
- this.emitEvent({
2058
- type: "tool_update",
2059
- toolCallId,
2060
- toolName: name,
2061
- status: "running",
2062
- message: "running",
2063
- ...this.eventBase(eventContext),
2064
- });
2065
- this.deps.onToolStart?.(name, args);
2066
- result = await tool.call(parsed.data, context);
2067
- }
2068
- const durationMs = Date.now() - startTime;
2069
- this.deps.onToolEnd?.(name, { success: result.success, summary: result.summary || '...', durationMs });
2070
- this.emitActivity("tool", formatToolActivity(result.success ? "Finished" : "Failed", name, result.summary || "..."), eventContext, toolCallId);
2071
- this.emitEvent({
2072
- type: "tool_update",
2073
- toolCallId,
2074
- toolName: name,
2075
- status: "result",
2076
- message: result.summary || "...",
2077
- ...this.eventBase(eventContext),
2078
- });
2079
- this.emitEvent({
2080
- type: "tool_end",
2081
- toolCallId,
2082
- toolName: name,
2083
- success: result.success,
2084
- summary: result.summary || "...",
2085
- durationMs,
2086
- ...this.eventBase(eventContext),
2087
- });
2088
- // Prefer structured data (JSON) over plain summary so the LLM gets actionable content
2089
- return result.data != null ? JSON.stringify(result.data) : (result.summary ?? "(no result)");
2090
- }
2091
- catch (err) {
2092
- const message = err instanceof Error ? err.message : String(err);
2093
- const durationMs = Date.now() - startTime;
2094
- this.deps.onToolEnd?.(name, { success: false, summary: message, durationMs });
2095
- this.emitActivity("tool", formatToolActivity("Failed", name, message), eventContext, toolCallId);
2096
- this.emitEvent({
2097
- type: "tool_end",
2098
- toolCallId,
2099
- toolName: name,
2100
- success: false,
2101
- summary: message,
2102
- durationMs,
2103
- ...this.eventBase(eventContext),
2104
- });
2105
- return JSON.stringify({ error: `Tool ${name} failed: ${message}` });
2106
- }
441
+ resolveRouteFromInput(input, runtimeControlContext) {
442
+ return this.resolveRouteFromIngress(buildStandaloneIngressMessageFromContext(input, runtimeControlContext, this.deps));
2107
443
  }
2108
- async sendLLMMessage(llmClient, messages, options, assistantBuffer, eventContext) {
2109
- let streamed = false;
2110
- if (llmClient.sendMessageStream) {
2111
- const response = await llmClient.sendMessageStream(messages, options, {
2112
- onTextDelta: (delta) => {
2113
- streamed = true;
2114
- this.pushAssistantDelta(delta, assistantBuffer, eventContext);
2115
- },
2116
- });
2117
- if (!streamed && response.content) {
2118
- this.pushAssistantDelta(response.content, assistantBuffer, eventContext);
2119
- }
2120
- return response;
2121
- }
2122
- const response = await llmClient.sendMessage(messages, options);
2123
- if (response.content) {
2124
- this.pushAssistantDelta(response.content, assistantBuffer, eventContext);
2125
- }
2126
- return response;
444
+ loadedSessionToChatSession(session) {
445
+ return loadedSessionToChatSession(session);
2127
446
  }
2128
- createEventContext() {
447
+ routeHost() {
2129
448
  return {
2130
- runId: crypto.randomUUID(),
2131
- turnId: crypto.randomUUID(),
449
+ deps: this.deps,
450
+ eventBridge: this.eventBridge,
451
+ activatedTools: this.activatedTools,
452
+ getConversationSessionId: () => this.history?.getSessionId() ?? null,
453
+ getSessionCwd: () => this.sessionCwd,
454
+ getNativeAgentLoopStatePath: () => this.nativeAgentLoopStatePath,
455
+ getSessionExecutionPolicy: () => this.getSessionExecutionPolicy(),
456
+ setSessionExecutionPolicy: (policy) => { this.sessionExecutionPolicy = policy; },
2132
457
  };
2133
458
  }
2134
- eventBase(context) {
2135
- return { ...context, createdAt: new Date().toISOString() };
2136
- }
2137
- emitEvent(event) {
2138
- const handler = this.onEvent ?? this.deps.onEvent;
2139
- handler?.(event);
2140
- }
2141
- emitActivity(kind, message, eventContext, sourceId) {
2142
- if (!message.trim())
2143
- return;
2144
- this.emitEvent({
2145
- type: "activity",
2146
- kind,
2147
- message,
2148
- ...(sourceId ? { sourceId } : {}),
2149
- transient: true,
2150
- ...this.eventBase(eventContext),
2151
- });
2152
- }
2153
- pushAssistantDelta(delta, assistantBuffer, eventContext) {
2154
- if (!delta)
2155
- return;
2156
- assistantBuffer.text += delta;
2157
- this.emitEvent({
2158
- type: "assistant_delta",
2159
- delta,
2160
- text: assistantBuffer.text,
2161
- ...this.eventBase(eventContext),
2162
- });
2163
- }
2164
- emitLifecycleEndEvent(status, elapsedMs, eventContext, persisted) {
2165
- this.emitEvent({
2166
- type: "lifecycle_end",
2167
- status,
2168
- elapsedMs,
2169
- persisted,
2170
- ...this.eventBase(eventContext),
2171
- });
2172
- }
2173
- emitLifecycleErrorEvent(error, partialText, eventContext) {
2174
- this.emitEvent({
2175
- type: "lifecycle_error",
2176
- error,
2177
- partialText,
2178
- persisted: false,
2179
- ...this.eventBase(eventContext),
2180
- });
2181
- }
2182
- /** Build a ToolCallContext from ChatRunnerDeps for tool dispatch. */
2183
- async getSessionExecutionPolicy() {
2184
- if (this.sessionExecutionPolicy)
2185
- return this.sessionExecutionPolicy;
2186
- const config = await loadProviderConfig({ saveMigration: false });
2187
- this.sessionExecutionPolicy = resolveExecutionPolicy({
2188
- workspaceRoot: this.sessionCwd ?? process.cwd(),
2189
- security: config.agent_loop?.security,
2190
- });
2191
- return this.sessionExecutionPolicy;
459
+ providerConfigBaseDir() {
460
+ const stateManager = this.deps.stateManager;
461
+ return typeof stateManager.getBaseDir === "function" ? stateManager.getBaseDir() : getPulseedDirPath();
2192
462
  }
2193
- async buildToolCallContext(goalId = this.deps.goalId) {
2194
- const executionPolicy = await this.getSessionExecutionPolicy();
2195
- return {
2196
- cwd: this.sessionCwd ?? process.cwd(),
2197
- goalId: goalId ?? "",
2198
- trustBalance: 0,
2199
- preApproved: false,
2200
- approvalFn: async (req) => {
2201
- if (this.deps.approvalFn) {
2202
- return this.deps.approvalFn(req.reason);
2203
- }
2204
- return false;
2205
- },
2206
- executionPolicy,
2207
- };
463
+ finalizeNonPersistentResult(result, eventContext) {
464
+ if (result.output) {
465
+ this.eventBridge.emitEvent({
466
+ type: "assistant_final",
467
+ text: result.output,
468
+ persisted: false,
469
+ ...this.eventBridge.eventBase(eventContext),
470
+ });
471
+ }
472
+ this.eventBridge.emitLifecycleEndEvent(result.success ? "completed" : "error", result.elapsed_ms, eventContext, false);
473
+ return result;
2208
474
  }
2209
475
  }
476
+ void COMMAND_HELP;
477
+ void formatRoute;
2210
478
  //# sourceMappingURL=chat-runner.js.map