attocode 0.2.5 → 0.2.6

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 (672) hide show
  1. package/CHANGELOG.md +33 -1
  2. package/dist/src/adapters.d.ts +37 -0
  3. package/dist/src/adapters.d.ts.map +1 -1
  4. package/dist/src/adapters.js +146 -19
  5. package/dist/src/adapters.js.map +1 -1
  6. package/dist/src/agent/agent-builder.d.ts.map +1 -1
  7. package/dist/src/agent/agent-builder.js.map +1 -1
  8. package/dist/src/agent/feature-initializer.d.ts +1 -1
  9. package/dist/src/agent/feature-initializer.d.ts.map +1 -1
  10. package/dist/src/agent/feature-initializer.js +40 -41
  11. package/dist/src/agent/feature-initializer.js.map +1 -1
  12. package/dist/src/agent/index.d.ts +2 -2
  13. package/dist/src/agent/index.d.ts.map +1 -1
  14. package/dist/src/agent/index.js +2 -2
  15. package/dist/src/agent/index.js.map +1 -1
  16. package/dist/src/agent/message-builder.d.ts.map +1 -1
  17. package/dist/src/agent/message-builder.js +8 -5
  18. package/dist/src/agent/message-builder.js.map +1 -1
  19. package/dist/src/agent/session-api.d.ts.map +1 -1
  20. package/dist/src/agent/session-api.js +3 -1
  21. package/dist/src/agent/session-api.js.map +1 -1
  22. package/dist/src/agent-tools/lsp-file-tools.d.ts.map +1 -1
  23. package/dist/src/agent-tools/lsp-file-tools.js +17 -13
  24. package/dist/src/agent-tools/lsp-file-tools.js.map +1 -1
  25. package/dist/src/agent.d.ts +12 -2
  26. package/dist/src/agent.d.ts.map +1 -1
  27. package/dist/src/agent.js +207 -76
  28. package/dist/src/agent.js.map +1 -1
  29. package/dist/src/analysis/feedback-loop.d.ts.map +1 -1
  30. package/dist/src/analysis/feedback-loop.js +13 -9
  31. package/dist/src/analysis/feedback-loop.js.map +1 -1
  32. package/dist/src/analysis/index.d.ts +1 -1
  33. package/dist/src/analysis/index.d.ts.map +1 -1
  34. package/dist/src/analysis/index.js +1 -1
  35. package/dist/src/analysis/index.js.map +1 -1
  36. package/dist/src/analysis/prompt-templates.d.ts.map +1 -1
  37. package/dist/src/analysis/prompt-templates.js.map +1 -1
  38. package/dist/src/analysis/trace-summary.d.ts.map +1 -1
  39. package/dist/src/analysis/trace-summary.js +25 -9
  40. package/dist/src/analysis/trace-summary.js.map +1 -1
  41. package/dist/src/cli.d.ts.map +1 -1
  42. package/dist/src/cli.js +3 -1
  43. package/dist/src/cli.js.map +1 -1
  44. package/dist/src/commands/agents-commands.d.ts.map +1 -1
  45. package/dist/src/commands/agents-commands.js +3 -3
  46. package/dist/src/commands/agents-commands.js.map +1 -1
  47. package/dist/src/commands/handler.d.ts.map +1 -1
  48. package/dist/src/commands/handler.js +60 -37
  49. package/dist/src/commands/handler.js.map +1 -1
  50. package/dist/src/commands/init-commands.d.ts.map +1 -1
  51. package/dist/src/commands/init-commands.js +8 -10
  52. package/dist/src/commands/init-commands.js.map +1 -1
  53. package/dist/src/commands/init.js +16 -16
  54. package/dist/src/commands/init.js.map +1 -1
  55. package/dist/src/commands/skills-commands.d.ts.map +1 -1
  56. package/dist/src/commands/skills-commands.js +10 -7
  57. package/dist/src/commands/skills-commands.js.map +1 -1
  58. package/dist/src/commands/types.d.ts.map +1 -1
  59. package/dist/src/config/config-manager.d.ts.map +1 -1
  60. package/dist/src/config/config-manager.js +4 -1
  61. package/dist/src/config/config-manager.js.map +1 -1
  62. package/dist/src/config/index.d.ts +1 -1
  63. package/dist/src/config/index.d.ts.map +1 -1
  64. package/dist/src/config/schema.d.ts.map +1 -1
  65. package/dist/src/config/schema.js +6 -2
  66. package/dist/src/config/schema.js.map +1 -1
  67. package/dist/src/core/agent-state-machine.d.ts.map +1 -1
  68. package/dist/src/core/agent-state-machine.js +5 -2
  69. package/dist/src/core/agent-state-machine.js.map +1 -1
  70. package/dist/src/core/completion-analyzer.d.ts.map +1 -1
  71. package/dist/src/core/completion-analyzer.js +2 -2
  72. package/dist/src/core/completion-analyzer.js.map +1 -1
  73. package/dist/src/core/execution-loop.d.ts +172 -1
  74. package/dist/src/core/execution-loop.d.ts.map +1 -1
  75. package/dist/src/core/execution-loop.js +481 -383
  76. package/dist/src/core/execution-loop.js.map +1 -1
  77. package/dist/src/core/index.d.ts +2 -2
  78. package/dist/src/core/index.d.ts.map +1 -1
  79. package/dist/src/core/index.js +1 -1
  80. package/dist/src/core/index.js.map +1 -1
  81. package/dist/src/core/queues/event-queue.d.ts.map +1 -1
  82. package/dist/src/core/queues/event-queue.js.map +1 -1
  83. package/dist/src/core/response-handler.d.ts.map +1 -1
  84. package/dist/src/core/response-handler.js +17 -8
  85. package/dist/src/core/response-handler.js.map +1 -1
  86. package/dist/src/core/subagent-spawner.d.ts.map +1 -1
  87. package/dist/src/core/subagent-spawner.js +85 -53
  88. package/dist/src/core/subagent-spawner.js.map +1 -1
  89. package/dist/src/core/tool-executor.d.ts.map +1 -1
  90. package/dist/src/core/tool-executor.js +56 -25
  91. package/dist/src/core/tool-executor.js.map +1 -1
  92. package/dist/src/core/types.d.ts.map +1 -1
  93. package/dist/src/core/types.js.map +1 -1
  94. package/dist/src/costs/model-registry.js +6 -6
  95. package/dist/src/costs/model-registry.js.map +1 -1
  96. package/dist/src/defaults.d.ts.map +1 -1
  97. package/dist/src/defaults.js +67 -20
  98. package/dist/src/defaults.js.map +1 -1
  99. package/dist/src/errors/index.d.ts.map +1 -1
  100. package/dist/src/errors/index.js +6 -8
  101. package/dist/src/errors/index.js.map +1 -1
  102. package/dist/src/first-run.d.ts.map +1 -1
  103. package/dist/src/first-run.js +11 -11
  104. package/dist/src/first-run.js.map +1 -1
  105. package/dist/src/integrations/agents/agent-registry.d.ts.map +1 -1
  106. package/dist/src/integrations/agents/agent-registry.js +16 -16
  107. package/dist/src/integrations/agents/agent-registry.js.map +1 -1
  108. package/dist/src/integrations/agents/async-subagent.d.ts.map +1 -1
  109. package/dist/src/integrations/agents/async-subagent.js +7 -9
  110. package/dist/src/integrations/agents/async-subagent.js.map +1 -1
  111. package/dist/src/integrations/agents/complexity-classifier.d.ts.map +1 -1
  112. package/dist/src/integrations/agents/complexity-classifier.js +46 -15
  113. package/dist/src/integrations/agents/complexity-classifier.js.map +1 -1
  114. package/dist/src/integrations/agents/delegation-protocol.d.ts.map +1 -1
  115. package/dist/src/integrations/agents/delegation-protocol.js +6 -6
  116. package/dist/src/integrations/agents/delegation-protocol.js.map +1 -1
  117. package/dist/src/integrations/agents/multi-agent.d.ts.map +1 -1
  118. package/dist/src/integrations/agents/multi-agent.js +10 -14
  119. package/dist/src/integrations/agents/multi-agent.js.map +1 -1
  120. package/dist/src/integrations/agents/result-synthesizer.d.ts.map +1 -1
  121. package/dist/src/integrations/agents/result-synthesizer.js +8 -6
  122. package/dist/src/integrations/agents/result-synthesizer.js.map +1 -1
  123. package/dist/src/integrations/agents/shared-blackboard.d.ts.map +1 -1
  124. package/dist/src/integrations/agents/shared-blackboard.js.map +1 -1
  125. package/dist/src/integrations/agents/subagent-output-store.d.ts.map +1 -1
  126. package/dist/src/integrations/agents/subagent-output-store.js +3 -4
  127. package/dist/src/integrations/agents/subagent-output-store.js.map +1 -1
  128. package/dist/src/integrations/budget/budget-pool.d.ts.map +1 -1
  129. package/dist/src/integrations/budget/budget-pool.js +4 -8
  130. package/dist/src/integrations/budget/budget-pool.js.map +1 -1
  131. package/dist/src/integrations/budget/cancellation.d.ts.map +1 -1
  132. package/dist/src/integrations/budget/cancellation.js +16 -2
  133. package/dist/src/integrations/budget/cancellation.js.map +1 -1
  134. package/dist/src/integrations/budget/dynamic-budget.d.ts.map +1 -1
  135. package/dist/src/integrations/budget/dynamic-budget.js +4 -6
  136. package/dist/src/integrations/budget/dynamic-budget.js.map +1 -1
  137. package/dist/src/integrations/budget/economics.d.ts.map +1 -1
  138. package/dist/src/integrations/budget/economics.js +51 -19
  139. package/dist/src/integrations/budget/economics.js.map +1 -1
  140. package/dist/src/integrations/budget/injection-budget.js +1 -1
  141. package/dist/src/integrations/budget/injection-budget.js.map +1 -1
  142. package/dist/src/integrations/budget/loop-detector.d.ts.map +1 -1
  143. package/dist/src/integrations/budget/loop-detector.js +23 -6
  144. package/dist/src/integrations/budget/loop-detector.js.map +1 -1
  145. package/dist/src/integrations/budget/phase-tracker.d.ts.map +1 -1
  146. package/dist/src/integrations/budget/phase-tracker.js +4 -1
  147. package/dist/src/integrations/budget/phase-tracker.js.map +1 -1
  148. package/dist/src/integrations/budget/resources.d.ts.map +1 -1
  149. package/dist/src/integrations/budget/resources.js +54 -10
  150. package/dist/src/integrations/budget/resources.js.map +1 -1
  151. package/dist/src/integrations/context/auto-compaction.d.ts.map +1 -1
  152. package/dist/src/integrations/context/auto-compaction.js +16 -8
  153. package/dist/src/integrations/context/auto-compaction.js.map +1 -1
  154. package/dist/src/integrations/context/code-analyzer.d.ts.map +1 -1
  155. package/dist/src/integrations/context/code-analyzer.js +17 -20
  156. package/dist/src/integrations/context/code-analyzer.js.map +1 -1
  157. package/dist/src/integrations/context/code-selector.d.ts.map +1 -1
  158. package/dist/src/integrations/context/code-selector.js +42 -23
  159. package/dist/src/integrations/context/code-selector.js.map +1 -1
  160. package/dist/src/integrations/context/codebase-ast.d.ts.map +1 -1
  161. package/dist/src/integrations/context/codebase-ast.js +121 -58
  162. package/dist/src/integrations/context/codebase-ast.js.map +1 -1
  163. package/dist/src/integrations/context/codebase-context.d.ts.map +1 -1
  164. package/dist/src/integrations/context/codebase-context.js +26 -17
  165. package/dist/src/integrations/context/codebase-context.js.map +1 -1
  166. package/dist/src/integrations/context/compaction.d.ts.map +1 -1
  167. package/dist/src/integrations/context/compaction.js +27 -20
  168. package/dist/src/integrations/context/compaction.js.map +1 -1
  169. package/dist/src/integrations/context/context-engineering.d.ts.map +1 -1
  170. package/dist/src/integrations/context/context-engineering.js.map +1 -1
  171. package/dist/src/integrations/context/semantic-cache.d.ts.map +1 -1
  172. package/dist/src/integrations/context/semantic-cache.js +6 -1
  173. package/dist/src/integrations/context/semantic-cache.js.map +1 -1
  174. package/dist/src/integrations/index.d.ts +2 -2
  175. package/dist/src/integrations/index.d.ts.map +1 -1
  176. package/dist/src/integrations/index.js +2 -2
  177. package/dist/src/integrations/index.js.map +1 -1
  178. package/dist/src/integrations/mcp/mcp-client.d.ts.map +1 -1
  179. package/dist/src/integrations/mcp/mcp-client.js +48 -27
  180. package/dist/src/integrations/mcp/mcp-client.js.map +1 -1
  181. package/dist/src/integrations/mcp/mcp-custom-tools.d.ts.map +1 -1
  182. package/dist/src/integrations/mcp/mcp-custom-tools.js +2 -2
  183. package/dist/src/integrations/mcp/mcp-custom-tools.js.map +1 -1
  184. package/dist/src/integrations/mcp/mcp-tool-search.d.ts.map +1 -1
  185. package/dist/src/integrations/mcp/mcp-tool-search.js +8 -8
  186. package/dist/src/integrations/mcp/mcp-tool-search.js.map +1 -1
  187. package/dist/src/integrations/mcp/mcp-tool-validator.d.ts.map +1 -1
  188. package/dist/src/integrations/mcp/mcp-tool-validator.js +5 -7
  189. package/dist/src/integrations/mcp/mcp-tool-validator.js.map +1 -1
  190. package/dist/src/integrations/persistence/codebase-repository.d.ts.map +1 -1
  191. package/dist/src/integrations/persistence/codebase-repository.js +6 -2
  192. package/dist/src/integrations/persistence/codebase-repository.js.map +1 -1
  193. package/dist/src/integrations/persistence/goal-repository.d.ts.map +1 -1
  194. package/dist/src/integrations/persistence/goal-repository.js +8 -5
  195. package/dist/src/integrations/persistence/goal-repository.js.map +1 -1
  196. package/dist/src/integrations/persistence/history.d.ts.map +1 -1
  197. package/dist/src/integrations/persistence/history.js +2 -4
  198. package/dist/src/integrations/persistence/history.js.map +1 -1
  199. package/dist/src/integrations/persistence/persistence.d.ts.map +1 -1
  200. package/dist/src/integrations/persistence/persistence.js +6 -3
  201. package/dist/src/integrations/persistence/persistence.js.map +1 -1
  202. package/dist/src/integrations/persistence/session-repository.d.ts.map +1 -1
  203. package/dist/src/integrations/persistence/session-repository.js +39 -28
  204. package/dist/src/integrations/persistence/session-repository.js.map +1 -1
  205. package/dist/src/integrations/persistence/session-store.d.ts.map +1 -1
  206. package/dist/src/integrations/persistence/session-store.js +4 -4
  207. package/dist/src/integrations/persistence/session-store.js.map +1 -1
  208. package/dist/src/integrations/persistence/sqlite-store.d.ts.map +1 -1
  209. package/dist/src/integrations/persistence/sqlite-store.js +6 -2
  210. package/dist/src/integrations/persistence/sqlite-store.js.map +1 -1
  211. package/dist/src/integrations/persistence/worker-repository.d.ts.map +1 -1
  212. package/dist/src/integrations/persistence/worker-repository.js +1 -3
  213. package/dist/src/integrations/persistence/worker-repository.js.map +1 -1
  214. package/dist/src/integrations/quality/auto-checkpoint.d.ts.map +1 -1
  215. package/dist/src/integrations/quality/auto-checkpoint.js +3 -5
  216. package/dist/src/integrations/quality/auto-checkpoint.js.map +1 -1
  217. package/dist/src/integrations/quality/dead-letter-queue.d.ts.map +1 -1
  218. package/dist/src/integrations/quality/dead-letter-queue.js +14 -8
  219. package/dist/src/integrations/quality/dead-letter-queue.js.map +1 -1
  220. package/dist/src/integrations/quality/health-check.d.ts.map +1 -1
  221. package/dist/src/integrations/quality/health-check.js +14 -11
  222. package/dist/src/integrations/quality/health-check.js.map +1 -1
  223. package/dist/src/integrations/quality/learning-store.d.ts.map +1 -1
  224. package/dist/src/integrations/quality/learning-store.js +108 -31
  225. package/dist/src/integrations/quality/learning-store.js.map +1 -1
  226. package/dist/src/integrations/quality/self-improvement.d.ts.map +1 -1
  227. package/dist/src/integrations/quality/self-improvement.js +1 -1
  228. package/dist/src/integrations/quality/self-improvement.js.map +1 -1
  229. package/dist/src/integrations/quality/tool-recommendation.d.ts.map +1 -1
  230. package/dist/src/integrations/quality/tool-recommendation.js +40 -10
  231. package/dist/src/integrations/quality/tool-recommendation.js.map +1 -1
  232. package/dist/src/integrations/safety/bash-policy.d.ts.map +1 -1
  233. package/dist/src/integrations/safety/bash-policy.js +8 -5
  234. package/dist/src/integrations/safety/bash-policy.js.map +1 -1
  235. package/dist/src/integrations/safety/execution-policy.d.ts.map +1 -1
  236. package/dist/src/integrations/safety/execution-policy.js +15 -5
  237. package/dist/src/integrations/safety/execution-policy.js.map +1 -1
  238. package/dist/src/integrations/safety/policy-engine.d.ts.map +1 -1
  239. package/dist/src/integrations/safety/policy-engine.js +51 -11
  240. package/dist/src/integrations/safety/policy-engine.js.map +1 -1
  241. package/dist/src/integrations/safety/safety.d.ts.map +1 -1
  242. package/dist/src/integrations/safety/safety.js +18 -15
  243. package/dist/src/integrations/safety/safety.js.map +1 -1
  244. package/dist/src/integrations/safety/sandbox/basic.d.ts.map +1 -1
  245. package/dist/src/integrations/safety/sandbox/basic.js +1 -3
  246. package/dist/src/integrations/safety/sandbox/basic.js.map +1 -1
  247. package/dist/src/integrations/safety/sandbox/docker.d.ts.map +1 -1
  248. package/dist/src/integrations/safety/sandbox/docker.js.map +1 -1
  249. package/dist/src/integrations/safety/sandbox/index.d.ts.map +1 -1
  250. package/dist/src/integrations/safety/sandbox/index.js +28 -4
  251. package/dist/src/integrations/safety/sandbox/index.js.map +1 -1
  252. package/dist/src/integrations/safety/sandbox/landlock.d.ts.map +1 -1
  253. package/dist/src/integrations/safety/sandbox/landlock.js +7 -3
  254. package/dist/src/integrations/safety/sandbox/landlock.js.map +1 -1
  255. package/dist/src/integrations/safety/sandbox/seatbelt.d.ts.map +1 -1
  256. package/dist/src/integrations/safety/sandbox/seatbelt.js +4 -11
  257. package/dist/src/integrations/safety/sandbox/seatbelt.js.map +1 -1
  258. package/dist/src/integrations/safety/type-checker.d.ts.map +1 -1
  259. package/dist/src/integrations/safety/type-checker.js +6 -2
  260. package/dist/src/integrations/safety/type-checker.js.map +1 -1
  261. package/dist/src/integrations/skills/skill-executor.d.ts.map +1 -1
  262. package/dist/src/integrations/skills/skill-executor.js +3 -7
  263. package/dist/src/integrations/skills/skill-executor.js.map +1 -1
  264. package/dist/src/integrations/skills/skills.d.ts.map +1 -1
  265. package/dist/src/integrations/skills/skills.js +24 -15
  266. package/dist/src/integrations/skills/skills.js.map +1 -1
  267. package/dist/src/integrations/streaming/pty-shell.d.ts.map +1 -1
  268. package/dist/src/integrations/streaming/pty-shell.js +5 -1
  269. package/dist/src/integrations/streaming/pty-shell.js.map +1 -1
  270. package/dist/src/integrations/streaming/streaming.d.ts.map +1 -1
  271. package/dist/src/integrations/streaming/streaming.js +7 -5
  272. package/dist/src/integrations/streaming/streaming.js.map +1 -1
  273. package/dist/src/integrations/swarm/failure-classifier.d.ts.map +1 -1
  274. package/dist/src/integrations/swarm/failure-classifier.js +18 -3
  275. package/dist/src/integrations/swarm/failure-classifier.js.map +1 -1
  276. package/dist/src/integrations/swarm/index.d.ts +5 -5
  277. package/dist/src/integrations/swarm/index.d.ts.map +1 -1
  278. package/dist/src/integrations/swarm/index.js +4 -4
  279. package/dist/src/integrations/swarm/index.js.map +1 -1
  280. package/dist/src/integrations/swarm/model-selector.d.ts.map +1 -1
  281. package/dist/src/integrations/swarm/model-selector.js +20 -23
  282. package/dist/src/integrations/swarm/model-selector.js.map +1 -1
  283. package/dist/src/integrations/swarm/request-throttle.d.ts.map +1 -1
  284. package/dist/src/integrations/swarm/request-throttle.js +7 -4
  285. package/dist/src/integrations/swarm/request-throttle.js.map +1 -1
  286. package/dist/src/integrations/swarm/swarm-budget.d.ts.map +1 -1
  287. package/dist/src/integrations/swarm/swarm-budget.js +1 -1
  288. package/dist/src/integrations/swarm/swarm-budget.js.map +1 -1
  289. package/dist/src/integrations/swarm/swarm-config-loader.d.ts.map +1 -1
  290. package/dist/src/integrations/swarm/swarm-config-loader.js +46 -17
  291. package/dist/src/integrations/swarm/swarm-config-loader.js.map +1 -1
  292. package/dist/src/integrations/swarm/swarm-event-bridge.d.ts.map +1 -1
  293. package/dist/src/integrations/swarm/swarm-event-bridge.js +69 -23
  294. package/dist/src/integrations/swarm/swarm-event-bridge.js.map +1 -1
  295. package/dist/src/integrations/swarm/swarm-events.d.ts.map +1 -1
  296. package/dist/src/integrations/swarm/swarm-events.js +1 -1
  297. package/dist/src/integrations/swarm/swarm-events.js.map +1 -1
  298. package/dist/src/integrations/swarm/swarm-execution.d.ts.map +1 -1
  299. package/dist/src/integrations/swarm/swarm-execution.js +96 -46
  300. package/dist/src/integrations/swarm/swarm-execution.js.map +1 -1
  301. package/dist/src/integrations/swarm/swarm-helpers.d.ts.map +1 -1
  302. package/dist/src/integrations/swarm/swarm-helpers.js +25 -12
  303. package/dist/src/integrations/swarm/swarm-helpers.js.map +1 -1
  304. package/dist/src/integrations/swarm/swarm-lifecycle.d.ts.map +1 -1
  305. package/dist/src/integrations/swarm/swarm-lifecycle.js +102 -47
  306. package/dist/src/integrations/swarm/swarm-lifecycle.js.map +1 -1
  307. package/dist/src/integrations/swarm/swarm-orchestrator.d.ts +1 -1
  308. package/dist/src/integrations/swarm/swarm-orchestrator.d.ts.map +1 -1
  309. package/dist/src/integrations/swarm/swarm-orchestrator.js +97 -39
  310. package/dist/src/integrations/swarm/swarm-orchestrator.js.map +1 -1
  311. package/dist/src/integrations/swarm/swarm-quality-gate.d.ts.map +1 -1
  312. package/dist/src/integrations/swarm/swarm-quality-gate.js +18 -14
  313. package/dist/src/integrations/swarm/swarm-quality-gate.js.map +1 -1
  314. package/dist/src/integrations/swarm/swarm-recovery.d.ts.map +1 -1
  315. package/dist/src/integrations/swarm/swarm-recovery.js +42 -29
  316. package/dist/src/integrations/swarm/swarm-recovery.js.map +1 -1
  317. package/dist/src/integrations/swarm/swarm-state-store.d.ts.map +1 -1
  318. package/dist/src/integrations/swarm/swarm-state-store.js +4 -2
  319. package/dist/src/integrations/swarm/swarm-state-store.js.map +1 -1
  320. package/dist/src/integrations/swarm/task-queue.d.ts +7 -1
  321. package/dist/src/integrations/swarm/task-queue.d.ts.map +1 -1
  322. package/dist/src/integrations/swarm/task-queue.js +32 -25
  323. package/dist/src/integrations/swarm/task-queue.js.map +1 -1
  324. package/dist/src/integrations/swarm/types.d.ts.map +1 -1
  325. package/dist/src/integrations/swarm/types.js +89 -12
  326. package/dist/src/integrations/swarm/types.js.map +1 -1
  327. package/dist/src/integrations/swarm/worker-pool.d.ts.map +1 -1
  328. package/dist/src/integrations/swarm/worker-pool.js +32 -24
  329. package/dist/src/integrations/swarm/worker-pool.js.map +1 -1
  330. package/dist/src/integrations/tasks/dependency-analyzer.d.ts.map +1 -1
  331. package/dist/src/integrations/tasks/dependency-analyzer.js +1 -2
  332. package/dist/src/integrations/tasks/dependency-analyzer.js.map +1 -1
  333. package/dist/src/integrations/tasks/interactive-planning.d.ts.map +1 -1
  334. package/dist/src/integrations/tasks/interactive-planning.js +2 -9
  335. package/dist/src/integrations/tasks/interactive-planning.js.map +1 -1
  336. package/dist/src/integrations/tasks/pending-plan.d.ts.map +1 -1
  337. package/dist/src/integrations/tasks/pending-plan.js +16 -16
  338. package/dist/src/integrations/tasks/pending-plan.js.map +1 -1
  339. package/dist/src/integrations/tasks/planning.d.ts.map +1 -1
  340. package/dist/src/integrations/tasks/planning.js +42 -23
  341. package/dist/src/integrations/tasks/planning.js.map +1 -1
  342. package/dist/src/integrations/tasks/smart-decomposer.d.ts.map +1 -1
  343. package/dist/src/integrations/tasks/smart-decomposer.js +17 -10
  344. package/dist/src/integrations/tasks/smart-decomposer.js.map +1 -1
  345. package/dist/src/integrations/tasks/task-manager.d.ts.map +1 -1
  346. package/dist/src/integrations/tasks/task-manager.js +25 -18
  347. package/dist/src/integrations/tasks/task-manager.js.map +1 -1
  348. package/dist/src/integrations/tasks/task-splitter.d.ts.map +1 -1
  349. package/dist/src/integrations/tasks/task-splitter.js +21 -16
  350. package/dist/src/integrations/tasks/task-splitter.js.map +1 -1
  351. package/dist/src/integrations/tasks/verification-gate.d.ts.map +1 -1
  352. package/dist/src/integrations/tasks/verification-gate.js +4 -2
  353. package/dist/src/integrations/tasks/verification-gate.js.map +1 -1
  354. package/dist/src/integrations/tasks/work-log.d.ts.map +1 -1
  355. package/dist/src/integrations/tasks/work-log.js +22 -10
  356. package/dist/src/integrations/tasks/work-log.js.map +1 -1
  357. package/dist/src/integrations/utilities/capabilities.d.ts.map +1 -1
  358. package/dist/src/integrations/utilities/capabilities.js +46 -8
  359. package/dist/src/integrations/utilities/capabilities.js.map +1 -1
  360. package/dist/src/integrations/utilities/diff-utils.d.ts.map +1 -1
  361. package/dist/src/integrations/utilities/diff-utils.js +6 -7
  362. package/dist/src/integrations/utilities/diff-utils.js.map +1 -1
  363. package/dist/src/integrations/utilities/environment-facts.d.ts.map +1 -1
  364. package/dist/src/integrations/utilities/environment-facts.js +12 -2
  365. package/dist/src/integrations/utilities/environment-facts.js.map +1 -1
  366. package/dist/src/integrations/utilities/file-change-tracker.d.ts.map +1 -1
  367. package/dist/src/integrations/utilities/file-change-tracker.js +7 -8
  368. package/dist/src/integrations/utilities/file-change-tracker.js.map +1 -1
  369. package/dist/src/integrations/utilities/graph-visualization.d.ts.map +1 -1
  370. package/dist/src/integrations/utilities/graph-visualization.js +8 -6
  371. package/dist/src/integrations/utilities/graph-visualization.js.map +1 -1
  372. package/dist/src/integrations/utilities/hierarchical-config.d.ts.map +1 -1
  373. package/dist/src/integrations/utilities/hierarchical-config.js +5 -1
  374. package/dist/src/integrations/utilities/hierarchical-config.js.map +1 -1
  375. package/dist/src/integrations/utilities/hooks.d.ts.map +1 -1
  376. package/dist/src/integrations/utilities/hooks.js +3 -3
  377. package/dist/src/integrations/utilities/hooks.js.map +1 -1
  378. package/dist/src/integrations/utilities/ignore.js +1 -1
  379. package/dist/src/integrations/utilities/ignore.js.map +1 -1
  380. package/dist/src/integrations/utilities/image-renderer.d.ts.map +1 -1
  381. package/dist/src/integrations/utilities/image-renderer.js +4 -9
  382. package/dist/src/integrations/utilities/image-renderer.js.map +1 -1
  383. package/dist/src/integrations/utilities/logger.d.ts.map +1 -1
  384. package/dist/src/integrations/utilities/logger.js +1 -3
  385. package/dist/src/integrations/utilities/logger.js.map +1 -1
  386. package/dist/src/integrations/utilities/memory.d.ts.map +1 -1
  387. package/dist/src/integrations/utilities/memory.js +1 -3
  388. package/dist/src/integrations/utilities/memory.js.map +1 -1
  389. package/dist/src/integrations/utilities/observability.d.ts.map +1 -1
  390. package/dist/src/integrations/utilities/observability.js +2 -1
  391. package/dist/src/integrations/utilities/observability.js.map +1 -1
  392. package/dist/src/integrations/utilities/openrouter-pricing.d.ts.map +1 -1
  393. package/dist/src/integrations/utilities/openrouter-pricing.js +3 -3
  394. package/dist/src/integrations/utilities/openrouter-pricing.js.map +1 -1
  395. package/dist/src/integrations/utilities/react.d.ts.map +1 -1
  396. package/dist/src/integrations/utilities/react.js +5 -9
  397. package/dist/src/integrations/utilities/react.js.map +1 -1
  398. package/dist/src/integrations/utilities/retry.d.ts.map +1 -1
  399. package/dist/src/integrations/utilities/retry.js +1 -1
  400. package/dist/src/integrations/utilities/retry.js.map +1 -1
  401. package/dist/src/integrations/utilities/routing.d.ts.map +1 -1
  402. package/dist/src/integrations/utilities/routing.js +16 -4
  403. package/dist/src/integrations/utilities/routing.js.map +1 -1
  404. package/dist/src/integrations/utilities/rules.d.ts.map +1 -1
  405. package/dist/src/integrations/utilities/rules.js +4 -6
  406. package/dist/src/integrations/utilities/rules.js.map +1 -1
  407. package/dist/src/integrations/utilities/sourcegraph.d.ts.map +1 -1
  408. package/dist/src/integrations/utilities/sourcegraph.js +3 -5
  409. package/dist/src/integrations/utilities/sourcegraph.js.map +1 -1
  410. package/dist/src/integrations/utilities/thinking-strategy.d.ts.map +1 -1
  411. package/dist/src/integrations/utilities/thinking-strategy.js.map +1 -1
  412. package/dist/src/integrations/utilities/thread-manager.d.ts.map +1 -1
  413. package/dist/src/integrations/utilities/thread-manager.js +8 -6
  414. package/dist/src/integrations/utilities/thread-manager.js.map +1 -1
  415. package/dist/src/integrations/utilities/token-estimate.d.ts +5 -0
  416. package/dist/src/integrations/utilities/token-estimate.d.ts.map +1 -1
  417. package/dist/src/integrations/utilities/token-estimate.js +7 -1
  418. package/dist/src/integrations/utilities/token-estimate.js.map +1 -1
  419. package/dist/src/main.js +41 -24
  420. package/dist/src/main.js.map +1 -1
  421. package/dist/src/modes/repl.d.ts.map +1 -1
  422. package/dist/src/modes/repl.js +51 -17
  423. package/dist/src/modes/repl.js.map +1 -1
  424. package/dist/src/modes/tui.d.ts.map +1 -1
  425. package/dist/src/modes/tui.js +70 -10
  426. package/dist/src/modes/tui.js.map +1 -1
  427. package/dist/src/modes.d.ts.map +1 -1
  428. package/dist/src/modes.js +13 -13
  429. package/dist/src/modes.js.map +1 -1
  430. package/dist/src/observability/tracer.d.ts.map +1 -1
  431. package/dist/src/observability/tracer.js +7 -3
  432. package/dist/src/observability/tracer.js.map +1 -1
  433. package/dist/src/observability/types.d.ts.map +1 -1
  434. package/dist/src/observability/types.js.map +1 -1
  435. package/dist/src/paths.d.ts.map +1 -1
  436. package/dist/src/paths.js +2 -6
  437. package/dist/src/paths.js.map +1 -1
  438. package/dist/src/persistence/migrator.d.ts.map +1 -1
  439. package/dist/src/persistence/migrator.js +7 -7
  440. package/dist/src/persistence/migrator.js.map +1 -1
  441. package/dist/src/providers/adapters/anthropic.d.ts.map +1 -1
  442. package/dist/src/providers/adapters/anthropic.js +50 -38
  443. package/dist/src/providers/adapters/anthropic.js.map +1 -1
  444. package/dist/src/providers/adapters/azure.d.ts.map +1 -1
  445. package/dist/src/providers/adapters/azure.js +31 -16
  446. package/dist/src/providers/adapters/azure.js.map +1 -1
  447. package/dist/src/providers/adapters/mock.d.ts.map +1 -1
  448. package/dist/src/providers/adapters/mock.js +9 -9
  449. package/dist/src/providers/adapters/mock.js.map +1 -1
  450. package/dist/src/providers/adapters/openai.d.ts.map +1 -1
  451. package/dist/src/providers/adapters/openai.js +22 -15
  452. package/dist/src/providers/adapters/openai.js.map +1 -1
  453. package/dist/src/providers/adapters/openrouter.d.ts.map +1 -1
  454. package/dist/src/providers/adapters/openrouter.js +60 -33
  455. package/dist/src/providers/adapters/openrouter.js.map +1 -1
  456. package/dist/src/providers/circuit-breaker.d.ts.map +1 -1
  457. package/dist/src/providers/circuit-breaker.js +4 -3
  458. package/dist/src/providers/circuit-breaker.js.map +1 -1
  459. package/dist/src/providers/fallback-chain.d.ts.map +1 -1
  460. package/dist/src/providers/fallback-chain.js +3 -3
  461. package/dist/src/providers/fallback-chain.js.map +1 -1
  462. package/dist/src/providers/llm-resilience.d.ts.map +1 -1
  463. package/dist/src/providers/llm-resilience.js +2 -2
  464. package/dist/src/providers/llm-resilience.js.map +1 -1
  465. package/dist/src/providers/provider.d.ts.map +1 -1
  466. package/dist/src/providers/provider.js +1 -2
  467. package/dist/src/providers/provider.js.map +1 -1
  468. package/dist/src/providers/resilient-fetch.d.ts.map +1 -1
  469. package/dist/src/providers/resilient-fetch.js +3 -4
  470. package/dist/src/providers/resilient-fetch.js.map +1 -1
  471. package/dist/src/providers/resilient-provider.d.ts.map +1 -1
  472. package/dist/src/providers/resilient-provider.js +8 -5
  473. package/dist/src/providers/resilient-provider.js.map +1 -1
  474. package/dist/src/session-picker.d.ts.map +1 -1
  475. package/dist/src/session-picker.js +9 -5
  476. package/dist/src/session-picker.js.map +1 -1
  477. package/dist/src/shared/budget-tracker.d.ts.map +1 -1
  478. package/dist/src/shared/budget-tracker.js +1 -1
  479. package/dist/src/shared/budget-tracker.js.map +1 -1
  480. package/dist/src/shared/context-engine.d.ts.map +1 -1
  481. package/dist/src/shared/context-engine.js +1 -1
  482. package/dist/src/shared/context-engine.js.map +1 -1
  483. package/dist/src/shared/persistence.d.ts.map +1 -1
  484. package/dist/src/shared/persistence.js +2 -6
  485. package/dist/src/shared/persistence.js.map +1 -1
  486. package/dist/src/shared/shared-context-state.d.ts.map +1 -1
  487. package/dist/src/shared/shared-context-state.js.map +1 -1
  488. package/dist/src/shared/shared-economics-state.d.ts.map +1 -1
  489. package/dist/src/shared/shared-economics-state.js.map +1 -1
  490. package/dist/src/tools/agent.d.ts +1 -1
  491. package/dist/src/tools/agent.d.ts.map +1 -1
  492. package/dist/src/tools/agent.js +10 -7
  493. package/dist/src/tools/agent.js.map +1 -1
  494. package/dist/src/tools/bash.d.ts.map +1 -1
  495. package/dist/src/tools/bash.js.map +1 -1
  496. package/dist/src/tools/coercion.js +1 -1
  497. package/dist/src/tools/coercion.js.map +1 -1
  498. package/dist/src/tools/file.d.ts.map +1 -1
  499. package/dist/src/tools/file.js +1 -1
  500. package/dist/src/tools/file.js.map +1 -1
  501. package/dist/src/tools/permission.js +5 -6
  502. package/dist/src/tools/permission.js.map +1 -1
  503. package/dist/src/tools/registry.d.ts.map +1 -1
  504. package/dist/src/tools/registry.js +3 -5
  505. package/dist/src/tools/registry.js.map +1 -1
  506. package/dist/src/tools/standard.d.ts.map +1 -1
  507. package/dist/src/tools/standard.js +1 -3
  508. package/dist/src/tools/standard.js.map +1 -1
  509. package/dist/src/tools/tasks.d.ts.map +1 -1
  510. package/dist/src/tools/tasks.js +4 -4
  511. package/dist/src/tools/tasks.js.map +1 -1
  512. package/dist/src/tools/types.d.ts.map +1 -1
  513. package/dist/src/tools/types.js +5 -1
  514. package/dist/src/tools/types.js.map +1 -1
  515. package/dist/src/tools/undo.d.ts.map +1 -1
  516. package/dist/src/tools/undo.js +4 -2
  517. package/dist/src/tools/undo.js.map +1 -1
  518. package/dist/src/tracing/cache-boundary-tracker.d.ts.map +1 -1
  519. package/dist/src/tracing/cache-boundary-tracker.js +7 -11
  520. package/dist/src/tracing/cache-boundary-tracker.js.map +1 -1
  521. package/dist/src/tracing/trace-collector.d.ts.map +1 -1
  522. package/dist/src/tracing/trace-collector.js +28 -28
  523. package/dist/src/tracing/trace-collector.js.map +1 -1
  524. package/dist/src/tracing/types.d.ts.map +1 -1
  525. package/dist/src/tracing/types.js.map +1 -1
  526. package/dist/src/tricks/failure-evidence.d.ts.map +1 -1
  527. package/dist/src/tricks/failure-evidence.js +16 -26
  528. package/dist/src/tricks/failure-evidence.js.map +1 -1
  529. package/dist/src/tricks/json-utils.d.ts.map +1 -1
  530. package/dist/src/tricks/json-utils.js +1 -4
  531. package/dist/src/tricks/json-utils.js.map +1 -1
  532. package/dist/src/tricks/kv-cache-context.d.ts.map +1 -1
  533. package/dist/src/tricks/kv-cache-context.js +2 -3
  534. package/dist/src/tricks/kv-cache-context.js.map +1 -1
  535. package/dist/src/tricks/recitation.d.ts.map +1 -1
  536. package/dist/src/tricks/recitation.js +22 -18
  537. package/dist/src/tricks/recitation.js.map +1 -1
  538. package/dist/src/tricks/recursive-context.d.ts.map +1 -1
  539. package/dist/src/tricks/recursive-context.js +8 -5
  540. package/dist/src/tricks/recursive-context.js.map +1 -1
  541. package/dist/src/tricks/reversible-compaction.d.ts.map +1 -1
  542. package/dist/src/tricks/reversible-compaction.js +11 -7
  543. package/dist/src/tricks/reversible-compaction.js.map +1 -1
  544. package/dist/src/tricks/serialization-diversity.d.ts.map +1 -1
  545. package/dist/src/tricks/serialization-diversity.js +12 -12
  546. package/dist/src/tricks/serialization-diversity.js.map +1 -1
  547. package/dist/src/tui/app.d.ts +6 -2
  548. package/dist/src/tui/app.d.ts.map +1 -1
  549. package/dist/src/tui/app.js +636 -583
  550. package/dist/src/tui/app.js.map +1 -1
  551. package/dist/src/tui/components/ActiveAgentsPanel.d.ts +2 -0
  552. package/dist/src/tui/components/ActiveAgentsPanel.d.ts.map +1 -1
  553. package/dist/src/tui/components/ActiveAgentsPanel.js +5 -5
  554. package/dist/src/tui/components/ActiveAgentsPanel.js.map +1 -1
  555. package/dist/src/tui/components/ApprovalDialog.d.ts.map +1 -1
  556. package/dist/src/tui/components/ApprovalDialog.js +14 -0
  557. package/dist/src/tui/components/ApprovalDialog.js.map +1 -1
  558. package/dist/src/tui/components/BudgetExtensionDialog.d.ts +18 -0
  559. package/dist/src/tui/components/BudgetExtensionDialog.d.ts.map +1 -0
  560. package/dist/src/tui/components/BudgetExtensionDialog.js +40 -0
  561. package/dist/src/tui/components/BudgetExtensionDialog.js.map +1 -0
  562. package/dist/src/tui/components/CollapsibleDiffView.d.ts.map +1 -1
  563. package/dist/src/tui/components/CollapsibleDiffView.js +18 -13
  564. package/dist/src/tui/components/CollapsibleDiffView.js.map +1 -1
  565. package/dist/src/tui/components/DebugPanel.d.ts.map +1 -1
  566. package/dist/src/tui/components/DebugPanel.js +46 -26
  567. package/dist/src/tui/components/DebugPanel.js.map +1 -1
  568. package/dist/src/tui/components/DiagnosticsPanel.d.ts.map +1 -1
  569. package/dist/src/tui/components/DiagnosticsPanel.js +18 -2
  570. package/dist/src/tui/components/DiagnosticsPanel.js.map +1 -1
  571. package/dist/src/tui/components/DiffView.d.ts.map +1 -1
  572. package/dist/src/tui/components/DiffView.js +21 -14
  573. package/dist/src/tui/components/DiffView.js.map +1 -1
  574. package/dist/src/tui/components/ErrorBoundary.d.ts.map +1 -1
  575. package/dist/src/tui/components/ErrorBoundary.js +7 -2
  576. package/dist/src/tui/components/ErrorBoundary.js.map +1 -1
  577. package/dist/src/tui/components/ErrorDetailPanel.d.ts.map +1 -1
  578. package/dist/src/tui/components/ErrorDetailPanel.js +4 -4
  579. package/dist/src/tui/components/ErrorDetailPanel.js.map +1 -1
  580. package/dist/src/tui/components/FileChangeSummary.d.ts.map +1 -1
  581. package/dist/src/tui/components/FileChangeSummary.js +3 -3
  582. package/dist/src/tui/components/FileChangeSummary.js.map +1 -1
  583. package/dist/src/tui/components/InputArea.d.ts.map +1 -1
  584. package/dist/src/tui/components/InputArea.js +32 -15
  585. package/dist/src/tui/components/InputArea.js.map +1 -1
  586. package/dist/src/tui/components/LearningValidationDialog.d.ts +25 -0
  587. package/dist/src/tui/components/LearningValidationDialog.d.ts.map +1 -0
  588. package/dist/src/tui/components/LearningValidationDialog.js +35 -0
  589. package/dist/src/tui/components/LearningValidationDialog.js.map +1 -0
  590. package/dist/src/tui/components/MessageItem.d.ts.map +1 -1
  591. package/dist/src/tui/components/MessageItem.js.map +1 -1
  592. package/dist/src/tui/components/PlanPanel.d.ts +27 -0
  593. package/dist/src/tui/components/PlanPanel.d.ts.map +1 -0
  594. package/dist/src/tui/components/PlanPanel.js +45 -0
  595. package/dist/src/tui/components/PlanPanel.js.map +1 -0
  596. package/dist/src/tui/components/ScrollableBox.d.ts.map +1 -1
  597. package/dist/src/tui/components/ScrollableBox.js +2 -2
  598. package/dist/src/tui/components/ScrollableBox.js.map +1 -1
  599. package/dist/src/tui/components/SideBySideDiff.d.ts.map +1 -1
  600. package/dist/src/tui/components/SideBySideDiff.js +20 -18
  601. package/dist/src/tui/components/SideBySideDiff.js.map +1 -1
  602. package/dist/src/tui/components/StatusBar.d.ts +41 -0
  603. package/dist/src/tui/components/StatusBar.d.ts.map +1 -0
  604. package/dist/src/tui/components/StatusBar.js +114 -0
  605. package/dist/src/tui/components/StatusBar.js.map +1 -0
  606. package/dist/src/tui/components/SwarmStatusPanel.d.ts.map +1 -1
  607. package/dist/src/tui/components/SwarmStatusPanel.js +25 -17
  608. package/dist/src/tui/components/SwarmStatusPanel.js.map +1 -1
  609. package/dist/src/tui/components/TasksPanel.d.ts.map +1 -1
  610. package/dist/src/tui/components/TasksPanel.js +12 -11
  611. package/dist/src/tui/components/TasksPanel.js.map +1 -1
  612. package/dist/src/tui/components/ToolCallItem.d.ts.map +1 -1
  613. package/dist/src/tui/components/ToolCallItem.js +19 -6
  614. package/dist/src/tui/components/ToolCallItem.js.map +1 -1
  615. package/dist/src/tui/components/ToolCallsPanel.d.ts +15 -0
  616. package/dist/src/tui/components/ToolCallsPanel.d.ts.map +1 -0
  617. package/dist/src/tui/components/ToolCallsPanel.js +34 -0
  618. package/dist/src/tui/components/ToolCallsPanel.js.map +1 -0
  619. package/dist/src/tui/components/TransparencyPanel.d.ts +15 -0
  620. package/dist/src/tui/components/TransparencyPanel.d.ts.map +1 -0
  621. package/dist/src/tui/components/TransparencyPanel.js +46 -0
  622. package/dist/src/tui/components/TransparencyPanel.js.map +1 -0
  623. package/dist/src/tui/components/index.d.ts +8 -2
  624. package/dist/src/tui/components/index.d.ts.map +1 -1
  625. package/dist/src/tui/components/index.js +14 -2
  626. package/dist/src/tui/components/index.js.map +1 -1
  627. package/dist/src/tui/event-display.d.ts.map +1 -1
  628. package/dist/src/tui/event-display.js +12 -3
  629. package/dist/src/tui/event-display.js.map +1 -1
  630. package/dist/src/tui/hooks/index.d.ts +1 -0
  631. package/dist/src/tui/hooks/index.d.ts.map +1 -1
  632. package/dist/src/tui/hooks/index.js +1 -0
  633. package/dist/src/tui/hooks/index.js.map +1 -1
  634. package/dist/src/tui/hooks/use-agent-events.d.ts +53 -0
  635. package/dist/src/tui/hooks/use-agent-events.d.ts.map +1 -0
  636. package/dist/src/tui/hooks/use-agent-events.js +444 -0
  637. package/dist/src/tui/hooks/use-agent-events.js.map +1 -0
  638. package/dist/src/tui/hooks/use-throttled-state.d.ts +18 -0
  639. package/dist/src/tui/hooks/use-throttled-state.d.ts.map +1 -0
  640. package/dist/src/tui/hooks/use-throttled-state.js +93 -0
  641. package/dist/src/tui/hooks/use-throttled-state.js.map +1 -0
  642. package/dist/src/tui/hooks/useMessagePruning.d.ts.map +1 -1
  643. package/dist/src/tui/hooks/useMessagePruning.js.map +1 -1
  644. package/dist/src/tui/index.d.ts +2 -2
  645. package/dist/src/tui/index.d.ts.map +1 -1
  646. package/dist/src/tui/index.js +101 -6
  647. package/dist/src/tui/index.js.map +1 -1
  648. package/dist/src/tui/input/CommandPalette.d.ts.map +1 -1
  649. package/dist/src/tui/input/CommandPalette.js +2 -2
  650. package/dist/src/tui/input/CommandPalette.js.map +1 -1
  651. package/dist/src/tui/input/index.d.ts +1 -1
  652. package/dist/src/tui/input/index.d.ts.map +1 -1
  653. package/dist/src/tui/input/index.js +1 -1
  654. package/dist/src/tui/input/index.js.map +1 -1
  655. package/dist/src/tui/syntax/languages/bash.js +94 -16
  656. package/dist/src/tui/syntax/languages/bash.js.map +1 -1
  657. package/dist/src/tui/syntax/languages/javascript.js +65 -12
  658. package/dist/src/tui/syntax/languages/javascript.js.map +1 -1
  659. package/dist/src/tui/syntax/languages/json.js.map +1 -1
  660. package/dist/src/tui/syntax/languages/python.js +81 -15
  661. package/dist/src/tui/syntax/languages/python.js.map +1 -1
  662. package/dist/src/tui/theme/index.js.map +1 -1
  663. package/dist/src/tui/transparency-aggregator.d.ts.map +1 -1
  664. package/dist/src/tui/transparency-aggregator.js +18 -4
  665. package/dist/src/tui/transparency-aggregator.js.map +1 -1
  666. package/dist/src/tui/types.d.ts.map +1 -1
  667. package/dist/src/tui/types.js.map +1 -1
  668. package/dist/src/tui/utils/keyboard.d.ts.map +1 -1
  669. package/dist/src/tui/utils/keyboard.js.map +1 -1
  670. package/dist/src/types.d.ts +12 -0
  671. package/dist/src/types.d.ts.map +1 -1
  672. package/package.json +1 -1
@@ -8,7 +8,7 @@
8
8
  * resilience handling, tool execution, and compaction.
9
9
  */
10
10
  import { isFeatureEnabled } from '../defaults.js';
11
- import { estimateTokenCount } from '../integrations/utilities/token-estimate.js';
11
+ import { estimateTokenCount, estimateTokensFromCharCount } from '../integrations/utilities/token-estimate.js';
12
12
  import { callLLM } from './response-handler.js';
13
13
  import { executeToolCalls } from './tool-executor.js';
14
14
  import { TIMEOUT_WRAPUP_PROMPT, stableStringify, } from '../integrations/index.js';
@@ -21,11 +21,30 @@ import { invalidateAST } from '../integrations/context/codebase-ast.js';
21
21
  import * as fs from 'node:fs';
22
22
  const log = createComponentLogger('ExecutionLoop');
23
23
  // =============================================================================
24
+ // EXECUTION LOOP DEFAULTS
25
+ // =============================================================================
26
+ export const EXECUTION_LOOP_DEFAULTS = {
27
+ /** Preview length when compacting long tool outputs */
28
+ COMPACT_PREVIEW_LENGTH: 200,
29
+ /** Max expensive results preserved from compaction */
30
+ MAX_PRESERVED_EXPENSIVE_RESULTS: 6,
31
+ /** Messages to keep during emergency truncation */
32
+ PRESERVE_RECENT: 10,
33
+ /** Max chars per tool output before truncation */
34
+ MAX_TOOL_OUTPUT_CHARS: 8000,
35
+ /** Number of TS edits before triggering a type check */
36
+ TYPE_CHECK_EDIT_THRESHOLD: 5,
37
+ /** Safety margin ratio for context overflow guard */
38
+ CONTEXT_SAFETY_RATIO: 0.9,
39
+ /** Per-result budget safety margin */
40
+ PER_RESULT_BUDGET_RATIO: 0.95,
41
+ };
42
+ // =============================================================================
24
43
  // HELPER FUNCTIONS (extracted from ProductionAgent private methods)
25
44
  // =============================================================================
26
45
  /**
27
46
  * Estimate total tokens in a message array.
28
- * Uses ~4 chars per token heuristic for fast estimation.
47
+ * Delegates to the shared token estimation utility (~3.5 chars/token).
29
48
  */
30
49
  export function estimateContextTokens(messages) {
31
50
  let totalChars = 0;
@@ -40,14 +59,13 @@ export function estimateContextTokens(messages) {
40
59
  }
41
60
  }
42
61
  }
43
- return Math.ceil(totalChars / 4);
62
+ return estimateTokensFromCharCount(totalChars);
44
63
  }
45
64
  /**
46
65
  * Compact tool outputs to save context.
47
66
  */
48
67
  export function compactToolOutputs(messages) {
49
- const COMPACT_PREVIEW_LENGTH = 200;
50
- const MAX_PRESERVED_EXPENSIVE_RESULTS = 6;
68
+ const { COMPACT_PREVIEW_LENGTH, MAX_PRESERVED_EXPENSIVE_RESULTS } = EXECUTION_LOOP_DEFAULTS;
51
69
  let compactedCount = 0;
52
70
  let savedChars = 0;
53
71
  const preservedExpensiveIndexes = messages
@@ -69,7 +87,10 @@ export function compactToolOutputs(messages) {
69
87
  }
70
88
  }
71
89
  if (compactedCount > 0 && process.env.DEBUG) {
72
- log.debug('Compacted tool outputs', { compactedCount, savedTokens: Math.round(savedChars / 4) });
90
+ log.debug('Compacted tool outputs', {
91
+ compactedCount,
92
+ savedTokens: estimateTokensFromCharCount(savedChars),
93
+ });
73
94
  }
74
95
  }
75
96
  /**
@@ -86,21 +107,303 @@ export function isRequestedArtifactMissing(requestedArtifact, executedToolNames)
86
107
  if (!requestedArtifact)
87
108
  return false;
88
109
  const artifactWriteTools = ['write_file', 'edit_file', 'apply_patch', 'append_file'];
89
- return !artifactWriteTools.some(toolName => executedToolNames.has(toolName));
110
+ return !artifactWriteTools.some((toolName) => executedToolNames.has(toolName));
90
111
  }
91
112
  function getOpenTaskSummary(ctx) {
92
113
  if (!ctx.taskManager)
93
114
  return undefined;
94
115
  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;
116
+ const pending = tasks.filter((t) => t.status === 'pending').length;
117
+ const inProgress = tasks.filter((t) => t.status === 'in_progress').length;
118
+ const blocked = tasks.filter((t) => t.status === 'pending' && ctx.taskManager?.isBlocked(t.id)).length;
98
119
  return { pending, inProgress, blocked };
99
120
  }
100
121
  function getPendingWithOwnerCount(ctx) {
101
122
  if (!ctx.taskManager)
102
123
  return 0;
103
- return ctx.taskManager.list().filter(t => t.status === 'pending' && !!t.owner).length;
124
+ return ctx.taskManager.list().filter((t) => t.status === 'pending' && !!t.owner).length;
125
+ }
126
+ /**
127
+ * Check economics/iteration budget before an iteration.
128
+ * Returns whether to continue, stop, or whether recovery succeeded.
129
+ */
130
+ export function checkIterationBudget(deps, messages) {
131
+ if (deps.economics) {
132
+ const budgetCheck = deps.economics.checkBudget();
133
+ const forceTextOnly = budgetCheck.forceTextOnly ?? false;
134
+ const budgetInjectedPrompt = budgetCheck.injectedPrompt;
135
+ const budgetAllowsTaskContinuation = budgetCheck.allowTaskContinuation ?? true;
136
+ deps.traceCollector?.record({
137
+ type: 'budget.check',
138
+ data: {
139
+ iteration: deps.state.iteration,
140
+ canContinue: budgetCheck.canContinue,
141
+ percentUsed: budgetCheck.percentUsed,
142
+ budgetType: budgetCheck.budgetType,
143
+ budgetMode: budgetCheck.budgetMode,
144
+ forceTextOnly,
145
+ allowTaskContinuation: budgetAllowsTaskContinuation,
146
+ enforcementMode: deps.economics.getBudget().enforcementMode ?? 'strict',
147
+ tokenUsage: deps.economics.getUsage().tokens,
148
+ maxTokens: deps.economics.getBudget().maxTokens,
149
+ },
150
+ });
151
+ if (!budgetCheck.canContinue) {
152
+ // RECOVERY ATTEMPT: Try emergency context reduction
153
+ const isTokenLimit = budgetCheck.budgetType === 'tokens' || budgetCheck.budgetType === 'cost';
154
+ const alreadyTriedRecovery = deps.state._recoveryAttempted === true;
155
+ if (isTokenLimit && !alreadyTriedRecovery) {
156
+ deps.observability?.logger?.info('Budget limit reached, attempting recovery via context reduction', { reason: budgetCheck.reason, percentUsed: budgetCheck.percentUsed });
157
+ deps.emit({
158
+ type: 'resilience.retry',
159
+ reason: 'budget_limit_compaction',
160
+ attempt: 1,
161
+ maxAttempts: 1,
162
+ });
163
+ deps.state.metrics.retryCount = (deps.state.metrics.retryCount ?? 0) + 1;
164
+ deps.state._recoveryAttempted = true;
165
+ const tokensBefore = estimateContextTokens(messages);
166
+ // Step 1: Compact tool outputs aggressively
167
+ compactToolOutputs(deps.state.messages);
168
+ // Step 2: Emergency truncation - keep system + last N messages
169
+ const PRESERVE_RECENT = EXECUTION_LOOP_DEFAULTS.PRESERVE_RECENT;
170
+ if (messages.length > PRESERVE_RECENT + 2) {
171
+ const systemMessage = messages.find((m) => m.role === 'system');
172
+ const recentMessages = messages.slice(-PRESERVE_RECENT);
173
+ messages.length = 0;
174
+ if (systemMessage) {
175
+ messages.push(systemMessage);
176
+ }
177
+ messages.push({
178
+ role: 'system',
179
+ content: `[CONTEXT REDUCED: Earlier messages were removed to stay within budget. Conversation continues from recent context.]`,
180
+ });
181
+ messages.push(...recentMessages);
182
+ // Inject work log after emergency truncation
183
+ if (deps.workLog?.hasContent()) {
184
+ messages.push({ role: 'user', content: deps.workLog.toCompactString() });
185
+ }
186
+ // Update state messages too
187
+ deps.state.messages.length = 0;
188
+ deps.state.messages.push(...messages);
189
+ }
190
+ const tokensAfter = estimateContextTokens(messages);
191
+ const reduction = Math.round((1 - tokensAfter / tokensBefore) * 100);
192
+ if (tokensAfter < tokensBefore * 0.8) {
193
+ deps.observability?.logger?.info('Context reduction successful, continuing execution', { tokensBefore, tokensAfter, reduction });
194
+ deps.emit({ type: 'resilience.recovered', reason: 'budget_limit_compaction', attempts: 1 });
195
+ deps.emit({ type: 'compaction.auto', tokensBefore, tokensAfter, messagesCompacted: tokensBefore - tokensAfter });
196
+ deps.economics?.updateBaseline(tokensAfter);
197
+ return { action: 'recovery_success' };
198
+ }
199
+ deps.observability?.logger?.warn('Context reduction insufficient', {
200
+ tokensBefore, tokensAfter, reduction,
201
+ });
202
+ }
203
+ // Hard limit reached and recovery failed
204
+ deps.observability?.logger?.warn('Budget limit reached', {
205
+ reason: budgetCheck.reason,
206
+ budgetType: budgetCheck.budgetType,
207
+ });
208
+ if (budgetCheck.budgetType === 'iterations') {
209
+ const totalIter = deps.getTotalIterations();
210
+ const iterMsg = deps.parentIterations > 0
211
+ ? `${deps.state.iteration} + ${deps.parentIterations} parent = ${totalIter}`
212
+ : `${deps.state.iteration}`;
213
+ const reason = `Max iterations reached (${iterMsg})`;
214
+ deps.emit({ type: 'error', error: reason });
215
+ return { action: 'stop', result: { success: false, terminationReason: 'max_iterations', failureReason: reason } };
216
+ }
217
+ else {
218
+ const reason = budgetCheck.reason || 'Budget exceeded';
219
+ deps.emit({ type: 'error', error: reason });
220
+ return { action: 'stop', result: { success: false, terminationReason: 'budget_limit', failureReason: reason } };
221
+ }
222
+ }
223
+ // Check for soft limits
224
+ if (budgetCheck.isSoftLimit && budgetCheck.suggestedAction === 'request_extension') {
225
+ deps.observability?.logger?.info('Approaching budget limit', {
226
+ reason: budgetCheck.reason,
227
+ percentUsed: budgetCheck.percentUsed,
228
+ });
229
+ }
230
+ return { action: 'continue', forceTextOnly, budgetInjectedPrompt, budgetAllowsTaskContinuation };
231
+ }
232
+ else {
233
+ // Fallback to simple iteration check
234
+ if (deps.getTotalIterations() >= deps.maxIterations) {
235
+ const totalIter = deps.getTotalIterations();
236
+ const reason = `Max iterations reached (${totalIter})`;
237
+ deps.observability?.logger?.warn('Max iterations reached', {
238
+ iteration: deps.state.iteration,
239
+ parentIterations: deps.parentIterations,
240
+ total: totalIter,
241
+ });
242
+ deps.emit({ type: 'error', error: reason });
243
+ return { action: 'stop', result: { success: false, terminationReason: 'max_iterations', failureReason: reason } };
244
+ }
245
+ return { action: 'continue', forceTextOnly: false, budgetAllowsTaskContinuation: true };
246
+ }
247
+ }
248
+ /**
249
+ * Handle auto-compaction of context when approaching token limits.
250
+ * Returns the compaction status and whether messages were modified.
251
+ */
252
+ export async function handleAutoCompaction(deps, messages, stateMessages, setCompactionPending) {
253
+ const currentContextTokens = estimateContextTokens(messages);
254
+ if (deps.autoCompactionManager) {
255
+ const compactionResult = await deps.autoCompactionManager.checkAndMaybeCompact({
256
+ currentTokens: currentContextTokens,
257
+ messages: messages,
258
+ });
259
+ if (compactionResult.status === 'compacted' && compactionResult.compactedMessages) {
260
+ if (!deps.compactionPending) {
261
+ setCompactionPending(true);
262
+ const preCompactionMsg = {
263
+ role: 'user',
264
+ 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.',
265
+ };
266
+ messages.push(preCompactionMsg);
267
+ stateMessages.push(preCompactionMsg);
268
+ deps.observability?.logger?.info('Pre-compaction agentic turn: injected summary request');
269
+ return { status: 'compaction_prompt_injected' };
270
+ }
271
+ else {
272
+ setCompactionPending(false);
273
+ // Replace messages with compacted version
274
+ messages.length = 0;
275
+ messages.push(...compactionResult.compactedMessages);
276
+ stateMessages.length = 0;
277
+ stateMessages.push(...compactionResult.compactedMessages);
278
+ // Inject work log after compaction
279
+ if (deps.workLog?.hasContent()) {
280
+ const workLogMessage = { role: 'user', content: deps.workLog.toCompactString() };
281
+ messages.push(workLogMessage);
282
+ stateMessages.push(workLogMessage);
283
+ }
284
+ // Context recovery
285
+ const recoveryParts = [];
286
+ if (deps.store) {
287
+ const goalsSummary = deps.store.getGoalsSummary();
288
+ if (goalsSummary && goalsSummary !== 'No active goals.' && goalsSummary !== 'Goals feature not available.') {
289
+ recoveryParts.push(goalsSummary);
290
+ }
291
+ }
292
+ if (deps.store) {
293
+ const juncturesSummary = deps.store.getJuncturesSummary(undefined, 5);
294
+ if (juncturesSummary) {
295
+ recoveryParts.push(juncturesSummary);
296
+ }
297
+ }
298
+ if (deps.learningStore) {
299
+ const learnings = deps.learningStore.getLearningContext({ maxLearnings: 3 });
300
+ if (learnings) {
301
+ recoveryParts.push(learnings);
302
+ }
303
+ }
304
+ if (recoveryParts.length > 0) {
305
+ const recoveryMessage = {
306
+ role: 'user',
307
+ content: `[CONTEXT RECOVERY — Re-injected after compaction]\n\n${recoveryParts.join('\n\n')}`,
308
+ };
309
+ messages.push(recoveryMessage);
310
+ stateMessages.push(recoveryMessage);
311
+ }
312
+ const compactionTokensAfter = estimateContextTokens(messages);
313
+ deps.economics?.updateBaseline(compactionTokensAfter);
314
+ const compactionEvent = {
315
+ type: 'context.compacted',
316
+ tokensBefore: currentContextTokens,
317
+ tokensAfter: compactionTokensAfter,
318
+ recoveryInjected: recoveryParts.length > 0,
319
+ };
320
+ deps.emit(compactionEvent);
321
+ deps.traceCollector?.record({
322
+ type: 'context.compacted',
323
+ data: {
324
+ tokensBefore: currentContextTokens,
325
+ tokensAfter: compactionTokensAfter,
326
+ recoveryInjected: recoveryParts.length > 0,
327
+ },
328
+ });
329
+ return { status: 'compacted', tokensBefore: currentContextTokens, tokensAfter: compactionTokensAfter };
330
+ }
331
+ }
332
+ else if (compactionResult.status === 'hard_limit') {
333
+ const reason = `Context hard limit reached (${Math.round(compactionResult.ratio * 100)}% of max tokens)`;
334
+ deps.emit({ type: 'error', error: reason });
335
+ return {
336
+ status: 'hard_limit',
337
+ result: { success: false, terminationReason: 'hard_context_limit', failureReason: reason },
338
+ };
339
+ }
340
+ }
341
+ else if (deps.economics) {
342
+ // Fallback to simple compaction
343
+ const currentUsage = deps.economics.getUsage();
344
+ const budget = deps.economics.getBudget();
345
+ const percentUsed = (currentUsage.tokens / budget.maxTokens) * 100;
346
+ if (percentUsed >= 70) {
347
+ deps.observability?.logger?.info('Proactive compaction triggered', {
348
+ percentUsed: Math.round(percentUsed),
349
+ currentTokens: currentUsage.tokens,
350
+ maxTokens: budget.maxTokens,
351
+ });
352
+ compactToolOutputs(stateMessages);
353
+ return { status: 'simple_compaction_triggered' };
354
+ }
355
+ }
356
+ return { status: 'ok' };
357
+ }
358
+ /**
359
+ * Guard against mass tool results overflowing the context window.
360
+ * Truncates tool results that would push total context beyond budget.
361
+ * Mutates toolResults in-place.
362
+ */
363
+ export function applyContextOverflowGuard(deps, messages, toolResults) {
364
+ if (!deps.economics || toolResults.length <= 10)
365
+ return 0;
366
+ const preAccumTokens = estimateContextTokens(messages);
367
+ const budget = deps.economics.getBudget();
368
+ const availableTokens = budget.maxTokens * EXECUTION_LOOP_DEFAULTS.CONTEXT_SAFETY_RATIO - preAccumTokens;
369
+ const MAX_TOOL_OUTPUT_CHARS = EXECUTION_LOOP_DEFAULTS.MAX_TOOL_OUTPUT_CHARS;
370
+ let totalResultTokens = 0;
371
+ for (const r of toolResults) {
372
+ const c = typeof r.result === 'string' ? r.result : stableStringify(r.result);
373
+ totalResultTokens += estimateTokensFromCharCount(Math.min(c.length, MAX_TOOL_OUTPUT_CHARS));
374
+ }
375
+ if (totalResultTokens > availableTokens && availableTokens > 0) {
376
+ log.warn('Tool results would exceed context budget — truncating batch', {
377
+ resultCount: toolResults.length,
378
+ estimatedTokens: totalResultTokens,
379
+ availableTokens: Math.round(availableTokens),
380
+ });
381
+ let tokenBudget = availableTokens;
382
+ for (let i = 0; i < toolResults.length; i++) {
383
+ const c = typeof toolResults[i].result === 'string'
384
+ ? toolResults[i].result
385
+ : stableStringify(toolResults[i].result);
386
+ const tokens = estimateTokensFromCharCount(Math.min(c.length, MAX_TOOL_OUTPUT_CHARS));
387
+ if (tokens > tokenBudget) {
388
+ const skipped = toolResults.length - i;
389
+ for (let j = i; j < toolResults.length; j++) {
390
+ toolResults[j] = {
391
+ callId: toolResults[j].callId,
392
+ result: `[Result omitted: context overflow guard — ${skipped} of ${toolResults.length} results skipped]`,
393
+ };
394
+ }
395
+ deps.emit({
396
+ type: 'safeguard.context_overflow_guard',
397
+ estimatedTokens: totalResultTokens,
398
+ maxTokens: budget.maxTokens,
399
+ toolResultsSkipped: skipped,
400
+ });
401
+ return skipped;
402
+ }
403
+ tokenBudget -= tokens;
404
+ }
405
+ }
406
+ return 0;
104
407
  }
105
408
  // =============================================================================
106
409
  // MAIN EXECUTION LOOP
@@ -135,12 +438,8 @@ export async function executeDirectly(task, messages, ctx, mutators) {
135
438
  const reflectionConfig = ctx.config.reflection;
136
439
  const reflectionEnabled = isFeatureEnabled(reflectionConfig);
137
440
  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;
441
+ const maxReflectionAttempts = reflectionEnabled ? reflectionConfig.maxAttempts || 3 : 1;
442
+ const confidenceThreshold = reflectionEnabled ? reflectionConfig.confidenceThreshold || 0.8 : 0.8;
144
443
  let reflectionAttempt = 0;
145
444
  let lastResponse = '';
146
445
  let incompleteActionRetries = 0;
@@ -194,163 +493,33 @@ export async function executeDirectly(task, messages, ctx, mutators) {
194
493
  }
195
494
  }
196
495
  // =======================================================================
197
- // ECONOMICS CHECK (Token Budget)
496
+ // ECONOMICS CHECK (Token Budget) — delegated to checkIterationBudget()
198
497
  // =======================================================================
199
498
  let forceTextOnly = false;
200
499
  let budgetInjectedPrompt;
201
500
  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
- }
501
+ const budgetResult = checkIterationBudget({
502
+ economics: ctx.economics,
503
+ getTotalIterations: () => ctx.getTotalIterations(),
504
+ maxIterations: ctx.config.maxIterations,
505
+ parentIterations: ctx.parentIterations,
506
+ state: ctx.state,
507
+ workLog: ctx.workLog,
508
+ observability: ctx.observability,
509
+ traceCollector: ctx.traceCollector,
510
+ emit: (event) => ctx.emit(event),
511
+ }, messages);
512
+ if (budgetResult.action === 'recovery_success') {
513
+ continue;
514
+ }
515
+ else if (budgetResult.action === 'stop') {
516
+ result = budgetResult.result;
517
+ break;
335
518
  }
336
519
  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
- }
520
+ forceTextOnly = budgetResult.forceTextOnly;
521
+ budgetInjectedPrompt = budgetResult.budgetInjectedPrompt;
522
+ budgetAllowsTaskContinuation = budgetResult.budgetAllowsTaskContinuation;
354
523
  }
355
524
  // =======================================================================
356
525
  // GRACEFUL WRAPUP CHECK
@@ -396,15 +565,17 @@ export async function executeDirectly(task, messages, ctx, mutators) {
396
565
  }
397
566
  const enrichedMessages = ctx.contextEngineering.injectRecitation(messages, {
398
567
  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,
568
+ plan: ctx.state.plan
569
+ ? {
570
+ description: ctx.state.plan.goal || task,
571
+ tasks: ctx.state.plan.tasks.map((t) => ({
572
+ id: t.id,
573
+ description: t.description,
574
+ status: t.status,
575
+ })),
576
+ currentTaskIndex: ctx.state.plan.tasks.findIndex((t) => t.status === 'in_progress'),
577
+ }
578
+ : undefined,
408
579
  activeFiles: ctx.economics?.getProgress().filesModified
409
580
  ? [`${ctx.economics.getProgress().filesModified} files modified`]
410
581
  : undefined,
@@ -412,7 +583,9 @@ export async function executeDirectly(task, messages, ctx, mutators) {
412
583
  });
413
584
  if (process.env.DEBUG_LLM) {
414
585
  if (process.env.DEBUG)
415
- log.debug('Recitation after', { messageCount: enrichedMessages?.length ?? 'null/undefined' });
586
+ log.debug('Recitation after', {
587
+ messageCount: enrichedMessages?.length ?? 'null/undefined',
588
+ });
416
589
  }
417
590
  if (enrichedMessages && enrichedMessages !== messages && enrichedMessages.length > 0) {
418
591
  messages.length = 0;
@@ -421,7 +594,7 @@ export async function executeDirectly(task, messages, ctx, mutators) {
421
594
  else if (!enrichedMessages || enrichedMessages.length === 0) {
422
595
  log.warn('Recitation returned empty/null messages, keeping original');
423
596
  }
424
- const contextTokens = messages.reduce((sum, m) => sum + (m.content?.length || 0) / 4, 0);
597
+ const contextTokens = estimateContextTokens(messages);
425
598
  ctx.contextEngineering.updateRecitationFrequency(contextTokens);
426
599
  }
427
600
  // =======================================================================
@@ -448,7 +621,9 @@ export async function executeDirectly(task, messages, ctx, mutators) {
448
621
  // =======================================================================
449
622
  // RESUME ORIENTATION — after compaction, nudge the agent to act, not re-summarize
450
623
  // =======================================================================
451
- const hasCompactionSummary = messages.some(m => m.role === 'system' && typeof m.content === 'string' && m.content.includes('[Conversation Summary'));
624
+ const hasCompactionSummary = messages.some((m) => m.role === 'system' &&
625
+ typeof m.content === 'string' &&
626
+ m.content.includes('[Conversation Summary'));
452
627
  if (hasCompactionSummary && ctx.state.iteration <= 2) {
453
628
  messages.push({
454
629
  role: 'user',
@@ -461,31 +636,48 @@ export async function executeDirectly(task, messages, ctx, mutators) {
461
636
  if (ctx.injectionBudget) {
462
637
  const proposals = [];
463
638
  if (budgetInjectedPrompt) {
464
- proposals.push({ name: 'budget_warning', priority: 0, maxTokens: 500, content: budgetInjectedPrompt });
639
+ proposals.push({
640
+ name: 'budget_warning',
641
+ priority: 0,
642
+ maxTokens: 500,
643
+ content: budgetInjectedPrompt,
644
+ });
465
645
  }
466
646
  if (ctx.contextEngineering) {
467
647
  const failureCtx = ctx.contextEngineering.getFailureContext(5);
468
648
  if (failureCtx) {
469
- proposals.push({ name: 'failure_context', priority: 2, maxTokens: 300, content: failureCtx });
649
+ proposals.push({
650
+ name: 'failure_context',
651
+ priority: 2,
652
+ maxTokens: 300,
653
+ content: failureCtx,
654
+ });
470
655
  }
471
656
  }
472
657
  if (proposals.length > 0) {
473
658
  const accepted = ctx.injectionBudget.allocate(proposals);
474
659
  const stats = ctx.injectionBudget.getLastStats();
475
660
  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 });
661
+ log.debug('Injection budget dropped items', {
662
+ droppedNames: stats.droppedNames.join(', '),
663
+ proposedTokens: stats.proposedTokens,
664
+ acceptedTokens: stats.acceptedTokens,
665
+ });
477
666
  }
478
667
  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 });
668
+ log.debug('Injection budget summary', {
669
+ iteration: ctx.state.iteration,
670
+ accepted: accepted.length,
671
+ total: proposals.length,
672
+ tokens: stats.acceptedTokens,
673
+ });
480
674
  }
481
675
  }
482
676
  }
483
677
  // =======================================================================
484
678
  // RESILIENT LLM CALL
485
679
  // =======================================================================
486
- const resilienceConfig = typeof ctx.config.resilience === 'object'
487
- ? ctx.config.resilience
488
- : {};
680
+ const resilienceConfig = typeof ctx.config.resilience === 'object' ? ctx.config.resilience : {};
489
681
  const resilienceEnabled = isFeatureEnabled(ctx.config.resilience);
490
682
  const MAX_EMPTY_RETRIES = resilienceConfig.maxEmptyRetries ?? 2;
491
683
  const MAX_CONTINUATIONS = resilienceConfig.maxContinuations ?? 3;
@@ -537,8 +729,10 @@ export async function executeDirectly(task, messages, ctx, mutators) {
537
729
  // skip the expensive LLM call (whose tool calls would be discarded) and
538
730
  // go directly to the task continuation gate. Only allowed once per
539
731
  // forceTextOnly episode to prevent tight loops.
540
- if (forceTextOnly && budgetAllowsTaskContinuation && ctx.taskManager
541
- && !ctx.state._lastSkippedLLMIteration) {
732
+ if (forceTextOnly &&
733
+ budgetAllowsTaskContinuation &&
734
+ ctx.taskManager &&
735
+ !ctx.state._lastSkippedLLMIteration) {
542
736
  const availableTasks = ctx.taskManager.getAvailableTasks();
543
737
  if (availableTasks.length > 0) {
544
738
  log.info('Skipping LLM call — forceTextOnly with tasks available, going to task continuation', {
@@ -546,7 +740,8 @@ export async function executeDirectly(task, messages, ctx, mutators) {
546
740
  iteration: ctx.state.iteration,
547
741
  });
548
742
  // Mark that we skipped so we don't skip again on the next iteration
549
- ctx.state._lastSkippedLLMIteration = ctx.state.iteration;
743
+ ctx.state._lastSkippedLLMIteration =
744
+ ctx.state.iteration;
550
745
  // Reset forceTextOnly for the next iteration so the task can run normally
551
746
  forceTextOnly = false;
552
747
  const nextTask = availableTasks[0];
@@ -638,7 +833,10 @@ export async function executeDirectly(task, messages, ctx, mutators) {
638
833
  response = await callLLM(messages, ctx);
639
834
  }
640
835
  // Phase 2: Handle max_tokens truncation with continuation
641
- if (resilienceEnabled && AUTO_CONTINUE && response.stopReason === 'max_tokens' && !response.toolCalls?.length) {
836
+ if (resilienceEnabled &&
837
+ AUTO_CONTINUE &&
838
+ response.stopReason === 'max_tokens' &&
839
+ !response.toolCalls?.length) {
642
840
  let accumulatedContent = response.content || '';
643
841
  while (continuations < MAX_CONTINUATIONS && response.stopReason === 'max_tokens') {
644
842
  continuations++;
@@ -682,10 +880,10 @@ export async function executeDirectly(task, messages, ctx, mutators) {
682
880
  if (resilienceEnabled && response.stopReason === 'max_tokens' && response.toolCalls?.length) {
683
881
  ctx.emit({
684
882
  type: 'resilience.truncated_tool_call',
685
- toolNames: response.toolCalls.map(tc => tc.name),
883
+ toolNames: response.toolCalls.map((tc) => tc.name),
686
884
  });
687
885
  ctx.observability?.logger?.warn('Tool call truncated at max_tokens', {
688
- toolNames: response.toolCalls.map(tc => tc.name),
886
+ toolNames: response.toolCalls.map((tc) => tc.name),
689
887
  outputTokens: response.usage?.outputTokens,
690
888
  });
691
889
  const truncatedResponse = response;
@@ -728,9 +926,12 @@ export async function executeDirectly(task, messages, ctx, mutators) {
728
926
  ctx.state.messages.push(assistantMessage);
729
927
  lastResponse = response.content || (response.thinking ? response.thinking : '');
730
928
  // 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)) {
929
+ if (ctx.modeManager.getMode() === 'plan' &&
930
+ response.content &&
931
+ response.content.length > 50) {
932
+ const hasReadOnlyTools = response.toolCalls?.every((tc) => ['read_file', 'list_files', 'glob', 'grep', 'search', 'mcp_'].some((prefix) => tc.name.startsWith(prefix) || tc.name === prefix));
933
+ if (hasReadOnlyTools &&
934
+ !response.content.match(/^(Let me|I'll|I will|I need to|First,)/i)) {
734
935
  ctx.pendingPlanManager.appendExplorationFinding(response.content.slice(0, 1000));
735
936
  }
736
937
  }
@@ -751,10 +952,10 @@ export async function executeDirectly(task, messages, ctx, mutators) {
751
952
  const missingRequiredArtifact = ENFORCE_REQUESTED_ARTIFACTS
752
953
  ? isRequestedArtifactMissing(requestedArtifact, executedToolNames)
753
954
  : false;
754
- const shouldRecoverIncompleteAction = resilienceEnabled
755
- && INCOMPLETE_ACTION_RECOVERY
756
- && !forceTextOnly
757
- && (incompleteAction || missingRequiredArtifact);
955
+ const shouldRecoverIncompleteAction = resilienceEnabled &&
956
+ INCOMPLETE_ACTION_RECOVERY &&
957
+ !forceTextOnly &&
958
+ (incompleteAction || missingRequiredArtifact);
758
959
  if (shouldRecoverIncompleteAction) {
759
960
  ctx.emit({
760
961
  type: 'completion.before',
@@ -847,15 +1048,20 @@ export async function executeDirectly(task, messages, ctx, mutators) {
847
1048
  incompleteActionRetries = 0;
848
1049
  }
849
1050
  // 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)) {
1051
+ if (ctx.typeCheckerState?.tsconfigDir &&
1052
+ !forceTextOnly &&
1053
+ (ctx.typeCheckerState.tsEditsSinceLastCheck > 0 || !ctx.typeCheckerState.hasRunOnce)) {
853
1054
  const tscResult = await runTypeCheck(ctx.typeCheckerState.tsconfigDir);
854
1055
  ctx.typeCheckerState.tsEditsSinceLastCheck = 0;
855
1056
  ctx.typeCheckerState.lastResult = tscResult;
856
1057
  ctx.typeCheckerState.hasRunOnce = true;
857
1058
  ctx.verificationGate?.recordCompilationResult(tscResult.success, tscResult.errorCount);
858
- ctx.emit({ type: 'diagnostics.tsc-check', errorCount: tscResult.errorCount, duration: tscResult.duration, trigger: 'completion' });
1059
+ ctx.emit({
1060
+ type: 'diagnostics.tsc-check',
1061
+ errorCount: tscResult.errorCount,
1062
+ duration: tscResult.duration,
1063
+ trigger: 'completion',
1064
+ });
859
1065
  if (!tscResult.success) {
860
1066
  const vState = ctx.verificationGate?.getState();
861
1067
  const maxCompNudges = 8;
@@ -865,7 +1071,10 @@ export async function executeDirectly(task, messages, ctx, mutators) {
865
1071
  messages.push(nudgeMessage);
866
1072
  ctx.state.messages.push(nudgeMessage);
867
1073
  ctx.verificationGate?.incrementCompilationNudge();
868
- log.info('Compilation gate blocked completion', { count: tscResult.errorCount, nudgeCount: ctx.verificationGate?.getState().compilationNudgeCount });
1074
+ log.info('Compilation gate blocked completion', {
1075
+ count: tscResult.errorCount,
1076
+ nudgeCount: ctx.verificationGate?.getState().compilationNudgeCount,
1077
+ });
869
1078
  ctx.emit({
870
1079
  type: 'iteration.after',
871
1080
  iteration: ctx.state.iteration,
@@ -995,7 +1204,9 @@ export async function executeDirectly(task, messages, ctx, mutators) {
995
1204
  }
996
1205
  const reasons = [
997
1206
  `Open tasks remain: ${openTasks.pending} pending, ${openTasks.inProgress} in_progress`,
998
- openTasks.blocked > 0 ? `${openTasks.blocked} pending tasks are currently blocked` : '',
1207
+ openTasks.blocked > 0
1208
+ ? `${openTasks.blocked} pending tasks are currently blocked`
1209
+ : '',
999
1210
  ].filter(Boolean);
1000
1211
  ctx.emit({
1001
1212
  type: 'completion.blocked',
@@ -1025,7 +1236,7 @@ export async function executeDirectly(task, messages, ctx, mutators) {
1025
1236
  log.warn('Tool call explosion detected — capping', {
1026
1237
  requested: toolCalls.length,
1027
1238
  cap: maxToolCallsPerResponse,
1028
- toolNames: [...new Set(toolCalls.map(tc => tc.name))],
1239
+ toolNames: [...new Set(toolCalls.map((tc) => tc.name))],
1029
1240
  });
1030
1241
  ctx.emit({
1031
1242
  type: 'safeguard.tool_call_cap',
@@ -1052,7 +1263,9 @@ export async function executeDirectly(task, messages, ctx, mutators) {
1052
1263
  // Record in work log
1053
1264
  const toolOutput = result?.result && typeof result.result === 'object' && 'output' in result.result
1054
1265
  ? String(result.result.output)
1055
- : typeof result?.result === 'string' ? result.result : undefined;
1266
+ : typeof result?.result === 'string'
1267
+ ? result.result
1268
+ : undefined;
1056
1269
  ctx.workLog?.recordToolExecution(toolCall.name, toolCall.arguments, toolOutput);
1057
1270
  // Record in verification gate
1058
1271
  if (ctx.verificationGate) {
@@ -1060,9 +1273,11 @@ export async function executeDirectly(task, messages, ctx, mutators) {
1060
1273
  const toolRes = result?.result;
1061
1274
  const output = toolRes && typeof toolRes === 'object' && 'output' in toolRes
1062
1275
  ? String(toolRes.output)
1063
- : typeof toolRes === 'string' ? toolRes : '';
1276
+ : typeof toolRes === 'string'
1277
+ ? toolRes
1278
+ : '';
1064
1279
  const exitCode = toolRes && typeof toolRes === 'object' && toolRes.metadata
1065
- ? toolRes.metadata.exitCode ?? null
1280
+ ? (toolRes.metadata.exitCode ?? null)
1066
1281
  : null;
1067
1282
  ctx.verificationGate.recordBashExecution(String(toolCall.arguments.command || ''), output, exitCode);
1068
1283
  }
@@ -1071,7 +1286,9 @@ export async function executeDirectly(task, messages, ctx, mutators) {
1071
1286
  }
1072
1287
  }
1073
1288
  // Phase 5.1: Post-edit syntax validation + AST cache invalidation
1074
- if (['write_file', 'edit_file'].includes(toolCall.name) && result?.result && result.result.success) {
1289
+ if (['write_file', 'edit_file'].includes(toolCall.name) &&
1290
+ result?.result &&
1291
+ result.result.success) {
1075
1292
  const filePath = String(toolCall.arguments.path || '');
1076
1293
  if (filePath) {
1077
1294
  // Invalidate stale AST cache entry so next analysis/validation reparses
@@ -1086,18 +1303,26 @@ export async function executeDirectly(task, messages, ctx, mutators) {
1086
1303
  try {
1087
1304
  await ctx.codebaseContext.updateFile(filePath, content);
1088
1305
  }
1089
- catch { /* non-blocking */ }
1306
+ catch {
1307
+ /* non-blocking */
1308
+ }
1090
1309
  }
1091
1310
  const validation = validateSyntax(content, filePath);
1092
1311
  if (!validation.valid && result.result && typeof result.result === 'object') {
1093
1312
  const errorSummary = validation.errors
1094
1313
  .slice(0, 3)
1095
- .map(e => ` L${e.line}:${e.column}: ${e.message}`)
1314
+ .map((e) => ` L${e.line}:${e.column}: ${e.message}`)
1096
1315
  .join('\n');
1097
- result.result.output += `\n\n⚠ Syntax validation warning:\n${errorSummary}`;
1316
+ result.result.output +=
1317
+ `\n\n⚠ Syntax validation warning:\n${errorSummary}`;
1098
1318
  // Emit diagnostic events for each syntax error
1099
1319
  for (const err of validation.errors.slice(0, 5)) {
1100
- ctx.emit({ type: 'diagnostics.syntax-error', file: filePath, line: err.line, message: err.message });
1320
+ ctx.emit({
1321
+ type: 'diagnostics.syntax-error',
1322
+ file: filePath,
1323
+ line: err.line,
1324
+ message: err.message,
1325
+ });
1101
1326
  }
1102
1327
  }
1103
1328
  }
@@ -1112,180 +1337,48 @@ export async function executeDirectly(task, messages, ctx, mutators) {
1112
1337
  }
1113
1338
  }
1114
1339
  // 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
- }
1340
+ const MAX_TOOL_OUTPUT_CHARS = EXECUTION_LOOP_DEFAULTS.MAX_TOOL_OUTPUT_CHARS;
1341
+ // PROACTIVE BUDGET CHECK — delegate to extracted function
1342
+ const compactionStatus = await handleAutoCompaction({
1343
+ autoCompactionManager: ctx.autoCompactionManager ?? null,
1344
+ compactionPending: ctx.compactionPending,
1345
+ economics: ctx.economics,
1346
+ workLog: ctx.workLog,
1347
+ store: ctx.store,
1348
+ learningStore: ctx.learningStore,
1349
+ observability: ctx.observability,
1350
+ traceCollector: ctx.traceCollector,
1351
+ emit: (event) => ctx.emit(event),
1352
+ }, messages, ctx.state.messages, (v) => mutators.setCompactionPending(v));
1353
+ if (compactionStatus.status === 'hard_limit') {
1354
+ result = compactionStatus.result;
1355
+ break;
1273
1356
  }
1274
- const toolCallNameById = new Map(toolCalls.map(tc => [tc.id, tc.name]));
1357
+ // SAFEGUARD: Aggregate context guard delegate to extracted function
1358
+ applyContextOverflowGuard({ economics: ctx.economics, emit: (event) => ctx.emit(event) }, messages, toolResults);
1359
+ const toolCallNameById = new Map(toolCalls.map((tc) => [tc.id, tc.name]));
1275
1360
  for (const result of toolResults) {
1276
- let content = typeof result.result === 'string' ? result.result : stableStringify(result.result);
1361
+ let content = typeof result.result === 'string'
1362
+ ? result.result
1363
+ : ctx.contextEngineering
1364
+ ? ctx.contextEngineering.serialize(result.result)
1365
+ : stableStringify(result.result);
1277
1366
  const sourceToolName = toolCallNameById.get(result.callId);
1278
1367
  const isExpensiveResult = sourceToolName === 'spawn_agent' || sourceToolName === 'spawn_agents_parallel';
1279
- const effectiveMaxChars = isExpensiveResult ? MAX_TOOL_OUTPUT_CHARS * 2 : MAX_TOOL_OUTPUT_CHARS;
1368
+ const effectiveMaxChars = isExpensiveResult
1369
+ ? MAX_TOOL_OUTPUT_CHARS * 2
1370
+ : MAX_TOOL_OUTPUT_CHARS;
1280
1371
  if (content.length > effectiveMaxChars) {
1281
- content = content.slice(0, effectiveMaxChars) + `\n\n... [truncated ${content.length - effectiveMaxChars} chars]`;
1372
+ content =
1373
+ content.slice(0, effectiveMaxChars) +
1374
+ `\n\n... [truncated ${content.length - effectiveMaxChars} chars]`;
1282
1375
  }
1283
1376
  // Check if adding this result would exceed budget
1284
1377
  if (ctx.economics) {
1285
1378
  const estimatedNewTokens = estimateTokenCount(content);
1286
1379
  const currentCtxTokens = estimateContextTokens(messages);
1287
1380
  const budget = ctx.economics.getBudget();
1288
- if (currentCtxTokens + estimatedNewTokens > budget.maxTokens * 0.95) {
1381
+ if (currentCtxTokens + estimatedNewTokens > budget.maxTokens * EXECUTION_LOOP_DEFAULTS.PER_RESULT_BUDGET_RATIO) {
1289
1382
  ctx.observability?.logger?.warn('Skipping tool result to stay within budget', {
1290
1383
  toolCallId: result.callId,
1291
1384
  estimatedTokens: estimatedNewTokens,
@@ -1320,16 +1413,21 @@ export async function executeDirectly(task, messages, ctx, mutators) {
1320
1413
  ctx.state.messages.push(toolMessage);
1321
1414
  }
1322
1415
  // 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) {
1416
+ const TYPE_CHECK_EDIT_THRESHOLD = EXECUTION_LOOP_DEFAULTS.TYPE_CHECK_EDIT_THRESHOLD;
1417
+ if (ctx.typeCheckerState?.tsconfigDir &&
1418
+ ctx.typeCheckerState.tsEditsSinceLastCheck >= TYPE_CHECK_EDIT_THRESHOLD &&
1419
+ !forceTextOnly) {
1327
1420
  const tscResult = await runTypeCheck(ctx.typeCheckerState.tsconfigDir);
1328
1421
  ctx.typeCheckerState.tsEditsSinceLastCheck = 0;
1329
1422
  ctx.typeCheckerState.lastResult = tscResult;
1330
1423
  ctx.typeCheckerState.hasRunOnce = true;
1331
1424
  ctx.verificationGate?.recordCompilationResult(tscResult.success, tscResult.errorCount);
1332
- ctx.emit({ type: 'diagnostics.tsc-check', errorCount: tscResult.errorCount, duration: tscResult.duration, trigger: 'periodic' });
1425
+ ctx.emit({
1426
+ type: 'diagnostics.tsc-check',
1427
+ errorCount: tscResult.errorCount,
1428
+ duration: tscResult.duration,
1429
+ trigger: 'periodic',
1430
+ });
1333
1431
  if (!tscResult.success) {
1334
1432
  const nudge = formatTypeCheckNudge(tscResult);
1335
1433
  const infoMsg = { role: 'user', content: nudge };