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

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/01le1j4ie1ia2.js +1 -0
  242. package/.next/static/chunks/039na2e9_1jis.js +1 -0
  243. package/.next/static/chunks/049vx3qljs1tt.js +1 -0
  244. package/.next/static/chunks/04cf.98_cyxen.js +1 -0
  245. package/.next/static/chunks/066jf0nk75nic.css +2 -0
  246. package/.next/static/chunks/071_tudui5~lp.js +4 -0
  247. package/.next/static/chunks/0_bn~gcrgo.4n.js +1 -0
  248. package/.next/static/chunks/0g4d-_fi-d9hg.js +1 -0
  249. package/.next/static/chunks/0scww97p6z5z..css +1 -0
  250. package/.next/static/chunks/0t4lpxu4ny9-3.js +1 -0
  251. package/.next/static/chunks/0vgrwqsgja19l.js +1 -0
  252. package/.next/static/chunks/0wz0122ym_gr3.js +1 -0
  253. package/.next/static/chunks/0y5gol09tlu63.js +1 -0
  254. package/.next/static/chunks/143g3n8za083f.js +7 -0
  255. package/.next/static/chunks/149a4l50_3vw-.js +7 -0
  256. package/.next/static/chunks/152_p6jt7txp6.js +1 -0
  257. package/.next/static/chunks/15iu5i37682id.js +1 -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 +36 -20
  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 +69 -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 +45 -270
  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 → sGM_ABZO60VSkgAa_q0Sz}/_buildManifest.js +0 -0
  375. /package/.next/static/{ZeU15JAI2Ap6fZ675phhF → sGM_ABZO60VSkgAa_q0Sz}/_clientMiddlewareManifest.js +0 -0
  376. /package/.next/static/{ZeU15JAI2Ap6fZ675phhF → sGM_ABZO60VSkgAa_q0Sz}/_ssgManifest.js +0 -0
@@ -4,29 +4,35 @@ interface StatsBarProps {
4
4
  online: number;
5
5
  working: number;
6
6
  total: number;
7
- version: string;
8
- uptime: string;
9
7
  }
10
8
 
11
- export function StatsBar({ online, working, total, version, uptime }: StatsBarProps) {
9
+ export function StatsBar({ online, working, total }: StatsBarProps) {
12
10
  const onlinePercent = total > 0 ? Math.round((online / total) * 100) : 0;
13
11
  const fleetEmpty = total === 0;
14
12
 
13
+ // #209 R29 (mobile vertical rhythm — goal "大幅提升移动端体验"):
14
+ // populated branch previously left mb-8 (32 px) below the 4-card grid,
15
+ // the single biggest gap on the Overview page. Drop to mb-4 (16 px)
16
+ // on phones, restore mb-8 from sm: up. Pairs with R28's section-gap
17
+ // tighten — together they reclaim ~48 px of pure scroll waste before
18
+ // the agent grid. The empty-fleet branch already used mb-4 since R72,
19
+ // so this only touches the populated case.
15
20
  return (
16
- <div className={fleetEmpty ? 'mb-4' : 'mb-8'}>
17
- {/* Title row */}
18
- <div className="flex flex-wrap items-center gap-3 mb-4">
19
- <h1 className="text-2xl font-bold text-white tracking-tight">Agent Network</h1>
20
- <span className="text-xs text-gray-500">
21
- CommHub {version} &middot; {uptime}
22
- </span>
21
+ <div className={fleetEmpty ? 'mb-4' : 'mb-4 sm:mb-8'}>
22
+ {/* Title row. #217 S3 dropped the version/uptime subtitle (lives in
23
+ Settings CommHub Connection). S9 (Vincent tg 613 "没居中"):
24
+ WeChat-style centered title on phones — centering also clears
25
+ the fixed hamburger symmetrically, replacing the old ml-10
26
+ indent that read as misalignment. Left-aligned from lg: up. */}
27
+ <div className="mb-4">
28
+ <h1 className="text-2xl font-bold text-white tracking-tight text-center lg:text-left">Agent Network</h1>
23
29
  </div>
24
30
 
25
31
  {fleetEmpty ? (
26
32
  /* Round 72: thin status strip replaces the 4-card grid when fleet
27
33
  is empty. Saves ~280px on mobile (CTA y=650 → ~370) and keeps
28
34
  the same data visible in a single inline row. */
29
- <div className="anet-stat-strip flex flex-wrap items-center gap-x-4 gap-y-1.5 text-xs text-gray-500 border-t border-b border-[#2a2a4a] py-2">
35
+ <div className="anet-stat-strip flex flex-wrap items-center gap-x-4 gap-y-1.5 text-xs text-gray-500 border-t border-b border-[#26262b] py-2">
30
36
  <span className="inline-flex items-center gap-1.5">
31
37
  <span aria-hidden className="inline-block w-1.5 h-1.5 rounded-full bg-gray-600" />
32
38
  <span className="text-gray-300 tabular-nums">0</span> online
@@ -43,63 +49,84 @@ export function StatsBar({ online, working, total, version, uptime }: StatsBarPr
43
49
  </span>
44
50
  </div>
45
51
  ) : (
46
- /* Populated state — full 4-card grid as before */
47
- <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
52
+ <>
53
+ {/* #217 M1 (Vincent: "再简洁点你自己理解一下"): on phones the
54
+ populated state reuses the round-72 thin strip instead of
55
+ the card grid — one quiet line of numbers, ~70px reclaimed.
56
+ Cards return from sm: up where they have room to breathe. */}
57
+ <div className="sm:hidden anet-stat-strip flex flex-wrap items-center gap-x-4 gap-y-1.5 text-xs text-gray-500 border-t border-b border-[#26262b] py-2">
58
+ <span className="inline-flex items-center gap-1.5">
59
+ <span aria-hidden className="inline-block w-1.5 h-1.5 rounded-full bg-green-400" />
60
+ <span className="text-gray-200 tabular-nums">{online}</span> online
61
+ </span>
62
+ {working > 0 && (
63
+ <>
64
+ <span className="text-gray-700">·</span>
65
+ <span className="inline-flex items-center gap-1.5">
66
+ <span aria-hidden className="inline-block w-1.5 h-1.5 rounded-full bg-green-400 anet-brand-pulse" />
67
+ <span className="text-gray-200 tabular-nums">{working}</span> working
68
+ </span>
69
+ </>
70
+ )}
71
+ <span className="text-gray-700">·</span>
72
+ <span className="inline-flex items-center gap-1.5">
73
+ <span aria-hidden className="inline-block w-1.5 h-1.5 rounded-full bg-gray-600" />
74
+ <span className="text-gray-200 tabular-nums">{total - online}</span> offline
75
+ </span>
76
+ <span className="text-gray-700">·</span>
77
+ <span className="inline-flex items-center gap-1.5">
78
+ <span className="text-gray-200 tabular-nums">{total}</span> total
79
+ </span>
80
+ </div>
81
+ {/* Populated state, sm: up. #217 S2 (less is more): the Working
82
+ card only earns its grid cell when something is actually
83
+ working. */}
84
+ <div className={`hidden sm:grid gap-3 ${working > 0 ? 'sm:grid-cols-4' : 'sm:grid-cols-3'}`}>
48
85
  <StatCard
49
86
  value={online}
50
87
  label="Online"
51
88
  sub={`${onlinePercent}% of fleet`}
52
89
  color="text-green-400"
53
- accent="from-green-500/20 to-green-500/0"
54
- border="border-green-500/15"
55
- />
56
- <StatCard
57
- value={working}
58
- label="Working"
59
- sub={online > 0 ? `${Math.round((working / online) * 100)}% utilization` : '--'}
60
- color="text-cyan-400"
61
- accent="from-cyan-500/20 to-cyan-500/0"
62
- border="border-cyan-500/15"
63
90
  />
91
+ {working > 0 && (
92
+ <StatCard
93
+ value={working}
94
+ label="Working"
95
+ sub={online > 0 ? `${Math.round((working / online) * 100)}% utilization` : '--'}
96
+ color="text-cyan-400"
97
+ />
98
+ )}
64
99
  <StatCard
65
100
  value={total - online}
66
101
  label="Offline"
67
102
  sub={total - online === 0 ? 'All systems go' : `${total - online} disconnected`}
68
103
  color="text-gray-400"
69
- accent="from-gray-500/10 to-gray-500/0"
70
- border="border-gray-500/15"
71
104
  />
72
105
  <StatCard
73
106
  value={total}
74
107
  label="Total"
75
108
  sub="Registered nodes"
76
109
  color="text-white"
77
- accent="from-blue-500/15 to-blue-500/0"
78
- border="border-blue-500/15"
79
110
  />
80
111
  </div>
112
+ </>
81
113
  )}
82
114
  </div>
83
115
  );
84
116
  }
85
117
 
86
- function StatCard({ value, label, sub, color, accent, border }: {
87
- value: number; label: string; sub: string; color: string; accent: string; border: string;
118
+ function StatCard({ value, label, sub, color }: {
119
+ value: number; label: string; sub: string; color: string;
88
120
  }) {
89
- // Extract the color family (green/cyan/gray/blue/white) from `color` prop
90
- // so the light-theme top-strip CSS can pick the right accent.
91
- const accentKey = color.replace('text-', '').split('-')[0];
121
+ // #217 D2 (OpenWebUI-style color restraint): the per-color gradient
122
+ // wash + tinted borders made the KPI row read as four neon billboards.
123
+ // Surfaces are now neutral (shared border + bg); color survives only
124
+ // on the number itself. Mobile density values are #209 R39.
92
125
  return (
93
- <div
94
- data-anet-stat-card={accentKey}
95
- className={`anet-stat-card relative overflow-hidden rounded-xl border ${border} bg-[#111128] px-4 py-3 transition-all`}
96
- >
97
- <div className={`absolute inset-0 bg-gradient-to-br ${accent} pointer-events-none`} />
98
- <div className="relative">
99
- <div className={`text-3xl font-bold ${color} tabular-nums leading-tight`}>{value}</div>
100
- <div className="text-sm text-gray-300 mt-0.5">{label}</div>
101
- <div className="text-xs text-gray-600 mt-1">{sub}</div>
102
- </div>
126
+ <div className="anet-stat-card rounded-xl border border-[#26262b] bg-[#161618] px-3 sm:px-4 py-2.5 sm:py-3 transition-all">
127
+ <div className={`text-2xl sm:text-3xl font-bold ${color} tabular-nums leading-tight`}>{value}</div>
128
+ <div className="text-xs sm:text-sm text-gray-300 mt-0.5">{label}</div>
129
+ <div className="text-[10px] sm:text-xs text-gray-600 mt-1">{sub}</div>
103
130
  </div>
104
131
  );
105
132
  }
@@ -483,7 +483,14 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
483
483
  const chatContent = (
484
484
  <>
485
485
  {/* Messages area */}
486
- <div className="flex-1 overflow-y-auto px-3 py-3 sm:px-4 sm:py-4 space-y-3 sm:space-y-4">
486
+ {/* R12 of #190 mobile polish: the chat scroll surface used
487
+ space-y-3 between task+reply pairs at mobile = 12 px, which
488
+ in a long thread (the panel's bread-and-butter use case)
489
+ adds up to a significant scroll length. Drop to space-y-2 at
490
+ mobile and the per-pair grouping (line 540) from space-y-2
491
+ to space-y-1.5 so messages read denser without losing the
492
+ speaker-turn rhythm. Desktop unchanged at sm: and up. */}
493
+ <div className="flex-1 overflow-y-auto px-3 py-3 sm:px-4 sm:py-4 space-y-2 sm:space-y-4">
487
494
  {!historyLoaded && (
488
495
  <div className="flex justify-center py-8">
489
496
  <div className="w-5 h-5 border-2 border-cyan-500/30 border-t-cyan-500 rounded-full animate-spin" />
@@ -537,7 +544,7 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
537
544
  );
538
545
  }
539
546
  return (
540
- <div key={`${m.task_id}:task`} className="space-y-2">
547
+ <div key={`${m.task_id}:task`} className="space-y-1.5 sm:space-y-2">
541
548
  {/* Outgoing task — labeled with origin so peer-forwarded tasks are obvious */}
542
549
  <div className="flex justify-end">
543
550
  <div className="max-w-[92%] sm:max-w-[85%] bg-cyan-500/8 border border-cyan-500/15 rounded-2xl rounded-br-md px-3 py-2.5 sm:px-4 shadow-sm">
@@ -626,8 +633,11 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
626
633
  </select>
627
634
  </div>
628
635
  </div>
629
- <button onClick={send} disabled={sending || (!input.trim() && attachedFiles.length === 0)}
630
- className="p-2.5 bg-cyan-600 hover:bg-cyan-500 disabled:bg-[var(--border)] disabled:text-[var(--fg-dim)] text-[var(--fg)] rounded-xl transition-all shrink-0 active:scale-95">
636
+ {/* R17 of #190: send button was p-2.5 + w-5 icon = ~40 x 40
637
+ hit zone, 4 px short of the iOS 44 px guideline on
638
+ the short axis. Bump to inline-flex + min-h/w 44. */}
639
+ <button onClick={send} aria-label="Send message" disabled={sending || (!input.trim() && attachedFiles.length === 0)}
640
+ className="inline-flex min-h-[44px] min-w-[44px] items-center justify-center bg-cyan-600 hover:bg-cyan-500 disabled:bg-[var(--border)] disabled:text-[var(--fg-dim)] text-[var(--fg)] rounded-xl transition-all shrink-0 active:scale-95">
631
641
  {sending ? (
632
642
  <div className="w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin" />
633
643
  ) : (
@@ -673,7 +683,11 @@ export function TaskChatPanel({ alias, onClose, inline, availableNodes }: TaskCh
673
683
  <div className="text-[10px] text-[var(--fg-muted)]">{pollingIds.size > 0 ? 'Processing...' : 'Ready'}</div>
674
684
  </div>
675
685
  </div>
676
- <button onClick={onClose} className="text-[var(--fg-muted)] hover:text-[var(--fg)] p-1.5 rounded-lg hover:bg-[var(--bg-elevated)]">
686
+ {/* R16 of #190: was p-1.5 + w-5 h-5 svg = ~32 px tap target.
687
+ The chat panel close is high-frequency on mobile (user
688
+ dismisses to scroll the underlying page); bump to a
689
+ uniform 44 x 44 hit zone via inline-flex + min-h/w. */}
690
+ <button onClick={onClose} aria-label="Close chat" className="inline-flex min-h-[44px] min-w-[44px] items-center justify-center text-[var(--fg-muted)] hover:text-[var(--fg)] rounded-lg hover:bg-[var(--bg-elevated)]">
677
691
  <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
678
692
  <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
679
693
  </svg>
@@ -81,14 +81,16 @@ export function TaskDrawer({ taskId, onClose }: TaskDrawerProps) {
81
81
  return (
82
82
  <>
83
83
  <div className="fixed inset-0 bg-black/30 z-40 anet-fade-in" onClick={onClose} />
84
- <div className="fixed top-0 right-0 h-[100dvh] w-full lg:w-[500px] bg-[#0a0a1a] border-l border-[#2a2a4a] z-50 flex flex-col shadow-2xl shadow-black/60 overflow-y-auto animate-slide-in">
84
+ <div className="fixed top-0 right-0 h-[100dvh] w-full lg:w-[500px] bg-[#0b0b0d] border-l border-[#26262b] z-50 flex flex-col shadow-2xl shadow-black/60 overflow-y-auto animate-slide-in">
85
85
  {/* Header */}
86
- <div className="flex items-center justify-between px-5 py-4 border-b border-[#2a2a4a] bg-[#0d0d1a] sticky top-0">
86
+ <div className="flex items-center justify-between px-5 py-4 border-b border-[#26262b] bg-[#111113] sticky top-0">
87
87
  <div>
88
88
  <div className="text-sm font-semibold text-white">Task Detail</div>
89
89
  <div className="text-[10px] text-gray-500 mt-0.5">{taskId.slice(0, 16)}...</div>
90
90
  </div>
91
- <button onClick={onClose} className="text-gray-500 hover:text-white p-1.5 rounded-lg hover:bg-[#1a1a2a]">
91
+ {/* R16 of #190: same chat-panel close pattern — was ~32 px
92
+ tap target; lift to a uniform 44 x 44 hit zone. */}
93
+ <button onClick={onClose} aria-label="Close task drawer" className="inline-flex min-h-[44px] min-w-[44px] items-center justify-center text-gray-500 hover:text-white rounded-lg hover:bg-[#1c1c1f]">
92
94
  <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
93
95
  <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
94
96
  </svg>
@@ -127,7 +129,7 @@ export function TaskDrawer({ taskId, onClose }: TaskDrawerProps) {
127
129
 
128
130
  {/* Timeline — round 36 polish: relative timestamps, current-step
129
131
  pulse if task is still in flight, full ISO in title=. */}
130
- <div className="bg-[#111128] border border-[#2a2a4a] rounded-xl p-4">
132
+ <div className="bg-[#161618] border border-[#26262b] rounded-xl p-4">
131
133
  <div className="flex items-center justify-between mb-3">
132
134
  <div className="text-xs text-gray-500 uppercase tracking-wide">Timeline</div>
133
135
  {duration !== null && (
@@ -180,14 +182,14 @@ export function TaskDrawer({ taskId, onClose }: TaskDrawerProps) {
180
182
  </div>
181
183
 
182
184
  {/* Content */}
183
- <div className="bg-[#111128] border border-[#2a2a4a] rounded-xl p-4">
185
+ <div className="bg-[#161618] border border-[#26262b] rounded-xl p-4">
184
186
  <div className="text-xs text-gray-500 uppercase mb-2">Input</div>
185
187
  <div className="text-sm text-gray-300 whitespace-pre-wrap">{task.content || '--'}</div>
186
188
  </div>
187
189
 
188
190
  {/* Result */}
189
191
  {task.result && (
190
- <div className="bg-[#111128] border border-[#2a2a4a] rounded-xl p-4">
192
+ <div className="bg-[#161618] border border-[#26262b] rounded-xl p-4">
191
193
  <div className="text-xs text-gray-500 uppercase mb-2">Output</div>
192
194
  <div className="text-sm text-gray-300 whitespace-pre-wrap max-h-64 overflow-y-auto">{task.result}</div>
193
195
  </div>
@@ -195,7 +197,7 @@ export function TaskDrawer({ taskId, onClose }: TaskDrawerProps) {
195
197
 
196
198
  {/* Events */}
197
199
  {events.length > 0 && (
198
- <div className="bg-[#111128] border border-[#2a2a4a] rounded-xl p-4">
200
+ <div className="bg-[#161618] border border-[#26262b] rounded-xl p-4">
199
201
  <div className="text-xs text-gray-500 uppercase mb-2">Events ({events.length})</div>
200
202
  <div className="space-y-1.5 max-h-40 overflow-y-auto">
201
203
  {events.map(e => (
@@ -1,89 +1,25 @@
1
1
  'use client';
2
2
 
3
- import { useEffect, useState } from 'react';
3
+ import { useEffect } from 'react';
4
4
 
5
- const THEMES = [
6
- { id: 'cyber', label: 'Cyber', emoji: '🌃', desc: '默认深色' },
7
- { id: 'light', label: 'Light', emoji: '☀️', desc: '浅色简洁' },
8
- { id: 'mint', label: 'Mint', emoji: '🌿', desc: '薄荷绿' },
9
- { id: 'sunset', label: 'Sunset', emoji: '🌅', desc: '暖色橙紫' },
10
- ] as const;
5
+ // #217 S6 — two verified themes: cyber (dark, default) and light (white,
6
+ // Vincent-requested, tokens restored from pre-R8 history). The issue #4
7
+ // cleanup locked this to cyber because the old light/mint/sunset themes
8
+ // were unverified; light is now owned by Settings → Appearance, so the
9
+ // provider honors the persisted choice again. Anything else in storage
10
+ // (old mint/sunset values) falls back to cyber.
11
11
 
12
- type ThemeId = typeof THEMES[number]['id'];
13
- const THEME_KEY = 'anet-theme';
14
-
15
- function applyTheme(theme: ThemeId) {
16
- if (typeof document !== 'undefined') {
17
- document.documentElement.setAttribute('data-theme', theme);
18
- }
19
- }
12
+ const THEMES = new Set(['cyber', 'light']);
20
13
 
21
14
  export function ThemeProvider({ children }: { children: React.ReactNode }) {
22
- // Apply persisted theme on first render so we don't flash dark before
23
- // user-selected light. Initial value comes from cookie/localStorage.
24
15
  useEffect(() => {
25
- const stored = (localStorage.getItem(THEME_KEY) as ThemeId) || 'cyber';
26
- applyTheme(stored);
16
+ if (typeof document === 'undefined') return;
17
+ let t = 'cyber';
18
+ try {
19
+ const saved = localStorage.getItem('anet-theme');
20
+ if (saved && THEMES.has(saved)) t = saved;
21
+ } catch {}
22
+ document.documentElement.setAttribute('data-theme', t);
27
23
  }, []);
28
24
  return <>{children}</>;
29
25
  }
30
-
31
- export function ThemeSwitcher({ compact = false }: { compact?: boolean }) {
32
- const [theme, setTheme] = useState<ThemeId>('cyber');
33
- const [open, setOpen] = useState(false);
34
-
35
- useEffect(() => {
36
- const stored = (localStorage.getItem(THEME_KEY) as ThemeId) || 'cyber';
37
- setTheme(stored);
38
- applyTheme(stored);
39
- }, []);
40
-
41
- function pick(next: ThemeId) {
42
- setTheme(next);
43
- localStorage.setItem(THEME_KEY, next);
44
- applyTheme(next);
45
- setOpen(false);
46
- }
47
-
48
- const current = THEMES.find(t => t.id === theme) || THEMES[0];
49
-
50
- return (
51
- <div className="relative">
52
- <button
53
- aria-label="切换主题"
54
- onClick={() => setOpen(!open)}
55
- className="px-2.5 py-1.5 rounded-md text-xs flex items-center gap-1.5 hover:opacity-80 transition-opacity"
56
- style={{ background: 'var(--bg-elevated)', color: 'var(--fg)', border: '1px solid var(--border)' }}
57
- >
58
- <span aria-hidden>{current.emoji}</span>
59
- {!compact && <span>{current.label}</span>}
60
- </button>
61
- {open && (
62
- <>
63
- <div className="fixed inset-0 z-40" onClick={() => setOpen(false)} />
64
- <div
65
- className="absolute right-0 top-full mt-1 z-50 rounded-md min-w-[160px] py-1 shadow-lg"
66
- style={{ background: 'var(--bg-secondary)', border: '1px solid var(--border)' }}
67
- >
68
- {THEMES.map(t => (
69
- <button
70
- key={t.id}
71
- onClick={() => pick(t.id)}
72
- className="w-full px-3 py-2 text-left text-xs flex items-center gap-2 hover:opacity-80"
73
- style={{
74
- background: t.id === theme ? 'var(--bg-elevated)' : 'transparent',
75
- color: 'var(--fg)',
76
- }}
77
- >
78
- <span aria-hidden>{t.emoji}</span>
79
- <span className="flex-1">{t.label}</span>
80
- <span style={{ color: 'var(--fg-dim)' }} className="text-[10px]">{t.desc}</span>
81
- {t.id === theme && <span style={{ color: 'var(--accent)' }}>•</span>}
82
- </button>
83
- ))}
84
- </div>
85
- </>
86
- )}
87
- </div>
88
- );
89
- }
@@ -422,11 +422,11 @@ interface Palette {
422
422
  }
423
423
 
424
424
  const DARK_PALETTE: Palette = {
425
- panelStops: ['#0b1220', '#080814', '#101018'],
425
+ panelStops: ['#0b1220', '#0a0a0c', '#101018'],
426
426
  radarStops: [
427
427
  { color: '#22d3ee', opacity: 0.18 },
428
428
  { color: '#22c55e', opacity: 0.045 },
429
- { color: '#020617', opacity: 0 },
429
+ { color: '#060608', opacity: 0 },
430
430
  ],
431
431
  arrowFill: '#67e8f9',
432
432
  ringStroke: '#164e63',
@@ -434,14 +434,14 @@ const DARK_PALETTE: Palette = {
434
434
  flowEdge: '#67e8f9',
435
435
  flowPath: '#e0f2fe',
436
436
  flowParticle: '#fef08a',
437
- nodeFill: { online: '#020617', offline: '#080814' },
438
- labelBox: { fill: '#020617', stroke: '#1f2937' },
439
- legendBox: { fill: '#020617', stroke: '#1f2937' },
437
+ nodeFill: { online: '#060608', offline: '#0a0a0c' },
438
+ labelBox: { fill: '#060608', stroke: '#1f2937' },
439
+ legendBox: { fill: '#060608', stroke: '#1f2937' },
440
440
  legendText: '#94a3b8',
441
441
  legendHeadline: '#e5e7eb',
442
442
  legendAccent: '#67e8f9',
443
- containerBg: '#080814',
444
- containerBorder: '#2a2a4a',
443
+ containerBg: '#0a0a0c',
444
+ containerBorder: '#26262b',
445
445
  topRailGradient: 'from-transparent via-cyan-400/70 to-transparent',
446
446
  };
447
447
 
@@ -462,7 +462,7 @@ const LIGHT_PALETTE: Palette = {
462
462
  labelBox: { fill: '#ffffff', stroke: '#e2e8f0' },
463
463
  legendBox: { fill: '#ffffff', stroke: '#e2e8f0' },
464
464
  legendText: '#475569',
465
- legendHeadline: '#0f172a',
465
+ legendHeadline: '#18181b',
466
466
  legendAccent: '#0d9488',
467
467
  containerBg: '#ffffff',
468
468
  containerBorder: '#e3e6eb',
@@ -2059,8 +2059,18 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
2059
2059
  }
2060
2060
  };
2061
2061
 
2062
+ // #209 R27 (Vincent msg 545+547 — TopoGraph "中间太小,往左右扩"):
2063
+ // drop the unique `max-w-6xl mx-auto` cap. Every other section on
2064
+ // the Overview page (KPI cards, agent grid, Recent Activity, etc.)
2065
+ // is full-width; only TopoGraph was self-limiting to 1152 px,
2066
+ // leaving ~70 px slack on each side of the typical (~1290 px main
2067
+ // area) viewport. Now matches the rest of the page — the inner SVG
2068
+ // layout is already resize-aware (ring/grid/tree all re-fit on
2069
+ // container width change), so widening the card naturally spreads
2070
+ // the node cluster. Less is more: one fewer arbitrary constraint.
2071
+ // Picked option A over a 1536 px cap (option B) per Vincent msg 547.
2062
2072
  return (
2063
- <section className="w-full max-w-6xl mx-auto mb-8">
2073
+ <section className="w-full mb-8">
2064
2074
  {/* Round 299 / Loop: title block bottom margin mb-3 (12px) →
2065
2075
  mb-4 (16px). After R298 tightened the title-block internal
2066
2076
  gap (12→10px) packing brand-logo + kicker + h2 into a more
@@ -2663,7 +2673,7 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
2663
2673
  wrapper + Grid button's internal divider used hardcoded
2664
2674
  `border-gray-500/25` (pale gray, fixed in both themes)
2665
2675
  while the bottom-right chrome strip (nodeSize, zoom)
2666
- used pal.containerBorder (cyber #2a2a4a dark indigo ↔
2676
+ used pal.containerBorder (cyber #26262b dark indigo ↔
2667
2677
  light #e3e6eb pale gray). Visible mismatch in cyber
2668
2678
  theme: Layout toggle border read as pale gray while
2669
2679
  chrome strip borders read as darker indigo — two
@@ -4942,7 +4952,7 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
4942
4952
  /* Round 254 / Loop: top-level TopoGraph wrapper gains theme-
4943
4953
  toggle transition. This is the BIGGEST theme-driven surface
4944
4954
  on the dashboard by pixel area — pal.containerBg fills the
4945
- entire visible canvas area (cyber #080814 ↔ light #ffffff),
4955
+ entire visible canvas area (cyber #0a0a0c ↔ light #ffffff),
4946
4956
  and pal.containerBorder rims it. Pre-R254 every inner
4947
4957
  element eased through theme but the outer wrapper hard-cut,
4948
4958
  visually anchoring the snap. R253 declared
@@ -5860,7 +5870,7 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
5860
5870
  <filter id="topo-groupbox-lift" x="-10%" y="-10%" width="120%" height="120%">
5861
5871
  <feDropShadow
5862
5872
  dx="0" dy="3" stdDeviation="4"
5863
- floodColor={isLight ? '#0f172a' : '#000000'}
5873
+ floodColor={isLight ? '#18181b' : '#000000'}
5864
5874
  floodOpacity={isLight ? 0.18 : 0.55}
5865
5875
  />
5866
5876
  </filter>
@@ -7035,7 +7045,7 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
7035
7045
  data-group-box-rx exposes the resolved value. */
7036
7046
  rx={isPinned ? '16' : '14'}
7037
7047
  data-group-box-rx={isPinned ? '16' : '14'}
7038
- fill={isLight ? '#0f172a' : '#a5b4fc'}
7048
+ fill={isLight ? '#18181b' : '#a5b4fc'}
7039
7049
  // R68: 3-tier opacity + stroke ladder.
7040
7050
  // pinned → fill 0.08 / 0.13, stroke 3 px (locked)
7041
7051
  // hovered → fill 0.05 / 0.09, stroke 2 px (inspecting)
@@ -7248,7 +7258,7 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
7248
7258
  : undefined,
7249
7259
  /* Round 248 / Loop: append fill 200ms ease-out to
7250
7260
  the existing R66 transition list. Pre-R248 the
7251
- rect's fill (isLight ? '#0f172a' (slate-900) :
7261
+ rect's fill (isLight ? '#18181b' (slate-900) :
7252
7262
  '#a5b4fc' (indigo-300)) snapped on theme toggle
7253
7263
  while stroke / fill-opacity / filter all eased.
7254
7264
  Closes the last theme-toggle snap on the group
@@ -8786,7 +8796,7 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
8786
8796
  r 180ms (R164 hover lift)
8787
8797
  stroke 300ms (R188 hot/pinned colour flip)
8788
8798
  stroke-width 300ms (R188 hot/pinned width flip)
8789
- fill (pal.legendBox.fill: cyber #020617 ↔ light
8799
+ fill (pal.legendBox.fill: cyber #060608 ↔ light
8790
8800
  #ffffff) and opacity (cyber 0.82 ↔ light 0.95)
8791
8801
  were theme-driven but missed from the list —
8792
8802
  the badge chrome snapped on theme switch while
@@ -11304,7 +11314,7 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
11304
11314
  gap so offline halos read more confidently as
11305
11315
  present-but-stale anchors. Cyber theme stays at
11306
11316
  R407's 0.30 (cyber backdrop is dark; the cyber
11307
- offline halo against #080814 contains a stronger
11317
+ offline halo against #0a0a0c contains a stronger
11308
11318
  contrast envelope than light, so doesn't need
11309
11319
  the same lift). R440 hover 0.45→0.60 light + R12
11310
11320
  status.halo color + R407 transition list all
@@ -12521,7 +12531,7 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
12521
12531
  fill + opacity in its transition list. R142
12522
12532
  already eased filter (drop-shadow) + stroke
12523
12533
  (R217 cyan tint on hover); the rect's fill
12524
- (pal.labelBox.fill: cyber #020617 ↔ light
12534
+ (pal.labelBox.fill: cyber #060608 ↔ light
12525
12535
  #ffffff) and theme-derived opacity (0.94
12526
12536
  cyber / 1 light) still snapped on theme
12527
12537
  toggle. R211 already closed the alias/sub
@@ -12908,7 +12918,7 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
12908
12918
  for legibility" pattern, now applied to the
12909
12919
  per-node sub-text line. At fontSize=8-9
12910
12920
  monospace against the label-card chrome
12911
- (pal.labelBox.fill cyber #020617 / light
12921
+ (pal.labelBox.fill cyber #060608 / light
12912
12922
  #ffffff), the default fw=400 sits at the
12913
12923
  legibility floor; fw=500 (font-medium) lifts
12914
12924
  it into a clearly readable band without
@@ -13546,7 +13556,7 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
13546
13556
  include fill + stroke + opacity at 200ms. R135
13547
13557
  already eased filter (hover drop-shadow); the
13548
13558
  three theme-driven properties (pal.legendBox.fill
13549
- cyber #020617 ↔ light #ffffff, pal.legendBox.
13559
+ cyber #060608 ↔ light #ffffff, pal.legendBox.
13550
13560
  stroke cyber #1f2937 ↔ light #e2e8f0, opacity
13551
13561
  0.92 ↔ 0.97) still snapped on theme toggle. Same
13552
13562
  per-element 4-property easing R246 added to the
@@ -13580,7 +13590,7 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
13580
13590
  {/* Round 266 / Loop: panel title fill picks up theme-toggle
13581
13591
  transition. Pre-R266 the title "recent signal" had
13582
13592
  fill={pal.legendHeadline} (cyber #e5e7eb ↔ light
13583
- #0f172a) without any inline transition — so the BIGGEST
13593
+ #18181b) without any inline transition — so the BIGGEST
13584
13594
  text in the recent-signal panel (fontSize 12 fontWeight
13585
13595
  700) hard-flipped color on theme toggle while the panel
13586
13596
  rect (R247) and every row inside (various) eased.
@@ -16525,7 +16535,7 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
16525
16535
  corners hold recent-signal + legend panels, bottom-
16526
16536
  right holds the chrome strip). No icon yet — public/
16527
16537
  has only favicon.svg (small abstract network icon
16528
- with hardcoded #0a0a1a dark bg that wouldn't blend on
16538
+ with hardcoded #0b0b0d dark bg that wouldn't blend on
16529
16539
  light theme) + intern_avatar.png (书生 brand-specific).
16530
16540
  Without a sleep2agi-specific crescent/lockup asset,
16531
16541
  R282 ships a low-opacity text-only mark; R283+ can
@@ -110,7 +110,7 @@ export function UserBar() {
110
110
  const initials = (auth.user.display_name || auth.user.username).slice(0, 2).toUpperCase();
111
111
 
112
112
  return (
113
- <div className="flex items-center justify-between bg-[#111128] border border-[#2a2a4a] rounded-lg px-4 py-2.5 mb-4">
113
+ <div className="flex items-center justify-between bg-[#161618] border border-[#26262b] rounded-lg px-4 py-2.5 mb-4">
114
114
  {/* User info */}
115
115
  <div className="flex items-center gap-3">
116
116
  <div className="w-8 h-8 rounded-full bg-gradient-to-br from-cyan-500 to-blue-600 flex items-center justify-center text-xs font-bold text-white">
@@ -133,7 +133,7 @@ export function UserBar() {
133
133
  setNetworkId(e.target.value);
134
134
  sessionStorage.setItem('anet_v3_auth', JSON.stringify(updated));
135
135
  }}
136
- className="bg-[#0a0a15] border border-[#2a2a4a] rounded px-2 py-1 text-xs text-white focus:outline-none"
136
+ className="bg-[#0e0e10] border border-[#26262b] rounded px-2 py-1 text-base sm:text-xs text-white focus:outline-none"
137
137
  >
138
138
  {auth.networks.map(n => (
139
139
  <option key={n.network_id} value={n.network_id}>{n.network_name}</option>
@@ -158,11 +158,11 @@ export function UserBar() {
158
158
  </button>
159
159
  </div>
160
160
  {editing && (
161
- <div className="flex flex-wrap items-center gap-2 mt-2 pt-2 border-t border-[#2a2a4a]">
161
+ <div className="flex flex-wrap items-center gap-2 mt-2 pt-2 border-t border-[#26262b]">
162
162
  <input type="text" value={editName} onChange={e => setEditName(e.target.value)} placeholder="Display name"
163
- className="bg-[#0a0a15] border border-[#2a2a4a] rounded px-2 py-1 text-xs text-white placeholder-gray-600 focus:outline-none w-32" />
163
+ className="bg-[#0e0e10] border border-[#26262b] rounded px-2 py-1 text-base sm:text-xs text-white placeholder-gray-600 focus:outline-none w-32" />
164
164
  <input type="email" value={editEmail} onChange={e => setEditEmail(e.target.value)} placeholder="Email"
165
- className="bg-[#0a0a15] border border-[#2a2a4a] rounded px-2 py-1 text-xs text-white placeholder-gray-600 focus:outline-none w-40" />
165
+ className="bg-[#0e0e10] border border-[#26262b] rounded px-2 py-1 text-base sm:text-xs text-white placeholder-gray-600 focus:outline-none w-40" />
166
166
  <button onClick={updateProfile} className="px-2 py-1 bg-cyan-600 hover:bg-cyan-500 text-white text-xs rounded">Save</button>
167
167
  </div>
168
168
  )}