import { createLogger } from "../../utils/logger/index.js";
import { init_logger } from "../../utils/logger.js";
import { readAgentMessageContent } from "./agent-message-access.js";
//#region src/agent/memory/message-sanitizer.ts
init_logger();
const log = createLogger("MessageSanitizer");
/**
* Single multimodal / structured block is meaningful for history persistence.
* Handles blocks without `type` (e.g. { data, mimeType } only) that some providers emit.
*/
function isMeaningfulContentBlock(item) {
	if (typeof item === "string") return item.trim().length > 0;
	if (!item || typeof item !== "object") return false;
	const o = item;
	const t = o.type;
	if (t === "text") return String(o.text ?? "").trim().length > 0;
	if (t === "toolCall") return String(o.name ?? "").trim().length > 0;
	if (t === "thinking") return true;
	if (t === "image" || t === "image_url" || t === "input_image" || t === "file" || t === "audio" || t === "video") return true;
	if (o.image_url !== void 0 || o.imageUrl !== void 0) return true;
	if (o.inlineData !== void 0 || o.inline_data !== void 0) return true;
	if (typeof o.data === "string" && o.data.length > 0 && typeof o.mimeType === "string") return true;
	if (typeof t === "string" && t.length > 0) return true;
	return false;
}
/**
* Check if a message has valid, non-empty content
*/
function hasValidContent(message) {
	const msg = message;
	if (message.role === "assistant") {
		if (Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0) return true;
		if (Array.isArray(msg.toolCalls) && msg.toolCalls.length > 0) return true;
	}
	const content = readAgentMessageContent(message);
	if (typeof content === "string") return content.trim().length > 0;
	if (Array.isArray(content)) return content.some((item) => isMeaningfulContentBlock(item));
	return false;
}
/**
* Check if a message is an error message from a failed LLM call
*/
function isErrorMessage(message) {
	if (message.role !== "assistant") return false;
	const msg = message;
	if (msg.stopReason === "error") return true;
	if (msg.stopReason === "aborted") return !hasValidContent(message);
	if (msg.errorMessage) return true;
	return false;
}
/**
* Check if a message might cause issues in subsequent API calls
*/
function isProblematicMessage(message) {
	if (message.role !== "assistant") return false;
	if (isErrorMessage(message)) return true;
	if (!hasValidContent(message)) return true;
	return false;
}
/**
* Sanitize messages before saving to history.
*
* Removes:
* - Assistant messages with stopReason: "error"
* - Assistant messages with stopReason: "aborted" only when empty (partial interrupted text is kept)
* - Assistant messages with errorMessage field
* - Assistant messages with empty/invalid content
*
* @param messages - Messages to sanitize
* @param options - Sanitization options
* @returns Sanitized messages and removal details
*/
function sanitizeMessages(messages, options = {}) {
	const { removeErrors = true, removeEmpty = true, keepRecent = 0, logRemovals = true } = options;
	const reasons = [];
	const result = [];
	const preserveIndices = /* @__PURE__ */ new Set();
	if (keepRecent > 0) for (let i = Math.max(0, messages.length - keepRecent); i < messages.length; i++) preserveIndices.add(i);
	for (let i = 0; i < messages.length; i++) {
		const message = messages[i];
		const originalIndex = i;
		if (message.role !== "assistant") {
			result.push(message);
			continue;
		}
		if (preserveIndices.has(i)) {
			result.push(message);
			continue;
		}
		if (removeErrors && isErrorMessage(message)) {
			reasons.push({
				index: originalIndex,
				reason: `Error message: stopReason=${message.stopReason}, errorMessage=${message.errorMessage || "none"}`
			});
			continue;
		}
		if (removeEmpty && !hasValidContent(message)) {
			reasons.push({
				index: originalIndex,
				reason: "Empty or invalid content"
			});
			continue;
		}
		result.push(message);
	}
	const removed = messages.length - result.length;
	if (logRemovals && removed > 0) log.info({
		removed,
		original: messages.length,
		sanitized: result.length,
		reasons: reasons.slice(0, 5)
	}, "Sanitized messages");
	return {
		messages: result,
		removed,
		reasons
	};
}
/**
* Clean trailing error messages from message history.
*
* This is useful for cleaning up after a failed turn, ensuring
* the conversation can continue from the last valid state.
*
* @param messages - Messages to clean
* @returns Cleaned messages
*/
function cleanTrailingErrors(messages) {
	const result = [...messages];
	while (result.length > 0) {
		const last = result[result.length - 1];
		if (last.role === "assistant" && isProblematicMessage(last)) {
			const msg = last;
			log.debug({ stopReason: msg.stopReason }, "Removing trailing error message");
			result.pop();
		} else break;
	}
	return result;
}
/**
* Validate a single message for potential issues.
* Returns null if valid, or an error description if problematic.
*/
function validateMessage(message) {
	if (message.role === "assistant") {
		if (isErrorMessage(message)) return `Error message: stopReason=${message.stopReason}`;
		if (!hasValidContent(message)) return "Empty or invalid content";
	}
	if (message.role === "toolResult") {
		const content = message.content;
		if (typeof content === "string" && content.includes("tool_call_id is not found")) return "Contains invalid tool_call_id reference";
	}
	return null;
}
/**
* Quick check if messages contain any problematic entries.
* Useful for debugging and monitoring.
*/
function hasProblematicMessages(messages) {
	return messages.some((m) => isProblematicMessage(m));
}
//#endregion
export { cleanTrailingErrors, hasProblematicMessages, sanitizeMessages, validateMessage };

//# sourceMappingURL=message-sanitizer.js.map