@sleep2agi/agent-network-dashboard 0.4.5-preview.7 → 0.4.5-preview.71

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +3 -3
  3. package/.next/diagnostics/route-bundle-stats.json +49 -49
  4. package/.next/fallback-build-manifest.json +3 -3
  5. package/.next/prerender-manifest.json +3 -3
  6. package/.next/server/app/_global-error.html +1 -1
  7. package/.next/server/app/_global-error.rsc +1 -1
  8. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  14. package/.next/server/app/_not-found.html +4 -4
  15. package/.next/server/app/_not-found.rsc +12 -12
  16. package/.next/server/app/_not-found.segments/_full.segment.rsc +12 -12
  17. package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  18. package/.next/server/app/_not-found.segments/_index.segment.rsc +7 -7
  19. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  20. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  21. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  22. package/.next/server/app/admin/page.js.nft.json +1 -1
  23. package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
  24. package/.next/server/app/admin.html +4 -4
  25. package/.next/server/app/admin.rsc +14 -14
  26. package/.next/server/app/admin.segments/_full.segment.rsc +14 -14
  27. package/.next/server/app/admin.segments/_head.segment.rsc +4 -4
  28. package/.next/server/app/admin.segments/_index.segment.rsc +7 -7
  29. package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
  30. package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +4 -4
  31. package/.next/server/app/admin.segments/admin.segment.rsc +3 -3
  32. package/.next/server/app/index.html +4 -4
  33. package/.next/server/app/index.rsc +14 -14
  34. package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
  35. package/.next/server/app/index.segments/_full.segment.rsc +14 -14
  36. package/.next/server/app/index.segments/_head.segment.rsc +4 -4
  37. package/.next/server/app/index.segments/_index.segment.rsc +7 -7
  38. package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  39. package/.next/server/app/login/page.js.nft.json +1 -1
  40. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  41. package/.next/server/app/login.html +2 -2
  42. package/.next/server/app/login.rsc +14 -14
  43. package/.next/server/app/login.segments/_full.segment.rsc +14 -14
  44. package/.next/server/app/login.segments/_head.segment.rsc +4 -4
  45. package/.next/server/app/login.segments/_index.segment.rsc +7 -7
  46. package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  47. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
  48. package/.next/server/app/login.segments/login.segment.rsc +3 -3
  49. package/.next/server/app/logs/page.js.nft.json +1 -1
  50. package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
  51. package/.next/server/app/logs.html +4 -4
  52. package/.next/server/app/logs.rsc +14 -14
  53. package/.next/server/app/logs.segments/_full.segment.rsc +14 -14
  54. package/.next/server/app/logs.segments/_head.segment.rsc +4 -4
  55. package/.next/server/app/logs.segments/_index.segment.rsc +7 -7
  56. package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
  57. package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +4 -4
  58. package/.next/server/app/logs.segments/logs.segment.rsc +3 -3
  59. package/.next/server/app/messages/page.js.nft.json +1 -1
  60. package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
  61. package/.next/server/app/messages.html +4 -4
  62. package/.next/server/app/messages.rsc +14 -14
  63. package/.next/server/app/messages.segments/_full.segment.rsc +14 -14
  64. package/.next/server/app/messages.segments/_head.segment.rsc +4 -4
  65. package/.next/server/app/messages.segments/_index.segment.rsc +7 -7
  66. package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
  67. package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +4 -4
  68. package/.next/server/app/messages.segments/messages.segment.rsc +3 -3
  69. package/.next/server/app/node/page.js.nft.json +1 -1
  70. package/.next/server/app/node/page_client-reference-manifest.js +1 -1
  71. package/.next/server/app/node.html +4 -4
  72. package/.next/server/app/node.rsc +14 -14
  73. package/.next/server/app/node.segments/_full.segment.rsc +14 -14
  74. package/.next/server/app/node.segments/_head.segment.rsc +4 -4
  75. package/.next/server/app/node.segments/_index.segment.rsc +7 -7
  76. package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
  77. package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +4 -4
  78. package/.next/server/app/node.segments/node.segment.rsc +3 -3
  79. package/.next/server/app/nodes/page.js.nft.json +1 -1
  80. package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
  81. package/.next/server/app/nodes.html +4 -4
  82. package/.next/server/app/nodes.rsc +14 -14
  83. package/.next/server/app/nodes.segments/_full.segment.rsc +14 -14
  84. package/.next/server/app/nodes.segments/_head.segment.rsc +4 -4
  85. package/.next/server/app/nodes.segments/_index.segment.rsc +7 -7
  86. package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
  87. package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +4 -4
  88. package/.next/server/app/nodes.segments/nodes.segment.rsc +3 -3
  89. package/.next/server/app/page.js.nft.json +1 -1
  90. package/.next/server/app/page_client-reference-manifest.js +1 -1
  91. package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
  92. package/.next/server/app/server-logs.html +4 -4
  93. package/.next/server/app/server-logs.rsc +14 -14
  94. package/.next/server/app/server-logs.segments/_full.segment.rsc +14 -14
  95. package/.next/server/app/server-logs.segments/_head.segment.rsc +4 -4
  96. package/.next/server/app/server-logs.segments/_index.segment.rsc +7 -7
  97. package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
  98. package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +4 -4
  99. package/.next/server/app/server-logs.segments/server-logs.segment.rsc +3 -3
  100. package/.next/server/app/settings/networks/page.js.nft.json +1 -1
  101. package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
  102. package/.next/server/app/settings/networks.html +4 -4
  103. package/.next/server/app/settings/networks.rsc +14 -14
  104. package/.next/server/app/settings/networks.segments/_full.segment.rsc +14 -14
  105. package/.next/server/app/settings/networks.segments/_head.segment.rsc +4 -4
  106. package/.next/server/app/settings/networks.segments/_index.segment.rsc +7 -7
  107. package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
  108. package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +4 -4
  109. package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +3 -3
  110. package/.next/server/app/settings/networks.segments/settings.segment.rsc +3 -3
  111. package/.next/server/app/settings/page.js.nft.json +1 -1
  112. package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  113. package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
  114. package/.next/server/app/settings/tokens.html +4 -4
  115. package/.next/server/app/settings/tokens.rsc +14 -14
  116. package/.next/server/app/settings/tokens.segments/_full.segment.rsc +14 -14
  117. package/.next/server/app/settings/tokens.segments/_head.segment.rsc +4 -4
  118. package/.next/server/app/settings/tokens.segments/_index.segment.rsc +7 -7
  119. package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
  120. package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +4 -4
  121. package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +3 -3
  122. package/.next/server/app/settings/tokens.segments/settings.segment.rsc +3 -3
  123. package/.next/server/app/settings.html +4 -4
  124. package/.next/server/app/settings.rsc +14 -14
  125. package/.next/server/app/settings.segments/_full.segment.rsc +14 -14
  126. package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
  127. package/.next/server/app/settings.segments/_index.segment.rsc +7 -7
  128. package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  129. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
  130. package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
  131. package/.next/server/app/tasks/[id]/page.js.nft.json +1 -1
  132. package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
  133. package/.next/server/app/tasks/page.js.nft.json +1 -1
  134. package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
  135. package/.next/server/app/tasks.html +4 -4
  136. package/.next/server/app/tasks.rsc +14 -14
  137. package/.next/server/app/tasks.segments/_full.segment.rsc +14 -14
  138. package/.next/server/app/tasks.segments/_head.segment.rsc +4 -4
  139. package/.next/server/app/tasks.segments/_index.segment.rsc +7 -7
  140. package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
  141. package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +4 -4
  142. package/.next/server/app/tasks.segments/tasks.segment.rsc +3 -3
  143. package/.next/server/chunks/ssr/[root-of-the-server]__02ee4km._.js +3 -0
  144. package/.next/server/chunks/ssr/[root-of-the-server]__02ee4km._.js.map +1 -0
  145. package/.next/server/chunks/ssr/[root-of-the-server]__0n4l2is._.js +3 -0
  146. package/.next/server/chunks/ssr/[root-of-the-server]__0n4l2is._.js.map +1 -0
  147. package/.next/server/chunks/ssr/[root-of-the-server]__0o8yj3c._.js +3 -0
  148. package/.next/server/chunks/ssr/[root-of-the-server]__0o8yj3c._.js.map +1 -0
  149. package/.next/server/chunks/ssr/[root-of-the-server]__0xm3h9x._.js +1 -1
  150. package/.next/server/chunks/ssr/[root-of-the-server]__0xm3h9x._.js.map +1 -1
  151. package/.next/server/chunks/ssr/_0nne7mz._.js +3 -0
  152. package/.next/server/chunks/ssr/_0nne7mz._.js.map +1 -0
  153. package/.next/server/chunks/ssr/app_0.zbtn5._.js +9 -0
  154. package/.next/server/chunks/ssr/app_0.zbtn5._.js.map +1 -0
  155. package/.next/server/chunks/ssr/app_01y-~mp._.js +3 -0
  156. package/.next/server/chunks/ssr/app_01y-~mp._.js.map +1 -0
  157. package/.next/server/chunks/ssr/app_04n78pr._.js +3 -0
  158. package/.next/server/chunks/ssr/app_04n78pr._.js.map +1 -0
  159. package/.next/server/chunks/ssr/app_0_agk0r._.js +3 -0
  160. package/.next/server/chunks/ssr/app_0_agk0r._.js.map +1 -0
  161. package/.next/server/chunks/ssr/app_0aum_g5._.js +3 -0
  162. package/.next/server/chunks/ssr/app_0aum_g5._.js.map +1 -0
  163. package/.next/server/chunks/ssr/app_0esuljp._.js +3 -0
  164. package/.next/server/chunks/ssr/app_0esuljp._.js.map +1 -0
  165. package/.next/server/chunks/ssr/app_0izi28j._.js +1 -1
  166. package/.next/server/chunks/ssr/app_0izi28j._.js.map +1 -1
  167. package/.next/server/chunks/ssr/app_0py1sns._.js +3 -0
  168. package/.next/server/chunks/ssr/app_0py1sns._.js.map +1 -0
  169. package/.next/server/chunks/ssr/app_0tncr1_._.js +3 -0
  170. package/.next/server/chunks/ssr/app_0tncr1_._.js.map +1 -0
  171. package/.next/server/chunks/ssr/app_components_08ys5y3._.js +5 -5
  172. package/.next/server/chunks/ssr/app_components_08ys5y3._.js.map +1 -1
  173. package/.next/server/chunks/ssr/app_server-logs_page_tsx_0_kpp1p._.js +1 -1
  174. package/.next/server/chunks/ssr/app_server-logs_page_tsx_0_kpp1p._.js.map +1 -1
  175. package/.next/server/chunks/ssr/app_tasks_page_tsx_0z-d6mp._.js +1 -1
  176. package/.next/server/chunks/ssr/app_tasks_page_tsx_0z-d6mp._.js.map +1 -1
  177. package/.next/server/middleware-build-manifest.js +3 -3
  178. package/.next/server/pages/404.html +4 -4
  179. package/.next/server/pages/500.html +1 -1
  180. package/.next/server/server-reference-manifest.js +1 -1
  181. package/.next/server/server-reference-manifest.json +1 -1
  182. package/.next/static/chunks/013_kw~b7_tqy.js +1 -0
  183. package/.next/static/chunks/04dbz0h45njew.js +1 -0
  184. package/.next/static/chunks/06uku.~mtk9zz.js +1 -0
  185. package/.next/static/chunks/07gtk5bhf8gn9.js +1 -0
  186. package/.next/static/chunks/08scyy1.s_5my.js +1 -0
  187. package/.next/static/chunks/09oxaqu0qn3c9.js +1 -0
  188. package/.next/static/chunks/0b8qzoyn-7e~f.js +1 -0
  189. package/.next/static/chunks/{07okhs5561y5y.js → 0c1bp~g7.8ru..js} +1 -1
  190. package/.next/static/chunks/0dj5~edkdwh1n.js +1 -0
  191. package/.next/static/chunks/0glm3gl882al6.js +1 -0
  192. package/.next/static/chunks/0gnf.w4c8z.l~.js +1 -0
  193. package/.next/static/chunks/0iwn.7hiigyrz.js +7 -0
  194. package/.next/static/chunks/0l8112gmzl31s.js +1 -0
  195. package/.next/static/chunks/0rk5zmyp19fv8.js +7 -0
  196. package/.next/static/chunks/0uh.dd0_.y_dh.js +1 -0
  197. package/.next/static/chunks/0vn.u7tcybvik.js +1 -0
  198. package/.next/static/chunks/13u~uqoww_0ib.css +2 -0
  199. package/.next/trace +2 -2
  200. package/.next/trace-build +1 -1
  201. package/app/admin/page.tsx +90 -26
  202. package/app/components/AgentCard.tsx +19 -5
  203. package/app/components/BroadcastBar.tsx +22 -4
  204. package/app/components/DispatchPanel.tsx +9 -5
  205. package/app/components/EmptyState.tsx +77 -4
  206. package/app/components/HealthBanner.tsx +11 -2
  207. package/app/components/HelpOverlay.tsx +50 -10
  208. package/app/components/InboxPanel.tsx +7 -4
  209. package/app/components/Sidebar.tsx +49 -41
  210. package/app/components/StatsBar.tsx +59 -36
  211. package/app/components/TaskChatPanel.tsx +8 -10
  212. package/app/components/TaskDrawer.tsx +72 -28
  213. package/app/components/TopoGraph.tsx +118 -24
  214. package/app/components/utils.ts +13 -0
  215. package/app/globals.css +90 -0
  216. package/app/lib/status.ts +63 -0
  217. package/app/lib/version.ts +7 -0
  218. package/app/login/page.tsx +40 -7
  219. package/app/logs/page.tsx +70 -21
  220. package/app/messages/page.tsx +24 -7
  221. package/app/node/page.tsx +48 -25
  222. package/app/nodes/page.tsx +37 -9
  223. package/app/page.tsx +107 -36
  224. package/app/server-logs/page.tsx +97 -25
  225. package/app/settings/networks/page.tsx +37 -13
  226. package/app/settings/page.tsx +39 -11
  227. package/app/tasks/[id]/page.tsx +2 -13
  228. package/app/tasks/page.tsx +66 -73
  229. package/package.json +1 -1
  230. package/scripts/fold-only.mjs +44 -0
  231. package/scripts/loop-review.mjs +226 -0
  232. package/.next/server/chunks/ssr/[root-of-the-server]__06pu~4t._.js +0 -3
  233. package/.next/server/chunks/ssr/[root-of-the-server]__06pu~4t._.js.map +0 -1
  234. package/.next/server/chunks/ssr/[root-of-the-server]__0_jnflc._.js +0 -3
  235. package/.next/server/chunks/ssr/[root-of-the-server]__0_jnflc._.js.map +0 -1
  236. package/.next/server/chunks/ssr/[root-of-the-server]__0nrckjd._.js +0 -3
  237. package/.next/server/chunks/ssr/[root-of-the-server]__0nrckjd._.js.map +0 -1
  238. package/.next/server/chunks/ssr/_0uw5cjt._.js +0 -3
  239. package/.next/server/chunks/ssr/_0uw5cjt._.js.map +0 -1
  240. package/.next/server/chunks/ssr/app_0.0wpa~._.js +0 -3
  241. package/.next/server/chunks/ssr/app_0.0wpa~._.js.map +0 -1
  242. package/.next/server/chunks/ssr/app_0ap_oiq._.js +0 -3
  243. package/.next/server/chunks/ssr/app_0ap_oiq._.js.map +0 -1
  244. package/.next/server/chunks/ssr/app_0dk5wao._.js +0 -3
  245. package/.next/server/chunks/ssr/app_0dk5wao._.js.map +0 -1
  246. package/.next/server/chunks/ssr/app_0et5yua._.js +0 -3
  247. package/.next/server/chunks/ssr/app_0et5yua._.js.map +0 -1
  248. package/.next/server/chunks/ssr/app_0k8xbx~._.js +0 -9
  249. package/.next/server/chunks/ssr/app_0k8xbx~._.js.map +0 -1
  250. package/.next/server/chunks/ssr/app_11vl967._.js +0 -3
  251. package/.next/server/chunks/ssr/app_11vl967._.js.map +0 -1
  252. package/.next/server/chunks/ssr/app_login_page_tsx_0z71ad3._.js +0 -3
  253. package/.next/server/chunks/ssr/app_login_page_tsx_0z71ad3._.js.map +0 -1
  254. package/.next/server/chunks/ssr/app_page_tsx_0es_sk2._.js +0 -3
  255. package/.next/server/chunks/ssr/app_page_tsx_0es_sk2._.js.map +0 -1
  256. package/.next/static/chunks/02flrewxlf_m_.js +0 -1
  257. package/.next/static/chunks/051gslfjka1kj.js +0 -1
  258. package/.next/static/chunks/06t_vzei8s9_h.js +0 -1
  259. package/.next/static/chunks/07oobuohrpigy.js +0 -1
  260. package/.next/static/chunks/09al3qm76q7nd.js +0 -1
  261. package/.next/static/chunks/0e7c40p~wq665.js +0 -1
  262. package/.next/static/chunks/0g7m7zk.v7g6h.js +0 -1
  263. package/.next/static/chunks/0ogeals5ufhho.js +0 -1
  264. package/.next/static/chunks/0v~9m62eciynd.js +0 -1
  265. package/.next/static/chunks/0xh3wr5rwvifr.css +0 -2
  266. package/.next/static/chunks/0z.pzy8zpa~js.js +0 -7
  267. package/.next/static/chunks/1031v6nw33ud3.js +0 -1
  268. package/.next/static/chunks/10ir.g.n~hre0.js +0 -7
  269. package/.next/static/chunks/10njj7kn9ylkf.js +0 -1
  270. package/.next/static/chunks/11v5tec4s1168.js +0 -1
  271. package/.next/static/chunks/13.dst7liziwo.js +0 -1
  272. package/public/file.svg +0 -1
  273. package/public/globe.svg +0 -1
  274. package/public/next.svg +0 -1
  275. package/public/vercel.svg +0 -1
  276. package/public/window.svg +0 -1
  277. /package/.next/static/{kyIvxswGu-u-KGQRAaXfV → C7A8u316NGa1ZA9zcEOFm}/_buildManifest.js +0 -0
  278. /package/.next/static/{kyIvxswGu-u-KGQRAaXfV → C7A8u316NGa1ZA9zcEOFm}/_clientMiddlewareManifest.js +0 -0
  279. /package/.next/static/{kyIvxswGu-u-KGQRAaXfV → C7A8u316NGa1ZA9zcEOFm}/_ssgManifest.js +0 -0
@@ -7,6 +7,8 @@ import { useNetworkId } from '../lib/network-context';
7
7
  import { TaskDrawer } from '../components/TaskDrawer';
8
8
  import { EmptyState } from '../components/EmptyState';
9
9
  import { AliasAvatar } from '../components/AliasAvatar';
10
+ import { previewContent } from '../components/utils';
11
+ import { TASK_STATUSES, STATUS_CHIP_CLASS, STATUS_DOT_HEX, STATUS_BAR_CLASS } from '../lib/status';
10
12
 
11
13
  interface Task {
12
14
  task_id: string;
@@ -24,48 +26,8 @@ interface Task {
24
26
  expires_at: string;
25
27
  }
26
28
 
27
- const STATUS_OPTIONS = [
28
- '',
29
- 'created',
30
- 'delivered',
31
- 'acked',
32
- 'running',
33
- 'replied',
34
- 'closed',
35
- 'failed',
36
- 'cancelled',
37
- 'expired',
38
- ];
39
-
40
- const STATUS_COLORS: Record<string, string> = {
41
- created: 'bg-gray-500/10 text-gray-400 border-gray-500/20',
42
- delivered: 'bg-blue-500/10 text-blue-300 border-blue-500/20',
43
- acked: 'bg-cyan-500/10 text-cyan-300 border-cyan-500/20',
44
- running: 'bg-green-500/10 text-green-300 border-green-500/20',
45
- replied: 'bg-purple-500/10 text-purple-300 border-purple-500/20',
46
- closed: 'bg-gray-500/10 text-gray-500 border-gray-500/20',
47
- failed: 'bg-red-500/10 text-red-300 border-red-500/20',
48
- cancelled: 'bg-yellow-500/10 text-yellow-300 border-yellow-500/20',
49
- expired: 'bg-orange-500/10 text-orange-300 border-orange-500/20',
50
- };
51
-
52
- /** Small colored dot per status — visible on every tab (active + inactive)
53
- * so users can scan the row at a glance. Hex inlined to avoid Tailwind
54
- * purging dynamic `bg-${family}-400` class names. */
55
- const STATUS_DOTS: Record<string, string> = {
56
- created: '#9ca3af',
57
- delivered: '#60a5fa',
58
- acked: '#22d3ee',
59
- running: '#4ade80',
60
- replied: '#a78bfa',
61
- closed: '#6b7280',
62
- failed: '#f87171',
63
- cancelled: '#facc15',
64
- expired: '#fb923c',
65
- };
66
-
67
29
  function statusBadge(status: string) {
68
- const color = STATUS_COLORS[status] || 'bg-gray-500/10 text-gray-400 border-gray-500/20';
30
+ const color = STATUS_CHIP_CLASS[status] || 'bg-gray-500/10 text-gray-400 border-gray-500/20';
69
31
  return `text-xs px-2 py-0.5 rounded-md border ${color}`;
70
32
  }
71
33
 
@@ -145,11 +107,25 @@ function TasksContent() {
145
107
  {/* Header */}
146
108
  <div className="flex items-center gap-4 mb-6">
147
109
  <h1 className="text-2xl font-bold text-white lg:ml-0 ml-10">Tasks</h1>
148
- <span className="text-xs bg-blue-900/30 text-blue-400 px-2 py-0.5 rounded-full border border-blue-800/30">
149
- {count}
110
+ {/* Round 88: pagination-aware chip. When tasks.length < count
111
+ the API has more rows than the current limit=100 slice;
112
+ show `loaded / total` so users notice. Otherwise just the
113
+ single total — matches r87 /logs pattern. */}
114
+ <span
115
+ className="text-xs bg-blue-900/30 text-blue-400 px-2 py-0.5 rounded-full border border-blue-800/30 tabular-nums"
116
+ title={tasks.length < count ? `Showing ${tasks.length} of ${count} tasks` : undefined}
117
+ >
118
+ {tasks.length < count ? `${tasks.length} / ${count}` : count}
150
119
  </span>
151
120
  </div>
152
121
 
122
+ {/* Round 75: hide the status tab strip + From/To filter row when
123
+ there are no tasks at all. Each tab would show "0" and the
124
+ filter inputs would have nothing to act on — pure noise above
125
+ the empty-state CTA. When at least one task exists, the chrome
126
+ comes back even if the current filter happens to hide
127
+ everything (so users can clear filters). */}
128
+ {tasks.length > 0 && <>
153
129
  {/* Status Tabs — color-coded dots per status family so users can
154
130
  scan the row at a glance. Active tab gets full chip styling
155
131
  (bg + border + text color), inactive tabs only carry the dot
@@ -159,23 +135,39 @@ function TasksContent() {
159
135
  elements) hinting more content. */}
160
136
  <div className="anet-tabstrip-wrap mb-4">
161
137
  <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">
162
- {['', ...STATUS_OPTIONS.filter(Boolean)].map(s => (
163
- <button key={s} onClick={() => setFilterStatus(s)}
164
- className={`px-3 py-1.5 rounded-md text-xs transition-colors flex items-center gap-1.5 shrink-0 whitespace-nowrap ${
165
- filterStatus === s
166
- ? `${STATUS_COLORS[s] || 'bg-cyan-500/10 text-cyan-300 border-cyan-500/20'} border`
167
- : 'text-gray-500 hover:text-gray-300 hover:bg-[#1a1a2a]/40'
168
- }`}>
169
- {s && (
170
- <span
171
- aria-hidden
172
- className="inline-block w-1.5 h-1.5 rounded-full shrink-0"
173
- style={{ backgroundColor: STATUS_DOTS[s] || '#6b7280' }}
174
- />
175
- )}
176
- <span>{s || 'All'}</span>
177
- </button>
178
- ))}
138
+ {(() => {
139
+ // Round 56: compute per-status counts so the tab strip doubles as a
140
+ // status distribution dashboard. Matches Audit Log (r43) + Overview
141
+ // agent filter (r34) chip-with-count pattern.
142
+ const counts: Record<string, number> = {};
143
+ tasks.forEach(t => { counts[t.status] = (counts[t.status] || 0) + 1; });
144
+ return ['', ...TASK_STATUSES].map(s => {
145
+ const count = s === '' ? tasks.length : counts[s] || 0;
146
+ const isActive = filterStatus === s;
147
+ return (
148
+ <button
149
+ key={s}
150
+ onClick={() => setFilterStatus(s)}
151
+ disabled={count === 0 && s !== '' && !isActive}
152
+ 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 ${
153
+ isActive
154
+ ? `${STATUS_CHIP_CLASS[s] || 'bg-cyan-500/10 text-cyan-300 border-cyan-500/20'} border`
155
+ : 'text-gray-500 hover:text-gray-300 hover:bg-[#1a1a2a]/40'
156
+ }`}
157
+ >
158
+ {s && (
159
+ <span
160
+ aria-hidden
161
+ className="inline-block w-1.5 h-1.5 rounded-full shrink-0"
162
+ style={{ backgroundColor: STATUS_DOT_HEX[s] || '#6b7280' }}
163
+ />
164
+ )}
165
+ <span>{s || 'All'}</span>
166
+ <span className={`text-[10px] tabular-nums ${isActive ? 'opacity-80' : 'text-gray-600'}`}>{count}</span>
167
+ </button>
168
+ );
169
+ });
170
+ })()}
179
171
  </div>
180
172
  </div>
181
173
 
@@ -211,27 +203,28 @@ function TasksContent() {
211
203
  </button>
212
204
  )}
213
205
  </div>
206
+ </>}
214
207
 
215
208
  {/* Status distribution */}
216
209
  {tasks.length > 0 && !filterStatus && (() => {
217
210
  const stats: Record<string, number> = {};
218
211
  tasks.forEach(t => { stats[t.status] = (stats[t.status] || 0) + 1; });
219
212
  const total = tasks.length || 1;
220
- const bars = [
221
- { key: 'running', color: 'bg-green-500', text: 'text-green-400' },
222
- { key: 'delivered', color: 'bg-blue-500', text: 'text-blue-400' },
223
- { key: 'replied', color: 'bg-purple-500', text: 'text-purple-400' },
224
- { key: 'failed', color: 'bg-red-500', text: 'text-red-400' },
225
- { key: 'expired', color: 'bg-orange-500', text: 'text-orange-400' },
226
- ].filter(b => stats[b.key]);
213
+ // Round 67: derive from shared TASK_STATUSES + STATUS_BAR_CLASS in
214
+ // app/lib/status.ts. Adding a new lifecycle status updates badge,
215
+ // tab dots, and bar in one edit.
216
+ const bars = TASK_STATUSES
217
+ .map(key => ({ key, color: STATUS_BAR_CLASS[key] }))
218
+ .filter(b => stats[b.key]);
227
219
  if (!bars.length) return null;
220
+ // Round 63: removed the per-status legend row beneath the bar —
221
+ // it duplicated the counts already shown in the tab chip strip
222
+ // since r56. The proportional bar stays because it adds a visual
223
+ // "shape of workload" that the chip numbers don't convey.
228
224
  return (
229
225
  <div className="mb-6">
230
226
  <div className="flex h-2 rounded-full overflow-hidden bg-gray-800">
231
- {bars.map(b => <div key={b.key} className={b.color} style={{ width: `${(stats[b.key]/total)*100}%` }} />)}
232
- </div>
233
- <div className="flex flex-wrap gap-3 mt-1.5 text-[10px] text-gray-500">
234
- {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>)}
227
+ {bars.map(b => <div key={b.key} className={b.color} style={{ width: `${(stats[b.key]/total)*100}%` }} title={`${b.key}: ${stats[b.key]}`} />)}
235
228
  </div>
236
229
  </div>
237
230
  );
@@ -301,7 +294,7 @@ function TasksContent() {
301
294
  <span className="truncate text-sm text-gray-200">{t.to_name || '--'}</span>
302
295
  </div>
303
296
  <div className="col-span-4 text-xs text-gray-400 truncate" title={t.content}>
304
- {t.content || '--'}
297
+ {previewContent(t.content)}
305
298
  </div>
306
299
  <div className="col-span-1">
307
300
  <span className={`text-xs ${priorityBadge(t.priority)}`}>{t.priority || 'normal'}</span>
@@ -340,7 +333,7 @@ function TasksContent() {
340
333
  {t.to_name && <AliasAvatar alias={t.to_name} size={16} />}
341
334
  <span className="truncate max-w-[40%]">{t.to_name || '--'}</span>
342
335
  </div>
343
- <div className="text-xs text-gray-400 line-clamp-1">{t.content || '--'}</div>
336
+ <div className="text-xs text-gray-400 line-clamp-1" title={t.content}>{previewContent(t.content)}</div>
344
337
  <div className="text-xs text-gray-600">{timeAgo(t.created_at)}</div>
345
338
  </div>
346
339
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sleep2agi/agent-network-dashboard",
3
- "version": "0.4.5-preview.7",
3
+ "version": "0.4.5-preview.71",
4
4
  "description": "Agent Network Dashboard — Web UI for managing AI Agent networks",
5
5
  "scripts": {
6
6
  "dev": "next dev",
@@ -0,0 +1,44 @@
1
+ /* Captures the fold (viewport-only screenshot) for a given page so we
2
+ * can inspect what the user actually sees on first paint. */
3
+
4
+ import { chromium } from 'playwright';
5
+ import { mkdirSync } from 'node:fs';
6
+ import path from 'node:path';
7
+
8
+ const TOKEN = process.env.LOOP_REVIEW_TOKEN;
9
+ const OUT = path.resolve(process.cwd(), 'test-results/loop-review/folds');
10
+ mkdirSync(OUT, { recursive: true });
11
+
12
+ const targets = [
13
+ { name: 'tasks-cyber-desktop', path: '/tasks', theme: 'cyber', w: 1440, h: 900 },
14
+ { name: 'tasks-cyber-mobile', path: '/tasks', theme: 'cyber', w: 390, h: 844 },
15
+ { name: 'nodes-cyber-desktop', path: '/nodes', theme: 'cyber', w: 1440, h: 900 },
16
+ { name: 'nodes-cyber-mobile', path: '/nodes', theme: 'cyber', w: 390, h: 844 },
17
+ { name: 'overview-cyber-desktop', path: '/', theme: 'cyber', w: 1440, h: 900 },
18
+ { name: 'overview-light-desktop', path: '/', theme: 'light', w: 1440, h: 900 },
19
+ { name: 'server-logs-cyber-desktop', path: '/server-logs', theme: 'cyber', w: 1440, h: 900 },
20
+ { name: 'server-logs-cyber-mobile', path: '/server-logs', theme: 'cyber', w: 390, h: 844 },
21
+ { name: 'admin-cyber-desktop', path: '/admin', theme: 'cyber', w: 1440, h: 900 },
22
+ ];
23
+
24
+ const browser = await chromium.launch({ headless: true });
25
+ for (const t of targets) {
26
+ const ctx = await browser.newContext({ viewport: { width: t.w, height: t.h } });
27
+ await ctx.addCookies([{
28
+ name: 'anet_dashboard_session',
29
+ value: `v3:${TOKEN}`,
30
+ domain: '127.0.0.1', path: '/',
31
+ }]);
32
+ await ctx.addInitScript(theme => {
33
+ try { localStorage.setItem('anet-theme', theme); sessionStorage.setItem('anet_v3_auth', '1'); } catch {}
34
+ }, t.theme);
35
+ const page = await ctx.newPage();
36
+ await page.goto(`http://127.0.0.1:3000${t.path}`, { waitUntil: 'domcontentloaded' });
37
+ await page.waitForTimeout(2500);
38
+ await page.evaluate(theme => document.documentElement.setAttribute('data-theme', theme), t.theme);
39
+ await page.waitForTimeout(300);
40
+ await page.screenshot({ path: path.join(OUT, `${t.name}.png`), fullPage: false, animations: 'disabled' });
41
+ await ctx.close();
42
+ }
43
+ await browser.close();
44
+ console.log('captured', targets.length, 'fold-only screenshots to', OUT);
@@ -0,0 +1,226 @@
1
+ /* Loop self-review — captures Overview in cyber+light × desktop+mobile,
2
+ * runs a few observable checks, prints a per-axis score. Not a regression
3
+ * test — the cron's "review and score then propose next round" output.
4
+ *
5
+ * Round 71: replaced the toy checks (overflow, sidebar visible, blur count)
6
+ * with checks that actually catch the bugs we keep shipping:
7
+ * - CTA-above-fold: does the primary "Spin up" / "Get started" / etc
8
+ * button live within the first viewport? (deduct 3)
9
+ * - Zero-card density: how many "0" stat cards are crammed in above the
10
+ * CTA? (deduct 1 per zero-card beyond the first 2)
11
+ * - Whitespace gap: any element-to-element vertical gap >200px in the
12
+ * top half? (deduct 1)
13
+ * - Misleading-copy: "All systems go" text rendered when nodes.total=0
14
+ * (deduct 2) — round-70-class bug guard
15
+ * - Old: theme, horizontal overflow, sidebar, glow tell — still in
16
+ *
17
+ * Score is 10 max; deductions accumulate. The pre-r70 design that scored
18
+ * 10/10 here should now score ~4–5.
19
+ */
20
+
21
+ import { chromium } from 'playwright';
22
+ import { mkdirSync } from 'node:fs';
23
+ import path from 'node:path';
24
+
25
+ const BASE = process.env.LOOP_REVIEW_BASE || 'http://127.0.0.1:3000';
26
+ const TOKEN = process.env.LOOP_REVIEW_TOKEN; // utok_...
27
+ const OUT = path.resolve(process.cwd(), 'test-results/loop-review');
28
+ mkdirSync(OUT, { recursive: true });
29
+
30
+ if (!TOKEN) {
31
+ console.error('LOOP_REVIEW_TOKEN env var required (utok_...)');
32
+ process.exit(1);
33
+ }
34
+
35
+ const viewports = [
36
+ { tag: 'desktop', width: 1440, height: 900 },
37
+ { tag: 'mobile', width: 390, height: 844 },
38
+ ];
39
+ const themes = ['cyber', 'light'];
40
+ const pages = [
41
+ { name: 'overview', path: '/' },
42
+ { name: 'nodes', path: '/nodes' },
43
+ { name: 'tasks', path: '/tasks' },
44
+ { name: 'messages', path: '/messages' },
45
+ { name: 'admin', path: '/admin' },
46
+ { name: 'settings', path: '/settings' },
47
+ { name: 'networks', path: '/settings/networks' },
48
+ { name: 'logs', path: '/logs' },
49
+ ];
50
+
51
+ const matrix = [];
52
+ for (const t of themes) for (const v of viewports) for (const p of pages) {
53
+ matrix.push({ theme: t, viewport: { width: v.width, height: v.height }, tag: v.tag, pageName: p.name, pagePath: p.path });
54
+ }
55
+
56
+ const browser = await chromium.launch({ headless: true });
57
+
58
+ const report = [];
59
+
60
+ for (const m of matrix) {
61
+ const ctx = await browser.newContext({
62
+ viewport: m.viewport,
63
+ deviceScaleFactor: 1,
64
+ });
65
+ await ctx.addCookies([{
66
+ name: 'anet_dashboard_session',
67
+ value: `v3:${TOKEN}`,
68
+ domain: '127.0.0.1',
69
+ path: '/',
70
+ }]);
71
+ await ctx.addInitScript((theme) => {
72
+ try {
73
+ localStorage.setItem('anet-theme', theme);
74
+ sessionStorage.setItem('anet_v3_auth', '1');
75
+ } catch {}
76
+ }, m.theme);
77
+
78
+ const page = await ctx.newPage();
79
+ await page.goto(`${BASE}${m.pagePath}`, { waitUntil: 'domcontentloaded', timeout: 15000 });
80
+ await page.waitForTimeout(1200);
81
+
82
+ await page.evaluate((t) => document.documentElement.setAttribute('data-theme', t), m.theme);
83
+ await page.waitForTimeout(300);
84
+
85
+ const file = path.join(OUT, `${m.pageName}-${m.theme}-${m.tag}.png`);
86
+ // animations: 'disabled' so polling/spinner-induced render churn does
87
+ // not stall the screenshot when the dash is populated.
88
+ await page.screenshot({ path: file, fullPage: true, animations: 'disabled', timeout: 60000 });
89
+
90
+ const checks = await page.evaluate(() => {
91
+ const doc = document.documentElement;
92
+ const theme = doc.getAttribute('data-theme');
93
+ const body = document.body;
94
+ const bodyBg = getComputedStyle(body).backgroundColor;
95
+ const bodyFg = getComputedStyle(body).color;
96
+
97
+ const viewportH = window.innerHeight;
98
+ const viewportW = window.innerWidth;
99
+
100
+ // --- CTA-above-fold ---
101
+ // We treat any of these texts as the page's primary CTA:
102
+ // "Spin up your first agent" — empty Overview onboarding
103
+ // "Get started" — generic
104
+ // "Dispatch" (when not empty) — populated state primary action
105
+ const ctaTextRe = /Spin up your first agent|Get started/i;
106
+ const ctaCandidates = [...document.querySelectorAll('h1, h2, h3, p, div, button, a')]
107
+ .filter(el => ctaTextRe.test(el.textContent || ''));
108
+ let ctaTop = null;
109
+ if (ctaCandidates.length) {
110
+ // Pick the smallest (innermost) element matching to avoid catching a wrapping section
111
+ const sorted = ctaCandidates.sort((a, b) => (a.textContent?.length || 0) - (b.textContent?.length || 0));
112
+ const r = sorted[0].getBoundingClientRect();
113
+ ctaTop = r.top;
114
+ }
115
+
116
+ // --- Zero-card density ---
117
+ // Count visible elements whose trimmed text === "0". These are usually
118
+ // big stat-card values dominating prime real estate.
119
+ const zeroCards = [...document.querySelectorAll('div, span')]
120
+ .filter(el => {
121
+ const t = el.textContent?.trim();
122
+ if (t !== '0' && t !== '0/0') return false;
123
+ const r = el.getBoundingClientRect();
124
+ return r.top >= 0 && r.top < viewportH && r.width > 20 && r.height > 20;
125
+ });
126
+
127
+ // --- Whitespace gap ---
128
+ // Look for sibling-to-sibling top gaps >200px in the page content
129
+ // container. AppShell wraps page children in
130
+ // <main><HealthBanner/><div><div class="min-h-screen ...">{page}</div></div></main>,
131
+ // so we walk into that inner page wrapper to read real section gaps.
132
+ const main = document.querySelector('main');
133
+ const inner = main?.querySelector(':scope > div:last-of-type > div') || main || document.body;
134
+ const directKids = [...inner.children].filter(el => {
135
+ const r = el.getBoundingClientRect();
136
+ return r.height > 0 && r.width > 0;
137
+ });
138
+ let maxGap = 0;
139
+ for (let i = 0; i + 1 < directKids.length; i++) {
140
+ const a = directKids[i].getBoundingClientRect();
141
+ const b = directKids[i + 1].getBoundingClientRect();
142
+ if (a.bottom < 1600 && b.top - a.bottom > maxGap) {
143
+ maxGap = Math.round(b.top - a.bottom);
144
+ }
145
+ }
146
+
147
+ // --- Misleading copy guard ---
148
+ // "All systems go" must not appear anywhere when nodes.total === 0.
149
+ // We can't read state directly, but if the page also shows
150
+ // "Waiting for first agent" then we know fleet is empty.
151
+ const bodyText = document.body.innerText;
152
+ const fleetEmpty = /Waiting for first agent/i.test(bodyText);
153
+ const sayingAllSystemsGo = /All systems go/i.test(bodyText);
154
+ const misleadingCopy = fleetEmpty && sayingAllSystemsGo;
155
+
156
+ // --- Carryover ---
157
+ const docWidth = doc.scrollWidth;
158
+ const horizontalOverflow = docWidth > viewportW + 2;
159
+ let glowyCount = 0;
160
+ for (const el of document.querySelectorAll('body *')) {
161
+ const cs = getComputedStyle(el);
162
+ if (cs.filter && cs.filter.includes('blur(') && !cs.filter.includes('blur(0px)')) glowyCount++;
163
+ }
164
+ const sidebar = document.querySelector('aside, [data-sidebar], nav');
165
+ const sidebarRect = sidebar?.getBoundingClientRect();
166
+ const sidebarVisible = !!(sidebarRect && sidebarRect.width > 0 && sidebarRect.height > 0);
167
+
168
+ return {
169
+ theme, bodyBg, bodyFg,
170
+ viewportH, viewportW,
171
+ ctaTop, ctaPresent: ctaCandidates.length > 0,
172
+ zeroCardCount: zeroCards.length,
173
+ maxGap,
174
+ fleetEmpty, sayingAllSystemsGo, misleadingCopy,
175
+ docWidth, horizontalOverflow,
176
+ glowyCount, sidebarVisible,
177
+ };
178
+ });
179
+
180
+ let score = 10;
181
+ const notes = [];
182
+ if (checks.theme !== m.theme) { score -= 3; notes.push(`theme=${checks.theme}`); }
183
+ if (checks.horizontalOverflow) { score -= 2; notes.push(`horiz overflow ${checks.docWidth}/${checks.viewportW}`); }
184
+ if (m.tag === 'desktop' && !checks.sidebarVisible) { score -= 1; notes.push('sidebar missing on desktop'); }
185
+ if (checks.glowyCount > 8) { score -= 1; notes.push(`${checks.glowyCount} blur-filter elements (glow tell)`); }
186
+
187
+ // New checks — the ones that would have caught r70's bug
188
+ if (checks.ctaPresent && checks.ctaTop !== null) {
189
+ if (checks.ctaTop > checks.viewportH) {
190
+ score -= 3;
191
+ notes.push(`CTA below fold (top=${Math.round(checks.ctaTop)} > vh=${checks.viewportH})`);
192
+ } else if (checks.ctaTop > checks.viewportH * 0.7) {
193
+ score -= 1;
194
+ notes.push(`CTA low in fold (top=${Math.round(checks.ctaTop)})`);
195
+ }
196
+ }
197
+ if (checks.zeroCardCount > 4) {
198
+ const extra = Math.min(checks.zeroCardCount - 4, 3);
199
+ score -= extra;
200
+ notes.push(`${checks.zeroCardCount} zero-value cards above fold`);
201
+ }
202
+ if (checks.maxGap > 200) {
203
+ score -= 1;
204
+ notes.push(`whitespace gap ${checks.maxGap}px`);
205
+ }
206
+ if (checks.misleadingCopy) {
207
+ score -= 2;
208
+ notes.push(`'All systems go' shown while fleet empty`);
209
+ }
210
+
211
+ report.push({ ...m, file, checks, score: Math.max(score, 0), notes });
212
+
213
+ await page.close();
214
+ await ctx.close();
215
+ }
216
+
217
+ await browser.close();
218
+
219
+ console.log('\n=== Loop self-review (harness r73) ===\n');
220
+ for (const r of report) {
221
+ console.log(`${r.pageName.padEnd(8)} ${r.theme}/${r.tag.padEnd(7)} score=${r.score}/10`);
222
+ console.log(` cta_top=${r.checks.ctaTop !== null ? Math.round(r.checks.ctaTop) : '--'} zero_cards=${r.checks.zeroCardCount} max_gap=${r.checks.maxGap}px fleet_empty=${r.checks.fleetEmpty}`);
223
+ if (r.notes.length) console.log(` notes: ${r.notes.join(' · ')}`);
224
+ }
225
+ const avg = report.reduce((s, r) => s + r.score, 0) / report.length;
226
+ console.log(`\noverall avg = ${avg.toFixed(1)}/10 across ${report.length} captures`);
@@ -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},1720,a=>{"use strict";var b=a.i(87924);let c=[180,200,220,270,300,330,30,90];a.s(["AliasAvatar",0,function({alias:a,size:d=28,className:e=""}){let f=function(a){let b=0;for(let c=0;c<a.length;c++)b=31*b+a.charCodeAt(c)>>>0;let d=c[b%c.length];return{bg:`hsl(${d} 55% 22%)`,ring:`hsl(${d} 60% 45%)`,text:`hsl(${d} 80% 78%)`}}(a),g=Math.max(9,Math.round(.42*d));return(0,b.jsx)("span",{className:`anet-alias-avatar inline-flex items-center justify-center rounded-full border shrink-0 font-semibold ${e}`,style:{width:d,height:d,fontSize:g,backgroundColor:f.bg,borderColor:f.ring,color:f.text},title:a,"aria-hidden":!0,children:a?(a.trim().match(/[\p{L}\p{N}]/u)?.[0]||a.trim()[0]||"·").toUpperCase():"·"})}])},96794,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(38246),e=a.i(43515),f=a.i(44332),g=a.i(15261),h=a.i(53142),i=a.i(1720);let j={working:"bg-green-500/10 text-green-300 border-green-500/20",idle:"bg-blue-500/10 text-blue-300 border-blue-500/20",blocked:"bg-yellow-500/10 text-yellow-300 border-yellow-500/20",error:"bg-red-500/10 text-red-300 border-red-500/20",offline:"bg-gray-500/10 text-gray-500 border-gray-500/20"};a.s(["default",0,function(){let a,k,l,m,{sessions:n,isLoading:o}=(0,f.useSessions)(),{health:p}=(0,f.useHealth)(),q=p?.sse_sessions||{},r=a=>(a.network_id?q[`${a.network_id}:${a.alias}`]:void 0)??q[a.alias],[s,t]=(0,c.useState)(""),[u,v]=(0,c.useState)(""),[w,x]=(0,c.useState)("list"),[y,z]=(0,c.useState)({}),[A,B]=(0,c.useState)(null),[C,D]=(0,c.useState)({}),[E,F]=(0,c.useState)(null),G=n.map(a=>({...a,online:!!r(a)})).filter(a=>"online"===s?a.online:"offline"===s?!a.online:!s||s===a.status).filter(a=>!u||a.alias.toLowerCase().includes(u.toLowerCase())||(a.agent||"").toLowerCase().includes(u.toLowerCase())).sort((a,b)=>!!b.online-!!a.online||("working"===b.status)-("working"===a.status)),H=n.filter(a=>r(a)).length,I=a=>{B(b=>b===a?null:a),D(b=>({...b,[a]:{}}))},J=(a,b)=>{z(c=>({...c,[a]:b}))},K=async a=>{let b=y[a]?.trim()||"";if(b){D(b=>({...b,[a]:{sending:!0}}));try{let c=await fetch("/api/hub/send",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({alias:a,task:b})}),d=await c.json();if(!c.ok||d?.ok===!1)throw Error(d?.error||"Send failed");z(b=>({...b,[a]:""})),D(b=>({...b,[a]:{success:"Task sent"}})),B(null)}catch(b){D(c=>({...c,[a]:{error:b instanceof Error?b.message:"Send failed"}}))}}};return(0,b.jsxs)("div",{className:"min-h-screen bg-[#0a0a1a] text-gray-100 p-4 sm:p-6 font-mono",children:[(0,b.jsxs)("div",{className:"flex items-center gap-4 mb-6",children:[(0,b.jsx)("h1",{className:"text-2xl font-bold text-white lg:ml-0 ml-10",children:"Nodes"}),(0,b.jsxs)("span",{className:"text-xs bg-green-900/30 text-green-400 px-2 py-0.5 rounded-full border border-green-800/30",children:[H," online"]}),(0,b.jsxs)("span",{className:"text-xs bg-gray-900/30 text-gray-400 px-2 py-0.5 rounded-full border border-gray-800/30",children:[n.length," total"]})]}),n.length>0&&(a=G.filter(a=>a.online&&"working"===a.status).length,k=G.filter(a=>a.online&&"idle"===a.status).length,l=G.filter(a=>!a.online).length,m=G.length||1,(0,b.jsxs)("div",{className:"mb-6",children:[(0,b.jsxs)("div",{className:"flex h-2 rounded-full overflow-hidden bg-gray-800",children:[a>0&&(0,b.jsx)("div",{className:"bg-green-500",style:{width:`${a/m*100}%`}}),k>0&&(0,b.jsx)("div",{className:"bg-cyan-500",style:{width:`${k/m*100}%`}}),l>0&&(0,b.jsx)("div",{className:"bg-gray-600",style:{width:`${l/m*100}%`}})]}),(0,b.jsxs)("div",{className:"flex gap-4 mt-1.5 text-[10px] text-gray-500",children:[a>0&&(0,b.jsxs)("span",{children:[(0,b.jsx)("span",{className:"inline-block w-2 h-2 rounded-full bg-green-500 mr-1"}),a," working"]}),k>0&&(0,b.jsxs)("span",{children:[(0,b.jsx)("span",{className:"inline-block w-2 h-2 rounded-full bg-cyan-500 mr-1"}),k," idle"]}),l>0&&(0,b.jsxs)("span",{children:[(0,b.jsx)("span",{className:"inline-block w-2 h-2 rounded-full bg-gray-600 mr-1"}),l," offline"]})]})]})),(0,b.jsxs)("div",{className:"flex flex-wrap gap-3 mb-6",children:[(0,b.jsx)("input",{type:"text",value:u,onChange:a=>v(a.target.value),placeholder:"Search nodes...",className:"bg-[#111128] border border-[#2a2a4a] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-blue-500/50 focus:outline-none w-48"}),(0,b.jsxs)("select",{value:s,onChange:a=>t(a.target.value),className:"bg-[#111128] border border-[#2a2a4a] rounded-lg px-3 py-2 text-sm text-white focus:border-blue-500/50 focus:outline-none",children:[(0,b.jsx)("option",{value:"",children:"All"}),(0,b.jsx)("option",{value:"online",children:"Online"}),(0,b.jsx)("option",{value:"offline",children:"Offline"}),(0,b.jsx)("option",{value:"working",children:"Working"}),(0,b.jsx)("option",{value:"idle",children:"Idle"}),(0,b.jsx)("option",{value:"blocked",children:"Blocked"}),(0,b.jsx)("option",{value:"error",children:"Error"})]}),(0,b.jsx)("div",{className:"ml-auto flex rounded-lg border border-[#2a2a4a] bg-[#111128] p-1 text-sm",children:["list","grid"].map(a=>(0,b.jsx)("button",{type:"button",onClick:()=>x(a),className:`rounded-md px-3 py-1.5 transition-colors ${w===a?"bg-cyan-500/10 text-cyan-300":"text-gray-500 hover:text-gray-200"}`,children:"list"===a?"List":"Grid"},a))})]}),o?(0,b.jsx)("div",{className:"animate-pulse space-y-2",children:[1,2,3,4].map(a=>(0,b.jsx)("div",{className:"h-16 bg-gray-800/20 rounded-lg"},a))}):0===G.length?(0,b.jsx)(h.EmptyState,{variant:"nodes",title:"No nodes match your filters",sub:"Try clearing search or status filters, or wait for an agent to register."}):"grid"===w?(0,b.jsx)("div",{className:"grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4",children:G.map(a=>{let c=a.online?a.status:"offline",f=C[a.alias]||{},g="number"==typeof a.progress?a.progress:0;return(0,b.jsxs)("div",{className:`relative overflow-hidden rounded-xl border border-[#2a2a4a] bg-[#111128] p-4 transition-colors ${!a.online?"opacity-60":""}`,children:[!a.online&&(0,b.jsx)("div",{className:"pointer-events-none absolute inset-0 flex items-center justify-center",children:(0,b.jsx)("span",{className:"rotate-[-20deg] rounded-xl border border-white/10 bg-black/20 px-5 py-2 text-xl font-bold uppercase tracking-[0.35em] text-white/10",children:"Offline"})}),(0,b.jsxs)("div",{className:"flex items-start gap-3",children:[(0,b.jsx)(i.AliasAvatar,{alias:a.alias,size:36}),(0,b.jsxs)(d.default,{href:`/node?alias=${encodeURIComponent(a.alias)}`,className:"min-w-0 flex-1 hover:text-cyan-300",children:[(0,b.jsxs)("div",{className:"flex items-center gap-2",children:[(0,b.jsx)("span",{className:"truncate text-base font-semibold text-white",children:a.alias}),(0,b.jsx)("span",{className:`shrink-0 rounded-md border px-2 py-0.5 text-[10px] uppercase tracking-wide ${j[c]||j.offline}`,children:c})]}),(0,b.jsxs)("div",{className:"mt-0.5 truncate text-xs text-gray-500",children:[a.agent||"—",(0,b.jsx)("span",{className:"text-gray-700 mx-1.5",children:"·"}),a.server||"—"]})]}),(0,b.jsxs)("div",{className:"flex gap-1.5 shrink-0",children:[(0,b.jsx)("button",{type:"button",onClick:()=>F(a.alias),className:"rounded-lg border border-green-500/20 bg-green-500/10 px-3 py-1.5 text-xs text-green-300 transition-colors hover:bg-green-500/20",children:"Chat"}),(0,b.jsx)("button",{type:"button",onClick:()=>I(a.alias),className:"rounded-lg border border-cyan-500/20 bg-cyan-500/10 px-3 py-1.5 text-xs text-cyan-300 transition-colors hover:bg-cyan-500/20",children:"Task"})]})]}),(0,b.jsxs)("div",{className:"mt-3 rounded-lg border border-[#1a1a2a] bg-[#0a0a15] px-3 py-2 text-xs",children:[(0,b.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,b.jsx)("span",{className:"text-[10px] uppercase tracking-wide text-gray-600",children:"Current task"}),(0,b.jsx)("span",{className:"text-[10px] text-gray-600",children:(0,e.timeAgo)(a.last_seen_at||a.updated_at)})]}),(0,b.jsx)("div",{className:`mt-1 line-clamp-2 ${a.task?"text-gray-300":"text-gray-600 italic"}`,children:a.task||"No current task"})]}),g>0&&g<100&&(0,b.jsx)("div",{className:"mt-3 h-1.5 overflow-hidden rounded-full bg-gray-800",children:(0,b.jsx)("div",{className:"h-1.5 rounded-full bg-cyan-400 transition-all",style:{width:`${g}%`}})}),A===a.alias&&(0,b.jsxs)("div",{className:"mt-4 space-y-2 rounded-lg border border-[#2a2a4a] bg-[#0a0a15] p-3",children:[(0,b.jsx)("input",{type:"text",value:y[a.alias]||"",onChange:b=>J(a.alias,b.target.value),onKeyDown:b=>"Enter"===b.key&&K(a.alias),placeholder:`Send task to ${a.alias}...`,className:"w-full rounded-lg border border-[#2a2a4a] bg-[#050510] px-3 py-2 text-xs text-white placeholder-gray-600 focus:border-cyan-500 focus:outline-none"}),(0,b.jsxs)("div",{className:"flex justify-end gap-2",children:[(0,b.jsx)("button",{type:"button",onClick:()=>B(null),className:"rounded-lg border border-gray-700 px-3 py-1.5 text-xs text-gray-400 hover:text-gray-200",children:"Cancel"}),(0,b.jsx)("button",{type:"button",onClick:()=>K(a.alias),disabled:f.sending||!(y[a.alias]||"").trim(),className:"rounded-lg bg-cyan-600 px-3 py-1.5 text-xs text-white hover:bg-cyan-500 disabled:cursor-not-allowed disabled:bg-gray-700",children:f.sending?"Sending...":"Send"})]})]}),f.error&&(0,b.jsx)("div",{className:"mt-2 text-xs text-red-400",children:f.error}),f.success&&A!==a.alias&&(0,b.jsx)("div",{className:"mt-2 text-xs text-green-400",children:f.success})]},a.alias)})}):(0,b.jsxs)("div",{className:"space-y-2",children:[(0,b.jsxs)("div",{className:"hidden sm:grid sm:grid-cols-12 gap-2 px-4 py-2 text-xs text-gray-600 uppercase",children:[(0,b.jsx)("div",{className:"col-span-1",children:"Status"}),(0,b.jsx)("div",{className:"col-span-2",children:"Alias"}),(0,b.jsx)("div",{className:"col-span-2",children:"Agent"}),(0,b.jsx)("div",{className:"col-span-2",children:"Server"}),(0,b.jsx)("div",{className:"col-span-2",children:"Current Task"}),(0,b.jsx)("div",{className:"col-span-1",children:"Updated"}),(0,b.jsx)("div",{className:"col-span-2 text-right",children:"Actions"})]}),G.map(a=>{let c=a.online?a.status:"offline",f=C[a.alias]||{};return(0,b.jsxs)("div",{className:`rounded-lg border border-[#2a2a4a] bg-[#111128] px-4 py-3 transition-colors hover:border-[#3a3a5a] ${!a.online?"opacity-50":""}`,children:[(0,b.jsxs)("div",{className:"hidden sm:grid sm:grid-cols-12 gap-2 items-center",children:[(0,b.jsx)("div",{className:"col-span-1",children:(0,b.jsx)("span",{className:`text-xs px-2 py-0.5 rounded-md border ${j[c]||j.offline}`,children:c})}),(0,b.jsx)("div",{className:"col-span-2 min-w-0",children:(0,b.jsxs)(d.default,{href:`/node?alias=${encodeURIComponent(a.alias)}`,className:"flex items-center gap-2 min-w-0 hover:text-cyan-300",children:[(0,b.jsx)(i.AliasAvatar,{alias:a.alias,size:20}),(0,b.jsx)("span",{className:"truncate text-sm font-medium text-white",children:a.alias})]})}),(0,b.jsx)("div",{className:"col-span-2 truncate text-xs text-gray-400",children:a.agent||"--"}),(0,b.jsx)("div",{className:"col-span-2 truncate text-xs text-gray-400",children:a.server||"--"}),(0,b.jsx)("div",{className:"col-span-2 truncate text-xs text-gray-500",children:a.task||"--"}),(0,b.jsx)("div",{className:"col-span-1 text-xs text-gray-500",children:(0,e.timeAgo)(a.last_seen_at||a.updated_at)}),(0,b.jsxs)("div",{className:"col-span-2 flex justify-end gap-1.5",children:[(0,b.jsx)("button",{type:"button",onClick:()=>F(a.alias),className:"rounded-lg border border-green-500/20 bg-green-500/10 px-2 py-1 text-xs text-green-300 hover:bg-green-500/20",children:"Chat"}),(0,b.jsx)("button",{type:"button",onClick:()=>I(a.alias),className:"rounded-lg border border-cyan-500/20 bg-cyan-500/10 px-2 py-1 text-xs text-cyan-300 hover:bg-cyan-500/20",children:"Task"})]})]}),(0,b.jsxs)("div",{className:"sm:hidden space-y-2",children:[(0,b.jsxs)("div",{className:"flex items-center gap-2.5",children:[(0,b.jsx)(i.AliasAvatar,{alias:a.alias,size:28}),(0,b.jsxs)(d.default,{href:`/node?alias=${encodeURIComponent(a.alias)}`,className:"min-w-0 flex-1 hover:text-cyan-300",children:[(0,b.jsx)("div",{className:"truncate text-sm font-medium text-white",children:a.alias}),(0,b.jsxs)("div",{className:"truncate text-[10px] text-gray-500",children:[a.agent||"—"," · ",(0,e.timeAgo)(a.last_seen_at||a.updated_at)]})]}),(0,b.jsx)("span",{className:`shrink-0 text-xs px-2 py-0.5 rounded-md border ${j[c]||j.offline}`,children:c})]}),a.task&&(0,b.jsx)("div",{className:"truncate text-xs text-gray-500",children:a.task}),(0,b.jsxs)("div",{className:"flex gap-2",children:[(0,b.jsx)("button",{type:"button",onClick:()=>F(a.alias),className:"flex-1 rounded-lg border border-green-500/20 bg-green-500/10 px-3 py-2 text-xs text-green-300 hover:bg-green-500/20",children:"Chat"}),(0,b.jsx)("button",{type:"button",onClick:()=>I(a.alias),className:"flex-1 rounded-lg border border-cyan-500/20 bg-cyan-500/10 px-3 py-2 text-xs text-cyan-300 hover:bg-cyan-500/20",children:"Send Task"})]})]}),A===a.alias&&(0,b.jsxs)("div",{className:"mt-3 space-y-2 border-t border-[#2a2a4a] pt-3",children:[(0,b.jsx)("input",{type:"text",value:y[a.alias]||"",onChange:b=>J(a.alias,b.target.value),onKeyDown:b=>"Enter"===b.key&&K(a.alias),placeholder:`Send task to ${a.alias}...`,className:"w-full rounded-lg border border-[#2a2a4a] bg-[#0a0a15] px-3 py-2 text-xs text-white placeholder-gray-600 focus:border-cyan-500 focus:outline-none"}),(0,b.jsxs)("div",{className:"flex justify-end gap-2",children:[(0,b.jsx)("button",{type:"button",onClick:()=>B(null),className:"rounded-lg border border-gray-700 px-3 py-1.5 text-xs text-gray-400 hover:text-gray-200",children:"Cancel"}),(0,b.jsx)("button",{type:"button",onClick:()=>K(a.alias),disabled:f.sending||!(y[a.alias]||"").trim(),className:"rounded-lg bg-cyan-600 px-3 py-1.5 text-xs text-white hover:bg-cyan-500 disabled:cursor-not-allowed disabled:bg-gray-700",children:f.sending?"Sending...":"Send"})]})]}),f.error&&(0,b.jsx)("div",{className:"mt-2 text-xs text-red-400",children:f.error}),f.success&&A!==a.alias&&(0,b.jsx)("div",{className:"mt-2 text-xs text-green-400",children:f.success})]},a.alias)})]}),E&&(0,b.jsx)(g.TaskChatPanel,{alias:E,onClose:()=>F(null)})]})}])}];
2
-
3
- //# sourceMappingURL=%5Broot-of-the-server%5D__06pu~4t._.js.map