@sleep2agi/agent-network-dashboard 0.4.5-preview.0 → 0.4.5-preview.2

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 (198) 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 +30 -30
  4. package/.next/fallback-build-manifest.json +3 -3
  5. package/.next/prerender-manifest.json +3 -3
  6. package/.next/server/app/_global-error.html +1 -1
  7. package/.next/server/app/_global-error.rsc +1 -1
  8. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  14. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  15. package/.next/server/app/_not-found.html +2 -2
  16. package/.next/server/app/_not-found.rsc +12 -12
  17. package/.next/server/app/_not-found.segments/_full.segment.rsc +12 -12
  18. package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  19. package/.next/server/app/_not-found.segments/_index.segment.rsc +7 -7
  20. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  21. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  22. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  23. package/.next/server/app/admin/page.js.nft.json +1 -1
  24. package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
  25. package/.next/server/app/admin.html +2 -2
  26. package/.next/server/app/admin.rsc +14 -14
  27. package/.next/server/app/admin.segments/_full.segment.rsc +14 -14
  28. package/.next/server/app/admin.segments/_head.segment.rsc +4 -4
  29. package/.next/server/app/admin.segments/_index.segment.rsc +7 -7
  30. package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
  31. package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +4 -4
  32. package/.next/server/app/admin.segments/admin.segment.rsc +3 -3
  33. package/.next/server/app/index.html +2 -2
  34. package/.next/server/app/index.rsc +14 -14
  35. package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
  36. package/.next/server/app/index.segments/_full.segment.rsc +14 -14
  37. package/.next/server/app/index.segments/_head.segment.rsc +4 -4
  38. package/.next/server/app/index.segments/_index.segment.rsc +7 -7
  39. package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  40. package/.next/server/app/login/page.js.nft.json +1 -1
  41. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  42. package/.next/server/app/login.html +2 -2
  43. package/.next/server/app/login.rsc +14 -14
  44. package/.next/server/app/login.segments/_full.segment.rsc +14 -14
  45. package/.next/server/app/login.segments/_head.segment.rsc +4 -4
  46. package/.next/server/app/login.segments/_index.segment.rsc +7 -7
  47. package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  48. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
  49. package/.next/server/app/login.segments/login.segment.rsc +3 -3
  50. package/.next/server/app/logs/page.js.nft.json +1 -1
  51. package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
  52. package/.next/server/app/logs.html +2 -2
  53. package/.next/server/app/logs.rsc +14 -14
  54. package/.next/server/app/logs.segments/_full.segment.rsc +14 -14
  55. package/.next/server/app/logs.segments/_head.segment.rsc +4 -4
  56. package/.next/server/app/logs.segments/_index.segment.rsc +7 -7
  57. package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
  58. package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +4 -4
  59. package/.next/server/app/logs.segments/logs.segment.rsc +3 -3
  60. package/.next/server/app/messages/page.js.nft.json +1 -1
  61. package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
  62. package/.next/server/app/messages.html +2 -2
  63. package/.next/server/app/messages.rsc +14 -14
  64. package/.next/server/app/messages.segments/_full.segment.rsc +14 -14
  65. package/.next/server/app/messages.segments/_head.segment.rsc +4 -4
  66. package/.next/server/app/messages.segments/_index.segment.rsc +7 -7
  67. package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
  68. package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +4 -4
  69. package/.next/server/app/messages.segments/messages.segment.rsc +3 -3
  70. package/.next/server/app/node/page.js.nft.json +1 -1
  71. package/.next/server/app/node/page_client-reference-manifest.js +1 -1
  72. package/.next/server/app/node.html +2 -2
  73. package/.next/server/app/node.rsc +14 -14
  74. package/.next/server/app/node.segments/_full.segment.rsc +14 -14
  75. package/.next/server/app/node.segments/_head.segment.rsc +4 -4
  76. package/.next/server/app/node.segments/_index.segment.rsc +7 -7
  77. package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
  78. package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +4 -4
  79. package/.next/server/app/node.segments/node.segment.rsc +3 -3
  80. package/.next/server/app/nodes/page.js.nft.json +1 -1
  81. package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
  82. package/.next/server/app/nodes.html +2 -2
  83. package/.next/server/app/nodes.rsc +14 -14
  84. package/.next/server/app/nodes.segments/_full.segment.rsc +14 -14
  85. package/.next/server/app/nodes.segments/_head.segment.rsc +4 -4
  86. package/.next/server/app/nodes.segments/_index.segment.rsc +7 -7
  87. package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
  88. package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +4 -4
  89. package/.next/server/app/nodes.segments/nodes.segment.rsc +3 -3
  90. package/.next/server/app/page.js.nft.json +1 -1
  91. package/.next/server/app/page_client-reference-manifest.js +1 -1
  92. package/.next/server/app/server-logs/page.js.nft.json +1 -1
  93. package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
  94. package/.next/server/app/server-logs.html +2 -2
  95. package/.next/server/app/server-logs.rsc +14 -14
  96. package/.next/server/app/server-logs.segments/_full.segment.rsc +14 -14
  97. package/.next/server/app/server-logs.segments/_head.segment.rsc +4 -4
  98. package/.next/server/app/server-logs.segments/_index.segment.rsc +7 -7
  99. package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
  100. package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +4 -4
  101. package/.next/server/app/server-logs.segments/server-logs.segment.rsc +3 -3
  102. package/.next/server/app/settings/networks/page.js.nft.json +1 -1
  103. package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
  104. package/.next/server/app/settings/networks.html +2 -2
  105. package/.next/server/app/settings/networks.rsc +14 -14
  106. package/.next/server/app/settings/networks.segments/_full.segment.rsc +14 -14
  107. package/.next/server/app/settings/networks.segments/_head.segment.rsc +4 -4
  108. package/.next/server/app/settings/networks.segments/_index.segment.rsc +7 -7
  109. package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
  110. package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +4 -4
  111. package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +3 -3
  112. package/.next/server/app/settings/networks.segments/settings.segment.rsc +3 -3
  113. package/.next/server/app/settings/page.js.nft.json +1 -1
  114. package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  115. package/.next/server/app/settings/tokens/page.js.nft.json +1 -1
  116. package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
  117. package/.next/server/app/settings/tokens.html +2 -2
  118. package/.next/server/app/settings/tokens.rsc +14 -14
  119. package/.next/server/app/settings/tokens.segments/_full.segment.rsc +14 -14
  120. package/.next/server/app/settings/tokens.segments/_head.segment.rsc +4 -4
  121. package/.next/server/app/settings/tokens.segments/_index.segment.rsc +7 -7
  122. package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
  123. package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +4 -4
  124. package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +3 -3
  125. package/.next/server/app/settings/tokens.segments/settings.segment.rsc +3 -3
  126. package/.next/server/app/settings.html +2 -2
  127. package/.next/server/app/settings.rsc +14 -14
  128. package/.next/server/app/settings.segments/_full.segment.rsc +14 -14
  129. package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
  130. package/.next/server/app/settings.segments/_index.segment.rsc +7 -7
  131. package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  132. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
  133. package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
  134. package/.next/server/app/tasks/[id]/page.js.nft.json +1 -1
  135. package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
  136. package/.next/server/app/tasks/page.js.nft.json +1 -1
  137. package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
  138. package/.next/server/app/tasks.html +2 -2
  139. package/.next/server/app/tasks.rsc +14 -14
  140. package/.next/server/app/tasks.segments/_full.segment.rsc +14 -14
  141. package/.next/server/app/tasks.segments/_head.segment.rsc +4 -4
  142. package/.next/server/app/tasks.segments/_index.segment.rsc +7 -7
  143. package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
  144. package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +4 -4
  145. package/.next/server/app/tasks.segments/tasks.segment.rsc +3 -3
  146. package/.next/server/chunks/ssr/[root-of-the-server]__0a0ffmv._.js +3 -0
  147. package/.next/server/chunks/ssr/[root-of-the-server]__0a0ffmv._.js.map +1 -0
  148. package/.next/server/chunks/ssr/app_components_08ys5y3._.js +9 -0
  149. package/.next/server/chunks/ssr/app_components_08ys5y3._.js.map +1 -0
  150. package/.next/server/chunks/ssr/app_page_tsx_0es_sk2._.js +1 -1
  151. package/.next/server/chunks/ssr/app_page_tsx_0es_sk2._.js.map +1 -1
  152. package/.next/server/chunks/ssr/app_tasks_page_tsx_0z-d6mp._.js +1 -1
  153. package/.next/server/chunks/ssr/app_tasks_page_tsx_0z-d6mp._.js.map +1 -1
  154. package/.next/server/middleware-build-manifest.js +3 -3
  155. package/.next/server/pages/404.html +2 -2
  156. package/.next/server/pages/500.html +1 -1
  157. package/.next/server/server-reference-manifest.js +1 -1
  158. package/.next/server/server-reference-manifest.json +1 -1
  159. package/.next/static/chunks/{0hyhubmh-__wg.js → 0b1ymo-btjfha.js} +1 -1
  160. package/.next/static/chunks/0qgc758gz3on4.js +7 -0
  161. package/.next/static/chunks/0xxk2ms76kkuz.css +2 -0
  162. package/.next/static/chunks/1031v6nw33ud3.js +1 -0
  163. package/.next/trace +2 -2
  164. package/.next/trace-build +1 -1
  165. package/app/components/AppShell.tsx +9 -1
  166. package/app/components/CommandPalette.tsx +358 -0
  167. package/app/components/HealthBanner.tsx +132 -0
  168. package/app/components/HelpOverlay.tsx +121 -0
  169. package/app/components/LoadingSkeleton.tsx +81 -25
  170. package/app/components/Sidebar.tsx +18 -0
  171. package/app/components/UserBar.tsx +16 -2
  172. package/app/globals.css +181 -0
  173. package/app/page.tsx +87 -14
  174. package/app/tasks/page.tsx +35 -5
  175. package/docs/loop-design-rounds.md +298 -3
  176. package/docs/screenshots/0.4.5-preview.1/cyber-admin.png +0 -0
  177. package/docs/screenshots/0.4.5-preview.1/cyber-cmdk-search.png +0 -0
  178. package/docs/screenshots/0.4.5-preview.1/cyber-cmdk.png +0 -0
  179. package/docs/screenshots/0.4.5-preview.1/cyber-login.png +0 -0
  180. package/docs/screenshots/0.4.5-preview.1/cyber-overview.png +0 -0
  181. package/docs/screenshots/0.4.5-preview.1/cyber-settings.png +0 -0
  182. package/docs/screenshots/0.4.5-preview.1/cyber-tasks.png +0 -0
  183. package/docs/screenshots/0.4.5-preview.1/light-admin.png +0 -0
  184. package/docs/screenshots/0.4.5-preview.1/light-cmdk-search.png +0 -0
  185. package/docs/screenshots/0.4.5-preview.1/light-cmdk.png +0 -0
  186. package/docs/screenshots/0.4.5-preview.1/light-login.png +0 -0
  187. package/docs/screenshots/0.4.5-preview.1/light-overview.png +0 -0
  188. package/docs/screenshots/0.4.5-preview.1/light-settings.png +0 -0
  189. package/docs/screenshots/0.4.5-preview.1/light-tasks.png +0 -0
  190. package/package.json +1 -1
  191. package/.next/server/chunks/ssr/[root-of-the-server]__013i9e9._.js +0 -9
  192. package/.next/server/chunks/ssr/[root-of-the-server]__013i9e9._.js.map +0 -1
  193. package/.next/static/chunks/0snd~q2ucn.h1.css +0 -2
  194. package/.next/static/chunks/0xn9.0ejo1s_a.js +0 -7
  195. package/.next/static/chunks/0y0lo-~k2c~00.js +0 -1
  196. /package/.next/static/{2m1yIfZCIYDWMYrrJEKSC → dvjBKNMRovte6RFP_k8Lq}/_buildManifest.js +0 -0
  197. /package/.next/static/{2m1yIfZCIYDWMYrrJEKSC → dvjBKNMRovte6RFP_k8Lq}/_clientMiddlewareManifest.js +0 -0
  198. /package/.next/static/{2m1yIfZCIYDWMYrrJEKSC → dvjBKNMRovte6RFP_k8Lq}/_ssgManifest.js +0 -0
@@ -497,6 +497,301 @@ Natural ship-point. Round 8 = the publish itself:
497
497
  4. Tell 通äŋĄéž™ to bump CLI preview's PINNED_DASHBOARD_VERSION
498
498
  5. Telegram Vincent: `npm i -g @sleep2agi/agent-network@preview`
499
499
 
500
- After ship, rounds 9+ accumulate toward `0.4.6-preview.0`. Backlog
501
- ideas: layout collision avoidance in TopoGraph, hover affordances on
502
- KPI cards, Cmd+K command palette, header health banner, mobile audit.
500
+ After ship, rounds 9+ accumulate toward the **next** preview in the
501
+ SAME `0.4.5-preview.N` series (Vincent's policy: don't burn base version
502
+ numbers on preview-only work). Backlog ideas: layout collision
503
+ avoidance in TopoGraph, hover affordances on KPI cards, Cmd+K command
504
+ palette, header health banner, mobile audit.
505
+
506
+ > **Version policy (round 8 + Vincent telegram)**: stable stays at
507
+ > `0.4.2` until Vincent explicitly promotes a preview. All new previews
508
+ > bump only the `-preview.N` suffix on the same `0.4.5` base. The
509
+ > `latest` npm tag never moves without sign-off.
510
+
511
+ ---
512
+
513
+ ## Round 9 — Header health banner
514
+
515
+ ### What changed
516
+ - New `app/components/HealthBanner.tsx`: thin sticky strip mounted in
517
+ `AppShell` between sidebar and page content, visible on every
518
+ non-login page.
519
+ - Three states, priority-ranked:
520
+ - **red** — `CommHub unreachable — agents may be offline` + CTA
521
+ "Open Settings →"
522
+ - **amber** — `N task(s) failed recently` + CTA "Review failures →"
523
+ (links to `/tasks?status=failed`). Dot pulses with the same 1.6s
524
+ opacity drift as the sidebar online pulse.
525
+ - **green** — `All systems go`. Quiet. No CTA. Doesn't render until
526
+ at least one stats response confirms (avoids flashing green on
527
+ first paint before data arrives).
528
+ - Pulls from `/api/hub/stats` + `/api/hub/health` via SWR (15s refresh,
529
+ 5s dedupe). Both endpoints are already polled elsewhere — request
530
+ dedupes free, banner has zero net cost.
531
+ - Dismissible per-session via `sessionStorage.anet-hb-dismissed = '1'`.
532
+ Re-shows on next session.
533
+ - Light/mint themes get bumped color saturation via `.anet-health-banner`
534
+ override rules in globals.css so red/amber/green read crisply on
535
+ white surfaces.
536
+
537
+ ### Self-score: **8.7 / 10**
538
+
539
+ | Dimension | Score | Notes |
540
+ |--------------------------|------:|------------------------------------------------------------------------|
541
+ | Information value | 9 | Fleet health visible from every page without navigating to /nodes |
542
+ | Restraint | 9 | 32px-tall strip; opacity-only pulse; no glow; auto-dismissible |
543
+ | Affordance (CTAs) | 9 | Each non-green state has a clear "fix this" link |
544
+ | Theme parity | 9 | All 3 states verified in light + cyber |
545
+ | Failure-state robustness | 8 | "Red" fires only when both `/stats` AND `/health` fail; safer than either alone |
546
+ | Mobile | 7 | Strip wraps at 390px viewport; could collapse "Review failures →" copy further |
547
+
548
+ **Deductions**:
549
+ - −0.6: on very narrow mobile (<340px) the CTA + dismiss can wrap or
550
+ overlap. Could collapse CTA to icon-only at that breakpoint.
551
+ - −0.4: red state has a single message; doesn't distinguish "hub down"
552
+ vs "auth expired" vs "network error". Future round could add error
553
+ classification.
554
+ - −0.3: dismiss is session-scoped. Some users may want
555
+ "dismiss for this session only" vs "dismiss forever". Defer.
556
+
557
+ ### Round 10 plan: **KPI card rich hover preview**
558
+
559
+ Overview's stat strip (round 3) shows top-level numbers — `Nodes 4/5`,
560
+ `Tasks 0`, `Failed 0` — but a power user wants to see the breakdown
561
+ without clicking through. Add small CSS-only popovers that appear on
562
+ hover:
563
+ - Nodes hover → "3 working · 2 idle · 0 offline"
564
+ - Tasks hover → "by status: 4 running, 2 replied, 1 failed, 0 expired"
565
+ - Failed hover → "5 in last hour · last failure 12m ago"
566
+
567
+ Pure CSS popover (no JS state), 200ms delay-show, fades out on
568
+ unhover. Both themes. Doesn't affect mobile (touch shows full card
569
+ already).
570
+
571
+ Estimated work: 25 min. Fires next `*/5`.
572
+
573
+ ---
574
+
575
+ ## Round 10 — KPI card rich hover preview
576
+
577
+ ### What changed
578
+ - The 3-stat strip on Overview (Nodes / Tasks / Failed) now gets a
579
+ **hover popover** showing the breakdown that the headline number
580
+ abstracts away.
581
+ - **Nodes** hover → `● working {n}` / `● idle {n}` / `● offline {n}`
582
+ - **Tasks** hover → list of all populated statuses in priority
583
+ order (running → replied → failed → cancelled → expired → closed
584
+ → created → delivered → acked), each with its color dot + count
585
+ - **Failed** hover → `no failures yet` or `{n} in current view`
586
+ - **Pure CSS** popover: hidden by default, `opacity-0 translate-y-[-2px]`
587
+ transitions to `opacity-100 translate-y-0` on `group-hover`. 100ms
588
+ delay-show so a quick mouse-pass doesn't flicker. No React state.
589
+ - `pointer-events-none` on the popover so it never intercepts the
590
+ click through to the underlying Link target.
591
+ - **Mobile gate**: `hidden md:block` — touch devices don't get the
592
+ popover (no `:hover`). The card itself still navigates on tap, so no
593
+ functionality lost.
594
+ - Dot colors inlined as hex (`#4ade80` green, `#a78bfa` purple, etc.)
595
+ to dodge Tailwind's purge of dynamic `bg-${family}-400` class names.
596
+
597
+ ### Self-score: **8.5 / 10**
598
+
599
+ **Deductions**: no `:focus-within` trigger (keyboard users miss
600
+ popover); "Failed" copy doesn't show time bucket; dot hex inlined
601
+ rather than centralized in a constants palette.
602
+
603
+ ### Round 11 plan: **Mobile audit + polish pass**
604
+
605
+ Nine rounds in, the desktop story is solid. Mobile hasn't gotten a
606
+ dedicated round since the initial audit. Likely findings:
607
+
608
+ - Health banner at <340px: CTA + dismiss button + truncated message
609
+ competes for ~280px usable width. Collapse CTA to icon-only or
610
+ move it below the message.
611
+ - Stat strip 3-col at 360-390px: "View →" affordance shrinks below
612
+ legibility. Either drop "View →" on mobile or stack 1-col.
613
+ - Sidebar mobile drawer: not screenshot-audited against the latest
614
+ brand-mark + pulse changes.
615
+ - Footer text spacing on /login at 320px: wraps awkwardly.
616
+
617
+ Action: capture mobile screenshots across 5-6 key pages at 390×844
618
+ AND 360×740, identify worst offenders, fix the top 3.
619
+
620
+ Estimated work: 30 min. Fires next `*/5`.
621
+
622
+ ---
623
+
624
+ ## Round 11 — Mobile audit + polish pass
625
+
626
+ ### Findings (390×844 + 360×740)
627
+ Captured 12 screenshots (6 pages × 2 themes × 2 viewports). Three
628
+ clear regressions at narrow widths:
629
+
630
+ 1. **Health banner** ran into the fixed-position hamburger button at
631
+ top-left (top:4 left:3, ~44×44 hit area). Message text was
632
+ truncated to "...sks failed recently" because the leading 6
633
+ characters sat under the hamburger.
634
+ 2. **UserBar** "Edit" + "Sign out" text links cramped against the
635
+ user name + role on narrow screens, wrapping "Sign out" onto
636
+ two lines.
637
+ 3. **Stat strip** "View →" affordance in each card's top-right took
638
+ horizontal space the headline number needed, making the 3-col
639
+ grid feel cramped at 360px.
640
+
641
+ ### What changed
642
+ - **HealthBanner**: `pl-3` → `pl-14` on mobile (clears the hamburger
643
+ button), CTA text "Review failures" / "Open Settings" collapses to
644
+ a bare arrow on `<sm` with a proper `aria-label` so screen
645
+ readers still hear the destination.
646
+ - **UserBar Edit / Sign out**: text on `>=sm`, single inline-svg icon
647
+ on `<sm` (pencil for edit, doorway-arrow for sign out). Both stay
648
+ same hit area, just label-trimmed.
649
+ - **Stat strip "View →"**: `hidden sm:block` so the affordance only
650
+ appears on desktop. Mobile cards are fully tappable, so the
651
+ affordance is implicit.
652
+
653
+ ### Self-score: **9.0 / 10**
654
+
655
+ | Dimension | Score | Notes |
656
+ |------------------------|------:|------------------------------------------------------------------|
657
+ | Defect closure | 10 | All three observed mobile regressions resolved |
658
+ | Desktop non-regression | 9 | All changes wrapped in `sm:` breakpoint — pixel-identical >640px |
659
+ | Restraint | 9 | Icons are simple line SVGs matching the design system |
660
+ | Accessibility | 9 | `aria-label` on collapsed CTAs and icon-only buttons |
661
+ | Touch target | 8 | Icons are 16px visual; full `<button>` is still 44px hit area |
662
+
663
+ **Deductions**:
664
+ - −0.5: not tested below 360px (e.g. 320px iPhone SE first-gen).
665
+ Probably still fine but unverified.
666
+ - −0.3: sidebar drawer mobile state (when hamburger is tapped) not
667
+ re-screenshotted post round-4 brand changes.
668
+ - −0.2: existing chip filter rows on Tasks/Messages still wrap at
669
+ narrow widths. Not the most painful, deferred.
670
+
671
+ ### Round 12 plan: **Loading skeleton refresh**
672
+
673
+ The `LoadingSkeleton` component in `app/components/LoadingSkeleton.tsx`
674
+ still uses `bg-gray-800` / `bg-gray-800/40` patterns from the
675
+ pre-theme-token era. It works (CSS shim catches `bg-gray-800` in
676
+ light), but it's the only surface that didn't get a deliberate
677
+ restyle. Refresh to use:
678
+ - subtle bg + animated pulse using the same `anet-brand-pulse`
679
+ rhythm (1.6s opacity drift) for visual cohesion
680
+ - proper card structure matching round 3's stat-strip shape
681
+ - both themes, no AI-noise
682
+
683
+ Estimated work: 20 min. Fires next `*/5`.
684
+
685
+ ---
686
+
687
+ ## Round 14 — Cmd+K command palette (scaffold)
688
+
689
+ ### What changed
690
+ - New `app/components/CommandPalette.tsx` mounted in `AppShell` so it's
691
+ globally available on every non-login page.
692
+ - **Keyboard shortcuts** (global, not per-page):
693
+ - `⌘K` / `Ctrl+K` toggles open/closed
694
+ - `/` opens when no input is focused (Linear-style)
695
+ - `↑↓` navigates results, `Enter` activates, `Esc` closes
696
+ - **Layout**: centered modal at 10vh-15vh from top, max-w-xl, backdrop
697
+ blur over content. Search input + grouped results + footer hint bar.
698
+ - **Initial command set**: 10 navigation entries covering every
699
+ primary page (Overview / Tasks / Failed tasks / Nodes / Messages /
700
+ Networks / Audit Log / Server Logs / Admin / Settings). Each carries
701
+ a hint subtitle and a thin-stroke icon.
702
+ - **Filter behavior**: case-insensitive search over title + hint + id.
703
+ Active row gets emerald tint + `â†ĩ` glyph; mouse hover updates the
704
+ selected index so keyboard and pointer stay in sync.
705
+ - **Light/mint surface**: white modal with real soft shadow (vs the
706
+ default `bg-[#0d0d1a]` navy that CSS shim would translate). Override
707
+ ruled in globals.css.
708
+
709
+ ### Self-score: **8.7 / 10**
710
+
711
+ | Dimension | Score | Notes |
712
+ |------------------------|------:|------------------------------------------------------------------------|
713
+ | Adoption signal | 9 | Stripe/Linear/Vercel staple — sets reader expectation that we're modern |
714
+ | Keyboard-first | 9 | All keys wired; mouse + keyboard stay in sync |
715
+ | Restraint | 9 | Mono-stroke icons, single accent color, no AI shimmer |
716
+ | Theme parity | 9 | Light gets a proper white surface w/ shadow; cyber uses navy |
717
+ | Discoverability | 7 | No visible "press ⌘K" hint anywhere on the page yet |
718
+ | Mobile | 6 | Works on mobile (tap to open via UI) — but no on-screen launcher yet |
719
+
720
+ **Deductions**:
721
+ - −0.7: zero on-page hint that the palette exists. Most users will
722
+ never find `⌘K` without docs. Should add a tiny "⌘K" badge in
723
+ sidebar footer or in the UserBar.
724
+ - −0.4: no mobile launcher. Mobile has no obvious affordance.
725
+ - −0.2: command set is navigation-only. Round 15 will add actions
726
+ (theme toggle / sign out / Dispatch open) and recent-commands.
727
+
728
+ ### Round 15 plan: **Cmd+K actions + recent-commands**
729
+
730
+ Extend the scaffold with the "Actions" group:
731
+ - Toggle theme (cyber ↔ light)
732
+ - Open Dispatch dialog (current page's Dispatch button)
733
+ - Sign out
734
+ - Copy current URL
735
+
736
+ Plus add a `Recents` group at the top that surfaces the last 3-5
737
+ commands the user invoked (ring buffer in `sessionStorage`).
738
+
739
+ Plus a discoverability nudge — tiny `⌘K` chip in sidebar footer +
740
+ UserBar tooltip.
741
+
742
+ Estimated work: 25 min. Fires next `*/5`.
743
+
744
+ ---
745
+
746
+ ## Round 12 — Loading skeleton refresh
747
+
748
+ ### What changed
749
+ - `LoadingSkeleton` now **mirrors the actual Overview layout** so the
750
+ page doesn't shift on data arrival. Old version was generic header
751
+ + broadcast + topology + 4-card grid; new version shows: 4 KPI
752
+ cards, Dispatch+UserBar row, Config bar, 3-card stat strip, 3-tile
753
+ nav rail, Broadcast bar, 4-card agent grid.
754
+ - Switched from Tailwind's `animate-pulse` (1s opacity drift) to a
755
+ custom `anet-skeleton-pulse` (1.6s) to match the same rhythm as
756
+ `anet-brand-pulse` in the sidebar and the health banner amber dot.
757
+ Visual cohesion across the design system.
758
+ - Introduced `anet-skeleton-bar` class with explicit per-theme
759
+ background: `#1a1a2a` on dark (lighter navy on dark card),
760
+ `#d4d8df` on light/mint (mid-grey on white card). The previous
761
+ attempt to reuse the `bg-[#1a1a2a]` shim was too subtle (light
762
+ card #ffffff vs bar mapped to bg-elevated #eef0f4 = only ~7
763
+ brightness levels different = invisible bars).
764
+ - All bar dimensions use rem-based explicit values via inline style
765
+ so they don't depend on Tailwind purge correctness.
766
+ - `prefers-reduced-motion: reduce` kills the pulse on both classes.
767
+
768
+ ### Self-score: **9.0 / 10**
769
+
770
+ | Dimension | Score | Notes |
771
+ |------------------------|------:|------------------------------------------------------------------|
772
+ | No content shift | 9 | Skeleton matches Overview structure cell-for-cell |
773
+ | Theme parity | 10 | Both themes get visible bars (the original sin of round 11 plan) |
774
+ | Restraint | 9 | No shimmer-gradient, no animation noise, just 1.6s opacity drift |
775
+ | Design-system cohesion | 9 | Same pulse rhythm as brand pulse + health banner amber |
776
+ | Accessibility | 9 | prefers-reduced-motion respected on both classes |
777
+
778
+ **Deductions**:
779
+ - −0.5: skeleton shows the FULL Overview (8+ blocks). Most actual
780
+ page-loads complete in <300ms so user barely sees this. Slower
781
+ hubs may see the whole thing; some users might prefer a shorter
782
+ skeleton. Could trim agent grid to 2 cards if it feels long in
783
+ practice.
784
+ - −0.5: the agent-card skeleton is generic (status dot + alias bar
785
+ + 3 detail bars). Real cards carry status chip + agent type +
786
+ server hostname + uptime — could mirror more specifically.
787
+
788
+ ### Round 13 plan: **Tasks status tabs — color coding**
789
+
790
+ The Tasks page filter tab strip (`All / created / delivered / acked /
791
+ running / replied / closed / failed / cancelled / expired`) is all
792
+ neutral-styled — no visual scannability. Color-code each by its
793
+ status family using the same tokens as the chips system used
794
+ elsewhere (running=green, replied=purple, failed=red, etc.), so the
795
+ user can spot "failed" without reading every label.
796
+
797
+ Estimated work: 20 min. Fires next `*/5`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sleep2agi/agent-network-dashboard",
3
- "version": "0.4.5-preview.0",
3
+ "version": "0.4.5-preview.2",
4
4
  "description": "Agent Network Dashboard — Web UI for managing AI Agent networks",
5
5
  "scripts": {
6
6
  "dev": "next dev",
@@ -1,9 +0,0 @@
1
- module.exports=[18622,(a,b,c)=>{b.exports=a.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},56704,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/work-async-storage.external.js",()=>require("next/dist/server/app-render/work-async-storage.external.js"))},32319,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/work-unit-async-storage.external.js",()=>require("next/dist/server/app-render/work-unit-async-storage.external.js"))},24725,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/after-task-async-storage.external.js",()=>require("next/dist/server/app-render/after-task-async-storage.external.js"))},20635,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/action-async-storage.external.js",()=>require("next/dist/server/app-render/action-async-storage.external.js"))},43285,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/dynamic-access-async-storage.external.js",()=>require("next/dist/server/app-render/dynamic-access-async-storage.external.js"))},42602,(a,b,c)=>{"use strict";b.exports=a.r(18622)},87924,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored["react-ssr"].ReactJsxRuntime},72131,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored["react-ssr"].React},9270,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored.contexts.AppRouterContext},38783,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored["react-ssr"].ReactServerDOMTurbopackClient},36313,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored.contexts.HooksClientContext},18341,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored.contexts.ServerInsertedHtml},22397,a=>{"use strict";var b=a.i(87924),c=a.i(72131);let d=(0,c.createContext)({networkId:"",setNetworkId:()=>{}});a.s(["NetworkProvider",0,function({children:a}){let[e,f]=(0,c.useState)("");return(0,c.useEffect)(()=>{let a=sessionStorage.getItem("anet_network_id");a&&f(a)},[]),(0,b.jsx)(d.Provider,{value:{networkId:e,setNetworkId:a=>{f(a),sessionStorage.setItem("anet_network_id",a)}},children:a})},"useNetworkId",0,function(){return(0,c.useContext)(d)}])},76194,a=>{"use strict";var b=a.i(87924),c=a.i(72131);let d=[{id:"cyber",label:"Cyber",emoji:"🌃",desc:"éģ˜čŽ¤æˇąč‰˛"},{id:"light",label:"Light",emoji:"â˜€ī¸",desc:"æĩ…č‰˛įŽ€æ´"},{id:"mint",label:"Mint",emoji:"đŸŒŋ",desc:"薄荷įģŋ"},{id:"sunset",label:"Sunset",emoji:"🌅",desc:"æš–č‰˛æŠ™į´Ģ"}],e="anet-theme";function f(a){"u">typeof document&&document.documentElement.setAttribute("data-theme",a)}a.s(["ThemeProvider",0,function({children:a}){return(0,c.useEffect)(()=>{f(localStorage.getItem(e)||"cyber")},[]),(0,b.jsx)(b.Fragment,{children:a})},"ThemeSwitcher",0,function({compact:a=!1}){let[g,h]=(0,c.useState)("cyber"),[i,j]=(0,c.useState)(!1);(0,c.useEffect)(()=>{let a=localStorage.getItem(e)||"cyber";h(a),f(a)},[]);let k=d.find(a=>a.id===g)||d[0];return(0,b.jsxs)("div",{className:"relative",children:[(0,b.jsxs)("button",{"aria-label":"切æĸä¸ģéĸ˜",onClick:()=>j(!i),className:"px-2.5 py-1.5 rounded-md text-xs flex items-center gap-1.5 hover:opacity-80 transition-opacity",style:{background:"var(--bg-elevated)",color:"var(--fg)",border:"1px solid var(--border)"},children:[(0,b.jsx)("span",{"aria-hidden":!0,children:k.emoji}),!a&&(0,b.jsx)("span",{children:k.label})]}),i&&(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)("div",{className:"fixed inset-0 z-40",onClick:()=>j(!1)}),(0,b.jsx)("div",{className:"absolute right-0 top-full mt-1 z-50 rounded-md min-w-[160px] py-1 shadow-lg",style:{background:"var(--bg-secondary)",border:"1px solid var(--border)"},children:d.map(a=>(0,b.jsxs)("button",{onClick:()=>{var b;h(b=a.id),localStorage.setItem(e,b),f(b),j(!1)},className:"w-full px-3 py-2 text-left text-xs flex items-center gap-2 hover:opacity-80",style:{background:a.id===g?"var(--bg-elevated)":"transparent",color:"var(--fg)"},children:[(0,b.jsx)("span",{"aria-hidden":!0,children:a.emoji}),(0,b.jsx)("span",{className:"flex-1",children:a.label}),(0,b.jsx)("span",{style:{color:"var(--fg-dim)"},className:"text-[10px]",children:a.desc}),a.id===g&&(0,b.jsx)("span",{style:{color:"var(--accent)"},children:"â€ĸ"})]},a.id))})]})]})}])},42588,a=>{"use strict";var b=a.i(87924),c=a.i(50944),d=a.i(38246),e=a.i(72131),f=a.i(72596),g=a.i(22397),h=a.i(76194);let i=a=>fetch(a).then(a=>a.ok?a.json():{networks:[]}),j=[{href:"/",label:"Overview",icon:"M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"},{href:"/tasks",label:"Tasks",icon:"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"},{href:"/nodes",label:"Nodes",icon:"M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2m-2-4h.01M17 16h.01"},{href:"/messages",label:"Messages",icon:"M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"},{href:"/settings/networks",label:"Networks",icon:"M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9"},{href:"/logs",label:"Audit Log",icon:"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"},{href:"/server-logs",label:"Server Logs",icon:"M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"},{href:"/admin",label:"Admin",icon:"M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"},{href:"/settings",label:"Settings",icon:"M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.066 2.573c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.573 1.066c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.066-2.573c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z M15 12a3 3 0 11-6 0 3 3 0 016 0z"}],k={owner:"⭐",admin:"🔧",member:"👤",viewer:"👁"};function l(){let a=(0,c.usePathname)(),[l,m]=(0,e.useState)(!1),[o,p]=(0,e.useState)(!1),{networkId:q,setNetworkId:r}=(0,g.useNetworkId)(),{data:s}=(0,f.default)("/api/hub/networks",i,{refreshInterval:15e3,dedupingInterval:1e4}),t=s?.networks||[],u=(0,b.jsx)("nav",{className:"flex flex-col gap-1 px-2 py-4",children:j.map(c=>{var e;return(0,b.jsxs)(d.default,{href:c.href,prefetch:!1,onClick:()=>p(!1),className:`relative flex items-center gap-3 px-3 py-3 rounded-lg text-sm transition-colors active:bg-[#1a1a3a] ${("/"===(e=c.href)?"/"===a:"/settings"===e?"/settings"===a:a.startsWith(e))?"bg-cyan-500/10 text-cyan-300 border border-cyan-500/20 anet-nav-active":"text-gray-400 hover:text-gray-200 hover:bg-[#1a1a2a]"} ${l?"justify-center":""}`,children:[(0,b.jsx)("svg",{className:"w-5 h-5 shrink-0",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,children:(0,b.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:c.icon})}),!l&&(0,b.jsx)("span",{children:c.label})]},c.href)})});return(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)("button",{onClick:()=>p(!o),className:"fixed top-4 left-3 z-50 lg:hidden bg-[#111128] border border-[#2a2a4a] rounded-lg p-2.5 text-gray-400 hover:text-white active:bg-[#1a1a3a]","aria-label":"Toggle menu",children:(0,b.jsx)("svg",{className:"w-5 h-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:o?(0,b.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M6 18L18 6M6 6l12 12"}):(0,b.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M4 6h16M4 12h16M4 18h16"})})}),o&&(0,b.jsx)("div",{className:"fixed inset-0 bg-black/50 z-30 lg:hidden",onClick:()=>p(!1)}),(0,b.jsxs)("aside",{"data-anet-sidebar":"true",className:`
2
- fixed top-0 left-0 h-full z-40 bg-[#0d0d1a] border-r border-[#2a2a4a]
3
- transition-all duration-200
4
- ${l?"w-16":"w-52"}
5
- ${o?"translate-x-0":"-translate-x-full"}
6
- lg:translate-x-0 lg:static lg:shrink-0
7
- `,children:[(0,b.jsx)(n,{collapsed:l}),(0,b.jsx)("div",{className:"border-b border-[#2a2a4a]"}),!l&&t.length>0&&(0,b.jsxs)("div",{className:"px-2 py-3 border-b border-[#2a2a4a]",children:[(0,b.jsx)("div",{className:"px-3 text-[10px] text-gray-600 uppercase mb-2",children:"Networks"}),(0,b.jsx)("div",{className:"space-y-0.5 max-h-32 overflow-y-auto",children:t.map(a=>(0,b.jsxs)("button",{onClick:()=>{r(a.network_id),p(!1)},className:`w-full flex items-center gap-2 px-3 py-1.5 rounded-md text-xs transition-colors text-left ${q===a.network_id?"bg-cyan-500/10 text-cyan-300":"text-gray-500 hover:text-gray-300 hover:bg-[#1a1a2a]"}`,children:[(0,b.jsx)("span",{children:k[a.role||"member"]||"👤"}),(0,b.jsx)("span",{className:"truncate",children:a.network_name})]},a.network_id))})]}),(0,b.jsx)("div",{className:"pb-20",children:u}),(0,b.jsxs)("div",{className:"absolute bottom-0 left-0 right-0 border-t border-[#2a2a4a] bg-[#0d0d1a]",children:[!l&&(0,b.jsxs)("button",{onClick:async()=>{await fetch("/api/auth/logout",{method:"POST"}).catch(()=>{}),sessionStorage.removeItem("anet_v3_auth"),window.location.assign("/login")},className:"w-full flex items-center gap-3 px-5 py-3 text-xs text-gray-500 hover:text-red-400 hover:bg-red-500/5 transition-colors",children:[(0,b.jsx)("svg",{className:"w-4 h-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,children:(0,b.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15m3 0l3-3m0 0l-3-3m3 3H9"})}),"Sign out"]}),(0,b.jsxs)("div",{className:`flex items-center gap-2 px-3 py-2 ${l?"justify-center":"justify-between"}`,children:[(0,b.jsx)(h.ThemeSwitcher,{compact:l}),(0,b.jsx)("button",{onClick:()=>m(!l),className:"hidden lg:flex p-1.5 rounded text-gray-600 hover:text-gray-400 transition-colors","aria-label":l?"Expand sidebar":"Collapse sidebar",children:(0,b.jsx)("svg",{className:`w-4 h-4 transition-transform ${l?"rotate-180":""}`,fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:(0,b.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M15 19l-7-7 7-7"})})})]})]})]})]})}let m=a=>fetch(a).then(a=>a.ok?a.json():{sessions:[]});function n({collapsed:a}){let{data:c}=(0,f.default)("/api/hub/status",m,{refreshInterval:1e4,dedupingInterval:4e3}),e=c?.sessions||[],g=e.filter(a=>a.status&&"offline"!==a.status).length,h=e.length;return a?(0,b.jsx)(d.default,{href:"/",className:"block px-3 py-4 flex justify-center hover:opacity-80 transition-opacity","aria-label":"Agent Network — home",children:(0,b.jsx)(o,{size:32})}):(0,b.jsxs)(d.default,{href:"/",className:"block px-4 py-4 flex items-center gap-3 hover:bg-[#11112a]/40 transition-colors rounded-r-xl","aria-label":"Agent Network — home",children:[(0,b.jsx)(o,{size:32}),(0,b.jsxs)("div",{className:"min-w-0",children:[(0,b.jsx)("div",{className:"text-white text-[13px] font-semibold leading-tight",children:"Agent Network"}),(0,b.jsxs)("div",{className:"text-[10px] text-gray-500 flex items-center gap-1.5 mt-0.5",children:[(0,b.jsx)("span",{className:`inline-block w-1.5 h-1.5 rounded-full ${g>0?"bg-emerald-400 anet-brand-pulse":"bg-gray-600"}`,"aria-hidden":!0}),0===h?(0,b.jsx)("span",{children:"waiting for agents"}):(0,b.jsxs)("span",{children:[(0,b.jsx)("span",{className:"text-gray-300 font-medium tabular-nums",children:g}),(0,b.jsxs)("span",{className:"text-gray-600",children:["/",h]})," online"]})]})]})]})}function o({size:a}){return(0,b.jsxs)("svg",{width:a,height:a,viewBox:"0 0 32 32","aria-hidden":!0,className:"shrink-0",children:[(0,b.jsx)("circle",{cx:"16",cy:"16",r:"10",fill:"none",stroke:"currentColor",strokeWidth:"1.5",opacity:"0.2",className:"text-cyan-400"}),(0,b.jsx)("line",{x1:"16",y1:"10",x2:"10",y2:"20",stroke:"currentColor",strokeWidth:"1",opacity:"0.45",className:"text-cyan-400"}),(0,b.jsx)("line",{x1:"16",y1:"10",x2:"22",y2:"20",stroke:"currentColor",strokeWidth:"1",opacity:"0.45",className:"text-cyan-400"}),(0,b.jsx)("line",{x1:"10",y1:"20",x2:"22",y2:"20",stroke:"currentColor",strokeWidth:"1",opacity:"0.45",className:"text-cyan-400"}),(0,b.jsx)("circle",{cx:"16",cy:"10",r:"2.5",fill:"currentColor",className:"text-cyan-400"}),(0,b.jsx)("circle",{cx:"10",cy:"20",r:"2.5",fill:"currentColor",className:"text-green-400"}),(0,b.jsx)("circle",{cx:"22",cy:"20",r:"2.5",fill:"currentColor",className:"text-violet-400"})]})}let p=["/login"];a.s(["AppShell",0,function({children:a}){let d=(0,c.usePathname)();return p.includes(d)?(0,b.jsx)(b.Fragment,{children:a}):(0,b.jsxs)("div",{className:"flex min-h-screen",children:[(0,b.jsx)(l,{}),(0,b.jsx)("main",{className:"flex-1 min-w-0",children:a})]})}],42588)}];
8
-
9
- //# sourceMappingURL=%5Broot-of-the-server%5D__013i9e9._.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../node_modules/next/src/server/route-modules/app-page/module.compiled.js","../../../../node_modules/next/src/server/route-modules/app-page/vendored/ssr/react-jsx-runtime.ts","../../../../node_modules/next/src/server/route-modules/app-page/vendored/ssr/react.ts","../../../../node_modules/next/src/server/route-modules/app-page/vendored/contexts/app-router-context.ts","../../../../node_modules/next/src/server/route-modules/app-page/vendored/ssr/react-server-dom-turbopack-client.ts","../../../../node_modules/next/src/server/route-modules/app-page/vendored/contexts/hooks-client-context.ts","../../../../node_modules/next/src/server/route-modules/app-page/vendored/contexts/server-inserted-html.ts","../../../../app/lib/network-context.tsx","../../../../app/components/ThemeSwitcher.tsx","../../../../app/components/AppShell.tsx","../../../../app/components/Sidebar.tsx"],"sourcesContent":["if (process.env.NEXT_RUNTIME === 'edge') {\n module.exports = require('next/dist/server/route-modules/app-page/module.js')\n} else {\n if (process.env.__NEXT_EXPERIMENTAL_REACT) {\n if (process.env.NODE_ENV === 'development') {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo-experimental.runtime.dev.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page-experimental.runtime.dev.js')\n }\n } else {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page-experimental.runtime.prod.js')\n }\n }\n } else {\n if (process.env.NODE_ENV === 'development') {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo.runtime.dev.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page.runtime.dev.js')\n }\n } else {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo.runtime.prod.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page.runtime.prod.js')\n }\n }\n }\n}\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['react-ssr']!.ReactJsxRuntime\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['react-ssr']!.React\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['contexts'].AppRouterContext\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['react-ssr']!.ReactServerDOMTurbopackClient\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['contexts'].HooksClientContext\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['contexts'].ServerInsertedHtml\n","'use client';\n\nimport { createContext, useContext, useState, useEffect, ReactNode } from 'react';\n\ninterface NetworkContextType {\n networkId: string;\n setNetworkId: (id: string) => void;\n}\n\nconst NetworkContext = createContext<NetworkContextType>({ networkId: '', setNetworkId: () => {} });\n\nexport function NetworkProvider({ children }: { children: ReactNode }) {\n const [networkId, setNetworkId] = useState('');\n\n useEffect(() => {\n const saved = sessionStorage.getItem('anet_network_id');\n if (saved) setNetworkId(saved);\n }, []);\n\n const setAndPersist = (id: string) => {\n setNetworkId(id);\n sessionStorage.setItem('anet_network_id', id);\n };\n\n return (\n <NetworkContext.Provider value={{ networkId, setNetworkId: setAndPersist }}>\n {children}\n </NetworkContext.Provider>\n );\n}\n\nexport function useNetworkId() {\n return useContext(NetworkContext);\n}\n","'use client';\n\nimport { useEffect, useState } from 'react';\n\nconst THEMES = [\n { id: 'cyber', label: 'Cyber', emoji: '🌃', desc: 'éģ˜čŽ¤æˇąč‰˛' },\n { id: 'light', label: 'Light', emoji: 'â˜€ī¸', desc: 'æĩ…č‰˛įŽ€æ´' },\n { id: 'mint', label: 'Mint', emoji: 'đŸŒŋ', desc: '薄荷įģŋ' },\n { id: 'sunset', label: 'Sunset', emoji: '🌅', desc: 'æš–č‰˛æŠ™į´Ģ' },\n] as const;\n\ntype ThemeId = typeof THEMES[number]['id'];\nconst THEME_KEY = 'anet-theme';\n\nfunction applyTheme(theme: ThemeId) {\n if (typeof document !== 'undefined') {\n document.documentElement.setAttribute('data-theme', theme);\n }\n}\n\nexport function ThemeProvider({ children }: { children: React.ReactNode }) {\n // Apply persisted theme on first render so we don't flash dark before\n // user-selected light. Initial value comes from cookie/localStorage.\n useEffect(() => {\n const stored = (localStorage.getItem(THEME_KEY) as ThemeId) || 'cyber';\n applyTheme(stored);\n }, []);\n return <>{children}</>;\n}\n\nexport function ThemeSwitcher({ compact = false }: { compact?: boolean }) {\n const [theme, setTheme] = useState<ThemeId>('cyber');\n const [open, setOpen] = useState(false);\n\n useEffect(() => {\n const stored = (localStorage.getItem(THEME_KEY) as ThemeId) || 'cyber';\n setTheme(stored);\n applyTheme(stored);\n }, []);\n\n function pick(next: ThemeId) {\n setTheme(next);\n localStorage.setItem(THEME_KEY, next);\n applyTheme(next);\n setOpen(false);\n }\n\n const current = THEMES.find(t => t.id === theme) || THEMES[0];\n\n return (\n <div className=\"relative\">\n <button\n aria-label=\"切æĸä¸ģéĸ˜\"\n onClick={() => setOpen(!open)}\n className=\"px-2.5 py-1.5 rounded-md text-xs flex items-center gap-1.5 hover:opacity-80 transition-opacity\"\n style={{ background: 'var(--bg-elevated)', color: 'var(--fg)', border: '1px solid var(--border)' }}\n >\n <span aria-hidden>{current.emoji}</span>\n {!compact && <span>{current.label}</span>}\n </button>\n {open && (\n <>\n <div className=\"fixed inset-0 z-40\" onClick={() => setOpen(false)} />\n <div\n className=\"absolute right-0 top-full mt-1 z-50 rounded-md min-w-[160px] py-1 shadow-lg\"\n style={{ background: 'var(--bg-secondary)', border: '1px solid var(--border)' }}\n >\n {THEMES.map(t => (\n <button\n key={t.id}\n onClick={() => pick(t.id)}\n className=\"w-full px-3 py-2 text-left text-xs flex items-center gap-2 hover:opacity-80\"\n style={{\n background: t.id === theme ? 'var(--bg-elevated)' : 'transparent',\n color: 'var(--fg)',\n }}\n >\n <span aria-hidden>{t.emoji}</span>\n <span className=\"flex-1\">{t.label}</span>\n <span style={{ color: 'var(--fg-dim)' }} className=\"text-[10px]\">{t.desc}</span>\n {t.id === theme && <span style={{ color: 'var(--accent)' }}>â€ĸ</span>}\n </button>\n ))}\n </div>\n </>\n )}\n </div>\n );\n}\n","'use client';\n\nimport { usePathname } from 'next/navigation';\nimport { Sidebar } from './Sidebar';\n\nconst NO_SHELL_PATHS = ['/login'];\n\nexport function AppShell({ children }: { children: React.ReactNode }) {\n const pathname = usePathname();\n\n if (NO_SHELL_PATHS.includes(pathname)) {\n return <>{children}</>;\n }\n\n return (\n <div className=\"flex min-h-screen\">\n <Sidebar />\n <main className=\"flex-1 min-w-0\">{children}</main>\n </div>\n );\n}\n","'use client';\n\nimport Link from 'next/link';\nimport { usePathname } from 'next/navigation';\nimport { useState } from 'react';\nimport useSWR from 'swr';\nimport { useNetworkId } from '../lib/network-context';\nimport { ThemeSwitcher } from './ThemeSwitcher';\n\nconst networkFetcher = (url: string) => fetch(url).then(r => r.ok ? r.json() : { networks: [] });\n\nconst NAV_ITEMS = [\n { href: '/', label: 'Overview', icon: 'M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6' },\n { href: '/tasks', label: 'Tasks', icon: 'M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4' },\n { href: '/nodes', label: 'Nodes', icon: 'M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2m-2-4h.01M17 16h.01' },\n { href: '/messages', label: 'Messages', icon: 'M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z' },\n { href: '/settings/networks', label: 'Networks', icon: 'M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9' },\n { href: '/logs', label: 'Audit Log', icon: 'M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z' },\n { href: '/server-logs', label: 'Server Logs', icon: 'M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z' },\n { href: '/admin', label: 'Admin', icon: 'M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z' },\n { href: '/settings', label: 'Settings', icon: 'M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.066 2.573c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.573 1.066c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.066-2.573c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z M15 12a3 3 0 11-6 0 3 3 0 016 0z' },\n];\n\ninterface SidebarNetwork {\n network_id: string;\n network_name: string;\n role?: string;\n}\n\nconst ROLE_ICON: Record<string, string> = { owner: '⭐', admin: '🔧', member: '👤', viewer: '👁' };\n\nexport function Sidebar() {\n const pathname = usePathname();\n const [collapsed, setCollapsed] = useState(false);\n const [mobileOpen, setMobileOpen] = useState(false);\n const { networkId, setNetworkId } = useNetworkId();\n const { data: netData } = useSWR<{ networks: SidebarNetwork[] }>('/api/hub/networks', networkFetcher, { refreshInterval: 15000, dedupingInterval: 10000 });\n const networks = netData?.networks || [];\n\n const isActive = (href: string) => {\n if (href === '/') return pathname === '/';\n if (href === '/settings') return pathname === '/settings';\n return pathname.startsWith(href);\n };\n\n const nav = (\n <nav className=\"flex flex-col gap-1 px-2 py-4\">\n {NAV_ITEMS.map(item => (\n <Link\n key={item.href}\n href={item.href}\n prefetch={false}\n onClick={() => setMobileOpen(false)}\n className={`relative flex items-center gap-3 px-3 py-3 rounded-lg text-sm transition-colors active:bg-[#1a1a3a] ${\n isActive(item.href)\n ? 'bg-cyan-500/10 text-cyan-300 border border-cyan-500/20 anet-nav-active'\n : 'text-gray-400 hover:text-gray-200 hover:bg-[#1a1a2a]'\n } ${collapsed ? 'justify-center' : ''}`}\n >\n <svg className=\"w-5 h-5 shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d={item.icon} />\n </svg>\n {!collapsed && <span>{item.label}</span>}\n </Link>\n ))}\n </nav>\n );\n\n return (\n <>\n {/* Mobile hamburger */}\n <button\n onClick={() => setMobileOpen(!mobileOpen)}\n className=\"fixed top-4 left-3 z-50 lg:hidden bg-[#111128] border border-[#2a2a4a] rounded-lg p-2.5 text-gray-400 hover:text-white active:bg-[#1a1a3a]\"\n aria-label=\"Toggle menu\"\n >\n <svg className=\"w-5 h-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n {mobileOpen\n ? <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n : <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M4 6h16M4 12h16M4 18h16\" />}\n </svg>\n </button>\n\n {/* Mobile overlay */}\n {mobileOpen && (\n <div\n className=\"fixed inset-0 bg-black/50 z-30 lg:hidden\"\n onClick={() => setMobileOpen(false)}\n />\n )}\n\n {/* Sidebar — `bg-[#0d0d1a]` resolves to var(--bg) in dark themes,\n but in light/mint we want a distinct surface, so we layer\n `lg:bg-white` / `lg:dark:bg-[#0d0d1a]` via the theme attribute.\n The CSS shim in globals.css upgrades sidebar bg to bg-secondary\n in light themes so the sidebar reads as its own card. */}\n <aside data-anet-sidebar=\"true\" className={`\n fixed top-0 left-0 h-full z-40 bg-[#0d0d1a] border-r border-[#2a2a4a]\n transition-all duration-200\n ${collapsed ? 'w-16' : 'w-52'}\n ${mobileOpen ? 'translate-x-0' : '-translate-x-full'}\n lg:translate-x-0 lg:static lg:shrink-0\n `}>\n {/* Brand header — round 4: 3-node mesh mark matches /login,\n with an inline live \"online\" pulse so every page surfaces\n fleet health without leaving for /nodes. */}\n <SidebarBrand collapsed={collapsed} />\n <div className={`border-b border-[#2a2a4a]`} />\n\n {/* Network list */}\n {!collapsed && networks.length > 0 && (\n <div className=\"px-2 py-3 border-b border-[#2a2a4a]\">\n <div className=\"px-3 text-[10px] text-gray-600 uppercase mb-2\">Networks</div>\n <div className=\"space-y-0.5 max-h-32 overflow-y-auto\">\n {networks.map((n: SidebarNetwork) => (\n <button\n key={n.network_id}\n onClick={() => { setNetworkId(n.network_id); setMobileOpen(false); }}\n className={`w-full flex items-center gap-2 px-3 py-1.5 rounded-md text-xs transition-colors text-left ${\n networkId === n.network_id\n ? 'bg-cyan-500/10 text-cyan-300'\n : 'text-gray-500 hover:text-gray-300 hover:bg-[#1a1a2a]'\n }`}\n >\n <span>{ROLE_ICON[n.role || 'member'] || '👤'}</span>\n <span className=\"truncate\">{n.network_name}</span>\n </button>\n ))}\n </div>\n </div>\n )}\n\n <div className=\"pb-20\">\n {nav}\n </div>\n\n {/* Sign out + collapse */}\n <div className=\"absolute bottom-0 left-0 right-0 border-t border-[#2a2a4a] bg-[#0d0d1a]\">\n {!collapsed && (\n <button\n onClick={async () => {\n await fetch('/api/auth/logout', { method: 'POST' }).catch(() => {});\n sessionStorage.removeItem('anet_v3_auth');\n window.location.assign('/login');\n }}\n className=\"w-full flex items-center gap-3 px-5 py-3 text-xs text-gray-500 hover:text-red-400 hover:bg-red-500/5 transition-colors\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15m3 0l3-3m0 0l-3-3m3 3H9\" />\n </svg>\n Sign out\n </button>\n )}\n <div className={`flex items-center gap-2 px-3 py-2 ${collapsed ? 'justify-center' : 'justify-between'}`}>\n <ThemeSwitcher compact={collapsed} />\n <button\n onClick={() => setCollapsed(!collapsed)}\n className=\"hidden lg:flex p-1.5 rounded text-gray-600 hover:text-gray-400 transition-colors\"\n aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}\n >\n <svg className={`w-4 h-4 transition-transform ${collapsed ? 'rotate-180' : ''}`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n </div>\n </div>\n </aside>\n </>\n );\n}\n\ninterface StatusData {\n sessions?: Array<{ status?: string; alias?: string }>;\n}\n\nconst statusFetcher = (url: string) =>\n fetch(url).then(r => r.ok ? r.json() as Promise<StatusData> : { sessions: [] });\n\nfunction SidebarBrand({ collapsed }: { collapsed: boolean }) {\n // Live online count — re-uses the same /api/hub/status endpoint the\n // Overview already polls, so SWR dedupes the request. Pulse is muted —\n // emerald dot at 4px with a 1.6s slow opacity pulse, no glow, no halo.\n const { data } = useSWR<StatusData>('/api/hub/status', statusFetcher, {\n refreshInterval: 10000,\n dedupingInterval: 4000,\n });\n const sessions = data?.sessions || [];\n const online = sessions.filter(s => s.status && s.status !== 'offline').length;\n const total = sessions.length;\n\n if (collapsed) {\n return (\n <Link href=\"/\" className=\"block px-3 py-4 flex justify-center hover:opacity-80 transition-opacity\" aria-label=\"Agent Network — home\">\n <BrandMark size={32} />\n </Link>\n );\n }\n\n return (\n <Link\n href=\"/\"\n className=\"block px-4 py-4 flex items-center gap-3 hover:bg-[#11112a]/40 transition-colors rounded-r-xl\"\n aria-label=\"Agent Network — home\"\n >\n <BrandMark size={32} />\n <div className=\"min-w-0\">\n <div className=\"text-white text-[13px] font-semibold leading-tight\">Agent Network</div>\n <div className=\"text-[10px] text-gray-500 flex items-center gap-1.5 mt-0.5\">\n <span\n className={`inline-block w-1.5 h-1.5 rounded-full ${online > 0 ? 'bg-emerald-400 anet-brand-pulse' : 'bg-gray-600'}`}\n aria-hidden\n />\n {total === 0 ? (\n <span>waiting for agents</span>\n ) : (\n <span><span className=\"text-gray-300 font-medium tabular-nums\">{online}</span><span className=\"text-gray-600\">/{total}</span> online</span>\n )}\n </div>\n </div>\n </Link>\n );\n}\n\n/** 3-node mesh mark — same SVG as /login, reusable. */\nfunction BrandMark({ size }: { size: number }) {\n return (\n <svg width={size} height={size} viewBox=\"0 0 32 32\" aria-hidden className=\"shrink-0\">\n <circle cx=\"16\" cy=\"16\" r=\"10\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" opacity=\"0.2\" className=\"text-cyan-400\" />\n <line x1=\"16\" y1=\"10\" x2=\"10\" y2=\"20\" stroke=\"currentColor\" strokeWidth=\"1\" opacity=\"0.45\" className=\"text-cyan-400\" />\n <line x1=\"16\" y1=\"10\" x2=\"22\" y2=\"20\" stroke=\"currentColor\" strokeWidth=\"1\" opacity=\"0.45\" className=\"text-cyan-400\" />\n <line x1=\"10\" y1=\"20\" x2=\"22\" y2=\"20\" stroke=\"currentColor\" strokeWidth=\"1\" opacity=\"0.45\" className=\"text-cyan-400\" />\n <circle cx=\"16\" cy=\"10\" r=\"2.5\" fill=\"currentColor\" className=\"text-cyan-400\" />\n <circle cx=\"10\" cy=\"20\" r=\"2.5\" fill=\"currentColor\" className=\"text-green-400\" />\n <circle cx=\"22\" cy=\"20\" r=\"2.5\" fill=\"currentColor\" className=\"text-violet-400\" />\n </svg>\n );\n}\n"],"names":["process","env","NEXT_RUNTIME","module","exports","require","__NEXT_EXPERIMENTAL_REACT","NODE_ENV","TURBOPACK","vendored","ReactJsxRuntime","React","AppRouterContext","ReactServerDOMTurbopackClient","HooksClientContext","ServerInsertedHtml","NetworkContext","networkId","setNetworkId","NetworkProvider","children","saved","sessionStorage","getItem","setAndPersist","id","setItem","Provider","value","useNetworkId","THEMES","label","emoji","desc","THEME_KEY","applyTheme","theme","document","documentElement","setAttribute","ThemeProvider","stored","localStorage","ThemeSwitcher","compact","setTheme","open","setOpen","pick","next","current","find","t","className","onClick","style","background","color","border","map","networkFetcher","url","fetch","then","r","ok","json","networks","NAV_ITEMS","href","icon","ROLE_ICON","owner","admin","member","viewer","Sidebar","pathname","collapsed","setCollapsed","mobileOpen","setMobileOpen","data","netData","refreshInterval","dedupingInterval","isActive","startsWith","nav","item","prefetch","fill","viewBox","stroke","strokeWidth","strokeLinecap","strokeLinejoin","d","SidebarBrand","length","n","network_id","role","network_name","method","catch","removeItem","window","location","assign","statusFetcher","sessions","online","filter","s","status","total","BrandMark","size","width","height","cx","cy","opacity","x1","y1","x2","y2"],"mappings":"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","ignoreList":[0,1,2,3,4,5,6]}