@sleep2agi/agent-network-dashboard 0.6.3-preview.1 → 0.6.3-preview.10

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 (348) hide show
  1. package/.next/BUILD_COMMIT +1 -1
  2. package/.next/BUILD_ID +1 -1
  3. package/.next/app-path-routes-manifest.json +5 -0
  4. package/.next/build-manifest.json +3 -3
  5. package/.next/cache/.previewinfo +1 -0
  6. package/.next/cache/.rscinfo +1 -0
  7. package/.next/diagnostics/route-bundle-stats.json +56 -39
  8. package/.next/fallback-build-manifest.json +3 -3
  9. package/.next/prerender-manifest.json +27 -3
  10. package/.next/routes-manifest.json +30 -0
  11. package/.next/server/app/_global-error.html +1 -1
  12. package/.next/server/app/_global-error.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  14. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  15. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  16. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  17. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  18. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  19. package/.next/server/app/_not-found.html +2 -2
  20. package/.next/server/app/_not-found.rsc +13 -13
  21. package/.next/server/app/_not-found.segments/_full.segment.rsc +13 -13
  22. package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  23. package/.next/server/app/_not-found.segments/_index.segment.rsc +8 -8
  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 +2 -2
  27. package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
  28. package/.next/server/app/admin.html +2 -2
  29. package/.next/server/app/admin.rsc +15 -15
  30. package/.next/server/app/admin.segments/_full.segment.rsc +15 -15
  31. package/.next/server/app/admin.segments/_head.segment.rsc +4 -4
  32. package/.next/server/app/admin.segments/_index.segment.rsc +8 -8
  33. package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
  34. package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +4 -4
  35. package/.next/server/app/admin.segments/admin.segment.rsc +3 -3
  36. package/.next/server/app/api/anet/host-supervisors/route/app-paths-manifest.json +3 -0
  37. package/.next/server/app/api/anet/host-supervisors/route/build-manifest.json +9 -0
  38. package/.next/server/app/api/anet/host-supervisors/route/server-reference-manifest.json +4 -0
  39. package/.next/server/app/api/anet/host-supervisors/route.js +7 -0
  40. package/.next/server/app/api/anet/host-supervisors/route.js.map +5 -0
  41. package/.next/server/app/api/anet/host-supervisors/route.js.nft.json +1 -0
  42. package/.next/server/app/api/anet/host-supervisors/route_client-reference-manifest.js +3 -0
  43. package/.next/server/app/api/anet/providers/probe/route/app-paths-manifest.json +3 -0
  44. package/.next/server/app/api/anet/providers/probe/route/build-manifest.json +9 -0
  45. package/.next/server/app/api/anet/providers/probe/route/server-reference-manifest.json +4 -0
  46. package/.next/server/app/api/anet/providers/probe/route.js +7 -0
  47. package/.next/server/app/api/anet/providers/probe/route.js.map +5 -0
  48. package/.next/server/app/api/anet/providers/probe/route.js.nft.json +1 -0
  49. package/.next/server/app/api/anet/providers/probe/route_client-reference-manifest.js +3 -0
  50. package/.next/server/app/api/anet/providers/probe-results/route/app-paths-manifest.json +3 -0
  51. package/.next/server/app/api/anet/providers/probe-results/route/build-manifest.json +9 -0
  52. package/.next/server/app/api/anet/providers/probe-results/route/server-reference-manifest.json +4 -0
  53. package/.next/server/app/api/anet/providers/probe-results/route.js +7 -0
  54. package/.next/server/app/api/anet/providers/probe-results/route.js.map +5 -0
  55. package/.next/server/app/api/anet/providers/probe-results/route.js.nft.json +1 -0
  56. package/.next/server/app/api/anet/providers/probe-results/route_client-reference-manifest.js +3 -0
  57. package/.next/server/app/api/anet/providers/route/app-paths-manifest.json +3 -0
  58. package/.next/server/app/api/anet/providers/route/build-manifest.json +9 -0
  59. package/.next/server/app/api/anet/providers/route/server-reference-manifest.json +4 -0
  60. package/.next/server/app/api/anet/providers/route.js +8 -0
  61. package/.next/server/app/api/anet/providers/route.js.map +5 -0
  62. package/.next/server/app/api/anet/providers/route.js.nft.json +1 -0
  63. package/.next/server/app/api/anet/providers/route_client-reference-manifest.js +3 -0
  64. package/.next/server/app/index.html +2 -2
  65. package/.next/server/app/index.rsc +15 -15
  66. package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
  67. package/.next/server/app/index.segments/_full.segment.rsc +15 -15
  68. package/.next/server/app/index.segments/_head.segment.rsc +4 -4
  69. package/.next/server/app/index.segments/_index.segment.rsc +8 -8
  70. package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  71. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  72. package/.next/server/app/login.html +2 -2
  73. package/.next/server/app/login.rsc +15 -15
  74. package/.next/server/app/login.segments/_full.segment.rsc +15 -15
  75. package/.next/server/app/login.segments/_head.segment.rsc +4 -4
  76. package/.next/server/app/login.segments/_index.segment.rsc +8 -8
  77. package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  78. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
  79. package/.next/server/app/login.segments/login.segment.rsc +3 -3
  80. package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
  81. package/.next/server/app/logs.html +2 -2
  82. package/.next/server/app/logs.rsc +15 -15
  83. package/.next/server/app/logs.segments/_full.segment.rsc +15 -15
  84. package/.next/server/app/logs.segments/_head.segment.rsc +4 -4
  85. package/.next/server/app/logs.segments/_index.segment.rsc +8 -8
  86. package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
  87. package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +4 -4
  88. package/.next/server/app/logs.segments/logs.segment.rsc +3 -3
  89. package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
  90. package/.next/server/app/messages.html +2 -2
  91. package/.next/server/app/messages.rsc +15 -15
  92. package/.next/server/app/messages.segments/_full.segment.rsc +15 -15
  93. package/.next/server/app/messages.segments/_head.segment.rsc +4 -4
  94. package/.next/server/app/messages.segments/_index.segment.rsc +8 -8
  95. package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
  96. package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +4 -4
  97. package/.next/server/app/messages.segments/messages.segment.rsc +3 -3
  98. package/.next/server/app/node/page_client-reference-manifest.js +1 -1
  99. package/.next/server/app/node.html +2 -2
  100. package/.next/server/app/node.rsc +15 -15
  101. package/.next/server/app/node.segments/_full.segment.rsc +15 -15
  102. package/.next/server/app/node.segments/_head.segment.rsc +4 -4
  103. package/.next/server/app/node.segments/_index.segment.rsc +8 -8
  104. package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
  105. package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +4 -4
  106. package/.next/server/app/node.segments/node.segment.rsc +3 -3
  107. package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
  108. package/.next/server/app/nodes.html +2 -2
  109. package/.next/server/app/nodes.rsc +15 -15
  110. package/.next/server/app/nodes.segments/_full.segment.rsc +15 -15
  111. package/.next/server/app/nodes.segments/_head.segment.rsc +4 -4
  112. package/.next/server/app/nodes.segments/_index.segment.rsc +8 -8
  113. package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
  114. package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +4 -4
  115. package/.next/server/app/nodes.segments/nodes.segment.rsc +3 -3
  116. package/.next/server/app/page_client-reference-manifest.js +1 -1
  117. package/.next/server/app/providers/page/app-paths-manifest.json +3 -0
  118. package/.next/server/app/providers/page/build-manifest.json +17 -0
  119. package/.next/server/app/providers/page/next-font-manifest.json +11 -0
  120. package/.next/server/app/providers/page/react-loadable-manifest.json +1 -0
  121. package/.next/server/app/providers/page/server-reference-manifest.json +4 -0
  122. package/.next/server/app/providers/page.js +14 -0
  123. package/.next/server/app/providers/page.js.map +5 -0
  124. package/.next/server/app/providers/page.js.nft.json +1 -0
  125. package/.next/server/app/providers/page_client-reference-manifest.js +3 -0
  126. package/.next/server/app/providers.html +12 -0
  127. package/.next/server/app/providers.meta +15 -0
  128. package/.next/server/app/providers.rsc +27 -0
  129. package/.next/server/app/providers.segments/_full.segment.rsc +27 -0
  130. package/.next/server/app/providers.segments/_head.segment.rsc +6 -0
  131. package/.next/server/app/providers.segments/_index.segment.rsc +10 -0
  132. package/.next/server/app/providers.segments/_tree.segment.rsc +5 -0
  133. package/.next/server/app/providers.segments/providers/__PAGE__.segment.rsc +9 -0
  134. package/.next/server/app/providers.segments/providers.segment.rsc +5 -0
  135. package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
  136. package/.next/server/app/server-logs.html +2 -2
  137. package/.next/server/app/server-logs.rsc +15 -15
  138. package/.next/server/app/server-logs.segments/_full.segment.rsc +15 -15
  139. package/.next/server/app/server-logs.segments/_head.segment.rsc +4 -4
  140. package/.next/server/app/server-logs.segments/_index.segment.rsc +8 -8
  141. package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
  142. package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +4 -4
  143. package/.next/server/app/server-logs.segments/server-logs.segment.rsc +3 -3
  144. package/.next/server/app/servers/page_client-reference-manifest.js +1 -1
  145. package/.next/server/app/servers.html +2 -2
  146. package/.next/server/app/servers.rsc +15 -15
  147. package/.next/server/app/servers.segments/_full.segment.rsc +15 -15
  148. package/.next/server/app/servers.segments/_head.segment.rsc +4 -4
  149. package/.next/server/app/servers.segments/_index.segment.rsc +8 -8
  150. package/.next/server/app/servers.segments/_tree.segment.rsc +2 -2
  151. package/.next/server/app/servers.segments/servers/__PAGE__.segment.rsc +4 -4
  152. package/.next/server/app/servers.segments/servers.segment.rsc +3 -3
  153. package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
  154. package/.next/server/app/settings/networks.html +2 -2
  155. package/.next/server/app/settings/networks.rsc +15 -15
  156. package/.next/server/app/settings/networks.segments/_full.segment.rsc +15 -15
  157. package/.next/server/app/settings/networks.segments/_head.segment.rsc +4 -4
  158. package/.next/server/app/settings/networks.segments/_index.segment.rsc +8 -8
  159. package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
  160. package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +4 -4
  161. package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +3 -3
  162. package/.next/server/app/settings/networks.segments/settings.segment.rsc +3 -3
  163. package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  164. package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
  165. package/.next/server/app/settings/tokens.html +2 -2
  166. package/.next/server/app/settings/tokens.rsc +15 -15
  167. package/.next/server/app/settings/tokens.segments/_full.segment.rsc +15 -15
  168. package/.next/server/app/settings/tokens.segments/_head.segment.rsc +4 -4
  169. package/.next/server/app/settings/tokens.segments/_index.segment.rsc +8 -8
  170. package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
  171. package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +4 -4
  172. package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +3 -3
  173. package/.next/server/app/settings/tokens.segments/settings.segment.rsc +3 -3
  174. package/.next/server/app/settings.html +2 -2
  175. package/.next/server/app/settings.rsc +15 -15
  176. package/.next/server/app/settings.segments/_full.segment.rsc +15 -15
  177. package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
  178. package/.next/server/app/settings.segments/_index.segment.rsc +8 -8
  179. package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  180. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
  181. package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
  182. package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
  183. package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
  184. package/.next/server/app/tasks.html +2 -2
  185. package/.next/server/app/tasks.rsc +15 -15
  186. package/.next/server/app/tasks.segments/_full.segment.rsc +15 -15
  187. package/.next/server/app/tasks.segments/_head.segment.rsc +4 -4
  188. package/.next/server/app/tasks.segments/_index.segment.rsc +8 -8
  189. package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
  190. package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +4 -4
  191. package/.next/server/app/tasks.segments/tasks.segment.rsc +3 -3
  192. package/.next/server/app-paths-manifest.json +5 -0
  193. package/.next/server/chunks/00jm_next_dist_esm_build_templates_app-route_0bobkt3.js +3 -0
  194. package/.next/server/chunks/00jm_next_dist_esm_build_templates_app-route_0bobkt3.js.map +1 -0
  195. package/.next/server/chunks/0dk5_next-internal_server_app_api_anet_providers_probe-results_route_actions_07.d.5a.js +3 -0
  196. package/.next/server/chunks/0dk5_next-internal_server_app_api_anet_providers_probe-results_route_actions_07.d.5a.js.map +1 -0
  197. package/.next/server/chunks/0ykm__next-internal_server_app_api_anet_host-supervisors_route_actions_0g3hek2.js +3 -0
  198. package/.next/server/chunks/0ykm__next-internal_server_app_api_anet_host-supervisors_route_actions_0g3hek2.js.map +1 -0
  199. package/.next/server/chunks/0ykm__next-internal_server_app_api_anet_providers_probe_route_actions_05f000..js +3 -0
  200. package/.next/server/chunks/0ykm__next-internal_server_app_api_anet_providers_probe_route_actions_05f000..js.map +1 -0
  201. package/.next/server/chunks/0ykm__next-internal_server_app_api_anet_providers_route_actions_10htbhd.js +3 -0
  202. package/.next/server/chunks/0ykm__next-internal_server_app_api_anet_providers_route_actions_10htbhd.js.map +1 -0
  203. package/.next/server/chunks/[root-of-the-server]__0-29ynz._.js.map +1 -1
  204. package/.next/server/chunks/[root-of-the-server]__0-2le8-._.js.map +1 -1
  205. package/.next/server/chunks/[root-of-the-server]__0-8_f0o._.js.map +1 -1
  206. package/.next/server/chunks/[root-of-the-server]__02p2n3n._.js.map +1 -1
  207. package/.next/server/chunks/[root-of-the-server]__03nze3z._.js +3 -0
  208. package/.next/server/chunks/[root-of-the-server]__03nze3z._.js.map +1 -0
  209. package/.next/server/chunks/[root-of-the-server]__043tnx2._.js.map +1 -1
  210. package/.next/server/chunks/[root-of-the-server]__04z62zk._.js.map +1 -1
  211. package/.next/server/chunks/[root-of-the-server]__07ztet2._.js.map +1 -1
  212. package/.next/server/chunks/[root-of-the-server]__0aqb4n5._.js +1 -1
  213. package/.next/server/chunks/[root-of-the-server]__0aqb4n5._.js.map +1 -1
  214. package/.next/server/chunks/[root-of-the-server]__0cphmer._.js +3 -0
  215. package/.next/server/chunks/[root-of-the-server]__0cphmer._.js.map +1 -0
  216. package/.next/server/chunks/[root-of-the-server]__0e3ucl1._.js.map +1 -1
  217. package/.next/server/chunks/[root-of-the-server]__0e6yail._.js.map +1 -1
  218. package/.next/server/chunks/[root-of-the-server]__0gx2_6a._.js.map +1 -1
  219. package/.next/server/chunks/[root-of-the-server]__0hg3_8r._.js.map +1 -1
  220. package/.next/server/chunks/[root-of-the-server]__0lhq4ha._.js.map +1 -1
  221. package/.next/server/chunks/[root-of-the-server]__0mkwzz7._.js +1 -1
  222. package/.next/server/chunks/[root-of-the-server]__0mkwzz7._.js.map +1 -1
  223. package/.next/server/chunks/[root-of-the-server]__0mxw4vb._.js.map +1 -1
  224. package/.next/server/chunks/[root-of-the-server]__0mzopco._.js.map +1 -1
  225. package/.next/server/chunks/[root-of-the-server]__0o45a4q._.js.map +1 -1
  226. package/.next/server/chunks/[root-of-the-server]__0w1w_w0._.js +3 -0
  227. package/.next/server/chunks/[root-of-the-server]__0w1w_w0._.js.map +1 -0
  228. package/.next/server/chunks/[root-of-the-server]__0xtp-et._.js.map +1 -1
  229. package/.next/server/chunks/[root-of-the-server]__0yyo7k5._.js +1 -1
  230. package/.next/server/chunks/[root-of-the-server]__0yyo7k5._.js.map +1 -1
  231. package/.next/server/chunks/[root-of-the-server]__0~rwgo1._.js +3 -0
  232. package/.next/server/chunks/[root-of-the-server]__0~rwgo1._.js.map +1 -0
  233. package/.next/server/chunks/[root-of-the-server]__10pvabe._.js.map +1 -1
  234. package/.next/server/chunks/[root-of-the-server]__10t11zq._.js.map +1 -1
  235. package/.next/server/chunks/[root-of-the-server]__12r~omy._.js.map +1 -1
  236. package/.next/server/chunks/[root-of-the-server]__1389~cs._.js.map +1 -1
  237. package/.next/server/chunks/[root-of-the-server]__13n8t..._.js.map +1 -1
  238. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_02lorbl.js +4 -0
  239. package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_02lorbl.js.map +1 -0
  240. package/.next/server/chunks/ssr/[root-of-the-server]__030vg4n._.js.map +1 -1
  241. package/.next/server/chunks/ssr/[root-of-the-server]__04mx~5g._.js +3 -0
  242. package/.next/server/chunks/ssr/[root-of-the-server]__04mx~5g._.js.map +1 -0
  243. package/.next/server/chunks/ssr/[root-of-the-server]__05kf31s._.js +1 -1
  244. package/.next/server/chunks/ssr/[root-of-the-server]__05kf31s._.js.map +1 -1
  245. package/.next/server/chunks/ssr/[root-of-the-server]__096ytyk._.js.map +1 -1
  246. package/.next/server/chunks/ssr/[root-of-the-server]__0fhoq8i._.js +1 -1
  247. package/.next/server/chunks/ssr/[root-of-the-server]__0fhoq8i._.js.map +1 -1
  248. package/.next/server/chunks/ssr/[root-of-the-server]__0h5dae6._.js +1 -1
  249. package/.next/server/chunks/ssr/[root-of-the-server]__0h5dae6._.js.map +1 -1
  250. package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js +3 -3
  251. package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js.map +1 -1
  252. package/.next/server/chunks/ssr/agent-network-dashboard__next-internal_server_app_providers_page_actions_0ou6p43.js +3 -0
  253. package/.next/server/chunks/ssr/agent-network-dashboard__next-internal_server_app_providers_page_actions_0ou6p43.js.map +1 -0
  254. package/.next/server/chunks/ssr/agent-network-dashboard_app_012oyw5._.js +1 -1
  255. package/.next/server/chunks/ssr/agent-network-dashboard_app_012oyw5._.js.map +1 -1
  256. package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js +1 -1
  257. package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js.map +1 -1
  258. package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js +1 -1
  259. package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js.map +1 -1
  260. package/.next/server/chunks/ssr/agent-network-dashboard_app_0_d45-d._.js +1 -1
  261. package/.next/server/chunks/ssr/agent-network-dashboard_app_0_d45-d._.js.map +1 -1
  262. package/.next/server/chunks/ssr/agent-network-dashboard_app_0gd.4pc._.js +1 -1
  263. package/.next/server/chunks/ssr/agent-network-dashboard_app_0gd.4pc._.js.map +1 -1
  264. package/.next/server/chunks/ssr/agent-network-dashboard_app_12l4oto._.js.map +1 -1
  265. package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0r7kb.o._.js +1 -1
  266. package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0r7kb.o._.js.map +1 -1
  267. package/.next/server/chunks/ssr/agent-network-dashboard_app_components_EmptyState_tsx_0aol-el._.js +3 -0
  268. package/.next/server/chunks/ssr/agent-network-dashboard_app_components_EmptyState_tsx_0aol-el._.js.map +1 -0
  269. package/.next/server/chunks/ssr/agent-network-dashboard_app_nodes_page_tsx_11haf_p._.js +2 -1
  270. package/.next/server/chunks/ssr/agent-network-dashboard_app_nodes_page_tsx_11haf_p._.js.map +1 -1
  271. package/.next/server/chunks/ssr/agent-network-dashboard_app_providers_page_tsx_0hw2n0v._.js +3 -0
  272. package/.next/server/chunks/ssr/agent-network-dashboard_app_providers_page_tsx_0hw2n0v._.js.map +1 -0
  273. package/.next/server/chunks/ssr/agent-network-dashboard_app_tasks_page_tsx_0mwxy4z._.js.map +1 -1
  274. package/.next/server/middleware-build-manifest.js +3 -3
  275. package/.next/server/next-font-manifest.js +1 -1
  276. package/.next/server/next-font-manifest.json +4 -0
  277. package/.next/server/pages/404.html +2 -2
  278. package/.next/server/pages/500.html +1 -1
  279. package/.next/server/server-reference-manifest.js +1 -1
  280. package/.next/server/server-reference-manifest.json +1 -1
  281. package/.next/static/chunks/{10kkhdde5ve~c.js → 0-z_kfck7-6_1.js} +3 -3
  282. package/.next/static/chunks/049vx3qljs1tt.js +1 -0
  283. package/.next/static/chunks/06.5euf239uvr.css +1 -0
  284. package/.next/static/chunks/{0vun~4ljcrj3p.js → 091hae.lhv9t1.js} +2 -2
  285. package/.next/static/chunks/0chpv7zsh-qrg.js +1 -0
  286. package/.next/static/chunks/0i-l67o_ae5hk.js +2 -0
  287. package/.next/static/chunks/{0vus9xpsz0s~i.js → 0l.gu-iqnmeja.js} +1 -1
  288. package/.next/static/chunks/{149a4l50_3vw-.js → 0mnmn-~ava1vy.js} +1 -1
  289. package/.next/static/chunks/0o-b62_a66.jr.js +1 -0
  290. package/.next/static/chunks/0pk6amtz5icbx.js +1 -0
  291. package/.next/static/chunks/0r4u1.sl.8p15.js +1 -0
  292. package/.next/static/chunks/0wz0122ym_gr3.js +1 -0
  293. package/.next/static/chunks/15aqdc5txzq9r.js +1 -0
  294. package/.next/trace +2 -2
  295. package/.next/trace-build +1 -1
  296. package/.next/types/routes.d.ts +7 -2
  297. package/.next/types/validator.ts +45 -0
  298. package/app/admin/page.tsx +3 -1
  299. package/app/api/anet/host-supervisors/route.ts +102 -0
  300. package/app/api/anet/node-config/route.ts +26 -2
  301. package/app/api/anet/node-create/route.ts +14 -5
  302. package/app/api/anet/node-lifecycle/route.ts +54 -5
  303. package/app/api/anet/providers/probe/route.ts +79 -0
  304. package/app/api/anet/providers/probe-results/route.ts +60 -0
  305. package/app/api/anet/providers/route.ts +191 -0
  306. package/app/api/hub/auth/route.ts +0 -12
  307. package/app/api/hub/networks/route.ts +1 -1
  308. package/app/api/hub/nodes/route.ts +0 -14
  309. package/app/api/hub/upload/route.ts +0 -9
  310. package/app/components/CommandCenter.tsx +3 -6
  311. package/app/components/CommandPalette.tsx +0 -5
  312. package/app/components/CreateNodeWizard.tsx +140 -47
  313. package/app/components/HostSupervisorPicker.tsx +283 -0
  314. package/app/components/NodeLifecycleMenu.tsx +436 -0
  315. package/app/components/NodeSettingsPanel.tsx +80 -39
  316. package/app/components/ProviderFormModal.tsx +303 -0
  317. package/app/components/ReachabilityMatrix.tsx +196 -0
  318. package/app/components/Sidebar.tsx +1 -0
  319. package/app/components/TaskDrawer.tsx +1 -0
  320. package/app/components/TopoGraph.tsx +4 -8
  321. package/app/components/UserBar.tsx +37 -0
  322. package/app/components/types.ts +11 -0
  323. package/app/lib/chat-unread.ts +0 -6
  324. package/app/lib/dashboard-auth.ts +0 -12
  325. package/app/lib/hooks.ts +22 -4
  326. package/app/lib/hub.ts +4 -0
  327. package/app/lib/network-context.tsx +0 -6
  328. package/app/lib/rate-limit.ts +2 -16
  329. package/app/node/page.tsx +12 -1
  330. package/app/nodes/page.tsx +42 -2
  331. package/app/page.tsx +1 -0
  332. package/app/providers/page.tsx +182 -0
  333. package/app/settings/networks/page.tsx +1 -1
  334. package/app/settings/page.tsx +5 -0
  335. package/app/tasks/[id]/page.tsx +1 -0
  336. package/app/tasks/page.tsx +1 -0
  337. package/package.json +1 -1
  338. package/.next/static/chunks/0-t2rbg9~-oh5.js +0 -1
  339. package/.next/static/chunks/0iv.0p9_5b36e.js +0 -1
  340. package/.next/static/chunks/0l_hz3xrjwumg.js +0 -1
  341. package/.next/static/chunks/0lmdw~i5qjqsg.js +0 -1
  342. package/.next/static/chunks/0vruzstkdr99w.js +0 -1
  343. package/.next/static/chunks/0xssg9sin~2xw.js +0 -1
  344. package/.next/static/chunks/124dtwo1k24ao.css +0 -1
  345. package/bun.lock +0 -1663
  346. /package/.next/static/{ZxdmFd_iOEELuA2Km4Q5t → tRPXkJdGLR6a0skqvMgQa}/_buildManifest.js +0 -0
  347. /package/.next/static/{ZxdmFd_iOEELuA2Km4Q5t → tRPXkJdGLR6a0skqvMgQa}/_clientMiddlewareManifest.js +0 -0
  348. /package/.next/static/{ZxdmFd_iOEELuA2Km4Q5t → tRPXkJdGLR6a0skqvMgQa}/_ssgManifest.js +0 -0
@@ -16,12 +16,6 @@ function hashSecret(secret: string) {
16
16
  return createHash('sha256').update(`anet-dashboard:${secret}`).digest('hex');
17
17
  }
18
18
 
19
- // Constant-time string compare. Callers always pass sha256 hex digests
20
- // (see hashSecret / verifyDashboardPassword), never raw secrets — two wins:
21
- // the inputs are always 64 chars so the length guard never short-circuits
22
- // on real data, and any residual timing signal leaks bytes of the *hash*,
23
- // not the password. The length check is required because timingSafeEqual
24
- // throws on mismatched buffer lengths.
25
19
  function safeEqual(a: string, b: string) {
26
20
  const aBuffer = Buffer.from(a);
27
21
  const bBuffer = Buffer.from(b);
@@ -55,12 +49,6 @@ export async function verifyDashboardPassword(password: string) {
55
49
  return expectedPassword.length > 0 && safeEqual(hashSecret(password), hashSecret(expectedPassword));
56
50
  }
57
51
 
58
- // The session cookie carries one of two valid formats:
59
- // • "v3:<token>" — a hub-issued token (atok_/utok_/ntok_). The dashboard
60
- // is a thin proxy, so getV3UserToken forwards this as the Bearer for hub
61
- // calls; here we only sanity-check its shape (real auth is the hub's).
62
- // • a bare password hash — the legacy single-password login, compared in
63
- // constant time against the expected hash.
64
52
  export async function verifyDashboardSession() {
65
53
  const cookieStore = await cookies();
66
54
  const sessionValue = cookieStore.get(DASHBOARD_SESSION_COOKIE)?.value || '';
package/app/lib/hooks.ts CHANGED
@@ -11,10 +11,6 @@ const fetcher = async (url: string) => {
11
11
  return res.json();
12
12
  };
13
13
 
14
- // 5s refresh keeps the fleet view live-ish without hammering the hub;
15
- // 3s dedup collapses the burst of revalidations when several components
16
- // mount or the tab refocuses at once, so one shared key = one in-flight
17
- // request rather than N. (dedup < refresh so periodic refreshes still fire.)
18
14
  const SWR_OPTIONS = { refreshInterval: 5000, dedupingInterval: 3000 };
19
15
 
20
16
  /** Append network_id to URL if set */
@@ -34,6 +30,28 @@ export function useSessions() {
34
30
  return { sessions: data?.sessions || [], hint: data?._hint, error, isLoading };
35
31
  }
36
32
 
33
+ // RFC-027 PR2 — alias → lifecycle_state map sourced from /api/nodes
34
+ // (commhub-server preview.12+). /api/status reads from `sessions` which
35
+ // doesn't carry lifecycle_state; /api/nodes does. Cheap secondary
36
+ // fetch, same SWR cadence as useSessions; merged client-side by alias.
37
+ // Absent alias → caller defaults to 'active'.
38
+ interface NodesResp { nodes?: Array<{ alias?: string; node_id?: string; lifecycle_state?: string | null }>; }
39
+ export function useNodeLifecycle() {
40
+ const { networkId } = useNetworkId();
41
+ const { data, error } = useSWR<NodesResp>(
42
+ withNetwork('/api/hub/nodes', networkId),
43
+ fetcher,
44
+ SWR_OPTIONS,
45
+ );
46
+ const lifecycleByAlias: Record<string, string> = {};
47
+ const nodeIdByAlias: Record<string, string> = {};
48
+ for (const n of data?.nodes ?? []) {
49
+ if (n.alias && typeof n.lifecycle_state === 'string') lifecycleByAlias[n.alias] = n.lifecycle_state;
50
+ if (n.alias && typeof n.node_id === 'string') nodeIdByAlias[n.alias] = n.node_id;
51
+ }
52
+ return { lifecycleByAlias, nodeIdByAlias, error };
53
+ }
54
+
37
55
  export function useHealth() {
38
56
  const { data, error } = useSWR<Health>('/api/hub/health', fetcher, SWR_OPTIONS);
39
57
  return { health: data || null, error };
package/app/lib/hub.ts CHANGED
@@ -6,6 +6,10 @@ function getHubUrl() {
6
6
 
7
7
  export const HUB_URL = getHubUrl();
8
8
 
9
+ export function hubHeaders(): Record<string, string> {
10
+ return {};
11
+ }
12
+
9
13
  /**
10
14
  * Fetch from CommHub. Uses the browser session's V3 user token when available.
11
15
  * Dashboard is a thin proxy and does not fall back to a service/master token.
@@ -9,12 +9,6 @@ interface NetworkContextType {
9
9
 
10
10
  const NetworkContext = createContext<NetworkContextType>({ networkId: '', setNetworkId: () => {} });
11
11
 
12
- // Holds the network selected in UserBar. Empty string is the sentinel for
13
- // "no filter / global view": the withNetwork() helpers (hooks.ts,
14
- // chat-unread.ts) omit the network_id query param when it's '', so every
15
- // SWR key falls back to the unscoped hub endpoint. Persisted in
16
- // sessionStorage so a reload keeps the selection (per-tab, like the auth
17
- // session — not shared across tabs).
18
12
  export function NetworkProvider({ children }: { children: ReactNode }) {
19
13
  const [networkId, setNetworkId] = useState('');
20
14
 
@@ -1,17 +1,6 @@
1
1
  /**
2
2
  * Simple in-memory rate limiter for login attempts.
3
- * Tracks by IP, allows MAX_ATTEMPTS per WINDOW_MS.
4
- *
5
- * Fixed-window, not sliding: the window opens on the first attempt and
6
- * the whole counter resets once `resetAt` passes (a burst right after a
7
- * reset can briefly allow up to 2×MAX over the boundary — acceptable for
8
- * a login throttle, not a billing meter).
9
- *
10
- * State lives in this process's heap, so the limit is per-instance: the
11
- * dashboard runs as a single `next start` process, so one shared counter.
12
- * Behind multiple replicas the effective limit multiplies by replica
13
- * count and an attacker could be balanced across them — move to a shared
14
- * store (Redis) before scaling out.
3
+ * Tracks by IP, allows `max` attempts per `windowMs`.
15
4
  */
16
5
  const attempts = new Map<string, { count: number; resetAt: number }>();
17
6
 
@@ -35,10 +24,7 @@ export function checkRateLimit(ip: string): { allowed: boolean; remaining: numbe
35
24
  return { allowed: true, remaining: MAX_ATTEMPTS - entry.count, retryAfterMs: 0 };
36
25
  }
37
26
 
38
- // Cleanup stale entries every 5 minutes. Expired windows are already
39
- // reset lazily on the next checkRateLimit for that IP (the `now >
40
- // resetAt` branch above), so this sweep only reclaims memory for IPs
41
- // that never come back — it isn't load-bearing for correctness.
27
+ // Cleanup stale entries every 5 minutes
42
28
  if (typeof setInterval !== 'undefined') {
43
29
  setInterval(() => {
44
30
  const now = Date.now();
package/app/node/page.tsx CHANGED
@@ -35,6 +35,15 @@ interface SessionDetail {
35
35
  version: string;
36
36
  }
37
37
 
38
+ interface Message {
39
+ id: string;
40
+ content: string;
41
+ from_session: string;
42
+ priority: string;
43
+ created_at: string;
44
+ type: string;
45
+ }
46
+
38
47
  function TmuxViewer({ tmuxName }: { tmuxName: string }) {
39
48
  const [output, setOutput] = useState('');
40
49
  const [loading, setLoading] = useState(false);
@@ -80,6 +89,7 @@ function NodeDetailContent() {
80
89
  const searchParams = useSearchParams();
81
90
  const alias = searchParams.get('alias') || '';
82
91
  const [session, setSession] = useState<SessionDetail | null>(null);
92
+ const [inbox, setInbox] = useState<Message[]>([]);
83
93
  const [sse, setSse] = useState(0);
84
94
  const [error, setError] = useState('');
85
95
  const [sendMsg, setSendMsg] = useState('');
@@ -91,6 +101,7 @@ function NodeDetailContent() {
91
101
  const res = await fetch(`/api/hub/session?alias=${encodeURIComponent(alias)}`);
92
102
  const data = await res.json();
93
103
  if (data.session) setSession(data.session);
104
+ if (data.inbox) setInbox(data.inbox);
94
105
  setSse(data.sse || 0);
95
106
  setError('');
96
107
  } catch (e: unknown) {
@@ -349,7 +360,7 @@ function EventsTimeline({ events, loading }: { events: Array<{ id: number; event
349
360
  {/* Vertical line */}
350
361
  <div className="absolute left-[9px] top-2 bottom-2 w-0.5 bg-[#1c1c1f]" />
351
362
 
352
- {taskEvents.map((e) => {
363
+ {taskEvents.map((e, i) => {
353
364
  const cfg = EVENT_COLORS[e.to_status] || EVENT_COLORS.created;
354
365
  return (
355
366
  <div key={e.id} className="relative pb-4 last:pb-0">
@@ -2,9 +2,11 @@
2
2
 
3
3
  import { useState } from 'react';
4
4
  import { timeAgo } from '../components/utils';
5
- import { useSessions, useHealth } from '../lib/hooks';
5
+ import { useSessions, useHealth, useNodeLifecycle } from '../lib/hooks';
6
+ import { useSWRConfig } from 'swr';
6
7
  import { TaskChatPanel } from '../components/TaskChatPanel';
7
8
  import { CreateNodeWizard } from '../components/CreateNodeWizard';
9
+ import { NodeLifecycleMenu } from '../components/NodeLifecycleMenu';
8
10
  import { EmptyState, NodesEmptyState } from '../components/EmptyState';
9
11
  import { AliasAvatar } from '../components/AliasAvatar';
10
12
  import { useCollapsibleSearch } from '../components/CollapsibleSearch';
@@ -26,7 +28,16 @@ type SessionRow = Session & { online: boolean };
26
28
  export default function NodesPage() {
27
29
  const { sessions, isLoading: loading } = useSessions();
28
30
  const { health } = useHealth();
31
+ const { lifecycleByAlias, nodeIdByAlias } = useNodeLifecycle();
29
32
  const { hasUnread } = useChatUnread();
33
+ const { mutate } = useSWRConfig();
34
+ // RFC-027 PR2 — after a stop/delete/restart dispatch lands, refresh
35
+ // /api/hub/nodes (lifecycle_state) AND /api/hub/status (sessions).
36
+ // Both feed the menu's state-aware items; otherwise menu stays
37
+ // stale until next 5s SWR poll.
38
+ const refreshNodes = () => {
39
+ mutate((k: unknown) => typeof k === 'string' && (k.startsWith('/api/hub/nodes') || k.startsWith('/api/hub/status')));
40
+ };
30
41
  const sseMap = health?.sse_sessions || {};
31
42
  // SSE keys are `network_id:alias` since server v0.7+. Look up with the
32
43
  // composite key first, fall back to alias-only for legacy hubs.
@@ -215,6 +226,16 @@ export default function NodesPage() {
215
226
  </div>
216
227
  </div>
217
228
  <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>
229
+ {/* RFC-027 PR2 — per-node ⋮ lifecycle menu. The button stopsPropagation
230
+ internally so it doesn't open chat. lifecycleByAlias absent → 'active'
231
+ default, menu renders normal stop/delete options. */}
232
+ <NodeLifecycleMenu
233
+ nodeId={nodeIdByAlias[s.alias] || s.node_id || s.alias}
234
+ alias={s.alias}
235
+ lifecycleState={lifecycleByAlias[s.alias]}
236
+ networkId={s.network_id || null}
237
+ onCompleted={refreshNodes}
238
+ />
218
239
  </div>
219
240
 
220
241
  <div className="mt-3 rounded-lg border border-[#1c1c1f] bg-[#0e0e10] px-3 py-2 text-xs">
@@ -282,7 +303,18 @@ export default function NodesPage() {
282
303
  <span className="truncate">{s.agent || '--'}<span className="text-gray-700 mx-1.5">·</span>{shortServer(s.server)}</span>
283
304
  </div>
284
305
  <div className="col-span-4 truncate text-xs text-gray-500" title={s.task || ''}>{s.task || '--'}</div>
285
- <div className="col-span-1 text-xs text-gray-500">{timeAgo(s.last_seen_at || s.updated_at)}</div>
306
+ <div className="col-span-1 flex items-center justify-between gap-2 text-xs text-gray-500">
307
+ <span className="truncate">{timeAgo(s.last_seen_at || s.updated_at)}</span>
308
+ {/* RFC-027 PR2 ⋮ lifecycle menu — desktop list. Defaults
309
+ to 'active' when lifecycleByAlias absent. */}
310
+ <NodeLifecycleMenu
311
+ nodeId={nodeIdByAlias[s.alias] || s.node_id || s.alias}
312
+ alias={s.alias}
313
+ lifecycleState={lifecycleByAlias[s.alias]}
314
+ networkId={s.network_id || null}
315
+ onCompleted={refreshNodes}
316
+ />
317
+ </div>
286
318
  </div>
287
319
  {/* R7 of #190: mobile node row was ~340px tall × ~150
288
320
  rows = the 51k page. Wins this round, in priority
@@ -307,6 +339,14 @@ export default function NodesPage() {
307
339
  <span className={`shrink-0 text-xs px-2 py-0.5 rounded-md border ${STATUS_COLORS[statusKey] || STATUS_COLORS.offline}`}>
308
340
  {statusKey}
309
341
  </span>
342
+ {/* RFC-027 PR2 ⋮ lifecycle menu — mobile list. */}
343
+ <NodeLifecycleMenu
344
+ nodeId={nodeIdByAlias[s.alias] || s.node_id || s.alias}
345
+ alias={s.alias}
346
+ lifecycleState={lifecycleByAlias[s.alias]}
347
+ networkId={s.network_id || null}
348
+ onCompleted={refreshNodes}
349
+ />
310
350
  </div>
311
351
  {s.task && <div className="truncate text-xs text-gray-500">{s.task}</div>}
312
352
  </div>
package/app/page.tsx CHANGED
@@ -256,6 +256,7 @@ export default function Dashboard() {
256
256
  <CommandCenter
257
257
  tabs={cmd.tabs}
258
258
  activeTab={cmd.activeTab}
259
+ onOpenTab={cmd.openTab}
259
260
  onCloseTab={cmd.closeTab}
260
261
  onSetActive={cmd.setActiveTab}
261
262
  onClose={cmd.closeAll}
@@ -0,0 +1,182 @@
1
+ 'use client';
2
+
3
+ import { useCallback, useEffect, useState } from 'react';
4
+ import { EmptyState } from '../components/EmptyState';
5
+ import { ProviderFormModal, type ProviderDraft } from '../components/ProviderFormModal';
6
+ import { ReachabilityMatrix } from '../components/ReachabilityMatrix';
7
+
8
+ /**
9
+ * Model providers (RFC-028 P1 — CRUD). Lists providers from
10
+ * /api/anet/providers, with create/edit (ProviderFormModal), an enabled
11
+ * toggle, soft-delete (enabled:0), and a per-row "Test" placeholder for the
12
+ * P2 connectivity matrix. Keys are write-only — the list only shows a
13
+ * key/no-key indicator, never a value.
14
+ *
15
+ * When the hub predates RFC-028 (#308 not merged / hub not upgraded) the API
16
+ * returns `unconfirmed` — we surface an honest banner instead of faking data.
17
+ * Set MOCK_PROVIDERS=1 on the dashboard server to preview the populated UI.
18
+ */
19
+
20
+ interface Provider {
21
+ provider_id?: string;
22
+ name: string;
23
+ type: string;
24
+ base_url: string;
25
+ models?: string[];
26
+ enabled?: boolean;
27
+ hasKey?: boolean;
28
+ }
29
+
30
+ function hostOf(url: string) {
31
+ try { return new URL(url).host; } catch { return url; }
32
+ }
33
+
34
+ // Humanize the raw vendor enum for the row badge so it matches the create
35
+ // modal's wording. A DeepSeek/MiniMax row tagged bare "anthropic" reads as
36
+ // wrong — they're Anthropic-*compatible* endpoints, not Anthropic itself.
37
+ const TYPE_LABELS: Record<string, string> = {
38
+ anthropic: 'Anthropic 兼容',
39
+ 'openai-compatible': 'OpenAI 兼容',
40
+ grok: 'Grok',
41
+ custom: 'Custom',
42
+ };
43
+ const typeLabel = (t: string) => TYPE_LABELS[t] || t;
44
+
45
+ export default function ProvidersPage() {
46
+ const [providers, setProviders] = useState<Provider[]>([]);
47
+ const [loading, setLoading] = useState(true);
48
+ const [unconfirmed, setUnconfirmed] = useState<string | null>(null);
49
+ const [mock, setMock] = useState(false);
50
+ const [editing, setEditing] = useState<ProviderDraft | null>(null);
51
+ const [showForm, setShowForm] = useState(false);
52
+ const [expandedId, setExpandedId] = useState<string | null>(null);
53
+
54
+ const fetchProviders = useCallback(async () => {
55
+ try {
56
+ const res = await fetch('/api/anet/providers', { cache: 'no-store' });
57
+ const data = await res.json().catch(() => ({}));
58
+ setProviders(Array.isArray(data?.providers) ? data.providers : []);
59
+ setUnconfirmed(data?.unconfirmed ? (data?.error || 'backend not available') : null);
60
+ setMock(!!data?.mock);
61
+ } catch { setUnconfirmed('request failed'); } finally { setLoading(false); }
62
+ }, []);
63
+
64
+ useEffect(() => { fetchProviders(); }, [fetchProviders]);
65
+
66
+ const openCreate = () => { setEditing(null); setShowForm(true); };
67
+ // Edit / enable-disable wired to update_provider (#317). vendor + key are
68
+ // immutable on the backend, so the edit form patches name/base_url/models
69
+ // only (changing the key is a separate secret-first flow).
70
+ const openEdit = (p: Provider) => {
71
+ setEditing({ provider_id: p.provider_id, name: p.name, type: p.type, base_url: p.base_url, models: p.models || [], enabled: p.enabled ?? true, hasKey: p.hasKey });
72
+ setShowForm(true);
73
+ };
74
+ const toggleEnabled = async (p: Provider) => {
75
+ setProviders(prev => prev.map(x => (x.provider_id || x.name) === (p.provider_id || p.name) ? { ...x, enabled: !x.enabled } : x)); // optimistic
76
+ await fetch('/api/anet/providers', {
77
+ method: 'POST', headers: { 'Content-Type': 'application/json' },
78
+ body: JSON.stringify({ provider_id: p.provider_id, enabled: !p.enabled }),
79
+ }).catch(() => {});
80
+ fetchProviders();
81
+ };
82
+
83
+ return (
84
+ <div className="min-h-screen bg-[#0b0b0d] text-gray-100 p-4 sm:p-6">
85
+ <div className="flex items-center gap-4 mb-6">
86
+ <h1 className="text-2xl font-bold text-white lg:ml-0 ml-10">Model Providers</h1>
87
+ {mock && <span className="text-[10px] px-2 py-0.5 rounded-full border border-amber-500/30 bg-amber-500/5 text-amber-300">preview fixture</span>}
88
+ <button
89
+ onClick={openCreate}
90
+ className="ml-auto inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap rounded-md bg-cyan-600 px-3 py-1.5 text-sm font-medium text-white hover:bg-cyan-500"
91
+ >
92
+ <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" aria-hidden><path d="M12 5v14M5 12h14" /></svg>
93
+ 新增供应商
94
+ </button>
95
+ </div>
96
+
97
+ <div className="max-w-3xl space-y-4">
98
+ <p className="text-sm text-gray-500">
99
+ Configure model providers and per-server reachability. API keys are stored write-only in the secret vault and never displayed.
100
+ </p>
101
+
102
+ {unconfirmed && (
103
+ <div className="rounded-xl border border-amber-500/30 bg-amber-500/5 px-4 py-3 text-xs text-amber-300">
104
+ 供应商后端(RFC-028)尚未在当前 hub 就绪:{unconfirmed}。UI 已就位;待 #308 合并 + hub 升级后接真后端。
105
+ <span className="text-amber-400/70">(开发预览可设 MOCK_PROVIDERS=1 看填充态。)</span>
106
+ </div>
107
+ )}
108
+
109
+ <section className="bg-[#161618] border border-[#26262b] rounded-xl p-5">
110
+ {loading ? (
111
+ <div className="animate-pulse space-y-2">{[1, 2, 3].map(i => <div key={i} className="h-14 bg-gray-800/20 rounded" />)}</div>
112
+ ) : providers.length === 0 ? (
113
+ <EmptyState
114
+ variant="generic"
115
+ title="No model providers"
116
+ sub="Add a provider to register its models and test per-server reachability."
117
+ cta={{ label: '新增供应商', onClick: openCreate }}
118
+ />
119
+ ) : (
120
+ <div className="space-y-2">
121
+ {providers.map(p => {
122
+ const rid = p.provider_id || p.name;
123
+ const isOpen = expandedId === rid;
124
+ return (
125
+ <div key={rid} className={`rounded-lg border border-[#1c1c1f] bg-[#0e0e10] ${p.enabled ? '' : 'opacity-60'}`} data-provider={p.name}>
126
+ <div className="flex flex-col gap-2 px-3 py-2.5 sm:flex-row sm:items-center sm:gap-3">
127
+ <div className="flex min-w-0 flex-1 items-center gap-3">
128
+ <span className={`inline-block h-2 w-2 shrink-0 rounded-full ${p.enabled ? 'bg-green-500' : 'bg-gray-600'}`} title={p.enabled ? 'enabled' : 'disabled'} />
129
+ <div className="min-w-0 flex-1">
130
+ <div className="flex flex-wrap items-center gap-x-2 gap-y-1">
131
+ <span className="text-sm font-semibold text-white truncate">{p.name}</span>
132
+ <span className="text-[10px] px-1.5 py-0.5 rounded border border-gray-600/30 text-gray-400 shrink-0" title={p.type}>{typeLabel(p.type)}</span>
133
+ {p.hasKey
134
+ ? <span className="text-[10px] px-1.5 py-0.5 rounded border border-green-500/20 bg-green-500/5 text-green-400 shrink-0">key set</span>
135
+ : <span className="text-[10px] px-1.5 py-0.5 rounded border border-gray-600/20 text-gray-500 shrink-0">no key</span>}
136
+ </div>
137
+ <div className="text-[11px] text-gray-500 truncate">
138
+ {hostOf(p.base_url)} · {(p.models?.length || 0)} model{(p.models?.length || 0) === 1 ? '' : 's'}
139
+ </div>
140
+ </div>
141
+ </div>
142
+ <div className="flex w-full shrink-0 items-center justify-end gap-1.5 border-t border-[#1c1c1f] pt-2 sm:w-auto sm:justify-normal sm:self-auto sm:border-t-0 sm:pt-0">
143
+ <button
144
+ type="button"
145
+ onClick={() => setExpandedId(isOpen ? null : rid)}
146
+ disabled={!p.enabled}
147
+ title={p.enabled ? '连通性测试(模型 × 服务器 可达矩阵)' : '供应商已停用,启用后可测连通性'}
148
+ className={`rounded border px-2 py-1 text-[11px] transition-colors ${!p.enabled ? 'border-[#26262b] text-gray-600 cursor-not-allowed' : isOpen ? 'border-cyan-500/40 bg-cyan-500/10 text-cyan-300' : 'border-[#26262b] text-gray-300 hover:border-cyan-500/30 hover:text-cyan-300'}`}
149
+ >Test{isOpen ? ' ▾' : ''}</button>
150
+ <button type="button" onClick={() => openEdit(p)} title="编辑(名称 / base_url / 模型)" className="rounded border border-[#26262b] px-2 py-1 text-[11px] text-gray-300 hover:border-cyan-500/30 hover:text-cyan-300">Edit</button>
151
+ <button type="button" onClick={() => toggleEnabled(p)} title={p.enabled ? '停用(软删,可重新启用)' : '启用'} className="rounded border border-[#26262b] px-2 py-1 text-[11px] text-gray-400 hover:text-gray-200">
152
+ {p.enabled ? 'Disable' : 'Enable'}
153
+ </button>
154
+ </div>
155
+ </div>
156
+ {isOpen && (
157
+ (p.models?.length || 0) > 0
158
+ ? <ReachabilityMatrix providerId={p.provider_id} models={p.models || []} />
159
+ : <div className="border-t border-[#1c1c1f] px-3 py-3 text-[11px] text-gray-500">该供应商未配置模型——先 Edit 添加模型再测可达性。</div>
160
+ )}
161
+ </div>
162
+ );
163
+ })}
164
+ </div>
165
+ )}
166
+ </section>
167
+
168
+ <p className="text-[11px] text-gray-600">
169
+ 按 <span className="text-gray-400">Test</span> 展开「模型 × 服务器」连通性矩阵(对每个模型实时探测可达性)。创建节点向导的模型下拉将从此处的 registry 拉取(即将支持)。
170
+ </p>
171
+ </div>
172
+
173
+ {showForm && (
174
+ <ProviderFormModal
175
+ initial={editing}
176
+ onClose={() => setShowForm(false)}
177
+ onSaved={fetchProviders}
178
+ />
179
+ )}
180
+ </div>
181
+ );
182
+ }
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { useState } from 'react';
3
+ import { useEffect, useState, useCallback } from 'react';
4
4
  import Link from 'next/link';
5
5
  import { timeAgo } from '../../components/utils';
6
6
  import { EmptyState } from '../../components/EmptyState';
@@ -269,6 +269,11 @@ export default function SettingsPage() {
269
269
  <p className="text-xs text-gray-500 mt-2">Create, manage, and delete agent networks.</p>
270
270
  <span className="text-xs text-cyan-400 mt-3 inline-block">Manage &rarr;</span>
271
271
  </Link>
272
+ <Link href="/settings/providers" className="bg-[#161618] border border-[#26262b] rounded-xl p-5 hover:border-cyan-500/30 transition-colors">
273
+ <h2 className="text-sm font-semibold text-gray-300">Model Providers</h2>
274
+ <p className="text-xs text-gray-500 mt-2">Configure model providers and per-server reachability.</p>
275
+ <span className="text-xs text-cyan-400 mt-3 inline-block">Manage &rarr;</span>
276
+ </Link>
272
277
  <Link href="/messages" className="bg-[#161618] border border-[#26262b] rounded-xl p-5 hover:border-cyan-500/30 transition-colors">
273
278
  <h2 className="text-sm font-semibold text-gray-300">Messages</h2>
274
279
  <p className="text-xs text-gray-500 mt-2">Global timeline of CommHub messages across all agents.</p>
@@ -19,6 +19,7 @@ interface TimelineStep {
19
19
  }
20
20
 
21
21
  function Timeline({ steps }: { steps: TimelineStep[] }) {
22
+ const activeCount = steps.filter(s => s.time).length;
22
23
 
23
24
  return (
24
25
  <div className="relative">
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { useEffect, useState, useCallback, Suspense } from 'react';
4
4
  import { useSearchParams } from 'next/navigation';
5
+ import Link from 'next/link';
5
6
  import { useNetworkId } from '../lib/network-context';
6
7
  import { TaskDrawer } from '../components/TaskDrawer';
7
8
  import { EmptyState } from '../components/EmptyState';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sleep2agi/agent-network-dashboard",
3
- "version": "0.6.3-preview.1",
3
+ "version": "0.6.3-preview.10",
4
4
  "description": "Agent Network Dashboard — Web UI for managing AI Agent networks",
5
5
  "main": "apps/desktop/electron/main.cjs",
6
6
  "scripts": {
@@ -1 +0,0 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,3479,e=>{"use strict";var a=e.i(59746);e.s(["previewContent",0,function(e){return e&&e.replace(/!\[([^\]]*)\]\([^)]*\)/g,"$1").replace(/\[([^\]]+)\]\([^)]*\)/g,"$1").replace(/`([^`]+)`/g,"$1").replace(/\s+/g," ").trim()||"--"},"timeAgo",0,function(e){return(0,a.relativeAgo)(e)??"--"}])},46228,e=>{"use strict";var a=e.i(22381);let t=[180,200,220,270,300,330,30,90];function r(e){let a=0;for(let t=0;t<e.length;t++)a=31*a+e.charCodeAt(t)>>>0;let r=t[a%t.length];return{bg:`hsl(${r} 55% 22%)`,ring:`hsl(${r} 60% 45%)`,text:`hsl(${r} 80% 78%)`}}function s(e){return e?(e.trim().match(/[\p{L}\p{N}]/u)?.[0]||e.trim()[0]||"·").toUpperCase():"·"}e.s(["AliasAvatar",0,function({alias:e,size:t=28,className:l=""}){if(/\bgrok\b|grok-build|grok测试员|grok-demo/i.test(e))return(0,a.jsx)("span",{className:`anet-alias-avatar inline-flex items-center justify-center rounded-full border border-emerald-500/45 bg-emerald-950/70 shrink-0 ${l}`,style:{width:t,height:t,backgroundImage:"url(/vendors/grok.svg)",backgroundPosition:"center",backgroundRepeat:"no-repeat",backgroundSize:"68% 68%"},title:e,"aria-hidden":!0});let n=r(e),i=Math.max(9,Math.round(.42*t));return(0,a.jsx)("span",{className:`anet-alias-avatar inline-flex items-center justify-center rounded-full border shrink-0 font-semibold ${l}`,style:{width:t,height:t,fontSize:i,backgroundColor:n.bg,borderColor:n.ring,color:n.text},title:e,"aria-hidden":!0,children:s(e)})},"aliasAvatarColors",0,r,"aliasInitial",0,s])},98025,e=>{"use strict";e.s(["SESSION_STATUS_CHIP_CLASS",0,{working:"bg-green-500/10 text-green-300 border-green-500/20",idle:"bg-gray-500/10 text-gray-300 border-gray-500/20",blocked:"bg-yellow-500/10 text-yellow-300 border-yellow-500/20",error:"bg-red-500/10 text-red-300 border-red-500/20",offline:"bg-gray-500/10 text-gray-500 border-gray-500/20"},"SESSION_STATUS_TEXT_CLASS",0,{working:"text-green-400",idle:"text-gray-400",blocked:"text-yellow-400",error:"text-red-400",offline:"text-gray-500"},"STATUS_BAR_CLASS",0,{created:"bg-gray-500",delivered:"bg-gray-400",acked:"bg-gray-300",running:"bg-green-500",replied:"bg-gray-400",closed:"bg-gray-600",failed:"bg-red-500",cancelled:"bg-gray-600",expired:"bg-gray-600"},"STATUS_CHIP_CLASS",0,{created:"bg-gray-500/10 text-gray-400 border-gray-500/20",delivered:"bg-gray-500/10 text-gray-300 border-gray-500/20",acked:"bg-gray-500/10 text-gray-300 border-gray-500/20",running:"bg-green-500/10 text-green-300 border-green-500/20",replied:"bg-gray-500/10 text-gray-300 border-gray-500/20",closed:"bg-gray-500/10 text-gray-500 border-gray-500/20",failed:"bg-red-500/10 text-red-300 border-red-500/20",cancelled:"bg-gray-500/10 text-gray-500 border-gray-500/20",expired:"bg-gray-500/10 text-gray-500 border-gray-500/20"},"STATUS_DOT_HEX",0,{created:"#9ca3af",delivered:"#9ca3af",acked:"#9ca3af",running:"#4ade80",replied:"#9ca3af",closed:"#6b7280",failed:"#f87171",cancelled:"#6b7280",expired:"#6b7280"},"TASK_STATUSES",0,["created","delivered","acked","running","replied","closed","failed","cancelled","expired"]])},51868,e=>{"use strict";var a=e.i(22381),t=e.i(23910),r=e.i(56058),s=e.i(56839),l=e.i(43058),n=e.i(3479),i=e.i(46228),d=e.i(98025),o=e.i(38263);function c({tmuxName:e}){let[r,s]=(0,t.useState)(""),[l,n]=(0,t.useState)(!1),[i,d]=(0,t.useState)(!1),o=async()=>{n(!0);try{let a=await fetch(`/api/hub/tmux?name=${encodeURIComponent(e)}`),t=await a.json();s(t.output||t.error||"No output")}catch{s("Failed to fetch")}n(!1)};return(0,a.jsxs)("div",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-4",children:[(0,a.jsxs)("div",{className:"flex items-center justify-between mb-2",children:[(0,a.jsxs)("h2",{className:"text-sm font-semibold text-gray-300",children:["Terminal (",e,")"]}),(0,a.jsxs)("div",{className:"flex gap-2",children:[(0,a.jsx)("button",{onClick:o,disabled:l,className:"text-xs text-cyan-400 hover:text-cyan-300 disabled:text-gray-600",children:l?"Loading...":"Capture"}),r&&(0,a.jsx)("button",{onClick:()=>d(!i),className:"text-xs text-gray-500 hover:text-gray-300",children:i?"Collapse":"Expand"})]})]}),r&&(0,a.jsx)("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 ${i?"max-h-96":"max-h-32"} overflow-y-auto`,children:r}),!r&&(0,a.jsx)("p",{className:"text-xs text-gray-600",children:"Click Capture to view terminal output"})]})}function x(){let e=(0,r.useSearchParams)().get("alias")||"",[l,n]=(0,t.useState)(null),[o,c]=(0,t.useState)(0),[x,b]=(0,t.useState)(""),[h,u]=(0,t.useState)(""),[m,p]=(0,t.useState)(!1),y=(0,t.useCallback)(async()=>{if(e)try{let a=await fetch(`/api/hub/session?alias=${encodeURIComponent(e)}`),t=await a.json();t.session&&n(t.session),c(t.sse||0),b("")}catch(e){b(e instanceof Error?e.message:"fetch failed")}},[e]);(0,t.useEffect)(()=>{y();let e=setInterval(y,5e3);return()=>clearInterval(e)},[y]);let[f,v]=(0,t.useState)(""),j=async()=>{if(h.trim()&&e){p(!0),v("");try{let a=await fetch("/api/hub/send",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({alias:e,task:h})}),t=await a.json();t.ok?(u(""),setTimeout(y,2e3)):v(t.error||"Send failed")}catch(e){v(e instanceof Error?e.message:"Send failed")}p(!1)}};if(!e)return(0,a.jsx)("div",{className:"min-h-screen bg-[#0b0b0d] text-gray-100 p-6 flex items-center justify-center",children:(0,a.jsxs)("p",{className:"text-gray-500",children:["No alias specified. ",(0,a.jsx)(s.default,{href:"/",className:"text-blue-400 hover:underline",children:"Back to dashboard"})]})});let S=d.SESSION_STATUS_TEXT_CLASS[l?.status||""]||d.SESSION_STATUS_TEXT_CLASS.offline;return(0,a.jsxs)("div",{className:"min-h-screen bg-[#0b0b0d] text-gray-100 p-4 sm:p-6",children:[(0,a.jsxs)("div",{className:"flex items-center gap-3 mb-6 lg:ml-0 ml-10",children:[(0,a.jsx)(s.default,{href:"/nodes",className:"text-gray-500 hover:text-gray-300 text-sm shrink-0",children:"← Nodes"}),(0,a.jsx)(i.AliasAvatar,{alias:e,size:32}),(0,a.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,a.jsxs)("div",{className:"flex items-center gap-2",children:[(0,a.jsx)("h1",{className:"text-xl sm:text-2xl font-bold text-white truncate",children:e}),(0,a.jsx)("span",{className:`inline-block w-1.5 h-1.5 rounded-full shrink-0 ${o>0?l?.status==="working"?"bg-green-500 animate-pulse":"bg-emerald-400":"bg-gray-500"}`}),(0,a.jsx)("span",{className:`text-[10px] uppercase tracking-wide font-semibold ${S}`,children:l?.status||"unknown"})]}),l?.agent&&(0,a.jsxs)("div",{className:"text-xs text-gray-500 truncate",children:[l.agent,l.server?(0,a.jsxs)(a.Fragment,{children:[" ",(0,a.jsx)("span",{className:"text-gray-700 mx-1",children:"·"})," ",l.server]}):null]})]})]}),x&&(0,a.jsx)("div",{className:"bg-red-900/20 border border-red-800/40 text-red-300 px-4 py-2 rounded-lg mb-6 text-sm",children:x}),(0,a.jsx)(g,{alias:e,session:l,sse:o,sendMsg:h,setSendMsg:u,sending:m,sendTask:j,sendError:f})]})}function g({alias:e,session:r,sse:s,sendMsg:n,setSendMsg:i,sending:d,sendTask:x,sendError:b}){let[u,m]=(0,t.useState)("chat"),{hasUnread:p}=(0,o.useChatUnread)(),[y,f]=(0,t.useState)([]),[v,j]=(0,t.useState)(!1),S=p(e);return(0,t.useEffect)(()=>{"events"!==u||v||fetch("/api/hub/task-events?limit=50").then(e=>e.json()).then(e=>{f(e.events||[]),j(!0)}).catch(()=>j(!0))},[u,v]),(0,a.jsxs)("div",{className:"bg-[#111113] border border-[#26262b] rounded-xl overflow-hidden h-[calc(100vh-140px)] flex flex-col",children:[(0,a.jsx)("div",{className:"flex border-b border-[#26262b] bg-[#0e0e10] shrink-0",children:[{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"},{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"},{id:"info",label:"Info",icon:"M12 21a9 9 0 100-18 9 9 0 000 18z M12 8h.01 M11 12h1v4h1"}].map(e=>(0,a.jsxs)("button",{onClick:()=>m(e.id),className:`flex items-center gap-2 px-5 py-3 text-sm font-medium border-b-2 transition-colors ${u===e.id?"border-cyan-400 text-cyan-300":"border-transparent text-gray-500 hover:text-gray-300"}`,children:[(0,a.jsx)("svg",{className:"w-4 h-4 shrink-0",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",children:(0,a.jsx)("path",{d:e.icon})}),(0,a.jsxs)("span",{className:"relative inline-flex items-center gap-2",children:[e.label,"chat"===e.id&&S&&"chat"!==u&&(0,a.jsx)("span",{className:"inline-block h-2.5 w-2.5 rounded-full bg-red-500","aria-label":"Unread chat messages"})]})]},e.id))}),(0,a.jsxs)("div",{className:"flex-1 overflow-hidden",children:["chat"===u&&(0,a.jsx)(l.TaskChatPanel,{alias:e,onClose:()=>{},inline:!0}),"events"===u&&(0,a.jsx)(h,{events:y,loading:!v}),"info"===u&&(0,a.jsxs)("div",{className:"p-4 overflow-y-auto h-full space-y-4 max-w-2xl",children:[(0,a.jsxs)("div",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-4",children:[(0,a.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-3",children:"Node Info"}),(0,a.jsx)("div",{className:"space-y-2 text-xs",children:[{label:"Node ID",value:r?.node_id,alwaysShow:!0},{label:"Session ID",value:r?.session_id,alwaysShow:!0},{label:"Resume ID",value:r?.resume_id,alwaysShow:!0},{label:"Alias",value:r?.alias,alwaysShow:!0},{label:"Agent",value:r?.agent,alwaysShow:!0},{label:"Model",value:r?.model,alwaysShow:!0},{label:"Version",value:r?.version},{label:"Server",value:r?.server,alwaysShow:!0},{label:"Hostname",value:r?.hostname,alwaysShow:!0},{label:"IP",value:r?.ip,alwaysShow:!0},{label:"Project",value:r?.project_dir},{label:"Config",value:r?.config_path,alwaysShow:!0},{label:"Channels",value:r?.channels?.length?Array.isArray(r.channels)?r.channels.join(", "):r.channels:null,alwaysShow:!0},{label:"Tmux",value:r?.tmux_name},{label:"SSE",value:s>0?`Connected (${s})`:"Disconnected",alwaysShow:!0},{label:"Progress",value:r?.progress?`${r.progress}%`:null},{label:"Score",value:r?.score},{label:"Last Seen",value:r?.last_seen_at,alwaysShow:!0},{label:"Registered",value:r?.registered_at,alwaysShow:!0},{label:"Updated",value:r?.updated_at,alwaysShow:!0}].map(({label:e,value:t,alwaysShow:r})=>t||r?(0,a.jsxs)("div",{className:"flex justify-between gap-3",children:[(0,a.jsx)("span",{className:"text-gray-500 shrink-0",children:e}),(0,a.jsx)("span",{className:"text-gray-300 truncate max-w-[200px]",title:t?String(t):"--",children:t?String(t):"--"})]},e):null)})]}),r?.task&&(0,a.jsxs)("div",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-4",children:[(0,a.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-2",children:"Current Task"}),(0,a.jsx)("p",{className:"text-xs text-gray-400 whitespace-pre-wrap",children:r.task})]}),r?.output&&(0,a.jsxs)("div",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-4",children:[(0,a.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-2",children:"Last Output"}),(0,a.jsx)("p",{className:"text-xs text-gray-400 whitespace-pre-wrap max-h-48 overflow-y-auto",children:r.output})]}),(0,a.jsxs)("div",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-4",children:[(0,a.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-2",children:"Send Task"}),(0,a.jsxs)("div",{className:"flex gap-2",children:[(0,a.jsx)("input",{type:"text",value:n,onChange:e=>i(e.target.value),onKeyDown:e=>"Enter"===e.key&&x(),placeholder:`Send task to ${e}...`,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"}),(0,a.jsx)("button",{onClick:x,disabled:d||!n.trim(),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",children:d?"...":"Send"})]}),b&&(0,a.jsx)("div",{className:"mt-2 text-xs text-red-400",children:b})]}),r?.tmux_name&&(0,a.jsx)(c,{tmuxName:r.tmux_name})]})]})]})}let b={delivered:{dot:"bg-blue-400",line:"bg-blue-500/30",path:"M12 5v14 M5 12l7 7 7-7"},acked:{dot:"bg-yellow-400",line:"bg-yellow-500/30",path:"M20 6 9 17l-5-5"},running:{dot:"bg-green-400",line:"bg-green-500/30",path:"M13 2L4 14h6l-1 8 10-12h-6l1-8z"},replied:{dot:"bg-purple-400",line:"bg-purple-500/30",path:"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"},failed:{dot:"bg-red-400",line:"bg-red-500/30",path:"M18 6 6 18 M6 6l12 12"},created:{dot:"bg-gray-400",line:"bg-gray-500/30",path:"M12 5v14 M5 12h14"}};function h({events:e,loading:t}){if(t)return(0,a.jsx)("div",{className:"flex justify-center py-8",children:(0,a.jsx)("div",{className:"w-5 h-5 border-2 border-cyan-500/30 border-t-cyan-500 rounded-full animate-spin"})});if(0===e.length)return(0,a.jsx)("div",{className:"text-center py-12 text-gray-600 text-xs",children:"No task events yet"});let r=new Map;return e.forEach(e=>{let a=e.task_id||`ungrouped-${e.id}`,t=r.get(a)||[];t.push(e),r.set(a,t)}),(0,a.jsx)("div",{className:"p-4 overflow-y-auto h-full space-y-4",children:[...r.entries()].map(([e,t])=>(0,a.jsxs)("div",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-4",children:[(0,a.jsxs)("div",{className:"text-[10px] text-gray-600 mb-3 truncate",children:["Task: ",e.slice(0,20),"..."]}),(0,a.jsxs)("div",{className:"relative pl-6",children:[(0,a.jsx)("div",{className:"absolute left-[9px] top-2 bottom-2 w-0.5 bg-[#1c1c1f]"}),t.map(e=>{let t=b[e.to_status]||b.created;return(0,a.jsxs)("div",{className:"relative pb-4 last:pb-0",children:[(0,a.jsx)("div",{className:`absolute -left-6 top-0.5 w-[18px] h-[18px] rounded-full ${t.dot} flex items-center justify-center z-10 border-2 border-[#161618]`,children:(0,a.jsx)("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"#0e0e10",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":!0,children:(0,a.jsx)("path",{d:t.path})})}),(0,a.jsxs)("div",{className:"ml-2",children:[(0,a.jsxs)("div",{className:"flex items-center gap-2",children:[(0,a.jsx)("span",{className:`text-xs font-medium ${"failed"===e.to_status?"text-red-400":"replied"===e.to_status?"text-purple-400":"text-gray-300"}`,children:e.event_type}),e.from_status&&(0,a.jsxs)("span",{className:"text-[10px] text-gray-600",children:[e.from_status," → ",e.to_status]}),(0,a.jsx)("span",{className:"text-[10px] text-gray-600 ml-auto",children:(0,n.timeAgo)(e.created_at)})]}),e.detail&&(0,a.jsxs)("div",{className:"text-[11px] text-gray-500 mt-0.5 truncate",children:[e.detail.slice(0,50),e.detail.length>50?"...":""]})]})]},e.id)})]})]},e))})}e.s(["default",0,function(){return(0,a.jsx)(t.Suspense,{fallback:(0,a.jsx)("div",{className:"min-h-screen bg-[#0b0b0d] text-gray-100 p-4 sm:p-6",children:(0,a.jsx)("div",{className:"lg:ml-0 ml-10 text-gray-500 text-sm",children:"Loading…"})}),children:(0,a.jsx)(x,{})})}])}]);
@@ -1 +0,0 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,3479,e=>{"use strict";var t=e.i(59746);e.s(["previewContent",0,function(e){return e&&e.replace(/!\[([^\]]*)\]\([^)]*\)/g,"$1").replace(/\[([^\]]+)\]\([^)]*\)/g,"$1").replace(/`([^`]+)`/g,"$1").replace(/\s+/g," ").trim()||"--"},"timeAgo",0,function(e){return(0,t.relativeAgo)(e)??"--"}])},46228,e=>{"use strict";var t=e.i(22381);let s=[180,200,220,270,300,330,30,90];function a(e){let t=0;for(let s=0;s<e.length;s++)t=31*t+e.charCodeAt(s)>>>0;let a=s[t%s.length];return{bg:`hsl(${a} 55% 22%)`,ring:`hsl(${a} 60% 45%)`,text:`hsl(${a} 80% 78%)`}}function r(e){return e?(e.trim().match(/[\p{L}\p{N}]/u)?.[0]||e.trim()[0]||"·").toUpperCase():"·"}e.s(["AliasAvatar",0,function({alias:e,size:s=28,className:l=""}){if(/\bgrok\b|grok-build|grok测试员|grok-demo/i.test(e))return(0,t.jsx)("span",{className:`anet-alias-avatar inline-flex items-center justify-center rounded-full border border-emerald-500/45 bg-emerald-950/70 shrink-0 ${l}`,style:{width:s,height:s,backgroundImage:"url(/vendors/grok.svg)",backgroundPosition:"center",backgroundRepeat:"no-repeat",backgroundSize:"68% 68%"},title:e,"aria-hidden":!0});let i=a(e),n=Math.max(9,Math.round(.42*s));return(0,t.jsx)("span",{className:`anet-alias-avatar inline-flex items-center justify-center rounded-full border shrink-0 font-semibold ${l}`,style:{width:s,height:s,fontSize:n,backgroundColor:i.bg,borderColor:i.ring,color:i.text},title:e,"aria-hidden":!0,children:r(e)})},"aliasAvatarColors",0,a,"aliasInitial",0,r])},98025,e=>{"use strict";e.s(["SESSION_STATUS_CHIP_CLASS",0,{working:"bg-green-500/10 text-green-300 border-green-500/20",idle:"bg-gray-500/10 text-gray-300 border-gray-500/20",blocked:"bg-yellow-500/10 text-yellow-300 border-yellow-500/20",error:"bg-red-500/10 text-red-300 border-red-500/20",offline:"bg-gray-500/10 text-gray-500 border-gray-500/20"},"SESSION_STATUS_TEXT_CLASS",0,{working:"text-green-400",idle:"text-gray-400",blocked:"text-yellow-400",error:"text-red-400",offline:"text-gray-500"},"STATUS_BAR_CLASS",0,{created:"bg-gray-500",delivered:"bg-gray-400",acked:"bg-gray-300",running:"bg-green-500",replied:"bg-gray-400",closed:"bg-gray-600",failed:"bg-red-500",cancelled:"bg-gray-600",expired:"bg-gray-600"},"STATUS_CHIP_CLASS",0,{created:"bg-gray-500/10 text-gray-400 border-gray-500/20",delivered:"bg-gray-500/10 text-gray-300 border-gray-500/20",acked:"bg-gray-500/10 text-gray-300 border-gray-500/20",running:"bg-green-500/10 text-green-300 border-green-500/20",replied:"bg-gray-500/10 text-gray-300 border-gray-500/20",closed:"bg-gray-500/10 text-gray-500 border-gray-500/20",failed:"bg-red-500/10 text-red-300 border-red-500/20",cancelled:"bg-gray-500/10 text-gray-500 border-gray-500/20",expired:"bg-gray-500/10 text-gray-500 border-gray-500/20"},"STATUS_DOT_HEX",0,{created:"#9ca3af",delivered:"#9ca3af",acked:"#9ca3af",running:"#4ade80",replied:"#9ca3af",closed:"#6b7280",failed:"#f87171",cancelled:"#6b7280",expired:"#6b7280"},"TASK_STATUSES",0,["created","delivered","acked","running","replied","closed","failed","cancelled","expired"]])},59276,e=>{"use strict";var t=e.i(12629),s=e.i(11449);let a=async e=>{let t=await fetch(e);if(401===t.status)throw window.location.assign("/login"),Error("unauthorized");return t.json()},r={refreshInterval:5e3,dedupingInterval:3e3};function l(e,t){if(!t)return e;let s=e.includes("?")?"&":"?";return`${e}${s}network_id=${encodeURIComponent(t)}`}e.s(["useAnetConfig",0,function(){let{data:e}=(0,t.default)("/api/anet/config",a,{refreshInterval:3e4});return{config:e||null}},"useHealth",0,function(){let{data:e,error:s}=(0,t.default)("/api/hub/health",a,r);return{health:e||null,error:s}},"useMessages",0,function(e=100){let{networkId:i}=(0,s.useNetworkId)(),{data:n,error:d,isLoading:o}=(0,t.default)(l(`/api/hub/messages?limit=${e}`,i),a,{...r,keepPreviousData:!0});return{messages:n?.messages||[],error:d,isLoading:o}},"useSessions",0,function(){let{networkId:e}=(0,s.useNetworkId)(),{data:i,error:n,isLoading:d}=(0,t.default)(l("/api/hub/status",e),a,r);return{sessions:i?.sessions||[],hint:i?._hint,error:n,isLoading:d}},"useStats",0,function(){let{networkId:e}=(0,s.useNetworkId)(),{data:i,error:n}=(0,t.default)(l("/api/hub/stats",e),a,r);return{stats:i?.ok?i:null,error:n}},"useTasks",0,function(e){let{networkId:i}=(0,s.useNetworkId)(),n=new URLSearchParams({limit:"100",...e}).toString(),{data:d,error:o,isLoading:c}=(0,t.default)(l(`/api/hub/tasks?${n}`,i),a,r);return{tasks:d?.tasks||[],count:d?.count??0,source:d?.source,error:o,isLoading:c}}])},28729,e=>{"use strict";var t=e.i(22381),s=e.i(23910),a=e.i(56839),r=e.i(59276),l=e.i(3479),i=e.i(46228),n=e.i(98025);e.s(["default",0,function(){let e,{sessions:d}=(0,r.useSessions)(),{health:o}=(0,r.useHealth)(),{stats:c}=(0,r.useStats)(),x=o?.sse_sessions||{},g=e=>(e.network_id?x[`${e.network_id}:${e.alias}`]:void 0)??x[e.alias],[u,b]=(0,s.useState)(""),[m,h]=(0,s.useState)(""),[p,y]=(0,s.useState)(""),[f,j]=(0,s.useState)(""),[v,N]=(0,s.useState)(""),[S,k]=(0,s.useState)(""),[w,T]=(0,s.useState)(""),[C,A]=(0,s.useState)(""),_=async()=>{if(u.trim()&&m.trim()){try{let e=await fetch("/api/hub/auth",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"register",username:u,password:m})}),t=await e.json();y(t.ok?`Created: ${t.user.username} (${t.user.user_id})`:`Failed: ${t.error}`),t.ok&&(b(""),h(""))}catch{y("Failed")}setTimeout(()=>y(""),8e3)}},$=async()=>{if(f.trim()){try{let e=await fetch("/api/hub/broadcast",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:f})}),t=await e.json();N(t.ok?`Sent to ${t.recipients} nodes`:`Failed: ${t.error}`),t.ok&&j("")}catch{N("Failed")}setTimeout(()=>N(""),5e3)}},O=async()=>{if(S&&w.trim()){try{let e=await fetch("/api/hub/send",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({alias:S,task:w})}),t=await e.json();A(t.ok?"Task sent":`Failed: ${t.error}`),t.ok&&T("")}catch{A("Failed")}setTimeout(()=>A(""),5e3)}},I=d.filter(e=>g(e)),U=d.filter(e=>!g(e));return(0,t.jsxs)("div",{className:"min-h-screen bg-[#0b0b0d] text-gray-100 p-4 sm:p-6",children:[(0,t.jsx)("h1",{className:"text-2xl font-bold text-white mb-3 lg:ml-0 ml-10",children:"Admin"}),(0,t.jsx)("nav",{className:"mb-4 sm:mb-8 flex flex-wrap gap-2 text-xs",children:[{href:"#status",label:"Status"},{href:"#actions",label:"Actions"},{href:"#users",label:"Users"}].map(e=>(0,t.jsx)("a",{href:e.href,className:"inline-flex min-h-[44px] items-center rounded-md border border-[#26262b] bg-[#0e0e10]/60 px-3 py-2 text-gray-400 hover:border-cyan-500/50 hover:text-cyan-300 hover:bg-cyan-500/10 transition-colors",children:e.label},e.href))}),(0,t.jsxs)("div",{className:"max-w-6xl space-y-10",children:[(0,t.jsxs)("div",{id:"status",className:"space-y-4 scroll-mt-6",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,t.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Status"}),(0,t.jsx)("div",{className:"flex-1 h-px bg-[#26262b]"})]}),(0,t.jsxs)("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-4",children:[(0,t.jsxs)("section",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-4 sm:p-5",children:[(0,t.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-3 sm:mb-4",children:"Server Overview"}),(0,t.jsxs)("div",{className:"grid grid-cols-2 gap-4 text-sm",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("div",{className:"text-2xl sm:text-3xl font-bold text-green-400 tabular-nums",children:I.length}),(0,t.jsx)("div",{className:"text-xs text-gray-500",children:"Online"})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("div",{className:"text-2xl sm:text-3xl font-bold text-gray-500 tabular-nums",children:U.length}),(0,t.jsx)("div",{className:"text-xs text-gray-500",children:"Offline"})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("div",{className:"text-2xl sm:text-3xl font-bold text-cyan-400 tabular-nums",children:o?.sse_connections??"--"}),(0,t.jsxs)("div",{className:"text-xs text-gray-500",children:["SSE Streams ",(0,t.jsx)("span",{className:"text-gray-600",children:"· server"})]})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("div",{className:"text-2xl sm:text-3xl font-bold text-white tabular-nums",children:c?.tasks?.total??"--"}),(0,t.jsx)("div",{className:"text-xs text-gray-500",children:"Total Tasks"})]})]}),c?.tasks?.by_status&&c.tasks.by_status.length>0&&(e=Object.fromEntries(c.tasks.by_status.map(e=>[e.status,e.count])),(0,t.jsxs)("div",{className:"mt-4 flex items-center justify-between border-t border-[#26262b] pt-3 text-xs",children:[(0,t.jsxs)("div",{className:"text-gray-400 tabular-nums",children:[(0,t.jsxs)("span",{className:e.running?"text-green-400":"text-gray-500",children:[e.running||0," running"]}),(0,t.jsx)("span",{className:"text-gray-600",children:" · "}),(0,t.jsxs)("span",{className:e.failed?"text-red-400":"text-gray-500",children:[e.failed||0," failed"]})]}),(0,t.jsx)(a.default,{href:"/tasks",prefetch:!1,className:"text-cyan-400 hover:text-cyan-300",children:"View all →"})]}))]}),(0,t.jsxs)("section",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-5",children:[(0,t.jsxs)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:["Online Sessions ",(0,t.jsxs)("span",{className:"text-gray-600",children:["(",I.length,")"]})]}),(0,t.jsx)("div",{className:"space-y-2 max-h-80 overflow-y-auto",children:0===I.length?(0,t.jsx)("div",{className:"text-xs text-gray-600 text-center py-4",children:"No online sessions"}):I.map(e=>(0,t.jsxs)("div",{className:"flex items-center gap-3 bg-[#0e0e10] rounded-lg px-3 py-2 border border-[#1c1c1f]",children:[(0,t.jsx)(i.AliasAvatar,{alias:e.alias,size:20}),(0,t.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,t.jsx)("div",{className:"text-sm text-white font-medium truncate",children:e.alias}),(0,t.jsxs)("div",{className:"text-xs text-gray-500 truncate",children:[e.agent||"--"," · ",e.task||"idle"]})]}),(0,t.jsxs)("div",{className:"flex items-center gap-2 shrink-0",children:[(0,t.jsx)("span",{className:`text-xs px-2 py-0.5 rounded border ${n.SESSION_STATUS_CHIP_CLASS[e.status]||n.SESSION_STATUS_CHIP_CLASS.idle}`,children:e.status}),(0,t.jsx)("span",{className:"text-[10px] text-gray-600",children:(0,l.timeAgo)(e.updated_at)})]})]},e.alias))})]})]})]}),(0,t.jsxs)("div",{id:"actions",className:"space-y-4 scroll-mt-6",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,t.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Actions"}),(0,t.jsx)("div",{className:"flex-1 h-px bg-[#26262b]"})]}),0===d.length?(0,t.jsx)("div",{className:"bg-[#161618] border border-[#26262b] rounded-xl px-5 py-4 text-sm text-gray-500",children:"Broadcast and Send Task become available after the first agent registers."}):(0,t.jsxs)("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-4",children:[(0,t.jsxs)("section",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-5",children:[(0,t.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Broadcast"}),(0,t.jsx)("textarea",{value:f,onChange:e=>j(e.target.value),placeholder:"Message to all online nodes...",rows:3,className:"w-full bg-[#0e0e10] border border-[#26262b] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-cyan-500/50 focus:outline-none resize-none"}),(0,t.jsxs)("div",{className:"flex justify-between items-center mt-3",children:[(0,t.jsxs)("span",{className:"text-xs text-gray-600",children:[f.length,"/500"]}),(0,t.jsx)("button",{onClick:$,disabled:!f.trim(),className:"px-4 py-2 bg-purple-600 hover:bg-purple-500 disabled:bg-gray-800 disabled:text-gray-600 text-white text-sm rounded-lg transition-colors",children:"Broadcast"})]}),v&&(0,t.jsx)("div",{className:`mt-2 text-xs ${v.startsWith("Failed")?"text-red-400":"text-green-400"}`,children:v})]}),(0,t.jsxs)("section",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-5",children:[(0,t.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Send Task"}),(0,t.jsxs)("select",{value:S,onChange:e=>k(e.target.value),className:"w-full bg-[#0e0e10] border border-[#26262b] rounded-lg px-3 py-2 text-base sm:text-sm text-white focus:border-cyan-500/50 focus:outline-none mb-3",children:[(0,t.jsx)("option",{value:"",children:"Select target node..."}),I.map(e=>(0,t.jsxs)("option",{value:e.alias,children:[e.alias," (",e.status,")"]},e.alias)),(0,t.jsx)("optgroup",{label:"Offline",children:U.map(e=>(0,t.jsxs)("option",{value:e.alias,children:[e.alias," (offline)"]},e.alias))})]}),(0,t.jsx)("textarea",{value:w,onChange:e=>T(e.target.value),placeholder:"Task content...",rows:3,className:"w-full bg-[#0e0e10] border border-[#26262b] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-cyan-500/50 focus:outline-none resize-none"}),(0,t.jsx)("div",{className:"flex justify-end mt-3",children:(0,t.jsx)("button",{onClick:O,disabled:!S||!w.trim(),className:"px-4 py-2 bg-cyan-600 hover:bg-cyan-500 disabled:bg-gray-800 disabled:text-gray-600 text-white text-sm rounded-lg transition-colors",children:"Send Task"})}),C&&(0,t.jsx)("div",{className:`mt-2 text-xs ${C.startsWith("Failed")?"text-red-400":"text-green-400"}`,children:C})]})]})]}),(0,t.jsxs)("div",{id:"users",className:"space-y-4 scroll-mt-6",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,t.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Users"}),(0,t.jsx)("div",{className:"flex-1 h-px bg-[#26262b]"})]}),(0,t.jsx)("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-4",children:(0,t.jsxs)("section",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-5",children:[(0,t.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Register User (V3)"}),(0,t.jsxs)("div",{className:"space-y-3",children:[(0,t.jsx)("input",{type:"text",value:u,onChange:e=>b(e.target.value),placeholder:"Username",className:"w-full bg-[#0e0e10] border border-[#26262b] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-cyan-500/50 focus:outline-none"}),(0,t.jsx)("input",{type:"password",value:m,onChange:e=>h(e.target.value),placeholder:"Password",className:"w-full bg-[#0e0e10] border border-[#26262b] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-cyan-500/50 focus:outline-none"}),(0,t.jsx)("button",{onClick:_,disabled:!u.trim()||!m.trim(),className:"w-full px-4 py-2 bg-green-600 hover:bg-green-500 disabled:bg-gray-800 disabled:text-gray-600 text-white text-sm rounded-lg transition-colors",children:"Register"})]}),p&&(0,t.jsx)("div",{className:`mt-2 text-xs ${p.startsWith("Failed")?"text-red-400":"text-green-400"}`,children:p})]})})]})]})]})}])}]);
@@ -1 +0,0 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,59276,e=>{"use strict";var s=e.i(12629),t=e.i(11449);let a=async e=>{let s=await fetch(e);if(401===s.status)throw window.location.assign("/login"),Error("unauthorized");return s.json()},r={refreshInterval:5e3,dedupingInterval:3e3};function n(e,s){if(!s)return e;let t=e.includes("?")?"&":"?";return`${e}${t}network_id=${encodeURIComponent(s)}`}e.s(["useAnetConfig",0,function(){let{data:e}=(0,s.default)("/api/anet/config",a,{refreshInterval:3e4});return{config:e||null}},"useHealth",0,function(){let{data:e,error:t}=(0,s.default)("/api/hub/health",a,r);return{health:e||null,error:t}},"useMessages",0,function(e=100){let{networkId:l}=(0,t.useNetworkId)(),{data:c,error:i,isLoading:o}=(0,s.default)(n(`/api/hub/messages?limit=${e}`,l),a,{...r,keepPreviousData:!0});return{messages:c?.messages||[],error:i,isLoading:o}},"useSessions",0,function(){let{networkId:e}=(0,t.useNetworkId)(),{data:l,error:c,isLoading:i}=(0,s.default)(n("/api/hub/status",e),a,r);return{sessions:l?.sessions||[],hint:l?._hint,error:c,isLoading:i}},"useStats",0,function(){let{networkId:e}=(0,t.useNetworkId)(),{data:l,error:c}=(0,s.default)(n("/api/hub/stats",e),a,r);return{stats:l?.ok?l:null,error:c}},"useTasks",0,function(e){let{networkId:l}=(0,t.useNetworkId)(),c=new URLSearchParams({limit:"100",...e}).toString(),{data:i,error:o,isLoading:d}=(0,s.default)(n(`/api/hub/tasks?${c}`,l),a,r);return{tasks:i?.tasks||[],count:i?.count??0,source:i?.source,error:o,isLoading:d}}])},70286,e=>{"use strict";e.s(["DASHBOARD_VERSION",0,"0.6.3-preview.0"],70286)},65610,e=>{"use strict";var s=e.i(22381),t=e.i(23910),a=e.i(56839),r=e.i(59276),n=e.i(70286);e.s(["default",0,function(){let{config:e}=(0,r.useAnetConfig)(),{health:l,error:c}=(0,r.useHealth)(),[i,o]=(0,t.useState)(()=>{try{return localStorage.getItem("anet-theme")||"cyber"}catch{return"cyber"}}),[d,x]=(0,t.useState)(""),[m,h]=(0,t.useState)(""),[b,g]=(0,t.useState)(""),u="flex flex-col gap-1 sm:flex-row sm:items-start sm:justify-between",p="break-all sm:max-w-[320px] sm:text-right";return(0,s.jsxs)("div",{className:"min-h-screen bg-[#0b0b0d] text-gray-100 p-4 sm:p-6",children:[(0,s.jsx)("h1",{className:"text-2xl font-bold text-white mb-3 lg:ml-0 ml-10",children:"Settings"}),(0,s.jsx)("nav",{className:"mb-4 sm:mb-8 flex flex-wrap gap-2 text-xs",children:[{href:"#appearance",label:"Appearance"},{href:"#connection",label:"Connection"},{href:"#account",label:"Account"},{href:"#resources",label:"Resources"}].map(e=>(0,s.jsx)("a",{href:e.href,className:"inline-flex min-h-[44px] items-center rounded-md border border-[#26262b] bg-[#0e0e10]/60 px-3 py-2 text-gray-400 hover:border-cyan-500/50 hover:text-cyan-300 hover:bg-cyan-500/10 transition-colors",children:e.label},e.href))}),(0,s.jsxs)("div",{className:"max-w-2xl space-y-10",children:[(0,s.jsxs)("div",{id:"appearance",className:"space-y-4 scroll-mt-6",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,s.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Appearance"}),(0,s.jsx)("div",{className:"flex-1 h-px bg-[#26262b]"})]}),(0,s.jsxs)("section",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Theme"}),(0,s.jsx)("div",{className:"grid grid-cols-2 gap-3",children:[{id:"cyber",label:"Dark",swatch:"#0b0b0d"},{id:"light",label:"Light",swatch:"#f6f7f9"}].map(e=>(0,s.jsxs)("button",{onClick:()=>{try{localStorage.setItem("anet-theme",e.id)}catch{}document.documentElement.setAttribute("data-theme",e.id),o(e.id)},"aria-pressed":i===e.id,className:`flex items-center gap-3 rounded-lg border px-4 py-3 text-sm transition-colors ${i===e.id?"border-cyan-500/60 bg-cyan-500/10 text-gray-100":"border-[#26262b] text-gray-400 hover:border-[#3a3a41]"}`,children:[(0,s.jsx)("span",{"aria-hidden":!0,className:"inline-block w-5 h-5 rounded-full border border-black/20 shrink-0",style:{backgroundColor:e.swatch}}),e.label,i===e.id&&(0,s.jsx)("span",{className:"ml-auto text-cyan-400",children:"✓"})]},e.id))})]})]}),(0,s.jsxs)("div",{id:"connection",className:"space-y-4 scroll-mt-6",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,s.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Connection"}),(0,s.jsx)("div",{className:"flex-1 h-px bg-[#26262b]"})]}),(0,s.jsxs)("section",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"CommHub Connection"}),(0,s.jsxs)("div",{className:"space-y-3 text-sm",children:[(0,s.jsxs)("div",{className:u,children:[(0,s.jsx)("span",{className:"text-gray-500 shrink-0",children:"Hub URL"}),(0,s.jsx)("span",{className:`text-cyan-300 ${p}`,children:e?.hub||"not configured"})]}),(0,s.jsxs)("div",{className:u,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Config Source"}),(0,s.jsx)("span",{className:`text-gray-300 ${p}`,children:e?.source==="file"?"Local file (~/.anet/config.json)":e?.source==="runtime-env"?"Vercel env vars":"Missing"})]}),(0,s.jsxs)("div",{className:u,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Auth Token"}),(0,s.jsx)("span",{className:`${e?.tokenConfigured?"text-green-400":"text-red-400"} ${p}`,children:e?.tokenConfigured?`Configured (${e.tokenPreview})`:"Not configured"})]}),(0,s.jsxs)("div",{className:u,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Server Auth"}),(0,s.jsx)("span",{className:`${l?.auth==="enabled"?"text-green-400":"text-yellow-400"} sm:text-right`,children:l?.auth||"--"})]}),e?.error&&(0,s.jsx)("div",{className:"border-t border-[#26262b] pt-3 text-xs text-gray-600",children:e.error}),(c||l?.ok===!1)&&(0,s.jsxs)("div",{className:"border-t border-red-500/20 pt-3 text-xs space-y-1.5",role:"alert",children:[(0,s.jsx)("div",{className:"text-red-300 font-medium",children:"CommHub unreachable — how to recover:"}),(0,s.jsxs)("div",{className:"text-gray-400",children:["1. Check the hub process on the server: ",(0,s.jsx)("code",{className:"font-mono bg-[#0e0e10] border border-[#1c1c1f] rounded px-1.5 py-0.5",children:"anet hub status"})]}),(0,s.jsxs)("div",{className:"text-gray-400",children:["2. Start it if stopped: ",(0,s.jsx)("code",{className:"font-mono bg-[#0e0e10] border border-[#1c1c1f] rounded px-1.5 py-0.5",children:"anet hub start"})]}),(0,s.jsx)("div",{className:"text-gray-400",children:"3. Confirm the Hub URL above matches where the hub actually listens."})]})]})]}),(0,s.jsxs)("section",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Server Info"}),(0,s.jsxs)("div",{className:"space-y-3 text-sm",children:[(0,s.jsxs)("div",{className:u,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Version"}),(0,s.jsx)("span",{className:`text-gray-300 ${p}`,children:l?.version||"--"})]}),(0,s.jsxs)("div",{className:u,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Sessions"}),(0,s.jsx)("span",{className:`text-gray-300 ${p}`,children:l?.sessions??"--"})]}),(0,s.jsxs)("div",{className:u,children:[(0,s.jsxs)("span",{className:"text-gray-500",children:["SSE streams ",(0,s.jsx)("span",{className:"text-gray-600",children:"· server"})]}),(0,s.jsx)("span",{className:`text-gray-300 ${p}`,children:l?.sse_connections??"--"})]}),(0,s.jsxs)("div",{className:u,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Uptime"}),(0,s.jsx)("span",{className:`text-gray-300 ${p}`,children:l?.uptime?`${Math.floor(l.uptime/3600)}h ${Math.floor(l.uptime%3600/60)}m`:"--"})]})]})]}),(0,s.jsxs)("section",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Dashboard"}),(0,s.jsxs)("div",{className:"space-y-3 text-sm",children:[(0,s.jsxs)("div",{className:u,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Version"}),(0,s.jsx)("span",{className:`text-gray-300 font-mono ${p}`,title:"From package.json @sleep2agi/agent-network-dashboard",children:n.DASHBOARD_VERSION})]}),(0,s.jsxs)("div",{className:u,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Data Layer"}),(0,s.jsx)("span",{className:`text-gray-300 ${p}`,children:"SWR (5s refresh, 3s dedup)"})]}),(0,s.jsxs)("div",{className:u,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Pages"}),(0,s.jsx)("span",{className:`text-gray-300 ${p}`,children:"Overview, Tasks, Nodes, Messages, Networks, Audit, Server Logs, Admin, Settings"})]})]})]})]}),(0,s.jsxs)("div",{id:"account",className:"space-y-4 scroll-mt-6",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,s.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Account"}),(0,s.jsx)("div",{className:"flex-1 h-px bg-[#26262b]"})]}),(0,s.jsxs)("section",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Change Password"}),(0,s.jsxs)("div",{className:"space-y-3",children:[(0,s.jsx)("input",{type:"password",value:d,onChange:e=>x(e.target.value),placeholder:"Current password",className:"w-full bg-[#0e0e10] border border-[#26262b] rounded-lg px-3 py-2 text-base sm:text-sm text-white placeholder-gray-600 focus:border-cyan-500/50 focus:outline-none"}),(0,s.jsx)("input",{type:"password",value:m,onChange:e=>h(e.target.value),placeholder:"New password",className:"w-full bg-[#0e0e10] border border-[#26262b] rounded-lg px-3 py-2 text-base sm:text-sm text-white placeholder-gray-600 focus:border-cyan-500/50 focus:outline-none"}),(0,s.jsx)("button",{onClick:async()=>{if(!d||!m)return;let e=sessionStorage.getItem("anet_v3_auth");if(!e)return void g("Not logged in with V3 auth");let{token:s}=JSON.parse(e),t=await fetch("/api/hub/auth",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"change_password",token:s,current_password:d,new_password:m})}),a=await t.json();if(g(a.ok?"Password changed":`Failed: ${a.error}`),a.ok){if(a.token){let s=JSON.parse(e);sessionStorage.setItem("anet_v3_auth",JSON.stringify({...s,token:a.token}))}x(""),h("")}setTimeout(()=>g(""),5e3)},disabled:!d||!m,className:"px-4 py-2 bg-cyan-600 hover:bg-cyan-500 disabled:bg-gray-800 disabled:text-gray-600 text-white text-sm rounded-lg transition-colors",children:"Change Password"})]}),b&&(0,s.jsx)("div",{className:`mt-2 text-xs ${b.startsWith("Failed")?"text-red-400":"text-green-400"}`,children:b})]}),(0,s.jsxs)("section",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Sign out"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mb-3",children:"Signing out clears your dashboard session cookie. You'll return to the login page."}),(0,s.jsx)("button",{onClick:async()=>{await fetch("/api/auth/logout",{method:"POST"}).catch(()=>{}),window.location.assign("/login")},className:"px-4 py-2 bg-transparent hover:bg-[#1c1c1f] text-gray-300 text-sm rounded-lg border border-[#26262b] hover:border-[#3a3a41] transition-colors",children:"Sign out"})]})]}),(0,s.jsxs)("div",{id:"resources",className:"space-y-4 scroll-mt-6",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,s.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Resources"}),(0,s.jsx)("div",{className:"flex-1 h-px bg-[#26262b]"})]}),(0,s.jsxs)("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4",children:[(0,s.jsxs)(a.default,{href:"/settings/tokens",className:"bg-[#161618] border border-[#26262b] rounded-xl p-5 hover:border-cyan-500/30 transition-colors",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300",children:"API Tokens"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-2",children:"Create and manage tokens for CLI access."}),(0,s.jsx)("span",{className:"text-xs text-cyan-400 mt-3 inline-block",children:"Manage →"})]}),(0,s.jsxs)(a.default,{href:"/settings/networks",className:"bg-[#161618] border border-[#26262b] rounded-xl p-5 hover:border-cyan-500/30 transition-colors",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300",children:"Networks"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-2",children:"Create, manage, and delete agent networks."}),(0,s.jsx)("span",{className:"text-xs text-cyan-400 mt-3 inline-block",children:"Manage →"})]}),(0,s.jsxs)(a.default,{href:"/messages",className:"bg-[#161618] border border-[#26262b] rounded-xl p-5 hover:border-cyan-500/30 transition-colors",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300",children:"Messages"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-2",children:"Global timeline of CommHub messages across all agents."}),(0,s.jsx)("span",{className:"text-xs text-cyan-400 mt-3 inline-block",children:"Open →"})]}),(0,s.jsxs)(a.default,{href:"/logs",className:"bg-[#161618] border border-[#26262b] rounded-xl p-5 hover:border-cyan-500/30 transition-colors",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300",children:"Audit Log"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-2",children:"Authentication, token rotations, and admin actions."}),(0,s.jsx)("span",{className:"text-xs text-cyan-400 mt-3 inline-block",children:"Open →"})]}),(0,s.jsxs)(a.default,{href:"/server-logs",className:"bg-[#161618] border border-[#26262b] rounded-xl p-5 hover:border-cyan-500/30 transition-colors",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300",children:"Server Logs"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-2",children:"Live stdout / stderr from the CommHub server."}),(0,s.jsx)("span",{className:"text-xs text-cyan-400 mt-3 inline-block",children:"Open →"})]})]})]})]})]})}])}]);