{"version":3,"file":"async_caller.cjs","names":["PQueueMod","pRetry","getAbortSignalError"],"sources":["../../src/utils/async_caller.ts"],"sourcesContent":["import PQueueMod from \"p-queue\";\n\nimport { getAbortSignalError } from \"./signal.js\";\nimport pRetry from \"./p-retry/index.js\";\n\nconst STATUS_NO_RETRY = [\n  400, // Bad Request\n  401, // Unauthorized\n  402, // Payment Required\n  403, // Forbidden\n  404, // Not Found\n  405, // Method Not Allowed\n  406, // Not Acceptable\n  407, // Proxy Authentication Required\n  409, // Conflict\n];\n\n/**\n * The default failed attempt handler for the AsyncCaller.\n * @param error - The error to handle.\n * @returns void\n */\nconst defaultFailedAttemptHandler = (error: unknown) => {\n  if (typeof error !== \"object\" || error === null) {\n    return;\n  }\n\n  if (\n    (\"message\" in error &&\n      typeof error.message === \"string\" &&\n      (error.message.startsWith(\"Cancel\") ||\n        error.message.startsWith(\"AbortError\"))) ||\n    (\"name\" in error &&\n      typeof error.name === \"string\" &&\n      error.name === \"AbortError\")\n  ) {\n    throw error;\n  }\n  if (\n    \"code\" in error &&\n    typeof error.code === \"string\" &&\n    error.code === \"ECONNABORTED\"\n  ) {\n    throw error;\n  }\n  const responseStatus =\n    \"response\" in error &&\n    typeof error.response === \"object\" &&\n    error.response !== null &&\n    \"status\" in error.response &&\n    typeof error.response.status === \"number\"\n      ? error.response.status\n      : undefined;\n\n  // OpenAI SDK errors expose status directly on the error object\n  const directStatus =\n    \"status\" in error && typeof error.status === \"number\"\n      ? error.status\n      : undefined;\n\n  const status = responseStatus ?? directStatus;\n  if (status && STATUS_NO_RETRY.includes(+status)) {\n    throw error;\n  }\n\n  const code =\n    \"error\" in error &&\n    typeof error.error === \"object\" &&\n    error.error !== null &&\n    \"code\" in error.error &&\n    typeof error.error.code === \"string\"\n      ? error.error.code\n      : undefined;\n  if (code === \"insufficient_quota\") {\n    const err = new Error(\n      \"message\" in error && typeof error.message === \"string\"\n        ? error.message\n        : \"Insufficient quota\"\n    );\n    err.name = \"InsufficientQuotaError\";\n    throw err;\n  }\n};\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nexport type FailedAttemptHandler = (error: any) => any;\n\nexport interface AsyncCallerParams {\n  /**\n   * The maximum number of concurrent calls that can be made.\n   * Defaults to `Infinity`, which means no limit.\n   */\n  maxConcurrency?: number;\n  /**\n   * The maximum number of retries that can be made for a single call,\n   * with an exponential backoff between each attempt. Defaults to 6.\n   */\n  maxRetries?: number;\n  /**\n   * Custom handler to handle failed attempts. Takes the originally thrown\n   * error object as input, and should itself throw an error if the input\n   * error is not retryable.\n   */\n  onFailedAttempt?: FailedAttemptHandler;\n}\n\nexport interface AsyncCallerCallOptions {\n  signal?: AbortSignal;\n}\n\n/**\n * A class that can be used to make async calls with concurrency and retry logic.\n *\n * This is useful for making calls to any kind of \"expensive\" external resource,\n * be it because it's rate-limited, subject to network issues, etc.\n *\n * Concurrent calls are limited by the `maxConcurrency` parameter, which defaults\n * to `Infinity`. This means that by default, all calls will be made in parallel.\n *\n * Retries are limited by the `maxRetries` parameter, which defaults to 6. This\n * means that by default, each call will be retried up to 6 times, with an\n * exponential backoff between each attempt.\n */\nexport class AsyncCaller {\n  protected maxConcurrency: AsyncCallerParams[\"maxConcurrency\"];\n\n  protected maxRetries: AsyncCallerParams[\"maxRetries\"];\n\n  protected onFailedAttempt: AsyncCallerParams[\"onFailedAttempt\"];\n\n  private queue: (typeof import(\"p-queue\"))[\"default\"][\"prototype\"];\n\n  constructor(params: AsyncCallerParams) {\n    this.maxConcurrency = params.maxConcurrency ?? Infinity;\n    this.maxRetries = params.maxRetries ?? 6;\n    this.onFailedAttempt =\n      params.onFailedAttempt ?? defaultFailedAttemptHandler;\n\n    const PQueue = (\n      \"default\" in PQueueMod ? PQueueMod.default : PQueueMod\n    ) as typeof PQueueMod;\n    this.queue = new PQueue({ concurrency: this.maxConcurrency });\n  }\n\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  async call<A extends any[], T extends (...args: A) => Promise<any>>(\n    callable: T,\n    ...args: Parameters<T>\n  ): Promise<Awaited<ReturnType<T>>> {\n    return this.queue.add(\n      () =>\n        pRetry(\n          () =>\n            callable(...args).catch((error) => {\n              // oxlint-disable-next-line no-instanceof/no-instanceof\n              if (error instanceof Error) {\n                throw error;\n              } else {\n                throw new Error(error);\n              }\n            }),\n          {\n            onFailedAttempt: ({ error }) => this.onFailedAttempt?.(error),\n            retries: this.maxRetries,\n            randomize: true,\n            // If needed we can change some of the defaults here,\n            // but they're quite sensible.\n          }\n        ),\n      { throwOnTimeout: true }\n    );\n  }\n\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  callWithOptions<A extends any[], T extends (...args: A) => Promise<any>>(\n    options: AsyncCallerCallOptions,\n    callable: T,\n    ...args: Parameters<T>\n  ): Promise<Awaited<ReturnType<T>>> {\n    // Note this doesn't cancel the underlying request,\n    // when available prefer to use the signal option of the underlying call\n    if (options.signal) {\n      let listener: (() => void) | undefined;\n      return Promise.race([\n        this.call<A, T>(callable, ...args),\n        new Promise<never>((_, reject) => {\n          listener = () => {\n            reject(getAbortSignalError(options.signal));\n          };\n          options.signal?.addEventListener(\"abort\", listener, { once: true });\n        }),\n      ]).finally(() => {\n        if (options.signal && listener) {\n          options.signal.removeEventListener(\"abort\", listener);\n        }\n      });\n    }\n    return this.call<A, T>(callable, ...args);\n  }\n\n  fetch(...args: Parameters<typeof fetch>): ReturnType<typeof fetch> {\n    return this.call(() =>\n      fetch(...args).then((res) => (res.ok ? res : Promise.reject(res)))\n    );\n  }\n}\n"],"mappings":";;;;;;;;AAKA,MAAM,kBAAkB;CACtB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;;;;;AAOD,MAAM,+BAA+B,UAAmB;AACtD,KAAI,OAAO,UAAU,YAAY,UAAU,KACzC;AAGF,KACG,aAAa,SACZ,OAAO,MAAM,YAAY,aACxB,MAAM,QAAQ,WAAW,SAAS,IACjC,MAAM,QAAQ,WAAW,aAAa,KACzC,UAAU,SACT,OAAO,MAAM,SAAS,YACtB,MAAM,SAAS,aAEjB,OAAM;AAER,KACE,UAAU,SACV,OAAO,MAAM,SAAS,YACtB,MAAM,SAAS,eAEf,OAAM;CAER,MAAM,iBACJ,cAAc,SACd,OAAO,MAAM,aAAa,YAC1B,MAAM,aAAa,QACnB,YAAY,MAAM,YAClB,OAAO,MAAM,SAAS,WAAW,WAC7B,MAAM,SAAS,SACf,KAAA;CAGN,MAAM,eACJ,YAAY,SAAS,OAAO,MAAM,WAAW,WACzC,MAAM,SACN,KAAA;CAEN,MAAM,SAAS,kBAAkB;AACjC,KAAI,UAAU,gBAAgB,SAAS,CAAC,OAAO,CAC7C,OAAM;AAWR,MAPE,WAAW,SACX,OAAO,MAAM,UAAU,YACvB,MAAM,UAAU,QAChB,UAAU,MAAM,SAChB,OAAO,MAAM,MAAM,SAAS,WACxB,MAAM,MAAM,OACZ,KAAA,OACO,sBAAsB;EACjC,MAAM,MAAM,IAAI,MACd,aAAa,SAAS,OAAO,MAAM,YAAY,WAC3C,MAAM,UACN,qBACL;AACD,MAAI,OAAO;AACX,QAAM;;;;;;;;;;;;;;;;AA2CV,IAAa,cAAb,MAAyB;CACvB;CAEA;CAEA;CAEA;CAEA,YAAY,QAA2B;AACrC,OAAK,iBAAiB,OAAO,kBAAkB;AAC/C,OAAK,aAAa,OAAO,cAAc;AACvC,OAAK,kBACH,OAAO,mBAAmB;AAK5B,OAAK,QAAQ,KAFX,aAAaA,QAAAA,UAAYA,QAAAA,QAAU,UAAUA,QAAAA,SAEvB,EAAE,aAAa,KAAK,gBAAgB,CAAC;;CAI/D,MAAM,KACJ,UACA,GAAG,MAC8B;AACjC,SAAO,KAAK,MAAM,UAEdC,cAAAA,cAEI,SAAS,GAAG,KAAK,CAAC,OAAO,UAAU;AAEjC,OAAI,iBAAiB,MACnB,OAAM;OAEN,OAAM,IAAI,MAAM,MAAM;IAExB,EACJ;GACE,kBAAkB,EAAE,YAAY,KAAK,kBAAkB,MAAM;GAC7D,SAAS,KAAK;GACd,WAAW;GAGZ,CACF,EACH,EAAE,gBAAgB,MAAM,CACzB;;CAIH,gBACE,SACA,UACA,GAAG,MAC8B;AAGjC,MAAI,QAAQ,QAAQ;GAClB,IAAI;AACJ,UAAO,QAAQ,KAAK,CAClB,KAAK,KAAW,UAAU,GAAG,KAAK,EAClC,IAAI,SAAgB,GAAG,WAAW;AAChC,qBAAiB;AACf,YAAOC,eAAAA,oBAAoB,QAAQ,OAAO,CAAC;;AAE7C,YAAQ,QAAQ,iBAAiB,SAAS,UAAU,EAAE,MAAM,MAAM,CAAC;KACnE,CACH,CAAC,CAAC,cAAc;AACf,QAAI,QAAQ,UAAU,SACpB,SAAQ,OAAO,oBAAoB,SAAS,SAAS;KAEvD;;AAEJ,SAAO,KAAK,KAAW,UAAU,GAAG,KAAK;;CAG3C,MAAM,GAAG,MAA0D;AACjE,SAAO,KAAK,WACV,MAAM,GAAG,KAAK,CAAC,MAAM,QAAS,IAAI,KAAK,MAAM,QAAQ,OAAO,IAAI,CAAE,CACnE"}