pulseed 0.6.3 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (509) hide show
  1. package/dist/adapters/datasources/artifact-metric-datasource.d.ts +11 -1
  2. package/dist/adapters/datasources/artifact-metric-datasource.d.ts.map +1 -1
  3. package/dist/adapters/datasources/artifact-metric-datasource.js +238 -8
  4. package/dist/adapters/datasources/artifact-metric-datasource.js.map +1 -1
  5. package/dist/base/config/global-config.d.ts +4 -4
  6. package/dist/base/protocol/exact-protocol.d.ts +47 -0
  7. package/dist/base/protocol/exact-protocol.d.ts.map +1 -0
  8. package/dist/base/protocol/exact-protocol.js +175 -0
  9. package/dist/base/protocol/exact-protocol.js.map +1 -0
  10. package/dist/base/types/core.d.ts +1 -1
  11. package/dist/base/types/core.d.ts.map +1 -1
  12. package/dist/base/types/core.js +1 -0
  13. package/dist/base/types/core.js.map +1 -1
  14. package/dist/base/utils/workspace-path.d.ts +6 -0
  15. package/dist/base/utils/workspace-path.d.ts.map +1 -0
  16. package/dist/base/utils/workspace-path.js +24 -0
  17. package/dist/base/utils/workspace-path.js.map +1 -0
  18. package/dist/index.d.ts +4 -0
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +2 -0
  21. package/dist/index.js.map +1 -1
  22. package/dist/interface/chat/chat-event-state.d.ts +2 -0
  23. package/dist/interface/chat/chat-event-state.d.ts.map +1 -1
  24. package/dist/interface/chat/chat-event-state.js +22 -41
  25. package/dist/interface/chat/chat-event-state.js.map +1 -1
  26. package/dist/interface/chat/chat-events.d.ts +15 -1
  27. package/dist/interface/chat/chat-events.d.ts.map +1 -1
  28. package/dist/interface/chat/chat-history.d.ts +3816 -192
  29. package/dist/interface/chat/chat-history.d.ts.map +1 -1
  30. package/dist/interface/chat/chat-history.js +529 -5
  31. package/dist/interface/chat/chat-history.js.map +1 -1
  32. package/dist/interface/chat/chat-runner-commands.d.ts.map +1 -1
  33. package/dist/interface/chat/chat-runner-commands.js +22 -18
  34. package/dist/interface/chat/chat-runner-commands.js.map +1 -1
  35. package/dist/interface/chat/chat-runner-contracts.d.ts +5 -1
  36. package/dist/interface/chat/chat-runner-contracts.d.ts.map +1 -1
  37. package/dist/interface/chat/chat-runner-event-bridge.d.ts +13 -1
  38. package/dist/interface/chat/chat-runner-event-bridge.d.ts.map +1 -1
  39. package/dist/interface/chat/chat-runner-event-bridge.js +51 -3
  40. package/dist/interface/chat/chat-runner-event-bridge.js.map +1 -1
  41. package/dist/interface/chat/chat-runner-routes.d.ts +5 -17
  42. package/dist/interface/chat/chat-runner-routes.d.ts.map +1 -1
  43. package/dist/interface/chat/chat-runner-routes.js +80 -51
  44. package/dist/interface/chat/chat-runner-routes.js.map +1 -1
  45. package/dist/interface/chat/chat-runner-runtime.d.ts.map +1 -1
  46. package/dist/interface/chat/chat-runner-runtime.js +4 -0
  47. package/dist/interface/chat/chat-runner-runtime.js.map +1 -1
  48. package/dist/interface/chat/chat-runner.d.ts +7 -1
  49. package/dist/interface/chat/chat-runner.d.ts.map +1 -1
  50. package/dist/interface/chat/chat-runner.js +135 -49
  51. package/dist/interface/chat/chat-runner.js.map +1 -1
  52. package/dist/interface/chat/chat-session-store.d.ts +3 -0
  53. package/dist/interface/chat/chat-session-store.d.ts.map +1 -1
  54. package/dist/interface/chat/chat-session-store.js +12 -0
  55. package/dist/interface/chat/chat-session-store.js.map +1 -1
  56. package/dist/interface/chat/cross-platform-session.d.ts +15 -0
  57. package/dist/interface/chat/cross-platform-session.d.ts.map +1 -1
  58. package/dist/interface/chat/cross-platform-session.js +260 -42
  59. package/dist/interface/chat/cross-platform-session.js.map +1 -1
  60. package/dist/interface/chat/failure-recovery.d.ts.map +1 -1
  61. package/dist/interface/chat/failure-recovery.js +15 -1
  62. package/dist/interface/chat/failure-recovery.js.map +1 -1
  63. package/dist/interface/chat/freeform-route-classifier.d.ts +2 -2
  64. package/dist/interface/chat/ingress-router.d.ts +3 -0
  65. package/dist/interface/chat/ingress-router.d.ts.map +1 -1
  66. package/dist/interface/chat/ingress-router.js +3 -0
  67. package/dist/interface/chat/ingress-router.js.map +1 -1
  68. package/dist/interface/chat/model-request-builder.d.ts +37 -0
  69. package/dist/interface/chat/model-request-builder.d.ts.map +1 -0
  70. package/dist/interface/chat/model-request-builder.js +76 -0
  71. package/dist/interface/chat/model-request-builder.js.map +1 -0
  72. package/dist/interface/chat/turn-context.d.ts +200 -0
  73. package/dist/interface/chat/turn-context.d.ts.map +1 -0
  74. package/dist/interface/chat/turn-context.js +249 -0
  75. package/dist/interface/chat/turn-context.js.map +1 -0
  76. package/dist/interface/chat/turn-protocol.d.ts +35 -0
  77. package/dist/interface/chat/turn-protocol.d.ts.map +1 -0
  78. package/dist/interface/chat/turn-protocol.js +27 -0
  79. package/dist/interface/chat/turn-protocol.js.map +1 -0
  80. package/dist/interface/chat/user-input.d.ts +55 -0
  81. package/dist/interface/chat/user-input.d.ts.map +1 -0
  82. package/dist/interface/chat/user-input.js +52 -0
  83. package/dist/interface/chat/user-input.js.map +1 -0
  84. package/dist/interface/cli/cli-command-registry.d.ts +1 -1
  85. package/dist/interface/cli/cli-command-registry.d.ts.map +1 -1
  86. package/dist/interface/cli/cli-command-registry.js +12 -16
  87. package/dist/interface/cli/cli-command-registry.js.map +1 -1
  88. package/dist/interface/cli/commands/daemon-shared.d.ts +8 -0
  89. package/dist/interface/cli/commands/daemon-shared.d.ts.map +1 -1
  90. package/dist/interface/cli/commands/daemon-shared.js +18 -2
  91. package/dist/interface/cli/commands/daemon-shared.js.map +1 -1
  92. package/dist/interface/cli/commands/daemon.d.ts.map +1 -1
  93. package/dist/interface/cli/commands/daemon.js +5 -1
  94. package/dist/interface/cli/commands/daemon.js.map +1 -1
  95. package/dist/interface/cli/commands/doctor.d.ts.map +1 -1
  96. package/dist/interface/cli/commands/doctor.js +14 -1
  97. package/dist/interface/cli/commands/doctor.js.map +1 -1
  98. package/dist/interface/cli/commands/goal-dispatch.d.ts.map +1 -1
  99. package/dist/interface/cli/commands/goal-dispatch.js +10 -6
  100. package/dist/interface/cli/commands/goal-dispatch.js.map +1 -1
  101. package/dist/interface/cli/commands/goal-utils.d.ts.map +1 -1
  102. package/dist/interface/cli/commands/goal-utils.js +3 -5
  103. package/dist/interface/cli/commands/goal-utils.js.map +1 -1
  104. package/dist/interface/cli/commands/run.d.ts.map +1 -1
  105. package/dist/interface/cli/commands/run.js +50 -0
  106. package/dist/interface/cli/commands/run.js.map +1 -1
  107. package/dist/interface/cli/setup.d.ts +1 -1
  108. package/dist/interface/cli/setup.d.ts.map +1 -1
  109. package/dist/interface/cli/setup.js +4 -3
  110. package/dist/interface/cli/setup.js.map +1 -1
  111. package/dist/interface/cli/utils/loop-runner.d.ts +1 -0
  112. package/dist/interface/cli/utils/loop-runner.d.ts.map +1 -1
  113. package/dist/interface/cli/utils/loop-runner.js +12 -3
  114. package/dist/interface/cli/utils/loop-runner.js.map +1 -1
  115. package/dist/interface/tui/app.d.ts +6 -1
  116. package/dist/interface/tui/app.d.ts.map +1 -1
  117. package/dist/interface/tui/app.js +29 -12
  118. package/dist/interface/tui/app.js.map +1 -1
  119. package/dist/interface/tui/bash-mode.d.ts.map +1 -1
  120. package/dist/interface/tui/bash-mode.js +2 -9
  121. package/dist/interface/tui/bash-mode.js.map +1 -1
  122. package/dist/interface/tui/chat/viewport.d.ts.map +1 -1
  123. package/dist/interface/tui/chat/viewport.js +57 -11
  124. package/dist/interface/tui/chat/viewport.js.map +1 -1
  125. package/dist/interface/tui/entry-deps.d.ts +6 -1
  126. package/dist/interface/tui/entry-deps.d.ts.map +1 -1
  127. package/dist/interface/tui/entry-deps.js +3 -0
  128. package/dist/interface/tui/entry-deps.js.map +1 -1
  129. package/dist/interface/tui/entry.d.ts.map +1 -1
  130. package/dist/interface/tui/entry.js +6 -2
  131. package/dist/interface/tui/entry.js.map +1 -1
  132. package/dist/interface/tui/input-action.d.ts.map +1 -1
  133. package/dist/interface/tui/input-action.js +3 -2
  134. package/dist/interface/tui/input-action.js.map +1 -1
  135. package/dist/interface/tui/intent-recognizer.d.ts.map +1 -1
  136. package/dist/interface/tui/intent-recognizer.js +21 -33
  137. package/dist/interface/tui/intent-recognizer.js.map +1 -1
  138. package/dist/orchestrator/execution/adapter-layer.d.ts +6 -1
  139. package/dist/orchestrator/execution/adapter-layer.d.ts.map +1 -1
  140. package/dist/orchestrator/execution/adapter-layer.js.map +1 -1
  141. package/dist/orchestrator/execution/agent-loop/agent-loop-command-classifier.d.ts +12 -1
  142. package/dist/orchestrator/execution/agent-loop/agent-loop-command-classifier.d.ts.map +1 -1
  143. package/dist/orchestrator/execution/agent-loop/agent-loop-command-classifier.js +16 -31
  144. package/dist/orchestrator/execution/agent-loop/agent-loop-command-classifier.js.map +1 -1
  145. package/dist/orchestrator/execution/agent-loop/agent-loop-compaction-record.d.ts +75 -0
  146. package/dist/orchestrator/execution/agent-loop/agent-loop-compaction-record.d.ts.map +1 -0
  147. package/dist/orchestrator/execution/agent-loop/agent-loop-compaction-record.js +10 -0
  148. package/dist/orchestrator/execution/agent-loop/agent-loop-compaction-record.js.map +1 -0
  149. package/dist/orchestrator/execution/agent-loop/agent-loop-compactor.d.ts +3 -2
  150. package/dist/orchestrator/execution/agent-loop/agent-loop-compactor.d.ts.map +1 -1
  151. package/dist/orchestrator/execution/agent-loop/agent-loop-compactor.js +185 -22
  152. package/dist/orchestrator/execution/agent-loop/agent-loop-compactor.js.map +1 -1
  153. package/dist/orchestrator/execution/agent-loop/agent-loop-default-profile.d.ts.map +1 -1
  154. package/dist/orchestrator/execution/agent-loop/agent-loop-default-profile.js +7 -1
  155. package/dist/orchestrator/execution/agent-loop/agent-loop-default-profile.js.map +1 -1
  156. package/dist/orchestrator/execution/agent-loop/agent-loop-events.d.ts +8 -1
  157. package/dist/orchestrator/execution/agent-loop/agent-loop-events.d.ts.map +1 -1
  158. package/dist/orchestrator/execution/agent-loop/agent-loop-events.js.map +1 -1
  159. package/dist/orchestrator/execution/agent-loop/agent-loop-history.d.ts +3 -1
  160. package/dist/orchestrator/execution/agent-loop/agent-loop-history.d.ts.map +1 -1
  161. package/dist/orchestrator/execution/agent-loop/agent-loop-history.js +12 -3
  162. package/dist/orchestrator/execution/agent-loop/agent-loop-history.js.map +1 -1
  163. package/dist/orchestrator/execution/agent-loop/agent-loop-model-client.d.ts.map +1 -1
  164. package/dist/orchestrator/execution/agent-loop/agent-loop-model-client.js +7 -1
  165. package/dist/orchestrator/execution/agent-loop/agent-loop-model-client.js.map +1 -1
  166. package/dist/orchestrator/execution/agent-loop/agent-loop-model.d.ts +37 -0
  167. package/dist/orchestrator/execution/agent-loop/agent-loop-model.d.ts.map +1 -1
  168. package/dist/orchestrator/execution/agent-loop/agent-loop-model.js +21 -0
  169. package/dist/orchestrator/execution/agent-loop/agent-loop-model.js.map +1 -1
  170. package/dist/orchestrator/execution/agent-loop/agent-loop-result.d.ts +17 -11
  171. package/dist/orchestrator/execution/agent-loop/agent-loop-result.d.ts.map +1 -1
  172. package/dist/orchestrator/execution/agent-loop/agent-loop-session-state.d.ts +4 -0
  173. package/dist/orchestrator/execution/agent-loop/agent-loop-session-state.d.ts.map +1 -1
  174. package/dist/orchestrator/execution/agent-loop/agent-loop-session-state.js +135 -0
  175. package/dist/orchestrator/execution/agent-loop/agent-loop-session-state.js.map +1 -1
  176. package/dist/orchestrator/execution/agent-loop/agent-loop-tool-runtime.d.ts +3 -2
  177. package/dist/orchestrator/execution/agent-loop/agent-loop-tool-runtime.d.ts.map +1 -1
  178. package/dist/orchestrator/execution/agent-loop/agent-loop-tool-runtime.js +68 -61
  179. package/dist/orchestrator/execution/agent-loop/agent-loop-tool-runtime.js.map +1 -1
  180. package/dist/orchestrator/execution/agent-loop/agent-loop-turn-context.d.ts +3 -1
  181. package/dist/orchestrator/execution/agent-loop/agent-loop-turn-context.d.ts.map +1 -1
  182. package/dist/orchestrator/execution/agent-loop/agent-loop-turn-context.js.map +1 -1
  183. package/dist/orchestrator/execution/agent-loop/agent-timeline.d.ts +12 -1
  184. package/dist/orchestrator/execution/agent-loop/agent-timeline.d.ts.map +1 -1
  185. package/dist/orchestrator/execution/agent-loop/agent-timeline.js +19 -56
  186. package/dist/orchestrator/execution/agent-loop/agent-timeline.js.map +1 -1
  187. package/dist/orchestrator/execution/agent-loop/anthropic-messages-agent-loop-model-client.d.ts.map +1 -1
  188. package/dist/orchestrator/execution/agent-loop/anthropic-messages-agent-loop-model-client.js +8 -2
  189. package/dist/orchestrator/execution/agent-loop/anthropic-messages-agent-loop-model-client.js.map +1 -1
  190. package/dist/orchestrator/execution/agent-loop/bounded-agent-loop-runner.d.ts +12 -0
  191. package/dist/orchestrator/execution/agent-loop/bounded-agent-loop-runner.d.ts.map +1 -1
  192. package/dist/orchestrator/execution/agent-loop/bounded-agent-loop-runner.js +400 -80
  193. package/dist/orchestrator/execution/agent-loop/bounded-agent-loop-runner.js.map +1 -1
  194. package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.d.ts +1 -1
  195. package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.d.ts.map +1 -1
  196. package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.js +80 -12
  197. package/dist/orchestrator/execution/agent-loop/chat-agent-loop-runner.js.map +1 -1
  198. package/dist/orchestrator/execution/agent-loop/chat-display-output.d.ts +1 -0
  199. package/dist/orchestrator/execution/agent-loop/chat-display-output.d.ts.map +1 -1
  200. package/dist/orchestrator/execution/agent-loop/chat-display-output.js +3 -1
  201. package/dist/orchestrator/execution/agent-loop/chat-display-output.js.map +1 -1
  202. package/dist/orchestrator/execution/agent-loop/index.d.ts +3 -0
  203. package/dist/orchestrator/execution/agent-loop/index.d.ts.map +1 -1
  204. package/dist/orchestrator/execution/agent-loop/index.js +3 -0
  205. package/dist/orchestrator/execution/agent-loop/index.js.map +1 -1
  206. package/dist/orchestrator/execution/agent-loop/openai-responses-agent-loop-model-client.d.ts +1 -0
  207. package/dist/orchestrator/execution/agent-loop/openai-responses-agent-loop-model-client.d.ts.map +1 -1
  208. package/dist/orchestrator/execution/agent-loop/openai-responses-agent-loop-model-client.js +51 -9
  209. package/dist/orchestrator/execution/agent-loop/openai-responses-agent-loop-model-client.js.map +1 -1
  210. package/dist/orchestrator/execution/agent-loop/response-item-tool-router.d.ts +20 -0
  211. package/dist/orchestrator/execution/agent-loop/response-item-tool-router.d.ts.map +1 -0
  212. package/dist/orchestrator/execution/agent-loop/response-item-tool-router.js +180 -0
  213. package/dist/orchestrator/execution/agent-loop/response-item-tool-router.js.map +1 -0
  214. package/dist/orchestrator/execution/agent-loop/response-item.d.ts +805 -0
  215. package/dist/orchestrator/execution/agent-loop/response-item.d.ts.map +1 -0
  216. package/dist/orchestrator/execution/agent-loop/response-item.js +104 -0
  217. package/dist/orchestrator/execution/agent-loop/response-item.js.map +1 -0
  218. package/dist/orchestrator/execution/agent-loop/task-agent-loop-context.d.ts +7 -2
  219. package/dist/orchestrator/execution/agent-loop/task-agent-loop-context.d.ts.map +1 -1
  220. package/dist/orchestrator/execution/agent-loop/task-agent-loop-context.js +20 -1
  221. package/dist/orchestrator/execution/agent-loop/task-agent-loop-context.js.map +1 -1
  222. package/dist/orchestrator/execution/agent-loop/task-agent-loop-result.d.ts +5 -3
  223. package/dist/orchestrator/execution/agent-loop/task-agent-loop-result.d.ts.map +1 -1
  224. package/dist/orchestrator/execution/agent-loop/task-agent-loop-result.js +109 -10
  225. package/dist/orchestrator/execution/agent-loop/task-agent-loop-result.js.map +1 -1
  226. package/dist/orchestrator/execution/agent-loop/task-agent-loop-runner.d.ts +2 -0
  227. package/dist/orchestrator/execution/agent-loop/task-agent-loop-runner.d.ts.map +1 -1
  228. package/dist/orchestrator/execution/agent-loop/task-agent-loop-runner.js +9 -4
  229. package/dist/orchestrator/execution/agent-loop/task-agent-loop-runner.js.map +1 -1
  230. package/dist/orchestrator/execution/agent-loop/task-agent-loop-verification.d.ts +0 -1
  231. package/dist/orchestrator/execution/agent-loop/task-agent-loop-verification.d.ts.map +1 -1
  232. package/dist/orchestrator/execution/agent-loop/task-agent-loop-verification.js +7 -87
  233. package/dist/orchestrator/execution/agent-loop/task-agent-loop-verification.js.map +1 -1
  234. package/dist/orchestrator/execution/agent-loop/task-agent-loop-worktree.d.ts.map +1 -1
  235. package/dist/orchestrator/execution/agent-loop/task-agent-loop-worktree.js +25 -0
  236. package/dist/orchestrator/execution/agent-loop/task-agent-loop-worktree.js.map +1 -1
  237. package/dist/orchestrator/execution/context/issue-context-fetcher.d.ts +5 -1
  238. package/dist/orchestrator/execution/context/issue-context-fetcher.d.ts.map +1 -1
  239. package/dist/orchestrator/execution/context/issue-context-fetcher.js +7 -4
  240. package/dist/orchestrator/execution/context/issue-context-fetcher.js.map +1 -1
  241. package/dist/orchestrator/execution/task/task-artifact-contract.d.ts +18 -0
  242. package/dist/orchestrator/execution/task/task-artifact-contract.d.ts.map +1 -0
  243. package/dist/orchestrator/execution/task/task-artifact-contract.js +176 -0
  244. package/dist/orchestrator/execution/task/task-artifact-contract.js.map +1 -0
  245. package/dist/orchestrator/execution/task/task-diff-capture.d.ts +14 -1
  246. package/dist/orchestrator/execution/task/task-diff-capture.d.ts.map +1 -1
  247. package/dist/orchestrator/execution/task/task-diff-capture.js +269 -17
  248. package/dist/orchestrator/execution/task/task-diff-capture.js.map +1 -1
  249. package/dist/orchestrator/execution/task/task-execution-helpers.d.ts +1 -0
  250. package/dist/orchestrator/execution/task/task-execution-helpers.d.ts.map +1 -1
  251. package/dist/orchestrator/execution/task/task-execution-helpers.js +76 -17
  252. package/dist/orchestrator/execution/task/task-execution-helpers.js.map +1 -1
  253. package/dist/orchestrator/execution/task/task-executor.d.ts +16 -1
  254. package/dist/orchestrator/execution/task/task-executor.d.ts.map +1 -1
  255. package/dist/orchestrator/execution/task/task-executor.js +55 -50
  256. package/dist/orchestrator/execution/task/task-executor.js.map +1 -1
  257. package/dist/orchestrator/execution/task/task-generation.d.ts +54 -1
  258. package/dist/orchestrator/execution/task/task-generation.d.ts.map +1 -1
  259. package/dist/orchestrator/execution/task/task-generation.js +19 -3
  260. package/dist/orchestrator/execution/task/task-generation.js.map +1 -1
  261. package/dist/orchestrator/execution/task/task-lifecycle-runner.d.ts +2 -2
  262. package/dist/orchestrator/execution/task/task-lifecycle-runner.d.ts.map +1 -1
  263. package/dist/orchestrator/execution/task/task-lifecycle-runner.js +31 -4
  264. package/dist/orchestrator/execution/task/task-lifecycle-runner.js.map +1 -1
  265. package/dist/orchestrator/execution/task/task-lifecycle.d.ts +3 -3
  266. package/dist/orchestrator/execution/task/task-lifecycle.d.ts.map +1 -1
  267. package/dist/orchestrator/execution/task/task-lifecycle.js +51 -10
  268. package/dist/orchestrator/execution/task/task-lifecycle.js.map +1 -1
  269. package/dist/orchestrator/execution/task/task-outcome-ledger.d.ts +8 -0
  270. package/dist/orchestrator/execution/task/task-outcome-ledger.d.ts.map +1 -1
  271. package/dist/orchestrator/execution/task/task-outcome-ledger.js +59 -3
  272. package/dist/orchestrator/execution/task/task-outcome-ledger.js.map +1 -1
  273. package/dist/orchestrator/execution/task/task-prompt-builder.d.ts +3 -1
  274. package/dist/orchestrator/execution/task/task-prompt-builder.d.ts.map +1 -1
  275. package/dist/orchestrator/execution/task/task-prompt-builder.js +23 -12
  276. package/dist/orchestrator/execution/task/task-prompt-builder.js.map +1 -1
  277. package/dist/orchestrator/execution/task/task-verifier-rules.d.ts +3 -2
  278. package/dist/orchestrator/execution/task/task-verifier-rules.d.ts.map +1 -1
  279. package/dist/orchestrator/execution/task/task-verifier-rules.js +328 -90
  280. package/dist/orchestrator/execution/task/task-verifier-rules.js.map +1 -1
  281. package/dist/orchestrator/execution/task/task-verifier-types.d.ts +13 -0
  282. package/dist/orchestrator/execution/task/task-verifier-types.d.ts.map +1 -1
  283. package/dist/orchestrator/execution/task/task-verifier-types.js.map +1 -1
  284. package/dist/orchestrator/execution/task/task-verifier.d.ts +5 -4
  285. package/dist/orchestrator/execution/task/task-verifier.d.ts.map +1 -1
  286. package/dist/orchestrator/execution/task/task-verifier.js +229 -22
  287. package/dist/orchestrator/execution/task/task-verifier.js.map +1 -1
  288. package/dist/orchestrator/execution/task/task-workspace.d.ts +5 -0
  289. package/dist/orchestrator/execution/task/task-workspace.d.ts.map +1 -1
  290. package/dist/orchestrator/execution/task/task-workspace.js +20 -10
  291. package/dist/orchestrator/execution/task/task-workspace.js.map +1 -1
  292. package/dist/orchestrator/execution/types/task-group.d.ts +76 -5
  293. package/dist/orchestrator/execution/types/task-group.d.ts.map +1 -1
  294. package/dist/orchestrator/execution/types/task.d.ts +117 -3
  295. package/dist/orchestrator/execution/types/task.d.ts.map +1 -1
  296. package/dist/orchestrator/execution/types/task.js +12 -0
  297. package/dist/orchestrator/execution/types/task.js.map +1 -1
  298. package/dist/orchestrator/loop/durable-loop/preparation.d.ts.map +1 -1
  299. package/dist/orchestrator/loop/durable-loop/preparation.js +7 -1
  300. package/dist/orchestrator/loop/durable-loop/preparation.js.map +1 -1
  301. package/dist/platform/corrections/memory-correction-ledger.d.ts +30 -30
  302. package/dist/platform/corrections/memory-governance.d.ts +2 -2
  303. package/dist/platform/knowledge/types/agent-memory.d.ts +30 -30
  304. package/dist/platform/observation/context-provider/collector.d.ts.map +1 -1
  305. package/dist/platform/observation/context-provider/collector.js +89 -24
  306. package/dist/platform/observation/context-provider/collector.js.map +1 -1
  307. package/dist/platform/observation/data-source-adapter.d.ts +2 -0
  308. package/dist/platform/observation/data-source-adapter.d.ts.map +1 -1
  309. package/dist/platform/observation/data-source-adapter.js.map +1 -1
  310. package/dist/platform/observation/observation-apply.d.ts.map +1 -1
  311. package/dist/platform/observation/observation-apply.js +8 -2
  312. package/dist/platform/observation/observation-apply.js.map +1 -1
  313. package/dist/platform/observation/observation-engine.d.ts.map +1 -1
  314. package/dist/platform/observation/observation-engine.js +118 -70
  315. package/dist/platform/observation/observation-engine.js.map +1 -1
  316. package/dist/platform/observation/observation-helpers.d.ts +2 -0
  317. package/dist/platform/observation/observation-helpers.d.ts.map +1 -1
  318. package/dist/platform/observation/observation-helpers.js.map +1 -1
  319. package/dist/platform/observation/types/data-source.d.ts +48 -0
  320. package/dist/platform/observation/types/data-source.d.ts.map +1 -1
  321. package/dist/platform/observation/types/data-source.js +4 -0
  322. package/dist/platform/observation/types/data-source.js.map +1 -1
  323. package/dist/platform/observation/workspace-context.d.ts.map +1 -1
  324. package/dist/platform/observation/workspace-context.js +13 -18
  325. package/dist/platform/observation/workspace-context.js.map +1 -1
  326. package/dist/platform/soil/contracts.d.ts +56 -56
  327. package/dist/reporting/types/report.d.ts +7 -0
  328. package/dist/reporting/types/report.d.ts.map +1 -1
  329. package/dist/runtime/approval-broker.d.ts +12 -0
  330. package/dist/runtime/approval-broker.d.ts.map +1 -1
  331. package/dist/runtime/approval-broker.js +27 -7
  332. package/dist/runtime/approval-broker.js.map +1 -1
  333. package/dist/runtime/control/daemon-runtime-control-executor.d.ts.map +1 -1
  334. package/dist/runtime/control/daemon-runtime-control-executor.js +9 -4
  335. package/dist/runtime/control/daemon-runtime-control-executor.js.map +1 -1
  336. package/dist/runtime/control/runtime-control-intent.d.ts.map +1 -1
  337. package/dist/runtime/control/runtime-control-intent.js +3 -2
  338. package/dist/runtime/control/runtime-control-intent.js.map +1 -1
  339. package/dist/runtime/control/runtime-control-service.d.ts +2 -1
  340. package/dist/runtime/control/runtime-control-service.d.ts.map +1 -1
  341. package/dist/runtime/control/runtime-control-service.js +9 -2
  342. package/dist/runtime/control/runtime-control-service.js.map +1 -1
  343. package/dist/runtime/control/runtime-target-resolver.js +2 -0
  344. package/dist/runtime/control/runtime-target-resolver.js.map +1 -1
  345. package/dist/runtime/daemon/runner-goal-cycle.d.ts.map +1 -1
  346. package/dist/runtime/daemon/runner-goal-cycle.js +1 -2
  347. package/dist/runtime/daemon/runner-goal-cycle.js.map +1 -1
  348. package/dist/runtime/daemon/runner-recovery.d.ts +17 -3
  349. package/dist/runtime/daemon/runner-recovery.d.ts.map +1 -1
  350. package/dist/runtime/daemon/runner-recovery.js +50 -12
  351. package/dist/runtime/daemon/runner-recovery.js.map +1 -1
  352. package/dist/runtime/daemon/runner-startup.d.ts.map +1 -1
  353. package/dist/runtime/daemon/runner-startup.js +18 -1
  354. package/dist/runtime/daemon/runner-startup.js.map +1 -1
  355. package/dist/runtime/daemon/runner.d.ts.map +1 -1
  356. package/dist/runtime/daemon/runner.js +3 -2
  357. package/dist/runtime/daemon/runner.js.map +1 -1
  358. package/dist/runtime/daemon/runtime-ownership.d.ts +0 -1
  359. package/dist/runtime/daemon/runtime-ownership.d.ts.map +1 -1
  360. package/dist/runtime/daemon/runtime-ownership.js +18 -18
  361. package/dist/runtime/daemon/runtime-ownership.js.map +1 -1
  362. package/dist/runtime/daemon/wait-deadline-resolver.d.ts.map +1 -1
  363. package/dist/runtime/daemon/wait-deadline-resolver.js +2 -0
  364. package/dist/runtime/daemon/wait-deadline-resolver.js.map +1 -1
  365. package/dist/runtime/evidence-answer.d.ts.map +1 -1
  366. package/dist/runtime/evidence-answer.js +34 -7
  367. package/dist/runtime/evidence-answer.js.map +1 -1
  368. package/dist/runtime/gateway/channel-adapter.d.ts +3 -0
  369. package/dist/runtime/gateway/channel-adapter.d.ts.map +1 -1
  370. package/dist/runtime/gateway/channel-display-policy.d.ts +42 -0
  371. package/dist/runtime/gateway/channel-display-policy.d.ts.map +1 -0
  372. package/dist/runtime/gateway/channel-display-policy.js +85 -0
  373. package/dist/runtime/gateway/channel-display-policy.js.map +1 -0
  374. package/dist/runtime/gateway/chat-event-rendering.d.ts +2 -1
  375. package/dist/runtime/gateway/chat-event-rendering.d.ts.map +1 -1
  376. package/dist/runtime/gateway/chat-event-rendering.js +2 -0
  377. package/dist/runtime/gateway/chat-event-rendering.js.map +1 -1
  378. package/dist/runtime/gateway/chat-session-dispatch.d.ts.map +1 -1
  379. package/dist/runtime/gateway/chat-session-dispatch.js +4 -9
  380. package/dist/runtime/gateway/chat-session-dispatch.js.map +1 -1
  381. package/dist/runtime/gateway/chat-session-port.d.ts +2 -0
  382. package/dist/runtime/gateway/chat-session-port.d.ts.map +1 -1
  383. package/dist/runtime/gateway/chat-session-port.js.map +1 -1
  384. package/dist/runtime/gateway/discord-gateway-adapter.d.ts +4 -0
  385. package/dist/runtime/gateway/discord-gateway-adapter.d.ts.map +1 -1
  386. package/dist/runtime/gateway/discord-gateway-adapter.js +100 -31
  387. package/dist/runtime/gateway/discord-gateway-adapter.js.map +1 -1
  388. package/dist/runtime/gateway/index.d.ts +4 -0
  389. package/dist/runtime/gateway/index.d.ts.map +1 -1
  390. package/dist/runtime/gateway/index.js +2 -0
  391. package/dist/runtime/gateway/index.js.map +1 -1
  392. package/dist/runtime/gateway/non-tui-display-projector.d.ts +40 -0
  393. package/dist/runtime/gateway/non-tui-display-projector.d.ts.map +1 -0
  394. package/dist/runtime/gateway/non-tui-display-projector.js +166 -0
  395. package/dist/runtime/gateway/non-tui-display-projector.js.map +1 -0
  396. package/dist/runtime/gateway/signal-gateway-adapter.d.ts +1 -0
  397. package/dist/runtime/gateway/signal-gateway-adapter.d.ts.map +1 -1
  398. package/dist/runtime/gateway/signal-gateway-adapter.js +47 -4
  399. package/dist/runtime/gateway/signal-gateway-adapter.js.map +1 -1
  400. package/dist/runtime/gateway/slack-channel-adapter.d.ts +1 -0
  401. package/dist/runtime/gateway/slack-channel-adapter.d.ts.map +1 -1
  402. package/dist/runtime/gateway/slack-channel-adapter.js +93 -18
  403. package/dist/runtime/gateway/slack-channel-adapter.js.map +1 -1
  404. package/dist/runtime/gateway/telegram-gateway-adapter.d.ts +2 -0
  405. package/dist/runtime/gateway/telegram-gateway-adapter.d.ts.map +1 -1
  406. package/dist/runtime/gateway/telegram-gateway-adapter.js +61 -113
  407. package/dist/runtime/gateway/telegram-gateway-adapter.js.map +1 -1
  408. package/dist/runtime/gateway/whatsapp-gateway-adapter.d.ts +1 -0
  409. package/dist/runtime/gateway/whatsapp-gateway-adapter.d.ts.map +1 -1
  410. package/dist/runtime/gateway/whatsapp-gateway-adapter.js +49 -4
  411. package/dist/runtime/gateway/whatsapp-gateway-adapter.js.map +1 -1
  412. package/dist/runtime/permission-dialogue.d.ts +113 -0
  413. package/dist/runtime/permission-dialogue.d.ts.map +1 -0
  414. package/dist/runtime/permission-dialogue.js +82 -0
  415. package/dist/runtime/permission-dialogue.js.map +1 -0
  416. package/dist/runtime/run-spec/derive.d.ts +14 -14
  417. package/dist/runtime/run-spec/handoff.js +2 -0
  418. package/dist/runtime/run-spec/handoff.js.map +1 -1
  419. package/dist/runtime/run-spec/types.d.ts +16 -16
  420. package/dist/runtime/session-registry/types.d.ts +12 -12
  421. package/dist/runtime/store/artifact-retention.d.ts +2 -0
  422. package/dist/runtime/store/artifact-retention.d.ts.map +1 -1
  423. package/dist/runtime/store/artifact-retention.js +24 -21
  424. package/dist/runtime/store/artifact-retention.js.map +1 -1
  425. package/dist/runtime/store/budget-store.d.ts +8 -8
  426. package/dist/runtime/store/evidence-ledger.d.ts.map +1 -1
  427. package/dist/runtime/store/evidence-ledger.js +39 -1
  428. package/dist/runtime/store/evidence-ledger.js.map +1 -1
  429. package/dist/runtime/store/evidence-types.d.ts +118 -118
  430. package/dist/runtime/store/experiment-queue-store.d.ts +20 -20
  431. package/dist/runtime/store/reproducibility-manifest.d.ts +20 -20
  432. package/dist/runtime/store/runtime-operation-schemas.d.ts +18 -18
  433. package/dist/runtime/store/runtime-operation-schemas.d.ts.map +1 -1
  434. package/dist/runtime/store/runtime-operation-schemas.js +1 -0
  435. package/dist/runtime/store/runtime-operation-schemas.js.map +1 -1
  436. package/dist/runtime/store/runtime-schemas.d.ts +58 -28
  437. package/dist/runtime/store/runtime-schemas.d.ts.map +1 -1
  438. package/dist/runtime/store/runtime-schemas.js +1 -0
  439. package/dist/runtime/store/runtime-schemas.js.map +1 -1
  440. package/dist/tools/execution/MemorySaveTool/MemorySaveTool.d.ts +8 -8
  441. package/dist/tools/execution/RunAdapterTool/RunAdapterTool.d.ts +6 -0
  442. package/dist/tools/execution/RunAdapterTool/RunAdapterTool.d.ts.map +1 -1
  443. package/dist/tools/execution/RunAdapterTool/RunAdapterTool.js +2 -0
  444. package/dist/tools/execution/RunAdapterTool/RunAdapterTool.js.map +1 -1
  445. package/dist/tools/execution-orchestrator.d.ts +29 -0
  446. package/dist/tools/execution-orchestrator.d.ts.map +1 -0
  447. package/dist/tools/execution-orchestrator.js +153 -0
  448. package/dist/tools/execution-orchestrator.js.map +1 -0
  449. package/dist/tools/executor.d.ts +6 -0
  450. package/dist/tools/executor.d.ts.map +1 -1
  451. package/dist/tools/executor.js +48 -11
  452. package/dist/tools/executor.js.map +1 -1
  453. package/dist/tools/fs/ApplyPatchTool/ApplyPatchTool.d.ts.map +1 -1
  454. package/dist/tools/fs/ApplyPatchTool/ApplyPatchTool.js +130 -17
  455. package/dist/tools/fs/ApplyPatchTool/ApplyPatchTool.js.map +1 -1
  456. package/dist/tools/mutation/TaskStopTool/TaskStopTool.d.ts.map +1 -1
  457. package/dist/tools/mutation/TaskStopTool/TaskStopTool.js +8 -0
  458. package/dist/tools/mutation/TaskStopTool/TaskStopTool.js.map +1 -1
  459. package/dist/tools/mutation/TaskUpdateTool/TaskUpdateTool.d.ts +6 -6
  460. package/dist/tools/network/GitHubCliTool/GitHubCliTool.d.ts +4 -4
  461. package/dist/tools/network/McpStdioTool/McpStdioTool.d.ts +4 -4
  462. package/dist/tools/permission.d.ts +0 -1
  463. package/dist/tools/permission.d.ts.map +1 -1
  464. package/dist/tools/permission.js +9 -33
  465. package/dist/tools/permission.js.map +1 -1
  466. package/dist/tools/query/CodeReadContextTool/CodeReadContextTool.d.ts +4 -4
  467. package/dist/tools/query/CodeSearchRepairTool/CodeSearchRepairTool.d.ts +8 -8
  468. package/dist/tools/query/CodeSearchTool/CodeSearchTool.d.ts +4 -4
  469. package/dist/tools/query/MemoryRecallTool/MemoryRecallTool.d.ts +4 -4
  470. package/dist/tools/query/runtime-session-tools.d.ts +73 -5
  471. package/dist/tools/query/runtime-session-tools.d.ts.map +1 -1
  472. package/dist/tools/query/runtime-session-tools.js +114 -0
  473. package/dist/tools/query/runtime-session-tools.js.map +1 -1
  474. package/dist/tools/runtime/LongRunningRuntimeTools.d.ts +60 -42
  475. package/dist/tools/runtime/LongRunningRuntimeTools.d.ts.map +1 -1
  476. package/dist/tools/runtime/LongRunningRuntimeTools.js +4 -1
  477. package/dist/tools/runtime/LongRunningRuntimeTools.js.map +1 -1
  478. package/dist/tools/runtime/RunSpecHandoffTools.d.ts.map +1 -1
  479. package/dist/tools/runtime/RunSpecHandoffTools.js +162 -2
  480. package/dist/tools/runtime/RunSpecHandoffTools.js.map +1 -1
  481. package/dist/tools/runtime/SetupRuntimeControlTools.d.ts.map +1 -1
  482. package/dist/tools/runtime/SetupRuntimeControlTools.js +169 -17
  483. package/dist/tools/runtime/SetupRuntimeControlTools.js.map +1 -1
  484. package/dist/tools/system/GitDiffTool/GitDiffTool.d.ts +4 -4
  485. package/dist/tools/system/ShellCommandTool/ShellCommandTool.d.ts.map +1 -1
  486. package/dist/tools/system/ShellCommandTool/ShellCommandTool.js +7 -1
  487. package/dist/tools/system/ShellCommandTool/ShellCommandTool.js.map +1 -1
  488. package/dist/tools/system/ShellTool/ShellTool.d.ts.map +1 -1
  489. package/dist/tools/system/ShellTool/ShellTool.js +24 -10
  490. package/dist/tools/system/ShellTool/ShellTool.js.map +1 -1
  491. package/dist/tools/system/ShellTool/command-policy.d.ts +11 -8
  492. package/dist/tools/system/ShellTool/command-policy.d.ts.map +1 -1
  493. package/dist/tools/system/ShellTool/command-policy.js +402 -98
  494. package/dist/tools/system/ShellTool/command-policy.js.map +1 -1
  495. package/dist/tools/system/TestRunnerTool/TestRunnerTool.d.ts +1 -1
  496. package/dist/tools/system/TestRunnerTool/TestRunnerTool.d.ts.map +1 -1
  497. package/dist/tools/system/TestRunnerTool/TestRunnerTool.js +152 -8
  498. package/dist/tools/system/TestRunnerTool/TestRunnerTool.js.map +1 -1
  499. package/dist/tools/system/UpdatePlanTool/UpdatePlanTool.js +1 -1
  500. package/dist/tools/system/UpdatePlanTool/UpdatePlanTool.js.map +1 -1
  501. package/dist/tools/types.d.ts +34 -12
  502. package/dist/tools/types.d.ts.map +1 -1
  503. package/dist/tools/types.js +26 -3
  504. package/dist/tools/types.js.map +1 -1
  505. package/dist/tools/workspace-scope.d.ts +11 -0
  506. package/dist/tools/workspace-scope.d.ts.map +1 -0
  507. package/dist/tools/workspace-scope.js +77 -0
  508. package/dist/tools/workspace-scope.js.map +1 -0
  509. package/package.json +1 -1
@@ -1,9 +1,37 @@
1
- import { randomUUID } from "node:crypto";
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import * as fsp from "node:fs/promises";
3
+ import * as path from "node:path";
2
4
  import { execFileNoThrow } from "../../../base/utils/execFileNoThrow.js";
3
5
  import { createAgentLoopHistory } from "./agent-loop-history.js";
4
6
  import { formatAgentLoopModelRef } from "./agent-loop-model.js";
5
7
  import { ExtractiveAgentLoopCompactor } from "./agent-loop-compactor.js";
8
+ import { cloneAgentLoopCompactionRecords } from "./agent-loop-compaction-record.js";
6
9
  import { classifyAgentLoopCommandResult } from "./agent-loop-command-classifier.js";
10
+ import { assistantTextResponseItem, functionToolCallResponseItem, } from "./response-item.js";
11
+ function readToolResultCheckOnly(result) {
12
+ const data = result.rawResult?.data;
13
+ if (result.toolName === "apply_patch" &&
14
+ data &&
15
+ typeof data === "object" &&
16
+ "checkOnly" in data &&
17
+ typeof data.checkOnly === "boolean") {
18
+ return data.checkOnly;
19
+ }
20
+ return undefined;
21
+ }
22
+ const FILESYSTEM_SNAPSHOT_EXCLUDED_DIRS = new Set([
23
+ ".git",
24
+ "node_modules",
25
+ ".venv",
26
+ "venv",
27
+ "__pycache__",
28
+ ".cache",
29
+ "dist",
30
+ "build",
31
+ ]);
32
+ const FILESYSTEM_SNAPSHOT_MAX_FILES = 5_000;
33
+ const FILESYSTEM_SNAPSHOT_HASH_MAX_BYTES = 1_000_000;
34
+ const MIN_MUTATING_TOOL_BATCH_REMAINING_MS = 1_000;
7
35
  export class BoundedAgentLoopRunner {
8
36
  deps;
9
37
  compactor;
@@ -22,12 +50,14 @@ export class BoundedAgentLoopRunner {
22
50
  let completionValidationAttempts = resumed?.completionValidationAttempts ?? 0;
23
51
  let finalText = resumed?.finalText ?? "";
24
52
  let compactions = resumed?.compactions ?? 0;
53
+ let compactionRecords = cloneAgentLoopCompactionRecords(resumed?.compactionRecords);
25
54
  const calledTools = new Set(resumed?.calledTools ?? []);
26
55
  let lastToolLoopSignature = resumed?.lastToolLoopSignature ?? null;
27
56
  let repeatedToolLoopCount = resumed?.repeatedToolLoopCount ?? 0;
28
57
  const commandResults = [];
29
58
  const toolResultSummaries = [];
30
59
  const initialWorkspaceSnapshot = await this.captureWorkspaceSnapshot(turn.cwd);
60
+ const stop = (reason, startedAt, modelTurns, toolCalls, finalText, output, success = false, compactions = 0, changedFiles = [], toolResults = [], commandResults = [], messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, completionValidationAttempts, reasonDetail, failureReason) => this.stop(turn, reason, startedAt, modelTurns, toolCalls, finalText, output, success, compactions, changedFiles, toolResults, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, completionValidationAttempts, reasonDetail, failureReason, compactionRecords);
31
61
  await this.record(turn, {
32
62
  type: "started",
33
63
  ...this.baseEvent(turn),
@@ -41,25 +71,26 @@ export class BoundedAgentLoopRunner {
41
71
  });
42
72
  }
43
73
  let messages = resumed?.messages ? [...resumed.messages] : [...turn.messages];
44
- const preTurnCompaction = await this.compactIfNeeded(turn, messages, "pre_turn", "context_limit", undefined, compactions);
74
+ const preTurnCompaction = await this.compactIfNeeded(turn, messages, "pre_turn", "context_limit", undefined, compactions, compactionRecords);
45
75
  if (preTurnCompaction.error) {
46
- return this.stop(turn, "fatal_error", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, [], toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
76
+ return stop("fatal_error", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, [], toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
47
77
  }
48
78
  messages = preTurnCompaction.messages;
79
+ compactionRecords = preTurnCompaction.compactionRecords;
49
80
  compactions += preTurnCompaction.compacted ? 1 : 0;
50
- await this.saveState(turn, messages, modelTurns, toolCalls, compactions, completionValidationAttempts, calledTools, lastToolLoopSignature, repeatedToolLoopCount, finalText, "running");
81
+ await this.saveState(turn, messages, compactionRecords, modelTurns, toolCalls, compactions, completionValidationAttempts, calledTools, lastToolLoopSignature, repeatedToolLoopCount, finalText, "running");
51
82
  while (true) {
52
83
  if (Date.now() - startedAt > turn.budget.maxWallClockMs) {
53
- return this.stop(turn, "timeout", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
84
+ return stop("timeout", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
54
85
  }
55
86
  if (modelTurns >= turn.budget.maxModelTurns) {
56
- return this.stop(turn, "max_model_turns", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
87
+ return stop("max_model_turns", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
57
88
  }
58
89
  if (toolCalls >= turn.budget.maxToolCalls) {
59
- return this.stop(turn, "max_tool_calls", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
90
+ return stop("max_tool_calls", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
60
91
  }
61
92
  if (turn.abortSignal?.aborted) {
62
- return this.stop(turn, "cancelled", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
93
+ return stop("cancelled", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
63
94
  }
64
95
  const tools = this.deps.toolRouter.modelVisibleTools(turn);
65
96
  if (modelTurns === 0) {
@@ -83,16 +114,16 @@ export class BoundedAgentLoopRunner {
83
114
  }
84
115
  catch (err) {
85
116
  if (turn.abortSignal?.aborted) {
86
- return this.stop(turn, "cancelled", startedAt, modelTurns, toolCalls, "Agent loop stopped: operator stop aborted active model work.", null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, completionValidationAttempts, err instanceof Error ? err.message : String(err));
117
+ return stop("cancelled", startedAt, modelTurns, toolCalls, "Agent loop stopped: operator stop aborted active model work.", null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, completionValidationAttempts, err instanceof Error ? err.message : String(err));
87
118
  }
88
119
  const failure = this.classifyRunFailure(err);
89
- return this.stop(turn, failure.reason, startedAt, modelTurns, toolCalls, failure.message, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, completionValidationAttempts, failure.detail);
120
+ return stop(failure.reason, startedAt, modelTurns, toolCalls, failure.message, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, completionValidationAttempts, failure.detail, failure.failureReason);
90
121
  }
91
122
  if (!protocol.responseCompleted) {
92
- return this.stop(turn, "protocol_incomplete", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
123
+ return stop("protocol_incomplete", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
93
124
  }
94
125
  if (turn.abortSignal?.aborted) {
95
- return this.stop(turn, "cancelled", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
126
+ return stop("cancelled", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
96
127
  }
97
128
  const response = this.protocolToResponse(protocol);
98
129
  modelTurns++;
@@ -111,20 +142,21 @@ export class BoundedAgentLoopRunner {
111
142
  if (response.content.trim().length === 0) {
112
143
  schemaRepairAttempts++;
113
144
  if (schemaRepairAttempts > turn.budget.maxSchemaRepairAttempts) {
114
- return this.stop(turn, "schema_error", startedAt, modelTurns, toolCalls, response.content, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
145
+ return stop("schema_error", startedAt, modelTurns, toolCalls, response.content, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
115
146
  }
116
147
  messages.push({ role: "assistant", content: response.content, phase: "final_answer" });
117
148
  messages.push({
118
149
  role: "user",
119
150
  content: "Your final answer was empty. Return a user-visible Markdown or plain text answer for the user.",
120
151
  });
121
- const compacted = await this.compactIfNeeded(turn, messages, "mid_turn", "context_limit", this.responseUsageTokens(protocol), compactions);
152
+ const compacted = await this.compactIfNeeded(turn, messages, "mid_turn", "context_limit", this.responseUsageTokens(protocol), compactions, compactionRecords);
122
153
  if (compacted.error) {
123
- return this.stop(turn, "fatal_error", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
154
+ return stop("fatal_error", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
124
155
  }
125
156
  messages = compacted.messages;
157
+ compactionRecords = compacted.compactionRecords;
126
158
  compactions += compacted.compacted ? 1 : 0;
127
- await this.saveState(turn, messages, modelTurns, toolCalls, compactions, completionValidationAttempts, calledTools, lastToolLoopSignature, repeatedToolLoopCount, finalText, "running");
159
+ await this.saveState(turn, messages, compactionRecords, modelTurns, toolCalls, compactions, completionValidationAttempts, calledTools, lastToolLoopSignature, repeatedToolLoopCount, finalText, "running");
128
160
  continue;
129
161
  }
130
162
  const missingRequiredTools = this.missingRequiredTools(turn, calledTools);
@@ -134,13 +166,14 @@ export class BoundedAgentLoopRunner {
134
166
  role: "user",
135
167
  content: `Before the final answer, call these required tool(s) at least once: ${missingRequiredTools.join(", ")}.`,
136
168
  });
137
- const compacted = await this.compactIfNeeded(turn, messages, "mid_turn", "context_limit", this.responseUsageTokens(protocol), compactions);
169
+ const compacted = await this.compactIfNeeded(turn, messages, "mid_turn", "context_limit", this.responseUsageTokens(protocol), compactions, compactionRecords);
138
170
  if (compacted.error) {
139
- return this.stop(turn, "fatal_error", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
171
+ return stop("fatal_error", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
140
172
  }
141
173
  messages = compacted.messages;
174
+ compactionRecords = compacted.compactionRecords;
142
175
  compactions += compacted.compacted ? 1 : 0;
143
- await this.saveState(turn, messages, modelTurns, toolCalls, compactions, completionValidationAttempts, calledTools, lastToolLoopSignature, repeatedToolLoopCount, finalText, "running");
176
+ await this.saveState(turn, messages, compactionRecords, modelTurns, toolCalls, compactions, completionValidationAttempts, calledTools, lastToolLoopSignature, repeatedToolLoopCount, finalText, "running");
144
177
  continue;
145
178
  }
146
179
  const changedFiles = await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot);
@@ -150,7 +183,7 @@ export class BoundedAgentLoopRunner {
150
183
  success: true,
151
184
  outputPreview: this.preview(response.content),
152
185
  });
153
- return this.stop(turn, "completed", startedAt, modelTurns, toolCalls, response.content, null, true, compactions, changedFiles, toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, completionValidationAttempts);
186
+ return stop("completed", startedAt, modelTurns, toolCalls, response.content, null, true, compactions, changedFiles, toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, completionValidationAttempts);
154
187
  }
155
188
  const parsed = this.parseFinal(response.content, turn.outputSchema);
156
189
  if (parsed.success) {
@@ -161,41 +194,45 @@ export class BoundedAgentLoopRunner {
161
194
  role: "user",
162
195
  content: `Before the final answer, call these required tool(s) at least once: ${missingRequiredTools.join(", ")}.`,
163
196
  });
164
- const compacted = await this.compactIfNeeded(turn, messages, "mid_turn", "context_limit", this.responseUsageTokens(protocol), compactions);
197
+ const compacted = await this.compactIfNeeded(turn, messages, "mid_turn", "context_limit", this.responseUsageTokens(protocol), compactions, compactionRecords);
165
198
  if (compacted.error) {
166
- return this.stop(turn, "fatal_error", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
199
+ return stop("fatal_error", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
167
200
  }
168
201
  messages = compacted.messages;
202
+ compactionRecords = compacted.compactionRecords;
169
203
  compactions += compacted.compacted ? 1 : 0;
170
- await this.saveState(turn, messages, modelTurns, toolCalls, compactions, completionValidationAttempts, calledTools, lastToolLoopSignature, repeatedToolLoopCount, finalText, "running");
204
+ await this.saveState(turn, messages, compactionRecords, modelTurns, toolCalls, compactions, completionValidationAttempts, calledTools, lastToolLoopSignature, repeatedToolLoopCount, finalText, "running");
171
205
  continue;
172
206
  }
173
207
  const changedFiles = await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot);
174
- const completionValidation = turn.completionValidator?.({
175
- output: parsed.output,
176
- changedFiles,
177
- commandResults,
178
- calledTools: [...calledTools],
179
- modelTurns,
180
- toolCalls,
181
- });
208
+ const completionValidation = turn.completionValidator
209
+ ? await turn.completionValidator({
210
+ output: parsed.output,
211
+ changedFiles,
212
+ commandResults,
213
+ calledTools: [...calledTools],
214
+ modelTurns,
215
+ toolCalls,
216
+ })
217
+ : undefined;
182
218
  if (completionValidation && !completionValidation.ok) {
183
219
  completionValidationAttempts++;
184
220
  if (completionValidationAttempts > turn.budget.maxCompletionValidationAttempts) {
185
- return this.stop(turn, "completion_gate_failed", startedAt, modelTurns, toolCalls, response.content, null, false, compactions, changedFiles, toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, completionValidationAttempts);
221
+ return stop("completion_gate_failed", startedAt, modelTurns, toolCalls, response.content, null, false, compactions, changedFiles, toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, completionValidationAttempts);
186
222
  }
187
223
  messages.push({ role: "assistant", content: response.content, phase: "final_answer" });
188
224
  messages.push({
189
225
  role: "user",
190
226
  content: this.buildCompletionRepairPrompt(completionValidation.reasons),
191
227
  });
192
- const compacted = await this.compactIfNeeded(turn, messages, "mid_turn", "context_limit", this.responseUsageTokens(protocol), compactions);
228
+ const compacted = await this.compactIfNeeded(turn, messages, "mid_turn", "context_limit", this.responseUsageTokens(protocol), compactions, compactionRecords);
193
229
  if (compacted.error) {
194
- return this.stop(turn, "fatal_error", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, changedFiles, toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, completionValidationAttempts);
230
+ return stop("fatal_error", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, changedFiles, toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, completionValidationAttempts);
195
231
  }
196
232
  messages = compacted.messages;
233
+ compactionRecords = compacted.compactionRecords;
197
234
  compactions += compacted.compacted ? 1 : 0;
198
- await this.saveState(turn, messages, modelTurns, toolCalls, compactions, completionValidationAttempts, calledTools, lastToolLoopSignature, repeatedToolLoopCount, finalText, "running");
235
+ await this.saveState(turn, messages, compactionRecords, modelTurns, toolCalls, compactions, completionValidationAttempts, calledTools, lastToolLoopSignature, repeatedToolLoopCount, finalText, "running");
199
236
  continue;
200
237
  }
201
238
  await this.record(turn, {
@@ -204,26 +241,31 @@ export class BoundedAgentLoopRunner {
204
241
  success: true,
205
242
  outputPreview: this.preview(response.content),
206
243
  });
207
- return this.stop(turn, "completed", startedAt, modelTurns, toolCalls, response.content, parsed.output, true, compactions, changedFiles, toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, completionValidationAttempts);
244
+ return stop("completed", startedAt, modelTurns, toolCalls, response.content, parsed.output, true, compactions, changedFiles, toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, completionValidationAttempts);
208
245
  }
209
246
  schemaRepairAttempts++;
210
247
  if (schemaRepairAttempts > turn.budget.maxSchemaRepairAttempts) {
211
- return this.stop(turn, "schema_error", startedAt, modelTurns, toolCalls, response.content, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
248
+ return stop("schema_error", startedAt, modelTurns, toolCalls, response.content, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
212
249
  }
213
250
  messages.push({ role: "assistant", content: response.content, phase: "final_answer" });
214
251
  messages.push({
215
252
  role: "user",
216
253
  content: `Your final answer did not match the required JSON schema. Return only valid JSON. Parse error: ${parsed.error}`,
217
254
  });
218
- const compacted = await this.compactIfNeeded(turn, messages, "mid_turn", "context_limit", this.responseUsageTokens(protocol), compactions);
255
+ const compacted = await this.compactIfNeeded(turn, messages, "mid_turn", "context_limit", this.responseUsageTokens(protocol), compactions, compactionRecords);
219
256
  if (compacted.error) {
220
- return this.stop(turn, "fatal_error", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
257
+ return stop("fatal_error", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
221
258
  }
222
259
  messages = compacted.messages;
260
+ compactionRecords = compacted.compactionRecords;
223
261
  compactions += compacted.compacted ? 1 : 0;
224
- await this.saveState(turn, messages, modelTurns, toolCalls, compactions, completionValidationAttempts, calledTools, lastToolLoopSignature, repeatedToolLoopCount, finalText, "running");
262
+ await this.saveState(turn, messages, compactionRecords, modelTurns, toolCalls, compactions, completionValidationAttempts, calledTools, lastToolLoopSignature, repeatedToolLoopCount, finalText, "running");
225
263
  continue;
226
264
  }
265
+ const toolBatchBudgetRefusal = this.toolBatchBudgetRefusalReason(response.toolCalls, turn, startedAt);
266
+ if (toolBatchBudgetRefusal) {
267
+ return stop("timeout", startedAt, modelTurns, toolCalls, toolBatchBudgetRefusal, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, completionValidationAttempts, toolBatchBudgetRefusal, "tool_batch_deadline_exceeded");
268
+ }
227
269
  messages.push({
228
270
  role: "assistant",
229
271
  content: response.content || `Calling ${response.toolCalls.map((call) => call.name).join(", ")}`,
@@ -238,10 +280,10 @@ export class BoundedAgentLoopRunner {
238
280
  repeatedToolLoopCount = 1;
239
281
  }
240
282
  if (repeatedToolLoopCount > turn.budget.maxRepeatedToolCalls) {
241
- return this.stop(turn, "stalled_tool_loop", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
283
+ return stop("stalled_tool_loop", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, undefined, undefined, "repeated_tool_calls");
242
284
  }
243
285
  if (turn.abortSignal?.aborted) {
244
- return this.stop(turn, "cancelled", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
286
+ return stop("cancelled", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
245
287
  }
246
288
  for (const call of response.toolCalls) {
247
289
  const activityCategory = this.deps.toolRouter.resolveTool(call.name)?.metadata.activityCategory;
@@ -254,18 +296,40 @@ export class BoundedAgentLoopRunner {
254
296
  ...(activityCategory ? { activityCategory } : {}),
255
297
  });
256
298
  }
257
- const { results: toolResults, timedOut: toolBatchTimedOut } = await this.executeToolBatchWithinBudget(response.toolCalls, turn, startedAt);
299
+ let toolBatch;
300
+ try {
301
+ toolBatch = await this.executeToolBatchWithinBudget(response.toolCalls, turn, startedAt);
302
+ }
303
+ catch (err) {
304
+ const detail = this.errorDetail(err);
305
+ const message = `Agent loop stopped: tool runtime failed. ${detail ? `Detail: ${detail}. ` : ""}Inspect the tool execution trace.`;
306
+ return stop("fatal_error", startedAt, modelTurns, toolCalls, message, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, completionValidationAttempts, detail, "tool_runtime_failure");
307
+ }
308
+ const { results: toolResults, timedOut: toolBatchTimedOut } = toolBatch;
309
+ if (toolBatchTimedOut && toolResults.length === 0) {
310
+ const timeoutReason = this.formatToolBatchWallClockExhaustedReason(response.toolCalls, turn.budget.maxWallClockMs);
311
+ return stop("timeout", startedAt, modelTurns, toolCalls, timeoutReason, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, completionValidationAttempts, timeoutReason, "tool_batch_timed_out");
312
+ }
258
313
  for (const result of toolResults) {
259
- calledTools.add(result.toolName);
314
+ const sourceCall = response.toolCalls.find((call) => call.id === result.callId);
315
+ const observation = this.createToolObservation(result, sourceCall, toolBatchTimedOut);
316
+ if (result.execution?.status !== "not_executed") {
317
+ calledTools.add(result.toolName);
318
+ }
260
319
  toolCalls++;
320
+ const toolResultSequence = toolCalls;
261
321
  if (result.success)
262
322
  consecutiveToolErrors = 0;
263
323
  else
264
324
  consecutiveToolErrors++;
325
+ const checkOnly = readToolResultCheckOnly(result);
265
326
  toolResultSummaries.push({
327
+ sequence: toolResultSequence,
266
328
  toolName: result.toolName,
267
329
  success: result.success,
268
330
  ...(result.execution ? { execution: result.execution } : {}),
331
+ ...(result.artifacts ? { artifacts: result.artifacts } : {}),
332
+ ...(checkOnly !== undefined ? { checkOnly } : {}),
269
333
  outputSummary: this.preview(result.content),
270
334
  durationMs: result.durationMs,
271
335
  });
@@ -274,6 +338,7 @@ export class BoundedAgentLoopRunner {
274
338
  toolCallId: result.callId,
275
339
  toolName: result.toolName,
276
340
  content: result.content,
341
+ observation,
277
342
  });
278
343
  await this.record(turn, {
279
344
  type: "tool_call_finished",
@@ -289,6 +354,11 @@ export class BoundedAgentLoopRunner {
289
354
  ...(result.truncated ? { truncated: result.truncated } : {}),
290
355
  ...(result.activityCategory ? { activityCategory: result.activityCategory } : {}),
291
356
  });
357
+ await this.record(turn, {
358
+ type: "tool_observation",
359
+ ...this.baseEvent(turn),
360
+ observation,
361
+ });
292
362
  if (result.disposition === "approval_denied") {
293
363
  await this.record(turn, {
294
364
  type: "approval",
@@ -309,36 +379,42 @@ export class BoundedAgentLoopRunner {
309
379
  const commandClassification = classifyAgentLoopCommandResult({
310
380
  toolName: result.toolName,
311
381
  command: result.command,
382
+ activityCategory: result.activityCategory,
383
+ verificationPlan: turn.verificationPlan,
312
384
  });
313
385
  commandResults.push({
386
+ sequence: toolResultSequence,
314
387
  toolName: result.toolName,
315
388
  command: result.command,
316
389
  cwd: result.cwd,
317
390
  success: result.success,
318
391
  ...(result.execution ? { execution: result.execution } : {}),
392
+ ...(result.activityCategory ? { activityCategory: result.activityCategory } : {}),
319
393
  category: commandClassification.category,
320
394
  evidenceEligible: commandClassification.evidenceEligible,
395
+ ...(commandClassification.evidenceSource ? { evidenceSource: commandClassification.evidenceSource } : {}),
321
396
  outputSummary: this.preview(result.content),
322
397
  durationMs: result.durationMs,
323
398
  });
324
399
  }
325
400
  if (result.disposition === "fatal" || result.fatal) {
326
- return this.stop(turn, "fatal_error", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
401
+ return stop("fatal_error", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, undefined, undefined, "tool_fatal");
327
402
  }
328
403
  if (result.disposition === "cancelled") {
329
- return this.stop(turn, toolBatchTimedOut ? "timeout" : "cancelled", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
404
+ return stop(toolBatchTimedOut ? "timeout" : "cancelled", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, undefined, undefined, toolBatchTimedOut ? "tool_batch_timed_out" : "tool_cancelled");
330
405
  }
331
406
  if (consecutiveToolErrors >= turn.budget.maxConsecutiveToolErrors) {
332
- return this.stop(turn, "consecutive_tool_errors", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
407
+ return stop("consecutive_tool_errors", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, undefined, undefined, "consecutive_tool_errors");
333
408
  }
334
409
  }
335
- const compacted = await this.compactIfNeeded(turn, messages, "mid_turn", "context_limit", this.responseUsageTokens(protocol), compactions);
410
+ const compacted = await this.compactIfNeeded(turn, messages, "mid_turn", "context_limit", this.responseUsageTokens(protocol), compactions, compactionRecords);
336
411
  if (compacted.error) {
337
- return this.stop(turn, "fatal_error", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
412
+ return stop("fatal_error", startedAt, modelTurns, toolCalls, finalText, null, false, compactions, await this.collectChangedFiles(turn.cwd, initialWorkspaceSnapshot), toolResultSummaries, commandResults, messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount);
338
413
  }
339
414
  messages = compacted.messages;
415
+ compactionRecords = compacted.compactionRecords;
340
416
  compactions += compacted.compacted ? 1 : 0;
341
- await this.saveState(turn, messages, modelTurns, toolCalls, compactions, completionValidationAttempts, calledTools, lastToolLoopSignature, repeatedToolLoopCount, finalText, "running");
417
+ await this.saveState(turn, messages, compactionRecords, modelTurns, toolCalls, compactions, completionValidationAttempts, calledTools, lastToolLoopSignature, repeatedToolLoopCount, finalText, "running");
342
418
  }
343
419
  }
344
420
  parseFinal(content, schema) {
@@ -354,12 +430,14 @@ export class BoundedAgentLoopRunner {
354
430
  const fence = content.match(/```json\s*([\s\S]*?)\s*```/);
355
431
  return fence?.[1] ?? content;
356
432
  }
357
- async stop(turn, reason, startedAt, modelTurns, toolCalls, finalText, output, success = false, compactions = 0, changedFiles = [], toolResults = [], commandResults = [], messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, completionValidationAttempts, reasonDetail) {
358
- await this.saveState(turn, messages ?? turn.messages, modelTurns, toolCalls, compactions, completionValidationAttempts ?? 0, calledTools ?? new Set(), lastToolLoopSignature ?? null, repeatedToolLoopCount ?? 0, finalText, success ? "completed" : "failed", reason, reasonDetail);
433
+ async stop(turn, reason, startedAt, modelTurns, toolCalls, finalText, output, success = false, compactions = 0, changedFiles = [], toolResults = [], commandResults = [], messages, calledTools, lastToolLoopSignature, repeatedToolLoopCount, completionValidationAttempts, reasonDetail, failureReason, compactionRecords = []) {
434
+ const resolvedFailureReason = success ? undefined : failureReason ?? this.defaultFailureReason(reason);
435
+ await this.saveState(turn, messages ?? turn.messages, compactionRecords, modelTurns, toolCalls, compactions, completionValidationAttempts ?? 0, calledTools ?? new Set(), lastToolLoopSignature ?? null, repeatedToolLoopCount ?? 0, finalText, success ? "completed" : "failed", reason, reasonDetail, resolvedFailureReason);
359
436
  await this.record(turn, {
360
437
  type: "stopped",
361
438
  ...this.baseEvent(turn),
362
439
  reason,
440
+ ...(resolvedFailureReason ? { failureReason: resolvedFailureReason } : {}),
363
441
  ...(reasonDetail ? { reasonDetail } : {}),
364
442
  });
365
443
  return {
@@ -367,6 +445,8 @@ export class BoundedAgentLoopRunner {
367
445
  output,
368
446
  finalText,
369
447
  stopReason: reason,
448
+ ...(resolvedFailureReason ? { failureReason: resolvedFailureReason } : {}),
449
+ ...(reasonDetail ? { failureDetail: reasonDetail } : {}),
370
450
  elapsedMs: Date.now() - startedAt,
371
451
  modelTurns,
372
452
  toolCalls,
@@ -378,6 +458,9 @@ export class BoundedAgentLoopRunner {
378
458
  traceId: turn.session.traceId,
379
459
  sessionId: turn.session.sessionId,
380
460
  turnId: turn.turnId,
461
+ ...(turn.profileName ? { profileName: turn.profileName } : {}),
462
+ ...(turn.reasoningEffort ? { reasoningEffort: turn.reasoningEffort } : {}),
463
+ ...(turn.executionPolicy ? { executionPolicy: turn.executionPolicy } : {}),
381
464
  };
382
465
  }
383
466
  buildCompletionRepairPrompt(reasons) {
@@ -419,47 +502,101 @@ export class BoundedAgentLoopRunner {
419
502
  return String(value);
420
503
  }
421
504
  }
505
+ defaultFailureReason(reason) {
506
+ switch (reason) {
507
+ case "timeout":
508
+ return "wall_clock_timeout";
509
+ case "max_model_turns":
510
+ return "max_model_turns";
511
+ case "max_tool_calls":
512
+ return "max_tool_calls";
513
+ case "consecutive_tool_errors":
514
+ return "consecutive_tool_errors";
515
+ case "stalled_tool_loop":
516
+ return "repeated_tool_calls";
517
+ case "schema_error":
518
+ return "schema_validation_failed";
519
+ case "cancelled":
520
+ return "operator_cancelled";
521
+ case "protocol_incomplete":
522
+ return "protocol_incomplete";
523
+ case "completion_gate_failed":
524
+ return "completion_gate_failed";
525
+ case "fatal_error":
526
+ default:
527
+ return "provider_failure";
528
+ }
529
+ }
422
530
  classifyRunFailure(error) {
423
- const detail = error instanceof Error
424
- ? [error.name !== "Error" ? error.name : null, error.message]
425
- .filter((part) => typeof part === "string" && part.length > 0)
426
- .join(": ")
427
- : String(error);
428
- const lowered = detail.toLowerCase();
429
- if (lowered.includes("timeout")
430
- || lowered.includes("timed out")
431
- || lowered.includes("aborterror")
432
- || lowered.includes("aborted")) {
531
+ const detail = this.errorDetail(error);
532
+ const structured = this.structuredRunFailureReason(error);
533
+ if (structured === "model_request_timeout") {
433
534
  return {
434
535
  reason: "timeout",
536
+ failureReason: "model_request_timeout",
435
537
  detail,
436
538
  message: "Agent loop stopped: model request timed out. Narrow broad repo-wide searches or increase `codex_timeout_ms` if this workload is expected.",
437
539
  };
438
540
  }
541
+ if (structured === "model_request_aborted") {
542
+ return {
543
+ reason: "fatal_error",
544
+ failureReason: "model_request_aborted",
545
+ detail,
546
+ message: "Agent loop stopped: model request was aborted by the provider or transport. Retry the turn or inspect the provider connection.",
547
+ };
548
+ }
439
549
  return {
440
550
  reason: "fatal_error",
551
+ failureReason: "provider_failure",
441
552
  detail,
442
553
  message: `Agent loop stopped: model request failed. ${detail ? `Detail: ${detail}. ` : ""}Retry the turn or inspect the provider connection.`,
443
554
  };
444
555
  }
445
- async compactIfNeeded(turn, messages, phase, reason, usageTokens, compactions) {
556
+ structuredRunFailureReason(error) {
557
+ if (!error || typeof error !== "object")
558
+ return null;
559
+ const value = error;
560
+ if (value.agentLoopFailureReason === "model_request_timeout" || value.agentLoopFailureReason === "model_request_aborted") {
561
+ return value.agentLoopFailureReason;
562
+ }
563
+ if (value.name === "TimeoutError" || value.code === "ETIMEDOUT" || value.code === "UND_ERR_HEADERS_TIMEOUT" || value.code === "UND_ERR_BODY_TIMEOUT") {
564
+ return "model_request_timeout";
565
+ }
566
+ if (value.name === "AbortError" || value.code === "ABORT_ERR") {
567
+ return "model_request_aborted";
568
+ }
569
+ return this.structuredRunFailureReason(value.cause);
570
+ }
571
+ errorDetail(error) {
572
+ return error instanceof Error
573
+ ? [error.name !== "Error" ? error.name : null, error.message]
574
+ .filter((part) => typeof part === "string" && part.length > 0)
575
+ .join(": ")
576
+ : String(error);
577
+ }
578
+ async compactIfNeeded(turn, messages, phase, reason, usageTokens, compactions, compactionRecords) {
446
579
  const limit = this.autoCompactLimit(turn);
447
580
  if (!limit || compactions >= turn.budget.maxCompactions) {
448
- return { messages, compacted: false };
581
+ return { messages, compactionRecords: cloneAgentLoopCompactionRecords(compactionRecords), compacted: false };
449
582
  }
450
583
  const tokens = usageTokens && usageTokens > 0 ? usageTokens : this.estimateTokens(messages);
451
584
  if (tokens < limit) {
452
- return { messages, compacted: false };
585
+ return { messages, compactionRecords: cloneAgentLoopCompactionRecords(compactionRecords), compacted: false };
453
586
  }
454
587
  try {
455
588
  const result = await this.compactor.compact({
456
- history: createAgentLoopHistory(messages),
589
+ history: createAgentLoopHistory(messages, compactionRecords),
457
590
  maxMessages: turn.budget.compactionMaxMessages,
458
591
  phase,
459
592
  reason,
460
593
  });
461
594
  if (!result.compacted) {
462
- return { messages: result.history.messages, compacted: false };
595
+ return {
596
+ messages: result.history.messages,
597
+ compactionRecords: cloneAgentLoopCompactionRecords(result.history.compactionRecords),
598
+ compacted: false,
599
+ };
463
600
  }
464
601
  await this.record(turn, {
465
602
  type: "context_compaction",
@@ -470,10 +607,19 @@ export class BoundedAgentLoopRunner {
470
607
  outputMessages: result.history.messages.length,
471
608
  summaryPreview: this.preview(result.summary ?? ""),
472
609
  });
473
- return { messages: result.history.messages, compacted: true };
610
+ return {
611
+ messages: result.history.messages,
612
+ compactionRecords: cloneAgentLoopCompactionRecords(result.history.compactionRecords),
613
+ compacted: true,
614
+ };
474
615
  }
475
616
  catch (err) {
476
- return { messages, compacted: false, error: err instanceof Error ? err.message : String(err) };
617
+ return {
618
+ messages,
619
+ compactionRecords: cloneAgentLoopCompactionRecords(compactionRecords),
620
+ compacted: false,
621
+ error: err instanceof Error ? err.message : String(err),
622
+ };
477
623
  }
478
624
  }
479
625
  autoCompactLimit(turn) {
@@ -484,7 +630,10 @@ export class BoundedAgentLoopRunner {
484
630
  return contextLimit && contextLimit > 0 ? Math.floor(contextLimit * 0.9) : undefined;
485
631
  }
486
632
  async executeToolBatchWithinBudget(calls, turn, startedAt) {
487
- const remainingMs = Math.max(1, turn.budget.maxWallClockMs - (Date.now() - startedAt));
633
+ const remainingMs = turn.budget.maxWallClockMs - (Date.now() - startedAt);
634
+ if (remainingMs <= 0) {
635
+ return { results: [], timedOut: true };
636
+ }
488
637
  const controller = new AbortController();
489
638
  const parentSignal = turn.abortSignal;
490
639
  let timedOut = false;
@@ -517,6 +666,34 @@ export class BoundedAgentLoopRunner {
517
666
  parentSignal?.removeEventListener("abort", abortFromParent);
518
667
  }
519
668
  }
669
+ toolBatchBudgetRefusalReason(calls, turn, startedAt) {
670
+ const remainingMs = turn.budget.maxWallClockMs - (Date.now() - startedAt);
671
+ if (remainingMs <= 0) {
672
+ return this.formatToolBatchWallClockExhaustedReason(calls, turn.budget.maxWallClockMs);
673
+ }
674
+ const mutatingToolNames = calls
675
+ .filter((call) => this.isMutatingToolCall(call))
676
+ .map((call) => call.name);
677
+ if (mutatingToolNames.length === 0 || remainingMs >= MIN_MUTATING_TOOL_BATCH_REMAINING_MS) {
678
+ return null;
679
+ }
680
+ return [
681
+ "Tool batch was not started because the remaining wall-clock budget",
682
+ `(${Math.floor(remainingMs)}ms) is below the ${MIN_MUTATING_TOOL_BATCH_REMAINING_MS}ms minimum`,
683
+ `for mutating tools: ${[...new Set(mutatingToolNames)].join(", ")}.`,
684
+ ].join(" ");
685
+ }
686
+ formatToolBatchWallClockExhaustedReason(calls, maxWallClockMs) {
687
+ return [
688
+ "Tool batch was not started because the agent loop wall-clock budget is exhausted",
689
+ `(0ms remaining; limit ${maxWallClockMs}ms).`,
690
+ `Requested tools: ${calls.map((call) => call.name).join(", ")}.`,
691
+ ].join(" ");
692
+ }
693
+ isMutatingToolCall(call) {
694
+ const metadata = this.deps.toolRouter.resolveTool(call.name)?.metadata;
695
+ return metadata?.isReadOnly !== true;
696
+ }
520
697
  responseUsageTokens(response) {
521
698
  if (!response.usage)
522
699
  return undefined;
@@ -529,6 +706,56 @@ export class BoundedAgentLoopRunner {
529
706
  missingRequiredTools(turn, calledTools) {
530
707
  return [...(turn.toolPolicy.requiredTools ?? [])].filter((toolName) => !calledTools.has(toolName));
531
708
  }
709
+ createToolObservation(result, sourceCall, toolBatchTimedOut) {
710
+ const state = this.toolObservationState(result, toolBatchTimedOut);
711
+ const execution = this.toolObservationExecution(result, state);
712
+ const rawResult = result.rawResult;
713
+ return {
714
+ type: "tool_observation",
715
+ callId: result.callId,
716
+ toolName: result.toolName,
717
+ arguments: sourceCall?.input ?? {},
718
+ state,
719
+ success: result.success,
720
+ execution,
721
+ durationMs: result.durationMs,
722
+ output: {
723
+ content: result.content,
724
+ ...(rawResult?.summary ? { summary: rawResult.summary } : {}),
725
+ ...(rawResult && Object.prototype.hasOwnProperty.call(rawResult, "data") ? { data: rawResult.data } : {}),
726
+ ...(rawResult?.error ? { error: rawResult.error } : {}),
727
+ },
728
+ ...(result.command ? { command: result.command } : {}),
729
+ ...(result.cwd ? { cwd: result.cwd } : {}),
730
+ ...(result.artifacts ? { artifacts: result.artifacts } : {}),
731
+ ...(result.truncated ? { truncated: result.truncated } : {}),
732
+ ...(result.activityCategory ? { activityCategory: result.activityCategory } : {}),
733
+ };
734
+ }
735
+ toolObservationState(result, toolBatchTimedOut) {
736
+ const reason = result.execution?.reason;
737
+ if (reason === "timed_out" || (toolBatchTimedOut && result.disposition === "cancelled"))
738
+ return "timed_out";
739
+ if (reason === "interrupted" || result.disposition === "cancelled")
740
+ return "interrupted";
741
+ if (reason === "approval_denied" || reason === "permission_denied")
742
+ return "denied";
743
+ if (reason === "policy_blocked" || reason === "dry_run")
744
+ return "blocked";
745
+ return result.success ? "success" : "failure";
746
+ }
747
+ toolObservationExecution(result, state) {
748
+ if (result.execution)
749
+ return result.execution;
750
+ if (state === "timed_out" || state === "interrupted") {
751
+ return {
752
+ status: "executed",
753
+ reason: state === "timed_out" ? "timed_out" : "interrupted",
754
+ message: result.content,
755
+ };
756
+ }
757
+ return { status: "executed" };
758
+ }
532
759
  async createTurnProtocol(turn, messages, tools) {
533
760
  if (this.deps.modelClient.createTurnProtocol) {
534
761
  return this.deps.modelClient.createTurnProtocol({
@@ -550,18 +777,36 @@ export class BoundedAgentLoopRunner {
550
777
  phase: response.toolCalls.length > 0 ? "commentary" : "final_answer",
551
778
  }] : [],
552
779
  toolCalls: response.toolCalls,
780
+ responseItems: [
781
+ ...(response.content || response.toolCalls.length > 0
782
+ ? [assistantTextResponseItem(response.content || `Calling ${response.toolCalls.map((call) => call.name).join(", ")}`, response.toolCalls.length > 0 ? "commentary" : "final_answer")]
783
+ : []),
784
+ ...response.toolCalls.map((call) => functionToolCallResponseItem(call)),
785
+ ],
553
786
  stopReason: response.stopReason,
554
787
  responseCompleted: true,
555
788
  usage: response.usage,
556
789
  };
557
790
  }
558
791
  protocolToResponse(protocol) {
792
+ const responseItemText = protocol.responseItems
793
+ ?.filter((item) => item.type === "assistant_text")
794
+ .map((item) => item.content)
795
+ .filter(Boolean)
796
+ .join("\n");
797
+ const responseItemToolCalls = protocol.responseItems
798
+ ?.filter((item) => item.type === "function_tool_call")
799
+ .map((item) => ({
800
+ id: item.id,
801
+ name: item.name,
802
+ input: item.arguments,
803
+ }));
559
804
  return {
560
- content: protocol.assistant.map((item) => item.content).filter(Boolean).join("\n"),
561
- toolCalls: protocol.toolCalls,
805
+ content: protocol.assistant.map((item) => item.content).filter(Boolean).join("\n") || responseItemText || "",
806
+ toolCalls: protocol.responseItems ? responseItemToolCalls ?? [] : protocol.toolCalls,
562
807
  };
563
808
  }
564
- async saveState(turn, messages, modelTurns, toolCalls, compactions, completionValidationAttempts, calledTools, lastToolLoopSignature, repeatedToolLoopCount, finalText, status, stopReason, stopDetail) {
809
+ async saveState(turn, messages, compactionRecords, modelTurns, toolCalls, compactions, completionValidationAttempts, calledTools, lastToolLoopSignature, repeatedToolLoopCount, finalText, status, stopReason, stopDetail, failureReason) {
565
810
  const state = {
566
811
  sessionId: turn.session.sessionId,
567
812
  traceId: turn.session.traceId,
@@ -571,6 +816,7 @@ export class BoundedAgentLoopRunner {
571
816
  cwd: turn.cwd,
572
817
  modelRef: formatAgentLoopModelRef(turn.model),
573
818
  messages,
819
+ compactionRecords: cloneAgentLoopCompactionRecords(compactionRecords),
574
820
  modelTurns,
575
821
  toolCalls,
576
822
  compactions,
@@ -581,6 +827,7 @@ export class BoundedAgentLoopRunner {
581
827
  finalText,
582
828
  status,
583
829
  ...(stopReason ? { stopReason } : {}),
830
+ ...(failureReason ? { failureReason } : {}),
584
831
  ...(stopDetail ? { stopDetail } : {}),
585
832
  updatedAt: new Date().toISOString(),
586
833
  };
@@ -588,18 +835,22 @@ export class BoundedAgentLoopRunner {
588
835
  }
589
836
  async captureWorkspaceSnapshot(cwd) {
590
837
  const result = await execFileNoThrow("git", ["status", "--porcelain", "--untracked-files=all"], { cwd, timeoutMs: 10_000 });
591
- if ((result.exitCode ?? 1) !== 0)
592
- return null;
593
- return new Set(this.parseGitStatusPaths(result.stdout));
838
+ if ((result.exitCode ?? 1) === 0) {
839
+ return { kind: "git", paths: new Set(this.parseGitStatusPaths(result.stdout)) };
840
+ }
841
+ return { kind: "filesystem", files: await this.captureFilesystemSnapshot(cwd) };
594
842
  }
595
843
  async collectChangedFiles(cwd, before) {
596
844
  const afterResult = await execFileNoThrow("git", ["status", "--porcelain", "--untracked-files=all"], { cwd, timeoutMs: 10_000 });
597
- if ((afterResult.exitCode ?? 1) !== 0)
598
- return [];
845
+ if ((afterResult.exitCode ?? 1) !== 0) {
846
+ if (before?.kind !== "filesystem")
847
+ return [];
848
+ return this.collectFilesystemChangedPaths(before.files, await this.captureFilesystemSnapshot(cwd));
849
+ }
599
850
  const after = new Set(this.parseGitStatusPaths(afterResult.stdout));
600
- if (!before)
851
+ if (!before || before.kind !== "git")
601
852
  return [...after];
602
- return [...after].filter((file) => !before.has(file));
853
+ return [...after].filter((file) => !before.paths.has(file));
603
854
  }
604
855
  parseGitStatusPaths(stdout) {
605
856
  return stdout
@@ -609,5 +860,74 @@ export class BoundedAgentLoopRunner {
609
860
  .map((line) => line.slice(3).trim())
610
861
  .map((filePath) => filePath.includes(" -> ") ? filePath.split(" -> ").at(-1) ?? filePath : filePath);
611
862
  }
863
+ async captureFilesystemSnapshot(cwd) {
864
+ const files = new Map();
865
+ const root = path.resolve(cwd);
866
+ const visit = async (dir) => {
867
+ if (files.size >= FILESYSTEM_SNAPSHOT_MAX_FILES)
868
+ return;
869
+ let entries;
870
+ try {
871
+ entries = await fsp.readdir(dir, { withFileTypes: true });
872
+ }
873
+ catch {
874
+ return;
875
+ }
876
+ for (const entry of entries) {
877
+ if (files.size >= FILESYSTEM_SNAPSHOT_MAX_FILES)
878
+ return;
879
+ if (entry.name.startsWith(".pulseed-"))
880
+ continue;
881
+ const absolutePath = path.join(dir, entry.name);
882
+ if (entry.isDirectory()) {
883
+ if (!FILESYSTEM_SNAPSHOT_EXCLUDED_DIRS.has(entry.name)) {
884
+ await visit(absolutePath);
885
+ }
886
+ continue;
887
+ }
888
+ if (!entry.isFile())
889
+ continue;
890
+ const relativePath = path.relative(root, absolutePath).replace(/\\/g, "/");
891
+ try {
892
+ const stat = await fsp.stat(absolutePath);
893
+ const snapshotEntry = {
894
+ size: stat.size,
895
+ mtimeMs: stat.mtimeMs,
896
+ };
897
+ if (stat.size <= FILESYSTEM_SNAPSHOT_HASH_MAX_BYTES) {
898
+ snapshotEntry.hash = createHash("sha256")
899
+ .update(await fsp.readFile(absolutePath))
900
+ .digest("hex");
901
+ }
902
+ files.set(relativePath, snapshotEntry);
903
+ }
904
+ catch {
905
+ // File may have changed while scanning; skip and let the next scan observe it.
906
+ }
907
+ }
908
+ };
909
+ await visit(root);
910
+ return files;
911
+ }
912
+ collectFilesystemChangedPaths(before, after) {
913
+ const changed = new Set();
914
+ for (const [filePath, afterEntry] of after) {
915
+ const beforeEntry = before.get(filePath);
916
+ if (!beforeEntry || !this.sameFilesystemEntry(beforeEntry, afterEntry)) {
917
+ changed.add(filePath);
918
+ }
919
+ }
920
+ for (const filePath of before.keys()) {
921
+ if (!after.has(filePath)) {
922
+ changed.add(filePath);
923
+ }
924
+ }
925
+ return [...changed].sort();
926
+ }
927
+ sameFilesystemEntry(left, right) {
928
+ if (left.hash && right.hash)
929
+ return left.hash === right.hash;
930
+ return left.size === right.size && left.mtimeMs === right.mtimeMs;
931
+ }
612
932
  }
613
933
  //# sourceMappingURL=bounded-agent-loop-runner.js.map