"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/index.ts
var index_exports = {};
__export(index_exports, {
  CreateEnrichmentParametersFormat: () => CreateEnrichmentParametersFormat,
  CreateImportParametersFormat: () => CreateImportParametersFormat,
  EventType: () => EventType,
  EventsClient: () => EventsClient,
  Exa: () => Exa2,
  ExaError: () => ExaError,
  HttpStatusCode: () => HttpStatusCode,
  ImportFailedReason: () => ImportFailedReason,
  ImportFormat: () => ImportFormat,
  ImportObject: () => ImportObject,
  ImportStatus: () => ImportStatus,
  ImportsClient: () => ImportsClient,
  MonitorObject: () => MonitorObject,
  MonitorRunObject: () => MonitorRunObject,
  MonitorRunStatus: () => MonitorRunStatus,
  MonitorRunType: () => MonitorRunType,
  MonitorStatus: () => MonitorStatus,
  UpdateMonitorStatus: () => UpdateMonitorStatus,
  WebhookStatus: () => WebhookStatus,
  WebsetEnrichmentFormat: () => WebsetEnrichmentFormat,
  WebsetEnrichmentStatus: () => WebsetEnrichmentStatus,
  WebsetEnrichmentsClient: () => WebsetEnrichmentsClient,
  WebsetExcludeSource: () => WebsetExcludeSource,
  WebsetImportSource: () => WebsetImportSource,
  WebsetItemEvaluationSatisfied: () => WebsetItemEvaluationSatisfied,
  WebsetItemSource: () => WebsetItemSource,
  WebsetItemsClient: () => WebsetItemsClient,
  WebsetMonitorsClient: () => WebsetMonitorsClient,
  WebsetSearchBehavior: () => WebsetSearchBehavior,
  WebsetSearchCanceledReason: () => WebsetSearchCanceledReason,
  WebsetSearchScopeSource: () => WebsetSearchScopeSource,
  WebsetSearchStatus: () => WebsetSearchStatus,
  WebsetSearchesClient: () => WebsetSearchesClient,
  WebsetStatus: () => WebsetStatus,
  WebsetWebhooksClient: () => WebsetWebhooksClient,
  WebsetsClient: () => WebsetsClient,
  default: () => index_default
});
module.exports = __toCommonJS(index_exports);
var import_cross_fetch = __toESM(require("cross-fetch"));

// package.json
var package_default = {
  name: "exa-js",
  version: "1.10.2",
  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",
    typecheck: "tsc --noEmit",
    "typecheck:src": "tsc --noEmit src/**/*.ts",
    "typecheck:examples": "tsc --noEmit examples/**/*.ts",
    "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",
    "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-node": "~10.9.2",
    tsup: "~8.4.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
var import_zod = require("zod");
var import_zod_to_json_schema = require("zod-to-json-schema");
function isZodSchema(obj) {
  return obj instanceof import_zod.ZodType;
}
function zodToJsonSchema(schema) {
  return (0, import_zod_to_json_schema.zodToJsonSchema)(schema, {
    $refStrategy: "none"
  });
}

// 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");
  }
};

// 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));
    }
  }
};

// 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");
  }
};

// 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 this.list(pageOptions);
      for (const webhook of response.data) {
        yield webhook;
      }
      if (!response.hasMore || !response.nextCursor) {
        break;
      }
      cursor = response.nextCursor;
    }
  }
  /**
   * Collect all Webhooks into an array
   * @param options Pagination options
   * @returns Promise resolving to an array of all Webhooks
   */
  async getAll(options) {
    const webhooks = [];
    for await (const webhook of this.listAll(options)) {
      webhooks.push(webhook);
    }
    return webhooks;
  }
  /**
   * Update a Webhook
   * @param id The ID of the Webhook
   * @param params The webhook update parameters (events, metadata, url)
   * @returns The updated Webhook
   */
  async update(id, params) {
    return this.request(`/v0/webhooks/${id}`, "PATCH", params);
  }
  /**
   * Delete a Webhook
   * @param id The ID of the Webhook
   * @returns The deleted Webhook
   */
  async delete(id) {
    return this.request(`/v0/webhooks/${id}`, "DELETE");
  }
  /**
   * List all attempts for a Webhook
   * @param id The ID of the Webhook
   * @param options Pagination and filtering options
   * @returns The list of Webhook attempts
   */
  async listAttempts(id, options) {
    const params = {
      cursor: options?.cursor,
      limit: options?.limit,
      eventType: options?.eventType,
      successful: options?.successful
    };
    return this.request(
      `/v0/webhooks/${id}/attempts`,
      "GET",
      void 0,
      params
    );
  }
  /**
   * Iterate through all attempts for a Webhook, handling pagination automatically
   * @param id The ID of the Webhook
   * @param options Pagination and filtering options
   * @returns Async generator of Webhook attempts
   */
  async *listAllAttempts(id, options) {
    let cursor = void 0;
    const pageOptions = options ? { ...options } : {};
    while (true) {
      pageOptions.cursor = cursor;
      const response = await this.listAttempts(id, pageOptions);
      for (const attempt of response.data) {
        yield attempt;
      }
      if (!response.hasMore || !response.nextCursor) {
        break;
      }
      cursor = response.nextCursor;
    }
  }
  /**
   * Collect all attempts for a Webhook into an array
   * @param id The ID of the Webhook
   * @param options Pagination and filtering options
   * @returns Promise resolving to an array of all Webhook attempts
   */
  async getAllAttempts(id, options) {
    const attempts = [];
    for await (const attempt of this.listAllAttempts(id, options)) {
      attempts.push(attempt);
    }
    return attempts;
  }
};

// src/websets/client.ts
var WebsetsClient = class extends WebsetsBaseClient {
  /**
   * Initialize a new Websets client
   * @param client The Exa client instance
   */
  constructor(client) {
    super(client);
    this.events = new EventsClient(client);
    this.imports = new ImportsClient(client);
    this.items = new WebsetItemsClient(client);
    this.searches = new WebsetSearchesClient(client);
    this.enrichments = new WebsetEnrichmentsClient(client);
    this.monitors = new WebsetMonitorsClient(client);
    this.webhooks = new WebsetWebhooksClient(client);
  }
  /**
   * Create a new Webset
   * @param params The Webset creation parameters
   * @returns The created Webset
   */
  async create(params, options) {
    return this.request(
      "/v0/websets",
      "POST",
      params,
      void 0,
      options?.headers
    );
  }
  /**
   * Preview a webset
   * @param params The preview parameters
   * @returns The preview response showing how the query will be decomposed
   */
  async preview(params) {
    return this.request(
      "/v0/websets/preview",
      "POST",
      params
    );
  }
  /**
   * Get a Webset by ID
   * @param id The ID of the Webset
   * @param expand Optional array of relations to expand
   * @returns The Webset
   */
  async get(id, expand) {
    const params = {};
    if (expand) {
      params.expand = expand;
    }
    return this.request(
      `/v0/websets/${id}`,
      "GET",
      void 0,
      params
    );
  }
  /**
   * List all Websets
   * @param options Pagination options (filtering by status is not supported by API)
   * @returns The list of Websets
   */
  async list(options) {
    const params = this.buildPaginationParams(options);
    return this.request(
      "/v0/websets",
      "GET",
      void 0,
      params
    );
  }
  /**
   * Iterate through all Websets, handling pagination automatically
   * @param options Pagination options
   * @returns Async generator of Websets
   */
  async *listAll(options) {
    let cursor = void 0;
    const pageOptions = options ? { ...options } : {};
    while (true) {
      pageOptions.cursor = cursor;
      const response = await this.list(pageOptions);
      for (const webset of response.data) {
        yield webset;
      }
      if (!response.hasMore || !response.nextCursor) {
        break;
      }
      cursor = response.nextCursor;
    }
  }
  /**
   * Collect all Websets into an array
   * @param options Pagination options
   * @returns Promise resolving to an array of all Websets
   */
  async getAll(options) {
    const websets = [];
    for await (const webset of this.listAll(options)) {
      websets.push(webset);
    }
    return websets;
  }
  /**
   * Update a Webset
   * @param id The ID of the Webset
   * @param params The Webset update parameters
   * @returns The updated Webset
   */
  async update(id, params) {
    return this.request(`/v0/websets/${id}`, "POST", params);
  }
  /**
   * Delete a Webset
   * @param id The ID of the Webset
   * @returns The deleted Webset
   */
  async delete(id) {
    return this.request(`/v0/websets/${id}`, "DELETE");
  }
  /**
   * Cancel a running Webset
   * @param id The ID or external ID of the Webset
   * @returns The canceled Webset (as returned by the API)
   */
  async cancel(id) {
    return this.request(`/v0/websets/${id}/cancel`, "POST");
  }
  /**
   * Wait until a Webset is idle
   * @param id The ID of the Webset
   * @param options Configuration options for timeout and polling
   * @returns The Webset once it becomes idle
   * @throws Error if the Webset does not become idle within the timeout
   */
  async waitUntilIdle(id, options) {
    let timeout;
    let pollInterval = 1e3;
    let onPoll;
    if (typeof options === "number") {
      timeout = options;
    } else if (options) {
      timeout = options.timeout;
      pollInterval = options.pollInterval || 1e3;
      onPoll = options.onPoll;
    }
    const startTime = Date.now();
    while (true) {
      const webset = await this.get(id);
      if (onPoll) {
        onPoll(webset.status);
      }
      if (webset.status === "idle" /* idle */) {
        return webset;
      }
      if (timeout && Date.now() - startTime > timeout) {
        throw new ExaError(
          `Webset ${id} did not reach idle state within ${timeout}ms. Current status: ${webset.status}`,
          408 /* RequestTimeout */
        );
      }
      await new Promise((resolve) => setTimeout(resolve, pollInterval));
    }
  }
};

// src/index.ts
var fetchImpl = typeof global !== "undefined" && global.fetch ? global.fetch : import_cross_fetch.default;
var HeadersImpl = typeof global !== "undefined" && global.Headers ? global.Headers : import_cross_fetch.Headers;
var Exa2 = class {
  /**
   * Helper method to separate out the contents-specific options from the rest.
   */
  extractContentsOptions(options) {
    const {
      text,
      highlights,
      summary,
      subpages,
      subpageTarget,
      extras,
      livecrawl,
      livecrawlTimeout,
      context,
      ...rest
    } = options;
    const contentsOptions = {};
    if (text === void 0 && summary === void 0 && highlights === void 0 && extras === void 0) {
      contentsOptions.text = true;
    }
    if (text !== void 0) contentsOptions.text = text;
    if (summary !== void 0) {
      if (typeof summary === "object" && summary !== null && "schema" in summary && summary.schema && isZodSchema(summary.schema)) {
        contentsOptions.summary = {
          ...summary,
          schema: zodToJsonSchema(summary.schema)
        };
      } else {
        contentsOptions.summary = summary;
      }
    }
    if (highlights !== void 0) contentsOptions.highlights = highlights;
    if (subpages !== void 0) contentsOptions.subpages = subpages;
    if (subpageTarget !== void 0)
      contentsOptions.subpageTarget = subpageTarget;
    if (extras !== void 0) contentsOptions.extras = extras;
    if (livecrawl !== void 0) contentsOptions.livecrawl = livecrawl;
    if (livecrawlTimeout !== void 0)
      contentsOptions.livecrawlTimeout = livecrawlTimeout;
    if (context !== void 0) contentsOptions.context = context;
    return {
      contentsOptions,
      restOptions: rest
    };
  }
  /**
   * Constructs the Exa API client.
   * @param {string} apiKey - The API key for authentication.
   * @param {string} [baseURL] - The base URL of the Exa API.
   */
  constructor(apiKey, baseURL = "https://api.exa.ai") {
    this.baseURL = baseURL;
    if (!apiKey) {
      apiKey = process.env.EXASEARCH_API_KEY;
      if (!apiKey) {
        throw new ExaError(
          "API key must be provided as an argument or as an environment variable (EXASEARCH_API_KEY)",
          401 /* Unauthorized */
        );
      }
    }
    this.headers = new HeadersImpl({
      "x-api-key": apiKey,
      "Content-Type": "application/json",
      "User-Agent": `exa-node ${package_default.version}`
    });
    this.websets = new WebsetsClient(this);
    this.research = new ResearchClient(this);
  }
  /**
   * Makes a request to the Exa API.
   * @param {string} endpoint - The API endpoint to call.
   * @param {string} method - The HTTP method to use.
   * @param {any} [body] - The request body for POST requests.
   * @param {Record<string, any>} [params] - The query parameters.
   * @returns {Promise<any>} The response from the API.
   * @throws {ExaError} When any API request fails with structured error information
   */
  async request(endpoint, method, body, params, headers) {
    let url = this.baseURL + endpoint;
    if (params && Object.keys(params).length > 0) {
      const searchParams = new URLSearchParams();
      for (const [key, value] of Object.entries(params)) {
        if (Array.isArray(value)) {
          for (const item of value) {
            searchParams.append(key, item);
          }
        } else if (value !== void 0) {
          searchParams.append(key, String(value));
        }
      }
      url += `?${searchParams.toString()}`;
    }
    let combinedHeaders = {};
    if (this.headers instanceof HeadersImpl) {
      this.headers.forEach((value, key) => {
        combinedHeaders[key] = value;
      });
    } else {
      combinedHeaders = { ...this.headers };
    }
    if (headers) {
      combinedHeaders = { ...combinedHeaders, ...headers };
    }
    const response = await fetchImpl(url, {
      method,
      headers: combinedHeaders,
      body: body ? JSON.stringify(body) : void 0
    });
    if (!response.ok) {
      const errorData = await response.json();
      if (!errorData.statusCode) {
        errorData.statusCode = response.status;
      }
      if (!errorData.timestamp) {
        errorData.timestamp = (/* @__PURE__ */ new Date()).toISOString();
      }
      if (!errorData.path) {
        errorData.path = endpoint;
      }
      let message = errorData.error || "Unknown error";
      if (errorData.message) {
        message += (message.length > 0 ? ". " : "") + errorData.message;
      }
      throw new ExaError(
        message,
        response.status,
        errorData.timestamp,
        errorData.path
      );
    }
    const contentType = response.headers.get("content-type") || "";
    if (contentType.includes("text/event-stream")) {
      return await this.parseSSEStream(response);
    }
    return await response.json();
  }
  async rawRequest(endpoint, method = "POST", body, queryParams) {
    let url = this.baseURL + endpoint;
    if (queryParams) {
      const searchParams = new URLSearchParams();
      for (const [key, value] of Object.entries(queryParams)) {
        if (Array.isArray(value)) {
          for (const item of value) {
            searchParams.append(key, String(item));
          }
        } else if (value !== void 0) {
          searchParams.append(key, String(value));
        }
      }
      url += `?${searchParams.toString()}`;
    }
    const response = await fetchImpl(url, {
      method,
      headers: this.headers,
      body: body ? JSON.stringify(body) : void 0
    });
    return response;
  }
  /**
   * Performs a search with an Exa prompt-engineered query.
   *
   * @param {string} query - The query string.
   * @param {RegularSearchOptions} [options] - Additional search options
   * @returns {Promise<SearchResponse<{}>>} A list of relevant search results.
   */
  async search(query, options) {
    return await this.request("/search", "POST", { query, ...options });
  }
  /**
   * Performs a search with an Exa prompt-engineered query and returns the contents of the documents.
   *
   * @param {string} query - The query string.
   * @param {RegularSearchOptions & T} [options] - Additional search + contents options
   * @returns {Promise<SearchResponse<T>>} A list of relevant search results with requested contents.
   */
  async searchAndContents(query, options) {
    const { contentsOptions, restOptions } = options === void 0 ? { contentsOptions: { text: true }, restOptions: {} } : this.extractContentsOptions(options);
    return await this.request("/search", "POST", {
      query,
      contents: contentsOptions,
      ...restOptions
    });
  }
  /**
   * Finds similar links to the provided URL.
   * @param {string} url - The URL for which to find similar links.
   * @param {FindSimilarOptions} [options] - Additional options for finding similar links.
   * @returns {Promise<SearchResponse<{}>>} A list of similar search results.
   */
  async findSimilar(url, options) {
    return await this.request("/findSimilar", "POST", { url, ...options });
  }
  /**
   * Finds similar links to the provided URL and returns the contents of the documents.
   * @param {string} url - The URL for which to find similar links.
   * @param {FindSimilarOptions & T} [options] - Additional options for finding similar links + contents.
   * @returns {Promise<SearchResponse<T>>} A list of similar search results, including requested contents.
   */
  async findSimilarAndContents(url, options) {
    const { contentsOptions, restOptions } = options === void 0 ? { contentsOptions: { text: true }, restOptions: {} } : this.extractContentsOptions(options);
    return await this.request("/findSimilar", "POST", {
      url,
      contents: contentsOptions,
      ...restOptions
    });
  }
  /**
   * Retrieves contents of documents based on URLs.
   * @param {string | string[] | SearchResult[]} urls - A URL or array of URLs, or an array of SearchResult objects.
   * @param {ContentsOptions} [options] - Additional options for retrieving document contents.
   * @returns {Promise<SearchResponse<T>>} A list of document contents for the requested URLs.
   */
  async getContents(urls, options) {
    if (!urls || Array.isArray(urls) && urls.length === 0) {
      throw new ExaError(
        "Must provide at least one URL",
        400 /* BadRequest */
      );
    }
    let requestUrls;
    if (typeof urls === "string") {
      requestUrls = [urls];
    } else if (typeof urls[0] === "string") {
      requestUrls = urls;
    } else {
      requestUrls = urls.map((result) => result.url);
    }
    const payload = {
      urls: requestUrls,
      ...options
    };
    return await this.request("/contents", "POST", payload);
  }
  async answer(query, options) {
    if (options?.stream) {
      throw new ExaError(
        "For streaming responses, please use streamAnswer() instead:\n\nfor await (const chunk of exa.streamAnswer(query)) {\n  // Handle chunks\n}",
        400 /* BadRequest */
      );
    }
    let outputSchema = options?.outputSchema;
    if (outputSchema && isZodSchema(outputSchema)) {
      outputSchema = zodToJsonSchema(outputSchema);
    }
    const requestBody = {
      query,
      stream: false,
      text: options?.text ?? false,
      model: options?.model ?? "exa",
      systemPrompt: options?.systemPrompt,
      outputSchema,
      userLocation: options?.userLocation
    };
    return await this.request("/answer", "POST", requestBody);
  }
  async *streamAnswer(query, options) {
    let outputSchema = options?.outputSchema;
    if (outputSchema && isZodSchema(outputSchema)) {
      outputSchema = zodToJsonSchema(outputSchema);
    }
    const body = {
      query,
      text: options?.text ?? false,
      stream: true,
      model: options?.model ?? "exa",
      systemPrompt: options?.systemPrompt,
      outputSchema
    };
    const response = await fetchImpl(this.baseURL + "/answer", {
      method: "POST",
      headers: this.headers,
      body: JSON.stringify(body)
    });
    if (!response.ok) {
      const message = await response.text();
      throw new ExaError(message, response.status, (/* @__PURE__ */ new Date()).toISOString());
    }
    const reader = response.body?.getReader();
    if (!reader) {
      throw new ExaError(
        "No response body available for streaming.",
        500,
        (/* @__PURE__ */ new Date()).toISOString()
      );
    }
    const decoder = new TextDecoder();
    let buffer = "";
    try {
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        buffer += decoder.decode(value, { stream: true });
        const lines = buffer.split("\n");
        buffer = lines.pop() || "";
        for (const line of lines) {
          if (!line.startsWith("data: ")) continue;
          const jsonStr = line.replace(/^data:\s*/, "").trim();
          if (!jsonStr || jsonStr === "[DONE]") {
            continue;
          }
          let chunkData;
          try {
            chunkData = JSON.parse(jsonStr);
          } catch (err) {
            continue;
          }
          const chunk = this.processChunk(chunkData);
          if (chunk.content || chunk.citations) {
            yield chunk;
          }
        }
      }
      if (buffer.startsWith("data: ")) {
        const leftover = buffer.replace(/^data:\s*/, "").trim();
        if (leftover && leftover !== "[DONE]") {
          try {
            const chunkData = JSON.parse(leftover);
            const chunk = this.processChunk(chunkData);
            if (chunk.content || chunk.citations) {
              yield chunk;
            }
          } catch (e) {
          }
        }
      }
    } finally {
      reader.releaseLock();
    }
  }
  processChunk(chunkData) {
    let content;
    let citations;
    if (chunkData.choices && chunkData.choices[0] && chunkData.choices[0].delta) {
      content = chunkData.choices[0].delta.content;
    }
    if (chunkData.citations && chunkData.citations !== "null") {
      citations = chunkData.citations.map((c) => ({
        id: c.id,
        url: c.url,
        title: c.title,
        publishedDate: c.publishedDate,
        author: c.author,
        text: c.text
      }));
    }
    return { content, citations };
  }
  async parseSSEStream(response) {
    const reader = response.body?.getReader();
    if (!reader) {
      throw new ExaError(
        "No response body available for streaming.",
        500,
        (/* @__PURE__ */ new Date()).toISOString()
      );
    }
    const decoder = new TextDecoder();
    let buffer = "";
    return new Promise(async (resolve, reject) => {
      try {
        while (true) {
          const { done, value } = await reader.read();
          if (done) break;
          buffer += decoder.decode(value, { stream: true });
          const lines = buffer.split("\n");
          buffer = lines.pop() || "";
          for (const line of lines) {
            if (!line.startsWith("data: ")) continue;
            const jsonStr = line.replace(/^data:\s*/, "").trim();
            if (!jsonStr || jsonStr === "[DONE]") {
              continue;
            }
            let chunk;
            try {
              chunk = JSON.parse(jsonStr);
            } catch {
              continue;
            }
            switch (chunk.tag) {
              case "complete":
                reader.releaseLock();
                resolve(chunk.data);
                return;
              case "error": {
                const message = chunk.error?.message || "Unknown error";
                reader.releaseLock();
                reject(
                  new ExaError(
                    message,
                    500 /* InternalServerError */,
                    (/* @__PURE__ */ new Date()).toISOString()
                  )
                );
                return;
              }
              // 'progress' and any other tags are ignored for the blocking variant
              default:
                break;
            }
          }
        }
        reject(
          new ExaError(
            "Stream ended without a completion event.",
            500 /* InternalServerError */,
            (/* @__PURE__ */ new Date()).toISOString()
          )
        );
      } catch (err) {
        reject(err);
      } finally {
        try {
          reader.releaseLock();
        } catch {
        }
      }
    });
  }
};
var index_default = Exa2;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  CreateEnrichmentParametersFormat,
  CreateImportParametersFormat,
  EventType,
  EventsClient,
  Exa,
  ExaError,
  HttpStatusCode,
  ImportFailedReason,
  ImportFormat,
  ImportObject,
  ImportStatus,
  ImportsClient,
  MonitorObject,
  MonitorRunObject,
  MonitorRunStatus,
  MonitorRunType,
  MonitorStatus,
  UpdateMonitorStatus,
  WebhookStatus,
  WebsetEnrichmentFormat,
  WebsetEnrichmentStatus,
  WebsetEnrichmentsClient,
  WebsetExcludeSource,
  WebsetImportSource,
  WebsetItemEvaluationSatisfied,
  WebsetItemSource,
  WebsetItemsClient,
  WebsetMonitorsClient,
  WebsetSearchBehavior,
  WebsetSearchCanceledReason,
  WebsetSearchScopeSource,
  WebsetSearchStatus,
  WebsetSearchesClient,
  WebsetStatus,
  WebsetWebhooksClient,
  WebsetsClient
});
//# sourceMappingURL=index.js.map