@travisennis/acai 0.0.1 → 0.0.2

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 (323) 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.js +1 -1
  9. package/dist/models/openrouter-provider.d.ts +4 -1
  10. package/dist/models/openrouter-provider.js +46 -4
  11. package/dist/models/providers.d.ts +1 -1
  12. package/dist/prompts/manager.d.ts +1 -0
  13. package/dist/prompts/manager.js +10 -0
  14. package/dist/prompts.js +8 -6
  15. package/dist/repl.js +49 -26
  16. package/dist/terminal/formatting.d.ts +16 -5
  17. package/dist/terminal/formatting.js +40 -6
  18. package/dist/terminal/index.d.ts +1 -1
  19. package/dist/terminal/index.js +54 -14
  20. package/dist/terminal/markdown.js +0 -1
  21. package/dist/terminal/supports-color.d.ts +16 -0
  22. package/dist/terminal/supports-color.js +121 -0
  23. package/dist/terminal/supports-hyperlinks.d.ts +7 -0
  24. package/dist/terminal/supports-hyperlinks.js +98 -0
  25. package/dist/tools/bash.js +95 -117
  26. package/dist/tools/code-interpreter.js +11 -1
  27. package/dist/tools/command-validation.d.ts +7 -3
  28. package/dist/tools/command-validation.js +67 -23
  29. package/dist/tools/delete-file.d.ts +4 -1
  30. package/dist/tools/delete-file.js +47 -3
  31. package/dist/tools/git-utils.d.ts +6 -0
  32. package/dist/tools/git-utils.js +89 -12
  33. package/dist/tools/grep.d.ts +20 -0
  34. package/dist/tools/grep.js +128 -40
  35. package/dist/tools/index.d.ts +2 -18
  36. package/dist/tools/index.js +4 -18
  37. package/package.json +30 -20
  38. package/.acai/acai.json +0 -9
  39. package/.acai/prompts/add-openrouter-model.md +0 -13
  40. package/.acai/prompts/project-status.md +0 -4
  41. package/.acai/prompts/update-architecture-document.md +0 -9
  42. package/.acai/rules/learned-rules.md +0 -9
  43. package/.ai/docs/available-tools.txt +0 -3
  44. package/.ai/docs/cognitive_complexity_refactoring_progress.md +0 -65
  45. package/.ai/docs/deleted_tools.md +0 -168
  46. package/.ai/docs/deleted_tools_88ced9ef.md +0 -56
  47. package/.ai/docs/image-pasting.md +0 -46
  48. package/.ai/docs/initialize-app.md +0 -117
  49. package/.ai/docs/issue-4-plan.md +0 -44
  50. package/.ai/docs/marked-renderer-debug.md +0 -15
  51. package/.ai/docs/marked-renderer-refactor-plan.md +0 -64
  52. package/.ai/docs/memory-use-cases.md +0 -55
  53. package/.ai/docs/prompt-consistency.md +0 -31
  54. package/.ai/docs/refactoring-tools.md +0 -98
  55. package/.ai/docs/system-prompt-update.md +0 -174
  56. package/.ai/docs/system_prompt.txt +0 -210
  57. package/.ai/docs/tasks.md +0 -49
  58. package/.ai/plan.md +0 -131
  59. package/.ai/prompt.md +0 -1
  60. package/.ai/scripts/fetch_models.js +0 -27
  61. package/.ai/scripts/generateSystemPrompt.ts +0 -15
  62. package/.ai/scripts/list-tools.mjs +0 -4
  63. package/.ai/scripts/p5_geometric_shapes.js +0 -149
  64. package/.husky/commit-msg +0 -1
  65. package/.husky/pre-commit +0 -3
  66. package/.husky/pre-push +0 -1
  67. package/.ignore +0 -4
  68. package/AGENTS.md +0 -25
  69. package/ARCHITECTURE.md +0 -304
  70. package/TODO.md +0 -2
  71. package/biome.json +0 -61
  72. package/commitlint.config.js +0 -3
  73. package/dist/source/cli.d.ts +0 -19
  74. package/dist/source/cli.js +0 -116
  75. package/dist/source/commands/application-log-command.d.ts +0 -2
  76. package/dist/source/commands/application-log-command.js +0 -43
  77. package/dist/source/commands/clear-command.d.ts +0 -2
  78. package/dist/source/commands/clear-command.js +0 -12
  79. package/dist/source/commands/compact-command.d.ts +0 -2
  80. package/dist/source/commands/compact-command.js +0 -51
  81. package/dist/source/commands/copy-command.d.ts +0 -2
  82. package/dist/source/commands/copy-command.js +0 -51
  83. package/dist/source/commands/edit-command.d.ts +0 -2
  84. package/dist/source/commands/edit-command.js +0 -53
  85. package/dist/source/commands/edit-prompt-command.d.ts +0 -2
  86. package/dist/source/commands/edit-prompt-command.js +0 -25
  87. package/dist/source/commands/exit-command.d.ts +0 -2
  88. package/dist/source/commands/exit-command.js +0 -14
  89. package/dist/source/commands/files-command.d.ts +0 -2
  90. package/dist/source/commands/files-command.js +0 -63
  91. package/dist/source/commands/generate-rules-command.d.ts +0 -2
  92. package/dist/source/commands/generate-rules-command.js +0 -61
  93. package/dist/source/commands/help-command.d.ts +0 -2
  94. package/dist/source/commands/help-command.js +0 -19
  95. package/dist/source/commands/init-command.d.ts +0 -2
  96. package/dist/source/commands/init-command.js +0 -40
  97. package/dist/source/commands/last-log-command.d.ts +0 -2
  98. package/dist/source/commands/last-log-command.js +0 -76
  99. package/dist/source/commands/manager.d.ts +0 -22
  100. package/dist/source/commands/manager.js +0 -123
  101. package/dist/source/commands/model-command.d.ts +0 -2
  102. package/dist/source/commands/model-command.js +0 -84
  103. package/dist/source/commands/paste-command.d.ts +0 -2
  104. package/dist/source/commands/paste-command.js +0 -40
  105. package/dist/source/commands/prompt-command.d.ts +0 -2
  106. package/dist/source/commands/prompt-command.js +0 -111
  107. package/dist/source/commands/reset-command.d.ts +0 -2
  108. package/dist/source/commands/reset-command.js +0 -16
  109. package/dist/source/commands/rules-command.d.ts +0 -2
  110. package/dist/source/commands/rules-command.js +0 -68
  111. package/dist/source/commands/save-command.d.ts +0 -2
  112. package/dist/source/commands/save-command.js +0 -14
  113. package/dist/source/commands/types.d.ts +0 -26
  114. package/dist/source/commands/types.js +0 -1
  115. package/dist/source/commands/usage-command.d.ts +0 -2
  116. package/dist/source/commands/usage-command.js +0 -21
  117. package/dist/source/config.d.ts +0 -60
  118. package/dist/source/config.js +0 -193
  119. package/dist/source/conversation-analyzer.d.ts +0 -10
  120. package/dist/source/conversation-analyzer.js +0 -88
  121. package/dist/source/dedent.d.ts +0 -3
  122. package/dist/source/dedent.js +0 -38
  123. package/dist/source/formatting.d.ts +0 -17
  124. package/dist/source/formatting.js +0 -103
  125. package/dist/source/index.d.ts +0 -18
  126. package/dist/source/index.js +0 -213
  127. package/dist/source/logger.d.ts +0 -2
  128. package/dist/source/logger.js +0 -24
  129. package/dist/source/mentions.d.ts +0 -9
  130. package/dist/source/mentions.js +0 -182
  131. package/dist/source/messages.d.ts +0 -69
  132. package/dist/source/messages.js +0 -261
  133. package/dist/source/middleware/audit-message.d.ts +0 -5
  134. package/dist/source/middleware/audit-message.js +0 -95
  135. package/dist/source/middleware/index.d.ts +0 -2
  136. package/dist/source/middleware/index.js +0 -2
  137. package/dist/source/middleware/rate-limit.d.ts +0 -4
  138. package/dist/source/middleware/rate-limit.js +0 -17
  139. package/dist/source/models/ai-config.d.ts +0 -12
  140. package/dist/source/models/ai-config.js +0 -87
  141. package/dist/source/models/anthropic-provider.d.ts +0 -25
  142. package/dist/source/models/anthropic-provider.js +0 -184
  143. package/dist/source/models/deepseek-provider.d.ts +0 -20
  144. package/dist/source/models/deepseek-provider.js +0 -42
  145. package/dist/source/models/google-provider.d.ts +0 -19
  146. package/dist/source/models/google-provider.js +0 -56
  147. package/dist/source/models/manager.d.ts +0 -15
  148. package/dist/source/models/manager.js +0 -48
  149. package/dist/source/models/openai-provider.d.ts +0 -22
  150. package/dist/source/models/openai-provider.js +0 -70
  151. package/dist/source/models/openrouter-provider.d.ts +0 -36
  152. package/dist/source/models/openrouter-provider.js +0 -276
  153. package/dist/source/models/providers.d.ts +0 -33
  154. package/dist/source/models/providers.js +0 -116
  155. package/dist/source/models/xai-provider.d.ts +0 -20
  156. package/dist/source/models/xai-provider.js +0 -47
  157. package/dist/source/parsing.d.ts +0 -2
  158. package/dist/source/parsing.js +0 -18
  159. package/dist/source/prompts/manager.d.ts +0 -19
  160. package/dist/source/prompts/manager.js +0 -71
  161. package/dist/source/prompts.d.ts +0 -4
  162. package/dist/source/prompts.js +0 -158
  163. package/dist/source/repl-prompt.d.ts +0 -14
  164. package/dist/source/repl-prompt.js +0 -147
  165. package/dist/source/repl.d.ts +0 -27
  166. package/dist/source/repl.js +0 -431
  167. package/dist/source/terminal/formatting.d.ts +0 -37
  168. package/dist/source/terminal/formatting.js +0 -106
  169. package/dist/source/terminal/index.d.ts +0 -94
  170. package/dist/source/terminal/index.js +0 -420
  171. package/dist/source/terminal/markdown-utils.d.ts +0 -2
  172. package/dist/source/terminal/markdown-utils.js +0 -81
  173. package/dist/source/terminal/markdown.d.ts +0 -1
  174. package/dist/source/terminal/markdown.js +0 -111
  175. package/dist/source/terminal/types.d.ts +0 -71
  176. package/dist/source/terminal/types.js +0 -1
  177. package/dist/source/terminal-output.d.ts +0 -8
  178. package/dist/source/terminal-output.js +0 -213
  179. package/dist/source/terminal-output.test.d.ts +0 -8
  180. package/dist/source/terminal-output.test.js +0 -213
  181. package/dist/source/token-tracker.d.ts +0 -14
  182. package/dist/source/token-tracker.js +0 -53
  183. package/dist/source/token-utils.d.ts +0 -7
  184. package/dist/source/token-utils.js +0 -13
  185. package/dist/source/tools/agent.d.ts +0 -17
  186. package/dist/source/tools/agent.js +0 -87
  187. package/dist/source/tools/bash.d.ts +0 -19
  188. package/dist/source/tools/bash.js +0 -294
  189. package/dist/source/tools/code-interpreter.d.ts +0 -12
  190. package/dist/source/tools/code-interpreter.js +0 -131
  191. package/dist/source/tools/command-validation.d.ts +0 -8
  192. package/dist/source/tools/command-validation.js +0 -69
  193. package/dist/source/tools/delete-file.d.ts +0 -12
  194. package/dist/source/tools/delete-file.js +0 -56
  195. package/dist/source/tools/directory-tree.d.ts +0 -12
  196. package/dist/source/tools/directory-tree.js +0 -38
  197. package/dist/source/tools/edit-file.d.ts +0 -19
  198. package/dist/source/tools/edit-file.js +0 -107
  199. package/dist/source/tools/filesystem-utils.d.ts +0 -22
  200. package/dist/source/tools/filesystem-utils.js +0 -191
  201. package/dist/source/tools/git-utils.d.ts +0 -14
  202. package/dist/source/tools/git-utils.js +0 -64
  203. package/dist/source/tools/grep.d.ts +0 -17
  204. package/dist/source/tools/grep.js +0 -138
  205. package/dist/source/tools/index.d.ts +0 -161
  206. package/dist/source/tools/index.js +0 -209
  207. package/dist/source/tools/memory-read.d.ts +0 -13
  208. package/dist/source/tools/memory-read.js +0 -135
  209. package/dist/source/tools/memory-write.d.ts +0 -12
  210. package/dist/source/tools/memory-write.js +0 -83
  211. package/dist/source/tools/move-file.d.ts +0 -13
  212. package/dist/source/tools/move-file.js +0 -44
  213. package/dist/source/tools/read-file.d.ts +0 -17
  214. package/dist/source/tools/read-file.js +0 -86
  215. package/dist/source/tools/read-multiple-files.d.ts +0 -14
  216. package/dist/source/tools/read-multiple-files.js +0 -55
  217. package/dist/source/tools/save-file.d.ts +0 -17
  218. package/dist/source/tools/save-file.js +0 -98
  219. package/dist/source/tools/think.d.ts +0 -11
  220. package/dist/source/tools/think.js +0 -45
  221. package/dist/source/tools/types.d.ts +0 -29
  222. package/dist/source/tools/types.js +0 -14
  223. package/dist/source/tools/web-fetch.d.ts +0 -47
  224. package/dist/source/tools/web-fetch.js +0 -246
  225. package/dist/source/tools/web-search.d.ts +0 -13
  226. package/dist/source/tools/web-search.js +0 -80
  227. package/dist/source/utils/process.d.ts +0 -36
  228. package/dist/source/utils/process.js +0 -75
  229. package/dist/source/version.d.ts +0 -1
  230. package/dist/source/version.js +0 -21
  231. package/dist/terminal-output.d.ts +0 -8
  232. package/dist/terminal-output.js +0 -213
  233. package/dist/tools/memory-read.d.ts +0 -13
  234. package/dist/tools/memory-read.js +0 -135
  235. package/dist/tools/memory-write.d.ts +0 -12
  236. package/dist/tools/memory-write.js +0 -83
  237. package/knip.json +0 -5
  238. package/source/cli.ts +0 -172
  239. package/source/commands/application-log-command.ts +0 -53
  240. package/source/commands/clear-command.ts +0 -14
  241. package/source/commands/compact-command.ts +0 -64
  242. package/source/commands/copy-command.ts +0 -55
  243. package/source/commands/edit-command.ts +0 -63
  244. package/source/commands/edit-prompt-command.ts +0 -31
  245. package/source/commands/exit-command.ts +0 -18
  246. package/source/commands/files-command.ts +0 -85
  247. package/source/commands/generate-rules-command.ts +0 -82
  248. package/source/commands/help-command.ts +0 -27
  249. package/source/commands/init-command.ts +0 -48
  250. package/source/commands/last-log-command.ts +0 -88
  251. package/source/commands/manager.ts +0 -151
  252. package/source/commands/model-command.ts +0 -123
  253. package/source/commands/paste-command.ts +0 -62
  254. package/source/commands/prompt-command.ts +0 -150
  255. package/source/commands/reset-command.ts +0 -22
  256. package/source/commands/rules-command.ts +0 -76
  257. package/source/commands/save-command.ts +0 -20
  258. package/source/commands/types.ts +0 -28
  259. package/source/commands/usage-command.ts +0 -26
  260. package/source/config.ts +0 -223
  261. package/source/conversation-analyzer.ts +0 -115
  262. package/source/dedent.ts +0 -53
  263. package/source/formatting.ts +0 -132
  264. package/source/index.ts +0 -240
  265. package/source/logger.ts +0 -29
  266. package/source/mentions.ts +0 -227
  267. package/source/messages.ts +0 -360
  268. package/source/middleware/audit-message.ts +0 -133
  269. package/source/middleware/index.ts +0 -2
  270. package/source/middleware/rate-limit.ts +0 -24
  271. package/source/models/ai-config.ts +0 -109
  272. package/source/models/anthropic-provider.ts +0 -199
  273. package/source/models/deepseek-provider.ts +0 -53
  274. package/source/models/google-provider.ts +0 -68
  275. package/source/models/manager.ts +0 -84
  276. package/source/models/openai-provider.ts +0 -81
  277. package/source/models/openrouter-provider.ts +0 -288
  278. package/source/models/providers.ts +0 -197
  279. package/source/models/xai-provider.ts +0 -59
  280. package/source/parsing.ts +0 -20
  281. package/source/prompts/manager.ts +0 -90
  282. package/source/prompts.ts +0 -172
  283. package/source/repl-prompt.ts +0 -196
  284. package/source/repl.ts +0 -572
  285. package/source/terminal/formatting.ts +0 -121
  286. package/source/terminal/index.ts +0 -518
  287. package/source/terminal/markdown-utils.ts +0 -89
  288. package/source/terminal/markdown.ts +0 -155
  289. package/source/terminal/types.ts +0 -84
  290. package/source/terminal-output.test.ts +0 -266
  291. package/source/token-tracker.ts +0 -78
  292. package/source/token-utils.ts +0 -17
  293. package/source/tools/agent.ts +0 -107
  294. package/source/tools/bash.ts +0 -367
  295. package/source/tools/code-interpreter.ts +0 -172
  296. package/source/tools/command-validation.ts +0 -81
  297. package/source/tools/delete-file.ts +0 -71
  298. package/source/tools/directory-tree.ts +0 -54
  299. package/source/tools/edit-file.ts +0 -155
  300. package/source/tools/filesystem-utils.ts +0 -265
  301. package/source/tools/git-utils.ts +0 -70
  302. package/source/tools/grep.ts +0 -184
  303. package/source/tools/index.ts +0 -278
  304. package/source/tools/memory-read.ts +0 -174
  305. package/source/tools/memory-write.ts +0 -105
  306. package/source/tools/move-file.ts +0 -59
  307. package/source/tools/read-file.ts +0 -129
  308. package/source/tools/read-multiple-files.ts +0 -80
  309. package/source/tools/save-file.ts +0 -147
  310. package/source/tools/think.ts +0 -51
  311. package/source/tools/types.ts +0 -58
  312. package/source/tools/web-fetch.ts +0 -327
  313. package/source/tools/web-search.ts +0 -101
  314. package/source/utils/process.ts +0 -121
  315. package/source/version.ts +0 -21
  316. package/test/commands/copy-command.test.ts +0 -69
  317. package/test/config.test.ts +0 -200
  318. package/test/terminal/markdown-utils.test.ts +0 -124
  319. package/test/tools/bash-tool.test.ts +0 -58
  320. package/test/tools/code-interpreter.test.ts +0 -91
  321. package/test/tools/command-validation.test.ts +0 -48
  322. package/tsconfig.build.json +0 -9
  323. 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
- }