@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.
- package/.next/BUILD_COMMIT +1 -1
- package/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +5 -0
- package/.next/build-manifest.json +3 -3
- package/.next/cache/.previewinfo +1 -0
- package/.next/cache/.rscinfo +1 -0
- package/.next/diagnostics/route-bundle-stats.json +56 -39
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/prerender-manifest.json +27 -3
- package/.next/routes-manifest.json +30 -0
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +2 -2
- package/.next/server/app/_not-found.rsc +13 -13
- package/.next/server/app/_not-found.segments/_full.segment.rsc +13 -13
- package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/server/app/_not-found.segments/_index.segment.rsc +8 -8
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
- package/.next/server/app/admin.html +2 -2
- package/.next/server/app/admin.rsc +15 -15
- package/.next/server/app/admin.segments/_full.segment.rsc +15 -15
- package/.next/server/app/admin.segments/_head.segment.rsc +4 -4
- package/.next/server/app/admin.segments/_index.segment.rsc +8 -8
- package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/admin.segments/admin.segment.rsc +3 -3
- package/.next/server/app/api/anet/host-supervisors/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/anet/host-supervisors/route/build-manifest.json +9 -0
- package/.next/server/app/api/anet/host-supervisors/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/anet/host-supervisors/route.js +7 -0
- package/.next/server/app/api/anet/host-supervisors/route.js.map +5 -0
- package/.next/server/app/api/anet/host-supervisors/route.js.nft.json +1 -0
- package/.next/server/app/api/anet/host-supervisors/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/anet/providers/probe/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/anet/providers/probe/route/build-manifest.json +9 -0
- package/.next/server/app/api/anet/providers/probe/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/anet/providers/probe/route.js +7 -0
- package/.next/server/app/api/anet/providers/probe/route.js.map +5 -0
- package/.next/server/app/api/anet/providers/probe/route.js.nft.json +1 -0
- package/.next/server/app/api/anet/providers/probe/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/anet/providers/probe-results/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/anet/providers/probe-results/route/build-manifest.json +9 -0
- package/.next/server/app/api/anet/providers/probe-results/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/anet/providers/probe-results/route.js +7 -0
- package/.next/server/app/api/anet/providers/probe-results/route.js.map +5 -0
- package/.next/server/app/api/anet/providers/probe-results/route.js.nft.json +1 -0
- package/.next/server/app/api/anet/providers/probe-results/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/anet/providers/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/anet/providers/route/build-manifest.json +9 -0
- package/.next/server/app/api/anet/providers/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/anet/providers/route.js +8 -0
- package/.next/server/app/api/anet/providers/route.js.map +5 -0
- package/.next/server/app/api/anet/providers/route.js.nft.json +1 -0
- package/.next/server/app/api/anet/providers/route_client-reference-manifest.js +3 -0
- package/.next/server/app/index.html +2 -2
- package/.next/server/app/index.rsc +15 -15
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/index.segments/_full.segment.rsc +15 -15
- package/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/server/app/index.segments/_index.segment.rsc +8 -8
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login.html +2 -2
- package/.next/server/app/login.rsc +15 -15
- package/.next/server/app/login.segments/_full.segment.rsc +15 -15
- package/.next/server/app/login.segments/_head.segment.rsc +4 -4
- package/.next/server/app/login.segments/_index.segment.rsc +8 -8
- package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/login.segments/login.segment.rsc +3 -3
- package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/logs.html +2 -2
- package/.next/server/app/logs.rsc +15 -15
- package/.next/server/app/logs.segments/_full.segment.rsc +15 -15
- package/.next/server/app/logs.segments/_head.segment.rsc +4 -4
- package/.next/server/app/logs.segments/_index.segment.rsc +8 -8
- package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/logs.segments/logs.segment.rsc +3 -3
- package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
- package/.next/server/app/messages.html +2 -2
- package/.next/server/app/messages.rsc +15 -15
- package/.next/server/app/messages.segments/_full.segment.rsc +15 -15
- package/.next/server/app/messages.segments/_head.segment.rsc +4 -4
- package/.next/server/app/messages.segments/_index.segment.rsc +8 -8
- package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/messages.segments/messages.segment.rsc +3 -3
- package/.next/server/app/node/page_client-reference-manifest.js +1 -1
- package/.next/server/app/node.html +2 -2
- package/.next/server/app/node.rsc +15 -15
- package/.next/server/app/node.segments/_full.segment.rsc +15 -15
- package/.next/server/app/node.segments/_head.segment.rsc +4 -4
- package/.next/server/app/node.segments/_index.segment.rsc +8 -8
- package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/node.segments/node.segment.rsc +3 -3
- package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
- package/.next/server/app/nodes.html +2 -2
- package/.next/server/app/nodes.rsc +15 -15
- package/.next/server/app/nodes.segments/_full.segment.rsc +15 -15
- package/.next/server/app/nodes.segments/_head.segment.rsc +4 -4
- package/.next/server/app/nodes.segments/_index.segment.rsc +8 -8
- package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/nodes.segments/nodes.segment.rsc +3 -3
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/providers/page/app-paths-manifest.json +3 -0
- package/.next/server/app/providers/page/build-manifest.json +17 -0
- package/.next/server/app/providers/page/next-font-manifest.json +11 -0
- package/.next/server/app/providers/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/providers/page/server-reference-manifest.json +4 -0
- package/.next/server/app/providers/page.js +14 -0
- package/.next/server/app/providers/page.js.map +5 -0
- package/.next/server/app/providers/page.js.nft.json +1 -0
- package/.next/server/app/providers/page_client-reference-manifest.js +3 -0
- package/.next/server/app/providers.html +12 -0
- package/.next/server/app/providers.meta +15 -0
- package/.next/server/app/providers.rsc +27 -0
- package/.next/server/app/providers.segments/_full.segment.rsc +27 -0
- package/.next/server/app/providers.segments/_head.segment.rsc +6 -0
- package/.next/server/app/providers.segments/_index.segment.rsc +10 -0
- package/.next/server/app/providers.segments/_tree.segment.rsc +5 -0
- package/.next/server/app/providers.segments/providers/__PAGE__.segment.rsc +9 -0
- package/.next/server/app/providers.segments/providers.segment.rsc +5 -0
- package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs.html +2 -2
- package/.next/server/app/server-logs.rsc +15 -15
- package/.next/server/app/server-logs.segments/_full.segment.rsc +15 -15
- package/.next/server/app/server-logs.segments/_head.segment.rsc +4 -4
- package/.next/server/app/server-logs.segments/_index.segment.rsc +8 -8
- package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/server-logs.segments/server-logs.segment.rsc +3 -3
- package/.next/server/app/servers/page_client-reference-manifest.js +1 -1
- package/.next/server/app/servers.html +2 -2
- package/.next/server/app/servers.rsc +15 -15
- package/.next/server/app/servers.segments/_full.segment.rsc +15 -15
- package/.next/server/app/servers.segments/_head.segment.rsc +4 -4
- package/.next/server/app/servers.segments/_index.segment.rsc +8 -8
- package/.next/server/app/servers.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/servers.segments/servers/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/servers.segments/servers.segment.rsc +3 -3
- package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/networks.html +2 -2
- package/.next/server/app/settings/networks.rsc +15 -15
- package/.next/server/app/settings/networks.segments/_full.segment.rsc +15 -15
- package/.next/server/app/settings/networks.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings/networks.segments/_index.segment.rsc +8 -8
- package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +3 -3
- package/.next/server/app/settings/networks.segments/settings.segment.rsc +3 -3
- package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens.html +2 -2
- package/.next/server/app/settings/tokens.rsc +15 -15
- package/.next/server/app/settings/tokens.segments/_full.segment.rsc +15 -15
- package/.next/server/app/settings/tokens.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings/tokens.segments/_index.segment.rsc +8 -8
- package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +3 -3
- package/.next/server/app/settings/tokens.segments/settings.segment.rsc +3 -3
- package/.next/server/app/settings.html +2 -2
- package/.next/server/app/settings.rsc +15 -15
- package/.next/server/app/settings.segments/_full.segment.rsc +15 -15
- package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
- package/.next/server/app/settings.segments/_index.segment.rsc +8 -8
- package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
- package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks.html +2 -2
- package/.next/server/app/tasks.rsc +15 -15
- package/.next/server/app/tasks.segments/_full.segment.rsc +15 -15
- package/.next/server/app/tasks.segments/_head.segment.rsc +4 -4
- package/.next/server/app/tasks.segments/_index.segment.rsc +8 -8
- package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/tasks.segments/tasks.segment.rsc +3 -3
- package/.next/server/app-paths-manifest.json +5 -0
- package/.next/server/chunks/00jm_next_dist_esm_build_templates_app-route_0bobkt3.js +3 -0
- package/.next/server/chunks/00jm_next_dist_esm_build_templates_app-route_0bobkt3.js.map +1 -0
- package/.next/server/chunks/0dk5_next-internal_server_app_api_anet_providers_probe-results_route_actions_07.d.5a.js +3 -0
- package/.next/server/chunks/0dk5_next-internal_server_app_api_anet_providers_probe-results_route_actions_07.d.5a.js.map +1 -0
- package/.next/server/chunks/0ykm__next-internal_server_app_api_anet_host-supervisors_route_actions_0g3hek2.js +3 -0
- package/.next/server/chunks/0ykm__next-internal_server_app_api_anet_host-supervisors_route_actions_0g3hek2.js.map +1 -0
- package/.next/server/chunks/0ykm__next-internal_server_app_api_anet_providers_probe_route_actions_05f000..js +3 -0
- package/.next/server/chunks/0ykm__next-internal_server_app_api_anet_providers_probe_route_actions_05f000..js.map +1 -0
- package/.next/server/chunks/0ykm__next-internal_server_app_api_anet_providers_route_actions_10htbhd.js +3 -0
- package/.next/server/chunks/0ykm__next-internal_server_app_api_anet_providers_route_actions_10htbhd.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0-29ynz._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0-2le8-._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0-8_f0o._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__02p2n3n._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__03nze3z._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__03nze3z._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__043tnx2._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__04z62zk._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__07ztet2._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0aqb4n5._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0aqb4n5._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0cphmer._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0cphmer._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0e3ucl1._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0e6yail._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0gx2_6a._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0hg3_8r._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0lhq4ha._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0mkwzz7._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0mkwzz7._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0mxw4vb._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0mzopco._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0o45a4q._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0w1w_w0._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0w1w_w0._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0xtp-et._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0yyo7k5._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__0yyo7k5._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__0~rwgo1._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0~rwgo1._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__10pvabe._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__10t11zq._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__12r~omy._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__1389~cs._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__13n8t..._.js.map +1 -1
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_02lorbl.js +4 -0
- package/.next/server/chunks/ssr/00jm_next_dist_esm_build_templates_app-page_02lorbl.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__030vg4n._.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__04mx~5g._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__04mx~5g._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__05kf31s._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__05kf31s._.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__096ytyk._.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0fhoq8i._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0fhoq8i._.js.map +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0h5dae6._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0h5dae6._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js +3 -3
- package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard__next-internal_server_app_providers_page_actions_0ou6p43.js +3 -0
- package/.next/server/chunks/ssr/agent-network-dashboard__next-internal_server_app_providers_page_actions_0ou6p43.js.map +1 -0
- package/.next/server/chunks/ssr/agent-network-dashboard_app_012oyw5._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_012oyw5._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0_d45-d._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0_d45-d._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0gd.4pc._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_0gd.4pc._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_12l4oto._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0r7kb.o._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_components_0r7kb.o._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_components_EmptyState_tsx_0aol-el._.js +3 -0
- package/.next/server/chunks/ssr/agent-network-dashboard_app_components_EmptyState_tsx_0aol-el._.js.map +1 -0
- package/.next/server/chunks/ssr/agent-network-dashboard_app_nodes_page_tsx_11haf_p._.js +2 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_nodes_page_tsx_11haf_p._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_providers_page_tsx_0hw2n0v._.js +3 -0
- package/.next/server/chunks/ssr/agent-network-dashboard_app_providers_page_tsx_0hw2n0v._.js.map +1 -0
- package/.next/server/chunks/ssr/agent-network-dashboard_app_tasks_page_tsx_0mwxy4z._.js.map +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/next-font-manifest.js +1 -1
- package/.next/server/next-font-manifest.json +4 -0
- package/.next/server/pages/404.html +2 -2
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/{10kkhdde5ve~c.js → 0-z_kfck7-6_1.js} +3 -3
- package/.next/static/chunks/049vx3qljs1tt.js +1 -0
- package/.next/static/chunks/06.5euf239uvr.css +1 -0
- package/.next/static/chunks/{0vun~4ljcrj3p.js → 091hae.lhv9t1.js} +2 -2
- package/.next/static/chunks/0chpv7zsh-qrg.js +1 -0
- package/.next/static/chunks/0i-l67o_ae5hk.js +2 -0
- package/.next/static/chunks/{0vus9xpsz0s~i.js → 0l.gu-iqnmeja.js} +1 -1
- package/.next/static/chunks/{149a4l50_3vw-.js → 0mnmn-~ava1vy.js} +1 -1
- package/.next/static/chunks/0o-b62_a66.jr.js +1 -0
- package/.next/static/chunks/0pk6amtz5icbx.js +1 -0
- package/.next/static/chunks/0r4u1.sl.8p15.js +1 -0
- package/.next/static/chunks/0wz0122ym_gr3.js +1 -0
- package/.next/static/chunks/15aqdc5txzq9r.js +1 -0
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/.next/types/routes.d.ts +7 -2
- package/.next/types/validator.ts +45 -0
- package/app/admin/page.tsx +3 -1
- package/app/api/anet/host-supervisors/route.ts +102 -0
- package/app/api/anet/node-config/route.ts +26 -2
- package/app/api/anet/node-create/route.ts +14 -5
- package/app/api/anet/node-lifecycle/route.ts +54 -5
- package/app/api/anet/providers/probe/route.ts +79 -0
- package/app/api/anet/providers/probe-results/route.ts +60 -0
- package/app/api/anet/providers/route.ts +191 -0
- package/app/api/hub/auth/route.ts +0 -12
- package/app/api/hub/networks/route.ts +1 -1
- package/app/api/hub/nodes/route.ts +0 -14
- package/app/api/hub/upload/route.ts +0 -9
- package/app/components/CommandCenter.tsx +3 -6
- package/app/components/CommandPalette.tsx +0 -5
- package/app/components/CreateNodeWizard.tsx +140 -47
- package/app/components/HostSupervisorPicker.tsx +283 -0
- package/app/components/NodeLifecycleMenu.tsx +436 -0
- package/app/components/NodeSettingsPanel.tsx +80 -39
- package/app/components/ProviderFormModal.tsx +303 -0
- package/app/components/ReachabilityMatrix.tsx +196 -0
- package/app/components/Sidebar.tsx +1 -0
- package/app/components/TaskDrawer.tsx +1 -0
- package/app/components/TopoGraph.tsx +4 -8
- package/app/components/UserBar.tsx +37 -0
- package/app/components/types.ts +11 -0
- package/app/lib/chat-unread.ts +0 -6
- package/app/lib/dashboard-auth.ts +0 -12
- package/app/lib/hooks.ts +22 -4
- package/app/lib/hub.ts +4 -0
- package/app/lib/network-context.tsx +0 -6
- package/app/lib/rate-limit.ts +2 -16
- package/app/node/page.tsx +12 -1
- package/app/nodes/page.tsx +42 -2
- package/app/page.tsx +1 -0
- package/app/providers/page.tsx +182 -0
- package/app/settings/networks/page.tsx +1 -1
- package/app/settings/page.tsx +5 -0
- package/app/tasks/[id]/page.tsx +1 -0
- package/app/tasks/page.tsx +1 -0
- package/package.json +1 -1
- package/.next/static/chunks/0-t2rbg9~-oh5.js +0 -1
- package/.next/static/chunks/0iv.0p9_5b36e.js +0 -1
- package/.next/static/chunks/0l_hz3xrjwumg.js +0 -1
- package/.next/static/chunks/0lmdw~i5qjqsg.js +0 -1
- package/.next/static/chunks/0vruzstkdr99w.js +0 -1
- package/.next/static/chunks/0xssg9sin~2xw.js +0 -1
- package/.next/static/chunks/124dtwo1k24ao.css +0 -1
- package/bun.lock +0 -1663
- /package/.next/static/{ZxdmFd_iOEELuA2Km4Q5t → tRPXkJdGLR6a0skqvMgQa}/_buildManifest.js +0 -0
- /package/.next/static/{ZxdmFd_iOEELuA2Km4Q5t → tRPXkJdGLR6a0skqvMgQa}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{ZxdmFd_iOEELuA2Km4Q5t → tRPXkJdGLR6a0skqvMgQa}/_ssgManifest.js +0 -0
|
@@ -2,29 +2,46 @@
|
|
|
2
2
|
|
|
3
3
|
import { useEffect, useState } from 'react';
|
|
4
4
|
import { useNetworkId } from '../lib/network-context';
|
|
5
|
+
import { DaemonOption, HostSupervisorPicker } from './HostSupervisorPicker';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
|
-
* Create-node wizard (node-lifecycle UI M2 — RFC-026 §3.1
|
|
8
|
-
*
|
|
8
|
+
* Create-node wizard (node-lifecycle UI M2/PR4 — RFC-026 §3.1).
|
|
9
|
+
* 6 steps now: ⓪ host (PR4 #338) ① name ② runtime ③ model ④ flags ⑤ confirm
|
|
10
|
+
* → POST /api/anet/node-create with `daemon_node_id` set to the chosen host.
|
|
9
11
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* -
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
12
|
+
* PR4 (#338 main lane PR4) folds RFC-026 §9.4 host_supervisor picker in front
|
|
13
|
+
* of the existing 5 steps. Three states the picker resolves internally:
|
|
14
|
+
* - count=0 → onboarding (no daemon, show install command + block forward)
|
|
15
|
+
* - count=1 → auto-pick + forward immediately
|
|
16
|
+
* - count≥2 → user picks, then forward
|
|
17
|
+
* The wizard now ALWAYS passes daemon_node_id to /api/anet/node-create (the
|
|
18
|
+
* route's `resolveLocalDaemonNodeId` fallback only fires if daemon_node_id is
|
|
19
|
+
* absent — kept for back-compat with non-wizard callers but no longer used
|
|
20
|
+
* from this flow). Per [[feedback_doc_capability_claim_verify_code_path]] —
|
|
21
|
+
* the API contract is exercised locally before any prod hub touches the path.
|
|
19
22
|
*/
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
// IDs MUST match the hub validator enums (server/src/create-node-validate.ts).
|
|
25
|
+
// Caught via local /mcp probe during mobile wizard build (#338 plan B):
|
|
26
|
+
// pre-fix RUNTIMES had 'codex' + 'grok' but hub accepts 'codex-sdk' +
|
|
27
|
+
// 'grok-build-acp'; pre-fix PERMISSION_MODES had 'auto' but hub rejects it
|
|
28
|
+
// (flag_value_invalid). The wizard has been silently shipping invalid combos
|
|
29
|
+
// for any non-claude-agent-sdk pick since M2 — only worked end-to-end with
|
|
30
|
+
// the default claude path.
|
|
31
|
+
//
|
|
32
|
+
// `defaultModel` — hub's `create_node.node_spec.model` schema is
|
|
33
|
+
// `z.string().min(1).max(100)`; the wizard's "默认" option leaves the state
|
|
34
|
+
// empty, so pre-fix the POST body dropped `model` entirely and hub rejected
|
|
35
|
+
// with `Invalid input: expected string, received undefined`. `defaultModel`
|
|
36
|
+
// gets substituted before submit (and shown in the dropdown label so the
|
|
37
|
+
// operator knows what "默认" will actually become).
|
|
38
|
+
const RUNTIMES: { id: string; label: string; models: string[]; defaultModel: string }[] = [
|
|
39
|
+
{ id: 'claude-agent-sdk', label: 'Claude Agent SDK', models: ['deepseek-v4-pro', 'MiniMax-M3', 'claude-sonnet-4-6', 'claude-opus-4-x'], defaultModel: 'claude-sonnet-4-6' },
|
|
40
|
+
{ id: 'codex-sdk', label: 'Codex SDK', models: ['gpt-5.5'], defaultModel: 'gpt-5.5' },
|
|
41
|
+
{ id: 'grok-build-acp', label: 'Grok (build-acp)', models: ['grok-build'], defaultModel: 'grok-build' },
|
|
25
42
|
];
|
|
26
|
-
const PERMISSION_MODES = ['
|
|
27
|
-
const STEPS = ['名字', 'Runtime', '模型', '参数', '确认'];
|
|
43
|
+
const PERMISSION_MODES = ['default', 'acceptEdits', 'plan', 'bypassPermissions'];
|
|
44
|
+
const STEPS = ['服务器', '名字', 'Runtime', '模型', '参数', '确认'];
|
|
28
45
|
|
|
29
46
|
type Phase = 'form' | 'creating' | 'done' | 'unconfirmed' | 'error';
|
|
30
47
|
|
|
@@ -38,10 +55,15 @@ export function CreateNodeWizard({
|
|
|
38
55
|
onCreated?: (result: unknown) => void;
|
|
39
56
|
}) {
|
|
40
57
|
const [step, setStep] = useState(0);
|
|
58
|
+
const [daemonNodeId, setDaemonNodeId] = useState<string | null>(null);
|
|
59
|
+
// (#338 wizard-runtime-filter) keep the full daemon row so the Runtime
|
|
60
|
+
// step can disable runtimes the chosen daemon doesn't declare support
|
|
61
|
+
// for. Hub-side enforcement still wins; this is UX surfacing.
|
|
62
|
+
const [daemon, setDaemon] = useState<DaemonOption | null>(null);
|
|
41
63
|
const [name, setName] = useState('');
|
|
42
64
|
const [runtimeId, setRuntimeId] = useState(RUNTIMES[0].id);
|
|
43
65
|
const [model, setModel] = useState('');
|
|
44
|
-
const [permissionMode, setPermissionMode] = useState('
|
|
66
|
+
const [permissionMode, setPermissionMode] = useState('default');
|
|
45
67
|
const [maxTurns, setMaxTurns] = useState('');
|
|
46
68
|
const [budget, setBudget] = useState('');
|
|
47
69
|
const [timeout, setTimeout] = useState('');
|
|
@@ -84,17 +106,26 @@ export function CreateNodeWizard({
|
|
|
84
106
|
|
|
85
107
|
const runtime = RUNTIMES.find(r => r.id === runtimeId) || RUNTIMES[0];
|
|
86
108
|
const nameValid = name.trim().length > 0;
|
|
87
|
-
const canNext =
|
|
109
|
+
const canNext =
|
|
110
|
+
(step === 0 && Boolean(daemonNodeId)) || // step 0: must have chosen a daemon
|
|
111
|
+
(step === 1 && nameValid) || // step 1: name non-empty
|
|
112
|
+
(step >= 2 && step < STEPS.length); // later steps: nothing required to advance
|
|
88
113
|
const busy = phase === 'creating';
|
|
89
114
|
|
|
90
115
|
async function handleCreate() {
|
|
91
116
|
setPhase('creating');
|
|
92
117
|
setMsg('');
|
|
93
118
|
const numOrUndef = (v: string) => (v.trim() === '' ? undefined : Number(v));
|
|
119
|
+
// Hub's create_node.node_spec.model schema is z.string().min(1); the
|
|
120
|
+
// wizard's "默认" option leaves state empty, so pick the runtime's
|
|
121
|
+
// documented default here. This mirrors what agent-node itself defaults
|
|
122
|
+
// to at boot (see agent-node cli.ts model resolution), so the "默认"
|
|
123
|
+
// dropdown label + this fallback both point at the same model.
|
|
124
|
+
const effectiveModel = model || runtime.defaultModel;
|
|
94
125
|
const node_spec = {
|
|
95
126
|
name: name.trim(),
|
|
96
127
|
runtime: runtimeId,
|
|
97
|
-
|
|
128
|
+
model: effectiveModel,
|
|
98
129
|
flags: {
|
|
99
130
|
permissionMode,
|
|
100
131
|
maxTurns: numOrUndef(maxTurns),
|
|
@@ -106,7 +137,11 @@ export function CreateNodeWizard({
|
|
|
106
137
|
const r = await fetch('/api/anet/node-create', {
|
|
107
138
|
method: 'POST',
|
|
108
139
|
headers: { 'Content-Type': 'application/json' },
|
|
109
|
-
body: JSON.stringify({
|
|
140
|
+
body: JSON.stringify({
|
|
141
|
+
node_spec,
|
|
142
|
+
...(daemonNodeId ? { daemon_node_id: daemonNodeId } : {}),
|
|
143
|
+
...(networkId ? { network_id: networkId } : {}),
|
|
144
|
+
}),
|
|
110
145
|
});
|
|
111
146
|
const data = await r.json().catch(() => ({}));
|
|
112
147
|
if (r.ok && data?.ok) {
|
|
@@ -135,7 +170,9 @@ export function CreateNodeWizard({
|
|
|
135
170
|
<div
|
|
136
171
|
role="dialog"
|
|
137
172
|
aria-label="新建节点"
|
|
138
|
-
|
|
173
|
+
// RFC-026 §9.4 responsive: mobile single-screen (full width minus
|
|
174
|
+
// gutter, taller); desktop ~3-col-friendly width when picker is shown.
|
|
175
|
+
className="fixed left-1/2 top-1/2 z-50 w-[min(94vw,440px)] md:w-[min(92vw,720px)] -translate-x-1/2 -translate-y-1/2 rounded-xl border border-[#26262b] bg-[#161618] shadow-2xl"
|
|
139
176
|
>
|
|
140
177
|
{/* Header */}
|
|
141
178
|
<div className="flex items-center justify-between border-b border-[#26262b] px-4 py-3">
|
|
@@ -187,44 +224,94 @@ export function CreateNodeWizard({
|
|
|
187
224
|
) : (
|
|
188
225
|
<>
|
|
189
226
|
{step === 0 && (
|
|
227
|
+
<div className="space-y-2">
|
|
228
|
+
<span className="text-xs text-gray-400">在哪台机器上创建</span>
|
|
229
|
+
<HostSupervisorPicker
|
|
230
|
+
networkId={netId || undefined}
|
|
231
|
+
value={daemonNodeId}
|
|
232
|
+
onChange={(id, d) => {
|
|
233
|
+
setDaemonNodeId(id);
|
|
234
|
+
setDaemon(d);
|
|
235
|
+
// (#338 wizard-runtime-filter) If the current runtime
|
|
236
|
+
// pick isn't supported by the new daemon, reset so
|
|
237
|
+
// the user is forced to re-pick on step 2. Otherwise
|
|
238
|
+
// they could land on step 5 (确认) with an
|
|
239
|
+
// already-invalid combo that only hub rejection
|
|
240
|
+
// surfaces.
|
|
241
|
+
const supported = d?.runtimes_supported;
|
|
242
|
+
if (supported && supported.length > 0 && !supported.includes(runtimeId)) {
|
|
243
|
+
setRuntimeId(supported[0]);
|
|
244
|
+
setModel('');
|
|
245
|
+
}
|
|
246
|
+
}}
|
|
247
|
+
/>
|
|
248
|
+
{!daemonNodeId && (
|
|
249
|
+
<p className="text-[11px] text-gray-600">
|
|
250
|
+
没选服务器之前无法继续;如果列表是空的,按提示在目标机器上跑 <code className="rounded bg-black/40 px-1 py-0.5">anet daemon up <name></code>。
|
|
251
|
+
</p>
|
|
252
|
+
)}
|
|
253
|
+
</div>
|
|
254
|
+
)}
|
|
255
|
+
{step === 1 && (
|
|
190
256
|
<label className="block space-y-1.5">
|
|
191
257
|
<span className="text-xs text-gray-400">节点名字</span>
|
|
192
258
|
<input autoFocus value={name} onChange={e => setName(e.target.value)} placeholder="例如 my-agent-1" className={inputCls} />
|
|
193
259
|
{!nameValid && <span className="text-[11px] text-gray-600">名字不能为空</span>}
|
|
194
260
|
</label>
|
|
195
261
|
)}
|
|
196
|
-
{step ===
|
|
262
|
+
{step === 2 && (
|
|
197
263
|
<div className="space-y-2">
|
|
198
|
-
<span className="text-xs text-gray-400">
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
264
|
+
<span className="text-xs text-gray-400">
|
|
265
|
+
Runtime{daemon ? `(${daemon.alias} 支持)` : ''}
|
|
266
|
+
</span>
|
|
267
|
+
{RUNTIMES.map(r => {
|
|
268
|
+
// (#338 wizard-runtime-filter) Permissive when the
|
|
269
|
+
// daemon didn't publish runtimes_supported at all
|
|
270
|
+
// (pre-PR3 daemons OR daemons not yet upgraded) — hub
|
|
271
|
+
// still validates. Restrictive only when the daemon
|
|
272
|
+
// explicitly told us its supported set.
|
|
273
|
+
const supported = daemon?.runtimes_supported;
|
|
274
|
+
const disabled = Array.isArray(supported) && supported.length > 0 && !supported.includes(r.id);
|
|
275
|
+
const selected = runtimeId === r.id;
|
|
276
|
+
return (
|
|
277
|
+
<button
|
|
278
|
+
key={r.id}
|
|
279
|
+
type="button"
|
|
280
|
+
disabled={disabled}
|
|
281
|
+
onClick={() => { if (!disabled) { setRuntimeId(r.id); setModel(''); } }}
|
|
282
|
+
title={disabled ? `${daemon?.alias || '该 daemon'} 未声明支持此 runtime` : undefined}
|
|
283
|
+
className={`flex w-full items-center justify-between rounded-md border px-3 py-2 text-sm transition-colors ${
|
|
284
|
+
disabled
|
|
285
|
+
? 'border-[#1c1c1f] bg-[#0a0a0c] text-gray-600 cursor-not-allowed'
|
|
286
|
+
: selected
|
|
287
|
+
? 'border-cyan-600 bg-cyan-900/15 text-cyan-200'
|
|
288
|
+
: 'border-[#26262b] bg-[#0e0e10] text-gray-300 hover:border-[#3a3a41]'
|
|
289
|
+
}`}
|
|
290
|
+
>
|
|
291
|
+
<span>
|
|
292
|
+
{r.label}
|
|
293
|
+
{disabled && <span className="ml-2 text-[10px] text-gray-700">该 daemon 不支持</span>}
|
|
294
|
+
</span>
|
|
295
|
+
{selected && !disabled && (
|
|
296
|
+
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden>
|
|
297
|
+
<path d="M20 6 9 17l-5-5" />
|
|
298
|
+
</svg>
|
|
299
|
+
)}
|
|
300
|
+
</button>
|
|
301
|
+
);
|
|
302
|
+
})}
|
|
216
303
|
</div>
|
|
217
304
|
)}
|
|
218
|
-
{step ===
|
|
305
|
+
{step === 3 && (
|
|
219
306
|
<label className="block space-y-1.5">
|
|
220
307
|
<span className="text-xs text-gray-400">模型({runtime.label})</span>
|
|
221
308
|
<select value={model} onChange={e => setModel(e.target.value)} className={inputCls}>
|
|
222
|
-
<option value=""
|
|
309
|
+
<option value="">默认({runtime.defaultModel})</option>
|
|
223
310
|
{runtime.models.map(m => <option key={m} value={m}>{m}</option>)}
|
|
224
311
|
</select>
|
|
225
312
|
</label>
|
|
226
313
|
)}
|
|
227
|
-
{step ===
|
|
314
|
+
{step === 4 && (
|
|
228
315
|
<div className="space-y-3">
|
|
229
316
|
<label className="block space-y-1.5">
|
|
230
317
|
<span className="text-xs text-gray-400">permissionMode</span>
|
|
@@ -239,17 +326,23 @@ export function CreateNodeWizard({
|
|
|
239
326
|
</div>
|
|
240
327
|
</div>
|
|
241
328
|
)}
|
|
242
|
-
{step ===
|
|
329
|
+
{step === 5 && (
|
|
243
330
|
<div className="space-y-2 text-sm">
|
|
244
331
|
<div className="rounded-md border border-[#26262b] bg-[#0e0e10] divide-y divide-[#1c1c1f]">
|
|
245
|
-
{[
|
|
332
|
+
{[
|
|
333
|
+
['服务器', daemonNodeId ? `${daemonNodeId.slice(0, 24)}…` : '—'],
|
|
334
|
+
['名字', name.trim() || '—'],
|
|
335
|
+
['Runtime', runtime.label],
|
|
336
|
+
['模型', model || `默认(${runtime.defaultModel})`],
|
|
337
|
+
['permissionMode', permissionMode],
|
|
338
|
+
['maxTurns / budget / timeout', `${maxTurns || '—'} / ${budget || '—'} / ${timeout || '—'}`],
|
|
339
|
+
].map(([k, v]) => (
|
|
246
340
|
<div key={k} className="flex items-start justify-between gap-3 px-3 py-2">
|
|
247
341
|
<span className="shrink-0 text-gray-500 text-xs">{k}</span>
|
|
248
342
|
<span className="text-right text-gray-200 text-xs break-all">{v}</span>
|
|
249
343
|
</div>
|
|
250
344
|
))}
|
|
251
345
|
</div>
|
|
252
|
-
<p className="text-[11px] text-gray-600">P1:创建在本机 daemon(绕过选服务器)。</p>
|
|
253
346
|
</div>
|
|
254
347
|
)}
|
|
255
348
|
</>
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* PR4 #338 — host_supervisor daemon picker (RFC-026 §9.4 locked mockup).
|
|
7
|
+
*
|
|
8
|
+
* Three states (the only branching the wizard ever sees):
|
|
9
|
+
*
|
|
10
|
+
* count=0 → onboarding: explain what a daemon is + give the install command.
|
|
11
|
+
* No daemon = nothing to dispatch to; create flow is blocked here
|
|
12
|
+
* until the user runs `anet daemon init <name>` somewhere.
|
|
13
|
+
*
|
|
14
|
+
* count=1 → auto-pick: just show "using <alias>" + a quiet `换一个 →` link
|
|
15
|
+
* (which switches to the picker view if the user really wants).
|
|
16
|
+
*
|
|
17
|
+
* count≥2 → picker grid: cards for each daemon w/ runtimes + alert chip,
|
|
18
|
+
* click selects. Desktop = up to 3 columns; mobile = single column.
|
|
19
|
+
*
|
|
20
|
+
* Data shape mirrors `/api/anet/host-supervisors`, which in turn mirrors the
|
|
21
|
+
* hub's GET /api/host-supervisors (#338 PR2 — needs commhub-server@0.9.0-preview.8+).
|
|
22
|
+
* On `unconfirmed` (older hub), we degrade honestly to an upgrade hint — never
|
|
23
|
+
* show a fake empty list. Per [[feedback_doc_capability_claim_verify_code_path]].
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
export interface DaemonOption {
|
|
27
|
+
// Hub canonical key is `daemon_node_id` (PR2 v2 §9.2 contract). We keep the
|
|
28
|
+
// same name end-to-end so the value the wizard passes back to create_node
|
|
29
|
+
// as `daemon_node_id` doesn't need a rename layer.
|
|
30
|
+
daemon_node_id: string;
|
|
31
|
+
alias: string;
|
|
32
|
+
hostname?: string | null;
|
|
33
|
+
online?: boolean;
|
|
34
|
+
last_seen_at?: string | null;
|
|
35
|
+
runtimes_supported?: string[];
|
|
36
|
+
host_telemetry?: {
|
|
37
|
+
alert_level?: 'green' | 'yellow' | 'red' | 'gray';
|
|
38
|
+
cpu_cores?: number | null;
|
|
39
|
+
mem_gb?: number | null;
|
|
40
|
+
ip_internal?: string | null;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface PickResponse {
|
|
45
|
+
ok: boolean;
|
|
46
|
+
unconfirmed?: boolean;
|
|
47
|
+
error?: string;
|
|
48
|
+
count: number;
|
|
49
|
+
daemons: DaemonOption[];
|
|
50
|
+
selected?: string | null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
type LoadState = 'loading' | 'ready' | 'error' | 'unconfirmed';
|
|
54
|
+
|
|
55
|
+
export function HostSupervisorPicker({
|
|
56
|
+
networkId,
|
|
57
|
+
value,
|
|
58
|
+
onChange,
|
|
59
|
+
}: {
|
|
60
|
+
networkId?: string | null;
|
|
61
|
+
value: string | null;
|
|
62
|
+
// (#338 wizard-runtime-filter) passes the full daemon row alongside the
|
|
63
|
+
// id so the wizard can filter the Runtime step by daemon.runtimes_supported
|
|
64
|
+
// — disabling combos the hub would reject anyway and surfacing why upfront.
|
|
65
|
+
onChange: (nodeId: string | null, daemon: DaemonOption | null) => void;
|
|
66
|
+
}) {
|
|
67
|
+
const [state, setState] = useState<LoadState>('loading');
|
|
68
|
+
const [daemons, setDaemons] = useState<DaemonOption[]>([]);
|
|
69
|
+
const [errMsg, setErrMsg] = useState('');
|
|
70
|
+
const [forcePicker, setForcePicker] = useState(false);
|
|
71
|
+
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
let alive = true;
|
|
74
|
+
setState('loading');
|
|
75
|
+
setErrMsg('');
|
|
76
|
+
const url = networkId
|
|
77
|
+
? `/api/anet/host-supervisors?network_id=${encodeURIComponent(networkId)}`
|
|
78
|
+
: '/api/anet/host-supervisors';
|
|
79
|
+
fetch(url, { cache: 'no-store' })
|
|
80
|
+
.then(r => r.json().then(d => ({ status: r.status, body: d as PickResponse })))
|
|
81
|
+
.then(({ status, body }) => {
|
|
82
|
+
if (!alive) return;
|
|
83
|
+
if (status === 501 || body?.unconfirmed) {
|
|
84
|
+
setState('unconfirmed');
|
|
85
|
+
setErrMsg(body?.error || 'hub /api/host-supervisors unavailable — upgrade to >=0.9.0-preview.8');
|
|
86
|
+
setDaemons([]);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (!body?.ok) {
|
|
90
|
+
setState('error');
|
|
91
|
+
setErrMsg(body?.error || `hub ${status}`);
|
|
92
|
+
setDaemons([]);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const list = Array.isArray(body.daemons) ? body.daemons : [];
|
|
96
|
+
setDaemons(list);
|
|
97
|
+
setState('ready');
|
|
98
|
+
// count=1 auto-pick: preselect the only daemon. count≥2 leaves the
|
|
99
|
+
// selection to the user (parent value stays null until click).
|
|
100
|
+
if (list.length === 1 && !value) onChange(list[0].daemon_node_id, list[0]);
|
|
101
|
+
})
|
|
102
|
+
.catch(e => {
|
|
103
|
+
if (!alive) return;
|
|
104
|
+
setState('error');
|
|
105
|
+
setErrMsg(e instanceof Error ? e.message : String(e));
|
|
106
|
+
setDaemons([]);
|
|
107
|
+
});
|
|
108
|
+
return () => { alive = false; };
|
|
109
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
110
|
+
}, [networkId]);
|
|
111
|
+
|
|
112
|
+
// ───── render branches ──────────────────────────────────────────────
|
|
113
|
+
|
|
114
|
+
if (state === 'loading') {
|
|
115
|
+
return (
|
|
116
|
+
<div className="flex items-center gap-2 rounded-md border border-[#26262b] bg-[#0e0e10] px-3 py-3 text-xs text-gray-500">
|
|
117
|
+
<svg className="h-3.5 w-3.5 animate-spin" viewBox="0 0 24 24" fill="none" aria-hidden>
|
|
118
|
+
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
|
119
|
+
<path className="opacity-90" fill="currentColor" d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z" />
|
|
120
|
+
</svg>
|
|
121
|
+
正在查询可用的 host_supervisor 节点…
|
|
122
|
+
</div>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (state === 'unconfirmed') {
|
|
127
|
+
return (
|
|
128
|
+
<div className="rounded-md border border-amber-700/40 bg-amber-900/10 px-3 py-3 text-xs text-amber-200">
|
|
129
|
+
<div className="font-semibold mb-1">hub 暂未升级</div>
|
|
130
|
+
<div className="text-amber-200/80">{errMsg}</div>
|
|
131
|
+
<div className="mt-1 text-[11px] text-amber-200/60">
|
|
132
|
+
升级到 <code className="rounded bg-black/40 px-1 py-0.5">@sleep2agi/commhub-server@0.9.0-preview.8</code> 后选服务器功能才会出现。
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (state === 'error') {
|
|
139
|
+
return (
|
|
140
|
+
<div className="rounded-md border border-red-700/40 bg-red-900/10 px-3 py-3 text-xs text-red-200">
|
|
141
|
+
查询 host_supervisor 节点失败:{errMsg}
|
|
142
|
+
</div>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// count=0 — onboarding
|
|
147
|
+
if (daemons.length === 0) {
|
|
148
|
+
return (
|
|
149
|
+
<div className="rounded-md border border-[#26262b] bg-[#0e0e10] px-3 py-4 text-xs text-gray-300">
|
|
150
|
+
<div className="text-sm font-semibold text-gray-200">还没有可用的 host_supervisor 节点</div>
|
|
151
|
+
<p className="mt-1 text-gray-500">
|
|
152
|
+
要在某台机器上创建节点,先在那台机器上跑一次 daemon 初始化命令:
|
|
153
|
+
</p>
|
|
154
|
+
<pre className="mt-2 overflow-x-auto rounded bg-black/40 p-2 text-[11px] text-cyan-300">{`# 任选一台目标机器(你的笔记本 / 一台服务器都行)
|
|
155
|
+
anet daemon up my-daemon`}</pre>
|
|
156
|
+
<p className="mt-2 text-gray-500">
|
|
157
|
+
注册成功后这里会自动出现,无需刷新。
|
|
158
|
+
</p>
|
|
159
|
+
</div>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// count=1 — auto-pick (collapsed). User can opt into picker via "换一个 →".
|
|
164
|
+
if (daemons.length === 1 && !forcePicker) {
|
|
165
|
+
const d = daemons[0];
|
|
166
|
+
return (
|
|
167
|
+
<div className="rounded-md border border-cyan-700/40 bg-cyan-900/10 px-3 py-3 text-xs text-cyan-100">
|
|
168
|
+
<div className="flex items-center justify-between gap-2">
|
|
169
|
+
<div>
|
|
170
|
+
<span className="text-cyan-400/80">将在</span>{' '}
|
|
171
|
+
<span className="font-semibold">{d.alias}</span>
|
|
172
|
+
<span className="text-cyan-300/60"> ({d.hostname || '—'}) </span>
|
|
173
|
+
<span className="text-cyan-400/80">上创建</span>
|
|
174
|
+
</div>
|
|
175
|
+
{/* Single-daemon networks can still let the user enter picker view; */}
|
|
176
|
+
{/* useful if they want to see telemetry before committing. */}
|
|
177
|
+
<button
|
|
178
|
+
type="button"
|
|
179
|
+
onClick={() => setForcePicker(true)}
|
|
180
|
+
className="text-[11px] text-cyan-400 hover:text-cyan-200 underline-offset-2 hover:underline"
|
|
181
|
+
>
|
|
182
|
+
详情 →
|
|
183
|
+
</button>
|
|
184
|
+
</div>
|
|
185
|
+
<RuntimeList runtimes={d.runtimes_supported} className="mt-1" />
|
|
186
|
+
</div>
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// count≥2 (or forcePicker=true) — grid picker. Desktop up to 3 columns,
|
|
191
|
+
// mobile = single column. Locked per RFC-026 §9.4 mockup.
|
|
192
|
+
return (
|
|
193
|
+
<div className="space-y-2">
|
|
194
|
+
<div className="flex items-center justify-between text-xs text-gray-400">
|
|
195
|
+
<span>选择一台 host_supervisor 节点({daemons.length} 台在线)</span>
|
|
196
|
+
{forcePicker && daemons.length === 1 && (
|
|
197
|
+
<button
|
|
198
|
+
type="button"
|
|
199
|
+
onClick={() => setForcePicker(false)}
|
|
200
|
+
className="text-[11px] text-gray-500 hover:text-gray-300"
|
|
201
|
+
>
|
|
202
|
+
← 折叠
|
|
203
|
+
</button>
|
|
204
|
+
)}
|
|
205
|
+
</div>
|
|
206
|
+
<div className="grid grid-cols-1 gap-2 md:grid-cols-2 lg:grid-cols-3">
|
|
207
|
+
{daemons.map(d => (
|
|
208
|
+
<DaemonCard
|
|
209
|
+
key={d.daemon_node_id}
|
|
210
|
+
daemon={d}
|
|
211
|
+
selected={d.daemon_node_id === value}
|
|
212
|
+
onClick={() => onChange(d.daemon_node_id, d)}
|
|
213
|
+
/>
|
|
214
|
+
))}
|
|
215
|
+
</div>
|
|
216
|
+
</div>
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// ───── subcomponents ──────────────────────────────────────────────────
|
|
221
|
+
|
|
222
|
+
function DaemonCard({
|
|
223
|
+
daemon,
|
|
224
|
+
selected,
|
|
225
|
+
onClick,
|
|
226
|
+
}: {
|
|
227
|
+
daemon: DaemonOption;
|
|
228
|
+
selected: boolean;
|
|
229
|
+
onClick: () => void;
|
|
230
|
+
}) {
|
|
231
|
+
const alert = daemon.host_telemetry?.alert_level || 'gray';
|
|
232
|
+
return (
|
|
233
|
+
<button
|
|
234
|
+
type="button"
|
|
235
|
+
onClick={onClick}
|
|
236
|
+
aria-pressed={selected}
|
|
237
|
+
className={`flex w-full flex-col gap-1.5 rounded-md border px-3 py-2.5 text-left text-xs transition-colors ${
|
|
238
|
+
selected
|
|
239
|
+
? 'border-cyan-600 bg-cyan-900/15 text-cyan-100'
|
|
240
|
+
: 'border-[#26262b] bg-[#0e0e10] text-gray-300 hover:border-[#3a3a41]'
|
|
241
|
+
}`}
|
|
242
|
+
>
|
|
243
|
+
<div className="flex items-center justify-between gap-2">
|
|
244
|
+
<span className="truncate font-semibold">{daemon.alias}</span>
|
|
245
|
+
<AlertChip level={alert} />
|
|
246
|
+
</div>
|
|
247
|
+
<div className="truncate text-[11px] text-gray-500">{daemon.hostname || '—'}</div>
|
|
248
|
+
<RuntimeList runtimes={daemon.runtimes_supported} />
|
|
249
|
+
{(daemon.host_telemetry?.cpu_cores != null || daemon.host_telemetry?.mem_gb != null) && (
|
|
250
|
+
<div className="flex gap-3 text-[10px] text-gray-500">
|
|
251
|
+
{daemon.host_telemetry?.cpu_cores != null && <span>{daemon.host_telemetry.cpu_cores} 核</span>}
|
|
252
|
+
{daemon.host_telemetry?.mem_gb != null && <span>{daemon.host_telemetry.mem_gb} GB</span>}
|
|
253
|
+
</div>
|
|
254
|
+
)}
|
|
255
|
+
</button>
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function RuntimeList({ runtimes, className = '' }: { runtimes?: string[]; className?: string }) {
|
|
260
|
+
if (!runtimes || runtimes.length === 0) {
|
|
261
|
+
return <div className={`text-[10px] text-gray-600 ${className}`}>runtimes_supported: —</div>;
|
|
262
|
+
}
|
|
263
|
+
return (
|
|
264
|
+
<div className={`flex flex-wrap gap-1 ${className}`}>
|
|
265
|
+
{runtimes.map(r => (
|
|
266
|
+
<span key={r} className="rounded bg-[#1c1c1f] px-1.5 py-0.5 text-[10px] text-gray-400">{r}</span>
|
|
267
|
+
))}
|
|
268
|
+
</div>
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function AlertChip({ level }: { level: 'green' | 'yellow' | 'red' | 'gray' }) {
|
|
273
|
+
const cls = {
|
|
274
|
+
green: 'bg-green-600/20 text-green-300 border-green-700/40',
|
|
275
|
+
yellow: 'bg-amber-600/20 text-amber-300 border-amber-700/40',
|
|
276
|
+
red: 'bg-red-600/20 text-red-300 border-red-700/40',
|
|
277
|
+
gray: 'bg-gray-600/20 text-gray-400 border-gray-700/40',
|
|
278
|
+
}[level];
|
|
279
|
+
const label = { green: '正常', yellow: '注意', red: '警报', gray: '离线' }[level];
|
|
280
|
+
return (
|
|
281
|
+
<span className={`rounded border px-1.5 py-0.5 text-[10px] ${cls}`}>{label}</span>
|
|
282
|
+
);
|
|
283
|
+
}
|