@sleep2agi/agent-network-dashboard 0.4.6-preview.9 → 0.4.6
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.
- package/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +1 -0
- package/.next/build-manifest.json +3 -3
- package/.next/diagnostics/route-bundle-stats.json +69 -55
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/prerender-manifest.json +3 -3
- package/.next/routes-manifest.json +6 -0
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +2 -2
- package/.next/server/app/_not-found.rsc +12 -12
- package/.next/server/app/_not-found.segments/_full.segment.rsc +12 -12
- package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/server/app/_not-found.segments/_index.segment.rsc +7 -7
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
- package/.next/server/app/admin.html +2 -2
- package/.next/server/app/admin.rsc +14 -14
- package/.next/server/app/admin.segments/_full.segment.rsc +14 -14
- package/.next/server/app/admin.segments/_head.segment.rsc +4 -4
- package/.next/server/app/admin.segments/_index.segment.rsc +7 -7
- package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/admin.segments/admin.segment.rsc +3 -3
- package/.next/server/app/api/hub/servers/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/hub/servers/route/build-manifest.json +9 -0
- package/.next/server/app/api/hub/servers/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/hub/servers/route.js +7 -0
- package/.next/server/app/api/hub/servers/route.js.map +5 -0
- package/.next/server/app/api/hub/servers/route.js.nft.json +1 -0
- package/.next/server/app/api/hub/servers/route_client-reference-manifest.js +3 -0
- package/.next/server/app/index.html +2 -2
- package/.next/server/app/index.rsc +14 -14
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/index.segments/_full.segment.rsc +14 -14
- package/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/server/app/index.segments/_index.segment.rsc +7 -7
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login.html +2 -2
- package/.next/server/app/login.rsc +14 -14
- package/.next/server/app/login.segments/_full.segment.rsc +14 -14
- package/.next/server/app/login.segments/_head.segment.rsc +4 -4
- package/.next/server/app/login.segments/_index.segment.rsc +7 -7
- package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/login.segments/login.segment.rsc +3 -3
- package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/logs.html +2 -2
- package/.next/server/app/logs.rsc +14 -14
- package/.next/server/app/logs.segments/_full.segment.rsc +14 -14
- package/.next/server/app/logs.segments/_head.segment.rsc +4 -4
- package/.next/server/app/logs.segments/_index.segment.rsc +7 -7
- package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/logs.segments/logs.segment.rsc +3 -3
- package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
- package/.next/server/app/messages.html +2 -2
- package/.next/server/app/messages.rsc +14 -14
- package/.next/server/app/messages.segments/_full.segment.rsc +14 -14
- package/.next/server/app/messages.segments/_head.segment.rsc +4 -4
- package/.next/server/app/messages.segments/_index.segment.rsc +7 -7
- package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/messages.segments/messages.segment.rsc +3 -3
- package/.next/server/app/node/page_client-reference-manifest.js +1 -1
- package/.next/server/app/node.html +2 -2
- package/.next/server/app/node.rsc +14 -14
- package/.next/server/app/node.segments/_full.segment.rsc +14 -14
- package/.next/server/app/node.segments/_head.segment.rsc +4 -4
- package/.next/server/app/node.segments/_index.segment.rsc +7 -7
- package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/node.segments/node.segment.rsc +3 -3
- package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
- package/.next/server/app/nodes.html +2 -2
- package/.next/server/app/nodes.rsc +14 -14
- package/.next/server/app/nodes.segments/_full.segment.rsc +14 -14
- package/.next/server/app/nodes.segments/_head.segment.rsc +4 -4
- package/.next/server/app/nodes.segments/_index.segment.rsc +7 -7
- package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/nodes.segments/nodes.segment.rsc +3 -3
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs.html +2 -2
- package/.next/server/app/server-logs.rsc +14 -14
- package/.next/server/app/server-logs.segments/_full.segment.rsc +14 -14
- package/.next/server/app/server-logs.segments/_head.segment.rsc +4 -4
- package/.next/server/app/server-logs.segments/_index.segment.rsc +7 -7
- package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/server-logs.segments/server-logs.segment.rsc +3 -3
- package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/networks.html +2 -2
- package/.next/server/app/settings/networks.rsc +14 -14
- package/.next/server/app/settings/networks.segments/_full.segment.rsc +14 -14
- package/.next/server/app/settings/networks.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings/networks.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +3 -3
- package/.next/server/app/settings/networks.segments/settings.segment.rsc +3 -3
- package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens.html +2 -2
- package/.next/server/app/settings/tokens.rsc +14 -14
- package/.next/server/app/settings/tokens.segments/_full.segment.rsc +14 -14
- package/.next/server/app/settings/tokens.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings/tokens.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +3 -3
- package/.next/server/app/settings/tokens.segments/settings.segment.rsc +3 -3
- package/.next/server/app/settings.html +2 -2
- package/.next/server/app/settings.rsc +14 -14
- package/.next/server/app/settings.segments/_full.segment.rsc +14 -14
- package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
- package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks.html +2 -2
- package/.next/server/app/tasks.rsc +14 -14
- package/.next/server/app/tasks.segments/_full.segment.rsc +14 -14
- package/.next/server/app/tasks.segments/_head.segment.rsc +4 -4
- package/.next/server/app/tasks.segments/_index.segment.rsc +7 -7
- package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/tasks.segments/tasks.segment.rsc +3 -3
- package/.next/server/app-paths-manifest.json +1 -0
- package/.next/server/chunks/0ykm__next-internal_server_app_api_hub_servers_route_actions_08-m-cs.js +3 -0
- package/.next/server/chunks/0ykm__next-internal_server_app_api_hub_servers_route_actions_08-m-cs.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0tx8s8i._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0tx8s8i._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__03b.f76._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__03b.f76._.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0fhoq8i._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0fhoq8i._.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0nw~zhp._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0nw~zhp._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js +2 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_057q.ne._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_057q.ne._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0_d45-d._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0_d45-d._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0i3759l._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0i3759l._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0xgney8._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0xgney8._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_10hjgv4._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_10hjgv4._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_1153xeb._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_1153xeb._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_12l4oto._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_12l4oto._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js.map +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/pages/404.html +2 -2
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/0-mpa_947ipeq.js +1 -0
- package/.next/static/chunks/01lmbsd37fybu.js +1 -0
- package/.next/static/chunks/03o.h6kvmw4l_.js +1 -0
- package/.next/static/chunks/03~~oirxz7~vc.js +1 -0
- package/.next/static/chunks/05uk96gc~9mni.js +1 -0
- package/.next/static/chunks/088ouqy7tekty.js +2 -0
- package/.next/static/chunks/08kf-.bgs10ze.js +1 -0
- package/.next/static/chunks/0glmrdj9112tc.js +7 -0
- package/.next/static/chunks/0hyl7mdapsz38.js +1 -0
- package/.next/static/chunks/0mqwn-l7wtcdo.js +7 -0
- package/.next/static/chunks/0rxrez_cjn.eh.js +1 -0
- package/.next/static/chunks/0tvn2l1pc.h65.js +1 -0
- package/.next/static/chunks/0x8x.29hkju5a.js +1 -0
- package/.next/static/chunks/127kw7~wsnyu7.css +2 -0
- package/.next/static/chunks/16yfxp9ak2gdm.js +1 -0
- package/.next/static/chunks/174re5ar~kxne.js +1 -0
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/.next/types/routes.d.ts +2 -1
- package/.next/types/validator.ts +9 -0
- package/app/api/hub/servers/route.ts +39 -0
- package/app/components/AppShell.tsx +2 -0
- package/app/components/ChatPopover.tsx +38 -2
- package/app/components/HelpOverlay.tsx +18 -0
- package/app/components/ServersDrawer.tsx +206 -0
- package/app/components/TopoGraph.tsx +833 -138
- package/app/components/utils.ts +8 -7
- package/app/lib/time.ts +36 -0
- package/package.json +1 -1
- package/scripts/help-overlay-topo-test.mjs +44 -0
- package/scripts/servers-drawer-live-test.mjs +96 -0
- package/scripts/topo-active-links-chip-test.mjs +73 -0
- package/scripts/topo-arrow-tier-test.mjs +61 -0
- package/scripts/topo-auto-fit-test.mjs +73 -0
- package/scripts/topo-chat-focus-ring-test.mjs +77 -0
- package/scripts/topo-click-ripple-test.mjs +66 -0
- package/scripts/topo-cwd-tooltip-test.mjs +64 -0
- package/scripts/topo-dblclick-reset-test.mjs +74 -0
- package/scripts/topo-edge-hover-test.mjs +85 -0
- package/scripts/topo-edge-tooltip-test.mjs +70 -0
- package/scripts/topo-fit-key-test.mjs +106 -0
- package/scripts/topo-freshness-chip-test.mjs +74 -0
- package/scripts/topo-group-count-test.mjs +63 -0
- package/scripts/topo-group-hover-test.mjs +82 -0
- package/scripts/topo-hub-title-test.mjs +88 -0
- package/scripts/topo-label-lift-test.mjs +115 -0
- package/scripts/topo-label-scale-test.mjs +78 -0
- package/scripts/topo-lastseen-tooltip-test.mjs +59 -0
- package/scripts/topo-layout-key-test.mjs +91 -0
- package/scripts/topo-minimap-test.mjs +68 -0
- package/scripts/topo-mobile-chips-test.mjs +103 -0
- package/scripts/topo-offline-dim-test.mjs +70 -0
- package/scripts/topo-overlap-test.mjs +32 -5
- package/scripts/topo-pan-cursor-test.mjs +62 -0
- package/scripts/topo-popover-meta-test.mjs +78 -0
- package/scripts/topo-pressure-bar-test.mjs +69 -0
- package/scripts/topo-pulse-rate-test.mjs +71 -0
- package/scripts/topo-recent-signal-empty-test.mjs +63 -0
- package/scripts/topo-reduced-motion-test.mjs +77 -0
- package/scripts/topo-tz-ghost-test.mjs +69 -0
- package/scripts/topo-wheel-zoom-test.mjs +79 -0
- package/scripts/topo-zoom-keys-test.mjs +89 -0
- package/.next/static/chunks/0-7iowzu4.798.js +0 -1
- package/.next/static/chunks/02t5jr4shh.hy.js +0 -1
- package/.next/static/chunks/0_qfg5s5uzs7..js +0 -7
- package/.next/static/chunks/0_rmxom9~1lmk.css +0 -2
- package/.next/static/chunks/0cj5qr_a8dzky.js +0 -7
- package/.next/static/chunks/0elalb9n_.~di.js +0 -1
- package/.next/static/chunks/0j_q__o8p6g83.js +0 -1
- package/.next/static/chunks/0jl6_w50zh4l5.js +0 -1
- package/.next/static/chunks/0kgak.tfh2-~i.js +0 -1
- package/.next/static/chunks/0r4q73.-1bkyl.js +0 -1
- package/.next/static/chunks/0r_c8eccg3z2o.js +0 -1
- package/.next/static/chunks/10oi7l-tycgl9.js +0 -1
- package/.next/static/chunks/11uk1izuv3~0t.js +0 -1
- package/.next/static/chunks/131.zrqhdbu5x.js +0 -1
- package/.next/static/chunks/165lqf5.z.n10.js +0 -1
- /package/.next/static/{T0hK2WE0kVtyFouPsSpos → 23MxP0RBVA4BaOJ_HMYmM}/_buildManifest.js +0 -0
- /package/.next/static/{T0hK2WE0kVtyFouPsSpos → 23MxP0RBVA4BaOJ_HMYmM}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{T0hK2WE0kVtyFouPsSpos → 23MxP0RBVA4BaOJ_HMYmM}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../agent-network-dashboard/node_modules/styled-jsx/dist/index/index.js","../../../../../agent-network-dashboard/node_modules/styled-jsx/style.js","../../../../../agent-network-dashboard/app/page.tsx","../../../../../agent-network-dashboard/app/components/StatsBar.tsx","../../../../../agent-network-dashboard/app/components/BroadcastBar.tsx","../../../../../agent-network-dashboard/app/components/TopoGraph.tsx","../../../../../agent-network-dashboard/app/components/ChatPopover.tsx","../../../../../agent-network-dashboard/app/lib/vendorIdentity.ts","../../../../../agent-network-dashboard/app/components/AgentCard.tsx","../../../../../agent-network-dashboard/app/components/InboxPanel.tsx","../../../../../agent-network-dashboard/app/components/LoadingSkeleton.tsx","../../../../../agent-network-dashboard/app/components/UserBar.tsx","../../../../../agent-network-dashboard/app/components/CommandCenter.tsx","../../../../../agent-network-dashboard/app/components/DispatchPanel.tsx"],"sourcesContent":["require('client-only');\nvar React = require('react');\n\nfunction _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }\n\nvar React__default = /*#__PURE__*/_interopDefaultLegacy(React);\n\n/*\nBased on Glamor's sheet\nhttps://github.com/threepointone/glamor/blob/667b480d31b3721a905021b26e1290ce92ca2879/src/sheet.js\n*/ function _defineProperties(target, props) {\n for(var i = 0; i < props.length; i++){\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n}\nfunction _createClass(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n return Constructor;\n}\nvar isProd = typeof process !== \"undefined\" && process.env && process.env.NODE_ENV === \"production\";\nvar isString = function(o) {\n return Object.prototype.toString.call(o) === \"[object String]\";\n};\nvar StyleSheet = /*#__PURE__*/ function() {\n function StyleSheet(param) {\n var ref = param === void 0 ? {} : param, _name = ref.name, name = _name === void 0 ? \"stylesheet\" : _name, _optimizeForSpeed = ref.optimizeForSpeed, optimizeForSpeed = _optimizeForSpeed === void 0 ? isProd : _optimizeForSpeed;\n invariant$1(isString(name), \"`name` must be a string\");\n this._name = name;\n this._deletedRulePlaceholder = \"#\" + name + \"-deleted-rule____{}\";\n invariant$1(typeof optimizeForSpeed === \"boolean\", \"`optimizeForSpeed` must be a boolean\");\n this._optimizeForSpeed = optimizeForSpeed;\n this._serverSheet = undefined;\n this._tags = [];\n this._injected = false;\n this._rulesCount = 0;\n var node = typeof window !== \"undefined\" && document.querySelector('meta[property=\"csp-nonce\"]');\n this._nonce = node ? node.getAttribute(\"content\") : null;\n }\n var _proto = StyleSheet.prototype;\n _proto.setOptimizeForSpeed = function setOptimizeForSpeed(bool) {\n invariant$1(typeof bool === \"boolean\", \"`setOptimizeForSpeed` accepts a boolean\");\n invariant$1(this._rulesCount === 0, \"optimizeForSpeed cannot be when rules have already been inserted\");\n this.flush();\n this._optimizeForSpeed = bool;\n this.inject();\n };\n _proto.isOptimizeForSpeed = function isOptimizeForSpeed() {\n return this._optimizeForSpeed;\n };\n _proto.inject = function inject() {\n var _this = this;\n invariant$1(!this._injected, \"sheet already injected\");\n this._injected = true;\n if (typeof window !== \"undefined\" && this._optimizeForSpeed) {\n this._tags[0] = this.makeStyleTag(this._name);\n this._optimizeForSpeed = \"insertRule\" in this.getSheet();\n if (!this._optimizeForSpeed) {\n if (!isProd) {\n console.warn(\"StyleSheet: optimizeForSpeed mode not supported falling back to standard mode.\");\n }\n this.flush();\n this._injected = true;\n }\n return;\n }\n this._serverSheet = {\n cssRules: [],\n insertRule: function(rule, index) {\n if (typeof index === \"number\") {\n _this._serverSheet.cssRules[index] = {\n cssText: rule\n };\n } else {\n _this._serverSheet.cssRules.push({\n cssText: rule\n });\n }\n return index;\n },\n deleteRule: function(index) {\n _this._serverSheet.cssRules[index] = null;\n }\n };\n };\n _proto.getSheetForTag = function getSheetForTag(tag) {\n if (tag.sheet) {\n return tag.sheet;\n }\n // this weirdness brought to you by firefox\n for(var i = 0; i < document.styleSheets.length; i++){\n if (document.styleSheets[i].ownerNode === tag) {\n return document.styleSheets[i];\n }\n }\n };\n _proto.getSheet = function getSheet() {\n return this.getSheetForTag(this._tags[this._tags.length - 1]);\n };\n _proto.insertRule = function insertRule(rule, index) {\n invariant$1(isString(rule), \"`insertRule` accepts only strings\");\n if (typeof window === \"undefined\") {\n if (typeof index !== \"number\") {\n index = this._serverSheet.cssRules.length;\n }\n this._serverSheet.insertRule(rule, index);\n return this._rulesCount++;\n }\n if (this._optimizeForSpeed) {\n var sheet = this.getSheet();\n if (typeof index !== \"number\") {\n index = sheet.cssRules.length;\n }\n // this weirdness for perf, and chrome's weird bug\n // https://stackoverflow.com/questions/20007992/chrome-suddenly-stopped-accepting-insertrule\n try {\n sheet.insertRule(rule, index);\n } catch (error) {\n if (!isProd) {\n console.warn(\"StyleSheet: illegal rule: \\n\\n\" + rule + \"\\n\\nSee https://stackoverflow.com/q/20007992 for more info\");\n }\n return -1;\n }\n } else {\n var insertionPoint = this._tags[index];\n this._tags.push(this.makeStyleTag(this._name, rule, insertionPoint));\n }\n return this._rulesCount++;\n };\n _proto.replaceRule = function replaceRule(index, rule) {\n if (this._optimizeForSpeed || typeof window === \"undefined\") {\n var sheet = typeof window !== \"undefined\" ? this.getSheet() : this._serverSheet;\n if (!rule.trim()) {\n rule = this._deletedRulePlaceholder;\n }\n if (!sheet.cssRules[index]) {\n // @TBD Should we throw an error?\n return index;\n }\n sheet.deleteRule(index);\n try {\n sheet.insertRule(rule, index);\n } catch (error) {\n if (!isProd) {\n console.warn(\"StyleSheet: illegal rule: \\n\\n\" + rule + \"\\n\\nSee https://stackoverflow.com/q/20007992 for more info\");\n }\n // In order to preserve the indices we insert a deleteRulePlaceholder\n sheet.insertRule(this._deletedRulePlaceholder, index);\n }\n } else {\n var tag = this._tags[index];\n invariant$1(tag, \"old rule at index `\" + index + \"` not found\");\n tag.textContent = rule;\n }\n return index;\n };\n _proto.deleteRule = function deleteRule(index) {\n if (typeof window === \"undefined\") {\n this._serverSheet.deleteRule(index);\n return;\n }\n if (this._optimizeForSpeed) {\n this.replaceRule(index, \"\");\n } else {\n var tag = this._tags[index];\n invariant$1(tag, \"rule at index `\" + index + \"` not found\");\n tag.parentNode.removeChild(tag);\n this._tags[index] = null;\n }\n };\n _proto.flush = function flush() {\n this._injected = false;\n this._rulesCount = 0;\n if (typeof window !== \"undefined\") {\n this._tags.forEach(function(tag) {\n return tag && tag.parentNode.removeChild(tag);\n });\n this._tags = [];\n } else {\n // simpler on server\n this._serverSheet.cssRules = [];\n }\n };\n _proto.cssRules = function cssRules() {\n var _this = this;\n if (typeof window === \"undefined\") {\n return this._serverSheet.cssRules;\n }\n return this._tags.reduce(function(rules, tag) {\n if (tag) {\n rules = rules.concat(Array.prototype.map.call(_this.getSheetForTag(tag).cssRules, function(rule) {\n return rule.cssText === _this._deletedRulePlaceholder ? null : rule;\n }));\n } else {\n rules.push(null);\n }\n return rules;\n }, []);\n };\n _proto.makeStyleTag = function makeStyleTag(name, cssString, relativeToTag) {\n if (cssString) {\n invariant$1(isString(cssString), \"makeStyleTag accepts only strings as second parameter\");\n }\n var tag = document.createElement(\"style\");\n if (this._nonce) tag.setAttribute(\"nonce\", this._nonce);\n tag.type = \"text/css\";\n tag.setAttribute(\"data-\" + name, \"\");\n if (cssString) {\n tag.appendChild(document.createTextNode(cssString));\n }\n var head = document.head || document.getElementsByTagName(\"head\")[0];\n if (relativeToTag) {\n head.insertBefore(tag, relativeToTag);\n } else {\n head.appendChild(tag);\n }\n return tag;\n };\n _createClass(StyleSheet, [\n {\n key: \"length\",\n get: function get() {\n return this._rulesCount;\n }\n }\n ]);\n return StyleSheet;\n}();\nfunction invariant$1(condition, message) {\n if (!condition) {\n throw new Error(\"StyleSheet: \" + message + \".\");\n }\n}\n\nfunction hash(str) {\n var _$hash = 5381, i = str.length;\n while(i){\n _$hash = _$hash * 33 ^ str.charCodeAt(--i);\n }\n /* JavaScript does bitwise operations (like XOR, above) on 32-bit signed\n * integers. Since we want the results to be always positive, convert the\n * signed int to an unsigned by doing an unsigned bitshift. */ return _$hash >>> 0;\n}\nvar stringHash = hash;\n\nvar sanitize = function(rule) {\n return rule.replace(/\\/style/gi, \"\\\\/style\");\n};\nvar cache = {};\n/**\n * computeId\n *\n * Compute and memoize a jsx id from a basedId and optionally props.\n */ function computeId(baseId, props) {\n if (!props) {\n return \"jsx-\" + baseId;\n }\n var propsToString = String(props);\n var key = baseId + propsToString;\n if (!cache[key]) {\n cache[key] = \"jsx-\" + stringHash(baseId + \"-\" + propsToString);\n }\n return cache[key];\n}\n/**\n * computeSelector\n *\n * Compute and memoize dynamic selectors.\n */ function computeSelector(id, css) {\n var selectoPlaceholderRegexp = /__jsx-style-dynamic-selector/g;\n // Sanitize SSR-ed CSS.\n // Client side code doesn't need to be sanitized since we use\n // document.createTextNode (dev) and the CSSOM api sheet.insertRule (prod).\n if (typeof window === \"undefined\") {\n css = sanitize(css);\n }\n var idcss = id + css;\n if (!cache[idcss]) {\n cache[idcss] = css.replace(selectoPlaceholderRegexp, id);\n }\n return cache[idcss];\n}\n\nfunction mapRulesToStyle(cssRules, options) {\n if (options === void 0) options = {};\n return cssRules.map(function(args) {\n var id = args[0];\n var css = args[1];\n return /*#__PURE__*/ React__default[\"default\"].createElement(\"style\", {\n id: \"__\" + id,\n // Avoid warnings upon render with a key\n key: \"__\" + id,\n nonce: options.nonce ? options.nonce : undefined,\n dangerouslySetInnerHTML: {\n __html: css\n }\n });\n });\n}\nvar StyleSheetRegistry = /*#__PURE__*/ function() {\n function StyleSheetRegistry(param) {\n var ref = param === void 0 ? {} : param, _styleSheet = ref.styleSheet, styleSheet = _styleSheet === void 0 ? null : _styleSheet, _optimizeForSpeed = ref.optimizeForSpeed, optimizeForSpeed = _optimizeForSpeed === void 0 ? false : _optimizeForSpeed;\n this._sheet = styleSheet || new StyleSheet({\n name: \"styled-jsx\",\n optimizeForSpeed: optimizeForSpeed\n });\n this._sheet.inject();\n if (styleSheet && typeof optimizeForSpeed === \"boolean\") {\n this._sheet.setOptimizeForSpeed(optimizeForSpeed);\n this._optimizeForSpeed = this._sheet.isOptimizeForSpeed();\n }\n this._fromServer = undefined;\n this._indices = {};\n this._instancesCounts = {};\n }\n var _proto = StyleSheetRegistry.prototype;\n _proto.add = function add(props) {\n var _this = this;\n if (undefined === this._optimizeForSpeed) {\n this._optimizeForSpeed = Array.isArray(props.children);\n this._sheet.setOptimizeForSpeed(this._optimizeForSpeed);\n this._optimizeForSpeed = this._sheet.isOptimizeForSpeed();\n }\n if (typeof window !== \"undefined\" && !this._fromServer) {\n this._fromServer = this.selectFromServer();\n this._instancesCounts = Object.keys(this._fromServer).reduce(function(acc, tagName) {\n acc[tagName] = 0;\n return acc;\n }, {});\n }\n var ref = this.getIdAndRules(props), styleId = ref.styleId, rules = ref.rules;\n // Deduping: just increase the instances count.\n if (styleId in this._instancesCounts) {\n this._instancesCounts[styleId] += 1;\n return;\n }\n var indices = rules.map(function(rule) {\n return _this._sheet.insertRule(rule);\n })// Filter out invalid rules\n .filter(function(index) {\n return index !== -1;\n });\n this._indices[styleId] = indices;\n this._instancesCounts[styleId] = 1;\n };\n _proto.remove = function remove(props) {\n var _this = this;\n var styleId = this.getIdAndRules(props).styleId;\n invariant(styleId in this._instancesCounts, \"styleId: `\" + styleId + \"` not found\");\n this._instancesCounts[styleId] -= 1;\n if (this._instancesCounts[styleId] < 1) {\n var tagFromServer = this._fromServer && this._fromServer[styleId];\n if (tagFromServer) {\n tagFromServer.parentNode.removeChild(tagFromServer);\n delete this._fromServer[styleId];\n } else {\n this._indices[styleId].forEach(function(index) {\n return _this._sheet.deleteRule(index);\n });\n delete this._indices[styleId];\n }\n delete this._instancesCounts[styleId];\n }\n };\n _proto.update = function update(props, nextProps) {\n this.add(nextProps);\n this.remove(props);\n };\n _proto.flush = function flush() {\n this._sheet.flush();\n this._sheet.inject();\n this._fromServer = undefined;\n this._indices = {};\n this._instancesCounts = {};\n };\n _proto.cssRules = function cssRules() {\n var _this = this;\n var fromServer = this._fromServer ? Object.keys(this._fromServer).map(function(styleId) {\n return [\n styleId,\n _this._fromServer[styleId]\n ];\n }) : [];\n var cssRules = this._sheet.cssRules();\n return fromServer.concat(Object.keys(this._indices).map(function(styleId) {\n return [\n styleId,\n _this._indices[styleId].map(function(index) {\n return cssRules[index].cssText;\n }).join(_this._optimizeForSpeed ? \"\" : \"\\n\")\n ];\n })// filter out empty rules\n .filter(function(rule) {\n return Boolean(rule[1]);\n }));\n };\n _proto.styles = function styles(options) {\n return mapRulesToStyle(this.cssRules(), options);\n };\n _proto.getIdAndRules = function getIdAndRules(props) {\n var css = props.children, dynamic = props.dynamic, id = props.id;\n if (dynamic) {\n var styleId = computeId(id, dynamic);\n return {\n styleId: styleId,\n rules: Array.isArray(css) ? css.map(function(rule) {\n return computeSelector(styleId, rule);\n }) : [\n computeSelector(styleId, css)\n ]\n };\n }\n return {\n styleId: computeId(id),\n rules: Array.isArray(css) ? css : [\n css\n ]\n };\n };\n /**\n * selectFromServer\n *\n * Collects style tags from the document with id __jsx-XXX\n */ _proto.selectFromServer = function selectFromServer() {\n var elements = Array.prototype.slice.call(document.querySelectorAll('[id^=\"__jsx-\"]'));\n return elements.reduce(function(acc, element) {\n var id = element.id.slice(2);\n acc[id] = element;\n return acc;\n }, {});\n };\n return StyleSheetRegistry;\n}();\nfunction invariant(condition, message) {\n if (!condition) {\n throw new Error(\"StyleSheetRegistry: \" + message + \".\");\n }\n}\nvar StyleSheetContext = /*#__PURE__*/ React.createContext(null);\nStyleSheetContext.displayName = \"StyleSheetContext\";\nfunction createStyleRegistry() {\n return new StyleSheetRegistry();\n}\nfunction StyleRegistry(param) {\n var configuredRegistry = param.registry, children = param.children;\n var rootRegistry = React.useContext(StyleSheetContext);\n var ref = React.useState(function() {\n return rootRegistry || configuredRegistry || createStyleRegistry();\n }), registry = ref[0];\n return /*#__PURE__*/ React__default[\"default\"].createElement(StyleSheetContext.Provider, {\n value: registry\n }, children);\n}\nfunction useStyleRegistry() {\n return React.useContext(StyleSheetContext);\n}\n\n// Opt-into the new `useInsertionEffect` API in React 18, fallback to `useLayoutEffect`.\n// https://github.com/reactwg/react-18/discussions/110\nvar useInsertionEffect = React__default[\"default\"].useInsertionEffect || React__default[\"default\"].useLayoutEffect;\nvar defaultRegistry = typeof window !== \"undefined\" ? createStyleRegistry() : undefined;\nfunction JSXStyle(props) {\n var registry = defaultRegistry ? defaultRegistry : useStyleRegistry();\n // If `registry` does not exist, we do nothing here.\n if (!registry) {\n return null;\n }\n if (typeof window === \"undefined\") {\n registry.add(props);\n return null;\n }\n useInsertionEffect(function() {\n registry.add(props);\n return function() {\n registry.remove(props);\n };\n // props.children can be string[], will be striped since id is identical\n }, [\n props.id,\n String(props.dynamic)\n ]);\n return null;\n}\nJSXStyle.dynamic = function(info) {\n return info.map(function(tagInfo) {\n var baseId = tagInfo[0];\n var props = tagInfo[1];\n return computeId(baseId, props);\n }).join(\" \");\n};\n\nexports.StyleRegistry = StyleRegistry;\nexports.createStyleRegistry = createStyleRegistry;\nexports.style = JSXStyle;\nexports.useStyleRegistry = useStyleRegistry;\n","module.exports = require('./dist/index').style\n","'use client';\n\nimport { useEffect, useState } from 'react';\nimport Link from 'next/link';\nimport { formatUptime, previewContent } from './components/utils';\nimport { StatsBar } from './components/StatsBar';\nimport { BroadcastBar } from './components/BroadcastBar';\nimport { TopoGraph } from './components/TopoGraph';\nimport { AgentCard } from './components/AgentCard';\nimport { InboxPanel } from './components/InboxPanel';\nimport { LoadingSkeleton } from './components/LoadingSkeleton';\nimport { NodesEmptyState as EmptyState } from './components/EmptyState';\nimport { AliasAvatar } from './components/AliasAvatar';\nimport { STATUS_DOT_HEX, STATUS_CHIP_CLASS } from './lib/status';\nimport { UserBar } from './components/UserBar';\nimport { CommandCenter, useCommandCenter } from './components/CommandCenter';\nimport { DispatchPanel } from './components/DispatchPanel';\nimport { useSessions, useHealth, useAnetConfig, useTasks, useStats } from './lib/hooks';\nimport { useSSE } from './lib/useSSE';\nimport { InboxMessage } from './components/types';\nimport { useSWRConfig } from 'swr';\n\nexport default function Dashboard() {\n // Auto-upgrade: if no V3 auth in session, force re-login to get user token\n useEffect(() => {\n const hasV3 = sessionStorage.getItem('anet_v3_auth');\n if (!hasV3) {\n // Try silent re-auth: logout old cookie + redirect to login\n fetch('/api/auth/logout', { method: 'POST' }).catch(() => {});\n window.location.assign('/login');\n }\n }, []);\n\n const { sessions, hint: sessHint, error: sessError, isLoading } = useSessions();\n const { health } = useHealth();\n const { config: anetConfig } = useAnetConfig();\n const { tasks } = useTasks({ limit: '500' });\n const { stats } = useStats();\n const [showTopo, setShowTopo] = useState(typeof window !== 'undefined' && window.innerWidth >= 1024);\n const [showConfig, setShowConfig] = useState(false);\n const cmd = useCommandCenter();\n const [showDispatch, setShowDispatch] = useState(false);\n const [inbox, setInbox] = useState<InboxMessage[]>([]);\n const [agentFilter, setAgentFilter] = useState<'all' | 'working' | 'idle' | 'offline'>('all');\n // #84: last node.renamed event — passed to TopoGraph so an open chat\n // popover follows the rename instead of pointing at a dead alias. `ts`\n // makes the effect re-fire even when the same from/to repeats.\n const [renameSignal, setRenameSignal] = useState<{ from: string; to: string; ts: number } | null>(null);\n const { mutate } = useSWRConfig();\n\n // SSE: instant revalidation on CommHub events\n // Opt-out via NEXT_PUBLIC_DISABLE_SSE=1 — avoids HTTP/1.1 head-of-line blocking on navigation\n const sseEnabled = process.env.NEXT_PUBLIC_DISABLE_SSE !== '1';\n const { connected: sseConnected, supported: sseSupported } = useSSE({\n url: '/api/hub/events',\n enabled: sseEnabled,\n onEvent: (event) => {\n // #84 (RFC-010 §3.4): node.renamed — revalidate the session list so the\n // new alias propagates instantly (TopoGraph + node grid re-render, the\n // avatar hue recomputes as a pure fn of alias) instead of waiting for\n // the next 5s poll. The renamed node's history keeps the old alias\n // server-side, so the task list needs no revalidation here.\n if (event.type === 'node.renamed') {\n mutate('/api/hub/status');\n const d = event.data as { old_alias?: string; new_alias?: string } | undefined;\n if (d?.old_alias && d?.new_alias) {\n setRenameSignal({ from: d.old_alias, to: d.new_alias, ts: Date.now() });\n }\n return;\n }\n if (['new_task', 'new_message', 'new_reply', 'node_status_changed', 'broadcast'].includes(event.type)) {\n mutate('/api/hub/status');\n mutate((key: string) => typeof key === 'string' && key.startsWith('/api/hub/tasks'), undefined, { revalidate: true });\n }\n },\n });\n\n // Fetch inbox (not in SWR since it accumulates)\n useEffect(() => {\n const fetchInbox = () => {\n fetch('/api/hub/inbox').then(r => r.json()).then(data => {\n if (data.messages?.length) setInbox(prev => {\n const ids = new Set(prev.map(m => m.id));\n const newMsgs = data.messages.filter((m: { id: string }) => !ids.has(m.id));\n return [...newMsgs, ...prev].slice(0, 100);\n });\n }).catch(() => {});\n };\n fetchInbox();\n const interval = setInterval(fetchInbox, 10000);\n return () => clearInterval(interval);\n }, []);\n\n if (isLoading) return <LoadingSkeleton />;\n\n const sseSessions = health?.sse_sessions || {};\n // SSE keys are `network_id:alias` since v0.7+ (per-network scoping).\n // Fall back to alias-only for legacy hubs.\n const sseLookup = (s: { alias: string; network_id?: string }) =>\n (s.network_id ? sseSessions[`${s.network_id}:${s.alias}`] : undefined) ?? sseSessions[s.alias];\n // Online = status is not 'offline' (not just SSE-connected)\n const isOnline = (s: { alias: string; status: string; network_id?: string }) => s.status !== 'offline' || !!sseLookup(s);\n const online = sessions.filter(isOnline).length;\n const total = sessions.length;\n const working = sessions.filter(s => s.status === 'working').length;\n const uptime = health ? formatUptime(health.uptime) : '--';\n const version = health?.version || '--';\n const configHealthy = Boolean(anetConfig?.hub && anetConfig.tokenConfigured);\n const configSourceLabel =\n anetConfig?.source === 'file' ? 'Local config'\n : anetConfig?.source === 'runtime-env' ? 'Runtime env'\n : 'Config missing';\n\n // Task stats: prefer /api/stats, fallback to manual\n const taskStats: Record<string, number> = {};\n if (stats?.tasks?.by_status?.length) {\n for (const s of stats.tasks.by_status) {\n taskStats[s.status] = s.count;\n }\n } else {\n for (const t of tasks) {\n taskStats[t.status] = (taskStats[t.status] || 0) + 1;\n }\n }\n\n const sortedSessions = [...sessions].sort((a, b) => {\n const aOnline = isOnline(a) ? 1 : 0;\n const bOnline = isOnline(b) ? 1 : 0;\n if (aOnline !== bOnline) return bOnline - aOnline;\n const aWorking = a.status === 'working' ? 1 : 0;\n const bWorking = b.status === 'working' ? 1 : 0;\n return bWorking - aWorking;\n });\n\n /** Round 70: when the fleet is empty, the Overview reorders to lead with\n * the \"Spin up your first agent\" CTA and hides the Quick Navigation /\n * Nav rail / Broadcast bar that would otherwise occupy prime real estate\n * with zeros and dead-end links. Computed once, used as a gate below. */\n const fleetEmpty = sessions.length === 0 && !sessError;\n\n return (\n <div className=\"min-h-screen bg-[#0a0a1a] text-gray-100 p-4 sm:p-6 font-mono\">\n <div className=\"lg:ml-0 ml-10\">\n <StatsBar online={online} working={working} total={total} version={version} uptime={uptime} />\n </div>\n\n {/* Dispatch + User Bar — Dispatch hidden when fleet empty (nothing to\n dispatch to); UserBar still useful (account/sign-out menu). */}\n <div className=\"flex items-center gap-3 mb-4\">\n {!fleetEmpty && (\n <button onClick={() => setShowDispatch(true)}\n className=\"px-4 py-2 bg-gradient-to-r from-cyan-600 to-blue-600 hover:from-cyan-500 hover:to-blue-500 text-white text-sm font-medium rounded-xl shadow-lg shadow-cyan-500/10 transition-all active:scale-95 shrink-0\">\n ⚡ Dispatch\n </button>\n )}\n <div className=\"flex-1\"><UserBar /></div>\n </div>\n\n {/* anet config (collapsed by default) */}\n <section className=\"mb-6 rounded-lg border border-[#2a2a4a] bg-[#111128] px-4 py-3 shadow-lg shadow-black/20\">\n <button onClick={() => setShowConfig(!showConfig)} className=\"w-full flex items-center justify-between text-left\">\n <div className=\"flex items-center gap-2 text-xs\">\n <span className=\"uppercase text-gray-600\">Config</span>\n <span className={`w-2 h-2 rounded-full ${configHealthy ? 'bg-green-400' : 'bg-red-400'}`} />\n <span className=\"text-gray-500\">{configSourceLabel}</span>\n </div>\n <svg className={`w-4 h-4 text-gray-600 transition-transform ${showConfig ? 'rotate-180' : ''}`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </button>\n {showConfig && (\n <div className=\"mt-3 pt-3 border-t border-[#2a2a4a]\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"min-w-0\">\n <div className=\"text-gray-100 truncate text-sm\" title={anetConfig?.hub || undefined}>\n Hub: <span className={anetConfig?.hub ? 'text-cyan-300' : 'text-red-300'}>{anetConfig?.hub?.trim() || 'not configured'}</span>\n </div>\n </div>\n <div className=\"flex flex-wrap gap-2 text-xs\">\n <span className={`px-2.5 py-1 rounded-md border ${anetConfig?.tokenConfigured ? 'bg-blue-500/5 text-blue-300 border-blue-500/20' : 'bg-gray-500/5 text-gray-400 border-gray-500/20'}`}>\n Token: {anetConfig?.tokenPreview || 'not configured'}\n </span>\n </div>\n </div>\n {anetConfig?.error && <div className=\"mt-2 text-xs text-gray-600\">{anetConfig.error}</div>}\n </div>\n )}\n </section>\n\n {/* Task Status Stats */}\n {Object.keys(taskStats).length > 0 && (\n <section className=\"mb-6 rounded-lg border border-[#2a2a4a] bg-[#111128] px-4 py-3 shadow-lg shadow-black/20\">\n <div className=\"flex items-center justify-between mb-2\">\n <div className=\"text-xs uppercase text-gray-600\">Task Status</div>\n <Link href=\"/tasks\" prefetch={false} className=\"text-xs text-cyan-400 hover:text-cyan-300\">View all →</Link>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n {/* Round 69: order is \"hot first\" — active flow before terminal\n states — intentionally different from the lifecycle order on\n /tasks. Colors come from shared STATUS_CHIP_CLASS so a\n palette tweak in app/lib/status.ts updates here too.\n 'created' added in r69 (was missing — enum-coverage bug). */}\n {(['running', 'delivered', 'acked', 'replied', 'created', 'failed', 'cancelled', 'expired', 'closed'] as const)\n .filter((key) => taskStats[key])\n .map((key) => (\n <Link key={key} href={`/tasks?status=${key}`} prefetch={false} className={`px-2.5 py-1 rounded-md border text-xs ${STATUS_CHIP_CLASS[key]} hover:opacity-80 transition-opacity`}>\n {key}: {taskStats[key]}\n </Link>\n ))}\n </div>\n </section>\n )}\n\n {/* Quick Actions — split into two distinct intents:\n (1) Top: live stat cards (carry data, drill-in on click)\n (2) Bottom: pure nav rail (no number, icon + label)\n Round 24 — wrap both in a labelled block so the rhythm reads as\n \"here are the main jumps\" instead of two disconnected strips.\n Round 70 — entire Quick Nav + Nav rail + Broadcast + Recent\n Activity block is hidden when the fleet is empty so the\n onboarding CTA gets the page above the fold. */}\n {!fleetEmpty && <>\n <div className=\"text-[10px] uppercase tracking-[0.12em] text-gray-600 mb-2\">Quick navigation</div>\n <section className=\"mb-3 grid grid-cols-3 gap-2 sm:gap-3\">\n {(() => {\n // Build breakdown popover content per card. Pure data — pure CSS\n // popover (no JS state) wires the hover-show transition below.\n const idleCount = sessions.filter(s => isOnline(s) && s.status !== 'working').length;\n const offlineCount = total - online;\n const orderedStatuses = ['running', 'replied', 'failed', 'cancelled', 'expired', 'closed', 'created', 'delivered', 'acked'];\n const failedRecent = tasks.filter((t: { status: string }) => t.status === 'failed').length;\n\n const cards = [\n {\n href: '/nodes', label: 'Nodes',\n value: `${online}/${total}`,\n sub: `${total > 0 ? Math.round((online / total) * 100) : 0}% online`,\n color: 'text-green-400 border-green-500/20',\n popover: total === 0 ? null : [\n { k: 'working', v: working, dot: '', color: '#4ade80' },\n { k: 'idle', v: idleCount, dot: '', color: '#22d3ee' },\n { k: 'offline', v: offlineCount, dot: '', color: '#9ca3af' },\n ],\n },\n {\n href: '/tasks', label: 'Tasks',\n value: String(Object.values(taskStats).reduce((a, b) => a + b, 0) || 0),\n sub: 'all-time',\n color: 'text-cyan-400 border-cyan-500/20',\n popover: Object.keys(taskStats).length === 0 ? null\n : orderedStatuses\n .filter(s => taskStats[s])\n .map(s => {\n // Inline hex avoids Tailwind purging dynamic\n // `bg-${color}-400` class names.\n const hex = ({\n running: '#4ade80', replied: '#a78bfa', failed: '#f87171',\n cancelled: '#facc15', expired: '#fb923c', closed: '#9ca3af',\n created: '#9ca3af', delivered: '#60a5fa', acked: '#22d3ee',\n } as Record<string, string>)[s] || '#9ca3af';\n return { k: s, v: taskStats[s], dot: '', color: hex };\n }),\n },\n {\n href: '/tasks?status=failed', label: 'Failed',\n value: String(taskStats['failed'] || 0),\n sub: taskStats['failed'] ? 'needs review' : 'none',\n color: taskStats['failed'] ? 'text-red-400 border-red-500/25' : 'text-gray-500 border-gray-700/30',\n popover: !failedRecent ? [{ k: 'no failures yet', v: '', dot: '', color: '#4b5563' }]\n : [{ k: `${failedRecent} in current view`, v: '', dot: '', color: '#f87171' }],\n },\n ];\n\n return cards.map(a => (\n <Link\n key={a.href}\n href={a.href}\n prefetch={false}\n className={`anet-stat-link group relative rounded-xl border ${a.color} bg-[#111128] px-3 py-3 transition-all hover:-translate-y-px`}\n >\n <div className=\"flex items-baseline justify-between\">\n <div className={`text-xl font-semibold tabular-nums ${a.color.split(' ')[0]}`}>{a.value}</div>\n <div className=\"hidden sm:block text-[10px] text-gray-600 group-hover:text-gray-400 transition-colors\">View →</div>\n </div>\n <div className=\"text-[11px] text-gray-400 mt-0.5\">{a.label}</div>\n <div className=\"text-[10px] text-gray-600 mt-px\">{a.sub}</div>\n\n {/* Hover popover — CSS-only, restrained. Hidden on touch\n (no :hover) so mobile is unaffected. Positioned just\n below the card so it doesn't fight nav rail. */}\n {a.popover && a.popover.length > 0 && (\n <div className=\"anet-stat-popover hidden md:block pointer-events-none absolute left-2 right-2 top-full mt-1 z-20 rounded-lg border border-[#2a2a4a] bg-[#0d0d1a] shadow-lg shadow-black/30 px-3 py-2 opacity-0 translate-y-[-2px] group-hover:opacity-100 group-hover:translate-y-0 transition-all duration-150 delay-100\">\n <div className=\"text-[10px] text-gray-600 uppercase tracking-wider mb-1.5\">Breakdown</div>\n <ul className=\"space-y-1\">\n {a.popover.map(row => (\n <li key={row.k} className=\"flex items-center gap-2 text-[11px]\">\n <span\n className=\"inline-block w-1.5 h-1.5 rounded-full shrink-0\"\n style={{ backgroundColor: row.color }}\n aria-hidden\n />\n <span className=\"text-gray-400 capitalize\">{row.k}</span>\n {row.v !== '' && <span className=\"ml-auto text-gray-300 tabular-nums font-medium\">{row.v}</span>}\n </li>\n ))}\n </ul>\n </div>\n )}\n </Link>\n ));\n })()}\n </section>\n\n {/* Nav rail — pure navigation, icon + label, no data */}\n <section className=\"mb-6 grid grid-cols-3 gap-2 sm:gap-3\">\n {[\n { href: '/messages', label: 'Messages', icon: 'M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z' },\n { href: '/logs', label: 'Audit log', icon: 'M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z M14 2v6h6 M16 13H8 M16 17H8 M10 9H8' },\n { href: '/admin', label: 'Admin', icon: 'M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4z M6 21v-2a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v2' },\n ].map(a => (\n <Link key={a.href} href={a.href} prefetch={false}\n className=\"anet-nav-tile flex items-center justify-center gap-2 rounded-xl border border-[#2a2a4a] bg-[#111128] px-3 py-2.5 text-[12px] text-gray-400 hover:text-gray-200 transition-colors\">\n <svg className=\"w-4 h-4 shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d={a.icon} />\n </svg>\n <span>{a.label}</span>\n </Link>\n ))}\n </section>\n\n <BroadcastBar />\n\n {/* Recent Activity */}\n {tasks.length > 0 && (\n <section className=\"mb-6 bg-[#111128] border border-[#2a2a4a] rounded-xl p-4\">\n <div className=\"flex items-center justify-between mb-3\">\n <h2 className=\"text-sm font-semibold text-gray-300\">Recent Activity</h2>\n <Link href=\"/tasks\" className=\"text-xs text-cyan-400 hover:text-cyan-300\">All tasks →</Link>\n </div>\n <div className=\"space-y-2 max-h-40 overflow-y-auto\">\n {tasks.slice(0, 5).map((t: { task_id: string; from_name: string; to_name: string; status: string; content: string; created_at: string }) => (\n <div key={t.task_id} className=\"flex items-center gap-2 text-xs\">\n <span\n className=\"w-1.5 h-1.5 rounded-full shrink-0\"\n style={{ backgroundColor: STATUS_DOT_HEX[t.status] || '#6b7280' }}\n />\n {t.from_name && <AliasAvatar alias={t.from_name} size={14} />}\n <span className=\"text-gray-300 shrink-0 max-w-[20%] truncate\">{t.from_name || '?'}</span>\n <span className=\"text-gray-600\">→</span>\n {t.to_name && <AliasAvatar alias={t.to_name} size={14} />}\n <span className=\"text-gray-300 shrink-0 max-w-[20%] truncate\">{t.to_name || '?'}</span>\n <span className=\"text-gray-500 truncate flex-1\" title={t.content || ''}>{previewContent(t.content).slice(0, 60)}</span>\n <span className={`shrink-0 px-1.5 py-0.5 rounded text-[10px] border ${\n STATUS_CHIP_CLASS[t.status] || 'text-gray-500 border-gray-700/30'\n }`}>{t.status}</span>\n </div>\n ))}\n </div>\n </section>\n )}\n </>}\n\n {sessError && (\n <div className=\"bg-red-900/20 border border-red-800/40 text-red-300 px-4 py-3 rounded-lg mb-6 text-sm flex items-center justify-between\" role=\"alert\">\n <span>{String(sessError)}</span>\n <span className=\"text-gray-500 text-xs\">Check CommHub connection</span>\n </div>\n )}\n\n {sessions.length > 0 && (\n <div className=\"flex justify-center mb-4\">\n <button\n onClick={() => setShowTopo(!showTopo)}\n className=\"text-xs text-gray-500 hover:text-gray-300 border border-gray-700/50 px-4 py-1.5 rounded-lg transition-colors hover:border-gray-600 cursor-pointer\"\n >\n {showTopo ? 'Hide Topology' : 'Show Topology'}\n </button>\n </div>\n )}\n\n {/* Mobile hint when topo hidden */}\n {!showTopo && sessions.length > 0 && (\n <div className=\"lg:hidden text-center text-xs text-gray-600 mb-4\">\n Topology hidden on mobile for better readability\n </div>\n )}\n\n {showTopo && sessions.length > 0 && <TopoGraph sessions={sessions} sseSessions={sseSessions} renameSignal={renameSignal} />}\n\n {sessions.length === 0 && !sessError ? (\n <EmptyState\n hint={sessHint}\n taskHistoryCount={Object.values(taskStats).reduce((a, b) => a + b, 0)}\n />\n ) : (() => {\n const counts = {\n all: sortedSessions.length,\n working: sortedSessions.filter(s => isOnline(s) && s.status === 'working').length,\n idle: sortedSessions.filter(s => isOnline(s) && s.status !== 'working').length,\n offline: sortedSessions.filter(s => !isOnline(s)).length,\n };\n const filtered = sortedSessions.filter(s => {\n if (agentFilter === 'all') return true;\n if (agentFilter === 'offline') return !isOnline(s);\n if (agentFilter === 'working') return isOnline(s) && s.status === 'working';\n if (agentFilter === 'idle') return isOnline(s) && s.status !== 'working';\n return true;\n });\n // Filter chip color keyed to status (round 34): working=green, idle=cyan,\n // offline=gray, all=neutral. Inline hex dots avoid Tailwind v4 purge.\n const chips: { key: typeof agentFilter; label: string; dot?: string }[] = [\n { key: 'all', label: 'All' },\n { key: 'working', label: 'Working', dot: '#4ade80' },\n { key: 'idle', label: 'Idle', dot: '#22d3ee' },\n { key: 'offline', label: 'Offline', dot: '#6b7280' },\n ];\n return (\n <>\n <div className=\"mb-3 flex flex-wrap items-center gap-1\">\n {chips.map(c => (\n <button\n key={c.key}\n type=\"button\"\n onClick={() => setAgentFilter(c.key)}\n disabled={counts[c.key] === 0 && c.key !== 'all'}\n className={`flex items-center gap-1.5 rounded-md px-2.5 py-1 text-xs transition-colors disabled:opacity-30 disabled:cursor-not-allowed ${\n agentFilter === c.key\n ? 'bg-cyan-500/10 text-cyan-300 border border-cyan-500/30'\n : 'text-gray-500 hover:text-gray-200 hover:bg-[#1a1a2a] border border-transparent'\n }`}\n >\n {c.dot && <span aria-hidden className=\"inline-block w-1.5 h-1.5 rounded-full\" style={{ backgroundColor: c.dot }} />}\n <span>{c.label}</span>\n <span className={`text-[10px] tabular-nums ${agentFilter === c.key ? 'text-cyan-400' : 'text-gray-600'}`}>{counts[c.key]}</span>\n </button>\n ))}\n </div>\n {/* Round 48: previous breakpoints had `lg:grid-cols-2 xl:grid-cols-3`\n which kept lg (1024-1279px) at only 2 columns even though\n each AgentCard is fine ≥260px wide. With the sidebar (208px),\n main area at lg is ~816px so 3 cols at ~272px each fits.\n xl breakpoint auto-inherits lg=3 cols; 2xl bumps to 4. */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 gap-3 sm:gap-4\">\n {filtered.map(s => (\n <AgentCard key={s.alias} session={s} hasSse={isOnline(s)} sseCount={sseLookup(s) || 0} onChat={cmd.openTab} />\n ))}\n </div>\n {filtered.length === 0 && (\n <div className=\"mt-4 text-center text-xs text-gray-600\">\n No agents match \"{agentFilter}\" — <button onClick={() => setAgentFilter('all')} className=\"underline hover:text-gray-400\">Show all</button>\n </div>\n )}\n </>\n );\n })()}\n\n <InboxPanel messages={inbox} />\n\n {/* Round 111 (issue #82): dropped the license badge — \"trial (12d\n left)\" read like a paywall countdown on an open-source dashboard\n and Vincent flagged it as misleading more than once. The SSE /\n polling dot stays: it's a real connection-status indicator, not\n a sales surface. */}\n <div className=\"mt-8 text-center text-xs text-gray-600 flex items-center justify-center gap-2 flex-wrap\">\n {sseSupported && (\n <>\n <span className={`w-1.5 h-1.5 rounded-full ${sseConnected ? 'bg-green-400' : 'bg-gray-600'}`} />\n {sseConnected ? 'SSE live' : 'SWR polling'}\n </>\n )}\n </div>\n\n {/* Dispatch Panel */}\n {showDispatch && <DispatchPanel sessions={sessions} onClose={() => setShowDispatch(false)} />}\n\n {/* Command Center (multi-tab chat) */}\n {cmd.tabs.length > 0 && (\n <CommandCenter\n tabs={cmd.tabs}\n activeTab={cmd.activeTab}\n onOpenTab={cmd.openTab}\n onCloseTab={cmd.closeTab}\n onSetActive={cmd.setActiveTab}\n onClose={cmd.closeAll}\n />\n )}\n </div>\n );\n}\n","'use client';\n\ninterface StatsBarProps {\n online: number;\n working: number;\n total: number;\n version: string;\n uptime: string;\n}\n\nexport function StatsBar({ online, working, total, version, uptime }: StatsBarProps) {\n const onlinePercent = total > 0 ? Math.round((online / total) * 100) : 0;\n const fleetEmpty = total === 0;\n\n return (\n <div className={fleetEmpty ? 'mb-4' : 'mb-8'}>\n {/* Title row */}\n <div className=\"flex flex-wrap items-center gap-3 mb-4\">\n <h1 className=\"text-2xl font-bold text-white tracking-tight\">Agent Network</h1>\n <span className=\"text-xs text-gray-500\">\n CommHub {version} · {uptime}\n </span>\n </div>\n\n {fleetEmpty ? (\n /* Round 72: thin status strip replaces the 4-card grid when fleet\n is empty. Saves ~280px on mobile (CTA y=650 → ~370) and keeps\n the same data visible in a single inline row. */\n <div className=\"anet-stat-strip flex flex-wrap items-center gap-x-4 gap-y-1.5 text-xs text-gray-500 border-t border-b border-[#2a2a4a] py-2\">\n <span className=\"inline-flex items-center gap-1.5\">\n <span aria-hidden className=\"inline-block w-1.5 h-1.5 rounded-full bg-gray-600\" />\n <span className=\"text-gray-300 tabular-nums\">0</span> online\n </span>\n <span className=\"text-gray-700\">·</span>\n <span className=\"inline-flex items-center gap-1.5\">\n <span aria-hidden className=\"inline-block w-1.5 h-1.5 rounded-full bg-gray-600\" />\n <span className=\"text-gray-300 tabular-nums\">0</span> working\n </span>\n <span className=\"text-gray-700\">·</span>\n <span className=\"inline-flex items-center gap-1.5\">\n <span aria-hidden className=\"inline-block w-1.5 h-1.5 rounded-full bg-gray-600\" />\n <span className=\"text-gray-300 tabular-nums\">0</span> registered\n </span>\n </div>\n ) : (\n /* Populated state — full 4-card grid as before */\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-3\">\n <StatCard\n value={online}\n label=\"Online\"\n sub={`${onlinePercent}% of fleet`}\n color=\"text-green-400\"\n accent=\"from-green-500/20 to-green-500/0\"\n border=\"border-green-500/15\"\n />\n <StatCard\n value={working}\n label=\"Working\"\n sub={online > 0 ? `${Math.round((working / online) * 100)}% utilization` : '--'}\n color=\"text-cyan-400\"\n accent=\"from-cyan-500/20 to-cyan-500/0\"\n border=\"border-cyan-500/15\"\n />\n <StatCard\n value={total - online}\n label=\"Offline\"\n sub={total - online === 0 ? 'All systems go' : `${total - online} disconnected`}\n color=\"text-gray-400\"\n accent=\"from-gray-500/10 to-gray-500/0\"\n border=\"border-gray-500/15\"\n />\n <StatCard\n value={total}\n label=\"Total\"\n sub=\"Registered nodes\"\n color=\"text-white\"\n accent=\"from-blue-500/15 to-blue-500/0\"\n border=\"border-blue-500/15\"\n />\n </div>\n )}\n </div>\n );\n}\n\nfunction StatCard({ value, label, sub, color, accent, border }: {\n value: number; label: string; sub: string; color: string; accent: string; border: string;\n}) {\n // Extract the color family (green/cyan/gray/blue/white) from `color` prop\n // so the light-theme top-strip CSS can pick the right accent.\n const accentKey = color.replace('text-', '').split('-')[0];\n return (\n <div\n data-anet-stat-card={accentKey}\n className={`anet-stat-card relative overflow-hidden rounded-xl border ${border} bg-[#111128] px-4 py-3 transition-all`}\n >\n <div className={`absolute inset-0 bg-gradient-to-br ${accent} pointer-events-none`} />\n <div className=\"relative\">\n <div className={`text-3xl font-bold ${color} tabular-nums leading-tight`}>{value}</div>\n <div className=\"text-sm text-gray-300 mt-0.5\">{label}</div>\n <div className=\"text-xs text-gray-600 mt-1\">{sub}</div>\n </div>\n </div>\n );\n}\n","'use client';\n\nimport { useState } from 'react';\n\nexport function BroadcastBar() {\n const [broadcastMsg, setBroadcastMsg] = useState('');\n const [broadcasting, setBroadcasting] = useState(false);\n const [broadcastResult, setBroadcastResult] = useState('');\n\n const sendBroadcast = async () => {\n if (!broadcastMsg.trim()) return;\n setBroadcasting(true);\n setBroadcastResult('');\n try {\n const res = await fetch('/api/hub/broadcast', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ message: broadcastMsg }),\n });\n const data = await res.json();\n if (data.ok) {\n setBroadcastResult(`Broadcast sent to ${data.recipients} node(s)`);\n setBroadcastMsg('');\n } else {\n setBroadcastResult(`Failed: ${data.error || 'Send error'}`);\n }\n } catch (e: unknown) {\n setBroadcastResult(`Failed: ${e instanceof Error ? e.message : 'Send error'}`);\n }\n setBroadcasting(false);\n setTimeout(() => setBroadcastResult(''), 5000);\n };\n\n return (\n <div className=\"mb-6\">\n <div className=\"flex gap-2\">\n <input\n type=\"text\"\n value={broadcastMsg}\n onChange={e => setBroadcastMsg(e.target.value)}\n onKeyDown={e => e.key === 'Enter' && sendBroadcast()}\n placeholder=\"Broadcast message to all online agents...\"\n maxLength={500}\n aria-label=\"Broadcast message\"\n className=\"flex-1 bg-[#111128] border border-[#2a2a4a] rounded-lg px-4 py-2.5 text-sm text-white placeholder-gray-600 focus:border-blue-500/50 focus:ring-1 focus:ring-blue-500/20 focus:outline-none transition-colors\"\n />\n <button\n onClick={sendBroadcast}\n disabled={broadcasting || !broadcastMsg.trim()}\n aria-label=\"Send broadcast\"\n className=\"flex items-center gap-2 px-5 py-2.5 bg-blue-600 hover:bg-blue-500 disabled:bg-gray-800 disabled:text-gray-600 text-white text-sm rounded-lg transition-all font-medium cursor-pointer disabled:cursor-not-allowed\"\n >\n {broadcasting ? (\n <>\n <svg aria-hidden className=\"w-4 h-4 animate-spin\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"3\" opacity=\"0.25\" />\n <path d=\"M4 12a8 8 0 018-8\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" />\n </svg>\n <span>Sending…</span>\n </>\n ) : (\n <>\n {/* Megaphone icon — \"broadcast to all\" affordance */}\n <svg aria-hidden className=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M3 11v3a1 1 0 0 0 1 1h2l3.29 3.29a1 1 0 0 0 1.71-.71V7.42a1 1 0 0 0-1.71-.71L6 10H4a1 1 0 0 0-1 1Z\" />\n <path d=\"M16 8a5 5 0 0 1 0 6\" opacity=\"0.7\" />\n <path d=\"M19 5a9 9 0 0 1 0 12\" opacity=\"0.45\" />\n </svg>\n <span>Broadcast</span>\n </>\n )}\n </button>\n </div>\n {broadcastMsg.length > 0 && (\n <div className=\"text-right text-xs text-gray-600 mt-1 tabular-nums\">{broadcastMsg.length}/500</div>\n )}\n {broadcastResult && (\n <div className={`mt-3 text-sm text-center anet-fade-in ${broadcastResult.startsWith('Failed') ? 'text-red-400' : 'text-green-400/80'}`}>\n {broadcastResult}\n </div>\n )}\n </div>\n );\n}\n","'use client';\n\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { Session } from './types';\nimport { aliasAvatarColors, aliasInitial } from './AliasAvatar';\nimport { ChatPopover } from './ChatPopover';\nimport { vendorForModel, runtimeIdentity, identityLine } from '../lib/vendorIdentity';\n\ninterface MessageFlow {\n from_alias: string;\n to_alias: string;\n content: string;\n created_at: string;\n}\n\ninterface TopoGraphProps {\n sessions: Session[];\n sseSessions: Record<string, number>;\n // #84: a node.renamed event from the Overview's SSE listener. When the\n // currently open chat popover targets `from`, it follows the rename to `to`.\n renameSignal?: { from: string; to: string; ts: number } | null;\n}\n\ninterface Point {\n x: number;\n y: number;\n}\n\ninterface FlowLink {\n key: string;\n from: string;\n to: string;\n count: number;\n content: string;\n}\n\nconst cx = 500;\nconst cy = 330;\nconst onlineRadius = 220;\n// Round 97 (issue #50): tier into two rings when N > 8; round 98\n// (issue #61): tier into three rings when N > 14. At N=22 (Vincent's\n// network) two rings still leave 11 nodes per ring → inner chord of\n// 88px can't fit a 100px label; three rings give ~⌈N/3⌉ per ring so\n// every tier has enough arc room.\nconst onlineTierThreshold = 8;\nconst onlineTripleThreshold = 14;\nconst onlineInnerRadius = 175;\nconst onlineOuterRadius = 260;\nconst onlineTripleInnerR = 145;\nconst onlineTripleMidR = 215;\nconst onlineTripleOuterR = 285;\nconst offlineRadius = 325;\n\n/** Polar coordinate for a node on a ring. `rotateBy` lets the caller offset\n * the whole ring so two stacked rings don't align radially (round 25: the\n * offline ring gets a half-step rotation so its nodes sit in the gaps\n * between online ones). */\nfunction polarPoint(index: number, total: number, radius: number, rotateBy = 0) {\n const spread = total <= 2 ? Math.PI : Math.PI * 1.78;\n const start = -Math.PI / 2 - spread / 2;\n const angle = total <= 1 ? -Math.PI / 2 : start + (spread * index) / (total - 1) + rotateBy;\n return {\n x: cx + radius * Math.cos(angle),\n y: cy + radius * Math.sin(angle),\n };\n}\n\nfunction curvePath(from: Point, to: Point, lift = 0) {\n const mx = (from.x + to.x) / 2;\n const my = (from.y + to.y) / 2;\n const dx = to.x - from.x;\n const dy = to.y - from.y;\n const length = Math.hypot(dx, dy) || 1;\n const normalX = -dy / length;\n const normalY = dx / length;\n const control = {\n x: mx + normalX * lift,\n y: my + normalY * lift,\n };\n\n return `M${from.x},${from.y} Q${control.x},${control.y} ${to.x},${to.y}`;\n}\n\nfunction truncate(value: string, max: number) {\n return value.length > max ? `${value.slice(0, max - 1)}...` : value;\n}\n\nfunction nodeStatus(session: Session, isOnline: boolean, isLight: boolean) {\n if (!isOnline) {\n return {\n label: 'offline',\n primary: isLight ? '#94a3b8' : '#6b7280',\n halo: isLight ? '#e2e8f0' : '#111827',\n text: isLight ? '#475569' : '#9ca3af',\n };\n }\n if (session.status === 'working') {\n return {\n label: 'working',\n primary: isLight ? '#059669' : '#22c55e',\n halo: isLight ? '#d1fae5' : '#14532d',\n text: isLight ? '#065f46' : '#dcfce7',\n };\n }\n if (session.status === 'idle') {\n return {\n label: 'idle',\n primary: isLight ? '#0d9488' : '#2dd4bf',\n halo: isLight ? '#ccfbf1' : '#134e4a',\n text: isLight ? '#115e59' : '#ccfbf1',\n };\n }\n return {\n label: session.status || 'online',\n primary: isLight ? '#0284c7' : '#38bdf8',\n halo: isLight ? '#dbeafe' : '#0c4a6e',\n text: isLight ? '#0c4a6e' : '#e0f2fe',\n };\n}\n\n/** Theme-aware color palette for the topology SVG. */\ninterface Palette {\n panelStops: [string, string, string];\n radarStops: { color: string; opacity: number }[];\n arrowFill: string;\n ringStroke: string;\n spokeStroke: { active: string; idle: string };\n flowEdge: string;\n flowPath: string;\n flowParticle: string;\n nodeFill: { online: string; offline: string };\n labelBox: { fill: string; stroke: string };\n legendBox: { fill: string; stroke: string };\n legendText: string;\n legendHeadline: string;\n legendAccent: string;\n containerBg: string;\n containerBorder: string;\n topRailGradient: string;\n}\n\nconst DARK_PALETTE: Palette = {\n panelStops: ['#0b1220', '#080814', '#101018'],\n radarStops: [\n { color: '#22d3ee', opacity: 0.18 },\n { color: '#22c55e', opacity: 0.045 },\n { color: '#020617', opacity: 0 },\n ],\n arrowFill: '#67e8f9',\n ringStroke: '#164e63',\n spokeStroke: { active: '#22d3ee', idle: '#155e75' },\n flowEdge: '#67e8f9',\n flowPath: '#e0f2fe',\n flowParticle: '#fef08a',\n nodeFill: { online: '#020617', offline: '#080814' },\n labelBox: { fill: '#020617', stroke: '#1f2937' },\n legendBox: { fill: '#020617', stroke: '#1f2937' },\n legendText: '#94a3b8',\n legendHeadline: '#e5e7eb',\n legendAccent: '#67e8f9',\n containerBg: '#080814',\n containerBorder: '#2a2a4a',\n topRailGradient: 'from-transparent via-cyan-400/70 to-transparent',\n};\n\nconst LIGHT_PALETTE: Palette = {\n panelStops: ['#f8fafc', '#ffffff', '#f1f5f9'],\n radarStops: [\n { color: '#10b981', opacity: 0.06 },\n { color: '#3b82f6', opacity: 0.03 },\n { color: '#ffffff', opacity: 0 },\n ],\n arrowFill: '#10b981',\n ringStroke: '#cbd5e1',\n spokeStroke: { active: '#10b981', idle: '#cbd5e1' },\n flowEdge: '#10b981',\n flowPath: '#475569',\n flowParticle: '#f59e0b',\n nodeFill: { online: '#ffffff', offline: '#f8fafc' },\n labelBox: { fill: '#ffffff', stroke: '#e2e8f0' },\n legendBox: { fill: '#ffffff', stroke: '#e2e8f0' },\n legendText: '#475569',\n legendHeadline: '#0f172a',\n legendAccent: '#0d9488',\n containerBg: '#ffffff',\n containerBorder: '#e3e6eb',\n topRailGradient: 'from-transparent via-emerald-500/40 to-transparent',\n};\n\nfunction useTheme(): 'light' | 'dark' {\n const [theme, setTheme] = useState<'light' | 'dark'>('dark');\n useEffect(() => {\n const read = () => {\n const t = document.documentElement.getAttribute('data-theme') || 'cyber';\n setTheme(t === 'light' || t === 'mint' ? 'light' : 'dark');\n };\n read();\n const obs = new MutationObserver(read);\n obs.observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] });\n return () => obs.disconnect();\n }, []);\n return theme;\n}\n\n/** Round 100 (issue #79): brand showcase mode. Activate via `?brand=intern`\n * on any dashboard page — TopoGraph nodes show the 书小生 mascot instead\n * of alias initials. Stored in localStorage so the flag persists across\n * navigation. Clears with `?brand=none` or `?brand=` (empty). */\nfunction useBrand(): string | null {\n const [brand, setBrand] = useState<string | null>(null);\n useEffect(() => {\n try {\n const url = new URL(window.location.href);\n const param = url.searchParams.get('brand');\n if (param !== null) {\n if (param === '' || param === 'none') {\n localStorage.removeItem('anet-brand');\n setBrand(null);\n } else {\n localStorage.setItem('anet-brand', param);\n setBrand(param);\n }\n } else {\n setBrand(localStorage.getItem('anet-brand'));\n }\n } catch {}\n }, []);\n return brand;\n}\n\n/** Round 106 (issue #83): cluster agents by shared alias prefix so a team\n * reads as one unit in the topology. Adjacent (sorted) aliases that share\n * a ≥2-char prefix join the same group; the group key is the prefix common\n * to every member. Singletons map to their own alias (no hue shift). The\n * group key feeds aliasAvatarColors() so e.g. all 通信* nodes get one hue,\n * all 研究员* another — the \"同色相 tint\" clustering option from #83. */\nfunction commonPrefix(a: string, b: string): string {\n let i = 0;\n while (i < a.length && i < b.length && a[i] === b[i]) i++;\n return a.slice(0, i);\n}\n\n/** #83 + #111: group nodes that share a ≥2-char alias prefix OR a project_dir\n * (\"either criterion → same group\", Vincent 4724). Union-find over the\n * sessions; the component label prefers the shared project_dir's basename,\n * else the common alias prefix. Returns alias → groupKey. */\nfunction computeGroups(sessions: { alias: string; project_dir?: string | null }[]): Record<string, string> {\n const n = sessions.length;\n const parent = sessions.map((_, i) => i);\n const find = (i: number): number => {\n while (parent[i] !== i) { parent[i] = parent[parent[i]]; i = parent[i]; }\n return i;\n };\n const union = (a: number, b: number) => {\n const ra = find(a), rb = find(b);\n if (ra !== rb) parent[ra] = rb;\n };\n\n // union by shared project_dir\n const byDir: Record<string, number[]> = {};\n sessions.forEach((s, i) => {\n const d = s.project_dir?.trim();\n if (d) (byDir[d] ||= []).push(i);\n });\n for (const idxs of Object.values(byDir)) {\n for (let k = 1; k < idxs.length; k++) union(idxs[0], idxs[k]);\n }\n\n // union by shared ≥2-char alias prefix — sort, link adjacent pairs\n const order = sessions.map((_, i) => i).sort((a, b) => sessions[a].alias.localeCompare(sessions[b].alias));\n for (let k = 0; k + 1 < order.length; k++) {\n if (commonPrefix(sessions[order[k]].alias, sessions[order[k + 1]].alias).length >= 2) {\n union(order[k], order[k + 1]);\n }\n }\n\n // label each connected component\n const comps: Record<number, number[]> = {};\n for (let i = 0; i < n; i++) (comps[find(i)] ||= []).push(i);\n const keys: Record<string, string> = {};\n for (const members of Object.values(comps)) {\n let label: string;\n if (members.length === 1) {\n label = sessions[members[0]].alias;\n } else {\n const dirs = new Set(members.map(i => sessions[i].project_dir?.trim()).filter(Boolean) as string[]);\n if (dirs.size === 1) {\n const d = [...dirs][0];\n label = d.split('/').filter(Boolean).pop() || d;\n } else {\n label = members.map(i => sessions[i].alias).reduce((a, b) => commonPrefix(a, b));\n if (label.length < 2) label = sessions[members[0]].alias;\n }\n }\n for (const i of members) keys[sessions[i].alias] = label;\n }\n return keys;\n}\n\nfunction buildFlowLinks(messages: MessageFlow[], positions: Record<string, Point>) {\n const links = new Map<string, FlowLink>();\n\n messages.forEach(message => {\n if (\n !positions[message.from_alias] ||\n !positions[message.to_alias] ||\n message.from_alias === message.to_alias\n ) {\n return;\n }\n\n const key = `${message.from_alias}->${message.to_alias}`;\n const current = links.get(key);\n\n links.set(key, {\n key,\n from: message.from_alias,\n to: message.to_alias,\n count: (current?.count || 0) + 1,\n content: current?.content || message.content,\n });\n });\n\n return [...links.values()].slice(0, 18);\n}\n\nexport function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProps) {\n const theme = useTheme();\n const isLight = theme === 'light';\n const pal = isLight ? LIGHT_PALETTE : DARK_PALETTE;\n const brand = useBrand();\n const isIntern = brand === 'intern';\n const [messages, setMessages] = useState<MessageFlow[]>([]);\n // Issue #87: ring | grid layout toggle. Ring is the tiered-radial default;\n // grid arranges nodes in an N×M grid (better for 30+ nodes). Persisted to\n // localStorage like the zoom/pan view state. Declared above nodePositions\n // since that useMemo branches on it.\n const [layout, setLayout] = useState<'ring' | 'grid'>('ring');\n useEffect(() => {\n try {\n const saved = localStorage.getItem('anet-topo-layout');\n if (saved === 'grid' || saved === 'ring') setLayout(saved);\n } catch {}\n }, []);\n const toggleLayout = () => setLayout(prev => {\n const next = prev === 'ring' ? 'grid' : 'ring';\n try { localStorage.setItem('anet-topo-layout', next); } catch {}\n return next;\n });\n // Issue #113: node size scale (Vincent 4727 — nodes too big / crowded at\n // ~22 nodes). S/M/L → 0.7/0.84/1.0; default M (one notch down from the old\n // fixed size). Persisted like the layout toggle.\n const [nodeScale, setNodeScale] = useState(0.84);\n useEffect(() => {\n try {\n const saved = parseFloat(localStorage.getItem('anet-topo-nodescale') || '');\n if (saved === 0.7 || saved === 0.84 || saved === 1) setNodeScale(saved);\n } catch {}\n }, []);\n const pickNodeScale = (v: number) => {\n setNodeScale(v);\n try { localStorage.setItem('anet-topo-nodescale', String(v)); } catch {}\n };\n\n useEffect(() => {\n const fetchMessages = async () => {\n try {\n const res = await fetch('/api/hub/messages?limit=50');\n if (res.status === 401) {\n window.location.assign('/login');\n return;\n }\n\n const data = await res.json();\n setMessages(data.messages || []);\n } catch {}\n };\n fetchMessages();\n const interval = setInterval(fetchMessages, 5000);\n return () => clearInterval(interval);\n }, []);\n\n const {\n onlineNodes,\n offlineNodes,\n nodePositions,\n flowLinks,\n activeAliases,\n groupKeys,\n groupBoxes,\n } = useMemo(() => {\n const sseCount = (s: { alias: string; network_id?: string }) =>\n (s.network_id ? sseSessions[`${s.network_id}:${s.alias}`] : undefined) ?? sseSessions[s.alias];\n // Round 106 (issue #83): sort by alias so same-prefix agents\n // (通信龙 / 通信牛 / 通信工程马 …, or 研究员1号 / 研究员2号 …) end up\n // adjacent in the array — the tier layout below assigns angles by\n // index, so contiguous-in-array becomes contiguous-in-ring, i.e.\n // each team visually clusters. localeCompare keeps CJK ordering sane.\n const byAlias = (a: Session, b: Session) => a.alias.localeCompare(b.alias);\n // #112 umbrella: ghost age-out — an offline node not seen for over a day\n // is almost certainly a deleted node the server `/api/status` still\n // returns (#74 root cause is server-side; this is the dashboard-side\n // fallback so stale ghosts stop cluttering the topology). A missing\n // last_seen_at is kept (conservative — could be a legitimately new node).\n const GHOST_MS = 24 * 60 * 60 * 1000;\n const now = Date.now();\n const isGhost = (s: Session) => {\n if (s.status !== 'offline' || sseCount(s) || !s.last_seen_at) return false;\n const t = Date.parse(s.last_seen_at);\n return !Number.isNaN(t) && now - t > GHOST_MS;\n };\n const online = sessions.filter(s => s.status !== 'offline' || sseCount(s)).sort(byAlias);\n const offline = sessions.filter(s => s.status === 'offline' && !sseCount(s) && !isGhost(s)).sort(byAlias);\n const positions: Record<string, Point> = {};\n\n if (layout === 'grid') {\n // Issue #87 + #111: group-banded grid. Nodes are sorted by alias so\n // same-prefix aliases are adjacent; each multi-member prefix group then\n // gets its OWN row(s) starting at column 0, while singletons pack into\n // shared rows. Group-banded placement keeps every group's bounding box\n // (#111) a clean rectangle — no box ever overlaps another group's.\n const all = [...online, ...offline];\n const groupKeys = computeGroups(all);\n const cols = Math.max(1, Math.ceil(Math.sqrt(all.length)));\n // #112: gy0 starts below the (now compact) recent-signal / legend\n // overlay panels — their max bottom edge is y≈112 — so grid row 0 is\n // never occluded; gy1 extends near the canvas bottom for breathing room.\n const gx0 = 150, gx1 = 850, gy0 = 126, gy1 = 652;\n const cellW = (gx1 - gx0) / cols;\n // largest node radius at the current size scale — drives the group\n // label band + the row-height floor so nothing ever overlaps.\n const nodeR = Math.round(26 * nodeScale);\n\n // ordered runs of consecutive same-group-key nodes (≥2 = real group)\n const runs: { key: string; members: Session[] }[] = [];\n for (const s of all) {\n const gk = groupKeys[s.alias];\n const last = runs[runs.length - 1];\n if (last && last.key === gk) last.members.push(s);\n else runs.push({ key: gk, members: [s] });\n }\n\n // Pass 1 — assign each run to a band: a multi-member group owns its\n // rows (left-aligned, so its bounding box is a tidy rect); contiguous\n // singletons pack into shared rows (centred). Collect total row count.\n type Band = { members: Session[]; startRow: number; centred: boolean; isGroup: boolean };\n const bands: Band[] = [];\n let row = 0;\n let i = 0;\n while (i < runs.length) {\n if (runs[i].members.length >= 2) {\n bands.push({ members: runs[i].members, startRow: row, centred: false, isGroup: true });\n row += Math.ceil(runs[i].members.length / cols);\n i++;\n } else {\n const singles: Session[] = [];\n while (i < runs.length && runs[i].members.length < 2) {\n singles.push(runs[i].members[0]);\n i++;\n }\n bands.push({ members: singles, startRow: row, centred: true, isGroup: false });\n row += Math.ceil(singles.length / cols);\n }\n }\n const totalRows = Math.max(1, row);\n // #112: the group label sits in a band ABOVE the topmost node, so the\n // band must clear the node radius — GROUP_TOP is node-relative, never\n // cellH-derived (cellH-derived was the label↔node overlap bug Vincent\n // hit). cellH then floors at GROUP_TOP + 30 so the label band + bottom\n // padding always fit and stacked group boxes never touch; past the\n // floor the grid overflows and zoom/pan handles it.\n const GROUP_TOP = nodeR + 20;\n // Row-height floor = the tightest of: a node + its label below it\n // (2·nodeR + ~22), and the label band + min box padding (GROUP_TOP + 12).\n // Below this, rows would overlap; past it the grid overflows and\n // zoom/pan covers the rest.\n const cellH = Math.max(2 * nodeR + 22, GROUP_TOP + 12, Math.min(100, (gy1 - gy0) / totalRows));\n\n // Pass 2 — place each band's members.\n for (const band of bands) {\n band.members.forEach((s, idx) => {\n const rowInBand = Math.floor(idx / cols);\n const c = idx % cols;\n const inRow = Math.min(cols, band.members.length - rowInBand * cols);\n const inset = band.centred ? ((cols - inRow) * cellW) / 2 : 0;\n positions[s.alias] = {\n x: gx0 + inset + (c + 0.5) * cellW,\n y: gy0 + (band.startRow + rowInBand + 0.5) * cellH,\n };\n });\n }\n\n const links = buildFlowLinks(messages, positions);\n const active = new Set<string>();\n links.forEach(link => { active.add(link.from); active.add(link.to); });\n // #111: one bounding box per multi-member group (Vincent 4722). Each\n // group owns its rows; GROUP_PAD fills the row space left below the\n // nodes after the label band, so stacked group boxes always have a\n // gap between them (GROUP_TOP is defined above, with cellH).\n const GROUP_PAD = Math.max(8, Math.min(26, cellH - GROUP_TOP - 8)); // side/bottom\n const groupBoxes = bands\n .filter(b => b.isGroup)\n .map(band => {\n const pts = band.members.map(s => positions[s.alias]).filter(Boolean);\n const xs = pts.map(p => p.x);\n const ys = pts.map(p => p.y);\n const minX = Math.min(...xs), minY = Math.min(...ys);\n return {\n key: band.members.length ? groupKeys[band.members[0].alias] : '',\n x: minX - GROUP_PAD,\n y: minY - GROUP_TOP,\n w: Math.max(...xs) - minX + GROUP_PAD * 2,\n h: Math.max(...ys) - minY + GROUP_TOP + GROUP_PAD,\n };\n });\n return {\n onlineNodes: online,\n offlineNodes: offline,\n nodePositions: positions,\n flowLinks: links,\n activeAliases: active,\n groupKeys,\n groupBoxes,\n };\n }\n\n // Round 97 (issue #50) + 98 (issue #61): three layout modes by N.\n // N ≤ 8 → single ring (r=220)\n // 8 < N ≤ 14 → two rings (inner r=175, outer r=260, half-step rot)\n // N > 14 → three rings (r=145/215/285, ⌈N/3⌉ per ring)\n // Each ring's spread is 1.78π so its node count drives chord length:\n // labels are 100px wide so each ring needs ≥110px chord per node.\n const tripleTier = online.length > onlineTripleThreshold;\n const dualTier = !tripleTier && online.length > onlineTierThreshold;\n let outerOnlineCount = online.length;\n if (tripleTier) {\n const per = Math.ceil(online.length / 3);\n const r1 = online.slice(0, per);\n const r2 = online.slice(per, 2 * per);\n const r3 = online.slice(2 * per);\n r1.forEach((s, index) => {\n positions[s.alias] = polarPoint(index, Math.max(r1.length, 1), onlineTripleInnerR);\n });\n const r1Spread = r1.length <= 2 ? Math.PI : Math.PI * 1.78;\n const r1Step = r1.length > 1 ? r1Spread / (r1.length - 1) : 0;\n r2.forEach((s, index) => {\n positions[s.alias] = polarPoint(index, Math.max(r2.length, 1), onlineTripleMidR, r1Step / 2);\n });\n r3.forEach((s, index) => {\n positions[s.alias] = polarPoint(index, Math.max(r3.length, 1), onlineTripleOuterR);\n });\n outerOnlineCount = r3.length;\n } else if (dualTier) {\n const innerCount = Math.ceil(online.length / 2);\n const outerCount = online.length - innerCount;\n const innerNodes = online.slice(0, innerCount);\n const outerNodes = online.slice(innerCount);\n innerNodes.forEach((s, index) => {\n positions[s.alias] = polarPoint(index, Math.max(innerCount, 1), onlineInnerRadius);\n });\n const innerSpread = innerCount <= 2 ? Math.PI : Math.PI * 1.78;\n const innerStep = innerCount > 1 ? innerSpread / (innerCount - 1) : 0;\n outerNodes.forEach((s, index) => {\n positions[s.alias] = polarPoint(index, Math.max(outerCount, 1), onlineOuterRadius, innerStep / 2);\n });\n outerOnlineCount = outerCount;\n } else {\n online.forEach((s, index) => {\n positions[s.alias] = polarPoint(index, Math.max(online.length, 1), onlineRadius);\n });\n }\n\n // Offset the offline ring radially by half the outermost online step so\n // offline bubbles sit in the angular gaps between online bubbles instead\n // of stacking directly behind them. Also push the outer ring further when\n // there are many offline nodes so labels don't crowd the legend.\n const outerSpreadBase = outerOnlineCount <= 2 ? Math.PI : Math.PI * 1.78;\n const outerStep = outerOnlineCount > 1 ? outerSpreadBase / (outerOnlineCount - 1) : 0;\n const offlineRotation = outerOnlineCount > 0 ? outerStep / 2 : 0;\n const offlineR = offlineRadius + Math.max(0, offline.length - 4) * 6;\n\n offline.forEach((s, index) => {\n positions[s.alias] = polarPoint(index, Math.max(offline.length, 1), offlineR, offlineRotation);\n });\n\n const links = buildFlowLinks(messages, positions);\n const active = new Set<string>();\n links.forEach(link => {\n active.add(link.from);\n active.add(link.to);\n });\n\n // Round 106 (issue #83): group key per alias → shared hue per team.\n const groupKeys = computeGroups([...online, ...offline]);\n\n return {\n onlineNodes: online,\n offlineNodes: offline,\n nodePositions: positions,\n flowLinks: links,\n activeAliases: active,\n groupKeys,\n // #111: group boxes are a grid-layout feature only — radially scattered\n // ring nodes can't be cleanly boxed. Ring keeps the #83 prefix hue.\n groupBoxes: [] as { key: string; x: number; y: number; w: number; h: number }[],\n };\n }, [messages, sessions, sseSessions, layout, nodeScale]);\n\n const workingCount = onlineNodes.filter(s => s.status === 'working').length;\n // Round 109 (Vincent 4582 P0): hover-gated labels above this node count\n // so dense fleets show clean avatars instead of a wall of overlapping\n // label cards. 16 ≈ where the triple-tier rings start to crowd.\n const denseLayout = onlineNodes.length + offlineNodes.length > 16;\n const [hoveredAlias, setHoveredAlias] = useState<string | null>(null);\n\n // --- Round 103 (issue #81): fullscreen + zoom + pan interaction layer ---\n // DIY native (no d3 / svg-pan-zoom): wrap the topology content in a single\n // <g transform> and drive it with wheel + pointer-drag. The panel <rect>\n // backdrop stays fixed so panning never reveals empty canvas. View state\n // {zoom,x,y} persists to localStorage (same sticky pattern as brand flag).\n const VIEWBOX_W = 1000;\n const VIEWBOX_H = 680;\n const ZOOM_MIN = 0.5;\n const ZOOM_MAX = 4;\n const containerRef = useRef<HTMLDivElement>(null);\n const svgRef = useRef<SVGSVGElement>(null);\n const [view, setView] = useState({ zoom: 1, x: 0, y: 0 });\n const viewRef = useRef(view);\n const dragRef = useRef({ active: false, startX: 0, startY: 0, baseX: 0, baseY: 0 });\n const [isFullscreen, setIsFullscreen] = useState(false);\n // Issue #100: singleton chat popover. One alias at a time — clicking\n // another node swaps the target and the conversation switches in place.\n const [chatAlias, setChatAlias] = useState<string | null>(null);\n // #84: when a node is renamed while its chat popover is open, follow the\n // rename so the conversation keeps targeting a live alias.\n useEffect(() => {\n if (renameSignal && renameSignal.from === chatAlias) {\n setChatAlias(renameSignal.to);\n }\n // chatAlias intentionally omitted — only react to a new rename signal,\n // not to the user opening/closing the popover.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [renameSignal]);\n\n useEffect(() => { viewRef.current = view; }, [view]);\n\n // restore persisted view once on mount\n useEffect(() => {\n try {\n const raw = localStorage.getItem('anet-topo-view');\n if (raw) {\n const v = JSON.parse(raw);\n if (typeof v?.zoom === 'number') {\n setView({\n zoom: Math.min(ZOOM_MAX, Math.max(ZOOM_MIN, v.zoom)),\n x: typeof v.x === 'number' ? v.x : 0,\n y: typeof v.y === 'number' ? v.y : 0,\n });\n }\n }\n } catch {}\n }, []);\n\n // persist view\n useEffect(() => {\n try { localStorage.setItem('anet-topo-view', JSON.stringify(view)); } catch {}\n }, [view]);\n\n // track fullscreen state (button label + Esc-exit sync)\n useEffect(() => {\n const onFsChange = () => setIsFullscreen(document.fullscreenElement === containerRef.current);\n document.addEventListener('fullscreenchange', onFsChange);\n return () => document.removeEventListener('fullscreenchange', onFsChange);\n }, []);\n\n // wheel zoom — native non-passive listener so preventDefault() actually\n // stops the page from scrolling. Uses functional setState so the listener\n // never goes stale and can attach once.\n useEffect(() => {\n const svg = svgRef.current;\n if (!svg) return;\n const onWheel = (e: WheelEvent) => {\n e.preventDefault();\n const rect = svg.getBoundingClientRect();\n const mx = ((e.clientX - rect.left) / rect.width) * VIEWBOX_W;\n const my = ((e.clientY - rect.top) / rect.height) * VIEWBOX_H;\n setView(prev => {\n // Round 104 (issue #81 follow-up): Vincent 实测 zoom 太灵敏. The\n // old factor was a fixed 1.15x per wheel *event* — fine for a\n // mouse notch but a trackpad fires dozens of events per gesture\n // so it compounded into huge jumps. Scale the factor by deltaY\n // magnitude with a small coefficient, then clamp the per-event\n // change so no single tick moves more than ~8%.\n const factor = Math.min(1.08, Math.max(0.926, Math.exp(-e.deltaY * 0.0006)));\n const nz = Math.min(ZOOM_MAX, Math.max(ZOOM_MIN, prev.zoom * factor));\n const ratio = nz / prev.zoom;\n // keep the point under the cursor stationary\n return { zoom: nz, x: mx - (mx - prev.x) * ratio, y: my - (my - prev.y) * ratio };\n });\n };\n svg.addEventListener('wheel', onWheel, { passive: false });\n return () => svg.removeEventListener('wheel', onWheel);\n }, []);\n\n const onPointerDown = (e: React.PointerEvent<SVGSVGElement>) => {\n if (e.button !== 0) return;\n (e.currentTarget as Element).setPointerCapture?.(e.pointerId);\n dragRef.current = {\n active: true,\n startX: e.clientX,\n startY: e.clientY,\n baseX: viewRef.current.x,\n baseY: viewRef.current.y,\n };\n };\n const onPointerMove = (e: React.PointerEvent<SVGSVGElement>) => {\n const d = dragRef.current;\n if (!d.active) return;\n const svg = svgRef.current;\n if (!svg) return;\n const rect = svg.getBoundingClientRect();\n const dx = ((e.clientX - d.startX) / rect.width) * VIEWBOX_W;\n const dy = ((e.clientY - d.startY) / rect.height) * VIEWBOX_H;\n setView(prev => ({ ...prev, x: d.baseX + dx, y: d.baseY + dy }));\n };\n const onPointerUp = (e: React.PointerEvent<SVGSVGElement>) => {\n if (!dragRef.current.active) return;\n dragRef.current.active = false;\n try {\n (e.currentTarget as Element).releasePointerCapture?.(e.pointerId);\n } catch {}\n };\n\n // zoom buttons — zoom around the canvas center\n const zoomBy = (factor: number) => {\n setView(prev => {\n const nz = Math.min(ZOOM_MAX, Math.max(ZOOM_MIN, prev.zoom * factor));\n const ratio = nz / prev.zoom;\n const cx0 = VIEWBOX_W / 2;\n const cy0 = VIEWBOX_H / 2;\n return { zoom: nz, x: cx0 - (cx0 - prev.x) * ratio, y: cy0 - (cy0 - prev.y) * ratio };\n });\n };\n const resetView = () => setView({ zoom: 1, x: 0, y: 0 });\n\n const toggleFullscreen = () => {\n const el = containerRef.current;\n if (!el) return;\n if (document.fullscreenElement) {\n document.exitFullscreen?.();\n } else {\n const req =\n el.requestFullscreen ||\n (el as unknown as { webkitRequestFullscreen?: () => void }).webkitRequestFullscreen;\n req?.call(el);\n }\n };\n\n return (\n <section className=\"w-full max-w-6xl mx-auto mb-8\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between mb-3 px-1\">\n <div>\n <div className=\"text-xs uppercase text-gray-600 tracking-wider\">Network Topology</div>\n <h2 className=\"text-lg text-white font-semibold\">Command mesh</h2>\n </div>\n <div className=\"flex flex-wrap items-center gap-2 text-xs\">\n {/* Issue #87: ring | grid layout toggle — segmented control,\n persisted to localStorage anet-topo-layout. */}\n <div className=\"inline-flex rounded-md border border-gray-500/25 overflow-hidden\" role=\"group\" aria-label=\"Topology layout\">\n <button\n onClick={() => { if (layout !== 'ring') toggleLayout(); }}\n aria-pressed={layout === 'ring'}\n className={`px-2.5 py-1 transition-colors ${layout === 'ring' ? 'bg-cyan-500/15 text-cyan-300' : 'text-gray-500 hover:text-gray-400'}`}\n >\n Ring\n </button>\n <button\n onClick={() => { if (layout !== 'grid') toggleLayout(); }}\n aria-pressed={layout === 'grid'}\n className={`px-2.5 py-1 border-l border-gray-500/25 transition-colors ${layout === 'grid' ? 'bg-cyan-500/15 text-cyan-300' : 'text-gray-500 hover:text-gray-400'}`}\n >\n Grid\n </button>\n </div>\n <span className=\"px-2.5 py-1 rounded-md bg-green-500/10 text-green-300 border border-green-500/20\">\n {workingCount} working\n </span>\n <span className=\"px-2.5 py-1 rounded-md bg-cyan-500/10 text-cyan-300 border border-cyan-500/20\">\n {onlineNodes.length} online\n </span>\n <span className=\"px-2.5 py-1 rounded-md bg-gray-500/10 text-gray-400 border border-gray-500/20\">\n {flowLinks.length} active links\n </span>\n </div>\n </div>\n\n <div\n ref={containerRef}\n className={`relative overflow-hidden rounded-lg border shadow-2xl ${isLight ? 'shadow-zinc-900/5' : 'shadow-cyan-950/30'} ${isFullscreen ? 'flex items-center justify-center' : ''}`}\n style={{ background: pal.containerBg, borderColor: pal.containerBorder }}\n >\n <div className={`absolute inset-x-0 top-0 h-px bg-gradient-to-r ${pal.topRailGradient}`} />\n\n <svg\n ref={svgRef}\n viewBox=\"0 0 1000 680\"\n className=\"w-full h-auto block\"\n preserveAspectRatio=\"xMidYMid meet\"\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerLeave={onPointerUp}\n style={{ cursor: 'grab', touchAction: 'none' }}\n >\n <defs>\n <linearGradient id=\"topo-panel\" x1=\"0\" x2=\"1\" y1=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={pal.panelStops[0]} />\n <stop offset=\"48%\" stopColor={pal.panelStops[1]} />\n <stop offset=\"100%\" stopColor={pal.panelStops[2]} />\n </linearGradient>\n <radialGradient id=\"topo-radar\" cx=\"50%\" cy=\"50%\" r=\"55%\">\n <stop offset=\"0%\" stopColor={pal.radarStops[0].color} stopOpacity={pal.radarStops[0].opacity} />\n <stop offset=\"45%\" stopColor={pal.radarStops[1].color} stopOpacity={pal.radarStops[1].opacity} />\n <stop offset=\"100%\" stopColor={pal.radarStops[2].color} stopOpacity={pal.radarStops[2].opacity} />\n </radialGradient>\n {!isLight && (\n <filter id=\"topo-glow\">\n <feGaussianBlur stdDeviation=\"4\" result=\"blur\" />\n <feMerge>\n <feMergeNode in=\"blur\" />\n <feMergeNode in=\"SourceGraphic\" />\n </feMerge>\n </filter>\n )}\n <marker id=\"topo-arrow\" viewBox=\"0 0 10 10\" refX=\"8\" refY=\"5\" markerWidth=\"5\" markerHeight=\"5\" orient=\"auto-start-reverse\">\n <path d=\"M 0 0 L 10 5 L 0 10 z\" fill={pal.arrowFill} />\n </marker>\n {/* Round 45: radial radar sweep gradient — bright at center\n (where it meets the hub) fading to leading edge. */}\n <radialGradient id=\"topo-sweep\" cx=\"0%\" cy=\"50%\" r=\"100%\">\n <stop offset=\"0%\" stopColor={isLight ? '#0d9488' : '#22d3ee'} stopOpacity={isLight ? 0.18 : 0.32} />\n <stop offset=\"70%\" stopColor={isLight ? '#0d9488' : '#22d3ee'} stopOpacity={isLight ? 0.10 : 0.18} />\n <stop offset=\"100%\" stopColor={isLight ? '#0d9488' : '#22d3ee'} stopOpacity=\"0\" />\n </radialGradient>\n </defs>\n\n {/* panel backdrop stays fixed — panning never reveals empty canvas */}\n <rect width=\"1000\" height=\"680\" fill=\"url(#topo-panel)\" />\n\n {/* Round 103 (issue #81): everything inside this <g> zooms + pans\n together. transform order = translate then scale. */}\n <g transform={`translate(${view.x} ${view.y}) scale(${view.zoom})`}>\n {/* Issue #87: radar/ring ambiance renders only in ring layout —\n grid mode drops it so the concentric rings don't sit behind a\n rectangular grid. */}\n {layout === 'ring' && (<>\n <circle cx={cx} cy={cy} r=\"330\" fill=\"url(#topo-radar)\" />\n\n {/* Round 45: subtle star field — 24 deterministic dots scattered\n across the canvas give the radar bg some depth. Skipped on\n light theme so the white surface stays clean. */}\n {!isLight && (\n <g opacity=\"0.5\">\n {Array.from({ length: 28 }).map((_, i) => {\n // Deterministic pseudo-random scatter so positions are\n // stable between renders (no JS hydration mismatch).\n const seed = i * 9301 + 49297;\n const x = ((seed * 13) % 1000);\n const y = ((seed * 7) % 680);\n const r = (i % 3 === 0) ? 1.2 : 0.7;\n return <circle key={i} cx={x} cy={y} r={r} fill=\"#a5b4fc\" opacity={0.35 + (i % 4) * 0.05} />;\n })}\n </g>\n )}\n\n {/* Round 45: rotating radar sweep — a 40° wedge with a soft\n leading-edge gradient. Slow 6s rotation reads as a radar\n scan without being noisy. Inline transform-origin on the\n <g> wrapper ensures Chrome / Firefox rotate around (cx,cy)\n instead of the SVG viewBox corner. */}\n <g\n style={{\n transformOrigin: `${cx}px ${cy}px`,\n transformBox: 'view-box',\n }}\n className=\"anet-topo-sweep\"\n opacity={isLight ? 0.7 : 1}\n >\n <path\n d={`M ${cx} ${cy} L ${cx + 330} ${cy} A 330 330 0 0 0 ${cx + 330 * Math.cos(-Math.PI / 4.5)} ${cy + 330 * Math.sin(-Math.PI / 4.5)} Z`}\n fill=\"url(#topo-sweep)\"\n />\n </g>\n\n {/* radar rings */}\n {[90, 170, 250, 330].map(radius => (\n <circle key={radius} cx={cx} cy={cy} r={radius} fill=\"none\" stroke={pal.ringStroke} strokeWidth=\"1\" opacity={isLight ? 0.6 : 0.35} />\n ))}\n\n {/* Round 50: 4 small particles slowly orbiting the outer ring\n (r=330). Each starts at a different angle (offset 0/0.25/0.5/0.75\n of the cycle) so they're evenly spaced. 16s per revolution is\n slow enough to feel ambient, not noisy. Skipped on light theme\n so the white surface stays clean. */}\n {!isLight && [0, 0.25, 0.5, 0.75].map((phase, i) => (\n <g key={`orbit-${i}`}>\n <circle\n cx={cx + 330} cy={cy}\n r={i === 0 ? 2.8 : 2.2}\n fill=\"#22d3ee\"\n opacity={0.9}\n filter=\"url(#topo-glow)\"\n >\n <animateTransform\n attributeName=\"transform\"\n type=\"rotate\"\n from={`${phase * 360} ${cx} ${cy}`}\n to={`${phase * 360 + 360} ${cx} ${cy}`}\n dur=\"16s\"\n repeatCount=\"indefinite\"\n />\n </circle>\n </g>\n ))}\n\n {[0, 30, 60, 90, 120, 150].map(angle => (\n <line\n key={angle}\n x1={cx - 360 * Math.cos(angle * Math.PI / 180)}\n y1={cy - 360 * Math.sin(angle * Math.PI / 180)}\n x2={cx + 360 * Math.cos(angle * Math.PI / 180)}\n y2={cy + 360 * Math.sin(angle * Math.PI / 180)}\n stroke={pal.ringStroke}\n strokeWidth=\"1\"\n opacity={isLight ? 0.35 : 0.18}\n />\n ))}\n </>)}\n\n {/* hub links — round 46: idle spokes now have animated\n stroke-dashoffset so dashes flow outward from the hub\n (\"command relay\" feel). Active spokes carrying live message\n flow stay as solid bright strokes. */}\n {layout === 'ring' && onlineNodes.map((session, idx) => {\n const pos = nodePositions[session.alias];\n if (!pos) return null;\n const path = curvePath({ x: cx, y: cy }, pos, 0);\n const isActiveSpoke = activeAliases.has(session.alias);\n\n return (\n <path\n key={`hub-${session.alias}`}\n d={path}\n fill=\"none\"\n stroke={isActiveSpoke ? pal.spokeStroke.active : pal.spokeStroke.idle}\n strokeWidth={isActiveSpoke ? 2 : 1}\n strokeDasharray={isActiveSpoke ? 'none' : '6 14'}\n opacity={isActiveSpoke ? 0.7 : 0.45}\n className={isActiveSpoke ? undefined : 'anet-topo-spoke-flow'}\n style={isActiveSpoke ? undefined : { animationDelay: `${-(idx * 0.25)}s` }}\n />\n );\n })}\n\n {/* #111: prefix-group boundary boxes (Vincent 4722). Grid layout\n only — groupBoxes is empty in ring mode. Rendered behind the\n flow links + nodes; pointer-events off so they never intercept\n a node click. Restrained dashed container + group-name label. */}\n {groupBoxes.map(box => (\n <g key={`grp-${box.key}`} data-group={box.key} style={{ pointerEvents: 'none' }}>\n <rect\n x={box.x}\n y={box.y}\n width={box.w}\n height={box.h}\n rx=\"14\"\n fill={isLight ? '#0f172a' : '#a5b4fc'}\n fillOpacity={isLight ? 0.025 : 0.045}\n stroke={pal.ringStroke}\n strokeWidth=\"1.5\"\n strokeDasharray=\"6 6\"\n />\n <text\n x={box.x + 12}\n y={box.y + 14}\n fill={pal.legendText}\n fontSize=\"13\"\n fontFamily=\"monospace\"\n fontWeight=\"700\"\n >\n {box.key}\n </text>\n </g>\n ))}\n\n {/* directed message flows */}\n {flowLinks.map((link, index) => {\n const from = nodePositions[link.from];\n const to = nodePositions[link.to];\n if (!from || !to) return null;\n\n const lift = index % 2 === 0 ? 36 : -36;\n const path = curvePath(from, to, lift);\n const width = Math.min(2 + link.count, 7);\n const duration = 2.2 + (index % 5) * 0.32;\n\n return (\n <g key={link.key}>\n <path\n d={path}\n fill=\"none\"\n stroke={pal.flowEdge}\n strokeWidth={width}\n opacity={isLight ? 0.22 : 0.28}\n filter={isLight ? undefined : 'url(#topo-glow)'}\n markerEnd=\"url(#topo-arrow)\"\n />\n <path\n id={`flow-path-${index}`}\n d={path}\n fill=\"none\"\n stroke={pal.flowPath}\n strokeWidth=\"1\"\n strokeDasharray=\"2 12\"\n opacity={isLight ? 0.4 : 0.75}\n />\n <circle r=\"4\" fill={pal.flowParticle} filter={isLight ? undefined : 'url(#topo-glow)'}>\n <animateMotion dur={`${duration}s`} repeatCount=\"indefinite\" path={path} />\n </circle>\n </g>\n );\n })}\n\n {/* center hub — round 39: enlarged from r=6 (12px) to r=10 (20px)\n core so the \"control plane\" reads as the network's anchor,\n not a stray particle. Static halo ring at r=18 grounds it\n visually; two outward pulses keep the \"signal source\" idea\n from r17. Light theme gets a paler core to avoid hot-spotting\n the bg. */}\n {layout === 'ring' && (<g>\n {/* static grounding halo — sits underneath, low opacity */}\n <circle\n cx={cx} cy={cy} r=\"18\"\n fill={isLight ? '#d1fae5' : '#10b981'}\n opacity={isLight ? 0.35 : 0.10}\n />\n {/* outer pulse 1 */}\n <circle cx={cx} cy={cy} r=\"10\" fill=\"none\" stroke=\"#10b981\" strokeWidth=\"1.5\">\n <animate attributeName=\"r\" values=\"10;38;10\" dur=\"2.4s\" repeatCount=\"indefinite\" />\n <animate attributeName=\"opacity\" values=\"0.55;0;0.55\" dur=\"2.4s\" repeatCount=\"indefinite\" />\n </circle>\n {/* outer pulse 2 (delayed 1.2s) */}\n <circle cx={cx} cy={cy} r=\"10\" fill=\"none\" stroke=\"#10b981\" strokeWidth=\"1.5\" opacity=\"0\">\n <animate attributeName=\"r\" values=\"10;38;10\" dur=\"2.4s\" begin=\"1.2s\" repeatCount=\"indefinite\" />\n <animate attributeName=\"opacity\" values=\"0.45;0;0.45\" dur=\"2.4s\" begin=\"1.2s\" repeatCount=\"indefinite\" />\n </circle>\n {/* core — 20px diameter, larger inner highlight reads as a \"lit lamp\" */}\n <circle cx={cx} cy={cy} r=\"10\" fill={isLight ? '#059669' : '#10b981'} />\n <circle cx={cx} cy={cy} r=\"5\" fill=\"#d1fae5\" opacity=\"0.9\" />\n </g>)}\n\n {/* agent nodes */}\n {[...onlineNodes, ...offlineNodes].map(session => {\n const pos = nodePositions[session.alias];\n if (!pos) return null;\n\n const sseCountFor = (session.network_id ? sseSessions[`${session.network_id}:${session.alias}`] : undefined) ?? sseSessions[session.alias];\n const isOnline = session.status !== 'offline' || !!sseCountFor;\n const status = nodeStatus(session, isOnline, isLight);\n const isActive = activeAliases.has(session.alias);\n // #113: node size scales with the S/M/L control; halos, labels,\n // badge and avatar all derive from `radius` so they follow.\n const radius = Math.round((isOnline ? 26 : 18) * nodeScale);\n // Round 109/110 (Vincent 4582 + 4583 P0): at high node counts\n // the 100px opaque label cards overlapped each other and\n // covered neighbouring avatars. But hiding text entirely went\n // too far (\"还是得有文字\"). So: below the density threshold the\n // full name+status card shows always; above it each node shows\n // a lightweight plain-text alias (no opaque card → can't\n // occlude an avatar), and the full card appears only for the\n // hovered node or once zoomed in past 1.4×.\n const showFullLabel = !denseLayout || hoveredAlias === session.alias || view.zoom >= 1.4;\n\n return (\n <g\n key={session.alias}\n data-node={session.alias}\n className=\"transition-opacity\"\n style={{ cursor: 'pointer' }}\n // Stop the pointerdown from reaching the SVG pan handler: the\n // SVG calls setPointerCapture, and a captured pointer makes\n // Chromium fire the follow-up `click` on the SVG instead of\n // this node — so without this the node's onClick never runs.\n // Side effect (intended): you pan from empty canvas, not by\n // grabbing a node.\n onPointerDown={(e) => e.stopPropagation()}\n onPointerEnter={() => denseLayout && setHoveredAlias(session.alias)}\n onPointerLeave={() => denseLayout && setHoveredAlias(prev => (prev === session.alias ? null : prev))}\n onClick={() => setChatAlias(session.alias)}\n >\n {/* Issue #96: native hover tooltip — \"Vendor · model · Runtime\".\n Falls back to just the alias when the node reports no\n model/runtime. */}\n <title>{identityLine(session.model, session.runtime) || session.alias}</title>\n {isActive && (\n <circle cx={pos.x} cy={pos.y} r={radius + 14} fill={status.primary} opacity={isLight ? 0.08 : 0.12}>\n <animate attributeName=\"r\" values={`${radius + 8};${radius + 22};${radius + 8}`} dur=\"2.4s\" repeatCount=\"indefinite\" />\n <animate attributeName=\"opacity\" values={isLight ? '0.12;0.02;0.12' : '0.18;0.04;0.18'} dur=\"2.4s\" repeatCount=\"indefinite\" />\n </circle>\n )}\n <circle cx={pos.x} cy={pos.y} r={radius + 8} fill={status.halo} opacity={isOnline ? (isLight ? 0.85 : 0.65) : (isLight ? 0.4 : 0.25)} />\n <circle\n cx={pos.x}\n cy={pos.y}\n r={radius}\n fill={isOnline ? pal.nodeFill.online : pal.nodeFill.offline}\n stroke={status.primary}\n strokeWidth={isOnline ? 3 : 1.5}\n strokeDasharray={isOnline ? 'none' : '5 5'}\n filter={isOnline && !isLight ? 'url(#topo-glow)' : undefined}\n />\n {/* Issue #96: node \"avatar\" is now driven by the model\n vendor. Decision order:\n 1. ?brand=intern flag, or an intern-aliased node with\n no model field → 书生 coin (preserves #79).\n 2. vendor has a packaged logo asset → that logo image\n (intern-s1-* models land here via vendorForModel).\n 3. known vendor, logo asset not shipped yet → a\n vendor-tinted monogram (spec-mandated fallback).\n 4. unknown vendor / null model → the prefix-group\n hue-hashed initial (#83/#99 behaviour, unchanged). */}\n {(() => {\n const ar = Math.round((isOnline ? 14 : 10) * nodeScale);\n const size = radius * 2;\n const vendor = vendorForModel(session.model);\n const internByAlias = /书生|书小生|intern/i.test(session.alias);\n\n if (isIntern || internByAlias || vendor.logo) {\n return (\n <image\n href={vendor.logo ?? '/intern_avatar.png'}\n x={pos.x - size / 2}\n y={pos.y - size / 2}\n width={size}\n height={size}\n preserveAspectRatio=\"xMidYMid meet\"\n />\n );\n }\n if (vendor.id !== 'unknown') {\n // Known model house, logo asset not in public/vendors/\n // yet — vendor-tinted monogram stands in.\n return (\n <>\n <circle cx={pos.x} cy={pos.y} r={ar} fill={vendor.mono.bg} stroke={vendor.mono.ring} strokeWidth=\"1\" />\n <text\n x={pos.x} y={pos.y} dy=\"0.34em\" textAnchor=\"middle\"\n fill={vendor.mono.text} fontSize={ar}\n fontFamily=\"monospace\" fontWeight=\"700\"\n >\n {vendor.initial}\n </text>\n </>\n );\n }\n // Round 106 (issue #83): hue keyed to the prefix group,\n // not the full alias — every 通信* node shares one color.\n const c = aliasAvatarColors(groupKeys[session.alias] || session.alias);\n return (\n <>\n <circle cx={pos.x} cy={pos.y} r={ar} fill={c.bg} stroke={c.ring} strokeWidth=\"1\" />\n <text\n x={pos.x}\n y={pos.y}\n dy=\"0.34em\"\n textAnchor=\"middle\"\n fill={c.text}\n fontSize={ar}\n fontFamily=\"monospace\"\n fontWeight=\"700\"\n >\n {aliasInitial(session.alias)}\n </text>\n </>\n );\n })()}\n {/* Issue #96: runtime badge — small corner glyph marking the\n execution shell (CLI / SDK / HTTP API). Sits bottom-right\n of the avatar; colours kept off the working/idle/offline\n status hues. Absent when the node reports no runtime. */}\n {(() => {\n const rt = runtimeIdentity(session.runtime);\n if (!rt) return null;\n const br = isOnline ? 7 : 5.5;\n const bx = pos.x + radius * 0.72;\n const by = pos.y + radius * 0.72;\n const icon = br * 2 * 0.62;\n return (\n <g style={{ pointerEvents: 'none' }}>\n <circle cx={bx} cy={by} r={br} fill={pal.containerBg} stroke={rt.color} strokeWidth=\"1.5\" />\n <g transform={`translate(${bx - icon / 2} ${by - icon / 2}) scale(${icon / 24})`}>\n <path d={rt.iconPath} fill=\"none\" stroke={rt.color} strokeWidth=\"2.4\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </g>\n </g>\n );\n })()}\n {session.status === 'working' && (\n // working pulse — small dot just inside the status ring,\n // above the avatar text. Was a 18px horizontal bar at\n // y+11 which now collides with the avatar; the dot reads\n // as the same \"active\" cue without occluding the initial.\n <circle cx={pos.x} cy={pos.y - (radius - 6)} r=\"2.5\" fill={pal.flowParticle}>\n <animate attributeName=\"opacity\" values=\"1;0.25;1\" dur=\"1.1s\" repeatCount=\"indefinite\" />\n </circle>\n )}\n\n {/* Round 98 (issue #61): label rect 124px → 100px.\n Round 109/110 (Vincent P0): full opaque card below the\n density threshold / on hover / when zoomed; otherwise a\n lightweight plain-text alias that keeps every node\n labelled without an opaque box covering its neighbours. */}\n {showFullLabel ? (\n <g transform={`translate(${pos.x}, ${pos.y + radius + 22})`} style={{ pointerEvents: 'none' }}>\n <rect x=\"-50\" y=\"-14\" width=\"100\" height=\"42\" rx=\"6\" fill={pal.labelBox.fill} stroke={pal.labelBox.stroke} opacity={isLight ? 1 : 0.94} />\n <text x=\"0\" y=\"1\" textAnchor=\"middle\" fill={status.text} fontSize=\"12\" fontFamily=\"monospace\" fontWeight=\"700\">\n {truncate(session.alias, 12)}\n </text>\n <text x=\"0\" y=\"17\" textAnchor=\"middle\" fill={status.primary} fontSize=\"9\" fontFamily=\"monospace\">\n {status.label}{isOnline && sseCountFor != null ? ` sse:${sseCountFor}` : ''}\n </text>\n </g>\n ) : (\n <text\n x={pos.x}\n y={pos.y + radius + 14}\n textAnchor=\"middle\"\n fill={status.text}\n fontSize=\"10\"\n fontFamily=\"monospace\"\n fontWeight=\"700\"\n opacity={0.9}\n style={{ pointerEvents: 'none', paintOrder: 'stroke' }}\n stroke={pal.containerBg}\n strokeWidth=\"3\"\n >\n {truncate(session.alias, 10)}\n </text>\n )}\n </g>\n );\n })}\n\n </g>\n\n {/* #112: overlay panels (recent-signal + legend) render OUTSIDE the\n zoom/pan <g> so they stay fixed while the topology pans/zooms.\n They're sized + tucked into the top corners so every corner of\n each panel is >325px from the canvas centre — i.e. fully outside\n the outermost (offline) ring. No node on any ring can reach the\n corner triangles, so the panels never overlap a node, in ring\n OR grid layout (Vincent 4727 zero-overlap criterion). */}\n {/* latest flow labels */}\n <g transform=\"translate(16, 16)\">\n <rect x=\"0\" y=\"0\" width=\"230\" height=\"84\" rx=\"10\" fill={pal.legendBox.fill} stroke={pal.legendBox.stroke} opacity={isLight ? 0.97 : 0.92} />\n <text x=\"13\" y=\"21\" fill={pal.legendHeadline} fontSize=\"12\" fontFamily=\"monospace\" fontWeight=\"700\">recent signal</text>\n <text x=\"150\" y=\"21\" fill={pal.legendAccent} fontSize=\"10\" fontFamily=\"monospace\">{messages.length} msgs</text>\n {flowLinks.slice(0, 3).map((link, index) => (\n <text key={link.key} x=\"13\" y={38 + index * 16} fill={pal.legendText} fontSize=\"9\" fontFamily=\"monospace\">\n {truncate(link.from, 6)} {'->'} {truncate(link.to, 6)} / {link.count} / {truncate(link.content, 12)}\n </text>\n ))}\n </g>\n\n {/* legend */}\n <g transform=\"translate(760, 16)\">\n <rect x=\"0\" y=\"0\" width=\"224\" height=\"96\" rx=\"10\" fill={pal.legendBox.fill} stroke={pal.legendBox.stroke} opacity={isLight ? 0.97 : 0.92} />\n <circle cx=\"16\" cy=\"24\" r=\"5.5\" fill={isLight ? '#059669' : '#22c55e'} />\n <text x=\"30\" y=\"28\" fill={pal.legendText} fontSize=\"11\" fontFamily=\"monospace\">working node</text>\n <circle cx=\"16\" cy=\"48\" r=\"5.5\" fill={isLight ? '#0d9488' : '#2dd4bf'} />\n <text x=\"30\" y=\"52\" fill={pal.legendText} fontSize=\"11\" fontFamily=\"monospace\">online idle</text>\n <circle cx=\"16\" cy=\"72\" r=\"5.5\" fill={isLight ? '#94a3b8' : '#6b7280'} />\n <text x=\"30\" y=\"76\" fill={pal.legendText} fontSize=\"11\" fontFamily=\"monospace\">offline / no SSE</text>\n <path d=\"M140,72 Q164,48 196,72\" fill=\"none\" stroke={pal.flowEdge} strokeWidth=\"3\" markerEnd=\"url(#topo-arrow)\" />\n </g>\n </svg>\n\n {/* Round 103 (issue #81): zoom / pan / fullscreen controls — HTML\n overlay so they stay fixed while the SVG content transforms.\n Round 104: Vincent 实测 — the reset action used to be hidden\n behind the \"%\" label (looked like an indicator, not a button).\n Split into a plain % readout + an explicit reset button with\n its own icon + tooltip. */}\n <div className=\"absolute bottom-3 right-3 flex items-center gap-1.5 text-xs select-none\">\n {/* #113: node size — S / M / L segmented control (Vincent 4727). */}\n <div\n className=\"flex items-center rounded-md border overflow-hidden\"\n style={{ background: pal.legendBox.fill, borderColor: pal.containerBorder }}\n role=\"group\"\n aria-label=\"Node size\"\n >\n {([['S', 0.7], ['M', 0.84], ['L', 1]] as const).map(([lbl, v], idx) => (\n <button\n key={lbl}\n onClick={() => pickNodeScale(v)}\n aria-pressed={nodeScale === v}\n title={`Node size: ${lbl === 'S' ? 'small' : lbl === 'M' ? 'medium' : 'large'}`}\n className={`px-2 py-1 transition-colors ${idx > 0 ? 'border-l' : ''} ${nodeScale === v ? 'bg-cyan-500/15 text-cyan-300' : 'hover:bg-white/5'}`}\n style={{ color: nodeScale === v ? undefined : pal.legendText, borderColor: pal.containerBorder }}\n >\n {lbl}\n </button>\n ))}\n </div>\n <div\n className=\"flex items-center rounded-md border overflow-hidden\"\n style={{ background: pal.legendBox.fill, borderColor: pal.containerBorder }}\n >\n <button\n onClick={() => zoomBy(1 / 1.2)}\n className=\"px-2 py-1 hover:bg-white/5 transition-colors\"\n style={{ color: pal.legendText }}\n aria-label=\"Zoom out\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" aria-hidden><path d=\"M5 12h14\" /></svg>\n </button>\n <span\n className=\"px-2 py-1 tabular-nums border-x text-center\"\n style={{ color: pal.legendText, borderColor: pal.containerBorder, minWidth: 46 }}\n title=\"Current zoom level\"\n >\n {Math.round(view.zoom * 100)}%\n </span>\n <button\n onClick={() => zoomBy(1.2)}\n className=\"px-2 py-1 hover:bg-white/5 transition-colors\"\n style={{ color: pal.legendText }}\n aria-label=\"Zoom in\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" aria-hidden><path d=\"M12 5v14M5 12h14\" /></svg>\n </button>\n </div>\n <button\n onClick={resetView}\n className=\"p-1.5 rounded-md border hover:bg-white/5 transition-colors\"\n style={{ background: pal.legendBox.fill, borderColor: pal.containerBorder, color: pal.legendText }}\n aria-label=\"Reset view\"\n title=\"Reset zoom + pan (or double-click the canvas)\"\n >\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M3 12a9 9 0 1 0 9-9 9 9 0 0 0-6.4 2.6L3 8\" />\n <path d=\"M3 3v5h5\" />\n </svg>\n </button>\n <button\n onClick={toggleFullscreen}\n className=\"p-1.5 rounded-md border hover:bg-white/5 transition-colors\"\n style={{ background: pal.legendBox.fill, borderColor: pal.containerBorder, color: pal.legendText }}\n aria-label={isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'}\n title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}\n >\n {isFullscreen ? (\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M8 3v4a1 1 0 0 1-1 1H3M21 8h-4a1 1 0 0 1-1-1V3M3 16h4a1 1 0 0 1 1 1v4M16 21v-4a1 1 0 0 1 1-1h4\" />\n </svg>\n ) : (\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M3 8V5a2 2 0 0 1 2-2h3M21 8V5a2 2 0 0 0-2-2h-3M3 16v3a2 2 0 0 0 2 2h3M21 16v3a2 2 0 0 1-2 2h-3\" />\n </svg>\n )}\n </button>\n </div>\n\n {/* Issue #100/#106: draggable, resizable singleton chat popover.\n position:fixed so it floats above the page (overflow-hidden here\n doesn't clip fixed children). Rendered *inside* the container so\n that when the graph goes fullscreen (#81) the popover joins the\n fullscreen subtree and stays visible — a sibling render would be\n outside the fullscreened element and disappear. */}\n {chatAlias && (\n <ChatPopover alias={chatAlias} onClose={() => setChatAlias(null)} />\n )}\n </div>\n </section>\n );\n}\n","'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { AliasAvatar } from './AliasAvatar';\nimport { TaskChatPanel } from './TaskChatPanel';\n\ninterface ChatPopoverProps {\n /** Node alias to chat with. Changing it switches the conversation. */\n alias: string;\n onClose: () => void;\n}\n\nconst MAX_W = 380;\nconst MAX_H = 520;\nconst MIN_W = 300;\nconst MIN_H = 320;\nconst MARGIN = 16;\nconst MOBILE_BP = 640;\n\n/**\n * Issue #100: a floating, draggable chat window opened by clicking a node\n * avatar in the topology graph. Singleton — the parent (TopoGraph) keeps a\n * single `chatAlias`, so clicking another node just swaps `alias` here and\n * the conversation switches in place.\n *\n * Issue #106: a bottom-right handle resizes the window (drag to change w/h,\n * clamped to MIN_W/MIN_H .. the viewport). Coexists with the header move-drag\n * and the close button — each interaction lives on a distinct element and\n * stops its own pointerdown from reaching the others.\n *\n * One consistent design across viewports: a floating draggable card sized to\n * fit (`min(380, vw-32) × min(520, vh-96)`). On a phone it ends up near\n * full-width, so it's docked low on open — the graph above stays visible, and\n * to chat with a different node you drag it down / tap an exposed avatar.\n *\n * The chat body reuses TaskChatPanel's `inline` mode — send / SSE-receive /\n * history are already solved there; this component only adds the floating\n * shell + drag/resize behaviour.\n */\nexport function ChatPopover({ alias, onClose }: ChatPopoverProps) {\n // Position + size are resolved on mount (SSR-safe defaults here).\n const [pos, setPos] = useState({ x: 0, y: 0 });\n const [size, setSize] = useState({ w: MAX_W, h: MAX_H });\n const dragRef = useRef<{ active: boolean; startX: number; startY: number; baseX: number; baseY: number }>({\n active: false, startX: 0, startY: 0, baseX: 0, baseY: 0,\n });\n const resizeRef = useRef<{ active: boolean; startX: number; startY: number; baseW: number; baseH: number }>({\n active: false, startX: 0, startY: 0, baseW: 0, baseH: 0,\n });\n\n const clamp = useCallback((x: number, y: number, w: number, h: number) => {\n const maxX = Math.max(MARGIN, window.innerWidth - w - MARGIN);\n const maxY = Math.max(MARGIN, window.innerHeight - h - MARGIN);\n return {\n x: Math.min(Math.max(MARGIN, x), maxX),\n y: Math.min(Math.max(MARGIN, y), maxY),\n };\n }, []);\n\n useEffect(() => {\n const place = () => {\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n const w = Math.min(MAX_W, vw - MARGIN * 2);\n const h = Math.min(MAX_H, vh - MARGIN * 6);\n setSize({ w, h });\n const mobile = vw < MOBILE_BP;\n // Desktop: top-right of the graph. Mobile: docked low so the graph\n // above stays visible — switch nodes by tapping an exposed avatar.\n const x = mobile ? MARGIN : vw - w - 24;\n const y = mobile ? vh - h - MARGIN : 96;\n setPos(clamp(x, y, w, h));\n };\n place();\n // Keep the popover on-screen if the window is resized.\n window.addEventListener('resize', place);\n return () => window.removeEventListener('resize', place);\n }, [clamp]);\n\n // Esc closes — matches the rest of the dashboard's overlay convention.\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [onClose]);\n\n const onPointerDown = (e: React.PointerEvent<HTMLDivElement>) => {\n if (e.button !== 0) return;\n (e.currentTarget as Element).setPointerCapture?.(e.pointerId);\n dragRef.current = { active: true, startX: e.clientX, startY: e.clientY, baseX: pos.x, baseY: pos.y };\n };\n const onPointerMove = (e: React.PointerEvent<HTMLDivElement>) => {\n const d = dragRef.current;\n if (!d.active) return;\n setPos(clamp(d.baseX + (e.clientX - d.startX), d.baseY + (e.clientY - d.startY), size.w, size.h));\n };\n const onPointerUp = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!dragRef.current.active) return;\n dragRef.current.active = false;\n try { (e.currentTarget as Element).releasePointerCapture?.(e.pointerId); } catch {}\n };\n\n // Resize from the bottom-right handle. stopPropagation keeps the header\n // move-drag out of it; the popover is top-left anchored so growing it can\n // only push the bottom/right edges, which we clamp to the viewport.\n const onResizeDown = (e: React.PointerEvent<HTMLDivElement>) => {\n if (e.button !== 0) return;\n e.stopPropagation();\n (e.currentTarget as Element).setPointerCapture?.(e.pointerId);\n resizeRef.current = { active: true, startX: e.clientX, startY: e.clientY, baseW: size.w, baseH: size.h };\n };\n const onResizeMove = (e: React.PointerEvent<HTMLDivElement>) => {\n const r = resizeRef.current;\n if (!r.active) return;\n e.stopPropagation();\n const maxW = Math.max(MIN_W, window.innerWidth - pos.x - MARGIN);\n const maxH = Math.max(MIN_H, window.innerHeight - pos.y - MARGIN);\n setSize({\n w: Math.min(maxW, Math.max(MIN_W, r.baseW + (e.clientX - r.startX))),\n h: Math.min(maxH, Math.max(MIN_H, r.baseH + (e.clientY - r.startY))),\n });\n };\n const onResizeUp = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!resizeRef.current.active) return;\n resizeRef.current.active = false;\n e.stopPropagation();\n try { (e.currentTarget as Element).releasePointerCapture?.(e.pointerId); } catch {}\n };\n\n return (\n <div\n className=\"fixed z-50 flex flex-col overflow-hidden rounded-xl border border-[var(--border)] bg-[var(--bg)] shadow-2xl shadow-black/60 anet-fade-in\"\n style={{ left: pos.x, top: pos.y, width: size.w, height: size.h }}\n role=\"dialog\"\n aria-label={`Chat with ${alias}`}\n >\n {/* Drag handle — the whole header bar moves the window. */}\n <div\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerCancel={onPointerUp}\n className=\"flex items-center justify-between px-3 py-2.5 border-b border-[var(--border)] bg-[var(--bg-secondary)] rounded-t-xl cursor-grab active:cursor-grabbing select-none touch-none\"\n >\n <div className=\"flex items-center gap-2.5 min-w-0\">\n <AliasAvatar alias={alias} size={28} />\n <div className=\"min-w-0\">\n <div className=\"text-sm font-semibold text-[var(--fg)] truncate\">{alias}</div>\n <div className=\"text-[10px] text-[var(--fg-muted)]\">Drag to move · Esc to close</div>\n </div>\n </div>\n <button\n onClick={onClose}\n // Without this the header's drag handler captures the pointer and\n // Chromium retargets the click to the header — the button never fires.\n onPointerDown={(e) => e.stopPropagation()}\n aria-label=\"Close chat\"\n className=\"text-[var(--fg-muted)] hover:text-[var(--fg)] p-1.5 rounded-lg hover:bg-[var(--bg-elevated)] shrink-0\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n {/* Chat body — TaskChatPanel inline mode owns send / SSE / history. */}\n <div className=\"flex-1 min-h-0\">\n <TaskChatPanel alias={alias} onClose={onClose} inline />\n </div>\n\n {/* Issue #106: bottom-right resize handle. */}\n <div\n onPointerDown={onResizeDown}\n onPointerMove={onResizeMove}\n onPointerUp={onResizeUp}\n onPointerCancel={onResizeUp}\n aria-label=\"Resize chat\"\n className=\"absolute bottom-0 right-0 w-5 h-5 cursor-nwse-resize touch-none z-10\"\n style={{ touchAction: 'none' }}\n >\n <svg className=\"absolute bottom-0.5 right-0.5 w-3 h-3 text-[var(--fg-dim)]\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" aria-hidden>\n <path d=\"M11 5L5 11M11 9L9 11\" />\n </svg>\n </div>\n </div>\n );\n}\n","/** Issue #96: node visual identity — model vendor + runtime.\n *\n * Single source for two orthogonal node dimensions:\n * - vendor : which model house powers the node (avatar body)\n * - runtime: which execution shell it runs in (corner badge)\n *\n * Both are driven by the server `model` / `runtime` fields added in\n * commhub-server 0.8.1-preview.0 (#96 Phase 1, commit 08482ef). Old nodes\n * report `model: null` / `runtime: null` and fall back gracefully — never a\n * broken image or blank avatar.\n *\n * Adding a vendor = one entry in VENDOR_RULES. Dropping a real logo file into\n * public/vendors/ + setting `logo` lights it up with zero render-code change;\n * until then a vendor-tinted monogram stands in (not a fake official logo).\n */\n\nexport interface VendorIdentity {\n id: string;\n label: string;\n /** Monogram fallback colours, used when `logo` is null. */\n mono: { bg: string; ring: string; text: string };\n /** 1-char monogram shown when there's no logo asset. */\n initial: string;\n /** Packaged logo asset path, or null → render the monogram instead. */\n logo: string | null;\n}\n\nconst UNKNOWN_VENDOR: VendorIdentity = {\n id: 'unknown',\n label: 'Unknown vendor',\n mono: { bg: 'hsl(220 10% 26%)', ring: 'hsl(220 10% 46%)', text: 'hsl(220 14% 82%)' },\n initial: '?',\n logo: null,\n};\n\n// Ordered prefix rules — first match wins. `test` runs against a lowercased\n// model id. Keep the most specific prefixes first.\nconst VENDOR_RULES: Array<{ test: (m: string) => boolean; vendor: VendorIdentity }> = [\n {\n test: (m) => m.startsWith('intern'),\n vendor: {\n id: 'intern',\n label: '书生 · 上海 AI 实验室',\n mono: { bg: 'hsl(28 38% 24%)', ring: 'hsl(32 45% 52%)', text: 'hsl(34 60% 82%)' },\n initial: '书',\n // #79 shipped this asset — reuse it as the 书生 vendor logo.\n logo: '/intern_avatar.png',\n },\n },\n {\n test: (m) => m.startsWith('minimax'),\n vendor: {\n id: 'minimax',\n label: 'MiniMax',\n mono: { bg: 'hsl(18 50% 26%)', ring: 'hsl(18 65% 52%)', text: 'hsl(20 80% 82%)' },\n initial: 'M',\n logo: null, // → public/vendors/minimax.* when assets land\n },\n },\n {\n test: (m) => m.startsWith('claude'),\n vendor: {\n id: 'anthropic',\n label: 'Anthropic',\n mono: { bg: 'hsl(16 32% 26%)', ring: 'hsl(16 48% 54%)', text: 'hsl(18 60% 84%)' },\n initial: 'A',\n logo: null,\n },\n },\n {\n test: (m) => m.startsWith('gpt') || m.startsWith('codex') || m.startsWith('o1') || m.startsWith('o3') || m.startsWith('o4'),\n vendor: {\n id: 'openai',\n label: 'OpenAI',\n mono: { bg: 'hsl(165 26% 22%)', ring: 'hsl(165 40% 44%)', text: 'hsl(165 45% 80%)' },\n initial: 'O',\n logo: null,\n },\n },\n];\n\n/** Resolve a model id to its vendor identity. `null` / unmatched → UNKNOWN. */\nexport function vendorForModel(model: string | null | undefined): VendorIdentity {\n if (!model) return UNKNOWN_VENDOR;\n const m = model.toLowerCase();\n for (const rule of VENDOR_RULES) {\n if (rule.test(m)) return rule.vendor;\n }\n return UNKNOWN_VENDOR;\n}\n\nexport type Runtime = 'claude-code-cli' | 'codex-sdk' | 'claude-agent-sdk' | 'http-api';\n\nexport interface RuntimeIdentity {\n label: string;\n /** SVG path(s) drawn inside a 0..24 viewBox for the corner badge. */\n iconPath: string;\n /** Badge accent colour — kept clear of working/idle/offline status hues. */\n color: string;\n}\n\nconst RUNTIME_MAP: Record<Runtime, RuntimeIdentity> = {\n // terminal / CLI\n 'claude-code-cli': {\n label: 'Claude Code CLI',\n iconPath: 'M4 5h16v14H4z M7 9l3 3-3 3 M13 15h4',\n color: '#a78bfa',\n },\n // code-block / SDK\n 'codex-sdk': {\n label: 'Codex SDK',\n iconPath: 'M9 7l-5 5 5 5 M15 7l5 5-5 5',\n color: '#38bdf8',\n },\n // SDK, distinct hue from codex\n 'claude-agent-sdk': {\n label: 'Claude Agent SDK',\n iconPath: 'M4 7h16v10H4z M8 11h8 M8 14h5',\n color: '#34d399',\n },\n // cloud / API — non-resident process\n 'http-api': {\n label: 'HTTP API',\n iconPath: 'M7 18a4 4 0 010-8 5 5 0 019.6-1.3A3.5 3.5 0 0118 18z',\n color: '#fbbf24',\n },\n};\n\n/** Resolve a server runtime string to badge identity. Unknown → null. */\nexport function runtimeIdentity(runtime: string | null | undefined): RuntimeIdentity | null {\n if (!runtime) return null;\n return RUNTIME_MAP[runtime as Runtime] ?? null;\n}\n\n/** Compact one-line identity for hover / detail surfaces:\n * \"Anthropic · claude-opus-4 · Claude Code CLI\". Pieces with no data drop. */\nexport function identityLine(model: string | null | undefined, runtime: string | null | undefined): string {\n const v = vendorForModel(model);\n const r = runtimeIdentity(runtime);\n const parts: string[] = [];\n if (v.id !== 'unknown') parts.push(v.label);\n if (model) parts.push(model);\n if (r) parts.push(r.label);\n return parts.join(' · ');\n}\n","'use client';\n\nimport Link from 'next/link';\nimport { Session } from './types';\nimport { timeAgo } from './utils';\nimport { AliasAvatar } from './AliasAvatar';\n\ninterface AgentCardProps {\n session: Session;\n hasSse: boolean;\n sseCount: number;\n onChat?: (alias: string) => void;\n}\n\nconst STATUS_CONFIG: Record<string, { bg: string; text: string; dot: string; glow: string }> = {\n working: { bg: 'bg-green-900/30 border-green-800/30', text: 'text-green-300', dot: 'bg-green-500', glow: 'shadow-green-500/10' },\n idle: { bg: 'bg-cyan-900/30 border-cyan-800/30', text: 'text-cyan-300', dot: 'bg-cyan-400', glow: 'shadow-cyan-500/5' },\n blocked: { bg: 'bg-yellow-900/30 border-yellow-800/30', text: 'text-yellow-300', dot: 'bg-yellow-500', glow: '' },\n error: { bg: 'bg-red-900/30 border-red-800/30', text: 'text-red-300', dot: 'bg-red-500', glow: '' },\n};\n\nconst DEFAULT_STATUS = { bg: 'bg-gray-800/50 border-gray-700/30', text: 'text-gray-500', dot: 'bg-gray-500', glow: '' };\n\nexport function AgentCard({ session: s, hasSse, sseCount, onChat }: AgentCardProps) {\n const cfg = hasSse ? (STATUS_CONFIG[s.status] || DEFAULT_STATUS) : DEFAULT_STATUS;\n\n return (\n <Link\n href={`/node?alias=${encodeURIComponent(s.alias)}`}\n prefetch={false}\n className={`anet-agent-card group relative block rounded-xl border p-4 transition-all duration-300 cursor-pointer hover:-translate-y-0.5 ${\n hasSse\n ? `bg-[#111128] border-[#2a2a4a] hover:border-cyan-500/30 hover:shadow-lg ${cfg.glow}`\n : 'bg-[#0d0d1a] border-[#1a1a2a] opacity-40'\n }`}\n >\n {/* Header: avatar + name + status. Avatar carries the alias→hue map\n shared with Messages/Nodes/Tasks/Overview; the live status dot\n stays as a small pulse-capable indicator. */}\n <div className=\"flex items-center justify-between mb-3\">\n <div className=\"flex items-center gap-2 min-w-0\">\n <AliasAvatar alias={s.alias} size={22} />\n <span className=\"font-semibold text-white truncate text-sm\" title={s.alias}>{s.alias}</span>\n <span className={`inline-block w-1.5 h-1.5 rounded-full shrink-0 ${cfg.dot} ${hasSse && s.status === 'working' ? 'animate-pulse' : ''}`} />\n </div>\n <span className={`text-[11px] px-2 py-0.5 rounded-md border shrink-0 ${cfg.bg} ${cfg.text}`}>\n {hasSse ? s.status : 'offline'}\n </span>\n </div>\n\n {/* Agent type badge */}\n <div className=\"flex items-center gap-2 mb-3\">\n <span className=\"text-xs text-gray-600 bg-[#0a0a15] px-2 py-0.5 rounded border border-[#1a1a2a]\">\n {s.agent || 'unknown'}\n </span>\n {hasSse && (\n <span className=\"text-[10px] text-green-500\">SSE:{sseCount}</span>\n )}\n </div>\n\n {/* Task */}\n {s.task ? (\n <div className=\"text-xs text-gray-400 bg-[#0a0a15] rounded-lg px-3 py-2 border border-[#1a1a2a] line-clamp-2\" title={s.task}>\n {s.task}\n </div>\n ) : (\n <div className=\"text-xs text-gray-700 italic\">No active task</div>\n )}\n\n {/* Progress bar */}\n {s.progress > 0 && (\n <div className=\"mt-3\">\n <div className=\"flex justify-between text-[10px] mb-1\">\n <span className=\"text-gray-600\">Progress</span>\n <span className={cfg.text}>{s.progress}%</span>\n </div>\n <div className=\"w-full bg-gray-800 rounded-full h-1.5 overflow-hidden\">\n <div\n className={`h-1.5 rounded-full transition-all duration-700 ${s.status === 'working' ? 'bg-green-500' : 'bg-cyan-500'}`}\n style={{ width: `${Math.min(s.progress, 100)}%` }}\n />\n </div>\n </div>\n )}\n\n {/* Footer: time + chat + hover chevron affordance (round 44).\n The card is a <Link> so it's clickable everywhere, but with no\n visible cue users may not realise. Chevron appears on hover and\n slides right ~2px for a \"drill in\" hint. */}\n <div className=\"mt-3 flex justify-between items-center text-[10px] text-gray-600\">\n <span className=\"truncate\" title={s.server || ''}>{s.server || '--'}</span>\n <div className=\"flex items-center gap-2\">\n {onChat && hasSse && (\n <button\n onClick={e => { e.preventDefault(); e.stopPropagation(); onChat(s.alias); }}\n className=\"text-cyan-400 hover:text-cyan-300 px-1.5 py-0.5 rounded border border-cyan-500/20 hover:bg-cyan-500/10 transition-colors\"\n >\n Chat\n </button>\n )}\n <span>{timeAgo(s.updated_at)}</span>\n <svg\n aria-hidden\n className=\"w-3 h-3 text-gray-700 opacity-0 -translate-x-1 group-hover:opacity-100 group-hover:translate-x-0 transition-all duration-200\"\n fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"\n >\n <path d=\"M9 18l6-6-6-6\" />\n </svg>\n </div>\n </div>\n </Link>\n );\n}\n","'use client';\n\nimport { InboxMessage } from './types';\nimport { AliasAvatar } from './AliasAvatar';\nimport { timeAgo, previewContent } from './utils';\n\ninterface InboxPanelProps {\n messages: InboxMessage[];\n}\n\nexport function InboxPanel({ messages }: InboxPanelProps) {\n if (messages.length === 0) return null;\n\n return (\n <div className=\"mt-8\">\n <h2 className=\"text-lg font-semibold text-white mb-3 flex items-center gap-2\">\n <span className=\"text-gray-500\">Inbox</span>\n <span className=\"text-xs bg-blue-900/30 text-blue-400 px-2 py-0.5 rounded-full border border-blue-800/30\">\n {messages.length}\n </span>\n </h2>\n <div className=\"space-y-2 max-h-96 overflow-y-auto pr-1 scrollbar-thin\">\n {messages.map(m => (\n <div key={m.id} className=\"bg-[#111128] border border-[#2a2a4a] rounded-lg px-4 py-3 text-sm transition-colors hover:border-[#3a3a5a]\">\n <div className=\"flex items-center gap-2 text-xs mb-1.5\">\n {m.from_session && <AliasAvatar alias={m.from_session} size={16} />}\n <span className=\"text-gray-200 font-medium truncate\">{m.from_session}</span>\n <span className=\"ml-auto text-gray-600 shrink-0\" title={m.created_at}>{timeAgo(m.created_at)}</span>\n </div>\n <div className=\"text-gray-300 leading-relaxed line-clamp-3\" title={m.content || ''}>{previewContent(m.content)}</div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","'use client';\n\n/**\n * Loading skeleton — mirrors the actual Overview layout structure so the\n * page doesn't appear to \"shift\" once data arrives. Uses the same\n * `anet-skeleton-pulse` rhythm as the brand pulse (1.6s opacity drift,\n * no scale, no blur, no glow) so the loading animation feels native to\n * the rest of the dashboard rather than a generic spinner.\n *\n * Bars are theme-aware: anet-skeleton-bar (existing CSS shim resolves this to\n * var(--bg-elevated) on light/mint), so light theme shows soft grey blocks\n * on white cards and dark theme shows lighter blocks on navy cards.\n */\nexport function LoadingSkeleton() {\n return (\n <div className=\"min-h-screen bg-[#0a0a1a] text-gray-100 p-4 sm:p-6 font-mono\">\n {/* KPI top strip — 4 cards matching StatsBar */}\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-3 mb-8 anet-skeleton-pulse\">\n {[1, 2, 3, 4].map(i => (\n <div key={i} className=\"rounded-xl border border-[#2a2a4a] bg-[#111128] px-4 py-3\">\n <Bar w=\"2.5rem\" h=\"1.75rem\" />\n <Bar w=\"3.5rem\" h=\"0.75rem\" className=\"mt-2\" />\n <Bar w=\"5rem\" h=\"0.625rem\" className=\"mt-1\" />\n </div>\n ))}\n </div>\n\n {/* Dispatch + UserBar row */}\n <div className=\"flex items-center gap-3 mb-3 anet-skeleton-pulse\">\n <Bar w=\"6rem\" h=\"2.5rem\" rounded=\"0.75rem\" />\n <div className=\"flex-1 rounded-lg border border-[#2a2a4a] bg-[#111128] px-4 py-2.5 flex items-center gap-3\">\n <div className=\"w-8 h-8 rounded-full anet-skeleton-bar\" />\n <div className=\"flex-1\">\n <Bar w=\"6rem\" h=\"0.875rem\" />\n <Bar w=\"10rem\" h=\"0.625rem\" className=\"mt-1\" />\n </div>\n </div>\n </div>\n\n {/* Config bar */}\n <div className=\"mb-6 rounded-lg border border-[#2a2a4a] bg-[#111128] px-4 py-3 anet-skeleton-pulse\">\n <Bar w=\"14rem\" h=\"0.875rem\" />\n </div>\n\n {/* Stat strip 3 cards */}\n <div className=\"grid grid-cols-3 gap-2 sm:gap-3 mb-3 anet-skeleton-pulse\">\n {[1, 2, 3].map(i => (\n <div key={i} className=\"rounded-xl border border-[#2a2a4a] bg-[#111128] px-3 py-3\">\n <Bar w=\"2rem\" h=\"1.25rem\" />\n <Bar w=\"2.5rem\" h=\"0.75rem\" className=\"mt-1\" />\n <Bar w=\"3.5rem\" h=\"0.625rem\" className=\"mt-px\" />\n </div>\n ))}\n </div>\n\n {/* Nav rail 3 cards */}\n <div className=\"grid grid-cols-3 gap-2 sm:gap-3 mb-6 anet-skeleton-pulse\">\n {[1, 2, 3].map(i => (\n <div key={i} className=\"rounded-xl border border-[#2a2a4a] bg-[#111128] px-3 py-2.5 flex items-center justify-center gap-2\">\n <div className=\"w-4 h-4 rounded anet-skeleton-bar\" />\n <Bar w=\"4rem\" h=\"0.75rem\" />\n </div>\n ))}\n </div>\n\n {/* Broadcast bar */}\n <div className=\"mb-6 flex gap-2 anet-skeleton-pulse\">\n <div className=\"flex-1 h-10 rounded-lg border border-[#2a2a4a] bg-[#111128]\" />\n <div className=\"w-28 h-10 rounded-lg anet-skeleton-bar\" />\n </div>\n\n {/* Agent card grid */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-3 sm:gap-4 anet-skeleton-pulse\">\n {[1, 2, 3, 4].map(i => (\n <div key={i} className=\"rounded-xl border border-[#2a2a4a] bg-[#111128] p-4\">\n <div className=\"flex items-center gap-2 mb-3\">\n <div className=\"w-2 h-2 rounded-full anet-skeleton-bar\" />\n <Bar w=\"6rem\" h=\"0.875rem\" />\n </div>\n <div className=\"space-y-2\">\n <Bar w=\"100%\" h=\"0.625rem\" />\n <Bar w=\"75%\" h=\"0.625rem\" />\n <Bar w=\"55%\" h=\"0.625rem\" />\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n\n/** Single shimmer bar — uses `anet-skeleton-bar` so theme-specific bar\n * color (dark navy on dark themes, mid-grey on light) overrides the\n * default. */\nfunction Bar({ w, h, rounded, className }: { w: string; h: string; rounded?: string; className?: string }) {\n return (\n <div\n className={`anet-skeleton-bar ${className || ''}`}\n style={{ width: w, height: h, borderRadius: rounded || '0.375rem' }}\n />\n );\n}\n\n// EmptyState export removed in 0.4.5 — replaced by EmptyState.tsx with\n// per-variant glyphs and a NodesEmptyState wrapper for the Overview\n// hint-aware behavior. See app/components/EmptyState.tsx.\n","'use client';\n\nimport { useEffect, useState } from 'react';\nimport { useNetworkId } from '../lib/network-context';\n\ninterface User {\n user_id: string;\n username: string;\n display_name: string;\n role: string;\n}\n\ninterface Network {\n network_id: string;\n network_name: string;\n description: string;\n}\n\ninterface AuthState {\n user: User | null;\n networks: Network[];\n currentNetwork: string;\n token: string;\n}\n\nexport function UserBar() {\n const { setNetworkId } = useNetworkId();\n const [auth, setAuth] = useState<AuthState>({ user: null, networks: [], currentNetwork: '', token: '' });\n const [showLogin, setShowLogin] = useState(false);\n const [username, setUsername] = useState('');\n const [password, setPassword] = useState('');\n const [loginError, setLoginError] = useState('');\n const [loginPending, setLoginPending] = useState(false);\n\n // Try to restore from sessionStorage\n useEffect(() => {\n const saved = sessionStorage.getItem('anet_v3_auth');\n if (saved) {\n try { setAuth(JSON.parse(saved)); } catch {}\n }\n }, []);\n\n const doAuth = async (action: 'login' | 'register') => {\n if (!username.trim() || !password.trim()) return;\n setLoginPending(true);\n setLoginError('');\n try {\n const res = await fetch('/api/hub/auth', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ action, username, password }),\n });\n const data = await res.json();\n if (!data.ok) { setLoginError(data.error || 'Failed'); setLoginPending(false); return; }\n\n // Fetch user details\n const meRes = await fetch(`/api/hub/auth?token=${data.token}&endpoint=/api/auth/me`);\n const meData = await meRes.json();\n\n const newAuth: AuthState = {\n user: data.user,\n networks: meData.networks || [],\n currentNetwork: meData.current_network?.network_id || meData.networks?.[0]?.network_id || '',\n token: data.token,\n };\n setAuth(newAuth);\n sessionStorage.setItem('anet_v3_auth', JSON.stringify(newAuth));\n setShowLogin(false);\n setUsername('');\n setPassword('');\n } catch { setLoginError('Connection failed'); }\n setLoginPending(false);\n };\n\n const logout = () => {\n setAuth({ user: null, networks: [], currentNetwork: '', token: '' });\n sessionStorage.removeItem('anet_v3_auth');\n };\n\n const [editing, setEditing] = useState(false);\n const [editName, setEditName] = useState('');\n const [editEmail, setEditEmail] = useState('');\n\n const updateProfile = async () => {\n try {\n const res = await fetch(`/api/hub/auth?token=${auth.token}&endpoint=/api/auth/me`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ action: 'update_profile', token: auth.token, display_name: editName, email: editEmail }),\n });\n // Use a direct PUT via a new proxy approach\n const putRes = await fetch('/api/hub/auth', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ action: 'update_profile', token: auth.token, display_name: editName, email: editEmail }),\n });\n const data = await putRes.json();\n if (data.ok && data.user) {\n const updated = { ...auth, user: data.user };\n setAuth(updated);\n sessionStorage.setItem('anet_v3_auth', JSON.stringify(updated));\n setEditing(false);\n }\n } catch {}\n };\n\n // Don't show anything when not logged in — login page handles that\n if (!auth.user) return null;\n\n const initials = (auth.user.display_name || auth.user.username).slice(0, 2).toUpperCase();\n\n return (\n <div className=\"flex items-center justify-between bg-[#111128] border border-[#2a2a4a] rounded-lg px-4 py-2.5 mb-4\">\n {/* User info */}\n <div className=\"flex items-center gap-3\">\n <div className=\"w-8 h-8 rounded-full bg-gradient-to-br from-cyan-500 to-blue-600 flex items-center justify-center text-xs font-bold text-white\">\n {initials}\n </div>\n <div>\n <div className=\"text-sm text-white font-medium\">{auth.user.display_name || auth.user.username}</div>\n <div className=\"text-[10px] text-gray-500\">{auth.user.role} · {auth.user.user_id}</div>\n </div>\n </div>\n\n {/* Network switcher */}\n <div className=\"flex items-center gap-3\">\n {auth.networks.length > 0 && (\n <select\n value={auth.currentNetwork}\n onChange={e => {\n const updated = { ...auth, currentNetwork: e.target.value };\n setAuth(updated);\n setNetworkId(e.target.value);\n sessionStorage.setItem('anet_v3_auth', JSON.stringify(updated));\n }}\n className=\"bg-[#0a0a15] border border-[#2a2a4a] rounded px-2 py-1 text-xs text-white focus:outline-none\"\n >\n {auth.networks.map(n => (\n <option key={n.network_id} value={n.network_id}>{n.network_name}</option>\n ))}\n </select>\n )}\n <button onClick={() => { setEditName(auth.user?.display_name || ''); setEditEmail(''); setEditing(!editing); }}\n className=\"text-xs text-gray-500 hover:text-gray-300 whitespace-nowrap\"\n aria-label=\"Edit profile\">\n <span className=\"hidden sm:inline\">Edit</span>\n <svg className=\"sm:hidden w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.862 4.487z\" />\n </svg>\n </button>\n <button onClick={logout}\n className=\"text-xs text-gray-500 hover:text-gray-300 whitespace-nowrap\"\n aria-label=\"Sign out\">\n <span className=\"hidden sm:inline\">Sign out</span>\n <svg className=\"sm:hidden w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15m3 0l3-3m0 0l-3-3m3 3H9\" />\n </svg>\n </button>\n </div>\n {editing && (\n <div className=\"flex flex-wrap items-center gap-2 mt-2 pt-2 border-t border-[#2a2a4a]\">\n <input type=\"text\" value={editName} onChange={e => setEditName(e.target.value)} placeholder=\"Display name\"\n className=\"bg-[#0a0a15] border border-[#2a2a4a] rounded px-2 py-1 text-xs text-white placeholder-gray-600 focus:outline-none w-32\" />\n <input type=\"email\" value={editEmail} onChange={e => setEditEmail(e.target.value)} placeholder=\"Email\"\n className=\"bg-[#0a0a15] border border-[#2a2a4a] rounded px-2 py-1 text-xs text-white placeholder-gray-600 focus:outline-none w-40\" />\n <button onClick={updateProfile} className=\"px-2 py-1 bg-cyan-600 hover:bg-cyan-500 text-white text-xs rounded\">Save</button>\n </div>\n )}\n </div>\n );\n}\n","'use client';\n\nimport { useState } from 'react';\nimport { TaskChatPanel } from './TaskChatPanel';\n\ninterface CommandCenterProps {\n /** Currently open chat tabs */\n tabs: string[];\n activeTab: string;\n onOpenTab: (alias: string) => void;\n onCloseTab: (alias: string) => void;\n onSetActive: (alias: string) => void;\n onClose: () => void;\n}\n\n/**\n * Multi-tab chat panel for commanding multiple agents simultaneously.\n * Wraps TaskChatPanel with a tab bar for switching between agents.\n */\nexport function CommandCenter({ tabs, activeTab, onOpenTab, onCloseTab, onSetActive, onClose }: CommandCenterProps) {\n if (tabs.length === 0) return null;\n\n return (\n <>\n {/* Backdrop */}\n <div className=\"fixed inset-0 bg-black/30 z-40 lg:hidden\" onClick={onClose} />\n\n {/* Panel */}\n <div className=\"fixed top-0 right-0 h-full w-full lg:w-[500px] bg-[#0a0a1a] border-l border-[#2a2a4a] z-50 flex flex-col shadow-2xl shadow-black/60 animate-slide-in\">\n {/* Tab bar */}\n <div className=\"flex items-center border-b border-[#2a2a4a] bg-[#0d0d1a] overflow-x-auto\">\n <div className=\"flex-1 flex min-w-0\">\n {tabs.map(alias => (\n <button\n key={alias}\n onClick={() => onSetActive(alias)}\n className={`flex items-center gap-1.5 px-3 py-2.5 text-xs border-b-2 transition-colors shrink-0 ${\n activeTab === alias\n ? 'border-cyan-400 text-cyan-300 bg-cyan-500/5'\n : 'border-transparent text-gray-500 hover:text-gray-300'\n }`}\n >\n <div className={`w-2 h-2 rounded-full ${activeTab === alias ? 'bg-cyan-400' : 'bg-gray-600'}`} />\n <span className=\"max-w-[80px] truncate\">{alias}</span>\n <button\n onClick={e => { e.stopPropagation(); onCloseTab(alias); }}\n className=\"ml-1 text-gray-600 hover:text-gray-300 p-0.5\"\n >\n ×\n </button>\n </button>\n ))}\n </div>\n <button onClick={onClose} className=\"text-gray-500 hover:text-white px-3 py-2.5 shrink-0 border-l border-[#2a2a4a]\">\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n {/* Active chat - render all but only show active (preserves state) */}\n <div className=\"flex-1 relative overflow-hidden\">\n {tabs.map(alias => (\n <div key={alias} className={`absolute inset-0 ${activeTab === alias ? 'block' : 'hidden'}`}>\n <InlineChat alias={alias} />\n </div>\n ))}\n </div>\n </div>\n\n <style jsx global>{`\n @keyframes slide-in {\n from { transform: translateX(100%); }\n to { transform: translateX(0); }\n }\n .animate-slide-in {\n animation: slide-in 0.2s ease-out;\n }\n `}</style>\n </>\n );\n}\n\n/** Inline chat without the panel chrome (used inside CommandCenter tabs) */\nfunction InlineChat({ alias }: { alias: string }) {\n // Reuse TaskChatPanel's logic but render without the outer frame\n return <TaskChatPanel alias={alias} onClose={() => {}} inline />;\n}\n\n/**\n * Hook to manage multi-tab command center state.\n */\nexport function useCommandCenter() {\n const [tabs, setTabs] = useState<string[]>([]);\n const [activeTab, setActiveTab] = useState('');\n\n const openTab = (alias: string) => {\n setTabs(prev => prev.includes(alias) ? prev : [...prev, alias]);\n setActiveTab(alias);\n };\n\n const closeTab = (alias: string) => {\n setTabs(prev => {\n const next = prev.filter(t => t !== alias);\n if (activeTab === alias) setActiveTab(next[next.length - 1] || '');\n return next;\n });\n };\n\n const closeAll = () => {\n setTabs([]);\n setActiveTab('');\n };\n\n return { tabs, activeTab, openTab, closeTab, closeAll, setActiveTab };\n}\n","'use client';\n\nimport { useState } from 'react';\nimport type { Session } from './types';\nimport { AliasAvatar } from './AliasAvatar';\n\ninterface DispatchPanelProps {\n sessions: Session[];\n onClose: () => void;\n}\n\ninterface SendResult {\n alias: string;\n ok: boolean;\n error?: string;\n}\n\nexport function DispatchPanel({ sessions, onClose }: DispatchPanelProps) {\n const [selected, setSelected] = useState<Set<string>>(new Set());\n const [prompt, setPrompt] = useState('');\n const [priority, setPriority] = useState('normal');\n const [sending, setSending] = useState(false);\n const [results, setResults] = useState<SendResult[]>([]);\n const [filter, setFilter] = useState('');\n\n const onlineNodes = sessions.filter(s => s.status !== 'offline');\n const filtered = onlineNodes.filter(s =>\n !filter || s.alias.toLowerCase().includes(filter.toLowerCase()) || (s.agent || '').toLowerCase().includes(filter.toLowerCase())\n );\n\n const toggleNode = (alias: string) => {\n setSelected(prev => {\n const next = new Set(prev);\n if (next.has(alias)) next.delete(alias); else next.add(alias);\n return next;\n });\n };\n\n const selectAll = () => {\n if (selected.size === filtered.length) {\n setSelected(new Set());\n } else {\n setSelected(new Set(filtered.map(s => s.alias)));\n }\n };\n\n const dispatch = async () => {\n if (!prompt.trim() || selected.size === 0 || sending) return;\n setSending(true);\n setResults([]);\n\n const promises = [...selected].map(async alias => {\n try {\n const res = await fetch('/api/hub/send', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ alias, task: prompt, priority }),\n });\n const data = await res.json();\n return { alias, ok: !!data.ok, error: data.error };\n } catch (e) {\n return { alias, ok: false, error: 'send failed' };\n }\n });\n\n const res = await Promise.all(promises);\n setResults(res);\n setSending(false);\n };\n\n const successCount = results.filter(r => r.ok).length;\n\n return (\n <>\n <div className=\"fixed inset-0 bg-black/50 z-40 anet-fade-in\" onClick={onClose} />\n <div className=\"fixed inset-4 lg:inset-x-[15%] lg:inset-y-[5%] bg-[#0a0a1a] border border-[#2a2a4a] rounded-2xl z-50 flex flex-col shadow-2xl shadow-black/70 overflow-hidden anet-fade-in\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-[#2a2a4a] bg-[#0d0d1a]\">\n <div>\n <h2 className=\"text-lg font-bold text-white\">Dispatch Task</h2>\n <p className=\"text-xs text-gray-500 mt-0.5\">Send a task to one or more agents</p>\n </div>\n <button onClick={onClose} className=\"text-gray-500 hover:text-white p-1.5 rounded-lg hover:bg-[#1a1a2a]\">\n <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n <div className=\"flex-1 flex flex-col lg:flex-row overflow-hidden\">\n {/* Left: Node selection */}\n <div className=\"lg:w-[280px] border-b lg:border-b-0 lg:border-r border-[#2a2a4a] flex flex-col\">\n <div className=\"px-4 py-3 border-b border-[#2a2a4a]\">\n <input\n type=\"text\" value={filter} onChange={e => setFilter(e.target.value)}\n placeholder=\"Filter agents...\"\n className=\"w-full bg-[#111128] border border-[#2a2a4a] rounded-lg px-3 py-2 text-xs text-white placeholder-gray-600 focus:border-cyan-500/40 focus:outline-none\"\n />\n <div className=\"flex items-center justify-between mt-2\">\n <button onClick={selectAll} className=\"text-[10px] text-cyan-400 hover:text-cyan-300\">\n {selected.size === filtered.length ? 'Deselect all' : `Select all (${filtered.length})`}\n </button>\n <span className=\"text-[10px] text-gray-600\">{selected.size} selected</span>\n </div>\n </div>\n <div className=\"flex-1 overflow-y-auto px-2 py-2 space-y-0.5 max-h-[200px] lg:max-h-none\">\n {filtered.map(s => (\n <button key={s.alias} onClick={() => toggleNode(s.alias)}\n className={`w-full flex items-center gap-2 px-3 py-2 rounded-lg text-xs text-left transition-colors ${\n selected.has(s.alias) ? 'bg-cyan-500/10 text-cyan-300 border border-cyan-500/20' : 'text-gray-400 hover:bg-[#1a1a2a]'\n }`}>\n <AliasAvatar alias={s.alias} size={16} />\n <div className={`w-1.5 h-1.5 rounded-full shrink-0 ${s.status === 'working' ? 'bg-green-400' : s.status === 'idle' ? 'bg-cyan-400' : 'bg-gray-500'}`} />\n <span className=\"truncate flex-1\">{s.alias}</span>\n <span className=\"text-[9px] text-gray-600\">{s.agent || '--'}</span>\n </button>\n ))}\n {filtered.length === 0 && <div className=\"text-center text-xs text-gray-600 py-4\">No online agents</div>}\n </div>\n </div>\n\n {/* Right: Prompt + Send */}\n <div className=\"flex-1 flex flex-col\">\n <div className=\"flex-1 px-6 py-4 flex flex-col\">\n <label className=\"text-xs text-gray-500 uppercase mb-2\">Task Prompt</label>\n <textarea\n value={prompt} onChange={e => setPrompt(e.target.value)}\n placeholder=\"Enter the task you want to dispatch...\"\n className=\"flex-1 min-h-[120px] bg-[#111128] border border-[#2a2a4a] rounded-xl px-4 py-3 text-sm text-white placeholder-gray-600 focus:border-cyan-500/40 focus:outline-none resize-none\"\n />\n\n <div className=\"flex items-center gap-3 mt-4\">\n <select value={priority} onChange={e => setPriority(e.target.value)}\n className=\"bg-[#111128] border border-[#2a2a4a] rounded-lg px-3 py-2 text-xs text-white focus:outline-none\">\n <option value=\"normal\">Normal priority</option>\n <option value=\"high\">High priority</option>\n <option value=\"low\">Low priority</option>\n </select>\n\n <div className=\"flex-1\" />\n\n <button onClick={dispatch} disabled={sending || !prompt.trim() || selected.size === 0}\n className=\"px-6 py-2.5 bg-gradient-to-r from-cyan-600 to-blue-600 hover:from-cyan-500 hover:to-blue-500 disabled:from-gray-800 disabled:to-gray-800 disabled:text-gray-600 text-white text-sm font-medium rounded-xl transition-all shadow-lg shadow-cyan-500/10 disabled:shadow-none active:scale-95\">\n {sending ? (\n <span className=\"flex items-center gap-2\">\n <span className=\"w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin\" />\n Sending...\n </span>\n ) : (\n `Dispatch to ${selected.size} agent${selected.size > 1 ? 's' : ''}`\n )}\n </button>\n </div>\n </div>\n\n {/* Results */}\n {results.length > 0 && (\n <div className=\"px-6 py-3 border-t border-[#2a2a4a] bg-[#0d0d1a]\">\n <div className=\"text-xs text-gray-500 mb-2\">\n {successCount}/{results.length} dispatched successfully\n </div>\n <div className=\"flex flex-wrap gap-1.5\">\n {results.map(r => (\n <span key={r.alias} className={`flex items-center gap-1.5 text-[10px] pl-1 pr-2 py-0.5 rounded-full border ${\n r.ok ? 'text-green-300 border-green-500/20 bg-green-500/5' : 'text-red-300 border-red-500/20 bg-red-500/5'\n }`}>\n <AliasAvatar alias={r.alias} size={14} />\n <span>{r.alias}</span>\n <span aria-hidden>{r.ok ? '✓' : r.error || '✗'}</span>\n </span>\n ))}\n </div>\n </div>\n )}\n </div>\n </div>\n </div>\n </>\n );\n}\n"],"names":["React","_interopDefaultLegacy","e","React__default","_defineProperties","target","props","i","length","descriptor","enumerable","configurable","writable","Object","defineProperty","key","_createClass","Constructor","protoProps","staticProps","prototype","isProd","process","env","isString","o","toString","call","StyleSheet","param","ref","_name","name","_optimizeForSpeed","optimizeForSpeed","invariant$1","_deletedRulePlaceholder","_serverSheet","undefined","_tags","_injected","_rulesCount","node","document","querySelector","_nonce","_proto","setOptimizeForSpeed","bool","flush","inject","isOptimizeForSpeed","_this","cssRules","insertRule","rule","index","cssText","push","deleteRule","getSheetForTag","tag","sheet","styleSheets","ownerNode","getSheet","insertionPoint","replaceRule","trim","error","console","warn","makeStyleTag","cssString","relativeToTag","createElement","setAttribute","type","appendChild","createTextNode","head","getElementsByTagName","insertBefore","get","condition","message","Error","hash","str","_$hash","charCodeAt","stringHash","sanitize","replace","cache","computeId","baseId","propsToString","String","computeSelector","id","css","selectoPlaceholderRegexp","idcss","mapRulesToStyle","options","map","args","nonce","dangerouslySetInnerHTML","__html","StyleSheetRegistry","_styleSheet","styleSheet","_sheet","_fromServer","_indices","_instancesCounts","add","Array","isArray","children","getIdAndRules","styleId","rules","indices","filter","remove","invariant","tagFromServer","parentNode","removeChild","forEach","update","nextProps","fromServer","keys","concat","join","Boolean","styles","dynamic","selectFromServer","elements","slice","querySelectorAll","reduce","acc","element","StyleSheetContext","createContext","displayName","createStyleRegistry","StyleRegistry","configuredRegistry","registry","rootRegistry","useContext","useState","Provider","value","useStyleRegistry","useInsertionEffect","useLayoutEffect","defaultRegistry","JSXStyle","info","tagInfo","exports","style","module","StatsBar","online","working","total","version","uptime","onlinePercent","Math","round","fleetEmpty","className","StatCard","label","sub","color","accent","border","accentKey","split"],"mappings":"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","ignoreList":[0,1]}
|
|
1
|
+
{"version":3,"sources":["../../../../../agent-network-dashboard/node_modules/styled-jsx/dist/index/index.js","../../../../../agent-network-dashboard/node_modules/styled-jsx/style.js","../../../../../agent-network-dashboard/app/page.tsx","../../../../../agent-network-dashboard/app/components/StatsBar.tsx","../../../../../agent-network-dashboard/app/components/BroadcastBar.tsx","../../../../../agent-network-dashboard/app/components/TopoGraph.tsx","../../../../../agent-network-dashboard/app/components/ChatPopover.tsx","../../../../../agent-network-dashboard/app/lib/vendorIdentity.ts","../../../../../agent-network-dashboard/app/components/AgentCard.tsx","../../../../../agent-network-dashboard/app/components/InboxPanel.tsx","../../../../../agent-network-dashboard/app/components/LoadingSkeleton.tsx","../../../../../agent-network-dashboard/app/components/UserBar.tsx","../../../../../agent-network-dashboard/app/components/CommandCenter.tsx","../../../../../agent-network-dashboard/app/components/DispatchPanel.tsx"],"sourcesContent":["require('client-only');\nvar React = require('react');\n\nfunction _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }\n\nvar React__default = /*#__PURE__*/_interopDefaultLegacy(React);\n\n/*\nBased on Glamor's sheet\nhttps://github.com/threepointone/glamor/blob/667b480d31b3721a905021b26e1290ce92ca2879/src/sheet.js\n*/ function _defineProperties(target, props) {\n for(var i = 0; i < props.length; i++){\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n}\nfunction _createClass(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n return Constructor;\n}\nvar isProd = typeof process !== \"undefined\" && process.env && process.env.NODE_ENV === \"production\";\nvar isString = function(o) {\n return Object.prototype.toString.call(o) === \"[object String]\";\n};\nvar StyleSheet = /*#__PURE__*/ function() {\n function StyleSheet(param) {\n var ref = param === void 0 ? {} : param, _name = ref.name, name = _name === void 0 ? \"stylesheet\" : _name, _optimizeForSpeed = ref.optimizeForSpeed, optimizeForSpeed = _optimizeForSpeed === void 0 ? isProd : _optimizeForSpeed;\n invariant$1(isString(name), \"`name` must be a string\");\n this._name = name;\n this._deletedRulePlaceholder = \"#\" + name + \"-deleted-rule____{}\";\n invariant$1(typeof optimizeForSpeed === \"boolean\", \"`optimizeForSpeed` must be a boolean\");\n this._optimizeForSpeed = optimizeForSpeed;\n this._serverSheet = undefined;\n this._tags = [];\n this._injected = false;\n this._rulesCount = 0;\n var node = typeof window !== \"undefined\" && document.querySelector('meta[property=\"csp-nonce\"]');\n this._nonce = node ? node.getAttribute(\"content\") : null;\n }\n var _proto = StyleSheet.prototype;\n _proto.setOptimizeForSpeed = function setOptimizeForSpeed(bool) {\n invariant$1(typeof bool === \"boolean\", \"`setOptimizeForSpeed` accepts a boolean\");\n invariant$1(this._rulesCount === 0, \"optimizeForSpeed cannot be when rules have already been inserted\");\n this.flush();\n this._optimizeForSpeed = bool;\n this.inject();\n };\n _proto.isOptimizeForSpeed = function isOptimizeForSpeed() {\n return this._optimizeForSpeed;\n };\n _proto.inject = function inject() {\n var _this = this;\n invariant$1(!this._injected, \"sheet already injected\");\n this._injected = true;\n if (typeof window !== \"undefined\" && this._optimizeForSpeed) {\n this._tags[0] = this.makeStyleTag(this._name);\n this._optimizeForSpeed = \"insertRule\" in this.getSheet();\n if (!this._optimizeForSpeed) {\n if (!isProd) {\n console.warn(\"StyleSheet: optimizeForSpeed mode not supported falling back to standard mode.\");\n }\n this.flush();\n this._injected = true;\n }\n return;\n }\n this._serverSheet = {\n cssRules: [],\n insertRule: function(rule, index) {\n if (typeof index === \"number\") {\n _this._serverSheet.cssRules[index] = {\n cssText: rule\n };\n } else {\n _this._serverSheet.cssRules.push({\n cssText: rule\n });\n }\n return index;\n },\n deleteRule: function(index) {\n _this._serverSheet.cssRules[index] = null;\n }\n };\n };\n _proto.getSheetForTag = function getSheetForTag(tag) {\n if (tag.sheet) {\n return tag.sheet;\n }\n // this weirdness brought to you by firefox\n for(var i = 0; i < document.styleSheets.length; i++){\n if (document.styleSheets[i].ownerNode === tag) {\n return document.styleSheets[i];\n }\n }\n };\n _proto.getSheet = function getSheet() {\n return this.getSheetForTag(this._tags[this._tags.length - 1]);\n };\n _proto.insertRule = function insertRule(rule, index) {\n invariant$1(isString(rule), \"`insertRule` accepts only strings\");\n if (typeof window === \"undefined\") {\n if (typeof index !== \"number\") {\n index = this._serverSheet.cssRules.length;\n }\n this._serverSheet.insertRule(rule, index);\n return this._rulesCount++;\n }\n if (this._optimizeForSpeed) {\n var sheet = this.getSheet();\n if (typeof index !== \"number\") {\n index = sheet.cssRules.length;\n }\n // this weirdness for perf, and chrome's weird bug\n // https://stackoverflow.com/questions/20007992/chrome-suddenly-stopped-accepting-insertrule\n try {\n sheet.insertRule(rule, index);\n } catch (error) {\n if (!isProd) {\n console.warn(\"StyleSheet: illegal rule: \\n\\n\" + rule + \"\\n\\nSee https://stackoverflow.com/q/20007992 for more info\");\n }\n return -1;\n }\n } else {\n var insertionPoint = this._tags[index];\n this._tags.push(this.makeStyleTag(this._name, rule, insertionPoint));\n }\n return this._rulesCount++;\n };\n _proto.replaceRule = function replaceRule(index, rule) {\n if (this._optimizeForSpeed || typeof window === \"undefined\") {\n var sheet = typeof window !== \"undefined\" ? this.getSheet() : this._serverSheet;\n if (!rule.trim()) {\n rule = this._deletedRulePlaceholder;\n }\n if (!sheet.cssRules[index]) {\n // @TBD Should we throw an error?\n return index;\n }\n sheet.deleteRule(index);\n try {\n sheet.insertRule(rule, index);\n } catch (error) {\n if (!isProd) {\n console.warn(\"StyleSheet: illegal rule: \\n\\n\" + rule + \"\\n\\nSee https://stackoverflow.com/q/20007992 for more info\");\n }\n // In order to preserve the indices we insert a deleteRulePlaceholder\n sheet.insertRule(this._deletedRulePlaceholder, index);\n }\n } else {\n var tag = this._tags[index];\n invariant$1(tag, \"old rule at index `\" + index + \"` not found\");\n tag.textContent = rule;\n }\n return index;\n };\n _proto.deleteRule = function deleteRule(index) {\n if (typeof window === \"undefined\") {\n this._serverSheet.deleteRule(index);\n return;\n }\n if (this._optimizeForSpeed) {\n this.replaceRule(index, \"\");\n } else {\n var tag = this._tags[index];\n invariant$1(tag, \"rule at index `\" + index + \"` not found\");\n tag.parentNode.removeChild(tag);\n this._tags[index] = null;\n }\n };\n _proto.flush = function flush() {\n this._injected = false;\n this._rulesCount = 0;\n if (typeof window !== \"undefined\") {\n this._tags.forEach(function(tag) {\n return tag && tag.parentNode.removeChild(tag);\n });\n this._tags = [];\n } else {\n // simpler on server\n this._serverSheet.cssRules = [];\n }\n };\n _proto.cssRules = function cssRules() {\n var _this = this;\n if (typeof window === \"undefined\") {\n return this._serverSheet.cssRules;\n }\n return this._tags.reduce(function(rules, tag) {\n if (tag) {\n rules = rules.concat(Array.prototype.map.call(_this.getSheetForTag(tag).cssRules, function(rule) {\n return rule.cssText === _this._deletedRulePlaceholder ? null : rule;\n }));\n } else {\n rules.push(null);\n }\n return rules;\n }, []);\n };\n _proto.makeStyleTag = function makeStyleTag(name, cssString, relativeToTag) {\n if (cssString) {\n invariant$1(isString(cssString), \"makeStyleTag accepts only strings as second parameter\");\n }\n var tag = document.createElement(\"style\");\n if (this._nonce) tag.setAttribute(\"nonce\", this._nonce);\n tag.type = \"text/css\";\n tag.setAttribute(\"data-\" + name, \"\");\n if (cssString) {\n tag.appendChild(document.createTextNode(cssString));\n }\n var head = document.head || document.getElementsByTagName(\"head\")[0];\n if (relativeToTag) {\n head.insertBefore(tag, relativeToTag);\n } else {\n head.appendChild(tag);\n }\n return tag;\n };\n _createClass(StyleSheet, [\n {\n key: \"length\",\n get: function get() {\n return this._rulesCount;\n }\n }\n ]);\n return StyleSheet;\n}();\nfunction invariant$1(condition, message) {\n if (!condition) {\n throw new Error(\"StyleSheet: \" + message + \".\");\n }\n}\n\nfunction hash(str) {\n var _$hash = 5381, i = str.length;\n while(i){\n _$hash = _$hash * 33 ^ str.charCodeAt(--i);\n }\n /* JavaScript does bitwise operations (like XOR, above) on 32-bit signed\n * integers. Since we want the results to be always positive, convert the\n * signed int to an unsigned by doing an unsigned bitshift. */ return _$hash >>> 0;\n}\nvar stringHash = hash;\n\nvar sanitize = function(rule) {\n return rule.replace(/\\/style/gi, \"\\\\/style\");\n};\nvar cache = {};\n/**\n * computeId\n *\n * Compute and memoize a jsx id from a basedId and optionally props.\n */ function computeId(baseId, props) {\n if (!props) {\n return \"jsx-\" + baseId;\n }\n var propsToString = String(props);\n var key = baseId + propsToString;\n if (!cache[key]) {\n cache[key] = \"jsx-\" + stringHash(baseId + \"-\" + propsToString);\n }\n return cache[key];\n}\n/**\n * computeSelector\n *\n * Compute and memoize dynamic selectors.\n */ function computeSelector(id, css) {\n var selectoPlaceholderRegexp = /__jsx-style-dynamic-selector/g;\n // Sanitize SSR-ed CSS.\n // Client side code doesn't need to be sanitized since we use\n // document.createTextNode (dev) and the CSSOM api sheet.insertRule (prod).\n if (typeof window === \"undefined\") {\n css = sanitize(css);\n }\n var idcss = id + css;\n if (!cache[idcss]) {\n cache[idcss] = css.replace(selectoPlaceholderRegexp, id);\n }\n return cache[idcss];\n}\n\nfunction mapRulesToStyle(cssRules, options) {\n if (options === void 0) options = {};\n return cssRules.map(function(args) {\n var id = args[0];\n var css = args[1];\n return /*#__PURE__*/ React__default[\"default\"].createElement(\"style\", {\n id: \"__\" + id,\n // Avoid warnings upon render with a key\n key: \"__\" + id,\n nonce: options.nonce ? options.nonce : undefined,\n dangerouslySetInnerHTML: {\n __html: css\n }\n });\n });\n}\nvar StyleSheetRegistry = /*#__PURE__*/ function() {\n function StyleSheetRegistry(param) {\n var ref = param === void 0 ? {} : param, _styleSheet = ref.styleSheet, styleSheet = _styleSheet === void 0 ? null : _styleSheet, _optimizeForSpeed = ref.optimizeForSpeed, optimizeForSpeed = _optimizeForSpeed === void 0 ? false : _optimizeForSpeed;\n this._sheet = styleSheet || new StyleSheet({\n name: \"styled-jsx\",\n optimizeForSpeed: optimizeForSpeed\n });\n this._sheet.inject();\n if (styleSheet && typeof optimizeForSpeed === \"boolean\") {\n this._sheet.setOptimizeForSpeed(optimizeForSpeed);\n this._optimizeForSpeed = this._sheet.isOptimizeForSpeed();\n }\n this._fromServer = undefined;\n this._indices = {};\n this._instancesCounts = {};\n }\n var _proto = StyleSheetRegistry.prototype;\n _proto.add = function add(props) {\n var _this = this;\n if (undefined === this._optimizeForSpeed) {\n this._optimizeForSpeed = Array.isArray(props.children);\n this._sheet.setOptimizeForSpeed(this._optimizeForSpeed);\n this._optimizeForSpeed = this._sheet.isOptimizeForSpeed();\n }\n if (typeof window !== \"undefined\" && !this._fromServer) {\n this._fromServer = this.selectFromServer();\n this._instancesCounts = Object.keys(this._fromServer).reduce(function(acc, tagName) {\n acc[tagName] = 0;\n return acc;\n }, {});\n }\n var ref = this.getIdAndRules(props), styleId = ref.styleId, rules = ref.rules;\n // Deduping: just increase the instances count.\n if (styleId in this._instancesCounts) {\n this._instancesCounts[styleId] += 1;\n return;\n }\n var indices = rules.map(function(rule) {\n return _this._sheet.insertRule(rule);\n })// Filter out invalid rules\n .filter(function(index) {\n return index !== -1;\n });\n this._indices[styleId] = indices;\n this._instancesCounts[styleId] = 1;\n };\n _proto.remove = function remove(props) {\n var _this = this;\n var styleId = this.getIdAndRules(props).styleId;\n invariant(styleId in this._instancesCounts, \"styleId: `\" + styleId + \"` not found\");\n this._instancesCounts[styleId] -= 1;\n if (this._instancesCounts[styleId] < 1) {\n var tagFromServer = this._fromServer && this._fromServer[styleId];\n if (tagFromServer) {\n tagFromServer.parentNode.removeChild(tagFromServer);\n delete this._fromServer[styleId];\n } else {\n this._indices[styleId].forEach(function(index) {\n return _this._sheet.deleteRule(index);\n });\n delete this._indices[styleId];\n }\n delete this._instancesCounts[styleId];\n }\n };\n _proto.update = function update(props, nextProps) {\n this.add(nextProps);\n this.remove(props);\n };\n _proto.flush = function flush() {\n this._sheet.flush();\n this._sheet.inject();\n this._fromServer = undefined;\n this._indices = {};\n this._instancesCounts = {};\n };\n _proto.cssRules = function cssRules() {\n var _this = this;\n var fromServer = this._fromServer ? Object.keys(this._fromServer).map(function(styleId) {\n return [\n styleId,\n _this._fromServer[styleId]\n ];\n }) : [];\n var cssRules = this._sheet.cssRules();\n return fromServer.concat(Object.keys(this._indices).map(function(styleId) {\n return [\n styleId,\n _this._indices[styleId].map(function(index) {\n return cssRules[index].cssText;\n }).join(_this._optimizeForSpeed ? \"\" : \"\\n\")\n ];\n })// filter out empty rules\n .filter(function(rule) {\n return Boolean(rule[1]);\n }));\n };\n _proto.styles = function styles(options) {\n return mapRulesToStyle(this.cssRules(), options);\n };\n _proto.getIdAndRules = function getIdAndRules(props) {\n var css = props.children, dynamic = props.dynamic, id = props.id;\n if (dynamic) {\n var styleId = computeId(id, dynamic);\n return {\n styleId: styleId,\n rules: Array.isArray(css) ? css.map(function(rule) {\n return computeSelector(styleId, rule);\n }) : [\n computeSelector(styleId, css)\n ]\n };\n }\n return {\n styleId: computeId(id),\n rules: Array.isArray(css) ? css : [\n css\n ]\n };\n };\n /**\n * selectFromServer\n *\n * Collects style tags from the document with id __jsx-XXX\n */ _proto.selectFromServer = function selectFromServer() {\n var elements = Array.prototype.slice.call(document.querySelectorAll('[id^=\"__jsx-\"]'));\n return elements.reduce(function(acc, element) {\n var id = element.id.slice(2);\n acc[id] = element;\n return acc;\n }, {});\n };\n return StyleSheetRegistry;\n}();\nfunction invariant(condition, message) {\n if (!condition) {\n throw new Error(\"StyleSheetRegistry: \" + message + \".\");\n }\n}\nvar StyleSheetContext = /*#__PURE__*/ React.createContext(null);\nStyleSheetContext.displayName = \"StyleSheetContext\";\nfunction createStyleRegistry() {\n return new StyleSheetRegistry();\n}\nfunction StyleRegistry(param) {\n var configuredRegistry = param.registry, children = param.children;\n var rootRegistry = React.useContext(StyleSheetContext);\n var ref = React.useState(function() {\n return rootRegistry || configuredRegistry || createStyleRegistry();\n }), registry = ref[0];\n return /*#__PURE__*/ React__default[\"default\"].createElement(StyleSheetContext.Provider, {\n value: registry\n }, children);\n}\nfunction useStyleRegistry() {\n return React.useContext(StyleSheetContext);\n}\n\n// Opt-into the new `useInsertionEffect` API in React 18, fallback to `useLayoutEffect`.\n// https://github.com/reactwg/react-18/discussions/110\nvar useInsertionEffect = React__default[\"default\"].useInsertionEffect || React__default[\"default\"].useLayoutEffect;\nvar defaultRegistry = typeof window !== \"undefined\" ? createStyleRegistry() : undefined;\nfunction JSXStyle(props) {\n var registry = defaultRegistry ? defaultRegistry : useStyleRegistry();\n // If `registry` does not exist, we do nothing here.\n if (!registry) {\n return null;\n }\n if (typeof window === \"undefined\") {\n registry.add(props);\n return null;\n }\n useInsertionEffect(function() {\n registry.add(props);\n return function() {\n registry.remove(props);\n };\n // props.children can be string[], will be striped since id is identical\n }, [\n props.id,\n String(props.dynamic)\n ]);\n return null;\n}\nJSXStyle.dynamic = function(info) {\n return info.map(function(tagInfo) {\n var baseId = tagInfo[0];\n var props = tagInfo[1];\n return computeId(baseId, props);\n }).join(\" \");\n};\n\nexports.StyleRegistry = StyleRegistry;\nexports.createStyleRegistry = createStyleRegistry;\nexports.style = JSXStyle;\nexports.useStyleRegistry = useStyleRegistry;\n","module.exports = require('./dist/index').style\n","'use client';\n\nimport { useEffect, useState } from 'react';\nimport Link from 'next/link';\nimport { formatUptime, previewContent } from './components/utils';\nimport { StatsBar } from './components/StatsBar';\nimport { BroadcastBar } from './components/BroadcastBar';\nimport { TopoGraph } from './components/TopoGraph';\nimport { AgentCard } from './components/AgentCard';\nimport { InboxPanel } from './components/InboxPanel';\nimport { LoadingSkeleton } from './components/LoadingSkeleton';\nimport { NodesEmptyState as EmptyState } from './components/EmptyState';\nimport { AliasAvatar } from './components/AliasAvatar';\nimport { STATUS_DOT_HEX, STATUS_CHIP_CLASS } from './lib/status';\nimport { UserBar } from './components/UserBar';\nimport { CommandCenter, useCommandCenter } from './components/CommandCenter';\nimport { DispatchPanel } from './components/DispatchPanel';\nimport { useSessions, useHealth, useAnetConfig, useTasks, useStats } from './lib/hooks';\nimport { useSSE } from './lib/useSSE';\nimport { InboxMessage } from './components/types';\nimport { useSWRConfig } from 'swr';\n\nexport default function Dashboard() {\n // Auto-upgrade: if no V3 auth in session, force re-login to get user token\n useEffect(() => {\n const hasV3 = sessionStorage.getItem('anet_v3_auth');\n if (!hasV3) {\n // Try silent re-auth: logout old cookie + redirect to login\n fetch('/api/auth/logout', { method: 'POST' }).catch(() => {});\n window.location.assign('/login');\n }\n }, []);\n\n const { sessions, hint: sessHint, error: sessError, isLoading } = useSessions();\n const { health } = useHealth();\n const { config: anetConfig } = useAnetConfig();\n const { tasks } = useTasks({ limit: '500' });\n const { stats } = useStats();\n const [showTopo, setShowTopo] = useState(typeof window !== 'undefined' && window.innerWidth >= 1024);\n const [showConfig, setShowConfig] = useState(false);\n const cmd = useCommandCenter();\n const [showDispatch, setShowDispatch] = useState(false);\n const [inbox, setInbox] = useState<InboxMessage[]>([]);\n const [agentFilter, setAgentFilter] = useState<'all' | 'working' | 'idle' | 'offline'>('all');\n // #84: last node.renamed event — passed to TopoGraph so an open chat\n // popover follows the rename instead of pointing at a dead alias. `ts`\n // makes the effect re-fire even when the same from/to repeats.\n const [renameSignal, setRenameSignal] = useState<{ from: string; to: string; ts: number } | null>(null);\n const { mutate } = useSWRConfig();\n\n // SSE: instant revalidation on CommHub events\n // Opt-out via NEXT_PUBLIC_DISABLE_SSE=1 — avoids HTTP/1.1 head-of-line blocking on navigation\n const sseEnabled = process.env.NEXT_PUBLIC_DISABLE_SSE !== '1';\n const { connected: sseConnected, supported: sseSupported } = useSSE({\n url: '/api/hub/events',\n enabled: sseEnabled,\n onEvent: (event) => {\n // #84 (RFC-010 §3.4): node.renamed — revalidate the session list so the\n // new alias propagates instantly (TopoGraph + node grid re-render, the\n // avatar hue recomputes as a pure fn of alias) instead of waiting for\n // the next 5s poll. The renamed node's history keeps the old alias\n // server-side, so the task list needs no revalidation here.\n if (event.type === 'node.renamed') {\n mutate('/api/hub/status');\n const d = event.data as { old_alias?: string; new_alias?: string } | undefined;\n if (d?.old_alias && d?.new_alias) {\n setRenameSignal({ from: d.old_alias, to: d.new_alias, ts: Date.now() });\n }\n return;\n }\n if (['new_task', 'new_message', 'new_reply', 'node_status_changed', 'broadcast'].includes(event.type)) {\n mutate('/api/hub/status');\n mutate((key: string) => typeof key === 'string' && key.startsWith('/api/hub/tasks'), undefined, { revalidate: true });\n }\n },\n });\n\n // Fetch inbox (not in SWR since it accumulates)\n useEffect(() => {\n const fetchInbox = () => {\n fetch('/api/hub/inbox').then(r => r.json()).then(data => {\n if (data.messages?.length) setInbox(prev => {\n const ids = new Set(prev.map(m => m.id));\n const newMsgs = data.messages.filter((m: { id: string }) => !ids.has(m.id));\n return [...newMsgs, ...prev].slice(0, 100);\n });\n }).catch(() => {});\n };\n fetchInbox();\n const interval = setInterval(fetchInbox, 10000);\n return () => clearInterval(interval);\n }, []);\n\n if (isLoading) return <LoadingSkeleton />;\n\n const sseSessions = health?.sse_sessions || {};\n // SSE keys are `network_id:alias` since v0.7+ (per-network scoping).\n // Fall back to alias-only for legacy hubs.\n const sseLookup = (s: { alias: string; network_id?: string }) =>\n (s.network_id ? sseSessions[`${s.network_id}:${s.alias}`] : undefined) ?? sseSessions[s.alias];\n // Online = status is not 'offline' (not just SSE-connected)\n const isOnline = (s: { alias: string; status: string; network_id?: string }) => s.status !== 'offline' || !!sseLookup(s);\n const online = sessions.filter(isOnline).length;\n const total = sessions.length;\n const working = sessions.filter(s => s.status === 'working').length;\n const uptime = health ? formatUptime(health.uptime) : '--';\n const version = health?.version || '--';\n const configHealthy = Boolean(anetConfig?.hub && anetConfig.tokenConfigured);\n const configSourceLabel =\n anetConfig?.source === 'file' ? 'Local config'\n : anetConfig?.source === 'runtime-env' ? 'Runtime env'\n : 'Config missing';\n\n // Task stats: prefer /api/stats, fallback to manual\n const taskStats: Record<string, number> = {};\n if (stats?.tasks?.by_status?.length) {\n for (const s of stats.tasks.by_status) {\n taskStats[s.status] = s.count;\n }\n } else {\n for (const t of tasks) {\n taskStats[t.status] = (taskStats[t.status] || 0) + 1;\n }\n }\n\n const sortedSessions = [...sessions].sort((a, b) => {\n const aOnline = isOnline(a) ? 1 : 0;\n const bOnline = isOnline(b) ? 1 : 0;\n if (aOnline !== bOnline) return bOnline - aOnline;\n const aWorking = a.status === 'working' ? 1 : 0;\n const bWorking = b.status === 'working' ? 1 : 0;\n return bWorking - aWorking;\n });\n\n /** Round 70: when the fleet is empty, the Overview reorders to lead with\n * the \"Spin up your first agent\" CTA and hides the Quick Navigation /\n * Nav rail / Broadcast bar that would otherwise occupy prime real estate\n * with zeros and dead-end links. Computed once, used as a gate below. */\n const fleetEmpty = sessions.length === 0 && !sessError;\n\n return (\n <div className=\"min-h-screen bg-[#0a0a1a] text-gray-100 p-4 sm:p-6 font-mono\">\n <div className=\"lg:ml-0 ml-10\">\n <StatsBar online={online} working={working} total={total} version={version} uptime={uptime} />\n </div>\n\n {/* Dispatch + User Bar — Dispatch hidden when fleet empty (nothing to\n dispatch to); UserBar still useful (account/sign-out menu). */}\n <div className=\"flex items-center gap-3 mb-4\">\n {!fleetEmpty && (\n <button onClick={() => setShowDispatch(true)}\n className=\"px-4 py-2 bg-gradient-to-r from-cyan-600 to-blue-600 hover:from-cyan-500 hover:to-blue-500 text-white text-sm font-medium rounded-xl shadow-lg shadow-cyan-500/10 transition-all active:scale-95 shrink-0\">\n ⚡ Dispatch\n </button>\n )}\n <div className=\"flex-1\"><UserBar /></div>\n </div>\n\n {/* anet config (collapsed by default) */}\n <section className=\"mb-6 rounded-lg border border-[#2a2a4a] bg-[#111128] px-4 py-3 shadow-lg shadow-black/20\">\n <button onClick={() => setShowConfig(!showConfig)} className=\"w-full flex items-center justify-between text-left\">\n <div className=\"flex items-center gap-2 text-xs\">\n <span className=\"uppercase text-gray-600\">Config</span>\n <span className={`w-2 h-2 rounded-full ${configHealthy ? 'bg-green-400' : 'bg-red-400'}`} />\n <span className=\"text-gray-500\">{configSourceLabel}</span>\n </div>\n <svg className={`w-4 h-4 text-gray-600 transition-transform ${showConfig ? 'rotate-180' : ''}`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </button>\n {showConfig && (\n <div className=\"mt-3 pt-3 border-t border-[#2a2a4a]\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"min-w-0\">\n <div className=\"text-gray-100 truncate text-sm\" title={anetConfig?.hub || undefined}>\n Hub: <span className={anetConfig?.hub ? 'text-cyan-300' : 'text-red-300'}>{anetConfig?.hub?.trim() || 'not configured'}</span>\n </div>\n </div>\n <div className=\"flex flex-wrap gap-2 text-xs\">\n <span className={`px-2.5 py-1 rounded-md border ${anetConfig?.tokenConfigured ? 'bg-blue-500/5 text-blue-300 border-blue-500/20' : 'bg-gray-500/5 text-gray-400 border-gray-500/20'}`}>\n Token: {anetConfig?.tokenPreview || 'not configured'}\n </span>\n </div>\n </div>\n {anetConfig?.error && <div className=\"mt-2 text-xs text-gray-600\">{anetConfig.error}</div>}\n </div>\n )}\n </section>\n\n {/* Task Status Stats */}\n {Object.keys(taskStats).length > 0 && (\n <section className=\"mb-6 rounded-lg border border-[#2a2a4a] bg-[#111128] px-4 py-3 shadow-lg shadow-black/20\">\n <div className=\"flex items-center justify-between mb-2\">\n <div className=\"text-xs uppercase text-gray-600\">Task Status</div>\n <Link href=\"/tasks\" prefetch={false} className=\"text-xs text-cyan-400 hover:text-cyan-300\">View all →</Link>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n {/* Round 69: order is \"hot first\" — active flow before terminal\n states — intentionally different from the lifecycle order on\n /tasks. Colors come from shared STATUS_CHIP_CLASS so a\n palette tweak in app/lib/status.ts updates here too.\n 'created' added in r69 (was missing — enum-coverage bug). */}\n {(['running', 'delivered', 'acked', 'replied', 'created', 'failed', 'cancelled', 'expired', 'closed'] as const)\n .filter((key) => taskStats[key])\n .map((key) => (\n <Link key={key} href={`/tasks?status=${key}`} prefetch={false} className={`px-2.5 py-1 rounded-md border text-xs ${STATUS_CHIP_CLASS[key]} hover:opacity-80 transition-opacity`}>\n {key}: {taskStats[key]}\n </Link>\n ))}\n </div>\n </section>\n )}\n\n {/* Quick Actions — split into two distinct intents:\n (1) Top: live stat cards (carry data, drill-in on click)\n (2) Bottom: pure nav rail (no number, icon + label)\n Round 24 — wrap both in a labelled block so the rhythm reads as\n \"here are the main jumps\" instead of two disconnected strips.\n Round 70 — entire Quick Nav + Nav rail + Broadcast + Recent\n Activity block is hidden when the fleet is empty so the\n onboarding CTA gets the page above the fold. */}\n {!fleetEmpty && <>\n <div className=\"text-[10px] uppercase tracking-[0.12em] text-gray-600 mb-2\">Quick navigation</div>\n <section className=\"mb-3 grid grid-cols-3 gap-2 sm:gap-3\">\n {(() => {\n // Build breakdown popover content per card. Pure data — pure CSS\n // popover (no JS state) wires the hover-show transition below.\n const idleCount = sessions.filter(s => isOnline(s) && s.status !== 'working').length;\n const offlineCount = total - online;\n const orderedStatuses = ['running', 'replied', 'failed', 'cancelled', 'expired', 'closed', 'created', 'delivered', 'acked'];\n const failedRecent = tasks.filter((t: { status: string }) => t.status === 'failed').length;\n\n const cards = [\n {\n href: '/nodes', label: 'Nodes',\n value: `${online}/${total}`,\n sub: `${total > 0 ? Math.round((online / total) * 100) : 0}% online`,\n color: 'text-green-400 border-green-500/20',\n popover: total === 0 ? null : [\n { k: 'working', v: working, dot: '', color: '#4ade80' },\n { k: 'idle', v: idleCount, dot: '', color: '#22d3ee' },\n { k: 'offline', v: offlineCount, dot: '', color: '#9ca3af' },\n ],\n },\n {\n href: '/tasks', label: 'Tasks',\n value: String(Object.values(taskStats).reduce((a, b) => a + b, 0) || 0),\n sub: 'all-time',\n color: 'text-cyan-400 border-cyan-500/20',\n popover: Object.keys(taskStats).length === 0 ? null\n : orderedStatuses\n .filter(s => taskStats[s])\n .map(s => {\n // Inline hex avoids Tailwind purging dynamic\n // `bg-${color}-400` class names.\n const hex = ({\n running: '#4ade80', replied: '#a78bfa', failed: '#f87171',\n cancelled: '#facc15', expired: '#fb923c', closed: '#9ca3af',\n created: '#9ca3af', delivered: '#60a5fa', acked: '#22d3ee',\n } as Record<string, string>)[s] || '#9ca3af';\n return { k: s, v: taskStats[s], dot: '', color: hex };\n }),\n },\n {\n href: '/tasks?status=failed', label: 'Failed',\n value: String(taskStats['failed'] || 0),\n sub: taskStats['failed'] ? 'needs review' : 'none',\n color: taskStats['failed'] ? 'text-red-400 border-red-500/25' : 'text-gray-500 border-gray-700/30',\n popover: !failedRecent ? [{ k: 'no failures yet', v: '', dot: '', color: '#4b5563' }]\n : [{ k: `${failedRecent} in current view`, v: '', dot: '', color: '#f87171' }],\n },\n ];\n\n return cards.map(a => (\n <Link\n key={a.href}\n href={a.href}\n prefetch={false}\n className={`anet-stat-link group relative rounded-xl border ${a.color} bg-[#111128] px-3 py-3 transition-all hover:-translate-y-px`}\n >\n <div className=\"flex items-baseline justify-between\">\n <div className={`text-xl font-semibold tabular-nums ${a.color.split(' ')[0]}`}>{a.value}</div>\n <div className=\"hidden sm:block text-[10px] text-gray-600 group-hover:text-gray-400 transition-colors\">View →</div>\n </div>\n <div className=\"text-[11px] text-gray-400 mt-0.5\">{a.label}</div>\n <div className=\"text-[10px] text-gray-600 mt-px\">{a.sub}</div>\n\n {/* Hover popover — CSS-only, restrained. Hidden on touch\n (no :hover) so mobile is unaffected. Positioned just\n below the card so it doesn't fight nav rail. */}\n {a.popover && a.popover.length > 0 && (\n <div className=\"anet-stat-popover hidden md:block pointer-events-none absolute left-2 right-2 top-full mt-1 z-20 rounded-lg border border-[#2a2a4a] bg-[#0d0d1a] shadow-lg shadow-black/30 px-3 py-2 opacity-0 translate-y-[-2px] group-hover:opacity-100 group-hover:translate-y-0 transition-all duration-150 delay-100\">\n <div className=\"text-[10px] text-gray-600 uppercase tracking-wider mb-1.5\">Breakdown</div>\n <ul className=\"space-y-1\">\n {a.popover.map(row => (\n <li key={row.k} className=\"flex items-center gap-2 text-[11px]\">\n <span\n className=\"inline-block w-1.5 h-1.5 rounded-full shrink-0\"\n style={{ backgroundColor: row.color }}\n aria-hidden\n />\n <span className=\"text-gray-400 capitalize\">{row.k}</span>\n {row.v !== '' && <span className=\"ml-auto text-gray-300 tabular-nums font-medium\">{row.v}</span>}\n </li>\n ))}\n </ul>\n </div>\n )}\n </Link>\n ));\n })()}\n </section>\n\n {/* Nav rail — pure navigation, icon + label, no data */}\n <section className=\"mb-6 grid grid-cols-3 gap-2 sm:gap-3\">\n {[\n { href: '/messages', label: 'Messages', icon: 'M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z' },\n { href: '/logs', label: 'Audit log', icon: 'M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z M14 2v6h6 M16 13H8 M16 17H8 M10 9H8' },\n { href: '/admin', label: 'Admin', icon: 'M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4z M6 21v-2a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v2' },\n ].map(a => (\n <Link key={a.href} href={a.href} prefetch={false}\n className=\"anet-nav-tile flex items-center justify-center gap-2 rounded-xl border border-[#2a2a4a] bg-[#111128] px-3 py-2.5 text-[12px] text-gray-400 hover:text-gray-200 transition-colors\">\n <svg className=\"w-4 h-4 shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d={a.icon} />\n </svg>\n <span>{a.label}</span>\n </Link>\n ))}\n </section>\n\n <BroadcastBar />\n\n {/* Recent Activity */}\n {tasks.length > 0 && (\n <section className=\"mb-6 bg-[#111128] border border-[#2a2a4a] rounded-xl p-4\">\n <div className=\"flex items-center justify-between mb-3\">\n <h2 className=\"text-sm font-semibold text-gray-300\">Recent Activity</h2>\n <Link href=\"/tasks\" className=\"text-xs text-cyan-400 hover:text-cyan-300\">All tasks →</Link>\n </div>\n <div className=\"space-y-2 max-h-40 overflow-y-auto\">\n {tasks.slice(0, 5).map((t: { task_id: string; from_name: string; to_name: string; status: string; content: string; created_at: string }) => (\n <div key={t.task_id} className=\"flex items-center gap-2 text-xs\">\n <span\n className=\"w-1.5 h-1.5 rounded-full shrink-0\"\n style={{ backgroundColor: STATUS_DOT_HEX[t.status] || '#6b7280' }}\n />\n {t.from_name && <AliasAvatar alias={t.from_name} size={14} />}\n <span className=\"text-gray-300 shrink-0 max-w-[20%] truncate\">{t.from_name || '?'}</span>\n <span className=\"text-gray-600\">→</span>\n {t.to_name && <AliasAvatar alias={t.to_name} size={14} />}\n <span className=\"text-gray-300 shrink-0 max-w-[20%] truncate\">{t.to_name || '?'}</span>\n <span className=\"text-gray-500 truncate flex-1\" title={t.content || ''}>{previewContent(t.content).slice(0, 60)}</span>\n <span className={`shrink-0 px-1.5 py-0.5 rounded text-[10px] border ${\n STATUS_CHIP_CLASS[t.status] || 'text-gray-500 border-gray-700/30'\n }`}>{t.status}</span>\n </div>\n ))}\n </div>\n </section>\n )}\n </>}\n\n {sessError && (\n <div className=\"bg-red-900/20 border border-red-800/40 text-red-300 px-4 py-3 rounded-lg mb-6 text-sm flex items-center justify-between\" role=\"alert\">\n <span>{String(sessError)}</span>\n <span className=\"text-gray-500 text-xs\">Check CommHub connection</span>\n </div>\n )}\n\n {sessions.length > 0 && (\n <div className=\"flex justify-center mb-4\">\n <button\n onClick={() => setShowTopo(!showTopo)}\n className=\"text-xs text-gray-500 hover:text-gray-300 border border-gray-700/50 px-4 py-1.5 rounded-lg transition-colors hover:border-gray-600 cursor-pointer\"\n >\n {showTopo ? 'Hide Topology' : 'Show Topology'}\n </button>\n </div>\n )}\n\n {/* Mobile hint when topo hidden */}\n {!showTopo && sessions.length > 0 && (\n <div className=\"lg:hidden text-center text-xs text-gray-600 mb-4\">\n Topology hidden on mobile for better readability\n </div>\n )}\n\n {showTopo && sessions.length > 0 && <TopoGraph sessions={sessions} sseSessions={sseSessions} renameSignal={renameSignal} />}\n\n {sessions.length === 0 && !sessError ? (\n <EmptyState\n hint={sessHint}\n taskHistoryCount={Object.values(taskStats).reduce((a, b) => a + b, 0)}\n />\n ) : (() => {\n const counts = {\n all: sortedSessions.length,\n working: sortedSessions.filter(s => isOnline(s) && s.status === 'working').length,\n idle: sortedSessions.filter(s => isOnline(s) && s.status !== 'working').length,\n offline: sortedSessions.filter(s => !isOnline(s)).length,\n };\n const filtered = sortedSessions.filter(s => {\n if (agentFilter === 'all') return true;\n if (agentFilter === 'offline') return !isOnline(s);\n if (agentFilter === 'working') return isOnline(s) && s.status === 'working';\n if (agentFilter === 'idle') return isOnline(s) && s.status !== 'working';\n return true;\n });\n // Filter chip color keyed to status (round 34): working=green, idle=cyan,\n // offline=gray, all=neutral. Inline hex dots avoid Tailwind v4 purge.\n const chips: { key: typeof agentFilter; label: string; dot?: string }[] = [\n { key: 'all', label: 'All' },\n { key: 'working', label: 'Working', dot: '#4ade80' },\n { key: 'idle', label: 'Idle', dot: '#22d3ee' },\n { key: 'offline', label: 'Offline', dot: '#6b7280' },\n ];\n return (\n <>\n <div className=\"mb-3 flex flex-wrap items-center gap-1\">\n {chips.map(c => (\n <button\n key={c.key}\n type=\"button\"\n onClick={() => setAgentFilter(c.key)}\n disabled={counts[c.key] === 0 && c.key !== 'all'}\n className={`flex items-center gap-1.5 rounded-md px-2.5 py-1 text-xs transition-colors disabled:opacity-30 disabled:cursor-not-allowed ${\n agentFilter === c.key\n ? 'bg-cyan-500/10 text-cyan-300 border border-cyan-500/30'\n : 'text-gray-500 hover:text-gray-200 hover:bg-[#1a1a2a] border border-transparent'\n }`}\n >\n {c.dot && <span aria-hidden className=\"inline-block w-1.5 h-1.5 rounded-full\" style={{ backgroundColor: c.dot }} />}\n <span>{c.label}</span>\n <span className={`text-[10px] tabular-nums ${agentFilter === c.key ? 'text-cyan-400' : 'text-gray-600'}`}>{counts[c.key]}</span>\n </button>\n ))}\n </div>\n {/* Round 48: previous breakpoints had `lg:grid-cols-2 xl:grid-cols-3`\n which kept lg (1024-1279px) at only 2 columns even though\n each AgentCard is fine ≥260px wide. With the sidebar (208px),\n main area at lg is ~816px so 3 cols at ~272px each fits.\n xl breakpoint auto-inherits lg=3 cols; 2xl bumps to 4. */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 gap-3 sm:gap-4\">\n {filtered.map(s => (\n <AgentCard key={s.alias} session={s} hasSse={isOnline(s)} sseCount={sseLookup(s) || 0} onChat={cmd.openTab} />\n ))}\n </div>\n {filtered.length === 0 && (\n <div className=\"mt-4 text-center text-xs text-gray-600\">\n No agents match \"{agentFilter}\" — <button onClick={() => setAgentFilter('all')} className=\"underline hover:text-gray-400\">Show all</button>\n </div>\n )}\n </>\n );\n })()}\n\n <InboxPanel messages={inbox} />\n\n {/* Round 111 (issue #82): dropped the license badge — \"trial (12d\n left)\" read like a paywall countdown on an open-source dashboard\n and Vincent flagged it as misleading more than once. The SSE /\n polling dot stays: it's a real connection-status indicator, not\n a sales surface. */}\n <div className=\"mt-8 text-center text-xs text-gray-600 flex items-center justify-center gap-2 flex-wrap\">\n {sseSupported && (\n <>\n <span className={`w-1.5 h-1.5 rounded-full ${sseConnected ? 'bg-green-400' : 'bg-gray-600'}`} />\n {sseConnected ? 'SSE live' : 'SWR polling'}\n </>\n )}\n </div>\n\n {/* Dispatch Panel */}\n {showDispatch && <DispatchPanel sessions={sessions} onClose={() => setShowDispatch(false)} />}\n\n {/* Command Center (multi-tab chat) */}\n {cmd.tabs.length > 0 && (\n <CommandCenter\n tabs={cmd.tabs}\n activeTab={cmd.activeTab}\n onOpenTab={cmd.openTab}\n onCloseTab={cmd.closeTab}\n onSetActive={cmd.setActiveTab}\n onClose={cmd.closeAll}\n />\n )}\n </div>\n );\n}\n","'use client';\n\ninterface StatsBarProps {\n online: number;\n working: number;\n total: number;\n version: string;\n uptime: string;\n}\n\nexport function StatsBar({ online, working, total, version, uptime }: StatsBarProps) {\n const onlinePercent = total > 0 ? Math.round((online / total) * 100) : 0;\n const fleetEmpty = total === 0;\n\n return (\n <div className={fleetEmpty ? 'mb-4' : 'mb-8'}>\n {/* Title row */}\n <div className=\"flex flex-wrap items-center gap-3 mb-4\">\n <h1 className=\"text-2xl font-bold text-white tracking-tight\">Agent Network</h1>\n <span className=\"text-xs text-gray-500\">\n CommHub {version} · {uptime}\n </span>\n </div>\n\n {fleetEmpty ? (\n /* Round 72: thin status strip replaces the 4-card grid when fleet\n is empty. Saves ~280px on mobile (CTA y=650 → ~370) and keeps\n the same data visible in a single inline row. */\n <div className=\"anet-stat-strip flex flex-wrap items-center gap-x-4 gap-y-1.5 text-xs text-gray-500 border-t border-b border-[#2a2a4a] py-2\">\n <span className=\"inline-flex items-center gap-1.5\">\n <span aria-hidden className=\"inline-block w-1.5 h-1.5 rounded-full bg-gray-600\" />\n <span className=\"text-gray-300 tabular-nums\">0</span> online\n </span>\n <span className=\"text-gray-700\">·</span>\n <span className=\"inline-flex items-center gap-1.5\">\n <span aria-hidden className=\"inline-block w-1.5 h-1.5 rounded-full bg-gray-600\" />\n <span className=\"text-gray-300 tabular-nums\">0</span> working\n </span>\n <span className=\"text-gray-700\">·</span>\n <span className=\"inline-flex items-center gap-1.5\">\n <span aria-hidden className=\"inline-block w-1.5 h-1.5 rounded-full bg-gray-600\" />\n <span className=\"text-gray-300 tabular-nums\">0</span> registered\n </span>\n </div>\n ) : (\n /* Populated state — full 4-card grid as before */\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-3\">\n <StatCard\n value={online}\n label=\"Online\"\n sub={`${onlinePercent}% of fleet`}\n color=\"text-green-400\"\n accent=\"from-green-500/20 to-green-500/0\"\n border=\"border-green-500/15\"\n />\n <StatCard\n value={working}\n label=\"Working\"\n sub={online > 0 ? `${Math.round((working / online) * 100)}% utilization` : '--'}\n color=\"text-cyan-400\"\n accent=\"from-cyan-500/20 to-cyan-500/0\"\n border=\"border-cyan-500/15\"\n />\n <StatCard\n value={total - online}\n label=\"Offline\"\n sub={total - online === 0 ? 'All systems go' : `${total - online} disconnected`}\n color=\"text-gray-400\"\n accent=\"from-gray-500/10 to-gray-500/0\"\n border=\"border-gray-500/15\"\n />\n <StatCard\n value={total}\n label=\"Total\"\n sub=\"Registered nodes\"\n color=\"text-white\"\n accent=\"from-blue-500/15 to-blue-500/0\"\n border=\"border-blue-500/15\"\n />\n </div>\n )}\n </div>\n );\n}\n\nfunction StatCard({ value, label, sub, color, accent, border }: {\n value: number; label: string; sub: string; color: string; accent: string; border: string;\n}) {\n // Extract the color family (green/cyan/gray/blue/white) from `color` prop\n // so the light-theme top-strip CSS can pick the right accent.\n const accentKey = color.replace('text-', '').split('-')[0];\n return (\n <div\n data-anet-stat-card={accentKey}\n className={`anet-stat-card relative overflow-hidden rounded-xl border ${border} bg-[#111128] px-4 py-3 transition-all`}\n >\n <div className={`absolute inset-0 bg-gradient-to-br ${accent} pointer-events-none`} />\n <div className=\"relative\">\n <div className={`text-3xl font-bold ${color} tabular-nums leading-tight`}>{value}</div>\n <div className=\"text-sm text-gray-300 mt-0.5\">{label}</div>\n <div className=\"text-xs text-gray-600 mt-1\">{sub}</div>\n </div>\n </div>\n );\n}\n","'use client';\n\nimport { useState } from 'react';\n\nexport function BroadcastBar() {\n const [broadcastMsg, setBroadcastMsg] = useState('');\n const [broadcasting, setBroadcasting] = useState(false);\n const [broadcastResult, setBroadcastResult] = useState('');\n\n const sendBroadcast = async () => {\n if (!broadcastMsg.trim()) return;\n setBroadcasting(true);\n setBroadcastResult('');\n try {\n const res = await fetch('/api/hub/broadcast', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ message: broadcastMsg }),\n });\n const data = await res.json();\n if (data.ok) {\n setBroadcastResult(`Broadcast sent to ${data.recipients} node(s)`);\n setBroadcastMsg('');\n } else {\n setBroadcastResult(`Failed: ${data.error || 'Send error'}`);\n }\n } catch (e: unknown) {\n setBroadcastResult(`Failed: ${e instanceof Error ? e.message : 'Send error'}`);\n }\n setBroadcasting(false);\n setTimeout(() => setBroadcastResult(''), 5000);\n };\n\n return (\n <div className=\"mb-6\">\n <div className=\"flex gap-2\">\n <input\n type=\"text\"\n value={broadcastMsg}\n onChange={e => setBroadcastMsg(e.target.value)}\n onKeyDown={e => e.key === 'Enter' && sendBroadcast()}\n placeholder=\"Broadcast message to all online agents...\"\n maxLength={500}\n aria-label=\"Broadcast message\"\n className=\"flex-1 bg-[#111128] border border-[#2a2a4a] rounded-lg px-4 py-2.5 text-sm text-white placeholder-gray-600 focus:border-blue-500/50 focus:ring-1 focus:ring-blue-500/20 focus:outline-none transition-colors\"\n />\n <button\n onClick={sendBroadcast}\n disabled={broadcasting || !broadcastMsg.trim()}\n aria-label=\"Send broadcast\"\n className=\"flex items-center gap-2 px-5 py-2.5 bg-blue-600 hover:bg-blue-500 disabled:bg-gray-800 disabled:text-gray-600 text-white text-sm rounded-lg transition-all font-medium cursor-pointer disabled:cursor-not-allowed\"\n >\n {broadcasting ? (\n <>\n <svg aria-hidden className=\"w-4 h-4 animate-spin\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"3\" opacity=\"0.25\" />\n <path d=\"M4 12a8 8 0 018-8\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" />\n </svg>\n <span>Sending…</span>\n </>\n ) : (\n <>\n {/* Megaphone icon — \"broadcast to all\" affordance */}\n <svg aria-hidden className=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M3 11v3a1 1 0 0 0 1 1h2l3.29 3.29a1 1 0 0 0 1.71-.71V7.42a1 1 0 0 0-1.71-.71L6 10H4a1 1 0 0 0-1 1Z\" />\n <path d=\"M16 8a5 5 0 0 1 0 6\" opacity=\"0.7\" />\n <path d=\"M19 5a9 9 0 0 1 0 12\" opacity=\"0.45\" />\n </svg>\n <span>Broadcast</span>\n </>\n )}\n </button>\n </div>\n {broadcastMsg.length > 0 && (\n <div className=\"text-right text-xs text-gray-600 mt-1 tabular-nums\">{broadcastMsg.length}/500</div>\n )}\n {broadcastResult && (\n <div className={`mt-3 text-sm text-center anet-fade-in ${broadcastResult.startsWith('Failed') ? 'text-red-400' : 'text-green-400/80'}`}>\n {broadcastResult}\n </div>\n )}\n </div>\n );\n}\n","'use client';\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { Session } from './types';\nimport { aliasAvatarColors, aliasInitial } from './AliasAvatar';\nimport { ChatPopover } from './ChatPopover';\nimport { vendorForModel, runtimeIdentity, identityLine } from '../lib/vendorIdentity';\nimport { parseHubTime, relativeAgo } from '../lib/time';\n\ninterface MessageFlow {\n from_alias: string;\n to_alias: string;\n content: string;\n created_at: string;\n}\n\ninterface TopoGraphProps {\n sessions: Session[];\n sseSessions: Record<string, number>;\n // #84: a node.renamed event from the Overview's SSE listener. When the\n // currently open chat popover targets `from`, it follows the rename to `to`.\n renameSignal?: { from: string; to: string; ts: number } | null;\n}\n\ninterface Point {\n x: number;\n y: number;\n}\n\ninterface FlowLink {\n key: string;\n from: string;\n to: string;\n count: number;\n content: string;\n /** ISO timestamp of the most recent message on this edge — drives\n * the Round 10 freshness fade so dormant links recede visually. */\n last_at: string;\n}\n\nconst cx = 500;\nconst cy = 330;\nconst onlineRadius = 220;\n// Round 97 (issue #50): tier into two rings when N > 8; round 98\n// (issue #61): tier into three rings when N > 14. At N=22 (Vincent's\n// network) two rings still leave 11 nodes per ring → inner chord of\n// 88px can't fit a 100px label; three rings give ~⌈N/3⌉ per ring so\n// every tier has enough arc room.\nconst onlineTierThreshold = 8;\nconst onlineTripleThreshold = 14;\nconst onlineInnerRadius = 175;\nconst onlineOuterRadius = 260;\nconst onlineTripleInnerR = 145;\nconst onlineTripleMidR = 215;\nconst onlineTripleOuterR = 285;\nconst offlineRadius = 325;\n\n/** Polar coordinate for a node on a ring. `rotateBy` lets the caller offset\n * the whole ring so two stacked rings don't align radially (round 25: the\n * offline ring gets a half-step rotation so its nodes sit in the gaps\n * between online ones). */\nfunction polarPoint(index: number, total: number, radius: number, rotateBy = 0) {\n const spread = total <= 2 ? Math.PI : Math.PI * 1.78;\n const start = -Math.PI / 2 - spread / 2;\n const angle = total <= 1 ? -Math.PI / 2 : start + (spread * index) / (total - 1) + rotateBy;\n return {\n x: cx + radius * Math.cos(angle),\n y: cy + radius * Math.sin(angle),\n };\n}\n\nfunction curvePath(from: Point, to: Point, lift = 0) {\n const mx = (from.x + to.x) / 2;\n const my = (from.y + to.y) / 2;\n const dx = to.x - from.x;\n const dy = to.y - from.y;\n const length = Math.hypot(dx, dy) || 1;\n const normalX = -dy / length;\n const normalY = dx / length;\n const control = {\n x: mx + normalX * lift,\n y: my + normalY * lift,\n };\n\n return `M${from.x},${from.y} Q${control.x},${control.y} ${to.x},${to.y}`;\n}\n\nfunction truncate(value: string, max: number) {\n return value.length > max ? `${value.slice(0, max - 1)}...` : value;\n}\n\n/** Round 46 / Loop: SWR-freshness chip.\n *\n * TopoGraph's data refreshes every 5 s via SWR but the user has no\n * visible signal that the canvas they're looking at is current. The\n * flow particles and chips (R42 active-links, R43 hub) tell you when\n * the FLEET last did something, not when the DATA last syncing. This\n * chip ticks `live · Ns` against a 1-second interval so the operator\n * can trust freshness without doing internal math.\n *\n * Owns its own setInterval so the parent topology doesn't re-render\n * every second (only this small chip does). lastSyncRef is updated\n * whenever the `sessions` prop reference changes — that's the SWR\n * refresh signal. */\nfunction FreshnessChip({ sessions }: { sessions: unknown }) {\n const lastSyncRef = useRef<number>(Date.now());\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n // sessions reference changed → SWR just delivered a new payload.\n lastSyncRef.current = Date.now();\n }, [sessions]);\n useEffect(() => {\n const id = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(id);\n }, []);\n const sec = Math.max(0, Math.floor((now - lastSyncRef.current) / 1000));\n // Tint the chip warmer when the data goes stale (>10s since last sync).\n // SWR's default refreshInterval here is 5s, so anything past ~10s is\n // either a poll miss or a network hiccup.\n const stale = sec > 10;\n return (\n <span\n className={stale\n ? \"hidden sm:inline px-2.5 py-1 rounded-md bg-amber-500/10 text-amber-300 border border-amber-500/20 font-mono\"\n : \"hidden sm:inline px-2.5 py-1 rounded-md bg-gray-500/10 text-gray-400 border border-gray-500/20 font-mono\"}\n title={stale ? `Last sync ${sec}s ago — SWR refresh may be lagging` : `Live data · refreshes every 5s · last sync ${sec}s ago`}\n data-freshness-chip\n >\n live · {sec}s\n </span>\n );\n}\n\n/** Round 36 / Loop: prefers-reduced-motion hook.\n *\n * Round 29's a11y sweep zeroed CSS animations via media query, but SVG\n * SMIL `<animate>` / `<animateMotion>` elements aren't reachable from CSS\n * — they need JS to opt out. This hook reads the media query and listens\n * for changes so the topology's flow particles, pulses, click ripple\n * and hub breath honour the OS-level preference. */\nfunction useReducedMotion(): boolean {\n const [reduced, setReduced] = useState(false);\n useEffect(() => {\n if (typeof window === 'undefined' || !window.matchMedia) return;\n const mq = window.matchMedia('(prefers-reduced-motion: reduce)');\n setReduced(mq.matches);\n const onChange = (e: MediaQueryListEvent) => setReduced(e.matches);\n mq.addEventListener('change', onChange);\n return () => mq.removeEventListener('change', onChange);\n }, []);\n return reduced;\n}\n\n// Round 38 / Loop: parseHubTime + relativeAgo factored to app/lib/time.ts\n// — the Round 35 fix lives there now alongside the Round 37 mirror so\n// any future TZ-safe parse update happens in one place.\n\n/** Round 12 / Loop: status trio audit.\n *\n * Each (status × theme) cell returns a {primary, halo, text} trio. The trio\n * invariant — keep it when adding states or tweaking shades:\n *\n * light: primary = <hue>-600 halo = <hue>-100 * text = <hue>-800/900\n * dark: primary = <hue>-400/500 halo = <hue>-900 text = <hue>-100\n *\n * * offline.halo light deviates intentionally to slate-200 (#e2e8f0):\n * slate-100 (#f1f5f9) is too close to the panel bg (#f8fafc) and the\n * halo would vanish. The other three rows keep the 100-shade.\n *\n * Audit caught one cross-family drift before this round: online-other halo\n * light was #dbeafe (blue-100) while its primary (#0284c7 sky-600) and text\n * (#0c4a6e sky-900) were sky-family — now sky-100 (#e0f2fe). Tiny visual\n * difference; large hygiene win — every trio is now mono-hue. */\nfunction nodeStatus(session: Session, isOnline: boolean, isLight: boolean) {\n if (!isOnline) {\n return {\n label: 'offline',\n primary: isLight ? '#94a3b8' : '#6b7280', // slate-400 / gray-500\n halo: isLight ? '#e2e8f0' : '#111827', // slate-200* / gray-900\n text: isLight ? '#475569' : '#9ca3af', // slate-600 / gray-400\n };\n }\n if (session.status === 'working') {\n return {\n label: 'working',\n primary: isLight ? '#059669' : '#22c55e', // emerald-600 / green-500\n halo: isLight ? '#d1fae5' : '#14532d', // emerald-100 / green-900\n text: isLight ? '#065f46' : '#dcfce7', // emerald-800 / green-100\n };\n }\n if (session.status === 'idle') {\n return {\n label: 'idle',\n primary: isLight ? '#0d9488' : '#2dd4bf', // teal-600 / teal-400\n halo: isLight ? '#ccfbf1' : '#134e4a', // teal-100 / teal-900\n text: isLight ? '#115e59' : '#ccfbf1', // teal-800 / teal-100\n };\n }\n return {\n label: session.status || 'online',\n primary: isLight ? '#0284c7' : '#38bdf8', // sky-600 / sky-400\n halo: isLight ? '#e0f2fe' : '#0c4a6e', // sky-100 / sky-900 (was blue-100 — drift fixed Round 12)\n text: isLight ? '#0c4a6e' : '#e0f2fe', // sky-900 / sky-100\n };\n}\n\n/** Theme-aware color palette for the topology SVG. */\ninterface Palette {\n panelStops: [string, string, string];\n radarStops: { color: string; opacity: number }[];\n arrowFill: string;\n ringStroke: string;\n spokeStroke: { active: string; idle: string };\n flowEdge: string;\n flowPath: string;\n flowParticle: string;\n nodeFill: { online: string; offline: string };\n labelBox: { fill: string; stroke: string };\n legendBox: { fill: string; stroke: string };\n legendText: string;\n legendHeadline: string;\n legendAccent: string;\n containerBg: string;\n containerBorder: string;\n topRailGradient: string;\n}\n\nconst DARK_PALETTE: Palette = {\n panelStops: ['#0b1220', '#080814', '#101018'],\n radarStops: [\n { color: '#22d3ee', opacity: 0.18 },\n { color: '#22c55e', opacity: 0.045 },\n { color: '#020617', opacity: 0 },\n ],\n arrowFill: '#67e8f9',\n ringStroke: '#164e63',\n spokeStroke: { active: '#22d3ee', idle: '#155e75' },\n flowEdge: '#67e8f9',\n flowPath: '#e0f2fe',\n flowParticle: '#fef08a',\n nodeFill: { online: '#020617', offline: '#080814' },\n labelBox: { fill: '#020617', stroke: '#1f2937' },\n legendBox: { fill: '#020617', stroke: '#1f2937' },\n legendText: '#94a3b8',\n legendHeadline: '#e5e7eb',\n legendAccent: '#67e8f9',\n containerBg: '#080814',\n containerBorder: '#2a2a4a',\n topRailGradient: 'from-transparent via-cyan-400/70 to-transparent',\n};\n\nconst LIGHT_PALETTE: Palette = {\n panelStops: ['#f8fafc', '#ffffff', '#f1f5f9'],\n radarStops: [\n { color: '#10b981', opacity: 0.06 },\n { color: '#3b82f6', opacity: 0.03 },\n { color: '#ffffff', opacity: 0 },\n ],\n arrowFill: '#10b981',\n ringStroke: '#cbd5e1',\n spokeStroke: { active: '#10b981', idle: '#cbd5e1' },\n flowEdge: '#10b981',\n flowPath: '#475569',\n flowParticle: '#f59e0b',\n nodeFill: { online: '#ffffff', offline: '#f8fafc' },\n labelBox: { fill: '#ffffff', stroke: '#e2e8f0' },\n legendBox: { fill: '#ffffff', stroke: '#e2e8f0' },\n legendText: '#475569',\n legendHeadline: '#0f172a',\n legendAccent: '#0d9488',\n containerBg: '#ffffff',\n containerBorder: '#e3e6eb',\n topRailGradient: 'from-transparent via-emerald-500/40 to-transparent',\n};\n\nfunction useTheme(): 'light' | 'dark' {\n const [theme, setTheme] = useState<'light' | 'dark'>('dark');\n useEffect(() => {\n const read = () => {\n const t = document.documentElement.getAttribute('data-theme') || 'cyber';\n setTheme(t === 'light' || t === 'mint' ? 'light' : 'dark');\n };\n read();\n const obs = new MutationObserver(read);\n obs.observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] });\n return () => obs.disconnect();\n }, []);\n return theme;\n}\n\n/** Round 100 (issue #79): brand showcase mode. Activate via `?brand=intern`\n * on any dashboard page — TopoGraph nodes show the 书小生 mascot instead\n * of alias initials. Stored in localStorage so the flag persists across\n * navigation. Clears with `?brand=none` or `?brand=` (empty). */\nfunction useBrand(): string | null {\n const [brand, setBrand] = useState<string | null>(null);\n useEffect(() => {\n try {\n const url = new URL(window.location.href);\n const param = url.searchParams.get('brand');\n if (param !== null) {\n if (param === '' || param === 'none') {\n localStorage.removeItem('anet-brand');\n setBrand(null);\n } else {\n localStorage.setItem('anet-brand', param);\n setBrand(param);\n }\n } else {\n setBrand(localStorage.getItem('anet-brand'));\n }\n } catch {}\n }, []);\n return brand;\n}\n\n/** Round 106 (issue #83): cluster agents by shared alias prefix so a team\n * reads as one unit in the topology. Adjacent (sorted) aliases that share\n * a ≥2-char prefix join the same group; the group key is the prefix common\n * to every member. Singletons map to their own alias (no hue shift). The\n * group key feeds aliasAvatarColors() so e.g. all 通信* nodes get one hue,\n * all 研究员* another — the \"同色相 tint\" clustering option from #83. */\nfunction commonPrefix(a: string, b: string): string {\n let i = 0;\n while (i < a.length && i < b.length && a[i] === b[i]) i++;\n return a.slice(0, i);\n}\n\n/** #83 + #111: group nodes that share a ≥2-char alias prefix OR a project_dir\n * (\"either criterion → same group\", Vincent 4724). Union-find over the\n * sessions; the component label prefers the shared project_dir's basename,\n * else the common alias prefix. Returns alias → groupKey. */\nfunction computeGroups(sessions: { alias: string; project_dir?: string | null }[]): Record<string, string> {\n const n = sessions.length;\n const parent = sessions.map((_, i) => i);\n const find = (i: number): number => {\n while (parent[i] !== i) { parent[i] = parent[parent[i]]; i = parent[i]; }\n return i;\n };\n const union = (a: number, b: number) => {\n const ra = find(a), rb = find(b);\n if (ra !== rb) parent[ra] = rb;\n };\n\n // union by shared project_dir\n const byDir: Record<string, number[]> = {};\n sessions.forEach((s, i) => {\n const d = s.project_dir?.trim();\n if (d) (byDir[d] ||= []).push(i);\n });\n for (const idxs of Object.values(byDir)) {\n for (let k = 1; k < idxs.length; k++) union(idxs[0], idxs[k]);\n }\n\n // union by shared ≥2-char alias prefix — sort, link adjacent pairs\n const order = sessions.map((_, i) => i).sort((a, b) => sessions[a].alias.localeCompare(sessions[b].alias));\n for (let k = 0; k + 1 < order.length; k++) {\n if (commonPrefix(sessions[order[k]].alias, sessions[order[k + 1]].alias).length >= 2) {\n union(order[k], order[k + 1]);\n }\n }\n\n // label each connected component\n const comps: Record<number, number[]> = {};\n for (let i = 0; i < n; i++) (comps[find(i)] ||= []).push(i);\n const keys: Record<string, string> = {};\n for (const members of Object.values(comps)) {\n let label: string;\n if (members.length === 1) {\n label = sessions[members[0]].alias;\n } else {\n const dirs = new Set(members.map(i => sessions[i].project_dir?.trim()).filter(Boolean) as string[]);\n if (dirs.size === 1) {\n const d = [...dirs][0];\n label = d.split('/').filter(Boolean).pop() || d;\n } else {\n label = members.map(i => sessions[i].alias).reduce((a, b) => commonPrefix(a, b));\n if (label.length < 2) label = sessions[members[0]].alias;\n }\n }\n for (const i of members) keys[sessions[i].alias] = label;\n }\n return keys;\n}\n\nfunction buildFlowLinks(messages: MessageFlow[], positions: Record<string, Point>) {\n const links = new Map<string, FlowLink>();\n\n messages.forEach(message => {\n if (\n !positions[message.from_alias] ||\n !positions[message.to_alias] ||\n message.from_alias === message.to_alias\n ) {\n return;\n }\n\n const key = `${message.from_alias}->${message.to_alias}`;\n const current = links.get(key);\n\n // Keep the most-recent timestamp per pair so the render can fade\n // dormant edges (Round 10 freshness fade).\n const incoming = message.created_at || '';\n const last_at = !current\n ? incoming\n : (incoming > current.last_at ? incoming : current.last_at);\n\n links.set(key, {\n key,\n from: message.from_alias,\n to: message.to_alias,\n count: (current?.count || 0) + 1,\n content: current?.content || message.content,\n last_at,\n });\n });\n\n return [...links.values()].slice(0, 18);\n}\n\nexport function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProps) {\n const theme = useTheme();\n const isLight = theme === 'light';\n const reducedMotion = useReducedMotion();\n const pal = isLight ? LIGHT_PALETTE : DARK_PALETTE;\n const brand = useBrand();\n const isIntern = brand === 'intern';\n const [messages, setMessages] = useState<MessageFlow[]>([]);\n // Issue #87: ring | grid layout toggle. Ring is the tiered-radial default;\n // grid arranges nodes in an N×M grid (better for 30+ nodes). Persisted to\n // localStorage like the zoom/pan view state. Declared above nodePositions\n // since that useMemo branches on it.\n const [layout, setLayout] = useState<'ring' | 'grid'>('ring');\n useEffect(() => {\n try {\n const saved = localStorage.getItem('anet-topo-layout');\n if (saved === 'grid' || saved === 'ring') setLayout(saved);\n } catch {}\n }, []);\n const toggleLayout = () => setLayout(prev => {\n const next = prev === 'ring' ? 'grid' : 'ring';\n try { localStorage.setItem('anet-topo-layout', next); } catch {}\n return next;\n });\n // Issue #113: node size scale (Vincent 4727 — nodes too big / crowded at\n // ~22 nodes). S/M/L → 0.7/0.84/1.0; default M (one notch down from the old\n // fixed size). Persisted like the layout toggle.\n const [nodeScale, setNodeScale] = useState(0.84);\n useEffect(() => {\n try {\n const saved = parseFloat(localStorage.getItem('anet-topo-nodescale') || '');\n if (saved === 0.7 || saved === 0.84 || saved === 1) setNodeScale(saved);\n } catch {}\n }, []);\n const pickNodeScale = (v: number) => {\n setNodeScale(v);\n try { localStorage.setItem('anet-topo-nodescale', String(v)); } catch {}\n };\n\n useEffect(() => {\n const fetchMessages = async () => {\n try {\n const res = await fetch('/api/hub/messages?limit=50');\n if (res.status === 401) {\n window.location.assign('/login');\n return;\n }\n\n const data = await res.json();\n setMessages(data.messages || []);\n } catch {}\n };\n fetchMessages();\n const interval = setInterval(fetchMessages, 5000);\n return () => clearInterval(interval);\n }, []);\n\n const {\n onlineNodes,\n offlineNodes,\n nodePositions,\n flowLinks,\n activeAliases,\n groupKeys,\n groupBoxes,\n gridContentBottom,\n } = useMemo(() => {\n const sseCount = (s: { alias: string; network_id?: string }) =>\n (s.network_id ? sseSessions[`${s.network_id}:${s.alias}`] : undefined) ?? sseSessions[s.alias];\n // Round 106 (issue #83): sort by alias so same-prefix agents\n // (通信龙 / 通信牛 / 通信工程马 …, or 研究员1号 / 研究员2号 …) end up\n // adjacent in the array — the tier layout below assigns angles by\n // index, so contiguous-in-array becomes contiguous-in-ring, i.e.\n // each team visually clusters. localeCompare keeps CJK ordering sane.\n const byAlias = (a: Session, b: Session) => a.alias.localeCompare(b.alias);\n // #112 umbrella: ghost age-out — an offline node not seen recently is\n // almost certainly a deleted node the server `/api/status` still\n // returns (#74 root cause is server-side; this is the dashboard-side\n // fallback so stale ghosts stop cluttering the topology). A missing\n // last_seen_at is kept (conservative — could be a legitimately new node).\n // Round 27 / P0: the 24h threshold was too lenient — Vincent's preview.29\n // screenshot showed B站马 nodes deleted ~4 h earlier still visible. A\n // healthy agent heartbeats every few seconds; if it's been silent for\n // an hour it's effectively gone. 1 h gives a fresh disconnect time to\n // come back while removing dead nodes well within an operator session.\n const GHOST_MS = 60 * 60 * 1000;\n const now = Date.now();\n const isGhost = (s: Session) => {\n if (s.status !== 'offline' || sseCount(s) || !s.last_seen_at) return false;\n // Round 35 / Loop: parseHubTime normalises SQL-style timestamps to UTC\n // before parsing so non-UTC browsers don't see a phantom 8-hour skew\n // and ghost freshly-disconnected nodes.\n const t = parseHubTime(s.last_seen_at);\n return t !== null && now - t > GHOST_MS;\n };\n const online = sessions.filter(s => s.status !== 'offline' || sseCount(s)).sort(byAlias);\n const offline = sessions.filter(s => s.status === 'offline' && !sseCount(s) && !isGhost(s)).sort(byAlias);\n const positions: Record<string, Point> = {};\n\n if (layout === 'grid') {\n // Issue #87 + #111: group-banded grid. Nodes are sorted by alias so\n // same-prefix aliases are adjacent; each multi-member prefix group then\n // gets its OWN row(s) starting at column 0, while singletons pack into\n // shared rows. Group-banded placement keeps every group's bounding box\n // (#111) a clean rectangle — no box ever overlaps another group's.\n const all = [...online, ...offline];\n const groupKeys = computeGroups(all);\n const cols = Math.max(1, Math.ceil(Math.sqrt(all.length)));\n // #112: gy0 starts below the (now compact) recent-signal / legend\n // overlay panels — their max bottom edge is y≈112 — so grid row 0 is\n // never occluded; gy1 extends near the canvas bottom for breathing room.\n const gx0 = 150, gx1 = 850, gy0 = 126, gy1 = 652;\n const cellW = (gx1 - gx0) / cols;\n // largest node radius at the current size scale — drives the group\n // label band + the row-height floor so nothing ever overlaps.\n const nodeR = Math.round(26 * nodeScale);\n\n // ordered runs of consecutive same-group-key nodes (≥2 = real group)\n const runs: { key: string; members: Session[] }[] = [];\n for (const s of all) {\n const gk = groupKeys[s.alias];\n const last = runs[runs.length - 1];\n if (last && last.key === gk) last.members.push(s);\n else runs.push({ key: gk, members: [s] });\n }\n\n // Pass 1 — assign each run to a band: a multi-member group owns its\n // rows (left-aligned, so its bounding box is a tidy rect); contiguous\n // singletons pack into shared rows (centred). Collect total row count.\n type Band = { members: Session[]; startRow: number; centred: boolean; isGroup: boolean };\n const bands: Band[] = [];\n let row = 0;\n let i = 0;\n while (i < runs.length) {\n if (runs[i].members.length >= 2) {\n bands.push({ members: runs[i].members, startRow: row, centred: false, isGroup: true });\n row += Math.ceil(runs[i].members.length / cols);\n i++;\n } else {\n const singles: Session[] = [];\n while (i < runs.length && runs[i].members.length < 2) {\n singles.push(runs[i].members[0]);\n i++;\n }\n bands.push({ members: singles, startRow: row, centred: true, isGroup: false });\n row += Math.ceil(singles.length / cols);\n }\n }\n const totalRows = Math.max(1, row);\n // #112: the group label sits in a band ABOVE the topmost node, so the\n // band must clear the node radius — GROUP_TOP is node-relative, never\n // cellH-derived (cellH-derived was the label↔node overlap bug Vincent\n // hit). cellH then floors at GROUP_TOP + 30 so the label band + bottom\n // padding always fit and stacked group boxes never touch; past the\n // floor the grid overflows and zoom/pan handles it.\n const GROUP_TOP = nodeR + 20;\n // Round 27 / P0 (Vincent screenshot preview.29): dense plain-text\n // node labels (`pos.y + radius + denseDrop`, with a 3 px containerBg\n // stroke halo for readability) at the BOTTOM row of band N would\n // paint OVER the start of band N+1's group label, creating the\n // \"blueleap → eleap\", \"agent-network-dashboard → t-network / board\"\n // visual chopping. Geometry of the collision:\n // dense label visual bottom = node_N.y + radius + denseDrop + halo\n // group label glyph top = boxY + 4 (text y=boxY+14, ~10px ascent)\n // = node_N+1.y - GROUP_TOP + 4\n // node_N+1.y - node_N.y = cellH for consecutive rows, so no-collide:\n // cellH ≥ radius + denseDrop + halo + GROUP_TOP - 4 + buffer\n // With halo=3 buffer=4: cellH ≥ nodeR + denseDrop + GROUP_TOP + 3.\n const denseDrop = nodeScale < 0.8 ? 12 : 14;\n const cellH = Math.max(\n 2 * nodeR + 22, // node + dense label within band\n GROUP_TOP + 12, // group-label band + box padding\n nodeR + denseDrop + GROUP_TOP + 3, // round-27 dense↔group label clearance\n Math.min(100, (gy1 - gy0) / totalRows),\n );\n\n // Pass 2 — place each band's members.\n for (const band of bands) {\n band.members.forEach((s, idx) => {\n const rowInBand = Math.floor(idx / cols);\n const c = idx % cols;\n const inRow = Math.min(cols, band.members.length - rowInBand * cols);\n const inset = band.centred ? ((cols - inRow) * cellW) / 2 : 0;\n positions[s.alias] = {\n x: gx0 + inset + (c + 0.5) * cellW,\n y: gy0 + (band.startRow + rowInBand + 0.5) * cellH,\n };\n });\n }\n\n const links = buildFlowLinks(messages, positions);\n const active = new Set<string>();\n links.forEach(link => { active.add(link.from); active.add(link.to); });\n // #111: one bounding box per multi-member group (Vincent 4722). Each\n // group owns its rows; GROUP_PAD fills the row space left below the\n // nodes after the label band, so stacked group boxes always have a\n // gap between them (GROUP_TOP is defined above, with cellH).\n const GROUP_PAD = Math.max(8, Math.min(26, cellH - GROUP_TOP - 8)); // side/bottom\n const groupBoxes = bands\n .filter(b => b.isGroup)\n .map(band => {\n const pts = band.members.map(s => positions[s.alias]).filter(Boolean);\n const xs = pts.map(p => p.x);\n const ys = pts.map(p => p.y);\n const minX = Math.min(...xs), minY = Math.min(...ys);\n return {\n key: band.members.length ? groupKeys[band.members[0].alias] : '',\n count: band.members.length,\n x: minX - GROUP_PAD,\n y: minY - GROUP_TOP,\n w: Math.max(...xs) - minX + GROUP_PAD * 2,\n h: Math.max(...ys) - minY + GROUP_TOP + GROUP_PAD,\n };\n });\n // Round 28 / Loop: surface the grid's natural content bottom so the\n // mount effect can auto-fit zoom when the layout would overflow the\n // viewBox. = bottom of the last node row + its label drop + a small\n // breathing buffer. Round 27's cellH bump makes this overflow more\n // common (30-node fleets reach ~774 px, viewBox is 680).\n const gridContentBottom = gy0 + totalRows * cellH + 8;\n return {\n onlineNodes: online,\n offlineNodes: offline,\n nodePositions: positions,\n flowLinks: links,\n activeAliases: active,\n groupKeys,\n groupBoxes,\n gridContentBottom,\n };\n }\n\n // Round 97 (issue #50) + 98 (issue #61): three layout modes by N.\n // N ≤ 8 → single ring (r=220)\n // 8 < N ≤ 14 → two rings (inner r=175, outer r=260, half-step rot)\n // N > 14 → three rings (r=145/215/285, ⌈N/3⌉ per ring)\n // Each ring's spread is 1.78π so its node count drives chord length:\n // labels are 100px wide so each ring needs ≥110px chord per node.\n const tripleTier = online.length > onlineTripleThreshold;\n const dualTier = !tripleTier && online.length > onlineTierThreshold;\n let outerOnlineCount = online.length;\n if (tripleTier) {\n const per = Math.ceil(online.length / 3);\n const r1 = online.slice(0, per);\n const r2 = online.slice(per, 2 * per);\n const r3 = online.slice(2 * per);\n r1.forEach((s, index) => {\n positions[s.alias] = polarPoint(index, Math.max(r1.length, 1), onlineTripleInnerR);\n });\n const r1Spread = r1.length <= 2 ? Math.PI : Math.PI * 1.78;\n const r1Step = r1.length > 1 ? r1Spread / (r1.length - 1) : 0;\n r2.forEach((s, index) => {\n positions[s.alias] = polarPoint(index, Math.max(r2.length, 1), onlineTripleMidR, r1Step / 2);\n });\n r3.forEach((s, index) => {\n positions[s.alias] = polarPoint(index, Math.max(r3.length, 1), onlineTripleOuterR);\n });\n outerOnlineCount = r3.length;\n } else if (dualTier) {\n const innerCount = Math.ceil(online.length / 2);\n const outerCount = online.length - innerCount;\n const innerNodes = online.slice(0, innerCount);\n const outerNodes = online.slice(innerCount);\n innerNodes.forEach((s, index) => {\n positions[s.alias] = polarPoint(index, Math.max(innerCount, 1), onlineInnerRadius);\n });\n const innerSpread = innerCount <= 2 ? Math.PI : Math.PI * 1.78;\n const innerStep = innerCount > 1 ? innerSpread / (innerCount - 1) : 0;\n outerNodes.forEach((s, index) => {\n positions[s.alias] = polarPoint(index, Math.max(outerCount, 1), onlineOuterRadius, innerStep / 2);\n });\n outerOnlineCount = outerCount;\n } else {\n online.forEach((s, index) => {\n positions[s.alias] = polarPoint(index, Math.max(online.length, 1), onlineRadius);\n });\n }\n\n // Offset the offline ring radially by half the outermost online step so\n // offline bubbles sit in the angular gaps between online bubbles instead\n // of stacking directly behind them. Also push the outer ring further when\n // there are many offline nodes so labels don't crowd the legend.\n const outerSpreadBase = outerOnlineCount <= 2 ? Math.PI : Math.PI * 1.78;\n const outerStep = outerOnlineCount > 1 ? outerSpreadBase / (outerOnlineCount - 1) : 0;\n const offlineRotation = outerOnlineCount > 0 ? outerStep / 2 : 0;\n const offlineR = offlineRadius + Math.max(0, offline.length - 4) * 6;\n\n offline.forEach((s, index) => {\n positions[s.alias] = polarPoint(index, Math.max(offline.length, 1), offlineR, offlineRotation);\n });\n\n const links = buildFlowLinks(messages, positions);\n const active = new Set<string>();\n links.forEach(link => {\n active.add(link.from);\n active.add(link.to);\n });\n\n // Round 106 (issue #83): group key per alias → shared hue per team.\n const groupKeys = computeGroups([...online, ...offline]);\n\n return {\n onlineNodes: online,\n offlineNodes: offline,\n nodePositions: positions,\n flowLinks: links,\n activeAliases: active,\n groupKeys,\n // #111: group boxes are a grid-layout feature only — radially scattered\n // ring nodes can't be cleanly boxed. Ring keeps the #83 prefix hue.\n groupBoxes: [] as { key: string; count: number; x: number; y: number; w: number; h: number }[],\n // ring fits within VIEWBOX_H by construction (offlineRadius=325 + centre at y=330)\n gridContentBottom: 0,\n };\n }, [messages, sessions, sseSessions, layout, nodeScale]);\n\n const workingCount = onlineNodes.filter(s => s.status === 'working').length;\n // Round 6 / Loop: vendor distribution for the header chip — at a glance\n // \"what's in the fleet\" (A:5 M:2 O:8 书:12 …) without opening a node.\n // Sorted by count desc; \"unknown\" vendors collapse into a \"?\" bucket.\n const vendorDist = useMemo(() => {\n const tally = new Map<string, { initial: string; count: number; color: string }>();\n for (const s of [...onlineNodes, ...offlineNodes]) {\n const v = vendorForModel(s.model);\n const key = v.id === 'unknown' ? '?' : v.initial;\n const cur = tally.get(key);\n if (cur) cur.count++;\n else tally.set(key, { initial: key, count: 1, color: v.mono.text });\n }\n return [...tally.values()].sort((a, b) => b.count - a.count);\n }, [onlineNodes, offlineNodes]);\n // Round 109 (Vincent 4582 P0): hover-gated labels above this node count\n // so dense fleets show clean avatars instead of a wall of overlapping\n // label cards. 16 ≈ where the triple-tier rings start to crowd.\n const denseLayout = onlineNodes.length + offlineNodes.length > 16;\n const [hoveredAlias, setHoveredAlias] = useState<string | null>(null);\n // Round 8 / Loop: which group is currently focused. Nodes outside this\n // group + other group boxes fade so the eye locks onto the team you're\n // pointing at. Singletons use their own alias as the group key.\n const hoveredGroup = hoveredAlias ? (groupKeys[hoveredAlias] ?? hoveredAlias) : null;\n\n // --- Round 103 (issue #81): fullscreen + zoom + pan interaction layer ---\n // DIY native (no d3 / svg-pan-zoom): wrap the topology content in a single\n // <g transform> and drive it with wheel + pointer-drag. The panel <rect>\n // backdrop stays fixed so panning never reveals empty canvas. View state\n // {zoom,x,y} persists to localStorage (same sticky pattern as brand flag).\n const VIEWBOX_W = 1000;\n const VIEWBOX_H = 680;\n const ZOOM_MIN = 0.5;\n const ZOOM_MAX = 4;\n const containerRef = useRef<HTMLDivElement>(null);\n const svgRef = useRef<SVGSVGElement>(null);\n const [view, setView] = useState({ zoom: 1, x: 0, y: 0 });\n const viewRef = useRef(view);\n const dragRef = useRef({ active: false, startX: 0, startY: 0, baseX: 0, baseY: 0 });\n const [isFullscreen, setIsFullscreen] = useState(false);\n // Issue #100: singleton chat popover. One alias at a time — clicking\n // another node swaps the target and the conversation switches in place.\n const [chatAlias, setChatAlias] = useState<string | null>(null);\n // Round 14 / Loop: one-shot click ripple — fades outward from the clicked\n // node so the click registers physically before the popover snaps in.\n // Pairs with the Round 11 chat-focus ring: ripple expands, ring locks on.\n // Keyed by ts so re-clicking the same node remounts the <circle> and the\n // SMIL <animate> replays. Cleared 600ms after click (longer than the\n // 500ms animation so a final frame at opacity 0 is still in the tree).\n const [clickRipple, setClickRipple] = useState<{\n ts: number; x: number; y: number; r0: number; color: string;\n } | null>(null);\n // #84: when a node is renamed while its chat popover is open, follow the\n // rename so the conversation keeps targeting a live alias.\n useEffect(() => {\n if (renameSignal && renameSignal.from === chatAlias) {\n setChatAlias(renameSignal.to);\n }\n // chatAlias intentionally omitted — only react to a new rename signal,\n // not to the user opening/closing the popover.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [renameSignal]);\n\n useEffect(() => { viewRef.current = view; }, [view]);\n\n // restore persisted view once on mount\n useEffect(() => {\n try {\n const raw = localStorage.getItem('anet-topo-view');\n if (raw) {\n const v = JSON.parse(raw);\n if (typeof v?.zoom === 'number') {\n setView({\n zoom: Math.min(ZOOM_MAX, Math.max(ZOOM_MIN, v.zoom)),\n x: typeof v.x === 'number' ? v.x : 0,\n y: typeof v.y === 'number' ? v.y : 0,\n });\n }\n }\n } catch {}\n }, []);\n\n // Round 28 / Loop: first-paint auto-fit. Round 27's cellH bump means\n // dense grids (≥6-7 rows) overflow the 680-px viewBox at the natural\n // 100% zoom — a new user sees the topology with its bottom rows\n // clipped and no hint that there's more below. Auto-fit on first\n // paint (and only if the user has no persisted view) sets the\n // initial zoom so all content fits. Subsequent zoom changes persist\n // and override the auto-fit on reload; explicit reset (0 key) still\n // goes back to 100% so the gesture's \"reset to natural size\" semantic\n // is preserved.\n //\n // Capture pre-mount persistence in a useState initializer — the\n // existing `persist` effect (declared below) runs on first render\n // with the default {1,0,0} view and writes it to localStorage before\n // the auto-fit effect (deps on async-arriving sessions) gets a turn.\n // Reading localStorage from the effect would see that write and\n // skip the fit. The useState snapshot fires once, before any effects.\n const [hadPersistedViewOnMount] = useState<boolean>(\n () => typeof window !== 'undefined' && !!localStorage.getItem('anet-topo-view'),\n );\n const autoFitDoneRef = useRef(false);\n useEffect(() => {\n if (autoFitDoneRef.current) return;\n if (hadPersistedViewOnMount) {\n autoFitDoneRef.current = true;\n return;\n }\n if (layout !== 'grid' || sessions.length === 0 || !gridContentBottom) return;\n if (gridContentBottom <= VIEWBOX_H) {\n autoFitDoneRef.current = true; // no overflow → no fit needed\n return;\n }\n const fitZoom = Math.max(ZOOM_MIN, Math.min(1, VIEWBOX_H / gridContentBottom));\n setView({ zoom: fitZoom, x: 0, y: 0 });\n autoFitDoneRef.current = true;\n }, [layout, sessions.length, gridContentBottom, hadPersistedViewOnMount]);\n\n // persist view\n useEffect(() => {\n try { localStorage.setItem('anet-topo-view', JSON.stringify(view)); } catch {}\n }, [view]);\n\n // track fullscreen state (button label + Esc-exit sync)\n useEffect(() => {\n const onFsChange = () => setIsFullscreen(document.fullscreenElement === containerRef.current);\n document.addEventListener('fullscreenchange', onFsChange);\n return () => document.removeEventListener('fullscreenchange', onFsChange);\n }, []);\n\n // wheel zoom — native non-passive listener so preventDefault() actually\n // stops the page from scrolling. Uses functional setState so the listener\n // never goes stale and can attach once.\n useEffect(() => {\n const svg = svgRef.current;\n if (!svg) return;\n const onWheel = (e: WheelEvent) => {\n // Round 23 / Loop: only zoom on Ctrl/Meta+wheel when inline; plain\n // wheel over the canvas keeps scrolling the page (the topo sits at\n // the top of /; trapping page scroll mid-page is the classic\n // \"scroll-jail\" anti-pattern). In fullscreen the canvas owns the\n // viewport so any wheel zooms — no page scroll to preserve. Pinch-\n // zoom on a trackpad surfaces as ctrlKey=true natively, which is\n // also what we want (zoom the canvas, not the browser).\n if (!isFullscreen && !e.ctrlKey && !e.metaKey) return;\n e.preventDefault();\n const rect = svg.getBoundingClientRect();\n const mx = ((e.clientX - rect.left) / rect.width) * VIEWBOX_W;\n const my = ((e.clientY - rect.top) / rect.height) * VIEWBOX_H;\n setView(prev => {\n // Round 104 (issue #81 follow-up): Vincent 实测 zoom 太灵敏. The\n // old factor was a fixed 1.15x per wheel *event* — fine for a\n // mouse notch but a trackpad fires dozens of events per gesture\n // so it compounded into huge jumps. Scale the factor by deltaY\n // magnitude with a small coefficient, then clamp the per-event\n // change so no single tick moves more than ~8%.\n const factor = Math.min(1.08, Math.max(0.926, Math.exp(-e.deltaY * 0.0006)));\n const nz = Math.min(ZOOM_MAX, Math.max(ZOOM_MIN, prev.zoom * factor));\n const ratio = nz / prev.zoom;\n // keep the point under the cursor stationary\n return { zoom: nz, x: mx - (mx - prev.x) * ratio, y: my - (my - prev.y) * ratio };\n });\n };\n svg.addEventListener('wheel', onWheel, { passive: false });\n return () => svg.removeEventListener('wheel', onWheel);\n // Re-attach when the fullscreen flag toggles so the handler's\n // closure picks up the new value (capture-by-closure means we'd\n // otherwise read the stale boolean forever).\n }, [isFullscreen]);\n\n // Round 21 / Loop: pan-aware cursor. Static `grab` gave no tactile cue\n // that the canvas was actually being dragged — \"grabbing\" while\n // dragRef.current.active = true tells the hand it's moving the\n // viewport. Mirroring dragRef.active into state is the only way to\n // re-render the SVG style; the ref itself doesn't trigger renders.\n const [isPanning, setIsPanning] = useState(false);\n const onPointerDown = (e: React.PointerEvent<SVGSVGElement>) => {\n if (e.button !== 0) return;\n (e.currentTarget as Element).setPointerCapture?.(e.pointerId);\n dragRef.current = {\n active: true,\n startX: e.clientX,\n startY: e.clientY,\n baseX: viewRef.current.x,\n baseY: viewRef.current.y,\n };\n setIsPanning(true);\n };\n const onPointerMove = (e: React.PointerEvent<SVGSVGElement>) => {\n const d = dragRef.current;\n if (!d.active) return;\n const svg = svgRef.current;\n if (!svg) return;\n const rect = svg.getBoundingClientRect();\n const dx = ((e.clientX - d.startX) / rect.width) * VIEWBOX_W;\n const dy = ((e.clientY - d.startY) / rect.height) * VIEWBOX_H;\n setView(prev => ({ ...prev, x: d.baseX + dx, y: d.baseY + dy }));\n };\n const onPointerUp = (e: React.PointerEvent<SVGSVGElement>) => {\n if (!dragRef.current.active) return;\n dragRef.current.active = false;\n setIsPanning(false);\n try {\n (e.currentTarget as Element).releasePointerCapture?.(e.pointerId);\n } catch {}\n };\n\n // zoom buttons — zoom around the canvas center\n const zoomBy = (factor: number) => {\n setView(prev => {\n const nz = Math.min(ZOOM_MAX, Math.max(ZOOM_MIN, prev.zoom * factor));\n const ratio = nz / prev.zoom;\n const cx0 = VIEWBOX_W / 2;\n const cy0 = VIEWBOX_H / 2;\n return { zoom: nz, x: cx0 - (cx0 - prev.x) * ratio, y: cy0 - (cy0 - prev.y) * ratio };\n });\n };\n const resetView = () => setView({ zoom: 1, x: 0, y: 0 });\n\n // Round 29 / Loop: `f` = fit-to-content. Shared by the Round 28\n // first-paint auto-fit effect and the keyboard handler so the math is\n // in one place. When content already fits at natural zoom, this is\n // effectively a \"recenter\" — `f` always lands on a known good view.\n const fitView = useCallback(() => {\n const zoom = !gridContentBottom || gridContentBottom <= VIEWBOX_H\n ? 1\n : Math.max(ZOOM_MIN, Math.min(1, VIEWBOX_H / gridContentBottom));\n setView({ zoom, x: 0, y: 0 });\n }, [gridContentBottom]);\n\n // Round 22 / Loop: keyboard zoom — +/= zoom in, - zoom out, 0 reset.\n // Round 29 / Loop: +f to fit content.\n // Listen on window so the user doesn't need to focus the SVG first,\n // but only act when no text input has focus (otherwise typing \"-\" in\n // a chat would zoom the topology — surprising and bad). Modifier keys\n // pass through so Cmd/Ctrl combos still hit their owners. The button\n // titles below document these shortcuts so users discover them.\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.ctrlKey || e.metaKey || e.altKey) return;\n const ae = document.activeElement as HTMLElement | null;\n if (ae) {\n const tag = ae.tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || ae.isContentEditable) return;\n }\n if (e.key === '+' || e.key === '=') { zoomBy(1.2); e.preventDefault(); }\n else if (e.key === '-' || e.key === '_') { zoomBy(1 / 1.2); e.preventDefault(); }\n else if (e.key === '0') { resetView(); e.preventDefault(); }\n else if (e.key === 'f' || e.key === 'F') { fitView(); e.preventDefault(); }\n // Round 32 / Loop: `l` toggles ring|grid. The vim-style `g l` route\n // (Audit Log) requires a preceding `g` within 1500ms; a bare `l`\n // outside that window is free for topology use.\n else if (e.key === 'l' || e.key === 'L') { toggleLayout(); e.preventDefault(); }\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n // zoomBy / resetView are stable wrt setView callback; fitView changes\n // with gridContentBottom so deps list catches it.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [fitView]);\n\n const toggleFullscreen = () => {\n const el = containerRef.current;\n if (!el) return;\n if (document.fullscreenElement) {\n document.exitFullscreen?.();\n } else {\n const req =\n el.requestFullscreen ||\n (el as unknown as { webkitRequestFullscreen?: () => void }).webkitRequestFullscreen;\n req?.call(el);\n }\n };\n\n return (\n <section className=\"w-full max-w-6xl mx-auto mb-8\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between mb-3 px-1\">\n <div>\n <div className=\"text-xs uppercase text-gray-600 tracking-wider\">Network Topology</div>\n <h2 className=\"text-lg text-white font-semibold\">Command mesh</h2>\n </div>\n <div className=\"flex flex-wrap items-center gap-2 text-xs\">\n {/* Issue #87: ring | grid layout toggle — segmented control,\n persisted to localStorage anet-topo-layout. */}\n <div className=\"inline-flex rounded-md border border-gray-500/25 overflow-hidden\" role=\"group\" aria-label=\"Topology layout\">\n <button\n onClick={() => { if (layout !== 'ring') toggleLayout(); }}\n aria-pressed={layout === 'ring'}\n title=\"Ring layout (l to toggle)\"\n className={`px-2.5 py-1 transition-colors ${layout === 'ring' ? 'bg-cyan-500/15 text-cyan-300' : 'text-gray-500 hover:text-gray-400'}`}\n >\n Ring\n </button>\n <button\n onClick={() => { if (layout !== 'grid') toggleLayout(); }}\n aria-pressed={layout === 'grid'}\n title=\"Grid layout (l to toggle)\"\n className={`px-2.5 py-1 border-l border-gray-500/25 transition-colors ${layout === 'grid' ? 'bg-cyan-500/15 text-cyan-300' : 'text-gray-500 hover:text-gray-400'}`}\n >\n Grid\n </button>\n </div>\n <span className=\"px-2.5 py-1 rounded-md bg-green-500/10 text-green-300 border border-green-500/20\">\n {workingCount} working\n </span>\n <span className=\"px-2.5 py-1 rounded-md bg-cyan-500/10 text-cyan-300 border border-cyan-500/20\">\n {onlineNodes.length} online\n </span>\n {/* Round 31 / Loop: fleet-health pressure bar. The \"X working /\n Y online\" chips already carry the raw counts; the bar lets\n the eye get the working/idle/offline RATIO in one glance\n without mental math. Stacked 3-segment chip, ~64 px wide. */}\n {(() => {\n const w = workingCount;\n const i = onlineNodes.length - workingCount; // idle = online - working\n const o = offlineNodes.length;\n const total = w + i + o;\n if (total === 0) return null;\n const seg = (n: number, color: string, key: string) => {\n if (n === 0) return null;\n return <span key={key} style={{ width: `${(n / total) * 100}%`, background: color, height: '100%' }} />;\n };\n // Round 47 / Loop: hidden on mobile — at <640px the chip row\n // wraps to multiple lines and crowds the topology header;\n // pressure ratio is best read with the working+online raw\n // counts (kept visible) anyway.\n return (\n <span\n className=\"hidden sm:inline-flex items-center gap-2 px-2.5 py-1 rounded-md bg-gray-500/10 text-gray-400 border border-gray-500/20 font-mono\"\n title={`${w} working · ${i} idle · ${o} offline`}\n data-fleet-pressure\n >\n <span className=\"text-[10px] tracking-wide\">pressure</span>\n <span className=\"inline-flex h-1.5 w-16 rounded-full overflow-hidden\" style={{ background: 'rgb(75 85 99 / 0.25)' }}>\n {seg(w, isLight ? '#059669' : '#22c55e', 'w')}\n {seg(i, isLight ? '#0d9488' : '#2dd4bf', 'i')}\n {seg(o, isLight ? '#94a3b8' : '#6b7280', 'o')}\n </span>\n </span>\n );\n })()}\n {vendorDist.length > 1 && (\n <span\n className=\"hidden sm:inline-flex items-center gap-2 px-2.5 py-1 rounded-md bg-gray-500/10 text-gray-400 border border-gray-500/20 font-mono\"\n title=\"Fleet by model vendor\"\n >\n {vendorDist.map(v => (\n <span key={v.initial} className=\"inline-flex items-baseline gap-0.5\">\n <span style={{ color: v.color }}>{v.initial}</span>\n <span className=\"text-gray-500\">:{v.count}</span>\n </span>\n ))}\n </span>\n )}\n {/* Round 42 / Loop: extend active-links chip with the timestamp\n of the most-recent flow event. Tells the operator at a glance\n whether the topology is currently humming (last 30s) or has\n been quiet for a while — the visual flow particles and\n edge brightness only show that there IS traffic, not when\n the last one was. Reuses Round 38's relativeAgo. */}\n {(() => {\n const recent = flowLinks.reduce<number | null>((acc, l) => {\n if (!l.last_at) return acc;\n const t = parseHubTime(l.last_at);\n if (t === null) return acc;\n return acc === null || t > acc ? t : acc;\n }, null);\n const rel = recent !== null ? relativeAgo(new Date(recent).toISOString()) : null;\n return (\n <span className=\"hidden sm:inline px-2.5 py-1 rounded-md bg-gray-500/10 text-gray-400 border border-gray-500/20\">\n {flowLinks.length} active link{flowLinks.length === 1 ? '' : 's'}\n {rel ? <span className=\"text-gray-500\"> · last {rel}</span> : null}\n </span>\n );\n })()}\n <FreshnessChip sessions={sessions} />\n </div>\n </div>\n\n <div\n ref={containerRef}\n className={`relative overflow-hidden rounded-lg border shadow-2xl ${isLight ? 'shadow-zinc-900/5' : 'shadow-cyan-950/30'} ${isFullscreen ? 'flex items-center justify-center' : ''}`}\n style={{ background: pal.containerBg, borderColor: pal.containerBorder }}\n >\n <div className={`absolute inset-x-0 top-0 h-px bg-gradient-to-r ${pal.topRailGradient}`} />\n\n <svg\n ref={svgRef}\n viewBox=\"0 0 1000 680\"\n className=\"w-full h-auto block\"\n preserveAspectRatio=\"xMidYMid meet\"\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerLeave={onPointerUp}\n // Round 41 / Loop: the reset-button title (R22) and the Help\n // overlay (R25) both advertise \"double-click the canvas to\n // reset\", but the handler was never actually wired. The text\n // was lying. Wire it here, guarded so dbl-clicking a node\n // (which would also trigger the SVG-level handler via event\n // bubbling) doesn't unexpectedly reset the view on the user.\n onDoubleClick={(e) => {\n const t = e.target as Element | null;\n if (t?.closest('g[data-node]')) return;\n resetView();\n }}\n style={{ cursor: isPanning ? 'grabbing' : 'grab', touchAction: 'none' }}\n >\n <defs>\n <linearGradient id=\"topo-panel\" x1=\"0\" x2=\"1\" y1=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={pal.panelStops[0]} />\n <stop offset=\"48%\" stopColor={pal.panelStops[1]} />\n <stop offset=\"100%\" stopColor={pal.panelStops[2]} />\n </linearGradient>\n <radialGradient id=\"topo-radar\" cx=\"50%\" cy=\"50%\" r=\"55%\">\n <stop offset=\"0%\" stopColor={pal.radarStops[0].color} stopOpacity={pal.radarStops[0].opacity} />\n <stop offset=\"45%\" stopColor={pal.radarStops[1].color} stopOpacity={pal.radarStops[1].opacity} />\n <stop offset=\"100%\" stopColor={pal.radarStops[2].color} stopOpacity={pal.radarStops[2].opacity} />\n </radialGradient>\n {!isLight && (\n <filter id=\"topo-glow\">\n <feGaussianBlur stdDeviation=\"4\" result=\"blur\" />\n <feMerge>\n <feMergeNode in=\"blur\" />\n <feMergeNode in=\"SourceGraphic\" />\n </feMerge>\n </filter>\n )}\n {/* Round 16 / Loop: 3-tier flow-link arrow markers.\n The single marker had `markerUnits` defaulting to\n `strokeWidth`, so heavy edges (stroke=7) rendered 35-user-\n unit arrowheads — visually dominant, the head outweighed\n the line. Switching to `userSpaceOnUse` decouples arrow\n size from stroke; binning by count gives a clearer\n hierarchy than continuous linear scaling:\n s (count 1-2) → 12 user units\n m (count 3-4) → 16 user units (alias for `topo-arrow`)\n l (count 5+) → 22 user units\n `topo-arrow` stays bound to the medium tier so the legend\n swatch (line ~1500) renders without change. */}\n {[\n { id: 'topo-arrow-s', size: 12 },\n { id: 'topo-arrow', size: 16 },\n { id: 'topo-arrow-l', size: 22 },\n ].map(m => (\n <marker\n key={m.id}\n id={m.id}\n viewBox=\"0 0 10 10\"\n refX=\"8\"\n refY=\"5\"\n markerWidth={m.size}\n markerHeight={m.size}\n markerUnits=\"userSpaceOnUse\"\n orient=\"auto-start-reverse\"\n >\n <path d=\"M 0 0 L 10 5 L 0 10 z\" fill={pal.arrowFill} />\n </marker>\n ))}\n {/* Round 45: radial radar sweep gradient — bright at center\n (where it meets the hub) fading to leading edge. */}\n <radialGradient id=\"topo-sweep\" cx=\"0%\" cy=\"50%\" r=\"100%\">\n <stop offset=\"0%\" stopColor={isLight ? '#0d9488' : '#22d3ee'} stopOpacity={isLight ? 0.18 : 0.32} />\n <stop offset=\"70%\" stopColor={isLight ? '#0d9488' : '#22d3ee'} stopOpacity={isLight ? 0.10 : 0.18} />\n <stop offset=\"100%\" stopColor={isLight ? '#0d9488' : '#22d3ee'} stopOpacity=\"0\" />\n </radialGradient>\n </defs>\n\n {/* panel backdrop stays fixed — panning never reveals empty canvas */}\n <rect width=\"1000\" height=\"680\" fill=\"url(#topo-panel)\" />\n\n {/* Round 103 (issue #81): everything inside this <g> zooms + pans\n together. transform order = translate then scale. */}\n <g transform={`translate(${view.x} ${view.y}) scale(${view.zoom})`}>\n {/* Issue #87: radar/ring ambiance renders only in ring layout —\n grid mode drops it so the concentric rings don't sit behind a\n rectangular grid. */}\n {layout === 'ring' && (<>\n <circle cx={cx} cy={cy} r=\"330\" fill=\"url(#topo-radar)\" />\n\n {/* Round 45: subtle star field — 24 deterministic dots scattered\n across the canvas give the radar bg some depth. Skipped on\n light theme so the white surface stays clean. */}\n {!isLight && (\n <g opacity=\"0.5\">\n {Array.from({ length: 28 }).map((_, i) => {\n // Deterministic pseudo-random scatter so positions are\n // stable between renders (no JS hydration mismatch).\n const seed = i * 9301 + 49297;\n const x = ((seed * 13) % 1000);\n const y = ((seed * 7) % 680);\n const r = (i % 3 === 0) ? 1.2 : 0.7;\n return <circle key={i} cx={x} cy={y} r={r} fill=\"#a5b4fc\" opacity={0.35 + (i % 4) * 0.05} />;\n })}\n </g>\n )}\n\n {/* Round 45: rotating radar sweep — a 40° wedge with a soft\n leading-edge gradient. Slow 6s rotation reads as a radar\n scan without being noisy. Inline transform-origin on the\n <g> wrapper ensures Chrome / Firefox rotate around (cx,cy)\n instead of the SVG viewBox corner. */}\n <g\n style={{\n transformOrigin: `${cx}px ${cy}px`,\n transformBox: 'view-box',\n }}\n className=\"anet-topo-sweep\"\n opacity={isLight ? 0.7 : 1}\n >\n <path\n d={`M ${cx} ${cy} L ${cx + 330} ${cy} A 330 330 0 0 0 ${cx + 330 * Math.cos(-Math.PI / 4.5)} ${cy + 330 * Math.sin(-Math.PI / 4.5)} Z`}\n fill=\"url(#topo-sweep)\"\n />\n </g>\n\n {/* radar rings */}\n {[90, 170, 250, 330].map(radius => (\n <circle key={radius} cx={cx} cy={cy} r={radius} fill=\"none\" stroke={pal.ringStroke} strokeWidth=\"1\" opacity={isLight ? 0.6 : 0.35} />\n ))}\n\n {/* Round 50: 4 small particles slowly orbiting the outer ring\n (r=330). Each starts at a different angle (offset 0/0.25/0.5/0.75\n of the cycle) so they're evenly spaced. 16s per revolution is\n slow enough to feel ambient, not noisy. Skipped on light theme\n so the white surface stays clean. */}\n {!isLight && [0, 0.25, 0.5, 0.75].map((phase, i) => (\n <g key={`orbit-${i}`}>\n <circle\n cx={cx + 330} cy={cy}\n r={i === 0 ? 2.8 : 2.2}\n fill=\"#22d3ee\"\n opacity={0.9}\n filter=\"url(#topo-glow)\"\n >\n <animateTransform\n attributeName=\"transform\"\n type=\"rotate\"\n from={`${phase * 360} ${cx} ${cy}`}\n to={`${phase * 360 + 360} ${cx} ${cy}`}\n dur=\"16s\"\n repeatCount=\"indefinite\"\n />\n </circle>\n </g>\n ))}\n\n {[0, 30, 60, 90, 120, 150].map(angle => (\n <line\n key={angle}\n x1={cx - 360 * Math.cos(angle * Math.PI / 180)}\n y1={cy - 360 * Math.sin(angle * Math.PI / 180)}\n x2={cx + 360 * Math.cos(angle * Math.PI / 180)}\n y2={cy + 360 * Math.sin(angle * Math.PI / 180)}\n stroke={pal.ringStroke}\n strokeWidth=\"1\"\n opacity={isLight ? 0.35 : 0.18}\n />\n ))}\n </>)}\n\n {/* hub links — round 46: idle spokes now have animated\n stroke-dashoffset so dashes flow outward from the hub\n (\"command relay\" feel). Active spokes carrying live message\n flow stay as solid bright strokes. */}\n {layout === 'ring' && onlineNodes.map((session, idx) => {\n const pos = nodePositions[session.alias];\n if (!pos) return null;\n const path = curvePath({ x: cx, y: cy }, pos, 0);\n const isActiveSpoke = activeAliases.has(session.alias);\n\n return (\n <path\n key={`hub-${session.alias}`}\n d={path}\n fill=\"none\"\n stroke={isActiveSpoke ? pal.spokeStroke.active : pal.spokeStroke.idle}\n strokeWidth={isActiveSpoke ? 2 : 1}\n strokeDasharray={isActiveSpoke ? 'none' : '6 14'}\n opacity={isActiveSpoke ? 0.7 : 0.45}\n className={isActiveSpoke ? undefined : 'anet-topo-spoke-flow'}\n style={isActiveSpoke ? undefined : { animationDelay: `${-(idx * 0.25)}s` }}\n />\n );\n })}\n\n {/* #111: prefix-group boundary boxes (Vincent 4722). Grid layout\n only — groupBoxes is empty in ring mode. Rendered behind the\n flow links + nodes; pointer-events off so they never intercept\n a node click. Restrained dashed container + group-name label. */}\n {groupBoxes.map(box => {\n const isHovered = hoveredGroup === box.key;\n // Round 18 / Loop: group-box hover linkage. The Round 8 fade\n // already dropped OUT-of-focus groups to 0.28, but the IN-focus\n // group sat at its baseline appearance — no positive emphasis.\n // Hovering now upgrades the box to an \"accent\" treatment:\n // solid stroke (not dashed), thicker, accent-coloured; brighter\n // text and slightly stronger fill. Label and box read as one\n // selected unit. Geometry unchanged → overlap test untouched.\n return (\n <g\n key={`grp-${box.key}`}\n data-group={box.key}\n className=\"transition-opacity\"\n style={{ pointerEvents: 'none', opacity: !hoveredGroup || isHovered ? 1 : 0.28 }}\n >\n <rect\n x={box.x}\n y={box.y}\n width={box.w}\n height={box.h}\n rx=\"14\"\n fill={isLight ? '#0f172a' : '#a5b4fc'}\n fillOpacity={isHovered ? (isLight ? 0.05 : 0.09) : (isLight ? 0.025 : 0.045)}\n stroke={isHovered ? pal.legendAccent : pal.ringStroke}\n strokeWidth={isHovered ? 2 : 1.5}\n strokeDasharray={isHovered ? 'none' : '6 6'}\n style={{ transition: 'stroke 200ms ease-out, stroke-width 200ms ease-out, fill-opacity 200ms ease-out' }}\n />\n <text\n x={box.x + 12}\n y={box.y + 14}\n fill={isHovered ? pal.legendHeadline : pal.legendText}\n fontSize=\"13\"\n fontFamily=\"monospace\"\n fontWeight=\"700\"\n style={{ transition: 'fill 200ms ease-out' }}\n >\n {box.key}\n {/* Round 19 / Loop: member-count chip. Inline tspan stays\n in the single <text> bbox the overlap test reads, so\n the node↔label guard still catches if the chip ever\n pushes the label far enough right to clip a node.\n Smaller + lighter weight reads as metadata, not name. */}\n <tspan dx=\"6\" fill={pal.legendText} fontSize=\"11\" fontWeight=\"400\">· {box.count}</tspan>\n </text>\n </g>\n );\n })}\n\n {/* directed message flows */}\n {flowLinks.map((link, index) => {\n const from = nodePositions[link.from];\n const to = nodePositions[link.to];\n if (!from || !to) return null;\n\n // Round 7 / Loop: lift now scales with distance so short links\n // aren't over-bent (long links keep the ~36px hump), and the\n // particle period shortens with link.count so busier edges\n // visibly pulse faster — instant info density on top of the\n // existing stroke-width-by-count chip.\n const dist = Math.hypot(to.x - from.x, to.y - from.y);\n const lift = (index % 2 === 0 ? 1 : -1) * Math.min(36, dist * 0.18);\n const path = curvePath(from, to, lift);\n const width = Math.min(2 + link.count, 7);\n const duration = Math.max(0.9, 2.6 / Math.sqrt(link.count));\n // Round 10 / Loop: freshness fade. An edge that fired ≤30s ago\n // stays at full intensity; over 5 minutes it decays to ~35%.\n // Surfaces \"what's happening now\" vs background chatter without\n // hiding old flow entirely (some context still useful). `now`\n // captured at useMemo-recompute time (every 5s message refresh)\n // — accuracy is within the poll interval, plenty.\n const ageMs = link.last_at ? Math.max(0, Date.now() - Date.parse(link.last_at)) : 0;\n const fresh = Math.max(0.35, 1 - ageMs / (5 * 60 * 1000));\n // Round 16 arrow-tier binning — keep `topo-arrow` as the\n // medium tier id so the legend swatch picks it up unchanged.\n const arrowId = link.count <= 2 ? 'topo-arrow-s'\n : link.count <= 4 ? 'topo-arrow'\n : 'topo-arrow-l';\n\n // Round 39 / Loop: edge hover tooltip — surface the same\n // last_at + count info the freshness fade and arrow tier\n // already encode visually, in plain text. The stroke is the\n // hover target; SVG `<title>` honours newlines on every\n // browser the dashboard targets.\n const lastAt = relativeAgo(link.last_at);\n const tooltip = `${link.from} → ${link.to}\\n${link.count} message${link.count === 1 ? '' : 's'}${lastAt ? ` · last ${lastAt}` : ''}`;\n // Round 40 / Loop: edges follow node hover — when an alias is\n // hovered, every edge touching it brightens, the rest fade.\n // Pairs with the Round 8 group-focus fade on nodes: hover a\n // node to find \"who is this agent talking to\" at a glance.\n // No hover → multiplier is 1.0 (current behaviour preserved).\n const edgeOpacityMul = !hoveredAlias\n ? 1\n : (link.from === hoveredAlias || link.to === hoveredAlias)\n ? 1.7 // boost the touching edge\n : 0.35; // dim the rest\n return (\n <g key={link.key}>\n <path\n d={path}\n fill=\"none\"\n stroke={pal.flowEdge}\n strokeWidth={width}\n opacity={Math.min(1, (isLight ? 0.22 : 0.28) * fresh * edgeOpacityMul)}\n filter={isLight ? undefined : 'url(#topo-glow)'}\n markerEnd={`url(#${arrowId})`}\n className=\"transition-opacity duration-300\"\n style={{ pointerEvents: 'stroke' }}\n >\n <title>{tooltip}</title>\n </path>\n <path\n id={`flow-path-${index}`}\n d={path}\n fill=\"none\"\n stroke={pal.flowPath}\n strokeWidth=\"1\"\n strokeDasharray=\"2 12\"\n opacity={Math.min(1, (isLight ? 0.4 : 0.75) * fresh * edgeOpacityMul)}\n className=\"transition-opacity duration-300\"\n />\n {!reducedMotion && (\n <circle r=\"4\" fill={pal.flowParticle} filter={isLight ? undefined : 'url(#topo-glow)'} opacity={Math.min(1, fresh * edgeOpacityMul)}>\n <animateMotion dur={`${duration}s`} repeatCount=\"indefinite\" path={path} />\n </circle>\n )}\n </g>\n );\n })}\n\n {/* center hub — round 39 sized + round 13 restraint.\n The hub is the control-plane anchor. r39 gave it two outward\n pulses (r 10→38, 2.4s, double-phase) which read as \"loudest\n node in the room\" — wrong semantics: anchors don't emit,\n they hold. r13 swaps the kinetic pulse for a slow opacity\n breath on the static halo (4s, ±15% from base), so the hub\n stays alive without throwing kinetic energy outward. The\n dual-circle \"lit lamp\" core is unchanged. */}\n {layout === 'ring' && (<g data-topo-hub>\n {/* Round 43 / Loop: hub `<title>` summary — hovering the\n central glow now answers \"what is this?\" with a one-line\n fleet snapshot. Duplicates the header chips by design;\n hovering the most visually prominent element is the\n most natural impulse, so satisfy it where the cursor\n already is. Falls clean: omits sub-clauses when their\n counts are zero. */}\n <title>{(() => {\n const total = sessions.length;\n const parts = [`Network hub`, `${total} session${total === 1 ? '' : 's'}`];\n if (onlineNodes.length > 0) parts.push(`${onlineNodes.length} online`);\n if (workingCount > 0) parts.push(`${workingCount} working`);\n if (flowLinks.length > 0) parts.push(`${flowLinks.length} active link${flowLinks.length === 1 ? '' : 's'}`);\n return parts.join(' · ');\n })()}</title>\n {/* grounding halo — now breathes in opacity, no expansion */}\n <circle\n cx={cx} cy={cy} r=\"18\"\n fill={isLight ? '#d1fae5' : '#10b981'}\n opacity={isLight ? 0.42 : 0.12}\n >\n {!reducedMotion && (\n <animate\n attributeName=\"opacity\"\n values={isLight ? '0.32;0.52;0.32' : '0.08;0.16;0.08'}\n dur=\"4s\"\n repeatCount=\"indefinite\"\n />\n )}\n </circle>\n {/* core — 20px diameter, larger inner highlight reads as a \"lit lamp\" */}\n <circle cx={cx} cy={cy} r=\"10\" fill={isLight ? '#059669' : '#10b981'} />\n <circle cx={cx} cy={cy} r=\"5\" fill=\"#d1fae5\" opacity=\"0.9\" />\n </g>)}\n\n {/* agent nodes */}\n {[...onlineNodes, ...offlineNodes].map((session, nodeIdx) => {\n const pos = nodePositions[session.alias];\n if (!pos) return null;\n\n const sseCountFor = (session.network_id ? sseSessions[`${session.network_id}:${session.alias}`] : undefined) ?? sseSessions[session.alias];\n const isOnline = session.status !== 'offline' || !!sseCountFor;\n const status = nodeStatus(session, isOnline, isLight);\n const isActive = activeAliases.has(session.alias);\n // #113: node size scales with the S/M/L control; halos, labels,\n // badge and avatar all derive from `radius` so they follow.\n const radius = Math.round((isOnline ? 26 : 18) * nodeScale);\n // Round 109/110 (Vincent 4582 + 4583 P0): at high node counts\n // the 100px opaque label cards overlapped each other and\n // covered neighbouring avatars. But hiding text entirely went\n // too far (\"还是得有文字\"). So: below the density threshold the\n // full name+status card shows always; above it each node shows\n // a lightweight plain-text alias (no opaque card → can't\n // occlude an avatar), and the full card appears only for the\n // hovered node or once zoomed in past 1.4×.\n const showFullLabel = !denseLayout || hoveredAlias === session.alias || view.zoom >= 1.4;\n // Round 8: when a node in another group is hovered, fade this\n // one. Same-group nodes (incl. singletons matching the hovered\n // alias) stay full. Pure visual focus, geometry unchanged.\n const inFocus = !hoveredGroup || (groupKeys[session.alias] ?? session.alias) === hoveredGroup;\n\n return (\n <g\n key={session.alias}\n data-node={session.alias}\n // Round 3 / Loop: `anet-fade-in` runs once when the <g>\n // mounts — a new session entering the fleet (or the topology\n // first rendering) eases in instead of popping. Re-renders of\n // an existing node don't re-trigger (React preserves the <g>\n // via the alias key), so status changes don't flicker. The\n // global prefers-reduced-motion sweep already neutralises it.\n className=\"group transition-opacity anet-fade-in\"\n style={{\n cursor: 'pointer',\n // Round 17 / Loop: offline nodes drop to 0.6 at rest so\n // online nodes pop without losing the offline-as-ghost\n // information. The dashed stroke + smaller radius already\n // say \"offline\"; dimming the whole group strengthens the\n // online-vs-offline hierarchy at first glance. Exempt the\n // chat-focused node — if the user explicitly opened a\n // popover targeting an offline alias, that node stays\n // full-brightness so the focus ring + popover read as one\n // selected thing rather than a dimmed selection. Group-\n // hover fade (Round 8) still wins when inFocus is false.\n opacity: !inFocus\n ? 0.32\n : chatAlias === session.alias\n ? 1\n : isOnline ? 1 : 0.6,\n // Round 9 / Loop: stagger the anet-fade-in so the topology\n // reveals as a wave on first paint instead of one big pop.\n // Cap at 24 indices (≈600ms tail) so 50-node fleets still\n // finish revealing within a beat. CSS animation-delay only\n // applies during the keyframe — re-renders without a new\n // mount (same alias key) don't replay, so status changes\n // never trigger the stagger again.\n animationDelay: `${Math.min(nodeIdx, 24) * 25}ms`,\n }}\n // Stop the pointerdown from reaching the SVG pan handler: the\n // SVG calls setPointerCapture, and a captured pointer makes\n // Chromium fire the follow-up `click` on the SVG instead of\n // this node — so without this the node's onClick never runs.\n // Side effect (intended): you pan from empty canvas, not by\n // grabbing a node.\n onPointerDown={(e) => e.stopPropagation()}\n // Track hover globally (not just under denseLayout) so the\n // Round 8 group-focus fade works at any fleet size.\n onPointerEnter={() => setHoveredAlias(session.alias)}\n onPointerLeave={() => setHoveredAlias(prev => (prev === session.alias ? null : prev))}\n onClick={() => {\n setChatAlias(session.alias);\n // Round 14 ripple — capture position, radius and status\n // colour at click time so the one-shot circle is self-\n // contained (no re-render-time recomputation needed).\n setClickRipple({\n ts: Date.now(),\n x: pos.x, y: pos.y, r0: radius,\n color: status.primary,\n });\n setTimeout(() => setClickRipple(prev =>\n prev && Date.now() - prev.ts >= 590 ? null : prev), 600);\n }}\n >\n {/* Issue #96: native hover tooltip — \"Vendor · model · Runtime\".\n Falls back to just the alias when the node reports no\n model/runtime.\n Round 33 / Loop: cwd line answers \"what is this agent on?\".\n Round 34 / Loop: for offline nodes, append \"last seen: 6m ago\"\n so the operator knows whether to wait or chase. Online nodes\n skip the line (Round 27's 1 h ghost age-out means anything\n still online has heartbeated recently — the line would just\n be noise). Accepts both ISO (\"…T06:00:28Z\") and SQL-style\n (\"… 06:00:28\" assumed UTC) formats. */}\n {(() => {\n // Round 35 / Loop: TZ-safe parsing via the shared lib helper\n // — same parseHubTime is used by isGhost above (Round 38\n // factored it to app/lib/time.ts so both paths interpret SQL\n // bare timestamps as UTC on every browser).\n const lastSeen = !isOnline && session.last_seen_at ? relativeAgo(session.last_seen_at) : null;\n return (\n <title>{[\n identityLine(session.model, session.runtime) || session.alias,\n session.project_dir ? `cwd: ${session.project_dir}` : null,\n lastSeen ? `last seen: ${lastSeen}` : null,\n ].filter(Boolean).join('\\n')}</title>\n );\n })()}\n {/* Round 2 / Loop: hover ring — a thin outer stroke that fades\n in when the cursor enters the node, signalling clickability\n (real-user feedback for the chat-popover open). Pure CSS via\n Tailwind group-hover, so it costs nothing per frame and\n respects prefers-reduced-motion via the global media query. */}\n <circle\n cx={pos.x}\n cy={pos.y}\n r={radius + 12}\n fill=\"none\"\n stroke={status.primary}\n // strokeWidth must NOT be 1.5 (offline status ring) or 3\n // (online status ring) — the overlap test selects by those\n // exact widths and would mis-count this invisible hover\n // ring as a node footprint.\n strokeWidth=\"2\"\n className=\"opacity-0 group-hover:opacity-70 transition-opacity duration-150\"\n style={{ pointerEvents: 'none' }}\n />\n {/* Round 11 / Loop: chat-focus ring — when the ChatPopover is\n open targeting this node, anchor a persistent ring around\n it so the floating popover visibly links back to its source\n node. Static (not pulsing) so it reads as \"selected state\"\n rather than \"this node is active\". strokeWidth=2.5 stays\n clear of the overlap-test selectors (1.5 / 3). Sits just\n outside the halo radius+8 so it never overlaps a neighbour\n (halos already pack flush in dense grids). */}\n {chatAlias === session.alias && (\n <circle\n cx={pos.x}\n cy={pos.y}\n r={radius + 14}\n fill=\"none\"\n stroke={status.primary}\n strokeWidth=\"2.5\"\n opacity={isLight ? 0.85 : 0.95}\n filter={!isLight ? 'url(#topo-glow)' : undefined}\n className=\"transition-opacity duration-200\"\n style={{ pointerEvents: 'none' }}\n />\n )}\n {isActive && !reducedMotion && (\n <circle cx={pos.x} cy={pos.y} r={radius + 14} fill={status.primary} opacity={isLight ? 0.08 : 0.12}>\n <animate attributeName=\"r\" values={`${radius + 8};${radius + 22};${radius + 8}`} dur=\"2.4s\" repeatCount=\"indefinite\" />\n <animate attributeName=\"opacity\" values={isLight ? '0.12;0.02;0.12' : '0.18;0.04;0.18'} dur=\"2.4s\" repeatCount=\"indefinite\" />\n </circle>\n )}\n {/* Round 4 / Loop: transition-[fill,stroke,opacity] smooths\n status colour changes so idle↔working↔offline doesn't snap\n — task replies / node-rename / SSE updates ease in. */}\n <circle\n cx={pos.x}\n cy={pos.y}\n r={radius + 8}\n fill={status.halo}\n opacity={isOnline ? (isLight ? 0.85 : 0.65) : (isLight ? 0.4 : 0.25)}\n className=\"transition-[fill,opacity] duration-300 ease-out\"\n />\n <circle\n cx={pos.x}\n cy={pos.y}\n r={radius}\n fill={isOnline ? pal.nodeFill.online : pal.nodeFill.offline}\n stroke={status.primary}\n strokeWidth={isOnline ? 3 : 1.5}\n strokeDasharray={isOnline ? 'none' : '5 5'}\n filter={isOnline && !isLight ? 'url(#topo-glow)' : undefined}\n className=\"transition-[fill,stroke] duration-300 ease-out\"\n />\n {/* Issue #96: node \"avatar\" is now driven by the model\n vendor. Decision order:\n 1. ?brand=intern flag, or an intern-aliased node with\n no model field → 书生 coin (preserves #79).\n 2. vendor has a packaged logo asset → that logo image\n (intern-s1-* models land here via vendorForModel).\n 3. known vendor, logo asset not shipped yet → a\n vendor-tinted monogram (spec-mandated fallback).\n 4. unknown vendor / null model → the prefix-group\n hue-hashed initial (#83/#99 behaviour, unchanged). */}\n {(() => {\n const ar = Math.round((isOnline ? 14 : 10) * nodeScale);\n const size = radius * 2;\n const vendor = vendorForModel(session.model);\n const internByAlias = /书生|书小生|intern/i.test(session.alias);\n\n if (isIntern || internByAlias || vendor.logo) {\n return (\n <image\n href={vendor.logo ?? '/intern_avatar.png'}\n x={pos.x - size / 2}\n y={pos.y - size / 2}\n width={size}\n height={size}\n preserveAspectRatio=\"xMidYMid meet\"\n />\n );\n }\n if (vendor.id !== 'unknown') {\n // Known model house, logo asset not in public/vendors/\n // yet — vendor-tinted monogram stands in.\n return (\n <>\n <circle cx={pos.x} cy={pos.y} r={ar} fill={vendor.mono.bg} stroke={vendor.mono.ring} strokeWidth=\"1\" />\n <text\n x={pos.x} y={pos.y} dy=\"0.34em\" textAnchor=\"middle\"\n fill={vendor.mono.text} fontSize={ar}\n fontFamily=\"monospace\" fontWeight=\"700\"\n >\n {vendor.initial}\n </text>\n </>\n );\n }\n // Round 106 (issue #83): hue keyed to the prefix group,\n // not the full alias — every 通信* node shares one color.\n const c = aliasAvatarColors(groupKeys[session.alias] || session.alias);\n return (\n <>\n <circle cx={pos.x} cy={pos.y} r={ar} fill={c.bg} stroke={c.ring} strokeWidth=\"1\" />\n <text\n x={pos.x}\n y={pos.y}\n dy=\"0.34em\"\n textAnchor=\"middle\"\n fill={c.text}\n fontSize={ar}\n fontFamily=\"monospace\"\n fontWeight=\"700\"\n >\n {aliasInitial(session.alias)}\n </text>\n </>\n );\n })()}\n {/* Issue #96: runtime badge — small corner glyph marking the\n execution shell (CLI / SDK / HTTP API). Sits bottom-right\n of the avatar; colours kept off the working/idle/offline\n status hues. Absent when the node reports no runtime. */}\n {(() => {\n const rt = runtimeIdentity(session.runtime);\n if (!rt) return null;\n const br = isOnline ? 7 : 5.5;\n const bx = pos.x + radius * 0.72;\n const by = pos.y + radius * 0.72;\n const icon = br * 2 * 0.62;\n return (\n <g style={{ pointerEvents: 'none' }}>\n <circle cx={bx} cy={by} r={br} fill={pal.containerBg} stroke={rt.color} strokeWidth=\"1.5\" />\n <g transform={`translate(${bx - icon / 2} ${by - icon / 2}) scale(${icon / 24})`}>\n <path d={rt.iconPath} fill=\"none\" stroke={rt.color} strokeWidth=\"2.4\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </g>\n </g>\n );\n })()}\n {session.status === 'working' && (() => {\n // Round 24 / Loop: pulse rate ↔ traffic. The dot's dur\n // was a flat 1.1s — every working node looked equally\n // busy. Mapping it to sse:N lets the eye land on what's\n // actually hot. 3 discrete tiers read cleaner than\n // continuous easing at a glance; thresholds picked so\n // typical 1-2-SSE Claude/Codex sessions stay in the\n // \"active\" tier and only multi-pane orchestrators pop\n // into the \"busy\" tier. Geometry unchanged (r=2.5).\n const sse = sseCountFor ?? 0;\n const dur = sse >= 4 ? '0.7s' : sse >= 2 ? '0.9s' : '1.2s';\n return (\n <circle cx={pos.x} cy={pos.y - (radius - 6)} r=\"2.5\" fill={pal.flowParticle} data-pulse-dur={dur} opacity={reducedMotion ? 0.6 : undefined}>\n {!reducedMotion && (\n <animate attributeName=\"opacity\" values=\"1;0.25;1\" dur={dur} repeatCount=\"indefinite\" />\n )}\n </circle>\n );\n })()}\n\n {/* Round 98 (issue #61): label rect 124px → 100px.\n Round 109/110 (Vincent P0): full opaque card below the\n density threshold / on hover / when zoomed; otherwise a\n lightweight plain-text alias that keeps every node\n labelled without an opaque box covering its neighbours.\n Round 15 / Loop: when nodeScale=S the node shrinks 30%\n but the label card was staying full-size, so the label\n visually outweighed the small node. Tighten the card\n frame, alias / sub fontSize, drop-offset and truncate\n length specifically for S; M and L keep their existing\n sizes (M ≈ L for labels by design — the S user is the\n one who explicitly asked for a denser view). */}\n {(() => {\n const isSmall = nodeScale < 0.8;\n const cardW = isSmall ? 88 : 100;\n const cardH = isSmall ? 36 : 42;\n const cardTopY = isSmall ? -12 : -14;\n const aliasFs = isSmall ? 11 : 12;\n const subFs = isSmall ? 8 : 9;\n const subY = isSmall ? 15 : 17;\n const dropY = isSmall ? 18 : 22;\n const fullMax = isSmall ? 11 : 12;\n const denseFs = isSmall ? 9 : 10;\n const denseDrop = isSmall ? 12 : 14;\n // Round 26 / Loop: micro-lift the label group on hover —\n // 1.5 px upward, 200 ms ease. Pairs with the Round 18\n // group-box hover-accent treatment to give the same\n // \"this is the focused element\" feedback at the per-\n // node level. CSS transform stacks onto the SVG\n // positioning transform attribute (SVG 2 cascade);\n // bbox is unchanged at rest, so the overlap-test gate\n // continues to see the geometric layout it expects.\n return showFullLabel ? (\n <g transform={`translate(${pos.x}, ${pos.y + radius + dropY})`} style={{ pointerEvents: 'none' }}\n className=\"transition-transform duration-200 group-hover:-translate-y-[1.5px]\">\n <rect x={-cardW / 2} y={cardTopY} width={cardW} height={cardH} rx=\"6\" fill={pal.labelBox.fill} stroke={pal.labelBox.stroke} opacity={isLight ? 1 : 0.94} />\n <text x=\"0\" y=\"1\" textAnchor=\"middle\" fill={status.text} fontSize={aliasFs} fontFamily=\"monospace\" fontWeight=\"700\">\n {truncate(session.alias, fullMax)}\n </text>\n <text x=\"0\" y={subY} textAnchor=\"middle\" fill={status.primary} fontSize={subFs} fontFamily=\"monospace\">\n {status.label}{isOnline && sseCountFor != null ? ` sse:${sseCountFor}` : ''}\n </text>\n </g>\n ) : (\n <text\n x={pos.x}\n y={pos.y + radius + denseDrop}\n textAnchor=\"middle\"\n fill={status.text}\n fontSize={denseFs}\n fontFamily=\"monospace\"\n fontWeight=\"700\"\n opacity={0.9}\n className=\"transition-transform duration-200 group-hover:-translate-y-[1.5px]\"\n style={{ pointerEvents: 'none', paintOrder: 'stroke' }}\n stroke={pal.containerBg}\n strokeWidth=\"3\"\n >\n {truncate(session.alias, isSmall ? 9 : 10)}\n </text>\n );\n })()}\n </g>\n );\n })}\n\n {/* Round 14 / Loop: click ripple — one-shot expanding ring from\n the clicked node, ~500ms, status-coloured. Sits inside the\n zoom/pan <g> so it scales / pans with the topology. Keyed by\n ts so a re-click on any node (same or different) remounts the\n <circle> and the SMIL <animate> elements replay from t=0.\n strokeWidth=2 doesn't match the overlap-test selectors. */}\n {clickRipple && !reducedMotion && (\n <circle\n key={clickRipple.ts}\n cx={clickRipple.x}\n cy={clickRipple.y}\n r={clickRipple.r0 + 4}\n fill=\"none\"\n stroke={clickRipple.color}\n strokeWidth=\"2\"\n opacity=\"0\"\n style={{ pointerEvents: 'none' }}\n >\n <animate attributeName=\"r\" values={`${clickRipple.r0 + 4};${clickRipple.r0 + 30}`} dur=\"0.5s\" fill=\"freeze\" />\n <animate attributeName=\"opacity\" values=\"0.7;0\" dur=\"0.5s\" fill=\"freeze\" />\n </circle>\n )}\n\n </g>\n\n {/* #112: overlay panels (recent-signal + legend) render OUTSIDE the\n zoom/pan <g> so they stay fixed while the topology pans/zooms.\n They're sized + tucked into the top corners so every corner of\n each panel is >325px from the canvas centre — i.e. fully outside\n the outermost (offline) ring. No node on any ring can reach the\n corner triangles, so the panels never overlap a node, in ring\n OR grid layout (Vincent 4727 zero-overlap criterion). */}\n {/* latest flow labels */}\n <g transform=\"translate(16, 16)\">\n <rect x=\"0\" y=\"0\" width=\"230\" height=\"84\" rx=\"10\" fill={pal.legendBox.fill} stroke={pal.legendBox.stroke} opacity={isLight ? 0.97 : 0.92} />\n <text x=\"13\" y=\"21\" fill={pal.legendHeadline} fontSize=\"12\" fontFamily=\"monospace\" fontWeight=\"700\">recent signal</text>\n <text x=\"150\" y=\"21\" fill={pal.legendAccent} fontSize=\"10\" fontFamily=\"monospace\">{messages.length} msgs</text>\n {/* Round 45 / Loop: empty state. The panel used to render\n \"recent signal\" + \"0 msgs\" with three blank slots below\n when no flow yet — read as \"broken\" rather than \"quiet\".\n A muted centred placeholder makes the empty state\n deliberate. Messages count CAN diverge from flowLinks\n count (raw count vs. deduped pairs), so the placeholder\n fires on flowLinks.length=0 specifically. */}\n {flowLinks.length === 0 ? (\n <text x=\"115\" y=\"60\" textAnchor=\"middle\" fill={pal.legendText} fontSize=\"10\" fontFamily=\"monospace\" fontStyle=\"italic\" opacity={0.65} data-recent-signal-empty>\n no flow yet\n </text>\n ) : (\n flowLinks.slice(0, 3).map((link, index) => (\n <text key={link.key} x=\"13\" y={38 + index * 16} fill={pal.legendText} fontSize=\"9\" fontFamily=\"monospace\">\n {truncate(link.from, 6)} {'->'} {truncate(link.to, 6)} / {link.count} / {truncate(link.content, 12)}\n </text>\n ))\n )}\n </g>\n\n {/* legend */}\n <g transform=\"translate(760, 16)\">\n <rect x=\"0\" y=\"0\" width=\"224\" height=\"96\" rx=\"10\" fill={pal.legendBox.fill} stroke={pal.legendBox.stroke} opacity={isLight ? 0.97 : 0.92} />\n <circle cx=\"16\" cy=\"24\" r=\"5.5\" fill={isLight ? '#059669' : '#22c55e'} />\n <text x=\"30\" y=\"28\" fill={pal.legendText} fontSize=\"11\" fontFamily=\"monospace\">working node</text>\n <circle cx=\"16\" cy=\"48\" r=\"5.5\" fill={isLight ? '#0d9488' : '#2dd4bf'} />\n <text x=\"30\" y=\"52\" fill={pal.legendText} fontSize=\"11\" fontFamily=\"monospace\">online idle</text>\n <circle cx=\"16\" cy=\"72\" r=\"5.5\" fill={isLight ? '#94a3b8' : '#6b7280'} />\n <text x=\"30\" y=\"76\" fill={pal.legendText} fontSize=\"11\" fontFamily=\"monospace\">offline / no SSE</text>\n <path d=\"M140,72 Q164,48 196,72\" fill=\"none\" stroke={pal.flowEdge} strokeWidth=\"3\" markerEnd=\"url(#topo-arrow)\" />\n </g>\n </svg>\n\n {/* Round 30 / Loop: minimap. Big fleets in fullscreen mode at high\n zoom let users lose their position — the minimap shows the\n whole topology miniaturised plus a viewport rectangle so the\n user always knows where they are. Click anywhere to recenter\n the canvas there. Only mounted when the view is non-default\n (zoomed or panned) since at 1× centered the minimap and the\n canvas show the same thing. HTML overlay so it stays fixed\n while the SVG transforms. */}\n {(() => {\n const isDefaultView = Math.abs(view.zoom - 1) < 0.01 && Math.abs(view.x) < 1 && Math.abs(view.y) < 1;\n if (isDefaultView || (onlineNodes.length + offlineNodes.length) === 0) return null;\n const MW = 120, MH = 82;\n const sx = MW / VIEWBOX_W, sy = MH / VIEWBOX_H;\n const rectX = (-view.x / view.zoom) * sx;\n const rectY = (-view.y / view.zoom) * sy;\n const rectW = (VIEWBOX_W / view.zoom) * sx;\n const rectH = (VIEWBOX_H / view.zoom) * sy;\n return (\n <div\n className=\"absolute right-3 rounded-md border shadow-lg shadow-black/30 overflow-hidden anet-fade-in\"\n style={{ bottom: 56, background: pal.legendBox.fill, borderColor: pal.containerBorder, cursor: 'crosshair' }}\n role=\"img\"\n aria-label=\"Topology minimap — click to recenter\"\n title=\"Minimap · click to recenter\"\n onClick={(e) => {\n const r = e.currentTarget.getBoundingClientRect();\n const fx = (e.clientX - r.left) / r.width;\n const fy = (e.clientY - r.top) / r.height;\n setView(prev => ({\n ...prev,\n x: VIEWBOX_W / 2 - fx * VIEWBOX_W * prev.zoom,\n y: VIEWBOX_H / 2 - fy * VIEWBOX_H * prev.zoom,\n }));\n }}\n data-topo-minimap\n >\n <svg width={MW} height={MH} viewBox={`0 0 ${MW} ${MH}`} style={{ display: 'block' }}>\n {[...onlineNodes, ...offlineNodes].map(s => {\n const p = nodePositions[s.alias];\n if (!p) return null;\n const sseN = (s.network_id ? sseSessions[`${s.network_id}:${s.alias}`] : undefined) ?? sseSessions[s.alias];\n const isOn = s.status !== 'offline' || !!sseN;\n const st = nodeStatus(s, isOn, isLight);\n return <circle key={s.alias} cx={p.x * sx} cy={p.y * sy} r={isOn ? 1.7 : 1.2} fill={st.primary} opacity={isOn ? 0.9 : 0.5} />;\n })}\n {/* viewport rectangle */}\n <rect\n x={Math.max(0, rectX)} y={Math.max(0, rectY)}\n width={Math.max(0, Math.min(MW - Math.max(0, rectX), rectW))}\n height={Math.max(0, Math.min(MH - Math.max(0, rectY), rectH))}\n fill=\"none\" stroke={pal.legendAccent} strokeWidth=\"1\" opacity=\"0.9\"\n />\n </svg>\n </div>\n );\n })()}\n {/* Round 103 (issue #81): zoom / pan / fullscreen controls — HTML\n overlay so they stay fixed while the SVG content transforms.\n Round 104: Vincent 实测 — the reset action used to be hidden\n behind the \"%\" label (looked like an indicator, not a button).\n Split into a plain % readout + an explicit reset button with\n its own icon + tooltip. */}\n <div className=\"absolute bottom-3 right-3 flex items-center gap-1.5 text-xs select-none\">\n {/* #113: node size — S / M / L segmented control (Vincent 4727). */}\n <div\n className=\"flex items-center rounded-md border overflow-hidden\"\n style={{ background: pal.legendBox.fill, borderColor: pal.containerBorder }}\n role=\"group\"\n aria-label=\"Node size\"\n >\n {([['S', 0.7], ['M', 0.84], ['L', 1]] as const).map(([lbl, v], idx) => (\n <button\n key={lbl}\n onClick={() => pickNodeScale(v)}\n aria-pressed={nodeScale === v}\n title={`Node size: ${lbl === 'S' ? 'small' : lbl === 'M' ? 'medium' : 'large'}`}\n className={`px-2 py-1 transition-colors ${idx > 0 ? 'border-l' : ''} ${nodeScale === v ? 'bg-cyan-500/15 text-cyan-300' : 'hover:bg-white/5'}`}\n style={{ color: nodeScale === v ? undefined : pal.legendText, borderColor: pal.containerBorder }}\n >\n {lbl}\n </button>\n ))}\n </div>\n <div\n className=\"flex items-center rounded-md border overflow-hidden\"\n style={{ background: pal.legendBox.fill, borderColor: pal.containerBorder }}\n >\n <button\n onClick={() => zoomBy(1 / 1.2)}\n className=\"px-2 py-1 hover:bg-white/5 transition-colors\"\n style={{ color: pal.legendText }}\n aria-label=\"Zoom out\"\n title=\"Zoom out (−)\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" aria-hidden><path d=\"M5 12h14\" /></svg>\n </button>\n <span\n className=\"px-2 py-1 tabular-nums border-x text-center\"\n style={{ color: pal.legendText, borderColor: pal.containerBorder, minWidth: 46 }}\n title=\"Current zoom level\"\n >\n {Math.round(view.zoom * 100)}%\n </span>\n <button\n onClick={() => zoomBy(1.2)}\n className=\"px-2 py-1 hover:bg-white/5 transition-colors\"\n style={{ color: pal.legendText }}\n aria-label=\"Zoom in\"\n title=\"Zoom in (+)\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" aria-hidden><path d=\"M12 5v14M5 12h14\" /></svg>\n </button>\n </div>\n <button\n onClick={resetView}\n className=\"p-1.5 rounded-md border hover:bg-white/5 transition-colors\"\n style={{ background: pal.legendBox.fill, borderColor: pal.containerBorder, color: pal.legendText }}\n aria-label=\"Reset view\"\n title=\"Reset zoom + pan (0, or double-click the canvas)\"\n >\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M3 12a9 9 0 1 0 9-9 9 9 0 0 0-6.4 2.6L3 8\" />\n <path d=\"M3 3v5h5\" />\n </svg>\n </button>\n <button\n onClick={toggleFullscreen}\n className=\"p-1.5 rounded-md border hover:bg-white/5 transition-colors\"\n style={{ background: pal.legendBox.fill, borderColor: pal.containerBorder, color: pal.legendText }}\n aria-label={isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'}\n title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}\n >\n {isFullscreen ? (\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M8 3v4a1 1 0 0 1-1 1H3M21 8h-4a1 1 0 0 1-1-1V3M3 16h4a1 1 0 0 1 1 1v4M16 21v-4a1 1 0 0 1 1-1h4\" />\n </svg>\n ) : (\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M3 8V5a2 2 0 0 1 2-2h3M21 8V5a2 2 0 0 0-2-2h-3M3 16v3a2 2 0 0 0 2 2h3M21 16v3a2 2 0 0 1-2 2h-3\" />\n </svg>\n )}\n </button>\n </div>\n\n {/* Issue #100/#106: draggable, resizable singleton chat popover.\n position:fixed so it floats above the page (overflow-hidden here\n doesn't clip fixed children). Rendered *inside* the container so\n that when the graph goes fullscreen (#81) the popover joins the\n fullscreen subtree and stays visible — a sibling render would be\n outside the fullscreened element and disappear. */}\n {chatAlias && (\n <ChatPopover alias={chatAlias} onClose={() => setChatAlias(null)} />\n )}\n </div>\n </section>\n );\n}\n","'use client';\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { AliasAvatar } from './AliasAvatar';\nimport { TaskChatPanel } from './TaskChatPanel';\nimport { useSessions } from '../lib/hooks';\nimport { relativeAgo } from '../lib/time';\n\ninterface ChatPopoverProps {\n /** Node alias to chat with. Changing it switches the conversation. */\n alias: string;\n onClose: () => void;\n}\n\nconst MAX_W = 380;\nconst MAX_H = 520;\nconst MIN_W = 300;\nconst MIN_H = 320;\nconst MARGIN = 16;\nconst MOBILE_BP = 640;\n\n/**\n * Issue #100: a floating, draggable chat window opened by clicking a node\n * avatar in the topology graph. Singleton — the parent (TopoGraph) keeps a\n * single `chatAlias`, so clicking another node just swaps `alias` here and\n * the conversation switches in place.\n *\n * Issue #106: a bottom-right handle resizes the window (drag to change w/h,\n * clamped to MIN_W/MIN_H .. the viewport). Coexists with the header move-drag\n * and the close button — each interaction lives on a distinct element and\n * stops its own pointerdown from reaching the others.\n *\n * One consistent design across viewports: a floating draggable card sized to\n * fit (`min(380, vw-32) × min(520, vh-96)`). On a phone it ends up near\n * full-width, so it's docked low on open — the graph above stays visible, and\n * to chat with a different node you drag it down / tap an exposed avatar.\n *\n * The chat body reuses TaskChatPanel's `inline` mode — send / SSE-receive /\n * history are already solved there; this component only adds the floating\n * shell + drag/resize behaviour.\n */\n/** Round 37 / Loop: surface node metadata (cwd + last-seen) inside the\n * ChatPopover header. The SVG <title> tooltip (Rounds 33-34) only shows\n * on hover-over-node, which is lost once the popover is open and\n * potentially dragged away. Lifting cwd and last-seen into the popover\n * header keeps the context where the user actually needs it.\n *\n * Round 38: relativeAgo factored to app/lib/time.ts so this file shares\n * the same TZ-safe parser as TopoGraph (was a duplicated mirror until\n * this round). */\n\nexport function ChatPopover({ alias, onClose }: ChatPopoverProps) {\n // Position + size are resolved on mount (SSR-safe defaults here).\n const [pos, setPos] = useState({ x: 0, y: 0 });\n const [size, setSize] = useState({ w: MAX_W, h: MAX_H });\n const dragRef = useRef<{ active: boolean; startX: number; startY: number; baseX: number; baseY: number }>({\n active: false, startX: 0, startY: 0, baseX: 0, baseY: 0,\n });\n const resizeRef = useRef<{ active: boolean; startX: number; startY: number; baseW: number; baseH: number }>({\n active: false, startX: 0, startY: 0, baseW: 0, baseH: 0,\n });\n\n // Round 37 / Loop: pull the target session out of the SWR cache that\n // TopoGraph already populates — same URL, so no extra network fetch.\n const { sessions } = useSessions();\n const session = useMemo(() => sessions.find(s => s.alias === alias), [sessions, alias]);\n const isOnline = !!session && session.status !== 'offline';\n const lastSeenLine = !isOnline ? relativeAgo(session?.last_seen_at) : null;\n\n const clamp = useCallback((x: number, y: number, w: number, h: number) => {\n const maxX = Math.max(MARGIN, window.innerWidth - w - MARGIN);\n const maxY = Math.max(MARGIN, window.innerHeight - h - MARGIN);\n return {\n x: Math.min(Math.max(MARGIN, x), maxX),\n y: Math.min(Math.max(MARGIN, y), maxY),\n };\n }, []);\n\n useEffect(() => {\n const place = () => {\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n const w = Math.min(MAX_W, vw - MARGIN * 2);\n const h = Math.min(MAX_H, vh - MARGIN * 6);\n setSize({ w, h });\n const mobile = vw < MOBILE_BP;\n // Desktop: top-right of the graph. Mobile: docked low so the graph\n // above stays visible — switch nodes by tapping an exposed avatar.\n const x = mobile ? MARGIN : vw - w - 24;\n const y = mobile ? vh - h - MARGIN : 96;\n setPos(clamp(x, y, w, h));\n };\n place();\n // Keep the popover on-screen if the window is resized.\n window.addEventListener('resize', place);\n return () => window.removeEventListener('resize', place);\n }, [clamp]);\n\n // Esc closes — matches the rest of the dashboard's overlay convention.\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [onClose]);\n\n const onPointerDown = (e: React.PointerEvent<HTMLDivElement>) => {\n if (e.button !== 0) return;\n (e.currentTarget as Element).setPointerCapture?.(e.pointerId);\n dragRef.current = { active: true, startX: e.clientX, startY: e.clientY, baseX: pos.x, baseY: pos.y };\n };\n const onPointerMove = (e: React.PointerEvent<HTMLDivElement>) => {\n const d = dragRef.current;\n if (!d.active) return;\n setPos(clamp(d.baseX + (e.clientX - d.startX), d.baseY + (e.clientY - d.startY), size.w, size.h));\n };\n const onPointerUp = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!dragRef.current.active) return;\n dragRef.current.active = false;\n try { (e.currentTarget as Element).releasePointerCapture?.(e.pointerId); } catch {}\n };\n\n // Resize from the bottom-right handle. stopPropagation keeps the header\n // move-drag out of it; the popover is top-left anchored so growing it can\n // only push the bottom/right edges, which we clamp to the viewport.\n const onResizeDown = (e: React.PointerEvent<HTMLDivElement>) => {\n if (e.button !== 0) return;\n e.stopPropagation();\n (e.currentTarget as Element).setPointerCapture?.(e.pointerId);\n resizeRef.current = { active: true, startX: e.clientX, startY: e.clientY, baseW: size.w, baseH: size.h };\n };\n const onResizeMove = (e: React.PointerEvent<HTMLDivElement>) => {\n const r = resizeRef.current;\n if (!r.active) return;\n e.stopPropagation();\n const maxW = Math.max(MIN_W, window.innerWidth - pos.x - MARGIN);\n const maxH = Math.max(MIN_H, window.innerHeight - pos.y - MARGIN);\n setSize({\n w: Math.min(maxW, Math.max(MIN_W, r.baseW + (e.clientX - r.startX))),\n h: Math.min(maxH, Math.max(MIN_H, r.baseH + (e.clientY - r.startY))),\n });\n };\n const onResizeUp = (e: React.PointerEvent<HTMLDivElement>) => {\n if (!resizeRef.current.active) return;\n resizeRef.current.active = false;\n e.stopPropagation();\n try { (e.currentTarget as Element).releasePointerCapture?.(e.pointerId); } catch {}\n };\n\n return (\n <div\n className=\"fixed z-50 flex flex-col overflow-hidden rounded-xl border border-[var(--border)] bg-[var(--bg)] shadow-2xl shadow-black/60 anet-fade-in\"\n style={{ left: pos.x, top: pos.y, width: size.w, height: size.h }}\n role=\"dialog\"\n aria-label={`Chat with ${alias}`}\n >\n {/* Drag handle — the whole header bar moves the window. */}\n <div\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerCancel={onPointerUp}\n className=\"flex items-center justify-between px-3 py-2.5 border-b border-[var(--border)] bg-[var(--bg-secondary)] rounded-t-xl cursor-grab active:cursor-grabbing select-none touch-none\"\n >\n <div className=\"flex items-center gap-2.5 min-w-0\">\n <AliasAvatar alias={alias} size={28} />\n <div className=\"min-w-0\">\n <div className=\"text-sm font-semibold text-[var(--fg)] truncate\">{alias}</div>\n {/* Round 37: cwd / last-seen lines surface the same metadata\n the SVG <title> tooltip carries (rounds 33-34), but inside\n the popover where it stays accessible after dragging the\n window away from the node. Fall back to the drag-hint\n when no metadata is reported. */}\n {session?.project_dir ? (\n <div className=\"text-[10px] text-[var(--fg-muted)] truncate font-mono\" title={session.project_dir} data-popover-cwd>\n cwd: {session.project_dir}\n </div>\n ) : null}\n {lastSeenLine ? (\n <div className=\"text-[10px] text-[var(--fg-muted)] truncate\" data-popover-lastseen>\n last seen: {lastSeenLine}\n </div>\n ) : null}\n {!session?.project_dir && !lastSeenLine ? (\n <div className=\"text-[10px] text-[var(--fg-muted)]\">Drag to move · Esc to close</div>\n ) : null}\n </div>\n </div>\n <button\n onClick={onClose}\n // Without this the header's drag handler captures the pointer and\n // Chromium retargets the click to the header — the button never fires.\n onPointerDown={(e) => e.stopPropagation()}\n aria-label=\"Close chat\"\n className=\"text-[var(--fg-muted)] hover:text-[var(--fg)] p-1.5 rounded-lg hover:bg-[var(--bg-elevated)] shrink-0\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n {/* Chat body — TaskChatPanel inline mode owns send / SSE / history. */}\n <div className=\"flex-1 min-h-0\">\n <TaskChatPanel alias={alias} onClose={onClose} inline />\n </div>\n\n {/* Issue #106: bottom-right resize handle. */}\n <div\n onPointerDown={onResizeDown}\n onPointerMove={onResizeMove}\n onPointerUp={onResizeUp}\n onPointerCancel={onResizeUp}\n aria-label=\"Resize chat\"\n className=\"absolute bottom-0 right-0 w-5 h-5 cursor-nwse-resize touch-none z-10\"\n style={{ touchAction: 'none' }}\n >\n <svg className=\"absolute bottom-0.5 right-0.5 w-3 h-3 text-[var(--fg-dim)]\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" aria-hidden>\n <path d=\"M11 5L5 11M11 9L9 11\" />\n </svg>\n </div>\n </div>\n );\n}\n","/** Issue #96: node visual identity — model vendor + runtime.\n *\n * Single source for two orthogonal node dimensions:\n * - vendor : which model house powers the node (avatar body)\n * - runtime: which execution shell it runs in (corner badge)\n *\n * Both are driven by the server `model` / `runtime` fields added in\n * commhub-server 0.8.1-preview.0 (#96 Phase 1, commit 08482ef). Old nodes\n * report `model: null` / `runtime: null` and fall back gracefully — never a\n * broken image or blank avatar.\n *\n * Adding a vendor = one entry in VENDOR_RULES. Dropping a real logo file into\n * public/vendors/ + setting `logo` lights it up with zero render-code change;\n * until then a vendor-tinted monogram stands in (not a fake official logo).\n */\n\nexport interface VendorIdentity {\n id: string;\n label: string;\n /** Monogram fallback colours, used when `logo` is null. */\n mono: { bg: string; ring: string; text: string };\n /** 1-char monogram shown when there's no logo asset. */\n initial: string;\n /** Packaged logo asset path, or null → render the monogram instead. */\n logo: string | null;\n}\n\nconst UNKNOWN_VENDOR: VendorIdentity = {\n id: 'unknown',\n label: 'Unknown vendor',\n mono: { bg: 'hsl(220 10% 26%)', ring: 'hsl(220 10% 46%)', text: 'hsl(220 14% 82%)' },\n initial: '?',\n logo: null,\n};\n\n// Ordered prefix rules — first match wins. `test` runs against a lowercased\n// model id. Keep the most specific prefixes first.\nconst VENDOR_RULES: Array<{ test: (m: string) => boolean; vendor: VendorIdentity }> = [\n {\n test: (m) => m.startsWith('intern'),\n vendor: {\n id: 'intern',\n label: '书生 · 上海 AI 实验室',\n mono: { bg: 'hsl(28 38% 24%)', ring: 'hsl(32 45% 52%)', text: 'hsl(34 60% 82%)' },\n initial: '书',\n // #79 shipped this asset — reuse it as the 书生 vendor logo.\n logo: '/intern_avatar.png',\n },\n },\n {\n test: (m) => m.startsWith('minimax'),\n vendor: {\n id: 'minimax',\n label: 'MiniMax',\n mono: { bg: 'hsl(18 50% 26%)', ring: 'hsl(18 65% 52%)', text: 'hsl(20 80% 82%)' },\n initial: 'M',\n logo: null, // → public/vendors/minimax.* when assets land\n },\n },\n {\n test: (m) => m.startsWith('claude'),\n vendor: {\n id: 'anthropic',\n label: 'Anthropic',\n mono: { bg: 'hsl(16 32% 26%)', ring: 'hsl(16 48% 54%)', text: 'hsl(18 60% 84%)' },\n initial: 'A',\n logo: null,\n },\n },\n {\n test: (m) => m.startsWith('gpt') || m.startsWith('codex') || m.startsWith('o1') || m.startsWith('o3') || m.startsWith('o4'),\n vendor: {\n id: 'openai',\n label: 'OpenAI',\n mono: { bg: 'hsl(165 26% 22%)', ring: 'hsl(165 40% 44%)', text: 'hsl(165 45% 80%)' },\n initial: 'O',\n logo: null,\n },\n },\n];\n\n/** Resolve a model id to its vendor identity. `null` / unmatched → UNKNOWN. */\nexport function vendorForModel(model: string | null | undefined): VendorIdentity {\n if (!model) return UNKNOWN_VENDOR;\n const m = model.toLowerCase();\n for (const rule of VENDOR_RULES) {\n if (rule.test(m)) return rule.vendor;\n }\n return UNKNOWN_VENDOR;\n}\n\nexport type Runtime = 'claude-code-cli' | 'codex-sdk' | 'claude-agent-sdk' | 'http-api';\n\nexport interface RuntimeIdentity {\n label: string;\n /** SVG path(s) drawn inside a 0..24 viewBox for the corner badge. */\n iconPath: string;\n /** Badge accent colour — kept clear of working/idle/offline status hues. */\n color: string;\n}\n\nconst RUNTIME_MAP: Record<Runtime, RuntimeIdentity> = {\n // terminal / CLI\n 'claude-code-cli': {\n label: 'Claude Code CLI',\n iconPath: 'M4 5h16v14H4z M7 9l3 3-3 3 M13 15h4',\n color: '#a78bfa',\n },\n // code-block / SDK\n 'codex-sdk': {\n label: 'Codex SDK',\n iconPath: 'M9 7l-5 5 5 5 M15 7l5 5-5 5',\n color: '#38bdf8',\n },\n // SDK, distinct hue from codex\n 'claude-agent-sdk': {\n label: 'Claude Agent SDK',\n iconPath: 'M4 7h16v10H4z M8 11h8 M8 14h5',\n color: '#34d399',\n },\n // cloud / API — non-resident process\n 'http-api': {\n label: 'HTTP API',\n iconPath: 'M7 18a4 4 0 010-8 5 5 0 019.6-1.3A3.5 3.5 0 0118 18z',\n color: '#fbbf24',\n },\n};\n\n/** Resolve a server runtime string to badge identity. Unknown → null. */\nexport function runtimeIdentity(runtime: string | null | undefined): RuntimeIdentity | null {\n if (!runtime) return null;\n return RUNTIME_MAP[runtime as Runtime] ?? null;\n}\n\n/** Compact one-line identity for hover / detail surfaces:\n * \"Anthropic · claude-opus-4 · Claude Code CLI\". Pieces with no data drop. */\nexport function identityLine(model: string | null | undefined, runtime: string | null | undefined): string {\n const v = vendorForModel(model);\n const r = runtimeIdentity(runtime);\n const parts: string[] = [];\n if (v.id !== 'unknown') parts.push(v.label);\n if (model) parts.push(model);\n if (r) parts.push(r.label);\n return parts.join(' · ');\n}\n","'use client';\n\nimport Link from 'next/link';\nimport { Session } from './types';\nimport { timeAgo } from './utils';\nimport { AliasAvatar } from './AliasAvatar';\n\ninterface AgentCardProps {\n session: Session;\n hasSse: boolean;\n sseCount: number;\n onChat?: (alias: string) => void;\n}\n\nconst STATUS_CONFIG: Record<string, { bg: string; text: string; dot: string; glow: string }> = {\n working: { bg: 'bg-green-900/30 border-green-800/30', text: 'text-green-300', dot: 'bg-green-500', glow: 'shadow-green-500/10' },\n idle: { bg: 'bg-cyan-900/30 border-cyan-800/30', text: 'text-cyan-300', dot: 'bg-cyan-400', glow: 'shadow-cyan-500/5' },\n blocked: { bg: 'bg-yellow-900/30 border-yellow-800/30', text: 'text-yellow-300', dot: 'bg-yellow-500', glow: '' },\n error: { bg: 'bg-red-900/30 border-red-800/30', text: 'text-red-300', dot: 'bg-red-500', glow: '' },\n};\n\nconst DEFAULT_STATUS = { bg: 'bg-gray-800/50 border-gray-700/30', text: 'text-gray-500', dot: 'bg-gray-500', glow: '' };\n\nexport function AgentCard({ session: s, hasSse, sseCount, onChat }: AgentCardProps) {\n const cfg = hasSse ? (STATUS_CONFIG[s.status] || DEFAULT_STATUS) : DEFAULT_STATUS;\n\n return (\n <Link\n href={`/node?alias=${encodeURIComponent(s.alias)}`}\n prefetch={false}\n className={`anet-agent-card group relative block rounded-xl border p-4 transition-all duration-300 cursor-pointer hover:-translate-y-0.5 ${\n hasSse\n ? `bg-[#111128] border-[#2a2a4a] hover:border-cyan-500/30 hover:shadow-lg ${cfg.glow}`\n : 'bg-[#0d0d1a] border-[#1a1a2a] opacity-40'\n }`}\n >\n {/* Header: avatar + name + status. Avatar carries the alias→hue map\n shared with Messages/Nodes/Tasks/Overview; the live status dot\n stays as a small pulse-capable indicator. */}\n <div className=\"flex items-center justify-between mb-3\">\n <div className=\"flex items-center gap-2 min-w-0\">\n <AliasAvatar alias={s.alias} size={22} />\n <span className=\"font-semibold text-white truncate text-sm\" title={s.alias}>{s.alias}</span>\n <span className={`inline-block w-1.5 h-1.5 rounded-full shrink-0 ${cfg.dot} ${hasSse && s.status === 'working' ? 'animate-pulse' : ''}`} />\n </div>\n <span className={`text-[11px] px-2 py-0.5 rounded-md border shrink-0 ${cfg.bg} ${cfg.text}`}>\n {hasSse ? s.status : 'offline'}\n </span>\n </div>\n\n {/* Agent type badge */}\n <div className=\"flex items-center gap-2 mb-3\">\n <span className=\"text-xs text-gray-600 bg-[#0a0a15] px-2 py-0.5 rounded border border-[#1a1a2a]\">\n {s.agent || 'unknown'}\n </span>\n {hasSse && (\n <span className=\"text-[10px] text-green-500\">SSE:{sseCount}</span>\n )}\n </div>\n\n {/* Task */}\n {s.task ? (\n <div className=\"text-xs text-gray-400 bg-[#0a0a15] rounded-lg px-3 py-2 border border-[#1a1a2a] line-clamp-2\" title={s.task}>\n {s.task}\n </div>\n ) : (\n <div className=\"text-xs text-gray-700 italic\">No active task</div>\n )}\n\n {/* Progress bar */}\n {s.progress > 0 && (\n <div className=\"mt-3\">\n <div className=\"flex justify-between text-[10px] mb-1\">\n <span className=\"text-gray-600\">Progress</span>\n <span className={cfg.text}>{s.progress}%</span>\n </div>\n <div className=\"w-full bg-gray-800 rounded-full h-1.5 overflow-hidden\">\n <div\n className={`h-1.5 rounded-full transition-all duration-700 ${s.status === 'working' ? 'bg-green-500' : 'bg-cyan-500'}`}\n style={{ width: `${Math.min(s.progress, 100)}%` }}\n />\n </div>\n </div>\n )}\n\n {/* Footer: time + chat + hover chevron affordance (round 44).\n The card is a <Link> so it's clickable everywhere, but with no\n visible cue users may not realise. Chevron appears on hover and\n slides right ~2px for a \"drill in\" hint. */}\n <div className=\"mt-3 flex justify-between items-center text-[10px] text-gray-600\">\n <span className=\"truncate\" title={s.server || ''}>{s.server || '--'}</span>\n <div className=\"flex items-center gap-2\">\n {onChat && hasSse && (\n <button\n onClick={e => { e.preventDefault(); e.stopPropagation(); onChat(s.alias); }}\n className=\"text-cyan-400 hover:text-cyan-300 px-1.5 py-0.5 rounded border border-cyan-500/20 hover:bg-cyan-500/10 transition-colors\"\n >\n Chat\n </button>\n )}\n <span>{timeAgo(s.updated_at)}</span>\n <svg\n aria-hidden\n className=\"w-3 h-3 text-gray-700 opacity-0 -translate-x-1 group-hover:opacity-100 group-hover:translate-x-0 transition-all duration-200\"\n fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"\n >\n <path d=\"M9 18l6-6-6-6\" />\n </svg>\n </div>\n </div>\n </Link>\n );\n}\n","'use client';\n\nimport { InboxMessage } from './types';\nimport { AliasAvatar } from './AliasAvatar';\nimport { timeAgo, previewContent } from './utils';\n\ninterface InboxPanelProps {\n messages: InboxMessage[];\n}\n\nexport function InboxPanel({ messages }: InboxPanelProps) {\n if (messages.length === 0) return null;\n\n return (\n <div className=\"mt-8\">\n <h2 className=\"text-lg font-semibold text-white mb-3 flex items-center gap-2\">\n <span className=\"text-gray-500\">Inbox</span>\n <span className=\"text-xs bg-blue-900/30 text-blue-400 px-2 py-0.5 rounded-full border border-blue-800/30\">\n {messages.length}\n </span>\n </h2>\n <div className=\"space-y-2 max-h-96 overflow-y-auto pr-1 scrollbar-thin\">\n {messages.map(m => (\n <div key={m.id} className=\"bg-[#111128] border border-[#2a2a4a] rounded-lg px-4 py-3 text-sm transition-colors hover:border-[#3a3a5a]\">\n <div className=\"flex items-center gap-2 text-xs mb-1.5\">\n {m.from_session && <AliasAvatar alias={m.from_session} size={16} />}\n <span className=\"text-gray-200 font-medium truncate\">{m.from_session}</span>\n <span className=\"ml-auto text-gray-600 shrink-0\" title={m.created_at}>{timeAgo(m.created_at)}</span>\n </div>\n <div className=\"text-gray-300 leading-relaxed line-clamp-3\" title={m.content || ''}>{previewContent(m.content)}</div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n","'use client';\n\n/**\n * Loading skeleton — mirrors the actual Overview layout structure so the\n * page doesn't appear to \"shift\" once data arrives. Uses the same\n * `anet-skeleton-pulse` rhythm as the brand pulse (1.6s opacity drift,\n * no scale, no blur, no glow) so the loading animation feels native to\n * the rest of the dashboard rather than a generic spinner.\n *\n * Bars are theme-aware: anet-skeleton-bar (existing CSS shim resolves this to\n * var(--bg-elevated) on light/mint), so light theme shows soft grey blocks\n * on white cards and dark theme shows lighter blocks on navy cards.\n */\nexport function LoadingSkeleton() {\n return (\n <div className=\"min-h-screen bg-[#0a0a1a] text-gray-100 p-4 sm:p-6 font-mono\">\n {/* KPI top strip — 4 cards matching StatsBar */}\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-3 mb-8 anet-skeleton-pulse\">\n {[1, 2, 3, 4].map(i => (\n <div key={i} className=\"rounded-xl border border-[#2a2a4a] bg-[#111128] px-4 py-3\">\n <Bar w=\"2.5rem\" h=\"1.75rem\" />\n <Bar w=\"3.5rem\" h=\"0.75rem\" className=\"mt-2\" />\n <Bar w=\"5rem\" h=\"0.625rem\" className=\"mt-1\" />\n </div>\n ))}\n </div>\n\n {/* Dispatch + UserBar row */}\n <div className=\"flex items-center gap-3 mb-3 anet-skeleton-pulse\">\n <Bar w=\"6rem\" h=\"2.5rem\" rounded=\"0.75rem\" />\n <div className=\"flex-1 rounded-lg border border-[#2a2a4a] bg-[#111128] px-4 py-2.5 flex items-center gap-3\">\n <div className=\"w-8 h-8 rounded-full anet-skeleton-bar\" />\n <div className=\"flex-1\">\n <Bar w=\"6rem\" h=\"0.875rem\" />\n <Bar w=\"10rem\" h=\"0.625rem\" className=\"mt-1\" />\n </div>\n </div>\n </div>\n\n {/* Config bar */}\n <div className=\"mb-6 rounded-lg border border-[#2a2a4a] bg-[#111128] px-4 py-3 anet-skeleton-pulse\">\n <Bar w=\"14rem\" h=\"0.875rem\" />\n </div>\n\n {/* Stat strip 3 cards */}\n <div className=\"grid grid-cols-3 gap-2 sm:gap-3 mb-3 anet-skeleton-pulse\">\n {[1, 2, 3].map(i => (\n <div key={i} className=\"rounded-xl border border-[#2a2a4a] bg-[#111128] px-3 py-3\">\n <Bar w=\"2rem\" h=\"1.25rem\" />\n <Bar w=\"2.5rem\" h=\"0.75rem\" className=\"mt-1\" />\n <Bar w=\"3.5rem\" h=\"0.625rem\" className=\"mt-px\" />\n </div>\n ))}\n </div>\n\n {/* Nav rail 3 cards */}\n <div className=\"grid grid-cols-3 gap-2 sm:gap-3 mb-6 anet-skeleton-pulse\">\n {[1, 2, 3].map(i => (\n <div key={i} className=\"rounded-xl border border-[#2a2a4a] bg-[#111128] px-3 py-2.5 flex items-center justify-center gap-2\">\n <div className=\"w-4 h-4 rounded anet-skeleton-bar\" />\n <Bar w=\"4rem\" h=\"0.75rem\" />\n </div>\n ))}\n </div>\n\n {/* Broadcast bar */}\n <div className=\"mb-6 flex gap-2 anet-skeleton-pulse\">\n <div className=\"flex-1 h-10 rounded-lg border border-[#2a2a4a] bg-[#111128]\" />\n <div className=\"w-28 h-10 rounded-lg anet-skeleton-bar\" />\n </div>\n\n {/* Agent card grid */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-3 sm:gap-4 anet-skeleton-pulse\">\n {[1, 2, 3, 4].map(i => (\n <div key={i} className=\"rounded-xl border border-[#2a2a4a] bg-[#111128] p-4\">\n <div className=\"flex items-center gap-2 mb-3\">\n <div className=\"w-2 h-2 rounded-full anet-skeleton-bar\" />\n <Bar w=\"6rem\" h=\"0.875rem\" />\n </div>\n <div className=\"space-y-2\">\n <Bar w=\"100%\" h=\"0.625rem\" />\n <Bar w=\"75%\" h=\"0.625rem\" />\n <Bar w=\"55%\" h=\"0.625rem\" />\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n\n/** Single shimmer bar — uses `anet-skeleton-bar` so theme-specific bar\n * color (dark navy on dark themes, mid-grey on light) overrides the\n * default. */\nfunction Bar({ w, h, rounded, className }: { w: string; h: string; rounded?: string; className?: string }) {\n return (\n <div\n className={`anet-skeleton-bar ${className || ''}`}\n style={{ width: w, height: h, borderRadius: rounded || '0.375rem' }}\n />\n );\n}\n\n// EmptyState export removed in 0.4.5 — replaced by EmptyState.tsx with\n// per-variant glyphs and a NodesEmptyState wrapper for the Overview\n// hint-aware behavior. See app/components/EmptyState.tsx.\n","'use client';\n\nimport { useEffect, useState } from 'react';\nimport { useNetworkId } from '../lib/network-context';\n\ninterface User {\n user_id: string;\n username: string;\n display_name: string;\n role: string;\n}\n\ninterface Network {\n network_id: string;\n network_name: string;\n description: string;\n}\n\ninterface AuthState {\n user: User | null;\n networks: Network[];\n currentNetwork: string;\n token: string;\n}\n\nexport function UserBar() {\n const { setNetworkId } = useNetworkId();\n const [auth, setAuth] = useState<AuthState>({ user: null, networks: [], currentNetwork: '', token: '' });\n const [showLogin, setShowLogin] = useState(false);\n const [username, setUsername] = useState('');\n const [password, setPassword] = useState('');\n const [loginError, setLoginError] = useState('');\n const [loginPending, setLoginPending] = useState(false);\n\n // Try to restore from sessionStorage\n useEffect(() => {\n const saved = sessionStorage.getItem('anet_v3_auth');\n if (saved) {\n try { setAuth(JSON.parse(saved)); } catch {}\n }\n }, []);\n\n const doAuth = async (action: 'login' | 'register') => {\n if (!username.trim() || !password.trim()) return;\n setLoginPending(true);\n setLoginError('');\n try {\n const res = await fetch('/api/hub/auth', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ action, username, password }),\n });\n const data = await res.json();\n if (!data.ok) { setLoginError(data.error || 'Failed'); setLoginPending(false); return; }\n\n // Fetch user details\n const meRes = await fetch(`/api/hub/auth?token=${data.token}&endpoint=/api/auth/me`);\n const meData = await meRes.json();\n\n const newAuth: AuthState = {\n user: data.user,\n networks: meData.networks || [],\n currentNetwork: meData.current_network?.network_id || meData.networks?.[0]?.network_id || '',\n token: data.token,\n };\n setAuth(newAuth);\n sessionStorage.setItem('anet_v3_auth', JSON.stringify(newAuth));\n setShowLogin(false);\n setUsername('');\n setPassword('');\n } catch { setLoginError('Connection failed'); }\n setLoginPending(false);\n };\n\n const logout = () => {\n setAuth({ user: null, networks: [], currentNetwork: '', token: '' });\n sessionStorage.removeItem('anet_v3_auth');\n };\n\n const [editing, setEditing] = useState(false);\n const [editName, setEditName] = useState('');\n const [editEmail, setEditEmail] = useState('');\n\n const updateProfile = async () => {\n try {\n const res = await fetch(`/api/hub/auth?token=${auth.token}&endpoint=/api/auth/me`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ action: 'update_profile', token: auth.token, display_name: editName, email: editEmail }),\n });\n // Use a direct PUT via a new proxy approach\n const putRes = await fetch('/api/hub/auth', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ action: 'update_profile', token: auth.token, display_name: editName, email: editEmail }),\n });\n const data = await putRes.json();\n if (data.ok && data.user) {\n const updated = { ...auth, user: data.user };\n setAuth(updated);\n sessionStorage.setItem('anet_v3_auth', JSON.stringify(updated));\n setEditing(false);\n }\n } catch {}\n };\n\n // Don't show anything when not logged in — login page handles that\n if (!auth.user) return null;\n\n const initials = (auth.user.display_name || auth.user.username).slice(0, 2).toUpperCase();\n\n return (\n <div className=\"flex items-center justify-between bg-[#111128] border border-[#2a2a4a] rounded-lg px-4 py-2.5 mb-4\">\n {/* User info */}\n <div className=\"flex items-center gap-3\">\n <div className=\"w-8 h-8 rounded-full bg-gradient-to-br from-cyan-500 to-blue-600 flex items-center justify-center text-xs font-bold text-white\">\n {initials}\n </div>\n <div>\n <div className=\"text-sm text-white font-medium\">{auth.user.display_name || auth.user.username}</div>\n <div className=\"text-[10px] text-gray-500\">{auth.user.role} · {auth.user.user_id}</div>\n </div>\n </div>\n\n {/* Network switcher */}\n <div className=\"flex items-center gap-3\">\n {auth.networks.length > 0 && (\n <select\n value={auth.currentNetwork}\n onChange={e => {\n const updated = { ...auth, currentNetwork: e.target.value };\n setAuth(updated);\n setNetworkId(e.target.value);\n sessionStorage.setItem('anet_v3_auth', JSON.stringify(updated));\n }}\n className=\"bg-[#0a0a15] border border-[#2a2a4a] rounded px-2 py-1 text-xs text-white focus:outline-none\"\n >\n {auth.networks.map(n => (\n <option key={n.network_id} value={n.network_id}>{n.network_name}</option>\n ))}\n </select>\n )}\n <button onClick={() => { setEditName(auth.user?.display_name || ''); setEditEmail(''); setEditing(!editing); }}\n className=\"text-xs text-gray-500 hover:text-gray-300 whitespace-nowrap\"\n aria-label=\"Edit profile\">\n <span className=\"hidden sm:inline\">Edit</span>\n <svg className=\"sm:hidden w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.862 4.487z\" />\n </svg>\n </button>\n <button onClick={logout}\n className=\"text-xs text-gray-500 hover:text-gray-300 whitespace-nowrap\"\n aria-label=\"Sign out\">\n <span className=\"hidden sm:inline\">Sign out</span>\n <svg className=\"sm:hidden w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15m3 0l3-3m0 0l-3-3m3 3H9\" />\n </svg>\n </button>\n </div>\n {editing && (\n <div className=\"flex flex-wrap items-center gap-2 mt-2 pt-2 border-t border-[#2a2a4a]\">\n <input type=\"text\" value={editName} onChange={e => setEditName(e.target.value)} placeholder=\"Display name\"\n className=\"bg-[#0a0a15] border border-[#2a2a4a] rounded px-2 py-1 text-xs text-white placeholder-gray-600 focus:outline-none w-32\" />\n <input type=\"email\" value={editEmail} onChange={e => setEditEmail(e.target.value)} placeholder=\"Email\"\n className=\"bg-[#0a0a15] border border-[#2a2a4a] rounded px-2 py-1 text-xs text-white placeholder-gray-600 focus:outline-none w-40\" />\n <button onClick={updateProfile} className=\"px-2 py-1 bg-cyan-600 hover:bg-cyan-500 text-white text-xs rounded\">Save</button>\n </div>\n )}\n </div>\n );\n}\n","'use client';\n\nimport { useState } from 'react';\nimport { TaskChatPanel } from './TaskChatPanel';\n\ninterface CommandCenterProps {\n /** Currently open chat tabs */\n tabs: string[];\n activeTab: string;\n onOpenTab: (alias: string) => void;\n onCloseTab: (alias: string) => void;\n onSetActive: (alias: string) => void;\n onClose: () => void;\n}\n\n/**\n * Multi-tab chat panel for commanding multiple agents simultaneously.\n * Wraps TaskChatPanel with a tab bar for switching between agents.\n */\nexport function CommandCenter({ tabs, activeTab, onOpenTab, onCloseTab, onSetActive, onClose }: CommandCenterProps) {\n if (tabs.length === 0) return null;\n\n return (\n <>\n {/* Backdrop */}\n <div className=\"fixed inset-0 bg-black/30 z-40 lg:hidden\" onClick={onClose} />\n\n {/* Panel */}\n <div className=\"fixed top-0 right-0 h-full w-full lg:w-[500px] bg-[#0a0a1a] border-l border-[#2a2a4a] z-50 flex flex-col shadow-2xl shadow-black/60 animate-slide-in\">\n {/* Tab bar */}\n <div className=\"flex items-center border-b border-[#2a2a4a] bg-[#0d0d1a] overflow-x-auto\">\n <div className=\"flex-1 flex min-w-0\">\n {tabs.map(alias => (\n <button\n key={alias}\n onClick={() => onSetActive(alias)}\n className={`flex items-center gap-1.5 px-3 py-2.5 text-xs border-b-2 transition-colors shrink-0 ${\n activeTab === alias\n ? 'border-cyan-400 text-cyan-300 bg-cyan-500/5'\n : 'border-transparent text-gray-500 hover:text-gray-300'\n }`}\n >\n <div className={`w-2 h-2 rounded-full ${activeTab === alias ? 'bg-cyan-400' : 'bg-gray-600'}`} />\n <span className=\"max-w-[80px] truncate\">{alias}</span>\n <button\n onClick={e => { e.stopPropagation(); onCloseTab(alias); }}\n className=\"ml-1 text-gray-600 hover:text-gray-300 p-0.5\"\n >\n ×\n </button>\n </button>\n ))}\n </div>\n <button onClick={onClose} className=\"text-gray-500 hover:text-white px-3 py-2.5 shrink-0 border-l border-[#2a2a4a]\">\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n {/* Active chat - render all but only show active (preserves state) */}\n <div className=\"flex-1 relative overflow-hidden\">\n {tabs.map(alias => (\n <div key={alias} className={`absolute inset-0 ${activeTab === alias ? 'block' : 'hidden'}`}>\n <InlineChat alias={alias} />\n </div>\n ))}\n </div>\n </div>\n\n <style jsx global>{`\n @keyframes slide-in {\n from { transform: translateX(100%); }\n to { transform: translateX(0); }\n }\n .animate-slide-in {\n animation: slide-in 0.2s ease-out;\n }\n `}</style>\n </>\n );\n}\n\n/** Inline chat without the panel chrome (used inside CommandCenter tabs) */\nfunction InlineChat({ alias }: { alias: string }) {\n // Reuse TaskChatPanel's logic but render without the outer frame\n return <TaskChatPanel alias={alias} onClose={() => {}} inline />;\n}\n\n/**\n * Hook to manage multi-tab command center state.\n */\nexport function useCommandCenter() {\n const [tabs, setTabs] = useState<string[]>([]);\n const [activeTab, setActiveTab] = useState('');\n\n const openTab = (alias: string) => {\n setTabs(prev => prev.includes(alias) ? prev : [...prev, alias]);\n setActiveTab(alias);\n };\n\n const closeTab = (alias: string) => {\n setTabs(prev => {\n const next = prev.filter(t => t !== alias);\n if (activeTab === alias) setActiveTab(next[next.length - 1] || '');\n return next;\n });\n };\n\n const closeAll = () => {\n setTabs([]);\n setActiveTab('');\n };\n\n return { tabs, activeTab, openTab, closeTab, closeAll, setActiveTab };\n}\n","'use client';\n\nimport { useState } from 'react';\nimport type { Session } from './types';\nimport { AliasAvatar } from './AliasAvatar';\n\ninterface DispatchPanelProps {\n sessions: Session[];\n onClose: () => void;\n}\n\ninterface SendResult {\n alias: string;\n ok: boolean;\n error?: string;\n}\n\nexport function DispatchPanel({ sessions, onClose }: DispatchPanelProps) {\n const [selected, setSelected] = useState<Set<string>>(new Set());\n const [prompt, setPrompt] = useState('');\n const [priority, setPriority] = useState('normal');\n const [sending, setSending] = useState(false);\n const [results, setResults] = useState<SendResult[]>([]);\n const [filter, setFilter] = useState('');\n\n const onlineNodes = sessions.filter(s => s.status !== 'offline');\n const filtered = onlineNodes.filter(s =>\n !filter || s.alias.toLowerCase().includes(filter.toLowerCase()) || (s.agent || '').toLowerCase().includes(filter.toLowerCase())\n );\n\n const toggleNode = (alias: string) => {\n setSelected(prev => {\n const next = new Set(prev);\n if (next.has(alias)) next.delete(alias); else next.add(alias);\n return next;\n });\n };\n\n const selectAll = () => {\n if (selected.size === filtered.length) {\n setSelected(new Set());\n } else {\n setSelected(new Set(filtered.map(s => s.alias)));\n }\n };\n\n const dispatch = async () => {\n if (!prompt.trim() || selected.size === 0 || sending) return;\n setSending(true);\n setResults([]);\n\n const promises = [...selected].map(async alias => {\n try {\n const res = await fetch('/api/hub/send', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ alias, task: prompt, priority }),\n });\n const data = await res.json();\n return { alias, ok: !!data.ok, error: data.error };\n } catch (e) {\n return { alias, ok: false, error: 'send failed' };\n }\n });\n\n const res = await Promise.all(promises);\n setResults(res);\n setSending(false);\n };\n\n const successCount = results.filter(r => r.ok).length;\n\n return (\n <>\n <div className=\"fixed inset-0 bg-black/50 z-40 anet-fade-in\" onClick={onClose} />\n <div className=\"fixed inset-4 lg:inset-x-[15%] lg:inset-y-[5%] bg-[#0a0a1a] border border-[#2a2a4a] rounded-2xl z-50 flex flex-col shadow-2xl shadow-black/70 overflow-hidden anet-fade-in\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-[#2a2a4a] bg-[#0d0d1a]\">\n <div>\n <h2 className=\"text-lg font-bold text-white\">Dispatch Task</h2>\n <p className=\"text-xs text-gray-500 mt-0.5\">Send a task to one or more agents</p>\n </div>\n <button onClick={onClose} className=\"text-gray-500 hover:text-white p-1.5 rounded-lg hover:bg-[#1a1a2a]\">\n <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n <div className=\"flex-1 flex flex-col lg:flex-row overflow-hidden\">\n {/* Left: Node selection */}\n <div className=\"lg:w-[280px] border-b lg:border-b-0 lg:border-r border-[#2a2a4a] flex flex-col\">\n <div className=\"px-4 py-3 border-b border-[#2a2a4a]\">\n <input\n type=\"text\" value={filter} onChange={e => setFilter(e.target.value)}\n placeholder=\"Filter agents...\"\n className=\"w-full bg-[#111128] border border-[#2a2a4a] rounded-lg px-3 py-2 text-xs text-white placeholder-gray-600 focus:border-cyan-500/40 focus:outline-none\"\n />\n <div className=\"flex items-center justify-between mt-2\">\n <button onClick={selectAll} className=\"text-[10px] text-cyan-400 hover:text-cyan-300\">\n {selected.size === filtered.length ? 'Deselect all' : `Select all (${filtered.length})`}\n </button>\n <span className=\"text-[10px] text-gray-600\">{selected.size} selected</span>\n </div>\n </div>\n <div className=\"flex-1 overflow-y-auto px-2 py-2 space-y-0.5 max-h-[200px] lg:max-h-none\">\n {filtered.map(s => (\n <button key={s.alias} onClick={() => toggleNode(s.alias)}\n className={`w-full flex items-center gap-2 px-3 py-2 rounded-lg text-xs text-left transition-colors ${\n selected.has(s.alias) ? 'bg-cyan-500/10 text-cyan-300 border border-cyan-500/20' : 'text-gray-400 hover:bg-[#1a1a2a]'\n }`}>\n <AliasAvatar alias={s.alias} size={16} />\n <div className={`w-1.5 h-1.5 rounded-full shrink-0 ${s.status === 'working' ? 'bg-green-400' : s.status === 'idle' ? 'bg-cyan-400' : 'bg-gray-500'}`} />\n <span className=\"truncate flex-1\">{s.alias}</span>\n <span className=\"text-[9px] text-gray-600\">{s.agent || '--'}</span>\n </button>\n ))}\n {filtered.length === 0 && <div className=\"text-center text-xs text-gray-600 py-4\">No online agents</div>}\n </div>\n </div>\n\n {/* Right: Prompt + Send */}\n <div className=\"flex-1 flex flex-col\">\n <div className=\"flex-1 px-6 py-4 flex flex-col\">\n <label className=\"text-xs text-gray-500 uppercase mb-2\">Task Prompt</label>\n <textarea\n value={prompt} onChange={e => setPrompt(e.target.value)}\n placeholder=\"Enter the task you want to dispatch...\"\n className=\"flex-1 min-h-[120px] bg-[#111128] border border-[#2a2a4a] rounded-xl px-4 py-3 text-sm text-white placeholder-gray-600 focus:border-cyan-500/40 focus:outline-none resize-none\"\n />\n\n <div className=\"flex items-center gap-3 mt-4\">\n <select value={priority} onChange={e => setPriority(e.target.value)}\n className=\"bg-[#111128] border border-[#2a2a4a] rounded-lg px-3 py-2 text-xs text-white focus:outline-none\">\n <option value=\"normal\">Normal priority</option>\n <option value=\"high\">High priority</option>\n <option value=\"low\">Low priority</option>\n </select>\n\n <div className=\"flex-1\" />\n\n <button onClick={dispatch} disabled={sending || !prompt.trim() || selected.size === 0}\n className=\"px-6 py-2.5 bg-gradient-to-r from-cyan-600 to-blue-600 hover:from-cyan-500 hover:to-blue-500 disabled:from-gray-800 disabled:to-gray-800 disabled:text-gray-600 text-white text-sm font-medium rounded-xl transition-all shadow-lg shadow-cyan-500/10 disabled:shadow-none active:scale-95\">\n {sending ? (\n <span className=\"flex items-center gap-2\">\n <span className=\"w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin\" />\n Sending...\n </span>\n ) : (\n `Dispatch to ${selected.size} agent${selected.size > 1 ? 's' : ''}`\n )}\n </button>\n </div>\n </div>\n\n {/* Results */}\n {results.length > 0 && (\n <div className=\"px-6 py-3 border-t border-[#2a2a4a] bg-[#0d0d1a]\">\n <div className=\"text-xs text-gray-500 mb-2\">\n {successCount}/{results.length} dispatched successfully\n </div>\n <div className=\"flex flex-wrap gap-1.5\">\n {results.map(r => (\n <span key={r.alias} className={`flex items-center gap-1.5 text-[10px] pl-1 pr-2 py-0.5 rounded-full border ${\n r.ok ? 'text-green-300 border-green-500/20 bg-green-500/5' : 'text-red-300 border-red-500/20 bg-red-500/5'\n }`}>\n <AliasAvatar alias={r.alias} size={14} />\n <span>{r.alias}</span>\n <span aria-hidden>{r.ok ? '✓' : r.error || '✗'}</span>\n </span>\n ))}\n </div>\n </div>\n )}\n </div>\n </div>\n </div>\n </>\n );\n}\n"],"names":["React","_interopDefaultLegacy","e","React__default","_defineProperties","target","props","i","length","descriptor","enumerable","configurable","writable","Object","defineProperty","key","_createClass","Constructor","protoProps","staticProps","prototype","isProd","process","env","isString","o","toString","call","StyleSheet","param","ref","_name","name","_optimizeForSpeed","optimizeForSpeed","invariant$1","_deletedRulePlaceholder","_serverSheet","undefined","_tags","_injected","_rulesCount","node","document","querySelector","_nonce","_proto","setOptimizeForSpeed","bool","flush","inject","isOptimizeForSpeed","_this","cssRules","insertRule","rule","index","cssText","push","deleteRule","getSheetForTag","tag","sheet","styleSheets","ownerNode","getSheet","insertionPoint","replaceRule","trim","error","console","warn","makeStyleTag","cssString","relativeToTag","createElement","setAttribute","type","appendChild","createTextNode","head","getElementsByTagName","insertBefore","get","condition","message","Error","hash","str","_$hash","charCodeAt","stringHash","sanitize","replace","cache","computeId","baseId","propsToString","String","computeSelector","id","css","selectoPlaceholderRegexp","idcss","mapRulesToStyle","options","map","args","nonce","dangerouslySetInnerHTML","__html","StyleSheetRegistry","_styleSheet","styleSheet","_sheet","_fromServer","_indices","_instancesCounts","add","Array","isArray","children","getIdAndRules","styleId","rules","indices","filter","remove","invariant","tagFromServer","parentNode","removeChild","forEach","update","nextProps","fromServer","keys","concat","join","Boolean","styles","dynamic","selectFromServer","elements","slice","querySelectorAll","reduce","acc","element","StyleSheetContext","createContext","displayName","createStyleRegistry","StyleRegistry","configuredRegistry","registry","rootRegistry","useContext","useState","Provider","value","useStyleRegistry","useInsertionEffect","useLayoutEffect","defaultRegistry","JSXStyle","info","tagInfo","exports","style","module","StatsBar","online","working","total","version","uptime","onlinePercent","Math","round","fleetEmpty","className","StatCard","label","sub","color","accent","border","accentKey","split"],"mappings":"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","ignoreList":[0,1]}
|