pulseed 0.5.2 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (395) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/interface/chat/chat-event-state.d.ts +10 -0
  6. package/dist/interface/chat/chat-event-state.d.ts.map +1 -1
  7. package/dist/interface/chat/chat-event-state.js +184 -9
  8. package/dist/interface/chat/chat-event-state.js.map +1 -1
  9. package/dist/interface/chat/chat-events.d.ts +3 -1
  10. package/dist/interface/chat/chat-events.d.ts.map +1 -1
  11. package/dist/interface/chat/chat-runner.d.ts +24 -1
  12. package/dist/interface/chat/chat-runner.d.ts.map +1 -1
  13. package/dist/interface/chat/chat-runner.js +678 -67
  14. package/dist/interface/chat/chat-runner.js.map +1 -1
  15. package/dist/interface/chat/chat-verifier.d.ts +3 -1
  16. package/dist/interface/chat/chat-verifier.d.ts.map +1 -1
  17. package/dist/interface/chat/chat-verifier.js +2 -2
  18. package/dist/interface/chat/chat-verifier.js.map +1 -1
  19. package/dist/interface/chat/cross-platform-session.d.ts +1 -0
  20. package/dist/interface/chat/cross-platform-session.d.ts.map +1 -1
  21. package/dist/interface/chat/cross-platform-session.js +24 -0
  22. package/dist/interface/chat/cross-platform-session.js.map +1 -1
  23. package/dist/interface/chat/failure-recovery.d.ts +11 -0
  24. package/dist/interface/chat/failure-recovery.d.ts.map +1 -0
  25. package/dist/interface/chat/failure-recovery.js +115 -0
  26. package/dist/interface/chat/failure-recovery.js.map +1 -0
  27. package/dist/interface/chat/ingress-router.d.ts +9 -0
  28. package/dist/interface/chat/ingress-router.d.ts.map +1 -1
  29. package/dist/interface/chat/ingress-router.js +35 -1
  30. package/dist/interface/chat/ingress-router.js.map +1 -1
  31. package/dist/interface/chat/tend-command.d.ts +8 -0
  32. package/dist/interface/chat/tend-command.d.ts.map +1 -1
  33. package/dist/interface/chat/tend-command.js +80 -4
  34. package/dist/interface/chat/tend-command.js.map +1 -1
  35. package/dist/interface/cli/cli-command-registry.d.ts.map +1 -1
  36. package/dist/interface/cli/cli-command-registry.js +4 -0
  37. package/dist/interface/cli/cli-command-registry.js.map +1 -1
  38. package/dist/interface/cli/commands/runtime.d.ts +3 -0
  39. package/dist/interface/cli/commands/runtime.d.ts.map +1 -0
  40. package/dist/interface/cli/commands/runtime.js +231 -0
  41. package/dist/interface/cli/commands/runtime.js.map +1 -0
  42. package/dist/interface/cli/utils.d.ts.map +1 -1
  43. package/dist/interface/cli/utils.js +4 -0
  44. package/dist/interface/cli/utils.js.map +1 -1
  45. package/dist/interface/tui/app.d.ts.map +1 -1
  46. package/dist/interface/tui/app.js +22 -1
  47. package/dist/interface/tui/app.js.map +1 -1
  48. package/dist/interface/tui/chat/scroll.d.ts +3 -0
  49. package/dist/interface/tui/chat/scroll.d.ts.map +1 -1
  50. package/dist/interface/tui/chat/scroll.js +15 -0
  51. package/dist/interface/tui/chat/scroll.js.map +1 -1
  52. package/dist/interface/tui/chat/types.d.ts +1 -1
  53. package/dist/interface/tui/chat/types.d.ts.map +1 -1
  54. package/dist/interface/tui/chat/viewport.d.ts.map +1 -1
  55. package/dist/interface/tui/chat/viewport.js +8 -2
  56. package/dist/interface/tui/chat/viewport.js.map +1 -1
  57. package/dist/interface/tui/chat-surface.d.ts +2 -0
  58. package/dist/interface/tui/chat-surface.d.ts.map +1 -1
  59. package/dist/interface/tui/chat-surface.js +11 -0
  60. package/dist/interface/tui/chat-surface.js.map +1 -1
  61. package/dist/interface/tui/chat.d.ts.map +1 -1
  62. package/dist/interface/tui/chat.js +15 -7
  63. package/dist/interface/tui/chat.js.map +1 -1
  64. package/dist/interface/tui/clipboard.d.ts +6 -1
  65. package/dist/interface/tui/clipboard.d.ts.map +1 -1
  66. package/dist/interface/tui/clipboard.js +24 -5
  67. package/dist/interface/tui/clipboard.js.map +1 -1
  68. package/dist/interface/tui/entry.d.ts.map +1 -1
  69. package/dist/interface/tui/entry.js +14 -2
  70. package/dist/interface/tui/entry.js.map +1 -1
  71. package/dist/interface/tui/flicker/MouseTracking.d.ts +1 -1
  72. package/dist/interface/tui/flicker/MouseTracking.d.ts.map +1 -1
  73. package/dist/interface/tui/flicker/MouseTracking.js +8 -4
  74. package/dist/interface/tui/flicker/MouseTracking.js.map +1 -1
  75. package/dist/interface/tui/fullscreen-chat.d.ts +86 -5
  76. package/dist/interface/tui/fullscreen-chat.d.ts.map +1 -1
  77. package/dist/interface/tui/fullscreen-chat.js +586 -32
  78. package/dist/interface/tui/fullscreen-chat.js.map +1 -1
  79. package/dist/interface/tui/help-overlay.d.ts.map +1 -1
  80. package/dist/interface/tui/help-overlay.js +1 -1
  81. package/dist/interface/tui/help-overlay.js.map +1 -1
  82. package/dist/interface/tui/markdown-renderer.d.ts.map +1 -1
  83. package/dist/interface/tui/markdown-renderer.js +40 -12
  84. package/dist/interface/tui/markdown-renderer.js.map +1 -1
  85. package/dist/interface/tui/test-entry.js +1 -1
  86. package/dist/interface/tui/test-entry.js.map +1 -1
  87. package/dist/orchestrator/execution/agent-loop/agent-loop-context-assembler.d.ts.map +1 -1
  88. package/dist/orchestrator/execution/agent-loop/agent-loop-context-assembler.js +1 -0
  89. package/dist/orchestrator/execution/agent-loop/agent-loop-context-assembler.js.map +1 -1
  90. package/dist/orchestrator/execution/agent-loop/agent-loop-default-profile.d.ts.map +1 -1
  91. package/dist/orchestrator/execution/agent-loop/agent-loop-default-profile.js +27 -13
  92. package/dist/orchestrator/execution/agent-loop/agent-loop-default-profile.js.map +1 -1
  93. package/dist/orchestrator/execution/agent-loop/agent-loop-dogfood-benchmark.d.ts.map +1 -1
  94. package/dist/orchestrator/execution/agent-loop/agent-loop-dogfood-benchmark.js +7 -4
  95. package/dist/orchestrator/execution/agent-loop/agent-loop-dogfood-benchmark.js.map +1 -1
  96. package/dist/orchestrator/execution/agent-loop/bounded-agent-loop-runner.d.ts.map +1 -1
  97. package/dist/orchestrator/execution/agent-loop/bounded-agent-loop-runner.js +6 -0
  98. package/dist/orchestrator/execution/agent-loop/bounded-agent-loop-runner.js.map +1 -1
  99. package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.d.ts +1 -0
  100. package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.d.ts.map +1 -1
  101. package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.js +1 -0
  102. package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.js.map +1 -1
  103. package/dist/orchestrator/execution/agent-loop/index.d.ts +1 -0
  104. package/dist/orchestrator/execution/agent-loop/index.d.ts.map +1 -1
  105. package/dist/orchestrator/execution/agent-loop/index.js +1 -0
  106. package/dist/orchestrator/execution/agent-loop/index.js.map +1 -1
  107. package/dist/orchestrator/execution/agent-loop/kaggle-training-benchmark.d.ts +34 -0
  108. package/dist/orchestrator/execution/agent-loop/kaggle-training-benchmark.d.ts.map +1 -0
  109. package/dist/orchestrator/execution/agent-loop/kaggle-training-benchmark.js +54 -0
  110. package/dist/orchestrator/execution/agent-loop/kaggle-training-benchmark.js.map +1 -0
  111. package/dist/orchestrator/loop/core-loop/phase-policy.d.ts.map +1 -1
  112. package/dist/orchestrator/loop/core-loop/phase-policy.js +3 -0
  113. package/dist/orchestrator/loop/core-loop/phase-policy.js.map +1 -1
  114. package/dist/platform/code-search/candidate-normalizer.d.ts +3 -0
  115. package/dist/platform/code-search/candidate-normalizer.d.ts.map +1 -0
  116. package/dist/platform/code-search/candidate-normalizer.js +61 -0
  117. package/dist/platform/code-search/candidate-normalizer.js.map +1 -0
  118. package/dist/platform/code-search/candidate.d.ts +25 -0
  119. package/dist/platform/code-search/candidate.d.ts.map +1 -0
  120. package/dist/platform/code-search/candidate.js +61 -0
  121. package/dist/platform/code-search/candidate.js.map +1 -0
  122. package/dist/platform/code-search/contracts.d.ts +275 -0
  123. package/dist/platform/code-search/contracts.d.ts.map +1 -0
  124. package/dist/platform/code-search/contracts.js +22 -0
  125. package/dist/platform/code-search/contracts.js.map +1 -0
  126. package/dist/platform/code-search/eval/fixtures.d.ts +14 -0
  127. package/dist/platform/code-search/eval/fixtures.d.ts.map +1 -0
  128. package/dist/platform/code-search/eval/fixtures.js +24 -0
  129. package/dist/platform/code-search/eval/fixtures.js.map +1 -0
  130. package/dist/platform/code-search/eval/metrics.d.ts +10 -0
  131. package/dist/platform/code-search/eval/metrics.d.ts.map +1 -0
  132. package/dist/platform/code-search/eval/metrics.js +20 -0
  133. package/dist/platform/code-search/eval/metrics.js.map +1 -0
  134. package/dist/platform/code-search/eval/runner.d.ts +3 -0
  135. package/dist/platform/code-search/eval/runner.d.ts.map +1 -0
  136. package/dist/platform/code-search/eval/runner.js +13 -0
  137. package/dist/platform/code-search/eval/runner.js.map +1 -0
  138. package/dist/platform/code-search/fusion.d.ts +6 -0
  139. package/dist/platform/code-search/fusion.d.ts.map +1 -0
  140. package/dist/platform/code-search/fusion.js +12 -0
  141. package/dist/platform/code-search/fusion.js.map +1 -0
  142. package/dist/platform/code-search/generated-detector.d.ts +15 -0
  143. package/dist/platform/code-search/generated-detector.d.ts.map +1 -0
  144. package/dist/platform/code-search/generated-detector.js +42 -0
  145. package/dist/platform/code-search/generated-detector.js.map +1 -0
  146. package/dist/platform/code-search/indexes/call-graph.d.ts +3 -0
  147. package/dist/platform/code-search/indexes/call-graph.d.ts.map +1 -0
  148. package/dist/platform/code-search/indexes/call-graph.js +13 -0
  149. package/dist/platform/code-search/indexes/call-graph.js.map +1 -0
  150. package/dist/platform/code-search/indexes/config-index.d.ts +3 -0
  151. package/dist/platform/code-search/indexes/config-index.d.ts.map +1 -0
  152. package/dist/platform/code-search/indexes/config-index.js +7 -0
  153. package/dist/platform/code-search/indexes/config-index.js.map +1 -0
  154. package/dist/platform/code-search/indexes/file-index.d.ts +5 -0
  155. package/dist/platform/code-search/indexes/file-index.d.ts.map +1 -0
  156. package/dist/platform/code-search/indexes/file-index.js +106 -0
  157. package/dist/platform/code-search/indexes/file-index.js.map +1 -0
  158. package/dist/platform/code-search/indexes/index-store.d.ts +6 -0
  159. package/dist/platform/code-search/indexes/index-store.d.ts.map +1 -0
  160. package/dist/platform/code-search/indexes/index-store.js +14 -0
  161. package/dist/platform/code-search/indexes/index-store.js.map +1 -0
  162. package/dist/platform/code-search/indexes/indexer.d.ts +3 -0
  163. package/dist/platform/code-search/indexes/indexer.d.ts.map +1 -0
  164. package/dist/platform/code-search/indexes/indexer.js +27 -0
  165. package/dist/platform/code-search/indexes/indexer.js.map +1 -0
  166. package/dist/platform/code-search/indexes/package-graph.d.ts +3 -0
  167. package/dist/platform/code-search/indexes/package-graph.d.ts.map +1 -0
  168. package/dist/platform/code-search/indexes/package-graph.js +26 -0
  169. package/dist/platform/code-search/indexes/package-graph.js.map +1 -0
  170. package/dist/platform/code-search/indexes/repo-map-index.d.ts +3 -0
  171. package/dist/platform/code-search/indexes/repo-map-index.d.ts.map +1 -0
  172. package/dist/platform/code-search/indexes/repo-map-index.js +26 -0
  173. package/dist/platform/code-search/indexes/repo-map-index.js.map +1 -0
  174. package/dist/platform/code-search/indexes/semantic-index.d.ts +3 -0
  175. package/dist/platform/code-search/indexes/semantic-index.d.ts.map +1 -0
  176. package/dist/platform/code-search/indexes/semantic-index.js +4 -0
  177. package/dist/platform/code-search/indexes/semantic-index.js.map +1 -0
  178. package/dist/platform/code-search/indexes/symbol-index.d.ts +3 -0
  179. package/dist/platform/code-search/indexes/symbol-index.d.ts.map +1 -0
  180. package/dist/platform/code-search/indexes/symbol-index.js +84 -0
  181. package/dist/platform/code-search/indexes/symbol-index.js.map +1 -0
  182. package/dist/platform/code-search/indexes/test-index.d.ts +3 -0
  183. package/dist/platform/code-search/indexes/test-index.d.ts.map +1 -0
  184. package/dist/platform/code-search/indexes/test-index.js +22 -0
  185. package/dist/platform/code-search/indexes/test-index.js.map +1 -0
  186. package/dist/platform/code-search/orchestrator.d.ts +9 -0
  187. package/dist/platform/code-search/orchestrator.d.ts.map +1 -0
  188. package/dist/platform/code-search/orchestrator.js +81 -0
  189. package/dist/platform/code-search/orchestrator.js.map +1 -0
  190. package/dist/platform/code-search/path-policy.d.ts +6 -0
  191. package/dist/platform/code-search/path-policy.d.ts.map +1 -0
  192. package/dist/platform/code-search/path-policy.js +60 -0
  193. package/dist/platform/code-search/path-policy.js.map +1 -0
  194. package/dist/platform/code-search/progressive-reader.d.ts +8 -0
  195. package/dist/platform/code-search/progressive-reader.d.ts.map +1 -0
  196. package/dist/platform/code-search/progressive-reader.js +173 -0
  197. package/dist/platform/code-search/progressive-reader.js.map +1 -0
  198. package/dist/platform/code-search/query-planner.d.ts +4 -0
  199. package/dist/platform/code-search/query-planner.d.ts.map +1 -0
  200. package/dist/platform/code-search/query-planner.js +107 -0
  201. package/dist/platform/code-search/query-planner.js.map +1 -0
  202. package/dist/platform/code-search/reranker.d.ts +4 -0
  203. package/dist/platform/code-search/reranker.d.ts.map +1 -0
  204. package/dist/platform/code-search/reranker.js +57 -0
  205. package/dist/platform/code-search/reranker.js.map +1 -0
  206. package/dist/platform/code-search/retrievers/callgraph-retriever.d.ts +6 -0
  207. package/dist/platform/code-search/retrievers/callgraph-retriever.d.ts.map +1 -0
  208. package/dist/platform/code-search/retrievers/callgraph-retriever.js +31 -0
  209. package/dist/platform/code-search/retrievers/callgraph-retriever.js.map +1 -0
  210. package/dist/platform/code-search/retrievers/config-retriever.d.ts +6 -0
  211. package/dist/platform/code-search/retrievers/config-retriever.d.ts.map +1 -0
  212. package/dist/platform/code-search/retrievers/config-retriever.js +23 -0
  213. package/dist/platform/code-search/retrievers/config-retriever.js.map +1 -0
  214. package/dist/platform/code-search/retrievers/lexical-retriever.d.ts +6 -0
  215. package/dist/platform/code-search/retrievers/lexical-retriever.d.ts.map +1 -0
  216. package/dist/platform/code-search/retrievers/lexical-retriever.js +49 -0
  217. package/dist/platform/code-search/retrievers/lexical-retriever.js.map +1 -0
  218. package/dist/platform/code-search/retrievers/package-retriever.d.ts +6 -0
  219. package/dist/platform/code-search/retrievers/package-retriever.d.ts.map +1 -0
  220. package/dist/platform/code-search/retrievers/package-retriever.js +29 -0
  221. package/dist/platform/code-search/retrievers/package-retriever.js.map +1 -0
  222. package/dist/platform/code-search/retrievers/repo-map-retriever.d.ts +6 -0
  223. package/dist/platform/code-search/retrievers/repo-map-retriever.d.ts.map +1 -0
  224. package/dist/platform/code-search/retrievers/repo-map-retriever.js +30 -0
  225. package/dist/platform/code-search/retrievers/repo-map-retriever.js.map +1 -0
  226. package/dist/platform/code-search/retrievers/semantic-retriever.d.ts +6 -0
  227. package/dist/platform/code-search/retrievers/semantic-retriever.d.ts.map +1 -0
  228. package/dist/platform/code-search/retrievers/semantic-retriever.js +18 -0
  229. package/dist/platform/code-search/retrievers/semantic-retriever.js.map +1 -0
  230. package/dist/platform/code-search/retrievers/stacktrace-retriever.d.ts +6 -0
  231. package/dist/platform/code-search/retrievers/stacktrace-retriever.d.ts.map +1 -0
  232. package/dist/platform/code-search/retrievers/stacktrace-retriever.js +30 -0
  233. package/dist/platform/code-search/retrievers/stacktrace-retriever.js.map +1 -0
  234. package/dist/platform/code-search/retrievers/symbol-retriever.d.ts +6 -0
  235. package/dist/platform/code-search/retrievers/symbol-retriever.d.ts.map +1 -0
  236. package/dist/platform/code-search/retrievers/symbol-retriever.js +32 -0
  237. package/dist/platform/code-search/retrievers/symbol-retriever.js.map +1 -0
  238. package/dist/platform/code-search/retrievers/test-retriever.d.ts +6 -0
  239. package/dist/platform/code-search/retrievers/test-retriever.d.ts.map +1 -0
  240. package/dist/platform/code-search/retrievers/test-retriever.js +30 -0
  241. package/dist/platform/code-search/retrievers/test-retriever.js.map +1 -0
  242. package/dist/platform/code-search/session-store.d.ts +11 -0
  243. package/dist/platform/code-search/session-store.d.ts.map +1 -0
  244. package/dist/platform/code-search/session-store.js +41 -0
  245. package/dist/platform/code-search/session-store.js.map +1 -0
  246. package/dist/platform/code-search/trace.d.ts +9 -0
  247. package/dist/platform/code-search/trace.d.ts.map +1 -0
  248. package/dist/platform/code-search/trace.js +25 -0
  249. package/dist/platform/code-search/trace.js.map +1 -0
  250. package/dist/platform/code-search/verification-retrieval.d.ts +3 -0
  251. package/dist/platform/code-search/verification-retrieval.d.ts.map +1 -0
  252. package/dist/platform/code-search/verification-retrieval.js +33 -0
  253. package/dist/platform/code-search/verification-retrieval.js.map +1 -0
  254. package/dist/platform/observation/context-provider.d.ts.map +1 -1
  255. package/dist/platform/observation/context-provider.js +37 -0
  256. package/dist/platform/observation/context-provider.js.map +1 -1
  257. package/dist/platform/observation/workspace-context.d.ts.map +1 -1
  258. package/dist/platform/observation/workspace-context.js +27 -0
  259. package/dist/platform/observation/workspace-context.js.map +1 -1
  260. package/dist/runtime/daemon/client.d.ts +13 -1
  261. package/dist/runtime/daemon/client.d.ts.map +1 -1
  262. package/dist/runtime/daemon/client.js +2 -2
  263. package/dist/runtime/daemon/client.js.map +1 -1
  264. package/dist/runtime/daemon/runner-commands.d.ts +9 -1
  265. package/dist/runtime/daemon/runner-commands.d.ts.map +1 -1
  266. package/dist/runtime/daemon/runner-commands.js +33 -2
  267. package/dist/runtime/daemon/runner-commands.js.map +1 -1
  268. package/dist/runtime/daemon/runner-startup.d.ts.map +1 -1
  269. package/dist/runtime/daemon/runner-startup.js +22 -1
  270. package/dist/runtime/daemon/runner-startup.js.map +1 -1
  271. package/dist/runtime/daemon/runner.d.ts.map +1 -1
  272. package/dist/runtime/daemon/runner.js +3 -2
  273. package/dist/runtime/daemon/runner.js.map +1 -1
  274. package/dist/runtime/daemon/runtime-root.d.ts +5 -0
  275. package/dist/runtime/daemon/runtime-root.d.ts.map +1 -0
  276. package/dist/runtime/daemon/runtime-root.js +60 -0
  277. package/dist/runtime/daemon/runtime-root.js.map +1 -0
  278. package/dist/runtime/event/server-command-handler.d.ts.map +1 -1
  279. package/dist/runtime/event/server-command-handler.js +47 -3
  280. package/dist/runtime/event/server-command-handler.js.map +1 -1
  281. package/dist/runtime/executor/goal-worker.d.ts +1 -0
  282. package/dist/runtime/executor/goal-worker.d.ts.map +1 -1
  283. package/dist/runtime/executor/goal-worker.js +1 -0
  284. package/dist/runtime/executor/goal-worker.js.map +1 -1
  285. package/dist/runtime/executor/loop-supervisor.d.ts +24 -1
  286. package/dist/runtime/executor/loop-supervisor.d.ts.map +1 -1
  287. package/dist/runtime/executor/loop-supervisor.js +191 -12
  288. package/dist/runtime/executor/loop-supervisor.js.map +1 -1
  289. package/dist/runtime/gateway/telegram-gateway-adapter.d.ts.map +1 -1
  290. package/dist/runtime/gateway/telegram-gateway-adapter.js +2 -1
  291. package/dist/runtime/gateway/telegram-gateway-adapter.js.map +1 -1
  292. package/dist/runtime/session-registry/index.d.ts +3 -0
  293. package/dist/runtime/session-registry/index.d.ts.map +1 -0
  294. package/dist/runtime/session-registry/index.js +3 -0
  295. package/dist/runtime/session-registry/index.js.map +1 -0
  296. package/dist/runtime/session-registry/registry.d.ts +39 -0
  297. package/dist/runtime/session-registry/registry.d.ts.map +1 -0
  298. package/dist/runtime/session-registry/registry.js +761 -0
  299. package/dist/runtime/session-registry/registry.js.map +1 -0
  300. package/dist/runtime/session-registry/types.d.ts +985 -0
  301. package/dist/runtime/session-registry/types.d.ts.map +1 -0
  302. package/dist/runtime/session-registry/types.js +108 -0
  303. package/dist/runtime/session-registry/types.js.map +1 -0
  304. package/dist/runtime/store/background-run-store.d.ts +75 -0
  305. package/dist/runtime/store/background-run-store.d.ts.map +1 -0
  306. package/dist/runtime/store/background-run-store.js +157 -0
  307. package/dist/runtime/store/background-run-store.js.map +1 -0
  308. package/dist/runtime/store/index.d.ts +2 -0
  309. package/dist/runtime/store/index.d.ts.map +1 -1
  310. package/dist/runtime/store/index.js +1 -0
  311. package/dist/runtime/store/index.js.map +1 -1
  312. package/dist/runtime/store/runtime-operation-schemas.d.ts +24 -24
  313. package/dist/runtime/store/runtime-paths.d.ts +2 -0
  314. package/dist/runtime/store/runtime-paths.d.ts.map +1 -1
  315. package/dist/runtime/store/runtime-paths.js +6 -0
  316. package/dist/runtime/store/runtime-paths.js.map +1 -1
  317. package/dist/runtime/types/daemon.d.ts +3 -0
  318. package/dist/runtime/types/daemon.d.ts.map +1 -1
  319. package/dist/runtime/types/daemon.js +1 -0
  320. package/dist/runtime/types/daemon.js.map +1 -1
  321. package/dist/tools/builtin/exports.d.ts +4 -0
  322. package/dist/tools/builtin/exports.d.ts.map +1 -1
  323. package/dist/tools/builtin/exports.js +4 -0
  324. package/dist/tools/builtin/exports.js.map +1 -1
  325. package/dist/tools/builtin/factory.d.ts.map +1 -1
  326. package/dist/tools/builtin/factory.js +18 -0
  327. package/dist/tools/builtin/factory.js.map +1 -1
  328. package/dist/tools/fs/GlobTool/GlobTool.js +2 -2
  329. package/dist/tools/fs/GlobTool/GlobTool.js.map +1 -1
  330. package/dist/tools/fs/GrepTool/GrepTool.js +2 -2
  331. package/dist/tools/fs/GrepTool/GrepTool.js.map +1 -1
  332. package/dist/tools/fs/ReadTool/ReadTool.js +2 -2
  333. package/dist/tools/fs/ReadTool/ReadTool.js.map +1 -1
  334. package/dist/tools/kaggle/KaggleExperimentTools.d.ts +395 -0
  335. package/dist/tools/kaggle/KaggleExperimentTools.d.ts.map +1 -0
  336. package/dist/tools/kaggle/KaggleExperimentTools.js +923 -0
  337. package/dist/tools/kaggle/KaggleExperimentTools.js.map +1 -0
  338. package/dist/tools/kaggle/KaggleSubmissionTools.d.ts +241 -0
  339. package/dist/tools/kaggle/KaggleSubmissionTools.d.ts.map +1 -0
  340. package/dist/tools/kaggle/KaggleSubmissionTools.js +558 -0
  341. package/dist/tools/kaggle/KaggleSubmissionTools.js.map +1 -0
  342. package/dist/tools/kaggle/KaggleWorkspacePrepareTool.d.ts +105 -0
  343. package/dist/tools/kaggle/KaggleWorkspacePrepareTool.d.ts.map +1 -0
  344. package/dist/tools/kaggle/KaggleWorkspacePrepareTool.js +135 -0
  345. package/dist/tools/kaggle/KaggleWorkspacePrepareTool.js.map +1 -0
  346. package/dist/tools/kaggle/index.d.ts +6 -0
  347. package/dist/tools/kaggle/index.d.ts.map +1 -0
  348. package/dist/tools/kaggle/index.js +6 -0
  349. package/dist/tools/kaggle/index.js.map +1 -0
  350. package/dist/tools/kaggle/metrics.d.ts +89 -0
  351. package/dist/tools/kaggle/metrics.d.ts.map +1 -0
  352. package/dist/tools/kaggle/metrics.js +51 -0
  353. package/dist/tools/kaggle/metrics.js.map +1 -0
  354. package/dist/tools/kaggle/paths.d.ts +15 -0
  355. package/dist/tools/kaggle/paths.d.ts.map +1 -0
  356. package/dist/tools/kaggle/paths.js +136 -0
  357. package/dist/tools/kaggle/paths.js.map +1 -0
  358. package/dist/tools/network/GitHubCliTool/GitHubCliTool.d.ts +2 -2
  359. package/dist/tools/query/CodeReadContextTool/CodeReadContextTool.d.ts +801 -0
  360. package/dist/tools/query/CodeReadContextTool/CodeReadContextTool.d.ts.map +1 -0
  361. package/dist/tools/query/CodeReadContextTool/CodeReadContextTool.js +147 -0
  362. package/dist/tools/query/CodeReadContextTool/CodeReadContextTool.js.map +1 -0
  363. package/dist/tools/query/CodeReadContextTool/constants.d.ts +5 -0
  364. package/dist/tools/query/CodeReadContextTool/constants.d.ts.map +1 -0
  365. package/dist/tools/query/CodeReadContextTool/constants.js +5 -0
  366. package/dist/tools/query/CodeReadContextTool/constants.js.map +1 -0
  367. package/dist/tools/query/CodeReadContextTool/prompt.d.ts +2 -0
  368. package/dist/tools/query/CodeReadContextTool/prompt.d.ts.map +1 -0
  369. package/dist/tools/query/CodeReadContextTool/prompt.js +6 -0
  370. package/dist/tools/query/CodeReadContextTool/prompt.js.map +1 -0
  371. package/dist/tools/query/CodeSearchRepairTool/CodeSearchRepairTool.d.ts +125 -0
  372. package/dist/tools/query/CodeSearchRepairTool/CodeSearchRepairTool.d.ts.map +1 -0
  373. package/dist/tools/query/CodeSearchRepairTool/CodeSearchRepairTool.js +97 -0
  374. package/dist/tools/query/CodeSearchRepairTool/CodeSearchRepairTool.js.map +1 -0
  375. package/dist/tools/query/CodeSearchRepairTool/constants.d.ts +5 -0
  376. package/dist/tools/query/CodeSearchRepairTool/constants.d.ts.map +1 -0
  377. package/dist/tools/query/CodeSearchRepairTool/constants.js +5 -0
  378. package/dist/tools/query/CodeSearchRepairTool/constants.js.map +1 -0
  379. package/dist/tools/query/CodeSearchRepairTool/prompt.d.ts +2 -0
  380. package/dist/tools/query/CodeSearchRepairTool/prompt.d.ts.map +1 -0
  381. package/dist/tools/query/CodeSearchRepairTool/prompt.js +5 -0
  382. package/dist/tools/query/CodeSearchRepairTool/prompt.js.map +1 -0
  383. package/dist/tools/query/CodeSearchTool/CodeSearchTool.d.ts +123 -0
  384. package/dist/tools/query/CodeSearchTool/CodeSearchTool.d.ts.map +1 -0
  385. package/dist/tools/query/CodeSearchTool/CodeSearchTool.js +95 -0
  386. package/dist/tools/query/CodeSearchTool/CodeSearchTool.js.map +1 -0
  387. package/dist/tools/query/CodeSearchTool/constants.d.ts +5 -0
  388. package/dist/tools/query/CodeSearchTool/constants.d.ts.map +1 -0
  389. package/dist/tools/query/CodeSearchTool/constants.js +5 -0
  390. package/dist/tools/query/CodeSearchTool/constants.js.map +1 -0
  391. package/dist/tools/query/CodeSearchTool/prompt.d.ts +2 -0
  392. package/dist/tools/query/CodeSearchTool/prompt.d.ts.map +1 -0
  393. package/dist/tools/query/CodeSearchTool/prompt.js +6 -0
  394. package/dist/tools/query/CodeSearchTool/prompt.js.map +1 -0
  395. package/package.json +2 -1
@@ -18,12 +18,15 @@ import { toToolDefinitionsFiltered } from "../../tools/tool-definition-adapter.j
18
18
  import { TendCommand } from "./tend-command.js";
19
19
  import { EventSubscriber } from "./event-subscriber.js";
20
20
  import { buildPromptedToolProtocolSystemPrompt, extractPromptedToolCalls, } from "../../orchestrator/execution/agent-loop/prompted-tool-protocol.js";
21
+ import { classifyFailureRecovery, formatFailureRecovery, formatLifecycleFailureMessage } from "./failure-recovery.js";
21
22
  import { resolveExecutionPolicy, summarizeExecutionPolicy, withExecutionPolicyOverrides, } from "../../orchestrator/execution/agent-loop/execution-policy.js";
22
23
  import { buildStandaloneIngressMessage, createIngressRouter, } from "./ingress-router.js";
24
+ import { createRuntimeSessionRegistry } from "../../runtime/session-registry/index.js";
23
25
  const DEFAULT_TIMEOUT_MS = 120_000;
24
26
  const MAX_VERIFY_RETRIES = 2;
25
27
  const MAX_TOOL_LOOPS = 5;
26
28
  const ACTIVITY_PREVIEW_CHARS = 40;
29
+ const DIFF_ARTIFACT_MAX_LINES = 80;
27
30
  const standaloneIngressRouter = createIngressRouter();
28
31
  // ─── Command help text ───
29
32
  const COMMAND_HELP = `Available commands:
@@ -36,6 +39,7 @@ Session
36
39
  /resume [id|title] Resume native agentloop state for the current or selected session
37
40
  /cleanup [--dry-run] Clean up stale chat sessions
38
41
  /compact Summarize older chat turns and keep the latest turns
42
+ /context Show active working context and session assumptions
39
43
  /exit Exit chat mode
40
44
 
41
45
  Goals and tasks
@@ -69,14 +73,109 @@ function checkGitChanges(cwd) {
69
73
  });
70
74
  });
71
75
  }
76
+ function runGit(cwd, args, timeout = 5_000) {
77
+ return new Promise((resolve) => {
78
+ execFile("git", args, { cwd, timeout }, (err, stdout, stderr) => {
79
+ if (err) {
80
+ resolve(null);
81
+ return;
82
+ }
83
+ resolve((stdout + stderr).trim());
84
+ });
85
+ });
86
+ }
87
+ function parseGitLines(output) {
88
+ return output ? output.split("\n").map((line) => line.trim()).filter(Boolean) : [];
89
+ }
90
+ async function buildUntrackedFilePatch(cwd, relativePath) {
91
+ const absolutePath = path.resolve(cwd, relativePath);
92
+ const relativeFromCwd = path.relative(cwd, absolutePath);
93
+ if (relativeFromCwd.startsWith("..") || path.isAbsolute(relativeFromCwd)) {
94
+ return `diff --git a/${relativePath} b/${relativePath}\nnew file skipped: path outside workspace`;
95
+ }
96
+ try {
97
+ const stat = await fsp.stat(absolutePath);
98
+ if (!stat.isFile()) {
99
+ return `diff --git a/${relativePath} b/${relativePath}\nnew file skipped: not a regular file`;
100
+ }
101
+ if (stat.size > 100_000) {
102
+ return `diff --git a/${relativePath} b/${relativePath}\nnew file skipped: ${stat.size} bytes`;
103
+ }
104
+ const content = await fsp.readFile(absolutePath, "utf-8");
105
+ const lines = content.split("\n");
106
+ const body = lines.map((line) => `+${line}`).join("\n");
107
+ return [
108
+ `diff --git a/${relativePath} b/${relativePath}`,
109
+ "new file mode 100644",
110
+ "--- /dev/null",
111
+ `+++ b/${relativePath}`,
112
+ `@@ -0,0 +1,${lines.length} @@`,
113
+ body,
114
+ ].join("\n");
115
+ }
116
+ catch {
117
+ return `diff --git a/${relativePath} b/${relativePath}\nnew file skipped: unreadable`;
118
+ }
119
+ }
120
+ async function collectGitDiffArtifact(cwd) {
121
+ const trackedStat = await runGit(cwd, ["diff", "HEAD", "--stat"]);
122
+ const untrackedFiles = parseGitLines(await runGit(cwd, ["ls-files", "--others", "--exclude-standard"]));
123
+ if (!trackedStat && untrackedFiles.length === 0)
124
+ return null;
125
+ const trackedNameStatus = await runGit(cwd, ["diff", "HEAD", "--name-status"]) ?? "";
126
+ const trackedPatch = await runGit(cwd, ["diff", "HEAD", "--patch", "--unified=3"], 10_000) ?? "";
127
+ const untrackedPatchParts = await Promise.all(untrackedFiles.slice(0, 10).map((file) => buildUntrackedFilePatch(cwd, file)));
128
+ if (untrackedFiles.length > 10) {
129
+ untrackedPatchParts.push(`... ${untrackedFiles.length - 10} additional untracked file(s) omitted`);
130
+ }
131
+ const stat = [
132
+ trackedStat,
133
+ untrackedFiles.length > 0
134
+ ? ["Untracked files:", ...untrackedFiles.map((file) => ` ${file}`)].join("\n")
135
+ : "",
136
+ ].filter(Boolean).join("\n");
137
+ const nameStatus = [
138
+ trackedNameStatus,
139
+ ...untrackedFiles.map((file) => `A\t${file}`),
140
+ ].filter(Boolean).join("\n");
141
+ const patch = [trackedPatch, ...untrackedPatchParts].filter(Boolean).join("\n");
142
+ const patchLines = patch.split("\n");
143
+ const truncated = patchLines.length > DIFF_ARTIFACT_MAX_LINES;
144
+ return {
145
+ stat,
146
+ nameStatus,
147
+ patch: patchLines.slice(0, DIFF_ARTIFACT_MAX_LINES).join("\n"),
148
+ truncated,
149
+ };
150
+ }
72
151
  function previewActivityText(value, maxChars = ACTIVITY_PREVIEW_CHARS) {
73
152
  const normalized = value.replace(/\s+/g, " ").trim();
74
153
  return normalized.length > maxChars ? `${normalized.slice(0, maxChars)}...` : normalized;
75
154
  }
155
+ function classifyInterruptRedirect(input) {
156
+ const normalized = input.trim().toLowerCase();
157
+ if (/\b(background|bg)\b|バックグラウンド|裏で|裏側|continue.*background/.test(normalized)) {
158
+ return "background";
159
+ }
160
+ if (/\b(review|read.?only|readonly)\b|レビュー|確認だけ|読むだけ/.test(normalized)) {
161
+ return "review";
162
+ }
163
+ if (/\b(diff|changes?|patch)\b|差分|変更.*見|変更内容/.test(normalized)) {
164
+ return "diff";
165
+ }
166
+ if (/\b(stop|pause|summary|summarize|interrupt)\b|止め|停止|中断|一旦|要約/.test(normalized)) {
167
+ return "summary";
168
+ }
169
+ return "redirect";
170
+ }
76
171
  function formatToolActivity(action, toolName, detail) {
77
172
  const preview = detail ? previewActivityText(detail) : "";
78
173
  return preview ? `${action} tool: ${toolName} - ${preview}` : `${action} tool: ${toolName}`;
79
174
  }
175
+ function formatIntentInput(input, maxChars = 96) {
176
+ const normalized = input.replace(/\s+/g, " ").trim();
177
+ return normalized.length > maxChars ? `${normalized.slice(0, maxChars - 3)}...` : normalized;
178
+ }
80
179
  function resolveSelfIdentityResponse(input, baseDir) {
81
180
  const normalized = input.trim().toLowerCase().replace(/\s+/g, "");
82
181
  if (!normalized)
@@ -116,6 +215,8 @@ export class ChatRunner {
116
215
  nativeAgentLoopStatePath = null;
117
216
  runtimeControlContext = null;
118
217
  sessionExecutionPolicy = null;
218
+ lastSelectedRoute = null;
219
+ activeTurn = null;
119
220
  constructor(deps) {
120
221
  this.deps = deps;
121
222
  this.groundingGateway = createChatGroundingGateway({
@@ -153,6 +254,68 @@ export class ChatRunner {
153
254
  getCurrentSessionMessages() {
154
255
  return this.history?.getMessages() ?? [];
155
256
  }
257
+ hasActiveTurn() {
258
+ return this.activeTurn !== null;
259
+ }
260
+ async interruptAndRedirect(input, cwd, timeoutMs = DEFAULT_TIMEOUT_MS) {
261
+ const activeTurn = this.activeTurn;
262
+ if (!activeTurn) {
263
+ return this.execute(input, cwd, timeoutMs);
264
+ }
265
+ const start = Date.now();
266
+ const redirect = classifyInterruptRedirect(input);
267
+ if (redirect === "background") {
268
+ return this.emitEphemeralAssistantResult(input, [
269
+ "Continuing this same turn in the background is not available yet.",
270
+ "",
271
+ "The active turn is still running in the foreground.",
272
+ "Use /tend for daemon-backed work, or send a narrower follow-up request.",
273
+ ].join("\n"), true, start);
274
+ }
275
+ activeTurn.interruptRequested = true;
276
+ if (!activeTurn.abortController.signal.aborted) {
277
+ activeTurn.abortController.abort();
278
+ }
279
+ this.emitCheckpoint("Interrupt requested", `Redirect: ${previewActivityText(input, 120)}`, activeTurn.context, "interrupt");
280
+ const stopped = await this.waitForActiveTurn(activeTurn, 2_000);
281
+ if (!stopped) {
282
+ return this.emitEphemeralAssistantResult(input, "Interrupt requested. The active turn will stop at the next safe point.", false, start);
283
+ }
284
+ if (redirect === "redirect") {
285
+ return this.execute(input, cwd, timeoutMs);
286
+ }
287
+ let output;
288
+ if (redirect === "diff") {
289
+ const diff = await collectGitDiffArtifact(activeTurn.cwd);
290
+ if (diff) {
291
+ const context = this.createEventContext();
292
+ this.emitDiffArtifact(diff, context);
293
+ output = "Interrupted the active turn. Current diff is shown above.";
294
+ }
295
+ else {
296
+ output = "Interrupted the active turn. No working-tree changes were detected.";
297
+ }
298
+ }
299
+ else if (redirect === "review") {
300
+ const review = await this.handleReview(start);
301
+ output = `Interrupted the active turn and switched to review-only mode.\n\n${review.output}`;
302
+ }
303
+ else {
304
+ output = [
305
+ "Interrupted the active turn.",
306
+ "",
307
+ "Recent activity",
308
+ ...(activeTurn.recentEvents.length > 0
309
+ ? activeTurn.recentEvents.slice(-6).map((event) => `- ${event}`)
310
+ : ["- No activity was captured before the interrupt."]),
311
+ "",
312
+ "Next actions",
313
+ "- Ask for the exact continuation you want.",
314
+ "- Ask to show diff or switch to review if files may have changed.",
315
+ ].join("\n");
316
+ }
317
+ return this.emitEphemeralAssistantResult(input, output, true, start);
318
+ }
156
319
  setRuntimeControlContext(context) {
157
320
  this.runtimeControlContext = context;
158
321
  }
@@ -179,6 +342,9 @@ export class ChatRunner {
179
342
  hasAgentLoop: this.deps.chatAgentLoopRunner !== undefined,
180
343
  hasToolLoop: this.deps.llmClient !== undefined,
181
344
  hasRuntimeControlService: this.deps.runtimeControlService !== undefined,
345
+ hasDaemonTend: this.deps.llmClient !== undefined
346
+ && this.deps.goalNegotiator !== undefined
347
+ && this.deps.daemonClient !== undefined,
182
348
  };
183
349
  }
184
350
  buildStandaloneIngressMessage(input, runtimeControlContext) {
@@ -259,15 +425,94 @@ export class ChatRunner {
259
425
  ...(session.agentLoop ? { agentLoop: session.agentLoop } : {}),
260
426
  };
261
427
  }
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")}`;
428
+ formatRuntimeTimestamp(value) {
429
+ return value ?? "unknown";
430
+ }
431
+ formatRuntimeTitle(value) {
432
+ return value ? ` "${value}"` : "";
433
+ }
434
+ runtimeWarningLine(warnings) {
435
+ return warnings.length > 0 ? `Warnings: ${warnings.length}` : null;
436
+ }
437
+ activeRuntimeSession(session) {
438
+ return session.status === "active";
439
+ }
440
+ statusRuntimeRun(run) {
441
+ return run.status === "queued"
442
+ || run.status === "running"
443
+ || run.status === "failed"
444
+ || run.status === "timed_out"
445
+ || run.status === "lost";
446
+ }
447
+ compactRunLine(run) {
448
+ const title = this.formatRuntimeTitle(run.title);
449
+ const updated = this.formatRuntimeTimestamp(run.updated_at ?? run.started_at ?? run.created_at);
450
+ const summary = run.summary ? ` - ${run.summary.replace(/\s+/g, " ").trim()}` : "";
451
+ const error = run.error ? ` - error: ${run.error.replace(/\s+/g, " ").trim()}` : "";
452
+ return `- ${run.id}${title} [${run.kind}, ${run.status}], updated ${updated}${summary}${error}`;
453
+ }
454
+ compactSessionLine(session) {
455
+ const displayId = session.kind === "conversation"
456
+ ? session.transcript_ref?.id ?? session.id.replace(/^session:conversation:/, "")
457
+ : session.id;
458
+ const title = this.formatRuntimeTitle(session.title);
459
+ const updated = this.formatRuntimeTimestamp(session.updated_at ?? session.last_event_at ?? session.created_at);
460
+ const workspace = session.workspace ? `, cwd ${session.workspace}` : "";
461
+ const resumable = session.resumable ? ", resumable" : "";
462
+ const attachable = session.attachable ? ", attachable" : "";
463
+ const runtimeId = displayId === session.id ? "" : `, runtime ${session.id}`;
464
+ return `- ${displayId}${title} [${session.kind}, ${session.status}], updated ${updated}${workspace}${resumable}${attachable}${runtimeId}`;
465
+ }
466
+ formatRuntimeSessionsList(snapshot) {
467
+ const chatSessions = snapshot.sessions.filter((session) => session.kind === "conversation");
468
+ const nonChatSessions = snapshot.sessions.filter((session) => session.kind !== "conversation");
469
+ const lines = ["Chat sessions:"];
470
+ if (chatSessions.length === 0) {
471
+ lines.push("No chat sessions found.");
472
+ }
473
+ else {
474
+ for (const session of chatSessions) {
475
+ lines.push(this.compactSessionLine(session));
476
+ const runs = snapshot.background_runs.filter((run) => run.parent_session_id === session.id);
477
+ for (const run of runs) {
478
+ lines.push(` ${this.compactRunLine(run)}`);
479
+ }
480
+ }
481
+ }
482
+ if (nonChatSessions.length > 0) {
483
+ lines.push("", "Other runtime sessions:");
484
+ lines.push(...nonChatSessions.map((session) => this.compactSessionLine(session)));
485
+ }
486
+ if (snapshot.background_runs.length > 0) {
487
+ lines.push("", "Background runs:");
488
+ lines.push(...snapshot.background_runs.map((run) => this.compactRunLine(run)));
489
+ }
490
+ const warningLine = this.runtimeWarningLine(snapshot.warnings);
491
+ if (warningLine)
492
+ lines.push("", warningLine);
493
+ return lines.join("\n");
494
+ }
495
+ formatRuntimeStatus(snapshot) {
496
+ const activeSessions = snapshot.sessions.filter((session) => this.activeRuntimeSession(session));
497
+ const statusRuns = snapshot.background_runs.filter((run) => this.statusRuntimeRun(run));
498
+ const lines = [];
499
+ if (activeSessions.length > 0) {
500
+ lines.push("Active runtime sessions:");
501
+ lines.push(...activeSessions.map((session) => this.compactSessionLine(session)));
502
+ }
503
+ if (statusRuns.length > 0) {
504
+ if (lines.length > 0)
505
+ lines.push("");
506
+ lines.push("Background runs (queued/running/attention-needed):");
507
+ lines.push(...statusRuns.map((run) => this.compactRunLine(run)));
508
+ }
509
+ const warningLine = this.runtimeWarningLine(snapshot.warnings);
510
+ if (warningLine) {
511
+ if (lines.length > 0)
512
+ lines.push("");
513
+ lines.push(warningLine);
514
+ }
515
+ return lines.length > 0 ? lines.join("\n") : "No active runtime sessions or running/failed/lost background runs found.";
271
516
  }
272
517
  formatHistory(session) {
273
518
  const title = session.title ? ` "${session.title}"` : "";
@@ -356,14 +601,19 @@ export class ChatRunner {
356
601
  ];
357
602
  return { success: true, output: lines.join("\n"), elapsed_ms: Date.now() - start };
358
603
  }
359
- const goals = await this.loadGoals();
604
+ const registry = createRuntimeSessionRegistry({ stateManager: this.deps.stateManager });
605
+ const [goals, runtimeSnapshot] = await Promise.all([
606
+ this.loadGoals(),
607
+ registry.snapshot(),
608
+ ]);
360
609
  const active = this.activeGoals(goals);
610
+ const runtimeStatus = this.formatRuntimeStatus(runtimeSnapshot);
361
611
  if (active.length === 0) {
362
- return { success: true, output: "No active goals found.", elapsed_ms: Date.now() - start };
612
+ return { success: true, output: `No active goals found.\n\n${runtimeStatus}`, elapsed_ms: Date.now() - start };
363
613
  }
364
614
  return {
365
615
  success: true,
366
- output: `Active goals:\n${active.map((goal) => this.formatGoalLine(goal)).join("\n")}`,
616
+ output: `Active goals:\n${active.map((goal) => this.formatGoalLine(goal)).join("\n")}\n\n${runtimeStatus}`,
367
617
  elapsed_ms: Date.now() - start,
368
618
  };
369
619
  }
@@ -812,7 +1062,79 @@ export class ChatRunner {
812
1062
  elapsed_ms: Date.now() - start,
813
1063
  };
814
1064
  }
815
- async handleCommand(input) {
1065
+ formatRoute(route) {
1066
+ if (!route)
1067
+ return "none selected yet";
1068
+ const details = [
1069
+ `lane=${route.lane}`,
1070
+ `kind=${route.kind}`,
1071
+ `reason=${route.reason}`,
1072
+ ];
1073
+ if (route.kind === "direct_answer") {
1074
+ details.push(`model_tier=${route.modelTier}`, `max_tokens=${route.maxTokens}`);
1075
+ }
1076
+ if (route.kind === "runtime_control") {
1077
+ details.push(`intent=${route.intent.kind}`);
1078
+ }
1079
+ return details.join(", ");
1080
+ }
1081
+ async handleContext(start, cwdOverride) {
1082
+ const cwd = this.sessionCwd ?? (cwdOverride ? resolveGitRoot(cwdOverride) : process.cwd());
1083
+ const session = this.history?.getSessionData() ?? null;
1084
+ const messages = session?.messages ?? [];
1085
+ const policy = await this.getSessionExecutionPolicy();
1086
+ const recentMessages = messages.slice(-6);
1087
+ const userTurns = messages.filter((message) => message.role === "user").length;
1088
+ const assistantTurns = messages.filter((message) => message.role === "assistant").length;
1089
+ const compactionSummary = session?.compactionSummary?.trim() ?? "";
1090
+ const agentLoopPath = this.nativeAgentLoopStatePath ?? session?.agentLoopStatePath ?? null;
1091
+ const replyTarget = this.runtimeControlContext?.replyTarget ?? this.deps.runtimeReplyTarget ?? null;
1092
+ const routeCapabilities = this.getRouteCapabilities();
1093
+ const replyTargetParts = replyTarget
1094
+ ? [replyTarget.surface, replyTarget.platform, replyTarget.conversation_id].filter(Boolean)
1095
+ : [];
1096
+ const contextLines = [
1097
+ "Working context",
1098
+ "",
1099
+ "Session",
1100
+ `- session_id: ${this.history?.getSessionId() ?? "none"}`,
1101
+ `- cwd: ${cwd}`,
1102
+ `- messages: ${messages.length} (${userTurns} user, ${assistantTurns} assistant)`,
1103
+ `- recent_turns_retained: ${recentMessages.length}`,
1104
+ `- compaction_summary: ${compactionSummary ? "present" : "none"}`,
1105
+ `- agentloop_state_path: ${agentLoopPath ?? "none"}`,
1106
+ "",
1107
+ "Turn context",
1108
+ `- last_selected_route: ${this.formatRoute(this.lastSelectedRoute)}`,
1109
+ `- reply_target: ${replyTargetParts.length > 0 ? replyTargetParts.join(":") : "none"}`,
1110
+ `- route_capabilities: light_llm=${routeCapabilities.hasLightweightLlm}, agent_loop=${routeCapabilities.hasAgentLoop}, tool_loop=${routeCapabilities.hasToolLoop}, runtime_control=${routeCapabilities.hasRuntimeControlService}, daemon_tend=${routeCapabilities.hasDaemonTend}`,
1111
+ "",
1112
+ "Working assumptions",
1113
+ "- this view exposes operational context, not hidden reasoning",
1114
+ "- last_selected_route describes the most recent non-command turn in this ChatRunner",
1115
+ "- future turns may select a different route based on the next input",
1116
+ "",
1117
+ "Active constraints",
1118
+ ...summarizeExecutionPolicy(policy).split("\n").map((line) => `- ${line}`),
1119
+ "",
1120
+ "Included context",
1121
+ "- current session cwd and execution policy because they constrain tool and route behavior",
1122
+ `- ${recentMessages.length} latest persisted message(s)`,
1123
+ `- ${compactionSummary ? "compacted older chat summary because older turns were summarized" : "no compacted older chat summary because none is stored"}`,
1124
+ `- ${agentLoopPath ? "native agent-loop resume path because this session can persist agent-loop state" : "no native agent-loop resume path because none is active"}`,
1125
+ "",
1126
+ "Not included",
1127
+ "- hidden reasoning or private model chain-of-thought",
1128
+ "- raw state files unless a command explicitly reads them",
1129
+ "- older chat turns beyond the retained window unless compacted into the session summary",
1130
+ ];
1131
+ return {
1132
+ success: true,
1133
+ output: contextLines.join("\n"),
1134
+ elapsed_ms: Date.now() - start,
1135
+ };
1136
+ }
1137
+ async handleCommand(input, cwd) {
816
1138
  const trimmed = input.trim();
817
1139
  if (!trimmed.startsWith("/"))
818
1140
  return null;
@@ -826,9 +1148,9 @@ export class ChatRunner {
826
1148
  return { success: true, output: "Conversation history cleared.", elapsed_ms: Date.now() - start };
827
1149
  }
828
1150
  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 };
1151
+ const registry = createRuntimeSessionRegistry({ stateManager: this.deps.stateManager });
1152
+ const snapshot = await registry.snapshot();
1153
+ return { success: true, output: this.formatRuntimeSessionsList(snapshot), elapsed_ms: Date.now() - start };
832
1154
  }
833
1155
  if (cmd === "/history") {
834
1156
  const catalog = new ChatSessionCatalog(this.deps.stateManager);
@@ -901,6 +1223,9 @@ export class ChatRunner {
901
1223
  if (cmd === "/usage") {
902
1224
  return this.handleUsage(trimmed.slice("/usage".length).trim(), start);
903
1225
  }
1226
+ if (cmd === "/context" || cmd === "/working-memory") {
1227
+ return this.handleContext(start, cwd);
1228
+ }
904
1229
  if (cmd === "/review") {
905
1230
  return this.handleReview(start);
906
1231
  }
@@ -910,6 +1235,26 @@ export class ChatRunner {
910
1235
  if (cmd === "/undo") {
911
1236
  return this.handleUndo(start);
912
1237
  }
1238
+ if (cmd === "/retry") {
1239
+ return {
1240
+ success: false,
1241
+ output: [
1242
+ "/retry is not supported yet.",
1243
+ "",
1244
+ formatFailureRecovery({
1245
+ kind: "runtime_interruption",
1246
+ label: "Retry unavailable",
1247
+ summary: "PulSeed does not yet have a safe replay contract for the previous turn.",
1248
+ nextActions: [
1249
+ "Use /review to inspect any current diff before continuing.",
1250
+ "Use /resume when PulSeed reports resumable agent-loop state.",
1251
+ "Ask for the exact next step to rerun instead of replaying the full turn.",
1252
+ ],
1253
+ }),
1254
+ ].join("\n"),
1255
+ elapsed_ms: Date.now() - start,
1256
+ };
1257
+ }
913
1258
  if (cmd === "/exit") {
914
1259
  return { success: true, output: "Exiting chat mode.", elapsed_ms: Date.now() - start };
915
1260
  }
@@ -1110,6 +1455,9 @@ export class ChatRunner {
1110
1455
  daemonClient: this.deps.daemonClient,
1111
1456
  stateManager: this.deps.stateManager,
1112
1457
  chatHistory: history,
1458
+ sessionId: this.history?.getSessionId() ?? null,
1459
+ workspace: this.sessionCwd ?? process.cwd(),
1460
+ replyTarget: this.runtimeControlContext?.replyTarget ?? this.deps.runtimeReplyTarget ?? null,
1113
1461
  };
1114
1462
  const tendCommand = new TendCommand();
1115
1463
  const result = await tendCommand.execute(args, tendDeps);
@@ -1175,7 +1523,34 @@ export class ChatRunner {
1175
1523
  }
1176
1524
  }
1177
1525
  try {
1178
- await this.deps.daemonClient.startGoal(goalId);
1526
+ const tendDeps = {
1527
+ llmClient: this.deps.llmClient,
1528
+ goalNegotiator: this.deps.goalNegotiator,
1529
+ daemonClient: this.deps.daemonClient,
1530
+ stateManager: this.deps.stateManager,
1531
+ chatHistory: this.history?.getMessages() ?? [],
1532
+ sessionId: this.history?.getSessionId() ?? null,
1533
+ workspace: this.sessionCwd ?? process.cwd(),
1534
+ replyTarget: this.runtimeControlContext?.replyTarget ?? this.deps.runtimeReplyTarget ?? null,
1535
+ };
1536
+ const result = await new TendCommand().startAcceptedGoal(goalId, maxIterations, tendDeps);
1537
+ if (!result.success) {
1538
+ if (subscriber) {
1539
+ subscriber.unsubscribe();
1540
+ this.activeSubscribers.delete(goalId);
1541
+ }
1542
+ return {
1543
+ success: false,
1544
+ output: result.message,
1545
+ elapsed_ms: Date.now() - start,
1546
+ };
1547
+ }
1548
+ const shortId = goalId.length > 12 ? goalId.slice(0, 12) : goalId;
1549
+ return {
1550
+ success: true,
1551
+ output: `[tend] ${shortId}: Started — daemon is now tending your goal${maxIterations !== undefined ? ` (max ${maxIterations} iterations)` : ""}.\nBackground run: ${result.backgroundRunId}\nRun 'pulseed status' to check progress.`,
1552
+ elapsed_ms: Date.now() - start,
1553
+ };
1179
1554
  }
1180
1555
  catch (err) {
1181
1556
  if (subscriber) {
@@ -1189,13 +1564,6 @@ export class ChatRunner {
1189
1564
  elapsed_ms: Date.now() - start,
1190
1565
  };
1191
1566
  }
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
1567
  }
1200
1568
  /**
1201
1569
  * Execute a single chat turn.
@@ -1211,12 +1579,13 @@ export class ChatRunner {
1211
1579
  */
1212
1580
  async execute(input, cwd, timeoutMs = DEFAULT_TIMEOUT_MS, options = {}) {
1213
1581
  const eventContext = this.createEventContext();
1582
+ const activeTurn = this.beginActiveTurn(eventContext, resolveGitRoot(cwd));
1214
1583
  const resumeCommand = this.parseResumeCommand(input);
1215
1584
  const resumeOnly = resumeCommand !== null;
1216
1585
  const runtimeControlContext = options.runtimeControlContext ?? this.runtimeControlContext;
1217
1586
  const executionGoalId = options.goalId ?? this.deps.goalId;
1218
1587
  // Intercept commands before any adapter call
1219
- const commandResult = resumeOnly ? null : await this.handleCommand(input);
1588
+ const commandResult = resumeOnly ? null : await this.handleCommand(input, cwd);
1220
1589
  if (commandResult !== null) {
1221
1590
  if (commandResult.output) {
1222
1591
  this.emitEvent({
@@ -1245,11 +1614,24 @@ export class ChatRunner {
1245
1614
  }
1246
1615
  if (resumeOnly && resumeCommand.selector) {
1247
1616
  try {
1617
+ const selectorResolution = await this.resolveChatResumeSelector(resumeCommand.selector);
1618
+ if (selectorResolution.nonResumableMessage) {
1619
+ const elapsed_ms = 0;
1620
+ const output = selectorResolution.nonResumableMessage;
1621
+ this.emitEvent({
1622
+ type: "assistant_final",
1623
+ text: output,
1624
+ persisted: false,
1625
+ ...this.eventBase(eventContext),
1626
+ });
1627
+ this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
1628
+ return { success: false, output, elapsed_ms };
1629
+ }
1248
1630
  const catalog = new ChatSessionCatalog(this.deps.stateManager);
1249
- const session = await catalog.loadSessionBySelector(resumeCommand.selector);
1631
+ const session = await catalog.loadSessionBySelector(selectorResolution.chatSelector);
1250
1632
  if (!session) {
1251
1633
  const elapsed_ms = 0;
1252
- const output = `No chat session matched selector "${resumeCommand.selector}".`;
1634
+ const output = `No chat session matched selector "${selectorResolution.chatSelector}".`;
1253
1635
  this.emitEvent({
1254
1636
  type: "assistant_final",
1255
1637
  text: output,
@@ -1284,6 +1666,7 @@ export class ChatRunner {
1284
1666
  }
1285
1667
  const executionCwd = this.sessionCwd ?? cwd;
1286
1668
  const gitRoot = this.sessionCwd ?? resolveGitRoot(cwd);
1669
+ activeTurn.cwd = gitRoot;
1287
1670
  // history is always assigned by this point (either by startSession or the block above)
1288
1671
  const history = this.history;
1289
1672
  this.emitEvent({
@@ -1323,7 +1706,14 @@ export class ChatRunner {
1323
1706
  const selectedRoute = resumeOnly
1324
1707
  ? null
1325
1708
  : (options.selectedRoute ?? this.resolveRouteFromInput(input, runtimeControlContext));
1709
+ this.lastSelectedRoute = selectedRoute;
1326
1710
  const directPrompt = historyBlock ? `${historyBlock}${input}` : input;
1711
+ if (!resumeOnly) {
1712
+ this.emitIntent(input, selectedRoute, eventContext);
1713
+ }
1714
+ else if (resumeOnly) {
1715
+ this.emitIntent(input, null, eventContext);
1716
+ }
1327
1717
  const start = Date.now();
1328
1718
  const assistantBuffer = { text: "" };
1329
1719
  const turnUsage = this.zeroUsageCounter();
@@ -1346,9 +1736,11 @@ export class ChatRunner {
1346
1736
  };
1347
1737
  }
1348
1738
  if (selectedRoute?.kind === "runtime_control") {
1739
+ this.emitCheckpoint("Runtime control selected", `${selectedRoute.intent.kind} request recognized.`, eventContext, "route");
1349
1740
  const runtimeControlResult = await this.executeRuntimeControlRoute(selectedRoute, runtimeControlContext, executionCwd, start);
1350
1741
  if (runtimeControlResult.success) {
1351
1742
  await history.appendAssistantMessage(runtimeControlResult.output);
1743
+ this.emitCheckpoint("Runtime control completed", "The runtime-control operation produced a result.", eventContext, "complete");
1352
1744
  this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
1353
1745
  this.emitEvent({
1354
1746
  type: "assistant_final",
@@ -1359,11 +1751,32 @@ export class ChatRunner {
1359
1751
  this.emitLifecycleEndEvent("completed", runtimeControlResult.elapsed_ms, eventContext, true);
1360
1752
  }
1361
1753
  else {
1362
- this.emitLifecycleErrorEvent(runtimeControlResult.output, assistantBuffer.text, eventContext);
1754
+ runtimeControlResult.output = this.emitLifecycleErrorEvent(runtimeControlResult.output, assistantBuffer.text, eventContext);
1363
1755
  this.emitLifecycleEndEvent("error", runtimeControlResult.elapsed_ms, eventContext, false);
1364
1756
  }
1365
1757
  return runtimeControlResult;
1366
1758
  }
1759
+ if (selectedRoute?.kind === "daemon_tend") {
1760
+ this.emitCheckpoint("Durable goal selected", "This long-running request is being prepared for daemon-backed CoreLoop execution.", eventContext, "route");
1761
+ const tendResult = await this.handleTend("", start);
1762
+ if (tendResult.success) {
1763
+ await history.appendAssistantMessage(tendResult.output);
1764
+ this.emitCheckpoint("Durable goal prepared", "The daemon-backed goal confirmation is ready.", eventContext, "complete");
1765
+ this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
1766
+ this.emitEvent({
1767
+ type: "assistant_final",
1768
+ text: tendResult.output,
1769
+ persisted: true,
1770
+ ...this.eventBase(eventContext),
1771
+ });
1772
+ this.emitLifecycleEndEvent("completed", tendResult.elapsed_ms, eventContext, true);
1773
+ }
1774
+ else {
1775
+ tendResult.output = this.emitLifecycleErrorEvent(tendResult.output, assistantBuffer.text, eventContext);
1776
+ this.emitLifecycleEndEvent("error", tendResult.elapsed_ms, eventContext, false);
1777
+ }
1778
+ return tendResult;
1779
+ }
1367
1780
  if (selectedRoute?.kind === "direct_answer") {
1368
1781
  try {
1369
1782
  this.emitActivity("lifecycle", "Calling model...", eventContext, "lifecycle:model");
@@ -1378,7 +1791,12 @@ export class ChatRunner {
1378
1791
  if (this.hasUsage(turnUsage)) {
1379
1792
  history.recordUsage("execution", turnUsage);
1380
1793
  }
1794
+ const diffArtifact = await collectGitDiffArtifact(gitRoot);
1795
+ if (diffArtifact) {
1796
+ this.emitDiffArtifact(diffArtifact, eventContext);
1797
+ }
1381
1798
  await history.appendAssistantMessage(output);
1799
+ this.emitCheckpoint("Response ready", "The direct answer has been persisted for this turn.", eventContext, "complete");
1382
1800
  this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
1383
1801
  this.emitEvent({
1384
1802
  type: "assistant_final",
@@ -1401,13 +1819,11 @@ export class ChatRunner {
1401
1819
  }
1402
1820
  catch (err) {
1403
1821
  const message = err instanceof Error ? err.message : String(err);
1404
- this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
1822
+ const output = this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
1405
1823
  this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
1406
1824
  return {
1407
1825
  success: false,
1408
- output: assistantBuffer.text
1409
- ? `${assistantBuffer.text}\n\n[interrupted: ${message}]`
1410
- : `Error: ${message}`,
1826
+ output,
1411
1827
  elapsed_ms: Date.now() - start,
1412
1828
  diagnostics: {
1413
1829
  route: "direct",
@@ -1453,6 +1869,9 @@ export class ChatRunner {
1453
1869
  catch {
1454
1870
  systemPrompt = this.cachedStaticSystemPrompt ?? "";
1455
1871
  }
1872
+ this.emitCheckpoint("Context gathered", usesNativeAgentLoop
1873
+ ? "Workspace and agent-loop grounding are ready."
1874
+ : "Workspace grounding is ready.", eventContext, "context");
1456
1875
  }
1457
1876
  const agentLoopSystemPrompt = [
1458
1877
  systemPrompt,
@@ -1466,13 +1885,7 @@ export class ChatRunner {
1466
1885
  const prompt = historyBlock ? `${historyBlock}${basePrompt}` : basePrompt;
1467
1886
  if (resumeOnly && !this.deps.chatAgentLoopRunner) {
1468
1887
  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
- });
1888
+ const output = this.emitLifecycleErrorEvent("Resume requires the native chat agentloop runtime.", assistantBuffer.text, eventContext);
1476
1889
  this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
1477
1890
  return {
1478
1891
  success: false,
@@ -1486,13 +1899,7 @@ export class ChatRunner {
1486
1899
  const resumeState = resumeOnly ? await this.loadResumableAgentLoopState() : null;
1487
1900
  if (resumeOnly && !resumeState) {
1488
1901
  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
- });
1902
+ const output = this.emitLifecycleErrorEvent("No resumable native agentloop state found.", assistantBuffer.text, eventContext);
1496
1903
  this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
1497
1904
  return {
1498
1905
  success: false,
@@ -1500,6 +1907,9 @@ export class ChatRunner {
1500
1907
  elapsed_ms,
1501
1908
  };
1502
1909
  }
1910
+ this.emitCheckpoint(resumeOnly ? "Session resumed" : "Agent loop started", resumeOnly
1911
+ ? "Resumable agent-loop state is loaded."
1912
+ : "The agent loop can now inspect, plan, edit, or verify with visible tool activity.", eventContext, "execution");
1503
1913
  this.emitActivity("lifecycle", "Calling model...", eventContext, "lifecycle:model");
1504
1914
  const result = await chatAgentLoopRunner.execute({
1505
1915
  message: basePrompt,
@@ -1523,6 +1933,7 @@ export class ChatRunner {
1523
1933
  ...(resumeState ? { resumeState } : {}),
1524
1934
  ...(resumeOnly ? { resumeOnly: true } : {}),
1525
1935
  ...(agentLoopSystemPrompt ? { systemPrompt: agentLoopSystemPrompt } : {}),
1936
+ abortSignal: activeTurn.abortController.signal,
1526
1937
  });
1527
1938
  const elapsed_ms = Date.now() - start;
1528
1939
  const agentLoopUsage = result.agentLoop?.usage
@@ -1535,7 +1946,12 @@ export class ChatRunner {
1535
1946
  this.pushAssistantDelta(result.output, assistantBuffer, eventContext);
1536
1947
  }
1537
1948
  if (result.success) {
1949
+ const diffArtifact = await collectGitDiffArtifact(gitRoot);
1950
+ if (diffArtifact) {
1951
+ this.emitDiffArtifact(diffArtifact, eventContext);
1952
+ }
1538
1953
  await history.appendAssistantMessage(result.output);
1954
+ this.emitCheckpoint("Response ready", "The agent-loop response has been persisted for this turn.", eventContext, "complete");
1539
1955
  this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
1540
1956
  this.emitEvent({
1541
1957
  type: "assistant_final",
@@ -1546,7 +1962,7 @@ export class ChatRunner {
1546
1962
  this.emitLifecycleEndEvent("completed", elapsed_ms, eventContext, true);
1547
1963
  }
1548
1964
  else {
1549
- this.emitLifecycleErrorEvent(result.output || result.error || "Unknown error", assistantBuffer.text, eventContext);
1965
+ result.output = this.emitLifecycleErrorEvent(result.output || result.error || "Unknown error", assistantBuffer.text, eventContext);
1550
1966
  this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
1551
1967
  }
1552
1968
  return {
@@ -1557,13 +1973,11 @@ export class ChatRunner {
1557
1973
  }
1558
1974
  catch (err) {
1559
1975
  const message = err instanceof Error ? err.message : String(err);
1560
- this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
1976
+ const output = this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
1561
1977
  this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
1562
1978
  return {
1563
1979
  success: false,
1564
- output: assistantBuffer.text
1565
- ? `${assistantBuffer.text}\n\n[interrupted: ${message}]`
1566
- : `Error: ${message}`,
1980
+ output,
1567
1981
  elapsed_ms: Date.now() - start,
1568
1982
  };
1569
1983
  }
@@ -1571,12 +1985,18 @@ export class ChatRunner {
1571
1985
  // Prefer the local LLM/tool loop over the external adapter fallback whenever a client is available.
1572
1986
  if (selectedRoute?.kind === "tool_loop") {
1573
1987
  try {
1988
+ this.emitCheckpoint("Tool loop started", "The model will choose tools from the active catalog.", eventContext, "execution");
1574
1989
  const toolResult = await this.executeWithTools(prompt, eventContext, assistantBuffer, systemPrompt || undefined, executionGoalId);
1575
1990
  const elapsed_ms = Date.now() - start;
1576
1991
  if (this.hasUsage(toolResult.usage)) {
1577
1992
  history.recordUsage("execution", toolResult.usage);
1578
1993
  }
1994
+ const diffArtifact = await collectGitDiffArtifact(gitRoot);
1995
+ if (diffArtifact) {
1996
+ this.emitDiffArtifact(diffArtifact, eventContext);
1997
+ }
1579
1998
  await history.appendAssistantMessage(toolResult.output);
1999
+ this.emitCheckpoint("Response ready", "The tool-loop response has been persisted for this turn.", eventContext, "complete");
1580
2000
  this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
1581
2001
  this.emitEvent({
1582
2002
  type: "assistant_final",
@@ -1589,21 +2009,18 @@ export class ChatRunner {
1589
2009
  }
1590
2010
  catch (err) {
1591
2011
  const message = err instanceof Error ? err.message : String(err);
1592
- this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
2012
+ const output = this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
1593
2013
  this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
1594
2014
  return {
1595
2015
  success: false,
1596
- output: assistantBuffer.text
1597
- ? `${assistantBuffer.text}\n\n[interrupted: ${message}]`
1598
- : `Error: ${message}`,
2016
+ output,
1599
2017
  elapsed_ms: Date.now() - start,
1600
2018
  };
1601
2019
  }
1602
2020
  }
1603
2021
  if (!resumeOnly && selectedRoute && selectedRoute.kind !== "adapter") {
1604
2022
  const elapsed_ms = Date.now() - start;
1605
- const output = `Unsupported chat route: ${selectedRoute.kind}`;
1606
- this.emitLifecycleErrorEvent(output, assistantBuffer.text, eventContext);
2023
+ const output = this.emitLifecycleErrorEvent(`Unsupported chat route: ${selectedRoute.kind}`, assistantBuffer.text, eventContext);
1607
2024
  this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
1608
2025
  return {
1609
2026
  success: false,
@@ -1619,10 +2036,25 @@ export class ChatRunner {
1619
2036
  ...(systemPrompt ? { system_prompt: systemPrompt } : {}),
1620
2037
  };
1621
2038
  const resolvedTimeoutMs = task.timeout_ms ?? DEFAULT_TIMEOUT_MS;
2039
+ this.emitCheckpoint("Adapter started", "The configured adapter has the current prompt and project context.", eventContext, "execution");
1622
2040
  this.emitActivity("lifecycle", "Calling adapter...", eventContext, "lifecycle:adapter");
1623
2041
  const adapterPromise = this.deps.adapter.execute(task);
1624
2042
  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]);
2043
+ let result;
2044
+ try {
2045
+ result = await Promise.race([adapterPromise, timeoutPromise]);
2046
+ }
2047
+ catch (err) {
2048
+ const message = err instanceof Error ? err.message : String(err);
2049
+ const output = this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
2050
+ const timeoutElapsedMs = Date.now() - start;
2051
+ this.emitLifecycleEndEvent("error", timeoutElapsedMs, eventContext, false);
2052
+ return {
2053
+ success: false,
2054
+ output,
2055
+ elapsed_ms: timeoutElapsedMs,
2056
+ };
2057
+ }
1626
2058
  // Surface adapter errors into output when output is empty
1627
2059
  if (!result.output && result.error) {
1628
2060
  result = { ...result, output: `Error: ${result.error}` };
@@ -1632,34 +2064,47 @@ export class ChatRunner {
1632
2064
  this.pushAssistantDelta(result.output, assistantBuffer, eventContext);
1633
2065
  }
1634
2066
  // Verification loop: check if git has uncommitted changes; if so, run tests
1635
- const gitChanges = await checkGitChanges(gitRoot);
1636
- if (gitChanges !== null && gitChanges !== "") {
2067
+ const diffArtifact = await collectGitDiffArtifact(gitRoot);
2068
+ if (diffArtifact) {
1637
2069
  let retries = 0;
1638
2070
  const VERIFY_TIMEOUT_MS = 30_000;
2071
+ this.emitCheckpoint("Changes detected", "Verification is starting because the turn changed the working tree.", eventContext, "changes");
1639
2072
  this.emitActivity("lifecycle", "Checking result...", eventContext, "lifecycle:checking");
1640
2073
  let verification = await Promise.race([
1641
- verifyChatAction(gitRoot, this.deps.toolExecutor),
2074
+ verifyChatAction(gitRoot, this.deps.toolExecutor, { force: true }),
1642
2075
  new Promise((resolve) => setTimeout(() => resolve({ passed: true }), VERIFY_TIMEOUT_MS)),
1643
2076
  ]);
1644
2077
  while (!verification.passed && retries < MAX_VERIFY_RETRIES) {
1645
2078
  retries++;
2079
+ this.emitCheckpoint("Verification retry", `Attempt ${retries} of ${MAX_VERIFY_RETRIES} is repairing failed checks.`, eventContext, `verification-retry-${retries}`);
1646
2080
  const retryPrompt = `The previous changes caused test failures. Please fix them.\n\nTest output:\n${verification.testOutput ?? verification.errors.join("\n")}`;
1647
2081
  const retryTask = { ...task, prompt: retryPrompt };
1648
2082
  result = await this.deps.adapter.execute(retryTask);
1649
- verification = await verifyChatAction(gitRoot, this.deps.toolExecutor);
2083
+ verification = await verifyChatAction(gitRoot, this.deps.toolExecutor, { force: true });
1650
2084
  }
1651
2085
  if (!verification.passed) {
1652
- this.emitLifecycleErrorEvent(`Changes applied but tests are still failing after ${MAX_VERIFY_RETRIES} retries.`, assistantBuffer.text, eventContext);
2086
+ const finalDiffArtifact = await collectGitDiffArtifact(gitRoot);
2087
+ if (finalDiffArtifact) {
2088
+ this.emitDiffArtifact(finalDiffArtifact, eventContext);
2089
+ }
2090
+ this.emitCheckpoint("Verification failed", `Checks are still failing after ${MAX_VERIFY_RETRIES} retries.`, eventContext, "verification");
2091
+ const failureOutput = this.emitLifecycleErrorEvent(`Changes applied but tests are still failing after ${MAX_VERIFY_RETRIES} retries.`, assistantBuffer.text, eventContext);
1653
2092
  this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
1654
2093
  return {
1655
2094
  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(),
2095
+ output: `${failureOutput}\n\nTest output:\n${verification.testOutput ?? verification.errors.join("\n")}`.trim(),
1657
2096
  elapsed_ms: Date.now() - start,
1658
2097
  };
1659
2098
  }
2099
+ const finalDiffArtifact = await collectGitDiffArtifact(gitRoot);
2100
+ if (finalDiffArtifact) {
2101
+ this.emitDiffArtifact(finalDiffArtifact, eventContext);
2102
+ }
2103
+ this.emitCheckpoint("Verification passed", "Changed files passed the configured chat verification.", eventContext, "verification");
1660
2104
  }
1661
2105
  if (result.success) {
1662
2106
  await history.appendAssistantMessage(result.output);
2107
+ this.emitCheckpoint("Response ready", "The assistant response has been persisted for this turn.", eventContext, "complete");
1663
2108
  this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
1664
2109
  this.emitEvent({
1665
2110
  type: "assistant_final",
@@ -1671,7 +2116,7 @@ export class ChatRunner {
1671
2116
  }
1672
2117
  else {
1673
2118
  const partialText = assistantBuffer.text !== result.output ? assistantBuffer.text : "";
1674
- this.emitLifecycleErrorEvent(result.output || result.error || "Unknown error", partialText, eventContext);
2119
+ result.output = this.emitLifecycleErrorEvent(result.output || result.error || "Unknown error", partialText, eventContext);
1675
2120
  this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
1676
2121
  }
1677
2122
  return {
@@ -1854,6 +2299,7 @@ export class ChatRunner {
1854
2299
  }
1855
2300
  if (event.type === "plan_update") {
1856
2301
  this.emitActivity("tool", `Updated plan: ${previewActivityText(event.summary)}`, eventContext, `plan:${event.turnId}`);
2302
+ this.emitCheckpoint("Plan updated", previewActivityText(event.summary, 160), eventContext, `plan:${event.eventId}`);
1857
2303
  this.emitEvent({
1858
2304
  type: "tool_update",
1859
2305
  toolCallId: `plan:${event.turnId}:${event.createdAt}`,
@@ -1866,6 +2312,7 @@ export class ChatRunner {
1866
2312
  }
1867
2313
  if (event.type === "approval_request") {
1868
2314
  this.emitActivity("tool", formatToolActivity("Running", event.toolName, `awaiting approval: ${event.reason}`), eventContext, event.callId);
2315
+ this.emitCheckpoint("Approval requested", `${event.toolName}: ${event.reason}`, eventContext, `approval:${event.callId}`);
1869
2316
  this.emitEvent({
1870
2317
  type: "tool_update",
1871
2318
  toolCallId: event.callId,
@@ -1924,6 +2371,34 @@ export class ChatRunner {
1924
2371
  }
1925
2372
  return preview ? { preview } : {};
1926
2373
  }
2374
+ async resolveChatResumeSelector(selector) {
2375
+ if (selector.startsWith("session:conversation:")) {
2376
+ return { chatSelector: selector.slice("session:conversation:".length) };
2377
+ }
2378
+ if (selector.startsWith("session:") || selector.startsWith("run:")) {
2379
+ const registry = createRuntimeSessionRegistry({ stateManager: this.deps.stateManager });
2380
+ if (selector.startsWith("session:")) {
2381
+ const session = await registry.getSession(selector);
2382
+ if (session?.kind === "conversation") {
2383
+ return { chatSelector: selector.slice("session:conversation:".length) };
2384
+ }
2385
+ if (session?.kind === "agent"
2386
+ && session.resumable
2387
+ && session.parent_session_id?.startsWith("session:conversation:")) {
2388
+ return { chatSelector: session.parent_session_id.slice("session:conversation:".length) };
2389
+ }
2390
+ return {
2391
+ chatSelector: selector,
2392
+ nonResumableMessage: `Runtime session ${selector} is not chat-resumable. Inspect it with 'pulseed runtime session ${selector}'.`,
2393
+ };
2394
+ }
2395
+ return {
2396
+ chatSelector: selector,
2397
+ nonResumableMessage: `Background run ${selector} is not chat-resumable. Inspect it with 'pulseed runtime run ${selector}'.`,
2398
+ };
2399
+ }
2400
+ return { chatSelector: selector };
2401
+ }
1927
2402
  parseResumeCommand(input) {
1928
2403
  const trimmed = input.trim();
1929
2404
  const match = /^\/resume(?:\s+(.+))?$/i.exec(trimmed);
@@ -2134,11 +2609,81 @@ export class ChatRunner {
2134
2609
  eventBase(context) {
2135
2610
  return { ...context, createdAt: new Date().toISOString() };
2136
2611
  }
2612
+ beginActiveTurn(context, cwd) {
2613
+ let resolveFinished = () => { };
2614
+ const finished = new Promise((resolve) => {
2615
+ resolveFinished = resolve;
2616
+ });
2617
+ const turn = {
2618
+ context,
2619
+ cwd,
2620
+ startedAt: Date.now(),
2621
+ abortController: new AbortController(),
2622
+ finished,
2623
+ resolveFinished,
2624
+ recentEvents: [],
2625
+ interruptRequested: false,
2626
+ };
2627
+ this.activeTurn = turn;
2628
+ return turn;
2629
+ }
2630
+ finishActiveTurn(context) {
2631
+ const activeTurn = this.activeTurn;
2632
+ if (!activeTurn || activeTurn.context.runId !== context.runId)
2633
+ return;
2634
+ activeTurn.resolveFinished();
2635
+ this.activeTurn = null;
2636
+ }
2637
+ waitForActiveTurn(turn, timeoutMs) {
2638
+ return Promise.race([
2639
+ turn.finished.then(() => true),
2640
+ new Promise((resolve) => setTimeout(() => resolve(false), timeoutMs)),
2641
+ ]);
2642
+ }
2643
+ emitEphemeralAssistantResult(input, output, success, start) {
2644
+ const context = this.createEventContext();
2645
+ this.emitEvent({
2646
+ type: "lifecycle_start",
2647
+ input,
2648
+ ...this.eventBase(context),
2649
+ });
2650
+ this.emitEvent({
2651
+ type: "assistant_final",
2652
+ text: output,
2653
+ persisted: false,
2654
+ ...this.eventBase(context),
2655
+ });
2656
+ const elapsed_ms = Date.now() - start;
2657
+ this.emitLifecycleEndEvent(success ? "completed" : "error", elapsed_ms, context, false);
2658
+ return { success, output, elapsed_ms };
2659
+ }
2660
+ rememberActiveTurnEvent(event) {
2661
+ const activeTurn = this.activeTurn;
2662
+ if (!activeTurn || activeTurn.context.turnId !== event.turnId)
2663
+ return;
2664
+ let summary = null;
2665
+ if (event.type === "activity") {
2666
+ summary = previewActivityText(event.message, 140);
2667
+ }
2668
+ else if (event.type === "tool_start") {
2669
+ summary = `Started ${event.toolName}`;
2670
+ }
2671
+ else if (event.type === "tool_update") {
2672
+ summary = `${event.toolName}: ${previewActivityText(event.message, 100)}`;
2673
+ }
2674
+ else if (event.type === "tool_end") {
2675
+ summary = `${event.success ? "Finished" : "Failed"} ${event.toolName}: ${previewActivityText(event.summary, 100)}`;
2676
+ }
2677
+ if (!summary)
2678
+ return;
2679
+ activeTurn.recentEvents = [...activeTurn.recentEvents, summary].slice(-12);
2680
+ }
2137
2681
  emitEvent(event) {
2682
+ this.rememberActiveTurnEvent(event);
2138
2683
  const handler = this.onEvent ?? this.deps.onEvent;
2139
2684
  handler?.(event);
2140
2685
  }
2141
- emitActivity(kind, message, eventContext, sourceId) {
2686
+ emitActivity(kind, message, eventContext, sourceId, transient = true) {
2142
2687
  if (!message.trim())
2143
2688
  return;
2144
2689
  this.emitEvent({
@@ -2146,10 +2691,72 @@ export class ChatRunner {
2146
2691
  kind,
2147
2692
  message,
2148
2693
  ...(sourceId ? { sourceId } : {}),
2149
- transient: true,
2694
+ transient,
2150
2695
  ...this.eventBase(eventContext),
2151
2696
  });
2152
2697
  }
2698
+ emitIntent(input, selectedRoute, eventContext) {
2699
+ const subject = formatIntentInput(input);
2700
+ let nextStep = "resume the saved agent loop state before continuing.";
2701
+ let reason = "resume needs the prior runtime context before any further action.";
2702
+ if (selectedRoute?.kind === "runtime_control") {
2703
+ nextStep = `prepare the ${selectedRoute.intent.kind} runtime-control request.`;
2704
+ reason = "runtime changes need an explicit operation plan and approval path.";
2705
+ }
2706
+ else if (selectedRoute?.kind === "daemon_tend") {
2707
+ nextStep = "convert the request into a daemon-backed CoreLoop goal confirmation.";
2708
+ reason = "long-running work should survive chat turn timeouts and run through durable runtime state.";
2709
+ }
2710
+ else if (selectedRoute?.kind === "direct_answer") {
2711
+ nextStep = "ask the lightweight model for a concise direct answer.";
2712
+ reason = "the router classified this as a simple question that does not need tools.";
2713
+ }
2714
+ else if (selectedRoute?.kind === "agent_loop") {
2715
+ nextStep = "gather workspace context, then let the agent loop inspect or change files with visible tool activity.";
2716
+ reason = "this request may require multiple tool-backed steps.";
2717
+ }
2718
+ else if (selectedRoute?.kind === "tool_loop") {
2719
+ nextStep = "call the model with the tool catalog, then execute selected tools with visible activity.";
2720
+ reason = "the available tools are needed to answer from current project state.";
2721
+ }
2722
+ else if (selectedRoute?.kind === "adapter") {
2723
+ nextStep = "prepare project context before handing the turn to the configured adapter.";
2724
+ reason = "the adapter needs the current workspace context to act correctly.";
2725
+ }
2726
+ const message = [
2727
+ "Intent",
2728
+ `- Confirm: ${subject || "the current request"}`,
2729
+ `- Next: ${nextStep}`,
2730
+ `- Why: ${reason}`,
2731
+ ].join("\n");
2732
+ this.emitActivity("commentary", message, eventContext, "intent:first-step", false);
2733
+ }
2734
+ emitCheckpoint(title, detail, eventContext, sourceKey) {
2735
+ const message = detail
2736
+ ? `Checkpoint\n- ${title}: ${detail}`
2737
+ : `Checkpoint\n- ${title}`;
2738
+ this.emitActivity("checkpoint", message, eventContext, `checkpoint:${sourceKey}`, false);
2739
+ }
2740
+ emitDiffArtifact(artifact, eventContext) {
2741
+ const sections = [
2742
+ "Changed files",
2743
+ "",
2744
+ "Modified files",
2745
+ artifact.nameStatus || artifact.stat,
2746
+ "",
2747
+ "Diff summary",
2748
+ artifact.stat,
2749
+ "",
2750
+ "Inline patch",
2751
+ "```diff",
2752
+ artifact.patch || "(patch unavailable)",
2753
+ artifact.truncated ? `... truncated after ${DIFF_ARTIFACT_MAX_LINES} lines; run /review for the full diff.` : "",
2754
+ "```",
2755
+ "",
2756
+ "Files inspected are shown separately in the activity log.",
2757
+ ].filter((line) => line !== "").join("\n");
2758
+ this.emitActivity("diff", sections, eventContext, "diff:working-tree", false);
2759
+ }
2153
2760
  pushAssistantDelta(delta, assistantBuffer, eventContext) {
2154
2761
  if (!delta)
2155
2762
  return;
@@ -2169,15 +2776,19 @@ export class ChatRunner {
2169
2776
  persisted,
2170
2777
  ...this.eventBase(eventContext),
2171
2778
  });
2779
+ this.finishActiveTurn(eventContext);
2172
2780
  }
2173
2781
  emitLifecycleErrorEvent(error, partialText, eventContext) {
2782
+ const recovery = classifyFailureRecovery(error);
2174
2783
  this.emitEvent({
2175
2784
  type: "lifecycle_error",
2176
2785
  error,
2177
2786
  partialText,
2178
2787
  persisted: false,
2788
+ recovery,
2179
2789
  ...this.eventBase(eventContext),
2180
2790
  });
2791
+ return formatLifecycleFailureMessage(error, partialText, recovery);
2181
2792
  }
2182
2793
  /** Build a ToolCallContext from ChatRunnerDeps for tool dispatch. */
2183
2794
  async getSessionExecutionPolicy() {