{"version":3,"file":"ai-model/service-caller/index.mjs","sources":["../../../../src/ai-model/service-caller/index.ts"],"sourcesContent":["import type { AIUsageInfo } from '@/types';\nimport type { CodeGenerationChunk, StreamingCallback } from '@/types';\n\n// Error class that preserves usage and rawResponse when AI call parsing fails\nexport class AIResponseParseError extends Error {\n  usage?: AIUsageInfo;\n  /**\n   * Adapter-extracted content used by Midscene for parsing. This is not the\n   * full provider response or choices[0].message.\n   */\n  rawResponse: string;\n  rawChoiceMessage?: unknown;\n\n  constructor(\n    message: string,\n    rawResponse: string,\n    usage?: AIUsageInfo,\n    rawChoiceMessage?: unknown,\n  ) {\n    super(message);\n    this.name = 'AIResponseParseError';\n    this.rawResponse = rawResponse;\n    this.usage = usage;\n    this.rawChoiceMessage = rawChoiceMessage;\n  }\n}\nimport {\n  type IModelConfig,\n  MIDSCENE_LANGFUSE_DEBUG,\n  MIDSCENE_LANGSMITH_DEBUG,\n  type TModelFamily,\n  globalConfigManager,\n} from '@midscene/shared/env';\n\nimport { getDebug } from '@midscene/shared/logger';\nimport { assert, ifInBrowser } from '@midscene/shared/utils';\nimport OpenAI from 'openai';\nimport type { ChatCompletionMessageParam } from 'openai/resources/index';\nimport type { Stream } from 'openai/streaming';\nimport { type ModelRuntime, getModelRuntime } from '../models';\nimport type { AIArgs } from '../types';\nimport {\n  callAIWithCodexAppServer,\n  isCodexAppServerProvider,\n} from './codex-app-server';\nimport type { JsonParserSource } from './json';\nimport {\n  buildRequestAbortSignal,\n  isHardTimeoutError,\n  resolveEffectiveTimeoutMs,\n} from './request-timeout';\nexport {\n  extractJSONFromCodeBlock,\n  normalJsonParser,\n  safeParseJson,\n} from './json';\nexport type { JsonParser } from './json';\n\nfunction stringifyForDebug(value: unknown): string {\n  try {\n    return JSON.stringify(value);\n  } catch (_error) {\n    return String(value);\n  }\n}\n\nfunction getErrorMessage(error: unknown): string {\n  return error instanceof Error ? error.message : String(error);\n}\n\nfunction toError(error: unknown): Error {\n  return error instanceof Error ? error : new Error(String(error));\n}\n\nfunction normalizeRetryCount(retryCount: unknown): number {\n  if (typeof retryCount !== 'number' || !Number.isFinite(retryCount)) {\n    return 1;\n  }\n\n  return Math.max(0, Math.floor(retryCount));\n}\n\nfunction appendAIRequestFailureSummary<T extends Error>(\n  error: T,\n  attemptErrors: Array<{ attempt: number; error: unknown }>,\n  maxAttempts: number,\n): T {\n  const failedAttempts = attemptErrors.length;\n  const retries = Math.max(0, failedAttempts - 1);\n  const retryLabel = retries === 1 ? 'retry' : 'retries';\n  const originalMessage = error.message;\n  const previousAttemptErrors = attemptErrors.slice(0, -1);\n\n  error.message = `AI model request failed after ${retries} ${retryLabel} (${failedAttempts}/${maxAttempts} attempts). Last error: ${originalMessage}`;\n\n  if (previousAttemptErrors.length === 0) {\n    return error;\n  }\n\n  const details = previousAttemptErrors\n    .map(\n      ({ attempt, error }) => `Attempt ${attempt}: ${getErrorMessage(error)}`,\n    )\n    .join('\\n');\n\n  error.message = `${error.message}\\nPrevious AI call attempt errors:\\n${details}`;\n  return error;\n}\n\nexport async function createChatClient({\n  modelConfig,\n}: {\n  modelConfig: IModelConfig;\n}): Promise<{\n  completion: OpenAI.Chat.Completions;\n  modelName: string;\n  modelDescription: string;\n  modelFamily: TModelFamily | undefined;\n}> {\n  const {\n    socksProxy,\n    httpProxy,\n    modelName,\n    openaiBaseURL,\n    openaiApiKey,\n    openaiExtraConfig,\n    modelDescription,\n    modelFamily,\n    createOpenAIClient,\n    timeout,\n  } = modelConfig;\n\n  let proxyAgent: any = undefined;\n  const warnClient = getDebug('ai:call', { console: true });\n  const debugProxy = getDebug('ai:call:proxy');\n  const warnProxy = getDebug('ai:call:proxy', { console: true });\n\n  // Helper function to sanitize proxy URL for logging (remove credentials)\n  // Uses URL API instead of regex to avoid ReDoS vulnerabilities\n  const sanitizeProxyUrl = (url: string): string => {\n    try {\n      const parsed = new URL(url);\n      if (parsed.username) {\n        // Keep username for debugging, hide password for security\n        parsed.password = '****';\n        return parsed.href;\n      }\n      return url;\n    } catch {\n      // If URL parsing fails, return original URL (will be caught later)\n      return url;\n    }\n  };\n\n  if (httpProxy) {\n    debugProxy('using http proxy', sanitizeProxyUrl(httpProxy));\n    if (ifInBrowser) {\n      warnProxy(\n        'HTTP proxy is configured but not supported in browser environment',\n      );\n    } else {\n      // Dynamic import with variable to avoid bundler static analysis\n      const moduleName = 'undici';\n      const { ProxyAgent } = await import(moduleName);\n      proxyAgent = new ProxyAgent({\n        uri: httpProxy,\n        // Note: authentication is handled via the URI (e.g., http://user:pass@proxy.com:8080)\n      });\n    }\n  } else if (socksProxy) {\n    debugProxy('using socks proxy', sanitizeProxyUrl(socksProxy));\n    if (ifInBrowser) {\n      warnProxy(\n        'SOCKS proxy is configured but not supported in browser environment',\n      );\n    } else {\n      try {\n        // Dynamic import with variable to avoid bundler static analysis\n        const moduleName = 'fetch-socks';\n        const { socksDispatcher } = await import(moduleName);\n        // Parse SOCKS proxy URL (e.g., socks5://127.0.0.1:1080)\n        const proxyUrl = new URL(socksProxy);\n\n        // Validate hostname\n        if (!proxyUrl.hostname) {\n          throw new Error('SOCKS proxy URL must include a valid hostname');\n        }\n\n        // Validate and parse port\n        const port = Number.parseInt(proxyUrl.port, 10);\n        if (!proxyUrl.port || Number.isNaN(port)) {\n          throw new Error('SOCKS proxy URL must include a valid port');\n        }\n\n        // Parse SOCKS version from protocol\n        const protocol = proxyUrl.protocol.replace(':', '');\n        const socksType =\n          protocol === 'socks4' ? 4 : protocol === 'socks5' ? 5 : 5;\n\n        proxyAgent = socksDispatcher({\n          type: socksType,\n          host: proxyUrl.hostname,\n          port,\n          ...(proxyUrl.username\n            ? {\n                userId: decodeURIComponent(proxyUrl.username),\n                password: decodeURIComponent(proxyUrl.password || ''),\n              }\n            : {}),\n        });\n        debugProxy('socks proxy configured successfully', {\n          type: socksType,\n          host: proxyUrl.hostname,\n          port: port,\n        });\n      } catch (error) {\n        warnProxy('Failed to configure SOCKS proxy:', error);\n        throw new Error(\n          `Invalid SOCKS proxy URL: ${socksProxy}. Expected format: socks4://host:port, socks5://host:port, or with authentication: socks5://user:pass@host:port`,\n        );\n      }\n    }\n  }\n\n  const effectiveTimeoutMs = resolveEffectiveTimeoutMs({ timeout });\n  const openAIOptions = {\n    baseURL: openaiBaseURL,\n    apiKey: openaiApiKey,\n    // Use fetchOptions.dispatcher for fetch-based SDK instead of httpAgent\n    // Note: Type assertion needed due to undici version mismatch between dependencies\n    ...(proxyAgent ? { fetchOptions: { dispatcher: proxyAgent as any } } : {}),\n    ...openaiExtraConfig,\n    // Midscene already handles retries in callAI(), so disable SDK-level retries\n    // to avoid duplicate attempts and duplicated backoff latency.\n    maxRetries: 0,\n    // When disabled (timeoutMs === null) fall through to the SDK default so\n    // only the caller-provided abortSignal can cancel the request.\n    ...(effectiveTimeoutMs !== null ? { timeout: effectiveTimeoutMs } : {}),\n    dangerouslyAllowBrowser: true,\n  };\n\n  const baseOpenAI = new OpenAI(openAIOptions);\n\n  let openai: OpenAI = baseOpenAI;\n\n  // LangSmith wrapper\n  if (\n    openai &&\n    globalConfigManager.getEnvConfigInBoolean(MIDSCENE_LANGSMITH_DEBUG)\n  ) {\n    if (ifInBrowser) {\n      throw new Error('langsmith is not supported in browser');\n    }\n    warnClient('DEBUGGING MODE: langsmith wrapper enabled');\n    // Use variable to prevent static analysis by bundlers\n    const langsmithModule = 'langsmith/wrappers';\n    const { wrapOpenAI } = await import(langsmithModule);\n    openai = wrapOpenAI(openai);\n  }\n\n  // Langfuse wrapper\n  if (\n    openai &&\n    globalConfigManager.getEnvConfigInBoolean(MIDSCENE_LANGFUSE_DEBUG)\n  ) {\n    if (ifInBrowser) {\n      throw new Error('langfuse is not supported in browser');\n    }\n    warnClient('DEBUGGING MODE: langfuse wrapper enabled');\n    // Use variable to prevent static analysis by bundlers\n    const langfuseModule = '@langfuse/openai';\n    const { observeOpenAI } = await import(langfuseModule);\n    openai = observeOpenAI(openai);\n  }\n\n  if (createOpenAIClient) {\n    const wrappedClient = await createOpenAIClient(baseOpenAI, openAIOptions);\n\n    if (wrappedClient) {\n      openai = wrappedClient as OpenAI;\n    }\n  }\n\n  return {\n    completion: openai.chat.completions,\n    modelName,\n    modelDescription,\n    modelFamily,\n  };\n}\n\ninterface CallAIOptions {\n  stream?: boolean;\n  onChunk?: StreamingCallback;\n  abortSignal?: AbortSignal;\n  requiresOriginalImageDetail?: boolean;\n}\n\nexport async function callAI(\n  messages: ChatCompletionMessageParam[],\n  modelRuntime: ModelRuntime,\n  options?: CallAIOptions,\n): Promise<{\n  content: string;\n  reasoning_content?: string;\n  rawChoiceMessage?: unknown;\n  usage?: AIUsageInfo;\n  isStreamed: boolean;\n}> {\n  const { config: modelConfig, adapter } = modelRuntime;\n\n  if (isCodexAppServerProvider(modelConfig.openaiBaseURL)) {\n    return callAIWithCodexAppServer(messages, modelConfig, {\n      stream: options?.stream,\n      onChunk: options?.onChunk,\n      reasoningEnabled: modelConfig.reasoningEnabled,\n      abortSignal: options?.abortSignal,\n    });\n  }\n\n  const { completion, modelName, modelDescription, modelFamily } =\n    await createChatClient({\n      modelConfig,\n    });\n  const effectiveTimeoutMs = resolveEffectiveTimeoutMs(modelConfig);\n\n  const extraBody = modelConfig.extraBody;\n\n  const debugCall = getDebug('ai:call');\n  const warnCall = getDebug('ai:call', { console: true });\n  const debugProfileStats = getDebug('ai:profile:stats');\n  const debugProfileDetail = getDebug('ai:profile:detail');\n\n  const startTime = Date.now();\n\n  const isStreaming = options?.stream && options?.onChunk;\n  const chatCompletionInput = {\n    intent: modelConfig.intent,\n    userConfig: {\n      temperature: modelConfig.temperature,\n      reasoningEnabled: modelConfig.reasoningEnabled,\n      reasoningEffort: modelConfig.reasoningEffort,\n      reasoningBudget: modelConfig.reasoningBudget,\n    },\n    requiresOriginalImageDetail: options?.requiresOriginalImageDetail,\n  };\n  const { config: adapterChatCompletionParams } =\n    adapter.chatCompletion.buildChatCompletionParams(chatCompletionInput);\n  debugCall(\n    `adapter chat completion params: ${stringifyForDebug({\n      config: adapterChatCompletionParams,\n    })}`,\n  );\n  let content: string | undefined;\n  let accumulated = '';\n  let accumulatedReasoning = '';\n  let rawChoiceMessage: unknown;\n  let usage: OpenAI.CompletionUsage | undefined;\n  let timeCost: number | undefined;\n  let requestId: string | null | undefined;\n  let responseModelName: string | undefined;\n\n  const hasUsableText = (value: string | null | undefined): value is string =>\n    typeof value === 'string' && value.trim().length > 0;\n\n  const buildUsageInfo = (\n    usageData?: OpenAI.CompletionUsage,\n    requestId?: string | null,\n  ) => {\n    if (!usageData) return undefined;\n\n    const cachedInputTokens = (\n      usageData as { prompt_tokens_details?: { cached_tokens?: number } }\n    )?.prompt_tokens_details?.cached_tokens;\n\n    return {\n      ...usageData,\n      prompt_tokens: usageData.prompt_tokens ?? 0,\n      completion_tokens: usageData.completion_tokens ?? 0,\n      total_tokens: usageData.total_tokens ?? 0,\n      cached_input: cachedInputTokens ?? 0,\n      time_cost: timeCost ?? 0,\n      model_name: modelName,\n      model_description: modelDescription,\n      response_model_name: responseModelName,\n      slot: modelConfig.slot,\n      // Agent task layers fill semantic intent after the raw model call.\n      intent: undefined,\n      request_id: requestId ?? undefined,\n    } satisfies AIUsageInfo;\n  };\n\n  const requestConfig = {\n    ...adapterChatCompletionParams,\n    ...(extraBody ?? {}),\n  };\n  const temperature = requestConfig.temperature;\n\n  const imageDetail =\n    adapter.chatCompletion.resolveImageDetail(chatCompletionInput);\n\n  // Some adapters request original image detail to preserve screenshot\n  // resolution for localization-sensitive tasks.\n  const messagesWithImageDetail: ChatCompletionMessageParam[] = (() => {\n    if (!imageDetail) {\n      return messages;\n    }\n\n    return messages.map((msg) => {\n      if (!Array.isArray(msg.content)) {\n        return msg;\n      }\n\n      const content = msg.content.map((part) => {\n        if (part && part.type === 'image_url' && part.image_url?.url) {\n          return {\n            ...part,\n            image_url: {\n              ...part.image_url,\n              detail: imageDetail,\n            },\n          };\n        }\n        return part;\n      });\n\n      return {\n        ...msg,\n        content,\n      } as ChatCompletionMessageParam;\n    });\n  })();\n\n  try {\n    debugCall(\n      `sending ${isStreaming ? 'streaming ' : ''}request to ${modelName}`,\n    );\n\n    if (isStreaming) {\n      const { signal: streamSignal, cleanup: cleanupStreamSignal } =\n        buildRequestAbortSignal(effectiveTimeoutMs, options?.abortSignal);\n      try {\n        const stream = (await completion.create(\n          {\n            model: modelName,\n            messages: messagesWithImageDetail,\n            ...requestConfig,\n            stream: true,\n          },\n          {\n            stream: true,\n            signal: streamSignal,\n          },\n        )) as Stream<OpenAI.Chat.Completions.ChatCompletionChunk> & {\n          _request_id?: string | null;\n        };\n\n        requestId = stream._request_id;\n\n        for await (const chunk of stream) {\n          const parsedChunk = adapter.chatCompletion.extractContentAndReasoning(\n            chunk.choices?.[0]?.delta,\n          );\n          const content = parsedChunk.content || '';\n          const reasoning_content = parsedChunk.reasoning_content || '';\n\n          // Check for usage info in any chunk (OpenAI provides usage in separate chunks)\n          if (chunk.usage) {\n            usage = chunk.usage;\n          }\n          if (chunk.model) {\n            responseModelName = chunk.model;\n          }\n\n          if (content || reasoning_content) {\n            accumulated += content;\n            accumulatedReasoning += reasoning_content;\n            const chunkData: CodeGenerationChunk = {\n              content,\n              reasoning_content,\n              accumulated,\n              isComplete: false,\n              usage: undefined,\n            };\n            options.onChunk!(chunkData);\n          }\n\n          // Check if stream is complete\n          if (chunk.choices?.[0]?.finish_reason) {\n            timeCost = Date.now() - startTime;\n\n            // If usage is not available from the stream, provide a basic usage info\n            if (!usage) {\n              // Estimate token counts based on content length (rough approximation)\n              const estimatedTokens = Math.max(\n                1,\n                Math.floor(accumulated.length / 4),\n              );\n              usage = {\n                prompt_tokens: estimatedTokens,\n                completion_tokens: estimatedTokens,\n                total_tokens: estimatedTokens * 2,\n              };\n            }\n\n            // Send final chunk\n            const finalChunk: CodeGenerationChunk = {\n              content: '',\n              accumulated,\n              reasoning_content: '',\n              isComplete: true,\n              usage: buildUsageInfo(usage, requestId),\n            };\n            options.onChunk!(finalChunk);\n            break;\n          }\n        }\n      } finally {\n        cleanupStreamSignal();\n      }\n      content = accumulated;\n      debugProfileStats(\n        `streaming model, ${modelName}, mode, ${modelFamily || 'default'}, cost-ms, ${timeCost}, temperature, ${temperature ?? ''}`,\n      );\n    } else {\n      // Non-streaming with retry logic\n      const retryCount = normalizeRetryCount(modelConfig.retryCount);\n      const retryInterval = modelConfig.retryInterval ?? 2000;\n      const maxAttempts = retryCount + 1; // retryCount=1 means 2 total attempts (1 initial + 1 retry)\n\n      let lastError: Error | undefined;\n      const attemptErrors: Array<{ attempt: number; error: unknown }> = [];\n\n      for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n        const { signal: attemptSignal, cleanup: cleanupAttemptSignal } =\n          buildRequestAbortSignal(effectiveTimeoutMs, options?.abortSignal);\n        try {\n          const result = await completion.create(\n            {\n              model: modelName,\n              messages: messagesWithImageDetail,\n              ...requestConfig,\n              stream: false,\n            } as any,\n            { signal: attemptSignal },\n          );\n\n          timeCost = Date.now() - startTime;\n\n          debugProfileStats(\n            `model, ${modelName}, mode, ${modelFamily || 'default'}, prompt-tokens, ${result.usage?.prompt_tokens || ''}, completion-tokens, ${result.usage?.completion_tokens || ''}, total-tokens, ${result.usage?.total_tokens || ''}, cost-ms, ${timeCost}, requestId, ${result._request_id || ''}, temperature, ${temperature ?? ''}`,\n          );\n\n          debugProfileDetail(\n            `model usage detail: ${JSON.stringify(result.usage)}`,\n          );\n\n          if (!result.choices) {\n            throw new Error(\n              `invalid response from LLM service: ${JSON.stringify(result)}`,\n            );\n          }\n\n          rawChoiceMessage = result.choices[0].message;\n          const parsedMessage =\n            adapter.chatCompletion.extractContentAndReasoning(\n              result.choices[0].message,\n            );\n          content = parsedMessage.content;\n          accumulatedReasoning = parsedMessage.reasoning_content;\n          usage = result.usage;\n          requestId = result._request_id;\n          responseModelName = result.model;\n\n          if (!hasUsableText(content) && hasUsableText(accumulatedReasoning)) {\n            warnCall('empty content from AI model, using reasoning content');\n            content = accumulatedReasoning;\n          }\n\n          if (!hasUsableText(content)) {\n            throw new AIResponseParseError(\n              'empty content from AI model',\n              JSON.stringify(result),\n              buildUsageInfo(usage, requestId),\n              rawChoiceMessage,\n            );\n          }\n\n          break; // Success, exit retry loop\n        } catch (error) {\n          lastError = toError(error);\n          attemptErrors.push({ attempt, error });\n          const wasHardTimeout = isHardTimeoutError(lastError);\n          if (wasHardTimeout) {\n            warnCall(\n              `AI call hit hard timeout (${effectiveTimeoutMs}ms, attempt ${attempt}/${maxAttempts}, model ${modelName}, slot ${modelConfig.slot})`,\n            );\n          }\n          // Do not retry if the request was aborted by the caller\n          if (options?.abortSignal?.aborted) {\n            break;\n          }\n          if (attempt < maxAttempts) {\n            warnCall(\n              `AI call failed (attempt ${attempt}/${maxAttempts}), retrying in ${retryInterval}ms... Error: ${lastError.message}`,\n            );\n            await new Promise((resolve) => setTimeout(resolve, retryInterval));\n          }\n        } finally {\n          cleanupAttemptSignal();\n        }\n      }\n\n      if (!content) {\n        assert(\n          lastError,\n          'AI model request failed without recording an attempt error',\n        );\n        throw appendAIRequestFailureSummary(\n          lastError,\n          attemptErrors,\n          maxAttempts,\n        );\n      }\n    }\n\n    debugCall(`response reasoning content: ${accumulatedReasoning}`);\n    debugCall(`response content: ${content}`);\n\n    // Ensure we always have usage info for streaming responses\n    if (isStreaming && !usage) {\n      // Estimate token counts based on content length (rough approximation)\n      const estimatedTokens = Math.max(\n        1,\n        Math.floor((content || '').length / 4),\n      );\n      usage = {\n        prompt_tokens: estimatedTokens,\n        completion_tokens: estimatedTokens,\n        total_tokens: estimatedTokens * 2,\n      } as OpenAI.CompletionUsage;\n    }\n\n    return {\n      content: content || '',\n      reasoning_content: accumulatedReasoning || undefined,\n      rawChoiceMessage,\n      usage: buildUsageInfo(usage, requestId),\n      isStreamed: !!isStreaming,\n    };\n  } catch (e: any) {\n    warnCall('call AI error', e);\n\n    if (e instanceof AIResponseParseError) {\n      throw e;\n    }\n\n    const newError = new Error(\n      `failed to call ${isStreaming ? 'streaming ' : ''}AI model service (${modelName}): ${e.message}\\nTrouble shooting: https://midscenejs.com/model-provider.html`,\n      {\n        cause: e,\n      },\n    );\n    throw newError;\n  }\n}\n\nexport async function callAIWithObjectResponse<T>(\n  messages: ChatCompletionMessageParam[],\n  // Keep IModelConfig compatibility for midscene-example/connectivity-test/tests/connectivity.test.ts; internal workflow callers should pass ModelRuntime instead.\n  model: IModelConfig | ModelRuntime,\n  options?: {\n    abortSignal?: AbortSignal;\n    jsonParserSource?: JsonParserSource;\n  },\n): Promise<{\n  // TODO: `content` is a misleading name here because this is already the parsed object response. Consider renaming it to `object` or `data`.\n  content: T;\n  contentString: string;\n  usage?: AIUsageInfo;\n  reasoning_content?: string;\n  rawChoiceMessage?: unknown;\n}> {\n  const modelRuntime = resolveCompatibleModelRuntime(model);\n  const { config: modelConfig, adapter } = modelRuntime;\n  const response = await callAI(messages, modelRuntime, {\n    abortSignal: options?.abortSignal,\n  });\n  assert(response, 'empty response');\n  let jsonContent: unknown;\n  try {\n    jsonContent = adapter.jsonParser(response.content, {\n      source: options?.jsonParserSource ?? 'generic-object',\n    });\n  } catch (error) {\n    const errorMessage = error instanceof Error ? error.message : String(error);\n    throw new AIResponseParseError(\n      errorMessage,\n      response.content,\n      response.usage,\n    );\n  }\n  if (typeof jsonContent !== 'object') {\n    throw new AIResponseParseError(\n      `failed to parse json response from model (${modelConfig.modelName}): ${response.content}`,\n      response.content,\n      response.usage,\n      response.rawChoiceMessage,\n    );\n  }\n  return {\n    content: jsonContent as T,\n    contentString: response.content,\n    usage: response.usage,\n    reasoning_content: response.reasoning_content,\n    rawChoiceMessage: response.rawChoiceMessage,\n  };\n}\n\nfunction resolveCompatibleModelRuntime(\n  model: IModelConfig | ModelRuntime,\n): ModelRuntime {\n  if ('config' in model && 'adapter' in model) {\n    return model;\n  }\n\n  return getModelRuntime(model);\n}\n\nexport async function callAIWithStringResponse(\n  msgs: AIArgs,\n  modelRuntime: ModelRuntime,\n  options?: Pick<CallAIOptions, 'abortSignal' | 'requiresOriginalImageDetail'>,\n): Promise<{\n  content: string;\n  usage?: AIUsageInfo;\n  rawChoiceMessage?: unknown;\n}> {\n  const { content, usage, rawChoiceMessage } = await callAI(\n    msgs,\n    modelRuntime,\n    options,\n  );\n  return { content, usage, rawChoiceMessage };\n}\n"],"names":["AIResponseParseError","Error","message","rawResponse","usage","rawChoiceMessage","stringifyForDebug","value","JSON","_error","String","getErrorMessage","error","toError","normalizeRetryCount","retryCount","Number","Math","appendAIRequestFailureSummary","attemptErrors","maxAttempts","failedAttempts","retries","retryLabel","originalMessage","previousAttemptErrors","details","attempt","createChatClient","modelConfig","socksProxy","httpProxy","modelName","openaiBaseURL","openaiApiKey","openaiExtraConfig","modelDescription","modelFamily","createOpenAIClient","timeout","proxyAgent","warnClient","getDebug","debugProxy","warnProxy","sanitizeProxyUrl","url","parsed","URL","ifInBrowser","moduleName","ProxyAgent","socksDispatcher","proxyUrl","port","protocol","socksType","decodeURIComponent","effectiveTimeoutMs","resolveEffectiveTimeoutMs","openAIOptions","baseOpenAI","OpenAI","openai","globalConfigManager","MIDSCENE_LANGSMITH_DEBUG","langsmithModule","wrapOpenAI","MIDSCENE_LANGFUSE_DEBUG","langfuseModule","observeOpenAI","wrappedClient","callAI","messages","modelRuntime","options","adapter","isCodexAppServerProvider","callAIWithCodexAppServer","completion","extraBody","debugCall","warnCall","debugProfileStats","debugProfileDetail","startTime","Date","isStreaming","chatCompletionInput","adapterChatCompletionParams","content","accumulated","accumulatedReasoning","timeCost","requestId","responseModelName","hasUsableText","buildUsageInfo","usageData","cachedInputTokens","undefined","requestConfig","temperature","imageDetail","messagesWithImageDetail","msg","Array","part","streamSignal","cleanupStreamSignal","buildRequestAbortSignal","stream","chunk","parsedChunk","reasoning_content","chunkData","estimatedTokens","finalChunk","retryInterval","lastError","attemptSignal","cleanupAttemptSignal","result","parsedMessage","wasHardTimeout","isHardTimeoutError","Promise","resolve","setTimeout","assert","e","newError","callAIWithObjectResponse","model","resolveCompatibleModelRuntime","response","jsonContent","errorMessage","getModelRuntime","callAIWithStringResponse","msgs"],"mappings":";;;;;;;;;;;;;;;;;;AAIO,MAAMA,6BAA6BC;IASxC,YACEC,OAAe,EACfC,WAAmB,EACnBC,KAAmB,EACnBC,gBAA0B,CAC1B;QACA,KAAK,CAACH,UAdR,yCAKA,+CACA;QASE,IAAI,CAAC,IAAI,GAAG;QACZ,IAAI,CAAC,WAAW,GAAGC;QACnB,IAAI,CAAC,KAAK,GAAGC;QACb,IAAI,CAAC,gBAAgB,GAAGC;IAC1B;AACF;AAiCA,SAASC,kBAAkBC,KAAc;IACvC,IAAI;QACF,OAAOC,KAAK,SAAS,CAACD;IACxB,EAAE,OAAOE,QAAQ;QACf,OAAOC,OAAOH;IAChB;AACF;AAEA,SAASI,gBAAgBC,KAAc;IACrC,OAAOA,iBAAiBX,QAAQW,MAAM,OAAO,GAAGF,OAAOE;AACzD;AAEA,SAASC,QAAQD,KAAc;IAC7B,OAAOA,iBAAiBX,QAAQW,QAAQ,IAAIX,MAAMS,OAAOE;AAC3D;AAEA,SAASE,oBAAoBC,UAAmB;IAC9C,IAAI,AAAsB,YAAtB,OAAOA,cAA2B,CAACC,OAAO,QAAQ,CAACD,aACrD,OAAO;IAGT,OAAOE,KAAK,GAAG,CAAC,GAAGA,KAAK,KAAK,CAACF;AAChC;AAEA,SAASG,8BACPN,KAAQ,EACRO,aAAyD,EACzDC,WAAmB;IAEnB,MAAMC,iBAAiBF,cAAc,MAAM;IAC3C,MAAMG,UAAUL,KAAK,GAAG,CAAC,GAAGI,iBAAiB;IAC7C,MAAME,aAAaD,AAAY,MAAZA,UAAgB,UAAU;IAC7C,MAAME,kBAAkBZ,MAAM,OAAO;IACrC,MAAMa,wBAAwBN,cAAc,KAAK,CAAC,GAAG;IAErDP,MAAM,OAAO,GAAG,CAAC,8BAA8B,EAAEU,QAAQ,CAAC,EAAEC,WAAW,EAAE,EAAEF,eAAe,CAAC,EAAED,YAAY,wBAAwB,EAAEI,iBAAiB;IAEpJ,IAAIC,AAAiC,MAAjCA,sBAAsB,MAAM,EAC9B,OAAOb;IAGT,MAAMc,UAAUD,sBACb,GAAG,CACF,CAAC,EAAEE,OAAO,EAAEf,KAAK,EAAE,GAAK,CAAC,QAAQ,EAAEe,QAAQ,EAAE,EAAEhB,gBAAgBC,QAAQ,EAExE,IAAI,CAAC;IAERA,MAAM,OAAO,GAAG,GAAGA,MAAM,OAAO,CAAC,oCAAoC,EAAEc,SAAS;IAChF,OAAOd;AACT;AAEO,eAAegB,iBAAiB,EACrCC,WAAW,EAGZ;IAMC,MAAM,EACJC,UAAU,EACVC,SAAS,EACTC,SAAS,EACTC,aAAa,EACbC,YAAY,EACZC,iBAAiB,EACjBC,gBAAgB,EAChBC,WAAW,EACXC,kBAAkB,EAClBC,OAAO,EACR,GAAGV;IAEJ,IAAIW;IACJ,MAAMC,aAAaC,SAAS,WAAW;QAAE,SAAS;IAAK;IACvD,MAAMC,aAAaD,SAAS;IAC5B,MAAME,YAAYF,SAAS,iBAAiB;QAAE,SAAS;IAAK;IAI5D,MAAMG,mBAAmB,CAACC;QACxB,IAAI;YACF,MAAMC,SAAS,IAAIC,IAAIF;YACvB,IAAIC,OAAO,QAAQ,EAAE;gBAEnBA,OAAO,QAAQ,GAAG;gBAClB,OAAOA,OAAO,IAAI;YACpB;YACA,OAAOD;QACT,EAAE,OAAM;YAEN,OAAOA;QACT;IACF;IAEA,IAAIf,WAAW;QACbY,WAAW,oBAAoBE,iBAAiBd;QAChD,IAAIkB,aACFL,UACE;aAEG;YAEL,MAAMM,aAAa;YACnB,MAAM,EAAEC,UAAU,EAAE,GAAG,MAAM,MAAM,CAACD;YACpCV,aAAa,IAAIW,WAAW;gBAC1B,KAAKpB;YAEP;QACF;IACF,OAAO,IAAID,YAAY;QACrBa,WAAW,qBAAqBE,iBAAiBf;QACjD,IAAImB,aACFL,UACE;aAGF,IAAI;YAEF,MAAMM,aAAa;YACnB,MAAM,EAAEE,eAAe,EAAE,GAAG,MAAM,MAAM,CAACF;YAEzC,MAAMG,WAAW,IAAIL,IAAIlB;YAGzB,IAAI,CAACuB,SAAS,QAAQ,EACpB,MAAM,IAAIpD,MAAM;YAIlB,MAAMqD,OAAOtC,OAAO,QAAQ,CAACqC,SAAS,IAAI,EAAE;YAC5C,IAAI,CAACA,SAAS,IAAI,IAAIrC,OAAO,KAAK,CAACsC,OACjC,MAAM,IAAIrD,MAAM;YAIlB,MAAMsD,WAAWF,SAAS,QAAQ,CAAC,OAAO,CAAC,KAAK;YAChD,MAAMG,YACJD,AAAa,aAAbA,WAAwB,IAAIA,AAAa,aAAbA,WAAwB,IAAI;YAE1Df,aAAaY,gBAAgB;gBAC3B,MAAMI;gBACN,MAAMH,SAAS,QAAQ;gBACvBC;gBACA,GAAID,SAAS,QAAQ,GACjB;oBACE,QAAQI,mBAAmBJ,SAAS,QAAQ;oBAC5C,UAAUI,mBAAmBJ,SAAS,QAAQ,IAAI;gBACpD,IACA,CAAC,CAAC;YACR;YACAV,WAAW,uCAAuC;gBAChD,MAAMa;gBACN,MAAMH,SAAS,QAAQ;gBACvB,MAAMC;YACR;QACF,EAAE,OAAO1C,OAAO;YACdgC,UAAU,oCAAoChC;YAC9C,MAAM,IAAIX,MACR,CAAC,yBAAyB,EAAE6B,WAAW,+GAA+G,CAAC;QAE3J;IAEJ;IAEA,MAAM4B,qBAAqBC,0BAA0B;QAAEpB;IAAQ;IAC/D,MAAMqB,gBAAgB;QACpB,SAAS3B;QACT,QAAQC;QAGR,GAAIM,aAAa;YAAE,cAAc;gBAAE,YAAYA;YAAkB;QAAE,IAAI,CAAC,CAAC;QACzE,GAAGL,iBAAiB;QAGpB,YAAY;QAGZ,GAAIuB,AAAuB,SAAvBA,qBAA8B;YAAE,SAASA;QAAmB,IAAI,CAAC,CAAC;QACtE,yBAAyB;IAC3B;IAEA,MAAMG,aAAa,IAAIC,SAAOF;IAE9B,IAAIG,SAAiBF;IAGrB,IACEE,UACAC,oBAAoB,qBAAqB,CAACC,2BAC1C;QACA,IAAIhB,aACF,MAAM,IAAIhD,MAAM;QAElBwC,WAAW;QAEX,MAAMyB,kBAAkB;QACxB,MAAM,EAAEC,UAAU,EAAE,GAAG,MAAM,MAAM,CAACD;QACpCH,SAASI,WAAWJ;IACtB;IAGA,IACEA,UACAC,oBAAoB,qBAAqB,CAACI,0BAC1C;QACA,IAAInB,aACF,MAAM,IAAIhD,MAAM;QAElBwC,WAAW;QAEX,MAAM4B,iBAAiB;QACvB,MAAM,EAAEC,aAAa,EAAE,GAAG,MAAM,MAAM,CAACD;QACvCN,SAASO,cAAcP;IACzB;IAEA,IAAIzB,oBAAoB;QACtB,MAAMiC,gBAAgB,MAAMjC,mBAAmBuB,YAAYD;QAE3D,IAAIW,eACFR,SAASQ;IAEb;IAEA,OAAO;QACL,YAAYR,OAAO,IAAI,CAAC,WAAW;QACnC/B;QACAI;QACAC;IACF;AACF;AASO,eAAemC,OACpBC,QAAsC,EACtCC,YAA0B,EAC1BC,OAAuB;IAQvB,MAAM,EAAE,QAAQ9C,WAAW,EAAE+C,OAAO,EAAE,GAAGF;IAEzC,IAAIG,yBAAyBhD,YAAY,aAAa,GACpD,OAAOiD,yBAAyBL,UAAU5C,aAAa;QACrD,QAAQ8C,SAAS;QACjB,SAASA,SAAS;QAClB,kBAAkB9C,YAAY,gBAAgB;QAC9C,aAAa8C,SAAS;IACxB;IAGF,MAAM,EAAEI,UAAU,EAAE/C,SAAS,EAAEI,gBAAgB,EAAEC,WAAW,EAAE,GAC5D,MAAMT,iBAAiB;QACrBC;IACF;IACF,MAAM6B,qBAAqBC,0BAA0B9B;IAErD,MAAMmD,YAAYnD,YAAY,SAAS;IAEvC,MAAMoD,YAAYvC,SAAS;IAC3B,MAAMwC,WAAWxC,SAAS,WAAW;QAAE,SAAS;IAAK;IACrD,MAAMyC,oBAAoBzC,SAAS;IACnC,MAAM0C,qBAAqB1C,SAAS;IAEpC,MAAM2C,YAAYC,KAAK,GAAG;IAE1B,MAAMC,cAAcZ,SAAS,UAAUA,SAAS;IAChD,MAAMa,sBAAsB;QAC1B,QAAQ3D,YAAY,MAAM;QAC1B,YAAY;YACV,aAAaA,YAAY,WAAW;YACpC,kBAAkBA,YAAY,gBAAgB;YAC9C,iBAAiBA,YAAY,eAAe;YAC5C,iBAAiBA,YAAY,eAAe;QAC9C;QACA,6BAA6B8C,SAAS;IACxC;IACA,MAAM,EAAE,QAAQc,2BAA2B,EAAE,GAC3Cb,QAAQ,cAAc,CAAC,yBAAyB,CAACY;IACnDP,UACE,CAAC,gCAAgC,EAAE3E,kBAAkB;QACnD,QAAQmF;IACV,IAAI;IAEN,IAAIC;IACJ,IAAIC,cAAc;IAClB,IAAIC,uBAAuB;IAC3B,IAAIvF;IACJ,IAAID;IACJ,IAAIyF;IACJ,IAAIC;IACJ,IAAIC;IAEJ,MAAMC,gBAAgB,CAACzF,QACrB,AAAiB,YAAjB,OAAOA,SAAsBA,MAAM,IAAI,GAAG,MAAM,GAAG;IAErD,MAAM0F,iBAAiB,CACrBC,WACAJ;QAEA,IAAI,CAACI,WAAW;QAEhB,MAAMC,oBACJD,WACC,uBAAuB;QAE1B,OAAO;YACL,GAAGA,SAAS;YACZ,eAAeA,UAAU,aAAa,IAAI;YAC1C,mBAAmBA,UAAU,iBAAiB,IAAI;YAClD,cAAcA,UAAU,YAAY,IAAI;YACxC,cAAcC,qBAAqB;YACnC,WAAWN,YAAY;YACvB,YAAY7D;YACZ,mBAAmBI;YACnB,qBAAqB2D;YACrB,MAAMlE,YAAY,IAAI;YAEtB,QAAQuE;YACR,YAAYN,aAAaM;QAC3B;IACF;IAEA,MAAMC,gBAAgB;QACpB,GAAGZ,2BAA2B;QAC9B,GAAIT,aAAa,CAAC,CAAC;IACrB;IACA,MAAMsB,cAAcD,cAAc,WAAW;IAE7C,MAAME,cACJ3B,QAAQ,cAAc,CAAC,kBAAkB,CAACY;IAI5C,MAAMgB,0BAAyD,AAAC;QAC9D,IAAI,CAACD,aACH,OAAO9B;QAGT,OAAOA,SAAS,GAAG,CAAC,CAACgC;YACnB,IAAI,CAACC,MAAM,OAAO,CAACD,IAAI,OAAO,GAC5B,OAAOA;YAGT,MAAMf,UAAUe,IAAI,OAAO,CAAC,GAAG,CAAC,CAACE;gBAC/B,IAAIA,QAAQA,AAAc,gBAAdA,KAAK,IAAI,IAAoBA,KAAK,SAAS,EAAE,KACvD,OAAO;oBACL,GAAGA,IAAI;oBACP,WAAW;wBACT,GAAGA,KAAK,SAAS;wBACjB,QAAQJ;oBACV;gBACF;gBAEF,OAAOI;YACT;YAEA,OAAO;gBACL,GAAGF,GAAG;gBACNf;YACF;QACF;IACF;IAEA,IAAI;QACFT,UACE,CAAC,QAAQ,EAAEM,cAAc,eAAe,GAAG,WAAW,EAAEvD,WAAW;QAGrE,IAAIuD,aAAa;YACf,MAAM,EAAE,QAAQqB,YAAY,EAAE,SAASC,mBAAmB,EAAE,GAC1DC,wBAAwBpD,oBAAoBiB,SAAS;YACvD,IAAI;gBACF,MAAMoC,SAAU,MAAMhC,WAAW,MAAM,CACrC;oBACE,OAAO/C;oBACP,UAAUwE;oBACV,GAAGH,aAAa;oBAChB,QAAQ;gBACV,GACA;oBACE,QAAQ;oBACR,QAAQO;gBACV;gBAKFd,YAAYiB,OAAO,WAAW;gBAE9B,WAAW,MAAMC,SAASD,OAAQ;oBAChC,MAAME,cAAcrC,QAAQ,cAAc,CAAC,0BAA0B,CACnEoC,MAAM,OAAO,EAAE,CAAC,EAAE,EAAE;oBAEtB,MAAMtB,UAAUuB,YAAY,OAAO,IAAI;oBACvC,MAAMC,oBAAoBD,YAAY,iBAAiB,IAAI;oBAG3D,IAAID,MAAM,KAAK,EACb5G,QAAQ4G,MAAM,KAAK;oBAErB,IAAIA,MAAM,KAAK,EACbjB,oBAAoBiB,MAAM,KAAK;oBAGjC,IAAItB,WAAWwB,mBAAmB;wBAChCvB,eAAeD;wBACfE,wBAAwBsB;wBACxB,MAAMC,YAAiC;4BACrCzB;4BACAwB;4BACAvB;4BACA,YAAY;4BACZ,OAAOS;wBACT;wBACAzB,QAAQ,OAAO,CAAEwC;oBACnB;oBAGA,IAAIH,MAAM,OAAO,EAAE,CAAC,EAAE,EAAE,eAAe;wBACrCnB,WAAWP,KAAK,GAAG,KAAKD;wBAGxB,IAAI,CAACjF,OAAO;4BAEV,MAAMgH,kBAAkBnG,KAAK,GAAG,CAC9B,GACAA,KAAK,KAAK,CAAC0E,YAAY,MAAM,GAAG;4BAElCvF,QAAQ;gCACN,eAAegH;gCACf,mBAAmBA;gCACnB,cAAcA,AAAkB,IAAlBA;4BAChB;wBACF;wBAGA,MAAMC,aAAkC;4BACtC,SAAS;4BACT1B;4BACA,mBAAmB;4BACnB,YAAY;4BACZ,OAAOM,eAAe7F,OAAO0F;wBAC/B;wBACAnB,QAAQ,OAAO,CAAE0C;wBACjB;oBACF;gBACF;YACF,SAAU;gBACRR;YACF;YACAnB,UAAUC;YACVR,kBACE,CAAC,iBAAiB,EAAEnD,UAAU,QAAQ,EAAEK,eAAe,UAAU,WAAW,EAAEwD,SAAS,eAAe,EAAES,eAAe,IAAI;QAE/H,OAAO;YAEL,MAAMvF,aAAaD,oBAAoBe,YAAY,UAAU;YAC7D,MAAMyF,gBAAgBzF,YAAY,aAAa,IAAI;YACnD,MAAMT,cAAcL,aAAa;YAEjC,IAAIwG;YACJ,MAAMpG,gBAA4D,EAAE;YAEpE,IAAK,IAAIQ,UAAU,GAAGA,WAAWP,aAAaO,UAAW;gBACvD,MAAM,EAAE,QAAQ6F,aAAa,EAAE,SAASC,oBAAoB,EAAE,GAC5DX,wBAAwBpD,oBAAoBiB,SAAS;gBACvD,IAAI;oBACF,MAAM+C,SAAS,MAAM3C,WAAW,MAAM,CACpC;wBACE,OAAO/C;wBACP,UAAUwE;wBACV,GAAGH,aAAa;wBAChB,QAAQ;oBACV,GACA;wBAAE,QAAQmB;oBAAc;oBAG1B3B,WAAWP,KAAK,GAAG,KAAKD;oBAExBF,kBACE,CAAC,OAAO,EAAEnD,UAAU,QAAQ,EAAEK,eAAe,UAAU,iBAAiB,EAAEqF,OAAO,KAAK,EAAE,iBAAiB,GAAG,qBAAqB,EAAEA,OAAO,KAAK,EAAE,qBAAqB,GAAG,gBAAgB,EAAEA,OAAO,KAAK,EAAE,gBAAgB,GAAG,WAAW,EAAE7B,SAAS,aAAa,EAAE6B,OAAO,WAAW,IAAI,GAAG,eAAe,EAAEpB,eAAe,IAAI;oBAGhUlB,mBACE,CAAC,oBAAoB,EAAE5E,KAAK,SAAS,CAACkH,OAAO,KAAK,GAAG;oBAGvD,IAAI,CAACA,OAAO,OAAO,EACjB,MAAM,IAAIzH,MACR,CAAC,mCAAmC,EAAEO,KAAK,SAAS,CAACkH,SAAS;oBAIlErH,mBAAmBqH,OAAO,OAAO,CAAC,EAAE,CAAC,OAAO;oBAC5C,MAAMC,gBACJ/C,QAAQ,cAAc,CAAC,0BAA0B,CAC/C8C,OAAO,OAAO,CAAC,EAAE,CAAC,OAAO;oBAE7BhC,UAAUiC,cAAc,OAAO;oBAC/B/B,uBAAuB+B,cAAc,iBAAiB;oBACtDvH,QAAQsH,OAAO,KAAK;oBACpB5B,YAAY4B,OAAO,WAAW;oBAC9B3B,oBAAoB2B,OAAO,KAAK;oBAEhC,IAAI,CAAC1B,cAAcN,YAAYM,cAAcJ,uBAAuB;wBAClEV,SAAS;wBACTQ,UAAUE;oBACZ;oBAEA,IAAI,CAACI,cAAcN,UACjB,MAAM,IAAI1F,qBACR,+BACAQ,KAAK,SAAS,CAACkH,SACfzB,eAAe7F,OAAO0F,YACtBzF;oBAIJ;gBACF,EAAE,OAAOO,OAAO;oBACd2G,YAAY1G,QAAQD;oBACpBO,cAAc,IAAI,CAAC;wBAAEQ;wBAASf;oBAAM;oBACpC,MAAMgH,iBAAiBC,mBAAmBN;oBAC1C,IAAIK,gBACF1C,SACE,CAAC,0BAA0B,EAAExB,mBAAmB,YAAY,EAAE/B,QAAQ,CAAC,EAAEP,YAAY,QAAQ,EAAEY,UAAU,OAAO,EAAEH,YAAY,IAAI,CAAC,CAAC,CAAC;oBAIzI,IAAI8C,SAAS,aAAa,SACxB;oBAEF,IAAIhD,UAAUP,aAAa;wBACzB8D,SACE,CAAC,wBAAwB,EAAEvD,QAAQ,CAAC,EAAEP,YAAY,eAAe,EAAEkG,cAAc,aAAa,EAAEC,UAAU,OAAO,EAAE;wBAErH,MAAM,IAAIO,QAAQ,CAACC,UAAYC,WAAWD,SAAST;oBACrD;gBACF,SAAU;oBACRG;gBACF;YACF;YAEA,IAAI,CAAC/B,SAAS;gBACZuC,OACEV,WACA;gBAEF,MAAMrG,8BACJqG,WACApG,eACAC;YAEJ;QACF;QAEA6D,UAAU,CAAC,4BAA4B,EAAEW,sBAAsB;QAC/DX,UAAU,CAAC,kBAAkB,EAAES,SAAS;QAGxC,IAAIH,eAAe,CAACnF,OAAO;YAEzB,MAAMgH,kBAAkBnG,KAAK,GAAG,CAC9B,GACAA,KAAK,KAAK,CAAEyE,AAAAA,CAAAA,WAAW,EAAC,EAAG,MAAM,GAAG;YAEtCtF,QAAQ;gBACN,eAAegH;gBACf,mBAAmBA;gBACnB,cAAcA,AAAkB,IAAlBA;YAChB;QACF;QAEA,OAAO;YACL,SAAS1B,WAAW;YACpB,mBAAmBE,wBAAwBQ;YAC3C/F;YACA,OAAO4F,eAAe7F,OAAO0F;YAC7B,YAAY,CAAC,CAACP;QAChB;IACF,EAAE,OAAO2C,GAAQ;QACfhD,SAAS,iBAAiBgD;QAE1B,IAAIA,aAAalI,sBACf,MAAMkI;QAGR,MAAMC,WAAW,IAAIlI,MACnB,CAAC,eAAe,EAAEsF,cAAc,eAAe,GAAG,kBAAkB,EAAEvD,UAAU,GAAG,EAAEkG,EAAE,OAAO,CAAC,8DAA8D,CAAC,EAC9J;YACE,OAAOA;QACT;QAEF,MAAMC;IACR;AACF;AAEO,eAAeC,yBACpB3D,QAAsC,EAEtC4D,KAAkC,EAClC1D,OAGC;IASD,MAAMD,eAAe4D,8BAA8BD;IACnD,MAAM,EAAE,QAAQxG,WAAW,EAAE+C,OAAO,EAAE,GAAGF;IACzC,MAAM6D,WAAW,MAAM/D,OAAOC,UAAUC,cAAc;QACpD,aAAaC,SAAS;IACxB;IACAsD,OAAOM,UAAU;IACjB,IAAIC;IACJ,IAAI;QACFA,cAAc5D,QAAQ,UAAU,CAAC2D,SAAS,OAAO,EAAE;YACjD,QAAQ5D,SAAS,oBAAoB;QACvC;IACF,EAAE,OAAO/D,OAAO;QACd,MAAM6H,eAAe7H,iBAAiBX,QAAQW,MAAM,OAAO,GAAGF,OAAOE;QACrE,MAAM,IAAIZ,qBACRyI,cACAF,SAAS,OAAO,EAChBA,SAAS,KAAK;IAElB;IACA,IAAI,AAAuB,YAAvB,OAAOC,aACT,MAAM,IAAIxI,qBACR,CAAC,0CAA0C,EAAE6B,YAAY,SAAS,CAAC,GAAG,EAAE0G,SAAS,OAAO,EAAE,EAC1FA,SAAS,OAAO,EAChBA,SAAS,KAAK,EACdA,SAAS,gBAAgB;IAG7B,OAAO;QACL,SAASC;QACT,eAAeD,SAAS,OAAO;QAC/B,OAAOA,SAAS,KAAK;QACrB,mBAAmBA,SAAS,iBAAiB;QAC7C,kBAAkBA,SAAS,gBAAgB;IAC7C;AACF;AAEA,SAASD,8BACPD,KAAkC;IAElC,IAAI,YAAYA,SAAS,aAAaA,OACpC,OAAOA;IAGT,OAAOK,gBAAgBL;AACzB;AAEO,eAAeM,yBACpBC,IAAY,EACZlE,YAA0B,EAC1BC,OAA4E;IAM5E,MAAM,EAAEe,OAAO,EAAEtF,KAAK,EAAEC,gBAAgB,EAAE,GAAG,MAAMmE,OACjDoE,MACAlE,cACAC;IAEF,OAAO;QAAEe;QAAStF;QAAOC;IAAiB;AAC5C"}