{"version":3,"file":"pipe0.mjs","names":[],"sources":["../src/pipe0.ts"],"sourcesContent":["import createFetchClient, { type Client } from \"openapi-fetch\";\nimport { type CapacitySnapshot, CapacityTracker } from \"./capacity-tracker.js\";\nimport type { paths } from \"./generated/openapi.types.js\";\n\nexport type PipesRequest =\n  paths[\"/v1/pipes/run\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"];\nexport type PipesResponse =\n  paths[\"/v1/pipes/check/{run_id}\"][\"get\"][\"responses\"][\"200\"][\"content\"][\"application/json\"];\n\nexport type SearchesRequest =\n  paths[\"/v1/searches/run\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"];\nexport type SearchesResponse =\n  paths[\"/v1/searches/check/{run_id}\"][\"get\"][\"responses\"][\"200\"][\"content\"][\"application/json\"];\n\nexport type SearchRequest =\n  paths[\"/v1/search/run\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"];\nexport type SearchResponse =\n  paths[\"/v1/search/check/{run_id}\"][\"get\"][\"responses\"][\"200\"][\"content\"][\"application/json\"];\n\nexport type SheetEffectsRequest =\n  paths[\"/v1/sheets/{sheet_id}/effects/run\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"];\nexport type SheetEffectsResponse =\n  paths[\"/v1/sheets/{sheet_id}/effects/check/{run_id}\"][\"get\"][\"responses\"][\"200\"][\"content\"][\"application/json\"];\n\nexport class Pipe0TimeoutError extends Error {\n  constructor(\n    message: string,\n    public readonly runId?: string,\n  ) {\n    super(message);\n    this.name = \"Pipe0TimeoutError\";\n    this.runId = runId;\n  }\n}\n\nexport class Pipe0AbortError extends Error {\n  constructor(\n    message: string,\n    public readonly runId?: string,\n  ) {\n    super(message);\n    this.name = \"Pipe0AbortError\";\n    this.runId = runId;\n  }\n}\n\n/**\n * The server reports the run as `canceled` (via `pipes.cancel` /\n * `searches.cancel` or another client). Subclasses {@link Pipe0AbortError} so\n * existing `instanceof Pipe0AbortError` handling keeps working.\n */\nexport class Pipe0CanceledError extends Pipe0AbortError {\n  constructor(message: string, runId?: string) {\n    super(message, runId);\n    this.name = \"Pipe0CanceledError\";\n  }\n}\n\nexport class Pipe0BatchError extends Error {\n  constructor(\n    message: string,\n    public readonly errors: Array<{ batchIndex: number; error: Error }>,\n    public readonly successfulBatches: PipesResponse[],\n  ) {\n    super(message);\n    this.name = \"Pipe0BatchError\";\n    this.errors = errors;\n    this.successfulBatches = successfulBatches;\n  }\n}\n\nexport class Pipe0TaskError extends Error {\n  constructor(\n    message: string,\n    public readonly responseBody?: unknown,\n  ) {\n    super(message);\n    this.name = \"Pipe0TaskError\";\n    this.responseBody = responseBody;\n  }\n}\n\nexport class Pipe0ServerError extends Error {\n  /** HTTP status of the error response, when known. */\n  public readonly status?: number;\n  /** RFC 7807 problem `type` discriminator (e.g. \"queue-limit-exceeded\", \"org-rate-limited\"). */\n  public readonly problemType?: string;\n\n  constructor(message: string, options: { status?: number; problemType?: string } = {}) {\n    super(message);\n    this.name = \"Pipe0ServerError\";\n    this.status = options.status;\n    this.problemType = options.problemType;\n  }\n}\n\n/**\n * Thrown only after the SDK's automatic 429 handling exhausted its wait\n * budget (`rateLimitMaxWaitMs` / `queueFullMaxWaitMs`), or immediately when\n * `autoRetry429` is disabled the error surfaces as a plain\n * {@link Pipe0ServerError} instead. Subclasses Pipe0ServerError so existing\n * handling keeps working.\n */\nexport class Pipe0RateLimitError extends Pipe0ServerError {\n  /** The delay the SDK would have waited next, in ms. */\n  public readonly retryAfterMs?: number;\n  /** Attempts made before giving up. */\n  public readonly attempts: number;\n\n  constructor(\n    message: string,\n    options: { problemType?: string; retryAfterMs?: number; attempts?: number } = {},\n  ) {\n    super(message, { status: 429, problemType: options.problemType });\n    this.name = \"Pipe0RateLimitError\";\n    this.retryAfterMs = options.retryAfterMs;\n    this.attempts = options.attempts ?? 1;\n  }\n}\n\nexport interface BatchOptions {\n  /**\n   * Callback invoked on each poll for any batch\n   */\n  onPoll?: (_batchIndex: number, _response: PipesResponse) => void;\n  /**\n   * Callback invoked when each batch completes\n   */\n  onBatchComplete?: (_batchIndex: number, _result: PipesResponse) => void;\n  /**\n   * Whether to stop all batches if one fails\n   * @default true\n   */\n  stopOnError?: boolean;\n  /**\n   * AbortSignal to cancel all batch operations\n   */\n  signal?: AbortSignal;\n  /**\n   * The worst task priority the pool will voluntarily submit at. When the\n   * next batch would land below this floor, submission waits for capacity\n   * (returned by your own runs completing) instead. `3` means only the hard\n   * ceiling paces you. @default the instance `priorityFloor` (2)\n   */\n  priorityFloor?: 1 | 2 | 3;\n  /**\n   * Cancel still-pending runs server-side when the AbortSignal fires.\n   * @default the instance `cancelOnAbort` (true)\n   */\n  cancelOnAbort?: boolean;\n}\n\nexport interface SearchAllItem {\n  /** The search payload (`search_id` + `config`), same shape as `searches.search`. */\n  search: SearchRequest[\"search\"];\n  /**\n   * Max pages to fetch for this search. Pagination is auto-detected from each\n   * response's `next_page`, so cursor- and page-number-based searches both work.\n   * @default the call-level `maxPages`\n   */\n  maxPages?: number;\n}\n\nexport interface SearchAllOptions {\n  /** Searches to run concurrently. Results are merged into one array. */\n  searches: SearchAllItem[];\n  /** Shared request config (e.g. `{ environment }`) applied to every search. */\n  config?: SearchRequest[\"config\"];\n  /**\n   * Field names to dedupe the merged results by, compared on each field's\n   * resolved `.value`. Multiple fields form a composite key; first match wins.\n   * Rows missing any key field are kept as-is (never deduped away).\n   */\n  dedupeBy?: string[];\n  /**\n   * Default max pages per search when an item doesn't set its own. Pass\n   * `Infinity` to fetch every page until the server reports no `next_page`.\n   * @default 1\n   */\n  maxPages?: number;\n  /**\n   * Normalize the merged results to a single shape: every row gets the union of\n   * all field names seen across every search, with absent fields set to `null`\n   * (e.g. so `crustdata_company_match` / `amplemarket_company_match` both exist\n   * on every row). @default true\n   */\n  normalize?: boolean;\n  /** Max searches to run at once. @default maxConcurrentBatches */\n  maxConcurrency?: number;\n  /** AbortSignal to cancel all searches. */\n  signal?: AbortSignal;\n  /**\n   * Throw on the first search error. When `false`, failed searches are collected\n   * in `errors` and partial results are returned. @default true\n   */\n  stopOnError?: boolean;\n  /**\n   * Cancel still-pending search runs server-side when the AbortSignal fires.\n   * @default the instance `cancelOnAbort` (true)\n   */\n  cancelOnAbort?: boolean;\n}\n\nexport interface SearchAllResult {\n  /** Merged (and optionally deduped) results across every search and page. */\n  results: SearchResponse[\"results\"];\n  /** Per-search failures, populated only when `stopOnError` is `false`. */\n  errors: Array<{ searchIndex: number; error: Error }>;\n}\n\nexport interface Pipe0Options {\n  apiKey?: string;\n  baseUrl?: string;\n  credentials?: RequestInit[\"credentials\"];\n  /**\n   * Default timeout for polling operations in milliseconds\n   * @default 900000 (15 minutes)\n   */\n  pollingTimeoutMs?: number;\n  /**\n   * Default polling interval in milliseconds\n   * @default 1000 (1 second)\n   */\n  minPollingIntervalMs?: number;\n  /**\n   * Maximum polling interval in milliseconds (for exponential backoff)\n   * @default 3000 (3 seconds)\n   */\n  maxPollingIntervalMs?: number;\n  /**\n   * Default batch size for large payloads\n   * @default 100\n   */\n  defaultBatchSize?: number;\n  /**\n   * Maximum number of concurrent batch requests\n   * @default 5\n   */\n  maxConcurrentBatches?: number;\n  /**\n   * Automatically absorb 429 responses: `org-rate-limited` sleeps the\n   * server's Retry-After and retries; `queue-limit-exceeded` (queued-record\n   * hard ceiling) backoff-retries the create until capacity frees. A\n   * {@link Pipe0RateLimitError} is thrown only after the wait budget below is\n   * exhausted. @default true\n   */\n  autoRetry429?: boolean;\n  /**\n   * Upper bound on a single Retry-After wait in milliseconds.\n   * @default 30000 (30 seconds)\n   */\n  retryAfterCapMs?: number;\n  /**\n   * Total wait budget for `org-rate-limited` retries per request.\n   * @default 120000 (2 minutes)\n   */\n  rateLimitMaxWaitMs?: number;\n  /**\n   * Total wait budget for `queue-limit-exceeded` retries per create.\n   * @default 900000 (15 minutes)\n   */\n  queueFullMaxWaitMs?: number;\n  /**\n   * When an AbortSignal fires while the SDK is waiting on runs, cancel the\n   * still-pending runs server-side (best-effort) so their records return to\n   * your capacity immediately. Set `false` for abort-but-keep-running\n   * semantics. @default true\n   */\n  cancelOnAbort?: boolean;\n  /**\n   * Default priority floor for `pipeInBatches`: the worst task priority the\n   * batch pool voluntarily submits at (see the X-P1/P2/P3-Capacity headers).\n   * @default 2\n   */\n  priorityFloor?: 1 | 2 | 3;\n  /**\n   * When batch submission is capacity-blocked with nothing of its own in\n   * flight (capacity held by other clients), the pool re-probes by submitting\n   * one batch after this delay — its response headers re-baseline the\n   * capacity estimate. @default 15000 (15 seconds)\n   */\n  pacingProbeMs?: number;\n  /** Observer invoked whenever fresh capacity headers are seen. */\n  onCapacity?: (snapshot: CapacitySnapshot) => void;\n  /** Custom fetch implementation (e.g. for testing). */\n  fetch?: (input: Request) => Promise<Response>;\n}\n\n// Utility type for any possible API response data shape\ntype Pipe0TaskStatusResponse = PipesResponse | SearchResponse | SheetEffectsResponse;\n\n/** The run-creating endpoints — the only responses that carry capacity headers. */\nconst CAPACITY_HEADER_PATHS = new Set([\n  \"/v1/pipes/run\",\n  \"/v1/pipes/run/sync\",\n  \"/v1/search/run\",\n  \"/v1/search/run/sync\",\n  \"/v1/searches/run\",\n  \"/v1/searches/run/sync\",\n  \"/v1/pipes/cancel/{run_id}\",\n  \"/v1/search/cancel/{run_id}\",\n]);\n\nfunction extractProblemType(error: unknown): string | undefined {\n  if (\n    error !== null &&\n    typeof error === \"object\" &&\n    \"type\" in error &&\n    typeof (error as { type: unknown }).type === \"string\"\n  ) {\n    return (error as { type: string }).type;\n  }\n  return undefined;\n}\n\nexport class Pipe0 {\n  public client: Client<paths, `${string}/${string}`>;\n  private apiKey?: string;\n\n  private pollingTimeoutMs: number;\n  private minPollingIntervalMs: number;\n  private maxPollingIntervalMs: number;\n  private defaultBatchSize: number;\n  private maxConcurrentBatches: number;\n  private autoRetry429: boolean;\n  private retryAfterCapMs: number;\n  private rateLimitMaxWaitMs: number;\n  private queueFullMaxWaitMs: number;\n  private defaultCancelOnAbort: boolean;\n  private defaultPriorityFloor: 1 | 2 | 3;\n  private pacingProbeMs: number;\n  private onCapacity?: (snapshot: CapacitySnapshot) => void;\n  private tracker = new CapacityTracker();\n\n  constructor(options: Pipe0Options = {}) {\n    // eslint-disable-next-line turbo/no-undeclared-env-vars\n    const envApiKey = typeof process !== \"undefined\" ? process.env?.PIPE0_API_KEY : undefined;\n    this.apiKey = options.apiKey ?? envApiKey;\n\n    this.pollingTimeoutMs = options.pollingTimeoutMs ?? 900000;\n    this.minPollingIntervalMs = options.minPollingIntervalMs ?? 1000;\n    this.maxPollingIntervalMs = options.maxPollingIntervalMs ?? this.minPollingIntervalMs * 3;\n    this.defaultBatchSize = options.defaultBatchSize ?? 100;\n    this.maxConcurrentBatches = options.maxConcurrentBatches ?? 5;\n    this.autoRetry429 = options.autoRetry429 ?? true;\n    this.retryAfterCapMs = options.retryAfterCapMs ?? 30_000;\n    this.rateLimitMaxWaitMs = options.rateLimitMaxWaitMs ?? 120_000;\n    this.queueFullMaxWaitMs = options.queueFullMaxWaitMs ?? 900_000;\n    this.defaultCancelOnAbort = options.cancelOnAbort ?? true;\n    this.defaultPriorityFloor = options.priorityFloor ?? 2;\n    this.pacingProbeMs = options.pacingProbeMs ?? 15_000;\n    this.onCapacity = options.onCapacity;\n\n    const headers: Record<string, string> = {};\n\n    if (this.apiKey) {\n      headers.Authorization = `Bearer ${this.apiKey}`;\n    }\n\n    this.client = createFetchClient<paths>({\n      baseUrl: options.baseUrl ?? \"https://api.pipe0.com\",\n      credentials: options.credentials\n        ? options.credentials\n        : options.baseUrl\n          ? \"same-origin\"\n          : \"include\",\n      headers,\n      fetch: options.fetch,\n    });\n\n    // Observe-only middleware: feeds the capacity tracker from response\n    // headers so even direct `pipe0.client.POST(...)` usage keeps the\n    // estimate fresh. Retrying lives in `request()` — middleware cannot\n    // re-issue a request.\n    this.client.use({\n      onResponse: ({ schemaPath, response }) => {\n        if (!CAPACITY_HEADER_PATHS.has(schemaPath)) return undefined;\n        const snapshot = this.tracker.observeHeaders(response.headers);\n        if (snapshot && this.onCapacity) {\n          try {\n            this.onCapacity(snapshot);\n          } catch {\n            // observer errors must never break requests\n          }\n        }\n        return undefined;\n      },\n    });\n  }\n\n  /**\n   * The SDK's current estimate of your organization's queue capacity, from\n   * the most recent run-creating response's headers adjusted by runs the SDK\n   * has since observed completing. Null until the first create.\n   */\n  get capacity(): CapacitySnapshot | null {\n    return this.tracker.snapshot();\n  }\n\n  /**\n   * The single request funnel: every API call goes through here so 429\n   * handling and capacity bookkeeping live in exactly one place.\n   *\n   * - `org-rate-limited` (request bucket, has Retry-After): sleep and retry,\n   *   budget `rateLimitMaxWaitMs`.\n   * - `queue-limit-exceeded` (queued-record hard ceiling, no Retry-After):\n   *   exponential backoff retry, budget `queueFullMaxWaitMs` — re-issuing the\n   *   create is safe because the ceiling rejects before anything is queued.\n   * - Anything else throws {@link Pipe0ServerError} with `status` +\n   *   `problemType` attached.\n   */\n  private async request<T>(\n    fn: () => Promise<{ data?: T; error?: unknown; response: Response }>,\n    opts: {\n      signal?: AbortSignal;\n      retry?: boolean;\n      /** Present ⇒ this is a run-creating call carrying this many records. */\n      capacity?: { records: number };\n    } = {},\n  ): Promise<T> {\n    const retryEnabled = opts.retry ?? this.autoRetry429;\n    const startedAt = Date.now();\n    let attempts = 0;\n    let queueDelayMs = 5_000;\n\n    while (true) {\n      attempts += 1;\n      // Debit BEFORE the await so concurrent submitters can't double-spend\n      // the same capacity estimate.\n      if (opts.capacity) this.tracker.onCreateIssued(opts.capacity.records);\n      let result: { data?: T; error?: unknown; response: Response };\n      try {\n        result = await fn();\n      } finally {\n        // The middleware re-baselined from headers before this runs.\n        if (opts.capacity) this.tracker.onCreateSettled(opts.capacity.records);\n      }\n\n      if (!result.error) return result.data as T;\n\n      const status = result.response?.status;\n      const problemType = extractProblemType(result.error);\n\n      if (status !== 429 || !retryEnabled) {\n        throw new Pipe0ServerError(JSON.stringify(result.error), { status, problemType });\n      }\n\n      const isQueueFull = problemType === \"queue-limit-exceeded\";\n      let delayMs: number;\n      let budgetMs: number;\n      if (isQueueFull) {\n        delayMs = queueDelayMs;\n        queueDelayMs = Math.min(queueDelayMs * 2, 60_000);\n        budgetMs = this.queueFullMaxWaitMs;\n      } else {\n        // org-rate-limited (or an unknown 429): honor Retry-After when present.\n        const retryAfterSeconds = Number(result.response.headers.get(\"Retry-After\"));\n        const baseMs =\n          Number.isFinite(retryAfterSeconds) && retryAfterSeconds > 0\n            ? retryAfterSeconds * 1000\n            : 5_000;\n        delayMs = Math.min(Math.max(baseMs, 1_000), this.retryAfterCapMs);\n        budgetMs = this.rateLimitMaxWaitMs;\n      }\n      delayMs = Math.round(delayMs * (1 + Math.random() * 0.25));\n\n      if (Date.now() - startedAt + delayMs > budgetMs) {\n        throw new Pipe0RateLimitError(\n          `Request still rate limited (${problemType ?? \"429\"}) after ${attempts} attempt(s) over ${Date.now() - startedAt}ms`,\n          { problemType, retryAfterMs: delayMs, attempts },\n        );\n      }\n      await this.sleep(delayMs, opts.signal);\n    }\n  }\n\n  /**\n   * Centralized logic to poll until a task completes, fails, or times out.\n   */\n  private async _pollUntilComplete<TResponse extends Pipe0TaskStatusResponse>(\n    runId: string | Promise<string>,\n    checkFn: (_id: string) => Promise<TResponse>,\n    taskType: \"Pipe\" | \"Search\" | \"Effects\",\n    options: {\n      onPoll?: (_response: TResponse) => unknown;\n      signal?: AbortSignal;\n      /** Cancel the run server-side (best-effort) when the signal aborts. */\n      cancelOnAbort?: boolean;\n      /** How to cancel this run remotely; absent = surface has no cancel endpoint. */\n      cancelFn?: (_id: string) => Promise<unknown>;\n    } = {},\n  ): Promise<TResponse> {\n    const resolvedRunId = await runId;\n\n    const timeout = this.pollingTimeoutMs;\n    const initialInterval = this.minPollingIntervalMs;\n    const maxInterval = this.maxPollingIntervalMs;\n    const cancelOnAbort = options.cancelOnAbort ?? this.defaultCancelOnAbort;\n    // We can hardcode backoff for simplicity since it's the only logic\n    const useBackoff = true;\n\n    const startTime = Date.now();\n    let currentInterval = initialInterval;\n\n    try {\n      while (true) {\n        if (Date.now() - startTime >= timeout) {\n          throw new Pipe0TimeoutError(\n            `${taskType} polling timed out after ${timeout}ms`,\n            resolvedRunId,\n          );\n        }\n\n        if (options.signal?.aborted) {\n          throw new Pipe0AbortError(`${taskType} polling was aborted`, resolvedRunId);\n        }\n\n        const polledResponse = await checkFn(resolvedRunId);\n\n        if (options.onPoll) {\n          await options.onPoll(polledResponse);\n        }\n\n        if (polledResponse.status === \"completed\") {\n          this.tracker.creditTerminal(resolvedRunId);\n          return polledResponse;\n        }\n\n        // Effects-only terminal states: \"skipped\" means every step was a no-op —\n        // a conclusion, not an error. \"canceled\" ends the run from the outside.\n        if (polledResponse.status === \"skipped\") {\n          this.tracker.creditTerminal(resolvedRunId);\n          return polledResponse;\n        }\n\n        if (polledResponse.status === \"canceled\") {\n          this.tracker.creditTerminal(resolvedRunId);\n          throw new Pipe0CanceledError(`${taskType} run was canceled`, resolvedRunId);\n        }\n\n        if (polledResponse.status === \"failed\") {\n          this.tracker.creditTerminal(resolvedRunId);\n          throw new Pipe0TaskError(\n            `${taskType} failed with status: ${polledResponse.status}`,\n            polledResponse,\n          );\n        }\n\n        await this.sleep(currentInterval, options.signal);\n\n        if (useBackoff) {\n          currentInterval = Math.min(currentInterval * 1.1, maxInterval);\n        }\n      }\n    } catch (error) {\n      // Abort exits (explicit check, aborted sleep, aborted fetch): the run is\n      // still pending/processing server-side — best-effort cancel it so its\n      // records return to the organization's capacity. Server-side \"canceled\"\n      // is already terminal — nothing to cancel.\n      if (\n        cancelOnAbort &&\n        options.cancelFn &&\n        options.signal?.aborted &&\n        !(error instanceof Pipe0CanceledError)\n      ) {\n        void options.cancelFn(resolvedRunId).catch(() => {});\n      }\n      throw error;\n    }\n  }\n\n  public pipes = {\n    /**\n     * Create and immediately wait for completion (convenience method)\n     */\n    pipe: async (\n      payload: PipesRequest,\n      options: {\n        onPoll?: (_response: PipesResponse) => unknown;\n        signal?: AbortSignal;\n        cancelOnAbort?: boolean;\n      } = {},\n    ): Promise<PipesResponse> => {\n      return this.pipes.waitUntilComplete(await this.pipes.create(payload, options), options);\n    },\n    /**\n     * Create a pipes task but don't wait for it. Use this method if you want to fire and forget.\n     */\n    create: async (payload: PipesRequest, options: { signal?: AbortSignal } = {}) => {\n      const records = Array.isArray(payload.input) ? payload.input.length : 1;\n      // No fetch-level signal on creates: the SDK must always learn the run id\n      // so an abort can cancel the run remotely instead of orphaning it.\n      const data = await this.request(() => this.client.POST(\"/v1/pipes/run\", { body: payload }), {\n        signal: options.signal,\n        capacity: { records },\n      });\n      this.tracker.registerRun(data.id, records);\n      return data.id;\n    },\n    /**\n     * Check the status of a pipes task manually.\n     */\n    check: async (runId: string, options: { signal?: AbortSignal } = {}) => {\n      return this.request(\n        () =>\n          this.client.GET(\"/v1/pipes/check/{run_id}\", {\n            params: { path: { run_id: runId } },\n            signal: options.signal,\n          }),\n        { signal: options.signal },\n      );\n    },\n    /**\n     * Cancel a still-pending pipes run. Its records return to your\n     * organization's capacity immediately. Runs that are already processing\n     * or finished throw a {@link Pipe0ServerError} with `status: 409`.\n     */\n    cancel: async (runId: string, options: { signal?: AbortSignal } = {}) => {\n      const data = await this.request(\n        () =>\n          this.client.POST(\"/v1/pipes/cancel/{run_id}\", {\n            params: { path: { run_id: runId } },\n            signal: options.signal,\n          }),\n        { signal: options.signal },\n      );\n      this.tracker.creditTerminal(runId);\n      return data;\n    },\n    waitUntilComplete: async (\n      runId: string | Promise<string>,\n      options: {\n        /**\n         * Callback invoked on each poll with the current status\n         */\n        onPoll?: (_response: PipesResponse) => unknown;\n        /**\n         * AbortSignal to cancel the polling operation\n         */\n        signal?: AbortSignal;\n        /**\n         * Cancel the run server-side (best-effort) when the signal aborts.\n         * @default the instance `cancelOnAbort` (true)\n         */\n        cancelOnAbort?: boolean;\n      } = {},\n    ): Promise<PipesResponse> => {\n      return this._pollUntilComplete<PipesResponse>(\n        runId,\n        (id) => this.pipes.check(id, { signal: options.signal }),\n        \"Pipe\",\n        { ...options, cancelFn: (id) => this.pipes.cancel(id) },\n      );\n    },\n    /**\n     * Process a large payload by batching the input array through a rolling\n     * pool: the next batch is submitted whenever a concurrency slot is free\n     * AND the capacity estimate says it would still be admitted at\n     * `priorityFloor` or better (see the X-P1/P2/P3-Capacity headers).\n     * @param payload - The pipe request payload with a large input array\n     * @param options - Batching options\n     * @returns Array of completed batch responses\n     */\n    pipeInBatches: async (\n      payload: PipesRequest,\n      { stopOnError = true, priorityFloor, cancelOnAbort, ...options }: BatchOptions = {},\n    ): Promise<PipesResponse[]> => {\n      const batchSize = this.defaultBatchSize;\n      const maxConcurrency = this.maxConcurrentBatches;\n      const floor = priorityFloor ?? this.defaultPriorityFloor;\n      const doCancelOnAbort = cancelOnAbort ?? this.defaultCancelOnAbort;\n\n      // Extract and validate input array\n      if (!Array.isArray(payload.input)) {\n        throw new Error(\"payload.input must be an array for batched operations\");\n      }\n\n      const inputArray = payload.input;\n\n      // Create batches\n      const batches: PipesRequest[] = [];\n      for (let i = 0; i < inputArray.length; i += batchSize) {\n        batches.push({ ...payload, input: inputArray.slice(i, i + batchSize) });\n      }\n\n      const results: (PipesResponse | undefined)[] = new Array(batches.length);\n      const errors: Array<{ batchIndex: number; error: Error }> = [];\n      const inFlight = new Set<Promise<void>>();\n      /** batchIndex → runId while the run is still cancelable. */\n      const pendingRuns = new Map<number, string>();\n      let next = 0;\n      let stopped = false;\n\n      const sweepCancel = () => {\n        if (!doCancelOnAbort) return;\n        for (const runId of pendingRuns.values()) {\n          void this.pipes.cancel(runId).catch(() => {});\n        }\n        pendingRuns.clear();\n      };\n\n      const runBatch = async (batchIndex: number) => {\n        try {\n          const runId = await this.pipes.create(batches[batchIndex]!, { signal: options.signal });\n          pendingRuns.set(batchIndex, runId);\n          const result = await this.pipes.waitUntilComplete(runId, {\n            signal: options.signal,\n            // The pool owns remote cancellation via sweepCancel — avoid\n            // duplicate cancel requests from every inner waiter.\n            cancelOnAbort: false,\n            onPoll: options.onPoll\n              ? (response) => options.onPoll!(batchIndex, response)\n              : undefined,\n          });\n          pendingRuns.delete(batchIndex);\n          results[batchIndex] = result;\n          if (options.onBatchComplete) {\n            options.onBatchComplete(batchIndex, result);\n          }\n        } catch (error) {\n          if (error instanceof Pipe0AbortError && options.signal?.aborted) {\n            // Aborted mid-run: keep the pendingRuns entry — the sweep cancels\n            // it — and don't record abort noise as a batch failure.\n            return;\n          }\n          pendingRuns.delete(batchIndex);\n          errors.push({\n            batchIndex,\n            error: error instanceof Error ? error : new Error(String(error)),\n          });\n          if (stopOnError) stopped = true;\n        }\n      };\n\n      const submit = (batchIndex: number) => {\n        const p: Promise<void> = runBatch(batchIndex).finally(() => inFlight.delete(p));\n        inFlight.add(p);\n      };\n\n      try {\n        while ((next < batches.length && !stopped) || inFlight.size > 0) {\n          if (options.signal?.aborted) {\n            throw new Pipe0AbortError(\"Batch operation was aborted\");\n          }\n\n          if (!stopped && next < batches.length && inFlight.size < maxConcurrency) {\n            const records = (batches[next]!.input as unknown[]).length;\n            const estimate = this.tracker.estimate(floor);\n            if (estimate === null || estimate >= records) {\n              submit(next++);\n              continue; // greedily fill remaining slots\n            }\n            if (inFlight.size === 0) {\n              // Capacity is held by other clients and nothing of ours is in\n              // flight to wait on — timed probe: submit one batch regardless;\n              // its response headers re-baseline the estimate. A bounded,\n              // self-correcting floor violation.\n              await this.sleep(this.pacingProbeMs, options.signal);\n              if (options.signal?.aborted) {\n                throw new Pipe0AbortError(\"Batch operation was aborted\");\n              }\n              submit(next++);\n              continue;\n            }\n          }\n\n          if (inFlight.size > 0) {\n            // runBatch never rejects, so race only ever observes settles.\n            await Promise.race(inFlight);\n          }\n        }\n      } catch (error) {\n        sweepCancel();\n        throw error;\n      }\n\n      const compact = results.filter((r): r is PipesResponse => r !== undefined);\n\n      if (stopped) {\n        throw new Pipe0BatchError(\n          `Batch ${errors[0]?.batchIndex} failed and stopOnError is enabled`,\n          errors,\n          compact,\n        );\n      }\n      if (errors.length > 0) {\n        throw new Pipe0BatchError(\n          `${errors.length} batch(es) failed out of ${batches.length} total`,\n          errors,\n          compact,\n        );\n      }\n\n      return compact;\n    },\n  };\n\n  searches = {\n    /**\n     * Create and immediately wait for completion (convenience method)\n     */\n    search: async (\n      payload: SearchRequest,\n      options: {\n        onPoll?: (_response: SearchResponse) => unknown;\n        signal?: AbortSignal;\n        cancelOnAbort?: boolean;\n      } = {},\n    ): Promise<SearchResponse> => {\n      return this.searches.waitUntilComplete(await this.searches.create(payload, options), options);\n    },\n\n    /**\n     * Create a searches task but don't wait for it.\n     * Use this if you want fire and forget.\n     */\n    create: async (payload: SearchRequest, options: { signal?: AbortSignal } = {}) => {\n      // One search = one queued record, regardless of result count.\n      const data = await this.request(() => this.client.POST(\"/v1/search/run\", { body: payload }), {\n        signal: options.signal,\n        capacity: { records: 1 },\n      });\n      this.tracker.registerRun(data.id, 1);\n      return data.id;\n    },\n\n    /**\n     * Check the status of a search task manually.\n     */\n    check: async (runId: string, options: { signal?: AbortSignal } = {}) => {\n      return this.request(\n        () =>\n          this.client.GET(\"/v1/search/check/{run_id}\", {\n            params: { path: { run_id: runId } },\n            signal: options.signal,\n          }),\n        { signal: options.signal },\n      );\n    },\n\n    /**\n     * Cancel a still-pending search run. It returns to your organization's\n     * capacity immediately. Runs that are already processing or finished\n     * throw a {@link Pipe0ServerError} with `status: 409`.\n     */\n    cancel: async (runId: string, options: { signal?: AbortSignal } = {}) => {\n      const data = await this.request(\n        () =>\n          this.client.POST(\"/v1/search/cancel/{run_id}\", {\n            params: { path: { run_id: runId } },\n            signal: options.signal,\n          }),\n        { signal: options.signal },\n      );\n      this.tracker.creditTerminal(runId);\n      return data;\n    },\n\n    /**\n     * Poll until the search completes or fails.\n     */\n    waitUntilComplete: async (\n      runId: string | Promise<string>,\n      options: {\n        onPoll?: (_response: SearchResponse) => unknown;\n        signal?: AbortSignal;\n        /**\n         * Cancel the run server-side (best-effort) when the signal aborts.\n         * @default the instance `cancelOnAbort` (true)\n         */\n        cancelOnAbort?: boolean;\n      } = {},\n    ): Promise<SearchResponse> => {\n      return this._pollUntilComplete<SearchResponse>(\n        runId,\n        (id) => this.searches.check(id, { signal: options.signal }),\n        \"Search\",\n        { ...options, cancelFn: (id) => this.searches.cancel(id) },\n      );\n    },\n\n    /**\n     * Run several searches concurrently, auto-paginate each, and return one merged\n     * (optionally deduped) result set. Pagination is detected from each response's\n     * `next_page` token — which is itself a ready-to-send payload — so cursor- and\n     * page-number-based searches are handled transparently.\n     *\n     * @example\n     * const { results } = await pipe0.searches.searchAll({\n     *   config: { environment: \"production\" },\n     *   dedupeBy: [\"company_domain\"],\n     *   maxPages: 3,\n     *   searches: [\n     *     { search: { search_id: \"companies:profiles:crustdata@2\", config: { filters } } },\n     *     { search: { search_id: \"companies:profiles:amplemarket@2\", config: { filters } } },\n     *   ],\n     * });\n     */\n    searchAll: async ({\n      searches,\n      config,\n      dedupeBy,\n      maxPages = 1,\n      normalize = true,\n      maxConcurrency = this.maxConcurrentBatches,\n      signal,\n      stopOnError = true,\n      cancelOnAbort,\n    }: SearchAllOptions): Promise<SearchAllResult> => {\n      const errors: SearchAllResult[\"errors\"] = [];\n      const merged: SearchResponse[\"results\"] = [];\n\n      const runItem = async (item: SearchAllItem): Promise<SearchResponse[\"results\"]> => {\n        const rows: SearchResponse[\"results\"] = [];\n        let search = item.search;\n        const pages = item.maxPages ?? maxPages;\n        for (let page = 0; page < pages; page++) {\n          if (signal?.aborted) throw new Pipe0AbortError(\"searchAll was aborted\");\n          const res = await this.searches.search({ config, search }, { signal, cancelOnAbort });\n          rows.push(...res.results);\n          // `next_page` is a complete, re-sendable payload (original filters +\n          // output_fields with only the cursor/page_number advanced), so we send\n          // it verbatim — no need to know which pagination style the search uses.\n          const next = res.next_page as SearchRequest[\"search\"] | null;\n          if (!next) break;\n          search = next;\n        }\n        return rows;\n      };\n\n      for (let i = 0; i < searches.length; i += maxConcurrency) {\n        if (signal?.aborted) throw new Pipe0AbortError(\"searchAll was aborted\");\n        const group = searches.slice(i, i + maxConcurrency);\n        const settled = await Promise.all(\n          group.map(async (item, groupIndex) => {\n            try {\n              return await runItem(item);\n            } catch (err) {\n              const error = err instanceof Error ? err : new Error(String(err));\n              errors.push({ searchIndex: i + groupIndex, error });\n              if (stopOnError) throw error;\n              return [] as SearchResponse[\"results\"];\n            }\n          }),\n        );\n        for (const rows of settled) merged.push(...rows);\n      }\n\n      const deduped = dedupeBy?.length ? dedupeResults(merged, dedupeBy) : merged;\n      return {\n        results: normalize ? normalizeResults(deduped) : deduped,\n        errors,\n      };\n    },\n  };\n\n  sheets = {\n    effects: {\n      /**\n       * Start an effects run on a sheet and return as soon as the server has\n       * accepted it — the effects themselves keep running server-side, so the\n       * returned run is normally still `processing`. This is the fire-and-forget\n       * entry point; poll with `check` / `waitUntilComplete` only if you care\n       * about the outcome.\n       *\n       * @example\n       * await pipe0.sheets.effects.run(sheetId, {\n       *   config: { run_added_rows: true },\n       *   effects: [\n       *     {\n       *       effect_id: \"rows:add@1\",\n       *       connector: null,\n       *       config: { input: [{ email: \"ada@example.com\" }], allow_field_creation: false },\n       *     },\n       *   ],\n       * });\n       */\n      run: async (sheetId: string, payload: SheetEffectsRequest): Promise<SheetEffectsResponse> => {\n        return this.request(() =>\n          this.client.POST(\"/v1/sheets/{sheet_id}/effects/run\", {\n            params: { path: { sheet_id: sheetId } },\n            body: payload,\n          }),\n        );\n      },\n\n      /**\n       * Check the status of an effects run manually.\n       */\n      check: async (\n        sheetId: string,\n        runId: string,\n        options: { signal?: AbortSignal } = {},\n      ): Promise<SheetEffectsResponse> => {\n        return this.request(\n          () =>\n            this.client.GET(\"/v1/sheets/{sheet_id}/effects/check/{run_id}\", {\n              params: { path: { sheet_id: sheetId, run_id: runId } },\n              signal: options.signal,\n            }),\n          { signal: options.signal },\n        );\n      },\n\n      /**\n       * Poll until the effects run concludes (`completed` / `skipped`), fails,\n       * or is canceled.\n       */\n      waitUntilComplete: async (\n        sheetId: string,\n        runId: string | Promise<string>,\n        options: {\n          onPoll?: (_response: SheetEffectsResponse) => unknown;\n          signal?: AbortSignal;\n        } = {},\n      ): Promise<SheetEffectsResponse> => {\n        return this._pollUntilComplete<SheetEffectsResponse>(\n          runId,\n          (id) => this.sheets.effects.check(sheetId, id, { signal: options.signal }),\n          \"Effects\",\n          // No task-level cancel endpoint for effects runs — no cancelFn.\n          options,\n        );\n      },\n\n      /**\n       * Run the effects and wait for the run to conclude (convenience method).\n       */\n      runUntilComplete: async (\n        sheetId: string,\n        payload: SheetEffectsRequest,\n        options: {\n          onPoll?: (_response: SheetEffectsResponse) => unknown;\n          signal?: AbortSignal;\n        } = {},\n      ): Promise<SheetEffectsResponse> => {\n        const { id } = await this.sheets.effects.run(sheetId, payload);\n        return this.sheets.effects.waitUntilComplete(sheetId, id, options);\n      },\n    },\n  };\n\n  private sleep(ms: number, signal?: AbortSignal): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const timeout = setTimeout(resolve, ms);\n\n      if (signal) {\n        const onAbort = () => {\n          clearTimeout(timeout);\n          reject(new Pipe0AbortError(\"Sleep was aborted\"));\n        };\n\n        if (signal.aborted) {\n          clearTimeout(timeout);\n          reject(new Pipe0AbortError(\"Sleep was aborted\"));\n          return;\n        }\n\n        signal.addEventListener(\"abort\", onAbort, { once: true });\n      }\n    });\n  }\n}\n\n/**\n * Dedupe search-result rows by the resolved `.value` of one or more fields.\n * First occurrence wins; rows missing any key field are kept (can't be deduped).\n */\nfunction dedupeResults(\n  rows: SearchResponse[\"results\"],\n  fields: string[],\n): SearchResponse[\"results\"] {\n  const seen = new Set<string>();\n  const out: SearchResponse[\"results\"] = [];\n  for (const row of rows) {\n    const cells = row as Record<string, { value?: unknown } | null>;\n    const parts: string[] = [];\n    let keyable = true;\n    for (const field of fields) {\n      const cell = cells[field];\n      if (cell == null || cell.value == null) {\n        keyable = false;\n        break;\n      }\n      parts.push(JSON.stringify(cell.value));\n    }\n    if (!keyable) {\n      out.push(row);\n      continue;\n    }\n    const key = parts.join(\" \");\n    if (seen.has(key)) continue;\n    seen.add(key);\n    out.push(row);\n  }\n  return out;\n}\n\n/**\n * Normalize merged rows to a uniform shape: every row gains the union of all\n * field names seen across the set, with absent fields set to `null`. A field\n * already present (even if its value is null) is left untouched.\n */\nfunction normalizeResults(rows: SearchResponse[\"results\"]): SearchResponse[\"results\"] {\n  const keys = new Set<string>();\n  for (const row of rows) {\n    for (const key of Object.keys(row)) keys.add(key);\n  }\n  return rows.map((row) => {\n    const source = row as Record<string, unknown>;\n    const out: Record<string, unknown> = {};\n    for (const key of keys) {\n      out[key] = key in source ? source[key] : null;\n    }\n    return out as SearchResponse[\"results\"][number];\n  });\n}\n"],"mappings":";;;;AAwBA,IAAa,oBAAb,cAAuC,MAAM;CAC3C,YACE,SACA,AAAgB,OAChB;AACA,QAAM,QAAQ;EAFE;AAGhB,OAAK,OAAO;AACZ,OAAK,QAAQ;;;AAIjB,IAAa,kBAAb,cAAqC,MAAM;CACzC,YACE,SACA,AAAgB,OAChB;AACA,QAAM,QAAQ;EAFE;AAGhB,OAAK,OAAO;AACZ,OAAK,QAAQ;;;;;;;;AASjB,IAAa,qBAAb,cAAwC,gBAAgB;CACtD,YAAY,SAAiB,OAAgB;AAC3C,QAAM,SAAS,MAAM;AACrB,OAAK,OAAO;;;AAIhB,IAAa,kBAAb,cAAqC,MAAM;CACzC,YACE,SACA,AAAgB,QAChB,AAAgB,mBAChB;AACA,QAAM,QAAQ;EAHE;EACA;AAGhB,OAAK,OAAO;AACZ,OAAK,SAAS;AACd,OAAK,oBAAoB;;;AAI7B,IAAa,iBAAb,cAAoC,MAAM;CACxC,YACE,SACA,AAAgB,cAChB;AACA,QAAM,QAAQ;EAFE;AAGhB,OAAK,OAAO;AACZ,OAAK,eAAe;;;AAIxB,IAAa,mBAAb,cAAsC,MAAM;;CAE1C,AAAgB;;CAEhB,AAAgB;CAEhB,YAAY,SAAiB,UAAqD,EAAE,EAAE;AACpF,QAAM,QAAQ;AACd,OAAK,OAAO;AACZ,OAAK,SAAS,QAAQ;AACtB,OAAK,cAAc,QAAQ;;;;;;;;;;AAW/B,IAAa,sBAAb,cAAyC,iBAAiB;;CAExD,AAAgB;;CAEhB,AAAgB;CAEhB,YACE,SACA,UAA8E,EAAE,EAChF;AACA,QAAM,SAAS;GAAE,QAAQ;GAAK,aAAa,QAAQ;GAAa,CAAC;AACjE,OAAK,OAAO;AACZ,OAAK,eAAe,QAAQ;AAC5B,OAAK,WAAW,QAAQ,YAAY;;;;AAgLxC,MAAM,wBAAwB,IAAI,IAAI;CACpC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,SAAS,mBAAmB,OAAoC;AAC9D,KACE,UAAU,QACV,OAAO,UAAU,YACjB,UAAU,SACV,OAAQ,MAA4B,SAAS,SAE7C,QAAQ,MAA2B;;AAKvC,IAAa,QAAb,MAAmB;CACjB,AAAO;CACP,AAAQ;CAER,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ,UAAU,IAAI,iBAAiB;CAEvC,YAAY,UAAwB,EAAE,EAAE;EAEtC,MAAM,YAAY,OAAO,YAAY,cAAc,QAAQ,KAAK,gBAAgB;AAChF,OAAK,SAAS,QAAQ,UAAU;AAEhC,OAAK,mBAAmB,QAAQ,oBAAoB;AACpD,OAAK,uBAAuB,QAAQ,wBAAwB;AAC5D,OAAK,uBAAuB,QAAQ,wBAAwB,KAAK,uBAAuB;AACxF,OAAK,mBAAmB,QAAQ,oBAAoB;AACpD,OAAK,uBAAuB,QAAQ,wBAAwB;AAC5D,OAAK,eAAe,QAAQ,gBAAgB;AAC5C,OAAK,kBAAkB,QAAQ,mBAAmB;AAClD,OAAK,qBAAqB,QAAQ,sBAAsB;AACxD,OAAK,qBAAqB,QAAQ,sBAAsB;AACxD,OAAK,uBAAuB,QAAQ,iBAAiB;AACrD,OAAK,uBAAuB,QAAQ,iBAAiB;AACrD,OAAK,gBAAgB,QAAQ,iBAAiB;AAC9C,OAAK,aAAa,QAAQ;EAE1B,MAAM,UAAkC,EAAE;AAE1C,MAAI,KAAK,OACP,SAAQ,gBAAgB,UAAU,KAAK;AAGzC,OAAK,SAAS,kBAAyB;GACrC,SAAS,QAAQ,WAAW;GAC5B,aAAa,QAAQ,cACjB,QAAQ,cACR,QAAQ,UACN,gBACA;GACN;GACA,OAAO,QAAQ;GAChB,CAAC;AAMF,OAAK,OAAO,IAAI,EACd,aAAa,EAAE,YAAY,eAAe;AACxC,OAAI,CAAC,sBAAsB,IAAI,WAAW,CAAE,QAAO;GACnD,MAAM,WAAW,KAAK,QAAQ,eAAe,SAAS,QAAQ;AAC9D,OAAI,YAAY,KAAK,WACnB,KAAI;AACF,SAAK,WAAW,SAAS;WACnB;KAMb,CAAC;;;;;;;CAQJ,IAAI,WAAoC;AACtC,SAAO,KAAK,QAAQ,UAAU;;;;;;;;;;;;;;CAehC,MAAc,QACZ,IACA,OAKI,EAAE,EACM;EACZ,MAAM,eAAe,KAAK,SAAS,KAAK;EACxC,MAAM,YAAY,KAAK,KAAK;EAC5B,IAAI,WAAW;EACf,IAAI,eAAe;AAEnB,SAAO,MAAM;AACX,eAAY;AAGZ,OAAI,KAAK,SAAU,MAAK,QAAQ,eAAe,KAAK,SAAS,QAAQ;GACrE,IAAI;AACJ,OAAI;AACF,aAAS,MAAM,IAAI;aACX;AAER,QAAI,KAAK,SAAU,MAAK,QAAQ,gBAAgB,KAAK,SAAS,QAAQ;;AAGxE,OAAI,CAAC,OAAO,MAAO,QAAO,OAAO;GAEjC,MAAM,SAAS,OAAO,UAAU;GAChC,MAAM,cAAc,mBAAmB,OAAO,MAAM;AAEpD,OAAI,WAAW,OAAO,CAAC,aACrB,OAAM,IAAI,iBAAiB,KAAK,UAAU,OAAO,MAAM,EAAE;IAAE;IAAQ;IAAa,CAAC;GAGnF,MAAM,cAAc,gBAAgB;GACpC,IAAI;GACJ,IAAI;AACJ,OAAI,aAAa;AACf,cAAU;AACV,mBAAe,KAAK,IAAI,eAAe,GAAG,IAAO;AACjD,eAAW,KAAK;UACX;IAEL,MAAM,oBAAoB,OAAO,OAAO,SAAS,QAAQ,IAAI,cAAc,CAAC;IAC5E,MAAM,SACJ,OAAO,SAAS,kBAAkB,IAAI,oBAAoB,IACtD,oBAAoB,MACpB;AACN,cAAU,KAAK,IAAI,KAAK,IAAI,QAAQ,IAAM,EAAE,KAAK,gBAAgB;AACjE,eAAW,KAAK;;AAElB,aAAU,KAAK,MAAM,WAAW,IAAI,KAAK,QAAQ,GAAG,KAAM;AAE1D,OAAI,KAAK,KAAK,GAAG,YAAY,UAAU,SACrC,OAAM,IAAI,oBACR,+BAA+B,eAAe,MAAM,UAAU,SAAS,mBAAmB,KAAK,KAAK,GAAG,UAAU,KACjH;IAAE;IAAa,cAAc;IAAS;IAAU,CACjD;AAEH,SAAM,KAAK,MAAM,SAAS,KAAK,OAAO;;;;;;CAO1C,MAAc,mBACZ,OACA,SACA,UACA,UAOI,EAAE,EACc;EACpB,MAAM,gBAAgB,MAAM;EAE5B,MAAM,UAAU,KAAK;EACrB,MAAM,kBAAkB,KAAK;EAC7B,MAAM,cAAc,KAAK;EACzB,MAAM,gBAAgB,QAAQ,iBAAiB,KAAK;EAIpD,MAAM,YAAY,KAAK,KAAK;EAC5B,IAAI,kBAAkB;AAEtB,MAAI;AACF,UAAO,MAAM;AACX,QAAI,KAAK,KAAK,GAAG,aAAa,QAC5B,OAAM,IAAI,kBACR,GAAG,SAAS,2BAA2B,QAAQ,KAC/C,cACD;AAGH,QAAI,QAAQ,QAAQ,QAClB,OAAM,IAAI,gBAAgB,GAAG,SAAS,uBAAuB,cAAc;IAG7E,MAAM,iBAAiB,MAAM,QAAQ,cAAc;AAEnD,QAAI,QAAQ,OACV,OAAM,QAAQ,OAAO,eAAe;AAGtC,QAAI,eAAe,WAAW,aAAa;AACzC,UAAK,QAAQ,eAAe,cAAc;AAC1C,YAAO;;AAKT,QAAI,eAAe,WAAW,WAAW;AACvC,UAAK,QAAQ,eAAe,cAAc;AAC1C,YAAO;;AAGT,QAAI,eAAe,WAAW,YAAY;AACxC,UAAK,QAAQ,eAAe,cAAc;AAC1C,WAAM,IAAI,mBAAmB,GAAG,SAAS,oBAAoB,cAAc;;AAG7E,QAAI,eAAe,WAAW,UAAU;AACtC,UAAK,QAAQ,eAAe,cAAc;AAC1C,WAAM,IAAI,eACR,GAAG,SAAS,uBAAuB,eAAe,UAClD,eACD;;AAGH,UAAM,KAAK,MAAM,iBAAiB,QAAQ,OAAO;AAG/C,sBAAkB,KAAK,IAAI,kBAAkB,KAAK,YAAY;;WAG3D,OAAO;AAKd,OACE,iBACA,QAAQ,YACR,QAAQ,QAAQ,WAChB,EAAE,iBAAiB,oBAEnB,CAAK,QAAQ,SAAS,cAAc,CAAC,YAAY,GAAG;AAEtD,SAAM;;;CAIV,AAAO,QAAQ;EAIb,MAAM,OACJ,SACA,UAII,EAAE,KACqB;AAC3B,UAAO,KAAK,MAAM,kBAAkB,MAAM,KAAK,MAAM,OAAO,SAAS,QAAQ,EAAE,QAAQ;;EAKzF,QAAQ,OAAO,SAAuB,UAAoC,EAAE,KAAK;GAC/E,MAAM,UAAU,MAAM,QAAQ,QAAQ,MAAM,GAAG,QAAQ,MAAM,SAAS;GAGtE,MAAM,OAAO,MAAM,KAAK,cAAc,KAAK,OAAO,KAAK,iBAAiB,EAAE,MAAM,SAAS,CAAC,EAAE;IAC1F,QAAQ,QAAQ;IAChB,UAAU,EAAE,SAAS;IACtB,CAAC;AACF,QAAK,QAAQ,YAAY,KAAK,IAAI,QAAQ;AAC1C,UAAO,KAAK;;EAKd,OAAO,OAAO,OAAe,UAAoC,EAAE,KAAK;AACtE,UAAO,KAAK,cAER,KAAK,OAAO,IAAI,4BAA4B;IAC1C,QAAQ,EAAE,MAAM,EAAE,QAAQ,OAAO,EAAE;IACnC,QAAQ,QAAQ;IACjB,CAAC,EACJ,EAAE,QAAQ,QAAQ,QAAQ,CAC3B;;EAOH,QAAQ,OAAO,OAAe,UAAoC,EAAE,KAAK;GACvE,MAAM,OAAO,MAAM,KAAK,cAEpB,KAAK,OAAO,KAAK,6BAA6B;IAC5C,QAAQ,EAAE,MAAM,EAAE,QAAQ,OAAO,EAAE;IACnC,QAAQ,QAAQ;IACjB,CAAC,EACJ,EAAE,QAAQ,QAAQ,QAAQ,CAC3B;AACD,QAAK,QAAQ,eAAe,MAAM;AAClC,UAAO;;EAET,mBAAmB,OACjB,OACA,UAcI,EAAE,KACqB;AAC3B,UAAO,KAAK,mBACV,QACC,OAAO,KAAK,MAAM,MAAM,IAAI,EAAE,QAAQ,QAAQ,QAAQ,CAAC,EACxD,QACA;IAAE,GAAG;IAAS,WAAW,OAAO,KAAK,MAAM,OAAO,GAAG;IAAE,CACxD;;EAWH,eAAe,OACb,SACA,EAAE,cAAc,MAAM,eAAe,eAAe,GAAG,YAA0B,EAAE,KACtD;GAC7B,MAAM,YAAY,KAAK;GACvB,MAAM,iBAAiB,KAAK;GAC5B,MAAM,QAAQ,iBAAiB,KAAK;GACpC,MAAM,kBAAkB,iBAAiB,KAAK;AAG9C,OAAI,CAAC,MAAM,QAAQ,QAAQ,MAAM,CAC/B,OAAM,IAAI,MAAM,wDAAwD;GAG1E,MAAM,aAAa,QAAQ;GAG3B,MAAM,UAA0B,EAAE;AAClC,QAAK,IAAI,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK,UAC1C,SAAQ,KAAK;IAAE,GAAG;IAAS,OAAO,WAAW,MAAM,GAAG,IAAI,UAAU;IAAE,CAAC;GAGzE,MAAM,UAAyC,IAAI,MAAM,QAAQ,OAAO;GACxE,MAAM,SAAsD,EAAE;GAC9D,MAAM,2BAAW,IAAI,KAAoB;;GAEzC,MAAM,8BAAc,IAAI,KAAqB;GAC7C,IAAI,OAAO;GACX,IAAI,UAAU;GAEd,MAAM,oBAAoB;AACxB,QAAI,CAAC,gBAAiB;AACtB,SAAK,MAAM,SAAS,YAAY,QAAQ,CACtC,CAAK,KAAK,MAAM,OAAO,MAAM,CAAC,YAAY,GAAG;AAE/C,gBAAY,OAAO;;GAGrB,MAAM,WAAW,OAAO,eAAuB;AAC7C,QAAI;KACF,MAAM,QAAQ,MAAM,KAAK,MAAM,OAAO,QAAQ,aAAc,EAAE,QAAQ,QAAQ,QAAQ,CAAC;AACvF,iBAAY,IAAI,YAAY,MAAM;KAClC,MAAM,SAAS,MAAM,KAAK,MAAM,kBAAkB,OAAO;MACvD,QAAQ,QAAQ;MAGhB,eAAe;MACf,QAAQ,QAAQ,UACX,aAAa,QAAQ,OAAQ,YAAY,SAAS,GACnD;MACL,CAAC;AACF,iBAAY,OAAO,WAAW;AAC9B,aAAQ,cAAc;AACtB,SAAI,QAAQ,gBACV,SAAQ,gBAAgB,YAAY,OAAO;aAEtC,OAAO;AACd,SAAI,iBAAiB,mBAAmB,QAAQ,QAAQ,QAGtD;AAEF,iBAAY,OAAO,WAAW;AAC9B,YAAO,KAAK;MACV;MACA,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC;MACjE,CAAC;AACF,SAAI,YAAa,WAAU;;;GAI/B,MAAM,UAAU,eAAuB;IACrC,MAAM,IAAmB,SAAS,WAAW,CAAC,cAAc,SAAS,OAAO,EAAE,CAAC;AAC/E,aAAS,IAAI,EAAE;;AAGjB,OAAI;AACF,WAAQ,OAAO,QAAQ,UAAU,CAAC,WAAY,SAAS,OAAO,GAAG;AAC/D,SAAI,QAAQ,QAAQ,QAClB,OAAM,IAAI,gBAAgB,8BAA8B;AAG1D,SAAI,CAAC,WAAW,OAAO,QAAQ,UAAU,SAAS,OAAO,gBAAgB;MACvE,MAAM,UAAW,QAAQ,MAAO,MAAoB;MACpD,MAAM,WAAW,KAAK,QAAQ,SAAS,MAAM;AAC7C,UAAI,aAAa,QAAQ,YAAY,SAAS;AAC5C,cAAO,OAAO;AACd;;AAEF,UAAI,SAAS,SAAS,GAAG;AAKvB,aAAM,KAAK,MAAM,KAAK,eAAe,QAAQ,OAAO;AACpD,WAAI,QAAQ,QAAQ,QAClB,OAAM,IAAI,gBAAgB,8BAA8B;AAE1D,cAAO,OAAO;AACd;;;AAIJ,SAAI,SAAS,OAAO,EAElB,OAAM,QAAQ,KAAK,SAAS;;YAGzB,OAAO;AACd,iBAAa;AACb,UAAM;;GAGR,MAAM,UAAU,QAAQ,QAAQ,MAA0B,MAAM,OAAU;AAE1E,OAAI,QACF,OAAM,IAAI,gBACR,SAAS,OAAO,IAAI,WAAW,qCAC/B,QACA,QACD;AAEH,OAAI,OAAO,SAAS,EAClB,OAAM,IAAI,gBACR,GAAG,OAAO,OAAO,2BAA2B,QAAQ,OAAO,SAC3D,QACA,QACD;AAGH,UAAO;;EAEV;CAED,WAAW;EAIT,QAAQ,OACN,SACA,UAII,EAAE,KACsB;AAC5B,UAAO,KAAK,SAAS,kBAAkB,MAAM,KAAK,SAAS,OAAO,SAAS,QAAQ,EAAE,QAAQ;;EAO/F,QAAQ,OAAO,SAAwB,UAAoC,EAAE,KAAK;GAEhF,MAAM,OAAO,MAAM,KAAK,cAAc,KAAK,OAAO,KAAK,kBAAkB,EAAE,MAAM,SAAS,CAAC,EAAE;IAC3F,QAAQ,QAAQ;IAChB,UAAU,EAAE,SAAS,GAAG;IACzB,CAAC;AACF,QAAK,QAAQ,YAAY,KAAK,IAAI,EAAE;AACpC,UAAO,KAAK;;EAMd,OAAO,OAAO,OAAe,UAAoC,EAAE,KAAK;AACtE,UAAO,KAAK,cAER,KAAK,OAAO,IAAI,6BAA6B;IAC3C,QAAQ,EAAE,MAAM,EAAE,QAAQ,OAAO,EAAE;IACnC,QAAQ,QAAQ;IACjB,CAAC,EACJ,EAAE,QAAQ,QAAQ,QAAQ,CAC3B;;EAQH,QAAQ,OAAO,OAAe,UAAoC,EAAE,KAAK;GACvE,MAAM,OAAO,MAAM,KAAK,cAEpB,KAAK,OAAO,KAAK,8BAA8B;IAC7C,QAAQ,EAAE,MAAM,EAAE,QAAQ,OAAO,EAAE;IACnC,QAAQ,QAAQ;IACjB,CAAC,EACJ,EAAE,QAAQ,QAAQ,QAAQ,CAC3B;AACD,QAAK,QAAQ,eAAe,MAAM;AAClC,UAAO;;EAMT,mBAAmB,OACjB,OACA,UAQI,EAAE,KACsB;AAC5B,UAAO,KAAK,mBACV,QACC,OAAO,KAAK,SAAS,MAAM,IAAI,EAAE,QAAQ,QAAQ,QAAQ,CAAC,EAC3D,UACA;IAAE,GAAG;IAAS,WAAW,OAAO,KAAK,SAAS,OAAO,GAAG;IAAE,CAC3D;;EAoBH,WAAW,OAAO,EAChB,UACA,QACA,UACA,WAAW,GACX,YAAY,MACZ,iBAAiB,KAAK,sBACtB,QACA,cAAc,MACd,oBACgD;GAChD,MAAM,SAAoC,EAAE;GAC5C,MAAM,SAAoC,EAAE;GAE5C,MAAM,UAAU,OAAO,SAA4D;IACjF,MAAM,OAAkC,EAAE;IAC1C,IAAI,SAAS,KAAK;IAClB,MAAM,QAAQ,KAAK,YAAY;AAC/B,SAAK,IAAI,OAAO,GAAG,OAAO,OAAO,QAAQ;AACvC,SAAI,QAAQ,QAAS,OAAM,IAAI,gBAAgB,wBAAwB;KACvE,MAAM,MAAM,MAAM,KAAK,SAAS,OAAO;MAAE;MAAQ;MAAQ,EAAE;MAAE;MAAQ;MAAe,CAAC;AACrF,UAAK,KAAK,GAAG,IAAI,QAAQ;KAIzB,MAAM,OAAO,IAAI;AACjB,SAAI,CAAC,KAAM;AACX,cAAS;;AAEX,WAAO;;AAGT,QAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK,gBAAgB;AACxD,QAAI,QAAQ,QAAS,OAAM,IAAI,gBAAgB,wBAAwB;IACvE,MAAM,QAAQ,SAAS,MAAM,GAAG,IAAI,eAAe;IACnD,MAAM,UAAU,MAAM,QAAQ,IAC5B,MAAM,IAAI,OAAO,MAAM,eAAe;AACpC,SAAI;AACF,aAAO,MAAM,QAAQ,KAAK;cACnB,KAAK;MACZ,MAAM,QAAQ,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC;AACjE,aAAO,KAAK;OAAE,aAAa,IAAI;OAAY;OAAO,CAAC;AACnD,UAAI,YAAa,OAAM;AACvB,aAAO,EAAE;;MAEX,CACH;AACD,SAAK,MAAM,QAAQ,QAAS,QAAO,KAAK,GAAG,KAAK;;GAGlD,MAAM,UAAU,UAAU,SAAS,cAAc,QAAQ,SAAS,GAAG;AACrE,UAAO;IACL,SAAS,YAAY,iBAAiB,QAAQ,GAAG;IACjD;IACD;;EAEJ;CAED,SAAS,EACP,SAAS;EAoBP,KAAK,OAAO,SAAiB,YAAgE;AAC3F,UAAO,KAAK,cACV,KAAK,OAAO,KAAK,qCAAqC;IACpD,QAAQ,EAAE,MAAM,EAAE,UAAU,SAAS,EAAE;IACvC,MAAM;IACP,CAAC,CACH;;EAMH,OAAO,OACL,SACA,OACA,UAAoC,EAAE,KACJ;AAClC,UAAO,KAAK,cAER,KAAK,OAAO,IAAI,gDAAgD;IAC9D,QAAQ,EAAE,MAAM;KAAE,UAAU;KAAS,QAAQ;KAAO,EAAE;IACtD,QAAQ,QAAQ;IACjB,CAAC,EACJ,EAAE,QAAQ,QAAQ,QAAQ,CAC3B;;EAOH,mBAAmB,OACjB,SACA,OACA,UAGI,EAAE,KAC4B;AAClC,UAAO,KAAK,mBACV,QACC,OAAO,KAAK,OAAO,QAAQ,MAAM,SAAS,IAAI,EAAE,QAAQ,QAAQ,QAAQ,CAAC,EAC1E,WAEA,QACD;;EAMH,kBAAkB,OAChB,SACA,SACA,UAGI,EAAE,KAC4B;GAClC,MAAM,EAAE,OAAO,MAAM,KAAK,OAAO,QAAQ,IAAI,SAAS,QAAQ;AAC9D,UAAO,KAAK,OAAO,QAAQ,kBAAkB,SAAS,IAAI,QAAQ;;EAErE,EACF;CAED,AAAQ,MAAM,IAAY,QAAqC;AAC7D,SAAO,IAAI,SAAS,SAAS,WAAW;GACtC,MAAM,UAAU,WAAW,SAAS,GAAG;AAEvC,OAAI,QAAQ;IACV,MAAM,gBAAgB;AACpB,kBAAa,QAAQ;AACrB,YAAO,IAAI,gBAAgB,oBAAoB,CAAC;;AAGlD,QAAI,OAAO,SAAS;AAClB,kBAAa,QAAQ;AACrB,YAAO,IAAI,gBAAgB,oBAAoB,CAAC;AAChD;;AAGF,WAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,MAAM,CAAC;;IAE3D;;;;;;;AAQN,SAAS,cACP,MACA,QAC2B;CAC3B,MAAM,uBAAO,IAAI,KAAa;CAC9B,MAAM,MAAiC,EAAE;AACzC,MAAK,MAAM,OAAO,MAAM;EACtB,MAAM,QAAQ;EACd,MAAM,QAAkB,EAAE;EAC1B,IAAI,UAAU;AACd,OAAK,MAAM,SAAS,QAAQ;GAC1B,MAAM,OAAO,MAAM;AACnB,OAAI,QAAQ,QAAQ,KAAK,SAAS,MAAM;AACtC,cAAU;AACV;;AAEF,SAAM,KAAK,KAAK,UAAU,KAAK,MAAM,CAAC;;AAExC,MAAI,CAAC,SAAS;AACZ,OAAI,KAAK,IAAI;AACb;;EAEF,MAAM,MAAM,MAAM,KAAK,IAAI;AAC3B,MAAI,KAAK,IAAI,IAAI,CAAE;AACnB,OAAK,IAAI,IAAI;AACb,MAAI,KAAK,IAAI;;AAEf,QAAO;;;;;;;AAQT,SAAS,iBAAiB,MAA4D;CACpF,MAAM,uBAAO,IAAI,KAAa;AAC9B,MAAK,MAAM,OAAO,KAChB,MAAK,MAAM,OAAO,OAAO,KAAK,IAAI,CAAE,MAAK,IAAI,IAAI;AAEnD,QAAO,KAAK,KAAK,QAAQ;EACvB,MAAM,SAAS;EACf,MAAM,MAA+B,EAAE;AACvC,OAAK,MAAM,OAAO,KAChB,KAAI,OAAO,OAAO,SAAS,OAAO,OAAO;AAE3C,SAAO;GACP"}