attocode 0.2.3 → 0.2.5

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 (787) hide show
  1. package/CHANGELOG.md +122 -1
  2. package/README.md +65 -5
  3. package/dist/src/adapters.d.ts +2 -1
  4. package/dist/src/adapters.d.ts.map +1 -1
  5. package/dist/src/adapters.js +74 -12
  6. package/dist/src/adapters.js.map +1 -1
  7. package/dist/src/agent/agent-builder.d.ts +117 -0
  8. package/dist/src/agent/agent-builder.d.ts.map +1 -0
  9. package/dist/src/agent/agent-builder.js +204 -0
  10. package/dist/src/agent/agent-builder.js.map +1 -0
  11. package/dist/src/agent/feature-initializer.d.ts +80 -0
  12. package/dist/src/agent/feature-initializer.d.ts.map +1 -0
  13. package/dist/src/agent/feature-initializer.js +677 -0
  14. package/dist/src/agent/feature-initializer.js.map +1 -0
  15. package/dist/src/agent/index.d.ts +13 -0
  16. package/dist/src/agent/index.d.ts.map +1 -0
  17. package/dist/src/agent/index.js +13 -0
  18. package/dist/src/agent/index.js.map +1 -0
  19. package/dist/src/agent/message-builder.d.ts +50 -0
  20. package/dist/src/agent/message-builder.d.ts.map +1 -0
  21. package/dist/src/agent/message-builder.js +173 -0
  22. package/dist/src/agent/message-builder.js.map +1 -0
  23. package/dist/src/agent/session-api.d.ts +94 -0
  24. package/dist/src/agent/session-api.d.ts.map +1 -0
  25. package/dist/src/agent/session-api.js +262 -0
  26. package/dist/src/agent/session-api.js.map +1 -0
  27. package/dist/src/agent-tools/lsp-file-tools.d.ts +1 -1
  28. package/dist/src/agent-tools/lsp-file-tools.d.ts.map +1 -1
  29. package/dist/src/agent.d.ts +52 -213
  30. package/dist/src/agent.d.ts.map +1 -1
  31. package/dist/src/agent.js +544 -4072
  32. package/dist/src/agent.js.map +1 -1
  33. package/dist/src/cli.d.ts.map +1 -1
  34. package/dist/src/cli.js +2 -1
  35. package/dist/src/cli.js.map +1 -1
  36. package/dist/src/commands/handler.d.ts.map +1 -1
  37. package/dist/src/commands/handler.js +18 -9
  38. package/dist/src/commands/handler.js.map +1 -1
  39. package/dist/src/commands/init-commands.d.ts.map +1 -1
  40. package/dist/src/commands/init-commands.js +16 -1
  41. package/dist/src/commands/init-commands.js.map +1 -1
  42. package/dist/src/commands/init.d.ts.map +1 -1
  43. package/dist/src/commands/init.js +31 -0
  44. package/dist/src/commands/init.js.map +1 -1
  45. package/dist/src/config/base-types.d.ts +45 -0
  46. package/dist/src/config/base-types.d.ts.map +1 -0
  47. package/dist/src/config/base-types.js +9 -0
  48. package/dist/src/config/base-types.js.map +1 -0
  49. package/dist/src/config/config-manager.d.ts +35 -0
  50. package/dist/src/config/config-manager.d.ts.map +1 -0
  51. package/dist/src/config/config-manager.js +108 -0
  52. package/dist/src/config/config-manager.js.map +1 -0
  53. package/dist/src/config/index.d.ts +4 -0
  54. package/dist/src/config/index.d.ts.map +1 -0
  55. package/dist/src/config/index.js +3 -0
  56. package/dist/src/config/index.js.map +1 -0
  57. package/dist/src/config/schema.d.ts +1546 -0
  58. package/dist/src/config/schema.d.ts.map +1 -0
  59. package/dist/src/config/schema.js +268 -0
  60. package/dist/src/config/schema.js.map +1 -0
  61. package/dist/src/config.d.ts +4 -1
  62. package/dist/src/config.d.ts.map +1 -1
  63. package/dist/src/config.js +8 -12
  64. package/dist/src/config.js.map +1 -1
  65. package/dist/src/core/agent-state-machine.d.ts +131 -0
  66. package/dist/src/core/agent-state-machine.d.ts.map +1 -0
  67. package/dist/src/core/agent-state-machine.js +302 -0
  68. package/dist/src/core/agent-state-machine.js.map +1 -0
  69. package/dist/src/core/base-manager.d.ts +79 -0
  70. package/dist/src/core/base-manager.d.ts.map +1 -0
  71. package/dist/src/core/base-manager.js +170 -0
  72. package/dist/src/core/base-manager.js.map +1 -0
  73. package/dist/src/core/completion-analyzer.d.ts +15 -0
  74. package/dist/src/core/completion-analyzer.d.ts.map +1 -0
  75. package/dist/src/core/completion-analyzer.js +53 -0
  76. package/dist/src/core/completion-analyzer.js.map +1 -0
  77. package/dist/src/core/execution-loop.d.ts +46 -0
  78. package/dist/src/core/execution-loop.d.ts.map +1 -0
  79. package/dist/src/core/execution-loop.js +1397 -0
  80. package/dist/src/core/execution-loop.js.map +1 -0
  81. package/dist/src/core/index.d.ts +7 -0
  82. package/dist/src/core/index.d.ts.map +1 -1
  83. package/dist/src/core/index.js +9 -0
  84. package/dist/src/core/index.js.map +1 -1
  85. package/dist/src/core/process-handlers.d.ts.map +1 -1
  86. package/dist/src/core/process-handlers.js +14 -0
  87. package/dist/src/core/process-handlers.js.map +1 -1
  88. package/dist/src/core/protocol/types.d.ts +12 -12
  89. package/dist/src/core/response-handler.d.ts +16 -0
  90. package/dist/src/core/response-handler.d.ts.map +1 -0
  91. package/dist/src/core/response-handler.js +235 -0
  92. package/dist/src/core/response-handler.js.map +1 -0
  93. package/dist/src/core/subagent-spawner.d.ts +43 -0
  94. package/dist/src/core/subagent-spawner.d.ts.map +1 -0
  95. package/dist/src/core/subagent-spawner.js +973 -0
  96. package/dist/src/core/subagent-spawner.js.map +1 -0
  97. package/dist/src/core/tool-executor.d.ts +59 -0
  98. package/dist/src/core/tool-executor.d.ts.map +1 -0
  99. package/dist/src/core/tool-executor.js +682 -0
  100. package/dist/src/core/tool-executor.js.map +1 -0
  101. package/dist/src/core/types.d.ts +134 -0
  102. package/dist/src/core/types.d.ts.map +1 -0
  103. package/dist/src/core/types.js +12 -0
  104. package/dist/src/core/types.js.map +1 -0
  105. package/dist/src/defaults.d.ts +2 -2
  106. package/dist/src/defaults.d.ts.map +1 -1
  107. package/dist/src/defaults.js +29 -1
  108. package/dist/src/defaults.js.map +1 -1
  109. package/dist/src/integrations/agents/agent-registry.d.ts +262 -0
  110. package/dist/src/integrations/agents/agent-registry.d.ts.map +1 -0
  111. package/dist/src/integrations/agents/agent-registry.js +686 -0
  112. package/dist/src/integrations/agents/agent-registry.js.map +1 -0
  113. package/dist/src/integrations/agents/async-subagent.d.ts +135 -0
  114. package/dist/src/integrations/agents/async-subagent.d.ts.map +1 -0
  115. package/dist/src/integrations/agents/async-subagent.js +213 -0
  116. package/dist/src/integrations/agents/async-subagent.js.map +1 -0
  117. package/dist/src/integrations/agents/complexity-classifier.d.ts +86 -0
  118. package/dist/src/integrations/agents/complexity-classifier.d.ts.map +1 -0
  119. package/dist/src/integrations/agents/complexity-classifier.js +233 -0
  120. package/dist/src/integrations/agents/complexity-classifier.js.map +1 -0
  121. package/dist/src/integrations/agents/delegation-protocol.d.ts +86 -0
  122. package/dist/src/integrations/agents/delegation-protocol.d.ts.map +1 -0
  123. package/dist/src/integrations/agents/delegation-protocol.js +127 -0
  124. package/dist/src/integrations/agents/delegation-protocol.js.map +1 -0
  125. package/dist/src/integrations/agents/multi-agent.d.ts +150 -0
  126. package/dist/src/integrations/agents/multi-agent.d.ts.map +1 -0
  127. package/dist/src/integrations/agents/multi-agent.js +306 -0
  128. package/dist/src/integrations/agents/multi-agent.js.map +1 -0
  129. package/dist/src/integrations/agents/result-synthesizer.d.ts +389 -0
  130. package/dist/src/integrations/agents/result-synthesizer.d.ts.map +1 -0
  131. package/dist/src/integrations/agents/result-synthesizer.js +951 -0
  132. package/dist/src/integrations/agents/result-synthesizer.js.map +1 -0
  133. package/dist/src/integrations/agents/shared-blackboard.d.ts +406 -0
  134. package/dist/src/integrations/agents/shared-blackboard.d.ts.map +1 -0
  135. package/dist/src/integrations/agents/shared-blackboard.js +757 -0
  136. package/dist/src/integrations/agents/shared-blackboard.js.map +1 -0
  137. package/dist/src/integrations/agents/subagent-output-store.d.ts +91 -0
  138. package/dist/src/integrations/agents/subagent-output-store.d.ts.map +1 -0
  139. package/dist/src/integrations/agents/subagent-output-store.js +257 -0
  140. package/dist/src/integrations/agents/subagent-output-store.js.map +1 -0
  141. package/dist/src/integrations/auto-compaction.d.ts.map +1 -1
  142. package/dist/src/integrations/auto-compaction.js +3 -2
  143. package/dist/src/integrations/auto-compaction.js.map +1 -1
  144. package/dist/src/integrations/budget/budget-pool.d.ts +115 -0
  145. package/dist/src/integrations/budget/budget-pool.d.ts.map +1 -0
  146. package/dist/src/integrations/budget/budget-pool.js +205 -0
  147. package/dist/src/integrations/budget/budget-pool.js.map +1 -0
  148. package/dist/src/integrations/budget/cancellation.d.ts +229 -0
  149. package/dist/src/integrations/budget/cancellation.d.ts.map +1 -0
  150. package/dist/src/integrations/budget/cancellation.js +520 -0
  151. package/dist/src/integrations/budget/cancellation.js.map +1 -0
  152. package/dist/src/integrations/budget/dynamic-budget.d.ts +81 -0
  153. package/dist/src/integrations/budget/dynamic-budget.d.ts.map +1 -0
  154. package/dist/src/integrations/budget/dynamic-budget.js +151 -0
  155. package/dist/src/integrations/budget/dynamic-budget.js.map +1 -0
  156. package/dist/src/integrations/budget/economics.d.ts +435 -0
  157. package/dist/src/integrations/budget/economics.d.ts.map +1 -0
  158. package/dist/src/integrations/budget/economics.js +1007 -0
  159. package/dist/src/integrations/budget/economics.js.map +1 -0
  160. package/dist/src/integrations/budget/injection-budget.d.ts +71 -0
  161. package/dist/src/integrations/budget/injection-budget.d.ts.map +1 -0
  162. package/dist/src/integrations/budget/injection-budget.js +137 -0
  163. package/dist/src/integrations/budget/injection-budget.js.map +1 -0
  164. package/dist/src/integrations/budget/loop-detector.d.ts +105 -0
  165. package/dist/src/integrations/budget/loop-detector.d.ts.map +1 -0
  166. package/dist/src/integrations/budget/loop-detector.js +287 -0
  167. package/dist/src/integrations/budget/loop-detector.js.map +1 -0
  168. package/dist/src/integrations/budget/phase-tracker.d.ts +114 -0
  169. package/dist/src/integrations/budget/phase-tracker.d.ts.map +1 -0
  170. package/dist/src/integrations/budget/phase-tracker.js +262 -0
  171. package/dist/src/integrations/budget/phase-tracker.js.map +1 -0
  172. package/dist/src/integrations/budget/resources.d.ts +182 -0
  173. package/dist/src/integrations/budget/resources.d.ts.map +1 -0
  174. package/dist/src/integrations/budget/resources.js +318 -0
  175. package/dist/src/integrations/budget/resources.js.map +1 -0
  176. package/dist/src/integrations/budget-pool.d.ts +7 -0
  177. package/dist/src/integrations/budget-pool.d.ts.map +1 -1
  178. package/dist/src/integrations/budget-pool.js +43 -0
  179. package/dist/src/integrations/budget-pool.js.map +1 -1
  180. package/dist/src/integrations/codebase-ast.d.ts +52 -0
  181. package/dist/src/integrations/codebase-ast.d.ts.map +1 -0
  182. package/dist/src/integrations/codebase-ast.js +457 -0
  183. package/dist/src/integrations/codebase-ast.js.map +1 -0
  184. package/dist/src/integrations/codebase-context.d.ts +18 -0
  185. package/dist/src/integrations/codebase-context.d.ts.map +1 -1
  186. package/dist/src/integrations/codebase-context.js +197 -17
  187. package/dist/src/integrations/codebase-context.js.map +1 -1
  188. package/dist/src/integrations/compaction.d.ts.map +1 -1
  189. package/dist/src/integrations/compaction.js +14 -6
  190. package/dist/src/integrations/compaction.js.map +1 -1
  191. package/dist/src/integrations/context/auto-compaction.d.ts +210 -0
  192. package/dist/src/integrations/context/auto-compaction.d.ts.map +1 -0
  193. package/dist/src/integrations/context/auto-compaction.js +477 -0
  194. package/dist/src/integrations/context/auto-compaction.js.map +1 -0
  195. package/dist/src/integrations/context/code-analyzer.d.ts +71 -0
  196. package/dist/src/integrations/context/code-analyzer.d.ts.map +1 -0
  197. package/dist/src/integrations/context/code-analyzer.js +448 -0
  198. package/dist/src/integrations/context/code-analyzer.js.map +1 -0
  199. package/dist/src/integrations/context/code-selector.d.ts +78 -0
  200. package/dist/src/integrations/context/code-selector.d.ts.map +1 -0
  201. package/dist/src/integrations/context/code-selector.js +649 -0
  202. package/dist/src/integrations/context/code-selector.js.map +1 -0
  203. package/dist/src/integrations/context/codebase-ast.d.ts +138 -0
  204. package/dist/src/integrations/context/codebase-ast.d.ts.map +1 -0
  205. package/dist/src/integrations/context/codebase-ast.js +818 -0
  206. package/dist/src/integrations/context/codebase-ast.js.map +1 -0
  207. package/dist/src/integrations/context/codebase-context.d.ts +473 -0
  208. package/dist/src/integrations/context/codebase-context.d.ts.map +1 -0
  209. package/dist/src/integrations/context/codebase-context.js +685 -0
  210. package/dist/src/integrations/context/codebase-context.js.map +1 -0
  211. package/dist/src/integrations/context/compaction.d.ts +191 -0
  212. package/dist/src/integrations/context/compaction.d.ts.map +1 -0
  213. package/dist/src/integrations/context/compaction.js +384 -0
  214. package/dist/src/integrations/context/compaction.js.map +1 -0
  215. package/dist/src/integrations/context/context-engineering.d.ts +274 -0
  216. package/dist/src/integrations/context/context-engineering.d.ts.map +1 -0
  217. package/dist/src/integrations/context/context-engineering.js +437 -0
  218. package/dist/src/integrations/context/context-engineering.js.map +1 -0
  219. package/dist/src/integrations/context/file-cache.d.ts +97 -0
  220. package/dist/src/integrations/context/file-cache.d.ts.map +1 -0
  221. package/dist/src/integrations/context/file-cache.js +218 -0
  222. package/dist/src/integrations/context/file-cache.js.map +1 -0
  223. package/dist/src/integrations/context/semantic-cache.d.ts +178 -0
  224. package/dist/src/integrations/context/semantic-cache.d.ts.map +1 -0
  225. package/dist/src/integrations/context/semantic-cache.js +372 -0
  226. package/dist/src/integrations/context/semantic-cache.js.map +1 -0
  227. package/dist/src/integrations/context-engineering.d.ts +8 -0
  228. package/dist/src/integrations/context-engineering.d.ts.map +1 -1
  229. package/dist/src/integrations/context-engineering.js +19 -0
  230. package/dist/src/integrations/context-engineering.js.map +1 -1
  231. package/dist/src/integrations/economics.d.ts +25 -1
  232. package/dist/src/integrations/economics.d.ts.map +1 -1
  233. package/dist/src/integrations/economics.js +217 -38
  234. package/dist/src/integrations/economics.js.map +1 -1
  235. package/dist/src/integrations/edit-validator.d.ts +30 -0
  236. package/dist/src/integrations/edit-validator.d.ts.map +1 -0
  237. package/dist/src/integrations/edit-validator.js +85 -0
  238. package/dist/src/integrations/edit-validator.js.map +1 -0
  239. package/dist/src/integrations/file-cache.d.ts +7 -0
  240. package/dist/src/integrations/file-cache.d.ts.map +1 -1
  241. package/dist/src/integrations/file-cache.js +54 -0
  242. package/dist/src/integrations/file-cache.js.map +1 -1
  243. package/dist/src/integrations/health-check.d.ts.map +1 -1
  244. package/dist/src/integrations/health-check.js +3 -2
  245. package/dist/src/integrations/health-check.js.map +1 -1
  246. package/dist/src/integrations/hierarchical-config.d.ts +3 -0
  247. package/dist/src/integrations/hierarchical-config.d.ts.map +1 -1
  248. package/dist/src/integrations/hierarchical-config.js +3 -0
  249. package/dist/src/integrations/hierarchical-config.js.map +1 -1
  250. package/dist/src/integrations/hooks.d.ts +2 -0
  251. package/dist/src/integrations/hooks.d.ts.map +1 -1
  252. package/dist/src/integrations/hooks.js +99 -15
  253. package/dist/src/integrations/hooks.js.map +1 -1
  254. package/dist/src/integrations/index.d.ts +77 -66
  255. package/dist/src/integrations/index.d.ts.map +1 -1
  256. package/dist/src/integrations/index.js +83 -67
  257. package/dist/src/integrations/index.js.map +1 -1
  258. package/dist/src/integrations/logger.d.ts +104 -0
  259. package/dist/src/integrations/logger.d.ts.map +1 -0
  260. package/dist/src/integrations/logger.js +219 -0
  261. package/dist/src/integrations/logger.js.map +1 -0
  262. package/dist/src/integrations/lsp/lsp.d.ts +196 -0
  263. package/dist/src/integrations/lsp/lsp.d.ts.map +1 -0
  264. package/dist/src/integrations/lsp/lsp.js +583 -0
  265. package/dist/src/integrations/lsp/lsp.js.map +1 -0
  266. package/dist/src/integrations/lsp.d.ts.map +1 -1
  267. package/dist/src/integrations/lsp.js +5 -4
  268. package/dist/src/integrations/lsp.js.map +1 -1
  269. package/dist/src/integrations/mcp/mcp-client.d.ts +279 -0
  270. package/dist/src/integrations/mcp/mcp-client.d.ts.map +1 -0
  271. package/dist/src/integrations/mcp/mcp-client.js +755 -0
  272. package/dist/src/integrations/mcp/mcp-client.js.map +1 -0
  273. package/dist/src/integrations/mcp/mcp-custom-tools.d.ts +102 -0
  274. package/dist/src/integrations/mcp/mcp-custom-tools.d.ts.map +1 -0
  275. package/dist/src/integrations/mcp/mcp-custom-tools.js +232 -0
  276. package/dist/src/integrations/mcp/mcp-custom-tools.js.map +1 -0
  277. package/dist/src/integrations/mcp/mcp-tool-search.d.ts +77 -0
  278. package/dist/src/integrations/mcp/mcp-tool-search.d.ts.map +1 -0
  279. package/dist/src/integrations/mcp/mcp-tool-search.js +220 -0
  280. package/dist/src/integrations/mcp/mcp-tool-search.js.map +1 -0
  281. package/dist/src/integrations/mcp/mcp-tool-validator.d.ts +60 -0
  282. package/dist/src/integrations/mcp/mcp-tool-validator.d.ts.map +1 -0
  283. package/dist/src/integrations/mcp/mcp-tool-validator.js +141 -0
  284. package/dist/src/integrations/mcp/mcp-tool-validator.js.map +1 -0
  285. package/dist/src/integrations/mcp-client.d.ts.map +1 -1
  286. package/dist/src/integrations/mcp-client.js +8 -7
  287. package/dist/src/integrations/mcp-client.js.map +1 -1
  288. package/dist/src/integrations/observability.d.ts.map +1 -1
  289. package/dist/src/integrations/observability.js +5 -4
  290. package/dist/src/integrations/observability.js.map +1 -1
  291. package/dist/src/integrations/openrouter-pricing.d.ts.map +1 -1
  292. package/dist/src/integrations/openrouter-pricing.js +4 -3
  293. package/dist/src/integrations/openrouter-pricing.js.map +1 -1
  294. package/dist/src/integrations/persistence/codebase-repository.d.ts +45 -0
  295. package/dist/src/integrations/persistence/codebase-repository.d.ts.map +1 -0
  296. package/dist/src/integrations/persistence/codebase-repository.js +81 -0
  297. package/dist/src/integrations/persistence/codebase-repository.js.map +1 -0
  298. package/dist/src/integrations/persistence/goal-repository.d.ts +71 -0
  299. package/dist/src/integrations/persistence/goal-repository.d.ts.map +1 -0
  300. package/dist/src/integrations/persistence/goal-repository.js +184 -0
  301. package/dist/src/integrations/persistence/goal-repository.js.map +1 -0
  302. package/dist/src/integrations/persistence/history.d.ts +72 -0
  303. package/dist/src/integrations/persistence/history.d.ts.map +1 -0
  304. package/dist/src/integrations/persistence/history.js +165 -0
  305. package/dist/src/integrations/persistence/history.js.map +1 -0
  306. package/dist/src/integrations/persistence/persistence.d.ts +49 -0
  307. package/dist/src/integrations/persistence/persistence.d.ts.map +1 -0
  308. package/dist/src/integrations/persistence/persistence.js +197 -0
  309. package/dist/src/integrations/persistence/persistence.js.map +1 -0
  310. package/dist/src/integrations/persistence/session-repository.d.ts +212 -0
  311. package/dist/src/integrations/persistence/session-repository.d.ts.map +1 -0
  312. package/dist/src/integrations/persistence/session-repository.js +770 -0
  313. package/dist/src/integrations/persistence/session-repository.js.map +1 -0
  314. package/dist/src/integrations/persistence/session-store.d.ts +184 -0
  315. package/dist/src/integrations/persistence/session-store.d.ts.map +1 -0
  316. package/dist/src/integrations/persistence/session-store.js +346 -0
  317. package/dist/src/integrations/persistence/session-store.js.map +1 -0
  318. package/dist/src/integrations/persistence/sqlite-store.d.ts +453 -0
  319. package/dist/src/integrations/persistence/sqlite-store.d.ts.map +1 -0
  320. package/dist/src/integrations/persistence/sqlite-store.js +676 -0
  321. package/dist/src/integrations/persistence/sqlite-store.js.map +1 -0
  322. package/dist/src/integrations/persistence/worker-repository.d.ts +65 -0
  323. package/dist/src/integrations/persistence/worker-repository.d.ts.map +1 -0
  324. package/dist/src/integrations/persistence/worker-repository.js +183 -0
  325. package/dist/src/integrations/persistence/worker-repository.js.map +1 -0
  326. package/dist/src/integrations/persistence.d.ts.map +1 -1
  327. package/dist/src/integrations/persistence.js +5 -4
  328. package/dist/src/integrations/persistence.js.map +1 -1
  329. package/dist/src/integrations/planning.d.ts.map +1 -1
  330. package/dist/src/integrations/planning.js +5 -4
  331. package/dist/src/integrations/planning.js.map +1 -1
  332. package/dist/src/integrations/quality/auto-checkpoint.d.ts +98 -0
  333. package/dist/src/integrations/quality/auto-checkpoint.d.ts.map +1 -0
  334. package/dist/src/integrations/quality/auto-checkpoint.js +252 -0
  335. package/dist/src/integrations/quality/auto-checkpoint.js.map +1 -0
  336. package/dist/src/integrations/quality/dead-letter-queue.d.ts +233 -0
  337. package/dist/src/integrations/quality/dead-letter-queue.d.ts.map +1 -0
  338. package/dist/src/integrations/quality/dead-letter-queue.js +543 -0
  339. package/dist/src/integrations/quality/dead-letter-queue.js.map +1 -0
  340. package/dist/src/integrations/quality/health-check.d.ts +218 -0
  341. package/dist/src/integrations/quality/health-check.d.ts.map +1 -0
  342. package/dist/src/integrations/quality/health-check.js +415 -0
  343. package/dist/src/integrations/quality/health-check.js.map +1 -0
  344. package/dist/src/integrations/quality/learning-store.d.ts +291 -0
  345. package/dist/src/integrations/quality/learning-store.d.ts.map +1 -0
  346. package/dist/src/integrations/quality/learning-store.js +646 -0
  347. package/dist/src/integrations/quality/learning-store.js.map +1 -0
  348. package/dist/src/integrations/quality/self-improvement.d.ts +90 -0
  349. package/dist/src/integrations/quality/self-improvement.d.ts.map +1 -0
  350. package/dist/src/integrations/quality/self-improvement.js +229 -0
  351. package/dist/src/integrations/quality/self-improvement.js.map +1 -0
  352. package/dist/src/integrations/quality/tool-recommendation.d.ts +61 -0
  353. package/dist/src/integrations/quality/tool-recommendation.d.ts.map +1 -0
  354. package/dist/src/integrations/quality/tool-recommendation.js +268 -0
  355. package/dist/src/integrations/quality/tool-recommendation.js.map +1 -0
  356. package/dist/src/integrations/retry.d.ts +1 -0
  357. package/dist/src/integrations/retry.d.ts.map +1 -1
  358. package/dist/src/integrations/retry.js.map +1 -1
  359. package/dist/src/integrations/routing.d.ts.map +1 -1
  360. package/dist/src/integrations/routing.js +2 -1
  361. package/dist/src/integrations/routing.js.map +1 -1
  362. package/dist/src/integrations/safety/bash-policy.d.ts +33 -0
  363. package/dist/src/integrations/safety/bash-policy.d.ts.map +1 -0
  364. package/dist/src/integrations/safety/bash-policy.js +144 -0
  365. package/dist/src/integrations/safety/bash-policy.js.map +1 -0
  366. package/dist/src/integrations/safety/edit-validator.d.ts +30 -0
  367. package/dist/src/integrations/safety/edit-validator.d.ts.map +1 -0
  368. package/dist/src/integrations/safety/edit-validator.js +87 -0
  369. package/dist/src/integrations/safety/edit-validator.js.map +1 -0
  370. package/dist/src/integrations/safety/execution-policy.d.ts +189 -0
  371. package/dist/src/integrations/safety/execution-policy.d.ts.map +1 -0
  372. package/dist/src/integrations/safety/execution-policy.js +352 -0
  373. package/dist/src/integrations/safety/execution-policy.js.map +1 -0
  374. package/dist/src/integrations/safety/policy-engine.d.ts +55 -0
  375. package/dist/src/integrations/safety/policy-engine.d.ts.map +1 -0
  376. package/dist/src/integrations/safety/policy-engine.js +247 -0
  377. package/dist/src/integrations/safety/policy-engine.js.map +1 -0
  378. package/dist/src/integrations/safety/safety.d.ts +174 -0
  379. package/dist/src/integrations/safety/safety.d.ts.map +1 -0
  380. package/dist/src/integrations/safety/safety.js +470 -0
  381. package/dist/src/integrations/safety/safety.js.map +1 -0
  382. package/dist/src/integrations/safety/sandbox/basic.d.ts +81 -0
  383. package/dist/src/integrations/safety/sandbox/basic.d.ts.map +1 -0
  384. package/dist/src/integrations/safety/sandbox/basic.js +335 -0
  385. package/dist/src/integrations/safety/sandbox/basic.js.map +1 -0
  386. package/dist/src/integrations/safety/sandbox/docker.d.ts +94 -0
  387. package/dist/src/integrations/safety/sandbox/docker.d.ts.map +1 -0
  388. package/dist/src/integrations/safety/sandbox/docker.js +294 -0
  389. package/dist/src/integrations/safety/sandbox/docker.js.map +1 -0
  390. package/dist/src/integrations/safety/sandbox/index.d.ts +188 -0
  391. package/dist/src/integrations/safety/sandbox/index.d.ts.map +1 -0
  392. package/dist/src/integrations/safety/sandbox/index.js +386 -0
  393. package/dist/src/integrations/safety/sandbox/index.js.map +1 -0
  394. package/dist/src/integrations/safety/sandbox/landlock.d.ts +59 -0
  395. package/dist/src/integrations/safety/sandbox/landlock.d.ts.map +1 -0
  396. package/dist/src/integrations/safety/sandbox/landlock.js +329 -0
  397. package/dist/src/integrations/safety/sandbox/landlock.js.map +1 -0
  398. package/dist/src/integrations/safety/sandbox/seatbelt.d.ts +68 -0
  399. package/dist/src/integrations/safety/sandbox/seatbelt.d.ts.map +1 -0
  400. package/dist/src/integrations/safety/sandbox/seatbelt.js +298 -0
  401. package/dist/src/integrations/safety/sandbox/seatbelt.js.map +1 -0
  402. package/dist/src/integrations/safety/type-checker.d.ts +53 -0
  403. package/dist/src/integrations/safety/type-checker.d.ts.map +1 -0
  404. package/dist/src/integrations/safety/type-checker.js +142 -0
  405. package/dist/src/integrations/safety/type-checker.js.map +1 -0
  406. package/dist/src/integrations/safety.d.ts.map +1 -1
  407. package/dist/src/integrations/safety.js +13 -13
  408. package/dist/src/integrations/safety.js.map +1 -1
  409. package/dist/src/integrations/sandbox/docker.d.ts.map +1 -1
  410. package/dist/src/integrations/sandbox/docker.js +2 -1
  411. package/dist/src/integrations/sandbox/docker.js.map +1 -1
  412. package/dist/src/integrations/sandbox/index.d.ts.map +1 -1
  413. package/dist/src/integrations/sandbox/index.js +5 -4
  414. package/dist/src/integrations/sandbox/index.js.map +1 -1
  415. package/dist/src/integrations/session-store.d.ts +1 -0
  416. package/dist/src/integrations/session-store.d.ts.map +1 -1
  417. package/dist/src/integrations/session-store.js +1 -0
  418. package/dist/src/integrations/session-store.js.map +1 -1
  419. package/dist/src/integrations/shared-blackboard.d.ts +3 -0
  420. package/dist/src/integrations/shared-blackboard.d.ts.map +1 -1
  421. package/dist/src/integrations/shared-blackboard.js +47 -0
  422. package/dist/src/integrations/shared-blackboard.js.map +1 -1
  423. package/dist/src/integrations/skills/skill-executor.d.ts +113 -0
  424. package/dist/src/integrations/skills/skill-executor.d.ts.map +1 -0
  425. package/dist/src/integrations/skills/skill-executor.js +270 -0
  426. package/dist/src/integrations/skills/skill-executor.js.map +1 -0
  427. package/dist/src/integrations/skills/skills.d.ts +262 -0
  428. package/dist/src/integrations/skills/skills.d.ts.map +1 -0
  429. package/dist/src/integrations/skills/skills.js +602 -0
  430. package/dist/src/integrations/skills/skills.js.map +1 -0
  431. package/dist/src/integrations/smart-decomposer.d.ts +27 -0
  432. package/dist/src/integrations/smart-decomposer.d.ts.map +1 -1
  433. package/dist/src/integrations/smart-decomposer.js +414 -30
  434. package/dist/src/integrations/smart-decomposer.js.map +1 -1
  435. package/dist/src/integrations/sqlite-store.d.ts +2 -0
  436. package/dist/src/integrations/sqlite-store.d.ts.map +1 -1
  437. package/dist/src/integrations/sqlite-store.js +18 -6
  438. package/dist/src/integrations/sqlite-store.js.map +1 -1
  439. package/dist/src/integrations/streaming/pty-shell.d.ts +169 -0
  440. package/dist/src/integrations/streaming/pty-shell.d.ts.map +1 -0
  441. package/dist/src/integrations/streaming/pty-shell.js +367 -0
  442. package/dist/src/integrations/streaming/pty-shell.js.map +1 -0
  443. package/dist/src/integrations/streaming/streaming.d.ts +102 -0
  444. package/dist/src/integrations/streaming/streaming.d.ts.map +1 -0
  445. package/dist/src/integrations/streaming/streaming.js +362 -0
  446. package/dist/src/integrations/streaming/streaming.js.map +1 -0
  447. package/dist/src/integrations/swarm/failure-classifier.d.ts +11 -0
  448. package/dist/src/integrations/swarm/failure-classifier.d.ts.map +1 -0
  449. package/dist/src/integrations/swarm/failure-classifier.js +95 -0
  450. package/dist/src/integrations/swarm/failure-classifier.js.map +1 -0
  451. package/dist/src/integrations/swarm/index.d.ts +2 -1
  452. package/dist/src/integrations/swarm/index.d.ts.map +1 -1
  453. package/dist/src/integrations/swarm/index.js +2 -0
  454. package/dist/src/integrations/swarm/index.js.map +1 -1
  455. package/dist/src/integrations/swarm/model-selector.d.ts.map +1 -1
  456. package/dist/src/integrations/swarm/model-selector.js +2 -1
  457. package/dist/src/integrations/swarm/model-selector.js.map +1 -1
  458. package/dist/src/integrations/swarm/swarm-budget.d.ts +1 -1
  459. package/dist/src/integrations/swarm/swarm-budget.d.ts.map +1 -1
  460. package/dist/src/integrations/swarm/swarm-budget.js +1 -1
  461. package/dist/src/integrations/swarm/swarm-budget.js.map +1 -1
  462. package/dist/src/integrations/swarm/swarm-config-loader.d.ts +8 -0
  463. package/dist/src/integrations/swarm/swarm-config-loader.d.ts.map +1 -1
  464. package/dist/src/integrations/swarm/swarm-config-loader.js +102 -0
  465. package/dist/src/integrations/swarm/swarm-config-loader.js.map +1 -1
  466. package/dist/src/integrations/swarm/swarm-event-bridge.d.ts +74 -0
  467. package/dist/src/integrations/swarm/swarm-event-bridge.d.ts.map +1 -1
  468. package/dist/src/integrations/swarm/swarm-event-bridge.js +37 -0
  469. package/dist/src/integrations/swarm/swarm-event-bridge.js.map +1 -1
  470. package/dist/src/integrations/swarm/swarm-events.d.ts +4 -1
  471. package/dist/src/integrations/swarm/swarm-events.d.ts.map +1 -1
  472. package/dist/src/integrations/swarm/swarm-events.js +1 -1
  473. package/dist/src/integrations/swarm/swarm-events.js.map +1 -1
  474. package/dist/src/integrations/swarm/swarm-execution.d.ts +27 -0
  475. package/dist/src/integrations/swarm/swarm-execution.d.ts.map +1 -0
  476. package/dist/src/integrations/swarm/swarm-execution.js +1021 -0
  477. package/dist/src/integrations/swarm/swarm-execution.js.map +1 -0
  478. package/dist/src/integrations/swarm/swarm-helpers.d.ts +26 -0
  479. package/dist/src/integrations/swarm/swarm-helpers.d.ts.map +1 -0
  480. package/dist/src/integrations/swarm/swarm-helpers.js +95 -0
  481. package/dist/src/integrations/swarm/swarm-helpers.js.map +1 -0
  482. package/dist/src/integrations/swarm/swarm-lifecycle.d.ts +100 -0
  483. package/dist/src/integrations/swarm/swarm-lifecycle.d.ts.map +1 -0
  484. package/dist/src/integrations/swarm/swarm-lifecycle.js +922 -0
  485. package/dist/src/integrations/swarm/swarm-lifecycle.js.map +1 -0
  486. package/dist/src/integrations/swarm/swarm-orchestrator.d.ts +96 -192
  487. package/dist/src/integrations/swarm/swarm-orchestrator.d.ts.map +1 -1
  488. package/dist/src/integrations/swarm/swarm-orchestrator.js +384 -2528
  489. package/dist/src/integrations/swarm/swarm-orchestrator.js.map +1 -1
  490. package/dist/src/integrations/swarm/swarm-quality-gate.js +1 -1
  491. package/dist/src/integrations/swarm/swarm-quality-gate.js.map +1 -1
  492. package/dist/src/integrations/swarm/swarm-recovery.d.ts +75 -0
  493. package/dist/src/integrations/swarm/swarm-recovery.d.ts.map +1 -0
  494. package/dist/src/integrations/swarm/swarm-recovery.js +550 -0
  495. package/dist/src/integrations/swarm/swarm-recovery.js.map +1 -0
  496. package/dist/src/integrations/swarm/swarm-state-store.d.ts +4 -1
  497. package/dist/src/integrations/swarm/swarm-state-store.d.ts.map +1 -1
  498. package/dist/src/integrations/swarm/swarm-state-store.js +14 -1
  499. package/dist/src/integrations/swarm/swarm-state-store.js.map +1 -1
  500. package/dist/src/integrations/swarm/task-queue.d.ts +11 -1
  501. package/dist/src/integrations/swarm/task-queue.d.ts.map +1 -1
  502. package/dist/src/integrations/swarm/task-queue.js +64 -2
  503. package/dist/src/integrations/swarm/task-queue.js.map +1 -1
  504. package/dist/src/integrations/swarm/types.d.ts +57 -4
  505. package/dist/src/integrations/swarm/types.d.ts.map +1 -1
  506. package/dist/src/integrations/swarm/types.js +9 -0
  507. package/dist/src/integrations/swarm/types.js.map +1 -1
  508. package/dist/src/integrations/swarm/worker-pool.d.ts +13 -3
  509. package/dist/src/integrations/swarm/worker-pool.d.ts.map +1 -1
  510. package/dist/src/integrations/swarm/worker-pool.js +66 -13
  511. package/dist/src/integrations/swarm/worker-pool.js.map +1 -1
  512. package/dist/src/integrations/task-manager.d.ts +33 -1
  513. package/dist/src/integrations/task-manager.d.ts.map +1 -1
  514. package/dist/src/integrations/task-manager.js +78 -4
  515. package/dist/src/integrations/task-manager.js.map +1 -1
  516. package/dist/src/integrations/tasks/dependency-analyzer.d.ts +34 -0
  517. package/dist/src/integrations/tasks/dependency-analyzer.d.ts.map +1 -0
  518. package/dist/src/integrations/tasks/dependency-analyzer.js +232 -0
  519. package/dist/src/integrations/tasks/dependency-analyzer.js.map +1 -0
  520. package/dist/src/integrations/tasks/interactive-planning.d.ts +322 -0
  521. package/dist/src/integrations/tasks/interactive-planning.d.ts.map +1 -0
  522. package/dist/src/integrations/tasks/interactive-planning.js +655 -0
  523. package/dist/src/integrations/tasks/interactive-planning.js.map +1 -0
  524. package/dist/src/integrations/tasks/pending-plan.d.ts +196 -0
  525. package/dist/src/integrations/tasks/pending-plan.d.ts.map +1 -0
  526. package/dist/src/integrations/tasks/pending-plan.js +431 -0
  527. package/dist/src/integrations/tasks/pending-plan.js.map +1 -0
  528. package/dist/src/integrations/tasks/planning.d.ts +115 -0
  529. package/dist/src/integrations/tasks/planning.d.ts.map +1 -0
  530. package/dist/src/integrations/tasks/planning.js +413 -0
  531. package/dist/src/integrations/tasks/planning.js.map +1 -0
  532. package/dist/src/integrations/tasks/smart-decomposer.d.ts +316 -0
  533. package/dist/src/integrations/tasks/smart-decomposer.d.ts.map +1 -0
  534. package/dist/src/integrations/tasks/smart-decomposer.js +661 -0
  535. package/dist/src/integrations/tasks/smart-decomposer.js.map +1 -0
  536. package/dist/src/integrations/tasks/task-manager.d.ts +164 -0
  537. package/dist/src/integrations/tasks/task-manager.d.ts.map +1 -0
  538. package/dist/src/integrations/tasks/task-manager.js +383 -0
  539. package/dist/src/integrations/tasks/task-manager.js.map +1 -0
  540. package/dist/src/integrations/tasks/task-splitter.d.ts +56 -0
  541. package/dist/src/integrations/tasks/task-splitter.d.ts.map +1 -0
  542. package/dist/src/integrations/tasks/task-splitter.js +537 -0
  543. package/dist/src/integrations/tasks/task-splitter.js.map +1 -0
  544. package/dist/src/integrations/tasks/verification-gate.d.ts +103 -0
  545. package/dist/src/integrations/tasks/verification-gate.d.ts.map +1 -0
  546. package/dist/src/integrations/tasks/verification-gate.js +193 -0
  547. package/dist/src/integrations/tasks/verification-gate.js.map +1 -0
  548. package/dist/src/integrations/tasks/work-log.d.ts +87 -0
  549. package/dist/src/integrations/tasks/work-log.d.ts.map +1 -0
  550. package/dist/src/integrations/tasks/work-log.js +275 -0
  551. package/dist/src/integrations/tasks/work-log.js.map +1 -0
  552. package/dist/src/integrations/utilities/capabilities.d.ts +160 -0
  553. package/dist/src/integrations/utilities/capabilities.d.ts.map +1 -0
  554. package/dist/src/integrations/utilities/capabilities.js +426 -0
  555. package/dist/src/integrations/utilities/capabilities.js.map +1 -0
  556. package/dist/src/integrations/utilities/diff-utils.d.ts +105 -0
  557. package/dist/src/integrations/utilities/diff-utils.d.ts.map +1 -0
  558. package/dist/src/integrations/utilities/diff-utils.js +497 -0
  559. package/dist/src/integrations/utilities/diff-utils.js.map +1 -0
  560. package/dist/src/integrations/utilities/environment-facts.d.ts +52 -0
  561. package/dist/src/integrations/utilities/environment-facts.d.ts.map +1 -0
  562. package/dist/src/integrations/utilities/environment-facts.js +84 -0
  563. package/dist/src/integrations/utilities/environment-facts.js.map +1 -0
  564. package/dist/src/integrations/utilities/file-change-tracker.d.ts +162 -0
  565. package/dist/src/integrations/utilities/file-change-tracker.d.ts.map +1 -0
  566. package/dist/src/integrations/utilities/file-change-tracker.js +538 -0
  567. package/dist/src/integrations/utilities/file-change-tracker.js.map +1 -0
  568. package/dist/src/integrations/utilities/graph-visualization.d.ts +72 -0
  569. package/dist/src/integrations/utilities/graph-visualization.d.ts.map +1 -0
  570. package/dist/src/integrations/utilities/graph-visualization.js +383 -0
  571. package/dist/src/integrations/utilities/graph-visualization.js.map +1 -0
  572. package/dist/src/integrations/utilities/hierarchical-config.d.ts +215 -0
  573. package/dist/src/integrations/utilities/hierarchical-config.d.ts.map +1 -0
  574. package/dist/src/integrations/utilities/hierarchical-config.js +504 -0
  575. package/dist/src/integrations/utilities/hierarchical-config.js.map +1 -0
  576. package/dist/src/integrations/utilities/hooks.d.ts +116 -0
  577. package/dist/src/integrations/utilities/hooks.d.ts.map +1 -0
  578. package/dist/src/integrations/utilities/hooks.js +410 -0
  579. package/dist/src/integrations/utilities/hooks.js.map +1 -0
  580. package/dist/src/integrations/utilities/ignore.d.ts +143 -0
  581. package/dist/src/integrations/utilities/ignore.d.ts.map +1 -0
  582. package/dist/src/integrations/utilities/ignore.js +417 -0
  583. package/dist/src/integrations/utilities/ignore.js.map +1 -0
  584. package/dist/src/integrations/utilities/image-renderer.d.ts +119 -0
  585. package/dist/src/integrations/utilities/image-renderer.d.ts.map +1 -0
  586. package/dist/src/integrations/utilities/image-renderer.js +306 -0
  587. package/dist/src/integrations/utilities/image-renderer.js.map +1 -0
  588. package/dist/src/integrations/utilities/logger.d.ts +104 -0
  589. package/dist/src/integrations/utilities/logger.d.ts.map +1 -0
  590. package/dist/src/integrations/utilities/logger.js +219 -0
  591. package/dist/src/integrations/utilities/logger.js.map +1 -0
  592. package/dist/src/integrations/utilities/memory.d.ts +116 -0
  593. package/dist/src/integrations/utilities/memory.d.ts.map +1 -0
  594. package/dist/src/integrations/utilities/memory.js +311 -0
  595. package/dist/src/integrations/utilities/memory.js.map +1 -0
  596. package/dist/src/integrations/utilities/observability.d.ts +162 -0
  597. package/dist/src/integrations/utilities/observability.d.ts.map +1 -0
  598. package/dist/src/integrations/utilities/observability.js +407 -0
  599. package/dist/src/integrations/utilities/observability.js.map +1 -0
  600. package/dist/src/integrations/utilities/openrouter-pricing.d.ts +67 -0
  601. package/dist/src/integrations/utilities/openrouter-pricing.d.ts.map +1 -0
  602. package/dist/src/integrations/utilities/openrouter-pricing.js +166 -0
  603. package/dist/src/integrations/utilities/openrouter-pricing.js.map +1 -0
  604. package/dist/src/integrations/utilities/react.d.ts +139 -0
  605. package/dist/src/integrations/utilities/react.d.ts.map +1 -0
  606. package/dist/src/integrations/utilities/react.js +273 -0
  607. package/dist/src/integrations/utilities/react.js.map +1 -0
  608. package/dist/src/integrations/utilities/retry.d.ts +132 -0
  609. package/dist/src/integrations/utilities/retry.d.ts.map +1 -0
  610. package/dist/src/integrations/utilities/retry.js +233 -0
  611. package/dist/src/integrations/utilities/retry.js.map +1 -0
  612. package/dist/src/integrations/utilities/routing.d.ts +118 -0
  613. package/dist/src/integrations/utilities/routing.d.ts.map +1 -0
  614. package/dist/src/integrations/utilities/routing.js +348 -0
  615. package/dist/src/integrations/utilities/routing.js.map +1 -0
  616. package/dist/src/integrations/utilities/rules.d.ts +131 -0
  617. package/dist/src/integrations/utilities/rules.d.ts.map +1 -0
  618. package/dist/src/integrations/utilities/rules.js +284 -0
  619. package/dist/src/integrations/utilities/rules.js.map +1 -0
  620. package/dist/src/integrations/utilities/sourcegraph.d.ts +169 -0
  621. package/dist/src/integrations/utilities/sourcegraph.d.ts.map +1 -0
  622. package/dist/src/integrations/utilities/sourcegraph.js +379 -0
  623. package/dist/src/integrations/utilities/sourcegraph.js.map +1 -0
  624. package/dist/src/integrations/utilities/thinking-strategy.d.ts +52 -0
  625. package/dist/src/integrations/utilities/thinking-strategy.d.ts.map +1 -0
  626. package/dist/src/integrations/utilities/thinking-strategy.js +129 -0
  627. package/dist/src/integrations/utilities/thinking-strategy.js.map +1 -0
  628. package/dist/src/integrations/utilities/thread-manager.d.ts +199 -0
  629. package/dist/src/integrations/utilities/thread-manager.d.ts.map +1 -0
  630. package/dist/src/integrations/utilities/thread-manager.js +357 -0
  631. package/dist/src/integrations/utilities/thread-manager.js.map +1 -0
  632. package/dist/src/integrations/utilities/token-estimate.d.ts +11 -0
  633. package/dist/src/integrations/utilities/token-estimate.d.ts.map +1 -0
  634. package/dist/src/integrations/utilities/token-estimate.js +14 -0
  635. package/dist/src/integrations/utilities/token-estimate.js.map +1 -0
  636. package/dist/src/main.js +92 -35
  637. package/dist/src/main.js.map +1 -1
  638. package/dist/src/modes/repl.d.ts.map +1 -1
  639. package/dist/src/modes/repl.js +60 -11
  640. package/dist/src/modes/repl.js.map +1 -1
  641. package/dist/src/modes/tui.d.ts.map +1 -1
  642. package/dist/src/modes/tui.js +57 -10
  643. package/dist/src/modes/tui.js.map +1 -1
  644. package/dist/src/modes.js +1 -1
  645. package/dist/src/modes.js.map +1 -1
  646. package/dist/src/observability/tracer.d.ts.map +1 -1
  647. package/dist/src/observability/tracer.js +2 -1
  648. package/dist/src/observability/tracer.js.map +1 -1
  649. package/dist/src/persistence/schema.d.ts +2 -0
  650. package/dist/src/persistence/schema.d.ts.map +1 -1
  651. package/dist/src/persistence/schema.js +42 -0
  652. package/dist/src/persistence/schema.js.map +1 -1
  653. package/dist/src/providers/adapters/anthropic.d.ts +6 -0
  654. package/dist/src/providers/adapters/anthropic.d.ts.map +1 -1
  655. package/dist/src/providers/adapters/anthropic.js +101 -16
  656. package/dist/src/providers/adapters/anthropic.js.map +1 -1
  657. package/dist/src/providers/adapters/azure.d.ts +74 -0
  658. package/dist/src/providers/adapters/azure.d.ts.map +1 -0
  659. package/dist/src/providers/adapters/azure.js +354 -0
  660. package/dist/src/providers/adapters/azure.js.map +1 -0
  661. package/dist/src/providers/adapters/mock.d.ts +16 -2
  662. package/dist/src/providers/adapters/mock.d.ts.map +1 -1
  663. package/dist/src/providers/adapters/mock.js +44 -3
  664. package/dist/src/providers/adapters/mock.js.map +1 -1
  665. package/dist/src/providers/adapters/openai.d.ts +6 -1
  666. package/dist/src/providers/adapters/openai.d.ts.map +1 -1
  667. package/dist/src/providers/adapters/openai.js +41 -9
  668. package/dist/src/providers/adapters/openai.js.map +1 -1
  669. package/dist/src/providers/adapters/openrouter.d.ts +6 -0
  670. package/dist/src/providers/adapters/openrouter.d.ts.map +1 -1
  671. package/dist/src/providers/adapters/openrouter.js +83 -13
  672. package/dist/src/providers/adapters/openrouter.js.map +1 -1
  673. package/dist/src/providers/circuit-breaker.d.ts +1 -0
  674. package/dist/src/providers/circuit-breaker.d.ts.map +1 -1
  675. package/dist/src/providers/circuit-breaker.js.map +1 -1
  676. package/dist/src/providers/provider.d.ts.map +1 -1
  677. package/dist/src/providers/provider.js +2 -1
  678. package/dist/src/providers/provider.js.map +1 -1
  679. package/dist/src/providers/resilient-provider.d.ts.map +1 -1
  680. package/dist/src/providers/resilient-provider.js +2 -1
  681. package/dist/src/providers/resilient-provider.js.map +1 -1
  682. package/dist/src/providers/types.d.ts +23 -2
  683. package/dist/src/providers/types.d.ts.map +1 -1
  684. package/dist/src/session-picker.d.ts +1 -1
  685. package/dist/src/session-picker.d.ts.map +1 -1
  686. package/dist/src/session-picker.js +40 -5
  687. package/dist/src/session-picker.js.map +1 -1
  688. package/dist/src/shared/budget-tracker.d.ts +65 -0
  689. package/dist/src/shared/budget-tracker.d.ts.map +1 -0
  690. package/dist/src/shared/budget-tracker.js +128 -0
  691. package/dist/src/shared/budget-tracker.js.map +1 -0
  692. package/dist/src/shared/context-engine.d.ts +64 -0
  693. package/dist/src/shared/context-engine.d.ts.map +1 -0
  694. package/dist/src/shared/context-engine.js +117 -0
  695. package/dist/src/shared/context-engine.js.map +1 -0
  696. package/dist/src/shared/index.d.ts +12 -0
  697. package/dist/src/shared/index.d.ts.map +1 -0
  698. package/dist/src/shared/index.js +12 -0
  699. package/dist/src/shared/index.js.map +1 -0
  700. package/dist/src/shared/persistence.d.ts +57 -0
  701. package/dist/src/shared/persistence.d.ts.map +1 -0
  702. package/dist/src/shared/persistence.js +168 -0
  703. package/dist/src/shared/persistence.js.map +1 -0
  704. package/dist/src/shared/shared-context-state.d.ts +89 -0
  705. package/dist/src/shared/shared-context-state.d.ts.map +1 -0
  706. package/dist/src/shared/shared-context-state.js +175 -0
  707. package/dist/src/shared/shared-context-state.js.map +1 -0
  708. package/dist/src/shared/shared-economics-state.d.ts +61 -0
  709. package/dist/src/shared/shared-economics-state.d.ts.map +1 -0
  710. package/dist/src/shared/shared-economics-state.js +100 -0
  711. package/dist/src/shared/shared-economics-state.js.map +1 -0
  712. package/dist/src/tools/agent.d.ts +1 -1
  713. package/dist/src/tools/agent.d.ts.map +1 -1
  714. package/dist/src/tools/bash.d.ts +3 -3
  715. package/dist/src/tools/bash.d.ts.map +1 -1
  716. package/dist/src/tools/bash.js +2 -1
  717. package/dist/src/tools/bash.js.map +1 -1
  718. package/dist/src/tools/file.d.ts +3 -3
  719. package/dist/src/tools/file.js +1 -1
  720. package/dist/src/tools/file.js.map +1 -1
  721. package/dist/src/tools/permission.d.ts.map +1 -1
  722. package/dist/src/tools/permission.js +7 -6
  723. package/dist/src/tools/permission.js.map +1 -1
  724. package/dist/src/tools/registry.d.ts +1 -1
  725. package/dist/src/tools/registry.d.ts.map +1 -1
  726. package/dist/src/tools/registry.js +1 -1
  727. package/dist/src/tools/registry.js.map +1 -1
  728. package/dist/src/tools/tasks.d.ts +1 -1
  729. package/dist/src/tools/tasks.d.ts.map +1 -1
  730. package/dist/src/tools/types.d.ts +1 -0
  731. package/dist/src/tools/types.d.ts.map +1 -1
  732. package/dist/src/tools/types.js.map +1 -1
  733. package/dist/src/tools/undo.d.ts +1 -1
  734. package/dist/src/tools/undo.d.ts.map +1 -1
  735. package/dist/src/tracing/cache-boundary-tracker.d.ts.map +1 -1
  736. package/dist/src/tracing/cache-boundary-tracker.js +2 -2
  737. package/dist/src/tracing/cache-boundary-tracker.js.map +1 -1
  738. package/dist/src/tracing/trace-collector.d.ts +147 -0
  739. package/dist/src/tracing/trace-collector.d.ts.map +1 -1
  740. package/dist/src/tracing/trace-collector.js +138 -7
  741. package/dist/src/tracing/trace-collector.js.map +1 -1
  742. package/dist/src/tracing/types.d.ts +112 -1
  743. package/dist/src/tracing/types.d.ts.map +1 -1
  744. package/dist/src/tracing/types.js.map +1 -1
  745. package/dist/src/tricks/failure-evidence.d.ts.map +1 -1
  746. package/dist/src/tricks/failure-evidence.js +2 -1
  747. package/dist/src/tricks/failure-evidence.js.map +1 -1
  748. package/dist/src/tricks/recitation.d.ts.map +1 -1
  749. package/dist/src/tricks/recitation.js +2 -1
  750. package/dist/src/tricks/recitation.js.map +1 -1
  751. package/dist/src/tricks/recursive-context.d.ts.map +1 -1
  752. package/dist/src/tricks/recursive-context.js +2 -2
  753. package/dist/src/tricks/recursive-context.js.map +1 -1
  754. package/dist/src/tricks/reversible-compaction.d.ts.map +1 -1
  755. package/dist/src/tricks/reversible-compaction.js +6 -2
  756. package/dist/src/tricks/reversible-compaction.js.map +1 -1
  757. package/dist/src/tui/app.d.ts +16 -3
  758. package/dist/src/tui/app.d.ts.map +1 -1
  759. package/dist/src/tui/app.js +211 -25
  760. package/dist/src/tui/app.js.map +1 -1
  761. package/dist/src/tui/components/CollapsibleDiffView.d.ts +1 -1
  762. package/dist/src/tui/components/CollapsibleDiffView.d.ts.map +1 -1
  763. package/dist/src/tui/components/DiagnosticsPanel.d.ts +24 -0
  764. package/dist/src/tui/components/DiagnosticsPanel.d.ts.map +1 -0
  765. package/dist/src/tui/components/DiagnosticsPanel.js +47 -0
  766. package/dist/src/tui/components/DiagnosticsPanel.js.map +1 -0
  767. package/dist/src/tui/components/DiffView.d.ts +1 -1
  768. package/dist/src/tui/components/DiffView.d.ts.map +1 -1
  769. package/dist/src/tui/components/ErrorBoundary.d.ts.map +1 -1
  770. package/dist/src/tui/components/ErrorBoundary.js +3 -2
  771. package/dist/src/tui/components/ErrorBoundary.js.map +1 -1
  772. package/dist/src/tui/components/TasksPanel.d.ts +1 -1
  773. package/dist/src/tui/components/TasksPanel.d.ts.map +1 -1
  774. package/dist/src/tui/event-display.d.ts.map +1 -1
  775. package/dist/src/tui/event-display.js +36 -62
  776. package/dist/src/tui/event-display.js.map +1 -1
  777. package/dist/src/tui/index.d.ts +4 -0
  778. package/dist/src/tui/index.d.ts.map +1 -1
  779. package/dist/src/tui/index.js +17 -0
  780. package/dist/src/tui/index.js.map +1 -1
  781. package/dist/src/tui/transparency-aggregator.d.ts +13 -0
  782. package/dist/src/tui/transparency-aggregator.d.ts.map +1 -1
  783. package/dist/src/tui/transparency-aggregator.js +21 -0
  784. package/dist/src/tui/transparency-aggregator.js.map +1 -1
  785. package/dist/src/types.d.ts +170 -3
  786. package/dist/src/types.d.ts.map +1 -1
  787. package/package.json +18 -3
@@ -0,0 +1,1397 @@
1
+ /**
2
+ * Execution Loop Module (Phase 2.1)
3
+ *
4
+ * Extracted from ProductionAgent.executeDirectly().
5
+ * Contains the main ReAct while(true) loop: cancellation checks, resource checks,
6
+ * economics/budget checks with compaction recovery, loop detection, context
7
+ * engineering injection (recitation, failure evidence), LLM call dispatch,
8
+ * resilience handling, tool execution, and compaction.
9
+ */
10
+ import { isFeatureEnabled } from '../defaults.js';
11
+ import { estimateTokenCount } from '../integrations/utilities/token-estimate.js';
12
+ import { callLLM } from './response-handler.js';
13
+ import { executeToolCalls } from './tool-executor.js';
14
+ import { TIMEOUT_WRAPUP_PROMPT, stableStringify, } from '../integrations/index.js';
15
+ import { detectIncompleteActionResponse } from './completion-analyzer.js';
16
+ export { detectIncompleteActionResponse } from './completion-analyzer.js';
17
+ import { createComponentLogger } from '../integrations/utilities/logger.js';
18
+ import { validateSyntax } from '../integrations/safety/edit-validator.js';
19
+ import { runTypeCheck, formatTypeCheckNudge } from '../integrations/safety/type-checker.js';
20
+ import { invalidateAST } from '../integrations/context/codebase-ast.js';
21
+ import * as fs from 'node:fs';
22
+ const log = createComponentLogger('ExecutionLoop');
23
+ // =============================================================================
24
+ // HELPER FUNCTIONS (extracted from ProductionAgent private methods)
25
+ // =============================================================================
26
+ /**
27
+ * Estimate total tokens in a message array.
28
+ * Uses ~4 chars per token heuristic for fast estimation.
29
+ */
30
+ export function estimateContextTokens(messages) {
31
+ let totalChars = 0;
32
+ for (const msg of messages) {
33
+ if (msg.content) {
34
+ totalChars += msg.content.length;
35
+ }
36
+ if (msg.toolCalls) {
37
+ for (const tc of msg.toolCalls) {
38
+ totalChars += tc.name.length;
39
+ totalChars += JSON.stringify(tc.arguments).length;
40
+ }
41
+ }
42
+ }
43
+ return Math.ceil(totalChars / 4);
44
+ }
45
+ /**
46
+ * Compact tool outputs to save context.
47
+ */
48
+ export function compactToolOutputs(messages) {
49
+ const COMPACT_PREVIEW_LENGTH = 200;
50
+ const MAX_PRESERVED_EXPENSIVE_RESULTS = 6;
51
+ let compactedCount = 0;
52
+ let savedChars = 0;
53
+ const preservedExpensiveIndexes = messages
54
+ .map((msg, index) => ({ msg, index }))
55
+ .filter(({ msg }) => msg.role === 'tool' && msg.metadata?.preserveFromCompaction === true)
56
+ .map(({ index }) => index);
57
+ const preserveSet = new Set(preservedExpensiveIndexes.slice(-MAX_PRESERVED_EXPENSIVE_RESULTS));
58
+ for (let i = 0; i < messages.length; i++) {
59
+ const msg = messages[i];
60
+ if (msg.role === 'tool' && msg.content && msg.content.length > COMPACT_PREVIEW_LENGTH * 2) {
61
+ if (msg.metadata?.preserveFromCompaction === true && preserveSet.has(i)) {
62
+ continue;
63
+ }
64
+ const originalLength = msg.content.length;
65
+ const preview = msg.content.slice(0, COMPACT_PREVIEW_LENGTH).replace(/\n/g, ' ');
66
+ msg.content = `[${preview}...] (${originalLength} chars, compacted)`;
67
+ savedChars += originalLength - msg.content.length;
68
+ compactedCount++;
69
+ }
70
+ }
71
+ if (compactedCount > 0 && process.env.DEBUG) {
72
+ log.debug('Compacted tool outputs', { compactedCount, savedTokens: Math.round(savedChars / 4) });
73
+ }
74
+ }
75
+ /**
76
+ * Extract a requested markdown artifact filename from a task prompt.
77
+ */
78
+ export function extractRequestedArtifact(task) {
79
+ const markdownArtifactMatch = task.match(/(?:write|save|create)[^.\n]{0,120}\b([A-Za-z0-9._/-]+\.md)\b/i);
80
+ return markdownArtifactMatch?.[1] ?? null;
81
+ }
82
+ /**
83
+ * Check whether a requested artifact appears to be missing.
84
+ */
85
+ export function isRequestedArtifactMissing(requestedArtifact, executedToolNames) {
86
+ if (!requestedArtifact)
87
+ return false;
88
+ const artifactWriteTools = ['write_file', 'edit_file', 'apply_patch', 'append_file'];
89
+ return !artifactWriteTools.some(toolName => executedToolNames.has(toolName));
90
+ }
91
+ function getOpenTaskSummary(ctx) {
92
+ if (!ctx.taskManager)
93
+ return undefined;
94
+ const tasks = ctx.taskManager.list();
95
+ const pending = tasks.filter(t => t.status === 'pending').length;
96
+ const inProgress = tasks.filter(t => t.status === 'in_progress').length;
97
+ const blocked = tasks.filter(t => t.status === 'pending' && ctx.taskManager?.isBlocked(t.id)).length;
98
+ return { pending, inProgress, blocked };
99
+ }
100
+ function getPendingWithOwnerCount(ctx) {
101
+ if (!ctx.taskManager)
102
+ return 0;
103
+ return ctx.taskManager.list().filter(t => t.status === 'pending' && !!t.owner).length;
104
+ }
105
+ // =============================================================================
106
+ // MAIN EXECUTION LOOP
107
+ // =============================================================================
108
+ /**
109
+ * Execute a task directly without planning.
110
+ * This is the main ReAct loop extracted from ProductionAgent.executeDirectly().
111
+ *
112
+ * @param task - The user task to execute
113
+ * @param ctx - Agent context (managers, config, state)
114
+ * @param mutators - Functions to update mutable agent state
115
+ */
116
+ export async function executeDirectly(task, messages, ctx, mutators) {
117
+ // Reset economics for new task
118
+ ctx.economics?.reset();
119
+ const taskLeaseStaleMs = typeof ctx.config.resilience === 'object'
120
+ ? (ctx.config.resilience.taskLeaseStaleMs ?? 5 * 60 * 1000)
121
+ : 5 * 60 * 1000;
122
+ // Recover orphaned in-progress tasks left behind by interrupted runs.
123
+ if (ctx.taskManager) {
124
+ const recovered = ctx.taskManager.reconcileStaleInProgress({
125
+ staleAfterMs: taskLeaseStaleMs,
126
+ reason: 'execution_loop_start',
127
+ });
128
+ if (recovered.reconciled > 0) {
129
+ log.info('Recovered stale in-progress tasks at execution start', {
130
+ recovered: recovered.reconciled,
131
+ });
132
+ }
133
+ }
134
+ // Reflection configuration
135
+ const reflectionConfig = ctx.config.reflection;
136
+ const reflectionEnabled = isFeatureEnabled(reflectionConfig);
137
+ const autoReflect = reflectionEnabled && reflectionConfig.autoReflect;
138
+ const maxReflectionAttempts = reflectionEnabled
139
+ ? (reflectionConfig.maxAttempts || 3)
140
+ : 1;
141
+ const confidenceThreshold = reflectionEnabled
142
+ ? (reflectionConfig.confidenceThreshold || 0.8)
143
+ : 0.8;
144
+ let reflectionAttempt = 0;
145
+ let lastResponse = '';
146
+ let incompleteActionRetries = 0;
147
+ const requestedArtifact = extractRequestedArtifact(task);
148
+ const executedToolNames = new Set();
149
+ let result = {
150
+ success: true,
151
+ terminationReason: 'completed',
152
+ };
153
+ // Outer loop for reflection (if enabled)
154
+ while (reflectionAttempt < maxReflectionAttempts) {
155
+ reflectionAttempt++;
156
+ // Agent loop - uses economics-based budget checking
157
+ while (true) {
158
+ ctx.state.iteration++;
159
+ ctx.emit({ type: 'iteration.before', iteration: ctx.state.iteration });
160
+ // Record iteration start for tracing
161
+ ctx.traceCollector?.record({
162
+ type: 'iteration.start',
163
+ data: { iterationNumber: ctx.state.iteration },
164
+ });
165
+ // =======================================================================
166
+ // CANCELLATION CHECK
167
+ // =======================================================================
168
+ if (ctx.cancellation?.isCancelled) {
169
+ ctx.cancellation.token.throwIfCancellationRequested();
170
+ }
171
+ // =======================================================================
172
+ // RESOURCE CHECK
173
+ // =======================================================================
174
+ if (ctx.resourceManager) {
175
+ const resourceCheck = ctx.resourceManager.check();
176
+ if (!resourceCheck.canContinue) {
177
+ ctx.observability?.logger?.warn('Resource limit reached', {
178
+ status: resourceCheck.status,
179
+ message: resourceCheck.message,
180
+ });
181
+ const reason = resourceCheck.message || 'Resource limit exceeded';
182
+ ctx.emit({ type: 'error', error: reason });
183
+ result = {
184
+ success: false,
185
+ terminationReason: 'resource_limit',
186
+ failureReason: reason,
187
+ };
188
+ break;
189
+ }
190
+ if (resourceCheck.status === 'warning' || resourceCheck.status === 'critical') {
191
+ ctx.observability?.logger?.info(`Resource status: ${resourceCheck.status}`, {
192
+ message: resourceCheck.message,
193
+ });
194
+ }
195
+ }
196
+ // =======================================================================
197
+ // ECONOMICS CHECK (Token Budget)
198
+ // =======================================================================
199
+ let forceTextOnly = false;
200
+ let budgetInjectedPrompt;
201
+ let budgetAllowsTaskContinuation = true;
202
+ if (ctx.economics) {
203
+ const budgetCheck = ctx.economics.checkBudget();
204
+ forceTextOnly = budgetCheck.forceTextOnly ?? false;
205
+ budgetInjectedPrompt = budgetCheck.injectedPrompt;
206
+ budgetAllowsTaskContinuation = budgetCheck.allowTaskContinuation ?? true;
207
+ // Record budget check in trace for debugging premature death
208
+ ctx.traceCollector?.record({
209
+ type: 'budget.check',
210
+ data: {
211
+ iteration: ctx.state.iteration,
212
+ canContinue: budgetCheck.canContinue,
213
+ percentUsed: budgetCheck.percentUsed,
214
+ budgetType: budgetCheck.budgetType,
215
+ budgetMode: budgetCheck.budgetMode,
216
+ forceTextOnly,
217
+ allowTaskContinuation: budgetAllowsTaskContinuation,
218
+ enforcementMode: ctx.economics.getBudget().enforcementMode ?? 'strict',
219
+ tokenUsage: ctx.economics.getUsage().tokens,
220
+ maxTokens: ctx.economics.getBudget().maxTokens,
221
+ },
222
+ });
223
+ if (!budgetCheck.canContinue) {
224
+ // RECOVERY ATTEMPT: Try emergency context reduction
225
+ const isTokenLimit = budgetCheck.budgetType === 'tokens' || budgetCheck.budgetType === 'cost';
226
+ const alreadyTriedRecovery = ctx.state._recoveryAttempted === true;
227
+ if (isTokenLimit && !alreadyTriedRecovery) {
228
+ ctx.observability?.logger?.info('Budget limit reached, attempting recovery via context reduction', {
229
+ reason: budgetCheck.reason,
230
+ percentUsed: budgetCheck.percentUsed,
231
+ });
232
+ ctx.emit({
233
+ type: 'resilience.retry',
234
+ reason: 'budget_limit_compaction',
235
+ attempt: 1,
236
+ maxAttempts: 1,
237
+ });
238
+ ctx.state.metrics.retryCount = (ctx.state.metrics.retryCount ?? 0) + 1;
239
+ ctx.state._recoveryAttempted = true;
240
+ const tokensBefore = estimateContextTokens(messages);
241
+ // Step 1: Compact tool outputs aggressively
242
+ compactToolOutputs(ctx.state.messages);
243
+ // Step 2: Emergency truncation - keep system + last N messages
244
+ const PRESERVE_RECENT = 10;
245
+ if (messages.length > PRESERVE_RECENT + 2) {
246
+ const systemMessage = messages.find(m => m.role === 'system');
247
+ const recentMessages = messages.slice(-(PRESERVE_RECENT));
248
+ messages.length = 0;
249
+ if (systemMessage) {
250
+ messages.push(systemMessage);
251
+ }
252
+ messages.push({
253
+ role: 'system',
254
+ content: `[CONTEXT REDUCED: Earlier messages were removed to stay within budget. Conversation continues from recent context.]`,
255
+ });
256
+ messages.push(...recentMessages);
257
+ // Inject work log after emergency truncation
258
+ if (ctx.workLog?.hasContent()) {
259
+ const workLogMessage = {
260
+ role: 'user',
261
+ content: ctx.workLog.toCompactString(),
262
+ };
263
+ messages.push(workLogMessage);
264
+ }
265
+ // Update state messages too
266
+ ctx.state.messages.length = 0;
267
+ ctx.state.messages.push(...messages);
268
+ }
269
+ const tokensAfter = estimateContextTokens(messages);
270
+ const reduction = Math.round((1 - tokensAfter / tokensBefore) * 100);
271
+ if (tokensAfter < tokensBefore * 0.8) {
272
+ ctx.observability?.logger?.info('Context reduction successful, continuing execution', {
273
+ tokensBefore,
274
+ tokensAfter,
275
+ reduction,
276
+ });
277
+ ctx.emit({
278
+ type: 'resilience.recovered',
279
+ reason: 'budget_limit_compaction',
280
+ attempts: 1,
281
+ });
282
+ ctx.emit({
283
+ type: 'compaction.auto',
284
+ tokensBefore,
285
+ tokensAfter,
286
+ messagesCompacted: tokensBefore - tokensAfter,
287
+ });
288
+ // Update baseline after emergency context reduction so
289
+ // incremental token accounting reflects the new context size
290
+ ctx.economics?.updateBaseline(tokensAfter);
291
+ continue;
292
+ }
293
+ ctx.observability?.logger?.warn('Context reduction insufficient', {
294
+ tokensBefore,
295
+ tokensAfter,
296
+ reduction,
297
+ });
298
+ }
299
+ // Hard limit reached and recovery failed
300
+ ctx.observability?.logger?.warn('Budget limit reached', {
301
+ reason: budgetCheck.reason,
302
+ budgetType: budgetCheck.budgetType,
303
+ });
304
+ if (budgetCheck.budgetType === 'iterations') {
305
+ const totalIter = ctx.getTotalIterations();
306
+ const iterMsg = ctx.parentIterations > 0
307
+ ? `${ctx.state.iteration} + ${ctx.parentIterations} parent = ${totalIter}`
308
+ : `${ctx.state.iteration}`;
309
+ const reason = `Max iterations reached (${iterMsg})`;
310
+ ctx.emit({ type: 'error', error: reason });
311
+ result = {
312
+ success: false,
313
+ terminationReason: 'max_iterations',
314
+ failureReason: reason,
315
+ };
316
+ }
317
+ else {
318
+ const reason = budgetCheck.reason || 'Budget exceeded';
319
+ ctx.emit({ type: 'error', error: reason });
320
+ result = {
321
+ success: false,
322
+ terminationReason: 'budget_limit',
323
+ failureReason: reason,
324
+ };
325
+ }
326
+ break;
327
+ }
328
+ // Check for soft limits and potential extension
329
+ if (budgetCheck.isSoftLimit && budgetCheck.suggestedAction === 'request_extension') {
330
+ ctx.observability?.logger?.info('Approaching budget limit', {
331
+ reason: budgetCheck.reason,
332
+ percentUsed: budgetCheck.percentUsed,
333
+ });
334
+ }
335
+ }
336
+ else {
337
+ // Fallback to simple iteration check
338
+ if (ctx.getTotalIterations() >= ctx.config.maxIterations) {
339
+ const totalIter = ctx.getTotalIterations();
340
+ const reason = `Max iterations reached (${totalIter})`;
341
+ ctx.observability?.logger?.warn('Max iterations reached', {
342
+ iteration: ctx.state.iteration,
343
+ parentIterations: ctx.parentIterations,
344
+ total: totalIter,
345
+ });
346
+ ctx.emit({ type: 'error', error: reason });
347
+ result = {
348
+ success: false,
349
+ terminationReason: 'max_iterations',
350
+ failureReason: reason,
351
+ };
352
+ break;
353
+ }
354
+ }
355
+ // =======================================================================
356
+ // GRACEFUL WRAPUP CHECK
357
+ // =======================================================================
358
+ if (ctx.wrapupRequested && !forceTextOnly) {
359
+ forceTextOnly = true;
360
+ budgetInjectedPrompt = TIMEOUT_WRAPUP_PROMPT;
361
+ mutators.setWrapupRequested(false);
362
+ }
363
+ // =======================================================================
364
+ // EXTERNAL CANCELLATION CHECK (deferred)
365
+ // =======================================================================
366
+ if (ctx.externalCancellationToken?.isCancellationRequested && !forceTextOnly) {
367
+ ctx.externalCancellationToken.throwIfCancellationRequested();
368
+ }
369
+ // =======================================================================
370
+ // INTELLIGENT LOOP DETECTION & NUDGE INJECTION
371
+ // =======================================================================
372
+ if (ctx.economics && budgetInjectedPrompt) {
373
+ messages.push({
374
+ role: 'user',
375
+ content: budgetInjectedPrompt,
376
+ });
377
+ const loopState = ctx.economics.getLoopState();
378
+ const phaseState = ctx.economics.getPhaseState();
379
+ ctx.observability?.logger?.info('Loop detection - injecting guidance', {
380
+ iteration: ctx.state.iteration,
381
+ doomLoop: loopState.doomLoopDetected,
382
+ phase: phaseState.phase,
383
+ filesRead: phaseState.uniqueFilesRead,
384
+ filesModified: phaseState.filesModified,
385
+ shouldTransition: phaseState.shouldTransition,
386
+ forceTextOnly,
387
+ });
388
+ }
389
+ // =======================================================================
390
+ // RECITATION INJECTION (Trick Q)
391
+ // =======================================================================
392
+ if (ctx.contextEngineering) {
393
+ if (process.env.DEBUG_LLM) {
394
+ if (process.env.DEBUG)
395
+ log.debug('Recitation before', { messageCount: messages.length });
396
+ }
397
+ const enrichedMessages = ctx.contextEngineering.injectRecitation(messages, {
398
+ goal: task,
399
+ plan: ctx.state.plan ? {
400
+ description: ctx.state.plan.goal || task,
401
+ tasks: ctx.state.plan.tasks.map(t => ({
402
+ id: t.id,
403
+ description: t.description,
404
+ status: t.status,
405
+ })),
406
+ currentTaskIndex: ctx.state.plan.tasks.findIndex(t => t.status === 'in_progress'),
407
+ } : undefined,
408
+ activeFiles: ctx.economics?.getProgress().filesModified
409
+ ? [`${ctx.economics.getProgress().filesModified} files modified`]
410
+ : undefined,
411
+ recentErrors: ctx.contextEngineering.getFailureInsights().slice(0, 2),
412
+ });
413
+ if (process.env.DEBUG_LLM) {
414
+ if (process.env.DEBUG)
415
+ log.debug('Recitation after', { messageCount: enrichedMessages?.length ?? 'null/undefined' });
416
+ }
417
+ if (enrichedMessages && enrichedMessages !== messages && enrichedMessages.length > 0) {
418
+ messages.length = 0;
419
+ messages.push(...enrichedMessages);
420
+ }
421
+ else if (!enrichedMessages || enrichedMessages.length === 0) {
422
+ log.warn('Recitation returned empty/null messages, keeping original');
423
+ }
424
+ const contextTokens = messages.reduce((sum, m) => sum + (m.content?.length || 0) / 4, 0);
425
+ ctx.contextEngineering.updateRecitationFrequency(contextTokens);
426
+ }
427
+ // =======================================================================
428
+ // FAILURE CONTEXT INJECTION (Trick S)
429
+ // =======================================================================
430
+ if (ctx.contextEngineering) {
431
+ const failureContext = ctx.contextEngineering.getFailureContext(5);
432
+ if (failureContext) {
433
+ let lastUserIdx = -1;
434
+ for (let i = messages.length - 1; i >= 0; i--) {
435
+ if (messages[i].role === 'user') {
436
+ lastUserIdx = i;
437
+ break;
438
+ }
439
+ }
440
+ if (lastUserIdx > 0) {
441
+ messages.splice(lastUserIdx, 0, {
442
+ role: 'system',
443
+ content: failureContext,
444
+ });
445
+ }
446
+ }
447
+ }
448
+ // =======================================================================
449
+ // RESUME ORIENTATION — after compaction, nudge the agent to act, not re-summarize
450
+ // =======================================================================
451
+ const hasCompactionSummary = messages.some(m => m.role === 'system' && typeof m.content === 'string' && m.content.includes('[Conversation Summary'));
452
+ if (hasCompactionSummary && ctx.state.iteration <= 2) {
453
+ messages.push({
454
+ role: 'user',
455
+ content: `[System] Context was compacted. Review the summary above for what's been done and what remains. Do NOT repeat the summary — start working on the next task immediately using your tools.`,
456
+ });
457
+ }
458
+ // =======================================================================
459
+ // INJECTION BUDGET ANALYSIS (Phase 2 - monitoring mode)
460
+ // =======================================================================
461
+ if (ctx.injectionBudget) {
462
+ const proposals = [];
463
+ if (budgetInjectedPrompt) {
464
+ proposals.push({ name: 'budget_warning', priority: 0, maxTokens: 500, content: budgetInjectedPrompt });
465
+ }
466
+ if (ctx.contextEngineering) {
467
+ const failureCtx = ctx.contextEngineering.getFailureContext(5);
468
+ if (failureCtx) {
469
+ proposals.push({ name: 'failure_context', priority: 2, maxTokens: 300, content: failureCtx });
470
+ }
471
+ }
472
+ if (proposals.length > 0) {
473
+ const accepted = ctx.injectionBudget.allocate(proposals);
474
+ const stats = ctx.injectionBudget.getLastStats();
475
+ if (stats && stats.droppedNames.length > 0 && process.env.DEBUG) {
476
+ log.debug('Injection budget dropped items', { droppedNames: stats.droppedNames.join(', '), proposedTokens: stats.proposedTokens, acceptedTokens: stats.acceptedTokens });
477
+ }
478
+ if (stats && process.env.DEBUG_LLM) {
479
+ log.debug('Injection budget summary', { iteration: ctx.state.iteration, accepted: accepted.length, total: proposals.length, tokens: stats.acceptedTokens });
480
+ }
481
+ }
482
+ }
483
+ // =======================================================================
484
+ // RESILIENT LLM CALL
485
+ // =======================================================================
486
+ const resilienceConfig = typeof ctx.config.resilience === 'object'
487
+ ? ctx.config.resilience
488
+ : {};
489
+ const resilienceEnabled = isFeatureEnabled(ctx.config.resilience);
490
+ const MAX_EMPTY_RETRIES = resilienceConfig.maxEmptyRetries ?? 2;
491
+ const MAX_CONTINUATIONS = resilienceConfig.maxContinuations ?? 3;
492
+ const AUTO_CONTINUE = resilienceConfig.autoContinue ?? true;
493
+ const MIN_CONTENT_LENGTH = resilienceConfig.minContentLength ?? 1;
494
+ const INCOMPLETE_ACTION_RECOVERY = resilienceConfig.incompleteActionRecovery ?? true;
495
+ const MAX_INCOMPLETE_ACTION_RETRIES = resilienceConfig.maxIncompleteActionRetries ?? 2;
496
+ const ENFORCE_REQUESTED_ARTIFACTS = resilienceConfig.enforceRequestedArtifacts ?? true;
497
+ // PRE-FLIGHT BUDGET CHECK
498
+ if (ctx.economics && !forceTextOnly) {
499
+ const estimatedInputTokens = estimateContextTokens(messages);
500
+ const currentUsage = ctx.economics.getUsage();
501
+ const budget = ctx.economics.getBudget();
502
+ const isStrictEnforcement = (budget.enforcementMode ?? 'strict') === 'strict';
503
+ // Use proportional output estimate: 10% of remaining budget, capped at 4096, floored at 512.
504
+ // The old hardcoded 4096 caused premature wrapup for subagents with smaller budgets.
505
+ const remainingTokens = budget.maxTokens - currentUsage.tokens - estimatedInputTokens;
506
+ const estimatedOutputTokens = Math.min(4096, Math.max(512, Math.floor(remainingTokens * 0.1)));
507
+ const projectedTotal = currentUsage.tokens + estimatedInputTokens + estimatedOutputTokens;
508
+ if (projectedTotal > budget.maxTokens) {
509
+ ctx.observability?.logger?.warn('Pre-flight budget check: projected overshoot', {
510
+ currentTokens: currentUsage.tokens,
511
+ estimatedInput: estimatedInputTokens,
512
+ projectedTotal,
513
+ maxTokens: budget.maxTokens,
514
+ enforcementMode: budget.enforcementMode ?? 'strict',
515
+ });
516
+ // Only force text-only in strict mode. In doomloop_only mode,
517
+ // the pre-flight check warns but does not kill the agent.
518
+ // NEVER force text-only on the first iteration — an agent that hasn't
519
+ // made a single tool call yet should always get at least one chance.
520
+ // This prevents swarm workers from being killed before they can work.
521
+ if (isStrictEnforcement && ctx.state.iteration > 1) {
522
+ if (!budgetInjectedPrompt) {
523
+ messages.push({
524
+ role: 'user',
525
+ content: '[System] BUDGET CRITICAL: This is your LAST response. Summarize findings concisely and stop. Do NOT call tools.',
526
+ });
527
+ ctx.state.messages.push({
528
+ role: 'user',
529
+ content: '[System] BUDGET CRITICAL: This is your LAST response. Summarize findings concisely and stop. Do NOT call tools.',
530
+ });
531
+ }
532
+ forceTextOnly = true;
533
+ }
534
+ }
535
+ }
536
+ // EARLY EXIT: When forceTextOnly is set but task continuation is allowed,
537
+ // skip the expensive LLM call (whose tool calls would be discarded) and
538
+ // go directly to the task continuation gate. Only allowed once per
539
+ // forceTextOnly episode to prevent tight loops.
540
+ if (forceTextOnly && budgetAllowsTaskContinuation && ctx.taskManager
541
+ && !ctx.state._lastSkippedLLMIteration) {
542
+ const availableTasks = ctx.taskManager.getAvailableTasks();
543
+ if (availableTasks.length > 0) {
544
+ log.info('Skipping LLM call — forceTextOnly with tasks available, going to task continuation', {
545
+ availableTasks: availableTasks.length,
546
+ iteration: ctx.state.iteration,
547
+ });
548
+ // Mark that we skipped so we don't skip again on the next iteration
549
+ ctx.state._lastSkippedLLMIteration = ctx.state.iteration;
550
+ // Reset forceTextOnly for the next iteration so the task can run normally
551
+ forceTextOnly = false;
552
+ const nextTask = availableTasks[0];
553
+ ctx.taskManager.claim(nextTask.id, ctx.agentId);
554
+ const taskPrompt = {
555
+ role: 'user',
556
+ content: `[System] Budget warning noted. Continuing with next task:\n\n**Task ${nextTask.id}: ${nextTask.subject}**\n${nextTask.description}\n\nStart working on this task now using your tools.`,
557
+ };
558
+ messages.push(taskPrompt);
559
+ ctx.state.messages.push(taskPrompt);
560
+ ctx.emit({
561
+ type: 'iteration.after',
562
+ iteration: ctx.state.iteration,
563
+ hadToolCalls: false,
564
+ completionCandidate: false,
565
+ });
566
+ continue; // Re-enter main loop for next task without wasting an LLM call
567
+ }
568
+ }
569
+ let response = await callLLM(messages, ctx);
570
+ // Clear the LLM-skip guard now that we've made a real LLM call
571
+ delete ctx.state._lastSkippedLLMIteration;
572
+ let emptyRetries = 0;
573
+ let continuations = 0;
574
+ // Phase 1: Handle empty responses with retry
575
+ while (resilienceEnabled && emptyRetries < MAX_EMPTY_RETRIES) {
576
+ const hasContent = response.content && response.content.length >= MIN_CONTENT_LENGTH;
577
+ const hasToolCalls = response.toolCalls && response.toolCalls.length > 0;
578
+ const hasThinking = response.thinking && response.thinking.length > 0;
579
+ if (hasContent || hasToolCalls) {
580
+ if (emptyRetries > 0) {
581
+ ctx.emit({
582
+ type: 'resilience.recovered',
583
+ reason: 'empty_response',
584
+ attempts: emptyRetries,
585
+ });
586
+ ctx.observability?.logger?.info('Recovered from empty response', {
587
+ retries: emptyRetries,
588
+ });
589
+ }
590
+ break;
591
+ }
592
+ if (hasThinking && !hasContent && !hasToolCalls) {
593
+ if (emptyRetries === 0) {
594
+ emptyRetries++;
595
+ ctx.emit({
596
+ type: 'resilience.retry',
597
+ reason: 'thinking_only_response',
598
+ attempt: emptyRetries,
599
+ maxAttempts: MAX_EMPTY_RETRIES,
600
+ });
601
+ ctx.state.metrics.retryCount = (ctx.state.metrics.retryCount ?? 0) + 1;
602
+ ctx.observability?.logger?.warn('Thinking-only response (no visible content), nudging', {
603
+ thinkingLength: response.thinking.length,
604
+ });
605
+ const thinkingNudge = {
606
+ role: 'user',
607
+ content: '[System: You produced reasoning but no visible response. Please provide your answer based on your analysis.]',
608
+ };
609
+ messages.push(thinkingNudge);
610
+ ctx.state.messages.push(thinkingNudge);
611
+ response = await callLLM(messages, ctx);
612
+ continue;
613
+ }
614
+ ctx.observability?.logger?.info('Accepting thinking as content after nudge failed', {
615
+ thinkingLength: response.thinking.length,
616
+ });
617
+ response = { ...response, content: response.thinking };
618
+ break;
619
+ }
620
+ emptyRetries++;
621
+ ctx.emit({
622
+ type: 'resilience.retry',
623
+ reason: 'empty_response',
624
+ attempt: emptyRetries,
625
+ maxAttempts: MAX_EMPTY_RETRIES,
626
+ });
627
+ ctx.state.metrics.retryCount = (ctx.state.metrics.retryCount ?? 0) + 1;
628
+ ctx.observability?.logger?.warn('Empty LLM response, retrying', {
629
+ attempt: emptyRetries,
630
+ maxAttempts: MAX_EMPTY_RETRIES,
631
+ });
632
+ const nudgeMessage = {
633
+ role: 'user',
634
+ content: '[System: Your previous response was empty. Please provide a response or use a tool.]',
635
+ };
636
+ messages.push(nudgeMessage);
637
+ ctx.state.messages.push(nudgeMessage);
638
+ response = await callLLM(messages, ctx);
639
+ }
640
+ // Phase 2: Handle max_tokens truncation with continuation
641
+ if (resilienceEnabled && AUTO_CONTINUE && response.stopReason === 'max_tokens' && !response.toolCalls?.length) {
642
+ let accumulatedContent = response.content || '';
643
+ while (continuations < MAX_CONTINUATIONS && response.stopReason === 'max_tokens') {
644
+ continuations++;
645
+ ctx.emit({
646
+ type: 'resilience.continue',
647
+ reason: 'max_tokens',
648
+ continuation: continuations,
649
+ maxContinuations: MAX_CONTINUATIONS,
650
+ accumulatedLength: accumulatedContent.length,
651
+ });
652
+ ctx.observability?.logger?.info('Response truncated at max_tokens, continuing', {
653
+ continuation: continuations,
654
+ accumulatedLength: accumulatedContent.length,
655
+ });
656
+ const continuationMessage = {
657
+ role: 'assistant',
658
+ content: accumulatedContent,
659
+ };
660
+ const continueRequest = {
661
+ role: 'user',
662
+ content: '[System: Please continue from where you left off. Do not repeat what you already said.]',
663
+ };
664
+ messages.push(continuationMessage, continueRequest);
665
+ ctx.state.messages.push(continuationMessage, continueRequest);
666
+ response = await callLLM(messages, ctx);
667
+ if (response.content) {
668
+ accumulatedContent += response.content;
669
+ }
670
+ }
671
+ if (continuations > 0) {
672
+ response = { ...response, content: accumulatedContent };
673
+ ctx.emit({
674
+ type: 'resilience.completed',
675
+ reason: 'max_tokens_continuation',
676
+ continuations,
677
+ finalLength: accumulatedContent.length,
678
+ });
679
+ }
680
+ }
681
+ // Phase 2b: Handle truncated tool calls
682
+ if (resilienceEnabled && response.stopReason === 'max_tokens' && response.toolCalls?.length) {
683
+ ctx.emit({
684
+ type: 'resilience.truncated_tool_call',
685
+ toolNames: response.toolCalls.map(tc => tc.name),
686
+ });
687
+ ctx.observability?.logger?.warn('Tool call truncated at max_tokens', {
688
+ toolNames: response.toolCalls.map(tc => tc.name),
689
+ outputTokens: response.usage?.outputTokens,
690
+ });
691
+ const truncatedResponse = response;
692
+ response = { ...response, toolCalls: undefined };
693
+ const recoveryMessage = {
694
+ role: 'user',
695
+ content: '[System: Your previous tool call was truncated because the output exceeded the token limit. ' +
696
+ 'The tool call arguments were cut off and could not be parsed. ' +
697
+ 'Please retry with a smaller approach: for write_file, break the content into smaller chunks ' +
698
+ 'or use edit_file for targeted changes instead of rewriting entire files.]',
699
+ };
700
+ messages.push({ role: 'assistant', content: truncatedResponse.content || '' });
701
+ messages.push(recoveryMessage);
702
+ ctx.state.messages.push({ role: 'assistant', content: truncatedResponse.content || '' });
703
+ ctx.state.messages.push(recoveryMessage);
704
+ response = await callLLM(messages, ctx);
705
+ }
706
+ // Record LLM usage for economics
707
+ if (ctx.economics && response.usage) {
708
+ ctx.economics.recordLLMUsage(response.usage.inputTokens, response.usage.outputTokens, ctx.config.model, response.usage.cost, response.usage.cacheReadTokens);
709
+ // POST-LLM BUDGET CHECK
710
+ if (!forceTextOnly) {
711
+ const postCheck = ctx.economics.checkBudget();
712
+ if (!postCheck.canContinue) {
713
+ ctx.observability?.logger?.warn('Budget exceeded after LLM call, skipping tool execution', {
714
+ reason: postCheck.reason,
715
+ });
716
+ forceTextOnly = true;
717
+ }
718
+ }
719
+ }
720
+ // Add assistant message
721
+ const assistantMessage = {
722
+ role: 'assistant',
723
+ content: response.content,
724
+ toolCalls: response.toolCalls,
725
+ ...(response.thinking ? { metadata: { thinking: response.thinking } } : {}),
726
+ };
727
+ messages.push(assistantMessage);
728
+ ctx.state.messages.push(assistantMessage);
729
+ lastResponse = response.content || (response.thinking ? response.thinking : '');
730
+ // Plan mode: capture exploration findings
731
+ if (ctx.modeManager.getMode() === 'plan' && response.content && response.content.length > 50) {
732
+ const hasReadOnlyTools = response.toolCalls?.every(tc => ['read_file', 'list_files', 'glob', 'grep', 'search', 'mcp_'].some(prefix => tc.name.startsWith(prefix) || tc.name === prefix));
733
+ if (hasReadOnlyTools && !response.content.match(/^(Let me|I'll|I will|I need to|First,)/i)) {
734
+ ctx.pendingPlanManager.appendExplorationFinding(response.content.slice(0, 1000));
735
+ }
736
+ }
737
+ // Check for tool calls
738
+ const hasToolCalls = response.toolCalls && response.toolCalls.length > 0;
739
+ if (!hasToolCalls || forceTextOnly) {
740
+ if (forceTextOnly && hasToolCalls) {
741
+ ctx.observability?.logger?.info('Ignoring tool calls due to forceTextOnly (max steps reached)', {
742
+ toolCallCount: response.toolCalls?.length,
743
+ iteration: ctx.state.iteration,
744
+ });
745
+ }
746
+ // Track text-only turns for summary-loop detection (skip forceTextOnly — that's expected)
747
+ if (!hasToolCalls && !forceTextOnly) {
748
+ ctx.economics?.recordTextOnlyTurn();
749
+ }
750
+ const incompleteAction = detectIncompleteActionResponse(response.content || '');
751
+ const missingRequiredArtifact = ENFORCE_REQUESTED_ARTIFACTS
752
+ ? isRequestedArtifactMissing(requestedArtifact, executedToolNames)
753
+ : false;
754
+ const shouldRecoverIncompleteAction = resilienceEnabled
755
+ && INCOMPLETE_ACTION_RECOVERY
756
+ && !forceTextOnly
757
+ && (incompleteAction || missingRequiredArtifact);
758
+ if (shouldRecoverIncompleteAction) {
759
+ ctx.emit({
760
+ type: 'completion.before',
761
+ reason: missingRequiredArtifact && requestedArtifact
762
+ ? `missing_requested_artifact:${requestedArtifact}`
763
+ : 'future_intent_without_action',
764
+ attempt: incompleteActionRetries + 1,
765
+ maxAttempts: MAX_INCOMPLETE_ACTION_RETRIES,
766
+ });
767
+ if (incompleteActionRetries < MAX_INCOMPLETE_ACTION_RETRIES) {
768
+ incompleteActionRetries++;
769
+ const reason = missingRequiredArtifact && requestedArtifact
770
+ ? `missing_requested_artifact:${requestedArtifact}`
771
+ : 'future_intent_without_action';
772
+ ctx.emit({
773
+ type: 'recovery.before',
774
+ reason,
775
+ attempt: incompleteActionRetries,
776
+ maxAttempts: MAX_INCOMPLETE_ACTION_RETRIES,
777
+ });
778
+ ctx.emit({
779
+ type: 'resilience.incomplete_action_detected',
780
+ reason,
781
+ attempt: incompleteActionRetries,
782
+ maxAttempts: MAX_INCOMPLETE_ACTION_RETRIES,
783
+ requiresArtifact: missingRequiredArtifact,
784
+ });
785
+ ctx.observability?.logger?.warn('Incomplete action detected, retrying with nudge', {
786
+ reason,
787
+ attempt: incompleteActionRetries,
788
+ maxAttempts: MAX_INCOMPLETE_ACTION_RETRIES,
789
+ });
790
+ const nudgeMessage = {
791
+ role: 'user',
792
+ content: missingRequiredArtifact && requestedArtifact
793
+ ? `[System: You said you would complete the next action, but no tool call was made. The task requires creating or updating "${requestedArtifact}". Execute the required tool now, or explicitly explain why it cannot be produced.]`
794
+ : '[System: You described a next action but did not execute it. If work remains, call the required tool now. If the task is complete, provide a final answer with no pending action language.]',
795
+ };
796
+ messages.push(nudgeMessage);
797
+ ctx.state.messages.push(nudgeMessage);
798
+ ctx.emit({
799
+ type: 'iteration.after',
800
+ iteration: ctx.state.iteration,
801
+ hadToolCalls: false,
802
+ completionCandidate: false,
803
+ });
804
+ continue;
805
+ }
806
+ const failureReason = missingRequiredArtifact && requestedArtifact
807
+ ? `incomplete_action_missing_artifact:${requestedArtifact}`
808
+ : 'incomplete_action_unresolved';
809
+ ctx.emit({
810
+ type: 'resilience.incomplete_action_failed',
811
+ reason: failureReason,
812
+ attempts: incompleteActionRetries,
813
+ maxAttempts: MAX_INCOMPLETE_ACTION_RETRIES,
814
+ });
815
+ ctx.emit({
816
+ type: 'recovery.after',
817
+ reason: failureReason,
818
+ recovered: false,
819
+ attempts: incompleteActionRetries,
820
+ });
821
+ const reason = `LLM failed to complete requested action after ${incompleteActionRetries} retries (${failureReason})`;
822
+ result = {
823
+ success: false,
824
+ terminationReason: 'incomplete_action',
825
+ failureReason: reason,
826
+ };
827
+ ctx.emit({
828
+ type: 'completion.after',
829
+ success: false,
830
+ reason: 'incomplete_action',
831
+ details: reason,
832
+ });
833
+ throw new Error(reason);
834
+ }
835
+ if (incompleteActionRetries > 0) {
836
+ ctx.emit({
837
+ type: 'resilience.incomplete_action_recovered',
838
+ reason: 'incomplete_action',
839
+ attempts: incompleteActionRetries,
840
+ });
841
+ ctx.emit({
842
+ type: 'recovery.after',
843
+ reason: 'incomplete_action',
844
+ recovered: true,
845
+ attempts: incompleteActionRetries,
846
+ });
847
+ incompleteActionRetries = 0;
848
+ }
849
+ // TypeScript compilation gate — block completion if TS files edited and errors exist
850
+ if (ctx.typeCheckerState?.tsconfigDir
851
+ && !forceTextOnly
852
+ && (ctx.typeCheckerState.tsEditsSinceLastCheck > 0 || !ctx.typeCheckerState.hasRunOnce)) {
853
+ const tscResult = await runTypeCheck(ctx.typeCheckerState.tsconfigDir);
854
+ ctx.typeCheckerState.tsEditsSinceLastCheck = 0;
855
+ ctx.typeCheckerState.lastResult = tscResult;
856
+ ctx.typeCheckerState.hasRunOnce = true;
857
+ ctx.verificationGate?.recordCompilationResult(tscResult.success, tscResult.errorCount);
858
+ ctx.emit({ type: 'diagnostics.tsc-check', errorCount: tscResult.errorCount, duration: tscResult.duration, trigger: 'completion' });
859
+ if (!tscResult.success) {
860
+ const vState = ctx.verificationGate?.getState();
861
+ const maxCompNudges = 8;
862
+ if (!vState || (vState.compilationNudgeCount ?? 0) < maxCompNudges) {
863
+ const nudge = formatTypeCheckNudge(tscResult);
864
+ const nudgeMessage = { role: 'user', content: nudge };
865
+ messages.push(nudgeMessage);
866
+ ctx.state.messages.push(nudgeMessage);
867
+ ctx.verificationGate?.incrementCompilationNudge();
868
+ log.info('Compilation gate blocked completion', { count: tscResult.errorCount, nudgeCount: ctx.verificationGate?.getState().compilationNudgeCount });
869
+ ctx.emit({
870
+ type: 'iteration.after',
871
+ iteration: ctx.state.iteration,
872
+ hadToolCalls: false,
873
+ completionCandidate: false,
874
+ });
875
+ continue; // Re-enter main loop — agent must fix errors
876
+ }
877
+ // If exceeded max nudges, fall through to verification gate (which will forceAllow)
878
+ }
879
+ }
880
+ // Verification gate
881
+ if (ctx.verificationGate && !forceTextOnly) {
882
+ const vResult = ctx.verificationGate.check();
883
+ if (!vResult.satisfied && !vResult.forceAllow && vResult.nudge) {
884
+ const nudgeMessage = {
885
+ role: 'user',
886
+ content: vResult.nudge,
887
+ };
888
+ messages.push(nudgeMessage);
889
+ ctx.state.messages.push(nudgeMessage);
890
+ ctx.observability?.logger?.info('Verification gate nudge', {
891
+ missing: vResult.missing,
892
+ nudgeCount: ctx.verificationGate.getState().nudgeCount,
893
+ });
894
+ ctx.emit({
895
+ type: 'iteration.after',
896
+ iteration: ctx.state.iteration,
897
+ hadToolCalls: false,
898
+ completionCandidate: false,
899
+ });
900
+ continue;
901
+ }
902
+ }
903
+ // No tool calls — agent is done
904
+ compactToolOutputs(ctx.state.messages);
905
+ // Plan mode: capture exploration summary
906
+ if (ctx.modeManager.getMode() === 'plan' && ctx.pendingPlanManager.hasPendingPlan()) {
907
+ const explorationContent = response.content || '';
908
+ if (explorationContent.length > 0) {
909
+ ctx.pendingPlanManager.setExplorationSummary(explorationContent);
910
+ }
911
+ }
912
+ // Final validation
913
+ if (!response.content || response.content.length === 0) {
914
+ ctx.observability?.logger?.error('Agent finished with empty response after all retries', {
915
+ emptyRetries,
916
+ continuations,
917
+ iteration: ctx.state.iteration,
918
+ });
919
+ ctx.emit({
920
+ type: 'resilience.failed',
921
+ reason: 'empty_final_response',
922
+ emptyRetries,
923
+ continuations,
924
+ });
925
+ }
926
+ ctx.emit({
927
+ type: 'completion.after',
928
+ success: true,
929
+ reason: 'completed',
930
+ });
931
+ ctx.emit({
932
+ type: 'iteration.after',
933
+ iteration: ctx.state.iteration,
934
+ hadToolCalls: false,
935
+ completionCandidate: true,
936
+ });
937
+ // Record iteration end for tracing (no tool calls case)
938
+ ctx.traceCollector?.record({
939
+ type: 'iteration.end',
940
+ data: { iterationNumber: ctx.state.iteration },
941
+ });
942
+ // =====================================================================
943
+ // TASK EXECUTION LOOP — pick up next available task before exiting
944
+ // =====================================================================
945
+ if (ctx.taskManager) {
946
+ // Reconcile stale in-progress tasks before deciding there is no more work.
947
+ ctx.taskManager.reconcileStaleInProgress({
948
+ staleAfterMs: taskLeaseStaleMs,
949
+ reason: 'completion_gate',
950
+ });
951
+ const pendingWithOwner = getPendingWithOwnerCount(ctx);
952
+ const availableTasks = ctx.taskManager.getAvailableTasks();
953
+ if ((!forceTextOnly || budgetAllowsTaskContinuation) && availableTasks.length > 0) {
954
+ const nextTask = availableTasks[0];
955
+ ctx.taskManager.claim(nextTask.id, ctx.agentId);
956
+ log.info('Picking up next task from task list', {
957
+ taskId: nextTask.id,
958
+ subject: nextTask.subject,
959
+ });
960
+ const taskPrompt = {
961
+ role: 'user',
962
+ content: `[System] Previous work is done. Now work on the next task:\n\n**Task ${nextTask.id}: ${nextTask.subject}**\n${nextTask.description}\n\nStart working on this task now using your tools.`,
963
+ };
964
+ messages.push(taskPrompt);
965
+ ctx.state.messages.push(taskPrompt);
966
+ ctx.emit({
967
+ type: 'iteration.after',
968
+ iteration: ctx.state.iteration,
969
+ hadToolCalls: false,
970
+ completionCandidate: false,
971
+ });
972
+ continue; // Re-enter the main loop for the next task
973
+ }
974
+ const openTasks = getOpenTaskSummary(ctx);
975
+ if (openTasks && (openTasks.inProgress > 0 || openTasks.pending > 0)) {
976
+ if (forceTextOnly) {
977
+ const reason = `Task continuation suppressed by forceTextOnly mode: ${openTasks.pending} pending, ${openTasks.inProgress} in_progress`;
978
+ ctx.emit({
979
+ type: 'completion.blocked',
980
+ reasons: [reason],
981
+ openTasks,
982
+ diagnostics: {
983
+ forceTextOnly: true,
984
+ availableTasks: availableTasks.length,
985
+ pendingWithOwner,
986
+ },
987
+ });
988
+ result = {
989
+ success: false,
990
+ terminationReason: 'budget_limit',
991
+ failureReason: reason,
992
+ openTasks,
993
+ };
994
+ break;
995
+ }
996
+ const reasons = [
997
+ `Open tasks remain: ${openTasks.pending} pending, ${openTasks.inProgress} in_progress`,
998
+ openTasks.blocked > 0 ? `${openTasks.blocked} pending tasks are currently blocked` : '',
999
+ ].filter(Boolean);
1000
+ ctx.emit({
1001
+ type: 'completion.blocked',
1002
+ reasons,
1003
+ openTasks,
1004
+ diagnostics: {
1005
+ forceTextOnly: false,
1006
+ availableTasks: availableTasks.length,
1007
+ pendingWithOwner,
1008
+ },
1009
+ });
1010
+ result = {
1011
+ success: false,
1012
+ terminationReason: 'open_tasks',
1013
+ failureReason: reasons.join('; '),
1014
+ openTasks,
1015
+ };
1016
+ }
1017
+ }
1018
+ break;
1019
+ }
1020
+ // Execute tool calls
1021
+ const toolCalls = response.toolCalls;
1022
+ // SAFEGUARD: Hard cap on tool calls per LLM response
1023
+ const maxToolCallsPerResponse = ctx.economics?.getBudget()?.tuning?.maxToolCallsPerResponse ?? 25;
1024
+ if (toolCalls.length > maxToolCallsPerResponse) {
1025
+ log.warn('Tool call explosion detected — capping', {
1026
+ requested: toolCalls.length,
1027
+ cap: maxToolCallsPerResponse,
1028
+ toolNames: [...new Set(toolCalls.map(tc => tc.name))],
1029
+ });
1030
+ ctx.emit({
1031
+ type: 'safeguard.tool_call_cap',
1032
+ requested: toolCalls.length,
1033
+ cap: maxToolCallsPerResponse,
1034
+ droppedCount: toolCalls.length - maxToolCallsPerResponse,
1035
+ });
1036
+ toolCalls.splice(maxToolCallsPerResponse);
1037
+ }
1038
+ const toolResults = await executeToolCalls(toolCalls, ctx);
1039
+ ctx.emit({
1040
+ type: 'iteration.after',
1041
+ iteration: ctx.state.iteration,
1042
+ hadToolCalls: true,
1043
+ completionCandidate: false,
1044
+ });
1045
+ // Record tool calls for economics/progress tracking + work log
1046
+ for (let i = 0; i < toolCalls.length; i++) {
1047
+ const toolCall = toolCalls[i];
1048
+ const result = toolResults[i];
1049
+ executedToolNames.add(toolCall.name);
1050
+ ctx.economics?.recordToolCall(toolCall.name, toolCall.arguments, result?.result);
1051
+ ctx.stateMachine?.recordToolCall(toolCall.name, toolCall.arguments, result?.result);
1052
+ // Record in work log
1053
+ const toolOutput = result?.result && typeof result.result === 'object' && 'output' in result.result
1054
+ ? String(result.result.output)
1055
+ : typeof result?.result === 'string' ? result.result : undefined;
1056
+ ctx.workLog?.recordToolExecution(toolCall.name, toolCall.arguments, toolOutput);
1057
+ // Record in verification gate
1058
+ if (ctx.verificationGate) {
1059
+ if (toolCall.name === 'bash') {
1060
+ const toolRes = result?.result;
1061
+ const output = toolRes && typeof toolRes === 'object' && 'output' in toolRes
1062
+ ? String(toolRes.output)
1063
+ : typeof toolRes === 'string' ? toolRes : '';
1064
+ const exitCode = toolRes && typeof toolRes === 'object' && toolRes.metadata
1065
+ ? toolRes.metadata.exitCode ?? null
1066
+ : null;
1067
+ ctx.verificationGate.recordBashExecution(String(toolCall.arguments.command || ''), output, exitCode);
1068
+ }
1069
+ if (['write_file', 'edit_file'].includes(toolCall.name)) {
1070
+ ctx.verificationGate.recordFileChange();
1071
+ }
1072
+ }
1073
+ // Phase 5.1: Post-edit syntax validation + AST cache invalidation
1074
+ if (['write_file', 'edit_file'].includes(toolCall.name) && result?.result && result.result.success) {
1075
+ const filePath = String(toolCall.arguments.path || '');
1076
+ if (filePath) {
1077
+ // Invalidate stale AST cache entry so next analysis/validation reparses
1078
+ invalidateAST(filePath);
1079
+ try {
1080
+ const content = toolCall.name === 'write_file'
1081
+ ? String(toolCall.arguments.content || '')
1082
+ : await fs.promises.readFile(filePath, 'utf-8');
1083
+ // Update codebase context first — fullReparse caches the AST tree,
1084
+ // so validateSyntax below will use the cached tree (no double-parse)
1085
+ if (ctx.codebaseContext) {
1086
+ try {
1087
+ await ctx.codebaseContext.updateFile(filePath, content);
1088
+ }
1089
+ catch { /* non-blocking */ }
1090
+ }
1091
+ const validation = validateSyntax(content, filePath);
1092
+ if (!validation.valid && result.result && typeof result.result === 'object') {
1093
+ const errorSummary = validation.errors
1094
+ .slice(0, 3)
1095
+ .map(e => ` L${e.line}:${e.column}: ${e.message}`)
1096
+ .join('\n');
1097
+ result.result.output += `\n\n⚠ Syntax validation warning:\n${errorSummary}`;
1098
+ // Emit diagnostic events for each syntax error
1099
+ for (const err of validation.errors.slice(0, 5)) {
1100
+ ctx.emit({ type: 'diagnostics.syntax-error', file: filePath, line: err.line, message: err.message });
1101
+ }
1102
+ }
1103
+ }
1104
+ catch {
1105
+ // Validation failure is non-blocking
1106
+ }
1107
+ // Track .ts/.tsx edits for periodic type checking
1108
+ if (ctx.typeCheckerState?.tsconfigDir && /\.(ts|tsx)$/.test(filePath)) {
1109
+ ctx.typeCheckerState.tsEditsSinceLastCheck++;
1110
+ }
1111
+ }
1112
+ }
1113
+ }
1114
+ // Add tool results to messages (with truncation and proactive budget management)
1115
+ const MAX_TOOL_OUTPUT_CHARS = 8000;
1116
+ // PROACTIVE BUDGET CHECK
1117
+ const currentContextTokens = estimateContextTokens(messages);
1118
+ if (ctx.autoCompactionManager) {
1119
+ const compactionResult = await ctx.autoCompactionManager.checkAndMaybeCompact({
1120
+ currentTokens: currentContextTokens,
1121
+ messages: messages,
1122
+ });
1123
+ if (compactionResult.status === 'compacted' && compactionResult.compactedMessages) {
1124
+ if (!ctx.compactionPending) {
1125
+ mutators.setCompactionPending(true);
1126
+ const preCompactionMsg = {
1127
+ role: 'user',
1128
+ content: '[SYSTEM] Context compaction is imminent. Summarize your current progress, key findings, and next steps into a single concise message. This will be preserved after compaction.',
1129
+ };
1130
+ messages.push(preCompactionMsg);
1131
+ ctx.state.messages.push(preCompactionMsg);
1132
+ ctx.observability?.logger?.info('Pre-compaction agentic turn: injected summary request');
1133
+ }
1134
+ else {
1135
+ mutators.setCompactionPending(false);
1136
+ // Pre-compaction checkpoint
1137
+ // NOTE: autoCheckpoint is called via the agent's method, not directly here
1138
+ // The agent wires this through the mutators pattern
1139
+ // Replace messages with compacted version
1140
+ messages.length = 0;
1141
+ messages.push(...compactionResult.compactedMessages);
1142
+ ctx.state.messages.length = 0;
1143
+ ctx.state.messages.push(...compactionResult.compactedMessages);
1144
+ // Inject work log after compaction
1145
+ if (ctx.workLog?.hasContent()) {
1146
+ const workLogMessage = {
1147
+ role: 'user',
1148
+ content: ctx.workLog.toCompactString(),
1149
+ };
1150
+ messages.push(workLogMessage);
1151
+ ctx.state.messages.push(workLogMessage);
1152
+ }
1153
+ // Context recovery
1154
+ const recoveryParts = [];
1155
+ if (ctx.store) {
1156
+ const goalsSummary = ctx.store.getGoalsSummary();
1157
+ if (goalsSummary && goalsSummary !== 'No active goals.' && goalsSummary !== 'Goals feature not available.') {
1158
+ recoveryParts.push(goalsSummary);
1159
+ }
1160
+ }
1161
+ if (ctx.store) {
1162
+ const juncturesSummary = ctx.store.getJuncturesSummary(undefined, 5);
1163
+ if (juncturesSummary) {
1164
+ recoveryParts.push(juncturesSummary);
1165
+ }
1166
+ }
1167
+ if (ctx.learningStore) {
1168
+ const learnings = ctx.learningStore.getLearningContext({ maxLearnings: 3 });
1169
+ if (learnings) {
1170
+ recoveryParts.push(learnings);
1171
+ }
1172
+ }
1173
+ if (recoveryParts.length > 0) {
1174
+ const recoveryMessage = {
1175
+ role: 'user',
1176
+ content: `[CONTEXT RECOVERY — Re-injected after compaction]\n\n${recoveryParts.join('\n\n')}`,
1177
+ };
1178
+ messages.push(recoveryMessage);
1179
+ ctx.state.messages.push(recoveryMessage);
1180
+ }
1181
+ // Emit compaction event
1182
+ const compactionTokensAfter = estimateContextTokens(messages);
1183
+ const compactionRecoveryInjected = recoveryParts.length > 0;
1184
+ // Update baseline after compaction so incremental token
1185
+ // accounting reflects the reduced context size
1186
+ ctx.economics?.updateBaseline(compactionTokensAfter);
1187
+ const compactionEvent = {
1188
+ type: 'context.compacted',
1189
+ tokensBefore: currentContextTokens,
1190
+ tokensAfter: compactionTokensAfter,
1191
+ recoveryInjected: compactionRecoveryInjected,
1192
+ };
1193
+ ctx.emit(compactionEvent);
1194
+ if (ctx.traceCollector) {
1195
+ ctx.traceCollector.record({
1196
+ type: 'context.compacted',
1197
+ data: {
1198
+ tokensBefore: currentContextTokens,
1199
+ tokensAfter: compactionTokensAfter,
1200
+ recoveryInjected: compactionRecoveryInjected,
1201
+ },
1202
+ });
1203
+ }
1204
+ }
1205
+ }
1206
+ else if (compactionResult.status === 'hard_limit') {
1207
+ const reason = `Context hard limit reached (${Math.round(compactionResult.ratio * 100)}% of max tokens)`;
1208
+ ctx.emit({ type: 'error', error: reason });
1209
+ result = {
1210
+ success: false,
1211
+ terminationReason: 'hard_context_limit',
1212
+ failureReason: reason,
1213
+ };
1214
+ break;
1215
+ }
1216
+ }
1217
+ else if (ctx.economics) {
1218
+ // Fallback to simple compaction
1219
+ const currentUsage = ctx.economics.getUsage();
1220
+ const budget = ctx.economics.getBudget();
1221
+ const percentUsed = (currentUsage.tokens / budget.maxTokens) * 100;
1222
+ if (percentUsed >= 70) {
1223
+ ctx.observability?.logger?.info('Proactive compaction triggered', {
1224
+ percentUsed: Math.round(percentUsed),
1225
+ currentTokens: currentUsage.tokens,
1226
+ maxTokens: budget.maxTokens,
1227
+ });
1228
+ compactToolOutputs(ctx.state.messages);
1229
+ }
1230
+ }
1231
+ // SAFEGUARD: Aggregate context guard — prevent mass small results from overflowing
1232
+ if (ctx.economics && toolResults.length > 10) {
1233
+ const preAccumTokens = estimateContextTokens(messages);
1234
+ const budget = ctx.economics.getBudget();
1235
+ const availableTokens = budget.maxTokens * 0.90 - preAccumTokens;
1236
+ // Estimate total result tokens
1237
+ let totalResultTokens = 0;
1238
+ for (const r of toolResults) {
1239
+ const c = typeof r.result === 'string' ? r.result : stableStringify(r.result);
1240
+ totalResultTokens += Math.ceil(Math.min(c.length, MAX_TOOL_OUTPUT_CHARS) / 4);
1241
+ }
1242
+ if (totalResultTokens > availableTokens && availableTokens > 0) {
1243
+ log.warn('Tool results would exceed context budget — truncating batch', {
1244
+ resultCount: toolResults.length,
1245
+ estimatedTokens: totalResultTokens,
1246
+ availableTokens: Math.round(availableTokens),
1247
+ });
1248
+ let tokenBudget = availableTokens;
1249
+ for (let i = 0; i < toolResults.length; i++) {
1250
+ const c = typeof toolResults[i].result === 'string'
1251
+ ? toolResults[i].result
1252
+ : stableStringify(toolResults[i].result);
1253
+ const tokens = Math.ceil(Math.min(c.length, MAX_TOOL_OUTPUT_CHARS) / 4);
1254
+ if (tokens > tokenBudget) {
1255
+ const skipped = toolResults.length - i;
1256
+ for (let j = i; j < toolResults.length; j++) {
1257
+ toolResults[j] = {
1258
+ callId: toolResults[j].callId,
1259
+ result: `[Result omitted: context overflow guard — ${skipped} of ${toolResults.length} results skipped]`,
1260
+ };
1261
+ }
1262
+ ctx.emit({
1263
+ type: 'safeguard.context_overflow_guard',
1264
+ estimatedTokens: totalResultTokens,
1265
+ maxTokens: budget.maxTokens,
1266
+ toolResultsSkipped: skipped,
1267
+ });
1268
+ break;
1269
+ }
1270
+ tokenBudget -= tokens;
1271
+ }
1272
+ }
1273
+ }
1274
+ const toolCallNameById = new Map(toolCalls.map(tc => [tc.id, tc.name]));
1275
+ for (const result of toolResults) {
1276
+ let content = typeof result.result === 'string' ? result.result : stableStringify(result.result);
1277
+ const sourceToolName = toolCallNameById.get(result.callId);
1278
+ const isExpensiveResult = sourceToolName === 'spawn_agent' || sourceToolName === 'spawn_agents_parallel';
1279
+ const effectiveMaxChars = isExpensiveResult ? MAX_TOOL_OUTPUT_CHARS * 2 : MAX_TOOL_OUTPUT_CHARS;
1280
+ if (content.length > effectiveMaxChars) {
1281
+ content = content.slice(0, effectiveMaxChars) + `\n\n... [truncated ${content.length - effectiveMaxChars} chars]`;
1282
+ }
1283
+ // Check if adding this result would exceed budget
1284
+ if (ctx.economics) {
1285
+ const estimatedNewTokens = estimateTokenCount(content);
1286
+ const currentCtxTokens = estimateContextTokens(messages);
1287
+ const budget = ctx.economics.getBudget();
1288
+ if (currentCtxTokens + estimatedNewTokens > budget.maxTokens * 0.95) {
1289
+ ctx.observability?.logger?.warn('Skipping tool result to stay within budget', {
1290
+ toolCallId: result.callId,
1291
+ estimatedTokens: estimatedNewTokens,
1292
+ currentContext: currentCtxTokens,
1293
+ limit: budget.maxTokens,
1294
+ });
1295
+ const toolMessage = {
1296
+ role: 'tool',
1297
+ content: `[Result omitted to stay within token budget. Original size: ${content.length} chars]`,
1298
+ toolCallId: result.callId,
1299
+ };
1300
+ messages.push(toolMessage);
1301
+ ctx.state.messages.push(toolMessage);
1302
+ continue;
1303
+ }
1304
+ }
1305
+ const toolMessage = {
1306
+ role: 'tool',
1307
+ content,
1308
+ toolCallId: result.callId,
1309
+ ...(isExpensiveResult
1310
+ ? {
1311
+ metadata: {
1312
+ preserveFromCompaction: true,
1313
+ costToRegenerate: 'high',
1314
+ source: sourceToolName,
1315
+ },
1316
+ }
1317
+ : {}),
1318
+ };
1319
+ messages.push(toolMessage);
1320
+ ctx.state.messages.push(toolMessage);
1321
+ }
1322
+ // Periodic TypeScript compilation check (every 5 TS edits)
1323
+ const TYPE_CHECK_EDIT_THRESHOLD = 5;
1324
+ if (ctx.typeCheckerState?.tsconfigDir
1325
+ && ctx.typeCheckerState.tsEditsSinceLastCheck >= TYPE_CHECK_EDIT_THRESHOLD
1326
+ && !forceTextOnly) {
1327
+ const tscResult = await runTypeCheck(ctx.typeCheckerState.tsconfigDir);
1328
+ ctx.typeCheckerState.tsEditsSinceLastCheck = 0;
1329
+ ctx.typeCheckerState.lastResult = tscResult;
1330
+ ctx.typeCheckerState.hasRunOnce = true;
1331
+ ctx.verificationGate?.recordCompilationResult(tscResult.success, tscResult.errorCount);
1332
+ ctx.emit({ type: 'diagnostics.tsc-check', errorCount: tscResult.errorCount, duration: tscResult.duration, trigger: 'periodic' });
1333
+ if (!tscResult.success) {
1334
+ const nudge = formatTypeCheckNudge(tscResult);
1335
+ const infoMsg = { role: 'user', content: nudge };
1336
+ messages.push(infoMsg);
1337
+ ctx.state.messages.push(infoMsg);
1338
+ log.info('Periodic tsc check found errors', { count: tscResult.errorCount });
1339
+ }
1340
+ }
1341
+ // Emit context health
1342
+ const currentTokenEstimate = estimateContextTokens(messages);
1343
+ const contextLimit = ctx.getMaxContextTokens();
1344
+ const percentUsed = Math.round((currentTokenEstimate / contextLimit) * 100);
1345
+ const avgTokensPerExchange = currentTokenEstimate / Math.max(1, ctx.state.iteration);
1346
+ const remainingTokens = contextLimit - currentTokenEstimate;
1347
+ const estimatedExchanges = Math.floor(remainingTokens / Math.max(1, avgTokensPerExchange));
1348
+ ctx.emit({
1349
+ type: 'context.health',
1350
+ currentTokens: currentTokenEstimate,
1351
+ maxTokens: contextLimit,
1352
+ estimatedExchanges,
1353
+ percentUsed,
1354
+ });
1355
+ // Record iteration end
1356
+ ctx.traceCollector?.record({
1357
+ type: 'iteration.end',
1358
+ data: { iterationNumber: ctx.state.iteration },
1359
+ });
1360
+ }
1361
+ // =======================================================================
1362
+ // REFLECTION (Lesson 16)
1363
+ // =======================================================================
1364
+ if (!result.success) {
1365
+ break;
1366
+ }
1367
+ if (autoReflect && ctx.planning && reflectionAttempt < maxReflectionAttempts) {
1368
+ ctx.emit({ type: 'reflection', attempt: reflectionAttempt, satisfied: false });
1369
+ const reflectionResult = await ctx.planning.reflect(task, lastResponse, ctx.provider);
1370
+ ctx.state.metrics.reflectionAttempts = reflectionAttempt;
1371
+ if (reflectionResult.satisfied && reflectionResult.confidence >= confidenceThreshold) {
1372
+ ctx.emit({ type: 'reflection', attempt: reflectionAttempt, satisfied: true });
1373
+ break;
1374
+ }
1375
+ const feedbackMessage = {
1376
+ role: 'user',
1377
+ content: `[Reflection feedback]\nThe previous output needs improvement:\n- Critique: ${reflectionResult.critique}\n- Suggestions: ${reflectionResult.suggestions.join(', ')}\n\nPlease improve the output.`,
1378
+ };
1379
+ messages.push(feedbackMessage);
1380
+ ctx.state.messages.push(feedbackMessage);
1381
+ ctx.observability?.logger?.info('Reflection not satisfied, retrying', {
1382
+ attempt: reflectionAttempt,
1383
+ confidence: reflectionResult.confidence,
1384
+ critique: reflectionResult.critique,
1385
+ });
1386
+ }
1387
+ else {
1388
+ break;
1389
+ }
1390
+ }
1391
+ // Store conversation in memory
1392
+ ctx.memory?.storeConversation(ctx.state.messages);
1393
+ // Memory stats update (hook point)
1394
+ ctx.memory?.getStats();
1395
+ return result;
1396
+ }
1397
+ //# sourceMappingURL=execution-loop.js.map