@travisennis/acai 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) hide show
  1. package/README.md +4 -2
  2. package/dist/agent/index.d.ts +119 -0
  3. package/dist/agent/index.d.ts.map +1 -0
  4. package/dist/agent/index.js +406 -0
  5. package/dist/agent/manual-loop.d.ts +41 -0
  6. package/dist/agent/manual-loop.d.ts.map +1 -0
  7. package/dist/agent/manual-loop.js +278 -0
  8. package/dist/cli.d.ts +2 -0
  9. package/dist/cli.d.ts.map +1 -1
  10. package/dist/cli.js +27 -33
  11. package/dist/commands/add-directory-command.d.ts +3 -0
  12. package/dist/commands/add-directory-command.d.ts.map +1 -0
  13. package/dist/commands/add-directory-command.js +85 -0
  14. package/dist/commands/application-log-command.d.ts.map +1 -1
  15. package/dist/commands/application-log-command.js +34 -0
  16. package/dist/commands/clear-command.d.ts.map +1 -1
  17. package/dist/commands/clear-command.js +8 -0
  18. package/dist/commands/compact-command.d.ts.map +1 -1
  19. package/dist/commands/compact-command.js +15 -2
  20. package/dist/commands/context-command.d.ts +3 -0
  21. package/dist/commands/context-command.d.ts.map +1 -0
  22. package/dist/commands/context-command.js +183 -0
  23. package/dist/commands/copy-command.d.ts.map +1 -1
  24. package/dist/commands/copy-command.js +28 -0
  25. package/dist/commands/edit-command.d.ts.map +1 -1
  26. package/dist/commands/edit-command.js +33 -0
  27. package/dist/commands/edit-prompt-command.d.ts.map +1 -1
  28. package/dist/commands/edit-prompt-command.js +28 -0
  29. package/dist/commands/exit-command.d.ts.map +1 -1
  30. package/dist/commands/exit-command.js +20 -0
  31. package/dist/commands/files-command.d.ts.map +1 -1
  32. package/dist/commands/files-command.js +57 -0
  33. package/dist/commands/generate-rules-command.d.ts.map +1 -1
  34. package/dist/commands/generate-rules-command.js +311 -1
  35. package/dist/commands/handoff-command.d.ts +3 -0
  36. package/dist/commands/handoff-command.d.ts.map +1 -0
  37. package/dist/commands/handoff-command.js +202 -0
  38. package/dist/commands/health-command.d.ts.map +1 -1
  39. package/dist/commands/health-command.js +119 -2
  40. package/dist/commands/help-command.d.ts.map +1 -1
  41. package/dist/commands/help-command.js +28 -0
  42. package/dist/commands/history-command.d.ts +3 -0
  43. package/dist/commands/history-command.d.ts.map +1 -0
  44. package/dist/commands/history-command.js +534 -0
  45. package/dist/commands/init-command.d.ts +1 -1
  46. package/dist/commands/init-command.d.ts.map +1 -1
  47. package/dist/commands/init-command.js +55 -18
  48. package/dist/commands/last-log-command.d.ts.map +1 -1
  49. package/dist/commands/last-log-command.js +27 -0
  50. package/dist/commands/list-directories-command.d.ts +3 -0
  51. package/dist/commands/list-directories-command.d.ts.map +1 -0
  52. package/dist/commands/list-directories-command.js +48 -0
  53. package/dist/commands/list-tools-command.d.ts.map +1 -1
  54. package/dist/commands/list-tools-command.js +66 -3
  55. package/dist/commands/manager.d.ts +15 -3
  56. package/dist/commands/manager.d.ts.map +1 -1
  57. package/dist/commands/manager.js +86 -26
  58. package/dist/commands/model-command.d.ts +22 -0
  59. package/dist/commands/model-command.d.ts.map +1 -1
  60. package/dist/commands/model-command.js +256 -0
  61. package/dist/commands/paste-command.d.ts.map +1 -1
  62. package/dist/commands/paste-command.js +92 -0
  63. package/dist/commands/pickup-command.d.ts +3 -0
  64. package/dist/commands/pickup-command.d.ts.map +1 -0
  65. package/dist/commands/pickup-command.js +161 -0
  66. package/dist/commands/prompt-command.d.ts +1 -1
  67. package/dist/commands/prompt-command.d.ts.map +1 -1
  68. package/dist/commands/prompt-command.js +117 -2
  69. package/dist/commands/remove-directory-command.d.ts +3 -0
  70. package/dist/commands/remove-directory-command.d.ts.map +1 -0
  71. package/dist/commands/remove-directory-command.js +87 -0
  72. package/dist/commands/reset-command.d.ts +1 -1
  73. package/dist/commands/reset-command.d.ts.map +1 -1
  74. package/dist/commands/reset-command.js +13 -2
  75. package/dist/commands/rules-command.d.ts.map +1 -1
  76. package/dist/commands/rules-command.js +65 -0
  77. package/dist/commands/save-command.d.ts.map +1 -1
  78. package/dist/commands/save-command.js +12 -0
  79. package/dist/commands/shell-command.d.ts.map +1 -1
  80. package/dist/commands/shell-command.js +68 -0
  81. package/dist/commands/types.d.ts +9 -4
  82. package/dist/commands/types.d.ts.map +1 -1
  83. package/dist/commands/usage-command.d.ts.map +1 -1
  84. package/dist/commands/usage-command.js +22 -0
  85. package/dist/config.d.ts +6 -7
  86. package/dist/config.d.ts.map +1 -1
  87. package/dist/config.js +23 -29
  88. package/dist/formatting.d.ts +108 -0
  89. package/dist/formatting.d.ts.map +1 -1
  90. package/dist/formatting.js +147 -0
  91. package/dist/index.d.ts +7 -2
  92. package/dist/index.d.ts.map +1 -1
  93. package/dist/index.js +140 -38
  94. package/dist/logger.d.ts.map +1 -1
  95. package/dist/logger.js +47 -18
  96. package/dist/mentions.d.ts +2 -1
  97. package/dist/mentions.d.ts.map +1 -1
  98. package/dist/mentions.js +16 -1
  99. package/dist/messages.d.ts +8 -0
  100. package/dist/messages.d.ts.map +1 -1
  101. package/dist/messages.js +56 -19
  102. package/dist/middleware/cache.d.ts +3 -0
  103. package/dist/middleware/cache.d.ts.map +1 -0
  104. package/dist/middleware/cache.js +53 -0
  105. package/dist/middleware/index.d.ts +1 -0
  106. package/dist/middleware/index.d.ts.map +1 -1
  107. package/dist/middleware/index.js +1 -0
  108. package/dist/models/ai-config.d.ts +4 -2
  109. package/dist/models/ai-config.d.ts.map +1 -1
  110. package/dist/models/ai-config.js +12 -2
  111. package/dist/models/anthropic-provider.d.ts.map +1 -1
  112. package/dist/models/anthropic-provider.js +3 -60
  113. package/dist/models/manager.d.ts +2 -1
  114. package/dist/models/manager.d.ts.map +1 -1
  115. package/dist/models/manager.js +26 -2
  116. package/dist/models/openrouter-provider.d.ts +7 -14
  117. package/dist/models/openrouter-provider.d.ts.map +1 -1
  118. package/dist/models/openrouter-provider.js +114 -169
  119. package/dist/models/providers.d.ts +1 -1
  120. package/dist/models/providers.d.ts.map +1 -1
  121. package/dist/prompts.d.ts +1 -0
  122. package/dist/prompts.d.ts.map +1 -1
  123. package/dist/prompts.js +53 -4
  124. package/dist/repl/display-tool-messages.d.ts +1 -1
  125. package/dist/repl/display-tool-messages.d.ts.map +1 -1
  126. package/dist/repl/display-tool-messages.js +47 -44
  127. package/dist/repl/get-prompt-header.d.ts.map +1 -1
  128. package/dist/repl/get-prompt-header.js +1 -30
  129. package/dist/repl/project-status-line.d.ts +2 -0
  130. package/dist/repl/project-status-line.d.ts.map +1 -0
  131. package/dist/repl/project-status-line.js +31 -0
  132. package/dist/repl/prompt.d.ts +21 -0
  133. package/dist/repl/prompt.d.ts.map +1 -0
  134. package/dist/{repl-prompt.js → repl/prompt.js} +119 -22
  135. package/dist/repl/tool-call-repair.d.ts.map +1 -1
  136. package/dist/repl/tool-call-repair.js +8 -4
  137. package/dist/repl-new.d.ts +53 -0
  138. package/dist/repl-new.d.ts.map +1 -0
  139. package/dist/repl-new.js +374 -0
  140. package/dist/repl.d.ts +3 -5
  141. package/dist/repl.d.ts.map +1 -1
  142. package/dist/repl.js +74 -166
  143. package/dist/terminal/checkbox-prompt.d.ts.map +1 -1
  144. package/dist/terminal/checkbox-prompt.js +10 -4
  145. package/dist/terminal/index.d.ts +7 -0
  146. package/dist/terminal/index.d.ts.map +1 -1
  147. package/dist/terminal/index.js +94 -0
  148. package/dist/terminal/input-prompt.d.ts +2 -1
  149. package/dist/terminal/input-prompt.d.ts.map +1 -1
  150. package/dist/terminal/markdown.js +3 -0
  151. package/dist/terminal/search-prompt.d.ts.map +1 -1
  152. package/dist/terminal/search-prompt.js +11 -10
  153. package/dist/terminal/select-prompt.d.ts +2 -2
  154. package/dist/terminal/select-prompt.d.ts.map +1 -1
  155. package/dist/terminal/select-prompt.js +47 -39
  156. package/dist/tokens/threshold.d.ts +35 -0
  157. package/dist/tokens/threshold.d.ts.map +1 -0
  158. package/dist/tokens/threshold.js +85 -0
  159. package/dist/tools/advanced-edit-file.d.ts +69 -0
  160. package/dist/tools/advanced-edit-file.d.ts.map +1 -0
  161. package/dist/tools/advanced-edit-file.js +281 -0
  162. package/dist/tools/agent.d.ts +16 -5
  163. package/dist/tools/agent.d.ts.map +1 -1
  164. package/dist/tools/agent.js +71 -58
  165. package/dist/tools/bash-utils.d.ts +1 -1
  166. package/dist/tools/bash-utils.d.ts.map +1 -1
  167. package/dist/tools/bash-utils.js +14 -6
  168. package/dist/tools/bash.d.ts +21 -12
  169. package/dist/tools/bash.d.ts.map +1 -1
  170. package/dist/tools/bash.js +88 -135
  171. package/dist/tools/code-interpreter.d.ts +21 -9
  172. package/dist/tools/code-interpreter.d.ts.map +1 -1
  173. package/dist/tools/code-interpreter.js +138 -137
  174. package/dist/tools/delete-file.d.ts +17 -10
  175. package/dist/tools/delete-file.d.ts.map +1 -1
  176. package/dist/tools/delete-file.js +51 -95
  177. package/dist/tools/directory-tree.d.ts +17 -6
  178. package/dist/tools/directory-tree.d.ts.map +1 -1
  179. package/dist/tools/directory-tree.js +47 -49
  180. package/dist/tools/dynamic-tool-loader.d.ts +18 -8
  181. package/dist/tools/dynamic-tool-loader.d.ts.map +1 -1
  182. package/dist/tools/dynamic-tool-loader.js +121 -129
  183. package/dist/tools/dynamic-tool-parser.d.ts +1 -0
  184. package/dist/tools/dynamic-tool-parser.d.ts.map +1 -1
  185. package/dist/tools/dynamic-tool-parser.js +1 -0
  186. package/dist/tools/edit-file.d.ts +35 -15
  187. package/dist/tools/edit-file.d.ts.map +1 -1
  188. package/dist/tools/edit-file.js +112 -112
  189. package/dist/tools/filesystem-utils.d.ts +2 -1
  190. package/dist/tools/filesystem-utils.d.ts.map +1 -1
  191. package/dist/tools/filesystem-utils.js +31 -17
  192. package/dist/tools/glob.d.ts +36 -0
  193. package/dist/tools/glob.d.ts.map +1 -0
  194. package/dist/tools/glob.js +143 -0
  195. package/dist/tools/grep.d.ts +73 -12
  196. package/dist/tools/grep.d.ts.map +1 -1
  197. package/dist/tools/grep.js +413 -168
  198. package/dist/tools/index.d.ts +204 -124
  199. package/dist/tools/index.d.ts.map +1 -1
  200. package/dist/tools/index.js +242 -135
  201. package/dist/tools/llm-edit-fixer.d.ts +25 -0
  202. package/dist/tools/llm-edit-fixer.d.ts.map +1 -0
  203. package/dist/tools/llm-edit-fixer.js +150 -0
  204. package/dist/tools/move-file.d.ts +19 -7
  205. package/dist/tools/move-file.d.ts.map +1 -1
  206. package/dist/tools/move-file.js +40 -33
  207. package/dist/tools/read-file.d.ts +47 -9
  208. package/dist/tools/read-file.d.ts.map +1 -1
  209. package/dist/tools/read-file.js +74 -69
  210. package/dist/tools/read-multiple-files.d.ts +17 -6
  211. package/dist/tools/read-multiple-files.d.ts.map +1 -1
  212. package/dist/tools/read-multiple-files.js +76 -73
  213. package/dist/tools/save-file.d.ts +45 -12
  214. package/dist/tools/save-file.d.ts.map +1 -1
  215. package/dist/tools/save-file.js +58 -101
  216. package/dist/tools/think.d.ts +15 -7
  217. package/dist/tools/think.d.ts.map +1 -1
  218. package/dist/tools/think.js +30 -22
  219. package/dist/tools/types.d.ts +4 -10
  220. package/dist/tools/types.d.ts.map +1 -1
  221. package/dist/tools/types.js +9 -0
  222. package/dist/tools/utils.d.ts +14 -0
  223. package/dist/tools/utils.d.ts.map +1 -0
  224. package/dist/tools/utils.js +16 -0
  225. package/dist/tools/web-fetch.d.ts +11 -4
  226. package/dist/tools/web-fetch.d.ts.map +1 -1
  227. package/dist/tools/web-fetch.js +39 -38
  228. package/dist/tools/web-search.d.ts +15 -6
  229. package/dist/tools/web-search.d.ts.map +1 -1
  230. package/dist/tools/web-search.js +50 -32
  231. package/dist/tui/autocomplete.d.ts +44 -0
  232. package/dist/tui/autocomplete.d.ts.map +1 -0
  233. package/dist/tui/autocomplete.js +466 -0
  234. package/dist/tui/components/assistant-message.d.ts +18 -0
  235. package/dist/tui/components/assistant-message.d.ts.map +1 -0
  236. package/dist/tui/components/assistant-message.js +29 -0
  237. package/dist/tui/components/editor.d.ts +51 -0
  238. package/dist/tui/components/editor.d.ts.map +1 -0
  239. package/dist/tui/components/editor.js +758 -0
  240. package/dist/tui/components/footer.d.ts +24 -0
  241. package/dist/tui/components/footer.d.ts.map +1 -0
  242. package/dist/tui/components/footer.js +197 -0
  243. package/dist/tui/components/input.d.ts +14 -0
  244. package/dist/tui/components/input.d.ts.map +1 -0
  245. package/dist/tui/components/input.js +122 -0
  246. package/dist/tui/components/loader.d.ts +19 -0
  247. package/dist/tui/components/loader.d.ts.map +1 -0
  248. package/dist/tui/components/loader.js +45 -0
  249. package/dist/tui/components/markdown.d.ts +103 -0
  250. package/dist/tui/components/markdown.d.ts.map +1 -0
  251. package/dist/tui/components/markdown.js +533 -0
  252. package/dist/tui/components/modal.d.ts +40 -0
  253. package/dist/tui/components/modal.d.ts.map +1 -0
  254. package/dist/tui/components/modal.js +292 -0
  255. package/dist/tui/components/prompt-status.d.ts +16 -0
  256. package/dist/tui/components/prompt-status.d.ts.map +1 -0
  257. package/dist/tui/components/prompt-status.js +21 -0
  258. package/dist/tui/components/select-list.d.ts +22 -0
  259. package/dist/tui/components/select-list.d.ts.map +1 -0
  260. package/dist/tui/components/select-list.js +143 -0
  261. package/dist/tui/components/spacer.d.ts +16 -0
  262. package/dist/tui/components/spacer.d.ts.map +1 -0
  263. package/dist/tui/components/spacer.js +27 -0
  264. package/dist/tui/components/text.d.ts +26 -0
  265. package/dist/tui/components/text.d.ts.map +1 -0
  266. package/dist/tui/components/text.js +143 -0
  267. package/dist/tui/components/thinking-block.d.ts +14 -0
  268. package/dist/tui/components/thinking-block.d.ts.map +1 -0
  269. package/dist/tui/components/thinking-block.js +30 -0
  270. package/dist/tui/components/tool-execution.d.ts +17 -0
  271. package/dist/tui/components/tool-execution.d.ts.map +1 -0
  272. package/dist/tui/components/tool-execution.js +153 -0
  273. package/dist/tui/components/user-message.d.ts +9 -0
  274. package/dist/tui/components/user-message.d.ts.map +1 -0
  275. package/dist/tui/components/user-message.js +21 -0
  276. package/dist/tui/components/welcome.d.ts +6 -0
  277. package/dist/tui/components/welcome.d.ts.map +1 -0
  278. package/dist/tui/components/welcome.js +30 -0
  279. package/dist/tui/index.d.ts +14 -0
  280. package/dist/tui/index.d.ts.map +1 -0
  281. package/dist/tui/index.js +18 -0
  282. package/dist/tui/terminal.d.ts +37 -0
  283. package/dist/tui/terminal.d.ts.map +1 -0
  284. package/dist/tui/terminal.js +104 -0
  285. package/dist/tui/tui.d.ts +67 -0
  286. package/dist/tui/tui.d.ts.map +1 -0
  287. package/dist/tui/tui.js +184 -0
  288. package/dist/tui/utils.d.ts +19 -0
  289. package/dist/tui/utils.d.ts.map +1 -0
  290. package/dist/tui/utils.js +31 -0
  291. package/dist/utils/generators.d.ts +3 -0
  292. package/dist/utils/generators.d.ts.map +1 -0
  293. package/dist/utils/generators.js +25 -0
  294. package/dist/utils/iterables.d.ts +2 -0
  295. package/dist/utils/iterables.d.ts.map +1 -0
  296. package/dist/utils/iterables.js +6 -0
  297. package/package.json +16 -16
  298. package/dist/conversation-analyzer.d.ts +0 -11
  299. package/dist/conversation-analyzer.d.ts.map +0 -1
  300. package/dist/conversation-analyzer.js +0 -88
  301. package/dist/repl-prompt.d.ts +0 -15
  302. package/dist/repl-prompt.d.ts.map +0 -1
  303. package/dist/tokens/manage-output.d.ts +0 -34
  304. package/dist/tokens/manage-output.d.ts.map +0 -1
  305. package/dist/tokens/manage-output.js +0 -44
  306. package/dist/tool-executor.d.ts +0 -28
  307. package/dist/tool-executor.d.ts.map +0 -1
  308. package/dist/tool-executor.js +0 -74
  309. package/dist/tools/file-editing-utils.d.ts +0 -2
  310. package/dist/tools/file-editing-utils.d.ts.map +0 -1
  311. package/dist/tools/file-editing-utils.js +0 -135
@@ -0,0 +1,292 @@
1
+ import { getTerminalSize } from "../../terminal/formatting.js";
2
+ import { table } from "../../terminal/index.js";
3
+ import style from "../../terminal/style.js";
4
+ import { Container } from "../tui.js";
5
+ import { visibleWidth } from "../utils.js";
6
+ /**
7
+ * Modal component - displays content in an overlay on top of the main UI
8
+ */
9
+ export class Modal extends Container {
10
+ title;
11
+ backdrop;
12
+ onClose;
13
+ maxWidth;
14
+ maxHeight;
15
+ scrollPosition = 0;
16
+ constructor(title, content, backdrop = true, onClose, maxWidth, maxHeight) {
17
+ super();
18
+ this.title = title;
19
+ this.backdrop = backdrop;
20
+ this.onClose = onClose;
21
+ const { columns, rows } = getTerminalSize();
22
+ this.maxWidth = maxWidth ?? columns;
23
+ this.maxHeight = maxHeight ?? rows;
24
+ this.addChild(content);
25
+ }
26
+ handleInput(data) {
27
+ // Handle Escape key to close modal
28
+ if (data === "\x1b") {
29
+ this.close();
30
+ return;
31
+ }
32
+ // Handle scrolling
33
+ if (data === "\x1b[A") {
34
+ // Up arrow
35
+ this.scrollPosition = Math.max(0, this.scrollPosition - 1);
36
+ return;
37
+ }
38
+ if (data === "\x1b[B") {
39
+ // Down arrow
40
+ this.scrollPosition += 1;
41
+ return;
42
+ }
43
+ if (data === "\x1b[5~") {
44
+ // Page up
45
+ this.scrollPosition = Math.max(0, this.scrollPosition - 10);
46
+ return;
47
+ }
48
+ if (data === "\x1b[6~") {
49
+ // Page down
50
+ this.scrollPosition += 10;
51
+ return;
52
+ }
53
+ if (data === "\x1b[H" || data === "g") {
54
+ // Home key or 'g' for top
55
+ this.scrollPosition = 0;
56
+ return;
57
+ }
58
+ if (data === "\x1b[F" || data === "G") {
59
+ // End key or 'G' for bottom
60
+ this.scrollPosition = Number.POSITIVE_INFINITY; // Will be clamped in render
61
+ return;
62
+ }
63
+ // Pass input to focused child component
64
+ if (this.children.length > 0) {
65
+ const focusedChild = this.children[0];
66
+ if (focusedChild.handleInput) {
67
+ focusedChild.handleInput(data);
68
+ }
69
+ }
70
+ }
71
+ close() {
72
+ if (this.onClose) {
73
+ this.onClose();
74
+ }
75
+ }
76
+ render(width) {
77
+ const lines = [];
78
+ // Calculate modal dimensions - use dynamic sizing
79
+ // Use the provided width directly, ensuring reasonable minimum and maximum
80
+ const modalWidth = Math.max(40, width - 2);
81
+ const contentWidth = modalWidth - 4; // Account for borders and padding
82
+ // Calculate content height
83
+ const contentLines = super.render(contentWidth);
84
+ const contentHeight = contentLines.length;
85
+ // Calculate modal height based on content
86
+ const modalHeight = Math.min(this.maxHeight, Math.max(8, contentHeight + 4));
87
+ // Calculate vertical positioning (centered)
88
+ const { rows } = getTerminalSize();
89
+ const terminalHeight = rows;
90
+ const topOffset = Math.max(0, Math.floor((terminalHeight - modalHeight) / 2));
91
+ // Add top offset for centering
92
+ for (let i = 0; i < topOffset; i++) {
93
+ lines.push(" ".repeat(width));
94
+ }
95
+ // Render modal frame
96
+ const horizontalBorder = style.white("─".repeat(modalWidth - 2));
97
+ const emptyLine = style.white("│") + " ".repeat(modalWidth - 2) + style.white("│");
98
+ // Calculate horizontal offset for centering
99
+ // Use different offsets for left and right to ensure full width coverage
100
+ const leftOffset = Math.floor((width - modalWidth) / 2);
101
+ const rightOffset = width - modalWidth - leftOffset;
102
+ // Top border
103
+ lines.push(" ".repeat(leftOffset) +
104
+ style.white("┌") +
105
+ horizontalBorder +
106
+ style.white("┐") +
107
+ " ".repeat(rightOffset));
108
+ // Render content lines with scrolling support
109
+ const visibleContentHeight = Math.min(contentHeight, modalHeight - 4);
110
+ const maxScroll = Math.max(0, contentHeight - visibleContentHeight);
111
+ // Clamp scroll position
112
+ this.scrollPosition = Math.min(maxScroll, Math.max(0, this.scrollPosition));
113
+ // Add scroll indicator to title if content is scrollable
114
+ let displayTitle = this.title;
115
+ if (contentHeight > visibleContentHeight) {
116
+ const scrollInfo = ` (${this.scrollPosition + 1}-${Math.min(this.scrollPosition + visibleContentHeight, contentHeight)}/${contentHeight})`;
117
+ displayTitle = this.title + scrollInfo;
118
+ }
119
+ displayTitle += " [esc to exit]";
120
+ // Update title line with scroll info
121
+ const titleText = ` ${displayTitle} `;
122
+ const titlePadding = Math.max(0, modalWidth - 2 - visibleWidth(titleText));
123
+ const titleLine = style.white("│") +
124
+ style.bold(titleText) +
125
+ " ".repeat(titlePadding) +
126
+ style.white("│");
127
+ lines.push(" ".repeat(leftOffset) + titleLine + " ".repeat(rightOffset));
128
+ // Separator line
129
+ const separator = style.white("├") + "─".repeat(modalWidth - 2) + style.white("┤");
130
+ lines.push(" ".repeat(leftOffset) + separator + " ".repeat(rightOffset));
131
+ for (let i = 0; i < visibleContentHeight; i++) {
132
+ const contentLineIndex = this.scrollPosition + i;
133
+ const contentLine = contentLines[contentLineIndex] || "";
134
+ const visibleLength = visibleWidth(contentLine);
135
+ const padding = " ".repeat(Math.max(0, contentWidth - visibleLength));
136
+ const line = `${style.white("│")} ${contentLine}${padding} ${style.white("│")}`;
137
+ lines.push(" ".repeat(leftOffset) + line + " ".repeat(rightOffset));
138
+ }
139
+ // Fill remaining content area with empty lines if needed
140
+ const remainingLines = modalHeight - 4 - visibleContentHeight;
141
+ for (let i = 0; i < remainingLines; i++) {
142
+ lines.push(" ".repeat(leftOffset) + emptyLine + " ".repeat(rightOffset));
143
+ }
144
+ // Bottom border
145
+ lines.push(" ".repeat(leftOffset) +
146
+ style.white("└") +
147
+ horizontalBorder +
148
+ style.white("┘") +
149
+ " ".repeat(rightOffset));
150
+ // Fill remaining terminal height with empty lines
151
+ const totalLinesSoFar = lines.length;
152
+ const remainingTerminalLines = Math.max(0, terminalHeight - totalLinesSoFar);
153
+ for (let i = 0; i < remainingTerminalLines; i++) {
154
+ lines.push(" ".repeat(width));
155
+ }
156
+ return lines;
157
+ }
158
+ getCursorPosition() {
159
+ // Modal doesn't have its own cursor, but children might
160
+ if (this.children.length > 0) {
161
+ const childCursor = this.children[0].getCursorPosition?.();
162
+ if (childCursor) {
163
+ // Adjust cursor position for modal frame and centering
164
+ const [childRow, childCol] = childCursor;
165
+ const modalWidth = Math.min(this.maxWidth, 80 - 4);
166
+ const horizontalOffset = Math.floor((80 - modalWidth) / 2);
167
+ // Top padding + title + separator + content offset
168
+ const { columns } = getTerminalSize();
169
+ const terminalHeight = columns;
170
+ const modalHeight = Math.min(this.maxHeight, terminalHeight - 4);
171
+ const topPadding = Math.max(0, Math.floor((terminalHeight - modalHeight) / 2));
172
+ return [
173
+ topPadding + 3 + childRow, // 3 = top border + title + separator
174
+ horizontalOffset + 2 + childCol, // 2 = left border + padding
175
+ ];
176
+ }
177
+ }
178
+ return null;
179
+ }
180
+ }
181
+ /**
182
+ * ModalText component - displays text content in a modal with word wrapping
183
+ */
184
+ export class ModalText extends Container {
185
+ text;
186
+ paddingX;
187
+ paddingY;
188
+ constructor(text, paddingX = 1, paddingY = 0) {
189
+ super();
190
+ this.text = text;
191
+ this.paddingX = paddingX;
192
+ this.paddingY = paddingY;
193
+ }
194
+ render(width) {
195
+ const lines = [];
196
+ const contentWidth = Math.max(1, width - this.paddingX * 2);
197
+ if (!this.text || this.text.trim() === "") {
198
+ return [];
199
+ }
200
+ // Replace tabs with spaces
201
+ const normalizedText = this.text.replace(/\t/g, " ");
202
+ const textLines = normalizedText.split("\n");
203
+ for (const line of textLines) {
204
+ const visibleLineLength = visibleWidth(line);
205
+ if (visibleLineLength <= contentWidth) {
206
+ lines.push(line);
207
+ }
208
+ 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
+ }
242
+ }
243
+ }
244
+ // Add padding
245
+ const leftPad = " ".repeat(this.paddingX);
246
+ const paddedLines = [];
247
+ // Top padding
248
+ for (let i = 0; i < this.paddingY; i++) {
249
+ paddedLines.push("");
250
+ }
251
+ // Content with horizontal padding
252
+ for (const line of lines) {
253
+ const visibleLength = visibleWidth(line);
254
+ const rightPadLength = Math.max(0, width - this.paddingX - visibleLength);
255
+ const rightPad = " ".repeat(rightPadLength);
256
+ paddedLines.push(leftPad + line + rightPad);
257
+ }
258
+ // Bottom padding
259
+ for (let i = 0; i < this.paddingY; i++) {
260
+ paddedLines.push("");
261
+ }
262
+ return paddedLines;
263
+ }
264
+ }
265
+ /**
266
+ * ModalTable component - displays tabular data in a modal
267
+ * Uses the terminal table function for proper text wrapping and formatting
268
+ */
269
+ export class ModalTable extends Container {
270
+ data;
271
+ headers;
272
+ colWidths;
273
+ constructor(data, headers, colWidths) {
274
+ super();
275
+ this.data = data;
276
+ this.headers = headers;
277
+ this.colWidths = colWidths;
278
+ }
279
+ render(width) {
280
+ if (this.data.length === 0) {
281
+ return [];
282
+ }
283
+ // Use the terminal table function for proper text wrapping and formatting
284
+ const tableString = table(this.data, {
285
+ header: this.headers,
286
+ colWidths: this.colWidths,
287
+ width: width,
288
+ });
289
+ // Split the table string into lines and return
290
+ return tableString.split("\n");
291
+ }
292
+ }
@@ -0,0 +1,16 @@
1
+ import type { ModelManager } from "../../models/manager.ts";
2
+ import type { Component } from "../index.ts";
3
+ type State = {
4
+ projectStatus: string;
5
+ currentContextWindow: number;
6
+ contextWindow: number;
7
+ };
8
+ export declare class PromptStatusComponent implements Component {
9
+ private modelManager;
10
+ private state;
11
+ constructor(modelManager: ModelManager, state: State);
12
+ setState(state: State): void;
13
+ render(width: number): string[];
14
+ }
15
+ export {};
16
+ //# sourceMappingURL=prompt-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-status.d.ts","sourceRoot":"","sources":["../../../source/tui/components/prompt-status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAG5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,KAAK,KAAK,GAAG;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,qBAAa,qBAAsB,YAAW,SAAS;IACrD,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,KAAK,CAAQ;gBACT,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK;IAKpD,QAAQ,CAAC,KAAK,EAAE,KAAK;IAIrB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAkBhC"}
@@ -0,0 +1,21 @@
1
+ import { displayProgressBar } from "../../terminal/index.js";
2
+ import style from "../../terminal/style.js";
3
+ export class PromptStatusComponent {
4
+ modelManager;
5
+ state;
6
+ constructor(modelManager, state) {
7
+ this.modelManager = modelManager;
8
+ this.state = state;
9
+ }
10
+ setState(state) {
11
+ this.state = state;
12
+ }
13
+ render(width) {
14
+ const results = [];
15
+ // results.push(style.dim(hr(width)));
16
+ results.push(this.state.projectStatus);
17
+ results.push(style.dim(`${this.modelManager.getModelMetadata("repl").id} [${this.modelManager.getModel("repl").modelId}]`));
18
+ results.push(displayProgressBar(this.state.currentContextWindow, this.state.contextWindow, width));
19
+ return results;
20
+ }
21
+ }
@@ -0,0 +1,22 @@
1
+ import type { Component } from "../tui.ts";
2
+ export interface SelectItem {
3
+ value: string;
4
+ label: string;
5
+ description?: string;
6
+ }
7
+ export declare class SelectList implements Component {
8
+ private items;
9
+ private filteredItems;
10
+ private selectedIndex;
11
+ private maxVisible;
12
+ onSelect?: (item: SelectItem) => void;
13
+ onCancel?: () => void;
14
+ constructor(items: SelectItem[], maxVisible?: number);
15
+ updateItems(items: SelectItem[]): void;
16
+ setFilter(filter: string): void;
17
+ setSelectedIndex(index: number): void;
18
+ render(width: number): string[];
19
+ handleInput(keyData: string): void;
20
+ getSelectedItem(): SelectItem | null;
21
+ }
22
+ //# sourceMappingURL=select-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-list.d.ts","sourceRoot":"","sources":["../../../source/tui/components/select-list.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;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;IAEhB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;gBAEjB,KAAK,EAAE,UAAU,EAAE,EAAE,UAAU,SAAI;IAM/C,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE;IAK/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;IA8G/B,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IA2BlC,eAAe,IAAI,UAAU,GAAG,IAAI;CAIrC"}
@@ -0,0 +1,143 @@
1
+ import style from "../../terminal/style.js";
2
+ export class SelectList {
3
+ items = [];
4
+ filteredItems = [];
5
+ selectedIndex = 0;
6
+ maxVisible = 5;
7
+ onSelect;
8
+ onCancel;
9
+ constructor(items, maxVisible = 5) {
10
+ this.items = items;
11
+ this.filteredItems = items;
12
+ this.maxVisible = maxVisible;
13
+ }
14
+ updateItems(items) {
15
+ this.items = items;
16
+ this.filteredItems = items;
17
+ }
18
+ setFilter(filter) {
19
+ this.filteredItems = this.items.filter((item) => item.value.toLowerCase().startsWith(filter.toLowerCase()));
20
+ // Reset selection when filter changes
21
+ this.selectedIndex = 0;
22
+ }
23
+ setSelectedIndex(index) {
24
+ this.selectedIndex = Math.max(0, Math.min(index, this.filteredItems.length - 1));
25
+ }
26
+ render(width) {
27
+ const lines = [];
28
+ // If no items match filter, show message
29
+ if (this.filteredItems.length === 0) {
30
+ lines.push(style.gray(" No matching commands"));
31
+ return lines;
32
+ }
33
+ // Calculate visible range with scrolling
34
+ const startIndex = Math.max(0, Math.min(this.selectedIndex - Math.floor(this.maxVisible / 2), this.filteredItems.length - this.maxVisible));
35
+ const endIndex = Math.min(startIndex + this.maxVisible, this.filteredItems.length);
36
+ // Render visible items
37
+ for (let i = startIndex; i < endIndex; i++) {
38
+ const item = this.filteredItems[i];
39
+ if (!item)
40
+ continue;
41
+ const isSelected = i === this.selectedIndex;
42
+ let line = "";
43
+ if (isSelected) {
44
+ // Use arrow indicator for selection
45
+ const prefix = style.blue("→ ");
46
+ const prefixWidth = 2; // "→ " is 2 characters visually
47
+ const displayValue = item.label || item.value;
48
+ if (item.description && width > 40) {
49
+ // Calculate how much space we have for value + description
50
+ const maxValueLength = Math.min(displayValue.length, 30);
51
+ const truncatedValue = displayValue.substring(0, maxValueLength);
52
+ const spacing = " ".repeat(Math.max(1, 32 - truncatedValue.length));
53
+ // Calculate remaining space for description using visible widths
54
+ const descriptionStart = prefixWidth + truncatedValue.length + spacing.length;
55
+ const remainingWidth = width - descriptionStart - 2; // -2 for safety
56
+ if (remainingWidth > 10) {
57
+ const truncatedDesc = item.description.substring(0, remainingWidth);
58
+ line =
59
+ prefix +
60
+ style.blue(truncatedValue) +
61
+ style.gray(spacing + truncatedDesc);
62
+ }
63
+ else {
64
+ // Not enough space for description
65
+ const maxWidth = width - prefixWidth - 2;
66
+ line = prefix + style.blue(displayValue.substring(0, maxWidth));
67
+ }
68
+ }
69
+ else {
70
+ // No description or not enough width
71
+ const maxWidth = width - prefixWidth - 2;
72
+ line = prefix + style.blue(displayValue.substring(0, maxWidth));
73
+ }
74
+ }
75
+ else {
76
+ const displayValue = item.label || item.value;
77
+ const prefix = " ";
78
+ if (item.description && width > 40) {
79
+ // Calculate how much space we have for value + description
80
+ const maxValueLength = Math.min(displayValue.length, 30);
81
+ const truncatedValue = displayValue.substring(0, maxValueLength);
82
+ const spacing = " ".repeat(Math.max(1, 32 - truncatedValue.length));
83
+ // Calculate remaining space for description
84
+ const descriptionStart = prefix.length + truncatedValue.length + spacing.length;
85
+ const remainingWidth = width - descriptionStart - 2; // -2 for safety
86
+ if (remainingWidth > 10) {
87
+ const truncatedDesc = item.description.substring(0, remainingWidth);
88
+ line =
89
+ prefix + truncatedValue + style.gray(spacing + truncatedDesc);
90
+ }
91
+ else {
92
+ // Not enough space for description
93
+ const maxWidth = width - prefix.length - 2;
94
+ line = prefix + displayValue.substring(0, maxWidth);
95
+ }
96
+ }
97
+ else {
98
+ // No description or not enough width
99
+ const maxWidth = width - prefix.length - 2;
100
+ line = prefix + displayValue.substring(0, maxWidth);
101
+ }
102
+ }
103
+ lines.push(line);
104
+ }
105
+ // Add scroll indicators if needed
106
+ if (startIndex > 0 || endIndex < this.filteredItems.length) {
107
+ const scrollText = ` (${this.selectedIndex + 1}/${this.filteredItems.length})`;
108
+ // Truncate if too long for terminal
109
+ const maxWidth = width - 2;
110
+ const truncated = scrollText.substring(0, maxWidth);
111
+ const scrollInfo = style.gray(truncated);
112
+ lines.push(scrollInfo);
113
+ }
114
+ return lines;
115
+ }
116
+ handleInput(keyData) {
117
+ // Up arrow
118
+ if (keyData === "\x1b[A") {
119
+ this.selectedIndex = Math.max(0, this.selectedIndex - 1);
120
+ }
121
+ // Down arrow or Tab
122
+ else if (keyData === "\x1b[B" || keyData === "\t") {
123
+ this.selectedIndex = Math.min(this.filteredItems.length - 1, this.selectedIndex + 1);
124
+ }
125
+ // Enter
126
+ else if (keyData === "\r") {
127
+ const selectedItem = this.filteredItems[this.selectedIndex];
128
+ if (selectedItem && this.onSelect) {
129
+ this.onSelect(selectedItem);
130
+ }
131
+ }
132
+ // Escape or Ctrl+C
133
+ else if (keyData === "\x1b" || keyData === "\x03") {
134
+ if (this.onCancel) {
135
+ this.onCancel();
136
+ }
137
+ }
138
+ }
139
+ getSelectedItem() {
140
+ const item = this.filteredItems[this.selectedIndex];
141
+ return item || null;
142
+ }
143
+ }
@@ -0,0 +1,16 @@
1
+ import type { Component } from "../tui.ts";
2
+ /**
3
+ * Spacer component that renders empty lines
4
+ */
5
+ export declare class Spacer implements Component {
6
+ private lines;
7
+ private customBgRgb?;
8
+ constructor(lines?: number, customBgRgb?: {
9
+ r: number;
10
+ g: number;
11
+ b: number;
12
+ });
13
+ setLines(lines: number): void;
14
+ render(_width: number): string[];
15
+ }
16
+ //# sourceMappingURL=spacer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spacer.d.ts","sourceRoot":"","sources":["../../../source/tui/components/spacer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C;;GAEG;AACH,qBAAa,MAAO,YAAW,SAAS;IACtC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,WAAW,CAAC,CAAsC;gBAE9C,KAAK,SAAI,EAAE,WAAW,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE;IAKxE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7B,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;CAgBjC"}
@@ -0,0 +1,27 @@
1
+ import style from "../../terminal/style.js";
2
+ /**
3
+ * Spacer component that renders empty lines
4
+ */
5
+ export class Spacer {
6
+ lines;
7
+ customBgRgb;
8
+ constructor(lines = 1, customBgRgb) {
9
+ this.lines = lines;
10
+ this.customBgRgb = customBgRgb;
11
+ }
12
+ setLines(lines) {
13
+ this.lines = lines;
14
+ }
15
+ render(_width) {
16
+ const result = [];
17
+ for (let i = 0; i < this.lines; i++) {
18
+ let line = "";
19
+ // Apply background color if specified
20
+ if (this.customBgRgb) {
21
+ line = style.bgRgb(this.customBgRgb.r, this.customBgRgb.g, this.customBgRgb.b)(line);
22
+ }
23
+ result.push(line);
24
+ }
25
+ return result;
26
+ }
27
+ }
@@ -0,0 +1,26 @@
1
+ import type { Component } from "../tui.ts";
2
+ /**
3
+ * Text component - displays multi-line text with word wrapping
4
+ */
5
+ export declare class Text implements Component {
6
+ private text;
7
+ private paddingX;
8
+ private paddingY;
9
+ private customBgRgb?;
10
+ private cachedText?;
11
+ private cachedWidth?;
12
+ private cachedLines?;
13
+ constructor(text?: string, paddingX?: number, paddingY?: number, customBgRgb?: {
14
+ r: number;
15
+ g: number;
16
+ b: number;
17
+ });
18
+ setText(text: string): void;
19
+ setCustomBgRgb(customBgRgb?: {
20
+ r: number;
21
+ g: number;
22
+ b: number;
23
+ }): void;
24
+ render(width: number): string[];
25
+ }
26
+ //# sourceMappingURL=text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../source/tui/components/text.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3C;;GAEG;AACH,qBAAa,IAAK,YAAW,SAAS;IACpC,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAAC,CAAsC;IAG1D,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAC,CAAW;gBAG7B,IAAI,SAAK,EACT,QAAQ,SAAI,EACZ,QAAQ,SAAI,EACZ,WAAW,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE;IAQnD,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQ3B,cAAc,CAAC,WAAW,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAQvE,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CA4IhC"}