@sleep2agi/agent-network-dashboard 0.4.6-preview.16 → 0.4.6-preview.161
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/01lmbsd37fybu.js +1 -0
- package/.next/static/chunks/032~4k7il7hnk.css +2 -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/06fy8p2g0jbz1.js +4 -0
- package/.next/static/chunks/08kf-.bgs10ze.js +1 -0
- package/.next/static/chunks/0ggj5ummw2a84.js +7 -0
- package/.next/static/chunks/0glmrdj9112tc.js +7 -0
- package/.next/static/chunks/0oehx47rte9ek.js +1 -0
- package/.next/static/chunks/0rxrez_cjn.eh.js +1 -0
- package/.next/static/chunks/0x8x.29hkju5a.js +1 -0
- package/.next/static/chunks/10z.kc0g0jj8p.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/ChatPopover.tsx +38 -2
- package/app/components/CommandPalette.tsx +107 -0
- package/app/components/HelpOverlay.tsx +126 -0
- package/app/components/ServersDrawer.tsx +64 -27
- package/app/components/TopoGraph.tsx +3102 -237
- package/app/components/utils.ts +8 -7
- package/app/globals.css +46 -5
- 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-nav-test.mjs +117 -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-chrome-a11y-test.mjs +107 -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-hot-test.mjs +115 -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-hot-test.mjs +129 -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-a11y-test.mjs +113 -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-hover-lift-test.mjs +127 -0
- package/scripts/topo-groupbox-live-test.mjs +100 -0
- package/scripts/topo-groupbox-march-busyness-test.mjs +155 -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-r134-test.mjs +74 -0
- package/scripts/topo-help-overlay-r137-test.mjs +81 -0
- package/scripts/topo-help-overlay-r141-test.mjs +86 -0
- package/scripts/topo-help-overlay-r153-test.mjs +85 -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-hub-working-count-test.mjs +99 -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-hover-lift-test.mjs +109 -0
- package/scripts/topo-legend-row-tint-test.mjs +95 -0
- package/scripts/topo-legend-row-title-test.mjs +102 -0
- package/scripts/topo-minimap-test.mjs +68 -0
- package/scripts/topo-mobile-chips-test.mjs +103 -0
- package/scripts/topo-node-a11y-test.mjs +107 -0
- package/scripts/topo-node-hover-lift-test.mjs +85 -0
- package/scripts/topo-node-title-peers-test.mjs +107 -0
- package/scripts/topo-node-title-test.mjs +101 -0
- package/scripts/topo-offline-dim-test.mjs +70 -0
- package/scripts/topo-online-chip-nav-test.mjs +143 -0
- package/scripts/topo-orbit-busyness-test.mjs +96 -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-panel-hover-elevation-test.mjs +118 -0
- package/scripts/topo-particle-stagger-test.mjs +82 -0
- package/scripts/topo-pin-intersection-empty-test.mjs +129 -0
- package/scripts/topo-pin-intersection-test.mjs +121 -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-panel-hot-header-test.mjs +132 -0
- package/scripts/topo-recent-panel-more-nav-test.mjs +127 -0
- package/scripts/topo-recent-panel-more-test.mjs +106 -0
- package/scripts/topo-recent-row-hot-test.mjs +110 -0
- package/scripts/topo-recent-row-hover-lift-test.mjs +128 -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-title-test.mjs +112 -0
- package/scripts/topo-recent-row-ts-test.mjs +95 -0
- package/scripts/topo-recent-row-typography-test.mjs +119 -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-spoke-busyness-test.mjs +110 -0
- package/scripts/topo-status-chip-hover-test.mjs +101 -0
- package/scripts/topo-status-chip-tooltip-test.mjs +95 -0
- package/scripts/topo-sweep-busyness-test.mjs +94 -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-chip-pin-test.mjs +148 -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/05gis4d.n_tv~.js +0 -1
- package/.next/static/chunks/09~8xbt2mo_.u.js +0 -1
- package/.next/static/chunks/0_qfg5s5uzs7..js +0 -7
- package/.next/static/chunks/0a0wcpeb8i2my.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/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/13vw-ubg-9pjp.css +0 -2
- /package/.next/static/{71LBMB3-nZe_9iMTuD7GZ → IJ5nEFbzhj38AtfV6zg14}/_buildManifest.js +0 -0
- /package/.next/static/{71LBMB3-nZe_9iMTuD7GZ → IJ5nEFbzhj38AtfV6zg14}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{71LBMB3-nZe_9iMTuD7GZ → IJ5nEFbzhj38AtfV6zg14}/_ssgManifest.js +0 -0
|
@@ -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,132 @@
|
|
|
1
|
+
/* Round 129 verification: recent-signal panel header gains a
|
|
2
|
+
* " · N hot" amber tail when ≥ 1 flowLink has count ≥ 10.
|
|
3
|
+
*
|
|
4
|
+
* The hot-lane convention's surfaces:
|
|
5
|
+
* R126: canvas midpoint count badge → amber stroke
|
|
6
|
+
* R127: recent-signal row count digit → amber + bold
|
|
7
|
+
* R129: recent-signal panel HEADER → " · N hot" amber suffix
|
|
8
|
+
*
|
|
9
|
+
* Vertical scan path now reads: header → rows → canvas. Each layer
|
|
10
|
+
* answers a different scope: header = "how many hot?", rows =
|
|
11
|
+
* "which ones?", canvas = "where on the topology?".
|
|
12
|
+
*
|
|
13
|
+
* Three states:
|
|
14
|
+
* A. 3 pairs, all count < 10 → header "3 flows", no hot tail
|
|
15
|
+
* B. 5 pairs, 2 of them count ≥ 10 → header "5 flows · 2 hot", amber tail
|
|
16
|
+
* C. 5 pairs, 5 of them count ≥ 10 → header "5 flows · 5 hot"
|
|
17
|
+
*/
|
|
18
|
+
import { chromium } from 'playwright';
|
|
19
|
+
import { readFileSync } from 'node:fs';
|
|
20
|
+
|
|
21
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
22
|
+
|
|
23
|
+
async function probe(seedPairs) {
|
|
24
|
+
// seedPairs is an array of [from, to, count] tuples — each pair gets
|
|
25
|
+
// `count` msgs to make link.count == count after dedup.
|
|
26
|
+
const browser = await chromium.launch({ headless: true });
|
|
27
|
+
const ctx = await browser.newContext({ viewport: { width: 1400, height: 1500 } });
|
|
28
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
29
|
+
await ctx.addInitScript(() => {
|
|
30
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
34
|
+
const aliasSet = new Set();
|
|
35
|
+
for (const [a, b] of seedPairs) { aliasSet.add(a); aliasSet.add(b); }
|
|
36
|
+
const aliases = [...aliasSet];
|
|
37
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
38
|
+
const r = await route.fetch();
|
|
39
|
+
const b = await r.json();
|
|
40
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
41
|
+
const mk = (alias) => ({
|
|
42
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'cli-claude-code',
|
|
43
|
+
network_id: nid, project_dir: null,
|
|
44
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
45
|
+
});
|
|
46
|
+
await route.fulfill({ response: r, json: { ...b, sessions: aliases.map(mk) } });
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const now = Date.now();
|
|
50
|
+
const msgs = [];
|
|
51
|
+
let id = 0;
|
|
52
|
+
for (const [from, to, count] of seedPairs) {
|
|
53
|
+
for (let i = 0; i < count; i++) {
|
|
54
|
+
msgs.push({
|
|
55
|
+
id: `m${id++}`,
|
|
56
|
+
from_alias: from,
|
|
57
|
+
to_alias: to,
|
|
58
|
+
content: 'hi',
|
|
59
|
+
network_id: 'default',
|
|
60
|
+
created_at: new Date(now - (20000 + i * 500 + id * 13)).toISOString(),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: msgs } }));
|
|
65
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
66
|
+
|
|
67
|
+
const page = await ctx.newPage();
|
|
68
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
69
|
+
await page.waitForFunction((n) => document.querySelectorAll('g[data-node]').length === n, aliases.length, { timeout: 30000 });
|
|
70
|
+
await page.waitForTimeout(500);
|
|
71
|
+
|
|
72
|
+
const out = await page.evaluate(() => {
|
|
73
|
+
const count = document.querySelector('[data-recent-panel-count]');
|
|
74
|
+
const hot = document.querySelector('[data-recent-panel-hot-count]');
|
|
75
|
+
return {
|
|
76
|
+
countText: count?.textContent,
|
|
77
|
+
hotText: hot?.textContent,
|
|
78
|
+
hotAttr: hot?.getAttribute('data-recent-panel-hot-count'),
|
|
79
|
+
hotFill: hot?.getAttribute('fill'),
|
|
80
|
+
hotWeight: hot?.getAttribute('font-weight'),
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
await browser.close();
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// State A: all warm
|
|
89
|
+
const a = await probe([
|
|
90
|
+
['alpha', 'beta', 4],
|
|
91
|
+
['gamma', 'delta', 5],
|
|
92
|
+
['epsilon', 'zeta', 3],
|
|
93
|
+
]);
|
|
94
|
+
|
|
95
|
+
// State B: 5 pairs, 2 hot (≥ 10)
|
|
96
|
+
const b = await probe([
|
|
97
|
+
['alpha', 'beta', 12], // hot
|
|
98
|
+
['gamma', 'delta', 15], // hot
|
|
99
|
+
['epsilon', 'zeta', 4],
|
|
100
|
+
['eta', 'theta', 6],
|
|
101
|
+
['iota', 'kappa', 8],
|
|
102
|
+
]);
|
|
103
|
+
|
|
104
|
+
// State C: 5 pairs, all 5 hot
|
|
105
|
+
const c = await probe([
|
|
106
|
+
['alpha', 'beta', 12],
|
|
107
|
+
['gamma', 'delta', 11],
|
|
108
|
+
['epsilon', 'zeta', 14],
|
|
109
|
+
['eta', 'theta', 13],
|
|
110
|
+
['iota', 'kappa', 25],
|
|
111
|
+
]);
|
|
112
|
+
|
|
113
|
+
const amber = '#fbbf24';
|
|
114
|
+
|
|
115
|
+
const results = {
|
|
116
|
+
a_count_3flows: a.countText === '3 flows',
|
|
117
|
+
a_noHotTspan: a.hotText === undefined,
|
|
118
|
+
|
|
119
|
+
b_count_5flows: b.countText === '5 flows',
|
|
120
|
+
b_hot_text: b.hotText === ' · 2 hot',
|
|
121
|
+
b_hot_attr: b.hotAttr === '2',
|
|
122
|
+
b_hot_amberFill: (b.hotFill || '').toLowerCase() === amber,
|
|
123
|
+
b_hot_boldWeight: b.hotWeight === '700',
|
|
124
|
+
|
|
125
|
+
c_count_5flows: c.countText === '5 flows',
|
|
126
|
+
c_hot_text: c.hotText === ' · 5 hot',
|
|
127
|
+
c_hot_attr: c.hotAttr === '5',
|
|
128
|
+
};
|
|
129
|
+
const ok = Object.values(results).every(Boolean);
|
|
130
|
+
console.log(`${ok ? '✅' : '❌'} recent-panel hot header:`, JSON.stringify(results),
|
|
131
|
+
`\n A=`, a, `\n B=`, b, `\n C=`, c);
|
|
132
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/* Round 133 verification: R128's "+N more flows" footer becomes a
|
|
2
|
+
* clickable nav to /messages. R128 introduced the truncation hint
|
|
3
|
+
* as pure metadata; R133 lets the user act on it.
|
|
4
|
+
*
|
|
5
|
+
* Three states tested:
|
|
6
|
+
* A. Click footer → navigation lands on /messages
|
|
7
|
+
* B. Hover footer → opacity rises 0.55 → 0.85, underline appears
|
|
8
|
+
* C. Leave hover → opacity drops back, underline gone
|
|
9
|
+
*
|
|
10
|
+
* Plus: footer carries role="link" + cursor:pointer + a tooltip
|
|
11
|
+
* referencing /messages, all for discoverability and a11y.
|
|
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
|
+
const aliases = ['alpha', 'beta', 'gamma', 'delta', 'epsilon', 'zeta'];
|
|
27
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
28
|
+
const r = await route.fetch();
|
|
29
|
+
const b = await r.json();
|
|
30
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
31
|
+
const mk = (alias) => ({
|
|
32
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'cli-claude-code',
|
|
33
|
+
network_id: nid, project_dir: null,
|
|
34
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
35
|
+
});
|
|
36
|
+
await route.fulfill({ response: r, json: { ...b, sessions: aliases.map(mk) } });
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const now = Date.now();
|
|
40
|
+
const msgs = [];
|
|
41
|
+
// 5 distinct pairs → forces R128 footer with "+ 2 more flows"
|
|
42
|
+
for (let i = 0; i < 5; i++) {
|
|
43
|
+
msgs.push({
|
|
44
|
+
id: `m${i}`,
|
|
45
|
+
from_alias: aliases[i],
|
|
46
|
+
to_alias: aliases[(i + 1) % aliases.length],
|
|
47
|
+
content: 'hi',
|
|
48
|
+
network_id: 'default',
|
|
49
|
+
created_at: new Date(now - (20000 + i * 1000)).toISOString(),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: msgs } }));
|
|
53
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
54
|
+
|
|
55
|
+
const page = await ctx.newPage();
|
|
56
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
57
|
+
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 6, { timeout: 30000 });
|
|
58
|
+
await page.waitForSelector('[data-recent-panel-more-nav]', { timeout: 10000 });
|
|
59
|
+
await page.waitForTimeout(400);
|
|
60
|
+
|
|
61
|
+
const beforeHover = await page.evaluate(() => {
|
|
62
|
+
const wrap = document.querySelector('[data-recent-panel-more-nav]');
|
|
63
|
+
const text = wrap?.querySelector('text[data-recent-panel-more]');
|
|
64
|
+
return {
|
|
65
|
+
role: wrap?.getAttribute('role'),
|
|
66
|
+
tabindex: wrap?.getAttribute('tabindex'),
|
|
67
|
+
cursor: (wrap?.getAttribute('style') || '').includes('pointer'),
|
|
68
|
+
title: wrap?.querySelector('title')?.textContent,
|
|
69
|
+
opacity: text?.getAttribute('opacity'),
|
|
70
|
+
underline: text?.getAttribute('text-decoration'),
|
|
71
|
+
moreCount: text?.getAttribute('data-recent-panel-more'),
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Hover the footer
|
|
76
|
+
await page.locator('[data-recent-panel-more-nav]').hover();
|
|
77
|
+
await page.waitForTimeout(250);
|
|
78
|
+
const onHover = await page.evaluate(() => {
|
|
79
|
+
const text = document.querySelector('[data-recent-panel-more-nav] text');
|
|
80
|
+
return {
|
|
81
|
+
opacity: text?.getAttribute('opacity'),
|
|
82
|
+
underline: text?.getAttribute('text-decoration'),
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Move away → restore
|
|
87
|
+
await page.mouse.move(10, 10);
|
|
88
|
+
await page.waitForTimeout(250);
|
|
89
|
+
const afterLeave = await page.evaluate(() => {
|
|
90
|
+
const text = document.querySelector('[data-recent-panel-more-nav] text');
|
|
91
|
+
return {
|
|
92
|
+
opacity: text?.getAttribute('opacity'),
|
|
93
|
+
underline: text?.getAttribute('text-decoration'),
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Click → expect /messages navigation
|
|
98
|
+
await page.locator('[data-recent-panel-more-nav]').click();
|
|
99
|
+
await page.waitForURL('**/messages', { timeout: 10000 });
|
|
100
|
+
const finalUrl = page.url();
|
|
101
|
+
|
|
102
|
+
await browser.close();
|
|
103
|
+
|
|
104
|
+
const results = {
|
|
105
|
+
before_roleLink: beforeHover.role === 'link',
|
|
106
|
+
before_tabIndex0: beforeHover.tabindex === '0',
|
|
107
|
+
before_cursorPointer: beforeHover.cursor,
|
|
108
|
+
before_titleMentionsMessages: (beforeHover.title || '').includes('/messages'),
|
|
109
|
+
before_moreCount2: beforeHover.moreCount === '2',
|
|
110
|
+
before_opacity55: beforeHover.opacity === '0.55',
|
|
111
|
+
before_noUnderline: beforeHover.underline === 'none' || !beforeHover.underline,
|
|
112
|
+
|
|
113
|
+
hover_opacity85: onHover.opacity === '0.85',
|
|
114
|
+
hover_underline: onHover.underline === 'underline',
|
|
115
|
+
|
|
116
|
+
leave_opacityRestored: afterLeave.opacity === '0.55',
|
|
117
|
+
leave_underlineGone: afterLeave.underline === 'none' || !afterLeave.underline,
|
|
118
|
+
|
|
119
|
+
click_navigatedToMessages: /\/messages$/.test(finalUrl),
|
|
120
|
+
};
|
|
121
|
+
const ok = Object.values(results).every(Boolean);
|
|
122
|
+
console.log(`${ok ? '✅' : '❌'} recent-panel more nav:`, JSON.stringify(results),
|
|
123
|
+
`\n before=`, beforeHover,
|
|
124
|
+
`\n onHover=`, onHover,
|
|
125
|
+
`\n afterLeave=`, afterLeave,
|
|
126
|
+
`\n finalUrl=`, finalUrl);
|
|
127
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/* Round 128 verification: "+N more flows" overflow hint in the
|
|
2
|
+
* recent-signal panel.
|
|
3
|
+
*
|
|
4
|
+
* The panel renders top 3 flowLinks via .slice(0, 3). When the
|
|
5
|
+
* fleet has > 3 active flows, the rest silently disappear — the
|
|
6
|
+
* R96 "X flows" header reports the total but doesn't make
|
|
7
|
+
* truncation explicit. R128 adds a muted italic footer
|
|
8
|
+
* "+ N more flow(s)"
|
|
9
|
+
* inside the existing panel (y=82, between row-3 baseline and the
|
|
10
|
+
* panel bottom at y=84), only when flowLinks.length > 3.
|
|
11
|
+
*
|
|
12
|
+
* Three states tested:
|
|
13
|
+
* - 5 distinct flow pairs → footer shows "+ 2 more flows"
|
|
14
|
+
* - exactly 3 flow pairs → footer absent
|
|
15
|
+
* - 0 flows (empty panel) → footer absent (R45 placeholder wins)
|
|
16
|
+
*
|
|
17
|
+
* Note: the test seeds (count) messages per pair so each unique
|
|
18
|
+
* (from→to) pair becomes ONE flowLink (deduped). Pairs > 3 force
|
|
19
|
+
* the hint; pairs ≤ 3 don't.
|
|
20
|
+
*/
|
|
21
|
+
import { chromium } from 'playwright';
|
|
22
|
+
import { readFileSync } from 'node:fs';
|
|
23
|
+
|
|
24
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
25
|
+
|
|
26
|
+
async function probe(pairCount) {
|
|
27
|
+
const browser = await chromium.launch({ headless: true });
|
|
28
|
+
const ctx = await browser.newContext({ viewport: { width: 1400, height: 1500 } });
|
|
29
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
30
|
+
await ctx.addInitScript(() => {
|
|
31
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
35
|
+
const aliases = ['alpha', 'beta', 'gamma', 'delta', 'epsilon', 'zeta'];
|
|
36
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
37
|
+
const r = await route.fetch();
|
|
38
|
+
const b = await r.json();
|
|
39
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
40
|
+
const mk = (alias) => ({
|
|
41
|
+
alias, status: 'working', model: 'claude-opus-4', runtime: 'cli-claude-code',
|
|
42
|
+
network_id: nid, project_dir: null,
|
|
43
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
44
|
+
});
|
|
45
|
+
await route.fulfill({ response: r, json: { ...b, sessions: aliases.map(mk) } });
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const now = Date.now();
|
|
49
|
+
const msgs = [];
|
|
50
|
+
// Make pairCount distinct (from→to) pairs, 1 msg each, ascending age
|
|
51
|
+
for (let i = 0; i < pairCount; i++) {
|
|
52
|
+
msgs.push({
|
|
53
|
+
id: `m${i}`,
|
|
54
|
+
from_alias: aliases[i],
|
|
55
|
+
to_alias: aliases[(i + 1) % aliases.length],
|
|
56
|
+
content: 'hi',
|
|
57
|
+
network_id: 'default',
|
|
58
|
+
created_at: new Date(now - (20000 + i * 1000)).toISOString(),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: { messages: msgs } }));
|
|
62
|
+
await ctx.route('**/api/hub/tasks*', (route) => route.fulfill({ json: { tasks: [] } }));
|
|
63
|
+
|
|
64
|
+
const page = await ctx.newPage();
|
|
65
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
66
|
+
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 6, { timeout: 30000 });
|
|
67
|
+
await page.waitForTimeout(500);
|
|
68
|
+
|
|
69
|
+
const out = await page.evaluate(() => {
|
|
70
|
+
const el = document.querySelector('[data-recent-panel-more]');
|
|
71
|
+
const rows = document.querySelectorAll('[data-recent-row]').length;
|
|
72
|
+
const headerCount = document.querySelector('[data-recent-panel-count]')?.textContent;
|
|
73
|
+
return {
|
|
74
|
+
footerPresent: !!el,
|
|
75
|
+
footerText: el?.textContent?.trim(),
|
|
76
|
+
footerAttr: el?.getAttribute('data-recent-panel-more'),
|
|
77
|
+
rows,
|
|
78
|
+
headerCount,
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
await browser.close();
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const five = await probe(5);
|
|
87
|
+
const three = await probe(3);
|
|
88
|
+
const zero = await probe(0);
|
|
89
|
+
|
|
90
|
+
const results = {
|
|
91
|
+
five_footerPresent: five.footerPresent,
|
|
92
|
+
five_footerText: five.footerText === '+ 2 more flows',
|
|
93
|
+
five_footerAttr: five.footerAttr === '2',
|
|
94
|
+
five_rowsCapped3: five.rows === 3,
|
|
95
|
+
five_headerSaysFive: five.headerCount?.startsWith('5'),
|
|
96
|
+
|
|
97
|
+
three_footerAbsent: !three.footerPresent,
|
|
98
|
+
three_rowsExactly3: three.rows === 3,
|
|
99
|
+
|
|
100
|
+
zero_footerAbsent: !zero.footerPresent,
|
|
101
|
+
zero_rowsZero: zero.rows === 0,
|
|
102
|
+
};
|
|
103
|
+
const ok = Object.values(results).every(Boolean);
|
|
104
|
+
console.log(`${ok ? '✅' : '❌'} recent-panel more:`, JSON.stringify(results),
|
|
105
|
+
`\n five=`, five, `\n three=`, three, `\n zero=`, zero);
|
|
106
|
+
process.exit(ok ? 0 : 1);
|