@sleep2agi/agent-network-dashboard 0.4.5-preview.4 → 0.4.5-preview.41
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_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_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]__0jjqrcf._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0jjqrcf._.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_0dk5wao._.js +1 -1
- package/.next/server/chunks/ssr/app_0dk5wao._.js.map +1 -1
- 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_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_components_0lhp_k.._.js +3 -0
- package/.next/server/chunks/ssr/app_components_0lhp_k.._.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_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/02oje7pf-g1v5.js +1 -0
- package/.next/static/chunks/06x7w8nwggx~~.js +1 -0
- package/.next/static/chunks/0943n0t.9c-o2.js +1 -0
- package/.next/static/chunks/{07okhs5561y5y.js → 0c1bp~g7.8ru..js} +1 -1
- package/.next/static/chunks/0csmku~3y472t.js +1 -0
- package/.next/static/chunks/0df0py1glk9xm.js +1 -0
- package/.next/static/chunks/0edt_z0rlxgfk.js +1 -0
- package/.next/static/chunks/0g394kqz_d5.x.js +1 -0
- package/.next/static/chunks/0irkayokwc1fm.js +1 -0
- package/.next/static/chunks/0j8ee64jv6zb7.js +7 -0
- package/.next/static/chunks/0qe_pfeioih-5.css +2 -0
- package/.next/static/chunks/0qnpc7rbxn12u.js +1 -0
- package/.next/static/chunks/0xdl435t_mf1c.js +1 -0
- package/.next/static/chunks/0~n.cadw9_e8s.js +7 -0
- package/.next/static/chunks/11_n-vjzf735y.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/version.ts +7 -0
- package/app/login/page.tsx +37 -7
- package/app/logs/page.tsx +72 -21
- package/app/messages/page.tsx +85 -51
- package/app/node/page.tsx +32 -15
- package/app/nodes/page.tsx +21 -23
- package/app/page.tsx +71 -13
- package/app/server-logs/page.tsx +37 -3
- package/app/settings/networks/page.tsx +37 -13
- package/app/settings/page.tsx +38 -10
- package/app/tasks/page.tsx +77 -41
- 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_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_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/03sm_xa792mxv.css +0 -2
- 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/0lo_g.q1fm-hr.js +0 -7
- package/.next/static/chunks/0m328uz90rp81.js +0 -1
- package/.next/static/chunks/0ogeals5ufhho.js +0 -1
- 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/{dvKGMaUCm52sSTROKhYVL → t8ckUU0UVyOpv2ymrRHll}/_buildManifest.js +0 -0
- /package/.next/static/{dvKGMaUCm52sSTROKhYVL → t8ckUU0UVyOpv2ymrRHll}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{dvKGMaUCm52sSTROKhYVL → t8ckUU0UVyOpv2ymrRHll}/_ssgManifest.js +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useEffect, useState } from 'react';
|
|
3
|
+
import { useEffect, useState, useRef } from 'react';
|
|
4
|
+
import { useRouter } from 'next/navigation';
|
|
4
5
|
|
|
5
6
|
/** Help overlay — press `?` to see keyboard shortcuts.
|
|
6
7
|
* Restrained: no animation noise, single column, all global keys in one
|
|
@@ -23,29 +24,52 @@ const SHORTCUTS: { group: string; items: Shortcut[] }[] = [
|
|
|
23
24
|
],
|
|
24
25
|
},
|
|
25
26
|
{
|
|
26
|
-
group: '
|
|
27
|
+
group: 'Navigate (vim-style)',
|
|
27
28
|
items: [
|
|
28
|
-
{ keys: ['
|
|
29
|
-
{ keys: ['
|
|
30
|
-
{ keys: ['
|
|
29
|
+
{ keys: ['g', 'o'], label: 'Go to Overview' },
|
|
30
|
+
{ keys: ['g', 't'], label: 'Go to Tasks' },
|
|
31
|
+
{ keys: ['g', 'n'], label: 'Go to Nodes' },
|
|
32
|
+
{ keys: ['g', 'm'], label: 'Go to Messages' },
|
|
33
|
+
{ keys: ['g', 'w'], label: 'Go to Networks' },
|
|
34
|
+
{ keys: ['g', 'a'], label: 'Go to Admin' },
|
|
35
|
+
{ keys: ['g', 'l'], label: 'Go to Audit Log' },
|
|
36
|
+
{ keys: ['g', 's'], label: 'Go to Settings' },
|
|
31
37
|
],
|
|
32
38
|
},
|
|
33
39
|
{
|
|
34
|
-
group: '
|
|
40
|
+
group: 'Command palette',
|
|
35
41
|
items: [
|
|
36
|
-
{ keys: ['
|
|
37
|
-
{ keys: ['
|
|
42
|
+
{ keys: ['↑', '↓'], label: 'Move selection' },
|
|
43
|
+
{ keys: ['↵'], label: 'Activate selected command' },
|
|
44
|
+
{ keys: ['type'], label: 'Filter — searches commands, agents, tasks' },
|
|
38
45
|
],
|
|
39
46
|
},
|
|
40
47
|
];
|
|
41
48
|
|
|
49
|
+
const GO_TARGETS: Record<string, string> = {
|
|
50
|
+
o: '/',
|
|
51
|
+
t: '/tasks',
|
|
52
|
+
n: '/nodes',
|
|
53
|
+
m: '/messages',
|
|
54
|
+
w: '/settings/networks',
|
|
55
|
+
a: '/admin',
|
|
56
|
+
l: '/logs',
|
|
57
|
+
s: '/settings',
|
|
58
|
+
};
|
|
59
|
+
|
|
42
60
|
export function HelpOverlay() {
|
|
43
61
|
const [open, setOpen] = useState(false);
|
|
62
|
+
const router = useRouter();
|
|
63
|
+
/** Timestamp when `g` was last pressed. The next single letter within
|
|
64
|
+
* 1500ms is interpreted as the target page. vim-style `g o`, `g t`, etc. */
|
|
65
|
+
const gAtRef = useRef<number>(0);
|
|
44
66
|
|
|
45
67
|
useEffect(() => {
|
|
46
68
|
const onKey = (e: KeyboardEvent) => {
|
|
69
|
+
const tag = document.activeElement?.tagName;
|
|
70
|
+
const inInput = tag === 'INPUT' || tag === 'TEXTAREA' || (document.activeElement as HTMLElement | null)?.isContentEditable;
|
|
47
71
|
// `?` toggles — Shift+/ on US layout. Only when no input is focused.
|
|
48
|
-
if (e.key === '?' &&
|
|
72
|
+
if (e.key === '?' && !inInput) {
|
|
49
73
|
e.preventDefault();
|
|
50
74
|
setOpen(prev => !prev);
|
|
51
75
|
return;
|
|
@@ -53,10 +77,26 @@ export function HelpOverlay() {
|
|
|
53
77
|
if (e.key === 'Escape' && open) {
|
|
54
78
|
setOpen(false);
|
|
55
79
|
}
|
|
80
|
+
// Vim-style `g + letter` route shortcuts (round 35). Skip when modifier
|
|
81
|
+
// keys are held (g is a perfectly fine letter when ⌘ is involved) and
|
|
82
|
+
// when typing into a field.
|
|
83
|
+
if (inInput || e.metaKey || e.ctrlKey || e.altKey) return;
|
|
84
|
+
if (e.key === 'g') {
|
|
85
|
+
gAtRef.current = Date.now();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (Date.now() - gAtRef.current < 1500) {
|
|
89
|
+
const target = GO_TARGETS[e.key.toLowerCase()];
|
|
90
|
+
if (target) {
|
|
91
|
+
e.preventDefault();
|
|
92
|
+
gAtRef.current = 0;
|
|
93
|
+
router.push(target);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
56
96
|
};
|
|
57
97
|
window.addEventListener('keydown', onKey);
|
|
58
98
|
return () => window.removeEventListener('keydown', onKey);
|
|
59
|
-
}, [open]);
|
|
99
|
+
}, [open, router]);
|
|
60
100
|
|
|
61
101
|
if (!open) return null;
|
|
62
102
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { InboxMessage } from './types';
|
|
4
|
+
import { AliasAvatar } from './AliasAvatar';
|
|
5
|
+
import { timeAgo } from './utils';
|
|
4
6
|
|
|
5
7
|
interface InboxPanelProps {
|
|
6
8
|
messages: InboxMessage[];
|
|
@@ -20,9 +22,10 @@ export function InboxPanel({ messages }: InboxPanelProps) {
|
|
|
20
22
|
<div className="space-y-2 max-h-96 overflow-y-auto pr-1 scrollbar-thin">
|
|
21
23
|
{messages.map(m => (
|
|
22
24
|
<div key={m.id} className="bg-[#111128] border border-[#2a2a4a] rounded-lg px-4 py-3 text-sm transition-colors hover:border-[#3a3a5a]">
|
|
23
|
-
<div className="flex
|
|
24
|
-
<
|
|
25
|
-
<span>{m.
|
|
25
|
+
<div className="flex items-center gap-2 text-xs mb-1.5">
|
|
26
|
+
{m.from_session && <AliasAvatar alias={m.from_session} size={16} />}
|
|
27
|
+
<span className="text-gray-200 font-medium truncate">{m.from_session}</span>
|
|
28
|
+
<span className="ml-auto text-gray-600 shrink-0" title={m.created_at}>{timeAgo(m.created_at)}</span>
|
|
26
29
|
</div>
|
|
27
30
|
<div className="text-gray-300 leading-relaxed">{m.content}</div>
|
|
28
31
|
</div>
|
|
@@ -51,11 +51,12 @@ export function Sidebar() {
|
|
|
51
51
|
href={item.href}
|
|
52
52
|
prefetch={false}
|
|
53
53
|
onClick={() => setMobileOpen(false)}
|
|
54
|
+
title={collapsed ? item.label : undefined}
|
|
54
55
|
className={`relative flex items-center gap-3 px-3 py-3 rounded-lg text-sm transition-colors active:bg-[#1a1a3a] ${
|
|
55
56
|
isActive(item.href)
|
|
56
57
|
? 'bg-cyan-500/10 text-cyan-300 border border-cyan-500/20 anet-nav-active'
|
|
57
58
|
: 'text-gray-400 hover:text-gray-200 hover:bg-[#1a1a2a]'
|
|
58
|
-
} ${collapsed ? 'justify-center' : ''}`}
|
|
59
|
+
} ${collapsed ? 'justify-center px-0' : ''}`}
|
|
59
60
|
>
|
|
60
61
|
<svg className="w-5 h-5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
|
|
61
62
|
<path strokeLinecap="round" strokeLinejoin="round" d={item.icon} />
|
|
@@ -81,10 +82,11 @@ export function Sidebar() {
|
|
|
81
82
|
</svg>
|
|
82
83
|
</button>
|
|
83
84
|
|
|
84
|
-
{/* Mobile overlay
|
|
85
|
+
{/* Mobile overlay — round 47: fades in via anet-fade-in (150ms ease-out)
|
|
86
|
+
matching the TaskDrawer / TaskChatPanel backdrop. */}
|
|
85
87
|
{mobileOpen && (
|
|
86
88
|
<div
|
|
87
|
-
className="fixed inset-0 bg-black/50 z-30 lg:hidden"
|
|
89
|
+
className="fixed inset-0 bg-black/50 z-30 lg:hidden anet-fade-in"
|
|
88
90
|
onClick={() => setMobileOpen(false)}
|
|
89
91
|
/>
|
|
90
92
|
)}
|
|
@@ -93,13 +95,15 @@ export function Sidebar() {
|
|
|
93
95
|
but in light/mint we want a distinct surface, so we layer
|
|
94
96
|
`lg:bg-white` / `lg:dark:bg-[#0d0d1a]` via the theme attribute.
|
|
95
97
|
The CSS shim in globals.css upgrades sidebar bg to bg-secondary
|
|
96
|
-
in light themes so the sidebar reads as its own card.
|
|
98
|
+
in light themes so the sidebar reads as its own card.
|
|
99
|
+
Round 47: explicit ease-out curve + slight shadow so the drawer
|
|
100
|
+
edge "leaves a trail" as it slides in. */}
|
|
97
101
|
<aside data-anet-sidebar="true" className={`
|
|
98
102
|
fixed top-0 left-0 h-full z-40 bg-[#0d0d1a] border-r border-[#2a2a4a]
|
|
99
|
-
transition-
|
|
103
|
+
transition-transform duration-200 ease-out
|
|
100
104
|
${collapsed ? 'w-16' : 'w-52'}
|
|
101
|
-
${mobileOpen ? 'translate-x-0' : '-translate-x-full'}
|
|
102
|
-
lg:translate-x-0 lg:static lg:shrink-0
|
|
105
|
+
${mobileOpen ? 'translate-x-0 shadow-2xl shadow-black/40 lg:shadow-none' : '-translate-x-full'}
|
|
106
|
+
lg:translate-x-0 lg:static lg:shrink-0 lg:shadow-none
|
|
103
107
|
`}>
|
|
104
108
|
{/* Brand header — round 4: 3-node mesh mark matches /login,
|
|
105
109
|
with an inline live "online" pulse so every page surfaces
|
|
@@ -134,45 +138,49 @@ export function Sidebar() {
|
|
|
134
138
|
{nav}
|
|
135
139
|
</div>
|
|
136
140
|
|
|
137
|
-
{/* Sign out + collapse
|
|
141
|
+
{/* Sign out + collapse — round 27: collapsed-state gets icon-only
|
|
142
|
+
variants so users still have Sign out / Quick search access at
|
|
143
|
+
56px width, plus title= tooltips. */}
|
|
138
144
|
<div className="absolute bottom-0 left-0 right-0 border-t border-[#2a2a4a] bg-[#0d0d1a]">
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
145
|
+
<button
|
|
146
|
+
onClick={() => {
|
|
147
|
+
window.dispatchEvent(new KeyboardEvent('keydown', { key: 'k', metaKey: true, ctrlKey: true }));
|
|
148
|
+
}}
|
|
149
|
+
title={collapsed ? 'Quick search (⌘K)' : undefined}
|
|
150
|
+
className={`w-full flex items-center text-[11px] text-gray-600 hover:text-gray-400 hover:bg-[#1a1a2a] transition-colors ${
|
|
151
|
+
collapsed ? 'justify-center px-0 py-2.5' : 'justify-between gap-2 px-5 py-2'
|
|
152
|
+
}`}
|
|
153
|
+
aria-label="Open command palette"
|
|
154
|
+
>
|
|
155
|
+
<span className={`flex items-center ${collapsed ? '' : 'gap-2'}`}>
|
|
156
|
+
<svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
|
|
157
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
|
150
158
|
</svg>
|
|
151
|
-
|
|
152
|
-
</
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
<div className={`flex items-center gap-2 px-3 py-2 ${collapsed ? 'justify-center' : 'justify-between'}`}>
|
|
159
|
+
{!collapsed && 'Quick search'}
|
|
160
|
+
</span>
|
|
161
|
+
{!collapsed && <kbd className="text-[10px] border border-current rounded px-1 py-0.5 opacity-60 font-mono">⌘K</kbd>}
|
|
162
|
+
</button>
|
|
163
|
+
<button
|
|
164
|
+
onClick={async () => {
|
|
165
|
+
await fetch('/api/auth/logout', { method: 'POST' }).catch(() => {});
|
|
166
|
+
sessionStorage.removeItem('anet_v3_auth');
|
|
167
|
+
window.location.assign('/login');
|
|
168
|
+
}}
|
|
169
|
+
title={collapsed ? 'Sign out' : undefined}
|
|
170
|
+
className={`w-full flex items-center text-xs text-gray-500 hover:text-red-400 hover:bg-red-500/5 transition-colors ${
|
|
171
|
+
collapsed ? 'justify-center px-0 py-2.5' : 'gap-3 px-5 py-3'
|
|
172
|
+
}`}
|
|
173
|
+
>
|
|
174
|
+
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
|
|
175
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15m3 0l3-3m0 0l-3-3m3 3H9" />
|
|
176
|
+
</svg>
|
|
177
|
+
{!collapsed && 'Sign out'}
|
|
178
|
+
</button>
|
|
179
|
+
<div className={`flex items-center gap-2 ${collapsed ? 'flex-col px-0 py-2' : 'px-3 py-2 justify-between'}`}>
|
|
173
180
|
<ThemeSwitcher compact={collapsed} />
|
|
174
181
|
<button
|
|
175
182
|
onClick={() => setCollapsed(!collapsed)}
|
|
183
|
+
title={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}
|
|
176
184
|
className="hidden lg:flex p-1.5 rounded text-gray-600 hover:text-gray-400 transition-colors"
|
|
177
185
|
aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}
|
|
178
186
|
>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { useState, useEffect, useRef, useCallback } from 'react';
|
|
4
4
|
import { timeAgo } from './utils';
|
|
5
|
+
import { AliasAvatar } from './AliasAvatar';
|
|
5
6
|
|
|
6
7
|
interface ChatTask {
|
|
7
8
|
task_id: string;
|
|
@@ -386,7 +387,10 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
|
|
|
386
387
|
{m.result && (
|
|
387
388
|
<div className="flex justify-start">
|
|
388
389
|
<div className="max-w-[85%] bg-green-500/8 border border-green-500/15 rounded-2xl rounded-bl-md px-4 py-2.5 shadow-sm">
|
|
389
|
-
<div className="
|
|
390
|
+
<div className="flex items-center gap-1.5 mb-1.5">
|
|
391
|
+
{m.to_name && <AliasAvatar alias={m.to_name} size={14} />}
|
|
392
|
+
<span className="text-[10px] text-gray-200 font-medium">{m.to_name}</span>
|
|
393
|
+
</div>
|
|
390
394
|
<div className="text-[13px] text-gray-200">
|
|
391
395
|
<MarkdownContent text={m.result} />
|
|
392
396
|
</div>
|
|
@@ -422,7 +426,7 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
|
|
|
422
426
|
{filteredMentions.map(node => (
|
|
423
427
|
<button key={node} onClick={() => insertMention(node)}
|
|
424
428
|
className="w-full flex items-center gap-2 px-3 py-2 text-xs text-left hover:bg-cyan-500/10 transition-colors">
|
|
425
|
-
<
|
|
429
|
+
<AliasAvatar alias={node} size={16} />
|
|
426
430
|
<span className="text-gray-300">{node}</span>
|
|
427
431
|
</button>
|
|
428
432
|
))}
|
|
@@ -471,14 +475,12 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
|
|
|
471
475
|
|
|
472
476
|
return (
|
|
473
477
|
<>
|
|
474
|
-
<div className="fixed inset-0 bg-black/30 z-40 lg:hidden" onClick={onClose} />
|
|
478
|
+
<div className="fixed inset-0 bg-black/30 z-40 lg:hidden anet-fade-in" onClick={onClose} />
|
|
475
479
|
<div className="fixed top-0 right-0 h-full w-full lg:w-[500px] bg-[#0a0a1a] border-l border-[#2a2a4a] z-50 flex flex-col shadow-2xl shadow-black/60 animate-slide-in">
|
|
476
480
|
{/* Header */}
|
|
477
481
|
<div className="flex items-center justify-between px-4 py-3 border-b border-[#2a2a4a] bg-[#0d0d1a]">
|
|
478
482
|
<div className="flex items-center gap-3">
|
|
479
|
-
<
|
|
480
|
-
{alias.slice(0, 2)}
|
|
481
|
-
</div>
|
|
483
|
+
<AliasAvatar alias={alias} size={32} />
|
|
482
484
|
<div>
|
|
483
485
|
<div className="text-sm font-semibold text-white">{alias}</div>
|
|
484
486
|
<div className="text-[10px] text-gray-500">{pollingIds.size > 0 ? 'Processing...' : 'Ready'}</div>
|
|
@@ -492,10 +494,6 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
|
|
|
492
494
|
</div>
|
|
493
495
|
{chatContent}
|
|
494
496
|
</div>
|
|
495
|
-
<style jsx global>{`
|
|
496
|
-
@keyframes slide-in { from { transform: translateX(100%); } to { transform: translateX(0); } }
|
|
497
|
-
.animate-slide-in { animation: slide-in 0.2s ease-out; }
|
|
498
|
-
`}</style>
|
|
499
497
|
</>
|
|
500
498
|
);
|
|
501
499
|
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { useEffect, useState } from 'react';
|
|
4
4
|
import { timeAgo } from './utils';
|
|
5
5
|
import Link from 'next/link';
|
|
6
|
+
import { AliasAvatar } from './AliasAvatar';
|
|
6
7
|
|
|
7
8
|
interface TaskDetail {
|
|
8
9
|
task_id: string;
|
|
@@ -58,12 +59,20 @@ export function TaskDrawer({ taskId, onClose }: TaskDrawerProps) {
|
|
|
58
59
|
})();
|
|
59
60
|
}, [taskId]);
|
|
60
61
|
|
|
62
|
+
/** Timeline steps — same 4 hops every task goes through. `time` is set
|
|
63
|
+
* when the hop has happened; missing time means pending. Round 36 adds
|
|
64
|
+
* `key` for the "current step" highlight + the `done` flag for layout. */
|
|
61
65
|
const timeline = task ? [
|
|
62
|
-
{ label: 'Created',
|
|
63
|
-
{ label: 'Delivered', time: task.delivered_at,
|
|
64
|
-
{ label: 'Started',
|
|
65
|
-
{ label: 'Completed', time: task.completed_at,
|
|
66
|
-
] : [];
|
|
66
|
+
{ key: 'created', label: 'Created', time: task.created_at, color: 'bg-gray-400' },
|
|
67
|
+
{ key: 'delivered', label: 'Delivered', time: task.delivered_at, color: 'bg-blue-400' },
|
|
68
|
+
{ key: 'started', label: 'Started', time: task.started_at, color: 'bg-green-400' },
|
|
69
|
+
{ key: 'completed', label: 'Completed', time: task.completed_at, color: 'bg-purple-400'},
|
|
70
|
+
].map(s => ({ ...s, done: !!s.time })) : [];
|
|
71
|
+
|
|
72
|
+
/** Index of the highest-completed step. The step *after* this index is
|
|
73
|
+
* the "current" one (in-progress). When all are done, currentIdx = -1. */
|
|
74
|
+
const currentStepIdx = timeline.findIndex(s => !s.done);
|
|
75
|
+
const isActive = task && task.status !== 'completed' && task.status !== 'failed' && task.status !== 'expired' && task.status !== 'cancelled';
|
|
67
76
|
|
|
68
77
|
const duration = task?.started_at && task?.completed_at
|
|
69
78
|
? Math.round((new Date(task.completed_at).getTime() - new Date(task.started_at).getTime()) / 1000)
|
|
@@ -71,7 +80,7 @@ export function TaskDrawer({ taskId, onClose }: TaskDrawerProps) {
|
|
|
71
80
|
|
|
72
81
|
return (
|
|
73
82
|
<>
|
|
74
|
-
<div className="fixed inset-0 bg-black/30 z-40" onClick={onClose} />
|
|
83
|
+
<div className="fixed inset-0 bg-black/30 z-40 anet-fade-in" onClick={onClose} />
|
|
75
84
|
<div className="fixed top-0 right-0 h-full w-full lg:w-[500px] bg-[#0a0a1a] border-l border-[#2a2a4a] z-50 flex flex-col shadow-2xl shadow-black/60 overflow-y-auto animate-slide-in">
|
|
76
85
|
{/* Header */}
|
|
77
86
|
<div className="flex items-center justify-between px-5 py-4 border-b border-[#2a2a4a] bg-[#0d0d1a] sticky top-0">
|
|
@@ -105,29 +114,68 @@ export function TaskDrawer({ taskId, onClose }: TaskDrawerProps) {
|
|
|
105
114
|
)}
|
|
106
115
|
</div>
|
|
107
116
|
|
|
108
|
-
{/* From → To
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
<
|
|
117
|
+
{/* From → To — round 41: use AliasAvatar so from/to colours
|
|
118
|
+
match the rest of the app instead of the legacy blue/cyan
|
|
119
|
+
hardcode. */}
|
|
120
|
+
<div className="flex items-center gap-2 text-sm flex-wrap">
|
|
121
|
+
{task.from_name && <AliasAvatar alias={task.from_name} size={18} />}
|
|
122
|
+
<span className="text-gray-200 font-medium">{task.from_name || '--'}</span>
|
|
123
|
+
<span className="text-gray-600">→</span>
|
|
124
|
+
{task.to_name && <AliasAvatar alias={task.to_name} size={18} />}
|
|
125
|
+
<span className="text-gray-200 font-medium">{task.to_name || '--'}</span>
|
|
113
126
|
</div>
|
|
114
127
|
|
|
115
|
-
{/* Timeline
|
|
128
|
+
{/* Timeline — round 36 polish: relative timestamps, current-step
|
|
129
|
+
pulse if task is still in flight, full ISO in title=. */}
|
|
116
130
|
<div className="bg-[#111128] border border-[#2a2a4a] rounded-xl p-4">
|
|
117
|
-
<div className="
|
|
131
|
+
<div className="flex items-center justify-between mb-3">
|
|
132
|
+
<div className="text-xs text-gray-500 uppercase tracking-wide">Timeline</div>
|
|
133
|
+
{duration !== null && (
|
|
134
|
+
<div className="text-[10px] text-gray-600">
|
|
135
|
+
{duration < 60 ? `${duration}s` : `${Math.floor(duration/60)}m ${duration%60}s`} runtime
|
|
136
|
+
</div>
|
|
137
|
+
)}
|
|
138
|
+
</div>
|
|
118
139
|
<div className="space-y-3">
|
|
119
|
-
{timeline.map((step, i) =>
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
140
|
+
{timeline.map((step, i) => {
|
|
141
|
+
const isCurrent = isActive && i === currentStepIdx;
|
|
142
|
+
const isNextDone = !!timeline[i+1]?.done;
|
|
143
|
+
return (
|
|
144
|
+
<div key={step.key} className="flex items-start gap-3">
|
|
145
|
+
<div className="flex flex-col items-center pt-0.5">
|
|
146
|
+
<span
|
|
147
|
+
className={`relative w-3 h-3 rounded-full shrink-0 ${
|
|
148
|
+
step.done ? step.color : 'bg-gray-700'
|
|
149
|
+
}`}
|
|
150
|
+
>
|
|
151
|
+
{isCurrent && (
|
|
152
|
+
<span
|
|
153
|
+
aria-hidden
|
|
154
|
+
className="absolute -inset-1 rounded-full border border-current opacity-60 anet-current-step-pulse"
|
|
155
|
+
style={{ borderColor: 'currentColor' }}
|
|
156
|
+
/>
|
|
157
|
+
)}
|
|
158
|
+
</span>
|
|
159
|
+
{i < timeline.length - 1 && (
|
|
160
|
+
<div className={`w-0.5 h-5 mt-1 ${
|
|
161
|
+
step.done && isNextDone ? 'bg-gray-500' : step.done ? 'bg-gradient-to-b from-gray-500 to-gray-800' : 'bg-gray-800'
|
|
162
|
+
}`} />
|
|
163
|
+
)}
|
|
164
|
+
</div>
|
|
165
|
+
<div className="flex-1 min-w-0">
|
|
166
|
+
<div className={`text-xs font-medium flex items-center gap-2 ${
|
|
167
|
+
step.done ? 'text-gray-200' : isCurrent ? 'text-cyan-300' : 'text-gray-600'
|
|
168
|
+
}`}>
|
|
169
|
+
<span>{step.label}</span>
|
|
170
|
+
{isCurrent && <span className="text-[9px] uppercase tracking-wide text-cyan-400">in progress</span>}
|
|
171
|
+
</div>
|
|
172
|
+
<div className="text-[10px] text-gray-500" title={step.time || undefined}>
|
|
173
|
+
{step.time ? timeAgo(step.time) : isCurrent ? '—' : 'Pending'}
|
|
174
|
+
</div>
|
|
175
|
+
</div>
|
|
124
176
|
</div>
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
<div className="text-[10px] text-gray-500">{step.time || 'Pending'}</div>
|
|
128
|
-
</div>
|
|
129
|
-
</div>
|
|
130
|
-
))}
|
|
177
|
+
);
|
|
178
|
+
})}
|
|
131
179
|
</div>
|
|
132
180
|
</div>
|
|
133
181
|
|
|
@@ -172,10 +220,6 @@ export function TaskDrawer({ taskId, onClose }: TaskDrawerProps) {
|
|
|
172
220
|
</div>
|
|
173
221
|
)}
|
|
174
222
|
</div>
|
|
175
|
-
<style jsx global>{`
|
|
176
|
-
@keyframes slide-in { from { transform: translateX(100%); } to { transform: translateX(0); } }
|
|
177
|
-
.animate-slide-in { animation: slide-in 0.2s ease-out; }
|
|
178
|
-
`}</style>
|
|
179
223
|
</>
|
|
180
224
|
);
|
|
181
225
|
}
|