@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,200 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import fs from "node:fs/promises";
3
- import os from "node:os";
4
- import path from "node:path";
5
- import test from "node:test";
6
-
7
- import { ConfigManager, DirectoryProvider } from "../source/config.ts";
8
-
9
- // Helper to create and cleanup a temp directory
10
- async function withTempDir<T>(fn: (dir: string) => Promise<T>) {
11
- const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "acai-test-"));
12
- try {
13
- return await fn(tmp);
14
- } finally {
15
- // best-effort cleanup
16
- try {
17
- await fs.rm(tmp, { recursive: true, force: true });
18
- } catch {}
19
- }
20
- }
21
-
22
- test("DirectoryProvider.ensurePath async and sync create directories", async () => {
23
- await withTempDir(async (tmp) => {
24
- const base = path.join(tmp, "base");
25
- const dp = new DirectoryProvider(base);
26
-
27
- const asyncDir = await dp.ensurePath("async-sub");
28
- const stat = await fs.stat(asyncDir);
29
- assert(stat.isDirectory(), "async-created path should be a directory");
30
-
31
- const syncDir = dp.ensurePathSync("sync-sub");
32
- const stat2 = await fs.stat(syncDir);
33
- assert(stat2.isDirectory(), "sync-created path should be a directory");
34
- });
35
- });
36
-
37
- test("ConfigManager.ensureAppConfig creates default app config in HOME", async () => {
38
- await withTempDir(async (tmpHome) => {
39
- const oldHome = process.env.HOME;
40
- try {
41
- process.env.HOME = tmpHome;
42
-
43
- const mgr = new ConfigManager();
44
- const cfg = await mgr.ensureAppConfig("acai");
45
-
46
- // Defaults expected
47
- assert.equal((cfg as Record<string, unknown>).notify, true);
48
- assert.equal(
49
- ((cfg as Record<string, unknown>).tools as Record<string, unknown>)
50
- .maxTokens as number,
51
- 30000,
52
- );
53
-
54
- const configPath = path.join(tmpHome, ".acai", "acai.json");
55
- const data = JSON.parse(await fs.readFile(configPath, "utf8"));
56
- assert.equal(data.notify, true);
57
- assert.equal(data.tools.maxTokens, 30000);
58
- } finally {
59
- if (oldHome !== undefined) process.env.HOME = oldHome;
60
- }
61
- });
62
- });
63
-
64
- test("writeProjectLearnedRulesFile creates project rules file inside .acai", async () => {
65
- await withTempDir(async (tmpProject) => {
66
- const oldCwd = process.cwd();
67
- try {
68
- process.chdir(tmpProject);
69
- const mgr = new ConfigManager();
70
-
71
- await mgr.writeProjectLearnedRulesFile("# rules\nhello");
72
-
73
- const target = path.join(
74
- tmpProject,
75
- ".acai",
76
- "rules",
77
- "learned-rules.md",
78
- );
79
- const content = await fs.readFile(target, "utf8");
80
- assert(content.includes("hello"));
81
-
82
- // readProjectLearnedRulesFile should return the same content
83
- const read = await mgr.readProjectLearnedRulesFile();
84
- assert(read.includes("hello"));
85
- } finally {
86
- process.chdir(oldCwd);
87
- }
88
- });
89
- });
90
-
91
- test("writeCachedLearnedRulesFile and readCachedLearnedRulesFile in HOME", async () => {
92
- await withTempDir(async (tmpHome) => {
93
- const oldHome = process.env.HOME;
94
- try {
95
- process.env.HOME = tmpHome;
96
- const mgr = new ConfigManager();
97
-
98
- await mgr.writeCachedLearnedRulesFile("cached rules\nabc");
99
- const content = await mgr.readCachedLearnedRulesFile();
100
- assert(content.includes("abc"));
101
-
102
- // Removing file should cause read to return empty string
103
- const filePath = path.join(tmpHome, ".acai", "rules", "learned-rules.md");
104
- await fs.rm(filePath);
105
- const missing = await mgr.readCachedLearnedRulesFile();
106
- assert.equal(missing, "");
107
- } finally {
108
- if (oldHome !== undefined) process.env.HOME = oldHome;
109
- }
110
- });
111
- });
112
-
113
- test("readAppConfig returns {} for missing and throws for malformed", async () => {
114
- await withTempDir(async (tmpHome) => {
115
- const oldHome = process.env.HOME;
116
- try {
117
- process.env.HOME = tmpHome;
118
- const mgr = new ConfigManager();
119
-
120
- const missing = await mgr.readAppConfig("nonexistent");
121
- assert.deepEqual(missing, {});
122
-
123
- // Create malformed JSON
124
- const cfgDir = path.join(tmpHome, ".acai");
125
- await fs.mkdir(cfgDir, { recursive: true });
126
- const cfgPath = path.join(cfgDir, "bad.json");
127
- await fs.writeFile(cfgPath, "{ invalid json", "utf8");
128
-
129
- let threw = false;
130
- try {
131
- await mgr.readAppConfig("bad");
132
- } catch (_e) {
133
- threw = true;
134
- }
135
- assert.equal(threw, true, "readAppConfig should throw on malformed JSON");
136
- } finally {
137
- if (oldHome !== undefined) process.env.HOME = oldHome;
138
- }
139
- });
140
- });
141
-
142
- test("readProjectConfig merges app and project configs with project precedence", async () => {
143
- await withTempDir(async (tmpHome) => {
144
- const oldHome = process.env.HOME;
145
- const oldCwd = process.cwd();
146
- try {
147
- process.env.HOME = tmpHome;
148
- const projectDir = path.join(tmpHome, "proj");
149
- await fs.mkdir(projectDir, { recursive: true });
150
- process.chdir(projectDir);
151
-
152
- // write app config in HOME
153
- const appCfgDir = path.join(tmpHome, ".acai");
154
- await fs.mkdir(appCfgDir, { recursive: true });
155
- const appCfg = { tools: { maxTokens: 100 }, notify: true };
156
- await fs.writeFile(
157
- path.join(appCfgDir, "acai.json"),
158
- JSON.stringify(appCfg),
159
- "utf8",
160
- );
161
-
162
- // write project config overriding tools.maxTokens and notify
163
- const projCfgDir = path.join(projectDir, ".acai");
164
- await fs.mkdir(path.join(projCfgDir), { recursive: true });
165
- const projCfg = { tools: { maxTokens: 50 }, notify: false };
166
- await fs.writeFile(
167
- path.join(projCfgDir, "acai.json"),
168
- JSON.stringify(projCfg),
169
- "utf8",
170
- );
171
-
172
- const mgr = new ConfigManager();
173
- const merged = await mgr.readProjectConfig();
174
- assert.equal(merged.tools.maxTokens, 50);
175
- assert.equal(merged.notify, false);
176
- } finally {
177
- if (oldHome !== undefined) process.env.HOME = oldHome;
178
- process.chdir(oldCwd);
179
- }
180
- });
181
- });
182
-
183
- test("readAgentsFile and writeAgentsFile operate in CWD", async () => {
184
- await withTempDir(async (tmpCwd) => {
185
- const oldCwd = process.cwd();
186
- try {
187
- process.chdir(tmpCwd);
188
- const mgr = new ConfigManager();
189
-
190
- const initial = await mgr.readAgentsFile();
191
- assert.equal(initial, "");
192
-
193
- await mgr.writeAgentsFile("# Agents\nagent1");
194
- const content = await mgr.readAgentsFile();
195
- assert(content.includes("agent1"));
196
- } finally {
197
- process.chdir(oldCwd);
198
- }
199
- });
200
- });
@@ -1,124 +0,0 @@
1
- import { strict as assert } from "node:assert/strict";
2
- import { describe, it } from "node:test";
3
- import {
4
- getListNumber,
5
- isMarkdown,
6
- } from "../../source/terminal/markdown-utils.ts";
7
-
8
- describe("isMarkdown", () => {
9
- it("should return true for markdown headings", () => {
10
- assert.strictEqual(isMarkdown("# Heading 1"), true);
11
- assert.strictEqual(isMarkdown("## Heading 2"), true);
12
- assert.strictEqual(isMarkdown("### Heading 3"), true);
13
- assert.strictEqual(isMarkdown("#### Heading 4"), true);
14
- assert.strictEqual(isMarkdown("##### Heading 5"), true);
15
- assert.strictEqual(isMarkdown("###### Heading 6"), true);
16
- });
17
-
18
- it("should return true for markdown bold text", () => {
19
- assert.strictEqual(isMarkdown("**bold text**"), true);
20
- assert.strictEqual(isMarkdown("__bold text__"), true);
21
- });
22
-
23
- it("should return true for markdown italic text", () => {
24
- assert.strictEqual(isMarkdown("*italic text*"), true);
25
- assert.strictEqual(isMarkdown("_italic text_"), true);
26
- });
27
-
28
- it("should return true for markdown code blocks", () => {
29
- assert.strictEqual(isMarkdown("`code`"), true);
30
- assert.strictEqual(isMarkdown("```code block```"), true);
31
- });
32
-
33
- it("should return true for markdown links", () => {
34
- assert.strictEqual(isMarkdown("(alt text](url)"), true);
35
- });
36
-
37
- it("should return true for markdown blockquotes", () => {
38
- assert.strictEqual(isMarkdown("> blockquote"), true);
39
- });
40
-
41
- it("should return true for markdown unordered lists", () => {
42
- assert.strictEqual(isMarkdown("- list item"), true);
43
- assert.strictEqual(isMarkdown("* list item"), true);
44
- assert.strictEqual(isMarkdown("+ list item"), true);
45
- });
46
-
47
- it("should return true for markdown ordered lists", () => {
48
- assert.strictEqual(isMarkdown("1. list item"), true);
49
- });
50
-
51
- it("should return true for markdown horizontal rules", () => {
52
- assert.strictEqual(isMarkdown("---"), true);
53
- });
54
-
55
- it("should return true for markdown images", () => {
56
- assert.strictEqual(isMarkdown("![alt text](url)"), true);
57
- });
58
-
59
- it("should return false for plain text", () => {
60
- assert.strictEqual(isMarkdown("This is plain text."), false);
61
- });
62
-
63
- it("should return false for an empty string", () => {
64
- assert.strictEqual(isMarkdown(""), false);
65
- });
66
-
67
- it("should return true for mixed markdown content", () => {
68
- assert.strictEqual(
69
- isMarkdown("# Heading\nSome *italic* and **bold** text."),
70
- true,
71
- );
72
- });
73
- });
74
-
75
- describe("getListNumber", () => {
76
- it("should return arabic numerals for depth 0", () => {
77
- assert.strictEqual(getListNumber(0, 1), "1");
78
- assert.strictEqual(getListNumber(0, 10), "10");
79
- assert.strictEqual(getListNumber(0, 0), "0"); // Though practically, list numbers start from 1
80
- });
81
-
82
- it("should return arabic numerals for depth 1", () => {
83
- assert.strictEqual(getListNumber(1, 1), "1");
84
- assert.strictEqual(getListNumber(1, 5), "5");
85
- });
86
-
87
- it("should return lowercase letters for depth 2", () => {
88
- assert.strictEqual(getListNumber(2, 1), "a");
89
- assert.strictEqual(getListNumber(2, 26), "z");
90
- assert.strictEqual(getListNumber(2, 27), "aa");
91
- assert.strictEqual(getListNumber(2, 0), "");
92
- });
93
-
94
- it("should return lowercase Roman numerals for depth 3", () => {
95
- assert.strictEqual(getListNumber(3, 1), "i");
96
- assert.strictEqual(getListNumber(3, 4), "iv");
97
- assert.strictEqual(getListNumber(3, 9), "ix");
98
- assert.strictEqual(getListNumber(3, 10), "x");
99
- assert.strictEqual(getListNumber(3, 40), "xl");
100
- assert.strictEqual(getListNumber(3, 0), "");
101
- });
102
-
103
- it("should return arabic numerals for depth greater than 3 (default case)", () => {
104
- assert.strictEqual(getListNumber(4, 1), "1");
105
- assert.strictEqual(getListNumber(10, 5), "5");
106
- });
107
-
108
- it("should handle various numbers for depth 1 list (arabic)", () => {
109
- assert.strictEqual(getListNumber(1, 123), "123");
110
- });
111
-
112
- it("should handle various numbers for depth 2 list (letters)", () => {
113
- assert.strictEqual(getListNumber(2, 52), "az");
114
- assert.strictEqual(getListNumber(2, 702), "zz");
115
- assert.strictEqual(getListNumber(2, 703), "aaa");
116
- });
117
-
118
- it("should handle various numbers for depth 3 list (roman)", () => {
119
- assert.strictEqual(getListNumber(3, 49), "xlix");
120
- assert.strictEqual(getListNumber(3, 99), "xcix");
121
- assert.strictEqual(getListNumber(3, 499), "cdxcix");
122
- assert.strictEqual(getListNumber(3, 1994), "mcmxciv");
123
- });
124
- });
@@ -1,58 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { describe, it } from "node:test";
3
- import { config } from "../../source/config.ts";
4
- import { createBashTool } from "../../source/tools/bash.ts";
5
-
6
- // Minimal token counter mock
7
- const tokenCounter = { count: (s: string) => s.length } as const;
8
-
9
- await config.readProjectConfig();
10
-
11
- const baseDir = process.cwd();
12
-
13
- describe("bash tool path validation for git message flags", () => {
14
- const { bash } = createBashTool({
15
- baseDir,
16
- tokenCounter,
17
- autoAcceptAll: true,
18
- });
19
-
20
- async function run(command: string) {
21
- const toolImpl = bash as unknown as {
22
- execute: (
23
- args: { command: string; cwd: string; timeout: number },
24
- meta: { toolCallId: string },
25
- ) => Promise<string>;
26
- };
27
- const result = await toolImpl.execute(
28
- { command, cwd: baseDir, timeout: 1000 },
29
- { toolCallId: "t1" },
30
- );
31
- return String(result);
32
- }
33
-
34
- it("allows commit messages with /copy", async () => {
35
- const res = await run('echo ok && git commit -m "docs: mention /copy"');
36
- assert.ok(!res.includes("references path outside"));
37
- });
38
-
39
- it("allows URLs in messages", async () => {
40
- const res = await run('git commit -m "URL https://example.com/p/a/t/h"');
41
- assert.ok(!res.includes("references path outside"));
42
- });
43
-
44
- it("rejects absolute path in git add", async () => {
45
- const res = await run("git add /etc/hosts");
46
- assert.ok(res.includes("references path outside"));
47
- });
48
-
49
- it("rejects commit -F with file outside", async () => {
50
- const res = await run("git commit -F /tmp/message.txt");
51
- assert.ok(res.includes("references path outside"));
52
- });
53
-
54
- it("handles multiple -m flags", async () => {
55
- const res = await run('git commit -m "first /copy" -m "second /path"');
56
- assert.ok(!res.includes("references path outside"));
57
- });
58
- });
@@ -1,91 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { describe, it } from "node:test";
3
- import {
4
- CodeInterpreterTool,
5
- createCodeInterpreterTool,
6
- } from "../../source/tools/code-interpreter.ts";
7
-
8
- // Helper to run the tool easily
9
- async function runTool(input: {
10
- code: string;
11
- timeoutSeconds?: number;
12
- }): Promise<{ ok: boolean; value: unknown }> {
13
- const events: Array<{ event: string; data: unknown }> = [];
14
- const { [CodeInterpreterTool.name]: tool } = createCodeInterpreterTool({
15
- sendData: async (msg) => {
16
- events.push({ event: msg.event, data: msg.data });
17
- },
18
- });
19
-
20
- const output = await tool.execute(
21
- input as never,
22
- { toolCallId: "t1" } as never,
23
- );
24
- if (typeof output === "string" && output.startsWith("{")) {
25
- return { ok: true, value: JSON.parse(output) };
26
- }
27
- return { ok: false, value: output };
28
- }
29
-
30
- describe("code-interpreter tool", () => {
31
- it("executes simple console.log", async () => {
32
- const res = await runTool({ code: "console.log('ok');" });
33
- assert.equal(res.ok, true);
34
- const v = res.value as { stdout: string; stderr: string; exitCode: number };
35
- assert.equal(v.exitCode, 0);
36
- assert.equal(v.stdout.trim(), "ok");
37
- // Ignore stderr in this test due to environment-specific Node warnings.
38
- assert.equal(typeof v.stderr, "string");
39
- });
40
-
41
- it("enforces timeout", async () => {
42
- const res = await runTool({ code: "for(;;){}", timeoutSeconds: 1 });
43
- assert.equal(res.ok, false);
44
- assert.equal(res.value, "Script timed out");
45
- });
46
-
47
- it("allows fs within cwd", async () => {
48
- const code = `
49
- import { writeFileSync, readFileSync, rmSync } from 'node:fs';
50
- writeFileSync('tmp_test_file.txt', 'hello', { encoding: 'utf8' });
51
- const s = readFileSync('tmp_test_file.txt', { encoding: 'utf8' });
52
- console.log(s);
53
- rmSync('tmp_test_file.txt', { force: true });
54
- `;
55
- const res = await runTool({ code });
56
- assert.equal(res.ok, true);
57
- const v = res.value as { stdout: string };
58
- assert.equal(v.stdout.trim(), "hello");
59
- });
60
-
61
- it("denies fs outside cwd", async () => {
62
- const code = `
63
- import { writeFileSync } from 'node:fs';
64
- import { resolve } from 'node:path';
65
- writeFileSync(resolve('..', 'should_not_write.txt'), 'x', { encoding: 'utf8' });
66
- console.log('done');
67
- `;
68
- const res = await runTool({ code });
69
- assert.equal(res.ok, false);
70
- assert.match(String(res.value), /Process exited with code|permission/i);
71
- });
72
-
73
- it("denies child_process", async () => {
74
- const code = `
75
- import { spawnSync } from 'node:child_process';
76
- const r = spawnSync('node', ['-v']);
77
- console.log(String(r.stdout || ''));
78
- `;
79
- const res = await runTool({ code });
80
- assert.equal(res.ok, false);
81
- });
82
-
83
- it("denies network", async () => {
84
- const code = `
85
- import https from 'node:https';
86
- https.get('https://example.com', (res) => { console.log('status', res.statusCode); }).on('error', (e) => { console.error(String(e)); });
87
- `;
88
- const res = await runTool({ code });
89
- assert.equal(res.ok, false);
90
- });
91
- });
@@ -1,48 +0,0 @@
1
- import assert from "node:assert";
2
- import { describe, it } from "node:test";
3
- import { CommandValidation } from "../../source/tools/command-validation.ts";
4
-
5
- describe("CommandValidation", () => {
6
- const allowedCommands = ["ls", "pwd", "echo", "grep", "sleep"];
7
- const validator = new CommandValidation(allowedCommands);
8
-
9
- describe("Valid Commands", () => {
10
- it("allows ls && pwd", () => {
11
- assert.strictEqual(validator.isValid("ls && pwd"), true);
12
- });
13
-
14
- it("allows echo 'hi' || ls", () => {
15
- assert.strictEqual(validator.isValid("echo 'hi' || ls"), true);
16
- });
17
-
18
- it("allows ls; pwd", () => {
19
- assert.strictEqual(validator.isValid("ls; pwd"), true);
20
- });
21
-
22
- it("allows ls | grep .ts", () => {
23
- assert.strictEqual(validator.isValid("ls | grep .ts"), true);
24
- });
25
-
26
- it("allows sleep 1 &", () => {
27
- assert.strictEqual(validator.isValid("sleep 1 &"), true);
28
- });
29
- });
30
-
31
- describe("Invalid Commands", () => {
32
- it("blocks ls > file (unsafe operator)", () => {
33
- assert.strictEqual(validator.isValid("ls > file"), false);
34
- });
35
-
36
- it("blocks echo $(date) (unsafe operator)", () => {
37
- assert.strictEqual(validator.isValid("echo $(date)"), false);
38
- });
39
-
40
- it("blocks rm -rf / (disallowed command)", () => {
41
- assert.strictEqual(validator.isValid("rm -rf /"), false);
42
- });
43
-
44
- it("blocks empty command", () => {
45
- assert.strictEqual(validator.isValid(""), false);
46
- });
47
- });
48
- });
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "exclude": ["test", "**/*.test.ts"],
4
- "compilerOptions": {
5
- "rootDir": "source",
6
- "outDir": "dist"
7
- }
8
- }
9
-
package/tsconfig.json DELETED
@@ -1,30 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "outDir": "./dist",
4
- "target": "ESNext",
5
- "module": "ESNext",
6
- "declaration": true,
7
- "composite": true,
8
- "moduleResolution": "Bundler",
9
- "strict": true,
10
- "allowUnusedLabels": false,
11
- "allowUnreachableCode": false,
12
- "exactOptionalPropertyTypes": false,
13
- "noFallthroughCasesInSwitch": true,
14
- "noImplicitOverride": true,
15
- "noImplicitReturns": true,
16
- "noPropertyAccessFromIndexSignature": true,
17
- "noUncheckedIndexedAccess": true,
18
- "noUnusedLocals": true,
19
- "noUnusedParameters": true,
20
- "isolatedModules": true,
21
- "checkJs": true,
22
- "skipLibCheck": true,
23
- "rewriteRelativeImportExtensions": true,
24
- "types": ["node"],
25
- "lib": ["ESNext"]
26
- },
27
- "include": ["source/**/*.ts"],
28
- "$schema": "https://json.schemastore.org/tsconfig",
29
- "_version": "2.0.0"
30
- }