{"version":3,"file":"ai-model/service-caller/semantic-retry.mjs","sources":["../../../../src/ai-model/service-caller/semantic-retry.ts"],"sourcesContent":["export type CallAiAndParseWithRetryOptions<Response, Parsed> = {\n  /** Sends a single model request. Request errors are always propagated as-is. */\n  callAi: () => Promise<Response>;\n  /** Parses a successful model response. Only failures from this callback retry. */\n  parseResponse: (response: Response) => Parsed | Promise<Parsed>;\n  /** Converts the final parsing failure into the caller's domain error. */\n  toParseError: (error: unknown, response: Response) => Error;\n  /** Number of additional model requests after a parsing failure. Defaults to 0. */\n  parseRetryTimes?: number;\n  abortSignal?: AbortSignal;\n  /** Runs immediately before a parsing failure triggers another model request. */\n  onParseRetry?: (error: unknown, response: Response) => void;\n};\n\n/**\n * Calls AI and parses its response, retrying only when the response cannot be\n * structurally parsed.\n *\n * Errors thrown by callAi() intentionally bypass this retry mechanism and are\n * propagated as-is. Only a successful callAi() response that fails the\n * parseResponse() callback triggers another model request.\n */\nexport async function callAiAndParseWithRetry<Response, Parsed>({\n  callAi,\n  parseResponse,\n  toParseError,\n  parseRetryTimes = 0,\n  abortSignal,\n  onParseRetry,\n}: CallAiAndParseWithRetryOptions<Response, Parsed>): Promise<Parsed> {\n  const normalizedRetryTimes = Number.isFinite(parseRetryTimes)\n    ? Math.max(0, Math.floor(parseRetryTimes))\n    : 0;\n\n  const callAndParseOnce = async (\n    remainingRetries: number,\n  ): Promise<Parsed> => {\n    const response = await callAi();\n\n    try {\n      return await parseResponse(response);\n    } catch (error) {\n      if (remainingRetries > 0 && !abortSignal?.aborted) {\n        onParseRetry?.(error, response);\n        return callAndParseOnce(remainingRetries - 1);\n      }\n      throw toParseError(error, response);\n    }\n  };\n\n  return callAndParseOnce(normalizedRetryTimes);\n}\n"],"names":["callAiAndParseWithRetry","callAi","parseResponse","toParseError","parseRetryTimes","abortSignal","onParseRetry","normalizedRetryTimes","Number","Math","callAndParseOnce","remainingRetries","response","error"],"mappings":"AAsBO,eAAeA,wBAA0C,EAC9DC,MAAM,EACNC,aAAa,EACbC,YAAY,EACZC,kBAAkB,CAAC,EACnBC,WAAW,EACXC,YAAY,EACqC;IACjD,MAAMC,uBAAuBC,OAAO,QAAQ,CAACJ,mBACzCK,KAAK,GAAG,CAAC,GAAGA,KAAK,KAAK,CAACL,oBACvB;IAEJ,MAAMM,mBAAmB,OACvBC;QAEA,MAAMC,WAAW,MAAMX;QAEvB,IAAI;YACF,OAAO,MAAMC,cAAcU;QAC7B,EAAE,OAAOC,OAAO;YACd,IAAIF,mBAAmB,KAAK,CAACN,aAAa,SAAS;gBACjDC,eAAeO,OAAOD;gBACtB,OAAOF,iBAAiBC,mBAAmB;YAC7C;YACA,MAAMR,aAAaU,OAAOD;QAC5B;IACF;IAEA,OAAOF,iBAAiBH;AAC1B"}