@sleep2agi/agent-network-dashboard 0.5.2-preview.9 → 0.5.3-preview.0

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.
Files changed (154) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +3 -3
  3. package/.next/diagnostics/route-bundle-stats.json +5 -5
  4. package/.next/fallback-build-manifest.json +3 -3
  5. package/.next/server/app/_global-error.html +1 -1
  6. package/.next/server/app/_global-error.rsc +1 -1
  7. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  8. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  12. package/.next/server/app/_not-found.html +1 -1
  13. package/.next/server/app/_not-found.rsc +1 -1
  14. package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  15. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  16. package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  17. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  18. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  19. package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  20. package/.next/server/app/admin.html +1 -1
  21. package/.next/server/app/admin.rsc +1 -1
  22. package/.next/server/app/admin.segments/_full.segment.rsc +1 -1
  23. package/.next/server/app/admin.segments/_head.segment.rsc +1 -1
  24. package/.next/server/app/admin.segments/_index.segment.rsc +1 -1
  25. package/.next/server/app/admin.segments/_tree.segment.rsc +1 -1
  26. package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +1 -1
  27. package/.next/server/app/admin.segments/admin.segment.rsc +1 -1
  28. package/.next/server/app/index.html +2 -2
  29. package/.next/server/app/index.rsc +2 -2
  30. package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  31. package/.next/server/app/index.segments/_full.segment.rsc +2 -2
  32. package/.next/server/app/index.segments/_head.segment.rsc +1 -1
  33. package/.next/server/app/index.segments/_index.segment.rsc +1 -1
  34. package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  35. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  36. package/.next/server/app/login.html +2 -2
  37. package/.next/server/app/login.rsc +2 -2
  38. package/.next/server/app/login.segments/_full.segment.rsc +2 -2
  39. package/.next/server/app/login.segments/_head.segment.rsc +1 -1
  40. package/.next/server/app/login.segments/_index.segment.rsc +1 -1
  41. package/.next/server/app/login.segments/_tree.segment.rsc +1 -1
  42. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
  43. package/.next/server/app/login.segments/login.segment.rsc +1 -1
  44. package/.next/server/app/logs.html +1 -1
  45. package/.next/server/app/logs.rsc +1 -1
  46. package/.next/server/app/logs.segments/_full.segment.rsc +1 -1
  47. package/.next/server/app/logs.segments/_head.segment.rsc +1 -1
  48. package/.next/server/app/logs.segments/_index.segment.rsc +1 -1
  49. package/.next/server/app/logs.segments/_tree.segment.rsc +1 -1
  50. package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +1 -1
  51. package/.next/server/app/logs.segments/logs.segment.rsc +1 -1
  52. package/.next/server/app/messages.html +1 -1
  53. package/.next/server/app/messages.rsc +1 -1
  54. package/.next/server/app/messages.segments/_full.segment.rsc +1 -1
  55. package/.next/server/app/messages.segments/_head.segment.rsc +1 -1
  56. package/.next/server/app/messages.segments/_index.segment.rsc +1 -1
  57. package/.next/server/app/messages.segments/_tree.segment.rsc +1 -1
  58. package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +1 -1
  59. package/.next/server/app/messages.segments/messages.segment.rsc +1 -1
  60. package/.next/server/app/node.html +1 -1
  61. package/.next/server/app/node.rsc +1 -1
  62. package/.next/server/app/node.segments/_full.segment.rsc +1 -1
  63. package/.next/server/app/node.segments/_head.segment.rsc +1 -1
  64. package/.next/server/app/node.segments/_index.segment.rsc +1 -1
  65. package/.next/server/app/node.segments/_tree.segment.rsc +1 -1
  66. package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +1 -1
  67. package/.next/server/app/node.segments/node.segment.rsc +1 -1
  68. package/.next/server/app/nodes.html +1 -1
  69. package/.next/server/app/nodes.rsc +1 -1
  70. package/.next/server/app/nodes.segments/_full.segment.rsc +1 -1
  71. package/.next/server/app/nodes.segments/_head.segment.rsc +1 -1
  72. package/.next/server/app/nodes.segments/_index.segment.rsc +1 -1
  73. package/.next/server/app/nodes.segments/_tree.segment.rsc +1 -1
  74. package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +1 -1
  75. package/.next/server/app/nodes.segments/nodes.segment.rsc +1 -1
  76. package/.next/server/app/page_client-reference-manifest.js +1 -1
  77. package/.next/server/app/server-logs.html +1 -1
  78. package/.next/server/app/server-logs.rsc +1 -1
  79. package/.next/server/app/server-logs.segments/_full.segment.rsc +1 -1
  80. package/.next/server/app/server-logs.segments/_head.segment.rsc +1 -1
  81. package/.next/server/app/server-logs.segments/_index.segment.rsc +1 -1
  82. package/.next/server/app/server-logs.segments/_tree.segment.rsc +1 -1
  83. package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +1 -1
  84. package/.next/server/app/server-logs.segments/server-logs.segment.rsc +1 -1
  85. package/.next/server/app/settings/networks.html +1 -1
  86. package/.next/server/app/settings/networks.rsc +1 -1
  87. package/.next/server/app/settings/networks.segments/_full.segment.rsc +1 -1
  88. package/.next/server/app/settings/networks.segments/_head.segment.rsc +1 -1
  89. package/.next/server/app/settings/networks.segments/_index.segment.rsc +1 -1
  90. package/.next/server/app/settings/networks.segments/_tree.segment.rsc +1 -1
  91. package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +1 -1
  92. package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +1 -1
  93. package/.next/server/app/settings/networks.segments/settings.segment.rsc +1 -1
  94. package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  95. package/.next/server/app/settings/tokens.html +1 -1
  96. package/.next/server/app/settings/tokens.rsc +1 -1
  97. package/.next/server/app/settings/tokens.segments/_full.segment.rsc +1 -1
  98. package/.next/server/app/settings/tokens.segments/_head.segment.rsc +1 -1
  99. package/.next/server/app/settings/tokens.segments/_index.segment.rsc +1 -1
  100. package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +1 -1
  101. package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +1 -1
  102. package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +1 -1
  103. package/.next/server/app/settings/tokens.segments/settings.segment.rsc +1 -1
  104. package/.next/server/app/settings.html +2 -2
  105. package/.next/server/app/settings.rsc +2 -2
  106. package/.next/server/app/settings.segments/_full.segment.rsc +2 -2
  107. package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  108. package/.next/server/app/settings.segments/_index.segment.rsc +1 -1
  109. package/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
  110. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +2 -2
  111. package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
  112. package/.next/server/app/tasks.html +1 -1
  113. package/.next/server/app/tasks.rsc +1 -1
  114. package/.next/server/app/tasks.segments/_full.segment.rsc +1 -1
  115. package/.next/server/app/tasks.segments/_head.segment.rsc +1 -1
  116. package/.next/server/app/tasks.segments/_index.segment.rsc +1 -1
  117. package/.next/server/app/tasks.segments/_tree.segment.rsc +1 -1
  118. package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +1 -1
  119. package/.next/server/app/tasks.segments/tasks.segment.rsc +1 -1
  120. package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js +1 -1
  121. package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js.map +1 -1
  122. package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js +3 -3
  123. package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js.map +1 -1
  124. package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js +1 -1
  125. package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js.map +1 -1
  126. package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js +1 -1
  127. package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js.map +1 -1
  128. package/.next/server/middleware-build-manifest.js +3 -3
  129. package/.next/server/pages/404.html +1 -1
  130. package/.next/server/pages/500.html +1 -1
  131. package/.next/static/chunks/{06zeyg88cp6h-.js → 06umjir3xxdkg.js} +1 -1
  132. package/.next/static/chunks/0lpjexuspbsws.js +4 -0
  133. package/.next/static/chunks/{167vt72829uc..js → 0udv401.-i0wx.js} +1 -1
  134. package/.next/static/chunks/{0anxuadtbfxck.js → 0xv4drghck_7d.js} +1 -1
  135. package/.next/trace +2 -2
  136. package/.next/trace-build +1 -1
  137. package/app/components/TopoGraph.tsx +266 -29
  138. package/package.json +1 -1
  139. package/screenshots/v0.10.4-150-orphans/after.png +0 -0
  140. package/scripts/p150-orphan-layout-screenshot.mjs +82 -0
  141. package/scripts/topo-edge-badge-hot-glow-test.mjs +101 -0
  142. package/scripts/topo-edge-particle-opacity-lift-test.mjs +109 -0
  143. package/scripts/topo-group-label-glow-test.mjs +104 -0
  144. package/scripts/topo-legend-panel-title-fw-test.mjs +95 -0
  145. package/scripts/topo-minimap-dot-lift-test.mjs +115 -0
  146. package/scripts/topo-minimap-zoom-glow-test.mjs +86 -0
  147. package/scripts/topo-orphan-band-test.mjs +106 -0
  148. package/scripts/topo-recent-panel-title-fw-test.mjs +106 -0
  149. package/scripts/topo-recent-row-ts-lift-test.mjs +97 -0
  150. package/scripts/topo-zoom-attr-test.mjs +74 -0
  151. package/.next/static/chunks/0nw~q-jv9.x7v.js +0 -4
  152. /package/.next/static/{BgTBIeF-pfDSGSCiCttKZ → Q7AfghHYz-a578rrDCx1S}/_buildManifest.js +0 -0
  153. /package/.next/static/{BgTBIeF-pfDSGSCiCttKZ → Q7AfghHYz-a578rrDCx1S}/_clientMiddlewareManifest.js +0 -0
  154. /package/.next/static/{BgTBIeF-pfDSGSCiCttKZ → Q7AfghHYz-a578rrDCx1S}/_ssgManifest.js +0 -0
@@ -0,0 +1,106 @@
1
+ /* Round 482 verification: recent-signal panel title "recent signal"
2
+ * gains fontWeight 700 → 800 on activeEdgeKey (any row hover or pin).
3
+ * Extends the "data tightens under attention" pattern to the panel-
4
+ * title scope alongside R345's existing letter-spacing tween on
5
+ * panel-chrome hover.
6
+ *
7
+ * Contract:
8
+ * - at rest (no row hover/pin): data-recent-panel-title-fw='700'
9
+ * + data-recent-panel-title-active='false'
10
+ * - click a recent-signal row hitbox to pin: title fw flips to '800'
11
+ * + active='true'
12
+ * - click again to unpin: title returns to fw='700'
13
+ * - source-file conditional wired
14
+ */
15
+ import { chromium } from 'playwright';
16
+ import { readFileSync } from 'node:fs';
17
+
18
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
19
+ const nowIso = () => new Date().toISOString();
20
+ const sessionFresh = new Date(Date.now() - 60 * 1000).toISOString();
21
+
22
+ const browser = await chromium.launch({ headless: true });
23
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
24
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
25
+ await ctx.addInitScript(() => {
26
+ try {
27
+ localStorage.setItem('anet-theme', 'cyber');
28
+ localStorage.setItem('anet-topo-layout', 'ring');
29
+ sessionStorage.setItem('anet_v3_auth', '1');
30
+ } catch {}
31
+ });
32
+ await ctx.route('**/api/hub/status*', async (route) => {
33
+ const r = await route.fetch();
34
+ const b = await r.json();
35
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
36
+ const mk = (alias, status) => ({
37
+ alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
38
+ network_id: nid, project_dir: null,
39
+ created_at: sessionFresh, updated_at: sessionFresh, last_seen_at: sessionFresh,
40
+ });
41
+ await route.fulfill({ response: r, json: { ...b, sessions: [
42
+ mk('a·1', 'working'), mk('a·2', 'idle'), mk('b·1', 'working'),
43
+ ] } });
44
+ });
45
+ await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: {
46
+ messages: [
47
+ { id: 'm1', from_alias: 'a·1', to_alias: 'a·2', content: 'ping', created_at: nowIso() },
48
+ { id: 'm2', from_alias: 'b·1', to_alias: 'a·1', content: 'pong', created_at: nowIso() },
49
+ ],
50
+ } }));
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: 'networkidle' });
55
+ await page.waitForSelector('[data-recent-panel-title]', { timeout: 15000 });
56
+ await page.waitForTimeout(800);
57
+
58
+ const readTitle = () => page.evaluate(() => {
59
+ const t = document.querySelector('[data-recent-panel-title]');
60
+ if (!t) return null;
61
+ return {
62
+ fw: t.getAttribute('data-recent-panel-title-fw'),
63
+ active: t.getAttribute('data-recent-panel-title-active'),
64
+ liveFW: t.getAttribute('font-weight'),
65
+ };
66
+ });
67
+
68
+ const rest = await readTitle();
69
+ // Click first recent-row to pin
70
+ await page.click('[data-recent-row]');
71
+ await page.waitForTimeout(400);
72
+ const pinned = await readTitle();
73
+ // Click again to unpin (toggles pinnedEdgeKey).
74
+ // After the click, move pointer off the row — otherwise
75
+ // hoveredEdgeKey still holds even after pin clears
76
+ // (activeEdgeKey = hoveredEdgeKey ?? pinnedEdgeKey).
77
+ await page.click('[data-recent-row]');
78
+ await page.mouse.move(50, 50); // off the recent-signal panel
79
+ await page.waitForTimeout(400);
80
+ const restAgain = await readTitle();
81
+
82
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
83
+ const sourceFwConditional = /fontWeight=\{activeEdgeKey \? '800' : '700'\}/.test(src);
84
+ const sourceFwTween = /font-weight 200ms ease-out/.test(src);
85
+ const sourceDataAttr = /data-recent-panel-title-fw=\{activeEdgeKey \?/.test(src);
86
+
87
+ await browser.close();
88
+
89
+ const restIs700 = rest?.fw === '700' && rest?.active === 'false' && rest?.liveFW === '700';
90
+ const pinIs800 = pinned?.fw === '800' && pinned?.active === 'true' && pinned?.liveFW === '800';
91
+ const restAgainIs700 = restAgain?.fw === '700' && restAgain?.active === 'false' && restAgain?.liveFW === '700';
92
+
93
+ const results = {
94
+ rest_is_700_inactive: restIs700,
95
+ pin_flips_to_800_active: pinIs800,
96
+ unpin_back_to_700: restAgainIs700,
97
+ source_fw_conditional: sourceFwConditional,
98
+ source_fw_tween: sourceFwTween,
99
+ source_data_attr: sourceDataAttr,
100
+ };
101
+ const ok = Object.values(results).every(Boolean);
102
+ console.log(`${ok ? '✅' : '❌'} recent-panel title fw 700→800:`, JSON.stringify(results),
103
+ '\n rest:', JSON.stringify(rest),
104
+ '\n pinned:', JSON.stringify(pinned),
105
+ '\n rest again:', JSON.stringify(restAgain));
106
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,97 @@
1
+ /* Round 484 verification: recent-row timestamp opacity lifts to
2
+ * 1.0 when isRowHovered || isRowPinned, overriding the R191
3
+ * freshness-decay tsAlpha. Inspection state shows full freshness
4
+ * regardless of decay.
5
+ *
6
+ * Contract:
7
+ * - stale row (5min ago): tsAlpha ≈ 0.30, ts-lifted='false',
8
+ * live opacity matches tsAlpha
9
+ * - click stale row to pin: ts-lifted='true', live opacity='1'
10
+ * - source-file conditional wired
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 sessionFresh = new Date(Date.now() - 60 * 1000).toISOString();
17
+ const fiveMinAgo = new Date(Date.now() - 5 * 60 * 1000).toISOString();
18
+
19
+ const browser = await chromium.launch({ headless: true });
20
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
21
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
22
+ await ctx.addInitScript(() => {
23
+ try {
24
+ localStorage.setItem('anet-theme', 'cyber');
25
+ localStorage.setItem('anet-topo-layout', 'ring');
26
+ sessionStorage.setItem('anet_v3_auth', '1');
27
+ } catch {}
28
+ });
29
+ await ctx.route('**/api/hub/status*', async (route) => {
30
+ const r = await route.fetch();
31
+ const b = await r.json();
32
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
33
+ const mk = (alias, status) => ({
34
+ alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
35
+ network_id: nid, project_dir: null,
36
+ created_at: sessionFresh, updated_at: sessionFresh, last_seen_at: sessionFresh,
37
+ });
38
+ await route.fulfill({ response: r, json: { ...b, sessions: [
39
+ mk('a·1', 'working'), mk('a·2', 'idle'),
40
+ ] } });
41
+ });
42
+ // One stale message — its freshness alpha decays to ~0.30 at 5min
43
+ await ctx.route('**/api/hub/messages*', (route) => route.fulfill({ json: {
44
+ messages: [
45
+ { id: 'm1', from_alias: 'a·1', to_alias: 'a·2', content: 'old', created_at: fiveMinAgo },
46
+ ],
47
+ } }));
48
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
49
+
50
+ const page = await ctx.newPage();
51
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
52
+ await page.waitForSelector('[data-recent-row-ts]', { timeout: 15000 });
53
+ await page.waitForTimeout(500);
54
+
55
+ const readTs = () => page.evaluate(() => {
56
+ const t = document.querySelector('[data-recent-row-ts]');
57
+ if (!t) return null;
58
+ return {
59
+ alpha: parseFloat(t.getAttribute('data-recent-row-ts-alpha') || '0'),
60
+ lifted: t.getAttribute('data-recent-row-ts-lifted'),
61
+ opacity: t.getAttribute('opacity'),
62
+ };
63
+ });
64
+
65
+ const rest = await readTs();
66
+ // Click recent-row to pin
67
+ await page.click('[data-recent-row]');
68
+ await page.waitForTimeout(400);
69
+ const pinned = await readTs();
70
+
71
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
72
+ const sourceLiftConditional = /opacity=\{\(isRowHovered \|\| isRowPinned\) \? 1 : tsAlpha\}/.test(src);
73
+ const sourceLiftedAttr = /data-recent-row-ts-lifted=/.test(src);
74
+
75
+ await browser.close();
76
+
77
+ // Rest: alpha < 0.7 (stale) + lifted='false' + opacity matches alpha
78
+ const restValid = rest?.lifted === 'false' && rest?.alpha < 0.7 &&
79
+ Math.abs(parseFloat(rest?.opacity || '0') - rest?.alpha) < 0.01;
80
+ // Pinned: lifted='true' + opacity=1 (overrides stale alpha)
81
+ const pinValid = pinned?.lifted === 'true' && pinned?.opacity === '1';
82
+
83
+ const results = {
84
+ ts_present: !!rest,
85
+ rest_lifted_false: rest?.lifted === 'false',
86
+ rest_alpha_stale: rest?.alpha < 0.7,
87
+ rest_opacity_matches_alpha: restValid,
88
+ pin_lifted_true: pinned?.lifted === 'true',
89
+ pin_opacity_is_1: pinned?.opacity === '1',
90
+ source_lift_conditional: sourceLiftConditional,
91
+ source_lifted_attr: sourceLiftedAttr,
92
+ };
93
+ const ok = Object.values(results).every(Boolean);
94
+ console.log(`${ok ? '✅' : '❌'} recent-row ts opacity lift on active:`, JSON.stringify(results),
95
+ '\n rest:', JSON.stringify(rest),
96
+ '\n pinned:', JSON.stringify(pinned));
97
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,74 @@
1
+ /* Round 487 verification: root svg surfaces `data-topo-zoom`
2
+ * numeric attr reflecting current view.zoom. Extends the R469/
3
+ * R471 root-svg state surface set to 10 attrs.
4
+ *
5
+ * Contract:
6
+ * - default zoom (1.0): data-topo-zoom='1.00'
7
+ * - localStorage-seed zoom=1.6: data-topo-zoom='1.60'
8
+ * - source-file conditional wired
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(viewZoom) {
17
+ const browser = await chromium.launch({ headless: true });
18
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
19
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
20
+ await ctx.addInitScript((arg) => {
21
+ try {
22
+ localStorage.setItem('anet-theme', 'cyber');
23
+ localStorage.setItem('anet-topo-layout', 'ring');
24
+ if (arg.zoom !== 1.0) {
25
+ localStorage.setItem('anet-topo-view', JSON.stringify({ zoom: arg.zoom, x: 0, y: 0 }));
26
+ } else {
27
+ localStorage.removeItem('anet-topo-view');
28
+ }
29
+ sessionStorage.setItem('anet_v3_auth', '1');
30
+ } catch {}
31
+ }, { zoom: viewZoom });
32
+ await ctx.route('**/api/hub/status*', async (route) => {
33
+ const r = await route.fetch();
34
+ const b = await r.json();
35
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
36
+ const mk = (alias, status) => ({
37
+ alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
38
+ network_id: nid, project_dir: null,
39
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
40
+ });
41
+ await route.fulfill({ response: r, json: { ...b, sessions: [
42
+ mk('a·1', 'working'),
43
+ ] } });
44
+ });
45
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
46
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
47
+ const page = await ctx.newPage();
48
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
49
+ await page.waitForSelector('svg[data-topo-zoom]', { timeout: 15000 });
50
+ await page.waitForTimeout(2800); // wait for localStorage-restore useEffect
51
+ const attr = await page.evaluate(() =>
52
+ document.querySelector('svg[viewBox="0 0 1000 680"]')?.getAttribute('data-topo-zoom')
53
+ );
54
+ await browser.close();
55
+ return attr;
56
+ }
57
+
58
+ const defaultZoom = await probe(1.0);
59
+ const seededZoom = await probe(1.6);
60
+
61
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
62
+ const sourceAttr = /data-topo-zoom=\{view\.zoom\.toFixed\(2\)\}/.test(src);
63
+
64
+ const results = {
65
+ default_zoom_attr_present: defaultZoom !== null,
66
+ default_zoom_value: defaultZoom === '1.00',
67
+ seeded_zoom_attr_present: seededZoom !== null,
68
+ seeded_zoom_value: seededZoom === '1.60',
69
+ source_attr_wired: sourceAttr,
70
+ };
71
+ const ok = Object.values(results).every(Boolean);
72
+ console.log(`${ok ? '✅' : '❌'} svg data-topo-zoom attr:`, JSON.stringify(results),
73
+ '\n default:', defaultZoom, '/ seeded:', seededZoom);
74
+ process.exit(ok ? 0 : 1);