@travisennis/acai 0.0.3 → 0.0.5

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 (316) hide show
  1. package/README.md +225 -6
  2. package/dist/api/exa/index.d.ts +177 -0
  3. package/dist/api/exa/index.d.ts.map +1 -0
  4. package/dist/api/exa/index.js +439 -0
  5. package/dist/cli.d.ts +3 -2
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/commands/application-log-command.d.ts +1 -0
  8. package/dist/commands/application-log-command.d.ts.map +1 -0
  9. package/dist/commands/application-log-command.js +5 -3
  10. package/dist/commands/clear-command.d.ts +1 -0
  11. package/dist/commands/clear-command.d.ts.map +1 -0
  12. package/dist/commands/clear-command.js +2 -3
  13. package/dist/commands/compact-command.d.ts +1 -0
  14. package/dist/commands/compact-command.d.ts.map +1 -0
  15. package/dist/commands/compact-command.js +1 -1
  16. package/dist/commands/copy-command.d.ts +1 -0
  17. package/dist/commands/copy-command.d.ts.map +1 -0
  18. package/dist/commands/copy-command.js +3 -2
  19. package/dist/commands/edit-command.d.ts +1 -0
  20. package/dist/commands/edit-command.d.ts.map +1 -0
  21. package/dist/commands/edit-command.js +7 -5
  22. package/dist/commands/edit-prompt-command.d.ts +2 -1
  23. package/dist/commands/edit-prompt-command.d.ts.map +1 -0
  24. package/dist/commands/edit-prompt-command.js +15 -7
  25. package/dist/commands/exit-command.d.ts +13 -2
  26. package/dist/commands/exit-command.d.ts.map +1 -0
  27. package/dist/commands/exit-command.js +14 -2
  28. package/dist/commands/files-command.d.ts +1 -0
  29. package/dist/commands/files-command.d.ts.map +1 -0
  30. package/dist/commands/files-command.js +9 -8
  31. package/dist/commands/generate-rules-command.d.ts +1 -0
  32. package/dist/commands/generate-rules-command.d.ts.map +1 -0
  33. package/dist/commands/generate-rules-command.js +4 -3
  34. package/dist/commands/health-command.d.ts +3 -1
  35. package/dist/commands/health-command.d.ts.map +1 -0
  36. package/dist/commands/health-command.js +42 -5
  37. package/dist/commands/help-command.d.ts +1 -0
  38. package/dist/commands/help-command.d.ts.map +1 -0
  39. package/dist/commands/help-command.js +2 -3
  40. package/dist/commands/init-command.d.ts +1 -0
  41. package/dist/commands/init-command.d.ts.map +1 -0
  42. package/dist/commands/init-command.js +1 -2
  43. package/dist/commands/last-log-command.d.ts +1 -0
  44. package/dist/commands/last-log-command.d.ts.map +1 -0
  45. package/dist/commands/last-log-command.js +12 -17
  46. package/dist/commands/list-tools-command.d.ts +3 -0
  47. package/dist/commands/list-tools-command.d.ts.map +1 -0
  48. package/dist/commands/list-tools-command.js +61 -0
  49. package/dist/commands/manager.d.ts +7 -2
  50. package/dist/commands/manager.d.ts.map +1 -0
  51. package/dist/commands/manager.js +43 -6
  52. package/dist/commands/model-command.d.ts +1 -0
  53. package/dist/commands/model-command.d.ts.map +1 -0
  54. package/dist/commands/model-command.js +5 -5
  55. package/dist/commands/paste-command.d.ts +1 -0
  56. package/dist/commands/paste-command.d.ts.map +1 -0
  57. package/dist/commands/paste-command.js +6 -5
  58. package/dist/commands/prompt-command.d.ts +2 -1
  59. package/dist/commands/prompt-command.d.ts.map +1 -0
  60. package/dist/commands/prompt-command.js +62 -8
  61. package/dist/commands/reset-command.d.ts +1 -0
  62. package/dist/commands/reset-command.d.ts.map +1 -0
  63. package/dist/commands/reset-command.js +1 -1
  64. package/dist/commands/rules-command.d.ts +1 -0
  65. package/dist/commands/rules-command.d.ts.map +1 -0
  66. package/dist/commands/rules-command.js +5 -3
  67. package/dist/commands/save-command.d.ts +1 -0
  68. package/dist/commands/save-command.d.ts.map +1 -0
  69. package/dist/commands/save-command.js +1 -1
  70. package/dist/commands/shell-command.d.ts +3 -0
  71. package/dist/commands/shell-command.d.ts.map +1 -0
  72. package/dist/commands/shell-command.js +60 -0
  73. package/dist/commands/types.d.ts +9 -6
  74. package/dist/commands/types.d.ts.map +1 -0
  75. package/dist/commands/usage-command.d.ts +1 -0
  76. package/dist/commands/usage-command.d.ts.map +1 -0
  77. package/dist/commands/usage-command.js +2 -3
  78. package/dist/config.d.ts +22 -34
  79. package/dist/config.d.ts.map +1 -0
  80. package/dist/config.js +61 -15
  81. package/dist/conversation-analyzer.d.ts +2 -1
  82. package/dist/conversation-analyzer.d.ts.map +1 -0
  83. package/dist/dedent.d.ts +1 -0
  84. package/dist/dedent.d.ts.map +1 -0
  85. package/dist/execution/index.d.ts +112 -0
  86. package/dist/execution/index.d.ts.map +1 -0
  87. package/dist/execution/index.js +432 -0
  88. package/dist/formatting.d.ts +2 -13
  89. package/dist/formatting.d.ts.map +1 -0
  90. package/dist/formatting.js +5 -64
  91. package/dist/index.d.ts +1 -0
  92. package/dist/index.d.ts.map +1 -0
  93. package/dist/index.js +14 -4
  94. package/dist/logger.d.ts +1 -0
  95. package/dist/logger.d.ts.map +1 -0
  96. package/dist/mentions.d.ts +4 -0
  97. package/dist/mentions.d.ts.map +1 -0
  98. package/dist/mentions.js +42 -10
  99. package/dist/messages.d.ts +8 -20
  100. package/dist/messages.d.ts.map +1 -0
  101. package/dist/messages.js +33 -53
  102. package/dist/middleware/audit-message.d.ts +1 -0
  103. package/dist/middleware/audit-message.d.ts.map +1 -0
  104. package/dist/middleware/index.d.ts +1 -0
  105. package/dist/middleware/index.d.ts.map +1 -0
  106. package/dist/middleware/rate-limit.d.ts +1 -0
  107. package/dist/middleware/rate-limit.d.ts.map +1 -0
  108. package/dist/models/ai-config.d.ts +1 -0
  109. package/dist/models/ai-config.d.ts.map +1 -0
  110. package/dist/models/anthropic-provider.d.ts +1 -0
  111. package/dist/models/anthropic-provider.d.ts.map +1 -0
  112. package/dist/models/deepseek-provider.d.ts +1 -0
  113. package/dist/models/deepseek-provider.d.ts.map +1 -0
  114. package/dist/models/google-provider.d.ts +1 -0
  115. package/dist/models/google-provider.d.ts.map +1 -0
  116. package/dist/models/groq-provider.d.ts +20 -0
  117. package/dist/models/groq-provider.d.ts.map +1 -0
  118. package/dist/models/groq-provider.js +31 -0
  119. package/dist/models/manager.d.ts +1 -0
  120. package/dist/models/manager.d.ts.map +1 -0
  121. package/dist/models/openai-provider.d.ts +2 -1
  122. package/dist/models/openai-provider.d.ts.map +1 -0
  123. package/dist/models/openrouter-provider.d.ts +31 -22
  124. package/dist/models/openrouter-provider.d.ts.map +1 -0
  125. package/dist/models/openrouter-provider.js +115 -1
  126. package/dist/models/providers.d.ts +4 -5
  127. package/dist/models/providers.d.ts.map +1 -0
  128. package/dist/models/providers.js +7 -3
  129. package/dist/models/xai-provider.d.ts +1 -0
  130. package/dist/models/xai-provider.d.ts.map +1 -0
  131. package/dist/parsing.d.ts +2 -1
  132. package/dist/parsing.d.ts.map +1 -0
  133. package/dist/prompts/manager.d.ts +14 -2
  134. package/dist/prompts/manager.d.ts.map +1 -0
  135. package/dist/prompts.d.ts +1 -0
  136. package/dist/prompts.d.ts.map +1 -0
  137. package/dist/prompts.js +17 -11
  138. package/dist/repl/display-tool-messages.d.ts +4 -0
  139. package/dist/repl/display-tool-messages.d.ts.map +1 -0
  140. package/dist/repl/display-tool-messages.js +55 -0
  141. package/dist/repl/display-tool-use.d.ts +14 -0
  142. package/dist/repl/display-tool-use.d.ts.map +1 -0
  143. package/dist/repl/display-tool-use.js +63 -0
  144. package/dist/repl/get-prompt-header.d.ts +8 -0
  145. package/dist/repl/get-prompt-header.d.ts.map +1 -0
  146. package/dist/repl/get-prompt-header.js +38 -0
  147. package/dist/repl/tool-call-repair.d.ts +4 -0
  148. package/dist/repl/tool-call-repair.d.ts.map +1 -0
  149. package/dist/repl/tool-call-repair.js +50 -0
  150. package/dist/repl-prompt.d.ts +1 -0
  151. package/dist/repl-prompt.d.ts.map +1 -0
  152. package/dist/repl.d.ts +8 -4
  153. package/dist/repl.d.ts.map +1 -0
  154. package/dist/repl.js +108 -252
  155. package/dist/terminal/ansi-styles.d.ts +77 -0
  156. package/dist/terminal/ansi-styles.d.ts.map +1 -0
  157. package/dist/terminal/ansi-styles.js +215 -0
  158. package/dist/terminal/checkbox-prompt.d.ts +36 -0
  159. package/dist/terminal/checkbox-prompt.d.ts.map +1 -0
  160. package/dist/terminal/checkbox-prompt.js +362 -0
  161. package/dist/terminal/default-theme.d.ts +6 -0
  162. package/dist/terminal/default-theme.d.ts.map +1 -0
  163. package/dist/terminal/default-theme.js +182 -0
  164. package/dist/terminal/east-asian-width.d.ts +8 -0
  165. package/dist/terminal/east-asian-width.d.ts.map +1 -0
  166. package/dist/terminal/east-asian-width.js +409 -0
  167. package/dist/terminal/editor-prompt.d.ts +10 -0
  168. package/dist/terminal/editor-prompt.d.ts.map +1 -0
  169. package/dist/terminal/editor-prompt.js +61 -0
  170. package/dist/terminal/errors.d.ts +19 -0
  171. package/dist/terminal/errors.d.ts.map +1 -0
  172. package/dist/terminal/errors.js +37 -0
  173. package/dist/terminal/formatting.d.ts +1 -11
  174. package/dist/terminal/formatting.d.ts.map +1 -0
  175. package/dist/terminal/formatting.js +4 -20
  176. package/dist/terminal/highlight/index.d.ts +53 -0
  177. package/dist/terminal/highlight/index.d.ts.map +1 -0
  178. package/dist/terminal/highlight/index.js +90 -0
  179. package/dist/terminal/highlight/theme.d.ts +233 -0
  180. package/dist/terminal/highlight/theme.d.ts.map +1 -0
  181. package/dist/terminal/highlight/theme.js +83 -0
  182. package/dist/terminal/index.d.ts +16 -9
  183. package/dist/terminal/index.d.ts.map +1 -0
  184. package/dist/terminal/index.js +42 -126
  185. package/dist/terminal/input-prompt.d.ts +16 -0
  186. package/dist/terminal/input-prompt.d.ts.map +1 -0
  187. package/dist/terminal/input-prompt.js +181 -0
  188. package/dist/terminal/markdown-utils.d.ts +1 -0
  189. package/dist/terminal/markdown-utils.d.ts.map +1 -0
  190. package/dist/terminal/markdown.d.ts +1 -0
  191. package/dist/terminal/markdown.d.ts.map +1 -0
  192. package/dist/terminal/markdown.js +17 -12
  193. package/dist/terminal/search-prompt.d.ts +20 -0
  194. package/dist/terminal/search-prompt.d.ts.map +1 -0
  195. package/dist/terminal/search-prompt.js +279 -0
  196. package/dist/terminal/select-prompt.d.ts +26 -0
  197. package/dist/terminal/select-prompt.d.ts.map +1 -0
  198. package/dist/terminal/select-prompt.js +298 -0
  199. package/dist/terminal/string-width.d.ts +7 -0
  200. package/dist/terminal/string-width.d.ts.map +1 -0
  201. package/dist/terminal/string-width.js +61 -0
  202. package/dist/terminal/strip-ansi.d.ts +2 -0
  203. package/dist/terminal/strip-ansi.d.ts.map +1 -0
  204. package/dist/terminal/strip-ansi.js +20 -0
  205. package/dist/terminal/style.d.ts +191 -0
  206. package/dist/terminal/style.d.ts.map +1 -0
  207. package/dist/terminal/style.js +259 -0
  208. package/dist/terminal/supports-color.d.ts +1 -0
  209. package/dist/terminal/supports-color.d.ts.map +1 -0
  210. package/dist/terminal/supports-hyperlinks.d.ts +1 -3
  211. package/dist/terminal/supports-hyperlinks.d.ts.map +1 -0
  212. package/dist/terminal/supports-hyperlinks.js +1 -1
  213. package/dist/terminal/types.d.ts +1 -37
  214. package/dist/terminal/types.d.ts.map +1 -0
  215. package/dist/terminal/wrap-ansi.d.ts +8 -0
  216. package/dist/terminal/wrap-ansi.d.ts.map +1 -0
  217. package/dist/terminal/wrap-ansi.js +190 -0
  218. package/dist/{token-utils.d.ts → tokens/counter.d.ts} +1 -0
  219. package/dist/tokens/counter.d.ts.map +1 -0
  220. package/dist/{token-utils.js → tokens/counter.js} +1 -1
  221. package/dist/tokens/manage-output.d.ts +34 -0
  222. package/dist/tokens/manage-output.d.ts.map +1 -0
  223. package/dist/tokens/manage-output.js +44 -0
  224. package/dist/{token-tracker.d.ts → tokens/tracker.d.ts} +1 -0
  225. package/dist/tokens/tracker.d.ts.map +1 -0
  226. package/dist/tool-executor.d.ts +28 -0
  227. package/dist/tool-executor.d.ts.map +1 -0
  228. package/dist/tool-executor.js +74 -0
  229. package/dist/tools/agent.d.ts +3 -2
  230. package/dist/tools/agent.d.ts.map +1 -0
  231. package/dist/tools/agent.js +7 -4
  232. package/dist/tools/bash-utils.d.ts +7 -0
  233. package/dist/tools/bash-utils.d.ts.map +1 -0
  234. package/dist/tools/bash-utils.js +212 -0
  235. package/dist/tools/bash.d.ts +9 -7
  236. package/dist/tools/bash.d.ts.map +1 -0
  237. package/dist/tools/bash.js +95 -212
  238. package/dist/tools/code-interpreter.d.ts +1 -0
  239. package/dist/tools/code-interpreter.d.ts.map +1 -0
  240. package/dist/tools/code-interpreter.js +33 -8
  241. package/dist/tools/delete-file.d.ts +5 -3
  242. package/dist/tools/delete-file.d.ts.map +1 -0
  243. package/dist/tools/delete-file.js +47 -33
  244. package/dist/tools/directory-tree.d.ts +10 -1
  245. package/dist/tools/directory-tree.d.ts.map +1 -0
  246. package/dist/tools/directory-tree.js +91 -8
  247. package/dist/tools/dynamic-tool-loader.d.ts +12 -0
  248. package/dist/tools/dynamic-tool-loader.d.ts.map +1 -0
  249. package/dist/tools/dynamic-tool-loader.js +280 -0
  250. package/dist/tools/dynamic-tool-parser.d.ts +20 -0
  251. package/dist/tools/dynamic-tool-parser.d.ts.map +1 -0
  252. package/dist/tools/dynamic-tool-parser.js +21 -0
  253. package/dist/tools/edit-file.d.ts +10 -2
  254. package/dist/tools/edit-file.d.ts.map +1 -0
  255. package/dist/tools/edit-file.js +117 -40
  256. package/dist/tools/file-editing-utils.d.ts +2 -0
  257. package/dist/tools/file-editing-utils.d.ts.map +1 -0
  258. package/dist/tools/file-editing-utils.js +135 -0
  259. package/dist/tools/filesystem-utils.d.ts +6 -21
  260. package/dist/tools/filesystem-utils.d.ts.map +1 -0
  261. package/dist/tools/filesystem-utils.js +96 -148
  262. package/dist/tools/git-utils.d.ts +1 -0
  263. package/dist/tools/git-utils.d.ts.map +1 -0
  264. package/dist/tools/grep.d.ts +5 -3
  265. package/dist/tools/grep.d.ts.map +1 -0
  266. package/dist/tools/grep.js +67 -27
  267. package/dist/tools/index.d.ts +10 -14
  268. package/dist/tools/index.d.ts.map +1 -0
  269. package/dist/tools/index.js +33 -22
  270. package/dist/tools/move-file.d.ts +1 -0
  271. package/dist/tools/move-file.d.ts.map +1 -0
  272. package/dist/tools/move-file.js +12 -5
  273. package/dist/tools/read-file.d.ts +2 -1
  274. package/dist/tools/read-file.d.ts.map +1 -0
  275. package/dist/tools/read-file.js +13 -6
  276. package/dist/tools/read-multiple-files.d.ts +2 -1
  277. package/dist/tools/read-multiple-files.d.ts.map +1 -0
  278. package/dist/tools/read-multiple-files.js +90 -9
  279. package/dist/tools/save-file.d.ts +5 -3
  280. package/dist/tools/save-file.d.ts.map +1 -0
  281. package/dist/tools/save-file.js +64 -36
  282. package/dist/tools/think.d.ts +1 -0
  283. package/dist/tools/think.d.ts.map +1 -0
  284. package/dist/tools/think.js +5 -1
  285. package/dist/tools/types.d.ts +14 -1
  286. package/dist/tools/types.d.ts.map +1 -0
  287. package/dist/tools/web-fetch.d.ts +4 -2
  288. package/dist/tools/web-fetch.d.ts.map +1 -0
  289. package/dist/tools/web-fetch.js +2 -2
  290. package/dist/tools/web-search.d.ts +2 -1
  291. package/dist/tools/web-search.d.ts.map +1 -0
  292. package/dist/tools/web-search.js +46 -11
  293. package/dist/utils/filesystem.d.ts +23 -0
  294. package/dist/utils/filesystem.d.ts.map +1 -0
  295. package/dist/utils/filesystem.js +140 -0
  296. package/dist/utils/filetype-detection.d.ts +3 -0
  297. package/dist/utils/filetype-detection.d.ts.map +1 -0
  298. package/dist/utils/filetype-detection.js +112 -0
  299. package/dist/utils/glob.d.ts +52 -0
  300. package/dist/utils/glob.d.ts.map +1 -0
  301. package/dist/utils/glob.js +376 -0
  302. package/dist/utils/ignore.d.ts +104 -0
  303. package/dist/utils/ignore.d.ts.map +1 -0
  304. package/dist/utils/ignore.js +649 -0
  305. package/dist/utils/process.d.ts +10 -1
  306. package/dist/utils/process.d.ts.map +1 -0
  307. package/dist/utils/process.js +104 -5
  308. package/dist/utils/zod-utils.d.ts +4 -0
  309. package/dist/utils/zod-utils.d.ts.map +1 -0
  310. package/dist/utils/zod-utils.js +7 -0
  311. package/dist/version.d.ts +1 -0
  312. package/dist/version.d.ts.map +1 -0
  313. package/package.json +32 -30
  314. package/dist/tools/command-validation.d.ts +0 -12
  315. package/dist/tools/command-validation.js +0 -113
  316. /package/dist/{token-tracker.js → tokens/tracker.js} +0 -0
@@ -0,0 +1,279 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Standalone search prompt (inquirer-like)
4
+ * - TypeScript version
5
+ */
6
+ // ANSI helpers
7
+ const ESC = "\x1b[";
8
+ const hideCursor = () => process.stdout.write(`${ESC}?25l`);
9
+ const showCursor = () => process.stdout.write(`${ESC}?25h`);
10
+ const clearLine = () => process.stdout.write("\x1b[2K\r");
11
+ function normalizeChoice(choice) {
12
+ if (typeof choice === "string") {
13
+ return { name: choice, value: choice, disabled: false };
14
+ }
15
+ const { name, value, disabled = false } = choice;
16
+ return { name, value, disabled };
17
+ }
18
+ function render(choices, pointerIndex, pageStart, pageSize, prompt, searchInput) {
19
+ const visible = choices.slice(pageStart, pageStart + pageSize);
20
+ const lines = [];
21
+ lines.push(`${prompt}${searchInput ? ` (search: ${searchInput})` : ""}`);
22
+ for (let i = 0; i < visible.length; i++) {
23
+ const actualIndex = pageStart + i;
24
+ const ch = visible[i];
25
+ const prefix = actualIndex === pointerIndex ? "›" : " ";
26
+ if (ch.disabled) {
27
+ lines.push(` ${prefix} ${ch.name} (disabled)`);
28
+ }
29
+ else if (actualIndex === pointerIndex) {
30
+ lines.push(`\x1b[36m ${prefix} ${ch.name}\x1b[0m`);
31
+ }
32
+ else {
33
+ lines.push(` ${prefix} ${ch.name}`);
34
+ }
35
+ }
36
+ if (choices.length > pageSize) {
37
+ const pageCount = Math.ceil(choices.length / pageSize);
38
+ const currentPage = Math.ceil(pageStart / pageSize) + 1;
39
+ lines.push(`\x1b[2mPage ${currentPage}/${pageCount}\x1b[0m`);
40
+ }
41
+ return lines.join("\n");
42
+ }
43
+ export async function search({ message = "Search", source, pageSize = 7, signal, }) {
44
+ const stdin = process.stdin;
45
+ const stdout = process.stdout;
46
+ if (!stdin.isTTY)
47
+ throw new Error("TTY required");
48
+ stdin.setRawMode(true);
49
+ stdin.resume();
50
+ stdin.setEncoding("utf8");
51
+ let searchInput = "";
52
+ let choices = [];
53
+ let pointer = 0;
54
+ let pageStart = 0;
55
+ let lastSourceCall = null;
56
+ 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
66
+ }
67
+ const out = render(choices, pointer, pageStart, pageSize, message, searchInput);
68
+ // Count lines in current output
69
+ previousOutputLines = out.split("\n").length;
70
+ stdout.write(`${out}\n`);
71
+ }
72
+ function move(delta) {
73
+ const len = choices.length;
74
+ if (len === 0)
75
+ return;
76
+ let newIndex = pointer;
77
+ do {
78
+ newIndex = (newIndex + delta + len) % len;
79
+ } while (choices[newIndex]?.disabled && newIndex !== pointer);
80
+ pointer = newIndex;
81
+ // Update pageStart to snap to page boundaries
82
+ const currentPage = Math.floor(pointer / pageSize);
83
+ pageStart = currentPage * pageSize;
84
+ // Ensure pageStart is within bounds
85
+ pageStart = Math.max(0, Math.min(pageStart, choices.length - pageSize));
86
+ renderToScreen();
87
+ }
88
+ async function updateChoices(input) {
89
+ // Cancel previous source call if still in progress
90
+ if (lastSourceCall) {
91
+ // We can't actually cancel the promise, but we can ignore its result
92
+ lastSourceCall.catch(() => { });
93
+ }
94
+ const sourcePromise = source(input);
95
+ lastSourceCall = sourcePromise.then(() => { });
96
+ try {
97
+ const newChoices = await sourcePromise;
98
+ choices = newChoices.map(normalizeChoice);
99
+ // Reset pointer to first selectable choice
100
+ pointer = 0;
101
+ if (choices.length > 0) {
102
+ for (let i = 0; i < choices.length; i++) {
103
+ if (!choices[i].disabled) {
104
+ pointer = i;
105
+ break;
106
+ }
107
+ }
108
+ }
109
+ pageStart = 0;
110
+ renderToScreen();
111
+ }
112
+ catch (_error) {
113
+ // Handle source errors gracefully
114
+ choices = [];
115
+ pointer = 0;
116
+ pageStart = 0;
117
+ renderToScreen();
118
+ }
119
+ }
120
+ return new Promise((resolve, reject) => {
121
+ let resolved = false;
122
+ function cleanup() {
123
+ if (resolved)
124
+ return;
125
+ resolved = true;
126
+ stdin.setRawMode(false);
127
+ stdin.pause();
128
+ stdin.removeListener("data", onData);
129
+ showCursor();
130
+ }
131
+ // Handle abort signal
132
+ if (signal) {
133
+ signal.addEventListener("abort", () => {
134
+ cleanup();
135
+ const err = new Error("AbortError");
136
+ err.name = "AbortError";
137
+ reject(err);
138
+ });
139
+ }
140
+ function onData(key) {
141
+ if (key === "\u0003") {
142
+ cleanup();
143
+ stdout.write("\n");
144
+ const err = new Error("Cancelled");
145
+ err.isCanceled = true;
146
+ reject(err);
147
+ return;
148
+ }
149
+ if (key === "\r" || key === "\n") {
150
+ if (choices.length === 0) {
151
+ // No choices available, just return
152
+ cleanup();
153
+ stdout.write("\n");
154
+ const err = new Error("No choices available");
155
+ err.isCanceled = true;
156
+ reject(err);
157
+ return;
158
+ }
159
+ const chosen = choices[pointer];
160
+ if (chosen && !chosen.disabled) {
161
+ cleanup();
162
+ stdout.write("\n");
163
+ resolve(chosen.value);
164
+ return;
165
+ }
166
+ return;
167
+ }
168
+ if (key === "\x1b[A") {
169
+ move(-1);
170
+ return;
171
+ }
172
+ if (key === "\x1b[B") {
173
+ move(1);
174
+ return;
175
+ }
176
+ if (key === "\x1b[H" || key === "\x1b[1~") {
177
+ if (choices.length > 0) {
178
+ for (let i = 0; i < choices.length; i++) {
179
+ if (!choices[i].disabled) {
180
+ pointer = i;
181
+ break;
182
+ }
183
+ }
184
+ // Update pageStart to snap to page boundaries
185
+ const currentPage = Math.floor(pointer / pageSize);
186
+ pageStart = currentPage * pageSize;
187
+ pageStart = Math.max(0, Math.min(pageStart, choices.length - pageSize));
188
+ renderToScreen();
189
+ }
190
+ return;
191
+ }
192
+ if (key === "\x1b[F" || key === "\x1b[4~") {
193
+ if (choices.length > 0) {
194
+ for (let i = choices.length - 1; i >= 0; i--) {
195
+ if (!choices[i].disabled) {
196
+ pointer = i;
197
+ break;
198
+ }
199
+ }
200
+ // Update pageStart to snap to page boundaries
201
+ const currentPage = Math.floor(pointer / pageSize);
202
+ pageStart = currentPage * pageSize;
203
+ pageStart = Math.max(0, Math.min(pageStart, choices.length - pageSize));
204
+ renderToScreen();
205
+ }
206
+ return;
207
+ }
208
+ if (key === "\x7f" || key === "\b") {
209
+ if (searchInput.length > 0) {
210
+ searchInput = searchInput.slice(0, -1);
211
+ updateChoices(searchInput);
212
+ }
213
+ return;
214
+ }
215
+ if (key && key >= " " && key <= "~") {
216
+ searchInput += key;
217
+ updateChoices(searchInput);
218
+ return;
219
+ }
220
+ }
221
+ hideCursor();
222
+ // Initial render with empty search
223
+ updateChoices("");
224
+ stdin.on("data", onData);
225
+ process.on("exit", () => {
226
+ if (!resolved) {
227
+ cleanup();
228
+ stdout.write("\n");
229
+ }
230
+ });
231
+ });
232
+ }
233
+ // Quick test when run directly
234
+ if (import.meta.url === `file://${process.argv[1]}`) {
235
+ (async () => {
236
+ try {
237
+ const res = await search({
238
+ message: "Search for fruit",
239
+ source: async (input) => {
240
+ // Simulate async search
241
+ await new Promise((resolve) => setTimeout(resolve, 100));
242
+ const fruits = [
243
+ "Apple",
244
+ "Banana",
245
+ "Cherry",
246
+ "Date",
247
+ "Elderberry",
248
+ "Fig",
249
+ "Grapes",
250
+ "Honeydew",
251
+ "Orange",
252
+ ];
253
+ if (!input) {
254
+ return fruits.slice(0, 5);
255
+ }
256
+ return fruits
257
+ .filter((fruit) => fruit.toLowerCase().includes(input.toLowerCase()))
258
+ .slice(0, 10);
259
+ },
260
+ pageSize: 5,
261
+ });
262
+ console.log("You selected:", res);
263
+ process.exit(0);
264
+ }
265
+ catch (err) {
266
+ if (err &&
267
+ typeof err === "object" &&
268
+ "isCanceled" in err &&
269
+ err.isCanceled) {
270
+ console.error("Canceled");
271
+ process.exit(2);
272
+ }
273
+ else {
274
+ console.error(err);
275
+ process.exit(1);
276
+ }
277
+ }
278
+ })();
279
+ }
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Standalone select prompt (inquirer-like)
4
+ * - TypeScript version
5
+ */
6
+ interface ChoiceObject<T = unknown> {
7
+ name: string;
8
+ value: T;
9
+ disabled?: boolean;
10
+ }
11
+ export type Choice<T = unknown> = string | ChoiceObject<T>;
12
+ interface TerminalIo {
13
+ stdin: NodeJS.ReadStream;
14
+ stdout: NodeJS.WriteStream;
15
+ }
16
+ export interface SelectOptions<T = unknown> {
17
+ message?: string;
18
+ choices: Choice<T>[];
19
+ initial?: number;
20
+ pageSize?: number;
21
+ signal?: AbortSignal;
22
+ terminal?: TerminalIo;
23
+ }
24
+ export declare function select<T = unknown>({ message, choices, initial, pageSize, signal, terminal, }: SelectOptions<T>): Promise<T>;
25
+ export {};
26
+ //# sourceMappingURL=select-prompt.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,298 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Standalone select prompt (inquirer-like)
4
+ * - TypeScript version
5
+ */
6
+ const Keys = {
7
+ up: "\x1b[A",
8
+ down: "\x1b[B",
9
+ home: "\x1b[H",
10
+ homeAlt: "\x1b[1~",
11
+ end: "\x1b[F",
12
+ endAlt: "\x1b[4~",
13
+ ctrlC: "\u0003",
14
+ enter: "\r",
15
+ newline: "\n",
16
+ backspace: "\x7f",
17
+ backspaceAlt: "\b",
18
+ };
19
+ const ANSI = {
20
+ hideCursor: "\x1b[?25l",
21
+ showCursor: "\x1b[?25h",
22
+ clearLine: "\x1b[2K",
23
+ carriageReturn: "\r",
24
+ moveToStart: "\x1b[0G",
25
+ clearFromCursor: "\x1b[0J",
26
+ moveUp: "\x1b[1A",
27
+ cyan: "\x1b[36m",
28
+ dim: "\x1b[2m",
29
+ reset: "\x1b[0m",
30
+ };
31
+ function normalizeChoice(choice) {
32
+ if (typeof choice === "string") {
33
+ return { name: choice, value: choice, disabled: false };
34
+ }
35
+ const { name, value, disabled = false } = choice;
36
+ return { name, value, disabled };
37
+ }
38
+ function updatePageStart(pointerIndex, pageSize, totalItems) {
39
+ const currentPage = Math.floor(pointerIndex / pageSize);
40
+ const pageStart = currentPage * pageSize;
41
+ return Math.max(0, Math.min(pageStart, Math.max(0, totalItems - pageSize)));
42
+ }
43
+ function findNextEnabledIndex(choices, startIndex, direction) {
44
+ const len = choices.length;
45
+ let index = startIndex;
46
+ for (let i = 0; i < len; i++) {
47
+ index = (index + direction + len) % len;
48
+ if (!choices[index].disabled) {
49
+ return index;
50
+ }
51
+ }
52
+ return startIndex;
53
+ }
54
+ function findFirstEnabledIndex(choices) {
55
+ for (let i = 0; i < choices.length; i++) {
56
+ if (!choices[i].disabled) {
57
+ return i;
58
+ }
59
+ }
60
+ return 0;
61
+ }
62
+ function findLastEnabledIndex(choices) {
63
+ for (let i = choices.length - 1; i >= 0; i--) {
64
+ if (!choices[i].disabled) {
65
+ return i;
66
+ }
67
+ }
68
+ return choices.length - 1;
69
+ }
70
+ function render(choices, pointerIndex, pageStart, pageSize, prompt, typed) {
71
+ const visible = choices.slice(pageStart, pageStart + pageSize);
72
+ const lines = [];
73
+ lines.push(`${prompt}${typed ? ` (search: ${typed})` : ""}`);
74
+ for (let i = 0; i < visible.length; i++) {
75
+ const actualIndex = pageStart + i;
76
+ const ch = visible[i];
77
+ const prefix = actualIndex === pointerIndex ? "›" : " ";
78
+ if (ch.disabled) {
79
+ lines.push(` ${prefix} ${ch.name} (disabled)`);
80
+ }
81
+ else if (actualIndex === pointerIndex) {
82
+ lines.push(`${ANSI.cyan} ${prefix} ${ch.name}${ANSI.reset}`);
83
+ }
84
+ else {
85
+ lines.push(` ${prefix} ${ch.name}`);
86
+ }
87
+ }
88
+ if (choices.length > pageSize) {
89
+ const pageCount = Math.ceil(choices.length / pageSize);
90
+ const currentPage = Math.ceil(pageStart / pageSize) + 1;
91
+ lines.push(`${ANSI.dim}Page ${currentPage}/${pageCount}${ANSI.reset}`);
92
+ }
93
+ return lines.join("\n");
94
+ }
95
+ export async function select({ message = "Select", choices, initial = 0, pageSize = 7, signal, terminal = { stdin: process.stdin, stdout: process.stdout }, }) {
96
+ if (!Array.isArray(choices) || choices.length === 0) {
97
+ throw new Error("choices must be a non-empty array");
98
+ }
99
+ const normalized = choices.map(normalizeChoice);
100
+ const hasEnabledChoice = normalized.some((ch) => !ch.disabled);
101
+ if (!hasEnabledChoice) {
102
+ throw new Error("At least one choice must be enabled");
103
+ }
104
+ let pointer = Math.max(0, Math.min(Math.floor(initial ?? 0), normalized.length - 1));
105
+ if (normalized[pointer].disabled) {
106
+ pointer = findNextEnabledIndex(normalized, pointer, 1);
107
+ }
108
+ let pageStart = updatePageStart(pointer, pageSize, normalized.length);
109
+ const { stdin, stdout } = terminal;
110
+ if (!stdin.isTTY)
111
+ throw new Error("TTY required");
112
+ let searchBuffer = "";
113
+ let searchTimer = null;
114
+ const resetSearchBuffer = () => {
115
+ if (searchTimer)
116
+ clearTimeout(searchTimer);
117
+ searchTimer = setTimeout(() => {
118
+ searchBuffer = "";
119
+ }, 800);
120
+ };
121
+ let previousOutputLines = 0;
122
+ function clearPreviousOutput(lineCount) {
123
+ for (let i = 0; i < lineCount; i++) {
124
+ stdout.write(`${ANSI.moveUp}${ANSI.clearLine}`);
125
+ }
126
+ }
127
+ function renderToScreen() {
128
+ stdout.write(ANSI.clearLine);
129
+ stdout.write(ANSI.moveToStart);
130
+ stdout.write(ANSI.clearFromCursor);
131
+ clearPreviousOutput(previousOutputLines);
132
+ const out = render(normalized, pointer, pageStart, pageSize, message, searchBuffer);
133
+ previousOutputLines = out.split("\n").length;
134
+ stdout.write(`${out}\n`);
135
+ }
136
+ function move(delta) {
137
+ pointer = findNextEnabledIndex(normalized, pointer, delta);
138
+ pageStart = updatePageStart(pointer, pageSize, normalized.length);
139
+ renderToScreen();
140
+ }
141
+ function jumpToIndexStartingWith(prefix) {
142
+ const start = (pointer + 1) % normalized.length;
143
+ const lowerPref = prefix.toLowerCase();
144
+ for (let i = 0; i < normalized.length; i++) {
145
+ const idx = (start + i) % normalized.length;
146
+ if (normalized[idx].disabled)
147
+ continue;
148
+ if (normalized[idx].name.toLowerCase().startsWith(lowerPref)) {
149
+ pointer = idx;
150
+ pageStart = updatePageStart(pointer, pageSize, normalized.length);
151
+ renderToScreen();
152
+ return true;
153
+ }
154
+ }
155
+ return false;
156
+ }
157
+ return new Promise((resolve, reject) => {
158
+ let resolved = false;
159
+ function cleanup() {
160
+ if (resolved)
161
+ return;
162
+ resolved = true;
163
+ stdin.setRawMode(false);
164
+ stdin.pause();
165
+ stdin.removeListener("data", onData);
166
+ if (searchTimer)
167
+ clearTimeout(searchTimer);
168
+ if (signal && abortHandler) {
169
+ signal.removeEventListener("abort", abortHandler);
170
+ }
171
+ stdout.write(ANSI.showCursor);
172
+ }
173
+ const abortHandler = signal
174
+ ? () => {
175
+ cleanup();
176
+ const err = new Error("AbortError");
177
+ err.name = "AbortError";
178
+ reject(err);
179
+ }
180
+ : null;
181
+ if (signal && abortHandler) {
182
+ signal.addEventListener("abort", abortHandler);
183
+ }
184
+ function onData(key) {
185
+ if (key === Keys.ctrlC) {
186
+ cleanup();
187
+ stdout.write("\n");
188
+ const err = new Error("Cancelled");
189
+ err.isCanceled = true;
190
+ reject(err);
191
+ return;
192
+ }
193
+ if (key === Keys.enter || key === Keys.newline) {
194
+ cleanup();
195
+ const chosen = normalized[pointer];
196
+ stdout.write("\n");
197
+ resolve(chosen.value);
198
+ return;
199
+ }
200
+ if (key === Keys.up) {
201
+ move(-1);
202
+ return;
203
+ }
204
+ if (key === Keys.down) {
205
+ move(1);
206
+ return;
207
+ }
208
+ if (key === Keys.home || key === Keys.homeAlt) {
209
+ pointer = findFirstEnabledIndex(normalized);
210
+ pageStart = updatePageStart(pointer, pageSize, normalized.length);
211
+ renderToScreen();
212
+ return;
213
+ }
214
+ if (key === Keys.end || key === Keys.endAlt) {
215
+ pointer = findLastEnabledIndex(normalized);
216
+ pageStart = updatePageStart(pointer, pageSize, normalized.length);
217
+ renderToScreen();
218
+ return;
219
+ }
220
+ if (key === Keys.backspace || key === Keys.backspaceAlt) {
221
+ if (searchBuffer.length > 0) {
222
+ searchBuffer = searchBuffer.slice(0, -1);
223
+ if (searchBuffer.length === 0)
224
+ resetSearchBuffer();
225
+ renderToScreen();
226
+ }
227
+ return;
228
+ }
229
+ if (key && key >= " " && key <= "~") {
230
+ searchBuffer += key;
231
+ resetSearchBuffer();
232
+ const found = jumpToIndexStartingWith(searchBuffer);
233
+ if (!found) {
234
+ searchBuffer = key;
235
+ resetSearchBuffer();
236
+ jumpToIndexStartingWith(searchBuffer);
237
+ }
238
+ renderToScreen();
239
+ return;
240
+ }
241
+ }
242
+ try {
243
+ stdin.setRawMode(true);
244
+ stdin.resume();
245
+ stdin.setEncoding("utf8");
246
+ stdout.write(ANSI.hideCursor);
247
+ renderToScreen();
248
+ stdin.on("data", onData);
249
+ const exitHandler = () => {
250
+ if (!resolved) {
251
+ cleanup();
252
+ stdout.write("\n");
253
+ }
254
+ };
255
+ process.on("exit", exitHandler);
256
+ }
257
+ catch (error) {
258
+ cleanup();
259
+ throw error;
260
+ }
261
+ });
262
+ }
263
+ if (import.meta.url === `file://${process.argv[1]}`) {
264
+ (async () => {
265
+ try {
266
+ const res = await select({
267
+ message: "Pick a fruit",
268
+ choices: [
269
+ "Apple",
270
+ "Banana",
271
+ "Date",
272
+ "Elderberry",
273
+ "Fig",
274
+ "Grapes",
275
+ "Honeydew",
276
+ "Orange",
277
+ ],
278
+ pageSize: 3,
279
+ initial: 0,
280
+ });
281
+ console.info("You picked:", res);
282
+ process.exit(0);
283
+ }
284
+ catch (err) {
285
+ if (err &&
286
+ typeof err === "object" &&
287
+ "isCanceled" in err &&
288
+ err.isCanceled) {
289
+ console.error("Canceled");
290
+ process.exit(2);
291
+ }
292
+ else {
293
+ console.error(err);
294
+ process.exit(1);
295
+ }
296
+ }
297
+ })();
298
+ }
@@ -0,0 +1,7 @@
1
+ interface StringWidthOptions {
2
+ ambiguousIsNarrow?: boolean;
3
+ countAnsiEscapeCodes?: boolean;
4
+ }
5
+ export default function stringWidth(input: string, options?: StringWidthOptions): number;
6
+ export {};
7
+ //# sourceMappingURL=string-width.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"string-width.d.ts","sourceRoot":"","sources":["../../source/terminal/string-width.ts"],"names":[],"mappings":"AAGA,UAAU,kBAAkB;IAC1B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAwCD,MAAM,CAAC,OAAO,UAAU,WAAW,CACjC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,kBAAuB,GAC/B,MAAM,CA0CR"}
@@ -0,0 +1,61 @@
1
+ import { eastAsianWidth } from "./east-asian-width.js";
2
+ import stripAnsi from "./strip-ansi.js";
3
+ const segmenter = new Intl.Segmenter();
4
+ // Whole-cluster zero-width
5
+ const zeroWidthClusterRegex = /^(?:\p{Default_Ignorable_Code_Point}|\p{Control}|\p{Mark}|\p{Surrogate})+$/v;
6
+ // Pick the base scalar if the cluster starts with Prepend/Format/Marks
7
+ const leadingNonPrintingRegex = /^[\p{Default_Ignorable_Code_Point}\p{Control}\p{Format}\p{Mark}\p{Surrogate}]+/v;
8
+ // RGI emoji sequences
9
+ const rgiEmojiRegex = /^\p{RGI_Emoji}$/v;
10
+ function baseVisible(segment) {
11
+ return segment.replace(leadingNonPrintingRegex, "");
12
+ }
13
+ function isZeroWidthCluster(segment) {
14
+ return zeroWidthClusterRegex.test(segment);
15
+ }
16
+ function trailingHalfwidthWidth(segment, eastAsianWidthOptions) {
17
+ let extra = 0;
18
+ if (segment.length > 1) {
19
+ for (const char of segment.slice(1)) {
20
+ const codePoint = char.codePointAt(0);
21
+ if (codePoint !== undefined && char >= "\\uFF00" && char <= "\\uFFEF") {
22
+ extra += eastAsianWidth(codePoint, eastAsianWidthOptions);
23
+ }
24
+ }
25
+ }
26
+ return extra;
27
+ }
28
+ export default function stringWidth(input, options = {}) {
29
+ if (typeof input !== "string" || input.length === 0) {
30
+ return 0;
31
+ }
32
+ const { ambiguousIsNarrow = true, countAnsiEscapeCodes = false } = options;
33
+ let string = input;
34
+ if (!countAnsiEscapeCodes) {
35
+ string = stripAnsi(string);
36
+ }
37
+ if (string.length === 0) {
38
+ return 0;
39
+ }
40
+ let width = 0;
41
+ const eastAsianWidthOptions = { ambiguousAsWide: !ambiguousIsNarrow };
42
+ for (const { segment } of segmenter.segment(string)) {
43
+ // Zero-width / non-printing clusters
44
+ if (isZeroWidthCluster(segment)) {
45
+ continue;
46
+ }
47
+ // Emoji width logic
48
+ if (rgiEmojiRegex.test(segment)) {
49
+ width += 2;
50
+ continue;
51
+ }
52
+ // Everything else: EAW of the cluster’s first visible scalar
53
+ const codePoint = baseVisible(segment).codePointAt(0);
54
+ if (codePoint !== undefined) {
55
+ width += eastAsianWidth(codePoint, eastAsianWidthOptions);
56
+ // Add width for trailing Halfwidth and Fullwidth Forms (e.g., ゙, ゚, ー)
57
+ width += trailingHalfwidthWidth(segment, eastAsianWidthOptions);
58
+ }
59
+ }
60
+ return width;
61
+ }
@@ -0,0 +1,2 @@
1
+ export default function stripAnsi(string: string): string;
2
+ //# sourceMappingURL=strip-ansi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strip-ansi.d.ts","sourceRoot":"","sources":["../../source/terminal/strip-ansi.ts"],"names":[],"mappings":"AAkBA,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CASxD"}