@travisennis/acai 0.0.3 → 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 +17 -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 -0
  239. package/dist/tools/code-interpreter.d.ts.map +1 -0
  240. package/dist/tools/code-interpreter.js +33 -8
  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 -14
  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 +10 -1
  306. package/dist/utils/process.d.ts.map +1 -0
  307. package/dist/utils/process.js +104 -5
  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 -12
  315. package/dist/tools/command-validation.js +0 -113
  316. /package/dist/{token-tracker.js → tokens/tracker.js} +0 -0
@@ -0,0 +1,439 @@
1
+ import { isZodSchema, zodToJsonSchema } from "../../utils/zod-utils.js";
2
+ // Prefer global fetch/Headers from Node >= 18
3
+ const fetchImpl = globalThis.fetch;
4
+ const HeadersImpl = globalThis.Headers;
5
+ /**
6
+ * HTTP status codes
7
+ */
8
+ const HttpStatusCode = {
9
+ badRequest: 400,
10
+ notFound: 404,
11
+ unauthorized: 401,
12
+ forbidden: 403,
13
+ tooManyRequests: 429,
14
+ requestTimeout: 408,
15
+ internalServerError: 500,
16
+ serviceUnavailable: 503,
17
+ };
18
+ /**
19
+ * Base error class for all Exa API errors
20
+ */
21
+ class ExaError extends Error {
22
+ statusCode;
23
+ timestamp;
24
+ path;
25
+ constructor(message, statusCode, timestamp, path) {
26
+ super(message);
27
+ this.name = "ExaError";
28
+ this.statusCode = statusCode;
29
+ this.timestamp = timestamp ?? new Date().toISOString();
30
+ this.path = path;
31
+ }
32
+ }
33
+ export default class Exa {
34
+ baseUrl;
35
+ headers;
36
+ constructor(apiKey, baseUrl = "https://api.exa.ai") {
37
+ this.baseUrl = baseUrl;
38
+ let resolvedKey = apiKey;
39
+ if (!resolvedKey) {
40
+ resolvedKey = process.env["EXA_API_KEY"];
41
+ if (!resolvedKey) {
42
+ throw new ExaError("API key must be provided as an argument or as an environment variable (EXA_API_KEY)", HttpStatusCode.unauthorized);
43
+ }
44
+ }
45
+ // Build base headers
46
+ const headers = new HeadersImpl();
47
+ headers.set("x-api-key", resolvedKey);
48
+ headers.set("Content-Type", "application/json");
49
+ headers.set("User-Agent", "acai-exa");
50
+ // Store as a simple record for easier merging and type safety in this codebase
51
+ const headerRecord = {};
52
+ headers.forEach((value, key) => {
53
+ headerRecord[key] = value;
54
+ });
55
+ this.headers = headerRecord;
56
+ }
57
+ extractContentsOptions(options) {
58
+ const { text, highlights, summary, subpages, subpageTarget, extras, livecrawl, livecrawlTimeout, context, ...rest } = options;
59
+ const contentsOptions = {};
60
+ if (text === undefined &&
61
+ summary === undefined &&
62
+ highlights === undefined &&
63
+ extras === undefined) {
64
+ contentsOptions.text = true;
65
+ }
66
+ if (text !== undefined)
67
+ contentsOptions.text = text;
68
+ if (summary !== undefined) {
69
+ if (typeof summary === "object" &&
70
+ summary !== null &&
71
+ "schema" in summary &&
72
+ summary.schema &&
73
+ isZodSchema(summary.schema)) {
74
+ const { schema, ...restSummary } = summary;
75
+ contentsOptions.summary = {
76
+ ...restSummary,
77
+ schema: zodToJsonSchema(schema),
78
+ };
79
+ }
80
+ else {
81
+ contentsOptions.summary = summary;
82
+ }
83
+ }
84
+ if (highlights !== undefined)
85
+ contentsOptions.highlights = highlights;
86
+ if (subpages !== undefined)
87
+ contentsOptions.subpages = subpages;
88
+ if (subpageTarget !== undefined)
89
+ contentsOptions.subpageTarget = subpageTarget;
90
+ if (extras !== undefined)
91
+ contentsOptions.extras = extras;
92
+ if (livecrawl !== undefined)
93
+ contentsOptions.livecrawl = livecrawl;
94
+ if (livecrawlTimeout !== undefined)
95
+ contentsOptions.livecrawlTimeout = livecrawlTimeout;
96
+ if (context !== undefined)
97
+ contentsOptions.context = context;
98
+ return {
99
+ contentsOptions,
100
+ restOptions: rest,
101
+ };
102
+ }
103
+ async request(endpoint, method, body, params, headers) {
104
+ if (!fetchImpl) {
105
+ throw new ExaError("Global fetch is not available in this environment.", HttpStatusCode.internalServerError);
106
+ }
107
+ let url = this.baseUrl + endpoint;
108
+ if (params && Object.keys(params).length > 0) {
109
+ const searchParams = new URLSearchParams();
110
+ for (const [key, value] of Object.entries(params)) {
111
+ if (Array.isArray(value)) {
112
+ for (const item of value) {
113
+ searchParams.append(key, String(item));
114
+ }
115
+ }
116
+ else if (value !== undefined && value !== null) {
117
+ searchParams.append(key, String(value));
118
+ }
119
+ }
120
+ url += `?${searchParams.toString()}`;
121
+ }
122
+ const combinedHeaders = {
123
+ ...this.headers,
124
+ ...(headers ?? {}),
125
+ };
126
+ const response = await fetchImpl(url, {
127
+ method,
128
+ headers: combinedHeaders,
129
+ body: body !== undefined ? JSON.stringify(body) : undefined,
130
+ });
131
+ if (!response.ok) {
132
+ let errorMessage = `HTTP ${response.status}`;
133
+ let errorTimestamp;
134
+ let errorPath = endpoint;
135
+ try {
136
+ const errorData = await response.json();
137
+ const message = (errorData &&
138
+ (errorData.error || errorData.message));
139
+ if (typeof message === "string" && message.length > 0) {
140
+ errorMessage = message;
141
+ }
142
+ errorTimestamp =
143
+ (errorData && errorData.timestamp) ??
144
+ new Date().toISOString();
145
+ errorPath =
146
+ (errorData && errorData.path) ?? endpoint;
147
+ }
148
+ catch {
149
+ // ignore body parse errors
150
+ }
151
+ throw new ExaError(errorMessage, response.status, errorTimestamp, errorPath);
152
+ }
153
+ const contentType = response.headers.get("content-type") || "";
154
+ if (contentType.includes("text/event-stream")) {
155
+ return (await this.parseSseStream(response));
156
+ }
157
+ return (await response.json());
158
+ }
159
+ async rawRequest(endpoint, method = "POST", body, queryParams) {
160
+ if (!fetchImpl) {
161
+ throw new ExaError("Global fetch is not available in this environment.", HttpStatusCode.internalServerError);
162
+ }
163
+ let url = this.baseUrl + endpoint;
164
+ if (queryParams) {
165
+ const searchParams = new URLSearchParams();
166
+ for (const [key, value] of Object.entries(queryParams)) {
167
+ if (Array.isArray(value)) {
168
+ for (const item of value) {
169
+ searchParams.append(key, String(item));
170
+ }
171
+ }
172
+ else if (value !== undefined && value !== null) {
173
+ searchParams.append(key, String(value));
174
+ }
175
+ }
176
+ url += `?${searchParams.toString()}`;
177
+ }
178
+ const response = await fetchImpl(url, {
179
+ method,
180
+ headers: this.headers,
181
+ body: body ? JSON.stringify(body) : undefined,
182
+ });
183
+ return response;
184
+ }
185
+ async search(query, options) {
186
+ return await this.request("/search", "POST", { query, ...options });
187
+ }
188
+ async searchAndContents(query, options) {
189
+ const { contentsOptions, restOptions } = options === undefined
190
+ ? {
191
+ contentsOptions: { text: true },
192
+ restOptions: {},
193
+ }
194
+ : this.extractContentsOptions(options);
195
+ return await this.request("/search", "POST", {
196
+ query,
197
+ contents: contentsOptions,
198
+ ...restOptions,
199
+ });
200
+ }
201
+ async findSimilar(url, options) {
202
+ return await this.request("/findSimilar", "POST", { url, ...options });
203
+ }
204
+ async findSimilarAndContents(url, options) {
205
+ const { contentsOptions, restOptions } = options === undefined
206
+ ? {
207
+ contentsOptions: { text: true },
208
+ restOptions: {},
209
+ }
210
+ : this.extractContentsOptions(options);
211
+ return await this.request("/findSimilar", "POST", {
212
+ url,
213
+ contents: contentsOptions,
214
+ ...restOptions,
215
+ });
216
+ }
217
+ async getContents(urls, options) {
218
+ if (!urls || (Array.isArray(urls) && urls.length === 0)) {
219
+ throw new ExaError("Must provide at least one URL", HttpStatusCode.badRequest);
220
+ }
221
+ let requestUrls;
222
+ if (typeof urls === "string") {
223
+ requestUrls = [urls];
224
+ }
225
+ else if (Array.isArray(urls) && typeof urls[0] === "string") {
226
+ requestUrls = urls;
227
+ }
228
+ else {
229
+ requestUrls = urls.map((result) => result.url);
230
+ }
231
+ const payload = {
232
+ urls: requestUrls,
233
+ ...(options ?? {}),
234
+ };
235
+ return await this.request("/contents", "POST", payload);
236
+ }
237
+ async answer(query, options) {
238
+ if (options?.stream) {
239
+ throw new ExaError("For streaming responses, please use streamAnswer() instead:\n\n" +
240
+ "for await (const chunk of exa.streamAnswer(query)) {\n" +
241
+ " // Handle chunks\n" +
242
+ "}", HttpStatusCode.badRequest);
243
+ }
244
+ let outputSchema = options
245
+ ?.outputSchema;
246
+ if (outputSchema && isZodSchema(outputSchema)) {
247
+ outputSchema = zodToJsonSchema(outputSchema);
248
+ }
249
+ const requestBody = {
250
+ query,
251
+ stream: false,
252
+ text: options?.text ?? false,
253
+ model: options?.model ?? "exa",
254
+ systemPrompt: options
255
+ ?.systemPrompt,
256
+ outputSchema,
257
+ userLocation: options
258
+ ?.userLocation,
259
+ };
260
+ return await this.request("/answer", "POST", requestBody);
261
+ }
262
+ async *streamAnswer(query, options) {
263
+ if (!fetchImpl) {
264
+ throw new ExaError("Global fetch is not available in this environment.", HttpStatusCode.internalServerError);
265
+ }
266
+ let outputSchema = options?.outputSchema;
267
+ if (outputSchema && isZodSchema(outputSchema)) {
268
+ outputSchema = zodToJsonSchema(outputSchema);
269
+ }
270
+ const body = {
271
+ query,
272
+ text: options?.text ?? false,
273
+ stream: true,
274
+ model: options?.model ?? "exa",
275
+ systemPrompt: options?.systemPrompt,
276
+ outputSchema,
277
+ };
278
+ const response = await fetchImpl(`${this.baseUrl}/answer`, {
279
+ method: "POST",
280
+ headers: this.headers,
281
+ body: JSON.stringify(body),
282
+ });
283
+ if (!response.ok) {
284
+ const message = await response.text();
285
+ throw new ExaError(message, response.status, new Date().toISOString());
286
+ }
287
+ const reader = response.body?.getReader();
288
+ if (!reader) {
289
+ throw new ExaError("No response body available for streaming.", 500, new Date().toISOString());
290
+ }
291
+ const decoder = new TextDecoder();
292
+ let buffer = "";
293
+ try {
294
+ while (true) {
295
+ const { done, value } = await reader.read();
296
+ if (done)
297
+ break;
298
+ buffer += decoder.decode(value, { stream: true });
299
+ const lines = buffer.split("\n");
300
+ buffer = lines.pop() ?? "";
301
+ for (const line of lines) {
302
+ if (!line.startsWith("data: "))
303
+ continue;
304
+ const jsonStr = line.replace(/^data:\s*/, "").trim();
305
+ if (!jsonStr || jsonStr === "[DONE]") {
306
+ continue;
307
+ }
308
+ let chunkData;
309
+ try {
310
+ chunkData = JSON.parse(jsonStr);
311
+ }
312
+ catch {
313
+ continue;
314
+ }
315
+ const chunk = this.processChunk(chunkData);
316
+ if (chunk.content || chunk.citations) {
317
+ yield chunk;
318
+ }
319
+ }
320
+ }
321
+ if (buffer.startsWith("data: ")) {
322
+ const leftover = buffer.replace(/^data:\s*/, "").trim();
323
+ if (leftover && leftover !== "[DONE]") {
324
+ try {
325
+ const chunkData = JSON.parse(leftover);
326
+ const chunk = this.processChunk(chunkData);
327
+ if (chunk.content || chunk.citations) {
328
+ yield chunk;
329
+ }
330
+ }
331
+ catch {
332
+ // ignore
333
+ }
334
+ }
335
+ }
336
+ }
337
+ finally {
338
+ reader.releaseLock();
339
+ }
340
+ }
341
+ processChunk(chunkData) {
342
+ let content;
343
+ let citations;
344
+ const data = chunkData;
345
+ const choices = data?.["choices"] ?? undefined;
346
+ if (choices?.[0]?.delta) {
347
+ const c = choices[0].delta.content;
348
+ if (typeof c === "string") {
349
+ content = c;
350
+ }
351
+ }
352
+ const rawCitations = data?.["citations"];
353
+ if (rawCitations &&
354
+ rawCitations !== "null" &&
355
+ Array.isArray(rawCitations)) {
356
+ citations = rawCitations.map((c) => ({
357
+ id: String(c["id"] ?? ""),
358
+ url: String(c["url"] ?? ""),
359
+ title: typeof c["title"] === "string"
360
+ ? c["title"]
361
+ : undefined,
362
+ publishedDate: typeof c["publishedDate"] === "string"
363
+ ? c["publishedDate"]
364
+ : undefined,
365
+ author: typeof c["author"] === "string"
366
+ ? c["author"]
367
+ : undefined,
368
+ text: typeof c["text"] === "string"
369
+ ? c["text"]
370
+ : undefined,
371
+ }));
372
+ }
373
+ return { content, citations };
374
+ }
375
+ async parseSseStream(response) {
376
+ const reader = response.body?.getReader();
377
+ if (!reader) {
378
+ throw new ExaError("No response body available for streaming.", 500, new Date().toISOString());
379
+ }
380
+ const decoder = new TextDecoder();
381
+ let buffer = "";
382
+ return await new Promise((resolve, reject) => {
383
+ (async () => {
384
+ try {
385
+ while (true) {
386
+ const { done, value } = await reader.read();
387
+ if (done)
388
+ break;
389
+ buffer += decoder.decode(value, { stream: true });
390
+ const lines = buffer.split("\n");
391
+ buffer = lines.pop() ?? "";
392
+ for (const line of lines) {
393
+ if (!line.startsWith("data: "))
394
+ continue;
395
+ const jsonStr = line.replace(/^data:\s*/, "").trim();
396
+ if (!jsonStr || jsonStr === "[DONE]") {
397
+ continue;
398
+ }
399
+ let chunk;
400
+ try {
401
+ chunk = JSON.parse(jsonStr);
402
+ }
403
+ catch {
404
+ continue;
405
+ }
406
+ const tagged = chunk;
407
+ switch (tagged.tag) {
408
+ case "complete":
409
+ reader.releaseLock();
410
+ resolve(tagged.data);
411
+ return;
412
+ case "error": {
413
+ const message = tagged.error?.message || "Unknown error";
414
+ reader.releaseLock();
415
+ reject(new ExaError(message, HttpStatusCode.internalServerError, new Date().toISOString()));
416
+ return;
417
+ }
418
+ default:
419
+ break;
420
+ }
421
+ }
422
+ }
423
+ reject(new ExaError("Stream ended without a completion event.", HttpStatusCode.internalServerError, new Date().toISOString()));
424
+ }
425
+ catch (err) {
426
+ reject(err);
427
+ }
428
+ finally {
429
+ try {
430
+ reader.releaseLock();
431
+ }
432
+ catch {
433
+ // ignore
434
+ }
435
+ }
436
+ })();
437
+ });
438
+ }
439
+ }
package/dist/cli.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import type { MessageHistory } from "./messages.ts";
2
2
  import type { ModelManager } from "./models/manager.js";
3
3
  import type { PromptManager } from "./prompts/manager.ts";
4
- import type { TokenTracker } from "./token-tracker.ts";
5
- import type { TokenCounter } from "./token-utils.ts";
4
+ import type { TokenCounter } from "./tokens/counter.ts";
5
+ import type { TokenTracker } from "./tokens/tracker.ts";
6
6
  interface CliOptions {
7
7
  messageHistory: MessageHistory;
8
8
  promptManager: PromptManager;
@@ -17,3 +17,4 @@ export declare class Cli {
17
17
  run(): Promise<void>;
18
18
  }
19
19
  export {};
20
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../source/cli.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAQxD,UAAU,UAAU;IAClB,cAAc,EAAE,cAAc,CAAC;IAC/B,aAAa,EAAE,aAAa,CAAC;IAC7B,YAAY,EAAE,YAAY,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACrC,YAAY,EAAE,YAAY,CAAC;CAC5B;AAID,qBAAa,GAAG;IACd,OAAO,CAAC,OAAO,CAAa;gBAChB,OAAO,EAAE,UAAU;IAIzB,GAAG;CAgGV"}
@@ -1,2 +1,3 @@
1
1
  import type { CommandOptions, ReplCommand } from "./types.ts";
2
2
  export declare const applicationLogCommand: ({ terminal, }: CommandOptions) => ReplCommand;
3
+ //# sourceMappingURL=application-log-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"application-log-command.d.ts","sourceRoot":"","sources":["../../source/commands/application-log-command.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9D,eAAO,MAAM,qBAAqB,GAAI,eAEnC,cAAc,KAAG,WAgDnB,CAAC"}
@@ -1,11 +1,10 @@
1
1
  import { readFile } from "node:fs/promises";
2
- import { editor } from "@inquirer/prompts";
3
2
  import { config } from "../config.js";
3
+ import { editor } from "../terminal/editor-prompt.js";
4
4
  export const applicationLogCommand = ({ terminal, }) => {
5
5
  return {
6
6
  command: "/application-logs",
7
7
  description: "Opens the application log file defined in acai.json in the editor.",
8
- result: "continue",
9
8
  getSubCommands: () => Promise.resolve([]),
10
9
  execute: async () => {
11
10
  let logFilePath;
@@ -14,7 +13,7 @@ export const applicationLogCommand = ({ terminal, }) => {
14
13
  logFilePath = projectConfig.logs?.path;
15
14
  if (!logFilePath) {
16
15
  terminal.error("Application log path is not defined in .acai/acai.json under the 'logs.path' key.");
17
- return;
16
+ return "continue";
18
17
  }
19
18
  const content = await readFile(logFilePath, { encoding: "utf8" });
20
19
  // Use the editor prompt to display the content (read-only)
@@ -27,8 +26,10 @@ export const applicationLogCommand = ({ terminal, }) => {
27
26
  default: content,
28
27
  // By not providing an onSubmit or similar handler to write the file,
29
28
  // and not calling writeFileSync after, this effectively becomes read-only.
29
+ skipPrompt: true,
30
30
  });
31
31
  terminal.info(`Closed log view for: ${logFilePath}`);
32
+ return "continue";
32
33
  }
33
34
  catch (error) {
34
35
  if (logFilePath && error.code === "ENOENT") {
@@ -37,6 +38,7 @@ export const applicationLogCommand = ({ terminal, }) => {
37
38
  else {
38
39
  terminal.error(`Error reading or displaying log file ${logFilePath ?? "specified in config"}: ${error}`);
39
40
  }
41
+ return "continue";
40
42
  }
41
43
  },
42
44
  };
@@ -1,2 +1,3 @@
1
1
  import type { CommandOptions, ReplCommand } from "./types.ts";
2
2
  export declare const clearCommand: ({ terminal }: CommandOptions) => ReplCommand;
3
+ //# sourceMappingURL=clear-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clear-command.d.ts","sourceRoot":"","sources":["../../source/commands/clear-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9D,eAAO,MAAM,YAAY,GAAI,cAAc,cAAc,KAAG,WAU3D,CAAC"}
@@ -2,11 +2,10 @@ export const clearCommand = ({ terminal }) => {
2
2
  return {
3
3
  command: "/clear",
4
4
  description: "Clears the terminal screen.",
5
- result: "continue", // Keep the REPL running
6
5
  getSubCommands: () => Promise.resolve([]),
7
- execute: () => {
6
+ execute: async () => {
8
7
  terminal.clear();
9
- return Promise.resolve();
8
+ return "continue";
10
9
  },
11
10
  };
12
11
  };
@@ -1,2 +1,3 @@
1
1
  import type { CommandOptions, ReplCommand } from "./types.ts";
2
2
  export declare const compactCommand: (options: CommandOptions) => ReplCommand;
3
+ //# sourceMappingURL=compact-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compact-command.d.ts","sourceRoot":"","sources":["../../source/commands/compact-command.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9D,eAAO,MAAM,cAAc,GAAI,SAAS,cAAc,KAAG,WAiBxD,CAAC"}
@@ -4,7 +4,6 @@ export const compactCommand = (options) => {
4
4
  return {
5
5
  command: "/compact",
6
6
  description: "Saves, summarizes, and resets the chat history. Optional instructions can be provided for the summary.",
7
- result: "continue",
8
7
  getSubCommands: () => Promise.resolve([]),
9
8
  execute: async (args) => {
10
9
  const { messageHistory, terminal } = options;
@@ -13,6 +12,7 @@ export const compactCommand = (options) => {
13
12
  await summarizeAndReset(options, additionalInstructions);
14
13
  }
15
14
  terminal.info("Message history summarized and reset.");
15
+ return "continue";
16
16
  },
17
17
  };
18
18
  };
@@ -1,2 +1,3 @@
1
1
  import type { CommandOptions, ReplCommand } from "./types.ts";
2
2
  export declare function copyCommand(options: CommandOptions): ReplCommand;
3
+ //# sourceMappingURL=copy-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy-command.d.ts","sourceRoot":"","sources":["../../source/commands/copy-command.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAyB9D,wBAAgB,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,WAAW,CA6BhE"}
@@ -26,7 +26,6 @@ export function copyCommand(options) {
26
26
  return {
27
27
  command: "/copy",
28
28
  description: "Copy the last assistant response to the clipboard",
29
- result: "continue",
30
29
  async getSubCommands() {
31
30
  return [];
32
31
  },
@@ -36,15 +35,17 @@ export function copyCommand(options) {
36
35
  const lastText = extractLastAssistantText(history);
37
36
  if (!lastText) {
38
37
  terminal.info("No assistant response to copy.");
39
- return;
38
+ return "continue";
40
39
  }
41
40
  try {
42
41
  await Clipboard.setText(lastText);
43
42
  terminal.success("Copied last response to clipboard.");
43
+ return "continue";
44
44
  }
45
45
  catch (err) {
46
46
  const message = err instanceof Error ? err.message : String(err);
47
47
  terminal.error(`Could not copy to clipboard: ${message}`);
48
+ return "continue";
48
49
  }
49
50
  },
50
51
  };
@@ -1,2 +1,3 @@
1
1
  import type { CommandOptions, ReplCommand } from "./types.ts";
2
2
  export declare const editCommand: ({ terminal }: CommandOptions) => ReplCommand;
3
+ //# sourceMappingURL=edit-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit-command.d.ts","sourceRoot":"","sources":["../../source/commands/edit-command.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9D,eAAO,MAAM,WAAW,GAAI,cAAc,cAAc,KAAG,WA0D1D,CAAC"}
@@ -1,12 +1,12 @@
1
1
  import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
2
  import { extname, resolve } from "node:path";
3
- import { editor, search } from "@inquirer/prompts";
4
- import { globby } from "globby";
3
+ import { editor } from "../terminal/editor-prompt.js";
4
+ import { search } from "../terminal/search-prompt.js";
5
+ import { glob } from "../utils/glob.js";
5
6
  export const editCommand = ({ terminal }) => {
6
7
  return {
7
8
  command: "/edit",
8
9
  description: "Opens file in $EDITOR for editing. Usage: /edit [file-path]",
9
- result: "continue",
10
10
  getSubCommands: () => Promise.resolve([]),
11
11
  execute: async (args) => {
12
12
  let fileToEdit;
@@ -16,7 +16,7 @@ export const editCommand = ({ terminal }) => {
16
16
  const resolvedPath = resolve(filePath);
17
17
  if (!existsSync(resolvedPath)) {
18
18
  terminal.error(`File not found: ${filePath}`);
19
- return;
19
+ return "continue";
20
20
  }
21
21
  fileToEdit = filePath;
22
22
  }
@@ -28,7 +28,7 @@ export const editCommand = ({ terminal }) => {
28
28
  if (!input) {
29
29
  return [];
30
30
  }
31
- const foundFiles = await globby(`**/*${input}*`, {
31
+ const foundFiles = await glob(`**/*${input}*`, {
32
32
  gitignore: true,
33
33
  });
34
34
  return foundFiles.map((file) => ({
@@ -43,11 +43,13 @@ export const editCommand = ({ terminal }) => {
43
43
  message: `Edit ${fileToEdit}?`,
44
44
  postfix: extname(fileToEdit),
45
45
  default: content,
46
+ skipPrompt: true,
46
47
  });
47
48
  writeFileSync(fileToEdit, edit);
48
49
  if (content !== edit) {
49
50
  terminal.info(`File updated: ${fileToEdit}`);
50
51
  }
52
+ return "continue";
51
53
  },
52
54
  };
53
55
  };
@@ -1,2 +1,3 @@
1
1
  import type { CommandOptions, ReplCommand } from "./types.ts";
2
- export declare const editPromptCommand: ({ terminal, promptManager, }: CommandOptions) => ReplCommand;
2
+ export declare const editPromptCommand: ({ terminal, promptManager, promptHistory, }: CommandOptions) => ReplCommand;
3
+ //# sourceMappingURL=edit-prompt-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit-prompt-command.d.ts","sourceRoot":"","sources":["../../source/commands/edit-prompt-command.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9D,eAAO,MAAM,iBAAiB,GAAI,6CAI/B,cAAc,KAAG,WAmCnB,CAAC"}