/**
 * Message Processor Module
 *
 * Handles message processing, streaming, and tool call extraction.
 * Extracted from CodeBuddyAgent for better modularity and testability.
 */
import { EventEmitter } from "events";
/**
 * LLM output sanitization patterns
 */
const LLM_CONTROL_PATTERNS = [
    /<\|[^|>]+\|>/g, // Control tokens like <|channel|>, <|message|>
    /\[INST\].*?\[\/INST\]/gs, // Instruction tags
];
/**
 * Sanitize LLM output by removing control tokens
 */
export function sanitizeLLMOutput(content) {
    let sanitized = content;
    for (const pattern of LLM_CONTROL_PATTERNS) {
        sanitized = sanitized.replace(pattern, "");
    }
    return sanitized;
}
/**
 * Extract tool calls from commentary-style patterns in content
 *
 * Handles patterns like:
 * - "commentary to=web_search {"query":"..."}"
 * - "web_search({"query":"test"})"
 */
export function extractCommentaryToolCalls(content) {
    const toolCalls = [];
    let remainingContent = content;
    // Pattern 1: commentary to=tool_name {...}
    const commentaryPattern = /commentary\s+to=(\w+)\s+(\{[^}]+\})/g;
    let match;
    while ((match = commentaryPattern.exec(content)) !== null) {
        try {
            const toolName = match[1];
            const args = JSON.parse(match[2]);
            toolCalls.push({ name: toolName, arguments: args });
            remainingContent = remainingContent.replace(match[0], "").trim();
        }
        catch {
            // Invalid JSON, skip this match
        }
    }
    // Pattern 2: tool_name({...})
    const functionCallPattern = /(\w+)\s*\(\s*(\{[^}]+\})\s*\)/g;
    while ((match = functionCallPattern.exec(content)) !== null) {
        try {
            const toolName = match[1];
            // Skip if it's a common JavaScript function
            if (["console", "log", "error", "warn", "info", "debug"].includes(toolName)) {
                continue;
            }
            const args = JSON.parse(match[2]);
            toolCalls.push({ name: toolName, arguments: args });
            remainingContent = remainingContent.replace(match[0], "").trim();
        }
        catch {
            // Invalid JSON, skip this match
        }
    }
    return { toolCalls, remainingContent };
}
/**
 * MessageProcessor handles message creation and history management.
 */
export class MessageProcessor extends EventEmitter {
    chatHistory = [];
    messages = [];
    constructor(systemPrompt) {
        super();
        if (systemPrompt) {
            this.messages.push({
                role: "system",
                content: systemPrompt,
            });
        }
    }
    /**
     * Add a user message to history
     */
    addUserMessage(content) {
        const entry = {
            type: "user",
            content,
            timestamp: new Date(),
        };
        this.chatHistory.push(entry);
        this.messages.push({
            role: "user",
            content,
        });
        this.emit("message:added", entry);
    }
    /**
     * Add an assistant message to history
     */
    addAssistantMessage(content, toolCalls) {
        const entry = {
            type: "assistant",
            content,
            timestamp: new Date(),
            toolCalls,
        };
        this.chatHistory.push(entry);
        this.messages.push({
            role: "assistant",
            content,
            tool_calls: toolCalls,
        });
        this.emit("message:added", entry);
    }
    /**
     * Add a tool result to history
     */
    addToolResult(toolCall, result) {
        const entry = {
            type: "tool_result",
            content: result.success ? result.output || "Success" : result.error || "Error",
            timestamp: new Date(),
            toolCall,
            toolResult: result,
        };
        this.chatHistory.push(entry);
        this.messages.push({
            role: "tool",
            content: result.success ? result.output || "Success" : result.error || "Error",
            tool_call_id: toolCall.id,
        });
        this.emit("tool_result:added", entry);
    }
    /**
     * Add a system message
     */
    addSystemMessage(content) {
        const entry = {
            type: "system",
            content,
            timestamp: new Date(),
        };
        this.chatHistory.push(entry);
        this.emit("message:added", entry);
    }
    /**
     * Get all messages for API call
     */
    getMessages() {
        return [...this.messages];
    }
    /**
     * Get chat history
     */
    getChatHistory() {
        return [...this.chatHistory];
    }
    /**
     * Set messages (for context management)
     */
    setMessages(messages) {
        this.messages = messages;
    }
    /**
     * Get the system message
     */
    getSystemMessage() {
        return this.messages.find((m) => m.role === "system");
    }
    /**
     * Update the system message
     */
    updateSystemMessage(content) {
        const systemMessage = this.messages.find((m) => m.role === "system");
        if (systemMessage) {
            systemMessage.content = content;
        }
        else {
            this.messages.unshift({
                role: "system",
                content,
            });
        }
        this.emit("system:updated", content);
    }
    /**
     * Clear all history except system message
     */
    clear() {
        this.chatHistory = [];
        // Keep only the system message
        this.messages = this.messages.filter((m) => m.role === "system");
        this.emit("cleared");
    }
    /**
     * Trim history to prevent unbounded growth
     */
    trimHistory(maxSize) {
        if (this.chatHistory.length > maxSize) {
            this.chatHistory = this.chatHistory.slice(-maxSize);
        }
        // Trim messages, keeping system message
        const maxMessages = maxSize + 1;
        if (this.messages.length > maxMessages) {
            const systemMessage = this.messages.find((m) => m.role === "system");
            const recentMessages = this.messages
                .filter((m) => m.role !== "system")
                .slice(-maxSize);
            this.messages = systemMessage
                ? [systemMessage, ...recentMessages]
                : recentMessages;
        }
        this.emit("trimmed", { size: this.chatHistory.length });
    }
    /**
     * Get message count
     */
    getMessageCount() {
        return this.messages.length;
    }
    /**
     * Get the last N messages
     */
    getRecentMessages(count) {
        return this.messages.slice(-count);
    }
    /**
     * Build accumulated message from streaming chunks
     */
    buildAccumulatedMessage(chunks) {
        let content = "";
        let toolCalls;
        for (const chunk of chunks) {
            if (chunk.choices[0]?.delta?.content) {
                content += chunk.choices[0].delta.content;
            }
            if (chunk.choices[0]?.delta?.tool_calls) {
                // Accumulate tool calls
                if (!toolCalls)
                    toolCalls = [];
                // This is simplified - actual implementation needs to merge tool call deltas
            }
        }
        return { content, tool_calls: toolCalls };
    }
    /**
     * Create an error message entry
     */
    createErrorEntry(error) {
        return {
            type: "assistant",
            content: `Sorry, I encountered an error: ${error}`,
            timestamp: new Date(),
        };
    }
    /**
     * Export history to JSON
     */
    exportHistory() {
        return JSON.stringify(this.chatHistory, null, 2);
    }
    /**
     * Import history from JSON
     */
    importHistory(json) {
        try {
            const history = JSON.parse(json);
            this.chatHistory = history.map((entry) => ({
                ...entry,
                timestamp: new Date(entry.timestamp),
            }));
            this.emit("history:imported", this.chatHistory.length);
        }
        catch {
            throw new Error("Invalid history JSON");
        }
    }
}
//# sourceMappingURL=message-processor.js.map