@sleep2agi/agent-network-dashboard 0.4.6-preview.13 → 0.4.6-preview.130
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 +41 -41
- 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 +4 -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/006b.89impj42.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/08kf-.bgs10ze.js +1 -0
- package/.next/static/chunks/0crl..r7yf03t.js +4 -0
- package/.next/static/chunks/0dpdwcai7vfxu.js +1 -0
- package/.next/static/chunks/0glmrdj9112tc.js +7 -0
- package/.next/static/chunks/0rxrez_cjn.eh.js +1 -0
- package/.next/static/chunks/0x8x.29hkju5a.js +1 -0
- package/.next/static/chunks/0yv1jpx~5v038.js +7 -0
- package/.next/static/chunks/1450fa_~v9qpc.css +2 -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/ChatPopover.tsx +38 -2
- package/app/components/CommandPalette.tsx +107 -0
- package/app/components/HelpOverlay.tsx +87 -0
- package/app/components/ServersDrawer.tsx +64 -27
- package/app/components/TopoGraph.tsx +2345 -163
- package/app/components/utils.ts +8 -7
- package/app/globals.css +19 -1
- 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-filter-pill-test.mjs +101 -0
- package/scripts/topo-active-links-chip-hover-test.mjs +103 -0
- package/scripts/topo-active-links-chip-test.mjs +73 -0
- package/scripts/topo-active-links-tooltip-test.mjs +79 -0
- package/scripts/topo-arrival-ping-test.mjs +87 -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-chat-target-breath-test.mjs +84 -0
- package/scripts/topo-chip-pin-mirror-test.mjs +113 -0
- package/scripts/topo-click-ripple-test.mjs +66 -0
- package/scripts/topo-cmdk-edge-clear-test.mjs +109 -0
- package/scripts/topo-cmdk-layout-view-test.mjs +108 -0
- package/scripts/topo-cmdk-pin-test.mjs +123 -0
- package/scripts/topo-cmdk-vendor-clear-test.mjs +133 -0
- package/scripts/topo-cmdk-vendor-pin-test.mjs +103 -0
- package/scripts/topo-cwd-tooltip-test.mjs +64 -0
- package/scripts/topo-dblclick-reset-test.mjs +74 -0
- package/scripts/topo-dispatch-pulse-test.mjs +83 -0
- package/scripts/topo-edge-badge-click-pin-test.mjs +94 -0
- package/scripts/topo-edge-badge-hover-test.mjs +85 -0
- package/scripts/topo-edge-count-badge-test.mjs +86 -0
- package/scripts/topo-edge-endpoint-highlight-test.mjs +111 -0
- package/scripts/topo-edge-focus-test.mjs +113 -0
- package/scripts/topo-edge-hover-test.mjs +93 -0
- package/scripts/topo-edge-pill-test.mjs +105 -0
- package/scripts/topo-edge-tooltip-test.mjs +70 -0
- package/scripts/topo-endpoint-ring-test.mjs +93 -0
- package/scripts/topo-esc-clears-pin-test.mjs +98 -0
- package/scripts/topo-filter-pill-aliases-test.mjs +121 -0
- package/scripts/topo-filter-pill-body-click-test.mjs +112 -0
- package/scripts/topo-filter-pill-count-test.mjs +110 -0
- package/scripts/topo-filter-pill-mobile-test.mjs +90 -0
- package/scripts/topo-fit-key-test.mjs +106 -0
- package/scripts/topo-freshness-chip-test.mjs +74 -0
- package/scripts/topo-group-box-pinned-state-test.mjs +95 -0
- package/scripts/topo-group-count-test.mjs +68 -0
- package/scripts/topo-group-hover-test.mjs +82 -0
- package/scripts/topo-group-label-hover-test.mjs +119 -0
- package/scripts/topo-group-label-tint-test.mjs +99 -0
- package/scripts/topo-group-label-title-test.mjs +83 -0
- package/scripts/topo-group-pin-test.mjs +119 -0
- package/scripts/topo-group-status-pips-test.mjs +103 -0
- package/scripts/topo-groupbox-live-test.mjs +100 -0
- package/scripts/topo-groupbox-test.mjs +4 -2
- package/scripts/topo-help-overlay-r109-test.mjs +67 -0
- package/scripts/topo-help-overlay-r118-test.mjs +69 -0
- package/scripts/topo-help-overlay-r123-test.mjs +69 -0
- package/scripts/topo-help-overlay-r59-test.mjs +67 -0
- package/scripts/topo-help-overlay-r65-test.mjs +64 -0
- package/scripts/topo-help-overlay-r70-test.mjs +63 -0
- package/scripts/topo-help-overlay-r78-test.mjs +59 -0
- package/scripts/topo-help-overlay-r81-test.mjs +58 -0
- package/scripts/topo-help-overlay-r87-test.mjs +64 -0
- package/scripts/topo-help-overlay-r91-test.mjs +65 -0
- package/scripts/topo-hub-busyness-test.mjs +100 -0
- package/scripts/topo-hub-click-fit-test.mjs +137 -0
- package/scripts/topo-hub-hover-ring-test.mjs +82 -0
- package/scripts/topo-hub-title-test.mjs +93 -0
- package/scripts/topo-ingroup-edge-test.mjs +103 -0
- package/scripts/topo-label-lift-test.mjs +119 -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-legend-count-test.mjs +88 -0
- package/scripts/topo-legend-hover-test.mjs +113 -0
- package/scripts/topo-legend-panel-header-test.mjs +83 -0
- package/scripts/topo-legend-pin-test.mjs +128 -0
- package/scripts/topo-legend-row-tint-test.mjs +95 -0
- package/scripts/topo-minimap-test.mjs +68 -0
- package/scripts/topo-mobile-chips-test.mjs +103 -0
- package/scripts/topo-node-hover-lift-test.mjs +85 -0
- package/scripts/topo-node-title-test.mjs +101 -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-panel-elevation-test.mjs +76 -0
- package/scripts/topo-particle-stagger-test.mjs +82 -0
- package/scripts/topo-pin-persistence-test.mjs +105 -0
- package/scripts/topo-popover-meta-test.mjs +78 -0
- package/scripts/topo-pressure-bar-test.mjs +69 -0
- package/scripts/topo-pressure-hover-test.mjs +123 -0
- package/scripts/topo-pressure-pin-test.mjs +119 -0
- package/scripts/topo-pressure-seg-tooltip-test.mjs +98 -0
- package/scripts/topo-pulse-rate-test.mjs +71 -0
- package/scripts/topo-recent-panel-count-test.mjs +72 -0
- package/scripts/topo-recent-row-hover-test.mjs +122 -0
- package/scripts/topo-recent-row-pin-test.mjs +126 -0
- package/scripts/topo-recent-row-tint-test.mjs +91 -0
- package/scripts/topo-recent-row-ts-test.mjs +92 -0
- package/scripts/topo-recent-signal-empty-hint-test.mjs +73 -0
- package/scripts/topo-recent-signal-empty-test.mjs +63 -0
- package/scripts/topo-reduced-motion-test.mjs +77 -0
- package/scripts/topo-status-chip-hover-test.mjs +101 -0
- package/scripts/topo-status-chip-tooltip-test.mjs +95 -0
- package/scripts/topo-tier-ring-occupancy-test.mjs +87 -0
- package/scripts/topo-tier-ring-test.mjs +69 -0
- package/scripts/topo-tier-ring-tint-test.mjs +110 -0
- package/scripts/topo-tier-stagger-test.mjs +89 -0
- package/scripts/topo-tz-ghost-test.mjs +69 -0
- package/scripts/topo-vendor-chip-hover-test.mjs +111 -0
- package/scripts/topo-vendor-letter-tooltip-test.mjs +92 -0
- package/scripts/topo-vendor-pill-test.mjs +125 -0
- package/scripts/topo-vendor-pin-test.mjs +125 -0
- package/scripts/topo-wheel-zoom-test.mjs +79 -0
- package/scripts/topo-working-halo-breath-test.mjs +86 -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/03u_oa2o2jrr~.js +0 -1
- package/.next/static/chunks/0_qfg5s5uzs7..js +0 -7
- package/.next/static/chunks/0dttftqqehpdj.js +0 -1
- package/.next/static/chunks/0elalb9n_.~di.js +0 -1
- package/.next/static/chunks/0fqy_0wj_1xa7.js +0 -7
- package/.next/static/chunks/0j_q__o8p6g83.js +0 -1
- package/.next/static/chunks/0jl6_w50zh4l5.js +0 -1
- package/.next/static/chunks/0q_z8ad2uojv5.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/17h~0~zsxjx6x.css +0 -2
- /package/.next/static/{nhazRrlYzcsAAYMwx8NFz → Ewya-AK7nUFpoTc-KK3lb}/_buildManifest.js +0 -0
- /package/.next/static/{nhazRrlYzcsAAYMwx8NFz → Ewya-AK7nUFpoTc-KK3lb}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{nhazRrlYzcsAAYMwx8NFz → Ewya-AK7nUFpoTc-KK3lb}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/* Round 60 verification: each pressure-bar segment toggles a sticky
|
|
2
|
+
* status filter. Click "working" → all non-working nodes dim, working
|
|
3
|
+
* ones stay. Click again → release. Pin and the R55 legend hover feed
|
|
4
|
+
* the same node-opacity branch via `activeStatus = hoveredStatus ??
|
|
5
|
+
* pinnedStatus`, so hover transiently overrides without nuking the pin.
|
|
6
|
+
*
|
|
7
|
+
* Sessions:
|
|
8
|
+
* wkr — working
|
|
9
|
+
* idl1 — idle
|
|
10
|
+
* idl2 — idle
|
|
11
|
+
* off — offline
|
|
12
|
+
*/
|
|
13
|
+
import { chromium } from 'playwright';
|
|
14
|
+
import { readFileSync } from 'node:fs';
|
|
15
|
+
|
|
16
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
17
|
+
const browser = await chromium.launch({ headless: true });
|
|
18
|
+
|
|
19
|
+
const ctx = await browser.newContext({ viewport: { width: 1400, height: 1500 } });
|
|
20
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
21
|
+
await ctx.addInitScript(() => {
|
|
22
|
+
try {
|
|
23
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
24
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
25
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
26
|
+
} catch {}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
30
|
+
const stale = new Date(Date.now() - 30 * 60 * 1000).toISOString();
|
|
31
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
32
|
+
const r = await route.fetch();
|
|
33
|
+
const b = await r.json();
|
|
34
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
35
|
+
const sessions = [
|
|
36
|
+
{ alias: 'wkr', status: 'working', network_id: nid, project_dir: null, created_at: fresh, updated_at: fresh, last_seen_at: fresh },
|
|
37
|
+
{ alias: 'idl1', status: 'idle', network_id: nid, project_dir: null, created_at: fresh, updated_at: fresh, last_seen_at: fresh },
|
|
38
|
+
{ alias: 'idl2', status: 'idle', network_id: nid, project_dir: null, created_at: fresh, updated_at: fresh, last_seen_at: fresh },
|
|
39
|
+
{ alias: 'off', status: 'offline', network_id: nid, project_dir: null, created_at: stale, updated_at: stale, last_seen_at: stale },
|
|
40
|
+
];
|
|
41
|
+
await route.fulfill({ response: r, json: { ...b, sessions } });
|
|
42
|
+
});
|
|
43
|
+
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [] } }));
|
|
44
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
45
|
+
const page = await ctx.newPage();
|
|
46
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
47
|
+
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 4, { timeout: 30000 });
|
|
48
|
+
await page.waitForTimeout(500);
|
|
49
|
+
|
|
50
|
+
const opacities = () => page.evaluate(() => {
|
|
51
|
+
const o = {};
|
|
52
|
+
for (const a of ['wkr', 'idl1', 'idl2', 'off']) {
|
|
53
|
+
const g = document.querySelector(`g[data-node="${a}"]`);
|
|
54
|
+
o[a] = g ? +(g.style.opacity || '1') : null;
|
|
55
|
+
}
|
|
56
|
+
return o;
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const before = await opacities();
|
|
60
|
+
|
|
61
|
+
const bright = (v) => v != null && v >= 0.55;
|
|
62
|
+
const dim = (v) => v != null && v < 0.4;
|
|
63
|
+
|
|
64
|
+
// Click the WORKING segment.
|
|
65
|
+
const workingSeg = page.locator('[data-pressure-seg="working"]').first();
|
|
66
|
+
const workingExists = await workingSeg.count() > 0;
|
|
67
|
+
if (!workingExists) { console.log('❌ pressure segment[working] not found'); process.exit(1); }
|
|
68
|
+
await workingSeg.click({ force: true });
|
|
69
|
+
await page.waitForTimeout(250);
|
|
70
|
+
const afterPin = await opacities();
|
|
71
|
+
|
|
72
|
+
// Pin should persist past mouse moving away.
|
|
73
|
+
await page.mouse.move(10, 10);
|
|
74
|
+
await page.waitForTimeout(250);
|
|
75
|
+
const afterMouseMove = await opacities();
|
|
76
|
+
|
|
77
|
+
// Click again to release. R79 added hover-affordances on the working
|
|
78
|
+
// + online chips, so the click locator's mouse path can light a
|
|
79
|
+
// transient hoveredStatus en route to the pressure segment. Mouse-move
|
|
80
|
+
// to a neutral spot after the release click so we observe pin-only
|
|
81
|
+
// state (same gotcha R61's test documented inline).
|
|
82
|
+
await workingSeg.click({ force: true });
|
|
83
|
+
await page.mouse.move(10, 10);
|
|
84
|
+
await page.waitForTimeout(250);
|
|
85
|
+
const afterRelease = await opacities();
|
|
86
|
+
|
|
87
|
+
// Repeat for offline segment.
|
|
88
|
+
const offlineSeg = page.locator('[data-pressure-seg="offline"]').first();
|
|
89
|
+
await offlineSeg.click({ force: true });
|
|
90
|
+
await page.mouse.move(10, 10);
|
|
91
|
+
await page.waitForTimeout(250);
|
|
92
|
+
const afterOfflinePin = await opacities();
|
|
93
|
+
await offlineSeg.click({ force: true });
|
|
94
|
+
await page.mouse.move(10, 10);
|
|
95
|
+
await page.waitForTimeout(250);
|
|
96
|
+
const afterOfflineRelease = await opacities();
|
|
97
|
+
|
|
98
|
+
await browser.close();
|
|
99
|
+
|
|
100
|
+
const results = {
|
|
101
|
+
before_baseline: bright(before.wkr) && bright(before.idl1),
|
|
102
|
+
working_pinKeepsWorking: bright(afterPin.wkr),
|
|
103
|
+
working_pinDimsIdle: dim(afterPin.idl1) && dim(afterPin.idl2),
|
|
104
|
+
working_pinDimsOffline: dim(afterPin.off),
|
|
105
|
+
working_pinSurvivesMouse: bright(afterMouseMove.wkr) && dim(afterMouseMove.idl1),
|
|
106
|
+
working_releaseRestoresAll: bright(afterRelease.wkr) && bright(afterRelease.idl1),
|
|
107
|
+
offline_pinKeepsOffline: bright(afterOfflinePin.off), // base offline 0.6 reads as bright (>=0.55)
|
|
108
|
+
offline_pinDimsOnline: dim(afterOfflinePin.wkr) && dim(afterOfflinePin.idl1),
|
|
109
|
+
offline_releaseRestoresAll: bright(afterOfflineRelease.wkr),
|
|
110
|
+
};
|
|
111
|
+
const ok = Object.values(results).every(Boolean);
|
|
112
|
+
console.log(`${ok ? '✅' : '❌'} pressure pin:`, JSON.stringify(results),
|
|
113
|
+
`\n before=`, before,
|
|
114
|
+
`\n afterPin=`, afterPin,
|
|
115
|
+
`\n afterMouseMove=`, afterMouseMove,
|
|
116
|
+
`\n afterRelease=`, afterRelease,
|
|
117
|
+
`\n afterOfflinePin=`, afterOfflinePin,
|
|
118
|
+
`\n afterOfflineRelease=`, afterOfflineRelease);
|
|
119
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/* Round 102 verification: pressure-bar segment tooltips list the
|
|
2
|
+
* aliases that fall into that status bucket. Closes the last "how
|
|
3
|
+
* many but not which" gap in the chip-row surfaces. Composes with
|
|
4
|
+
* the existing R83 hover preview (canvas dims still answer it
|
|
5
|
+
* visually too) — this adds a screen-reader-friendly textual
|
|
6
|
+
* channel for the same info.
|
|
7
|
+
*
|
|
8
|
+
* Fleet: 2 working + 2 idle + 1 offline. Verify each segment's
|
|
9
|
+
* title contains the matching aliases + action hint; data-pressure-
|
|
10
|
+
* seg-aliases attr carries the full CSV.
|
|
11
|
+
*/
|
|
12
|
+
import { chromium } from 'playwright';
|
|
13
|
+
import { readFileSync } from 'node:fs';
|
|
14
|
+
|
|
15
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
16
|
+
const browser = await chromium.launch({ headless: true });
|
|
17
|
+
|
|
18
|
+
const ctx = await browser.newContext({ viewport: { width: 1400, height: 1500 } });
|
|
19
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
20
|
+
await ctx.addInitScript(() => {
|
|
21
|
+
try {
|
|
22
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
23
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
24
|
+
sessionStorage.removeItem('anet-topo-pinned-status');
|
|
25
|
+
} catch {}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
29
|
+
const stale10 = new Date(Date.now() - 10 * 60 * 1000).toISOString();
|
|
30
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
31
|
+
const r = await route.fetch();
|
|
32
|
+
const b = await r.json();
|
|
33
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
34
|
+
const mk = (alias, status, ts) => ({
|
|
35
|
+
alias, status, model: 'claude-opus-4', runtime: 'cli-claude-code',
|
|
36
|
+
network_id: nid, project_dir: null,
|
|
37
|
+
created_at: ts, updated_at: ts, last_seen_at: ts,
|
|
38
|
+
});
|
|
39
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
40
|
+
mk('wkr1', 'working', fresh),
|
|
41
|
+
mk('wkr2', 'working', fresh),
|
|
42
|
+
mk('idl1', 'idle', fresh),
|
|
43
|
+
mk('idl2', 'idle', fresh),
|
|
44
|
+
mk('off1', 'offline', stale10),
|
|
45
|
+
] } });
|
|
46
|
+
});
|
|
47
|
+
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [] } }));
|
|
48
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
49
|
+
const page = await ctx.newPage();
|
|
50
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
51
|
+
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 5, { timeout: 30000 });
|
|
52
|
+
await page.waitForTimeout(400);
|
|
53
|
+
|
|
54
|
+
const read = (key) => page.evaluate((k) => {
|
|
55
|
+
const el = document.querySelector(`[data-pressure-seg="${k}"]`);
|
|
56
|
+
if (!el) return null;
|
|
57
|
+
return {
|
|
58
|
+
title: el.getAttribute('title') || '',
|
|
59
|
+
aliases: el.getAttribute('data-pressure-seg-aliases') || '',
|
|
60
|
+
};
|
|
61
|
+
}, key);
|
|
62
|
+
|
|
63
|
+
const working = await read('working');
|
|
64
|
+
const idle = await read('idle');
|
|
65
|
+
const offline = await read('offline');
|
|
66
|
+
|
|
67
|
+
// Pin working — action hint should flip in the title.
|
|
68
|
+
await page.locator('[data-pressure-seg="working"]').click();
|
|
69
|
+
await page.waitForTimeout(250);
|
|
70
|
+
const workingPinned = await read('working');
|
|
71
|
+
|
|
72
|
+
await browser.close();
|
|
73
|
+
|
|
74
|
+
const sameSet = (csv, expected) => {
|
|
75
|
+
const got = new Set(csv.split(',').filter(Boolean));
|
|
76
|
+
const exp = new Set(expected);
|
|
77
|
+
return got.size === exp.size && [...exp].every(x => got.has(x));
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const results = {
|
|
81
|
+
working_aliasesMatch: sameSet(working?.aliases || '', ['wkr1', 'wkr2']),
|
|
82
|
+
working_titleListsThem: /wkr1.*wkr2|wkr2.*wkr1/.test(working?.title || ''),
|
|
83
|
+
working_titleClickHint: /click to highlight/.test(working?.title || ''),
|
|
84
|
+
working_titleStatusN: /^2 working/m.test(working?.title || ''),
|
|
85
|
+
idle_aliasesMatch: sameSet(idle?.aliases || '', ['idl1', 'idl2']),
|
|
86
|
+
idle_titleListsThem: /idl1.*idl2|idl2.*idl1/.test(idle?.title || ''),
|
|
87
|
+
offline_aliasesMatch: sameSet(offline?.aliases || '', ['off1']),
|
|
88
|
+
offline_titleListsThem: /off1/.test(offline?.title || ''),
|
|
89
|
+
workingPin_aliasesStable: sameSet(workingPinned?.aliases || '', ['wkr1', 'wkr2']),
|
|
90
|
+
workingPin_hintFlipped: /click to release filter/.test(workingPinned?.title || ''),
|
|
91
|
+
};
|
|
92
|
+
const ok = Object.values(results).every(Boolean);
|
|
93
|
+
console.log(`${ok ? '✅' : '❌'} pressure-seg tooltip:`, JSON.stringify(results),
|
|
94
|
+
`\n working:`, working,
|
|
95
|
+
`\n idle:`, idle,
|
|
96
|
+
`\n offline:`, offline,
|
|
97
|
+
`\n workingPinned:`, workingPinned);
|
|
98
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/* Round 24 verification: working-node pulse duration tiers by sse:N.
|
|
2
|
+
* sse 0-1 → 1.2s (calm)
|
|
3
|
+
* sse 2-3 → 0.9s (active)
|
|
4
|
+
* sse ≥ 4 → 0.7s (busy)
|
|
5
|
+
* Inject sse counts via mocked /api/hub/health → sse_sessions map. */
|
|
6
|
+
import { chromium } from 'playwright';
|
|
7
|
+
import { readFileSync } from 'node:fs';
|
|
8
|
+
|
|
9
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
10
|
+
const browser = await chromium.launch({ headless: true });
|
|
11
|
+
|
|
12
|
+
const ctx = await browser.newContext({ viewport: { width: 1280, height: 900 } });
|
|
13
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
14
|
+
await ctx.addInitScript(() => {
|
|
15
|
+
try {
|
|
16
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
17
|
+
localStorage.setItem('anet-topo-layout', 'grid');
|
|
18
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
19
|
+
} catch {}
|
|
20
|
+
});
|
|
21
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
22
|
+
// Three working sessions with different sse counts. Use a known network_id
|
|
23
|
+
// so the `${nid}:${alias}` sse-map key works (the page's grouped lookup).
|
|
24
|
+
const NID = 'net_test';
|
|
25
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
26
|
+
await route.fulfill({ json: {
|
|
27
|
+
ok: true,
|
|
28
|
+
sessions: ['calm', 'active', 'busy'].map(alias => ({
|
|
29
|
+
alias, status: 'working', network_id: NID, project_dir: null,
|
|
30
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
31
|
+
})),
|
|
32
|
+
} });
|
|
33
|
+
});
|
|
34
|
+
await ctx.route('**/api/hub/health*', async (route) => {
|
|
35
|
+
await route.fulfill({ json: {
|
|
36
|
+
ok: true,
|
|
37
|
+
version: '0.8.0-test',
|
|
38
|
+
sse_sessions: {
|
|
39
|
+
[`${NID}:calm`]: 1,
|
|
40
|
+
[`${NID}:active`]: 2,
|
|
41
|
+
[`${NID}:busy`]: 4,
|
|
42
|
+
},
|
|
43
|
+
} });
|
|
44
|
+
});
|
|
45
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
46
|
+
const page = await ctx.newPage();
|
|
47
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
48
|
+
await page.waitForFunction(() => {
|
|
49
|
+
const svg = document.querySelector('svg[viewBox="0 0 1000 680"]');
|
|
50
|
+
return !!svg && svg.querySelectorAll('g[data-node]').length === 3;
|
|
51
|
+
}, { timeout: 30000 }).catch(() => {});
|
|
52
|
+
await page.waitForTimeout(600);
|
|
53
|
+
|
|
54
|
+
const durOf = alias => page.$eval(
|
|
55
|
+
`g[data-node="${alias}"] circle[data-pulse-dur]`,
|
|
56
|
+
el => el.getAttribute('data-pulse-dur'),
|
|
57
|
+
).catch(() => null);
|
|
58
|
+
|
|
59
|
+
const calm = await durOf('calm');
|
|
60
|
+
const active = await durOf('active');
|
|
61
|
+
const busy = await durOf('busy');
|
|
62
|
+
|
|
63
|
+
await browser.close();
|
|
64
|
+
const results = {
|
|
65
|
+
calmIs1_2s: calm === '1.2s',
|
|
66
|
+
activeIs0_9s: active === '0.9s',
|
|
67
|
+
busyIs0_7s: busy === '0.7s',
|
|
68
|
+
};
|
|
69
|
+
const ok = Object.values(results).every(Boolean);
|
|
70
|
+
console.log(`${ok ? '✅' : '❌'} pulse rate:`, JSON.stringify(results), `calm=${calm} active=${active} busy=${busy}`);
|
|
71
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/* Round 96 verification: the recent-signal panel header count now
|
|
2
|
+
* reads "X flows" off flowLinks.length (matching the deduped rows
|
|
3
|
+
* below), not "X msgs" off the raw messages.length. Pre-R96 a
|
|
4
|
+
* fleet with 10 messages aggregating to 3 unique pairs read
|
|
5
|
+
* "10 msgs" above only 3 rendered rows — read as broken.
|
|
6
|
+
*
|
|
7
|
+
* Mock 5 messages between 2 distinct pairs: alpha↔beta gets 4
|
|
8
|
+
* msgs (4 separate exchanges, dedupes to 1 flow), gamma→delta
|
|
9
|
+
* gets 1 msg (1 flow). Total = 5 msgs, 2 flows. Header should
|
|
10
|
+
* show "2 flows", panel renders 2 rows.
|
|
11
|
+
*/
|
|
12
|
+
import { chromium } from 'playwright';
|
|
13
|
+
import { readFileSync } from 'node:fs';
|
|
14
|
+
|
|
15
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
16
|
+
const browser = await chromium.launch({ headless: true });
|
|
17
|
+
|
|
18
|
+
const ctx = await browser.newContext({ viewport: { width: 1400, height: 1500 } });
|
|
19
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
20
|
+
await ctx.addInitScript(() => {
|
|
21
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
25
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
26
|
+
const r = await route.fetch();
|
|
27
|
+
const b = await r.json();
|
|
28
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
29
|
+
const mk = (alias) => ({
|
|
30
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'cli-claude-code',
|
|
31
|
+
network_id: nid, project_dir: null,
|
|
32
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
33
|
+
});
|
|
34
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('alpha'), mk('beta'), mk('gamma'), mk('delta')] } });
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const now = Date.now();
|
|
38
|
+
const mkMsg = (id, from_alias, to_alias, content, ageMs) => ({
|
|
39
|
+
id, from_alias, to_alias, content, network_id: 'default',
|
|
40
|
+
created_at: new Date(now - ageMs).toISOString(),
|
|
41
|
+
});
|
|
42
|
+
// 5 messages → 2 flow pairs (alpha→beta × 4, gamma→delta × 1).
|
|
43
|
+
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [
|
|
44
|
+
mkMsg('m1', 'alpha', 'beta', 'ping-1', 60 * 1000),
|
|
45
|
+
mkMsg('m2', 'alpha', 'beta', 'ping-2', 50 * 1000),
|
|
46
|
+
mkMsg('m3', 'alpha', 'beta', 'ping-3', 40 * 1000),
|
|
47
|
+
mkMsg('m4', 'alpha', 'beta', 'ping-4', 30 * 1000),
|
|
48
|
+
mkMsg('m5', 'gamma', 'delta', 'hello', 20 * 1000),
|
|
49
|
+
] } }));
|
|
50
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
51
|
+
const page = await ctx.newPage();
|
|
52
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
53
|
+
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 4, { timeout: 30000 });
|
|
54
|
+
await page.waitForSelector('[data-recent-panel-count]', { timeout: 10000 });
|
|
55
|
+
await page.waitForTimeout(400);
|
|
56
|
+
|
|
57
|
+
const headerCount = await page.locator('[data-recent-panel-count]').textContent();
|
|
58
|
+
const renderedRows = await page.locator('[data-recent-row]').count();
|
|
59
|
+
|
|
60
|
+
await browser.close();
|
|
61
|
+
|
|
62
|
+
const results = {
|
|
63
|
+
header_saysFlowsNotMsgs: /\bflows\b/.test(headerCount || ''),
|
|
64
|
+
header_count2: /^2 flows/.test(headerCount || ''),
|
|
65
|
+
rows_match_header: renderedRows === 2,
|
|
66
|
+
no_msgs_word: !/\bmsgs?\b/.test(headerCount || ''),
|
|
67
|
+
};
|
|
68
|
+
const ok = Object.values(results).every(Boolean);
|
|
69
|
+
console.log(`${ok ? '✅' : '❌'} recent-panel count:`, JSON.stringify(results),
|
|
70
|
+
`\n header=`, JSON.stringify(headerCount),
|
|
71
|
+
`\n rows=`, renderedRows);
|
|
72
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/* Round 56 verification: hovering a recent-signal panel row sets
|
|
2
|
+
* hoveredEdgeKey to that link, which fires the R50 edge-focus +
|
|
3
|
+
* R49 endpoint-highlight ladders against the canvas.
|
|
4
|
+
*
|
|
5
|
+
* Sessions: alpha, beta, gamma, delta, epsilon, zeta (all idle).
|
|
6
|
+
* Messages create three deduped flow links in this order:
|
|
7
|
+
* alpha → beta
|
|
8
|
+
* gamma → delta
|
|
9
|
+
* epsilon → zeta
|
|
10
|
+
* Hover the FIRST recent-signal row (alpha→beta):
|
|
11
|
+
* - alpha→beta visible edge: opacity boosts ≥1.5× baseline (R50)
|
|
12
|
+
* - other edges (γ→δ, ε→ζ): opacity dims < 0.6× baseline
|
|
13
|
+
* - alpha + beta nodes: stay bright (≥0.55) — endpoint highlight (R49)
|
|
14
|
+
* - gamma/delta/epsilon/zeta nodes: dim (<0.4)
|
|
15
|
+
* Release → all restore.
|
|
16
|
+
*/
|
|
17
|
+
import { chromium } from 'playwright';
|
|
18
|
+
import { readFileSync } from 'node:fs';
|
|
19
|
+
|
|
20
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
21
|
+
const browser = await chromium.launch({ headless: true });
|
|
22
|
+
|
|
23
|
+
const ctx = await browser.newContext({ viewport: { width: 1400, height: 1500 } });
|
|
24
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
25
|
+
await ctx.addInitScript(() => {
|
|
26
|
+
try {
|
|
27
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
28
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
29
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
30
|
+
} catch {}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
34
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
35
|
+
const r = await route.fetch();
|
|
36
|
+
const b = await r.json();
|
|
37
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
38
|
+
const sessions = ['alpha', 'beta', 'gamma', 'delta', 'epsilon', 'zeta'].map(a => ({
|
|
39
|
+
alias: a, status: 'idle', network_id: nid, project_dir: null,
|
|
40
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
41
|
+
}));
|
|
42
|
+
await route.fulfill({ response: r, json: { ...b, sessions } });
|
|
43
|
+
});
|
|
44
|
+
const now = new Date().toISOString();
|
|
45
|
+
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [
|
|
46
|
+
{ from_alias: 'alpha', to_alias: 'beta', content: 'm', created_at: now },
|
|
47
|
+
{ from_alias: 'gamma', to_alias: 'delta', content: 'm', created_at: now },
|
|
48
|
+
{ from_alias: 'epsilon', to_alias: 'zeta', content: 'm', created_at: now },
|
|
49
|
+
] } }));
|
|
50
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
51
|
+
const page = await ctx.newPage();
|
|
52
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
53
|
+
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 6, { timeout: 30000 });
|
|
54
|
+
await page.waitForTimeout(600);
|
|
55
|
+
|
|
56
|
+
const readState = () => page.evaluate(() => {
|
|
57
|
+
const svg = document.querySelector('svg[viewBox="0 0 1000 680"]');
|
|
58
|
+
const edges = {};
|
|
59
|
+
for (const g of svg.querySelectorAll(':scope > g > g')) {
|
|
60
|
+
const t = g.querySelector('path[data-edge-hitbox] title');
|
|
61
|
+
if (!t) continue;
|
|
62
|
+
const route = (t.textContent || '').split('\n')[0];
|
|
63
|
+
const base = [...g.querySelectorAll(':scope > path')].find(
|
|
64
|
+
p => !p.hasAttribute('data-edge-hitbox') && p.hasAttribute('marker-end')
|
|
65
|
+
);
|
|
66
|
+
if (base) edges[route] = +base.getAttribute('opacity');
|
|
67
|
+
}
|
|
68
|
+
const nodes = {};
|
|
69
|
+
for (const a of ['alpha', 'beta', 'gamma', 'delta', 'epsilon', 'zeta']) {
|
|
70
|
+
const n = document.querySelector(`g[data-node="${a}"]`);
|
|
71
|
+
nodes[a] = n ? +(n.style.opacity || '1') : null;
|
|
72
|
+
}
|
|
73
|
+
return { edges, nodes };
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const before = await readState();
|
|
77
|
+
|
|
78
|
+
// Hover the first recent-signal row — its key is "alpha->beta".
|
|
79
|
+
const rowRect = await page.evaluate(() => {
|
|
80
|
+
const g = document.querySelector('g[data-recent-row="alpha->beta"]');
|
|
81
|
+
if (!g) return null;
|
|
82
|
+
const r = g.getBoundingClientRect();
|
|
83
|
+
return { x: r.x + r.width / 2, y: r.y + r.height / 2 };
|
|
84
|
+
});
|
|
85
|
+
if (!rowRect) { console.log('❌ recent-signal row alpha->beta not found'); process.exit(1); }
|
|
86
|
+
await page.mouse.move(10, 10);
|
|
87
|
+
await page.mouse.move(rowRect.x, rowRect.y);
|
|
88
|
+
await page.waitForTimeout(350);
|
|
89
|
+
const during = await readState();
|
|
90
|
+
|
|
91
|
+
await page.mouse.move(10, 10);
|
|
92
|
+
await page.waitForTimeout(350);
|
|
93
|
+
const after = await readState();
|
|
94
|
+
|
|
95
|
+
await browser.close();
|
|
96
|
+
|
|
97
|
+
const baseEdgeOp = before.edges['alpha → beta'];
|
|
98
|
+
const eAB = during.edges['alpha → beta'];
|
|
99
|
+
const eGD = during.edges['gamma → delta'];
|
|
100
|
+
const eEZ = during.edges['epsilon → zeta'];
|
|
101
|
+
|
|
102
|
+
const bright = (v) => v != null && v >= 0.55;
|
|
103
|
+
const dim = (v) => v != null && v < 0.4;
|
|
104
|
+
const results = {
|
|
105
|
+
baselineEqual: Math.abs(before.edges['alpha → beta'] - before.edges['gamma → delta']) < 0.001
|
|
106
|
+
&& Math.abs(before.edges['alpha → beta'] - before.edges['epsilon → zeta']) < 0.001,
|
|
107
|
+
hoverBrightensTargetEdge: eAB > baseEdgeOp * 1.5,
|
|
108
|
+
hoverDimsOtherEdges: eGD < baseEdgeOp * 0.6 && eEZ < baseEdgeOp * 0.6,
|
|
109
|
+
endpointsStayBright: bright(during.nodes.alpha) && bright(during.nodes.beta),
|
|
110
|
+
nonEndpointsDim: dim(during.nodes.gamma) && dim(during.nodes.delta)
|
|
111
|
+
&& dim(during.nodes.epsilon) && dim(during.nodes.zeta),
|
|
112
|
+
releaseRestoresEdges: Math.abs(after.edges['alpha → beta'] - baseEdgeOp) < 0.05
|
|
113
|
+
&& Math.abs(after.edges['gamma → delta'] - baseEdgeOp) < 0.05,
|
|
114
|
+
releaseRestoresNodes: bright(after.nodes.alpha) && bright(after.nodes.gamma) && bright(after.nodes.epsilon),
|
|
115
|
+
};
|
|
116
|
+
const ok = Object.values(results).every(Boolean);
|
|
117
|
+
console.log(`${ok ? '✅' : '❌'} recent-row hover:`, JSON.stringify(results),
|
|
118
|
+
`\n baseline α→β=${baseEdgeOp}`,
|
|
119
|
+
`\n during α→β=${eAB} γ→δ=${eGD} ε→ζ=${eEZ}`,
|
|
120
|
+
`\n during nodes=`, during.nodes,
|
|
121
|
+
`\n after edges=`, after.edges);
|
|
122
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/* Round 116 verification: recent-signal row click pins the edge.
|
|
2
|
+
* R56 made hover transient; R116 makes click sticky — survives
|
|
3
|
+
* mouseleave, releases on second click or Esc. activeEdgeKey =
|
|
4
|
+
* hoveredEdgeKey ?? pinnedEdgeKey, so hover-while-pinned previews
|
|
5
|
+
* another edge transiently and mouseleave falls back to the pin.
|
|
6
|
+
*
|
|
7
|
+
* Drives 2 flow rows. Click row 0 → row's aria-pressed=true,
|
|
8
|
+
* data-recent-row-pinned=true, the edge stays bright after mouseleave
|
|
9
|
+
* (non-endpoints stay dim, endpoint ring stays). Click row 0 again
|
|
10
|
+
* → release. Pin row 0, hover row 1 → row-1 preview wins; leave →
|
|
11
|
+
* row-0 pin restores. Esc clears.
|
|
12
|
+
*/
|
|
13
|
+
import { chromium } from 'playwright';
|
|
14
|
+
import { readFileSync } from 'node:fs';
|
|
15
|
+
|
|
16
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
17
|
+
const browser = await chromium.launch({ headless: true });
|
|
18
|
+
|
|
19
|
+
const ctx = await browser.newContext({ viewport: { width: 1400, height: 1500 } });
|
|
20
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
21
|
+
await ctx.addInitScript(() => {
|
|
22
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
26
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
27
|
+
const r = await route.fetch();
|
|
28
|
+
const b = await r.json();
|
|
29
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
30
|
+
const mk = (alias) => ({
|
|
31
|
+
alias, status: 'idle', model: 'claude-opus-4', runtime: 'cli-claude-code',
|
|
32
|
+
network_id: nid, project_dir: null,
|
|
33
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
34
|
+
});
|
|
35
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('alpha'), mk('beta'), mk('gamma'), mk('delta')] } });
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const now = Date.now();
|
|
39
|
+
const mkMsg = (id, from_alias, to_alias, ageMs) => ({
|
|
40
|
+
id, from_alias, to_alias, content: 'hi', network_id: 'default',
|
|
41
|
+
created_at: new Date(now - ageMs).toISOString(),
|
|
42
|
+
});
|
|
43
|
+
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: [
|
|
44
|
+
mkMsg('m1', 'alpha', 'beta', 30 * 1000),
|
|
45
|
+
mkMsg('m2', 'gamma', 'delta', 60 * 1000),
|
|
46
|
+
] } }));
|
|
47
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
48
|
+
const page = await ctx.newPage();
|
|
49
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
50
|
+
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 4, { timeout: 30000 });
|
|
51
|
+
await page.waitForSelector('[data-recent-row]', { timeout: 10000 });
|
|
52
|
+
await page.waitForTimeout(400);
|
|
53
|
+
|
|
54
|
+
const rowState = (key) => page.evaluate((k) => {
|
|
55
|
+
const g = document.querySelector(`[data-recent-row="${k}"]`);
|
|
56
|
+
return {
|
|
57
|
+
pinned: g?.getAttribute('data-recent-row-pinned') || '',
|
|
58
|
+
aria: g?.getAttribute('aria-pressed') || '',
|
|
59
|
+
};
|
|
60
|
+
}, key);
|
|
61
|
+
const endpointRingFor = (alias) => page.evaluate((a) => {
|
|
62
|
+
const g = document.querySelector(`g[data-node="${a}"]`);
|
|
63
|
+
return !!g?.querySelector('[data-edge-endpoint-ring]');
|
|
64
|
+
}, alias);
|
|
65
|
+
|
|
66
|
+
const before = await rowState('alpha->beta');
|
|
67
|
+
|
|
68
|
+
// Click row 0 → pin.
|
|
69
|
+
await page.locator('[data-recent-row="alpha->beta"]').click();
|
|
70
|
+
await page.mouse.move(10, 10);
|
|
71
|
+
await page.waitForTimeout(300);
|
|
72
|
+
const afterPin = await rowState('alpha->beta');
|
|
73
|
+
const alphaRingPin = await endpointRingFor('alpha');
|
|
74
|
+
const betaRingPin = await endpointRingFor('beta');
|
|
75
|
+
const gammaRingPin = await endpointRingFor('gamma');
|
|
76
|
+
|
|
77
|
+
// Click again → release.
|
|
78
|
+
await page.locator('[data-recent-row="alpha->beta"]').click();
|
|
79
|
+
await page.mouse.move(10, 10);
|
|
80
|
+
await page.waitForTimeout(300);
|
|
81
|
+
const afterRelease = await rowState('alpha->beta');
|
|
82
|
+
const alphaRingRelease = await endpointRingFor('alpha');
|
|
83
|
+
|
|
84
|
+
// Pin row 0 again, hover row 1 — preview wins.
|
|
85
|
+
await page.locator('[data-recent-row="alpha->beta"]').click();
|
|
86
|
+
await page.mouse.move(10, 10);
|
|
87
|
+
await page.waitForTimeout(200);
|
|
88
|
+
await page.locator('[data-recent-row="gamma->delta"]').hover();
|
|
89
|
+
await page.waitForTimeout(300);
|
|
90
|
+
const alphaWhileHoverGamma = await endpointRingFor('alpha');
|
|
91
|
+
const gammaWhileHover = await endpointRingFor('gamma');
|
|
92
|
+
|
|
93
|
+
// Leave gamma row — row-0 pin restores.
|
|
94
|
+
await page.mouse.move(10, 10);
|
|
95
|
+
await page.waitForTimeout(300);
|
|
96
|
+
const alphaAfterLeave = await endpointRingFor('alpha');
|
|
97
|
+
const gammaAfterLeave = await endpointRingFor('gamma');
|
|
98
|
+
|
|
99
|
+
// Esc clears.
|
|
100
|
+
await page.keyboard.press('Escape');
|
|
101
|
+
await page.waitForTimeout(300);
|
|
102
|
+
const afterEsc = await rowState('alpha->beta');
|
|
103
|
+
const alphaAfterEsc = await endpointRingFor('alpha');
|
|
104
|
+
|
|
105
|
+
await browser.close();
|
|
106
|
+
|
|
107
|
+
const results = {
|
|
108
|
+
before_notPinned: before.pinned === 'false' && before.aria === 'false',
|
|
109
|
+
pin_attrTrue: afterPin.pinned === 'true' && afterPin.aria === 'true',
|
|
110
|
+
pin_endpointsLit: alphaRingPin === true && betaRingPin === true,
|
|
111
|
+
pin_nonEndpointDark: gammaRingPin === false,
|
|
112
|
+
releaseAfterReclick: afterRelease.pinned === 'false' && alphaRingRelease === false,
|
|
113
|
+
hoverPreview_gammaLit: gammaWhileHover === true,
|
|
114
|
+
hoverPreview_alphaDark: alphaWhileHoverGamma === false,
|
|
115
|
+
leave_pinRestored: alphaAfterLeave === true && gammaAfterLeave === false,
|
|
116
|
+
esc_clearsPin: afterEsc.pinned === 'false' && alphaAfterEsc === false,
|
|
117
|
+
};
|
|
118
|
+
const ok = Object.values(results).every(Boolean);
|
|
119
|
+
console.log(`${ok ? '✅' : '❌'} recent-row pin:`, JSON.stringify(results),
|
|
120
|
+
`\n afterPin=`, afterPin,
|
|
121
|
+
`\n rings@pin: alpha=`, alphaRingPin, ' beta=', betaRingPin, ' gamma=', gammaRingPin,
|
|
122
|
+
`\n afterRelease=`, afterRelease,
|
|
123
|
+
`\n hoverPreview: alpha=`, alphaWhileHoverGamma, ' gamma=', gammaWhileHover,
|
|
124
|
+
`\n afterLeave: alpha=`, alphaAfterLeave, ' gamma=', gammaAfterLeave,
|
|
125
|
+
`\n afterEsc=`, afterEsc);
|
|
126
|
+
process.exit(ok ? 0 : 1);
|