@sleep2agi/agent-network-dashboard 0.4.5-preview.5 → 0.4.5-preview.50
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 +3 -3
- package/.next/diagnostics/route-bundle-stats.json +50 -50
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/prerender-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_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +4 -4
- 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.js.nft.json +1 -1
- package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
- package/.next/server/app/admin.html +4 -4
- 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 +4 -4
- 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.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.js.nft.json +1 -1
- package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/logs.html +4 -4
- 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.js.nft.json +1 -1
- package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
- package/.next/server/app/messages.html +4 -4
- 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.js.nft.json +1 -1
- package/.next/server/app/node/page_client-reference-manifest.js +1 -1
- package/.next/server/app/node.html +4 -4
- 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.js.nft.json +1 -1
- package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
- package/.next/server/app/nodes.html +4 -4
- 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.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs.html +4 -4
- 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.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 +4 -4
- 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.js.nft.json +1 -1
- package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens.html +4 -4
- 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 +4 -4
- 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_client-reference-manifest.js +1 -1
- 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 +4 -4
- 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]__02ee4km._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__02ee4km._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0n4l2is._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0n4l2is._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0o8yj3c._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0o8yj3c._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0xm3h9x._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0xm3h9x._.js.map +1 -1
- package/.next/server/chunks/ssr/_0nne7mz._.js +3 -0
- package/.next/server/chunks/ssr/_0nne7mz._.js.map +1 -0
- package/.next/server/chunks/ssr/app_0.zbtn5._.js +9 -0
- package/.next/server/chunks/ssr/app_0.zbtn5._.js.map +1 -0
- package/.next/server/chunks/ssr/app_04n78pr._.js +3 -0
- package/.next/server/chunks/ssr/app_04n78pr._.js.map +1 -0
- package/.next/server/chunks/ssr/app_0_agk0r._.js +3 -0
- package/.next/server/chunks/ssr/app_0_agk0r._.js.map +1 -0
- package/.next/server/chunks/ssr/app_0aum_g5._.js +3 -0
- package/.next/server/chunks/ssr/app_0aum_g5._.js.map +1 -0
- package/.next/server/chunks/ssr/app_0esuljp._.js +3 -0
- package/.next/server/chunks/ssr/app_0esuljp._.js.map +1 -0
- package/.next/server/chunks/ssr/app_0izi28j._.js +1 -1
- package/.next/server/chunks/ssr/app_0izi28j._.js.map +1 -1
- package/.next/server/chunks/ssr/app_0py1sns._.js +3 -0
- package/.next/server/chunks/ssr/app_0py1sns._.js.map +1 -0
- package/.next/server/chunks/ssr/app_0tncr1_._.js +3 -0
- package/.next/server/chunks/ssr/app_0tncr1_._.js.map +1 -0
- package/.next/server/chunks/ssr/app_components_08ys5y3._.js +5 -5
- package/.next/server/chunks/ssr/app_components_08ys5y3._.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/middleware-build-manifest.js +3 -3
- package/.next/server/pages/404.html +4 -4
- 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/000qcyr-yo73c.css +2 -0
- package/.next/static/chunks/02oje7pf-g1v5.js +1 -0
- package/.next/static/chunks/06x7w8nwggx~~.js +1 -0
- package/.next/static/chunks/{07okhs5561y5y.js → 0c1bp~g7.8ru..js} +1 -1
- package/.next/static/chunks/0edt_z0rlxgfk.js +1 -0
- package/.next/static/chunks/0irkayokwc1fm.js +1 -0
- package/.next/static/chunks/0j8ee64jv6zb7.js +7 -0
- package/.next/static/chunks/0l2rkodu2.v~r.js +1 -0
- package/.next/static/chunks/0mdu-2u9-dx.4.js +1 -0
- package/.next/static/chunks/0uar..avu998d.js +1 -0
- package/.next/static/chunks/0vqk_f6kf2hnl.js +1 -0
- package/.next/static/chunks/0xu37uygp5fs-.js +1 -0
- package/.next/static/chunks/0~n.cadw9_e8s.js +7 -0
- package/.next/static/chunks/12hyhrnzrx~ys.js +1 -0
- package/.next/static/chunks/1528e.3d.l1ve.js +1 -0
- package/.next/static/chunks/15c9pv6gxir.5.js +1 -0
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/admin/page.tsx +77 -25
- package/app/components/AgentCard.tsx +19 -5
- package/app/components/AliasAvatar.tsx +51 -0
- package/app/components/BroadcastBar.tsx +22 -4
- package/app/components/DispatchPanel.tsx +9 -5
- package/app/components/EmptyState.tsx +77 -4
- package/app/components/HealthBanner.tsx +1 -1
- package/app/components/HelpOverlay.tsx +50 -10
- package/app/components/InboxPanel.tsx +6 -3
- package/app/components/Sidebar.tsx +49 -41
- package/app/components/TaskChatPanel.tsx +8 -10
- package/app/components/TaskDrawer.tsx +72 -28
- package/app/components/TopoGraph.tsx +118 -24
- package/app/globals.css +90 -0
- package/app/lib/status.ts +63 -0
- package/app/lib/version.ts +7 -0
- package/app/login/page.tsx +40 -7
- package/app/logs/page.tsx +72 -21
- package/app/messages/page.tsx +8 -33
- package/app/node/page.tsx +48 -25
- package/app/nodes/page.tsx +21 -23
- package/app/page.tsx +77 -17
- package/app/server-logs/page.tsx +70 -12
- package/app/settings/networks/page.tsx +37 -13
- package/app/settings/page.tsx +38 -10
- package/app/tasks/page.tsx +90 -93
- package/package.json +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0_jnflc._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0_jnflc._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0nrckjd._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__0nrckjd._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__12mpoig._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__12mpoig._.js.map +0 -1
- package/.next/server/chunks/ssr/_0d-fuox._.js +0 -3
- package/.next/server/chunks/ssr/_0d-fuox._.js.map +0 -1
- package/.next/server/chunks/ssr/app_0.0wpa~._.js +0 -3
- package/.next/server/chunks/ssr/app_0.0wpa~._.js.map +0 -1
- package/.next/server/chunks/ssr/app_0ap_oiq._.js +0 -3
- package/.next/server/chunks/ssr/app_0ap_oiq._.js.map +0 -1
- package/.next/server/chunks/ssr/app_0dk5wao._.js +0 -3
- package/.next/server/chunks/ssr/app_0dk5wao._.js.map +0 -1
- package/.next/server/chunks/ssr/app_0et5yua._.js +0 -3
- package/.next/server/chunks/ssr/app_0et5yua._.js.map +0 -1
- package/.next/server/chunks/ssr/app_0ff~kjj._.js +0 -9
- package/.next/server/chunks/ssr/app_0ff~kjj._.js.map +0 -1
- package/.next/server/chunks/ssr/app_login_page_tsx_0z71ad3._.js +0 -3
- package/.next/server/chunks/ssr/app_login_page_tsx_0z71ad3._.js.map +0 -1
- package/.next/server/chunks/ssr/app_page_tsx_0es_sk2._.js +0 -3
- package/.next/server/chunks/ssr/app_page_tsx_0es_sk2._.js.map +0 -1
- package/.next/static/chunks/02flrewxlf_m_.js +0 -1
- package/.next/static/chunks/051gslfjka1kj.js +0 -1
- package/.next/static/chunks/06t_vzei8s9_h.js +0 -1
- package/.next/static/chunks/07oobuohrpigy.js +0 -1
- package/.next/static/chunks/0e7c40p~wq665.js +0 -1
- package/.next/static/chunks/0g7m7zk.v7g6h.js +0 -1
- package/.next/static/chunks/0khpyxpdrp~ty.js +0 -1
- package/.next/static/chunks/0m328uz90rp81.js +0 -1
- package/.next/static/chunks/0ogeals5ufhho.js +0 -1
- package/.next/static/chunks/0svy-tmgb8ajq.js +0 -7
- package/.next/static/chunks/1031v6nw33ud3.js +0 -1
- package/.next/static/chunks/10ir.g.n~hre0.js +0 -7
- package/.next/static/chunks/10njj7kn9ylkf.js +0 -1
- package/.next/static/chunks/13.dst7liziwo.js +0 -1
- package/.next/static/chunks/168ijr_r0ku-q.css +0 -2
- package/public/file.svg +0 -1
- package/public/globe.svg +0 -1
- package/public/next.svg +0 -1
- package/public/vercel.svg +0 -1
- package/public/window.svg +0 -1
- /package/.next/static/{HWCPpUEba8WqttkPXD5x8 → AQXM9jmgIyScbdEjjvrFL}/_buildManifest.js +0 -0
- /package/.next/static/{HWCPpUEba8WqttkPXD5x8 → AQXM9jmgIyScbdEjjvrFL}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{HWCPpUEba8WqttkPXD5x8 → AQXM9jmgIyScbdEjjvrFL}/_ssgManifest.js +0 -0
package/app/server-logs/page.tsx
CHANGED
|
@@ -23,6 +23,30 @@ const LEVEL_BADGE: Record<LogLine['level'], string> = {
|
|
|
23
23
|
error: 'bg-red-500/10 text-red-300 border-red-500/30',
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
+
/** Left-rail strip color per log level — gives the eye a vertical guide
|
|
27
|
+
* when scanning long log walls. Plain hex so Tailwind purge can't drop it. */
|
|
28
|
+
const LEVEL_STRIPE: Record<LogLine['level'], string> = {
|
|
29
|
+
log: 'transparent',
|
|
30
|
+
info: '#22d3ee',
|
|
31
|
+
warn: '#f59e0b',
|
|
32
|
+
error: '#ef4444',
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/** Highlight search-matched substring inside a log line. Case-insensitive
|
|
36
|
+
* first-match wrap; mark inherits color so log-level coloring stays. */
|
|
37
|
+
function highlightSearch(line: string, q: string) {
|
|
38
|
+
if (!q) return line;
|
|
39
|
+
const idx = line.toLowerCase().indexOf(q.toLowerCase());
|
|
40
|
+
if (idx < 0) return line;
|
|
41
|
+
return (
|
|
42
|
+
<>
|
|
43
|
+
{line.slice(0, idx)}
|
|
44
|
+
<mark className="bg-yellow-500/30 text-yellow-100 rounded-sm px-0.5">{line.slice(idx, idx + q.length)}</mark>
|
|
45
|
+
{line.slice(idx + q.length)}
|
|
46
|
+
</>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
26
50
|
function shortTime(iso: string) {
|
|
27
51
|
try {
|
|
28
52
|
const d = new Date(iso);
|
|
@@ -93,24 +117,48 @@ export default function ServerLogsPage() {
|
|
|
93
117
|
|
|
94
118
|
return (
|
|
95
119
|
<div className="p-6 max-w-[1600px] mx-auto">
|
|
96
|
-
<div className="flex items-
|
|
97
|
-
<div className="flex items-
|
|
120
|
+
<div className="flex items-center justify-between mb-4 gap-3">
|
|
121
|
+
<div className="flex items-center gap-3 min-w-0">
|
|
98
122
|
<h1 className="text-2xl font-bold text-white">Server Logs</h1>
|
|
99
|
-
|
|
123
|
+
{logs.length > 0 && (
|
|
124
|
+
<span className="text-xs bg-blue-900/30 text-blue-400 px-2 py-0.5 rounded-full border border-blue-800/30 tabular-nums">
|
|
125
|
+
{logs.length}
|
|
126
|
+
</span>
|
|
127
|
+
)}
|
|
128
|
+
<span className="text-xs text-gray-500 hidden sm:inline">CommHub stdout/stderr</span>
|
|
100
129
|
</div>
|
|
101
|
-
<div className="flex items-center gap-2 text-xs">
|
|
130
|
+
<div className="flex items-center gap-2 text-xs shrink-0">
|
|
102
131
|
<button
|
|
103
132
|
onClick={() => setPaused(p => !p)}
|
|
104
|
-
className={`px-3 py-1 rounded border ${paused ? 'bg-amber-500/10 text-amber-300 border-amber-500/30' : 'bg-cyan-500/10 text-cyan-300 border-cyan-500/30'}`}
|
|
133
|
+
className={`flex items-center gap-1.5 px-3 py-1 rounded border ${paused ? 'bg-amber-500/10 text-amber-300 border-amber-500/30' : 'bg-cyan-500/10 text-cyan-300 border-cyan-500/30'}`}
|
|
105
134
|
>
|
|
106
|
-
{paused ?
|
|
135
|
+
{paused ? (
|
|
136
|
+
<>
|
|
137
|
+
<svg width="10" height="10" viewBox="0 0 24 24" fill="currentColor" aria-hidden><path d="M8 5v14l11-7z" /></svg>
|
|
138
|
+
Resume
|
|
139
|
+
</>
|
|
140
|
+
) : (
|
|
141
|
+
<>
|
|
142
|
+
<svg width="10" height="10" viewBox="0 0 24 24" fill="currentColor" aria-hidden>
|
|
143
|
+
<rect x="6" y="5" width="4" height="14" rx="0.5" />
|
|
144
|
+
<rect x="14" y="5" width="4" height="14" rx="0.5" />
|
|
145
|
+
</svg>
|
|
146
|
+
Pause
|
|
147
|
+
</>
|
|
148
|
+
)}
|
|
107
149
|
</button>
|
|
108
150
|
<label className="flex items-center gap-1 text-gray-400 select-none">
|
|
109
151
|
<input type="checkbox" checked={autoRefresh} onChange={e => setAutoRefresh(e.target.checked)} className="accent-cyan-500" />
|
|
110
|
-
auto-refresh
|
|
152
|
+
<span className="hidden sm:inline">auto-refresh</span>
|
|
111
153
|
</label>
|
|
112
|
-
<button onClick={() => fetchLogs(true)} className="px-3 py-1 rounded border bg-gray-500/10 text-gray-300 border-gray-500/20 hover:bg-gray-500/20">
|
|
113
|
-
|
|
154
|
+
<button onClick={() => fetchLogs(true)} className="flex items-center gap-1.5 px-3 py-1 rounded border bg-gray-500/10 text-gray-300 border-gray-500/20 hover:bg-gray-500/20">
|
|
155
|
+
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden>
|
|
156
|
+
<path d="M3 12a9 9 0 0 1 15.5-6.4L21 8" />
|
|
157
|
+
<path d="M21 3v5h-5" />
|
|
158
|
+
<path d="M21 12a9 9 0 0 1-15.5 6.4L3 16" />
|
|
159
|
+
<path d="M3 21v-5h5" />
|
|
160
|
+
</svg>
|
|
161
|
+
<span className="hidden sm:inline">Reload</span>
|
|
114
162
|
</button>
|
|
115
163
|
</div>
|
|
116
164
|
</div>
|
|
@@ -182,12 +230,22 @@ export default function ServerLogsPage() {
|
|
|
182
230
|
) : (
|
|
183
231
|
<div className="divide-y divide-[#0d0d18] max-h-[calc(100vh-260px)] overflow-y-auto">
|
|
184
232
|
{filtered.map((l, i) => (
|
|
185
|
-
<div key={`${l.ts}-${i}`} className="
|
|
186
|
-
|
|
233
|
+
<div key={`${l.ts}-${i}`} className="relative pl-3 pr-3 py-1 hover:bg-[#0a0a14] flex gap-3">
|
|
234
|
+
{/* Round 32: 2px left rail keyed to level. Makes warn/error
|
|
235
|
+
spike visible in a wall of `log` lines without users having
|
|
236
|
+
to read the level chip on every row. */}
|
|
237
|
+
<span
|
|
238
|
+
aria-hidden
|
|
239
|
+
className="absolute left-0 top-0 bottom-0 w-0.5"
|
|
240
|
+
style={{ backgroundColor: LEVEL_STRIPE[l.level] }}
|
|
241
|
+
/>
|
|
242
|
+
<span className="text-gray-600 shrink-0 w-[100px] text-[10px] tabular-nums">{shortTime(l.ts)}</span>
|
|
187
243
|
<span className={`shrink-0 px-1.5 rounded border text-[9px] uppercase ${LEVEL_BADGE[l.level]}`}>
|
|
188
244
|
{l.level}
|
|
189
245
|
</span>
|
|
190
|
-
<span className={`break-all whitespace-pre-wrap ${LEVEL_COLOR[l.level]}`}>
|
|
246
|
+
<span className={`break-all whitespace-pre-wrap ${LEVEL_COLOR[l.level]}`}>
|
|
247
|
+
{highlightSearch(l.line, search)}
|
|
248
|
+
</span>
|
|
191
249
|
</div>
|
|
192
250
|
))}
|
|
193
251
|
</div>
|
|
@@ -4,6 +4,7 @@ import { useEffect, useState, useCallback } from 'react';
|
|
|
4
4
|
import Link from 'next/link';
|
|
5
5
|
import { timeAgo } from '../../components/utils';
|
|
6
6
|
import { EmptyState } from '../../components/EmptyState';
|
|
7
|
+
import { AliasAvatar } from '../../components/AliasAvatar';
|
|
7
8
|
import useSWR from 'swr';
|
|
8
9
|
|
|
9
10
|
const fetcher = (url: string) => fetch(url).then(r => r.json());
|
|
@@ -123,7 +124,12 @@ export default function NetworksPage() {
|
|
|
123
124
|
|
|
124
125
|
{/* List */}
|
|
125
126
|
<section className="bg-[#111128] border border-[#2a2a4a] rounded-xl p-5">
|
|
126
|
-
<
|
|
127
|
+
<div className="flex items-center justify-between mb-3">
|
|
128
|
+
<h2 className="text-sm font-semibold text-gray-300">My Networks</h2>
|
|
129
|
+
{networks.length > 0 && (
|
|
130
|
+
<span className="text-[10px] text-gray-600 uppercase tracking-wide">{networks.length} total</span>
|
|
131
|
+
)}
|
|
132
|
+
</div>
|
|
127
133
|
{loading ? (
|
|
128
134
|
<div className="animate-pulse space-y-2">{[1,2].map(i => <div key={i} className="h-14 bg-gray-800/20 rounded" />)}</div>
|
|
129
135
|
) : networks.length === 0 ? (
|
|
@@ -136,11 +142,14 @@ export default function NetworksPage() {
|
|
|
136
142
|
<div className="space-y-3">
|
|
137
143
|
{networks.map(n => (
|
|
138
144
|
<div key={n.network_id} className="bg-[#0a0a15] rounded-lg px-4 py-3 border border-[#1a1a2a]">
|
|
139
|
-
<div className="flex items-
|
|
140
|
-
<div className="min-w-0">
|
|
141
|
-
<
|
|
142
|
-
<div className="
|
|
143
|
-
|
|
145
|
+
<div className="flex items-start justify-between gap-3">
|
|
146
|
+
<div className="flex items-start gap-3 min-w-0">
|
|
147
|
+
<AliasAvatar alias={n.network_name} size={28} />
|
|
148
|
+
<div className="min-w-0">
|
|
149
|
+
<div className="text-sm text-white font-medium truncate">{n.network_name}</div>
|
|
150
|
+
<div className="text-[10px] text-gray-500 font-mono truncate" title={n.network_id}>{n.network_id} · {timeAgo(n.created_at)}</div>
|
|
151
|
+
{n.description && <div className="text-xs text-gray-400 mt-1">{n.description}</div>}
|
|
152
|
+
</div>
|
|
144
153
|
</div>
|
|
145
154
|
<div className="flex gap-2 shrink-0">
|
|
146
155
|
<button onClick={() => {
|
|
@@ -169,14 +178,20 @@ export default function NetworksPage() {
|
|
|
169
178
|
{(members[n.network_id] || []).length === 0 ? (
|
|
170
179
|
<div className="text-[10px] text-gray-600">No members or V3 auth required</div>
|
|
171
180
|
) : (
|
|
172
|
-
(members[n.network_id] || []).map(m =>
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
181
|
+
(members[n.network_id] || []).map(m => {
|
|
182
|
+
const name = m.username || m.display_name || '?';
|
|
183
|
+
return (
|
|
184
|
+
<div key={m.user_id} className="flex items-center gap-2 justify-between text-xs py-1">
|
|
185
|
+
<div className="flex items-center gap-2 min-w-0">
|
|
186
|
+
<AliasAvatar alias={name} size={16} />
|
|
187
|
+
<span className="text-gray-300 truncate">{name}</span>
|
|
188
|
+
</div>
|
|
189
|
+
<span className={`px-1.5 py-0.5 rounded border text-[10px] shrink-0 ${
|
|
176
190
|
m.role === 'owner' ? 'text-yellow-300 border-yellow-500/20' : 'text-gray-400 border-gray-600/20'
|
|
177
191
|
}`}>{m.role}</span>
|
|
178
192
|
</div>
|
|
179
|
-
|
|
193
|
+
);
|
|
194
|
+
})
|
|
180
195
|
)}
|
|
181
196
|
|
|
182
197
|
{/* Invite */}
|
|
@@ -196,8 +211,17 @@ export default function NetworksPage() {
|
|
|
196
211
|
</div>
|
|
197
212
|
{inviteCode && (
|
|
198
213
|
<div className="mt-2 bg-green-500/5 border border-green-500/20 rounded px-3 py-2">
|
|
199
|
-
<div className="
|
|
200
|
-
|
|
214
|
+
<div className="flex items-center justify-between mb-1">
|
|
215
|
+
<div className="text-[10px] text-green-400 uppercase tracking-wide">Invite code</div>
|
|
216
|
+
<button
|
|
217
|
+
type="button"
|
|
218
|
+
onClick={() => { navigator.clipboard?.writeText(inviteCode).catch(() => {}); }}
|
|
219
|
+
className="text-[10px] text-green-300 hover:text-green-200 px-1.5 py-0.5 rounded border border-green-500/20 hover:bg-green-500/10"
|
|
220
|
+
>
|
|
221
|
+
Copy
|
|
222
|
+
</button>
|
|
223
|
+
</div>
|
|
224
|
+
<code className="text-xs text-green-300 select-all break-all">{inviteCode}</code>
|
|
201
225
|
</div>
|
|
202
226
|
)}
|
|
203
227
|
</div>
|
package/app/settings/page.tsx
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
import Link from 'next/link';
|
|
5
5
|
import { useAnetConfig, useHealth, useLicense } from '../lib/hooks';
|
|
6
|
+
import { DASHBOARD_VERSION } from '../lib/version';
|
|
6
7
|
|
|
7
8
|
export default function SettingsPage() {
|
|
8
9
|
const { config } = useAnetConfig();
|
|
@@ -18,12 +19,31 @@ export default function SettingsPage() {
|
|
|
18
19
|
|
|
19
20
|
return (
|
|
20
21
|
<div className="min-h-screen bg-[#0a0a1a] text-gray-100 p-4 sm:p-6 font-mono">
|
|
21
|
-
<h1 className="text-2xl font-bold text-white mb-
|
|
22
|
+
<h1 className="text-2xl font-bold text-white mb-3 lg:ml-0 ml-10">Settings</h1>
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
{/* Section anchor nav (round 28) — jump to a group instead of scrolling
|
|
25
|
+
through the whole page. Mirrors the section headers below; pages
|
|
26
|
+
with 7+ cards benefit from a visible table-of-contents. */}
|
|
27
|
+
<nav className="mb-8 flex flex-wrap gap-1 text-xs">
|
|
28
|
+
{[
|
|
29
|
+
{ href: '#connection', label: 'Connection' },
|
|
30
|
+
{ href: '#account', label: 'Account' },
|
|
31
|
+
{ href: '#resources', label: 'Resources' },
|
|
32
|
+
].map(a => (
|
|
33
|
+
<a key={a.href} href={a.href}
|
|
34
|
+
className="rounded-md px-2.5 py-1 text-gray-500 hover:text-cyan-300 hover:bg-cyan-500/10 transition-colors">
|
|
35
|
+
{a.label}
|
|
36
|
+
</a>
|
|
37
|
+
))}
|
|
38
|
+
</nav>
|
|
39
|
+
|
|
40
|
+
<div className="max-w-2xl space-y-10">
|
|
24
41
|
{/* ── Group: Connection ─────────────────────────────────── */}
|
|
25
|
-
<div className="space-y-4">
|
|
26
|
-
<div className="
|
|
42
|
+
<div id="connection" className="space-y-4 scroll-mt-6">
|
|
43
|
+
<div className="flex items-center gap-2 px-1">
|
|
44
|
+
<div className="text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold">Connection</div>
|
|
45
|
+
<div className="flex-1 h-px bg-[#2a2a4a]" />
|
|
46
|
+
</div>
|
|
27
47
|
|
|
28
48
|
{/* CommHub Connection */}
|
|
29
49
|
<section className="bg-[#111128] border border-[#2a2a4a] rounded-xl p-5">
|
|
@@ -88,7 +108,9 @@ export default function SettingsPage() {
|
|
|
88
108
|
<div className="space-y-3 text-sm">
|
|
89
109
|
<div className={rowClass}>
|
|
90
110
|
<span className="text-gray-500">Version</span>
|
|
91
|
-
<span className={`text-gray-300 ${valueClass}`}
|
|
111
|
+
<span className={`text-gray-300 font-mono ${valueClass}`} title="From package.json @sleep2agi/agent-network-dashboard">
|
|
112
|
+
{DASHBOARD_VERSION}
|
|
113
|
+
</span>
|
|
92
114
|
</div>
|
|
93
115
|
<div className={rowClass}>
|
|
94
116
|
<span className="text-gray-500">Data Layer</span>
|
|
@@ -96,15 +118,18 @@ export default function SettingsPage() {
|
|
|
96
118
|
</div>
|
|
97
119
|
<div className={rowClass}>
|
|
98
120
|
<span className="text-gray-500">Pages</span>
|
|
99
|
-
<span className={`text-gray-300 ${valueClass}`}>Overview, Tasks, Nodes, Messages, Settings</span>
|
|
121
|
+
<span className={`text-gray-300 ${valueClass}`}>Overview, Tasks, Nodes, Messages, Networks, Audit, Server Logs, Admin, Settings</span>
|
|
100
122
|
</div>
|
|
101
123
|
</div>
|
|
102
124
|
</section>
|
|
103
125
|
</div>
|
|
104
126
|
|
|
105
127
|
{/* ── Group: Account ────────────────────────────────────── */}
|
|
106
|
-
<div className="space-y-4">
|
|
107
|
-
<div className="
|
|
128
|
+
<div id="account" className="space-y-4 scroll-mt-6">
|
|
129
|
+
<div className="flex items-center gap-2 px-1">
|
|
130
|
+
<div className="text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold">Account</div>
|
|
131
|
+
<div className="flex-1 h-px bg-[#2a2a4a]" />
|
|
132
|
+
</div>
|
|
108
133
|
|
|
109
134
|
{/* License */}
|
|
110
135
|
<section className="bg-[#111128] border border-[#2a2a4a] rounded-xl p-5">
|
|
@@ -232,8 +257,11 @@ export default function SettingsPage() {
|
|
|
232
257
|
</div>
|
|
233
258
|
|
|
234
259
|
{/* ── Group: Resources ──────────────────────────────────── */}
|
|
235
|
-
<div className="space-y-4">
|
|
236
|
-
<div className="
|
|
260
|
+
<div id="resources" className="space-y-4 scroll-mt-6">
|
|
261
|
+
<div className="flex items-center gap-2 px-1">
|
|
262
|
+
<div className="text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold">Resources</div>
|
|
263
|
+
<div className="flex-1 h-px bg-[#2a2a4a]" />
|
|
264
|
+
</div>
|
|
237
265
|
|
|
238
266
|
{/* API Tokens + Networks */}
|
|
239
267
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
package/app/tasks/page.tsx
CHANGED
|
@@ -6,6 +6,8 @@ import Link from 'next/link';
|
|
|
6
6
|
import { useNetworkId } from '../lib/network-context';
|
|
7
7
|
import { TaskDrawer } from '../components/TaskDrawer';
|
|
8
8
|
import { EmptyState } from '../components/EmptyState';
|
|
9
|
+
import { AliasAvatar } from '../components/AliasAvatar';
|
|
10
|
+
import { TASK_STATUSES, STATUS_CHIP_CLASS, STATUS_DOT_HEX, STATUS_BAR_CLASS } from '../lib/status';
|
|
9
11
|
|
|
10
12
|
interface Task {
|
|
11
13
|
task_id: string;
|
|
@@ -23,48 +25,8 @@ interface Task {
|
|
|
23
25
|
expires_at: string;
|
|
24
26
|
}
|
|
25
27
|
|
|
26
|
-
const STATUS_OPTIONS = [
|
|
27
|
-
'',
|
|
28
|
-
'created',
|
|
29
|
-
'delivered',
|
|
30
|
-
'acked',
|
|
31
|
-
'running',
|
|
32
|
-
'replied',
|
|
33
|
-
'closed',
|
|
34
|
-
'failed',
|
|
35
|
-
'cancelled',
|
|
36
|
-
'expired',
|
|
37
|
-
];
|
|
38
|
-
|
|
39
|
-
const STATUS_COLORS: Record<string, string> = {
|
|
40
|
-
created: 'bg-gray-500/10 text-gray-400 border-gray-500/20',
|
|
41
|
-
delivered: 'bg-blue-500/10 text-blue-300 border-blue-500/20',
|
|
42
|
-
acked: 'bg-cyan-500/10 text-cyan-300 border-cyan-500/20',
|
|
43
|
-
running: 'bg-green-500/10 text-green-300 border-green-500/20',
|
|
44
|
-
replied: 'bg-purple-500/10 text-purple-300 border-purple-500/20',
|
|
45
|
-
closed: 'bg-gray-500/10 text-gray-500 border-gray-500/20',
|
|
46
|
-
failed: 'bg-red-500/10 text-red-300 border-red-500/20',
|
|
47
|
-
cancelled: 'bg-yellow-500/10 text-yellow-300 border-yellow-500/20',
|
|
48
|
-
expired: 'bg-orange-500/10 text-orange-300 border-orange-500/20',
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
/** Small colored dot per status — visible on every tab (active + inactive)
|
|
52
|
-
* so users can scan the row at a glance. Hex inlined to avoid Tailwind
|
|
53
|
-
* purging dynamic `bg-${family}-400` class names. */
|
|
54
|
-
const STATUS_DOTS: Record<string, string> = {
|
|
55
|
-
created: '#9ca3af',
|
|
56
|
-
delivered: '#60a5fa',
|
|
57
|
-
acked: '#22d3ee',
|
|
58
|
-
running: '#4ade80',
|
|
59
|
-
replied: '#a78bfa',
|
|
60
|
-
closed: '#6b7280',
|
|
61
|
-
failed: '#f87171',
|
|
62
|
-
cancelled: '#facc15',
|
|
63
|
-
expired: '#fb923c',
|
|
64
|
-
};
|
|
65
|
-
|
|
66
28
|
function statusBadge(status: string) {
|
|
67
|
-
const color =
|
|
29
|
+
const color = STATUS_CHIP_CLASS[status] || 'bg-gray-500/10 text-gray-400 border-gray-500/20';
|
|
68
30
|
return `text-xs px-2 py-0.5 rounded-md border ${color}`;
|
|
69
31
|
}
|
|
70
32
|
|
|
@@ -158,42 +120,73 @@ function TasksContent() {
|
|
|
158
120
|
elements) hinting more content. */}
|
|
159
121
|
<div className="anet-tabstrip-wrap mb-4">
|
|
160
122
|
<div className="anet-tabstrip flex sm:flex-wrap gap-1 bg-[#111128] rounded-lg border border-[#2a2a4a] p-1 overflow-x-auto sm:overflow-x-visible scrollbar-thin">
|
|
161
|
-
{
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
123
|
+
{(() => {
|
|
124
|
+
// Round 56: compute per-status counts so the tab strip doubles as a
|
|
125
|
+
// status distribution dashboard. Matches Audit Log (r43) + Overview
|
|
126
|
+
// agent filter (r34) chip-with-count pattern.
|
|
127
|
+
const counts: Record<string, number> = {};
|
|
128
|
+
tasks.forEach(t => { counts[t.status] = (counts[t.status] || 0) + 1; });
|
|
129
|
+
return ['', ...TASK_STATUSES].map(s => {
|
|
130
|
+
const count = s === '' ? tasks.length : counts[s] || 0;
|
|
131
|
+
const isActive = filterStatus === s;
|
|
132
|
+
return (
|
|
133
|
+
<button
|
|
134
|
+
key={s}
|
|
135
|
+
onClick={() => setFilterStatus(s)}
|
|
136
|
+
disabled={count === 0 && s !== '' && !isActive}
|
|
137
|
+
className={`px-3 py-1.5 rounded-md text-xs transition-colors flex items-center gap-1.5 shrink-0 whitespace-nowrap disabled:opacity-30 disabled:cursor-not-allowed ${
|
|
138
|
+
isActive
|
|
139
|
+
? `${STATUS_CHIP_CLASS[s] || 'bg-cyan-500/10 text-cyan-300 border-cyan-500/20'} border`
|
|
140
|
+
: 'text-gray-500 hover:text-gray-300 hover:bg-[#1a1a2a]/40'
|
|
141
|
+
}`}
|
|
142
|
+
>
|
|
143
|
+
{s && (
|
|
144
|
+
<span
|
|
145
|
+
aria-hidden
|
|
146
|
+
className="inline-block w-1.5 h-1.5 rounded-full shrink-0"
|
|
147
|
+
style={{ backgroundColor: STATUS_DOT_HEX[s] || '#6b7280' }}
|
|
148
|
+
/>
|
|
149
|
+
)}
|
|
150
|
+
<span>{s || 'All'}</span>
|
|
151
|
+
<span className={`text-[10px] tabular-nums ${isActive ? 'opacity-80' : 'text-gray-600'}`}>{count}</span>
|
|
152
|
+
</button>
|
|
153
|
+
);
|
|
154
|
+
});
|
|
155
|
+
})()}
|
|
178
156
|
</div>
|
|
179
157
|
</div>
|
|
180
158
|
|
|
181
|
-
{/* From/To Filters */}
|
|
182
|
-
<div className="flex flex-wrap gap-
|
|
183
|
-
<
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
159
|
+
{/* From/To Filters — same visual block as the status tabs above. */}
|
|
160
|
+
<div className="flex flex-wrap items-center gap-2 mb-6">
|
|
161
|
+
<div className="flex items-center gap-1.5 rounded-lg border border-[#2a2a4a] bg-[#111128] px-2.5 py-1.5 focus-within:border-blue-500/40">
|
|
162
|
+
<span className="text-[10px] uppercase tracking-wide text-gray-600">From</span>
|
|
163
|
+
<input
|
|
164
|
+
type="text"
|
|
165
|
+
value={filterFrom}
|
|
166
|
+
onChange={e => setFilterFrom(e.target.value)}
|
|
167
|
+
placeholder="any node"
|
|
168
|
+
className="w-28 bg-transparent text-sm text-white placeholder-gray-700 focus:outline-none"
|
|
169
|
+
/>
|
|
170
|
+
</div>
|
|
171
|
+
<div className="flex items-center gap-1.5 rounded-lg border border-[#2a2a4a] bg-[#111128] px-2.5 py-1.5 focus-within:border-blue-500/40">
|
|
172
|
+
<span className="text-[10px] uppercase tracking-wide text-gray-600">To</span>
|
|
173
|
+
<input
|
|
174
|
+
type="text"
|
|
175
|
+
value={filterTo}
|
|
176
|
+
onChange={e => setFilterTo(e.target.value)}
|
|
177
|
+
placeholder="any node"
|
|
178
|
+
className="w-28 bg-transparent text-sm text-white placeholder-gray-700 focus:outline-none"
|
|
179
|
+
/>
|
|
180
|
+
</div>
|
|
181
|
+
{(filterStatus || filterFrom || filterTo) && (
|
|
182
|
+
<button
|
|
183
|
+
type="button"
|
|
184
|
+
onClick={() => { setFilterStatus(''); setFilterFrom(''); setFilterTo(''); }}
|
|
185
|
+
className="rounded-lg border border-gray-700 px-2.5 py-1.5 text-[11px] text-gray-500 hover:text-gray-200 hover:border-gray-600"
|
|
186
|
+
>
|
|
187
|
+
Clear filters
|
|
188
|
+
</button>
|
|
189
|
+
)}
|
|
197
190
|
</div>
|
|
198
191
|
|
|
199
192
|
{/* Status distribution */}
|
|
@@ -201,21 +194,21 @@ function TasksContent() {
|
|
|
201
194
|
const stats: Record<string, number> = {};
|
|
202
195
|
tasks.forEach(t => { stats[t.status] = (stats[t.status] || 0) + 1; });
|
|
203
196
|
const total = tasks.length || 1;
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
{ key
|
|
209
|
-
|
|
210
|
-
].filter(b => stats[b.key]);
|
|
197
|
+
// Round 67: derive from shared TASK_STATUSES + STATUS_BAR_CLASS in
|
|
198
|
+
// app/lib/status.ts. Adding a new lifecycle status updates badge,
|
|
199
|
+
// tab dots, and bar in one edit.
|
|
200
|
+
const bars = TASK_STATUSES
|
|
201
|
+
.map(key => ({ key, color: STATUS_BAR_CLASS[key] }))
|
|
202
|
+
.filter(b => stats[b.key]);
|
|
211
203
|
if (!bars.length) return null;
|
|
204
|
+
// Round 63: removed the per-status legend row beneath the bar —
|
|
205
|
+
// it duplicated the counts already shown in the tab chip strip
|
|
206
|
+
// since r56. The proportional bar stays because it adds a visual
|
|
207
|
+
// "shape of workload" that the chip numbers don't convey.
|
|
212
208
|
return (
|
|
213
209
|
<div className="mb-6">
|
|
214
210
|
<div className="flex h-2 rounded-full overflow-hidden bg-gray-800">
|
|
215
|
-
{bars.map(b => <div key={b.key} className={b.color} style={{ width: `${(stats[b.key]/total)*100}%` }} />)}
|
|
216
|
-
</div>
|
|
217
|
-
<div className="flex flex-wrap gap-3 mt-1.5 text-[10px] text-gray-500">
|
|
218
|
-
{bars.map(b => <span key={b.key}><span className={`inline-block w-2 h-2 rounded-full ${b.color} mr-1`} />{stats[b.key]} {b.key}</span>)}
|
|
211
|
+
{bars.map(b => <div key={b.key} className={b.color} style={{ width: `${(stats[b.key]/total)*100}%` }} title={`${b.key}: ${stats[b.key]}`} />)}
|
|
219
212
|
</div>
|
|
220
213
|
</div>
|
|
221
214
|
);
|
|
@@ -276,11 +269,13 @@ function TasksContent() {
|
|
|
276
269
|
<div className="col-span-1">
|
|
277
270
|
<span className={statusBadge(t.status)}>{t.status}</span>
|
|
278
271
|
</div>
|
|
279
|
-
<div className="col-span-2
|
|
280
|
-
{t.from_name
|
|
272
|
+
<div className="col-span-2 flex items-center gap-1.5 min-w-0" title={t.from_name}>
|
|
273
|
+
{t.from_name && <AliasAvatar alias={t.from_name} size={18} />}
|
|
274
|
+
<span className="truncate text-sm text-gray-200">{t.from_name || '--'}</span>
|
|
281
275
|
</div>
|
|
282
|
-
<div className="col-span-2
|
|
283
|
-
{t.to_name
|
|
276
|
+
<div className="col-span-2 flex items-center gap-1.5 min-w-0" title={t.to_name}>
|
|
277
|
+
{t.to_name && <AliasAvatar alias={t.to_name} size={18} />}
|
|
278
|
+
<span className="truncate text-sm text-gray-200">{t.to_name || '--'}</span>
|
|
284
279
|
</div>
|
|
285
280
|
<div className="col-span-4 text-xs text-gray-400 truncate" title={t.content}>
|
|
286
281
|
{t.content || '--'}
|
|
@@ -315,10 +310,12 @@ function TasksContent() {
|
|
|
315
310
|
</svg>
|
|
316
311
|
</div>
|
|
317
312
|
</div>
|
|
318
|
-
<div className="text-xs text-gray-
|
|
319
|
-
<
|
|
320
|
-
<span className="
|
|
321
|
-
<span className="text-
|
|
313
|
+
<div className="flex items-center gap-1.5 text-xs text-gray-300 min-w-0">
|
|
314
|
+
{t.from_name && <AliasAvatar alias={t.from_name} size={16} />}
|
|
315
|
+
<span className="truncate max-w-[40%]">{t.from_name || '--'}</span>
|
|
316
|
+
<span className="text-gray-600">→</span>
|
|
317
|
+
{t.to_name && <AliasAvatar alias={t.to_name} size={16} />}
|
|
318
|
+
<span className="truncate max-w-[40%]">{t.to_name || '--'}</span>
|
|
322
319
|
</div>
|
|
323
320
|
<div className="text-xs text-gray-400 line-clamp-1">{t.content || '--'}</div>
|
|
324
321
|
<div className="text-xs text-gray-600">{timeAgo(t.created_at)}</div>
|
package/package.json
CHANGED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
module.exports=[50227,(a,b,c)=>{b.exports=a.x("node:path",()=>require("node:path"))},43515,a=>{"use strict";a.s(["formatUptime",0,function(a){let b=Math.floor(a/3600),c=Math.floor(a%3600/60);return b>0?`${b}h ${c}m`:`${c}m`},"timeAgo",0,function(a){if(!a)return"--";let b=Math.floor((Date.now()-new Date(a.replace(" ","T")+"Z").getTime())/1e3);return b<60?`${b}s ago`:b<3600?`${Math.floor(b/60)}m ago`:b<86400?`${Math.floor(b/3600)}h ago`:`${Math.floor(b/86400)}d ago`}])},53142,a=>{"use strict";var b=a.i(87924),c=a.i(38246);let d={nodes:{title:"No agents in this network",sub:"Agent sessions will appear here once they connect to the CommHub."},tasks:{title:"No tasks yet",sub:"Tasks will appear here when agents send them via CommHub."},messages:{title:"No messages",sub:"Messages between agents will appear here."},logs:{title:"No audit logs",sub:"Events will appear here when users register, login, or perform actions."},tokens:{title:"No API tokens",sub:"Create one to authenticate CLI tools and external integrations."},networks:{title:"No networks found",sub:"Create one or sign in with V3 auth to see your networks."},generic:{title:"Nothing here yet",sub:"Data will appear here once available."}};function e({variant:a,size:c}){let d={width:c,height:c},f={fill:"none",stroke:"currentColor",strokeWidth:1.25,strokeLinecap:"round",strokeLinejoin:"round"};switch(a){case"nodes":return(0,b.jsx)("svg",{viewBox:"0 0 64 64",...d,children:(0,b.jsxs)("g",{...f,children:[(0,b.jsx)("circle",{cx:"32",cy:"14",r:"4"}),(0,b.jsx)("circle",{cx:"14",cy:"44",r:"4"}),(0,b.jsx)("circle",{cx:"50",cy:"44",r:"4"}),(0,b.jsx)("line",{x1:"32",y1:"18",x2:"14",y2:"40",strokeDasharray:"3 3",opacity:"0.6"}),(0,b.jsx)("line",{x1:"32",y1:"18",x2:"50",y2:"40",strokeDasharray:"3 3",opacity:"0.6"}),(0,b.jsx)("line",{x1:"18",y1:"44",x2:"46",y2:"44",strokeDasharray:"3 3",opacity:"0.6"})]})});case"tasks":return(0,b.jsx)("svg",{viewBox:"0 0 64 64",...d,children:(0,b.jsxs)("g",{...f,children:[(0,b.jsx)("rect",{x:"14",y:"14",width:"36",height:"6",rx:"1.5"}),(0,b.jsx)("rect",{x:"14",y:"26",width:"36",height:"6",rx:"1.5",opacity:"0.6"}),(0,b.jsx)("rect",{x:"14",y:"38",width:"36",height:"6",rx:"1.5",opacity:"0.35"})]})});case"messages":return(0,b.jsx)("svg",{viewBox:"0 0 64 64",...d,children:(0,b.jsxs)("g",{...f,children:[(0,b.jsx)("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"}),(0,b.jsx)("line",{x1:"22",y1:"28",x2:"42",y2:"28",opacity:"0.5"}),(0,b.jsx)("line",{x1:"22",y1:"34",x2:"36",y2:"34",opacity:"0.5"})]})});case"logs":return(0,b.jsx)("svg",{viewBox:"0 0 64 64",...d,children:(0,b.jsxs)("g",{...f,children:[(0,b.jsx)("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"}),(0,b.jsx)("path",{d:"M40 12 v8 h8",opacity:"0.6"}),(0,b.jsx)("line",{x1:"24",y1:"32",x2:"40",y2:"32",opacity:"0.55"}),(0,b.jsx)("line",{x1:"24",y1:"38",x2:"40",y2:"38",opacity:"0.4"}),(0,b.jsx)("line",{x1:"24",y1:"44",x2:"34",y2:"44",opacity:"0.25"})]})});case"tokens":return(0,b.jsx)("svg",{viewBox:"0 0 64 64",...d,children:(0,b.jsxs)("g",{...f,children:[(0,b.jsx)("circle",{cx:"22",cy:"32",r:"8"}),(0,b.jsx)("line",{x1:"30",y1:"32",x2:"54",y2:"32"}),(0,b.jsx)("line",{x1:"44",y1:"32",x2:"44",y2:"38"}),(0,b.jsx)("line",{x1:"50",y1:"32",x2:"50",y2:"40"})]})});case"networks":return(0,b.jsx)("svg",{viewBox:"0 0 64 64",...d,children:(0,b.jsxs)("g",{...f,children:[(0,b.jsx)("circle",{cx:"32",cy:"32",r:"18"}),(0,b.jsx)("ellipse",{cx:"32",cy:"32",rx:"18",ry:"9",opacity:"0.55"}),(0,b.jsx)("line",{x1:"14",y1:"32",x2:"50",y2:"32",opacity:"0.55"}),(0,b.jsx)("line",{x1:"32",y1:"14",x2:"32",y2:"50",opacity:"0.55"})]})});default:return(0,b.jsx)("svg",{viewBox:"0 0 64 64",...d,children:(0,b.jsxs)("g",{...f,children:[(0,b.jsx)("circle",{cx:"32",cy:"32",r:"14",strokeDasharray:"3 3",opacity:"0.6"}),(0,b.jsx)("circle",{cx:"32",cy:"32",r:"3"})]})})}}function f({variant:a="generic",title:g,sub:h,cta:i,compact:j=!1}){let k=d[a],l=g??k.title,m=h??k.sub;return(0,b.jsxs)("div",{className:`text-center ${j?"py-8":"py-16"} px-4`,role:"status",children:[(0,b.jsx)("div",{className:"anet-empty-glyph inline-flex items-center justify-center mb-4 text-gray-500","aria-hidden":!0,children:(0,b.jsx)(e,{variant:a,size:j?40:56})}),(0,b.jsx)("h3",{className:`font-medium text-gray-300 ${j?"text-sm":"text-base"}`,children:l}),m&&(0,b.jsx)("p",{className:`text-gray-500 ${j?"text-xs mt-1.5":"text-sm mt-2"} max-w-md mx-auto leading-relaxed`,children:m}),i&&(0,b.jsx)("div",{className:"mt-4",children:i.href?(0,b.jsxs)(c.default,{href:i.href,className:"inline-flex items-center gap-1.5 text-sm font-medium text-cyan-400 hover:text-cyan-300",children:[i.label,(0,b.jsx)("span",{"aria-hidden":!0,children:"→"})]}):(0,b.jsxs)("button",{onClick:i.onClick,className:"inline-flex items-center gap-1.5 text-sm font-medium text-cyan-400 hover:text-cyan-300",children:[i.label,(0,b.jsx)("span",{"aria-hidden":!0,children:"→"})]})})]})}a.s(["EmptyState",0,f,"NodesEmptyState",0,function({hint:a}){return a?.global_count?(0,b.jsx)(f,{variant:"nodes",title:"No agents in this network",sub:`Server has ${a.global_count} nodes globally, but none are registered to the current network. Switch network or contact admin.`}):(0,b.jsx)(f,{variant:"nodes",cta:{label:"Run anet quickstart",href:"https://anet.sh"}})}])},44332,a=>{"use strict";var b=a.i(72596),c=a.i(22397);let d=async a=>{let b=await fetch(a);if(401===b.status)throw window.location.assign("/login"),Error("unauthorized");return b.json()},e={refreshInterval:5e3,dedupingInterval:3e3};function f(a,b){if(!b)return a;let c=a.includes("?")?"&":"?";return`${a}${c}network_id=${encodeURIComponent(b)}`}a.s(["useAnetConfig",0,function(){let{data:a}=(0,b.default)("/api/anet/config",d,{refreshInterval:3e4});return{config:a||null}},"useHealth",0,function(){let{data:a,error:c}=(0,b.default)("/api/hub/health",d,e);return{health:a||null,error:c}},"useLicense",0,function(){let{data:a,error:c}=(0,b.default)("/api/hub/license",d,{refreshInterval:6e4});return{license:a?.ok?a:null,error:c}},"useMessages",0,function(a=100){let{networkId:g}=(0,c.useNetworkId)(),{data:h,error:i,isLoading:j}=(0,b.default)(f(`/api/hub/messages?limit=${a}`,g),d,e);return{messages:h?.messages||[],error:i,isLoading:j}},"useSessions",0,function(){let{networkId:a}=(0,c.useNetworkId)(),{data:g,error:h,isLoading:i}=(0,b.default)(f("/api/hub/status",a),d,e);return{sessions:g?.sessions||[],hint:g?._hint,error:h,isLoading:i}},"useStats",0,function(){let{networkId:a}=(0,c.useNetworkId)(),{data:g,error:h}=(0,b.default)(f("/api/hub/stats",a),d,e);return{stats:g?.ok?g:null,error:h}},"useTasks",0,function(a){let{networkId:g}=(0,c.useNetworkId)(),h=new URLSearchParams({limit:"100",...a}).toString(),{data:i,error:j,isLoading:k}=(0,b.default)(f(`/api/hub/tasks?${h}`,g),d,e);return{tasks:i?.tasks||[],count:i?.count??0,source:i?.source,error:j,isLoading:k}}])},54826,(a,b,c)=>{},15299,(a,b,c)=>{a.r(54826);var d=a.r(72131),e=d&&"object"==typeof d&&"default"in d?d:{default:d},f="u">typeof process&&process.env&&!0,g=function(a){return"[object String]"===Object.prototype.toString.call(a)},h=function(){function a(a){var b=void 0===a?{}:a,c=b.name,d=void 0===c?"stylesheet":c,e=b.optimizeForSpeed,h=void 0===e?f:e;i(g(d),"`name` must be a string"),this._name=d,this._deletedRulePlaceholder="#"+d+"-deleted-rule____{}",i("boolean"==typeof h,"`optimizeForSpeed` must be a boolean"),this._optimizeForSpeed=h,this._serverSheet=void 0,this._tags=[],this._injected=!1,this._rulesCount=0,this._nonce=null}var b,c=a.prototype;return c.setOptimizeForSpeed=function(a){i("boolean"==typeof a,"`setOptimizeForSpeed` accepts a boolean"),i(0===this._rulesCount,"optimizeForSpeed cannot be when rules have already been inserted"),this.flush(),this._optimizeForSpeed=a,this.inject()},c.isOptimizeForSpeed=function(){return this._optimizeForSpeed},c.inject=function(){var a=this;i(!this._injected,"sheet already injected"),this._injected=!0,this._serverSheet={cssRules:[],insertRule:function(b,c){return"number"==typeof c?a._serverSheet.cssRules[c]={cssText:b}:a._serverSheet.cssRules.push({cssText:b}),c},deleteRule:function(b){a._serverSheet.cssRules[b]=null}}},c.getSheetForTag=function(a){if(a.sheet)return a.sheet;for(var b=0;b<document.styleSheets.length;b++)if(document.styleSheets[b].ownerNode===a)return document.styleSheets[b]},c.getSheet=function(){return this.getSheetForTag(this._tags[this._tags.length-1])},c.insertRule=function(a,b){return i(g(a),"`insertRule` accepts only strings"),"number"!=typeof b&&(b=this._serverSheet.cssRules.length),this._serverSheet.insertRule(a,b),this._rulesCount++},c.replaceRule=function(a,b){this._optimizeForSpeed;var c=this._serverSheet;if(b.trim()||(b=this._deletedRulePlaceholder),!c.cssRules[a])return a;c.deleteRule(a);try{c.insertRule(b,a)}catch(d){f||console.warn("StyleSheet: illegal rule: \n\n"+b+"\n\nSee https://stackoverflow.com/q/20007992 for more info"),c.insertRule(this._deletedRulePlaceholder,a)}return a},c.deleteRule=function(a){this._serverSheet.deleteRule(a)},c.flush=function(){this._injected=!1,this._rulesCount=0,this._serverSheet.cssRules=[]},c.cssRules=function(){return this._serverSheet.cssRules},c.makeStyleTag=function(a,b,c){b&&i(g(b),"makeStyleTag accepts only strings as second parameter");var d=document.createElement("style");this._nonce&&d.setAttribute("nonce",this._nonce),d.type="text/css",d.setAttribute("data-"+a,""),b&&d.appendChild(document.createTextNode(b));var e=document.head||document.getElementsByTagName("head")[0];return c?e.insertBefore(d,c):e.appendChild(d),d},b=[{key:"length",get:function(){return this._rulesCount}}],function(a,b){for(var c=0;c<b.length;c++){var d=b[c];d.enumerable=d.enumerable||!1,d.configurable=!0,"value"in d&&(d.writable=!0),Object.defineProperty(a,d.key,d)}}(a.prototype,b),a}();function i(a,b){if(!a)throw Error("StyleSheet: "+b+".")}var j=function(a){for(var b=5381,c=a.length;c;)b=33*b^a.charCodeAt(--c);return b>>>0},k={};function l(a,b){if(!b)return"jsx-"+a;var c=String(b),d=a+c;return k[d]||(k[d]="jsx-"+j(a+"-"+c)),k[d]}function m(a,b){var c=a+(b=b.replace(/\/style/gi,"\\/style"));return k[c]||(k[c]=b.replace(/__jsx-style-dynamic-selector/g,a)),k[c]}var n=function(){function a(a){var b=void 0===a?{}:a,c=b.styleSheet,d=void 0===c?null:c,e=b.optimizeForSpeed,f=void 0!==e&&e;this._sheet=d||new h({name:"styled-jsx",optimizeForSpeed:f}),this._sheet.inject(),d&&"boolean"==typeof f&&(this._sheet.setOptimizeForSpeed(f),this._optimizeForSpeed=this._sheet.isOptimizeForSpeed()),this._fromServer=void 0,this._indices={},this._instancesCounts={}}var b=a.prototype;return b.add=function(a){var b=this;void 0===this._optimizeForSpeed&&(this._optimizeForSpeed=Array.isArray(a.children),this._sheet.setOptimizeForSpeed(this._optimizeForSpeed),this._optimizeForSpeed=this._sheet.isOptimizeForSpeed());var c=this.getIdAndRules(a),d=c.styleId,e=c.rules;if(d in this._instancesCounts){this._instancesCounts[d]+=1;return}var f=e.map(function(a){return b._sheet.insertRule(a)}).filter(function(a){return -1!==a});this._indices[d]=f,this._instancesCounts[d]=1},b.remove=function(a){var b=this,c=this.getIdAndRules(a).styleId;if(function(a,b){if(!a)throw Error("StyleSheetRegistry: "+b+".")}(c in this._instancesCounts,"styleId: `"+c+"` not found"),this._instancesCounts[c]-=1,this._instancesCounts[c]<1){var d=this._fromServer&&this._fromServer[c];d?(d.parentNode.removeChild(d),delete this._fromServer[c]):(this._indices[c].forEach(function(a){return b._sheet.deleteRule(a)}),delete this._indices[c]),delete this._instancesCounts[c]}},b.update=function(a,b){this.add(b),this.remove(a)},b.flush=function(){this._sheet.flush(),this._sheet.inject(),this._fromServer=void 0,this._indices={},this._instancesCounts={}},b.cssRules=function(){var a=this,b=this._fromServer?Object.keys(this._fromServer).map(function(b){return[b,a._fromServer[b]]}):[],c=this._sheet.cssRules();return b.concat(Object.keys(this._indices).map(function(b){return[b,a._indices[b].map(function(a){return c[a].cssText}).join(a._optimizeForSpeed?"":"\n")]}).filter(function(a){return!!a[1]}))},b.styles=function(a){var b,c;return b=this.cssRules(),void 0===(c=a)&&(c={}),b.map(function(a){var b=a[0],d=a[1];return e.default.createElement("style",{id:"__"+b,key:"__"+b,nonce:c.nonce?c.nonce:void 0,dangerouslySetInnerHTML:{__html:d}})})},b.getIdAndRules=function(a){var b=a.children,c=a.dynamic,d=a.id;if(c){var e=l(d,c);return{styleId:e,rules:Array.isArray(b)?b.map(function(a){return m(e,a)}):[m(e,b)]}}return{styleId:l(d),rules:Array.isArray(b)?b:[b]}},b.selectFromServer=function(){return Array.prototype.slice.call(document.querySelectorAll('[id^="__jsx-"]')).reduce(function(a,b){return a[b.id.slice(2)]=b,a},{})},a}(),o=d.createContext(null);function p(){return new n}function q(){return d.useContext(o)}function r(a){var b=q();return b&&b.add(a),null}o.displayName="StyleSheetContext",e.default.useInsertionEffect||e.default.useLayoutEffect,r.dynamic=function(a){return a.map(function(a){return l(a[0],a[1])}).join(" ")},c.StyleRegistry=function(a){var b=a.registry,c=a.children,f=d.useContext(o),g=d.useState(function(){return f||b||p()})[0];return e.default.createElement(o.Provider,{value:g},c)},c.createStyleRegistry=p,c.style=r,c.useStyleRegistry=q},31626,(a,b,c)=>{b.exports=a.r(15299).style}];
|
|
2
|
-
|
|
3
|
-
//# sourceMappingURL=%5Broot-of-the-server%5D__0_jnflc._.js.map
|