function isRecord(value) {
    return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
}
const ORPHAN_TAG_RE = /^\s*(?:[•*+-]\s*)?(?:<\/?\s*function_calls\s*\/?\s*>|<\/\s*(?:parameter|function|tool_call)\s*>)\s*$/i;
function stripOrphanTagLines(text) {
    const raw = String(text ?? '');
    if (!raw)
        return { text: raw, changed: false };
    const lines = raw.split(/\r?\n/);
    const kept = [];
    let changed = false;
    for (const line of lines) {
        if (ORPHAN_TAG_RE.test(line)) {
            changed = true;
            continue;
        }
        kept.push(line);
    }
    return { text: kept.join('\n'), changed };
}
function stripInMessageInPlace(message) {
    let changed = false;
    const content = message.content;
    if (typeof content === 'string') {
        const res = stripOrphanTagLines(content);
        if (res.changed) {
            message.content = res.text;
            changed = true;
        }
    }
    else if (Array.isArray(content)) {
        const next = content.map((part) => {
            if (typeof part === 'string') {
                const res = stripOrphanTagLines(part);
                if (res.changed)
                    changed = true;
                return res.text;
            }
            if (!isRecord(part))
                return part;
            const p = { ...part };
            if (typeof p.text === 'string') {
                const res = stripOrphanTagLines(p.text);
                if (res.changed) {
                    p.text = res.text;
                    changed = true;
                }
            }
            if (typeof p.content === 'string') {
                const res = stripOrphanTagLines(p.content);
                if (res.changed) {
                    p.content = res.text;
                    changed = true;
                }
            }
            return p;
        });
        if (changed) {
            message.content = next;
        }
    }
    for (const key of ['reasoning', 'thinking', 'reasoning_content']) {
        const raw = message[key];
        if (typeof raw === 'string' && raw.trim().length) {
            const res = stripOrphanTagLines(raw);
            if (res.changed) {
                message[key] = res.text;
                changed = true;
            }
        }
    }
    return changed;
}
function stripInChatPayloadInPlace(root) {
    const choices = Array.isArray(root.choices) ? root.choices : [];
    if (!choices.length)
        return false;
    let changed = false;
    for (const choice of choices) {
        if (!isRecord(choice))
            continue;
        const message = choice.message;
        if (!isRecord(message))
            continue;
        const role = typeof message.role === 'string' ? String(message.role).trim().toLowerCase() : 'assistant';
        if (role !== 'assistant')
            continue;
        if (stripInMessageInPlace(message)) {
            changed = true;
            choice.message = message;
        }
    }
    return changed;
}
function stripInResponsesPayloadInPlace(root) {
    const output = Array.isArray(root.output) ? root.output : [];
    if (!output.length)
        return false;
    let changed = false;
    for (const item of output) {
        if (!isRecord(item))
            continue;
        const type = typeof item.type === 'string' ? String(item.type).trim().toLowerCase() : '';
        if (type !== 'message')
            continue;
        const role = typeof item.role === 'string' ? String(item.role).trim().toLowerCase() : 'assistant';
        if (role !== 'assistant')
            continue;
        const content = Array.isArray(item.content) ? item.content : [];
        if (content.length) {
            const next = content.map((part) => {
                if (!isRecord(part))
                    return part;
                const p = { ...part };
                for (const key of ['text', 'content', 'value']) {
                    if (typeof p[key] === 'string' && String(p[key]).trim().length) {
                        const res = stripOrphanTagLines(String(p[key]));
                        if (res.changed) {
                            p[key] = res.text;
                            changed = true;
                        }
                    }
                }
                return p;
            });
            if (changed) {
                item.content = next;
            }
        }
        if (typeof item.output_text === 'string' && String(item.output_text).trim().length) {
            const res = stripOrphanTagLines(String(item.output_text));
            if (res.changed) {
                item.output_text = res.text;
                changed = true;
            }
        }
    }
    return changed;
}
export function stripOrphanFunctionCallsTag(payload) {
    try {
        if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
            return payload;
        }
        const root = structuredClone(payload);
        const changed = stripInChatPayloadInPlace(root) || stripInResponsesPayloadInPlace(root);
        return (changed ? root : payload);
    }
    catch {
        return payload;
    }
}
