@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
@@ -0,0 +1,79 @@
1
+ import { requireDashboardAuth } from '@/app/lib/dashboard-auth';
2
+ import { hubFetch } from '@/app/lib/hub';
3
+ import { callMcp, parseMcpEnvelope, resolveDefaultNetworkId } from '@/app/lib/hub-mcp';
4
+
5
+ /**
6
+ * Provider connectivity probe (RFC-028 P2 — aligned to real #308 schema).
7
+ *
8
+ * GET → probe-target server set (online host_supervisor daemons).
9
+ * POST { provider_id, model_name, daemon_node_id } → DISPATCH a probe
10
+ * (probe_provider_model is async: it mints a pending probe_results
11
+ * row + doorbells the daemon, and returns only { probe_id }). The
12
+ * actual cell status lands later in probe_results — the matrix polls
13
+ * /api/anet/providers/probe-results (get_probe_results) for it.
14
+ *
15
+ * Hub-without-RFC-028 → flagged `unconfirmed`. MOCK_PROVIDERS=1 → no-op
16
+ * dispatch (the mock results come from the probe-results route).
17
+ */
18
+
19
+ function mockServers() {
20
+ return [
21
+ { daemon_node_id: 'node_daemon_gpu1', hostname: 'gpu-node-1' },
22
+ { daemon_node_id: 'node_daemon_gpu2', hostname: 'gpu-node-2' },
23
+ { daemon_node_id: 'node_daemon_cpu1', hostname: 'cpu-node-1' },
24
+ ];
25
+ }
26
+
27
+ async function resolveServerSet(): Promise<Array<{ daemon_node_id: string; hostname: string }>> {
28
+ try {
29
+ const res = await hubFetch('/api/nodes');
30
+ if (!res.ok) return [];
31
+ const data = (await res.json()) as { nodes?: unknown; sessions?: unknown };
32
+ const raw = data.nodes ?? data.sessions ?? data;
33
+ const arr = (Array.isArray(raw) ? raw : raw && typeof raw === 'object' ? Object.values(raw) : []) as Array<Record<string, unknown>>;
34
+ const out: Array<{ daemon_node_id: string; hostname: string }> = [];
35
+ for (const n of arr) {
36
+ if (!n || typeof n !== 'object') continue;
37
+ const id = String(n.node_id || '');
38
+ if (n.role === 'host_supervisor' || id.startsWith('node_daemon_')) {
39
+ out.push({ daemon_node_id: id, hostname: String(n.server || n.hostname || n.alias || id) });
40
+ }
41
+ }
42
+ return out;
43
+ } catch { return []; }
44
+ }
45
+
46
+ export async function GET() {
47
+ const authFailure = await requireDashboardAuth();
48
+ if (authFailure) return authFailure;
49
+ if (process.env.MOCK_PROVIDERS === '1') return Response.json({ ok: true, mock: true, servers: mockServers() });
50
+ return Response.json({ ok: true, servers: await resolveServerSet() });
51
+ }
52
+
53
+ export async function POST(req: Request) {
54
+ const authFailure = await requireDashboardAuth();
55
+ if (authFailure) return authFailure;
56
+ let body: { provider_id?: string; model_name?: string; daemon_node_id?: string; network_id?: string };
57
+ try { body = await req.json(); } catch { return Response.json({ error: 'invalid JSON body' }, { status: 400 }); }
58
+ const { provider_id, model_name, daemon_node_id } = body;
59
+ if (!provider_id || !model_name || !daemon_node_id) {
60
+ return Response.json({ error: 'provider_id, model_name, daemon_node_id required' }, { status: 400 });
61
+ }
62
+ if (process.env.MOCK_PROVIDERS === '1') {
63
+ return Response.json({ ok: true, mock: true, probe_id: `mock_${model_name}_${daemon_node_id}` });
64
+ }
65
+ const networkId = body.network_id || (await resolveDefaultNetworkId());
66
+ const args = { provider_id, model_name, daemon_node_id, ...(networkId ? { network_id: networkId } : {}) };
67
+ try {
68
+ const res = await callMcp('probe_provider_model', args);
69
+ if (res.status === 404 || res.status === 501) {
70
+ return Response.json({ ok: false, unconfirmed: true, error: 'hub lacks RFC-028 probe_provider_model (needs #308)' }, { status: 200 });
71
+ }
72
+ if (!res.ok) return Response.json({ ok: false, error: `hub ${res.status}` }, { status: 502 });
73
+ const result = (await parseMcpEnvelope(res)) as { ok?: boolean; probe_id?: string; error?: string };
74
+ if (result?.ok === false) return Response.json({ ok: false, error: result.error || 'dispatch_failed' }, { status: 502 });
75
+ return Response.json({ ok: true, probe_id: result?.probe_id });
76
+ } catch (e: unknown) {
77
+ return Response.json({ ok: false, error: e instanceof Error ? e.message : String(e) }, { status: 502 });
78
+ }
79
+ }
@@ -0,0 +1,60 @@
1
+ import { requireDashboardAuth } from '@/app/lib/dashboard-auth';
2
+ import { callMcp, parseMcpEnvelope, resolveDefaultNetworkId } from '@/app/lib/hub-mcp';
3
+
4
+ /**
5
+ * Probe-results poll (RFC-028 P2 — get_probe_results, the matrix renderer
6
+ * source). The matrix dispatches probes (async) then polls this for each
7
+ * cell's resolved status. Returns rows:
8
+ * { provider_id, model_name, daemon_node_id, status, latency_ms, error_label, raw_status_code, probed_at }
9
+ *
10
+ * MOCK_PROVIDERS=1 → deterministic schema-shaped fixture so the preview matrix
11
+ * resolves instantly. Real → get_probe_results MCP.
12
+ */
13
+
14
+ const MOCK_SERVERS = ['node_daemon_gpu1', 'node_daemon_gpu2', 'node_daemon_cpu1'];
15
+ const MOCK_MODELS: Record<string, string[]> = {
16
+ prov_claude: ['claude-opus-4-x', 'claude-sonnet-4-6'],
17
+ prov_deepseek: ['deepseek-v4-pro'],
18
+ prov_minimax: ['MiniMax-M3'],
19
+ };
20
+
21
+ function mockCell(model: string, server: string) {
22
+ let h = 0;
23
+ const s = `${model}@${server}`;
24
+ for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) & 0xffff;
25
+ const bucket = h % 10;
26
+ if (bucket === 7) return { status: 'auth_fail', error_label: '401 key rejected', raw_status_code: 401 };
27
+ if (bucket === 3) return { status: 'unreachable', error_label: 'connect ETIMEDOUT', raw_status_code: 0 };
28
+ if (bucket === 9) return { status: 'incompatible', error_label: 'model not served', raw_status_code: 404 };
29
+ return { status: 'ok', latency_ms: 80 + (h % 600) };
30
+ }
31
+
32
+ export async function GET(req: Request) {
33
+ const authFailure = await requireDashboardAuth();
34
+ if (authFailure) return authFailure;
35
+ const { searchParams } = new URL(req.url);
36
+ const providerId = searchParams.get('provider_id') || undefined;
37
+
38
+ if (process.env.MOCK_PROVIDERS === '1') {
39
+ const models = (providerId && MOCK_MODELS[providerId]) || [];
40
+ const results = models.flatMap(m => MOCK_SERVERS.map(srv => ({
41
+ provider_id: providerId, model_name: m, daemon_node_id: srv, probed_at: Date.now(), ...mockCell(m, srv),
42
+ })));
43
+ return Response.json({ ok: true, mock: true, results });
44
+ }
45
+
46
+ const networkId = await resolveDefaultNetworkId();
47
+ const args: Record<string, unknown> = { ...(providerId ? { provider_id: providerId } : {}), ...(networkId ? { network_id: networkId } : {}), limit: 500 };
48
+ try {
49
+ const res = await callMcp('get_probe_results', args);
50
+ if (res.status === 404 || res.status === 501) {
51
+ return Response.json({ ok: false, unconfirmed: true, results: [], error: 'hub lacks RFC-028 get_probe_results (needs #308)' }, { status: 200 });
52
+ }
53
+ if (!res.ok) return Response.json({ ok: false, error: `hub ${res.status}`, results: [] }, { status: 502 });
54
+ const result = (await parseMcpEnvelope(res)) as { ok?: boolean; results?: unknown[]; error?: string };
55
+ if (result?.ok === false) return Response.json({ ok: false, error: result.error || 'query_failed', results: [] }, { status: 502 });
56
+ return Response.json({ ok: true, results: Array.isArray(result?.results) ? result.results : [] });
57
+ } catch (e: unknown) {
58
+ return Response.json({ ok: false, error: e instanceof Error ? e.message : String(e), results: [] }, { status: 502 });
59
+ }
60
+ }
@@ -0,0 +1,191 @@
1
+ import { requireDashboardAuth } from '@/app/lib/dashboard-auth';
2
+ import { callMcp, parseMcpEnvelope, resolveDefaultNetworkId } from '@/app/lib/hub-mcp';
3
+
4
+ /**
5
+ * Model-provider registry proxy (RFC-028 P1 — aligned to the real #308 schema,
6
+ * commit f32725e; 通信龙 gap-A ruling commhub 1e451a0f).
7
+ *
8
+ * GET → list_providers, mapped to the UI shape (vendor→type, models objects
9
+ * → model_name strings, in_vault→hasKey).
10
+ * POST → create only: secret-FIRST. The vault key must exist before the
11
+ * provider, so we upsert_network_secret (UPPERCASE-regex key derived
12
+ * from the name) then upsert_provider (vendor + models as objects).
13
+ * A key is REQUIRED on create (the backend rejects providers whose
14
+ * secret_key_ref is not in the vault).
15
+ * DELETE / edit → NOT wired: #308's upsert_provider is INSERT-only with no
16
+ * enabled arg and there is no update_provider / set_provider_enabled
17
+ * tool (P1.5 follow-up). The UI edit/disable/delete controls are
18
+ * disabled placeholders; this route reports `unsupported` if called.
19
+ *
20
+ * Keys are WRITE-ONLY (vault); never returned to the client. Hub-without-RFC-028
21
+ * → flagged `unconfirmed` (no fake success). MOCK_PROVIDERS=1 → env-gated
22
+ * contract-fixture (schema-shaped) for preview; off in production.
23
+ */
24
+
25
+ const VENDORS = ['openai-compatible', 'anthropic', 'grok', 'custom'] as const;
26
+
27
+ interface ProviderInput {
28
+ name: string;
29
+ type: string; // UI label for `vendor`
30
+ base_url: string;
31
+ models: string[]; // UI: model name strings
32
+ apiKey?: string; // write-only
33
+ }
34
+
35
+ // UPPERCASE secret-key ref derived from provider name (matches the backend
36
+ // regex /^[A-Z][A-Z0-9_]{0,63}$/): "OpenAI" → "PROVIDER_OPENAI_KEY".
37
+ function secretKeyFor(name: string): string {
38
+ const slug = name.toUpperCase().replace(/[^A-Z0-9]+/g, '_').replace(/^_+|_+$/g, '').slice(0, 48) || 'PROVIDER';
39
+ const ref = `PROVIDER_${slug}_KEY`;
40
+ return /^[A-Z][A-Z0-9_]{0,63}$/.test(ref) ? ref : `PROVIDER_${Date.now().toString(36).toUpperCase().replace(/[^A-Z0-9]/g, '')}_KEY`;
41
+ }
42
+
43
+ // Anthropic-compatible covers Claude + DeepSeek (api.deepseek.com/anthropic)
44
+ // + MiniMax (api.minimax.chat/anthropic) etc. via custom base_url — preview
45
+ // reflects that real coverage.
46
+ function mockProviders() {
47
+ // All three live after #320 (SSRF allowlist: anthropic / deepseek /
48
+ // minimax.chat / minimax.io).
49
+ return [
50
+ { provider_id: 'prov_claude', name: 'Claude (Anthropic)', type: 'anthropic', base_url: 'https://api.anthropic.com', models: ['claude-opus-4-x', 'claude-sonnet-4-6'], enabled: true, hasKey: true },
51
+ { provider_id: 'prov_deepseek', name: 'DeepSeek', type: 'anthropic', base_url: 'https://api.deepseek.com/anthropic', models: ['deepseek-v4-pro'], enabled: true, hasKey: true },
52
+ { provider_id: 'prov_minimax', name: 'MiniMax', type: 'anthropic', base_url: 'https://api.minimax.chat/anthropic', models: ['MiniMax-M3'], enabled: false, hasKey: true },
53
+ ];
54
+ }
55
+
56
+ export async function GET() {
57
+ const authFailure = await requireDashboardAuth();
58
+ if (authFailure) return authFailure;
59
+ if (process.env.MOCK_PROVIDERS === '1') {
60
+ return Response.json({ ok: true, mock: true, providers: mockProviders() });
61
+ }
62
+
63
+ const networkId = await resolveDefaultNetworkId();
64
+ const args = networkId ? { network_id: networkId } : {};
65
+ try {
66
+ const res = await callMcp('list_providers', args);
67
+ if (res.status === 404 || res.status === 501) {
68
+ return Response.json({ ok: false, unconfirmed: true, providers: [], error: 'hub lacks RFC-028 list_providers (needs #308 + hub upgrade)' }, { status: 200 });
69
+ }
70
+ if (!res.ok) return Response.json({ ok: false, error: `hub ${res.status}`, providers: [] }, { status: 502 });
71
+ const result = (await parseMcpEnvelope(res)) as { ok?: boolean; providers?: unknown[]; error?: string };
72
+ if (result?.ok === false) return Response.json({ ok: false, error: result.error || 'list_failed', providers: [] }, { status: 502 });
73
+
74
+ // Map the real shape → UI shape.
75
+ const providers = (Array.isArray(result?.providers) ? result.providers : []).map((p) => {
76
+ const pp = p as Record<string, unknown>;
77
+ const models = Array.isArray(pp.models) ? (pp.models as Array<Record<string, unknown>>).map(m => String(m.model_name || '')).filter(Boolean) : [];
78
+ return {
79
+ provider_id: pp.provider_id,
80
+ name: pp.name,
81
+ type: pp.vendor, // vendor → type (UI label)
82
+ base_url: pp.base_url,
83
+ models,
84
+ enabled: pp.enabled === undefined ? true : !!pp.enabled,
85
+ hasKey: pp.in_vault === undefined ? true : !!pp.in_vault,
86
+ };
87
+ });
88
+ return Response.json({ ok: true, providers });
89
+ } catch (e: unknown) {
90
+ return Response.json({ ok: false, error: e instanceof Error ? e.message : String(e), providers: [] }, { status: 502 });
91
+ }
92
+ }
93
+
94
+ export async function POST(req: Request) {
95
+ const authFailure = await requireDashboardAuth();
96
+ if (authFailure) return authFailure;
97
+
98
+ let body: Partial<ProviderInput> & { provider_id?: string; network_id?: string; enabled?: boolean };
99
+ try { body = await req.json(); } catch { return Response.json({ error: 'invalid JSON body' }, { status: 400 }); }
100
+
101
+ // Edit path (RFC-028 P1.5, #317 update_provider — patch semantics; vendor /
102
+ // secret / network are immutable; changing the key goes via the secret-first
103
+ // create flow, not here).
104
+ if (body.provider_id) {
105
+ if (process.env.MOCK_PROVIDERS === '1') return Response.json({ ok: true, mock: true, provider_id: body.provider_id });
106
+ const patch: Record<string, unknown> = {};
107
+ if (body.name !== undefined) patch.name = String(body.name).trim();
108
+ if (body.base_url !== undefined) patch.base_url = String(body.base_url).trim();
109
+ if (Array.isArray(body.models)) patch.models = body.models.map(m => String(m).trim()).filter(Boolean).map(m => ({ model_name: m }));
110
+ if (body.enabled !== undefined) patch.enabled = !!body.enabled;
111
+ if (!Object.keys(patch).length) return Response.json({ ok: false, error: 'no fields to update' }, { status: 400 });
112
+ const networkId = body.network_id || (await resolveDefaultNetworkId());
113
+ try {
114
+ const res = await callMcp('update_provider', { provider_id: body.provider_id, ...(networkId ? { network_id: networkId } : {}), patch });
115
+ if (res.status === 404 || res.status === 501) return Response.json({ ok: false, unconfirmed: true, error: 'hub lacks update_provider (needs #317)' }, { status: 200 });
116
+ const result = (await parseMcpEnvelope(res)) as { ok?: boolean; error?: string };
117
+ if (result?.ok === false) {
118
+ // a no-op patch is benign, not a failure.
119
+ if (result.error === 'no_changes' || result.error === 'noop_no_changes') return Response.json({ ok: true, no_changes: true });
120
+ return Response.json({ ok: false, error: result.error || 'update_failed' }, { status: 502 });
121
+ }
122
+ return Response.json({ ok: true, provider_id: body.provider_id });
123
+ } catch (e: unknown) {
124
+ return Response.json({ ok: false, error: e instanceof Error ? e.message : String(e) }, { status: 502 });
125
+ }
126
+ }
127
+
128
+ const name = (body.name || '').toString().trim();
129
+ if (!name) return Response.json({ error: 'name required' }, { status: 400 });
130
+ const vendor = (body.type || 'openai-compatible').toString();
131
+ if (!VENDORS.includes(vendor as (typeof VENDORS)[number])) {
132
+ return Response.json({ error: `type must be one of: ${VENDORS.join(', ')}` }, { status: 400 });
133
+ }
134
+ const base_url = (body.base_url || '').toString().trim();
135
+ if (!base_url) return Response.json({ error: 'base_url required' }, { status: 400 });
136
+ const modelNames = Array.isArray(body.models) ? body.models.map(m => String(m).trim()).filter(Boolean) : [];
137
+ const apiKey = (body.apiKey || '').toString();
138
+ // secret-first: the backend requires secret_key_ref to already be in the vault.
139
+ if (!apiKey) return Response.json({ ok: false, error: 'API key 必填(供应商创建需先写入密钥库)' }, { status: 400 });
140
+
141
+ if (process.env.MOCK_PROVIDERS === '1') {
142
+ return Response.json({ ok: true, mock: true, provider_id: `prov_mock_${Date.now().toString(36)}` });
143
+ }
144
+
145
+ const networkId = body.network_id || (await resolveDefaultNetworkId());
146
+ const netArg = networkId ? { network_id: networkId } : {};
147
+ const secret_key_ref = secretKeyFor(name);
148
+
149
+ try {
150
+ // 1) vault the key (OWNER-only on the hub side).
151
+ const sres = await callMcp('upsert_network_secret', { ...netArg, key: secret_key_ref, value: apiKey });
152
+ if (sres.status === 404 || sres.status === 501) {
153
+ return Response.json({ ok: false, unconfirmed: true, error: 'hub lacks RFC-028 upsert_network_secret (needs #308)' }, { status: 200 });
154
+ }
155
+ const sresult = (await parseMcpEnvelope(sres)) as { ok?: boolean; error?: string };
156
+ if (sresult?.ok === false) {
157
+ return Response.json({ ok: false, error: sresult.error || 'secret_write_failed', detail: 'vault 写入失败(可能需 OWNER 角色)' }, { status: 502 });
158
+ }
159
+ // 2) create the provider referencing the vault key + models as objects.
160
+ const models = modelNames.map(m => ({ model_name: m }));
161
+ const pres = await callMcp('upsert_provider', { ...netArg, name, vendor, base_url, secret_key_ref, models });
162
+ if (pres.status === 404 || pres.status === 501) {
163
+ return Response.json({ ok: false, unconfirmed: true, error: 'hub lacks RFC-028 upsert_provider (needs #308)' }, { status: 200 });
164
+ }
165
+ const presult = (await parseMcpEnvelope(pres)) as { ok?: boolean; error?: string; provider_id?: string };
166
+ if (presult?.ok === false) return Response.json({ ok: false, error: presult.error || 'upsert_failed', result: presult }, { status: 502 });
167
+ return Response.json({ ok: true, provider_id: presult?.provider_id });
168
+ } catch (e: unknown) {
169
+ return Response.json({ ok: false, error: e instanceof Error ? e.message : String(e) }, { status: 502 });
170
+ }
171
+ }
172
+
173
+ export async function DELETE(req: Request) {
174
+ const authFailure = await requireDashboardAuth();
175
+ if (authFailure) return authFailure;
176
+ const { searchParams } = new URL(req.url);
177
+ const providerId = searchParams.get('id');
178
+ if (!providerId) return Response.json({ error: 'id required' }, { status: 400 });
179
+ if (process.env.MOCK_PROVIDERS === '1') return Response.json({ ok: true, mock: true });
180
+ // Soft-delete = update_provider{enabled:false} (#317; no delete_provider).
181
+ const networkId = await resolveDefaultNetworkId();
182
+ try {
183
+ const res = await callMcp('update_provider', { provider_id: providerId, ...(networkId ? { network_id: networkId } : {}), patch: { enabled: false } });
184
+ if (res.status === 404 || res.status === 501) return Response.json({ ok: false, unconfirmed: true, error: 'hub lacks update_provider (needs #317)' }, { status: 200 });
185
+ const result = (await parseMcpEnvelope(res)) as { ok?: boolean; error?: string };
186
+ if (result?.ok === false && result.error !== 'no_changes') return Response.json({ ok: false, error: result.error || 'disable_failed' }, { status: 502 });
187
+ return Response.json({ ok: true });
188
+ } catch (e: unknown) {
189
+ return Response.json({ ok: false, error: e instanceof Error ? e.message : String(e) }, { status: 502 });
190
+ }
191
+ }
@@ -36,7 +36,6 @@ export async function POST(req: Request) {
36
36
  }
37
37
 
38
38
  if (action === 'change_password') {
39
- // UI calls it current_password; the hub expects old_password.
40
39
  const { token: userToken, current_password, new_password } = payload;
41
40
  const res = await hubFetch('/api/auth/password', {
42
41
  method: 'POST',
@@ -45,18 +44,7 @@ export async function POST(req: Request) {
45
44
  });
46
45
  const data = await res.json();
47
46
  const response = NextResponse.json(data);
48
- // A successful password change rotates the token server-side, so the
49
- // hub returns a fresh one. Re-issue the session cookie with it —
50
- // otherwise the old token in the existing cookie is now invalid and
51
- // the user's very next request would 401 (logged out mid-session).
52
- // This is the only action that touches the cookie; the rest just proxy.
53
47
  if (data.ok && data.token) {
54
- // Behind the Caddy TLS terminator the connection to Next is plain
55
- // http, so req.url's protocol reads "http" and a secure cookie would
56
- // never be set over the user's real HTTPS session — trust the
57
- // x-forwarded-proto the proxy sets, falling back to the raw protocol
58
- // for direct (non-proxied) hits. COOKIE_INSECURE=1 forces it off for
59
- // local http dev.
60
48
  const proto = req.headers.get('x-forwarded-proto') || new URL(req.url).protocol.replace(':', '');
61
49
  response.cookies.set(DASHBOARD_SESSION_COOKIE, `v3:${data.token}`, {
62
50
  httpOnly: true,
@@ -1,4 +1,4 @@
1
- import { requireDashboardAuth } from '@/app/lib/dashboard-auth';
1
+ import { requireDashboardAuth, getV3UserToken } from '@/app/lib/dashboard-auth';
2
2
  import { hubFetch } from '@/app/lib/hub';
3
3
 
4
4
  export async function GET(req: Request) {
@@ -9,20 +9,6 @@ async function hubHeaders(): Promise<Record<string, string>> {
9
9
  return h;
10
10
  }
11
11
 
12
- /**
13
- * Node list with a three-tier fallback so /nodes is never blank while
14
- * agents are demonstrably live:
15
- * 1. hub /api/nodes — the persistent node registry (the canonical source).
16
- * 2. registry empty but sessions exist — derive node rows from live
17
- * /api/status sessions (tagged `source: 'sessions'`). The registry can
18
- * lag or be empty (older hub, node never persisted) even when agents
19
- * are actively connected; deriving from sessions keeps the page useful
20
- * instead of showing "no nodes" next to a busy fleet (cf. #92 / #74).
21
- * 3. upstream non-JSON / not-ok — empty list tagged `source: 'fallback'`,
22
- * so the client renders the empty state rather than erroring.
23
- * The `source` tag lets the client distinguish registry data from the
24
- * session-derived stand-in. A thrown fetch (hub down) is the only 502.
25
- */
26
12
  export async function GET(req: Request) {
27
13
  const authFailure = await requireDashboardAuth();
28
14
  if (authFailure) return authFailure;
@@ -6,12 +6,6 @@ import path from 'path';
6
6
  const UPLOAD_DIR = '/tmp/agent-network-dashboard-uploads';
7
7
  const MAX_BYTES = 12 * 1024 * 1024;
8
8
 
9
- // Generate the on-disk name from scratch — the user's original filename is
10
- // discarded entirely, keeping only a sanitized extension. This makes stored
11
- // names unguessable and path-traversal-proof (no "../" can survive), so the
12
- // untrusted upload name never reaches the filesystem. The "<epoch>-<uuid>.<ext>"
13
- // shape is the contract the GET handler's regex re-validates against — keep
14
- // the two in sync if this format ever changes.
15
9
  function safeName(name: string) {
16
10
  const ext = path.extname(name).toLowerCase().replace(/[^a-z0-9.]/g, '');
17
11
  return `${Date.now()}-${randomUUID()}${ext || '.bin'}`;
@@ -63,9 +57,6 @@ export async function GET(req: Request) {
63
57
 
64
58
  const url = new URL(req.url);
65
59
  const filename = url.searchParams.get('file') || '';
66
- // Path-traversal guard: only serve names matching safeName's exact shape
67
- // (<epoch>-<uuid>.<ext>). The pattern admits no '/', '\' or '.' runs, so a
68
- // crafted ?file=../../etc/passwd is rejected before it reaches path.join.
69
60
  if (!/^[0-9]+-[a-f0-9-]+\.[a-z0-9]+$/i.test(filename)) {
70
61
  return Response.json({ error: 'invalid file' }, { status: 400 });
71
62
  }
@@ -7,6 +7,7 @@ interface CommandCenterProps {
7
7
  /** Currently open chat tabs */
8
8
  tabs: string[];
9
9
  activeTab: string;
10
+ onOpenTab: (alias: string) => void;
10
11
  onCloseTab: (alias: string) => void;
11
12
  onSetActive: (alias: string) => void;
12
13
  onClose: () => void;
@@ -16,7 +17,7 @@ interface CommandCenterProps {
16
17
  * Multi-tab chat panel for commanding multiple agents simultaneously.
17
18
  * Wraps TaskChatPanel with a tab bar for switching between agents.
18
19
  */
19
- export function CommandCenter({ tabs, activeTab, onCloseTab, onSetActive, onClose }: CommandCenterProps) {
20
+ export function CommandCenter({ tabs, activeTab, onOpenTab, onCloseTab, onSetActive, onClose }: CommandCenterProps) {
20
21
  if (tabs.length === 0) return null;
21
22
 
22
23
  return (
@@ -67,11 +68,7 @@ export function CommandCenter({ tabs, activeTab, onCloseTab, onSetActive, onClos
67
68
  </button>
68
69
  </div>
69
70
 
70
- {/* Render every open tab, toggling visibility with CSS (block/hidden)
71
- rather than conditionally mounting only the active one. Each
72
- InlineChat owns a live SSE subscription plus scroll position and
73
- an unsent draft — unmounting on tab switch would tear down the SSE
74
- and lose scroll/draft. Don't "optimize" this to render only active. */}
71
+ {/* Active chat - render all but only show active (preserves state) */}
75
72
  <div className="flex-1 relative overflow-hidden">
76
73
  {tabs.map(alias => (
77
74
  <div key={alias} className={`absolute inset-0 ${activeTab === alias ? 'block' : 'hidden'}`}>
@@ -59,11 +59,6 @@ function fuzzyMatch(hay: string, needle: string): FuzzyResult {
59
59
  const N = needle.toLowerCase();
60
60
  let hi = 0, ni = 0, score = 0, streak = 0;
61
61
  const indices: number[] = [];
62
- // Scoring, highest-weighted first: consecutive matches (the `streak`
63
- // bonus stacks on the base +2/char, so contiguous hits beat scattered
64
- // ones), then matches at a word boundary (+4 — "sl" ranks "Server Logs"
65
- // high, Linear/Raycast style), then a small length penalty at the end as
66
- // a tiebreaker that prefers tighter/shorter haystacks.
67
62
  while (hi < H.length && ni < N.length) {
68
63
  if (H[hi] === N[ni]) {
69
64
  score += 2 + streak;