import "../constants.js";
import { AIMessageChunk, isBaseMessage, isBaseMessageChunk, isToolMessage } from "@langchain/core/messages";
import { BaseCallbackHandler } from "@langchain/core/callbacks/base";
//#region src/pregel/messages.ts
function isChatGenerationChunk(x) {
	return isBaseMessage(x?.message);
}
function normalizeStreamMetadata(metadata, tags, name) {
	if (!metadata) return;
	const streamNamespace = metadata.langgraph_checkpoint_ns;
	const checkpointNs = metadata.checkpoint_ns;
	const namespace = streamNamespace ?? checkpointNs;
	if (!namespace) return;
	return [namespace.split("|"), {
		tags,
		name,
		...metadata
	}];
}
/**
* A callback handler that implements stream_mode=messages.
* Collects messages from (1) chat model stream events and (2) node outputs.
*/
var StreamMessagesHandler = class extends BaseCallbackHandler {
	name = "StreamMessagesHandler";
	streamFn;
	metadatas = {};
	seen = {};
	emittedChatModelRunIds = {};
	stableMessageIdMap = {};
	lc_prefer_streaming = true;
	constructor(streamFn) {
		super();
		this.streamFn = streamFn;
	}
	_emit(meta, message, runId, dedupe = false) {
		if (dedupe && message.id !== void 0 && this.seen[message.id] !== void 0) return;
		let messageId = message.id;
		if (runId != null) if (isToolMessage(message)) messageId ??= `run-${runId}-tool-${message.tool_call_id}`;
		else {
			if (messageId == null || messageId === `run-${runId}`) messageId = this.stableMessageIdMap[runId] ?? messageId ?? `run-${runId}`;
			this.stableMessageIdMap[runId] ??= messageId;
		}
		if (messageId !== message.id) {
			message.id = messageId;
			message.lc_kwargs.id = messageId;
		}
		if (message.id != null) this.seen[message.id] = message;
		this.streamFn([
			meta[0],
			"messages",
			[message, meta[1]]
		]);
	}
	handleChatModelStart(_llm, _messages, runId, _parentRunId, _extraParams, tags, metadata, name) {
		if (metadata && (!tags || !tags.includes("langsmith:nostream") && !tags.includes("nostream"))) this.metadatas[runId] = normalizeStreamMetadata(metadata, tags, name);
	}
	handleLLMNewToken(token, _idx, runId, _parentRunId, _tags, fields) {
		const chunk = fields?.chunk;
		this.emittedChatModelRunIds[runId] = true;
		if (this.metadatas[runId] !== void 0) if (isChatGenerationChunk(chunk)) this._emit(this.metadatas[runId], chunk.message, runId);
		else this._emit(this.metadatas[runId], new AIMessageChunk({ content: token }), runId);
	}
	handleLLMEnd(output, runId) {
		if (this.metadatas[runId] === void 0) return;
		if (!this.emittedChatModelRunIds[runId]) {
			const chatGeneration = output.generations?.[0]?.[0];
			if (isBaseMessage(chatGeneration?.message)) this._emit(this.metadatas[runId], chatGeneration?.message, runId, true);
			delete this.emittedChatModelRunIds[runId];
		}
		delete this.metadatas[runId];
		delete this.stableMessageIdMap[runId];
	}
	handleLLMError(_err, runId) {
		delete this.metadatas[runId];
	}
	handleChainStart(_chain, inputs, runId, _parentRunId, tags, metadata, _runType, name) {
		if (metadata !== void 0 && name === metadata.langgraph_node && (tags === void 0 || !tags.includes("langsmith:hidden"))) {
			this.metadatas[runId] = normalizeStreamMetadata(metadata, tags, name);
			if (typeof inputs === "object") {
				for (const value of Object.values(inputs)) if ((isBaseMessage(value) || isBaseMessageChunk(value)) && value.id !== void 0) this.seen[value.id] = value;
				else if (Array.isArray(value)) {
					for (const item of value) if ((isBaseMessage(item) || isBaseMessageChunk(item)) && item.id !== void 0) this.seen[item.id] = item;
				}
			}
		}
	}
	handleChainEnd(outputs, runId) {
		const metadata = this.metadatas[runId];
		delete this.metadatas[runId];
		if (metadata !== void 0) {
			if (isBaseMessage(outputs)) this._emit(metadata, outputs, runId, true);
			else if (Array.isArray(outputs)) {
				for (const value of outputs) if (isBaseMessage(value)) this._emit(metadata, value, runId, true);
			} else if (outputs != null && typeof outputs === "object") {
				for (const value of Object.values(outputs)) if (isBaseMessage(value)) this._emit(metadata, value, runId, true);
				else if (Array.isArray(value)) {
					for (const item of value) if (isBaseMessage(item)) this._emit(metadata, item, runId, true);
				}
			}
		}
	}
	handleChainError(_err, runId) {
		delete this.metadatas[runId];
	}
};
//#endregion
export { StreamMessagesHandler };

//# sourceMappingURL=messages.js.map