@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/node/page.tsx CHANGED
@@ -60,7 +60,7 @@ function TmuxViewer({ tmuxName }: { tmuxName: string }) {
60
60
  };
61
61
 
62
62
  return (
63
- <div className="bg-[#111128] border border-[#2a2a4a] rounded-xl p-4">
63
+ <div className="bg-[#161618] border border-[#26262b] rounded-xl p-4">
64
64
  <div className="flex items-center justify-between mb-2">
65
65
  <h2 className="text-sm font-semibold text-gray-300">Terminal ({tmuxName})</h2>
66
66
  <div className="flex gap-2">
@@ -76,7 +76,7 @@ function TmuxViewer({ tmuxName }: { tmuxName: string }) {
76
76
  </div>
77
77
  </div>
78
78
  {output && (
79
- <pre className={`text-[11px] text-green-300 bg-[#050510] rounded-lg px-3 py-2 border border-[#1a1a2a] overflow-x-auto whitespace-pre font-mono ${expanded ? 'max-h-96' : 'max-h-32'} overflow-y-auto`}>
79
+ <pre className={`text-[11px] text-green-300 bg-[#060607] rounded-lg px-3 py-2 border border-[#1c1c1f] overflow-x-auto whitespace-pre font-mono ${expanded ? 'max-h-96' : 'max-h-32'} overflow-y-auto`}>
80
80
  {output}
81
81
  </pre>
82
82
  )}
@@ -142,7 +142,7 @@ function NodeDetailContent() {
142
142
 
143
143
  if (!alias) {
144
144
  return (
145
- <div className="min-h-screen bg-[#0a0a1a] text-gray-100 p-6 font-mono flex items-center justify-center">
145
+ <div className="min-h-screen bg-[#0b0b0d] text-gray-100 p-6 flex items-center justify-center">
146
146
  <p className="text-gray-500">No alias specified. <Link href="/" className="text-blue-400 hover:underline">Back to dashboard</Link></p>
147
147
  </div>
148
148
  );
@@ -153,7 +153,7 @@ function NodeDetailContent() {
153
153
  const statusColor = SESSION_STATUS_TEXT_CLASS[session?.status || ''] || SESSION_STATUS_TEXT_CLASS.offline;
154
154
 
155
155
  return (
156
- <div className="min-h-screen bg-[#0a0a1a] text-gray-100 p-4 sm:p-6 font-mono">
156
+ <div className="min-h-screen bg-[#0b0b0d] text-gray-100 p-4 sm:p-6">
157
157
  {/* Header — round 40: avatar joins the alias for cross-page hue
158
158
  consistency; agent type lives in a subtitle so users know what
159
159
  kind of node they're looking at. */}
@@ -203,10 +203,10 @@ function NodeFullPanel({ alias, session, sse, sendMsg, setSendMsg, sending, send
203
203
  }, [tab, eventsLoaded]);
204
204
 
205
205
  return (
206
- <div className="bg-[#0d0d1a] border border-[#2a2a4a] rounded-xl overflow-hidden h-[calc(100vh-140px)] flex flex-col">
206
+ <div className="bg-[#111113] border border-[#26262b] rounded-xl overflow-hidden h-[calc(100vh-140px)] flex flex-col">
207
207
  {/* Tab bar — round 40: emoji icons (💬 📋 📊) replaced with stroke
208
208
  SVG to drop the "AI generated" tell. */}
209
- <div className="flex border-b border-[#2a2a4a] bg-[#0a0a15] shrink-0">
209
+ <div className="flex border-b border-[#26262b] bg-[#0e0e10] shrink-0">
210
210
  {([
211
211
  { id: 'chat', label: 'Chat', 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' },
212
212
  { id: 'events', label: 'Events', 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' },
@@ -241,7 +241,7 @@ function NodeFullPanel({ alias, session, sse, sendMsg, setSendMsg, sending, send
241
241
 
242
242
  {tab === 'info' && (
243
243
  <div className="p-4 overflow-y-auto h-full space-y-4 max-w-2xl">
244
- <div className="bg-[#111128] border border-[#2a2a4a] rounded-xl p-4">
244
+ <div className="bg-[#161618] border border-[#26262b] rounded-xl p-4">
245
245
  <h2 className="text-sm font-semibold text-gray-300 mb-3">Node Info</h2>
246
246
  <div className="space-y-2 text-xs">
247
247
  {[
@@ -278,7 +278,7 @@ function NodeFullPanel({ alias, session, sse, sendMsg, setSendMsg, sending, send
278
278
 
279
279
  {/* Current Task */}
280
280
  {session?.task && (
281
- <div className="bg-[#111128] border border-[#2a2a4a] rounded-xl p-4">
281
+ <div className="bg-[#161618] border border-[#26262b] rounded-xl p-4">
282
282
  <h2 className="text-sm font-semibold text-gray-300 mb-2">Current Task</h2>
283
283
  <p className="text-xs text-gray-400 whitespace-pre-wrap">{session.task}</p>
284
284
  </div>
@@ -286,14 +286,14 @@ function NodeFullPanel({ alias, session, sse, sendMsg, setSendMsg, sending, send
286
286
 
287
287
  {/* Output */}
288
288
  {session?.output && (
289
- <div className="bg-[#111128] border border-[#2a2a4a] rounded-xl p-4">
289
+ <div className="bg-[#161618] border border-[#26262b] rounded-xl p-4">
290
290
  <h2 className="text-sm font-semibold text-gray-300 mb-2">Last Output</h2>
291
291
  <p className="text-xs text-gray-400 whitespace-pre-wrap max-h-48 overflow-y-auto">{session.output}</p>
292
292
  </div>
293
293
  )}
294
294
 
295
295
  {/* Send Task */}
296
- <div className="bg-[#111128] border border-[#2a2a4a] rounded-xl p-4">
296
+ <div className="bg-[#161618] border border-[#26262b] rounded-xl p-4">
297
297
  <h2 className="text-sm font-semibold text-gray-300 mb-2">Send Task</h2>
298
298
  <div className="flex gap-2">
299
299
  <input
@@ -302,12 +302,12 @@ function NodeFullPanel({ alias, session, sse, sendMsg, setSendMsg, sending, send
302
302
  onChange={e => setSendMsg(e.target.value)}
303
303
  onKeyDown={e => e.key === 'Enter' && sendTask()}
304
304
  placeholder={`Send task to ${alias}...`}
305
- className="flex-1 bg-[#0a0a15] border border-[#2a2a4a] rounded px-3 py-2 text-xs text-white placeholder-gray-600 focus:border-blue-500 focus:outline-none"
305
+ className="flex-1 bg-[#0e0e10] border border-[#26262b] rounded px-3 py-2 text-base sm:text-xs text-white placeholder-gray-600 focus:border-blue-500 focus:outline-none"
306
306
  />
307
307
  <button
308
308
  onClick={sendTask}
309
309
  disabled={sending || !sendMsg.trim()}
310
- className="px-3 py-2 bg-blue-600 hover:bg-blue-500 disabled:bg-gray-700 text-white text-xs rounded transition-colors"
310
+ className="inline-flex min-h-[44px] items-center justify-center px-4 py-2 bg-blue-600 hover:bg-blue-500 disabled:bg-gray-700 text-white text-xs rounded transition-colors"
311
311
  >
312
312
  {sending ? '...' : 'Send'}
313
313
  </button>
@@ -354,11 +354,11 @@ function EventsTimeline({ events, loading }: { events: Array<{ id: number; event
354
354
  return (
355
355
  <div className="p-4 overflow-y-auto h-full space-y-4">
356
356
  {[...groups.entries()].map(([taskId, taskEvents]) => (
357
- <div key={taskId} className="bg-[#111128] border border-[#2a2a4a] rounded-xl p-4">
357
+ <div key={taskId} className="bg-[#161618] border border-[#26262b] rounded-xl p-4">
358
358
  <div className="text-[10px] text-gray-600 mb-3 truncate">Task: {taskId.slice(0, 20)}...</div>
359
359
  <div className="relative pl-6">
360
360
  {/* Vertical line */}
361
- <div className="absolute left-[9px] top-2 bottom-2 w-0.5 bg-[#1a1a2a]" />
361
+ <div className="absolute left-[9px] top-2 bottom-2 w-0.5 bg-[#1c1c1f]" />
362
362
 
363
363
  {taskEvents.map((e, i) => {
364
364
  const cfg = EVENT_COLORS[e.to_status] || EVENT_COLORS.created;
@@ -366,8 +366,8 @@ function EventsTimeline({ events, loading }: { events: Array<{ id: number; event
366
366
  <div key={e.id} className="relative pb-4 last:pb-0">
367
367
  {/* Dot on line — round 59: emoji icons replaced with
368
368
  a 10px stroke SVG path matching event type. */}
369
- <div className={`absolute -left-6 top-0.5 w-[18px] h-[18px] rounded-full ${cfg.dot} flex items-center justify-center z-10 border-2 border-[#111128]`}>
370
- <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="#0a0a15" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden>
369
+ <div className={`absolute -left-6 top-0.5 w-[18px] h-[18px] rounded-full ${cfg.dot} flex items-center justify-center z-10 border-2 border-[#161618]`}>
370
+ <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="#0e0e10" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden>
371
371
  <path d={cfg.path} />
372
372
  </svg>
373
373
  </div>
@@ -398,7 +398,17 @@ function EventsTimeline({ events, loading }: { events: Array<{ id: number; event
398
398
 
399
399
  export default function NodePage() {
400
400
  return (
401
- <Suspense fallback={<div className="min-h-screen bg-[#0a0a1a] text-gray-100 p-6 font-mono">Loading...</div>}>
401
+ <Suspense fallback={
402
+ // #209 R36: same pattern R30 fixed on /tasks — bare "Loading..."
403
+ // string used p-6 (no mobile padding tighten) + no left indent,
404
+ // so the fixed top-3 left-3 mobile hamburger covered the "Loa".
405
+ // Match the loaded layout: p-4 sm:p-6 + lg:ml-0 ml-10 mobile
406
+ // indent on the text. Loading state now visually maps to the
407
+ // populated /node detail page.
408
+ <div className="min-h-screen bg-[#0b0b0d] text-gray-100 p-4 sm:p-6">
409
+ <div className="lg:ml-0 ml-10 text-gray-500 text-sm">Loading…</div>
410
+ </div>
411
+ }>
402
412
  <NodeDetailContent />
403
413
  </Suspense>
404
414
  );
@@ -6,6 +6,7 @@ import { useSessions, useHealth } from '../lib/hooks';
6
6
  import { TaskChatPanel } from '../components/TaskChatPanel';
7
7
  import { EmptyState, NodesEmptyState } from '../components/EmptyState';
8
8
  import { AliasAvatar } from '../components/AliasAvatar';
9
+ import { useCollapsibleSearch } from '../components/CollapsibleSearch';
9
10
  import type { Session } from '../components/types';
10
11
  import { SESSION_STATUS_CHIP_CLASS as STATUS_COLORS } from '../lib/status';
11
12
  import { useChatUnread } from '../lib/chat-unread';
@@ -34,6 +35,17 @@ export default function NodesPage() {
34
35
  const [search, setSearch] = useState('');
35
36
  const [viewMode, setViewMode] = useState<ViewMode>('list');
36
37
  const [chatAlias, setChatAlias] = useState<string | null>(null);
38
+ // #209 R32→R34: the WeChat-style magnifier-toggle search was hand-rolled
39
+ // inline in R32. R34 extracted it to a shared hook so /nodes, /messages,
40
+ // and any future search surface stay visually + behaviourally identical.
41
+ // The hook returns a Button (place in header) + Row (place after header).
42
+ const searchCtl = useCollapsibleSearch({
43
+ value: search,
44
+ onChange: setSearch,
45
+ placeholder: 'Search nodes…',
46
+ label: 'Search nodes',
47
+ enabled: sessions.length > 0,
48
+ });
37
49
 
38
50
  const filtered: SessionRow[] = sessions
39
51
  .map(s => ({ ...s, online: !!sseFor(s) }))
@@ -49,38 +61,37 @@ export default function NodesPage() {
49
61
  const onlineCount = sessions.filter(s => sseFor(s)).length;
50
62
 
51
63
  return (
52
- <div className="min-h-screen max-w-full overflow-x-hidden bg-[#0a0a1a] text-gray-100 p-4 sm:p-6 font-mono">
53
- <div className="flex items-center gap-4 mb-6">
54
- <h1 className="text-2xl font-bold text-white lg:ml-0 ml-10">Nodes</h1>
55
- <span className="text-xs bg-green-900/30 text-green-400 px-2 py-0.5 rounded-full border border-green-800/30">
56
- {onlineCount} online
57
- </span>
58
- <span className="text-xs bg-gray-900/30 text-gray-400 px-2 py-0.5 rounded-full border border-gray-800/30">
59
- {sessions.length} total
60
- </span>
64
+ <div className="min-h-screen max-w-full overflow-x-hidden bg-[#0b0b0d] text-gray-100 p-4 sm:p-6">
65
+ {/* #209 R31 (mobile vertical rhythm — goal "大幅提升移动端体验",
66
+ extending R28's Overview pattern + R30's /tasks pattern):
67
+ this header row + the status-bar wrapper + the filter row
68
+ below all drop mb-6 → mb-4 sm:mb-6. Three spots × 8 px =
69
+ ~24 px scroll reclaim on /nodes before the first card.
70
+ #209 R32: search affordance moved to top-right magnifier
71
+ button (Vincent WeChat ref msg 563). justify-between makes
72
+ the title cluster hug left, button hugs right. */}
73
+ <div className="flex items-center gap-4 mb-4 sm:mb-6">
74
+ <div className="flex items-center gap-3 min-w-0 flex-1">
75
+ <h1 className="text-2xl font-bold text-white lg:ml-0 ml-10">Nodes</h1>
76
+ <span className="text-xs bg-green-900/30 text-green-400 px-2 py-0.5 rounded-full border border-green-800/30 shrink-0">
77
+ {onlineCount} online
78
+ </span>
79
+ <span className="text-xs bg-gray-900/30 text-gray-400 px-2 py-0.5 rounded-full border border-gray-800/30 shrink-0">
80
+ {sessions.length} total
81
+ </span>
82
+ </div>
83
+ <searchCtl.Button />
61
84
  </div>
62
85
 
63
- {/* Status bar */}
64
- {sessions.length > 0 && (() => {
65
- const working = filtered.filter(s => s.online && s.status === 'working').length;
66
- const idle = filtered.filter(s => s.online && s.status === 'idle').length;
67
- const offline = filtered.filter(s => !s.online).length;
68
- const total = filtered.length || 1;
69
- return (
70
- <div className="mb-6">
71
- <div className="flex h-2 rounded-full overflow-hidden bg-gray-800">
72
- {working > 0 && <div className="bg-green-500" style={{ width: `${(working/total)*100}%` }} />}
73
- {idle > 0 && <div className="bg-cyan-500" style={{ width: `${(idle/total)*100}%` }} />}
74
- {offline > 0 && <div className="bg-gray-600" style={{ width: `${(offline/total)*100}%` }} />}
75
- </div>
76
- <div className="flex gap-4 mt-1.5 text-[10px] text-gray-500">
77
- {working > 0 && <span><span className="inline-block w-2 h-2 rounded-full bg-green-500 mr-1" />{working} working</span>}
78
- {idle > 0 && <span><span className="inline-block w-2 h-2 rounded-full bg-cyan-500 mr-1" />{idle} idle</span>}
79
- {offline > 0 && <span><span className="inline-block w-2 h-2 rounded-full bg-gray-600 mr-1" />{offline} offline</span>}
80
- </div>
81
- </div>
82
- );
83
- })()}
86
+ {/* #209 R34: shared <CollapsibleSearch> component handles row reveal,
87
+ autofocus, Escape, and Cancel. enabled=sessions.length>0 hides
88
+ everything until there's content to search. */}
89
+ <searchCtl.Row />
90
+
91
+ {/* #217 D6 (less is more): the status distribution bar + its
92
+ working/idle/offline legend duplicated the header chips
93
+ (N online / N total) and the per-card status pills right
94
+ below. One count display per screen — the bar is gone. */}
84
95
 
85
96
  {/* Round 74: hide the filter+view chrome when there are no nodes
86
97
  anywhere — these controls have nothing to act on, and they only
@@ -88,18 +99,14 @@ export default function NodesPage() {
88
99
  exists, the chrome is back even if the current filter happens
89
100
  to hide everything (so users can clear filters). */}
90
101
  {sessions.length > 0 && (
91
- <div className="flex flex-wrap gap-3 mb-6">
92
- <input
93
- type="text"
94
- value={search}
95
- onChange={e => setSearch(e.target.value)}
96
- placeholder="Search nodes..."
97
- className="bg-[#111128] border border-[#2a2a4a] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-blue-500/50 focus:outline-none w-48"
98
- />
102
+ <div className="flex flex-wrap gap-3 mb-4 sm:mb-6">
103
+ {/* R32: the inline search input was moved to the top-right
104
+ magnifier toggle above. The status select + List/Grid
105
+ toggle stay here. */}
99
106
  <select
100
107
  value={filterStatus}
101
108
  onChange={e => setFilterStatus(e.target.value)}
102
- className="bg-[#111128] border border-[#2a2a4a] rounded-lg px-3 py-2 text-sm text-white focus:border-blue-500/50 focus:outline-none"
109
+ className="bg-[#161618] border border-[#26262b] rounded-lg px-3 py-2 text-base sm:text-sm text-white focus:border-blue-500/50 focus:outline-none"
103
110
  >
104
111
  <option value="">All</option>
105
112
  <option value="online">Online</option>
@@ -113,7 +120,7 @@ export default function NodesPage() {
113
120
  grid-cols-1 below `md` and List degrades to the same single
114
121
  column, so the toggle has no visual effect under sm and only
115
122
  steals a row of vertical space. */}
116
- <div className="hidden sm:flex ml-auto rounded-lg border border-[#2a2a4a] bg-[#111128] p-1 text-sm">
123
+ <div className="hidden sm:flex ml-auto rounded-lg border border-[#26262b] bg-[#161618] p-1 text-sm">
117
124
  {(['list', 'grid'] as const).map(mode => (
118
125
  <button
119
126
  key={mode}
@@ -165,7 +172,7 @@ export default function NodesPage() {
165
172
  tabIndex={0}
166
173
  onClick={() => setChatAlias(s.alias)}
167
174
  onKeyDown={e => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setChatAlias(s.alias); } }}
168
- className={`relative min-w-0 max-w-full overflow-hidden rounded-xl border border-[#2a2a4a] bg-[#111128] p-4 transition-colors hover:border-cyan-500/40 cursor-pointer ${!s.online ? 'opacity-60' : ''}`}
175
+ className={`relative min-w-0 max-w-full overflow-hidden rounded-xl border border-[#26262b] bg-[#161618] p-4 transition-colors hover:border-cyan-500/40 cursor-pointer ${!s.online ? 'opacity-60' : ''}`}
169
176
  >
170
177
  {!s.online && (
171
178
  <div className="pointer-events-none absolute inset-0 flex items-center justify-center">
@@ -177,7 +184,7 @@ export default function NodesPage() {
177
184
  <div className="flex items-start gap-3">
178
185
  <div className="relative shrink-0">
179
186
  <AliasAvatar alias={s.alias} size={36} />
180
- {unread && <span className="absolute -right-1 -top-1 h-3 w-3 rounded-full border-2 border-[#111128] bg-red-500" />}
187
+ {unread && <span className="absolute -right-1 -top-1 h-3 w-3 rounded-full border-2 border-[#161618] bg-red-500" />}
181
188
  </div>
182
189
  <div className="min-w-0 flex-1">
183
190
  <div className="flex items-center gap-2">
@@ -194,7 +201,7 @@ export default function NodesPage() {
194
201
  <span className="hidden shrink-0 rounded-lg border border-cyan-500/15 bg-cyan-500/5 px-2 py-1 text-[10px] text-cyan-300/70 sm:inline">Tap to chat</span>
195
202
  </div>
196
203
 
197
- <div className="mt-3 rounded-lg border border-[#1a1a2a] bg-[#0a0a15] px-3 py-2 text-xs">
204
+ <div className="mt-3 rounded-lg border border-[#1c1c1f] bg-[#0e0e10] px-3 py-2 text-xs">
198
205
  <div className="flex items-center justify-between gap-3">
199
206
  <span className="text-[10px] uppercase tracking-wide text-gray-600">Current task</span>
200
207
  <span className="text-[10px] text-gray-600">{timeAgo(s.last_seen_at || s.updated_at)}</span>
@@ -215,7 +222,7 @@ export default function NodesPage() {
215
222
  })}
216
223
  </div>
217
224
  ) : (
218
- <div className="space-y-2">
225
+ <div className="space-y-1 sm:space-y-2">
219
226
  {/* Round 94: AGENT + SERVER merged into one `agent · server`
220
227
  cell. Round mobile-command: node row itself opens chat, so
221
228
  the old Chat / Send Task action column is gone. */}
@@ -237,7 +244,7 @@ export default function NodesPage() {
237
244
  tabIndex={0}
238
245
  onClick={() => setChatAlias(s.alias)}
239
246
  onKeyDown={e => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setChatAlias(s.alias); } }}
240
- className={`rounded-lg border border-[#2a2a4a] bg-[#111128] px-4 py-3 transition-colors hover:border-cyan-500/40 cursor-pointer ${!s.online ? 'opacity-50' : ''}`}
247
+ className={`rounded-lg border border-[#26262b] bg-[#161618] px-3 py-2 sm:px-4 sm:py-3 transition-colors hover:border-cyan-500/40 cursor-pointer ${!s.online ? 'opacity-50' : ''}`}
241
248
  >
242
249
  <div className="hidden sm:grid sm:grid-cols-10 gap-2 items-center">
243
250
  <div className="col-span-1">
@@ -249,7 +256,7 @@ export default function NodesPage() {
249
256
  <div className="flex items-center gap-2 min-w-0">
250
257
  <div className="relative shrink-0">
251
258
  <AliasAvatar alias={s.alias} size={20} />
252
- {unread && <span className="absolute -right-1 -top-1 h-2.5 w-2.5 rounded-full border border-[#111128] bg-red-500" />}
259
+ {unread && <span className="absolute -right-1 -top-1 h-2.5 w-2.5 rounded-full border border-[#161618] bg-red-500" />}
253
260
  </div>
254
261
  <span className="truncate text-sm font-medium text-white">{s.alias}</span>
255
262
  {unread && <span className="shrink-0 rounded-full bg-red-500/15 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-red-300">New</span>}
@@ -261,11 +268,18 @@ export default function NodesPage() {
261
268
  <div className="col-span-4 truncate text-xs text-gray-500" title={s.task || ''}>{s.task || '--'}</div>
262
269
  <div className="col-span-1 text-xs text-gray-500">{timeAgo(s.last_seen_at || s.updated_at)}</div>
263
270
  </div>
264
- <div className="sm:hidden space-y-2">
271
+ {/* R7 of #190: mobile node row was ~340px tall × ~150
272
+ rows = the 51k page. Wins this round, in priority
273
+ order: (1) drop the per-row "Tap anywhere to chat"
274
+ hint — useful once, redundant 149 times; the cyan
275
+ border on hover/focus still teaches it. (2) tighten
276
+ space-y-2 → space-y-1 so the avatar/task gap is
277
+ 4px tighter on every row. */}
278
+ <div className="sm:hidden space-y-1">
265
279
  <div className="flex items-center gap-2.5">
266
280
  <div className="relative shrink-0">
267
281
  <AliasAvatar alias={s.alias} size={28} />
268
- {unread && <span className="absolute -right-1 -top-1 h-3 w-3 rounded-full border-2 border-[#111128] bg-red-500" />}
282
+ {unread && <span className="absolute -right-1 -top-1 h-3 w-3 rounded-full border-2 border-[#161618] bg-red-500" />}
269
283
  </div>
270
284
  <div className="min-w-0 flex-1">
271
285
  <div className="flex items-center gap-2 min-w-0">
@@ -279,7 +293,6 @@ export default function NodesPage() {
279
293
  </span>
280
294
  </div>
281
295
  {s.task && <div className="truncate text-xs text-gray-500">{s.task}</div>}
282
- <div className="text-[10px] text-cyan-300/70">Tap anywhere to chat</div>
283
296
  </div>
284
297
  </div>
285
298
  );