{"version":3,"file":"fallback-nIkuEgL-.mjs","names":[],"sources":["../src/core/fallback.ts"],"sourcesContent":["import { HTTPError, PaymentError, RateLimitError, WebError } from \"./errors.ts\";\n\n/** Operation whose automatic provider selection may continue after a failure. */\nexport type FallbackOperation = \"search\" | \"read\";\n\nconst FALLBACK_HTTP_STATUS_CODES = new Set([0, 402, 408, 429]);\n\n/** Serializable failure retained by detailed automatic-provider responses. */\nexport interface ProviderFailure {\n  readonly provider: string;\n  readonly error: string;\n}\n\n/** Raised when automatic selection cannot return after one or more eligible provider failures. */\nexport class ProviderFallbackError extends WebError {\n  readonly operation: FallbackOperation;\n  readonly attempts: readonly string[];\n  readonly failures: readonly ProviderFailure[];\n\n  constructor(operation: FallbackOperation, failures: readonly ProviderFailure[], cause?: unknown) {\n    super(\n      fallbackErrorMessage(operation, failures),\n      cause instanceof Error ? { cause } : undefined,\n    );\n    this.name = \"ProviderFallbackError\";\n    this.operation = operation;\n    this.failures = failures.map((failure) => ({ ...failure }));\n    this.attempts = this.failures.map(({ provider }) => provider);\n  }\n}\n\n/**\n * Returns whether automatic provider selection may safely try the next provider.\n * Authentication failures, invalid requests, and unknown failures stay strict.\n * @param error - Provider rejection to classify.\n * @param provider - Provider that failed.\n * @param operation - Capability being attempted.\n * @returns {boolean} Whether automatic selection may continue.\n */\nexport function isFallbackEligible(\n  error: unknown,\n  provider: string,\n  operation: FallbackOperation,\n): boolean {\n  if (error instanceof PaymentError || error instanceof RateLimitError) return true;\n  if (!(error instanceof HTTPError)) return false;\n\n  const isJinaReadConflict =\n    operation === \"read\" && provider === \"jina\" && error.statusCode === 409;\n  return (\n    FALLBACK_HTTP_STATUS_CODES.has(error.statusCode) || error.isServerError() || isJinaReadConflict\n  );\n}\n\n/**\n * Convert an arbitrary provider rejection into stable response diagnostics.\n * @param provider - Provider that failed.\n * @param error - Provider rejection to describe.\n * @returns {ProviderFailure} Serializable provider failure.\n */\nexport function providerFailure(provider: string, error: unknown): ProviderFailure {\n  return {\n    provider,\n    error: error instanceof Error ? error.message : String(error),\n  };\n}\n\nfunction fallbackErrorMessage(\n  operation: FallbackOperation,\n  failures: readonly ProviderFailure[],\n): string {\n  const details = failures.map(({ provider, error }) => `${provider}: ${error}`).join(\"; \");\n  return `Automatic ${operation} failed after ${failures.length} provider attempt(s): ${details}`;\n}\n"],"mappings":";;AAKA,MAAM,6CAA6B,IAAI,IAAI;CAAC;CAAG;CAAK;CAAK;AAAG,CAAC;;AAS7D,IAAa,wBAAb,cAA2C,SAAS;CAClD;CACA;CACA;CAEA,YAAY,WAA8B,UAAsC,OAAiB;EAC/F,MACE,qBAAqB,WAAW,QAAQ,GACxC,iBAAiB,QAAQ,EAAE,MAAM,IAAI,KAAA,CACvC;EACA,KAAK,OAAO;EACZ,KAAK,YAAY;EACjB,KAAK,WAAW,SAAS,KAAK,aAAa,EAAE,GAAG,QAAQ,EAAE;EAC1D,KAAK,WAAW,KAAK,SAAS,KAAK,EAAE,eAAe,QAAQ;CAC9D;AACF;;;;;;;;;AAUA,SAAgB,mBACd,OACA,UACA,WACS;CACT,IAAI,iBAAiB,gBAAgB,iBAAiB,gBAAgB,OAAO;CAC7E,IAAI,EAAE,iBAAiB,YAAY,OAAO;CAE1C,MAAM,qBACJ,cAAc,UAAU,aAAa,UAAU,MAAM,eAAe;CACtE,OACE,2BAA2B,IAAI,MAAM,UAAU,KAAK,MAAM,cAAc,KAAK;AAEjF;;;;;;;AAQA,SAAgB,gBAAgB,UAAkB,OAAiC;CACjF,OAAO;EACL;EACA,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;CAC9D;AACF;AAEA,SAAS,qBACP,WACA,UACQ;CACR,MAAM,UAAU,SAAS,KAAK,EAAE,UAAU,YAAY,GAAG,SAAS,IAAI,OAAO,CAAC,CAAC,KAAK,IAAI;CACxF,OAAO,aAAa,UAAU,gBAAgB,SAAS,OAAO,wBAAwB;AACxF"}