import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import React, { useState, useRef, useEffect } from "react";
import { SimpleIconButton } from "../ui/SimpleIconButton";
import { ArrowLeft, List, Plus } from "lucide-react";
import { CloseButton } from "../../components/ui/close-button";
import { cn } from "../../lib/utils";
import { sanitizeSvg } from "../../lib/sanitize";
import { getActiveAgents, } from "../services/agentService";
import { isExecutingAgentStatus, parseAgentRunStatusData, parseAgentStatus, shouldIgnoreReplayRunStart, } from "../services/agentStatus";
import { AgentTerminal } from "./AgentTerminal";
import { useEditContext } from "../client/editContext";
import { loadAiProfiles } from "../services/aiService";
import { resolveDefaultProfile } from "./agentProfileDefaults";
import { AgentProfileSelector } from "./AgentProfileSelector";
import { AgentsView } from "../../agents-view/AgentsView";
import { ParheliaAgentIcon } from "../ui/Icons";
import { Spinner } from "../ui/Spinner";
import { Splitter } from "../ui/Splitter";
import { localStorageService } from "../services/localStorageService";
import { LicenseFeatures, useFeature } from "../../licensing";
import { ACTIVE_AGENT_STORAGE_KEY, setActiveAgentConversation, } from "./useActiveAgentConversation";
import { requestSplitterPanelSize } from "../ui/splitterResizeEvent";
import { getUniqueAgentsById } from "./agentCollection";
// function convertAgentMessagesToTerminalMessages(
//   agentMessages: AgentChatMessage[],
// ): Message[] {
//   return agentMessages.map((msg) => ({
//     id: msg.id,
//     content: msg.content,
//     name: msg.name,
//     role: msg.role,
//     tool_calls: msg.functionName
//       ? [
//           {
//             id: msg.toolCallId || msg.id,
//             displayName: msg.functionName,
//             function: {
//               name: msg.functionName,
//               arguments: msg.functionArguments || "",
//             },
//           },
//         ]
//       : [],
//     tool_call_id: msg.toolCallId,
//   }));
// }
const TASKBOARD_PROJECT_QUERY_KEY = "tbProjectId";
const TASKBOARD_TASK_QUERY_KEY = "tbTaskId";
const AGENTS_LIST_WIDTH = 320;
const AGENTS_EXPANDED_PANEL_WIDTH = 920;
const AGENTS_LIST_PINNED_STORAGE_KEY = "agentsPanel.listPinned";
const AGENTS_CHAT_LIST_SPLITTER_STORAGE_KEY = "agentsPanel.chatListSizes";
const EDITOR_SPLITTER_STORAGE_KEY = "editor.panelSizes";
const FAR_RIGHT_AGENTS_PANEL_NAME = "farRightSidebar";
function readTaskboardLinkageFromUrl() {
    if (typeof window === "undefined") {
        return {};
    }
    const params = new URLSearchParams(window.location.search);
    const projectId = params.get(TASKBOARD_PROJECT_QUERY_KEY)?.trim() || "";
    const taskId = params.get(TASKBOARD_TASK_QUERY_KEY)?.trim() || "";
    return {
        projectId: projectId || undefined,
        taskId: taskId || undefined,
    };
}
export const Agents = React.memo(function Agents({ closeButton, }) {
    const [agents, setAgents] = useState([]);
    const [activeAgentId, setActiveAgentId] = useState(""); // "" = pending new default chat, null = show overview, string = agent ID
    const activeAgentIdRef = useRef("");
    const singleAgentModeRef = useRef(false);
    // Remembers the agent to return to when dismissing the agents-list or
    // profile-selector overlay via the X button.
    const returnAgentIdRef = useRef(null);
    const [loadingAgents, setLoadingAgents] = useState(true);
    const [inactiveAgents, setInactiveAgents] = useState([]);
    const [initialMetadataMap, setInitialMetadataMap] = useState({});
    const [availableProfiles, setAvailableProfiles] = useState([]);
    const [selectedProfileId, setSelectedProfileId] = useState("");
    const [loadingProfiles, setLoadingProfiles] = useState(false);
    const [agentsListPinned, setAgentsListPinned] = useState(() => localStorageService.getItem(AGENTS_LIST_PINNED_STORAGE_KEY) ??
        false);
    const editContext = useEditContext();
    const canUseAi = useFeature(LicenseFeatures.AI);
    useEffect(() => {
        if (loadingAgents && activeAgentId === "")
            return;
        const hasActiveConversation = typeof activeAgentId === "string" && activeAgentId !== "";
        setActiveAgentConversation(hasActiveConversation ? activeAgentId : null);
    }, [activeAgentId, loadingAgents]);
    const defaultCloseButton = (_jsx(CloseButton, { onClick: () => {
            editContext?.setShowAgentsPanel(false);
            if (editContext?.openSidebars.includes("agents-panel")) {
                editContext.toggleSidebar("agents-panel", { forceClose: true });
            }
        }, label: "Close Agents Panel", showTooltip: false }));
    // Resolve the profile SVG icon for the active/return agent shown in the header.
    const getAgentIcon = (agent) => availableProfiles.find((p) => p.id === agent.profileId)?.svgIcon ||
        agent.profileSvgIcon;
    // Detect single-agent mode from query parameter once on mount
    useEffect(() => {
        try {
            const params = new URLSearchParams(window.location.search);
            const value = params.get("singleAgent");
            singleAgentModeRef.current =
                value === "true" || params.has("singleAgent");
        }
        catch { }
    }, []);
    // Helper function to get the most recently updated agent
    const getMostRecentAgent = (agentList) => {
        if (agentList.length === 0)
            return null;
        return agentList.reduce((mostRecent, current) => {
            return new Date(current.updatedDate) > new Date(mostRecent.updatedDate)
                ? current
                : mostRecent;
        });
    };
    // Helper function to set active agent and persist to localStorage.
    // Keep this as a plain React update: the embedded panel can contain long
    // transcripts, profile grids, and hidden running terminals, and browser View
    // Transition snapshots have proven too expensive here.
    const setActiveAgentIdWithStorage = (agentId) => {
        activeAgentIdRef.current = agentId;
        setActiveAgentId(agentId);
        setActiveAgentConversation(agentId);
    };
    // Remember the currently open agent (if any) so the overlay X can return to it.
    const rememberReturnAgent = () => {
        const current = activeAgentIdRef.current;
        if (typeof current === "string" && current) {
            returnAgentIdRef.current = current;
        }
    };
    // The "+" button: enter the new-chat state. The default-draft effect turns
    // it into a ready-to-type chat on the default profile.
    const startNewChat = () => {
        rememberReturnAgent();
        setActiveAgentIdWithStorage("");
    };
    const requestExpandedAgentsPanel = React.useCallback(() => {
        requestSplitterPanelSize({
            localStorageKey: EDITOR_SPLITTER_STORAGE_KEY,
            panelName: FAR_RIGHT_AGENTS_PANEL_NAME,
            size: AGENTS_EXPANDED_PANEL_WIDTH,
        });
    }, []);
    const setAgentsListPinnedState = React.useCallback((nextPinned) => {
        setAgentsListPinned(nextPinned);
        localStorageService.setItem(AGENTS_LIST_PINNED_STORAGE_KEY, nextPinned);
        if (nextPinned) {
            requestExpandedAgentsPanel();
        }
    }, [requestExpandedAgentsPanel]);
    const toggleAgentsListPinned = React.useCallback(() => {
        setAgentsListPinnedState(!agentsListPinned);
    }, [agentsListPinned, setAgentsListPinnedState]);
    // The overlay X: return to the previously open agent, falling back to the
    // most recent agent, or the agents list when nothing is open.
    const dismissOverlay = () => {
        const ret = returnAgentIdRef.current;
        if (ret && agents.some((a) => a.id === ret)) {
            setActiveAgentIdWithStorage(ret);
            return;
        }
        const mostRecent = getMostRecentAgent(agents);
        setActiveAgentIdWithStorage(mostRecent ? mostRecent.id : null);
    };
    // Open an agent from history (or switch to it if already open)
    const openAgentFromHistory = React.useCallback(async (agent) => {
        if (!canUseAi) {
            return;
        }
        const existingAgent = agents.find((a) => a.id === agent.id);
        if (existingAgent) {
            setAgents((prev) => getUniqueAgentsById(prev));
            setActiveAgentIdWithStorage(existingAgent.id);
            return;
        }
        // If agent data is incomplete (e.g., only has ID), fetch full details from backend
        let fullAgent = agent;
        if (!agent.name || !agent.userId) {
            try {
                const { getAgent } = await import("../services/agentService");
                const agentDetails = await getAgent(agent.id);
                fullAgent = {
                    id: agentDetails.id,
                    name: agentDetails.name,
                    description: agentDetails.description,
                    userId: agentDetails.userId,
                    updatedDate: agentDetails.updatedDate,
                    status: agentDetails.status,
                    isShared: agentDetails.isShared,
                    ownerName: agentDetails.ownerName,
                    profileId: agentDetails.profileId,
                    profileName: agentDetails.profileName,
                    profileSvgIcon: agentDetails.profileSvgIcon,
                    messageCount: agentDetails.messageCount,
                    totalCost: agentDetails.totalCost,
                    totalTokensUsed: agentDetails.totalTokensUsed,
                    statusMessage: agentDetails.statusMessage,
                    lastMessageDate: agentDetails.lastMessageDate,
                };
            }
            catch (error) {
                console.error("Failed to fetch agent details:", error);
                // Fall back to using whatever data we have
            }
        }
        // Add the closed agent to the active agents list
        const reopenedAgent = {
            ...fullAgent,
            // Keep the original status to allow AgentTerminal to load the full agent data
        };
        setAgents((prev) => getUniqueAgentsById([...prev, reopenedAgent]));
        setActiveAgentIdWithStorage(reopenedAgent.id);
    }, [agents, canUseAi]);
    // Load agents from backend on mount
    useEffect(() => {
        if (!canUseAi) {
            setAgents([]);
            setInactiveAgents([]);
            setAvailableProfiles([]);
            setActiveAgentId(null);
            activeAgentIdRef.current = null;
            setSelectedProfileId("");
            setLoadingAgents(false);
            setLoadingProfiles(false);
            localStorageService.removeItem(ACTIVE_AGENT_STORAGE_KEY);
            return;
        }
        loadAgentsFromBackend();
    }, [canUseAi]);
    // When no agents are present (empty state) or when switching to the profile selector,
    // keep selection state consistent without triggering extra fetches.
    useEffect(() => {
        // When showing empty state (no agents) or profile selector is active, force placeholder selection
        if (agents.length === 0 || activeAgentId === "") {
            setSelectedProfileId("");
        }
        else {
            // Otherwise preserve placeholder if not set yet
            setSelectedProfileId((prev) => prev || "");
        }
    }, [activeAgentId, agents.length]);
    // Function to reload profiles
    const reloadProfiles = React.useCallback(async () => {
        if (!canUseAi) {
            setAvailableProfiles([]);
            setLoadingProfiles(false);
            return;
        }
        try {
            setLoadingProfiles(true);
            const profiles = await loadAiProfiles(editContext?.currentItemDescriptor);
            setAvailableProfiles(profiles || []);
        }
        catch (e) {
            console.error("Failed to load AI profiles", e);
        }
        finally {
            setLoadingProfiles(false);
        }
    }, [canUseAi, editContext?.currentItemDescriptor]);
    // Ensure profiles are loaded once for terminals (centralized load)
    // Only load on mount - profiles are cached and will be reloaded via websocket when changed
    useEffect(() => {
        if (!canUseAi) {
            setAvailableProfiles([]);
            setLoadingProfiles(false);
            return;
        }
        let cancelled = false;
        (async () => {
            try {
                setLoadingProfiles(true);
                const profiles = await loadAiProfiles(editContext?.currentItemDescriptor);
                if (cancelled)
                    return;
                setAvailableProfiles(profiles || []);
            }
            catch (e) {
                console.error("Failed to load AI profiles", e);
            }
            finally {
                if (!cancelled)
                    setLoadingProfiles(false);
            }
        })();
        return () => {
            cancelled = true;
        };
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [canUseAi]); // Only run on mount - profiles reload via websocket when changed
    // Listen for agent profile changes via websocket (when profiles are updated in Sitecore)
    useEffect(() => {
        if (!canUseAi || !editContext?.addSocketMessageListener)
            return;
        const removeListener = editContext.addSocketMessageListener((message) => {
            if (message.type === "agent-profiles-changed") {
                reloadProfiles();
            }
        });
        return () => {
            removeListener();
        };
    }, [canUseAi, editContext?.addSocketMessageListener, reloadProfiles]);
    // Listen for external requests to add a new agent (e.g., AI command)
    useEffect(() => {
        if (!canUseAi)
            return;
        const handleAddNewAgent = (ev) => {
            let initialMetadata = undefined;
            try {
                const ce = ev;
                initialMetadata = (ce.detail && ce.detail.metadata);
            }
            catch { }
            addAgent(initialMetadata);
            // Ensure the prompt focuses after the agent tab mounts
            setTimeout(() => {
                try {
                    window.dispatchEvent(new CustomEvent("editor:focusAgentPrompt"));
                }
                catch { }
            }, 60);
        };
        window.addEventListener("editor:addNewAgent", handleAddNewAgent);
        return () => window.removeEventListener("editor:addNewAgent", handleAddNewAgent);
    }, [canUseAi]);
    // Listen for external requests to select an existing open agent without switching views
    useEffect(() => {
        if (!canUseAi)
            return;
        const handleSelectAgent = (ev) => {
            try {
                const ce = ev;
                const agentId = (ce.detail && ce.detail.agentId);
                if (!agentId)
                    return;
                const existingAgent = agents.find((a) => a.id === agentId);
                if (existingAgent) {
                    setActiveAgentIdWithStorage(agentId);
                }
            }
            catch { }
        };
        window.addEventListener("editor:selectAgent", handleSelectAgent);
        return () => window.removeEventListener("editor:selectAgent", handleSelectAgent);
    }, [canUseAi, agents]);
    // Listen for external requests to open an existing agent
    useEffect(() => {
        if (!canUseAi)
            return;
        const handleOpenAgent = (ev) => {
            try {
                const ce = ev;
                const agentId = (ce.detail && ce.detail.agentId);
                if (!agentId)
                    return;
                // Load the agent from history (or switch to it if already open)
                // The openAgentFromHistory function handles both cases internally
                openAgentFromHistory({ id: agentId });
            }
            catch (error) {
                console.error("Error opening agent:", error);
            }
        };
        window.addEventListener("editor:openAgent", handleOpenAgent);
        return () => window.removeEventListener("editor:openAgent", handleOpenAgent);
    }, [canUseAi, openAgentFromHistory]);
    // Listen for external requests to create a new agent with a specific profile
    useEffect(() => {
        if (!canUseAi)
            return;
        const handleCreateAgentWithProfile = (ev) => {
            try {
                const ce = ev;
                const profile = (ce.detail && ce.detail.profile);
                if (!profile)
                    return;
                const suggestedInitialPrompt = (ce.detail && ce.detail.initialPrompt
                    ? String(ce.detail.initialPrompt)
                    : "").trim();
                // Build additionalData with preconfigured todos if available
                const additionalData = {
                    profileId: profile.id,
                    profileName: profile.name,
                };
                // A suggested opening prompt pre-fills the new chat's composer but is NOT auto-sent,
                // so the user can review/edit it before submitting.
                if (suggestedInitialPrompt) {
                    additionalData.initialPrompt = suggestedInitialPrompt;
                    additionalData.initialPromptAutoSubmit = false;
                }
                // Add preconfigured todos as todoList if the profile has them
                const preconfiguredTodos = profile.preconfiguredTodos;
                if (preconfiguredTodos && preconfiguredTodos.length > 0) {
                    additionalData.todoList = {
                        title: "Preconfigured Tasks",
                        items: preconfiguredTodos.map((todo) => ({
                            id: todo.id || crypto.randomUUID(),
                            title: todo.title,
                            status: "pending",
                            instructions: todo.instructions,
                            agentProfileId: todo.agentProfileId,
                        })),
                    };
                }
                // Create metadata with profile info
                const metadata = {
                    profile: profile.name,
                    additionalData,
                };
                // Create a new agent with the profile
                const newAgent = {
                    status: "new",
                    id: crypto.randomUUID(),
                    name: profile.agentName || profile.displayTitle || profile.name,
                    updatedDate: new Date().toISOString(),
                    userId: "",
                    profileId: profile.id,
                    profileName: profile.name,
                    profileSvgIcon: profile.svgIcon,
                };
                setAgents((prev) => [...prev, newAgent]);
                setActiveAgentIdWithStorage(newAgent.id);
                setInitialMetadataMap((prev) => ({ ...prev, [newAgent.id]: metadata }));
                // Focus the prompt after the agent tab mounts
                setTimeout(() => {
                    try {
                        window.dispatchEvent(new CustomEvent("editor:focusAgentPrompt"));
                    }
                    catch { }
                }, 60);
            }
            catch (error) {
                console.error("Error creating agent with profile:", error);
            }
        };
        window.addEventListener("editor:createAgentWithProfile", handleCreateAgentWithProfile);
        return () => window.removeEventListener("editor:createAgentWithProfile", handleCreateAgentWithProfile);
    }, [canUseAi]);
    // Subscribe to websocket messages for agent events
    useEffect(() => {
        if (!canUseAi || !editContext?.addSocketMessageListener)
            return;
        const unsubscribe = editContext.addSocketMessageListener((message) => {
            // In single-agent mode, ignore events that would add or remove agents,
            // but still allow updates (e.g., name/status) for the current tab.
            if (singleAgentModeRef.current) {
                if (message.type === "agent:run:start" ||
                    message.type === "agent:run:closed") {
                    return;
                }
            }
            if (message.type === "agent:run:start") {
                const payload = message.payload || {};
                const agentId = payload.agentId;
                const agentName = payload.agentName;
                const autoSelect = payload.autoSelect;
                const profileId = payload.profileId;
                const profileName = payload.profileName;
                const timestamp = payload.timestamp;
                if (!agentId || !agentName) {
                    console.warn("Invalid agent:run:start message payload:", message.payload);
                    return;
                }
                setAgents((prevAgents) => {
                    // Check if agent already exists
                    const existingAgentIndex = prevAgents.findIndex((agent) => agent.id === agentId);
                    if (existingAgentIndex !== -1) {
                        // Update existing agent name and profile info
                        const updatedAgents = [...prevAgents];
                        const existingAgent = updatedAgents[existingAgentIndex];
                        if (shouldIgnoreReplayRunStart(existingAgent.status, existingAgent.updatedDate, typeof timestamp === "string" ? timestamp : undefined)) {
                            return prevAgents;
                        }
                        updatedAgents[existingAgentIndex] = {
                            ...existingAgent,
                            name: agentName,
                            status: "running",
                            updatedDate: new Date().toISOString(),
                            ...(profileId && { profileId }),
                            ...(profileName && { profileName }),
                        };
                        return updatedAgents;
                    }
                    else {
                        // Add new agent to the array
                        const newAgent = {
                            id: agentId,
                            name: agentName,
                            status: "running",
                            userId: "", // Will be populated from backend if needed
                            updatedDate: new Date().toISOString(),
                            ...(profileId && { profileId }),
                            ...(profileName && { profileName }),
                        };
                        return [...prevAgents, newAgent];
                    }
                });
                // Auto-switch to the spawned agent if requested
                if (autoSelect === true) {
                    setActiveAgentIdWithStorage(agentId);
                }
            }
            else if (message.type === "agent:info:updated") {
                const payload = message.payload || {};
                const agentId = payload.agentId;
                const agentName = payload.agentName;
                const agentDescription = payload.agentDescription;
                if (!agentId)
                    return;
                // Update the agent name and/or description in the tabs list
                setAgents((prevAgents) => {
                    const existingIndex = prevAgents.findIndex((a) => a.id === agentId);
                    if (existingIndex === -1)
                        return prevAgents;
                    const updatedAgents = [...prevAgents];
                    const existingAgent = updatedAgents[existingIndex];
                    updatedAgents[existingIndex] = {
                        ...existingAgent,
                        ...(agentName !== undefined && { name: agentName }),
                        ...(agentDescription !== undefined && {
                            description: agentDescription,
                        }),
                        updatedDate: new Date().toISOString(),
                    };
                    return updatedAgents;
                });
            }
            else if (message.type === "agent:run:status") {
                // Unified status updates (state only)
                const payload = message.payload || {};
                const agentId = payload.agentId;
                const data = payload.data;
                if (!agentId)
                    return;
                const status = parseAgentRunStatusData(data);
                if (!status)
                    return;
                setAgents((prevAgents) => {
                    const existingIndex = prevAgents.findIndex((a) => a.id === agentId);
                    if (existingIndex !== -1) {
                        const updatedAgents = [...prevAgents];
                        const existingAgent = updatedAgents[existingIndex];
                        updatedAgents[existingIndex] = {
                            ...existingAgent,
                            status,
                            updatedDate: new Date().toISOString(),
                        };
                        return updatedAgents;
                    }
                    return prevAgents;
                });
            }
            else if (message.type === "agent:run:closed") {
                // Remove agent from tabs when closed in another browser instance
                const { agentId } = message.payload || {};
                if (!agentId)
                    return;
                setAgents((prevAgents) => {
                    const filtered = prevAgents.filter((a) => a.id !== agentId);
                    // Find the closed agent to add to history
                    const closedAgent = prevAgents.find((a) => a.id === agentId);
                    if (closedAgent) {
                        // Add to inactive agents list (history) if it doesn't already exist
                        setInactiveAgents((prevInactive) => {
                            const alreadyExists = prevInactive.some((a) => a.id === agentId);
                            if (alreadyExists) {
                                return prevInactive;
                            }
                            return [
                                {
                                    ...closedAgent,
                                    status: "closed",
                                    updatedDate: new Date().toISOString(),
                                },
                                ...prevInactive,
                            ];
                        });
                    }
                    // If we're closing the active agent, switch to the most recent remaining one
                    if (activeAgentIdRef.current === agentId) {
                        if (filtered.length > 0) {
                            const mostRecentAgent = getMostRecentAgent(filtered);
                            setActiveAgentIdWithStorage(mostRecentAgent?.id || null);
                        }
                        else {
                            // No agents left, show profile selector
                            setActiveAgentId("");
                            activeAgentIdRef.current = "";
                            localStorageService.removeItem(ACTIVE_AGENT_STORAGE_KEY);
                        }
                    }
                    // If no agents remain, reset profile selection to placeholder
                    if (filtered.length === 0) {
                        setSelectedProfileId("");
                    }
                    return filtered;
                });
            }
            else if (message.type === "agent:profile:switched") {
                // Handle profile switch initiated by the agent (via switch-profile function)
                const payload = message.payload || {};
                const agentId = payload.agentId;
                const newProfileId = payload.newProfileId;
                const newProfileName = payload.newProfileName;
                if (!agentId || !newProfileId)
                    return;
                // Find the profile's icon from available profiles
                const newProfile = availableProfiles.find((p) => p.id.toLowerCase() === newProfileId?.toLowerCase());
                setAgents((prevAgents) => {
                    const existingIndex = prevAgents.findIndex((a) => a.id === agentId);
                    if (existingIndex === -1)
                        return prevAgents;
                    const updatedAgents = [...prevAgents];
                    const existingAgent = updatedAgents[existingIndex];
                    updatedAgents[existingIndex] = {
                        ...existingAgent,
                        profileId: newProfileId,
                        profileName: newProfileName,
                        profileSvgIcon: newProfile?.svgIcon,
                        updatedDate: new Date().toISOString(),
                    };
                    return updatedAgents;
                });
            }
        });
        return unsubscribe;
    }, [canUseAi, editContext?.addSocketMessageListener, availableProfiles]);
    const loadAgentsFromBackend = async () => {
        try {
            if (!canUseAi) {
                setAgents([]);
                setInactiveAgents([]);
                setLoadingAgents(false);
                return;
            }
            // In single-agent mode, skip loading any pre-existing/open agents or history
            if (singleAgentModeRef.current) {
                setAgents([]);
                setInactiveAgents([]);
                // In single-agent mode, start with profile selector (empty string) instead of overview (null)
                setActiveAgentId("");
                activeAgentIdRef.current = "";
                localStorageService.removeItem(ACTIVE_AGENT_STORAGE_KEY);
                setLoadingAgents(false);
                return;
            }
            setLoadingAgents(true);
            // Load active agents (exclude shared agents for the agent panel)
            const activeAgentsResponse = await getActiveAgents({
                limit: 1000,
                includeShared: false, // Agent panel only shows user's own agents
                includeOwned: true,
                excludeClosed: true, // Exclude closed and cancelled agents
            });
            const activeAgentsResult = activeAgentsResponse.agents;
            // Merge the backend agents with any locally added "new" agents that haven't been saved yet
            setAgents((prev) => {
                const newAgents = prev.filter((a) => a.status === "new");
                // Avoid duplicates if any new agents were already saved and returned in activeAgentsResult
                const backendIds = new Set(activeAgentsResult.map((a) => a.id));
                const filteredNewAgents = newAgents.filter((a) => !backendIds.has(a.id));
                return getUniqueAgentsById([
                    ...activeAgentsResult,
                    ...filteredNewAgents,
                ]);
            });
            // Try to restore the previously active agent from localStorage if one exists
            let selectedAgentId = null;
            if (activeAgentsResult.length > 0) {
                const storedAgentId = localStorageService.getString(ACTIVE_AGENT_STORAGE_KEY);
                const storedAgent = activeAgentsResult.find((agent) => agent.id === storedAgentId);
                if (storedAgent) {
                    selectedAgentId = storedAgent.id;
                }
                else {
                    // If no stored agent or stored agent not found, select the most recent agent
                    const mostRecentAgent = getMostRecentAgent(activeAgentsResult);
                    selectedAgentId = mostRecentAgent?.id || null;
                }
            }
            // If there are no active agents after load, keep the new-chat sentinel
            // so the default-draft effect lands the user on a ready-to-type chat
            // instead of the overview.
            if (activeAgentsResult.length === 0) {
                if (!activeAgentIdRef.current) {
                    setActiveAgentId("");
                    activeAgentIdRef.current = "";
                    localStorageService.removeItem(ACTIVE_AGENT_STORAGE_KEY);
                    setSelectedProfileId("");
                }
            }
            else {
                // Only restore from backend/storage if no new agent is currently active
                // This prevents overwriting a newly created agent from a comment (especially on mobile)
                const currentActiveId = activeAgentIdRef.current;
                if (!currentActiveId) {
                    setActiveAgentIdWithStorage(selectedAgentId);
                }
            }
        }
        catch (error) {
            console.error("Failed to load agents:", error);
        }
        finally {
            setLoadingAgents(false);
        }
    };
    // const loadAgentMessages = async (
    //   agentId: string,
    // ): Promise<AgentChat | null> => {
    //   try {
    //     const result = await getAgent(agentId);
    //     if (result.type === "success" && result.data) {
    //       return result.data;
    //     }
    //   } catch (error) {
    //     console.error(`Failed to load messages for agent ${agentId}:`, error);
    //   }
    //   return null;
    // };
    const addAgent = (metadata) => {
        if (!canUseAi) {
            return;
        }
        const newAgent = {
            status: "new",
            id: crypto.randomUUID(),
            name: `New Agent`,
            updatedDate: new Date().toISOString(),
            userId: "",
            profileId: metadata?.additionalData?.profileId,
            profileName: metadata?.additionalData?.profileName || metadata?.profile,
        };
        setAgents((prev) => [...prev, newAgent]);
        // User-initiated creation should activate the new agent tab
        setActiveAgentIdWithStorage(newAgent.id);
        if (metadata) {
            setInitialMetadataMap((prev) => ({ ...prev, [newAgent.id]: metadata }));
        }
        // Ensure the prompt focuses after the agent tab mounts
        setTimeout(() => {
            try {
                window.dispatchEvent(new CustomEvent("editor:focusAgentPrompt"));
            }
            catch { }
        }, 60);
    };
    const createAgentWithSelectedProfile = (profileId) => {
        const selected = availableProfiles.find((p) => p.id === profileId);
        const taskboardLinkage = readTaskboardLinkageFromUrl();
        // Build additionalData with preconfigured todos if available
        // Backend uses [PreserveNames] so check both camelCase and PascalCase
        const additionalData = selected
            ? {
                profileId: selected.id,
                profileName: selected.name,
                ...(taskboardLinkage.projectId
                    ? { projectId: taskboardLinkage.projectId }
                    : {}),
                ...(taskboardLinkage.taskId
                    ? { taskId: taskboardLinkage.taskId }
                    : {}),
            }
            : {};
        const preconfiguredTodos = selected?.preconfiguredTodos;
        if (preconfiguredTodos && preconfiguredTodos.length > 0) {
            additionalData.todoList = {
                title: "Preconfigured Tasks",
                items: preconfiguredTodos.map((todo) => ({
                    id: todo.id || crypto.randomUUID(),
                    title: todo.title,
                    status: "pending",
                    instructions: todo.instructions,
                    agentProfileId: todo.agentProfileId,
                })),
            };
        }
        const metadata = selected
            ? {
                profile: selected.name,
                additionalData,
            }
            : undefined;
        addAgent(metadata);
    };
    const handleAgentUpdate = React.useCallback((agentId, updates) => {
        setAgents((prev) => prev.map((agent) => agent.id === agentId ? { ...agent, ...updates } : agent));
    }, []);
    const handleDraftMetadataUpdate = React.useCallback((agentId, metadata) => {
        setInitialMetadataMap((prev) => {
            const current = prev[agentId];
            const nextAdditionalData = {
                ...(current?.additionalData || {}),
                ...(metadata.additionalData || {}),
            };
            // Profile switches own the todo list. An omitted todoList in the
            // complete draft metadata means the selected profile has no todos;
            // do not resurrect the previous profile's list on a remount.
            if (!Object.prototype.hasOwnProperty.call(metadata.additionalData || {}, "todoList")) {
                delete nextAdditionalData.todoList;
            }
            return {
                ...prev,
                [agentId]: {
                    ...(current || {}),
                    ...metadata,
                    additionalData: nextAdditionalData,
                },
            };
        });
    }, []);
    // Whenever the new-chat sentinel ("") is active, create a draft on the
    // default profile so the user lands on the greeting ready to type. The ref
    // guards against duplicate drafts (StrictMode double-invoke, re-renders
    // before the draft's id becomes the active agent).
    const pendingDefaultDraftRef = useRef(false);
    useEffect(() => {
        if (activeAgentId !== "") {
            pendingDefaultDraftRef.current = false;
            return;
        }
        if (loadingAgents || loadingProfiles)
            return;
        if (pendingDefaultDraftRef.current)
            return;
        const defaultProfile = resolveDefaultProfile(availableProfiles);
        if (!defaultProfile)
            return;
        pendingDefaultDraftRef.current = true;
        createAgentWithSelectedProfile(defaultProfile.id);
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [activeAgentId, loadingAgents, loadingProfiles, availableProfiles]);
    useEffect(() => {
        if (agentsListPinned &&
            agents.length > 0 &&
            activeAgentId !== "" &&
            activeAgentId !== null) {
            requestExpandedAgentsPanel();
        }
    }, [
        activeAgentId,
        agents.length,
        agentsListPinned,
        requestExpandedAgentsPanel,
    ]);
    if (!canUseAi) {
        return (_jsx("div", { className: "text-neutral-grey-50 flex h-full items-center justify-center p-4 text-center text-sm", children: "AI features are unavailable with the current license." }));
    }
    if (loadingAgents) {
        return (_jsxs("div", { className: "flex h-full items-center justify-center gap-2", children: [_jsx(Spinner, { size: "sm" }), _jsx("div", { className: "text-neutral-grey-50 text-xs", children: "Loading agents..." })] }));
    }
    // Derived display state for the header and responsive agents list.
    const uniqueAgents = getUniqueAgentsById(agents);
    const activeAgent = uniqueAgents.find((a) => a.id === activeAgentId);
    // Main content modes shown instead of an agent terminal:
    //   null = agents list, "" = profile selector, string = an agent.
    const showingMainList = activeAgentId === null;
    const showingSelector = activeAgentId === "";
    const inMainOverlay = showingMainList || showingSelector;
    // The return button can go back to an agent only when at least one is open.
    const canDismissToAgent = uniqueAgents.length > 0;
    const headerActsAsBack = inMainOverlay && canDismissToAgent;
    const canShowAgentsListSidebar = uniqueAgents.length > 0 && !showingMainList && !showingSelector;
    const showChatHistorySidebar = canShowAgentsListSidebar && agentsListPinned;
    const selectedListAgentId = typeof activeAgentId === "string" && activeAgentId
        ? activeAgentId
        : returnAgentIdRef.current &&
            uniqueAgents.some((a) => a.id === returnAgentIdRef.current)
            ? returnAgentIdRef.current
            : undefined;
    const contextLabel = showingSelector
        ? "New chat"
        : showingMainList
            ? "Select an agent session"
            : activeAgent
                ? activeAgent.name
                : "Agents";
    const headerAgent = !inMainOverlay ? activeAgent : null;
    const headerAgentIcon = headerAgent ? getAgentIcon(headerAgent) : undefined;
    const handleAgentsListSelect = (agent) => {
        openAgentFromHistory(agent);
    };
    const handleAgentsListCreate = () => {
        startNewChat();
    };
    const renderAgentsList = ({ hideNewAgentButton = false, showProfileIcons = true, } = {}) => (_jsx(AgentsView, { compact: true, selectedAgentId: selectedListAgentId, onSelectAgent: handleAgentsListSelect, onRequestCreateAgent: handleAgentsListCreate, hideNewAgentButton: hideNewAgentButton, showProfileIcons: showProfileIcons }));
    const agentChatPane = (_jsx("div", { className: "relative h-full w-full min-w-0 flex-1 overflow-hidden bg-white", children: (() => {
            const shouldKeepMounted = (agent) => {
                const parsedStatus = parseAgentStatus(agent.status);
                return (agent.id === activeAgentId ||
                    isExecutingAgentStatus(parsedStatus) ||
                    parsedStatus === "waitingForInput" ||
                    parsedStatus === "costLimitReached");
            };
            const mountedAgents = uniqueAgents.filter(shouldKeepMounted);
            return (_jsxs(_Fragment, { children: [mountedAgents.map((agent) => {
                        const isSelected = agent.id === activeAgentId;
                        const parsedStatus = parseAgentStatus(agent.status);
                        const keepStreaming = isSelected ||
                            isExecutingAgentStatus(parsedStatus) ||
                            parsedStatus === "waitingForInput" ||
                            parsedStatus === "costLimitReached";
                        return (_jsx("div", { 
                            // No view-transition-name here. The full streaming transcript
                            // renders inside this div; a name makes any document-wide
                            // startViewTransition (workspace switch, splitter collapse)
                            // snapshot the old transcript and cross-fade it over the live
                            // one, painting the same content at offset positions (a
                            // ghosted z-stack). The tab-switch crossfade this name once
                            // paired with was removed for perf (see
                            // setActiveAgentIdWithStorage), so the name was dead metadata.
                            className: cn("absolute inset-0", !isSelected && "hidden"), children: _jsx(AgentTerminal, { agentStub: agent, initialMetadata: initialMetadataMap[agent.id], profiles: availableProfiles, onReloadProfiles: reloadProfiles, isActive: isSelected, isVisible: keepStreaming, isFocused: isSelected, enableGreetingProfileSwitcher: true, onAgentUpdate: (updates) => handleAgentUpdate(agent.id, updates), onDraftMetadataUpdate: (metadata) => handleDraftMetadataUpdate(agent.id, metadata) }) }, agent.id));
                    }), showingMainList ? (
                    // Agents list - pick an agent to switch, or create a new one.
                    _jsx("div", { className: "absolute inset-0", children: renderAgentsList() })) : showingSelector ? (!loadingProfiles && availableProfiles.length === 0 ? (
                    // No default profile resolvable - fall back to the card
                    // picker, which renders the "no profiles" empty state.
                    _jsx("div", { className: "absolute inset-0 flex items-start justify-center overflow-y-auto p-2", children: _jsx("div", { className: "w-full max-w-5xl", children: _jsx(AgentProfileSelector, { profiles: availableProfiles, onSelectProfile: createAgentWithSelectedProfile, loading: loadingProfiles, title: "" }) }) })) : (
                    // Transient state: the default-draft effect replaces this
                    // with a ready-to-type chat as soon as profiles arrive.
                    _jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: _jsx(Spinner, { size: "sm" }) }))) : null] }));
        })() }));
    const chatHistoryPane = (_jsx("div", { className: "relative h-full overflow-hidden bg-white", "data-testid": "agent-chat-history-sidebar", children: renderAgentsList({ hideNewAgentButton: true, showProfileIcons: false }) }));
    const chatHistorySplitterPanels = [
        {
            name: "agent-chat",
            defaultSize: "auto",
            // The collapsed history rail leaves roughly 260px for chat at the
            // narrowest supported agents-panel width.
            minSize: 240,
            content: agentChatPane,
        },
        {
            name: "agent-chat-history",
            defaultSize: AGENTS_LIST_WIDTH,
            minSize: 260,
            content: chatHistoryPane,
            collapsed: !showChatHistorySidebar,
            animatedCollapse: true,
        },
    ];
    const terminalContent = canShowAgentsListSidebar ? (_jsx(Splitter, { direction: "horizontal", localStorageKey: AGENTS_CHAT_LIST_SPLITTER_STORAGE_KEY, panels: chatHistorySplitterPanels, className: "h-full min-w-0 flex-1", splitterClassName: "md:w-[6px]" })) : (agentChatPane);
    return (_jsxs("div", { className: "flex h-full flex-col", children: [_jsxs("div", { className: cn("border-border-default flex min-h-12 items-center gap-1.5 border-b bg-white px-2.5 py-2", headerActsAsBack && "cursor-pointer"), onClick: headerActsAsBack ? dismissOverlay : undefined, children: [_jsxs("button", { type: "button", "data-active": !inMainOverlay ? "true" : undefined, "data-agent-id": typeof activeAgentId === "string" ? activeAgentId : "", "data-testid": "agent-title", "aria-label": headerActsAsBack ? "Return to agent" : "Active agent", onClick: (event) => {
                            if (headerActsAsBack) {
                                event.stopPropagation();
                                dismissOverlay();
                            }
                        }, className: cn("flex min-w-0 flex-1 items-center gap-1.5 rounded-md px-1.5 py-1 text-left", headerActsAsBack
                            ? "hover:bg-neutral-grey-5 cursor-pointer"
                            : "cursor-default"), children: [headerActsAsBack && (_jsx(ArrowLeft, { className: "text-neutral-grey-50 size-4 shrink-0", strokeWidth: 1 })), headerAgent &&
                                (headerAgentIcon ? (_jsx("div", { className: "text-neutral-grey-100 flex size-[22px] shrink-0 items-center justify-center [&>svg]:h-full [&>svg]:w-full", dangerouslySetInnerHTML: {
                                        __html: sanitizeSvg(headerAgentIcon),
                                    } })) : (_jsx(ParheliaAgentIcon, { size: 22, strokeWidth: 1, className: "text-neutral-grey-100 shrink-0" }))), _jsx("span", { className: "text-neutral-grey-100 min-w-0 flex-1 truncate text-[14px] font-medium", children: contextLabel })] }), _jsx("div", { className: "flex shrink-0 items-center gap-1", onClick: (event) => event.stopPropagation(), children: _jsx("div", { className: "flex items-center pl-0.5", children: closeButton ?? defaultCloseButton }) })] }), _jsxs("div", { className: "relative flex min-h-0 flex-1 overflow-hidden", children: [terminalContent, canShowAgentsListSidebar && (_jsxs("div", { className: "border-border-default flex h-full w-12 shrink-0 flex-col items-center gap-2 border-l bg-white px-1.5 py-3", "data-testid": "agent-terminal-right-rail", children: [_jsx(SimpleIconButton, { onClick: toggleAgentsListPinned, icon: _jsx(List, { className: "size-4", strokeWidth: 1 }), label: showChatHistorySidebar
                                    ? "Hide chat history"
                                    : "Show chat history", "aria-expanded": showChatHistorySidebar, selected: showChatHistorySidebar, className: "border-border-default text-neutral-grey-50 hover:text-neutral-grey-100 h-8 w-8 bg-white p-0 hover:bg-white", "data-testid": "agent-chat-history-button" }), _jsx(SimpleIconButton, { onClick: handleAgentsListCreate, icon: _jsx(Plus, { className: "size-4", strokeWidth: 1 }), label: "Start new chat", className: "border-border-default text-neutral-grey-50 hover:text-neutral-grey-100 h-8 w-8 bg-white p-0 hover:bg-white", "data-testid": "agent-rail-new-chat-button" })] }))] })] }));
});
//# sourceMappingURL=Agents.js.map