@compilr-dev/cli 0.5.0 → 0.5.1

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 (591) hide show
  1. package/README.md +236 -68
  2. package/dist/.tsbuildinfo.app +1 -0
  3. package/dist/.tsbuildinfo.data +1 -0
  4. package/dist/.tsbuildinfo.domain +1 -0
  5. package/dist/.tsbuildinfo.foundation +1 -0
  6. package/dist/agent.d.ts +61 -4
  7. package/dist/agent.js +241 -245
  8. package/dist/anchors/index.d.ts +1 -1
  9. package/dist/anchors/index.js +1 -1
  10. package/dist/anchors/project-anchors.d.ts +2 -2
  11. package/dist/anchors/project-anchors.js +1 -1
  12. package/dist/auth/api-client.d.ts +124 -0
  13. package/dist/auth/api-client.js +261 -0
  14. package/dist/auth/index.d.ts +172 -0
  15. package/dist/auth/index.js +545 -0
  16. package/dist/auth/storage.d.ts +52 -0
  17. package/dist/auth/storage.js +118 -0
  18. package/dist/changelog/index.d.ts +16 -0
  19. package/dist/changelog/index.js +24 -0
  20. package/dist/changelog/releases.d.ts +17 -0
  21. package/dist/changelog/releases.js +63 -0
  22. package/dist/commands-v2/handlers/auth.d.ts +10 -0
  23. package/dist/commands-v2/handlers/auth.js +118 -0
  24. package/dist/commands-v2/handlers/background.d.ts +14 -0
  25. package/dist/commands-v2/handlers/background.js +276 -0
  26. package/dist/commands-v2/handlers/context.js +266 -81
  27. package/dist/commands-v2/handlers/core.d.ts +1 -0
  28. package/dist/commands-v2/handlers/core.js +133 -8
  29. package/dist/commands-v2/handlers/debug.js +18 -0
  30. package/dist/commands-v2/handlers/delegations.d.ts +8 -0
  31. package/dist/commands-v2/handlers/delegations.js +29 -0
  32. package/dist/commands-v2/handlers/files.d.ts +8 -0
  33. package/dist/commands-v2/handlers/files.js +162 -0
  34. package/dist/commands-v2/handlers/filter.d.ts +9 -0
  35. package/dist/commands-v2/handlers/filter.js +130 -0
  36. package/dist/commands-v2/handlers/games.d.ts +7 -0
  37. package/dist/commands-v2/handlers/games.js +57 -0
  38. package/dist/commands-v2/handlers/index.d.ts +13 -0
  39. package/dist/commands-v2/handlers/index.js +39 -0
  40. package/dist/commands-v2/handlers/mcp.d.ts +8 -0
  41. package/dist/commands-v2/handlers/mcp.js +39 -0
  42. package/dist/commands-v2/handlers/notifications.d.ts +9 -0
  43. package/dist/commands-v2/handlers/notifications.js +34 -0
  44. package/dist/commands-v2/handlers/project.js +244 -23
  45. package/dist/commands-v2/handlers/reset.d.ts +11 -0
  46. package/dist/commands-v2/handlers/reset.js +118 -0
  47. package/dist/commands-v2/handlers/session.d.ts +161 -0
  48. package/dist/commands-v2/handlers/session.js +805 -0
  49. package/dist/commands-v2/handlers/settings.d.ts +2 -0
  50. package/dist/commands-v2/handlers/settings.js +217 -35
  51. package/dist/commands-v2/handlers/tasks.d.ts +5 -0
  52. package/dist/commands-v2/handlers/tasks.js +36 -0
  53. package/dist/commands-v2/handlers/team.d.ts +9 -0
  54. package/dist/commands-v2/handlers/team.js +549 -0
  55. package/dist/commands-v2/handlers/terminals.d.ts +9 -0
  56. package/dist/commands-v2/handlers/terminals.js +34 -0
  57. package/dist/commands-v2/index.d.ts +3 -2
  58. package/dist/commands-v2/index.js +4 -1
  59. package/dist/commands-v2/registry.d.ts +15 -0
  60. package/dist/commands-v2/registry.js +34 -0
  61. package/dist/commands-v2/types.d.ts +81 -3
  62. package/dist/commands.js +13 -0
  63. package/dist/compilr-diff-companion.vsix +0 -0
  64. package/dist/db/index.js +98 -4
  65. package/dist/db/repositories/document-repository.d.ts +2 -0
  66. package/dist/db/repositories/document-repository.js +5 -1
  67. package/dist/db/repositories/index.d.ts +2 -0
  68. package/dist/db/repositories/index.js +1 -0
  69. package/dist/db/repositories/plan-repository.d.ts +101 -0
  70. package/dist/db/repositories/plan-repository.js +275 -0
  71. package/dist/db/repositories/project-repository.d.ts +6 -0
  72. package/dist/db/repositories/project-repository.js +41 -0
  73. package/dist/db/repositories/work-item-repository.d.ts +15 -0
  74. package/dist/db/repositories/work-item-repository.js +69 -4
  75. package/dist/db/schema.d.ts +40 -3
  76. package/dist/db/schema.js +66 -3
  77. package/dist/episodes/index.d.ts +20 -0
  78. package/dist/episodes/index.js +27 -0
  79. package/dist/episodes/recorder.d.ts +51 -0
  80. package/dist/episodes/recorder.js +195 -0
  81. package/dist/episodes/significant-work.d.ts +21 -0
  82. package/dist/episodes/significant-work.js +56 -0
  83. package/dist/episodes/store.d.ts +38 -0
  84. package/dist/episodes/store.js +199 -0
  85. package/dist/episodes/types.d.ts +35 -0
  86. package/dist/episodes/types.js +6 -0
  87. package/dist/episodes/work-at-risk.d.ts +12 -0
  88. package/dist/episodes/work-at-risk.js +38 -0
  89. package/dist/episodes/work-summary-anchor.d.ts +23 -0
  90. package/dist/episodes/work-summary-anchor.js +73 -0
  91. package/dist/games/coins.d.ts +66 -0
  92. package/dist/games/coins.js +165 -0
  93. package/dist/games/game-base.d.ts +84 -0
  94. package/dist/games/game-base.js +204 -0
  95. package/dist/games/index.d.ts +16 -0
  96. package/dist/games/index.js +49 -0
  97. package/dist/games/scores.d.ts +69 -0
  98. package/dist/games/scores.js +191 -0
  99. package/dist/games/tetris/board.d.ts +59 -0
  100. package/dist/games/tetris/board.js +170 -0
  101. package/dist/games/tetris/index.d.ts +109 -0
  102. package/dist/games/tetris/index.js +610 -0
  103. package/dist/games/tetris/pieces.d.ts +44 -0
  104. package/dist/games/tetris/pieces.js +271 -0
  105. package/dist/games/tetris/renderer.d.ts +26 -0
  106. package/dist/games/tetris/renderer.js +77 -0
  107. package/dist/guide/guide-content.d.ts +23 -0
  108. package/dist/guide/guide-content.js +196 -0
  109. package/dist/guide/index.d.ts +8 -0
  110. package/dist/guide/index.js +7 -0
  111. package/dist/guide/shared-content.d.ts +37 -0
  112. package/dist/guide/shared-content.js +1272 -0
  113. package/dist/guide/tutorial-helpers.d.ts +57 -0
  114. package/dist/guide/tutorial-helpers.js +147 -0
  115. package/dist/handlers/ask-user-handlers.d.ts +32 -0
  116. package/dist/handlers/ask-user-handlers.js +104 -0
  117. package/dist/handlers/delegation-handlers.d.ts +34 -0
  118. package/dist/handlers/delegation-handlers.js +291 -0
  119. package/dist/handlers/permission-handler.d.ts +30 -0
  120. package/dist/handlers/permission-handler.js +205 -0
  121. package/dist/index.d.ts +11 -1
  122. package/dist/index.js +448 -271
  123. package/dist/input-handlers/memory-handler.d.ts +1 -1
  124. package/dist/input-handlers/memory-handler.js +2 -1
  125. package/dist/models/index.d.ts +10 -0
  126. package/dist/models/index.js +12 -0
  127. package/dist/models/model-registry.d.ts +38 -0
  128. package/dist/models/model-registry.js +69 -0
  129. package/dist/models/model-tiers.d.ts +28 -0
  130. package/dist/models/model-tiers.js +71 -0
  131. package/dist/models/model-validation.d.ts +25 -0
  132. package/dist/models/model-validation.js +291 -0
  133. package/dist/models/ollama-models.d.ts +73 -0
  134. package/dist/models/ollama-models.js +178 -0
  135. package/dist/models/provider-types.d.ts +6 -0
  136. package/dist/models/provider-types.js +1 -0
  137. package/dist/models/providers.d.ts +35 -0
  138. package/dist/models/providers.js +58 -0
  139. package/dist/models/types.d.ts +4 -0
  140. package/dist/models/types.js +4 -0
  141. package/dist/multi-agent/activity.d.ts +21 -0
  142. package/dist/multi-agent/activity.js +34 -0
  143. package/dist/multi-agent/agent-selection.d.ts +55 -0
  144. package/dist/multi-agent/agent-selection.js +90 -0
  145. package/dist/multi-agent/artifacts.d.ts +197 -0
  146. package/dist/multi-agent/artifacts.js +379 -0
  147. package/dist/multi-agent/checkpointer.d.ts +138 -0
  148. package/dist/multi-agent/checkpointer.js +471 -0
  149. package/dist/multi-agent/collision-utils.d.ts +16 -0
  150. package/dist/multi-agent/collision-utils.js +28 -0
  151. package/dist/multi-agent/context-resolver.d.ts +97 -0
  152. package/dist/multi-agent/context-resolver.js +316 -0
  153. package/dist/multi-agent/custom-agents.d.ts +83 -0
  154. package/dist/multi-agent/custom-agents.js +227 -0
  155. package/dist/multi-agent/delegation-tracker.d.ts +157 -0
  156. package/dist/multi-agent/delegation-tracker.js +243 -0
  157. package/dist/multi-agent/file-lock-hook.d.ts +29 -0
  158. package/dist/multi-agent/file-lock-hook.js +97 -0
  159. package/dist/multi-agent/file-locks.d.ts +58 -0
  160. package/dist/multi-agent/file-locks.js +194 -0
  161. package/dist/multi-agent/index.d.ts +24 -0
  162. package/dist/multi-agent/index.js +30 -0
  163. package/dist/multi-agent/mention-parser.d.ts +64 -0
  164. package/dist/multi-agent/mention-parser.js +146 -0
  165. package/dist/multi-agent/notification-manager.d.ts +84 -0
  166. package/dist/multi-agent/notification-manager.js +224 -0
  167. package/dist/multi-agent/pending-requests.d.ts +122 -0
  168. package/dist/multi-agent/pending-requests.js +155 -0
  169. package/dist/multi-agent/session-registry.d.ts +139 -0
  170. package/dist/multi-agent/session-registry.js +514 -0
  171. package/dist/multi-agent/shared-context.d.ts +293 -0
  172. package/dist/multi-agent/shared-context.js +671 -0
  173. package/dist/multi-agent/skill-requirements.d.ts +66 -0
  174. package/dist/multi-agent/skill-requirements.js +178 -0
  175. package/dist/multi-agent/task-assignment.d.ts +69 -0
  176. package/dist/multi-agent/task-assignment.js +123 -0
  177. package/dist/multi-agent/task-suggestion.d.ts +31 -0
  178. package/dist/multi-agent/task-suggestion.js +72 -0
  179. package/dist/multi-agent/team-agent.d.ts +201 -0
  180. package/dist/multi-agent/team-agent.js +488 -0
  181. package/dist/multi-agent/team.d.ts +286 -0
  182. package/dist/multi-agent/team.js +610 -0
  183. package/dist/multi-agent/tool-config.d.ts +110 -0
  184. package/dist/multi-agent/tool-config.js +661 -0
  185. package/dist/multi-agent/types.d.ts +211 -0
  186. package/dist/multi-agent/types.js +617 -0
  187. package/dist/prompts/plan-mode-prompt.d.ts +11 -0
  188. package/dist/prompts/plan-mode-prompt.js +95 -0
  189. package/dist/repl-helpers.js +3 -2
  190. package/dist/repl-v2.d.ts +401 -2
  191. package/dist/repl-v2.js +2577 -65
  192. package/dist/session/index.d.ts +6 -0
  193. package/dist/session/index.js +6 -0
  194. package/dist/session/project-session-manager.d.ts +158 -0
  195. package/dist/session/project-session-manager.js +650 -0
  196. package/dist/settings/index.d.ts +133 -13
  197. package/dist/settings/index.js +329 -24
  198. package/dist/settings/mcp-config.d.ts +76 -0
  199. package/dist/settings/mcp-config.js +143 -0
  200. package/dist/settings/paths.d.ts +4 -0
  201. package/dist/settings/paths.js +6 -0
  202. package/dist/shared-handlers.d.ts +62 -0
  203. package/dist/shared-handlers.js +48 -0
  204. package/dist/system-prompt/builder.d.ts +5 -0
  205. package/dist/system-prompt/builder.js +4 -0
  206. package/dist/system-prompt/index.d.ts +18 -0
  207. package/dist/system-prompt/index.js +18 -0
  208. package/dist/system-prompt/modules.d.ts +5 -0
  209. package/dist/system-prompt/modules.js +4 -0
  210. package/dist/tabbed-menu.js +2 -1
  211. package/dist/templates/compilr-md-import.d.ts +16 -0
  212. package/dist/templates/compilr-md-import.js +241 -0
  213. package/dist/templates/compilr-md.js +10 -61
  214. package/dist/templates/config-json.d.ts +1 -25
  215. package/dist/templates/index.d.ts +2 -0
  216. package/dist/templates/index.js +34 -73
  217. package/dist/tool-names.d.ts +108 -0
  218. package/dist/tool-names.js +227 -0
  219. package/dist/tools/anchor-tools.d.ts +4 -4
  220. package/dist/tools/anchor-tools.js +1 -1
  221. package/dist/tools/artifact-tools.d.ts +42 -0
  222. package/dist/tools/artifact-tools.js +328 -0
  223. package/dist/tools/ask-user-simple.d.ts +1 -1
  224. package/dist/tools/ask-user-simple.js +2 -1
  225. package/dist/tools/ask-user.d.ts +1 -1
  226. package/dist/tools/ask-user.js +2 -1
  227. package/dist/tools/backlog-wrappers.d.ts +5 -3
  228. package/dist/tools/backlog-wrappers.js +16 -1
  229. package/dist/tools/backlog.d.ts +2 -2
  230. package/dist/tools/backlog.js +1 -1
  231. package/dist/tools/db-tools.d.ts +8 -61
  232. package/dist/tools/db-tools.js +8 -13
  233. package/dist/tools/delegate-background.d.ts +27 -0
  234. package/dist/tools/delegate-background.js +115 -0
  235. package/dist/tools/delegate.d.ts +22 -0
  236. package/dist/tools/delegate.js +97 -0
  237. package/dist/tools/delegation-status.d.ts +16 -0
  238. package/dist/tools/delegation-status.js +128 -0
  239. package/dist/tools/document-db.d.ts +5 -5
  240. package/dist/tools/document-db.js +1 -1
  241. package/dist/tools/guide-tool.d.ts +12 -0
  242. package/dist/tools/guide-tool.js +59 -0
  243. package/dist/tools/handoff.d.ts +25 -0
  244. package/dist/tools/handoff.js +99 -0
  245. package/dist/tools/meta-tools.d.ts +26 -0
  246. package/dist/tools/meta-tools.js +47 -0
  247. package/dist/tools/plan-tools.d.ts +54 -0
  248. package/dist/tools/plan-tools.js +338 -0
  249. package/dist/tools/platform-adapter.d.ts +29 -0
  250. package/dist/tools/platform-adapter.js +394 -0
  251. package/dist/tools/project-db.d.ts +5 -73
  252. package/dist/tools/project-db.js +5 -336
  253. package/dist/tools/recall-work-tool.d.ts +18 -0
  254. package/dist/tools/recall-work-tool.js +82 -0
  255. package/dist/tools/workitem-db.d.ts +43 -11
  256. package/dist/tools/workitem-db.js +186 -5
  257. package/dist/tools.d.ts +67 -2
  258. package/dist/tools.js +237 -47
  259. package/dist/ui/autocomplete-controller.d.ts +42 -0
  260. package/dist/ui/autocomplete-controller.js +384 -0
  261. package/dist/ui/base/index.d.ts +1 -1
  262. package/dist/ui/base/index.js +1 -1
  263. package/dist/ui/base/overlay-base-v2.d.ts +10 -0
  264. package/dist/ui/base/overlay-base-v2.js +14 -0
  265. package/dist/ui/base/render-utils.d.ts +19 -0
  266. package/dist/ui/base/render-utils.js +25 -0
  267. package/dist/ui/base/tabbed-list-overlay-v2.d.ts +16 -1
  268. package/dist/ui/base/tabbed-list-overlay-v2.js +19 -1
  269. package/dist/ui/constants/labels.d.ts +14 -0
  270. package/dist/ui/constants/labels.js +51 -0
  271. package/dist/ui/conversation-store.d.ts +55 -0
  272. package/dist/ui/conversation-store.js +107 -0
  273. package/dist/ui/conversation.js +11 -13
  274. package/dist/ui/diff.d.ts +7 -1
  275. package/dist/ui/diff.js +85 -48
  276. package/dist/ui/ephemeral.js +3 -9
  277. package/dist/ui/file-autocomplete.d.ts +24 -0
  278. package/dist/ui/file-autocomplete.js +56 -0
  279. package/dist/ui/footer-renderer.d.ts +69 -0
  280. package/dist/ui/footer-renderer.js +431 -0
  281. package/dist/ui/footer.d.ts +74 -7
  282. package/dist/ui/footer.js +173 -16
  283. package/dist/ui/input-controller.d.ts +51 -0
  284. package/dist/ui/input-controller.js +176 -0
  285. package/dist/ui/input-prompt.d.ts +19 -0
  286. package/dist/ui/input-prompt.js +206 -14
  287. package/dist/ui/keyboard-handler.d.ts +57 -0
  288. package/dist/ui/keyboard-handler.js +557 -0
  289. package/dist/ui/live-region-facade.d.ts +42 -0
  290. package/dist/ui/live-region-facade.js +205 -0
  291. package/dist/ui/live-region.d.ts +0 -4
  292. package/dist/ui/live-region.js +6 -14
  293. package/dist/ui/mascot/renderer.d.ts +1 -1
  294. package/dist/ui/mascot/renderer.js +37 -2
  295. package/dist/ui/overlay/data/tutorial-content.d.ts +9 -0
  296. package/dist/ui/overlay/data/tutorial-content.js +9 -0
  297. package/dist/ui/overlay/data/tutorial-registry.d.ts +12 -0
  298. package/dist/ui/overlay/data/tutorial-registry.js +116 -0
  299. package/dist/ui/overlay/data/tutorial-types.d.ts +35 -0
  300. package/dist/ui/overlay/data/tutorial-types.js +6 -0
  301. package/dist/ui/overlay/data/tutorials/basics/first-conversation.d.ts +7 -0
  302. package/dist/ui/overlay/data/tutorials/basics/first-conversation.js +220 -0
  303. package/dist/ui/overlay/data/tutorials/basics/first-project.d.ts +7 -0
  304. package/dist/ui/overlay/data/tutorials/basics/first-project.js +284 -0
  305. package/dist/ui/overlay/data/tutorials/basics/navigation.d.ts +8 -0
  306. package/dist/ui/overlay/data/tutorials/basics/navigation.js +22 -0
  307. package/dist/ui/overlay/data/tutorials/basics/welcome.d.ts +7 -0
  308. package/dist/ui/overlay/data/tutorials/basics/welcome.js +174 -0
  309. package/dist/ui/overlay/data/tutorials/config/context-management.d.ts +7 -0
  310. package/dist/ui/overlay/data/tutorials/config/context-management.js +158 -0
  311. package/dist/ui/overlay/data/tutorials/config/mcp-servers.d.ts +8 -0
  312. package/dist/ui/overlay/data/tutorials/config/mcp-servers.js +155 -0
  313. package/dist/ui/overlay/data/tutorials/config/model-selection.d.ts +7 -0
  314. package/dist/ui/overlay/data/tutorials/config/model-selection.js +162 -0
  315. package/dist/ui/overlay/data/tutorials/config/permissions-safety.d.ts +7 -0
  316. package/dist/ui/overlay/data/tutorials/config/permissions-safety.js +163 -0
  317. package/dist/ui/overlay/data/tutorials/config/settings-config.d.ts +7 -0
  318. package/dist/ui/overlay/data/tutorials/config/settings-config.js +166 -0
  319. package/dist/ui/overlay/data/tutorials/planning/arch.d.ts +7 -0
  320. package/dist/ui/overlay/data/tutorials/planning/arch.js +168 -0
  321. package/dist/ui/overlay/data/tutorials/planning/backlog.d.ts +7 -0
  322. package/dist/ui/overlay/data/tutorials/planning/backlog.js +103 -0
  323. package/dist/ui/overlay/data/tutorials/planning/build.d.ts +7 -0
  324. package/dist/ui/overlay/data/tutorials/planning/build.js +173 -0
  325. package/dist/ui/overlay/data/tutorials/planning/design.d.ts +7 -0
  326. package/dist/ui/overlay/data/tutorials/planning/design.js +205 -0
  327. package/dist/ui/overlay/data/tutorials/planning/docs.d.ts +7 -0
  328. package/dist/ui/overlay/data/tutorials/planning/docs.js +143 -0
  329. package/dist/ui/overlay/data/tutorials/planning/prd.d.ts +7 -0
  330. package/dist/ui/overlay/data/tutorials/planning/prd.js +173 -0
  331. package/dist/ui/overlay/data/tutorials/planning/scaffold.d.ts +7 -0
  332. package/dist/ui/overlay/data/tutorials/planning/scaffold.js +164 -0
  333. package/dist/ui/overlay/data/tutorials/planning/sketch.d.ts +7 -0
  334. package/dist/ui/overlay/data/tutorials/planning/sketch.js +58 -0
  335. package/dist/ui/overlay/data/tutorials/projects/anchors.d.ts +7 -0
  336. package/dist/ui/overlay/data/tutorials/projects/anchors.js +248 -0
  337. package/dist/ui/overlay/data/tutorials/projects/import-project.d.ts +7 -0
  338. package/dist/ui/overlay/data/tutorials/projects/import-project.js +172 -0
  339. package/dist/ui/overlay/data/tutorials/projects/managing-projects.d.ts +8 -0
  340. package/dist/ui/overlay/data/tutorials/projects/managing-projects.js +212 -0
  341. package/dist/ui/overlay/data/tutorials/projects/new-project.d.ts +7 -0
  342. package/dist/ui/overlay/data/tutorials/projects/new-project.js +251 -0
  343. package/dist/ui/overlay/data/tutorials/projects/session-management.d.ts +7 -0
  344. package/dist/ui/overlay/data/tutorials/projects/session-management.js +169 -0
  345. package/dist/ui/overlay/data/tutorials/teams/background-execution.d.ts +7 -0
  346. package/dist/ui/overlay/data/tutorials/teams/background-execution.js +171 -0
  347. package/dist/ui/overlay/data/tutorials/teams/multi-terminal.d.ts +8 -0
  348. package/dist/ui/overlay/data/tutorials/teams/multi-terminal.js +147 -0
  349. package/dist/ui/overlay/data/tutorials/teams/task-assignment.d.ts +7 -0
  350. package/dist/ui/overlay/data/tutorials/teams/task-assignment.js +204 -0
  351. package/dist/ui/overlay/data/tutorials/teams/team-overview.d.ts +7 -0
  352. package/dist/ui/overlay/data/tutorials/teams/team-overview.js +165 -0
  353. package/dist/ui/overlay/data/tutorials/teams/working-with-agents.d.ts +7 -0
  354. package/dist/ui/overlay/data/tutorials/teams/working-with-agents.js +172 -0
  355. package/dist/ui/overlay/impl/agents-overlay-v2.js +6 -17
  356. package/dist/ui/overlay/impl/anchors-overlay-v2.js +30 -64
  357. package/dist/ui/overlay/impl/artifact-detail-overlay-v2.d.ts +43 -0
  358. package/dist/ui/overlay/impl/artifact-detail-overlay-v2.js +232 -0
  359. package/dist/ui/overlay/impl/artifact-overlay-v2.d.ts +40 -0
  360. package/dist/ui/overlay/impl/artifact-overlay-v2.js +115 -0
  361. package/dist/ui/overlay/impl/ask-user-overlay-v2.js +2 -5
  362. package/dist/ui/overlay/impl/background-overlay-v2.d.ts +40 -0
  363. package/dist/ui/overlay/impl/background-overlay-v2.js +147 -0
  364. package/dist/ui/overlay/impl/backlog-overlay-v2.d.ts +4 -1
  365. package/dist/ui/overlay/impl/backlog-overlay-v2.js +55 -16
  366. package/dist/ui/overlay/impl/changelog-overlay-v2.d.ts +44 -0
  367. package/dist/ui/overlay/impl/changelog-overlay-v2.js +165 -0
  368. package/dist/ui/overlay/impl/commands-overlay-v2.js +4 -6
  369. package/dist/ui/overlay/impl/config-overlay-v2.d.ts +12 -1
  370. package/dist/ui/overlay/impl/config-overlay-v2.js +164 -100
  371. package/dist/ui/overlay/impl/custom-agent-form-overlay-v2.d.ts +83 -0
  372. package/dist/ui/overlay/impl/custom-agent-form-overlay-v2.js +711 -0
  373. package/dist/ui/overlay/impl/dashboard-overlay-v2.d.ts +2 -0
  374. package/dist/ui/overlay/impl/dashboard-overlay-v2.js +26 -3
  375. package/dist/ui/overlay/impl/delegations-overlay-v2.d.ts +28 -0
  376. package/dist/ui/overlay/impl/delegations-overlay-v2.js +279 -0
  377. package/dist/ui/overlay/impl/docs-overlay-v2.js +12 -9
  378. package/dist/ui/overlay/impl/document-detail-overlay-v2.d.ts +7 -0
  379. package/dist/ui/overlay/impl/document-detail-overlay-v2.js +119 -78
  380. package/dist/ui/overlay/impl/filter-overlay-v2.d.ts +41 -0
  381. package/dist/ui/overlay/impl/filter-overlay-v2.js +110 -0
  382. package/dist/ui/overlay/impl/games-overlay-v2.d.ts +31 -0
  383. package/dist/ui/overlay/impl/games-overlay-v2.js +135 -0
  384. package/dist/ui/overlay/impl/help-overlay-v2.d.ts +26 -3
  385. package/dist/ui/overlay/impl/help-overlay-v2.js +20 -42
  386. package/dist/ui/overlay/impl/login-overlay-v2.d.ts +49 -0
  387. package/dist/ui/overlay/impl/login-overlay-v2.js +277 -0
  388. package/dist/ui/overlay/impl/mcp-overlay-v2.d.ts +63 -0
  389. package/dist/ui/overlay/impl/mcp-overlay-v2.js +907 -0
  390. package/dist/ui/overlay/impl/model-overlay-v2.d.ts +57 -13
  391. package/dist/ui/overlay/impl/model-overlay-v2.js +1086 -61
  392. package/dist/ui/overlay/impl/new-overlay-v2.d.ts +37 -6
  393. package/dist/ui/overlay/impl/new-overlay-v2.js +715 -65
  394. package/dist/ui/overlay/impl/notifications-overlay-v2.d.ts +20 -0
  395. package/dist/ui/overlay/impl/notifications-overlay-v2.js +116 -0
  396. package/dist/ui/overlay/impl/onboarding-wizard-overlay-v2.d.ts +76 -0
  397. package/dist/ui/overlay/impl/onboarding-wizard-overlay-v2.js +728 -0
  398. package/dist/ui/overlay/impl/pending-overlay-v2.d.ts +51 -0
  399. package/dist/ui/overlay/impl/pending-overlay-v2.js +445 -0
  400. package/dist/ui/overlay/impl/permission-overlay-v2.js +5 -5
  401. package/dist/ui/overlay/impl/permissions-overlay-v2.d.ts +85 -0
  402. package/dist/ui/overlay/impl/permissions-overlay-v2.js +820 -0
  403. package/dist/ui/overlay/impl/plan-approval-overlay-v2.d.ts +35 -0
  404. package/dist/ui/overlay/impl/plan-approval-overlay-v2.js +181 -0
  405. package/dist/ui/overlay/impl/project-edit-overlay-v2.d.ts +36 -0
  406. package/dist/ui/overlay/impl/project-edit-overlay-v2.js +195 -0
  407. package/dist/ui/overlay/impl/projects-overlay-v2.d.ts +1 -0
  408. package/dist/ui/overlay/impl/projects-overlay-v2.js +278 -44
  409. package/dist/ui/overlay/impl/reset-overlay-v2.d.ts +39 -0
  410. package/dist/ui/overlay/impl/reset-overlay-v2.js +107 -0
  411. package/dist/ui/overlay/impl/resume-overlay-v2.d.ts +60 -0
  412. package/dist/ui/overlay/impl/resume-overlay-v2.js +414 -0
  413. package/dist/ui/overlay/impl/session-mode-overlay-v2.d.ts +43 -0
  414. package/dist/ui/overlay/impl/session-mode-overlay-v2.js +124 -0
  415. package/dist/ui/overlay/impl/tasks-overlay-v2.d.ts +28 -0
  416. package/dist/ui/overlay/impl/tasks-overlay-v2.js +283 -0
  417. package/dist/ui/overlay/impl/team-overlay-v2.d.ts +86 -0
  418. package/dist/ui/overlay/impl/team-overlay-v2.js +692 -0
  419. package/dist/ui/overlay/impl/terminals-overlay-v2.d.ts +26 -0
  420. package/dist/ui/overlay/impl/terminals-overlay-v2.js +217 -0
  421. package/dist/ui/overlay/impl/tools-overlay-v2.js +3 -7
  422. package/dist/ui/overlay/impl/tutorial-overlay-v2.d.ts +30 -16
  423. package/dist/ui/overlay/impl/tutorial-overlay-v2.js +133 -956
  424. package/dist/ui/overlay/impl/workflow-overlay-v2.js +5 -1
  425. package/dist/ui/overlay/index.d.ts +20 -1
  426. package/dist/ui/overlay/index.js +19 -0
  427. package/dist/ui/overlay/types.d.ts +5 -0
  428. package/dist/ui/overlay-manager.d.ts +43 -0
  429. package/dist/ui/overlay-manager.js +238 -0
  430. package/dist/ui/overlays.js +4 -16
  431. package/dist/ui/permission-overlay.js +6 -5
  432. package/dist/ui/status-bar-controller.d.ts +33 -0
  433. package/dist/ui/status-bar-controller.js +99 -0
  434. package/dist/ui/subagent-renderer.js +3 -19
  435. package/dist/ui/terminal-autocomplete-utils.d.ts +23 -0
  436. package/dist/ui/terminal-autocomplete-utils.js +83 -0
  437. package/dist/ui/terminal-line-builders.d.ts +17 -0
  438. package/dist/ui/terminal-line-builders.js +42 -0
  439. package/dist/ui/terminal-render-item.d.ts +16 -0
  440. package/dist/ui/terminal-render-item.js +267 -0
  441. package/dist/ui/terminal-renderer.d.ts +7 -8
  442. package/dist/ui/terminal-renderer.js +7 -8
  443. package/dist/ui/terminal-types.d.ts +179 -0
  444. package/dist/ui/terminal-types.js +34 -0
  445. package/dist/ui/terminal-ui.d.ts +144 -276
  446. package/dist/ui/terminal-ui.js +384 -1861
  447. package/dist/ui/todo-zone.d.ts +19 -1
  448. package/dist/ui/todo-zone.js +71 -13
  449. package/dist/ui/tool-formatters.js +512 -1
  450. package/dist/ui/turn-metrics.d.ts +56 -0
  451. package/dist/ui/turn-metrics.js +75 -0
  452. package/dist/ui/types.d.ts +28 -0
  453. package/dist/ui/types.js +1 -0
  454. package/dist/ui/vscode-diff-ipc.d.ts +102 -0
  455. package/dist/ui/vscode-diff-ipc.js +385 -0
  456. package/dist/utils/credentials.d.ts +24 -5
  457. package/dist/utils/credentials.js +123 -9
  458. package/dist/utils/format-tokens.d.ts +13 -0
  459. package/dist/utils/format-tokens.js +18 -0
  460. package/dist/utils/git-config.d.ts +26 -0
  461. package/dist/utils/git-config.js +54 -0
  462. package/dist/utils/message-utils.d.ts +61 -0
  463. package/dist/utils/message-utils.js +72 -0
  464. package/dist/utils/model-tiers.d.ts +8 -1
  465. package/dist/utils/model-tiers.js +38 -16
  466. package/dist/utils/open-browser.d.ts +5 -0
  467. package/dist/utils/open-browser.js +32 -0
  468. package/dist/utils/path-safety.js +3 -2
  469. package/dist/utils/project-detection.d.ts +58 -0
  470. package/dist/utils/project-detection.js +424 -0
  471. package/dist/utils/project-memory.js +2 -1
  472. package/dist/utils/project-status.d.ts +2 -2
  473. package/dist/utils/startup-perf.d.ts +18 -0
  474. package/dist/utils/startup-perf.js +60 -0
  475. package/dist/utils/token-tracker.d.ts +62 -0
  476. package/dist/utils/token-tracker.js +150 -0
  477. package/dist/utils/token-types.d.ts +23 -0
  478. package/dist/utils/token-types.js +18 -0
  479. package/dist/utils/types/config-types.d.ts +32 -0
  480. package/dist/utils/types/config-types.js +8 -0
  481. package/dist/utils/update-checker.d.ts +28 -0
  482. package/dist/utils/update-checker.js +106 -0
  483. package/dist/utils/version.d.ts +7 -0
  484. package/dist/utils/version.js +10 -0
  485. package/dist/utils/vscode-detect.d.ts +39 -0
  486. package/dist/utils/vscode-detect.js +137 -0
  487. package/package.json +25 -12
  488. package/dist/commands/handler-types.d.ts +0 -68
  489. package/dist/commands/handler-types.js +0 -8
  490. package/dist/commands/handlers/agent-commands.d.ts +0 -13
  491. package/dist/commands/handlers/agent-commands.js +0 -305
  492. package/dist/commands/handlers/design-commands.d.ts +0 -15
  493. package/dist/commands/handlers/design-commands.js +0 -334
  494. package/dist/commands/handlers/index.d.ts +0 -20
  495. package/dist/commands/handlers/index.js +0 -43
  496. package/dist/commands/handlers/overlay-commands.d.ts +0 -21
  497. package/dist/commands/handlers/overlay-commands.js +0 -287
  498. package/dist/commands/handlers/project-commands.d.ts +0 -11
  499. package/dist/commands/handlers/project-commands.js +0 -167
  500. package/dist/commands/handlers/simple-commands.d.ts +0 -19
  501. package/dist/commands/handlers/simple-commands.js +0 -144
  502. package/dist/commands/registry.d.ts +0 -50
  503. package/dist/commands/registry.js +0 -75
  504. package/dist/index.old.d.ts +0 -7
  505. package/dist/index.old.js +0 -1014
  506. package/dist/repl.d.ts +0 -149
  507. package/dist/repl.js +0 -1151
  508. package/dist/templates/claude-md.d.ts +0 -7
  509. package/dist/templates/claude-md.js +0 -189
  510. package/dist/test-autocomplete.d.ts +0 -7
  511. package/dist/test-autocomplete.js +0 -85
  512. package/dist/test-tabbed-menu.d.ts +0 -7
  513. package/dist/test-tabbed-menu.js +0 -25
  514. package/dist/tool-selector.d.ts +0 -71
  515. package/dist/tool-selector.js +0 -184
  516. package/dist/ui/agents-overlay-v2.d.ts +0 -43
  517. package/dist/ui/agents-overlay-v2.js +0 -809
  518. package/dist/ui/agents-overlay.d.ts +0 -12
  519. package/dist/ui/agents-overlay.js +0 -863
  520. package/dist/ui/anchors-overlay.d.ts +0 -12
  521. package/dist/ui/anchors-overlay.js +0 -775
  522. package/dist/ui/arch-type-overlay.d.ts +0 -15
  523. package/dist/ui/arch-type-overlay.js +0 -201
  524. package/dist/ui/ask-user-overlay-v2.d.ts +0 -26
  525. package/dist/ui/ask-user-overlay-v2.js +0 -555
  526. package/dist/ui/ask-user-simple-overlay-v2.d.ts +0 -25
  527. package/dist/ui/ask-user-simple-overlay-v2.js +0 -215
  528. package/dist/ui/backlog-overlay.d.ts +0 -32
  529. package/dist/ui/backlog-overlay.js +0 -652
  530. package/dist/ui/commands-overlay-v2.d.ts +0 -33
  531. package/dist/ui/commands-overlay-v2.js +0 -441
  532. package/dist/ui/commands-overlay.d.ts +0 -16
  533. package/dist/ui/commands-overlay.js +0 -439
  534. package/dist/ui/config-overlay.d.ts +0 -35
  535. package/dist/ui/config-overlay.js +0 -707
  536. package/dist/ui/docs-overlay.d.ts +0 -17
  537. package/dist/ui/docs-overlay.js +0 -303
  538. package/dist/ui/footer-v2.d.ts +0 -222
  539. package/dist/ui/footer-v2.js +0 -1349
  540. package/dist/ui/help-overlay-v2.d.ts +0 -34
  541. package/dist/ui/help-overlay-v2.js +0 -309
  542. package/dist/ui/help-overlay.d.ts +0 -16
  543. package/dist/ui/help-overlay.js +0 -316
  544. package/dist/ui/init-overlay-v2.d.ts +0 -34
  545. package/dist/ui/init-overlay-v2.js +0 -600
  546. package/dist/ui/init-overlay.d.ts +0 -34
  547. package/dist/ui/init-overlay.js +0 -604
  548. package/dist/ui/input-prompt-v2.d.ts +0 -180
  549. package/dist/ui/input-prompt-v2.js +0 -999
  550. package/dist/ui/iteration-limit-overlay-v2.d.ts +0 -21
  551. package/dist/ui/iteration-limit-overlay-v2.js +0 -114
  552. package/dist/ui/keys-overlay-v2.d.ts +0 -41
  553. package/dist/ui/keys-overlay-v2.js +0 -248
  554. package/dist/ui/mascot-overlay-v2.d.ts +0 -41
  555. package/dist/ui/mascot-overlay-v2.js +0 -138
  556. package/dist/ui/mascot-overlay.d.ts +0 -21
  557. package/dist/ui/mascot-overlay.js +0 -146
  558. package/dist/ui/model-overlay-v2.d.ts +0 -49
  559. package/dist/ui/model-overlay-v2.js +0 -118
  560. package/dist/ui/model-overlay.d.ts +0 -27
  561. package/dist/ui/model-overlay.js +0 -221
  562. package/dist/ui/model-warning-overlay.d.ts +0 -30
  563. package/dist/ui/model-warning-overlay.js +0 -169
  564. package/dist/ui/new-overlay.d.ts +0 -34
  565. package/dist/ui/new-overlay.js +0 -604
  566. package/dist/ui/overlay/impl/init-overlay-v2.d.ts +0 -77
  567. package/dist/ui/overlay/impl/init-overlay-v2.js +0 -593
  568. package/dist/ui/overlay/overlay-types.d.ts +0 -128
  569. package/dist/ui/overlay/overlay-types.js +0 -22
  570. package/dist/ui/overlays/help-overlay-v2.d.ts +0 -28
  571. package/dist/ui/overlays/help-overlay-v2.js +0 -198
  572. package/dist/ui/overlays/index.d.ts +0 -11
  573. package/dist/ui/overlays/index.js +0 -11
  574. package/dist/ui/permission-overlay-v2.d.ts +0 -36
  575. package/dist/ui/permission-overlay-v2.js +0 -380
  576. package/dist/ui/projects-overlay.d.ts +0 -19
  577. package/dist/ui/projects-overlay.js +0 -484
  578. package/dist/ui/theme-overlay-v2.d.ts +0 -42
  579. package/dist/ui/theme-overlay-v2.js +0 -135
  580. package/dist/ui/theme-overlay.d.ts +0 -24
  581. package/dist/ui/theme-overlay.js +0 -127
  582. package/dist/ui/tools-overlay-v2.d.ts +0 -47
  583. package/dist/ui/tools-overlay-v2.js +0 -218
  584. package/dist/ui/tools-overlay.d.ts +0 -34
  585. package/dist/ui/tools-overlay.js +0 -230
  586. package/dist/ui/tutorial-overlay-v2.d.ts +0 -31
  587. package/dist/ui/tutorial-overlay-v2.js +0 -1035
  588. package/dist/ui/tutorial-overlay.d.ts +0 -11
  589. package/dist/ui/tutorial-overlay.js +0 -1034
  590. package/dist/ui/workflow-overlay.d.ts +0 -22
  591. package/dist/ui/workflow-overlay.js +0 -636
package/dist/repl.js DELETED
@@ -1,1151 +0,0 @@
1
- /**
2
- * REPL (Read-Eval-Print Loop)
3
- *
4
- * Main orchestration for the interactive agent session.
5
- * Coordinates between input, agent execution, and output.
6
- *
7
- * Uses event-driven architecture with Footer component for:
8
- * - Persistent todo list while agent runs
9
- * - Persistent input prompt (always visible)
10
- * - Input queueing during agent execution
11
- * - Esc to cancel running agent
12
- */
13
- import { exec } from 'child_process';
14
- import { getToolPermissionInfo } from './agent.js';
15
- import * as fs from 'fs';
16
- import * as path from 'path';
17
- import pc from 'picocolors';
18
- import { debug, debugError } from './debug.js';
19
- import { debugLog } from './utils/debug-log.js';
20
- import { getNextMode, MODE_INFO } from './ui/types.js';
21
- import { createInitialState, updateTodos, setAgentRunning } from './state.js';
22
- import { Footer } from './ui/footer.js';
23
- import * as conversation from './ui/conversation.js';
24
- import * as overlays from './ui/overlays.js';
25
- import * as terminal from './ui/terminal.js';
26
- import { TerminalRenderer, RenderMode } from './ui/terminal-renderer.js';
27
- import { resolveCommand } from './commands.js';
28
- // Note: All overlay imports (showConfigOverlay, showModelOverlay, showThemeOverlay, showMascotOverlay, etc.)
29
- // are now handled by command handlers in ./commands/handlers/
30
- import { showToolsOverlay } from './ui/tools-overlay.js';
31
- import { registerFooterCallbacks } from './ui/overlay-controller.js';
32
- import { getCustomCommandRegistry, commandRegistry, registerAllHandlers } from './commands/index.js';
33
- import { getPermissionMode } from './settings/index.js';
34
- // Note: findBacklogPath, parseBacklogItems moved to command handlers
35
- import { isOverlayActive } from './shared-handlers.js';
36
- import { getActiveProject } from './tools/project-db.js';
37
- import { getAnchorManager } from './anchors/index.js';
38
- import { isMemoryInput, handleMemoryInput } from './input-handlers/index.js';
39
- // Helper functions extracted to reduce file size
40
- import { selectToolNamesByIntent } from './repl-helpers.js';
41
- // =============================================================================
42
- // REPL Class
43
- // =============================================================================
44
- export class REPL {
45
- agent;
46
- model;
47
- currentModel; // Can be hot-switched
48
- provider;
49
- version;
50
- showFiltering;
51
- onModeChange;
52
- onAgentFinish;
53
- clearSubagentTracking;
54
- startTime;
55
- initialCommand;
56
- state;
57
- footer;
58
- renderer;
59
- // Session stats
60
- sessionInputTokens = 0;
61
- sessionOutputTokens = 0;
62
- sessionRequests = 0;
63
- // Running state
64
- isRunning = false;
65
- shouldReturnToMenu = false;
66
- agentRunning = false;
67
- abortController = null;
68
- // Promise for waiting on REPL exit
69
- exitResolve = null;
70
- // Text buffer flush function (set during processMessage, allows permission handler to flush)
71
- textBufferFlusher = null;
72
- constructor(options) {
73
- this.agent = options.agent;
74
- this.model = options.model;
75
- this.currentModel = options.model; // Start with same model, can be hot-switched
76
- this.provider = options.provider ?? 'unknown';
77
- this.version = options.version ?? '0.0.1';
78
- this.showFiltering = options.showFiltering ?? false;
79
- this.onModeChange = options.onModeChange;
80
- this.onAgentFinish = options.onAgentFinish;
81
- this.clearSubagentTracking = options.clearSubagentTracking;
82
- this.startTime = new Date();
83
- this.initialCommand = options.initialCommand;
84
- this.state = createInitialState(this.model);
85
- // Map permission mode setting to AgentMode
86
- const permissionMode = getPermissionMode();
87
- const initialMode = permissionMode === 'bypass' ? 'auto-accept' :
88
- permissionMode === 'plan' ? 'plan' : 'normal';
89
- this.footer = new Footer({
90
- showSeparators: true,
91
- initialMode,
92
- });
93
- // Initialize TerminalRenderer in REPL mode
94
- // TODO: Scroll regions disabled until incremental rebuild is complete
95
- this.renderer = new TerminalRenderer({
96
- initialMode: RenderMode.REPL,
97
- useScrollRegions: false, // DISABLED: Use legacy mode for now
98
- debug: false,
99
- });
100
- // Connect footer to renderer (enables external renderer mode on footer)
101
- this.renderer.setFooter(this.footer);
102
- // Connect conversation output to renderer
103
- conversation.setRenderer(this.renderer);
104
- // Note: renderer.start() is called in run(), not here
105
- // This ensures proper startup sequence: footer.start() → renderer.start() → printWelcome()
106
- // Notify external state handler of initial mode
107
- if (this.onModeChange && initialMode !== 'normal') {
108
- this.onModeChange(initialMode);
109
- }
110
- // Set up event handlers
111
- this.setupEventHandlers();
112
- // Notify that footer is ready with pause/resume/setSuggestion functions
113
- if (options.onFooterReady) {
114
- options.onFooterReady(() => { this.footer.pauseAnimation(); }, () => { this.footer.resumeAnimation(); }, (action) => { this.footer.setSuggestion(action); });
115
- }
116
- // Provide text buffer flush function (for permission handler to flush before overlay)
117
- if (options.onTextBufferReady) {
118
- options.onTextBufferReady(() => {
119
- if (this.textBufferFlusher) {
120
- this.textBufferFlusher();
121
- }
122
- });
123
- }
124
- // Provide subagent tracking callbacks (for agent to report subagent activity)
125
- if (options.onSubagentReady) {
126
- options.onSubagentReady({
127
- onStart: (agentId, agentType, description) => {
128
- this.footer.onSubagentStart(agentId, agentType, description);
129
- },
130
- onToolUse: (agentId, toolName, summary) => {
131
- this.footer.onSubagentToolUse(agentId, toolName, summary);
132
- },
133
- onEnd: (agentId, success, tokenCount, error) => {
134
- this.footer.onSubagentEnd(agentId, success, tokenCount, error);
135
- },
136
- });
137
- }
138
- // Register footer callbacks for overlay controller (used by tools like ask_user)
139
- registerFooterCallbacks(() => { this.footer.pauseAnimation(); }, () => { this.footer.resumeAnimation(); });
140
- // Register all command handlers (idempotent - safe to call multiple times)
141
- registerAllHandlers();
142
- }
143
- /**
144
- * Reload project-specific anchors when switching projects
145
- * Clears old project anchors and loads new project anchors
146
- */
147
- reloadProjectAnchors(oldProjectId, newProjectId) {
148
- // Clear old project anchors (if any)
149
- if (oldProjectId) {
150
- const clearedCount = this.agent.clearAnchors({ projectId: oldProjectId });
151
- debug('anchors', `Cleared ${String(clearedCount)} anchors for project ${oldProjectId}`);
152
- }
153
- // Load new project anchors from disk
154
- const newProjectAnchors = getAnchorManager(newProjectId).getAll({ scope: 'persistent' });
155
- debug('anchors', `Loading ${String(newProjectAnchors.length)} anchors for project ${newProjectId}`);
156
- // Add new project anchors to the agent
157
- for (const anchor of newProjectAnchors) {
158
- this.agent.addAnchor({
159
- id: anchor.id,
160
- content: anchor.content,
161
- priority: anchor.priority,
162
- scope: anchor.scope,
163
- tags: anchor.tags,
164
- projectId: newProjectId,
165
- });
166
- }
167
- if (newProjectAnchors.length > 0) {
168
- conversation.printInfo(` Anchors: ${String(newProjectAnchors.length)} loaded for project`);
169
- }
170
- }
171
- /**
172
- * Set up Footer event handlers
173
- */
174
- setupEventHandlers() {
175
- // Handle submit - process message or it gets queued by Footer
176
- this.footer.on('submit', (input) => {
177
- if (!this.agentRunning && input.trim()) {
178
- void this.handleSubmit(input);
179
- }
180
- // If agent is running, Footer automatically queues the input
181
- });
182
- // Handle slash commands
183
- this.footer.on('command', (command, args) => {
184
- debugLog('REPL:command', `received /${command}`);
185
- // NOTE: Don't pause footer here - let overlays pause when ready to render
186
- // This prevents blank screen flash when overlays have slow constructors
187
- void this.handleCommand(command, args).then((shouldContinue) => {
188
- debugLog('REPL:command', 'handler complete');
189
- if (!shouldContinue) {
190
- // Exiting - don't restart input, just resolve
191
- this.isRunning = false;
192
- if (this.exitResolve) {
193
- this.exitResolve();
194
- }
195
- }
196
- else {
197
- // Overlays handle their own pause/resume via lifecycle
198
- // For non-overlay commands, we need to restart the input prompt
199
- // (finishInput() stopped it when user pressed Enter)
200
- this.footer.restartInput();
201
- }
202
- });
203
- });
204
- // Handle Esc - abort running agent
205
- this.footer.on('escape', () => {
206
- if (this.agentRunning && this.abortController) {
207
- this.abortController.abort();
208
- conversation.printWarning('Agent execution cancelled');
209
- }
210
- });
211
- // Handle Ctrl+C - exit REPL
212
- this.footer.on('cancel', () => {
213
- this.isRunning = false;
214
- if (this.exitResolve) {
215
- this.exitResolve();
216
- }
217
- });
218
- // Handle Shift+Tab - cycle modes
219
- this.footer.on('modeChange', () => {
220
- this.cycleMode();
221
- });
222
- }
223
- /**
224
- * Cycle through agent modes (normal -> auto-accept -> plan -> normal)
225
- */
226
- cycleMode() {
227
- const currentMode = this.footer.getMode();
228
- const nextMode = getNextMode(currentMode);
229
- this.footer.setMode(nextMode);
230
- // Notify external state handler
231
- if (this.onModeChange) {
232
- this.onModeChange(nextMode);
233
- }
234
- // Show feedback
235
- const modeInfo = MODE_INFO[nextMode];
236
- this.footer.clearForOutput();
237
- conversation.printInfo(`Mode: ${modeInfo.label} - ${modeInfo.description}`);
238
- this.footer.forceRender();
239
- }
240
- // ===========================================================================
241
- // Public API
242
- // ===========================================================================
243
- /**
244
- * Start the REPL (event-driven)
245
- */
246
- async run() {
247
- this.isRunning = true;
248
- // Set terminal title, clear screen, and show welcome
249
- terminal.setTitle('compilr');
250
- terminal.clearScreen();
251
- conversation.printWelcome(this.model, this.version, getActiveProject()?.displayName ?? null);
252
- // Start footer (begins render loop and input capture)
253
- this.footer.start();
254
- // Start renderer (in legacy mode, this is mostly a no-op)
255
- this.renderer.start();
256
- // Set project name in footer
257
- const activeProject = getActiveProject();
258
- if (activeProject) {
259
- this.footer.setProjectName(activeProject.displayName);
260
- }
261
- // Execute initial command if provided (e.g., /design from project menu)
262
- if (this.initialCommand) {
263
- const cmd = this.initialCommand;
264
- // Give footer a moment to render before running command
265
- setTimeout(() => {
266
- void this.handleCommand(cmd, '');
267
- }, 100);
268
- }
269
- // Wait for exit signal
270
- await this.waitForExit();
271
- // Cleanup
272
- this.footer.stop();
273
- this.renderer.stop();
274
- // Only print goodbye when actually exiting (not when returning to menu)
275
- if (!this.shouldReturnToMenu) {
276
- terminal.writeLine('');
277
- conversation.printInfo('Goodbye!');
278
- }
279
- }
280
- /**
281
- * Wait for REPL exit
282
- */
283
- waitForExit() {
284
- return new Promise((resolve) => {
285
- this.exitResolve = resolve;
286
- });
287
- }
288
- /**
289
- * Get current model
290
- */
291
- getCurrentModel() {
292
- return this.currentModel;
293
- }
294
- /**
295
- * Get current provider
296
- */
297
- getProvider() {
298
- return this.provider;
299
- }
300
- /**
301
- * Set model for hot-switching (within same provider)
302
- */
303
- setModel(model) {
304
- this.currentModel = model;
305
- conversation.printInfo(`Model switched to: ${model}`);
306
- }
307
- /**
308
- * Set the agent mode programmatically (e.g., from permission handler)
309
- */
310
- setMode(mode) {
311
- this.footer.setMode(mode);
312
- // Notify external state handler
313
- if (this.onModeChange) {
314
- this.onModeChange(mode);
315
- }
316
- // Show feedback
317
- const modeInfo = MODE_INFO[mode];
318
- this.footer.clearForOutput();
319
- conversation.printInfo(`Mode: ${modeInfo.label} - ${modeInfo.description}`);
320
- this.footer.forceRender();
321
- }
322
- /**
323
- * Stop the REPL
324
- */
325
- stop() {
326
- this.isRunning = false;
327
- this.footer.stop();
328
- this.renderer.stop();
329
- if (this.exitResolve) {
330
- this.exitResolve();
331
- }
332
- }
333
- /**
334
- * Check if the user requested to return to the startup menu
335
- */
336
- wantsReturnToMenu() {
337
- return this.shouldReturnToMenu;
338
- }
339
- /**
340
- * Handle submitted input (processes message and queued inputs)
341
- */
342
- async handleSubmit(input) {
343
- // Clear any previous suggestion when new input is submitted
344
- this.footer.setSuggestion(null);
345
- // Handle memory prefix: "# note" creates a persistent anchor
346
- if (isMemoryInput(input)) {
347
- handleMemoryInput(input, { agent: this.agent, footer: this.footer });
348
- return;
349
- }
350
- await this.processMessage(input);
351
- // Process queued inputs (FIFO)
352
- while (this.footer.hasQueuedInput() && this.isRunning) {
353
- const queued = this.footer.popQueuedInput();
354
- if (queued) {
355
- await this.processMessage(queued);
356
- }
357
- }
358
- }
359
- // ===========================================================================
360
- // Command Handling
361
- // ===========================================================================
362
- /**
363
- * Create command context for handler execution.
364
- */
365
- getCommandContext() {
366
- return {
367
- // Agent and model
368
- agent: this.agent,
369
- model: this.model,
370
- currentModel: this.currentModel,
371
- provider: this.provider,
372
- version: this.version,
373
- // UI components
374
- footer: this.footer,
375
- state: this.state,
376
- // Session info
377
- startTime: this.startTime,
378
- sessionInputTokens: this.sessionInputTokens,
379
- sessionOutputTokens: this.sessionOutputTokens,
380
- sessionRequests: this.sessionRequests,
381
- // Callbacks
382
- onModeChange: this.onModeChange,
383
- setShouldReturnToMenu: (value) => {
384
- this.shouldReturnToMenu = value;
385
- },
386
- // REPL methods (bound to this instance)
387
- processMessage: (message, options) => this.processMessage(message, options),
388
- handleCommand: (cmd, cmdArgs) => this.handleCommand(cmd, cmdArgs),
389
- setModel: (model) => {
390
- this.setModel(model);
391
- },
392
- // UI helper methods
393
- showTools: () => this.showTools(),
394
- showTokens: () => {
395
- this.showTokens();
396
- },
397
- showContext: () => {
398
- this.showContext();
399
- },
400
- showStatus: () => {
401
- this.showStatus();
402
- },
403
- showTodos: () => {
404
- this.showTodos();
405
- },
406
- handleCompact: () => this.handleCompact(),
407
- handleExport: (exportArgs) => this.handleExport(exportArgs),
408
- reloadProjectAnchors: (oldId, newId) => {
409
- this.reloadProjectAnchors(oldId, newId);
410
- },
411
- };
412
- }
413
- /**
414
- * Handle slash command
415
- * Returns false if REPL should exit
416
- */
417
- async handleCommand(command, args) {
418
- // Resolve aliases to canonical command name
419
- const resolved = resolveCommand(command);
420
- if (!resolved) {
421
- // Check if it's a custom command
422
- const customRegistry = getCustomCommandRegistry();
423
- if (customRegistry.has(command)) {
424
- // Expand custom command and send as message
425
- const customArgs = args ? args.split(' ').filter(a => a.trim()) : [];
426
- const expanded = customRegistry.expand(command, customArgs);
427
- if (expanded) {
428
- // Resume animation before processing (it was paused for overlay commands)
429
- this.footer.resumeAnimation();
430
- // Process as a regular message
431
- await this.processMessage(expanded);
432
- return true;
433
- }
434
- }
435
- conversation.printWarning(`Unknown command: /${command}`);
436
- conversation.printInfo('Type /help to see available commands');
437
- return true;
438
- }
439
- // Try command registry first (for extracted handlers)
440
- const ctx = this.getCommandContext();
441
- const registryResult = await commandRegistry.execute(resolved, args, ctx);
442
- if (registryResult !== null) {
443
- return registryResult;
444
- }
445
- // All commands are now handled by the registry
446
- // This shouldn't happen if resolveCommand works correctly
447
- conversation.printWarning(`Unknown command: /${command}`);
448
- return true;
449
- }
450
- // ===========================================================================
451
- // Message Processing
452
- // ===========================================================================
453
- /**
454
- * Strip '@' prefix from @path mentions before sending to agent
455
- * The '@' is UI syntax for path autocomplete, not part of the actual path
456
- * Only strips @ when it's at start of a word (not in middle like email@domain.com)
457
- */
458
- stripAtMentions(input) {
459
- // Match @ at start of string or after whitespace, followed by non-whitespace
460
- return input.replace(/(^|\s)@(\S+)/g, '$1$2');
461
- }
462
- /**
463
- * Process a message to the agent
464
- * @param input - The full message to send to the agent
465
- * @param options - Optional settings
466
- * @param options.displayMessage - What to show the user (defaults to input)
467
- * @param options.skipPlanModeCheck - Skip plan mode handling (for /design, /refine)
468
- */
469
- async processMessage(input, options) {
470
- // Print user message to conversation (show displayMessage or original)
471
- this.footer.clearForOutput();
472
- conversation.printUserMessage(options?.displayMessage ?? input);
473
- this.footer.forceRender();
474
- // Strip @ prefix from path mentions before sending to agent
475
- const cleanedInput = this.stripAtMentions(input);
476
- // Check current mode (unless skipped for skill-based commands)
477
- const mode = this.footer.getMode();
478
- // Plan mode - placeholder for now (skip for /design, /refine which handle their own flow)
479
- if (mode === 'plan' && !options?.skipPlanModeCheck) {
480
- this.footer.clearForOutput();
481
- conversation.printInfo('📋 Plan Mode (coming soon)');
482
- conversation.printInfo('In plan mode, the agent will analyze your request and create');
483
- conversation.printInfo('a detailed execution plan without performing any actions.');
484
- conversation.printInfo('');
485
- conversation.printInfo('For now, switch to Normal or Auto-accept mode with Shift+Tab.');
486
- terminal.writeLine('');
487
- this.footer.forceRender();
488
- return;
489
- }
490
- // Get all tool names and filter based on intent (use cleaned input)
491
- const allToolNames = this.agent.getToolDefinitions().map((t) => t.name);
492
- const selectedNames = selectToolNamesByIntent(cleanedInput, allToolNames);
493
- // Show filtering analysis if enabled
494
- if (this.showFiltering) {
495
- const saved = allToolNames.length - selectedNames.length;
496
- const pct = Math.round((saved / allToolNames.length) * 100);
497
- this.footer.clearForOutput();
498
- conversation.printInfo(`[Tool Filtering] ${String(selectedNames.length)}/${String(allToolNames.length)} tools, ~${String(pct)}% reduction`);
499
- this.footer.forceRender();
500
- }
501
- // Start agent running state
502
- this.agentRunning = true;
503
- setAgentRunning(this.state, true);
504
- this.footer.setAgentRunning(true);
505
- // Clear subagent tracking to prevent stale data from previous runs
506
- // (both in agent.ts and in footer's SubagentRenderer)
507
- this.clearSubagentTracking?.();
508
- this.footer.clearSubagents();
509
- this.abortController = new AbortController();
510
- let totalInputTokens = 0;
511
- let totalOutputTokens = 0;
512
- let llmCalls = 0;
513
- let hasTextOutput = false;
514
- let usedTools = false;
515
- let lastToolInput = null;
516
- // Event-based rendering: accumulate text, render complete blocks
517
- let textAccumulator = '';
518
- // Set up text buffer flusher so permission handler can flush before showing overlay
519
- this.textBufferFlusher = () => {
520
- if (textAccumulator.trim()) {
521
- this.footer.clearForOutput();
522
- conversation.printAssistantResponse(textAccumulator.trim());
523
- terminal.writeLine('');
524
- this.footer.forceRender();
525
- textAccumulator = '';
526
- }
527
- };
528
- debug('processMessage', 'Starting agent stream', {
529
- inputLength: cleanedInput.length,
530
- toolCount: selectedNames.length,
531
- model: this.currentModel,
532
- });
533
- try {
534
- for await (const event of this.agent.stream(cleanedInput, {
535
- toolFilter: selectedNames,
536
- signal: this.abortController.signal,
537
- chatOptions: { model: this.currentModel },
538
- })) {
539
- debug('processMessage', `Event received: ${event.type}`, event);
540
- // Check if aborted
541
- if (this.abortController.signal.aborted) {
542
- debug('processMessage', 'Aborted');
543
- break;
544
- }
545
- if (event.type === 'llm_chunk') {
546
- if (event.chunk.type === 'text' && event.chunk.text) {
547
- // Event-based rendering: accumulate text until tool_start or stream end
548
- // This allows complete code blocks to be rendered with syntax highlighting
549
- textAccumulator += event.chunk.text;
550
- hasTextOutput = true;
551
- }
552
- else if (event.chunk.type === 'done' && event.chunk.usage) {
553
- const tokens = event.chunk.usage.inputTokens + event.chunk.usage.outputTokens;
554
- this.footer.addTokens(tokens);
555
- totalInputTokens += event.chunk.usage.inputTokens;
556
- totalOutputTokens += event.chunk.usage.outputTokens;
557
- llmCalls++;
558
- }
559
- }
560
- else if (event.type === 'tool_start') {
561
- // Event-based rendering: flush accumulated text before tool output
562
- // Exception: For ask_user/ask_user_simple tools, we'll buffer the text and print after overlay closes
563
- // to avoid the text interfering with the overlay rendering
564
- // Also skip if an overlay is currently active (e.g., permission overlay)
565
- const isAskUserTool = event.name === 'ask_user' || event.name === 'ask_user_simple';
566
- const shouldBuffer = isAskUserTool || isOverlayActive();
567
- if (textAccumulator.trim() && !shouldBuffer) {
568
- this.footer.clearForOutput();
569
- conversation.printAssistantResponse(textAccumulator.trim());
570
- terminal.writeLine('');
571
- this.footer.forceRender();
572
- textAccumulator = '';
573
- }
574
- usedTools = true;
575
- lastToolInput = event.input;
576
- // Show tool in spinner (but not silent tools)
577
- if (event.name !== 'todo_read' && event.name !== 'todo_write' && event.name !== 'suggest') {
578
- // For task tool, show subagent type
579
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
580
- if (event.name === 'task' && event.input) {
581
- const inputObj = event.input;
582
- const subagentType = typeof inputObj.subagent_type === 'string' ? inputObj.subagent_type : 'general';
583
- const description = typeof inputObj.description === 'string' ? inputObj.description : '';
584
- this.footer.setCurrentTool(`task(${subagentType}): ${description}`);
585
- }
586
- else {
587
- this.footer.setCurrentTool(event.name);
588
- }
589
- }
590
- // Note: Diff is shown in the permission handler (index.ts) BEFORE the prompt
591
- }
592
- else if (event.type === 'tool_end') {
593
- const toolName = event.name;
594
- const toolInput = lastToolInput;
595
- const result = event.result;
596
- lastToolInput = null;
597
- // Handle todo_write - update state and render
598
- if (toolName === 'todo_write' && toolInput && Array.isArray(toolInput.todos)) {
599
- const todos = toolInput.todos.map((t) => {
600
- const content = typeof t.content === 'string' ? t.content :
601
- typeof t.title === 'string' ? t.title :
602
- typeof t.task === 'string' ? t.task :
603
- typeof t.description === 'string' ? t.description :
604
- typeof t.text === 'string' ? t.text : 'Untitled task';
605
- const status = (typeof t.status === 'string' && ['pending', 'in_progress', 'completed'].includes(t.status)
606
- ? t.status
607
- : 'pending');
608
- const activeForm = typeof t.activeForm === 'string' ? t.activeForm : undefined;
609
- return { content, status, activeForm };
610
- });
611
- updateTodos(this.state, todos);
612
- this.footer.setTodos(todos);
613
- this.footer.setCurrentTool(null);
614
- continue;
615
- }
616
- // Skip todo_read display
617
- if (toolName === 'todo_read') {
618
- this.footer.setCurrentTool(null);
619
- continue;
620
- }
621
- // Skip suggest tool display (suggestion is shown in input prompt)
622
- if (toolName === 'suggest') {
623
- this.footer.setCurrentTool(null);
624
- this.footer.forceRender();
625
- continue;
626
- }
627
- // Handle ask_user/ask_user_simple tools - print buffered text now that overlay is done
628
- if (toolName === 'ask_user' || toolName === 'ask_user_simple') {
629
- // Print any accumulated text that was buffered before the overlay
630
- if (textAccumulator.trim()) {
631
- this.footer.clearForOutput();
632
- conversation.printAssistantResponse(textAccumulator.trim());
633
- terminal.writeLine('');
634
- textAccumulator = '';
635
- }
636
- this.footer.setCurrentTool(null);
637
- this.footer.forceRender();
638
- continue;
639
- }
640
- // Handle edit tool - diff was already shown on tool_start (no output needed)
641
- if (toolName === 'edit') {
642
- // Just clear the tool indicator, diff was shown before permission prompt
643
- this.footer.setCurrentTool(null);
644
- this.footer.forceRender();
645
- continue;
646
- }
647
- // Handle task tool - print sub-agent completion summary to scrolling zone
648
- // Format: ● Explore(description) \n ⎿ Done (stats)
649
- if (toolName === 'task') {
650
- this.footer.setCurrentTool(null);
651
- // Get stats BEFORE clearing (so we have the data to print)
652
- const stats = this.footer.getLastSubagentStats();
653
- // Clear footer BEFORE clearing subagent data (so lastRenderHeight is still accurate)
654
- this.footer.clearForOutput();
655
- // Print the completion summary to scrolling zone
656
- if (stats) {
657
- conversation.printSubagentResponse(stats);
658
- }
659
- // Now clear the subagent data
660
- this.footer.clearSubagents();
661
- this.footer.forceRender();
662
- continue;
663
- }
664
- // Clear footer for output (for tools that actually print output)
665
- this.footer.clearForOutput();
666
- // Build argument summary for other tools
667
- let argSummary = '';
668
- if (toolInput) {
669
- const path = toolInput.path ?? toolInput.file_path ?? toolInput.filePath;
670
- const command = toolInput.command;
671
- const pattern = toolInput.pattern;
672
- if (typeof path === 'string') {
673
- argSummary = path.split('/').pop() ?? path;
674
- }
675
- else if (typeof command === 'string') {
676
- argSummary = command.length > 40 ? command.slice(0, 40) + '...' : command;
677
- }
678
- else if (typeof pattern === 'string') {
679
- argSummary = pattern;
680
- }
681
- }
682
- // Format result summary
683
- let resultSummary = '';
684
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
685
- if (result && typeof result === 'object') {
686
- const resultObj = result;
687
- if (resultObj.error) {
688
- const errorObj = resultObj.error;
689
- const errorMsg = typeof errorObj.message === 'string' ? errorObj.message : JSON.stringify(resultObj.error);
690
- resultSummary = pc.red(`Error: ${errorMsg.slice(0, 60)}`);
691
- }
692
- else if (resultObj.result !== undefined) {
693
- resultSummary = conversation.formatToolResult(resultObj.result);
694
- }
695
- }
696
- // Print tool log
697
- conversation.printToolExecution(toolName, argSummary, resultSummary);
698
- // Re-render footer after output
699
- this.footer.setCurrentTool(null);
700
- this.footer.forceRender();
701
- }
702
- else if (event.type === 'guardrail_warning') {
703
- // Show guardrail warning to user (non-blocking)
704
- const result = event.result;
705
- const name = result.guardrail?.name ?? 'Unknown';
706
- const message = event.message || result.guardrail?.message || 'Risky operation detected';
707
- const category = result.guardrail?.tags?.[0] ?? 'general';
708
- this.footer.clearForOutput();
709
- conversation.printWarning(`[${category}] ${name}: ${message}`);
710
- this.footer.forceRender();
711
- }
712
- else if (event.type === 'guardrail_blocked') {
713
- // Show guardrail block message (operation was prevented)
714
- const message = event.message || 'Operation blocked by guardrail';
715
- this.footer.clearForOutput();
716
- conversation.printError(`Blocked: ${message}`);
717
- this.footer.forceRender();
718
- }
719
- }
720
- debug('processMessage', 'Stream completed', {
721
- hasTextOutput,
722
- usedTools,
723
- totalInputTokens,
724
- totalOutputTokens,
725
- llmCalls,
726
- textAccumulatorLength: textAccumulator.length,
727
- });
728
- // Skip stats if aborted
729
- if (this.abortController.signal.aborted) {
730
- this.agentRunning = false;
731
- setAgentRunning(this.state, false);
732
- this.footer.setAgentRunning(false);
733
- this.abortController = null;
734
- return;
735
- }
736
- // Event-based rendering: flush any remaining accumulated text
737
- if (textAccumulator.trim()) {
738
- this.footer.clearForOutput();
739
- conversation.printAssistantResponse(textAccumulator.trim());
740
- terminal.writeLine('');
741
- textAccumulator = '';
742
- }
743
- // Warn if tools used but no text
744
- if (usedTools && !hasTextOutput) {
745
- this.footer.clearForOutput();
746
- conversation.printWarning('No text response from model - try a more capable model');
747
- }
748
- // Update session stats
749
- this.sessionInputTokens += totalInputTokens;
750
- this.sessionOutputTokens += totalOutputTokens;
751
- this.sessionRequests++;
752
- // Clear subagents BEFORE printing stats so footer won't show them afterward
753
- this.footer.clearSubagents();
754
- // Show token usage
755
- if (totalInputTokens > 0 || totalOutputTokens > 0) {
756
- this.footer.clearForOutput();
757
- const total = totalInputTokens + totalOutputTokens;
758
- const sessionTotal = this.sessionInputTokens + this.sessionOutputTokens;
759
- conversation.printInfo(`[Tokens: ${total.toLocaleString()} (${totalInputTokens.toLocaleString()} in / ${totalOutputTokens.toLocaleString()} out) - ${String(llmCalls)} LLM call(s)]`);
760
- conversation.printInfo(`[Session: ${sessionTotal.toLocaleString()} total (${String(this.sessionRequests)} requests)]`);
761
- terminal.writeLine('');
762
- this.footer.forceRender();
763
- }
764
- // Stop spinner and re-render footer (AFTER all output is printed)
765
- this.agentRunning = false;
766
- setAgentRunning(this.state, false);
767
- this.footer.setAgentRunning(false);
768
- }
769
- catch (error) {
770
- debugError('processMessage', error);
771
- if (error.name !== 'AbortError') {
772
- this.footer.clearForOutput();
773
- conversation.printError(error.message);
774
- this.footer.forceRender();
775
- }
776
- }
777
- finally {
778
- // Ensure agent is stopped even on error
779
- this.agentRunning = false;
780
- setAgentRunning(this.state, false);
781
- this.footer.setAgentRunning(false);
782
- this.abortController = null;
783
- // Clear text buffer flusher
784
- this.textBufferFlusher = null;
785
- // Ensure footer is rendered and isPaused is reset
786
- // (clearForOutput sets isPaused=true, forceRender resets it)
787
- this.footer.forceRender();
788
- // Notify that agent has finished (for applying deferred suggestions)
789
- this.onAgentFinish?.();
790
- }
791
- }
792
- // ===========================================================================
793
- // Helper Commands
794
- // ===========================================================================
795
- async handleCompact() {
796
- const contextManager = this.agent.getContextManager();
797
- if (!contextManager) {
798
- this.footer.clearForOutput();
799
- conversation.printWarning('Context manager not available');
800
- this.footer.forceRender();
801
- return;
802
- }
803
- const history = this.agent.getHistory();
804
- if (history.length === 0) {
805
- this.footer.clearForOutput();
806
- conversation.printInfo('No conversation history to compact');
807
- this.footer.forceRender();
808
- return;
809
- }
810
- const stats = contextManager.getStats(history.length);
811
- this.footer.clearForOutput();
812
- conversation.printInfo(`Current: ${stats.currentTokens.toLocaleString()} tokens, ${String(history.length)} messages`);
813
- const confirmed = await overlays.showConfirmation('Compact conversation history?');
814
- if (!confirmed) {
815
- this.footer.forceRender();
816
- return;
817
- }
818
- // Show spinner during compaction
819
- this.footer.setSpinnerText('Compacting context');
820
- setAgentRunning(this.state, true);
821
- this.footer.setAgentRunning(true);
822
- this.footer.forceRender(); // Render immediately before blocking operation
823
- try {
824
- // Use the agent's compact() method - handles summarization, tool pairing, and hints
825
- const result = (await this.agent.compact());
826
- // Stop spinner and clear for output
827
- setAgentRunning(this.state, false);
828
- this.footer.setAgentRunning(false);
829
- this.footer.setSpinnerText(null);
830
- this.footer.clearForOutput();
831
- if (!result.success) {
832
- conversation.printWarning('Compaction not available (no context manager)');
833
- this.footer.forceRender();
834
- return;
835
- }
836
- // Build status message
837
- const newHistory = this.agent.getHistory();
838
- const statusParts = [
839
- `Compacted: ${String(result.originalTokens ?? 0).replace(/\B(?=(\d{3})+(?!\d))/g, ',')} → ${String(result.summaryTokens ?? 0).replace(/\B(?=(\d{3})+(?!\d))/g, ',')} tokens`,
840
- `(${String(history.length)} → ${String(newHistory.length)} messages, ${String(result.messagesPreserved ?? 0)} preserved)`,
841
- ];
842
- // Add smart compaction category info
843
- if (result.categoryStats) {
844
- const actions = [];
845
- if (result.categoryStats.toolResults.action === 'compacted') {
846
- actions.push('tool results → files');
847
- }
848
- if (result.categoryStats.history.action === 'summarized') {
849
- actions.push('history → summary');
850
- }
851
- if (actions.length > 0) {
852
- statusParts.push(`[${actions.join(', ')}]`);
853
- }
854
- }
855
- // Add files created info
856
- if (result.filesCreated && result.filesCreated.length > 0) {
857
- statusParts.push(`[${String(result.filesCreated.length)} file(s) created]`);
858
- }
859
- // Add file tracking info
860
- if (result.restorationHintsInjected) {
861
- const fileTracker = this.agent.getFileTracker();
862
- const trackerStats = fileTracker?.getStats();
863
- const filesTracked = trackerStats ? trackerStats.total : 0;
864
- statusParts.push(`[${String(filesTracked)} files tracked]`);
865
- }
866
- // Add repair info if tool_results were fixed
867
- if (result.toolResultsRepaired && result.toolResultsRepaired > 0) {
868
- statusParts.push(`[${String(result.toolResultsRepaired)} orphaned tool results removed]`);
869
- }
870
- conversation.printSuccess(statusParts.join(' '));
871
- }
872
- catch (error) {
873
- // Stop spinner on error too
874
- setAgentRunning(this.state, false);
875
- this.footer.setAgentRunning(false);
876
- this.footer.setSpinnerText(null);
877
- this.footer.clearForOutput();
878
- conversation.printError(`Compaction failed: ${error.message}`);
879
- }
880
- this.footer.forceRender();
881
- }
882
- async showTools() {
883
- const tools = this.agent.getToolDefinitions().map((t) => {
884
- // Extract parameters from inputSchema
885
- const parameters = [];
886
- const props = t.inputSchema.properties;
887
- const required = t.inputSchema.required ?? [];
888
- for (const [name, schema] of Object.entries(props)) {
889
- parameters.push({
890
- name,
891
- type: schema.type ?? 'unknown',
892
- description: schema.description,
893
- required: required.includes(name),
894
- });
895
- }
896
- // Look up permission info
897
- const permissionInfo = getToolPermissionInfo(t.name);
898
- const permission = permissionInfo
899
- ? { level: permissionInfo.level, description: permissionInfo.description }
900
- : undefined;
901
- // For task tool, extract just the intro (before verbose agent types list)
902
- let description = t.description;
903
- if (t.name === 'task' && description.includes('Available agent types:')) {
904
- description = description.split('Available agent types:')[0].trim();
905
- }
906
- return {
907
- name: t.name,
908
- description,
909
- parameters,
910
- permission,
911
- };
912
- });
913
- // Overlay lifecycle handles footer pause/resume
914
- await showToolsOverlay(tools);
915
- }
916
- showTokens() {
917
- this.footer.clearForOutput();
918
- overlays.showTokenUsage({
919
- inputTokens: this.sessionInputTokens,
920
- outputTokens: this.sessionOutputTokens,
921
- totalTokens: this.sessionInputTokens + this.sessionOutputTokens,
922
- });
923
- this.footer.forceRender();
924
- }
925
- showContext() {
926
- const contextManager = this.agent.getContextManager();
927
- const history = this.agent.getHistory();
928
- this.footer.clearForOutput();
929
- if (contextManager) {
930
- const stats = contextManager.getStats(history.length);
931
- overlays.showContextStats({
932
- tokens: stats.currentTokens,
933
- maxTokens: stats.maxTokens,
934
- messages: stats.messageCount,
935
- turns: stats.turnCount,
936
- utilization: stats.utilization,
937
- });
938
- }
939
- else {
940
- // Fallback to session tracking
941
- overlays.showContextStats({
942
- tokens: this.sessionInputTokens + this.sessionOutputTokens,
943
- maxTokens: 200000,
944
- messages: history.length,
945
- turns: Math.floor(history.filter((m) => m.role === 'user').length),
946
- utilization: (this.sessionInputTokens + this.sessionOutputTokens) / 200000,
947
- });
948
- }
949
- this.footer.forceRender();
950
- }
951
- showStatus() {
952
- const contextManager = this.agent.getContextManager();
953
- const history = this.agent.getHistory();
954
- const mode = this.footer.getMode();
955
- const modeInfo = MODE_INFO[mode];
956
- this.footer.clearForOutput();
957
- terminal.writeLine('');
958
- terminal.writeLine(pc.bold('Status'));
959
- terminal.writeLine(pc.dim('─'.repeat(40)));
960
- terminal.writeLine(` Version: ${pc.cyan(this.version)}`);
961
- terminal.writeLine(` Model: ${pc.cyan(this.model)}`);
962
- terminal.writeLine(` Mode: ${pc.cyan(modeInfo.label)}`);
963
- if (contextManager) {
964
- const stats = contextManager.getStats(history.length);
965
- const pct = (stats.utilization * 100).toFixed(1);
966
- const bar = this.renderProgressBar(stats.utilization, 20);
967
- terminal.writeLine(` Context: ${bar} ${pct}%`);
968
- terminal.writeLine(` Messages: ${pc.cyan(String(stats.messageCount))}`);
969
- }
970
- else {
971
- const total = this.sessionInputTokens + this.sessionOutputTokens;
972
- terminal.writeLine(` Tokens: ${pc.cyan(total.toLocaleString())}`);
973
- terminal.writeLine(` Messages: ${pc.cyan(String(history.length))}`);
974
- }
975
- terminal.writeLine(` Requests: ${pc.cyan(String(this.sessionRequests))}`);
976
- terminal.writeLine('');
977
- this.footer.forceRender();
978
- }
979
- renderProgressBar(ratio, width) {
980
- const filled = Math.round(ratio * width);
981
- const empty = width - filled;
982
- const color = ratio > 0.9 ? pc.red : ratio > 0.7 ? pc.yellow : pc.green;
983
- return color('█'.repeat(filled)) + pc.dim('░'.repeat(empty));
984
- }
985
- showTodos() {
986
- const todos = this.state.todos;
987
- this.footer.clearForOutput();
988
- terminal.writeLine('');
989
- if (todos.length === 0) {
990
- terminal.writeLine(pc.dim('No todos. The agent will create todos when working on tasks.'));
991
- terminal.writeLine('');
992
- this.footer.forceRender();
993
- return;
994
- }
995
- terminal.writeLine(pc.bold('Todos'));
996
- terminal.writeLine(pc.dim('─'.repeat(40)));
997
- for (const todo of todos) {
998
- let icon;
999
- let style;
1000
- switch (todo.status) {
1001
- case 'completed':
1002
- icon = pc.green('✓');
1003
- style = pc.strikethrough;
1004
- break;
1005
- case 'in_progress':
1006
- icon = pc.yellow('●');
1007
- style = pc.bold;
1008
- break;
1009
- default:
1010
- icon = pc.dim('○');
1011
- style = (s) => s;
1012
- }
1013
- terminal.writeLine(` ${icon} ${style(todo.content)}`);
1014
- }
1015
- terminal.writeLine('');
1016
- this.footer.forceRender();
1017
- }
1018
- async handleExport(args) {
1019
- const history = this.agent.getHistory();
1020
- if (history.length === 0) {
1021
- this.footer.clearForOutput();
1022
- conversation.printWarning('No conversation to export');
1023
- this.footer.forceRender();
1024
- return;
1025
- }
1026
- // Format conversation as markdown
1027
- const markdown = this.formatConversationAsMarkdown(history);
1028
- if (args.trim()) {
1029
- // Export to file
1030
- const filename = args.trim();
1031
- const filepath = path.isAbsolute(filename) ? filename : path.join(process.cwd(), filename);
1032
- try {
1033
- fs.writeFileSync(filepath, markdown, 'utf-8');
1034
- this.footer.clearForOutput();
1035
- conversation.printSuccess(`Exported to ${filepath}`);
1036
- this.footer.forceRender();
1037
- }
1038
- catch (error) {
1039
- this.footer.clearForOutput();
1040
- conversation.printError(`Failed to export: ${error.message}`);
1041
- this.footer.forceRender();
1042
- }
1043
- }
1044
- else {
1045
- // Export to clipboard
1046
- try {
1047
- await this.copyToClipboard(markdown);
1048
- this.footer.clearForOutput();
1049
- conversation.printSuccess(`Copied ${String(history.length)} messages to clipboard`);
1050
- this.footer.forceRender();
1051
- }
1052
- catch (error) {
1053
- this.footer.clearForOutput();
1054
- conversation.printError(`Failed to copy to clipboard: ${error.message}`);
1055
- this.footer.forceRender();
1056
- }
1057
- }
1058
- }
1059
- formatConversationAsMarkdown(history) {
1060
- const lines = [];
1061
- const timestamp = new Date().toISOString().split('T')[0];
1062
- lines.push(`# Conversation Export`);
1063
- lines.push('');
1064
- lines.push(`**Model:** ${this.model}`);
1065
- lines.push(`**Date:** ${timestamp}`);
1066
- lines.push(`**Messages:** ${String(history.length)}`);
1067
- lines.push('');
1068
- lines.push('---');
1069
- lines.push('');
1070
- for (const msg of history) {
1071
- const role = msg.role === 'user' ? '👤 User' : '🤖 Assistant';
1072
- lines.push(`## ${role}`);
1073
- lines.push('');
1074
- if (typeof msg.content === 'string') {
1075
- lines.push(msg.content);
1076
- }
1077
- else if (Array.isArray(msg.content)) {
1078
- // Handle content blocks (tool calls, etc.)
1079
- for (const block of msg.content) {
1080
- if (typeof block === 'object' && block !== null) {
1081
- const b = block;
1082
- if (b.type === 'text' && typeof b.text === 'string') {
1083
- lines.push(b.text);
1084
- }
1085
- else if (b.type === 'tool_use') {
1086
- const toolName = typeof b.name === 'string' ? b.name : String(b.name);
1087
- lines.push(`**Tool:** \`${toolName}\``);
1088
- lines.push('```json');
1089
- lines.push(JSON.stringify(b.input, null, 2));
1090
- lines.push('```');
1091
- }
1092
- else if (b.type === 'tool_result') {
1093
- lines.push(`**Tool Result:**`);
1094
- const content = typeof b.content === 'string' ? b.content : JSON.stringify(b.content);
1095
- if (content.length > 500) {
1096
- lines.push('```');
1097
- lines.push(content.slice(0, 500) + '...[truncated]');
1098
- lines.push('```');
1099
- }
1100
- else {
1101
- lines.push('```');
1102
- lines.push(content);
1103
- lines.push('```');
1104
- }
1105
- }
1106
- }
1107
- }
1108
- }
1109
- else {
1110
- lines.push(JSON.stringify(msg.content, null, 2));
1111
- }
1112
- lines.push('');
1113
- lines.push('---');
1114
- lines.push('');
1115
- }
1116
- return lines.join('\n');
1117
- }
1118
- async copyToClipboard(text) {
1119
- const platform = process.platform;
1120
- let command;
1121
- if (platform === 'darwin') {
1122
- command = 'pbcopy';
1123
- }
1124
- else if (platform === 'linux') {
1125
- // Try xclip first, fall back to xsel
1126
- command = 'xclip -selection clipboard';
1127
- }
1128
- else if (platform === 'win32') {
1129
- command = 'clip';
1130
- }
1131
- else {
1132
- throw new Error(`Unsupported platform: ${platform}`);
1133
- }
1134
- const child = exec(command);
1135
- if (child.stdin) {
1136
- child.stdin.write(text);
1137
- child.stdin.end();
1138
- }
1139
- await new Promise((resolve, reject) => {
1140
- child.on('exit', (code) => {
1141
- if (code === 0) {
1142
- resolve();
1143
- }
1144
- else {
1145
- reject(new Error(`Clipboard command exited with code ${String(code ?? 'unknown')}`));
1146
- }
1147
- });
1148
- child.on('error', reject);
1149
- });
1150
- }
1151
- }