import { BaseMessage } from "../messages/base.js";
import { ToolMessage } from "../messages/tool.js";
import { AIMessage } from "../messages/ai.js";
import { HumanMessage } from "../messages/human.js";
import { SystemMessage } from "../messages/system.js";
import "../messages/index.js";
//#region src/testing/matchers.ts
function getMessageTypeName(msg) {
	if (!BaseMessage.isInstance(msg)) return typeof msg;
	return msg.constructor.name || msg.type;
}
function makeMessageTypeMatcher(typeName, isInstance) {
	return function(received, expected) {
		const { isNot, utils } = this;
		if (!isInstance(received)) return {
			pass: false,
			message: () => `${utils.matcherHint(`toBe${typeName}`, void 0, void 0)}\n\nExpected: ${isNot ? "not " : ""}${typeName}\nReceived: ${getMessageTypeName(received)}`,
			actual: getMessageTypeName(received),
			expected: typeName
		};
		if (expected === void 0) return {
			pass: true,
			message: () => `${utils.matcherHint(`toBe${typeName}`, void 0, void 0)}\n\nExpected: not ${typeName}\nReceived: ${typeName}`
		};
		const msg = received;
		if (typeof expected === "string") return {
			pass: msg.content === expected,
			message: () => `${utils.matcherHint(`toBe${typeName}`, void 0, void 0)}\n\nExpected: ${typeName} with content ${utils.printExpected(expected)}\nReceived: ${typeName} with content ${utils.printReceived(msg.content)}`,
			actual: msg.content,
			expected
		};
		return {
			pass: Object.entries(expected).every(([key, value]) => this.equals(msg[key], value)),
			message: () => {
				const receivedFields = {};
				for (const key of Object.keys(expected)) receivedFields[key] = msg[key];
				return `${utils.matcherHint(`toBe${typeName}`, void 0, void 0)}\n\nExpected: ${typeName} matching ${utils.printExpected(expected)}\nReceived: ${typeName} with ${utils.printReceived(receivedFields)}`;
			},
			actual: (() => {
				const receivedFields = {};
				for (const key of Object.keys(expected)) receivedFields[key] = msg[key];
				return receivedFields;
			})(),
			expected
		};
	};
}
const toBeHumanMessage = makeMessageTypeMatcher("HumanMessage", HumanMessage.isInstance);
const toBeAIMessage = makeMessageTypeMatcher("AIMessage", AIMessage.isInstance);
const toBeSystemMessage = makeMessageTypeMatcher("SystemMessage", SystemMessage.isInstance);
const toBeToolMessage = makeMessageTypeMatcher("ToolMessage", ToolMessage.isInstance);
function toHaveToolCalls(received, expected) {
	const { isNot, utils } = this;
	if (!AIMessage.isInstance(received)) return {
		pass: false,
		message: () => `${utils.matcherHint("toHaveToolCalls")}\n\nExpected: AIMessage\nReceived: ${getMessageTypeName(received)}`
	};
	const actual = received.tool_calls ?? [];
	if (actual.length !== expected.length) return {
		pass: false,
		message: () => `${utils.matcherHint("toHaveToolCalls")}\n\nExpected ${isNot ? "not " : ""}${expected.length} tool call(s), received ${actual.length}`,
		actual: actual.length,
		expected: expected.length
	};
	const unmatched = expected.filter((exp) => !actual.some((tc) => Object.entries(exp).every(([key, value]) => this.equals(tc[key], value))));
	if (unmatched.length > 0) return {
		pass: false,
		message: () => `${utils.matcherHint("toHaveToolCalls")}\n\nCould not find matching tool call(s) for:\n${utils.printExpected(unmatched)}\nReceived tool calls: ${utils.printReceived(actual.map((tc) => ({
			name: tc.name,
			id: tc.id,
			args: tc.args
		})))}`,
		actual: actual.map((tc) => ({
			name: tc.name,
			id: tc.id,
			args: tc.args
		})),
		expected
	};
	return {
		pass: true,
		message: () => `${utils.matcherHint("toHaveToolCalls")}\n\nExpected AIMessage not to have matching tool calls`
	};
}
function toHaveToolCallCount(received, expected) {
	const { isNot, utils } = this;
	if (!AIMessage.isInstance(received)) return {
		pass: false,
		message: () => `${utils.matcherHint("toHaveToolCallCount")}\n\nExpected: AIMessage\nReceived: ${getMessageTypeName(received)}`
	};
	const actual = received.tool_calls?.length ?? 0;
	return {
		pass: actual === expected,
		message: () => `${utils.matcherHint("toHaveToolCallCount")}\n\nExpected ${isNot ? "not " : ""}${expected} tool call(s)\nReceived: ${actual}`,
		actual,
		expected
	};
}
function toContainToolCall(received, expected) {
	const { isNot, utils } = this;
	if (!AIMessage.isInstance(received)) return {
		pass: false,
		message: () => `${utils.matcherHint("toContainToolCall")}\n\nExpected: AIMessage\nReceived: ${getMessageTypeName(received)}`
	};
	const actual = received.tool_calls ?? [];
	return {
		pass: actual.some((tc) => Object.entries(expected).every(([key, value]) => this.equals(tc[key], value))),
		message: () => `${utils.matcherHint("toContainToolCall")}\n\nExpected AIMessage ${isNot ? "not " : ""}to contain a tool call matching ${utils.printExpected(expected)}\nReceived tool calls: ${utils.printReceived(actual.map((tc) => ({
			name: tc.name,
			id: tc.id
		})))}`,
		actual: actual.map((tc) => ({
			name: tc.name,
			id: tc.id
		})),
		expected
	};
}
function toHaveToolMessages(received, expected) {
	const { isNot, utils } = this;
	if (!Array.isArray(received)) return {
		pass: false,
		message: () => `${utils.matcherHint("toHaveToolMessages")}\n\nExpected an array of messages\nReceived: ${typeof received}`
	};
	const toolMessages = received.filter(ToolMessage.isInstance);
	if (toolMessages.length !== expected.length) return {
		pass: false,
		message: () => `${utils.matcherHint("toHaveToolMessages")}\n\nExpected ${isNot ? "not " : ""}${expected.length} tool message(s), found ${toolMessages.length}`,
		actual: toolMessages.length,
		expected: expected.length
	};
	for (let i = 0; i < expected.length; i++) if (!Object.entries(expected[i]).every(([key, value]) => this.equals(toolMessages[i][key], value))) return {
		pass: false,
		message: () => {
			const receivedFields = {};
			for (const key of Object.keys(expected[i])) receivedFields[key] = toolMessages[i][key];
			return `${utils.matcherHint("toHaveToolMessages")}\n\nTool message at index ${i} did not match:\nExpected: ${utils.printExpected(expected[i])}\nReceived: ${utils.printReceived(receivedFields)}`;
		},
		actual: toolMessages[i],
		expected: expected[i]
	};
	return {
		pass: true,
		message: () => `${utils.matcherHint("toHaveToolMessages")}\n\nExpected messages not to contain matching tool messages`
	};
}
function toHaveBeenInterrupted(received, expectedValue) {
	const { isNot, utils } = this;
	const interrupts = received?.__interrupt__;
	if (!(Array.isArray(interrupts) && interrupts.length > 0)) return {
		pass: false,
		message: () => `${utils.matcherHint("toHaveBeenInterrupted")}\n\nExpected result ${isNot ? "not " : ""}to have been interrupted\nReceived __interrupt__: ${utils.printReceived(interrupts)}`
	};
	if (expectedValue === void 0) return {
		pass: true,
		message: () => `${utils.matcherHint("toHaveBeenInterrupted")}\n\nExpected result not to have been interrupted\nReceived ${interrupts.length} interrupt(s)`
	};
	const actualValue = interrupts[0]?.value;
	return {
		pass: this.equals(actualValue, expectedValue),
		message: () => `${utils.matcherHint("toHaveBeenInterrupted")}\n\nExpected interrupt value: ${utils.printExpected(expectedValue)}\nReceived interrupt value: ${utils.printReceived(actualValue)}`,
		actual: actualValue,
		expected: expectedValue
	};
}
function toHaveStructuredResponse(received, expected) {
	const { isNot, utils } = this;
	const structuredResponse = received?.structuredResponse;
	if (!(structuredResponse !== void 0)) return {
		pass: false,
		message: () => `${utils.matcherHint("toHaveStructuredResponse")}\n\nExpected result ${isNot ? "not " : ""}to have a structured response\nReceived structuredResponse: undefined`
	};
	if (expected === void 0) return {
		pass: true,
		message: () => `${utils.matcherHint("toHaveStructuredResponse")}\n\nExpected result not to have a structured response`
	};
	return {
		pass: Object.entries(expected).every(([key, value]) => this.equals(structuredResponse[key], value)),
		message: () => `${utils.matcherHint("toHaveStructuredResponse")}\n\nExpected structured response: ${utils.printExpected(expected)}\nReceived structured response: ${utils.printReceived(structuredResponse)}`,
		actual: structuredResponse,
		expected
	};
}
/**
* All matcher functions bundled for convenient use with `expect.extend()`.
*/
const langchainMatchers = {
	toBeHumanMessage,
	toBeAIMessage,
	toBeSystemMessage,
	toBeToolMessage,
	toHaveToolCalls,
	toHaveToolCallCount,
	toContainToolCall,
	toHaveToolMessages,
	toHaveBeenInterrupted,
	toHaveStructuredResponse
};
//#endregion
export { langchainMatchers, toBeAIMessage, toBeHumanMessage, toBeSystemMessage, toBeToolMessage, toContainToolCall, toHaveBeenInterrupted, toHaveStructuredResponse, toHaveToolCallCount, toHaveToolCalls, toHaveToolMessages };

//# sourceMappingURL=matchers.js.map