pulseed 0.5.1 → 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 (573) hide show
  1. package/dist/adapters/types/a2a.d.ts +6 -6
  2. package/dist/base/config/identity-loader.d.ts +6 -0
  3. package/dist/base/config/identity-loader.d.ts.map +1 -1
  4. package/dist/base/config/identity-loader.js +34 -8
  5. package/dist/base/config/identity-loader.js.map +1 -1
  6. package/dist/grounding/gateway.d.ts.map +1 -1
  7. package/dist/grounding/gateway.js +2 -1
  8. package/dist/grounding/gateway.js.map +1 -1
  9. package/dist/grounding/providers/static-policy-provider.d.ts +1 -1
  10. package/dist/grounding/providers/static-policy-provider.d.ts.map +1 -1
  11. package/dist/grounding/providers/static-policy-provider.js +12 -8
  12. package/dist/grounding/providers/static-policy-provider.js.map +1 -1
  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-runner.d.ts +25 -1
  24. package/dist/interface/chat/chat-runner.d.ts.map +1 -1
  25. package/dist/interface/chat/chat-runner.js +751 -83
  26. package/dist/interface/chat/chat-runner.js.map +1 -1
  27. package/dist/interface/chat/chat-verifier.d.ts +3 -1
  28. package/dist/interface/chat/chat-verifier.d.ts.map +1 -1
  29. package/dist/interface/chat/chat-verifier.js +2 -2
  30. package/dist/interface/chat/chat-verifier.js.map +1 -1
  31. package/dist/interface/chat/cross-platform-session.d.ts +4 -0
  32. package/dist/interface/chat/cross-platform-session.d.ts.map +1 -1
  33. package/dist/interface/chat/cross-platform-session.js +33 -0
  34. package/dist/interface/chat/cross-platform-session.js.map +1 -1
  35. package/dist/interface/chat/failure-recovery.d.ts +11 -0
  36. package/dist/interface/chat/failure-recovery.d.ts.map +1 -0
  37. package/dist/interface/chat/failure-recovery.js +115 -0
  38. package/dist/interface/chat/failure-recovery.js.map +1 -0
  39. package/dist/interface/chat/grounding.d.ts +1 -1
  40. package/dist/interface/chat/grounding.d.ts.map +1 -1
  41. package/dist/interface/chat/grounding.js +2 -2
  42. package/dist/interface/chat/grounding.js.map +1 -1
  43. package/dist/interface/chat/ingress-router.d.ts +11 -0
  44. package/dist/interface/chat/ingress-router.d.ts.map +1 -1
  45. package/dist/interface/chat/ingress-router.js +46 -2
  46. package/dist/interface/chat/ingress-router.js.map +1 -1
  47. package/dist/interface/chat/tend-command.d.ts +8 -0
  48. package/dist/interface/chat/tend-command.d.ts.map +1 -1
  49. package/dist/interface/chat/tend-command.js +80 -4
  50. package/dist/interface/chat/tend-command.js.map +1 -1
  51. package/dist/interface/cli/cli-command-registry.d.ts.map +1 -1
  52. package/dist/interface/cli/cli-command-registry.js +4 -0
  53. package/dist/interface/cli/cli-command-registry.js.map +1 -1
  54. package/dist/interface/cli/commands/daemon.d.ts.map +1 -1
  55. package/dist/interface/cli/commands/daemon.js +41 -7
  56. package/dist/interface/cli/commands/daemon.js.map +1 -1
  57. package/dist/interface/cli/commands/runtime.d.ts +3 -0
  58. package/dist/interface/cli/commands/runtime.d.ts.map +1 -0
  59. package/dist/interface/cli/commands/runtime.js +231 -0
  60. package/dist/interface/cli/commands/runtime.js.map +1 -0
  61. package/dist/interface/cli/commands/setup/steps-identity.d.ts.map +1 -1
  62. package/dist/interface/cli/commands/setup/steps-identity.js +5 -0
  63. package/dist/interface/cli/commands/setup/steps-identity.js.map +1 -1
  64. package/dist/interface/cli/commands/setup/steps-runtime.d.ts +2 -0
  65. package/dist/interface/cli/commands/setup/steps-runtime.d.ts.map +1 -1
  66. package/dist/interface/cli/commands/setup/steps-runtime.js +11 -2
  67. package/dist/interface/cli/commands/setup/steps-runtime.js.map +1 -1
  68. package/dist/interface/cli/setup.d.ts.map +1 -1
  69. package/dist/interface/cli/setup.js +14 -1
  70. package/dist/interface/cli/setup.js.map +1 -1
  71. package/dist/interface/cli/utils.d.ts.map +1 -1
  72. package/dist/interface/cli/utils.js +4 -0
  73. package/dist/interface/cli/utils.js.map +1 -1
  74. package/dist/interface/tui/app.d.ts +2 -0
  75. package/dist/interface/tui/app.d.ts.map +1 -1
  76. package/dist/interface/tui/app.js +73 -16
  77. package/dist/interface/tui/app.js.map +1 -1
  78. package/dist/interface/tui/chat/scroll.d.ts +3 -0
  79. package/dist/interface/tui/chat/scroll.d.ts.map +1 -1
  80. package/dist/interface/tui/chat/scroll.js +15 -0
  81. package/dist/interface/tui/chat/scroll.js.map +1 -1
  82. package/dist/interface/tui/chat/types.d.ts +1 -1
  83. package/dist/interface/tui/chat/types.d.ts.map +1 -1
  84. package/dist/interface/tui/chat/viewport.d.ts.map +1 -1
  85. package/dist/interface/tui/chat/viewport.js +8 -2
  86. package/dist/interface/tui/chat/viewport.js.map +1 -1
  87. package/dist/interface/tui/chat-surface.d.ts +2 -0
  88. package/dist/interface/tui/chat-surface.d.ts.map +1 -1
  89. package/dist/interface/tui/chat-surface.js +11 -0
  90. package/dist/interface/tui/chat-surface.js.map +1 -1
  91. package/dist/interface/tui/chat.d.ts.map +1 -1
  92. package/dist/interface/tui/chat.js +15 -7
  93. package/dist/interface/tui/chat.js.map +1 -1
  94. package/dist/interface/tui/clipboard.d.ts +6 -1
  95. package/dist/interface/tui/clipboard.d.ts.map +1 -1
  96. package/dist/interface/tui/clipboard.js +24 -5
  97. package/dist/interface/tui/clipboard.js.map +1 -1
  98. package/dist/interface/tui/entry.d.ts.map +1 -1
  99. package/dist/interface/tui/entry.js +28 -3
  100. package/dist/interface/tui/entry.js.map +1 -1
  101. package/dist/interface/tui/flicker/MouseTracking.d.ts +1 -1
  102. package/dist/interface/tui/flicker/MouseTracking.d.ts.map +1 -1
  103. package/dist/interface/tui/flicker/MouseTracking.js +8 -4
  104. package/dist/interface/tui/flicker/MouseTracking.js.map +1 -1
  105. package/dist/interface/tui/fullscreen-chat.d.ts +86 -5
  106. package/dist/interface/tui/fullscreen-chat.d.ts.map +1 -1
  107. package/dist/interface/tui/fullscreen-chat.js +586 -32
  108. package/dist/interface/tui/fullscreen-chat.js.map +1 -1
  109. package/dist/interface/tui/help-overlay.d.ts.map +1 -1
  110. package/dist/interface/tui/help-overlay.js +1 -1
  111. package/dist/interface/tui/help-overlay.js.map +1 -1
  112. package/dist/interface/tui/markdown-renderer.d.ts.map +1 -1
  113. package/dist/interface/tui/markdown-renderer.js +40 -12
  114. package/dist/interface/tui/markdown-renderer.js.map +1 -1
  115. package/dist/interface/tui/test-entry.js +1 -1
  116. package/dist/interface/tui/test-entry.js.map +1 -1
  117. package/dist/orchestrator/execution/adapter-layer.d.ts +2 -0
  118. package/dist/orchestrator/execution/adapter-layer.d.ts.map +1 -1
  119. package/dist/orchestrator/execution/adapter-layer.js.map +1 -1
  120. package/dist/orchestrator/execution/agent-loop/agent-loop-context-assembler.d.ts.map +1 -1
  121. package/dist/orchestrator/execution/agent-loop/agent-loop-context-assembler.js +1 -0
  122. package/dist/orchestrator/execution/agent-loop/agent-loop-context-assembler.js.map +1 -1
  123. package/dist/orchestrator/execution/agent-loop/agent-loop-default-profile.d.ts.map +1 -1
  124. package/dist/orchestrator/execution/agent-loop/agent-loop-default-profile.js +53 -12
  125. package/dist/orchestrator/execution/agent-loop/agent-loop-default-profile.js.map +1 -1
  126. package/dist/orchestrator/execution/agent-loop/agent-loop-dogfood-benchmark.d.ts.map +1 -1
  127. package/dist/orchestrator/execution/agent-loop/agent-loop-dogfood-benchmark.js +7 -4
  128. package/dist/orchestrator/execution/agent-loop/agent-loop-dogfood-benchmark.js.map +1 -1
  129. package/dist/orchestrator/execution/agent-loop/agent-loop-prompts.d.ts +1 -0
  130. package/dist/orchestrator/execution/agent-loop/agent-loop-prompts.d.ts.map +1 -1
  131. package/dist/orchestrator/execution/agent-loop/agent-loop-prompts.js +10 -3
  132. package/dist/orchestrator/execution/agent-loop/agent-loop-prompts.js.map +1 -1
  133. package/dist/orchestrator/execution/agent-loop/agent-loop-session-factory.d.ts.map +1 -1
  134. package/dist/orchestrator/execution/agent-loop/agent-loop-session-factory.js +2 -1
  135. package/dist/orchestrator/execution/agent-loop/agent-loop-session-factory.js.map +1 -1
  136. package/dist/orchestrator/execution/agent-loop/agent-loop-turn-context.d.ts +2 -0
  137. package/dist/orchestrator/execution/agent-loop/agent-loop-turn-context.d.ts.map +1 -1
  138. package/dist/orchestrator/execution/agent-loop/agent-loop-turn-context.js.map +1 -1
  139. package/dist/orchestrator/execution/agent-loop/bounded-agent-loop-runner.d.ts.map +1 -1
  140. package/dist/orchestrator/execution/agent-loop/bounded-agent-loop-runner.js +51 -0
  141. package/dist/orchestrator/execution/agent-loop/bounded-agent-loop-runner.js.map +1 -1
  142. package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.d.ts +13 -4
  143. package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.d.ts.map +1 -1
  144. package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.js +44 -126
  145. package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.js.map +1 -1
  146. package/dist/orchestrator/execution/agent-loop/chat-display-output.d.ts +27 -0
  147. package/dist/orchestrator/execution/agent-loop/chat-display-output.d.ts.map +1 -0
  148. package/dist/orchestrator/execution/agent-loop/chat-display-output.js +157 -0
  149. package/dist/orchestrator/execution/agent-loop/chat-display-output.js.map +1 -0
  150. package/dist/orchestrator/execution/agent-loop/core-phase-runner.d.ts +1 -1
  151. package/dist/orchestrator/execution/agent-loop/core-phase-runner.d.ts.map +1 -1
  152. package/dist/orchestrator/execution/agent-loop/core-phase-runner.js.map +1 -1
  153. package/dist/orchestrator/execution/agent-loop/index.d.ts +1 -0
  154. package/dist/orchestrator/execution/agent-loop/index.d.ts.map +1 -1
  155. package/dist/orchestrator/execution/agent-loop/index.js +1 -0
  156. package/dist/orchestrator/execution/agent-loop/index.js.map +1 -1
  157. package/dist/orchestrator/execution/agent-loop/kaggle-training-benchmark.d.ts +34 -0
  158. package/dist/orchestrator/execution/agent-loop/kaggle-training-benchmark.d.ts.map +1 -0
  159. package/dist/orchestrator/execution/agent-loop/kaggle-training-benchmark.js +54 -0
  160. package/dist/orchestrator/execution/agent-loop/kaggle-training-benchmark.js.map +1 -0
  161. package/dist/orchestrator/execution/agent-loop/task-agent-loop-factory.d.ts +2 -0
  162. package/dist/orchestrator/execution/agent-loop/task-agent-loop-factory.d.ts.map +1 -1
  163. package/dist/orchestrator/execution/agent-loop/task-agent-loop-factory.js +10 -0
  164. package/dist/orchestrator/execution/agent-loop/task-agent-loop-factory.js.map +1 -1
  165. package/dist/orchestrator/goal/goal-suggest.d.ts +4 -4
  166. package/dist/orchestrator/goal/types/goal-tree.d.ts +2 -2
  167. package/dist/orchestrator/loop/core-loop/contracts.d.ts +19 -0
  168. package/dist/orchestrator/loop/core-loop/contracts.d.ts.map +1 -1
  169. package/dist/orchestrator/loop/core-loop/contracts.js.map +1 -1
  170. package/dist/orchestrator/loop/core-loop/iteration-kernel.d.ts +1 -0
  171. package/dist/orchestrator/loop/core-loop/iteration-kernel.d.ts.map +1 -1
  172. package/dist/orchestrator/loop/core-loop/iteration-kernel.js +61 -2
  173. package/dist/orchestrator/loop/core-loop/iteration-kernel.js.map +1 -1
  174. package/dist/orchestrator/loop/core-loop/phase-policy.d.ts.map +1 -1
  175. package/dist/orchestrator/loop/core-loop/phase-policy.js +27 -0
  176. package/dist/orchestrator/loop/core-loop/phase-policy.js.map +1 -1
  177. package/dist/orchestrator/loop/core-loop/phase-specs.d.ts +37 -0
  178. package/dist/orchestrator/loop/core-loop/phase-specs.d.ts.map +1 -1
  179. package/dist/orchestrator/loop/core-loop/phase-specs.js +28 -0
  180. package/dist/orchestrator/loop/core-loop/phase-specs.js.map +1 -1
  181. package/dist/orchestrator/loop/core-loop/task-cycle.d.ts +12 -0
  182. package/dist/orchestrator/loop/core-loop/task-cycle.d.ts.map +1 -1
  183. package/dist/orchestrator/loop/core-loop/task-cycle.js +170 -23
  184. package/dist/orchestrator/loop/core-loop/task-cycle.js.map +1 -1
  185. package/dist/orchestrator/loop/core-loop.d.ts +2 -1
  186. package/dist/orchestrator/loop/core-loop.d.ts.map +1 -1
  187. package/dist/orchestrator/loop/core-loop.js +3 -0
  188. package/dist/orchestrator/loop/core-loop.js.map +1 -1
  189. package/dist/orchestrator/loop/loop-report-helper.d.ts.map +1 -1
  190. package/dist/orchestrator/loop/loop-report-helper.js +24 -0
  191. package/dist/orchestrator/loop/loop-report-helper.js.map +1 -1
  192. package/dist/orchestrator/loop/loop-result-types.d.ts +7 -0
  193. package/dist/orchestrator/loop/loop-result-types.d.ts.map +1 -1
  194. package/dist/orchestrator/loop/loop-result-types.js.map +1 -1
  195. package/dist/orchestrator/strategy/portfolio-manager.d.ts +2 -2
  196. package/dist/orchestrator/strategy/portfolio-manager.d.ts.map +1 -1
  197. package/dist/orchestrator/strategy/portfolio-manager.js +11 -1
  198. package/dist/orchestrator/strategy/portfolio-manager.js.map +1 -1
  199. package/dist/orchestrator/strategy/portfolio-rebalance.d.ts +4 -2
  200. package/dist/orchestrator/strategy/portfolio-rebalance.d.ts.map +1 -1
  201. package/dist/orchestrator/strategy/portfolio-rebalance.js +490 -12
  202. package/dist/orchestrator/strategy/portfolio-rebalance.js.map +1 -1
  203. package/dist/orchestrator/strategy/strategy-manager.js +3 -3
  204. package/dist/orchestrator/strategy/strategy-manager.js.map +1 -1
  205. package/dist/orchestrator/strategy/types/cross-portfolio.d.ts +2 -2
  206. package/dist/orchestrator/strategy/types/portfolio.d.ts +12 -12
  207. package/dist/orchestrator/strategy/types/strategy.d.ts +639 -8
  208. package/dist/orchestrator/strategy/types/strategy.d.ts.map +1 -1
  209. package/dist/orchestrator/strategy/types/strategy.js +122 -0
  210. package/dist/orchestrator/strategy/types/strategy.js.map +1 -1
  211. package/dist/platform/code-search/candidate-normalizer.d.ts +3 -0
  212. package/dist/platform/code-search/candidate-normalizer.d.ts.map +1 -0
  213. package/dist/platform/code-search/candidate-normalizer.js +61 -0
  214. package/dist/platform/code-search/candidate-normalizer.js.map +1 -0
  215. package/dist/platform/code-search/candidate.d.ts +25 -0
  216. package/dist/platform/code-search/candidate.d.ts.map +1 -0
  217. package/dist/platform/code-search/candidate.js +61 -0
  218. package/dist/platform/code-search/candidate.js.map +1 -0
  219. package/dist/platform/code-search/contracts.d.ts +275 -0
  220. package/dist/platform/code-search/contracts.d.ts.map +1 -0
  221. package/dist/platform/code-search/contracts.js +22 -0
  222. package/dist/platform/code-search/contracts.js.map +1 -0
  223. package/dist/platform/code-search/eval/fixtures.d.ts +14 -0
  224. package/dist/platform/code-search/eval/fixtures.d.ts.map +1 -0
  225. package/dist/platform/code-search/eval/fixtures.js +24 -0
  226. package/dist/platform/code-search/eval/fixtures.js.map +1 -0
  227. package/dist/platform/code-search/eval/metrics.d.ts +10 -0
  228. package/dist/platform/code-search/eval/metrics.d.ts.map +1 -0
  229. package/dist/platform/code-search/eval/metrics.js +20 -0
  230. package/dist/platform/code-search/eval/metrics.js.map +1 -0
  231. package/dist/platform/code-search/eval/runner.d.ts +3 -0
  232. package/dist/platform/code-search/eval/runner.d.ts.map +1 -0
  233. package/dist/platform/code-search/eval/runner.js +13 -0
  234. package/dist/platform/code-search/eval/runner.js.map +1 -0
  235. package/dist/platform/code-search/fusion.d.ts +6 -0
  236. package/dist/platform/code-search/fusion.d.ts.map +1 -0
  237. package/dist/platform/code-search/fusion.js +12 -0
  238. package/dist/platform/code-search/fusion.js.map +1 -0
  239. package/dist/platform/code-search/generated-detector.d.ts +15 -0
  240. package/dist/platform/code-search/generated-detector.d.ts.map +1 -0
  241. package/dist/platform/code-search/generated-detector.js +42 -0
  242. package/dist/platform/code-search/generated-detector.js.map +1 -0
  243. package/dist/platform/code-search/indexes/call-graph.d.ts +3 -0
  244. package/dist/platform/code-search/indexes/call-graph.d.ts.map +1 -0
  245. package/dist/platform/code-search/indexes/call-graph.js +13 -0
  246. package/dist/platform/code-search/indexes/call-graph.js.map +1 -0
  247. package/dist/platform/code-search/indexes/config-index.d.ts +3 -0
  248. package/dist/platform/code-search/indexes/config-index.d.ts.map +1 -0
  249. package/dist/platform/code-search/indexes/config-index.js +7 -0
  250. package/dist/platform/code-search/indexes/config-index.js.map +1 -0
  251. package/dist/platform/code-search/indexes/file-index.d.ts +5 -0
  252. package/dist/platform/code-search/indexes/file-index.d.ts.map +1 -0
  253. package/dist/platform/code-search/indexes/file-index.js +106 -0
  254. package/dist/platform/code-search/indexes/file-index.js.map +1 -0
  255. package/dist/platform/code-search/indexes/index-store.d.ts +6 -0
  256. package/dist/platform/code-search/indexes/index-store.d.ts.map +1 -0
  257. package/dist/platform/code-search/indexes/index-store.js +14 -0
  258. package/dist/platform/code-search/indexes/index-store.js.map +1 -0
  259. package/dist/platform/code-search/indexes/indexer.d.ts +3 -0
  260. package/dist/platform/code-search/indexes/indexer.d.ts.map +1 -0
  261. package/dist/platform/code-search/indexes/indexer.js +27 -0
  262. package/dist/platform/code-search/indexes/indexer.js.map +1 -0
  263. package/dist/platform/code-search/indexes/package-graph.d.ts +3 -0
  264. package/dist/platform/code-search/indexes/package-graph.d.ts.map +1 -0
  265. package/dist/platform/code-search/indexes/package-graph.js +26 -0
  266. package/dist/platform/code-search/indexes/package-graph.js.map +1 -0
  267. package/dist/platform/code-search/indexes/repo-map-index.d.ts +3 -0
  268. package/dist/platform/code-search/indexes/repo-map-index.d.ts.map +1 -0
  269. package/dist/platform/code-search/indexes/repo-map-index.js +26 -0
  270. package/dist/platform/code-search/indexes/repo-map-index.js.map +1 -0
  271. package/dist/platform/code-search/indexes/semantic-index.d.ts +3 -0
  272. package/dist/platform/code-search/indexes/semantic-index.d.ts.map +1 -0
  273. package/dist/platform/code-search/indexes/semantic-index.js +4 -0
  274. package/dist/platform/code-search/indexes/semantic-index.js.map +1 -0
  275. package/dist/platform/code-search/indexes/symbol-index.d.ts +3 -0
  276. package/dist/platform/code-search/indexes/symbol-index.d.ts.map +1 -0
  277. package/dist/platform/code-search/indexes/symbol-index.js +84 -0
  278. package/dist/platform/code-search/indexes/symbol-index.js.map +1 -0
  279. package/dist/platform/code-search/indexes/test-index.d.ts +3 -0
  280. package/dist/platform/code-search/indexes/test-index.d.ts.map +1 -0
  281. package/dist/platform/code-search/indexes/test-index.js +22 -0
  282. package/dist/platform/code-search/indexes/test-index.js.map +1 -0
  283. package/dist/platform/code-search/orchestrator.d.ts +9 -0
  284. package/dist/platform/code-search/orchestrator.d.ts.map +1 -0
  285. package/dist/platform/code-search/orchestrator.js +81 -0
  286. package/dist/platform/code-search/orchestrator.js.map +1 -0
  287. package/dist/platform/code-search/path-policy.d.ts +6 -0
  288. package/dist/platform/code-search/path-policy.d.ts.map +1 -0
  289. package/dist/platform/code-search/path-policy.js +60 -0
  290. package/dist/platform/code-search/path-policy.js.map +1 -0
  291. package/dist/platform/code-search/progressive-reader.d.ts +8 -0
  292. package/dist/platform/code-search/progressive-reader.d.ts.map +1 -0
  293. package/dist/platform/code-search/progressive-reader.js +173 -0
  294. package/dist/platform/code-search/progressive-reader.js.map +1 -0
  295. package/dist/platform/code-search/query-planner.d.ts +4 -0
  296. package/dist/platform/code-search/query-planner.d.ts.map +1 -0
  297. package/dist/platform/code-search/query-planner.js +107 -0
  298. package/dist/platform/code-search/query-planner.js.map +1 -0
  299. package/dist/platform/code-search/reranker.d.ts +4 -0
  300. package/dist/platform/code-search/reranker.d.ts.map +1 -0
  301. package/dist/platform/code-search/reranker.js +57 -0
  302. package/dist/platform/code-search/reranker.js.map +1 -0
  303. package/dist/platform/code-search/retrievers/callgraph-retriever.d.ts +6 -0
  304. package/dist/platform/code-search/retrievers/callgraph-retriever.d.ts.map +1 -0
  305. package/dist/platform/code-search/retrievers/callgraph-retriever.js +31 -0
  306. package/dist/platform/code-search/retrievers/callgraph-retriever.js.map +1 -0
  307. package/dist/platform/code-search/retrievers/config-retriever.d.ts +6 -0
  308. package/dist/platform/code-search/retrievers/config-retriever.d.ts.map +1 -0
  309. package/dist/platform/code-search/retrievers/config-retriever.js +23 -0
  310. package/dist/platform/code-search/retrievers/config-retriever.js.map +1 -0
  311. package/dist/platform/code-search/retrievers/lexical-retriever.d.ts +6 -0
  312. package/dist/platform/code-search/retrievers/lexical-retriever.d.ts.map +1 -0
  313. package/dist/platform/code-search/retrievers/lexical-retriever.js +49 -0
  314. package/dist/platform/code-search/retrievers/lexical-retriever.js.map +1 -0
  315. package/dist/platform/code-search/retrievers/package-retriever.d.ts +6 -0
  316. package/dist/platform/code-search/retrievers/package-retriever.d.ts.map +1 -0
  317. package/dist/platform/code-search/retrievers/package-retriever.js +29 -0
  318. package/dist/platform/code-search/retrievers/package-retriever.js.map +1 -0
  319. package/dist/platform/code-search/retrievers/repo-map-retriever.d.ts +6 -0
  320. package/dist/platform/code-search/retrievers/repo-map-retriever.d.ts.map +1 -0
  321. package/dist/platform/code-search/retrievers/repo-map-retriever.js +30 -0
  322. package/dist/platform/code-search/retrievers/repo-map-retriever.js.map +1 -0
  323. package/dist/platform/code-search/retrievers/semantic-retriever.d.ts +6 -0
  324. package/dist/platform/code-search/retrievers/semantic-retriever.d.ts.map +1 -0
  325. package/dist/platform/code-search/retrievers/semantic-retriever.js +18 -0
  326. package/dist/platform/code-search/retrievers/semantic-retriever.js.map +1 -0
  327. package/dist/platform/code-search/retrievers/stacktrace-retriever.d.ts +6 -0
  328. package/dist/platform/code-search/retrievers/stacktrace-retriever.d.ts.map +1 -0
  329. package/dist/platform/code-search/retrievers/stacktrace-retriever.js +30 -0
  330. package/dist/platform/code-search/retrievers/stacktrace-retriever.js.map +1 -0
  331. package/dist/platform/code-search/retrievers/symbol-retriever.d.ts +6 -0
  332. package/dist/platform/code-search/retrievers/symbol-retriever.d.ts.map +1 -0
  333. package/dist/platform/code-search/retrievers/symbol-retriever.js +32 -0
  334. package/dist/platform/code-search/retrievers/symbol-retriever.js.map +1 -0
  335. package/dist/platform/code-search/retrievers/test-retriever.d.ts +6 -0
  336. package/dist/platform/code-search/retrievers/test-retriever.d.ts.map +1 -0
  337. package/dist/platform/code-search/retrievers/test-retriever.js +30 -0
  338. package/dist/platform/code-search/retrievers/test-retriever.js.map +1 -0
  339. package/dist/platform/code-search/session-store.d.ts +11 -0
  340. package/dist/platform/code-search/session-store.d.ts.map +1 -0
  341. package/dist/platform/code-search/session-store.js +41 -0
  342. package/dist/platform/code-search/session-store.js.map +1 -0
  343. package/dist/platform/code-search/trace.d.ts +9 -0
  344. package/dist/platform/code-search/trace.d.ts.map +1 -0
  345. package/dist/platform/code-search/trace.js +25 -0
  346. package/dist/platform/code-search/trace.js.map +1 -0
  347. package/dist/platform/code-search/verification-retrieval.d.ts +3 -0
  348. package/dist/platform/code-search/verification-retrieval.d.ts.map +1 -0
  349. package/dist/platform/code-search/verification-retrieval.js +33 -0
  350. package/dist/platform/code-search/verification-retrieval.js.map +1 -0
  351. package/dist/platform/dream/dream-types.d.ts +52 -52
  352. package/dist/platform/drive/types/satisficing.d.ts +2 -2
  353. package/dist/platform/knowledge/types/memory-lifecycle.d.ts +2 -2
  354. package/dist/platform/observation/context-provider.d.ts.map +1 -1
  355. package/dist/platform/observation/context-provider.js +37 -0
  356. package/dist/platform/observation/context-provider.js.map +1 -1
  357. package/dist/platform/observation/observation-helpers.d.ts +2 -2
  358. package/dist/platform/observation/workspace-context.d.ts.map +1 -1
  359. package/dist/platform/observation/workspace-context.js +27 -0
  360. package/dist/platform/observation/workspace-context.js.map +1 -1
  361. package/dist/platform/soil/contracts.d.ts +47 -47
  362. package/dist/platform/traits/types/curiosity.d.ts +24 -24
  363. package/dist/prompt/purposes/learning.d.ts +4 -4
  364. package/dist/reporting/report-formatters.d.ts.map +1 -1
  365. package/dist/reporting/report-formatters.js +33 -2
  366. package/dist/reporting/report-formatters.js.map +1 -1
  367. package/dist/reporting/reporting-engine.d.ts.map +1 -1
  368. package/dist/reporting/reporting-engine.js +2 -1
  369. package/dist/reporting/reporting-engine.js.map +1 -1
  370. package/dist/reporting/reporting-types.d.ts +11 -0
  371. package/dist/reporting/reporting-types.d.ts.map +1 -1
  372. package/dist/reporting/types/report.d.ts +72 -4
  373. package/dist/reporting/types/report.d.ts.map +1 -1
  374. package/dist/reporting/types/report.js +10 -0
  375. package/dist/reporting/types/report.js.map +1 -1
  376. package/dist/runtime/approval-broker.d.ts +1 -1
  377. package/dist/runtime/approval-broker.d.ts.map +1 -1
  378. package/dist/runtime/approval-broker.js +1 -2
  379. package/dist/runtime/approval-broker.js.map +1 -1
  380. package/dist/runtime/control/index.d.ts +1 -0
  381. package/dist/runtime/control/index.d.ts.map +1 -1
  382. package/dist/runtime/control/index.js +1 -0
  383. package/dist/runtime/control/index.js.map +1 -1
  384. package/dist/runtime/control/runtime-control-intent.d.ts.map +1 -1
  385. package/dist/runtime/control/runtime-control-intent.js +0 -8
  386. package/dist/runtime/control/runtime-control-intent.js.map +1 -1
  387. package/dist/runtime/control/runtime-control-result-routing.d.ts +28 -0
  388. package/dist/runtime/control/runtime-control-result-routing.d.ts.map +1 -0
  389. package/dist/runtime/control/runtime-control-result-routing.js +47 -0
  390. package/dist/runtime/control/runtime-control-result-routing.js.map +1 -0
  391. package/dist/runtime/control/runtime-control-service.d.ts +2 -1
  392. package/dist/runtime/control/runtime-control-service.d.ts.map +1 -1
  393. package/dist/runtime/control/runtime-control-service.js +32 -4
  394. package/dist/runtime/control/runtime-control-service.js.map +1 -1
  395. package/dist/runtime/daemon/client.d.ts +13 -1
  396. package/dist/runtime/daemon/client.d.ts.map +1 -1
  397. package/dist/runtime/daemon/client.js +2 -2
  398. package/dist/runtime/daemon/client.js.map +1 -1
  399. package/dist/runtime/daemon/index.d.ts +1 -0
  400. package/dist/runtime/daemon/index.d.ts.map +1 -1
  401. package/dist/runtime/daemon/index.js +1 -0
  402. package/dist/runtime/daemon/index.js.map +1 -1
  403. package/dist/runtime/daemon/runner-commands.d.ts +9 -1
  404. package/dist/runtime/daemon/runner-commands.d.ts.map +1 -1
  405. package/dist/runtime/daemon/runner-commands.js +33 -2
  406. package/dist/runtime/daemon/runner-commands.js.map +1 -1
  407. package/dist/runtime/daemon/runner-goal-cycle.d.ts.map +1 -1
  408. package/dist/runtime/daemon/runner-goal-cycle.js +55 -8
  409. package/dist/runtime/daemon/runner-goal-cycle.js.map +1 -1
  410. package/dist/runtime/daemon/runner-startup.d.ts +2 -1
  411. package/dist/runtime/daemon/runner-startup.d.ts.map +1 -1
  412. package/dist/runtime/daemon/runner-startup.js +32 -5
  413. package/dist/runtime/daemon/runner-startup.js.map +1 -1
  414. package/dist/runtime/daemon/runner.d.ts +2 -0
  415. package/dist/runtime/daemon/runner.d.ts.map +1 -1
  416. package/dist/runtime/daemon/runner.js +18 -3
  417. package/dist/runtime/daemon/runner.js.map +1 -1
  418. package/dist/runtime/daemon/runtime-root.d.ts +5 -0
  419. package/dist/runtime/daemon/runtime-root.d.ts.map +1 -0
  420. package/dist/runtime/daemon/runtime-root.js +60 -0
  421. package/dist/runtime/daemon/runtime-root.js.map +1 -0
  422. package/dist/runtime/daemon/wait-deadline-resolver.d.ts +25 -0
  423. package/dist/runtime/daemon/wait-deadline-resolver.d.ts.map +1 -0
  424. package/dist/runtime/daemon/wait-deadline-resolver.js +88 -0
  425. package/dist/runtime/daemon/wait-deadline-resolver.js.map +1 -0
  426. package/dist/runtime/event/server-command-handler.d.ts.map +1 -1
  427. package/dist/runtime/event/server-command-handler.js +47 -3
  428. package/dist/runtime/event/server-command-handler.js.map +1 -1
  429. package/dist/runtime/executor/goal-worker.d.ts +1 -0
  430. package/dist/runtime/executor/goal-worker.d.ts.map +1 -1
  431. package/dist/runtime/executor/goal-worker.js +1 -0
  432. package/dist/runtime/executor/goal-worker.js.map +1 -1
  433. package/dist/runtime/executor/loop-supervisor.d.ts +24 -1
  434. package/dist/runtime/executor/loop-supervisor.d.ts.map +1 -1
  435. package/dist/runtime/executor/loop-supervisor.js +191 -12
  436. package/dist/runtime/executor/loop-supervisor.js.map +1 -1
  437. package/dist/runtime/gateway/chat-session-dispatch.d.ts +1 -0
  438. package/dist/runtime/gateway/chat-session-dispatch.d.ts.map +1 -1
  439. package/dist/runtime/gateway/chat-session-dispatch.js +1 -0
  440. package/dist/runtime/gateway/chat-session-dispatch.js.map +1 -1
  441. package/dist/runtime/gateway/discord-gateway-adapter.d.ts.map +1 -1
  442. package/dist/runtime/gateway/discord-gateway-adapter.js +1 -0
  443. package/dist/runtime/gateway/discord-gateway-adapter.js.map +1 -1
  444. package/dist/runtime/gateway/signal-gateway-adapter.d.ts.map +1 -1
  445. package/dist/runtime/gateway/signal-gateway-adapter.js +1 -0
  446. package/dist/runtime/gateway/signal-gateway-adapter.js.map +1 -1
  447. package/dist/runtime/gateway/slack-channel-adapter.d.ts +4 -0
  448. package/dist/runtime/gateway/slack-channel-adapter.d.ts.map +1 -1
  449. package/dist/runtime/gateway/slack-channel-adapter.js +105 -10
  450. package/dist/runtime/gateway/slack-channel-adapter.js.map +1 -1
  451. package/dist/runtime/gateway/telegram-gateway-adapter.d.ts.map +1 -1
  452. package/dist/runtime/gateway/telegram-gateway-adapter.js +3 -1
  453. package/dist/runtime/gateway/telegram-gateway-adapter.js.map +1 -1
  454. package/dist/runtime/gateway/whatsapp-gateway-adapter.d.ts.map +1 -1
  455. package/dist/runtime/gateway/whatsapp-gateway-adapter.js +1 -0
  456. package/dist/runtime/gateway/whatsapp-gateway-adapter.js.map +1 -1
  457. package/dist/runtime/session-registry/index.d.ts +3 -0
  458. package/dist/runtime/session-registry/index.d.ts.map +1 -0
  459. package/dist/runtime/session-registry/index.js +3 -0
  460. package/dist/runtime/session-registry/index.js.map +1 -0
  461. package/dist/runtime/session-registry/registry.d.ts +39 -0
  462. package/dist/runtime/session-registry/registry.d.ts.map +1 -0
  463. package/dist/runtime/session-registry/registry.js +761 -0
  464. package/dist/runtime/session-registry/registry.js.map +1 -0
  465. package/dist/runtime/session-registry/types.d.ts +985 -0
  466. package/dist/runtime/session-registry/types.d.ts.map +1 -0
  467. package/dist/runtime/session-registry/types.js +108 -0
  468. package/dist/runtime/session-registry/types.js.map +1 -0
  469. package/dist/runtime/store/background-run-store.d.ts +75 -0
  470. package/dist/runtime/store/background-run-store.d.ts.map +1 -0
  471. package/dist/runtime/store/background-run-store.js +157 -0
  472. package/dist/runtime/store/background-run-store.js.map +1 -0
  473. package/dist/runtime/store/index.d.ts +2 -0
  474. package/dist/runtime/store/index.d.ts.map +1 -1
  475. package/dist/runtime/store/index.js +1 -0
  476. package/dist/runtime/store/index.js.map +1 -1
  477. package/dist/runtime/store/runtime-operation-schemas.d.ts +62 -22
  478. package/dist/runtime/store/runtime-operation-schemas.d.ts.map +1 -1
  479. package/dist/runtime/store/runtime-operation-schemas.js +5 -0
  480. package/dist/runtime/store/runtime-operation-schemas.js.map +1 -1
  481. package/dist/runtime/store/runtime-paths.d.ts +2 -0
  482. package/dist/runtime/store/runtime-paths.d.ts.map +1 -1
  483. package/dist/runtime/store/runtime-paths.js +6 -0
  484. package/dist/runtime/store/runtime-paths.js.map +1 -1
  485. package/dist/runtime/store/runtime-schemas.d.ts +6 -6
  486. package/dist/runtime/types/cron.d.ts +4 -4
  487. package/dist/runtime/types/daemon.d.ts +60 -0
  488. package/dist/runtime/types/daemon.d.ts.map +1 -1
  489. package/dist/runtime/types/daemon.js +14 -0
  490. package/dist/runtime/types/daemon.js.map +1 -1
  491. package/dist/runtime/types/envelope.d.ts +2 -2
  492. package/dist/runtime/types/notification.d.ts +1 -1
  493. package/dist/tools/builtin/exports.d.ts +4 -0
  494. package/dist/tools/builtin/exports.d.ts.map +1 -1
  495. package/dist/tools/builtin/exports.js +4 -0
  496. package/dist/tools/builtin/exports.js.map +1 -1
  497. package/dist/tools/builtin/factory.d.ts.map +1 -1
  498. package/dist/tools/builtin/factory.js +18 -0
  499. package/dist/tools/builtin/factory.js.map +1 -1
  500. package/dist/tools/fs/GlobTool/GlobTool.js +2 -2
  501. package/dist/tools/fs/GlobTool/GlobTool.js.map +1 -1
  502. package/dist/tools/fs/GrepTool/GrepTool.js +2 -2
  503. package/dist/tools/fs/GrepTool/GrepTool.js.map +1 -1
  504. package/dist/tools/fs/ReadTool/ReadTool.js +2 -2
  505. package/dist/tools/fs/ReadTool/ReadTool.js.map +1 -1
  506. package/dist/tools/kaggle/KaggleExperimentTools.d.ts +395 -0
  507. package/dist/tools/kaggle/KaggleExperimentTools.d.ts.map +1 -0
  508. package/dist/tools/kaggle/KaggleExperimentTools.js +923 -0
  509. package/dist/tools/kaggle/KaggleExperimentTools.js.map +1 -0
  510. package/dist/tools/kaggle/KaggleSubmissionTools.d.ts +241 -0
  511. package/dist/tools/kaggle/KaggleSubmissionTools.d.ts.map +1 -0
  512. package/dist/tools/kaggle/KaggleSubmissionTools.js +558 -0
  513. package/dist/tools/kaggle/KaggleSubmissionTools.js.map +1 -0
  514. package/dist/tools/kaggle/KaggleWorkspacePrepareTool.d.ts +105 -0
  515. package/dist/tools/kaggle/KaggleWorkspacePrepareTool.d.ts.map +1 -0
  516. package/dist/tools/kaggle/KaggleWorkspacePrepareTool.js +135 -0
  517. package/dist/tools/kaggle/KaggleWorkspacePrepareTool.js.map +1 -0
  518. package/dist/tools/kaggle/index.d.ts +6 -0
  519. package/dist/tools/kaggle/index.d.ts.map +1 -0
  520. package/dist/tools/kaggle/index.js +6 -0
  521. package/dist/tools/kaggle/index.js.map +1 -0
  522. package/dist/tools/kaggle/metrics.d.ts +89 -0
  523. package/dist/tools/kaggle/metrics.d.ts.map +1 -0
  524. package/dist/tools/kaggle/metrics.js +51 -0
  525. package/dist/tools/kaggle/metrics.js.map +1 -0
  526. package/dist/tools/kaggle/paths.d.ts +15 -0
  527. package/dist/tools/kaggle/paths.d.ts.map +1 -0
  528. package/dist/tools/kaggle/paths.js +136 -0
  529. package/dist/tools/kaggle/paths.js.map +1 -0
  530. package/dist/tools/network/GitHubCliTool/GitHubCliTool.d.ts +2 -2
  531. package/dist/tools/query/ArchitectureTool/ArchitectureTool.js +1 -1
  532. package/dist/tools/query/ArchitectureTool/ArchitectureTool.js.map +1 -1
  533. package/dist/tools/query/CodeReadContextTool/CodeReadContextTool.d.ts +801 -0
  534. package/dist/tools/query/CodeReadContextTool/CodeReadContextTool.d.ts.map +1 -0
  535. package/dist/tools/query/CodeReadContextTool/CodeReadContextTool.js +147 -0
  536. package/dist/tools/query/CodeReadContextTool/CodeReadContextTool.js.map +1 -0
  537. package/dist/tools/query/CodeReadContextTool/constants.d.ts +5 -0
  538. package/dist/tools/query/CodeReadContextTool/constants.d.ts.map +1 -0
  539. package/dist/tools/query/CodeReadContextTool/constants.js +5 -0
  540. package/dist/tools/query/CodeReadContextTool/constants.js.map +1 -0
  541. package/dist/tools/query/CodeReadContextTool/prompt.d.ts +2 -0
  542. package/dist/tools/query/CodeReadContextTool/prompt.d.ts.map +1 -0
  543. package/dist/tools/query/CodeReadContextTool/prompt.js +6 -0
  544. package/dist/tools/query/CodeReadContextTool/prompt.js.map +1 -0
  545. package/dist/tools/query/CodeSearchRepairTool/CodeSearchRepairTool.d.ts +125 -0
  546. package/dist/tools/query/CodeSearchRepairTool/CodeSearchRepairTool.d.ts.map +1 -0
  547. package/dist/tools/query/CodeSearchRepairTool/CodeSearchRepairTool.js +97 -0
  548. package/dist/tools/query/CodeSearchRepairTool/CodeSearchRepairTool.js.map +1 -0
  549. package/dist/tools/query/CodeSearchRepairTool/constants.d.ts +5 -0
  550. package/dist/tools/query/CodeSearchRepairTool/constants.d.ts.map +1 -0
  551. package/dist/tools/query/CodeSearchRepairTool/constants.js +5 -0
  552. package/dist/tools/query/CodeSearchRepairTool/constants.js.map +1 -0
  553. package/dist/tools/query/CodeSearchRepairTool/prompt.d.ts +2 -0
  554. package/dist/tools/query/CodeSearchRepairTool/prompt.d.ts.map +1 -0
  555. package/dist/tools/query/CodeSearchRepairTool/prompt.js +5 -0
  556. package/dist/tools/query/CodeSearchRepairTool/prompt.js.map +1 -0
  557. package/dist/tools/query/CodeSearchTool/CodeSearchTool.d.ts +123 -0
  558. package/dist/tools/query/CodeSearchTool/CodeSearchTool.d.ts.map +1 -0
  559. package/dist/tools/query/CodeSearchTool/CodeSearchTool.js +95 -0
  560. package/dist/tools/query/CodeSearchTool/CodeSearchTool.js.map +1 -0
  561. package/dist/tools/query/CodeSearchTool/constants.d.ts +5 -0
  562. package/dist/tools/query/CodeSearchTool/constants.d.ts.map +1 -0
  563. package/dist/tools/query/CodeSearchTool/constants.js +5 -0
  564. package/dist/tools/query/CodeSearchTool/constants.js.map +1 -0
  565. package/dist/tools/query/CodeSearchTool/prompt.d.ts +2 -0
  566. package/dist/tools/query/CodeSearchTool/prompt.d.ts.map +1 -0
  567. package/dist/tools/query/CodeSearchTool/prompt.js +6 -0
  568. package/dist/tools/query/CodeSearchTool/prompt.js.map +1 -0
  569. package/dist/tools/system/ProcessSessionTool/ProcessSessionTool.d.ts +35 -7
  570. package/dist/tools/system/ProcessSessionTool/ProcessSessionTool.d.ts.map +1 -1
  571. package/dist/tools/system/ProcessSessionTool/ProcessSessionTool.js +128 -3
  572. package/dist/tools/system/ProcessSessionTool/ProcessSessionTool.js.map +1 -1
  573. package/package.json +2 -1
@@ -6,6 +6,7 @@ import { execFile } from "node:child_process";
6
6
  import * as fsp from "node:fs/promises";
7
7
  import * as path from "node:path";
8
8
  import { getPulseedDirPath } from "../../base/utils/paths.js";
9
+ import { getSelfIdentityResponseForBaseDir } from "../../base/config/identity-loader.js";
9
10
  import { loadProviderConfig } from "../../base/llm/provider-config.js";
10
11
  import { TaskSchema } from "../../base/types/task.js";
11
12
  import { ChatHistory } from "./chat-history.js";
@@ -17,12 +18,15 @@ import { toToolDefinitionsFiltered } from "../../tools/tool-definition-adapter.j
17
18
  import { TendCommand } from "./tend-command.js";
18
19
  import { EventSubscriber } from "./event-subscriber.js";
19
20
  import { buildPromptedToolProtocolSystemPrompt, extractPromptedToolCalls, } from "../../orchestrator/execution/agent-loop/prompted-tool-protocol.js";
21
+ import { classifyFailureRecovery, formatFailureRecovery, formatLifecycleFailureMessage } from "./failure-recovery.js";
20
22
  import { resolveExecutionPolicy, summarizeExecutionPolicy, withExecutionPolicyOverrides, } from "../../orchestrator/execution/agent-loop/execution-policy.js";
21
23
  import { buildStandaloneIngressMessage, createIngressRouter, } from "./ingress-router.js";
24
+ import { createRuntimeSessionRegistry } from "../../runtime/session-registry/index.js";
22
25
  const DEFAULT_TIMEOUT_MS = 120_000;
23
26
  const MAX_VERIFY_RETRIES = 2;
24
27
  const MAX_TOOL_LOOPS = 5;
25
28
  const ACTIVITY_PREVIEW_CHARS = 40;
29
+ const DIFF_ARTIFACT_MAX_LINES = 80;
26
30
  const standaloneIngressRouter = createIngressRouter();
27
31
  // ─── Command help text ───
28
32
  const COMMAND_HELP = `Available commands:
@@ -35,6 +39,7 @@ Session
35
39
  /resume [id|title] Resume native agentloop state for the current or selected session
36
40
  /cleanup [--dry-run] Clean up stale chat sessions
37
41
  /compact Summarize older chat turns and keep the latest turns
42
+ /context Show active working context and session assumptions
38
43
  /exit Exit chat mode
39
44
 
40
45
  Goals and tasks
@@ -68,14 +73,123 @@ function checkGitChanges(cwd) {
68
73
  });
69
74
  });
70
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
+ }
71
151
  function previewActivityText(value, maxChars = ACTIVITY_PREVIEW_CHARS) {
72
152
  const normalized = value.replace(/\s+/g, " ").trim();
73
153
  return normalized.length > maxChars ? `${normalized.slice(0, maxChars)}...` : normalized;
74
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
+ }
75
171
  function formatToolActivity(action, toolName, detail) {
76
172
  const preview = detail ? previewActivityText(detail) : "";
77
173
  return preview ? `${action} tool: ${toolName} - ${preview}` : `${action} tool: ${toolName}`;
78
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
+ }
179
+ function resolveSelfIdentityResponse(input, baseDir) {
180
+ const normalized = input.trim().toLowerCase().replace(/\s+/g, "");
181
+ if (!normalized)
182
+ return null;
183
+ const isEnglishIdentityQuestion = /^(whoareyou|whatisyourname|what'syourname)[?]?$/.test(normalized);
184
+ const isIdentityQuestion = [
185
+ /^(あなた|君|きみ|お前|おまえ)(は|って)?(誰|だれ|何者|なにもの)(ですか|なの|です)?[??]?$/,
186
+ /^(あなた|君|きみ|お前|おまえ)の名前(は|って)?(何|なに)(ですか|なの|です)?[??]?$/,
187
+ /^名前(は|って)?(何|なに)(ですか|なの|です)?[??]?$/,
188
+ ].some((pattern) => pattern.test(normalized));
189
+ if (!isIdentityQuestion && !isEnglishIdentityQuestion)
190
+ return null;
191
+ return getSelfIdentityResponseForBaseDir(baseDir, isEnglishIdentityQuestion ? "en" : "ja");
192
+ }
79
193
  // ─── ChatRunner ───
80
194
  export class ChatRunner {
81
195
  deps;
@@ -101,6 +215,8 @@ export class ChatRunner {
101
215
  nativeAgentLoopStatePath = null;
102
216
  runtimeControlContext = null;
103
217
  sessionExecutionPolicy = null;
218
+ lastSelectedRoute = null;
219
+ activeTurn = null;
104
220
  constructor(deps) {
105
221
  this.deps = deps;
106
222
  this.groundingGateway = createChatGroundingGateway({
@@ -138,6 +254,68 @@ export class ChatRunner {
138
254
  getCurrentSessionMessages() {
139
255
  return this.history?.getMessages() ?? [];
140
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
+ }
141
319
  setRuntimeControlContext(context) {
142
320
  this.runtimeControlContext = context;
143
321
  }
@@ -146,7 +324,11 @@ export class ChatRunner {
146
324
  throw new Error("executeIngressMessage requires selectedRoute; use CrossPlatformChatSessionManager for ingress route selection.");
147
325
  }
148
326
  const runtimeControlContext = this.buildRuntimeControlContextFromIngress(ingress);
149
- return this.execute(ingress.text, cwd, timeoutMs, { selectedRoute, runtimeControlContext });
327
+ return this.execute(ingress.text, cwd, timeoutMs, {
328
+ selectedRoute,
329
+ runtimeControlContext,
330
+ goalId: ingress.goal_id,
331
+ });
150
332
  }
151
333
  resolveRouteFromIngress(ingress) {
152
334
  return standaloneIngressRouter.selectRoute(ingress, this.getRouteCapabilities());
@@ -160,6 +342,9 @@ export class ChatRunner {
160
342
  hasAgentLoop: this.deps.chatAgentLoopRunner !== undefined,
161
343
  hasToolLoop: this.deps.llmClient !== undefined,
162
344
  hasRuntimeControlService: this.deps.runtimeControlService !== undefined,
345
+ hasDaemonTend: this.deps.llmClient !== undefined
346
+ && this.deps.goalNegotiator !== undefined
347
+ && this.deps.daemonClient !== undefined,
163
348
  };
164
349
  }
165
350
  buildStandaloneIngressMessage(input, runtimeControlContext) {
@@ -173,6 +358,24 @@ export class ChatRunner {
173
358
  const runtimeApprovalFn = runtimeControlContext?.approvalFn
174
359
  ?? this.deps.runtimeControlApprovalFn
175
360
  ?? this.deps.approvalFn;
361
+ const replyTarget = runtimeControlContext?.replyTarget ?? this.deps.runtimeReplyTarget;
362
+ const replyTargetInput = replyTarget
363
+ ? {
364
+ ...(replyTarget.surface ? { surface: replyTarget.surface } : {}),
365
+ channel,
366
+ ...(replyTarget.platform ? { platform: replyTarget.platform } : {}),
367
+ ...(replyTarget.conversation_id ? { conversation_id: replyTarget.conversation_id } : {}),
368
+ ...(replyTarget.message_id ? { message_id: replyTarget.message_id } : {}),
369
+ ...(replyTarget.response_channel ? { response_channel: replyTarget.response_channel } : {}),
370
+ ...(replyTarget.outbox_topic ? { outbox_topic: replyTarget.outbox_topic } : {}),
371
+ ...(replyTarget.identity_key ? { identity_key: replyTarget.identity_key } : {}),
372
+ ...(replyTarget.user_id ? { user_id: replyTarget.user_id } : {}),
373
+ ...(replyTarget.deliveryMode === "reply" || replyTarget.deliveryMode === "notify" || replyTarget.deliveryMode === "thread_reply"
374
+ ? { deliveryMode: replyTarget.deliveryMode }
375
+ : {}),
376
+ ...(replyTarget.metadata ? { metadata: replyTarget.metadata } : {}),
377
+ }
378
+ : undefined;
176
379
  return buildStandaloneIngressMessage({
177
380
  text: input,
178
381
  channel,
@@ -181,7 +384,7 @@ export class ChatRunner {
181
384
  conversation_id: runtimeControlContext?.replyTarget?.conversation_id ?? this.deps.runtimeReplyTarget?.conversation_id,
182
385
  user_id: runtimeControlContext?.replyTarget?.user_id ?? this.deps.runtimeReplyTarget?.user_id,
183
386
  actor: runtimeControlContext?.actor ?? this.deps.runtimeControlActor,
184
- replyTarget: runtimeControlContext?.replyTarget ?? this.deps.runtimeReplyTarget,
387
+ replyTarget: replyTargetInput,
185
388
  runtimeControl: {
186
389
  allowed: true,
187
390
  approvalMode: "interactive",
@@ -222,15 +425,94 @@ export class ChatRunner {
222
425
  ...(session.agentLoop ? { agentLoop: session.agentLoop } : {}),
223
426
  };
224
427
  }
225
- formatSessionsList(entries) {
226
- if (entries.length === 0)
227
- return "No chat sessions found.";
228
- const lines = entries.map((entry) => {
229
- const title = entry.title ? ` "${entry.title}"` : "";
230
- const resumable = entry.agentLoopResumable ? " resumable" : "";
231
- return `${entry.id}${title} - ${entry.messageCount} message(s), updated ${entry.updatedAt}, cwd ${entry.cwd}${resumable}`;
232
- });
233
- 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.";
234
516
  }
235
517
  formatHistory(session) {
236
518
  const title = session.title ? ` "${session.title}"` : "";
@@ -319,14 +601,19 @@ export class ChatRunner {
319
601
  ];
320
602
  return { success: true, output: lines.join("\n"), elapsed_ms: Date.now() - start };
321
603
  }
322
- 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
+ ]);
323
609
  const active = this.activeGoals(goals);
610
+ const runtimeStatus = this.formatRuntimeStatus(runtimeSnapshot);
324
611
  if (active.length === 0) {
325
- 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 };
326
613
  }
327
614
  return {
328
615
  success: true,
329
- 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}`,
330
617
  elapsed_ms: Date.now() - start,
331
618
  };
332
619
  }
@@ -775,7 +1062,79 @@ export class ChatRunner {
775
1062
  elapsed_ms: Date.now() - start,
776
1063
  };
777
1064
  }
778
- 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) {
779
1138
  const trimmed = input.trim();
780
1139
  if (!trimmed.startsWith("/"))
781
1140
  return null;
@@ -789,9 +1148,9 @@ export class ChatRunner {
789
1148
  return { success: true, output: "Conversation history cleared.", elapsed_ms: Date.now() - start };
790
1149
  }
791
1150
  if (cmd === "/sessions") {
792
- const catalog = new ChatSessionCatalog(this.deps.stateManager);
793
- const sessions = await catalog.listSessions();
794
- 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 };
795
1154
  }
796
1155
  if (cmd === "/history") {
797
1156
  const catalog = new ChatSessionCatalog(this.deps.stateManager);
@@ -864,6 +1223,9 @@ export class ChatRunner {
864
1223
  if (cmd === "/usage") {
865
1224
  return this.handleUsage(trimmed.slice("/usage".length).trim(), start);
866
1225
  }
1226
+ if (cmd === "/context" || cmd === "/working-memory") {
1227
+ return this.handleContext(start, cwd);
1228
+ }
867
1229
  if (cmd === "/review") {
868
1230
  return this.handleReview(start);
869
1231
  }
@@ -873,6 +1235,26 @@ export class ChatRunner {
873
1235
  if (cmd === "/undo") {
874
1236
  return this.handleUndo(start);
875
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
+ }
876
1258
  if (cmd === "/exit") {
877
1259
  return { success: true, output: "Exiting chat mode.", elapsed_ms: Date.now() - start };
878
1260
  }
@@ -1073,6 +1455,9 @@ export class ChatRunner {
1073
1455
  daemonClient: this.deps.daemonClient,
1074
1456
  stateManager: this.deps.stateManager,
1075
1457
  chatHistory: history,
1458
+ sessionId: this.history?.getSessionId() ?? null,
1459
+ workspace: this.sessionCwd ?? process.cwd(),
1460
+ replyTarget: this.runtimeControlContext?.replyTarget ?? this.deps.runtimeReplyTarget ?? null,
1076
1461
  };
1077
1462
  const tendCommand = new TendCommand();
1078
1463
  const result = await tendCommand.execute(args, tendDeps);
@@ -1138,7 +1523,34 @@ export class ChatRunner {
1138
1523
  }
1139
1524
  }
1140
1525
  try {
1141
- 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
+ };
1142
1554
  }
1143
1555
  catch (err) {
1144
1556
  if (subscriber) {
@@ -1152,13 +1564,6 @@ export class ChatRunner {
1152
1564
  elapsed_ms: Date.now() - start,
1153
1565
  };
1154
1566
  }
1155
- const iterNote = maxIterations !== undefined ? ` (max ${maxIterations} iterations)` : "";
1156
- const shortId = goalId.length > 12 ? goalId.slice(0, 12) : goalId;
1157
- return {
1158
- success: true,
1159
- output: `[tend] ${shortId}: Started — daemon is now tending your goal${iterNote}.\nRun 'pulseed status' to check progress.`,
1160
- elapsed_ms: Date.now() - start,
1161
- };
1162
1567
  }
1163
1568
  /**
1164
1569
  * Execute a single chat turn.
@@ -1174,11 +1579,13 @@ export class ChatRunner {
1174
1579
  */
1175
1580
  async execute(input, cwd, timeoutMs = DEFAULT_TIMEOUT_MS, options = {}) {
1176
1581
  const eventContext = this.createEventContext();
1582
+ const activeTurn = this.beginActiveTurn(eventContext, resolveGitRoot(cwd));
1177
1583
  const resumeCommand = this.parseResumeCommand(input);
1178
1584
  const resumeOnly = resumeCommand !== null;
1179
1585
  const runtimeControlContext = options.runtimeControlContext ?? this.runtimeControlContext;
1586
+ const executionGoalId = options.goalId ?? this.deps.goalId;
1180
1587
  // Intercept commands before any adapter call
1181
- const commandResult = resumeOnly ? null : await this.handleCommand(input);
1588
+ const commandResult = resumeOnly ? null : await this.handleCommand(input, cwd);
1182
1589
  if (commandResult !== null) {
1183
1590
  if (commandResult.output) {
1184
1591
  this.emitEvent({
@@ -1207,11 +1614,24 @@ export class ChatRunner {
1207
1614
  }
1208
1615
  if (resumeOnly && resumeCommand.selector) {
1209
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
+ }
1210
1630
  const catalog = new ChatSessionCatalog(this.deps.stateManager);
1211
- const session = await catalog.loadSessionBySelector(resumeCommand.selector);
1631
+ const session = await catalog.loadSessionBySelector(selectorResolution.chatSelector);
1212
1632
  if (!session) {
1213
1633
  const elapsed_ms = 0;
1214
- const output = `No chat session matched selector "${resumeCommand.selector}".`;
1634
+ const output = `No chat session matched selector "${selectorResolution.chatSelector}".`;
1215
1635
  this.emitEvent({
1216
1636
  type: "assistant_final",
1217
1637
  text: output,
@@ -1244,7 +1664,9 @@ export class ChatRunner {
1244
1664
  this.nativeAgentLoopStatePath = `chat/agentloop/${sessionId}.state.json`;
1245
1665
  this.history.setAgentLoopStatePath(this.nativeAgentLoopStatePath);
1246
1666
  }
1667
+ const executionCwd = this.sessionCwd ?? cwd;
1247
1668
  const gitRoot = this.sessionCwd ?? resolveGitRoot(cwd);
1669
+ activeTurn.cwd = gitRoot;
1248
1670
  // history is always assigned by this point (either by startSession or the block above)
1249
1671
  const history = this.history;
1250
1672
  this.emitEvent({
@@ -1259,7 +1681,7 @@ export class ChatRunner {
1259
1681
  // Build static grounding once per session; dynamic context is rebuilt each turn.
1260
1682
  if (this.cachedStaticSystemPrompt === null) {
1261
1683
  try {
1262
- this.cachedStaticSystemPrompt = buildStaticSystemPrompt();
1684
+ this.cachedStaticSystemPrompt = buildStaticSystemPrompt(this.providerConfigBaseDir());
1263
1685
  }
1264
1686
  catch {
1265
1687
  this.cachedStaticSystemPrompt = "";
@@ -1284,14 +1706,41 @@ export class ChatRunner {
1284
1706
  const selectedRoute = resumeOnly
1285
1707
  ? null
1286
1708
  : (options.selectedRoute ?? this.resolveRouteFromInput(input, runtimeControlContext));
1709
+ this.lastSelectedRoute = selectedRoute;
1287
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
+ }
1288
1717
  const start = Date.now();
1289
1718
  const assistantBuffer = { text: "" };
1290
1719
  const turnUsage = this.zeroUsageCounter();
1720
+ const identityResponse = resumeOnly ? null : resolveSelfIdentityResponse(input, this.providerConfigBaseDir());
1721
+ if (identityResponse !== null) {
1722
+ const elapsed_ms = Date.now() - start;
1723
+ await history.appendAssistantMessage(identityResponse);
1724
+ this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
1725
+ this.emitEvent({
1726
+ type: "assistant_final",
1727
+ text: identityResponse,
1728
+ persisted: true,
1729
+ ...this.eventBase(eventContext),
1730
+ });
1731
+ this.emitLifecycleEndEvent("completed", elapsed_ms, eventContext, true);
1732
+ return {
1733
+ success: true,
1734
+ output: identityResponse,
1735
+ elapsed_ms,
1736
+ };
1737
+ }
1291
1738
  if (selectedRoute?.kind === "runtime_control") {
1292
- const runtimeControlResult = await this.executeRuntimeControlRoute(selectedRoute, runtimeControlContext, cwd, start);
1739
+ this.emitCheckpoint("Runtime control selected", `${selectedRoute.intent.kind} request recognized.`, eventContext, "route");
1740
+ const runtimeControlResult = await this.executeRuntimeControlRoute(selectedRoute, runtimeControlContext, executionCwd, start);
1293
1741
  if (runtimeControlResult.success) {
1294
1742
  await history.appendAssistantMessage(runtimeControlResult.output);
1743
+ this.emitCheckpoint("Runtime control completed", "The runtime-control operation produced a result.", eventContext, "complete");
1295
1744
  this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
1296
1745
  this.emitEvent({
1297
1746
  type: "assistant_final",
@@ -1302,11 +1751,32 @@ export class ChatRunner {
1302
1751
  this.emitLifecycleEndEvent("completed", runtimeControlResult.elapsed_ms, eventContext, true);
1303
1752
  }
1304
1753
  else {
1305
- this.emitLifecycleErrorEvent(runtimeControlResult.output, assistantBuffer.text, eventContext);
1754
+ runtimeControlResult.output = this.emitLifecycleErrorEvent(runtimeControlResult.output, assistantBuffer.text, eventContext);
1306
1755
  this.emitLifecycleEndEvent("error", runtimeControlResult.elapsed_ms, eventContext, false);
1307
1756
  }
1308
1757
  return runtimeControlResult;
1309
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
+ }
1310
1780
  if (selectedRoute?.kind === "direct_answer") {
1311
1781
  try {
1312
1782
  this.emitActivity("lifecycle", "Calling model...", eventContext, "lifecycle:model");
@@ -1321,7 +1791,12 @@ export class ChatRunner {
1321
1791
  if (this.hasUsage(turnUsage)) {
1322
1792
  history.recordUsage("execution", turnUsage);
1323
1793
  }
1794
+ const diffArtifact = await collectGitDiffArtifact(gitRoot);
1795
+ if (diffArtifact) {
1796
+ this.emitDiffArtifact(diffArtifact, eventContext);
1797
+ }
1324
1798
  await history.appendAssistantMessage(output);
1799
+ this.emitCheckpoint("Response ready", "The direct answer has been persisted for this turn.", eventContext, "complete");
1325
1800
  this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
1326
1801
  this.emitEvent({
1327
1802
  type: "assistant_final",
@@ -1344,13 +1819,11 @@ export class ChatRunner {
1344
1819
  }
1345
1820
  catch (err) {
1346
1821
  const message = err instanceof Error ? err.message : String(err);
1347
- this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
1822
+ const output = this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
1348
1823
  this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
1349
1824
  return {
1350
1825
  success: false,
1351
- output: assistantBuffer.text
1352
- ? `${assistantBuffer.text}\n\n[interrupted: ${message}]`
1353
- : `Error: ${message}`,
1826
+ output,
1354
1827
  elapsed_ms: Date.now() - start,
1355
1828
  diagnostics: {
1356
1829
  route: "direct",
@@ -1363,7 +1836,7 @@ export class ChatRunner {
1363
1836
  }
1364
1837
  const usesNativeAgentLoop = resumeOnly || selectedRoute?.kind === "agent_loop";
1365
1838
  const groundingWorkspaceContext = !resumeOnly && usesNativeAgentLoop
1366
- ? await buildChatContext(input, cwd)
1839
+ ? await buildChatContext(input, executionCwd)
1367
1840
  : undefined;
1368
1841
  let systemPrompt = this.cachedStaticSystemPrompt ?? "";
1369
1842
  if (!resumeOnly) {
@@ -1373,8 +1846,8 @@ export class ChatRunner {
1373
1846
  systemPrompt = await buildChatAgentLoopSystemPrompt({
1374
1847
  stateManager: this.deps.stateManager,
1375
1848
  pluginLoader: this.deps.pluginLoader,
1376
- workspaceRoot: cwd,
1377
- goalId: this.deps.goalId,
1849
+ workspaceRoot: executionCwd,
1850
+ goalId: executionGoalId,
1378
1851
  userMessage: input,
1379
1852
  trustProjectInstructions: this.sessionExecutionPolicy?.trustProjectInstructions ?? true,
1380
1853
  workspaceContext: groundingWorkspaceContext,
@@ -1384,8 +1857,8 @@ export class ChatRunner {
1384
1857
  const groundingBundle = await this.groundingGateway.build({
1385
1858
  surface: "chat",
1386
1859
  purpose: "general_turn",
1387
- workspaceRoot: cwd,
1388
- goalId: this.deps.goalId,
1860
+ workspaceRoot: executionCwd,
1861
+ goalId: executionGoalId,
1389
1862
  userMessage: input,
1390
1863
  query: input,
1391
1864
  trustProjectInstructions: this.sessionExecutionPolicy?.trustProjectInstructions ?? true,
@@ -1396,6 +1869,9 @@ export class ChatRunner {
1396
1869
  catch {
1397
1870
  systemPrompt = this.cachedStaticSystemPrompt ?? "";
1398
1871
  }
1872
+ this.emitCheckpoint("Context gathered", usesNativeAgentLoop
1873
+ ? "Workspace and agent-loop grounding are ready."
1874
+ : "Workspace grounding is ready.", eventContext, "context");
1399
1875
  }
1400
1876
  const agentLoopSystemPrompt = [
1401
1877
  systemPrompt,
@@ -1409,13 +1885,7 @@ export class ChatRunner {
1409
1885
  const prompt = historyBlock ? `${historyBlock}${basePrompt}` : basePrompt;
1410
1886
  if (resumeOnly && !this.deps.chatAgentLoopRunner) {
1411
1887
  const elapsed_ms = Date.now() - start;
1412
- const output = "Resume requires the native chat agentloop runtime.";
1413
- this.emitEvent({
1414
- type: "assistant_final",
1415
- text: output,
1416
- persisted: false,
1417
- ...this.eventBase(eventContext),
1418
- });
1888
+ const output = this.emitLifecycleErrorEvent("Resume requires the native chat agentloop runtime.", assistantBuffer.text, eventContext);
1419
1889
  this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
1420
1890
  return {
1421
1891
  success: false,
@@ -1429,13 +1899,7 @@ export class ChatRunner {
1429
1899
  const resumeState = resumeOnly ? await this.loadResumableAgentLoopState() : null;
1430
1900
  if (resumeOnly && !resumeState) {
1431
1901
  const elapsed_ms = Date.now() - start;
1432
- const output = "No resumable native agentloop state found.";
1433
- this.emitEvent({
1434
- type: "assistant_final",
1435
- text: output,
1436
- persisted: false,
1437
- ...this.eventBase(eventContext),
1438
- });
1902
+ const output = this.emitLifecycleErrorEvent("No resumable native agentloop state found.", assistantBuffer.text, eventContext);
1439
1903
  this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
1440
1904
  return {
1441
1905
  success: false,
@@ -1443,11 +1907,14 @@ export class ChatRunner {
1443
1907
  elapsed_ms,
1444
1908
  };
1445
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");
1446
1913
  this.emitActivity("lifecycle", "Calling model...", eventContext, "lifecycle:model");
1447
1914
  const result = await chatAgentLoopRunner.execute({
1448
1915
  message: basePrompt,
1449
- cwd,
1450
- goalId: this.deps.goalId,
1916
+ cwd: executionCwd,
1917
+ goalId: executionGoalId,
1451
1918
  history: priorTurns.map((m) => ({
1452
1919
  role: m.role === "assistant" ? "assistant" : "user",
1453
1920
  content: m.content,
@@ -1466,6 +1933,7 @@ export class ChatRunner {
1466
1933
  ...(resumeState ? { resumeState } : {}),
1467
1934
  ...(resumeOnly ? { resumeOnly: true } : {}),
1468
1935
  ...(agentLoopSystemPrompt ? { systemPrompt: agentLoopSystemPrompt } : {}),
1936
+ abortSignal: activeTurn.abortController.signal,
1469
1937
  });
1470
1938
  const elapsed_ms = Date.now() - start;
1471
1939
  const agentLoopUsage = result.agentLoop?.usage
@@ -1478,7 +1946,12 @@ export class ChatRunner {
1478
1946
  this.pushAssistantDelta(result.output, assistantBuffer, eventContext);
1479
1947
  }
1480
1948
  if (result.success) {
1949
+ const diffArtifact = await collectGitDiffArtifact(gitRoot);
1950
+ if (diffArtifact) {
1951
+ this.emitDiffArtifact(diffArtifact, eventContext);
1952
+ }
1481
1953
  await history.appendAssistantMessage(result.output);
1954
+ this.emitCheckpoint("Response ready", "The agent-loop response has been persisted for this turn.", eventContext, "complete");
1482
1955
  this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
1483
1956
  this.emitEvent({
1484
1957
  type: "assistant_final",
@@ -1489,7 +1962,7 @@ export class ChatRunner {
1489
1962
  this.emitLifecycleEndEvent("completed", elapsed_ms, eventContext, true);
1490
1963
  }
1491
1964
  else {
1492
- 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);
1493
1966
  this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
1494
1967
  }
1495
1968
  return {
@@ -1500,13 +1973,11 @@ export class ChatRunner {
1500
1973
  }
1501
1974
  catch (err) {
1502
1975
  const message = err instanceof Error ? err.message : String(err);
1503
- this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
1976
+ const output = this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
1504
1977
  this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
1505
1978
  return {
1506
1979
  success: false,
1507
- output: assistantBuffer.text
1508
- ? `${assistantBuffer.text}\n\n[interrupted: ${message}]`
1509
- : `Error: ${message}`,
1980
+ output,
1510
1981
  elapsed_ms: Date.now() - start,
1511
1982
  };
1512
1983
  }
@@ -1514,12 +1985,18 @@ export class ChatRunner {
1514
1985
  // Prefer the local LLM/tool loop over the external adapter fallback whenever a client is available.
1515
1986
  if (selectedRoute?.kind === "tool_loop") {
1516
1987
  try {
1517
- const toolResult = await this.executeWithTools(prompt, eventContext, assistantBuffer, systemPrompt || undefined);
1988
+ this.emitCheckpoint("Tool loop started", "The model will choose tools from the active catalog.", eventContext, "execution");
1989
+ const toolResult = await this.executeWithTools(prompt, eventContext, assistantBuffer, systemPrompt || undefined, executionGoalId);
1518
1990
  const elapsed_ms = Date.now() - start;
1519
1991
  if (this.hasUsage(toolResult.usage)) {
1520
1992
  history.recordUsage("execution", toolResult.usage);
1521
1993
  }
1994
+ const diffArtifact = await collectGitDiffArtifact(gitRoot);
1995
+ if (diffArtifact) {
1996
+ this.emitDiffArtifact(diffArtifact, eventContext);
1997
+ }
1522
1998
  await history.appendAssistantMessage(toolResult.output);
1999
+ this.emitCheckpoint("Response ready", "The tool-loop response has been persisted for this turn.", eventContext, "complete");
1523
2000
  this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
1524
2001
  this.emitEvent({
1525
2002
  type: "assistant_final",
@@ -1532,21 +2009,18 @@ export class ChatRunner {
1532
2009
  }
1533
2010
  catch (err) {
1534
2011
  const message = err instanceof Error ? err.message : String(err);
1535
- this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
2012
+ const output = this.emitLifecycleErrorEvent(message, assistantBuffer.text, eventContext);
1536
2013
  this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
1537
2014
  return {
1538
2015
  success: false,
1539
- output: assistantBuffer.text
1540
- ? `${assistantBuffer.text}\n\n[interrupted: ${message}]`
1541
- : `Error: ${message}`,
2016
+ output,
1542
2017
  elapsed_ms: Date.now() - start,
1543
2018
  };
1544
2019
  }
1545
2020
  }
1546
2021
  if (!resumeOnly && selectedRoute && selectedRoute.kind !== "adapter") {
1547
2022
  const elapsed_ms = Date.now() - start;
1548
- const output = `Unsupported chat route: ${selectedRoute.kind}`;
1549
- this.emitLifecycleErrorEvent(output, assistantBuffer.text, eventContext);
2023
+ const output = this.emitLifecycleErrorEvent(`Unsupported chat route: ${selectedRoute.kind}`, assistantBuffer.text, eventContext);
1550
2024
  this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
1551
2025
  return {
1552
2026
  success: false,
@@ -1562,10 +2036,25 @@ export class ChatRunner {
1562
2036
  ...(systemPrompt ? { system_prompt: systemPrompt } : {}),
1563
2037
  };
1564
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");
1565
2040
  this.emitActivity("lifecycle", "Calling adapter...", eventContext, "lifecycle:adapter");
1566
2041
  const adapterPromise = this.deps.adapter.execute(task);
1567
2042
  const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error(`Chat adapter timed out after ${resolvedTimeoutMs}ms`)), resolvedTimeoutMs));
1568
- 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
+ }
1569
2058
  // Surface adapter errors into output when output is empty
1570
2059
  if (!result.output && result.error) {
1571
2060
  result = { ...result, output: `Error: ${result.error}` };
@@ -1575,34 +2064,47 @@ export class ChatRunner {
1575
2064
  this.pushAssistantDelta(result.output, assistantBuffer, eventContext);
1576
2065
  }
1577
2066
  // Verification loop: check if git has uncommitted changes; if so, run tests
1578
- const gitChanges = await checkGitChanges(gitRoot);
1579
- if (gitChanges !== null && gitChanges !== "") {
2067
+ const diffArtifact = await collectGitDiffArtifact(gitRoot);
2068
+ if (diffArtifact) {
1580
2069
  let retries = 0;
1581
2070
  const VERIFY_TIMEOUT_MS = 30_000;
2071
+ this.emitCheckpoint("Changes detected", "Verification is starting because the turn changed the working tree.", eventContext, "changes");
1582
2072
  this.emitActivity("lifecycle", "Checking result...", eventContext, "lifecycle:checking");
1583
2073
  let verification = await Promise.race([
1584
- verifyChatAction(gitRoot, this.deps.toolExecutor),
2074
+ verifyChatAction(gitRoot, this.deps.toolExecutor, { force: true }),
1585
2075
  new Promise((resolve) => setTimeout(() => resolve({ passed: true }), VERIFY_TIMEOUT_MS)),
1586
2076
  ]);
1587
2077
  while (!verification.passed && retries < MAX_VERIFY_RETRIES) {
1588
2078
  retries++;
2079
+ this.emitCheckpoint("Verification retry", `Attempt ${retries} of ${MAX_VERIFY_RETRIES} is repairing failed checks.`, eventContext, `verification-retry-${retries}`);
1589
2080
  const retryPrompt = `The previous changes caused test failures. Please fix them.\n\nTest output:\n${verification.testOutput ?? verification.errors.join("\n")}`;
1590
2081
  const retryTask = { ...task, prompt: retryPrompt };
1591
2082
  result = await this.deps.adapter.execute(retryTask);
1592
- verification = await verifyChatAction(gitRoot, this.deps.toolExecutor);
2083
+ verification = await verifyChatAction(gitRoot, this.deps.toolExecutor, { force: true });
1593
2084
  }
1594
2085
  if (!verification.passed) {
1595
- 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);
1596
2092
  this.emitLifecycleEndEvent("error", Date.now() - start, eventContext, false);
1597
2093
  return {
1598
2094
  success: false,
1599
- 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(),
1600
2096
  elapsed_ms: Date.now() - start,
1601
2097
  };
1602
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");
1603
2104
  }
1604
2105
  if (result.success) {
1605
2106
  await history.appendAssistantMessage(result.output);
2107
+ this.emitCheckpoint("Response ready", "The assistant response has been persisted for this turn.", eventContext, "complete");
1606
2108
  this.emitActivity("lifecycle", "Finalizing response...", eventContext, "lifecycle:finalizing");
1607
2109
  this.emitEvent({
1608
2110
  type: "assistant_final",
@@ -1614,7 +2116,7 @@ export class ChatRunner {
1614
2116
  }
1615
2117
  else {
1616
2118
  const partialText = assistantBuffer.text !== result.output ? assistantBuffer.text : "";
1617
- this.emitLifecycleErrorEvent(result.output || result.error || "Unknown error", partialText, eventContext);
2119
+ result.output = this.emitLifecycleErrorEvent(result.output || result.error || "Unknown error", partialText, eventContext);
1618
2120
  this.emitLifecycleEndEvent("error", elapsed_ms, eventContext, false);
1619
2121
  }
1620
2122
  return {
@@ -1658,10 +2160,10 @@ export class ChatRunner {
1658
2160
  * Execute a chat turn using llmClient with self-knowledge tools (function calling).
1659
2161
  * Loops up to MAX_TOOL_LOOPS times to resolve tool calls, then returns final text.
1660
2162
  */
1661
- async executeWithTools(prompt, eventContext, assistantBuffer, systemPrompt) {
2163
+ async executeWithTools(prompt, eventContext, assistantBuffer, systemPrompt, goalId) {
1662
2164
  const llmClient = this.deps.llmClient;
1663
2165
  const messages = [{ role: "user", content: prompt }];
1664
- const toolCallContext = await this.buildToolCallContext();
2166
+ const toolCallContext = await this.buildToolCallContext(goalId);
1665
2167
  const usage = this.zeroUsageCounter();
1666
2168
  for (let loop = 0; loop < MAX_TOOL_LOOPS; loop++) {
1667
2169
  // Recompute tools each iteration so newly activated deferred tools are included
@@ -1797,6 +2299,7 @@ export class ChatRunner {
1797
2299
  }
1798
2300
  if (event.type === "plan_update") {
1799
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}`);
1800
2303
  this.emitEvent({
1801
2304
  type: "tool_update",
1802
2305
  toolCallId: `plan:${event.turnId}:${event.createdAt}`,
@@ -1809,6 +2312,7 @@ export class ChatRunner {
1809
2312
  }
1810
2313
  if (event.type === "approval_request") {
1811
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}`);
1812
2316
  this.emitEvent({
1813
2317
  type: "tool_update",
1814
2318
  toolCallId: event.callId,
@@ -1867,6 +2371,34 @@ export class ChatRunner {
1867
2371
  }
1868
2372
  return preview ? { preview } : {};
1869
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
+ }
1870
2402
  parseResumeCommand(input) {
1871
2403
  const trimmed = input.trim();
1872
2404
  const match = /^\/resume(?:\s+(.+))?$/i.exec(trimmed);
@@ -2077,11 +2609,81 @@ export class ChatRunner {
2077
2609
  eventBase(context) {
2078
2610
  return { ...context, createdAt: new Date().toISOString() };
2079
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
+ }
2080
2681
  emitEvent(event) {
2682
+ this.rememberActiveTurnEvent(event);
2081
2683
  const handler = this.onEvent ?? this.deps.onEvent;
2082
2684
  handler?.(event);
2083
2685
  }
2084
- emitActivity(kind, message, eventContext, sourceId) {
2686
+ emitActivity(kind, message, eventContext, sourceId, transient = true) {
2085
2687
  if (!message.trim())
2086
2688
  return;
2087
2689
  this.emitEvent({
@@ -2089,10 +2691,72 @@ export class ChatRunner {
2089
2691
  kind,
2090
2692
  message,
2091
2693
  ...(sourceId ? { sourceId } : {}),
2092
- transient: true,
2694
+ transient,
2093
2695
  ...this.eventBase(eventContext),
2094
2696
  });
2095
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
+ }
2096
2760
  pushAssistantDelta(delta, assistantBuffer, eventContext) {
2097
2761
  if (!delta)
2098
2762
  return;
@@ -2112,15 +2776,19 @@ export class ChatRunner {
2112
2776
  persisted,
2113
2777
  ...this.eventBase(eventContext),
2114
2778
  });
2779
+ this.finishActiveTurn(eventContext);
2115
2780
  }
2116
2781
  emitLifecycleErrorEvent(error, partialText, eventContext) {
2782
+ const recovery = classifyFailureRecovery(error);
2117
2783
  this.emitEvent({
2118
2784
  type: "lifecycle_error",
2119
2785
  error,
2120
2786
  partialText,
2121
2787
  persisted: false,
2788
+ recovery,
2122
2789
  ...this.eventBase(eventContext),
2123
2790
  });
2791
+ return formatLifecycleFailureMessage(error, partialText, recovery);
2124
2792
  }
2125
2793
  /** Build a ToolCallContext from ChatRunnerDeps for tool dispatch. */
2126
2794
  async getSessionExecutionPolicy() {
@@ -2133,11 +2801,11 @@ export class ChatRunner {
2133
2801
  });
2134
2802
  return this.sessionExecutionPolicy;
2135
2803
  }
2136
- async buildToolCallContext() {
2804
+ async buildToolCallContext(goalId = this.deps.goalId) {
2137
2805
  const executionPolicy = await this.getSessionExecutionPolicy();
2138
2806
  return {
2139
2807
  cwd: this.sessionCwd ?? process.cwd(),
2140
- goalId: this.deps.goalId ?? "",
2808
+ goalId: goalId ?? "",
2141
2809
  trustBalance: 0,
2142
2810
  preApproved: false,
2143
2811
  approvalFn: async (req) => {