@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
package/README.md CHANGED
@@ -41,7 +41,6 @@ Acai is built primarily with **TypeScript** and runs on **Node.js**. Key technol
41
41
  * **Tree-sitter:** For robust and efficient code parsing and syntax analysis across multiple programming languages (TypeScript, JavaScript, Java, Python).
42
42
  * **`chalk`, `ora`, `log-update`:** For rich and interactive terminal output.
43
43
  * **`@inquirer/prompts`:** For interactive prompts; CLI args parsed with Node's `util.parseArgs`.
44
- * **`simple-git`:** For Git operations.
45
44
  * **`ripgrep` (via `grep.ts` tool):** For fast file content searching.
46
45
  * **`marked`:** For rendering Markdown in the terminal.
47
46
  * **`pino`:** For structured logging.
@@ -53,7 +52,7 @@ Acai is built primarily with **TypeScript** and runs on **Node.js**. Key technol
53
52
  ### Prerequisites
54
53
 
55
54
  **Required:**
56
- * Node.js 18.20.0 or higher
55
+ * Node.js 20 or higher
57
56
  * Git
58
57
  * [Ripgrep](https://github.com/BurntSushi/ripgrep) (`rg` command) - Fast file content searching
59
58
  * [GitHub CLI](https://cli.github.com/) (`gh` command) - Git operations and repository management
@@ -118,7 +117,7 @@ OPENAI_API_KEY=your_openai_api_key_here
118
117
  ANTHROPIC_API_KEY=your_anthropic_api_key_here
119
118
 
120
119
  # Google (Gemini models)
121
- GOOGLE_API_KEY=your_google_api_key_here
120
+ GOOGLE_GENERATIVE_AI_API_KEY=your_google_api_key_here
122
121
 
123
122
  # DeepSeek
124
123
  DEEPSEEK_API_KEY=your_deepseek_api_key_here
@@ -159,7 +158,7 @@ OPENAI_API_KEY=sk-...
159
158
  ANTHROPIC_API_KEY=sk-ant-...
160
159
 
161
160
  # Optional: Additional providers
162
- GOOGLE_API_KEY=...
161
+ GOOGLE_GENERATIVE_AI_API_KEY=...
163
162
  OPENROUTER_API_KEY=sk-or-...
164
163
 
165
164
  # Optional: Web services (fallbacks available if not provided)
@@ -0,0 +1,2 @@
1
+ import type { CommandOptions, ReplCommand } from "./types.ts";
2
+ export declare function healthCommand({ terminal }: CommandOptions): ReplCommand;
@@ -0,0 +1,59 @@
1
+ export function healthCommand({ terminal }) {
2
+ return {
3
+ command: "/health",
4
+ description: "Show application health status and environment variables",
5
+ result: "continue",
6
+ getSubCommands: () => Promise.resolve([]),
7
+ execute() {
8
+ // Define the environment variables we care about
9
+ const envVars = [
10
+ // AI Provider API Keys
11
+ { name: "OPENAI_API_KEY", description: "OpenAI (GPT models)" },
12
+ { name: "ANTHROPIC_API_KEY", description: "Anthropic (Claude models)" },
13
+ {
14
+ name: "GOOGLE_GENERATIVE_AI_API_KEY",
15
+ description: "Google (Gemini models)",
16
+ },
17
+ { name: "DEEPSEEK_API_KEY", description: "DeepSeek" },
18
+ { name: "X_AI_API_KEY", description: "X.AI (Grok models)" },
19
+ { name: "XAI_API_KEY", description: "X.AI (Grok models - alt)" },
20
+ {
21
+ name: "OPENROUTER_API_KEY",
22
+ description: "OpenRouter (multiple models)",
23
+ },
24
+ // Web Service API Keys
25
+ { name: "EXA_API_KEY", description: "Exa (enhanced web search)" },
26
+ {
27
+ name: "JINA_READER_API_KEY",
28
+ description: "Jina Reader (web content extraction)",
29
+ },
30
+ // Application Configuration
31
+ { name: "LOG_LEVEL", description: "Logging level" },
32
+ ];
33
+ // Check each environment variable
34
+ const envStatus = envVars.map((envVar) => {
35
+ const value = process.env[envVar.name];
36
+ const hasValue = value !== undefined && value !== null && value.trim() !== "";
37
+ const status = hasValue ? "✓ Set" : "✗ Not set";
38
+ return [envVar.name, status, envVar.description];
39
+ });
40
+ // Display the table
41
+ terminal.info("Environment Variables Status:");
42
+ terminal.table(envStatus, {
43
+ header: ["Variable", "Status", "Description"],
44
+ colWidths: [30, 15, 55],
45
+ });
46
+ // Count how many are set (derived from envStatus to avoid re-checking process.env)
47
+ const setCount = envStatus.filter((row) => row[1] === "✓ Set").length;
48
+ const totalCount = envVars.length;
49
+ terminal.info(`\nSummary: ${setCount}/${totalCount} environment variables are set`);
50
+ if (setCount === 0) {
51
+ terminal.warn("⚠️ No AI provider API keys are configured. The app may not function properly.");
52
+ }
53
+ else {
54
+ terminal.info("✓ At least one AI provider is configured.");
55
+ }
56
+ return Promise.resolve();
57
+ },
58
+ };
59
+ }
@@ -7,6 +7,7 @@ import { editPromptCommand } from "./edit-prompt-command.js";
7
7
  import { exitCommand } from "./exit-command.js";
8
8
  import { filesCommand } from "./files-command.js";
9
9
  import { generateRulesCommand } from "./generate-rules-command.js";
10
+ import { healthCommand } from "./health-command.js";
10
11
  import { helpCommand } from "./help-command.js";
11
12
  import { initCommand } from "./init-command.js";
12
13
  import { lastLogCommand } from "./last-log-command.js";
@@ -59,6 +60,7 @@ export class CommandManager {
59
60
  editPromptCommand(options),
60
61
  exitCommand(options),
61
62
  filesCommand(options),
63
+ healthCommand(options),
62
64
  initCommand(options),
63
65
  pasteCommand(options),
64
66
  promptCommand(options),
@@ -1,2 +1,2 @@
1
1
  import type { CommandOptions, ReplCommand } from "./types.ts";
2
- export declare const pasteCommand: ({ terminal, modelManager, promptManager, }: CommandOptions) => ReplCommand;
2
+ export declare const pasteCommand: ({ terminal, modelManager, promptManager, tokenCounter, }: CommandOptions) => ReplCommand;
@@ -1,8 +1,104 @@
1
1
  import Clipboard from "@crosscopy/clipboard";
2
2
  import { formatBlock } from "../formatting.js";
3
3
  import { logger } from "../logger.js";
4
- const base64UrlRegex = /^data:(.*?);base64,/;
5
- export const pasteCommand = ({ terminal, modelManager, promptManager, }) => {
4
+ function extractBase64Content(dataUrl) {
5
+ return dataUrl.replace(/^data:.*?;base64,/, "");
6
+ }
7
+ function isValidBase64(str) {
8
+ try {
9
+ // Remove data URL prefix if present
10
+ const base64Content = extractBase64Content(str);
11
+ // Try to decode the base64 string
12
+ const decoded = Buffer.from(base64Content, "base64");
13
+ // Re-encode to verify it's valid base64
14
+ const reEncoded = decoded.toString("base64");
15
+ // Remove padding for comparison
16
+ const normalizedOriginal = base64Content.replace(/=/g, "");
17
+ const normalizedReEncoded = reEncoded.replace(/=/g, "");
18
+ return normalizedOriginal === normalizedReEncoded;
19
+ }
20
+ catch {
21
+ return false;
22
+ }
23
+ }
24
+ function detectImageFormatFromBase64(base64Content) {
25
+ try {
26
+ const buffer = Buffer.from(base64Content, "base64");
27
+ // Check for JPEG signature (FF D8 FF)
28
+ if (buffer.length >= 3 &&
29
+ buffer[0] === 0xff &&
30
+ buffer[1] === 0xd8 &&
31
+ buffer[2] === 0xff) {
32
+ return "image/jpeg";
33
+ }
34
+ // Check for PNG signature (89 50 4E 47 0D 0A 1A 0A)
35
+ if (buffer.length >= 8 &&
36
+ buffer[0] === 0x89 &&
37
+ buffer[1] === 0x50 &&
38
+ buffer[2] === 0x4e &&
39
+ buffer[3] === 0x47 &&
40
+ buffer[4] === 0x0d &&
41
+ buffer[5] === 0x0a &&
42
+ buffer[6] === 0x1a &&
43
+ buffer[7] === 0x0a) {
44
+ return "image/png";
45
+ }
46
+ // Check for GIF signature (GIF87a or GIF89a)
47
+ if (buffer.length >= 6 &&
48
+ ((buffer[0] === 0x47 &&
49
+ buffer[1] === 0x49 &&
50
+ buffer[2] === 0x46 &&
51
+ buffer[3] === 0x38 &&
52
+ buffer[4] === 0x37 &&
53
+ buffer[5] === 0x61) ||
54
+ (buffer[0] === 0x47 &&
55
+ buffer[1] === 0x49 &&
56
+ buffer[2] === 0x46 &&
57
+ buffer[3] === 0x38 &&
58
+ buffer[4] === 0x39 &&
59
+ buffer[5] === 0x61))) {
60
+ return "image/gif";
61
+ }
62
+ // Check for WebP signature (RIFF .... WEBP)
63
+ if (buffer.length >= 12 &&
64
+ buffer[0] === 0x52 &&
65
+ buffer[1] === 0x49 &&
66
+ buffer[2] === 0x46 &&
67
+ buffer[3] === 0x46 &&
68
+ buffer[8] === 0x57 &&
69
+ buffer[9] === 0x45 &&
70
+ buffer[10] === 0x42 &&
71
+ buffer[11] === 0x50) {
72
+ return "image/webp";
73
+ }
74
+ // Check for BMP signature (BM)
75
+ if (buffer.length >= 2 && buffer[0] === 0x42 && buffer[1] === 0x4d) {
76
+ return "image/bmp";
77
+ }
78
+ // Check for TIFF signatures (II* or MM*)
79
+ if (buffer.length >= 4 &&
80
+ ((buffer[0] === 0x49 &&
81
+ buffer[1] === 0x49 &&
82
+ buffer[2] === 0x2a &&
83
+ buffer[3] === 0x00) ||
84
+ (buffer[0] === 0x4d &&
85
+ buffer[1] === 0x4d &&
86
+ buffer[2] === 0x00 &&
87
+ buffer[3] === 0x2a))) {
88
+ return "image/tiff";
89
+ }
90
+ // If no known signature found, fall back to the data URL MIME type
91
+ return "unknown";
92
+ }
93
+ catch {
94
+ return "unknown";
95
+ }
96
+ }
97
+ function extractMimeTypeFromDataUrl(dataUrl) {
98
+ const match = dataUrl.match(/^data:([^;]+);base64,/);
99
+ return match?.[1] ? match[1] : "image/png";
100
+ }
101
+ export const pasteCommand = ({ terminal, modelManager, promptManager, tokenCounter, }) => {
6
102
  return {
7
103
  command: "/paste",
8
104
  description: "Pastes image or text content from the clipboard into the next prompt.",
@@ -12,13 +108,59 @@ export const pasteCommand = ({ terminal, modelManager, promptManager, }) => {
12
108
  try {
13
109
  if (Clipboard.hasImage()) {
14
110
  const base64DataUrl = await Clipboard.getImageBase64();
15
- const mimeTypeMatch = base64DataUrl.match(base64UrlRegex);
16
- const mimeType = mimeTypeMatch ? mimeTypeMatch[1] : "image/png";
17
- promptManager.addContext({
18
- type: "image",
19
- image: base64DataUrl,
20
- mediaType: mimeType,
21
- });
111
+ // Validate the base64 data
112
+ if (!isValidBase64(base64DataUrl)) {
113
+ terminal.error("Invalid base64 data in clipboard. The image data may be corrupted.");
114
+ return;
115
+ }
116
+ // Extract MIME type with better error handling and actual image format detection
117
+ let mimeType;
118
+ try {
119
+ // First, try to get MIME type from data URL
120
+ const dataUrlMimeType = extractMimeTypeFromDataUrl(base64DataUrl);
121
+ // Then, detect actual image format from base64 content
122
+ const base64Content = extractBase64Content(base64DataUrl);
123
+ const detectedFormat = detectImageFormatFromBase64(base64Content);
124
+ // Use detected format if available, otherwise fall back to data URL MIME type
125
+ if (detectedFormat !== "unknown") {
126
+ mimeType = detectedFormat;
127
+ // Log if there's a mismatch between data URL and actual format
128
+ if (dataUrlMimeType !== detectedFormat) {
129
+ logger.warn(`Clipboard library reported ${dataUrlMimeType} but actual image format is ${detectedFormat}. Using detected format.`);
130
+ }
131
+ }
132
+ else {
133
+ mimeType = dataUrlMimeType;
134
+ logger.warn(`Could not detect image format, using data URL MIME type: ${mimeType}`);
135
+ }
136
+ }
137
+ catch (error) {
138
+ logger.warn(`Failed to extract MIME type from clipboard image: ${error}`);
139
+ mimeType = "image/png";
140
+ }
141
+ // Ensure the data URL format is correct
142
+ if (!base64DataUrl.startsWith(`data:${mimeType};base64,`)) {
143
+ // Fix malformed data URLs
144
+ const base64Content = base64DataUrl.replace(/^data:.*?;base64,/, "");
145
+ const correctedDataUrl = `data:${mimeType};base64,${base64Content}`;
146
+ // Final validation
147
+ if (!isValidBase64(correctedDataUrl)) {
148
+ terminal.error("Failed to correct base64 data format. The image data may be corrupted.");
149
+ return;
150
+ }
151
+ promptManager.addContext({
152
+ type: "image",
153
+ image: correctedDataUrl,
154
+ mediaType: mimeType,
155
+ });
156
+ }
157
+ else {
158
+ promptManager.addContext({
159
+ type: "image",
160
+ image: base64DataUrl,
161
+ mediaType: mimeType,
162
+ });
163
+ }
22
164
  terminal.success("Image from clipboard will be added to your next prompt.");
23
165
  return;
24
166
  }
@@ -27,8 +169,10 @@ export const pasteCommand = ({ terminal, modelManager, promptManager, }) => {
27
169
  terminal.warn("Clipboard is empty.");
28
170
  return;
29
171
  }
30
- promptManager.addContext(formatBlock(clipboardContent, "clipboard", modelManager.getModelMetadata("repl").promptFormat));
31
- terminal.success("Clipboard content will be added to your next prompt.");
172
+ const content = formatBlock(clipboardContent, "clipboard", modelManager.getModelMetadata("repl").promptFormat);
173
+ promptManager.addContext(content);
174
+ const tokenCount = tokenCounter.count(content);
175
+ terminal.success(`Clipboard content will be added to your next prompt. (${tokenCount} tokens)`);
32
176
  }
33
177
  catch (error) {
34
178
  const message = error instanceof Error ? error.message : String(error);
@@ -1,6 +1,7 @@
1
1
  export const resetCommand = ({ terminal, messageHistory, }) => {
2
2
  return {
3
3
  command: "/reset",
4
+ aliases: ["/new"],
4
5
  description: "Saves the chat history and then resets it.",
5
6
  result: "continue",
6
7
  getSubCommands: () => Promise.resolve([]),
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  declare const flags: {
2
3
  model?: string | undefined;
3
4
  prompt?: string | undefined;
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  import { text } from "node:stream/consumers";
2
3
  import { parseArgs } from "node:util";
3
4
  import { select } from "@inquirer/prompts";
@@ -106,7 +107,7 @@ async function main() {
106
107
  terminal.setTitle(`acai: ${process.cwd()}`);
107
108
  const chosenModel = isSupportedModel(flags.model)
108
109
  ? flags.model
109
- : "openrouter:sonnet4";
110
+ : "openrouter:glm-4.5";
110
111
  const modelManager = new ModelManager({
111
112
  stateDir: await appDir.ensurePath("audit"),
112
113
  });
@@ -1,6 +1,7 @@
1
1
  import type { ModelMetadata } from "./providers.ts";
2
2
  declare const openrouterModels: {
3
3
  readonly "deepseek-v3": import("@ai-sdk/provider").LanguageModelV2;
4
+ readonly "deepseek-v3-1": import("@ai-sdk/provider").LanguageModelV2;
4
5
  readonly "deepseek-r1": import("@ai-sdk/provider").LanguageModelV2;
5
6
  readonly "deepseek-v3-free": import("@ai-sdk/provider").LanguageModelV2;
6
7
  readonly "deepseek-r1-free": import("@ai-sdk/provider").LanguageModelV2;
@@ -18,12 +19,14 @@ declare const openrouterModels: {
18
19
  readonly "glm-4.5": import("@ai-sdk/provider").LanguageModelV2;
19
20
  readonly "gpt-5": import("@ai-sdk/provider").LanguageModelV2;
20
21
  readonly "gpt-5-mini": import("@ai-sdk/provider").LanguageModelV2;
22
+ readonly "gpt-oss-120b": import("@ai-sdk/provider").LanguageModelV2;
23
+ readonly "grok-code-fast-1": import("@ai-sdk/provider").LanguageModelV2;
21
24
  };
22
25
  type ModelName = `openrouter:${keyof typeof openrouterModels}`;
23
26
  export declare const openrouterModelNames: ModelName[];
24
27
  export declare const openrouterProvider: {
25
28
  openrouter: import("@ai-sdk/provider").ProviderV2 & {
26
- languageModel(modelId: "gpt-5" | "gpt-5-mini" | "gpt-4.1" | "deepseek-v3" | "deepseek-r1" | "deepseek-v3-free" | "deepseek-r1-free" | "gemini-flash25" | "gemini-pro25" | "sonnet4" | "opus4" | "opus-4.1" | "kimi-k2" | "kimi-k2-free" | "devstral-medium" | "qwen3-coder" | "qwen3-coder-free" | "glm-4.5"): import("@ai-sdk/provider").LanguageModelV2;
29
+ languageModel(modelId: "gpt-5" | "gpt-5-mini" | "gpt-4.1" | "deepseek-v3" | "deepseek-v3-1" | "deepseek-r1" | "deepseek-v3-free" | "deepseek-r1-free" | "gemini-flash25" | "gemini-pro25" | "sonnet4" | "opus4" | "opus-4.1" | "kimi-k2" | "kimi-k2-free" | "devstral-medium" | "qwen3-coder" | "qwen3-coder-free" | "glm-4.5" | "gpt-oss-120b" | "grok-code-fast-1"): import("@ai-sdk/provider").LanguageModelV2;
27
30
  textEmbeddingModel(modelId: string): import("@ai-sdk/provider").EmbeddingModelV2<string>;
28
31
  imageModel(modelId: string): import("@ai-sdk/provider").ImageModelV2;
29
32
  transcriptionModel(modelId: string): import("@ai-sdk/provider").TranscriptionModelV2;
@@ -13,6 +13,7 @@ const openRouterClient = createOpenAICompatible({
13
13
  });
14
14
  const openrouterModels = {
15
15
  "deepseek-v3": openRouterClient("deepseek/deepseek-chat-v3-0324"),
16
+ "deepseek-v3-1": openRouterClient("deepseek/deepseek-chat-v3.1"),
16
17
  "deepseek-r1": openRouterClient("deepseek/deepseek-r1-0528"),
17
18
  "deepseek-v3-free": openRouterClient("deepseek/deepseek-chat-v3-0324:free"),
18
19
  "deepseek-r1-free": openRouterClient("deepseek/deepseek-r1-0528:free"),
@@ -30,6 +31,8 @@ const openrouterModels = {
30
31
  "glm-4.5": openRouterClient("z-ai/glm-4.5"),
31
32
  "gpt-5": openRouterClient("openai/gpt-5"),
32
33
  "gpt-5-mini": openRouterClient("openai/gpt-5-mini"),
34
+ "gpt-oss-120b": openRouterClient("openai/gpt-oss-120b"),
35
+ "grok-code-fast-1": openRouterClient("x-ai/grok-code-fast-1"),
33
36
  };
34
37
  export const openrouterModelNames = objectKeys(openrouterModels).map((key) => `openrouter:${key}`);
35
38
  export const openrouterProvider = {
@@ -78,6 +81,19 @@ export const openrouterModelRegistry = {
78
81
  costPerOutputToken: 0, // Assuming free tier or unknown cost
79
82
  category: "balanced",
80
83
  },
84
+ "openrouter:deepseek-v3-1": {
85
+ id: "openrouter:deepseek-v3-1",
86
+ provider: "openrouter",
87
+ contextWindow: 163840,
88
+ maxOutputTokens: 8000,
89
+ defaultTemperature: 0.3,
90
+ promptFormat: "bracket",
91
+ supportsReasoning: true,
92
+ supportsToolCalling: true,
93
+ costPerInputToken: 0.0000002,
94
+ costPerOutputToken: 0.0000008,
95
+ category: "balanced",
96
+ },
81
97
  "openrouter:deepseek-r1-free": {
82
98
  id: "openrouter:deepseek-r1-free",
83
99
  provider: "openrouter",
@@ -252,8 +268,8 @@ export const openrouterModelRegistry = {
252
268
  provider: "openrouter",
253
269
  contextWindow: 400000,
254
270
  maxOutputTokens: 128000,
255
- defaultTemperature: 0.3,
256
- promptFormat: "markdown",
271
+ defaultTemperature: 1.0,
272
+ promptFormat: "xml",
257
273
  supportsReasoning: true,
258
274
  supportsToolCalling: true,
259
275
  costPerInputToken: 0.00000125,
@@ -265,12 +281,38 @@ export const openrouterModelRegistry = {
265
281
  provider: "openrouter",
266
282
  contextWindow: 200000,
267
283
  maxOutputTokens: 64000,
268
- defaultTemperature: 0.3,
269
- promptFormat: "markdown",
284
+ defaultTemperature: 1.0,
285
+ promptFormat: "xml",
270
286
  supportsReasoning: true,
271
287
  supportsToolCalling: true,
272
288
  costPerInputToken: 0.00000015,
273
289
  costPerOutputToken: 0.0000006,
274
290
  category: "balanced",
275
291
  },
292
+ "openrouter:grok-code-fast-1": {
293
+ id: "openrouter:grok-code-fast-1",
294
+ provider: "openrouter",
295
+ contextWindow: 256000,
296
+ maxOutputTokens: 10000,
297
+ defaultTemperature: 0.5,
298
+ promptFormat: "markdown",
299
+ supportsReasoning: true,
300
+ supportsToolCalling: true,
301
+ costPerInputToken: 0.0000002,
302
+ costPerOutputToken: 0.0000015,
303
+ category: "fast",
304
+ },
305
+ "openrouter:gpt-oss-120b": {
306
+ id: "openrouter:gpt-oss-120b",
307
+ provider: "openrouter",
308
+ contextWindow: 131072,
309
+ maxOutputTokens: 64000,
310
+ defaultTemperature: 1.0,
311
+ promptFormat: "xml",
312
+ supportsReasoning: true,
313
+ supportsToolCalling: true,
314
+ costPerInputToken: 0.00000007256312,
315
+ costPerOutputToken: 0.0000002903936,
316
+ category: "fast",
317
+ },
276
318
  };
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
  export declare const providers: readonly ["anthropic", "openai", "google", "deepseek", "openrouter", "xai"];
3
3
  export type ModelProvider = (typeof providers)[number];
4
- export declare const models: readonly ("anthropic:opus" | "anthropic:sonnet" | "anthropic:sonnet37" | "anthropic:sonnet37-token-efficient-tools" | "anthropic:sonnet37-128k" | "anthropic:sonnet35" | "anthropic:haiku" | "deepseek:deepseek-chat" | "deepseek:deepseek-reasoner" | "google:flash25lite" | "google:pro25" | "google:flash25" | "openai:o3" | "openai:gpt-4.1" | "openai:o4-mini" | "openai:codex-mini" | "openrouter:gpt-5" | "openrouter:gpt-5-mini" | "openrouter:gpt-4.1" | "openrouter:deepseek-v3" | "openrouter:deepseek-r1" | "openrouter:deepseek-v3-free" | "openrouter:deepseek-r1-free" | "openrouter:gemini-flash25" | "openrouter:gemini-pro25" | "openrouter:sonnet4" | "openrouter:opus4" | "openrouter:opus-4.1" | "openrouter:kimi-k2" | "openrouter:kimi-k2-free" | "openrouter:devstral-medium" | "openrouter:qwen3-coder" | "openrouter:qwen3-coder-free" | "openrouter:glm-4.5" | "xai:grok3" | "xai:grok3-mini")[];
4
+ export declare const models: readonly ("anthropic:opus" | "anthropic:sonnet" | "anthropic:sonnet37" | "anthropic:sonnet37-token-efficient-tools" | "anthropic:sonnet37-128k" | "anthropic:sonnet35" | "anthropic:haiku" | "deepseek:deepseek-chat" | "deepseek:deepseek-reasoner" | "google:flash25lite" | "google:pro25" | "google:flash25" | "openai:o3" | "openai:gpt-4.1" | "openai:o4-mini" | "openai:codex-mini" | "openrouter:gpt-5" | "openrouter:gpt-5-mini" | "openrouter:gpt-4.1" | "openrouter:deepseek-v3" | "openrouter:deepseek-v3-1" | "openrouter:deepseek-r1" | "openrouter:deepseek-v3-free" | "openrouter:deepseek-r1-free" | "openrouter:gemini-flash25" | "openrouter:gemini-pro25" | "openrouter:sonnet4" | "openrouter:opus4" | "openrouter:opus-4.1" | "openrouter:kimi-k2" | "openrouter:kimi-k2-free" | "openrouter:devstral-medium" | "openrouter:qwen3-coder" | "openrouter:qwen3-coder-free" | "openrouter:glm-4.5" | "openrouter:gpt-oss-120b" | "openrouter:grok-code-fast-1" | "xai:grok3" | "xai:grok3-mini")[];
5
5
  export type ModelName = (typeof models)[number] | (`xai:${string}` & {}) | (`openai:${string}` & {}) | (`anthropic:${string}` & {}) | (`google:${string}` & {}) | (`deepseek:${string}` & {}) | (`openrouter:${string}` & {});
6
6
  export declare function isSupportedModel(model: unknown): model is ModelName;
7
7
  export declare function languageModel(model: ModelName): import("@ai-sdk/provider").LanguageModelV2;
@@ -16,4 +16,5 @@ export declare class PromptManager {
16
16
  hasContext(): boolean;
17
17
  clearContext(): void;
18
18
  clearAll(): void;
19
+ getContextTokenCount(): number;
19
20
  }
@@ -68,4 +68,14 @@ export class PromptManager {
68
68
  this.clearContext();
69
69
  this.prompt = undefined;
70
70
  }
71
+ getContextTokenCount() {
72
+ let totalTokens = 0;
73
+ for (const item of this.context) {
74
+ if (typeof item === "string") {
75
+ totalTokens += this.tokenCounter.count(item);
76
+ }
77
+ // Skip ImagePart items as they don't contain countable text
78
+ }
79
+ return totalTokens;
80
+ }
71
81
  }
package/dist/prompts.js CHANGED
@@ -6,11 +6,13 @@ import { dedent } from "./dedent.js";
6
6
  import { AgentTool } from "./tools/agent.js";
7
7
  import { BashTool } from "./tools/bash.js";
8
8
  import { CodeInterpreterTool } from "./tools/code-interpreter.js";
9
+ import { DeleteFileTool } from "./tools/delete-file.js";
9
10
  import { DirectoryTreeTool } from "./tools/directory-tree.js";
10
11
  import { EditFileTool } from "./tools/edit-file.js";
11
12
  import { getCurrentBranch, inGitDirectory } from "./tools/git-utils.js";
12
13
  import { GrepTool } from "./tools/grep.js";
13
14
  import { ReadFileTool } from "./tools/read-file.js";
15
+ import { ReadMultipleFilesTool } from "./tools/read-multiple-files.js";
14
16
  import { SaveFileTool } from "./tools/save-file.js";
15
17
  import { ThinkTool } from "./tools/think.js";
16
18
  import { WebFetchTool } from "./tools/web-fetch.js";
@@ -65,17 +67,18 @@ function toolUsage() {
65
67
 
66
68
  ### Information Gathering
67
69
  - Use \`${DirectoryTreeTool.name}\` for project structure
68
- - Use \`${ReadFileTool.name}\` for file contents if filenames are provided in the prompt
70
+ - Use \`${ReadFileTool.name}\` or \`${ReadMultipleFilesTool.name}\` for file contents if filenames are provided in the prompt
69
71
  - Use \`${GrepTool.name}\` for code pattern searches
70
72
  - Use \`${WebFetchTool.name}\` for text-based URLs provided in the prompt
71
73
  - Use \`${WebSearchTool.name}\` for external research (e.g., libraries, errors)
72
- - Use \`${AgentTool.name}\` for iterative keyword/file searches
74
+ - Use \`${AgentTool.name}\` for iterative keyword/file searches. Use this if you need to explore the project fo find what you are looking for.
73
75
  - If file contents or URLs are provided in the prompt, use them directly without re-fetching
74
76
  - Always verify file contents before suggesting changes unless provided in the prompt
75
77
 
76
78
  ### Code Modification
77
- - Use \`${EditFileTool.name}\` for existing file edits (requires user approval)
78
- - Use \`${SaveFileTool.name}\` for new files only
79
+ - Use \`${EditFileTool.name}\` to edit existing files
80
+ - Use \`${SaveFileTool.name}\` to create new files only
81
+ - Use \`${DeleteFileTool.name}\` to delete files
79
82
 
80
83
  ### Planning & Complex Tasks
81
84
  - Use \`${ThinkTool.name}\` for structured reasoning on complex problems
@@ -85,8 +88,7 @@ function toolUsage() {
85
88
  - Execute bash commands within project directory only
86
89
  - Always specify absolute paths to avoid errors
87
90
  - You have access to the Github CLI
88
- - **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
89
- - **Interactive Commands:** Try to avoid shell commands that are likely to require user interaction (e.g. \`git rebase -i\`). Use non-interactive versions of commands (e.g. \`npm init -y\` instead of \`npm init\`) when available, and otherwise remind the user that interactive shell commands are not supported and may cause hangs until canceled by the user.
91
+ - Try to avoid shell commands that are likely to require user interaction (e.g. \`git rebase -i\`). Use non-interactive versions of commands (e.g. \`npm init -y\` instead of \`npm init\`) when available, and otherwise remind the user that interactive shell commands are not supported and may cause hangs until canceled by the user.
90
92
 
91
93
  ### Code Interpreter (\`${CodeInterpreterTool.name}\`)
92
94
  - Executes JavaScript code in a separate Node.js process using Node's Permission Model