@travisennis/acai 0.0.1

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 (439) hide show
  1. package/.acai/acai.json +9 -0
  2. package/.acai/prompts/add-openrouter-model.md +13 -0
  3. package/.acai/prompts/project-status.md +4 -0
  4. package/.acai/prompts/update-architecture-document.md +9 -0
  5. package/.acai/rules/learned-rules.md +9 -0
  6. package/.ai/docs/available-tools.txt +3 -0
  7. package/.ai/docs/cognitive_complexity_refactoring_progress.md +65 -0
  8. package/.ai/docs/deleted_tools.md +168 -0
  9. package/.ai/docs/deleted_tools_88ced9ef.md +56 -0
  10. package/.ai/docs/image-pasting.md +46 -0
  11. package/.ai/docs/initialize-app.md +117 -0
  12. package/.ai/docs/issue-4-plan.md +44 -0
  13. package/.ai/docs/marked-renderer-debug.md +15 -0
  14. package/.ai/docs/marked-renderer-refactor-plan.md +64 -0
  15. package/.ai/docs/memory-use-cases.md +55 -0
  16. package/.ai/docs/prompt-consistency.md +31 -0
  17. package/.ai/docs/refactoring-tools.md +98 -0
  18. package/.ai/docs/system-prompt-update.md +174 -0
  19. package/.ai/docs/system_prompt.txt +210 -0
  20. package/.ai/docs/tasks.md +49 -0
  21. package/.ai/plan.md +131 -0
  22. package/.ai/prompt.md +1 -0
  23. package/.ai/scripts/fetch_models.js +27 -0
  24. package/.ai/scripts/generateSystemPrompt.ts +15 -0
  25. package/.ai/scripts/list-tools.mjs +4 -0
  26. package/.ai/scripts/p5_geometric_shapes.js +149 -0
  27. package/.husky/commit-msg +1 -0
  28. package/.husky/pre-commit +3 -0
  29. package/.husky/pre-push +1 -0
  30. package/.ignore +4 -0
  31. package/AGENTS.md +25 -0
  32. package/ARCHITECTURE.md +304 -0
  33. package/LICENSE +21 -0
  34. package/README.md +392 -0
  35. package/TODO.md +2 -0
  36. package/biome.json +61 -0
  37. package/commitlint.config.js +3 -0
  38. package/dist/cli.d.ts +19 -0
  39. package/dist/cli.js +116 -0
  40. package/dist/commands/application-log-command.d.ts +2 -0
  41. package/dist/commands/application-log-command.js +43 -0
  42. package/dist/commands/clear-command.d.ts +2 -0
  43. package/dist/commands/clear-command.js +12 -0
  44. package/dist/commands/compact-command.d.ts +2 -0
  45. package/dist/commands/compact-command.js +51 -0
  46. package/dist/commands/copy-command.d.ts +2 -0
  47. package/dist/commands/copy-command.js +51 -0
  48. package/dist/commands/edit-command.d.ts +2 -0
  49. package/dist/commands/edit-command.js +53 -0
  50. package/dist/commands/edit-prompt-command.d.ts +2 -0
  51. package/dist/commands/edit-prompt-command.js +25 -0
  52. package/dist/commands/exit-command.d.ts +2 -0
  53. package/dist/commands/exit-command.js +14 -0
  54. package/dist/commands/files-command.d.ts +2 -0
  55. package/dist/commands/files-command.js +63 -0
  56. package/dist/commands/generate-rules-command.d.ts +2 -0
  57. package/dist/commands/generate-rules-command.js +61 -0
  58. package/dist/commands/help-command.d.ts +2 -0
  59. package/dist/commands/help-command.js +19 -0
  60. package/dist/commands/init-command.d.ts +2 -0
  61. package/dist/commands/init-command.js +40 -0
  62. package/dist/commands/last-log-command.d.ts +2 -0
  63. package/dist/commands/last-log-command.js +76 -0
  64. package/dist/commands/manager.d.ts +22 -0
  65. package/dist/commands/manager.js +123 -0
  66. package/dist/commands/model-command.d.ts +2 -0
  67. package/dist/commands/model-command.js +84 -0
  68. package/dist/commands/paste-command.d.ts +2 -0
  69. package/dist/commands/paste-command.js +40 -0
  70. package/dist/commands/prompt-command.d.ts +2 -0
  71. package/dist/commands/prompt-command.js +111 -0
  72. package/dist/commands/reset-command.d.ts +2 -0
  73. package/dist/commands/reset-command.js +16 -0
  74. package/dist/commands/rules-command.d.ts +2 -0
  75. package/dist/commands/rules-command.js +68 -0
  76. package/dist/commands/save-command.d.ts +2 -0
  77. package/dist/commands/save-command.js +14 -0
  78. package/dist/commands/types.d.ts +26 -0
  79. package/dist/commands/types.js +1 -0
  80. package/dist/commands/usage-command.d.ts +2 -0
  81. package/dist/commands/usage-command.js +21 -0
  82. package/dist/config.d.ts +60 -0
  83. package/dist/config.js +193 -0
  84. package/dist/conversation-analyzer.d.ts +10 -0
  85. package/dist/conversation-analyzer.js +88 -0
  86. package/dist/dedent.d.ts +3 -0
  87. package/dist/dedent.js +38 -0
  88. package/dist/formatting.d.ts +17 -0
  89. package/dist/formatting.js +103 -0
  90. package/dist/index.d.ts +18 -0
  91. package/dist/index.js +213 -0
  92. package/dist/logger.d.ts +2 -0
  93. package/dist/logger.js +24 -0
  94. package/dist/mentions.d.ts +9 -0
  95. package/dist/mentions.js +182 -0
  96. package/dist/messages.d.ts +69 -0
  97. package/dist/messages.js +261 -0
  98. package/dist/middleware/audit-message.d.ts +5 -0
  99. package/dist/middleware/audit-message.js +95 -0
  100. package/dist/middleware/index.d.ts +2 -0
  101. package/dist/middleware/index.js +2 -0
  102. package/dist/middleware/rate-limit.d.ts +4 -0
  103. package/dist/middleware/rate-limit.js +17 -0
  104. package/dist/models/ai-config.d.ts +12 -0
  105. package/dist/models/ai-config.js +87 -0
  106. package/dist/models/anthropic-provider.d.ts +25 -0
  107. package/dist/models/anthropic-provider.js +184 -0
  108. package/dist/models/deepseek-provider.d.ts +20 -0
  109. package/dist/models/deepseek-provider.js +42 -0
  110. package/dist/models/google-provider.d.ts +19 -0
  111. package/dist/models/google-provider.js +56 -0
  112. package/dist/models/manager.d.ts +15 -0
  113. package/dist/models/manager.js +48 -0
  114. package/dist/models/openai-provider.d.ts +22 -0
  115. package/dist/models/openai-provider.js +70 -0
  116. package/dist/models/openrouter-provider.d.ts +36 -0
  117. package/dist/models/openrouter-provider.js +276 -0
  118. package/dist/models/providers.d.ts +33 -0
  119. package/dist/models/providers.js +116 -0
  120. package/dist/models/xai-provider.d.ts +20 -0
  121. package/dist/models/xai-provider.js +47 -0
  122. package/dist/parsing.d.ts +2 -0
  123. package/dist/parsing.js +18 -0
  124. package/dist/prompts/manager.d.ts +19 -0
  125. package/dist/prompts/manager.js +71 -0
  126. package/dist/prompts.d.ts +4 -0
  127. package/dist/prompts.js +158 -0
  128. package/dist/repl-prompt.d.ts +14 -0
  129. package/dist/repl-prompt.js +147 -0
  130. package/dist/repl.d.ts +27 -0
  131. package/dist/repl.js +431 -0
  132. package/dist/source/cli.d.ts +19 -0
  133. package/dist/source/cli.js +116 -0
  134. package/dist/source/commands/application-log-command.d.ts +2 -0
  135. package/dist/source/commands/application-log-command.js +43 -0
  136. package/dist/source/commands/clear-command.d.ts +2 -0
  137. package/dist/source/commands/clear-command.js +12 -0
  138. package/dist/source/commands/compact-command.d.ts +2 -0
  139. package/dist/source/commands/compact-command.js +51 -0
  140. package/dist/source/commands/copy-command.d.ts +2 -0
  141. package/dist/source/commands/copy-command.js +51 -0
  142. package/dist/source/commands/edit-command.d.ts +2 -0
  143. package/dist/source/commands/edit-command.js +53 -0
  144. package/dist/source/commands/edit-prompt-command.d.ts +2 -0
  145. package/dist/source/commands/edit-prompt-command.js +25 -0
  146. package/dist/source/commands/exit-command.d.ts +2 -0
  147. package/dist/source/commands/exit-command.js +14 -0
  148. package/dist/source/commands/files-command.d.ts +2 -0
  149. package/dist/source/commands/files-command.js +63 -0
  150. package/dist/source/commands/generate-rules-command.d.ts +2 -0
  151. package/dist/source/commands/generate-rules-command.js +61 -0
  152. package/dist/source/commands/help-command.d.ts +2 -0
  153. package/dist/source/commands/help-command.js +19 -0
  154. package/dist/source/commands/init-command.d.ts +2 -0
  155. package/dist/source/commands/init-command.js +40 -0
  156. package/dist/source/commands/last-log-command.d.ts +2 -0
  157. package/dist/source/commands/last-log-command.js +76 -0
  158. package/dist/source/commands/manager.d.ts +22 -0
  159. package/dist/source/commands/manager.js +123 -0
  160. package/dist/source/commands/model-command.d.ts +2 -0
  161. package/dist/source/commands/model-command.js +84 -0
  162. package/dist/source/commands/paste-command.d.ts +2 -0
  163. package/dist/source/commands/paste-command.js +40 -0
  164. package/dist/source/commands/prompt-command.d.ts +2 -0
  165. package/dist/source/commands/prompt-command.js +111 -0
  166. package/dist/source/commands/reset-command.d.ts +2 -0
  167. package/dist/source/commands/reset-command.js +16 -0
  168. package/dist/source/commands/rules-command.d.ts +2 -0
  169. package/dist/source/commands/rules-command.js +68 -0
  170. package/dist/source/commands/save-command.d.ts +2 -0
  171. package/dist/source/commands/save-command.js +14 -0
  172. package/dist/source/commands/types.d.ts +26 -0
  173. package/dist/source/commands/types.js +1 -0
  174. package/dist/source/commands/usage-command.d.ts +2 -0
  175. package/dist/source/commands/usage-command.js +21 -0
  176. package/dist/source/config.d.ts +60 -0
  177. package/dist/source/config.js +193 -0
  178. package/dist/source/conversation-analyzer.d.ts +10 -0
  179. package/dist/source/conversation-analyzer.js +88 -0
  180. package/dist/source/dedent.d.ts +3 -0
  181. package/dist/source/dedent.js +38 -0
  182. package/dist/source/formatting.d.ts +17 -0
  183. package/dist/source/formatting.js +103 -0
  184. package/dist/source/index.d.ts +18 -0
  185. package/dist/source/index.js +213 -0
  186. package/dist/source/logger.d.ts +2 -0
  187. package/dist/source/logger.js +24 -0
  188. package/dist/source/mentions.d.ts +9 -0
  189. package/dist/source/mentions.js +182 -0
  190. package/dist/source/messages.d.ts +69 -0
  191. package/dist/source/messages.js +261 -0
  192. package/dist/source/middleware/audit-message.d.ts +5 -0
  193. package/dist/source/middleware/audit-message.js +95 -0
  194. package/dist/source/middleware/index.d.ts +2 -0
  195. package/dist/source/middleware/index.js +2 -0
  196. package/dist/source/middleware/rate-limit.d.ts +4 -0
  197. package/dist/source/middleware/rate-limit.js +17 -0
  198. package/dist/source/models/ai-config.d.ts +12 -0
  199. package/dist/source/models/ai-config.js +87 -0
  200. package/dist/source/models/anthropic-provider.d.ts +25 -0
  201. package/dist/source/models/anthropic-provider.js +184 -0
  202. package/dist/source/models/deepseek-provider.d.ts +20 -0
  203. package/dist/source/models/deepseek-provider.js +42 -0
  204. package/dist/source/models/google-provider.d.ts +19 -0
  205. package/dist/source/models/google-provider.js +56 -0
  206. package/dist/source/models/manager.d.ts +15 -0
  207. package/dist/source/models/manager.js +48 -0
  208. package/dist/source/models/openai-provider.d.ts +22 -0
  209. package/dist/source/models/openai-provider.js +70 -0
  210. package/dist/source/models/openrouter-provider.d.ts +36 -0
  211. package/dist/source/models/openrouter-provider.js +276 -0
  212. package/dist/source/models/providers.d.ts +33 -0
  213. package/dist/source/models/providers.js +116 -0
  214. package/dist/source/models/xai-provider.d.ts +20 -0
  215. package/dist/source/models/xai-provider.js +47 -0
  216. package/dist/source/parsing.d.ts +2 -0
  217. package/dist/source/parsing.js +18 -0
  218. package/dist/source/prompts/manager.d.ts +19 -0
  219. package/dist/source/prompts/manager.js +71 -0
  220. package/dist/source/prompts.d.ts +4 -0
  221. package/dist/source/prompts.js +158 -0
  222. package/dist/source/repl-prompt.d.ts +14 -0
  223. package/dist/source/repl-prompt.js +147 -0
  224. package/dist/source/repl.d.ts +27 -0
  225. package/dist/source/repl.js +431 -0
  226. package/dist/source/terminal/formatting.d.ts +37 -0
  227. package/dist/source/terminal/formatting.js +106 -0
  228. package/dist/source/terminal/index.d.ts +94 -0
  229. package/dist/source/terminal/index.js +420 -0
  230. package/dist/source/terminal/markdown-utils.d.ts +2 -0
  231. package/dist/source/terminal/markdown-utils.js +81 -0
  232. package/dist/source/terminal/markdown.d.ts +1 -0
  233. package/dist/source/terminal/markdown.js +111 -0
  234. package/dist/source/terminal/types.d.ts +71 -0
  235. package/dist/source/terminal/types.js +1 -0
  236. package/dist/source/terminal-output.d.ts +8 -0
  237. package/dist/source/terminal-output.js +213 -0
  238. package/dist/source/terminal-output.test.d.ts +8 -0
  239. package/dist/source/terminal-output.test.js +213 -0
  240. package/dist/source/token-tracker.d.ts +14 -0
  241. package/dist/source/token-tracker.js +53 -0
  242. package/dist/source/token-utils.d.ts +7 -0
  243. package/dist/source/token-utils.js +13 -0
  244. package/dist/source/tools/agent.d.ts +17 -0
  245. package/dist/source/tools/agent.js +87 -0
  246. package/dist/source/tools/bash.d.ts +19 -0
  247. package/dist/source/tools/bash.js +294 -0
  248. package/dist/source/tools/code-interpreter.d.ts +12 -0
  249. package/dist/source/tools/code-interpreter.js +131 -0
  250. package/dist/source/tools/command-validation.d.ts +8 -0
  251. package/dist/source/tools/command-validation.js +69 -0
  252. package/dist/source/tools/delete-file.d.ts +12 -0
  253. package/dist/source/tools/delete-file.js +56 -0
  254. package/dist/source/tools/directory-tree.d.ts +12 -0
  255. package/dist/source/tools/directory-tree.js +38 -0
  256. package/dist/source/tools/edit-file.d.ts +19 -0
  257. package/dist/source/tools/edit-file.js +107 -0
  258. package/dist/source/tools/filesystem-utils.d.ts +22 -0
  259. package/dist/source/tools/filesystem-utils.js +191 -0
  260. package/dist/source/tools/git-utils.d.ts +14 -0
  261. package/dist/source/tools/git-utils.js +64 -0
  262. package/dist/source/tools/grep.d.ts +17 -0
  263. package/dist/source/tools/grep.js +138 -0
  264. package/dist/source/tools/index.d.ts +161 -0
  265. package/dist/source/tools/index.js +209 -0
  266. package/dist/source/tools/memory-read.d.ts +13 -0
  267. package/dist/source/tools/memory-read.js +135 -0
  268. package/dist/source/tools/memory-write.d.ts +12 -0
  269. package/dist/source/tools/memory-write.js +83 -0
  270. package/dist/source/tools/move-file.d.ts +13 -0
  271. package/dist/source/tools/move-file.js +44 -0
  272. package/dist/source/tools/read-file.d.ts +17 -0
  273. package/dist/source/tools/read-file.js +86 -0
  274. package/dist/source/tools/read-multiple-files.d.ts +14 -0
  275. package/dist/source/tools/read-multiple-files.js +55 -0
  276. package/dist/source/tools/save-file.d.ts +17 -0
  277. package/dist/source/tools/save-file.js +98 -0
  278. package/dist/source/tools/think.d.ts +11 -0
  279. package/dist/source/tools/think.js +45 -0
  280. package/dist/source/tools/types.d.ts +29 -0
  281. package/dist/source/tools/types.js +14 -0
  282. package/dist/source/tools/web-fetch.d.ts +47 -0
  283. package/dist/source/tools/web-fetch.js +246 -0
  284. package/dist/source/tools/web-search.d.ts +13 -0
  285. package/dist/source/tools/web-search.js +80 -0
  286. package/dist/source/utils/process.d.ts +36 -0
  287. package/dist/source/utils/process.js +75 -0
  288. package/dist/source/version.d.ts +1 -0
  289. package/dist/source/version.js +21 -0
  290. package/dist/terminal/formatting.d.ts +37 -0
  291. package/dist/terminal/formatting.js +106 -0
  292. package/dist/terminal/index.d.ts +94 -0
  293. package/dist/terminal/index.js +420 -0
  294. package/dist/terminal/markdown-utils.d.ts +2 -0
  295. package/dist/terminal/markdown-utils.js +81 -0
  296. package/dist/terminal/markdown.d.ts +1 -0
  297. package/dist/terminal/markdown.js +111 -0
  298. package/dist/terminal/types.d.ts +71 -0
  299. package/dist/terminal/types.js +1 -0
  300. package/dist/terminal-output.d.ts +8 -0
  301. package/dist/terminal-output.js +213 -0
  302. package/dist/token-tracker.d.ts +14 -0
  303. package/dist/token-tracker.js +53 -0
  304. package/dist/token-utils.d.ts +7 -0
  305. package/dist/token-utils.js +13 -0
  306. package/dist/tools/agent.d.ts +17 -0
  307. package/dist/tools/agent.js +87 -0
  308. package/dist/tools/bash.d.ts +19 -0
  309. package/dist/tools/bash.js +294 -0
  310. package/dist/tools/code-interpreter.d.ts +12 -0
  311. package/dist/tools/code-interpreter.js +131 -0
  312. package/dist/tools/command-validation.d.ts +8 -0
  313. package/dist/tools/command-validation.js +69 -0
  314. package/dist/tools/delete-file.d.ts +12 -0
  315. package/dist/tools/delete-file.js +56 -0
  316. package/dist/tools/directory-tree.d.ts +12 -0
  317. package/dist/tools/directory-tree.js +38 -0
  318. package/dist/tools/edit-file.d.ts +19 -0
  319. package/dist/tools/edit-file.js +107 -0
  320. package/dist/tools/filesystem-utils.d.ts +22 -0
  321. package/dist/tools/filesystem-utils.js +191 -0
  322. package/dist/tools/git-utils.d.ts +14 -0
  323. package/dist/tools/git-utils.js +64 -0
  324. package/dist/tools/grep.d.ts +17 -0
  325. package/dist/tools/grep.js +138 -0
  326. package/dist/tools/index.d.ts +161 -0
  327. package/dist/tools/index.js +209 -0
  328. package/dist/tools/memory-read.d.ts +13 -0
  329. package/dist/tools/memory-read.js +135 -0
  330. package/dist/tools/memory-write.d.ts +12 -0
  331. package/dist/tools/memory-write.js +83 -0
  332. package/dist/tools/move-file.d.ts +13 -0
  333. package/dist/tools/move-file.js +44 -0
  334. package/dist/tools/read-file.d.ts +17 -0
  335. package/dist/tools/read-file.js +86 -0
  336. package/dist/tools/read-multiple-files.d.ts +14 -0
  337. package/dist/tools/read-multiple-files.js +55 -0
  338. package/dist/tools/save-file.d.ts +17 -0
  339. package/dist/tools/save-file.js +98 -0
  340. package/dist/tools/think.d.ts +11 -0
  341. package/dist/tools/think.js +45 -0
  342. package/dist/tools/types.d.ts +29 -0
  343. package/dist/tools/types.js +14 -0
  344. package/dist/tools/web-fetch.d.ts +47 -0
  345. package/dist/tools/web-fetch.js +246 -0
  346. package/dist/tools/web-search.d.ts +13 -0
  347. package/dist/tools/web-search.js +80 -0
  348. package/dist/utils/process.d.ts +36 -0
  349. package/dist/utils/process.js +75 -0
  350. package/dist/version.d.ts +1 -0
  351. package/dist/version.js +21 -0
  352. package/knip.json +5 -0
  353. package/package.json +83 -0
  354. package/source/cli.ts +172 -0
  355. package/source/commands/application-log-command.ts +53 -0
  356. package/source/commands/clear-command.ts +14 -0
  357. package/source/commands/compact-command.ts +64 -0
  358. package/source/commands/copy-command.ts +55 -0
  359. package/source/commands/edit-command.ts +63 -0
  360. package/source/commands/edit-prompt-command.ts +31 -0
  361. package/source/commands/exit-command.ts +18 -0
  362. package/source/commands/files-command.ts +85 -0
  363. package/source/commands/generate-rules-command.ts +82 -0
  364. package/source/commands/help-command.ts +27 -0
  365. package/source/commands/init-command.ts +48 -0
  366. package/source/commands/last-log-command.ts +88 -0
  367. package/source/commands/manager.ts +151 -0
  368. package/source/commands/model-command.ts +123 -0
  369. package/source/commands/paste-command.ts +62 -0
  370. package/source/commands/prompt-command.ts +150 -0
  371. package/source/commands/reset-command.ts +22 -0
  372. package/source/commands/rules-command.ts +76 -0
  373. package/source/commands/save-command.ts +20 -0
  374. package/source/commands/types.ts +28 -0
  375. package/source/commands/usage-command.ts +26 -0
  376. package/source/config.ts +223 -0
  377. package/source/conversation-analyzer.ts +115 -0
  378. package/source/dedent.ts +53 -0
  379. package/source/formatting.ts +132 -0
  380. package/source/index.ts +240 -0
  381. package/source/logger.ts +29 -0
  382. package/source/mentions.ts +227 -0
  383. package/source/messages.ts +360 -0
  384. package/source/middleware/audit-message.ts +133 -0
  385. package/source/middleware/index.ts +2 -0
  386. package/source/middleware/rate-limit.ts +24 -0
  387. package/source/models/ai-config.ts +109 -0
  388. package/source/models/anthropic-provider.ts +199 -0
  389. package/source/models/deepseek-provider.ts +53 -0
  390. package/source/models/google-provider.ts +68 -0
  391. package/source/models/manager.ts +84 -0
  392. package/source/models/openai-provider.ts +81 -0
  393. package/source/models/openrouter-provider.ts +288 -0
  394. package/source/models/providers.ts +197 -0
  395. package/source/models/xai-provider.ts +59 -0
  396. package/source/parsing.ts +20 -0
  397. package/source/prompts/manager.ts +90 -0
  398. package/source/prompts.ts +172 -0
  399. package/source/repl-prompt.ts +196 -0
  400. package/source/repl.ts +572 -0
  401. package/source/terminal/formatting.ts +121 -0
  402. package/source/terminal/index.ts +518 -0
  403. package/source/terminal/markdown-utils.ts +89 -0
  404. package/source/terminal/markdown.ts +155 -0
  405. package/source/terminal/types.ts +84 -0
  406. package/source/terminal-output.test.ts +266 -0
  407. package/source/token-tracker.ts +78 -0
  408. package/source/token-utils.ts +17 -0
  409. package/source/tools/agent.ts +107 -0
  410. package/source/tools/bash.ts +367 -0
  411. package/source/tools/code-interpreter.ts +172 -0
  412. package/source/tools/command-validation.ts +81 -0
  413. package/source/tools/delete-file.ts +71 -0
  414. package/source/tools/directory-tree.ts +54 -0
  415. package/source/tools/edit-file.ts +155 -0
  416. package/source/tools/filesystem-utils.ts +265 -0
  417. package/source/tools/git-utils.ts +70 -0
  418. package/source/tools/grep.ts +184 -0
  419. package/source/tools/index.ts +278 -0
  420. package/source/tools/memory-read.ts +174 -0
  421. package/source/tools/memory-write.ts +105 -0
  422. package/source/tools/move-file.ts +59 -0
  423. package/source/tools/read-file.ts +129 -0
  424. package/source/tools/read-multiple-files.ts +80 -0
  425. package/source/tools/save-file.ts +147 -0
  426. package/source/tools/think.ts +51 -0
  427. package/source/tools/types.ts +58 -0
  428. package/source/tools/web-fetch.ts +327 -0
  429. package/source/tools/web-search.ts +101 -0
  430. package/source/utils/process.ts +121 -0
  431. package/source/version.ts +21 -0
  432. package/test/commands/copy-command.test.ts +69 -0
  433. package/test/config.test.ts +200 -0
  434. package/test/terminal/markdown-utils.test.ts +124 -0
  435. package/test/tools/bash-tool.test.ts +58 -0
  436. package/test/tools/code-interpreter.test.ts +91 -0
  437. package/test/tools/command-validation.test.ts +48 -0
  438. package/tsconfig.build.json +9 -0
  439. package/tsconfig.json +30 -0
@@ -0,0 +1,518 @@
1
+ /**
2
+ * Terminal Interface Module
3
+ *
4
+ * Provides a user interface for interacting with Claude Code in the terminal.
5
+ * Handles input/output, formatting, and display.
6
+ */
7
+
8
+ import chalk, { type ChalkInstance } from "chalk";
9
+ import Table from "cli-table3";
10
+ import ora from "ora";
11
+ import wrapAnsi from "wrap-ansi";
12
+ import { logger } from "../logger.ts";
13
+ import { getPackageVersion } from "../version.ts";
14
+ import {
15
+ clearTerminal,
16
+ getTerminalSize,
17
+ setTerminalTitle,
18
+ link as terminalLink,
19
+ } from "./formatting.ts";
20
+ import { applyMarkdown } from "./markdown.ts";
21
+ import type { SpinnerInstance, TerminalConfig } from "./types.ts";
22
+
23
+ /**
24
+ * Initialize the terminal interface
25
+ */
26
+ export function initTerminal(config: Partial<TerminalConfig> = {}): Terminal {
27
+ logger.debug("Initializing terminal interface");
28
+
29
+ const terminalConfig: TerminalConfig = {
30
+ theme: config.theme || "system",
31
+ useColors: config.useColors !== false,
32
+ showProgressIndicators: config.showProgressIndicators !== false,
33
+ codeHighlighting: config.codeHighlighting !== false,
34
+ maxHeight: config.maxHeight,
35
+ maxWidth: config.maxWidth,
36
+ };
37
+
38
+ const terminal = new Terminal(terminalConfig);
39
+
40
+ try {
41
+ // Detect terminal capabilities
42
+ terminal.detectCapabilities();
43
+
44
+ return terminal;
45
+ } catch (error) {
46
+ logger.warn(error, "Error initializing terminal interface:");
47
+
48
+ // Return a basic terminal interface even if there was an error
49
+ return terminal;
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Terminal class for handling user interaction
55
+ */
56
+ export class Terminal {
57
+ private config: TerminalConfig;
58
+ private activeSpinners: Map<string, SpinnerInstance> = new Map();
59
+ private terminalWidth: number;
60
+ private terminalHeight: number;
61
+ private isInteractive: boolean;
62
+
63
+ constructor(config: TerminalConfig) {
64
+ this.config = config;
65
+
66
+ // Get initial terminal size
67
+ const { rows, columns } = getTerminalSize();
68
+ this.terminalHeight = config.maxHeight || rows;
69
+ this.terminalWidth = config.maxWidth || columns;
70
+
71
+ // Assume interactive by default
72
+ this.isInteractive = process.stdout.isTTY && process.stdin.isTTY;
73
+
74
+ // Listen for terminal resize events
75
+ process.stdout.on("resize", () => {
76
+ const { rows, columns } = getTerminalSize();
77
+ this.terminalHeight = config.maxHeight || rows;
78
+ this.terminalWidth = config.maxWidth || columns;
79
+ logger.debug(`Terminal resized to ${columns}x${rows}`);
80
+ });
81
+ }
82
+
83
+ /**
84
+ * Detect terminal capabilities
85
+ */
86
+ detectCapabilities() {
87
+ // Check if the terminal is interactive
88
+ this.isInteractive = Boolean(process.stdout.isTTY && process.stdin.isTTY);
89
+
90
+ logger.debug(
91
+ {
92
+ isInteractive: this.isInteractive,
93
+ colorSupport: this.config.useColors ? "yes" : "no",
94
+ size: `${this.terminalWidth}x${this.terminalHeight}`,
95
+ },
96
+ "Terminal capabilities detected",
97
+ );
98
+ }
99
+
100
+ setTitle(title: string) {
101
+ setTerminalTitle(title);
102
+ }
103
+
104
+ getLogo(): string {
105
+ return `
106
+ █████╗ ██████╗ █████╗ ██╗
107
+ ██╔══██╗██╔════╝██╔══██╗██║
108
+ ███████║██║ ███████║██║
109
+ ██╔══██║██║ ██╔══██║██║
110
+ ██║ ██║╚██████╗██║ ██║██║
111
+ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝
112
+ `;
113
+ }
114
+
115
+ /**
116
+ * Display the welcome message
117
+ */
118
+ displayWelcome(): void {
119
+ this.clear();
120
+
121
+ const version = getPackageVersion();
122
+
123
+ this.writeln(chalk.magenta(this.getLogo()));
124
+ this.lineBreak();
125
+ this.writeln(chalk.magenta("Greetings! I am acai."));
126
+ this.writeln(chalk.gray(` Version ${version}`));
127
+ this.lineBreak();
128
+
129
+ this.writeln(
130
+ chalk.white(` Type ${chalk.cyan("/help")} to see available commands.`),
131
+ );
132
+ this.writeln(
133
+ chalk.white(
134
+ " You can ask acai to explain code, fix issues, or perform tasks.",
135
+ ),
136
+ );
137
+ this.writeln(
138
+ chalk.white(
139
+ ` Example: "${chalk.italic("Please analyze this codebase and explain its structure.")}"`,
140
+ ),
141
+ );
142
+ this.writeln(chalk.dim(" Use Ctrl+C to interrupt acai and exit."));
143
+
144
+ this.lineBreak();
145
+
146
+ this.writeln(
147
+ chalk.yellow(`The current working directory is ${process.cwd()}`),
148
+ );
149
+
150
+ this.lineBreak();
151
+ }
152
+
153
+ /**
154
+ * Clear the terminal screen
155
+ */
156
+ clear(): void {
157
+ if (this.isInteractive) {
158
+ clearTerminal();
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Display formatted content
164
+ */
165
+ display(content: string, wrap = false): void {
166
+ this.writeln(this.formatMarkdown(content, wrap));
167
+ }
168
+
169
+ /**
170
+ * Display a message with emphasis
171
+ */
172
+ emphasize(message: string): void {
173
+ if (this.config.useColors) {
174
+ this.writeln(chalk.cyan.bold(message));
175
+ } else {
176
+ this.writeln(message.toUpperCase());
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Display an informational message
182
+ */
183
+ info(message: string): void {
184
+ if (this.config.useColors) {
185
+ this.writeln(chalk.blue(`ℹ ${message}`));
186
+ } else {
187
+ this.writeln(`INFO: ${message}`);
188
+ }
189
+ }
190
+
191
+ /**
192
+ * Display a success message
193
+ */
194
+ success(message: string): void {
195
+ if (this.config.useColors) {
196
+ this.writeln(chalk.green(`✓ ${message}`));
197
+ } else {
198
+ this.writeln(`SUCCESS: ${message}`);
199
+ }
200
+ }
201
+
202
+ /**
203
+ * Display a warning message
204
+ */
205
+ warn(message: string): void {
206
+ if (this.config.useColors) {
207
+ this.writeln(chalk.yellow(`⚠ ${message}`));
208
+ } else {
209
+ this.writeln(`WARNING: ${message}`);
210
+ }
211
+ }
212
+
213
+ /**
214
+ * Display an error message
215
+ */
216
+ error(message: string): void {
217
+ if (this.config.useColors) {
218
+ this.writeln(chalk.red(`✗ ${message}`));
219
+ } else {
220
+ this.writeln(`ERROR: ${message}`);
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Emits an alert.
226
+ */
227
+ alert(): void {
228
+ if (!this.isInteractive) {
229
+ return;
230
+ }
231
+
232
+ const t = "acai";
233
+ const b = "";
234
+ try {
235
+ process.stdout.write("\x07");
236
+ const esc = "\u001b";
237
+ const bel = "\u0007";
238
+ const safe = (s: string) =>
239
+ s.replaceAll("\u0007", "").replaceAll("\u001b", "");
240
+ const payload = `${esc}]777;notify;${safe(t)};${safe(b)}${bel}`;
241
+ process.stdout.write(payload);
242
+ } catch (err) {
243
+ logger.warn({ err }, "Failed to emit alert");
244
+ }
245
+ }
246
+
247
+ write(input: string): void {
248
+ process.stdout.write(input);
249
+ }
250
+
251
+ writeln(input: string): void {
252
+ process.stdout.write(`${input}\n`);
253
+ }
254
+
255
+ lineBreak() {
256
+ this.writeln("");
257
+ }
258
+
259
+ header(header: string, chalkFn: ChalkInstance = chalk.green): void {
260
+ const cols = this.terminalWidth > 0 ? this.terminalWidth : 80;
261
+ const width = Math.max(0, cols - header.length - 4);
262
+ this.writeln(chalkFn(`\n── ${header} ${"─".repeat(width)} `));
263
+ }
264
+
265
+ async box(header: string, content: string): Promise<void> {
266
+ const cols = this.terminalWidth > 0 ? this.terminalWidth : 80;
267
+ const width = Math.max(4, cols - 4);
268
+
269
+ // Helper to strip ANSI sequences for accurate visible-width calculation
270
+ const stripAnsi = (s: string): string =>
271
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: need to detect ansi control characters
272
+ s.replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, "");
273
+
274
+ const paddedHeader = ` ${header} `;
275
+ const headerVisibleLen = stripAnsi(paddedHeader).length;
276
+ const headerStartPos = 1;
277
+
278
+ // Top border with header (use visible header length)
279
+ const leftDashes = headerStartPos;
280
+ const rightDashes = Math.max(0, width - leftDashes - headerVisibleLen);
281
+ const topBorder = `┌${"─".repeat(leftDashes)}${paddedHeader}${"─".repeat(rightDashes)}┐`;
282
+
283
+ // Prepare inner content: format markdown first, then wrap to inner width
284
+ const innerWidth = Math.max(1, width - 2);
285
+ const formatted = applyMarkdown(content);
286
+ const wrapped = wrapAnsi(formatted, innerWidth, { trim: false });
287
+
288
+ const contentLines = wrapped
289
+ .split("\n")
290
+ .map((line) => {
291
+ const visibleLen = stripAnsi(line).length;
292
+ const padCount = Math.max(0, innerWidth - visibleLen);
293
+ return `│ ${line}${" ".repeat(padCount)} │`;
294
+ })
295
+ .join("\n");
296
+
297
+ // Bottom border
298
+ const bottomBorder = `└${"─".repeat(width)}┘`;
299
+
300
+ // Write the box
301
+ this.writeln(`${topBorder}\n${contentLines}\n${bottomBorder}`);
302
+ }
303
+
304
+ hr(chalkFn: ChalkInstance = chalk.gray): void {
305
+ const cols = this.terminalWidth > 0 ? this.terminalWidth : 80;
306
+ this.writeln(chalkFn(`${"─".repeat(Math.max(1, cols - 1))} `));
307
+ }
308
+
309
+ /**
310
+ * Create a clickable link in the terminal if supported
311
+ */
312
+ link(text: string, url: string): string {
313
+ return terminalLink(text, url);
314
+ }
315
+
316
+ /**
317
+ * Display a table of data
318
+ */
319
+ table(
320
+ data: [string, string | number][],
321
+ options: { header?: string[]; colWidths?: number[] } = {},
322
+ ): void {
323
+ const { header, colWidths } = options;
324
+ // Calculate column widths based on terminal width
325
+ const padding = 5; // Account for table borders and padding
326
+ const availableWidth = Math.max(10, this.terminalWidth - padding);
327
+ const colCount = header?.length ?? 1;
328
+ const width = Math.max(
329
+ 10,
330
+ Math.floor(availableWidth / Math.max(1, colCount)),
331
+ );
332
+ const computedColWidths: number[] = colWidths
333
+ ? colWidths.map((percent) =>
334
+ Math.max(10, Math.floor((percent / 100) * availableWidth)),
335
+ )
336
+ : new Array(colCount).fill(width);
337
+
338
+ const table = new Table({
339
+ head: header,
340
+ colWidths: computedColWidths,
341
+ wordWrap: true, // Enable word wrapping for the description column
342
+ });
343
+
344
+ table.push(...data);
345
+
346
+ this.writeln(table.toString());
347
+ }
348
+
349
+ /**
350
+ * Create a spinner for showing progress
351
+ */
352
+ spinner(text: string, id = "default"): SpinnerInstance {
353
+ // Clean up existing spinner with the same ID
354
+ if (this.activeSpinners.has(id)) {
355
+ this.activeSpinners.get(id)?.stop();
356
+ this.activeSpinners.delete(id);
357
+ }
358
+
359
+ // Create spinner only if progress indicators are enabled and terminal is interactive
360
+ if (this.config.showProgressIndicators && this.isInteractive) {
361
+ const spinner = ora({
362
+ text,
363
+ spinner: "dots",
364
+ color: "cyan",
365
+ }).start();
366
+
367
+ const spinnerInstance: SpinnerInstance = {
368
+ id,
369
+ update: (newText: string) => {
370
+ spinner.text = newText;
371
+ return spinnerInstance;
372
+ },
373
+ succeed: (text?: string) => {
374
+ spinner.succeed(text);
375
+ this.activeSpinners.delete(id);
376
+ return spinnerInstance;
377
+ },
378
+ fail: (text?: string) => {
379
+ spinner.fail(text);
380
+ this.activeSpinners.delete(id);
381
+ return spinnerInstance;
382
+ },
383
+ warn: (text?: string) => {
384
+ spinner.warn(text);
385
+ this.activeSpinners.delete(id);
386
+ return spinnerInstance;
387
+ },
388
+ info: (text?: string) => {
389
+ spinner.info(text);
390
+ this.activeSpinners.delete(id);
391
+ return spinnerInstance;
392
+ },
393
+ clear: () => {
394
+ spinner.clear();
395
+ this.activeSpinners.delete(id);
396
+ return spinnerInstance;
397
+ },
398
+ stop: () => {
399
+ spinner.stop();
400
+ this.activeSpinners.delete(id);
401
+ return spinnerInstance;
402
+ },
403
+ };
404
+
405
+ this.activeSpinners.set(id, spinnerInstance);
406
+ return spinnerInstance;
407
+ }
408
+ // Fallback for non-interactive terminals or when progress indicators are disabled
409
+ console.info(text);
410
+
411
+ // Return a dummy spinner
412
+ const dummySpinner: SpinnerInstance = {
413
+ id,
414
+ update: (newText: string) => {
415
+ if (newText !== text) {
416
+ console.info(newText);
417
+ }
418
+ return dummySpinner;
419
+ },
420
+ succeed: (text?: string) => {
421
+ if (text) {
422
+ this.success(text);
423
+ }
424
+ return dummySpinner;
425
+ },
426
+ fail: (text?: string) => {
427
+ if (text) {
428
+ this.error(text);
429
+ }
430
+ return dummySpinner;
431
+ },
432
+ warn: (text?: string) => {
433
+ if (text) {
434
+ this.warn(text);
435
+ }
436
+ return dummySpinner;
437
+ },
438
+ info: (text?: string) => {
439
+ if (text) {
440
+ this.info(text);
441
+ }
442
+ return dummySpinner;
443
+ },
444
+ clear: () => {
445
+ return dummySpinner;
446
+ },
447
+ stop: () => {
448
+ return dummySpinner;
449
+ },
450
+ };
451
+
452
+ return dummySpinner;
453
+ }
454
+
455
+ /**
456
+ * Displays a horizontal progress bar in the console.
457
+ * @param current The current value.
458
+ * @param total The target value.
459
+ */
460
+ displayProgressBar(current: number, total: number): void {
461
+ const terminalWidth = this.terminalWidth > 0 ? this.terminalWidth : 80; // Default to 80 if columns not available
462
+
463
+ // Function to format numbers concisely (e.g., 1.2K, 5M)
464
+ const formatNumber = (num: number): string => {
465
+ if (num < 1000) {
466
+ return num.toString();
467
+ }
468
+ if (num < 1_000_000) {
469
+ return `${(num / 1000).toFixed(1)}K`;
470
+ }
471
+ if (num < 1_000_000_000) {
472
+ return `${(num / 1_000_000).toFixed(1)}M`;
473
+ }
474
+ return `${(num / 1_000_000_000).toFixed(1)}G`;
475
+ };
476
+
477
+ const currentFormatted = formatNumber(current);
478
+ const totalFormatted = formatNumber(total);
479
+ const progressText = `${currentFormatted}/${totalFormatted}`;
480
+ const progressTextLength = progressText.length + 1; // Add 1 for space
481
+
482
+ const progressBarMaxWidth = Math.max(
483
+ 1,
484
+ terminalWidth - progressTextLength - 1,
485
+ );
486
+
487
+ const percentage = total === 0 ? 1 : current / total;
488
+ const filledWidth = Math.max(
489
+ 0,
490
+ Math.min(
491
+ progressBarMaxWidth,
492
+ Math.floor(percentage * progressBarMaxWidth),
493
+ ),
494
+ );
495
+ const emptyWidth = Math.max(0, progressBarMaxWidth - filledWidth);
496
+
497
+ const a = chalk.yellow("─"); //"█"
498
+ const b = chalk.gray("─"); // "░"
499
+ const filledBar = a.repeat(filledWidth);
500
+ const emptyBar = b.repeat(emptyWidth);
501
+
502
+ // Use \r to move cursor to the beginning of the line for updates
503
+ this.writeln(`\r${filledBar}${emptyBar} ${progressText} `);
504
+ }
505
+
506
+ private formatMarkdown(content: string, wrap = false): string {
507
+ const columns = this.terminalWidth;
508
+ const formatted = applyMarkdown(content);
509
+
510
+ if (wrap) {
511
+ return wrapAnsi(formatted, columns - 6, { trim: false });
512
+ }
513
+ return formatted;
514
+ }
515
+ }
516
+
517
+ // Re-export the types
518
+ export * from "./types.ts";
@@ -0,0 +1,89 @@
1
+ const markdownHeaderRegex = /^#{1,6}\s/m;
2
+ const markdownBoldRegex = /(\*\*|__)(.*?)\1/;
3
+ const markdownItalicRegex = /(\*|_)(.*?)\1/;
4
+ const markdownCodeRegex = /`{1,3}[^`]+`{1,3}/;
5
+ const markdownLinkRegex = /\((.*?)\]\((.*?)\)/;
6
+ const markdownBlockquoteRegex = /^>\s/m;
7
+ const markdownUnorderedListRegex = /^-\s|\*\s|\+\s/m;
8
+ const markdownOrderedListRegex = /^\d+\.\s/m;
9
+ const markdownHorizontalRuleRegex = /^---$/m;
10
+ const markdownImageRegex = /!\[(.*?)\]\((.*?)\)/;
11
+
12
+ export function isMarkdown(input: string): boolean {
13
+ // Simple heuristics: look for common markdown syntax
14
+ const markdownPatterns = [
15
+ markdownHeaderRegex, // headings
16
+ markdownBoldRegex, // bold
17
+ markdownItalicRegex, // italic
18
+ markdownCodeRegex, // inline code or code block
19
+ markdownLinkRegex, // links
20
+ markdownBlockquoteRegex, // blockquote
21
+ markdownUnorderedListRegex, // unordered list
22
+ markdownOrderedListRegex, // ordered list
23
+ markdownHorizontalRuleRegex, // horizontal rule
24
+ markdownImageRegex, // images
25
+ ];
26
+ return markdownPatterns.some((pattern) => pattern.test(input));
27
+ }
28
+
29
+ function getDepth1ListNumber(i: number): string {
30
+ if (i <= 0) {
31
+ return "";
32
+ }
33
+ const letters: string[] = [];
34
+ let num = i;
35
+ while (num > 0) {
36
+ num--; // Adjust for 0-indexing
37
+ letters.unshift(String.fromCharCode(97 + (num % 26)));
38
+ num = Math.floor(num / 26);
39
+ }
40
+ return letters.join("");
41
+ }
42
+
43
+ function getDepth2ListNumber(i: number): string {
44
+ if (i <= 0) {
45
+ return "";
46
+ }
47
+ const romanNumerals = [
48
+ ["m", 1000],
49
+ ["cm", 900],
50
+ ["d", 500],
51
+ ["cd", 400],
52
+ ["c", 100],
53
+ ["xc", 90],
54
+ ["l", 50],
55
+ ["xl", 40],
56
+ ["x", 10],
57
+ ["ix", 9],
58
+ ["v", 5],
59
+ ["iv", 4],
60
+ ["i", 1],
61
+ ] as const;
62
+
63
+ let num = i;
64
+ let result = "";
65
+ for (const [roman, value] of romanNumerals) {
66
+ while (num >= value) {
67
+ result += roman;
68
+ num -= value;
69
+ }
70
+ }
71
+ return result;
72
+ }
73
+
74
+ export function getListNumber(
75
+ listDepth: number,
76
+ orderedListNumber: number,
77
+ ): string {
78
+ switch (listDepth) {
79
+ case 0:
80
+ case 1:
81
+ return orderedListNumber.toString();
82
+ case 2:
83
+ return getDepth1ListNumber(orderedListNumber);
84
+ case 3:
85
+ return getDepth2ListNumber(orderedListNumber);
86
+ default:
87
+ return orderedListNumber.toString();
88
+ }
89
+ }