@travisennis/acai 0.0.1 → 0.0.3

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 (324) hide show
  1. package/README.md +3 -4
  2. package/dist/commands/health-command.d.ts +2 -0
  3. package/dist/commands/health-command.js +59 -0
  4. package/dist/commands/manager.js +2 -0
  5. package/dist/commands/paste-command.d.ts +1 -1
  6. package/dist/commands/paste-command.js +155 -11
  7. package/dist/commands/reset-command.js +1 -0
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.js +2 -1
  10. package/dist/models/openrouter-provider.d.ts +4 -1
  11. package/dist/models/openrouter-provider.js +46 -4
  12. package/dist/models/providers.d.ts +1 -1
  13. package/dist/prompts/manager.d.ts +1 -0
  14. package/dist/prompts/manager.js +10 -0
  15. package/dist/prompts.js +8 -6
  16. package/dist/repl.js +49 -26
  17. package/dist/terminal/formatting.d.ts +16 -5
  18. package/dist/terminal/formatting.js +40 -6
  19. package/dist/terminal/index.d.ts +1 -1
  20. package/dist/terminal/index.js +54 -14
  21. package/dist/terminal/markdown.js +0 -1
  22. package/dist/terminal/supports-color.d.ts +16 -0
  23. package/dist/terminal/supports-color.js +121 -0
  24. package/dist/terminal/supports-hyperlinks.d.ts +7 -0
  25. package/dist/terminal/supports-hyperlinks.js +98 -0
  26. package/dist/tools/bash.js +95 -117
  27. package/dist/tools/code-interpreter.js +11 -1
  28. package/dist/tools/command-validation.d.ts +7 -3
  29. package/dist/tools/command-validation.js +67 -23
  30. package/dist/tools/delete-file.d.ts +4 -1
  31. package/dist/tools/delete-file.js +47 -3
  32. package/dist/tools/git-utils.d.ts +6 -0
  33. package/dist/tools/git-utils.js +89 -12
  34. package/dist/tools/grep.d.ts +20 -0
  35. package/dist/tools/grep.js +128 -40
  36. package/dist/tools/index.d.ts +2 -18
  37. package/dist/tools/index.js +4 -18
  38. package/package.json +30 -20
  39. package/.acai/acai.json +0 -9
  40. package/.acai/prompts/add-openrouter-model.md +0 -13
  41. package/.acai/prompts/project-status.md +0 -4
  42. package/.acai/prompts/update-architecture-document.md +0 -9
  43. package/.acai/rules/learned-rules.md +0 -9
  44. package/.ai/docs/available-tools.txt +0 -3
  45. package/.ai/docs/cognitive_complexity_refactoring_progress.md +0 -65
  46. package/.ai/docs/deleted_tools.md +0 -168
  47. package/.ai/docs/deleted_tools_88ced9ef.md +0 -56
  48. package/.ai/docs/image-pasting.md +0 -46
  49. package/.ai/docs/initialize-app.md +0 -117
  50. package/.ai/docs/issue-4-plan.md +0 -44
  51. package/.ai/docs/marked-renderer-debug.md +0 -15
  52. package/.ai/docs/marked-renderer-refactor-plan.md +0 -64
  53. package/.ai/docs/memory-use-cases.md +0 -55
  54. package/.ai/docs/prompt-consistency.md +0 -31
  55. package/.ai/docs/refactoring-tools.md +0 -98
  56. package/.ai/docs/system-prompt-update.md +0 -174
  57. package/.ai/docs/system_prompt.txt +0 -210
  58. package/.ai/docs/tasks.md +0 -49
  59. package/.ai/plan.md +0 -131
  60. package/.ai/prompt.md +0 -1
  61. package/.ai/scripts/fetch_models.js +0 -27
  62. package/.ai/scripts/generateSystemPrompt.ts +0 -15
  63. package/.ai/scripts/list-tools.mjs +0 -4
  64. package/.ai/scripts/p5_geometric_shapes.js +0 -149
  65. package/.husky/commit-msg +0 -1
  66. package/.husky/pre-commit +0 -3
  67. package/.husky/pre-push +0 -1
  68. package/.ignore +0 -4
  69. package/AGENTS.md +0 -25
  70. package/ARCHITECTURE.md +0 -304
  71. package/TODO.md +0 -2
  72. package/biome.json +0 -61
  73. package/commitlint.config.js +0 -3
  74. package/dist/source/cli.d.ts +0 -19
  75. package/dist/source/cli.js +0 -116
  76. package/dist/source/commands/application-log-command.d.ts +0 -2
  77. package/dist/source/commands/application-log-command.js +0 -43
  78. package/dist/source/commands/clear-command.d.ts +0 -2
  79. package/dist/source/commands/clear-command.js +0 -12
  80. package/dist/source/commands/compact-command.d.ts +0 -2
  81. package/dist/source/commands/compact-command.js +0 -51
  82. package/dist/source/commands/copy-command.d.ts +0 -2
  83. package/dist/source/commands/copy-command.js +0 -51
  84. package/dist/source/commands/edit-command.d.ts +0 -2
  85. package/dist/source/commands/edit-command.js +0 -53
  86. package/dist/source/commands/edit-prompt-command.d.ts +0 -2
  87. package/dist/source/commands/edit-prompt-command.js +0 -25
  88. package/dist/source/commands/exit-command.d.ts +0 -2
  89. package/dist/source/commands/exit-command.js +0 -14
  90. package/dist/source/commands/files-command.d.ts +0 -2
  91. package/dist/source/commands/files-command.js +0 -63
  92. package/dist/source/commands/generate-rules-command.d.ts +0 -2
  93. package/dist/source/commands/generate-rules-command.js +0 -61
  94. package/dist/source/commands/help-command.d.ts +0 -2
  95. package/dist/source/commands/help-command.js +0 -19
  96. package/dist/source/commands/init-command.d.ts +0 -2
  97. package/dist/source/commands/init-command.js +0 -40
  98. package/dist/source/commands/last-log-command.d.ts +0 -2
  99. package/dist/source/commands/last-log-command.js +0 -76
  100. package/dist/source/commands/manager.d.ts +0 -22
  101. package/dist/source/commands/manager.js +0 -123
  102. package/dist/source/commands/model-command.d.ts +0 -2
  103. package/dist/source/commands/model-command.js +0 -84
  104. package/dist/source/commands/paste-command.d.ts +0 -2
  105. package/dist/source/commands/paste-command.js +0 -40
  106. package/dist/source/commands/prompt-command.d.ts +0 -2
  107. package/dist/source/commands/prompt-command.js +0 -111
  108. package/dist/source/commands/reset-command.d.ts +0 -2
  109. package/dist/source/commands/reset-command.js +0 -16
  110. package/dist/source/commands/rules-command.d.ts +0 -2
  111. package/dist/source/commands/rules-command.js +0 -68
  112. package/dist/source/commands/save-command.d.ts +0 -2
  113. package/dist/source/commands/save-command.js +0 -14
  114. package/dist/source/commands/types.d.ts +0 -26
  115. package/dist/source/commands/types.js +0 -1
  116. package/dist/source/commands/usage-command.d.ts +0 -2
  117. package/dist/source/commands/usage-command.js +0 -21
  118. package/dist/source/config.d.ts +0 -60
  119. package/dist/source/config.js +0 -193
  120. package/dist/source/conversation-analyzer.d.ts +0 -10
  121. package/dist/source/conversation-analyzer.js +0 -88
  122. package/dist/source/dedent.d.ts +0 -3
  123. package/dist/source/dedent.js +0 -38
  124. package/dist/source/formatting.d.ts +0 -17
  125. package/dist/source/formatting.js +0 -103
  126. package/dist/source/index.d.ts +0 -18
  127. package/dist/source/index.js +0 -213
  128. package/dist/source/logger.d.ts +0 -2
  129. package/dist/source/logger.js +0 -24
  130. package/dist/source/mentions.d.ts +0 -9
  131. package/dist/source/mentions.js +0 -182
  132. package/dist/source/messages.d.ts +0 -69
  133. package/dist/source/messages.js +0 -261
  134. package/dist/source/middleware/audit-message.d.ts +0 -5
  135. package/dist/source/middleware/audit-message.js +0 -95
  136. package/dist/source/middleware/index.d.ts +0 -2
  137. package/dist/source/middleware/index.js +0 -2
  138. package/dist/source/middleware/rate-limit.d.ts +0 -4
  139. package/dist/source/middleware/rate-limit.js +0 -17
  140. package/dist/source/models/ai-config.d.ts +0 -12
  141. package/dist/source/models/ai-config.js +0 -87
  142. package/dist/source/models/anthropic-provider.d.ts +0 -25
  143. package/dist/source/models/anthropic-provider.js +0 -184
  144. package/dist/source/models/deepseek-provider.d.ts +0 -20
  145. package/dist/source/models/deepseek-provider.js +0 -42
  146. package/dist/source/models/google-provider.d.ts +0 -19
  147. package/dist/source/models/google-provider.js +0 -56
  148. package/dist/source/models/manager.d.ts +0 -15
  149. package/dist/source/models/manager.js +0 -48
  150. package/dist/source/models/openai-provider.d.ts +0 -22
  151. package/dist/source/models/openai-provider.js +0 -70
  152. package/dist/source/models/openrouter-provider.d.ts +0 -36
  153. package/dist/source/models/openrouter-provider.js +0 -276
  154. package/dist/source/models/providers.d.ts +0 -33
  155. package/dist/source/models/providers.js +0 -116
  156. package/dist/source/models/xai-provider.d.ts +0 -20
  157. package/dist/source/models/xai-provider.js +0 -47
  158. package/dist/source/parsing.d.ts +0 -2
  159. package/dist/source/parsing.js +0 -18
  160. package/dist/source/prompts/manager.d.ts +0 -19
  161. package/dist/source/prompts/manager.js +0 -71
  162. package/dist/source/prompts.d.ts +0 -4
  163. package/dist/source/prompts.js +0 -158
  164. package/dist/source/repl-prompt.d.ts +0 -14
  165. package/dist/source/repl-prompt.js +0 -147
  166. package/dist/source/repl.d.ts +0 -27
  167. package/dist/source/repl.js +0 -431
  168. package/dist/source/terminal/formatting.d.ts +0 -37
  169. package/dist/source/terminal/formatting.js +0 -106
  170. package/dist/source/terminal/index.d.ts +0 -94
  171. package/dist/source/terminal/index.js +0 -420
  172. package/dist/source/terminal/markdown-utils.d.ts +0 -2
  173. package/dist/source/terminal/markdown-utils.js +0 -81
  174. package/dist/source/terminal/markdown.d.ts +0 -1
  175. package/dist/source/terminal/markdown.js +0 -111
  176. package/dist/source/terminal/types.d.ts +0 -71
  177. package/dist/source/terminal/types.js +0 -1
  178. package/dist/source/terminal-output.d.ts +0 -8
  179. package/dist/source/terminal-output.js +0 -213
  180. package/dist/source/terminal-output.test.d.ts +0 -8
  181. package/dist/source/terminal-output.test.js +0 -213
  182. package/dist/source/token-tracker.d.ts +0 -14
  183. package/dist/source/token-tracker.js +0 -53
  184. package/dist/source/token-utils.d.ts +0 -7
  185. package/dist/source/token-utils.js +0 -13
  186. package/dist/source/tools/agent.d.ts +0 -17
  187. package/dist/source/tools/agent.js +0 -87
  188. package/dist/source/tools/bash.d.ts +0 -19
  189. package/dist/source/tools/bash.js +0 -294
  190. package/dist/source/tools/code-interpreter.d.ts +0 -12
  191. package/dist/source/tools/code-interpreter.js +0 -131
  192. package/dist/source/tools/command-validation.d.ts +0 -8
  193. package/dist/source/tools/command-validation.js +0 -69
  194. package/dist/source/tools/delete-file.d.ts +0 -12
  195. package/dist/source/tools/delete-file.js +0 -56
  196. package/dist/source/tools/directory-tree.d.ts +0 -12
  197. package/dist/source/tools/directory-tree.js +0 -38
  198. package/dist/source/tools/edit-file.d.ts +0 -19
  199. package/dist/source/tools/edit-file.js +0 -107
  200. package/dist/source/tools/filesystem-utils.d.ts +0 -22
  201. package/dist/source/tools/filesystem-utils.js +0 -191
  202. package/dist/source/tools/git-utils.d.ts +0 -14
  203. package/dist/source/tools/git-utils.js +0 -64
  204. package/dist/source/tools/grep.d.ts +0 -17
  205. package/dist/source/tools/grep.js +0 -138
  206. package/dist/source/tools/index.d.ts +0 -161
  207. package/dist/source/tools/index.js +0 -209
  208. package/dist/source/tools/memory-read.d.ts +0 -13
  209. package/dist/source/tools/memory-read.js +0 -135
  210. package/dist/source/tools/memory-write.d.ts +0 -12
  211. package/dist/source/tools/memory-write.js +0 -83
  212. package/dist/source/tools/move-file.d.ts +0 -13
  213. package/dist/source/tools/move-file.js +0 -44
  214. package/dist/source/tools/read-file.d.ts +0 -17
  215. package/dist/source/tools/read-file.js +0 -86
  216. package/dist/source/tools/read-multiple-files.d.ts +0 -14
  217. package/dist/source/tools/read-multiple-files.js +0 -55
  218. package/dist/source/tools/save-file.d.ts +0 -17
  219. package/dist/source/tools/save-file.js +0 -98
  220. package/dist/source/tools/think.d.ts +0 -11
  221. package/dist/source/tools/think.js +0 -45
  222. package/dist/source/tools/types.d.ts +0 -29
  223. package/dist/source/tools/types.js +0 -14
  224. package/dist/source/tools/web-fetch.d.ts +0 -47
  225. package/dist/source/tools/web-fetch.js +0 -246
  226. package/dist/source/tools/web-search.d.ts +0 -13
  227. package/dist/source/tools/web-search.js +0 -80
  228. package/dist/source/utils/process.d.ts +0 -36
  229. package/dist/source/utils/process.js +0 -75
  230. package/dist/source/version.d.ts +0 -1
  231. package/dist/source/version.js +0 -21
  232. package/dist/terminal-output.d.ts +0 -8
  233. package/dist/terminal-output.js +0 -213
  234. package/dist/tools/memory-read.d.ts +0 -13
  235. package/dist/tools/memory-read.js +0 -135
  236. package/dist/tools/memory-write.d.ts +0 -12
  237. package/dist/tools/memory-write.js +0 -83
  238. package/knip.json +0 -5
  239. package/source/cli.ts +0 -172
  240. package/source/commands/application-log-command.ts +0 -53
  241. package/source/commands/clear-command.ts +0 -14
  242. package/source/commands/compact-command.ts +0 -64
  243. package/source/commands/copy-command.ts +0 -55
  244. package/source/commands/edit-command.ts +0 -63
  245. package/source/commands/edit-prompt-command.ts +0 -31
  246. package/source/commands/exit-command.ts +0 -18
  247. package/source/commands/files-command.ts +0 -85
  248. package/source/commands/generate-rules-command.ts +0 -82
  249. package/source/commands/help-command.ts +0 -27
  250. package/source/commands/init-command.ts +0 -48
  251. package/source/commands/last-log-command.ts +0 -88
  252. package/source/commands/manager.ts +0 -151
  253. package/source/commands/model-command.ts +0 -123
  254. package/source/commands/paste-command.ts +0 -62
  255. package/source/commands/prompt-command.ts +0 -150
  256. package/source/commands/reset-command.ts +0 -22
  257. package/source/commands/rules-command.ts +0 -76
  258. package/source/commands/save-command.ts +0 -20
  259. package/source/commands/types.ts +0 -28
  260. package/source/commands/usage-command.ts +0 -26
  261. package/source/config.ts +0 -223
  262. package/source/conversation-analyzer.ts +0 -115
  263. package/source/dedent.ts +0 -53
  264. package/source/formatting.ts +0 -132
  265. package/source/index.ts +0 -240
  266. package/source/logger.ts +0 -29
  267. package/source/mentions.ts +0 -227
  268. package/source/messages.ts +0 -360
  269. package/source/middleware/audit-message.ts +0 -133
  270. package/source/middleware/index.ts +0 -2
  271. package/source/middleware/rate-limit.ts +0 -24
  272. package/source/models/ai-config.ts +0 -109
  273. package/source/models/anthropic-provider.ts +0 -199
  274. package/source/models/deepseek-provider.ts +0 -53
  275. package/source/models/google-provider.ts +0 -68
  276. package/source/models/manager.ts +0 -84
  277. package/source/models/openai-provider.ts +0 -81
  278. package/source/models/openrouter-provider.ts +0 -288
  279. package/source/models/providers.ts +0 -197
  280. package/source/models/xai-provider.ts +0 -59
  281. package/source/parsing.ts +0 -20
  282. package/source/prompts/manager.ts +0 -90
  283. package/source/prompts.ts +0 -172
  284. package/source/repl-prompt.ts +0 -196
  285. package/source/repl.ts +0 -572
  286. package/source/terminal/formatting.ts +0 -121
  287. package/source/terminal/index.ts +0 -518
  288. package/source/terminal/markdown-utils.ts +0 -89
  289. package/source/terminal/markdown.ts +0 -155
  290. package/source/terminal/types.ts +0 -84
  291. package/source/terminal-output.test.ts +0 -266
  292. package/source/token-tracker.ts +0 -78
  293. package/source/token-utils.ts +0 -17
  294. package/source/tools/agent.ts +0 -107
  295. package/source/tools/bash.ts +0 -367
  296. package/source/tools/code-interpreter.ts +0 -172
  297. package/source/tools/command-validation.ts +0 -81
  298. package/source/tools/delete-file.ts +0 -71
  299. package/source/tools/directory-tree.ts +0 -54
  300. package/source/tools/edit-file.ts +0 -155
  301. package/source/tools/filesystem-utils.ts +0 -265
  302. package/source/tools/git-utils.ts +0 -70
  303. package/source/tools/grep.ts +0 -184
  304. package/source/tools/index.ts +0 -278
  305. package/source/tools/memory-read.ts +0 -174
  306. package/source/tools/memory-write.ts +0 -105
  307. package/source/tools/move-file.ts +0 -59
  308. package/source/tools/read-file.ts +0 -129
  309. package/source/tools/read-multiple-files.ts +0 -80
  310. package/source/tools/save-file.ts +0 -147
  311. package/source/tools/think.ts +0 -51
  312. package/source/tools/types.ts +0 -58
  313. package/source/tools/web-fetch.ts +0 -327
  314. package/source/tools/web-search.ts +0 -101
  315. package/source/utils/process.ts +0 -121
  316. package/source/version.ts +0 -21
  317. package/test/commands/copy-command.test.ts +0 -69
  318. package/test/config.test.ts +0 -200
  319. package/test/terminal/markdown-utils.test.ts +0 -124
  320. package/test/tools/bash-tool.test.ts +0 -58
  321. package/test/tools/code-interpreter.test.ts +0 -91
  322. package/test/tools/command-validation.test.ts +0 -48
  323. package/tsconfig.build.json +0 -9
  324. package/tsconfig.json +0 -30
@@ -1,16 +1,48 @@
1
1
  import { memoize } from "@travisennis/stdlib/functional";
2
- import { simpleGit } from "simple-git";
3
2
  import { executeCommand } from "../utils/process.js";
4
3
  // Function to get diff stats
5
4
  export async function getDiffStat() {
6
- const git = simpleGit(process.cwd());
7
5
  try {
8
6
  // Get diff stat comparing working directory to HEAD
9
- const diffSummary = await git.diffSummary(["--stat"]);
7
+ const result = await executeCommand(["git", "diff", "--stat"], {
8
+ cwd: process.cwd(),
9
+ throwOnError: false,
10
+ });
11
+ if (result.code !== 0) {
12
+ console.error("Error getting git diff stat:", result.stderr);
13
+ return {
14
+ filesChanged: 0,
15
+ insertions: 0,
16
+ deletions: 0,
17
+ };
18
+ }
19
+ // Parse the git diff --stat output
20
+ // Example output: " 3 files changed, 15 insertions(+), 3 deletions(-)"
21
+ const statLine = result.stdout.trim();
22
+ if (!statLine) {
23
+ return {
24
+ filesChanged: 0,
25
+ insertions: 0,
26
+ deletions: 0,
27
+ };
28
+ }
29
+ // Extract numbers using regex
30
+ const filesMatch = statLine.match(/(\d+) files? changed/);
31
+ const insertionsMatch = statLine.match(/(\d+) insertion/);
32
+ const deletionsMatch = statLine.match(/(\d+) deletion/);
33
+ const filesChanged = filesMatch?.[1]
34
+ ? Number.parseInt(filesMatch[1], 10)
35
+ : 0;
36
+ const insertions = insertionsMatch?.[1]
37
+ ? Number.parseInt(insertionsMatch[1], 10)
38
+ : 0;
39
+ const deletions = deletionsMatch?.[1]
40
+ ? Number.parseInt(deletionsMatch[1], 10)
41
+ : 0;
10
42
  return {
11
- filesChanged: diffSummary.files.length,
12
- insertions: diffSummary.insertions,
13
- deletions: diffSummary.deletions,
43
+ filesChanged,
44
+ insertions,
45
+ deletions,
14
46
  };
15
47
  }
16
48
  catch (error) {
@@ -23,6 +55,43 @@ export async function getDiffStat() {
23
55
  };
24
56
  }
25
57
  }
58
+ export async function getGitStatus() {
59
+ // Git status processing (optimized)
60
+ const result = await executeCommand(["git", "status", "--porcelain"], {
61
+ cwd: process.cwd(),
62
+ throwOnError: false,
63
+ });
64
+ let added = 0;
65
+ let modified = 0;
66
+ let deleted = 0;
67
+ let untracked = 0;
68
+ if (result.code === 0) {
69
+ const lines = result.stdout.split("\n");
70
+ for (const line of lines) {
71
+ if (!line)
72
+ continue;
73
+ const s = line.slice(0, 2);
74
+ if (s[0] === "A" || s === "M ")
75
+ added++;
76
+ else if (s[1] === "M" || s === " M")
77
+ modified++;
78
+ else if (s[0] === "D" || s === " D")
79
+ deleted++;
80
+ else if (s === "??")
81
+ untracked++;
82
+ }
83
+ // if (added) gitStatus += ` +${added}`;
84
+ // if (modified) gitStatus += ` ~${modified}`;
85
+ // if (deleted) gitStatus += ` -${deleted}`;
86
+ // if (untracked) gitStatus += ` ?${untracked}`;
87
+ }
88
+ return {
89
+ added,
90
+ modified,
91
+ deleted,
92
+ untracked,
93
+ };
94
+ }
26
95
  export const inGitDirectory = memoize(async () => {
27
96
  const { code } = await executeCommand(["git", "rev-parse", "--is-inside-work-tree"], {
28
97
  cwd: process.cwd(),
@@ -37,10 +106,13 @@ export async function hasUncommittedChanges() {
37
106
  if (!(await inGitDirectory())) {
38
107
  return false;
39
108
  }
40
- const git = simpleGit(process.cwd());
41
109
  try {
42
- const status = await git.status();
43
- return status.files.length > 0;
110
+ const result = await executeCommand(["git", "status", "--porcelain"], {
111
+ cwd: process.cwd(),
112
+ throwOnError: false,
113
+ });
114
+ // If there are uncommitted changes, --porcelain will output lines for each changed file
115
+ return result.stdout.trim().length > 0;
44
116
  }
45
117
  catch {
46
118
  return false;
@@ -53,10 +125,15 @@ export async function getCurrentBranch() {
53
125
  if (!(await inGitDirectory())) {
54
126
  return null;
55
127
  }
56
- const git = simpleGit(process.cwd());
57
128
  try {
58
- const branch = await git.revparse(["--abbrev-ref", "HEAD"]);
59
- return branch.trim();
129
+ const result = await executeCommand(["git", "rev-parse", "--abbrev-ref", "HEAD"], {
130
+ cwd: process.cwd(),
131
+ throwOnError: false,
132
+ });
133
+ if (result.code !== 0) {
134
+ return null;
135
+ }
136
+ return result.stdout.trim();
60
137
  }
61
138
  catch {
62
139
  return null;
@@ -13,5 +13,25 @@ export declare const createGrepTool: (options?: {
13
13
  filePattern: string | null;
14
14
  contextLines: number | null;
15
15
  searchIgnored: boolean | null;
16
+ literal: boolean | null;
16
17
  }, string>;
17
18
  };
19
+ interface GrepOptions {
20
+ recursive?: boolean | null;
21
+ ignoreCase?: boolean | null;
22
+ filePattern?: string | null;
23
+ contextLines?: number | null;
24
+ searchIgnored?: boolean | null;
25
+ literal?: boolean | null;
26
+ }
27
+ /**
28
+ * Search files for patterns using ripgrep
29
+ *
30
+ * @param pattern - The regex pattern to search for
31
+ * @param path - The path to search in
32
+ * @param options - Additional options for the grep command
33
+ * @returns The result of the grep command
34
+ */
35
+ export declare function buildGrepCommand(pattern: string, path: string, options?: GrepOptions): string;
36
+ export declare function grepFiles(pattern: string, path: string, options?: GrepOptions): string;
37
+ export {};
@@ -34,20 +34,54 @@ export const createGrepTool = (options = {}) => {
34
34
  .boolean()
35
35
  .nullable()
36
36
  .describe("Pass null to use the default (false, don't search ignored files)."),
37
+ literal: z
38
+ .boolean()
39
+ .nullable()
40
+ .describe("Pass true to search as a fixed string (no regex). Pass null to auto-detect."),
37
41
  }),
38
- execute: ({ pattern, path, recursive, ignoreCase, filePattern, contextLines, searchIgnored, }, { toolCallId }) => {
42
+ execute: ({ pattern, path, recursive, ignoreCase, filePattern, contextLines, searchIgnored, literal, }, { toolCallId }) => {
39
43
  try {
40
44
  sendData?.({
41
45
  event: "tool-init",
42
46
  id: toolCallId,
43
47
  data: `Searching codebase for "${chalk.cyan(inspect(pattern))}" in ${chalk.cyan(path)}`,
44
48
  });
49
+ // Normalize literal option: if null => auto-detect using heuristic
50
+ let effectiveLiteral = null;
51
+ if (literal === true) {
52
+ effectiveLiteral = true;
53
+ }
54
+ else if (literal === false) {
55
+ effectiveLiteral = false;
56
+ }
57
+ else {
58
+ // auto-detect
59
+ try {
60
+ if (likelyUnbalancedRegex(pattern)) {
61
+ effectiveLiteral = true;
62
+ sendData?.({
63
+ event: "tool-update",
64
+ id: toolCallId,
65
+ data: {
66
+ primary: "Pattern appears to contain unbalanced regex metacharacters; using fixed-string mode (-F).",
67
+ },
68
+ });
69
+ }
70
+ else {
71
+ effectiveLiteral = false;
72
+ }
73
+ }
74
+ catch (_err) {
75
+ effectiveLiteral = false;
76
+ }
77
+ }
45
78
  const result = grepFiles(pattern, path, {
46
79
  recursive,
47
80
  ignoreCase,
48
81
  filePattern,
49
82
  contextLines,
50
83
  searchIgnored,
84
+ literal: effectiveLiteral,
51
85
  });
52
86
  const matchCount = result === "No matches found."
53
87
  ? 0
@@ -58,11 +92,6 @@ export const createGrepTool = (options = {}) => {
58
92
  if (line === "--") {
59
93
  return false;
60
94
  }
61
- // A match line from ripgrep with --line-number has the format:
62
- // path:linenumber:match
63
- // A context line has the format:
64
- // path-linenumber-match
65
- // This regex distinguishes between them by looking for the colon after the line number.
66
95
  return /^(.+?):(\d+):(.*)$/.test(line);
67
96
  }).length;
68
97
  sendData?.({
@@ -84,6 +113,53 @@ export const createGrepTool = (options = {}) => {
84
113
  }),
85
114
  };
86
115
  };
116
+ function likelyUnbalancedRegex(pattern) {
117
+ const counts = {
118
+ openParen: 0,
119
+ closeParen: 0,
120
+ openBracket: 0,
121
+ closeBracket: 0,
122
+ openBrace: 0,
123
+ closeBrace: 0,
124
+ };
125
+ let escaped = false;
126
+ for (let i = 0; i < pattern.length; i++) {
127
+ const ch = pattern[i];
128
+ if (escaped) {
129
+ escaped = false;
130
+ continue;
131
+ }
132
+ if (ch === "\\") {
133
+ escaped = true;
134
+ continue;
135
+ }
136
+ switch (ch) {
137
+ case "(":
138
+ counts.openParen++;
139
+ break;
140
+ case ")":
141
+ counts.closeParen++;
142
+ break;
143
+ case "[":
144
+ counts.openBracket++;
145
+ break;
146
+ case "]":
147
+ counts.closeBracket++;
148
+ break;
149
+ case "{":
150
+ counts.openBrace++;
151
+ break;
152
+ case "}":
153
+ counts.closeBrace++;
154
+ break;
155
+ default:
156
+ break;
157
+ }
158
+ }
159
+ return (counts.openParen !== counts.closeParen ||
160
+ counts.openBracket !== counts.closeBracket ||
161
+ counts.openBrace !== counts.closeBrace);
162
+ }
87
163
  /**
88
164
  * Search files for patterns using ripgrep
89
165
  *
@@ -92,45 +168,57 @@ export const createGrepTool = (options = {}) => {
92
168
  * @param options - Additional options for the grep command
93
169
  * @returns The result of the grep command
94
170
  */
95
- function grepFiles(pattern, path, options = {}) {
171
+ export function buildGrepCommand(pattern, path, options = {}) {
172
+ const effectiveRecursive = options.recursive === null ? true : options.recursive;
173
+ const effectiveIgnoreCase = options.ignoreCase === null ? false : options.ignoreCase;
174
+ const effectiveSearchIgnored = options.searchIgnored === null ? false : options.searchIgnored;
175
+ const effectiveFilePattern = options.filePattern;
176
+ const effectiveContextLines = options.contextLines;
177
+ // Determine literal handling: if options.literal is explicitly provided, use it.
178
+ // If null/undefined, auto-detect unbalanced regexes and prefer fixed-strings.
179
+ let effectiveLiteral;
180
+ if (options.literal === true) {
181
+ effectiveLiteral = true;
182
+ }
183
+ else if (options.literal === false) {
184
+ effectiveLiteral = false;
185
+ }
186
+ else {
187
+ effectiveLiteral = likelyUnbalancedRegex(pattern);
188
+ }
189
+ let command = "rg --line-number";
190
+ if (effectiveRecursive === false) {
191
+ command += " --max-depth=0";
192
+ }
193
+ if (effectiveIgnoreCase) {
194
+ command += " --ignore-case";
195
+ }
196
+ if (effectiveContextLines !== null && effectiveContextLines !== undefined) {
197
+ command += ` --context=${effectiveContextLines}`;
198
+ }
199
+ if (effectiveFilePattern !== null && effectiveFilePattern !== undefined) {
200
+ command += ` --glob=${JSON.stringify(effectiveFilePattern)}`;
201
+ }
202
+ if (effectiveSearchIgnored) {
203
+ command += " --no-ignore";
204
+ }
205
+ if (effectiveLiteral) {
206
+ command += " -F";
207
+ }
208
+ command += ` ${JSON.stringify(pattern)}`;
209
+ command += ` ${path}`;
210
+ return command;
211
+ }
212
+ export function grepFiles(pattern, path, options = {}) {
96
213
  try {
97
- // Handle null values by providing defaults
98
- const effectiveRecursive = options.recursive === null ? true : options.recursive;
99
- const effectiveIgnoreCase = options.ignoreCase === null ? false : options.ignoreCase;
100
- const effectiveSearchIgnored = options.searchIgnored === null ? false : options.searchIgnored;
101
- const effectiveFilePattern = options.filePattern;
102
- const effectiveContextLines = options.contextLines;
103
- // Build the ripgrep command
104
- let command = "rg --line-number";
105
- // Ripgrep is recursive by default, so we only need to add
106
- // --no-recursive if effectiveRecursive is explicitly false
107
- if (effectiveRecursive === false) {
108
- command += " --max-depth=0";
109
- }
110
- if (effectiveIgnoreCase) {
111
- command += " --ignore-case";
112
- }
113
- if (effectiveContextLines !== null && effectiveContextLines !== undefined) {
114
- command += ` --context=${effectiveContextLines}`;
115
- }
116
- // Add pattern (escaped for shell)
117
- command += ` ${JSON.stringify(pattern)}`;
118
- // Add path
119
- command += ` ${path}`;
120
- // Add file pattern if specified
121
- if (effectiveFilePattern !== null && effectiveFilePattern !== undefined) {
122
- command += ` --glob=${JSON.stringify(effectiveFilePattern)}`;
123
- }
124
- if (effectiveSearchIgnored) {
125
- command += " --no-ignore";
126
- }
127
- // Execute the command
214
+ const command = buildGrepCommand(pattern, path, options);
128
215
  const result = execSync(command, { encoding: "utf-8" });
129
216
  return result;
130
217
  }
131
218
  catch (error) {
132
- if (error instanceof Error && "status" in error && error.status === 1) {
133
- // Status 1 in ripgrep just means "no matches found"
219
+ if (error instanceof Error &&
220
+ "status" in error &&
221
+ error.status === 1) {
134
222
  return "No matches found.";
135
223
  }
136
224
  throw new Error(`Error executing ripgrep: ${error.message}`);
@@ -9,15 +9,6 @@ export declare function initTools({ terminal, tokenCounter, events, autoAcceptAl
9
9
  events: Map<string, Message[]>;
10
10
  autoAcceptAll: boolean;
11
11
  }): Promise<{
12
- readonly memoryWrite: import("ai").Tool<{
13
- filePath: string;
14
- content: string;
15
- }, string>;
16
- readonly memoryRead: import("ai").Tool<{
17
- filePath: string | null;
18
- }, string | {
19
- content: string;
20
- }>;
21
12
  readonly webSearch: import("ai").Tool<{
22
13
  query: string;
23
14
  }, string>;
@@ -40,6 +31,7 @@ export declare function initTools({ terminal, tokenCounter, events, autoAcceptAl
40
31
  filePattern: string | null;
41
32
  contextLines: number | null;
42
33
  searchIgnored: boolean | null;
34
+ literal: boolean | null;
43
35
  }, string>;
44
36
  readonly codeInterpreter: import("ai").Tool<{
45
37
  code: string;
@@ -80,15 +72,6 @@ export declare function initTools({ terminal, tokenCounter, events, autoAcceptAl
80
72
  export declare function initCliTools({ tokenCounter, }: {
81
73
  tokenCounter: TokenCounter;
82
74
  }): Promise<{
83
- readonly memoryWrite: import("ai").Tool<{
84
- filePath: string;
85
- content: string;
86
- }, string>;
87
- readonly memoryRead: import("ai").Tool<{
88
- filePath: string | null;
89
- }, string | {
90
- content: string;
91
- }>;
92
75
  readonly webSearch: import("ai").Tool<{
93
76
  query: string;
94
77
  }, string>;
@@ -111,6 +94,7 @@ export declare function initCliTools({ tokenCounter, }: {
111
94
  filePattern: string | null;
112
95
  contextLines: number | null;
113
96
  searchIgnored: boolean | null;
97
+ literal: boolean | null;
114
98
  }, string>;
115
99
  readonly codeInterpreter: import("ai").Tool<{
116
100
  code: string;
@@ -5,8 +5,6 @@ import { createDeleteFileTool } from "./delete-file.js";
5
5
  import { createDirectoryTreeTool } from "./directory-tree.js";
6
6
  import { createEditFileTool } from "./edit-file.js";
7
7
  import { createGrepTool } from "./grep.js";
8
- import { createMemoryReadTool } from "./memory-read.js";
9
- import { createMemoryWriteTool } from "./memory-write.js";
10
8
  import { createMoveFileTool } from "./move-file.js";
11
9
  import { createReadFileTool } from "./read-file.js";
12
10
  import { createReadMultipleFilesTool } from "./read-multiple-files.js";
@@ -60,6 +58,8 @@ export async function initTools({ terminal, tokenCounter, events, autoAcceptAll,
60
58
  const deleteFileTool = await createDeleteFileTool({
61
59
  workingDir: process.cwd(),
62
60
  sendData: sendDataFn,
61
+ terminal,
62
+ autoAcceptAll,
63
63
  });
64
64
  const codeInterpreterTool = createCodeInterpreterTool({
65
65
  sendData: sendDataFn,
@@ -85,12 +85,6 @@ export async function initTools({ terminal, tokenCounter, events, autoAcceptAll,
85
85
  terminal,
86
86
  autoAcceptAll,
87
87
  });
88
- const memoryReadTool = createMemoryReadTool({
89
- sendData: sendDataFn,
90
- });
91
- const memoryWriteTool = createMemoryWriteTool({
92
- sendData: sendDataFn,
93
- });
94
88
  const tools = {
95
89
  ...readFileTool,
96
90
  ...readMultipleFilesTool,
@@ -105,8 +99,6 @@ export async function initTools({ terminal, tokenCounter, events, autoAcceptAll,
105
99
  ...webFetchTool,
106
100
  ...bashTool,
107
101
  ...webSearchTool,
108
- ...memoryReadTool,
109
- ...memoryWriteTool,
110
102
  };
111
103
  return tools;
112
104
  }
@@ -144,6 +136,8 @@ export async function initCliTools({ tokenCounter, }) {
144
136
  const deleteFileTool = await createDeleteFileTool({
145
137
  workingDir: process.cwd(),
146
138
  sendData: undefined,
139
+ terminal: undefined,
140
+ autoAcceptAll: true,
147
141
  });
148
142
  const codeInterpreterTool = createCodeInterpreterTool({
149
143
  sendData: undefined,
@@ -169,12 +163,6 @@ export async function initCliTools({ tokenCounter, }) {
169
163
  terminal: undefined,
170
164
  autoAcceptAll: true,
171
165
  });
172
- const memoryReadTool = createMemoryReadTool({
173
- sendData: undefined,
174
- });
175
- const memoryWriteTool = createMemoryWriteTool({
176
- sendData: undefined,
177
- });
178
166
  const tools = {
179
167
  ...readFileTool,
180
168
  ...readMultipleFilesTool,
@@ -189,8 +177,6 @@ export async function initCliTools({ tokenCounter, }) {
189
177
  ...webFetchTool,
190
178
  ...bashTool,
191
179
  ...webSearchTool,
192
- ...memoryReadTool,
193
- ...memoryWriteTool,
194
180
  };
195
181
  return tools;
196
182
  }
package/package.json CHANGED
@@ -1,11 +1,19 @@
1
1
  {
2
2
  "name": "@travisennis/acai",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "An AI assistant for developing software.",
5
5
  "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
6
8
  "bin": {
7
- "acai": "dist/index.js"
9
+ "acai": "dist/index.js",
10
+ "@travisennis/acai": "dist/index.js"
8
11
  },
12
+ "files": [
13
+ "dist",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
9
17
  "keywords": [
10
18
  "cli",
11
19
  "ai",
@@ -17,12 +25,13 @@
17
25
  "license": "MIT",
18
26
  "scripts": {
19
27
  "build": "tsc --pretty -p tsconfig.build.json",
20
- "clean": "rm -rf ./dist/",
28
+ "clean": "rm -rf ./dist/ ./tsconfig.build.tsbuildinfo",
21
29
  "compile": "tsc --pretty -p tsconfig.json",
22
30
  "lint": "biome lint",
23
31
  "lint:fix": "biome lint --unsafe --write",
24
32
  "lint:staged": "biome lint --error-on-warnings --no-errors-on-unmatched --staged",
25
33
  "format:staged": "biome check --staged --formatter-enabled=true --linter-enabled=false --no-errors-on-unmatched",
34
+ "prepack": "npm run clean && npm run build",
26
35
  "prepare": "husky",
27
36
  "test": "c8 node --no-warnings --test test/**/*.test.ts",
28
37
  "pretest": "npm run compile",
@@ -35,48 +44,49 @@
35
44
  "typecheck:staged": "tsc --noEmit --pretty -p tsconfig.json"
36
45
  },
37
46
  "dependencies": {
38
- "@ai-sdk/anthropic": "^2.0.2",
39
- "@ai-sdk/deepseek": "^1.0.6",
40
- "@ai-sdk/google": "^2.0.5",
41
- "@ai-sdk/openai": "^2.0.11",
42
- "@ai-sdk/openai-compatible": "^1.0.6",
47
+ "@ai-sdk/anthropic": "^2.0.6",
48
+ "@ai-sdk/deepseek": "^1.0.11",
49
+ "@ai-sdk/google": "^2.0.8",
50
+ "@ai-sdk/openai": "^2.0.20",
51
+ "@ai-sdk/openai-compatible": "^1.0.11",
43
52
  "@crosscopy/clipboard": "^0.2.8",
44
- "@inquirer/prompts": "^7.8.1",
45
- "@travisennis/stdlib": "^0.0.13",
46
- "ai": "^5.0.11",
47
- "chalk": "^5.5.0",
53
+ "@inquirer/prompts": "^7.8.4",
54
+ "@travisennis/stdlib": "^0.0.14",
55
+ "ai": "^5.0.23",
56
+ "chalk": "^5.6.0",
48
57
  "cheerio": "^1.1.2",
49
58
  "cli-highlight": "^2.1.11",
50
59
  "cli-table3": "^0.6.5",
51
60
  "diff": "^8.0.2",
52
61
  "duck-duck-scrape": "^2.2.7",
53
- "exa-js": "^1.8.27",
62
+ "exa-js": "^1.9.2",
54
63
  "globby": "^14.1.0",
55
64
  "ignore": "^7.0.5",
56
65
  "log-update": "^6.1.0",
57
- "marked": "16.1.2",
58
- "node-notifier": "^10.0.1",
66
+ "marked": "16.2.0",
59
67
  "ora": "^8.2.0",
60
- "p-throttle": "^7.0.0",
61
- "pino": "^9.8.0",
68
+ "p-throttle": "^8.0.0",
69
+ "pino": "^9.9.0",
62
70
  "pino-pretty": "^13.1.1",
63
71
  "pino-roll": "^3.1.0",
64
- "simple-git": "^3.28.0",
65
72
  "tiktoken": "^1.0.22",
66
73
  "wrap-ansi": "^9.0.0",
67
74
  "zod": "^3.25.75"
68
75
  },
69
76
  "devDependencies": {
70
77
  "@ai-sdk/provider": "^2.0.0",
71
- "@biomejs/biome": "2.1.4",
78
+ "@biomejs/biome": "2.2.2",
72
79
  "@commitlint/config-conventional": "^19.8.1",
73
- "@types/node": "^24.2.1",
80
+ "@types/node": "^24.3.0",
74
81
  "@types/node-notifier": "^8.0.5",
75
82
  "c8": "^10.1.3",
76
83
  "commitlint": "^19.8.1",
77
84
  "husky": "^9.1.7",
78
85
  "typescript": "^5.9.2"
79
86
  },
87
+ "engines": {
88
+ "node": ">=20"
89
+ },
80
90
  "publishConfig": {
81
91
  "access": "public"
82
92
  }
package/.acai/acai.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "logs": {
3
- "path": "/Users/travisennis/.acai/logs/current.log"
4
- },
5
- "tools": {
6
- "maxTokens": 30000
7
- },
8
- "notify": true
9
- }
@@ -1,13 +0,0 @@
1
- Your task it to add a new model to the ./source/model/openrouter-provider.ts.
2
-
3
- I want you to accomplish this by writing a javascript script and executing it with the code-interpreter tool.
4
-
5
- This script should do the following:
6
- 1. fetch `openrouter.ai/api/v1/models` using https
7
- 2. parse the json response. the shape should be `{"data":[]}`
8
- 3. filter the `data` array to find the object whose `id` is `{{INPUT}}`
9
- 4. log the model information found in the object
10
-
11
- Take that model information and use it to add a new model to openrouter-provider.ts. Follow the pattern that exists to add a new model. If any information is missing ask the user to provide guidance.
12
-
13
- Create a new git branch before making any edits.
@@ -1,4 +0,0 @@
1
- Summarize the current git status of this project.
2
-
3
- Status:
4
- !`git status`
@@ -1,9 +0,0 @@
1
- Manage the ./ARCHITECTURE.md document for this project. If file doesn't exist create it. If it does exist make sure it is up-to-date and reflects the current state of the project.
2
-
3
- The main header of the document should be Acai Architecture.
4
-
5
- Include a Project Structure that is the current directory tree for the entire project.
6
-
7
- Next, there should be section called File Descriptions that should include a list of every file in the project and a brief description of what each is and does.
8
-
9
- Finally, a section called Flow Diagram should document with mermaid diagrams the primary flows in the application, starting with the entry points defined in the package.json.
@@ -1,9 +0,0 @@
1
- - Always adhere to existing code patterns and project conventions when generating code.
2
- - Always explicitly ask for user confirmation before committing changes.
3
- - Always replace usages console.log with usages of console.info.
4
- - Always run a build after making code changes to verify correctness.
5
- - Always use the most efficient workflow to complete tasks.
6
- - Always stage changes before attempting to commit them.
7
- - Never amend git commits without approval from the user.
8
- - Never use `git add -A` when preparing for multiple, distinct commits; instead, selectively add files or hunks relevant to each commit.
9
- - Always use `git checkout -b <branch-name>` with a branch name that accurately reflects the *type* of changes being made.
@@ -1,3 +0,0 @@
1
- Available tools:
2
-
3
- bashTool