@sleep2agi/agent-network-dashboard 0.5.7-preview.6 → 0.5.7-preview.66

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 (376) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +0 -1
  3. package/.next/build-manifest.json +3 -3
  4. package/.next/diagnostics/route-bundle-stats.json +65 -65
  5. package/.next/fallback-build-manifest.json +3 -3
  6. package/.next/prerender-manifest.json +3 -3
  7. package/.next/routes-manifest.json +0 -6
  8. package/.next/server/app/_global-error.html +1 -1
  9. package/.next/server/app/_global-error.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  14. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/.next/server/app/_not-found/page/next-font-manifest.json +2 -1
  16. package/.next/server/app/_not-found/page.js +1 -1
  17. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  18. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  19. package/.next/server/app/_not-found.html +4 -4
  20. package/.next/server/app/_not-found.rsc +16 -16
  21. package/.next/server/app/_not-found.segments/_full.segment.rsc +16 -16
  22. package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  23. package/.next/server/app/_not-found.segments/_index.segment.rsc +9 -9
  24. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  25. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  26. package/.next/server/app/_not-found.segments/_tree.segment.rsc +3 -3
  27. package/.next/server/app/admin/page/next-font-manifest.json +2 -1
  28. package/.next/server/app/admin/page.js +1 -1
  29. package/.next/server/app/admin/page.js.nft.json +1 -1
  30. package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
  31. package/.next/server/app/admin.html +4 -4
  32. package/.next/server/app/admin.rsc +20 -19
  33. package/.next/server/app/admin.segments/_full.segment.rsc +20 -19
  34. package/.next/server/app/admin.segments/_head.segment.rsc +4 -4
  35. package/.next/server/app/admin.segments/_index.segment.rsc +9 -9
  36. package/.next/server/app/admin.segments/_tree.segment.rsc +5 -4
  37. package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +4 -4
  38. package/.next/server/app/admin.segments/admin.segment.rsc +3 -3
  39. package/.next/server/app/index.html +4 -4
  40. package/.next/server/app/index.rsc +20 -19
  41. package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
  42. package/.next/server/app/index.segments/_full.segment.rsc +20 -19
  43. package/.next/server/app/index.segments/_head.segment.rsc +4 -4
  44. package/.next/server/app/index.segments/_index.segment.rsc +9 -9
  45. package/.next/server/app/index.segments/_tree.segment.rsc +5 -4
  46. package/.next/server/app/login/page/next-font-manifest.json +2 -1
  47. package/.next/server/app/login/page.js +1 -1
  48. package/.next/server/app/login/page.js.nft.json +1 -1
  49. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  50. package/.next/server/app/login.html +2 -2
  51. package/.next/server/app/login.rsc +20 -19
  52. package/.next/server/app/login.segments/_full.segment.rsc +20 -19
  53. package/.next/server/app/login.segments/_head.segment.rsc +4 -4
  54. package/.next/server/app/login.segments/_index.segment.rsc +9 -9
  55. package/.next/server/app/login.segments/_tree.segment.rsc +5 -4
  56. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
  57. package/.next/server/app/login.segments/login.segment.rsc +3 -3
  58. package/.next/server/app/logs/page/next-font-manifest.json +2 -1
  59. package/.next/server/app/logs/page.js +1 -1
  60. package/.next/server/app/logs/page.js.nft.json +1 -1
  61. package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
  62. package/.next/server/app/logs.html +4 -4
  63. package/.next/server/app/logs.rsc +20 -19
  64. package/.next/server/app/logs.segments/_full.segment.rsc +20 -19
  65. package/.next/server/app/logs.segments/_head.segment.rsc +4 -4
  66. package/.next/server/app/logs.segments/_index.segment.rsc +9 -9
  67. package/.next/server/app/logs.segments/_tree.segment.rsc +5 -4
  68. package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +4 -4
  69. package/.next/server/app/logs.segments/logs.segment.rsc +3 -3
  70. package/.next/server/app/manifest.webmanifest.body +1 -1
  71. package/.next/server/app/messages/page/next-font-manifest.json +2 -1
  72. package/.next/server/app/messages/page.js +1 -1
  73. package/.next/server/app/messages/page.js.nft.json +1 -1
  74. package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
  75. package/.next/server/app/messages.html +4 -4
  76. package/.next/server/app/messages.rsc +20 -19
  77. package/.next/server/app/messages.segments/_full.segment.rsc +20 -19
  78. package/.next/server/app/messages.segments/_head.segment.rsc +4 -4
  79. package/.next/server/app/messages.segments/_index.segment.rsc +9 -9
  80. package/.next/server/app/messages.segments/_tree.segment.rsc +5 -4
  81. package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +4 -4
  82. package/.next/server/app/messages.segments/messages.segment.rsc +3 -3
  83. package/.next/server/app/node/page/next-font-manifest.json +2 -1
  84. package/.next/server/app/node/page.js +1 -1
  85. package/.next/server/app/node/page.js.nft.json +1 -1
  86. package/.next/server/app/node/page_client-reference-manifest.js +1 -1
  87. package/.next/server/app/node.html +4 -4
  88. package/.next/server/app/node.rsc +20 -19
  89. package/.next/server/app/node.segments/_full.segment.rsc +20 -19
  90. package/.next/server/app/node.segments/_head.segment.rsc +4 -4
  91. package/.next/server/app/node.segments/_index.segment.rsc +9 -9
  92. package/.next/server/app/node.segments/_tree.segment.rsc +5 -4
  93. package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +4 -4
  94. package/.next/server/app/node.segments/node.segment.rsc +3 -3
  95. package/.next/server/app/nodes/page/next-font-manifest.json +2 -1
  96. package/.next/server/app/nodes/page.js +1 -1
  97. package/.next/server/app/nodes/page.js.nft.json +1 -1
  98. package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
  99. package/.next/server/app/nodes.html +4 -4
  100. package/.next/server/app/nodes.rsc +20 -19
  101. package/.next/server/app/nodes.segments/_full.segment.rsc +20 -19
  102. package/.next/server/app/nodes.segments/_head.segment.rsc +4 -4
  103. package/.next/server/app/nodes.segments/_index.segment.rsc +9 -9
  104. package/.next/server/app/nodes.segments/_tree.segment.rsc +5 -4
  105. package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +4 -4
  106. package/.next/server/app/nodes.segments/nodes.segment.rsc +3 -3
  107. package/.next/server/app/page/next-font-manifest.json +2 -1
  108. package/.next/server/app/page.js +1 -1
  109. package/.next/server/app/page.js.nft.json +1 -1
  110. package/.next/server/app/page_client-reference-manifest.js +1 -1
  111. package/.next/server/app/server-logs/page/next-font-manifest.json +2 -1
  112. package/.next/server/app/server-logs/page.js +1 -1
  113. package/.next/server/app/server-logs/page.js.nft.json +1 -1
  114. package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
  115. package/.next/server/app/server-logs.html +4 -4
  116. package/.next/server/app/server-logs.rsc +20 -19
  117. package/.next/server/app/server-logs.segments/_full.segment.rsc +20 -19
  118. package/.next/server/app/server-logs.segments/_head.segment.rsc +4 -4
  119. package/.next/server/app/server-logs.segments/_index.segment.rsc +9 -9
  120. package/.next/server/app/server-logs.segments/_tree.segment.rsc +5 -4
  121. package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +4 -4
  122. package/.next/server/app/server-logs.segments/server-logs.segment.rsc +3 -3
  123. package/.next/server/app/servers/page/next-font-manifest.json +2 -1
  124. package/.next/server/app/servers/page.js +1 -1
  125. package/.next/server/app/servers/page.js.nft.json +1 -1
  126. package/.next/server/app/servers/page_client-reference-manifest.js +1 -1
  127. package/.next/server/app/servers.html +4 -4
  128. package/.next/server/app/servers.rsc +20 -19
  129. package/.next/server/app/servers.segments/_full.segment.rsc +20 -19
  130. package/.next/server/app/servers.segments/_head.segment.rsc +4 -4
  131. package/.next/server/app/servers.segments/_index.segment.rsc +9 -9
  132. package/.next/server/app/servers.segments/_tree.segment.rsc +5 -4
  133. package/.next/server/app/servers.segments/servers/__PAGE__.segment.rsc +4 -4
  134. package/.next/server/app/servers.segments/servers.segment.rsc +3 -3
  135. package/.next/server/app/settings/networks/page/next-font-manifest.json +2 -1
  136. package/.next/server/app/settings/networks/page.js +1 -1
  137. package/.next/server/app/settings/networks/page.js.nft.json +1 -1
  138. package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
  139. package/.next/server/app/settings/networks.html +4 -4
  140. package/.next/server/app/settings/networks.rsc +20 -19
  141. package/.next/server/app/settings/networks.segments/_full.segment.rsc +20 -19
  142. package/.next/server/app/settings/networks.segments/_head.segment.rsc +4 -4
  143. package/.next/server/app/settings/networks.segments/_index.segment.rsc +9 -9
  144. package/.next/server/app/settings/networks.segments/_tree.segment.rsc +5 -4
  145. package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +4 -4
  146. package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +3 -3
  147. package/.next/server/app/settings/networks.segments/settings.segment.rsc +3 -3
  148. package/.next/server/app/settings/page/next-font-manifest.json +2 -1
  149. package/.next/server/app/settings/page.js +1 -1
  150. package/.next/server/app/settings/page.js.nft.json +1 -1
  151. package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  152. package/.next/server/app/settings/tokens/page/next-font-manifest.json +2 -1
  153. package/.next/server/app/settings/tokens/page.js +1 -1
  154. package/.next/server/app/settings/tokens/page.js.nft.json +1 -1
  155. package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
  156. package/.next/server/app/settings/tokens.html +4 -4
  157. package/.next/server/app/settings/tokens.rsc +20 -19
  158. package/.next/server/app/settings/tokens.segments/_full.segment.rsc +20 -19
  159. package/.next/server/app/settings/tokens.segments/_head.segment.rsc +4 -4
  160. package/.next/server/app/settings/tokens.segments/_index.segment.rsc +9 -9
  161. package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +5 -4
  162. package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +4 -4
  163. package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +3 -3
  164. package/.next/server/app/settings/tokens.segments/settings.segment.rsc +3 -3
  165. package/.next/server/app/settings.html +4 -4
  166. package/.next/server/app/settings.rsc +20 -19
  167. package/.next/server/app/settings.segments/_full.segment.rsc +20 -19
  168. package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
  169. package/.next/server/app/settings.segments/_index.segment.rsc +9 -9
  170. package/.next/server/app/settings.segments/_tree.segment.rsc +5 -4
  171. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
  172. package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
  173. package/.next/server/app/tasks/[id]/page/next-font-manifest.json +2 -1
  174. package/.next/server/app/tasks/[id]/page.js +1 -1
  175. package/.next/server/app/tasks/[id]/page.js.nft.json +1 -1
  176. package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
  177. package/.next/server/app/tasks/page/next-font-manifest.json +2 -1
  178. package/.next/server/app/tasks/page.js +1 -1
  179. package/.next/server/app/tasks/page.js.nft.json +1 -1
  180. package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
  181. package/.next/server/app/tasks.html +4 -4
  182. package/.next/server/app/tasks.rsc +20 -19
  183. package/.next/server/app/tasks.segments/_full.segment.rsc +20 -19
  184. package/.next/server/app/tasks.segments/_head.segment.rsc +4 -4
  185. package/.next/server/app/tasks.segments/_index.segment.rsc +9 -9
  186. package/.next/server/app/tasks.segments/_tree.segment.rsc +5 -4
  187. package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +4 -4
  188. package/.next/server/app/tasks.segments/tasks.segment.rsc +3 -3
  189. package/.next/server/app-paths-manifest.json +0 -1
  190. package/.next/server/chunks/00jm_next_dist_0ju_ux9._.js +1 -1
  191. package/.next/server/chunks/00jm_next_dist_0ju_ux9._.js.map +1 -1
  192. package/.next/server/chunks/ssr/[root-of-the-server]__030vg4n._.js +1 -1
  193. package/.next/server/chunks/ssr/[root-of-the-server]__030vg4n._.js.map +1 -1
  194. package/.next/server/chunks/ssr/[root-of-the-server]__04gz75y._.js +3 -0
  195. package/.next/server/chunks/ssr/[root-of-the-server]__04gz75y._.js.map +1 -0
  196. package/.next/server/chunks/ssr/[root-of-the-server]__05kf31s._.js +3 -0
  197. package/.next/server/chunks/ssr/[root-of-the-server]__05kf31s._.js.map +1 -0
  198. package/.next/server/chunks/ssr/[root-of-the-server]__096ytyk._.js +3 -0
  199. package/.next/server/chunks/ssr/[root-of-the-server]__096ytyk._.js.map +1 -0
  200. package/.next/server/chunks/ssr/[root-of-the-server]__0fhoq8i._.js +1 -1
  201. package/.next/server/chunks/ssr/[root-of-the-server]__0fhoq8i._.js.map +1 -1
  202. package/.next/server/chunks/ssr/[root-of-the-server]__0u4-66w._.js +8 -0
  203. package/.next/server/chunks/ssr/[root-of-the-server]__0u4-66w._.js.map +1 -0
  204. package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js +3 -3
  205. package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js.map +1 -1
  206. package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js +1 -1
  207. package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js.map +1 -1
  208. package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js +1 -1
  209. package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js.map +1 -1
  210. package/.next/server/chunks/ssr/agent-network-dashboard_app_0_870i8._.js +3 -0
  211. package/.next/server/chunks/ssr/agent-network-dashboard_app_0_870i8._.js.map +1 -0
  212. package/.next/server/chunks/ssr/agent-network-dashboard_app_0_d45-d._.js +1 -1
  213. package/.next/server/chunks/ssr/agent-network-dashboard_app_0_d45-d._.js.map +1 -1
  214. package/.next/server/chunks/ssr/agent-network-dashboard_app_0fjlnh~._.js +3 -0
  215. package/.next/server/chunks/ssr/agent-network-dashboard_app_0fjlnh~._.js.map +1 -0
  216. package/.next/server/chunks/ssr/agent-network-dashboard_app_0gd.4pc._.js +9 -0
  217. package/.next/server/chunks/ssr/agent-network-dashboard_app_0gd.4pc._.js.map +1 -0
  218. package/.next/server/chunks/ssr/agent-network-dashboard_app_0wn4jc5._.js +3 -0
  219. package/.next/server/chunks/ssr/agent-network-dashboard_app_0wn4jc5._.js.map +1 -0
  220. package/.next/server/chunks/ssr/agent-network-dashboard_app_0xgney8._.js +1 -1
  221. package/.next/server/chunks/ssr/agent-network-dashboard_app_0xgney8._.js.map +1 -1
  222. package/.next/server/chunks/ssr/agent-network-dashboard_app_10hjgv4._.js +1 -1
  223. package/.next/server/chunks/ssr/agent-network-dashboard_app_10hjgv4._.js.map +1 -1
  224. package/.next/server/chunks/ssr/agent-network-dashboard_app_12l4oto._.js +1 -1
  225. package/.next/server/chunks/ssr/agent-network-dashboard_app_12l4oto._.js.map +1 -1
  226. package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0r7kb.o._.js +9 -0
  227. package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0r7kb.o._.js.map +1 -0
  228. package/.next/server/chunks/ssr/agent-network-dashboard_app_servers_page_tsx_0jib5qm._.js +1 -1
  229. package/.next/server/chunks/ssr/agent-network-dashboard_app_servers_page_tsx_0jib5qm._.js.map +1 -1
  230. package/.next/server/chunks/ssr/agent-network-dashboard_app_tasks_page_tsx_0mwxy4z._.js +1 -1
  231. package/.next/server/chunks/ssr/agent-network-dashboard_app_tasks_page_tsx_0mwxy4z._.js.map +1 -1
  232. package/.next/server/middleware-build-manifest.js +3 -3
  233. package/.next/server/next-font-manifest.js +1 -1
  234. package/.next/server/next-font-manifest.json +30 -15
  235. package/.next/server/pages/404.html +4 -4
  236. package/.next/server/pages/500.html +1 -1
  237. package/.next/server/server-reference-manifest.js +1 -1
  238. package/.next/server/server-reference-manifest.json +1 -1
  239. package/.next/static/chunks/{0jp~cs9-zkmqa.js → 00b4y77vxfabl.js} +1 -1
  240. package/.next/static/chunks/00y0qgigxb62-.js +1 -0
  241. package/.next/static/chunks/049vx3qljs1tt.js +1 -0
  242. package/.next/static/chunks/04cf.98_cyxen.js +1 -0
  243. package/.next/static/chunks/066jf0nk75nic.css +2 -0
  244. package/.next/static/chunks/07sj5zwg46-5~.css +1 -0
  245. package/.next/static/chunks/0_bn~gcrgo.4n.js +1 -0
  246. package/.next/static/chunks/0g4d-_fi-d9hg.js +1 -0
  247. package/.next/static/chunks/0t4lpxu4ny9-3.js +1 -0
  248. package/.next/static/chunks/0vgrwqsgja19l.js +1 -0
  249. package/.next/static/chunks/0wz0122ym_gr3.js +1 -0
  250. package/.next/static/chunks/0xxx7yeapw~2a.js +1 -0
  251. package/.next/static/chunks/0y5gol09tlu63.js +1 -0
  252. package/.next/static/chunks/143g3n8za083f.js +7 -0
  253. package/.next/static/chunks/149a4l50_3vw-.js +7 -0
  254. package/.next/static/chunks/14lac~_cpjlh..js +1 -0
  255. package/.next/static/chunks/152_p6jt7txp6.js +1 -0
  256. package/.next/static/chunks/165v74i3j-wk0.js +1 -0
  257. package/.next/static/chunks/16glr1c4nc85n.js +4 -0
  258. package/.next/static/chunks/17-7ama~oijou.js +1 -0
  259. package/.next/static/media/4fa387ec64143e14-s.0wkzw~je483f-.woff2 +0 -0
  260. package/.next/static/media/53b9e256198e5412-s.0-wfv7uh4i7h9.woff2 +0 -0
  261. package/.next/static/media/5ce348bf30bf5439-s.0zgw-jeven.3w.woff2 +0 -0
  262. package/.next/static/media/6306c77e7c8268e4-s.0rhz0arwfsn~5.woff2 +0 -0
  263. package/.next/static/media/7178b3e590c64307-s.0nx0ww8fni_q3.woff2 +0 -0
  264. package/.next/static/media/797e433ab948586e-s.p.08e28id.o-okb.woff2 +0 -0
  265. package/.next/static/media/7d817b4c03b0c5f1-s.0l76wvqk9d84w.woff2 +0 -0
  266. package/.next/static/media/8a480f0b521d4e75-s.0jzbimsg8vl84.woff2 +0 -0
  267. package/.next/static/media/bbc41e54d2fcbd21-s.0k4k9394f2q-k.woff2 +0 -0
  268. package/.next/static/media/caa3a2e1cccd8315-s.p.09~u27dqhyhd6.woff2 +0 -0
  269. package/.next/static/media/fef07dbb0973bf53-s.12tyk43_3sh9u.woff2 +0 -0
  270. package/.next/trace +2 -2
  271. package/.next/trace-build +1 -1
  272. package/.next/types/routes.d.ts +1 -2
  273. package/.next/types/validator.ts +0 -9
  274. package/app/admin/page.tsx +53 -38
  275. package/app/components/AgentCard.tsx +20 -9
  276. package/app/components/AppShell.tsx +7 -1
  277. package/app/components/ChatPopover.tsx +1 -1
  278. package/app/components/CollapsibleSearch.tsx +127 -0
  279. package/app/components/CommandCenter.tsx +14 -4
  280. package/app/components/CommandPalette.tsx +6 -6
  281. package/app/components/DispatchPanel.tsx +13 -10
  282. package/app/components/EmptyState.tsx +11 -4
  283. package/app/components/HealthBanner.tsx +28 -4
  284. package/app/components/HelpOverlay.tsx +4 -7
  285. package/app/components/LoadingSkeleton.tsx +31 -21
  286. package/app/components/MobileNav.tsx +28 -21
  287. package/app/components/Sidebar.tsx +30 -23
  288. package/app/components/StatsBar.tsx +40 -42
  289. package/app/components/TaskChatPanel.tsx +19 -5
  290. package/app/components/TaskDrawer.tsx +9 -7
  291. package/app/components/ThemeSwitcher.tsx +15 -79
  292. package/app/components/TopoGraph.tsx +31 -21
  293. package/app/components/UserBar.tsx +5 -5
  294. package/app/globals.css +1757 -1776
  295. package/app/layout.tsx +37 -4
  296. package/app/lib/hooks.ts +0 -5
  297. package/app/lib/status.ts +24 -17
  298. package/app/login/page.tsx +7 -7
  299. package/app/logs/page.tsx +12 -6
  300. package/app/manifest.ts +2 -2
  301. package/app/messages/page.tsx +84 -57
  302. package/app/node/page.tsx +27 -17
  303. package/app/nodes/page.tsx +62 -49
  304. package/app/page.tsx +40 -269
  305. package/app/server-logs/page.tsx +40 -14
  306. package/app/servers/page.tsx +33 -12
  307. package/app/settings/networks/page.tsx +17 -15
  308. package/app/settings/page.tsx +90 -95
  309. package/app/settings/tokens/page.tsx +5 -5
  310. package/app/tasks/[id]/page.tsx +10 -10
  311. package/app/tasks/page.tsx +58 -34
  312. package/bin/start.js +0 -0
  313. package/package.json +1 -1
  314. package/public/favicon.svg +1 -1
  315. package/public/manifest.webmanifest +24 -0
  316. package/public/robots.txt +7 -0
  317. package/.next/server/app/api/hub/license/route/app-paths-manifest.json +0 -3
  318. package/.next/server/app/api/hub/license/route/build-manifest.json +0 -9
  319. package/.next/server/app/api/hub/license/route/server-reference-manifest.json +0 -4
  320. package/.next/server/app/api/hub/license/route.js +0 -7
  321. package/.next/server/app/api/hub/license/route.js.map +0 -5
  322. package/.next/server/app/api/hub/license/route.js.nft.json +0 -1
  323. package/.next/server/app/api/hub/license/route_client-reference-manifest.js +0 -3
  324. package/.next/server/chunks/0ykm__next-internal_server_app_api_hub_license_route_actions_0a4.fuh.js +0 -3
  325. package/.next/server/chunks/0ykm__next-internal_server_app_api_hub_license_route_actions_0a4.fuh.js.map +0 -1
  326. package/.next/server/chunks/[root-of-the-server]__0rovr5-._.js +0 -3
  327. package/.next/server/chunks/[root-of-the-server]__0rovr5-._.js.map +0 -1
  328. package/.next/server/chunks/ssr/[root-of-the-server]__0lu1wok._.js +0 -8
  329. package/.next/server/chunks/ssr/[root-of-the-server]__0lu1wok._.js.map +0 -1
  330. package/.next/server/chunks/ssr/[root-of-the-server]__0nw~zhp._.js +0 -3
  331. package/.next/server/chunks/ssr/[root-of-the-server]__0nw~zhp._.js.map +0 -1
  332. package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js +0 -3
  333. package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js.map +0 -1
  334. package/.next/server/chunks/ssr/[root-of-the-server]__11fu-5m._.js +0 -3
  335. package/.next/server/chunks/ssr/[root-of-the-server]__11fu-5m._.js.map +0 -1
  336. package/.next/server/chunks/ssr/agent-network-dashboard_app_057q.ne._.js +0 -3
  337. package/.next/server/chunks/ssr/agent-network-dashboard_app_057q.ne._.js.map +0 -1
  338. package/.next/server/chunks/ssr/agent-network-dashboard_app_0i3759l._.js +0 -3
  339. package/.next/server/chunks/ssr/agent-network-dashboard_app_0i3759l._.js.map +0 -1
  340. package/.next/server/chunks/ssr/agent-network-dashboard_app_1153xeb._.js +0 -9
  341. package/.next/server/chunks/ssr/agent-network-dashboard_app_1153xeb._.js.map +0 -1
  342. package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0s5uqlp._.js +0 -9
  343. package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0s5uqlp._.js.map +0 -1
  344. package/.next/server/chunks/ssr/agent-network-dashboard_app_server-logs_page_tsx_0dg.l_8._.js +0 -3
  345. package/.next/server/chunks/ssr/agent-network-dashboard_app_server-logs_page_tsx_0dg.l_8._.js.map +0 -1
  346. package/.next/static/chunks/0-mpa_947ipeq.js +0 -1
  347. package/.next/static/chunks/00zay6nmw22rq.js +0 -1
  348. package/.next/static/chunks/03~5pxwbxxw-b.js +0 -1
  349. package/.next/static/chunks/04~fkia6-79k3.js +0 -1
  350. package/.next/static/chunks/0561vp5-q5.zp.js +0 -1
  351. package/.next/static/chunks/05uk96gc~9mni.js +0 -1
  352. package/.next/static/chunks/0a.9~-nf0gpec.js +0 -1
  353. package/.next/static/chunks/0dlmr1dhvv6mu.js +0 -1
  354. package/.next/static/chunks/0im751o4n61c7.js +0 -1
  355. package/.next/static/chunks/0inql3s9ldyx5.js +0 -1
  356. package/.next/static/chunks/0ku0fjqlm9mca.js +0 -1
  357. package/.next/static/chunks/0mcamnu4w_x1r.js +0 -4
  358. package/.next/static/chunks/0nqm.7w9_inwd.js +0 -7
  359. package/.next/static/chunks/0tn~avb7mn01c.css +0 -1
  360. package/.next/static/chunks/0ynu45t2_2dxl.js +0 -1
  361. package/.next/static/chunks/13yktdzuatx3d.js +0 -1
  362. package/.next/static/chunks/15-ltfhot3b4n.js +0 -7
  363. package/.next/static/chunks/17sxlwlx5fhrp.css +0 -1
  364. package/.next/static/chunks/181u38qblp8lz.js +0 -1
  365. package/.next/static/media/4fa387ec64143e14-s.0.qu-9752pffj.woff2 +0 -0
  366. package/.next/static/media/5ce348bf30bf5439-s.0ee55_hj9qcer.woff2 +0 -0
  367. package/.next/static/media/6306c77e7c8268e4-s.0mao5jbfbduzp.woff2 +0 -0
  368. package/.next/static/media/797e433ab948586e-s.p.09zddjkbdep5a.woff2 +0 -0
  369. package/.next/static/media/7d817b4c03b0c5f1-s.0uzt.a6d44yda.woff2 +0 -0
  370. package/.next/static/media/bbc41e54d2fcbd21-s.0mvwgmnhv29no.woff2 +0 -0
  371. package/app/api/hub/license/route.ts +0 -33
  372. package/app/components/BroadcastBar.tsx +0 -84
  373. package/app/components/InboxPanel.tsx +0 -36
  374. /package/.next/static/{ZeU15JAI2Ap6fZ675phhF → 2dHfsg3G4Q4tXXzlz3hFv}/_buildManifest.js +0 -0
  375. /package/.next/static/{ZeU15JAI2Ap6fZ675phhF → 2dHfsg3G4Q4tXXzlz3hFv}/_clientMiddlewareManifest.js +0 -0
  376. /package/.next/static/{ZeU15JAI2Ap6fZ675phhF → 2dHfsg3G4Q4tXXzlz3hFv}/_ssgManifest.js +0 -0
package/app/page.tsx CHANGED
@@ -2,22 +2,14 @@
2
2
 
3
3
  import { useEffect, useState } from 'react';
4
4
  import Link from 'next/link';
5
- import { formatUptime, previewContent } from './components/utils';
6
5
  import { StatsBar } from './components/StatsBar';
7
- import { BroadcastBar } from './components/BroadcastBar';
8
6
  import { TopoGraph } from './components/TopoGraph';
9
7
  import { AgentCard } from './components/AgentCard';
10
- import { InboxPanel } from './components/InboxPanel';
11
8
  import { LoadingSkeleton } from './components/LoadingSkeleton';
12
9
  import { NodesEmptyState as EmptyState } from './components/EmptyState';
13
- import { AliasAvatar } from './components/AliasAvatar';
14
- import { STATUS_DOT_HEX, STATUS_CHIP_CLASS } from './lib/status';
15
- import { UserBar } from './components/UserBar';
16
10
  import { CommandCenter, useCommandCenter } from './components/CommandCenter';
17
- import { DispatchPanel } from './components/DispatchPanel';
18
- import { useSessions, useHealth, useAnetConfig, useTasks, useStats } from './lib/hooks';
11
+ import { useSessions, useHealth, useTasks, useStats } from './lib/hooks';
19
12
  import { useSSE } from './lib/useSSE';
20
- import { InboxMessage } from './components/types';
21
13
  import { useSWRConfig } from 'swr';
22
14
 
23
15
  export default function Dashboard() {
@@ -33,14 +25,10 @@ export default function Dashboard() {
33
25
 
34
26
  const { sessions, hint: sessHint, error: sessError, isLoading } = useSessions();
35
27
  const { health } = useHealth();
36
- const { config: anetConfig } = useAnetConfig();
37
28
  const { tasks } = useTasks({ limit: '500' });
38
29
  const { stats } = useStats();
39
30
  const [showTopo, setShowTopo] = useState(typeof window !== 'undefined' && window.innerWidth >= 1024);
40
- const [showConfig, setShowConfig] = useState(false);
41
31
  const cmd = useCommandCenter();
42
- const [showDispatch, setShowDispatch] = useState(false);
43
- const [inbox, setInbox] = useState<InboxMessage[]>([]);
44
32
  const [agentFilter, setAgentFilter] = useState<'all' | 'working' | 'idle' | 'offline'>('all');
45
33
  // #84: last node.renamed event — passed to TopoGraph so an open chat
46
34
  // popover follows the rename instead of pointing at a dead alias. `ts`
@@ -75,22 +63,6 @@ export default function Dashboard() {
75
63
  },
76
64
  });
77
65
 
78
- // Fetch inbox (not in SWR since it accumulates)
79
- useEffect(() => {
80
- const fetchInbox = () => {
81
- fetch('/api/hub/inbox').then(r => r.json()).then(data => {
82
- if (data.messages?.length) setInbox(prev => {
83
- const ids = new Set(prev.map(m => m.id));
84
- const newMsgs = data.messages.filter((m: { id: string }) => !ids.has(m.id));
85
- return [...newMsgs, ...prev].slice(0, 100);
86
- });
87
- }).catch(() => {});
88
- };
89
- fetchInbox();
90
- const interval = setInterval(fetchInbox, 10000);
91
- return () => clearInterval(interval);
92
- }, []);
93
-
94
66
  if (isLoading) return <LoadingSkeleton />;
95
67
 
96
68
  const sseSessions = health?.sse_sessions || {};
@@ -103,14 +75,6 @@ export default function Dashboard() {
103
75
  const online = sessions.filter(isOnline).length;
104
76
  const total = sessions.length;
105
77
  const working = sessions.filter(s => s.status === 'working').length;
106
- const uptime = health ? formatUptime(health.uptime) : '--';
107
- const version = health?.version || '--';
108
- const configHealthy = Boolean(anetConfig?.hub && anetConfig.tokenConfigured);
109
- const configSourceLabel =
110
- anetConfig?.source === 'file' ? 'Local config'
111
- : anetConfig?.source === 'runtime-env' ? 'Runtime env'
112
- : 'Config missing';
113
-
114
78
  // Task stats: prefer /api/stats, fallback to manual
115
79
  const taskStats: Record<string, number> = {};
116
80
  if (stats?.tasks?.by_status?.length) {
@@ -132,233 +96,37 @@ export default function Dashboard() {
132
96
  return bWorking - aWorking;
133
97
  });
134
98
 
135
- /** Round 70: when the fleet is empty, the Overview reorders to lead with
136
- * the "Spin up your first agent" CTA and hides the Quick Navigation /
137
- * Nav rail / Broadcast bar that would otherwise occupy prime real estate
138
- * with zeros and dead-end links. Computed once, used as a gate below. */
139
- const fleetEmpty = sessions.length === 0 && !sessError;
140
-
141
99
  return (
142
- <div className="min-h-screen bg-[#0a0a1a] text-gray-100 p-4 sm:p-6 font-mono">
143
- <div className="lg:ml-0 ml-10">
144
- <StatsBar online={online} working={working} total={total} version={version} uptime={uptime} />
145
- </div>
100
+ <div className="min-h-screen bg-[#0b0b0d] text-gray-100 p-4 sm:p-6">
101
+ <StatsBar online={online} working={working} total={total} />
146
102
 
147
- {/* Dispatch + User Bar — Dispatch hidden when fleet empty (nothing to
148
- dispatch to); UserBar still useful (account/sign-out menu). */}
149
- <div className="flex items-center gap-3 mb-4">
150
- {!fleetEmpty && (
151
- <button onClick={() => setShowDispatch(true)}
152
- className="px-4 py-2 bg-gradient-to-r from-cyan-600 to-blue-600 hover:from-cyan-500 hover:to-blue-500 text-white text-sm font-medium rounded-xl shadow-lg shadow-cyan-500/10 transition-all active:scale-95 shrink-0">
153
- ⚡ Dispatch
154
- </button>
155
- )}
156
- <div className="flex-1"><UserBar /></div>
157
- </div>
158
-
159
- {/* anet config (collapsed by default) */}
160
- <section className="mb-6 rounded-lg border border-[#2a2a4a] bg-[#111128] px-4 py-3 shadow-lg shadow-black/20">
161
- <button onClick={() => setShowConfig(!showConfig)} className="w-full flex items-center justify-between text-left">
162
- <div className="flex items-center gap-2 text-xs">
163
- <span className="uppercase text-gray-600">Config</span>
164
- <span className={`w-2 h-2 rounded-full ${configHealthy ? 'bg-green-400' : 'bg-red-400'}`} />
165
- <span className="text-gray-500">{configSourceLabel}</span>
166
- </div>
167
- <svg className={`w-4 h-4 text-gray-600 transition-transform ${showConfig ? 'rotate-180' : ''}`} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
168
- <path strokeLinecap="round" strokeLinejoin="round" d="M19 9l-7 7-7-7" />
169
- </svg>
170
- </button>
171
- {showConfig && (
172
- <div className="mt-3 pt-3 border-t border-[#2a2a4a]">
173
- <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
174
- <div className="min-w-0">
175
- <div className="text-gray-100 truncate text-sm" title={anetConfig?.hub || undefined}>
176
- Hub: <span className={anetConfig?.hub ? 'text-cyan-300' : 'text-red-300'}>{anetConfig?.hub?.trim() || 'not configured'}</span>
177
- </div>
178
- </div>
179
- <div className="flex flex-wrap gap-2 text-xs">
180
- <span className={`px-2.5 py-1 rounded-md border ${anetConfig?.tokenConfigured ? 'bg-blue-500/5 text-blue-300 border-blue-500/20' : 'bg-gray-500/5 text-gray-400 border-gray-500/20'}`}>
181
- Token: {anetConfig?.tokenPreview || 'not configured'}
182
- </span>
183
- </div>
184
- </div>
185
- {anetConfig?.error && <div className="mt-2 text-xs text-gray-600">{anetConfig.error}</div>}
186
- </div>
187
- )}
188
- </section>
103
+ {/* #217 S5 (Vincent: "极简极简,这些都可以放到设置里面去"): the
104
+ Dispatch button and UserBar row are gone from Overview.
105
+ Dispatch lives in /admin (Send Task panel); sign-out lives in
106
+ Settings and the sidebar; network switching lives in the
107
+ sidebar. */}
189
108
 
190
- {/* Task Status Stats */}
109
+ {/* Task summary. #217 S5 (Vincent: "乱七八糟的东西太多"): the
110
+ 9-status colored chip wall is now a single quiet line — the
111
+ only two numbers that drive action are running and failed;
112
+ everything else lives on /tasks. */}
191
113
  {Object.keys(taskStats).length > 0 && (
192
- <section className="mb-6 rounded-lg border border-[#2a2a4a] bg-[#111128] px-4 py-3 shadow-lg shadow-black/20">
193
- <div className="flex items-center justify-between mb-2">
194
- <div className="text-xs uppercase text-gray-600">Task Status</div>
195
- <Link href="/tasks" prefetch={false} className="text-xs text-cyan-400 hover:text-cyan-300">View all &rarr;</Link>
196
- </div>
197
- <div className="flex flex-wrap gap-2">
198
- {/* Round 69: order is "hot first" — active flow before terminal
199
- states — intentionally different from the lifecycle order on
200
- /tasks. Colors come from shared STATUS_CHIP_CLASS so a
201
- palette tweak in app/lib/status.ts updates here too.
202
- 'created' added in r69 (was missing — enum-coverage bug). */}
203
- {(['running', 'delivered', 'acked', 'replied', 'created', 'failed', 'cancelled', 'expired', 'closed'] as const)
204
- .filter((key) => taskStats[key])
205
- .map((key) => (
206
- <Link key={key} href={`/tasks?status=${key}`} prefetch={false} className={`px-2.5 py-1 rounded-md border text-xs ${STATUS_CHIP_CLASS[key]} hover:opacity-80 transition-opacity`}>
207
- {key}: {taskStats[key]}
208
- </Link>
209
- ))}
114
+ <section className="mb-4 sm:mb-6 flex items-center justify-between rounded-lg border border-[#26262b] bg-[#161618] px-4 py-2.5 text-xs">
115
+ <div className="text-gray-400 tabular-nums">
116
+ <span className={taskStats['running'] ? 'text-green-400' : 'text-gray-500'}>{taskStats['running'] || 0} running</span>
117
+ <span className="text-gray-600"> &middot; </span>
118
+ <span className={taskStats['failed'] ? 'text-red-400' : 'text-gray-500'}>{taskStats['failed'] || 0} failed</span>
210
119
  </div>
120
+ <Link href="/tasks" prefetch={false} className="text-cyan-400 hover:text-cyan-300">View all &rarr;</Link>
211
121
  </section>
212
122
  )}
213
123
 
214
- {/* Quick Actions split into two distinct intents:
215
- (1) Top: live stat cards (carry data, drill-in on click)
216
- (2) Bottom: pure nav rail (no number, icon + label)
217
- Round 24 wrap both in a labelled block so the rhythm reads as
218
- "here are the main jumps" instead of two disconnected strips.
219
- Round 70 entire Quick Nav + Nav rail + Broadcast + Recent
220
- Activity block is hidden when the fleet is empty so the
221
- onboarding CTA gets the page above the fold. */}
222
- {!fleetEmpty && <>
223
- <div className="text-[10px] uppercase tracking-[0.12em] text-gray-600 mb-2">Quick navigation</div>
224
- <section className="mb-3 grid grid-cols-3 gap-2 sm:gap-3">
225
- {(() => {
226
- // Build breakdown popover content per card. Pure data — pure CSS
227
- // popover (no JS state) wires the hover-show transition below.
228
- const idleCount = sessions.filter(s => isOnline(s) && s.status !== 'working').length;
229
- const offlineCount = total - online;
230
- const orderedStatuses = ['running', 'replied', 'failed', 'cancelled', 'expired', 'closed', 'created', 'delivered', 'acked'];
231
- const failedRecent = tasks.filter((t: { status: string }) => t.status === 'failed').length;
232
-
233
- const cards = [
234
- {
235
- href: '/nodes', label: 'Nodes',
236
- value: `${online}/${total}`,
237
- sub: `${total > 0 ? Math.round((online / total) * 100) : 0}% online`,
238
- color: 'text-green-400 border-green-500/20',
239
- popover: total === 0 ? null : [
240
- { k: 'working', v: working, dot: '', color: '#4ade80' },
241
- { k: 'idle', v: idleCount, dot: '', color: '#22d3ee' },
242
- { k: 'offline', v: offlineCount, dot: '', color: '#9ca3af' },
243
- ],
244
- },
245
- {
246
- href: '/tasks', label: 'Tasks',
247
- value: String(Object.values(taskStats).reduce((a, b) => a + b, 0) || 0),
248
- sub: 'all-time',
249
- color: 'text-cyan-400 border-cyan-500/20',
250
- popover: Object.keys(taskStats).length === 0 ? null
251
- : orderedStatuses
252
- .filter(s => taskStats[s])
253
- .map(s => {
254
- // Inline hex avoids Tailwind purging dynamic
255
- // `bg-${color}-400` class names.
256
- const hex = ({
257
- running: '#4ade80', replied: '#a78bfa', failed: '#f87171',
258
- cancelled: '#facc15', expired: '#fb923c', closed: '#9ca3af',
259
- created: '#9ca3af', delivered: '#60a5fa', acked: '#22d3ee',
260
- } as Record<string, string>)[s] || '#9ca3af';
261
- return { k: s, v: taskStats[s], dot: '', color: hex };
262
- }),
263
- },
264
- {
265
- href: '/tasks?status=failed', label: 'Failed',
266
- value: String(taskStats['failed'] || 0),
267
- sub: taskStats['failed'] ? 'needs review' : 'none',
268
- color: taskStats['failed'] ? 'text-red-400 border-red-500/25' : 'text-gray-500 border-gray-700/30',
269
- popover: !failedRecent ? [{ k: 'no failures yet', v: '', dot: '', color: '#4b5563' }]
270
- : [{ k: `${failedRecent} in current view`, v: '', dot: '', color: '#f87171' }],
271
- },
272
- ];
273
-
274
- return cards.map(a => (
275
- <Link
276
- key={a.href}
277
- href={a.href}
278
- prefetch={false}
279
- className={`anet-stat-link group relative rounded-xl border ${a.color} bg-[#111128] px-3 py-3 transition-all hover:-translate-y-px`}
280
- >
281
- <div className="flex items-baseline justify-between">
282
- <div className={`text-xl font-semibold tabular-nums ${a.color.split(' ')[0]}`}>{a.value}</div>
283
- <div className="hidden sm:block text-[10px] text-gray-600 group-hover:text-gray-400 transition-colors">View →</div>
284
- </div>
285
- <div className="text-[11px] text-gray-400 mt-0.5">{a.label}</div>
286
- <div className="text-[10px] text-gray-600 mt-px">{a.sub}</div>
287
-
288
- {/* Hover popover — CSS-only, restrained. Hidden on touch
289
- (no :hover) so mobile is unaffected. Positioned just
290
- below the card so it doesn't fight nav rail. */}
291
- {a.popover && a.popover.length > 0 && (
292
- <div className="anet-stat-popover hidden md:block pointer-events-none absolute left-2 right-2 top-full mt-1 z-20 rounded-lg border border-[#2a2a4a] bg-[#0d0d1a] shadow-lg shadow-black/30 px-3 py-2 opacity-0 translate-y-[-2px] group-hover:opacity-100 group-hover:translate-y-0 transition-all duration-150 delay-100">
293
- <div className="text-[10px] text-gray-600 uppercase tracking-wider mb-1.5">Breakdown</div>
294
- <ul className="space-y-1">
295
- {a.popover.map(row => (
296
- <li key={row.k} className="flex items-center gap-2 text-[11px]">
297
- <span
298
- className="inline-block w-1.5 h-1.5 rounded-full shrink-0"
299
- style={{ backgroundColor: row.color }}
300
- aria-hidden
301
- />
302
- <span className="text-gray-400 capitalize">{row.k}</span>
303
- {row.v !== '' && <span className="ml-auto text-gray-300 tabular-nums font-medium">{row.v}</span>}
304
- </li>
305
- ))}
306
- </ul>
307
- </div>
308
- )}
309
- </Link>
310
- ));
311
- })()}
312
- </section>
313
-
314
- {/* Nav rail — pure navigation, icon + label, no data */}
315
- <section className="mb-6 grid grid-cols-3 gap-2 sm:gap-3">
316
- {[
317
- { href: '/messages', label: 'Messages', icon: 'M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z' },
318
- { href: '/logs', label: 'Audit log', icon: 'M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z M14 2v6h6 M16 13H8 M16 17H8 M10 9H8' },
319
- { href: '/admin', label: 'Admin', icon: 'M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4z M6 21v-2a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v2' },
320
- ].map(a => (
321
- <Link key={a.href} href={a.href} prefetch={false}
322
- className="anet-nav-tile flex items-center justify-center gap-2 rounded-xl border border-[#2a2a4a] bg-[#111128] px-3 py-2.5 text-[12px] text-gray-400 hover:text-gray-200 transition-colors">
323
- <svg className="w-4 h-4 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
324
- <path d={a.icon} />
325
- </svg>
326
- <span>{a.label}</span>
327
- </Link>
328
- ))}
329
- </section>
330
-
331
- <BroadcastBar />
332
-
333
- {/* Recent Activity */}
334
- {tasks.length > 0 && (
335
- <section className="mb-6 bg-[#111128] border border-[#2a2a4a] rounded-xl p-4">
336
- <div className="flex items-center justify-between mb-3">
337
- <h2 className="text-sm font-semibold text-gray-300">Recent Activity</h2>
338
- <Link href="/tasks" className="text-xs text-cyan-400 hover:text-cyan-300">All tasks &rarr;</Link>
339
- </div>
340
- <div className="space-y-2 max-h-40 overflow-y-auto">
341
- {tasks.slice(0, 5).map((t: { task_id: string; from_name: string; to_name: string; status: string; content: string; created_at: string }) => (
342
- <div key={t.task_id} className="flex items-center gap-2 text-xs">
343
- <span
344
- className="w-1.5 h-1.5 rounded-full shrink-0"
345
- style={{ backgroundColor: STATUS_DOT_HEX[t.status] || '#6b7280' }}
346
- />
347
- {t.from_name && <AliasAvatar alias={t.from_name} size={14} />}
348
- <span className="text-gray-300 shrink-0 max-w-[20%] truncate">{t.from_name || '?'}</span>
349
- <span className="text-gray-600">&rarr;</span>
350
- {t.to_name && <AliasAvatar alias={t.to_name} size={14} />}
351
- <span className="text-gray-300 shrink-0 max-w-[20%] truncate">{t.to_name || '?'}</span>
352
- <span className="text-gray-500 truncate flex-1" title={t.content || ''}>{previewContent(t.content).slice(0, 60)}</span>
353
- <span className={`shrink-0 px-1.5 py-0.5 rounded text-[10px] border ${
354
- STATUS_CHIP_CLASS[t.status] || 'text-gray-500 border-gray-700/30'
355
- }`}>{t.status}</span>
356
- </div>
357
- ))}
358
- </div>
359
- </section>
360
- )}
361
- </>}
124
+ {/* #217 S5 (less is more): Quick Navigation stat cards, the nav
125
+ rail, and Recent Activity are deleted. Every route they linked
126
+ to is one tap away in the bottom tab bar (mobile) or sidebar
127
+ (desktop), the headline numbers already live in the KPI cards
128
+ and the task summary line, and recent tasks live on /tasks.
129
+ Restore path: git revert this commit. */}
362
130
 
363
131
  {sessError && (
364
132
  <div className="bg-red-900/20 border border-red-800/40 text-red-300 px-4 py-3 rounded-lg mb-6 text-sm flex items-center justify-between" role="alert">
@@ -378,15 +146,21 @@ export default function Dashboard() {
378
146
  </div>
379
147
  )}
380
148
 
381
- {/* Mobile hint when topo hidden */}
382
- {!showTopo && sessions.length > 0 && (
383
- <div className="lg:hidden text-center text-xs text-gray-600 mb-4">
384
- Topology hidden on mobile for better readability
149
+ {showTopo && sessions.length > 0 && (
150
+ // #209 R41: mobile-only soft cap on the rendered TopoGraph.
151
+ // Default behaviour on desktop is unchanged (lg: drops the cap
152
+ // entirely). On phones the SVG card was free to claim ~600+ px
153
+ // of vertical real-estate, which on a 667-844 px viewport meant
154
+ // tapping "Show Topology" pushed the agent grid completely off
155
+ // screen. Capping to 70 vh with overflow-y-auto keeps the graph
156
+ // interactive (the SVG already does its own pan + zoom inside
157
+ // the viewport) while letting the page below stay reachable
158
+ // with a single ordinary scroll past the cap.
159
+ <div className="lg:max-h-none lg:overflow-visible max-h-[70vh] overflow-y-auto rounded-xl border border-transparent lg:border-0">
160
+ <TopoGraph sessions={sessions} sseSessions={sseSessions} renameSignal={renameSignal} />
385
161
  </div>
386
162
  )}
387
163
 
388
- {showTopo && sessions.length > 0 && <TopoGraph sessions={sessions} sseSessions={sseSessions} renameSignal={renameSignal} />}
389
-
390
164
  {sessions.length === 0 && !sessError ? (
391
165
  <EmptyState
392
166
  hint={sessHint}
@@ -426,12 +200,14 @@ export default function Dashboard() {
426
200
  className={`flex items-center gap-1.5 rounded-md px-2.5 py-1 text-xs transition-colors disabled:opacity-30 disabled:cursor-not-allowed ${
427
201
  agentFilter === c.key
428
202
  ? 'bg-cyan-500/10 text-cyan-300 border border-cyan-500/30'
429
- : 'text-gray-500 hover:text-gray-200 hover:bg-[#1a1a2a] border border-transparent'
203
+ : 'text-gray-500 hover:text-gray-200 hover:bg-[#1c1c1f] border border-transparent'
430
204
  }`}
431
205
  >
432
206
  {c.dot && <span aria-hidden className="inline-block w-1.5 h-1.5 rounded-full" style={{ backgroundColor: c.dot }} />}
207
+ {/* #217 D5: counts dropped — the KPI cards directly above
208
+ already carry 53/100/153; repeating them here doubled
209
+ every number on the first screen. */}
433
210
  <span>{c.label}</span>
434
- <span className={`text-[10px] tabular-nums ${agentFilter === c.key ? 'text-cyan-400' : 'text-gray-600'}`}>{counts[c.key]}</span>
435
211
  </button>
436
212
  ))}
437
213
  </div>
@@ -454,8 +230,6 @@ export default function Dashboard() {
454
230
  );
455
231
  })()}
456
232
 
457
- <InboxPanel messages={inbox} />
458
-
459
233
  {/* Round 111 (issue #82): dropped the license badge — "trial (12d
460
234
  left)" read like a paywall countdown on an open-source dashboard
461
235
  and Vincent flagged it as misleading more than once. The SSE /
@@ -470,9 +244,6 @@ export default function Dashboard() {
470
244
  )}
471
245
  </div>
472
246
 
473
- {/* Dispatch Panel */}
474
- {showDispatch && <DispatchPanel sessions={sessions} onClose={() => setShowDispatch(false)} />}
475
-
476
247
  {/* Command Center (multi-tab chat) */}
477
248
  {cmd.tabs.length > 0 && (
478
249
  <CommandCenter
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { useState, useEffect, useRef, useCallback } from 'react';
4
+ import { useCollapsibleSearch } from '@/app/components/CollapsibleSearch';
4
5
  import Link from 'next/link';
5
6
 
6
7
  interface LogLine {
@@ -63,6 +64,16 @@ export default function ServerLogsPage() {
63
64
  const [filterLevel, setFilterLevel] = useState<'all' | LogLine['level']>('all');
64
65
  const [search, setSearch] = useState('');
65
66
  const [autoRefresh, setAutoRefresh] = useState(true);
67
+ // #209 R35: adopt the shared CollapsibleSearch hook (R34) so the
68
+ // inline 全宽 search input collapses behind a magnifier circle in
69
+ // the toolbar — same WeChat-style affordance as /nodes /messages.
70
+ const searchCtl = useCollapsibleSearch({
71
+ value: search,
72
+ onChange: setSearch,
73
+ placeholder: '搜索关键字 (alias / task_id / error message)',
74
+ label: 'Search logs',
75
+ enabled: true,
76
+ });
66
77
  const lastTsRef = useRef<string>('');
67
78
 
68
79
  const fetchLogs = useCallback(async (initial = false) => {
@@ -116,10 +127,17 @@ export default function ServerLogsPage() {
116
127
  for (const l of logs) counts[l.level]++;
117
128
 
118
129
  return (
119
- <div className="p-6 max-w-[1600px] mx-auto">
130
+ // #209 R35: p-6 → p-4 sm:p-6 mobile-tighten (matches /tasks, /nodes,
131
+ // /messages, /overview convention). Saves 16 px of L/R padding on phones.
132
+ <div className="p-4 sm:p-6 max-w-[1600px] mx-auto">
120
133
  <div className="flex items-center justify-between mb-4 gap-3">
121
134
  <div className="flex items-center gap-3 min-w-0">
122
- <h1 className="text-2xl font-bold text-white">Server Logs</h1>
135
+ {/* #209 R35: lg:ml-0 ml-10 burger-clearance — without it the
136
+ fixed top-3 left-3 mobile hamburger sat right on top of the
137
+ "Se" of "Server Logs". Caught by playwright mobile shot. */}
138
+ {/* #217 D8: text-xl + nowrap on phones — at text-2xl the title
139
+ wrapped to two lines under the 4-control toolbar. */}
140
+ <h1 className="text-xl sm:text-2xl font-bold text-white lg:ml-0 ml-10 whitespace-nowrap">Server Logs</h1>
123
141
  {/* Round 86: dropped the {logs.length} header chip — r84 added
124
142
  `all <count>` to the filter strip just below, so this duplicated
125
143
  the value within 40px of itself. */}
@@ -158,9 +176,17 @@ export default function ServerLogsPage() {
158
176
  </svg>
159
177
  <span className="hidden sm:inline">Reload</span>
160
178
  </button>
179
+ {/* #209 R35: magnifier-toggle search (WeChat-style, via the
180
+ shared CollapsibleSearch hook). Lives at the tail of the
181
+ toolbar so it sits at the right edge of the header. */}
182
+ <searchCtl.Button />
161
183
  </div>
162
184
  </div>
163
185
 
186
+ {/* R35: collapsible search row — sits above the filter chip strip
187
+ so toggling it doesn't shift the chip layout. */}
188
+ <searchCtl.Row />
189
+
164
190
  {/* Round 95: flex-wrap + min-w-0 on the search wrapper so the
165
191
  search input drops below the chip strip on mobile instead of
166
192
  overflowing past the viewport. Desktop layout (single row)
@@ -183,7 +209,7 @@ export default function ServerLogsPage() {
183
209
  className={`px-2.5 py-1 rounded border flex items-center gap-1 disabled:opacity-30 disabled:cursor-not-allowed ${
184
210
  isActive
185
211
  ? 'bg-cyan-500/15 text-cyan-200 border-cyan-500/40'
186
- : 'bg-[#11111c] text-gray-400 border-[#2a2a4a] hover:bg-[#1a1a2a]'
212
+ : 'bg-[#161618] text-gray-400 border-[#26262b] hover:bg-[#1c1c1f]'
187
213
  }`}
188
214
  >
189
215
  <span>{lv}</span>
@@ -192,15 +218,15 @@ export default function ServerLogsPage() {
192
218
  );
193
219
  })}
194
220
  </div>
195
- <input
196
- value={search}
197
- onChange={e => setSearch(e.target.value)}
198
- placeholder="搜索关键字 (alias / task_id / error message)"
199
- className="flex-1 min-w-[140px] basis-full sm:basis-0 px-3 py-1.5 text-xs bg-[#11111c] border border-[#2a2a4a] rounded text-gray-200 focus:outline-none focus:border-cyan-500/40"
200
- />
201
- <span className="text-[10px] text-gray-600">
202
- {filtered.length} / {logs.length}
203
- </span>
221
+ {/* #217 D8 (same rule as the D6 /tasks chip): the counter only
222
+ renders when it carries unique info — a filter or search is
223
+ actually narrowing the list. "500 / 500" duplicated the
224
+ `all 500` chip 20px to its left. */}
225
+ {filtered.length < logs.length && (
226
+ <span className="text-[10px] text-gray-600 ml-auto tabular-nums">
227
+ {filtered.length} / {logs.length}
228
+ </span>
229
+ )}
204
230
  </div>
205
231
 
206
232
  {error && (() => {
@@ -235,7 +261,7 @@ export default function ServerLogsPage() {
235
261
  );
236
262
  })()}
237
263
 
238
- <div className="rounded border border-[#1a1a2a] bg-[#050510] font-mono text-[11px] leading-relaxed overflow-hidden">
264
+ <div className="rounded border border-[#1c1c1f] bg-[#060607] font-mono text-[11px] leading-relaxed overflow-hidden">
239
265
  {filtered.length === 0 ? (
240
266
  <div className="p-8 text-center text-gray-600">
241
267
  {error ? '加载失败' : logs.length === 0 ? '加载中...' : '没有匹配的日志'}
@@ -243,7 +269,7 @@ export default function ServerLogsPage() {
243
269
  ) : (
244
270
  <div className="divide-y divide-[#0d0d18] max-h-[calc(100vh-260px)] overflow-y-auto">
245
271
  {filtered.map((l, i) => (
246
- <div key={`${l.ts}-${i}`} className="relative pl-3 pr-3 py-1 hover:bg-[#0a0a14] flex gap-3">
272
+ <div key={`${l.ts}-${i}`} className="relative pl-3 pr-3 py-1 hover:bg-[#0e0e10] flex gap-3">
247
273
  {/* Round 32: 2px left rail keyed to level. Makes warn/error
248
274
  spike visible in a wall of `log` lines without users having
249
275
  to read the level chip on every row. */}
@@ -4,24 +4,45 @@ import { ServersPanel } from '../components/ServersDrawer';
4
4
 
5
5
  export default function ServersPage() {
6
6
  return (
7
- <main className="min-h-screen bg-[#0a0a1a] px-4 py-5 text-gray-100 sm:px-6 lg:px-8">
7
+ <main className="min-h-screen bg-[#0b0b0d] px-4 py-5 text-gray-100 sm:px-6 lg:px-8">
8
8
  <div className="mx-auto max-w-5xl space-y-5">
9
- <header className="rounded-2xl border border-[#2a2a4a] bg-[#111128] p-5 shadow-lg shadow-black/20">
10
- <div className="flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between">
11
- <div>
12
- <p className="text-[11px] uppercase tracking-[0.18em] text-cyan-300/70">Infrastructure</p>
13
- <h1 className="mt-2 text-2xl font-semibold text-white">Servers</h1>
14
- <p className="mt-2 max-w-2xl text-sm leading-6 text-gray-400">
15
- Host-level health, disk, memory, CPU history, and agent rollups from CommHub telemetry.
16
- </p>
9
+ {/* #209 R37: header card compressed for mobile. Original layout
10
+ stacked 4 things vertically on phones (INFRASTRUCTURE eyebrow,
11
+ big h1, 3-line description, full-width "live" chip) eating
12
+ ~50% of the iPhone viewport before any server card appeared.
13
+ New shape:
14
+ row 1: h1 "Servers" + tiny live chip (inline on every width)
15
+ row 2: optional desc line, single-truncate on mobile so it
16
+ fits without wrapping; full text via title= on hover.
17
+ eyebrow: kept but inlined with h1 as small uppercase prefix
18
+ (sm: up) — drops out on phones for density.
19
+ p-5 → p-4 sm:p-5 also tightens the inner padding.
20
+ Zero feature removed; the eyebrow + desc still render where
21
+ there is room. */}
22
+ <header className="rounded-2xl border border-[#26262b] bg-[#161618] p-4 sm:p-5 shadow-lg shadow-black/20">
23
+ <div className="flex items-center justify-between gap-3 lg:ml-0 ml-10">
24
+ <div className="flex items-baseline gap-2 min-w-0">
25
+ <span className="hidden sm:inline text-[11px] uppercase tracking-[0.18em] text-cyan-300/70 shrink-0">
26
+ Infrastructure
27
+ </span>
28
+ <span className="hidden sm:inline text-gray-700">·</span>
29
+ <h1 className="text-xl sm:text-2xl font-semibold text-white truncate">Servers</h1>
17
30
  </div>
18
- <div className="rounded-xl border border-cyan-500/20 bg-cyan-500/10 px-3 py-2 text-xs font-mono text-cyan-200">
19
- live · refreshes every 5s
31
+ <div className="shrink-0 rounded-full border border-cyan-500/20 bg-cyan-500/10 px-2.5 py-1 text-[11px] font-mono text-cyan-200 inline-flex items-center gap-1.5">
32
+ <span aria-hidden className="inline-block w-1.5 h-1.5 rounded-full bg-cyan-400 animate-pulse" />
33
+ <span className="hidden sm:inline">live · refreshes every 5s</span>
34
+ <span className="sm:hidden">live</span>
20
35
  </div>
21
36
  </div>
37
+ <p
38
+ className="mt-2 max-w-2xl text-xs sm:text-sm leading-snug sm:leading-6 text-gray-400 truncate sm:whitespace-normal lg:ml-0 ml-10"
39
+ title="Host-level health, disk, memory, CPU history, and agent rollups from CommHub telemetry."
40
+ >
41
+ Host-level health, disk, memory, CPU history, and agent rollups from CommHub telemetry.
42
+ </p>
22
43
  </header>
23
44
 
24
- <section className="rounded-2xl border border-[#2a2a4a] bg-[#111128] p-3 shadow-lg shadow-black/20">
45
+ <section className="rounded-2xl border border-[#26262b] bg-[#161618] p-3 shadow-lg shadow-black/20">
25
46
  <ServersPanel className="max-h-none overflow-visible" />
26
47
  </section>
27
48
  </div>