"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.globalXmlToolCallProcessor = exports.XmlToolCallProcessor = void 0;
class XmlToolCallProcessor {
    static instance;
    static getInstance() {
        if (!XmlToolCallProcessor.instance) {
            XmlToolCallProcessor.instance = new XmlToolCallProcessor();
        }
        return XmlToolCallProcessor.instance;
    }
    detectXmlToolCalls(content) {
        const toolCallMatches = content.match(/<tool_call>/g);
        const xmlToolCallPattern1SelfClosing = /<(?:tool_call|toolCall|function_call)\s+name=["']([^"']+)["']\s+arguments=(['"])((?:\\.|(?!\2)[^\\])*?)\2[^>]*\/>/g;
        const xmlToolCallPattern1 = /<(?:tool_call|toolCall|function_call)\s+name=["']([^"']+)["'](?:\s+arguments=["']([^"']*)["'])?[^>]*>([^<]*)<\/(?:tool_call|toolCall|function_call)>/g;
        const xmlToolCallPattern2 = /<(?:tool_call|toolCall|function_call)>\s*(\{(?:[^{}]|{[^{}]*})*?"name"\s*:\s*"([^"]+)"(?:[^{}]|{[^{}]*})*?\})\s*<\/(?:tool_call|toolCall|function_call)>/gs;
        const xmlToolCallPattern2Complex = /<(?:tool_call|toolCall|function_call)>\s*(\{[\s\S]*?\})\s*<\/(?:tool_call|toolCall|function_call)>/g;
        const xmlToolCallPattern3 = /<(?:tool_call|toolCall|function_call)>\s*<invoke\s+name=["']([^"']+)["']>\s*(.*?)\s*<\/invoke>\s*<\/(?:tool_call|toolCall|function_call)>/gs;
        const processedRanges = [];
        const matches = [];
        let match;
        xmlToolCallPattern1SelfClosing.lastIndex = 0;
        while ((match = xmlToolCallPattern1SelfClosing.exec(content)) !== null) {
            const [fullMatch, toolName, quoteChar, argsAttribute] = match;
            const selfClosingMatch = [fullMatch, toolName, argsAttribute, ""];
            selfClosingMatch.index = match.index;
            selfClosingMatch.input = match.input;
            matches.push(selfClosingMatch);
            processedRanges.push({ start: match.index, end: match.index + match[0].length });
        }
        while ((match = xmlToolCallPattern1.exec(content)) !== null) {
            matches.push(match);
        }
        xmlToolCallPattern1.lastIndex = 0;
        xmlToolCallPattern2.lastIndex = 0;
        while ((match = xmlToolCallPattern2.exec(content)) !== null) {
            const matchStart = match.index;
            const matchEnd = matchStart + match[0].length;
            const alreadyProcessed = processedRanges.some(range => (matchStart >= range.start && matchStart < range.end) ||
                (matchEnd > range.start && matchEnd <= range.end));
            if (alreadyProcessed)
                continue;
            const [fullMatch, jsonContent, toolName] = match;
            try {
                let fixedJsonContent = jsonContent;
                const argumentsStringMatch = jsonContent.match(/"arguments"\s*:\s*"(\{.*\})"/);
                if (argumentsStringMatch) {
                    const innerJson = argumentsStringMatch[1];
                    const escapedInnerJson = innerJson.replace(/"/g, '\\"');
                    fixedJsonContent = jsonContent.replace(/"arguments"\s*:\s*"\{.*\}"/, `"arguments": "${escapedInnerJson}"`);
                }
                const parsed = JSON.parse(fixedJsonContent);
                let argumentsContent = parsed.arguments || "{}";
                if (typeof argumentsContent === 'string') {
                    try {
                        const parsedArgs = JSON.parse(argumentsContent);
                        argumentsContent = argumentsContent;
                    }
                    catch {
                        argumentsContent = JSON.stringify({ input: argumentsContent });
                    }
                }
                else {
                    argumentsContent = JSON.stringify(argumentsContent);
                }
                const restructuredMatch = [
                    fullMatch,
                    toolName,
                    undefined,
                    argumentsContent,
                ];
                restructuredMatch.index = match.index;
                restructuredMatch.input = match.input;
                matches.push(restructuredMatch);
                processedRanges.push({ start: matchStart, end: matchEnd });
            }
            catch (error) {
                try {
                    const stringBlocks = this.extractToolCallBlocks(fullMatch);
                    if (stringBlocks.length > 0) {
                        const block = stringBlocks[0];
                        const restructuredMatch = [fullMatch, block.name, block.arguments, ""];
                        restructuredMatch.index = match.index;
                        restructuredMatch.input = match.input;
                        matches.push(restructuredMatch);
                        processedRanges.push({ start: matchStart, end: matchEnd });
                    }
                    else {
                        continue;
                    }
                }
                catch (stringError) {
                    continue;
                }
            }
        }
        xmlToolCallPattern2Complex.lastIndex = 0;
        while ((match = xmlToolCallPattern2Complex.exec(content)) !== null) {
            const matchStart = match.index;
            const matchEnd = matchStart + match[0].length;
            const alreadyProcessed = processedRanges.some(range => (matchStart >= range.start && matchStart < range.end) ||
                (matchEnd > range.start && matchEnd <= range.end));
            if (alreadyProcessed)
                continue;
            const [fullMatch, jsonContent, ...rest] = match;
            try {
                const parsed = JSON.parse(jsonContent);
                const toolName = parsed.name;
                if (toolName) {
                    let argumentsContent = parsed.arguments || "{}";
                    if (typeof argumentsContent === 'object') {
                        argumentsContent = JSON.stringify(argumentsContent);
                    }
                    const restructuredMatch = [fullMatch, toolName, argumentsContent, ""];
                    restructuredMatch.index = match.index;
                    restructuredMatch.input = match.input;
                    matches.push(restructuredMatch);
                    processedRanges.push({ start: matchStart, end: matchEnd });
                }
            }
            catch (error) {
                continue;
            }
        }
        xmlToolCallPattern3.lastIndex = 0;
        while ((match = xmlToolCallPattern3.exec(content)) !== null) {
            const [fullMatch, toolName, innerXml] = match;
            const restructuredMatch = [
                fullMatch,
                toolName,
                undefined,
                innerXml,
            ];
            restructuredMatch.index = match.index;
            restructuredMatch.input = match.input;
            matches.push(restructuredMatch);
        }
        return matches;
    }
    parseToolCallArguments(argsAttribute, innerContent) {
        if (innerContent && typeof innerContent !== 'string') {
            return typeof innerContent === 'object' ? JSON.stringify(innerContent) : String(innerContent);
        }
        if (innerContent && typeof innerContent === 'string' && innerContent.trim()) {
            const trimmedContent = innerContent.trim();
            try {
                JSON.parse(trimmedContent);
                return trimmedContent;
            }
            catch {
            }
        }
        if (innerContent && innerContent.includes("<parameter")) {
            try {
                const parameterPattern = /<parameter\s+name=["']([^"']+)["']>([^<]*)<\/parameter>/g;
                const parameters = {};
                let paramMatch;
                while ((paramMatch = parameterPattern.exec(innerContent)) !== null) {
                    const [, paramName, paramValue] = paramMatch;
                    parameters[paramName] = paramValue.trim();
                }
                if (Object.keys(parameters).length > 0) {
                    return JSON.stringify(parameters);
                }
            }
            catch (error) {
            }
        }
        if (argsAttribute && argsAttribute.trim()) {
            return argsAttribute.trim();
        }
        if (innerContent && innerContent.trim()) {
            const trimmedContent = innerContent.trim();
            try {
                JSON.parse(trimmedContent);
                return trimmedContent;
            }
            catch {
                if (trimmedContent.includes("=") || trimmedContent.includes(":")) {
                    try {
                        const jsonArgs = {};
                        const pairs = trimmedContent.split(/[,\n]/);
                        for (const pair of pairs) {
                            const trimmedPair = pair.trim();
                            if (trimmedPair.includes("=")) {
                                const [key, ...valueParts] = trimmedPair.split("=");
                                const value = valueParts.join("=").trim();
                                jsonArgs[key.trim()] = value.replace(/^["']|["']$/g, "");
                            }
                            else if (trimmedPair.includes(":")) {
                                const [key, ...valueParts] = trimmedPair.split(":");
                                const value = valueParts.join(":").trim();
                                jsonArgs[key.trim()] = value.replace(/^["']|["']$/g, "");
                            }
                        }
                        if (Object.keys(jsonArgs).length > 0) {
                            return JSON.stringify(jsonArgs);
                        }
                    }
                    catch {
                    }
                }
                return JSON.stringify({ input: trimmedContent });
            }
        }
        return "{}";
    }
    generateToolCallId() {
        return `call_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    }
    convertXmlToToolCalls(matches) {
        const toolCalls = [];
        for (const match of matches) {
            const [fullMatch, toolName, argsAttribute, innerContent] = match;
            if (!toolName)
                continue;
            const toolCall = {
                id: this.generateToolCallId(),
                type: "function",
                function: {
                    name: toolName,
                    arguments: this.parseToolCallArguments(argsAttribute, innerContent),
                },
            };
            toolCalls.push(toolCall);
        }
        return toolCalls;
    }
    detectIncompleteToolCalls(content) {
        const blocks = [];
        let startIndex = 0;
        while (true) {
            const toolCallStart = content.indexOf('<tool_call>', startIndex);
            if (toolCallStart === -1)
                break;
            const toolCallEnd = content.indexOf('</tool_call>', toolCallStart);
            if (toolCallEnd === -1) {
                const jsonStart = toolCallStart + '<tool_call>'.length;
                const remainingContent = content.substring(jsonStart).trim();
                try {
                    const parsed = JSON.parse(remainingContent);
                    if (parsed.name && parsed.arguments !== undefined) {
                        blocks.push({
                            name: parsed.name,
                            arguments: typeof parsed.arguments === 'string' ? parsed.arguments : JSON.stringify(parsed.arguments),
                        });
                    }
                }
                catch (error) {
                }
                startIndex = toolCallStart + '<tool_call>'.length;
                continue;
            }
            startIndex = toolCallEnd + '</tool_call>'.length;
        }
        return blocks;
    }
    extractToolCallBlocks(content) {
        const blocks = [];
        let startIndex = 0;
        while (true) {
            const toolCallStart = content.indexOf('<tool_call>', startIndex);
            if (toolCallStart === -1)
                break;
            const toolCallEnd = content.indexOf('</tool_call>', toolCallStart);
            if (toolCallEnd === -1)
                break;
            const jsonStart = toolCallStart + '<tool_call>'.length;
            const jsonContent = content.substring(jsonStart, toolCallEnd).trim();
            try {
                const parsed = JSON.parse(jsonContent);
                if (parsed.name && parsed.arguments !== undefined) {
                    blocks.push({
                        name: parsed.name,
                        arguments: typeof parsed.arguments === 'string' ? parsed.arguments : JSON.stringify(parsed.arguments),
                    });
                }
            }
            catch (error) {
                try {
                    let fixedContent = jsonContent;
                    fixedContent = fixedContent.replace(/"((?:[^"\\]|\\.)*)"/g, (match, content) => {
                        const escapedContent = content
                            .replace(/\\/g, '\\\\')
                            .replace(/\n/g, '\\n')
                            .replace(/\r/g, '\\r')
                            .replace(/\t/g, '\\t');
                        return `"${escapedContent}"`;
                    });
                    const parsed = JSON.parse(fixedContent);
                    if (parsed.name && parsed.arguments !== undefined) {
                        blocks.push({
                            name: parsed.name,
                            arguments: typeof parsed.arguments === 'string' ? parsed.arguments : JSON.stringify(parsed.arguments),
                        });
                    }
                }
                catch (secondError) {
                }
            }
            startIndex = toolCallEnd + '</tool_call>'.length;
        }
        return blocks;
    }
    processMessage(message) {
        if (message.role !== "assistant") {
            return;
        }
        if (typeof message.content !== "string") {
            return;
        }
        if (message?.tool_calls?.length) {
            return;
        }
        const matches = this.detectXmlToolCalls(message.content);
        let toolCalls = [];
        if (matches.length === 0) {
            const blocks = this.extractToolCallBlocks(message.content);
            let allBlocks = blocks;
            if (blocks.length === 0) {
                allBlocks = this.detectIncompleteToolCalls(message.content);
            }
            toolCalls = allBlocks.map(block => {
                return {
                    id: this.generateToolCallId(),
                    type: 'function',
                    function: {
                        name: block.name,
                        arguments: block.arguments,
                    },
                };
            });
        }
        else {
            toolCalls = this.convertXmlToToolCalls(matches);
        }
        if (toolCalls.length === 0) {
            return;
        }
        if (message.tool_calls) {
            message.tool_calls.push(...toolCalls);
        }
        else {
            message.tool_calls = toolCalls;
        }
    }
    createProcessor() {
        return (originalMessages, modifiedMessages) => {
            for (const message of modifiedMessages) {
                this.processMessage(message);
            }
        };
    }
}
exports.XmlToolCallProcessor = XmlToolCallProcessor;
exports.globalXmlToolCallProcessor = new XmlToolCallProcessor();
//# sourceMappingURL=XmlToolCallProcessor.js.map