@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
package/dist/repl.js CHANGED
@@ -1,15 +1,14 @@
1
- import { isNumber, isRecord } from "@travisennis/stdlib/typeguards";
2
- import { stepCountIs, streamText } from "ai";
1
+ import { isRecord } from "@travisennis/stdlib/typeguards";
2
+ import { runManualLoop } from "./agent/manual-loop.js";
3
3
  import { config as configManager } from "./config.js";
4
+ import { formatDuration } from "./formatting.js";
4
5
  import { logger } from "./logger.js";
5
6
  import { PromptError, processPrompt } from "./mentions.js";
6
- import { AiConfig } from "./models/ai-config.js";
7
7
  import { systemPrompt } from "./prompts.js";
8
- import { displayToolMessages } from "./repl/display-tool-messages.js";
9
8
  import { displayToolUse } from "./repl/display-tool-use.js";
10
9
  import { getPromptHeader } from "./repl/get-prompt-header.js";
10
+ import { ReplPrompt } from "./repl/prompt.js";
11
11
  import { toolCallRepair } from "./repl/tool-call-repair.js";
12
- import { ReplPrompt } from "./repl-prompt.js";
13
12
  import style from "./terminal/style.js";
14
13
  import { initAgents, initTools } from "./tools/index.js";
15
14
  export class Repl {
@@ -20,29 +19,34 @@ export class Repl {
20
19
  this.showLastMessage = options.showLastMessage;
21
20
  }
22
21
  async run() {
23
- const { config, promptManager, terminal, modelManager, tokenTracker, messageHistory, commands, tokenCounter, toolEvents, toolExecutor, promptHistory, } = this.options;
22
+ const { config, promptManager, terminal, modelManager, tokenTracker, messageHistory, commands, tokenCounter, promptHistory, } = this.options;
24
23
  logger.info(config, "Config:");
25
24
  terminal.displayWelcome();
26
25
  let currentContextWindow = 0;
27
26
  messageHistory.on("clear-history", () => {
28
27
  currentContextWindow = 0;
29
28
  });
30
- const finalSystemPrompt = await systemPrompt();
31
29
  // Initialize tools once outside the loop - all models support tool calling
30
+ const coreTools = await initTools({
31
+ tokenCounter,
32
+ workspace: this.options.workspace,
33
+ modelManager,
34
+ tokenTracker,
35
+ });
36
+ const agentTools = await initAgents({
37
+ terminal,
38
+ modelManager,
39
+ tokenTracker,
40
+ tokenCounter,
41
+ workspace: this.options.workspace,
42
+ });
43
+ const completeToolDefs = {
44
+ ...coreTools.toolDefs,
45
+ ...agentTools.toolDefs,
46
+ };
32
47
  const tools = {
33
- ...(await initTools({
34
- terminal,
35
- tokenCounter,
36
- events: toolEvents,
37
- toolExecutor,
38
- })),
39
- ...(await initAgents({
40
- terminal,
41
- modelManager,
42
- tokenTracker,
43
- tokenCounter,
44
- events: toolEvents,
45
- })),
48
+ toolDefs: completeToolDefs,
49
+ executors: new Map([...coreTools.executors, ...agentTools.executors]),
46
50
  };
47
51
  let currentAbortController = null;
48
52
  // Handle Ctrl+C (SIGINT) as a fallback when not in raw mode
@@ -61,6 +65,7 @@ export class Repl {
61
65
  contextWindow: modelConfig.contextWindow,
62
66
  currentContextWindow,
63
67
  });
68
+ const projectConfig = await configManager.readProjectConfig();
64
69
  // Display last message when continuing/resuming a conversation
65
70
  if (this.showLastMessage) {
66
71
  const lastMessage = messageHistory.getLastMessage();
@@ -76,9 +81,15 @@ export class Repl {
76
81
  }
77
82
  if (!promptManager.isPending()) {
78
83
  // For interactive input
79
- const prompt = new ReplPrompt({ commands, history: promptHistory });
84
+ const prompt = new ReplPrompt({
85
+ commands,
86
+ history: promptHistory,
87
+ workspace: this.options.workspace,
88
+ });
80
89
  const userInput = await prompt.input();
90
+ const pasteStore = prompt.getPasteStore();
81
91
  prompt.close();
92
+ prompt.resetPasteStore();
82
93
  terminal.startProgress();
83
94
  // see if the userInput contains a command
84
95
  const commandResult = await commands.handle({ userInput });
@@ -101,6 +112,7 @@ export class Repl {
101
112
  const processedPrompt = await processPrompt(userInput, {
102
113
  baseDir: process.cwd(),
103
114
  model: modelConfig,
115
+ pasteStore,
104
116
  });
105
117
  for (const context of processedPrompt.context) {
106
118
  promptManager.addContext(context);
@@ -123,11 +135,15 @@ export class Repl {
123
135
  throw error; // Re-throw other errors
124
136
  }
125
137
  }
138
+ else {
139
+ promptHistory.push(promptManager.get());
140
+ }
126
141
  terminal.lineBreak();
127
142
  }
128
143
  else {
129
144
  terminal.startProgress();
130
145
  }
146
+ const start = performance.now();
131
147
  // flag to see if the user prompt has added context
132
148
  const hasAddedContext = promptManager.hasContext();
133
149
  if (hasAddedContext) {
@@ -138,155 +154,47 @@ export class Repl {
138
154
  const userPrompt = promptManager.get();
139
155
  const userMsg = promptManager.getUserMessage();
140
156
  messageHistory.appendUserMessage(userMsg);
141
- const aiConfig = new AiConfig({
142
- modelMetadata: modelConfig,
143
- prompt: userPrompt,
144
- });
145
- const maxTokens = aiConfig.getMaxTokens();
157
+ const finalSystemPrompt = await systemPrompt();
146
158
  try {
147
- const result = streamText({
148
- model: langModel,
149
- maxOutputTokens: maxTokens,
150
- messages: [
151
- {
152
- role: "system",
153
- content: finalSystemPrompt,
154
- providerOptions: {
155
- anthropic: { cacheControl: { type: "ephemeral" } },
156
- },
157
- },
158
- ...messageHistory.get(),
159
- ],
160
- temperature: modelConfig.defaultTemperature > -1
161
- ? modelConfig.defaultTemperature
162
- : undefined,
163
- stopWhen: stepCountIs(90),
164
- maxRetries: 2,
165
- providerOptions: aiConfig.getProviderOptions(),
166
- tools,
167
- // biome-ignore lint/style/useNamingConvention: third-party controlled
168
- experimental_repairToolCall: toolCallRepair(modelManager),
159
+ const { toolDefs, executors } = tools;
160
+ const result = await runManualLoop({
161
+ modelManager,
162
+ terminal,
163
+ messageHistory,
164
+ systemPrompt: finalSystemPrompt,
165
+ input: userPrompt,
166
+ toolDefs,
167
+ executors,
168
+ maxIterations: projectConfig.loop.maxIterations,
169
169
  abortSignal: signal,
170
- onAbort(_event) {
171
- logger.warn("The agent loop was aborted by the user.");
172
- terminal.warn("Operation aborted by user.");
173
- },
174
- onFinish: async (result) => {
175
- logger.debug("onFinish called");
176
- if (result.response.messages.length > 0) {
177
- messageHistory.appendResponseMessages(result.response.messages);
178
- }
179
- terminal.hr();
180
- // Notify if configured in project config (acai.json)
181
- const projectConfig = await configManager.readProjectConfig();
182
- if (projectConfig.notify) {
183
- terminal.alert();
184
- }
185
- // Create a more visual representation of steps/tool usage
186
- displayToolUse(result, terminal);
187
- const total = result.totalUsage ??
188
- result.usage;
189
- const inputTokens = isNumber(total.inputTokens)
190
- ? total.inputTokens
191
- : 0;
192
- const outputTokens = isNumber(total.outputTokens)
193
- ? total.outputTokens
194
- : 0;
195
- const tokenSummary = `Tokens: ↑ ${inputTokens} ↓ ${outputTokens}`;
196
- terminal.writeln(style.dim(tokenSummary));
197
- const inputCost = modelConfig.costPerInputToken * inputTokens;
198
- const outputCost = modelConfig.costPerOutputToken * outputTokens;
199
- terminal.writeln(style.dim(`Cost: $${(inputCost + outputCost).toFixed(2)}`));
200
- // Track aggregate usage across all steps when available
201
- tokenTracker.trackUsage("repl", total);
202
- // Derive current context window from final step usage
203
- const finalTotalTokens = result.usage.totalTokens;
204
- if (isNumber(finalTotalTokens)) {
205
- currentContextWindow = finalTotalTokens ?? 0;
206
- }
207
- else {
208
- // Fallback: find the stopped step
209
- for (const step of result.steps) {
210
- if (step.finishReason === "stop") {
211
- const usage = step.usage;
212
- currentContextWindow = Number.isNaN(usage.totalTokens)
213
- ? 0
214
- : (usage.totalTokens ?? 0);
215
- }
216
- }
217
- }
218
- terminal.hr();
219
- },
220
- onError: ({ error }) => {
221
- logger.error(error, // Log the full error object
222
- "Error on REPL streamText");
223
- terminal.error(error.message.length > 100
224
- ? `${error.message.slice(0, 100)}...`
225
- : error.message);
226
- },
170
+ toolCallRepair: toolCallRepair(modelManager),
227
171
  });
228
- let accumulatedText = "";
229
- let lastType = null;
230
- for await (const chunk of result.fullStream) {
231
- // Handle text-related chunks (reasoning or text-delta)
232
- if (chunk.type === "reasoning-delta" || chunk.type === "text-delta") {
233
- if (chunk.type === "reasoning-delta") {
234
- if (lastType !== "reasoning") {
235
- terminal.writeln(style.dim("<think>"));
236
- }
237
- terminal.write(style.dim(chunk.text)); // Stream reasoning directly
238
- lastType = "reasoning";
239
- }
240
- else if (chunk.type === "text-delta") {
241
- if (lastType === "reasoning") {
242
- // Finishing reasoning: Print </think>
243
- terminal.writeln(style.dim("\n</think>\n"));
244
- }
245
- accumulatedText += chunk.text;
246
- lastType = "text";
247
- }
248
- }
249
- else if (chunk.type === "tool-call") {
250
- terminal.stopProgress();
251
- }
252
- else if (chunk.type === "tool-result") {
253
- const messages = toolEvents.get(chunk.toolCallId);
254
- if (messages) {
255
- displayToolMessages(messages, terminal);
256
- toolEvents.delete(chunk.toolCallId);
257
- }
258
- else {
259
- logger.warn(`No tool events found for ${chunk.toolCallId}`);
260
- }
261
- }
262
- else {
263
- // Close thinking tags when moving from reasoning to any other chunk type
264
- if (lastType === "reasoning") {
265
- terminal.write(style.dim("\n</think>\n\n"));
266
- }
267
- terminal.stopProgress();
268
- // if there is accumulatedText, display it
269
- if (accumulatedText.trim()) {
270
- terminal.writeln(`${style.blue.bold("● Response:")}`);
271
- terminal.display(accumulatedText, true);
272
- terminal.lineBreak();
273
- }
274
- accumulatedText = "";
275
- lastType = null;
276
- }
277
- }
278
- // Ensure the final closing tag for reasoning is written if it was the last type
279
- if (lastType === "reasoning") {
280
- terminal.write(style.gray("\n</think>\n\n"));
172
+ const stop = performance.now();
173
+ terminal.hr();
174
+ // Notify if configured in project config (acai.json)
175
+ if (projectConfig.notify) {
176
+ terminal.alert();
281
177
  }
282
- // if there is accumulatedText, display it
283
- if (accumulatedText.trim()) {
284
- terminal.writeln(`${style.green.bold("● Response:")}`);
285
- terminal.display(accumulatedText, true);
286
- terminal.lineBreak();
287
- }
288
- terminal.lineBreak(); // Add a final newline for clarity
289
- await result.consumeStream();
178
+ // Create a more visual representation of steps/tool usage
179
+ displayToolUse(result, terminal);
180
+ // Show time spend on this prompt
181
+ terminal.writeln(style.dim(`Time: ${formatDuration(stop - start)}`));
182
+ const total = result.totalUsage;
183
+ const inputTokens = total.inputTokens;
184
+ const outputTokens = total.outputTokens;
185
+ const cachedInputTokens = total.cachedInputTokens;
186
+ const tokenSummary = `Tokens: ↑ ${inputTokens} (${cachedInputTokens}) ↓ ${outputTokens}`;
187
+ terminal.writeln(style.dim(tokenSummary));
188
+ const inputCost = modelConfig.costPerInputToken * inputTokens;
189
+ const outputCost = modelConfig.costPerOutputToken * outputTokens;
190
+ terminal.writeln(style.dim(`Cost: $${(inputCost + outputCost).toFixed(2)}`));
191
+ // Track aggregate usage across all steps when available
192
+ tokenTracker.trackUsage("repl", total);
193
+ // Derive current context window from final step usage
194
+ currentContextWindow = result.usage.totalTokens;
195
+ messageHistory.save();
196
+ terminal.hr();
197
+ terminal.lineBreak();
290
198
  }
291
199
  catch (e) {
292
200
  if (isRecord(e) && isRecord(e["data"]) && "error" in e["data"]) {
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox-prompt.d.ts","sourceRoot":"","sources":["../../source/terminal/checkbox-prompt.ts"],"names":[],"mappings":";AACA;;;GAGG;AAoCH,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC;CAC5B;AAED,UAAU,YAAY,CAAC,CAAC,GAAG,OAAO;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,CAAC;IACT,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AACD,MAAM,MAAM,MAAM,CAAC,CAAC,GAAG,OAAO,IAAI,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AAS3D,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,UAAU,CAAC;CACvB;AA4GD;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,EAC1C,OAAkB,EAClB,OAAO,EACP,OAAW,EACX,QAAY,EACZ,QAAgB,EAChB,MAAM,EACN,QAA2D,GAC5D,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAyPnC"}
1
+ {"version":3,"file":"checkbox-prompt.d.ts","sourceRoot":"","sources":["../../source/terminal/checkbox-prompt.ts"],"names":[],"mappings":";AACA;;;GAGG;AAoCH,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC;CAC5B;AAED,UAAU,YAAY,CAAC,CAAC,GAAG,OAAO;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,CAAC;IACT,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AACD,MAAM,MAAM,MAAM,CAAC,CAAC,GAAG,OAAO,IAAI,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AAS3D,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,UAAU,CAAC;CACvB;AA4GD;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,EAC1C,OAAkB,EAClB,OAAO,EACP,OAAW,EACX,QAAY,EACZ,QAAgB,EAChB,MAAM,EACN,QAA2D,GAC5D,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAiQnC"}
@@ -144,15 +144,19 @@ export async function checkbox({ message = "Select", choices, initial = 0, pageS
144
144
  }, 800);
145
145
  };
146
146
  let previousOutputLines = 0;
147
+ function clearPreviousOutput(lineCount) {
148
+ for (let i = 0; i < lineCount; i++) {
149
+ stdout.write(`${ANSI.moveUp}${ANSI.clearLine}`);
150
+ }
151
+ }
147
152
  function renderToScreen() {
153
+ // Clear current line and move to start
148
154
  stdout.write(ANSI.clearLine);
149
155
  stdout.write(ANSI.moveToStart);
156
+ // Clear from cursor to end of screen to remove any existing output below
150
157
  stdout.write(ANSI.clearFromCursor);
151
158
  // Clear previous output by moving up and clearing lines
152
- for (let i = 0; i < previousOutputLines; i++) {
153
- stdout.write(ANSI.moveUp);
154
- stdout.write(ANSI.clearLine);
155
- }
159
+ clearPreviousOutput(previousOutputLines);
156
160
  const out = render(normalized, pointer, pageStart, pageSize, message, searchBuffer, requiredError);
157
161
  // Count lines in current output
158
162
  previousOutputLines = out.split("\n").length;
@@ -306,6 +310,8 @@ export async function checkbox({ message = "Select", choices, initial = 0, pageS
306
310
  }
307
311
  try {
308
312
  stdout.write(ANSI.hideCursor);
313
+ // Reset previous output lines counter to ensure clean start
314
+ previousOutputLines = 0;
309
315
  renderToScreen();
310
316
  stdin.on("data", onData);
311
317
  const exitHandler = () => {
@@ -7,6 +7,13 @@
7
7
  import { type StyleInstance } from "./style.ts";
8
8
  import type { TerminalConfig } from "./types.ts";
9
9
  export declare function getShell(): string;
10
+ export declare function hr(width: number): string;
11
+ export declare function table(data: (string | number)[][], options: {
12
+ header?: string[];
13
+ colWidths?: number[];
14
+ width: number;
15
+ }): string;
16
+ export declare function displayProgressBar(current: number, total: number, width: number): string;
10
17
  /**
11
18
  * Initialize the terminal interface
12
19
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/terminal/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH,OAAc,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD,wBAAgB,QAAQ,WAEvB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,GAAE,OAAO,CAAC,cAAc,CAAM,GAAG,QAAQ,CAyB3E;AAED;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAU;gBAEnB,MAAM,EAAE,cAAc;IAoBlC;;OAEG;IACH,kBAAkB;IAclB,QAAQ,CAAC,KAAK,EAAE,MAAM;IAItB,OAAO,IAAI,MAAM;IAWjB;;OAEG;IACH,cAAc,IAAI,IAAI;IAmCtB;;OAEG;IACH,KAAK,IAAI,IAAI;IAMb;;;OAGG;IACH,aAAa,IAAI,IAAI;IAIrB;;;OAGG;IACH,YAAY,IAAI,IAAI;IAIpB;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,UAAQ,GAAG,IAAI;IAI5C;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQhC;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQ3B;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQ9B;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQ3B;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQ5B;;OAEG;IACH,KAAK,IAAI,IAAI;IAoBb,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI1B,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI5B,SAAS;IAIT,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,aAA0B,GAAG,IAAI;IAQ3D,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCzD,EAAE,CAAC,OAAO,GAAE,aAA0B,GAAG,IAAI;IAK7C;;OAEG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM;IAIvC;;OAEG;IACH,KAAK,CACH,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,EAC3B,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;KAAO,GACxD,IAAI;IAuEP;;;;OAIG;IACH,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAiDxD,OAAO,CAAC,cAAc;CASvB;AAGD,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/terminal/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH,OAAc,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD,wBAAgB,QAAQ,WAEvB;AAED,wBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,UAE/B;AAED,wBAAgB,KAAK,CACnB,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,EAC3B,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClE,MAAM,CAqER;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,UA0Cd;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,GAAE,OAAO,CAAC,cAAc,CAAM,GAAG,QAAQ,CAyB3E;AAED;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAU;gBAEnB,MAAM,EAAE,cAAc;IAoBlC;;OAEG;IACH,kBAAkB;IAclB,QAAQ,CAAC,KAAK,EAAE,MAAM;IAItB,OAAO,IAAI,MAAM;IAWjB;;OAEG;IACH,cAAc,IAAI,IAAI;IAmCtB;;OAEG;IACH,KAAK,IAAI,IAAI;IAMb;;;OAGG;IACH,aAAa,IAAI,IAAI;IAIrB;;;OAGG;IACH,YAAY,IAAI,IAAI;IAIpB;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,UAAQ,GAAG,IAAI;IAI5C;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQhC;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQ3B;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQ9B;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQ3B;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQ5B;;OAEG;IACH,KAAK,IAAI,IAAI;IAoBb,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI1B,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI5B,SAAS;IAIT,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,aAA0B,GAAG,IAAI;IAQ3D,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCzD,EAAE,CAAC,OAAO,GAAE,aAA0B,GAAG,IAAI;IAK7C;;OAEG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM;IAIvC;;OAEG;IACH,KAAK,CACH,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,EAC3B,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;KAAO,GACxD,IAAI;IAuEP;;;;OAIG;IACH,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAiDxD,OAAO,CAAC,cAAc;CASvB;AAGD,cAAc,YAAY,CAAC"}
@@ -15,6 +15,100 @@ import wrapAnsi from "./wrap-ansi.js";
15
15
  export function getShell() {
16
16
  return process.env["ZSH_VERSION"] ? "zsh" : process.env["SHELL"] || "bash";
17
17
  }
18
+ export function hr(width) {
19
+ return `${style.gray("─").repeat(width)} `;
20
+ }
21
+ export function table(data, options) {
22
+ const { header, colWidths, width } = options;
23
+ // Determine number of columns from data or header
24
+ let colCount = header?.length;
25
+ if (colCount === undefined) {
26
+ colCount = data.length > 0 && data[0] ? data[0].length : 1;
27
+ }
28
+ // Calculate column widths based on terminal width
29
+ const padding = 5; // Account for table borders and padding
30
+ const availableWidth = Math.max(20, width - padding);
31
+ let computedColWidths;
32
+ if (colWidths && colWidths.length === colCount) {
33
+ // Use provided percentages
34
+ computedColWidths = colWidths.map((percent) => Math.max(10, Math.floor((percent / 100) * availableWidth)));
35
+ }
36
+ else {
37
+ // Distribute width evenly with minimum width per column
38
+ const minColWidth = 15;
39
+ const maxColsThatFit = Math.floor(availableWidth / minColWidth);
40
+ const actualColCount = Math.min(colCount, maxColsThatFit);
41
+ if (actualColCount === 1) {
42
+ computedColWidths = [availableWidth];
43
+ }
44
+ else {
45
+ // Calculate base width and distribute remaining pixels
46
+ const baseWidth = Math.floor(availableWidth / actualColCount);
47
+ const remainder = availableWidth % actualColCount;
48
+ computedColWidths = Array(actualColCount).fill(baseWidth);
49
+ // Distribute remainder pixels to first few columns
50
+ for (let i = 0; i < remainder && i < actualColCount; i++) {
51
+ computedColWidths[i] = (computedColWidths[i] || 0) + 1;
52
+ }
53
+ }
54
+ // If we have fewer computed widths than columns, extend the array
55
+ while (computedColWidths.length < colCount) {
56
+ computedColWidths.push(minColWidth);
57
+ }
58
+ }
59
+ const table = new Table({
60
+ head: header,
61
+ colWidths: computedColWidths,
62
+ wordWrap: true,
63
+ wrapOnWordBoundary: true,
64
+ });
65
+ // Ensure all data rows have the same number of columns
66
+ const normalizedData = data.map((row) => {
67
+ if (row.length < colCount) {
68
+ // Pad with empty strings if row has fewer columns
69
+ return [...row, ...Array(colCount - row.length).fill("")];
70
+ }
71
+ if (row.length > colCount) {
72
+ // Truncate if row has more columns
73
+ return row.slice(0, colCount);
74
+ }
75
+ return row;
76
+ });
77
+ table.push(...normalizedData);
78
+ return table.toString();
79
+ }
80
+ export function displayProgressBar(current, total, width) {
81
+ const terminalWidth = width;
82
+ // Function to format numbers concisely (e.g., 1.2K, 5M)
83
+ const formatNumber = (num) => {
84
+ if (num < 1000) {
85
+ return num.toString();
86
+ }
87
+ if (num < 1_000_000) {
88
+ return `${(num / 1000).toFixed(1)}K`;
89
+ }
90
+ if (num < 1_000_000_000) {
91
+ return `${(num / 1_000_000).toFixed(1)}M`;
92
+ }
93
+ return `${(num / 1_000_000_000).toFixed(1)}G`;
94
+ };
95
+ const currentFormatted = formatNumber(current);
96
+ const totalFormatted = formatNumber(total);
97
+ const progressText = `${currentFormatted}/${totalFormatted}`;
98
+ const progressTextLength = progressText.length + 1; // Add 1 for space
99
+ const progressBarMaxWidth = Math.max(1, terminalWidth - progressTextLength);
100
+ const percentage = total === 0 ? 1 : current / total;
101
+ const filledWidth = Math.max(0, Math.min(progressBarMaxWidth, Math.floor(percentage * progressBarMaxWidth)));
102
+ const emptyWidth = Math.max(0, progressBarMaxWidth - filledWidth);
103
+ const a = filledWidth / progressBarMaxWidth > 0.5
104
+ ? style.red("─")
105
+ : style.yellow("─"); //"█"
106
+ const b = style.gray("─"); // "░"
107
+ const filledBar = a.repeat(filledWidth);
108
+ const emptyBar = b.repeat(emptyWidth);
109
+ // Use \r to move cursor to the beginning of the line for updates
110
+ return `\r${filledBar}${emptyBar} ${progressText} `;
111
+ }
18
112
  /**
19
113
  * Initialize the terminal interface
20
114
  */
@@ -3,7 +3,7 @@
3
3
  * Standalone input prompt (inquirer-like)
4
4
  * - TypeScript version
5
5
  */
6
- export interface InputOptions {
6
+ interface InputOptions {
7
7
  message?: string;
8
8
  default?: string;
9
9
  validate?: (input: string) => true | string;
@@ -13,4 +13,5 @@ export interface InputOptions {
13
13
  signal?: AbortSignal;
14
14
  }
15
15
  export declare function input({ message, default: defaultValue, validate, required, minLength, maxLength, signal, }?: InputOptions): Promise<string>;
16
+ export {};
16
17
  //# sourceMappingURL=input-prompt.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"input-prompt.d.ts","sourceRoot":"","sources":["../../source/terminal/input-prompt.ts"],"names":[],"mappings":";AACA;;;GAGG;AAWH,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,CAAC;IAC5C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AA4HD,wBAAsB,KAAK,CAAC,EAC1B,OAAuB,EACvB,OAAO,EAAE,YAAY,EACrB,QAAQ,EACR,QAAgB,EAChB,SAAS,EACT,SAAS,EACT,MAAM,GACP,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CA0DrC"}
1
+ {"version":3,"file":"input-prompt.d.ts","sourceRoot":"","sources":["../../source/terminal/input-prompt.ts"],"names":[],"mappings":";AACA;;;GAGG;AAWH,UAAU,YAAY;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,CAAC;IAC5C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AA4HD,wBAAsB,KAAK,CAAC,EAC1B,OAAuB,EACvB,OAAO,EAAE,YAAY,EACrB,QAAQ,EACR,QAAgB,EAChB,SAAS,EACT,SAAS,EACT,MAAM,GACP,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CA0DrC"}
@@ -109,6 +109,9 @@ function format(token, listDepth = 0, orderedListNumber = null, parent = null) {
109
109
  case "del": {
110
110
  return style.strikethrough(token.text);
111
111
  }
112
+ case "html":
113
+ // Render HTML tags with dim styling and content as normal text
114
+ return style.dim(token.text);
112
115
  default:
113
116
  return "";
114
117
  }
@@ -1 +1 @@
1
- {"version":3,"file":"search-prompt.d.ts","sourceRoot":"","sources":["../../source/terminal/search-prompt.ts"],"names":[],"mappings":";AACA;;;GAGG;AAQH,UAAU,YAAY,CAAC,CAAC,GAAG,OAAO;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,CAAC;IACT,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AACD,MAAM,MAAM,MAAM,CAAC,CAAC,GAAG,OAAO,IAAI,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AAQ3D,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,OAAO;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AA8CD,wBAAsB,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,EACxC,OAAkB,EAClB,MAAM,EACN,QAAY,EACZ,MAAM,GACP,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAsO/B"}
1
+ {"version":3,"file":"search-prompt.d.ts","sourceRoot":"","sources":["../../source/terminal/search-prompt.ts"],"names":[],"mappings":";AACA;;;GAGG;AAQH,UAAU,YAAY,CAAC,CAAC,GAAG,OAAO;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,CAAC;IACT,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AACD,MAAM,MAAM,MAAM,CAAC,CAAC,GAAG,OAAO,IAAI,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AAQ3D,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,OAAO;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AA8CD,wBAAsB,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,EACxC,OAAkB,EAClB,MAAM,EACN,QAAY,EACZ,MAAM,GACP,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAyO/B"}
@@ -7,7 +7,6 @@
7
7
  const ESC = "\x1b[";
8
8
  const hideCursor = () => process.stdout.write(`${ESC}?25l`);
9
9
  const showCursor = () => process.stdout.write(`${ESC}?25h`);
10
- const clearLine = () => process.stdout.write("\x1b[2K\r");
11
10
  function normalizeChoice(choice) {
12
11
  if (typeof choice === "string") {
13
12
  return { name: choice, value: choice, disabled: false };
@@ -54,16 +53,16 @@ export async function search({ message = "Search", source, pageSize = 7, signal,
54
53
  let pageStart = 0;
55
54
  let lastSourceCall = null;
56
55
  let previousOutputLines = 0;
57
- function renderToScreen() {
58
- clearLine();
59
- // Move cursor to beginning of line
60
- stdout.write("\x1b[0G");
61
- stdout.write("\x1b[0J"); // clear from cursor to end of screen
62
- // Clear previous output by moving up and clearing lines
63
- for (let i = 0; i < previousOutputLines; i++) {
64
- stdout.write("\x1b[1A"); // Move up one line
65
- stdout.write("\x1b[2K"); // Clear the entire line
56
+ function clearPreviousOutput(lineCount) {
57
+ for (let i = 0; i < lineCount; i++) {
58
+ stdout.write("\x1b[1A\x1b[2K"); // Move up and clear line
66
59
  }
60
+ }
61
+ function renderToScreen() {
62
+ stdout.write("\x1b[2K"); // Clear current line
63
+ stdout.write("\x1b[0G"); // Move to start of line
64
+ stdout.write("\x1b[0J"); // Clear from cursor to end of screen
65
+ clearPreviousOutput(previousOutputLines);
67
66
  const out = render(choices, pointer, pageStart, pageSize, message, searchInput);
68
67
  // Count lines in current output
69
68
  previousOutputLines = out.split("\n").length;
@@ -219,6 +218,8 @@ export async function search({ message = "Search", source, pageSize = 7, signal,
219
218
  }
220
219
  }
221
220
  hideCursor();
221
+ // Reset previous output lines counter to ensure clean start
222
+ previousOutputLines = 0;
222
223
  // Initial render with empty search
223
224
  updateChoices("");
224
225
  stdin.on("data", onData);
@@ -8,12 +8,12 @@ interface ChoiceObject<T = unknown> {
8
8
  value: T;
9
9
  disabled?: boolean;
10
10
  }
11
- export type Choice<T = unknown> = string | ChoiceObject<T>;
11
+ type Choice<T = unknown> = string | ChoiceObject<T>;
12
12
  interface TerminalIo {
13
13
  stdin: NodeJS.ReadStream;
14
14
  stdout: NodeJS.WriteStream;
15
15
  }
16
- export interface SelectOptions<T = unknown> {
16
+ interface SelectOptions<T = unknown> {
17
17
  message?: string;
18
18
  choices: Choice<T>[];
19
19
  initial?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"select-prompt.d.ts","sourceRoot":"","sources":["../../source/terminal/select-prompt.ts"],"names":[],"mappings":";AACA;;;GAGG;AA6BH,UAAU,YAAY,CAAC,CAAC,GAAG,OAAO;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,CAAC;IACT,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AACD,MAAM,MAAM,MAAM,CAAC,CAAC,GAAG,OAAO,IAAI,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AAQ3D,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,OAAO;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,UAAU,CAAC;CACvB;AA0FD,wBAAsB,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,EACxC,OAAkB,EAClB,OAAO,EACP,OAAW,EACX,QAAY,EACZ,MAAM,EACN,QAA2D,GAC5D,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAuM/B"}
1
+ {"version":3,"file":"select-prompt.d.ts","sourceRoot":"","sources":["../../source/terminal/select-prompt.ts"],"names":[],"mappings":";AACA;;;GAGG;AA6BH,UAAU,YAAY,CAAC,CAAC,GAAG,OAAO;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,CAAC;IACT,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AACD,KAAK,MAAM,CAAC,CAAC,GAAG,OAAO,IAAI,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AAQpD,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC;CAC5B;AAED,UAAU,aAAa,CAAC,CAAC,GAAG,OAAO;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,UAAU,CAAC;CACvB;AAgGD,wBAAsB,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,EACxC,OAAkB,EAClB,OAAO,EACP,OAAW,EACX,QAAY,EACZ,MAAM,EACN,QAA2D,GAC5D,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAgN/B"}