import { getActiveContext } from "../context.js";
import { calculateCost, inferProvider } from "../utils/costs.js";

//#region src/integrations/langchain.ts
var AmplitudeCallbackHandler = class {
	_ai;
	_userId;
	_sessionId;
	_agentId;
	_env;
	_privacyConfig;
	_runStartTimes = /* @__PURE__ */ new Map();
	_runModelNames = /* @__PURE__ */ new Map();
	_toolInputs = /* @__PURE__ */ new Map();
	_toolNames = /* @__PURE__ */ new Map();
	constructor(options) {
		this._ai = options.amplitudeAI;
		this._userId = options.userId ?? null;
		this._sessionId = options.sessionId ?? null;
		this._agentId = options.agentId ?? null;
		this._env = options.env ?? null;
		this._privacyConfig = options.privacyConfig ?? null;
	}
	_getContext() {
		const ctx = getActiveContext();
		return {
			userId: this._userId ?? ctx?.userId ?? "unknown",
			sessionId: this._sessionId ?? ctx?.sessionId ?? void 0,
			agentId: this._agentId ?? ctx?.agentId ?? void 0,
			env: this._env ?? ctx?.env ?? void 0,
			traceId: ctx?.traceId ?? void 0
		};
	}
	handleLLMStart(serialized, prompts, runId) {
		this._runStartTimes.set(runId, performance.now());
		const kwargs = serialized.kwargs;
		const idModel = Array.isArray(serialized.id) ? serialized.id.find((v) => typeof v === "string" && (/\d/.test(v) || v.includes("."))) : void 0;
		const modelName = String(kwargs?.model ?? kwargs?.modelName ?? kwargs?.model_name ?? idModel ?? "");
		if (modelName) this._runModelNames.set(runId, modelName);
		const trackUserMessage = this._ai.trackUserMessage;
		if (typeof trackUserMessage === "function") {
			const ctx = this._getContext();
			for (const prompt of prompts) {
				if (!prompt) continue;
				trackUserMessage({
					userId: ctx.userId,
					content: prompt,
					sessionId: ctx.sessionId ?? "langchain-session",
					traceId: ctx.traceId,
					agentId: ctx.agentId,
					env: ctx.env
				});
			}
		}
	}
	handleLLMEnd(output, runId) {
		const startTime = this._runStartTimes.get(runId) ?? performance.now();
		this._runStartTimes.delete(runId);
		const latencyMs = performance.now() - startTime;
		const firstGen = output.generations?.[0]?.[0];
		const content = _extractLangchainText(firstGen);
		const llmOutput = output.llmOutput;
		const usage = llmOutput?.tokenUsage ?? llmOutput?.usage ?? llmOutput?.usage_metadata;
		const modelFromStart = this._runModelNames.get(runId);
		this._runModelNames.delete(runId);
		const ctx = this._getContext();
		const modelName = String(llmOutput?.modelName ?? modelFromStart ?? "unknown");
		const { inputTokens, outputTokens, cacheReadTokens, cacheCreationTokens } = _extractLangchainUsage(usage);
		let costUsd;
		if (modelName !== "unknown" && inputTokens != null && outputTokens != null) try {
			const cost = calculateCost({
				modelName,
				inputTokens,
				outputTokens,
				cacheReadInputTokens: cacheReadTokens,
				cacheCreationInputTokens: cacheCreationTokens,
				defaultProvider: inferProvider(modelName)
			});
			if (cost > 0) costUsd = cost;
		} catch {}
		this._ai.trackAiMessage({
			userId: ctx.userId,
			content,
			sessionId: ctx.sessionId ?? "langchain-session",
			model: modelName,
			provider: "langchain",
			latencyMs,
			traceId: ctx.traceId,
			agentId: ctx.agentId,
			env: ctx.env,
			inputTokens,
			outputTokens,
			totalTokens: _safeNumber(usage?.totalTokens ?? usage?.total_tokens),
			totalCostUsd: costUsd,
			privacyConfig: this._privacyConfig
		});
	}
	handleToolStart(serialized, input, runId) {
		this._runStartTimes.set(runId, performance.now());
		this._toolInputs.set(runId, input);
		const name = String(serialized.name ?? serialized.id?.slice(-1)[0] ?? "langchain-tool");
		this._toolNames.set(runId, name);
	}
	handleToolEnd(output, runId) {
		const startTime = this._runStartTimes.get(runId) ?? performance.now();
		this._runStartTimes.delete(runId);
		const latencyMs = performance.now() - startTime;
		const toolInput = this._toolInputs.get(runId);
		this._toolInputs.delete(runId);
		const toolName = this._toolNames.get(runId) ?? "langchain-tool";
		this._toolNames.delete(runId);
		const ctx = this._getContext();
		this._ai.trackToolCall({
			userId: ctx.userId,
			toolName,
			latencyMs,
			success: true,
			sessionId: ctx.sessionId,
			traceId: ctx.traceId,
			agentId: ctx.agentId,
			env: ctx.env,
			input: toolInput,
			output
		});
	}
	handleToolError(error, runId) {
		const startTime = this._runStartTimes.get(runId) ?? performance.now();
		this._runStartTimes.delete(runId);
		const latencyMs = performance.now() - startTime;
		const toolInput = this._toolInputs.get(runId);
		this._toolInputs.delete(runId);
		const toolName = this._toolNames.get(runId) ?? "langchain-tool";
		this._toolNames.delete(runId);
		const ctx = this._getContext();
		this._ai.trackToolCall({
			userId: ctx.userId,
			toolName,
			latencyMs,
			success: false,
			sessionId: ctx.sessionId,
			traceId: ctx.traceId,
			agentId: ctx.agentId,
			env: ctx.env,
			input: toolInput,
			errorMessage: error instanceof Error ? error.message : String(error)
		});
	}
	handleLLMError(error, runId) {
		const startTime = this._runStartTimes.get(runId) ?? performance.now();
		this._runStartTimes.delete(runId);
		const latencyMs = performance.now() - startTime;
		const ctx = this._getContext();
		this._ai.trackAiMessage({
			userId: ctx.userId,
			content: "",
			sessionId: ctx.sessionId ?? "langchain-session",
			model: "unknown",
			provider: "langchain",
			latencyMs,
			traceId: ctx.traceId,
			agentId: ctx.agentId,
			env: ctx.env,
			isError: true,
			errorMessage: error instanceof Error ? error.message : String(error)
		});
	}
};
function createAmplitudeCallback(options) {
	return new AmplitudeCallbackHandler(options);
}
function _safeNumber(value) {
	return typeof value === "number" ? value : void 0;
}
function _extractLangchainUsage(usage) {
	if (!usage) return {
		inputTokens: void 0,
		outputTokens: void 0,
		cacheReadTokens: 0,
		cacheCreationTokens: 0
	};
	const outputTokens = _safeNumber(usage.completionTokens ?? usage.completion_tokens ?? usage.output_tokens);
	const promptTokens = _safeNumber(usage.promptTokens ?? usage.prompt_tokens);
	if (promptTokens != null) {
		const details = usage.prompt_tokens_details;
		return {
			inputTokens: promptTokens,
			outputTokens,
			cacheReadTokens: _safeNumber(details?.cached_tokens ?? details?.cachedTokens) ?? 0,
			cacheCreationTokens: 0
		};
	}
	const rawInput = _safeNumber(usage.input_tokens);
	const cacheRead = _safeNumber(usage.cache_read_input_tokens) ?? 0;
	const cacheCreation = _safeNumber(usage.cache_creation_input_tokens) ?? 0;
	return {
		inputTokens: rawInput != null ? rawInput + cacheRead + cacheCreation : void 0,
		outputTokens,
		cacheReadTokens: cacheRead,
		cacheCreationTokens: cacheCreation
	};
}
function _extractLangchainText(generation) {
	if (generation == null || typeof generation !== "object") return "";
	const gen = generation;
	if (typeof gen.text === "string") return gen.text;
	const message = gen.message;
	if (message == null) return "";
	if (typeof message.content === "string") return message.content;
	if (!Array.isArray(message.content)) return "";
	return message.content.map((part) => {
		if (typeof part === "string") return part;
		const item = part;
		return typeof item.text === "string" ? item.text : "";
	}).join("");
}

//#endregion
export { AmplitudeCallbackHandler, createAmplitudeCallback };
//# sourceMappingURL=langchain.js.map