@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,105 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { dirname, isAbsolute, join, normalize, resolve, sep } from "node:path";
3
+ import { tool } from "ai";
4
+ import { z } from "zod";
5
+ import { config } from "../config.ts";
6
+ import type { SendData } from "./types.ts";
7
+
8
+ export const MemoryWriteTool = {
9
+ name: "memoryWrite" as const,
10
+ };
11
+
12
+ const MEMORY_DIR = config.app.ensurePathSync("memory");
13
+
14
+ export const createMemoryWriteTool = (
15
+ options: { sendData?: SendData | undefined } = {},
16
+ ) => {
17
+ const { sendData } = options;
18
+
19
+ const memoryWriteTool = tool({
20
+ description: "Write content to a memory file.",
21
+ inputSchema: z.object({
22
+ filePath: z
23
+ .string()
24
+ .describe(
25
+ 'Path to the memory file, relative to the memory directory. Cannot use ".." or absolute paths.',
26
+ ),
27
+ content: z.string().describe("Content to write to the file."),
28
+ }),
29
+ execute: async (
30
+ { filePath, content }: { filePath: string; content: string },
31
+ { toolCallId },
32
+ ) => {
33
+ sendData?.({
34
+ event: "tool-init",
35
+ id: toolCallId,
36
+ data: "Initializing memory write...",
37
+ });
38
+
39
+ const resolvedMemoryDir = resolve(MEMORY_DIR);
40
+ const normalizedRelativePath = normalize(filePath);
41
+
42
+ if (
43
+ normalizedRelativePath.startsWith("..") ||
44
+ normalizedRelativePath.includes("..") ||
45
+ isAbsolute(normalizedRelativePath)
46
+ ) {
47
+ const errorMsg = `Error: Invalid filePath "${filePath}". Must be a relative path within the memory directory and cannot use '..'.`;
48
+ sendData?.({
49
+ event: "tool-error",
50
+ id: toolCallId,
51
+ data: errorMsg,
52
+ });
53
+ return errorMsg;
54
+ }
55
+
56
+ const fullPath = join(resolvedMemoryDir, normalizedRelativePath);
57
+
58
+ if (
59
+ !fullPath.startsWith(resolvedMemoryDir + sep) &&
60
+ fullPath !== resolvedMemoryDir
61
+ ) {
62
+ const errorMsg = `Error: Path "${filePath}" resolves outside the allowed memory directory.`;
63
+ sendData?.({
64
+ event: "tool-error",
65
+ id: toolCallId,
66
+ data: errorMsg,
67
+ });
68
+ return errorMsg;
69
+ }
70
+
71
+ sendData?.({
72
+ event: "tool-update",
73
+ id: toolCallId,
74
+ data: { primary: "Writing to file:", secondary: [filePath] },
75
+ });
76
+
77
+ try {
78
+ await mkdir(dirname(fullPath), { recursive: true });
79
+ await writeFile(fullPath, content, "utf-8");
80
+ const successMsg = `Memory file '${filePath}' written successfully.`;
81
+ sendData?.({
82
+ event: "tool-completion",
83
+ id: toolCallId,
84
+ data: successMsg,
85
+ });
86
+ return successMsg;
87
+ } catch (error: unknown) {
88
+ let errorMsg = `Error writing memory file '${filePath}': An unknown error occurred`;
89
+ if (error instanceof Error) {
90
+ errorMsg = `Error writing memory file '${filePath}': ${error.message}`;
91
+ }
92
+ sendData?.({
93
+ event: "tool-error",
94
+ id: toolCallId,
95
+ data: errorMsg,
96
+ });
97
+ return errorMsg;
98
+ }
99
+ },
100
+ });
101
+
102
+ return {
103
+ [MemoryWriteTool.name]: memoryWriteTool,
104
+ };
105
+ };
@@ -0,0 +1,59 @@
1
+ import fs from "node:fs/promises";
2
+ import { tool } from "ai";
3
+ import chalk from "chalk";
4
+ import { z } from "zod";
5
+ import { joinWorkingDir, validatePath } from "./filesystem-utils.ts";
6
+ import type { SendData } from "./types.ts";
7
+
8
+ export const MoveFileTool = {
9
+ name: "moveFile" as const,
10
+ };
11
+
12
+ export const createMoveFileTool = async ({
13
+ workingDir,
14
+ sendData,
15
+ }: {
16
+ workingDir: string;
17
+ sendData?: SendData;
18
+ }) => {
19
+ const allowedDirectory = workingDir;
20
+ return {
21
+ [MoveFileTool.name]: tool({
22
+ description:
23
+ "Move or rename files and directories. Can move files between directories " +
24
+ "and rename them in a single operation. If the destination exists, the " +
25
+ "operation will fail. Works across different directories and can be used " +
26
+ "for simple renaming within the same directory. Both source and destination must be within allowed directories.",
27
+ inputSchema: z.object({
28
+ source: z.string(),
29
+ destination: z.string(),
30
+ }),
31
+ execute: async ({ source, destination }, { toolCallId }) => {
32
+ try {
33
+ sendData?.({
34
+ id: toolCallId,
35
+ event: "tool-init",
36
+ data: `Moving file from ${chalk.cyan(source)} to ${chalk.cyan(destination)}`,
37
+ });
38
+ const validSourcePath = await validatePath(
39
+ joinWorkingDir(source, workingDir),
40
+ allowedDirectory,
41
+ );
42
+ const validDestPath = await validatePath(
43
+ joinWorkingDir(destination, workingDir),
44
+ allowedDirectory,
45
+ );
46
+ await fs.rename(validSourcePath, validDestPath);
47
+ sendData?.({
48
+ id: toolCallId,
49
+ event: "tool-completion",
50
+ data: "Done",
51
+ });
52
+ return `Successfully moved ${source} to ${destination}`;
53
+ } catch (error) {
54
+ return `Failed to move file: ${(error as Error).message}`;
55
+ }
56
+ },
57
+ }),
58
+ };
59
+ };
@@ -0,0 +1,129 @@
1
+ import fs from "node:fs/promises";
2
+ import { isNumber } from "@travisennis/stdlib/typeguards";
3
+ import { tool } from "ai";
4
+ import chalk from "chalk";
5
+ import { z } from "zod";
6
+ import { config } from "../config.ts";
7
+ import type { TokenCounter } from "../token-utils.ts";
8
+ import { joinWorkingDir, validatePath } from "./filesystem-utils.ts";
9
+ import type { SendData } from "./types.ts";
10
+ import { fileEncodingSchema } from "./types.ts";
11
+
12
+ export const ReadFileTool = {
13
+ name: "readFile" as const,
14
+ };
15
+
16
+ export const createReadFileTool = async ({
17
+ workingDir,
18
+ sendData,
19
+ tokenCounter,
20
+ }: {
21
+ workingDir: string;
22
+ sendData?: SendData;
23
+ tokenCounter: TokenCounter;
24
+ }) => {
25
+ const allowedDirectory = workingDir;
26
+ return {
27
+ [ReadFileTool.name]: tool({
28
+ description:
29
+ "Read the complete contents of a file from the file system unless startLine and lineCount are given to read a file selection. " +
30
+ "Handles various text encodings and provides detailed error messages " +
31
+ "if the file cannot be read. Use this tool when you need to examine " +
32
+ "the contents of a single file. Only works within allowed directories.",
33
+ inputSchema: z.object({
34
+ path: z.string().describe("Absolute path to file to read"),
35
+ encoding: fileEncodingSchema.describe(
36
+ 'Encoding format for reading the file. Use "utf-8" as default for text files',
37
+ ),
38
+ startLine: z
39
+ .number()
40
+ .nullable()
41
+ .describe(
42
+ "1-based line number to start reading from. Pass null to start at beginning of file",
43
+ ),
44
+ lineCount: z
45
+ .number()
46
+ .nullable()
47
+ .describe(
48
+ "Maximum number of lines to read. Pass null to get all lines.",
49
+ ),
50
+ }),
51
+ execute: async (
52
+ {
53
+ path: providedPath,
54
+ encoding,
55
+ startLine,
56
+ lineCount,
57
+ }: {
58
+ path: string;
59
+ encoding: z.infer<typeof fileEncodingSchema>;
60
+ startLine: number | null;
61
+ lineCount: number | null;
62
+ },
63
+ { toolCallId },
64
+ ) => {
65
+ sendData?.({
66
+ id: toolCallId,
67
+ event: "tool-init",
68
+ data: `Reading file: ${chalk.cyan(providedPath)}${startLine ? chalk.cyan(`:${startLine}`) : ""}${lineCount ? chalk.cyan(`:${lineCount}`) : ""}`,
69
+ });
70
+ try {
71
+ const filePath = await validatePath(
72
+ joinWorkingDir(providedPath, workingDir),
73
+ allowedDirectory,
74
+ );
75
+
76
+ let file = await fs.readFile(filePath, { encoding });
77
+
78
+ // Apply line-based selection if requested
79
+ if (isNumber(startLine) || isNumber(lineCount)) {
80
+ const lines = file.split("\n");
81
+ const totalLines = lines.length;
82
+
83
+ const startIndex = (startLine ?? 1) - 1; // Default to start of file if only lineCount is given
84
+ const count = lineCount ?? totalLines - startIndex; // Default to read all lines from start if only startLine is given
85
+
86
+ if (startIndex < 0 || startIndex >= totalLines) {
87
+ return `startLine ${startLine} is out of bounds for file with ${totalLines} lines.`;
88
+ }
89
+
90
+ const endIndex = Math.min(startIndex + count, totalLines);
91
+ file = lines.slice(startIndex, endIndex).join("\n");
92
+ }
93
+ let tokenCount = 0;
94
+ try {
95
+ // Only calculate tokens for non-image files and if encoding is text-based
96
+ if (encoding.startsWith("utf")) {
97
+ tokenCount = tokenCounter.count(file);
98
+ }
99
+ } catch (tokenError) {
100
+ console.error("Error calculating token count:", tokenError);
101
+ // Log or handle error, but don't block file return
102
+ }
103
+
104
+ const maxTokens = (await config.readProjectConfig()).tools.maxTokens;
105
+ // Adjust max token check message if line selection was used
106
+ const maxTokenMessage =
107
+ isNumber(startLine) || isNumber(lineCount)
108
+ ? `Selected file content (${tokenCount} tokens) exceeds maximum allowed tokens (${maxTokens}). Consider adjusting startLine/lineCount or using grepFiles.`
109
+ : `File content (${tokenCount} tokens) exceeds maximum allowed tokens (${maxTokens}). Please use startLine and lineCount parameters to read specific portions of the file, or using grepFiles to search for specific content.`;
110
+
111
+ const result = tokenCount <= maxTokens ? file : maxTokenMessage;
112
+
113
+ sendData?.({
114
+ id: toolCallId,
115
+ event: "tool-completion",
116
+ // Include token count only if calculated (i.e., for text files)
117
+ data:
118
+ tokenCount <= maxTokens
119
+ ? `File read successfully ${tokenCount > 0 ? ` (${tokenCount} tokens)` : ""}`
120
+ : result,
121
+ });
122
+ return result;
123
+ } catch (error) {
124
+ return `Failed to read file: ${(error as Error).message}`;
125
+ }
126
+ },
127
+ }),
128
+ };
129
+ };
@@ -0,0 +1,80 @@
1
+ import { tool } from "ai";
2
+ import chalk from "chalk";
3
+ import { z } from "zod";
4
+ import { config } from "../config.ts";
5
+ import type { TokenCounter } from "../token-utils.ts";
6
+ import { readFileAndCountTokens } from "./filesystem-utils.ts";
7
+ import type { SendData } from "./types.ts";
8
+
9
+ export const ReadMultipleFilesTool = {
10
+ name: "readMultipleFiles" as const,
11
+ };
12
+
13
+ export const createReadMultipleFilesTool = async ({
14
+ workingDir,
15
+ sendData,
16
+ tokenCounter,
17
+ }: {
18
+ workingDir: string;
19
+ sendData?: SendData;
20
+ tokenCounter: TokenCounter;
21
+ }) => {
22
+ const allowedDirectory = workingDir;
23
+ return {
24
+ [ReadMultipleFilesTool.name]: tool({
25
+ description:
26
+ "Read the contents of multiple files simultaneously. This is more " +
27
+ "efficient than reading files one by one when you need to analyze " +
28
+ "or compare multiple files. Each file's content is returned with its " +
29
+ "path as a reference. Failed reads for individual files won't stop " +
30
+ "the entire operation. Only works within allowed directories.",
31
+ inputSchema: z.object({
32
+ paths: z.array(z.string()),
33
+ }),
34
+ execute: async ({ paths }, { toolCallId }) => {
35
+ sendData?.({
36
+ id: toolCallId,
37
+ event: "tool-init",
38
+ data: `Reading files: ${paths.map((p) => chalk.cyan(p)).join(", ")}`,
39
+ });
40
+ const maxTokens = (await config.readProjectConfig()).tools.maxTokens;
41
+ const results = await Promise.all(
42
+ paths.map((filePath) =>
43
+ readFileAndCountTokens(
44
+ filePath,
45
+ workingDir,
46
+ allowedDirectory,
47
+ tokenCounter,
48
+ maxTokens,
49
+ ),
50
+ ),
51
+ );
52
+ let totalTokens = 0;
53
+ let filesReadCount = 0;
54
+ const formattedResults = results.map((result) => {
55
+ if (result.error) {
56
+ return `${result.path}: Error - ${result.error}`;
57
+ }
58
+ // Check if tokenCount is > 0, meaning it wasn't skipped
59
+ if (result.tokenCount > 0) {
60
+ filesReadCount++;
61
+ }
62
+ totalTokens += result.tokenCount; // Add the token count (will be 0 for skipped files)
63
+ // Return content (or max token message)
64
+ return `${result.path}:\n${result.content}\n`;
65
+ });
66
+ const completionMessage =
67
+ filesReadCount === paths.length
68
+ ? `Read ${paths.length} files successfully (${totalTokens} total tokens).`
69
+ : `Read ${filesReadCount} of ${paths.length} files successfully (${totalTokens} total tokens). Files exceeding token limit were skipped.`;
70
+
71
+ sendData?.({
72
+ id: toolCallId,
73
+ event: "tool-completion",
74
+ data: completionMessage,
75
+ });
76
+ return formattedResults.join("\n---\n");
77
+ },
78
+ }),
79
+ };
80
+ };
@@ -0,0 +1,147 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { input, select } from "@inquirer/prompts";
4
+ import { tool } from "ai";
5
+ import chalk from "chalk";
6
+ import { z } from "zod";
7
+ import type { Terminal } from "../terminal/index.ts";
8
+ import { joinWorkingDir, validatePath } from "./filesystem-utils.ts";
9
+ import { fileEncodingSchema, type SendData } from "./types.ts";
10
+
11
+ export const SaveFileTool = {
12
+ name: "saveFile" as const,
13
+ };
14
+
15
+ export const createSaveFileTool = async ({
16
+ workingDir,
17
+ sendData,
18
+ terminal,
19
+ autoAcceptAll,
20
+ }: {
21
+ workingDir: string;
22
+ sendData?: SendData;
23
+ terminal?: Terminal;
24
+ autoAcceptAll?: boolean;
25
+ }) => {
26
+ const allowedDirectory = workingDir;
27
+ let autoAcceptSaves = autoAcceptAll ?? false;
28
+
29
+ return {
30
+ [SaveFileTool.name]: tool({
31
+ description:
32
+ "Create a new file or completely overwrite an existing file with new content. " +
33
+ "Use with caution as it will overwrite existing files without warning. " +
34
+ "Handles text content with proper encoding. Only works within allowed directories.",
35
+ inputSchema: z.object({
36
+ path: z.string().describe("Absolute path to file to save to"),
37
+ content: z.string().describe("Content to save in the file"),
38
+ encoding: fileEncodingSchema.describe(
39
+ 'Encoding format for saving the file. Use "utf-8" as default for text files',
40
+ ),
41
+ }),
42
+ execute: async (
43
+ {
44
+ path: userPath,
45
+ content,
46
+ encoding,
47
+ }: {
48
+ path: string;
49
+ content: string;
50
+ encoding: z.infer<typeof fileEncodingSchema>;
51
+ },
52
+ { toolCallId },
53
+ ) => {
54
+ sendData?.({
55
+ id: toolCallId,
56
+ event: "tool-init",
57
+ data: `Saving file: ${chalk.cyan(userPath)}`,
58
+ });
59
+ try {
60
+ const filePath = await validatePath(
61
+ joinWorkingDir(userPath, workingDir),
62
+ allowedDirectory,
63
+ );
64
+
65
+ if (terminal) {
66
+ terminal.writeln(
67
+ `\n${chalk.blue.bold("●")} Proposing file save: ${chalk.cyan(userPath)}`,
68
+ );
69
+
70
+ terminal.lineBreak();
71
+ terminal.writeln("Proposed file content:");
72
+ terminal.lineBreak();
73
+ terminal.display(content);
74
+ terminal.lineBreak();
75
+
76
+ let userChoice: string;
77
+ if (autoAcceptSaves) {
78
+ terminal.writeln(
79
+ chalk.green(
80
+ "✓ Auto-accepting saves (all future saves will be accepted)",
81
+ ),
82
+ );
83
+ userChoice = "accept";
84
+ } else {
85
+ userChoice = await select({
86
+ message: "What would you like to do with this file?",
87
+ choices: [
88
+ { name: "Accept and save this file", value: "accept" },
89
+ {
90
+ name: "Accept all future saves (including this)",
91
+ value: "accept-all",
92
+ },
93
+ { name: "Reject this save", value: "reject" },
94
+ ],
95
+ default: "accept",
96
+ });
97
+ }
98
+
99
+ terminal.lineBreak();
100
+
101
+ if (userChoice === "accept-all") {
102
+ autoAcceptSaves = true;
103
+ terminal.writeln(
104
+ chalk.yellow("✓ Auto-accept mode enabled for all future saves"),
105
+ );
106
+ terminal.lineBreak();
107
+ }
108
+
109
+ if (userChoice === "reject") {
110
+ const reason = await input({ message: "Feedback: " });
111
+
112
+ terminal.lineBreak();
113
+
114
+ sendData?.({
115
+ id: toolCallId,
116
+ event: "tool-completion",
117
+ data: `Save rejected by user. Reason: ${reason}`,
118
+ });
119
+
120
+ return `The user rejected this save. Reason: ${reason}`;
121
+ }
122
+
123
+ // If accepted, proceed to write file
124
+ }
125
+
126
+ // Ensure parent directory exists
127
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
128
+ await fs.writeFile(filePath, content, { encoding });
129
+
130
+ sendData?.({
131
+ id: toolCallId,
132
+ event: "tool-completion",
133
+ data: `File saved successfully: ${userPath}`,
134
+ });
135
+ return `File saved successfully: ${filePath}`;
136
+ } catch (error) {
137
+ sendData?.({
138
+ id: toolCallId,
139
+ event: "tool-error",
140
+ data: `Failed to save file: ${(error as Error).message}`,
141
+ });
142
+ return `Failed to save file: ${(error as Error).message}`;
143
+ }
144
+ },
145
+ }),
146
+ };
147
+ };
@@ -0,0 +1,51 @@
1
+ import { tool } from "ai";
2
+ import { z } from "zod";
3
+ import type { SendData } from "./types.ts";
4
+
5
+ export const ThinkTool = {
6
+ name: "think" as const,
7
+ };
8
+
9
+ const toolDescription = `Use the tool to think about something. It will not obtain new information or make any changes to the repository, but just log the thought. Use it when complex reasoning or brainstorming is needed.
10
+ Common use cases:
11
+ 1. When exploring a repository and discovering the source of a bug, call this tool to brainstorm several unique ways of fixing the bug, and assess which change(s) are likely to be simplest and most effective
12
+ 2. After receiving test results, use this tool to brainstorm ways to fix failing tests
13
+ 3. When planning a complex refactoring, use this tool to outline different approaches and their tradeoffs
14
+ 4. When designing a new feature, use this tool to think through architecture decisions and implementation details
15
+ 5. When debugging a complex issue, use this tool to organize your thoughts and hypotheses
16
+ The tool simply logs your thought process for better transparency and does not execute any code or make changes.`;
17
+
18
+ // This is a no-op tool that logs a thought. It is inspired by the tau-bench think tool.
19
+ export const createThinkTool = (
20
+ options: { sendData?: SendData | undefined } = {},
21
+ ) => {
22
+ const { sendData } = options;
23
+ return {
24
+ [ThinkTool.name]: tool({
25
+ description: toolDescription,
26
+ inputSchema: z.object({
27
+ thought: z.string().describe("Your thought"),
28
+ }),
29
+ execute: ({ thought }, { toolCallId }) => {
30
+ // Replace literal '\\n' with actual newline characters
31
+ const formattedThought = thought.replace(/\\n/g, "\n");
32
+ sendData?.({
33
+ event: "tool-init",
34
+ id: toolCallId,
35
+ data: "Logging Thought",
36
+ });
37
+ sendData?.({
38
+ event: "tool-update",
39
+ id: toolCallId,
40
+ data: { primary: "Thought:", secondary: [formattedThought] },
41
+ });
42
+ sendData?.({
43
+ event: "tool-completion",
44
+ id: toolCallId,
45
+ data: "Done",
46
+ });
47
+ return Promise.resolve("Your thought has been logged.");
48
+ },
49
+ }),
50
+ };
51
+ };
@@ -0,0 +1,58 @@
1
+ import { z } from "zod";
2
+
3
+ export const fileEncodingSchema = z.enum([
4
+ "ascii",
5
+ "utf8",
6
+ "utf-8",
7
+ "utf16le",
8
+ "ucs2",
9
+ "ucs-2",
10
+ "base64",
11
+ "base64url",
12
+ "latin1",
13
+ "binary",
14
+ "hex",
15
+ ]);
16
+
17
+ interface MessageData {
18
+ primary: string;
19
+ secondary?: string[] | undefined;
20
+ }
21
+
22
+ interface BaseMessage {
23
+ id: string;
24
+ retry?: number;
25
+ }
26
+
27
+ interface ToolInitMessage extends BaseMessage {
28
+ event: "tool-init";
29
+ data: string;
30
+ }
31
+
32
+ interface ToolErrorMessage extends BaseMessage {
33
+ event: "tool-error";
34
+ data: string;
35
+ }
36
+
37
+ interface ToolCompletionMessage extends BaseMessage {
38
+ event: "tool-completion";
39
+ data: string;
40
+ }
41
+
42
+ interface ToolUpdateMessage extends BaseMessage {
43
+ event: "tool-update";
44
+ data: MessageData;
45
+ }
46
+
47
+ export type Message =
48
+ | ToolInitMessage
49
+ | ToolErrorMessage
50
+ | ToolCompletionMessage
51
+ | ToolUpdateMessage;
52
+
53
+ export type SendData = ({
54
+ data,
55
+ event,
56
+ id,
57
+ retry,
58
+ }: Message) => void | Promise<void>;