@sleep2agi/agent-network-dashboard 0.4.6-preview.345 → 0.4.6-preview.346
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/build-manifest.json +3 -3
- package/.next/diagnostics/route-bundle-stats.json +4 -4
- package/.next/fallback-build-manifest.json +3 -3
- 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.html +1 -1
- package/.next/server/app/_not-found.rsc +1 -1
- package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/admin.html +1 -1
- package/.next/server/app/admin.rsc +1 -1
- package/.next/server/app/admin.segments/_full.segment.rsc +1 -1
- package/.next/server/app/admin.segments/_head.segment.rsc +1 -1
- package/.next/server/app/admin.segments/_index.segment.rsc +1 -1
- package/.next/server/app/admin.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/admin.segments/admin.segment.rsc +1 -1
- package/.next/server/app/index.html +2 -2
- package/.next/server/app/index.rsc +2 -2
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- 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 +2 -2
- package/.next/server/app/login.segments/_full.segment.rsc +2 -2
- package/.next/server/app/login.segments/_head.segment.rsc +1 -1
- package/.next/server/app/login.segments/_index.segment.rsc +1 -1
- package/.next/server/app/login.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/login.segments/login.segment.rsc +1 -1
- package/.next/server/app/logs.html +1 -1
- package/.next/server/app/logs.rsc +1 -1
- package/.next/server/app/logs.segments/_full.segment.rsc +1 -1
- package/.next/server/app/logs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/logs.segments/_index.segment.rsc +1 -1
- package/.next/server/app/logs.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/logs.segments/logs.segment.rsc +1 -1
- package/.next/server/app/messages.html +1 -1
- package/.next/server/app/messages.rsc +1 -1
- package/.next/server/app/messages.segments/_full.segment.rsc +1 -1
- package/.next/server/app/messages.segments/_head.segment.rsc +1 -1
- package/.next/server/app/messages.segments/_index.segment.rsc +1 -1
- package/.next/server/app/messages.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/messages.segments/messages.segment.rsc +1 -1
- package/.next/server/app/node.html +1 -1
- package/.next/server/app/node.rsc +1 -1
- package/.next/server/app/node.segments/_full.segment.rsc +1 -1
- package/.next/server/app/node.segments/_head.segment.rsc +1 -1
- package/.next/server/app/node.segments/_index.segment.rsc +1 -1
- package/.next/server/app/node.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/node.segments/node.segment.rsc +1 -1
- package/.next/server/app/nodes.html +1 -1
- package/.next/server/app/nodes.rsc +1 -1
- package/.next/server/app/nodes.segments/_full.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/_head.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/_index.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/nodes.segment.rsc +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs.html +1 -1
- package/.next/server/app/server-logs.rsc +1 -1
- package/.next/server/app/server-logs.segments/_full.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/_index.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/server-logs.segment.rsc +1 -1
- package/.next/server/app/settings/networks.html +1 -1
- package/.next/server/app/settings/networks.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_full.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_index.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/settings.segment.rsc +1 -1
- package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens.html +1 -1
- package/.next/server/app/settings/tokens.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_full.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_index.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/settings.segment.rsc +1 -1
- package/.next/server/app/settings.html +2 -2
- package/.next/server/app/settings.rsc +2 -2
- package/.next/server/app/settings.segments/_full.segment.rsc +2 -2
- package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_index.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
- package/.next/server/app/tasks.html +1 -1
- package/.next/server/app/tasks.rsc +1 -1
- package/.next/server/app/tasks.segments/_full.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/_head.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/_index.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/tasks.segment.rsc +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js +1 -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_09d29my._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js.map +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/static/chunks/{16bh0.ekdd5ge.js → 0d6e7f~0oulwt.js} +1 -1
- package/.next/static/chunks/{0ul0qqy8mexbh.js → 0hq2~4ey_gfcx.js} +1 -1
- package/.next/static/chunks/{0_e7lmzh87xp3.js → 0rqg8f7ygcty8.js} +1 -1
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/components/TopoGraph.tsx +17 -3
- package/package.json +1 -1
- package/screenshots/r293-p0/servers-drawer-v0.10.0-full.png +0 -0
- package/screenshots/r293-p0/servers-drawer-v0.10.0.png +0 -0
- package/scripts/p0-servers-drawer-screenshot.mjs +99 -0
- package/scripts/topo-group-pip-fadein-test.mjs +5 -1
- package/scripts/topo-group-pip-singletier-drop-test.mjs +131 -0
- /package/.next/static/{NhfYap25UUapTiHJmca96 → MBGamBXWPewuLnqj0_Ed-}/_buildManifest.js +0 -0
- /package/.next/static/{NhfYap25UUapTiHJmca96 → MBGamBXWPewuLnqj0_Ed-}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{NhfYap25UUapTiHJmca96 → MBGamBXWPewuLnqj0_Ed-}/_ssgManifest.js +0 -0
package/.next/trace-build
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
[{"name":"run-turbopack","duration":
|
|
1
|
+
[{"name":"run-turbopack","duration":7434216,"timestamp":120214470345,"id":14,"parentId":1,"tags":{},"startTime":1778928186717,"traceId":"04efb3bd722f9121"},{"name":"turbopack-build-events","duration":77,"timestamp":120214815235,"id":15,"parentId":1,"tags":{},"startTime":1778928187062,"traceId":"04efb3bd722f9121"},{"name":"run-typescript","duration":11026777,"timestamp":120221914825,"id":16,"parentId":1,"tags":{},"startTime":1778928194161,"traceId":"04efb3bd722f9121"},{"name":"static-check","duration":1074250,"timestamp":120233175548,"id":19,"parentId":1,"tags":{},"startTime":1778928205422,"traceId":"04efb3bd722f9121"},{"name":"static-generation","duration":697719,"timestamp":120234265215,"id":105,"parentId":1,"tags":{},"startTime":1778928206511,"traceId":"04efb3bd722f9121"},{"name":"telemetry-flush","duration":33209,"timestamp":120235008650,"id":114,"parentId":1,"tags":{},"startTime":1778928207255,"traceId":"04efb3bd722f9121"},{"name":"next-build","duration":20863334,"timestamp":120214178594,"id":1,"tags":{"buildMode":"default","version":"16.2.3","bundler":"turbopack","has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1778928186425,"traceId":"04efb3bd722f9121"}]
|
|
@@ -3698,7 +3698,21 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
3698
3698
|
tier-coloured pips alongside every other
|
|
3699
3699
|
theme-driven element. R230's tabular-nums
|
|
3700
3700
|
stays. */}
|
|
3701
|
-
{
|
|
3701
|
+
{/* Round 319 / Loop: drop a tier pip when its count
|
|
3702
|
+
equals box.count — i.e. single-tier groups (all
|
|
3703
|
+
working, all idle, all offline). Pre-R319 a 4-all-
|
|
3704
|
+
idle group rendered as `P站 · 4 4i` with the "4"
|
|
3705
|
+
visually doubled; Vincent telegram 5304 flagged
|
|
3706
|
+
this as 比较难看 in a real-data screenshot
|
|
3707
|
+
(ai-insight · 6 6i, blueleap · 3 3i, P站 · 4 4i).
|
|
3708
|
+
The dropped pip's information is already conveyed
|
|
3709
|
+
by the group-box stroke colour (R68 isPinned/
|
|
3710
|
+
hover accent uses the dominant-tier hue) plus
|
|
3711
|
+
the SVG <title> tooltip listing the status
|
|
3712
|
+
breakdown. Multi-tier groups (e.g. `alpha · 3
|
|
3713
|
+
2w 1i`) render unchanged — those pips genuinely
|
|
3714
|
+
add breakdown info that the total doesn't carry. */}
|
|
3715
|
+
{box.statuses.working > 0 && box.statuses.working !== box.count && (
|
|
3702
3716
|
<tspan
|
|
3703
3717
|
dx="8"
|
|
3704
3718
|
fill={isLight ? '#059669' : '#22c55e'}
|
|
@@ -3709,7 +3723,7 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
3709
3723
|
style={{ fontVariantNumeric: 'tabular-nums', transition: 'fill 200ms ease-out' }}
|
|
3710
3724
|
>{box.statuses.working}w</tspan>
|
|
3711
3725
|
)}
|
|
3712
|
-
{box.statuses.idle > 0 && (
|
|
3726
|
+
{box.statuses.idle > 0 && box.statuses.idle !== box.count && (
|
|
3713
3727
|
<tspan
|
|
3714
3728
|
dx="4"
|
|
3715
3729
|
fill={isLight ? '#0d9488' : '#2dd4bf'}
|
|
@@ -3720,7 +3734,7 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
3720
3734
|
style={{ fontVariantNumeric: 'tabular-nums', transition: 'fill 200ms ease-out' }}
|
|
3721
3735
|
>{box.statuses.idle}i</tspan>
|
|
3722
3736
|
)}
|
|
3723
|
-
{box.statuses.offline > 0 && (
|
|
3737
|
+
{box.statuses.offline > 0 && box.statuses.offline !== box.count && (
|
|
3724
3738
|
<tspan
|
|
3725
3739
|
dx="4"
|
|
3726
3740
|
fill={isLight ? '#94a3b8' : '#6b7280'}
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/* v0.10.0 Hero 1+2 — ServersDrawer extension screenshot evidence for #140.
|
|
2
|
+
* Mocks the /api/hub/servers response with disk + history + agents
|
|
3
|
+
* to surface the new expandable detail view. */
|
|
4
|
+
import { chromium } from 'playwright';
|
|
5
|
+
import { readFileSync } from 'node:fs';
|
|
6
|
+
|
|
7
|
+
const out = process.argv[2] || 'screenshots/r293-p0/servers-drawer-expanded';
|
|
8
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
9
|
+
const browser = await chromium.launch({ headless: true });
|
|
10
|
+
const ctx = await browser.newContext({ viewport: { width: 1600, height: 1000 }, deviceScaleFactor: 2 });
|
|
11
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
12
|
+
await ctx.addInitScript(() => {
|
|
13
|
+
try {
|
|
14
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
15
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
16
|
+
// Force drawer open + expand the first card by hostname guess.
|
|
17
|
+
localStorage.setItem('anet-servers-drawer', '1');
|
|
18
|
+
localStorage.setItem('anet-servers-drawer-expanded', JSON.stringify(['mock-1', 'mock-2']));
|
|
19
|
+
} catch {}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// Mock servers payload with full v0.10.0 schema.
|
|
23
|
+
await ctx.route('**/api/hub/servers*', (route) => {
|
|
24
|
+
route.fulfill({
|
|
25
|
+
json: {
|
|
26
|
+
servers: [
|
|
27
|
+
{
|
|
28
|
+
hostname: 'mock-1',
|
|
29
|
+
ip: '10.0.0.10',
|
|
30
|
+
cpu_load_1min: 2.4,
|
|
31
|
+
cpu_cores: 8,
|
|
32
|
+
mem_used_gb: 18.2,
|
|
33
|
+
mem_total_gb: 32,
|
|
34
|
+
disk_used_gb: 220,
|
|
35
|
+
disk_total_gb: 500,
|
|
36
|
+
cpu_history: [25, 28, 32, 30, 35, 38, 40, 36, 33, 30],
|
|
37
|
+
mem_history: [50, 52, 55, 56, 58, 57, 59, 60, 58, 57],
|
|
38
|
+
agents: [
|
|
39
|
+
{ alias: 'claude-1', runtime: 'claude-code-cli', status: 'working', progress: 0.42 },
|
|
40
|
+
{ alias: 'codex-1', runtime: 'codex-sdk', status: 'working', progress: 0.18 },
|
|
41
|
+
{ alias: 'intern-1', runtime: 'claude-agent-sdk', status: 'idle' },
|
|
42
|
+
],
|
|
43
|
+
agent_count: 3,
|
|
44
|
+
status: 'online',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
hostname: 'mock-2',
|
|
48
|
+
ip: '10.0.0.11',
|
|
49
|
+
cpu_load_1min: 7.1,
|
|
50
|
+
cpu_cores: 4,
|
|
51
|
+
mem_used_gb: 14.5,
|
|
52
|
+
mem_total_gb: 16,
|
|
53
|
+
disk_used_gb: 460,
|
|
54
|
+
disk_total_gb: 500,
|
|
55
|
+
cpu_history: [80, 88, 92, 95, 96, 94, 93, 91, 90, 89],
|
|
56
|
+
mem_history: [85, 87, 89, 91, 90, 92, 93, 91, 90, 91],
|
|
57
|
+
agents: [
|
|
58
|
+
{ alias: 'minimax-busy', runtime: 'claude-code-cli', status: 'working', progress: 0.78 },
|
|
59
|
+
],
|
|
60
|
+
agent_count: 1,
|
|
61
|
+
status: 'online',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
hostname: 'mock-offline',
|
|
65
|
+
ip: '10.0.0.20',
|
|
66
|
+
cpu_load_1min: null,
|
|
67
|
+
cpu_cores: 0,
|
|
68
|
+
mem_used_gb: null,
|
|
69
|
+
mem_total_gb: null,
|
|
70
|
+
agent_count: 2,
|
|
71
|
+
status: 'offline',
|
|
72
|
+
note: 'last seen 12m ago',
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
await ctx.route('**/api/hub/status*', (r) => r.fulfill({ json: { sessions: [], hub: { networks: [] } } }));
|
|
79
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
80
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
81
|
+
|
|
82
|
+
const page = await ctx.newPage();
|
|
83
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
84
|
+
await page.waitForSelector('[data-server-card]', { timeout: 15000 });
|
|
85
|
+
await page.waitForTimeout(800);
|
|
86
|
+
|
|
87
|
+
// Crop to the drawer region only.
|
|
88
|
+
const box = await page.evaluate(() => {
|
|
89
|
+
const aside = document.querySelector('[aria-label="Servers panel"]');
|
|
90
|
+
if (!aside) return null;
|
|
91
|
+
const r = aside.getBoundingClientRect();
|
|
92
|
+
return { x: r.x - 8, y: r.y - 8, width: r.width + 16, height: Math.min(r.height + 16, 980) };
|
|
93
|
+
});
|
|
94
|
+
if (box && box.width > 100) {
|
|
95
|
+
await page.screenshot({ path: `${out}.png`, clip: box });
|
|
96
|
+
}
|
|
97
|
+
await page.screenshot({ path: `${out}-full.png`, fullPage: false });
|
|
98
|
+
console.log(`✅ wrote ${out}.png + ${out}-full.png`);
|
|
99
|
+
await browser.close();
|
|
@@ -44,10 +44,14 @@ await ctx.route('**/api/hub/status*', async (route) => {
|
|
|
44
44
|
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
45
45
|
});
|
|
46
46
|
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
47
|
+
// R319 fixture: both groups must be multi-tier so all tier pips
|
|
48
|
+
// render. Pre-R319 beta was 2 working (single-tier) and its pip
|
|
49
|
+
// rendered fine; post-R319 a tier pip is dropped when its count
|
|
50
|
+
// equals box.count, so beta needs idle to remain multi-tier here.
|
|
47
51
|
mk('alpha-1', 'working'),
|
|
48
52
|
mk('alpha-2', 'idle'),
|
|
49
53
|
mk('beta-1', 'working'),
|
|
50
|
-
mk('beta-2', '
|
|
54
|
+
mk('beta-2', 'idle'),
|
|
51
55
|
] } });
|
|
52
56
|
});
|
|
53
57
|
await ctx.route('**/api/hub/messages*', (r2) => r2.fulfill({ json: { messages: [] } }));
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/* Round 319 verification: prefix-group label drops the redundant
|
|
2
|
+
* tier pip when its count equals box.count (single-tier groups).
|
|
3
|
+
*
|
|
4
|
+
* Vincent telegram 5304 (2026-05-16) flagged real-data screenshot
|
|
5
|
+
* with `ai-insight · 6 6i`, `blueleap · 3 3i`, `P站 · 4 4i` as
|
|
6
|
+
* 比较难看 — the same number was visually doubled (total chip "·N"
|
|
7
|
+
* + tier pip "Ni") whenever a group was single-tier.
|
|
8
|
+
*
|
|
9
|
+
* R319: tier pip is now conditionally rendered with both
|
|
10
|
+
* `box.statuses.{tier} > 0` AND `box.statuses.{tier} !== box.count`
|
|
11
|
+
* so single-tier groups collapse to `· N` (no duplicated digit).
|
|
12
|
+
* Multi-tier groups keep all pips — the breakdown is genuinely
|
|
13
|
+
* additional info there.
|
|
14
|
+
*
|
|
15
|
+
* Fixture:
|
|
16
|
+
* - alpha-1..alpha-3: all working (single-tier, count=3, working=3)
|
|
17
|
+
* - beta-1, beta-2: working; beta-3, beta-4: idle (multi-tier)
|
|
18
|
+
*
|
|
19
|
+
* Contract:
|
|
20
|
+
* - alpha group: no [data-group-pip="working"] tspan (dropped because
|
|
21
|
+
* working === count)
|
|
22
|
+
* - alpha group: still has [data-group-label-count] with value=3
|
|
23
|
+
* (R229 total chip untouched)
|
|
24
|
+
* - beta group: has [data-group-pip="working"] AND [data-group-pip="idle"]
|
|
25
|
+
* (multi-tier — both pips render because neither equals count)
|
|
26
|
+
* - beta group: [data-group-label-count-value]=4 still rendered
|
|
27
|
+
* - R317 inactive Layout toggle gray-400 + R318 active font-medium
|
|
28
|
+
* + R294 pulse absent all preserved.
|
|
29
|
+
*/
|
|
30
|
+
import { chromium } from 'playwright';
|
|
31
|
+
import { readFileSync } from 'node:fs';
|
|
32
|
+
|
|
33
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
34
|
+
const browser = await chromium.launch({ headless: true });
|
|
35
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
36
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
37
|
+
await ctx.addInitScript(() => {
|
|
38
|
+
try {
|
|
39
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
40
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
41
|
+
localStorage.setItem('anet-topo-layout', 'grid');
|
|
42
|
+
} catch {}
|
|
43
|
+
});
|
|
44
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
45
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
46
|
+
const r = await route.fetch();
|
|
47
|
+
const b = await r.json();
|
|
48
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
49
|
+
const mk = (alias, status) => ({
|
|
50
|
+
alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
51
|
+
network_id: nid, project_dir: null,
|
|
52
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
53
|
+
});
|
|
54
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
55
|
+
// alpha — single-tier (all working, count=3)
|
|
56
|
+
mk('alpha-1', 'working'),
|
|
57
|
+
mk('alpha-2', 'working'),
|
|
58
|
+
mk('alpha-3', 'working'),
|
|
59
|
+
// beta — multi-tier (2 working + 2 idle, count=4)
|
|
60
|
+
mk('beta-1', 'working'),
|
|
61
|
+
mk('beta-2', 'working'),
|
|
62
|
+
mk('beta-3', 'idle'),
|
|
63
|
+
mk('beta-4', 'idle'),
|
|
64
|
+
] } });
|
|
65
|
+
});
|
|
66
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
67
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
68
|
+
|
|
69
|
+
const page = await ctx.newPage();
|
|
70
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
71
|
+
await page.waitForFunction(() => document.querySelectorAll('g[data-node]').length === 7, { timeout: 30000 });
|
|
72
|
+
await page.waitForSelector('[data-group-label-count]', { timeout: 10000, state: 'attached' });
|
|
73
|
+
await page.waitForTimeout(500);
|
|
74
|
+
|
|
75
|
+
const probe = await page.evaluate(() => {
|
|
76
|
+
// Find each group's <text data-group-label> wrapper and its pip
|
|
77
|
+
// children + count tspan.
|
|
78
|
+
const labels = Array.from(document.querySelectorAll('[data-group-label]'));
|
|
79
|
+
const byGroup = {};
|
|
80
|
+
for (const label of labels) {
|
|
81
|
+
const key = label.getAttribute('data-group-label');
|
|
82
|
+
const countTspan = label.querySelector('[data-group-label-count]');
|
|
83
|
+
const pips = Array.from(label.querySelectorAll('[data-group-pip]'));
|
|
84
|
+
byGroup[key] = {
|
|
85
|
+
hasCountTspan: !!countTspan,
|
|
86
|
+
countValue: countTspan?.getAttribute('data-group-label-count-value') ?? null,
|
|
87
|
+
pipTiers: pips.map(p => p.getAttribute('data-group-pip')),
|
|
88
|
+
pipTexts: pips.map(p => p.textContent),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
groups: byGroup,
|
|
93
|
+
r317InactiveLayoutCls:
|
|
94
|
+
document.querySelector('[data-topo-chrome-layout="grid"]')?.className ?? '',
|
|
95
|
+
r317ActiveLayoutCls:
|
|
96
|
+
document.querySelector('[data-topo-chrome-layout="ring"]')?.className ?? '',
|
|
97
|
+
pulseCount: document.querySelectorAll('[data-pulse-wrapper]').length,
|
|
98
|
+
};
|
|
99
|
+
});
|
|
100
|
+
await browser.close();
|
|
101
|
+
|
|
102
|
+
// R106 cluster algorithm preserves the trailing separator in the
|
|
103
|
+
// group key (e.g. alpha-1/2/3 → key 'alpha-'); match by prefix.
|
|
104
|
+
const alpha = probe.groups['alpha-'] || probe.groups['alpha'] || null;
|
|
105
|
+
const beta = probe.groups['beta-'] || probe.groups['beta'] || null;
|
|
106
|
+
|
|
107
|
+
const results = {
|
|
108
|
+
alpha_group_found: alpha !== null,
|
|
109
|
+
alpha_has_count_tspan: alpha?.hasCountTspan === true,
|
|
110
|
+
alpha_count_value_3: alpha?.countValue === '3',
|
|
111
|
+
alpha_no_working_pip: !alpha?.pipTiers.includes('working'),
|
|
112
|
+
alpha_no_pips_at_all: alpha?.pipTiers.length === 0,
|
|
113
|
+
beta_group_found: beta !== null,
|
|
114
|
+
beta_has_count_tspan: beta?.hasCountTspan === true,
|
|
115
|
+
beta_count_value_4: beta?.countValue === '4',
|
|
116
|
+
beta_has_working_pip: beta?.pipTiers.includes('working'),
|
|
117
|
+
beta_has_idle_pip: beta?.pipTiers.includes('idle'),
|
|
118
|
+
beta_no_offline_pip: !beta?.pipTiers.includes('offline'),
|
|
119
|
+
// R317 regression — Layout toggle inactive Grid is the layout-active
|
|
120
|
+
// here (we forced grid via initScript), so check that Ring is the
|
|
121
|
+
// INACTIVE one with text-gray-400. After R318, the ACTIVE button
|
|
122
|
+
// (grid) has font-medium.
|
|
123
|
+
r317_ring_inactive_gray_400: probe.r317ActiveLayoutCls.includes('text-gray-400'),
|
|
124
|
+
r318_grid_active_font_medium: probe.r317InactiveLayoutCls.includes('font-medium'),
|
|
125
|
+
r294_pulse_absent: probe.pulseCount === 0,
|
|
126
|
+
};
|
|
127
|
+
const ok = Object.values(results).every(Boolean);
|
|
128
|
+
console.log(`${ok ? '✅' : '❌'} group-pip single-tier drop:`, JSON.stringify(results),
|
|
129
|
+
'\n alpha:', alpha,
|
|
130
|
+
'\n beta:', beta);
|
|
131
|
+
process.exit(ok ? 0 : 1);
|
|
File without changes
|
/package/.next/static/{NhfYap25UUapTiHJmca96 → MBGamBXWPewuLnqj0_Ed-}/_clientMiddlewareManifest.js
RENAMED
|
File without changes
|
|
File without changes
|