// Force strict mode and setup for ESM
"use strict";
import {
  OpenAILogger
} from "./chunk-EIMKVOSF.js";
import {
  areSensitiveSpanAttributesEnabled
} from "./chunk-RPYYTL7E.js";
import {
  OpenAIContentConverter,
  openaiRequestCaptureContext
} from "./chunk-4LKVQFHM.js";
import "./chunk-2J3OJGTL.js";
import {
  retryContext
} from "./chunk-P3QQPMQA.js";
import "./chunk-6O5DVH27.js";
import {
  getGenAiUsageProvenance
} from "./chunk-WK4TJUEA.js";
import {
  runtimeDiagnostics
} from "./chunk-GLCZKT5V.js";
import {
  createGenAiExchange
} from "./chunk-URN76TKR.js";
import "./chunk-2DNKEBXY.js";
import {
  ApiErrorEvent,
  ApiRequestEvent,
  ApiResponseEvent,
  isInternalPromptId,
  logApiError,
  logApiRequest,
  logApiResponse,
  subagentNameContext
} from "./chunk-4K3RV3OA.js";
import "./chunk-VGC4I5JJ.js";
import "./chunk-E4WHKETF.js";
import "./chunk-UEJESCS7.js";
import "./chunk-CFDR3GNL.js";
import "./chunk-H35Q5CEG.js";
import "./chunk-46UV252V.js";
import "./chunk-ZBVS26BY.js";
import "./chunk-BFHXDAR7.js";
import "./chunk-TYERNYH4.js";
import "./chunk-UH7Z7Y45.js";
import {
  API_CALL_ABORTED_SPAN_STATUS_MESSAGE,
  API_CALL_FAILED_SPAN_STATUS_MESSAGE,
  endLLMRequestSpan,
  startLLMRequestSpan
} from "./chunk-O2ZYHG33.js";
import "./chunk-W4RQUHY3.js";
import "./chunk-G7XXKQYS.js";
import {
  createDebugLogger,
  getErrorMessage,
  getErrorStatus,
  getErrorType
} from "./chunk-3RXUYQJI.js";
import "./chunk-VOQXFAY5.js";
import "./chunk-75DOP5OR.js";
import "./chunk-DMTGGOSA.js";
import "./chunk-YQ3U5MUC.js";
import {
  GenerateContentResponse
} from "./chunk-22C7BQ6D.js";
import "./chunk-TYAMGABM.js";
import "./chunk-FCMNKVXT.js";
import "./chunk-AMDSOFFV.js";
import {
  context,
  init_esm,
  trace
} from "./chunk-QUGAUQGJ.js";
import {
  init_esbuild_shims
} from "./chunk-5O2XNYP6.js";
import {
  __name
} from "./chunk-J2S4EL5Y.js";

// packages/core/src/core/loggingContentGenerator/index.ts
init_esbuild_shims();

// packages/core/src/core/loggingContentGenerator/loggingContentGenerator.ts
init_esbuild_shims();
init_esm();

// packages/core/src/core/loggingContentGenerator/streamContentDetection.ts
init_esbuild_shims();
function hasUserVisibleContent(chunk) {
  const parts = chunk.candidates?.[0]?.content?.parts;
  if (!parts || parts.length === 0) return false;
  return parts.some(isUserVisiblePart);
}
__name(hasUserVisibleContent, "hasUserVisibleContent");
function isUserVisiblePart(part) {
  if (part === null || typeof part !== "object") return false;
  const p = part;
  if (typeof p.text === "string" && p.text.length > 0) return true;
  if (p.functionCall !== void 0) return true;
  if (p.inlineData !== void 0) return true;
  if (p.executableCode !== void 0) return true;
  if (p.thought === true) return true;
  return false;
}
__name(isUserVisiblePart, "isUserVisiblePart");

// packages/core/src/telemetry/gen-ai-provider.ts
init_esbuild_shims();
var PROVIDER_BY_ENV_KEY = {
  ANTHROPIC_API_KEY: "anthropic",
  BAILIAN_CODING_PLAN_API_KEY: "dashscope",
  BAILIAN_TOKEN_PLAN_API_KEY: "dashscope",
  DASHSCOPE_API_KEY: "dashscope",
  DEEPSEEK_API_KEY: "deepseek",
  IDEALAB_API_KEY: "dashscope",
  MINIMAX_API_KEY: "minimax",
  MIMO_API_KEY: "mimo",
  MISTRAL_API_KEY: "mistral_ai",
  MODELSCOPE_API_KEY: "modelscope",
  OPENAI_API_KEY: "openai",
  OPENROUTER_API_KEY: "openrouter",
  REQUESTY_API_KEY: "requesty",
  XAI_API_KEY: "x_ai",
  XIAOMI_MIMO_API_KEY: "mimo",
  ZAI_API_KEY: "z_ai"
};
function isHostOrSubdomain(hostname, domain) {
  return hostname === domain || hostname.endsWith(`.${domain}`);
}
__name(isHostOrSubdomain, "isHostOrSubdomain");
function providerFromHostname(hostname) {
  if (isHostOrSubdomain(hostname, "dashscope.aliyuncs.com") || isHostOrSubdomain(hostname, "dashscope-intl.aliyuncs.com") || isHostOrSubdomain(hostname, "dashscope-us.aliyuncs.com") || hostname.startsWith("token-plan.") && isHostOrSubdomain(hostname, "maas.aliyuncs.com") || hostname.endsWith(".alibaba-inc.com") || hostname.endsWith(".aliyun-inc.com")) {
    return "dashscope";
  }
  if (isHostOrSubdomain(hostname, "openai.azure.com") || isHostOrSubdomain(hostname, "services.ai.azure.com")) {
    return "azure.ai.openai";
  }
  if (isHostOrSubdomain(hostname, "deepseek.com")) return "deepseek";
  if (isHostOrSubdomain(hostname, "x.ai")) return "x_ai";
  if (isHostOrSubdomain(hostname, "mistral.ai")) return "mistral_ai";
  if (isHostOrSubdomain(hostname, "minimax.io") || isHostOrSubdomain(hostname, "minimaxi.com")) {
    return "minimax";
  }
  if (isHostOrSubdomain(hostname, "z.ai") || isHostOrSubdomain(hostname, "bigmodel.cn")) {
    return "z_ai";
  }
  if (isHostOrSubdomain(hostname, "modelscope.cn")) return "modelscope";
  if (isHostOrSubdomain(hostname, "xiaomimimo.com")) return "mimo";
  if (isHostOrSubdomain(hostname, "openrouter.ai")) return "openrouter";
  if (isHostOrSubdomain(hostname, "requesty.ai")) return "requesty";
  if (isHostOrSubdomain(hostname, "anthropic.com")) return "anthropic";
  if (isHostOrSubdomain(hostname, "openai.com")) return "openai";
  return void 0;
}
__name(providerFromHostname, "providerFromHostname");
function parsedUrl(value) {
  if (!value) return void 0;
  try {
    return new URL(value);
  } catch {
    return void 0;
  }
}
__name(parsedUrl, "parsedUrl");
function normalizedEndpoint(value) {
  const url = parsedUrl(value);
  if (!url) return void 0;
  const pathname = url.pathname.replace(/\/+$/, "") || "/";
  return `${url.protocol}//${url.host}${pathname}${url.search}`;
}
__name(normalizedEndpoint, "normalizedEndpoint");
function resolveGenAiProviderName(config, dashscopeProxyBaseUrl) {
  if (config.authType === "qwen-oauth") return "dashscope";
  const baseUrl = normalizedEndpoint(config.baseUrl);
  const proxyUrl = normalizedEndpoint(dashscopeProxyBaseUrl);
  if (baseUrl && proxyUrl && baseUrl === proxyUrl) return "dashscope";
  const hostname = parsedUrl(config.baseUrl)?.hostname.toLowerCase();
  if (hostname) {
    const provider = providerFromHostname(hostname);
    if (provider) return provider;
  }
  const envProvider = config.apiKeyEnvKey ? PROVIDER_BY_ENV_KEY[config.apiKeyEnvKey.toUpperCase()] : void 0;
  if (envProvider) return envProvider;
  switch (config.authType) {
    case "anthropic":
      return "anthropic";
    case "gemini":
      return "gcp.gemini";
    case "vertex-ai":
      return "gcp.vertex_ai";
    default:
      return "openai";
  }
}
__name(resolveGenAiProviderName, "resolveGenAiProviderName");
function resolveGenAiOperationName(authType) {
  return authType === "gemini" || authType === "vertex-ai" ? "generate_content" : "chat";
}
__name(resolveGenAiOperationName, "resolveGenAiOperationName");
function resolveGenAiOutputType(authType, config) {
  if (authType !== "gemini" && authType !== "vertex-ai") return void 0;
  const mimeType = config?.responseMimeType?.split(";", 1)[0]?.trim().toLowerCase();
  if (mimeType) {
    if (mimeType === "application/json" || mimeType.endsWith("+json")) {
      return "json";
    }
    if (mimeType.startsWith("text/")) return "text";
    if (mimeType.startsWith("image/")) return "image";
    if (mimeType.startsWith("audio/")) return "speech";
  }
  const modalities = config?.responseModalities;
  if (modalities?.length !== 1) return void 0;
  switch (String(modalities[0]).toUpperCase()) {
    case "TEXT":
      return "text";
    case "IMAGE":
      return "image";
    case "AUDIO":
      return "speech";
    default:
      return void 0;
  }
}
__name(resolveGenAiOutputType, "resolveGenAiOutputType");

// packages/core/src/core/loggingContentGenerator/loggingContentGenerator.ts
function snapshotRetryMetadata() {
  const ctx = retryContext.getStore();
  return {
    attempt: ctx?.attempt ?? 1,
    requestSetupMs: ctx?.requestSetupMs,
    retryTotalDelayMs: ctx?.retryTotalDelayMs
  };
}
__name(snapshotRetryMetadata, "snapshotRetryMetadata");
function usageSpanMetadata(usage) {
  const provenance = getGenAiUsageProvenance(usage);
  return {
    inputTokens: usage?.promptTokenCount,
    outputTokens: usage?.candidatesTokenCount,
    cachedInputTokens: usage?.cachedContentTokenCount,
    cachedInputTokensReported: provenance?.cachedInputTokensReported ?? usage?.cachedContentTokenCount !== void 0,
    cacheCreationInputTokens: provenance?.cacheCreationInputTokens
  };
}
__name(usageSpanMetadata, "usageSpanMetadata");
function orderedFinishReasons(response) {
  const reasons = (response.candidates ?? []).map((candidate, position) => ({
    index: candidate.index ?? position,
    reason: candidate.finishReason ? String(candidate.finishReason) : void 0
  })).filter(
    (entry) => entry.reason !== void 0
  ).sort((left, right) => left.index - right.index).map((entry) => entry.reason);
  return reasons.length > 0 ? reasons : void 0;
}
__name(orderedFinishReasons, "orderedFinishReasons");
var debugLogger = createDebugLogger("LOGGING_CONTENT_GENERATOR");
var MAX_RESPONSE_TEXT_LENGTH = 4096;
var RESPONSE_TEXT_TRUNCATION_SUFFIX = "...[truncated]";
var LoggingContentGenerator = class {
  constructor(wrapped, config, generatorConfig) {
    this.wrapped = wrapped;
    this.config = config;
    this.modalities = generatorConfig.modalities;
    this.splitToolMedia = generatorConfig.splitToolMedia;
    this.toolResultContentFormat = generatorConfig.toolResultContentFormat;
    this.generatorAuthType = generatorConfig.authType;
    this.genAiProviderName = resolveGenAiProviderName(
      generatorConfig,
      process.env["DASHSCOPE_PROXY_BASE_URL"]
    );
    this.genAiOperationName = resolveGenAiOperationName(
      generatorConfig.authType
    );
    if (generatorConfig.enableOpenAILogging) {
      this.openaiLogger = new OpenAILogger(
        generatorConfig.openAILoggingDir,
        config.getWorkingDir()
      );
      this.schemaCompliance = generatorConfig.schemaCompliance;
    }
  }
  static {
    __name(this, "LoggingContentGenerator");
  }
  openaiLogger;
  schemaCompliance;
  modalities;
  splitToolMedia;
  toolResultContentFormat;
  generatorAuthType;
  genAiProviderName;
  genAiOperationName;
  getWrapped() {
    return this.wrapped;
  }
  logApiRequest(contents, model, promptId) {
    const requestText = JSON.stringify(contents);
    logApiRequest(
      this.config,
      new ApiRequestEvent(
        model,
        promptId,
        requestText,
        subagentNameContext.getStore()
      )
    );
  }
  _logApiResponse(responseId, durationMs, model, prompt_id, usageMetadata, responseText, ttftMs) {
    logApiResponse(
      this.config,
      new ApiResponseEvent(
        responseId,
        model,
        durationMs,
        prompt_id,
        this.generatorAuthType,
        usageMetadata,
        responseText,
        subagentNameContext.getStore(),
        ttftMs
      )
    );
  }
  _logApiError(responseId, durationMs, error, model, prompt_id) {
    const errorMessage = getErrorMessage(error);
    const errorType = getErrorType(error);
    const errorResponseId = error?.requestID || error?.request_id || responseId;
    const errorStatus = getErrorStatus(error);
    logApiError(
      this.config,
      new ApiErrorEvent({
        responseId: errorResponseId,
        model,
        durationMs,
        promptId: prompt_id,
        authType: this.generatorAuthType,
        errorMessage,
        errorType,
        statusCode: errorStatus,
        subagentName: subagentNameContext.getStore()
      })
    );
  }
  safelyLogApiError(responseId, durationMs, error, model, prompt_id) {
    try {
      this._logApiError(responseId, durationMs, error, model, prompt_id);
    } catch (loggingError) {
      debugLogger.warn("Failed to log API error:", loggingError);
    }
  }
  safelyLogApiResponse(responseId, durationMs, model, prompt_id, usageMetadata, responseText, ttftMs) {
    try {
      this._logApiResponse(
        responseId,
        durationMs,
        model,
        prompt_id,
        usageMetadata,
        responseText,
        ttftMs
      );
    } catch (loggingError) {
      debugLogger.warn("Failed to log API response:", loggingError);
    }
  }
  async generateContent(req, userPromptId) {
    const retrySnapshot = snapshotRetryMetadata();
    const llmSpan = startLLMRequestSpan(req.model, userPromptId, {
      operationName: this.genAiOperationName,
      providerName: this.genAiProviderName,
      outputType: resolveGenAiOutputType(this.generatorAuthType, req.config)
    });
    const isInternal = isInternalPromptId(userPromptId);
    const exchange = createGenAiExchange(
      trace.setSpan(context.active(), llmSpan),
      llmSpan,
      {
        captureContent: !isInternal && this.shouldCollectSensitiveSpanAttributes(),
        sensitiveAttributeMaxLength: this.config.getTelemetrySensitiveSpanAttributeMaxLength()
      }
    );
    const spanContext = exchange.context;
    const startTime = Date.now();
    const session = this.startCaptureSession();
    try {
      runtimeDiagnostics.recordGenerateContentRequest(req, {
        stream: false,
        source: "generateContent"
      });
      const response = await context.with(spanContext, async () => {
        if (!isInternal) {
          this.logApiRequest(
            this.toContents(req.contents),
            req.model,
            userPromptId
          );
        }
        const result = await session.wrap(
          () => this.wrapped.generateContent(req, userPromptId)
        );
        const durationMs = Date.now() - startTime;
        const responseText = isInternal ? void 0 : this.extractResponseText(result, MAX_RESPONSE_TEXT_LENGTH);
        this.safelyLogApiResponse(
          result.responseId ?? "",
          durationMs,
          result.modelVersion || req.model,
          userPromptId,
          result.usageMetadata,
          responseText
        );
        try {
          await this.safelyLogOpenAIInteraction(
            await session.resolve(req),
            result,
            void 0,
            userPromptId
          );
        } catch (loggingError) {
          debugLogger.warn("Failed to log OpenAI interaction:", loggingError);
        }
        return result;
      });
      const observedFinishReasons = exchange.controller.finalize(true);
      endLLMRequestSpan(llmSpan, {
        success: true,
        ...usageSpanMetadata(response.usageMetadata),
        durationMs: Date.now() - startTime,
        responseId: response.responseId || void 0,
        responseModel: response.modelVersion || void 0,
        finishReasons: observedFinishReasons ?? orderedFinishReasons(response),
        thoughtsTokenCount: response.usageMetadata?.thoughtsTokenCount,
        subagentName: subagentNameContext.getStore() || void 0,
        ...retrySnapshot,
        config: this.config
      });
      return response;
    } catch (error) {
      const durationMs = Date.now() - startTime;
      const observedFinishReasons = exchange.controller.finalize(false);
      const aborted = req.config?.abortSignal?.aborted ?? false;
      endLLMRequestSpan(llmSpan, {
        success: false,
        durationMs,
        error: aborted ? API_CALL_ABORTED_SPAN_STATUS_MESSAGE : API_CALL_FAILED_SPAN_STATUS_MESSAGE,
        errorType: getErrorType(error),
        errorStatusCode: getErrorStatus(error),
        finishReasons: observedFinishReasons,
        subagentName: subagentNameContext.getStore() || void 0,
        ...retrySnapshot,
        config: this.config
      });
      await context.with(spanContext, async () => {
        this.safelyLogApiError("", durationMs, error, req.model, userPromptId);
        try {
          await this.safelyLogOpenAIInteraction(
            await session.resolve(req),
            void 0,
            error,
            userPromptId
          );
        } catch (loggingError) {
          debugLogger.warn("Failed to log OpenAI interaction:", loggingError);
        }
      });
      throw error;
    }
  }
  async generateContentStream(req, userPromptId) {
    const retrySnapshot = snapshotRetryMetadata();
    const llmSpan = startLLMRequestSpan(req.model, userPromptId, {
      operationName: this.genAiOperationName,
      providerName: this.genAiProviderName,
      outputType: resolveGenAiOutputType(this.generatorAuthType, req.config)
    });
    try {
      llmSpan.setAttribute("gen_ai.request.stream", true);
    } catch {
    }
    const isInternal = isInternalPromptId(userPromptId);
    const exchange = createGenAiExchange(
      trace.setSpan(context.active(), llmSpan),
      llmSpan,
      {
        captureContent: !isInternal && this.shouldCollectSensitiveSpanAttributes(),
        sensitiveAttributeMaxLength: this.config.getTelemetrySensitiveSpanAttributeMaxLength()
      }
    );
    const spanContext = exchange.context;
    const startTime = Date.now();
    const session = this.startCaptureSession();
    let streamRequest;
    try {
      runtimeDiagnostics.recordGenerateContentRequest(req, {
        stream: true,
        source: "generateContentStream"
      });
      streamRequest = await context.with(spanContext, async () => {
        if (!isInternal) {
          this.logApiRequest(
            this.toContents(req.contents),
            req.model,
            userPromptId
          );
        }
        return session.wrap(async () => {
          const requestIssuedAtMs2 = performance.now();
          const stream2 = await this.wrapped.generateContentStream(
            req,
            userPromptId
          );
          return { stream: stream2, requestIssuedAtMs: requestIssuedAtMs2 };
        });
      });
    } catch (error) {
      const durationMs = Date.now() - startTime;
      const observedFinishReasons = exchange.controller.finalize(false);
      context.with(
        spanContext,
        () => this.safelyLogApiError("", durationMs, error, req.model, userPromptId)
      );
      const aborted = req.config?.abortSignal?.aborted ?? false;
      endLLMRequestSpan(llmSpan, {
        success: false,
        durationMs,
        error: aborted ? API_CALL_ABORTED_SPAN_STATUS_MESSAGE : API_CALL_FAILED_SPAN_STATUS_MESSAGE,
        errorType: getErrorType(error),
        errorStatusCode: getErrorStatus(error),
        finishReasons: observedFinishReasons,
        subagentName: subagentNameContext.getStore() || void 0,
        ...retrySnapshot,
        config: this.config
      });
      try {
        await this.safelyLogOpenAIInteraction(
          await session.resolve(req),
          void 0,
          error,
          userPromptId
        );
      } catch (loggingError) {
        debugLogger.warn("Failed to log OpenAI interaction:", loggingError);
      }
      throw error;
    }
    const { stream, requestIssuedAtMs } = streamRequest;
    const openaiRequestPromise = this.openaiLogger ? session.resolve(req).catch((loggingError) => {
      debugLogger.warn("Failed to resolve OpenAI request:", loggingError);
      return void 0;
    }) : void 0;
    return context.with(
      spanContext,
      () => this.loggingStreamWrapper(
        stream,
        startTime,
        requestIssuedAtMs,
        userPromptId,
        req.model,
        openaiRequestPromise,
        llmSpan,
        spanContext,
        req.config?.abortSignal,
        retrySnapshot,
        exchange.controller
      )
    );
  }
  startCaptureSession() {
    let captured;
    const skipCapture = !this.openaiLogger;
    return {
      wrap: /* @__PURE__ */ __name((fn) => skipCapture ? fn() : openaiRequestCaptureContext.run((built) => {
        captured = built;
      }, fn), "wrap"),
      resolve: /* @__PURE__ */ __name(async (req) => this.openaiLogger ? captured ?? await this.buildOpenAIRequestForLogging(req) : void 0, "resolve")
    };
  }
  async *loggingStreamWrapper(stream, startTime, requestIssuedAtMs, userPromptId, model, openaiRequestPromise, span, spanContext, abortSignal, retrySnapshot, exchangeController) {
    const isInternal = isInternalPromptId(userPromptId);
    const shouldCollectResponses = !isInternal || !!this.openaiLogger;
    const responses = [];
    let lastResponseForLogging;
    let firstResponseId = "";
    let firstModelVersion = "";
    let lastResponse;
    let lastUsageMetadata;
    const refreshLateUsageMetadata = /* @__PURE__ */ __name(() => {
      if (lastResponse?.usageMetadata) {
        lastUsageMetadata = lastResponse.usageMetadata;
      }
    }, "refreshLateUsageMetadata");
    let errorOccurred = false;
    let streamCompleted = false;
    const finishReasons = /* @__PURE__ */ new Map();
    let lastError;
    const subagentName = subagentNameContext.getStore();
    let ttftMs;
    let firstChunkObserved = false;
    let spanEndedByTimeout = false;
    const runInSpan = /* @__PURE__ */ __name((fn) => spanContext ? context.with(spanContext, fn) : fn(), "runInSpan");
    const STREAM_IDLE_TIMEOUT_MS = 5 * 6e4;
    let spanEndTimeout;
    const resetSpanTimeout = span ? () => {
      if (spanEndedByTimeout) return;
      if (spanEndTimeout !== void 0) clearTimeout(spanEndTimeout);
      spanEndTimeout = setTimeout(() => {
        refreshLateUsageMetadata();
        try {
          span.setAttribute("stream.timed_out", true);
        } catch {
        }
        const observedFinishReasons = exchangeController?.finalize(false);
        endLLMRequestSpan(span, {
          success: false,
          ...usageSpanMetadata(lastUsageMetadata),
          durationMs: Date.now() - startTime,
          error: "Stream span timed out (idle)",
          responseId: firstResponseId || void 0,
          responseModel: firstModelVersion || void 0,
          finishReasons: observedFinishReasons ?? (finishReasons.size > 0 ? [...finishReasons.entries()].sort(([left], [right]) => left - right).map(([, reason]) => reason) : void 0),
          subagentName: subagentName || void 0,
          ...retrySnapshot,
          config: this.config
        });
        spanEndedByTimeout = true;
      }, STREAM_IDLE_TIMEOUT_MS);
      spanEndTimeout.unref();
    } : void 0;
    resetSpanTimeout?.();
    try {
      for await (const response of stream) {
        if (!firstChunkObserved && !spanEndedByTimeout) {
          firstChunkObserved = true;
          try {
            const timeToFirstChunk = Math.max(0, performance.now() - requestIssuedAtMs) / 1e3;
            if (Number.isFinite(timeToFirstChunk)) {
              span?.setAttribute(
                "gen_ai.response.time_to_first_chunk",
                timeToFirstChunk
              );
            }
          } catch {
          }
        }
        lastResponse = response;
        if (!firstResponseId && response.responseId) {
          firstResponseId = response.responseId;
        }
        if (!firstModelVersion && response.modelVersion) {
          firstModelVersion = response.modelVersion;
        }
        const candidate = response.candidates?.[0];
        if (shouldCollectResponses) {
          lastResponseForLogging = response;
          if ((candidate?.content?.parts?.length ?? 0) > 0 || candidate?.finishReason) {
            responses.push(response);
          }
        }
        if (response.usageMetadata) {
          lastUsageMetadata = response.usageMetadata;
        }
        for (const [position, responseCandidate] of (response.candidates ?? []).entries()) {
          if (responseCandidate.finishReason) {
            finishReasons.set(
              responseCandidate.index ?? position,
              String(responseCandidate.finishReason)
            );
          }
        }
        if (ttftMs === void 0 && hasUserVisibleContent(response)) {
          ttftMs = Date.now() - startTime;
        }
        resetSpanTimeout?.();
        yield response;
      }
      streamCompleted = true;
      refreshLateUsageMetadata();
      if (spanEndTimeout !== void 0) {
        clearTimeout(spanEndTimeout);
        spanEndTimeout = void 0;
      }
      const durationMs = Date.now() - startTime;
      if (lastResponseForLogging && responses.at(-1) !== lastResponseForLogging) {
        responses.push(lastResponseForLogging);
      }
      const consolidatedResponse = shouldCollectResponses ? this.consolidateGeminiResponsesForLogging(responses) : void 0;
      if (consolidatedResponse) {
        consolidatedResponse.usageMetadata = lastUsageMetadata;
      }
      const streamResponseText = isInternal ? void 0 : this.extractResponseText(
        consolidatedResponse,
        MAX_RESPONSE_TEXT_LENGTH
      );
      if (!spanEndedByTimeout) {
        runInSpan(
          () => this.safelyLogApiResponse(
            firstResponseId,
            durationMs,
            firstModelVersion || model,
            userPromptId,
            lastUsageMetadata,
            streamResponseText,
            ttftMs
          )
        );
        const openaiRequest = await openaiRequestPromise;
        await runInSpan(
          () => this.safelyLogOpenAIInteraction(
            openaiRequest,
            consolidatedResponse,
            void 0,
            userPromptId
          )
        );
      }
    } catch (error) {
      errorOccurred = true;
      lastError = error;
      if (!spanEndedByTimeout) {
        const durationMs = Date.now() - startTime;
        runInSpan(
          () => this.safelyLogApiError(
            firstResponseId,
            durationMs,
            error,
            firstModelVersion || model,
            userPromptId
          )
        );
        const openaiRequest = await openaiRequestPromise;
        await runInSpan(
          () => this.safelyLogOpenAIInteraction(
            openaiRequest,
            void 0,
            error,
            userPromptId
          )
        );
      }
      throw error;
    } finally {
      if (spanEndTimeout !== void 0) {
        clearTimeout(spanEndTimeout);
      }
      refreshLateUsageMetadata();
      if (span && !spanEndedByTimeout) {
        const aborted = abortSignal?.aborted ?? false;
        const observedFinishReasons = exchangeController?.finalize(
          !errorOccurred && streamCompleted
        );
        endLLMRequestSpan(span, {
          success: !errorOccurred,
          ...usageSpanMetadata(lastUsageMetadata),
          ttftMs,
          durationMs: Date.now() - startTime,
          error: errorOccurred ? aborted ? API_CALL_ABORTED_SPAN_STATUS_MESSAGE : API_CALL_FAILED_SPAN_STATUS_MESSAGE : void 0,
          responseId: firstResponseId || void 0,
          responseModel: firstModelVersion || void 0,
          finishReasons: observedFinishReasons ?? (finishReasons.size > 0 ? [...finishReasons.entries()].sort(([left], [right]) => left - right).map(([, reason]) => reason) : void 0),
          thoughtsTokenCount: lastUsageMetadata?.thoughtsTokenCount,
          subagentName: subagentName || void 0,
          errorType: lastError ? getErrorType(lastError) : void 0,
          errorStatusCode: lastError ? getErrorStatus(lastError) : void 0,
          ...retrySnapshot,
          config: this.config
        });
      }
    }
  }
  async buildOpenAIRequestForLogging(request) {
    if (!this.openaiLogger) {
      return void 0;
    }
    const requestContext = this.createLoggingRequestContext(request.model);
    const messages = OpenAIContentConverter.convertGeminiRequestToOpenAI(
      request,
      requestContext,
      {
        cleanOrphanToolCalls: false
      }
    );
    const openaiRequest = {
      model: request.model,
      messages
    };
    if (request.config?.tools) {
      openaiRequest.tools = await OpenAIContentConverter.convertGeminiToolsToOpenAI(
        request.config.tools,
        this.schemaCompliance ?? "auto"
      );
    }
    if (request.config?.temperature !== void 0) {
      openaiRequest.temperature = request.config.temperature;
    }
    if (request.config?.topP !== void 0) {
      openaiRequest.top_p = request.config.topP;
    }
    if (request.config?.maxOutputTokens !== void 0) {
      openaiRequest.max_tokens = request.config.maxOutputTokens;
    }
    if (request.config?.presencePenalty !== void 0) {
      openaiRequest.presence_penalty = request.config.presencePenalty;
    }
    if (request.config?.frequencyPenalty !== void 0) {
      openaiRequest.frequency_penalty = request.config.frequencyPenalty;
    }
    return openaiRequest;
  }
  createLoggingRequestContext(model) {
    return {
      model,
      modalities: this.modalities ?? {},
      // Mirror the pipeline default (see pipeline.ts createRequestContext) so the
      // --openai-logging fallback reconstruction reflects the same split as the
      // request actually sent. Opt out via generationConfig.splitToolMedia = false.
      splitToolMedia: this.splitToolMedia ?? true,
      toolResultContentFormat: this.toolResultContentFormat ?? "parts",
      startTime: 0
    };
  }
  async logOpenAIInteraction(openaiRequest, response, error, promptId) {
    if (!this.openaiLogger || !openaiRequest) {
      return;
    }
    const openaiResponse = response ? this.convertGeminiResponseToOpenAIForLogging(response, openaiRequest) : void 0;
    await this.openaiLogger.logInteraction(
      openaiRequest,
      openaiResponse,
      error instanceof Error ? error : error ? new Error(String(error)) : void 0,
      promptId
    );
  }
  async safelyLogOpenAIInteraction(openaiRequest, response, error, promptId) {
    try {
      await this.logOpenAIInteraction(openaiRequest, response, error, promptId);
    } catch (loggingError) {
      debugLogger.warn("Failed to log OpenAI interaction:", loggingError);
    }
  }
  convertGeminiResponseToOpenAIForLogging(response, openaiRequest) {
    return OpenAIContentConverter.convertGeminiResponseToOpenAI(
      response,
      this.createLoggingRequestContext(openaiRequest.model)
    );
  }
  consolidateGeminiResponsesForLogging(responses) {
    if (responses.length === 0) {
      return void 0;
    }
    const consolidated = new GenerateContentResponse();
    const combinedParts = [];
    const functionCallIndex = /* @__PURE__ */ new Map();
    let finishReason;
    let usageMetadata;
    for (const response of responses) {
      if (response.usageMetadata) {
        usageMetadata = response.usageMetadata;
      }
      const candidate = response.candidates?.[0];
      if (candidate?.finishReason) {
        finishReason = candidate.finishReason;
      }
      const parts = candidate?.content?.parts ?? [];
      for (const part of parts) {
        if (typeof part === "string") {
          combinedParts.push({ text: part });
          continue;
        }
        if ("text" in part) {
          if (part.text) {
            combinedParts.push({
              text: part.text,
              ...part.thought ? { thought: true } : {},
              ...part.thoughtSignature ? { thoughtSignature: part.thoughtSignature } : {}
            });
          }
          continue;
        }
        if ("functionCall" in part && part.functionCall) {
          const callKey = part.functionCall.id || part.functionCall.name || "tool_call";
          const existingIndex = functionCallIndex.get(callKey);
          const functionPart = { functionCall: part.functionCall };
          if (existingIndex !== void 0) {
            combinedParts[existingIndex] = functionPart;
          } else {
            functionCallIndex.set(callKey, combinedParts.length);
            combinedParts.push(functionPart);
          }
          continue;
        }
        if ("functionResponse" in part && part.functionResponse) {
          combinedParts.push({ functionResponse: part.functionResponse });
          continue;
        }
        combinedParts.push(part);
      }
    }
    const lastResponse = responses[responses.length - 1];
    const lastCandidate = lastResponse.candidates?.[0];
    consolidated.responseId = lastResponse.responseId;
    consolidated.createTime = lastResponse.createTime;
    consolidated.modelVersion = lastResponse.modelVersion;
    consolidated.promptFeedback = lastResponse.promptFeedback;
    consolidated.usageMetadata = usageMetadata;
    consolidated.candidates = [
      {
        content: {
          role: lastCandidate?.content?.role || "model",
          parts: combinedParts
        },
        ...finishReason ? { finishReason } : {},
        index: 0,
        safetyRatings: lastCandidate?.safetyRatings || []
      }
    ];
    return consolidated;
  }
  extractResponseText(response, maxLength) {
    let text = "";
    let truncated = false;
    const maxPrefixLength = Math.max(
      0,
      maxLength - RESPONSE_TEXT_TRUNCATION_SUFFIX.length
    );
    const hasText = this.forEachVisibleResponseText(response, (partText) => {
      if (truncated) {
        return;
      }
      const remaining = maxPrefixLength - text.length;
      if (partText.length <= remaining) {
        text += partText;
        return;
      }
      text += partText.slice(0, Math.max(0, remaining));
      truncated = true;
    });
    if (!hasText) {
      return void 0;
    }
    return truncated ? `${text}${RESPONSE_TEXT_TRUNCATION_SUFFIX}` : text;
  }
  forEachVisibleResponseText(response, onText) {
    const parts = response?.candidates?.[0]?.content?.parts;
    if (!parts?.length) {
      return false;
    }
    let hasText = false;
    for (const part of parts) {
      const text = this.getVisibleResponsePartText(part);
      if (text === void 0) {
        continue;
      }
      hasText = true;
      onText(text);
    }
    return hasText;
  }
  getVisibleResponsePartText(part) {
    if (typeof part === "string") {
      return part;
    }
    if ("text" in part && typeof part.text === "string" && !("thought" in part && part.thought)) {
      return part.text;
    }
    return void 0;
  }
  shouldCollectSensitiveSpanAttributes() {
    return areSensitiveSpanAttributesEnabled(this.config);
  }
  async countTokens(req) {
    return this.wrapped.countTokens(req);
  }
  async embedContent(req) {
    return this.wrapped.embedContent(req);
  }
  useSummarizedThinking() {
    return this.wrapped.useSummarizedThinking();
  }
  toContents(contents) {
    if (Array.isArray(contents)) {
      return contents.map((c) => this.toContent(c));
    }
    return [this.toContent(contents)];
  }
  toContent(content) {
    if (Array.isArray(content)) {
      return {
        role: "user",
        parts: this.toParts(content)
      };
    }
    if (typeof content === "string") {
      return {
        role: "user",
        parts: [{ text: content }]
      };
    }
    if ("parts" in content) {
      return {
        ...content,
        parts: content.parts ? this.toParts(content.parts.filter((p) => p != null)) : []
      };
    }
    return {
      role: "user",
      parts: [this.toPart(content)]
    };
  }
  toParts(parts) {
    return parts.map((p) => this.toPart(p));
  }
  toPart(part) {
    if (typeof part === "string") {
      return { text: part };
    }
    if ("thought" in part && part.thought) {
      const thoughtText = `[Thought: ${part.thought}]`;
      const newPart = { ...part };
      delete newPart["thought"];
      const hasApiContent = "functionCall" in newPart || "functionResponse" in newPart || "inlineData" in newPart || "fileData" in newPart;
      if (hasApiContent) {
        return newPart;
      }
      const text = newPart.text;
      const existingText = text ? String(text) : "";
      const combinedText = existingText ? `${existingText}
${thoughtText}` : thoughtText;
      return {
        ...newPart,
        text: combinedText
      };
    }
    return part;
  }
};
export {
  LoggingContentGenerator
};
/**
 * @license
 * Copyright 2026 Qwen Team
 * SPDX-License-Identifier: Apache-2.0
 */
/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
/**
 * @license
 * Copyright 2025 Qwen
 * SPDX-License-Identifier: Apache-2.0
 */
