/**
 * Parser for Pi Coding Agent (`@earendil-works/pi-coding-agent`) transcript JSONL.
 *
 * Each line has a top-level `type` describing the record kind:
 *   - "session"                  — session header (skipped)
 *   - "model_change"             — model swap event (skipped)
 *   - "thinking_level_change"    — thinking config event (skipped)
 *   - "message"                  — the actual conversation turn (parsed)
 *
 * Message lines wrap an `@earendil-works/pi-ai` `Message`:
 *   { role: "user",       content: string | (TextContent | ImageContent)[] }
 *   { role: "assistant",  content: (TextContent | ThinkingContent | ToolCall)[] }
 *   { role: "toolResult", toolName, toolCallId, content: (TextContent | ImageContent)[], isError }
 *
 * ToolCall blocks look like:
 *   { type: "toolCall", id, name, arguments: {...} }
 *
 * This parser converts those records into the same `[User] / [Assistant] /
 * [Tool Call] / [Tool Error]` lines as the Claude parser so downstream
 * summary generation is engine-agnostic.
 */
import { isTrivialToolName } from "./trivial-tools.js";
import { sanitizeForSummary } from "./sanitize.js";
function extractTextFromContentArray(content) {
    const parts = [];
    for (const block of content) {
        if (typeof block !== "object" || block === null)
            continue;
        const b = block;
        if (b.type === "text" && typeof b.text === "string") {
            parts.push(b.text);
        }
        else if (b.type === "image") {
            parts.push("[Image omitted]");
        }
    }
    return parts.join("\n");
}
function parseLines(lines) {
    const entries = [];
    for (const line of lines) {
        if (!line.trim())
            continue;
        try {
            const parsed = JSON.parse(line);
            if (parsed.type !== "message")
                continue;
            const message = parsed.message;
            if (typeof message !== "object" || message === null)
                continue;
            const msg = message;
            const role = msg.role;
            if (role === "user") {
                const content = msg.content;
                if (typeof content === "string") {
                    entries.push({ type: "user_message", text: content });
                }
                else if (Array.isArray(content)) {
                    const text = extractTextFromContentArray(content);
                    if (text)
                        entries.push({ type: "user_message", text });
                }
            }
            else if (role === "assistant") {
                const content = msg.content;
                if (!Array.isArray(content))
                    continue;
                for (const block of content) {
                    if (typeof block !== "object" || block === null)
                        continue;
                    const b = block;
                    if (b.type === "text" && typeof b.text === "string") {
                        entries.push({ type: "assistant_text", text: b.text });
                    }
                    else if (b.type === "toolCall") {
                        const sanitizedInput = sanitizeForSummary(b.arguments);
                        const inputStr = sanitizedInput ? JSON.stringify(sanitizedInput) : "";
                        const truncated = inputStr.length > 500
                            ? inputStr.slice(0, 500) + "...[truncated]"
                            : inputStr;
                        entries.push({
                            type: "tool_call",
                            toolName: typeof b.name === "string" ? b.name : "unknown",
                            toolInput: truncated,
                        });
                    }
                    // thinking blocks are intentionally dropped from the summary
                }
            }
            else if (role === "toolResult") {
                const isError = msg.isError === true;
                // Mirror the Claude parser: only error results are interesting for
                // summarization; successful results are too large/noisy.
                if (!isError)
                    continue;
                const content = msg.content;
                const raw = Array.isArray(content)
                    ? extractTextFromContentArray(content)
                    : typeof content === "string"
                        ? content
                        : JSON.stringify(sanitizeForSummary(content));
                const truncated = raw.length > 300
                    ? raw.slice(0, 300) + "...[truncated]"
                    : raw;
                entries.push({
                    type: "tool_result",
                    toolName: typeof msg.toolName === "string" ? msg.toolName : "unknown",
                    text: truncated,
                    isError: true,
                });
            }
        }
        catch {
            // Skip malformed lines
        }
    }
    return entries;
}
function renderEntries(entries) {
    const parts = [];
    for (const entry of entries) {
        switch (entry.type) {
            case "user_message":
                parts.push(`[User] ${entry.text ?? ""}`);
                break;
            case "assistant_text":
                parts.push(`[Assistant] ${entry.text ?? ""}`);
                break;
            case "tool_call":
                parts.push(`[Tool Call] ${entry.toolName ?? "unknown"}(${entry.toolInput ?? ""})`);
                break;
            case "tool_result":
                if (entry.isError) {
                    parts.push(`[Tool Error] ${entry.toolName ?? "unknown"}: ${entry.text ?? ""}`);
                }
                break;
        }
    }
    return parts.join("\n");
}
const MAX_TOOL_CALLS_PER_CYCLE = 500;
const TOOLS_WITH_ACTION_ARG = new Set([
    "manage_email", "manage_calendar", "manage_drive",
    "manage_totp", "manage_skills", "manage_mcp_servers",
    "memory", "stock_data",
]);
export const piCodingTranscriptParser = {
    kind: "pi-coding-agent",
    parseForSummary(lines) {
        return renderEntries(parseLines(lines));
    },
    isOnlyTrivialToolCalls(lines) {
        let hasToolCalls = false;
        for (const line of lines) {
            if (!line.trim())
                continue;
            try {
                const parsed = JSON.parse(line);
                if (parsed.type !== "message")
                    continue;
                const message = parsed.message;
                if (typeof message !== "object" || message === null)
                    continue;
                const msg = message;
                if (msg.role !== "assistant")
                    continue;
                const content = msg.content;
                if (!Array.isArray(content))
                    continue;
                for (const block of content) {
                    if (typeof block !== "object" || block === null)
                        continue;
                    const b = block;
                    if (b.type !== "toolCall")
                        continue;
                    hasToolCalls = true;
                    const name = typeof b.name === "string" ? b.name : undefined;
                    if (!name || !isTrivialToolName(name)) {
                        return false;
                    }
                }
            }
            catch {
                // Skip malformed lines
            }
        }
        return hasToolCalls;
    },
    extractToolCalls(lines, context) {
        const inFlight = new Map();
        const completed = [];
        let currentTimestamp = context.cycleStartedAt;
        for (const line of lines) {
            if (!line.trim())
                continue;
            try {
                const parsed = JSON.parse(line);
                if (parsed.type !== "message")
                    continue;
                if (typeof parsed.timestamp === "string") {
                    currentTimestamp = parsed.timestamp;
                }
                const message = parsed.message;
                if (typeof message !== "object" || message === null)
                    continue;
                const msg = message;
                if (msg.role === "assistant") {
                    const content = msg.content;
                    if (!Array.isArray(content))
                        continue;
                    for (const block of content) {
                        if (typeof block !== "object" || block === null)
                            continue;
                        const b = block;
                        if (b.type === "toolCall") {
                            const toolUseId = typeof b.id === "string" ? b.id : undefined;
                            const toolName = typeof b.name === "string" ? b.name : undefined;
                            if (toolUseId && toolName) {
                                let action;
                                const strippedName = toolName.replace(/^mcp__visionclaw__/, "").replace(/^mcp__playwright__/, "");
                                if (TOOLS_WITH_ACTION_ARG.has(strippedName)) {
                                    const args = b.arguments;
                                    const rawAction = args?.action ?? args?.command;
                                    if (typeof rawAction === "string")
                                        action = rawAction;
                                }
                                inFlight.set(toolUseId, { toolUseId, toolName, startedAt: currentTimestamp, action });
                            }
                        }
                    }
                }
                else if (msg.role === "toolResult") {
                    const toolCallId = msg.toolCallId;
                    if (!toolCallId)
                        continue;
                    const pending = inFlight.get(toolCallId);
                    if (!pending)
                        continue;
                    inFlight.delete(toolCallId);
                    const isError = msg.isError === true;
                    completed.push({
                        toolName: pending.toolName,
                        toolUseId: pending.toolUseId,
                        startedAt: pending.startedAt,
                        endedAt: currentTimestamp,
                        success: !isError,
                        ...(isError ? { errorKind: "tool_error" } : {}),
                        ...(pending.action ? { action: pending.action } : {}),
                    });
                }
            }
            catch {
                // Skip malformed lines
            }
        }
        for (const pending of inFlight.values()) {
            completed.push({
                toolName: pending.toolName,
                toolUseId: pending.toolUseId,
                startedAt: pending.startedAt,
                endedAt: context.cycleEndedAt,
                success: false,
                errorKind: "missing_tool_result",
                ...(pending.action ? { action: pending.action } : {}),
            });
        }
        completed.sort((a, b) => a.startedAt.localeCompare(b.startedAt));
        const originalCount = completed.length;
        const truncated = originalCount > MAX_TOOL_CALLS_PER_CYCLE;
        const toolCalls = truncated ? completed.slice(0, MAX_TOOL_CALLS_PER_CYCLE) : completed;
        return {
            toolCalls,
            toolCallCount: originalCount,
            truncated,
            reportedToolCallCount: truncated ? toolCalls.length : null,
        };
    },
};
//# sourceMappingURL=pi-coding-parser.js.map