import { TOOL_NAME_SEND_INPUT_TO_AGENT, TOOL_NAME_SPAWN_AGENT, TOOL_NAME_TERMINATE_AGENT, TOOL_NAME_WAIT_FOR_AGENT, } from "../core/tools/tool_names.js";
const BASH_TERMINAL_EVENT_TYPES = new Set([
    "bash_execution",
    "bash_aborted",
    "bash_blocked",
]);
const DIFF_REVIEW_TERMINAL_EVENT_TYPES = new Set([
    "diff_review_finished",
    "diff_review_blocked",
]);
const SUBAGENT_TERMINAL_EVENT_TYPES = new Set([
    "spawn_agent_finished",
    "spawn_agent_blocked",
    "send_input_to_agent_finished",
    "send_input_to_agent_blocked",
    "wait_for_agent_finished",
    "wait_for_agent_blocked",
    "terminate_agent_finished",
    "terminate_agent_blocked",
]);
const PRUNED_STATUS_PREFIX = "✂ pruned";
export class ToolUiRouter {
    chatContainer;
    requestRender;
    runningBashComponents = new Map();
    runningDiffReviewTools = new Map();
    runningSubagentTools = new Map();
    latestToolEventsById = new Map();
    constructor(options) {
        this.chatContainer = options.chatContainer;
        this.requestRender = options.requestRender;
    }
    resetSession() {
        this.runningBashComponents.clear();
        this.runningDiffReviewTools.clear();
        this.runningSubagentTools.clear();
        this.latestToolEventsById.clear();
    }
    clearTransientState() {
        this.runningBashComponents.clear();
        this.runningDiffReviewTools.clear();
        this.runningSubagentTools.clear();
    }
    finalizePending(reason) {
        for (const [id, running] of this.runningBashComponents.entries()) {
            const headerTarget = running.command.split(/\r?\n/)[0] ?? running.command;
            const event = {
                type: "bash_aborted",
                toolCallId: id,
                command: running.command,
                headerTarget,
                reason,
            };
            this.replaceToolMessage(event);
        }
        for (const [id, running] of this.runningDiffReviewTools.entries()) {
            const event = {
                type: "diff_review_finished",
                toolCallId: id,
                command: running.command,
                headerTarget: running.command,
                status: "cancelled",
                reviewedFiles: [],
                reviewAgents: [],
                message: reason === "aborted" ? "diff review aborted." : "diff review interrupted.",
            };
            this.replaceToolMessage(event);
        }
        for (const [id, running] of this.runningSubagentTools.entries()) {
            const event = this.toSubagentAbortEvent(id, running, reason);
            this.replaceToolMessage(event);
        }
        this.requestRender();
    }
    handle(uiEvent) {
        if (uiEvent.type === "tool_pruned") {
            const updated = this.applyPrunedMutation(uiEvent);
            if (updated) {
                this.requestRender();
            }
            return;
        }
        this.upsertToolMessage(uiEvent);
        this.updateRunningToolState(uiEvent);
        this.requestRender();
    }
    updateRunningToolState(uiEvent) {
        const bashComponent = this.toRunningBashComponent(uiEvent);
        if (bashComponent) {
            this.runningBashComponents.set(uiEvent.toolCallId, bashComponent);
            return;
        }
        if (this.isBashTerminalType(uiEvent.type)) {
            this.runningBashComponents.delete(uiEvent.toolCallId);
            return;
        }
        const diffReviewTool = this.toRunningDiffReviewTool(uiEvent);
        if (diffReviewTool) {
            this.runningDiffReviewTools.set(uiEvent.toolCallId, diffReviewTool);
            return;
        }
        if (this.isDiffReviewTerminalType(uiEvent.type)) {
            this.runningDiffReviewTools.delete(uiEvent.toolCallId);
            return;
        }
        const subagentTool = this.toRunningSubagentTool(uiEvent);
        if (subagentTool) {
            this.runningSubagentTools.set(uiEvent.toolCallId, subagentTool);
            return;
        }
        if (this.isSubagentTerminalType(uiEvent.type)) {
            this.runningSubagentTools.delete(uiEvent.toolCallId);
        }
    }
    toRunningBashComponent(uiEvent) {
        if (uiEvent.type !== "bash_started") {
            return null;
        }
        return { command: uiEvent.command };
    }
    toRunningDiffReviewTool(uiEvent) {
        if (uiEvent.type !== "diff_review_started" && uiEvent.type !== "diff_review_updated") {
            return null;
        }
        return { command: uiEvent.command };
    }
    toRunningSubagentTool(uiEvent) {
        if (uiEvent.type === "spawn_agent_started") {
            return {
                kind: TOOL_NAME_SPAWN_AGENT,
                name: uiEvent.name,
                title: uiEvent.headerTarget ?? uiEvent.title,
            };
        }
        if (uiEvent.type === "send_input_to_agent_started") {
            return {
                kind: TOOL_NAME_SEND_INPUT_TO_AGENT,
                agentId: uiEvent.agentId,
                name: uiEvent.name,
                title: uiEvent.headerTarget ?? uiEvent.title,
            };
        }
        if (uiEvent.type === "wait_for_agent_started") {
            return {
                kind: TOOL_NAME_WAIT_FOR_AGENT,
                agentIds: uiEvent.agentIds,
            };
        }
        if (uiEvent.type === "terminate_agent_started") {
            return {
                kind: TOOL_NAME_TERMINATE_AGENT,
                agentId: uiEvent.agentId,
            };
        }
        return null;
    }
    isBashTerminalType(type) {
        return BASH_TERMINAL_EVENT_TYPES.has(type);
    }
    isDiffReviewTerminalType(type) {
        return DIFF_REVIEW_TERMINAL_EVENT_TYPES.has(type);
    }
    isSubagentTerminalType(type) {
        return SUBAGENT_TERMINAL_EVENT_TYPES.has(type);
    }
    upsertToolMessage(uiEvent) {
        if (this.replaceToolMessage(uiEvent)) {
            return;
        }
        this.chatContainer.addMessage({ type: "tool", event: uiEvent }, uiEvent.toolCallId);
        this.latestToolEventsById.set(uiEvent.toolCallId, uiEvent);
    }
    replaceToolMessage(uiEvent) {
        const replaced = this.chatContainer.replaceMessage(uiEvent.toolCallId, {
            type: "tool",
            event: uiEvent,
        });
        if (!replaced) {
            this.latestToolEventsById.delete(uiEvent.toolCallId);
            return false;
        }
        this.latestToolEventsById.set(uiEvent.toolCallId, uiEvent);
        return true;
    }
    applyPrunedMutation(uiEvent) {
        const existing = this.latestToolEventsById.get(uiEvent.toolCallId);
        if (!existing) {
            return false;
        }
        if ("uiText" in existing && existing.uiText) {
            const statusLine = existing.uiText.statusLine?.trim();
            const nextStatusLine = statusLine
                ? `${PRUNED_STATUS_PREFIX} · ${statusLine}`
                : PRUNED_STATUS_PREFIX;
            const nextLines = this.toToolUiLines(uiEvent.content);
            const nextUiText = {
                previewLines: nextLines,
                statusLine: nextStatusLine,
                fullLines: nextLines,
            };
            const nextEvent = { ...existing, uiText: nextUiText };
            return this.replaceToolMessage(nextEvent);
        }
        if ("reason" in existing && typeof existing.reason === "string") {
            return this.replaceToolMessage({
                ...existing,
                reason: uiEvent.content,
            });
        }
        if ("message" in existing) {
            return this.replaceToolMessage({
                ...existing,
                message: uiEvent.content,
            });
        }
        return false;
    }
    toToolUiLines(content) {
        if (!content) {
            return [];
        }
        return content.split("\n").map((text) => ({ text }));
    }
    toSubagentAbortEvent(toolCallId, running, reason) {
        if (running.kind === TOOL_NAME_SPAWN_AGENT) {
            return {
                type: "spawn_agent_finished",
                toolCallId,
                name: running.name,
                title: running.title,
                headerTarget: running.title,
                status: "error",
                message: reason,
            };
        }
        if (running.kind === TOOL_NAME_SEND_INPUT_TO_AGENT) {
            return {
                type: "send_input_to_agent_finished",
                toolCallId,
                agentId: running.agentId,
                name: running.name,
                title: running.title,
                headerTarget: running.title,
                status: "error",
                message: reason,
            };
        }
        if (running.kind === TOOL_NAME_WAIT_FOR_AGENT) {
            const headerTarget = running.agentIds.length > 0 ? running.agentIds.join(", ") : "(no ids)";
            return {
                type: "wait_for_agent_finished",
                toolCallId,
                agentIds: running.agentIds,
                headerTarget,
                status: "error",
                message: reason,
            };
        }
        return {
            type: "terminate_agent_finished",
            toolCallId,
            agentId: running.agentId,
            headerTarget: running.agentId,
            status: "error",
            message: reason,
        };
    }
}
//# sourceMappingURL=tool_ui_router.js.map