@travisennis/acai 0.0.9 → 0.0.11

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 (403) hide show
  1. package/README.md +51 -760
  2. package/bin/acai +52 -0
  3. package/dist/agent/index.d.ts +12 -2
  4. package/dist/agent/index.d.ts.map +1 -1
  5. package/dist/agent/index.js +380 -199
  6. package/dist/agent/sub-agent.d.ts +23 -0
  7. package/dist/agent/sub-agent.d.ts.map +1 -0
  8. package/dist/agent/sub-agent.js +109 -0
  9. package/dist/cli/index.d.ts +26 -0
  10. package/dist/cli/index.d.ts.map +1 -0
  11. package/dist/{cli.js → cli/index.js} +84 -77
  12. package/dist/{stdin.d.ts → cli/stdin.d.ts} +2 -1
  13. package/dist/cli/stdin.d.ts.map +1 -0
  14. package/dist/{stdin.js → cli/stdin.js} +11 -0
  15. package/dist/commands/copy/index.js +2 -2
  16. package/dist/commands/copy/utils.d.ts.map +1 -1
  17. package/dist/commands/copy/utils.js +15 -13
  18. package/dist/commands/generate-rules/index.d.ts +1 -1
  19. package/dist/commands/generate-rules/index.d.ts.map +1 -1
  20. package/dist/commands/generate-rules/index.js +16 -101
  21. package/dist/commands/generate-rules/service.d.ts +22 -0
  22. package/dist/commands/generate-rules/service.d.ts.map +1 -0
  23. package/dist/commands/generate-rules/service.js +103 -0
  24. package/dist/commands/handoff/index.js +2 -2
  25. package/dist/commands/health/index.js +1 -1
  26. package/dist/commands/health/utils.d.ts +3 -2
  27. package/dist/commands/health/utils.d.ts.map +1 -1
  28. package/dist/commands/health/utils.js +6 -0
  29. package/dist/commands/history/index.d.ts +1 -1
  30. package/dist/commands/history/index.d.ts.map +1 -1
  31. package/dist/commands/history/index.js +17 -18
  32. package/dist/commands/history/types.d.ts +38 -0
  33. package/dist/commands/history/types.d.ts.map +1 -1
  34. package/dist/commands/history/utils.d.ts.map +1 -1
  35. package/dist/commands/history/utils.js +63 -58
  36. package/dist/commands/init/index.d.ts.map +1 -1
  37. package/dist/commands/init/index.js +3 -8
  38. package/dist/commands/init-project/index.d.ts.map +1 -1
  39. package/dist/commands/init-project/index.js +3 -3
  40. package/dist/commands/init-project/utils.d.ts +2 -1
  41. package/dist/commands/init-project/utils.d.ts.map +1 -1
  42. package/dist/commands/init-project/utils.js +10 -2
  43. package/dist/commands/list-tools/index.d.ts.map +1 -1
  44. package/dist/commands/list-tools/index.js +7 -31
  45. package/dist/commands/manager.d.ts +2 -2
  46. package/dist/commands/manager.d.ts.map +1 -1
  47. package/dist/commands/manager.js +55 -33
  48. package/dist/commands/model/index.d.ts.map +1 -1
  49. package/dist/commands/model/index.js +20 -151
  50. package/dist/commands/model/model-panel.d.ts +4 -0
  51. package/dist/commands/model/model-panel.d.ts.map +1 -0
  52. package/dist/commands/model/model-panel.js +144 -0
  53. package/dist/commands/paste/index.d.ts.map +1 -1
  54. package/dist/commands/paste/index.js +59 -62
  55. package/dist/commands/paste/utils.d.ts.map +1 -1
  56. package/dist/commands/paste/utils.js +88 -58
  57. package/dist/commands/pickup/index.d.ts.map +1 -1
  58. package/dist/commands/pickup/index.js +6 -3
  59. package/dist/commands/pickup/utils.js +3 -3
  60. package/dist/commands/resources/index.d.ts.map +1 -1
  61. package/dist/commands/resources/index.js +33 -50
  62. package/dist/commands/review/index.d.ts.map +1 -1
  63. package/dist/commands/review/index.js +3 -117
  64. package/dist/commands/review/review-panel.d.ts +3 -0
  65. package/dist/commands/review/review-panel.d.ts.map +1 -0
  66. package/dist/commands/review/review-panel.js +186 -0
  67. package/dist/commands/review/utils.d.ts +15 -1
  68. package/dist/commands/review/utils.d.ts.map +1 -1
  69. package/dist/commands/review/utils.js +127 -68
  70. package/dist/commands/session/index.d.ts +1 -1
  71. package/dist/commands/session/index.d.ts.map +1 -1
  72. package/dist/commands/session/index.js +124 -135
  73. package/dist/commands/shell/index.d.ts.map +1 -1
  74. package/dist/commands/shell/index.js +16 -1
  75. package/dist/commands/types.d.ts +2 -2
  76. package/dist/commands/types.d.ts.map +1 -1
  77. package/dist/{config.d.ts → config/index.d.ts} +20 -9
  78. package/dist/config/index.d.ts.map +1 -0
  79. package/dist/{config.js → config/index.js} +43 -42
  80. package/dist/execution/index.d.ts.map +1 -1
  81. package/dist/execution/index.js +75 -55
  82. package/dist/index.d.ts +1 -0
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +148 -141
  85. package/dist/middleware/cache.d.ts.map +1 -1
  86. package/dist/middleware/cache.js +18 -36
  87. package/dist/models/ai-config.d.ts +1 -0
  88. package/dist/models/ai-config.d.ts.map +1 -1
  89. package/dist/models/ai-config.js +4 -3
  90. package/dist/models/anthropic-provider.d.ts +2 -5
  91. package/dist/models/anthropic-provider.d.ts.map +1 -1
  92. package/dist/models/anthropic-provider.js +3 -70
  93. package/dist/models/deepseek-provider.d.ts +1 -0
  94. package/dist/models/deepseek-provider.d.ts.map +1 -1
  95. package/dist/models/google-provider.d.ts +2 -3
  96. package/dist/models/google-provider.d.ts.map +1 -1
  97. package/dist/models/google-provider.js +0 -26
  98. package/dist/models/groq-provider.d.ts +1 -0
  99. package/dist/models/groq-provider.d.ts.map +1 -1
  100. package/dist/models/manager.d.ts +13 -2
  101. package/dist/models/manager.d.ts.map +1 -1
  102. package/dist/models/manager.js +20 -8
  103. package/dist/models/openai-provider.d.ts +2 -5
  104. package/dist/models/openai-provider.d.ts.map +1 -1
  105. package/dist/models/openai-provider.js +0 -52
  106. package/dist/models/opencode-go-provider.d.ts +25 -0
  107. package/dist/models/opencode-go-provider.d.ts.map +1 -0
  108. package/dist/models/opencode-go-provider.js +78 -0
  109. package/dist/models/opencode-zen-provider.d.ts +7 -3
  110. package/dist/models/opencode-zen-provider.d.ts.map +1 -1
  111. package/dist/models/opencode-zen-provider.js +49 -10
  112. package/dist/models/openrouter-provider.d.ts +27 -31
  113. package/dist/models/openrouter-provider.d.ts.map +1 -1
  114. package/dist/models/openrouter-provider.js +121 -180
  115. package/dist/models/providers.d.ts +3 -3
  116. package/dist/models/providers.d.ts.map +1 -1
  117. package/dist/models/providers.js +6 -0
  118. package/dist/models/xai-provider.d.ts +4 -3
  119. package/dist/models/xai-provider.d.ts.map +1 -1
  120. package/dist/models/xai-provider.js +18 -18
  121. package/dist/modes/manager.d.ts +24 -0
  122. package/dist/modes/manager.d.ts.map +1 -0
  123. package/dist/modes/manager.js +77 -0
  124. package/dist/modes/prompts.d.ts +2 -0
  125. package/dist/modes/prompts.d.ts.map +1 -0
  126. package/dist/modes/prompts.js +142 -0
  127. package/dist/prompts/mentions.d.ts +11 -0
  128. package/dist/prompts/mentions.d.ts.map +1 -0
  129. package/dist/{mentions.js → prompts/mentions.js} +55 -85
  130. package/dist/{prompts.d.ts → prompts/system-prompt.d.ts} +7 -2
  131. package/dist/prompts/system-prompt.d.ts.map +1 -0
  132. package/dist/{prompts.js → prompts/system-prompt.js} +31 -16
  133. package/dist/repl/index.d.ts +174 -0
  134. package/dist/repl/index.d.ts.map +1 -0
  135. package/dist/{repl-new.js → repl/index.js} +397 -76
  136. package/dist/repl/project-status.d.ts +1 -0
  137. package/dist/repl/project-status.d.ts.map +1 -1
  138. package/dist/repl/project-status.js +4 -1
  139. package/dist/sessions/manager.d.ts +92 -0
  140. package/dist/sessions/manager.d.ts.map +1 -1
  141. package/dist/sessions/manager.js +262 -9
  142. package/dist/sessions/summary.d.ts +4 -0
  143. package/dist/sessions/summary.d.ts.map +1 -0
  144. package/dist/sessions/summary.js +30 -0
  145. package/dist/skills/index.d.ts +29 -0
  146. package/dist/skills/index.d.ts.map +1 -0
  147. package/dist/skills/index.js +294 -0
  148. package/dist/subagents/index.d.ts +16 -0
  149. package/dist/subagents/index.d.ts.map +1 -0
  150. package/dist/subagents/index.js +231 -0
  151. package/dist/terminal/control.d.ts +1 -1
  152. package/dist/terminal/control.d.ts.map +1 -1
  153. package/dist/terminal/control.js +3 -3
  154. package/dist/terminal/east-asian-width.d.ts.map +1 -1
  155. package/dist/terminal/east-asian-width.js +404 -351
  156. package/dist/terminal/keys.d.ts +17 -0
  157. package/dist/terminal/keys.d.ts.map +1 -1
  158. package/dist/terminal/keys.js +37 -0
  159. package/dist/terminal/select-prompt.d.ts.map +1 -1
  160. package/dist/terminal/select-prompt.js +24 -12
  161. package/dist/terminal/string-width.d.ts.map +1 -1
  162. package/dist/terminal/string-width.js +25 -27
  163. package/dist/terminal/style.d.ts.map +1 -1
  164. package/dist/terminal/style.js +4 -7
  165. package/dist/terminal/supports-color.d.ts.map +1 -1
  166. package/dist/terminal/supports-color.js +41 -27
  167. package/dist/terminal/table/cell.d.ts +12 -0
  168. package/dist/terminal/table/cell.d.ts.map +1 -1
  169. package/dist/terminal/table/cell.js +40 -25
  170. package/dist/terminal/table/layout-manager.d.ts.map +1 -1
  171. package/dist/terminal/table/layout-manager.js +100 -68
  172. package/dist/terminal/table/utils.d.ts +1 -1
  173. package/dist/terminal/table/utils.d.ts.map +1 -1
  174. package/dist/terminal/table/utils.js +17 -10
  175. package/dist/terminal/wrap-ansi.d.ts.map +1 -1
  176. package/dist/terminal/wrap-ansi.js +174 -105
  177. package/dist/tokens/tracker.d.ts +1 -0
  178. package/dist/tokens/tracker.d.ts.map +1 -1
  179. package/dist/tokens/tracker.js +3 -0
  180. package/dist/tools/agent.d.ts +27 -0
  181. package/dist/tools/agent.d.ts.map +1 -0
  182. package/dist/tools/agent.js +81 -0
  183. package/dist/tools/apply-patch.d.ts +62 -0
  184. package/dist/tools/apply-patch.d.ts.map +1 -0
  185. package/dist/tools/apply-patch.js +377 -0
  186. package/dist/tools/bash.d.ts +4 -3
  187. package/dist/tools/bash.d.ts.map +1 -1
  188. package/dist/tools/bash.js +349 -141
  189. package/dist/tools/directory-tree.d.ts +3 -3
  190. package/dist/tools/directory-tree.d.ts.map +1 -1
  191. package/dist/tools/directory-tree.js +8 -5
  192. package/dist/tools/dynamic-tool-loader.d.ts +3 -6
  193. package/dist/tools/dynamic-tool-loader.d.ts.map +1 -1
  194. package/dist/tools/dynamic-tool-loader.js +20 -4
  195. package/dist/tools/edit-file.d.ts +7 -7
  196. package/dist/tools/edit-file.d.ts.map +1 -1
  197. package/dist/tools/edit-file.js +292 -85
  198. package/dist/tools/glob.d.ts +6 -6
  199. package/dist/tools/glob.d.ts.map +1 -1
  200. package/dist/tools/glob.js +110 -63
  201. package/dist/tools/grep.d.ts +15 -12
  202. package/dist/tools/grep.d.ts.map +1 -1
  203. package/dist/tools/grep.js +315 -193
  204. package/dist/tools/index.d.ts +114 -9
  205. package/dist/tools/index.d.ts.map +1 -1
  206. package/dist/tools/index.js +39 -24
  207. package/dist/tools/ls.d.ts +2 -2
  208. package/dist/tools/ls.d.ts.map +1 -1
  209. package/dist/tools/ls.js +7 -5
  210. package/dist/tools/read-file.d.ts +4 -6
  211. package/dist/tools/read-file.d.ts.map +1 -1
  212. package/dist/tools/read-file.js +84 -39
  213. package/dist/tools/save-file.d.ts +3 -3
  214. package/dist/tools/save-file.d.ts.map +1 -1
  215. package/dist/tools/save-file.js +36 -31
  216. package/dist/tools/skill.d.ts +23 -0
  217. package/dist/tools/skill.d.ts.map +1 -0
  218. package/dist/tools/skill.js +65 -0
  219. package/dist/tools/think.d.ts.map +1 -1
  220. package/dist/tools/think.js +2 -9
  221. package/dist/tools/utils.d.ts +2 -0
  222. package/dist/tools/utils.d.ts.map +1 -1
  223. package/dist/tools/utils.js +12 -0
  224. package/dist/tools/web-fetch.d.ts +50 -0
  225. package/dist/tools/web-fetch.d.ts.map +1 -0
  226. package/dist/tools/web-fetch.js +446 -0
  227. package/dist/tools/web-search.d.ts +44 -0
  228. package/dist/tools/web-search.d.ts.map +1 -0
  229. package/dist/tools/web-search.js +226 -0
  230. package/dist/tui/autocomplete/attachment-provider.d.ts +3 -6
  231. package/dist/tui/autocomplete/attachment-provider.d.ts.map +1 -1
  232. package/dist/tui/autocomplete/attachment-provider.js +25 -78
  233. package/dist/tui/autocomplete/base-provider.d.ts +1 -0
  234. package/dist/tui/autocomplete/base-provider.d.ts.map +1 -1
  235. package/dist/tui/autocomplete/combined-provider.d.ts +1 -4
  236. package/dist/tui/autocomplete/combined-provider.d.ts.map +1 -1
  237. package/dist/tui/autocomplete/combined-provider.js +3 -17
  238. package/dist/tui/autocomplete/command-provider.d.ts +1 -0
  239. package/dist/tui/autocomplete/command-provider.d.ts.map +1 -1
  240. package/dist/tui/autocomplete/command-provider.js +3 -0
  241. package/dist/tui/autocomplete/file-search-provider.d.ts +2 -1
  242. package/dist/tui/autocomplete/file-search-provider.d.ts.map +1 -1
  243. package/dist/tui/autocomplete/file-search-provider.js +37 -17
  244. package/dist/tui/autocomplete/skill-provider.d.ts +17 -0
  245. package/dist/tui/autocomplete/skill-provider.d.ts.map +1 -0
  246. package/dist/tui/autocomplete/skill-provider.js +49 -0
  247. package/dist/tui/autocomplete/utils.d.ts +2 -1
  248. package/dist/tui/autocomplete/utils.d.ts.map +1 -1
  249. package/dist/tui/autocomplete/utils.js +25 -23
  250. package/dist/tui/autocomplete.d.ts +2 -2
  251. package/dist/tui/autocomplete.d.ts.map +1 -1
  252. package/dist/tui/autocomplete.js +3 -5
  253. package/dist/tui/components/assistant-message.d.ts.map +1 -1
  254. package/dist/tui/components/assistant-message.js +0 -4
  255. package/dist/tui/components/editor.d.ts +18 -3
  256. package/dist/tui/components/editor.d.ts.map +1 -1
  257. package/dist/tui/components/editor.js +211 -237
  258. package/dist/tui/components/footer.d.ts +6 -4
  259. package/dist/tui/components/footer.d.ts.map +1 -1
  260. package/dist/tui/components/footer.js +49 -25
  261. package/dist/tui/components/markdown.d.ts +10 -7
  262. package/dist/tui/components/markdown.d.ts.map +1 -1
  263. package/dist/tui/components/markdown.js +57 -39
  264. package/dist/tui/components/modal.d.ts.map +1 -1
  265. package/dist/tui/components/modal.js +35 -33
  266. package/dist/tui/components/notification.d.ts +13 -2
  267. package/dist/tui/components/notification.d.ts.map +1 -1
  268. package/dist/tui/components/notification.js +36 -2
  269. package/dist/tui/components/progress-bar.js +1 -1
  270. package/dist/tui/components/select-list.d.ts +1 -0
  271. package/dist/tui/components/select-list.d.ts.map +1 -1
  272. package/dist/tui/components/select-list.js +14 -11
  273. package/dist/tui/components/text.d.ts +16 -0
  274. package/dist/tui/components/text.d.ts.map +1 -1
  275. package/dist/tui/components/text.js +72 -57
  276. package/dist/tui/components/thinking-block.d.ts +9 -0
  277. package/dist/tui/components/thinking-block.d.ts.map +1 -1
  278. package/dist/tui/components/thinking-block.js +43 -11
  279. package/dist/tui/components/tool-execution.d.ts +5 -1
  280. package/dist/tui/components/tool-execution.d.ts.map +1 -1
  281. package/dist/tui/components/tool-execution.js +19 -10
  282. package/dist/tui/components/user-message.d.ts.map +1 -1
  283. package/dist/tui/components/user-message.js +0 -3
  284. package/dist/tui/components/welcome.d.ts +2 -1
  285. package/dist/tui/components/welcome.d.ts.map +1 -1
  286. package/dist/tui/components/welcome.js +2 -2
  287. package/dist/tui/editor-launcher.d.ts +3 -2
  288. package/dist/tui/editor-launcher.d.ts.map +1 -1
  289. package/dist/tui/index.d.ts +0 -1
  290. package/dist/tui/index.d.ts.map +1 -1
  291. package/dist/tui/terminal.d.ts.map +1 -1
  292. package/dist/tui/terminal.js +10 -2
  293. package/dist/tui/tui.d.ts +43 -0
  294. package/dist/tui/tui.d.ts.map +1 -1
  295. package/dist/tui/tui.js +166 -41
  296. package/dist/tui/utils.d.ts +1 -5
  297. package/dist/tui/utils.d.ts.map +1 -1
  298. package/dist/tui/utils.js +271 -44
  299. package/dist/utils/bash/parse.d.ts +19 -0
  300. package/dist/utils/bash/parse.d.ts.map +1 -0
  301. package/dist/utils/bash/parse.js +223 -0
  302. package/dist/utils/bash/quote.d.ts +6 -0
  303. package/dist/utils/bash/quote.d.ts.map +1 -0
  304. package/dist/utils/bash/quote.js +23 -0
  305. package/dist/utils/bash.d.ts.map +1 -1
  306. package/dist/utils/bash.js +211 -126
  307. package/dist/utils/command-protection.d.ts +28 -0
  308. package/dist/utils/command-protection.d.ts.map +1 -0
  309. package/dist/utils/command-protection.js +324 -0
  310. package/dist/utils/dedent.d.ts.map +1 -0
  311. package/dist/utils/env-expand.d.ts +2 -0
  312. package/dist/utils/env-expand.d.ts.map +1 -0
  313. package/dist/utils/env-expand.js +8 -0
  314. package/dist/utils/filesystem/path-display.d.ts +11 -0
  315. package/dist/utils/filesystem/path-display.d.ts.map +1 -0
  316. package/dist/utils/filesystem/path-display.js +32 -0
  317. package/dist/utils/filesystem/security.d.ts +2 -2
  318. package/dist/utils/filesystem/security.d.ts.map +1 -1
  319. package/dist/utils/filesystem/security.js +28 -30
  320. package/dist/utils/formatting.d.ts.map +1 -0
  321. package/dist/{formatting.js → utils/formatting.js} +1 -1
  322. package/dist/utils/git.d.ts +4 -0
  323. package/dist/utils/git.d.ts.map +1 -1
  324. package/dist/utils/git.js +30 -0
  325. package/dist/utils/glob.d.ts +1 -1
  326. package/dist/utils/glob.d.ts.map +1 -1
  327. package/dist/utils/logger.d.ts.map +1 -0
  328. package/dist/{logger.js → utils/logger.js} +1 -1
  329. package/dist/utils/parsing.d.ts.map +1 -0
  330. package/dist/utils/process.d.ts.map +1 -1
  331. package/dist/utils/process.js +90 -37
  332. package/dist/utils/templates.d.ts +2 -0
  333. package/dist/utils/templates.d.ts.map +1 -0
  334. package/dist/utils/templates.js +24 -0
  335. package/dist/utils/version.d.ts.map +1 -0
  336. package/dist/{version.js → utils/version.js} +1 -1
  337. package/package.json +35 -26
  338. package/dist/cli.d.ts +0 -23
  339. package/dist/cli.d.ts.map +0 -1
  340. package/dist/commands/add-directory/types.d.ts +0 -6
  341. package/dist/commands/add-directory/types.d.ts.map +0 -1
  342. package/dist/commands/add-directory/types.js +0 -1
  343. package/dist/commands/copy/types.d.ts +0 -3
  344. package/dist/commands/copy/types.d.ts.map +0 -1
  345. package/dist/commands/copy/types.js +0 -1
  346. package/dist/commands/exit/index.d.ts +0 -10
  347. package/dist/commands/exit/index.d.ts.map +0 -1
  348. package/dist/commands/exit/index.js +0 -21
  349. package/dist/commands/exit/types.d.ts +0 -8
  350. package/dist/commands/exit/types.d.ts.map +0 -1
  351. package/dist/commands/exit/types.js +0 -1
  352. package/dist/commands/exit/utils.d.ts +0 -2
  353. package/dist/commands/exit/utils.d.ts.map +0 -1
  354. package/dist/commands/exit/utils.js +0 -13
  355. package/dist/commands/prompt/index.d.ts +0 -5
  356. package/dist/commands/prompt/index.d.ts.map +0 -1
  357. package/dist/commands/prompt/index.js +0 -122
  358. package/dist/commands/prompt/types.d.ts +0 -15
  359. package/dist/commands/prompt/types.d.ts.map +0 -1
  360. package/dist/commands/prompt/types.js +0 -1
  361. package/dist/commands/prompt/utils.d.ts +0 -12
  362. package/dist/commands/prompt/utils.d.ts.map +0 -1
  363. package/dist/commands/prompt/utils.js +0 -107
  364. package/dist/commands/reset/index.d.ts +0 -3
  365. package/dist/commands/reset/index.d.ts.map +0 -1
  366. package/dist/commands/reset/index.js +0 -25
  367. package/dist/commands/reset/types.d.ts +0 -1
  368. package/dist/commands/reset/types.d.ts.map +0 -1
  369. package/dist/commands/reset/types.js +0 -3
  370. package/dist/commands/review/types.d.ts +0 -12
  371. package/dist/commands/review/types.d.ts.map +0 -1
  372. package/dist/commands/review/types.js +0 -1
  373. package/dist/commands/save/index.d.ts +0 -3
  374. package/dist/commands/save/index.d.ts.map +0 -1
  375. package/dist/commands/save/index.js +0 -19
  376. package/dist/config.d.ts.map +0 -1
  377. package/dist/dedent.d.ts.map +0 -1
  378. package/dist/formatting.d.ts.map +0 -1
  379. package/dist/logger.d.ts.map +0 -1
  380. package/dist/mentions.d.ts +0 -14
  381. package/dist/mentions.d.ts.map +0 -1
  382. package/dist/parsing.d.ts.map +0 -1
  383. package/dist/prompts.d.ts.map +0 -1
  384. package/dist/repl-new.d.ts +0 -65
  385. package/dist/repl-new.d.ts.map +0 -1
  386. package/dist/skills.d.ts +0 -16
  387. package/dist/skills.d.ts.map +0 -1
  388. package/dist/skills.js +0 -233
  389. package/dist/stdin.d.ts.map +0 -1
  390. package/dist/tui/autocomplete/path-provider.d.ts +0 -21
  391. package/dist/tui/autocomplete/path-provider.d.ts.map +0 -1
  392. package/dist/tui/autocomplete/path-provider.js +0 -164
  393. package/dist/utils/iterables.d.ts +0 -2
  394. package/dist/utils/iterables.d.ts.map +0 -1
  395. package/dist/utils/iterables.js +0 -6
  396. package/dist/version.d.ts.map +0 -1
  397. /package/dist/{dedent.d.ts → utils/dedent.d.ts} +0 -0
  398. /package/dist/{dedent.js → utils/dedent.js} +0 -0
  399. /package/dist/{formatting.d.ts → utils/formatting.d.ts} +0 -0
  400. /package/dist/{logger.d.ts → utils/logger.d.ts} +0 -0
  401. /package/dist/{parsing.d.ts → utils/parsing.d.ts} +0 -0
  402. /package/dist/{parsing.js → utils/parsing.js} +0 -0
  403. /package/dist/{version.d.ts → utils/version.d.ts} +0 -0
@@ -1,6 +1,6 @@
1
- import { formatDuration, formatNumber } from "../../formatting.js";
2
1
  import { getTerminalSize } from "../../terminal/control.js";
3
2
  import style from "../../terminal/style.js";
3
+ import { formatDuration, formatNumber } from "../../utils/formatting.js";
4
4
  import { visibleWidth } from "../tui.js";
5
5
  import { ProgressBarComponent } from "./progress-bar.js";
6
6
  function formatProjectStatus(status) {
@@ -12,10 +12,13 @@ function formatProjectStatus(status) {
12
12
  const end = path.slice(-(Math.floor(maxPathLength / 2) - 1));
13
13
  path = `${start}...${end}`;
14
14
  }
15
- let result = style.blue(path);
15
+ const line1 = style.blue(path);
16
+ // Line 2: git information
16
17
  if (status.isGitRepository && status.branch) {
17
- const asterisk = status.hasChanges ? "*" : "";
18
- result += ` ${style.gray(status.branch + asterisk)}`;
18
+ let branchDisplay = status.branch;
19
+ if (status.unpushedCommits > 0) {
20
+ branchDisplay += ` ${style.cyan(`↑${status.unpushedCommits}`)}`;
21
+ }
19
22
  let fileStatus = "";
20
23
  if (status.fileChanges.added)
21
24
  fileStatus += ` +${status.fileChanges.added}`;
@@ -25,22 +28,23 @@ function formatProjectStatus(status) {
25
28
  fileStatus += ` -${status.fileChanges.deleted}`;
26
29
  if (status.fileChanges.untracked)
27
30
  fileStatus += ` ?${status.fileChanges.untracked}`;
28
- result +=
29
- " " +
30
- `${style.dim("[")}${style.yellow(fileStatus.trim())} ` +
31
- `${style.green(`+${status.diffStats.insertions}`)} ` +
32
- `${style.red(`-${status.diffStats.deletions}`)}${style.dim("]")}`;
31
+ const line2 = `${style.gray(branchDisplay)}` +
32
+ `${style.yellow(fileStatus)}` +
33
+ ` ${style.dim("[")}${style.green(`+${status.diffStats.insertions}`)} ${style.red(`-${status.diffStats.deletions}`)}${style.dim("]")}`;
34
+ return [line1, line2];
33
35
  }
34
- return result;
36
+ return [line1, null];
35
37
  }
36
38
  export class FooterComponent {
37
39
  modelManager;
40
+ tokenTracker;
38
41
  state;
39
42
  progressBar;
40
- usage;
41
43
  agentState;
42
- constructor(modelManager, state) {
44
+ currentMode = "Normal";
45
+ constructor(modelManager, tokenTracker, state) {
43
46
  this.modelManager = modelManager;
47
+ this.tokenTracker = tokenTracker;
44
48
  this.agentState = state.agentState;
45
49
  this.state = state;
46
50
  this.progressBar = new ProgressBarComponent(state.currentContextWindow, state.contextWindow, 0);
@@ -49,31 +53,51 @@ export class FooterComponent {
49
53
  if (state.agentState) {
50
54
  this.agentState = state.agentState;
51
55
  }
52
- if (state.usage) {
53
- this.usage = state.usage;
56
+ if (state.currentMode !== undefined) {
57
+ this.currentMode = state.currentMode;
54
58
  }
55
59
  this.state = state;
56
60
  this.progressBar.setCurrent(state.currentContextWindow);
57
61
  this.progressBar.setTotal(state.contextWindow);
58
62
  }
59
63
  resetState() {
60
- this.usage = undefined;
61
64
  this.agentState = undefined;
62
65
  }
66
+ getProjectStatus() {
67
+ return this.state.projectStatus;
68
+ }
63
69
  render(width) {
64
70
  const results = [];
65
- const modelInfo = `${this.modelManager.getModelMetadata("repl").id} [${this.modelManager.getModel("repl").modelId}]`;
66
- const projectStatusString = formatProjectStatus(this.state.projectStatus);
67
- const padding = Math.max(0, width - visibleWidth(projectStatusString) - modelInfo.length);
68
- results.push(projectStatusString + " ".repeat(padding) + style.dim(modelInfo));
69
- if (this.usage && this.agentState) {
70
- const inputTokens = this.usage.inputTokens ?? 0;
71
- const outputTokens = this.usage.outputTokens ?? 0;
72
- const cachedInputTokens = this.usage.inputTokenDetails.cacheReadTokens ?? 0;
71
+ const modelInfo = `${this.modelManager.getModelMetadata("repl").id}`;
72
+ const [pathLine, gitLine] = formatProjectStatus(this.state.projectStatus);
73
+ const padding = Math.max(0, width - visibleWidth(pathLine) - modelInfo.length);
74
+ results.push(pathLine + " ".repeat(padding) + style.dim(modelInfo));
75
+ const modeDisplay = this.currentMode !== "Normal"
76
+ ? style.magenta(`[${this.currentMode}]`)
77
+ : "";
78
+ if (gitLine) {
79
+ if (modeDisplay) {
80
+ const gitPadding = Math.max(0, width - visibleWidth(gitLine) - visibleWidth(modeDisplay));
81
+ results.push(`${gitLine}${" ".repeat(gitPadding)}${modeDisplay}`);
82
+ }
83
+ else {
84
+ results.push(gitLine);
85
+ }
86
+ }
87
+ else if (modeDisplay) {
88
+ results.push(modeDisplay);
89
+ }
90
+ // Line 3: Total session usage from token tracker (accumulated across all turns)
91
+ if (this.tokenTracker) {
92
+ const sessionUsage = this.tokenTracker.getUsageByApp("repl");
93
+ const inputTokens = sessionUsage.inputTokens ?? 0;
94
+ const outputTokens = sessionUsage.outputTokens ?? 0;
95
+ const cachedInputTokens = sessionUsage.inputTokenDetails?.cacheReadTokens ?? 0;
73
96
  const tokenSummary = `↑ ${formatNumber(inputTokens)} (${formatNumber(cachedInputTokens)}) ↓ ${formatNumber(outputTokens)} - `;
74
97
  let status = tokenSummary;
75
- const inputCost = this.agentState.modelConfig.costPerInputToken * inputTokens;
76
- const outputCost = this.agentState.modelConfig.costPerOutputToken * outputTokens;
98
+ const modelConfig = this.modelManager.getModelMetadata("repl");
99
+ const inputCost = modelConfig.costPerInputToken * inputTokens;
100
+ const outputCost = modelConfig.costPerOutputToken * outputTokens;
77
101
  status += `$${(inputCost + outputCost).toFixed(2)}`;
78
102
  results.push(style.dim(status));
79
103
  }
@@ -5,7 +5,7 @@ type Color = "black" | "red" | "green" | "yellow" | "blue" | "magenta" | "cyan"
5
5
  * Theme functions for markdown elements.
6
6
  * Each function takes text and returns styled text with ANSI codes.
7
7
  */
8
- export interface MarkdownTheme {
8
+ interface MarkdownTheme {
9
9
  heading: (text: string) => string;
10
10
  paragraph: (text: string) => string;
11
11
  link: (text: string) => string;
@@ -25,7 +25,7 @@ export interface MarkdownTheme {
25
25
  /**
26
26
  * Options for configuring Markdown component
27
27
  */
28
- export interface MarkdownOptions {
28
+ interface MarkdownOptions {
29
29
  /** Background color */
30
30
  bgColor?: Color;
31
31
  /** Custom background RGB color */
@@ -77,17 +77,20 @@ export declare class Markdown implements Component {
77
77
  */
78
78
  private cleanToStyledIndex;
79
79
  /**
80
- * Protect inline code spans by replacing them with placeholders
81
- * This prevents wrapAnsi from breaking code spans across lines
80
+ * Create a placeholder string whose visible width matches the target width.
81
+ * Returns null if the code span is too short to protect reliably.
82
+ */
83
+ private createWidthMatchedPlaceholder;
84
+ /**
85
+ * Protect inline code spans by replacing them with width-matched placeholders.
86
+ * This prevents wrapAnsi from breaking code spans across lines while
87
+ * preserving the correct visible width for accurate wrapping.
82
88
  */
83
89
  private protectCodeSpans;
84
90
  /**
85
91
  * Check if a line represents a nested list item
86
92
  */
87
93
  private isNestedListLine;
88
- /**
89
- * Restore code spans from placeholders after wrapping
90
- */
91
94
  private restoreCodeSpans;
92
95
  /**
93
96
  * Render a list with proper nesting support
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../../source/tui/components/markdown.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../../source/tui/components/markdown.ts"],"names":[],"mappings":"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"}
@@ -326,19 +326,13 @@ export class Markdown {
326
326
  return result;
327
327
  }
328
328
  wrapLine(line, contentWidth) {
329
- // Handle undefined or null lines
330
329
  if (!line) {
331
330
  return [""];
332
331
  }
333
- // Protect inline code spans from being split across lines
334
- // by temporarily replacing them with placeholders
335
- const { protectedText, codeSpans } = this.protectCodeSpans(line);
336
- // Use the existing wrapAnsi function for robust ANSI-aware wrapping
337
- // Use contentWidth (available width after padding) for wrapping
332
+ const { protectedText, codeSpans, placeholders } = this.protectCodeSpans(line);
338
333
  const wrappedText = wrapAnsi(protectedText, contentWidth, { trim: false });
339
334
  const lines = wrappedText.split("\n");
340
- // Restore the code spans
341
- const restoredLines = this.restoreCodeSpans(lines, codeSpans);
335
+ const restoredLines = this.restoreCodeSpans(lines, codeSpans, placeholders);
342
336
  return restoredLines;
343
337
  }
344
338
  /**
@@ -348,18 +342,34 @@ export class Markdown {
348
342
  cleanToStyledIndex(cleanText, styledText, cleanIndex) {
349
343
  let cleanPos = 0;
350
344
  let styledPos = 0;
351
- while (cleanPos < cleanIndex && styledPos < styledText.length) {
345
+ const escapeChar = String.fromCharCode(27);
346
+ // Handle edge case: if cleanIndex is 0, return 0
347
+ if (cleanIndex === 0) {
348
+ return 0;
349
+ }
350
+ while (styledPos < styledText.length) {
351
+ // If we've found all the clean characters we need, skip any escape
352
+ // sequences at the current position and return after them
353
+ if (cleanPos >= cleanIndex) {
354
+ // Skip any escape sequences at this position
355
+ while (styledPos < styledText.length &&
356
+ styledText[styledPos] === escapeChar) {
357
+ while (styledPos < styledText.length &&
358
+ styledText[styledPos] !== "m") {
359
+ styledPos++;
360
+ }
361
+ styledPos++; // skip 'm'
362
+ }
363
+ return styledPos;
364
+ }
352
365
  const char = cleanText[cleanPos];
353
- // Check if we're at an ANSI escape sequence in the styled text
354
- const escapeChar = String.fromCharCode(27);
355
366
  if (styledText[styledPos] === escapeChar) {
356
367
  // Skip the entire ANSI escape sequence
357
368
  while (styledPos < styledText.length && styledText[styledPos] !== "m") {
358
369
  styledPos++;
359
370
  }
360
- // Skip the 'm' character too
361
371
  styledPos++;
362
- // Don't increment cleanPos - ANSI codes are inserted between characters
372
+ // Don't increment cleanPos - ANSI codes don't correspond to clean text characters
363
373
  }
364
374
  else if (styledText[styledPos] === char) {
365
375
  // Characters match, advance both
@@ -375,24 +385,40 @@ export class Markdown {
375
385
  return styledPos;
376
386
  }
377
387
  /**
378
- * Protect inline code spans by replacing them with placeholders
379
- * This prevents wrapAnsi from breaking code spans across lines
388
+ * Create a placeholder string whose visible width matches the target width.
389
+ * Returns null if the code span is too short to protect reliably.
390
+ */
391
+ createWidthMatchedPlaceholder(index, targetWidth) {
392
+ if (targetWidth < 3) {
393
+ return null;
394
+ }
395
+ const core = `__CS${index}__`;
396
+ const coreWidth = core.length;
397
+ if (targetWidth >= coreWidth) {
398
+ return core + "_".repeat(targetWidth - coreWidth);
399
+ }
400
+ const short = `_${index}_`;
401
+ if (targetWidth >= short.length) {
402
+ return short + "_".repeat(targetWidth - short.length);
403
+ }
404
+ return null;
405
+ }
406
+ /**
407
+ * Protect inline code spans by replacing them with width-matched placeholders.
408
+ * This prevents wrapAnsi from breaking code spans across lines while
409
+ * preserving the correct visible width for accurate wrapping.
380
410
  */
381
411
  protectCodeSpans(text) {
382
412
  const codeSpans = [];
413
+ const placeholders = [];
383
414
  let protectedText = text;
384
415
  let placeholderIndex = 0;
385
- // Create a version of the text without ANSI codes for code span detection
386
- // This allows us to reliably find code spans regardless of styling
387
416
  const cleanText = stripAnsi(text);
388
- // Use the clean text to find code spans
389
417
  let i = 0;
390
418
  while (i < cleanText.length) {
391
- // Find the next backtick in clean text
392
419
  const backtickIndex = cleanText.indexOf("`", i);
393
420
  if (backtickIndex === -1)
394
421
  break;
395
- // Look for the closing backtick in clean text
396
422
  let closingIndex = -1;
397
423
  let depth = 1;
398
424
  for (let j = backtickIndex + 1; j < cleanText.length; j++) {
@@ -405,25 +431,23 @@ export class Markdown {
405
431
  }
406
432
  }
407
433
  if (closingIndex !== -1) {
408
- // Map the positions to the styled text
409
434
  const styledStart = this.cleanToStyledIndex(cleanText, text, backtickIndex);
410
435
  const styledEnd = this.cleanToStyledIndex(cleanText, text, closingIndex + 1);
411
- // Extract the styled code span
412
436
  const styledCodeSpan = text.slice(styledStart, styledEnd);
413
- const placeholder = `__CODE_SPAN_${placeholderIndex}__`;
414
- // Store the full styled code span for restoration
415
- codeSpans.push(styledCodeSpan);
416
- // Replace with placeholder
417
- protectedText = protectedText.replace(styledCodeSpan, placeholder);
418
- placeholderIndex++;
419
- // Move past this code span
437
+ const codeSpanWidth = visibleWidth(styledCodeSpan);
438
+ const placeholder = this.createWidthMatchedPlaceholder(placeholderIndex, codeSpanWidth);
439
+ if (placeholder !== null) {
440
+ codeSpans.push(styledCodeSpan);
441
+ placeholders.push(placeholder);
442
+ protectedText = protectedText.replace(styledCodeSpan, placeholder);
443
+ placeholderIndex++;
444
+ }
420
445
  i = closingIndex + 1;
421
446
  continue;
422
447
  }
423
- // Move to next character
424
448
  i = backtickIndex + 1;
425
449
  }
426
- return { protectedText, codeSpans };
450
+ return { protectedText, codeSpans, placeholders };
427
451
  }
428
452
  /**
429
453
  * Check if a line represents a nested list item
@@ -453,17 +477,11 @@ export class Markdown {
453
477
  }
454
478
  return false;
455
479
  }
456
- /**
457
- * Restore code spans from placeholders after wrapping
458
- */
459
- restoreCodeSpans(lines, codeSpans) {
480
+ restoreCodeSpans(lines, codeSpans, placeholders) {
460
481
  return lines.map((line) => {
461
482
  let restoredLine = line;
462
- // Restore each code span placeholder
463
483
  for (let i = 0; i < codeSpans.length; i++) {
464
- const placeholder = `__CODE_SPAN_${i}__`;
465
- const codeSpan = codeSpans[i];
466
- restoredLine = restoredLine.replace(placeholder, codeSpan);
484
+ restoredLine = restoredLine.replace(placeholders[i], codeSpans[i]);
467
485
  }
468
486
  return restoredLine;
469
487
  });
@@ -1 +1 @@
1
- {"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../../source/tui/components/modal.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC;;GAEG;AACH,qBAAa,KAAM,SAAQ,SAAU,YAAW,SAAS;IACvD,OAAO,CAAC,KAAK,CAAS;IACf,QAAQ,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,OAAO,CAAC,CAAa;IAC7B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAK;gBAGzB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,SAAS,EAClB,QAAQ,UAAO,EACf,OAAO,CAAC,EAAE,MAAM,IAAI,EACpB,QAAQ,CAAC,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM;IAYpB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAgD/B,KAAK,IAAI,IAAI;IAMJ,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAqHxC,iBAAiB,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;CA2B7C;AAED;;GAEG;AACH,qBAAa,SAAU,SAAQ,SAAS;IACtC,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;gBAEb,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAI,EAAE,QAAQ,SAAI;IAO3C,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAkFzC"}
1
+ {"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../../source/tui/components/modal.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC;;GAEG;AACH,qBAAa,KAAM,SAAQ,SAAU,YAAW,SAAS;IACvD,OAAO,CAAC,KAAK,CAAS;IACf,QAAQ,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,OAAO,CAAC,CAAa;IAC7B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAK;gBAGzB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,SAAS,EAClB,QAAQ,UAAO,EACf,OAAO,CAAC,EAAE,MAAM,IAAI,EACpB,QAAQ,CAAC,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM;IAYpB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAgD/B,KAAK,IAAI,IAAI;IAMJ,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAqHxC,iBAAiB,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;CA2B7C;AAwCD;;GAEG;AACH,qBAAa,SAAU,SAAQ,SAAS;IACtC,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;gBAEb,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAI,EAAE,QAAQ,SAAI;IAO3C,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CA8CzC"}
@@ -178,6 +178,40 @@ export class Modal extends Container {
178
178
  return null;
179
179
  }
180
180
  }
181
+ function wrapLine(line, contentWidth) {
182
+ const words = line.split(" ");
183
+ const lines = [];
184
+ let currentLine = "";
185
+ for (const word of words) {
186
+ const currentVisible = visibleWidth(currentLine);
187
+ const wordVisible = visibleWidth(word);
188
+ let finalWord = word;
189
+ if (wordVisible > contentWidth) {
190
+ let truncated = "";
191
+ for (const char of word) {
192
+ if (visibleWidth(truncated + char) > contentWidth) {
193
+ break;
194
+ }
195
+ truncated += char;
196
+ }
197
+ finalWord = truncated;
198
+ }
199
+ if (currentVisible === 0) {
200
+ currentLine = finalWord;
201
+ }
202
+ else if (currentVisible + 1 + visibleWidth(finalWord) <= contentWidth) {
203
+ currentLine += ` ${finalWord}`;
204
+ }
205
+ else {
206
+ lines.push(currentLine);
207
+ currentLine = finalWord;
208
+ }
209
+ }
210
+ if (currentLine.length > 0) {
211
+ lines.push(currentLine);
212
+ }
213
+ return lines;
214
+ }
181
215
  /**
182
216
  * ModalText component - displays text content in a modal with word wrapping
183
217
  */
@@ -206,39 +240,7 @@ export class ModalText extends Container {
206
240
  lines.push(line);
207
241
  }
208
242
  else {
209
- // Word wrap
210
- const words = line.split(" ");
211
- let currentLine = "";
212
- for (const word of words) {
213
- const currentVisible = visibleWidth(currentLine);
214
- const wordVisible = visibleWidth(word);
215
- let finalWord = word;
216
- if (wordVisible > contentWidth) {
217
- // Truncate word to fit
218
- let truncated = "";
219
- for (const char of word) {
220
- if (visibleWidth(truncated + char) > contentWidth) {
221
- break;
222
- }
223
- truncated += char;
224
- }
225
- finalWord = truncated;
226
- }
227
- if (currentVisible === 0) {
228
- currentLine = finalWord;
229
- }
230
- else if (currentVisible + 1 + visibleWidth(finalWord) <=
231
- contentWidth) {
232
- currentLine += ` ${finalWord}`;
233
- }
234
- else {
235
- lines.push(currentLine);
236
- currentLine = finalWord;
237
- }
238
- }
239
- if (currentLine.length > 0) {
240
- lines.push(currentLine);
241
- }
243
+ lines.push(...wrapLine(line, contentWidth));
242
244
  }
243
245
  }
244
246
  // Add padding
@@ -1,12 +1,15 @@
1
1
  import type { Component } from "../tui.ts";
2
2
  /**
3
3
  * NotificationComponent - displays a notification message with styling
4
+ * and auto-dismiss functionality.
4
5
  */
5
6
  export declare class NotificationComponent implements Component {
6
7
  private message;
7
8
  private bgColor;
8
9
  private textStyle;
9
10
  private paddingX;
11
+ private autoDismissTimer?;
12
+ private onDismiss?;
10
13
  private cachedMessage?;
11
14
  private cachedWidth?;
12
15
  private cachedLines?;
@@ -14,8 +17,16 @@ export declare class NotificationComponent implements Component {
14
17
  r: number;
15
18
  g: number;
16
19
  b: number;
17
- }, textStyle?: (text: string) => string, paddingX?: number);
18
- setMessage(message: string): void;
20
+ }, textStyle?: (text: string) => string, paddingX?: number, onDismiss?: () => void);
21
+ /**
22
+ * Clears the notification immediately and cancels any pending timer.
23
+ */
24
+ clear(): void;
25
+ /**
26
+ * Clears any pending auto-dismiss timer.
27
+ */
28
+ private clearTimer;
29
+ setMessage(message: string, autoDismissMs?: number): void;
19
30
  setBgColor(bgColor: {
20
31
  r: number;
21
32
  g: number;
@@ -1 +1 @@
1
- {"version":3,"file":"notification.d.ts","sourceRoot":"","sources":["../../../source/tui/components/notification.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3C;;GAEG;AACH,qBAAa,qBAAsB,YAAW,SAAS;IACrD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAsC;IACrD,OAAO,CAAC,SAAS,CAA2B;IAC5C,OAAO,CAAC,QAAQ,CAAS;IAGzB,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAC,CAAW;gBAG7B,OAAO,SAAK,EACZ,OAAO;;;;KAA0B,EACjC,SAAS,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAqB,EAClD,QAAQ,SAAI;IAQd,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAKjC,UAAU,CAAC,OAAO,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAK9D,YAAY,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI;IAKvD,OAAO,CAAC,eAAe;IAMvB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAsChC"}
1
+ {"version":3,"file":"notification.d.ts","sourceRoot":"","sources":["../../../source/tui/components/notification.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3C;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,SAAS;IACrD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAsC;IACrD,OAAO,CAAC,SAAS,CAA2B;IAC5C,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,gBAAgB,CAAC,CAAiB;IAC1C,OAAO,CAAC,SAAS,CAAC,CAAa;IAG/B,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAC,CAAW;gBAG7B,OAAO,SAAK,EACZ,OAAO;;;;KAA0B,EACjC,SAAS,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAqB,EAClD,QAAQ,SAAI,EACZ,SAAS,CAAC,EAAE,MAAM,IAAI;IASxB;;OAEG;IACH,KAAK,IAAI,IAAI;IAMb;;OAEG;IACH,OAAO,CAAC,UAAU;IAOlB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,SAAO,GAAG,IAAI;IAoBvD,UAAU,CAAC,OAAO,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAK9D,YAAY,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI;IAKvD,OAAO,CAAC,eAAe;IAMvB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAsChC"}
@@ -2,25 +2,59 @@ import style from "../../terminal/style.js";
2
2
  import { visibleWidth } from "../utils.js";
3
3
  /**
4
4
  * NotificationComponent - displays a notification message with styling
5
+ * and auto-dismiss functionality.
5
6
  */
6
7
  export class NotificationComponent {
7
8
  message;
8
9
  bgColor;
9
10
  textStyle;
10
11
  paddingX;
12
+ autoDismissTimer;
13
+ onDismiss;
11
14
  // Cache for rendered output
12
15
  cachedMessage;
13
16
  cachedWidth;
14
17
  cachedLines;
15
- constructor(message = "", bgColor = { r: 64, g: 64, b: 64 }, textStyle = style.yellow, paddingX = 1) {
18
+ constructor(message = "", bgColor = { r: 52, g: 53, b: 65 }, textStyle = style.yellow, paddingX = 1, onDismiss) {
16
19
  this.message = message;
17
20
  this.bgColor = bgColor;
18
21
  this.textStyle = textStyle;
19
22
  this.paddingX = paddingX;
23
+ this.onDismiss = onDismiss;
20
24
  }
21
- setMessage(message) {
25
+ /**
26
+ * Clears the notification immediately and cancels any pending timer.
27
+ */
28
+ clear() {
29
+ this.clearTimer();
30
+ this.message = "";
31
+ this.invalidateCache();
32
+ }
33
+ /**
34
+ * Clears any pending auto-dismiss timer.
35
+ */
36
+ clearTimer() {
37
+ if (this.autoDismissTimer) {
38
+ clearTimeout(this.autoDismissTimer);
39
+ this.autoDismissTimer = undefined;
40
+ }
41
+ }
42
+ setMessage(message, autoDismissMs = 3000) {
43
+ // Clear any pending timer first (handles reset on new notification)
44
+ this.clearTimer();
22
45
  this.message = message;
23
46
  this.invalidateCache();
47
+ // If message is non-empty, set up auto-dismiss
48
+ if (message) {
49
+ this.autoDismissTimer = setTimeout(() => {
50
+ this.message = "";
51
+ this.autoDismissTimer = undefined;
52
+ this.invalidateCache();
53
+ if (this.onDismiss) {
54
+ this.onDismiss();
55
+ }
56
+ }, autoDismissMs);
57
+ }
24
58
  }
25
59
  setBgColor(bgColor) {
26
60
  this.bgColor = bgColor;
@@ -1,5 +1,5 @@
1
- import { formatNumber } from "../../formatting.js";
2
1
  import style from "../../terminal/style.js";
2
+ import { formatNumber } from "../../utils/formatting.js";
3
3
  /**
4
4
  * Progress bar component - displays a visual progress indicator
5
5
  */
@@ -26,6 +26,7 @@ export declare class SelectList implements Component {
26
26
  setFilter(filter: string): void;
27
27
  setSelectedIndex(index: number): void;
28
28
  render(width: number): string[];
29
+ wantsNavigationKeys(): boolean;
29
30
  handleInput(keyData: string): void;
30
31
  private notifySelectionChange;
31
32
  getSelectedItem(): SelectItem | null;
@@ -1 +1 @@
1
- {"version":3,"file":"select-list.d.ts","sourceRoot":"","sources":["../../../source/tui/components/select-list.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3C,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACvC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACrC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACnC;AAED,qBAAa,UAAW,YAAW,SAAS;IAC1C,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,aAAa,CAAoB;IACzC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,KAAK,CAAkB;IAExB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;gBAE1C,KAAK,EAAE,UAAU,EAAE,EAAE,UAAU,SAAI,EAAE,KAAK,CAAC,EAAE,eAAe;IAOxE,OAAO,CAAC,kBAAkB;IAU1B,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE;IAQ/B,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAQ/B,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAOrC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAgI/B,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAgDlC,OAAO,CAAC,qBAAqB;IAO7B,eAAe,IAAI,UAAU,GAAG,IAAI;CAIrC"}
1
+ {"version":3,"file":"select-list.d.ts","sourceRoot":"","sources":["../../../source/tui/components/select-list.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3C,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACvC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACrC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACnC;AAED,qBAAa,UAAW,YAAW,SAAS;IAC1C,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,aAAa,CAAoB;IACzC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,KAAK,CAAkB;IAExB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;gBAE1C,KAAK,EAAE,UAAU,EAAE,EAAE,UAAU,SAAI,EAAE,KAAK,CAAC,EAAE,eAAe;IAOxE,OAAO,CAAC,kBAAkB;IAU1B,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE;IAQ/B,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAQ/B,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAOrC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAgI/B,mBAAmB,IAAI,OAAO;IAI9B,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAgDlC,OAAO,CAAC,qBAAqB;IAO7B,eAAe,IAAI,UAAU,GAAG,IAAI;CAIrC"}
@@ -63,27 +63,27 @@ export class SelectList {
63
63
  const displayValue = item.label || item.value;
64
64
  if (item.description && width > 40) {
65
65
  // Calculate how much space we have for value + description
66
- const maxValueWidth = Math.min(30, width - prefixWidth - 4);
67
- const truncatedValue = truncateToWidth(displayValue, maxValueWidth, "");
66
+ const maxValueWidth = width - prefixWidth - 4;
67
+ const truncatedValue = truncateToWidth(displayValue, maxValueWidth, "...");
68
68
  const spacing = " ".repeat(Math.max(1, 32 - truncatedValue.length));
69
69
  // Calculate remaining space for description using visible widths
70
70
  const descriptionStart = prefixWidth + truncatedValue.length + spacing.length;
71
71
  const remainingWidth = width - descriptionStart - 2; // -2 for safety
72
72
  if (remainingWidth > 10) {
73
- const truncatedDesc = truncateToWidth(item.description, remainingWidth, "");
73
+ const truncatedDesc = truncateToWidth(item.description, remainingWidth, "...");
74
74
  // Apply selectedText to entire line content
75
75
  line = this.theme.selectedText(`→ ${truncatedValue}${spacing}${truncatedDesc}`);
76
76
  }
77
77
  else {
78
78
  // Not enough space for description
79
79
  const maxWidth = width - prefixWidth - 2;
80
- line = this.theme.selectedText(`→ ${truncateToWidth(displayValue, maxWidth, "")}`);
80
+ line = this.theme.selectedText(`→ ${truncateToWidth(displayValue, maxWidth, "...")}`);
81
81
  }
82
82
  }
83
83
  else {
84
84
  // No description or not enough width
85
85
  const maxWidth = width - prefixWidth - 2;
86
- line = this.theme.selectedText(`→ ${truncateToWidth(displayValue, maxWidth, "")}`);
86
+ line = this.theme.selectedText(`→ ${truncateToWidth(displayValue, maxWidth, "...")}`);
87
87
  }
88
88
  }
89
89
  else {
@@ -91,27 +91,27 @@ export class SelectList {
91
91
  const prefix = " ";
92
92
  if (item.description && width > 40) {
93
93
  // Calculate how much space we have for value + description
94
- const maxValueWidth = Math.min(30, width - prefix.length - 4);
95
- const truncatedValue = truncateToWidth(displayValue, maxValueWidth, "");
94
+ const maxValueWidth = width - prefix.length - 4;
95
+ const truncatedValue = truncateToWidth(displayValue, maxValueWidth, "...");
96
96
  const spacing = " ".repeat(Math.max(1, 32 - truncatedValue.length));
97
97
  // Calculate remaining space for description
98
98
  const descriptionStart = prefix.length + truncatedValue.length + spacing.length;
99
99
  const remainingWidth = width - descriptionStart - 2; // -2 for safety
100
100
  if (remainingWidth > 10) {
101
- const truncatedDesc = truncateToWidth(item.description, remainingWidth, "");
101
+ const truncatedDesc = truncateToWidth(item.description, remainingWidth, "...");
102
102
  const descText = this.theme.description(spacing + truncatedDesc);
103
103
  line = prefix + truncatedValue + descText;
104
104
  }
105
105
  else {
106
106
  // Not enough space for description
107
107
  const maxWidth = width - prefix.length - 2;
108
- line = prefix + truncateToWidth(displayValue, maxWidth, "");
108
+ line = prefix + truncateToWidth(displayValue, maxWidth, "...");
109
109
  }
110
110
  }
111
111
  else {
112
112
  // No description or not enough width
113
113
  const maxWidth = width - prefix.length - 2;
114
- line = prefix + truncateToWidth(displayValue, maxWidth, "");
114
+ line = prefix + truncateToWidth(displayValue, maxWidth, "...");
115
115
  }
116
116
  }
117
117
  lines.push(line);
@@ -120,10 +120,13 @@ export class SelectList {
120
120
  if (startIndex > 0 || endIndex < this.filteredItems.length) {
121
121
  const scrollText = ` (${this.selectedIndex + 1}/${this.filteredItems.length})`;
122
122
  // Truncate if too long for terminal
123
- lines.push(this.theme.scrollInfo(truncateToWidth(scrollText, width - 2, "")));
123
+ lines.push(this.theme.scrollInfo(truncateToWidth(scrollText, width - 2, "...")));
124
124
  }
125
125
  return lines;
126
126
  }
127
+ wantsNavigationKeys() {
128
+ return true;
129
+ }
127
130
  handleInput(keyData) {
128
131
  // Up arrow - wrap to bottom when at top
129
132
  if (isArrowUp(keyData)) {