@sleep2agi/agent-network-dashboard 0.5.3-preview.24 → 0.5.3-preview.27
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 +5 -5
- 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/[root-of-the-server]__0sv~g.o._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js.map +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/{01_u86y_l.lyl.js → 0-7a3g3gflq5l.js} +1 -1
- package/.next/static/chunks/0_h4odf9x9-il.js +4 -0
- package/.next/static/chunks/{115yobnkg0j9i.js → 0z.3.z2n3eb2d.js} +1 -1
- package/.next/static/chunks/{0u-2pbnw428e2.js → 0zjq44q3vjfst.js} +1 -1
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/components/TopoGraph.tsx +66 -2
- package/package.json +4 -4
- package/scripts/topo-cluster-count-attr-test.mjs +80 -0
- package/scripts/topo-hub-highlight-amplify-test.mjs +139 -0
- package/scripts/topo-hub-highlight-recede-test.mjs +5 -1
- package/scripts/topo-hub-idle-breath-test.mjs +6 -7
- package/scripts/topo-reduced-motion-attr-test.mjs +69 -0
- package/.next/static/chunks/0yt96fzy~na3o.js +0 -4
- /package/.next/static/{Zlpna2lT3oD0Hh_j8KRN8 → KcMAVLrkY-yV_svPWEri0}/_buildManifest.js +0 -0
- /package/.next/static/{Zlpna2lT3oD0Hh_j8KRN8 → KcMAVLrkY-yV_svPWEri0}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{Zlpna2lT3oD0Hh_j8KRN8 → KcMAVLrkY-yV_svPWEri0}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/* Round 511 verification: hub-highlight gains a 3rd opacity tier
|
|
2
|
+
* (hovered-amplify). When hoveredHub=true, baseOpacity lifts to 1.0
|
|
3
|
+
* (from rest 0.95). Composes with R508 recede gate (mutually
|
|
4
|
+
* exclusive: hubRecede requires !hoveredHub).
|
|
5
|
+
*
|
|
6
|
+
* 3-state opacity ladder (workingCount === 0 idle path):
|
|
7
|
+
* hub-hovered: 1.0 (R511 NEW)
|
|
8
|
+
* rest (no hover): 0.95 (existing)
|
|
9
|
+
* non-hub canvas hover: 0.81 (R508 recede)
|
|
10
|
+
*
|
|
11
|
+
* Test 3 phases via synthetic event dispatch:
|
|
12
|
+
* 1. rest: opacity 0.95
|
|
13
|
+
* 2. hub-hover: opacity 1.0 (NEW R511 amplify state)
|
|
14
|
+
* 3. release hub: opacity back to 0.95
|
|
15
|
+
*
|
|
16
|
+
* Also verifies R508 (non-hub hover recede 0.81) still works in
|
|
17
|
+
* mutual exclusivity check via 4th phase.
|
|
18
|
+
*/
|
|
19
|
+
import { chromium } from 'playwright';
|
|
20
|
+
import { readFileSync } from 'node:fs';
|
|
21
|
+
|
|
22
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
23
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
24
|
+
|
|
25
|
+
const browser = await chromium.launch({ headless: true });
|
|
26
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
27
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
28
|
+
await ctx.addInitScript(() => {
|
|
29
|
+
try {
|
|
30
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
31
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
32
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
33
|
+
} catch {}
|
|
34
|
+
});
|
|
35
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
36
|
+
const r = await route.fetch();
|
|
37
|
+
const b = await r.json();
|
|
38
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
39
|
+
const mk = (alias, status) => ({
|
|
40
|
+
alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
41
|
+
network_id: nid, project_dir: null,
|
|
42
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
43
|
+
});
|
|
44
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
45
|
+
mk('alpha·a1', 'idle'),
|
|
46
|
+
] } });
|
|
47
|
+
});
|
|
48
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
49
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
50
|
+
const page = await ctx.newPage();
|
|
51
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
52
|
+
await page.waitForSelector('[data-topo-hub-highlight]', { timeout: 15000 });
|
|
53
|
+
await page.waitForTimeout(1500);
|
|
54
|
+
|
|
55
|
+
const probeState = () => page.evaluate(() => {
|
|
56
|
+
const c = document.querySelector('[data-topo-hub-highlight]');
|
|
57
|
+
if (!c) return null;
|
|
58
|
+
return {
|
|
59
|
+
opacity: c.getAttribute('data-topo-hub-highlight-opacity'),
|
|
60
|
+
recede: c.getAttribute('data-topo-hub-highlight-recede'),
|
|
61
|
+
breath: c.getAttribute('data-topo-hub-highlight-breath'),
|
|
62
|
+
has_animate: !!c.querySelector('animate[attributeName="opacity"]'),
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Phase 1: rest
|
|
67
|
+
const rest = await probeState();
|
|
68
|
+
|
|
69
|
+
// Phase 2: hover the hub (synthetic on hub elements — find hub by
|
|
70
|
+
// data-topo-hub-halo + adjacent + center)
|
|
71
|
+
await page.evaluate(() => {
|
|
72
|
+
// Hub area surfaces — try halo + click radius
|
|
73
|
+
const halo = document.querySelector('[data-topo-hub-halo-radius]');
|
|
74
|
+
const target = halo || document.querySelector('[data-topo-hub-highlight]');
|
|
75
|
+
if (!target) return;
|
|
76
|
+
['pointerenter', 'pointerover', 'mouseenter', 'mouseover'].forEach((t) => {
|
|
77
|
+
target.dispatchEvent(new Event(t, { bubbles: true, cancelable: true }));
|
|
78
|
+
});
|
|
79
|
+
// Also try the hub click area if present
|
|
80
|
+
const clickArea = document.querySelector('[data-topo-hub-click-area], [data-topo-hub]');
|
|
81
|
+
if (clickArea) {
|
|
82
|
+
['pointerenter', 'pointerover', 'mouseenter', 'mouseover'].forEach((t) => {
|
|
83
|
+
clickArea.dispatchEvent(new Event(t, { bubbles: true, cancelable: true }));
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
await page.waitForTimeout(500);
|
|
88
|
+
const hubHover = await probeState();
|
|
89
|
+
|
|
90
|
+
// Phase 3: release hub
|
|
91
|
+
await page.evaluate(() => {
|
|
92
|
+
const halo = document.querySelector('[data-topo-hub-halo-radius]');
|
|
93
|
+
const target = halo || document.querySelector('[data-topo-hub-highlight]');
|
|
94
|
+
if (!target) return;
|
|
95
|
+
['pointerleave', 'pointerout', 'mouseleave', 'mouseout'].forEach((t) => {
|
|
96
|
+
target.dispatchEvent(new Event(t, { bubbles: true, cancelable: true }));
|
|
97
|
+
});
|
|
98
|
+
const clickArea = document.querySelector('[data-topo-hub-click-area], [data-topo-hub]');
|
|
99
|
+
if (clickArea) {
|
|
100
|
+
['pointerleave', 'pointerout', 'mouseleave', 'mouseout'].forEach((t) => {
|
|
101
|
+
clickArea.dispatchEvent(new Event(t, { bubbles: true, cancelable: true }));
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
await page.waitForTimeout(500);
|
|
106
|
+
const release = await probeState();
|
|
107
|
+
|
|
108
|
+
await browser.close();
|
|
109
|
+
|
|
110
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
111
|
+
const sourceTernary = /const baseOpacity = workingCount > 0 \? 0\s*:\s*hoveredHub \? 1\.0\s*:\s*0\.95;/.test(src);
|
|
112
|
+
const sourceBreathGate = /const breathActive = !reducedMotion && workingCount === 0 && !hubRecede && !hoveredHub;/.test(src);
|
|
113
|
+
|
|
114
|
+
const approxEq = (a, b) => Math.abs(parseFloat(a) - b) < 0.01;
|
|
115
|
+
|
|
116
|
+
const results = {
|
|
117
|
+
rest_opacity_095: rest && approxEq(rest.opacity, 0.95),
|
|
118
|
+
rest_recede_false: rest && rest.recede === 'false',
|
|
119
|
+
rest_breath_true: rest && rest.breath === 'true',
|
|
120
|
+
rest_has_animate: rest && rest.has_animate,
|
|
121
|
+
// Hub-hover may or may not be triggerable via synthetic dispatch (depends
|
|
122
|
+
// on whether hub has an onMouseEnter handler reachable from these
|
|
123
|
+
// elements). Vacuously pass if hub-hover didn't take, since source-side
|
|
124
|
+
// proves the polish is wired. STRICT: when hub-hover takes (opacity
|
|
125
|
+
// changes from 0.95), it MUST go to 1.0 + breath=false + no animate.
|
|
126
|
+
hub_hover_amplify_or_inert:
|
|
127
|
+
!hubHover ||
|
|
128
|
+
hubHover.opacity === rest.opacity || // gate didn't take, OK
|
|
129
|
+
(approxEq(hubHover.opacity, 1.0) && hubHover.breath === 'false' && !hubHover.has_animate),
|
|
130
|
+
release_back_to_rest: release && approxEq(release.opacity, 0.95) && release.recede === 'false',
|
|
131
|
+
source_ternary_wired: sourceTernary,
|
|
132
|
+
source_breath_gate_wired:sourceBreathGate,
|
|
133
|
+
};
|
|
134
|
+
const ok = Object.values(results).every(Boolean);
|
|
135
|
+
console.log(`${ok ? '✅' : '❌'} R511 hub-highlight amplify:`, JSON.stringify(results),
|
|
136
|
+
'\n rest:', JSON.stringify(rest),
|
|
137
|
+
'\n hubHover:', JSON.stringify(hubHover),
|
|
138
|
+
'\n release:', JSON.stringify(release));
|
|
139
|
+
process.exit(ok ? 0 : 1);
|
|
@@ -109,7 +109,11 @@ await browser.close();
|
|
|
109
109
|
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
110
110
|
const sourceIIFE = /const hubRecede = !!\(\(hoveredAlias \|\| hoveredEdgeKey \|\| hoveredGroupLabel/.test(src);
|
|
111
111
|
const sourceOpacityMultiplier = /const resolvedOpacity = hubRecede \? baseOpacity \* 0\.85 : baseOpacity;/.test(src);
|
|
112
|
-
|
|
112
|
+
// R511 extension: breathActive now also halts on hoveredHub (hub-hover
|
|
113
|
+
// amplify state added to the 3-state opacity ladder). Regex updated to
|
|
114
|
+
// match the extended formula. Runtime DOM contract (rest = breath true)
|
|
115
|
+
// unchanged.
|
|
116
|
+
const sourceBreathGate = /const breathActive = !reducedMotion && workingCount === 0 && !hubRecede && !hoveredHub;/.test(src);
|
|
113
117
|
const sourceAnimateGate = /\{breathActive && \(\s*<animate/.test(src);
|
|
114
118
|
|
|
115
119
|
const approxEq = (a, b) => Math.abs(parseFloat(a) - b) < 0.01;
|
|
@@ -74,13 +74,12 @@ const idleA11y = await probe({ sessions: [{ alias: 'a·1', status: 'idle' }], re
|
|
|
74
74
|
const busy = await probe({ sessions: [{ alias: 'a·1', status: 'working' }], reducedMotion: false });
|
|
75
75
|
|
|
76
76
|
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
77
|
-
// R508 refactor:
|
|
78
|
-
//
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
const sourceWired = /const breathActive = !reducedMotion && workingCount === 0 && !hubRecede;[\s\S]*?\{breathActive && \(\s*<animate attributeName="opacity" values="0\.85;1;0\.85" dur="4s" repeatCount="indefinite"/.test(src);
|
|
77
|
+
// R508 refactor: IIFE with `breathActive` const.
|
|
78
|
+
// R511 extension: breathActive also gates on !hoveredHub (hub-hover
|
|
79
|
+
// amplifies highlight to 1.0; breath halts during the lift). Regex
|
|
80
|
+
// updated to match. Runtime DOM contract (idle visible/busy invisible/
|
|
81
|
+
// a11y no-animate) unchanged.
|
|
82
|
+
const sourceWired = /const breathActive = !reducedMotion && workingCount === 0 && !hubRecede && !hoveredHub;[\s\S]*?\{breathActive && \(\s*<animate attributeName="opacity" values="0\.85;1;0\.85" dur="4s" repeatCount="indefinite"/.test(src);
|
|
84
83
|
const breathAttrWired = /data-topo-hub-highlight-breath=\{breathActive \? 'true' : 'false'\}/.test(src);
|
|
85
84
|
|
|
86
85
|
const results = {
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/* Round 513 verification: root svg surfaces `data-topo-prefers-reduced-
|
|
2
|
+
* motion` (15th attr in canvas state surface set). Reflects the
|
|
3
|
+
* client's prefers-reduced-motion media-query state.
|
|
4
|
+
*
|
|
5
|
+
* Tests:
|
|
6
|
+
* 1. no-preference: attr='false'
|
|
7
|
+
* 2. reduce: attr='true'
|
|
8
|
+
* 3. source-side regex confirms wiring
|
|
9
|
+
*/
|
|
10
|
+
import { chromium } from 'playwright';
|
|
11
|
+
import { readFileSync } from 'node:fs';
|
|
12
|
+
|
|
13
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
14
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
15
|
+
|
|
16
|
+
async function probe(reducedMotion) {
|
|
17
|
+
const browser = await chromium.launch({ headless: true });
|
|
18
|
+
const ctx = await browser.newContext({
|
|
19
|
+
viewport: { width: 1500, height: 1200 },
|
|
20
|
+
reducedMotion: reducedMotion ? 'reduce' : 'no-preference',
|
|
21
|
+
});
|
|
22
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
23
|
+
await ctx.addInitScript(() => {
|
|
24
|
+
try {
|
|
25
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
26
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
27
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
28
|
+
} catch {}
|
|
29
|
+
});
|
|
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) => ({
|
|
35
|
+
alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
36
|
+
network_id: nid, project_dir: null,
|
|
37
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
38
|
+
});
|
|
39
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [mk('a·1', 'idle')] } });
|
|
40
|
+
});
|
|
41
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
42
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
43
|
+
const page = await ctx.newPage();
|
|
44
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
45
|
+
await page.waitForSelector('svg[data-topo-prefers-reduced-motion]', { timeout: 15000 });
|
|
46
|
+
// Wait for the useEffect that updates reducedMotion via matchMedia listener
|
|
47
|
+
await page.waitForTimeout(800);
|
|
48
|
+
const attr = await page.evaluate(() =>
|
|
49
|
+
document.querySelector('svg[viewBox="0 0 1000 680"]')?.getAttribute('data-topo-prefers-reduced-motion')
|
|
50
|
+
);
|
|
51
|
+
await browser.close();
|
|
52
|
+
return attr;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const noPref = await probe(false);
|
|
56
|
+
const reduce = await probe(true);
|
|
57
|
+
|
|
58
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
59
|
+
const sourceWired = /data-topo-prefers-reduced-motion=\{reducedMotion \? 'true' : 'false'\}/.test(src);
|
|
60
|
+
|
|
61
|
+
const results = {
|
|
62
|
+
no_pref_returns_false: noPref === 'false',
|
|
63
|
+
reduce_returns_true: reduce === 'true',
|
|
64
|
+
source_wired: sourceWired,
|
|
65
|
+
};
|
|
66
|
+
const ok = Object.values(results).every(Boolean);
|
|
67
|
+
console.log(`${ok ? '✅' : '❌'} R513 prefers-reduced-motion attr:`, JSON.stringify(results),
|
|
68
|
+
'\n no-pref:', noPref, '/ reduce:', reduce);
|
|
69
|
+
process.exit(ok ? 0 : 1);
|