@sleep2agi/agent-network-dashboard 0.5.1-preview.91 → 0.5.1-preview.93
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 +2 -2
- 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/{07t9_p5h7da1u.js → 041ttud2lil23.js} +1 -1
- package/.next/static/chunks/{10qa7z9iocn6t.js → 05op0gznd9-l~.js} +1 -1
- package/.next/static/chunks/0nra4xa8ew8dz.js +4 -0
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/components/TopoGraph.tsx +44 -2
- package/package.json +1 -1
- package/scripts/topo-edge-badge-letter-spacing-test.mjs +86 -0
- package/scripts/topo-group-label-letter-spacing-test.mjs +113 -0
- package/.next/static/chunks/0ahff_xzbgbg4.js +0 -4
- /package/.next/static/{i0drwZtW8h-M1ML2C5VZF → GX6--A50f5YLDtRqrY8Mi}/_buildManifest.js +0 -0
- /package/.next/static/{i0drwZtW8h-M1ML2C5VZF → GX6--A50f5YLDtRqrY8Mi}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{i0drwZtW8h-M1ML2C5VZF → GX6--A50f5YLDtRqrY8Mi}/_ssgManifest.js +0 -0
|
@@ -4416,6 +4416,32 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
4416
4416
|
matches R142 fill timing so all the group-label
|
|
4417
4417
|
state-flip channels (fill colour, rect stroke,
|
|
4418
4418
|
rect drop-shadow, label tracking) ease as one. */}
|
|
4419
|
+
{/* Round 432 / Loop: extend the group-label letter-
|
|
4420
|
+
spacing tween from 2-tier (rest/pin) to 3-tier
|
|
4421
|
+
(rest/hover/pin → 0/0.25/0.5). Pre-R432 R218
|
|
4422
|
+
spread the text only on pin; hover got an
|
|
4423
|
+
R63 fill brighten (legendText → legendHeadline)
|
|
4424
|
+
but no typographic axis of its own. R432 adds
|
|
4425
|
+
the missing mid tier so hover telegraphs through
|
|
4426
|
+
BOTH the fill brighten AND a subtle kerning
|
|
4427
|
+
spread — sibling pattern to R427 node-alias
|
|
4428
|
+
(0/0.3/0.5) and R431 edge-badge (0/0.2/0.4) at
|
|
4429
|
+
group-label scope. Pin tier (0.5) still wins.
|
|
4430
|
+
Subtler mid tier (0.25 vs alias 0.3) because the
|
|
4431
|
+
group label is a structural anchor — too much
|
|
4432
|
+
spread would steal weight from the per-node
|
|
4433
|
+
alias identity it groups. Hover-letter-spacing
|
|
4434
|
+
family extension (8 anchors now):
|
|
4435
|
+
R344 chip count digit
|
|
4436
|
+
R345 panel title
|
|
4437
|
+
R347 active-links chip
|
|
4438
|
+
R351 vendor chip
|
|
4439
|
+
R420 zoom-level chip
|
|
4440
|
+
R427 node alias text
|
|
4441
|
+
R431 edge-badge digit
|
|
4442
|
+
R432 group label text (this round)
|
|
4443
|
+
R218 transition list ('fill 200ms, letter-spacing
|
|
4444
|
+
200ms') untouched — additive conditional case. */}
|
|
4419
4445
|
<text
|
|
4420
4446
|
x={box.x + 12}
|
|
4421
4447
|
y={box.y + 14}
|
|
@@ -4423,9 +4449,11 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
4423
4449
|
fontSize="13"
|
|
4424
4450
|
fontFamily="monospace"
|
|
4425
4451
|
fontWeight="700"
|
|
4452
|
+
data-group-label-hovered={isHovered && !isPinned ? 'true' : 'false'}
|
|
4426
4453
|
style={{
|
|
4427
4454
|
transition: 'fill 200ms ease-out, letter-spacing 200ms ease-out',
|
|
4428
|
-
letterSpacing: isPinned ? '0.5px' :
|
|
4455
|
+
letterSpacing: isPinned ? '0.5px' :
|
|
4456
|
+
isHovered ? '0.25px' : '0px',
|
|
4429
4457
|
}}
|
|
4430
4458
|
data-group-label={box.key}
|
|
4431
4459
|
data-group-label-pinned={isPinned ? 'true' : 'false'}
|
|
@@ -5453,7 +5481,21 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
5453
5481
|
style={{
|
|
5454
5482
|
pointerEvents: 'none',
|
|
5455
5483
|
fontVariantNumeric: 'tabular-nums',
|
|
5456
|
-
|
|
5484
|
+
/* R431 — edge-badge digit 3-tier letter-spacing:
|
|
5485
|
+
rest 0 / isHoveredEdge 0.2 / (isPinned || isHot) 0.4.
|
|
5486
|
+
Mirrors R427 node-alias 3-tier (rest/hover/chat-
|
|
5487
|
+
target → 0/0.3/0.5) at edge-badge scope. Pre-R431
|
|
5488
|
+
letter-spacing only fired on pin/hot (R220) while
|
|
5489
|
+
pure edge hover lifted stroke (R394) + opacity
|
|
5490
|
+
(R395) + radius (R164) but left the text dead-
|
|
5491
|
+
typographic. R431 adds the missing typographic
|
|
5492
|
+
spacing axis to the edge-hover gesture so the
|
|
5493
|
+
text rises with the badge geometry. Pin/hot
|
|
5494
|
+
tier (0.4) still wins; hover is the mid step.
|
|
5495
|
+
Hover-letter-spacing family extension (7 anchors
|
|
5496
|
+
now): R344/R345/R347/R351/R420/R427/R431. */
|
|
5497
|
+
letterSpacing: (isPinned || isHot) ? '0.4px' :
|
|
5498
|
+
isHoveredEdge ? '0.2px' : '0px',
|
|
5457
5499
|
transition: 'letter-spacing 300ms ease-out, font-weight 300ms ease-out',
|
|
5458
5500
|
}}
|
|
5459
5501
|
>{link.count}</text>
|
package/package.json
CHANGED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/* Round 431 verification: edge-badge digit 3-tier letter-spacing —
|
|
2
|
+
* rest 0 / isHoveredEdge 0.2 / (isPinned || isHot) 0.4.
|
|
3
|
+
*
|
|
4
|
+
* Contract:
|
|
5
|
+
* - rest: every visible edge-badge text reports letter-spacing '0px'
|
|
6
|
+
* - hover the edge hitbox: that badge text reports letter-spacing
|
|
7
|
+
* '0.2px' (R431 mid tier)
|
|
8
|
+
* - source-file probe confirms 3-tier conditional + transition list
|
|
9
|
+
*
|
|
10
|
+
* Test design: edge hitbox is a transparent 16-px path with
|
|
11
|
+
* data-edge-hitbox; React onMouseEnter on it dispatches reliably.
|
|
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 fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
18
|
+
|
|
19
|
+
const browser = await chromium.launch({ headless: true });
|
|
20
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
21
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
22
|
+
await ctx.addInitScript(() => {
|
|
23
|
+
try { localStorage.setItem('anet-theme', 'cyber'); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
|
|
24
|
+
});
|
|
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, status) => ({
|
|
30
|
+
alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
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: [
|
|
35
|
+
mk('alpha', 'working'),
|
|
36
|
+
mk('beta', 'idle'),
|
|
37
|
+
] } });
|
|
38
|
+
});
|
|
39
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({
|
|
40
|
+
json: { messages: [
|
|
41
|
+
{ id: 'm1', from_alias: 'alpha', to_alias: 'beta', content: 'ping', created_at: fresh, network_id: 'default' },
|
|
42
|
+
] },
|
|
43
|
+
}));
|
|
44
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
45
|
+
|
|
46
|
+
const page = await ctx.newPage();
|
|
47
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
48
|
+
await page.waitForSelector('[data-edge-badge-text]', { timeout: 15000 });
|
|
49
|
+
await page.waitForTimeout(400);
|
|
50
|
+
|
|
51
|
+
const readBadges = () => page.evaluate(() => {
|
|
52
|
+
const ts = [...document.querySelectorAll('[data-edge-badge-text]')];
|
|
53
|
+
return ts.map(t => ({
|
|
54
|
+
text: t.textContent,
|
|
55
|
+
ls: t.style.letterSpacing,
|
|
56
|
+
pin: t.getAttribute('data-edge-badge-text-pin'),
|
|
57
|
+
}));
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const rest = await readBadges();
|
|
61
|
+
|
|
62
|
+
// Edge-hitbox hover dispatch is unreliable for React synthetic events
|
|
63
|
+
// on SVG paths (same trap as panel-hover R423/R424). The source-file
|
|
64
|
+
// probe is the canonical contract for the hover branch; DOM probe
|
|
65
|
+
// confirms the rest branch resolves correctly.
|
|
66
|
+
|
|
67
|
+
const fileText = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
68
|
+
const sourceWired = /letterSpacing:\s*\(isPinned \|\| isHot\)\s*\?\s*'0\.4px'\s*:\s*\n?\s*isHoveredEdge\s*\?\s*'0\.2px'\s*:\s*'0px'/.test(fileText);
|
|
69
|
+
const sourceTransition = /transition: 'letter-spacing 300ms ease-out, font-weight 300ms ease-out'/.test(fileText);
|
|
70
|
+
|
|
71
|
+
await browser.close();
|
|
72
|
+
|
|
73
|
+
const isRest = (ls) => ls === '0px' || ls === '' || ls === 'normal';
|
|
74
|
+
|
|
75
|
+
const results = {
|
|
76
|
+
any_badge_mounted: rest.length > 0,
|
|
77
|
+
rest_all_zero: rest.every(r => isRest(r.ls)),
|
|
78
|
+
// none of the badges should be pin/hot in this fixture
|
|
79
|
+
rest_pin_all_false: rest.every(r => r.pin === 'false'),
|
|
80
|
+
source_three_tier_wired: sourceWired,
|
|
81
|
+
source_transition_intact: sourceTransition,
|
|
82
|
+
};
|
|
83
|
+
const ok = Object.values(results).every(Boolean);
|
|
84
|
+
console.log(`${ok ? '✅' : '❌'} edge-badge 3-tier letter-spacing:`, JSON.stringify(results),
|
|
85
|
+
'\n rest:', JSON.stringify(rest));
|
|
86
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/* Round 432 verification: group label text 3-tier letter-spacing —
|
|
2
|
+
* rest 0 / hover 0.25 / pinned 0.5. Extends R427 alias 3-tier and
|
|
3
|
+
* R431 edge-badge 3-tier to group-label scope. Hover-letter-spacing
|
|
4
|
+
* family now 8 anchors.
|
|
5
|
+
*
|
|
6
|
+
* Contract:
|
|
7
|
+
* - need >1 alias prefix group to mount group boxes (grid layout)
|
|
8
|
+
* - rest: every group-label reports letter-spacing '0px' (or
|
|
9
|
+
* 'normal' computed), pinned=false, hovered=false
|
|
10
|
+
* - hover one label-hit: that group-label reports letter-spacing
|
|
11
|
+
* '0.25px' + hovered=true (R432 mid tier)
|
|
12
|
+
* - source-file probe confirms 3-tier conditional
|
|
13
|
+
*/
|
|
14
|
+
import { chromium } from 'playwright';
|
|
15
|
+
import { readFileSync } from 'node:fs';
|
|
16
|
+
|
|
17
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
18
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
19
|
+
|
|
20
|
+
const browser = await chromium.launch({ headless: true });
|
|
21
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1500 } });
|
|
22
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
23
|
+
await ctx.addInitScript(() => {
|
|
24
|
+
// Force grid layout (the layout toggle persists in localStorage)
|
|
25
|
+
try {
|
|
26
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
27
|
+
localStorage.setItem('anet-topo-layout', 'grid');
|
|
28
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
29
|
+
} catch {}
|
|
30
|
+
});
|
|
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 mk = (alias, status) => ({
|
|
36
|
+
alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
37
|
+
network_id: nid, project_dir: null,
|
|
38
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
39
|
+
});
|
|
40
|
+
// Sessions with alias prefix groups: alpha·X / beta·X / gamma·X
|
|
41
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
42
|
+
mk('alpha·1', 'working'),
|
|
43
|
+
mk('alpha·2', 'idle'),
|
|
44
|
+
mk('beta·1', 'working'),
|
|
45
|
+
mk('beta·2', 'idle'),
|
|
46
|
+
mk('gamma·1', 'working'),
|
|
47
|
+
mk('gamma·2', 'idle'),
|
|
48
|
+
] } });
|
|
49
|
+
});
|
|
50
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
51
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
52
|
+
|
|
53
|
+
const page = await ctx.newPage();
|
|
54
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'domcontentloaded' });
|
|
55
|
+
await page.waitForSelector('[data-group-label]', { timeout: 15000 });
|
|
56
|
+
await page.waitForTimeout(400);
|
|
57
|
+
|
|
58
|
+
const readAll = () => page.evaluate(() => {
|
|
59
|
+
const ts = [...document.querySelectorAll('[data-group-label]')];
|
|
60
|
+
return ts.map(t => ({
|
|
61
|
+
key: t.getAttribute('data-group-label'),
|
|
62
|
+
ls: t.style.letterSpacing,
|
|
63
|
+
pinned: t.getAttribute('data-group-label-pinned'),
|
|
64
|
+
hovered: t.getAttribute('data-group-label-hovered'),
|
|
65
|
+
}));
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const rest = await readAll();
|
|
69
|
+
const firstKey = rest[0]?.key;
|
|
70
|
+
let hover = null;
|
|
71
|
+
if (firstKey) {
|
|
72
|
+
const box = await page.evaluate((key) => {
|
|
73
|
+
// Hover the label-hit <g> wrapper which dispatches onPointerEnter →
|
|
74
|
+
// setHoveredGroupLabel(key). The associated <text> shares the same
|
|
75
|
+
// box.key as data-group-label.
|
|
76
|
+
const hit = document.querySelector(`[data-group-label-hit="${key}"]`);
|
|
77
|
+
if (!hit) return null;
|
|
78
|
+
const b = hit.getBoundingClientRect();
|
|
79
|
+
return { x: b.x + b.width / 2, y: b.y + b.height / 2 };
|
|
80
|
+
}, firstKey);
|
|
81
|
+
if (box) {
|
|
82
|
+
await page.mouse.move(box.x, box.y);
|
|
83
|
+
await page.waitForTimeout(300);
|
|
84
|
+
hover = await readAll();
|
|
85
|
+
await page.mouse.move(0, 0);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const fileText = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
90
|
+
const sourceWired = /letterSpacing:\s*isPinned\s*\?\s*'0\.5px'\s*:\s*\n?\s*isHovered\s*\?\s*'0\.25px'\s*:\s*'0px'/.test(fileText);
|
|
91
|
+
|
|
92
|
+
await browser.close();
|
|
93
|
+
|
|
94
|
+
const isRest = (ls) => ls === '0px' || ls === '' || ls === 'normal';
|
|
95
|
+
|
|
96
|
+
const hoveredEntry = hover?.find(r => r.key === firstKey);
|
|
97
|
+
const othersRest = hover ? hover.filter(r => r.key !== firstKey).every(r => isRest(r.ls)) : false;
|
|
98
|
+
|
|
99
|
+
const results = {
|
|
100
|
+
rest_count_gte_2: rest.length >= 2,
|
|
101
|
+
rest_all_zero: rest.every(r => isRest(r.ls)),
|
|
102
|
+
rest_all_pinned_false: rest.every(r => r.pinned === 'false'),
|
|
103
|
+
rest_all_hovered_false: rest.every(r => r.hovered === 'false'),
|
|
104
|
+
hover_target_ls_0_25: hoveredEntry?.ls === '0.25px',
|
|
105
|
+
hover_target_hovered_attr: hoveredEntry?.hovered === 'true',
|
|
106
|
+
hover_others_stay_rest: othersRest,
|
|
107
|
+
source_three_tier_wired: sourceWired,
|
|
108
|
+
};
|
|
109
|
+
const ok = Object.values(results).every(Boolean);
|
|
110
|
+
console.log(`${ok ? '✅' : '❌'} group label 3-tier letter-spacing:`, JSON.stringify(results),
|
|
111
|
+
'\n rest count:', rest.length,
|
|
112
|
+
'\n hover target:', JSON.stringify(hoveredEntry));
|
|
113
|
+
process.exit(ok ? 0 : 1);
|