{"version":3,"file":"provider-CR4OXou1.mjs","names":[],"sources":["../src/core/sse.ts","../src/core/client.ts","../src/core/provider.ts"],"sourcesContent":["import { HTTPError } from \"./errors.ts\";\n\nconst MAX_STREAM_BYTES = 8 * 1024 * 1024;\nconst MAX_EVENT_CHARACTERS = 1024 * 1024;\n\n/**\n * Decode bounded JSON SSE frames, cancelling the reader on early return or abort.\n * @param stream - Response body.\n * @param url - Safe request URL for protocol errors.\n * @param signal - Cancellation for the entire stream.\n * @yields {unknown} Parsed JSON data events.\n * @returns {AsyncGenerator<unknown>} Parsed JSON data events.\n */\nexport async function* readSseJson(\n  stream: Readonly<ReadableStream<Uint8Array>>,\n  url: string,\n  signal: Readonly<AbortSignal>,\n): AsyncGenerator<unknown> {\n  let data: string[] = [];\n  let frameSize = 0;\n  for await (const line of readLines(stream, url, signal)) {\n    frameSize += line.length + 1;\n    if (frameSize > MAX_EVENT_CHARACTERS) throw streamError(url, \"event exceeds 1 MiB\");\n    if (line === \"\") {\n      const payload = data.join(\"\\n\");\n      data = [];\n      frameSize = 0;\n      if (payload === \"[DONE]\") return;\n      if (payload) yield parseEvent(payload, url);\n    } else if (line === \"data\" || line.startsWith(\"data:\")) {\n      data.push(line.slice(5).replace(/^ /u, \"\"));\n    }\n  }\n  if (data.length > 0) throw streamError(url, \"incomplete event\");\n}\n\nasync function* readLines(\n  stream: Readonly<ReadableStream<Uint8Array>>,\n  url: string,\n  signal: Readonly<AbortSignal>,\n): AsyncGenerator<string> {\n  const reader = stream.getReader();\n  const decoder = new TextDecoder(\"utf-8\", { fatal: true });\n  const cancel = (): void => {\n    void reader.cancel().catch(() => {});\n  };\n  signal.addEventListener(\"abort\", cancel, { once: true });\n  let buffer = \"\";\n  let totalBytes = 0;\n  let done = false;\n  try {\n    while (!done) {\n      signal.throwIfAborted();\n      const chunk = await reader.read();\n      signal.throwIfAborted();\n      done = Boolean(chunk.done);\n      totalBytes += chunk.value?.byteLength ?? 0;\n      if (totalBytes > MAX_STREAM_BYTES) throw streamError(url, \"response exceeds 8 MiB\");\n      buffer += decoder.decode(chunk.value, { stream: !done });\n      let newline = nextNewline(buffer, done);\n      while (newline) {\n        yield buffer.slice(0, newline.index);\n        buffer = buffer.slice(newline.index + newline[0].length);\n        newline = nextNewline(buffer, done);\n      }\n      if (buffer.length > MAX_EVENT_CHARACTERS) throw streamError(url, \"event exceeds 1 MiB\");\n    }\n    if (buffer.length > 0) throw streamError(url, \"incomplete event\");\n  } finally {\n    signal.removeEventListener(\"abort\", cancel);\n    await reader.cancel().catch(() => {});\n    reader.releaseLock();\n  }\n}\n\nfunction nextNewline(buffer: string, done: boolean): RegExpExecArray | null {\n  const match = /\\r\\n|\\r|\\n/u.exec(buffer);\n  if (!done && match?.[0] === \"\\r\" && match.index === buffer.length - 1) return null;\n  return match;\n}\n\nfunction parseEvent(payload: string, url: string): unknown {\n  try {\n    return JSON.parse(payload);\n  } catch {\n    throw streamError(url, \"invalid JSON event\");\n  }\n}\n\nfunction streamError(url: string, reason: string): HTTPError {\n  return new HTTPError(502, url, `Invalid event stream: ${reason}`);\n}\n","import { ofetch, FetchError } from \"ofetch\";\nimport type { $Fetch } from \"ofetch\";\nimport type { ClientOptions } from \"./types.ts\";\nimport { HTTPError, RateLimitError, parseRetryAfter } from \"./errors.ts\";\nimport { version } from \"../version.ts\";\nimport { readSseJson } from \"./sse.ts\";\n\nconst DEFAULT_MAX_RETRIES = 5;\nconst DEFAULT_BASE_DELAY = 50;\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_USER_AGENT = `agntn-web/${version}`;\nconst RETRY_STATUS_CODES = new Set([408, 429, 500, 502, 503, 504]);\nconst MAX_CAUSE_DEPTH = 8;\n\n/** HTTP client with exponential backoff retry and error mapping to web error types. */\nexport class Client {\n  readonly maxRetries: number;\n  readonly baseDelay: number;\n  readonly timeout: number;\n  readonly userAgent: string;\n  private readonly fetch: $Fetch;\n\n  constructor(options: Readonly<ClientOptions> = {}) {\n    this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n    this.baseDelay = options.baseDelay ?? DEFAULT_BASE_DELAY;\n    this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n    this.userAgent = options.userAgent ?? DEFAULT_USER_AGENT;\n\n    const maxRetries = this.maxRetries;\n    const baseDelay = this.baseDelay;\n\n    this.fetch = ofetch.create({\n      retry: this.maxRetries,\n      retryDelay(context) {\n        const remaining = typeof context.options.retry === \"number\" ? context.options.retry : 0;\n        const attempt = maxRetries - remaining;\n        const delay = baseDelay * Math.pow(2, attempt - 1);\n        const jitter = delay * Math.random() * 0.1;\n        return delay + jitter;\n      },\n      retryStatusCodes: [408, 429, 500, 502, 503, 504],\n      timeout: this.timeout,\n      headers: {\n        Accept: \"application/json\",\n        \"User-Agent\": this.userAgent,\n      },\n    });\n  }\n\n  /**\n   * Send a GET request and parse the JSON response.\n   * @param {string} url - Request URL.\n   * @param {Readonly<Record<string, string>>} headers - Additional headers.\n   * @param {Readonly<AbortSignal>} signal - Cancellation signal.\n   * @returns {Promise<T>} Parsed response body.\n   */\n  async getJSON<T>(\n    url: string,\n    headers?: Readonly<Record<string, string>>,\n    signal?: Readonly<AbortSignal>,\n  ): Promise<T> {\n    try {\n      return signal\n        ? await this.fetchWithCancellation(\n            (attemptSignal) => this.fetch<T>(url, { headers, signal: attemptSignal, retry: false }),\n            signal,\n          )\n        : await this.fetch<T>(url, { headers, signal });\n    } catch (error) {\n      throw this.mapError(error, url);\n    }\n  }\n\n  /**\n   * Send a POST request with a JSON body and parse the JSON response.\n   * @param {string} url - Request URL.\n   * @param {Readonly<Record<string, unknown>>} body - JSON request body.\n   * @param {Readonly<Record<string, string>>} headers - Additional headers.\n   * @param {Readonly<AbortSignal>} signal - Cancellation signal.\n   * @returns {Promise<T>} Parsed response body.\n   */\n  async postJSON<T>(\n    url: string,\n    body: Readonly<Record<string, unknown>>,\n    headers?: Readonly<Record<string, string>>,\n    signal?: Readonly<AbortSignal>,\n  ): Promise<T> {\n    try {\n      return signal\n        ? await this.fetchWithCancellation(\n            (attemptSignal) =>\n              this.fetch<T>(url, {\n                method: \"POST\",\n                body,\n                headers,\n                signal: attemptSignal,\n                retry: false,\n              }),\n            signal,\n          )\n        : await this.fetch<T>(url, {\n            method: \"POST\",\n            body,\n            headers,\n            signal,\n          });\n    } catch (error) {\n      throw this.mapError(error, url);\n    }\n  }\n\n  /**\n   * Stream a metered POST without retries, redirects, or upstream error bodies.\n   * @param url - Request URL.\n   * @param body - JSON request body.\n   * @param headers - Authentication and protocol headers.\n   * @param signal - Caller cancellation.\n   * @yields {unknown} Parsed JSON data events.\n   * @returns {AsyncGenerator<unknown>} Bounded JSON SSE events.\n   */\n  async *postSSE(\n    url: string,\n    body: Readonly<Record<string, unknown>>,\n    headers?: Readonly<Record<string, string>>,\n    signal?: Readonly<AbortSignal>,\n  ): AsyncGenerator<unknown> {\n    const controller = new AbortController();\n    const timer =\n      this.timeout > 0\n        ? setTimeout(\n            () => controller.abort(new DOMException(\"Stream timed out\", \"TimeoutError\")),\n            this.timeout,\n          )\n        : undefined;\n    const effectiveSignal = signal\n      ? AbortSignal.any([signal, controller.signal])\n      : controller.signal;\n    const safeUrl = sanitizeUrl(url);\n    try {\n      effectiveSignal.throwIfAborted();\n      const stream = await this.openSSE(url, body, headers, effectiveSignal);\n      yield* readSseJson(stream, safeUrl, effectiveSignal);\n    } catch (error) {\n      effectiveSignal.throwIfAborted();\n      if (error instanceof HTTPError || error instanceof RateLimitError) throw error;\n      throw new HTTPError(502, safeUrl, \"Event stream transport failed\");\n    } finally {\n      clearTimeout(timer);\n      controller.abort();\n    }\n  }\n\n  private async openSSE(\n    url: string,\n    body: Readonly<Record<string, unknown>>,\n    headers: Readonly<Record<string, string>> | undefined,\n    signal: Readonly<AbortSignal>,\n  ): Promise<Readonly<ReadableStream<Uint8Array>>> {\n    const safeUrl = sanitizeUrl(url);\n    const response = await this.fetch.raw<unknown, \"stream\">(url, {\n      method: \"POST\",\n      body,\n      headers: { ...headers, Accept: \"text/event-stream\" },\n      responseType: \"stream\",\n      redirect: \"error\",\n      retry: false,\n      timeout: 0,\n      ignoreResponseError: true,\n      signal,\n    });\n    signal.throwIfAborted();\n    if (!response.ok) {\n      await response.body?.cancel().catch(() => {});\n      if (response.status === 429)\n        throw new RateLimitError(parseRetryAfter(response.headers.get(\"Retry-After\")));\n      throw new HTTPError(response.status, safeUrl, \"Streaming request rejected\");\n    }\n    const contentType = response.headers.get(\"Content-Type\")?.split(\";\")[0].trim().toLowerCase();\n    if (!response._data || (contentType !== undefined && contentType !== \"text/event-stream\")) {\n      await response.body?.cancel().catch(() => {});\n      throw new HTTPError(502, safeUrl, \"Expected an SSE response body\");\n    }\n    return response._data;\n  }\n\n  private async fetchWithCancellation<T>(\n    request: (signal: Readonly<AbortSignal>) => Promise<T>,\n    signal: Readonly<AbortSignal>,\n  ): Promise<T> {\n    for (let attempt = 0; ; attempt += 1) {\n      signal.throwIfAborted();\n      try {\n        return await this.requestWithTimeout(request, signal);\n      } catch (error) {\n        signal.throwIfAborted();\n        if (attempt >= this.maxRetries || !isRetryable(error)) throw error;\n        await abortableDelay(this.retryDelay(attempt), signal);\n      }\n    }\n  }\n\n  /**\n   * ofetch skips its own timeout once a signal is supplied, so each attempt gets one here.\n   * @param request - Function that performs one attempt with the effective signal.\n   * @param signal - Caller cancellation signal.\n   * @returns {Promise<T>} Parsed response body.\n   */\n  private async requestWithTimeout<T>(\n    request: (signal: Readonly<AbortSignal>) => Promise<T>,\n    signal: Readonly<AbortSignal>,\n  ): Promise<T> {\n    if (!this.timeout) return request(signal);\n\n    const controller = new AbortController();\n    const timer = setTimeout(\n      () =>\n        controller.abort(\n          new DOMException(\"The operation was aborted due to timeout\", \"TimeoutError\"),\n        ),\n      this.timeout,\n    );\n    try {\n      return await request(AbortSignal.any([signal, controller.signal]));\n    } finally {\n      clearTimeout(timer);\n    }\n  }\n\n  private retryDelay(attempt: number): number {\n    const delay = this.baseDelay * Math.pow(2, attempt - 1);\n    return delay + delay * Math.random() * 0.1;\n  }\n\n  private mapError(error: unknown, url: string): Error {\n    if (error instanceof FetchError) {\n      if (error.statusCode === 429) {\n        const retryAfter = parseRetryAfter(error.response?.headers.get(\"Retry-After\"));\n        return new RateLimitError(retryAfter);\n      }\n\n      const body = responseBody(error.data) || transportFailure(error.cause);\n      const options = error.cause === undefined ? undefined : { cause: error.cause };\n\n      return new HTTPError(error.statusCode ?? 0, sanitizeUrl(url), body, options);\n    }\n    return error instanceof Error ? error : new Error(String(error));\n  }\n}\n\nfunction responseBody(data: unknown): string {\n  if (typeof data === \"string\") return data;\n  return data === undefined || data === null ? \"\" : JSON.stringify(data);\n}\n\n/**\n * Name the failure behind a request that produced no usable response.\n * Reads the chain under the ofetch error, never its own message, which repeats the unredacted URL.\n * @param cause - Cause attached to the ofetch error.\n * @returns {string} Distinct cause messages from the outside in, or an empty string.\n */\nfunction transportFailure(cause: unknown): string {\n  const parts: string[] = [];\n  const seen = new Set<Error>();\n  let current: unknown = cause;\n\n  while (current instanceof Error && !seen.has(current) && seen.size < MAX_CAUSE_DEPTH) {\n    seen.add(current);\n    const part = errorSummary(current);\n    if (part.length > 0 && parts.at(-1) !== part) parts.push(part);\n    current = current.cause;\n  }\n\n  return parts.join(\": \");\n}\n\nfunction errorSummary(error: Readonly<Error>): string {\n  if (error.message.length > 0) return error.message;\n  if (error instanceof AggregateError) {\n    return error.errors\n      .map((inner: unknown) => (inner instanceof Error ? inner.message : String(inner)))\n      .filter((message) => message.length > 0)\n      .join(\", \");\n  }\n  return \"code\" in error && typeof error.code === \"string\" ? error.code : error.name;\n}\n\nfunction isRetryable(error: unknown): boolean {\n  if (!(error instanceof FetchError)) return false;\n  const statusCode = error.statusCode ?? 0;\n  return statusCode === 0 || RETRY_STATUS_CODES.has(statusCode);\n}\n\nfunction abortableDelay(milliseconds: number, signal: Readonly<AbortSignal>): Promise<void> {\n  signal.throwIfAborted();\n  return new Promise((resolve, reject) => {\n    const onAbort = (): void => {\n      clearTimeout(timer);\n      reject(signal.reason ?? new DOMException(\"The operation was aborted\", \"AbortError\"));\n    };\n    const timer = setTimeout(() => {\n      signal.removeEventListener(\"abort\", onAbort);\n      resolve();\n    }, milliseconds);\n    signal.addEventListener(\"abort\", onAbort, { once: true });\n  });\n}\n\nconst SENSITIVE_PARAMS = [\"api_key\", \"key\", \"token\", \"secret\", \"password\", \"apikey\", \"url\"];\nconst SENSITIVE_PARAM_SET = new Set(SENSITIVE_PARAMS.map((param) => param.toLowerCase()));\n\nfunction sanitizeUrl(url: string): string {\n  try {\n    const directRedaction = redactUrlComponents(url);\n    return redactEncodedPathUrls(directRedaction.url).url;\n  } catch {\n    return url;\n  }\n}\n\nfunction redactUrlComponents(url: string): { url: string; changed: boolean } {\n  const parsed = new URL(url);\n  const userInfoRedacted = redactUserInfo(\n    url,\n    parsed.username.length > 0 || parsed.password.length > 0,\n    parsed.password.length > 0,\n  );\n  const queryRedacted = redactSensitiveQueryParams(userInfoRedacted.url);\n\n  return {\n    url: queryRedacted.url,\n    changed: userInfoRedacted.changed || queryRedacted.changed,\n  };\n}\n\nfunction redactEncodedPathUrls(url: string): { url: string; changed: boolean } {\n  const schemeEnd = url.indexOf(\"://\");\n  if (schemeEnd === -1) {\n    return { url, changed: false };\n  }\n\n  const pathStart = url.indexOf(\"/\", schemeEnd + 3);\n  if (pathStart === -1) {\n    return { url, changed: false };\n  }\n\n  const queryStart = url.indexOf(\"?\", pathStart);\n  const fragmentStart = url.indexOf(\"#\", pathStart);\n  const pathEndCandidates = [queryStart, fragmentStart].filter((index) => index !== -1);\n  const pathEnd = pathEndCandidates.length > 0 ? Math.min(...pathEndCandidates) : url.length;\n  const path = url.slice(pathStart, pathEnd);\n  let changed = false;\n\n  const redactedPath = path\n    .split(\"/\")\n    .map((segment) => {\n      if (!segment.includes(\"%\")) {\n        return segment;\n      }\n\n      try {\n        const decoded = decodeURIComponent(segment);\n        const redacted = redactUrlComponents(decoded);\n        if (!redacted.changed) {\n          return segment;\n        }\n\n        changed = true;\n        return encodeURIComponent(redacted.url);\n      } catch {\n        return segment;\n      }\n    })\n    .join(\"/\");\n\n  if (!changed) {\n    return { url, changed: false };\n  }\n\n  return {\n    url: `${url.slice(0, pathStart)}${redactedPath}${url.slice(pathEnd)}`,\n    changed: true,\n  };\n}\n\nfunction redactUserInfo(\n  url: string,\n  hasUserInfo: boolean,\n  hasPassword: boolean,\n): { url: string; changed: boolean } {\n  if (!hasUserInfo) {\n    return { url, changed: false };\n  }\n\n  const schemeEnd = url.indexOf(\"://\");\n  if (schemeEnd === -1) {\n    return { url, changed: false };\n  }\n\n  const authorityStart = schemeEnd + 3;\n  const pathIndex = url.indexOf(\"/\", authorityStart);\n  const queryIndex = url.indexOf(\"?\", authorityStart);\n  const fragmentIndex = url.indexOf(\"#\", authorityStart);\n\n  const authorityEndCandidates = [pathIndex, queryIndex, fragmentIndex].filter(\n    (index) => index !== -1,\n  );\n  const authorityEnd =\n    authorityEndCandidates.length > 0 ? Math.min(...authorityEndCandidates) : url.length;\n\n  const authority = url.slice(authorityStart, authorityEnd);\n  const atIndex = authority.lastIndexOf(\"@\");\n  if (atIndex === -1) {\n    return { url, changed: false };\n  }\n\n  const redactedUserInfo = hasPassword ? \"[REDACTED]:[REDACTED]\" : \"[REDACTED]\";\n  const redactedAuthority = `${redactedUserInfo}@${authority.slice(atIndex + 1)}`;\n\n  return {\n    url: `${url.slice(0, authorityStart)}${redactedAuthority}${url.slice(authorityEnd)}`,\n    changed: true,\n  };\n}\n\nfunction redactSensitiveQueryParams(url: string): { url: string; changed: boolean } {\n  const queryStart = url.indexOf(\"?\");\n  if (queryStart === -1) {\n    return { url, changed: false };\n  }\n\n  const fragmentStart = url.indexOf(\"#\", queryStart);\n  const queryEnd = fragmentStart === -1 ? url.length : fragmentStart;\n  const prefix = url.slice(0, queryStart + 1);\n  const query = url.slice(queryStart + 1, queryEnd);\n  const suffix = fragmentStart === -1 ? \"\" : url.slice(fragmentStart);\n\n  let changed = false;\n  let redactedQuery = \"\";\n  let segmentStart = 0;\n\n  for (let index = 0; index <= query.length; index += 1) {\n    const isEnd = index === query.length;\n    const char = query[index];\n    if (!isEnd && char !== \"&\") {\n      continue;\n    }\n\n    const segment = query.slice(segmentStart, index);\n    redactedQuery += redactSegment(segment);\n    if (!isEnd) {\n      redactedQuery += char;\n    }\n    segmentStart = index + 1;\n  }\n\n  if (!changed) {\n    return { url, changed: false };\n  }\n\n  return { url: `${prefix}${redactedQuery}${suffix}`, changed: true };\n\n  function redactSegment(segment: string): string {\n    if (!segment) {\n      return segment;\n    }\n\n    const separatorIndex = segment.indexOf(\"=\");\n    const rawKey = separatorIndex === -1 ? segment : segment.slice(0, separatorIndex);\n\n    let decodedKey = rawKey;\n    try {\n      decodedKey = decodeURIComponent(rawKey);\n    } catch {\n      decodedKey = rawKey;\n    }\n\n    if (!SENSITIVE_PARAM_SET.has(decodedKey.toLowerCase())) {\n      return segment;\n    }\n\n    if (separatorIndex === -1) {\n      return segment;\n    }\n\n    changed = true;\n    return `${rawKey}=${encodeURIComponent(\"[REDACTED]\")}`;\n  }\n}\n\nlet _defaultClient: Client | undefined;\n\n/**\n * Lazily-initialized singleton {@link Client} used by all providers.\n * @returns {Client} Shared client instance.\n */\nexport function defaultClient(): Client {\n  _defaultClient ??= new Client();\n  return _defaultClient;\n}\n\nexport function resetDefaultClientForTests(): void {\n  _defaultClient = undefined;\n}\n","import { defaultClient, type Client } from \"./client.ts\";\nimport type {\n  ImageSearchRequestOptions,\n  ImageSearchResult,\n  ProviderConfig,\n  ReadOptions,\n  ReadResult,\n  ExecutionOptions,\n  SearchFilterCapabilities,\n  SearchFilterName,\n  SearchRequestOptions,\n  SearchResponse,\n  SearchResult,\n} from \"./types.ts\";\nimport { InvalidProviderUrlError } from \"./errors.ts\";\n\nexport type ProviderCapability = \"search\" | \"searchImage\" | \"read\";\nexport type SearchResultField = Exclude<keyof SearchResult, \"url\" | \"title\" | \"snippet\">;\nexport type SearchContentOptionName = \"highlights\" | \"summary\" | \"fullText\";\nexport type ReadOptionName = Exclude<keyof ReadOptions, keyof ExecutionOptions>;\nexport type ReadFormat = NonNullable<ReadOptions[\"format\"]>;\n\n/** Known result count behavior exposed by one provider adapter. */\nexport type ProviderResultLimit =\n  | { readonly default: number; readonly maximum?: number }\n  | { readonly default?: never; readonly maximum: number };\n\n/** Static search metadata that cannot be inferred from method presence. */\nexport interface SearchCapabilityDetails {\n  readonly contentOptions: readonly SearchContentOptionName[];\n  readonly resultLimit?: ProviderResultLimit;\n  readonly resultFields: readonly SearchResultField[];\n}\n\n/** Static reverse image search metadata that cannot be inferred from method presence. */\nexport interface ImageSearchCapabilityDetails {\n  readonly resultLimit: ProviderResultLimit;\n}\n\n/** Static URL reader metadata that cannot be inferred from method presence. */\nexport interface ReadCapabilityDetails {\n  readonly options: readonly ReadOptionName[];\n  readonly formats: readonly ReadFormat[];\n}\n\n/** Optional details declared by a provider class for each implemented operation. */\nexport interface ProviderCapabilityDetails {\n  readonly search?: SearchCapabilityDetails;\n  readonly searchImage?: ImageSearchCapabilityDetails;\n  readonly read?: ReadCapabilityDetails;\n}\n\n/** Machine-readable search capability reported by provider discovery. */\nexport interface ProviderSearchCapabilities {\n  readonly supported: boolean;\n  readonly filters?: readonly SearchFilterName[];\n  readonly categories?: readonly string[];\n  readonly contentOptions?: readonly SearchContentOptionName[];\n  readonly pagination?: boolean;\n  readonly resultLimit?: ProviderResultLimit;\n  readonly resultFields?: readonly SearchResultField[];\n}\n\n/** Machine-readable reverse image search capability reported by provider discovery. */\nexport interface ProviderImageSearchCapabilities {\n  readonly supported: boolean;\n  readonly resultLimit?: ProviderResultLimit;\n}\n\n/** Machine-readable URL reader capability reported by provider discovery. */\nexport interface ProviderReadCapabilities {\n  readonly supported: boolean;\n  readonly options?: readonly ReadOptionName[];\n  readonly formats?: readonly ReadFormat[];\n}\n\n/** Complete operation matrix for one registered provider. */\nexport interface ProviderCapabilities {\n  readonly search: ProviderSearchCapabilities;\n  readonly searchImage: ProviderImageSearchCapabilities;\n  readonly read: ProviderReadCapabilities;\n}\n\nexport interface ProviderConstructor {\n  readonly providerName: string;\n  readonly defaultBaseURL: string;\n  readonly apiKeyEnvVar?: string | null;\n  /** Optional local configuration check for providers requiring more than one credential. */\n  readonly isConfigured?: () => boolean;\n  readonly capabilities?: readonly ProviderCapability[];\n  readonly capabilityDetails?: ProviderCapabilityDetails;\n  readonly searchFilterCapabilities?: SearchFilterCapabilities;\n  readonly prototype: Readonly<Provider>;\n  new (config: Readonly<ProviderConfig>): Provider;\n}\n\nexport abstract class Provider {\n  readonly #name: string;\n  protected readonly client: Client;\n  protected readonly baseURL: string;\n\n  get name(): string {\n    return this.#name;\n  }\n\n  protected constructor(\n    config: Readonly<ProviderConfig>,\n    provider: Pick<ProviderConstructor, \"providerName\" | \"defaultBaseURL\">,\n  ) {\n    this.#name = provider.providerName;\n    const baseURL = config.baseURL ?? provider.defaultBaseURL;\n    assertProviderBaseURL(baseURL, this.name);\n    this.baseURL = baseURL.replace(/\\/+$/, \"\");\n    this.client = defaultClient();\n  }\n}\n\nexport function assertProviderBaseURL(baseURL: string, providerName: string): void {\n  let protocol: string;\n  try {\n    protocol = new URL(baseURL).protocol;\n  } catch {\n    throw new InvalidProviderUrlError(providerName);\n  }\n\n  if (protocol !== \"http:\" && protocol !== \"https:\") {\n    throw new InvalidProviderUrlError(providerName);\n  }\n}\n\nexport interface SearchProvider {\n  search(query: string, options?: SearchRequestOptions): Promise<SearchResult[]>;\n}\n\nexport interface DetailedSearchProvider {\n  searchDetailed(query: string, options?: SearchRequestOptions): Promise<SearchResponse>;\n}\n\n/** One provider page with an opaque provider-native token for the next page. */\nexport interface ProviderSearchPage extends SearchResponse {\n  continuation?: string;\n  continuationStatus?: \"next\" | \"unknown\";\n}\n\n/** Optional paging contract implemented without exposing provider state to callers. */\nexport interface PaginatedSearchProvider {\n  searchPage(\n    query: string,\n    options?: SearchRequestOptions,\n    continuation?: string,\n  ): Promise<ProviderSearchPage>;\n}\n\n/** Provider capability for finding public pages from an image URL. */\nexport interface ImageSearchProvider {\n  searchByImage(url: string, options?: ImageSearchRequestOptions): Promise<ImageSearchResult[]>;\n}\n\nexport interface ReadProvider {\n  read(url: string, options?: Readonly<ReadOptions>): Promise<ReadResult>;\n}\n\nexport interface AvailabilityProvider {\n  isAvailable(signal?: Readonly<AbortSignal>): Promise<boolean>;\n}\n\nexport function isSearchProvider(provider: object): provider is Provider & SearchProvider {\n  return \"search\" in provider && typeof provider.search === \"function\";\n}\n\nexport function isDetailedSearchProvider(\n  provider: object,\n): provider is Provider & DetailedSearchProvider {\n  return \"searchDetailed\" in provider && typeof provider.searchDetailed === \"function\";\n}\n\nexport function isPaginatedSearchProvider(\n  provider: object,\n): provider is Provider & SearchProvider & PaginatedSearchProvider {\n  return \"searchPage\" in provider && typeof provider.searchPage === \"function\";\n}\n\n/**\n * Return whether a provider implements reverse image search.\n * @param provider - Provider instance to inspect.\n * @returns {boolean} Whether the capability is present.\n */\nexport function isImageSearchProvider(\n  provider: object,\n): provider is Provider & ImageSearchProvider {\n  return \"searchByImage\" in provider && typeof provider.searchByImage === \"function\";\n}\n\nexport function isReadProvider(provider: object): provider is Provider & ReadProvider {\n  return \"read\" in provider && typeof provider.read === \"function\";\n}\n\nexport function isAvailabilityProvider(\n  provider: object,\n): provider is Provider & AvailabilityProvider {\n  return \"isAvailable\" in provider && typeof provider.isAvailable === \"function\";\n}\n"],"mappings":";;;;AAEA,MAAM,mBAAmB;AACzB,MAAM,uBAAuB;;;;;;;;;AAU7B,gBAAuB,YACrB,QACA,KACA,QACyB;CACzB,IAAI,OAAiB,CAAC;CACtB,IAAI,YAAY;CAChB,WAAW,MAAM,QAAQ,UAAU,QAAQ,KAAK,MAAM,GAAG;EACvD,aAAa,KAAK,SAAS;EAC3B,IAAI,YAAY,sBAAsB,MAAM,YAAY,KAAK,qBAAqB;EAClF,IAAI,SAAS,IAAI;GACf,MAAM,UAAU,KAAK,KAAK,IAAI;GAC9B,OAAO,CAAC;GACR,YAAY;GACZ,IAAI,YAAY,UAAU;GAC1B,IAAI,SAAS,MAAM,WAAW,SAAS,GAAG;EAC5C,OAAO,IAAI,SAAS,UAAU,KAAK,WAAW,OAAO,GACnD,KAAK,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,OAAO,EAAE,CAAC;CAE9C;CACA,IAAI,KAAK,SAAS,GAAG,MAAM,YAAY,KAAK,kBAAkB;AAChE;AAEA,gBAAgB,UACd,QACA,KACA,QACwB;CACxB,MAAM,SAAS,OAAO,UAAU;CAChC,MAAM,UAAU,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC;CACxD,MAAM,eAAqB;EACzB,OAAY,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC;CACrC;CACA,OAAO,iBAAiB,SAAS,QAAQ,EAAE,MAAM,KAAK,CAAC;CACvD,IAAI,SAAS;CACb,IAAI,aAAa;CACjB,IAAI,OAAO;CACX,IAAI;EACF,OAAO,CAAC,MAAM;GACZ,OAAO,eAAe;GACtB,MAAM,QAAQ,MAAM,OAAO,KAAK;GAChC,OAAO,eAAe;GACtB,OAAO,QAAQ,MAAM,IAAI;GACzB,cAAc,MAAM,OAAO,cAAc;GACzC,IAAI,aAAa,kBAAkB,MAAM,YAAY,KAAK,wBAAwB;GAClF,UAAU,QAAQ,OAAO,MAAM,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC;GACvD,IAAI,UAAU,YAAY,QAAQ,IAAI;GACtC,OAAO,SAAS;IACd,MAAM,OAAO,MAAM,GAAG,QAAQ,KAAK;IACnC,SAAS,OAAO,MAAM,QAAQ,QAAQ,QAAQ,EAAE,CAAC,MAAM;IACvD,UAAU,YAAY,QAAQ,IAAI;GACpC;GACA,IAAI,OAAO,SAAS,sBAAsB,MAAM,YAAY,KAAK,qBAAqB;EACxF;EACA,IAAI,OAAO,SAAS,GAAG,MAAM,YAAY,KAAK,kBAAkB;CAClE,UAAU;EACR,OAAO,oBAAoB,SAAS,MAAM;EAC1C,MAAM,OAAO,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC;EACpC,OAAO,YAAY;CACrB;AACF;AAEA,SAAS,YAAY,QAAgB,MAAuC;CAC1E,MAAM,QAAQ,cAAc,KAAK,MAAM;CACvC,IAAI,CAAC,QAAQ,QAAQ,OAAO,QAAQ,MAAM,UAAU,OAAO,SAAS,GAAG,OAAO;CAC9E,OAAO;AACT;AAEA,SAAS,WAAW,SAAiB,KAAsB;CACzD,IAAI;EACF,OAAO,KAAK,MAAM,OAAO;CAC3B,QAAQ;EACN,MAAM,YAAY,KAAK,oBAAoB;CAC7C;AACF;AAEA,SAAS,YAAY,KAAa,QAA2B;CAC3D,OAAO,IAAI,UAAU,KAAK,KAAK,yBAAyB,QAAQ;AAClE;;;ACpFA,MAAM,sBAAsB;AAC5B,MAAM,qBAAqB;AAC3B,MAAM,kBAAkB;AACxB,MAAM,qBAAqB,aAAa;AACxC,MAAM,qCAAqB,IAAI,IAAI;CAAC;CAAK;CAAK;CAAK;CAAK;CAAK;AAAG,CAAC;AACjE,MAAM,kBAAkB;;AAGxB,IAAa,SAAb,MAAoB;CAClB;CACA;CACA;CACA;CACA;CAEA,YAAY,UAAmC,CAAC,GAAG;EACjD,KAAK,aAAa,QAAQ,cAAc;EACxC,KAAK,YAAY,QAAQ,aAAa;EACtC,KAAK,UAAU,QAAQ,WAAW;EAClC,KAAK,YAAY,QAAQ,aAAa;EAEtC,MAAM,aAAa,KAAK;EACxB,MAAM,YAAY,KAAK;EAEvB,KAAK,QAAQ,OAAO,OAAO;GACzB,OAAO,KAAK;GACZ,WAAW,SAAS;IAClB,MAAM,YAAY,OAAO,QAAQ,QAAQ,UAAU,WAAW,QAAQ,QAAQ,QAAQ;IACtF,MAAM,UAAU,aAAa;IAC7B,MAAM,QAAQ,YAAY,KAAK,IAAI,GAAG,UAAU,CAAC;IAEjD,OAAO,QADQ,QAAQ,KAAK,OAAO,IAAI;GAEzC;GACA,kBAAkB;IAAC;IAAK;IAAK;IAAK;IAAK;IAAK;GAAG;GAC/C,SAAS,KAAK;GACd,SAAS;IACP,QAAQ;IACR,cAAc,KAAK;GACrB;EACF,CAAC;CACH;;;;;;;;CASA,MAAM,QACJ,KACA,SACA,QACY;EACZ,IAAI;GACF,OAAO,SACH,MAAM,KAAK,uBACR,kBAAkB,KAAK,MAAS,KAAK;IAAE;IAAS,QAAQ;IAAe,OAAO;GAAM,CAAC,GACtF,MACF,IACA,MAAM,KAAK,MAAS,KAAK;IAAE;IAAS;GAAO,CAAC;EAClD,SAAS,OAAO;GACd,MAAM,KAAK,SAAS,OAAO,GAAG;EAChC;CACF;;;;;;;;;CAUA,MAAM,SACJ,KACA,MACA,SACA,QACY;EACZ,IAAI;GACF,OAAO,SACH,MAAM,KAAK,uBACR,kBACC,KAAK,MAAS,KAAK;IACjB,QAAQ;IACR;IACA;IACA,QAAQ;IACR,OAAO;GACT,CAAC,GACH,MACF,IACA,MAAM,KAAK,MAAS,KAAK;IACvB,QAAQ;IACR;IACA;IACA;GACF,CAAC;EACP,SAAS,OAAO;GACd,MAAM,KAAK,SAAS,OAAO,GAAG;EAChC;CACF;;;;;;;;;;CAWA,OAAO,QACL,KACA,MACA,SACA,QACyB;EACzB,MAAM,aAAa,IAAI,gBAAgB;EACvC,MAAM,QACJ,KAAK,UAAU,IACX,iBACQ,WAAW,MAAM,IAAI,aAAa,oBAAoB,cAAc,CAAC,GAC3E,KAAK,OACP,IACA,KAAA;EACN,MAAM,kBAAkB,SACpB,YAAY,IAAI,CAAC,QAAQ,WAAW,MAAM,CAAC,IAC3C,WAAW;EACf,MAAM,UAAU,YAAY,GAAG;EAC/B,IAAI;GACF,gBAAgB,eAAe;GAE/B,OAAO,YAAY,MADE,KAAK,QAAQ,KAAK,MAAM,SAAS,eAAe,GAC1C,SAAS,eAAe;EACrD,SAAS,OAAO;GACd,gBAAgB,eAAe;GAC/B,IAAI,iBAAiB,aAAa,iBAAiB,gBAAgB,MAAM;GACzE,MAAM,IAAI,UAAU,KAAK,SAAS,+BAA+B;EACnE,UAAU;GACR,aAAa,KAAK;GAClB,WAAW,MAAM;EACnB;CACF;CAEA,MAAc,QACZ,KACA,MACA,SACA,QAC+C;EAC/C,MAAM,UAAU,YAAY,GAAG;EAC/B,MAAM,WAAW,MAAM,KAAK,MAAM,IAAuB,KAAK;GAC5D,QAAQ;GACR;GACA,SAAS;IAAE,GAAG;IAAS,QAAQ;GAAoB;GACnD,cAAc;GACd,UAAU;GACV,OAAO;GACP,SAAS;GACT,qBAAqB;GACrB;EACF,CAAC;EACD,OAAO,eAAe;EACtB,IAAI,CAAC,SAAS,IAAI;GAChB,MAAM,SAAS,MAAM,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC;GAC5C,IAAI,SAAS,WAAW,KACtB,MAAM,IAAI,eAAe,gBAAgB,SAAS,QAAQ,IAAI,aAAa,CAAC,CAAC;GAC/E,MAAM,IAAI,UAAU,SAAS,QAAQ,SAAS,4BAA4B;EAC5E;EACA,MAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,YAAY;EAC3F,IAAI,CAAC,SAAS,SAAU,gBAAgB,KAAA,KAAa,gBAAgB,qBAAsB;GACzF,MAAM,SAAS,MAAM,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC;GAC5C,MAAM,IAAI,UAAU,KAAK,SAAS,+BAA+B;EACnE;EACA,OAAO,SAAS;CAClB;CAEA,MAAc,sBACZ,SACA,QACY;EACZ,KAAK,IAAI,UAAU,IAAK,WAAW,GAAG;GACpC,OAAO,eAAe;GACtB,IAAI;IACF,OAAO,MAAM,KAAK,mBAAmB,SAAS,MAAM;GACtD,SAAS,OAAO;IACd,OAAO,eAAe;IACtB,IAAI,WAAW,KAAK,cAAc,CAAC,YAAY,KAAK,GAAG,MAAM;IAC7D,MAAM,eAAe,KAAK,WAAW,OAAO,GAAG,MAAM;GACvD;EACF;CACF;;;;;;;CAQA,MAAc,mBACZ,SACA,QACY;EACZ,IAAI,CAAC,KAAK,SAAS,OAAO,QAAQ,MAAM;EAExC,MAAM,aAAa,IAAI,gBAAgB;EACvC,MAAM,QAAQ,iBAEV,WAAW,MACT,IAAI,aAAa,4CAA4C,cAAc,CAC7E,GACF,KAAK,OACP;EACA,IAAI;GACF,OAAO,MAAM,QAAQ,YAAY,IAAI,CAAC,QAAQ,WAAW,MAAM,CAAC,CAAC;EACnE,UAAU;GACR,aAAa,KAAK;EACpB;CACF;CAEA,WAAmB,SAAyB;EAC1C,MAAM,QAAQ,KAAK,YAAY,KAAK,IAAI,GAAG,UAAU,CAAC;EACtD,OAAO,QAAQ,QAAQ,KAAK,OAAO,IAAI;CACzC;CAEA,SAAiB,OAAgB,KAAoB;EACnD,IAAI,iBAAiB,YAAY;GAC/B,IAAI,MAAM,eAAe,KAAK;IAC5B,MAAM,aAAa,gBAAgB,MAAM,UAAU,QAAQ,IAAI,aAAa,CAAC;IAC7E,OAAO,IAAI,eAAe,UAAU;GACtC;GAEA,MAAM,OAAO,aAAa,MAAM,IAAI,KAAK,iBAAiB,MAAM,KAAK;GACrE,MAAM,UAAU,MAAM,UAAU,KAAA,IAAY,KAAA,IAAY,EAAE,OAAO,MAAM,MAAM;GAE7E,OAAO,IAAI,UAAU,MAAM,cAAc,GAAG,YAAY,GAAG,GAAG,MAAM,OAAO;EAC7E;EACA,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;CACjE;AACF;AAEA,SAAS,aAAa,MAAuB;CAC3C,IAAI,OAAO,SAAS,UAAU,OAAO;CACrC,OAAO,SAAS,KAAA,KAAa,SAAS,OAAO,KAAK,KAAK,UAAU,IAAI;AACvE;;;;;;;AAQA,SAAS,iBAAiB,OAAwB;CAChD,MAAM,QAAkB,CAAC;CACzB,MAAM,uBAAO,IAAI,IAAW;CAC5B,IAAI,UAAmB;CAEvB,OAAO,mBAAmB,SAAS,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,OAAO,iBAAiB;EACpF,KAAK,IAAI,OAAO;EAChB,MAAM,OAAO,aAAa,OAAO;EACjC,IAAI,KAAK,SAAS,KAAK,MAAM,GAAG,EAAE,MAAM,MAAM,MAAM,KAAK,IAAI;EAC7D,UAAU,QAAQ;CACpB;CAEA,OAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,aAAa,OAAgC;CACpD,IAAI,MAAM,QAAQ,SAAS,GAAG,OAAO,MAAM;CAC3C,IAAI,iBAAiB,gBACnB,OAAO,MAAM,OACV,KAAK,UAAoB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAE,CAAC,CACjF,QAAQ,YAAY,QAAQ,SAAS,CAAC,CAAC,CACvC,KAAK,IAAI;CAEd,OAAO,UAAU,SAAS,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO,MAAM;AAChF;AAEA,SAAS,YAAY,OAAyB;CAC5C,IAAI,EAAE,iBAAiB,aAAa,OAAO;CAC3C,MAAM,aAAa,MAAM,cAAc;CACvC,OAAO,eAAe,KAAK,mBAAmB,IAAI,UAAU;AAC9D;AAEA,SAAS,eAAe,cAAsB,QAA8C;CAC1F,OAAO,eAAe;CACtB,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAM,gBAAsB;GAC1B,aAAa,KAAK;GAClB,OAAO,OAAO,UAAU,IAAI,aAAa,6BAA6B,YAAY,CAAC;EACrF;EACA,MAAM,QAAQ,iBAAiB;GAC7B,OAAO,oBAAoB,SAAS,OAAO;GAC3C,QAAQ;EACV,GAAG,YAAY;EACf,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;CAC1D,CAAC;AACH;AAGA,MAAM,sBAAsB,IAAI,IAAI;CADV;CAAW;CAAO;CAAS;CAAU;CAAY;CAAU;AAClC,CAAC,CAAC,KAAK,UAAU,MAAM,YAAY,CAAC,CAAC;AAExF,SAAS,YAAY,KAAqB;CACxC,IAAI;EAEF,OAAO,sBADiB,oBAAoB,GACD,CAAC,CAAC,GAAG,CAAC,CAAC;CACpD,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,oBAAoB,KAAgD;CAC3E,MAAM,SAAS,IAAI,IAAI,GAAG;CAC1B,MAAM,mBAAmB,eACvB,KACA,OAAO,SAAS,SAAS,KAAK,OAAO,SAAS,SAAS,GACvD,OAAO,SAAS,SAAS,CAC3B;CACA,MAAM,gBAAgB,2BAA2B,iBAAiB,GAAG;CAErE,OAAO;EACL,KAAK,cAAc;EACnB,SAAS,iBAAiB,WAAW,cAAc;CACrD;AACF;AAEA,SAAS,sBAAsB,KAAgD;CAC7E,MAAM,YAAY,IAAI,QAAQ,KAAK;CACnC,IAAI,cAAc,IAChB,OAAO;EAAE;EAAK,SAAS;CAAM;CAG/B,MAAM,YAAY,IAAI,QAAQ,KAAK,YAAY,CAAC;CAChD,IAAI,cAAc,IAChB,OAAO;EAAE;EAAK,SAAS;CAAM;CAK/B,MAAM,oBAAoB,CAFP,IAAI,QAAQ,KAAK,SAEA,GADd,IAAI,QAAQ,KAAK,SACY,CAAC,CAAC,CAAC,QAAQ,UAAU,UAAU,EAAE;CACpF,MAAM,UAAU,kBAAkB,SAAS,IAAI,KAAK,IAAI,GAAG,iBAAiB,IAAI,IAAI;CACpF,MAAM,OAAO,IAAI,MAAM,WAAW,OAAO;CACzC,IAAI,UAAU;CAEd,MAAM,eAAe,KAClB,MAAM,GAAG,CAAC,CACV,KAAK,YAAY;EAChB,IAAI,CAAC,QAAQ,SAAS,GAAG,GACvB,OAAO;EAGT,IAAI;GAEF,MAAM,WAAW,oBADD,mBAAmB,OACQ,CAAC;GAC5C,IAAI,CAAC,SAAS,SACZ,OAAO;GAGT,UAAU;GACV,OAAO,mBAAmB,SAAS,GAAG;EACxC,QAAQ;GACN,OAAO;EACT;CACF,CAAC,CAAC,CACD,KAAK,GAAG;CAEX,IAAI,CAAC,SACH,OAAO;EAAE;EAAK,SAAS;CAAM;CAG/B,OAAO;EACL,KAAK,GAAG,IAAI,MAAM,GAAG,SAAS,IAAI,eAAe,IAAI,MAAM,OAAO;EAClE,SAAS;CACX;AACF;AAEA,SAAS,eACP,KACA,aACA,aACmC;CACnC,IAAI,CAAC,aACH,OAAO;EAAE;EAAK,SAAS;CAAM;CAG/B,MAAM,YAAY,IAAI,QAAQ,KAAK;CACnC,IAAI,cAAc,IAChB,OAAO;EAAE;EAAK,SAAS;CAAM;CAG/B,MAAM,iBAAiB,YAAY;CAKnC,MAAM,yBAAyB;EAJb,IAAI,QAAQ,KAAK,cAIK;EAHrB,IAAI,QAAQ,KAAK,cAGgB;EAF9B,IAAI,QAAQ,KAAK,cAE4B;CAAC,CAAC,CAAC,QACnE,UAAU,UAAU,EACvB;CACA,MAAM,eACJ,uBAAuB,SAAS,IAAI,KAAK,IAAI,GAAG,sBAAsB,IAAI,IAAI;CAEhF,MAAM,YAAY,IAAI,MAAM,gBAAgB,YAAY;CACxD,MAAM,UAAU,UAAU,YAAY,GAAG;CACzC,IAAI,YAAY,IACd,OAAO;EAAE;EAAK,SAAS;CAAM;CAI/B,MAAM,oBAAoB,GADD,cAAc,0BAA0B,aACnB,GAAG,UAAU,MAAM,UAAU,CAAC;CAE5E,OAAO;EACL,KAAK,GAAG,IAAI,MAAM,GAAG,cAAc,IAAI,oBAAoB,IAAI,MAAM,YAAY;EACjF,SAAS;CACX;AACF;AAEA,SAAS,2BAA2B,KAAgD;CAClF,MAAM,aAAa,IAAI,QAAQ,GAAG;CAClC,IAAI,eAAe,IACjB,OAAO;EAAE;EAAK,SAAS;CAAM;CAG/B,MAAM,gBAAgB,IAAI,QAAQ,KAAK,UAAU;CACjD,MAAM,WAAW,kBAAkB,KAAK,IAAI,SAAS;CACrD,MAAM,SAAS,IAAI,MAAM,GAAG,aAAa,CAAC;CAC1C,MAAM,QAAQ,IAAI,MAAM,aAAa,GAAG,QAAQ;CAChD,MAAM,SAAS,kBAAkB,KAAK,KAAK,IAAI,MAAM,aAAa;CAElE,IAAI,UAAU;CACd,IAAI,gBAAgB;CACpB,IAAI,eAAe;CAEnB,KAAK,IAAI,QAAQ,GAAG,SAAS,MAAM,QAAQ,SAAS,GAAG;EACrD,MAAM,QAAQ,UAAU,MAAM;EAC9B,MAAM,OAAO,MAAM;EACnB,IAAI,CAAC,SAAS,SAAS,KACrB;EAGF,MAAM,UAAU,MAAM,MAAM,cAAc,KAAK;EAC/C,iBAAiB,cAAc,OAAO;EACtC,IAAI,CAAC,OACH,iBAAiB;EAEnB,eAAe,QAAQ;CACzB;CAEA,IAAI,CAAC,SACH,OAAO;EAAE;EAAK,SAAS;CAAM;CAG/B,OAAO;EAAE,KAAK,GAAG,SAAS,gBAAgB;EAAU,SAAS;CAAK;CAElE,SAAS,cAAc,SAAyB;EAC9C,IAAI,CAAC,SACH,OAAO;EAGT,MAAM,iBAAiB,QAAQ,QAAQ,GAAG;EAC1C,MAAM,SAAS,mBAAmB,KAAK,UAAU,QAAQ,MAAM,GAAG,cAAc;EAEhF,IAAI,aAAa;EACjB,IAAI;GACF,aAAa,mBAAmB,MAAM;EACxC,QAAQ;GACN,aAAa;EACf;EAEA,IAAI,CAAC,oBAAoB,IAAI,WAAW,YAAY,CAAC,GACnD,OAAO;EAGT,IAAI,mBAAmB,IACrB,OAAO;EAGT,UAAU;EACV,OAAO,GAAG,OAAO,GAAG,mBAAmB,YAAY;CACrD;AACF;AAEA,IAAI;;;;;AAMJ,SAAgB,gBAAwB;CACtC,mBAAmB,IAAI,OAAO;CAC9B,OAAO;AACT;;;AClZA,IAAsB,WAAtB,MAA+B;CAC7B;CACA;CACA;CAEA,IAAI,OAAe;EACjB,OAAO,KAAK;CACd;CAEA,YACE,QACA,UACA;EACA,KAAK,QAAQ,SAAS;EACtB,MAAM,UAAU,OAAO,WAAW,SAAS;EAC3C,sBAAsB,SAAS,KAAK,IAAI;EACxC,KAAK,UAAU,QAAQ,QAAQ,QAAQ,EAAE;EACzC,KAAK,SAAS,cAAc;CAC9B;AACF;AAEA,SAAgB,sBAAsB,SAAiB,cAA4B;CACjF,IAAI;CACJ,IAAI;EACF,WAAW,IAAI,IAAI,OAAO,CAAC,CAAC;CAC9B,QAAQ;EACN,MAAM,IAAI,wBAAwB,YAAY;CAChD;CAEA,IAAI,aAAa,WAAW,aAAa,UACvC,MAAM,IAAI,wBAAwB,YAAY;AAElD;AAsCA,SAAgB,iBAAiB,UAAyD;CACxF,OAAO,YAAY,YAAY,OAAO,SAAS,WAAW;AAC5D;AAEA,SAAgB,yBACd,UAC+C;CAC/C,OAAO,oBAAoB,YAAY,OAAO,SAAS,mBAAmB;AAC5E;AAEA,SAAgB,0BACd,UACiE;CACjE,OAAO,gBAAgB,YAAY,OAAO,SAAS,eAAe;AACpE;;;;;;AAOA,SAAgB,sBACd,UAC4C;CAC5C,OAAO,mBAAmB,YAAY,OAAO,SAAS,kBAAkB;AAC1E;AAEA,SAAgB,eAAe,UAAuD;CACpF,OAAO,UAAU,YAAY,OAAO,SAAS,SAAS;AACxD;AAEA,SAAgB,uBACd,UAC6C;CAC7C,OAAO,iBAAiB,YAAY,OAAO,SAAS,gBAAgB;AACtE"}