@sleep2agi/agent-network-dashboard 0.4.4-preview.0 → 0.4.5-preview.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +6 -6
- package/.next/diagnostics/route-bundle-stats.json +106 -92
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/prerender-manifest.json +3 -3
- package/.next/server/app/_global-error/page/build-manifest.json +3 -3
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page/build-manifest.json +3 -3
- package/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +2 -2
- package/.next/server/app/_not-found.rsc +12 -12
- package/.next/server/app/_not-found.segments/_full.segment.rsc +12 -12
- package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/server/app/_not-found.segments/_index.segment.rsc +7 -7
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin/page/build-manifest.json +3 -3
- package/.next/server/app/admin/page.js.nft.json +1 -1
- package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
- package/.next/server/app/admin.html +2 -2
- package/.next/server/app/admin.rsc +14 -14
- package/.next/server/app/admin.segments/_full.segment.rsc +14 -14
- package/.next/server/app/admin.segments/_head.segment.rsc +4 -4
- package/.next/server/app/admin.segments/_index.segment.rsc +7 -7
- package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/admin.segments/admin.segment.rsc +3 -3
- package/.next/server/app/index.html +2 -2
- package/.next/server/app/index.rsc +14 -14
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/index.segments/_full.segment.rsc +14 -14
- package/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/server/app/index.segments/_index.segment.rsc +7 -7
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login/page/build-manifest.json +3 -3
- package/.next/server/app/login/page.js.nft.json +1 -1
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login.html +2 -2
- package/.next/server/app/login.rsc +14 -14
- package/.next/server/app/login.segments/_full.segment.rsc +14 -14
- package/.next/server/app/login.segments/_head.segment.rsc +4 -4
- package/.next/server/app/login.segments/_index.segment.rsc +7 -7
- package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/login.segments/login.segment.rsc +3 -3
- package/.next/server/app/logs/page/build-manifest.json +3 -3
- package/.next/server/app/logs/page.js.nft.json +1 -1
- package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/logs.html +2 -2
- package/.next/server/app/logs.rsc +14 -14
- package/.next/server/app/logs.segments/_full.segment.rsc +14 -14
- package/.next/server/app/logs.segments/_head.segment.rsc +4 -4
- package/.next/server/app/logs.segments/_index.segment.rsc +7 -7
- package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/logs.segments/logs.segment.rsc +3 -3
- package/.next/server/app/messages/page/build-manifest.json +3 -3
- package/.next/server/app/messages/page.js.nft.json +1 -1
- package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
- package/.next/server/app/messages.html +2 -2
- package/.next/server/app/messages.rsc +14 -14
- package/.next/server/app/messages.segments/_full.segment.rsc +14 -14
- package/.next/server/app/messages.segments/_head.segment.rsc +4 -4
- package/.next/server/app/messages.segments/_index.segment.rsc +7 -7
- package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/messages.segments/messages.segment.rsc +3 -3
- package/.next/server/app/node/page/build-manifest.json +3 -3
- package/.next/server/app/node/page.js.nft.json +1 -1
- package/.next/server/app/node/page_client-reference-manifest.js +1 -1
- package/.next/server/app/node.html +2 -2
- package/.next/server/app/node.rsc +14 -14
- package/.next/server/app/node.segments/_full.segment.rsc +14 -14
- package/.next/server/app/node.segments/_head.segment.rsc +4 -4
- package/.next/server/app/node.segments/_index.segment.rsc +7 -7
- package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/node.segments/node.segment.rsc +3 -3
- package/.next/server/app/nodes/page/build-manifest.json +3 -3
- package/.next/server/app/nodes/page.js.nft.json +1 -1
- package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
- package/.next/server/app/nodes.html +2 -2
- package/.next/server/app/nodes.rsc +14 -14
- package/.next/server/app/nodes.segments/_full.segment.rsc +14 -14
- package/.next/server/app/nodes.segments/_head.segment.rsc +4 -4
- package/.next/server/app/nodes.segments/_index.segment.rsc +7 -7
- package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/nodes.segments/nodes.segment.rsc +3 -3
- package/.next/server/app/page/build-manifest.json +3 -3
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs/page/build-manifest.json +3 -3
- package/.next/server/app/server-logs/page.js.nft.json +1 -1
- package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs.html +2 -2
- package/.next/server/app/server-logs.rsc +14 -14
- package/.next/server/app/server-logs.segments/_full.segment.rsc +14 -14
- package/.next/server/app/server-logs.segments/_head.segment.rsc +4 -4
- package/.next/server/app/server-logs.segments/_index.segment.rsc +7 -7
- package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/server-logs.segments/server-logs.segment.rsc +3 -3
- package/.next/server/app/settings/networks/page/build-manifest.json +3 -3
- package/.next/server/app/settings/networks/page.js.nft.json +1 -1
- package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/networks.html +2 -2
- package/.next/server/app/settings/networks.rsc +14 -14
- package/.next/server/app/settings/networks.segments/_full.segment.rsc +14 -14
- package/.next/server/app/settings/networks.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings/networks.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +3 -3
- package/.next/server/app/settings/networks.segments/settings.segment.rsc +3 -3
- package/.next/server/app/settings/page/build-manifest.json +3 -3
- package/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens/page/build-manifest.json +3 -3
- package/.next/server/app/settings/tokens/page.js.nft.json +1 -1
- package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens.html +2 -2
- package/.next/server/app/settings/tokens.rsc +14 -14
- package/.next/server/app/settings/tokens.segments/_full.segment.rsc +14 -14
- package/.next/server/app/settings/tokens.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings/tokens.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +3 -3
- package/.next/server/app/settings/tokens.segments/settings.segment.rsc +3 -3
- package/.next/server/app/settings.html +2 -2
- package/.next/server/app/settings.rsc +14 -14
- package/.next/server/app/settings.segments/_full.segment.rsc +14 -14
- package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings.segments/_index.segment.rsc +7 -7
- package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
- package/.next/server/app/tasks/[id]/page/build-manifest.json +3 -3
- package/.next/server/app/tasks/[id]/page.js.nft.json +1 -1
- package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks/page/build-manifest.json +3 -3
- package/.next/server/app/tasks/page.js.nft.json +1 -1
- package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks.html +2 -2
- package/.next/server/app/tasks.rsc +14 -14
- package/.next/server/app/tasks.segments/_full.segment.rsc +14 -14
- package/.next/server/app/tasks.segments/_head.segment.rsc +4 -4
- package/.next/server/app/tasks.segments/_index.segment.rsc +7 -7
- package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/tasks.segments/tasks.segment.rsc +3 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0_jnflc._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0_jnflc._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0a0ffmv._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0a0ffmv._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__12mpoig._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__12mpoig._.js.map +1 -0
- package/.next/server/chunks/ssr/_0d-fuox._.js +3 -0
- package/.next/server/chunks/ssr/_0d-fuox._.js.map +1 -0
- package/.next/server/chunks/ssr/app_0.0wpa~._.js +3 -0
- package/.next/server/chunks/ssr/app_0.0wpa~._.js.map +1 -0
- package/.next/server/chunks/ssr/app_0dk5wao._.js +1 -1
- package/.next/server/chunks/ssr/app_0dk5wao._.js.map +1 -1
- package/.next/server/chunks/ssr/app_0et5yua._.js +3 -0
- package/.next/server/chunks/ssr/app_0et5yua._.js.map +1 -0
- package/.next/server/chunks/ssr/app_0ff~kjj._.js +9 -0
- package/.next/server/chunks/ssr/app_0ff~kjj._.js.map +1 -0
- package/.next/server/chunks/ssr/app_0izi28j._.js +3 -0
- package/.next/server/chunks/ssr/app_0izi28j._.js.map +1 -0
- package/.next/server/chunks/ssr/app_components_08ys5y3._.js +9 -0
- package/.next/server/chunks/ssr/app_components_08ys5y3._.js.map +1 -0
- package/.next/server/chunks/ssr/app_login_page_tsx_0z71ad3._.js +1 -1
- package/.next/server/chunks/ssr/app_login_page_tsx_0z71ad3._.js.map +1 -1
- package/.next/server/chunks/ssr/app_page_tsx_0es_sk2._.js +1 -1
- package/.next/server/chunks/ssr/app_page_tsx_0es_sk2._.js.map +1 -1
- package/.next/server/chunks/ssr/app_tasks_page_tsx_0z-d6mp._.js +1 -1
- package/.next/server/chunks/ssr/app_tasks_page_tsx_0z-d6mp._.js.map +1 -1
- package/.next/server/chunks/ssr/node_modules_0ck2~9g._.js +3 -0
- package/.next/server/chunks/ssr/node_modules_0ck2~9g._.js.map +1 -0
- package/.next/server/middleware-build-manifest.js +6 -6
- package/.next/server/pages/404.html +2 -2
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/0257pdz1-imal.js +2 -0
- package/.next/static/chunks/02flrewxlf_m_.js +1 -0
- package/.next/static/chunks/051gslfjka1kj.js +1 -0
- package/.next/static/chunks/06t_vzei8s9_h.js +1 -0
- package/.next/static/chunks/0a1wbl-spby3_.css +2 -0
- package/.next/static/chunks/0e-.zgw81gela.js +31 -0
- package/.next/static/chunks/0e7c40p~wq665.js +1 -0
- package/.next/static/chunks/0g7m7zk.v7g6h.js +1 -0
- package/.next/static/chunks/0gs9-~h7-pkuu.js +7 -0
- package/.next/static/chunks/0j3s_1ee66awv.js +1 -0
- package/.next/static/chunks/0khpyxpdrp~ty.js +1 -0
- package/.next/static/chunks/0lo_g.q1fm-hr.js +7 -0
- package/.next/static/chunks/0w1zwt8kq_7nb.js +1 -0
- package/.next/static/chunks/1031v6nw33ud3.js +1 -0
- package/.next/static/chunks/13.dst7liziwo.js +1 -0
- package/.next/static/chunks/{turbopack-0vsvjs02l449s.js → turbopack-01f1xs~cq_~si.js} +1 -1
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/components/AppShell.tsx +9 -1
- package/app/components/CommandPalette.tsx +316 -0
- package/app/components/EmptyState.tsx +189 -0
- package/app/components/HealthBanner.tsx +132 -0
- package/app/components/HelpOverlay.tsx +121 -0
- package/app/components/LoadingSkeleton.tsx +81 -40
- package/app/components/Sidebar.tsx +90 -11
- package/app/components/TopoGraph.tsx +151 -62
- package/app/components/UserBar.tsx +16 -2
- package/app/globals.css +175 -0
- package/app/login/page.tsx +26 -13
- package/app/logs/page.tsx +2 -5
- package/app/messages/page.tsx +2 -5
- package/app/nodes/page.tsx +6 -1
- package/app/page.tsx +109 -12
- package/app/settings/networks/page.tsx +6 -1
- package/app/settings/page.tsx +56 -29
- package/app/settings/tokens/page.tsx +6 -1
- package/app/tasks/page.tsx +39 -14
- package/docs/loop-design-rounds.md +797 -0
- package/docs/oss-readiness-report.md +189 -0
- package/docs/screenshots/0.4.5-preview.1/cyber-admin.png +0 -0
- package/docs/screenshots/0.4.5-preview.1/cyber-cmdk-search.png +0 -0
- package/docs/screenshots/0.4.5-preview.1/cyber-cmdk.png +0 -0
- package/docs/screenshots/0.4.5-preview.1/cyber-login.png +0 -0
- package/docs/screenshots/0.4.5-preview.1/cyber-overview.png +0 -0
- package/docs/screenshots/0.4.5-preview.1/cyber-settings.png +0 -0
- package/docs/screenshots/0.4.5-preview.1/cyber-tasks.png +0 -0
- package/docs/screenshots/0.4.5-preview.1/light-admin.png +0 -0
- package/docs/screenshots/0.4.5-preview.1/light-cmdk-search.png +0 -0
- package/docs/screenshots/0.4.5-preview.1/light-cmdk.png +0 -0
- package/docs/screenshots/0.4.5-preview.1/light-login.png +0 -0
- package/docs/screenshots/0.4.5-preview.1/light-overview.png +0 -0
- package/docs/screenshots/0.4.5-preview.1/light-settings.png +0 -0
- package/docs/screenshots/0.4.5-preview.1/light-tasks.png +0 -0
- package/package.json +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__093ymui._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__093ymui._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0i1gizm._.js +0 -9
- package/.next/server/chunks/ssr/[root-of-the-server]__0i1gizm._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0~yad5w._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0~yad5w._.js.map +0 -1
- package/.next/server/chunks/ssr/_06_xh1~._.js +0 -3
- package/.next/server/chunks/ssr/_06_xh1~._.js.map +0 -1
- package/.next/server/chunks/ssr/app_01vhyfx._.js +0 -9
- package/.next/server/chunks/ssr/app_01vhyfx._.js.map +0 -1
- package/.next/server/chunks/ssr/app_023a94i._.js +0 -3
- package/.next/server/chunks/ssr/app_023a94i._.js.map +0 -1
- package/.next/server/chunks/ssr/app_0basiqb._.js +0 -3
- package/.next/server/chunks/ssr/app_0basiqb._.js.map +0 -1
- package/.next/server/chunks/ssr/app_0pljk5o._.js +0 -3
- package/.next/server/chunks/ssr/app_0pljk5o._.js.map +0 -1
- package/.next/server/chunks/ssr/node_modules_next_dist_0t-hj0x._.js +0 -3
- package/.next/server/chunks/ssr/node_modules_next_dist_0t-hj0x._.js.map +0 -1
- package/.next/static/chunks/0.z~9klrgd.t-.js +0 -1
- package/.next/static/chunks/08aj9~75raaah.js +0 -7
- package/.next/static/chunks/08iom_z8w-wmz.js +0 -7
- package/.next/static/chunks/08v0-ki6vwpxf.js +0 -1
- package/.next/static/chunks/0dkkv90do9a4r.js +0 -1
- package/.next/static/chunks/0e-wrhqh4h3r5.js +0 -2
- package/.next/static/chunks/0ejz4zwhu3a3y.js +0 -1
- package/.next/static/chunks/0o5zj~5vjeks3.js +0 -1
- package/.next/static/chunks/0uqfv6rc-xdru.js +0 -1
- package/.next/static/chunks/0u~_.32f.midj.css +0 -2
- package/.next/static/chunks/0xrnwfefpke-g.js +0 -31
- package/.next/static/chunks/0y_po~f~fk~ap.js +0 -1
- package/.next/static/chunks/14sm.ta0zylsj.js +0 -1
- package/.next/static/chunks/18ac93ii3mjlj.js +0 -1
- /package/.next/static/{jTh5m77FIfQccc0gftvik → wcTnZXyx_R19_Ur1_cGMP}/_buildManifest.js +0 -0
- /package/.next/static/{jTh5m77FIfQccc0gftvik → wcTnZXyx_R19_Ur1_cGMP}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{jTh5m77FIfQccc0gftvik → wcTnZXyx_R19_Ur1_cGMP}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
|
|
5
|
+
/** Help overlay — press `?` to see keyboard shortcuts.
|
|
6
|
+
* Restrained: no animation noise, single column, all global keys in one
|
|
7
|
+
* place. Closes on Esc or `?` again or click-outside.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
interface Shortcut {
|
|
11
|
+
keys: string[];
|
|
12
|
+
label: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const SHORTCUTS: { group: string; items: Shortcut[] }[] = [
|
|
16
|
+
{
|
|
17
|
+
group: 'Global',
|
|
18
|
+
items: [
|
|
19
|
+
{ keys: ['⌘', 'K'], label: 'Open command palette (also Ctrl+K)' },
|
|
20
|
+
{ keys: ['/'], label: 'Open command palette' },
|
|
21
|
+
{ keys: ['?'], label: 'Toggle this help overlay' },
|
|
22
|
+
{ keys: ['Esc'], label: 'Close any open modal' },
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
group: 'Command palette',
|
|
27
|
+
items: [
|
|
28
|
+
{ keys: ['↑', '↓'], label: 'Move selection' },
|
|
29
|
+
{ keys: ['↵'], label: 'Activate selected command' },
|
|
30
|
+
{ keys: ['type'], label: 'Filter — searches commands, agents, tasks' },
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
group: 'Pages',
|
|
35
|
+
items: [
|
|
36
|
+
{ keys: ['click', 'sidebar logo'], label: 'Back to Overview' },
|
|
37
|
+
{ keys: ['Cmd+K', 'Go to agent X'], label: 'Jump straight to a node' },
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
export function HelpOverlay() {
|
|
43
|
+
const [open, setOpen] = useState(false);
|
|
44
|
+
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
const onKey = (e: KeyboardEvent) => {
|
|
47
|
+
// `?` toggles — Shift+/ on US layout. Only when no input is focused.
|
|
48
|
+
if (e.key === '?' && document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {
|
|
49
|
+
e.preventDefault();
|
|
50
|
+
setOpen(prev => !prev);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (e.key === 'Escape' && open) {
|
|
54
|
+
setOpen(false);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
window.addEventListener('keydown', onKey);
|
|
58
|
+
return () => window.removeEventListener('keydown', onKey);
|
|
59
|
+
}, [open]);
|
|
60
|
+
|
|
61
|
+
if (!open) return null;
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<div
|
|
65
|
+
role="dialog"
|
|
66
|
+
aria-modal="true"
|
|
67
|
+
aria-label="Keyboard shortcuts"
|
|
68
|
+
className="anet-help fixed inset-0 z-[101] flex items-center justify-center px-4"
|
|
69
|
+
onClick={() => setOpen(false)}
|
|
70
|
+
>
|
|
71
|
+
<div className="absolute inset-0 bg-black/50 backdrop-blur-sm" aria-hidden />
|
|
72
|
+
<div
|
|
73
|
+
className="relative w-full max-w-md rounded-xl border border-[#2a2a4a] bg-[#0d0d1a] shadow-2xl shadow-black/40 overflow-hidden"
|
|
74
|
+
onClick={e => e.stopPropagation()}
|
|
75
|
+
>
|
|
76
|
+
<div className="flex items-center justify-between border-b border-[#2a2a4a] px-4 py-2.5">
|
|
77
|
+
<div className="flex items-center gap-2 text-sm font-medium text-gray-200">
|
|
78
|
+
<svg width="14" height="14" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="1.5" className="text-gray-500">
|
|
79
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
80
|
+
</svg>
|
|
81
|
+
Keyboard shortcuts
|
|
82
|
+
</div>
|
|
83
|
+
<button
|
|
84
|
+
onClick={() => setOpen(false)}
|
|
85
|
+
aria-label="Close help"
|
|
86
|
+
className="text-gray-500 hover:text-gray-300 text-lg leading-none px-1"
|
|
87
|
+
>
|
|
88
|
+
×
|
|
89
|
+
</button>
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
<div className="px-4 py-3 max-h-[70vh] overflow-y-auto">
|
|
93
|
+
{SHORTCUTS.map(g => (
|
|
94
|
+
<div key={g.group} className="mb-3 last:mb-0">
|
|
95
|
+
<div className="text-[10px] uppercase tracking-[0.12em] text-gray-600 mb-1.5">{g.group}</div>
|
|
96
|
+
<ul className="space-y-1.5">
|
|
97
|
+
{g.items.map((s, i) => (
|
|
98
|
+
<li key={i} className="flex items-center gap-3 text-xs">
|
|
99
|
+
<span className="flex items-center gap-1">
|
|
100
|
+
{s.keys.map((k, ki) => (
|
|
101
|
+
<kbd key={ki} className="text-[10px] font-mono border border-[#2a2a4a] rounded px-1.5 py-0.5 text-gray-400 bg-[#1a1a2a]/40">
|
|
102
|
+
{k}
|
|
103
|
+
</kbd>
|
|
104
|
+
))}
|
|
105
|
+
</span>
|
|
106
|
+
<span className="text-gray-400 flex-1">{s.label}</span>
|
|
107
|
+
</li>
|
|
108
|
+
))}
|
|
109
|
+
</ul>
|
|
110
|
+
</div>
|
|
111
|
+
))}
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
<div className="border-t border-[#2a2a4a] px-4 py-1.5 text-[10px] text-gray-600 flex items-center justify-between">
|
|
115
|
+
<span>Press <kbd className="font-mono">?</kbd> to toggle</span>
|
|
116
|
+
<span>or <kbd className="font-mono">esc</kbd> to close</span>
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
</div>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
@@ -1,42 +1,86 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Loading skeleton — mirrors the actual Overview layout structure so the
|
|
5
|
+
* page doesn't appear to "shift" once data arrives. Uses the same
|
|
6
|
+
* `anet-skeleton-pulse` rhythm as the brand pulse (1.6s opacity drift,
|
|
7
|
+
* no scale, no blur, no glow) so the loading animation feels native to
|
|
8
|
+
* the rest of the dashboard rather than a generic spinner.
|
|
9
|
+
*
|
|
10
|
+
* Bars are theme-aware: anet-skeleton-bar (existing CSS shim resolves this to
|
|
11
|
+
* var(--bg-elevated) on light/mint), so light theme shows soft grey blocks
|
|
12
|
+
* on white cards and dark theme shows lighter blocks on navy cards.
|
|
13
|
+
*/
|
|
3
14
|
export function LoadingSkeleton() {
|
|
4
15
|
return (
|
|
5
|
-
<div className="min-h-screen bg-[#0a0a1a] text-gray-100 p-6 font-mono
|
|
6
|
-
{/*
|
|
7
|
-
<div className="
|
|
8
|
-
|
|
9
|
-
<div className="
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
<div className="min-h-screen bg-[#0a0a1a] text-gray-100 p-4 sm:p-6 font-mono">
|
|
17
|
+
{/* KPI top strip — 4 cards matching StatsBar */}
|
|
18
|
+
<div className="grid grid-cols-2 sm:grid-cols-4 gap-3 mb-8 anet-skeleton-pulse">
|
|
19
|
+
{[1, 2, 3, 4].map(i => (
|
|
20
|
+
<div key={i} className="rounded-xl border border-[#2a2a4a] bg-[#111128] px-4 py-3">
|
|
21
|
+
<Bar w="2.5rem" h="1.75rem" />
|
|
22
|
+
<Bar w="3.5rem" h="0.75rem" className="mt-2" />
|
|
23
|
+
<Bar w="5rem" h="0.625rem" className="mt-1" />
|
|
24
|
+
</div>
|
|
25
|
+
))}
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
{/* Dispatch + UserBar row */}
|
|
29
|
+
<div className="flex items-center gap-3 mb-3 anet-skeleton-pulse">
|
|
30
|
+
<Bar w="6rem" h="2.5rem" rounded="0.75rem" />
|
|
31
|
+
<div className="flex-1 rounded-lg border border-[#2a2a4a] bg-[#111128] px-4 py-2.5 flex items-center gap-3">
|
|
32
|
+
<div className="w-8 h-8 rounded-full anet-skeleton-bar" />
|
|
33
|
+
<div className="flex-1">
|
|
34
|
+
<Bar w="6rem" h="0.875rem" />
|
|
35
|
+
<Bar w="10rem" h="0.625rem" className="mt-1" />
|
|
36
|
+
</div>
|
|
16
37
|
</div>
|
|
17
38
|
</div>
|
|
18
39
|
|
|
19
|
-
{/*
|
|
20
|
-
<div className="mb-6
|
|
21
|
-
<
|
|
22
|
-
|
|
40
|
+
{/* Config bar */}
|
|
41
|
+
<div className="mb-6 rounded-lg border border-[#2a2a4a] bg-[#111128] px-4 py-3 anet-skeleton-pulse">
|
|
42
|
+
<Bar w="14rem" h="0.875rem" />
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
{/* Stat strip 3 cards */}
|
|
46
|
+
<div className="grid grid-cols-3 gap-2 sm:gap-3 mb-3 anet-skeleton-pulse">
|
|
47
|
+
{[1, 2, 3].map(i => (
|
|
48
|
+
<div key={i} className="rounded-xl border border-[#2a2a4a] bg-[#111128] px-3 py-3">
|
|
49
|
+
<Bar w="2rem" h="1.25rem" />
|
|
50
|
+
<Bar w="2.5rem" h="0.75rem" className="mt-1" />
|
|
51
|
+
<Bar w="3.5rem" h="0.625rem" className="mt-px" />
|
|
52
|
+
</div>
|
|
53
|
+
))}
|
|
23
54
|
</div>
|
|
24
55
|
|
|
25
|
-
{/*
|
|
26
|
-
<div className="
|
|
56
|
+
{/* Nav rail 3 cards */}
|
|
57
|
+
<div className="grid grid-cols-3 gap-2 sm:gap-3 mb-6 anet-skeleton-pulse">
|
|
58
|
+
{[1, 2, 3].map(i => (
|
|
59
|
+
<div key={i} className="rounded-xl border border-[#2a2a4a] bg-[#111128] px-3 py-2.5 flex items-center justify-center gap-2">
|
|
60
|
+
<div className="w-4 h-4 rounded anet-skeleton-bar" />
|
|
61
|
+
<Bar w="4rem" h="0.75rem" />
|
|
62
|
+
</div>
|
|
63
|
+
))}
|
|
64
|
+
</div>
|
|
27
65
|
|
|
28
|
-
{/*
|
|
29
|
-
<div className="
|
|
66
|
+
{/* Broadcast bar */}
|
|
67
|
+
<div className="mb-6 flex gap-2 anet-skeleton-pulse">
|
|
68
|
+
<div className="flex-1 h-10 rounded-lg border border-[#2a2a4a] bg-[#111128]" />
|
|
69
|
+
<div className="w-28 h-10 rounded-lg anet-skeleton-bar" />
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
{/* Agent card grid */}
|
|
73
|
+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-3 sm:gap-4 anet-skeleton-pulse">
|
|
30
74
|
{[1, 2, 3, 4].map(i => (
|
|
31
|
-
<div key={i} className="rounded-xl border border-
|
|
75
|
+
<div key={i} className="rounded-xl border border-[#2a2a4a] bg-[#111128] p-4">
|
|
32
76
|
<div className="flex items-center gap-2 mb-3">
|
|
33
|
-
<div className="w-2
|
|
34
|
-
<
|
|
77
|
+
<div className="w-2 h-2 rounded-full anet-skeleton-bar" />
|
|
78
|
+
<Bar w="6rem" h="0.875rem" />
|
|
35
79
|
</div>
|
|
36
80
|
<div className="space-y-2">
|
|
37
|
-
<
|
|
38
|
-
<
|
|
39
|
-
<
|
|
81
|
+
<Bar w="100%" h="0.625rem" />
|
|
82
|
+
<Bar w="75%" h="0.625rem" />
|
|
83
|
+
<Bar w="55%" h="0.625rem" />
|
|
40
84
|
</div>
|
|
41
85
|
</div>
|
|
42
86
|
))}
|
|
@@ -45,21 +89,18 @@ export function LoadingSkeleton() {
|
|
|
45
89
|
);
|
|
46
90
|
}
|
|
47
91
|
|
|
48
|
-
|
|
92
|
+
/** Single shimmer bar — uses `anet-skeleton-bar` so theme-specific bar
|
|
93
|
+
* color (dark navy on dark themes, mid-grey on light) overrides the
|
|
94
|
+
* default. */
|
|
95
|
+
function Bar({ w, h, rounded, className }: { w: string; h: string; rounded?: string; className?: string }) {
|
|
49
96
|
return (
|
|
50
|
-
<div
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
<p className="text-gray-500 text-sm max-w-md mx-auto">
|
|
55
|
-
Server has <span className="text-cyan-400 font-medium">{hint.global_count}</span> nodes globally,
|
|
56
|
-
but none are registered to the current network. Switch network or contact admin.
|
|
57
|
-
</p>
|
|
58
|
-
) : (
|
|
59
|
-
<p className="text-gray-600 text-sm max-w-md mx-auto">
|
|
60
|
-
Agent sessions will appear here once they connect to the CommHub.
|
|
61
|
-
</p>
|
|
62
|
-
)}
|
|
63
|
-
</div>
|
|
97
|
+
<div
|
|
98
|
+
className={`anet-skeleton-bar ${className || ''}`}
|
|
99
|
+
style={{ width: w, height: h, borderRadius: rounded || '0.375rem' }}
|
|
100
|
+
/>
|
|
64
101
|
);
|
|
65
102
|
}
|
|
103
|
+
|
|
104
|
+
// EmptyState export removed in 0.4.5 — replaced by EmptyState.tsx with
|
|
105
|
+
// per-variant glyphs and a NodesEmptyState wrapper for the Overview
|
|
106
|
+
// hint-aware behavior. See app/components/EmptyState.tsx.
|
|
@@ -101,17 +101,11 @@ export function Sidebar() {
|
|
|
101
101
|
${mobileOpen ? 'translate-x-0' : '-translate-x-full'}
|
|
102
102
|
lg:translate-x-0 lg:static lg:shrink-0
|
|
103
103
|
`}>
|
|
104
|
-
{/*
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
<div>
|
|
110
|
-
<div className="text-white font-bold text-sm">Agent Network</div>
|
|
111
|
-
<div className="text-gray-600 text-xs">Dashboard</div>
|
|
112
|
-
</div>
|
|
113
|
-
)}
|
|
114
|
-
</div>
|
|
104
|
+
{/* Brand header — round 4: 3-node mesh mark matches /login,
|
|
105
|
+
with an inline live "online" pulse so every page surfaces
|
|
106
|
+
fleet health without leaving for /nodes. */}
|
|
107
|
+
<SidebarBrand collapsed={collapsed} />
|
|
108
|
+
<div className={`border-b border-[#2a2a4a]`} />
|
|
115
109
|
|
|
116
110
|
{/* Network list */}
|
|
117
111
|
{!collapsed && networks.length > 0 && (
|
|
@@ -157,6 +151,24 @@ export function Sidebar() {
|
|
|
157
151
|
Sign out
|
|
158
152
|
</button>
|
|
159
153
|
)}
|
|
154
|
+
{!collapsed && (
|
|
155
|
+
<button
|
|
156
|
+
onClick={() => {
|
|
157
|
+
// Dispatch a synthetic keypress so the global Cmd+K listener fires
|
|
158
|
+
window.dispatchEvent(new KeyboardEvent('keydown', { key: 'k', metaKey: true, ctrlKey: true }));
|
|
159
|
+
}}
|
|
160
|
+
className="w-full flex items-center justify-between gap-2 px-5 py-2 text-[11px] text-gray-600 hover:text-gray-400 hover:bg-[#1a1a2a] transition-colors"
|
|
161
|
+
aria-label="Open command palette"
|
|
162
|
+
>
|
|
163
|
+
<span className="flex items-center gap-2">
|
|
164
|
+
<svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
|
|
165
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
|
166
|
+
</svg>
|
|
167
|
+
Quick search
|
|
168
|
+
</span>
|
|
169
|
+
<kbd className="text-[10px] border border-current rounded px-1 py-0.5 opacity-60 font-mono">⌘K</kbd>
|
|
170
|
+
</button>
|
|
171
|
+
)}
|
|
160
172
|
<div className={`flex items-center gap-2 px-3 py-2 ${collapsed ? 'justify-center' : 'justify-between'}`}>
|
|
161
173
|
<ThemeSwitcher compact={collapsed} />
|
|
162
174
|
<button
|
|
@@ -174,3 +186,70 @@ export function Sidebar() {
|
|
|
174
186
|
</>
|
|
175
187
|
);
|
|
176
188
|
}
|
|
189
|
+
|
|
190
|
+
interface StatusData {
|
|
191
|
+
sessions?: Array<{ status?: string; alias?: string }>;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const statusFetcher = (url: string) =>
|
|
195
|
+
fetch(url).then(r => r.ok ? r.json() as Promise<StatusData> : { sessions: [] });
|
|
196
|
+
|
|
197
|
+
function SidebarBrand({ collapsed }: { collapsed: boolean }) {
|
|
198
|
+
// Live online count — re-uses the same /api/hub/status endpoint the
|
|
199
|
+
// Overview already polls, so SWR dedupes the request. Pulse is muted —
|
|
200
|
+
// emerald dot at 4px with a 1.6s slow opacity pulse, no glow, no halo.
|
|
201
|
+
const { data } = useSWR<StatusData>('/api/hub/status', statusFetcher, {
|
|
202
|
+
refreshInterval: 10000,
|
|
203
|
+
dedupingInterval: 4000,
|
|
204
|
+
});
|
|
205
|
+
const sessions = data?.sessions || [];
|
|
206
|
+
const online = sessions.filter(s => s.status && s.status !== 'offline').length;
|
|
207
|
+
const total = sessions.length;
|
|
208
|
+
|
|
209
|
+
if (collapsed) {
|
|
210
|
+
return (
|
|
211
|
+
<Link href="/" className="block px-3 py-4 flex justify-center hover:opacity-80 transition-opacity" aria-label="Agent Network — home">
|
|
212
|
+
<BrandMark size={32} />
|
|
213
|
+
</Link>
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return (
|
|
218
|
+
<Link
|
|
219
|
+
href="/"
|
|
220
|
+
className="block px-4 py-4 flex items-center gap-3 hover:bg-[#11112a]/40 transition-colors rounded-r-xl"
|
|
221
|
+
aria-label="Agent Network — home"
|
|
222
|
+
>
|
|
223
|
+
<BrandMark size={32} />
|
|
224
|
+
<div className="min-w-0">
|
|
225
|
+
<div className="text-white text-[13px] font-semibold leading-tight">Agent Network</div>
|
|
226
|
+
<div className="text-[10px] text-gray-500 flex items-center gap-1.5 mt-0.5">
|
|
227
|
+
<span
|
|
228
|
+
className={`inline-block w-1.5 h-1.5 rounded-full ${online > 0 ? 'bg-emerald-400 anet-brand-pulse' : 'bg-gray-600'}`}
|
|
229
|
+
aria-hidden
|
|
230
|
+
/>
|
|
231
|
+
{total === 0 ? (
|
|
232
|
+
<span>waiting for agents</span>
|
|
233
|
+
) : (
|
|
234
|
+
<span><span className="text-gray-300 font-medium tabular-nums">{online}</span><span className="text-gray-600">/{total}</span> online</span>
|
|
235
|
+
)}
|
|
236
|
+
</div>
|
|
237
|
+
</div>
|
|
238
|
+
</Link>
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** 3-node mesh mark — same SVG as /login, reusable. */
|
|
243
|
+
function BrandMark({ size }: { size: number }) {
|
|
244
|
+
return (
|
|
245
|
+
<svg width={size} height={size} viewBox="0 0 32 32" aria-hidden className="shrink-0">
|
|
246
|
+
<circle cx="16" cy="16" r="10" fill="none" stroke="currentColor" strokeWidth="1.5" opacity="0.2" className="text-cyan-400" />
|
|
247
|
+
<line x1="16" y1="10" x2="10" y2="20" stroke="currentColor" strokeWidth="1" opacity="0.45" className="text-cyan-400" />
|
|
248
|
+
<line x1="16" y1="10" x2="22" y2="20" stroke="currentColor" strokeWidth="1" opacity="0.45" className="text-cyan-400" />
|
|
249
|
+
<line x1="10" y1="20" x2="22" y2="20" stroke="currentColor" strokeWidth="1" opacity="0.45" className="text-cyan-400" />
|
|
250
|
+
<circle cx="16" cy="10" r="2.5" fill="currentColor" className="text-cyan-400" />
|
|
251
|
+
<circle cx="10" cy="20" r="2.5" fill="currentColor" className="text-green-400" />
|
|
252
|
+
<circle cx="22" cy="20" r="2.5" fill="currentColor" className="text-violet-400" />
|
|
253
|
+
</svg>
|
|
254
|
+
);
|
|
255
|
+
}
|