agent-relay-server 0.35.2 → 0.35.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/docs/openapi.json +1 -1
  2. package/package.json +1 -1
  3. package/public/assets/{activity-WjOShx3N.js → activity-CPuZGkeP.js} +2 -2
  4. package/public/assets/{activity-WjOShx3N.js.map → activity-CPuZGkeP.js.map} +1 -1
  5. package/public/assets/{agents-Cihuuoxa.js → agents-Bz4eJ4zH.js} +2 -2
  6. package/public/assets/{agents-Cihuuoxa.js.map → agents-Bz4eJ4zH.js.map} +1 -1
  7. package/public/assets/{analytics-B5_HS2Lt.js → analytics-inmkBD_j.js} +2 -2
  8. package/public/assets/{analytics-B5_HS2Lt.js.map → analytics-inmkBD_j.js.map} +1 -1
  9. package/public/assets/{automation-CoOe2nEA.js → automation-DRN2lcqQ.js} +2 -2
  10. package/public/assets/{automation-CoOe2nEA.js.map → automation-DRN2lcqQ.js.map} +1 -1
  11. package/public/assets/chat-Dn3TEhl0.js +2 -0
  12. package/public/assets/chat-Dn3TEhl0.js.map +1 -0
  13. package/public/assets/display-Bebqs1qu.js.map +1 -1
  14. package/public/assets/{formatted-body-impl-DhCblnWM.js → formatted-body-impl-DP9iZsd4.js} +2 -2
  15. package/public/assets/{formatted-body-impl-DhCblnWM.js.map → formatted-body-impl-DP9iZsd4.js.map} +1 -1
  16. package/public/assets/{index-CvSlyTSI.js → index-BL8r94_U.js} +5 -5
  17. package/public/assets/{index-CvSlyTSI.js.map → index-BL8r94_U.js.map} +1 -1
  18. package/public/assets/{maintenance-CUxxVXsc.js → maintenance-DtfpsMZa.js} +2 -2
  19. package/public/assets/{maintenance-CUxxVXsc.js.map → maintenance-DtfpsMZa.js.map} +1 -1
  20. package/public/assets/{managed-agents-VZEeMMSP.js → managed-agents-C5pzetBh.js} +2 -2
  21. package/public/assets/{managed-agents-VZEeMMSP.js.map → managed-agents-C5pzetBh.js.map} +1 -1
  22. package/public/assets/{markdown-preview-impl-Bbwmbxvn.js → markdown-preview-impl-4s9YDGM7.js} +2 -2
  23. package/public/assets/{markdown-preview-impl-Bbwmbxvn.js.map → markdown-preview-impl-4s9YDGM7.js.map} +1 -1
  24. package/public/assets/{memory-BQAC3YmR.js → memory-BWfDbph3.js} +2 -2
  25. package/public/assets/{memory-BQAC3YmR.js.map → memory-BWfDbph3.js.map} +1 -1
  26. package/public/assets/{messages-_sdHV42k.js → messages-C8cP25kp.js} +2 -2
  27. package/public/assets/{messages-_sdHV42k.js.map → messages-C8cP25kp.js.map} +1 -1
  28. package/public/assets/{orchestrators-BkHHgd83.js → orchestrators-Clu8MNKo.js} +2 -2
  29. package/public/assets/{orchestrators-BkHHgd83.js.map → orchestrators-Clu8MNKo.js.map} +1 -1
  30. package/public/assets/{overview-CYAHOUyA.js → overview-CXcGh2D6.js} +2 -2
  31. package/public/assets/{overview-CYAHOUyA.js.map → overview-CXcGh2D6.js.map} +1 -1
  32. package/public/assets/{pairs-BvMH1CS7.js → pairs-eOZl_lQn.js} +2 -2
  33. package/public/assets/{pairs-BvMH1CS7.js.map → pairs-eOZl_lQn.js.map} +1 -1
  34. package/public/assets/{security-Dsdr3lSX.js → security-CA03sHyP.js} +2 -2
  35. package/public/assets/{security-Dsdr3lSX.js.map → security-CA03sHyP.js.map} +1 -1
  36. package/public/assets/{settings-DlovIWdE.js → settings-KTOwGJiW.js} +2 -2
  37. package/public/assets/{settings-DlovIWdE.js.map → settings-KTOwGJiW.js.map} +1 -1
  38. package/public/assets/{tasks-Cgan8Oqb.js → tasks-D6jbr2y6.js} +2 -2
  39. package/public/assets/{tasks-Cgan8Oqb.js.map → tasks-D6jbr2y6.js.map} +1 -1
  40. package/public/assets/{terminal-viewer-impl-DVW-LRbz.js → terminal-viewer-impl-DFODXxpG.js} +2 -2
  41. package/public/assets/{terminal-viewer-impl-DVW-LRbz.js.map → terminal-viewer-impl-DFODXxpG.js.map} +1 -1
  42. package/public/assets/{work-queue-B4CifZKH.js → work-queue-BWWckTVy.js} +2 -2
  43. package/public/assets/{work-queue-B4CifZKH.js.map → work-queue-BWWckTVy.js.map} +1 -1
  44. package/public/index.html +1 -1
  45. package/runner/src/adapter.ts +3 -1
  46. package/src/mcp.ts +28 -8
  47. package/public/assets/chat-0ZbxHlDu.js +0 -2
  48. package/public/assets/chat-0ZbxHlDu.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"chat-0ZbxHlDu.js","names":[],"sources":["../../dashboard/src/lib/slash-commands.ts","../../dashboard/src/components/views/chat.tsx"],"sourcesContent":["// Slash-command catalog for the chat-input autocomplete palette. Dashboard-only\n// UI data (the runner/server never need it), so it lives here rather than in the\n// SDK — which keeps the dashboard build free of a cross-package value dependency.\n\nexport interface SlashCommand {\n name: string\n description?: string\n /** \"builtin\" | \"skill\" — purely for grouping/icons. */\n source?: string\n /** Argument hint shown after the name, e.g. \"<message>\". */\n argumentHint?: string\n}\n\n// Agent Relay slash commands bundled into every managed session (the runner ships\n// these skills for both providers). Exact and stable — sourced from this repo.\nconst RELAY_SLASH_COMMANDS: SlashCommand[] = [\n { name: '/reply', source: 'skill', description: 'Reply to a relay message by id', argumentHint: '<messageId> <body>' },\n { name: '/message', source: 'skill', description: 'Send a relay message to an agent, label, tag, or broadcast', argumentHint: '<target> <body>' },\n { name: '/pair', source: 'skill', description: 'Start or manage a two-agent pair session' },\n { name: '/react', source: 'skill', description: 'Add a reaction to a relay message', argumentHint: '<messageId> <emoji>' },\n { name: '/read-message', source: 'skill', description: 'Fetch a full relay message by id', argumentHint: '<messageId>' },\n { name: '/send-claimable', source: 'skill', description: 'Enqueue a claimable work item for one agent to claim' },\n { name: '/status', source: 'skill', description: \"Show this agent's relay status\" },\n { name: '/tags', source: 'skill', description: \"List or update this agent's relay tags\" },\n { name: '/label', source: 'skill', description: \"Read, set, or clear this agent's relay label\" },\n { name: '/disconnect', source: 'skill', description: 'End the current relay pair session' },\n]\n\n// Stable provider built-ins. Deliberately conservative — only commands known to\n// exist across versions of each provider — so the palette never offers a command\n// that isn't there. Project/skill commands are grown in organically later.\nconst CLAUDE_BUILTIN_SLASH_COMMANDS: SlashCommand[] = [\n { name: '/clear', source: 'builtin', description: 'Clear conversation history and free up context' },\n { name: '/compact', source: 'builtin', description: 'Compact the conversation to reclaim context', argumentHint: '[instructions]' },\n { name: '/model', source: 'builtin', description: 'Switch the active model', argumentHint: '[model]' },\n { name: '/help', source: 'builtin', description: 'Show help' },\n]\n\nconst CODEX_BUILTIN_SLASH_COMMANDS: SlashCommand[] = [\n { name: '/compact', source: 'builtin', description: 'Compact the conversation to reclaim context' },\n { name: '/new', source: 'builtin', description: 'Start a new thread' },\n]\n\n/** Slash-command catalog for a provider's chat-input autocomplete palette. */\nexport function providerSlashCommands(provider: string | undefined): SlashCommand[] {\n const builtins = provider === 'claude' ? CLAUDE_BUILTIN_SLASH_COMMANDS\n : provider === 'codex' ? CODEX_BUILTIN_SLASH_COMMANDS\n : []\n return [...builtins, ...RELAY_SLASH_COMMANDS]\n}\n","import { memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'\nimport { useRelayStore, useNow, type ChatStatusEvent as StatusEvent } from '@/store'\nimport { useAllInboxThreads, useUniqueHosts } from '@/hooks/use-selectors'\nimport { useAgentTerminal } from '@/hooks/use-agent-terminal'\nimport { useKeyboardViewportHeight } from '@/hooks/use-keyboard-viewport'\nimport { FormattedBody } from '@/components/shared/formatted-body'\nimport { StatusDot } from '@/components/shared/status-dot'\nimport { AgentTypeIcon } from '@/components/shared/agent-type-icon'\nimport { AgentRuntimeChips, ContextRing, agentWorkspaceMeta, agentProjectName } from '@/components/shared/agent-runtime-summary'\nimport { BranchStateBadge } from '@/components/shared/branch-state-badge'\nimport { TerminalDialog } from '@/components/shared/terminal-viewer'\nimport { CopyButton } from '@/components/shared/copy-button'\nimport { DirectoryContent, FileContent } from '@/components/views/files'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Textarea } from '@/components/ui/textarea'\nimport {\n displayName, visibleAgents, agentType, messageBody, messagePreview,\n toTimestamp, timeAgo, fmtTime, userFacingCapabilities, providerBlockedState, shortPath,\n agentSupportsControlAction, isReactionEventMessage, normalizeReactionEmoji, inboxPeer,\n normalizePathForCompare, pathWithinBase, responseBodyContainsBlock,\n} from '@/lib/display'\nimport type { ProviderPendingApproval, ProviderQuestion } from '@/lib/display'\nimport { CHAT_STATUS_SORT_ORDER, HUMAN_AGENT_ID } from '@/lib/constants'\nimport {\n Search, Send, MailOpen, MailX, Download,\n MessageSquare, Bot, SortAsc, SortDesc, ArrowLeft,\n Circle, Paperclip, X, FileText, Loader2, AlertCircle,\n Clock, Check, CheckCheck, ZoomIn, FolderOpen,\n Terminal, Minimize2, Eraser, Power, MoreHorizontal, Plus, GitFork, SmilePlus,\n ChevronLeft, ChevronRight, ChevronUp, ChevronDown, MessageCircleQuestion, Brain, CircleStop, ListChecks,\n Volume2, VolumeX, Mic, SlidersHorizontal, Flag,\n} from 'lucide-react'\nimport { createPortal } from 'react-dom'\nimport { voiceTts, micAvailable, PttRecorder, transcribeClip } from '@/lib/voice'\nimport { Dialog, DialogContent, DialogTitle } from '@/components/ui/dialog'\nimport { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'\nimport { api, apiBlob, apiUpload } from '@/lib/api'\nimport type { Agent, Artifact, AttachmentRef, ChatHistoryImport, ChatHistoryImportEntry, FileStatResult, InboxThread, Message, Orchestrator } from '@/types'\nimport { providerSlashCommands } from '@/lib/slash-commands'\nimport type { SlashCommand } from '@/lib/slash-commands'\nimport { cn } from '@/lib/utils'\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\ninterface PendingAttachment {\n id: string\n fileName: string\n size: number\n previewUrl?: string\n artifact?: Artifact\n error?: string\n uploading: boolean\n}\n\ninterface ReferencedPathInfo {\n orchestratorId: string\n path: string\n type: 'file' | 'directory'\n}\n\nfunction formatBytes(size: number): string {\n if (size < 1024) return `${size} B`\n if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)} KB`\n return `${(size / 1024 / 1024).toFixed(1)} MB`\n}\n\nfunction resolveRelativePath(cwd: string, path: string): string {\n if (path.startsWith('/')) return path\n const parts = `${cwd.replace(/\\/+$/, '')}/${path}`.split('/')\n const stack: string[] = []\n for (const part of parts) {\n if (!part || part === '.') continue\n if (part === '..') stack.pop()\n else stack.push(part)\n }\n return '/' + stack.join('/')\n}\n\nfunction parentPath(path: string): string {\n const trimmed = path.replace(/\\/+$/, '')\n const index = trimmed.lastIndexOf('/')\n return index > 0 ? trimmed.slice(0, index) : '/'\n}\n\nfunction orchestratorForFilePreview(orchestrators: Orchestrator[], path: string): Orchestrator | undefined {\n return orchestrators\n .filter((orch) => orch.status === 'online' && pathWithinBase(path, orch.baseDir))\n .sort((a, b) => normalizePathForCompare(b.baseDir).length - normalizePathForCompare(a.baseDir).length)[0] ||\n orchestrators.find((orch) => orch.status === 'online')\n}\n\nfunction supportsSideFilePreview(): boolean {\n return typeof window !== 'undefined' && window.matchMedia('(min-width: 1280px)').matches\n}\n\nfunction hasActiveTextSelection(): boolean {\n return typeof window !== 'undefined' && Boolean(window.getSelection()?.toString())\n}\n\nfunction messageAttachments(msg: Message): AttachmentRef[] {\n const attachments = msg.payload?.attachments\n if (!Array.isArray(attachments)) return []\n return attachments.filter((item): item is AttachmentRef => Boolean(item && typeof item === 'object' && typeof (item as AttachmentRef).artifactId === 'string'))\n}\n\nconst QUICK_REACTIONS = ['👍', '❤️', '✅', '👀'] as const\n\nfunction groupedReactions(msg: Message): Array<{ emoji: string; count: number; mine: boolean; actors: string[] }> {\n const groups = new Map<string, { emoji: string; count: number; mine: boolean; actors: string[] }>()\n for (const reaction of msg.reactions || []) {\n const emoji = normalizeReactionEmoji(reaction.emoji)\n const current = groups.get(emoji) ?? { emoji, count: 0, mine: false, actors: [] }\n current.count += 1\n current.mine = current.mine || reaction.actorId === HUMAN_AGENT_ID\n current.actors.push(reaction.actorId)\n groups.set(emoji, current)\n }\n return [...groups.values()].sort((a, b) => b.count - a.count || a.emoji.localeCompare(b.emoji))\n}\n\nfunction isReactionEvent(msg: Message): boolean {\n return isReactionEventMessage(msg)\n}\n\nfunction outboundReceipt(msg: Message, peer: string): { label: string; title: string; tone: 'muted' | 'ok' | 'warn' | 'danger'; icon: typeof Check } {\n const readBy = msg.readBy || []\n const expectedReader = msg.resolvedToAgent || peer || msg.to\n const readByExpected = expectedReader ? readBy.includes(expectedReader) : false\n const readBySomeone = readBy.some((id) => id !== HUMAN_AGENT_ID)\n if (readByExpected || readBySomeone) {\n const reader = readByExpected ? expectedReader : readBy.find((id) => id !== HUMAN_AGENT_ID)\n return { label: 'read', title: reader ? `Read by ${reader}` : 'Read by agent', tone: 'ok', icon: CheckCheck }\n }\n if (msg.deliveryStatus === 'delivered') {\n return { label: 'delivered', title: 'Delivered to agent inbox', tone: 'ok', icon: CheckCheck }\n }\n if (msg.deliveryStatus === 'queued') {\n return { label: 'queued', title: 'Queued until the target agent is available', tone: 'warn', icon: Clock }\n }\n if (msg.deliveryStatus === 'failed' || msg.deliveryStatus === 'dead') {\n const detail = msg.deliveryPoisonReason || msg.deliveryLastError || msg.deliveryStatus\n return { label: msg.deliveryStatus, title: detail, tone: 'danger', icon: AlertCircle }\n }\n return { label: 'sent', title: 'Accepted by Relay', tone: 'muted', icon: Check }\n}\n\nfunction messageActivityTimestamp(msg: Message): number {\n const messageAt = toTimestamp(msg.createdAt)\n return (msg.reactions || []).reduce((latest, reaction) => {\n return Math.max(latest, toTimestamp(reaction.updatedAt || reaction.createdAt))\n }, messageAt)\n}\n\nfunction threadActivityTimestamp(thread: InboxThread | undefined): number {\n if (!thread) return 0\n return thread.messages.reduce((latest, msg) => Math.max(latest, messageActivityTimestamp(msg)), 0)\n}\n\n// ─── Agent list hook ─────────────────────────────────────────────────────────\n\nfunction useChatAgents() {\n const agents = useRelayStore((s) => s.agents)\n const showBuiltIns = useRelayStore((s) => s.showBuiltIns)\n const showOffline = useRelayStore((s) => s.showOffline)\n const chatAgentSearch = useRelayStore((s) => s.chatAgentSearch)\n const chatAgentProviderFilter = useRelayStore((s) => s.chatAgentProviderFilter)\n const chatAgentStatusFilter = useRelayStore((s) => s.chatAgentStatusFilter)\n const chatAgentTagFilter = useRelayStore((s) => s.chatAgentTagFilter)\n const chatAgentCapFilter = useRelayStore((s) => s.chatAgentCapFilter)\n const chatAgentHostFilter = useRelayStore((s) => s.chatAgentHostFilter)\n const chatAgentSort = useRelayStore((s) => s.chatAgentSort)\n const chatAgentSortDir = useRelayStore((s) => s.chatAgentSortDir)\n const managedPolicies = useRelayStore((s) => s.managedPolicies)\n\n return useMemo(() => {\n let list = visibleAgents(agents, showBuiltIns, managedPolicies)\n if (!showOffline) list = list.filter((a) => a.status !== 'offline')\n\n if (chatAgentSearch) {\n const q = chatAgentSearch.toLowerCase()\n list = list.filter((a) =>\n a.id.toLowerCase().includes(q) ||\n (a.name || '').toLowerCase().includes(q) ||\n (a.label || '').toLowerCase().includes(q) ||\n (a.tags || []).some((t) => t.toLowerCase().includes(q)) ||\n (a.capabilities || []).some((c) => c.toLowerCase().includes(q))\n )\n }\n\n if (chatAgentProviderFilter) list = list.filter((a) => agentType(a) === chatAgentProviderFilter)\n if (chatAgentStatusFilter) list = list.filter((a) => a.status === chatAgentStatusFilter)\n if (chatAgentTagFilter) list = list.filter((a) => (a.tags || []).includes(chatAgentTagFilter))\n if (chatAgentCapFilter) list = list.filter((a) => (a.capabilities || []).includes(chatAgentCapFilter))\n if (chatAgentHostFilter) list = list.filter((a) => (a.machine || '') === chatAgentHostFilter)\n\n const dir = chatAgentSortDir === 'desc' ? -1 : 1\n return [...list].sort((a, b) => {\n if (chatAgentSort === 'name') return displayName(a).localeCompare(displayName(b)) * dir\n if (chatAgentSort === 'lastSeen') return (toTimestamp(b.lastSeen) - toTimestamp(a.lastSeen)) * dir || displayName(a).localeCompare(displayName(b))\n const s = ((CHAT_STATUS_SORT_ORDER[a.status] ?? 9) - (CHAT_STATUS_SORT_ORDER[b.status] ?? 9)) * dir\n return s || displayName(a).localeCompare(displayName(b))\n })\n }, [agents, showBuiltIns, showOffline, managedPolicies, chatAgentSearch, chatAgentProviderFilter,\n chatAgentStatusFilter, chatAgentTagFilter, chatAgentCapFilter, chatAgentHostFilter, chatAgentSort, chatAgentSortDir])\n}\n\n// ─── Status events from persistent store ────────────────────────────────────\n\nconst NO_STATUS_EVENTS: StatusEvent[] = []\nconst NO_THREAD_HISTORY: Message[] = []\n\nfunction useAgentStatusEvents(agentId: string): StatusEvent[] {\n return useRelayStore((s) => s.chatStatusEvents[agentId] ?? NO_STATUS_EVENTS)\n}\n\n// ─── Back navigation protection ──────────────────────────────────────────────\n\nfunction useBackNavProtection(hasDraft: boolean, onBack: () => void) {\n const historyPushedRef = useRef(false)\n\n useEffect(() => {\n if (!hasDraft) return\n\n if (!historyPushedRef.current) {\n window.history.pushState({ chatGuard: true }, '')\n historyPushedRef.current = true\n }\n\n function handlePopState(e: PopStateEvent) {\n if (e.state?.chatGuard !== undefined || !historyPushedRef.current) {\n // Re-push state to keep the guard active\n window.history.pushState({ chatGuard: true }, '')\n onBack()\n }\n }\n\n function handleBeforeUnload(e: BeforeUnloadEvent) {\n e.preventDefault()\n }\n\n window.addEventListener('popstate', handlePopState)\n window.addEventListener('beforeunload', handleBeforeUnload)\n return () => {\n window.removeEventListener('popstate', handlePopState)\n window.removeEventListener('beforeunload', handleBeforeUnload)\n }\n }, [hasDraft, onBack])\n\n useEffect(() => {\n if (!hasDraft && historyPushedRef.current) {\n historyPushedRef.current = false\n }\n }, [hasDraft])\n}\n\n// ─── Draft cleanup for removed agents ────────────────────────────────────────\n\nfunction useDraftCleanup() {\n const inboxDrafts = useRelayStore((s) => s.inboxDrafts)\n const agentsById = useRelayStore((s) => s.agentsById)\n const set = useRelayStore((s) => s.set)\n\n useEffect(() => {\n const draftPeers = Object.keys(inboxDrafts)\n if (draftPeers.length === 0) return\n\n const stale = draftPeers.filter((peer) => !agentsById[peer] && peer !== HUMAN_AGENT_ID)\n if (stale.length === 0) return\n\n // Only clean up if the agent has been gone for a reasonable time (check on mount only)\n const timer = setTimeout(() => {\n const currentAgents = useRelayStore.getState().agentsById\n const next = { ...useRelayStore.getState().inboxDrafts }\n let changed = false\n for (const peer of stale) {\n if (!currentAgents[peer]) {\n delete next[peer]\n changed = true\n }\n }\n if (changed) set({ inboxDrafts: next })\n }, 30_000) // 30s grace period before purging\n\n return () => clearTimeout(timer)\n }, [])\n}\n\n// ─── Auto-growing textarea ───────────────────────────────────────────────────\n\nfunction AutoGrowTextarea({\n value, onChange, onKeyDown, onPaste, placeholder, className,\n}: {\n value: string\n onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void\n onKeyDown: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void\n onPaste?: (e: React.ClipboardEvent<HTMLTextAreaElement>) => void\n placeholder: string\n className?: string\n}) {\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n\n useEffect(() => {\n const el = textareaRef.current\n if (!el) return\n el.style.height = 'auto'\n el.style.height = Math.min(el.scrollHeight, 200) + 'px'\n }, [value])\n\n // Handle mobile keyboard: keep input visible\n useEffect(() => {\n const vv = window.visualViewport\n if (!vv) return\n\n function handleResize() {\n const el = textareaRef.current\n if (!el || document.activeElement !== el) return\n // Scroll the input into view when keyboard appears\n requestAnimationFrame(() => {\n el.scrollIntoView({ block: 'nearest', behavior: 'smooth' })\n })\n }\n\n vv.addEventListener('resize', handleResize)\n return () => vv.removeEventListener('resize', handleResize)\n }, [])\n\n return (\n <textarea\n ref={textareaRef}\n value={value}\n onChange={onChange}\n onKeyDown={onKeyDown}\n onPaste={onPaste}\n placeholder={placeholder}\n rows={1}\n className={cn(\n 'w-full resize-none rounded-xl border border-border bg-background px-3.5 py-2.5 text-sm',\n 'placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring',\n 'min-h-[42px] max-h-[200px] overflow-y-auto',\n className\n )}\n />\n )\n}\n\n// ─── Left panel: agent list ──────────────────────────────────────────────────\n\nfunction AgentListPanel({ threads, onSelectAgent }: { threads: InboxThread[]; onSelectAgent?: (id: string) => void }) {\n const set = useRelayStore((s) => s.set)\n const openInboxThread = useRelayStore((s) => s.openInboxThread)\n const openAgentSpawn = useRelayStore((s) => s.openAgentSpawn)\n const selectedInboxThread = useRelayStore((s) => s.selectedInboxThread)\n const chatAgentSearch = useRelayStore((s) => s.chatAgentSearch)\n const chatAgentSort = useRelayStore((s) => s.chatAgentSort)\n const chatAgentSortDir = useRelayStore((s) => s.chatAgentSortDir)\n const chatAgentProviderFilter = useRelayStore((s) => s.chatAgentProviderFilter)\n const chatAgentStatusFilter = useRelayStore((s) => s.chatAgentStatusFilter)\n const chatAgentTagFilter = useRelayStore((s) => s.chatAgentTagFilter)\n const chatAgentCapFilter = useRelayStore((s) => s.chatAgentCapFilter)\n const chatAgentHostFilter = useRelayStore((s) => s.chatAgentHostFilter)\n const chatAgentGroupBy = useRelayStore((s) => s.chatAgentGroupBy)\n const chatAgentFiltersCollapsed = useRelayStore((s) => s.chatAgentFiltersCollapsed)\n const now = useNow()\n const chatAgents = useChatAgents()\n\n const threadByPeer = useMemo(() => {\n const m = new Map<string, InboxThread>()\n for (const t of threads) m.set(t.peer, t)\n return m\n }, [threads])\n\n const sortedAgents = useMemo(() => {\n if (chatAgentSort !== 'lastMessage') return chatAgents\n const dir = chatAgentSortDir === 'desc' ? -1 : 1\n return [...chatAgents].sort((a, b) => {\n const ta = threadActivityTimestamp(threadByPeer.get(a.id))\n const tb = threadActivityTimestamp(threadByPeer.get(b.id))\n return (tb - ta) * dir || displayName(a).localeCompare(displayName(b))\n })\n }, [chatAgents, chatAgentSort, chatAgentSortDir, threadByPeer])\n\n const uniqueTags = useMemo(() => [...new Set(chatAgents.flatMap((a) => a.tags || []))], [chatAgents])\n const uniqueCaps = useMemo(() => [...new Set(chatAgents.flatMap((a) => userFacingCapabilities(a.capabilities || [])))], [chatAgents])\n const uniqueHosts = useUniqueHosts()\n\n // Group the (already sorted) agents by project, preserving sort order within\n // each group. null when grouping is off → render a flat list.\n const groupedAgents = useMemo(() => {\n if (chatAgentGroupBy !== 'project') return null\n const groups = new Map<string, Agent[]>()\n for (const a of sortedAgents) {\n const key = agentProjectName(a) || 'No project'\n const bucket = groups.get(key)\n if (bucket) bucket.push(a)\n else groups.set(key, [a])\n }\n return [...groups.entries()].sort((a, b) => a[0].localeCompare(b[0]))\n }, [sortedAgents, chatAgentGroupBy])\n\n const activeFilterCount = [chatAgentProviderFilter, chatAgentStatusFilter, chatAgentTagFilter, chatAgentCapFilter, chatAgentHostFilter].filter(Boolean).length\n\n function handleSelect(id: string) {\n openInboxThread(id, threadByPeer.get(id)?.messages)\n onSelectAgent?.(id)\n }\n\n function renderAgentRow(agent: Agent) {\n const thread = threadByPeer.get(agent.id)\n const unread = thread?.attention.unread || 0\n const lastMsg = thread?.previewMessage\n const lastActivityAt = threadActivityTimestamp(thread)\n const isSelected = selectedInboxThread === agent.id\n const ws = agentWorkspaceMeta(agent)\n const project = agentProjectName(agent)\n const WsIcon = ws.Icon\n\n return (\n <li key={agent.id}>\n <button\n className={cn(\n 'w-full text-left px-3 py-2.5 flex items-start gap-2.5 hover:bg-muted/50 transition-colors border-b border-border/50',\n isSelected && 'bg-muted/60'\n )}\n onClick={() => handleSelect(agent.id)}\n >\n <div className=\"relative shrink-0 mt-0.5\">\n <AgentTypeIcon agent={agent} />\n <StatusDot agent={agent} now={now} className=\"absolute -bottom-0.5 -right-0.5 w-2 h-2\" />\n </div>\n\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center justify-between gap-1 mb-0.5\">\n <span className=\"text-xs font-medium truncate\">{displayName(agent)}</span>\n <div className=\"flex items-center gap-1 shrink-0\">\n {lastActivityAt > 0 && (\n <span className=\"text-[10px] text-muted-foreground\" title={fmtTime(lastActivityAt)}>\n {timeAgo(now, lastActivityAt)}\n </span>\n )}\n {unread > 0 && (\n <Badge className=\"bg-red-500 text-white text-xs min-w-[18px] h-[18px] flex items-center justify-center shrink-0 px-1\">\n {unread}\n </Badge>\n )}\n </div>\n </div>\n\n {/* Workspace icon + project name, with context usage on the right */}\n <div className=\"flex items-center gap-1.5 mb-0.5 text-[10px] text-muted-foreground\">\n <span title={ws.title} className=\"inline-flex shrink-0\">\n <WsIcon className={cn('h-3 w-3', ws.iconColor)} />\n </span>\n <span className=\"truncate\">{project || ws.label}</span>\n {agent.context && (\n <span className=\"ml-auto shrink-0\">\n <ContextRing utilization={agent.context.utilization} size={18} />\n </span>\n )}\n </div>\n\n {lastMsg && (\n <p className=\"text-xs text-muted-foreground truncate leading-tight\">\n {lastMsg.from === HUMAN_AGENT_ID ? 'You: ' : ''}\n {messagePreview(lastMsg)}\n </p>\n )}\n\n {agent.status !== 'offline' && (\n <div className=\"mt-1\">\n <span className={cn('text-xs', agent.status === 'busy' ? 'text-yellow-400' : 'text-emerald-400')}>\n {agent.status}\n </span>\n </div>\n )}\n </div>\n </button>\n </li>\n )\n }\n\n return (\n <div className=\"flex flex-col h-full border-r border-border min-w-0\">\n {/* Search + filters */}\n <div className=\"p-3 border-b border-border space-y-2\">\n <div className=\"relative\">\n <Search className=\"absolute left-2.5 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted-foreground pointer-events-none\" />\n <Input\n placeholder=\"Search agents...\"\n value={chatAgentSearch}\n onChange={(e) => set({ chatAgentSearch: e.target.value })}\n className=\"pl-8 h-7 text-xs\"\n />\n </div>\n\n {/* Filters toggle — mobile only; on desktop the panel is always open */}\n <button\n type=\"button\"\n onClick={() => set({ chatAgentFiltersCollapsed: !chatAgentFiltersCollapsed })}\n className=\"sm:hidden flex w-full items-center justify-between h-6 px-1.5 text-xs rounded-md border border-border bg-background text-muted-foreground\"\n >\n <span className=\"inline-flex items-center gap-1.5\">\n <SlidersHorizontal className=\"w-3.5 h-3.5\" />\n Filters &amp; sort\n {activeFilterCount > 0 && (\n <Badge className=\"bg-primary/20 text-primary text-[10px] h-4 min-w-4 px-1 flex items-center justify-center\">{activeFilterCount}</Badge>\n )}\n </span>\n {chatAgentFiltersCollapsed ? <ChevronDown className=\"w-3.5 h-3.5\" /> : <ChevronUp className=\"w-3.5 h-3.5\" />}\n </button>\n\n <div className={cn('space-y-2', chatAgentFiltersCollapsed ? 'hidden' : 'block', 'sm:block')}>\n {/* Sort row */}\n <div className=\"flex items-center gap-1.5\">\n <select\n value={chatAgentSort}\n onChange={(e) => set({ chatAgentSort: e.target.value })}\n className=\"flex-1 h-6 text-xs rounded-md border border-border bg-background px-1.5 text-foreground\"\n >\n <option value=\"status\">By status</option>\n <option value=\"name\">By name</option>\n <option value=\"lastSeen\">By last seen</option>\n <option value=\"lastMessage\">By last activity</option>\n </select>\n <Button\n variant=\"ghost\"\n size=\"icon-xs\"\n onClick={() => set({ chatAgentSortDir: chatAgentSortDir === 'asc' ? 'desc' : 'asc' })}\n >\n {chatAgentSortDir === 'asc' ? <SortAsc className=\"w-3.5 h-3.5\" /> : <SortDesc className=\"w-3.5 h-3.5\" />}\n </Button>\n </div>\n\n {/* Grouping */}\n <select\n value={chatAgentGroupBy}\n onChange={(e) => set({ chatAgentGroupBy: e.target.value })}\n className=\"w-full h-6 text-xs rounded-md border border-border bg-background px-1.5 text-foreground\"\n >\n <option value=\"\">No grouping</option>\n <option value=\"project\">Group by project</option>\n </select>\n\n {/* Filter row */}\n <div className=\"flex gap-1\">\n <select\n value={chatAgentProviderFilter}\n onChange={(e) => set({ chatAgentProviderFilter: e.target.value })}\n className=\"flex-1 h-6 text-xs rounded-md border border-border bg-background px-1.5 text-foreground\"\n >\n <option value=\"\">All types</option>\n <option value=\"claude\">Claude</option>\n <option value=\"codex\">Codex</option>\n <option value=\"agent\">Agent</option>\n <option value=\"user\">User</option>\n </select>\n <select\n value={chatAgentStatusFilter}\n onChange={(e) => set({ chatAgentStatusFilter: e.target.value })}\n className=\"flex-1 h-6 text-xs rounded-md border border-border bg-background px-1.5 text-foreground\"\n >\n <option value=\"\">All status</option>\n <option value=\"online\">Online</option>\n <option value=\"idle\">Idle</option>\n <option value=\"busy\">Busy</option>\n <option value=\"offline\">Offline</option>\n </select>\n {uniqueHosts.length > 1 && (\n <select\n value={chatAgentHostFilter}\n onChange={(e) => set({ chatAgentHostFilter: e.target.value })}\n className=\"flex-1 h-6 text-xs rounded-md border border-border bg-background px-1.5 text-foreground\"\n >\n <option value=\"\">All hosts</option>\n {uniqueHosts.map((h) => <option key={h} value={h}>{h}</option>)}\n </select>\n )}\n </div>\n\n {(uniqueTags.length > 0 || uniqueCaps.length > 0) && (\n <div className=\"flex gap-1\">\n {uniqueTags.length > 0 && (\n <select\n value={chatAgentTagFilter}\n onChange={(e) => set({ chatAgentTagFilter: e.target.value })}\n className=\"flex-1 h-6 text-xs rounded-md border border-border bg-background px-1.5 text-foreground\"\n >\n <option value=\"\">All tags</option>\n {uniqueTags.map((t) => <option key={t} value={t}>#{t}</option>)}\n </select>\n )}\n {uniqueCaps.length > 0 && (\n <select\n value={chatAgentCapFilter}\n onChange={(e) => set({ chatAgentCapFilter: e.target.value })}\n className=\"flex-1 h-6 text-xs rounded-md border border-border bg-background px-1.5 text-foreground\"\n >\n <option value=\"\">All caps</option>\n {uniqueCaps.map((c) => <option key={c} value={c}>{c}</option>)}\n </select>\n )}\n </div>\n )}\n </div>\n </div>\n\n {/* Spawn — pinned above the list so it never scrolls out of reach */}\n <button\n type=\"button\"\n className=\"flex w-full shrink-0 items-center gap-2.5 border-b border-border px-3 py-2 text-left transition-colors hover:bg-muted/50\"\n onClick={openAgentSpawn}\n >\n <div className=\"flex h-7 w-7 shrink-0 items-center justify-center rounded-full border border-dashed border-primary/50 bg-primary/10 text-primary\">\n <Plus className=\"h-3.5 w-3.5\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-xs font-medium\">New Agent</div>\n <div className=\"truncate text-[10px] text-muted-foreground\">Spawn a fresh chat agent</div>\n </div>\n </button>\n\n {/* Agent list */}\n <div className=\"flex-1 overflow-y-auto\">\n {sortedAgents.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-10 text-center px-4\">\n <Bot className=\"w-8 h-8 text-zinc-600 mb-2\" />\n <p className=\"text-xs text-muted-foreground\">No agents match filters</p>\n </div>\n ) : groupedAgents ? (\n groupedAgents.map(([project, agents]) => (\n <div key={project}>\n <div className=\"sticky top-0 z-10 flex items-center gap-1.5 border-b border-border/50 bg-background/95 px-3 py-1 text-[10px] font-medium uppercase tracking-wide text-muted-foreground backdrop-blur\">\n <span className=\"truncate\">{project}</span>\n <span className=\"text-muted-foreground/50\">{agents.length}</span>\n </div>\n <ul>{agents.map(renderAgentRow)}</ul>\n </div>\n ))\n ) : (\n <ul>{sortedAgents.map(renderAgentRow)}</ul>\n )}\n </div>\n </div>\n )\n}\n\n// ─── Status event marker ─────────────────────────────────────────────────────\n\n// ─── Timestamp formatting ────────────────────────────────────────────────────\n\nfunction chatTimestamp(iso: string | number): string {\n const d = new Date(iso as string)\n return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n}\n\n// True event time of a message: occurredAt (set when a Runner backfilled a message it had\n// queued during an outage, #196) falling back to the server receive time. Used for chat\n// timeline ordering + display so a backfilled turn lands where it actually happened in the\n// conversation, not at the bottom. Display-only — DB poll cursors still use created_at.\nfunction messageEventTime(msg: Message): number {\n return new Date(msg.occurredAt ?? msg.createdAt).getTime()\n}\n\nfunction dateSeparatorLabel(dateStr: string): string {\n const today = new Date()\n const [y, m, d] = dateStr.split('-').map(Number)\n const target = new Date(y!, m! - 1, d)\n const todayKey = dateKey(today.getTime())\n if (dateStr === todayKey) return 'Today'\n const yesterday = new Date(today)\n yesterday.setDate(yesterday.getDate() - 1)\n if (dateStr === dateKey(yesterday.getTime())) return 'Yesterday'\n return target.toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric', year: target.getFullYear() !== today.getFullYear() ? 'numeric' : undefined })\n}\n\n// ─── Status, date, and created markers ──────────────────────────────────────\n\nconst TIMELINE_STATUS_COLORS: Record<string, string> = {\n online: 'text-emerald-400',\n offline: 'text-zinc-400',\n shutdown: 'text-zinc-400',\n restarted: 'text-blue-400',\n 'compaction-requested': 'text-zinc-400',\n compacting: 'text-amber-400',\n compacted: 'text-amber-400',\n 'compaction-stalled': 'text-red-400',\n 'clear-requested': 'text-zinc-400',\n 'clearing-context': 'text-amber-400',\n 'context-cleared': 'text-amber-400',\n 'clear-stalled': 'text-red-400',\n 'shutting-down': 'text-zinc-400',\n}\n\nconst TIMELINE_STATUS_LABELS: Record<string, string> = {\n online: 'came online',\n offline: 'went offline',\n shutdown: 'shut down',\n restarted: 'restarted',\n 'compaction-requested': 'compaction requested',\n compacting: 'compaction started',\n compacted: 'context compacted',\n 'compaction-stalled': 'compaction stalled — may need manual intervention',\n 'clear-requested': 'clear requested',\n 'clearing-context': 'clear started',\n 'context-cleared': 'context cleared',\n 'clear-stalled': 'context clear stalled — may need manual intervention',\n 'shutting-down': 'shutting down',\n}\n\nconst TIMELINE_STATUSES = new Set(Object.keys(TIMELINE_STATUS_LABELS))\nconst STATUS_DEDUPE_WINDOW_MS = 3000\nconst CHAT_BOTTOM_THRESHOLD_PX = 96\n\nfunction StatusMarker({ event }: { event: StatusEvent }) {\n return (\n <div className=\"flex items-center justify-center gap-2 py-2 my-1\">\n <div className=\"h-px flex-1 bg-border\" />\n <div className=\"flex items-center gap-1.5 text-xs text-muted-foreground\">\n <Circle className={cn('w-2 h-2 fill-current', TIMELINE_STATUS_COLORS[event.status] || 'text-zinc-400')} />\n <span>{TIMELINE_STATUS_LABELS[event.status] || event.status}</span>\n <span className=\"text-muted-foreground/60\">{chatTimestamp(event.timestamp)}</span>\n </div>\n <div className=\"h-px flex-1 bg-border\" />\n </div>\n )\n}\n\nfunction BusyIndicator({ blockedLabel, onInterrupt }: { blockedLabel?: string; onInterrupt?: () => void }) {\n if (blockedLabel) {\n return (\n <div className=\"flex justify-start mb-3\">\n <div className=\"flex items-center gap-2 rounded-2xl rounded-bl-sm bg-card ring-1 ring-red-500/30 px-4 py-2.5\">\n <AlertCircle className=\"w-3.5 h-3.5 text-red-400\" />\n <span className=\"text-xs text-red-300\">blocked: {blockedLabel}</span>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"flex justify-start mb-3\">\n <div className=\"flex items-center gap-2 rounded-2xl rounded-bl-sm bg-card ring-1 ring-foreground/10 px-4 py-2.5\">\n <div className=\"flex items-center gap-1\">\n <span className=\"w-1.5 h-1.5 rounded-full bg-yellow-400 animate-[pulse_1.4s_ease-in-out_infinite]\" />\n <span className=\"w-1.5 h-1.5 rounded-full bg-yellow-400 animate-[pulse_1.4s_ease-in-out_0.2s_infinite]\" />\n <span className=\"w-1.5 h-1.5 rounded-full bg-yellow-400 animate-[pulse_1.4s_ease-in-out_0.4s_infinite]\" />\n </div>\n <span className=\"text-xs text-muted-foreground\">working</span>\n {onInterrupt && (\n <button\n onClick={onInterrupt}\n title=\"Interrupt\"\n className=\"ml-1 flex items-center gap-1 rounded-full px-1.5 py-0.5 text-xs text-muted-foreground hover:text-red-300 hover:bg-red-500/10 transition-colors\"\n >\n <CircleStop className=\"w-3.5 h-3.5\" />\n Stop\n </button>\n )}\n </div>\n </div>\n )\n}\n\n// \"Hide tool steps\" is a viewer preference, not per-turn UI: persist it in\n// localStorage and share one value across every ActivityTrace (and browser tab),\n// so toggling on one turn folds them all and the choice survives a reload.\nconst HIDE_TOOLS_KEY = 'agent-relay:chat-hide-tools'\nconst hideToolsStore = (() => {\n const listeners = new Set<() => void>()\n let value = (() => {\n try {\n return window.localStorage.getItem(HIDE_TOOLS_KEY) === 'on'\n } catch {\n return false\n }\n })()\n const emit = () => listeners.forEach((l) => l())\n if (typeof window !== 'undefined') {\n window.addEventListener('storage', (e) => {\n if (e.key !== HIDE_TOOLS_KEY) return\n value = e.newValue === 'on'\n emit()\n })\n }\n return {\n subscribe(cb: () => void) {\n listeners.add(cb)\n return () => listeners.delete(cb)\n },\n get: () => value,\n toggle() {\n value = !value\n try {\n window.localStorage.setItem(HIDE_TOOLS_KEY, value ? 'on' : 'off')\n } catch {}\n emit()\n },\n }\n})()\n\nfunction useHideTools(): [boolean, () => void] {\n const hideTools = useSyncExternalStore(hideToolsStore.subscribe, hideToolsStore.get, () => false)\n return [hideTools, hideToolsStore.toggle]\n}\n\n// Live trace of a turn, in transcript order — the agent's narration (\"I'll read X\")\n// sits right next to the tool call it drives. Never a chat bubble. Narration is the\n// primary, always-visible content (the terminal's `●` lines); reasoning (the agent's\n// thinking) is hidden unless the viewer opts in via Settings; tool steps render\n// compactly in place and fold away on demand. Derived purely from messages.\nfunction ActivityTrace({ steps, showReasoning }: { steps: ActivityStep[]; showReasoning: boolean }) {\n const [hideTools, toggleHideTools] = useHideTools()\n const visible = showReasoning ? steps : steps.filter((s) => s.kind !== 'reasoning')\n if (!visible.length) return null\n const toolCount = visible.filter((s) => s.kind === 'tool').length\n return (\n <div className=\"flex justify-start mb-2\">\n <div className=\"max-w-[85%] md:max-w-[75%] min-w-0 space-y-1.5\">\n {visible.map((step) => {\n if (step.kind === 'narration') {\n return (\n <div key={step.id} className=\"text-sm leading-relaxed whitespace-pre-wrap break-words text-foreground/90 min-w-0\">\n {step.text}\n </div>\n )\n }\n if (step.kind === 'reasoning') {\n return (\n <div key={step.id} className=\"flex items-start gap-1.5 text-xs leading-relaxed text-muted-foreground/80\">\n <Brain className=\"w-3.5 h-3.5 mt-0.5 shrink-0 opacity-70\" />\n <span className=\"italic whitespace-pre-wrap break-words min-w-0\">{step.text}</span>\n </div>\n )\n }\n if (hideTools) return null\n return (\n <div key={step.id} className=\"flex items-start gap-1.5 text-xs leading-relaxed text-muted-foreground\">\n <Terminal className=\"w-3 h-3 mt-0.5 shrink-0 opacity-70\" />\n <span className=\"min-w-0 break-words\">\n <span className=\"font-medium\">{step.label || 'tool'}</span>\n {step.text ? <span className=\"opacity-70\"> — {step.text}</span> : null}\n </span>\n </div>\n )\n })}\n {toolCount > 0 && (\n <button\n onClick={toggleHideTools}\n className=\"flex items-center gap-1 text-[11px] text-muted-foreground/50 hover:text-muted-foreground transition-colors text-left\"\n >\n <ChevronRight className={cn('w-3 h-3 shrink-0 transition-transform', !hideTools && 'rotate-90')} />\n <span>{hideTools ? `show ${toolCount} tool step${toolCount === 1 ? '' : 's'}` : 'hide tool steps'}</span>\n </button>\n )}\n </div>\n </div>\n )\n}\n\nfunction PermissionRequestBubble({ agentId, approval }: { agentId: string; approval?: ProviderPendingApproval }) {\n const sendPermissionDecision = useRelayStore((s) => s.sendPermissionDecision)\n const [submitting, setSubmitting] = useState<string | null>(null)\n if (!approval) return null\n if (approval.questions && approval.questions.length) {\n return <QuestionForm agentId={agentId} approval={approval} questions={approval.questions} />\n }\n const currentApproval = approval\n const choices = approval.choices.length ? approval.choices : [\n { id: 'approve' as const, label: 'Approve' },\n { id: 'deny' as const, label: 'Deny' },\n ]\n\n async function choose(choice: typeof choices[number]) {\n if (submitting) return\n setSubmitting(choice.id)\n try {\n await sendPermissionDecision(agentId, currentApproval.id, choice.id)\n } finally {\n setSubmitting(null)\n }\n }\n\n const isPlan = approval.kind === 'plan'\n return (\n <div className=\"flex justify-start mb-3\">\n <div className=\"max-w-[92%] md:max-w-[78%] rounded-2xl rounded-bl-sm bg-card ring-1 ring-amber-500/35 px-3.5 py-3 text-sm\">\n <div className=\"flex items-start gap-2\">\n {isPlan ? <ListChecks className=\"mt-0.5 h-4 w-4 shrink-0 text-amber-400\" /> : <AlertCircle className=\"mt-0.5 h-4 w-4 shrink-0 text-amber-400\" />}\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-sm font-medium text-amber-100\">{approval.title}</div>\n {approval.body && (isPlan\n ? <div className=\"mt-2 max-h-72 overflow-auto rounded-md bg-background/60 p-2.5 text-xs leading-relaxed\"><FormattedBody text={approval.body} rawBody={approval.body} className=\"leading-relaxed\" /></div>\n : <pre className=\"mt-2 max-h-44 overflow-auto whitespace-pre-wrap break-words rounded-md bg-background/80 p-2 font-mono text-xs leading-relaxed text-muted-foreground\">{approval.body}</pre>)}\n <div className=\"mt-2 flex flex-wrap gap-1.5\">\n {choices.map((choice) => (\n <Button\n key={choice.id}\n size=\"sm\"\n variant={choice.id === 'deny' || choice.id === 'abort' ? 'outline' : 'default'}\n disabled={Boolean(submitting)}\n onClick={() => void choose(choice)}\n className=\"h-7 px-2 text-xs\"\n >\n {submitting === choice.id && <Loader2 className=\"mr-1.5 h-3 w-3 animate-spin\" />}\n {choice.label}\n </Button>\n ))}\n </div>\n </div>\n </div>\n </div>\n </div>\n )\n}\n\ninterface QState { labels: string[]; other: string; otherActive: boolean }\n\nfunction questionAnswered(s: QState | undefined): boolean {\n if (!s) return false\n if (s.otherActive && s.other.trim()) return true\n return s.labels.length > 0\n}\n\nfunction answerValue(s: QState): string {\n const parts = [...s.labels]\n if (s.otherActive && s.other.trim()) parts.push(s.other.trim())\n return parts.join(', ')\n}\n\n// Renders a Claude AskUserQuestion as a sequential form (one question at a\n// time). Collects all answers, then submits a single 'answer' decision that the\n// runner turns into a PreToolUse allow + updatedInput so the tool completes.\nfunction QuestionForm({ agentId, approval, questions }: { agentId: string; approval: ProviderPendingApproval; questions: ProviderQuestion[] }) {\n const sendPermissionDecision = useRelayStore((s) => s.sendPermissionDecision)\n const [step, setStep] = useState(0)\n const [state, setState] = useState<Record<number, QState>>({})\n const [submitting, setSubmitting] = useState<null | 'answer' | 'dismiss'>(null)\n\n const q = questions[Math.min(step, questions.length - 1)]\n const cur = state[step]\n if (!q) return null\n const multi = Boolean(q.multiSelect)\n const total = questions.length\n const isLast = step === total - 1\n const answered = questionAnswered(cur)\n const allAnswered = questions.every((_, i) => questionAnswered(state[i]))\n const busy = Boolean(submitting)\n\n function update(patch: Partial<QState>) {\n setState((prev) => {\n const base: QState = prev[step] ?? { labels: [], other: '', otherActive: false }\n return { ...prev, [step]: { ...base, ...patch } }\n })\n }\n function pickOption(label: string) {\n if (multi) {\n const has = cur?.labels.includes(label)\n update({ labels: has ? (cur?.labels ?? []).filter((l) => l !== label) : [...(cur?.labels ?? []), label] })\n } else {\n update({ labels: [label], otherActive: false })\n }\n }\n function pickOther() {\n if (multi) update({ otherActive: !cur?.otherActive })\n else update({ labels: [], otherActive: true })\n }\n\n async function submit() {\n if (!allAnswered || busy) return\n setSubmitting('answer')\n try {\n const answers: Record<string, string> = {}\n questions.forEach((qq, i) => { const s = state[i]; if (s) answers[qq.question] = answerValue(s) })\n await sendPermissionDecision(agentId, approval.id, 'answer', answers)\n } finally { setSubmitting(null) }\n }\n async function dismiss() {\n if (busy) return\n setSubmitting('dismiss')\n try { await sendPermissionDecision(agentId, approval.id, 'deny') } finally { setSubmitting(null) }\n }\n\n const otherActive = Boolean(cur?.otherActive)\n\n return (\n <div className=\"flex justify-start mb-3\">\n <div className=\"w-full max-w-[92%] md:max-w-[78%] rounded-2xl rounded-bl-sm bg-card ring-1 ring-amber-500/35 px-3.5 py-3 text-sm\">\n <div className=\"flex items-center gap-2\">\n <MessageCircleQuestion className=\"h-4 w-4 shrink-0 text-amber-400\" />\n <div className=\"text-sm font-medium text-amber-100\">{approval.title}</div>\n {total > 1 && (\n <Badge variant=\"outline\" className=\"ml-auto h-5 px-1.5 text-[10px] text-muted-foreground\">{step + 1} / {total}</Badge>\n )}\n </div>\n\n <div className=\"mt-3\">\n {q.header && <div className=\"text-[11px] font-semibold uppercase tracking-wide text-amber-300/80\">{q.header}</div>}\n <div className=\"mt-0.5 text-sm text-foreground whitespace-pre-wrap break-words\">{q.question}</div>\n {multi && <div className=\"mt-0.5 text-[11px] text-muted-foreground\">Select all that apply</div>}\n\n <div className=\"mt-2 flex flex-col gap-1.5\">\n {q.options.map((opt) => {\n const selected = Boolean(cur?.labels.includes(opt.label))\n return (\n <button\n key={opt.label}\n type=\"button\"\n disabled={busy}\n onClick={() => pickOption(opt.label)}\n className={cn(\n 'flex items-start gap-2 rounded-lg border px-2.5 py-2 text-left transition-colors',\n selected ? 'border-amber-500/60 bg-amber-500/10' : 'border-border bg-background/60 hover:bg-background',\n busy && 'opacity-60',\n )}\n >\n <span className={cn(\n 'mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center border text-amber-300',\n multi ? 'rounded' : 'rounded-full',\n selected ? 'border-amber-400 bg-amber-400/20' : 'border-muted-foreground/40',\n )}>\n {selected && <Check className=\"h-3 w-3\" />}\n </span>\n <span className=\"min-w-0\">\n <span className=\"text-sm text-foreground\">{opt.label}</span>\n {opt.description && <span className=\"block text-xs text-muted-foreground\">{opt.description}</span>}\n </span>\n </button>\n )\n })}\n\n <button\n type=\"button\"\n disabled={busy}\n onClick={pickOther}\n className={cn(\n 'flex items-start gap-2 rounded-lg border px-2.5 py-2 text-left transition-colors',\n otherActive ? 'border-amber-500/60 bg-amber-500/10' : 'border-border bg-background/60 hover:bg-background',\n busy && 'opacity-60',\n )}\n >\n <span className={cn(\n 'mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center border text-amber-300',\n multi ? 'rounded' : 'rounded-full',\n otherActive ? 'border-amber-400 bg-amber-400/20' : 'border-muted-foreground/40',\n )}>\n {otherActive && <Check className=\"h-3 w-3\" />}\n </span>\n <span className=\"text-sm text-foreground\">Other…</span>\n </button>\n {otherActive && (\n <Textarea\n autoFocus\n rows={2}\n disabled={busy}\n value={cur?.other ?? ''}\n onChange={(e) => update({ other: e.target.value, otherActive: true })}\n placeholder=\"Type your answer\"\n className=\"mt-1 text-sm\"\n />\n )}\n </div>\n </div>\n\n <div className=\"mt-3 flex items-center gap-1.5\">\n {step > 0 && (\n <Button size=\"sm\" variant=\"outline\" disabled={busy} onClick={() => setStep((s) => s - 1)} className=\"h-7 px-2 text-xs\">\n <ChevronLeft className=\"mr-1 h-3 w-3\" />Back\n </Button>\n )}\n {!isLast ? (\n <Button size=\"sm\" disabled={busy || !answered} onClick={() => setStep((s) => s + 1)} className=\"h-7 px-2 text-xs\">\n Next<ChevronRight className=\"ml-1 h-3 w-3\" />\n </Button>\n ) : (\n <Button size=\"sm\" disabled={busy || !allAnswered} onClick={() => void submit()} className=\"h-7 px-2 text-xs\">\n {submitting === 'answer' && <Loader2 className=\"mr-1.5 h-3 w-3 animate-spin\" />}\n Send answer{total > 1 ? 's' : ''}\n </Button>\n )}\n <Button size=\"sm\" variant=\"ghost\" disabled={busy} onClick={() => void dismiss()} className=\"ml-auto h-7 px-2 text-xs text-muted-foreground\">\n {submitting === 'dismiss' && <Loader2 className=\"mr-1.5 h-3 w-3 animate-spin\" />}\n Dismiss\n </Button>\n </div>\n </div>\n </div>\n )\n}\n\nfunction DateSeparator({ date }: { date: string }) {\n return (\n <div className=\"flex items-center justify-center gap-3 py-3 my-1\">\n <div className=\"h-px flex-1 bg-border\" />\n <span className=\"text-xs font-medium text-muted-foreground\">{dateSeparatorLabel(date)}</span>\n <div className=\"h-px flex-1 bg-border\" />\n </div>\n )\n}\n\nfunction CreatedMarker({ timestamp }: { timestamp: number }) {\n const d = new Date(timestamp)\n const label = d.toLocaleString(undefined, { month: 'short', day: 'numeric', year: 'numeric', hour: '2-digit', minute: '2-digit' })\n return (\n <div className=\"flex items-center justify-center gap-2 py-2 my-1\">\n <div className=\"h-px flex-1 bg-border\" />\n <span className=\"text-xs text-muted-foreground/60\">created {label}</span>\n <div className=\"h-px flex-1 bg-border\" />\n </div>\n )\n}\n\nfunction ImportedHistoryMarker({ history }: { history: ChatHistoryImport }) {\n const source = history.sourceAgentLabel || history.sourcePeerId\n const count = history.entries.length\n return (\n <div className=\"flex items-center justify-center gap-2 py-2 my-1\">\n <div className=\"h-px flex-1 bg-border\" />\n <div className=\"flex items-center gap-1.5 rounded-full border border-dashed border-border bg-muted/30 px-2 py-1 text-[11px] text-muted-foreground\">\n <GitFork className=\"h-3 w-3\" />\n <span>forked history from {source}</span>\n <span className=\"text-muted-foreground/60\">{count} {count === 1 ? 'entry' : 'entries'}</span>\n </div>\n <div className=\"h-px flex-1 bg-border\" />\n </div>\n )\n}\n\nfunction ImportedMessageBubble({ entry, sourceLabel }: { entry: ChatHistoryImportEntry; sourceLabel?: string }) {\n const msg = entry.message\n const body = messageBody(msg)\n const isOriginalHuman = entry.originalFrom === HUMAN_AGENT_ID\n return (\n <div className={cn('flex mb-3 opacity-80', isOriginalHuman ? 'justify-end' : 'justify-start')}>\n <div className=\"max-w-[85%] md:max-w-[75%]\">\n <div\n className={cn(\n 'rounded-2xl border border-dashed px-3.5 py-2 text-sm select-text',\n isOriginalHuman\n ? 'border-primary/25 bg-primary/10 text-foreground rounded-br-sm'\n : 'border-border bg-card/70 rounded-bl-sm'\n )}\n >\n <div className={cn('mb-1 text-[10px] uppercase tracking-normal', isOriginalHuman ? 'text-primary/70' : 'text-muted-foreground')}>\n forked history · {isOriginalHuman ? 'you' : (sourceLabel || entry.originalFrom)}\n </div>\n <FormattedBody text={body} rawBody={msg.body} className=\"leading-relaxed\" />\n <p className={cn('mt-1 flex items-center justify-end gap-1.5 text-xs', isOriginalHuman ? 'text-primary/60' : 'text-muted-foreground')}>\n <span className=\"opacity-40\">#{entry.originalMessageId}</span>\n <span>{chatTimestamp(entry.originalCreatedAt)}</span>\n </p>\n </div>\n </div>\n </div>\n )\n}\n\nfunction AttachmentPreview({ attachment, outbound }: { attachment: AttachmentRef; outbound: boolean }) {\n const isImage = attachment.kind === 'image'\n const title = attachment.title || attachment.artifactId\n const [objectUrl, setObjectUrl] = useState<string | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [loading, setLoading] = useState(false)\n const [lightboxOpen, setLightboxOpen] = useState(false)\n\n useEffect(() => {\n let cancelled = false\n let url: string | null = null\n\n async function load() {\n setLoading(true)\n setError(null)\n setObjectUrl(null)\n try {\n const blob = await apiBlob(`/artifacts/${encodeURIComponent(attachment.artifactId)}/content`)\n if (cancelled) return\n url = URL.createObjectURL(blob)\n setObjectUrl(url)\n } catch (e) {\n if (!cancelled) setError((e as Error).message)\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n\n void load()\n return () => {\n cancelled = true\n if (url) URL.revokeObjectURL(url)\n }\n }, [attachment.artifactId])\n\n function download() {\n if (!objectUrl) return\n const a = document.createElement('a')\n a.href = objectUrl\n a.download = title\n document.body.appendChild(a)\n a.click()\n a.remove()\n }\n\n if (isImage) {\n return (\n <>\n <button\n type=\"button\"\n onClick={() => objectUrl && setLightboxOpen(true)}\n disabled={!objectUrl}\n className=\"group/img mt-2 block overflow-hidden rounded-md border border-foreground/10 bg-black/10 text-left disabled:cursor-default relative\"\n >\n {objectUrl ? (\n <>\n <img src={objectUrl} alt={title} loading=\"lazy\" className=\"block max-h-72 max-w-full object-contain\" />\n <span className=\"absolute inset-0 flex items-center justify-center bg-black/0 group-hover/img:bg-black/30 transition-colors\">\n <ZoomIn className=\"w-6 h-6 text-white opacity-0 group-hover/img:opacity-100 transition-opacity drop-shadow-md\" />\n </span>\n </>\n ) : (\n <span className={cn('flex min-h-20 items-center gap-2 px-3 py-2 text-xs', error ? 'text-red-400' : 'text-muted-foreground')}>\n {loading ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <AlertCircle className=\"h-4 w-4\" />}\n {error || 'Loading image'}\n </span>\n )}\n </button>\n {objectUrl && (\n <Dialog open={lightboxOpen} onOpenChange={setLightboxOpen}>\n <DialogContent className=\"max-w-[95vw] max-h-[95vh] w-auto p-0 bg-black/95 border-zinc-800 gap-0 overflow-hidden\" showCloseButton={false}>\n <DialogTitle className=\"sr-only\">{title}</DialogTitle>\n <div className=\"relative flex items-center justify-center min-h-[200px]\">\n <img src={objectUrl} alt={title} className=\"max-w-[93vw] max-h-[90vh] object-contain\" />\n <div className=\"absolute top-2 right-2 flex gap-1\">\n <button type=\"button\" onClick={download} className=\"rounded-md bg-black/60 hover:bg-black/80 p-2 text-white transition-colors\" title=\"Download\">\n <Download className=\"w-4 h-4\" />\n </button>\n <button type=\"button\" onClick={() => setLightboxOpen(false)} className=\"rounded-md bg-black/60 hover:bg-black/80 p-2 text-white transition-colors\" title=\"Close\">\n <X className=\"w-4 h-4\" />\n </button>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n )}\n </>\n )\n }\n\n return (\n <button\n type=\"button\"\n onClick={download}\n disabled={!objectUrl}\n className={cn(\n 'mt-2 flex w-full items-center gap-2 rounded-md border px-2.5 py-2 text-left text-xs transition-colors disabled:cursor-default disabled:opacity-70',\n outbound ? 'border-primary-foreground/20 bg-primary-foreground/10 hover:bg-primary-foreground/15' : 'border-border bg-background hover:bg-muted'\n )}\n >\n {loading ? <Loader2 className=\"h-4 w-4 shrink-0 animate-spin\" /> : error ? <AlertCircle className=\"h-4 w-4 shrink-0 text-red-400\" /> : <FileText className=\"h-4 w-4 shrink-0\" />}\n <span className={cn('min-w-0 flex-1 truncate', error && 'text-red-400')}>{error || title}</span>\n <Download className=\"h-3.5 w-3.5 shrink-0\" />\n </button>\n )\n}\n\nfunction PendingAttachmentPreview({ item, onRemove }: { item: PendingAttachment; onRemove: () => void }) {\n const [open, setOpen] = useState(false)\n const canPreview = Boolean(item.previewUrl && !item.error)\n\n return (\n <>\n <div className=\"flex min-w-0 items-center gap-2 rounded-md border border-border bg-card px-2.5 py-2 text-xs\">\n <button\n type=\"button\"\n disabled={!canPreview}\n onClick={() => setOpen(true)}\n className=\"group/pending relative flex h-9 w-9 shrink-0 items-center justify-center overflow-hidden rounded bg-muted disabled:cursor-default\"\n title={canPreview ? 'Preview image' : item.fileName}\n >\n {item.previewUrl ? (\n <>\n <img src={item.previewUrl} alt={item.fileName} className=\"h-full w-full object-cover\" />\n <span className=\"absolute inset-0 flex items-center justify-center bg-black/0 group-hover/pending:bg-black/30 transition-colors\">\n <ZoomIn className=\"h-3.5 w-3.5 text-white opacity-0 group-hover/pending:opacity-100 transition-opacity drop-shadow-md\" />\n </span>\n </>\n ) : (\n item.error ? <AlertCircle className=\"h-4 w-4 text-red-400\" /> : item.uploading ? <Loader2 className=\"h-4 w-4 animate-spin text-muted-foreground\" /> : <FileText className=\"h-4 w-4 text-muted-foreground\" />\n )}\n </button>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate font-medium\">{item.fileName}</p>\n <p className={cn('truncate text-muted-foreground', item.error && 'text-red-400')}>{item.error || (item.uploading ? 'Uploading' : formatBytes(item.size))}</p>\n </div>\n <Button variant=\"ghost\" size=\"icon-sm\" title=\"Remove attachment\" onClick={onRemove}>\n <X className=\"h-3.5 w-3.5\" />\n </Button>\n </div>\n {item.previewUrl && (\n <Dialog open={open} onOpenChange={setOpen}>\n <DialogContent className=\"max-w-[95vw] max-h-[95vh] w-auto p-0 bg-black/95 border-zinc-800 gap-0 overflow-hidden\" showCloseButton={false}>\n <DialogTitle className=\"sr-only\">{item.fileName}</DialogTitle>\n <div className=\"relative flex items-center justify-center min-h-[200px]\">\n <img src={item.previewUrl} alt={item.fileName} className=\"max-w-[93vw] max-h-[90vh] object-contain\" />\n <button type=\"button\" onClick={() => setOpen(false)} className=\"absolute top-2 right-2 rounded-md bg-black/60 hover:bg-black/80 p-2 text-white transition-colors\" title=\"Close\">\n <X className=\"w-4 h-4\" />\n </button>\n </div>\n </DialogContent>\n </Dialog>\n )}\n </>\n )\n}\n\n// ─── Floating file preview (hover) ───────────────────────────────────────────\n\nfunction FloatingFilePreview({\n preview,\n error,\n onReadError,\n onMouseEnter,\n onMouseLeave,\n}: {\n preview: { orchestratorId: string; path: string; line: number; type: ReferencedPathInfo['type']; anchor: DOMRect }\n error: string\n onReadError: (error: string) => void\n onMouseEnter: () => void\n onMouseLeave: () => void\n}) {\n const { anchor } = preview\n const gap = 8\n const width = Math.min(560, window.innerWidth - 24)\n const height = Math.min(380, window.innerHeight - 24)\n const left = Math.max(12, Math.min(anchor.left, window.innerWidth - width - 12))\n const spaceBelow = window.innerHeight - anchor.bottom\n const top = spaceBelow >= height + gap\n ? anchor.bottom + gap\n : anchor.top - gap - height >= 12\n ? anchor.top - gap - height\n : Math.max(12, window.innerHeight - height - 12)\n\n return createPortal(\n <div\n className=\"fixed z-50 flex flex-col overflow-hidden rounded-lg border border-border bg-background shadow-xl\"\n style={{ top, left, width, height }}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n >\n <div className=\"flex h-8 shrink-0 items-center gap-2 border-b border-border px-2.5\">\n <span className=\"min-w-0 flex-1 truncate text-[11px] font-medium text-muted-foreground\">{preview.path}</span>\n {error && <span className=\"max-w-[12rem] truncate text-[11px] text-red-400\">{error}</span>}\n <span className=\"shrink-0 text-[10px] text-muted-foreground/70\">click to pin</span>\n </div>\n <div className=\"min-h-0 flex-1\">\n {preview.type === 'directory' ? (\n <DirectoryContent orchestratorId={preview.orchestratorId} selectedPath={preview.path} onReadError={onReadError} />\n ) : (\n <FileContent orchestratorId={preview.orchestratorId} selectedPath={preview.path} line={preview.line} onReadError={onReadError} />\n )}\n </div>\n </div>,\n document.body,\n )\n}\n\n// ─── Add-reaction control ────────────────────────────────────────────────────\n\nfunction AddReaction({ open, onToggle, onReact }: { open: boolean; onToggle: () => void; onReact: (emoji: string) => void }) {\n return (\n <div className=\"relative shrink-0\">\n <button\n type=\"button\"\n title=\"Add reaction\"\n onClick={onToggle}\n className={cn(\n 'inline-flex h-5 w-6 items-center justify-center rounded-full border border-border bg-popover text-muted-foreground shadow-sm transition hover:bg-muted hover:text-foreground',\n open ? 'opacity-100' : 'opacity-0 pointer-events-none md:group-hover/msg:opacity-100 md:group-hover/msg:pointer-events-auto'\n )}\n >\n <SmilePlus className=\"h-3 w-3\" />\n </button>\n {open && (\n <div className=\"absolute bottom-full left-0 z-30 mb-1 flex gap-0.5 rounded-full border border-border bg-popover p-0.5 shadow-md\">\n {QUICK_REACTIONS.map((emoji) => (\n <button\n key={emoji}\n type=\"button\"\n title={`React ${emoji}`}\n onClick={() => onReact(emoji)}\n className=\"inline-flex h-6 w-7 items-center justify-center rounded-full text-xs transition-colors hover:bg-muted\"\n >\n {emoji}\n </button>\n ))}\n </div>\n )}\n </div>\n )\n}\n\n// ─── Message bubble ──────────────────────────────────────────────────────────\n\n// The id of the bubble currently played on demand (play button), or null.\n// voiceTts is a plain controller, not reactive — bridge it into React.\nfunction useTtsPlayingKey(): string | null {\n return useSyncExternalStore(\n (cb) => voiceTts.subscribe(cb),\n () => voiceTts.getPlayingKey(),\n () => null,\n )\n}\n\nconst MessageBubble = memo(function MessageBubble({\n msg,\n peer,\n onOpenReferencedPath,\n onPreviewReferencedPath,\n onPreviewReferencedPathEnd,\n}: {\n msg: Message\n peer: string\n onOpenReferencedPath?: (path: string, line?: number, type?: ReferencedPathInfo['type']) => void\n onPreviewReferencedPath?: (path: string, line?: number, anchor?: DOMRect) => void\n onPreviewReferencedPathEnd?: () => void\n}) {\n const isOutbound = msg.from === HUMAN_AGENT_ID\n const reactToMessage = useRelayStore((s) => s.reactToMessage)\n const voiceTtsEnabled = useRelayStore((s) => s.voiceTtsEnabled)\n const ttsPlayingKey = useTtsPlayingKey()\n const peerCwd = useRelayStore((s) => {\n const cwd = s.agentsById[peer]?.meta?.cwd\n return typeof cwd === 'string' ? cwd : ''\n })\n const [showQuickReact, setShowQuickReact] = useState(false)\n const bubbleRef = useRef<HTMLDivElement>(null)\n const pointerStartRef = useRef<{ x: number; y: number } | null>(null)\n const suppressBubbleClickRef = useRef(false)\n const body = messageBody(msg)\n const time = chatTimestamp(msg.occurredAt ?? (msg.createdAt as string))\n const attachments = messageAttachments(msg)\n const reactions = groupedReactions(msg)\n const receipt = isOutbound ? outboundReceipt(msg, peer) : null\n const ReceiptIcon = receipt?.icon\n // On-demand TTS: replay any agent response through the same Kokoro/browser\n // pipeline. Only when the speaker is on, and only for inbound non-reaction text.\n const isTtsPlaying = ttsPlayingKey === String(msg.id)\n const showPlayButton = voiceTtsEnabled && !isOutbound && !isReactionEvent(msg) && body.trim().length > 0\n function togglePlay(e: React.MouseEvent) {\n e.stopPropagation()\n if (isTtsPlaying) voiceTts.bargeIn()\n else voiceTts.speak(msg.body, String(msg.id))\n }\n useEffect(() => {\n if (!showQuickReact) return\n function dismiss(e: MouseEvent | TouchEvent) {\n if (hasActiveTextSelection()) return\n if (bubbleRef.current && !bubbleRef.current.contains(e.target as Node)) setShowQuickReact(false)\n }\n document.addEventListener('mousedown', dismiss)\n document.addEventListener('touchstart', dismiss)\n return () => { document.removeEventListener('mousedown', dismiss); document.removeEventListener('touchstart', dismiss) }\n }, [showQuickReact])\n\n function resolvedReferencedPath(path: string): string {\n return resolveRelativePath(peerCwd || '/', path)\n }\n\n function openReferencedPath(path: string, line?: number) {\n const absolute = resolvedReferencedPath(path)\n onOpenReferencedPath?.(absolute, line)\n }\n\n function previewReferencedPath(path: string, line?: number, anchor?: DOMRect) {\n const absolute = resolvedReferencedPath(path)\n onPreviewReferencedPath?.(absolute, line, anchor)\n }\n\n function handleReact(emoji: string) {\n reactToMessage(msg, emoji)\n setShowQuickReact(false)\n }\n\n function handleBubblePointerDown(e: React.PointerEvent<HTMLDivElement>) {\n if (e.button !== 0) return\n pointerStartRef.current = { x: e.clientX, y: e.clientY }\n suppressBubbleClickRef.current = false\n }\n\n function handleBubblePointerMove(e: React.PointerEvent<HTMLDivElement>) {\n const start = pointerStartRef.current\n if (!start) return\n if (Math.abs(e.clientX - start.x) > 3 || Math.abs(e.clientY - start.y) > 3) {\n suppressBubbleClickRef.current = true\n }\n }\n\n function handleBubbleClick(e: React.MouseEvent<HTMLDivElement>) {\n if (isReactionEvent(msg) || isOutbound) return\n const target = e.target as HTMLElement\n if (target.closest('a,button,input,textarea,select,[role=\"button\"]')) return\n if (suppressBubbleClickRef.current || hasActiveTextSelection()) {\n suppressBubbleClickRef.current = false\n return\n }\n setShowQuickReact((v) => !v)\n }\n\n return (\n <div data-msg-id={msg.id} className={cn('group/msg flex mb-3', isOutbound ? 'justify-end' : 'justify-start')}>\n <div ref={bubbleRef} className=\"relative max-w-[85%] md:max-w-[75%]\">\n {showPlayButton && (\n <button\n type=\"button\"\n title={isTtsPlaying ? 'Stop playback' : 'Play aloud'}\n onClick={togglePlay}\n className={cn(\n 'absolute -top-2 -right-2 z-20 inline-flex h-6 w-6 items-center justify-center rounded-full border bg-popover shadow-sm transition',\n isTtsPlaying\n ? 'border-primary/50 text-primary opacity-100'\n // Hide-until-hover only on hover-capable devices; touch screens (iPad)\n // have no hover, so keep the button visible there instead of opacity-0.\n : 'border-border text-muted-foreground opacity-70 hover:bg-muted hover:text-foreground hover:opacity-100 [@media(hover:hover)]:md:opacity-0 [@media(hover:hover)]:md:group-hover/msg:opacity-100'\n )}\n >\n {isTtsPlaying ? <CircleStop className=\"h-3.5 w-3.5 animate-pulse\" /> : <Volume2 className=\"h-3.5 w-3.5\" />}\n </button>\n )}\n <div\n className={cn(\n 'rounded-2xl px-3.5 py-2 text-sm select-text',\n !isOutbound && !isReactionEvent(msg) && 'cursor-pointer',\n isOutbound\n ? 'bg-primary text-primary-foreground rounded-br-sm'\n : 'bg-card ring-1 ring-foreground/10 rounded-bl-sm'\n )}\n onPointerDown={handleBubblePointerDown}\n onPointerMove={handleBubblePointerMove}\n onClick={handleBubbleClick}\n >\n {msg.subject && (\n <p className={cn('text-xs font-semibold mb-1', isOutbound ? 'text-primary-foreground/70' : 'text-muted-foreground')}>\n {msg.subject}\n </p>\n )}\n <FormattedBody\n text={body}\n rawBody={msg.body}\n className=\"leading-relaxed\"\n onOpenPath={openReferencedPath}\n onPreviewPath={previewReferencedPath}\n onPreviewPathEnd={onPreviewReferencedPathEnd}\n resolvePathTitle={(path, line) => `${resolvedReferencedPath(path)}${line ? `:${line}` : ''}`}\n />\n {attachments.map((attachment) => (\n <AttachmentPreview key={`${msg.id}-${attachment.artifactId}-${attachment.role || ''}`} attachment={attachment} outbound={isOutbound} />\n ))}\n <p className={cn('text-xs mt-1 flex items-center gap-1.5', isOutbound ? 'justify-end text-primary-foreground/60' : 'justify-end text-muted-foreground')}>\n <span className=\"opacity-40\">#{msg.id}</span>\n <span>{time}</span>\n {receipt && ReceiptIcon && (\n <span\n className={cn(\n 'inline-flex items-center gap-1',\n receipt.tone === 'ok' && 'text-emerald-300',\n receipt.tone === 'warn' && 'text-amber-200',\n receipt.tone === 'danger' && 'text-red-200'\n )}\n title={receipt.title}\n >\n <ReceiptIcon className=\"h-3 w-3\" />\n {receipt.label}\n </span>\n )}\n </p>\n </div>\n {!isReactionEvent(msg) && reactions.length > 0 && (\n <div className={cn('flex flex-wrap items-center gap-0.5 -mt-1 relative z-10', isOutbound ? 'justify-end pr-2' : 'justify-start pl-2')}>\n {!isOutbound && <AddReaction open={showQuickReact} onToggle={() => setShowQuickReact((v) => !v)} onReact={handleReact} />}\n {reactions.map((reaction) => (\n <button\n key={reaction.emoji}\n type=\"button\"\n title={reaction.actors.join(', ')}\n onClick={() => handleReact(reaction.emoji)}\n className={cn(\n 'inline-flex h-5 items-center gap-0.5 rounded-full border px-1.5 text-[11px] shadow-sm transition-colors',\n reaction.mine\n ? 'border-primary/40 bg-primary/10 text-primary'\n : 'border-border bg-background hover:bg-muted text-foreground'\n )}\n >\n <span>{reaction.emoji}</span>\n {reaction.count > 1 && <span>{reaction.count}</span>}\n </button>\n ))}\n </div>\n )}\n {!isReactionEvent(msg) && !isOutbound && reactions.length === 0 && (\n <div className=\"absolute -bottom-2.5 left-1 z-20\">\n <AddReaction open={showQuickReact} onToggle={() => setShowQuickReact((v) => !v)} onReact={handleReact} />\n </div>\n )}\n </div>\n </div>\n )\n})\n\n// ─── Timeline with interleaved status events and date separators ────────────\n\ninterface ActivityStep { id: number; kind: 'narration' | 'reasoning' | 'tool'; label?: string; text: string; ts: number; turnId?: string }\n\ntype TimelineEntry =\n | { type: 'message'; msg: Message }\n | { type: 'activity'; steps: ActivityStep[]; timestamp: number }\n | { type: 'import-boundary'; history: ChatHistoryImport; timestamp: number }\n | { type: 'imported-message'; history: ChatHistoryImport; entry: ChatHistoryImportEntry }\n | { type: 'status'; event: StatusEvent }\n | { type: 'date'; date: string; timestamp: number }\n | { type: 'created'; timestamp: number }\n\n// Narration/reasoning/tool session events are mirrored as `kind:\"session\"` messages\n// but must not become chat bubbles — they render inline in the turn's activity trace.\n// (`narration` = the agent's intermediate spoken text; `reasoning` = its thinking.)\nfunction sessionActivityStep(msg: Message): ActivityStep | null {\n if (msg.kind !== 'session') return null\n const s = msg.payload?.session as { type?: string; label?: string; turnId?: string } | undefined\n if (!s || (s.type !== 'narration' && s.type !== 'reasoning' && s.type !== 'tool')) return null\n return {\n id: msg.id,\n kind: s.type,\n label: typeof s.label === 'string' ? s.label : undefined,\n text: msg.body,\n ts: messageEventTime(msg),\n turnId: typeof s.turnId === 'string' ? s.turnId : undefined,\n }\n}\n\nfunction dateKey(ts: number): string {\n const d = new Date(ts)\n return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`\n}\n\nfunction dedupeStatusEvents(statusEvents: StatusEvent[]): StatusEvent[] {\n const events = statusEvents\n .filter((event) => TIMELINE_STATUSES.has(event.status))\n .slice()\n .sort((a, b) => a.timestamp - b.timestamp)\n const result: StatusEvent[] = []\n for (const event of events) {\n if (result.some((existing) => existing.id === event.id)) continue\n if (result.some((existing) => existing.status === event.status && Math.abs(existing.timestamp - event.timestamp) <= STATUS_DEDUPE_WINDOW_MS)) continue\n result.push(event)\n }\n return result\n}\n\nfunction isNearTimelineBottom(el: HTMLElement): boolean {\n return el.scrollHeight - el.scrollTop - el.clientHeight <= CHAT_BOTTOM_THRESHOLD_PX\n}\n\nfunction usePinnedScroll<T extends HTMLElement>(resetKey: string, triggers: unknown[]) {\n const ref = useRef<T>(null)\n const stickToBottomRef = useRef(true)\n const lastResetKeyRef = useRef<string | null>(null)\n\n const onScroll = useCallback(() => {\n const el = ref.current\n if (!el) return\n stickToBottomRef.current = isNearTimelineBottom(el)\n }, [])\n\n useLayoutEffect(() => {\n const el = ref.current\n if (!el) return\n const reset = lastResetKeyRef.current !== resetKey\n if (reset) {\n lastResetKeyRef.current = resetKey\n stickToBottomRef.current = true\n }\n if (stickToBottomRef.current) el.scrollTop = el.scrollHeight\n }, [resetKey, ...triggers])\n\n return { ref, onScroll }\n}\n\nfunction revokePendingAttachmentUrls(items: PendingAttachment[]): void {\n for (const item of items) if (item.previewUrl) URL.revokeObjectURL(item.previewUrl)\n}\n\nfunction buildTimeline(messages: Message[], statusEvents: StatusEvent[], createdAt?: string | number | null, importedHistory: ChatHistoryImport[] = []): TimelineEntry[] {\n const raw: Array<{ ts: number; entry: TimelineEntry }> = []\n\n for (const history of importedHistory) {\n const firstImportedAt = history.entries.reduce((min, entry) => Math.min(min, toTimestamp(entry.originalCreatedAt)), Number.POSITIVE_INFINITY)\n const boundaryAt = Number.isFinite(firstImportedAt) ? firstImportedAt - 1 : history.importedAt\n raw.push({ ts: boundaryAt, entry: { type: 'import-boundary', history, timestamp: boundaryAt } })\n for (const entry of history.entries) {\n raw.push({ ts: toTimestamp(entry.originalCreatedAt), entry: { type: 'imported-message', history, entry } })\n }\n }\n\n if (createdAt) {\n const ts = new Date(createdAt as string).getTime()\n if (Number.isFinite(ts)) raw.push({ ts, entry: { type: 'created', timestamp: ts } })\n }\n\n // The closing response bubble (session type \"response\") repeats the turn's\n // narration. In `final` capture mode the body is just the final line; in `full`\n // mode it is every narration block \\n\\n-joined (matching extractLastAssistantTurn).\n // Collect the response bodies per turn so a narration step is suppressed from the\n // trace whenever it appears as a \\n\\n-delimited block of the body — so no line\n // shows twice in either mode (final: only the matching final line; full: all of them).\n const responseBodiesByTurn = new Map<string, string[]>()\n for (const msg of messages) {\n if (msg.kind !== 'session') continue\n const s = msg.payload?.session as { type?: string; turnId?: string } | undefined\n if (s?.type === 'response' && typeof s.turnId === 'string') {\n const list = responseBodiesByTurn.get(s.turnId) ?? []\n list.push(msg.body.trim())\n responseBodiesByTurn.set(s.turnId, list)\n }\n }\n\n for (const msg of messages) {\n if (isReactionEvent(msg)) continue\n const step = sessionActivityStep(msg)\n if (step) {\n if (step.kind === 'narration' && step.turnId) {\n const bodies = responseBodiesByTurn.get(step.turnId)\n if (bodies?.some((body) => responseBodyContainsBlock(body, step.text))) continue\n }\n raw.push({ ts: step.ts, entry: { type: 'activity', steps: [step], timestamp: step.ts } })\n continue\n }\n raw.push({ ts: messageEventTime(msg), entry: { type: 'message', msg } })\n }\n for (const event of dedupeStatusEvents(statusEvents)) {\n raw.push({ ts: event.timestamp, entry: { type: 'status', event } })\n }\n\n const typeOrder = { created: 0, date: 1, 'import-boundary': 2, 'imported-message': 3, message: 4, activity: 4, status: 5 } as const\n raw.sort((a, b) => {\n const dt = a.ts - b.ts\n if (Math.abs(dt) < 3000) return typeOrder[a.entry.type] - typeOrder[b.entry.type] || dt\n return dt\n })\n\n const entries: TimelineEntry[] = []\n let lastDate = ''\n for (const { ts, entry } of raw) {\n if (entry.type === 'created') {\n entries.push(entry)\n continue\n }\n const dk = dateKey(ts)\n if (dk !== lastDate) {\n entries.push({ type: 'date', date: dk, timestamp: ts })\n lastDate = dk\n }\n // Coalesce consecutive activity steps from the same turn into one trace.\n if (entry.type === 'activity') {\n const prev = entries[entries.length - 1]\n if (prev && prev.type === 'activity' && sameActivityTurn(prev, entry)) {\n prev.steps.push(...entry.steps)\n continue\n }\n }\n entries.push(entry)\n }\n\n return entries\n}\n\nfunction sameActivityTurn(a: Extract<TimelineEntry, { type: 'activity' }>, b: Extract<TimelineEntry, { type: 'activity' }>): boolean {\n const at = a.steps[a.steps.length - 1]?.turnId\n const bt = b.steps[0]?.turnId\n if (at && bt) return at === bt\n // No turn id on either side: group adjacent steps regardless.\n return !at && !bt\n}\n\n// ─── Sticky last-prompt banner ──────────────────────────────────────────────\n\nfunction StickyPromptBanner({ scrollRef, timeline }: { scrollRef: React.RefObject<HTMLElement | null>; timeline: TimelineEntry[] }) {\n const [hidden, setHidden] = useState(true)\n const [expanded, setExpanded] = useState(false)\n const [collapsed, setCollapsed] = useState(false)\n const [promptAbove, setPromptAbove] = useState(true)\n\n const lastOutbound = useMemo(() => {\n for (let i = timeline.length - 1; i >= 0; i--) {\n const entry = timeline[i]\n if (!entry || entry.type !== 'message') continue\n if (entry.msg.from === HUMAN_AGENT_ID) {\n return { id: entry.msg.id, body: messageBody(entry.msg) }\n }\n }\n return null\n }, [timeline])\n\n useEffect(() => {\n const scrollEl = scrollRef.current\n if (!lastOutbound || !scrollEl) { setHidden(true); return }\n const target = scrollEl.querySelector(`[data-msg-id=\"${lastOutbound.id}\"]`)\n if (!target) { setHidden(true); return }\n const observer = new IntersectionObserver(\n ([e]) => {\n if (!e) return\n setHidden(e.isIntersecting)\n if (!e.isIntersecting) {\n const rootTop = e.rootBounds?.top ?? scrollEl.getBoundingClientRect().top\n setPromptAbove(e.boundingClientRect.top < rootTop)\n }\n },\n { root: scrollEl, threshold: 0 }\n )\n observer.observe(target)\n const onScroll = () => {\n const r = target.getBoundingClientRect()\n const sr = scrollEl.getBoundingClientRect()\n setPromptAbove(r.top < sr.top)\n }\n scrollEl.addEventListener('scroll', onScroll, { passive: true })\n return () => { observer.disconnect(); scrollEl.removeEventListener('scroll', onScroll) }\n }, [lastOutbound?.id, scrollRef])\n\n useEffect(() => { setExpanded(false); setCollapsed(false) }, [lastOutbound?.id])\n\n if (hidden || !lastOutbound || !lastOutbound.body.trim()) return null\n\n function scrollToPrompt() {\n const scrollEl = scrollRef.current\n if (!scrollEl || !lastOutbound) return\n const target = scrollEl.querySelector(`[data-msg-id=\"${lastOutbound.id}\"]`)\n target?.scrollIntoView({ behavior: 'smooth', block: 'center' })\n }\n\n const arrow = promptAbove ? '↑' : '↓'\n\n if (collapsed) {\n return (\n <div className=\"sticky top-0 z-10 -mx-3 md:-mx-4 -mt-3 md:-mt-4 bg-background\">\n <button\n type=\"button\"\n className=\"w-full flex items-center justify-center gap-1.5 py-1 text-[11px] text-primary/60 hover:text-primary border-b border-primary/10 transition-colors\"\n onClick={() => setCollapsed(false)}\n >\n <span>Your prompt</span>\n <ChevronDown className=\"w-3 h-3\" />\n </button>\n </div>\n )\n }\n\n return (\n <div className=\"sticky top-0 z-10 -mx-3 md:-mx-4 -mt-3 md:-mt-4 px-2 md:px-3 pt-2 pb-1.5 bg-background border-b border-primary/10\">\n <div className=\"flex items-center gap-2 text-[11px] text-muted-foreground mb-0.5\">\n <span className=\"font-medium text-primary/70\">Your prompt</span>\n <button\n type=\"button\"\n className=\"ml-auto hover:text-foreground transition-colors\"\n onClick={scrollToPrompt}\n >\n {arrow} scroll to original\n </button>\n <button\n type=\"button\"\n className=\"hover:text-foreground transition-colors\"\n onClick={() => setCollapsed(true)}\n title=\"Minimize\"\n >\n <ChevronUp className=\"w-3 h-3\" />\n </button>\n </div>\n <p\n className={cn('text-sm text-foreground leading-snug cursor-pointer', !expanded && 'line-clamp-2')}\n onClick={() => setExpanded(e => !e)}\n >\n {lastOutbound.body}\n </p>\n </div>\n )\n}\n\n// ─── Right panel: chat ───────────────────────────────────────────────────────\n\nfunction ChatPanel({ threads, onBack, showBackButton }: { threads: InboxThread[]; onBack?: () => void; showBackButton?: boolean }) {\n const selectedInboxThread = useRelayStore((s) => s.selectedInboxThread)\n const agentsById = useRelayStore((s) => s.agentsById)\n const inboxDrafts = useRelayStore((s) => s.inboxDrafts)\n const now = useNow()\n const sendChatMessage = useRelayStore((s) => s.sendChatMessage)\n const openFilesAt = useRelayStore((s) => s.openFilesAt)\n const openFilesForAgent = useRelayStore((s) => s.openFilesForAgent)\n const openAgentDetail = useRelayStore((s) => s.openAgentDetail)\n const chatSending = useRelayStore((s) => s.chatSending)\n const markInboxThreadRead = useRelayStore((s) => s.markInboxThreadRead)\n const markInboxThreadUnread = useRelayStore((s) => s.markInboxThreadUnread)\n const setReplyDraft = useRelayStore((s) => s.setReplyDraft)\n const exportThread = useRelayStore((s) => s.exportThread)\n const doAgentAction = useRelayStore((s) => s.doAgentAction)\n const workspaceAction = useRelayStore((s) => s.workspaceAction)\n const openWorkspaceFocus = useRelayStore((s) => s.openWorkspaceFocus)\n const forkFromAgent = useRelayStore((s) => s.forkFromAgent)\n const chatHistoryImports = useRelayStore((s) => s.chatHistoryImports)\n const peerHistory = useRelayStore((s) => s.threadHistory[s.selectedInboxThread] ?? NO_THREAD_HISTORY)\n const openConfirm = useRelayStore((s) => s.openConfirm)\n const showError = useRelayStore((s) => s.showError)\n const orchestrators = useRelayStore((s) => s.orchestrators)\n const fetchOrchestrators = useRelayStore((s) => s.fetchOrchestrators)\n const showReasoning = useRelayStore((s) => s.showReasoning)\n const voiceTtsEnabled = useRelayStore((s) => s.voiceTtsEnabled)\n const setVoiceTtsEnabled = useRelayStore((s) => s.setVoiceTtsEnabled)\n const voiceInputMode = useRelayStore((s) => s.voiceInputMode)\n\n const fileInputRef = useRef<HTMLInputElement>(null)\n const pttRecorderRef = useRef<PttRecorder | null>(null)\n const [micState, setMicState] = useState<'idle' | 'recording' | 'transcribing'>('idle')\n const pendingAttachmentsRef = useRef<PendingAttachment[]>([])\n const [pendingAttachments, setPendingAttachments] = useState<PendingAttachment[]>([])\n const [dragActive, setDragActive] = useState(false)\n const [filePreview, setFilePreview] = useState<{ orchestratorId: string; path: string; line: number; type: ReferencedPathInfo['type'] } | null>(null)\n const [floatingPreview, setFloatingPreview] = useState<{ orchestratorId: string; path: string; line: number; type: ReferencedPathInfo['type']; anchor: DOMRect } | null>(null)\n const [filePreviewError, setFilePreviewError] = useState('')\n const filePreviewCloseTimer = useRef<number | null>(null)\n const filePreviewRequest = useRef(0)\n const statusEvents = useAgentStatusEvents(selectedInboxThread)\n\n const thread = useMemo(\n () => threads.find((t) => t.peer === selectedInboxThread) || null,\n [threads, selectedInboxThread]\n )\n\n // Union the live thread (from the capped global buffer) with the peer's fetched\n // backlog so older messages survive on a busy relay. Live entries win on id\n // collision (fresher delivery/reaction state); history is filtered to this peer\n // and de-reaction'd to match how useAllInboxThreads builds the live thread.\n const threadMessages = useMemo(() => {\n const live = thread?.messages ?? []\n if (peerHistory.length === 0) return live\n const byId = new Map<number, Message>()\n for (const m of peerHistory) {\n if (inboxPeer(m) === selectedInboxThread && !isReactionEventMessage(m)) byId.set(m.id, m)\n }\n for (const m of live) byId.set(m.id, m)\n return [...byId.values()].sort((a, b) => a.id - b.id)\n }, [thread?.messages, peerHistory, selectedInboxThread])\n\n const agent = agentsById[selectedInboxThread] || null\n // Pre-session-destroy window (#183): the agent is running end-of-session work before a\n // compact/clear/restart/shutdown and is intentionally non-addressable. Block the composer\n // so a message can't be fired into a session that's tearing down.\n const agentFinalizing = typeof agent?.meta?.lifecycleAction === 'string' && agent.meta.lifecycleAction.startsWith('finalizing-')\n const { terminalOpen, terminalTarget, terminalOpening, openTerminal: handleOpenTerminal, closeTerminal: handleCloseTerminal } = useAgentTerminal(agent?.id)\n const agentSpawnRequestId = typeof agent?.meta?.spawnRequestId === 'string' ? agent.meta.spawnRequestId as string : ''\n const importedHistory = useMemo(() => {\n return chatHistoryImports.filter((history) =>\n history.targetAgentId === selectedInboxThread ||\n Boolean(agentSpawnRequestId && history.targetSpawnRequestId === agentSpawnRequestId)\n )\n }, [agentSpawnRequestId, chatHistoryImports, selectedInboxThread])\n const blockedState = providerBlockedState(agent)\n const pendingApproval = blockedState?.pendingApproval\n const exportableThread = thread || (importedHistory.length > 0 ? { peer: selectedInboxThread, messages: [], importedHistory } : null)\n const draft = inboxDrafts[selectedInboxThread] || ''\n const importedEntryCount = importedHistory.reduce((sum, history) => sum + history.entries.length, 0)\n const pinnedScroll = usePinnedScroll<HTMLDivElement>(selectedInboxThread, [threadMessages.length, statusEvents.length, importedEntryCount, pendingApproval?.id, agent?.status])\n\n const tmuxSession = typeof agent?.meta?.tmuxSession === 'string' && (agent.meta.tmuxSession as string).trim() ? agent.meta.tmuxSession as string : null\n const termOrch = tmuxSession ? orchestrators.find((o) => (o as any).managedAgents?.some((m: any) => m.agentId === agent!.id || m.tmuxSession === tmuxSession)) ?? null : null\n const canReadTerminal = Boolean(tmuxSession && termOrch?.status === 'online' && agent?.providerCapabilities?.terminal?.live?.read)\n const runtimeProvider = agent?.providerCapabilities?.model?.provider ?? (typeof agent?.meta?.provider === 'string' ? agent.meta.provider : undefined)\n const canWriteTerminal = Boolean(canReadTerminal && (agent?.providerCapabilities?.terminal?.live?.write || runtimeProvider === 'claude'))\n const canAttachTerminal = agent?.providerCapabilities?.terminal?.attach?.create === true\n const canOpenTerminal = canReadTerminal || canAttachTerminal\n const canCompact = agentSupportsControlAction(agent, 'compact')\n const canClearContext = agentSupportsControlAction(agent, 'clearContext')\n const canShutdown = agentSupportsControlAction(agent, 'shutdown')\n const canInterrupt = agentSupportsControlAction(agent, 'interrupt')\n const interruptAgent = () => { if (agent) void doAgentAction(agent, 'interrupt') }\n\n // Slash-command palette (item 6). Derived purely from the draft during render —\n // no effect syncs it. slashClosed lets Escape dismiss until the draft changes.\n const [slashIndex, setSlashIndex] = useState(0)\n const [slashClosed, setSlashClosed] = useState(false)\n const slashEnabled = agent?.providerCapabilities?.liveSession?.slashCommands === true\n const slashProvider = agent?.providerCapabilities?.model?.provider ?? (typeof agent?.meta?.provider === 'string' ? agent.meta.provider : undefined)\n const slashMatches = (slashEnabled && !slashClosed && /^\\/\\S*$/.test(draft))\n ? providerSlashCommands(slashProvider).filter((c) => c.name.toLowerCase().startsWith(draft.toLowerCase()))\n : []\n const slashActiveIndex = slashMatches.length ? Math.min(slashIndex, slashMatches.length - 1) : 0\n function acceptSlash(cmd: SlashCommand) {\n setReplyDraft(selectedInboxThread, `${cmd.name} `)\n setSlashIndex(0)\n }\n function handleDraftChange(value: string) {\n setReplyDraft(selectedInboxThread, value)\n if (slashClosed) setSlashClosed(false)\n setSlashIndex(0)\n }\n const hasPendingUploads = pendingAttachments.some((item) => item.uploading)\n const readyAttachments = pendingAttachments.filter((item) => item.artifact)\n const hasDraft = draft.trim().length > 0 || pendingAttachments.length > 0\n\n // Back navigation protection when draft exists\n const handleBackNav = useCallback(() => {\n // Don't navigate away — the draft is protected\n }, [])\n useBackNavProtection(hasDraft, handleBackNav)\n\n pendingAttachmentsRef.current = pendingAttachments\n\n useEffect(() => {\n return () => {\n revokePendingAttachmentUrls(pendingAttachmentsRef.current)\n }\n }, [])\n\n useEffect(() => {\n if (agent?.meta?.tmuxSession && orchestrators.length === 0) void fetchOrchestrators()\n }, [agent?.id, agent?.meta?.tmuxSession, orchestrators.length])\n\n useEffect(() => {\n return () => {\n if (filePreviewCloseTimer.current !== null) window.clearTimeout(filePreviewCloseTimer.current)\n }\n }, [])\n\n const timeline = useMemo(\n () => buildTimeline(threadMessages, statusEvents, agent?.createdAt, importedHistory),\n [threadMessages, statusEvents, agent?.createdAt, importedHistory]\n )\n\n const clearFilePreviewCloseTimer = useCallback(() => {\n if (filePreviewCloseTimer.current === null) return\n window.clearTimeout(filePreviewCloseTimer.current)\n filePreviewCloseTimer.current = null\n }, [])\n\n const resolveReferencedFile = useCallback(async (path: string): Promise<ReferencedPathInfo | null> => {\n const orchestrator = orchestratorForFilePreview(orchestrators, path)\n if (!orchestrator) return null\n try {\n const stat = await api<FileStatResult>('GET', `/orchestrators/${encodeURIComponent(orchestrator.id)}/files/stat?path=${encodeURIComponent(path)}`)\n return { orchestratorId: orchestrator.id, path: stat.path, type: stat.type }\n } catch {\n return null\n }\n }, [orchestrators])\n\n // Hover shows a lightweight floating preview anchored to the link — it does\n // not reflow the chat, so the link stays under the cursor.\n const previewReferencedFile = useCallback((path: string, line?: number, anchor?: DOMRect) => {\n if (!supportsSideFilePreview() || !anchor) return\n const request = ++filePreviewRequest.current\n void resolveReferencedFile(path).then((info) => {\n if (filePreviewRequest.current !== request) return\n if (!info) return\n clearFilePreviewCloseTimer()\n setFloatingPreview({ ...info, line: line || 0, anchor })\n setFilePreviewError('')\n })\n }, [clearFilePreviewCloseTimer, resolveReferencedFile])\n\n const scheduleCloseReferencedFilePreview = useCallback(() => {\n filePreviewRequest.current += 1\n clearFilePreviewCloseTimer()\n filePreviewCloseTimer.current = window.setTimeout(() => {\n setFloatingPreview(null)\n }, 250)\n }, [clearFilePreviewCloseTimer])\n\n // Clicking the link commits to the side panel — and dismisses the floating\n // preview so the two never show at once.\n const openReferencedFile = useCallback((path: string, line?: number) => {\n void resolveReferencedFile(path).then((info) => {\n if (!info) {\n showError('File Not Found', path)\n return\n }\n if (supportsSideFilePreview()) {\n filePreviewRequest.current += 1\n clearFilePreviewCloseTimer()\n setFloatingPreview(null)\n setFilePreview({ ...info, line: line || 0 })\n setFilePreviewError('')\n return\n }\n if (info.type === 'directory') void openFilesAt({ orchestratorId: info.orchestratorId, path: info.path, overlay: true })\n else void openFilesAt({ orchestratorId: info.orchestratorId, path: parentPath(info.path), selectedPath: info.path, line, overlay: true })\n })\n }, [clearFilePreviewCloseTimer, openFilesAt, resolveReferencedFile, showError])\n\n function closeFilePreview() {\n setFilePreview(null)\n setFilePreviewError('')\n }\n async function uploadFiles(files: FileList | File[]) {\n const list = Array.from(files).filter((file) => file.size > 0)\n if (!list.length) return\n const pending = list.map((file): PendingAttachment => ({\n id: `${Date.now()}-${file.name}-${Math.random().toString(16).slice(2)}`,\n fileName: file.name,\n size: file.size,\n previewUrl: file.type.startsWith('image/') ? URL.createObjectURL(file) : undefined,\n uploading: true,\n }))\n setPendingAttachments((current) => [...current, ...pending])\n\n for (let i = 0; i < list.length; i += 1) {\n const file = list[i]!\n const item = pending[i]!\n try {\n const artifact = await apiUpload<Artifact>('/artifacts', file, {\n filename: file.name,\n sensitivity: 'normal',\n })\n setPendingAttachments((current) => current.map((entry) => entry.id === item.id ? { ...entry, artifact, uploading: false } : entry))\n } catch (e) {\n setPendingAttachments((current) => current.map((entry) => entry.id === item.id ? { ...entry, error: (e as Error).message, uploading: false } : entry))\n }\n }\n }\n\n function removePendingAttachment(id: string) {\n setPendingAttachments((current) => {\n const item = current.find((entry) => entry.id === id)\n if (item?.previewUrl) URL.revokeObjectURL(item.previewUrl)\n return current.filter((entry) => entry.id !== id)\n })\n }\n\n function clearPendingAttachments() {\n revokePendingAttachmentUrls(pendingAttachments)\n setPendingAttachments([])\n }\n\n function handleSend() {\n if ((!draft.trim() && readyAttachments.length === 0) || !selectedInboxThread || chatSending || hasPendingUploads || agentFinalizing) return\n const attachments = readyAttachments.map((item): AttachmentRef => ({\n artifactId: item.artifact!.id,\n kind: item.artifact!.kind,\n role: 'media',\n title: item.artifact!.filename || item.fileName,\n }))\n sendChatMessage(draft, { peer: selectedInboxThread, lastMessage: thread?.lastMessage || null }, attachments)\n clearPendingAttachments()\n }\n\n function handleKeyDown(e: React.KeyboardEvent<HTMLTextAreaElement>) {\n if (slashMatches.length) {\n if (e.key === 'ArrowDown') { e.preventDefault(); setSlashIndex((i) => Math.min(i + 1, slashMatches.length - 1)); return }\n if (e.key === 'ArrowUp') { e.preventDefault(); setSlashIndex((i) => Math.max(i - 1, 0)); return }\n if (e.key === 'Escape') { e.preventDefault(); setSlashClosed(true); return }\n if (e.key === 'Enter' || e.key === 'Tab') { e.preventDefault(); const cmd = slashMatches[slashActiveIndex]; if (cmd) acceptSlash(cmd); return }\n }\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n handleSend()\n }\n }\n\n function handlePaste(e: React.ClipboardEvent<HTMLTextAreaElement>) {\n const files = Array.from(e.clipboardData.files).filter((file) => file.type.startsWith('image/'))\n if (!files.length) return\n e.preventDefault()\n void uploadFiles(files)\n }\n\n // Push-to-talk. Two behaviours (Settings → Voice input):\n // 'compose' — transcribe into the composer (review, then Enter). The default.\n // 'autosend' — transcribe and send to the agent immediately, hands-light loop.\n async function startPtt() {\n if (!micAvailable || micState !== 'idle' || !selectedInboxThread) return\n voiceTts.bargeIn() // stop any speech while the user talks\n const recorder = new PttRecorder()\n try {\n await recorder.start()\n pttRecorderRef.current = recorder\n setMicState('recording')\n } catch (e) {\n pttRecorderRef.current = null\n setMicState('idle')\n showError('Microphone unavailable', (e as Error)?.message || 'Could not access the microphone.')\n }\n }\n\n async function stopPtt() {\n const recorder = pttRecorderRef.current\n if (!recorder || micState !== 'recording') return\n pttRecorderRef.current = null\n setMicState('transcribing')\n try {\n const clip = await recorder.stop()\n if (!clip) return\n const text = await transcribeClip(clip)\n if (!text) return\n const combined = draft ? `${draft} ${text}` : text\n if (voiceInputMode === 'autosend' && !chatSending && !hasPendingUploads) {\n // Speak-and-send: skip the composer, fire it straight at the agent. The\n // reply auto-speaks (voiceTts.onResponse) and you hold to talk again.\n const attachments = readyAttachments.map((item): AttachmentRef => ({\n artifactId: item.artifact!.id,\n kind: item.artifact!.kind,\n role: 'media',\n title: item.artifact!.filename || item.fileName,\n }))\n sendChatMessage(combined, { peer: selectedInboxThread, lastMessage: thread?.lastMessage || null }, attachments)\n clearPendingAttachments()\n } else {\n setReplyDraft(selectedInboxThread, combined)\n }\n } catch (e) {\n showError('Transcription failed', (e as Error)?.message || 'Could not transcribe audio.')\n } finally {\n setMicState('idle')\n }\n }\n\n if (!selectedInboxThread) {\n return (\n <div className=\"flex flex-col items-center justify-center h-full text-center px-4\">\n <MessageSquare className=\"w-12 h-12 text-zinc-600 mb-3\" />\n <p className=\"text-muted-foreground text-sm\">Select an agent to start chatting</p>\n </div>\n )\n }\n\n return (\n <>\n <div className=\"flex h-full min-w-0\">\n <div className=\"@container/chat flex h-full min-w-0 flex-1 flex-col\">\n {/* Header — toolbar collapses on the panel's own width (container query), not the\n viewport: in the two-pane chat layout this pane is only ~half the viewport, so\n viewport breakpoints over-revealed buttons and crushed the name (e.g. iPad portrait). */}\n <div className=\"flex items-center justify-between px-3 md:px-4 py-2.5 md:py-3 border-b border-border shrink-0\">\n <div className=\"flex items-center gap-2 md:gap-2.5 min-w-0\">\n {showBackButton && (\n <Button variant=\"ghost\" size=\"icon-sm\" onClick={onBack} className=\"shrink-0 -ml-1\">\n <ArrowLeft className=\"w-4 h-4\" />\n </Button>\n )}\n <button\n type=\"button\"\n className=\"flex items-center gap-2 md:gap-2.5 min-w-0 hover:opacity-80 transition-opacity\"\n onClick={() => agent && openAgentDetail(agent)}\n disabled={!agent}\n >\n <div className=\"relative shrink-0\">\n <AgentTypeIcon agent={agent} />\n <StatusDot agent={agent} now={now} className=\"absolute -bottom-0.5 -right-0.5 w-2 h-2\" />\n </div>\n <div className=\"min-w-0 text-left\">\n <p className=\"text-sm font-medium truncate\">{agent ? displayName(agent) : selectedInboxThread}</p>\n {agent && (\n <p className=\"text-xs text-muted-foreground truncate\">\n {blockedState ? `blocked: ${blockedState.label}` : agent.status}\n {agent.machine && ` · ${agent.machine}`}\n {typeof agent.meta?.cwd === 'string' && agent.meta.cwd && ` · ${shortPath(agent.meta.cwd as string, 1)}`}\n </p>\n )}\n </div>\n </button>\n {agent && <AgentRuntimeChips agent={agent} compact className=\"hidden @4xl/chat:flex shrink-0\" />}\n {agent?.context && <ContextRing utilization={agent.context.utilization} />}\n {agent?.branchState && agent.branchWorkspaceId && (\n <BranchStateBadge state={agent.branchState} className=\"shrink-0\" onClick={() => void openWorkspaceFocus(agent.branchWorkspaceId!)} />\n )}\n {thread?.attention.unread ? (\n <Badge className=\"bg-red-500/20 text-red-400 text-xs shrink-0 hidden @2xl/chat:flex\">{thread.attention.unread} unread</Badge>\n ) : null}\n </div>\n\n <div className=\"flex items-center gap-0.5 md:gap-1 shrink-0\">\n {agent && (\n <>\n <CopyButton value={agent.id} label=\"Copy agent ID\" size=\"icon-sm\" />\n {voiceTts.available && <Button variant=\"ghost\" size=\"icon-sm\" title={voiceTtsEnabled ? 'Speaking agent responses aloud — click to mute (engine & voice in Settings)' : 'Speak agent responses aloud (active chat) — engine & voice in Settings'} className={voiceTtsEnabled ? 'text-primary' : ''} onClick={() => setVoiceTtsEnabled(!voiceTtsEnabled)}>{voiceTtsEnabled ? <Volume2 className=\"w-3.5 h-3.5\" /> : <VolumeX className=\"w-3.5 h-3.5\" />}</Button>}\n {canOpenTerminal && <Button variant=\"ghost\" size=\"icon-sm\" className=\"hidden @4xl/chat:inline-flex\" disabled={terminalOpening} title=\"Terminal\" onClick={() => void handleOpenTerminal()}><Terminal className=\"w-3.5 h-3.5\" /></Button>}\n {canInterrupt && <Button variant=\"ghost\" size=\"icon-sm\" className=\"text-red-400 hover:text-red-300\" title=\"Interrupt\" onClick={interruptAgent}><CircleStop className=\"w-3.5 h-3.5\" /></Button>}\n {(agent.branchState === 'changes' || agent.branchState === 'idle') && agent.branchWorkspaceId && <Button variant=\"ghost\" size=\"icon-sm\" className=\"hidden @4xl/chat:inline-flex text-amber-400 hover:text-amber-300\" title=\"Mark workspace ready — hand off to the auto-merge\" onClick={() => openConfirm('Mark Workspace Ready', `Mark ${displayName(agent)}'s branch ready to land? The relay auto-merge will rebase and land it.`, () => workspaceAction(agent.branchWorkspaceId!, 'ready'))}><Flag className=\"w-3.5 h-3.5\" /></Button>}\n {canCompact && <Button variant=\"ghost\" size=\"icon-sm\" className=\"hidden @4xl/chat:inline-flex\" title=\"Compact\" onClick={() => openConfirm('Compact Agent', `Compact context for ${displayName(agent)}?`, () => doAgentAction(agent, 'compact'))}><Minimize2 className=\"w-3.5 h-3.5\" /></Button>}\n {canClearContext && <Button variant=\"ghost\" size=\"icon-sm\" className=\"hidden @4xl/chat:inline-flex\" title=\"Clear context\" onClick={() => openConfirm('Clear Context', `Clear context for ${displayName(agent)}?`, () => doAgentAction(agent, 'clearContext'))}><Eraser className=\"w-3.5 h-3.5\" /></Button>}\n {canShutdown && <Button variant=\"ghost\" size=\"icon-sm\" className=\"hidden @4xl/chat:inline-flex\" title=\"Shutdown\" onClick={() => openConfirm('Shutdown Agent', `Shutdown ${displayName(agent)}?`, () => doAgentAction(agent, 'shutdown'))}><Power className=\"w-3.5 h-3.5\" /></Button>}\n {agent && typeof agent.meta?.cwd === 'string' && agent.meta.cwd && <Button variant=\"ghost\" size=\"icon-sm\" className=\"hidden @4xl/chat:inline-flex\" title={`Open ${agent.meta.cwd as string} in Files`} onClick={() => void openFilesForAgent(agent)}><FolderOpen className=\"w-3.5 h-3.5\" /></Button>}\n {agent && thread && thread.messages.length > 0 && <Button variant=\"ghost\" size=\"icon-sm\" className=\"hidden @4xl/chat:inline-flex\" title=\"Fork — spawn new agent with this chat history\" onClick={() => forkFromAgent(agent.id, thread.messages)}><GitFork className=\"w-3.5 h-3.5\" /></Button>}\n {thread && <Button variant=\"ghost\" size=\"icon-sm\" className=\"hidden @4xl/chat:inline-flex\" title=\"Mark unread\" onClick={() => markInboxThreadUnread(selectedInboxThread)}><MailX className=\"w-3.5 h-3.5\" /></Button>}\n {thread && <Button variant=\"ghost\" size=\"icon-sm\" className=\"hidden @4xl/chat:inline-flex\" title=\"Mark read\" onClick={() => markInboxThreadRead(thread.peer, thread.messages)}><MailOpen className=\"w-3.5 h-3.5\" /></Button>}\n {exportableThread && <Button variant=\"ghost\" size=\"icon-sm\" className=\"hidden @4xl/chat:inline-flex\" title=\"Export thread\" onClick={() => exportThread({ ...exportableThread, importedHistory }, 'json')}><Download className=\"w-3.5 h-3.5\" /></Button>}\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"icon-sm\" className=\"@4xl/chat:hidden\"><MoreHorizontal className=\"w-3.5 h-3.5\" /></Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n {canOpenTerminal && <DropdownMenuItem disabled={terminalOpening} onClick={() => void handleOpenTerminal()}><Terminal className=\"w-3.5 h-3.5\" />Terminal</DropdownMenuItem>}\n {canInterrupt && <DropdownMenuItem onClick={interruptAgent}><CircleStop className=\"w-3.5 h-3.5\" />Interrupt</DropdownMenuItem>}\n {(agent.branchState === 'changes' || agent.branchState === 'idle') && agent.branchWorkspaceId && <DropdownMenuItem onClick={() => openConfirm('Mark Workspace Ready', `Mark ${displayName(agent)}'s branch ready to land? The relay auto-merge will rebase and land it.`, () => workspaceAction(agent.branchWorkspaceId!, 'ready'))}><Flag className=\"w-3.5 h-3.5\" />Mark Ready</DropdownMenuItem>}\n {canCompact && <DropdownMenuItem onClick={() => openConfirm('Compact Agent', `Compact context for ${displayName(agent)}?`, () => doAgentAction(agent, 'compact'))}><Minimize2 className=\"w-3.5 h-3.5\" />Compact</DropdownMenuItem>}\n {canClearContext && <DropdownMenuItem onClick={() => openConfirm('Clear Context', `Clear context for ${displayName(agent)}?`, () => doAgentAction(agent, 'clearContext'))}><Eraser className=\"w-3.5 h-3.5\" />Clear Context</DropdownMenuItem>}\n {canShutdown && <DropdownMenuItem onClick={() => openConfirm('Shutdown Agent', `Shutdown ${displayName(agent)}?`, () => doAgentAction(agent, 'shutdown'))}><Power className=\"w-3.5 h-3.5\" />Shutdown</DropdownMenuItem>}\n {agent && typeof agent.meta?.cwd === 'string' && agent.meta.cwd && <DropdownMenuItem onClick={() => void openFilesForAgent(agent)}><FolderOpen className=\"w-3.5 h-3.5\" />Open Files</DropdownMenuItem>}\n {agent && thread && thread.messages.length > 0 && <DropdownMenuItem onClick={() => forkFromAgent(agent.id, thread.messages)}><GitFork className=\"w-3.5 h-3.5\" />Fork</DropdownMenuItem>}\n {(canOpenTerminal || canCompact || canClearContext || canShutdown) && <DropdownMenuSeparator />}\n {thread && <DropdownMenuItem onClick={() => markInboxThreadUnread(selectedInboxThread)}><MailX className=\"w-3.5 h-3.5\" />Mark Unread</DropdownMenuItem>}\n {thread && <DropdownMenuItem onClick={() => markInboxThreadRead(thread.peer, thread.messages)}><MailOpen className=\"w-3.5 h-3.5\" />Mark Read</DropdownMenuItem>}\n {exportableThread && <DropdownMenuItem onClick={() => exportThread({ ...exportableThread, importedHistory }, 'json')}><Download className=\"w-3.5 h-3.5\" />Download</DropdownMenuItem>}\n </DropdownMenuContent>\n </DropdownMenu>\n </>\n )}\n </div>\n </div>\n\n {/* Timeline */}\n <div\n ref={pinnedScroll.ref}\n onScroll={pinnedScroll.onScroll}\n className=\"flex-1 overflow-y-auto px-3 md:px-4 py-3 md:py-4\"\n style={{ minHeight: 0 }}\n >\n {timeline.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center h-full text-center\">\n <MessageSquare className=\"w-8 h-8 text-zinc-600 mb-2\" />\n <p className=\"text-xs text-muted-foreground\">No messages yet</p>\n </div>\n ) : (\n <div>\n <StickyPromptBanner scrollRef={pinnedScroll.ref} timeline={timeline} />\n {timeline.map((entry) => {\n if (entry.type === 'message') {\n return (\n <MessageBubble\n key={entry.msg.id}\n msg={entry.msg}\n peer={selectedInboxThread}\n onOpenReferencedPath={openReferencedFile}\n onPreviewReferencedPath={previewReferencedFile}\n onPreviewReferencedPathEnd={scheduleCloseReferencedFilePreview}\n />\n )\n }\n if (entry.type === 'activity') return <ActivityTrace key={`act-${entry.steps[0]?.id ?? entry.timestamp}`} steps={entry.steps} showReasoning={showReasoning} />\n if (entry.type === 'import-boundary') return <ImportedHistoryMarker key={`import-${entry.history.id}`} history={entry.history} />\n if (entry.type === 'imported-message') {\n return (\n <ImportedMessageBubble\n key={`import-${entry.history.id}-${entry.entry.originalMessageId}-${entry.entry.position}`}\n entry={entry.entry}\n sourceLabel={entry.history.sourceAgentLabel || entry.history.sourcePeerId}\n />\n )\n }\n if (entry.type === 'status') return <StatusMarker key={entry.event.id} event={entry.event} />\n if (entry.type === 'date') return <DateSeparator key={`d-${entry.date}`} date={entry.date} />\n if (entry.type === 'created') return <CreatedMarker key=\"created\" timestamp={entry.timestamp} />\n return null\n })}\n {pendingApproval && agent && <PermissionRequestBubble agentId={agent.id} approval={pendingApproval} />}\n {agent?.status === 'busy' && !pendingApproval && <BusyIndicator blockedLabel={blockedState?.label} onInterrupt={canInterrupt ? interruptAgent : undefined} />}\n </div>\n )}\n </div>\n\n {/* Composer */}\n <div\n className={cn(\n 'relative shrink-0 border-t border-border px-3 md:px-4 py-2.5 md:py-3 safe-area-bottom',\n dragActive && 'bg-primary/5 ring-1 ring-primary/40'\n )}\n onDragOver={(e) => { e.preventDefault(); setDragActive(true) }}\n onDragLeave={() => setDragActive(false)}\n onDrop={(e) => {\n e.preventDefault()\n setDragActive(false)\n void uploadFiles(e.dataTransfer.files)\n }}\n >\n {pendingAttachments.length > 0 && (\n <div className=\"mb-2 grid gap-2 sm:grid-cols-2\">\n {pendingAttachments.map((item) => (\n <PendingAttachmentPreview key={item.id} item={item} onRemove={() => removePendingAttachment(item.id)} />\n ))}\n </div>\n )}\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n className=\"hidden\"\n onChange={(e) => {\n if (e.target.files) void uploadFiles(e.target.files)\n e.currentTarget.value = ''\n }}\n />\n {slashMatches.length > 0 && (\n <div className=\"absolute bottom-full left-3 right-3 md:left-4 md:right-4 mb-2 z-20 max-h-64 overflow-auto rounded-xl border border-border bg-popover shadow-lg\">\n {slashMatches.map((cmd, i) => (\n <button\n key={cmd.name}\n onMouseDown={(e) => { e.preventDefault(); acceptSlash(cmd) }}\n onMouseEnter={() => setSlashIndex(i)}\n className={cn('flex w-full items-baseline gap-2 px-3 py-1.5 text-left text-sm', i === slashActiveIndex ? 'bg-accent' : 'hover:bg-accent/50')}\n >\n <span className=\"font-medium shrink-0\">{cmd.name}</span>\n {cmd.argumentHint && <span className=\"text-xs text-muted-foreground shrink-0\">{cmd.argumentHint}</span>}\n {cmd.description && <span className=\"ml-auto truncate text-xs text-muted-foreground/70\">{cmd.description}</span>}\n </button>\n ))}\n </div>\n )}\n {/* Desktop: horizontal row */}\n <div className=\"hidden md:flex items-end gap-2\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n title=\"Attach files\"\n disabled={chatSending}\n onClick={() => fileInputRef.current?.click()}\n className=\"shrink-0 mb-0.5 rounded-xl h-[42px] w-[42px]\"\n >\n <Paperclip className=\"w-4 h-4\" />\n </Button>\n <AutoGrowTextarea\n value={draft}\n onChange={(e) => handleDraftChange(e.target.value)}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n placeholder={`Message ${agent ? displayName(agent) : selectedInboxThread}…`}\n className=\"flex-1\"\n />\n {micAvailable && (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n title={micState === 'recording' ? 'Release to transcribe' : 'Hold to talk'}\n disabled={chatSending || micState === 'transcribing'}\n onPointerDown={(e) => { e.preventDefault(); e.currentTarget.setPointerCapture(e.pointerId); void startPtt() }}\n onPointerUp={(e) => { e.preventDefault(); try { e.currentTarget.releasePointerCapture(e.pointerId) } catch { /* ignore */ } void stopPtt() }}\n className={`shrink-0 mb-0.5 rounded-xl h-[42px] w-[42px] ${micState === 'recording' ? 'text-red-400 animate-pulse' : ''}`}\n >\n {micState === 'transcribing' ? <Loader2 className=\"w-4 h-4 animate-spin\" /> : <Mic className=\"w-4 h-4\" />}\n </Button>\n )}\n <Button\n size=\"icon\"\n disabled={(!draft.trim() && readyAttachments.length === 0) || hasPendingUploads || chatSending || agentFinalizing}\n onClick={handleSend}\n className=\"shrink-0 mb-0.5 rounded-xl h-[42px] w-[42px]\"\n >\n <Send className=\"w-4 h-4\" />\n </Button>\n </div>\n {/* Mobile: textarea full width, buttons below */}\n <div className=\"md:hidden space-y-2\">\n <AutoGrowTextarea\n value={draft}\n onChange={(e) => handleDraftChange(e.target.value)}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n placeholder={`Message ${agent ? displayName(agent) : selectedInboxThread}…`}\n className=\"w-full\"\n />\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n title=\"Attach files\"\n disabled={chatSending}\n onClick={() => fileInputRef.current?.click()}\n className=\"rounded-xl h-9 w-9\"\n >\n <Paperclip className=\"w-4 h-4\" />\n </Button>\n {micAvailable && (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n title={micState === 'recording' ? 'Release to transcribe' : 'Hold to talk'}\n disabled={chatSending || micState === 'transcribing'}\n onPointerDown={(e) => { e.preventDefault(); e.currentTarget.setPointerCapture(e.pointerId); void startPtt() }}\n onPointerUp={(e) => { e.preventDefault(); try { e.currentTarget.releasePointerCapture(e.pointerId) } catch { /* ignore */ } void stopPtt() }}\n className={`rounded-xl h-9 w-9 ${micState === 'recording' ? 'text-red-400 animate-pulse' : ''}`}\n >\n {micState === 'transcribing' ? <Loader2 className=\"w-4 h-4 animate-spin\" /> : <Mic className=\"w-4 h-4\" />}\n </Button>\n )}\n </div>\n <Button\n size=\"icon\"\n disabled={(!draft.trim() && readyAttachments.length === 0) || hasPendingUploads || chatSending || agentFinalizing}\n onClick={handleSend}\n className=\"rounded-xl h-9 w-9\"\n >\n <Send className=\"w-4 h-4\" />\n </Button>\n </div>\n </div>\n <p className=\"text-xs text-muted-foreground mt-1.5 hidden md:block\">\n {agentFinalizing\n ? `${agent ? displayName(agent) : 'Agent'} is wrapping up (${(agent?.meta?.lifecycleAction as string).slice('finalizing-'.length)}) — messaging paused`\n : 'Enter to send · Shift+Enter for newline'}\n </p>\n </div>\n </div>\n {filePreview && (\n <aside\n className=\"hidden h-full w-[min(44vw,720px)] min-w-[360px] shrink-0 flex-col border-l border-border bg-background xl:flex\"\n >\n <div className=\"flex h-10 shrink-0 items-center gap-2 border-b border-border px-3\">\n <span className=\"min-w-0 flex-1 text-xs font-medium text-muted-foreground\">File preview</span>\n {filePreviewError && <span className=\"max-w-[18rem] truncate text-xs text-red-400\">{filePreviewError}</span>}\n <Button variant=\"ghost\" size=\"icon-sm\" title=\"Close preview\" onClick={closeFilePreview}>\n <X className=\"h-3.5 w-3.5\" />\n </Button>\n </div>\n <div className=\"min-h-0 flex-1\">\n {filePreview.type === 'directory' ? (\n <DirectoryContent\n orchestratorId={filePreview.orchestratorId}\n selectedPath={filePreview.path}\n onReadError={setFilePreviewError}\n />\n ) : (\n <FileContent\n orchestratorId={filePreview.orchestratorId}\n selectedPath={filePreview.path}\n line={filePreview.line}\n onReadError={setFilePreviewError}\n />\n )}\n </div>\n </aside>\n )}\n </div>\n {floatingPreview && (\n <FloatingFilePreview\n preview={floatingPreview}\n error={filePreviewError}\n onReadError={setFilePreviewError}\n onMouseEnter={clearFilePreviewCloseTimer}\n onMouseLeave={scheduleCloseReferencedFilePreview}\n />\n )}\n {terminalTarget && (\n <TerminalDialog open={terminalOpen} onOpenChange={handleCloseTerminal} orchestratorId={terminalTarget.orchestratorId} session={terminalTarget.session} interactive={terminalTarget.interactive || canWriteTerminal} />\n )}\n </>\n )\n}\n\n// ─── ChatView ────────────────────────────────────────────────────────────────\n\nexport function ChatView() {\n const threads = useAllInboxThreads()\n const selectedInboxThread = useRelayStore((s) => s.selectedInboxThread)\n const set = useRelayStore((s) => s.set)\n const visibleChatAgents = useChatAgents()\n const mobileShowChat = Boolean(selectedInboxThread)\n\n useDraftCleanup()\n\n useEffect(() => {\n if (!selectedInboxThread) return\n if (!visibleChatAgents.some((agent) => agent.id === selectedInboxThread)) {\n set({ selectedInboxThread: '' })\n }\n }, [selectedInboxThread, visibleChatAgents, set])\n\n function handleMobileBack() {\n set({ selectedInboxThread: '' })\n }\n\n return (\n <div\n className=\"flex -m-4 md:-m-6\"\n style={{ height: 'calc(100dvh - var(--header-h) - var(--sat))' }}\n >\n {/* Desktop: side-by-side layout */}\n <div className=\"hidden md:flex w-full\">\n {/* Left: agent list — 1/3 */}\n <div className=\"w-1/3 min-w-[240px] max-w-xs flex flex-col overflow-hidden\">\n <AgentListPanel threads={threads} />\n </div>\n\n {/* Right: chat — 2/3 */}\n <div className=\"flex-1 flex flex-col overflow-hidden\">\n <ChatPanel key={selectedInboxThread || 'empty'} threads={threads} />\n </div>\n </div>\n\n {/* Mobile: single panel toggle */}\n <div className=\"md:hidden flex w-full overflow-hidden\">\n {!mobileShowChat ? (\n <div className=\"w-full flex flex-col overflow-hidden\">\n <AgentListPanel threads={threads} />\n </div>\n ) : (\n <MobileChatContainer>\n <ChatPanel key={selectedInboxThread || 'empty'} threads={threads} onBack={handleMobileBack} showBackButton />\n </MobileChatContainer>\n )}\n </div>\n </div>\n )\n}\n\nfunction MobileChatContainer({ children }: { children: React.ReactNode }) {\n const height = useKeyboardViewportHeight()\n\n return (\n <div\n className=\"fixed inset-x-0 top-0 z-40 flex flex-col bg-background pt-[var(--sat)]\"\n style={{ height: height ? `${height}px` : '100dvh' }}\n >\n {children}\n </div>\n )\n}\n"],"mappings":"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"}