import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useState, useMemo, memo, useEffect, useRef } from "react";
import { JsonView, defaultStyles } from "react-json-view-lite";
import "react-json-view-lite/dist/index.css";
import { Spinner } from "../ui/Spinner";
import { Button } from "../../components/ui/button";
import { CopyButton } from "../../components/ui/copy-button";
import { Tooltip, TooltipTrigger, TooltipContent, } from "../../components/ui/tooltip";
import { approveToolCall, approveToolCalls, createOperationAllowance, rejectToolCall, updateAgentSettings, } from "../services/agentService";
import { formatTime } from "../utils";
// Custom dark theme styles for JSON view
const darkJsonStyles = {
    ...defaultStyles,
    container: "dark-json-container",
    label: "dark-json-label",
    punctuation: "dark-json-punctuation",
    stringValue: "dark-json-string",
    numberValue: "dark-json-number",
    booleanValue: "dark-json-boolean",
    nullValue: "dark-json-null",
    undefinedValue: "dark-json-undefined",
};
// JSON view light theme CSS
const JsonLightThemeStyles = () => (_jsx("style", { children: `
    .dark-json-container { color: #1f2937; }
    .dark-json-label { color: #2563eb; font-weight: 500; }
    .dark-json-punctuation { color: #6b7280; }
    .dark-json-string { color: #059669; }
    .dark-json-number { color: #d97706; }
    .dark-json-boolean { color: #7c3aed; }
    .dark-json-null { color: #dc2626; }
    .dark-json-undefined { color: #dc2626; }
  ` }));
import { FileText, Search, Code, FolderOpen, FileSearch, Trash2, Globe, Brain, CheckSquare, Edit, FileEdit, Wrench, ChevronDown, ChevronRight, Check, X, ShieldCheck, } from "lucide-react";
// Function to get the appropriate icon for each tool
const getToolIcon = (toolName) => {
    const iconMap = {
        // Content operations
        "get-page-content": _jsx(FileText, { strokeWidth: 1, size: 14 }),
        "edit-field": _jsx(Edit, { strokeWidth: 1, size: 14 }),
        "suggest-field-edit": _jsx(Edit, { strokeWidth: 1, size: 14 }),
        // Item operations
        "create-item": _jsx(FileEdit, { strokeWidth: 1, size: 14 }),
        "rename-item": _jsx(Edit, { strokeWidth: 1, size: 14 }),
        "load-item": _jsx(FileText, { strokeWidth: 1, size: 14 }),
        "get-items": _jsx(FolderOpen, { strokeWidth: 1, size: 14 }),
        "get-children": _jsx(FolderOpen, { strokeWidth: 1, size: 14 }),
        "get-insertoptions": _jsx(FolderOpen, { strokeWidth: 1, size: 14 }),
        // Component operations
        "add-component": _jsx(Code, { strokeWidth: 1, size: 14 }),
        "remove-component": _jsx(Trash2, { strokeWidth: 1, size: 14 }),
        "move-components": _jsx(Edit, { strokeWidth: 1, size: 14 }),
        "get-placeholders": _jsx(Code, { strokeWidth: 1, size: 14 }),
        "get-component-schema-with-placeholders": _jsx(Code, { strokeWidth: 1, size: 14 }),
        // Search operations
        "search-content": _jsx(Search, { strokeWidth: 1, size: 14 }),
        "search-images": _jsx(FileSearch, { strokeWidth: 1, size: 14 }),
        "google-search": _jsx(Globe, { strokeWidth: 1, size: 14 }),
        // Image operations
        "edit-image": _jsx(FileEdit, { strokeWidth: 1, size: 14 }),
        "get-image-description": _jsx(FileText, { strokeWidth: 1, size: 14 }),
        // Comments and suggestions
        "add-comment": _jsx(CheckSquare, { strokeWidth: 1, size: 14 }),
        "get-comments": _jsx(CheckSquare, { strokeWidth: 1, size: 14 }),
        "get-reviews": _jsx(CheckSquare, { strokeWidth: 1, size: 14 }),
        "invite-reviewer": _jsx(CheckSquare, { strokeWidth: 1, size: 14 }),
        "get-suggestions": _jsx(Brain, { strokeWidth: 1, size: 14 }),
        // Default fallback
        default: _jsx(Wrench, { strokeWidth: 1, size: 14 }),
    };
    return iconMap[toolName] || iconMap.default;
};
const formatToolDuration = (durationMs) => {
    if (typeof durationMs !== "number" ||
        !Number.isFinite(durationMs) ||
        durationMs < 0) {
        return null;
    }
    if (durationMs < 1000) {
        return `${Math.round(durationMs)}ms`;
    }
    if (durationMs < 10_000) {
        return `${(durationMs / 1000).toFixed(1)}s`;
    }
    if (durationMs < 60_000) {
        return `${Math.round(durationMs / 1000)}s`;
    }
    const totalSeconds = Math.round(durationMs / 1000);
    const minutes = Math.floor(totalSeconds / 60);
    const seconds = totalSeconds % 60;
    if (minutes < 60) {
        return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
    }
    const hours = Math.floor(minutes / 60);
    const remainingMinutes = minutes % 60;
    return remainingMinutes > 0 ? `${hours}h ${remainingMinutes}m` : `${hours}h`;
};
const formatToolCallMeta = (createdDate, durationMs) => {
    const parts = [];
    if (createdDate) {
        const parsed = new Date(createdDate);
        if (!Number.isNaN(parsed.getTime())) {
            parts.push(formatTime(parsed));
        }
    }
    const duration = formatToolDuration(durationMs);
    if (duration) {
        parts.push(duration);
    }
    return parts.length > 0 ? parts.join(" • ") : null;
};
// Helper function to normalize tool calls to a common format
const normalizeToolCall = (toolCall) => {
    if ("functionName" in toolCall) {
        // Agent tool call format
        return {
            id: toolCall.toolCallId,
            displayName: toolCall.functionName,
            function: {
                name: toolCall.functionName,
                arguments: toolCall.functionArguments,
                result: toolCall.functionResultRichContent || toolCall.functionResult,
                error: toolCall.functionError,
            },
            requiresApproval: toolCall.requiresApproval,
            isPruned: toolCall.isPruned,
            prunedAt: toolCall.prunedAt,
            responseTimeMs: toolCall.responseTimeMs,
            createdDate: toolCall.createdDate,
        };
    }
    // Already in base format
    return toolCall;
};
// Memoized JSON viewer component to prevent re-renders during streaming
const MemoizedJsonView = memo(({ data }) => {
    return (_jsxs("div", { className: "font-mono text-xs", style: { fontSize: "12px" }, children: [_jsx(JsonLightThemeStyles, {}), _jsx(JsonView, { data: data, shouldExpandNode: (level) => level < 2, style: darkJsonStyles })] }));
}, (prevProps, nextProps) => {
    // Only re-render if the data actually changed (deep comparison by stringifying)
    return JSON.stringify(prevProps.data) === JSON.stringify(nextProps.data);
});
MemoizedJsonView.displayName = "MemoizedJsonView";
// Helper function to parse JSON string to object
const parseJsonString = (json) => {
    // If it's already an object, return it directly
    if (typeof json === "object" && json !== null) {
        return json;
    }
    // Convert to string if not already
    const jsonString = typeof json === "string" ? json : String(json);
    // Try to parse as JSON
    try {
        let parsed = JSON.parse(jsonString);
        // If the result is still a string that looks like JSON, parse it again
        if (typeof parsed === "string" &&
            (parsed.startsWith("{") || parsed.startsWith("["))) {
            try {
                parsed = JSON.parse(parsed);
            }
            catch (e2) {
                console.log("Second parse failed, using first result");
            }
        }
        return parsed;
    }
    catch (e) {
        console.log("JSON parse failed:", e, "Trying to handle as string...");
        // Try to handle double-escaped JSON
        try {
            const unescaped = jsonString.replace(/\\"/g, '"').replace(/\\\\/g, "\\");
            const parsed = JSON.parse(unescaped);
            return parsed;
        }
        catch (e2) {
            console.log("Unescaping also failed:", e2);
            // If all parsing fails, return null to indicate we should display as plain text
            return null;
        }
    }
};
const isImageDataUrl = (value) => {
    return typeof value === "string" && /^data:image\//i.test(value.trim());
};
const getInlineImageSource = (value) => {
    if (isImageDataUrl(value)) {
        return value.trim();
    }
    if (!value || typeof value !== "object") {
        return null;
    }
    const candidate = value;
    if (isImageDataUrl(candidate.dataUrl)) {
        return candidate.dataUrl.trim();
    }
    if (isImageDataUrl(candidate.url)) {
        return candidate.url.trim();
    }
    if (isImageDataUrl(candidate.src)) {
        return candidate.src.trim();
    }
    const imageUrlCandidate = candidate.imageUrl ?? candidate.image_url;
    if (imageUrlCandidate && typeof imageUrlCandidate === "object") {
        const imageUrlRecord = imageUrlCandidate;
        if (isImageDataUrl(imageUrlRecord.url)) {
            return imageUrlRecord.url.trim();
        }
    }
    return null;
};
const extractInlineToolResultImage = (value) => {
    const directSource = getInlineImageSource(value);
    if (directSource) {
        return {
            src: directSource,
            alt: "Tool result image",
        };
    }
    if (Array.isArray(value)) {
        for (const entry of value) {
            const preview = extractInlineToolResultImage(entry);
            if (preview) {
                return preview;
            }
        }
        return null;
    }
    if (!value || typeof value !== "object") {
        return null;
    }
    const candidate = value;
    const nestedImage = candidate.image && typeof candidate.image === "object"
        ? candidate.image
        : undefined;
    const richImageSource = getInlineImageSource(candidate.imageUrl ??
        candidate.image_url);
    const src = isImageDataUrl(nestedImage?.dataUrl)
        ? nestedImage?.dataUrl.trim()
        : isImageDataUrl(candidate.dataUrl)
            ? candidate.dataUrl.trim()
            : richImageSource
                ? richImageSource
                : null;
    if (!src) {
        return null;
    }
    const width = typeof candidate.imageWidth === "number" &&
        Number.isFinite(candidate.imageWidth)
        ? candidate.imageWidth
        : typeof nestedImage?.width === "number" &&
            Number.isFinite(nestedImage.width)
            ? nestedImage.width
            : undefined;
    const height = typeof candidate.imageHeight === "number" &&
        Number.isFinite(candidate.imageHeight)
        ? candidate.imageHeight
        : typeof nestedImage?.height === "number" &&
            Number.isFinite(nestedImage.height)
            ? nestedImage.height
            : undefined;
    return {
        src,
        alt: candidate.scope
            ? `Screenshot result (${candidate.scope})`
            : "Tool result image",
        fileName: nestedImage?.fileName || candidate.fileName,
        dimensions: width && height
            ? `${Math.round(width)} x ${Math.round(height)}`
            : undefined,
    };
};
const sanitizeInlineImageDataForDisplay = (value) => {
    if (isImageDataUrl(value)) {
        return "[image data URL omitted from preview]";
    }
    if (Array.isArray(value)) {
        let hasChanges = false;
        const sanitizedItems = value.map((entry) => {
            const sanitizedEntry = sanitizeInlineImageDataForDisplay(entry);
            if (sanitizedEntry !== entry) {
                hasChanges = true;
            }
            return sanitizedEntry;
        });
        return hasChanges ? sanitizedItems : value;
    }
    if (!value || typeof value !== "object") {
        return value;
    }
    const candidate = value;
    let hasChanges = false;
    const clone = {};
    Object.entries(candidate).forEach(([key, entryValue]) => {
        const sanitizedValue = sanitizeInlineImageDataForDisplay(entryValue);
        clone[key] = sanitizedValue;
        if (sanitizedValue !== entryValue) {
            hasChanges = true;
        }
    });
    return hasChanges ? clone : value;
};
const InlineToolResultPreview = ({ preview, }) => {
    return (_jsxs("a", { href: preview.src, target: "_blank", rel: "noopener noreferrer", className: "mb-2 block overflow-hidden rounded border border-gray-200 bg-white transition-colors hover:border-gray-300", children: [_jsx("img", { src: preview.src, alt: preview.alt, loading: "lazy", className: "max-h-40 w-auto max-w-full bg-gray-100 object-contain" }), (preview.fileName || preview.dimensions) && (_jsxs("div", { className: "flex items-center justify-between gap-3 border-t border-gray-100 px-2 py-1 text-[10px] text-gray-500", children: [_jsx("span", { className: "truncate", children: preview.fileName || "Screenshot" }), preview.dimensions && (_jsx("span", { className: "shrink-0", children: preview.dimensions }))] }))] }));
};
// Helper function to render JSON or text
const renderJsonOrText = (json) => {
    const parsed = parseJsonString(json);
    if (parsed !== null) {
        return _jsx(MemoizedJsonView, { data: parsed });
    }
    // If parsing failed, display as plain text
    const jsonString = typeof json === "string" ? json : String(json);
    return (_jsx("div", { className: "font-mono text-xs wrap-break-word whitespace-pre-wrap text-gray-700", children: jsonString }));
};
// Expandable panel component
const ExpandablePanel = ({ title, children, defaultExpanded = false, actionButton, }) => {
    const [isExpanded, setIsExpanded] = useState(defaultExpanded);
    return (_jsxs("div", { className: "border-b border-gray-100 last:border-b-0", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex flex-1 cursor-pointer items-center gap-1.5 px-3 py-1.5 transition-colors hover:bg-gray-50/50", onClick: () => setIsExpanded(!isExpanded), children: [isExpanded ? (_jsx(ChevronDown, { size: 12, strokeWidth: 1.5, className: "text-gray-400 transition-transform" })) : (_jsx(ChevronRight, { size: 12, strokeWidth: 1.5, className: "text-gray-400 transition-transform" })), _jsx("span", { className: "text-[10px] font-medium text-gray-500", children: title })] }), actionButton && (_jsx("div", { className: "pr-2", onClick: (e) => e.stopPropagation(), children: actionButton }))] }), isExpanded && (_jsx("div", { className: "w-full overflow-auto px-3 pb-2", children: children }))] }));
};
// Helper function to create expandable tool call details
const ToolCallDetails = memo(({ toolCall, result, }) => {
    const isPruned = !!toolCall.isPruned;
    const hasError = !!toolCall.function?.error && !isPruned;
    const hasOutput = !!result || hasError || isPruned;
    const prunedOutput = useMemo(() => {
        if (!isPruned)
            return "";
        return result || toolCall.function?.error || "";
    }, [isPruned, result, toolCall.function?.error]);
    // Memoize parsed input data to prevent re-parsing on every render
    const parsedInput = useMemo(() => {
        return parseJsonString(toolCall.function?.arguments || "");
    }, [toolCall.function?.arguments]);
    // Memoize parsed output data to prevent re-parsing on every render
    const parsedOutput = useMemo(() => {
        return parseJsonString(result || "");
    }, [result]);
    const parsedPrunedOutput = useMemo(() => {
        return parseJsonString(prunedOutput);
    }, [prunedOutput]);
    const outputPreview = useMemo(() => {
        if (isPruned) {
            return extractInlineToolResultImage(parsedPrunedOutput ?? prunedOutput);
        }
        if (hasError) {
            return null;
        }
        return extractInlineToolResultImage(parsedOutput ?? (result || ""));
    }, [
        hasError,
        isPruned,
        parsedOutput,
        parsedPrunedOutput,
        prunedOutput,
        result,
    ]);
    const displayPrunedOutput = useMemo(() => {
        return sanitizeInlineImageDataForDisplay(parsedPrunedOutput ?? prunedOutput);
    }, [parsedPrunedOutput, prunedOutput]);
    const displayOutput = useMemo(() => {
        return sanitizeInlineImageDataForDisplay(parsedOutput ?? (result || ""));
    }, [parsedOutput, result]);
    // Get text to copy for input
    const inputTextToCopy = useMemo(() => {
        const args = toolCall.function?.arguments || "";
        if (parsedInput !== null) {
            return JSON.stringify(parsedInput, null, 2);
        }
        return args;
    }, [toolCall.function?.arguments, parsedInput]);
    // Get text to copy for output
    const outputTextToCopy = useMemo(() => {
        if (isPruned) {
            if (parsedPrunedOutput !== null) {
                return JSON.stringify(parsedPrunedOutput, null, 2);
            }
            return typeof prunedOutput === "object"
                ? JSON.stringify(prunedOutput, null, 2)
                : prunedOutput;
        }
        if (hasError) {
            return toolCall.function?.error || "";
        }
        if (parsedOutput !== null) {
            return JSON.stringify(parsedOutput, null, 2);
        }
        if (typeof result === "object") {
            return JSON.stringify(result, null, 2);
        }
        return result || "";
    }, [
        hasError,
        isPruned,
        toolCall.function?.error,
        parsedOutput,
        parsedPrunedOutput,
        prunedOutput,
        result,
    ]);
    return (_jsxs("div", { className: "mt-1 ml-5 overflow-hidden rounded border border-gray-200/60 bg-gray-50/40", children: [_jsx(ExpandablePanel, { title: "Input", defaultExpanded: !hasOutput, actionButton: _jsx(CopyButton, { textToCopy: inputTextToCopy, iconOnly: true, className: "cursor-pointer text-gray-400 hover:text-gray-600" }), children: _jsx("div", { className: "rounded bg-white p-2 text-xs", children: parsedInput !== null ? (_jsx(MemoizedJsonView, { data: parsedInput })) : (_jsx("div", { className: "font-mono text-xs wrap-break-word whitespace-pre-wrap text-gray-700", children: toolCall.function?.arguments || "" })) }) }), hasOutput && (_jsx(ExpandablePanel, { title: isPruned ? "Pruned" : hasError ? "Error" : "Output", defaultExpanded: true, actionButton: _jsx(CopyButton, { textToCopy: outputTextToCopy, iconOnly: true, className: "cursor-pointer text-gray-400 hover:text-gray-600" }), children: isPruned ? (_jsxs("div", { className: "rounded border-l-2 border-slate-400 bg-slate-50/70 p-2 text-xs text-slate-700", children: [_jsx("div", { className: "mb-1 text-[10px] font-medium text-slate-600", children: "Pruned from AI context" }), _jsx("div", { className: "mb-2 text-slate-600", children: "This tool call completed, but its output was pruned from future agent context to save tokens." }), prunedOutput ? (_jsxs("div", { className: "rounded bg-white p-2 text-xs", children: [outputPreview && (_jsx(InlineToolResultPreview, { preview: outputPreview })), displayPrunedOutput !== null &&
                                    typeof displayPrunedOutput === "object" ? (_jsx(MemoizedJsonView, { data: displayPrunedOutput })) : (_jsx("div", { className: "font-mono text-xs wrap-break-word whitespace-pre-wrap text-gray-700", children: String(displayPrunedOutput ?? prunedOutput) }))] })) : null] })) : hasError ? (_jsxs("div", { className: "rounded border-l-2 border-red-400 bg-red-50/60 p-2 text-xs text-red-700", children: [_jsx("div", { className: "mb-1 text-[10px] font-medium text-red-600", children: "Error" }), _jsx("div", { className: "text-red-600", children: toolCall.function?.error })] })) : (_jsxs("div", { className: "rounded bg-white p-2 text-xs", children: [outputPreview && (_jsx(InlineToolResultPreview, { preview: outputPreview })), displayOutput !== null && typeof displayOutput === "object" ? (_jsx(MemoizedJsonView, { data: displayOutput })) : (_jsx("div", { className: "font-mono text-xs wrap-break-word whitespace-pre-wrap text-gray-700", children: String(displayOutput ?? (result || "")) }))] })) }))] }));
}, (prevProps, nextProps) => {
    // Only re-render if the data actually changed
    return (prevProps.toolCall.id === nextProps.toolCall.id &&
        prevProps.toolCall.function?.arguments ===
            nextProps.toolCall.function?.arguments &&
        prevProps.result === nextProps.result &&
        prevProps.toolCall.function?.error ===
            nextProps.toolCall.function?.error &&
        prevProps.toolCall.isPruned === nextProps.toolCall.isPruned);
});
ToolCallDetails.displayName = "ToolCallDetails";
export function ToolCallDisplay({ toolCalls, finished, openPopovers, setOpenPopovers, messageId, agentId, allPendingApprovals = [], onSwitchToAutonomous, seenApprovalDialogs, onApprovalDialogShown, browserCaptureInlinePrompt, }) {
    const [batchRiskAction, setBatchRiskAction] = useState(null);
    const [isSwitchingMode, setIsSwitchingMode] = useState(false);
    const [isGroupExpanded, setIsGroupExpanded] = useState(() => {
        return (toolCalls?.some((tc) => {
            if (!tc.requiresApproval)
                return false;
            const funcName = ("functionName" in tc
                ? tc.functionName
                : normalizeToolCall(tc).function?.name) || "";
            return (!funcName.includes("(approved)") && !funcName.includes("(rejected)"));
        }) ?? false);
    });
    const [userToggled, setUserToggled] = useState(false);
    const hasPendingApprovalsInGroup = useMemo(() => {
        if (!toolCalls)
            return false;
        return toolCalls.some((tc) => {
            if (!tc.requiresApproval)
                return false;
            const funcName = ("functionName" in tc
                ? tc.functionName
                : normalizeToolCall(tc).function?.name) || "";
            return (!funcName.includes("(approved)") && !funcName.includes("(rejected)"));
        });
    }, [toolCalls]);
    useEffect(() => {
        if (!userToggled) {
            setIsGroupExpanded(hasPendingApprovalsInGroup);
        }
    }, [userToggled, hasPendingApprovalsInGroup]);
    const groupSummary = useMemo(() => {
        if (!toolCalls || toolCalls.length === 0)
            return null;
        const uniqueNames = [
            ...new Set(toolCalls
                .map((tc) => {
                const normalized = normalizeToolCall(tc);
                return (("functionName" in tc
                    ? tc.functionName
                    : normalized.function?.name) || "")
                    .replace(/ \(approved\)/g, "")
                    .replace(/ \(rejected\)/g, "")
                    .replace(/ \(pending approval\)/g, "")
                    .trim();
            })
                .filter(Boolean)),
        ];
        const errorCount = toolCalls.filter((tc) => {
            const normalized = normalizeToolCall(tc);
            return !!normalized.function?.error && !normalized.isPruned;
        }).length;
        return { uniqueNames, errorCount };
    }, [toolCalls]);
    const shouldShowGroupBrowserCaptureInlinePrompt = useMemo(() => {
        if (!browserCaptureInlinePrompt || !toolCalls?.length)
            return false;
        return toolCalls.some((tc) => {
            const normalized = normalizeToolCall(tc);
            const originalFunctionName = ("functionName" in tc ? tc.functionName : normalized.function?.name) || "";
            const baseFunctionName = originalFunctionName
                .replace(" (approved)", "")
                .replace(" (rejected)", "")
                .replace(" (pending approval)", "")
                .trim()
                .toLowerCase();
            const approvalInfo = tc.requiresApproval || normalized.requiresApproval;
            const isCompleted = "isCompleted" in tc
                ? tc.isCompleted
                : !!(normalized.function?.result || normalized.function?.error) &&
                    !approvalInfo;
            return (browserCaptureInlinePrompt.toolNames.includes(baseFunctionName) &&
                !isCompleted &&
                !normalized.function?.error);
        });
    }, [browserCaptureInlinePrompt, toolCalls]);
    const allToolCallsCompleted = useMemo(() => {
        if (!toolCalls || toolCalls.length === 0)
            return false;
        return toolCalls.every((tc) => {
            const isAgentToolCall = "isCompleted" in tc;
            if (isAgentToolCall)
                return tc.isCompleted;
            const normalized = normalizeToolCall(tc);
            const approvalInfo = tc.requiresApproval || normalized.requiresApproval;
            return !!(normalized.function?.result || normalized.function?.error) && !approvalInfo;
        });
    }, [toolCalls]);
    if (!toolCalls || toolCalls.length === 0) {
        return null;
    }
    const resolvePendingToolCalls = async (pendingToolCalls, approved) => {
        if (!agentId || pendingToolCalls.length === 0)
            return;
        const actionLabel = approved ? "approve" : "reject";
        if (approved && pendingToolCalls.length > 1) {
            const result = await approveToolCalls({
                agentId,
                toolCalls: pendingToolCalls.map((pending) => ({
                    messageId: pending.dbMessageId || pending.messageId,
                    toolCallId: pending.toolCallId,
                })),
            });
            const approvedToolCallIds = new Set(result.approvedToolCallIds || []);
            pendingToolCalls.forEach((pending) => {
                if (!approvedToolCallIds.has(pending.toolCallId)) {
                    return;
                }
                window.dispatchEvent(new CustomEvent("agent:toolApprovalResolved", {
                    detail: {
                        messageId: pending.dbMessageId || pending.messageId,
                        toolCallId: pending.toolCallId,
                        approved: true,
                    },
                }));
            });
            return;
        }
        await Promise.all(pendingToolCalls.map(async (pending) => {
            try {
                const params = {
                    agentId,
                    messageId: pending.dbMessageId || pending.messageId,
                    toolCallId: pending.toolCallId,
                };
                if (approved) {
                    await approveToolCall(params);
                }
                else {
                    await rejectToolCall(params);
                }
                window.dispatchEvent(new CustomEvent("agent:toolApprovalResolved", {
                    detail: {
                        messageId: pending.dbMessageId || pending.messageId,
                        toolCallId: pending.toolCallId,
                        approved,
                    },
                }));
            }
            catch (error) {
                console.error(`Failed to ${actionLabel} tool call ${pending.toolCallId}:`, error);
            }
        }));
    };
    // Helper to approve/reject all pending tool calls at once
    const handleApproveAllPending = async () => {
        if (!agentId || batchRiskAction)
            return;
        if (allPendingApprovals.length === 0)
            return;
        setBatchRiskAction("approve");
        try {
            await resolvePendingToolCalls(allPendingApprovals, true);
        }
        finally {
            setBatchRiskAction(null);
        }
    };
    const handleRejectAllPending = async () => {
        if (!agentId || batchRiskAction)
            return;
        if (allPendingApprovals.length === 0)
            return;
        setBatchRiskAction("reject");
        try {
            await resolvePendingToolCalls(allPendingApprovals, false);
        }
        finally {
            setBatchRiskAction(null);
        }
    };
    // Helper to switch to autonomous mode
    const handleSwitchToAutonomous = async () => {
        if (!agentId || isSwitchingMode)
            return;
        setIsSwitchingMode(true);
        try {
            const result = await updateAgentSettings(agentId, { mode: "autonomous" });
            if (result.success === false || result.updates?.mode === false) {
                throw new Error("Mode change was not applied");
            }
            onSwitchToAutonomous?.();
            // After switching to autonomous, approve all remaining pending tool calls
            if (allPendingApprovals.length > 0) {
                await resolvePendingToolCalls(allPendingApprovals, true);
            }
        }
        catch (error) {
            console.error("Failed to switch to autonomous mode:", error);
            alert(`Failed to switch to autonomous mode: ${error?.message || "Unknown error"}`);
        }
        finally {
            setIsSwitchingMode(false);
        }
    };
    const showGroupHeader = toolCalls.length > 0;
    return (_jsxs("div", { className: "flex flex-col", children: [showGroupHeader && (_jsxs("div", { className: "group flex cursor-pointer items-center gap-1.5 rounded-md px-1 py-1 text-xs text-gray-500 transition-all hover:bg-gray-100/60 hover:text-gray-700", onClick: () => {
                    setIsGroupExpanded((prev) => !prev);
                    setUserToggled(true);
                }, children: [_jsx("div", { className: "flex items-center transition-transform group-hover:scale-110", children: isGroupExpanded ? (_jsx(ChevronDown, { size: 14, strokeWidth: 1.5, className: "text-gray-500" })) : (_jsx(ChevronRight, { size: 14, strokeWidth: 1.5, className: "text-gray-500" })) }), _jsx("div", { className: "flex items-center text-gray-500", children: _jsx(Wrench, { strokeWidth: 1, size: 14 }) }), _jsxs("span", { className: `font-medium ${!allToolCallsCompleted ? "animate-text-shimmer" : ""}`, children: [toolCalls.length, " tool call", toolCalls.length !== 1 ? "s" : ""] }), !isGroupExpanded && groupSummary && (_jsx("span", { className: "ml-1 min-w-0 flex-1 truncate text-[10px] text-gray-400", children: groupSummary.uniqueNames.length <= 3
                            ? groupSummary.uniqueNames.join(", ")
                            : `${groupSummary.uniqueNames.slice(0, 2).join(", ")} +${groupSummary.uniqueNames.length - 2} more` })), groupSummary && groupSummary.errorCount > 0 && (_jsxs("span", { className: "ml-1 shrink-0 text-[10px] text-red-500", children: ["(", groupSummary.errorCount, " error", groupSummary.errorCount !== 1 ? "s" : "", ")"] }))] })), shouldShowGroupBrowserCaptureInlinePrompt && browserCaptureInlinePrompt && (_jsx("div", { className: "mt-2 ml-5 rounded-lg border border-blue-200 bg-blue-50 p-3 text-[11px] text-blue-900", children: _jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-semibold", children: browserCaptureInlinePrompt.label }), _jsx("div", { className: "mt-1 text-blue-800", children: browserCaptureInlinePrompt.description })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [_jsx("button", { type: "button", className: "rounded border border-blue-300 bg-white px-2 py-1 text-[11px] font-medium text-blue-900 disabled:cursor-not-allowed disabled:opacity-60", disabled: browserCaptureInlinePrompt.isPending, onClick: (event) => {
                                        event.stopPropagation();
                                        browserCaptureInlinePrompt.onAction();
                                    }, children: browserCaptureInlinePrompt.actionLabel }), browserCaptureInlinePrompt.onCancel && (_jsx("button", { type: "button", className: "rounded border border-blue-300 bg-white px-2 py-1 text-[11px] font-medium text-blue-900 disabled:cursor-not-allowed disabled:opacity-60", disabled: browserCaptureInlinePrompt.isPending, onClick: (event) => {
                                        event.stopPropagation();
                                        browserCaptureInlinePrompt.onCancel?.();
                                    }, children: browserCaptureInlinePrompt.cancelLabel ?? "Cancel" }))] })] }) })), isGroupExpanded && (_jsx("div", { className: "ml-4", children: toolCalls.map((originalToolCall, toolIndex) => {
                    const toolCall = normalizeToolCall(originalToolCall);
                    const toolResult = toolCall.function?.result;
                    const isAgentToolCall = "isCompleted" in originalToolCall;
                    const toolCallKey = ("toolCallId" in originalToolCall
                        ? originalToolCall.toolCallId
                        : toolCall.id) || `${messageId}-${toolIndex}`;
                    const popoverKey = `${messageId}-${toolCallKey}`;
                    const isPruned = !!toolCall.isPruned;
                    const toolCallMeta = formatToolCallMeta(toolCall.createdDate, toolCall.responseTimeMs);
                    // Get approval information to check if tool call is pending approval
                    const approvalInfo = originalToolCall.requiresApproval || toolCall.requiresApproval;
                    const isCompleted = isAgentToolCall
                        ? originalToolCall.isCompleted
                        : !!(toolResult || toolCall.function?.error) && !approvalInfo;
                    // Check if tool call is currently streaming (arguments still being generated)
                    const isStreaming = isAgentToolCall &&
                        "isStreaming" in originalToolCall &&
                        originalToolCall.isStreaming === true;
                    // Use the approval info from the backend
                    const finalApprovalInfo = approvalInfo;
                    // Check if this tool call's approval dialog has already been shown (for deduplication)
                    const toolCallIdForApproval = "toolCallId" in originalToolCall
                        ? originalToolCall.toolCallId
                        : toolCall.id;
                    const approvalAlreadyShown = seenApprovalDialogs?.has(toolCallIdForApproval) ?? false;
                    // Check if this tool call has been approved/rejected (look for status indicators in function name)
                    // The AgentTerminal adds " (approved)" or " (rejected)" or " (pending approval)" to the functionName field
                    const originalFunctionName = ("functionName" in originalToolCall
                        ? originalToolCall.functionName
                        : toolCall?.function?.name) || "";
                    const baseFunctionName = originalFunctionName
                        .replace(" (approved)", "")
                        .replace(" (rejected)", "")
                        .replace(" (pending approval)", "")
                        .trim()
                        .toLowerCase();
                    const isApproved = originalFunctionName.includes("(approved)");
                    const isRejected = originalFunctionName.includes("(rejected)");
                    const isPending = originalFunctionName.includes("(pending approval)");
                    // Treat only approved/rejected as final; pending should still show buttons
                    const hasApprovalStatus = isApproved || isRejected;
                    // Debug logging removed for performance
                    const isExpanded = openPopovers[popoverKey] || false;
                    const shouldShowBrowserCaptureInlinePrompt = !!browserCaptureInlinePrompt &&
                        browserCaptureInlinePrompt.toolNames.includes(baseFunctionName) &&
                        !isCompleted &&
                        !toolCall.function?.error;
                    const toolCallMessageId = originalToolCall.messageId || toolCall.messageId || messageId;
                    return (_jsxs("div", { children: [_jsxs("div", { className: "group flex cursor-pointer items-center gap-1.5 rounded-md px-1 py-1 text-xs text-gray-600 transition-all hover:bg-gray-100/60 hover:text-gray-800", onClick: () => {
                                    setOpenPopovers((prev) => ({
                                        ...prev,
                                        [popoverKey]: !prev[popoverKey],
                                    }));
                                }, children: [_jsx("div", { className: "flex items-center transition-transform group-hover:scale-110", children: isExpanded ? (_jsx(ChevronDown, { size: 14, strokeWidth: 1.5, className: "text-gray-500" })) : (_jsx(ChevronRight, { size: 14, strokeWidth: 1.5, className: "text-gray-500" })) }), isCompleted ? (_jsx("div", { className: `flex items-center transition-all ${toolCall.function?.error && !isPruned
                                            ? "text-red-500"
                                            : isPruned
                                                ? "text-slate-500"
                                                : "text-green-600"}`, children: getToolIcon(toolCall?.function?.name || "") })) : finalApprovalInfo && !hasApprovalStatus ? (_jsx("div", { className: "flex items-center text-amber-600 transition-all", children: getToolIcon(toolCall?.function?.name || "") })) : isStreaming || !finished ? (
                                    // Show spinner when tool call arguments are still being streamed or tool is executing
                                    _jsx(Spinner, { size: "xs" })) : (
                                    // Turn finished but tool call not completed - show static icon
                                    _jsx("div", { className: "flex items-center text-gray-400 transition-all", children: getToolIcon(toolCall?.function?.name || "") })), _jsxs("div", { className: "inline-flex min-w-0 flex-1 items-center gap-2", children: [_jsxs("span", { className: `shrink-0 font-medium transition-colors ${toolCall.function?.error && !isPruned
                                                    ? "text-red-600"
                                                    : isPruned
                                                        ? "text-slate-600"
                                                        : ""}`, children: [(originalFunctionName ||
                                                        toolCall?.function?.name ||
                                                        toolCall?.displayName ||
                                                        "(function name missing)")
                                                        .replace(" (approved)", "")
                                                        .replace(" (rejected)", "")
                                                        .replace(" (pending approval)", ""), toolCall.function?.error && !isRejected && !isPruned && (_jsx("span", { className: "ml-1 text-red-500", children: "(error)" })), isPruned && (_jsxs("span", { className: "ml-2 inline-flex items-center gap-1 rounded-full bg-slate-100 px-2 py-0.5 text-[10px] font-semibold text-slate-700", children: [_jsx("span", { children: "\u2702" }), " Pruned"] })), finalApprovalInfo && isRejected && (_jsxs("span", { className: "ml-2 inline-flex items-center gap-1 rounded-full bg-red-100 px-2 py-0.5 text-[10px] font-semibold text-red-700", children: [_jsx("span", { children: "\u2717" }), " Rejected"] }))] }), finalApprovalInfo?.summary && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { className: "min-w-0 flex-1 cursor-help truncate text-xs text-gray-500 italic", children: finalApprovalInfo.summary }) }), _jsx(TooltipContent, { side: "top", className: "max-w-md", children: finalApprovalInfo.summary })] })), _jsxs("div", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: [!isCompleted &&
                                                        finalApprovalInfo &&
                                                        !hasApprovalStatus && (_jsx(ApprovalDialog, { toolCallId: toolCallIdForApproval, onApprovalDialogShown: onApprovalDialogShown, finalApprovalInfo: finalApprovalInfo, isAgentToolCall: isAgentToolCall, originalToolCall: originalToolCall, toolCall: toolCall, messageId: toolCallMessageId, agentId: agentId })), toolCallMeta && (_jsx("span", { className: "text-[10px] text-gray-400", children: toolCallMeta }))] })] })] }), isExpanded && (_jsx(ToolCallDetails, { toolCall: toolCall, result: toolResult })), !shouldShowGroupBrowserCaptureInlinePrompt &&
                                shouldShowBrowserCaptureInlinePrompt &&
                                browserCaptureInlinePrompt && (_jsx("div", { className: "mt-2 ml-5 rounded-lg border border-blue-200 bg-blue-50 p-3 text-[11px] text-blue-900", children: _jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-semibold", children: browserCaptureInlinePrompt.label }), _jsx("div", { className: "mt-1 text-blue-800", children: browserCaptureInlinePrompt.description })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [_jsx("button", { type: "button", className: "rounded border border-blue-300 bg-white px-2 py-1 text-[11px] font-medium text-blue-900 disabled:cursor-not-allowed disabled:opacity-60", disabled: browserCaptureInlinePrompt.isPending, onClick: (event) => {
                                                        event.stopPropagation();
                                                        browserCaptureInlinePrompt.onAction();
                                                    }, children: browserCaptureInlinePrompt.actionLabel }), browserCaptureInlinePrompt.onCancel && (_jsx("button", { type: "button", className: "rounded border border-blue-300 bg-white px-2 py-1 text-[11px] font-medium text-blue-900 disabled:cursor-not-allowed disabled:opacity-60", disabled: browserCaptureInlinePrompt.isPending, onClick: (event) => {
                                                        event.stopPropagation();
                                                        browserCaptureInlinePrompt.onCancel?.();
                                                    }, children: browserCaptureInlinePrompt.cancelLabel ?? "Cancel" }))] })] }) }))] }, toolCallKey));
                }) })), (() => {
                if (!hasPendingApprovalsInGroup)
                    return null;
                const totalPending = allPendingApprovals.length;
                const uniqueRisks = Array.from(new Set(allPendingApprovals.map((p) => p.riskLevel || undefined)));
                const singleRisk = uniqueRisks.length === 1 ? uniqueRisks[0] : undefined;
                const riskLabel = singleRisk
                    ? `${singleRisk.charAt(0).toUpperCase()}${singleRisk.slice(1)} `
                    : "";
                // Hide autonomous switch if any pending tool call in the group is a delete
                const hideAutonomousSwitch = toolCalls.some((tc) => {
                    if (!tc.requiresApproval)
                        return false;
                    const name = ("functionName" in tc
                        ? tc.functionName
                        : normalizeToolCall(tc).function?.name) || "";
                    const base = name
                        .replace(" (approved)", "")
                        .replace(" (rejected)", "")
                        .replace(" (pending approval)", "")
                        .trim()
                        .toLowerCase();
                    return base === "delete-item" || base === "delete-items";
                });
                return (_jsxs("div", { className: "mt-2 flex flex-wrap items-center justify-end gap-2 p-2", children: [!hideAutonomousSwitch && (_jsx(Button, { size: "sm", variant: "outline", disabled: isSwitchingMode, onClick: handleSwitchToAutonomous, className: "text-xs", children: isSwitchingMode ? "Switching..." : "Switch to Autonomous" })), _jsx(Button, { size: "sm", variant: "outline", "data-testid": "agent-reject-all-button", disabled: batchRiskAction !== null, onClick: handleRejectAllPending, className: "text-xs", children: batchRiskAction === "reject"
                                ? "Rejecting..."
                                : `Reject All ${riskLabel}(${totalPending})` }), _jsx(Button, { size: "sm", "data-testid": "agent-approve-all-button", disabled: batchRiskAction !== null, onClick: handleApproveAllPending, className: "text-xs", children: batchRiskAction === "approve"
                                ? "Approving..."
                                : `Approve All ${riskLabel}(${totalPending})` })] }));
            })()] }));
}
// Separate component for approval dialog to properly handle useEffect
function ApprovalDialog({ toolCallId, onApprovalDialogShown, finalApprovalInfo, isAgentToolCall, originalToolCall, toolCall, messageId, agentId, }) {
    const hasMarkedAsShown = useRef(false);
    const [isCreatingAllowance, setIsCreatingAllowance] = useState(false);
    // Mark dialog as shown on mount to prevent duplicate dialogs
    // The dialog stays visible until hasApprovalStatus becomes true (after approve/reject)
    useEffect(() => {
        if (!hasMarkedAsShown.current && onApprovalDialogShown && toolCallId) {
            // Use requestAnimationFrame to ensure the dialog is rendered before marking as shown
            requestAnimationFrame(() => {
                requestAnimationFrame(() => {
                    if (!hasMarkedAsShown.current) {
                        onApprovalDialogShown(toolCallId);
                        hasMarkedAsShown.current = true;
                    }
                });
            });
        }
    }, [onApprovalDialogShown, toolCallId]);
    // Also mark as shown when user interacts (redundant but safe)
    const markAsShown = () => {
        if (!hasMarkedAsShown.current && onApprovalDialogShown && toolCallId) {
            onApprovalDialogShown(toolCallId);
            hasMarkedAsShown.current = true;
        }
    };
    const getActualMessageId = () => {
        return isAgentToolCall
            ? originalToolCall.dbMessageId || originalToolCall.messageId
            : messageId;
    };
    const dispatchApprovalResolved = (actualMessageId, approved) => {
        const ev = new CustomEvent("agent:toolApprovalResolved", {
            detail: {
                messageId: actualMessageId,
                toolCallId: toolCall.id,
                approved,
            },
        });
        window.dispatchEvent(ev);
    };
    const approveCurrentToolCall = async () => {
        const actualMessageId = getActualMessageId();
        if (!agentId) {
            console.error("Cannot approve tool call: agentId is missing");
            return;
        }
        if (!actualMessageId) {
            console.error("Cannot approve tool call: messageId is missing");
            return;
        }
        await approveToolCall({
            agentId,
            messageId: actualMessageId,
            toolCallId: toolCall.id,
        });
        dispatchApprovalResolved(actualMessageId, true);
    };
    const allowableScope = finalApprovalInfo.allowableScope;
    const showAllowInScopeButton = !!agentId &&
        allowableScope?.operationType === "delete" &&
        !!allowableScope.parentItemId &&
        !!allowableScope.parentItemPath;
    const riskLevel = finalApprovalInfo.riskLevel;
    const riskTagClass = riskLevel === "high"
        ? "bg-red-100 text-red-700"
        : riskLevel === "medium"
            ? "bg-amber-100 text-amber-700"
            : "bg-green-100 text-green-700";
    return (_jsxs(_Fragment, { children: [riskLevel && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { className: `shrink-0 cursor-help rounded px-1.5 py-0.5 text-[10px] font-semibold uppercase ${riskTagClass}`, children: riskLevel }) }), _jsxs(TooltipContent, { side: "top", className: "max-w-xs", children: [_jsxs("div", { className: "font-semibold", children: ["Risk: ", riskLevel.toUpperCase()] }), _jsx("div", { className: "mt-0.5 font-normal opacity-90", children: finalApprovalInfo.summary })] })] })), showAllowInScopeButton && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": isCreatingAllowance
                                ? "Allowing..."
                                : `Allow deletes in ${allowableScope?.parentItemPath}`, disabled: isCreatingAllowance, className: "flex size-5 shrink-0 items-center justify-center rounded text-gray-500 hover:bg-gray-100 hover:text-gray-900 disabled:cursor-not-allowed disabled:opacity-60", onClick: async (e) => {
                                e.stopPropagation();
                                markAsShown();
                                if (!agentId || !allowableScope?.parentItemId)
                                    return;
                                setIsCreatingAllowance(true);
                                try {
                                    await createOperationAllowance({
                                        agentId,
                                        itemId: allowableScope.parentItemId,
                                        operationType: "delete",
                                        scopeType: "itemSubtree",
                                    });
                                    await approveCurrentToolCall();
                                }
                                catch (error) {
                                    console.error("Failed to create operation allowance:", error);
                                    alert(`Failed to allow deletes in scope: ${error?.message || "Unknown error"}`);
                                }
                                finally {
                                    setIsCreatingAllowance(false);
                                }
                            }, children: _jsx(ShieldCheck, { className: "size-3" }) }) }), _jsx(TooltipContent, { side: "top", children: isCreatingAllowance
                            ? "Allowing..."
                            : `Allow deletes in ${allowableScope?.parentItemPath}` })] })), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": "Reject", "data-testid": "agent-reject-button", className: "flex size-5 shrink-0 items-center justify-center rounded text-red-600 hover:bg-red-50 hover:text-red-700", onClick: async (e) => {
                                e.stopPropagation();
                                markAsShown();
                                const actualMessageId = getActualMessageId();
                                if (!agentId) {
                                    console.error("❌ Cannot reject tool call: agentId is missing");
                                    return;
                                }
                                if (!actualMessageId) {
                                    console.error("❌ Cannot reject tool call: messageId is missing");
                                    return;
                                }
                                try {
                                    await rejectToolCall({
                                        agentId,
                                        messageId: actualMessageId,
                                        toolCallId: toolCall.id,
                                    });
                                    dispatchApprovalResolved(actualMessageId, false);
                                }
                                catch (error) {
                                    console.error("❌ Reject failed:", error);
                                }
                            }, children: _jsx(X, { className: "size-3" }) }) }), _jsx(TooltipContent, { side: "top", children: "Reject" })] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": "Approve", "data-testid": "agent-approve-button", className: "flex size-5 shrink-0 items-center justify-center rounded text-green-600 hover:bg-green-50 hover:text-green-700", onClick: async (e) => {
                                e.stopPropagation();
                                markAsShown();
                                try {
                                    await approveCurrentToolCall();
                                }
                                catch (error) {
                                    console.error("❌ Approve failed:", error);
                                    alert(`Failed to approve: ${error?.message || "Unknown error"}`);
                                }
                            }, children: _jsx(Check, { className: "size-3" }) }) }), _jsx(TooltipContent, { side: "top", children: "Approve" })] })] }));
}
//# sourceMappingURL=ToolCallDisplay.js.map