@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,143 @@
1
+ import style from "../../terminal/style.js";
2
+ import { visibleWidth } from "../utils.js";
3
+ /**
4
+ * Text component - displays multi-line text with word wrapping
5
+ */
6
+ export class Text {
7
+ text;
8
+ paddingX; // Left/right padding
9
+ paddingY; // Top/bottom padding
10
+ customBgRgb;
11
+ // Cache for rendered output
12
+ cachedText;
13
+ cachedWidth;
14
+ cachedLines;
15
+ constructor(text = "", paddingX = 1, paddingY = 1, customBgRgb) {
16
+ this.text = text;
17
+ this.paddingX = paddingX;
18
+ this.paddingY = paddingY;
19
+ this.customBgRgb = customBgRgb;
20
+ }
21
+ setText(text) {
22
+ this.text = text;
23
+ // Invalidate cache when text changes
24
+ this.cachedText = undefined;
25
+ this.cachedWidth = undefined;
26
+ this.cachedLines = undefined;
27
+ }
28
+ setCustomBgRgb(customBgRgb) {
29
+ this.customBgRgb = customBgRgb;
30
+ // Invalidate cache when color changes
31
+ this.cachedText = undefined;
32
+ this.cachedWidth = undefined;
33
+ this.cachedLines = undefined;
34
+ }
35
+ render(width) {
36
+ // Check cache
37
+ if (this.cachedLines &&
38
+ this.cachedText === this.text &&
39
+ this.cachedWidth === width) {
40
+ return this.cachedLines;
41
+ }
42
+ // Calculate available width for content (subtract horizontal padding)
43
+ const contentWidth = Math.max(1, width - this.paddingX * 2);
44
+ // Don't render anything if there's no actual text
45
+ if (!this.text || this.text.trim() === "") {
46
+ const result = [];
47
+ // Update cache
48
+ this.cachedText = this.text;
49
+ this.cachedWidth = width;
50
+ this.cachedLines = result;
51
+ return result;
52
+ }
53
+ // Replace tabs with 3 spaces for consistent rendering
54
+ const normalizedText = this.text.replace(/\t/g, " ");
55
+ const lines = [];
56
+ const textLines = normalizedText.split("\n");
57
+ for (const line of textLines) {
58
+ // Measure visible length (strip ANSI codes)
59
+ const visibleLineLength = visibleWidth(line);
60
+ if (visibleLineLength <= contentWidth) {
61
+ lines.push(line);
62
+ }
63
+ else {
64
+ // Word wrap
65
+ const words = line.split(" ");
66
+ let currentLine = "";
67
+ for (const word of words) {
68
+ const currentVisible = visibleWidth(currentLine);
69
+ const wordVisible = visibleWidth(word);
70
+ // If word is too long, truncate it
71
+ let finalWord = word;
72
+ if (wordVisible > contentWidth) {
73
+ // Truncate word to fit
74
+ let truncated = "";
75
+ for (const char of word) {
76
+ if (visibleWidth(truncated + char) > contentWidth) {
77
+ break;
78
+ }
79
+ truncated += char;
80
+ }
81
+ finalWord = truncated;
82
+ }
83
+ if (currentVisible === 0) {
84
+ currentLine = finalWord;
85
+ }
86
+ else if (currentVisible + 1 + visibleWidth(finalWord) <=
87
+ contentWidth) {
88
+ currentLine += ` ${finalWord}`;
89
+ }
90
+ else {
91
+ lines.push(currentLine);
92
+ currentLine = finalWord;
93
+ }
94
+ }
95
+ if (currentLine.length > 0) {
96
+ lines.push(currentLine);
97
+ }
98
+ }
99
+ }
100
+ // Add padding to each line
101
+ const leftPad = " ".repeat(this.paddingX);
102
+ const paddedLines = [];
103
+ for (const line of lines) {
104
+ // Calculate visible length (strip ANSI codes)
105
+ const visibleLength = visibleWidth(line);
106
+ // Right padding to fill to width (accounting for left padding and content)
107
+ const rightPadLength = Math.max(0, width - this.paddingX - visibleLength);
108
+ const rightPad = " ".repeat(rightPadLength);
109
+ let paddedLine = leftPad + line + rightPad;
110
+ // Apply background color if specified
111
+ if (this.customBgRgb) {
112
+ paddedLine = style.bgRgb(this.customBgRgb.r, this.customBgRgb.g, this.customBgRgb.b)(paddedLine);
113
+ }
114
+ paddedLines.push(paddedLine);
115
+ }
116
+ // Add top padding (empty lines)
117
+ const emptyLine = " ".repeat(width);
118
+ const topPadding = [];
119
+ for (let i = 0; i < this.paddingY; i++) {
120
+ let emptyPaddedLine = emptyLine;
121
+ if (this.customBgRgb) {
122
+ emptyPaddedLine = style.bgRgb(this.customBgRgb.r, this.customBgRgb.g, this.customBgRgb.b)(emptyPaddedLine);
123
+ }
124
+ topPadding.push(emptyPaddedLine);
125
+ }
126
+ // Add bottom padding (empty lines)
127
+ const bottomPadding = [];
128
+ for (let i = 0; i < this.paddingY; i++) {
129
+ let emptyPaddedLine = emptyLine;
130
+ if (this.customBgRgb) {
131
+ emptyPaddedLine = style.bgRgb(this.customBgRgb.r, this.customBgRgb.g, this.customBgRgb.b)(emptyPaddedLine);
132
+ }
133
+ bottomPadding.push(emptyPaddedLine);
134
+ }
135
+ // Combine top padding, content, and bottom padding
136
+ const result = [...topPadding, ...paddedLines, ...bottomPadding];
137
+ // Update cache
138
+ this.cachedText = this.text;
139
+ this.cachedWidth = width;
140
+ this.cachedLines = result;
141
+ return result.length > 0 ? result : [""];
142
+ }
143
+ }
@@ -0,0 +1,14 @@
1
+ import { Container } from "../tui.ts";
2
+ /**
3
+ * Component that renders a thinking block
4
+ */
5
+ export declare class ThinkingBlockComponent extends Container {
6
+ private contentContainer;
7
+ constructor(message?: {
8
+ content: string;
9
+ });
10
+ updateContent(message: {
11
+ content: string;
12
+ }): void;
13
+ }
14
+ //# sourceMappingURL=thinking-block.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thinking-block.d.ts","sourceRoot":"","sources":["../../../source/tui/components/thinking-block.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAItC;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,SAAS;IACnD,OAAO,CAAC,gBAAgB,CAAY;gBAExB,OAAO,CAAC,EAAE;QACpB,OAAO,EAAE,MAAM,CAAC;KACjB;IAYD,aAAa,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;CAsBlD"}
@@ -0,0 +1,30 @@
1
+ import style from "../../terminal/style.js";
2
+ import { Container } from "../tui.js";
3
+ import { Markdown } from "./markdown.js";
4
+ import { Spacer } from "./spacer.js";
5
+ /**
6
+ * Component that renders a thinking block
7
+ */
8
+ export class ThinkingBlockComponent extends Container {
9
+ contentContainer;
10
+ constructor(message) {
11
+ super();
12
+ // Container for text/thinking content
13
+ this.contentContainer = new Container();
14
+ this.addChild(this.contentContainer);
15
+ if (message) {
16
+ this.updateContent(message);
17
+ }
18
+ }
19
+ updateContent(message) {
20
+ // Clear content container
21
+ this.contentContainer.clear();
22
+ if (message.content.length > 0) {
23
+ this.contentContainer.addChild(new Spacer(1));
24
+ }
25
+ const content = message.content;
26
+ // Assistant text messages with no background - trim the text
27
+ // Set paddingY=0 to avoid extra spacing before tool executions
28
+ this.contentContainer.addChild(new Markdown(style.dim(content.trim()), undefined, undefined, undefined, 1, 0));
29
+ }
30
+ }
@@ -0,0 +1,17 @@
1
+ import type { ToolEvent } from "../../agent/index.ts";
2
+ import { Container } from "../index.ts";
3
+ export declare class ToolExecutionComponent extends Container {
4
+ private contentContainer;
5
+ private toolName;
6
+ private events;
7
+ constructor(event: ToolEvent);
8
+ update(event: ToolEvent): void;
9
+ private renderDisplay;
10
+ private getIndicator;
11
+ private handleToolInitMessage;
12
+ private handleToolUpdateMessage;
13
+ private handleToolCompletionMessage;
14
+ private handleToolErrorMessage;
15
+ private processEventsInOrder;
16
+ }
17
+ //# sourceMappingURL=tool-execution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-execution.d.ts","sourceRoot":"","sources":["../../../source/tui/components/tool-execution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,EAAE,SAAS,EAAgB,MAAM,aAAa,CAAC;AAItD,qBAAa,sBAAuB,SAAQ,SAAS;IACnD,OAAO,CAAC,gBAAgB,CAAY;IACpC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAc;gBAEhB,KAAK,EAAE,SAAS;IAY5B,MAAM,CAAC,KAAK,EAAE,SAAS;IAKvB,OAAO,CAAC,aAAa;IAwDrB,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,qBAAqB;IAU7B,OAAO,CAAC,uBAAuB;IAkB/B,OAAO,CAAC,2BAA2B;IAcnC,OAAO,CAAC,sBAAsB;IAI9B,OAAO,CAAC,oBAAoB;CA+C7B"}
@@ -0,0 +1,153 @@
1
+ import { capitalize } from "../../formatting.js";
2
+ import style from "../../terminal/style.js";
3
+ import { Container, Spacer, Text } from "../index.js";
4
+ export class ToolExecutionComponent extends Container {
5
+ contentContainer;
6
+ toolName;
7
+ events;
8
+ constructor(event) {
9
+ super();
10
+ this.toolName = event.name;
11
+ this.events = [event];
12
+ // Container for text/thinking content
13
+ this.contentContainer = new Container();
14
+ this.addChild(this.contentContainer);
15
+ this.renderDisplay();
16
+ }
17
+ update(event) {
18
+ this.events.push(event);
19
+ this.renderDisplay();
20
+ }
21
+ renderDisplay() {
22
+ // Clear content container
23
+ this.contentContainer.clear();
24
+ const lines = [];
25
+ // Build display from complete event history with proper ordering
26
+ const processedEvents = this.processEventsInOrder();
27
+ for (let i = 0; i < processedEvents.length; i++) {
28
+ const event = processedEvents[i];
29
+ const eventType = event.type;
30
+ switch (eventType) {
31
+ case "tool-call-start":
32
+ lines.push(`${this.handleToolInitMessage(event)}`);
33
+ break;
34
+ case "tool-call-update":
35
+ lines.push(`├── ${this.handleToolUpdateMessage(event.msg)}`);
36
+ break;
37
+ case "tool-call-end":
38
+ lines.push(`└── ${this.handleToolCompletionMessage(event.msg)}`);
39
+ break;
40
+ case "tool-call-error":
41
+ lines.push(`└── ${this.handleToolErrorMessage(event.msg)}`);
42
+ break;
43
+ default: {
44
+ eventType;
45
+ }
46
+ }
47
+ }
48
+ // Render all lines with proper indicators
49
+ const currentStatus = this.events[this.events.length - 1].type;
50
+ const indicator = this.getIndicator(currentStatus);
51
+ const displayLines = [];
52
+ for (let i = 0; i < lines.length; i++) {
53
+ let line = lines[i];
54
+ if (i === 0) {
55
+ line = `${indicator} ${line}`;
56
+ }
57
+ displayLines.push(line);
58
+ }
59
+ this.contentContainer.addChild(new Spacer(1));
60
+ this.contentContainer.addChild(new Text(displayLines.join("\n"), 1, 1, {
61
+ r: 52,
62
+ g: 53,
63
+ b: 65,
64
+ }));
65
+ }
66
+ getIndicator(status) {
67
+ switch (status) {
68
+ case "tool-call-start":
69
+ return style.blue.bold("●");
70
+ case "tool-call-update":
71
+ return style.yellow.bold("●");
72
+ case "tool-call-end":
73
+ return style.green.bold("●");
74
+ case "tool-call-error":
75
+ return style.red.bold("●");
76
+ default:
77
+ status;
78
+ }
79
+ return style.blue.bold("●");
80
+ }
81
+ handleToolInitMessage(event) {
82
+ const message = event.msg;
83
+ let result = `${style.bold(capitalize(this.toolName))} `;
84
+ result += message.trim() ? `${style.bold(message)} ` : "";
85
+ result += style.dim(JSON.stringify(event.args).slice(0, 50));
86
+ return result;
87
+ }
88
+ handleToolUpdateMessage(message) {
89
+ const newlineIndex = message.indexOf("\n");
90
+ let result = "";
91
+ if (newlineIndex === -1) {
92
+ result += style.bold(message);
93
+ }
94
+ else {
95
+ const firstLine = message.slice(0, newlineIndex);
96
+ // const remainingLines = message.slice(newlineIndex + 1);
97
+ result += style.bold(firstLine);
98
+ // if (remainingLines.trim()) {
99
+ // terminal.display(remainingLines);
100
+ // }
101
+ }
102
+ return result;
103
+ }
104
+ handleToolCompletionMessage(message) {
105
+ const newlineIndex = message.indexOf("\n");
106
+ let result = "";
107
+ if (newlineIndex === -1) {
108
+ result += style.bold(message);
109
+ }
110
+ else {
111
+ const firstLine = message.slice(0, newlineIndex);
112
+ result += style.bold(firstLine);
113
+ }
114
+ return result;
115
+ }
116
+ handleToolErrorMessage(message) {
117
+ return style.bold.red(message);
118
+ }
119
+ processEventsInOrder() {
120
+ const events = [...this.events];
121
+ const processed = [];
122
+ // Ensure we have a tool-call-start event
123
+ const hasStartEvent = events.some((event) => event.type === "tool-call-start");
124
+ if (!hasStartEvent && events.length > 0) {
125
+ // Create synthetic start event using the first event's name
126
+ const firstEvent = events[0];
127
+ processed.push({
128
+ type: "tool-call-start",
129
+ name: firstEvent.name,
130
+ toolCallId: firstEvent.toolCallId,
131
+ msg: "",
132
+ args: firstEvent.args,
133
+ });
134
+ }
135
+ // Process events in the correct order: start → update → end/error
136
+ const startEvents = events.filter((event) => event.type === "tool-call-start");
137
+ const updateEvents = events.filter((event) => event.type === "tool-call-update");
138
+ const endEvents = events.filter((event) => event.type === "tool-call-end");
139
+ const errorEvents = events.filter((event) => event.type === "tool-call-error");
140
+ // Add start events first
141
+ processed.push(...startEvents);
142
+ // Add update events
143
+ processed.push(...updateEvents);
144
+ // Add end or error events (only one should be present)
145
+ if (endEvents.length > 0) {
146
+ processed.push(...endEvents);
147
+ }
148
+ else if (errorEvents.length > 0) {
149
+ processed.push(...errorEvents);
150
+ }
151
+ return processed;
152
+ }
153
+ }
@@ -0,0 +1,9 @@
1
+ import { Container } from "../tui.ts";
2
+ /**
3
+ * Component that renders a user message
4
+ */
5
+ export declare class UserMessageComponent extends Container {
6
+ private markdown;
7
+ constructor(text: string);
8
+ }
9
+ //# sourceMappingURL=user-message.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-message.d.ts","sourceRoot":"","sources":["../../../source/tui/components/user-message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAItC;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;IACjD,OAAO,CAAC,QAAQ,CAAW;gBAEf,IAAI,EAAE,MAAM;CAezB"}
@@ -0,0 +1,21 @@
1
+ import { Container } from "../tui.js";
2
+ import { Markdown } from "./markdown.js";
3
+ import { Spacer } from "./spacer.js";
4
+ /**
5
+ * Component that renders a user message
6
+ */
7
+ export class UserMessageComponent extends Container {
8
+ markdown;
9
+ constructor(text) {
10
+ super();
11
+ this.addChild(new Spacer(1));
12
+ // User messages with dark gray background
13
+ this.markdown = new Markdown(text, undefined, undefined, {
14
+ r: 52,
15
+ g: 53,
16
+ b: 65,
17
+ });
18
+ this.addChild(this.markdown);
19
+ this.addChild(new Spacer(1));
20
+ }
21
+ }
@@ -0,0 +1,6 @@
1
+ import type { Component } from "../tui.ts";
2
+ export declare class Welcome implements Component {
3
+ render(_width: number): string[];
4
+ private getLogo;
5
+ }
6
+ //# sourceMappingURL=welcome.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"welcome.d.ts","sourceRoot":"","sources":["../../../source/tui/components/welcome.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C,qBAAa,OAAQ,YAAW,SAAS;IACvC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAiChC,OAAO,CAAC,OAAO;CAUhB"}
@@ -0,0 +1,30 @@
1
+ import style from "../../terminal/style.js";
2
+ import { getPackageVersion } from "../../version.js";
3
+ export class Welcome {
4
+ render(_width) {
5
+ const version = getPackageVersion();
6
+ const result = [];
7
+ result.push(style.magenta(this.getLogo()));
8
+ result.push("");
9
+ result.push(style.magenta("Greetings! I am acai."));
10
+ result.push(style.gray(` Version ${version}`));
11
+ result.push("");
12
+ result.push(style.white(` Type ${style.cyan("/help")} to see available commands.`));
13
+ result.push(style.white(" You can ask acai to explain code, fix issues, or perform tasks."));
14
+ result.push(style.white(` Example: "${style.italic("Please analyze this codebase and explain its structure.")}"`));
15
+ result.push(style.dim(" Use Ctrl+C to interrupt acai and exit."));
16
+ result.push("");
17
+ result.push(style.yellow(`The current working directory is ${process.cwd()}`));
18
+ return result;
19
+ }
20
+ getLogo() {
21
+ return `
22
+ █████╗ ██████╗ █████╗ ██╗
23
+ ██╔══██╗██╔════╝██╔══██╗██║
24
+ ███████║██║ ███████║██║
25
+ ██╔══██║██║ ██╔══██║██║
26
+ ██║ ██║╚██████╗██║ ██║██║
27
+ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝
28
+ `;
29
+ }
30
+ }
@@ -0,0 +1,14 @@
1
+ export { type AutocompleteItem, type AutocompleteProvider, CombinedAutocompleteProvider, type SlashCommand, } from "./autocomplete.ts";
2
+ export { Editor, type TextEditorConfig } from "./components/editor.ts";
3
+ export { Input } from "./components/input.ts";
4
+ export { Loader } from "./components/loader.ts";
5
+ export { Markdown } from "./components/markdown.ts";
6
+ export { Modal, ModalTable, ModalText } from "./components/modal.ts";
7
+ export { type SelectItem, SelectList } from "./components/select-list.ts";
8
+ export { Spacer } from "./components/spacer.ts";
9
+ export { Text } from "./components/text.ts";
10
+ export { UserMessageComponent } from "./components/user-message.ts";
11
+ export { ProcessTerminal, type Terminal } from "./terminal.ts";
12
+ export { type Component, Container, TUI } from "./tui.ts";
13
+ export { visibleWidth } from "./utils.ts";
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/tui/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,4BAA4B,EAC5B,KAAK,YAAY,GAClB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,MAAM,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,KAAK,UAAU,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEpE,OAAO,EAAE,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE1D,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,18 @@
1
+ // Core TUI interfaces and classes
2
+ // Autocomplete support
3
+ export { CombinedAutocompleteProvider, } from "./autocomplete.js";
4
+ // Components
5
+ export { Editor } from "./components/editor.js";
6
+ export { Input } from "./components/input.js";
7
+ export { Loader } from "./components/loader.js";
8
+ export { Markdown } from "./components/markdown.js";
9
+ export { Modal, ModalTable, ModalText } from "./components/modal.js";
10
+ export { SelectList } from "./components/select-list.js";
11
+ export { Spacer } from "./components/spacer.js";
12
+ export { Text } from "./components/text.js";
13
+ export { UserMessageComponent } from "./components/user-message.js";
14
+ // Terminal interface and implementations
15
+ export { ProcessTerminal } from "./terminal.js";
16
+ export { Container, TUI } from "./tui.js";
17
+ // Utilities
18
+ export { visibleWidth } from "./utils.js";
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Minimal terminal interface for TUI
3
+ */
4
+ export interface Terminal {
5
+ start(onInput: (data: string) => void, onResize: () => void): void;
6
+ stop(): void;
7
+ write(data: string): void;
8
+ get columns(): number;
9
+ get rows(): number;
10
+ moveBy(lines: number): void;
11
+ hideCursor(): void;
12
+ showCursor(): void;
13
+ clearLine(): void;
14
+ clearFromCursor(): void;
15
+ clearScreen(): void;
16
+ }
17
+ /**
18
+ * Real terminal using process.stdin/stdout
19
+ */
20
+ export declare class ProcessTerminal implements Terminal {
21
+ private wasRaw;
22
+ private inputHandler?;
23
+ private resizeHandler?;
24
+ private rl?;
25
+ start(onInput: (data: string) => void, onResize: () => void): void;
26
+ stop(): void;
27
+ write(data: string): void;
28
+ get columns(): number;
29
+ get rows(): number;
30
+ moveBy(lines: number): void;
31
+ hideCursor(): void;
32
+ showCursor(): void;
33
+ clearLine(): void;
34
+ clearFromCursor(): void;
35
+ clearScreen(): void;
36
+ }
37
+ //# sourceMappingURL=terminal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../source/tui/terminal.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,QAAQ;IAEvB,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAGnE,IAAI,IAAI,IAAI,CAAC;IAGb,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAG1B,IAAI,OAAO,IAAI,MAAM,CAAC;IACtB,IAAI,IAAI,IAAI,MAAM,CAAC;IAGnB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAG5B,UAAU,IAAI,IAAI,CAAC;IACnB,UAAU,IAAI,IAAI,CAAC;IAGnB,SAAS,IAAI,IAAI,CAAC;IAClB,eAAe,IAAI,IAAI,CAAC;IACxB,WAAW,IAAI,IAAI,CAAC;CACrB;AAID;;GAEG;AACH,qBAAa,eAAgB,YAAW,QAAQ;IAC9C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAC,CAAyB;IAC9C,OAAO,CAAC,aAAa,CAAC,CAAa;IACnC,OAAO,CAAC,EAAE,CAAC,CAAqB;IAEhC,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IA2ClE,IAAI,IAAI,IAAI;IA0BZ,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIzB,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAW3B,UAAU,IAAI,IAAI;IAIlB,UAAU,IAAI,IAAI;IAIlB,SAAS,IAAI,IAAI;IAIjB,eAAe,IAAI,IAAI;IAIvB,WAAW,IAAI,IAAI;CAGpB"}
@@ -0,0 +1,104 @@
1
+ import readline from "node:readline";
2
+ /**
3
+ * Real terminal using process.stdin/stdout
4
+ */
5
+ export class ProcessTerminal {
6
+ wasRaw = false;
7
+ inputHandler;
8
+ resizeHandler;
9
+ rl;
10
+ start(onInput, onResize) {
11
+ this.inputHandler = onInput;
12
+ this.resizeHandler = onResize;
13
+ // Save previous state
14
+ this.wasRaw = process.stdin.isRaw || false;
15
+ // Check if we're in a TTY environment
16
+ const isTty = process.stdin.isTTY && process.stdout.isTTY;
17
+ if (isTty) {
18
+ // Create readline interface for reliable input handling
19
+ this.rl = readline.createInterface({
20
+ input: process.stdin,
21
+ output: process.stdout,
22
+ terminal: true,
23
+ });
24
+ // Enable raw mode for character-by-character input
25
+ if (process.stdin.setRawMode) {
26
+ process.stdin.setRawMode(true);
27
+ }
28
+ process.stdin.setEncoding("utf8");
29
+ process.stdin.resume();
30
+ // Enable bracketed paste mode - terminal will wrap pastes in \x1b[200~ ... \x1b[201~
31
+ process.stdout.write("\x1b[?2004h");
32
+ // Set up input handler
33
+ process.stdin.on("data", this.inputHandler);
34
+ process.stdout.on("resize", this.resizeHandler);
35
+ }
36
+ else {
37
+ console.warn("Not running in a TTY environment - input will not work");
38
+ // In non-TTY environments, we can't use raw mode
39
+ // But we can still set up basic input handling if needed
40
+ process.stdin.setEncoding("utf8");
41
+ if (process.stdin.isPaused()) {
42
+ process.stdin.resume();
43
+ }
44
+ process.stdin.on("data", this.inputHandler);
45
+ }
46
+ }
47
+ stop() {
48
+ // Disable bracketed paste mode
49
+ process.stdout.write("\x1b[?2004l");
50
+ // Remove event handlers
51
+ if (this.inputHandler) {
52
+ process.stdin.removeListener("data", this.inputHandler);
53
+ this.inputHandler = undefined;
54
+ }
55
+ if (this.resizeHandler) {
56
+ process.stdout.removeListener("resize", this.resizeHandler);
57
+ this.resizeHandler = undefined;
58
+ }
59
+ // Close readline interface
60
+ if (this.rl) {
61
+ this.rl.close();
62
+ this.rl = undefined;
63
+ }
64
+ // Restore raw mode state
65
+ if (process.stdin.setRawMode) {
66
+ process.stdin.setRawMode(this.wasRaw);
67
+ }
68
+ }
69
+ write(data) {
70
+ process.stdout.write(data);
71
+ }
72
+ get columns() {
73
+ return process.stdout.columns || 80;
74
+ }
75
+ get rows() {
76
+ return process.stdout.rows || 24;
77
+ }
78
+ moveBy(lines) {
79
+ if (lines > 0) {
80
+ // Move down
81
+ process.stdout.write(`\x1b[${lines}B`);
82
+ }
83
+ else if (lines < 0) {
84
+ // Move up
85
+ process.stdout.write(`\x1b[${-lines}A`);
86
+ }
87
+ // lines === 0: no movement
88
+ }
89
+ hideCursor() {
90
+ process.stdout.write("\x1b[?25l");
91
+ }
92
+ showCursor() {
93
+ process.stdout.write("\x1b[?25h");
94
+ }
95
+ clearLine() {
96
+ process.stdout.write("\x1b[K");
97
+ }
98
+ clearFromCursor() {
99
+ process.stdout.write("\x1b[J");
100
+ }
101
+ clearScreen() {
102
+ process.stdout.write("\x1b[2J\x1b[H"); // Clear screen and move to home (1,1)
103
+ }
104
+ }