@travisennis/acai 0.0.4 → 0.0.5

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 (316) hide show
  1. package/README.md +225 -6
  2. package/dist/api/exa/index.d.ts +177 -0
  3. package/dist/api/exa/index.d.ts.map +1 -0
  4. package/dist/api/exa/index.js +439 -0
  5. package/dist/cli.d.ts +3 -2
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/commands/application-log-command.d.ts +1 -0
  8. package/dist/commands/application-log-command.d.ts.map +1 -0
  9. package/dist/commands/application-log-command.js +5 -3
  10. package/dist/commands/clear-command.d.ts +1 -0
  11. package/dist/commands/clear-command.d.ts.map +1 -0
  12. package/dist/commands/clear-command.js +2 -3
  13. package/dist/commands/compact-command.d.ts +1 -0
  14. package/dist/commands/compact-command.d.ts.map +1 -0
  15. package/dist/commands/compact-command.js +1 -1
  16. package/dist/commands/copy-command.d.ts +1 -0
  17. package/dist/commands/copy-command.d.ts.map +1 -0
  18. package/dist/commands/copy-command.js +3 -2
  19. package/dist/commands/edit-command.d.ts +1 -0
  20. package/dist/commands/edit-command.d.ts.map +1 -0
  21. package/dist/commands/edit-command.js +7 -5
  22. package/dist/commands/edit-prompt-command.d.ts +2 -1
  23. package/dist/commands/edit-prompt-command.d.ts.map +1 -0
  24. package/dist/commands/edit-prompt-command.js +15 -7
  25. package/dist/commands/exit-command.d.ts +13 -2
  26. package/dist/commands/exit-command.d.ts.map +1 -0
  27. package/dist/commands/exit-command.js +14 -2
  28. package/dist/commands/files-command.d.ts +1 -0
  29. package/dist/commands/files-command.d.ts.map +1 -0
  30. package/dist/commands/files-command.js +9 -8
  31. package/dist/commands/generate-rules-command.d.ts +1 -0
  32. package/dist/commands/generate-rules-command.d.ts.map +1 -0
  33. package/dist/commands/generate-rules-command.js +4 -3
  34. package/dist/commands/health-command.d.ts +3 -1
  35. package/dist/commands/health-command.d.ts.map +1 -0
  36. package/dist/commands/health-command.js +42 -5
  37. package/dist/commands/help-command.d.ts +1 -0
  38. package/dist/commands/help-command.d.ts.map +1 -0
  39. package/dist/commands/help-command.js +2 -3
  40. package/dist/commands/init-command.d.ts +1 -0
  41. package/dist/commands/init-command.d.ts.map +1 -0
  42. package/dist/commands/init-command.js +1 -2
  43. package/dist/commands/last-log-command.d.ts +1 -0
  44. package/dist/commands/last-log-command.d.ts.map +1 -0
  45. package/dist/commands/last-log-command.js +12 -17
  46. package/dist/commands/list-tools-command.d.ts +3 -0
  47. package/dist/commands/list-tools-command.d.ts.map +1 -0
  48. package/dist/commands/list-tools-command.js +61 -0
  49. package/dist/commands/manager.d.ts +7 -2
  50. package/dist/commands/manager.d.ts.map +1 -0
  51. package/dist/commands/manager.js +43 -6
  52. package/dist/commands/model-command.d.ts +1 -0
  53. package/dist/commands/model-command.d.ts.map +1 -0
  54. package/dist/commands/model-command.js +5 -5
  55. package/dist/commands/paste-command.d.ts +1 -0
  56. package/dist/commands/paste-command.d.ts.map +1 -0
  57. package/dist/commands/paste-command.js +6 -5
  58. package/dist/commands/prompt-command.d.ts +2 -1
  59. package/dist/commands/prompt-command.d.ts.map +1 -0
  60. package/dist/commands/prompt-command.js +62 -8
  61. package/dist/commands/reset-command.d.ts +1 -0
  62. package/dist/commands/reset-command.d.ts.map +1 -0
  63. package/dist/commands/reset-command.js +1 -1
  64. package/dist/commands/rules-command.d.ts +1 -0
  65. package/dist/commands/rules-command.d.ts.map +1 -0
  66. package/dist/commands/rules-command.js +5 -3
  67. package/dist/commands/save-command.d.ts +1 -0
  68. package/dist/commands/save-command.d.ts.map +1 -0
  69. package/dist/commands/save-command.js +1 -1
  70. package/dist/commands/shell-command.d.ts +3 -0
  71. package/dist/commands/shell-command.d.ts.map +1 -0
  72. package/dist/commands/shell-command.js +60 -0
  73. package/dist/commands/types.d.ts +9 -6
  74. package/dist/commands/types.d.ts.map +1 -0
  75. package/dist/commands/usage-command.d.ts +1 -0
  76. package/dist/commands/usage-command.d.ts.map +1 -0
  77. package/dist/commands/usage-command.js +2 -3
  78. package/dist/config.d.ts +22 -34
  79. package/dist/config.d.ts.map +1 -0
  80. package/dist/config.js +61 -15
  81. package/dist/conversation-analyzer.d.ts +2 -1
  82. package/dist/conversation-analyzer.d.ts.map +1 -0
  83. package/dist/dedent.d.ts +1 -0
  84. package/dist/dedent.d.ts.map +1 -0
  85. package/dist/execution/index.d.ts +112 -0
  86. package/dist/execution/index.d.ts.map +1 -0
  87. package/dist/execution/index.js +432 -0
  88. package/dist/formatting.d.ts +2 -13
  89. package/dist/formatting.d.ts.map +1 -0
  90. package/dist/formatting.js +5 -64
  91. package/dist/index.d.ts +1 -0
  92. package/dist/index.d.ts.map +1 -0
  93. package/dist/index.js +14 -4
  94. package/dist/logger.d.ts +1 -0
  95. package/dist/logger.d.ts.map +1 -0
  96. package/dist/mentions.d.ts +4 -0
  97. package/dist/mentions.d.ts.map +1 -0
  98. package/dist/mentions.js +42 -10
  99. package/dist/messages.d.ts +8 -20
  100. package/dist/messages.d.ts.map +1 -0
  101. package/dist/messages.js +33 -53
  102. package/dist/middleware/audit-message.d.ts +1 -0
  103. package/dist/middleware/audit-message.d.ts.map +1 -0
  104. package/dist/middleware/index.d.ts +1 -0
  105. package/dist/middleware/index.d.ts.map +1 -0
  106. package/dist/middleware/rate-limit.d.ts +1 -0
  107. package/dist/middleware/rate-limit.d.ts.map +1 -0
  108. package/dist/models/ai-config.d.ts +1 -0
  109. package/dist/models/ai-config.d.ts.map +1 -0
  110. package/dist/models/anthropic-provider.d.ts +1 -0
  111. package/dist/models/anthropic-provider.d.ts.map +1 -0
  112. package/dist/models/deepseek-provider.d.ts +1 -0
  113. package/dist/models/deepseek-provider.d.ts.map +1 -0
  114. package/dist/models/google-provider.d.ts +1 -0
  115. package/dist/models/google-provider.d.ts.map +1 -0
  116. package/dist/models/groq-provider.d.ts +20 -0
  117. package/dist/models/groq-provider.d.ts.map +1 -0
  118. package/dist/models/groq-provider.js +31 -0
  119. package/dist/models/manager.d.ts +1 -0
  120. package/dist/models/manager.d.ts.map +1 -0
  121. package/dist/models/openai-provider.d.ts +2 -1
  122. package/dist/models/openai-provider.d.ts.map +1 -0
  123. package/dist/models/openrouter-provider.d.ts +31 -22
  124. package/dist/models/openrouter-provider.d.ts.map +1 -0
  125. package/dist/models/openrouter-provider.js +115 -1
  126. package/dist/models/providers.d.ts +4 -5
  127. package/dist/models/providers.d.ts.map +1 -0
  128. package/dist/models/providers.js +7 -3
  129. package/dist/models/xai-provider.d.ts +1 -0
  130. package/dist/models/xai-provider.d.ts.map +1 -0
  131. package/dist/parsing.d.ts +2 -1
  132. package/dist/parsing.d.ts.map +1 -0
  133. package/dist/prompts/manager.d.ts +14 -2
  134. package/dist/prompts/manager.d.ts.map +1 -0
  135. package/dist/prompts.d.ts +1 -0
  136. package/dist/prompts.d.ts.map +1 -0
  137. package/dist/prompts.js +15 -11
  138. package/dist/repl/display-tool-messages.d.ts +4 -0
  139. package/dist/repl/display-tool-messages.d.ts.map +1 -0
  140. package/dist/repl/display-tool-messages.js +55 -0
  141. package/dist/repl/display-tool-use.d.ts +14 -0
  142. package/dist/repl/display-tool-use.d.ts.map +1 -0
  143. package/dist/repl/display-tool-use.js +63 -0
  144. package/dist/repl/get-prompt-header.d.ts +8 -0
  145. package/dist/repl/get-prompt-header.d.ts.map +1 -0
  146. package/dist/repl/get-prompt-header.js +38 -0
  147. package/dist/repl/tool-call-repair.d.ts +4 -0
  148. package/dist/repl/tool-call-repair.d.ts.map +1 -0
  149. package/dist/repl/tool-call-repair.js +50 -0
  150. package/dist/repl-prompt.d.ts +1 -0
  151. package/dist/repl-prompt.d.ts.map +1 -0
  152. package/dist/repl.d.ts +8 -4
  153. package/dist/repl.d.ts.map +1 -0
  154. package/dist/repl.js +108 -252
  155. package/dist/terminal/ansi-styles.d.ts +77 -0
  156. package/dist/terminal/ansi-styles.d.ts.map +1 -0
  157. package/dist/terminal/ansi-styles.js +215 -0
  158. package/dist/terminal/checkbox-prompt.d.ts +36 -0
  159. package/dist/terminal/checkbox-prompt.d.ts.map +1 -0
  160. package/dist/terminal/checkbox-prompt.js +362 -0
  161. package/dist/terminal/default-theme.d.ts +6 -0
  162. package/dist/terminal/default-theme.d.ts.map +1 -0
  163. package/dist/terminal/default-theme.js +182 -0
  164. package/dist/terminal/east-asian-width.d.ts +8 -0
  165. package/dist/terminal/east-asian-width.d.ts.map +1 -0
  166. package/dist/terminal/east-asian-width.js +409 -0
  167. package/dist/terminal/editor-prompt.d.ts +10 -0
  168. package/dist/terminal/editor-prompt.d.ts.map +1 -0
  169. package/dist/terminal/editor-prompt.js +61 -0
  170. package/dist/terminal/errors.d.ts +19 -0
  171. package/dist/terminal/errors.d.ts.map +1 -0
  172. package/dist/terminal/errors.js +37 -0
  173. package/dist/terminal/formatting.d.ts +1 -11
  174. package/dist/terminal/formatting.d.ts.map +1 -0
  175. package/dist/terminal/formatting.js +4 -20
  176. package/dist/terminal/highlight/index.d.ts +53 -0
  177. package/dist/terminal/highlight/index.d.ts.map +1 -0
  178. package/dist/terminal/highlight/index.js +90 -0
  179. package/dist/terminal/highlight/theme.d.ts +233 -0
  180. package/dist/terminal/highlight/theme.d.ts.map +1 -0
  181. package/dist/terminal/highlight/theme.js +83 -0
  182. package/dist/terminal/index.d.ts +16 -9
  183. package/dist/terminal/index.d.ts.map +1 -0
  184. package/dist/terminal/index.js +42 -126
  185. package/dist/terminal/input-prompt.d.ts +16 -0
  186. package/dist/terminal/input-prompt.d.ts.map +1 -0
  187. package/dist/terminal/input-prompt.js +181 -0
  188. package/dist/terminal/markdown-utils.d.ts +1 -0
  189. package/dist/terminal/markdown-utils.d.ts.map +1 -0
  190. package/dist/terminal/markdown.d.ts +1 -0
  191. package/dist/terminal/markdown.d.ts.map +1 -0
  192. package/dist/terminal/markdown.js +17 -12
  193. package/dist/terminal/search-prompt.d.ts +20 -0
  194. package/dist/terminal/search-prompt.d.ts.map +1 -0
  195. package/dist/terminal/search-prompt.js +279 -0
  196. package/dist/terminal/select-prompt.d.ts +26 -0
  197. package/dist/terminal/select-prompt.d.ts.map +1 -0
  198. package/dist/terminal/select-prompt.js +298 -0
  199. package/dist/terminal/string-width.d.ts +7 -0
  200. package/dist/terminal/string-width.d.ts.map +1 -0
  201. package/dist/terminal/string-width.js +61 -0
  202. package/dist/terminal/strip-ansi.d.ts +2 -0
  203. package/dist/terminal/strip-ansi.d.ts.map +1 -0
  204. package/dist/terminal/strip-ansi.js +20 -0
  205. package/dist/terminal/style.d.ts +191 -0
  206. package/dist/terminal/style.d.ts.map +1 -0
  207. package/dist/terminal/style.js +259 -0
  208. package/dist/terminal/supports-color.d.ts +1 -0
  209. package/dist/terminal/supports-color.d.ts.map +1 -0
  210. package/dist/terminal/supports-hyperlinks.d.ts +1 -3
  211. package/dist/terminal/supports-hyperlinks.d.ts.map +1 -0
  212. package/dist/terminal/supports-hyperlinks.js +1 -1
  213. package/dist/terminal/types.d.ts +1 -37
  214. package/dist/terminal/types.d.ts.map +1 -0
  215. package/dist/terminal/wrap-ansi.d.ts +8 -0
  216. package/dist/terminal/wrap-ansi.d.ts.map +1 -0
  217. package/dist/terminal/wrap-ansi.js +190 -0
  218. package/dist/{token-utils.d.ts → tokens/counter.d.ts} +1 -0
  219. package/dist/tokens/counter.d.ts.map +1 -0
  220. package/dist/{token-utils.js → tokens/counter.js} +1 -1
  221. package/dist/tokens/manage-output.d.ts +34 -0
  222. package/dist/tokens/manage-output.d.ts.map +1 -0
  223. package/dist/tokens/manage-output.js +44 -0
  224. package/dist/{token-tracker.d.ts → tokens/tracker.d.ts} +1 -0
  225. package/dist/tokens/tracker.d.ts.map +1 -0
  226. package/dist/tool-executor.d.ts +28 -0
  227. package/dist/tool-executor.d.ts.map +1 -0
  228. package/dist/tool-executor.js +74 -0
  229. package/dist/tools/agent.d.ts +3 -2
  230. package/dist/tools/agent.d.ts.map +1 -0
  231. package/dist/tools/agent.js +7 -4
  232. package/dist/tools/bash-utils.d.ts +7 -0
  233. package/dist/tools/bash-utils.d.ts.map +1 -0
  234. package/dist/tools/bash-utils.js +212 -0
  235. package/dist/tools/bash.d.ts +9 -7
  236. package/dist/tools/bash.d.ts.map +1 -0
  237. package/dist/tools/bash.js +95 -212
  238. package/dist/tools/code-interpreter.d.ts +1 -1
  239. package/dist/tools/code-interpreter.d.ts.map +1 -0
  240. package/dist/tools/code-interpreter.js +31 -96
  241. package/dist/tools/delete-file.d.ts +5 -3
  242. package/dist/tools/delete-file.d.ts.map +1 -0
  243. package/dist/tools/delete-file.js +47 -33
  244. package/dist/tools/directory-tree.d.ts +10 -1
  245. package/dist/tools/directory-tree.d.ts.map +1 -0
  246. package/dist/tools/directory-tree.js +91 -8
  247. package/dist/tools/dynamic-tool-loader.d.ts +12 -0
  248. package/dist/tools/dynamic-tool-loader.d.ts.map +1 -0
  249. package/dist/tools/dynamic-tool-loader.js +280 -0
  250. package/dist/tools/dynamic-tool-parser.d.ts +20 -0
  251. package/dist/tools/dynamic-tool-parser.d.ts.map +1 -0
  252. package/dist/tools/dynamic-tool-parser.js +21 -0
  253. package/dist/tools/edit-file.d.ts +10 -2
  254. package/dist/tools/edit-file.d.ts.map +1 -0
  255. package/dist/tools/edit-file.js +117 -40
  256. package/dist/tools/file-editing-utils.d.ts +2 -0
  257. package/dist/tools/file-editing-utils.d.ts.map +1 -0
  258. package/dist/tools/file-editing-utils.js +135 -0
  259. package/dist/tools/filesystem-utils.d.ts +6 -21
  260. package/dist/tools/filesystem-utils.d.ts.map +1 -0
  261. package/dist/tools/filesystem-utils.js +96 -148
  262. package/dist/tools/git-utils.d.ts +1 -0
  263. package/dist/tools/git-utils.d.ts.map +1 -0
  264. package/dist/tools/grep.d.ts +5 -3
  265. package/dist/tools/grep.d.ts.map +1 -0
  266. package/dist/tools/grep.js +67 -27
  267. package/dist/tools/index.d.ts +10 -16
  268. package/dist/tools/index.d.ts.map +1 -0
  269. package/dist/tools/index.js +33 -22
  270. package/dist/tools/move-file.d.ts +1 -0
  271. package/dist/tools/move-file.d.ts.map +1 -0
  272. package/dist/tools/move-file.js +12 -5
  273. package/dist/tools/read-file.d.ts +2 -1
  274. package/dist/tools/read-file.d.ts.map +1 -0
  275. package/dist/tools/read-file.js +13 -6
  276. package/dist/tools/read-multiple-files.d.ts +2 -1
  277. package/dist/tools/read-multiple-files.d.ts.map +1 -0
  278. package/dist/tools/read-multiple-files.js +90 -9
  279. package/dist/tools/save-file.d.ts +5 -3
  280. package/dist/tools/save-file.d.ts.map +1 -0
  281. package/dist/tools/save-file.js +64 -36
  282. package/dist/tools/think.d.ts +1 -0
  283. package/dist/tools/think.d.ts.map +1 -0
  284. package/dist/tools/think.js +5 -1
  285. package/dist/tools/types.d.ts +14 -1
  286. package/dist/tools/types.d.ts.map +1 -0
  287. package/dist/tools/web-fetch.d.ts +4 -2
  288. package/dist/tools/web-fetch.d.ts.map +1 -0
  289. package/dist/tools/web-fetch.js +2 -2
  290. package/dist/tools/web-search.d.ts +2 -1
  291. package/dist/tools/web-search.d.ts.map +1 -0
  292. package/dist/tools/web-search.js +46 -11
  293. package/dist/utils/filesystem.d.ts +23 -0
  294. package/dist/utils/filesystem.d.ts.map +1 -0
  295. package/dist/utils/filesystem.js +140 -0
  296. package/dist/utils/filetype-detection.d.ts +3 -0
  297. package/dist/utils/filetype-detection.d.ts.map +1 -0
  298. package/dist/utils/filetype-detection.js +112 -0
  299. package/dist/utils/glob.d.ts +52 -0
  300. package/dist/utils/glob.d.ts.map +1 -0
  301. package/dist/utils/glob.js +376 -0
  302. package/dist/utils/ignore.d.ts +104 -0
  303. package/dist/utils/ignore.d.ts.map +1 -0
  304. package/dist/utils/ignore.js +649 -0
  305. package/dist/utils/process.d.ts +3 -2
  306. package/dist/utils/process.d.ts.map +1 -0
  307. package/dist/utils/process.js +17 -2
  308. package/dist/utils/zod-utils.d.ts +4 -0
  309. package/dist/utils/zod-utils.d.ts.map +1 -0
  310. package/dist/utils/zod-utils.js +7 -0
  311. package/dist/version.d.ts +1 -0
  312. package/dist/version.d.ts.map +1 -0
  313. package/package.json +32 -30
  314. package/dist/tools/command-validation.d.ts +0 -11
  315. package/dist/tools/command-validation.js +0 -45
  316. /package/dist/{token-tracker.js → tokens/tracker.js} +0 -0
@@ -1,20 +1,20 @@
1
1
  import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
- import { input, select } from "@inquirer/prompts";
4
3
  import { tool } from "ai";
5
- import chalk from "chalk";
6
4
  import { z } from "zod";
5
+ import { formatCodeBlock } from "../formatting.js";
6
+ import style from "../terminal/style.js";
7
7
  import { joinWorkingDir, validatePath } from "./filesystem-utils.js";
8
8
  import { fileEncodingSchema } from "./types.js";
9
9
  export const SaveFileTool = {
10
10
  name: "saveFile",
11
11
  };
12
- export const createSaveFileTool = async ({ workingDir, sendData, terminal, autoAcceptAll, }) => {
12
+ export const createSaveFileTool = async ({ workingDir, terminal, sendData, toolExecutor, }) => {
13
13
  const allowedDirectory = workingDir;
14
- let autoAcceptSaves = autoAcceptAll ?? false;
15
14
  return {
16
15
  [SaveFileTool.name]: tool({
17
16
  description: "Create a new file or completely overwrite an existing file with new content. " +
17
+ "Automatically creates all missing parent directories. " +
18
18
  "Use with caution as it will overwrite existing files without warning. " +
19
19
  "Handles text content with proper encoding. Only works within allowed directories.",
20
20
  inputSchema: z.object({
@@ -22,61 +22,89 @@ export const createSaveFileTool = async ({ workingDir, sendData, terminal, autoA
22
22
  content: z.string().describe("Content to save in the file"),
23
23
  encoding: fileEncodingSchema.describe('Encoding format for saving the file. Use "utf-8" as default for text files'),
24
24
  }),
25
- execute: async ({ path: userPath, content, encoding, }, { toolCallId }) => {
25
+ execute: async ({ path: userPath, content, encoding, }, { toolCallId, abortSignal }) => {
26
+ // Check if execution has been aborted
27
+ if (abortSignal?.aborted) {
28
+ throw new Error("File saving aborted");
29
+ }
26
30
  sendData?.({
27
31
  id: toolCallId,
28
32
  event: "tool-init",
29
- data: `Saving file: ${chalk.cyan(userPath)}`,
33
+ data: `Saving file: ${style.cyan(userPath)}`,
30
34
  });
31
35
  try {
32
- const filePath = await validatePath(joinWorkingDir(userPath, workingDir), allowedDirectory);
36
+ const filePath = await validatePath(joinWorkingDir(userPath, workingDir), allowedDirectory, { requireExistence: false, abortSignal });
33
37
  if (terminal) {
34
- terminal.writeln(`\n${chalk.blue.bold("●")} Proposing file save: ${chalk.cyan(userPath)}`);
38
+ terminal.writeln(`\n${style.blue.bold("●")} Proposing file save: ${style.cyan(userPath)}`);
35
39
  terminal.lineBreak();
36
40
  terminal.writeln("Proposed file content:");
37
- terminal.lineBreak();
38
- terminal.display(content);
39
- terminal.lineBreak();
40
- let userChoice;
41
- if (autoAcceptSaves) {
42
- terminal.writeln(chalk.green("✓ Auto-accepting saves (all future saves will be accepted)"));
43
- userChoice = "accept";
41
+ terminal.hr();
42
+ terminal.display(formatCodeBlock(userPath, content));
43
+ terminal.hr();
44
+ // Determine overwrite status for display
45
+ let overwriteMessage = "";
46
+ try {
47
+ const stat = await fs.stat(filePath);
48
+ if (stat.isFile()) {
49
+ overwriteMessage = style.yellow("(Will overwrite existing file)");
50
+ }
44
51
  }
45
- else {
46
- userChoice = await select({
47
- message: "What would you like to do with this file?",
48
- choices: [
49
- { name: "Accept and save this file", value: "accept" },
50
- {
51
- name: "Accept all future saves (including this)",
52
- value: "accept-all",
53
- },
54
- { name: "Reject this save", value: "reject" },
55
- ],
56
- default: "accept",
57
- });
52
+ catch {
53
+ overwriteMessage = style.green("(Will create new file)");
58
54
  }
55
+ let userResponse;
56
+ if (toolExecutor) {
57
+ const ctx = {
58
+ toolName: SaveFileTool.name,
59
+ toolCallId,
60
+ message: `What would you like to do with this save? ${overwriteMessage}`,
61
+ choices: {
62
+ accept: "Accept this save",
63
+ acceptAll: "Accept all future saves (including this)",
64
+ reject: "Reject this save",
65
+ },
66
+ };
67
+ try {
68
+ userResponse = await toolExecutor.ask(ctx, { abortSignal });
69
+ }
70
+ catch (e) {
71
+ if (e.name === "AbortError") {
72
+ throw new Error("File saving aborted during user input");
73
+ }
74
+ throw e;
75
+ }
76
+ }
77
+ const { result: userChoice, reason } = userResponse ?? {
78
+ result: "accept",
79
+ };
59
80
  terminal.lineBreak();
60
81
  if (userChoice === "accept-all") {
61
- autoAcceptSaves = true;
62
- terminal.writeln(chalk.yellow("✓ Auto-accept mode enabled for all future saves"));
82
+ terminal.writeln(style.yellow("✓ Auto-accept mode enabled for all saves"));
63
83
  terminal.lineBreak();
64
84
  }
65
85
  if (userChoice === "reject") {
66
- const reason = await input({ message: "Feedback: " });
67
86
  terminal.lineBreak();
87
+ const rejectionReason = reason || "No reason provided";
68
88
  sendData?.({
69
89
  id: toolCallId,
70
90
  event: "tool-completion",
71
- data: `Save rejected by user. Reason: ${reason}`,
91
+ data: `Save rejected by user. Reason: ${rejectionReason}`,
72
92
  });
73
- return `The user rejected this save. Reason: ${reason}`;
93
+ return `The user rejected this save. Reason: ${rejectionReason}`;
74
94
  }
75
95
  // If accepted, proceed to write file
76
96
  }
77
- // Ensure parent directory exists
78
- await fs.mkdir(path.dirname(filePath), { recursive: true });
79
- await fs.writeFile(filePath, content, { encoding });
97
+ // Pre-side-effect check
98
+ if (abortSignal?.aborted) {
99
+ throw new Error("File saving aborted before writing");
100
+ }
101
+ // Ensure parent directory exists (create missing parents)
102
+ const parentDir = path.dirname(filePath);
103
+ await fs.mkdir(parentDir, { recursive: true });
104
+ await fs.writeFile(filePath, content, {
105
+ encoding,
106
+ signal: abortSignal,
107
+ });
80
108
  sendData?.({
81
109
  id: toolCallId,
82
110
  event: "tool-completion",
@@ -9,3 +9,4 @@ export declare const createThinkTool: (options?: {
9
9
  thought: string;
10
10
  }, string>;
11
11
  };
12
+ //# sourceMappingURL=think.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"think.d.ts","sourceRoot":"","sources":["../../source/tools/think.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,eAAO,MAAM,SAAS;;CAErB,CAAC;AAYF,eAAO,MAAM,eAAe,GAC1B,UAAS;IAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAA;CAAO;;;;CAmClD,CAAC"}
@@ -20,7 +20,11 @@ export const createThinkTool = (options = {}) => {
20
20
  inputSchema: z.object({
21
21
  thought: z.string().describe("Your thought"),
22
22
  }),
23
- execute: ({ thought }, { toolCallId }) => {
23
+ execute: ({ thought }, { toolCallId, abortSignal }) => {
24
+ // Check if execution has been aborted
25
+ if (abortSignal?.aborted) {
26
+ throw new Error("Thinking process aborted");
27
+ }
24
28
  // Replace literal '\\n' with actual newline characters
25
29
  const formattedThought = thought.replace(/\\n/g, "\n");
26
30
  sendData?.({
@@ -1,5 +1,17 @@
1
1
  import { z } from "zod";
2
- export declare const fileEncodingSchema: z.ZodEnum<["ascii", "utf8", "utf-8", "utf16le", "ucs2", "ucs-2", "base64", "base64url", "latin1", "binary", "hex"]>;
2
+ export declare const fileEncodingSchema: z.ZodEnum<{
3
+ utf8: "utf8";
4
+ ascii: "ascii";
5
+ "utf-8": "utf-8";
6
+ utf16le: "utf16le";
7
+ ucs2: "ucs2";
8
+ "ucs-2": "ucs-2";
9
+ base64: "base64";
10
+ base64url: "base64url";
11
+ latin1: "latin1";
12
+ binary: "binary";
13
+ hex: "hex";
14
+ }>;
3
15
  interface MessageData {
4
16
  primary: string;
5
17
  secondary?: string[] | undefined;
@@ -27,3 +39,4 @@ interface ToolUpdateMessage extends BaseMessage {
27
39
  export type Message = ToolInitMessage | ToolErrorMessage | ToolCompletionMessage | ToolUpdateMessage;
28
40
  export type SendData = ({ data, event, id, retry, }: Message) => void | Promise<void>;
29
41
  export {};
42
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../source/tools/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;EAY7B,CAAC;AAEH,UAAU,WAAW;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CAClC;AAED,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,eAAgB,SAAQ,WAAW;IAC3C,KAAK,EAAE,WAAW,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,gBAAiB,SAAQ,WAAW;IAC5C,KAAK,EAAE,YAAY,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,qBAAsB,SAAQ,WAAW;IACjD,KAAK,EAAE,iBAAiB,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,iBAAkB,SAAQ,WAAW;IAC7C,KAAK,EAAE,aAAa,CAAC;IACrB,IAAI,EAAE,WAAW,CAAC;CACnB;AAED,MAAM,MAAM,OAAO,GACf,eAAe,GACf,gBAAgB,GAChB,qBAAqB,GACrB,iBAAiB,CAAC;AAEtB,MAAM,MAAM,QAAQ,GAAG,CAAC,EACtB,IAAI,EACJ,KAAK,EACL,EAAE,EACF,KAAK,GACN,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { TokenCounter } from "../token-utils.ts";
1
+ import type { TokenCounter } from "../tokens/counter.ts";
2
2
  import type { SendData } from "./types.ts";
3
3
  export declare const WebFetchTool: {
4
4
  name: "webFetch";
@@ -11,7 +11,7 @@ export declare const createWebFetchTool: (options: {
11
11
  url: string;
12
12
  }, string>;
13
13
  };
14
- export type ContentType = "text/plain" | "text/html" | "text/markdown" | "application/json" | "application/xml" | "application/pdf" | "image/png" | "image/jpeg" | "image/gif" | "image/webp" | "image/svg+xml" | "audio/mpeg" | "audio/wav" | "video/mp4" | "video/webm" | "application/zip" | "application/octet-stream";
14
+ type ContentType = "text/plain" | "text/html" | "text/markdown" | "application/json" | "application/xml" | "application/pdf" | "image/png" | "image/jpeg" | "image/gif" | "image/webp" | "image/svg+xml" | "audio/mpeg" | "audio/wav" | "video/mp4" | "video/webm" | "application/zip" | "application/octet-stream";
15
15
  export type ReadUrlResult = {
16
16
  contentType: ContentType;
17
17
  data: string;
@@ -45,3 +45,5 @@ export declare class HtmlCleaner {
45
45
  */
46
46
  private removeEmptyElements;
47
47
  }
48
+ export {};
49
+ //# sourceMappingURL=web-fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-fetch.d.ts","sourceRoot":"","sources":["../../source/tools/web-fetch.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,eAAO,MAAM,YAAY;;CAExB,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,SAAS;IAC1C,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAChC,YAAY,EAAE,YAAY,CAAC;CAC5B;;;;CAyCA,CAAC;AAEF,KAAK,WAAW,GACZ,YAAY,GACZ,WAAW,GACX,eAAe,GACf,kBAAkB,GAClB,iBAAiB,GACjB,iBAAiB,GACjB,WAAW,GACX,YAAY,GACZ,WAAW,GACX,YAAY,GACZ,eAAe,GACf,YAAY,GACZ,WAAW,GACX,WAAW,GACX,YAAY,GACZ,iBAAiB,GACjB,0BAA0B,CAAC;AAE/B,MAAM,MAAM,aAAa,GAAG;IAAE,WAAW,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvE,wBAAsB,OAAO,CAC3B,GAAG,EAAE,MAAM,EACX,WAAW,CAAC,EAAE,WAAW,GAAG,SAAS,GACpC,OAAO,CAAC,aAAa,CAAC,CA6HxB;AAED,qBAAa,WAAW;IACtB,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW;IAIrC,OAAO,CAAC,IAAI,CAAS;IAErB,OAAO;IAIP;;;;;;OAMG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM;IAuBhE;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAyCjC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAuBzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAG5B"}
@@ -1,8 +1,8 @@
1
1
  import { tool } from "ai";
2
- import chalk from "chalk";
3
2
  import { load } from "cheerio";
4
3
  import { z } from "zod";
5
4
  import { logger } from "../logger.js";
5
+ import style from "../terminal/style.js";
6
6
  export const WebFetchTool = {
7
7
  name: "webFetch",
8
8
  };
@@ -19,7 +19,7 @@ export const createWebFetchTool = (options) => {
19
19
  sendData?.({
20
20
  event: "tool-init",
21
21
  id: toolCallId,
22
- data: `Reading URL: ${chalk.cyan(url)}`,
22
+ data: `Reading URL: ${style.cyan(url)}`,
23
23
  });
24
24
  logger.info(`Initiating fetch for URL: ${url}`);
25
25
  const result = await readUrl(url, abortSignal);
@@ -1,4 +1,4 @@
1
- import type { TokenCounter } from "../token-utils.ts";
1
+ import type { TokenCounter } from "../tokens/counter.ts";
2
2
  import type { SendData } from "./types.ts";
3
3
  export declare const WebSearchTool: {
4
4
  name: "webSearch";
@@ -11,3 +11,4 @@ export declare const createWebSearchTool: ({ sendData, tokenCounter, }: {
11
11
  query: string;
12
12
  }, string>;
13
13
  };
14
+ //# sourceMappingURL=web-search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-search.d.ts","sourceRoot":"","sources":["../../source/tools/web-search.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,eAAO,MAAM,aAAa;;CAEzB,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,6BAGjC;IACD,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,YAAY,EAAE,YAAY,CAAC;CAC5B;;;;CA0CA,CAAC"}
@@ -1,8 +1,8 @@
1
1
  import { tool } from "ai";
2
- import chalk from "chalk";
3
2
  import { SafeSearchType, search } from "duck-duck-scrape";
4
- import Exa from "exa-js";
5
3
  import { z } from "zod";
4
+ import Exa from "../api/exa/index.js";
5
+ import style from "../terminal/style.js";
6
6
  export const WebSearchTool = {
7
7
  name: "webSearch",
8
8
  };
@@ -13,13 +13,20 @@ export const createWebSearchTool = ({ sendData, tokenCounter, }) => {
13
13
  inputSchema: z.object({
14
14
  query: z.string().describe("The search query."),
15
15
  }),
16
- execute: async ({ query }, { toolCallId }) => {
16
+ execute: async ({ query }, { toolCallId, abortSignal }) => {
17
+ // Check if execution has been aborted
18
+ if (abortSignal?.aborted) {
19
+ throw new Error("Web search aborted");
20
+ }
17
21
  sendData?.({
18
22
  id: toolCallId,
19
23
  event: "tool-init",
20
- data: `Web search: ${chalk.cyan(query)}`,
24
+ data: `Web search: ${style.cyan(query)}`,
21
25
  });
22
- const result = await performSearch(query);
26
+ if (abortSignal?.aborted) {
27
+ throw new Error("Web search aborted before search execution");
28
+ }
29
+ const result = await performSearch(query, abortSignal);
23
30
  const sources = result.results.map((source) => `## ${source.title}\nURL: ${source.url}\n\n${source.text}`);
24
31
  const resultText = `# Search Results:\n\n${sources.join("\n\n")}`;
25
32
  const tokenCount = tokenCounter.count(resultText);
@@ -33,36 +40,64 @@ export const createWebSearchTool = ({ sendData, tokenCounter, }) => {
33
40
  }),
34
41
  };
35
42
  };
36
- async function performSearch(query) {
43
+ async function performSearch(query, abortSignal) {
37
44
  // Check if EXA API key is available
38
45
  const hasExaApiKey = process.env["EXA_API_KEY"] && process.env["EXA_API_KEY"].trim() !== "";
39
46
  if (hasExaApiKey) {
40
47
  // Use Exa search
41
48
  try {
49
+ if (abortSignal?.aborted) {
50
+ throw new Error("Web search aborted before Exa search");
51
+ }
42
52
  const exa = new Exa(process.env["EXA_API_KEY"]);
43
- const result = await exa.searchAndContents(query, {
53
+ // Create a promise that races with the abort signal
54
+ const searchPromise = exa.searchAndContents(query, {
44
55
  numResults: 5,
45
56
  text: true,
46
57
  });
58
+ const result = await Promise.race([
59
+ searchPromise,
60
+ new Promise((_, reject) => {
61
+ if (abortSignal) {
62
+ abortSignal.addEventListener("abort", () => {
63
+ reject(new Error("Web search aborted during Exa search"));
64
+ });
65
+ }
66
+ }),
67
+ ]);
47
68
  return result;
48
69
  }
49
70
  catch (error) {
50
71
  // If Exa fails, fall back to duck duck scrape
51
72
  console.info("Exa search failed, falling back to DuckDuckGo:", error);
52
- return await searchWithDuckDuckGo(query);
73
+ return await searchWithDuckDuckGo(query, abortSignal);
53
74
  }
54
75
  }
55
76
  else {
56
77
  // Use DuckDuckGo search as fallback
57
78
  console.info("EXA_API_KEY not set, using DuckDuckGo search");
58
- return await searchWithDuckDuckGo(query);
79
+ return await searchWithDuckDuckGo(query, abortSignal);
59
80
  }
60
81
  }
61
- async function searchWithDuckDuckGo(query) {
82
+ async function searchWithDuckDuckGo(query, abortSignal) {
62
83
  try {
63
- const searchResults = await search(query, {
84
+ if (abortSignal?.aborted) {
85
+ throw new Error("Web search aborted before DuckDuckGo search");
86
+ }
87
+ // Create a promise that races with the abort signal
88
+ const searchPromise = search(query, {
64
89
  safeSearch: SafeSearchType.MODERATE,
65
90
  });
91
+ const searchResults = await Promise.race([
92
+ searchPromise,
93
+ new Promise((_, reject) => {
94
+ if (abortSignal) {
95
+ abortSignal.addEventListener("abort", () => {
96
+ reject(new Error("Web search aborted during DuckDuckGo search"));
97
+ });
98
+ }
99
+ }),
100
+ ]);
66
101
  // Transform duck-duck-scrape results to match Exa format
67
102
  // Take only first 5 results to match Exa behavior
68
103
  const results = searchResults.results
@@ -0,0 +1,23 @@
1
+ export declare function toPath(urlOrPath: URL | string): string;
2
+ /**
3
+ * Converts Windows backslashes to POSIX forward slashes.
4
+ * Preserves UNC paths and extended-length paths.
5
+ * @param inputPath - Path to convert
6
+ * @returns Path with forward slashes
7
+ */
8
+ export declare function slash(inputPath: string): string;
9
+ /**
10
+ * Checks if a path exists and is a directory.
11
+ * @param filePath - Path to check (URL or string)
12
+ * @returns Promise resolving to true if path is a directory
13
+ * @throws TypeError if input is invalid
14
+ */
15
+ export declare function isDirectory(filePath: URL | string): Promise<boolean>;
16
+ /**
17
+ * Safely clears all contents of a directory.
18
+ * @param directoryPath - Path to the directory to clear (URL or string)
19
+ * @returns Promise that resolves when directory is cleared
20
+ * @throws Error if directory cannot be cleared or if path is invalid/unsafe
21
+ */
22
+ export declare function clearDirectory(directoryPath: URL | string): Promise<void>;
23
+ //# sourceMappingURL=filesystem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem.d.ts","sourceRoot":"","sources":["../../source/utils/filesystem.ts"],"names":[],"mappings":"AAIA,wBAAgB,MAAM,CAAC,SAAS,EAAE,GAAG,GAAG,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAS/C;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,GAAG,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAmB1E;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,aAAa,EAAE,GAAG,GAAG,MAAM,GAC1B,OAAO,CAAC,IAAI,CAAC,CAuGf"}
@@ -0,0 +1,140 @@
1
+ import * as fsPromises from "node:fs/promises";
2
+ import * as path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ export function toPath(urlOrPath) {
5
+ return urlOrPath instanceof URL ? fileURLToPath(urlOrPath) : urlOrPath;
6
+ }
7
+ /**
8
+ * Converts Windows backslashes to POSIX forward slashes.
9
+ * Preserves UNC paths and extended-length paths.
10
+ * @param inputPath - Path to convert
11
+ * @returns Path with forward slashes
12
+ */
13
+ export function slash(inputPath) {
14
+ const isExtendedLengthPath = inputPath.startsWith("\\\\?\\");
15
+ const isUncPath = inputPath.startsWith("\\\\");
16
+ if (isExtendedLengthPath || isUncPath) {
17
+ return inputPath;
18
+ }
19
+ return inputPath.replace(/\\/g, "/");
20
+ }
21
+ /**
22
+ * Checks if a path exists and is a directory.
23
+ * @param filePath - Path to check (URL or string)
24
+ * @returns Promise resolving to true if path is a directory
25
+ * @throws TypeError if input is invalid
26
+ */
27
+ export async function isDirectory(filePath) {
28
+ const resolvedPath = path.resolve(toPath(filePath));
29
+ if (typeof resolvedPath !== "string" || !resolvedPath.trim()) {
30
+ throw new TypeError(`Expected a non-empty string or URL, got ${typeof filePath}`);
31
+ }
32
+ try {
33
+ const stats = await fsPromises.stat(resolvedPath);
34
+ return stats.isDirectory();
35
+ }
36
+ catch (error) {
37
+ const err = error;
38
+ if (err.code === "ENOENT") {
39
+ return false;
40
+ }
41
+ throw error;
42
+ }
43
+ }
44
+ /**
45
+ * Safely clears all contents of a directory.
46
+ * @param directoryPath - Path to the directory to clear (URL or string)
47
+ * @returns Promise that resolves when directory is cleared
48
+ * @throws Error if directory cannot be cleared or if path is invalid/unsafe
49
+ */
50
+ export async function clearDirectory(directoryPath) {
51
+ // Convert URL to path and resolve to absolute path
52
+ const resolvedPath = path.resolve(toPath(directoryPath));
53
+ // Input validation
54
+ if (typeof resolvedPath !== "string" || !resolvedPath.trim()) {
55
+ throw new TypeError("Directory path must be a non-empty string");
56
+ }
57
+ // Safety checks - prevent clearing root or dangerous paths
58
+ const parsedPath = path.parse(resolvedPath);
59
+ const isRoot = resolvedPath === parsedPath.root;
60
+ const isCurrentDir = resolvedPath === "." || resolvedPath === path.resolve(".");
61
+ if (isRoot || isCurrentDir) {
62
+ throw new Error(`Refusing to clear dangerous path: ${resolvedPath}`);
63
+ }
64
+ try {
65
+ // Check if directory exists and is accessible
66
+ try {
67
+ const lst = await fsPromises.lstat(resolvedPath);
68
+ if (lst.isSymbolicLink()) {
69
+ throw new Error(`Refusing to clear symlink directory: ${resolvedPath}`);
70
+ }
71
+ if (!lst.isDirectory()) {
72
+ throw new Error(`Path is not a directory: ${resolvedPath}`);
73
+ }
74
+ }
75
+ catch (error) {
76
+ const err = error;
77
+ if (err.code === "ENOENT") {
78
+ // Directory doesn't exist, nothing to clear
79
+ return;
80
+ }
81
+ throw error;
82
+ }
83
+ // Read directory contents
84
+ const entries = await fsPromises.readdir(resolvedPath, {
85
+ withFileTypes: true,
86
+ });
87
+ // Delete all entries with concurrency control and proper error handling
88
+ const maxConcurrent = 50; // Limit concurrent operations to avoid EMFILE
89
+ const errors = [];
90
+ // Process entries in batches to control concurrency
91
+ for (let i = 0; i < entries.length; i += maxConcurrent) {
92
+ const batch = entries.slice(i, i + maxConcurrent);
93
+ const deletionPromises = batch.map(async (entry) => {
94
+ const entryPath = path.join(resolvedPath, entry.name);
95
+ const relativePath = path.relative(process.cwd(), entryPath);
96
+ try {
97
+ if (entry.isSymbolicLink()) {
98
+ // Always unlink symlinks, don't recurse
99
+ await fsPromises.unlink(entryPath);
100
+ }
101
+ else if (entry.isDirectory()) {
102
+ // Recursively delete subdirectories
103
+ await clearDirectory(entryPath);
104
+ // Use rm instead of deprecated rmdir
105
+ await fsPromises.rm(entryPath, { recursive: true });
106
+ }
107
+ else {
108
+ // Delete files using rm for consistency
109
+ await fsPromises.rm(entryPath, { force: false });
110
+ }
111
+ }
112
+ catch (error) {
113
+ const err = error;
114
+ errors.push({
115
+ path: relativePath,
116
+ error: err,
117
+ op: entry.isDirectory() ? "rm" : "unlink",
118
+ });
119
+ }
120
+ });
121
+ await Promise.all(deletionPromises);
122
+ }
123
+ // If any deletions failed, throw aggregated error
124
+ if (errors.length > 0) {
125
+ const errorDetails = errors
126
+ .map(({ path, error, op }) => {
127
+ const errnoError = error;
128
+ return `${path} (${op}): ${error.message} (${errnoError.code || "UNKNOWN"})`;
129
+ })
130
+ .join("; ");
131
+ throw new Error(`Failed to delete ${errors.length} entries: ${errorDetails}`, {
132
+ cause: errors[0].error,
133
+ });
134
+ }
135
+ }
136
+ catch (error) {
137
+ const err = error;
138
+ throw new Error(`Failed to clear directory ${resolvedPath}: ${err.message}`, { cause: err });
139
+ }
140
+ }
@@ -0,0 +1,3 @@
1
+ export declare function getLanguageFromFilePath(filePath: string): string | undefined;
2
+ export declare function getCodeblockFromFilePath(filePath: string): string | undefined;
3
+ //# sourceMappingURL=filetype-detection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filetype-detection.d.ts","sourceRoot":"","sources":["../../source/utils/filetype-detection.ts"],"names":[],"mappings":"AA+FA,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAW5E;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAW7E"}