import { trackToolCall, trackUserMessage } from "../core/tracking.js";
import { getActiveContext } from "../context.js";
import { calculateCost } from "../utils/costs.js";
import { getDefaultPropagateContext, injectContext } from "../propagation.js";
import { tryRequire } from "../utils/resolve-module.js";
import { StreamingAccumulator } from "../utils/streaming.js";
import { consumeToolUseLatencyMs, recordToolUsesFromResponse } from "../utils/tool-latency.js";
import { BaseAIProvider, applySessionContext, contextFields } from "./base.js";

//#region src/providers/openai.ts
/**
* OpenAI provider wrapper with automatic tracking.
*
* Wraps the OpenAI client and instruments:
* - chat.completions.create()
* - responses.create()
* to track AI response events via Amplitude.
*/
const _resolved = tryRequire("openai");
const OPENAI_AVAILABLE = _resolved != null;
const _OpenAIModule = _resolved;
var OpenAI = class extends BaseAIProvider {
	_client;
	chat;
	responses;
	_propagateContext;
	constructor(options) {
		super({
			amplitude: options.amplitude,
			privacyConfig: options.privacyConfig,
			providerName: "openai"
		});
		const mod = options.openaiModule ?? _OpenAIModule;
		if (mod == null) throw new Error("openai package is required. Install it with: npm install openai — or pass the module directly via the openaiModule option.");
		const OpenAISDK = mod.OpenAI;
		const clientOpts = {};
		if (options.apiKey) clientOpts.apiKey = options.apiKey;
		if (options.baseUrl) clientOpts.baseURL = options.baseUrl;
		this._client = new OpenAISDK(clientOpts);
		this._propagateContext = options.propagateContext ?? getDefaultPropagateContext();
		this.chat = new WrappedChat(this._client, this.trackFn(), this._amplitude, this._privacyConfig, this._propagateContext);
		this.responses = new WrappedResponses(this._client, this.trackFn(), this._amplitude, this._privacyConfig, this._propagateContext);
	}
	get client() {
		return this._client;
	}
};
var WrappedChat = class {
	completions;
	constructor(client, trackFn, amplitude, privacyConfig, propagateContext) {
		const chat = client.chat;
		this.completions = new WrappedCompletions(chat.completions, trackFn, amplitude, privacyConfig, propagateContext);
	}
};
var WrappedCompletions = class {
	_original;
	_trackFn;
	_amplitude;
	_privacyConfig;
	_propagateContext;
	_providerName;
	constructor(completions, trackFn, amplitude, privacyConfig, propagateContext, providerName = "openai") {
		this._original = completions;
		this._trackFn = typeof trackFn === "function" ? trackFn : trackFn.trackFn();
		this._amplitude = amplitude;
		this._privacyConfig = privacyConfig;
		this._propagateContext = propagateContext;
		this._providerName = providerName;
	}
	async create(params, amplitudeOverrides) {
		const createFn = this._original.create;
		const startTime = performance.now();
		let requestParams = this._withContextHeaders(params);
		const ctx = applySessionContext(amplitudeOverrides);
		if (requestParams.stream === true && requestParams.stream_options == null) requestParams = {
			...requestParams,
			stream_options: { include_usage: true }
		};
		try {
			this._trackInputMessages(requestParams.messages, ctx, amplitudeOverrides?.trackInputMessages ?? true);
			const response = await createFn.call(this._original, requestParams);
			if (requestParams.stream === true && _isAsyncIterable(response)) return this._wrapStream(response, requestParams, startTime, ctx);
			const latencyMs = performance.now() - startTime;
			const resp = response;
			const usage = resp.usage;
			const choice = resp.choices?.[0];
			const modelName = String(resp.model ?? requestParams.model ?? "unknown");
			const toolCalls = choice?.message?.tool_calls;
			const usageExt = usage;
			const promptDetails = usageExt?.prompt_tokens_details;
			const reasoningTokens = (usageExt?.completion_tokens_details)?.reasoning_tokens;
			const cachedTokens = promptDetails?.cached_tokens;
			let costUsd = null;
			if (usage?.prompt_tokens != null && usage?.completion_tokens != null) try {
				costUsd = calculateCost({
					modelName,
					inputTokens: usage.prompt_tokens,
					outputTokens: usage.completion_tokens,
					reasoningTokens: reasoningTokens ?? 0,
					cacheReadInputTokens: cachedTokens ?? 0,
					defaultProvider: "openai"
				});
			} catch {}
			this._trackFn({
				...contextFields(ctx),
				modelName,
				provider: this._providerName,
				responseContent: String(choice?.message?.content ?? ""),
				latencyMs,
				inputTokens: usage?.prompt_tokens,
				outputTokens: usage?.completion_tokens,
				totalTokens: usage?.total_tokens,
				reasoningTokens,
				cacheReadInputTokens: cachedTokens,
				totalCostUsd: costUsd,
				finishReason: choice?.finish_reason,
				toolCalls: toolCalls ?? void 0,
				isStreaming: false,
				toolDefinitions: extractToolDefinitions(requestParams),
				systemPrompt: extractSystemPrompt(requestParams),
				temperature: requestParams.temperature,
				maxOutputTokens: requestParams.max_tokens,
				topP: requestParams.top_p
			});
			recordToolUsesFromResponse(toolCalls, {
				sessionId: ctx.sessionId,
				agentId: ctx.agentId
			});
			return response;
		} catch (error) {
			const latencyMs = performance.now() - startTime;
			this._trackFn({
				...contextFields(ctx),
				modelName: String(requestParams.model ?? "unknown"),
				provider: this._providerName,
				responseContent: "",
				latencyMs,
				isError: true,
				errorMessage: error instanceof Error ? error.message : String(error)
			});
			throw error;
		}
	}
	async parse(params, amplitudeOverrides) {
		const parseFn = this._original.parse;
		if (typeof parseFn !== "function") throw new Error("OpenAI SDK does not expose chat.completions.parse");
		const originalCreate = this._original.create;
		this._original.create = parseFn;
		try {
			return await this.create(params, amplitudeOverrides);
		} finally {
			this._original.create = originalCreate;
		}
	}
	async *_wrapStream(stream, params, _startTime, sessionCtx) {
		const accumulator = new StreamingAccumulator();
		accumulator.model = String(params.model ?? "unknown");
		let reasoningContent = "";
		try {
			for await (const chunk of stream) {
				const c = chunk;
				const choices = c.choices;
				const delta = choices?.[0]?.delta;
				if (delta?.content != null) accumulator.addContent(String(delta.content));
				const deltaToolCalls = delta?.tool_calls;
				if (Array.isArray(deltaToolCalls)) for (const call of deltaToolCalls) {
					const idx = call.index;
					const id = call.id;
					const fn = call.function;
					if (idx != null && id && fn?.name != null) accumulator.setToolCallAt(idx, {
						type: "function",
						id,
						function: {
							name: fn.name,
							arguments: fn.arguments ?? ""
						}
					});
					else if (idx != null && fn?.arguments) accumulator.appendToolCallArgs(idx, fn.arguments);
					else accumulator.addToolCall(call);
				}
				if (delta?.reasoning_content != null) reasoningContent += String(delta.reasoning_content);
				const finishReason = choices?.[0]?.finish_reason;
				if (finishReason != null) accumulator.finishReason = String(finishReason);
				const usage = c.usage;
				if (usage != null) {
					const promptDetails = usage.prompt_tokens_details;
					const completionDetails = usage.completion_tokens_details;
					accumulator.setUsage({
						inputTokens: usage.prompt_tokens,
						outputTokens: usage.completion_tokens,
						totalTokens: usage.total_tokens,
						reasoningTokens: completionDetails?.reasoning_tokens,
						cacheReadTokens: promptDetails?.cached_tokens
					});
				}
				yield chunk;
			}
		} catch (error) {
			accumulator.setError(error instanceof Error ? error.message : String(error));
			throw error;
		} finally {
			const state = accumulator.getState();
			const modelName = String(accumulator.model ?? params.model ?? "unknown");
			let costUsd = null;
			if (state.inputTokens != null && state.outputTokens != null) try {
				costUsd = calculateCost({
					modelName,
					inputTokens: state.inputTokens,
					outputTokens: state.outputTokens,
					reasoningTokens: state.reasoningTokens ?? 0,
					cacheReadInputTokens: state.cacheReadTokens ?? 0,
					defaultProvider: "openai"
				});
			} catch {}
			this._trackFn({
				...contextFields(sessionCtx),
				modelName,
				provider: this._providerName,
				responseContent: state.content,
				latencyMs: accumulator.elapsedMs,
				inputTokens: state.inputTokens,
				outputTokens: state.outputTokens,
				totalTokens: state.totalTokens,
				reasoningTokens: state.reasoningTokens,
				cacheReadInputTokens: state.cacheReadTokens,
				totalCostUsd: costUsd,
				finishReason: state.finishReason,
				toolCalls: state.toolCalls.length > 0 ? state.toolCalls : void 0,
				providerTtfbMs: state.ttfbMs,
				isStreaming: true,
				isError: state.isError,
				errorMessage: state.errorMessage,
				reasoningContent: reasoningContent || void 0,
				toolDefinitions: extractToolDefinitions(params),
				systemPrompt: extractSystemPrompt(params),
				temperature: params.temperature,
				maxOutputTokens: params.max_tokens,
				topP: params.top_p
			});
			recordToolUsesFromResponse(state.toolCalls, {
				sessionId: sessionCtx.sessionId,
				agentId: sessionCtx.agentId
			});
		}
	}
	_withContextHeaders(params) {
		if (!this._propagateContext) return params;
		const injected = injectContext(params.extra_headers ?? params.headers);
		return {
			...params,
			extra_headers: injected
		};
	}
	_trackInputMessages(messages, ctx, shouldTrackInputMessages) {
		if (!shouldTrackInputMessages) return;
		if (ctx.userId == null && ctx.deviceId == null || ctx.sessionId == null) return;
		if (getActiveContext()?.skipAutoUserTracking) return;
		if (!Array.isArray(messages)) return;
		const msgs = messages;
		const lastReplyIdx = msgs.findLastIndex((m) => m?.role === "assistant" || m?.role === "tool");
		const newMessages = msgs.slice(lastReplyIdx + 1);
		for (const msg of newMessages) {
			if (msg?.role !== "user") continue;
			const content = msg.content;
			if (typeof content !== "string" || content.length === 0) continue;
			trackUserMessage({
				amplitude: this._amplitude,
				userId: ctx.userId ?? void 0,
				deviceId: ctx.deviceId ?? void 0,
				messageContent: content,
				sessionId: ctx.sessionId,
				traceId: ctx.traceId,
				turnId: ctx.turnId ?? void 0,
				messageSource: ctx.parentAgentId ? "agent" : "user",
				agentId: ctx.agentId,
				parentAgentId: ctx.parentAgentId,
				customerOrgId: ctx.customerOrgId,
				agentVersion: ctx.agentVersion,
				context: ctx.context,
				env: ctx.env,
				groups: ctx.groups,
				eventProperties: ctx.eventProperties,
				privacyConfig: this._privacyConfig
			});
		}
		extractAndTrackToolCalls(msgs, {
			amplitude: this._amplitude,
			ctx,
			privacyConfig: this._privacyConfig
		});
	}
};
var WrappedResponses = class {
	_original;
	_trackFn;
	_amplitude;
	_privacyConfig;
	_propagateContext;
	_providerName;
	constructor(client, trackFn, amplitude, privacyConfig, propagateContext, providerName = "openai") {
		this._original = client.responses ?? {};
		this._trackFn = typeof trackFn === "function" ? trackFn : trackFn.trackFn();
		this._amplitude = amplitude;
		this._privacyConfig = privacyConfig;
		this._propagateContext = propagateContext;
		this._providerName = providerName;
	}
	async create(params, amplitudeOverrides) {
		const createFn = this._original.create;
		const startTime = performance.now();
		const requestParams = this._withContextHeaders(params);
		const ctx = applySessionContext(amplitudeOverrides);
		try {
			this._trackInputMessages(requestParams.input, ctx, amplitudeOverrides?.trackInputMessages ?? true);
			const response = await createFn.call(this._original, requestParams);
			if (requestParams.stream === true && _isAsyncIterable(response)) return this._wrapStream(response, requestParams, startTime, ctx);
			const latencyMs = performance.now() - startTime;
			const resp = response;
			const usage = resp.usage;
			const responseText = extractResponsesText(resp);
			const responseToolCalls = extractResponsesToolCalls(resp);
			const modelName = String(resp.model ?? requestParams.model ?? "unknown");
			let costUsd = null;
			if (usage?.input_tokens != null && usage?.output_tokens != null) try {
				costUsd = calculateCost({
					modelName,
					inputTokens: usage.input_tokens,
					outputTokens: usage.output_tokens,
					reasoningTokens: usage.output_tokens_details?.reasoning_tokens ?? 0,
					defaultProvider: "openai"
				});
			} catch {}
			this._trackFn({
				...contextFields(ctx),
				modelName,
				provider: this._providerName,
				responseContent: responseText,
				latencyMs,
				inputTokens: usage?.input_tokens,
				outputTokens: usage?.output_tokens,
				totalTokens: usage?.total_tokens,
				reasoningTokens: usage?.output_tokens_details?.reasoning_tokens,
				totalCostUsd: costUsd,
				finishReason: extractResponsesFinishReason(resp),
				toolCalls: responseToolCalls.length > 0 ? responseToolCalls : void 0,
				isStreaming: false,
				toolDefinitions: extractResponsesToolDefinitions(requestParams),
				systemPrompt: extractResponsesSystemPrompt(requestParams),
				temperature: requestParams.temperature,
				maxOutputTokens: requestParams.max_output_tokens,
				topP: requestParams.top_p
			});
			recordToolUsesFromResponse(responseToolCalls, {
				sessionId: ctx.sessionId,
				agentId: ctx.agentId
			});
			return response;
		} catch (error) {
			const latencyMs = performance.now() - startTime;
			this._trackFn({
				...contextFields(ctx),
				modelName: String(requestParams.model ?? "unknown"),
				provider: this._providerName,
				responseContent: "",
				latencyMs,
				isError: true,
				errorMessage: error instanceof Error ? error.message : String(error)
			});
			throw error;
		}
	}
	async stream(params, amplitudeOverrides) {
		const streamFn = this._original.stream;
		if (typeof streamFn !== "function") throw new Error("OpenAI SDK does not expose responses.stream");
		const startTime = performance.now();
		const requestParams = this._withContextHeaders(params);
		const ctx = applySessionContext(amplitudeOverrides);
		try {
			this._trackInputMessages(requestParams.input, ctx, amplitudeOverrides?.trackInputMessages ?? true);
			const response = await streamFn.call(this._original, requestParams);
			if (!_isAsyncIterable(response)) throw new Error("OpenAI responses.stream did not return AsyncIterable");
			return this._wrapStream(response, requestParams, startTime, ctx);
		} catch (error) {
			this._trackFn({
				...contextFields(ctx),
				modelName: String(requestParams.model ?? "unknown"),
				provider: this._providerName,
				responseContent: "",
				latencyMs: performance.now() - startTime,
				isError: true,
				errorMessage: error instanceof Error ? error.message : String(error),
				isStreaming: true
			});
			throw error;
		}
	}
	async *_wrapStream(stream, params, _startTime, sessionCtx) {
		const accumulator = new StreamingAccumulator();
		accumulator.model = String(params.model ?? "unknown");
		try {
			for await (const event of stream) {
				const e = event;
				const type = e.type;
				if (type === "response.output_text.delta") {
					const delta = e.delta;
					if (typeof delta === "string") accumulator.addContent(delta);
				} else if (type === "response.completed") {
					const response = e.response;
					if (response != null) {
						const outputText = extractResponsesText(response);
						if (outputText.length > 0) accumulator.content = outputText;
						const usage = response.usage;
						accumulator.setUsage({
							inputTokens: usage?.input_tokens,
							outputTokens: usage?.output_tokens,
							totalTokens: usage?.total_tokens,
							reasoningTokens: usage?.output_tokens_details?.reasoning_tokens
						});
						const finishReason = extractResponsesFinishReason(response);
						if (finishReason != null) accumulator.finishReason = finishReason;
					}
				}
				yield event;
			}
		} catch (error) {
			accumulator.setError(error instanceof Error ? error.message : String(error));
			throw error;
		} finally {
			const state = accumulator.getState();
			let costUsd = null;
			if (state.inputTokens != null && state.outputTokens != null) try {
				costUsd = calculateCost({
					modelName: String(accumulator.model ?? params.model ?? "unknown"),
					inputTokens: state.inputTokens,
					outputTokens: state.outputTokens,
					reasoningTokens: state.reasoningTokens ?? 0,
					defaultProvider: "openai"
				});
			} catch {}
			this._trackFn({
				...contextFields(sessionCtx),
				modelName: String(accumulator.model ?? params.model ?? "unknown"),
				provider: this._providerName,
				responseContent: state.content,
				latencyMs: accumulator.elapsedMs,
				inputTokens: state.inputTokens,
				outputTokens: state.outputTokens,
				totalTokens: state.totalTokens,
				reasoningTokens: state.reasoningTokens,
				totalCostUsd: costUsd,
				finishReason: state.finishReason,
				providerTtfbMs: state.ttfbMs,
				isStreaming: true,
				isError: state.isError,
				errorMessage: state.errorMessage,
				toolDefinitions: extractResponsesToolDefinitions(params),
				systemPrompt: extractResponsesSystemPrompt(params),
				temperature: params.temperature,
				maxOutputTokens: params.max_output_tokens,
				topP: params.top_p
			});
		}
	}
	_withContextHeaders(params) {
		if (!this._propagateContext) return params;
		const injected = injectContext(params.extra_headers ?? params.headers);
		return {
			...params,
			extra_headers: injected
		};
	}
	_trackInputMessages(input, ctx, shouldTrackInputMessages) {
		if (!shouldTrackInputMessages) return;
		if (ctx.userId == null && ctx.deviceId == null || ctx.sessionId == null) return;
		if (getActiveContext()?.skipAutoUserTracking) return;
		for (const text of extractResponsesUserInputs(input)) {
			if (!text) continue;
			trackUserMessage({
				amplitude: this._amplitude,
				userId: ctx.userId ?? void 0,
				deviceId: ctx.deviceId ?? void 0,
				messageContent: text,
				sessionId: ctx.sessionId,
				traceId: ctx.traceId,
				turnId: ctx.turnId ?? void 0,
				messageSource: ctx.parentAgentId ? "agent" : "user",
				agentId: ctx.agentId,
				parentAgentId: ctx.parentAgentId,
				customerOrgId: ctx.customerOrgId,
				agentVersion: ctx.agentVersion,
				context: ctx.context,
				env: ctx.env,
				groups: ctx.groups,
				eventProperties: ctx.eventProperties,
				privacyConfig: this._privacyConfig
			});
		}
		extractAndTrackResponsesToolCalls(input, {
			amplitude: this._amplitude,
			ctx,
			privacyConfig: this._privacyConfig
		});
	}
};
function _isAsyncIterable(value) {
	return value != null && typeof value[Symbol.asyncIterator] === "function";
}
function extractSystemPrompt(params) {
	const messages = params.messages;
	if (!messages?.length) return void 0;
	const systemMsg = messages.find((m) => m.role === "system" || m.role === "developer");
	return systemMsg ? String(systemMsg.content ?? "") : void 0;
}
function extractResponsesSystemPrompt(params) {
	const instructions = params.instructions;
	return typeof instructions === "string" ? instructions : void 0;
}
function extractResponsesFinishReason(resp) {
	const status = resp.status;
	if (typeof status === "string" && status.length > 0) return status;
	const out = resp.output?.[0];
	if (out != null && typeof out.status === "string") return out.status;
}
function extractResponsesText(resp) {
	if (typeof resp.output_text === "string") return resp.output_text;
	const outputs = resp.output ?? [];
	let text = "";
	for (const item of outputs) text += extractOutputItemText(item);
	return text;
}
function extractResponsesToolCalls(resp) {
	const toolCalls = [];
	const outputs = resp.output ?? [];
	for (const item of outputs) {
		if (!Array.isArray(item.content)) continue;
		for (const contentItem of item.content) if (contentItem?.type === "tool_call" || contentItem?.type === "function_call") toolCalls.push(contentItem);
	}
	return toolCalls;
}
function extractOutputItemText(item) {
	if (!Array.isArray(item.content)) return "";
	let text = "";
	for (const c of item.content) if (typeof c?.text === "string") text += c.text;
	return text;
}
function extractToolDefinitions(params) {
	const tools = params.tools;
	return Array.isArray(tools) && tools.length > 0 ? tools : void 0;
}
function extractResponsesToolDefinitions(params) {
	const tools = params.tools;
	return Array.isArray(tools) && tools.length > 0 ? tools : void 0;
}
/**
* Extract tool call events from OpenAI Chat Completions message arrays.
*
* In a tool-use conversation, the messages array contains:
*   { role: "assistant", tool_calls: [{ id, function: { name, arguments } }] }
*   { role: "tool", tool_call_id: "...", content: "..." }
*
* We scan for the most recent assistant->tool exchange and emit
* trackToolCall() for each tool result. Only the latest exchange is
* processed to avoid re-tracking in multi-turn loops.
*/
function extractAndTrackToolCalls(msgs, { amplitude, ctx, privacyConfig }) {
	if (ctx.userId == null && ctx.deviceId == null || ctx.sessionId == null) return;
	let assistantIdx = -1;
	for (let i = msgs.length - 1; i >= 0; i--) {
		const m = msgs[i];
		if (m?.role === "assistant" && Array.isArray(m.tool_calls) && m.tool_calls.length > 0) {
			assistantIdx = i;
			break;
		}
	}
	if (assistantIdx < 0) return;
	const assistantMsg = msgs[assistantIdx];
	if (!assistantMsg) return;
	const toolCalls = assistantMsg.tool_calls;
	const toolCallMap = /* @__PURE__ */ new Map();
	for (const tc of toolCalls) if (tc.id && tc.function?.name) toolCallMap.set(tc.id, {
		name: tc.function.name,
		args: tc.function.arguments ?? ""
	});
	for (let i = assistantIdx + 1; i < msgs.length; i++) {
		const msg = msgs[i];
		if (msg?.role !== "tool") break;
		const toolCallId = msg.tool_call_id;
		const matched = toolCallId ? toolCallMap.get(toolCallId) : void 0;
		const toolName = matched?.name ?? "unknown";
		const toolInput = matched?.args;
		const toolOutput = typeof msg.content === "string" ? msg.content : void 0;
		const latencyMs = consumeToolUseLatencyMs({
			sessionId: ctx.sessionId,
			toolUseId: toolCallId,
			agentId: ctx.agentId
		});
		trackToolCall({
			amplitude,
			userId: ctx.userId ?? void 0,
			deviceId: ctx.deviceId ?? void 0,
			toolName,
			success: true,
			latencyMs,
			sessionId: ctx.sessionId,
			traceId: ctx.traceId,
			turnId: ctx.turnId ?? void 0,
			toolInput: toolInput != null ? toolInput : void 0,
			toolOutput,
			agentId: ctx.agentId,
			parentAgentId: ctx.parentAgentId,
			customerOrgId: ctx.customerOrgId,
			agentVersion: ctx.agentVersion,
			context: ctx.context,
			env: ctx.env,
			groups: ctx.groups,
			eventProperties: ctx.eventProperties,
			privacyConfig: privacyConfig ?? void 0
		});
	}
}
/**
* Extract tool call events from OpenAI Responses API input arrays.
*
* In the Responses API, tool results appear as entries with
* type: "function_call_output". We correlate with preceding
* type: "function_call" entries to get tool names and arguments.
*/
function extractAndTrackResponsesToolCalls(input, { amplitude, ctx, privacyConfig }) {
	if (ctx.userId == null && ctx.deviceId == null || ctx.sessionId == null) return;
	if (!Array.isArray(input)) return;
	const entries = input;
	let lastFnCallIdx = -1;
	for (let i = entries.length - 1; i >= 0; i--) {
		const e = entries[i];
		if (e != null && typeof e !== "string" && e.type === "function_call") {
			lastFnCallIdx = i;
			break;
		}
	}
	if (lastFnCallIdx < 0) return;
	const fnCallMap = /* @__PURE__ */ new Map();
	for (let i = lastFnCallIdx; i >= 0; i--) {
		const e = entries[i];
		if (e == null || typeof e === "string") break;
		if (e.type === "function_call") {
			const callId = e.call_id;
			const name = e.name;
			const args = e.arguments;
			if (callId && name) fnCallMap.set(callId, {
				name,
				args: args ?? ""
			});
		} else if (e.type !== "function_call_output") break;
	}
	for (let i = lastFnCallIdx + 1; i < entries.length; i++) {
		const e = entries[i];
		if (e == null || typeof e === "string") continue;
		if (e.type !== "function_call_output") continue;
		const callId = e.call_id;
		const matched = callId ? fnCallMap.get(callId) : void 0;
		const toolName = matched?.name ?? "unknown";
		const toolInput = matched?.args;
		const output = e.output;
		const latencyMs = consumeToolUseLatencyMs({
			sessionId: ctx.sessionId,
			toolUseId: callId,
			agentId: ctx.agentId
		});
		trackToolCall({
			amplitude,
			userId: ctx.userId ?? void 0,
			deviceId: ctx.deviceId ?? void 0,
			toolName,
			success: true,
			latencyMs,
			sessionId: ctx.sessionId,
			traceId: ctx.traceId,
			turnId: ctx.turnId ?? void 0,
			toolInput: toolInput != null ? toolInput : void 0,
			toolOutput: output,
			agentId: ctx.agentId,
			parentAgentId: ctx.parentAgentId,
			customerOrgId: ctx.customerOrgId,
			agentVersion: ctx.agentVersion,
			context: ctx.context,
			env: ctx.env,
			groups: ctx.groups,
			eventProperties: ctx.eventProperties,
			privacyConfig: privacyConfig ?? void 0
		});
	}
}
function extractResponsesUserInputs(input) {
	if (typeof input === "string") return [input];
	if (!Array.isArray(input)) return [];
	const entries = input;
	const lastReplyIdx = entries.findLastIndex((e) => {
		if (typeof e === "string") return false;
		return e.role === "assistant" || e.type === "function_call" || e.type === "function_call_output";
	});
	const newEntries = entries.slice(lastReplyIdx + 1);
	const result = [];
	for (const entry of newEntries) {
		if (typeof entry === "string") {
			result.push(entry);
			continue;
		}
		if (entry.role !== "user") continue;
		const content = entry.content;
		if (typeof content === "string") result.push(content);
		else if (Array.isArray(content)) {
			for (const part of content) if (typeof part?.text === "string") result.push(part.text);
		}
	}
	return result;
}

//#endregion
export { OPENAI_AVAILABLE, OpenAI, WrappedChat, WrappedCompletions, WrappedResponses, _OpenAIModule, extractSystemPrompt, extractToolDefinitions };
//# sourceMappingURL=openai.js.map