@compilr-dev/cli 0.5.0 → 0.5.2

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 (587) hide show
  1. package/LICENSE +108 -0
  2. package/README.md +237 -69
  3. package/dist/.tsbuildinfo.app +1 -0
  4. package/dist/.tsbuildinfo.data +1 -0
  5. package/dist/.tsbuildinfo.domain +1 -0
  6. package/dist/.tsbuildinfo.foundation +1 -0
  7. package/dist/agent.d.ts +61 -4
  8. package/dist/agent.js +241 -245
  9. package/dist/anchors/index.d.ts +1 -1
  10. package/dist/anchors/index.js +1 -1
  11. package/dist/anchors/project-anchors.d.ts +2 -2
  12. package/dist/anchors/project-anchors.js +1 -1
  13. package/dist/auth/api-client.d.ts +124 -0
  14. package/dist/auth/api-client.js +261 -0
  15. package/dist/auth/index.d.ts +172 -0
  16. package/dist/auth/index.js +545 -0
  17. package/dist/auth/storage.d.ts +52 -0
  18. package/dist/auth/storage.js +118 -0
  19. package/dist/changelog/index.d.ts +16 -0
  20. package/dist/changelog/index.js +24 -0
  21. package/dist/changelog/releases.d.ts +17 -0
  22. package/dist/changelog/releases.js +63 -0
  23. package/dist/commands-v2/handlers/auth.d.ts +10 -0
  24. package/dist/commands-v2/handlers/auth.js +118 -0
  25. package/dist/commands-v2/handlers/background.d.ts +14 -0
  26. package/dist/commands-v2/handlers/background.js +276 -0
  27. package/dist/commands-v2/handlers/context.js +286 -81
  28. package/dist/commands-v2/handlers/core.d.ts +1 -0
  29. package/dist/commands-v2/handlers/core.js +133 -8
  30. package/dist/commands-v2/handlers/debug.js +18 -0
  31. package/dist/commands-v2/handlers/delegations.d.ts +8 -0
  32. package/dist/commands-v2/handlers/delegations.js +29 -0
  33. package/dist/commands-v2/handlers/files.d.ts +8 -0
  34. package/dist/commands-v2/handlers/files.js +162 -0
  35. package/dist/commands-v2/handlers/filter.d.ts +9 -0
  36. package/dist/commands-v2/handlers/filter.js +130 -0
  37. package/dist/commands-v2/handlers/games.d.ts +7 -0
  38. package/dist/commands-v2/handlers/games.js +57 -0
  39. package/dist/commands-v2/handlers/index.d.ts +13 -0
  40. package/dist/commands-v2/handlers/index.js +39 -0
  41. package/dist/commands-v2/handlers/mcp.d.ts +8 -0
  42. package/dist/commands-v2/handlers/mcp.js +39 -0
  43. package/dist/commands-v2/handlers/notifications.d.ts +9 -0
  44. package/dist/commands-v2/handlers/notifications.js +34 -0
  45. package/dist/commands-v2/handlers/project.js +295 -31
  46. package/dist/commands-v2/handlers/reset.d.ts +11 -0
  47. package/dist/commands-v2/handlers/reset.js +118 -0
  48. package/dist/commands-v2/handlers/session.d.ts +161 -0
  49. package/dist/commands-v2/handlers/session.js +805 -0
  50. package/dist/commands-v2/handlers/settings.d.ts +2 -0
  51. package/dist/commands-v2/handlers/settings.js +217 -35
  52. package/dist/commands-v2/handlers/tasks.d.ts +5 -0
  53. package/dist/commands-v2/handlers/tasks.js +36 -0
  54. package/dist/commands-v2/handlers/team.d.ts +9 -0
  55. package/dist/commands-v2/handlers/team.js +549 -0
  56. package/dist/commands-v2/handlers/terminals.d.ts +9 -0
  57. package/dist/commands-v2/handlers/terminals.js +34 -0
  58. package/dist/commands-v2/index.d.ts +3 -2
  59. package/dist/commands-v2/index.js +4 -1
  60. package/dist/commands-v2/registry.d.ts +15 -0
  61. package/dist/commands-v2/registry.js +34 -0
  62. package/dist/commands-v2/types.d.ts +81 -3
  63. package/dist/commands.js +13 -0
  64. package/dist/compilr-diff-companion.vsix +0 -0
  65. package/dist/db/index.js +98 -4
  66. package/dist/db/repositories/document-repository.d.ts +2 -0
  67. package/dist/db/repositories/document-repository.js +6 -1
  68. package/dist/db/repositories/index.d.ts +2 -0
  69. package/dist/db/repositories/index.js +1 -0
  70. package/dist/db/repositories/plan-repository.d.ts +101 -0
  71. package/dist/db/repositories/plan-repository.js +275 -0
  72. package/dist/db/repositories/project-repository.d.ts +6 -0
  73. package/dist/db/repositories/project-repository.js +41 -0
  74. package/dist/db/repositories/work-item-repository.d.ts +15 -0
  75. package/dist/db/repositories/work-item-repository.js +69 -4
  76. package/dist/db/schema.d.ts +40 -3
  77. package/dist/db/schema.js +66 -3
  78. package/dist/episodes/index.d.ts +20 -0
  79. package/dist/episodes/index.js +27 -0
  80. package/dist/episodes/recorder.d.ts +51 -0
  81. package/dist/episodes/recorder.js +195 -0
  82. package/dist/episodes/significant-work.d.ts +21 -0
  83. package/dist/episodes/significant-work.js +56 -0
  84. package/dist/episodes/store.d.ts +38 -0
  85. package/dist/episodes/store.js +199 -0
  86. package/dist/episodes/types.d.ts +35 -0
  87. package/dist/episodes/types.js +6 -0
  88. package/dist/episodes/work-at-risk.d.ts +12 -0
  89. package/dist/episodes/work-at-risk.js +38 -0
  90. package/dist/episodes/work-summary-anchor.d.ts +23 -0
  91. package/dist/episodes/work-summary-anchor.js +73 -0
  92. package/dist/games/coins.d.ts +66 -0
  93. package/dist/games/coins.js +165 -0
  94. package/dist/games/game-base.d.ts +84 -0
  95. package/dist/games/game-base.js +204 -0
  96. package/dist/games/index.d.ts +16 -0
  97. package/dist/games/index.js +49 -0
  98. package/dist/games/scores.d.ts +69 -0
  99. package/dist/games/scores.js +191 -0
  100. package/dist/games/tetris/board.d.ts +59 -0
  101. package/dist/games/tetris/board.js +170 -0
  102. package/dist/games/tetris/index.d.ts +109 -0
  103. package/dist/games/tetris/index.js +610 -0
  104. package/dist/games/tetris/pieces.d.ts +44 -0
  105. package/dist/games/tetris/pieces.js +271 -0
  106. package/dist/games/tetris/renderer.d.ts +26 -0
  107. package/dist/games/tetris/renderer.js +77 -0
  108. package/dist/guide/guide-content.d.ts +23 -0
  109. package/dist/guide/guide-content.js +196 -0
  110. package/dist/guide/index.d.ts +8 -0
  111. package/dist/guide/index.js +7 -0
  112. package/dist/guide/shared-content.d.ts +37 -0
  113. package/dist/guide/shared-content.js +1272 -0
  114. package/dist/guide/tutorial-helpers.d.ts +57 -0
  115. package/dist/guide/tutorial-helpers.js +147 -0
  116. package/dist/handlers/ask-user-handlers.d.ts +32 -0
  117. package/dist/handlers/ask-user-handlers.js +104 -0
  118. package/dist/handlers/delegation-handlers.d.ts +34 -0
  119. package/dist/handlers/delegation-handlers.js +291 -0
  120. package/dist/handlers/permission-handler.d.ts +30 -0
  121. package/dist/handlers/permission-handler.js +205 -0
  122. package/dist/index.d.ts +11 -1
  123. package/dist/index.js +448 -271
  124. package/dist/input-handlers/memory-handler.d.ts +1 -1
  125. package/dist/input-handlers/memory-handler.js +2 -1
  126. package/dist/models/index.d.ts +10 -0
  127. package/dist/models/index.js +12 -0
  128. package/dist/models/model-registry.d.ts +38 -0
  129. package/dist/models/model-registry.js +69 -0
  130. package/dist/models/model-tiers.d.ts +28 -0
  131. package/dist/models/model-tiers.js +71 -0
  132. package/dist/models/model-validation.d.ts +25 -0
  133. package/dist/models/model-validation.js +291 -0
  134. package/dist/models/ollama-models.d.ts +73 -0
  135. package/dist/models/ollama-models.js +178 -0
  136. package/dist/models/provider-types.d.ts +6 -0
  137. package/dist/models/provider-types.js +1 -0
  138. package/dist/models/providers.d.ts +35 -0
  139. package/dist/models/providers.js +58 -0
  140. package/dist/models/types.d.ts +4 -0
  141. package/dist/models/types.js +4 -0
  142. package/dist/multi-agent/activity.d.ts +21 -0
  143. package/dist/multi-agent/activity.js +34 -0
  144. package/dist/multi-agent/agent-selection.d.ts +55 -0
  145. package/dist/multi-agent/agent-selection.js +90 -0
  146. package/dist/multi-agent/artifacts.d.ts +197 -0
  147. package/dist/multi-agent/artifacts.js +379 -0
  148. package/dist/multi-agent/checkpointer.d.ts +138 -0
  149. package/dist/multi-agent/checkpointer.js +471 -0
  150. package/dist/multi-agent/collision-utils.d.ts +16 -0
  151. package/dist/multi-agent/collision-utils.js +28 -0
  152. package/dist/multi-agent/context-resolver.d.ts +97 -0
  153. package/dist/multi-agent/context-resolver.js +316 -0
  154. package/dist/multi-agent/custom-agents.d.ts +83 -0
  155. package/dist/multi-agent/custom-agents.js +227 -0
  156. package/dist/multi-agent/delegation-tracker.d.ts +157 -0
  157. package/dist/multi-agent/delegation-tracker.js +243 -0
  158. package/dist/multi-agent/file-lock-hook.d.ts +29 -0
  159. package/dist/multi-agent/file-lock-hook.js +97 -0
  160. package/dist/multi-agent/file-locks.d.ts +58 -0
  161. package/dist/multi-agent/file-locks.js +194 -0
  162. package/dist/multi-agent/index.d.ts +24 -0
  163. package/dist/multi-agent/index.js +30 -0
  164. package/dist/multi-agent/mention-parser.d.ts +64 -0
  165. package/dist/multi-agent/mention-parser.js +146 -0
  166. package/dist/multi-agent/notification-manager.d.ts +84 -0
  167. package/dist/multi-agent/notification-manager.js +224 -0
  168. package/dist/multi-agent/pending-requests.d.ts +122 -0
  169. package/dist/multi-agent/pending-requests.js +155 -0
  170. package/dist/multi-agent/session-registry.d.ts +139 -0
  171. package/dist/multi-agent/session-registry.js +514 -0
  172. package/dist/multi-agent/shared-context.d.ts +293 -0
  173. package/dist/multi-agent/shared-context.js +671 -0
  174. package/dist/multi-agent/skill-requirements.d.ts +66 -0
  175. package/dist/multi-agent/skill-requirements.js +178 -0
  176. package/dist/multi-agent/task-assignment.d.ts +69 -0
  177. package/dist/multi-agent/task-assignment.js +123 -0
  178. package/dist/multi-agent/task-suggestion.d.ts +31 -0
  179. package/dist/multi-agent/task-suggestion.js +72 -0
  180. package/dist/multi-agent/team-agent.d.ts +201 -0
  181. package/dist/multi-agent/team-agent.js +488 -0
  182. package/dist/multi-agent/team.d.ts +286 -0
  183. package/dist/multi-agent/team.js +610 -0
  184. package/dist/multi-agent/tool-config.d.ts +110 -0
  185. package/dist/multi-agent/tool-config.js +661 -0
  186. package/dist/multi-agent/types.d.ts +211 -0
  187. package/dist/multi-agent/types.js +617 -0
  188. package/dist/prompts/plan-mode-prompt.d.ts +11 -0
  189. package/dist/prompts/plan-mode-prompt.js +95 -0
  190. package/dist/repl-helpers.js +5 -2
  191. package/dist/repl-v2.d.ts +401 -2
  192. package/dist/repl-v2.js +2588 -65
  193. package/dist/session/index.d.ts +6 -0
  194. package/dist/session/index.js +6 -0
  195. package/dist/session/project-session-manager.d.ts +158 -0
  196. package/dist/session/project-session-manager.js +650 -0
  197. package/dist/settings/index.d.ts +133 -13
  198. package/dist/settings/index.js +329 -24
  199. package/dist/settings/mcp-config.d.ts +76 -0
  200. package/dist/settings/mcp-config.js +143 -0
  201. package/dist/settings/paths.d.ts +4 -0
  202. package/dist/settings/paths.js +6 -0
  203. package/dist/shared-handlers.d.ts +62 -0
  204. package/dist/shared-handlers.js +48 -0
  205. package/dist/system-prompt/builder.d.ts +5 -0
  206. package/dist/system-prompt/builder.js +4 -0
  207. package/dist/system-prompt/index.d.ts +18 -0
  208. package/dist/system-prompt/index.js +18 -0
  209. package/dist/system-prompt/modules.d.ts +5 -0
  210. package/dist/system-prompt/modules.js +4 -0
  211. package/dist/tabbed-menu.js +2 -1
  212. package/dist/templates/compilr-md-import.d.ts +16 -0
  213. package/dist/templates/compilr-md-import.js +241 -0
  214. package/dist/templates/compilr-md.js +10 -61
  215. package/dist/templates/config-json.d.ts +1 -25
  216. package/dist/templates/index.d.ts +2 -0
  217. package/dist/templates/index.js +34 -73
  218. package/dist/tool-names.d.ts +113 -0
  219. package/dist/tool-names.js +239 -0
  220. package/dist/tools/ask-user-simple.d.ts +1 -1
  221. package/dist/tools/ask-user-simple.js +2 -1
  222. package/dist/tools/ask-user.d.ts +1 -1
  223. package/dist/tools/ask-user.js +2 -1
  224. package/dist/tools/backlog.d.ts +2 -2
  225. package/dist/tools/backlog.js +1 -1
  226. package/dist/tools/db-tools.d.ts +13 -61
  227. package/dist/tools/db-tools.js +12 -13
  228. package/dist/tools/delegate-background.d.ts +27 -0
  229. package/dist/tools/delegate-background.js +115 -0
  230. package/dist/tools/delegate.d.ts +22 -0
  231. package/dist/tools/delegate.js +97 -0
  232. package/dist/tools/delegation-status.d.ts +16 -0
  233. package/dist/tools/delegation-status.js +128 -0
  234. package/dist/tools/guide-tool.d.ts +12 -0
  235. package/dist/tools/guide-tool.js +59 -0
  236. package/dist/tools/handoff.d.ts +25 -0
  237. package/dist/tools/handoff.js +99 -0
  238. package/dist/tools/meta-tools.d.ts +26 -0
  239. package/dist/tools/meta-tools.js +47 -0
  240. package/dist/tools/platform-adapter.d.ts +35 -0
  241. package/dist/tools/platform-adapter.js +404 -0
  242. package/dist/tools/project-db.d.ts +5 -73
  243. package/dist/tools/project-db.js +5 -336
  244. package/dist/tools.d.ts +67 -2
  245. package/dist/tools.js +240 -48
  246. package/dist/ui/autocomplete-controller.d.ts +42 -0
  247. package/dist/ui/autocomplete-controller.js +384 -0
  248. package/dist/ui/base/index.d.ts +1 -1
  249. package/dist/ui/base/index.js +1 -1
  250. package/dist/ui/base/overlay-base-v2.d.ts +10 -0
  251. package/dist/ui/base/overlay-base-v2.js +14 -0
  252. package/dist/ui/base/render-utils.d.ts +19 -0
  253. package/dist/ui/base/render-utils.js +25 -0
  254. package/dist/ui/base/tabbed-list-overlay-v2.d.ts +16 -1
  255. package/dist/ui/base/tabbed-list-overlay-v2.js +19 -1
  256. package/dist/ui/constants/labels.d.ts +14 -0
  257. package/dist/ui/constants/labels.js +52 -0
  258. package/dist/ui/conversation-store.d.ts +55 -0
  259. package/dist/ui/conversation-store.js +107 -0
  260. package/dist/ui/conversation.js +11 -13
  261. package/dist/ui/diff.d.ts +7 -1
  262. package/dist/ui/diff.js +85 -48
  263. package/dist/ui/ephemeral.js +3 -9
  264. package/dist/ui/file-autocomplete.d.ts +24 -0
  265. package/dist/ui/file-autocomplete.js +56 -0
  266. package/dist/ui/footer-renderer.d.ts +69 -0
  267. package/dist/ui/footer-renderer.js +431 -0
  268. package/dist/ui/footer.d.ts +74 -7
  269. package/dist/ui/footer.js +173 -16
  270. package/dist/ui/input-controller.d.ts +51 -0
  271. package/dist/ui/input-controller.js +176 -0
  272. package/dist/ui/input-prompt.d.ts +19 -0
  273. package/dist/ui/input-prompt.js +206 -14
  274. package/dist/ui/keyboard-handler.d.ts +57 -0
  275. package/dist/ui/keyboard-handler.js +557 -0
  276. package/dist/ui/live-region-facade.d.ts +42 -0
  277. package/dist/ui/live-region-facade.js +205 -0
  278. package/dist/ui/live-region.d.ts +0 -4
  279. package/dist/ui/live-region.js +6 -14
  280. package/dist/ui/mascot/renderer.d.ts +1 -1
  281. package/dist/ui/mascot/renderer.js +37 -2
  282. package/dist/ui/overlay/data/tutorial-content.d.ts +9 -0
  283. package/dist/ui/overlay/data/tutorial-content.js +9 -0
  284. package/dist/ui/overlay/data/tutorial-registry.d.ts +12 -0
  285. package/dist/ui/overlay/data/tutorial-registry.js +116 -0
  286. package/dist/ui/overlay/data/tutorial-types.d.ts +35 -0
  287. package/dist/ui/overlay/data/tutorial-types.js +6 -0
  288. package/dist/ui/overlay/data/tutorials/basics/first-conversation.d.ts +7 -0
  289. package/dist/ui/overlay/data/tutorials/basics/first-conversation.js +220 -0
  290. package/dist/ui/overlay/data/tutorials/basics/first-project.d.ts +7 -0
  291. package/dist/ui/overlay/data/tutorials/basics/first-project.js +284 -0
  292. package/dist/ui/overlay/data/tutorials/basics/navigation.d.ts +8 -0
  293. package/dist/ui/overlay/data/tutorials/basics/navigation.js +22 -0
  294. package/dist/ui/overlay/data/tutorials/basics/welcome.d.ts +7 -0
  295. package/dist/ui/overlay/data/tutorials/basics/welcome.js +174 -0
  296. package/dist/ui/overlay/data/tutorials/config/context-management.d.ts +7 -0
  297. package/dist/ui/overlay/data/tutorials/config/context-management.js +158 -0
  298. package/dist/ui/overlay/data/tutorials/config/mcp-servers.d.ts +8 -0
  299. package/dist/ui/overlay/data/tutorials/config/mcp-servers.js +155 -0
  300. package/dist/ui/overlay/data/tutorials/config/model-selection.d.ts +7 -0
  301. package/dist/ui/overlay/data/tutorials/config/model-selection.js +162 -0
  302. package/dist/ui/overlay/data/tutorials/config/permissions-safety.d.ts +7 -0
  303. package/dist/ui/overlay/data/tutorials/config/permissions-safety.js +163 -0
  304. package/dist/ui/overlay/data/tutorials/config/settings-config.d.ts +7 -0
  305. package/dist/ui/overlay/data/tutorials/config/settings-config.js +166 -0
  306. package/dist/ui/overlay/data/tutorials/planning/arch.d.ts +7 -0
  307. package/dist/ui/overlay/data/tutorials/planning/arch.js +168 -0
  308. package/dist/ui/overlay/data/tutorials/planning/backlog.d.ts +7 -0
  309. package/dist/ui/overlay/data/tutorials/planning/backlog.js +103 -0
  310. package/dist/ui/overlay/data/tutorials/planning/build.d.ts +7 -0
  311. package/dist/ui/overlay/data/tutorials/planning/build.js +173 -0
  312. package/dist/ui/overlay/data/tutorials/planning/design.d.ts +7 -0
  313. package/dist/ui/overlay/data/tutorials/planning/design.js +205 -0
  314. package/dist/ui/overlay/data/tutorials/planning/docs.d.ts +7 -0
  315. package/dist/ui/overlay/data/tutorials/planning/docs.js +143 -0
  316. package/dist/ui/overlay/data/tutorials/planning/prd.d.ts +7 -0
  317. package/dist/ui/overlay/data/tutorials/planning/prd.js +173 -0
  318. package/dist/ui/overlay/data/tutorials/planning/scaffold.d.ts +7 -0
  319. package/dist/ui/overlay/data/tutorials/planning/scaffold.js +164 -0
  320. package/dist/ui/overlay/data/tutorials/planning/sketch.d.ts +7 -0
  321. package/dist/ui/overlay/data/tutorials/planning/sketch.js +58 -0
  322. package/dist/ui/overlay/data/tutorials/projects/anchors.d.ts +7 -0
  323. package/dist/ui/overlay/data/tutorials/projects/anchors.js +248 -0
  324. package/dist/ui/overlay/data/tutorials/projects/import-project.d.ts +7 -0
  325. package/dist/ui/overlay/data/tutorials/projects/import-project.js +172 -0
  326. package/dist/ui/overlay/data/tutorials/projects/managing-projects.d.ts +8 -0
  327. package/dist/ui/overlay/data/tutorials/projects/managing-projects.js +212 -0
  328. package/dist/ui/overlay/data/tutorials/projects/new-project.d.ts +7 -0
  329. package/dist/ui/overlay/data/tutorials/projects/new-project.js +251 -0
  330. package/dist/ui/overlay/data/tutorials/projects/session-management.d.ts +7 -0
  331. package/dist/ui/overlay/data/tutorials/projects/session-management.js +169 -0
  332. package/dist/ui/overlay/data/tutorials/teams/background-execution.d.ts +7 -0
  333. package/dist/ui/overlay/data/tutorials/teams/background-execution.js +171 -0
  334. package/dist/ui/overlay/data/tutorials/teams/multi-terminal.d.ts +8 -0
  335. package/dist/ui/overlay/data/tutorials/teams/multi-terminal.js +147 -0
  336. package/dist/ui/overlay/data/tutorials/teams/task-assignment.d.ts +7 -0
  337. package/dist/ui/overlay/data/tutorials/teams/task-assignment.js +204 -0
  338. package/dist/ui/overlay/data/tutorials/teams/team-overview.d.ts +7 -0
  339. package/dist/ui/overlay/data/tutorials/teams/team-overview.js +165 -0
  340. package/dist/ui/overlay/data/tutorials/teams/working-with-agents.d.ts +7 -0
  341. package/dist/ui/overlay/data/tutorials/teams/working-with-agents.js +172 -0
  342. package/dist/ui/overlay/impl/agents-overlay-v2.js +6 -17
  343. package/dist/ui/overlay/impl/anchors-overlay-v2.js +30 -64
  344. package/dist/ui/overlay/impl/artifact-detail-overlay-v2.d.ts +43 -0
  345. package/dist/ui/overlay/impl/artifact-detail-overlay-v2.js +232 -0
  346. package/dist/ui/overlay/impl/artifact-overlay-v2.d.ts +40 -0
  347. package/dist/ui/overlay/impl/artifact-overlay-v2.js +115 -0
  348. package/dist/ui/overlay/impl/ask-user-overlay-v2.js +2 -5
  349. package/dist/ui/overlay/impl/background-overlay-v2.d.ts +40 -0
  350. package/dist/ui/overlay/impl/background-overlay-v2.js +147 -0
  351. package/dist/ui/overlay/impl/backlog-overlay-v2.d.ts +4 -1
  352. package/dist/ui/overlay/impl/backlog-overlay-v2.js +55 -16
  353. package/dist/ui/overlay/impl/changelog-overlay-v2.d.ts +44 -0
  354. package/dist/ui/overlay/impl/changelog-overlay-v2.js +165 -0
  355. package/dist/ui/overlay/impl/commands-overlay-v2.js +4 -6
  356. package/dist/ui/overlay/impl/config-overlay-v2.d.ts +12 -1
  357. package/dist/ui/overlay/impl/config-overlay-v2.js +164 -100
  358. package/dist/ui/overlay/impl/custom-agent-form-overlay-v2.d.ts +83 -0
  359. package/dist/ui/overlay/impl/custom-agent-form-overlay-v2.js +711 -0
  360. package/dist/ui/overlay/impl/dashboard-overlay-v2.d.ts +2 -0
  361. package/dist/ui/overlay/impl/dashboard-overlay-v2.js +26 -3
  362. package/dist/ui/overlay/impl/delegations-overlay-v2.d.ts +28 -0
  363. package/dist/ui/overlay/impl/delegations-overlay-v2.js +279 -0
  364. package/dist/ui/overlay/impl/docs-overlay-v2.js +12 -9
  365. package/dist/ui/overlay/impl/document-detail-overlay-v2.d.ts +7 -0
  366. package/dist/ui/overlay/impl/document-detail-overlay-v2.js +119 -78
  367. package/dist/ui/overlay/impl/filter-overlay-v2.d.ts +41 -0
  368. package/dist/ui/overlay/impl/filter-overlay-v2.js +110 -0
  369. package/dist/ui/overlay/impl/games-overlay-v2.d.ts +31 -0
  370. package/dist/ui/overlay/impl/games-overlay-v2.js +135 -0
  371. package/dist/ui/overlay/impl/help-overlay-v2.d.ts +26 -3
  372. package/dist/ui/overlay/impl/help-overlay-v2.js +20 -42
  373. package/dist/ui/overlay/impl/login-overlay-v2.d.ts +49 -0
  374. package/dist/ui/overlay/impl/login-overlay-v2.js +277 -0
  375. package/dist/ui/overlay/impl/mcp-overlay-v2.d.ts +63 -0
  376. package/dist/ui/overlay/impl/mcp-overlay-v2.js +907 -0
  377. package/dist/ui/overlay/impl/model-overlay-v2.d.ts +57 -13
  378. package/dist/ui/overlay/impl/model-overlay-v2.js +1086 -61
  379. package/dist/ui/overlay/impl/new-overlay-v2.d.ts +37 -6
  380. package/dist/ui/overlay/impl/new-overlay-v2.js +715 -65
  381. package/dist/ui/overlay/impl/notifications-overlay-v2.d.ts +20 -0
  382. package/dist/ui/overlay/impl/notifications-overlay-v2.js +116 -0
  383. package/dist/ui/overlay/impl/onboarding-wizard-overlay-v2.d.ts +76 -0
  384. package/dist/ui/overlay/impl/onboarding-wizard-overlay-v2.js +728 -0
  385. package/dist/ui/overlay/impl/pending-overlay-v2.d.ts +51 -0
  386. package/dist/ui/overlay/impl/pending-overlay-v2.js +445 -0
  387. package/dist/ui/overlay/impl/permission-overlay-v2.js +5 -5
  388. package/dist/ui/overlay/impl/permissions-overlay-v2.d.ts +85 -0
  389. package/dist/ui/overlay/impl/permissions-overlay-v2.js +820 -0
  390. package/dist/ui/overlay/impl/plan-approval-overlay-v2.d.ts +35 -0
  391. package/dist/ui/overlay/impl/plan-approval-overlay-v2.js +181 -0
  392. package/dist/ui/overlay/impl/project-edit-overlay-v2.d.ts +36 -0
  393. package/dist/ui/overlay/impl/project-edit-overlay-v2.js +195 -0
  394. package/dist/ui/overlay/impl/projects-overlay-v2.d.ts +1 -0
  395. package/dist/ui/overlay/impl/projects-overlay-v2.js +278 -44
  396. package/dist/ui/overlay/impl/reset-overlay-v2.d.ts +39 -0
  397. package/dist/ui/overlay/impl/reset-overlay-v2.js +107 -0
  398. package/dist/ui/overlay/impl/resume-overlay-v2.d.ts +60 -0
  399. package/dist/ui/overlay/impl/resume-overlay-v2.js +414 -0
  400. package/dist/ui/overlay/impl/session-mode-overlay-v2.d.ts +43 -0
  401. package/dist/ui/overlay/impl/session-mode-overlay-v2.js +124 -0
  402. package/dist/ui/overlay/impl/tasks-overlay-v2.d.ts +28 -0
  403. package/dist/ui/overlay/impl/tasks-overlay-v2.js +283 -0
  404. package/dist/ui/overlay/impl/team-overlay-v2.d.ts +86 -0
  405. package/dist/ui/overlay/impl/team-overlay-v2.js +692 -0
  406. package/dist/ui/overlay/impl/terminals-overlay-v2.d.ts +26 -0
  407. package/dist/ui/overlay/impl/terminals-overlay-v2.js +217 -0
  408. package/dist/ui/overlay/impl/tools-overlay-v2.js +3 -7
  409. package/dist/ui/overlay/impl/tutorial-overlay-v2.d.ts +30 -16
  410. package/dist/ui/overlay/impl/tutorial-overlay-v2.js +133 -956
  411. package/dist/ui/overlay/impl/workflow-overlay-v2.d.ts +1 -0
  412. package/dist/ui/overlay/impl/workflow-overlay-v2.js +10 -4
  413. package/dist/ui/overlay/index.d.ts +20 -1
  414. package/dist/ui/overlay/index.js +19 -0
  415. package/dist/ui/overlay/types.d.ts +5 -0
  416. package/dist/ui/overlay-manager.d.ts +43 -0
  417. package/dist/ui/overlay-manager.js +238 -0
  418. package/dist/ui/overlays.js +4 -16
  419. package/dist/ui/permission-overlay.js +6 -5
  420. package/dist/ui/status-bar-controller.d.ts +33 -0
  421. package/dist/ui/status-bar-controller.js +99 -0
  422. package/dist/ui/subagent-renderer.js +3 -19
  423. package/dist/ui/terminal-autocomplete-utils.d.ts +23 -0
  424. package/dist/ui/terminal-autocomplete-utils.js +83 -0
  425. package/dist/ui/terminal-line-builders.d.ts +17 -0
  426. package/dist/ui/terminal-line-builders.js +42 -0
  427. package/dist/ui/terminal-render-item.d.ts +16 -0
  428. package/dist/ui/terminal-render-item.js +267 -0
  429. package/dist/ui/terminal-renderer.d.ts +7 -8
  430. package/dist/ui/terminal-renderer.js +7 -8
  431. package/dist/ui/terminal-types.d.ts +179 -0
  432. package/dist/ui/terminal-types.js +34 -0
  433. package/dist/ui/terminal-ui.d.ts +144 -276
  434. package/dist/ui/terminal-ui.js +384 -1861
  435. package/dist/ui/todo-zone.d.ts +19 -1
  436. package/dist/ui/todo-zone.js +71 -13
  437. package/dist/ui/tool-formatters.js +696 -1
  438. package/dist/ui/turn-metrics.d.ts +56 -0
  439. package/dist/ui/turn-metrics.js +75 -0
  440. package/dist/ui/types.d.ts +28 -0
  441. package/dist/ui/types.js +1 -0
  442. package/dist/ui/vscode-diff-ipc.d.ts +102 -0
  443. package/dist/ui/vscode-diff-ipc.js +385 -0
  444. package/dist/utils/credentials.d.ts +24 -5
  445. package/dist/utils/credentials.js +123 -9
  446. package/dist/utils/format-tokens.d.ts +13 -0
  447. package/dist/utils/format-tokens.js +18 -0
  448. package/dist/utils/git-config.d.ts +26 -0
  449. package/dist/utils/git-config.js +54 -0
  450. package/dist/utils/message-utils.d.ts +61 -0
  451. package/dist/utils/message-utils.js +72 -0
  452. package/dist/utils/model-tiers.d.ts +8 -1
  453. package/dist/utils/model-tiers.js +38 -16
  454. package/dist/utils/open-browser.d.ts +5 -0
  455. package/dist/utils/open-browser.js +32 -0
  456. package/dist/utils/path-safety.js +3 -2
  457. package/dist/utils/project-detection.d.ts +58 -0
  458. package/dist/utils/project-detection.js +424 -0
  459. package/dist/utils/project-memory.js +2 -1
  460. package/dist/utils/project-status.d.ts +2 -2
  461. package/dist/utils/startup-perf.d.ts +18 -0
  462. package/dist/utils/startup-perf.js +60 -0
  463. package/dist/utils/token-tracker.d.ts +62 -0
  464. package/dist/utils/token-tracker.js +150 -0
  465. package/dist/utils/token-types.d.ts +23 -0
  466. package/dist/utils/token-types.js +18 -0
  467. package/dist/utils/types/config-types.d.ts +32 -0
  468. package/dist/utils/types/config-types.js +8 -0
  469. package/dist/utils/update-checker.d.ts +28 -0
  470. package/dist/utils/update-checker.js +106 -0
  471. package/dist/utils/version.d.ts +7 -0
  472. package/dist/utils/version.js +10 -0
  473. package/dist/utils/vscode-detect.d.ts +39 -0
  474. package/dist/utils/vscode-detect.js +137 -0
  475. package/package.json +27 -13
  476. package/dist/commands/handler-types.d.ts +0 -68
  477. package/dist/commands/handler-types.js +0 -8
  478. package/dist/commands/handlers/agent-commands.d.ts +0 -13
  479. package/dist/commands/handlers/agent-commands.js +0 -305
  480. package/dist/commands/handlers/design-commands.d.ts +0 -15
  481. package/dist/commands/handlers/design-commands.js +0 -334
  482. package/dist/commands/handlers/index.d.ts +0 -20
  483. package/dist/commands/handlers/index.js +0 -43
  484. package/dist/commands/handlers/overlay-commands.d.ts +0 -21
  485. package/dist/commands/handlers/overlay-commands.js +0 -287
  486. package/dist/commands/handlers/project-commands.d.ts +0 -11
  487. package/dist/commands/handlers/project-commands.js +0 -167
  488. package/dist/commands/handlers/simple-commands.d.ts +0 -19
  489. package/dist/commands/handlers/simple-commands.js +0 -144
  490. package/dist/commands/registry.d.ts +0 -50
  491. package/dist/commands/registry.js +0 -75
  492. package/dist/index.old.d.ts +0 -7
  493. package/dist/index.old.js +0 -1014
  494. package/dist/repl.d.ts +0 -149
  495. package/dist/repl.js +0 -1151
  496. package/dist/templates/claude-md.d.ts +0 -7
  497. package/dist/templates/claude-md.js +0 -189
  498. package/dist/test-autocomplete.d.ts +0 -7
  499. package/dist/test-autocomplete.js +0 -85
  500. package/dist/test-tabbed-menu.d.ts +0 -7
  501. package/dist/test-tabbed-menu.js +0 -25
  502. package/dist/tool-selector.d.ts +0 -71
  503. package/dist/tool-selector.js +0 -184
  504. package/dist/tools/anchor-tools.d.ts +0 -31
  505. package/dist/tools/anchor-tools.js +0 -255
  506. package/dist/tools/backlog-wrappers.d.ts +0 -54
  507. package/dist/tools/backlog-wrappers.js +0 -338
  508. package/dist/tools/document-db.d.ts +0 -43
  509. package/dist/tools/document-db.js +0 -220
  510. package/dist/tools/workitem-db.d.ts +0 -103
  511. package/dist/tools/workitem-db.js +0 -549
  512. package/dist/ui/agents-overlay-v2.d.ts +0 -43
  513. package/dist/ui/agents-overlay-v2.js +0 -809
  514. package/dist/ui/agents-overlay.d.ts +0 -12
  515. package/dist/ui/agents-overlay.js +0 -863
  516. package/dist/ui/anchors-overlay.d.ts +0 -12
  517. package/dist/ui/anchors-overlay.js +0 -775
  518. package/dist/ui/arch-type-overlay.d.ts +0 -15
  519. package/dist/ui/arch-type-overlay.js +0 -201
  520. package/dist/ui/ask-user-overlay-v2.d.ts +0 -26
  521. package/dist/ui/ask-user-overlay-v2.js +0 -555
  522. package/dist/ui/ask-user-simple-overlay-v2.d.ts +0 -25
  523. package/dist/ui/ask-user-simple-overlay-v2.js +0 -215
  524. package/dist/ui/backlog-overlay.d.ts +0 -32
  525. package/dist/ui/backlog-overlay.js +0 -652
  526. package/dist/ui/commands-overlay-v2.d.ts +0 -33
  527. package/dist/ui/commands-overlay-v2.js +0 -441
  528. package/dist/ui/commands-overlay.d.ts +0 -16
  529. package/dist/ui/commands-overlay.js +0 -439
  530. package/dist/ui/config-overlay.d.ts +0 -35
  531. package/dist/ui/config-overlay.js +0 -707
  532. package/dist/ui/docs-overlay.d.ts +0 -17
  533. package/dist/ui/docs-overlay.js +0 -303
  534. package/dist/ui/footer-v2.d.ts +0 -222
  535. package/dist/ui/footer-v2.js +0 -1349
  536. package/dist/ui/help-overlay-v2.d.ts +0 -34
  537. package/dist/ui/help-overlay-v2.js +0 -309
  538. package/dist/ui/help-overlay.d.ts +0 -16
  539. package/dist/ui/help-overlay.js +0 -316
  540. package/dist/ui/init-overlay-v2.d.ts +0 -34
  541. package/dist/ui/init-overlay-v2.js +0 -600
  542. package/dist/ui/init-overlay.d.ts +0 -34
  543. package/dist/ui/init-overlay.js +0 -604
  544. package/dist/ui/input-prompt-v2.d.ts +0 -180
  545. package/dist/ui/input-prompt-v2.js +0 -999
  546. package/dist/ui/iteration-limit-overlay-v2.d.ts +0 -21
  547. package/dist/ui/iteration-limit-overlay-v2.js +0 -114
  548. package/dist/ui/keys-overlay-v2.d.ts +0 -41
  549. package/dist/ui/keys-overlay-v2.js +0 -248
  550. package/dist/ui/mascot-overlay-v2.d.ts +0 -41
  551. package/dist/ui/mascot-overlay-v2.js +0 -138
  552. package/dist/ui/mascot-overlay.d.ts +0 -21
  553. package/dist/ui/mascot-overlay.js +0 -146
  554. package/dist/ui/model-overlay-v2.d.ts +0 -49
  555. package/dist/ui/model-overlay-v2.js +0 -118
  556. package/dist/ui/model-overlay.d.ts +0 -27
  557. package/dist/ui/model-overlay.js +0 -221
  558. package/dist/ui/model-warning-overlay.d.ts +0 -30
  559. package/dist/ui/model-warning-overlay.js +0 -169
  560. package/dist/ui/new-overlay.d.ts +0 -34
  561. package/dist/ui/new-overlay.js +0 -604
  562. package/dist/ui/overlay/impl/init-overlay-v2.d.ts +0 -77
  563. package/dist/ui/overlay/impl/init-overlay-v2.js +0 -593
  564. package/dist/ui/overlay/overlay-types.d.ts +0 -128
  565. package/dist/ui/overlay/overlay-types.js +0 -22
  566. package/dist/ui/overlays/help-overlay-v2.d.ts +0 -28
  567. package/dist/ui/overlays/help-overlay-v2.js +0 -198
  568. package/dist/ui/overlays/index.d.ts +0 -11
  569. package/dist/ui/overlays/index.js +0 -11
  570. package/dist/ui/permission-overlay-v2.d.ts +0 -36
  571. package/dist/ui/permission-overlay-v2.js +0 -380
  572. package/dist/ui/projects-overlay.d.ts +0 -19
  573. package/dist/ui/projects-overlay.js +0 -484
  574. package/dist/ui/theme-overlay-v2.d.ts +0 -42
  575. package/dist/ui/theme-overlay-v2.js +0 -135
  576. package/dist/ui/theme-overlay.d.ts +0 -24
  577. package/dist/ui/theme-overlay.js +0 -127
  578. package/dist/ui/tools-overlay-v2.d.ts +0 -47
  579. package/dist/ui/tools-overlay-v2.js +0 -218
  580. package/dist/ui/tools-overlay.d.ts +0 -34
  581. package/dist/ui/tools-overlay.js +0 -230
  582. package/dist/ui/tutorial-overlay-v2.d.ts +0 -31
  583. package/dist/ui/tutorial-overlay-v2.js +0 -1035
  584. package/dist/ui/tutorial-overlay.d.ts +0 -11
  585. package/dist/ui/tutorial-overlay.js +0 -1034
  586. package/dist/ui/workflow-overlay.d.ts +0 -22
  587. package/dist/ui/workflow-overlay.js +0 -636
@@ -1,999 +0,0 @@
1
- /**
2
- * Input Prompt v2 (Event-Driven)
3
- *
4
- * Refactored input handling with event-driven architecture.
5
- * - Emits events instead of blocking with getInput()
6
- * - Supports queue mode for capturing input during agent execution
7
- * - Always captures keystrokes (no blocking)
8
- *
9
- * Events:
10
- * - 'submit' - User pressed Enter with input
11
- * - 'command' - User submitted a slash command
12
- * - 'cancel' - User pressed Ctrl+C
13
- * - 'escape' - User pressed Esc (for aborting agent)
14
- * - 'change' - Input text changed
15
- */
16
- import { EventEmitter } from 'events';
17
- import chalk from 'chalk';
18
- import { getStyles } from '../themes/index.js';
19
- import * as terminal from './terminal.js';
20
- import { getAutocompleteCommands } from '../commands.js';
21
- import { getFileMatches, extractAtMention, replaceAtMention, } from './file-autocomplete.js';
22
- import { debugRender } from '../utils/debug-log.js';
23
- import { stripAnsi as unifiedStripAnsi, getPhysicalLineCountWithOffset, } from './line-utils.js';
24
- // =============================================================================
25
- // Constants
26
- // =============================================================================
27
- const MAX_VISIBLE_COMMANDS = 10;
28
- // =============================================================================
29
- // Default Commands (from central registry)
30
- // =============================================================================
31
- export const DEFAULT_COMMANDS = getAutocompleteCommands();
32
- // =============================================================================
33
- // Helper Functions
34
- // =============================================================================
35
- /**
36
- * Strip ANSI codes from string
37
- * Uses unified line-utils for consistent behavior across components.
38
- */
39
- export function stripAnsi(str) {
40
- return unifiedStripAnsi(str);
41
- }
42
- /**
43
- * Calculate physical lines for wrapped text
44
- * Uses unified line-utils for consistent behavior across components.
45
- */
46
- function calcPhysicalLines(text, startCol, termWidth) {
47
- return getPhysicalLineCountWithOffset(text, startCol, termWidth);
48
- }
49
- /**
50
- * Calculate fuzzy match score for a query against a target string.
51
- * Higher score = better match.
52
- * Returns -1 if no match.
53
- */
54
- function fuzzyMatchScore(query, target) {
55
- const queryLower = query.toLowerCase();
56
- const targetLower = target.toLowerCase();
57
- // Exact prefix match - highest priority (score 1000+)
58
- if (targetLower.startsWith(queryLower)) {
59
- return 1000 + (100 - target.length); // Shorter commands rank higher
60
- }
61
- // Contiguous substring match - high priority (score 500+)
62
- if (targetLower.includes(queryLower)) {
63
- const index = targetLower.indexOf(queryLower);
64
- return 500 + (100 - index); // Earlier matches rank higher
65
- }
66
- // Fuzzy match - characters appear in order (score 100+)
67
- let queryIdx = 0;
68
- let consecutiveBonus = 0;
69
- let lastMatchIdx = -1;
70
- for (let i = 0; i < targetLower.length && queryIdx < queryLower.length; i++) {
71
- if (targetLower[i] === queryLower[queryIdx]) {
72
- // Bonus for consecutive matches
73
- if (lastMatchIdx === i - 1) {
74
- consecutiveBonus += 10;
75
- }
76
- lastMatchIdx = i;
77
- queryIdx++;
78
- }
79
- }
80
- // All query characters found in order
81
- if (queryIdx === queryLower.length) {
82
- return 100 + consecutiveBonus + (100 - target.length);
83
- }
84
- // No match
85
- return -1;
86
- }
87
- /**
88
- * Filter and rank commands matching input using fuzzy matching
89
- */
90
- function filterCommands(input, commands) {
91
- // Score all commands
92
- const scored = commands
93
- .map((cmd) => ({
94
- cmd,
95
- score: fuzzyMatchScore(input, cmd.command),
96
- }))
97
- .filter((item) => item.score >= 0);
98
- // Sort by score (highest first)
99
- scored.sort((a, b) => b.score - a.score);
100
- return scored.map((item) => item.cmd);
101
- }
102
- // =============================================================================
103
- // Input Prompt Class
104
- // =============================================================================
105
- export class InputPrompt extends EventEmitter {
106
- // Configuration
107
- prompt;
108
- promptLen;
109
- showSeparators;
110
- commands;
111
- // Input state
112
- state = {
113
- lines: [''],
114
- currentLine: 0,
115
- cursorPos: 0,
116
- };
117
- // Command autocomplete (for /commands)
118
- autocomplete = {
119
- active: false,
120
- matches: [],
121
- selectedIndex: 0,
122
- scrollOffset: 0,
123
- };
124
- // File autocomplete (for @paths)
125
- fileAutocomplete = {
126
- active: false,
127
- matches: [],
128
- selectedIndex: 0,
129
- scrollOffset: 0,
130
- partial: '',
131
- };
132
- // History
133
- history = [];
134
- historyIndex = -1;
135
- savedInput = '';
136
- // Queue mode
137
- queueMode = false;
138
- queuedInputs = [];
139
- // Rendering tracking
140
- renderedLines = 0;
141
- dropdownLines = 0;
142
- linesAboveCursor = 0;
143
- hasSeparators = false;
144
- // Control
145
- isRunning = false;
146
- // Double Esc detection
147
- lastEscTime = 0;
148
- DOUBLE_ESC_THRESHOLD_MS = 500; // 500ms window for double Esc
149
- // Suggestion (ghost text for next action)
150
- suggestion = null;
151
- constructor(options = {}) {
152
- super();
153
- this.prompt = options.prompt ?? getStyles().primary('❯ ');
154
- this.promptLen = stripAnsi(this.prompt).length;
155
- this.showSeparators = options.showSeparators ?? true;
156
- this.commands = options.commands ?? DEFAULT_COMMANDS;
157
- }
158
- // ===========================================================================
159
- // Public API
160
- // ===========================================================================
161
- /**
162
- * Update the prompt string (for dynamic theme changes)
163
- */
164
- setPrompt(prompt) {
165
- this.prompt = prompt;
166
- this.promptLen = stripAnsi(prompt).length;
167
- }
168
- /**
169
- * Set a suggestion for the next action (ghost text)
170
- */
171
- setSuggestion(action) {
172
- this.suggestion = action;
173
- }
174
- /**
175
- * Get the current suggestion
176
- */
177
- getSuggestion() {
178
- return this.suggestion;
179
- }
180
- /**
181
- * Clear the current suggestion
182
- */
183
- clearSuggestion() {
184
- this.suggestion = null;
185
- }
186
- /**
187
- * Start input capture (non-blocking, event-driven)
188
- */
189
- start() {
190
- if (this.isRunning)
191
- return;
192
- this.isRunning = true;
193
- terminal.enableRawMode();
194
- this.resetState();
195
- process.stdin.on('data', this.handleData);
196
- }
197
- /**
198
- * Stop input capture
199
- */
200
- stop() {
201
- if (!this.isRunning)
202
- return;
203
- this.isRunning = false;
204
- terminal.disableRawMode();
205
- process.stdin.removeListener('data', this.handleData);
206
- }
207
- /**
208
- * Check if running
209
- */
210
- isActive() {
211
- return this.isRunning;
212
- }
213
- /**
214
- * Enable/disable queue mode
215
- * In queue mode, Enter adds to queue instead of emitting 'submit'
216
- */
217
- setQueueMode(enabled) {
218
- this.queueMode = enabled;
219
- }
220
- /**
221
- * Check if in queue mode
222
- */
223
- isQueueMode() {
224
- return this.queueMode;
225
- }
226
- /**
227
- * Get all queued inputs (FIFO order)
228
- */
229
- getQueuedInputs() {
230
- return [...this.queuedInputs];
231
- }
232
- /**
233
- * Pop the first queued input
234
- */
235
- popQueuedInput() {
236
- return this.queuedInputs.shift() ?? null;
237
- }
238
- /**
239
- * Check if there are queued inputs
240
- */
241
- hasQueuedInput() {
242
- return this.queuedInputs.length > 0;
243
- }
244
- /**
245
- * Get number of queued inputs
246
- */
247
- getQueueLength() {
248
- return this.queuedInputs.length;
249
- }
250
- /**
251
- * Clear the queue
252
- */
253
- clearQueue() {
254
- this.queuedInputs = [];
255
- }
256
- /**
257
- * Get current buffer value
258
- */
259
- getValue() {
260
- return this.state.lines.join('\n');
261
- }
262
- /**
263
- * Set buffer value
264
- */
265
- setValue(value) {
266
- this.state.lines = value.split('\n');
267
- this.state.currentLine = this.state.lines.length - 1;
268
- this.state.cursorPos = this.state.lines[this.state.currentLine].length;
269
- this.updateAutocomplete();
270
- }
271
- /**
272
- * Clear input buffer
273
- */
274
- clearInput() {
275
- this.state = {
276
- lines: [''],
277
- currentLine: 0,
278
- cursorPos: 0,
279
- };
280
- this.autocomplete = {
281
- active: false,
282
- matches: [],
283
- selectedIndex: 0,
284
- scrollOffset: 0,
285
- };
286
- this.fileAutocomplete = {
287
- active: false,
288
- matches: [],
289
- selectedIndex: 0,
290
- scrollOffset: 0,
291
- partial: '',
292
- };
293
- }
294
- /**
295
- * Add command to history
296
- */
297
- addToHistory(input) {
298
- if (input.trim() && (this.history.length === 0 || this.history[this.history.length - 1] !== input)) {
299
- this.history.push(input);
300
- }
301
- }
302
- /**
303
- * Render the input prompt - returns array of lines
304
- * Does NOT write to terminal (Footer handles that)
305
- */
306
- render() {
307
- const lines = [];
308
- // Top separator
309
- if (this.showSeparators) {
310
- lines.push(this.getSeparatorLine());
311
- }
312
- // Input lines
313
- const s = getStyles();
314
- for (let i = 0; i < this.state.lines.length; i++) {
315
- const linePrompt = i === 0 ? this.prompt : s.muted(' \\ ');
316
- const lineContent = this.state.lines[i];
317
- // Show suggestion as ghost text on first line when input is empty
318
- if (i === 0 && lineContent === '' && this.suggestion && !this.autocomplete.active && !this.fileAutocomplete.active) {
319
- const hint = s.muted(' (tab to accept)');
320
- lines.push(linePrompt + s.muted(this.suggestion) + hint);
321
- }
322
- else {
323
- lines.push(linePrompt + lineContent);
324
- }
325
- }
326
- // Bottom separator
327
- if (this.showSeparators) {
328
- lines.push(this.getSeparatorLine());
329
- }
330
- return lines;
331
- }
332
- /**
333
- * Get the cursor position info for rendering
334
- */
335
- getCursorInfo() {
336
- const termWidth = terminal.getTerminalWidth();
337
- const currentLinePromptLen = this.state.currentLine === 0 ? this.promptLen : 5;
338
- const cursorAbsPos = currentLinePromptLen + this.state.cursorPos;
339
- // Calculate which row within input (accounting for separators)
340
- let row = this.showSeparators ? 1 : 0; // Start after top separator
341
- for (let i = 0; i < this.state.currentLine; i++) {
342
- const lp = i === 0 ? this.promptLen : 5;
343
- row += calcPhysicalLines(this.state.lines[i], lp, termWidth);
344
- }
345
- row += Math.floor(cursorAbsPos / termWidth);
346
- const col = cursorAbsPos % termWidth;
347
- debugRender('InputPrompt:getCursorInfo', `termWidth=${termWidth} cursorPos=${this.state.cursorPos} currentLine=${this.state.currentLine} promptLen=${this.promptLen}`);
348
- debugRender('InputPrompt:getCursorInfo', `cursorAbsPos=${cursorAbsPos} row=${row} col=${col}`);
349
- return { row, col };
350
- }
351
- /**
352
- * Get autocomplete dropdown lines (if active)
353
- */
354
- getAutocompleteLines() {
355
- const s = getStyles();
356
- // File autocomplete takes priority
357
- if (this.fileAutocomplete.active && this.fileAutocomplete.matches.length > 0) {
358
- const lines = [];
359
- const offset = this.fileAutocomplete.scrollOffset;
360
- const visible = this.fileAutocomplete.matches.slice(offset, offset + MAX_VISIBLE_COMMANDS);
361
- const total = this.fileAutocomplete.matches.length;
362
- // Show scroll indicator if there are more items above
363
- if (offset > 0) {
364
- lines.push(s.muted(` ↑ ${String(offset)} more above`));
365
- }
366
- for (let i = 0; i < visible.length; i++) {
367
- const file = visible[i];
368
- const actualIndex = offset + i;
369
- const isSelected = actualIndex === this.fileAutocomplete.selectedIndex;
370
- const prefix = isSelected ? s.primary('❯ ') : ' ';
371
- const icon = file.isDirectory ? s.warning('📁 ') : s.info('📄 ');
372
- const name = isSelected ? s.primary(chalk.bold(file.path)) : file.path;
373
- lines.push(`${prefix}${icon}${name}`);
374
- }
375
- // Show scroll indicator if there are more items below
376
- const remaining = total - offset - visible.length;
377
- if (remaining > 0) {
378
- lines.push(s.muted(` ↓ ${String(remaining)} more below`));
379
- }
380
- return lines;
381
- }
382
- // Command autocomplete
383
- if (!this.autocomplete.active || this.autocomplete.matches.length === 0) {
384
- return [];
385
- }
386
- const lines = [];
387
- const offset = this.autocomplete.scrollOffset;
388
- const visible = this.autocomplete.matches.slice(offset, offset + MAX_VISIBLE_COMMANDS);
389
- const total = this.autocomplete.matches.length;
390
- // Show scroll indicator if there are more items above
391
- if (offset > 0) {
392
- lines.push(s.muted(` ↑ ${String(offset)} more above`));
393
- }
394
- for (let i = 0; i < visible.length; i++) {
395
- const cmd = visible[i];
396
- const actualIndex = offset + i;
397
- const isSelected = actualIndex === this.autocomplete.selectedIndex;
398
- const prefix = isSelected ? s.primary('❯ ') : ' ';
399
- const name = isSelected ? s.primary(chalk.bold(cmd.command)) : cmd.command;
400
- const desc = s.muted(` - ${cmd.description}`);
401
- lines.push(`${prefix}${name}${desc}`);
402
- }
403
- // Show scroll indicator if there are more items below
404
- const remaining = total - offset - visible.length;
405
- if (remaining > 0) {
406
- lines.push(s.muted(` ↓ ${String(remaining)} more below`));
407
- }
408
- return lines;
409
- }
410
- /**
411
- * Check if autocomplete is showing
412
- */
413
- isAutocompleteActive() {
414
- return ((this.autocomplete.active && this.autocomplete.matches.length > 0) ||
415
- (this.fileAutocomplete.active && this.fileAutocomplete.matches.length > 0));
416
- }
417
- /**
418
- * Get height of rendered content
419
- */
420
- getHeight() {
421
- let height = this.state.lines.length;
422
- if (this.showSeparators)
423
- height += 2;
424
- return height;
425
- }
426
- // ===========================================================================
427
- // Legacy API (for backwards compatibility during migration)
428
- // ===========================================================================
429
- /**
430
- * @deprecated Use event-driven start() instead
431
- * Kept for backwards compatibility during migration
432
- */
433
- async getInput() {
434
- return new Promise((resolve) => {
435
- const onSubmit = (input) => {
436
- cleanup();
437
- resolve({ action: 'submit', value: input });
438
- };
439
- const onCommand = (command, args) => {
440
- cleanup();
441
- resolve({ action: 'command', command, args });
442
- };
443
- const onCancel = () => {
444
- cleanup();
445
- resolve({ action: 'cancel' });
446
- };
447
- const cleanup = () => {
448
- this.removeListener('submit', onSubmit);
449
- this.removeListener('command', onCommand);
450
- this.removeListener('cancel', onCancel);
451
- };
452
- this.on('submit', onSubmit);
453
- this.on('command', onCommand);
454
- this.on('cancel', onCancel);
455
- if (!this.isRunning) {
456
- this.start();
457
- }
458
- });
459
- }
460
- // ===========================================================================
461
- // Private: State Management
462
- // ===========================================================================
463
- resetState() {
464
- this.state = {
465
- lines: [''],
466
- currentLine: 0,
467
- cursorPos: 0,
468
- };
469
- this.autocomplete = {
470
- active: false,
471
- matches: [],
472
- selectedIndex: 0,
473
- scrollOffset: 0,
474
- };
475
- this.fileAutocomplete = {
476
- active: false,
477
- matches: [],
478
- selectedIndex: 0,
479
- scrollOffset: 0,
480
- partial: '',
481
- };
482
- this.historyIndex = -1;
483
- this.savedInput = '';
484
- this.renderedLines = 0;
485
- this.dropdownLines = 0;
486
- this.linesAboveCursor = 0;
487
- this.hasSeparators = false;
488
- }
489
- updateAutocomplete() {
490
- const fullInput = this.getValue();
491
- const currentLine = this.state.lines[this.state.currentLine];
492
- const cursorPos = this.state.cursorPos;
493
- // Check for @ file path autocomplete first
494
- const atMention = extractAtMention(currentLine, cursorPos);
495
- if (atMention !== null) {
496
- // File autocomplete mode
497
- this.autocomplete.active = false;
498
- this.autocomplete.matches = [];
499
- this.autocomplete.selectedIndex = 0;
500
- this.autocomplete.scrollOffset = 0;
501
- this.fileAutocomplete.active = true;
502
- this.fileAutocomplete.partial = atMention;
503
- this.fileAutocomplete.matches = getFileMatches(atMention);
504
- if (this.fileAutocomplete.selectedIndex >= this.fileAutocomplete.matches.length) {
505
- this.fileAutocomplete.selectedIndex = Math.max(0, this.fileAutocomplete.matches.length - 1);
506
- this.fileAutocomplete.scrollOffset = 0;
507
- }
508
- return;
509
- }
510
- // Reset file autocomplete
511
- this.fileAutocomplete.active = false;
512
- this.fileAutocomplete.matches = [];
513
- this.fileAutocomplete.selectedIndex = 0;
514
- this.fileAutocomplete.scrollOffset = 0;
515
- this.fileAutocomplete.partial = '';
516
- // Check for / command autocomplete
517
- if (fullInput.startsWith('/') && this.state.lines.length === 1) {
518
- this.autocomplete.active = true;
519
- // Refresh commands dynamically to include newly created custom commands
520
- const freshCommands = getAutocompleteCommands();
521
- this.autocomplete.matches = filterCommands(fullInput, freshCommands);
522
- if (this.autocomplete.selectedIndex >= this.autocomplete.matches.length) {
523
- this.autocomplete.selectedIndex = Math.max(0, this.autocomplete.matches.length - 1);
524
- this.autocomplete.scrollOffset = 0;
525
- }
526
- }
527
- else {
528
- this.autocomplete.active = false;
529
- this.autocomplete.matches = [];
530
- this.autocomplete.selectedIndex = 0;
531
- this.autocomplete.scrollOffset = 0;
532
- }
533
- }
534
- getSeparatorLine() {
535
- const s = getStyles();
536
- return s.muted('─'.repeat(terminal.getTerminalWidth()));
537
- }
538
- // ===========================================================================
539
- // Private: Input Handling
540
- // ===========================================================================
541
- handleData = (data) => {
542
- if (!this.isRunning)
543
- return;
544
- const key = data.toString();
545
- this.handleKey(key, data);
546
- };
547
- handleKey(key, data) {
548
- // Detect special keys
549
- const isEscape = data.length === 1 && data[0] === 0x1b;
550
- const isEnter = key === '\r' || key === '\n';
551
- const isBackspace = key === '\x7f' || key === '\b';
552
- const isTab = key === '\t';
553
- const isShiftTab = data.length === 3 && data[0] === 0x1b && data[1] === 0x5b && data[2] === 0x5a;
554
- const isCtrlC = key === '\x03';
555
- const isCtrlO = key === '\x0f'; // Ctrl+O for toggle subagent expand
556
- const isUpArrow = data.length === 3 && data[0] === 0x1b && data[1] === 0x5b && data[2] === 0x41;
557
- const isDownArrow = data.length === 3 && data[0] === 0x1b && data[1] === 0x5b && data[2] === 0x42;
558
- const isLeftArrow = data.length === 3 && data[0] === 0x1b && data[1] === 0x5b && data[2] === 0x44;
559
- const isRightArrow = data.length === 3 && data[0] === 0x1b && data[1] === 0x5b && data[2] === 0x43;
560
- // Mac Option + Arrow (word navigation)
561
- const isOptionLeft = (data.length === 6 &&
562
- data[0] === 0x1b &&
563
- data[1] === 0x5b &&
564
- data[2] === 0x31 &&
565
- data[3] === 0x3b &&
566
- data[4] === 0x33 &&
567
- data[5] === 0x44) ||
568
- (data.length === 2 && data[0] === 0x1b && data[1] === 0x62);
569
- const isOptionRight = (data.length === 6 &&
570
- data[0] === 0x1b &&
571
- data[1] === 0x5b &&
572
- data[2] === 0x31 &&
573
- data[3] === 0x3b &&
574
- data[4] === 0x33 &&
575
- data[5] === 0x43) ||
576
- (data.length === 2 && data[0] === 0x1b && data[1] === 0x66);
577
- // Home/End (Cmd+Left/Right on Mac, or Home/End keys)
578
- const isHome = key === '\x01' || (data.length === 3 && data[0] === 0x1b && data[1] === 0x5b && data[2] === 0x48);
579
- const isEnd = key === '\x05' || (data.length === 3 && data[0] === 0x1b && data[1] === 0x5b && data[2] === 0x46);
580
- // Ctrl+C - cancel
581
- if (isCtrlC) {
582
- this.emit('cancel');
583
- return;
584
- }
585
- // Ctrl+O - toggle subagent expand (only when agent is running)
586
- if (isCtrlO) {
587
- this.emit('toggleSubagentExpand');
588
- return;
589
- }
590
- // Escape - close autocomplete, double Esc clears input, or emit escape for agent abort
591
- if (isEscape) {
592
- const now = Date.now();
593
- const isDoubleEsc = now - this.lastEscTime < this.DOUBLE_ESC_THRESHOLD_MS;
594
- this.lastEscTime = now;
595
- if (this.fileAutocomplete.active) {
596
- // First priority: close file autocomplete
597
- this.fileAutocomplete.active = false;
598
- this.fileAutocomplete.matches = [];
599
- this.emit('change', this.getValue());
600
- }
601
- else if (this.autocomplete.active) {
602
- // Second priority: close command autocomplete
603
- this.autocomplete.active = false;
604
- this.autocomplete.matches = [];
605
- this.emit('change', this.getValue());
606
- }
607
- else if (isDoubleEsc && this.getValue().length > 0) {
608
- // Third priority: double Esc clears input (if there's content)
609
- this.clearInput();
610
- this.emit('change', this.getValue());
611
- }
612
- else {
613
- // Fourth priority: emit escape for agent abort
614
- this.emit('escape');
615
- }
616
- return;
617
- }
618
- // Enter
619
- if (isEnter) {
620
- this.handleEnter();
621
- return;
622
- }
623
- // Shift+Tab - cycle modes
624
- if (isShiftTab) {
625
- this.emit('modeChange');
626
- return;
627
- }
628
- // Tab - accept autocomplete or insert spaces
629
- if (isTab) {
630
- this.handleTab();
631
- return;
632
- }
633
- // Arrow keys
634
- if (isUpArrow) {
635
- this.handleArrowUp();
636
- return;
637
- }
638
- if (isDownArrow) {
639
- this.handleArrowDown();
640
- return;
641
- }
642
- if (isLeftArrow) {
643
- this.handleArrowLeft();
644
- return;
645
- }
646
- if (isRightArrow) {
647
- this.handleArrowRight();
648
- return;
649
- }
650
- // Word navigation
651
- if (isOptionLeft) {
652
- this.handleWordLeft();
653
- return;
654
- }
655
- if (isOptionRight) {
656
- this.handleWordRight();
657
- return;
658
- }
659
- // Home/End
660
- if (isHome) {
661
- this.state.cursorPos = 0;
662
- this.emit('change', this.getValue());
663
- return;
664
- }
665
- if (isEnd) {
666
- this.state.cursorPos = this.state.lines[this.state.currentLine].length;
667
- this.emit('change', this.getValue());
668
- return;
669
- }
670
- // Backspace
671
- if (isBackspace) {
672
- this.handleBackspace();
673
- return;
674
- }
675
- // Regular character(s) - handles typing and paste
676
- if (key.length >= 1) {
677
- const printable = key
678
- .split('')
679
- .filter((c) => c.charCodeAt(0) >= 32)
680
- .join('');
681
- if (printable.length > 0) {
682
- // Clear suggestion when user starts typing
683
- if (this.suggestion) {
684
- this.suggestion = null;
685
- }
686
- const line = this.state.lines[this.state.currentLine];
687
- this.state.lines[this.state.currentLine] =
688
- line.slice(0, this.state.cursorPos) + printable + line.slice(this.state.cursorPos);
689
- this.state.cursorPos += printable.length;
690
- this.historyIndex = -1;
691
- this.updateAutocomplete();
692
- this.emit('change', this.getValue());
693
- }
694
- }
695
- }
696
- handleEnter() {
697
- const currentLine = this.state.lines[this.state.currentLine];
698
- // Continuation with backslash
699
- if (currentLine.endsWith('\\')) {
700
- this.state.lines[this.state.currentLine] = currentLine.slice(0, -1);
701
- this.state.lines.push('');
702
- this.state.currentLine++;
703
- this.state.cursorPos = 0;
704
- this.autocomplete.active = false;
705
- this.emit('change', this.getValue());
706
- return;
707
- }
708
- // File autocomplete selection - accept the path and continue
709
- if (this.fileAutocomplete.active && this.fileAutocomplete.matches.length > 0) {
710
- const selectedFile = this.fileAutocomplete.matches[this.fileAutocomplete.selectedIndex];
711
- const result = replaceAtMention(currentLine, this.state.cursorPos, selectedFile.path);
712
- this.state.lines[this.state.currentLine] = result.input;
713
- this.state.cursorPos = result.cursorPos;
714
- this.fileAutocomplete.active = false;
715
- this.fileAutocomplete.matches = [];
716
- // Don't return - fall through to submit
717
- }
718
- // Command autocomplete selection - accept the command and continue to execute it
719
- if (this.autocomplete.active && this.autocomplete.matches.length > 0) {
720
- this.state.lines[0] = this.autocomplete.matches[this.autocomplete.selectedIndex].command;
721
- this.state.cursorPos = this.state.lines[0].length;
722
- this.autocomplete.active = false;
723
- // Don't return - fall through to execute the command
724
- }
725
- const input = this.getValue();
726
- // Empty input - ignore
727
- if (!input.trim()) {
728
- return;
729
- }
730
- // Add to history
731
- this.addToHistory(input);
732
- // Queue mode - add to queue instead of emitting
733
- if (this.queueMode) {
734
- this.queuedInputs.push(input);
735
- this.clearInput();
736
- this.emit('change', this.getValue());
737
- return;
738
- }
739
- // Check if it's a command
740
- if (input.startsWith('/')) {
741
- const parts = input.slice(1).split(/\s+/);
742
- const command = parts[0];
743
- const args = parts.slice(1).join(' ');
744
- this.clearInput();
745
- this.emit('command', command, args);
746
- }
747
- else {
748
- this.clearInput();
749
- this.emit('submit', input);
750
- }
751
- }
752
- handleTab() {
753
- // Accept suggestion if present and input is empty
754
- if (this.suggestion && this.getValue() === '') {
755
- this.state.lines[0] = this.suggestion;
756
- this.state.cursorPos = this.suggestion.length;
757
- this.suggestion = null;
758
- this.emit('change', this.getValue());
759
- return;
760
- }
761
- // File autocomplete completion
762
- if (this.fileAutocomplete.active && this.fileAutocomplete.matches.length > 0) {
763
- const selectedFile = this.fileAutocomplete.matches[this.fileAutocomplete.selectedIndex];
764
- const currentLine = this.state.lines[this.state.currentLine];
765
- const result = replaceAtMention(currentLine, this.state.cursorPos, selectedFile.path);
766
- this.state.lines[this.state.currentLine] = result.input;
767
- this.state.cursorPos = result.cursorPos;
768
- this.fileAutocomplete.active = false;
769
- this.fileAutocomplete.matches = [];
770
- this.updateAutocomplete(); // Check if still in @ context (e.g., directory selected)
771
- this.emit('change', this.getValue());
772
- return;
773
- }
774
- // Command autocomplete completion
775
- if (this.autocomplete.active && this.autocomplete.matches.length > 0) {
776
- this.state.lines[this.state.currentLine] =
777
- this.autocomplete.matches[this.autocomplete.selectedIndex].command;
778
- this.state.cursorPos = this.state.lines[this.state.currentLine].length;
779
- this.autocomplete.active = false;
780
- this.autocomplete.matches = [];
781
- }
782
- else {
783
- // Insert 2 spaces
784
- const line = this.state.lines[this.state.currentLine];
785
- this.state.lines[this.state.currentLine] =
786
- line.slice(0, this.state.cursorPos) + ' ' + line.slice(this.state.cursorPos);
787
- this.state.cursorPos += 2;
788
- this.historyIndex = -1;
789
- this.updateAutocomplete();
790
- }
791
- this.emit('change', this.getValue());
792
- }
793
- handleArrowUp() {
794
- // File autocomplete navigation
795
- if (this.fileAutocomplete.active && this.fileAutocomplete.selectedIndex > 0) {
796
- this.fileAutocomplete.selectedIndex--;
797
- // Adjust scroll offset if selection goes above visible area
798
- if (this.fileAutocomplete.selectedIndex < this.fileAutocomplete.scrollOffset) {
799
- this.fileAutocomplete.scrollOffset = this.fileAutocomplete.selectedIndex;
800
- }
801
- this.emit('change', this.getValue());
802
- return;
803
- }
804
- // Command autocomplete navigation
805
- if (this.autocomplete.active && this.autocomplete.selectedIndex > 0) {
806
- this.autocomplete.selectedIndex--;
807
- // Adjust scroll offset if selection goes above visible area
808
- if (this.autocomplete.selectedIndex < this.autocomplete.scrollOffset) {
809
- this.autocomplete.scrollOffset = this.autocomplete.selectedIndex;
810
- }
811
- this.emit('change', this.getValue());
812
- return;
813
- }
814
- const termWidth = terminal.getTerminalWidth();
815
- const currentLinePromptLen = this.state.currentLine === 0 ? this.promptLen : 5;
816
- const cursorAbsPos = currentLinePromptLen + this.state.cursorPos;
817
- const currentPhysicalRow = Math.floor(cursorAbsPos / termWidth);
818
- const cursorColInRow = cursorAbsPos % termWidth;
819
- // Navigate within wrapped line
820
- if (currentPhysicalRow > 0) {
821
- const newAbsPos = (currentPhysicalRow - 1) * termWidth + cursorColInRow;
822
- this.state.cursorPos = Math.max(0, newAbsPos - currentLinePromptLen);
823
- this.state.cursorPos = Math.min(this.state.cursorPos, this.state.lines[this.state.currentLine].length);
824
- this.emit('change', this.getValue());
825
- return;
826
- }
827
- // Navigate to previous logical line
828
- if (this.state.currentLine > 0) {
829
- this.state.currentLine--;
830
- const prevLinePromptLen = this.state.currentLine === 0 ? this.promptLen : 5;
831
- const prevLineLen = this.state.lines[this.state.currentLine].length;
832
- const prevLinePhysical = calcPhysicalLines(this.state.lines[this.state.currentLine], prevLinePromptLen, termWidth);
833
- const lastRowStart = (prevLinePhysical - 1) * termWidth;
834
- const targetAbsPos = lastRowStart + cursorColInRow;
835
- this.state.cursorPos = Math.max(0, targetAbsPos - prevLinePromptLen);
836
- this.state.cursorPos = Math.min(this.state.cursorPos, prevLineLen);
837
- this.emit('change', this.getValue());
838
- return;
839
- }
840
- // History navigation (at top of input)
841
- if (!this.autocomplete.active && this.history.length > 0) {
842
- if (this.historyIndex === -1) {
843
- this.savedInput = this.getValue();
844
- }
845
- if (this.historyIndex < this.history.length - 1) {
846
- this.historyIndex++;
847
- const historyEntry = this.history[this.history.length - 1 - this.historyIndex];
848
- this.state.lines = [historyEntry];
849
- this.state.currentLine = 0;
850
- this.state.cursorPos = historyEntry.length;
851
- this.emit('change', this.getValue());
852
- }
853
- }
854
- }
855
- handleArrowDown() {
856
- // File autocomplete navigation
857
- if (this.fileAutocomplete.active &&
858
- this.fileAutocomplete.selectedIndex < this.fileAutocomplete.matches.length - 1) {
859
- this.fileAutocomplete.selectedIndex++;
860
- // Adjust scroll offset if selection goes below visible area
861
- const maxVisibleIndex = this.fileAutocomplete.scrollOffset + MAX_VISIBLE_COMMANDS - 1;
862
- if (this.fileAutocomplete.selectedIndex > maxVisibleIndex) {
863
- this.fileAutocomplete.scrollOffset = this.fileAutocomplete.selectedIndex - MAX_VISIBLE_COMMANDS + 1;
864
- }
865
- this.emit('change', this.getValue());
866
- return;
867
- }
868
- // Command autocomplete navigation
869
- if (this.autocomplete.active &&
870
- this.autocomplete.selectedIndex < this.autocomplete.matches.length - 1) {
871
- this.autocomplete.selectedIndex++;
872
- // Adjust scroll offset if selection goes below visible area
873
- const maxVisibleIndex = this.autocomplete.scrollOffset + MAX_VISIBLE_COMMANDS - 1;
874
- if (this.autocomplete.selectedIndex > maxVisibleIndex) {
875
- this.autocomplete.scrollOffset = this.autocomplete.selectedIndex - MAX_VISIBLE_COMMANDS + 1;
876
- }
877
- this.emit('change', this.getValue());
878
- return;
879
- }
880
- const termWidth = terminal.getTerminalWidth();
881
- const currentLinePromptLen = this.state.currentLine === 0 ? this.promptLen : 5;
882
- const cursorAbsPos = currentLinePromptLen + this.state.cursorPos;
883
- const currentPhysicalRow = Math.floor(cursorAbsPos / termWidth);
884
- const cursorColInRow = cursorAbsPos % termWidth;
885
- const currentLinePhysical = calcPhysicalLines(this.state.lines[this.state.currentLine], currentLinePromptLen, termWidth);
886
- // Navigate within wrapped line
887
- if (currentPhysicalRow < currentLinePhysical - 1) {
888
- const newAbsPos = (currentPhysicalRow + 1) * termWidth + cursorColInRow;
889
- this.state.cursorPos = Math.max(0, newAbsPos - currentLinePromptLen);
890
- this.state.cursorPos = Math.min(this.state.cursorPos, this.state.lines[this.state.currentLine].length);
891
- this.emit('change', this.getValue());
892
- return;
893
- }
894
- // Navigate to next logical line
895
- if (this.state.currentLine < this.state.lines.length - 1) {
896
- this.state.currentLine++;
897
- const nextLinePromptLen = this.state.currentLine === 0 ? this.promptLen : 5;
898
- const nextLineLen = this.state.lines[this.state.currentLine].length;
899
- this.state.cursorPos = Math.max(0, cursorColInRow - nextLinePromptLen);
900
- this.state.cursorPos = Math.min(this.state.cursorPos, nextLineLen);
901
- this.emit('change', this.getValue());
902
- return;
903
- }
904
- // History forward
905
- if (this.historyIndex >= 0) {
906
- this.historyIndex--;
907
- if (this.historyIndex === -1) {
908
- this.state.lines = this.savedInput.split('\n');
909
- this.state.currentLine = this.state.lines.length - 1;
910
- this.state.cursorPos = this.state.lines[this.state.currentLine].length;
911
- }
912
- else {
913
- const historyEntry = this.history[this.history.length - 1 - this.historyIndex];
914
- this.state.lines = [historyEntry];
915
- this.state.currentLine = 0;
916
- this.state.cursorPos = historyEntry.length;
917
- }
918
- this.updateAutocomplete();
919
- this.emit('change', this.getValue());
920
- }
921
- }
922
- handleArrowLeft() {
923
- if (this.state.cursorPos > 0) {
924
- this.state.cursorPos--;
925
- this.emit('change', this.getValue());
926
- }
927
- else if (this.state.currentLine > 0) {
928
- this.state.currentLine--;
929
- this.state.cursorPos = this.state.lines[this.state.currentLine].length;
930
- this.emit('change', this.getValue());
931
- }
932
- }
933
- handleArrowRight() {
934
- if (this.state.cursorPos < this.state.lines[this.state.currentLine].length) {
935
- this.state.cursorPos++;
936
- this.emit('change', this.getValue());
937
- }
938
- else if (this.state.currentLine < this.state.lines.length - 1) {
939
- this.state.currentLine++;
940
- this.state.cursorPos = 0;
941
- this.emit('change', this.getValue());
942
- }
943
- }
944
- handleWordLeft() {
945
- const line = this.state.lines[this.state.currentLine];
946
- if (this.state.cursorPos > 0) {
947
- let pos = this.state.cursorPos;
948
- while (pos > 0 && line[pos - 1] === ' ')
949
- pos--;
950
- while (pos > 0 && line[pos - 1] !== ' ')
951
- pos--;
952
- this.state.cursorPos = pos;
953
- this.emit('change', this.getValue());
954
- }
955
- else if (this.state.currentLine > 0) {
956
- this.state.currentLine--;
957
- this.state.cursorPos = this.state.lines[this.state.currentLine].length;
958
- this.emit('change', this.getValue());
959
- }
960
- }
961
- handleWordRight() {
962
- const line = this.state.lines[this.state.currentLine];
963
- if (this.state.cursorPos < line.length) {
964
- let pos = this.state.cursorPos;
965
- while (pos < line.length && line[pos] !== ' ')
966
- pos++;
967
- while (pos < line.length && line[pos] === ' ')
968
- pos++;
969
- this.state.cursorPos = pos;
970
- this.emit('change', this.getValue());
971
- }
972
- else if (this.state.currentLine < this.state.lines.length - 1) {
973
- this.state.currentLine++;
974
- this.state.cursorPos = 0;
975
- this.emit('change', this.getValue());
976
- }
977
- }
978
- handleBackspace() {
979
- this.historyIndex = -1;
980
- if (this.state.cursorPos > 0) {
981
- const line = this.state.lines[this.state.currentLine];
982
- this.state.lines[this.state.currentLine] =
983
- line.slice(0, this.state.cursorPos - 1) + line.slice(this.state.cursorPos);
984
- this.state.cursorPos--;
985
- this.updateAutocomplete();
986
- this.emit('change', this.getValue());
987
- }
988
- else if (this.state.currentLine > 0) {
989
- const currentLine = this.state.lines[this.state.currentLine];
990
- const prevLine = this.state.lines[this.state.currentLine - 1];
991
- this.state.lines[this.state.currentLine - 1] = prevLine + currentLine;
992
- this.state.lines.splice(this.state.currentLine, 1);
993
- this.state.currentLine--;
994
- this.state.cursorPos = prevLine.length;
995
- this.updateAutocomplete();
996
- this.emit('change', this.getValue());
997
- }
998
- }
999
- }