attocode 0.2.4 → 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 (813) hide show
  1. package/CHANGELOG.md +88 -1
  2. package/dist/src/adapters.d.ts +39 -1
  3. package/dist/src/adapters.d.ts.map +1 -1
  4. package/dist/src/adapters.js +201 -16
  5. package/dist/src/adapters.js.map +1 -1
  6. package/dist/src/agent/agent-builder.d.ts +117 -0
  7. package/dist/src/agent/agent-builder.d.ts.map +1 -0
  8. package/dist/src/agent/agent-builder.js +204 -0
  9. package/dist/src/agent/agent-builder.js.map +1 -0
  10. package/dist/src/agent/feature-initializer.d.ts +80 -0
  11. package/dist/src/agent/feature-initializer.d.ts.map +1 -0
  12. package/dist/src/agent/feature-initializer.js +676 -0
  13. package/dist/src/agent/feature-initializer.js.map +1 -0
  14. package/dist/src/agent/index.d.ts +13 -0
  15. package/dist/src/agent/index.d.ts.map +1 -0
  16. package/dist/src/agent/index.js +13 -0
  17. package/dist/src/agent/index.js.map +1 -0
  18. package/dist/src/agent/message-builder.d.ts +50 -0
  19. package/dist/src/agent/message-builder.d.ts.map +1 -0
  20. package/dist/src/agent/message-builder.js +176 -0
  21. package/dist/src/agent/message-builder.js.map +1 -0
  22. package/dist/src/agent/session-api.d.ts +94 -0
  23. package/dist/src/agent/session-api.d.ts.map +1 -0
  24. package/dist/src/agent/session-api.js +264 -0
  25. package/dist/src/agent/session-api.js.map +1 -0
  26. package/dist/src/agent-tools/lsp-file-tools.d.ts +1 -1
  27. package/dist/src/agent-tools/lsp-file-tools.d.ts.map +1 -1
  28. package/dist/src/agent-tools/lsp-file-tools.js +17 -13
  29. package/dist/src/agent-tools/lsp-file-tools.js.map +1 -1
  30. package/dist/src/agent.d.ts +26 -117
  31. package/dist/src/agent.d.ts.map +1 -1
  32. package/dist/src/agent.js +239 -1249
  33. package/dist/src/agent.js.map +1 -1
  34. package/dist/src/analysis/feedback-loop.d.ts.map +1 -1
  35. package/dist/src/analysis/feedback-loop.js +13 -9
  36. package/dist/src/analysis/feedback-loop.js.map +1 -1
  37. package/dist/src/analysis/index.d.ts +1 -1
  38. package/dist/src/analysis/index.d.ts.map +1 -1
  39. package/dist/src/analysis/index.js +1 -1
  40. package/dist/src/analysis/index.js.map +1 -1
  41. package/dist/src/analysis/prompt-templates.d.ts.map +1 -1
  42. package/dist/src/analysis/prompt-templates.js.map +1 -1
  43. package/dist/src/analysis/trace-summary.d.ts.map +1 -1
  44. package/dist/src/analysis/trace-summary.js +25 -9
  45. package/dist/src/analysis/trace-summary.js.map +1 -1
  46. package/dist/src/cli.d.ts.map +1 -1
  47. package/dist/src/cli.js +4 -2
  48. package/dist/src/cli.js.map +1 -1
  49. package/dist/src/commands/agents-commands.d.ts.map +1 -1
  50. package/dist/src/commands/agents-commands.js +3 -3
  51. package/dist/src/commands/agents-commands.js.map +1 -1
  52. package/dist/src/commands/handler.d.ts.map +1 -1
  53. package/dist/src/commands/handler.js +68 -44
  54. package/dist/src/commands/handler.js.map +1 -1
  55. package/dist/src/commands/init-commands.d.ts.map +1 -1
  56. package/dist/src/commands/init-commands.js +8 -10
  57. package/dist/src/commands/init-commands.js.map +1 -1
  58. package/dist/src/commands/init.js +17 -17
  59. package/dist/src/commands/init.js.map +1 -1
  60. package/dist/src/commands/skills-commands.d.ts.map +1 -1
  61. package/dist/src/commands/skills-commands.js +10 -7
  62. package/dist/src/commands/skills-commands.js.map +1 -1
  63. package/dist/src/commands/types.d.ts.map +1 -1
  64. package/dist/src/config/config-manager.d.ts.map +1 -1
  65. package/dist/src/config/config-manager.js +4 -1
  66. package/dist/src/config/config-manager.js.map +1 -1
  67. package/dist/src/config/index.d.ts +1 -1
  68. package/dist/src/config/index.d.ts.map +1 -1
  69. package/dist/src/config/schema.d.ts +6 -6
  70. package/dist/src/config/schema.d.ts.map +1 -1
  71. package/dist/src/config/schema.js +6 -2
  72. package/dist/src/config/schema.js.map +1 -1
  73. package/dist/src/core/agent-state-machine.d.ts.map +1 -1
  74. package/dist/src/core/agent-state-machine.js +5 -2
  75. package/dist/src/core/agent-state-machine.js.map +1 -1
  76. package/dist/src/core/completion-analyzer.d.ts.map +1 -1
  77. package/dist/src/core/completion-analyzer.js +2 -2
  78. package/dist/src/core/completion-analyzer.js.map +1 -1
  79. package/dist/src/core/execution-loop.d.ts +172 -1
  80. package/dist/src/core/execution-loop.d.ts.map +1 -1
  81. package/dist/src/core/execution-loop.js +597 -360
  82. package/dist/src/core/execution-loop.js.map +1 -1
  83. package/dist/src/core/index.d.ts +2 -2
  84. package/dist/src/core/index.d.ts.map +1 -1
  85. package/dist/src/core/index.js +1 -1
  86. package/dist/src/core/index.js.map +1 -1
  87. package/dist/src/core/queues/event-queue.d.ts.map +1 -1
  88. package/dist/src/core/queues/event-queue.js.map +1 -1
  89. package/dist/src/core/response-handler.d.ts.map +1 -1
  90. package/dist/src/core/response-handler.js +20 -10
  91. package/dist/src/core/response-handler.js.map +1 -1
  92. package/dist/src/core/subagent-spawner.d.ts.map +1 -1
  93. package/dist/src/core/subagent-spawner.js +98 -59
  94. package/dist/src/core/subagent-spawner.js.map +1 -1
  95. package/dist/src/core/tool-executor.d.ts.map +1 -1
  96. package/dist/src/core/tool-executor.js +63 -27
  97. package/dist/src/core/tool-executor.js.map +1 -1
  98. package/dist/src/core/types.d.ts +1 -0
  99. package/dist/src/core/types.d.ts.map +1 -1
  100. package/dist/src/core/types.js.map +1 -1
  101. package/dist/src/costs/model-registry.js +6 -6
  102. package/dist/src/costs/model-registry.js.map +1 -1
  103. package/dist/src/defaults.d.ts.map +1 -1
  104. package/dist/src/defaults.js +67 -20
  105. package/dist/src/defaults.js.map +1 -1
  106. package/dist/src/errors/index.d.ts.map +1 -1
  107. package/dist/src/errors/index.js +6 -8
  108. package/dist/src/errors/index.js.map +1 -1
  109. package/dist/src/first-run.d.ts.map +1 -1
  110. package/dist/src/first-run.js +11 -11
  111. package/dist/src/first-run.js.map +1 -1
  112. package/dist/src/integrations/agents/agent-registry.d.ts +262 -0
  113. package/dist/src/integrations/agents/agent-registry.d.ts.map +1 -0
  114. package/dist/src/integrations/agents/agent-registry.js +686 -0
  115. package/dist/src/integrations/agents/agent-registry.js.map +1 -0
  116. package/dist/src/integrations/agents/async-subagent.d.ts +135 -0
  117. package/dist/src/integrations/agents/async-subagent.d.ts.map +1 -0
  118. package/dist/src/integrations/agents/async-subagent.js +211 -0
  119. package/dist/src/integrations/agents/async-subagent.js.map +1 -0
  120. package/dist/src/integrations/agents/complexity-classifier.d.ts +86 -0
  121. package/dist/src/integrations/agents/complexity-classifier.d.ts.map +1 -0
  122. package/dist/src/integrations/agents/complexity-classifier.js +264 -0
  123. package/dist/src/integrations/agents/complexity-classifier.js.map +1 -0
  124. package/dist/src/integrations/agents/delegation-protocol.d.ts +86 -0
  125. package/dist/src/integrations/agents/delegation-protocol.d.ts.map +1 -0
  126. package/dist/src/integrations/agents/delegation-protocol.js +127 -0
  127. package/dist/src/integrations/agents/delegation-protocol.js.map +1 -0
  128. package/dist/src/integrations/agents/multi-agent.d.ts +150 -0
  129. package/dist/src/integrations/agents/multi-agent.d.ts.map +1 -0
  130. package/dist/src/integrations/agents/multi-agent.js +302 -0
  131. package/dist/src/integrations/agents/multi-agent.js.map +1 -0
  132. package/dist/src/integrations/agents/result-synthesizer.d.ts +389 -0
  133. package/dist/src/integrations/agents/result-synthesizer.d.ts.map +1 -0
  134. package/dist/src/integrations/agents/result-synthesizer.js +953 -0
  135. package/dist/src/integrations/agents/result-synthesizer.js.map +1 -0
  136. package/dist/src/integrations/agents/shared-blackboard.d.ts +406 -0
  137. package/dist/src/integrations/agents/shared-blackboard.d.ts.map +1 -0
  138. package/dist/src/integrations/agents/shared-blackboard.js +757 -0
  139. package/dist/src/integrations/agents/shared-blackboard.js.map +1 -0
  140. package/dist/src/integrations/agents/subagent-output-store.d.ts +91 -0
  141. package/dist/src/integrations/agents/subagent-output-store.d.ts.map +1 -0
  142. package/dist/src/integrations/agents/subagent-output-store.js +256 -0
  143. package/dist/src/integrations/agents/subagent-output-store.js.map +1 -0
  144. package/dist/src/integrations/budget/budget-pool.d.ts +115 -0
  145. package/dist/src/integrations/budget/budget-pool.d.ts.map +1 -0
  146. package/dist/src/integrations/budget/budget-pool.js +201 -0
  147. package/dist/src/integrations/budget/budget-pool.js.map +1 -0
  148. package/dist/src/integrations/budget/cancellation.d.ts +229 -0
  149. package/dist/src/integrations/budget/cancellation.d.ts.map +1 -0
  150. package/dist/src/integrations/budget/cancellation.js +534 -0
  151. package/dist/src/integrations/budget/cancellation.js.map +1 -0
  152. package/dist/src/integrations/budget/dynamic-budget.d.ts +81 -0
  153. package/dist/src/integrations/budget/dynamic-budget.d.ts.map +1 -0
  154. package/dist/src/integrations/budget/dynamic-budget.js +149 -0
  155. package/dist/src/integrations/budget/dynamic-budget.js.map +1 -0
  156. package/dist/src/integrations/budget/economics.d.ts +435 -0
  157. package/dist/src/integrations/budget/economics.d.ts.map +1 -0
  158. package/dist/src/integrations/budget/economics.js +1039 -0
  159. package/dist/src/integrations/budget/economics.js.map +1 -0
  160. package/dist/src/integrations/budget/injection-budget.d.ts +71 -0
  161. package/dist/src/integrations/budget/injection-budget.d.ts.map +1 -0
  162. package/dist/src/integrations/budget/injection-budget.js +137 -0
  163. package/dist/src/integrations/budget/injection-budget.js.map +1 -0
  164. package/dist/src/integrations/budget/loop-detector.d.ts +105 -0
  165. package/dist/src/integrations/budget/loop-detector.d.ts.map +1 -0
  166. package/dist/src/integrations/budget/loop-detector.js +304 -0
  167. package/dist/src/integrations/budget/loop-detector.js.map +1 -0
  168. package/dist/src/integrations/budget/phase-tracker.d.ts +114 -0
  169. package/dist/src/integrations/budget/phase-tracker.d.ts.map +1 -0
  170. package/dist/src/integrations/budget/phase-tracker.js +265 -0
  171. package/dist/src/integrations/budget/phase-tracker.js.map +1 -0
  172. package/dist/src/integrations/budget/resources.d.ts +182 -0
  173. package/dist/src/integrations/budget/resources.d.ts.map +1 -0
  174. package/dist/src/integrations/budget/resources.js +362 -0
  175. package/dist/src/integrations/budget/resources.js.map +1 -0
  176. package/dist/src/integrations/context/auto-compaction.d.ts +210 -0
  177. package/dist/src/integrations/context/auto-compaction.d.ts.map +1 -0
  178. package/dist/src/integrations/context/auto-compaction.js +485 -0
  179. package/dist/src/integrations/context/auto-compaction.js.map +1 -0
  180. package/dist/src/integrations/context/code-analyzer.d.ts +71 -0
  181. package/dist/src/integrations/context/code-analyzer.d.ts.map +1 -0
  182. package/dist/src/integrations/context/code-analyzer.js +445 -0
  183. package/dist/src/integrations/context/code-analyzer.js.map +1 -0
  184. package/dist/src/integrations/context/code-selector.d.ts +78 -0
  185. package/dist/src/integrations/context/code-selector.d.ts.map +1 -0
  186. package/dist/src/integrations/context/code-selector.js +668 -0
  187. package/dist/src/integrations/context/code-selector.js.map +1 -0
  188. package/dist/src/integrations/context/codebase-ast.d.ts +138 -0
  189. package/dist/src/integrations/context/codebase-ast.d.ts.map +1 -0
  190. package/dist/src/integrations/context/codebase-ast.js +881 -0
  191. package/dist/src/integrations/context/codebase-ast.js.map +1 -0
  192. package/dist/src/integrations/context/codebase-context.d.ts +473 -0
  193. package/dist/src/integrations/context/codebase-context.d.ts.map +1 -0
  194. package/dist/src/integrations/context/codebase-context.js +694 -0
  195. package/dist/src/integrations/context/codebase-context.js.map +1 -0
  196. package/dist/src/integrations/context/compaction.d.ts +191 -0
  197. package/dist/src/integrations/context/compaction.d.ts.map +1 -0
  198. package/dist/src/integrations/context/compaction.js +391 -0
  199. package/dist/src/integrations/context/compaction.js.map +1 -0
  200. package/dist/src/integrations/context/context-engineering.d.ts +274 -0
  201. package/dist/src/integrations/context/context-engineering.d.ts.map +1 -0
  202. package/dist/src/integrations/context/context-engineering.js +437 -0
  203. package/dist/src/integrations/context/context-engineering.js.map +1 -0
  204. package/dist/src/integrations/context/file-cache.d.ts +97 -0
  205. package/dist/src/integrations/context/file-cache.d.ts.map +1 -0
  206. package/dist/src/integrations/context/file-cache.js +218 -0
  207. package/dist/src/integrations/context/file-cache.js.map +1 -0
  208. package/dist/src/integrations/context/semantic-cache.d.ts +178 -0
  209. package/dist/src/integrations/context/semantic-cache.d.ts.map +1 -0
  210. package/dist/src/integrations/context/semantic-cache.js +377 -0
  211. package/dist/src/integrations/context/semantic-cache.js.map +1 -0
  212. package/dist/src/integrations/index.d.ts +72 -68
  213. package/dist/src/integrations/index.d.ts.map +1 -1
  214. package/dist/src/integrations/index.js +76 -68
  215. package/dist/src/integrations/index.js.map +1 -1
  216. package/dist/src/integrations/lsp/lsp.d.ts +196 -0
  217. package/dist/src/integrations/lsp/lsp.d.ts.map +1 -0
  218. package/dist/src/integrations/lsp/lsp.js +583 -0
  219. package/dist/src/integrations/lsp/lsp.js.map +1 -0
  220. package/dist/src/integrations/mcp/mcp-client.d.ts +279 -0
  221. package/dist/src/integrations/mcp/mcp-client.d.ts.map +1 -0
  222. package/dist/src/integrations/mcp/mcp-client.js +776 -0
  223. package/dist/src/integrations/mcp/mcp-client.js.map +1 -0
  224. package/dist/src/integrations/mcp/mcp-custom-tools.d.ts +102 -0
  225. package/dist/src/integrations/mcp/mcp-custom-tools.d.ts.map +1 -0
  226. package/dist/src/integrations/mcp/mcp-custom-tools.js +232 -0
  227. package/dist/src/integrations/mcp/mcp-custom-tools.js.map +1 -0
  228. package/dist/src/integrations/mcp/mcp-tool-search.d.ts +77 -0
  229. package/dist/src/integrations/mcp/mcp-tool-search.d.ts.map +1 -0
  230. package/dist/src/integrations/mcp/mcp-tool-search.js +220 -0
  231. package/dist/src/integrations/mcp/mcp-tool-search.js.map +1 -0
  232. package/dist/src/integrations/mcp/mcp-tool-validator.d.ts +60 -0
  233. package/dist/src/integrations/mcp/mcp-tool-validator.d.ts.map +1 -0
  234. package/dist/src/integrations/mcp/mcp-tool-validator.js +139 -0
  235. package/dist/src/integrations/mcp/mcp-tool-validator.js.map +1 -0
  236. package/dist/src/integrations/persistence/codebase-repository.d.ts +45 -0
  237. package/dist/src/integrations/persistence/codebase-repository.d.ts.map +1 -0
  238. package/dist/src/integrations/persistence/codebase-repository.js +85 -0
  239. package/dist/src/integrations/persistence/codebase-repository.js.map +1 -0
  240. package/dist/src/integrations/persistence/goal-repository.d.ts +71 -0
  241. package/dist/src/integrations/persistence/goal-repository.d.ts.map +1 -0
  242. package/dist/src/integrations/persistence/goal-repository.js +187 -0
  243. package/dist/src/integrations/persistence/goal-repository.js.map +1 -0
  244. package/dist/src/integrations/persistence/history.d.ts +72 -0
  245. package/dist/src/integrations/persistence/history.d.ts.map +1 -0
  246. package/dist/src/integrations/persistence/history.js +163 -0
  247. package/dist/src/integrations/persistence/history.js.map +1 -0
  248. package/dist/src/integrations/persistence/persistence.d.ts +49 -0
  249. package/dist/src/integrations/persistence/persistence.d.ts.map +1 -0
  250. package/dist/src/integrations/persistence/persistence.js +200 -0
  251. package/dist/src/integrations/persistence/persistence.js.map +1 -0
  252. package/dist/src/integrations/persistence/session-repository.d.ts +212 -0
  253. package/dist/src/integrations/persistence/session-repository.d.ts.map +1 -0
  254. package/dist/src/integrations/persistence/session-repository.js +781 -0
  255. package/dist/src/integrations/persistence/session-repository.js.map +1 -0
  256. package/dist/src/integrations/persistence/session-store.d.ts +184 -0
  257. package/dist/src/integrations/persistence/session-store.d.ts.map +1 -0
  258. package/dist/src/integrations/persistence/session-store.js +346 -0
  259. package/dist/src/integrations/persistence/session-store.js.map +1 -0
  260. package/dist/src/integrations/persistence/sqlite-store.d.ts +453 -0
  261. package/dist/src/integrations/persistence/sqlite-store.d.ts.map +1 -0
  262. package/dist/src/integrations/persistence/sqlite-store.js +680 -0
  263. package/dist/src/integrations/persistence/sqlite-store.js.map +1 -0
  264. package/dist/src/integrations/persistence/worker-repository.d.ts +65 -0
  265. package/dist/src/integrations/persistence/worker-repository.d.ts.map +1 -0
  266. package/dist/src/integrations/persistence/worker-repository.js +181 -0
  267. package/dist/src/integrations/persistence/worker-repository.js.map +1 -0
  268. package/dist/src/integrations/quality/auto-checkpoint.d.ts +98 -0
  269. package/dist/src/integrations/quality/auto-checkpoint.d.ts.map +1 -0
  270. package/dist/src/integrations/quality/auto-checkpoint.js +250 -0
  271. package/dist/src/integrations/quality/auto-checkpoint.js.map +1 -0
  272. package/dist/src/integrations/quality/dead-letter-queue.d.ts +233 -0
  273. package/dist/src/integrations/quality/dead-letter-queue.d.ts.map +1 -0
  274. package/dist/src/integrations/quality/dead-letter-queue.js +549 -0
  275. package/dist/src/integrations/quality/dead-letter-queue.js.map +1 -0
  276. package/dist/src/integrations/quality/health-check.d.ts +218 -0
  277. package/dist/src/integrations/quality/health-check.d.ts.map +1 -0
  278. package/dist/src/integrations/quality/health-check.js +418 -0
  279. package/dist/src/integrations/quality/health-check.js.map +1 -0
  280. package/dist/src/integrations/quality/learning-store.d.ts +291 -0
  281. package/dist/src/integrations/quality/learning-store.d.ts.map +1 -0
  282. package/dist/src/integrations/quality/learning-store.js +723 -0
  283. package/dist/src/integrations/quality/learning-store.js.map +1 -0
  284. package/dist/src/integrations/quality/self-improvement.d.ts +90 -0
  285. package/dist/src/integrations/quality/self-improvement.d.ts.map +1 -0
  286. package/dist/src/integrations/quality/self-improvement.js +229 -0
  287. package/dist/src/integrations/quality/self-improvement.js.map +1 -0
  288. package/dist/src/integrations/quality/tool-recommendation.d.ts +61 -0
  289. package/dist/src/integrations/quality/tool-recommendation.d.ts.map +1 -0
  290. package/dist/src/integrations/quality/tool-recommendation.js +298 -0
  291. package/dist/src/integrations/quality/tool-recommendation.js.map +1 -0
  292. package/dist/src/integrations/safety/bash-policy.d.ts +33 -0
  293. package/dist/src/integrations/safety/bash-policy.d.ts.map +1 -0
  294. package/dist/src/integrations/safety/bash-policy.js +147 -0
  295. package/dist/src/integrations/safety/bash-policy.js.map +1 -0
  296. package/dist/src/integrations/safety/edit-validator.d.ts +30 -0
  297. package/dist/src/integrations/safety/edit-validator.d.ts.map +1 -0
  298. package/dist/src/integrations/safety/edit-validator.js +87 -0
  299. package/dist/src/integrations/safety/edit-validator.js.map +1 -0
  300. package/dist/src/integrations/safety/execution-policy.d.ts +189 -0
  301. package/dist/src/integrations/safety/execution-policy.d.ts.map +1 -0
  302. package/dist/src/integrations/safety/execution-policy.js +362 -0
  303. package/dist/src/integrations/safety/execution-policy.js.map +1 -0
  304. package/dist/src/integrations/safety/policy-engine.d.ts +55 -0
  305. package/dist/src/integrations/safety/policy-engine.d.ts.map +1 -0
  306. package/dist/src/integrations/safety/policy-engine.js +287 -0
  307. package/dist/src/integrations/safety/policy-engine.js.map +1 -0
  308. package/dist/src/integrations/safety/safety.d.ts +174 -0
  309. package/dist/src/integrations/safety/safety.d.ts.map +1 -0
  310. package/dist/src/integrations/safety/safety.js +473 -0
  311. package/dist/src/integrations/safety/safety.js.map +1 -0
  312. package/dist/src/integrations/safety/sandbox/basic.d.ts +81 -0
  313. package/dist/src/integrations/safety/sandbox/basic.d.ts.map +1 -0
  314. package/dist/src/integrations/safety/sandbox/basic.js +333 -0
  315. package/dist/src/integrations/safety/sandbox/basic.js.map +1 -0
  316. package/dist/src/integrations/safety/sandbox/docker.d.ts +94 -0
  317. package/dist/src/integrations/safety/sandbox/docker.d.ts.map +1 -0
  318. package/dist/src/integrations/safety/sandbox/docker.js +294 -0
  319. package/dist/src/integrations/safety/sandbox/docker.js.map +1 -0
  320. package/dist/src/integrations/safety/sandbox/index.d.ts +188 -0
  321. package/dist/src/integrations/safety/sandbox/index.d.ts.map +1 -0
  322. package/dist/src/integrations/safety/sandbox/index.js +410 -0
  323. package/dist/src/integrations/safety/sandbox/index.js.map +1 -0
  324. package/dist/src/integrations/safety/sandbox/landlock.d.ts +59 -0
  325. package/dist/src/integrations/safety/sandbox/landlock.d.ts.map +1 -0
  326. package/dist/src/integrations/safety/sandbox/landlock.js +333 -0
  327. package/dist/src/integrations/safety/sandbox/landlock.js.map +1 -0
  328. package/dist/src/integrations/safety/sandbox/seatbelt.d.ts +68 -0
  329. package/dist/src/integrations/safety/sandbox/seatbelt.d.ts.map +1 -0
  330. package/dist/src/integrations/safety/sandbox/seatbelt.js +291 -0
  331. package/dist/src/integrations/safety/sandbox/seatbelt.js.map +1 -0
  332. package/dist/src/integrations/safety/type-checker.d.ts +53 -0
  333. package/dist/src/integrations/safety/type-checker.d.ts.map +1 -0
  334. package/dist/src/integrations/safety/type-checker.js +146 -0
  335. package/dist/src/integrations/safety/type-checker.js.map +1 -0
  336. package/dist/src/integrations/skills/skill-executor.d.ts +113 -0
  337. package/dist/src/integrations/skills/skill-executor.d.ts.map +1 -0
  338. package/dist/src/integrations/skills/skill-executor.js +266 -0
  339. package/dist/src/integrations/skills/skill-executor.js.map +1 -0
  340. package/dist/src/integrations/skills/skills.d.ts +262 -0
  341. package/dist/src/integrations/skills/skills.d.ts.map +1 -0
  342. package/dist/src/integrations/skills/skills.js +611 -0
  343. package/dist/src/integrations/skills/skills.js.map +1 -0
  344. package/dist/src/integrations/streaming/pty-shell.d.ts +169 -0
  345. package/dist/src/integrations/streaming/pty-shell.d.ts.map +1 -0
  346. package/dist/src/integrations/streaming/pty-shell.js +371 -0
  347. package/dist/src/integrations/streaming/pty-shell.js.map +1 -0
  348. package/dist/src/integrations/streaming/streaming.d.ts +102 -0
  349. package/dist/src/integrations/streaming/streaming.d.ts.map +1 -0
  350. package/dist/src/integrations/streaming/streaming.js +364 -0
  351. package/dist/src/integrations/streaming/streaming.js.map +1 -0
  352. package/dist/src/integrations/swarm/failure-classifier.d.ts.map +1 -1
  353. package/dist/src/integrations/swarm/failure-classifier.js +18 -3
  354. package/dist/src/integrations/swarm/failure-classifier.js.map +1 -1
  355. package/dist/src/integrations/swarm/index.d.ts +6 -5
  356. package/dist/src/integrations/swarm/index.d.ts.map +1 -1
  357. package/dist/src/integrations/swarm/index.js +5 -3
  358. package/dist/src/integrations/swarm/index.js.map +1 -1
  359. package/dist/src/integrations/swarm/model-selector.d.ts.map +1 -1
  360. package/dist/src/integrations/swarm/model-selector.js +21 -24
  361. package/dist/src/integrations/swarm/model-selector.js.map +1 -1
  362. package/dist/src/integrations/swarm/request-throttle.d.ts.map +1 -1
  363. package/dist/src/integrations/swarm/request-throttle.js +7 -4
  364. package/dist/src/integrations/swarm/request-throttle.js.map +1 -1
  365. package/dist/src/integrations/swarm/swarm-budget.d.ts +1 -1
  366. package/dist/src/integrations/swarm/swarm-budget.d.ts.map +1 -1
  367. package/dist/src/integrations/swarm/swarm-budget.js +1 -1
  368. package/dist/src/integrations/swarm/swarm-budget.js.map +1 -1
  369. package/dist/src/integrations/swarm/swarm-config-loader.d.ts.map +1 -1
  370. package/dist/src/integrations/swarm/swarm-config-loader.js +53 -17
  371. package/dist/src/integrations/swarm/swarm-config-loader.js.map +1 -1
  372. package/dist/src/integrations/swarm/swarm-event-bridge.d.ts.map +1 -1
  373. package/dist/src/integrations/swarm/swarm-event-bridge.js +69 -23
  374. package/dist/src/integrations/swarm/swarm-event-bridge.js.map +1 -1
  375. package/dist/src/integrations/swarm/swarm-events.d.ts +1 -1
  376. package/dist/src/integrations/swarm/swarm-events.d.ts.map +1 -1
  377. package/dist/src/integrations/swarm/swarm-events.js +1 -1
  378. package/dist/src/integrations/swarm/swarm-events.js.map +1 -1
  379. package/dist/src/integrations/swarm/swarm-execution.d.ts +27 -0
  380. package/dist/src/integrations/swarm/swarm-execution.d.ts.map +1 -0
  381. package/dist/src/integrations/swarm/swarm-execution.js +1071 -0
  382. package/dist/src/integrations/swarm/swarm-execution.js.map +1 -0
  383. package/dist/src/integrations/swarm/swarm-helpers.d.ts +26 -0
  384. package/dist/src/integrations/swarm/swarm-helpers.d.ts.map +1 -0
  385. package/dist/src/integrations/swarm/swarm-helpers.js +108 -0
  386. package/dist/src/integrations/swarm/swarm-helpers.js.map +1 -0
  387. package/dist/src/integrations/swarm/swarm-lifecycle.d.ts +100 -0
  388. package/dist/src/integrations/swarm/swarm-lifecycle.d.ts.map +1 -0
  389. package/dist/src/integrations/swarm/swarm-lifecycle.js +977 -0
  390. package/dist/src/integrations/swarm/swarm-lifecycle.js.map +1 -0
  391. package/dist/src/integrations/swarm/swarm-orchestrator.d.ts +84 -203
  392. package/dist/src/integrations/swarm/swarm-orchestrator.d.ts.map +1 -1
  393. package/dist/src/integrations/swarm/swarm-orchestrator.js +338 -2899
  394. package/dist/src/integrations/swarm/swarm-orchestrator.js.map +1 -1
  395. package/dist/src/integrations/swarm/swarm-quality-gate.d.ts.map +1 -1
  396. package/dist/src/integrations/swarm/swarm-quality-gate.js +19 -15
  397. package/dist/src/integrations/swarm/swarm-quality-gate.js.map +1 -1
  398. package/dist/src/integrations/swarm/swarm-recovery.d.ts +75 -0
  399. package/dist/src/integrations/swarm/swarm-recovery.d.ts.map +1 -0
  400. package/dist/src/integrations/swarm/swarm-recovery.js +563 -0
  401. package/dist/src/integrations/swarm/swarm-recovery.js.map +1 -0
  402. package/dist/src/integrations/swarm/swarm-state-store.d.ts.map +1 -1
  403. package/dist/src/integrations/swarm/swarm-state-store.js +8 -0
  404. package/dist/src/integrations/swarm/swarm-state-store.js.map +1 -1
  405. package/dist/src/integrations/swarm/task-queue.d.ts +8 -2
  406. package/dist/src/integrations/swarm/task-queue.d.ts.map +1 -1
  407. package/dist/src/integrations/swarm/task-queue.js +60 -26
  408. package/dist/src/integrations/swarm/task-queue.js.map +1 -1
  409. package/dist/src/integrations/swarm/types.d.ts +17 -5
  410. package/dist/src/integrations/swarm/types.d.ts.map +1 -1
  411. package/dist/src/integrations/swarm/types.js +89 -12
  412. package/dist/src/integrations/swarm/types.js.map +1 -1
  413. package/dist/src/integrations/swarm/worker-pool.d.ts +1 -1
  414. package/dist/src/integrations/swarm/worker-pool.d.ts.map +1 -1
  415. package/dist/src/integrations/swarm/worker-pool.js +43 -31
  416. package/dist/src/integrations/swarm/worker-pool.js.map +1 -1
  417. package/dist/src/integrations/tasks/dependency-analyzer.d.ts +34 -0
  418. package/dist/src/integrations/tasks/dependency-analyzer.d.ts.map +1 -0
  419. package/dist/src/integrations/tasks/dependency-analyzer.js +231 -0
  420. package/dist/src/integrations/tasks/dependency-analyzer.js.map +1 -0
  421. package/dist/src/integrations/tasks/interactive-planning.d.ts +322 -0
  422. package/dist/src/integrations/tasks/interactive-planning.d.ts.map +1 -0
  423. package/dist/src/integrations/tasks/interactive-planning.js +648 -0
  424. package/dist/src/integrations/tasks/interactive-planning.js.map +1 -0
  425. package/dist/src/integrations/tasks/pending-plan.d.ts +196 -0
  426. package/dist/src/integrations/tasks/pending-plan.d.ts.map +1 -0
  427. package/dist/src/integrations/tasks/pending-plan.js +431 -0
  428. package/dist/src/integrations/tasks/pending-plan.js.map +1 -0
  429. package/dist/src/integrations/tasks/planning.d.ts +115 -0
  430. package/dist/src/integrations/tasks/planning.d.ts.map +1 -0
  431. package/dist/src/integrations/tasks/planning.js +432 -0
  432. package/dist/src/integrations/tasks/planning.js.map +1 -0
  433. package/dist/src/integrations/tasks/smart-decomposer.d.ts +316 -0
  434. package/dist/src/integrations/tasks/smart-decomposer.d.ts.map +1 -0
  435. package/dist/src/integrations/tasks/smart-decomposer.js +668 -0
  436. package/dist/src/integrations/tasks/smart-decomposer.js.map +1 -0
  437. package/dist/src/integrations/tasks/task-manager.d.ts +164 -0
  438. package/dist/src/integrations/tasks/task-manager.d.ts.map +1 -0
  439. package/dist/src/integrations/tasks/task-manager.js +390 -0
  440. package/dist/src/integrations/tasks/task-manager.js.map +1 -0
  441. package/dist/src/integrations/tasks/task-splitter.d.ts +56 -0
  442. package/dist/src/integrations/tasks/task-splitter.d.ts.map +1 -0
  443. package/dist/src/integrations/tasks/task-splitter.js +542 -0
  444. package/dist/src/integrations/tasks/task-splitter.js.map +1 -0
  445. package/dist/src/integrations/tasks/verification-gate.d.ts +103 -0
  446. package/dist/src/integrations/tasks/verification-gate.d.ts.map +1 -0
  447. package/dist/src/integrations/tasks/verification-gate.js +195 -0
  448. package/dist/src/integrations/tasks/verification-gate.js.map +1 -0
  449. package/dist/src/integrations/tasks/work-log.d.ts +87 -0
  450. package/dist/src/integrations/tasks/work-log.d.ts.map +1 -0
  451. package/dist/src/integrations/tasks/work-log.js +287 -0
  452. package/dist/src/integrations/tasks/work-log.js.map +1 -0
  453. package/dist/src/integrations/utilities/capabilities.d.ts +160 -0
  454. package/dist/src/integrations/utilities/capabilities.d.ts.map +1 -0
  455. package/dist/src/integrations/utilities/capabilities.js +464 -0
  456. package/dist/src/integrations/utilities/capabilities.js.map +1 -0
  457. package/dist/src/integrations/utilities/diff-utils.d.ts +105 -0
  458. package/dist/src/integrations/utilities/diff-utils.d.ts.map +1 -0
  459. package/dist/src/integrations/utilities/diff-utils.js +496 -0
  460. package/dist/src/integrations/utilities/diff-utils.js.map +1 -0
  461. package/dist/src/integrations/utilities/environment-facts.d.ts +52 -0
  462. package/dist/src/integrations/utilities/environment-facts.d.ts.map +1 -0
  463. package/dist/src/integrations/utilities/environment-facts.js +94 -0
  464. package/dist/src/integrations/utilities/environment-facts.js.map +1 -0
  465. package/dist/src/integrations/utilities/file-change-tracker.d.ts +162 -0
  466. package/dist/src/integrations/utilities/file-change-tracker.d.ts.map +1 -0
  467. package/dist/src/integrations/utilities/file-change-tracker.js +537 -0
  468. package/dist/src/integrations/utilities/file-change-tracker.js.map +1 -0
  469. package/dist/src/integrations/utilities/graph-visualization.d.ts +72 -0
  470. package/dist/src/integrations/utilities/graph-visualization.d.ts.map +1 -0
  471. package/dist/src/integrations/utilities/graph-visualization.js +385 -0
  472. package/dist/src/integrations/utilities/graph-visualization.js.map +1 -0
  473. package/dist/src/integrations/utilities/hierarchical-config.d.ts +215 -0
  474. package/dist/src/integrations/utilities/hierarchical-config.d.ts.map +1 -0
  475. package/dist/src/integrations/utilities/hierarchical-config.js +508 -0
  476. package/dist/src/integrations/utilities/hierarchical-config.js.map +1 -0
  477. package/dist/src/integrations/utilities/hooks.d.ts +116 -0
  478. package/dist/src/integrations/utilities/hooks.d.ts.map +1 -0
  479. package/dist/src/integrations/utilities/hooks.js +410 -0
  480. package/dist/src/integrations/utilities/hooks.js.map +1 -0
  481. package/dist/src/integrations/utilities/ignore.d.ts +143 -0
  482. package/dist/src/integrations/utilities/ignore.d.ts.map +1 -0
  483. package/dist/src/integrations/utilities/ignore.js +417 -0
  484. package/dist/src/integrations/utilities/ignore.js.map +1 -0
  485. package/dist/src/integrations/utilities/image-renderer.d.ts +119 -0
  486. package/dist/src/integrations/utilities/image-renderer.d.ts.map +1 -0
  487. package/dist/src/integrations/utilities/image-renderer.js +301 -0
  488. package/dist/src/integrations/utilities/image-renderer.js.map +1 -0
  489. package/dist/src/integrations/utilities/logger.d.ts +104 -0
  490. package/dist/src/integrations/utilities/logger.d.ts.map +1 -0
  491. package/dist/src/integrations/utilities/logger.js +217 -0
  492. package/dist/src/integrations/utilities/logger.js.map +1 -0
  493. package/dist/src/integrations/utilities/memory.d.ts +116 -0
  494. package/dist/src/integrations/utilities/memory.d.ts.map +1 -0
  495. package/dist/src/integrations/utilities/memory.js +309 -0
  496. package/dist/src/integrations/utilities/memory.js.map +1 -0
  497. package/dist/src/integrations/utilities/observability.d.ts +162 -0
  498. package/dist/src/integrations/utilities/observability.d.ts.map +1 -0
  499. package/dist/src/integrations/utilities/observability.js +408 -0
  500. package/dist/src/integrations/utilities/observability.js.map +1 -0
  501. package/dist/src/integrations/utilities/openrouter-pricing.d.ts +67 -0
  502. package/dist/src/integrations/utilities/openrouter-pricing.d.ts.map +1 -0
  503. package/dist/src/integrations/utilities/openrouter-pricing.js +166 -0
  504. package/dist/src/integrations/utilities/openrouter-pricing.js.map +1 -0
  505. package/dist/src/integrations/utilities/react.d.ts +139 -0
  506. package/dist/src/integrations/utilities/react.d.ts.map +1 -0
  507. package/dist/src/integrations/utilities/react.js +269 -0
  508. package/dist/src/integrations/utilities/react.js.map +1 -0
  509. package/dist/src/integrations/utilities/retry.d.ts +132 -0
  510. package/dist/src/integrations/utilities/retry.d.ts.map +1 -0
  511. package/dist/src/integrations/utilities/retry.js +233 -0
  512. package/dist/src/integrations/utilities/retry.js.map +1 -0
  513. package/dist/src/integrations/utilities/routing.d.ts +118 -0
  514. package/dist/src/integrations/utilities/routing.d.ts.map +1 -0
  515. package/dist/src/integrations/utilities/routing.js +360 -0
  516. package/dist/src/integrations/utilities/routing.js.map +1 -0
  517. package/dist/src/integrations/utilities/rules.d.ts +131 -0
  518. package/dist/src/integrations/utilities/rules.d.ts.map +1 -0
  519. package/dist/src/integrations/utilities/rules.js +282 -0
  520. package/dist/src/integrations/utilities/rules.js.map +1 -0
  521. package/dist/src/integrations/utilities/sourcegraph.d.ts +169 -0
  522. package/dist/src/integrations/utilities/sourcegraph.d.ts.map +1 -0
  523. package/dist/src/integrations/utilities/sourcegraph.js +377 -0
  524. package/dist/src/integrations/utilities/sourcegraph.js.map +1 -0
  525. package/dist/src/integrations/utilities/thinking-strategy.d.ts +52 -0
  526. package/dist/src/integrations/utilities/thinking-strategy.d.ts.map +1 -0
  527. package/dist/src/integrations/utilities/thinking-strategy.js +129 -0
  528. package/dist/src/integrations/utilities/thinking-strategy.js.map +1 -0
  529. package/dist/src/integrations/utilities/thread-manager.d.ts +199 -0
  530. package/dist/src/integrations/utilities/thread-manager.d.ts.map +1 -0
  531. package/dist/src/integrations/utilities/thread-manager.js +359 -0
  532. package/dist/src/integrations/utilities/thread-manager.js.map +1 -0
  533. package/dist/src/integrations/utilities/token-estimate.d.ts +16 -0
  534. package/dist/src/integrations/utilities/token-estimate.d.ts.map +1 -0
  535. package/dist/src/integrations/utilities/token-estimate.js +20 -0
  536. package/dist/src/integrations/utilities/token-estimate.js.map +1 -0
  537. package/dist/src/main.js +50 -27
  538. package/dist/src/main.js.map +1 -1
  539. package/dist/src/modes/repl.d.ts.map +1 -1
  540. package/dist/src/modes/repl.js +73 -22
  541. package/dist/src/modes/repl.js.map +1 -1
  542. package/dist/src/modes/tui.d.ts.map +1 -1
  543. package/dist/src/modes/tui.js +93 -16
  544. package/dist/src/modes/tui.js.map +1 -1
  545. package/dist/src/modes.d.ts.map +1 -1
  546. package/dist/src/modes.js +14 -14
  547. package/dist/src/modes.js.map +1 -1
  548. package/dist/src/observability/tracer.d.ts.map +1 -1
  549. package/dist/src/observability/tracer.js +8 -4
  550. package/dist/src/observability/tracer.js.map +1 -1
  551. package/dist/src/observability/types.d.ts.map +1 -1
  552. package/dist/src/observability/types.js.map +1 -1
  553. package/dist/src/paths.d.ts.map +1 -1
  554. package/dist/src/paths.js +2 -6
  555. package/dist/src/paths.js.map +1 -1
  556. package/dist/src/persistence/migrator.d.ts.map +1 -1
  557. package/dist/src/persistence/migrator.js +7 -7
  558. package/dist/src/persistence/migrator.js.map +1 -1
  559. package/dist/src/persistence/schema.d.ts +2 -0
  560. package/dist/src/persistence/schema.d.ts.map +1 -1
  561. package/dist/src/persistence/schema.js +31 -0
  562. package/dist/src/persistence/schema.js.map +1 -1
  563. package/dist/src/providers/adapters/anthropic.d.ts +6 -0
  564. package/dist/src/providers/adapters/anthropic.d.ts.map +1 -1
  565. package/dist/src/providers/adapters/anthropic.js +132 -36
  566. package/dist/src/providers/adapters/anthropic.js.map +1 -1
  567. package/dist/src/providers/adapters/azure.d.ts +74 -0
  568. package/dist/src/providers/adapters/azure.d.ts.map +1 -0
  569. package/dist/src/providers/adapters/azure.js +369 -0
  570. package/dist/src/providers/adapters/azure.js.map +1 -0
  571. package/dist/src/providers/adapters/mock.d.ts +16 -2
  572. package/dist/src/providers/adapters/mock.d.ts.map +1 -1
  573. package/dist/src/providers/adapters/mock.js +51 -10
  574. package/dist/src/providers/adapters/mock.js.map +1 -1
  575. package/dist/src/providers/adapters/openai.d.ts +6 -1
  576. package/dist/src/providers/adapters/openai.d.ts.map +1 -1
  577. package/dist/src/providers/adapters/openai.js +57 -19
  578. package/dist/src/providers/adapters/openai.js.map +1 -1
  579. package/dist/src/providers/adapters/openrouter.d.ts +6 -0
  580. package/dist/src/providers/adapters/openrouter.d.ts.map +1 -1
  581. package/dist/src/providers/adapters/openrouter.js +127 -30
  582. package/dist/src/providers/adapters/openrouter.js.map +1 -1
  583. package/dist/src/providers/circuit-breaker.d.ts.map +1 -1
  584. package/dist/src/providers/circuit-breaker.js +4 -3
  585. package/dist/src/providers/circuit-breaker.js.map +1 -1
  586. package/dist/src/providers/fallback-chain.d.ts.map +1 -1
  587. package/dist/src/providers/fallback-chain.js +3 -3
  588. package/dist/src/providers/fallback-chain.js.map +1 -1
  589. package/dist/src/providers/llm-resilience.d.ts.map +1 -1
  590. package/dist/src/providers/llm-resilience.js +2 -2
  591. package/dist/src/providers/llm-resilience.js.map +1 -1
  592. package/dist/src/providers/provider.d.ts.map +1 -1
  593. package/dist/src/providers/provider.js +2 -3
  594. package/dist/src/providers/provider.js.map +1 -1
  595. package/dist/src/providers/resilient-fetch.d.ts.map +1 -1
  596. package/dist/src/providers/resilient-fetch.js +3 -4
  597. package/dist/src/providers/resilient-fetch.js.map +1 -1
  598. package/dist/src/providers/resilient-provider.d.ts.map +1 -1
  599. package/dist/src/providers/resilient-provider.js +9 -6
  600. package/dist/src/providers/resilient-provider.js.map +1 -1
  601. package/dist/src/providers/types.d.ts +23 -2
  602. package/dist/src/providers/types.d.ts.map +1 -1
  603. package/dist/src/session-picker.d.ts +1 -1
  604. package/dist/src/session-picker.d.ts.map +1 -1
  605. package/dist/src/session-picker.js +10 -6
  606. package/dist/src/session-picker.js.map +1 -1
  607. package/dist/src/shared/budget-tracker.d.ts.map +1 -1
  608. package/dist/src/shared/budget-tracker.js +2 -2
  609. package/dist/src/shared/budget-tracker.js.map +1 -1
  610. package/dist/src/shared/context-engine.d.ts.map +1 -1
  611. package/dist/src/shared/context-engine.js +1 -1
  612. package/dist/src/shared/context-engine.js.map +1 -1
  613. package/dist/src/shared/persistence.d.ts.map +1 -1
  614. package/dist/src/shared/persistence.js +2 -6
  615. package/dist/src/shared/persistence.js.map +1 -1
  616. package/dist/src/shared/shared-context-state.d.ts.map +1 -1
  617. package/dist/src/shared/shared-context-state.js.map +1 -1
  618. package/dist/src/shared/shared-economics-state.d.ts.map +1 -1
  619. package/dist/src/shared/shared-economics-state.js.map +1 -1
  620. package/dist/src/tools/agent.d.ts +2 -2
  621. package/dist/src/tools/agent.d.ts.map +1 -1
  622. package/dist/src/tools/agent.js +10 -7
  623. package/dist/src/tools/agent.js.map +1 -1
  624. package/dist/src/tools/bash.d.ts.map +1 -1
  625. package/dist/src/tools/bash.js +1 -1
  626. package/dist/src/tools/bash.js.map +1 -1
  627. package/dist/src/tools/coercion.js +1 -1
  628. package/dist/src/tools/coercion.js.map +1 -1
  629. package/dist/src/tools/file.d.ts.map +1 -1
  630. package/dist/src/tools/file.js +2 -2
  631. package/dist/src/tools/file.js.map +1 -1
  632. package/dist/src/tools/permission.js +7 -8
  633. package/dist/src/tools/permission.js.map +1 -1
  634. package/dist/src/tools/registry.d.ts +1 -1
  635. package/dist/src/tools/registry.d.ts.map +1 -1
  636. package/dist/src/tools/registry.js +4 -6
  637. package/dist/src/tools/registry.js.map +1 -1
  638. package/dist/src/tools/standard.d.ts.map +1 -1
  639. package/dist/src/tools/standard.js +1 -3
  640. package/dist/src/tools/standard.js.map +1 -1
  641. package/dist/src/tools/tasks.d.ts +1 -1
  642. package/dist/src/tools/tasks.d.ts.map +1 -1
  643. package/dist/src/tools/tasks.js +4 -4
  644. package/dist/src/tools/tasks.js.map +1 -1
  645. package/dist/src/tools/types.d.ts.map +1 -1
  646. package/dist/src/tools/types.js +5 -1
  647. package/dist/src/tools/types.js.map +1 -1
  648. package/dist/src/tools/undo.d.ts +1 -1
  649. package/dist/src/tools/undo.d.ts.map +1 -1
  650. package/dist/src/tools/undo.js +4 -2
  651. package/dist/src/tools/undo.js.map +1 -1
  652. package/dist/src/tracing/cache-boundary-tracker.d.ts.map +1 -1
  653. package/dist/src/tracing/cache-boundary-tracker.js +9 -13
  654. package/dist/src/tracing/cache-boundary-tracker.js.map +1 -1
  655. package/dist/src/tracing/trace-collector.d.ts +22 -0
  656. package/dist/src/tracing/trace-collector.d.ts.map +1 -1
  657. package/dist/src/tracing/trace-collector.js +55 -31
  658. package/dist/src/tracing/trace-collector.js.map +1 -1
  659. package/dist/src/tracing/types.d.ts +17 -1
  660. package/dist/src/tracing/types.d.ts.map +1 -1
  661. package/dist/src/tracing/types.js.map +1 -1
  662. package/dist/src/tricks/failure-evidence.d.ts.map +1 -1
  663. package/dist/src/tricks/failure-evidence.js +17 -27
  664. package/dist/src/tricks/failure-evidence.js.map +1 -1
  665. package/dist/src/tricks/json-utils.d.ts.map +1 -1
  666. package/dist/src/tricks/json-utils.js +1 -4
  667. package/dist/src/tricks/json-utils.js.map +1 -1
  668. package/dist/src/tricks/kv-cache-context.d.ts.map +1 -1
  669. package/dist/src/tricks/kv-cache-context.js +2 -3
  670. package/dist/src/tricks/kv-cache-context.js.map +1 -1
  671. package/dist/src/tricks/recitation.d.ts.map +1 -1
  672. package/dist/src/tricks/recitation.js +24 -19
  673. package/dist/src/tricks/recitation.js.map +1 -1
  674. package/dist/src/tricks/recursive-context.d.ts.map +1 -1
  675. package/dist/src/tricks/recursive-context.js +10 -7
  676. package/dist/src/tricks/recursive-context.js.map +1 -1
  677. package/dist/src/tricks/reversible-compaction.d.ts.map +1 -1
  678. package/dist/src/tricks/reversible-compaction.js +17 -9
  679. package/dist/src/tricks/reversible-compaction.js.map +1 -1
  680. package/dist/src/tricks/serialization-diversity.d.ts.map +1 -1
  681. package/dist/src/tricks/serialization-diversity.js +12 -12
  682. package/dist/src/tricks/serialization-diversity.js.map +1 -1
  683. package/dist/src/tui/app.d.ts +9 -5
  684. package/dist/src/tui/app.d.ts.map +1 -1
  685. package/dist/src/tui/app.js +690 -565
  686. package/dist/src/tui/app.js.map +1 -1
  687. package/dist/src/tui/components/ActiveAgentsPanel.d.ts +2 -0
  688. package/dist/src/tui/components/ActiveAgentsPanel.d.ts.map +1 -1
  689. package/dist/src/tui/components/ActiveAgentsPanel.js +5 -5
  690. package/dist/src/tui/components/ActiveAgentsPanel.js.map +1 -1
  691. package/dist/src/tui/components/ApprovalDialog.d.ts.map +1 -1
  692. package/dist/src/tui/components/ApprovalDialog.js +14 -0
  693. package/dist/src/tui/components/ApprovalDialog.js.map +1 -1
  694. package/dist/src/tui/components/BudgetExtensionDialog.d.ts +18 -0
  695. package/dist/src/tui/components/BudgetExtensionDialog.d.ts.map +1 -0
  696. package/dist/src/tui/components/BudgetExtensionDialog.js +40 -0
  697. package/dist/src/tui/components/BudgetExtensionDialog.js.map +1 -0
  698. package/dist/src/tui/components/CollapsibleDiffView.d.ts +1 -1
  699. package/dist/src/tui/components/CollapsibleDiffView.d.ts.map +1 -1
  700. package/dist/src/tui/components/CollapsibleDiffView.js +18 -13
  701. package/dist/src/tui/components/CollapsibleDiffView.js.map +1 -1
  702. package/dist/src/tui/components/DebugPanel.d.ts.map +1 -1
  703. package/dist/src/tui/components/DebugPanel.js +46 -26
  704. package/dist/src/tui/components/DebugPanel.js.map +1 -1
  705. package/dist/src/tui/components/DiagnosticsPanel.d.ts +24 -0
  706. package/dist/src/tui/components/DiagnosticsPanel.d.ts.map +1 -0
  707. package/dist/src/tui/components/DiagnosticsPanel.js +63 -0
  708. package/dist/src/tui/components/DiagnosticsPanel.js.map +1 -0
  709. package/dist/src/tui/components/DiffView.d.ts +1 -1
  710. package/dist/src/tui/components/DiffView.d.ts.map +1 -1
  711. package/dist/src/tui/components/DiffView.js +21 -14
  712. package/dist/src/tui/components/DiffView.js.map +1 -1
  713. package/dist/src/tui/components/ErrorBoundary.d.ts.map +1 -1
  714. package/dist/src/tui/components/ErrorBoundary.js +8 -3
  715. package/dist/src/tui/components/ErrorBoundary.js.map +1 -1
  716. package/dist/src/tui/components/ErrorDetailPanel.d.ts.map +1 -1
  717. package/dist/src/tui/components/ErrorDetailPanel.js +4 -4
  718. package/dist/src/tui/components/ErrorDetailPanel.js.map +1 -1
  719. package/dist/src/tui/components/FileChangeSummary.d.ts.map +1 -1
  720. package/dist/src/tui/components/FileChangeSummary.js +3 -3
  721. package/dist/src/tui/components/FileChangeSummary.js.map +1 -1
  722. package/dist/src/tui/components/InputArea.d.ts.map +1 -1
  723. package/dist/src/tui/components/InputArea.js +32 -15
  724. package/dist/src/tui/components/InputArea.js.map +1 -1
  725. package/dist/src/tui/components/LearningValidationDialog.d.ts +25 -0
  726. package/dist/src/tui/components/LearningValidationDialog.d.ts.map +1 -0
  727. package/dist/src/tui/components/LearningValidationDialog.js +35 -0
  728. package/dist/src/tui/components/LearningValidationDialog.js.map +1 -0
  729. package/dist/src/tui/components/MessageItem.d.ts.map +1 -1
  730. package/dist/src/tui/components/MessageItem.js.map +1 -1
  731. package/dist/src/tui/components/PlanPanel.d.ts +27 -0
  732. package/dist/src/tui/components/PlanPanel.d.ts.map +1 -0
  733. package/dist/src/tui/components/PlanPanel.js +45 -0
  734. package/dist/src/tui/components/PlanPanel.js.map +1 -0
  735. package/dist/src/tui/components/ScrollableBox.d.ts.map +1 -1
  736. package/dist/src/tui/components/ScrollableBox.js +2 -2
  737. package/dist/src/tui/components/ScrollableBox.js.map +1 -1
  738. package/dist/src/tui/components/SideBySideDiff.d.ts.map +1 -1
  739. package/dist/src/tui/components/SideBySideDiff.js +20 -18
  740. package/dist/src/tui/components/SideBySideDiff.js.map +1 -1
  741. package/dist/src/tui/components/StatusBar.d.ts +41 -0
  742. package/dist/src/tui/components/StatusBar.d.ts.map +1 -0
  743. package/dist/src/tui/components/StatusBar.js +114 -0
  744. package/dist/src/tui/components/StatusBar.js.map +1 -0
  745. package/dist/src/tui/components/SwarmStatusPanel.d.ts.map +1 -1
  746. package/dist/src/tui/components/SwarmStatusPanel.js +25 -17
  747. package/dist/src/tui/components/SwarmStatusPanel.js.map +1 -1
  748. package/dist/src/tui/components/TasksPanel.d.ts +1 -1
  749. package/dist/src/tui/components/TasksPanel.d.ts.map +1 -1
  750. package/dist/src/tui/components/TasksPanel.js +12 -11
  751. package/dist/src/tui/components/TasksPanel.js.map +1 -1
  752. package/dist/src/tui/components/ToolCallItem.d.ts.map +1 -1
  753. package/dist/src/tui/components/ToolCallItem.js +19 -6
  754. package/dist/src/tui/components/ToolCallItem.js.map +1 -1
  755. package/dist/src/tui/components/ToolCallsPanel.d.ts +15 -0
  756. package/dist/src/tui/components/ToolCallsPanel.d.ts.map +1 -0
  757. package/dist/src/tui/components/ToolCallsPanel.js +34 -0
  758. package/dist/src/tui/components/ToolCallsPanel.js.map +1 -0
  759. package/dist/src/tui/components/TransparencyPanel.d.ts +15 -0
  760. package/dist/src/tui/components/TransparencyPanel.d.ts.map +1 -0
  761. package/dist/src/tui/components/TransparencyPanel.js +46 -0
  762. package/dist/src/tui/components/TransparencyPanel.js.map +1 -0
  763. package/dist/src/tui/components/index.d.ts +8 -2
  764. package/dist/src/tui/components/index.d.ts.map +1 -1
  765. package/dist/src/tui/components/index.js +14 -2
  766. package/dist/src/tui/components/index.js.map +1 -1
  767. package/dist/src/tui/event-display.d.ts.map +1 -1
  768. package/dist/src/tui/event-display.js +13 -4
  769. package/dist/src/tui/event-display.js.map +1 -1
  770. package/dist/src/tui/hooks/index.d.ts +1 -0
  771. package/dist/src/tui/hooks/index.d.ts.map +1 -1
  772. package/dist/src/tui/hooks/index.js +1 -0
  773. package/dist/src/tui/hooks/index.js.map +1 -1
  774. package/dist/src/tui/hooks/use-agent-events.d.ts +53 -0
  775. package/dist/src/tui/hooks/use-agent-events.d.ts.map +1 -0
  776. package/dist/src/tui/hooks/use-agent-events.js +444 -0
  777. package/dist/src/tui/hooks/use-agent-events.js.map +1 -0
  778. package/dist/src/tui/hooks/use-throttled-state.d.ts +18 -0
  779. package/dist/src/tui/hooks/use-throttled-state.d.ts.map +1 -0
  780. package/dist/src/tui/hooks/use-throttled-state.js +93 -0
  781. package/dist/src/tui/hooks/use-throttled-state.js.map +1 -0
  782. package/dist/src/tui/hooks/useMessagePruning.d.ts.map +1 -1
  783. package/dist/src/tui/hooks/useMessagePruning.js.map +1 -1
  784. package/dist/src/tui/index.d.ts +2 -2
  785. package/dist/src/tui/index.d.ts.map +1 -1
  786. package/dist/src/tui/index.js +102 -7
  787. package/dist/src/tui/index.js.map +1 -1
  788. package/dist/src/tui/input/CommandPalette.d.ts.map +1 -1
  789. package/dist/src/tui/input/CommandPalette.js +2 -2
  790. package/dist/src/tui/input/CommandPalette.js.map +1 -1
  791. package/dist/src/tui/input/index.d.ts +1 -1
  792. package/dist/src/tui/input/index.d.ts.map +1 -1
  793. package/dist/src/tui/input/index.js +1 -1
  794. package/dist/src/tui/input/index.js.map +1 -1
  795. package/dist/src/tui/syntax/languages/bash.js +94 -16
  796. package/dist/src/tui/syntax/languages/bash.js.map +1 -1
  797. package/dist/src/tui/syntax/languages/javascript.js +65 -12
  798. package/dist/src/tui/syntax/languages/javascript.js.map +1 -1
  799. package/dist/src/tui/syntax/languages/json.js.map +1 -1
  800. package/dist/src/tui/syntax/languages/python.js +81 -15
  801. package/dist/src/tui/syntax/languages/python.js.map +1 -1
  802. package/dist/src/tui/theme/index.js.map +1 -1
  803. package/dist/src/tui/transparency-aggregator.d.ts +13 -0
  804. package/dist/src/tui/transparency-aggregator.d.ts.map +1 -1
  805. package/dist/src/tui/transparency-aggregator.js +39 -4
  806. package/dist/src/tui/transparency-aggregator.js.map +1 -1
  807. package/dist/src/tui/types.d.ts.map +1 -1
  808. package/dist/src/tui/types.js.map +1 -1
  809. package/dist/src/tui/utils/keyboard.d.ts.map +1 -1
  810. package/dist/src/tui/utils/keyboard.js.map +1 -1
  811. package/dist/src/types.d.ts +39 -2
  812. package/dist/src/types.d.ts.map +1 -1
  813. package/package.json +1 -1
@@ -8,21 +8,43 @@
8
8
  * resilience handling, tool execution, and compaction.
9
9
  */
10
10
  import { isFeatureEnabled } from '../defaults.js';
11
+ import { estimateTokenCount, estimateTokensFromCharCount } from '../integrations/utilities/token-estimate.js';
11
12
  import { callLLM } from './response-handler.js';
12
13
  import { executeToolCalls } from './tool-executor.js';
13
14
  import { TIMEOUT_WRAPUP_PROMPT, stableStringify, } from '../integrations/index.js';
14
15
  import { detectIncompleteActionResponse } from './completion-analyzer.js';
15
16
  export { detectIncompleteActionResponse } from './completion-analyzer.js';
16
- import { createComponentLogger } from '../integrations/logger.js';
17
- import { validateSyntax } from '../integrations/edit-validator.js';
17
+ import { createComponentLogger } from '../integrations/utilities/logger.js';
18
+ import { validateSyntax } from '../integrations/safety/edit-validator.js';
19
+ import { runTypeCheck, formatTypeCheckNudge } from '../integrations/safety/type-checker.js';
20
+ import { invalidateAST } from '../integrations/context/codebase-ast.js';
18
21
  import * as fs from 'node:fs';
19
22
  const log = createComponentLogger('ExecutionLoop');
20
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
+ // =============================================================================
21
43
  // HELPER FUNCTIONS (extracted from ProductionAgent private methods)
22
44
  // =============================================================================
23
45
  /**
24
46
  * Estimate total tokens in a message array.
25
- * Uses ~4 chars per token heuristic for fast estimation.
47
+ * Delegates to the shared token estimation utility (~3.5 chars/token).
26
48
  */
27
49
  export function estimateContextTokens(messages) {
28
50
  let totalChars = 0;
@@ -37,14 +59,13 @@ export function estimateContextTokens(messages) {
37
59
  }
38
60
  }
39
61
  }
40
- return Math.ceil(totalChars / 4);
62
+ return estimateTokensFromCharCount(totalChars);
41
63
  }
42
64
  /**
43
65
  * Compact tool outputs to save context.
44
66
  */
45
67
  export function compactToolOutputs(messages) {
46
- const COMPACT_PREVIEW_LENGTH = 200;
47
- const MAX_PRESERVED_EXPENSIVE_RESULTS = 6;
68
+ const { COMPACT_PREVIEW_LENGTH, MAX_PRESERVED_EXPENSIVE_RESULTS } = EXECUTION_LOOP_DEFAULTS;
48
69
  let compactedCount = 0;
49
70
  let savedChars = 0;
50
71
  const preservedExpensiveIndexes = messages
@@ -66,7 +87,10 @@ export function compactToolOutputs(messages) {
66
87
  }
67
88
  }
68
89
  if (compactedCount > 0 && process.env.DEBUG) {
69
- log.debug('Compacted tool outputs', { compactedCount, savedTokens: Math.round(savedChars / 4) });
90
+ log.debug('Compacted tool outputs', {
91
+ compactedCount,
92
+ savedTokens: estimateTokensFromCharCount(savedChars),
93
+ });
70
94
  }
71
95
  }
72
96
  /**
@@ -83,21 +107,303 @@ export function isRequestedArtifactMissing(requestedArtifact, executedToolNames)
83
107
  if (!requestedArtifact)
84
108
  return false;
85
109
  const artifactWriteTools = ['write_file', 'edit_file', 'apply_patch', 'append_file'];
86
- return !artifactWriteTools.some(toolName => executedToolNames.has(toolName));
110
+ return !artifactWriteTools.some((toolName) => executedToolNames.has(toolName));
87
111
  }
88
112
  function getOpenTaskSummary(ctx) {
89
113
  if (!ctx.taskManager)
90
114
  return undefined;
91
115
  const tasks = ctx.taskManager.list();
92
- const pending = tasks.filter(t => t.status === 'pending').length;
93
- const inProgress = tasks.filter(t => t.status === 'in_progress').length;
94
- 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;
95
119
  return { pending, inProgress, blocked };
96
120
  }
97
121
  function getPendingWithOwnerCount(ctx) {
98
122
  if (!ctx.taskManager)
99
123
  return 0;
100
- 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;
101
407
  }
102
408
  // =============================================================================
103
409
  // MAIN EXECUTION LOOP
@@ -132,12 +438,8 @@ export async function executeDirectly(task, messages, ctx, mutators) {
132
438
  const reflectionConfig = ctx.config.reflection;
133
439
  const reflectionEnabled = isFeatureEnabled(reflectionConfig);
134
440
  const autoReflect = reflectionEnabled && reflectionConfig.autoReflect;
135
- const maxReflectionAttempts = reflectionEnabled
136
- ? (reflectionConfig.maxAttempts || 3)
137
- : 1;
138
- const confidenceThreshold = reflectionEnabled
139
- ? (reflectionConfig.confidenceThreshold || 0.8)
140
- : 0.8;
441
+ const maxReflectionAttempts = reflectionEnabled ? reflectionConfig.maxAttempts || 3 : 1;
442
+ const confidenceThreshold = reflectionEnabled ? reflectionConfig.confidenceThreshold || 0.8 : 0.8;
141
443
  let reflectionAttempt = 0;
142
444
  let lastResponse = '';
143
445
  let incompleteActionRetries = 0;
@@ -191,142 +493,33 @@ export async function executeDirectly(task, messages, ctx, mutators) {
191
493
  }
192
494
  }
193
495
  // =======================================================================
194
- // ECONOMICS CHECK (Token Budget)
496
+ // ECONOMICS CHECK (Token Budget) — delegated to checkIterationBudget()
195
497
  // =======================================================================
196
498
  let forceTextOnly = false;
197
499
  let budgetInjectedPrompt;
198
- if (ctx.economics) {
199
- const budgetCheck = ctx.economics.checkBudget();
200
- forceTextOnly = budgetCheck.forceTextOnly ?? false;
201
- budgetInjectedPrompt = budgetCheck.injectedPrompt;
202
- if (!budgetCheck.canContinue) {
203
- // RECOVERY ATTEMPT: Try emergency context reduction
204
- const isTokenLimit = budgetCheck.budgetType === 'tokens' || budgetCheck.budgetType === 'cost';
205
- const alreadyTriedRecovery = ctx.state._recoveryAttempted === true;
206
- if (isTokenLimit && !alreadyTriedRecovery) {
207
- ctx.observability?.logger?.info('Budget limit reached, attempting recovery via context reduction', {
208
- reason: budgetCheck.reason,
209
- percentUsed: budgetCheck.percentUsed,
210
- });
211
- ctx.emit({
212
- type: 'resilience.retry',
213
- reason: 'budget_limit_compaction',
214
- attempt: 1,
215
- maxAttempts: 1,
216
- });
217
- ctx.state.metrics.retryCount = (ctx.state.metrics.retryCount ?? 0) + 1;
218
- ctx.state._recoveryAttempted = true;
219
- const tokensBefore = estimateContextTokens(messages);
220
- // Step 1: Compact tool outputs aggressively
221
- compactToolOutputs(ctx.state.messages);
222
- // Step 2: Emergency truncation - keep system + last N messages
223
- const PRESERVE_RECENT = 10;
224
- if (messages.length > PRESERVE_RECENT + 2) {
225
- const systemMessage = messages.find(m => m.role === 'system');
226
- const recentMessages = messages.slice(-(PRESERVE_RECENT));
227
- messages.length = 0;
228
- if (systemMessage) {
229
- messages.push(systemMessage);
230
- }
231
- messages.push({
232
- role: 'system',
233
- content: `[CONTEXT REDUCED: Earlier messages were removed to stay within budget. Conversation continues from recent context.]`,
234
- });
235
- messages.push(...recentMessages);
236
- // Inject work log after emergency truncation
237
- if (ctx.workLog?.hasContent()) {
238
- const workLogMessage = {
239
- role: 'user',
240
- content: ctx.workLog.toCompactString(),
241
- };
242
- messages.push(workLogMessage);
243
- }
244
- // Update state messages too
245
- ctx.state.messages.length = 0;
246
- ctx.state.messages.push(...messages);
247
- }
248
- const tokensAfter = estimateContextTokens(messages);
249
- const reduction = Math.round((1 - tokensAfter / tokensBefore) * 100);
250
- if (tokensAfter < tokensBefore * 0.8) {
251
- ctx.observability?.logger?.info('Context reduction successful, continuing execution', {
252
- tokensBefore,
253
- tokensAfter,
254
- reduction,
255
- });
256
- ctx.emit({
257
- type: 'resilience.recovered',
258
- reason: 'budget_limit_compaction',
259
- attempts: 1,
260
- });
261
- ctx.emit({
262
- type: 'compaction.auto',
263
- tokensBefore,
264
- tokensAfter,
265
- messagesCompacted: tokensBefore - tokensAfter,
266
- });
267
- continue;
268
- }
269
- ctx.observability?.logger?.warn('Context reduction insufficient', {
270
- tokensBefore,
271
- tokensAfter,
272
- reduction,
273
- });
274
- }
275
- // Hard limit reached and recovery failed
276
- ctx.observability?.logger?.warn('Budget limit reached', {
277
- reason: budgetCheck.reason,
278
- budgetType: budgetCheck.budgetType,
279
- });
280
- if (budgetCheck.budgetType === 'iterations') {
281
- const totalIter = ctx.getTotalIterations();
282
- const iterMsg = ctx.parentIterations > 0
283
- ? `${ctx.state.iteration} + ${ctx.parentIterations} parent = ${totalIter}`
284
- : `${ctx.state.iteration}`;
285
- const reason = `Max iterations reached (${iterMsg})`;
286
- ctx.emit({ type: 'error', error: reason });
287
- result = {
288
- success: false,
289
- terminationReason: 'max_iterations',
290
- failureReason: reason,
291
- };
292
- }
293
- else {
294
- const reason = budgetCheck.reason || 'Budget exceeded';
295
- ctx.emit({ type: 'error', error: reason });
296
- result = {
297
- success: false,
298
- terminationReason: 'budget_limit',
299
- failureReason: reason,
300
- };
301
- }
302
- break;
303
- }
304
- // Check for soft limits and potential extension
305
- if (budgetCheck.isSoftLimit && budgetCheck.suggestedAction === 'request_extension') {
306
- ctx.observability?.logger?.info('Approaching budget limit', {
307
- reason: budgetCheck.reason,
308
- percentUsed: budgetCheck.percentUsed,
309
- });
310
- }
500
+ let budgetAllowsTaskContinuation = true;
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;
311
518
  }
312
519
  else {
313
- // Fallback to simple iteration check
314
- if (ctx.getTotalIterations() >= ctx.config.maxIterations) {
315
- const totalIter = ctx.getTotalIterations();
316
- const reason = `Max iterations reached (${totalIter})`;
317
- ctx.observability?.logger?.warn('Max iterations reached', {
318
- iteration: ctx.state.iteration,
319
- parentIterations: ctx.parentIterations,
320
- total: totalIter,
321
- });
322
- ctx.emit({ type: 'error', error: reason });
323
- result = {
324
- success: false,
325
- terminationReason: 'max_iterations',
326
- failureReason: reason,
327
- };
328
- break;
329
- }
520
+ forceTextOnly = budgetResult.forceTextOnly;
521
+ budgetInjectedPrompt = budgetResult.budgetInjectedPrompt;
522
+ budgetAllowsTaskContinuation = budgetResult.budgetAllowsTaskContinuation;
330
523
  }
331
524
  // =======================================================================
332
525
  // GRACEFUL WRAPUP CHECK
@@ -372,15 +565,17 @@ export async function executeDirectly(task, messages, ctx, mutators) {
372
565
  }
373
566
  const enrichedMessages = ctx.contextEngineering.injectRecitation(messages, {
374
567
  goal: task,
375
- plan: ctx.state.plan ? {
376
- description: ctx.state.plan.goal || task,
377
- tasks: ctx.state.plan.tasks.map(t => ({
378
- id: t.id,
379
- description: t.description,
380
- status: t.status,
381
- })),
382
- currentTaskIndex: ctx.state.plan.tasks.findIndex(t => t.status === 'in_progress'),
383
- } : 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,
384
579
  activeFiles: ctx.economics?.getProgress().filesModified
385
580
  ? [`${ctx.economics.getProgress().filesModified} files modified`]
386
581
  : undefined,
@@ -388,7 +583,9 @@ export async function executeDirectly(task, messages, ctx, mutators) {
388
583
  });
389
584
  if (process.env.DEBUG_LLM) {
390
585
  if (process.env.DEBUG)
391
- log.debug('Recitation after', { messageCount: enrichedMessages?.length ?? 'null/undefined' });
586
+ log.debug('Recitation after', {
587
+ messageCount: enrichedMessages?.length ?? 'null/undefined',
588
+ });
392
589
  }
393
590
  if (enrichedMessages && enrichedMessages !== messages && enrichedMessages.length > 0) {
394
591
  messages.length = 0;
@@ -397,7 +594,7 @@ export async function executeDirectly(task, messages, ctx, mutators) {
397
594
  else if (!enrichedMessages || enrichedMessages.length === 0) {
398
595
  log.warn('Recitation returned empty/null messages, keeping original');
399
596
  }
400
- const contextTokens = messages.reduce((sum, m) => sum + (m.content?.length || 0) / 4, 0);
597
+ const contextTokens = estimateContextTokens(messages);
401
598
  ctx.contextEngineering.updateRecitationFrequency(contextTokens);
402
599
  }
403
600
  // =======================================================================
@@ -424,7 +621,9 @@ export async function executeDirectly(task, messages, ctx, mutators) {
424
621
  // =======================================================================
425
622
  // RESUME ORIENTATION — after compaction, nudge the agent to act, not re-summarize
426
623
  // =======================================================================
427
- 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'));
428
627
  if (hasCompactionSummary && ctx.state.iteration <= 2) {
429
628
  messages.push({
430
629
  role: 'user',
@@ -437,31 +636,48 @@ export async function executeDirectly(task, messages, ctx, mutators) {
437
636
  if (ctx.injectionBudget) {
438
637
  const proposals = [];
439
638
  if (budgetInjectedPrompt) {
440
- 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
+ });
441
645
  }
442
646
  if (ctx.contextEngineering) {
443
647
  const failureCtx = ctx.contextEngineering.getFailureContext(5);
444
648
  if (failureCtx) {
445
- 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
+ });
446
655
  }
447
656
  }
448
657
  if (proposals.length > 0) {
449
658
  const accepted = ctx.injectionBudget.allocate(proposals);
450
659
  const stats = ctx.injectionBudget.getLastStats();
451
660
  if (stats && stats.droppedNames.length > 0 && process.env.DEBUG) {
452
- 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
+ });
453
666
  }
454
667
  if (stats && process.env.DEBUG_LLM) {
455
- 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
+ });
456
674
  }
457
675
  }
458
676
  }
459
677
  // =======================================================================
460
678
  // RESILIENT LLM CALL
461
679
  // =======================================================================
462
- const resilienceConfig = typeof ctx.config.resilience === 'object'
463
- ? ctx.config.resilience
464
- : {};
680
+ const resilienceConfig = typeof ctx.config.resilience === 'object' ? ctx.config.resilience : {};
465
681
  const resilienceEnabled = isFeatureEnabled(ctx.config.resilience);
466
682
  const MAX_EMPTY_RETRIES = resilienceConfig.maxEmptyRetries ?? 2;
467
683
  const MAX_CONTINUATIONS = resilienceConfig.maxContinuations ?? 3;
@@ -475,6 +691,7 @@ export async function executeDirectly(task, messages, ctx, mutators) {
475
691
  const estimatedInputTokens = estimateContextTokens(messages);
476
692
  const currentUsage = ctx.economics.getUsage();
477
693
  const budget = ctx.economics.getBudget();
694
+ const isStrictEnforcement = (budget.enforcementMode ?? 'strict') === 'strict';
478
695
  // Use proportional output estimate: 10% of remaining budget, capped at 4096, floored at 512.
479
696
  // The old hardcoded 4096 caused premature wrapup for subagents with smaller budgets.
480
697
  const remainingTokens = budget.maxTokens - currentUsage.tokens - estimatedInputTokens;
@@ -486,21 +703,67 @@ export async function executeDirectly(task, messages, ctx, mutators) {
486
703
  estimatedInput: estimatedInputTokens,
487
704
  projectedTotal,
488
705
  maxTokens: budget.maxTokens,
706
+ enforcementMode: budget.enforcementMode ?? 'strict',
489
707
  });
490
- if (!budgetInjectedPrompt) {
491
- messages.push({
492
- role: 'user',
493
- content: '[System] BUDGET CRITICAL: This is your LAST response. Summarize findings concisely and stop. Do NOT call tools.',
494
- });
495
- ctx.state.messages.push({
496
- role: 'user',
497
- content: '[System] BUDGET CRITICAL: This is your LAST response. Summarize findings concisely and stop. Do NOT call tools.',
498
- });
708
+ // Only force text-only in strict mode. In doomloop_only mode,
709
+ // the pre-flight check warns but does not kill the agent.
710
+ // NEVER force text-only on the first iteration — an agent that hasn't
711
+ // made a single tool call yet should always get at least one chance.
712
+ // This prevents swarm workers from being killed before they can work.
713
+ if (isStrictEnforcement && ctx.state.iteration > 1) {
714
+ if (!budgetInjectedPrompt) {
715
+ messages.push({
716
+ role: 'user',
717
+ content: '[System] BUDGET CRITICAL: This is your LAST response. Summarize findings concisely and stop. Do NOT call tools.',
718
+ });
719
+ ctx.state.messages.push({
720
+ role: 'user',
721
+ content: '[System] BUDGET CRITICAL: This is your LAST response. Summarize findings concisely and stop. Do NOT call tools.',
722
+ });
723
+ }
724
+ forceTextOnly = true;
499
725
  }
500
- forceTextOnly = true;
726
+ }
727
+ }
728
+ // EARLY EXIT: When forceTextOnly is set but task continuation is allowed,
729
+ // skip the expensive LLM call (whose tool calls would be discarded) and
730
+ // go directly to the task continuation gate. Only allowed once per
731
+ // forceTextOnly episode to prevent tight loops.
732
+ if (forceTextOnly &&
733
+ budgetAllowsTaskContinuation &&
734
+ ctx.taskManager &&
735
+ !ctx.state._lastSkippedLLMIteration) {
736
+ const availableTasks = ctx.taskManager.getAvailableTasks();
737
+ if (availableTasks.length > 0) {
738
+ log.info('Skipping LLM call — forceTextOnly with tasks available, going to task continuation', {
739
+ availableTasks: availableTasks.length,
740
+ iteration: ctx.state.iteration,
741
+ });
742
+ // Mark that we skipped so we don't skip again on the next iteration
743
+ ctx.state._lastSkippedLLMIteration =
744
+ ctx.state.iteration;
745
+ // Reset forceTextOnly for the next iteration so the task can run normally
746
+ forceTextOnly = false;
747
+ const nextTask = availableTasks[0];
748
+ ctx.taskManager.claim(nextTask.id, ctx.agentId);
749
+ const taskPrompt = {
750
+ role: 'user',
751
+ content: `[System] Budget warning noted. Continuing with next task:\n\n**Task ${nextTask.id}: ${nextTask.subject}**\n${nextTask.description}\n\nStart working on this task now using your tools.`,
752
+ };
753
+ messages.push(taskPrompt);
754
+ ctx.state.messages.push(taskPrompt);
755
+ ctx.emit({
756
+ type: 'iteration.after',
757
+ iteration: ctx.state.iteration,
758
+ hadToolCalls: false,
759
+ completionCandidate: false,
760
+ });
761
+ continue; // Re-enter main loop for next task without wasting an LLM call
501
762
  }
502
763
  }
503
764
  let response = await callLLM(messages, ctx);
765
+ // Clear the LLM-skip guard now that we've made a real LLM call
766
+ delete ctx.state._lastSkippedLLMIteration;
504
767
  let emptyRetries = 0;
505
768
  let continuations = 0;
506
769
  // Phase 1: Handle empty responses with retry
@@ -570,7 +833,10 @@ export async function executeDirectly(task, messages, ctx, mutators) {
570
833
  response = await callLLM(messages, ctx);
571
834
  }
572
835
  // Phase 2: Handle max_tokens truncation with continuation
573
- 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) {
574
840
  let accumulatedContent = response.content || '';
575
841
  while (continuations < MAX_CONTINUATIONS && response.stopReason === 'max_tokens') {
576
842
  continuations++;
@@ -614,10 +880,10 @@ export async function executeDirectly(task, messages, ctx, mutators) {
614
880
  if (resilienceEnabled && response.stopReason === 'max_tokens' && response.toolCalls?.length) {
615
881
  ctx.emit({
616
882
  type: 'resilience.truncated_tool_call',
617
- toolNames: response.toolCalls.map(tc => tc.name),
883
+ toolNames: response.toolCalls.map((tc) => tc.name),
618
884
  });
619
885
  ctx.observability?.logger?.warn('Tool call truncated at max_tokens', {
620
- toolNames: response.toolCalls.map(tc => tc.name),
886
+ toolNames: response.toolCalls.map((tc) => tc.name),
621
887
  outputTokens: response.usage?.outputTokens,
622
888
  });
623
889
  const truncatedResponse = response;
@@ -637,7 +903,7 @@ export async function executeDirectly(task, messages, ctx, mutators) {
637
903
  }
638
904
  // Record LLM usage for economics
639
905
  if (ctx.economics && response.usage) {
640
- ctx.economics.recordLLMUsage(response.usage.inputTokens, response.usage.outputTokens, ctx.config.model, response.usage.cost);
906
+ ctx.economics.recordLLMUsage(response.usage.inputTokens, response.usage.outputTokens, ctx.config.model, response.usage.cost, response.usage.cacheReadTokens);
641
907
  // POST-LLM BUDGET CHECK
642
908
  if (!forceTextOnly) {
643
909
  const postCheck = ctx.economics.checkBudget();
@@ -660,9 +926,12 @@ export async function executeDirectly(task, messages, ctx, mutators) {
660
926
  ctx.state.messages.push(assistantMessage);
661
927
  lastResponse = response.content || (response.thinking ? response.thinking : '');
662
928
  // Plan mode: capture exploration findings
663
- if (ctx.modeManager.getMode() === 'plan' && response.content && response.content.length > 50) {
664
- const hasReadOnlyTools = response.toolCalls?.every(tc => ['read_file', 'list_files', 'glob', 'grep', 'search', 'mcp_'].some(prefix => tc.name.startsWith(prefix) || tc.name === prefix));
665
- 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)) {
666
935
  ctx.pendingPlanManager.appendExplorationFinding(response.content.slice(0, 1000));
667
936
  }
668
937
  }
@@ -683,10 +952,10 @@ export async function executeDirectly(task, messages, ctx, mutators) {
683
952
  const missingRequiredArtifact = ENFORCE_REQUESTED_ARTIFACTS
684
953
  ? isRequestedArtifactMissing(requestedArtifact, executedToolNames)
685
954
  : false;
686
- const shouldRecoverIncompleteAction = resilienceEnabled
687
- && INCOMPLETE_ACTION_RECOVERY
688
- && !forceTextOnly
689
- && (incompleteAction || missingRequiredArtifact);
955
+ const shouldRecoverIncompleteAction = resilienceEnabled &&
956
+ INCOMPLETE_ACTION_RECOVERY &&
957
+ !forceTextOnly &&
958
+ (incompleteAction || missingRequiredArtifact);
690
959
  if (shouldRecoverIncompleteAction) {
691
960
  ctx.emit({
692
961
  type: 'completion.before',
@@ -778,6 +1047,45 @@ export async function executeDirectly(task, messages, ctx, mutators) {
778
1047
  });
779
1048
  incompleteActionRetries = 0;
780
1049
  }
1050
+ // TypeScript compilation gate — block completion if TS files edited and errors exist
1051
+ if (ctx.typeCheckerState?.tsconfigDir &&
1052
+ !forceTextOnly &&
1053
+ (ctx.typeCheckerState.tsEditsSinceLastCheck > 0 || !ctx.typeCheckerState.hasRunOnce)) {
1054
+ const tscResult = await runTypeCheck(ctx.typeCheckerState.tsconfigDir);
1055
+ ctx.typeCheckerState.tsEditsSinceLastCheck = 0;
1056
+ ctx.typeCheckerState.lastResult = tscResult;
1057
+ ctx.typeCheckerState.hasRunOnce = true;
1058
+ ctx.verificationGate?.recordCompilationResult(tscResult.success, tscResult.errorCount);
1059
+ ctx.emit({
1060
+ type: 'diagnostics.tsc-check',
1061
+ errorCount: tscResult.errorCount,
1062
+ duration: tscResult.duration,
1063
+ trigger: 'completion',
1064
+ });
1065
+ if (!tscResult.success) {
1066
+ const vState = ctx.verificationGate?.getState();
1067
+ const maxCompNudges = 8;
1068
+ if (!vState || (vState.compilationNudgeCount ?? 0) < maxCompNudges) {
1069
+ const nudge = formatTypeCheckNudge(tscResult);
1070
+ const nudgeMessage = { role: 'user', content: nudge };
1071
+ messages.push(nudgeMessage);
1072
+ ctx.state.messages.push(nudgeMessage);
1073
+ ctx.verificationGate?.incrementCompilationNudge();
1074
+ log.info('Compilation gate blocked completion', {
1075
+ count: tscResult.errorCount,
1076
+ nudgeCount: ctx.verificationGate?.getState().compilationNudgeCount,
1077
+ });
1078
+ ctx.emit({
1079
+ type: 'iteration.after',
1080
+ iteration: ctx.state.iteration,
1081
+ hadToolCalls: false,
1082
+ completionCandidate: false,
1083
+ });
1084
+ continue; // Re-enter main loop — agent must fix errors
1085
+ }
1086
+ // If exceeded max nudges, fall through to verification gate (which will forceAllow)
1087
+ }
1088
+ }
781
1089
  // Verification gate
782
1090
  if (ctx.verificationGate && !forceTextOnly) {
783
1091
  const vResult = ctx.verificationGate.check();
@@ -851,7 +1159,7 @@ export async function executeDirectly(task, messages, ctx, mutators) {
851
1159
  });
852
1160
  const pendingWithOwner = getPendingWithOwnerCount(ctx);
853
1161
  const availableTasks = ctx.taskManager.getAvailableTasks();
854
- if (!forceTextOnly && availableTasks.length > 0) {
1162
+ if ((!forceTextOnly || budgetAllowsTaskContinuation) && availableTasks.length > 0) {
855
1163
  const nextTask = availableTasks[0];
856
1164
  ctx.taskManager.claim(nextTask.id, ctx.agentId);
857
1165
  log.info('Picking up next task from task list', {
@@ -896,7 +1204,9 @@ export async function executeDirectly(task, messages, ctx, mutators) {
896
1204
  }
897
1205
  const reasons = [
898
1206
  `Open tasks remain: ${openTasks.pending} pending, ${openTasks.inProgress} in_progress`,
899
- openTasks.blocked > 0 ? `${openTasks.blocked} pending tasks are currently blocked` : '',
1207
+ openTasks.blocked > 0
1208
+ ? `${openTasks.blocked} pending tasks are currently blocked`
1209
+ : '',
900
1210
  ].filter(Boolean);
901
1211
  ctx.emit({
902
1212
  type: 'completion.blocked',
@@ -926,7 +1236,7 @@ export async function executeDirectly(task, messages, ctx, mutators) {
926
1236
  log.warn('Tool call explosion detected — capping', {
927
1237
  requested: toolCalls.length,
928
1238
  cap: maxToolCallsPerResponse,
929
- toolNames: [...new Set(toolCalls.map(tc => tc.name))],
1239
+ toolNames: [...new Set(toolCalls.map((tc) => tc.name))],
930
1240
  });
931
1241
  ctx.emit({
932
1242
  type: 'safeguard.tool_call_cap',
@@ -953,7 +1263,9 @@ export async function executeDirectly(task, messages, ctx, mutators) {
953
1263
  // Record in work log
954
1264
  const toolOutput = result?.result && typeof result.result === 'object' && 'output' in result.result
955
1265
  ? String(result.result.output)
956
- : typeof result?.result === 'string' ? result.result : undefined;
1266
+ : typeof result?.result === 'string'
1267
+ ? result.result
1268
+ : undefined;
957
1269
  ctx.workLog?.recordToolExecution(toolCall.name, toolCall.arguments, toolOutput);
958
1270
  // Record in verification gate
959
1271
  if (ctx.verificationGate) {
@@ -961,9 +1273,11 @@ export async function executeDirectly(task, messages, ctx, mutators) {
961
1273
  const toolRes = result?.result;
962
1274
  const output = toolRes && typeof toolRes === 'object' && 'output' in toolRes
963
1275
  ? String(toolRes.output)
964
- : typeof toolRes === 'string' ? toolRes : '';
1276
+ : typeof toolRes === 'string'
1277
+ ? toolRes
1278
+ : '';
965
1279
  const exitCode = toolRes && typeof toolRes === 'object' && toolRes.metadata
966
- ? toolRes.metadata.exitCode ?? null
1280
+ ? (toolRes.metadata.exitCode ?? null)
967
1281
  : null;
968
1282
  ctx.verificationGate.recordBashExecution(String(toolCall.arguments.command || ''), output, exitCode);
969
1283
  }
@@ -971,201 +1285,100 @@ export async function executeDirectly(task, messages, ctx, mutators) {
971
1285
  ctx.verificationGate.recordFileChange();
972
1286
  }
973
1287
  }
974
- // Phase 5.1: Post-edit syntax validation
975
- if (['write_file', 'edit_file'].includes(toolCall.name) && result?.result && result.result.success) {
1288
+ // Phase 5.1: Post-edit syntax validation + AST cache invalidation
1289
+ if (['write_file', 'edit_file'].includes(toolCall.name) &&
1290
+ result?.result &&
1291
+ result.result.success) {
976
1292
  const filePath = String(toolCall.arguments.path || '');
977
1293
  if (filePath) {
1294
+ // Invalidate stale AST cache entry so next analysis/validation reparses
1295
+ invalidateAST(filePath);
978
1296
  try {
979
1297
  const content = toolCall.name === 'write_file'
980
1298
  ? String(toolCall.arguments.content || '')
981
1299
  : await fs.promises.readFile(filePath, 'utf-8');
1300
+ // Update codebase context first — fullReparse caches the AST tree,
1301
+ // so validateSyntax below will use the cached tree (no double-parse)
1302
+ if (ctx.codebaseContext) {
1303
+ try {
1304
+ await ctx.codebaseContext.updateFile(filePath, content);
1305
+ }
1306
+ catch {
1307
+ /* non-blocking */
1308
+ }
1309
+ }
982
1310
  const validation = validateSyntax(content, filePath);
983
1311
  if (!validation.valid && result.result && typeof result.result === 'object') {
984
1312
  const errorSummary = validation.errors
985
1313
  .slice(0, 3)
986
- .map(e => ` L${e.line}:${e.column}: ${e.message}`)
1314
+ .map((e) => ` L${e.line}:${e.column}: ${e.message}`)
987
1315
  .join('\n');
988
- result.result.output += `\n\n⚠ Syntax validation warning:\n${errorSummary}`;
1316
+ result.result.output +=
1317
+ `\n\n⚠ Syntax validation warning:\n${errorSummary}`;
1318
+ // Emit diagnostic events for each syntax error
1319
+ for (const err of validation.errors.slice(0, 5)) {
1320
+ ctx.emit({
1321
+ type: 'diagnostics.syntax-error',
1322
+ file: filePath,
1323
+ line: err.line,
1324
+ message: err.message,
1325
+ });
1326
+ }
989
1327
  }
990
1328
  }
991
1329
  catch {
992
1330
  // Validation failure is non-blocking
993
1331
  }
994
- }
995
- }
996
- }
997
- // Add tool results to messages (with truncation and proactive budget management)
998
- const MAX_TOOL_OUTPUT_CHARS = 8000;
999
- // PROACTIVE BUDGET CHECK
1000
- const currentContextTokens = estimateContextTokens(messages);
1001
- if (ctx.autoCompactionManager) {
1002
- const compactionResult = await ctx.autoCompactionManager.checkAndMaybeCompact({
1003
- currentTokens: currentContextTokens,
1004
- messages: messages,
1005
- });
1006
- if (compactionResult.status === 'compacted' && compactionResult.compactedMessages) {
1007
- if (!ctx.compactionPending) {
1008
- mutators.setCompactionPending(true);
1009
- const preCompactionMsg = {
1010
- role: 'user',
1011
- 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.',
1012
- };
1013
- messages.push(preCompactionMsg);
1014
- ctx.state.messages.push(preCompactionMsg);
1015
- ctx.observability?.logger?.info('Pre-compaction agentic turn: injected summary request');
1016
- }
1017
- else {
1018
- mutators.setCompactionPending(false);
1019
- // Pre-compaction checkpoint
1020
- // NOTE: autoCheckpoint is called via the agent's method, not directly here
1021
- // The agent wires this through the mutators pattern
1022
- // Replace messages with compacted version
1023
- messages.length = 0;
1024
- messages.push(...compactionResult.compactedMessages);
1025
- ctx.state.messages.length = 0;
1026
- ctx.state.messages.push(...compactionResult.compactedMessages);
1027
- // Inject work log after compaction
1028
- if (ctx.workLog?.hasContent()) {
1029
- const workLogMessage = {
1030
- role: 'user',
1031
- content: ctx.workLog.toCompactString(),
1032
- };
1033
- messages.push(workLogMessage);
1034
- ctx.state.messages.push(workLogMessage);
1035
- }
1036
- // Context recovery
1037
- const recoveryParts = [];
1038
- if (ctx.store) {
1039
- const goalsSummary = ctx.store.getGoalsSummary();
1040
- if (goalsSummary && goalsSummary !== 'No active goals.' && goalsSummary !== 'Goals feature not available.') {
1041
- recoveryParts.push(goalsSummary);
1042
- }
1043
- }
1044
- if (ctx.store) {
1045
- const juncturesSummary = ctx.store.getJuncturesSummary(undefined, 5);
1046
- if (juncturesSummary) {
1047
- recoveryParts.push(juncturesSummary);
1048
- }
1049
- }
1050
- if (ctx.learningStore) {
1051
- const learnings = ctx.learningStore.getLearningContext({ maxLearnings: 3 });
1052
- if (learnings) {
1053
- recoveryParts.push(learnings);
1054
- }
1055
- }
1056
- if (recoveryParts.length > 0) {
1057
- const recoveryMessage = {
1058
- role: 'user',
1059
- content: `[CONTEXT RECOVERY — Re-injected after compaction]\n\n${recoveryParts.join('\n\n')}`,
1060
- };
1061
- messages.push(recoveryMessage);
1062
- ctx.state.messages.push(recoveryMessage);
1063
- }
1064
- // Emit compaction event
1065
- const compactionTokensAfter = estimateContextTokens(messages);
1066
- const compactionRecoveryInjected = recoveryParts.length > 0;
1067
- const compactionEvent = {
1068
- type: 'context.compacted',
1069
- tokensBefore: currentContextTokens,
1070
- tokensAfter: compactionTokensAfter,
1071
- recoveryInjected: compactionRecoveryInjected,
1072
- };
1073
- ctx.emit(compactionEvent);
1074
- if (ctx.traceCollector) {
1075
- ctx.traceCollector.record({
1076
- type: 'context.compacted',
1077
- data: {
1078
- tokensBefore: currentContextTokens,
1079
- tokensAfter: compactionTokensAfter,
1080
- recoveryInjected: compactionRecoveryInjected,
1081
- },
1082
- });
1332
+ // Track .ts/.tsx edits for periodic type checking
1333
+ if (ctx.typeCheckerState?.tsconfigDir && /\.(ts|tsx)$/.test(filePath)) {
1334
+ ctx.typeCheckerState.tsEditsSinceLastCheck++;
1083
1335
  }
1084
1336
  }
1085
1337
  }
1086
- else if (compactionResult.status === 'hard_limit') {
1087
- const reason = `Context hard limit reached (${Math.round(compactionResult.ratio * 100)}% of max tokens)`;
1088
- ctx.emit({ type: 'error', error: reason });
1089
- result = {
1090
- success: false,
1091
- terminationReason: 'hard_context_limit',
1092
- failureReason: reason,
1093
- };
1094
- break;
1095
- }
1096
1338
  }
1097
- else if (ctx.economics) {
1098
- // Fallback to simple compaction
1099
- const currentUsage = ctx.economics.getUsage();
1100
- const budget = ctx.economics.getBudget();
1101
- const percentUsed = (currentUsage.tokens / budget.maxTokens) * 100;
1102
- if (percentUsed >= 70) {
1103
- ctx.observability?.logger?.info('Proactive compaction triggered', {
1104
- percentUsed: Math.round(percentUsed),
1105
- currentTokens: currentUsage.tokens,
1106
- maxTokens: budget.maxTokens,
1107
- });
1108
- compactToolOutputs(ctx.state.messages);
1109
- }
1110
- }
1111
- // SAFEGUARD: Aggregate context guard — prevent mass small results from overflowing
1112
- if (ctx.economics && toolResults.length > 10) {
1113
- const preAccumTokens = estimateContextTokens(messages);
1114
- const budget = ctx.economics.getBudget();
1115
- const availableTokens = budget.maxTokens * 0.90 - preAccumTokens;
1116
- // Estimate total result tokens
1117
- let totalResultTokens = 0;
1118
- for (const r of toolResults) {
1119
- const c = typeof r.result === 'string' ? r.result : stableStringify(r.result);
1120
- totalResultTokens += Math.ceil(Math.min(c.length, MAX_TOOL_OUTPUT_CHARS) / 4);
1121
- }
1122
- if (totalResultTokens > availableTokens && availableTokens > 0) {
1123
- log.warn('Tool results would exceed context budget — truncating batch', {
1124
- resultCount: toolResults.length,
1125
- estimatedTokens: totalResultTokens,
1126
- availableTokens: Math.round(availableTokens),
1127
- });
1128
- let tokenBudget = availableTokens;
1129
- for (let i = 0; i < toolResults.length; i++) {
1130
- const c = typeof toolResults[i].result === 'string'
1131
- ? toolResults[i].result
1132
- : stableStringify(toolResults[i].result);
1133
- const tokens = Math.ceil(Math.min(c.length, MAX_TOOL_OUTPUT_CHARS) / 4);
1134
- if (tokens > tokenBudget) {
1135
- const skipped = toolResults.length - i;
1136
- for (let j = i; j < toolResults.length; j++) {
1137
- toolResults[j] = {
1138
- callId: toolResults[j].callId,
1139
- result: `[Result omitted: context overflow guard — ${skipped} of ${toolResults.length} results skipped]`,
1140
- };
1141
- }
1142
- ctx.emit({
1143
- type: 'safeguard.context_overflow_guard',
1144
- estimatedTokens: totalResultTokens,
1145
- maxTokens: budget.maxTokens,
1146
- toolResultsSkipped: skipped,
1147
- });
1148
- break;
1149
- }
1150
- tokenBudget -= tokens;
1151
- }
1152
- }
1339
+ // Add tool results to messages (with truncation and proactive budget management)
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;
1153
1356
  }
1154
- 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]));
1155
1360
  for (const result of toolResults) {
1156
- 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);
1157
1366
  const sourceToolName = toolCallNameById.get(result.callId);
1158
1367
  const isExpensiveResult = sourceToolName === 'spawn_agent' || sourceToolName === 'spawn_agents_parallel';
1159
- 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;
1160
1371
  if (content.length > effectiveMaxChars) {
1161
- 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]`;
1162
1375
  }
1163
1376
  // Check if adding this result would exceed budget
1164
1377
  if (ctx.economics) {
1165
- const estimatedNewTokens = Math.ceil(content.length / 4);
1378
+ const estimatedNewTokens = estimateTokenCount(content);
1166
1379
  const currentCtxTokens = estimateContextTokens(messages);
1167
1380
  const budget = ctx.economics.getBudget();
1168
- if (currentCtxTokens + estimatedNewTokens > budget.maxTokens * 0.95) {
1381
+ if (currentCtxTokens + estimatedNewTokens > budget.maxTokens * EXECUTION_LOOP_DEFAULTS.PER_RESULT_BUDGET_RATIO) {
1169
1382
  ctx.observability?.logger?.warn('Skipping tool result to stay within budget', {
1170
1383
  toolCallId: result.callId,
1171
1384
  estimatedTokens: estimatedNewTokens,
@@ -1199,6 +1412,30 @@ export async function executeDirectly(task, messages, ctx, mutators) {
1199
1412
  messages.push(toolMessage);
1200
1413
  ctx.state.messages.push(toolMessage);
1201
1414
  }
1415
+ // Periodic TypeScript compilation check (every 5 TS edits)
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) {
1420
+ const tscResult = await runTypeCheck(ctx.typeCheckerState.tsconfigDir);
1421
+ ctx.typeCheckerState.tsEditsSinceLastCheck = 0;
1422
+ ctx.typeCheckerState.lastResult = tscResult;
1423
+ ctx.typeCheckerState.hasRunOnce = true;
1424
+ ctx.verificationGate?.recordCompilationResult(tscResult.success, tscResult.errorCount);
1425
+ ctx.emit({
1426
+ type: 'diagnostics.tsc-check',
1427
+ errorCount: tscResult.errorCount,
1428
+ duration: tscResult.duration,
1429
+ trigger: 'periodic',
1430
+ });
1431
+ if (!tscResult.success) {
1432
+ const nudge = formatTypeCheckNudge(tscResult);
1433
+ const infoMsg = { role: 'user', content: nudge };
1434
+ messages.push(infoMsg);
1435
+ ctx.state.messages.push(infoMsg);
1436
+ log.info('Periodic tsc check found errors', { count: tscResult.errorCount });
1437
+ }
1438
+ }
1202
1439
  // Emit context health
1203
1440
  const currentTokenEstimate = estimateContextTokens(messages);
1204
1441
  const contextLimit = ctx.getMaxContextTokens();