@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
package/source/repl.ts DELETED
@@ -1,572 +0,0 @@
1
- import { isNumber, isRecord } from "@travisennis/stdlib/typeguards";
2
- import type { AsyncReturnType } from "@travisennis/stdlib/types";
3
- import {
4
- generateObject,
5
- NoSuchToolError,
6
- type StepResult,
7
- stepCountIs,
8
- streamText,
9
- type ToolCallRepairFunction,
10
- type ToolSet,
11
- } from "ai";
12
- import chalk, { type ChalkInstance } from "chalk";
13
- import type z from "zod";
14
- import type { CommandManager } from "./commands/manager.ts";
15
- import { config as configManager } from "./config.ts";
16
- import { logger } from "./logger.ts";
17
- import { processPrompt } from "./mentions.ts";
18
- import type { MessageHistory } from "./messages.ts";
19
- import { AiConfig } from "./models/ai-config.ts";
20
- import type { ModelManager } from "./models/manager.js";
21
- import type { PromptManager } from "./prompts/manager.ts";
22
- import { systemPrompt } from "./prompts.ts";
23
- import { ReplPrompt } from "./repl-prompt.ts";
24
- import type { Terminal } from "./terminal/index.ts";
25
- import { isMarkdown } from "./terminal/markdown-utils.ts";
26
- import type { TokenTracker } from "./token-tracker.ts";
27
- import type { TokenCounter } from "./token-utils.ts";
28
- import {
29
- getCurrentBranch,
30
- getDiffStat,
31
- hasUncommittedChanges,
32
- inGitDirectory,
33
- } from "./tools/git-utils.ts"; // Modified import
34
- import { initAgents, initTools } from "./tools/index.ts";
35
- import type { Message } from "./tools/types.ts";
36
-
37
- interface ReplOptions {
38
- messageHistory: MessageHistory;
39
- promptManager: PromptManager;
40
- modelManager: ModelManager;
41
- tokenTracker: TokenTracker;
42
- terminal: Terminal;
43
- commands: CommandManager;
44
- config: Record<PropertyKey, unknown>;
45
- tokenCounter: TokenCounter;
46
- toolEvents: Map<string, Message[]>;
47
- autoAcceptAll: boolean;
48
- }
49
-
50
- type CompleteToolSet = AsyncReturnType<typeof initTools> &
51
- AsyncReturnType<typeof initAgents>;
52
-
53
- type OnFinishResult<Tools extends ToolSet = CompleteToolSet> = Omit<
54
- StepResult<Tools>,
55
- "stepType" | "isContinued"
56
- > & {
57
- /**
58
- Details for all steps.
59
- */
60
- readonly steps: StepResult<Tools>[];
61
- };
62
-
63
- export class Repl {
64
- private options: ReplOptions;
65
- constructor(options: ReplOptions) {
66
- this.options = options;
67
- }
68
-
69
- async run() {
70
- const {
71
- config,
72
- promptManager,
73
- terminal,
74
- modelManager,
75
- tokenTracker,
76
- messageHistory,
77
- commands,
78
- tokenCounter,
79
- toolEvents,
80
- autoAcceptAll,
81
- } = this.options;
82
-
83
- logger.info(config, "Config:");
84
-
85
- terminal.displayWelcome();
86
-
87
- const promptHistory: string[] = [];
88
-
89
- let currentContextWindow = 0;
90
- messageHistory.on("clear-history", () => {
91
- currentContextWindow = 0;
92
- });
93
-
94
- let prevCb: (() => void) | null = null;
95
-
96
- while (true) {
97
- const abortController = new AbortController();
98
- const { signal } = abortController;
99
-
100
- const cb = () => {
101
- abortController.abort();
102
- };
103
-
104
- if (prevCb) {
105
- process.removeListener("SIGINT", prevCb);
106
- }
107
-
108
- // Handle Ctrl+C (SIGINT)
109
- process.on("SIGINT", cb);
110
- prevCb = cb;
111
-
112
- const langModel = modelManager.getModel("repl");
113
- const modelConfig = modelManager.getModelMetadata("repl");
114
-
115
- const currentDir = process.cwd().split("/").pop() || process.cwd();
116
- const branch = await getCurrentBranch();
117
-
118
- let branchDisplay = "";
119
- if (branch) {
120
- const hasChanges = await hasUncommittedChanges();
121
- const asterisk = hasChanges ? "*" : "";
122
- branchDisplay = ` ${chalk.gray(branch + asterisk)}`;
123
- }
124
-
125
- terminal.hr();
126
- terminal.writeln(`${chalk.blue(currentDir)}${branchDisplay}`);
127
- terminal.writeln(chalk.dim(langModel.modelId));
128
- terminal.displayProgressBar(
129
- currentContextWindow,
130
- modelConfig.contextWindow,
131
- );
132
-
133
- if (!promptManager.isPending()) {
134
- // For interactive input
135
- const prompt = new ReplPrompt({ commands, history: promptHistory });
136
- const userInput = await prompt.input();
137
- prompt.close();
138
-
139
- // see if the userInput contains a command
140
- const commandResult = await commands.handle({ userInput });
141
- if (commandResult.break) {
142
- break;
143
- }
144
- if (commandResult.continue) {
145
- terminal.lineBreak();
146
- continue;
147
- }
148
-
149
- if (!userInput.trim()) {
150
- continue;
151
- }
152
-
153
- // if there is no pending prompt then use the user's input. otherwise, the prompt was loaded from a command
154
- if (!promptManager.isPending()) {
155
- const processedPrompt = await processPrompt(userInput, {
156
- baseDir: process.cwd(),
157
- model: modelConfig,
158
- });
159
- for (const context of processedPrompt.context) {
160
- promptManager.addContext(context);
161
- }
162
- promptManager.set(processedPrompt.message);
163
- }
164
-
165
- terminal.lineBreak();
166
- }
167
-
168
- // flag to see if the user prompt has added context
169
- const hasAddedContext = promptManager.hasContext();
170
-
171
- if (hasAddedContext) {
172
- terminal.info("Context will be added to prompt.");
173
- terminal.lineBreak();
174
- }
175
-
176
- const userPrompt = promptManager.get();
177
-
178
- const userMsg = promptManager.getUserMessage();
179
-
180
- messageHistory.appendUserMessage(userMsg);
181
-
182
- const finalSystemPrompt = await systemPrompt({
183
- supportsToolCalling: modelConfig.supportsToolCalling,
184
- });
185
-
186
- const aiConfig = new AiConfig({
187
- modelMetadata: modelConfig,
188
- prompt: userPrompt,
189
- });
190
-
191
- const maxTokens = aiConfig.getMaxTokens();
192
-
193
- const tools = modelConfig.supportsToolCalling
194
- ? {
195
- ...(await initTools({
196
- terminal,
197
- tokenCounter,
198
- autoAcceptAll,
199
- events: toolEvents,
200
- })),
201
- ...(await initAgents({
202
- terminal,
203
- modelManager,
204
- tokenTracker,
205
- tokenCounter,
206
- events: toolEvents,
207
- })),
208
- }
209
- : undefined;
210
-
211
- try {
212
- const result = streamText({
213
- model: langModel,
214
- maxOutputTokens: maxTokens,
215
- messages: [
216
- {
217
- role: "system",
218
- content: finalSystemPrompt,
219
- providerOptions: {
220
- anthropic: { cacheControl: { type: "ephemeral" } },
221
- },
222
- },
223
- ...messageHistory.get(),
224
- ],
225
- temperature: modelConfig.defaultTemperature,
226
- stopWhen: stepCountIs(60),
227
- maxRetries: 2,
228
- providerOptions: aiConfig.getProviderOptions(),
229
- tools,
230
- // biome-ignore lint/style/useNamingConvention: third-party controlled
231
- experimental_repairToolCall: modelConfig.supportsToolCalling
232
- ? toolCallRepair(modelManager, terminal)
233
- : undefined,
234
- abortSignal: signal,
235
- onFinish: async (result) => {
236
- logger.debug("onFinish called");
237
- if (result.response.messages.length > 0) {
238
- messageHistory.appendResponseMessages(result.response.messages);
239
- }
240
-
241
- terminal.hr();
242
-
243
- // Notify if configured in project config (acai.json)
244
- const projectConfig = await configManager.readProjectConfig();
245
- if (projectConfig.notify) {
246
- terminal.alert();
247
- }
248
-
249
- // Create a more visual representation of steps/tool usage
250
- this.displayToolUse(result, terminal);
251
-
252
- if (await inGitDirectory()) {
253
- // Added check
254
- const stats = await getDiffStat();
255
- terminal.writeln(
256
- `${chalk.dim("Files changed:")} ${chalk.yellow(stats.filesChanged)} ` +
257
- `${chalk.green(`+${stats.insertions}`)} ` + // Insertions first (green)
258
- `${chalk.red(`-${stats.deletions}`)}`, // Deletions last (red)
259
- );
260
- }
261
-
262
- const total =
263
- (result as { totalUsage?: typeof result.usage }).totalUsage ??
264
- result.usage;
265
- const outgoingTokens = isNumber(total.inputTokens)
266
- ? total.inputTokens
267
- : 0;
268
- const incomingTokens = isNumber(total.outputTokens)
269
- ? total.outputTokens
270
- : 0;
271
- const tokenSummary = `Tokens: ↑ ${outgoingTokens} ↓ ${incomingTokens}`;
272
- terminal.writeln(chalk.dim(tokenSummary));
273
-
274
- // Track aggregate usage across all steps when available
275
- tokenTracker.trackUsage("repl", total);
276
-
277
- // Derive current context window from final step usage
278
- const finalTotalTokens = result.usage.totalTokens;
279
- if (isNumber(finalTotalTokens)) {
280
- currentContextWindow = finalTotalTokens ?? 0;
281
- } else {
282
- // Fallback: find the stopped step
283
- for (const step of result.steps) {
284
- if (step.finishReason === "stop") {
285
- const usage = step.usage;
286
- currentContextWindow = Number.isNaN(usage.totalTokens)
287
- ? 0
288
- : (usage.totalTokens ?? 0);
289
- }
290
- }
291
- }
292
-
293
- // comment out auto-summarization for now. it's been causing issues.
294
- // if (currentContextWindow > 70000) {
295
- // logger.info(
296
- // `Condensing history from ${currentContextWindow} to 0`,
297
- // );
298
- // await messageHistory.summarizeAndReset();
299
- // }
300
-
301
- terminal.hr();
302
- },
303
- onError: ({ error }) => {
304
- logger.error(
305
- error, // Log the full error object
306
- "Error on REPL streamText",
307
- );
308
- terminal.error(
309
- (error as Error).message.length > 100
310
- ? `${(error as Error).message.slice(0, 100)}...`
311
- : (error as Error).message,
312
- );
313
- },
314
- });
315
-
316
- let accumulatedText = "";
317
- let lastType: "reasoning" | "text" | null = null;
318
-
319
- for await (const chunk of result.fullStream) {
320
- // Handle text-related chunks (reasoning or text-delta)
321
- if (chunk.type === "reasoning-delta" || chunk.type === "text-delta") {
322
- if (chunk.type === "reasoning-delta") {
323
- if (lastType !== "reasoning") {
324
- terminal.writeln(chalk.dim("<think>"));
325
- }
326
- terminal.write(chalk.dim(chunk.text)); // Stream reasoning directly
327
- lastType = "reasoning";
328
- } else if (chunk.type === "text-delta") {
329
- if (lastType === "reasoning") {
330
- // Finishing reasoning: Print </think>
331
- terminal.writeln(chalk.dim("\n</think>\n"));
332
- }
333
- accumulatedText += chunk.text;
334
- lastType = "text";
335
- }
336
- } else if (chunk.type === "tool-result") {
337
- const messages = toolEvents.get(chunk.toolCallId);
338
- if (messages) {
339
- displayToolMessages(messages, terminal);
340
- toolEvents.delete(chunk.toolCallId);
341
- } else {
342
- logger.warn(`No tool events found for ${chunk.toolCallId}`);
343
- }
344
- } else {
345
- // Close thinking tags when moving from reasoning to any other chunk type
346
- if (lastType === "reasoning") {
347
- terminal.write(chalk.dim("\n</think>\n\n"));
348
- }
349
- // if there is accumulatedText, display it
350
- if (accumulatedText) {
351
- terminal.writeln(`${chalk.blue.bold("●")} Response:`);
352
- terminal.display(accumulatedText, true);
353
- terminal.lineBreak();
354
- }
355
- accumulatedText = "";
356
- lastType = null;
357
- }
358
- }
359
-
360
- // Ensure the final closing tag for reasoning is written if it was the last type
361
- if (lastType === "reasoning") {
362
- terminal.write(chalk.gray("\n</think>\n\n"));
363
- }
364
-
365
- // if there is accumulatedText, display it
366
- if (accumulatedText) {
367
- terminal.writeln(`${chalk.green.bold("●")} Response:`);
368
- terminal.display(accumulatedText, true);
369
- terminal.lineBreak();
370
- }
371
-
372
- terminal.lineBreak(); // Add a final newline for clarity
373
-
374
- await result.consumeStream();
375
- } catch (e) {
376
- if (isRecord(e) && isRecord(e["data"]) && "error" in e["data"]) {
377
- terminal.error(
378
- (e["data"]["error"] as Record<"message", string>).message,
379
- );
380
- } else {
381
- terminal.error(
382
- (e as Error).message.length > 100
383
- ? `${(e as Error).message.slice(0, 100)}...`
384
- : (e as Error).message,
385
- );
386
- }
387
- terminal.lineBreak();
388
- if (e instanceof Error) {
389
- logger.error(e);
390
- } else {
391
- logger.error(JSON.stringify(e, null, 2));
392
- }
393
- }
394
- }
395
- }
396
-
397
- private displayToolUse(result: OnFinishResult, terminal: Terminal) {
398
- const toolsCalled: string[] = [];
399
- const toolColors = new Map<string, ChalkInstance>();
400
-
401
- const chalkColors = [
402
- "red",
403
- "green",
404
- "yellow",
405
- "blue",
406
- "magenta",
407
- "cyan",
408
- "white",
409
- "gray",
410
- "redBright",
411
- "greenBright",
412
- "yellowBright",
413
- "blueBright",
414
- "magentaBright",
415
- "cyanBright",
416
- "whiteBright",
417
- "blackBright",
418
- ] as const;
419
-
420
- terminal.writeln(chalk.dim(`Steps: ${result.steps.length}`));
421
-
422
- for (const step of result.steps) {
423
- let currentToolCalls: Array<{ toolName: string }> = [];
424
-
425
- if (step.toolResults.length > 0) {
426
- currentToolCalls = step.toolResults;
427
- } else if (step.toolCalls.length > 0) {
428
- currentToolCalls = step.toolCalls;
429
- }
430
-
431
- for (const toolCallOrResult of currentToolCalls) {
432
- const toolName = toolCallOrResult.toolName;
433
- if (!toolColors.has(toolName)) {
434
- const availableColors = chalkColors.filter(
435
- (color) =>
436
- !Array.from(toolColors.values()).some((c) => c === chalk[color]),
437
- );
438
- const color =
439
- availableColors.length > 0
440
- ? (availableColors[
441
- Math.floor(Math.random() * availableColors.length)
442
- ] ?? "white")
443
- : "white";
444
- toolColors.set(toolName, chalk[color]);
445
- }
446
- toolsCalled.push(toolName);
447
- }
448
- }
449
-
450
- if (toolsCalled.length > 0) {
451
- terminal.writeln(chalk.dim("Tools:"));
452
- for (const toolCalled of toolsCalled) {
453
- const colorFn = toolColors.get(toolCalled) ?? chalk.white;
454
- terminal.write(`${colorFn("██")} `);
455
- }
456
- terminal.lineBreak();
457
-
458
- const uniqueTools = new Set(toolsCalled);
459
- for (const [index, toolCalled] of Array.from(uniqueTools).entries()) {
460
- const colorFn = toolColors.get(toolCalled) ?? chalk.white;
461
- terminal.write(colorFn(toolCalled));
462
- if (index < new Set(toolsCalled).size - 1) {
463
- terminal.write(" - ");
464
- }
465
- }
466
- terminal.lineBreak();
467
- terminal.lineBreak();
468
- }
469
- }
470
- }
471
-
472
- function displayToolMessages(messages: Message[], terminal: Terminal) {
473
- const isError = messages[messages.length - 1]?.event === "tool-error";
474
- const indicator = isError ? chalk.red.bold("●") : chalk.blue.bold("●");
475
- const initMessage =
476
- messages.find((m) => m.event === "tool-init")?.data ?? "Tool Execution";
477
-
478
- terminal.write(`${indicator} `); // Write indicator without newline (sync)
479
- terminal.display(initMessage); // Display initial message (async)
480
-
481
- for (const msg of messages) {
482
- switch (msg.event) {
483
- case "tool-update":
484
- _handleToolUpdateMessage(msg.data, terminal);
485
- break;
486
- case "tool-completion":
487
- _handleToolCompletionMessage(msg.data, terminal);
488
- break;
489
- case "tool-error":
490
- _handleToolErrorMessage(msg.data, terminal);
491
- break;
492
- // 'tool-init' is handled before the loop, so no case needed here.
493
- default:
494
- // Optional: Log an unexpected event type for debugging, or do nothing.
495
- logger.debug(`Unhandled tool message event: ${msg.event}`);
496
- break;
497
- }
498
- }
499
- terminal.lineBreak();
500
- }
501
-
502
- // Helper function to handle tool update messages
503
- function _handleToolUpdateMessage(
504
- data: { primary: string; secondary?: string[] },
505
- terminal: Terminal,
506
- ) {
507
- if (data.secondary && data.secondary.length > 0) {
508
- const content = data.secondary.join("\n");
509
- if (content.trim().length !== 0) {
510
- terminal.display(`└── ${data.primary}`);
511
- terminal.hr();
512
- if (isMarkdown(content)) {
513
- terminal.display(content, true);
514
- } else {
515
- terminal.write(chalk.green(content));
516
- terminal.lineBreak();
517
- }
518
- terminal.hr();
519
- }
520
- } else {
521
- terminal.display(`└── ${data.primary}`);
522
- }
523
- }
524
-
525
- // Helper function to handle tool completion messages
526
- function _handleToolCompletionMessage(data: string, terminal: Terminal) {
527
- terminal.display(`└── ${data}`);
528
- }
529
-
530
- // Helper function to handle tool error messages
531
- function _handleToolErrorMessage(data: string, terminal: Terminal) {
532
- terminal.write("└── ");
533
- terminal.error(data);
534
- }
535
-
536
- const toolCallRepair = (modelManager: ModelManager, terminal: Terminal) => {
537
- const fn: ToolCallRepairFunction<CompleteToolSet> = async ({
538
- toolCall,
539
- tools,
540
- inputSchema,
541
- error,
542
- }) => {
543
- if (NoSuchToolError.isInstance(error)) {
544
- return null; // do not attempt to fix invalid tool names
545
- }
546
-
547
- terminal.warn(`Attempting to repair tool call: ${toolCall.toolName}.`);
548
- terminal.lineBreak();
549
-
550
- const tool = tools[toolCall.toolName as keyof typeof tools];
551
-
552
- try {
553
- const { object: repairedArgs } = await generateObject({
554
- model: modelManager.getModel("tool-repair"),
555
- schema: tool.inputSchema as z.ZodSchema<unknown>,
556
- prompt: [
557
- `The model tried to call the tool "${toolCall.toolName}" with the following arguments:`,
558
- JSON.stringify(toolCall.input),
559
- "The tool accepts the following schema:",
560
- JSON.stringify(inputSchema(toolCall)),
561
- "Please fix the arguments.",
562
- ].join("\n"),
563
- });
564
-
565
- return { ...toolCall, args: JSON.stringify(repairedArgs) };
566
- } catch (err) {
567
- logger.error(err, `Failed to repair tool call: ${toolCall.toolName}.`);
568
- return null;
569
- }
570
- };
571
- return fn;
572
- };
@@ -1,121 +0,0 @@
1
- /**
2
- * Terminal Formatting Utilities
3
- *
4
- * Provides functions for formatting and displaying text in the terminal.
5
- */
6
-
7
- import chalk from "chalk";
8
-
9
- /**
10
- * Clear the terminal screen
11
- */
12
- export function clearScreen(): void {
13
- // Clear screen and move cursor to top-left
14
- process.stdout.write("\x1b[2J\x1b[0f");
15
- }
16
-
17
- /**
18
- * Clear the terminal screen including scrollback buffer
19
- *
20
- * Unlike clearScreen, this function:
21
- * 1. Clears the entire screen (\x1b[2J)
22
- * 2. Clears the scrollback buffer (\x1b[3J)
23
- * 3. Moves cursor to home position (\x1b[H)
24
- * 4. Returns a Promise that resolves when the write operation completes
25
- *
26
- * @returns Promise that resolves when the terminal has been cleared
27
- */
28
- export function clearTerminal(): Promise<void> {
29
- return new Promise((resolve) => {
30
- process.stdout.write("\x1b[2J\x1b[3J\x1b[H", () => {
31
- resolve();
32
- });
33
- });
34
- }
35
-
36
- /**
37
- * Sets the terminal title
38
- */
39
- export function setTerminalTitle(title: string): void {
40
- if (process.platform === "win32") {
41
- process.title = title ? `✳✳ ${title}` : title;
42
- } else {
43
- process.stdout.write(`\x1b]0;${title ? `✳✳ ${title}` : ""}\x07`);
44
- }
45
- }
46
-
47
- /**
48
- * Get the terminal size (rows and columns)
49
- */
50
- export function getTerminalSize(): { rows: number; columns: number } {
51
- // Default to a reasonable size if we can't determine the actual size
52
- const defaultSize = { rows: 24, columns: 80 };
53
-
54
- try {
55
- if (process.stdout.isTTY) {
56
- return {
57
- rows: process.stdout.rows || defaultSize.rows,
58
- columns: process.stdout.columns || defaultSize.columns,
59
- };
60
- }
61
- } catch (_error) {
62
- // Ignore errors
63
- }
64
-
65
- return defaultSize;
66
- }
67
-
68
- /**
69
- * Word wrap text to the specified width
70
- */
71
- export function wordWrap(text: string, width: number): string {
72
- const lines = text.split("\n");
73
-
74
- return lines.map((line) => wrapLine(line, width)).join("\n");
75
- }
76
-
77
- function wrapLine(line: string, width: number): string {
78
- // If the line is a code block or already shorter than the width, leave it as is
79
- if (line.trim().startsWith("┃") || line.length <= width) {
80
- return line;
81
- }
82
-
83
- // Word wrap the line
84
- const words = line.split(" ");
85
- const wrappedLines: string[] = [];
86
- let currentLine = "";
87
-
88
- for (const word of words) {
89
- // If adding this word would exceed the width
90
- if (currentLine.length + word.length + 1 > width) {
91
- // Add the current line to wrapped lines if it's not empty
92
- if (currentLine) {
93
- wrappedLines.push(currentLine);
94
- currentLine = word;
95
- } else {
96
- // If the current line is empty, it means the word itself is longer than the width
97
- wrappedLines.push(word);
98
- }
99
- } else {
100
- // Add the word to the current line
101
- currentLine = currentLine ? `${currentLine} ${word}` : word;
102
- }
103
- }
104
-
105
- // Add the last line if it's not empty
106
- if (currentLine) {
107
- wrappedLines.push(currentLine);
108
- }
109
-
110
- return wrappedLines.join("\n");
111
- }
112
-
113
- // const ESC = "\u001B[";
114
- const OSC = "\u001B]";
115
- const BEL = "\u0007";
116
- const SEP = ";";
117
-
118
- export const link = (text: string, url: string) =>
119
- chalk.underline.blue(
120
- [OSC, "8", SEP, SEP, url, BEL, text, OSC, "8", SEP, SEP, BEL].join(""),
121
- );