@sleep2agi/agent-network-dashboard 0.4.3-preview.1 → 0.4.5-preview.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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]__013i9e9._.js +9 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__013i9e9._.js.map +1 -0
- 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]__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_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_server-logs_page_tsx_0_kpp1p._.js +1 -1
- package/.next/server/chunks/ssr/app_server-logs_page_tsx_0_kpp1p._.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/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/0hyhubmh-__wg.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/0snd~q2ucn.h1.css +2 -0
- package/.next/static/chunks/0w1zwt8kq_7nb.js +1 -0
- package/.next/static/chunks/0xn9.0ejo1s_a.js +7 -0
- package/.next/static/chunks/0y0lo-~k2c~00.js +1 -0
- package/.next/static/chunks/10njj7kn9ylkf.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/EmptyState.tsx +189 -0
- package/app/components/LoadingSkeleton.tsx +3 -18
- package/app/components/Sidebar.tsx +72 -11
- package/app/components/StatsBar.tsx +7 -1
- package/app/components/TopoGraph.tsx +151 -62
- package/app/globals.css +108 -8
- package/app/login/page.tsx +26 -13
- package/app/logs/page.tsx +24 -11
- package/app/messages/page.tsx +2 -5
- package/app/nodes/page.tsx +6 -1
- package/app/page.tsx +36 -12
- package/app/server-logs/page.tsx +22 -11
- 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 +7 -9
- package/docs/loop-design-rounds.md +502 -0
- package/docs/oss-readiness-report.md +189 -0
- package/package.json +1 -1
- package/.mcp.json +0 -11
- 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/0agna31q2fjq1.css +0 -2
- 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/0ttvcv6~g0f6i.js +0 -1
- package/.next/static/chunks/0uqfv6rc-xdru.js +0 -1
- 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/0~93h~zb55yh9.js +0 -1
- package/.next/static/chunks/140l7~i5q9wrv.js +0 -1
- package/AGENTS.md +0 -5
- package/DASHBOARD_OPTIMIZATION_PLAN.md +0 -414
- package/docs/iteration-plan.md +0 -62
- package/docs/v4-plan.md +0 -38
- /package/.next/static/{7dwKlhAm5uyghPmkAubQK → 2m1yIfZCIYDWMYrrJEKSC}/_buildManifest.js +0 -0
- /package/.next/static/{7dwKlhAm5uyghPmkAubQK → 2m1yIfZCIYDWMYrrJEKSC}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{7dwKlhAm5uyghPmkAubQK → 2m1yIfZCIYDWMYrrJEKSC}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import Link from 'next/link';
|
|
4
|
+
|
|
5
|
+
export type EmptyVariant = 'nodes' | 'tasks' | 'messages' | 'logs' | 'tokens' | 'networks' | 'generic';
|
|
6
|
+
|
|
7
|
+
interface EmptyStateProps {
|
|
8
|
+
/** Picks the icon glyph and default copy if title/sub omitted. */
|
|
9
|
+
variant?: EmptyVariant;
|
|
10
|
+
/** Optional override headline. */
|
|
11
|
+
title?: string;
|
|
12
|
+
/** Optional override sub-copy. */
|
|
13
|
+
sub?: string;
|
|
14
|
+
/** Optional CTA: text + href (internal) or onClick. */
|
|
15
|
+
cta?: { label: string; href?: string; onClick?: () => void };
|
|
16
|
+
/** Compact mode for in-card empty states (smaller padding). */
|
|
17
|
+
compact?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const DEFAULTS: Record<EmptyVariant, { title: string; sub: string }> = {
|
|
21
|
+
nodes: { title: 'No agents in this network', sub: 'Agent sessions will appear here once they connect to the CommHub.' },
|
|
22
|
+
tasks: { title: 'No tasks yet', sub: 'Tasks will appear here when agents send them via CommHub.' },
|
|
23
|
+
messages: { title: 'No messages', sub: 'Messages between agents will appear here.' },
|
|
24
|
+
logs: { title: 'No audit logs', sub: 'Events will appear here when users register, login, or perform actions.' },
|
|
25
|
+
tokens: { title: 'No API tokens', sub: 'Create one to authenticate CLI tools and external integrations.' },
|
|
26
|
+
networks: { title: 'No networks found', sub: 'Create one or sign in with V3 auth to see your networks.' },
|
|
27
|
+
generic: { title: 'Nothing here yet', sub: 'Data will appear here once available.' },
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Minimal monochrome SVG glyphs per variant. No filled shapes, no gradients,
|
|
32
|
+
* no AI-decoration — just thin-stroke line art that fades into the page.
|
|
33
|
+
* 64×64 viewBox; rendered at 56×56 (compact 40×40).
|
|
34
|
+
*/
|
|
35
|
+
function Glyph({ variant, size }: { variant: EmptyVariant; size: number }) {
|
|
36
|
+
const s = { width: size, height: size };
|
|
37
|
+
const baseProps = {
|
|
38
|
+
fill: 'none',
|
|
39
|
+
stroke: 'currentColor',
|
|
40
|
+
strokeWidth: 1.25,
|
|
41
|
+
strokeLinecap: 'round' as const,
|
|
42
|
+
strokeLinejoin: 'round' as const,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
switch (variant) {
|
|
46
|
+
case 'nodes':
|
|
47
|
+
// Mesh with dashed edges = "nodes will land here"
|
|
48
|
+
return (
|
|
49
|
+
<svg viewBox="0 0 64 64" {...s}>
|
|
50
|
+
<g {...baseProps}>
|
|
51
|
+
<circle cx="32" cy="14" r="4" />
|
|
52
|
+
<circle cx="14" cy="44" r="4" />
|
|
53
|
+
<circle cx="50" cy="44" r="4" />
|
|
54
|
+
<line x1="32" y1="18" x2="14" y2="40" strokeDasharray="3 3" opacity="0.6" />
|
|
55
|
+
<line x1="32" y1="18" x2="50" y2="40" strokeDasharray="3 3" opacity="0.6" />
|
|
56
|
+
<line x1="18" y1="44" x2="46" y2="44" strokeDasharray="3 3" opacity="0.6" />
|
|
57
|
+
</g>
|
|
58
|
+
</svg>
|
|
59
|
+
);
|
|
60
|
+
case 'tasks':
|
|
61
|
+
// Empty checkbox list
|
|
62
|
+
return (
|
|
63
|
+
<svg viewBox="0 0 64 64" {...s}>
|
|
64
|
+
<g {...baseProps}>
|
|
65
|
+
<rect x="14" y="14" width="36" height="6" rx="1.5" />
|
|
66
|
+
<rect x="14" y="26" width="36" height="6" rx="1.5" opacity="0.6" />
|
|
67
|
+
<rect x="14" y="38" width="36" height="6" rx="1.5" opacity="0.35" />
|
|
68
|
+
</g>
|
|
69
|
+
</svg>
|
|
70
|
+
);
|
|
71
|
+
case 'messages':
|
|
72
|
+
// Speech bubble outline
|
|
73
|
+
return (
|
|
74
|
+
<svg viewBox="0 0 64 64" {...s}>
|
|
75
|
+
<g {...baseProps}>
|
|
76
|
+
<path d="M14 18 h36 a3 3 0 0 1 3 3 v18 a3 3 0 0 1 -3 3 h-18 l-8 6 v-6 h-10 a3 3 0 0 1 -3 -3 v-18 a3 3 0 0 1 3 -3 z" />
|
|
77
|
+
<line x1="22" y1="28" x2="42" y2="28" opacity="0.5" />
|
|
78
|
+
<line x1="22" y1="34" x2="36" y2="34" opacity="0.5" />
|
|
79
|
+
</g>
|
|
80
|
+
</svg>
|
|
81
|
+
);
|
|
82
|
+
case 'logs':
|
|
83
|
+
// Document with lines
|
|
84
|
+
return (
|
|
85
|
+
<svg viewBox="0 0 64 64" {...s}>
|
|
86
|
+
<g {...baseProps}>
|
|
87
|
+
<path d="M18 12 h22 l8 8 v32 a2 2 0 0 1 -2 2 h-28 a2 2 0 0 1 -2 -2 v-38 a2 2 0 0 1 2 -2 z" />
|
|
88
|
+
<path d="M40 12 v8 h8" opacity="0.6" />
|
|
89
|
+
<line x1="24" y1="32" x2="40" y2="32" opacity="0.55" />
|
|
90
|
+
<line x1="24" y1="38" x2="40" y2="38" opacity="0.4" />
|
|
91
|
+
<line x1="24" y1="44" x2="34" y2="44" opacity="0.25" />
|
|
92
|
+
</g>
|
|
93
|
+
</svg>
|
|
94
|
+
);
|
|
95
|
+
case 'tokens':
|
|
96
|
+
// Key outline
|
|
97
|
+
return (
|
|
98
|
+
<svg viewBox="0 0 64 64" {...s}>
|
|
99
|
+
<g {...baseProps}>
|
|
100
|
+
<circle cx="22" cy="32" r="8" />
|
|
101
|
+
<line x1="30" y1="32" x2="54" y2="32" />
|
|
102
|
+
<line x1="44" y1="32" x2="44" y2="38" />
|
|
103
|
+
<line x1="50" y1="32" x2="50" y2="40" />
|
|
104
|
+
</g>
|
|
105
|
+
</svg>
|
|
106
|
+
);
|
|
107
|
+
case 'networks':
|
|
108
|
+
// Globe-ish concentric ovals
|
|
109
|
+
return (
|
|
110
|
+
<svg viewBox="0 0 64 64" {...s}>
|
|
111
|
+
<g {...baseProps}>
|
|
112
|
+
<circle cx="32" cy="32" r="18" />
|
|
113
|
+
<ellipse cx="32" cy="32" rx="18" ry="9" opacity="0.55" />
|
|
114
|
+
<line x1="14" y1="32" x2="50" y2="32" opacity="0.55" />
|
|
115
|
+
<line x1="32" y1="14" x2="32" y2="50" opacity="0.55" />
|
|
116
|
+
</g>
|
|
117
|
+
</svg>
|
|
118
|
+
);
|
|
119
|
+
case 'generic':
|
|
120
|
+
default:
|
|
121
|
+
// Soft sparkle outline
|
|
122
|
+
return (
|
|
123
|
+
<svg viewBox="0 0 64 64" {...s}>
|
|
124
|
+
<g {...baseProps}>
|
|
125
|
+
<circle cx="32" cy="32" r="14" strokeDasharray="3 3" opacity="0.6" />
|
|
126
|
+
<circle cx="32" cy="32" r="3" />
|
|
127
|
+
</g>
|
|
128
|
+
</svg>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function EmptyState({ variant = 'generic', title, sub, cta, compact = false }: EmptyStateProps) {
|
|
134
|
+
const d = DEFAULTS[variant];
|
|
135
|
+
const headline = title ?? d.title;
|
|
136
|
+
const subcopy = sub ?? d.sub;
|
|
137
|
+
const iconSize = compact ? 40 : 56;
|
|
138
|
+
|
|
139
|
+
return (
|
|
140
|
+
<div className={`text-center ${compact ? 'py-8' : 'py-16'} px-4`} role="status">
|
|
141
|
+
<div className="anet-empty-glyph inline-flex items-center justify-center mb-4 text-gray-500" aria-hidden>
|
|
142
|
+
<Glyph variant={variant} size={iconSize} />
|
|
143
|
+
</div>
|
|
144
|
+
<h3 className={`font-medium text-gray-300 ${compact ? 'text-sm' : 'text-base'}`}>{headline}</h3>
|
|
145
|
+
{subcopy && (
|
|
146
|
+
<p className={`text-gray-500 ${compact ? 'text-xs mt-1.5' : 'text-sm mt-2'} max-w-md mx-auto leading-relaxed`}>
|
|
147
|
+
{subcopy}
|
|
148
|
+
</p>
|
|
149
|
+
)}
|
|
150
|
+
{cta && (
|
|
151
|
+
<div className="mt-4">
|
|
152
|
+
{cta.href ? (
|
|
153
|
+
<Link href={cta.href} className="inline-flex items-center gap-1.5 text-sm font-medium text-cyan-400 hover:text-cyan-300">
|
|
154
|
+
{cta.label}
|
|
155
|
+
<span aria-hidden>→</span>
|
|
156
|
+
</Link>
|
|
157
|
+
) : (
|
|
158
|
+
<button onClick={cta.onClick} className="inline-flex items-center gap-1.5 text-sm font-medium text-cyan-400 hover:text-cyan-300">
|
|
159
|
+
{cta.label}
|
|
160
|
+
<span aria-hidden>→</span>
|
|
161
|
+
</button>
|
|
162
|
+
)}
|
|
163
|
+
</div>
|
|
164
|
+
)}
|
|
165
|
+
</div>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Overview-specific variant with a hint about cross-network global count.
|
|
171
|
+
* Kept here so /app/page.tsx can drop in without ceremony.
|
|
172
|
+
*/
|
|
173
|
+
export function NodesEmptyState({ hint }: { hint?: { global_count?: number; filtered_network?: string } }) {
|
|
174
|
+
if (hint?.global_count) {
|
|
175
|
+
return (
|
|
176
|
+
<EmptyState
|
|
177
|
+
variant="nodes"
|
|
178
|
+
title="No agents in this network"
|
|
179
|
+
sub={`Server has ${hint.global_count} nodes globally, but none are registered to the current network. Switch network or contact admin.`}
|
|
180
|
+
/>
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
return (
|
|
184
|
+
<EmptyState
|
|
185
|
+
variant="nodes"
|
|
186
|
+
cta={{ label: 'Run anet quickstart', href: 'https://anet.sh' }}
|
|
187
|
+
/>
|
|
188
|
+
);
|
|
189
|
+
}
|
|
@@ -45,21 +45,6 @@ export function LoadingSkeleton() {
|
|
|
45
45
|
);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
<div className="text-gray-600 text-4xl mb-4">--</div>
|
|
52
|
-
<h3 className="text-gray-400 text-lg font-medium mb-2">No agents in this network</h3>
|
|
53
|
-
{hint?.global_count ? (
|
|
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>
|
|
64
|
-
);
|
|
65
|
-
}
|
|
48
|
+
// EmptyState export removed in 0.4.5 — replaced by EmptyState.tsx with
|
|
49
|
+
// per-variant glyphs and a NodesEmptyState wrapper for the Overview
|
|
50
|
+
// 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 && (
|
|
@@ -174,3 +168,70 @@ export function Sidebar() {
|
|
|
174
168
|
</>
|
|
175
169
|
);
|
|
176
170
|
}
|
|
171
|
+
|
|
172
|
+
interface StatusData {
|
|
173
|
+
sessions?: Array<{ status?: string; alias?: string }>;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const statusFetcher = (url: string) =>
|
|
177
|
+
fetch(url).then(r => r.ok ? r.json() as Promise<StatusData> : { sessions: [] });
|
|
178
|
+
|
|
179
|
+
function SidebarBrand({ collapsed }: { collapsed: boolean }) {
|
|
180
|
+
// Live online count — re-uses the same /api/hub/status endpoint the
|
|
181
|
+
// Overview already polls, so SWR dedupes the request. Pulse is muted —
|
|
182
|
+
// emerald dot at 4px with a 1.6s slow opacity pulse, no glow, no halo.
|
|
183
|
+
const { data } = useSWR<StatusData>('/api/hub/status', statusFetcher, {
|
|
184
|
+
refreshInterval: 10000,
|
|
185
|
+
dedupingInterval: 4000,
|
|
186
|
+
});
|
|
187
|
+
const sessions = data?.sessions || [];
|
|
188
|
+
const online = sessions.filter(s => s.status && s.status !== 'offline').length;
|
|
189
|
+
const total = sessions.length;
|
|
190
|
+
|
|
191
|
+
if (collapsed) {
|
|
192
|
+
return (
|
|
193
|
+
<Link href="/" className="block px-3 py-4 flex justify-center hover:opacity-80 transition-opacity" aria-label="Agent Network — home">
|
|
194
|
+
<BrandMark size={32} />
|
|
195
|
+
</Link>
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<Link
|
|
201
|
+
href="/"
|
|
202
|
+
className="block px-4 py-4 flex items-center gap-3 hover:bg-[#11112a]/40 transition-colors rounded-r-xl"
|
|
203
|
+
aria-label="Agent Network — home"
|
|
204
|
+
>
|
|
205
|
+
<BrandMark size={32} />
|
|
206
|
+
<div className="min-w-0">
|
|
207
|
+
<div className="text-white text-[13px] font-semibold leading-tight">Agent Network</div>
|
|
208
|
+
<div className="text-[10px] text-gray-500 flex items-center gap-1.5 mt-0.5">
|
|
209
|
+
<span
|
|
210
|
+
className={`inline-block w-1.5 h-1.5 rounded-full ${online > 0 ? 'bg-emerald-400 anet-brand-pulse' : 'bg-gray-600'}`}
|
|
211
|
+
aria-hidden
|
|
212
|
+
/>
|
|
213
|
+
{total === 0 ? (
|
|
214
|
+
<span>waiting for agents</span>
|
|
215
|
+
) : (
|
|
216
|
+
<span><span className="text-gray-300 font-medium tabular-nums">{online}</span><span className="text-gray-600">/{total}</span> online</span>
|
|
217
|
+
)}
|
|
218
|
+
</div>
|
|
219
|
+
</div>
|
|
220
|
+
</Link>
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** 3-node mesh mark — same SVG as /login, reusable. */
|
|
225
|
+
function BrandMark({ size }: { size: number }) {
|
|
226
|
+
return (
|
|
227
|
+
<svg width={size} height={size} viewBox="0 0 32 32" aria-hidden className="shrink-0">
|
|
228
|
+
<circle cx="16" cy="16" r="10" fill="none" stroke="currentColor" strokeWidth="1.5" opacity="0.2" className="text-cyan-400" />
|
|
229
|
+
<line x1="16" y1="10" x2="10" y2="20" stroke="currentColor" strokeWidth="1" opacity="0.45" className="text-cyan-400" />
|
|
230
|
+
<line x1="16" y1="10" x2="22" y2="20" stroke="currentColor" strokeWidth="1" opacity="0.45" className="text-cyan-400" />
|
|
231
|
+
<line x1="10" y1="20" x2="22" y2="20" stroke="currentColor" strokeWidth="1" opacity="0.45" className="text-cyan-400" />
|
|
232
|
+
<circle cx="16" cy="10" r="2.5" fill="currentColor" className="text-cyan-400" />
|
|
233
|
+
<circle cx="10" cy="20" r="2.5" fill="currentColor" className="text-green-400" />
|
|
234
|
+
<circle cx="22" cy="20" r="2.5" fill="currentColor" className="text-violet-400" />
|
|
235
|
+
</svg>
|
|
236
|
+
);
|
|
237
|
+
}
|
|
@@ -63,8 +63,14 @@ export function StatsBar({ online, working, total, version, uptime }: StatsBarPr
|
|
|
63
63
|
function StatCard({ value, label, sub, color, accent, border }: {
|
|
64
64
|
value: number; label: string; sub: string; color: string; accent: string; border: string;
|
|
65
65
|
}) {
|
|
66
|
+
// Extract the color family (green/cyan/gray/blue/white) from `color` prop
|
|
67
|
+
// so the light-theme top-strip CSS can pick the right accent.
|
|
68
|
+
const accentKey = color.replace('text-', '').split('-')[0];
|
|
66
69
|
return (
|
|
67
|
-
<div
|
|
70
|
+
<div
|
|
71
|
+
data-anet-stat-card={accentKey}
|
|
72
|
+
className={`anet-stat-card relative overflow-hidden rounded-xl border ${border} bg-[#111128] px-4 py-3 transition-all`}
|
|
73
|
+
>
|
|
68
74
|
<div className={`absolute inset-0 bg-gradient-to-br ${accent} pointer-events-none`} />
|
|
69
75
|
<div className="relative">
|
|
70
76
|
<div className={`text-3xl font-bold ${color} tabular-nums leading-tight`}>{value}</div>
|