UNPKG

exa-js

Version:

Exa SDK for Node.js and the browser

1,722 lines (1,704 loc) 77.3 kB
// src/index.ts import fetch2, { Headers } from "cross-fetch"; // package.json var package_default = { name: "exa-js", version: "2.16.0", description: "Exa SDK for Node.js and the browser", publishConfig: { access: "public" }, files: [ "dist" ], main: "./dist/index.js", module: "./dist/index.mjs", exports: { ".": { types: "./dist/index.d.ts", require: "./dist/index.js", module: "./dist/index.mjs", import: "./dist/index.mjs" }, "./package.json": "./package.json" }, types: "./dist/index.d.ts", scripts: { "build-fast": "tsup src/index.ts --format cjs,esm", build: "tsup", test: "vitest run", "test:unit": "vitest run --config vitest.unit.config.ts", "test:integration": "vitest run --config vitest.integration.config.ts", typecheck: "tsc --noEmit", "typecheck:examples": "tsc -p examples/tsconfig.json --noEmit", "generate:types:websets": "openapi-typescript https://raw.githubusercontent.com/exa-labs/openapi-spec/refs/heads/master/exa-websets-spec.yaml --enum --root-types --alphabetize --root-types-no-schema-prefix --output ./src/websets/openapi.ts && npm run format:websets", format: 'prettier --write "src/**/*.ts" "examples/**/*.ts"', "format:websets": "prettier --write src/websets/openapi.ts", "generate-docs": "npx tsx scripts/generate-docs.ts", "build:beta": "cross-env NPM_CONFIG_TAG=beta npm run build", "version:beta": "npm version prerelease --preid=beta", "version:stable": "npm version patch", "publish:beta": "npm run version:beta && npm run build:beta && npm publish --tag beta", "publish:stable": "npm run version:stable && npm run build && npm publish", prepublishOnly: "npm run build" }, license: "MIT", devDependencies: { "@types/node": "~22.14.0", "cross-env": "~7.0.3", "openapi-typescript": "~7.6.1", prettier: "~3.5.3", "ts-morph": "^27.0.2", "ts-node": "~10.9.2", tsup: "~8.4.0", tsx: "^4.21.0", typescript: "~5.8.3", vitest: "~3.1.1" }, dependencies: { "cross-fetch": "~4.1.0", dotenv: "~16.4.7", openai: "^5.0.1", zod: "^3.22.0", "zod-to-json-schema": "^3.20.0" }, directories: { test: "test" }, repository: { type: "git", url: "git+https://github.com/exa-labs/exa-js.git" }, keywords: [ "exa", "metaphor", "search", "AI", "LLMs", "RAG", "retrieval", "augmented", "generation" ], author: "jeffzwang", bugs: { url: "https://github.com/exa-labs/exa-js/issues" }, homepage: "https://github.com/exa-labs/exa-js#readme" }; // src/errors.ts var HttpStatusCode = /* @__PURE__ */ ((HttpStatusCode2) => { HttpStatusCode2[HttpStatusCode2["BadRequest"] = 400] = "BadRequest"; HttpStatusCode2[HttpStatusCode2["NotFound"] = 404] = "NotFound"; HttpStatusCode2[HttpStatusCode2["Unauthorized"] = 401] = "Unauthorized"; HttpStatusCode2[HttpStatusCode2["Forbidden"] = 403] = "Forbidden"; HttpStatusCode2[HttpStatusCode2["TooManyRequests"] = 429] = "TooManyRequests"; HttpStatusCode2[HttpStatusCode2["RequestTimeout"] = 408] = "RequestTimeout"; HttpStatusCode2[HttpStatusCode2["InternalServerError"] = 500] = "InternalServerError"; HttpStatusCode2[HttpStatusCode2["ServiceUnavailable"] = 503] = "ServiceUnavailable"; return HttpStatusCode2; })(HttpStatusCode || {}); var ExaError = class extends Error { /** * Create a new ExaError * @param message Error message * @param statusCode HTTP status code * @param timestamp ISO timestamp from API * @param path Path that caused the error */ constructor(message, statusCode, timestamp, path) { super(message); this.name = "ExaError"; this.statusCode = statusCode; this.timestamp = timestamp ?? (/* @__PURE__ */ new Date()).toISOString(); this.path = path; } }; // src/zod-utils.ts import { ZodType } from "zod"; import { zodToJsonSchema as convertZodToJsonSchema } from "zod-to-json-schema"; function isZodSchema(obj) { return obj instanceof ZodType; } function zodToJsonSchema(schema) { return convertZodToJsonSchema(schema, { $refStrategy: "none" }); } // src/agent/base.ts var AgentBaseClient = class { constructor(client) { this.client = client; } async request(endpoint, method = "POST", data, params, headers) { return this.client.request( `/agent/runs${endpoint}`, method, data, params, headers ); } async rawRequest(endpoint, method = "POST", data, params, headers) { return this.client.rawRequest( `/agent/runs${endpoint}`, method, data, params, headers ); } buildPaginationParams(pagination) { const params = {}; if (!pagination) return params; if (pagination.cursor) params.cursor = pagination.cursor; if (pagination.limit) params.limit = pagination.limit; return params; } }; // src/agent/client.ts var DEFAULT_AGENT_POLL_INTERVAL_MS = 1e3; var DEFAULT_AGENT_POLL_TIMEOUT_MS = 60 * 60 * 1e3; var DEFAULT_AGENT_CREATE_AND_WAIT_TIMEOUT_MS = 2 * 60 * 1e3; var TERMINAL_AGENT_RUN_STATUSES = /* @__PURE__ */ new Set([ "completed", "failed", "cancelled" ]); var AgentRunFailedError = class extends Error { constructor(run) { super(run.error?.message ?? `Agent run ${run.id} failed`); this.name = "AgentRunFailedError"; this.run = run; } }; var AgentRunCancelledError = class extends Error { constructor(run) { super(`Agent run ${run.id} was cancelled`); this.name = "AgentRunCancelledError"; this.run = run; } }; function headersForBetas(betas) { const betaValues = betas?.filter(Boolean); if (!betaValues?.length) return void 0; return { "Exa-Beta": betaValues.join(",") }; } function isTerminalAgentRunStatus(status) { return TERMINAL_AGENT_RUN_STATUSES.has(status); } function ensureCompletedRun(run) { if (run.status === "failed") { throw new AgentRunFailedError(run); } if (run.status === "cancelled") { throw new AgentRunCancelledError(run); } return run; } function createAndWaitPollOptions(options) { return { pollInterval: options?.pollInterval ?? DEFAULT_AGENT_POLL_INTERVAL_MS, timeoutMs: options?.timeoutMs ?? DEFAULT_AGENT_CREATE_AND_WAIT_TIMEOUT_MS }; } function buildAgentRunPayload(params) { const { stream, outputSchema, ...rest } = params; let schema = outputSchema; if (schema && isZodSchema(schema)) { schema = zodToJsonSchema(schema); } const payload = { ...rest }; if (schema) { payload.outputSchema = schema; } return { stream, payload }; } async function* streamAgentEvents(response) { if (!response.body) { throw new Error("No response body for SSE stream"); } const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ""; let doneReading = false; const processPart = (part) => { const event = {}; const dataLines = []; for (const line of part.split("\n")) { if (!line || !line.includes(":")) continue; const [field, ...rest] = line.split(":"); const value = rest.join(":").replace(/^ /, ""); if (field === "id") event.id = value; if (field === "event") event.event = value; if (field === "data") dataLines.push(value); } if (!event.event || dataLines.length === 0) return null; try { event.data = JSON.parse(dataLines.join("\n")); } catch { event.data = { value: dataLines.join("\n") }; } return event; }; try { while (true) { const { done, value } = await reader.read(); if (done) { doneReading = true; break; } buffer += decoder.decode(value, { stream: true }); const parts = buffer.split("\n\n"); buffer = parts.pop() ?? ""; for (const part of parts) { const event = processPart(part); if (event) yield event; } } if (buffer.trim()) { const event = processPart(buffer.trim()); if (event) yield event; } } finally { if (!doneReading) { await reader.cancel(); } reader.releaseLock(); } } var AgentRunEventsClient = class extends AgentBaseClient { /** * List stored events for an Agent run. */ async list(runId, options) { const params = this.buildPaginationParams(options); return this.request( `/${runId}/events`, "GET", void 0, params ); } }; var AgentRunsClient = class extends AgentBaseClient { constructor(client) { super(client); this.events = new AgentRunEventsClient(client); } async create(params) { const { stream, payload } = buildAgentRunPayload(params); if (stream) { const response = await this.rawRequest("", "POST", payload, void 0, { Accept: "text/event-stream" }); if (!response.ok) { const message = await response.text(); throw new ExaError( message || `Request failed with status code ${response.status}`, response.status, (/* @__PURE__ */ new Date()).toISOString(), "/agent/runs" ); } return streamAgentEvents(response); } return this.request("", "POST", payload); } /** * Get an Agent run by ID. */ async get(runId) { return this.request(`/${runId}`, "GET"); } /** * List Agent runs. */ async list(options) { const params = this.buildPaginationParams(options); return this.request("", "GET", void 0, params); } /** * Iterate through all Agent runs, handling pagination automatically. */ async *listAll(options) { let cursor = void 0; const pageOptions = options ? { ...options } : {}; while (true) { pageOptions.cursor = cursor; const response = await this.list(pageOptions); for (const run of response.data) { yield run; } if (!response.hasMore || !response.nextCursor) { break; } cursor = response.nextCursor; } } /** * Collect all Agent runs into an array. */ async getAll(options) { const runs = []; for await (const run of this.listAll(options)) { runs.push(run); } return runs; } /** * Cancel a queued or running Agent run. */ async cancel(runId) { return this.request(`/${runId}/cancel`, "POST"); } /** * Delete a stored Agent run. */ async delete(runId) { return this.request(`/${runId}`, "DELETE"); } /** * Poll an Agent run until it reaches a terminal status. */ async pollUntilFinished(runId, options) { const pollInterval = options?.pollInterval ?? DEFAULT_AGENT_POLL_INTERVAL_MS; const timeoutMs = options?.timeoutMs ?? DEFAULT_AGENT_POLL_TIMEOUT_MS; const startTime = Date.now(); while (true) { const run = await this.get(runId); if (isTerminalAgentRunStatus(run.status)) { return run; } if (Date.now() - startTime > timeoutMs) { throw new Error( `Polling timeout: Agent run ${runId} did not complete within ${timeoutMs}ms` ); } await new Promise((resolve) => setTimeout(resolve, pollInterval)); } } async createAndWait(params, options) { const { stream: _stream, ...createParams } = params; const run = await this.create( createParams ); const runId = run.id; const terminalRun = await this.pollUntilFinished( runId, createAndWaitPollOptions(options) ); return ensureCompletedRun(terminalRun); } }; var AgentClient = class { constructor(client) { this.client = client; this.runs = new AgentRunsClient(client); } }; var AgentBetaRunEventsClient = class extends AgentRunEventsClient { /** * List stored events for an Agent run. * * @deprecated Use exa.agent.runs.events instead. */ async list(runId, options) { const { betas, ...pagination } = options ?? {}; const params = this.buildPaginationParams(pagination); return this.request( `/${runId}/events`, "GET", void 0, params, headersForBetas(betas) ); } }; var AgentBetaRunsClient = class extends AgentRunsClient { constructor(client) { super(client); this.events = new AgentBetaRunEventsClient(client); } async create(params) { const { betas, ...createParams } = params; const { stream, payload } = buildAgentRunPayload( createParams ); const headers = headersForBetas(betas); if (stream) { const response = await this.rawRequest("", "POST", payload, void 0, { ...headers, Accept: "text/event-stream" }); if (!response.ok) { const message = await response.text(); throw new ExaError( message || `Request failed with status code ${response.status}`, response.status, (/* @__PURE__ */ new Date()).toISOString(), "/agent/runs" ); } return streamAgentEvents(response); } return this.request( "", "POST", payload, void 0, headers ); } async get(runId, options) { return this.request( `/${runId}`, "GET", void 0, void 0, headersForBetas(options?.betas) ); } async list(options) { const { betas, ...pagination } = options ?? {}; const params = this.buildPaginationParams(pagination); return this.request( "", "GET", void 0, params, headersForBetas(betas) ); } async *listAll(options) { let cursor = void 0; const { betas, ...pagination } = options ?? {}; const pageOptions = { ...pagination }; while (true) { pageOptions.cursor = cursor; const response = await this.list({ ...pageOptions, betas }); for (const run of response.data) { yield run; } if (!response.hasMore || !response.nextCursor) { break; } cursor = response.nextCursor; } } async getAll(options) { const runs = []; for await (const run of this.listAll(options)) { runs.push(run); } return runs; } async cancel(runId, options) { return this.request( `/${runId}/cancel`, "POST", void 0, void 0, headersForBetas(options?.betas) ); } async delete(runId, options) { return this.request( `/${runId}`, "DELETE", void 0, void 0, headersForBetas(options?.betas) ); } async pollUntilFinished(runId, options) { const pollInterval = options?.pollInterval ?? DEFAULT_AGENT_POLL_INTERVAL_MS; const timeoutMs = options?.timeoutMs ?? DEFAULT_AGENT_POLL_TIMEOUT_MS; const startTime = Date.now(); const headers = headersForBetas(options?.betas); while (true) { const run = await this.request( `/${runId}`, "GET", void 0, void 0, headers ); if (isTerminalAgentRunStatus(run.status)) { return run; } if (Date.now() - startTime > timeoutMs) { throw new Error( `Polling timeout: Agent run ${runId} did not complete within ${timeoutMs}ms` ); } await new Promise((resolve) => setTimeout(resolve, pollInterval)); } } async createAndWait(params, options) { const { betas, stream: _stream, ...createParams } = params; const run = await this.create({ ...createParams, betas }); const runId = run.id; const terminalRun = await this.pollUntilFinished(runId, { ...createAndWaitPollOptions(options), betas }); return ensureCompletedRun(terminalRun); } }; var AgentBetaClient = class extends AgentClient { constructor(clientOrAgent) { const client = clientOrAgent instanceof AgentClient ? clientOrAgent.client : clientOrAgent; super(client); this.runs = new AgentBetaRunsClient(client); } }; var BetaClient = class { constructor(clientOrAgent) { this.agent = new AgentBetaClient(clientOrAgent); } }; // src/monitors/base.ts var SearchMonitorsBaseClient = class { constructor(client) { this.client = client; } async request(endpoint, method = "POST", data, params) { return this.client.request( `/monitors${endpoint}`, method, data, params ); } buildPaginationParams(pagination) { const params = {}; if (!pagination) return params; if (pagination.cursor) params.cursor = pagination.cursor; if (pagination.limit) params.limit = pagination.limit; if ("status" in pagination && pagination.status) params.status = pagination.status; return params; } }; // src/monitors/client.ts var SearchMonitorRunsClient = class extends SearchMonitorsBaseClient { /** * List all runs for a Search Monitor * @param monitorId The ID of the Search Monitor * @param options Pagination options * @returns The list of Search Monitor runs */ async list(monitorId, options) { const params = this.buildPaginationParams(options); return this.request( `/${monitorId}/runs`, "GET", void 0, params ); } /** * Get a specific Search Monitor run * @param monitorId The ID of the Search Monitor * @param runId The ID of the run * @returns The Search Monitor run */ async get(monitorId, runId) { return this.request( `/${monitorId}/runs/${runId}`, "GET" ); } /** * Iterate through all runs for a Search Monitor, handling pagination automatically * @param monitorId The ID of the Search Monitor * @param options Pagination options * @returns Async generator of Search Monitor runs */ async *listAll(monitorId, options) { let cursor = void 0; const pageOptions = options ? { ...options } : {}; while (true) { pageOptions.cursor = cursor; const response = await this.list(monitorId, pageOptions); for (const run of response.data) { yield run; } if (!response.hasMore || !response.nextCursor) { break; } cursor = response.nextCursor; } } /** * Collect all runs for a Search Monitor into an array * @param monitorId The ID of the Search Monitor * @param options Pagination options * @returns Promise resolving to an array of all Search Monitor runs */ async getAll(monitorId, options) { const runs = []; for await (const run of this.listAll(monitorId, options)) { runs.push(run); } return runs; } }; var SearchMonitorsClient = class extends SearchMonitorsBaseClient { constructor(client) { super(client); this.runs = new SearchMonitorRunsClient(client); } /** * Create a Search Monitor * @param params The monitor creation parameters * @returns The created Search Monitor with webhookSecret */ async create(params) { return this.request("", "POST", params); } /** * Get a Search Monitor by ID * @param id The ID of the Search Monitor * @returns The Search Monitor */ async get(id) { return this.request(`/${id}`, "GET"); } /** * List Search Monitors * @param options Pagination and filtering options * @returns The list of Search Monitors */ async list(options) { const params = this.buildPaginationParams(options); return this.request( "", "GET", void 0, params ); } /** * Update a Search Monitor * @param id The ID of the Search Monitor * @param params The update parameters * @returns The updated Search Monitor */ async update(id, params) { return this.request(`/${id}`, "PATCH", params); } /** * Delete a Search Monitor * @param id The ID of the Search Monitor * @returns The deleted Search Monitor */ async delete(id) { return this.request(`/${id}`, "DELETE"); } /** * Trigger a Search Monitor run immediately * @param id The ID of the Search Monitor * @returns Whether the monitor was triggered */ async trigger(id) { return this.request( `/${id}/trigger`, "POST" ); } /** * Iterate through all Search Monitors, handling pagination automatically * @param options Pagination and filtering options * @returns Async generator of Search Monitors */ async *listAll(options) { let cursor = void 0; const pageOptions = options ? { ...options } : {}; while (true) { pageOptions.cursor = cursor; const response = await this.list(pageOptions); for (const monitor of response.data) { yield monitor; } if (!response.hasMore || !response.nextCursor) { break; } cursor = response.nextCursor; } } /** * Collect all Search Monitors into an array * @param options Pagination and filtering options * @returns Promise resolving to an array of all Search Monitors */ async getAll(options) { const monitors = []; for await (const monitor of this.listAll(options)) { monitors.push(monitor); } return monitors; } }; // src/research/base.ts var ResearchBaseClient = class { constructor(client) { this.client = client; } async request(endpoint, method = "POST", data, params) { return this.client.request( `/research/v1${endpoint}`, method, data, params ); } async rawRequest(endpoint, method = "POST", data, params) { return this.client.rawRequest( `/research/v1${endpoint}`, method, data, params ); } buildPaginationParams(pagination) { const params = {}; if (!pagination) return params; if (pagination.cursor) params.cursor = pagination.cursor; if (pagination.limit) params.limit = pagination.limit; return params; } }; // src/research/client.ts var ResearchClient = class extends ResearchBaseClient { constructor(client) { super(client); } async create(params) { const { instructions, model, outputSchema } = params; let schema = outputSchema; if (schema && isZodSchema(schema)) { schema = zodToJsonSchema(schema); } const payload = { instructions, model: model ?? "exa-research-fast" }; if (schema) { payload.outputSchema = schema; } return this.request("", "POST", payload); } get(researchId, options) { if (options?.stream) { const promise = async () => { const params = { stream: "true" }; if (options.events !== void 0) { params.events = options.events.toString(); } const resp = await this.rawRequest( `/${researchId}`, "GET", void 0, params ); if (!resp.body) { throw new Error("No response body for SSE stream"); } const reader = resp.body.getReader(); const decoder = new TextDecoder(); let buffer = ""; function processPart(part) { const lines = part.split("\n"); let data = lines.slice(1).join("\n"); if (data.startsWith("data:")) { data = data.slice(5).trimStart(); } try { return JSON.parse(data); } catch (e) { return null; } } async function* streamEvents() { while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); let parts = buffer.split("\n\n"); buffer = parts.pop() ?? ""; for (const part of parts) { const processed = processPart(part); if (processed) { yield processed; } } } if (buffer.trim()) { const processed = processPart(buffer.trim()); if (processed) { yield processed; } } } return streamEvents(); }; return promise(); } else { const params = { stream: "false" }; if (options?.events !== void 0) { params.events = options.events.toString(); } return this.request( `/${researchId}`, "GET", void 0, params ); } } async list(options) { const params = this.buildPaginationParams(options); return this.request("", "GET", void 0, params); } async pollUntilFinished(researchId, options) { const pollInterval = options?.pollInterval ?? 1e3; const timeoutMs = options?.timeoutMs ?? 10 * 60 * 1e3; const maxConsecutiveFailures = 5; const startTime = Date.now(); let consecutiveFailures = 0; while (true) { try { const research = await this.get(researchId, { events: options?.events }); consecutiveFailures = 0; if (research.status === "completed" || research.status === "failed" || research.status === "canceled") { return research; } } catch (err) { consecutiveFailures += 1; if (consecutiveFailures >= maxConsecutiveFailures) { throw new Error( `Polling failed ${maxConsecutiveFailures} times in a row for research ${researchId}: ${err}` ); } } if (Date.now() - startTime > timeoutMs) { throw new Error( `Polling timeout: Research ${researchId} did not complete within ${timeoutMs}ms` ); } await new Promise((resolve) => setTimeout(resolve, pollInterval)); } } }; // src/websets/base.ts var WebsetsBaseClient = class { /** * Initialize a new Websets base client * @param client The Exa client instance */ constructor(client) { this.client = client; } /** * Make a request to the Websets API * @param endpoint The endpoint path * @param method The HTTP method * @param data Optional request body data * @param params Optional query parameters * @returns The response JSON * @throws ExaError with API error details if the request fails */ async request(endpoint, method = "POST", data, params, headers) { return this.client.request( `/websets${endpoint}`, method, data, params, headers ); } /** * Helper to build pagination parameters * @param pagination The pagination parameters * @returns QueryParams object with pagination parameters */ buildPaginationParams(pagination) { const params = {}; if (!pagination) return params; if (pagination.cursor) params.cursor = pagination.cursor; if (pagination.limit) params.limit = pagination.limit; return params; } }; // src/websets/enrichments.ts var WebsetEnrichmentsClient = class extends WebsetsBaseClient { /** * Create an Enrichment for a Webset * @param websetId The ID of the Webset * @param params The enrichment parameters * @returns The created Webset Enrichment */ async create(websetId, params) { return this.request( `/v0/websets/${websetId}/enrichments`, "POST", params ); } /** * Get an Enrichment by ID * @param websetId The ID of the Webset * @param id The ID of the Enrichment * @returns The Webset Enrichment */ async get(websetId, id) { return this.request( `/v0/websets/${websetId}/enrichments/${id}`, "GET" ); } /** * Delete an Enrichment * @param websetId The ID of the Webset * @param id The ID of the Enrichment * @returns The deleted Webset Enrichment */ async delete(websetId, id) { return this.request( `/v0/websets/${websetId}/enrichments/${id}`, "DELETE" ); } /** * Update an Enrichment * @param websetId The ID of the Webset * @param id The ID of the Enrichment * @param params The enrichment update parameters * @returns Promise that resolves when the update is complete */ async update(websetId, id, params) { return this.request( `/v0/websets/${websetId}/enrichments/${id}`, "PATCH", params ); } /** * Cancel a running Enrichment * @param websetId The ID of the Webset * @param id The ID of the Enrichment * @returns The canceled Webset Enrichment */ async cancel(websetId, id) { return this.request( `/v0/websets/${websetId}/enrichments/${id}/cancel`, "POST" ); } }; // src/websets/events.ts var EventsClient = class extends WebsetsBaseClient { /** * Initialize a new Events client * @param client The Exa client instance */ constructor(client) { super(client); } /** * List all Events * @param options Optional filtering and pagination options * @returns The list of Events */ async list(options) { const params = { cursor: options?.cursor, limit: options?.limit, types: options?.types }; return this.request( "/v0/events", "GET", void 0, params ); } /** * Get an Event by ID * @param id The ID of the Event * @returns The Event */ async get(id) { return this.request(`/v0/events/${id}`, "GET"); } /** * Iterate through all Events, handling pagination automatically * @param options Filtering and pagination options * @returns Async generator of Events */ async *listAll(options) { let cursor = void 0; const pageOptions = options ? { ...options } : {}; while (true) { pageOptions.cursor = cursor; const response = await this.list(pageOptions); for (const event of response.data) { yield event; } if (!response.hasMore || !response.nextCursor) { break; } cursor = response.nextCursor; } } /** * Collect all Events into an array * @param options Filtering and pagination options * @returns Promise resolving to an array of all Events */ async getAll(options) { const events = []; for await (const event of this.listAll(options)) { events.push(event); } return events; } }; // src/websets/openapi.ts var CreateEnrichmentParametersFormat = /* @__PURE__ */ ((CreateEnrichmentParametersFormat2) => { CreateEnrichmentParametersFormat2["text"] = "text"; CreateEnrichmentParametersFormat2["date"] = "date"; CreateEnrichmentParametersFormat2["number"] = "number"; CreateEnrichmentParametersFormat2["options"] = "options"; CreateEnrichmentParametersFormat2["email"] = "email"; CreateEnrichmentParametersFormat2["phone"] = "phone"; CreateEnrichmentParametersFormat2["url"] = "url"; return CreateEnrichmentParametersFormat2; })(CreateEnrichmentParametersFormat || {}); var CreateImportParametersFormat = /* @__PURE__ */ ((CreateImportParametersFormat2) => { CreateImportParametersFormat2["csv"] = "csv"; return CreateImportParametersFormat2; })(CreateImportParametersFormat || {}); var WebsetImportSource = /* @__PURE__ */ ((WebsetImportSource2) => { WebsetImportSource2["import"] = "import"; WebsetImportSource2["webset"] = "webset"; return WebsetImportSource2; })(WebsetImportSource || {}); var EventType = /* @__PURE__ */ ((EventType2) => { EventType2["webset_created"] = "webset.created"; EventType2["webset_deleted"] = "webset.deleted"; EventType2["webset_paused"] = "webset.paused"; EventType2["webset_idle"] = "webset.idle"; EventType2["webset_search_created"] = "webset.search.created"; EventType2["webset_search_canceled"] = "webset.search.canceled"; EventType2["webset_search_completed"] = "webset.search.completed"; EventType2["webset_search_updated"] = "webset.search.updated"; EventType2["import_created"] = "import.created"; EventType2["import_completed"] = "import.completed"; EventType2["webset_item_created"] = "webset.item.created"; EventType2["webset_item_enriched"] = "webset.item.enriched"; EventType2["monitor_created"] = "monitor.created"; EventType2["monitor_updated"] = "monitor.updated"; EventType2["monitor_deleted"] = "monitor.deleted"; EventType2["monitor_run_created"] = "monitor.run.created"; EventType2["monitor_run_completed"] = "monitor.run.completed"; EventType2["webset_export_created"] = "webset.export.created"; EventType2["webset_export_completed"] = "webset.export.completed"; return EventType2; })(EventType || {}); var ImportFailedReason = /* @__PURE__ */ ((ImportFailedReason2) => { ImportFailedReason2["invalid_format"] = "invalid_format"; ImportFailedReason2["invalid_file_content"] = "invalid_file_content"; ImportFailedReason2["missing_identifier"] = "missing_identifier"; return ImportFailedReason2; })(ImportFailedReason || {}); var ImportFormat = /* @__PURE__ */ ((ImportFormat2) => { ImportFormat2["csv"] = "csv"; ImportFormat2["webset"] = "webset"; return ImportFormat2; })(ImportFormat || {}); var ImportObject = /* @__PURE__ */ ((ImportObject2) => { ImportObject2["import"] = "import"; return ImportObject2; })(ImportObject || {}); var ImportStatus = /* @__PURE__ */ ((ImportStatus2) => { ImportStatus2["pending"] = "pending"; ImportStatus2["processing"] = "processing"; ImportStatus2["completed"] = "completed"; ImportStatus2["failed"] = "failed"; return ImportStatus2; })(ImportStatus || {}); var MonitorObject = /* @__PURE__ */ ((MonitorObject2) => { MonitorObject2["monitor"] = "monitor"; return MonitorObject2; })(MonitorObject || {}); var MonitorStatus = /* @__PURE__ */ ((MonitorStatus2) => { MonitorStatus2["enabled"] = "enabled"; MonitorStatus2["disabled"] = "disabled"; return MonitorStatus2; })(MonitorStatus || {}); var MonitorRunObject = /* @__PURE__ */ ((MonitorRunObject2) => { MonitorRunObject2["monitor_run"] = "monitor_run"; return MonitorRunObject2; })(MonitorRunObject || {}); var MonitorRunStatus = /* @__PURE__ */ ((MonitorRunStatus2) => { MonitorRunStatus2["created"] = "created"; MonitorRunStatus2["running"] = "running"; MonitorRunStatus2["completed"] = "completed"; MonitorRunStatus2["canceled"] = "canceled"; MonitorRunStatus2["failed"] = "failed"; return MonitorRunStatus2; })(MonitorRunStatus || {}); var MonitorRunType = /* @__PURE__ */ ((MonitorRunType2) => { MonitorRunType2["search"] = "search"; MonitorRunType2["refresh"] = "refresh"; return MonitorRunType2; })(MonitorRunType || {}); var UpdateMonitorStatus = /* @__PURE__ */ ((UpdateMonitorStatus2) => { UpdateMonitorStatus2["enabled"] = "enabled"; UpdateMonitorStatus2["disabled"] = "disabled"; return UpdateMonitorStatus2; })(UpdateMonitorStatus || {}); var WebhookStatus = /* @__PURE__ */ ((WebhookStatus2) => { WebhookStatus2["active"] = "active"; WebhookStatus2["inactive"] = "inactive"; return WebhookStatus2; })(WebhookStatus || {}); var WebsetStatus = /* @__PURE__ */ ((WebsetStatus2) => { WebsetStatus2["idle"] = "idle"; WebsetStatus2["pending"] = "pending"; WebsetStatus2["running"] = "running"; WebsetStatus2["paused"] = "paused"; return WebsetStatus2; })(WebsetStatus || {}); var WebsetEnrichmentStatus = /* @__PURE__ */ ((WebsetEnrichmentStatus2) => { WebsetEnrichmentStatus2["pending"] = "pending"; WebsetEnrichmentStatus2["canceled"] = "canceled"; WebsetEnrichmentStatus2["completed"] = "completed"; return WebsetEnrichmentStatus2; })(WebsetEnrichmentStatus || {}); var WebsetEnrichmentFormat = /* @__PURE__ */ ((WebsetEnrichmentFormat2) => { WebsetEnrichmentFormat2["text"] = "text"; WebsetEnrichmentFormat2["date"] = "date"; WebsetEnrichmentFormat2["number"] = "number"; WebsetEnrichmentFormat2["options"] = "options"; WebsetEnrichmentFormat2["email"] = "email"; WebsetEnrichmentFormat2["phone"] = "phone"; WebsetEnrichmentFormat2["url"] = "url"; return WebsetEnrichmentFormat2; })(WebsetEnrichmentFormat || {}); var WebsetItemSource = /* @__PURE__ */ ((WebsetItemSource2) => { WebsetItemSource2["search"] = "search"; WebsetItemSource2["import"] = "import"; return WebsetItemSource2; })(WebsetItemSource || {}); var WebsetItemEvaluationSatisfied = /* @__PURE__ */ ((WebsetItemEvaluationSatisfied2) => { WebsetItemEvaluationSatisfied2["yes"] = "yes"; WebsetItemEvaluationSatisfied2["no"] = "no"; WebsetItemEvaluationSatisfied2["unclear"] = "unclear"; return WebsetItemEvaluationSatisfied2; })(WebsetItemEvaluationSatisfied || {}); var WebsetExcludeSource = /* @__PURE__ */ ((WebsetExcludeSource2) => { WebsetExcludeSource2["import"] = "import"; WebsetExcludeSource2["webset"] = "webset"; return WebsetExcludeSource2; })(WebsetExcludeSource || {}); var WebsetSearchScopeSource = /* @__PURE__ */ ((WebsetSearchScopeSource2) => { WebsetSearchScopeSource2["import"] = "import"; WebsetSearchScopeSource2["webset"] = "webset"; return WebsetSearchScopeSource2; })(WebsetSearchScopeSource || {}); var WebsetSearchStatus = /* @__PURE__ */ ((WebsetSearchStatus2) => { WebsetSearchStatus2["created"] = "created"; WebsetSearchStatus2["pending"] = "pending"; WebsetSearchStatus2["running"] = "running"; WebsetSearchStatus2["completed"] = "completed"; WebsetSearchStatus2["canceled"] = "canceled"; return WebsetSearchStatus2; })(WebsetSearchStatus || {}); var WebsetSearchBehavior = /* @__PURE__ */ ((WebsetSearchBehavior2) => { WebsetSearchBehavior2["override"] = "override"; WebsetSearchBehavior2["append"] = "append"; return WebsetSearchBehavior2; })(WebsetSearchBehavior || {}); var WebsetSearchCanceledReason = /* @__PURE__ */ ((WebsetSearchCanceledReason2) => { WebsetSearchCanceledReason2["webset_deleted"] = "webset_deleted"; WebsetSearchCanceledReason2["webset_canceled"] = "webset_canceled"; return WebsetSearchCanceledReason2; })(WebsetSearchCanceledReason || {}); // src/websets/imports.ts var ImportsClient = class extends WebsetsBaseClient { async create(params, csv) { if (csv === void 0) { return this.request( "/v0/imports", "POST", params ); } let csvBuffer; if (typeof csv === "string") { csvBuffer = Buffer.from(csv, "utf8"); } else if (Buffer.isBuffer(csv)) { csvBuffer = csv; } else { throw new ExaError( "Invalid CSV data input. Must be string or Buffer", 400 /* BadRequest */ ); } const sizeInBytes = csvBuffer.length; const sizeInMB = Math.max(1, Math.ceil(sizeInBytes / (1024 * 1024))); const csvText = csvBuffer.toString("utf8"); const lines = csvText.split("\n").filter((line) => line.trim().length > 0); const recordCount = Math.max(0, lines.length - 1); if (sizeInMB > 50) { throw new ExaError( `CSV file too large: ${sizeInMB}MB. Maximum size is 50MB.`, 400 /* BadRequest */ ); } if (recordCount === 0) { throw new ExaError( "CSV file appears to have no data records (only header or empty)", 400 /* BadRequest */ ); } const createParams = { title: params.title, format: "csv" /* csv */, entity: params.entity, size: sizeInBytes, count: recordCount, metadata: params.metadata, csv: params.csv }; const importResponse = await this.request( "/v0/imports", "POST", createParams ); try { const uploadResponse = await fetch(importResponse.uploadUrl, { method: "PUT", body: csvBuffer }); if (!uploadResponse.ok) { const errorText = await uploadResponse.text(); throw new ExaError( `Upload failed: ${uploadResponse.status} ${uploadResponse.statusText}. ${errorText}`, 400 /* BadRequest */ ); } } catch (error) { if (error instanceof ExaError) { throw error; } throw new ExaError( `Failed to upload CSV data: ${error.message}`, 400 /* BadRequest */ ); } return importResponse; } /** * Get an Import by ID * @param id The ID of the Import * @returns The Import */ async get(id) { return this.request(`/v0/imports/${id}`, "GET"); } /** * List all Imports * @param options Pagination options * @returns The list of Imports */ async list(options) { const params = this.buildPaginationParams(options); return this.request( "/v0/imports", "GET", void 0, params ); } /** * Update an Import * @param id The ID of the Import * @param params The import update parameters * @returns The updated Import */ async update(id, params) { return this.request(`/v0/imports/${id}`, "PATCH", params); } /** * Delete an Import * @param id The ID of the Import * @returns The deleted Import */ async delete(id) { return this.request(`/v0/imports/${id}`, "DELETE"); } /** * Wait until an Import is completed or failed * @param id The ID of the Import * @param options Configuration options for timeout and polling * @returns The Import once it reaches a final state (completed or failed) * @throws Error if the Import does not complete within the timeout or fails */ async waitUntilCompleted(id, options) { const timeout = options?.timeout ?? 30 * 60 * 1e3; const pollInterval = options?.pollInterval ?? 2e3; const onPoll = options?.onPoll; const startTime = Date.now(); while (true) { const importItem = await this.get(id); if (onPoll) { onPoll(importItem.status); } if (importItem.status === "completed" /* completed */) { return importItem; } if (importItem.status === "failed" /* failed */) { throw new ExaError( `Import ${id} failed: ${importItem.failedMessage || "Unknown error"}`, 400 /* BadRequest */ ); } if (Date.now() - startTime > timeout) { throw new ExaError( `Import ${id} did not complete within ${timeout}ms. Current status: ${importItem.status}`, 408 /* RequestTimeout */ ); } await new Promise((resolve) => setTimeout(resolve, pollInterval)); } } /** * Iterate through all Imports, handling pagination automatically * @param options Pagination options * @returns Async generator of Imports */ async *listAll(options) { let cursor = void 0; const pageOptions = options ? { ...options } : {}; while (true) { pageOptions.cursor = cursor; const response = await this.list(pageOptions); for (const importItem of response.data) { yield importItem; } if (!response.hasMore || !response.nextCursor) { break; } cursor = response.nextCursor; } } /** * Collect all Imports into an array * @param options Pagination options * @returns Promise resolving to an array of all Imports */ async getAll(options) { const imports = []; for await (const importItem of this.listAll(options)) { imports.push(importItem); } return imports; } }; // src/websets/items.ts var WebsetItemsClient = class extends WebsetsBaseClient { /** * List all Items for a Webset * @param websetId The ID of the Webset * @param params - Optional pagination and filtering parameters * @returns A promise that resolves with the list of Items */ list(websetId, params) { const queryParams = { ...this.buildPaginationParams(params), sourceId: params?.sourceId }; return this.request( `/v0/websets/${websetId}/items`, "GET", void 0, queryParams ); } /** * Iterate through all Items in a Webset, handling pagination automatically * @param websetId The ID of the Webset * @param options Pagination options * @returns Async generator of Webset Items */ async *listAll(websetId, options) { let cursor = void 0; const pageOptions = options ? { ...options } : {}; while (true) { pageOptions.cursor = cursor; const response = await this.list(websetId, pageOptions); for (const item of response.data) { yield item; } if (!response.hasMore || !response.nextCursor) { break; } cursor = response.nextCursor; } } /** * Collect all items from a Webset into an array * @param websetId The ID of the Webset * @param options Pagination options * @returns Promise resolving to an array of all Webset Items */ async getAll(websetId, options) { const items = []; for await (const item of this.listAll(websetId, options)) { items.push(item); } return items; } /** * Get an Item by ID * @param websetId The ID of the Webset * @param id The ID of the Item * @returns The Webset Item */ async get(websetId, id) { return this.request( `/v0/websets/${websetId}/items/${id}`, "GET" ); } /** * Delete an Item * @param websetId The ID of the Webset * @param id The ID of the Item * @returns The deleted Webset Item */ async delete(websetId, id) { return this.request( `/v0/websets/${websetId}/items/${id}`, "DELETE" ); } }; // src/websets/monitors.ts var WebsetMonitorRunsClient = class extends WebsetsBaseClient { /** * List all runs for a Monitor * @param monitorId The ID of the Monitor * @param options Pagination options * @returns The list of Monitor runs */ async list(monitorId, options) { const params = this.buildPaginationParams(options); return this.request( `/v0/monitors/${monitorId}/runs`, "GET", void 0, params ); } /** * Get a specific Monitor run * @param monitorId The ID of the Monitor * @param runId The ID of the Monitor run * @returns The Monitor run */ async get(monitorId, runId) { return this.request( `/v0/monitors/${monitorId}/runs/${runId}`, "GET" ); } }; var WebsetMonitorsClient = class extends WebsetsBaseClient { constructor(client) { super(client); this.runs = new WebsetMonitorRunsClient(client); } /** * Create a Monitor * @param params The monitor parameters * @returns The created Monitor */ async create(params) { return this.request("/v0/monitors", "POST", params); } /** * Get a Monitor by ID * @param id The ID of the Monitor * @returns The Monitor */ async get(id) { return this.request(`/v0/monitors/${id}`, "GET"); } /** * List all Monitors * @param options Pagination and filtering options * @returns The list of Monitors */ async list(options) { const params = { cursor: options?.cursor, limit: options?.limit, websetId: options?.websetId }; return this.request( "/v0/monitors", "GET", void 0, params ); } /** * Update a Monitor * @param id The ID of the Monitor * @param params The monitor update parameters (status, metadata) * @returns The updated Monitor */ async update(id, params) { return this.request(`/v0/monitors/${id}`, "PATCH", params); } /** * Delete a Monitor * @param id The ID of the Monitor * @returns The deleted Monitor */ async delete(id) { return this.request(`/v0/monitors/${id}`, "DELETE"); } /** * Iterate through all Monitors, handling pagination automatically * @param options Pagination and filtering options * @returns Async generator of Monitors */ async *listAll(options) { let cursor = void 0; const pageOptions = options ? { ...options } : {}; while (true) { pageOptions.cursor = cursor; const response = await this.list(pageOptions); for (const monitor of response.data) { yield monitor; } if (!response.hasMore || !response.nextCursor) { break; } cursor = response.nextCursor; } } /** * Collect all Monitors into an array * @param options Pagination and filtering options * @returns Promise resolving to an array of all Monitors */ async getAll(options) { const monitors = []; for await (const monitor of this.listAll(options)) { monitors.push(monitor); } return monitors; } }; // src/websets/searches.ts var WebsetSearchesClient = class extends WebsetsBaseClient { /** * Create a new Search for the Webset * @param websetId The ID of the Webset * @param params The search parameters * @returns The created Webset Search */ async create(websetId, params, options) { return this.request( `/v0/websets/${websetId}/searches`, "POST", params, void 0, options?.headers ); } /** * Get a Search by ID * @param websetId The ID of the Webset * @param id The ID of the Search * @returns The Webset Search */ async get(websetId, id) { return this.request( `/v0/websets/${websetId}/searches/${id}`, "GET" ); } /** * Cancel a running Search * @param websetId The ID of the Webset * @param id The ID of the Search * @returns The canceled Webset Search */ async cancel(websetId, id) { return this.request( `/v0/websets/${websetId}/searches/${id}/cancel`, "POST" ); } }; // src/websets/webhooks.ts var WebsetWebhooksClient = class extends WebsetsBaseClient { /** * Create a Webhook * @param params The webhook parameters * @returns The created Webhook */ async create(params) { return this.request("/v0/webhooks", "POST", params); } /** * Get a Webhook by ID * @param id The ID of the Webhook * @returns The Webhook */ async get(id) { return this.request(`/v0/webhooks/${id}`, "GET"); } /** * List all Webhooks * @param options Pagination options * @returns The list of Webhooks */ async list(options) { const params = this.buildPaginationParams(options); return this.request( "/v0/webhooks", "GET", void 0, params ); } /** * Iterate through all Webhooks, handling pagination automatically * @param options Pagination options * @returns Async generator of Webhooks */ async *listAll(options) { let cursor = void 0; const pageOptions = options ? { ...options } : {}; while (true) { pageOptions.cursor = cursor; const response = await