agent-relay-server 0.90.0 → 0.91.1

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 (63) hide show
  1. package/docs/openapi.json +1 -1
  2. package/package.json +2 -2
  3. package/public/assets/{MessageBubble-bI9fFi55.js → MessageBubble-Cl3gC5sO.js} +2 -2
  4. package/public/assets/{MessageBubble-bI9fFi55.js.map → MessageBubble-Cl3gC5sO.js.map} +1 -1
  5. package/public/assets/{PlanGraphPanel-a3Z57nIZ.js → PlanGraphPanel-BAu-lTm9.js} +2 -2
  6. package/public/assets/{PlanGraphPanel-a3Z57nIZ.js.map → PlanGraphPanel-BAu-lTm9.js.map} +1 -1
  7. package/public/assets/{activity-VTlBVIox.js → activity-navjipA_.js} +2 -2
  8. package/public/assets/{activity-VTlBVIox.js.map → activity-navjipA_.js.map} +1 -1
  9. package/public/assets/{agents-C2TNRCn1.js → agents-B09rJRik.js} +2 -2
  10. package/public/assets/{agents-C2TNRCn1.js.map → agents-B09rJRik.js.map} +1 -1
  11. package/public/assets/{automation-CUSyRZla.js → automation-BsXT9mKj.js} +2 -2
  12. package/public/assets/{automation-CUSyRZla.js.map → automation-BsXT9mKj.js.map} +1 -1
  13. package/public/assets/chat-Cmv-YVII.js +2 -0
  14. package/public/assets/chat-Cmv-YVII.js.map +1 -0
  15. package/public/assets/{formatted-body-impl-DBbmythT.js → formatted-body-impl-CwziXint.js} +2 -2
  16. package/public/assets/{formatted-body-impl-DBbmythT.js.map → formatted-body-impl-CwziXint.js.map} +1 -1
  17. package/public/assets/{index-CiBdEE9x.js → index-Dm1zlklN.js} +5 -5
  18. package/public/assets/{index-CiBdEE9x.js.map → index-Dm1zlklN.js.map} +1 -1
  19. package/public/assets/{insights-9P_MGbMS.js → insights-CGH0lI9i.js} +2 -2
  20. package/public/assets/{insights-9P_MGbMS.js.map → insights-CGH0lI9i.js.map} +1 -1
  21. package/public/assets/{maintenance-CA1XujU3.js → maintenance-BhpfPv6u.js} +2 -2
  22. package/public/assets/{maintenance-CA1XujU3.js.map → maintenance-BhpfPv6u.js.map} +1 -1
  23. package/public/assets/{managed-agents-DCfSlqW7.js → managed-agents-CwjcuvR6.js} +2 -2
  24. package/public/assets/{managed-agents-DCfSlqW7.js.map → managed-agents-CwjcuvR6.js.map} +1 -1
  25. package/public/assets/{markdown-preview-impl-MgZ3Nr7K.js → markdown-preview-impl-KBRWvxHt.js} +2 -2
  26. package/public/assets/{markdown-preview-impl-MgZ3Nr7K.js.map → markdown-preview-impl-KBRWvxHt.js.map} +1 -1
  27. package/public/assets/{memory-DatJLjrc.js → memory-CgpkkEKK.js} +2 -2
  28. package/public/assets/{memory-DatJLjrc.js.map → memory-CgpkkEKK.js.map} +1 -1
  29. package/public/assets/{messages-CQsmbtzx.js → messages-BV1z5tMO.js} +2 -2
  30. package/public/assets/{messages-CQsmbtzx.js.map → messages-BV1z5tMO.js.map} +1 -1
  31. package/public/assets/{orchestrators-CAWYWXmh.js → orchestrators-Bv6T_n-l.js} +2 -2
  32. package/public/assets/{orchestrators-CAWYWXmh.js.map → orchestrators-Bv6T_n-l.js.map} +1 -1
  33. package/public/assets/{overview-EqnqXVUb.js → overview-BdErDjo5.js} +2 -2
  34. package/public/assets/{overview-EqnqXVUb.js.map → overview-BdErDjo5.js.map} +1 -1
  35. package/public/assets/{pairs-BfKenirO.js → pairs-BpzbJ5OL.js} +2 -2
  36. package/public/assets/{pairs-BfKenirO.js.map → pairs-BpzbJ5OL.js.map} +1 -1
  37. package/public/assets/{security-CJVJ9MgS.js → security-CRsIxNpi.js} +2 -2
  38. package/public/assets/{security-CJVJ9MgS.js.map → security-CRsIxNpi.js.map} +1 -1
  39. package/public/assets/{select-BcmIzk-E.js → select-DmZ1eEzM.js} +2 -2
  40. package/public/assets/{select-BcmIzk-E.js.map → select-DmZ1eEzM.js.map} +1 -1
  41. package/public/assets/{settings-BWO-UyHv.js → settings-BqmYUpOu.js} +2 -2
  42. package/public/assets/{settings-BWO-UyHv.js.map → settings-BqmYUpOu.js.map} +1 -1
  43. package/public/assets/{tasks-DTdI_MJi.js → tasks-DZ8C8K2N.js} +2 -2
  44. package/public/assets/{tasks-DTdI_MJi.js.map → tasks-DZ8C8K2N.js.map} +1 -1
  45. package/public/assets/{teams-C9C3KVaV.js → teams-VmX_6z_9.js} +2 -2
  46. package/public/assets/{teams-C9C3KVaV.js.map → teams-VmX_6z_9.js.map} +1 -1
  47. package/public/assets/{terminal-viewer-impl-BDBa94-B.js → terminal-viewer-impl-BJilWDSR.js} +2 -2
  48. package/public/assets/{terminal-viewer-impl-BDBa94-B.js.map → terminal-viewer-impl-BJilWDSR.js.map} +1 -1
  49. package/public/assets/{user-avatar-BL-CJwnn.js → user-avatar-jqI4eKDf.js} +2 -2
  50. package/public/assets/{user-avatar-BL-CJwnn.js.map → user-avatar-jqI4eKDf.js.map} +1 -1
  51. package/public/assets/{work-queue-Vc_2-4DG.js → work-queue-lFDBNpds.js} +2 -2
  52. package/public/assets/{work-queue-Vc_2-4DG.js.map → work-queue-lFDBNpds.js.map} +1 -1
  53. package/public/index.html +1 -1
  54. package/runner/src/adapter.ts +4 -0
  55. package/src/config-store.ts +14 -0
  56. package/src/mcp/tools-spawn.ts +3 -0
  57. package/src/routes/agents-spawn.ts +2 -0
  58. package/src/self-resume.ts +21 -5
  59. package/src/services/register-agent.ts +4 -1
  60. package/src/services/spawn-agent.ts +18 -0
  61. package/src/shared-mcp.ts +57 -0
  62. package/public/assets/chat-BEssCn_H.js +0 -2
  63. package/public/assets/chat-BEssCn_H.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"PlanGraphPanel-a3Z57nIZ.js","names":[],"sources":["../../dashboard/src/components/chat/hooks/useIsMobile.ts","../../dashboard/src/components/chat/PlanGraphPanel.tsx"],"sourcesContent":["import { useSyncExternalStore } from 'react'\n\n// Reactive narrow-viewport flag. Subscribes to the same `max-width: 767px`\n// breakpoint the chat single-pane layout uses, via useSyncExternalStore — an\n// external-store subscription, not effect-driven derived state — so it stays\n// correct across resize/rotate without a useEffect.\nconst QUERY = '(max-width: 767px)'\n\nfunction subscribe(cb: () => void): () => void {\n if (typeof window === 'undefined') return () => {}\n const mql = window.matchMedia(QUERY)\n mql.addEventListener('change', cb)\n return () => mql.removeEventListener('change', cb)\n}\n\nexport function useIsMobile(): boolean {\n return useSyncExternalStore(\n subscribe,\n () => (typeof window !== 'undefined' ? window.matchMedia(QUERY).matches : false),\n () => false,\n )\n}\n","import { useEffect, useMemo } from 'react'\nimport { ChevronDown, ChevronUp, GitBranch } from 'lucide-react'\nimport { useRelayStore } from '@/store'\nimport type { Plan, PlanNode, PlanOwnerRef, PlanStatus } from '@/types'\nimport { cn } from '@/lib/utils'\nimport { planLookupKey, planTeamLookupKey } from '@/store/slices/plans'\nimport { IssueRefChip } from '@/components/shared/issue-ref-chip'\nimport { useIsMobile } from './hooks/useIsMobile'\n\n// Left-to-right DAG: dependency depth flows along x (sequential gates), nodes\n// that share a depth stack along y (parallel lanes). This keeps the panel SHORT\n// — it's an operator overlay above the chat, not a full view — and lets the\n// gate-vs-lane structure read at a glance. Height is capped + scrollable below.\nconst NODE_W = 196\nconst NODE_H = 84\nconst COL_GAP = 52\nconst ROW_GAP = 16\nconst PAD = 14\n\nconst STATUS_ORDER: PlanStatus[] = ['landed', 'in-progress', 'pending', 'blocked']\n\nconst STATUS_STYLE: Record<\n PlanStatus,\n { label: string; dot: string; accent: string; text: string; wire: string }\n> = {\n landed: { label: 'landed', dot: 'bg-emerald-400', accent: 'border-l-emerald-400', text: 'text-emerald-300', wire: '#34d399' },\n 'in-progress': { label: 'in progress', dot: 'bg-sky-400', accent: 'border-l-sky-400', text: 'text-sky-300', wire: '#38bdf8' },\n pending: { label: 'pending', dot: 'bg-amber-400', accent: 'border-l-amber-400', text: 'text-amber-300', wire: '#fbbf24' },\n blocked: { label: 'blocked', dot: 'bg-red-400', accent: 'border-l-red-400', text: 'text-red-300', wire: '#f87171' },\n}\n\ninterface LayoutNode {\n node: PlanNode\n x: number\n y: number\n layer: number\n}\n\nfunction ownerLabel(owner?: PlanOwnerRef): string {\n if (!owner) return ''\n return owner.label || (owner.policyName ? `policy:${owner.policyName}` : owner.agentId || '')\n}\n\nfunction layerPlan(plan: Plan): { nodes: LayoutNode[]; width: number; height: number } {\n const nodeById = new Map(plan.nodes.map((node) => [node.id, node]))\n const indexById = new Map(plan.nodes.map((node, index) => [node.id, index]))\n const outgoing = new Map<string, string[]>()\n const indegree = new Map(plan.nodes.map((node) => [node.id, 0]))\n for (const edge of plan.edges) {\n if (!nodeById.has(edge.from) || !nodeById.has(edge.to)) continue\n outgoing.set(edge.from, [...(outgoing.get(edge.from) ?? []), edge.to])\n indegree.set(edge.to, (indegree.get(edge.to) ?? 0) + 1)\n }\n\n const layerById = new Map(plan.nodes.map((node) => [node.id, 0]))\n const queue = plan.nodes\n .filter((node) => (indegree.get(node.id) ?? 0) === 0)\n .map((node) => node.id)\n const visited = new Set<string>()\n\n while (queue.length) {\n const id = queue.shift()!\n visited.add(id)\n const fromLayer = layerById.get(id) ?? 0\n for (const to of outgoing.get(id) ?? []) {\n layerById.set(to, Math.max(layerById.get(to) ?? 0, fromLayer + 1))\n indegree.set(to, (indegree.get(to) ?? 0) - 1)\n if ((indegree.get(to) ?? 0) === 0) queue.push(to)\n }\n }\n\n let fallbackLayer = Math.max(0, ...Array.from(layerById.values())) + 1\n for (const node of plan.nodes) {\n if (visited.has(node.id)) continue\n layerById.set(node.id, fallbackLayer++)\n }\n\n const layers = new Map<number, PlanNode[]>()\n for (const node of plan.nodes) {\n const layer = layerById.get(node.id) ?? 0\n layers.set(layer, [...(layers.get(layer) ?? []), node])\n }\n\n const orderedLayers = [...layers.entries()].sort(([a], [b]) => a - b)\n const maxRows = Math.max(1, ...orderedLayers.map(([, nodes]) => nodes.length))\n const rowPitch = NODE_H + ROW_GAP\n\n const layoutNodes: LayoutNode[] = []\n orderedLayers.forEach(([layer, nodes], col) => {\n const ordered = [...nodes].sort((a, b) => {\n const lane = (a.lane || '').localeCompare(b.lane || '')\n return lane || ((indexById.get(a.id) ?? 0) - (indexById.get(b.id) ?? 0))\n })\n // Center each column vertically against the tallest column so the spine\n // runs through the middle and the parallel fan reads as a fan.\n const offset = ((maxRows - ordered.length) * rowPitch) / 2\n ordered.forEach((node, row) => {\n layoutNodes.push({\n node,\n layer,\n x: PAD + col * (NODE_W + COL_GAP),\n y: PAD + offset + row * rowPitch,\n })\n })\n })\n\n const cols = orderedLayers.length\n return {\n nodes: layoutNodes,\n width: Math.max(320, PAD * 2 + cols * NODE_W + Math.max(0, cols - 1) * COL_GAP),\n height: Math.max(NODE_H + PAD * 2, PAD * 2 + maxRows * NODE_H + Math.max(0, maxRows - 1) * ROW_GAP),\n }\n}\n\nfunction edgePath(from: LayoutNode, to: LayoutNode): string {\n const x1 = from.x + NODE_W\n const y1 = from.y + NODE_H / 2\n const x2 = to.x\n const y2 = to.y + NODE_H / 2\n const midX = x1 + Math.max(20, (x2 - x1) / 2)\n return `M ${x1} ${y1} C ${midX} ${y1}, ${midX} ${y2}, ${x2} ${y2}`\n}\n\nexport function PlanGraphPanel({ threadId, teamId, channel }: { threadId?: string | number | null; teamId?: string | null; channel?: string }) {\n const key = teamId ? planTeamLookupKey(teamId, channel) : threadId ? planLookupKey(threadId, channel) : ''\n const plan = useRelayStore((s) => teamId ? s.plansByTeam[key] : key ? s.plansByThread[key] : null)\n const fetchPlan = useRelayStore((s) => s.fetchPlan)\n const planCollapsed = useRelayStore((s) => s.planCollapsed)\n const setPlanCollapsed = useRelayStore((s) => s.setPlanCollapsed)\n const issueRefsById = useRelayStore((s) => s.issueRefsById)\n const isMobile = useIsMobile()\n // null = no manual toggle yet → follow the viewport default. The graph\n // dominates a phone screen, so it starts collapsed there and expanded on\n // desktop; an explicit user toggle (persisted) overrides the default.\n const collapsed = planCollapsed ?? isMobile\n\n useEffect(() => {\n if (teamId) {\n void fetchPlan({ teamId, channel })\n return\n }\n if (threadId) void fetchPlan({ threadId, channel })\n }, [channel, fetchPlan, teamId, threadId])\n\n const layout = useMemo(() => plan ? layerPlan(plan) : null, [plan])\n const nodeById = useMemo(() => new Map(layout?.nodes.map((node) => [node.node.id, node]) ?? []), [layout])\n\n const legend = useMemo(() => {\n if (!plan) return []\n const counts = new Map<PlanStatus, number>()\n for (const node of plan.nodes) counts.set(node.status, (counts.get(node.status) ?? 0) + 1)\n return STATUS_ORDER.filter((status) => counts.has(status)).map((status) => ({\n status,\n count: counts.get(status) ?? 0,\n }))\n }, [plan])\n\n if (!plan || !layout) return null\n\n const nodeCount = plan.nodes.length\n const landedCount = legend.find((entry) => entry.status === 'landed')?.count ?? 0\n // Thin summary for the collapsed bar (the legend dots are hidden on mobile),\n // e.g. \"5 nodes · 4 landed\".\n const summary = `${nodeCount} node${nodeCount === 1 ? '' : 's'}${landedCount > 0 ? ` · ${landedCount} landed` : ''}`\n\n return (\n <section className=\"shrink-0 border-b border-border bg-card/45 px-3 py-2\">\n <button\n type=\"button\"\n onClick={() => setPlanCollapsed(!collapsed)}\n aria-expanded={!collapsed}\n aria-label={collapsed ? 'Expand plan graph' : 'Collapse plan graph'}\n className={cn(\n 'flex w-full min-w-0 items-center gap-2 text-left',\n !collapsed && 'mb-2',\n )}\n >\n <span className=\"flex h-5 w-5 shrink-0 items-center justify-center rounded bg-muted/60\">\n <GitBranch className=\"h-3 w-3 text-muted-foreground\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-[13px] font-semibold leading-tight text-foreground\">{plan.title || 'Plan'}</div>\n <div className=\"truncate text-[11px] leading-tight text-muted-foreground\">\n {collapsed ? summary : (plan.objective || summary)}\n </div>\n </div>\n {legend.length > 0 && (\n <div className=\"hidden shrink-0 items-center gap-2.5 sm:flex\">\n {legend.map(({ status, count }) => (\n <span key={status} className=\"flex items-center gap-1 text-[10px] text-muted-foreground\">\n <span className={cn('h-1.5 w-1.5 rounded-full', STATUS_STYLE[status].dot)} />\n <span className={cn('font-medium tabular-nums', STATUS_STYLE[status].text)}>{count}</span>\n <span>{STATUS_STYLE[status].label}</span>\n </span>\n ))}\n </div>\n )}\n <span className=\"shrink-0 rounded bg-muted/60 px-1.5 py-0.5 text-[10px] font-medium tabular-nums text-muted-foreground\">\n v{plan.version}\n </span>\n <span className=\"flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-muted/60 hover:text-foreground\">\n {collapsed ? <ChevronDown className=\"h-3.5 w-3.5\" /> : <ChevronUp className=\"h-3.5 w-3.5\" />}\n </span>\n </button>\n {collapsed ? null : plan.nodes.length === 0 ? (\n <div className=\"rounded-md border border-dashed border-border px-3 py-3 text-center text-xs text-muted-foreground\">\n No nodes yet — the plan graph fills in as the team is composed.\n </div>\n ) : (\n <div className=\"max-h-[min(46vh,360px)] overflow-auto\">\n <div className=\"relative\" style={{ width: layout.width, height: layout.height }}>\n <svg className=\"pointer-events-none absolute inset-0\" width={layout.width} height={layout.height} aria-hidden=\"true\">\n <defs>\n {STATUS_ORDER.map((status) => (\n <marker\n key={status}\n id={`plan-arrow-${status}`}\n viewBox=\"0 0 8 8\"\n refX=\"6.5\"\n refY=\"4\"\n markerWidth=\"6\"\n markerHeight=\"6\"\n orient=\"auto-start-reverse\"\n >\n <path d=\"M0 0 L8 4 L0 8 z\" fill={STATUS_STYLE[status].wire} />\n </marker>\n ))}\n </defs>\n {plan.edges.map((edge) => {\n const from = nodeById.get(edge.from)\n const to = nodeById.get(edge.to)\n if (!from || !to) return null\n const wire = STATUS_STYLE[from.node.status]\n return (\n <path\n key={`${edge.from}->${edge.to}`}\n d={edgePath(from, to)}\n stroke={wire.wire}\n strokeOpacity={0.7}\n strokeWidth={2}\n fill=\"none\"\n strokeLinecap=\"round\"\n markerEnd={`url(#plan-arrow-${from.node.status})`}\n />\n )\n })}\n </svg>\n {layout.nodes.map(({ node, x, y }) => {\n const status = STATUS_STYLE[node.status]\n const owner = ownerLabel(node.ownerRef)\n const issueRef = node.refs?.issueId ? issueRefsById[node.refs.issueId] : null\n return (\n <article\n key={node.id}\n className={cn(\n 'group absolute flex flex-col justify-between rounded-md border border-l-[3px] bg-background/95 p-2',\n 'shadow-sm transition-all hover:-translate-y-px hover:border-border hover:shadow-md hover:bg-background',\n status.accent,\n )}\n style={{ left: x, top: y, width: NODE_W, height: NODE_H }}\n title={node.scopeBlurb || node.label}\n >\n <div className=\"truncate text-xs font-semibold leading-tight text-foreground\">{node.label}</div>\n {(node.scopeBlurb || node.id) && (\n <div className=\"truncate text-[10px] leading-tight text-muted-foreground\">{node.scopeBlurb || node.id}</div>\n )}\n {issueRef && (\n <div className=\"min-w-0\">\n <IssueRefChip issueRef={issueRef} compact className=\"max-w-full\" />\n </div>\n )}\n <div className=\"flex min-w-0 items-center justify-between gap-1.5\">\n <div className=\"flex shrink-0 items-center gap-1.5\">\n <span className={cn('h-1.5 w-1.5 shrink-0 rounded-full', status.dot)} />\n <span className={cn('text-[10px] font-medium', status.text)}>{status.label}</span>\n </div>\n <div className=\"flex min-w-0 items-center gap-1.5\">\n {owner && <span className=\"truncate text-[10px] text-muted-foreground\">{owner}</span>}\n {node.lane && (\n <span className=\"shrink-0 rounded-sm bg-muted/70 px-1 py-px text-[9px] font-medium uppercase tracking-wide text-muted-foreground\">\n {node.lane}\n </span>\n )}\n </div>\n </div>\n </article>\n )\n })}\n </div>\n </div>\n )}\n </section>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"PlanGraphPanel-BAu-lTm9.js","names":[],"sources":["../../dashboard/src/components/chat/hooks/useIsMobile.ts","../../dashboard/src/components/chat/PlanGraphPanel.tsx"],"sourcesContent":["import { useSyncExternalStore } from 'react'\n\n// Reactive narrow-viewport flag. Subscribes to the same `max-width: 767px`\n// breakpoint the chat single-pane layout uses, via useSyncExternalStore — an\n// external-store subscription, not effect-driven derived state — so it stays\n// correct across resize/rotate without a useEffect.\nconst QUERY = '(max-width: 767px)'\n\nfunction subscribe(cb: () => void): () => void {\n if (typeof window === 'undefined') return () => {}\n const mql = window.matchMedia(QUERY)\n mql.addEventListener('change', cb)\n return () => mql.removeEventListener('change', cb)\n}\n\nexport function useIsMobile(): boolean {\n return useSyncExternalStore(\n subscribe,\n () => (typeof window !== 'undefined' ? window.matchMedia(QUERY).matches : false),\n () => false,\n )\n}\n","import { useEffect, useMemo } from 'react'\nimport { ChevronDown, ChevronUp, GitBranch } from 'lucide-react'\nimport { useRelayStore } from '@/store'\nimport type { Plan, PlanNode, PlanOwnerRef, PlanStatus } from '@/types'\nimport { cn } from '@/lib/utils'\nimport { planLookupKey, planTeamLookupKey } from '@/store/slices/plans'\nimport { IssueRefChip } from '@/components/shared/issue-ref-chip'\nimport { useIsMobile } from './hooks/useIsMobile'\n\n// Left-to-right DAG: dependency depth flows along x (sequential gates), nodes\n// that share a depth stack along y (parallel lanes). This keeps the panel SHORT\n// — it's an operator overlay above the chat, not a full view — and lets the\n// gate-vs-lane structure read at a glance. Height is capped + scrollable below.\nconst NODE_W = 196\nconst NODE_H = 84\nconst COL_GAP = 52\nconst ROW_GAP = 16\nconst PAD = 14\n\nconst STATUS_ORDER: PlanStatus[] = ['landed', 'in-progress', 'pending', 'blocked']\n\nconst STATUS_STYLE: Record<\n PlanStatus,\n { label: string; dot: string; accent: string; text: string; wire: string }\n> = {\n landed: { label: 'landed', dot: 'bg-emerald-400', accent: 'border-l-emerald-400', text: 'text-emerald-300', wire: '#34d399' },\n 'in-progress': { label: 'in progress', dot: 'bg-sky-400', accent: 'border-l-sky-400', text: 'text-sky-300', wire: '#38bdf8' },\n pending: { label: 'pending', dot: 'bg-amber-400', accent: 'border-l-amber-400', text: 'text-amber-300', wire: '#fbbf24' },\n blocked: { label: 'blocked', dot: 'bg-red-400', accent: 'border-l-red-400', text: 'text-red-300', wire: '#f87171' },\n}\n\ninterface LayoutNode {\n node: PlanNode\n x: number\n y: number\n layer: number\n}\n\nfunction ownerLabel(owner?: PlanOwnerRef): string {\n if (!owner) return ''\n return owner.label || (owner.policyName ? `policy:${owner.policyName}` : owner.agentId || '')\n}\n\nfunction layerPlan(plan: Plan): { nodes: LayoutNode[]; width: number; height: number } {\n const nodeById = new Map(plan.nodes.map((node) => [node.id, node]))\n const indexById = new Map(plan.nodes.map((node, index) => [node.id, index]))\n const outgoing = new Map<string, string[]>()\n const indegree = new Map(plan.nodes.map((node) => [node.id, 0]))\n for (const edge of plan.edges) {\n if (!nodeById.has(edge.from) || !nodeById.has(edge.to)) continue\n outgoing.set(edge.from, [...(outgoing.get(edge.from) ?? []), edge.to])\n indegree.set(edge.to, (indegree.get(edge.to) ?? 0) + 1)\n }\n\n const layerById = new Map(plan.nodes.map((node) => [node.id, 0]))\n const queue = plan.nodes\n .filter((node) => (indegree.get(node.id) ?? 0) === 0)\n .map((node) => node.id)\n const visited = new Set<string>()\n\n while (queue.length) {\n const id = queue.shift()!\n visited.add(id)\n const fromLayer = layerById.get(id) ?? 0\n for (const to of outgoing.get(id) ?? []) {\n layerById.set(to, Math.max(layerById.get(to) ?? 0, fromLayer + 1))\n indegree.set(to, (indegree.get(to) ?? 0) - 1)\n if ((indegree.get(to) ?? 0) === 0) queue.push(to)\n }\n }\n\n let fallbackLayer = Math.max(0, ...Array.from(layerById.values())) + 1\n for (const node of plan.nodes) {\n if (visited.has(node.id)) continue\n layerById.set(node.id, fallbackLayer++)\n }\n\n const layers = new Map<number, PlanNode[]>()\n for (const node of plan.nodes) {\n const layer = layerById.get(node.id) ?? 0\n layers.set(layer, [...(layers.get(layer) ?? []), node])\n }\n\n const orderedLayers = [...layers.entries()].sort(([a], [b]) => a - b)\n const maxRows = Math.max(1, ...orderedLayers.map(([, nodes]) => nodes.length))\n const rowPitch = NODE_H + ROW_GAP\n\n const layoutNodes: LayoutNode[] = []\n orderedLayers.forEach(([layer, nodes], col) => {\n const ordered = [...nodes].sort((a, b) => {\n const lane = (a.lane || '').localeCompare(b.lane || '')\n return lane || ((indexById.get(a.id) ?? 0) - (indexById.get(b.id) ?? 0))\n })\n // Center each column vertically against the tallest column so the spine\n // runs through the middle and the parallel fan reads as a fan.\n const offset = ((maxRows - ordered.length) * rowPitch) / 2\n ordered.forEach((node, row) => {\n layoutNodes.push({\n node,\n layer,\n x: PAD + col * (NODE_W + COL_GAP),\n y: PAD + offset + row * rowPitch,\n })\n })\n })\n\n const cols = orderedLayers.length\n return {\n nodes: layoutNodes,\n width: Math.max(320, PAD * 2 + cols * NODE_W + Math.max(0, cols - 1) * COL_GAP),\n height: Math.max(NODE_H + PAD * 2, PAD * 2 + maxRows * NODE_H + Math.max(0, maxRows - 1) * ROW_GAP),\n }\n}\n\nfunction edgePath(from: LayoutNode, to: LayoutNode): string {\n const x1 = from.x + NODE_W\n const y1 = from.y + NODE_H / 2\n const x2 = to.x\n const y2 = to.y + NODE_H / 2\n const midX = x1 + Math.max(20, (x2 - x1) / 2)\n return `M ${x1} ${y1} C ${midX} ${y1}, ${midX} ${y2}, ${x2} ${y2}`\n}\n\nexport function PlanGraphPanel({ threadId, teamId, channel }: { threadId?: string | number | null; teamId?: string | null; channel?: string }) {\n const key = teamId ? planTeamLookupKey(teamId, channel) : threadId ? planLookupKey(threadId, channel) : ''\n const plan = useRelayStore((s) => teamId ? s.plansByTeam[key] : key ? s.plansByThread[key] : null)\n const fetchPlan = useRelayStore((s) => s.fetchPlan)\n const planCollapsed = useRelayStore((s) => s.planCollapsed)\n const setPlanCollapsed = useRelayStore((s) => s.setPlanCollapsed)\n const issueRefsById = useRelayStore((s) => s.issueRefsById)\n const isMobile = useIsMobile()\n // null = no manual toggle yet → follow the viewport default. The graph\n // dominates a phone screen, so it starts collapsed there and expanded on\n // desktop; an explicit user toggle (persisted) overrides the default.\n const collapsed = planCollapsed ?? isMobile\n\n useEffect(() => {\n if (teamId) {\n void fetchPlan({ teamId, channel })\n return\n }\n if (threadId) void fetchPlan({ threadId, channel })\n }, [channel, fetchPlan, teamId, threadId])\n\n const layout = useMemo(() => plan ? layerPlan(plan) : null, [plan])\n const nodeById = useMemo(() => new Map(layout?.nodes.map((node) => [node.node.id, node]) ?? []), [layout])\n\n const legend = useMemo(() => {\n if (!plan) return []\n const counts = new Map<PlanStatus, number>()\n for (const node of plan.nodes) counts.set(node.status, (counts.get(node.status) ?? 0) + 1)\n return STATUS_ORDER.filter((status) => counts.has(status)).map((status) => ({\n status,\n count: counts.get(status) ?? 0,\n }))\n }, [plan])\n\n if (!plan || !layout) return null\n\n const nodeCount = plan.nodes.length\n const landedCount = legend.find((entry) => entry.status === 'landed')?.count ?? 0\n // Thin summary for the collapsed bar (the legend dots are hidden on mobile),\n // e.g. \"5 nodes · 4 landed\".\n const summary = `${nodeCount} node${nodeCount === 1 ? '' : 's'}${landedCount > 0 ? ` · ${landedCount} landed` : ''}`\n\n return (\n <section className=\"shrink-0 border-b border-border bg-card/45 px-3 py-2\">\n <button\n type=\"button\"\n onClick={() => setPlanCollapsed(!collapsed)}\n aria-expanded={!collapsed}\n aria-label={collapsed ? 'Expand plan graph' : 'Collapse plan graph'}\n className={cn(\n 'flex w-full min-w-0 items-center gap-2 text-left',\n !collapsed && 'mb-2',\n )}\n >\n <span className=\"flex h-5 w-5 shrink-0 items-center justify-center rounded bg-muted/60\">\n <GitBranch className=\"h-3 w-3 text-muted-foreground\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-[13px] font-semibold leading-tight text-foreground\">{plan.title || 'Plan'}</div>\n <div className=\"truncate text-[11px] leading-tight text-muted-foreground\">\n {collapsed ? summary : (plan.objective || summary)}\n </div>\n </div>\n {legend.length > 0 && (\n <div className=\"hidden shrink-0 items-center gap-2.5 sm:flex\">\n {legend.map(({ status, count }) => (\n <span key={status} className=\"flex items-center gap-1 text-[10px] text-muted-foreground\">\n <span className={cn('h-1.5 w-1.5 rounded-full', STATUS_STYLE[status].dot)} />\n <span className={cn('font-medium tabular-nums', STATUS_STYLE[status].text)}>{count}</span>\n <span>{STATUS_STYLE[status].label}</span>\n </span>\n ))}\n </div>\n )}\n <span className=\"shrink-0 rounded bg-muted/60 px-1.5 py-0.5 text-[10px] font-medium tabular-nums text-muted-foreground\">\n v{plan.version}\n </span>\n <span className=\"flex h-5 w-5 shrink-0 items-center justify-center rounded text-muted-foreground hover:bg-muted/60 hover:text-foreground\">\n {collapsed ? <ChevronDown className=\"h-3.5 w-3.5\" /> : <ChevronUp className=\"h-3.5 w-3.5\" />}\n </span>\n </button>\n {collapsed ? null : plan.nodes.length === 0 ? (\n <div className=\"rounded-md border border-dashed border-border px-3 py-3 text-center text-xs text-muted-foreground\">\n No nodes yet — the plan graph fills in as the team is composed.\n </div>\n ) : (\n <div className=\"max-h-[min(46vh,360px)] overflow-auto\">\n <div className=\"relative\" style={{ width: layout.width, height: layout.height }}>\n <svg className=\"pointer-events-none absolute inset-0\" width={layout.width} height={layout.height} aria-hidden=\"true\">\n <defs>\n {STATUS_ORDER.map((status) => (\n <marker\n key={status}\n id={`plan-arrow-${status}`}\n viewBox=\"0 0 8 8\"\n refX=\"6.5\"\n refY=\"4\"\n markerWidth=\"6\"\n markerHeight=\"6\"\n orient=\"auto-start-reverse\"\n >\n <path d=\"M0 0 L8 4 L0 8 z\" fill={STATUS_STYLE[status].wire} />\n </marker>\n ))}\n </defs>\n {plan.edges.map((edge) => {\n const from = nodeById.get(edge.from)\n const to = nodeById.get(edge.to)\n if (!from || !to) return null\n const wire = STATUS_STYLE[from.node.status]\n return (\n <path\n key={`${edge.from}->${edge.to}`}\n d={edgePath(from, to)}\n stroke={wire.wire}\n strokeOpacity={0.7}\n strokeWidth={2}\n fill=\"none\"\n strokeLinecap=\"round\"\n markerEnd={`url(#plan-arrow-${from.node.status})`}\n />\n )\n })}\n </svg>\n {layout.nodes.map(({ node, x, y }) => {\n const status = STATUS_STYLE[node.status]\n const owner = ownerLabel(node.ownerRef)\n const issueRef = node.refs?.issueId ? issueRefsById[node.refs.issueId] : null\n return (\n <article\n key={node.id}\n className={cn(\n 'group absolute flex flex-col justify-between rounded-md border border-l-[3px] bg-background/95 p-2',\n 'shadow-sm transition-all hover:-translate-y-px hover:border-border hover:shadow-md hover:bg-background',\n status.accent,\n )}\n style={{ left: x, top: y, width: NODE_W, height: NODE_H }}\n title={node.scopeBlurb || node.label}\n >\n <div className=\"truncate text-xs font-semibold leading-tight text-foreground\">{node.label}</div>\n {(node.scopeBlurb || node.id) && (\n <div className=\"truncate text-[10px] leading-tight text-muted-foreground\">{node.scopeBlurb || node.id}</div>\n )}\n {issueRef && (\n <div className=\"min-w-0\">\n <IssueRefChip issueRef={issueRef} compact className=\"max-w-full\" />\n </div>\n )}\n <div className=\"flex min-w-0 items-center justify-between gap-1.5\">\n <div className=\"flex shrink-0 items-center gap-1.5\">\n <span className={cn('h-1.5 w-1.5 shrink-0 rounded-full', status.dot)} />\n <span className={cn('text-[10px] font-medium', status.text)}>{status.label}</span>\n </div>\n <div className=\"flex min-w-0 items-center gap-1.5\">\n {owner && <span className=\"truncate text-[10px] text-muted-foreground\">{owner}</span>}\n {node.lane && (\n <span className=\"shrink-0 rounded-sm bg-muted/70 px-1 py-px text-[9px] font-medium uppercase tracking-wide text-muted-foreground\">\n {node.lane}\n </span>\n )}\n </div>\n </div>\n </article>\n )\n })}\n </div>\n </div>\n )}\n </section>\n )\n}\n"],"mappings":"6OAMM,EAAQ,qBAEd,SAAS,EAAU,EAA4B,CAC7C,GAAI,OAAO,OAAW,IAAa,UAAa,GAChD,IAAM,EAAM,OAAO,WAAW,EAAM,CAEpC,OADA,EAAI,iBAAiB,SAAU,EAAG,KACrB,EAAI,oBAAoB,SAAU,EAAG,CAGpD,SAAgB,GAAuB,CACrC,OAAA,EAAA,EAAA,sBACE,MACO,OAAO,OAAW,IAAc,OAAO,WAAW,EAAM,CAAC,QAAU,OACpE,GACP,WCPG,EAAS,IACT,EAAS,GACT,EAAU,GACV,EAAU,GACV,EAAM,GAEN,EAA6B,CAAC,SAAU,cAAe,UAAW,UAAU,CAE5E,EAGF,CACF,OAAQ,CAAE,MAAO,SAAU,IAAK,iBAAkB,OAAQ,uBAAwB,KAAM,mBAAoB,KAAM,UAAW,CAC7H,cAAe,CAAE,MAAO,cAAe,IAAK,aAAc,OAAQ,mBAAoB,KAAM,eAAgB,KAAM,UAAW,CAC7H,QAAS,CAAE,MAAO,UAAW,IAAK,eAAgB,OAAQ,qBAAsB,KAAM,iBAAkB,KAAM,UAAW,CACzH,QAAS,CAAE,MAAO,UAAW,IAAK,aAAc,OAAQ,mBAAoB,KAAM,eAAgB,KAAM,UAAW,CACpH,CASD,SAAS,EAAW,EAA8B,CAEhD,OADK,EACE,EAAM,QAAU,EAAM,WAAa,UAAU,EAAM,aAAe,EAAM,SAAW,IADvE,GAIrB,SAAS,EAAU,EAAoE,CACrF,IAAM,EAAW,IAAI,IAAI,EAAK,MAAM,IAAK,GAAS,CAAC,EAAK,GAAI,EAAK,CAAC,CAAC,CAC7D,EAAY,IAAI,IAAI,EAAK,MAAM,KAAK,EAAM,IAAU,CAAC,EAAK,GAAI,EAAM,CAAC,CAAC,CACtE,EAAW,IAAI,IACf,EAAW,IAAI,IAAI,EAAK,MAAM,IAAK,GAAS,CAAC,EAAK,GAAI,EAAE,CAAC,CAAC,CAChE,IAAK,IAAM,KAAQ,EAAK,MAClB,CAAC,EAAS,IAAI,EAAK,KAAK,EAAI,CAAC,EAAS,IAAI,EAAK,GAAG,GACtD,EAAS,IAAI,EAAK,KAAM,CAAC,GAAI,EAAS,IAAI,EAAK,KAAK,EAAI,EAAE,CAAG,EAAK,GAAG,CAAC,CACtE,EAAS,IAAI,EAAK,IAAK,EAAS,IAAI,EAAK,GAAG,EAAI,GAAK,EAAE,EAGzD,IAAM,EAAY,IAAI,IAAI,EAAK,MAAM,IAAK,GAAS,CAAC,EAAK,GAAI,EAAE,CAAC,CAAC,CAC3D,EAAQ,EAAK,MAChB,OAAQ,IAAU,EAAS,IAAI,EAAK,GAAG,EAAI,KAAO,EAAE,CACpD,IAAK,GAAS,EAAK,GAAG,CACnB,EAAU,IAAI,IAEpB,KAAO,EAAM,QAAQ,CACnB,IAAM,EAAK,EAAM,OAAO,CACxB,EAAQ,IAAI,EAAG,CACf,IAAM,EAAY,EAAU,IAAI,EAAG,EAAI,EACvC,IAAK,IAAM,KAAM,EAAS,IAAI,EAAG,EAAI,EAAE,CACrC,EAAU,IAAI,EAAI,KAAK,IAAI,EAAU,IAAI,EAAG,EAAI,EAAG,EAAY,EAAE,CAAC,CAClE,EAAS,IAAI,GAAK,EAAS,IAAI,EAAG,EAAI,GAAK,EAAE,EACxC,EAAS,IAAI,EAAG,EAAI,KAAO,GAAG,EAAM,KAAK,EAAG,CAIrD,IAAI,EAAgB,KAAK,IAAI,EAAG,GAAG,MAAM,KAAK,EAAU,QAAQ,CAAC,CAAC,CAAG,EACrE,IAAK,IAAM,KAAQ,EAAK,MAClB,EAAQ,IAAI,EAAK,GAAG,EACxB,EAAU,IAAI,EAAK,GAAI,IAAgB,CAGzC,IAAM,EAAS,IAAI,IACnB,IAAK,IAAM,KAAQ,EAAK,MAAO,CAC7B,IAAM,EAAQ,EAAU,IAAI,EAAK,GAAG,EAAI,EACxC,EAAO,IAAI,EAAO,CAAC,GAAI,EAAO,IAAI,EAAM,EAAI,EAAE,CAAG,EAAK,CAAC,CAGzD,IAAM,EAAgB,CAAC,GAAG,EAAO,SAAS,CAAC,CAAC,MAAM,CAAC,GAAI,CAAC,KAAO,EAAI,EAAE,CAC/D,EAAU,KAAK,IAAI,EAAG,GAAG,EAAc,KAAK,EAAG,KAAW,EAAM,OAAO,CAAC,CACxE,EAAW,EAAS,EAEpB,EAA4B,EAAE,CACpC,EAAc,SAAS,CAAC,EAAO,GAAQ,IAAQ,CAC7C,IAAM,EAAU,CAAC,GAAG,EAAM,CAAC,MAAM,EAAG,KACpB,EAAE,MAAQ,IAAI,cAAc,EAAE,MAAQ,GAC7C,GAAU,EAAU,IAAI,EAAE,GAAG,EAAI,IAAM,EAAU,IAAI,EAAE,GAAG,EAAI,GACrE,CAGI,GAAW,EAAU,EAAQ,QAAU,EAAY,EACzD,EAAQ,SAAS,EAAM,IAAQ,CAC7B,EAAY,KAAK,CACf,OACA,QACA,EAAG,EAAM,GAAO,EAAS,GACzB,EAAG,EAAM,EAAS,EAAM,EACzB,CAAC,EACF,EACF,CAEF,IAAM,EAAO,EAAc,OAC3B,MAAO,CACL,MAAO,EACP,MAAO,KAAK,IAAI,IAAK,EAAM,EAAI,EAAO,EAAS,KAAK,IAAI,EAAG,EAAO,EAAE,CAAG,EAAQ,CAC/E,OAAQ,KAAK,IAAI,EAAS,EAAM,EAAG,EAAM,EAAI,EAAU,EAAS,KAAK,IAAI,EAAG,EAAU,EAAE,CAAG,EAAQ,CACpG,CAGH,SAAS,EAAS,EAAkB,EAAwB,CAC1D,IAAM,EAAK,EAAK,EAAI,EACd,EAAK,EAAK,EAAI,EAAS,EACvB,EAAK,EAAG,EACR,EAAK,EAAG,EAAI,EAAS,EACrB,EAAO,EAAK,KAAK,IAAI,IAAK,EAAK,GAAM,EAAE,CAC7C,MAAO,KAAK,EAAG,GAAG,EAAG,KAAK,EAAK,GAAG,EAAG,IAAI,EAAK,GAAG,EAAG,IAAI,EAAG,GAAG,IAGhE,SAAgB,EAAe,CAAE,WAAU,SAAQ,WAA4F,CAC7I,IAAM,EAAM,EAAS,EAAkB,EAAQ,EAAQ,CAAG,EAAW,EAAc,EAAU,EAAQ,CAAG,GAClG,EAAO,EAAe,GAAM,EAAS,EAAE,YAAY,GAAO,EAAM,EAAE,cAAc,GAAO,KAAK,CAC5F,EAAY,EAAe,GAAM,EAAE,UAAU,CAC7C,EAAgB,EAAe,GAAM,EAAE,cAAc,CACrD,EAAmB,EAAe,GAAM,EAAE,iBAAiB,CAC3D,EAAgB,EAAe,GAAM,EAAE,cAAc,CACrD,EAAW,GAAa,CAIxB,EAAY,GAAiB,GAEnC,EAAA,EAAA,eAAgB,CACd,GAAI,EAAQ,CACV,EAAe,CAAE,SAAQ,UAAS,CAAC,CACnC,OAEE,GAAU,EAAe,CAAE,WAAU,UAAS,CAAC,EAClD,CAAC,EAAS,EAAW,EAAQ,EAAS,CAAC,CAE1C,IAAM,GAAA,EAAA,EAAA,aAAuB,EAAO,EAAU,EAAK,CAAG,KAAM,CAAC,EAAK,CAAC,CAC7D,GAAA,EAAA,EAAA,aAAyB,IAAI,IAAI,GAAQ,MAAM,IAAK,GAAS,CAAC,EAAK,KAAK,GAAI,EAAK,CAAC,EAAI,EAAE,CAAC,CAAE,CAAC,EAAO,CAAC,CAEpG,GAAA,EAAA,EAAA,aAAuB,CAC3B,GAAI,CAAC,EAAM,MAAO,EAAE,CACpB,IAAM,EAAS,IAAI,IACnB,IAAK,IAAM,KAAQ,EAAK,MAAO,EAAO,IAAI,EAAK,QAAS,EAAO,IAAI,EAAK,OAAO,EAAI,GAAK,EAAE,CAC1F,OAAO,EAAa,OAAQ,GAAW,EAAO,IAAI,EAAO,CAAC,CAAC,IAAK,IAAY,CAC1E,SACA,MAAO,EAAO,IAAI,EAAO,EAAI,EAC9B,EAAE,EACF,CAAC,EAAK,CAAC,CAEV,GAAI,CAAC,GAAQ,CAAC,EAAQ,OAAO,KAE7B,IAAM,EAAY,EAAK,MAAM,OACvB,EAAc,EAAO,KAAM,GAAU,EAAM,SAAW,SAAS,EAAE,OAAS,EAG1E,EAAU,GAAG,EAAU,OAAO,IAAc,EAAI,GAAK,MAAM,EAAc,EAAI,MAAM,EAAY,SAAW,KAEhH,OACE,EAAA,EAAA,MAAC,UAAD,CAAS,UAAU,gEAAnB,EACE,EAAA,EAAA,MAAC,SAAD,CACE,KAAK,SACL,YAAe,EAAiB,CAAC,EAAU,CAC3C,gBAAe,CAAC,EAChB,aAAY,EAAY,oBAAsB,sBAC9C,UAAW,EACT,mDACA,CAAC,GAAa,OACf,UARH,EAUE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,kFACd,EAAA,EAAA,KAAC,EAAD,CAAW,UAAU,gCAAkC,CAAA,CAClD,CAAA,EACP,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,0BAAf,EACE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,4EAAoE,EAAK,OAAS,OAAa,CAAA,EAC9G,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,oEACZ,EAAY,EAAW,EAAK,WAAa,EACtC,CAAA,CACF,GACL,EAAO,OAAS,IACf,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,wDACZ,EAAO,KAAK,CAAE,SAAQ,YACrB,EAAA,EAAA,MAAC,OAAD,CAAmB,UAAU,qEAA7B,EACE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,EAAG,2BAA4B,EAAa,GAAQ,IAAI,CAAI,CAAA,EAC7E,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,EAAG,2BAA4B,EAAa,GAAQ,KAAK,UAAG,EAAa,CAAA,EAC1F,EAAA,EAAA,KAAC,OAAD,CAAA,SAAO,EAAa,GAAQ,MAAa,CAAA,CACpC,EAJI,EAIJ,CACP,CACE,CAAA,EAER,EAAA,EAAA,MAAC,OAAD,CAAM,UAAU,iHAAhB,CAAwH,IACpH,EAAK,QACF,IACP,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,mIACb,GAAY,EAAA,EAAA,KAAC,EAAD,CAAa,UAAU,cAAgB,CAAA,EAAG,EAAA,EAAA,KAAC,EAAD,CAAW,UAAU,cAAgB,CAAA,CACvF,CAAA,CACA,GACR,EAAY,KAAO,EAAK,MAAM,SAAW,GACxC,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,6GAAoG,kEAE7G,CAAA,EAEN,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,kDACb,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,WAAW,MAAO,CAAE,MAAO,EAAO,MAAO,OAAQ,EAAO,OAAQ,UAA/E,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,uCAAuC,MAAO,EAAO,MAAO,OAAQ,EAAO,OAAQ,cAAY,gBAA9G,EACE,EAAA,EAAA,KAAC,OAAD,CAAA,SACG,EAAa,IAAK,IACjB,EAAA,EAAA,KAAC,SAAD,CAEE,GAAI,cAAc,IAClB,QAAQ,UACR,KAAK,MACL,KAAK,IACL,YAAY,IACZ,aAAa,IACb,OAAO,+BAEP,EAAA,EAAA,KAAC,OAAD,CAAM,EAAE,mBAAmB,KAAM,EAAa,GAAQ,KAAQ,CAAA,CACvD,CAVF,EAUE,CACT,CACG,CAAA,CACN,EAAK,MAAM,IAAK,GAAS,CACxB,IAAM,EAAO,EAAS,IAAI,EAAK,KAAK,CAC9B,EAAK,EAAS,IAAI,EAAK,GAAG,CAChC,GAAI,CAAC,GAAQ,CAAC,EAAI,OAAO,KACzB,IAAM,EAAO,EAAa,EAAK,KAAK,QACpC,OACE,EAAA,EAAA,KAAC,OAAD,CAEE,EAAG,EAAS,EAAM,EAAG,CACrB,OAAQ,EAAK,KACb,cAAe,GACf,YAAa,EACb,KAAK,OACL,cAAc,QACd,UAAW,mBAAmB,EAAK,KAAK,OAAO,GAC/C,CARK,GAAG,EAAK,KAAK,IAAI,EAAK,KAQ3B,EAEJ,CACE,GACL,EAAO,MAAM,KAAK,CAAE,OAAM,IAAG,OAAQ,CACpC,IAAM,EAAS,EAAa,EAAK,QAC3B,EAAQ,EAAW,EAAK,SAAS,CACjC,EAAW,EAAK,MAAM,QAAU,EAAc,EAAK,KAAK,SAAW,KACzE,OACE,EAAA,EAAA,MAAC,UAAD,CAEE,UAAW,EACT,qGACA,yGACA,EAAO,OACR,CACD,MAAO,CAAE,KAAM,EAAG,IAAK,EAAG,MAAO,EAAQ,OAAQ,EAAQ,CACzD,MAAO,EAAK,YAAc,EAAK,eARjC,EAUE,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,wEAAgE,EAAK,MAAY,CAAA,EAC9F,EAAK,YAAc,EAAK,MACxB,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,oEAA4D,EAAK,YAAc,EAAK,GAAS,CAAA,CAE7G,IACC,EAAA,EAAA,KAAC,MAAD,CAAK,UAAU,oBACb,EAAA,EAAA,KAAC,EAAD,CAAwB,WAAU,QAAA,GAAQ,UAAU,aAAe,CAAA,CAC/D,CAAA,EAER,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,6DAAf,EACE,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,8CAAf,EACE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,EAAG,oCAAqC,EAAO,IAAI,CAAI,CAAA,EACxE,EAAA,EAAA,KAAC,OAAD,CAAM,UAAW,EAAG,0BAA2B,EAAO,KAAK,UAAG,EAAO,MAAa,CAAA,CAC9E,IACN,EAAA,EAAA,MAAC,MAAD,CAAK,UAAU,6CAAf,CACG,IAAS,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,sDAA8C,EAAa,CAAA,CACpF,EAAK,OACJ,EAAA,EAAA,KAAC,OAAD,CAAM,UAAU,2HACb,EAAK,KACD,CAAA,CAEL,GACF,GACE,EAhCH,EAAK,GAgCF,EAEZ,CACE,GACF,CAAA,CAEA"}
@@ -1,2 +1,2 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{$ as t,F as n,Hn as r,Nt as i,Rt as a,Tn as o,Vn as s,Wn as c,an as l,dt as u,et as d,nn as f,rr as p,u as m}from"./lucide-react-CsPXvXMC.js";import{l as h,t as g}from"./store-DsqUEZOf.js";import{K as _,f as v,h as y,lt as b}from"./display-CWMHll1J.js";import{t as x}from"./badge-CK6ejiOh.js";import{t as S}from"./button-BAwKuRIq.js";import{s as C}from"./index-CiBdEE9x.js";import{r as w,t as T}from"./card-DDxxo-Fo.js";import{C as E,f as D,n as O,o as k,r as A,t as j,u as M}from"./MessageBubble-bI9fFi55.js";var N=e(p(),1),P=c(),F={question:l,reply:t,message:d,operator:m,pair:u,task:f,state:n},I={question:`bg-blue-500/10 text-blue-400 border-blue-500/20`,reply:`bg-emerald-500/10 text-emerald-400 border-emerald-500/20`,message:`bg-zinc-500/10 text-zinc-400 border-zinc-500/20`,operator:`bg-purple-500/10 text-purple-400 border-purple-500/20`,pair:`bg-yellow-500/10 text-yellow-400 border-yellow-500/20`,task:`bg-orange-500/10 text-orange-400 border-orange-500/20`,state:`bg-cyan-500/10 text-cyan-400 border-cyan-500/20`},L=[`question`,`reply`,`message`,`operator`,`pair`,`task`,`state`],R=[`chat`,`session`,`system`,`task`];function z(e){let t=e?.surface;if(!t||typeof t!=`object`)return null;let n=t,r=[];return typeof n.component==`string`&&r.push(n.component),typeof n.view==`string`&&n.view!==n.component&&r.push(n.view),typeof n.session==`string`&&r.push(`tab ${n.session.slice(0,6)}`),typeof n.client==`string`&&r.push(`client ${n.client.slice(0,6)}`),r.length?r.join(` · `):null}function B({entry:e,agentsById:t}){if(e.type===`notice`)return(0,P.jsx)(`div`,{className:`px-1`,children:(0,P.jsx)(M,{msg:e.msg})});if(e.type===`agent-action`)return(0,P.jsx)(`div`,{className:`px-1`,children:(0,P.jsx)(A,{entry:e})});if(e.type===`activity`)return(0,P.jsx)(`div`,{className:`px-1 opacity-60`,children:(0,P.jsx)(O,{steps:e.steps,showReasoning:!1})});if(e.type===`status`)return(0,P.jsx)(`div`,{className:`px-1`,children:(0,P.jsx)(D,{event:e.event})});if(e.type===`date`)return(0,P.jsx)(`div`,{className:`px-1`,children:(0,P.jsx)(k,{date:e.date})});if(e.type===`created`||e.type===`import-boundary`||e.type===`imported-message`||e.type!==`message`)return null;let{msg:n}=e,r=v(n.from,t),i=v(n.to,t);return(0,P.jsxs)(`div`,{children:[(0,P.jsxs)(`div`,{className:`flex items-center gap-1.5 px-3 mb-0.5`,children:[(0,P.jsx)(`span`,{className:`text-xs font-mono text-muted-foreground truncate max-w-[140px]`,title:n.from,children:r}),(0,P.jsx)(`span`,{className:`text-xs text-muted-foreground shrink-0`,children:`→`}),(0,P.jsx)(`span`,{className:`text-xs font-mono text-muted-foreground truncate max-w-[140px]`,title:n.to,children:i}),(0,P.jsx)(x,{variant:`outline`,className:`text-[10px] px-1 py-0 shrink-0 ml-1`,children:n.kind})]}),(0,P.jsx)(j,{msg:n,peer:b})]})}function V(){let e=g(e=>e.messages),t=g(e=>e.agentsById),[n,r]=(0,N.useState)(``),[i,a]=(0,N.useState)(``),o=(0,N.useMemo)(()=>{let t=e;if(n){let e=n.toLowerCase();t=t.filter(t=>t.from.toLowerCase().includes(e)||t.to.toLowerCase().includes(e))}return i&&(t=t.filter(e=>e.kind===i)),t},[e,n,i]),s=(0,N.useMemo)(()=>E(o,[]),[o]);return(0,P.jsxs)(P.Fragment,{children:[(0,P.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,P.jsx)(`input`,{type:`text`,className:`rounded-md border border-input bg-background px-3 py-1.5 text-sm w-44`,placeholder:`Filter by agent…`,value:n,onChange:e=>r(e.target.value)}),(0,P.jsxs)(`select`,{className:`rounded-md border border-input bg-background px-3 py-1.5 text-sm`,value:i,onChange:e=>a(e.target.value),children:[(0,P.jsx)(`option`,{value:``,children:`All kinds`}),R.map(e=>(0,P.jsx)(`option`,{value:e,children:e},e))]}),(0,P.jsx)(x,{variant:`secondary`,className:`ml-auto`,children:o.length})]}),(0,P.jsx)(C,{className:`h-[calc(100dvh-13rem)]`,children:(0,P.jsxs)(`div`,{className:`space-y-1 pr-2`,children:[s.length===0&&(0,P.jsx)(`div`,{className:`text-center text-muted-foreground py-16 text-sm`,children:`No messages yet`}),s.map((e,n)=>(0,P.jsx)(B,{entry:e,agentsById:t},n))]})})]})}function H(){let e=h(),t=g(e=>e.activityFilter),n=g(e=>e.activityEvents),r=g(e=>e.operatorActivity),i=g(e=>e.set),c=g(e=>e.openActivityItem),l=g(e=>e.exportActivity),u=(0,N.useMemo)(()=>{let e=[...n,...r],t=new Set,i=[];for(let n of e){let e=n.clientId||String(n.id);t.has(e)||(t.add(e),i.push(n))}return i.map(e=>({...e,ts:e.ts??new Date(e.createdAt).getTime()})).sort((e,t)=>(t.ts??0)-(e.ts??0))},[n,r]),d=(0,N.useMemo)(()=>t?u.filter(e=>e.kind===t):u,[u,t]);return(0,P.jsxs)(P.Fragment,{children:[(0,P.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,P.jsxs)(`select`,{className:`rounded-md border border-input bg-background px-3 py-1.5 text-sm`,value:t,onChange:e=>i({activityFilter:e.target.value}),children:[(0,P.jsx)(`option`,{value:``,children:`All types`}),L.map(e=>(0,P.jsx)(`option`,{value:e,children:e},e))]}),(0,P.jsxs)(S,{size:`sm`,variant:`outline`,onClick:()=>l(`markdown`),children:[(0,P.jsx)(a,{className:`w-4 h-4 mr-1`}),` Markdown`]}),(0,P.jsxs)(S,{size:`sm`,variant:`outline`,onClick:()=>l(`json`),children:[(0,P.jsx)(o,{className:`w-4 h-4 mr-1`}),` JSON`]}),(0,P.jsx)(x,{variant:`secondary`,className:`ml-auto`,children:d.length})]}),(0,P.jsx)(C,{className:`h-[calc(100dvh-13rem)]`,children:(0,P.jsxs)(`div`,{className:`space-y-2 pr-2`,children:[d.length===0&&(0,P.jsx)(`div`,{className:`text-center text-muted-foreground py-16 text-sm`,children:`No activity yet`}),d.map(t=>{let n=F[t.kind]||s,r=I[t.kind]||I.message,i=z(t.metadata);return(0,P.jsx)(T,{className:`cursor-pointer hover:bg-accent/40 transition-colors`,onClick:()=>c(t),children:(0,P.jsxs)(w,{className:`p-3 flex gap-3`,children:[(0,P.jsx)(`span`,{className:`inline-flex items-center justify-center w-7 h-7 rounded-md border shrink-0 mt-0.5 ${r}`,children:(0,P.jsx)(n,{className:`w-3.5 h-3.5`})}),(0,P.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,P.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,P.jsx)(`span`,{className:`font-medium text-sm truncate`,children:t.title}),(0,P.jsx)(x,{variant:`outline`,className:`text-xs px-1.5 py-0 border ${r}`,children:t.kind}),(0,P.jsx)(`span`,{className:`text-xs text-muted-foreground ml-auto shrink-0`,title:y(t.ts??t.createdAt),children:_(e,t.ts??t.createdAt)})]}),t.body&&(0,P.jsx)(`p`,{className:`text-xs text-muted-foreground mt-0.5 line-clamp-2`,children:t.body}),t.meta&&(0,P.jsx)(`p`,{className:`text-xs text-muted-foreground/60 mt-0.5 font-mono truncate`,children:t.meta}),i&&(0,P.jsxs)(`p`,{className:`text-xs text-muted-foreground/60 mt-0.5 truncate`,title:i,children:[(0,P.jsx)(`span`,{className:`opacity-70`,children:`via`}),` `,i]})]})]})},t.clientId||t.id)})]})})]})}function U(){let[e,t]=(0,N.useState)(`firehose`);return(0,P.jsxs)(`div`,{className:`space-y-4`,children:[(0,P.jsxs)(`div`,{className:`flex items-center justify-between flex-wrap gap-2`,children:[(0,P.jsxs)(`div`,{className:`flex items-center gap-2`,children:[e===`firehose`?(0,P.jsx)(i,{className:`w-5 h-5 text-muted-foreground`}):(0,P.jsx)(s,{className:`w-5 h-5 text-muted-foreground`}),(0,P.jsx)(`h2`,{className:`text-lg font-semibold`,children:e===`firehose`?`Firehose`:`Events`})]}),(0,P.jsxs)(`div`,{className:`flex items-center gap-1 rounded-md border border-input overflow-hidden`,children:[(0,P.jsx)(`button`,{className:r(`px-3 py-1.5 text-sm transition-colors`,e===`firehose`?`bg-primary text-primary-foreground`:`hover:bg-accent`),onClick:()=>t(`firehose`),children:`Firehose`}),(0,P.jsx)(`button`,{className:r(`px-3 py-1.5 text-sm transition-colors`,e===`events`?`bg-primary text-primary-foreground`:`hover:bg-accent`),onClick:()=>t(`events`),children:`Events`})]})]}),e===`firehose`?(0,P.jsx)(V,{}):(0,P.jsx)(H,{})]})}export{U as ActivityView};
2
- //# sourceMappingURL=activity-VTlBVIox.js.map
1
+ import{r as e}from"./chunk-CilyBKbf.js";import{$ as t,F as n,Hn as r,Nt as i,Rt as a,Tn as o,Vn as s,Wn as c,an as l,dt as u,et as d,nn as f,rr as p,u as m}from"./lucide-react-CsPXvXMC.js";import{l as h,t as g}from"./store-DsqUEZOf.js";import{K as _,f as v,h as y,lt as b}from"./display-CWMHll1J.js";import{t as x}from"./badge-CK6ejiOh.js";import{t as S}from"./button-BAwKuRIq.js";import{s as C}from"./index-Dm1zlklN.js";import{r as w,t as T}from"./card-DDxxo-Fo.js";import{C as E,f as D,n as O,o as k,r as A,t as j,u as M}from"./MessageBubble-Cl3gC5sO.js";var N=e(p(),1),P=c(),F={question:l,reply:t,message:d,operator:m,pair:u,task:f,state:n},I={question:`bg-blue-500/10 text-blue-400 border-blue-500/20`,reply:`bg-emerald-500/10 text-emerald-400 border-emerald-500/20`,message:`bg-zinc-500/10 text-zinc-400 border-zinc-500/20`,operator:`bg-purple-500/10 text-purple-400 border-purple-500/20`,pair:`bg-yellow-500/10 text-yellow-400 border-yellow-500/20`,task:`bg-orange-500/10 text-orange-400 border-orange-500/20`,state:`bg-cyan-500/10 text-cyan-400 border-cyan-500/20`},L=[`question`,`reply`,`message`,`operator`,`pair`,`task`,`state`],R=[`chat`,`session`,`system`,`task`];function z(e){let t=e?.surface;if(!t||typeof t!=`object`)return null;let n=t,r=[];return typeof n.component==`string`&&r.push(n.component),typeof n.view==`string`&&n.view!==n.component&&r.push(n.view),typeof n.session==`string`&&r.push(`tab ${n.session.slice(0,6)}`),typeof n.client==`string`&&r.push(`client ${n.client.slice(0,6)}`),r.length?r.join(` · `):null}function B({entry:e,agentsById:t}){if(e.type===`notice`)return(0,P.jsx)(`div`,{className:`px-1`,children:(0,P.jsx)(M,{msg:e.msg})});if(e.type===`agent-action`)return(0,P.jsx)(`div`,{className:`px-1`,children:(0,P.jsx)(A,{entry:e})});if(e.type===`activity`)return(0,P.jsx)(`div`,{className:`px-1 opacity-60`,children:(0,P.jsx)(O,{steps:e.steps,showReasoning:!1})});if(e.type===`status`)return(0,P.jsx)(`div`,{className:`px-1`,children:(0,P.jsx)(D,{event:e.event})});if(e.type===`date`)return(0,P.jsx)(`div`,{className:`px-1`,children:(0,P.jsx)(k,{date:e.date})});if(e.type===`created`||e.type===`import-boundary`||e.type===`imported-message`||e.type!==`message`)return null;let{msg:n}=e,r=v(n.from,t),i=v(n.to,t);return(0,P.jsxs)(`div`,{children:[(0,P.jsxs)(`div`,{className:`flex items-center gap-1.5 px-3 mb-0.5`,children:[(0,P.jsx)(`span`,{className:`text-xs font-mono text-muted-foreground truncate max-w-[140px]`,title:n.from,children:r}),(0,P.jsx)(`span`,{className:`text-xs text-muted-foreground shrink-0`,children:`→`}),(0,P.jsx)(`span`,{className:`text-xs font-mono text-muted-foreground truncate max-w-[140px]`,title:n.to,children:i}),(0,P.jsx)(x,{variant:`outline`,className:`text-[10px] px-1 py-0 shrink-0 ml-1`,children:n.kind})]}),(0,P.jsx)(j,{msg:n,peer:b})]})}function V(){let e=g(e=>e.messages),t=g(e=>e.agentsById),[n,r]=(0,N.useState)(``),[i,a]=(0,N.useState)(``),o=(0,N.useMemo)(()=>{let t=e;if(n){let e=n.toLowerCase();t=t.filter(t=>t.from.toLowerCase().includes(e)||t.to.toLowerCase().includes(e))}return i&&(t=t.filter(e=>e.kind===i)),t},[e,n,i]),s=(0,N.useMemo)(()=>E(o,[]),[o]);return(0,P.jsxs)(P.Fragment,{children:[(0,P.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,P.jsx)(`input`,{type:`text`,className:`rounded-md border border-input bg-background px-3 py-1.5 text-sm w-44`,placeholder:`Filter by agent…`,value:n,onChange:e=>r(e.target.value)}),(0,P.jsxs)(`select`,{className:`rounded-md border border-input bg-background px-3 py-1.5 text-sm`,value:i,onChange:e=>a(e.target.value),children:[(0,P.jsx)(`option`,{value:``,children:`All kinds`}),R.map(e=>(0,P.jsx)(`option`,{value:e,children:e},e))]}),(0,P.jsx)(x,{variant:`secondary`,className:`ml-auto`,children:o.length})]}),(0,P.jsx)(C,{className:`h-[calc(100dvh-13rem)]`,children:(0,P.jsxs)(`div`,{className:`space-y-1 pr-2`,children:[s.length===0&&(0,P.jsx)(`div`,{className:`text-center text-muted-foreground py-16 text-sm`,children:`No messages yet`}),s.map((e,n)=>(0,P.jsx)(B,{entry:e,agentsById:t},n))]})})]})}function H(){let e=h(),t=g(e=>e.activityFilter),n=g(e=>e.activityEvents),r=g(e=>e.operatorActivity),i=g(e=>e.set),c=g(e=>e.openActivityItem),l=g(e=>e.exportActivity),u=(0,N.useMemo)(()=>{let e=[...n,...r],t=new Set,i=[];for(let n of e){let e=n.clientId||String(n.id);t.has(e)||(t.add(e),i.push(n))}return i.map(e=>({...e,ts:e.ts??new Date(e.createdAt).getTime()})).sort((e,t)=>(t.ts??0)-(e.ts??0))},[n,r]),d=(0,N.useMemo)(()=>t?u.filter(e=>e.kind===t):u,[u,t]);return(0,P.jsxs)(P.Fragment,{children:[(0,P.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,P.jsxs)(`select`,{className:`rounded-md border border-input bg-background px-3 py-1.5 text-sm`,value:t,onChange:e=>i({activityFilter:e.target.value}),children:[(0,P.jsx)(`option`,{value:``,children:`All types`}),L.map(e=>(0,P.jsx)(`option`,{value:e,children:e},e))]}),(0,P.jsxs)(S,{size:`sm`,variant:`outline`,onClick:()=>l(`markdown`),children:[(0,P.jsx)(a,{className:`w-4 h-4 mr-1`}),` Markdown`]}),(0,P.jsxs)(S,{size:`sm`,variant:`outline`,onClick:()=>l(`json`),children:[(0,P.jsx)(o,{className:`w-4 h-4 mr-1`}),` JSON`]}),(0,P.jsx)(x,{variant:`secondary`,className:`ml-auto`,children:d.length})]}),(0,P.jsx)(C,{className:`h-[calc(100dvh-13rem)]`,children:(0,P.jsxs)(`div`,{className:`space-y-2 pr-2`,children:[d.length===0&&(0,P.jsx)(`div`,{className:`text-center text-muted-foreground py-16 text-sm`,children:`No activity yet`}),d.map(t=>{let n=F[t.kind]||s,r=I[t.kind]||I.message,i=z(t.metadata);return(0,P.jsx)(T,{className:`cursor-pointer hover:bg-accent/40 transition-colors`,onClick:()=>c(t),children:(0,P.jsxs)(w,{className:`p-3 flex gap-3`,children:[(0,P.jsx)(`span`,{className:`inline-flex items-center justify-center w-7 h-7 rounded-md border shrink-0 mt-0.5 ${r}`,children:(0,P.jsx)(n,{className:`w-3.5 h-3.5`})}),(0,P.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,P.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,P.jsx)(`span`,{className:`font-medium text-sm truncate`,children:t.title}),(0,P.jsx)(x,{variant:`outline`,className:`text-xs px-1.5 py-0 border ${r}`,children:t.kind}),(0,P.jsx)(`span`,{className:`text-xs text-muted-foreground ml-auto shrink-0`,title:y(t.ts??t.createdAt),children:_(e,t.ts??t.createdAt)})]}),t.body&&(0,P.jsx)(`p`,{className:`text-xs text-muted-foreground mt-0.5 line-clamp-2`,children:t.body}),t.meta&&(0,P.jsx)(`p`,{className:`text-xs text-muted-foreground/60 mt-0.5 font-mono truncate`,children:t.meta}),i&&(0,P.jsxs)(`p`,{className:`text-xs text-muted-foreground/60 mt-0.5 truncate`,title:i,children:[(0,P.jsx)(`span`,{className:`opacity-70`,children:`via`}),` `,i]})]})]})},t.clientId||t.id)})]})})]})}function U(){let[e,t]=(0,N.useState)(`firehose`);return(0,P.jsxs)(`div`,{className:`space-y-4`,children:[(0,P.jsxs)(`div`,{className:`flex items-center justify-between flex-wrap gap-2`,children:[(0,P.jsxs)(`div`,{className:`flex items-center gap-2`,children:[e===`firehose`?(0,P.jsx)(i,{className:`w-5 h-5 text-muted-foreground`}):(0,P.jsx)(s,{className:`w-5 h-5 text-muted-foreground`}),(0,P.jsx)(`h2`,{className:`text-lg font-semibold`,children:e===`firehose`?`Firehose`:`Events`})]}),(0,P.jsxs)(`div`,{className:`flex items-center gap-1 rounded-md border border-input overflow-hidden`,children:[(0,P.jsx)(`button`,{className:r(`px-3 py-1.5 text-sm transition-colors`,e===`firehose`?`bg-primary text-primary-foreground`:`hover:bg-accent`),onClick:()=>t(`firehose`),children:`Firehose`}),(0,P.jsx)(`button`,{className:r(`px-3 py-1.5 text-sm transition-colors`,e===`events`?`bg-primary text-primary-foreground`:`hover:bg-accent`),onClick:()=>t(`events`),children:`Events`})]})]}),e===`firehose`?(0,P.jsx)(V,{}):(0,P.jsx)(H,{})]})}export{U as ActivityView};
2
+ //# sourceMappingURL=activity-navjipA_.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"activity-VTlBVIox.js","names":[],"sources":["../../dashboard/src/components/views/activity.tsx"],"sourcesContent":["import { useRelayStore, useNow } from '@/store'\nimport { Card, CardContent } from '@/components/ui/card'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { ScrollArea } from '@/components/ui/scroll-area'\nimport {\n Activity, MessageCircle, MessageSquareReply, HelpCircle, User,\n Link, ClipboardList, Radio, FileDown, Braces, Flame,\n} from 'lucide-react'\nimport { timeAgo, fmtTime, displayTarget } from '@/lib/display'\nimport type { ActivityEvent, Agent, Message } from '@/types'\nimport { useMemo, useState } from 'react'\nimport { buildTimeline, type TimelineEntry } from '@/components/chat/sessionTrace'\nimport { AgentActionEntry, NoticePill, ActivityTrace, StatusMarker, DateSeparator } from '@/components/chat/TraceView'\nimport { MessageBubble } from '@/components/chat/MessageBubble'\nimport { HUMAN_AGENT_ID } from '@/lib/constants'\nimport { cn } from '@/lib/utils'\n\nconst KIND_ICONS: Record<string, React.ElementType> = {\n question: HelpCircle,\n reply: MessageSquareReply,\n message: MessageCircle,\n operator: User,\n pair: Link,\n task: ClipboardList,\n state: Radio,\n}\n\nconst KIND_COLORS: Record<string, string> = {\n question: 'bg-blue-500/10 text-blue-400 border-blue-500/20',\n reply: 'bg-emerald-500/10 text-emerald-400 border-emerald-500/20',\n message: 'bg-zinc-500/10 text-zinc-400 border-zinc-500/20',\n operator: 'bg-purple-500/10 text-purple-400 border-purple-500/20',\n pair: 'bg-yellow-500/10 text-yellow-400 border-yellow-500/20',\n task: 'bg-orange-500/10 text-orange-400 border-orange-500/20',\n state: 'bg-cyan-500/10 text-cyan-400 border-cyan-500/20',\n}\n\nconst EVENT_KIND_LABELS = ['question', 'reply', 'message', 'operator', 'pair', 'task', 'state'] as const\nconst MSG_KIND_LABELS = ['chat', 'session', 'system', 'task'] as const\n\n// Compact attribution line for dashboard-initiated lifecycle commands (#172): identifies the\n// surface that issued a restart/shutdown/reconnect — component, SPA view, tab session, browser.\nfunction formatSurface(metadata: Record<string, unknown> | undefined): string | null {\n const surface = metadata?.surface\n if (!surface || typeof surface !== 'object') return null\n const s = surface as Record<string, unknown>\n const parts: string[] = []\n if (typeof s.component === 'string') parts.push(s.component)\n if (typeof s.view === 'string' && s.view !== s.component) parts.push(s.view)\n if (typeof s.session === 'string') parts.push(`tab ${s.session.slice(0, 6)}`)\n if (typeof s.client === 'string') parts.push(`client ${s.client.slice(0, 6)}`)\n return parts.length ? parts.join(' · ') : null\n}\n\n// Render one firehose timeline entry using Tier-1 exported components.\n// No entry-render code is duplicated here — body formatting, reactions, code blocks,\n// notice pills, status markers, and date separators all live in the shared exports.\nfunction FirehoseRow({ entry, agentsById }: { entry: TimelineEntry; agentsById: Record<string, Agent> }) {\n if (entry.type === 'notice') return <div className=\"px-1\"><NoticePill msg={entry.msg} /></div>\n if (entry.type === 'agent-action') return <div className=\"px-1\"><AgentActionEntry entry={entry} /></div>\n if (entry.type === 'activity') return (\n <div className=\"px-1 opacity-60\">\n <ActivityTrace steps={entry.steps} showReasoning={false} />\n </div>\n )\n if (entry.type === 'status') return <div className=\"px-1\"><StatusMarker event={entry.event} /></div>\n if (entry.type === 'date') return <div className=\"px-1\"><DateSeparator date={entry.date} /></div>\n if (entry.type === 'created' || entry.type === 'import-boundary' || entry.type === 'imported-message') return null\n if (entry.type !== 'message') return null\n\n const { msg } = entry\n const fromLabel = displayTarget(msg.from, agentsById)\n const toLabel = displayTarget(msg.to, agentsById)\n return (\n <div>\n {/* Attribution header: both sides of the routing, not shown by MessageBubble alone */}\n <div className=\"flex items-center gap-1.5 px-3 mb-0.5\">\n <span className=\"text-xs font-mono text-muted-foreground truncate max-w-[140px]\" title={msg.from}>{fromLabel}</span>\n <span className=\"text-xs text-muted-foreground shrink-0\">→</span>\n <span className=\"text-xs font-mono text-muted-foreground truncate max-w-[140px]\" title={msg.to}>{toLabel}</span>\n <Badge variant=\"outline\" className=\"text-[10px] px-1 py-0 shrink-0 ml-1\">{msg.kind}</Badge>\n </div>\n {/* peer=HUMAN_AGENT_ID: agent messages render inbound (left), user messages outbound (right) */}\n <MessageBubble msg={msg} peer={HUMAN_AGENT_ID} />\n </div>\n )\n}\n\nfunction FirehoseTab() {\n const messages = useRelayStore((s) => s.messages) as Message[]\n const agentsById = useRelayStore((s) => s.agentsById)\n const [agentFilter, setAgentFilter] = useState('')\n const [kindFilter, setKindFilter] = useState('')\n\n const filteredMessages = useMemo(() => {\n let msgs = messages\n if (agentFilter) {\n const q = agentFilter.toLowerCase()\n msgs = msgs.filter((m) => m.from.toLowerCase().includes(q) || m.to.toLowerCase().includes(q))\n }\n if (kindFilter) msgs = msgs.filter((m) => m.kind === kindFilter)\n return msgs\n }, [messages, agentFilter, kindFilter])\n\n const timeline = useMemo(() => buildTimeline(filteredMessages, []), [filteredMessages])\n\n return (\n <>\n <div className=\"flex items-center gap-2 flex-wrap\">\n <input\n type=\"text\"\n className=\"rounded-md border border-input bg-background px-3 py-1.5 text-sm w-44\"\n placeholder=\"Filter by agent…\"\n value={agentFilter}\n onChange={(e) => setAgentFilter(e.target.value)}\n />\n <select\n className=\"rounded-md border border-input bg-background px-3 py-1.5 text-sm\"\n value={kindFilter}\n onChange={(e) => setKindFilter(e.target.value)}\n >\n <option value=\"\">All kinds</option>\n {MSG_KIND_LABELS.map((k) => <option key={k} value={k}>{k}</option>)}\n </select>\n <Badge variant=\"secondary\" className=\"ml-auto\">{filteredMessages.length}</Badge>\n </div>\n\n <ScrollArea className=\"h-[calc(100dvh-13rem)]\">\n <div className=\"space-y-1 pr-2\">\n {timeline.length === 0 && (\n <div className=\"text-center text-muted-foreground py-16 text-sm\">No messages yet</div>\n )}\n {timeline.map((entry, i) => (\n <FirehoseRow key={i} entry={entry} agentsById={agentsById} />\n ))}\n </div>\n </ScrollArea>\n </>\n )\n}\n\nfunction EventsTab() {\n const now = useNow()\n const activityFilter = useRelayStore((s) => s.activityFilter)\n const activityEvents = useRelayStore((s) => s.activityEvents)\n const operatorActivity = useRelayStore((s) => s.operatorActivity)\n const set = useRelayStore((s) => s.set)\n const openActivityItem = useRelayStore((s) => s.openActivityItem)\n const exportActivity = useRelayStore((s) => s.exportActivity)\n\n const allItems = useMemo(() => {\n const merged = [...activityEvents, ...operatorActivity]\n const seen = new Set<string>()\n const deduped: ActivityEvent[] = []\n for (const item of merged) {\n const key = item.clientId || String(item.id)\n if (!seen.has(key)) { seen.add(key); deduped.push(item) }\n }\n return deduped\n .map((e) => ({ ...e, ts: e.ts ?? new Date(e.createdAt as string).getTime() }))\n .sort((a, b) => (b.ts ?? 0) - (a.ts ?? 0))\n }, [activityEvents, operatorActivity])\n\n const filtered = useMemo(() => {\n if (!activityFilter) return allItems\n return allItems.filter((e) => e.kind === activityFilter)\n }, [allItems, activityFilter])\n\n return (\n <>\n <div className=\"flex items-center gap-2 flex-wrap\">\n <select\n className=\"rounded-md border border-input bg-background px-3 py-1.5 text-sm\"\n value={activityFilter}\n onChange={(e) => set({ activityFilter: e.target.value })}\n >\n <option value=\"\">All types</option>\n {EVENT_KIND_LABELS.map((k) => <option key={k} value={k}>{k}</option>)}\n </select>\n <Button size=\"sm\" variant=\"outline\" onClick={() => exportActivity('markdown')}>\n <FileDown className=\"w-4 h-4 mr-1\" /> Markdown\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={() => exportActivity('json')}>\n <Braces className=\"w-4 h-4 mr-1\" /> JSON\n </Button>\n <Badge variant=\"secondary\" className=\"ml-auto\">{filtered.length}</Badge>\n </div>\n\n <ScrollArea className=\"h-[calc(100dvh-13rem)]\">\n <div className=\"space-y-2 pr-2\">\n {filtered.length === 0 && (\n <div className=\"text-center text-muted-foreground py-16 text-sm\">No activity yet</div>\n )}\n {filtered.map((item) => {\n const Icon = KIND_ICONS[item.kind] || Activity\n const colorClass = KIND_COLORS[item.kind] || KIND_COLORS.message\n const surface = formatSurface(item.metadata)\n return (\n <Card\n key={item.clientId || item.id}\n className=\"cursor-pointer hover:bg-accent/40 transition-colors\"\n onClick={() => openActivityItem(item)}\n >\n <CardContent className=\"p-3 flex gap-3\">\n <span className={`inline-flex items-center justify-center w-7 h-7 rounded-md border shrink-0 mt-0.5 ${colorClass}`}>\n <Icon className=\"w-3.5 h-3.5\" />\n </span>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"font-medium text-sm truncate\">{item.title}</span>\n <Badge variant=\"outline\" className={`text-xs px-1.5 py-0 border ${colorClass}`}>{item.kind}</Badge>\n <span className=\"text-xs text-muted-foreground ml-auto shrink-0\" title={fmtTime(item.ts ?? item.createdAt)}>\n {timeAgo(now, item.ts ?? item.createdAt)}\n </span>\n </div>\n {item.body && (\n <p className=\"text-xs text-muted-foreground mt-0.5 line-clamp-2\">{item.body}</p>\n )}\n {item.meta && (\n <p className=\"text-xs text-muted-foreground/60 mt-0.5 font-mono truncate\">{item.meta}</p>\n )}\n {surface && (\n <p className=\"text-xs text-muted-foreground/60 mt-0.5 truncate\" title={surface}>\n <span className=\"opacity-70\">via</span> {surface}\n </p>\n )}\n </div>\n </CardContent>\n </Card>\n )\n })}\n </div>\n </ScrollArea>\n </>\n )\n}\n\ntype ActivityTab = 'firehose' | 'events'\n\nexport function ActivityView() {\n const [tab, setTab] = useState<ActivityTab>('firehose')\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between flex-wrap gap-2\">\n <div className=\"flex items-center gap-2\">\n {tab === 'firehose'\n ? <Flame className=\"w-5 h-5 text-muted-foreground\" />\n : <Activity className=\"w-5 h-5 text-muted-foreground\" />}\n <h2 className=\"text-lg font-semibold\">{tab === 'firehose' ? 'Firehose' : 'Events'}</h2>\n </div>\n <div className=\"flex items-center gap-1 rounded-md border border-input overflow-hidden\">\n <button\n className={cn('px-3 py-1.5 text-sm transition-colors', tab === 'firehose' ? 'bg-primary text-primary-foreground' : 'hover:bg-accent')}\n onClick={() => setTab('firehose')}\n >\n Firehose\n </button>\n <button\n className={cn('px-3 py-1.5 text-sm transition-colors', tab === 'events' ? 'bg-primary text-primary-foreground' : 'hover:bg-accent')}\n onClick={() => setTab('events')}\n >\n Events\n </button>\n </div>\n </div>\n\n {tab === 'firehose' ? <FirehoseTab /> : <EventsTab />}\n </div>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"activity-navjipA_.js","names":[],"sources":["../../dashboard/src/components/views/activity.tsx"],"sourcesContent":["import { useRelayStore, useNow } from '@/store'\nimport { Card, CardContent } from '@/components/ui/card'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { ScrollArea } from '@/components/ui/scroll-area'\nimport {\n Activity, MessageCircle, MessageSquareReply, HelpCircle, User,\n Link, ClipboardList, Radio, FileDown, Braces, Flame,\n} from 'lucide-react'\nimport { timeAgo, fmtTime, displayTarget } from '@/lib/display'\nimport type { ActivityEvent, Agent, Message } from '@/types'\nimport { useMemo, useState } from 'react'\nimport { buildTimeline, type TimelineEntry } from '@/components/chat/sessionTrace'\nimport { AgentActionEntry, NoticePill, ActivityTrace, StatusMarker, DateSeparator } from '@/components/chat/TraceView'\nimport { MessageBubble } from '@/components/chat/MessageBubble'\nimport { HUMAN_AGENT_ID } from '@/lib/constants'\nimport { cn } from '@/lib/utils'\n\nconst KIND_ICONS: Record<string, React.ElementType> = {\n question: HelpCircle,\n reply: MessageSquareReply,\n message: MessageCircle,\n operator: User,\n pair: Link,\n task: ClipboardList,\n state: Radio,\n}\n\nconst KIND_COLORS: Record<string, string> = {\n question: 'bg-blue-500/10 text-blue-400 border-blue-500/20',\n reply: 'bg-emerald-500/10 text-emerald-400 border-emerald-500/20',\n message: 'bg-zinc-500/10 text-zinc-400 border-zinc-500/20',\n operator: 'bg-purple-500/10 text-purple-400 border-purple-500/20',\n pair: 'bg-yellow-500/10 text-yellow-400 border-yellow-500/20',\n task: 'bg-orange-500/10 text-orange-400 border-orange-500/20',\n state: 'bg-cyan-500/10 text-cyan-400 border-cyan-500/20',\n}\n\nconst EVENT_KIND_LABELS = ['question', 'reply', 'message', 'operator', 'pair', 'task', 'state'] as const\nconst MSG_KIND_LABELS = ['chat', 'session', 'system', 'task'] as const\n\n// Compact attribution line for dashboard-initiated lifecycle commands (#172): identifies the\n// surface that issued a restart/shutdown/reconnect — component, SPA view, tab session, browser.\nfunction formatSurface(metadata: Record<string, unknown> | undefined): string | null {\n const surface = metadata?.surface\n if (!surface || typeof surface !== 'object') return null\n const s = surface as Record<string, unknown>\n const parts: string[] = []\n if (typeof s.component === 'string') parts.push(s.component)\n if (typeof s.view === 'string' && s.view !== s.component) parts.push(s.view)\n if (typeof s.session === 'string') parts.push(`tab ${s.session.slice(0, 6)}`)\n if (typeof s.client === 'string') parts.push(`client ${s.client.slice(0, 6)}`)\n return parts.length ? parts.join(' · ') : null\n}\n\n// Render one firehose timeline entry using Tier-1 exported components.\n// No entry-render code is duplicated here — body formatting, reactions, code blocks,\n// notice pills, status markers, and date separators all live in the shared exports.\nfunction FirehoseRow({ entry, agentsById }: { entry: TimelineEntry; agentsById: Record<string, Agent> }) {\n if (entry.type === 'notice') return <div className=\"px-1\"><NoticePill msg={entry.msg} /></div>\n if (entry.type === 'agent-action') return <div className=\"px-1\"><AgentActionEntry entry={entry} /></div>\n if (entry.type === 'activity') return (\n <div className=\"px-1 opacity-60\">\n <ActivityTrace steps={entry.steps} showReasoning={false} />\n </div>\n )\n if (entry.type === 'status') return <div className=\"px-1\"><StatusMarker event={entry.event} /></div>\n if (entry.type === 'date') return <div className=\"px-1\"><DateSeparator date={entry.date} /></div>\n if (entry.type === 'created' || entry.type === 'import-boundary' || entry.type === 'imported-message') return null\n if (entry.type !== 'message') return null\n\n const { msg } = entry\n const fromLabel = displayTarget(msg.from, agentsById)\n const toLabel = displayTarget(msg.to, agentsById)\n return (\n <div>\n {/* Attribution header: both sides of the routing, not shown by MessageBubble alone */}\n <div className=\"flex items-center gap-1.5 px-3 mb-0.5\">\n <span className=\"text-xs font-mono text-muted-foreground truncate max-w-[140px]\" title={msg.from}>{fromLabel}</span>\n <span className=\"text-xs text-muted-foreground shrink-0\">→</span>\n <span className=\"text-xs font-mono text-muted-foreground truncate max-w-[140px]\" title={msg.to}>{toLabel}</span>\n <Badge variant=\"outline\" className=\"text-[10px] px-1 py-0 shrink-0 ml-1\">{msg.kind}</Badge>\n </div>\n {/* peer=HUMAN_AGENT_ID: agent messages render inbound (left), user messages outbound (right) */}\n <MessageBubble msg={msg} peer={HUMAN_AGENT_ID} />\n </div>\n )\n}\n\nfunction FirehoseTab() {\n const messages = useRelayStore((s) => s.messages) as Message[]\n const agentsById = useRelayStore((s) => s.agentsById)\n const [agentFilter, setAgentFilter] = useState('')\n const [kindFilter, setKindFilter] = useState('')\n\n const filteredMessages = useMemo(() => {\n let msgs = messages\n if (agentFilter) {\n const q = agentFilter.toLowerCase()\n msgs = msgs.filter((m) => m.from.toLowerCase().includes(q) || m.to.toLowerCase().includes(q))\n }\n if (kindFilter) msgs = msgs.filter((m) => m.kind === kindFilter)\n return msgs\n }, [messages, agentFilter, kindFilter])\n\n const timeline = useMemo(() => buildTimeline(filteredMessages, []), [filteredMessages])\n\n return (\n <>\n <div className=\"flex items-center gap-2 flex-wrap\">\n <input\n type=\"text\"\n className=\"rounded-md border border-input bg-background px-3 py-1.5 text-sm w-44\"\n placeholder=\"Filter by agent…\"\n value={agentFilter}\n onChange={(e) => setAgentFilter(e.target.value)}\n />\n <select\n className=\"rounded-md border border-input bg-background px-3 py-1.5 text-sm\"\n value={kindFilter}\n onChange={(e) => setKindFilter(e.target.value)}\n >\n <option value=\"\">All kinds</option>\n {MSG_KIND_LABELS.map((k) => <option key={k} value={k}>{k}</option>)}\n </select>\n <Badge variant=\"secondary\" className=\"ml-auto\">{filteredMessages.length}</Badge>\n </div>\n\n <ScrollArea className=\"h-[calc(100dvh-13rem)]\">\n <div className=\"space-y-1 pr-2\">\n {timeline.length === 0 && (\n <div className=\"text-center text-muted-foreground py-16 text-sm\">No messages yet</div>\n )}\n {timeline.map((entry, i) => (\n <FirehoseRow key={i} entry={entry} agentsById={agentsById} />\n ))}\n </div>\n </ScrollArea>\n </>\n )\n}\n\nfunction EventsTab() {\n const now = useNow()\n const activityFilter = useRelayStore((s) => s.activityFilter)\n const activityEvents = useRelayStore((s) => s.activityEvents)\n const operatorActivity = useRelayStore((s) => s.operatorActivity)\n const set = useRelayStore((s) => s.set)\n const openActivityItem = useRelayStore((s) => s.openActivityItem)\n const exportActivity = useRelayStore((s) => s.exportActivity)\n\n const allItems = useMemo(() => {\n const merged = [...activityEvents, ...operatorActivity]\n const seen = new Set<string>()\n const deduped: ActivityEvent[] = []\n for (const item of merged) {\n const key = item.clientId || String(item.id)\n if (!seen.has(key)) { seen.add(key); deduped.push(item) }\n }\n return deduped\n .map((e) => ({ ...e, ts: e.ts ?? new Date(e.createdAt as string).getTime() }))\n .sort((a, b) => (b.ts ?? 0) - (a.ts ?? 0))\n }, [activityEvents, operatorActivity])\n\n const filtered = useMemo(() => {\n if (!activityFilter) return allItems\n return allItems.filter((e) => e.kind === activityFilter)\n }, [allItems, activityFilter])\n\n return (\n <>\n <div className=\"flex items-center gap-2 flex-wrap\">\n <select\n className=\"rounded-md border border-input bg-background px-3 py-1.5 text-sm\"\n value={activityFilter}\n onChange={(e) => set({ activityFilter: e.target.value })}\n >\n <option value=\"\">All types</option>\n {EVENT_KIND_LABELS.map((k) => <option key={k} value={k}>{k}</option>)}\n </select>\n <Button size=\"sm\" variant=\"outline\" onClick={() => exportActivity('markdown')}>\n <FileDown className=\"w-4 h-4 mr-1\" /> Markdown\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={() => exportActivity('json')}>\n <Braces className=\"w-4 h-4 mr-1\" /> JSON\n </Button>\n <Badge variant=\"secondary\" className=\"ml-auto\">{filtered.length}</Badge>\n </div>\n\n <ScrollArea className=\"h-[calc(100dvh-13rem)]\">\n <div className=\"space-y-2 pr-2\">\n {filtered.length === 0 && (\n <div className=\"text-center text-muted-foreground py-16 text-sm\">No activity yet</div>\n )}\n {filtered.map((item) => {\n const Icon = KIND_ICONS[item.kind] || Activity\n const colorClass = KIND_COLORS[item.kind] || KIND_COLORS.message\n const surface = formatSurface(item.metadata)\n return (\n <Card\n key={item.clientId || item.id}\n className=\"cursor-pointer hover:bg-accent/40 transition-colors\"\n onClick={() => openActivityItem(item)}\n >\n <CardContent className=\"p-3 flex gap-3\">\n <span className={`inline-flex items-center justify-center w-7 h-7 rounded-md border shrink-0 mt-0.5 ${colorClass}`}>\n <Icon className=\"w-3.5 h-3.5\" />\n </span>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"font-medium text-sm truncate\">{item.title}</span>\n <Badge variant=\"outline\" className={`text-xs px-1.5 py-0 border ${colorClass}`}>{item.kind}</Badge>\n <span className=\"text-xs text-muted-foreground ml-auto shrink-0\" title={fmtTime(item.ts ?? item.createdAt)}>\n {timeAgo(now, item.ts ?? item.createdAt)}\n </span>\n </div>\n {item.body && (\n <p className=\"text-xs text-muted-foreground mt-0.5 line-clamp-2\">{item.body}</p>\n )}\n {item.meta && (\n <p className=\"text-xs text-muted-foreground/60 mt-0.5 font-mono truncate\">{item.meta}</p>\n )}\n {surface && (\n <p className=\"text-xs text-muted-foreground/60 mt-0.5 truncate\" title={surface}>\n <span className=\"opacity-70\">via</span> {surface}\n </p>\n )}\n </div>\n </CardContent>\n </Card>\n )\n })}\n </div>\n </ScrollArea>\n </>\n )\n}\n\ntype ActivityTab = 'firehose' | 'events'\n\nexport function ActivityView() {\n const [tab, setTab] = useState<ActivityTab>('firehose')\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between flex-wrap gap-2\">\n <div className=\"flex items-center gap-2\">\n {tab === 'firehose'\n ? <Flame className=\"w-5 h-5 text-muted-foreground\" />\n : <Activity className=\"w-5 h-5 text-muted-foreground\" />}\n <h2 className=\"text-lg font-semibold\">{tab === 'firehose' ? 'Firehose' : 'Events'}</h2>\n </div>\n <div className=\"flex items-center gap-1 rounded-md border border-input overflow-hidden\">\n <button\n className={cn('px-3 py-1.5 text-sm transition-colors', tab === 'firehose' ? 'bg-primary text-primary-foreground' : 'hover:bg-accent')}\n onClick={() => setTab('firehose')}\n >\n Firehose\n </button>\n <button\n className={cn('px-3 py-1.5 text-sm transition-colors', tab === 'events' ? 'bg-primary text-primary-foreground' : 'hover:bg-accent')}\n onClick={() => setTab('events')}\n >\n Events\n </button>\n </div>\n </div>\n\n {tab === 'firehose' ? <FirehoseTab /> : <EventsTab />}\n </div>\n )\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{r as e}from"./chunk-CilyBKbf.js";import{Hn as t,I as n,Nn as r,Pt as i,Q as a,R as o,Rn as s,U as c,Ut as l,Wn as u,Y as d,dt as f,g as p,h as m,i as h,l as g,rr as _}from"./lucide-react-CsPXvXMC.js";import{l as ee,t as v}from"./store-DsqUEZOf.js";import{J as y,K as b,W as te,Y as x,a as S,d as C,i as ne,n as re}from"./display-CWMHll1J.js";import{o as w,r as T}from"./dist-CL2npVDe.js";import{t as E}from"./dist-CAFUEpK2.js";import{i as D,n as O}from"./dist-ERYvDMdt.js";import{t as k}from"./dist-Dmiv1tSO.js";import{t as A}from"./dist-YjP8Gd1C.js";import{a as ie,i as j,n as M,o as N,r as P,s as F,t as I}from"./es2015-Yto-4EBw.js";import{a as L,i as ae,n as R,r as oe,t as z}from"./dist-CnRv0y2x.js";import{t as B}from"./badge-CK6ejiOh.js";import{t as V}from"./button-BAwKuRIq.js";import{t as se}from"./copy-button-D3B_s7J7.js";import{G as H,K as U,L as ce,T as W,U as le,W as G,_ as ue,d as de,g as fe,l as pe,p as me,u as he,v as ge,w as K,y as _e}from"./index-CiBdEE9x.js";import{r as ve,t as ye}from"./card-DDxxo-Fo.js";import{n as be,t as xe}from"./branch-state-badge-Q4W68jxj.js";var q=e(_(),1),J=u(),Y=`Popover`,[Se,Ce]=D(Y,[L]),X=L(),[we,Z]=Se(Y),Te=e=>{let{__scopePopover:t,children:n,open:r,defaultOpen:i,onOpenChange:a,modal:o=!1}=e,s=X(t),c=q.useRef(null),[l,u]=q.useState(!1),[d,f]=k({prop:r,defaultProp:i??!1,onChange:a,caller:Y});return(0,J.jsx)(ae,{...s,children:(0,J.jsx)(we,{scope:t,contentId:F(),triggerRef:c,open:d,onOpenChange:f,onOpenToggle:q.useCallback(()=>f(e=>!e),[f]),hasCustomAnchor:l,onCustomAnchorAdd:q.useCallback(()=>u(!0),[]),onCustomAnchorRemove:q.useCallback(()=>u(!1),[]),modal:o,children:n})})};Te.displayName=Y;var Ee=`PopoverAnchor`,De=q.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=Z(Ee,n),a=X(n),{onCustomAnchorAdd:o,onCustomAnchorRemove:s}=i;return q.useEffect(()=>(o(),()=>s()),[o,s]),(0,J.jsx)(z,{...a,...r,ref:t})});De.displayName=Ee;var Oe=`PopoverTrigger`,ke=q.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=Z(Oe,n),a=X(n),o=w(t,i.triggerRef),s=(0,J.jsx)(E.button,{type:`button`,"aria-haspopup":`dialog`,"aria-expanded":i.open,"aria-controls":i.contentId,"data-state":He(i.open),...r,ref:o,onClick:O(e.onClick,i.onOpenToggle)});return i.hasCustomAnchor?s:(0,J.jsx)(z,{asChild:!0,...a,children:s})});ke.displayName=Oe;var Q=`PopoverPortal`,[Ae,je]=Se(Q,{forceMount:void 0}),Me=e=>{let{__scopePopover:t,forceMount:n,children:r,container:i}=e,a=Z(Q,t);return(0,J.jsx)(Ae,{scope:t,forceMount:n,children:(0,J.jsx)(A,{present:n||a.open,children:(0,J.jsx)(j,{asChild:!0,container:i,children:r})})})};Me.displayName=Q;var $=`PopoverContent`,Ne=q.forwardRef((e,t)=>{let n=je($,e.__scopePopover),{forceMount:r=n.forceMount,...i}=e,a=Z($,e.__scopePopover);return(0,J.jsx)(A,{present:r||a.open,children:a.modal?(0,J.jsx)(Fe,{...i,ref:t}):(0,J.jsx)(Ie,{...i,ref:t})})});Ne.displayName=$;var Pe=T(`PopoverContent.RemoveScroll`),Fe=q.forwardRef((e,t)=>{let n=Z($,e.__scopePopover),r=q.useRef(null),i=w(t,r),a=q.useRef(!1);return q.useEffect(()=>{let e=r.current;if(e)return I(e)},[]),(0,J.jsx)(M,{as:Pe,allowPinchZoom:!0,children:(0,J.jsx)(Le,{...e,ref:i,trapFocus:n.open,disableOutsidePointerEvents:!0,onCloseAutoFocus:O(e.onCloseAutoFocus,e=>{e.preventDefault(),a.current||n.triggerRef.current?.focus()}),onPointerDownOutside:O(e.onPointerDownOutside,e=>{let t=e.detail.originalEvent,n=t.button===0&&t.ctrlKey===!0;a.current=t.button===2||n},{checkForDefaultPrevented:!1}),onFocusOutside:O(e.onFocusOutside,e=>e.preventDefault(),{checkForDefaultPrevented:!1})})})}),Ie=q.forwardRef((e,t)=>{let n=Z($,e.__scopePopover),r=q.useRef(!1),i=q.useRef(!1);return(0,J.jsx)(Le,{...e,ref:t,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:t=>{e.onCloseAutoFocus?.(t),t.defaultPrevented||(r.current||n.triggerRef.current?.focus(),t.preventDefault()),r.current=!1,i.current=!1},onInteractOutside:t=>{e.onInteractOutside?.(t),t.defaultPrevented||(r.current=!0,t.detail.originalEvent.type===`pointerdown`&&(i.current=!0));let a=t.target;n.triggerRef.current?.contains(a)&&t.preventDefault(),t.detail.originalEvent.type===`focusin`&&i.current&&t.preventDefault()}})}),Le=q.forwardRef((e,t)=>{let{__scopePopover:n,trapFocus:r,onOpenAutoFocus:i,onCloseAutoFocus:a,disableOutsidePointerEvents:o,onEscapeKeyDown:s,onPointerDownOutside:c,onFocusOutside:l,onInteractOutside:u,...d}=e,f=Z($,n),p=X(n);return P(),(0,J.jsx)(ie,{asChild:!0,loop:!0,trapped:r,onMountAutoFocus:i,onUnmountAutoFocus:a,children:(0,J.jsx)(N,{asChild:!0,disableOutsidePointerEvents:o,onInteractOutside:u,onEscapeKeyDown:s,onPointerDownOutside:c,onFocusOutside:l,onDismiss:()=>f.onOpenChange(!1),children:(0,J.jsx)(oe,{"data-state":He(f.open),role:`dialog`,id:f.contentId,...p,...d,ref:t,style:{...d.style,"--radix-popover-content-transform-origin":`var(--radix-popper-transform-origin)`,"--radix-popover-content-available-width":`var(--radix-popper-available-width)`,"--radix-popover-content-available-height":`var(--radix-popper-available-height)`,"--radix-popover-trigger-width":`var(--radix-popper-anchor-width)`,"--radix-popover-trigger-height":`var(--radix-popper-anchor-height)`}})})})}),Re=`PopoverClose`,ze=q.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=Z(Re,n);return(0,J.jsx)(E.button,{type:`button`,...r,ref:t,onClick:O(e.onClick,()=>i.onOpenChange(!1))})});ze.displayName=Re;var Be=`PopoverArrow`,Ve=q.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=X(n);return(0,J.jsx)(R,{...i,...r,ref:t})});Ve.displayName=Be;function He(e){return e?`open`:`closed`}var Ue=Te,We=ke,Ge=Me,Ke=Ne;function qe({...e}){return(0,J.jsx)(Ue,{"data-slot":`popover`,...e})}function Je({...e}){return(0,J.jsx)(We,{"data-slot":`popover-trigger`,...e})}function Ye({className:e,align:n=`center`,sideOffset:r=4,...i}){return(0,J.jsx)(Ge,{children:(0,J.jsx)(Ke,{"data-slot":`popover-content`,align:n,sideOffset:r,className:t(`z-50 flex w-72 origin-(--radix-popover-content-transform-origin) flex-col gap-2.5 rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95`,e),...i})})}function Xe({className:e,...n}){return(0,J.jsx)(`div`,{"data-slot":`popover-header`,className:t(`flex flex-col gap-0.5 text-sm`,e),...n})}function Ze({className:e,...n}){return(0,J.jsx)(`div`,{"data-slot":`popover-title`,className:t(`font-medium`,e),...n})}function Qe({agent:e,childAgents:t=[],parentAgent:r}){let o=ee();v(e=>e.set);let s=v(e=>e.switchView),u=v(e=>e.openInboxThread),h=v(e=>e.openAgentDetail),_=v(e=>e.openPairInvite),w=v(e=>e.openRename),T=v(e=>e.openConfirm),E=v(e=>e.doAgentAction),D=v(e=>e.doDeleteAgent),O=v(e=>e.openFilesForAgent),k=v(e=>e.workspaceAction),A=v(e=>e.openWorkspaceFocus),{terminalOpen:ie,terminalTarget:j,terminalOpening:M,openTerminal:N,closeTerminal:P}=be(e.id),F=le(),I=ne(o,e,ce(e),F[e.id]||null),L=S(e,`shutdown`),ae=S(e,`compact`),R=S(e,`clearContext`),oe=!!(e.providerCapabilities?.terminal?.live?.read||e.providerCapabilities?.terminal?.attach?.create),z=!!(e.providerCapabilities?.terminal?.live?.write||e.providerCapabilities?.model?.provider===`claude`),H=re(e),U=r?C(r):e.spawnedBy,G=t.length>0;return(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(ye,{className:`group hover:border-zinc-600 transition-colors cursor-pointer`,onClick:()=>h(e),children:(0,J.jsxs)(ve,{className:`p-4`,children:[(0,J.jsxs)(`div`,{className:`flex items-start gap-2.5 mb-2.5`,children:[(0,J.jsx)(W,{agent:e,now:o,className:`mt-0.5`}),(0,J.jsx)(K,{agent:e}),(0,J.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,J.jsx)(`div`,{className:`text-sm font-medium truncate`,children:C(e)}),(0,J.jsx)(`div`,{className:`text-xs mt-0.5 ${y(I.tone)}`,children:I.label}),typeof e.meta?.cwd==`string`&&e.meta.cwd&&(0,J.jsx)(`button`,{type:`button`,className:`mt-0.5 block max-w-full truncate font-mono text-[10px] text-muted-foreground hover:text-foreground`,title:`Open ${e.meta.cwd} in Files`,onClick:t=>{t.stopPropagation(),O(e)},children:te(e.meta.cwd)}),(0,J.jsx)(me,{agent:e,className:`mt-1`})]}),e.branchState&&e.branchWorkspaceId&&(0,J.jsx)(xe,{state:e.branchState,className:`mt-0.5 shrink-0`,onClick:t=>{t.stopPropagation(),A(e.branchWorkspaceId)}})]}),I.badges.length>0&&(0,J.jsx)(`div`,{className:`flex flex-wrap gap-1 mb-2`,children:I.badges.map(e=>(0,J.jsx)(`span`,{className:`text-[10px] px-1.5 py-0.5 rounded-full font-medium ${e.className}`,children:e.label},e.label))}),(G||e.spawnedBy&&U)&&(0,J.jsxs)(`div`,{className:`mb-2 flex flex-wrap gap-1.5`,onClick:e=>e.stopPropagation(),children:[G&&(0,J.jsxs)(qe,{children:[(0,J.jsx)(Je,{asChild:!0,children:(0,J.jsxs)(`button`,{type:`button`,className:`inline-flex h-6 max-w-full items-center gap-1.5 rounded-full border border-sky-500/30 bg-sky-500/10 px-2 text-[10px] font-medium text-sky-300 transition-colors hover:bg-sky-500/15`,title:`${t.length} live child ${t.length===1?`agent`:`agents`}`,children:[(0,J.jsx)(g,{className:`h-3 w-3`}),(0,J.jsx)(`span`,{children:t.length}),(0,J.jsx)(`span`,{className:`flex -space-x-1`,children:t.slice(0,4).map(e=>(0,J.jsx)(W,{agent:e,now:o,className:`h-2 w-2 ring-1 ring-background`},e.id))})]})}),(0,J.jsxs)(Ye,{align:`start`,className:`w-80`,onClick:e=>e.stopPropagation(),children:[(0,J.jsx)(Xe,{children:(0,J.jsx)(Ze,{children:`Team`})}),(0,J.jsx)(`div`,{className:`space-y-1.5`,children:t.map(e=>(0,J.jsxs)(`div`,{className:`rounded-md border border-border bg-card/60 p-2`,children:[(0,J.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,J.jsx)(W,{agent:e,now:o,className:`mt-1`}),(0,J.jsx)(K,{agent:e}),(0,J.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,J.jsx)(`div`,{className:`truncate text-xs font-medium`,children:C(e)}),(0,J.jsx)(`div`,{className:`truncate text-[10px] text-muted-foreground`,children:e.providerCapabilities?.model?.alias||e.providerCapabilities?.model?.id||e.providerCapabilities?.model?.provider||e.status})]}),(0,J.jsx)(B,{variant:`outline`,className:`h-4 px-1.5 text-[9px]`,children:e.status})]}),(0,J.jsxs)(`div`,{className:`mt-2 flex gap-1`,children:[(0,J.jsx)(V,{size:`xs`,variant:`outline`,onClick:()=>h(e),children:`Open`}),(0,J.jsxs)(V,{size:`xs`,variant:`ghost`,onClick:()=>{u(e.id),s(`chat`)},children:[(0,J.jsx)(a,{className:`h-3 w-3`}),`Chat`]})]})]},e.id))})]})]}),e.spawnedBy&&U&&(0,J.jsx)(B,{variant:`outline`,className:`max-w-full text-[10px] text-muted-foreground`,children:(0,J.jsxs)(`span`,{className:`truncate`,children:[`spawned by `,U]})})]}),(e.tags.length>0||x(e.capabilities).length>0)&&(0,J.jsxs)(`div`,{className:`flex flex-wrap gap-1 mb-2`,children:[e.tags.slice(0,3).map(e=>(0,J.jsx)(B,{variant:`outline`,className:`text-[9px] px-1 py-0 h-4`,children:e},e)),x(e.capabilities).slice(0,2).map(e=>(0,J.jsx)(B,{variant:`secondary`,className:`text-[9px] px-1 py-0 h-4`,children:e},e))]}),(0,J.jsxs)(`div`,{className:`space-y-2 mb-2`,children:[(0,J.jsx)(ge,{agent:e}),(0,J.jsx)(ue,{agent:e,compact:!0}),(0,J.jsx)(_e,{agent:e})]}),(0,J.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:e.id!==`user`&&e.id!==`system`&&b(o,e.lastSeen)}),(0,J.jsxs)(`div`,{className:`flex gap-1 mt-2.5 opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity`,onClick:e=>e.stopPropagation(),children:[(0,J.jsx)(se,{value:e.id,label:`Copy agent ID`,size:`icon`,className:`h-7 w-7`,iconClassName:`w-3 h-3`}),(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Chat`,onClick:()=>{u(e.id),s(`chat`)},children:(0,J.jsx)(a,{className:`w-3 h-3`})}),(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Pair`,onClick:()=>_(e.id),children:(0,J.jsx)(f,{className:`w-3 h-3`})}),(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Rename`,onClick:()=>w(e),children:(0,J.jsx)(c,{className:`w-3 h-3`})}),oe&&(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Terminal`,disabled:M,onClick:()=>void N(),children:(0,J.jsx)(p,{className:`w-3 h-3`})}),(e.branchState===`changes`||e.branchState===`idle`)&&e.branchWorkspaceId&&(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7 text-amber-400 hover:text-amber-300`,title:`Mark workspace ready — hand off to the auto-merge`,onClick:()=>T(`Mark Workspace Ready`,`Mark ${C(e)}'s branch ready to land? The relay auto-merge will rebase and land it.`,()=>k(e.branchWorkspaceId,`ready`)),children:(0,J.jsx)(i,{className:`w-3 h-3`})}),ae&&(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Compact`,onClick:()=>T(`Compact Agent`,`Compact context for ${C(e)}?`,()=>E(e,`compact`,`agents-grid`)),children:(0,J.jsx)(d,{className:`w-3 h-3`})}),R&&(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Clear Context`,onClick:()=>T(`Clear Context`,`Clear context for ${C(e)}?`,()=>E(e,`clearContext`,`agents-grid`)),children:(0,J.jsx)(l,{className:`w-3 h-3`})}),L&&(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7 text-red-400 hover:text-red-300`,title:`Shutdown`,onClick:()=>T(`Shutdown Agent`,`Shutdown ${C(e)}?`,()=>E(e,`shutdown`,`agents-grid`)),children:(0,J.jsx)(n,{className:`w-3 h-3`})}),H&&(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7 text-red-400 hover:text-red-300`,title:`Forget stale agent`,onClick:()=>T(`Forget Agent`,`Forget ${C(e)}?`,()=>D(e.id)),children:(0,J.jsx)(m,{className:`w-3 h-3`})})]})]})}),j&&(0,J.jsx)(fe,{open:ie,onOpenChange:P,orchestratorId:j.orchestratorId,session:j.session,interactive:j.interactive||z})]})}function $e(){let e=v(e=>e.agentPresetFilter),t=v(e=>e.agentStatusFilter),n=v(e=>e.agentTagFilter),i=v(e=>e.agentHostFilter),a=v(e=>e.agentSort),c=v(e=>e.agentSortDir),l=v(e=>e.showOffline),u=v(e=>e.set),d=v(e=>e.openAgentSpawn),f=v(e=>e.agentsById),p=ee(),m=G(),g=U(),_=H(),y=pe(m,p),b=de(m,p),te=e||t||n||i;function x(){u({agentPresetFilter:``,agentStatusFilter:``,agentTagFilter:``,agentHostFilter:``})}function S(){u({agentSortDir:c===`asc`?`desc`:`asc`})}return(0,J.jsxs)(`div`,{className:`space-y-4`,children:[(0,J.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,J.jsxs)(`select`,{value:e,onChange:e=>u({agentPresetFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,J.jsx)(`option`,{value:``,children:`All agents`}),(0,J.jsx)(`option`,{value:`active`,children:`Active`}),(0,J.jsx)(`option`,{value:`claude`,children:`Claude`}),(0,J.jsx)(`option`,{value:`codex`,children:`Codex`}),(0,J.jsx)(`option`,{value:`paired`,children:`Paired`}),(0,J.jsx)(`option`,{value:`unpaired`,children:`Unpaired`}),(0,J.jsx)(`option`,{value:`offline_stale`,children:`Offline / Stale`})]}),(0,J.jsxs)(`select`,{value:t,onChange:e=>u({agentStatusFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,J.jsx)(`option`,{value:``,children:`Any status`}),(0,J.jsx)(`option`,{value:`online`,children:`Online`}),(0,J.jsx)(`option`,{value:`idle`,children:`Idle`}),(0,J.jsx)(`option`,{value:`busy`,children:`Busy`}),(0,J.jsx)(`option`,{value:`offline`,children:`Offline`}),(0,J.jsx)(`option`,{value:`starting`,children:`Starting`})]}),g.length>0&&(0,J.jsxs)(`select`,{value:n,onChange:e=>u({agentTagFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,J.jsx)(`option`,{value:``,children:`Any tag`}),g.map(e=>(0,J.jsx)(`option`,{value:e,children:e},e))]}),_.length>1&&(0,J.jsxs)(`select`,{value:i,onChange:e=>u({agentHostFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,J.jsx)(`option`,{value:``,children:`Any host`}),_.map(e=>(0,J.jsx)(`option`,{value:e,children:e},e))]}),(0,J.jsxs)(`select`,{value:a,onChange:e=>u({agentSort:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,J.jsx)(`option`,{value:`status`,children:`Sort: Status`}),(0,J.jsx)(`option`,{value:`name`,children:`Sort: Name`}),(0,J.jsx)(`option`,{value:`lastSeen`,children:`Sort: Last seen`}),(0,J.jsx)(`option`,{value:`created`,children:`Sort: Created`})]}),(0,J.jsx)(V,{size:`icon`,variant:`outline`,className:`h-8 w-8`,title:`Toggle sort direction`,onClick:S,children:c===`asc`?(0,J.jsx)(r,{className:`w-3.5 h-3.5`}):(0,J.jsx)(s,{className:`w-3.5 h-3.5`})}),(0,J.jsxs)(`label`,{className:`flex items-center gap-1.5 text-sm text-muted-foreground cursor-pointer select-none`,children:[(0,J.jsx)(`input`,{type:`checkbox`,checked:l,onChange:e=>u({showOffline:e.target.checked}),className:`rounded`}),`Show offline`]}),te&&(0,J.jsxs)(V,{size:`sm`,variant:`ghost`,className:`h-8 text-muted-foreground hover:text-foreground gap-1`,onClick:x,children:[(0,J.jsx)(h,{className:`w-3 h-3`}),`Clear filters`]}),(0,J.jsx)(`div`,{className:`ml-auto`,children:(0,J.jsxs)(V,{size:`sm`,onClick:d,className:`gap-1`,children:[(0,J.jsx)(o,{className:`w-3.5 h-3.5`}),`Spawn`]})})]}),b.length===0?(0,J.jsx)(`div`,{className:`text-center py-16 text-muted-foreground text-sm`,children:`No agents match the current filters.`}):(0,J.jsx)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 gap-3`,children:b.map(e=>(0,J.jsx)(Qe,{agent:e,parentAgent:e.spawnedBy?f[e.spawnedBy]??null:null,childAgents:he(y.get(e.id)??[])},e.id))})]})}export{$e as AgentsView};
2
- //# sourceMappingURL=agents-C2TNRCn1.js.map
1
+ import{r as e}from"./chunk-CilyBKbf.js";import{Hn as t,I as n,Nn as r,Pt as i,Q as a,R as o,Rn as s,U as c,Ut as l,Wn as u,Y as d,dt as f,g as p,h as m,i as h,l as g,rr as _}from"./lucide-react-CsPXvXMC.js";import{l as ee,t as v}from"./store-DsqUEZOf.js";import{J as y,K as b,W as te,Y as x,a as S,d as C,i as ne,n as re}from"./display-CWMHll1J.js";import{o as w,r as T}from"./dist-CL2npVDe.js";import{t as E}from"./dist-CAFUEpK2.js";import{i as D,n as O}from"./dist-ERYvDMdt.js";import{t as k}from"./dist-Dmiv1tSO.js";import{t as A}from"./dist-YjP8Gd1C.js";import{a as ie,i as j,n as M,o as N,r as P,s as F,t as I}from"./es2015-Yto-4EBw.js";import{a as L,i as ae,n as R,r as oe,t as z}from"./dist-CnRv0y2x.js";import{t as B}from"./badge-CK6ejiOh.js";import{t as V}from"./button-BAwKuRIq.js";import{t as se}from"./copy-button-D3B_s7J7.js";import{G as H,K as U,L as ce,T as W,U as le,W as G,_ as ue,d as de,g as fe,l as pe,p as me,u as he,v as ge,w as K,y as _e}from"./index-Dm1zlklN.js";import{r as ve,t as ye}from"./card-DDxxo-Fo.js";import{n as be,t as xe}from"./branch-state-badge-Q4W68jxj.js";var q=e(_(),1),J=u(),Y=`Popover`,[Se,Ce]=D(Y,[L]),X=L(),[we,Z]=Se(Y),Te=e=>{let{__scopePopover:t,children:n,open:r,defaultOpen:i,onOpenChange:a,modal:o=!1}=e,s=X(t),c=q.useRef(null),[l,u]=q.useState(!1),[d,f]=k({prop:r,defaultProp:i??!1,onChange:a,caller:Y});return(0,J.jsx)(ae,{...s,children:(0,J.jsx)(we,{scope:t,contentId:F(),triggerRef:c,open:d,onOpenChange:f,onOpenToggle:q.useCallback(()=>f(e=>!e),[f]),hasCustomAnchor:l,onCustomAnchorAdd:q.useCallback(()=>u(!0),[]),onCustomAnchorRemove:q.useCallback(()=>u(!1),[]),modal:o,children:n})})};Te.displayName=Y;var Ee=`PopoverAnchor`,De=q.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=Z(Ee,n),a=X(n),{onCustomAnchorAdd:o,onCustomAnchorRemove:s}=i;return q.useEffect(()=>(o(),()=>s()),[o,s]),(0,J.jsx)(z,{...a,...r,ref:t})});De.displayName=Ee;var Oe=`PopoverTrigger`,ke=q.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=Z(Oe,n),a=X(n),o=w(t,i.triggerRef),s=(0,J.jsx)(E.button,{type:`button`,"aria-haspopup":`dialog`,"aria-expanded":i.open,"aria-controls":i.contentId,"data-state":He(i.open),...r,ref:o,onClick:O(e.onClick,i.onOpenToggle)});return i.hasCustomAnchor?s:(0,J.jsx)(z,{asChild:!0,...a,children:s})});ke.displayName=Oe;var Q=`PopoverPortal`,[Ae,je]=Se(Q,{forceMount:void 0}),Me=e=>{let{__scopePopover:t,forceMount:n,children:r,container:i}=e,a=Z(Q,t);return(0,J.jsx)(Ae,{scope:t,forceMount:n,children:(0,J.jsx)(A,{present:n||a.open,children:(0,J.jsx)(j,{asChild:!0,container:i,children:r})})})};Me.displayName=Q;var $=`PopoverContent`,Ne=q.forwardRef((e,t)=>{let n=je($,e.__scopePopover),{forceMount:r=n.forceMount,...i}=e,a=Z($,e.__scopePopover);return(0,J.jsx)(A,{present:r||a.open,children:a.modal?(0,J.jsx)(Fe,{...i,ref:t}):(0,J.jsx)(Ie,{...i,ref:t})})});Ne.displayName=$;var Pe=T(`PopoverContent.RemoveScroll`),Fe=q.forwardRef((e,t)=>{let n=Z($,e.__scopePopover),r=q.useRef(null),i=w(t,r),a=q.useRef(!1);return q.useEffect(()=>{let e=r.current;if(e)return I(e)},[]),(0,J.jsx)(M,{as:Pe,allowPinchZoom:!0,children:(0,J.jsx)(Le,{...e,ref:i,trapFocus:n.open,disableOutsidePointerEvents:!0,onCloseAutoFocus:O(e.onCloseAutoFocus,e=>{e.preventDefault(),a.current||n.triggerRef.current?.focus()}),onPointerDownOutside:O(e.onPointerDownOutside,e=>{let t=e.detail.originalEvent,n=t.button===0&&t.ctrlKey===!0;a.current=t.button===2||n},{checkForDefaultPrevented:!1}),onFocusOutside:O(e.onFocusOutside,e=>e.preventDefault(),{checkForDefaultPrevented:!1})})})}),Ie=q.forwardRef((e,t)=>{let n=Z($,e.__scopePopover),r=q.useRef(!1),i=q.useRef(!1);return(0,J.jsx)(Le,{...e,ref:t,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:t=>{e.onCloseAutoFocus?.(t),t.defaultPrevented||(r.current||n.triggerRef.current?.focus(),t.preventDefault()),r.current=!1,i.current=!1},onInteractOutside:t=>{e.onInteractOutside?.(t),t.defaultPrevented||(r.current=!0,t.detail.originalEvent.type===`pointerdown`&&(i.current=!0));let a=t.target;n.triggerRef.current?.contains(a)&&t.preventDefault(),t.detail.originalEvent.type===`focusin`&&i.current&&t.preventDefault()}})}),Le=q.forwardRef((e,t)=>{let{__scopePopover:n,trapFocus:r,onOpenAutoFocus:i,onCloseAutoFocus:a,disableOutsidePointerEvents:o,onEscapeKeyDown:s,onPointerDownOutside:c,onFocusOutside:l,onInteractOutside:u,...d}=e,f=Z($,n),p=X(n);return P(),(0,J.jsx)(ie,{asChild:!0,loop:!0,trapped:r,onMountAutoFocus:i,onUnmountAutoFocus:a,children:(0,J.jsx)(N,{asChild:!0,disableOutsidePointerEvents:o,onInteractOutside:u,onEscapeKeyDown:s,onPointerDownOutside:c,onFocusOutside:l,onDismiss:()=>f.onOpenChange(!1),children:(0,J.jsx)(oe,{"data-state":He(f.open),role:`dialog`,id:f.contentId,...p,...d,ref:t,style:{...d.style,"--radix-popover-content-transform-origin":`var(--radix-popper-transform-origin)`,"--radix-popover-content-available-width":`var(--radix-popper-available-width)`,"--radix-popover-content-available-height":`var(--radix-popper-available-height)`,"--radix-popover-trigger-width":`var(--radix-popper-anchor-width)`,"--radix-popover-trigger-height":`var(--radix-popper-anchor-height)`}})})})}),Re=`PopoverClose`,ze=q.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=Z(Re,n);return(0,J.jsx)(E.button,{type:`button`,...r,ref:t,onClick:O(e.onClick,()=>i.onOpenChange(!1))})});ze.displayName=Re;var Be=`PopoverArrow`,Ve=q.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=X(n);return(0,J.jsx)(R,{...i,...r,ref:t})});Ve.displayName=Be;function He(e){return e?`open`:`closed`}var Ue=Te,We=ke,Ge=Me,Ke=Ne;function qe({...e}){return(0,J.jsx)(Ue,{"data-slot":`popover`,...e})}function Je({...e}){return(0,J.jsx)(We,{"data-slot":`popover-trigger`,...e})}function Ye({className:e,align:n=`center`,sideOffset:r=4,...i}){return(0,J.jsx)(Ge,{children:(0,J.jsx)(Ke,{"data-slot":`popover-content`,align:n,sideOffset:r,className:t(`z-50 flex w-72 origin-(--radix-popover-content-transform-origin) flex-col gap-2.5 rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95`,e),...i})})}function Xe({className:e,...n}){return(0,J.jsx)(`div`,{"data-slot":`popover-header`,className:t(`flex flex-col gap-0.5 text-sm`,e),...n})}function Ze({className:e,...n}){return(0,J.jsx)(`div`,{"data-slot":`popover-title`,className:t(`font-medium`,e),...n})}function Qe({agent:e,childAgents:t=[],parentAgent:r}){let o=ee();v(e=>e.set);let s=v(e=>e.switchView),u=v(e=>e.openInboxThread),h=v(e=>e.openAgentDetail),_=v(e=>e.openPairInvite),w=v(e=>e.openRename),T=v(e=>e.openConfirm),E=v(e=>e.doAgentAction),D=v(e=>e.doDeleteAgent),O=v(e=>e.openFilesForAgent),k=v(e=>e.workspaceAction),A=v(e=>e.openWorkspaceFocus),{terminalOpen:ie,terminalTarget:j,terminalOpening:M,openTerminal:N,closeTerminal:P}=be(e.id),F=le(),I=ne(o,e,ce(e),F[e.id]||null),L=S(e,`shutdown`),ae=S(e,`compact`),R=S(e,`clearContext`),oe=!!(e.providerCapabilities?.terminal?.live?.read||e.providerCapabilities?.terminal?.attach?.create),z=!!(e.providerCapabilities?.terminal?.live?.write||e.providerCapabilities?.model?.provider===`claude`),H=re(e),U=r?C(r):e.spawnedBy,G=t.length>0;return(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(ye,{className:`group hover:border-zinc-600 transition-colors cursor-pointer`,onClick:()=>h(e),children:(0,J.jsxs)(ve,{className:`p-4`,children:[(0,J.jsxs)(`div`,{className:`flex items-start gap-2.5 mb-2.5`,children:[(0,J.jsx)(W,{agent:e,now:o,className:`mt-0.5`}),(0,J.jsx)(K,{agent:e}),(0,J.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,J.jsx)(`div`,{className:`text-sm font-medium truncate`,children:C(e)}),(0,J.jsx)(`div`,{className:`text-xs mt-0.5 ${y(I.tone)}`,children:I.label}),typeof e.meta?.cwd==`string`&&e.meta.cwd&&(0,J.jsx)(`button`,{type:`button`,className:`mt-0.5 block max-w-full truncate font-mono text-[10px] text-muted-foreground hover:text-foreground`,title:`Open ${e.meta.cwd} in Files`,onClick:t=>{t.stopPropagation(),O(e)},children:te(e.meta.cwd)}),(0,J.jsx)(me,{agent:e,className:`mt-1`})]}),e.branchState&&e.branchWorkspaceId&&(0,J.jsx)(xe,{state:e.branchState,className:`mt-0.5 shrink-0`,onClick:t=>{t.stopPropagation(),A(e.branchWorkspaceId)}})]}),I.badges.length>0&&(0,J.jsx)(`div`,{className:`flex flex-wrap gap-1 mb-2`,children:I.badges.map(e=>(0,J.jsx)(`span`,{className:`text-[10px] px-1.5 py-0.5 rounded-full font-medium ${e.className}`,children:e.label},e.label))}),(G||e.spawnedBy&&U)&&(0,J.jsxs)(`div`,{className:`mb-2 flex flex-wrap gap-1.5`,onClick:e=>e.stopPropagation(),children:[G&&(0,J.jsxs)(qe,{children:[(0,J.jsx)(Je,{asChild:!0,children:(0,J.jsxs)(`button`,{type:`button`,className:`inline-flex h-6 max-w-full items-center gap-1.5 rounded-full border border-sky-500/30 bg-sky-500/10 px-2 text-[10px] font-medium text-sky-300 transition-colors hover:bg-sky-500/15`,title:`${t.length} live child ${t.length===1?`agent`:`agents`}`,children:[(0,J.jsx)(g,{className:`h-3 w-3`}),(0,J.jsx)(`span`,{children:t.length}),(0,J.jsx)(`span`,{className:`flex -space-x-1`,children:t.slice(0,4).map(e=>(0,J.jsx)(W,{agent:e,now:o,className:`h-2 w-2 ring-1 ring-background`},e.id))})]})}),(0,J.jsxs)(Ye,{align:`start`,className:`w-80`,onClick:e=>e.stopPropagation(),children:[(0,J.jsx)(Xe,{children:(0,J.jsx)(Ze,{children:`Team`})}),(0,J.jsx)(`div`,{className:`space-y-1.5`,children:t.map(e=>(0,J.jsxs)(`div`,{className:`rounded-md border border-border bg-card/60 p-2`,children:[(0,J.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,J.jsx)(W,{agent:e,now:o,className:`mt-1`}),(0,J.jsx)(K,{agent:e}),(0,J.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,J.jsx)(`div`,{className:`truncate text-xs font-medium`,children:C(e)}),(0,J.jsx)(`div`,{className:`truncate text-[10px] text-muted-foreground`,children:e.providerCapabilities?.model?.alias||e.providerCapabilities?.model?.id||e.providerCapabilities?.model?.provider||e.status})]}),(0,J.jsx)(B,{variant:`outline`,className:`h-4 px-1.5 text-[9px]`,children:e.status})]}),(0,J.jsxs)(`div`,{className:`mt-2 flex gap-1`,children:[(0,J.jsx)(V,{size:`xs`,variant:`outline`,onClick:()=>h(e),children:`Open`}),(0,J.jsxs)(V,{size:`xs`,variant:`ghost`,onClick:()=>{u(e.id),s(`chat`)},children:[(0,J.jsx)(a,{className:`h-3 w-3`}),`Chat`]})]})]},e.id))})]})]}),e.spawnedBy&&U&&(0,J.jsx)(B,{variant:`outline`,className:`max-w-full text-[10px] text-muted-foreground`,children:(0,J.jsxs)(`span`,{className:`truncate`,children:[`spawned by `,U]})})]}),(e.tags.length>0||x(e.capabilities).length>0)&&(0,J.jsxs)(`div`,{className:`flex flex-wrap gap-1 mb-2`,children:[e.tags.slice(0,3).map(e=>(0,J.jsx)(B,{variant:`outline`,className:`text-[9px] px-1 py-0 h-4`,children:e},e)),x(e.capabilities).slice(0,2).map(e=>(0,J.jsx)(B,{variant:`secondary`,className:`text-[9px] px-1 py-0 h-4`,children:e},e))]}),(0,J.jsxs)(`div`,{className:`space-y-2 mb-2`,children:[(0,J.jsx)(ge,{agent:e}),(0,J.jsx)(ue,{agent:e,compact:!0}),(0,J.jsx)(_e,{agent:e})]}),(0,J.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:e.id!==`user`&&e.id!==`system`&&b(o,e.lastSeen)}),(0,J.jsxs)(`div`,{className:`flex gap-1 mt-2.5 opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity`,onClick:e=>e.stopPropagation(),children:[(0,J.jsx)(se,{value:e.id,label:`Copy agent ID`,size:`icon`,className:`h-7 w-7`,iconClassName:`w-3 h-3`}),(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Chat`,onClick:()=>{u(e.id),s(`chat`)},children:(0,J.jsx)(a,{className:`w-3 h-3`})}),(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Pair`,onClick:()=>_(e.id),children:(0,J.jsx)(f,{className:`w-3 h-3`})}),(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Rename`,onClick:()=>w(e),children:(0,J.jsx)(c,{className:`w-3 h-3`})}),oe&&(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Terminal`,disabled:M,onClick:()=>void N(),children:(0,J.jsx)(p,{className:`w-3 h-3`})}),(e.branchState===`changes`||e.branchState===`idle`)&&e.branchWorkspaceId&&(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7 text-amber-400 hover:text-amber-300`,title:`Mark workspace ready — hand off to the auto-merge`,onClick:()=>T(`Mark Workspace Ready`,`Mark ${C(e)}'s branch ready to land? The relay auto-merge will rebase and land it.`,()=>k(e.branchWorkspaceId,`ready`)),children:(0,J.jsx)(i,{className:`w-3 h-3`})}),ae&&(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Compact`,onClick:()=>T(`Compact Agent`,`Compact context for ${C(e)}?`,()=>E(e,`compact`,`agents-grid`)),children:(0,J.jsx)(d,{className:`w-3 h-3`})}),R&&(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7`,title:`Clear Context`,onClick:()=>T(`Clear Context`,`Clear context for ${C(e)}?`,()=>E(e,`clearContext`,`agents-grid`)),children:(0,J.jsx)(l,{className:`w-3 h-3`})}),L&&(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7 text-red-400 hover:text-red-300`,title:`Shutdown`,onClick:()=>T(`Shutdown Agent`,`Shutdown ${C(e)}?`,()=>E(e,`shutdown`,`agents-grid`)),children:(0,J.jsx)(n,{className:`w-3 h-3`})}),H&&(0,J.jsx)(V,{size:`icon`,variant:`ghost`,className:`h-7 w-7 text-red-400 hover:text-red-300`,title:`Forget stale agent`,onClick:()=>T(`Forget Agent`,`Forget ${C(e)}?`,()=>D(e.id)),children:(0,J.jsx)(m,{className:`w-3 h-3`})})]})]})}),j&&(0,J.jsx)(fe,{open:ie,onOpenChange:P,orchestratorId:j.orchestratorId,session:j.session,interactive:j.interactive||z})]})}function $e(){let e=v(e=>e.agentPresetFilter),t=v(e=>e.agentStatusFilter),n=v(e=>e.agentTagFilter),i=v(e=>e.agentHostFilter),a=v(e=>e.agentSort),c=v(e=>e.agentSortDir),l=v(e=>e.showOffline),u=v(e=>e.set),d=v(e=>e.openAgentSpawn),f=v(e=>e.agentsById),p=ee(),m=G(),g=U(),_=H(),y=pe(m,p),b=de(m,p),te=e||t||n||i;function x(){u({agentPresetFilter:``,agentStatusFilter:``,agentTagFilter:``,agentHostFilter:``})}function S(){u({agentSortDir:c===`asc`?`desc`:`asc`})}return(0,J.jsxs)(`div`,{className:`space-y-4`,children:[(0,J.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,J.jsxs)(`select`,{value:e,onChange:e=>u({agentPresetFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,J.jsx)(`option`,{value:``,children:`All agents`}),(0,J.jsx)(`option`,{value:`active`,children:`Active`}),(0,J.jsx)(`option`,{value:`claude`,children:`Claude`}),(0,J.jsx)(`option`,{value:`codex`,children:`Codex`}),(0,J.jsx)(`option`,{value:`paired`,children:`Paired`}),(0,J.jsx)(`option`,{value:`unpaired`,children:`Unpaired`}),(0,J.jsx)(`option`,{value:`offline_stale`,children:`Offline / Stale`})]}),(0,J.jsxs)(`select`,{value:t,onChange:e=>u({agentStatusFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,J.jsx)(`option`,{value:``,children:`Any status`}),(0,J.jsx)(`option`,{value:`online`,children:`Online`}),(0,J.jsx)(`option`,{value:`idle`,children:`Idle`}),(0,J.jsx)(`option`,{value:`busy`,children:`Busy`}),(0,J.jsx)(`option`,{value:`offline`,children:`Offline`}),(0,J.jsx)(`option`,{value:`starting`,children:`Starting`})]}),g.length>0&&(0,J.jsxs)(`select`,{value:n,onChange:e=>u({agentTagFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,J.jsx)(`option`,{value:``,children:`Any tag`}),g.map(e=>(0,J.jsx)(`option`,{value:e,children:e},e))]}),_.length>1&&(0,J.jsxs)(`select`,{value:i,onChange:e=>u({agentHostFilter:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,J.jsx)(`option`,{value:``,children:`Any host`}),_.map(e=>(0,J.jsx)(`option`,{value:e,children:e},e))]}),(0,J.jsxs)(`select`,{value:a,onChange:e=>u({agentSort:e.target.value}),className:`h-8 rounded-md border border-border bg-card text-sm px-2 text-foreground`,children:[(0,J.jsx)(`option`,{value:`status`,children:`Sort: Status`}),(0,J.jsx)(`option`,{value:`name`,children:`Sort: Name`}),(0,J.jsx)(`option`,{value:`lastSeen`,children:`Sort: Last seen`}),(0,J.jsx)(`option`,{value:`created`,children:`Sort: Created`})]}),(0,J.jsx)(V,{size:`icon`,variant:`outline`,className:`h-8 w-8`,title:`Toggle sort direction`,onClick:S,children:c===`asc`?(0,J.jsx)(r,{className:`w-3.5 h-3.5`}):(0,J.jsx)(s,{className:`w-3.5 h-3.5`})}),(0,J.jsxs)(`label`,{className:`flex items-center gap-1.5 text-sm text-muted-foreground cursor-pointer select-none`,children:[(0,J.jsx)(`input`,{type:`checkbox`,checked:l,onChange:e=>u({showOffline:e.target.checked}),className:`rounded`}),`Show offline`]}),te&&(0,J.jsxs)(V,{size:`sm`,variant:`ghost`,className:`h-8 text-muted-foreground hover:text-foreground gap-1`,onClick:x,children:[(0,J.jsx)(h,{className:`w-3 h-3`}),`Clear filters`]}),(0,J.jsx)(`div`,{className:`ml-auto`,children:(0,J.jsxs)(V,{size:`sm`,onClick:d,className:`gap-1`,children:[(0,J.jsx)(o,{className:`w-3.5 h-3.5`}),`Spawn`]})})]}),b.length===0?(0,J.jsx)(`div`,{className:`text-center py-16 text-muted-foreground text-sm`,children:`No agents match the current filters.`}):(0,J.jsx)(`div`,{className:`grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 gap-3`,children:b.map(e=>(0,J.jsx)(Qe,{agent:e,parentAgent:e.spawnedBy?f[e.spawnedBy]??null:null,childAgents:he(y.get(e.id)??[])},e.id))})]})}export{$e as AgentsView};
2
+ //# sourceMappingURL=agents-B09rJRik.js.map