exa-js 1.4.6 → 1.4.8

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.
package/dist/index.d.ts CHANGED
@@ -32,6 +32,10 @@ type BaseSearchOptions = {
32
32
  * @typedef {Object} RegularSearchOptions
33
33
  */
34
34
  type RegularSearchOptions = BaseSearchOptions & {
35
+ /**
36
+ * If true, the search results are moderated for safety.
37
+ */
38
+ moderation?: boolean;
35
39
  useAutoprompt?: boolean;
36
40
  type?: "keyword" | "neural" | "auto";
37
41
  };
@@ -58,7 +62,7 @@ type ExtrasOptions = {
58
62
  * @property {boolean} [filterEmptyResults] - If true, filters out results with no contents. Default is true.
59
63
  * @property {number} [subpages] - The number of subpages to return for each result, where each subpage is derived from an internal link for the result.
60
64
  * @property {string | string[]} [subpageTarget] - Text used to match/rank subpages in the returned subpage list. You could use "about" to get *about* page for websites. Note that this is a fuzzy matcher.
61
- * @property {ExtrasOptions} [extras] - Miscelleneous data for derived from results
65
+ * @property {ExtrasOptions} [extras] - Miscelleneous data derived from results
62
66
  */
63
67
  type ContentsOptions = {
64
68
  text?: TextContentsOptions | true;
@@ -142,7 +146,7 @@ type ExtrasResponse = {
142
146
  };
143
147
  /**
144
148
  * @typedef {Object} SubpagesResponse
145
- * @property {ContentsResultComponent<T extends ContentsOptions>} subpages - The links on the page of a result
149
+ * @property {ContentsResultComponent<T extends ContentsOptions>} subpages - The subpages for a result
146
150
  */
147
151
  type SubpagesResponse<T extends ContentsOptions> = {
148
152
  subpages: ContentsResultComponent<T>[];
@@ -164,6 +168,8 @@ type ContentsResultComponent<T extends ContentsOptions> = Default<(T["text"] ext
164
168
  * @property {string} [author] - The author of the content, if available.
165
169
  * @property {number} [score] - Similarity score between the query/url and the result.
166
170
  * @property {string} id - The temporary ID for the document.
171
+ * @property {string} [image] - A representative image for the content, if any.
172
+ * @property {string} [favicon] - A favicon for the site, if any.
167
173
  */
168
174
  type SearchResult<T extends ContentsOptions> = {
169
175
  title: string | null;
@@ -205,7 +211,7 @@ type AnswerOptions = {
205
211
  * Represents an answer response object from the /answer endpoint.
206
212
  * @typedef {Object} AnswerResponse
207
213
  * @property {string} answer - The generated answer text.
208
- * @property {SearchResult<{}>[]]} sources - The sources used to generate the answer.
214
+ * @property {SearchResult<{}>[]} sources - The sources used to generate the answer.
209
215
  * @property {string} [requestId] - Optional request ID for the answer.
210
216
  */
211
217
  type AnswerResponse = {
@@ -231,6 +237,9 @@ type AnswerStreamResponse = {
231
237
  declare class Exa {
232
238
  private baseURL;
233
239
  private headers;
240
+ /**
241
+ * Helper method to separate out the contents-specific options from the rest.
242
+ */
234
243
  private extractContentsOptions;
235
244
  /**
236
245
  * Constructs the Exa API client.
@@ -250,16 +259,18 @@ declare class Exa {
250
259
  private request;
251
260
  /**
252
261
  * Performs a search with an Exa prompt-engineered query.
262
+ *
253
263
  * @param {string} query - The query string.
254
- * @param {RegularSearchOptions} [options] - Additional search options.
264
+ * @param {RegularSearchOptions} [options] - Additional search options
255
265
  * @returns {Promise<SearchResponse<{}>>} A list of relevant search results.
256
266
  */
257
267
  search(query: string, options?: RegularSearchOptions): Promise<SearchResponse<{}>>;
258
268
  /**
259
269
  * Performs a search with an Exa prompt-engineered query and returns the contents of the documents.
270
+ *
260
271
  * @param {string} query - The query string.
261
- * @param {RegularSearchOptions & T} [options] - Additional search + contents options.
262
- * @returns {Promise<SearchResponse<T>>} A list of relevant search results.
272
+ * @param {RegularSearchOptions & T} [options] - Additional search + contents options
273
+ * @returns {Promise<SearchResponse<T>>} A list of relevant search results with requested contents.
263
274
  */
264
275
  searchAndContents<T extends ContentsOptions>(query: string, options?: RegularSearchOptions & T): Promise<SearchResponse<T>>;
265
276
  /**
@@ -273,21 +284,21 @@ declare class Exa {
273
284
  * Finds similar links to the provided URL and returns the contents of the documents.
274
285
  * @param {string} url - The URL for which to find similar links.
275
286
  * @param {FindSimilarOptions & T} [options] - Additional options for finding similar links + contents.
276
- * @returns {Promise<SearchResponse<T>>} A list of similar search results.
287
+ * @returns {Promise<SearchResponse<T>>} A list of similar search results, including requested contents.
277
288
  */
278
289
  findSimilarAndContents<T extends ContentsOptions>(url: string, options?: FindSimilarOptions & T): Promise<SearchResponse<T>>;
279
290
  /**
280
- * Retrieves contents of documents based on URLs
281
- * @param {string | string[] | SearchResult[]} urls - An array of URLs.
291
+ * Retrieves contents of documents based on URLs.
292
+ * @param {string | string[] | SearchResult[]} urls - A URL or array of URLs, or an array of SearchResult objects.
282
293
  * @param {ContentsOptions} [options] - Additional options for retrieving document contents.
283
- * @returns {Promise<SearchResponse<T>>} A list of document contents.
294
+ * @returns {Promise<SearchResponse<T>>} A list of document contents for the requested URLs.
284
295
  */
285
296
  getContents<T extends ContentsOptions>(urls: string | string[] | SearchResult<T>[], options?: T): Promise<SearchResponse<T>>;
286
297
  /**
287
298
  * Generates an answer to a query using search results as context.
288
299
  * @param {string} query - The question or query to answer.
289
300
  * @param {AnswerOptions} [options] - Additional options for answer generation.
290
- * @param {(chunk: AnswerStreamResponse) => void} [onChunk] - Callback for handling stream chunks.
301
+ * @param {(chunk: AnswerStreamResponse) => void} [onChunk] - Callback for handling stream chunks (if streaming).
291
302
  * @returns {Promise<AnswerResponse | null>} The generated answer and source references, or null if streaming.
292
303
  */
293
304
  answer(query: string, options?: AnswerOptions, onChunk?: (chunk: AnswerStreamResponse) => void): Promise<AnswerResponse | null>;
package/dist/index.js CHANGED
@@ -37,6 +37,9 @@ var import_cross_fetch = __toESM(require("cross-fetch"));
37
37
  var fetchImpl = typeof global !== "undefined" && global.fetch ? global.fetch : import_cross_fetch.default;
38
38
  var HeadersImpl = typeof global !== "undefined" && global.Headers ? global.Headers : import_cross_fetch.Headers;
39
39
  var Exa = class {
40
+ /**
41
+ * Helper method to separate out the contents-specific options from the rest.
42
+ */
40
43
  extractContentsOptions(options) {
41
44
  const {
42
45
  text,
@@ -50,8 +53,9 @@ var Exa = class {
50
53
  ...rest
51
54
  } = options;
52
55
  const contentsOptions = {};
53
- if (text === void 0 && summary === void 0 && highlights === void 0 && extras === void 0)
56
+ if (text === void 0 && summary === void 0 && highlights === void 0 && extras === void 0) {
54
57
  contentsOptions.text = true;
58
+ }
55
59
  if (text !== void 0)
56
60
  contentsOptions.text = text;
57
61
  if (summary !== void 0)
@@ -155,8 +159,9 @@ var Exa = class {
155
159
  }
156
160
  /**
157
161
  * Performs a search with an Exa prompt-engineered query.
162
+ *
158
163
  * @param {string} query - The query string.
159
- * @param {RegularSearchOptions} [options] - Additional search options.
164
+ * @param {RegularSearchOptions} [options] - Additional search options
160
165
  * @returns {Promise<SearchResponse<{}>>} A list of relevant search results.
161
166
  */
162
167
  async search(query, options) {
@@ -164,9 +169,10 @@ var Exa = class {
164
169
  }
165
170
  /**
166
171
  * Performs a search with an Exa prompt-engineered query and returns the contents of the documents.
172
+ *
167
173
  * @param {string} query - The query string.
168
- * @param {RegularSearchOptions & T} [options] - Additional search + contents options.
169
- * @returns {Promise<SearchResponse<T>>} A list of relevant search results.
174
+ * @param {RegularSearchOptions & T} [options] - Additional search + contents options
175
+ * @returns {Promise<SearchResponse<T>>} A list of relevant search results with requested contents.
170
176
  */
171
177
  async searchAndContents(query, options) {
172
178
  const { contentsOptions, restOptions } = options === void 0 ? { contentsOptions: { text: true }, restOptions: {} } : this.extractContentsOptions(options);
@@ -189,7 +195,7 @@ var Exa = class {
189
195
  * Finds similar links to the provided URL and returns the contents of the documents.
190
196
  * @param {string} url - The URL for which to find similar links.
191
197
  * @param {FindSimilarOptions & T} [options] - Additional options for finding similar links + contents.
192
- * @returns {Promise<SearchResponse<T>>} A list of similar search results.
198
+ * @returns {Promise<SearchResponse<T>>} A list of similar search results, including requested contents.
193
199
  */
194
200
  async findSimilarAndContents(url, options) {
195
201
  const { contentsOptions, restOptions } = options === void 0 ? { contentsOptions: { text: true }, restOptions: {} } : this.extractContentsOptions(options);
@@ -200,13 +206,13 @@ var Exa = class {
200
206
  });
201
207
  }
202
208
  /**
203
- * Retrieves contents of documents based on URLs
204
- * @param {string | string[] | SearchResult[]} urls - An array of URLs.
209
+ * Retrieves contents of documents based on URLs.
210
+ * @param {string | string[] | SearchResult[]} urls - A URL or array of URLs, or an array of SearchResult objects.
205
211
  * @param {ContentsOptions} [options] - Additional options for retrieving document contents.
206
- * @returns {Promise<SearchResponse<T>>} A list of document contents.
212
+ * @returns {Promise<SearchResponse<T>>} A list of document contents for the requested URLs.
207
213
  */
208
214
  async getContents(urls, options) {
209
- if (urls.length === 0) {
215
+ if (!urls || Array.isArray(urls) && urls.length === 0) {
210
216
  throw new Error("Must provide at least one URL");
211
217
  }
212
218
  let requestUrls;
@@ -221,13 +227,13 @@ var Exa = class {
221
227
  urls: requestUrls,
222
228
  ...options
223
229
  };
224
- return await this.request(`/contents`, "POST", payload);
230
+ return await this.request("/contents", "POST", payload);
225
231
  }
226
232
  /**
227
233
  * Generates an answer to a query using search results as context.
228
234
  * @param {string} query - The question or query to answer.
229
235
  * @param {AnswerOptions} [options] - Additional options for answer generation.
230
- * @param {(chunk: AnswerStreamResponse) => void} [onChunk] - Callback for handling stream chunks.
236
+ * @param {(chunk: AnswerStreamResponse) => void} [onChunk] - Callback for handling stream chunks (if streaming).
231
237
  * @returns {Promise<AnswerResponse | null>} The generated answer and source references, or null if streaming.
232
238
  */
233
239
  async answer(query, options, onChunk) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import fetch, { Headers } from \"cross-fetch\";\n\n// Use native fetch in Node.js environments\nconst fetchImpl = typeof global !== \"undefined\" && global.fetch ? global.fetch : fetch;\nconst HeadersImpl = typeof global !== \"undefined\" && global.Headers ? global.Headers : Headers;\n\nconst isBeta = false;\n\n/**\n * Search options for performing a search query.\n * @typedef {Object} SearchOptions\n * @property {number} [numResults] - Number of search results to return. Default 10. Max 10 for basic plans.\n * @property {string[]} [includeDomains] - List of domains to include in the search.\n * @property {string[]} [excludeDomains] - List of domains to exclude in the search.\n * @property {string} [startCrawlDate] - Start date for results based on crawl date.\n * @property {string} [endCrawlDate] - End date for results based on crawl date.\n * @property {string} [startPublishedDate] - Start date for results based on published date.\n * @property {string} [endPublishedDate] - End date for results based on published date.\n * @property {string} [category] - A data category to focus on, with higher comprehensivity and data cleanliness. Currently, the only category is company.\n * @property {string[]} [includeText] - List of strings that must be present in webpage text of results. Currently only supports 1 string of up to 5 words.\n * @property {string[]} [excludeText] - List of strings that must not be present in webpage text of results. Currently only supports 1 string of up to 5 words.\n * @property {string[]} [flags] - Experimental flags\n */\nexport type BaseSearchOptions = {\n numResults?: number;\n includeDomains?: string[];\n excludeDomains?: string[];\n startCrawlDate?: string;\n endCrawlDate?: string;\n startPublishedDate?: string;\n endPublishedDate?: string;\n category?: \"company\" | \"research paper\" | \"news\" | \"pdf\" | \"github\" | \"tweet\" | \"personal site\" | \"linkedin profile\" | \"financial report\";\n includeText?: string[];\n excludeText?: string[];\n flags?: string[];\n};\n\n/**\n * Search options for performing a search query.\n * @typedef {Object} RegularSearchOptions\n */\nexport type RegularSearchOptions = BaseSearchOptions & {\n useAutoprompt?: boolean;\n type?: \"keyword\" | \"neural\" | \"auto\";\n};\n\n/**\n * Options for finding similar links.\n * @typedef {Object} FindSimilarOptions\n * @property {boolean} [excludeSourceDomain] - If true, excludes links from the base domain of the input.\n */\nexport type FindSimilarOptions = BaseSearchOptions & {\n excludeSourceDomain?: boolean;\n};\n\nexport type ExtrasOptions = { links?: number; imageLinks?: number };\n\n/**\n * Search options for performing a search query.\n * @typedef {Object} ContentsOptions\n * @property {TextContentsOptions | boolean} [text] - Options for retrieving text contents.\n * @property {HighlightsContentsOptions | boolean} [highlights] - Options for retrieving highlights.\n * @property {SummaryContentsOptions | boolean} [summary] - Options for retrieving summary.\n * @property {LivecrawlOptions} [livecrawl] - Options for livecrawling contents. Default is \"never\" for neural/auto search, \"fallback\" for keyword search.\n * @property {number} [livecrawlTimeout] - The timeout for livecrawling. Max and default is 10000ms.\n * @property {boolean} [filterEmptyResults] - If true, filters out results with no contents. Default is true.\n * @property {number} [subpages] - The number of subpages to return for each result, where each subpage is derived from an internal link for the result.\n * @property {string | string[]} [subpageTarget] - Text used to match/rank subpages in the returned subpage list. You could use \"about\" to get *about* page for websites. Note that this is a fuzzy matcher.\n * @property {ExtrasOptions} [extras] - Miscelleneous data for derived from results\n */\nexport type ContentsOptions = {\n text?: TextContentsOptions | true;\n highlights?: HighlightsContentsOptions | true;\n summary?: SummaryContentsOptions | true;\n livecrawl?: LivecrawlOptions;\n livecrawlTimeout?: number;\n filterEmptyResults?: boolean;\n subpages?: number;\n subpageTarget?: string | string[];\n extras?: ExtrasOptions;\n} & (typeof isBeta extends true ? {} : {});\n\n/**\n * Options for livecrawling contents\n * @typedef {string} LivecrawlOptions\n */\nexport type LivecrawlOptions = \"never\" | \"fallback\" | \"always\" | \"auto\";\n\n/**\n * Options for retrieving text from page.\n * @typedef {Object} TextContentsOptions\n * @property {number} [maxCharacters] - The maximum number of characters to return.\n * @property {boolean} [includeHtmlTags] - If true, includes HTML tags in the returned text. Default: false\n */\nexport type TextContentsOptions = {\n maxCharacters?: number;\n includeHtmlTags?: boolean;\n};\n\n/**\n * Options for retrieving highlights from page.\n * @typedef {Object} HighlightsContentsOptions\n * @property {string} [query] - The query string to use for highlights search.\n * @property {number} [numSentences] - The number of sentences to return for each highlight.\n * @property {number} [highlightsPerUrl] - The number of highlights to return for each URL.\n */\nexport type HighlightsContentsOptions = {\n query?: string;\n numSentences?: number;\n highlightsPerUrl?: number;\n};\n\n/**\n * Options for retrieving summary from page.\n * @typedef {Object} SummaryContentsOptions\n * @property {string} [query] - The query string to use for summary generation.\n */\nexport type SummaryContentsOptions = {\n query?: string;\n};\n\n/**\n * @typedef {Object} TextResponse\n * @property {string} text - Text from page\n */\nexport type TextResponse = { text: string };\n\n/**\n * @typedef {Object} HighlightsResponse\n * @property {string[]} highlights - The highlights as an array of strings.\n * @property {number[]} highlightScores - The corresponding scores as an array of floats, 0 to 1\n */\nexport type HighlightsResponse = {\n highlights: string[];\n highlightScores: number[];\n};\n\n/**\n * @typedef {Object} SummaryResponse\n * @property {string} summary - The generated summary of the page content.\n */\nexport type SummaryResponse = { summary: string };\n\n/**\n * @typedef {Object} ExtrasResponse\n * @property {string[]} links - The links on the page of a result\n * @property {string[]} imageLinks - The image links on the page of a result\n */\nexport type ExtrasResponse = { extras: { links?: string[]; imageLinks?: string[] } };\n\n/**\n * @typedef {Object} SubpagesResponse\n * @property {ContentsResultComponent<T extends ContentsOptions>} subpages - The links on the page of a result\n */\nexport type SubpagesResponse<T extends ContentsOptions> = {\n subpages: ContentsResultComponent<T>[];\n};\n\nexport type Default<T extends {}, U> = [keyof T] extends [never] ? U : T;\n\n/**\n * @typedef {Object} ContentsResultComponent\n * Depending on 'ContentsOptions', this yields a combination of 'TextResponse', 'HighlightsResponse', 'SummaryResponse', or an empty object.\n *\n * @template T - A type extending from 'ContentsOptions'.\n */\nexport type ContentsResultComponent<T extends ContentsOptions> = Default<\n (T[\"text\"] extends object | true ? TextResponse : {}) &\n (T[\"highlights\"] extends object | true ? HighlightsResponse : {}) &\n (T[\"summary\"] extends object | true ? SummaryResponse : {}) &\n (T[\"subpages\"] extends number ? SubpagesResponse<T> : {}) &\n (T[\"extras\"] extends object ? ExtrasResponse : {}),\n TextResponse\n>;\n\n/**\n * Represents a search result object.\n * @typedef {Object} SearchResult\n * @property {string} title - The title of the search result.\n * @property {string} url - The URL of the search result.\n * @property {string} [publishedDate] - The estimated creation date of the content.\n * @property {string} [author] - The author of the content, if available.\n * @property {number} [score] - Similarity score between the query/url and the result.\n * @property {string} id - The temporary ID for the document.\n */\nexport type SearchResult<T extends ContentsOptions> = {\n title: string | null;\n url: string;\n publishedDate?: string;\n author?: string;\n score?: number;\n id: string;\n image?: string;\n favicon?: string;\n} & ContentsResultComponent<T>;\n\n/**\n * Represents a search response object.\n * @typedef {Object} SearchResponse\n * @property {Result[]} results - The list of search results.\n * @property {string} [autopromptString] - The autoprompt string, if applicable.\n * @property {string} [autoDate] - The autoprompt date, if applicable.\n * @property {string} requestId - The request ID for the search.\n */\nexport type SearchResponse<T extends ContentsOptions> = {\n results: SearchResult<T>[];\n autopromptString?: string;\n autoDate?: string;\n requestId: string;\n};\n\n/**\n * Options for the answer endpoint\n * @typedef {Object} AnswerOptions\n * @property {number} [expandedQueriesLimit] - Maximum number of query variations (0-4). Default 1.\n * @property {boolean} [stream] - Whether to stream the response. Default false.\n * @property {boolean} [includeText] - Whether to include text in the source results. Default false.\n */\nexport type AnswerOptions = {\n expandedQueriesLimit?: number;\n stream?: boolean;\n includeText?: boolean;\n};\n\n/**\n * Represents an answer response object from the /answer endpoint.\n * @typedef {Object} AnswerResponse\n * @property {string} answer - The generated answer text.\n * @property {SearchResult<{}>[]]} sources - The sources used to generate the answer.\n * @property {string} [requestId] - Optional request ID for the answer.\n */\nexport type AnswerResponse = {\n answer: string;\n sources: SearchResult<{}>[];\n requestId?: string;\n};\n\n/**\n * Represents a streaming answer response chunk from the /answer endpoint.\n * @typedef {Object} AnswerStreamResponse\n * @property {string} [answer] - A chunk of the generated answer text.\n * @property {SearchResult<{}>[]]} [sources] - The sources used to generate the answer.\n * @property {string} [error] - Error message if something went wrong.\n */\nexport type AnswerStreamResponse = {\n answer?: string;\n sources?: SearchResult<{}>[];\n error?: string;\n};\n\n/**\n * The Exa class encapsulates the API's endpoints.\n */\nclass Exa {\n private baseURL: string;\n private headers: Headers;\n\n private extractContentsOptions<T extends ContentsOptions>(options: T): {\n contentsOptions: ContentsOptions;\n restOptions: Omit<T, keyof ContentsOptions>;\n } {\n const {\n text,\n highlights,\n summary,\n subpages,\n subpageTarget,\n extras,\n livecrawl,\n livecrawlTimeout,\n ...rest\n } = options;\n\n const contentsOptions: ContentsOptions = {};\n // don't send text if it's explicitly false\n if (\n text === undefined &&\n summary === undefined &&\n highlights === undefined &&\n extras === undefined\n )\n contentsOptions.text = true;\n if (text !== undefined) contentsOptions.text = text;\n\n if (summary !== undefined) contentsOptions.summary = summary;\n if (highlights !== undefined) contentsOptions.highlights = highlights;\n\n if (subpages !== undefined) contentsOptions.subpages = subpages;\n if (subpageTarget !== undefined)\n contentsOptions.subpageTarget = subpageTarget;\n\n if (extras !== undefined) contentsOptions.extras = extras;\n if (livecrawl !== undefined) contentsOptions.livecrawl = livecrawl;\n if (livecrawlTimeout !== undefined)\n contentsOptions.livecrawlTimeout = livecrawlTimeout;\n\n return {\n contentsOptions: contentsOptions,\n restOptions: rest as Omit<T, keyof ContentsOptions>,\n };\n }\n\n /**\n * Constructs the Exa API client.\n * @param {string} apiKey - The API key for authentication.\n * @param {string} [baseURL] - The base URL of the Exa API.\n */\n constructor(apiKey?: string, baseURL: string = \"https://api.exa.ai\") {\n this.baseURL = baseURL;\n if (!apiKey) {\n apiKey = process.env.EXASEARCH_API_KEY;\n if (!apiKey) {\n throw new Error(\n \"API key must be provided as an argument or as an environment variable (EXASEARCH_API_KEY)\",\n );\n }\n }\n this.headers = new HeadersImpl({\n \"x-api-key\": apiKey,\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"exa-node 1.4.0\",\n });\n }\n\n /**\n * Makes a request to the Exa API.\n * @param {string} endpoint - The API endpoint to call.\n * @param {string} method - The HTTP method to use.\n * @param {any} [body] - The request body for POST requests.\n * @param {boolean} [stream] - Whether to stream the response.\n * @param {(chunk: AnswerStreamResponse) => void} [onChunk] - Callback for handling stream chunks.\n * @returns {Promise<any>} The response from the API.\n */\n private async request(\n endpoint: string,\n method: string,\n body?: any,\n stream?: boolean,\n onChunk?: (chunk: AnswerStreamResponse) => void,\n ): Promise<any> {\n const response = await fetchImpl(this.baseURL + endpoint, {\n method,\n headers: this.headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n const message = (await response.json()).error;\n throw new Error(\n `Request failed with status ${response.status}. ${message}`,\n );\n }\n\n /**\n * Handle streaming responses from the API. This processes Server-Sent Events (SSE)\n * where data is sent in chunks with the format \"data: {...}\". Each chunk is decoded,\n * parsed as JSON, and passed to the provided callback function.\n */\n if (stream && response.body) {\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n try {\n const data = JSON.parse(line.slice(6));\n onChunk?.(data);\n } catch (e) {\n }\n }\n }\n }\n\n if (buffer && buffer.startsWith('data: ')) {\n try {\n const data = JSON.parse(buffer.slice(6));\n onChunk?.(data);\n } catch (e) {\n }\n }\n } catch (error: any) {\n throw new Error(`Streaming error: ${error?.message || 'Unknown error'}`);\n } finally {\n reader.releaseLock();\n }\n\n return null;\n }\n return await response.json();\n }\n\n /**\n * Performs a search with an Exa prompt-engineered query.\n * @param {string} query - The query string.\n * @param {RegularSearchOptions} [options] - Additional search options.\n * @returns {Promise<SearchResponse<{}>>} A list of relevant search results.\n */\n async search(\n query: string,\n options?: RegularSearchOptions,\n ): Promise<SearchResponse<{}>> {\n return await this.request(\"/search\", \"POST\", { query, ...options });\n }\n\n /**\n * Performs a search with an Exa prompt-engineered query and returns the contents of the documents.\n * @param {string} query - The query string.\n * @param {RegularSearchOptions & T} [options] - Additional search + contents options.\n * @returns {Promise<SearchResponse<T>>} A list of relevant search results.\n */\n async searchAndContents<T extends ContentsOptions>(\n query: string,\n options?: RegularSearchOptions & T,\n ): Promise<SearchResponse<T>> {\n const { contentsOptions, restOptions } =\n options === undefined\n ? { contentsOptions: { text: true }, restOptions: {} }\n : this.extractContentsOptions(options);\n\n return await this.request(\"/search\", \"POST\", {\n query,\n contents: contentsOptions,\n ...restOptions,\n });\n }\n\n /**\n * Finds similar links to the provided URL.\n * @param {string} url - The URL for which to find similar links.\n * @param {FindSimilarOptions} [options] - Additional options for finding similar links.\n * @returns {Promise<SearchResponse<{}>>} A list of similar search results.\n */\n async findSimilar(\n url: string,\n options?: FindSimilarOptions,\n ): Promise<SearchResponse<{}>> {\n return await this.request(\"/findSimilar\", \"POST\", { url, ...options });\n }\n\n /**\n * Finds similar links to the provided URL and returns the contents of the documents.\n * @param {string} url - The URL for which to find similar links.\n * @param {FindSimilarOptions & T} [options] - Additional options for finding similar links + contents.\n * @returns {Promise<SearchResponse<T>>} A list of similar search results.\n */\n async findSimilarAndContents<T extends ContentsOptions>(\n url: string,\n options?: FindSimilarOptions & T,\n ): Promise<SearchResponse<T>> {\n const { contentsOptions, restOptions } =\n options === undefined\n ? { contentsOptions: { text: true }, restOptions: {} }\n : this.extractContentsOptions(options);\n\n return await this.request(\"/findSimilar\", \"POST\", {\n url,\n contents: contentsOptions,\n ...restOptions,\n });\n }\n\n /**\n * Retrieves contents of documents based on URLs\n * @param {string | string[] | SearchResult[]} urls - An array of URLs.\n * @param {ContentsOptions} [options] - Additional options for retrieving document contents.\n * @returns {Promise<SearchResponse<T>>} A list of document contents.\n */\n async getContents<T extends ContentsOptions>(\n urls: string | string[] | SearchResult<T>[],\n options?: T,\n ): Promise<SearchResponse<T>> {\n if (urls.length === 0) {\n throw new Error(\"Must provide at least one URL\");\n }\n let requestUrls: string[];\n if (typeof urls === \"string\") {\n requestUrls = [urls];\n } else if (typeof urls[0] === \"string\") {\n requestUrls = urls as string[];\n } else {\n requestUrls = (urls as SearchResult<T>[]).map((result) => result.url);\n }\n const payload = {\n urls: requestUrls,\n ...options,\n };\n\n return await this.request(`/contents`, \"POST\", payload);\n }\n\n /**\n * Generates an answer to a query using search results as context.\n * @param {string} query - The question or query to answer.\n * @param {AnswerOptions} [options] - Additional options for answer generation.\n * @param {(chunk: AnswerStreamResponse) => void} [onChunk] - Callback for handling stream chunks.\n * @returns {Promise<AnswerResponse | null>} The generated answer and source references, or null if streaming.\n */\n async answer(\n query: string,\n options?: AnswerOptions,\n onChunk?: (chunk: AnswerStreamResponse) => void,\n ): Promise<AnswerResponse | null> {\n const requestBody = {\n query,\n expandedQueriesLimit: options?.expandedQueriesLimit ?? 1,\n stream: options?.stream ?? false,\n includeText: options?.includeText ?? false\n };\n return await this.request(\"/answer\", \"POST\", requestBody, options?.stream, onChunk);\n }\n}\n\nexport default Exa;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAA+B;AAG/B,IAAM,YAAY,OAAO,WAAW,eAAe,OAAO,QAAQ,OAAO,QAAQ,mBAAAA;AACjF,IAAM,cAAc,OAAO,WAAW,eAAe,OAAO,UAAU,OAAO,UAAU;AAyPvF,IAAM,MAAN,MAAU;AAAA,EAIA,uBAAkD,SAGxD;AACA,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IACL,IAAI;AAEJ,UAAM,kBAAmC,CAAC;AAE1C,QACE,SAAS,UACT,YAAY,UACZ,eAAe,UACf,WAAW;AAEX,sBAAgB,OAAO;AACzB,QAAI,SAAS;AAAW,sBAAgB,OAAO;AAE/C,QAAI,YAAY;AAAW,sBAAgB,UAAU;AACrD,QAAI,eAAe;AAAW,sBAAgB,aAAa;AAE3D,QAAI,aAAa;AAAW,sBAAgB,WAAW;AACvD,QAAI,kBAAkB;AACpB,sBAAgB,gBAAgB;AAElC,QAAI,WAAW;AAAW,sBAAgB,SAAS;AACnD,QAAI,cAAc;AAAW,sBAAgB,YAAY;AACzD,QAAI,qBAAqB;AACvB,sBAAgB,mBAAmB;AAErC,WAAO;AAAA,MACL;AAAA,MACA,aAAa;AAAA,IACf;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,QAAiB,UAAkB,sBAAsB;AACnE,SAAK,UAAU;AACf,QAAI,CAAC,QAAQ;AACX,eAAS,QAAQ,IAAI;AACrB,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,SAAK,UAAU,IAAI,YAAY;AAAA,MAC7B,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAc,QACZ,UACA,QACA,MACA,QACA,SACc;AACd,UAAM,WAAW,MAAM,UAAU,KAAK,UAAU,UAAU;AAAA,MACxD;AAAA,MACA,SAAS,KAAK;AAAA,MACd,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,IACtC,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,WAAW,MAAM,SAAS,KAAK,GAAG;AACxC,YAAM,IAAI;AAAA,QACR,8BAA8B,SAAS,WAAW;AAAA,MACpD;AAAA,IACF;AAOA,QAAI,UAAU,SAAS,MAAM;AAC3B,YAAM,SAAS,SAAS,KAAK,UAAU;AACvC,YAAM,UAAU,IAAI,YAAY;AAChC,UAAI,SAAS;AAEb,UAAI;AACF,eAAO,MAAM;AACX,gBAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,cAAI;AAAM;AAEV,oBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAChD,gBAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,mBAAS,MAAM,IAAI,KAAK;AAExB,qBAAW,QAAQ,OAAO;AACxB,gBAAI,KAAK,WAAW,QAAQ,GAAG;AAC7B,kBAAI;AACF,sBAAM,OAAO,KAAK,MAAM,KAAK,MAAM,CAAC,CAAC;AACrC,0BAAU,IAAI;AAAA,cAChB,SAAS,GAAP;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,YAAI,UAAU,OAAO,WAAW,QAAQ,GAAG;AACzC,cAAI;AACF,kBAAM,OAAO,KAAK,MAAM,OAAO,MAAM,CAAC,CAAC;AACvC,sBAAU,IAAI;AAAA,UAChB,SAAS,GAAP;AAAA,UACF;AAAA,QACF;AAAA,MACF,SAAS,OAAP;AACA,cAAM,IAAI,MAAM,oBAAoB,OAAO,WAAW,iBAAiB;AAAA,MACzE,UAAE;AACA,eAAO,YAAY;AAAA,MACrB;AAEA,aAAO;AAAA,IACT;AACA,WAAO,MAAM,SAAS,KAAK;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OACJ,OACA,SAC6B;AAC7B,WAAO,MAAM,KAAK,QAAQ,WAAW,QAAQ,EAAE,OAAO,GAAG,QAAQ,CAAC;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,kBACJ,OACA,SAC4B;AAC5B,UAAM,EAAE,iBAAiB,YAAY,IACnC,YAAY,SACR,EAAE,iBAAiB,EAAE,MAAM,KAAK,GAAG,aAAa,CAAC,EAAE,IACnD,KAAK,uBAAuB,OAAO;AAEzC,WAAO,MAAM,KAAK,QAAQ,WAAW,QAAQ;AAAA,MAC3C;AAAA,MACA,UAAU;AAAA,MACV,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,YACJ,KACA,SAC6B;AAC7B,WAAO,MAAM,KAAK,QAAQ,gBAAgB,QAAQ,EAAE,KAAK,GAAG,QAAQ,CAAC;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,uBACJ,KACA,SAC4B;AAC5B,UAAM,EAAE,iBAAiB,YAAY,IACnC,YAAY,SACR,EAAE,iBAAiB,EAAE,MAAM,KAAK,GAAG,aAAa,CAAC,EAAE,IACnD,KAAK,uBAAuB,OAAO;AAEzC,WAAO,MAAM,KAAK,QAAQ,gBAAgB,QAAQ;AAAA,MAChD;AAAA,MACA,UAAU;AAAA,MACV,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,YACJ,MACA,SAC4B;AAC5B,QAAI,KAAK,WAAW,GAAG;AACrB,YAAM,IAAI,MAAM,+BAA+B;AAAA,IACjD;AACA,QAAI;AACJ,QAAI,OAAO,SAAS,UAAU;AAC5B,oBAAc,CAAC,IAAI;AAAA,IACrB,WAAW,OAAO,KAAK,CAAC,MAAM,UAAU;AACtC,oBAAc;AAAA,IAChB,OAAO;AACL,oBAAe,KAA2B,IAAI,CAAC,WAAW,OAAO,GAAG;AAAA,IACtE;AACA,UAAM,UAAU;AAAA,MACd,MAAM;AAAA,MACN,GAAG;AAAA,IACL;AAEA,WAAO,MAAM,KAAK,QAAQ,aAAa,QAAQ,OAAO;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OACJ,OACA,SACA,SACgC;AAChC,UAAM,cAAc;AAAA,MAClB;AAAA,MACA,sBAAsB,SAAS,wBAAwB;AAAA,MACvD,QAAQ,SAAS,UAAU;AAAA,MAC3B,aAAa,SAAS,eAAe;AAAA,IACvC;AACA,WAAO,MAAM,KAAK,QAAQ,WAAW,QAAQ,aAAa,SAAS,QAAQ,OAAO;AAAA,EACpF;AACF;AAEA,IAAO,cAAQ;","names":["fetch"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import fetch, { Headers } from \"cross-fetch\";\n\n// Use native fetch in Node.js environments\nconst fetchImpl = typeof global !== \"undefined\" && global.fetch ? global.fetch : fetch;\nconst HeadersImpl = typeof global !== \"undefined\" && global.Headers ? global.Headers : Headers;\n\nconst isBeta = false;\n\n/**\n * Search options for performing a search query.\n * @typedef {Object} SearchOptions\n * @property {number} [numResults] - Number of search results to return. Default 10. Max 10 for basic plans.\n * @property {string[]} [includeDomains] - List of domains to include in the search.\n * @property {string[]} [excludeDomains] - List of domains to exclude in the search.\n * @property {string} [startCrawlDate] - Start date for results based on crawl date.\n * @property {string} [endCrawlDate] - End date for results based on crawl date.\n * @property {string} [startPublishedDate] - Start date for results based on published date.\n * @property {string} [endPublishedDate] - End date for results based on published date.\n * @property {string} [category] - A data category to focus on, with higher comprehensivity and data cleanliness. Currently, the only category is company.\n * @property {string[]} [includeText] - List of strings that must be present in webpage text of results. Currently only supports 1 string of up to 5 words.\n * @property {string[]} [excludeText] - List of strings that must not be present in webpage text of results. Currently only supports 1 string of up to 5 words.\n * @property {string[]} [flags] - Experimental flags\n */\nexport type BaseSearchOptions = {\n numResults?: number;\n includeDomains?: string[];\n excludeDomains?: string[];\n startCrawlDate?: string;\n endCrawlDate?: string;\n startPublishedDate?: string;\n endPublishedDate?: string;\n category?:\n | \"company\"\n | \"research paper\"\n | \"news\"\n | \"pdf\"\n | \"github\"\n | \"tweet\"\n | \"personal site\"\n | \"linkedin profile\"\n | \"financial report\";\n includeText?: string[];\n excludeText?: string[];\n flags?: string[];\n};\n\n/**\n * Search options for performing a search query.\n * @typedef {Object} RegularSearchOptions\n */\nexport type RegularSearchOptions = BaseSearchOptions & {\n /**\n * If true, the search results are moderated for safety.\n */\n moderation?: boolean;\n\n useAutoprompt?: boolean;\n type?: \"keyword\" | \"neural\" | \"auto\";\n};\n\n/**\n * Options for finding similar links.\n * @typedef {Object} FindSimilarOptions\n * @property {boolean} [excludeSourceDomain] - If true, excludes links from the base domain of the input.\n */\nexport type FindSimilarOptions = BaseSearchOptions & {\n excludeSourceDomain?: boolean;\n};\n\nexport type ExtrasOptions = { links?: number; imageLinks?: number };\n\n/**\n * Search options for performing a search query.\n * @typedef {Object} ContentsOptions\n * @property {TextContentsOptions | boolean} [text] - Options for retrieving text contents.\n * @property {HighlightsContentsOptions | boolean} [highlights] - Options for retrieving highlights.\n * @property {SummaryContentsOptions | boolean} [summary] - Options for retrieving summary.\n * @property {LivecrawlOptions} [livecrawl] - Options for livecrawling contents. Default is \"never\" for neural/auto search, \"fallback\" for keyword search.\n * @property {number} [livecrawlTimeout] - The timeout for livecrawling. Max and default is 10000ms.\n * @property {boolean} [filterEmptyResults] - If true, filters out results with no contents. Default is true.\n * @property {number} [subpages] - The number of subpages to return for each result, where each subpage is derived from an internal link for the result.\n * @property {string | string[]} [subpageTarget] - Text used to match/rank subpages in the returned subpage list. You could use \"about\" to get *about* page for websites. Note that this is a fuzzy matcher.\n * @property {ExtrasOptions} [extras] - Miscelleneous data derived from results\n */\nexport type ContentsOptions = {\n text?: TextContentsOptions | true;\n highlights?: HighlightsContentsOptions | true;\n summary?: SummaryContentsOptions | true;\n livecrawl?: LivecrawlOptions;\n livecrawlTimeout?: number;\n filterEmptyResults?: boolean;\n subpages?: number;\n subpageTarget?: string | string[];\n extras?: ExtrasOptions;\n} & (typeof isBeta extends true ? {} : {});\n\n/**\n * Options for livecrawling contents\n * @typedef {string} LivecrawlOptions\n */\nexport type LivecrawlOptions = \"never\" | \"fallback\" | \"always\" | \"auto\";\n\n/**\n * Options for retrieving text from page.\n * @typedef {Object} TextContentsOptions\n * @property {number} [maxCharacters] - The maximum number of characters to return.\n * @property {boolean} [includeHtmlTags] - If true, includes HTML tags in the returned text. Default: false\n */\nexport type TextContentsOptions = {\n maxCharacters?: number;\n includeHtmlTags?: boolean;\n};\n\n/**\n * Options for retrieving highlights from page.\n * @typedef {Object} HighlightsContentsOptions\n * @property {string} [query] - The query string to use for highlights search.\n * @property {number} [numSentences] - The number of sentences to return for each highlight.\n * @property {number} [highlightsPerUrl] - The number of highlights to return for each URL.\n */\nexport type HighlightsContentsOptions = {\n query?: string;\n numSentences?: number;\n highlightsPerUrl?: number;\n};\n\n/**\n * Options for retrieving summary from page.\n * @typedef {Object} SummaryContentsOptions\n * @property {string} [query] - The query string to use for summary generation.\n */\nexport type SummaryContentsOptions = {\n query?: string;\n};\n\n/**\n * @typedef {Object} TextResponse\n * @property {string} text - Text from page\n */\nexport type TextResponse = { text: string };\n\n/**\n * @typedef {Object} HighlightsResponse\n * @property {string[]} highlights - The highlights as an array of strings.\n * @property {number[]} highlightScores - The corresponding scores as an array of floats, 0 to 1\n */\nexport type HighlightsResponse = {\n highlights: string[];\n highlightScores: number[];\n};\n\n/**\n * @typedef {Object} SummaryResponse\n * @property {string} summary - The generated summary of the page content.\n */\nexport type SummaryResponse = { summary: string };\n\n/**\n * @typedef {Object} ExtrasResponse\n * @property {string[]} links - The links on the page of a result\n * @property {string[]} imageLinks - The image links on the page of a result\n */\nexport type ExtrasResponse = { extras: { links?: string[]; imageLinks?: string[] } };\n\n/**\n * @typedef {Object} SubpagesResponse\n * @property {ContentsResultComponent<T extends ContentsOptions>} subpages - The subpages for a result\n */\nexport type SubpagesResponse<T extends ContentsOptions> = {\n subpages: ContentsResultComponent<T>[];\n};\n\nexport type Default<T extends {}, U> = [keyof T] extends [never] ? U : T;\n\n/**\n * @typedef {Object} ContentsResultComponent\n * Depending on 'ContentsOptions', this yields a combination of 'TextResponse', 'HighlightsResponse', 'SummaryResponse', or an empty object.\n *\n * @template T - A type extending from 'ContentsOptions'.\n */\nexport type ContentsResultComponent<T extends ContentsOptions> = Default<\n (T[\"text\"] extends object | true ? TextResponse : {}) &\n (T[\"highlights\"] extends object | true ? HighlightsResponse : {}) &\n (T[\"summary\"] extends object | true ? SummaryResponse : {}) &\n (T[\"subpages\"] extends number ? SubpagesResponse<T> : {}) &\n (T[\"extras\"] extends object ? ExtrasResponse : {}),\n TextResponse\n>;\n\n/**\n * Represents a search result object.\n * @typedef {Object} SearchResult\n * @property {string} title - The title of the search result.\n * @property {string} url - The URL of the search result.\n * @property {string} [publishedDate] - The estimated creation date of the content.\n * @property {string} [author] - The author of the content, if available.\n * @property {number} [score] - Similarity score between the query/url and the result.\n * @property {string} id - The temporary ID for the document.\n * @property {string} [image] - A representative image for the content, if any.\n * @property {string} [favicon] - A favicon for the site, if any.\n */\nexport type SearchResult<T extends ContentsOptions> = {\n title: string | null;\n url: string;\n publishedDate?: string;\n author?: string;\n score?: number;\n id: string;\n image?: string;\n favicon?: string;\n} & ContentsResultComponent<T>;\n\n/**\n * Represents a search response object.\n * @typedef {Object} SearchResponse\n * @property {Result[]} results - The list of search results.\n * @property {string} [autopromptString] - The autoprompt string, if applicable.\n * @property {string} [autoDate] - The autoprompt date, if applicable.\n * @property {string} requestId - The request ID for the search.\n */\nexport type SearchResponse<T extends ContentsOptions> = {\n results: SearchResult<T>[];\n autopromptString?: string;\n autoDate?: string;\n requestId: string;\n};\n\n/**\n * Options for the answer endpoint\n * @typedef {Object} AnswerOptions\n * @property {number} [expandedQueriesLimit] - Maximum number of query variations (0-4). Default 1.\n * @property {boolean} [stream] - Whether to stream the response. Default false.\n * @property {boolean} [includeText] - Whether to include text in the source results. Default false.\n */\nexport type AnswerOptions = {\n expandedQueriesLimit?: number;\n stream?: boolean;\n includeText?: boolean;\n};\n\n/**\n * Represents an answer response object from the /answer endpoint.\n * @typedef {Object} AnswerResponse\n * @property {string} answer - The generated answer text.\n * @property {SearchResult<{}>[]} sources - The sources used to generate the answer.\n * @property {string} [requestId] - Optional request ID for the answer.\n */\nexport type AnswerResponse = {\n answer: string;\n sources: SearchResult<{}>[];\n requestId?: string;\n};\n\n/**\n * Represents a streaming answer response chunk from the /answer endpoint.\n * @typedef {Object} AnswerStreamResponse\n * @property {string} [answer] - A chunk of the generated answer text.\n * @property {SearchResult<{}>[]]} [sources] - The sources used to generate the answer.\n * @property {string} [error] - Error message if something went wrong.\n */\nexport type AnswerStreamResponse = {\n answer?: string;\n sources?: SearchResult<{}>[];\n error?: string;\n};\n\n/**\n * The Exa class encapsulates the API's endpoints.\n */\nclass Exa {\n private baseURL: string;\n private headers: Headers;\n\n /**\n * Helper method to separate out the contents-specific options from the rest.\n */\n private extractContentsOptions<T extends ContentsOptions>(options: T): {\n contentsOptions: ContentsOptions;\n restOptions: Omit<T, keyof ContentsOptions>;\n } {\n const {\n text,\n highlights,\n summary,\n subpages,\n subpageTarget,\n extras,\n livecrawl,\n livecrawlTimeout,\n ...rest\n } = options;\n\n const contentsOptions: ContentsOptions = {};\n\n // Default: if none of text, summary, or highlights is provided, we retrieve text\n if (\n text === undefined &&\n summary === undefined &&\n highlights === undefined &&\n extras === undefined\n ) {\n contentsOptions.text = true;\n }\n\n if (text !== undefined) contentsOptions.text = text;\n if (summary !== undefined) contentsOptions.summary = summary;\n if (highlights !== undefined) contentsOptions.highlights = highlights;\n if (subpages !== undefined) contentsOptions.subpages = subpages;\n if (subpageTarget !== undefined) contentsOptions.subpageTarget = subpageTarget;\n if (extras !== undefined) contentsOptions.extras = extras;\n if (livecrawl !== undefined) contentsOptions.livecrawl = livecrawl;\n if (livecrawlTimeout !== undefined) contentsOptions.livecrawlTimeout = livecrawlTimeout;\n\n return {\n contentsOptions,\n restOptions: rest as Omit<T, keyof ContentsOptions>,\n };\n }\n\n /**\n * Constructs the Exa API client.\n * @param {string} apiKey - The API key for authentication.\n * @param {string} [baseURL] - The base URL of the Exa API.\n */\n constructor(apiKey?: string, baseURL: string = \"https://api.exa.ai\") {\n this.baseURL = baseURL;\n if (!apiKey) {\n apiKey = process.env.EXASEARCH_API_KEY;\n if (!apiKey) {\n throw new Error(\n \"API key must be provided as an argument or as an environment variable (EXASEARCH_API_KEY)\",\n );\n }\n }\n this.headers = new HeadersImpl({\n \"x-api-key\": apiKey,\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"exa-node 1.4.0\",\n });\n }\n\n /**\n * Makes a request to the Exa API.\n * @param {string} endpoint - The API endpoint to call.\n * @param {string} method - The HTTP method to use.\n * @param {any} [body] - The request body for POST requests.\n * @param {boolean} [stream] - Whether to stream the response.\n * @param {(chunk: AnswerStreamResponse) => void} [onChunk] - Callback for handling stream chunks.\n * @returns {Promise<any>} The response from the API.\n */\n private async request(\n endpoint: string,\n method: string,\n body?: any,\n stream?: boolean,\n onChunk?: (chunk: AnswerStreamResponse) => void,\n ): Promise<any> {\n const response = await fetchImpl(this.baseURL + endpoint, {\n method,\n headers: this.headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n const message = (await response.json()).error;\n throw new Error(\n `Request failed with status ${response.status}. ${message}`,\n );\n }\n\n // Streaming logic if `stream` is true\n if (stream && response.body) {\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n try {\n const data = JSON.parse(line.slice(6));\n onChunk?.(data);\n } catch (e) {\n // Could not parse JSON, ignore\n }\n }\n }\n }\n\n if (buffer && buffer.startsWith('data: ')) {\n try {\n const data = JSON.parse(buffer.slice(6));\n onChunk?.(data);\n } catch (e) {\n // Could not parse JSON, ignore\n }\n }\n } catch (error: any) {\n throw new Error(`Streaming error: ${error?.message || 'Unknown error'}`);\n } finally {\n reader.releaseLock();\n }\n\n return null;\n }\n\n return await response.json();\n }\n\n /**\n * Performs a search with an Exa prompt-engineered query.\n * \n * @param {string} query - The query string.\n * @param {RegularSearchOptions} [options] - Additional search options\n * @returns {Promise<SearchResponse<{}>>} A list of relevant search results.\n */\n async search(\n query: string,\n options?: RegularSearchOptions,\n ): Promise<SearchResponse<{}>> {\n return await this.request(\"/search\", \"POST\", { query, ...options });\n }\n\n /**\n * Performs a search with an Exa prompt-engineered query and returns the contents of the documents.\n * \n * @param {string} query - The query string.\n * @param {RegularSearchOptions & T} [options] - Additional search + contents options\n * @returns {Promise<SearchResponse<T>>} A list of relevant search results with requested contents.\n */\n async searchAndContents<T extends ContentsOptions>(\n query: string,\n options?: RegularSearchOptions & T,\n ): Promise<SearchResponse<T>> {\n const { contentsOptions, restOptions } =\n options === undefined\n ? { contentsOptions: { text: true }, restOptions: {} }\n : this.extractContentsOptions(options);\n\n return await this.request(\"/search\", \"POST\", {\n query,\n contents: contentsOptions,\n ...restOptions,\n });\n }\n\n /**\n * Finds similar links to the provided URL.\n * @param {string} url - The URL for which to find similar links.\n * @param {FindSimilarOptions} [options] - Additional options for finding similar links.\n * @returns {Promise<SearchResponse<{}>>} A list of similar search results.\n */\n async findSimilar(\n url: string,\n options?: FindSimilarOptions,\n ): Promise<SearchResponse<{}>> {\n return await this.request(\"/findSimilar\", \"POST\", { url, ...options });\n }\n\n /**\n * Finds similar links to the provided URL and returns the contents of the documents.\n * @param {string} url - The URL for which to find similar links.\n * @param {FindSimilarOptions & T} [options] - Additional options for finding similar links + contents.\n * @returns {Promise<SearchResponse<T>>} A list of similar search results, including requested contents.\n */\n async findSimilarAndContents<T extends ContentsOptions>(\n url: string,\n options?: FindSimilarOptions & T,\n ): Promise<SearchResponse<T>> {\n const { contentsOptions, restOptions } =\n options === undefined\n ? { contentsOptions: { text: true }, restOptions: {} }\n : this.extractContentsOptions(options);\n\n return await this.request(\"/findSimilar\", \"POST\", {\n url,\n contents: contentsOptions,\n ...restOptions,\n });\n }\n\n /**\n * Retrieves contents of documents based on URLs.\n * @param {string | string[] | SearchResult[]} urls - A URL or array of URLs, or an array of SearchResult objects.\n * @param {ContentsOptions} [options] - Additional options for retrieving document contents.\n * @returns {Promise<SearchResponse<T>>} A list of document contents for the requested URLs.\n */\n async getContents<T extends ContentsOptions>(\n urls: string | string[] | SearchResult<T>[],\n options?: T,\n ): Promise<SearchResponse<T>> {\n if (!urls || (Array.isArray(urls) && urls.length === 0)) {\n throw new Error(\"Must provide at least one URL\");\n }\n\n let requestUrls: string[];\n\n if (typeof urls === \"string\") {\n requestUrls = [urls];\n } else if (typeof urls[0] === \"string\") {\n requestUrls = urls as string[];\n } else {\n requestUrls = (urls as SearchResult<T>[]).map((result) => result.url);\n }\n\n const payload = {\n urls: requestUrls,\n ...options,\n };\n\n return await this.request(\"/contents\", \"POST\", payload);\n }\n\n /**\n * Generates an answer to a query using search results as context.\n * @param {string} query - The question or query to answer.\n * @param {AnswerOptions} [options] - Additional options for answer generation.\n * @param {(chunk: AnswerStreamResponse) => void} [onChunk] - Callback for handling stream chunks (if streaming).\n * @returns {Promise<AnswerResponse | null>} The generated answer and source references, or null if streaming.\n */\n async answer(\n query: string,\n options?: AnswerOptions,\n onChunk?: (chunk: AnswerStreamResponse) => void,\n ): Promise<AnswerResponse | null> {\n const requestBody = {\n query,\n expandedQueriesLimit: options?.expandedQueriesLimit ?? 1,\n stream: options?.stream ?? false,\n includeText: options?.includeText ?? false\n };\n\n return await this.request(\"/answer\", \"POST\", requestBody, options?.stream, onChunk);\n }\n}\n\nexport default Exa;\n"],"mappings":"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","names":["fetch"]}
package/dist/index.mjs CHANGED
@@ -3,6 +3,9 @@ import fetch, { Headers } from "cross-fetch";
3
3
  var fetchImpl = typeof global !== "undefined" && global.fetch ? global.fetch : fetch;
4
4
  var HeadersImpl = typeof global !== "undefined" && global.Headers ? global.Headers : Headers;
5
5
  var Exa = class {
6
+ /**
7
+ * Helper method to separate out the contents-specific options from the rest.
8
+ */
6
9
  extractContentsOptions(options) {
7
10
  const {
8
11
  text,
@@ -16,8 +19,9 @@ var Exa = class {
16
19
  ...rest
17
20
  } = options;
18
21
  const contentsOptions = {};
19
- if (text === void 0 && summary === void 0 && highlights === void 0 && extras === void 0)
22
+ if (text === void 0 && summary === void 0 && highlights === void 0 && extras === void 0) {
20
23
  contentsOptions.text = true;
24
+ }
21
25
  if (text !== void 0)
22
26
  contentsOptions.text = text;
23
27
  if (summary !== void 0)
@@ -121,8 +125,9 @@ var Exa = class {
121
125
  }
122
126
  /**
123
127
  * Performs a search with an Exa prompt-engineered query.
128
+ *
124
129
  * @param {string} query - The query string.
125
- * @param {RegularSearchOptions} [options] - Additional search options.
130
+ * @param {RegularSearchOptions} [options] - Additional search options
126
131
  * @returns {Promise<SearchResponse<{}>>} A list of relevant search results.
127
132
  */
128
133
  async search(query, options) {
@@ -130,9 +135,10 @@ var Exa = class {
130
135
  }
131
136
  /**
132
137
  * Performs a search with an Exa prompt-engineered query and returns the contents of the documents.
138
+ *
133
139
  * @param {string} query - The query string.
134
- * @param {RegularSearchOptions & T} [options] - Additional search + contents options.
135
- * @returns {Promise<SearchResponse<T>>} A list of relevant search results.
140
+ * @param {RegularSearchOptions & T} [options] - Additional search + contents options
141
+ * @returns {Promise<SearchResponse<T>>} A list of relevant search results with requested contents.
136
142
  */
137
143
  async searchAndContents(query, options) {
138
144
  const { contentsOptions, restOptions } = options === void 0 ? { contentsOptions: { text: true }, restOptions: {} } : this.extractContentsOptions(options);
@@ -155,7 +161,7 @@ var Exa = class {
155
161
  * Finds similar links to the provided URL and returns the contents of the documents.
156
162
  * @param {string} url - The URL for which to find similar links.
157
163
  * @param {FindSimilarOptions & T} [options] - Additional options for finding similar links + contents.
158
- * @returns {Promise<SearchResponse<T>>} A list of similar search results.
164
+ * @returns {Promise<SearchResponse<T>>} A list of similar search results, including requested contents.
159
165
  */
160
166
  async findSimilarAndContents(url, options) {
161
167
  const { contentsOptions, restOptions } = options === void 0 ? { contentsOptions: { text: true }, restOptions: {} } : this.extractContentsOptions(options);
@@ -166,13 +172,13 @@ var Exa = class {
166
172
  });
167
173
  }
168
174
  /**
169
- * Retrieves contents of documents based on URLs
170
- * @param {string | string[] | SearchResult[]} urls - An array of URLs.
175
+ * Retrieves contents of documents based on URLs.
176
+ * @param {string | string[] | SearchResult[]} urls - A URL or array of URLs, or an array of SearchResult objects.
171
177
  * @param {ContentsOptions} [options] - Additional options for retrieving document contents.
172
- * @returns {Promise<SearchResponse<T>>} A list of document contents.
178
+ * @returns {Promise<SearchResponse<T>>} A list of document contents for the requested URLs.
173
179
  */
174
180
  async getContents(urls, options) {
175
- if (urls.length === 0) {
181
+ if (!urls || Array.isArray(urls) && urls.length === 0) {
176
182
  throw new Error("Must provide at least one URL");
177
183
  }
178
184
  let requestUrls;
@@ -187,13 +193,13 @@ var Exa = class {
187
193
  urls: requestUrls,
188
194
  ...options
189
195
  };
190
- return await this.request(`/contents`, "POST", payload);
196
+ return await this.request("/contents", "POST", payload);
191
197
  }
192
198
  /**
193
199
  * Generates an answer to a query using search results as context.
194
200
  * @param {string} query - The question or query to answer.
195
201
  * @param {AnswerOptions} [options] - Additional options for answer generation.
196
- * @param {(chunk: AnswerStreamResponse) => void} [onChunk] - Callback for handling stream chunks.
202
+ * @param {(chunk: AnswerStreamResponse) => void} [onChunk] - Callback for handling stream chunks (if streaming).
197
203
  * @returns {Promise<AnswerResponse | null>} The generated answer and source references, or null if streaming.
198
204
  */
199
205
  async answer(query, options, onChunk) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import fetch, { Headers } from \"cross-fetch\";\n\n// Use native fetch in Node.js environments\nconst fetchImpl = typeof global !== \"undefined\" && global.fetch ? global.fetch : fetch;\nconst HeadersImpl = typeof global !== \"undefined\" && global.Headers ? global.Headers : Headers;\n\nconst isBeta = false;\n\n/**\n * Search options for performing a search query.\n * @typedef {Object} SearchOptions\n * @property {number} [numResults] - Number of search results to return. Default 10. Max 10 for basic plans.\n * @property {string[]} [includeDomains] - List of domains to include in the search.\n * @property {string[]} [excludeDomains] - List of domains to exclude in the search.\n * @property {string} [startCrawlDate] - Start date for results based on crawl date.\n * @property {string} [endCrawlDate] - End date for results based on crawl date.\n * @property {string} [startPublishedDate] - Start date for results based on published date.\n * @property {string} [endPublishedDate] - End date for results based on published date.\n * @property {string} [category] - A data category to focus on, with higher comprehensivity and data cleanliness. Currently, the only category is company.\n * @property {string[]} [includeText] - List of strings that must be present in webpage text of results. Currently only supports 1 string of up to 5 words.\n * @property {string[]} [excludeText] - List of strings that must not be present in webpage text of results. Currently only supports 1 string of up to 5 words.\n * @property {string[]} [flags] - Experimental flags\n */\nexport type BaseSearchOptions = {\n numResults?: number;\n includeDomains?: string[];\n excludeDomains?: string[];\n startCrawlDate?: string;\n endCrawlDate?: string;\n startPublishedDate?: string;\n endPublishedDate?: string;\n category?: \"company\" | \"research paper\" | \"news\" | \"pdf\" | \"github\" | \"tweet\" | \"personal site\" | \"linkedin profile\" | \"financial report\";\n includeText?: string[];\n excludeText?: string[];\n flags?: string[];\n};\n\n/**\n * Search options for performing a search query.\n * @typedef {Object} RegularSearchOptions\n */\nexport type RegularSearchOptions = BaseSearchOptions & {\n useAutoprompt?: boolean;\n type?: \"keyword\" | \"neural\" | \"auto\";\n};\n\n/**\n * Options for finding similar links.\n * @typedef {Object} FindSimilarOptions\n * @property {boolean} [excludeSourceDomain] - If true, excludes links from the base domain of the input.\n */\nexport type FindSimilarOptions = BaseSearchOptions & {\n excludeSourceDomain?: boolean;\n};\n\nexport type ExtrasOptions = { links?: number; imageLinks?: number };\n\n/**\n * Search options for performing a search query.\n * @typedef {Object} ContentsOptions\n * @property {TextContentsOptions | boolean} [text] - Options for retrieving text contents.\n * @property {HighlightsContentsOptions | boolean} [highlights] - Options for retrieving highlights.\n * @property {SummaryContentsOptions | boolean} [summary] - Options for retrieving summary.\n * @property {LivecrawlOptions} [livecrawl] - Options for livecrawling contents. Default is \"never\" for neural/auto search, \"fallback\" for keyword search.\n * @property {number} [livecrawlTimeout] - The timeout for livecrawling. Max and default is 10000ms.\n * @property {boolean} [filterEmptyResults] - If true, filters out results with no contents. Default is true.\n * @property {number} [subpages] - The number of subpages to return for each result, where each subpage is derived from an internal link for the result.\n * @property {string | string[]} [subpageTarget] - Text used to match/rank subpages in the returned subpage list. You could use \"about\" to get *about* page for websites. Note that this is a fuzzy matcher.\n * @property {ExtrasOptions} [extras] - Miscelleneous data for derived from results\n */\nexport type ContentsOptions = {\n text?: TextContentsOptions | true;\n highlights?: HighlightsContentsOptions | true;\n summary?: SummaryContentsOptions | true;\n livecrawl?: LivecrawlOptions;\n livecrawlTimeout?: number;\n filterEmptyResults?: boolean;\n subpages?: number;\n subpageTarget?: string | string[];\n extras?: ExtrasOptions;\n} & (typeof isBeta extends true ? {} : {});\n\n/**\n * Options for livecrawling contents\n * @typedef {string} LivecrawlOptions\n */\nexport type LivecrawlOptions = \"never\" | \"fallback\" | \"always\" | \"auto\";\n\n/**\n * Options for retrieving text from page.\n * @typedef {Object} TextContentsOptions\n * @property {number} [maxCharacters] - The maximum number of characters to return.\n * @property {boolean} [includeHtmlTags] - If true, includes HTML tags in the returned text. Default: false\n */\nexport type TextContentsOptions = {\n maxCharacters?: number;\n includeHtmlTags?: boolean;\n};\n\n/**\n * Options for retrieving highlights from page.\n * @typedef {Object} HighlightsContentsOptions\n * @property {string} [query] - The query string to use for highlights search.\n * @property {number} [numSentences] - The number of sentences to return for each highlight.\n * @property {number} [highlightsPerUrl] - The number of highlights to return for each URL.\n */\nexport type HighlightsContentsOptions = {\n query?: string;\n numSentences?: number;\n highlightsPerUrl?: number;\n};\n\n/**\n * Options for retrieving summary from page.\n * @typedef {Object} SummaryContentsOptions\n * @property {string} [query] - The query string to use for summary generation.\n */\nexport type SummaryContentsOptions = {\n query?: string;\n};\n\n/**\n * @typedef {Object} TextResponse\n * @property {string} text - Text from page\n */\nexport type TextResponse = { text: string };\n\n/**\n * @typedef {Object} HighlightsResponse\n * @property {string[]} highlights - The highlights as an array of strings.\n * @property {number[]} highlightScores - The corresponding scores as an array of floats, 0 to 1\n */\nexport type HighlightsResponse = {\n highlights: string[];\n highlightScores: number[];\n};\n\n/**\n * @typedef {Object} SummaryResponse\n * @property {string} summary - The generated summary of the page content.\n */\nexport type SummaryResponse = { summary: string };\n\n/**\n * @typedef {Object} ExtrasResponse\n * @property {string[]} links - The links on the page of a result\n * @property {string[]} imageLinks - The image links on the page of a result\n */\nexport type ExtrasResponse = { extras: { links?: string[]; imageLinks?: string[] } };\n\n/**\n * @typedef {Object} SubpagesResponse\n * @property {ContentsResultComponent<T extends ContentsOptions>} subpages - The links on the page of a result\n */\nexport type SubpagesResponse<T extends ContentsOptions> = {\n subpages: ContentsResultComponent<T>[];\n};\n\nexport type Default<T extends {}, U> = [keyof T] extends [never] ? U : T;\n\n/**\n * @typedef {Object} ContentsResultComponent\n * Depending on 'ContentsOptions', this yields a combination of 'TextResponse', 'HighlightsResponse', 'SummaryResponse', or an empty object.\n *\n * @template T - A type extending from 'ContentsOptions'.\n */\nexport type ContentsResultComponent<T extends ContentsOptions> = Default<\n (T[\"text\"] extends object | true ? TextResponse : {}) &\n (T[\"highlights\"] extends object | true ? HighlightsResponse : {}) &\n (T[\"summary\"] extends object | true ? SummaryResponse : {}) &\n (T[\"subpages\"] extends number ? SubpagesResponse<T> : {}) &\n (T[\"extras\"] extends object ? ExtrasResponse : {}),\n TextResponse\n>;\n\n/**\n * Represents a search result object.\n * @typedef {Object} SearchResult\n * @property {string} title - The title of the search result.\n * @property {string} url - The URL of the search result.\n * @property {string} [publishedDate] - The estimated creation date of the content.\n * @property {string} [author] - The author of the content, if available.\n * @property {number} [score] - Similarity score between the query/url and the result.\n * @property {string} id - The temporary ID for the document.\n */\nexport type SearchResult<T extends ContentsOptions> = {\n title: string | null;\n url: string;\n publishedDate?: string;\n author?: string;\n score?: number;\n id: string;\n image?: string;\n favicon?: string;\n} & ContentsResultComponent<T>;\n\n/**\n * Represents a search response object.\n * @typedef {Object} SearchResponse\n * @property {Result[]} results - The list of search results.\n * @property {string} [autopromptString] - The autoprompt string, if applicable.\n * @property {string} [autoDate] - The autoprompt date, if applicable.\n * @property {string} requestId - The request ID for the search.\n */\nexport type SearchResponse<T extends ContentsOptions> = {\n results: SearchResult<T>[];\n autopromptString?: string;\n autoDate?: string;\n requestId: string;\n};\n\n/**\n * Options for the answer endpoint\n * @typedef {Object} AnswerOptions\n * @property {number} [expandedQueriesLimit] - Maximum number of query variations (0-4). Default 1.\n * @property {boolean} [stream] - Whether to stream the response. Default false.\n * @property {boolean} [includeText] - Whether to include text in the source results. Default false.\n */\nexport type AnswerOptions = {\n expandedQueriesLimit?: number;\n stream?: boolean;\n includeText?: boolean;\n};\n\n/**\n * Represents an answer response object from the /answer endpoint.\n * @typedef {Object} AnswerResponse\n * @property {string} answer - The generated answer text.\n * @property {SearchResult<{}>[]]} sources - The sources used to generate the answer.\n * @property {string} [requestId] - Optional request ID for the answer.\n */\nexport type AnswerResponse = {\n answer: string;\n sources: SearchResult<{}>[];\n requestId?: string;\n};\n\n/**\n * Represents a streaming answer response chunk from the /answer endpoint.\n * @typedef {Object} AnswerStreamResponse\n * @property {string} [answer] - A chunk of the generated answer text.\n * @property {SearchResult<{}>[]]} [sources] - The sources used to generate the answer.\n * @property {string} [error] - Error message if something went wrong.\n */\nexport type AnswerStreamResponse = {\n answer?: string;\n sources?: SearchResult<{}>[];\n error?: string;\n};\n\n/**\n * The Exa class encapsulates the API's endpoints.\n */\nclass Exa {\n private baseURL: string;\n private headers: Headers;\n\n private extractContentsOptions<T extends ContentsOptions>(options: T): {\n contentsOptions: ContentsOptions;\n restOptions: Omit<T, keyof ContentsOptions>;\n } {\n const {\n text,\n highlights,\n summary,\n subpages,\n subpageTarget,\n extras,\n livecrawl,\n livecrawlTimeout,\n ...rest\n } = options;\n\n const contentsOptions: ContentsOptions = {};\n // don't send text if it's explicitly false\n if (\n text === undefined &&\n summary === undefined &&\n highlights === undefined &&\n extras === undefined\n )\n contentsOptions.text = true;\n if (text !== undefined) contentsOptions.text = text;\n\n if (summary !== undefined) contentsOptions.summary = summary;\n if (highlights !== undefined) contentsOptions.highlights = highlights;\n\n if (subpages !== undefined) contentsOptions.subpages = subpages;\n if (subpageTarget !== undefined)\n contentsOptions.subpageTarget = subpageTarget;\n\n if (extras !== undefined) contentsOptions.extras = extras;\n if (livecrawl !== undefined) contentsOptions.livecrawl = livecrawl;\n if (livecrawlTimeout !== undefined)\n contentsOptions.livecrawlTimeout = livecrawlTimeout;\n\n return {\n contentsOptions: contentsOptions,\n restOptions: rest as Omit<T, keyof ContentsOptions>,\n };\n }\n\n /**\n * Constructs the Exa API client.\n * @param {string} apiKey - The API key for authentication.\n * @param {string} [baseURL] - The base URL of the Exa API.\n */\n constructor(apiKey?: string, baseURL: string = \"https://api.exa.ai\") {\n this.baseURL = baseURL;\n if (!apiKey) {\n apiKey = process.env.EXASEARCH_API_KEY;\n if (!apiKey) {\n throw new Error(\n \"API key must be provided as an argument or as an environment variable (EXASEARCH_API_KEY)\",\n );\n }\n }\n this.headers = new HeadersImpl({\n \"x-api-key\": apiKey,\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"exa-node 1.4.0\",\n });\n }\n\n /**\n * Makes a request to the Exa API.\n * @param {string} endpoint - The API endpoint to call.\n * @param {string} method - The HTTP method to use.\n * @param {any} [body] - The request body for POST requests.\n * @param {boolean} [stream] - Whether to stream the response.\n * @param {(chunk: AnswerStreamResponse) => void} [onChunk] - Callback for handling stream chunks.\n * @returns {Promise<any>} The response from the API.\n */\n private async request(\n endpoint: string,\n method: string,\n body?: any,\n stream?: boolean,\n onChunk?: (chunk: AnswerStreamResponse) => void,\n ): Promise<any> {\n const response = await fetchImpl(this.baseURL + endpoint, {\n method,\n headers: this.headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n const message = (await response.json()).error;\n throw new Error(\n `Request failed with status ${response.status}. ${message}`,\n );\n }\n\n /**\n * Handle streaming responses from the API. This processes Server-Sent Events (SSE)\n * where data is sent in chunks with the format \"data: {...}\". Each chunk is decoded,\n * parsed as JSON, and passed to the provided callback function.\n */\n if (stream && response.body) {\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n try {\n const data = JSON.parse(line.slice(6));\n onChunk?.(data);\n } catch (e) {\n }\n }\n }\n }\n\n if (buffer && buffer.startsWith('data: ')) {\n try {\n const data = JSON.parse(buffer.slice(6));\n onChunk?.(data);\n } catch (e) {\n }\n }\n } catch (error: any) {\n throw new Error(`Streaming error: ${error?.message || 'Unknown error'}`);\n } finally {\n reader.releaseLock();\n }\n\n return null;\n }\n return await response.json();\n }\n\n /**\n * Performs a search with an Exa prompt-engineered query.\n * @param {string} query - The query string.\n * @param {RegularSearchOptions} [options] - Additional search options.\n * @returns {Promise<SearchResponse<{}>>} A list of relevant search results.\n */\n async search(\n query: string,\n options?: RegularSearchOptions,\n ): Promise<SearchResponse<{}>> {\n return await this.request(\"/search\", \"POST\", { query, ...options });\n }\n\n /**\n * Performs a search with an Exa prompt-engineered query and returns the contents of the documents.\n * @param {string} query - The query string.\n * @param {RegularSearchOptions & T} [options] - Additional search + contents options.\n * @returns {Promise<SearchResponse<T>>} A list of relevant search results.\n */\n async searchAndContents<T extends ContentsOptions>(\n query: string,\n options?: RegularSearchOptions & T,\n ): Promise<SearchResponse<T>> {\n const { contentsOptions, restOptions } =\n options === undefined\n ? { contentsOptions: { text: true }, restOptions: {} }\n : this.extractContentsOptions(options);\n\n return await this.request(\"/search\", \"POST\", {\n query,\n contents: contentsOptions,\n ...restOptions,\n });\n }\n\n /**\n * Finds similar links to the provided URL.\n * @param {string} url - The URL for which to find similar links.\n * @param {FindSimilarOptions} [options] - Additional options for finding similar links.\n * @returns {Promise<SearchResponse<{}>>} A list of similar search results.\n */\n async findSimilar(\n url: string,\n options?: FindSimilarOptions,\n ): Promise<SearchResponse<{}>> {\n return await this.request(\"/findSimilar\", \"POST\", { url, ...options });\n }\n\n /**\n * Finds similar links to the provided URL and returns the contents of the documents.\n * @param {string} url - The URL for which to find similar links.\n * @param {FindSimilarOptions & T} [options] - Additional options for finding similar links + contents.\n * @returns {Promise<SearchResponse<T>>} A list of similar search results.\n */\n async findSimilarAndContents<T extends ContentsOptions>(\n url: string,\n options?: FindSimilarOptions & T,\n ): Promise<SearchResponse<T>> {\n const { contentsOptions, restOptions } =\n options === undefined\n ? { contentsOptions: { text: true }, restOptions: {} }\n : this.extractContentsOptions(options);\n\n return await this.request(\"/findSimilar\", \"POST\", {\n url,\n contents: contentsOptions,\n ...restOptions,\n });\n }\n\n /**\n * Retrieves contents of documents based on URLs\n * @param {string | string[] | SearchResult[]} urls - An array of URLs.\n * @param {ContentsOptions} [options] - Additional options for retrieving document contents.\n * @returns {Promise<SearchResponse<T>>} A list of document contents.\n */\n async getContents<T extends ContentsOptions>(\n urls: string | string[] | SearchResult<T>[],\n options?: T,\n ): Promise<SearchResponse<T>> {\n if (urls.length === 0) {\n throw new Error(\"Must provide at least one URL\");\n }\n let requestUrls: string[];\n if (typeof urls === \"string\") {\n requestUrls = [urls];\n } else if (typeof urls[0] === \"string\") {\n requestUrls = urls as string[];\n } else {\n requestUrls = (urls as SearchResult<T>[]).map((result) => result.url);\n }\n const payload = {\n urls: requestUrls,\n ...options,\n };\n\n return await this.request(`/contents`, \"POST\", payload);\n }\n\n /**\n * Generates an answer to a query using search results as context.\n * @param {string} query - The question or query to answer.\n * @param {AnswerOptions} [options] - Additional options for answer generation.\n * @param {(chunk: AnswerStreamResponse) => void} [onChunk] - Callback for handling stream chunks.\n * @returns {Promise<AnswerResponse | null>} The generated answer and source references, or null if streaming.\n */\n async answer(\n query: string,\n options?: AnswerOptions,\n onChunk?: (chunk: AnswerStreamResponse) => void,\n ): Promise<AnswerResponse | null> {\n const requestBody = {\n query,\n expandedQueriesLimit: options?.expandedQueriesLimit ?? 1,\n stream: options?.stream ?? false,\n includeText: options?.includeText ?? false\n };\n return await this.request(\"/answer\", \"POST\", requestBody, options?.stream, onChunk);\n }\n}\n\nexport default Exa;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import fetch, { Headers } from \"cross-fetch\";\n\n// Use native fetch in Node.js environments\nconst fetchImpl = typeof global !== \"undefined\" && global.fetch ? global.fetch : fetch;\nconst HeadersImpl = typeof global !== \"undefined\" && global.Headers ? global.Headers : Headers;\n\nconst isBeta = false;\n\n/**\n * Search options for performing a search query.\n * @typedef {Object} SearchOptions\n * @property {number} [numResults] - Number of search results to return. Default 10. Max 10 for basic plans.\n * @property {string[]} [includeDomains] - List of domains to include in the search.\n * @property {string[]} [excludeDomains] - List of domains to exclude in the search.\n * @property {string} [startCrawlDate] - Start date for results based on crawl date.\n * @property {string} [endCrawlDate] - End date for results based on crawl date.\n * @property {string} [startPublishedDate] - Start date for results based on published date.\n * @property {string} [endPublishedDate] - End date for results based on published date.\n * @property {string} [category] - A data category to focus on, with higher comprehensivity and data cleanliness. Currently, the only category is company.\n * @property {string[]} [includeText] - List of strings that must be present in webpage text of results. Currently only supports 1 string of up to 5 words.\n * @property {string[]} [excludeText] - List of strings that must not be present in webpage text of results. Currently only supports 1 string of up to 5 words.\n * @property {string[]} [flags] - Experimental flags\n */\nexport type BaseSearchOptions = {\n numResults?: number;\n includeDomains?: string[];\n excludeDomains?: string[];\n startCrawlDate?: string;\n endCrawlDate?: string;\n startPublishedDate?: string;\n endPublishedDate?: string;\n category?:\n | \"company\"\n | \"research paper\"\n | \"news\"\n | \"pdf\"\n | \"github\"\n | \"tweet\"\n | \"personal site\"\n | \"linkedin profile\"\n | \"financial report\";\n includeText?: string[];\n excludeText?: string[];\n flags?: string[];\n};\n\n/**\n * Search options for performing a search query.\n * @typedef {Object} RegularSearchOptions\n */\nexport type RegularSearchOptions = BaseSearchOptions & {\n /**\n * If true, the search results are moderated for safety.\n */\n moderation?: boolean;\n\n useAutoprompt?: boolean;\n type?: \"keyword\" | \"neural\" | \"auto\";\n};\n\n/**\n * Options for finding similar links.\n * @typedef {Object} FindSimilarOptions\n * @property {boolean} [excludeSourceDomain] - If true, excludes links from the base domain of the input.\n */\nexport type FindSimilarOptions = BaseSearchOptions & {\n excludeSourceDomain?: boolean;\n};\n\nexport type ExtrasOptions = { links?: number; imageLinks?: number };\n\n/**\n * Search options for performing a search query.\n * @typedef {Object} ContentsOptions\n * @property {TextContentsOptions | boolean} [text] - Options for retrieving text contents.\n * @property {HighlightsContentsOptions | boolean} [highlights] - Options for retrieving highlights.\n * @property {SummaryContentsOptions | boolean} [summary] - Options for retrieving summary.\n * @property {LivecrawlOptions} [livecrawl] - Options for livecrawling contents. Default is \"never\" for neural/auto search, \"fallback\" for keyword search.\n * @property {number} [livecrawlTimeout] - The timeout for livecrawling. Max and default is 10000ms.\n * @property {boolean} [filterEmptyResults] - If true, filters out results with no contents. Default is true.\n * @property {number} [subpages] - The number of subpages to return for each result, where each subpage is derived from an internal link for the result.\n * @property {string | string[]} [subpageTarget] - Text used to match/rank subpages in the returned subpage list. You could use \"about\" to get *about* page for websites. Note that this is a fuzzy matcher.\n * @property {ExtrasOptions} [extras] - Miscelleneous data derived from results\n */\nexport type ContentsOptions = {\n text?: TextContentsOptions | true;\n highlights?: HighlightsContentsOptions | true;\n summary?: SummaryContentsOptions | true;\n livecrawl?: LivecrawlOptions;\n livecrawlTimeout?: number;\n filterEmptyResults?: boolean;\n subpages?: number;\n subpageTarget?: string | string[];\n extras?: ExtrasOptions;\n} & (typeof isBeta extends true ? {} : {});\n\n/**\n * Options for livecrawling contents\n * @typedef {string} LivecrawlOptions\n */\nexport type LivecrawlOptions = \"never\" | \"fallback\" | \"always\" | \"auto\";\n\n/**\n * Options for retrieving text from page.\n * @typedef {Object} TextContentsOptions\n * @property {number} [maxCharacters] - The maximum number of characters to return.\n * @property {boolean} [includeHtmlTags] - If true, includes HTML tags in the returned text. Default: false\n */\nexport type TextContentsOptions = {\n maxCharacters?: number;\n includeHtmlTags?: boolean;\n};\n\n/**\n * Options for retrieving highlights from page.\n * @typedef {Object} HighlightsContentsOptions\n * @property {string} [query] - The query string to use for highlights search.\n * @property {number} [numSentences] - The number of sentences to return for each highlight.\n * @property {number} [highlightsPerUrl] - The number of highlights to return for each URL.\n */\nexport type HighlightsContentsOptions = {\n query?: string;\n numSentences?: number;\n highlightsPerUrl?: number;\n};\n\n/**\n * Options for retrieving summary from page.\n * @typedef {Object} SummaryContentsOptions\n * @property {string} [query] - The query string to use for summary generation.\n */\nexport type SummaryContentsOptions = {\n query?: string;\n};\n\n/**\n * @typedef {Object} TextResponse\n * @property {string} text - Text from page\n */\nexport type TextResponse = { text: string };\n\n/**\n * @typedef {Object} HighlightsResponse\n * @property {string[]} highlights - The highlights as an array of strings.\n * @property {number[]} highlightScores - The corresponding scores as an array of floats, 0 to 1\n */\nexport type HighlightsResponse = {\n highlights: string[];\n highlightScores: number[];\n};\n\n/**\n * @typedef {Object} SummaryResponse\n * @property {string} summary - The generated summary of the page content.\n */\nexport type SummaryResponse = { summary: string };\n\n/**\n * @typedef {Object} ExtrasResponse\n * @property {string[]} links - The links on the page of a result\n * @property {string[]} imageLinks - The image links on the page of a result\n */\nexport type ExtrasResponse = { extras: { links?: string[]; imageLinks?: string[] } };\n\n/**\n * @typedef {Object} SubpagesResponse\n * @property {ContentsResultComponent<T extends ContentsOptions>} subpages - The subpages for a result\n */\nexport type SubpagesResponse<T extends ContentsOptions> = {\n subpages: ContentsResultComponent<T>[];\n};\n\nexport type Default<T extends {}, U> = [keyof T] extends [never] ? U : T;\n\n/**\n * @typedef {Object} ContentsResultComponent\n * Depending on 'ContentsOptions', this yields a combination of 'TextResponse', 'HighlightsResponse', 'SummaryResponse', or an empty object.\n *\n * @template T - A type extending from 'ContentsOptions'.\n */\nexport type ContentsResultComponent<T extends ContentsOptions> = Default<\n (T[\"text\"] extends object | true ? TextResponse : {}) &\n (T[\"highlights\"] extends object | true ? HighlightsResponse : {}) &\n (T[\"summary\"] extends object | true ? SummaryResponse : {}) &\n (T[\"subpages\"] extends number ? SubpagesResponse<T> : {}) &\n (T[\"extras\"] extends object ? ExtrasResponse : {}),\n TextResponse\n>;\n\n/**\n * Represents a search result object.\n * @typedef {Object} SearchResult\n * @property {string} title - The title of the search result.\n * @property {string} url - The URL of the search result.\n * @property {string} [publishedDate] - The estimated creation date of the content.\n * @property {string} [author] - The author of the content, if available.\n * @property {number} [score] - Similarity score between the query/url and the result.\n * @property {string} id - The temporary ID for the document.\n * @property {string} [image] - A representative image for the content, if any.\n * @property {string} [favicon] - A favicon for the site, if any.\n */\nexport type SearchResult<T extends ContentsOptions> = {\n title: string | null;\n url: string;\n publishedDate?: string;\n author?: string;\n score?: number;\n id: string;\n image?: string;\n favicon?: string;\n} & ContentsResultComponent<T>;\n\n/**\n * Represents a search response object.\n * @typedef {Object} SearchResponse\n * @property {Result[]} results - The list of search results.\n * @property {string} [autopromptString] - The autoprompt string, if applicable.\n * @property {string} [autoDate] - The autoprompt date, if applicable.\n * @property {string} requestId - The request ID for the search.\n */\nexport type SearchResponse<T extends ContentsOptions> = {\n results: SearchResult<T>[];\n autopromptString?: string;\n autoDate?: string;\n requestId: string;\n};\n\n/**\n * Options for the answer endpoint\n * @typedef {Object} AnswerOptions\n * @property {number} [expandedQueriesLimit] - Maximum number of query variations (0-4). Default 1.\n * @property {boolean} [stream] - Whether to stream the response. Default false.\n * @property {boolean} [includeText] - Whether to include text in the source results. Default false.\n */\nexport type AnswerOptions = {\n expandedQueriesLimit?: number;\n stream?: boolean;\n includeText?: boolean;\n};\n\n/**\n * Represents an answer response object from the /answer endpoint.\n * @typedef {Object} AnswerResponse\n * @property {string} answer - The generated answer text.\n * @property {SearchResult<{}>[]} sources - The sources used to generate the answer.\n * @property {string} [requestId] - Optional request ID for the answer.\n */\nexport type AnswerResponse = {\n answer: string;\n sources: SearchResult<{}>[];\n requestId?: string;\n};\n\n/**\n * Represents a streaming answer response chunk from the /answer endpoint.\n * @typedef {Object} AnswerStreamResponse\n * @property {string} [answer] - A chunk of the generated answer text.\n * @property {SearchResult<{}>[]]} [sources] - The sources used to generate the answer.\n * @property {string} [error] - Error message if something went wrong.\n */\nexport type AnswerStreamResponse = {\n answer?: string;\n sources?: SearchResult<{}>[];\n error?: string;\n};\n\n/**\n * The Exa class encapsulates the API's endpoints.\n */\nclass Exa {\n private baseURL: string;\n private headers: Headers;\n\n /**\n * Helper method to separate out the contents-specific options from the rest.\n */\n private extractContentsOptions<T extends ContentsOptions>(options: T): {\n contentsOptions: ContentsOptions;\n restOptions: Omit<T, keyof ContentsOptions>;\n } {\n const {\n text,\n highlights,\n summary,\n subpages,\n subpageTarget,\n extras,\n livecrawl,\n livecrawlTimeout,\n ...rest\n } = options;\n\n const contentsOptions: ContentsOptions = {};\n\n // Default: if none of text, summary, or highlights is provided, we retrieve text\n if (\n text === undefined &&\n summary === undefined &&\n highlights === undefined &&\n extras === undefined\n ) {\n contentsOptions.text = true;\n }\n\n if (text !== undefined) contentsOptions.text = text;\n if (summary !== undefined) contentsOptions.summary = summary;\n if (highlights !== undefined) contentsOptions.highlights = highlights;\n if (subpages !== undefined) contentsOptions.subpages = subpages;\n if (subpageTarget !== undefined) contentsOptions.subpageTarget = subpageTarget;\n if (extras !== undefined) contentsOptions.extras = extras;\n if (livecrawl !== undefined) contentsOptions.livecrawl = livecrawl;\n if (livecrawlTimeout !== undefined) contentsOptions.livecrawlTimeout = livecrawlTimeout;\n\n return {\n contentsOptions,\n restOptions: rest as Omit<T, keyof ContentsOptions>,\n };\n }\n\n /**\n * Constructs the Exa API client.\n * @param {string} apiKey - The API key for authentication.\n * @param {string} [baseURL] - The base URL of the Exa API.\n */\n constructor(apiKey?: string, baseURL: string = \"https://api.exa.ai\") {\n this.baseURL = baseURL;\n if (!apiKey) {\n apiKey = process.env.EXASEARCH_API_KEY;\n if (!apiKey) {\n throw new Error(\n \"API key must be provided as an argument or as an environment variable (EXASEARCH_API_KEY)\",\n );\n }\n }\n this.headers = new HeadersImpl({\n \"x-api-key\": apiKey,\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"exa-node 1.4.0\",\n });\n }\n\n /**\n * Makes a request to the Exa API.\n * @param {string} endpoint - The API endpoint to call.\n * @param {string} method - The HTTP method to use.\n * @param {any} [body] - The request body for POST requests.\n * @param {boolean} [stream] - Whether to stream the response.\n * @param {(chunk: AnswerStreamResponse) => void} [onChunk] - Callback for handling stream chunks.\n * @returns {Promise<any>} The response from the API.\n */\n private async request(\n endpoint: string,\n method: string,\n body?: any,\n stream?: boolean,\n onChunk?: (chunk: AnswerStreamResponse) => void,\n ): Promise<any> {\n const response = await fetchImpl(this.baseURL + endpoint, {\n method,\n headers: this.headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n const message = (await response.json()).error;\n throw new Error(\n `Request failed with status ${response.status}. ${message}`,\n );\n }\n\n // Streaming logic if `stream` is true\n if (stream && response.body) {\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n try {\n const data = JSON.parse(line.slice(6));\n onChunk?.(data);\n } catch (e) {\n // Could not parse JSON, ignore\n }\n }\n }\n }\n\n if (buffer && buffer.startsWith('data: ')) {\n try {\n const data = JSON.parse(buffer.slice(6));\n onChunk?.(data);\n } catch (e) {\n // Could not parse JSON, ignore\n }\n }\n } catch (error: any) {\n throw new Error(`Streaming error: ${error?.message || 'Unknown error'}`);\n } finally {\n reader.releaseLock();\n }\n\n return null;\n }\n\n return await response.json();\n }\n\n /**\n * Performs a search with an Exa prompt-engineered query.\n * \n * @param {string} query - The query string.\n * @param {RegularSearchOptions} [options] - Additional search options\n * @returns {Promise<SearchResponse<{}>>} A list of relevant search results.\n */\n async search(\n query: string,\n options?: RegularSearchOptions,\n ): Promise<SearchResponse<{}>> {\n return await this.request(\"/search\", \"POST\", { query, ...options });\n }\n\n /**\n * Performs a search with an Exa prompt-engineered query and returns the contents of the documents.\n * \n * @param {string} query - The query string.\n * @param {RegularSearchOptions & T} [options] - Additional search + contents options\n * @returns {Promise<SearchResponse<T>>} A list of relevant search results with requested contents.\n */\n async searchAndContents<T extends ContentsOptions>(\n query: string,\n options?: RegularSearchOptions & T,\n ): Promise<SearchResponse<T>> {\n const { contentsOptions, restOptions } =\n options === undefined\n ? { contentsOptions: { text: true }, restOptions: {} }\n : this.extractContentsOptions(options);\n\n return await this.request(\"/search\", \"POST\", {\n query,\n contents: contentsOptions,\n ...restOptions,\n });\n }\n\n /**\n * Finds similar links to the provided URL.\n * @param {string} url - The URL for which to find similar links.\n * @param {FindSimilarOptions} [options] - Additional options for finding similar links.\n * @returns {Promise<SearchResponse<{}>>} A list of similar search results.\n */\n async findSimilar(\n url: string,\n options?: FindSimilarOptions,\n ): Promise<SearchResponse<{}>> {\n return await this.request(\"/findSimilar\", \"POST\", { url, ...options });\n }\n\n /**\n * Finds similar links to the provided URL and returns the contents of the documents.\n * @param {string} url - The URL for which to find similar links.\n * @param {FindSimilarOptions & T} [options] - Additional options for finding similar links + contents.\n * @returns {Promise<SearchResponse<T>>} A list of similar search results, including requested contents.\n */\n async findSimilarAndContents<T extends ContentsOptions>(\n url: string,\n options?: FindSimilarOptions & T,\n ): Promise<SearchResponse<T>> {\n const { contentsOptions, restOptions } =\n options === undefined\n ? { contentsOptions: { text: true }, restOptions: {} }\n : this.extractContentsOptions(options);\n\n return await this.request(\"/findSimilar\", \"POST\", {\n url,\n contents: contentsOptions,\n ...restOptions,\n });\n }\n\n /**\n * Retrieves contents of documents based on URLs.\n * @param {string | string[] | SearchResult[]} urls - A URL or array of URLs, or an array of SearchResult objects.\n * @param {ContentsOptions} [options] - Additional options for retrieving document contents.\n * @returns {Promise<SearchResponse<T>>} A list of document contents for the requested URLs.\n */\n async getContents<T extends ContentsOptions>(\n urls: string | string[] | SearchResult<T>[],\n options?: T,\n ): Promise<SearchResponse<T>> {\n if (!urls || (Array.isArray(urls) && urls.length === 0)) {\n throw new Error(\"Must provide at least one URL\");\n }\n\n let requestUrls: string[];\n\n if (typeof urls === \"string\") {\n requestUrls = [urls];\n } else if (typeof urls[0] === \"string\") {\n requestUrls = urls as string[];\n } else {\n requestUrls = (urls as SearchResult<T>[]).map((result) => result.url);\n }\n\n const payload = {\n urls: requestUrls,\n ...options,\n };\n\n return await this.request(\"/contents\", \"POST\", payload);\n }\n\n /**\n * Generates an answer to a query using search results as context.\n * @param {string} query - The question or query to answer.\n * @param {AnswerOptions} [options] - Additional options for answer generation.\n * @param {(chunk: AnswerStreamResponse) => void} [onChunk] - Callback for handling stream chunks (if streaming).\n * @returns {Promise<AnswerResponse | null>} The generated answer and source references, or null if streaming.\n */\n async answer(\n query: string,\n options?: AnswerOptions,\n onChunk?: (chunk: AnswerStreamResponse) => void,\n ): Promise<AnswerResponse | null> {\n const requestBody = {\n query,\n expandedQueriesLimit: options?.expandedQueriesLimit ?? 1,\n stream: options?.stream ?? false,\n includeText: options?.includeText ?? false\n };\n\n return await this.request(\"/answer\", \"POST\", requestBody, options?.stream, onChunk);\n }\n}\n\nexport default Exa;\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "exa-js",
3
- "version": "1.4.6",
3
+ "version": "1.4.8",
4
4
  "description": "Exa SDK for Node.js and the browser",
5
5
  "publishConfig": {
6
6
  "access": "public"