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

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 (177) 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 +32 -32
  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/page_client-reference-manifest.js +1 -1
  13. package/.next/server/app/_not-found.html +2 -2
  14. package/.next/server/app/_not-found.rsc +12 -12
  15. package/.next/server/app/_not-found.segments/_full.segment.rsc +12 -12
  16. package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  17. package/.next/server/app/_not-found.segments/_index.segment.rsc +7 -7
  18. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  19. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  20. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  21. package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
  22. package/.next/server/app/admin.html +2 -2
  23. package/.next/server/app/admin.rsc +14 -14
  24. package/.next/server/app/admin.segments/_full.segment.rsc +14 -14
  25. package/.next/server/app/admin.segments/_head.segment.rsc +4 -4
  26. package/.next/server/app/admin.segments/_index.segment.rsc +7 -7
  27. package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
  28. package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +4 -4
  29. package/.next/server/app/admin.segments/admin.segment.rsc +3 -3
  30. package/.next/server/app/index.html +2 -2
  31. package/.next/server/app/index.rsc +14 -14
  32. package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
  33. package/.next/server/app/index.segments/_full.segment.rsc +14 -14
  34. package/.next/server/app/index.segments/_head.segment.rsc +4 -4
  35. package/.next/server/app/index.segments/_index.segment.rsc +7 -7
  36. package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  37. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  38. package/.next/server/app/login.html +2 -2
  39. package/.next/server/app/login.rsc +14 -14
  40. package/.next/server/app/login.segments/_full.segment.rsc +14 -14
  41. package/.next/server/app/login.segments/_head.segment.rsc +4 -4
  42. package/.next/server/app/login.segments/_index.segment.rsc +7 -7
  43. package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  44. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
  45. package/.next/server/app/login.segments/login.segment.rsc +3 -3
  46. package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
  47. package/.next/server/app/logs.html +2 -2
  48. package/.next/server/app/logs.rsc +14 -14
  49. package/.next/server/app/logs.segments/_full.segment.rsc +14 -14
  50. package/.next/server/app/logs.segments/_head.segment.rsc +4 -4
  51. package/.next/server/app/logs.segments/_index.segment.rsc +7 -7
  52. package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
  53. package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +4 -4
  54. package/.next/server/app/logs.segments/logs.segment.rsc +3 -3
  55. package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
  56. package/.next/server/app/messages.html +2 -2
  57. package/.next/server/app/messages.rsc +14 -14
  58. package/.next/server/app/messages.segments/_full.segment.rsc +14 -14
  59. package/.next/server/app/messages.segments/_head.segment.rsc +4 -4
  60. package/.next/server/app/messages.segments/_index.segment.rsc +7 -7
  61. package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
  62. package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +4 -4
  63. package/.next/server/app/messages.segments/messages.segment.rsc +3 -3
  64. package/.next/server/app/node/page_client-reference-manifest.js +1 -1
  65. package/.next/server/app/node.html +2 -2
  66. package/.next/server/app/node.rsc +14 -14
  67. package/.next/server/app/node.segments/_full.segment.rsc +14 -14
  68. package/.next/server/app/node.segments/_head.segment.rsc +4 -4
  69. package/.next/server/app/node.segments/_index.segment.rsc +7 -7
  70. package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
  71. package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +4 -4
  72. package/.next/server/app/node.segments/node.segment.rsc +3 -3
  73. package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
  74. package/.next/server/app/nodes.html +2 -2
  75. package/.next/server/app/nodes.rsc +14 -14
  76. package/.next/server/app/nodes.segments/_full.segment.rsc +14 -14
  77. package/.next/server/app/nodes.segments/_head.segment.rsc +4 -4
  78. package/.next/server/app/nodes.segments/_index.segment.rsc +7 -7
  79. package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
  80. package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +4 -4
  81. package/.next/server/app/nodes.segments/nodes.segment.rsc +3 -3
  82. package/.next/server/app/page_client-reference-manifest.js +1 -1
  83. package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
  84. package/.next/server/app/server-logs.html +2 -2
  85. package/.next/server/app/server-logs.rsc +14 -14
  86. package/.next/server/app/server-logs.segments/_full.segment.rsc +14 -14
  87. package/.next/server/app/server-logs.segments/_head.segment.rsc +4 -4
  88. package/.next/server/app/server-logs.segments/_index.segment.rsc +7 -7
  89. package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
  90. package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +4 -4
  91. package/.next/server/app/server-logs.segments/server-logs.segment.rsc +3 -3
  92. package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
  93. package/.next/server/app/settings/networks.html +2 -2
  94. package/.next/server/app/settings/networks.rsc +14 -14
  95. package/.next/server/app/settings/networks.segments/_full.segment.rsc +14 -14
  96. package/.next/server/app/settings/networks.segments/_head.segment.rsc +4 -4
  97. package/.next/server/app/settings/networks.segments/_index.segment.rsc +7 -7
  98. package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
  99. package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +4 -4
  100. package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +3 -3
  101. package/.next/server/app/settings/networks.segments/settings.segment.rsc +3 -3
  102. package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  103. package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
  104. package/.next/server/app/settings/tokens.html +2 -2
  105. package/.next/server/app/settings/tokens.rsc +14 -14
  106. package/.next/server/app/settings/tokens.segments/_full.segment.rsc +14 -14
  107. package/.next/server/app/settings/tokens.segments/_head.segment.rsc +4 -4
  108. package/.next/server/app/settings/tokens.segments/_index.segment.rsc +7 -7
  109. package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
  110. package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +4 -4
  111. package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +3 -3
  112. package/.next/server/app/settings/tokens.segments/settings.segment.rsc +3 -3
  113. package/.next/server/app/settings.html +2 -2
  114. package/.next/server/app/settings.rsc +14 -14
  115. package/.next/server/app/settings.segments/_full.segment.rsc +14 -14
  116. package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
  117. package/.next/server/app/settings.segments/_index.segment.rsc +7 -7
  118. package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  119. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
  120. package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
  121. package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
  122. package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
  123. package/.next/server/app/tasks.html +2 -2
  124. package/.next/server/app/tasks.rsc +14 -14
  125. package/.next/server/app/tasks.segments/_full.segment.rsc +14 -14
  126. package/.next/server/app/tasks.segments/_head.segment.rsc +4 -4
  127. package/.next/server/app/tasks.segments/_index.segment.rsc +7 -7
  128. package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
  129. package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +4 -4
  130. package/.next/server/app/tasks.segments/tasks.segment.rsc +3 -3
  131. package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js +1 -1
  132. package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js.map +1 -1
  133. package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js +3 -3
  134. package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js.map +1 -1
  135. package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js +1 -1
  136. package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js.map +1 -1
  137. package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js +1 -1
  138. package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js.map +1 -1
  139. package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js +1 -1
  140. package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0mvyi-4._.js.map +1 -1
  141. package/.next/server/middleware-build-manifest.js +3 -3
  142. package/.next/server/pages/404.html +2 -2
  143. package/.next/server/pages/500.html +1 -1
  144. package/.next/static/chunks/0fuba20p57-zo.js +1 -0
  145. package/.next/static/chunks/{0hndl9yzpqajt.css → 0m.1mvl~t.avc.css} +1 -1
  146. package/.next/static/chunks/{00d~vl~k~7f75.js → 0ph1in3421~o-.js} +1 -1
  147. package/.next/static/chunks/{03a4--7ncekmk.js → 0v4-5tng.uh.7.js} +2 -2
  148. package/.next/static/chunks/10cj-86disers.js +1 -0
  149. package/.next/static/chunks/158h2g7f-nxbt.js +4 -0
  150. package/.next/trace +2 -2
  151. package/.next/trace-build +1 -1
  152. package/app/components/ServersDrawer.tsx +16 -3
  153. package/app/components/TopoGraph.tsx +442 -21
  154. package/app/globals.css +23 -0
  155. package/package.json +4 -4
  156. package/scripts/p157-servers-copy-test.mjs +95 -0
  157. package/scripts/topo-alias-glow-test.mjs +121 -0
  158. package/scripts/topo-avatar-brightness-test.mjs +116 -0
  159. package/scripts/topo-fleet-density-tier-test.mjs +84 -0
  160. package/scripts/topo-freshness-chip-fade-test.mjs +105 -0
  161. package/scripts/topo-hub-highlight-amplify-test.mjs +139 -0
  162. package/scripts/topo-hub-highlight-fill-transition-test.mjs +84 -0
  163. package/scripts/topo-hub-highlight-recede-test.mjs +144 -0
  164. package/scripts/topo-hub-highlight-theme-fill-test.mjs +83 -0
  165. package/scripts/topo-hub-idle-breath-test.mjs +109 -0
  166. package/scripts/topo-hub-recede-test.mjs +124 -0
  167. package/scripts/topo-orphan-box-dash-test.mjs +89 -0
  168. package/scripts/topo-orphan-fill-opacity-test.mjs +91 -0
  169. package/scripts/topo-orphan-label-italic-test.mjs +90 -0
  170. package/scripts/topo-pinned-aspect-test.mjs +89 -0
  171. package/scripts/topo-recent-hot-pulse-test.mjs +102 -0
  172. package/.next/static/chunks/0jn4lbsj97vfl.js +0 -1
  173. package/.next/static/chunks/0rz3-6.xs78~d.js +0 -1
  174. package/.next/static/chunks/0~~xbw42y4m3v.js +0 -4
  175. /package/.next/static/{nbpD7Lhttq59fvvIw9gTX → tQ1EtcEiS7ikgAoAyZWm7}/_buildManifest.js +0 -0
  176. /package/.next/static/{nbpD7Lhttq59fvvIw9gTX → tQ1EtcEiS7ikgAoAyZWm7}/_clientMiddlewareManifest.js +0 -0
  177. /package/.next/static/{nbpD7Lhttq59fvvIw9gTX → tQ1EtcEiS7ikgAoAyZWm7}/_ssgManifest.js +0 -0
@@ -0,0 +1,124 @@
1
+ /* Round 507 verification: hub-center workingCount digit fades to
2
+ * opacity 0.85 when ANY non-hub canvas surface is hovered. Lifts back
3
+ * to 1.0 on un-hover or when hovering the hub itself.
4
+ *
5
+ * Test phases:
6
+ * 1. rest (no hover) — opacity 1, data-topo-hub-recede='false'
7
+ * 2. node hover (synthetic pointerenter on g[data-node]) —
8
+ * opacity 0.85, data-topo-hub-recede='true'
9
+ * 3. release hover — back to opacity 1, recede='false'
10
+ *
11
+ * Source-side regex confirms gate + style + attr wired.
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: 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: fresh, updated_at: fresh, last_seen_at: fresh,
37
+ });
38
+ await route.fulfill({ response: r, json: { ...b, sessions: [
39
+ mk('alpha·a1', 'working'),
40
+ mk('alpha·a2', 'idle'),
41
+ ] } });
42
+ });
43
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
44
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
45
+ const page = await ctx.newPage();
46
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
47
+ await page.waitForSelector('[data-topo-hub-working-count-glow]', { timeout: 15000 });
48
+ await page.waitForTimeout(1500);
49
+
50
+ // Phase 1: rest state
51
+ const rest = await page.evaluate(() => {
52
+ const el = document.querySelector('[data-topo-hub-working-count-glow]');
53
+ if (!el) return null;
54
+ return {
55
+ recede_attr: el.getAttribute('data-topo-hub-recede'),
56
+ opacity: window.getComputedStyle(el).opacity,
57
+ };
58
+ });
59
+
60
+ // Phase 2: hover a node via R488 banked synthetic dispatch
61
+ await page.evaluate(() => {
62
+ const g = document.querySelector('g[data-node]');
63
+ if (!g) return;
64
+ const target = g.querySelector('circle, image, rect') || g;
65
+ ['pointerenter', 'pointerover', 'mouseenter', 'mouseover'].forEach((t) => {
66
+ target.dispatchEvent(new Event(t, { bubbles: true, cancelable: true }));
67
+ });
68
+ });
69
+ await page.waitForTimeout(500);
70
+ const hover = await page.evaluate(() => {
71
+ const el = document.querySelector('[data-topo-hub-working-count-glow]');
72
+ if (!el) return null;
73
+ return {
74
+ recede_attr: el.getAttribute('data-topo-hub-recede'),
75
+ opacity: window.getComputedStyle(el).opacity,
76
+ };
77
+ });
78
+
79
+ // Phase 3: release hover
80
+ await page.evaluate(() => {
81
+ const g = document.querySelector('g[data-node]');
82
+ if (!g) return;
83
+ const target = g.querySelector('circle, image, rect') || g;
84
+ ['pointerleave', 'pointerout', 'mouseleave', 'mouseout'].forEach((t) => {
85
+ target.dispatchEvent(new Event(t, { bubbles: true, cancelable: true }));
86
+ });
87
+ });
88
+ await page.waitForTimeout(500);
89
+ const release = await page.evaluate(() => {
90
+ const el = document.querySelector('[data-topo-hub-working-count-glow]');
91
+ if (!el) return null;
92
+ return {
93
+ recede_attr: el.getAttribute('data-topo-hub-recede'),
94
+ opacity: window.getComputedStyle(el).opacity,
95
+ };
96
+ });
97
+
98
+ await browser.close();
99
+
100
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
101
+ const sourceGateWired = /\(hoveredAlias \|\| hoveredEdgeKey \|\| hoveredGroupLabel \|\|\s*hoveredStatus \|\| hoveredVendor\) && !hoveredHub/.test(src);
102
+ const sourceOpacity = /opacity: \(hoveredAlias \|\| hoveredEdgeKey \|\| hoveredGroupLabel/.test(src);
103
+ const sourceAttr = /data-topo-hub-recede=\{/.test(src);
104
+
105
+ // computed opacity comes back as a number-string ('1', '0.85')
106
+ const approxEq = (a, b) => Math.abs(parseFloat(a) - b) < 0.01;
107
+
108
+ const results = {
109
+ rest_recede_false: rest && rest.recede_attr === 'false',
110
+ rest_opacity_1: rest && approxEq(rest.opacity, 1),
111
+ hover_recede_true: hover && hover.recede_attr === 'true',
112
+ hover_opacity_85: hover && approxEq(hover.opacity, 0.85),
113
+ release_recede_false: release && release.recede_attr === 'false',
114
+ release_opacity_1: release && approxEq(release.opacity, 1),
115
+ source_gate_wired: sourceGateWired,
116
+ source_opacity_wired: sourceOpacity,
117
+ source_attr_wired: sourceAttr,
118
+ };
119
+ const ok = Object.values(results).every(Boolean);
120
+ console.log(`${ok ? '✅' : '❌'} R507 hub-recede:`, JSON.stringify(results),
121
+ '\n rest:', JSON.stringify(rest),
122
+ '\n hover:', JSON.stringify(hover),
123
+ '\n release:', JSON.stringify(release));
124
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,89 @@
1
+ /* Round 503 verification: orphan band rect (data-group-box-orphan="true")
2
+ * uses strokeDasharray='3 6' at rest, while prefix-group bands keep
3
+ * '6 6'. Pinned/hovered orphan still gets 'none' (solid stroke) — the
4
+ * differentiation lives ONLY in the rest state.
5
+ *
6
+ * Category-differentiation family 2nd anchor:
7
+ * R499 orphan label fontStyle: italic (1st anchor, R499)
8
+ * R503 orphan rect '3 6' dash pattern (2nd anchor, this round)
9
+ *
10
+ * Fixture: 2 prefix groups (alpha×3, beta×2) + 3 orphans (zeta/omega/lonely)
11
+ * — same shape as R499 test. Drives #150 orphan-band creation with
12
+ * prefix groups for differential assertion.
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: 1200 } });
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', 'grid');
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: [
40
+ mk('alpha·1', 'working'), mk('alpha·2', 'idle'), mk('alpha·3', 'idle'),
41
+ mk('beta·1', 'working'), mk('beta·2', 'idle'),
42
+ mk('zeta', 'idle'),
43
+ mk('omega', 'idle'),
44
+ mk('lonely', 'idle'),
45
+ ] } });
46
+ });
47
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
48
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
49
+ const page = await ctx.newPage();
50
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
51
+ await page.waitForSelector('[data-group-box-orphan]', { timeout: 15000 });
52
+ await page.waitForTimeout(1500);
53
+
54
+ const rects = await page.evaluate(() => {
55
+ const els = Array.from(document.querySelectorAll('[data-group-box-orphan]'));
56
+ return els.map((el) => {
57
+ const cs = window.getComputedStyle(el);
58
+ return {
59
+ orphan_attr: el.getAttribute('data-group-box-orphan'),
60
+ dasharray: el.getAttribute('stroke-dasharray') || cs.strokeDasharray || '',
61
+ };
62
+ });
63
+ });
64
+
65
+ await browser.close();
66
+
67
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
68
+ const sourceTernary = /\(isPinned \|\| isHovered\) \? 'none' :\s*box\.isOrphan \? '3 6' : '6 6'/.test(src);
69
+ const sourceAttr = /data-group-box-orphan=\{box\.isOrphan \? 'true' : 'false'\}/.test(src);
70
+
71
+ const orphanRect = rects.find((r) => r.orphan_attr === 'true');
72
+ const prefixRects = rects.filter((r) => r.orphan_attr === 'false');
73
+
74
+ // Computed strokeDasharray comes back as 'px-suffixed' or raw — normalize
75
+ const normalize = (s) => (s || '').replace(/px/g, '').replace(/,\s*/g, ' ').trim();
76
+
77
+ const results = {
78
+ rects_found: rects.length >= 2,
79
+ orphan_rect_present: !!orphanRect,
80
+ orphan_dash_3_6: orphanRect && (normalize(orphanRect.dasharray) === '3 6' || normalize(orphanRect.dasharray) === '3 6'),
81
+ prefix_rects_present: prefixRects.length >= 1,
82
+ prefix_dash_6_6: prefixRects.length > 0 && prefixRects.every((r) => normalize(r.dasharray) === '6 6'),
83
+ source_ternary_wired: sourceTernary,
84
+ source_attr_wired: sourceAttr,
85
+ };
86
+ const ok = Object.values(results).every(Boolean);
87
+ console.log(`${ok ? '✅' : '❌'} R503 orphan box dash:`, JSON.stringify(results),
88
+ '\n rects:', JSON.stringify(rects));
89
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,91 @@
1
+ /* Round 506 verification: orphan band rect rest-state fillOpacity
2
+ * drops slightly below prefix-group rest (0.025/0.045 → 0.015/0.028).
3
+ * Category-differentiation family 3rd anchor.
4
+ *
5
+ * R499 orphan label fontStyle italic (1st anchor)
6
+ * R503 orphan rect '3 6' dasharray (2nd anchor)
7
+ * R506 orphan rect lower fillOpacity (3rd anchor)
8
+ *
9
+ * Pin and hover branches UNCHANGED (full inspection affordance).
10
+ * Differentiation lives ONLY in the rest state.
11
+ *
12
+ * Fixture: 2 prefix groups (alpha×3 + beta×2) + 3 orphans (zeta/omega/
13
+ * lonely) — same shape as R499/R503 tests for cross-round consistency.
14
+ * Cyber theme drives the 0.045 (prefix) vs 0.028 (orphan) comparison.
15
+ */
16
+ import { chromium } from 'playwright';
17
+ import { readFileSync } from 'node:fs';
18
+
19
+ const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
20
+ const fresh = 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', 'grid');
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: fresh, updated_at: fresh, last_seen_at: fresh,
40
+ });
41
+ await route.fulfill({ response: r, json: { ...b, sessions: [
42
+ mk('alpha·1', 'working'), mk('alpha·2', 'idle'), mk('alpha·3', 'idle'),
43
+ mk('beta·1', 'working'), mk('beta·2', 'idle'),
44
+ mk('zeta', 'idle'),
45
+ mk('omega', 'idle'),
46
+ mk('lonely', 'idle'),
47
+ ] } });
48
+ });
49
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
50
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
51
+ const page = await ctx.newPage();
52
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
53
+ await page.waitForSelector('[data-group-box-orphan]', { timeout: 15000 });
54
+ await page.waitForTimeout(1500);
55
+
56
+ const rects = await page.evaluate(() => {
57
+ const els = Array.from(document.querySelectorAll('[data-group-box-orphan]'));
58
+ return els.map((el) => ({
59
+ orphan_attr: el.getAttribute('data-group-box-orphan'),
60
+ fill_opacity_attr: el.getAttribute('data-group-box-fill-opacity'),
61
+ fill_opacity_dom: el.getAttribute('fill-opacity'),
62
+ }));
63
+ });
64
+
65
+ await browser.close();
66
+
67
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
68
+ const sourceTernary = /box\.isOrphan \? \(isLight \? 0\.015 : 0\.028\)\s*:\s*\(isLight \? 0\.025 : 0\.045\)/.test(src);
69
+ const sourceAttr = /data-group-box-fill-opacity=\{[\s\S]*?box\.isOrphan \? \(isLight \? 0\.015 : 0\.028\)/.test(src);
70
+
71
+ const orphanRect = rects.find((r) => r.orphan_attr === 'true');
72
+ const prefixRects = rects.filter((r) => r.orphan_attr === 'false');
73
+
74
+ // Cyber theme: prefix = 0.045, orphan = 0.028
75
+ const approxEq = (a, b) => Math.abs(parseFloat(a) - b) < 1e-9;
76
+
77
+ const results = {
78
+ rects_found: rects.length >= 2,
79
+ orphan_rect_present: !!orphanRect,
80
+ orphan_fill_028: orphanRect && approxEq(orphanRect.fill_opacity_attr, 0.028),
81
+ orphan_dom_fill_028: orphanRect && approxEq(orphanRect.fill_opacity_dom, 0.028),
82
+ prefix_rects_present: prefixRects.length >= 1,
83
+ prefix_fill_045: prefixRects.length > 0 && prefixRects.every((r) => approxEq(r.fill_opacity_attr, 0.045)),
84
+ prefix_dom_fill_045: prefixRects.length > 0 && prefixRects.every((r) => approxEq(r.fill_opacity_dom, 0.045)),
85
+ source_ternary_wired: sourceTernary,
86
+ source_attr_wired: sourceAttr,
87
+ };
88
+ const ok = Object.values(results).every(Boolean);
89
+ console.log(`${ok ? '✅' : '❌'} R506 orphan fill-opacity:`, JSON.stringify(results),
90
+ '\n rects:', JSON.stringify(rects));
91
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,90 @@
1
+ /* Round 499 verification: orphan band "其他" label gets fontStyle:
2
+ * italic, while prefix-group labels (alpha/beta/etc.) stay roman.
3
+ * Pure typography differentiation — no opacity / weight / fill / bbox
4
+ * change. data-group-label-orphan attr surfaces the gate for tests.
5
+ *
6
+ * Fixture: 2 prefix groups (alpha×3, beta×2) + 3 orphans (zeta/omega/
7
+ * lonely) — forces #150 orphan-band creation with at least 1 orphan
8
+ * and ≥ 1 prefix-group for differential assertion.
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
+ const browser = await chromium.launch({ headless: true });
17
+ const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
18
+ await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
19
+ await ctx.addInitScript(() => {
20
+ try {
21
+ localStorage.setItem('anet-theme', 'cyber');
22
+ // grid layout required for groupBoxes to render
23
+ localStorage.setItem('anet-topo-layout', 'grid');
24
+ sessionStorage.setItem('anet_v3_auth', '1');
25
+ } catch {}
26
+ });
27
+ await ctx.route('**/api/hub/status*', async (route) => {
28
+ const r = await route.fetch();
29
+ const b = await r.json();
30
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
31
+ const mk = (alias, status) => ({
32
+ alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
33
+ network_id: nid, project_dir: null,
34
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
35
+ });
36
+ await route.fulfill({ response: r, json: { ...b, sessions: [
37
+ mk('alpha·1', 'working'), mk('alpha·2', 'idle'), mk('alpha·3', 'idle'),
38
+ mk('beta·1', 'working'), mk('beta·2', 'idle'),
39
+ mk('zeta', 'idle'),
40
+ mk('omega', 'idle'),
41
+ mk('lonely', 'idle'),
42
+ ] } });
43
+ });
44
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
45
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
46
+ const page = await ctx.newPage();
47
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
48
+ await page.waitForSelector('[data-group-label]', { timeout: 15000 });
49
+ await page.waitForTimeout(1500);
50
+
51
+ const labels = await page.evaluate(() => {
52
+ const els = Array.from(document.querySelectorAll('[data-group-label]'));
53
+ return els.map((el) => {
54
+ const cs = window.getComputedStyle(el);
55
+ return {
56
+ key: el.getAttribute('data-group-label'),
57
+ orphan_attr:el.getAttribute('data-group-label-orphan'),
58
+ font_style: cs.fontStyle,
59
+ };
60
+ });
61
+ });
62
+
63
+ await browser.close();
64
+
65
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
66
+ const sourceTypeWired = /groupBoxes: \[\] as \{ key: string; isOrphan\?: boolean;/.test(src);
67
+ const sourceFieldWired = /isOrphan: !!band\.isOrphan,/.test(src);
68
+ const sourceStyleWired = /fontStyle: box\.isOrphan \? 'italic' : undefined/.test(src);
69
+ const sourceAttrWired = /data-group-label-orphan=\{box\.isOrphan \? 'true' : 'false'\}/.test(src);
70
+
71
+ const orphanLabel = labels.find((l) => l.key === '其他');
72
+ const prefixLabels = labels.filter((l) => l.key !== '其他' && l.key !== '');
73
+
74
+ const results = {
75
+ found_labels: labels.length >= 2,
76
+ orphan_label_present: !!orphanLabel,
77
+ orphan_attr_true: orphanLabel && orphanLabel.orphan_attr === 'true',
78
+ orphan_font_italic: orphanLabel && orphanLabel.font_style === 'italic',
79
+ prefix_labels_present: prefixLabels.length >= 1,
80
+ prefix_attrs_false: prefixLabels.length > 0 && prefixLabels.every((p) => p.orphan_attr === 'false'),
81
+ prefix_font_normal: prefixLabels.length > 0 && prefixLabels.every((p) => p.font_style !== 'italic'),
82
+ source_type_wired: sourceTypeWired,
83
+ source_field_wired: sourceFieldWired,
84
+ source_style_wired: sourceStyleWired,
85
+ source_attr_wired: sourceAttrWired,
86
+ };
87
+ const ok = Object.values(results).every(Boolean);
88
+ console.log(`${ok ? '✅' : '❌'} R499 orphan label italic:`, JSON.stringify(results),
89
+ '\n labels:', JSON.stringify(labels));
90
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,89 @@
1
+ /* Round 504 verification: root svg surfaces `data-topo-pinned-aspect`
2
+ * categorical attribute. Sibling to R488's `data-topo-hovered-alias`
3
+ * (hover identity); R504 is the pin axis identity. Reflects WHICH
4
+ * pin state is active — paired with R467's any-pinned boolean.
5
+ *
6
+ * Tier values:
7
+ * none, status, group, vendor, edge, multi
8
+ *
9
+ * Test scenarios — seed pins via localStorage to reach each tier
10
+ * deterministically.
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 fresh = new Date(Date.now() - 60 * 1000).toISOString();
17
+
18
+ async function probe({ pins }) {
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((p) => {
23
+ try {
24
+ localStorage.setItem('anet-theme', 'cyber');
25
+ localStorage.setItem('anet-topo-layout', 'ring');
26
+ sessionStorage.setItem('anet_v3_auth', '1');
27
+ // Pins persist via sessionStorage (not localStorage) — verified
28
+ // by grep of TopoGraph.tsx useState initializers at lines
29
+ // 1033/1148/1187. pinnedEdgeKey starts null (no persistence;
30
+ // edge pin only reachable via click, skipped in this test).
31
+ if (p.status) sessionStorage.setItem('anet-topo-pinned-status', p.status);
32
+ if (p.group) sessionStorage.setItem('anet-topo-pinned-group', p.group);
33
+ if (p.vendor) sessionStorage.setItem('anet-topo-pinned-vendor', p.vendor);
34
+ } catch {}
35
+ }, pins);
36
+ await ctx.route('**/api/hub/status*', async (route) => {
37
+ const r = await route.fetch();
38
+ const b = await r.json();
39
+ const nid = (b.sessions || [])[0]?.network_id || 'default';
40
+ const mk = (alias, status) => ({
41
+ alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
42
+ network_id: nid, project_dir: null,
43
+ created_at: fresh, updated_at: fresh, last_seen_at: fresh,
44
+ });
45
+ await route.fulfill({ response: r, json: { ...b, sessions: [
46
+ mk('alpha·1', 'working'),
47
+ mk('alpha·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
+ const page = await ctx.newPage();
53
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
54
+ await page.waitForSelector('svg[data-topo-pinned-aspect]', { timeout: 15000 });
55
+ await page.waitForTimeout(2800); // settle for localStorage-restore useEffect
56
+ const aspect = await page.evaluate(() => {
57
+ return document.querySelector('svg[viewBox="0 0 1000 680"]')?.getAttribute('data-topo-pinned-aspect');
58
+ });
59
+ await browser.close();
60
+ return aspect;
61
+ }
62
+
63
+ const none = await probe({ pins: {} });
64
+ const status = await probe({ pins: { status: 'working' } });
65
+ // Note: 'alpha' for group depends on actual alias-prefix derivation; valid
66
+ // because we seeded alpha·1 + alpha·2 (both have prefix 'alpha·')
67
+ const group = await probe({ pins: { group: 'alpha·' } });
68
+ // vendor uses initial letter — Anthropic = 'A' (from vendorIdentity.ts line 69)
69
+ // claude-opus-4 model resolves to Anthropic vendor; stale-purge keeps 'A' valid
70
+ const vendor = await probe({ pins: { vendor: 'A' } });
71
+ // edge needs from→to format; skip — edge pin keys are complex
72
+ // Multi: status + group together
73
+ const multi = await probe({ pins: { status: 'working', group: 'alpha·' } });
74
+
75
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
76
+ const sourceWired = /data-topo-pinned-aspect=\{\(\(\) => \{[\s\S]*?aspects\.push\('status'\)[\s\S]*?aspects\.push\('group'\)[\s\S]*?aspects\.push\('vendor'\)[\s\S]*?aspects\.push\('edge'\)/.test(src);
77
+
78
+ const results = {
79
+ none_resolves: none === 'none',
80
+ status_resolves: status === 'status',
81
+ group_resolves: group === 'group',
82
+ vendor_resolves: vendor === 'vendor',
83
+ multi_resolves: multi === 'multi',
84
+ source_wired: sourceWired,
85
+ };
86
+ const ok = Object.values(results).every(Boolean);
87
+ console.log(`${ok ? '✅' : '❌'} R504 pinned-aspect:`, JSON.stringify(results),
88
+ '\n raw:', { none, status, group, vendor, multi });
89
+ process.exit(ok ? 0 : 1);
@@ -0,0 +1,102 @@
1
+ /* Round 498 verification: recent-signal row hot-count tspan gains a
2
+ * 3s opacity pulse (0.85↔1.0) when count >= 10 (isHot && !reducedMotion).
3
+ * Adds the 呼吸感 theme's second anchor after R497 hub idle-breath —
4
+ * gentle motion attracts glance to high-traffic lanes.
5
+ *
6
+ * Test scenarios — needs >= 10 messages between two aliases to trigger
7
+ * the hot threshold AND the recent-signal panel to render. Uses a
8
+ * messages fixture with 10 messages from alpha·a1 → alpha·a2.
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: [
40
+ mk('alpha·a1', 'working'),
41
+ mk('alpha·a2', 'idle'),
42
+ ] } });
43
+ });
44
+ // 12 messages → count >= 10 → isHot true
45
+ const msgs = Array.from({ length: 12 }, (_, i) => ({
46
+ id: `m${i}`, from_alias: 'alpha·a1', to_alias: 'alpha·a2',
47
+ content: 'test', created_at: fresh,
48
+ }));
49
+ await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: msgs } }));
50
+ await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
51
+ const page = await ctx.newPage();
52
+ await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
53
+ await page.waitForTimeout(2000);
54
+
55
+ const result = await page.evaluate(() => {
56
+ const tspans = Array.from(document.querySelectorAll('[data-recent-row-count]'));
57
+ const hotTspan = tspans.find((t) => t.getAttribute('data-recent-row-count-hot') === 'true');
58
+ if (!hotTspan) return { found: false, totalTspans: tspans.length };
59
+ const cs = window.getComputedStyle(hotTspan);
60
+ return {
61
+ found: true,
62
+ class_has_pulse: /anet-recent-hot-pulse/.test(hotTspan.getAttribute('class') || ''),
63
+ pulse_attr: hotTspan.getAttribute('data-recent-row-count-hot-pulse'),
64
+ animation_name: cs.animationName,
65
+ animation_duration: cs.animationDuration,
66
+ };
67
+ });
68
+ await browser.close();
69
+ return result;
70
+ }
71
+
72
+ const motion = await probe({ reducedMotion: false });
73
+ const a11y = await probe({ reducedMotion: true });
74
+
75
+ const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
76
+ const css = readFileSync('/home/vansin/agent-network-dashboard/app/globals.css', 'utf8');
77
+ const sourceClassWired = /className=\{isHot && !reducedMotion \? 'anet-recent-hot-pulse' : undefined\}/.test(src);
78
+ const sourceAttrWired = /data-recent-row-count-hot-pulse=\{isHot && !reducedMotion \? 'true' : 'false'\}/.test(src);
79
+ const cssKeyframeWired = /@keyframes anet-recent-hot-pulse-kf\s*\{[\s\S]*?opacity:\s*0\.85[\s\S]*?opacity:\s*1[\s\S]*?\}/.test(css);
80
+ const cssClassWired = /\.anet-recent-hot-pulse\s*\{\s*animation:\s*anet-recent-hot-pulse-kf 3s ease-in-out infinite/.test(css);
81
+
82
+ const results = {
83
+ // Motion fixture: tspan found + class applied + attr='true' + animation runs
84
+ motion_hot_found: motion.found,
85
+ motion_class_pulse: motion.found && motion.class_has_pulse,
86
+ motion_attr_true: motion.found && motion.pulse_attr === 'true',
87
+ motion_anim_name: motion.found && motion.animation_name === 'anet-recent-hot-pulse-kf',
88
+ // a11y fixture: class still absent (component-side gate) — attr='false'
89
+ a11y_hot_found: a11y.found,
90
+ a11y_no_class: a11y.found && !a11y.class_has_pulse,
91
+ a11y_attr_false: a11y.found && a11y.pulse_attr === 'false',
92
+ // Source/CSS
93
+ source_class_wired: sourceClassWired,
94
+ source_attr_wired: sourceAttrWired,
95
+ css_keyframe_wired: cssKeyframeWired,
96
+ css_class_wired: cssClassWired,
97
+ };
98
+ const ok = Object.values(results).every(Boolean);
99
+ console.log(`${ok ? '✅' : '❌'} R498 recent-row hot pulse:`, JSON.stringify(results),
100
+ '\n motion:', JSON.stringify(motion),
101
+ '\n a11y: ', JSON.stringify(a11y));
102
+ process.exit(ok ? 0 : 1);
@@ -1 +0,0 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,59276,e=>{"use strict";var s=e.i(12629),a=e.i(11449);let t=async e=>{let s=await fetch(e);if(401===s.status)throw window.location.assign("/login"),Error("unauthorized");return s.json()},r={refreshInterval:5e3,dedupingInterval:3e3};function n(e,s){if(!s)return e;let a=e.includes("?")?"&":"?";return`${e}${a}network_id=${encodeURIComponent(s)}`}e.s(["useAnetConfig",0,function(){let{data:e}=(0,s.default)("/api/anet/config",t,{refreshInterval:3e4});return{config:e||null}},"useHealth",0,function(){let{data:e,error:a}=(0,s.default)("/api/hub/health",t,r);return{health:e||null,error:a}},"useLicense",0,function(){let{data:e,error:a}=(0,s.default)("/api/hub/license",t,{refreshInterval:6e4});return{license:e?.ok?e:null,error:a}},"useMessages",0,function(e=100){let{networkId:l}=(0,a.useNetworkId)(),{data:i,error:c,isLoading:d}=(0,s.default)(n(`/api/hub/messages?limit=${e}`,l),t,r);return{messages:i?.messages||[],error:c,isLoading:d}},"useSessions",0,function(){let{networkId:e}=(0,a.useNetworkId)(),{data:l,error:i,isLoading:c}=(0,s.default)(n("/api/hub/status",e),t,r);return{sessions:l?.sessions||[],hint:l?._hint,error:i,isLoading:c}},"useStats",0,function(){let{networkId:e}=(0,a.useNetworkId)(),{data:l,error:i}=(0,s.default)(n("/api/hub/stats",e),t,r);return{stats:l?.ok?l:null,error:i}},"useTasks",0,function(e){let{networkId:l}=(0,a.useNetworkId)(),i=new URLSearchParams({limit:"100",...e}).toString(),{data:c,error:d,isLoading:o}=(0,s.default)(n(`/api/hub/tasks?${i}`,l),t,r);return{tasks:c?.tasks||[],count:c?.count??0,source:c?.source,error:d,isLoading:o}}])},70286,e=>{"use strict";e.s(["DASHBOARD_VERSION",0,"0.5.3-preview.9"],70286)},65610,e=>{"use strict";var s=e.i(22381),a=e.i(23910),t=e.i(56839),r=e.i(59276),n=e.i(70286);e.s(["default",0,function(){let{config:e}=(0,r.useAnetConfig)(),{health:l}=(0,r.useHealth)(),{license:i}=(0,r.useLicense)(),[c,d]=(0,a.useState)(""),[o,x]=(0,a.useState)(""),[m,h]=(0,a.useState)(""),[g,u]=(0,a.useState)(""),[p,N]=(0,a.useState)(""),b="flex flex-col gap-1 sm:flex-row sm:items-start sm:justify-between",j="break-all sm:max-w-[320px] sm:text-right";return(0,s.jsxs)("div",{className:"min-h-screen bg-[#0a0a1a] text-gray-100 p-4 sm:p-6 font-mono",children:[(0,s.jsx)("h1",{className:"text-2xl font-bold text-white mb-3 lg:ml-0 ml-10",children:"Settings"}),(0,s.jsx)("nav",{className:"mb-8 flex flex-wrap gap-1 text-xs",children:[{href:"#connection",label:"Connection"},{href:"#account",label:"Account"},{href:"#resources",label:"Resources"}].map(e=>(0,s.jsx)("a",{href:e.href,className:"rounded-md px-2.5 py-1 text-gray-500 hover:text-cyan-300 hover:bg-cyan-500/10 transition-colors",children:e.label},e.href))}),(0,s.jsxs)("div",{className:"max-w-2xl space-y-10",children:[(0,s.jsxs)("div",{id:"connection",className:"space-y-4 scroll-mt-6",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,s.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Connection"}),(0,s.jsx)("div",{className:"flex-1 h-px bg-[#2a2a4a]"})]}),(0,s.jsxs)("section",{className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"CommHub Connection"}),(0,s.jsxs)("div",{className:"space-y-3 text-sm",children:[(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500 shrink-0",children:"Hub URL"}),(0,s.jsx)("span",{className:`text-cyan-300 ${j}`,children:e?.hub||"not configured"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Config Source"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:e?.source==="file"?"Local file (~/.anet/config.json)":e?.source==="runtime-env"?"Vercel env vars":"Missing"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Auth Token"}),(0,s.jsx)("span",{className:`${e?.tokenConfigured?"text-green-400":"text-red-400"} ${j}`,children:e?.tokenConfigured?`Configured (${e.tokenPreview})`:"Not configured"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Server Auth"}),(0,s.jsx)("span",{className:`${l?.auth==="enabled"?"text-green-400":"text-yellow-400"} sm:text-right`,children:l?.auth||"--"})]}),e?.error&&(0,s.jsx)("div",{className:"border-t border-[#2a2a4a] pt-3 text-xs text-gray-600",children:e.error})]})]}),(0,s.jsxs)("section",{className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Server Info"}),(0,s.jsxs)("div",{className:"space-y-3 text-sm",children:[(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Version"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:l?.version||"--"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Sessions"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:l?.sessions??"--"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsxs)("span",{className:"text-gray-500",children:["SSE streams ",(0,s.jsx)("span",{className:"text-gray-600",children:"· server"})]}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:l?.sse_connections??"--"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Uptime"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:l?.uptime?`${Math.floor(l.uptime/3600)}h ${Math.floor(l.uptime%3600/60)}m`:"--"})]})]})]}),(0,s.jsxs)("section",{className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Dashboard"}),(0,s.jsxs)("div",{className:"space-y-3 text-sm",children:[(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Version"}),(0,s.jsx)("span",{className:`text-gray-300 font-mono ${j}`,title:"From package.json @sleep2agi/agent-network-dashboard",children:n.DASHBOARD_VERSION})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Data Layer"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:"SWR (5s refresh, 3s dedup)"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Pages"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:"Overview, Tasks, Nodes, Messages, Networks, Audit, Server Logs, Admin, Settings"})]})]})]})]}),(0,s.jsxs)("div",{id:"account",className:"space-y-4 scroll-mt-6",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,s.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Account"}),(0,s.jsx)("div",{className:"flex-1 h-px bg-[#2a2a4a]"})]}),(0,s.jsxs)("section",{className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5",children:[(0,s.jsxs)("h2",{className:"text-sm font-semibold text-gray-300 mb-4 flex items-center gap-2",children:["License",i?.license&&(0,s.jsxs)("span",{className:`inline-flex items-center gap-1.5 text-[10px] font-medium px-2 py-0.5 rounded-full border ${"pro"===i.license.type?"text-green-300 bg-green-500/10 border-green-500/30":i.license.days_left<=7?"text-red-300 bg-red-500/10 border-red-500/30":"text-amber-300 bg-amber-500/10 border-amber-500/30"}`,children:[(0,s.jsx)("span",{"aria-hidden":!0,className:"w-1.5 h-1.5 rounded-full bg-current"}),i.license.type,i.license.days_left?` \xb7 ${i.license.days_left}d left`:""]})]}),i?.license?(0,s.jsxs)("div",{className:"space-y-3 text-sm",children:[i.license.days_left<=7&&(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-red-400 font-medium",children:"⚠ Expiring soon"}),(0,s.jsxs)("span",{className:"text-red-400",children:[i.license.days_left," days left"]})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Expires"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:i.license.expires_at})]}),i.limits&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Max Agents"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:i.limits.max_agents})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Max Networks"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:i.limits.max_networks})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Tasks/Day"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:i.limits.max_tasks_day})]})]}),(0,s.jsxs)("div",{className:"pt-3 border-t border-[#2a2a4a]",children:[(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)("input",{type:"text",value:c,onChange:e=>d(e.target.value),placeholder:"anet-XXXX-XXXX-XXXX-XXXX",className:"flex-1 bg-[#0a0a15] border border-[#2a2a4a] rounded px-3 py-2 text-xs text-white placeholder-gray-600 focus:outline-none"}),(0,s.jsx)("button",{onClick:async()=>{if(!c.trim())return;let e=await fetch("/api/hub/license",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:c})}),s=await e.json();x(s.ok?`Activated: ${s.type}`:`Failed: ${s.error}`),s.ok&&d(""),setTimeout(()=>x(""),5e3)},className:"px-3 py-2 bg-cyan-600 hover:bg-cyan-500 text-white text-xs rounded transition-colors",children:"Activate"})]}),o&&(0,s.jsx)("div",{className:`mt-2 text-xs ${o.startsWith("Failed")?"text-red-400":"text-green-400"}`,children:o})]})]}):(0,s.jsx)("div",{className:"text-xs text-gray-600",children:"License info not available"})]}),(0,s.jsxs)("section",{className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Change Password"}),(0,s.jsxs)("div",{className:"space-y-3",children:[(0,s.jsx)("input",{type:"password",value:m,onChange:e=>h(e.target.value),placeholder:"Current password",className:"w-full bg-[#0a0a15] border border-[#2a2a4a] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-cyan-500/50 focus:outline-none"}),(0,s.jsx)("input",{type:"password",value:g,onChange:e=>u(e.target.value),placeholder:"New password",className:"w-full bg-[#0a0a15] border border-[#2a2a4a] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-cyan-500/50 focus:outline-none"}),(0,s.jsx)("button",{onClick:async()=>{if(!m||!g)return;let e=sessionStorage.getItem("anet_v3_auth");if(!e)return void N("Not logged in with V3 auth");let{token:s}=JSON.parse(e),a=await fetch("/api/hub/auth",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"change_password",token:s,current_password:m,new_password:g})}),t=await a.json();if(N(t.ok?"Password changed":`Failed: ${t.error}`),t.ok){if(t.token){let s=JSON.parse(e);sessionStorage.setItem("anet_v3_auth",JSON.stringify({...s,token:t.token}))}h(""),u("")}setTimeout(()=>N(""),5e3)},disabled:!m||!g,className:"px-4 py-2 bg-cyan-600 hover:bg-cyan-500 disabled:bg-gray-800 disabled:text-gray-600 text-white text-sm rounded-lg transition-colors",children:"Change Password"})]}),p&&(0,s.jsx)("div",{className:`mt-2 text-xs ${p.startsWith("Failed")?"text-red-400":"text-green-400"}`,children:p})]}),(0,s.jsxs)("section",{className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Sign out"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mb-3",children:"Signing out clears your dashboard session cookie. You'll return to the login page."}),(0,s.jsx)("button",{onClick:async()=>{await fetch("/api/auth/logout",{method:"POST"}).catch(()=>{}),window.location.assign("/login")},className:"px-4 py-2 bg-transparent hover:bg-[#1a1a2a] text-gray-300 text-sm rounded-lg border border-[#2a2a4a] hover:border-[#3a3a5a] transition-colors",children:"Sign out"})]})]}),(0,s.jsxs)("div",{id:"resources",className:"space-y-4 scroll-mt-6",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,s.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Resources"}),(0,s.jsx)("div",{className:"flex-1 h-px bg-[#2a2a4a]"})]}),(0,s.jsxs)("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4",children:[(0,s.jsxs)(t.default,{href:"/settings/tokens",className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5 hover:border-cyan-500/30 transition-colors",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300",children:"API Tokens"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-2",children:"Create and manage tokens for CLI access."}),(0,s.jsx)("span",{className:"text-xs text-cyan-400 mt-3 inline-block",children:"Manage →"})]}),(0,s.jsxs)(t.default,{href:"/settings/networks",className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5 hover:border-cyan-500/30 transition-colors",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300",children:"Networks"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-2",children:"Create, manage, and delete agent networks."}),(0,s.jsx)("span",{className:"text-xs text-cyan-400 mt-3 inline-block",children:"Manage →"})]})]})]})]})]})}])}]);
@@ -1 +0,0 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,70286,e=>{"use strict";e.s(["DASHBOARD_VERSION",0,"0.5.3-preview.9"],70286)},48941,e=>{"use strict";var t=e.i(22381),r=e.i(23910),a=e.i(70286);e.s(["default",0,function(){let[e,s]=(0,r.useState)("login"),[n,o]=(0,r.useState)(""),[i,l]=(0,r.useState)(""),[c,d]=(0,r.useState)(!1),[x,g]=(0,r.useState)(""),[h,m]=(0,r.useState)(!1),u=async t=>{t.preventDefault(),m(!0),g("");try{let t=await fetch("/api/auth/v3",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:e,username:n,password:i})}),r=await t.json();if(r.ok){r.token&&sessionStorage.setItem("anet_v3_auth",JSON.stringify({user:r.user,token:r.token,networks:r.networks||[],currentNetwork:r.network_id||r.networks?.[0]?.network_id||""})),window.location.assign("/");return}g(r.error||"Login failed")}catch{g("Connection failed")}m(!1)};return(0,t.jsxs)("main",{className:"min-h-screen bg-[#0a0a1a] text-gray-100 font-mono flex items-center justify-center relative overflow-hidden px-4 py-10 sm:py-16",children:[(0,t.jsx)("div",{className:"absolute inset-0 pointer-events-none anet-login-bg","aria-hidden":!0}),(0,t.jsxs)("div",{className:"relative w-full max-w-sm",children:[(0,t.jsxs)("div",{className:"text-center mb-7",children:[(0,t.jsx)("div",{className:"inline-flex items-center justify-center w-16 h-16 mb-4 rounded-2xl bg-[#111128] border border-[#2a2a4a] anet-login-mark",children:(0,t.jsxs)("svg",{className:"w-9 h-9",viewBox:"0 0 32 32","aria-hidden":!0,children:[(0,t.jsx)("circle",{cx:"16",cy:"16",r:"10",fill:"none",stroke:"currentColor",strokeWidth:"1.5",opacity:"0.25",className:"text-cyan-400 anet-login-mark-ring"}),(0,t.jsx)("line",{x1:"16",y1:"10",x2:"10",y2:"20",stroke:"currentColor",strokeWidth:"1",opacity:"0.5",className:"text-cyan-400 anet-login-mark-edge"}),(0,t.jsx)("line",{x1:"16",y1:"10",x2:"22",y2:"20",stroke:"currentColor",strokeWidth:"1",opacity:"0.5",className:"text-cyan-400 anet-login-mark-edge"}),(0,t.jsx)("line",{x1:"10",y1:"20",x2:"22",y2:"20",stroke:"currentColor",strokeWidth:"1",opacity:"0.5",className:"text-cyan-400 anet-login-mark-edge"}),(0,t.jsx)("circle",{cx:"16",cy:"10",r:"3",fill:"currentColor",className:"text-cyan-400 anet-login-mark-node-a"}),(0,t.jsx)("circle",{cx:"10",cy:"20",r:"3",fill:"currentColor",className:"text-green-400 anet-login-mark-node-b"}),(0,t.jsx)("circle",{cx:"22",cy:"20",r:"3",fill:"currentColor",className:"text-violet-400 anet-login-mark-node-c"})]})}),(0,t.jsx)("h1",{className:"text-[22px] sm:text-2xl font-semibold text-white tracking-tight",children:"Agent Network"}),(0,t.jsx)("p",{className:"text-[13px] text-gray-500 mt-1.5 leading-snug",children:"login"===e?(0,t.jsxs)(t.Fragment,{children:["Welcome back · ",(0,t.jsx)("span",{className:"text-gray-600",children:"Tasks · Mesh · Messages"})]}):(0,t.jsxs)(t.Fragment,{children:["Create your account · ",(0,t.jsx)("span",{className:"text-gray-600",children:"Free preview · no credit card"})]})})]}),(0,t.jsx)("div",{className:"flex rounded-lg border border-[#2a2a4a] bg-[#111128] p-1 mb-4",children:["login","register"].map(r=>(0,t.jsx)("button",{type:"button",onClick:()=>{s(r),g("")},className:`flex-1 rounded-md px-3 py-2 text-sm transition-colors ${e===r?"bg-cyan-500/10 text-cyan-300":"text-gray-500 hover:text-gray-200"}`,children:"login"===r?"Sign in":"Register"},r))}),(0,t.jsxs)("form",{onSubmit:u,className:"border border-[#2a2a4a] bg-[#111128]/80 backdrop-blur-sm rounded-xl p-6 shadow-2xl shadow-black/30",children:[(0,t.jsx)("label",{htmlFor:"username",className:"block text-xs text-gray-500 mb-2 uppercase tracking-wider",children:"Username"}),(0,t.jsx)("input",{id:"username",type:"text",value:n,onChange:e=>o(e.target.value),autoFocus:!0,placeholder:"Enter username",className:"w-full bg-[#0a0a15] border border-[#2a2a4a] rounded-lg px-4 py-3 text-sm text-white placeholder-gray-600 focus:border-cyan-500/50 focus:ring-1 focus:ring-cyan-500/20 focus:outline-none transition-all mb-4"}),(0,t.jsx)("label",{htmlFor:"password",className:"block text-xs text-gray-500 mb-2 uppercase tracking-wider",children:"Password"}),(0,t.jsxs)("div",{className:"relative",children:[(0,t.jsx)("input",{id:"password",type:c?"text":"password",value:i,onChange:e=>l(e.target.value),placeholder:"Enter password",className:"w-full bg-[#0a0a15] border border-[#2a2a4a] rounded-lg px-4 pr-11 py-3 text-sm text-white placeholder-gray-600 focus:border-cyan-500/50 focus:ring-1 focus:ring-cyan-500/20 focus:outline-none transition-all"}),(0,t.jsx)("button",{type:"button",onClick:()=>d(e=>!e),tabIndex:-1,"aria-label":c?"Hide password":"Show password",className:"absolute inset-y-0 right-0 flex items-center px-3 text-gray-600 hover:text-gray-300 transition-colors",children:c?(0,t.jsxs)("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,t.jsx)("path",{d:"M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"}),(0,t.jsx)("line",{x1:"1",y1:"1",x2:"23",y2:"23"})]}):(0,t.jsxs)("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,t.jsx)("path",{d:"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"}),(0,t.jsx)("circle",{cx:"12",cy:"12",r:"3"})]})})]}),x&&(0,t.jsx)("div",{className:"mt-3 text-sm text-red-300 bg-red-500/5 border border-red-500/10 rounded-lg px-3 py-2",children:x}),(0,t.jsxs)("button",{type:"submit",disabled:h||!i||!n.trim(),className:"mt-5 w-full flex items-center justify-center gap-2 px-4 py-3 bg-gradient-to-r from-cyan-600 to-blue-600 hover:from-cyan-500 hover:to-blue-500 disabled:from-gray-800 disabled:to-gray-800 disabled:text-gray-600 text-white text-sm font-medium rounded-lg transition-all shadow-lg shadow-cyan-500/10 hover:shadow-cyan-500/20 disabled:shadow-none",children:[h&&(0,t.jsxs)("svg",{"aria-hidden":!0,className:"w-4 h-4 animate-spin",viewBox:"0 0 24 24",fill:"none",children:[(0,t.jsx)("circle",{cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"3",opacity:"0.25"}),(0,t.jsx)("path",{d:"M4 12a8 8 0 018-8",stroke:"currentColor",strokeWidth:"3",strokeLinecap:"round"})]}),(0,t.jsx)("span",{children:h?"login"===e?"Signing in…":"Registering…":"login"===e?"Sign in":"Create account"})]})]}),(0,t.jsxs)("p",{className:"text-center text-[11px] text-gray-700 mt-6",children:["Sleep2AGI · Apache-2.0 · ",(0,t.jsx)("a",{href:"https://anet.sh",className:"hover:text-gray-500 transition-colors",children:"anet.sh"}),(0,t.jsx)("span",{className:"mx-1 text-gray-800",children:"·"}),(0,t.jsxs)("span",{className:"font-mono",title:"@sleep2agi/agent-network-dashboard",children:["v",a.DASHBOARD_VERSION]})]})]})]})}])}]);