@sleep2agi/agent-network-dashboard 0.6.3-preview.3 → 0.6.3-preview.4

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 (187) hide show
  1. package/.next/BUILD_COMMIT +1 -1
  2. package/.next/BUILD_ID +1 -1
  3. package/.next/build-manifest.json +3 -3
  4. package/.next/diagnostics/route-bundle-stats.json +12 -11
  5. package/.next/fallback-build-manifest.json +3 -3
  6. package/.next/server/app/_global-error.html +1 -1
  7. package/.next/server/app/_global-error.rsc +1 -1
  8. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  14. package/.next/server/app/_not-found.html +2 -2
  15. package/.next/server/app/_not-found.rsc +2 -2
  16. package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  17. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  18. package/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  19. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  20. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  21. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  22. package/.next/server/app/admin/page.js.nft.json +1 -1
  23. package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
  24. package/.next/server/app/admin.html +2 -2
  25. package/.next/server/app/admin.rsc +3 -3
  26. package/.next/server/app/admin.segments/_full.segment.rsc +3 -3
  27. package/.next/server/app/admin.segments/_head.segment.rsc +1 -1
  28. package/.next/server/app/admin.segments/_index.segment.rsc +2 -2
  29. package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
  30. package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +2 -2
  31. package/.next/server/app/admin.segments/admin.segment.rsc +1 -1
  32. package/.next/server/app/index.html +2 -2
  33. package/.next/server/app/index.rsc +3 -3
  34. package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  35. package/.next/server/app/index.segments/_full.segment.rsc +3 -3
  36. package/.next/server/app/index.segments/_head.segment.rsc +1 -1
  37. package/.next/server/app/index.segments/_index.segment.rsc +2 -2
  38. package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  39. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  40. package/.next/server/app/login.html +2 -2
  41. package/.next/server/app/login.rsc +3 -3
  42. package/.next/server/app/login.segments/_full.segment.rsc +3 -3
  43. package/.next/server/app/login.segments/_head.segment.rsc +1 -1
  44. package/.next/server/app/login.segments/_index.segment.rsc +2 -2
  45. package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  46. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
  47. package/.next/server/app/login.segments/login.segment.rsc +1 -1
  48. package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
  49. package/.next/server/app/logs.html +2 -2
  50. package/.next/server/app/logs.rsc +2 -2
  51. package/.next/server/app/logs.segments/_full.segment.rsc +2 -2
  52. package/.next/server/app/logs.segments/_head.segment.rsc +1 -1
  53. package/.next/server/app/logs.segments/_index.segment.rsc +2 -2
  54. package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
  55. package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +1 -1
  56. package/.next/server/app/logs.segments/logs.segment.rsc +1 -1
  57. package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
  58. package/.next/server/app/messages.html +2 -2
  59. package/.next/server/app/messages.rsc +3 -3
  60. package/.next/server/app/messages.segments/_full.segment.rsc +3 -3
  61. package/.next/server/app/messages.segments/_head.segment.rsc +1 -1
  62. package/.next/server/app/messages.segments/_index.segment.rsc +2 -2
  63. package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
  64. package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +2 -2
  65. package/.next/server/app/messages.segments/messages.segment.rsc +1 -1
  66. package/.next/server/app/node/page_client-reference-manifest.js +1 -1
  67. package/.next/server/app/node.html +2 -2
  68. package/.next/server/app/node.rsc +2 -2
  69. package/.next/server/app/node.segments/_full.segment.rsc +2 -2
  70. package/.next/server/app/node.segments/_head.segment.rsc +1 -1
  71. package/.next/server/app/node.segments/_index.segment.rsc +2 -2
  72. package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
  73. package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +1 -1
  74. package/.next/server/app/node.segments/node.segment.rsc +1 -1
  75. package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
  76. package/.next/server/app/nodes.html +2 -2
  77. package/.next/server/app/nodes.rsc +3 -3
  78. package/.next/server/app/nodes.segments/_full.segment.rsc +3 -3
  79. package/.next/server/app/nodes.segments/_head.segment.rsc +1 -1
  80. package/.next/server/app/nodes.segments/_index.segment.rsc +2 -2
  81. package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
  82. package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +2 -2
  83. package/.next/server/app/nodes.segments/nodes.segment.rsc +1 -1
  84. package/.next/server/app/page_client-reference-manifest.js +1 -1
  85. package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
  86. package/.next/server/app/server-logs.html +2 -2
  87. package/.next/server/app/server-logs.rsc +2 -2
  88. package/.next/server/app/server-logs.segments/_full.segment.rsc +2 -2
  89. package/.next/server/app/server-logs.segments/_head.segment.rsc +1 -1
  90. package/.next/server/app/server-logs.segments/_index.segment.rsc +2 -2
  91. package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
  92. package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +1 -1
  93. package/.next/server/app/server-logs.segments/server-logs.segment.rsc +1 -1
  94. package/.next/server/app/servers/page_client-reference-manifest.js +1 -1
  95. package/.next/server/app/servers.html +2 -2
  96. package/.next/server/app/servers.rsc +2 -2
  97. package/.next/server/app/servers.segments/_full.segment.rsc +2 -2
  98. package/.next/server/app/servers.segments/_head.segment.rsc +1 -1
  99. package/.next/server/app/servers.segments/_index.segment.rsc +2 -2
  100. package/.next/server/app/servers.segments/_tree.segment.rsc +2 -2
  101. package/.next/server/app/servers.segments/servers/__PAGE__.segment.rsc +1 -1
  102. package/.next/server/app/servers.segments/servers.segment.rsc +1 -1
  103. package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
  104. package/.next/server/app/settings/networks.html +2 -2
  105. package/.next/server/app/settings/networks.rsc +2 -2
  106. package/.next/server/app/settings/networks.segments/_full.segment.rsc +2 -2
  107. package/.next/server/app/settings/networks.segments/_head.segment.rsc +1 -1
  108. package/.next/server/app/settings/networks.segments/_index.segment.rsc +2 -2
  109. package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
  110. package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +1 -1
  111. package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +1 -1
  112. package/.next/server/app/settings/networks.segments/settings.segment.rsc +1 -1
  113. package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  114. package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
  115. package/.next/server/app/settings/tokens.html +2 -2
  116. package/.next/server/app/settings/tokens.rsc +2 -2
  117. package/.next/server/app/settings/tokens.segments/_full.segment.rsc +2 -2
  118. package/.next/server/app/settings/tokens.segments/_head.segment.rsc +1 -1
  119. package/.next/server/app/settings/tokens.segments/_index.segment.rsc +2 -2
  120. package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
  121. package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +1 -1
  122. package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +1 -1
  123. package/.next/server/app/settings/tokens.segments/settings.segment.rsc +1 -1
  124. package/.next/server/app/settings.html +2 -2
  125. package/.next/server/app/settings.rsc +3 -3
  126. package/.next/server/app/settings.segments/_full.segment.rsc +3 -3
  127. package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  128. package/.next/server/app/settings.segments/_index.segment.rsc +2 -2
  129. package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  130. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +2 -2
  131. package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
  132. package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
  133. package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
  134. package/.next/server/app/tasks.html +2 -2
  135. package/.next/server/app/tasks.rsc +2 -2
  136. package/.next/server/app/tasks.segments/_full.segment.rsc +2 -2
  137. package/.next/server/app/tasks.segments/_head.segment.rsc +1 -1
  138. package/.next/server/app/tasks.segments/_index.segment.rsc +2 -2
  139. package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
  140. package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +1 -1
  141. package/.next/server/app/tasks.segments/tasks.segment.rsc +1 -1
  142. package/.next/server/chunks/[root-of-the-server]__0jg663w._.js +1 -1
  143. package/.next/server/chunks/[root-of-the-server]__0jg663w._.js.map +1 -1
  144. package/.next/server/chunks/ssr/[root-of-the-server]__0-n_oet._.js +1 -1
  145. package/.next/server/chunks/ssr/[root-of-the-server]__0-n_oet._.js.map +1 -1
  146. package/.next/server/chunks/ssr/[root-of-the-server]__0jgx8j4._.js +1 -1
  147. package/.next/server/chunks/ssr/[root-of-the-server]__0jgx8j4._.js.map +1 -1
  148. package/.next/server/chunks/ssr/dashboard-pr4-338_app_0_vh2hn._.js +1 -1
  149. package/.next/server/chunks/ssr/dashboard-pr4-338_app_0_vh2hn._.js.map +1 -1
  150. package/.next/server/chunks/ssr/dashboard-pr4-338_app_0a352ge._.js +1 -1
  151. package/.next/server/chunks/ssr/dashboard-pr4-338_app_0a352ge._.js.map +1 -1
  152. package/.next/server/chunks/ssr/dashboard-pr4-338_app_0k0.-6z._.js +1 -1
  153. package/.next/server/chunks/ssr/dashboard-pr4-338_app_0k0.-6z._.js.map +1 -1
  154. package/.next/server/chunks/ssr/dashboard-pr4-338_app_12jui6l._.js +3 -0
  155. package/.next/server/chunks/ssr/dashboard-pr4-338_app_12jui6l._.js.map +1 -0
  156. package/.next/server/chunks/ssr/dashboard-pr4-338_app_nodes_page_tsx_0.1qp86._.js +2 -2
  157. package/.next/server/chunks/ssr/dashboard-pr4-338_app_nodes_page_tsx_0.1qp86._.js.map +1 -1
  158. package/.next/server/middleware-build-manifest.js +3 -3
  159. package/.next/server/pages/404.html +2 -2
  160. package/.next/server/pages/500.html +1 -1
  161. package/.next/static/chunks/01.7wksc03ge7.js +1 -0
  162. package/.next/static/chunks/{1238uy.r8ebu0.js → 05ludq~vmjrpi.js} +1 -1
  163. package/.next/static/chunks/0nt58h_jnn298.js +2 -0
  164. package/.next/static/chunks/0~qpo2.zfv914.css +1 -0
  165. package/.next/static/chunks/10-herg8p2_u0.js +1 -0
  166. package/.next/static/chunks/{0r4f9a-1h0l8n.js → 1162nvfdeg.tg.js} +2 -2
  167. package/.next/static/chunks/11as~l5x7cdjy.js +1 -0
  168. package/.next/static/chunks/{0dzyz0tl5mmyh.js → 14eb0vbqm-0fq.js} +1 -1
  169. package/.next/trace +2 -2
  170. package/.next/trace-build +1 -1
  171. package/app/api/anet/node-lifecycle/route.ts +54 -5
  172. package/app/components/CreateNodeWizard.tsx +70 -24
  173. package/app/components/HostSupervisorPicker.tsx +6 -3
  174. package/app/components/NodeLifecycleMenu.tsx +436 -0
  175. package/app/components/types.ts +4 -0
  176. package/app/lib/hooks.ts +22 -0
  177. package/app/nodes/page.tsx +42 -2
  178. package/package.json +1 -1
  179. package/.next/server/chunks/ssr/dashboard-pr4-338_app_0l07md.._.js +0 -3
  180. package/.next/server/chunks/ssr/dashboard-pr4-338_app_0l07md.._.js.map +0 -1
  181. package/.next/static/chunks/0okyajjiuijbh.css +0 -1
  182. package/.next/static/chunks/0zezb.fc41oyb.js +0 -1
  183. package/.next/static/chunks/0zta~z4xpak8b.js +0 -2
  184. package/.next/static/chunks/10rif2p3a6hdl.js +0 -1
  185. /package/.next/static/{S9Q_U9UD2ZJQPBZjZgrZy → 3WnbjoWrJbRnQkx4ilgVm}/_buildManifest.js +0 -0
  186. /package/.next/static/{S9Q_U9UD2ZJQPBZjZgrZy → 3WnbjoWrJbRnQkx4ilgVm}/_clientMiddlewareManifest.js +0 -0
  187. /package/.next/static/{S9Q_U9UD2ZJQPBZjZgrZy → 3WnbjoWrJbRnQkx4ilgVm}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../dashboard-pr4-338/app/nodes/page.tsx","../../../../../dashboard-pr4-338/app/components/CreateNodeWizard.tsx","../../../../../dashboard-pr4-338/app/components/HostSupervisorPicker.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport { timeAgo } from '../components/utils';\nimport { useSessions, useHealth } from '../lib/hooks';\nimport { TaskChatPanel } from '../components/TaskChatPanel';\nimport { CreateNodeWizard } from '../components/CreateNodeWizard';\nimport { EmptyState, NodesEmptyState } from '../components/EmptyState';\nimport { AliasAvatar } from '../components/AliasAvatar';\nimport { useCollapsibleSearch } from '../components/CollapsibleSearch';\nimport type { Session } from '../components/types';\nimport { SESSION_STATUS_CHIP_CLASS as STATUS_COLORS } from '../lib/status';\nimport { useChatUnread } from '../lib/chat-unread';\n\n/** Round 81: shorten long server hostnames (Alibaba `iZ…oyZ` style)\n * for table display. Returns the original string unchanged when ≤12\n * chars. Full value should stay in `title=` for hover + screen-readers. */\nfunction shortServer(server: string | null | undefined): string {\n if (!server) return '—';\n return server.length > 12 ? `${server.slice(0, 8)}…` : server;\n}\n\ntype ViewMode = 'list' | 'grid';\ntype SessionRow = Session & { online: boolean };\n\nexport default function NodesPage() {\n const { sessions, isLoading: loading } = useSessions();\n const { health } = useHealth();\n const { hasUnread } = useChatUnread();\n const sseMap = health?.sse_sessions || {};\n // SSE keys are `network_id:alias` since server v0.7+. Look up with the\n // composite key first, fall back to alias-only for legacy hubs.\n const sseFor = (s: { alias: string; network_id?: string }) =>\n (s.network_id ? sseMap[`${s.network_id}:${s.alias}`] : undefined) ?? sseMap[s.alias];\n const [filterStatus, setFilterStatus] = useState('');\n const [search, setSearch] = useState('');\n const [viewMode, setViewMode] = useState<ViewMode>('list');\n const [chatAlias, setChatAlias] = useState<string | null>(null);\n const [showCreate, setShowCreate] = useState(false);\n // #209 R32→R34: the WeChat-style magnifier-toggle search was hand-rolled\n // inline in R32. R34 extracted it to a shared hook so /nodes, /messages,\n // and any future search surface stay visually + behaviourally identical.\n // The hook returns a Button (place in header) + Row (place after header).\n const searchCtl = useCollapsibleSearch({\n value: search,\n onChange: setSearch,\n placeholder: 'Search nodes…',\n label: 'Search nodes',\n enabled: sessions.length > 0,\n });\n\n const filtered: SessionRow[] = sessions\n .map(s => ({ ...s, online: !!sseFor(s) }))\n .filter(s => {\n if (filterStatus === 'online') return s.online;\n if (filterStatus === 'offline') return !s.online;\n if (filterStatus && filterStatus !== s.status) return false;\n return true;\n })\n .filter(s => !search || s.alias.toLowerCase().includes(search.toLowerCase()) || (s.agent || '').toLowerCase().includes(search.toLowerCase()))\n .sort((a, b) => (b.online ? 1 : 0) - (a.online ? 1 : 0) || (b.status === 'working' ? 1 : 0) - (a.status === 'working' ? 1 : 0));\n\n const onlineCount = sessions.filter(s => sseFor(s)).length;\n\n return (\n <div className=\"min-h-screen max-w-full overflow-x-hidden bg-[#0b0b0d] text-gray-100 p-4 sm:p-6\">\n {/* #209 R31 (mobile vertical rhythm — goal \"大幅提升移动端体验\",\n extending R28's Overview pattern + R30's /tasks pattern):\n this header row + the status-bar wrapper + the filter row\n below all drop mb-6 → mb-4 sm:mb-6. Three spots × 8 px =\n ~24 px scroll reclaim on /nodes before the first card.\n #209 R32: search affordance moved to top-right magnifier\n button (Vincent WeChat ref msg 563). justify-between makes\n the title cluster hug left, button hugs right. */}\n <div className=\"flex items-center gap-4 mb-4 sm:mb-6\">\n <div className=\"flex items-center gap-3 min-w-0 flex-1\">\n <h1 className=\"text-2xl font-bold text-white lg:ml-0 ml-10\">Nodes</h1>\n <span className=\"text-xs bg-green-900/30 text-green-400 px-2 py-0.5 rounded-full border border-green-800/30 shrink-0\">\n {onlineCount} online\n </span>\n <span className=\"text-xs bg-gray-900/30 text-gray-400 px-2 py-0.5 rounded-full border border-gray-800/30 shrink-0\">\n {sessions.length} total\n </span>\n </div>\n <div className=\"flex items-center gap-2 shrink-0\">\n {/* node-lifecycle M2: open the create-node wizard (RFC-026 §3.1 P1). */}\n <button\n type=\"button\"\n onClick={() => setShowCreate(true)}\n aria-label=\"新建节点\"\n className=\"inline-flex items-center gap-1 rounded-lg border border-cyan-700/50 bg-cyan-900/15 px-3 py-1.5 text-sm font-medium text-cyan-300 hover:bg-cyan-900/25 transition-colors\"\n >\n <span aria-hidden className=\"text-base leading-none\">+</span>\n <span className=\"hidden sm:inline\">新建节点</span>\n </button>\n <searchCtl.Button />\n </div>\n </div>\n\n {showCreate && <CreateNodeWizard onClose={() => setShowCreate(false)} />}\n\n {/* #209 R34: shared <CollapsibleSearch> component handles row reveal,\n autofocus, Escape, and Cancel. enabled=sessions.length>0 hides\n everything until there's content to search. */}\n <searchCtl.Row />\n\n {/* #217 D6 (less is more): the status distribution bar + its\n working/idle/offline legend duplicated the header chips\n (N online / N total) and the per-card status pills right\n below. One count display per screen — the bar is gone. */}\n\n {/* Round 74: hide the filter+view chrome when there are no nodes\n anywhere — these controls have nothing to act on, and they only\n push the onboarding CTA further down. When at least one session\n exists, the chrome is back even if the current filter happens\n to hide everything (so users can clear filters). */}\n {sessions.length > 0 && (\n <div className=\"flex flex-wrap gap-3 mb-4 sm:mb-6\">\n {/* R32: the inline search input was moved to the top-right\n magnifier toggle above. The status select + List/Grid\n toggle stay here. */}\n <select\n value={filterStatus}\n onChange={e => setFilterStatus(e.target.value)}\n className=\"bg-[#161618] border border-[#26262b] rounded-lg px-3 py-2 text-base sm:text-sm text-white focus:border-blue-500/50 focus:outline-none\"\n >\n <option value=\"\">All</option>\n <option value=\"online\">Online</option>\n <option value=\"offline\">Offline</option>\n <option value=\"working\">Working</option>\n <option value=\"idle\">Idle</option>\n <option value=\"blocked\">Blocked</option>\n <option value=\"error\">Error</option>\n </select>\n {/* Round 80: List/Grid toggle hidden on mobile — Grid uses\n grid-cols-1 below `md` and List degrades to the same single\n column, so the toggle has no visual effect under sm and only\n steals a row of vertical space. */}\n <div className=\"hidden sm:flex ml-auto rounded-lg border border-[#26262b] bg-[#161618] p-1 text-sm\">\n {(['list', 'grid'] as const).map(mode => (\n <button\n key={mode}\n type=\"button\"\n onClick={() => setViewMode(mode)}\n className={`rounded-md px-3 py-1.5 transition-colors ${\n viewMode === mode\n ? 'bg-cyan-500/10 text-cyan-300'\n : 'text-gray-500 hover:text-gray-200'\n }`}\n >\n {mode === 'list' ? 'List' : 'Grid'}\n </button>\n ))}\n </div>\n </div>\n )}\n\n {loading ? (\n <div className=\"animate-pulse space-y-2\">\n {[1,2,3,4].map(i => <div key={i} className=\"h-16 bg-gray-800/20 rounded-lg\" />)}\n </div>\n ) : filtered.length === 0 ? (\n sessions.length === 0 ? (\n /* Round 73: first-run case — no agents anywhere. Use the same\n onboarding empty state as the Overview (NodesEmptyState\n includes the `npx … init` quickstart command). Previously this\n was the \"No nodes match your filters\" copy, which was wrong\n for new users who have no filters applied. */\n <NodesEmptyState />\n ) : (\n <EmptyState\n variant=\"nodes\"\n title=\"No nodes match your filters\"\n sub=\"Try clearing search or status filters, or wait for an agent to register.\"\n />\n )\n ) : viewMode === 'grid' ? (\n <div className=\"grid min-w-0 grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4\">\n {filtered.map(s => {\n const statusKey = s.online ? s.status : 'offline';\n const progress = typeof s.progress === 'number' ? s.progress : 0;\n const unread = hasUnread(s.alias);\n\n return (\n <div\n key={s.alias}\n role=\"button\"\n tabIndex={0}\n onClick={() => setChatAlias(s.alias)}\n onKeyDown={e => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setChatAlias(s.alias); } }}\n className={`relative min-w-0 max-w-full overflow-hidden rounded-xl border border-[#26262b] bg-[#161618] p-4 transition-colors hover:border-cyan-500/40 cursor-pointer ${!s.online ? 'opacity-60' : ''}`}\n >\n {!s.online && (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <span className=\"rotate-[-20deg] rounded-xl border border-white/10 bg-black/20 px-5 py-2 text-xl font-bold uppercase tracking-[0.35em] text-white/10\">\n Offline\n </span>\n </div>\n )}\n <div className=\"flex items-start gap-3\">\n <div className=\"relative shrink-0\">\n <AliasAvatar alias={s.alias} size={36} />\n {unread && <span className=\"absolute -right-1 -top-1 h-3 w-3 rounded-full border-2 border-[#161618] bg-red-500\" />}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"truncate text-base font-semibold text-white\">{s.alias}</span>\n {unread && <span className=\"shrink-0 rounded-full bg-red-500/15 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-red-300\">New</span>}\n <span className={`shrink-0 rounded-md border px-2 py-0.5 text-[10px] uppercase tracking-wide ${STATUS_COLORS[statusKey] || STATUS_COLORS.offline}`}>\n {statusKey}\n </span>\n </div>\n <div className=\"mt-0.5 truncate text-xs text-gray-500\">\n {(s.agent || '—')}<span className=\"text-gray-700 mx-1.5\">·</span><span title={s.server || ''}>{shortServer(s.server)}</span>\n </div>\n </div>\n <span className=\"hidden shrink-0 rounded-lg border border-cyan-500/15 bg-cyan-500/5 px-2 py-1 text-[10px] text-cyan-300/70 sm:inline\">Tap to chat</span>\n </div>\n\n <div className=\"mt-3 rounded-lg border border-[#1c1c1f] bg-[#0e0e10] px-3 py-2 text-xs\">\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-[10px] uppercase tracking-wide text-gray-600\">Current task</span>\n <span className=\"text-[10px] text-gray-600\">{timeAgo(s.last_seen_at || s.updated_at)}</span>\n </div>\n <div className={`mt-1 line-clamp-2 ${s.task ? 'text-gray-300' : 'text-gray-600 italic'}`}>\n {s.task || 'No current task'}\n </div>\n </div>\n\n {progress > 0 && progress < 100 && (\n <div className=\"mt-3 h-1.5 overflow-hidden rounded-full bg-gray-800\">\n <div className=\"h-1.5 rounded-full bg-cyan-400 transition-all\" style={{ width: `${progress}%` }} />\n </div>\n )}\n\n </div>\n );\n })}\n </div>\n ) : (\n <div className=\"space-y-1 sm:space-y-2\">\n {/* Round 94: AGENT + SERVER merged into one `agent · server`\n cell. Round mobile-command: node row itself opens chat, so\n the old Chat / Send Task action column is gone. */}\n <div className=\"hidden sm:grid sm:grid-cols-10 gap-2 px-4 py-2 text-xs text-gray-600 uppercase\">\n <div className=\"col-span-1\">Status</div>\n <div className=\"col-span-2\">Alias</div>\n <div className=\"col-span-2\">Agent · Server</div>\n <div className=\"col-span-4\">Current Task</div>\n <div className=\"col-span-1\">Updated</div>\n </div>\n {filtered.map(s => {\n const statusKey = s.online ? s.status : 'offline';\n const unread = hasUnread(s.alias);\n\n return (\n <div\n key={s.alias}\n role=\"button\"\n tabIndex={0}\n onClick={() => setChatAlias(s.alias)}\n onKeyDown={e => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setChatAlias(s.alias); } }}\n className={`rounded-lg border border-[#26262b] bg-[#161618] px-3 py-2 sm:px-4 sm:py-3 transition-colors hover:border-cyan-500/40 cursor-pointer ${!s.online ? 'opacity-50' : ''}`}\n >\n <div className=\"hidden sm:grid sm:grid-cols-10 gap-2 items-center\">\n <div className=\"col-span-1\">\n <span className={`text-xs px-2 py-0.5 rounded-md border ${STATUS_COLORS[statusKey] || STATUS_COLORS.offline}`}>\n {statusKey}\n </span>\n </div>\n <div className=\"col-span-2 min-w-0\">\n <div className=\"flex items-center gap-2 min-w-0\">\n <div className=\"relative shrink-0\">\n <AliasAvatar alias={s.alias} size={20} />\n {unread && <span className=\"absolute -right-1 -top-1 h-2.5 w-2.5 rounded-full border border-[#161618] bg-red-500\" />}\n </div>\n <span className=\"truncate text-sm font-medium text-white\">{s.alias}</span>\n {unread && <span className=\"shrink-0 rounded-full bg-red-500/15 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-red-300\">New</span>}\n </div>\n </div>\n <div className=\"col-span-2 truncate text-xs text-gray-400\" title={s.server || ''}>\n <span className=\"truncate\">{s.agent || '--'}<span className=\"text-gray-700 mx-1.5\">·</span>{shortServer(s.server)}</span>\n </div>\n <div className=\"col-span-4 truncate text-xs text-gray-500\" title={s.task || ''}>{s.task || '--'}</div>\n <div className=\"col-span-1 text-xs text-gray-500\">{timeAgo(s.last_seen_at || s.updated_at)}</div>\n </div>\n {/* R7 of #190: mobile node row was ~340px tall × ~150\n rows = the 51k page. Wins this round, in priority\n order: (1) drop the per-row \"Tap anywhere to chat\"\n hint — useful once, redundant 149 times; the cyan\n border on hover/focus still teaches it. (2) tighten\n space-y-2 → space-y-1 so the avatar/task gap is\n 4px tighter on every row. */}\n <div className=\"sm:hidden space-y-1\">\n <div className=\"flex items-center gap-2.5\">\n <div className=\"relative shrink-0\">\n <AliasAvatar alias={s.alias} size={28} />\n {unread && <span className=\"absolute -right-1 -top-1 h-3 w-3 rounded-full border-2 border-[#161618] bg-red-500\" />}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2 min-w-0\">\n <div className=\"truncate text-sm font-medium text-white\">{s.alias}</div>\n {unread && <span className=\"shrink-0 rounded-full bg-red-500/15 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-red-300\">New</span>}\n </div>\n <div className=\"truncate text-[10px] text-gray-500\">{s.agent || '—'} · {timeAgo(s.last_seen_at || s.updated_at)}</div>\n </div>\n <span className={`shrink-0 text-xs px-2 py-0.5 rounded-md border ${STATUS_COLORS[statusKey] || STATUS_COLORS.offline}`}>\n {statusKey}\n </span>\n </div>\n {s.task && <div className=\"truncate text-xs text-gray-500\">{s.task}</div>}\n </div>\n </div>\n );\n })}\n </div>\n )}\n\n {chatAlias && <TaskChatPanel alias={chatAlias} onClose={() => setChatAlias(null)} />}\n </div>\n );\n}\n","'use client';\n\nimport { useEffect, useState } from 'react';\nimport { useNetworkId } from '../lib/network-context';\nimport { HostSupervisorPicker } from './HostSupervisorPicker';\n\n/**\n * Create-node wizard (node-lifecycle UI M2/PR4 — RFC-026 §3.1).\n * 6 steps now: ⓪ host (PR4 #338) ① name ② runtime ③ model ④ flags ⑤ confirm\n * → POST /api/anet/node-create with `daemon_node_id` set to the chosen host.\n *\n * PR4 (#338 main lane PR4) folds RFC-026 §9.4 host_supervisor picker in front\n * of the existing 5 steps. Three states the picker resolves internally:\n * - count=0 → onboarding (no daemon, show install command + block forward)\n * - count=1 → auto-pick + forward immediately\n * - count≥2 → user picks, then forward\n * The wizard now ALWAYS passes daemon_node_id to /api/anet/node-create (the\n * route's `resolveLocalDaemonNodeId` fallback only fires if daemon_node_id is\n * absent — kept for back-compat with non-wizard callers but no longer used\n * from this flow). Per [[feedback_doc_capability_claim_verify_code_path]] —\n * the API contract is exercised locally before any prod hub touches the path.\n */\n\nconst RUNTIMES: { id: string; label: string; models: string[] }[] = [\n { id: 'claude-agent-sdk', label: 'Claude Agent SDK', models: ['deepseek-v4-pro', 'MiniMax-M3', 'claude-sonnet-4-6', 'claude-opus-4-x'] },\n { id: 'codex', label: 'Codex', models: ['gpt-5.5'] },\n { id: 'grok', label: 'Grok', models: ['grok-build'] },\n];\nconst PERMISSION_MODES = ['auto', 'default', 'bypassPermissions'];\nconst STEPS = ['服务器', '名字', 'Runtime', '模型', '参数', '确认'];\n\ntype Phase = 'form' | 'creating' | 'done' | 'unconfirmed' | 'error';\n\nexport function CreateNodeWizard({\n networkId,\n onClose,\n onCreated,\n}: {\n networkId?: string;\n onClose: () => void;\n onCreated?: (result: unknown) => void;\n}) {\n const [step, setStep] = useState(0);\n const [daemonNodeId, setDaemonNodeId] = useState<string | null>(null);\n const [name, setName] = useState('');\n const [runtimeId, setRuntimeId] = useState(RUNTIMES[0].id);\n const [model, setModel] = useState('');\n const [permissionMode, setPermissionMode] = useState('auto');\n const [maxTurns, setMaxTurns] = useState('');\n const [budget, setBudget] = useState('');\n const [timeout, setTimeout] = useState('');\n const [phase, setPhase] = useState<Phase>('form');\n const [msg, setMsg] = useState('');\n const [childUp, setChildUp] = useState(false);\n const { networkId: ctxNetworkId } = useNetworkId();\n const netId = networkId || ctxNetworkId;\n\n // Escape closes the wizard (unless a create is mid-flight, so a stray key\n // can't drop the dialog while the request is settling).\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape' && phase !== 'creating') onClose(); };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [onClose, phase]);\n\n // After dispatch, confirm the child actually came up by watching the node\n // list for it to register (RFC-026 progress signal — get_create_request is\n // daemon-only, so the dashboard confirms via /api/hub/status). Polls ~24s.\n useEffect(() => {\n if (phase !== 'done' || childUp) return;\n let alive = true;\n let tries = 0;\n const want = name.trim();\n const tick = async () => {\n tries += 1;\n try {\n const url = netId ? `/api/hub/status?network_id=${encodeURIComponent(netId)}` : '/api/hub/status';\n const r = await fetch(url, { cache: 'no-store' });\n const d = await r.json().catch(() => ({}));\n const list = Array.isArray(d?.sessions) ? d.sessions : Array.isArray(d) ? d : [];\n if (alive && list.some((s: { alias?: string }) => s?.alias === want)) { setChildUp(true); return; }\n } catch { /* transient — keep polling */ }\n if (alive && tries < 16) window.setTimeout(tick, 1500);\n };\n const t = window.setTimeout(tick, 1200);\n return () => { alive = false; window.clearTimeout(t); };\n }, [phase, childUp, netId, name]);\n\n const runtime = RUNTIMES.find(r => r.id === runtimeId) || RUNTIMES[0];\n const nameValid = name.trim().length > 0;\n const canNext =\n (step === 0 && Boolean(daemonNodeId)) || // step 0: must have chosen a daemon\n (step === 1 && nameValid) || // step 1: name non-empty\n (step >= 2 && step < STEPS.length); // later steps: nothing required to advance\n const busy = phase === 'creating';\n\n async function handleCreate() {\n setPhase('creating');\n setMsg('');\n const numOrUndef = (v: string) => (v.trim() === '' ? undefined : Number(v));\n const node_spec = {\n name: name.trim(),\n runtime: runtimeId,\n ...(model ? { model } : {}),\n flags: {\n permissionMode,\n maxTurns: numOrUndef(maxTurns),\n budget: numOrUndef(budget),\n timeout: numOrUndef(timeout),\n },\n };\n try {\n const r = await fetch('/api/anet/node-create', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n node_spec,\n ...(daemonNodeId ? { daemon_node_id: daemonNodeId } : {}),\n ...(networkId ? { network_id: networkId } : {}),\n }),\n });\n const data = await r.json().catch(() => ({}));\n if (r.ok && data?.ok) {\n setPhase('done');\n setMsg('创建请求已下发,节点正在拉起…');\n onCreated?.(data.result);\n } else if (data?.unconfirmed) {\n setPhase('unconfirmed');\n setMsg(`后端 create_node 未就绪:${data?.error || '不可用'}(测试 hub 可能未含 #299)`);\n } else {\n setPhase('error');\n setMsg(data?.error ? `创建失败:${data.error}` : '创建失败');\n }\n } catch (e) {\n setPhase('error');\n setMsg(`创建失败:${e instanceof Error ? e.message : '网络错误'}`);\n }\n }\n\n const inputCls =\n 'w-full rounded-md border border-[#26262b] bg-[#0e0e10] px-3 py-2 text-sm text-gray-200 focus:border-cyan-600 focus:outline-none';\n\n return (\n <>\n <div className=\"fixed inset-0 bg-black/50 z-40\" onClick={onClose} aria-hidden />\n <div\n role=\"dialog\"\n aria-label=\"新建节点\"\n // RFC-026 §9.4 responsive: mobile single-screen (full width minus\n // gutter, taller); desktop ~3-col-friendly width when picker is shown.\n 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\"\n >\n {/* Header */}\n <div className=\"flex items-center justify-between border-b border-[#26262b] px-4 py-3\">\n <div className=\"text-sm font-semibold text-white\">新建节点</div>\n <button onClick={onClose} aria-label=\"关闭\" className=\"inline-flex h-8 w-8 items-center justify-center rounded-md text-gray-500 hover:bg-white/5 hover:text-white\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden>\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n {/* Step indicator */}\n <div className=\"flex items-center gap-1.5 px-4 pt-3\">\n {STEPS.map((label, i) => (\n <div key={label} className=\"flex flex-1 flex-col items-center gap-1\">\n <div className={`h-1 w-full rounded-full ${i <= step ? 'bg-cyan-500' : 'bg-[#26262b]'}`} />\n <span className={`text-[10px] ${i === step ? 'text-cyan-300' : 'text-gray-600'}`}>{label}</span>\n </div>\n ))}\n </div>\n\n {/* Body */}\n <div className=\"min-h-[180px] px-4 py-4\">\n {phase !== 'form' ? (\n <div className=\"flex h-[180px] flex-col items-center justify-center gap-3 text-center\">\n {busy && (\n <svg className=\"h-7 w-7 animate-spin text-cyan-400\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden>\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-90\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z\" />\n </svg>\n )}\n <div className={`text-sm ${phase === 'done' ? 'text-green-300' : phase === 'error' ? 'text-red-300' : phase === 'unconfirmed' ? 'text-amber-300' : 'text-gray-300'}`}>\n {busy ? '正在创建…' : phase === 'done' && childUp ? `✓ ${name.trim()} 已上线` : msg}\n </div>\n {/* Real progress: poll the node list for the child to register\n (派单→fork→注册→✓). */}\n {phase === 'done' && (childUp ? (\n <p className=\"text-[11px] text-green-500/80\">节点已注册,已出现在节点列表。</p>\n ) : (\n <p className=\"inline-flex items-center gap-1.5 text-[11px] text-gray-500\">\n <svg className=\"h-3 w-3 animate-spin\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden>\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-90\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z\" />\n </svg>\n 正在监测 {name.trim()} 注册…(最长 ~24s)\n </p>\n ))}\n </div>\n ) : (\n <>\n {step === 0 && (\n <div className=\"space-y-2\">\n <span className=\"text-xs text-gray-400\">在哪台机器上创建</span>\n <HostSupervisorPicker\n networkId={netId || undefined}\n value={daemonNodeId}\n onChange={setDaemonNodeId}\n />\n {!daemonNodeId && (\n <p className=\"text-[11px] text-gray-600\">\n 没选服务器之前无法继续;如果列表是空的,按提示在目标机器上跑 <code className=\"rounded bg-black/40 px-1 py-0.5\">anet daemon up &lt;name&gt;</code>。\n </p>\n )}\n </div>\n )}\n {step === 1 && (\n <label className=\"block space-y-1.5\">\n <span className=\"text-xs text-gray-400\">节点名字</span>\n <input autoFocus value={name} onChange={e => setName(e.target.value)} placeholder=\"例如 my-agent-1\" className={inputCls} />\n {!nameValid && <span className=\"text-[11px] text-gray-600\">名字不能为空</span>}\n </label>\n )}\n {step === 2 && (\n <div className=\"space-y-2\">\n <span className=\"text-xs text-gray-400\">Runtime</span>\n {RUNTIMES.map(r => (\n <button\n key={r.id}\n type=\"button\"\n onClick={() => { setRuntimeId(r.id); setModel(''); }}\n className={`flex w-full items-center justify-between rounded-md border px-3 py-2 text-sm transition-colors ${\n runtimeId === r.id ? 'border-cyan-600 bg-cyan-900/15 text-cyan-200' : 'border-[#26262b] bg-[#0e0e10] text-gray-300 hover:border-[#3a3a41]'\n }`}\n >\n {r.label}\n {runtimeId === r.id && (\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n )}\n </button>\n ))}\n </div>\n )}\n {step === 3 && (\n <label className=\"block space-y-1.5\">\n <span className=\"text-xs text-gray-400\">模型({runtime.label})</span>\n <select value={model} onChange={e => setModel(e.target.value)} className={inputCls}>\n <option value=\"\">默认</option>\n {runtime.models.map(m => <option key={m} value={m}>{m}</option>)}\n </select>\n </label>\n )}\n {step === 4 && (\n <div className=\"space-y-3\">\n <label className=\"block space-y-1.5\">\n <span className=\"text-xs text-gray-400\">permissionMode</span>\n <select value={permissionMode} onChange={e => setPermissionMode(e.target.value)} className={inputCls}>\n {PERMISSION_MODES.map(m => <option key={m} value={m}>{m}</option>)}\n </select>\n </label>\n <div className=\"grid grid-cols-3 gap-2\">\n <label className=\"space-y-1\"><span className=\"text-[11px] text-gray-500\">maxTurns</span><input inputMode=\"numeric\" value={maxTurns} onChange={e => setMaxTurns(e.target.value)} className={inputCls} /></label>\n <label className=\"space-y-1\"><span className=\"text-[11px] text-gray-500\">budget</span><input inputMode=\"numeric\" value={budget} onChange={e => setBudget(e.target.value)} className={inputCls} /></label>\n <label className=\"space-y-1\"><span className=\"text-[11px] text-gray-500\">timeout</span><input inputMode=\"numeric\" value={timeout} onChange={e => setTimeout(e.target.value)} className={inputCls} /></label>\n </div>\n </div>\n )}\n {step === 5 && (\n <div className=\"space-y-2 text-sm\">\n <div className=\"rounded-md border border-[#26262b] bg-[#0e0e10] divide-y divide-[#1c1c1f]\">\n {[\n ['服务器', daemonNodeId ? `${daemonNodeId.slice(0, 24)}…` : '—'],\n ['名字', name.trim() || '—'],\n ['Runtime', runtime.label],\n ['模型', model || '默认'],\n ['permissionMode', permissionMode],\n ['maxTurns / budget / timeout', `${maxTurns || '—'} / ${budget || '—'} / ${timeout || '—'}`],\n ].map(([k, v]) => (\n <div key={k} className=\"flex items-start justify-between gap-3 px-3 py-2\">\n <span className=\"shrink-0 text-gray-500 text-xs\">{k}</span>\n <span className=\"text-right text-gray-200 text-xs break-all\">{v}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n </>\n )}\n </div>\n\n {/* Footer nav */}\n {phase === 'form' ? (\n <div className=\"flex items-center justify-between border-t border-[#26262b] px-4 py-3\">\n <button type=\"button\" onClick={() => (step === 0 ? onClose() : setStep(step - 1))} className=\"rounded-md px-3 py-1.5 text-sm text-gray-400 hover:text-gray-200\">\n {step === 0 ? '取消' : '上一步'}\n </button>\n {step < STEPS.length - 1 ? (\n <button type=\"button\" disabled={!canNext} onClick={() => setStep(step + 1)} className={`rounded-md px-4 py-1.5 text-sm font-medium ${canNext ? 'bg-cyan-600 text-white hover:bg-cyan-500' : 'bg-[#1c1c1f] text-gray-600 cursor-not-allowed'}`}>\n 下一步\n </button>\n ) : (\n <button type=\"button\" onClick={handleCreate} className=\"rounded-md bg-green-600 px-4 py-1.5 text-sm font-medium text-white hover:bg-green-500\">\n 创建节点\n </button>\n )}\n </div>\n ) : (\n <div className=\"flex items-center justify-end border-t border-[#26262b] px-4 py-3\">\n <button type=\"button\" onClick={onClose} className=\"rounded-md bg-[#1c1c1f] px-4 py-1.5 text-sm text-gray-200 hover:bg-[#26262b]\">\n {phase === 'done' ? '完成' : '关闭'}\n </button>\n {(phase === 'error' || phase === 'unconfirmed') && (\n <button type=\"button\" onClick={() => setPhase('form')} className=\"ml-2 rounded-md bg-cyan-600 px-4 py-1.5 text-sm text-white hover:bg-cyan-500\">返回修改</button>\n )}\n </div>\n )}\n </div>\n </>\n );\n}\n","'use client';\n\nimport { useEffect, useState } from 'react';\n\n/**\n * PR4 #338 — host_supervisor daemon picker (RFC-026 §9.4 locked mockup).\n *\n * Three states (the only branching the wizard ever sees):\n *\n * count=0 → onboarding: explain what a daemon is + give the install command.\n * No daemon = nothing to dispatch to; create flow is blocked here\n * until the user runs `anet daemon init <name>` somewhere.\n *\n * count=1 → auto-pick: just show \"using <alias>\" + a quiet `换一个 →` link\n * (which switches to the picker view if the user really wants).\n *\n * count≥2 → picker grid: cards for each daemon w/ runtimes + alert chip,\n * click selects. Desktop = up to 3 columns; mobile = single column.\n *\n * Data shape mirrors `/api/anet/host-supervisors`, which in turn mirrors the\n * hub's GET /api/host-supervisors (#338 PR2 — needs commhub-server@0.9.0-preview.8+).\n * On `unconfirmed` (older hub), we degrade honestly to an upgrade hint — never\n * show a fake empty list. Per [[feedback_doc_capability_claim_verify_code_path]].\n */\n\nexport interface DaemonOption {\n // Hub canonical key is `daemon_node_id` (PR2 v2 §9.2 contract). We keep the\n // same name end-to-end so the value the wizard passes back to create_node\n // as `daemon_node_id` doesn't need a rename layer.\n daemon_node_id: string;\n alias: string;\n hostname?: string | null;\n online?: boolean;\n last_seen_at?: string | null;\n runtimes_supported?: string[];\n host_telemetry?: {\n alert_level?: 'green' | 'yellow' | 'red' | 'gray';\n cpu_cores?: number | null;\n mem_gb?: number | null;\n ip_internal?: string | null;\n };\n}\n\ninterface PickResponse {\n ok: boolean;\n unconfirmed?: boolean;\n error?: string;\n count: number;\n daemons: DaemonOption[];\n selected?: string | null;\n}\n\ntype LoadState = 'loading' | 'ready' | 'error' | 'unconfirmed';\n\nexport function HostSupervisorPicker({\n networkId,\n value,\n onChange,\n}: {\n networkId?: string | null;\n value: string | null;\n onChange: (nodeId: string | null) => void;\n}) {\n const [state, setState] = useState<LoadState>('loading');\n const [daemons, setDaemons] = useState<DaemonOption[]>([]);\n const [errMsg, setErrMsg] = useState('');\n const [forcePicker, setForcePicker] = useState(false);\n\n useEffect(() => {\n let alive = true;\n setState('loading');\n setErrMsg('');\n const url = networkId\n ? `/api/anet/host-supervisors?network_id=${encodeURIComponent(networkId)}`\n : '/api/anet/host-supervisors';\n fetch(url, { cache: 'no-store' })\n .then(r => r.json().then(d => ({ status: r.status, body: d as PickResponse })))\n .then(({ status, body }) => {\n if (!alive) return;\n if (status === 501 || body?.unconfirmed) {\n setState('unconfirmed');\n setErrMsg(body?.error || 'hub /api/host-supervisors unavailable — upgrade to >=0.9.0-preview.8');\n setDaemons([]);\n return;\n }\n if (!body?.ok) {\n setState('error');\n setErrMsg(body?.error || `hub ${status}`);\n setDaemons([]);\n return;\n }\n const list = Array.isArray(body.daemons) ? body.daemons : [];\n setDaemons(list);\n setState('ready');\n // count=1 auto-pick: preselect the only daemon. count≥2 leaves the\n // selection to the user (parent value stays null until click).\n if (list.length === 1 && !value) onChange(list[0].daemon_node_id);\n })\n .catch(e => {\n if (!alive) return;\n setState('error');\n setErrMsg(e instanceof Error ? e.message : String(e));\n setDaemons([]);\n });\n return () => { alive = false; };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [networkId]);\n\n // ───── render branches ──────────────────────────────────────────────\n\n if (state === 'loading') {\n return (\n <div className=\"flex items-center gap-2 rounded-md border border-[#26262b] bg-[#0e0e10] px-3 py-3 text-xs text-gray-500\">\n <svg className=\"h-3.5 w-3.5 animate-spin\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden>\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-90\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z\" />\n </svg>\n 正在查询可用的 host_supervisor 节点…\n </div>\n );\n }\n\n if (state === 'unconfirmed') {\n return (\n <div className=\"rounded-md border border-amber-700/40 bg-amber-900/10 px-3 py-3 text-xs text-amber-200\">\n <div className=\"font-semibold mb-1\">hub 暂未升级</div>\n <div className=\"text-amber-200/80\">{errMsg}</div>\n <div className=\"mt-1 text-[11px] text-amber-200/60\">\n 升级到 <code className=\"rounded bg-black/40 px-1 py-0.5\">@sleep2agi/commhub-server@0.9.0-preview.8</code> 后选服务器功能才会出现。\n </div>\n </div>\n );\n }\n\n if (state === 'error') {\n return (\n <div className=\"rounded-md border border-red-700/40 bg-red-900/10 px-3 py-3 text-xs text-red-200\">\n 查询 host_supervisor 节点失败:{errMsg}\n </div>\n );\n }\n\n // count=0 — onboarding\n if (daemons.length === 0) {\n return (\n <div className=\"rounded-md border border-[#26262b] bg-[#0e0e10] px-3 py-4 text-xs text-gray-300\">\n <div className=\"text-sm font-semibold text-gray-200\">还没有可用的 host_supervisor 节点</div>\n <p className=\"mt-1 text-gray-500\">\n 要在某台机器上创建节点,先在那台机器上跑一次 daemon 初始化命令:\n </p>\n <pre className=\"mt-2 overflow-x-auto rounded bg-black/40 p-2 text-[11px] text-cyan-300\">{`# 任选一台目标机器(你的笔记本 / 一台服务器都行)\nanet daemon up my-daemon`}</pre>\n <p className=\"mt-2 text-gray-500\">\n 注册成功后这里会自动出现,无需刷新。\n </p>\n </div>\n );\n }\n\n // count=1 — auto-pick (collapsed). User can opt into picker via \"换一个 →\".\n if (daemons.length === 1 && !forcePicker) {\n const d = daemons[0];\n return (\n <div className=\"rounded-md border border-cyan-700/40 bg-cyan-900/10 px-3 py-3 text-xs text-cyan-100\">\n <div className=\"flex items-center justify-between gap-2\">\n <div>\n <span className=\"text-cyan-400/80\">将在</span>{' '}\n <span className=\"font-semibold\">{d.alias}</span>\n <span className=\"text-cyan-300/60\"> ({d.hostname || '—'}) </span>\n <span className=\"text-cyan-400/80\">上创建</span>\n </div>\n {/* Single-daemon networks can still let the user enter picker view; */}\n {/* useful if they want to see telemetry before committing. */}\n <button\n type=\"button\"\n onClick={() => setForcePicker(true)}\n className=\"text-[11px] text-cyan-400 hover:text-cyan-200 underline-offset-2 hover:underline\"\n >\n 详情 →\n </button>\n </div>\n <RuntimeList runtimes={d.runtimes_supported} className=\"mt-1\" />\n </div>\n );\n }\n\n // count≥2 (or forcePicker=true) — grid picker. Desktop up to 3 columns,\n // mobile = single column. Locked per RFC-026 §9.4 mockup.\n return (\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between text-xs text-gray-400\">\n <span>选择一台 host_supervisor 节点({daemons.length} 台在线)</span>\n {forcePicker && daemons.length === 1 && (\n <button\n type=\"button\"\n onClick={() => setForcePicker(false)}\n className=\"text-[11px] text-gray-500 hover:text-gray-300\"\n >\n ← 折叠\n </button>\n )}\n </div>\n <div className=\"grid grid-cols-1 gap-2 md:grid-cols-2 lg:grid-cols-3\">\n {daemons.map(d => (\n <DaemonCard\n key={d.daemon_node_id}\n daemon={d}\n selected={d.daemon_node_id === value}\n onClick={() => onChange(d.daemon_node_id)}\n />\n ))}\n </div>\n </div>\n );\n}\n\n// ───── subcomponents ──────────────────────────────────────────────────\n\nfunction DaemonCard({\n daemon,\n selected,\n onClick,\n}: {\n daemon: DaemonOption;\n selected: boolean;\n onClick: () => void;\n}) {\n const alert = daemon.host_telemetry?.alert_level || 'gray';\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-pressed={selected}\n className={`flex w-full flex-col gap-1.5 rounded-md border px-3 py-2.5 text-left text-xs transition-colors ${\n selected\n ? 'border-cyan-600 bg-cyan-900/15 text-cyan-100'\n : 'border-[#26262b] bg-[#0e0e10] text-gray-300 hover:border-[#3a3a41]'\n }`}\n >\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"truncate font-semibold\">{daemon.alias}</span>\n <AlertChip level={alert} />\n </div>\n <div className=\"truncate text-[11px] text-gray-500\">{daemon.hostname || '—'}</div>\n <RuntimeList runtimes={daemon.runtimes_supported} />\n {(daemon.host_telemetry?.cpu_cores != null || daemon.host_telemetry?.mem_gb != null) && (\n <div className=\"flex gap-3 text-[10px] text-gray-500\">\n {daemon.host_telemetry?.cpu_cores != null && <span>{daemon.host_telemetry.cpu_cores} 核</span>}\n {daemon.host_telemetry?.mem_gb != null && <span>{daemon.host_telemetry.mem_gb} GB</span>}\n </div>\n )}\n </button>\n );\n}\n\nfunction RuntimeList({ runtimes, className = '' }: { runtimes?: string[]; className?: string }) {\n if (!runtimes || runtimes.length === 0) {\n return <div className={`text-[10px] text-gray-600 ${className}`}>runtimes_supported: —</div>;\n }\n return (\n <div className={`flex flex-wrap gap-1 ${className}`}>\n {runtimes.map(r => (\n <span key={r} className=\"rounded bg-[#1c1c1f] px-1.5 py-0.5 text-[10px] text-gray-400\">{r}</span>\n ))}\n </div>\n );\n}\n\nfunction AlertChip({ level }: { level: 'green' | 'yellow' | 'red' | 'gray' }) {\n const cls = {\n green: 'bg-green-600/20 text-green-300 border-green-700/40',\n yellow: 'bg-amber-600/20 text-amber-300 border-amber-700/40',\n red: 'bg-red-600/20 text-red-300 border-red-700/40',\n gray: 'bg-gray-600/20 text-gray-400 border-gray-700/40',\n }[level];\n const label = { green: '正常', yellow: '注意', red: '警报', gray: '离线' }[level];\n return (\n <span className={`rounded border px-1.5 py-0.5 text-[10px] ${cls}`}>{label}</span>\n );\n}\n"],"names":["HostSupervisorPicker","networkId","value","onChange","state","setState","daemons","setDaemons","errMsg","setErrMsg","forcePicker","setForcePicker","alive","url","encodeURIComponent","fetch","cache","then","r","json","d","status","body","unconfirmed","error","ok","list","Array","isArray","length","daemon_node_id","catch","e","Error","message","String","className","viewBox","fill","cx","cy","stroke","strokeWidth","alias","hostname","type","onClick","RuntimeList","runtimes","runtimes_supported","map","DaemonCard","daemon","selected","alert","host_telemetry","alert_level","AlertChip","level","cpu_cores","mem_gb","cls","green","yellow","red","gray","label"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../dashboard-pr4-338/app/nodes/page.tsx","../../../../../dashboard-pr4-338/app/components/CreateNodeWizard.tsx","../../../../../dashboard-pr4-338/app/components/HostSupervisorPicker.tsx","../../../../../dashboard-pr4-338/app/components/NodeLifecycleMenu.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport { timeAgo } from '../components/utils';\nimport { useSessions, useHealth, useNodeLifecycle } from '../lib/hooks';\nimport { useSWRConfig } from 'swr';\nimport { TaskChatPanel } from '../components/TaskChatPanel';\nimport { CreateNodeWizard } from '../components/CreateNodeWizard';\nimport { NodeLifecycleMenu } from '../components/NodeLifecycleMenu';\nimport { EmptyState, NodesEmptyState } from '../components/EmptyState';\nimport { AliasAvatar } from '../components/AliasAvatar';\nimport { useCollapsibleSearch } from '../components/CollapsibleSearch';\nimport type { Session } from '../components/types';\nimport { SESSION_STATUS_CHIP_CLASS as STATUS_COLORS } from '../lib/status';\nimport { useChatUnread } from '../lib/chat-unread';\n\n/** Round 81: shorten long server hostnames (Alibaba `iZ…oyZ` style)\n * for table display. Returns the original string unchanged when ≤12\n * chars. Full value should stay in `title=` for hover + screen-readers. */\nfunction shortServer(server: string | null | undefined): string {\n if (!server) return '—';\n return server.length > 12 ? `${server.slice(0, 8)}…` : server;\n}\n\ntype ViewMode = 'list' | 'grid';\ntype SessionRow = Session & { online: boolean };\n\nexport default function NodesPage() {\n const { sessions, isLoading: loading } = useSessions();\n const { health } = useHealth();\n const { lifecycleByAlias, nodeIdByAlias } = useNodeLifecycle();\n const { hasUnread } = useChatUnread();\n const { mutate } = useSWRConfig();\n // RFC-027 PR2 — after a stop/delete/restart dispatch lands, refresh\n // /api/hub/nodes (lifecycle_state) AND /api/hub/status (sessions).\n // Both feed the menu's state-aware items; otherwise menu stays\n // stale until next 5s SWR poll.\n const refreshNodes = () => {\n mutate((k: unknown) => typeof k === 'string' && (k.startsWith('/api/hub/nodes') || k.startsWith('/api/hub/status')));\n };\n const sseMap = health?.sse_sessions || {};\n // SSE keys are `network_id:alias` since server v0.7+. Look up with the\n // composite key first, fall back to alias-only for legacy hubs.\n const sseFor = (s: { alias: string; network_id?: string }) =>\n (s.network_id ? sseMap[`${s.network_id}:${s.alias}`] : undefined) ?? sseMap[s.alias];\n const [filterStatus, setFilterStatus] = useState('');\n const [search, setSearch] = useState('');\n const [viewMode, setViewMode] = useState<ViewMode>('list');\n const [chatAlias, setChatAlias] = useState<string | null>(null);\n const [showCreate, setShowCreate] = useState(false);\n // #209 R32→R34: the WeChat-style magnifier-toggle search was hand-rolled\n // inline in R32. R34 extracted it to a shared hook so /nodes, /messages,\n // and any future search surface stay visually + behaviourally identical.\n // The hook returns a Button (place in header) + Row (place after header).\n const searchCtl = useCollapsibleSearch({\n value: search,\n onChange: setSearch,\n placeholder: 'Search nodes…',\n label: 'Search nodes',\n enabled: sessions.length > 0,\n });\n\n const filtered: SessionRow[] = sessions\n .map(s => ({ ...s, online: !!sseFor(s) }))\n .filter(s => {\n if (filterStatus === 'online') return s.online;\n if (filterStatus === 'offline') return !s.online;\n if (filterStatus && filterStatus !== s.status) return false;\n return true;\n })\n .filter(s => !search || s.alias.toLowerCase().includes(search.toLowerCase()) || (s.agent || '').toLowerCase().includes(search.toLowerCase()))\n .sort((a, b) => (b.online ? 1 : 0) - (a.online ? 1 : 0) || (b.status === 'working' ? 1 : 0) - (a.status === 'working' ? 1 : 0));\n\n const onlineCount = sessions.filter(s => sseFor(s)).length;\n\n return (\n <div className=\"min-h-screen max-w-full overflow-x-hidden bg-[#0b0b0d] text-gray-100 p-4 sm:p-6\">\n {/* #209 R31 (mobile vertical rhythm — goal \"大幅提升移动端体验\",\n extending R28's Overview pattern + R30's /tasks pattern):\n this header row + the status-bar wrapper + the filter row\n below all drop mb-6 → mb-4 sm:mb-6. Three spots × 8 px =\n ~24 px scroll reclaim on /nodes before the first card.\n #209 R32: search affordance moved to top-right magnifier\n button (Vincent WeChat ref msg 563). justify-between makes\n the title cluster hug left, button hugs right. */}\n <div className=\"flex items-center gap-4 mb-4 sm:mb-6\">\n <div className=\"flex items-center gap-3 min-w-0 flex-1\">\n <h1 className=\"text-2xl font-bold text-white lg:ml-0 ml-10\">Nodes</h1>\n <span className=\"text-xs bg-green-900/30 text-green-400 px-2 py-0.5 rounded-full border border-green-800/30 shrink-0\">\n {onlineCount} online\n </span>\n <span className=\"text-xs bg-gray-900/30 text-gray-400 px-2 py-0.5 rounded-full border border-gray-800/30 shrink-0\">\n {sessions.length} total\n </span>\n </div>\n <div className=\"flex items-center gap-2 shrink-0\">\n {/* node-lifecycle M2: open the create-node wizard (RFC-026 §3.1 P1). */}\n <button\n type=\"button\"\n onClick={() => setShowCreate(true)}\n aria-label=\"新建节点\"\n className=\"inline-flex items-center gap-1 rounded-lg border border-cyan-700/50 bg-cyan-900/15 px-3 py-1.5 text-sm font-medium text-cyan-300 hover:bg-cyan-900/25 transition-colors\"\n >\n <span aria-hidden className=\"text-base leading-none\">+</span>\n <span className=\"hidden sm:inline\">新建节点</span>\n </button>\n <searchCtl.Button />\n </div>\n </div>\n\n {showCreate && <CreateNodeWizard onClose={() => setShowCreate(false)} />}\n\n {/* #209 R34: shared <CollapsibleSearch> component handles row reveal,\n autofocus, Escape, and Cancel. enabled=sessions.length>0 hides\n everything until there's content to search. */}\n <searchCtl.Row />\n\n {/* #217 D6 (less is more): the status distribution bar + its\n working/idle/offline legend duplicated the header chips\n (N online / N total) and the per-card status pills right\n below. One count display per screen — the bar is gone. */}\n\n {/* Round 74: hide the filter+view chrome when there are no nodes\n anywhere — these controls have nothing to act on, and they only\n push the onboarding CTA further down. When at least one session\n exists, the chrome is back even if the current filter happens\n to hide everything (so users can clear filters). */}\n {sessions.length > 0 && (\n <div className=\"flex flex-wrap gap-3 mb-4 sm:mb-6\">\n {/* R32: the inline search input was moved to the top-right\n magnifier toggle above. The status select + List/Grid\n toggle stay here. */}\n <select\n value={filterStatus}\n onChange={e => setFilterStatus(e.target.value)}\n className=\"bg-[#161618] border border-[#26262b] rounded-lg px-3 py-2 text-base sm:text-sm text-white focus:border-blue-500/50 focus:outline-none\"\n >\n <option value=\"\">All</option>\n <option value=\"online\">Online</option>\n <option value=\"offline\">Offline</option>\n <option value=\"working\">Working</option>\n <option value=\"idle\">Idle</option>\n <option value=\"blocked\">Blocked</option>\n <option value=\"error\">Error</option>\n </select>\n {/* Round 80: List/Grid toggle hidden on mobile — Grid uses\n grid-cols-1 below `md` and List degrades to the same single\n column, so the toggle has no visual effect under sm and only\n steals a row of vertical space. */}\n <div className=\"hidden sm:flex ml-auto rounded-lg border border-[#26262b] bg-[#161618] p-1 text-sm\">\n {(['list', 'grid'] as const).map(mode => (\n <button\n key={mode}\n type=\"button\"\n onClick={() => setViewMode(mode)}\n className={`rounded-md px-3 py-1.5 transition-colors ${\n viewMode === mode\n ? 'bg-cyan-500/10 text-cyan-300'\n : 'text-gray-500 hover:text-gray-200'\n }`}\n >\n {mode === 'list' ? 'List' : 'Grid'}\n </button>\n ))}\n </div>\n </div>\n )}\n\n {loading ? (\n <div className=\"animate-pulse space-y-2\">\n {[1,2,3,4].map(i => <div key={i} className=\"h-16 bg-gray-800/20 rounded-lg\" />)}\n </div>\n ) : filtered.length === 0 ? (\n sessions.length === 0 ? (\n /* Round 73: first-run case — no agents anywhere. Use the same\n onboarding empty state as the Overview (NodesEmptyState\n includes the `npx … init` quickstart command). Previously this\n was the \"No nodes match your filters\" copy, which was wrong\n for new users who have no filters applied. */\n <NodesEmptyState />\n ) : (\n <EmptyState\n variant=\"nodes\"\n title=\"No nodes match your filters\"\n sub=\"Try clearing search or status filters, or wait for an agent to register.\"\n />\n )\n ) : viewMode === 'grid' ? (\n <div className=\"grid min-w-0 grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4\">\n {filtered.map(s => {\n const statusKey = s.online ? s.status : 'offline';\n const progress = typeof s.progress === 'number' ? s.progress : 0;\n const unread = hasUnread(s.alias);\n\n return (\n <div\n key={s.alias}\n role=\"button\"\n tabIndex={0}\n onClick={() => setChatAlias(s.alias)}\n onKeyDown={e => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setChatAlias(s.alias); } }}\n className={`relative min-w-0 max-w-full overflow-hidden rounded-xl border border-[#26262b] bg-[#161618] p-4 transition-colors hover:border-cyan-500/40 cursor-pointer ${!s.online ? 'opacity-60' : ''}`}\n >\n {!s.online && (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <span className=\"rotate-[-20deg] rounded-xl border border-white/10 bg-black/20 px-5 py-2 text-xl font-bold uppercase tracking-[0.35em] text-white/10\">\n Offline\n </span>\n </div>\n )}\n <div className=\"flex items-start gap-3\">\n <div className=\"relative shrink-0\">\n <AliasAvatar alias={s.alias} size={36} />\n {unread && <span className=\"absolute -right-1 -top-1 h-3 w-3 rounded-full border-2 border-[#161618] bg-red-500\" />}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"truncate text-base font-semibold text-white\">{s.alias}</span>\n {unread && <span className=\"shrink-0 rounded-full bg-red-500/15 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-red-300\">New</span>}\n <span className={`shrink-0 rounded-md border px-2 py-0.5 text-[10px] uppercase tracking-wide ${STATUS_COLORS[statusKey] || STATUS_COLORS.offline}`}>\n {statusKey}\n </span>\n </div>\n <div className=\"mt-0.5 truncate text-xs text-gray-500\">\n {(s.agent || '—')}<span className=\"text-gray-700 mx-1.5\">·</span><span title={s.server || ''}>{shortServer(s.server)}</span>\n </div>\n </div>\n <span className=\"hidden shrink-0 rounded-lg border border-cyan-500/15 bg-cyan-500/5 px-2 py-1 text-[10px] text-cyan-300/70 sm:inline\">Tap to chat</span>\n {/* RFC-027 PR2 — per-node ⋮ lifecycle menu. The button stopsPropagation\n internally so it doesn't open chat. lifecycleByAlias absent → 'active'\n default, menu renders normal stop/delete options. */}\n <NodeLifecycleMenu\n nodeId={nodeIdByAlias[s.alias] || s.node_id || s.alias}\n alias={s.alias}\n lifecycleState={lifecycleByAlias[s.alias]}\n networkId={s.network_id || null}\n onCompleted={refreshNodes}\n />\n </div>\n\n <div className=\"mt-3 rounded-lg border border-[#1c1c1f] bg-[#0e0e10] px-3 py-2 text-xs\">\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-[10px] uppercase tracking-wide text-gray-600\">Current task</span>\n <span className=\"text-[10px] text-gray-600\">{timeAgo(s.last_seen_at || s.updated_at)}</span>\n </div>\n <div className={`mt-1 line-clamp-2 ${s.task ? 'text-gray-300' : 'text-gray-600 italic'}`}>\n {s.task || 'No current task'}\n </div>\n </div>\n\n {progress > 0 && progress < 100 && (\n <div className=\"mt-3 h-1.5 overflow-hidden rounded-full bg-gray-800\">\n <div className=\"h-1.5 rounded-full bg-cyan-400 transition-all\" style={{ width: `${progress}%` }} />\n </div>\n )}\n\n </div>\n );\n })}\n </div>\n ) : (\n <div className=\"space-y-1 sm:space-y-2\">\n {/* Round 94: AGENT + SERVER merged into one `agent · server`\n cell. Round mobile-command: node row itself opens chat, so\n the old Chat / Send Task action column is gone. */}\n <div className=\"hidden sm:grid sm:grid-cols-10 gap-2 px-4 py-2 text-xs text-gray-600 uppercase\">\n <div className=\"col-span-1\">Status</div>\n <div className=\"col-span-2\">Alias</div>\n <div className=\"col-span-2\">Agent · Server</div>\n <div className=\"col-span-4\">Current Task</div>\n <div className=\"col-span-1\">Updated</div>\n </div>\n {filtered.map(s => {\n const statusKey = s.online ? s.status : 'offline';\n const unread = hasUnread(s.alias);\n\n return (\n <div\n key={s.alias}\n role=\"button\"\n tabIndex={0}\n onClick={() => setChatAlias(s.alias)}\n onKeyDown={e => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setChatAlias(s.alias); } }}\n className={`rounded-lg border border-[#26262b] bg-[#161618] px-3 py-2 sm:px-4 sm:py-3 transition-colors hover:border-cyan-500/40 cursor-pointer ${!s.online ? 'opacity-50' : ''}`}\n >\n <div className=\"hidden sm:grid sm:grid-cols-10 gap-2 items-center\">\n <div className=\"col-span-1\">\n <span className={`text-xs px-2 py-0.5 rounded-md border ${STATUS_COLORS[statusKey] || STATUS_COLORS.offline}`}>\n {statusKey}\n </span>\n </div>\n <div className=\"col-span-2 min-w-0\">\n <div className=\"flex items-center gap-2 min-w-0\">\n <div className=\"relative shrink-0\">\n <AliasAvatar alias={s.alias} size={20} />\n {unread && <span className=\"absolute -right-1 -top-1 h-2.5 w-2.5 rounded-full border border-[#161618] bg-red-500\" />}\n </div>\n <span className=\"truncate text-sm font-medium text-white\">{s.alias}</span>\n {unread && <span className=\"shrink-0 rounded-full bg-red-500/15 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-red-300\">New</span>}\n </div>\n </div>\n <div className=\"col-span-2 truncate text-xs text-gray-400\" title={s.server || ''}>\n <span className=\"truncate\">{s.agent || '--'}<span className=\"text-gray-700 mx-1.5\">·</span>{shortServer(s.server)}</span>\n </div>\n <div className=\"col-span-4 truncate text-xs text-gray-500\" title={s.task || ''}>{s.task || '--'}</div>\n <div className=\"col-span-1 flex items-center justify-between gap-2 text-xs text-gray-500\">\n <span className=\"truncate\">{timeAgo(s.last_seen_at || s.updated_at)}</span>\n {/* RFC-027 PR2 ⋮ lifecycle menu — desktop list. Defaults\n to 'active' when lifecycleByAlias absent. */}\n <NodeLifecycleMenu\n nodeId={nodeIdByAlias[s.alias] || s.node_id || s.alias}\n alias={s.alias}\n lifecycleState={lifecycleByAlias[s.alias]}\n networkId={s.network_id || null}\n onCompleted={refreshNodes}\n />\n </div>\n </div>\n {/* R7 of #190: mobile node row was ~340px tall × ~150\n rows = the 51k page. Wins this round, in priority\n order: (1) drop the per-row \"Tap anywhere to chat\"\n hint — useful once, redundant 149 times; the cyan\n border on hover/focus still teaches it. (2) tighten\n space-y-2 → space-y-1 so the avatar/task gap is\n 4px tighter on every row. */}\n <div className=\"sm:hidden space-y-1\">\n <div className=\"flex items-center gap-2.5\">\n <div className=\"relative shrink-0\">\n <AliasAvatar alias={s.alias} size={28} />\n {unread && <span className=\"absolute -right-1 -top-1 h-3 w-3 rounded-full border-2 border-[#161618] bg-red-500\" />}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2 min-w-0\">\n <div className=\"truncate text-sm font-medium text-white\">{s.alias}</div>\n {unread && <span className=\"shrink-0 rounded-full bg-red-500/15 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-red-300\">New</span>}\n </div>\n <div className=\"truncate text-[10px] text-gray-500\">{s.agent || '—'} · {timeAgo(s.last_seen_at || s.updated_at)}</div>\n </div>\n <span className={`shrink-0 text-xs px-2 py-0.5 rounded-md border ${STATUS_COLORS[statusKey] || STATUS_COLORS.offline}`}>\n {statusKey}\n </span>\n {/* RFC-027 PR2 ⋮ lifecycle menu — mobile list. */}\n <NodeLifecycleMenu\n nodeId={nodeIdByAlias[s.alias] || s.node_id || s.alias}\n alias={s.alias}\n lifecycleState={lifecycleByAlias[s.alias]}\n networkId={s.network_id || null}\n onCompleted={refreshNodes}\n />\n </div>\n {s.task && <div className=\"truncate text-xs text-gray-500\">{s.task}</div>}\n </div>\n </div>\n );\n })}\n </div>\n )}\n\n {chatAlias && <TaskChatPanel alias={chatAlias} onClose={() => setChatAlias(null)} />}\n </div>\n );\n}\n","'use client';\n\nimport { useEffect, useState } from 'react';\nimport { useNetworkId } from '../lib/network-context';\nimport { DaemonOption, HostSupervisorPicker } from './HostSupervisorPicker';\n\n/**\n * Create-node wizard (node-lifecycle UI M2/PR4 — RFC-026 §3.1).\n * 6 steps now: ⓪ host (PR4 #338) ① name ② runtime ③ model ④ flags ⑤ confirm\n * → POST /api/anet/node-create with `daemon_node_id` set to the chosen host.\n *\n * PR4 (#338 main lane PR4) folds RFC-026 §9.4 host_supervisor picker in front\n * of the existing 5 steps. Three states the picker resolves internally:\n * - count=0 → onboarding (no daemon, show install command + block forward)\n * - count=1 → auto-pick + forward immediately\n * - count≥2 → user picks, then forward\n * The wizard now ALWAYS passes daemon_node_id to /api/anet/node-create (the\n * route's `resolveLocalDaemonNodeId` fallback only fires if daemon_node_id is\n * absent — kept for back-compat with non-wizard callers but no longer used\n * from this flow). Per [[feedback_doc_capability_claim_verify_code_path]] —\n * the API contract is exercised locally before any prod hub touches the path.\n */\n\n// IDs MUST match the hub validator enums (server/src/create-node-validate.ts).\n// Caught via local /mcp probe during mobile wizard build (#338 plan B):\n// pre-fix RUNTIMES had 'codex' + 'grok' but hub accepts 'codex-sdk' +\n// 'grok-build-acp'; pre-fix PERMISSION_MODES had 'auto' but hub rejects it\n// (flag_value_invalid). The wizard has been silently shipping invalid combos\n// for any non-claude-agent-sdk pick since M2 — only worked end-to-end with\n// the default claude path.\nconst RUNTIMES: { id: string; label: string; models: string[] }[] = [\n { id: 'claude-agent-sdk', label: 'Claude Agent SDK', models: ['deepseek-v4-pro', 'MiniMax-M3', 'claude-sonnet-4-6', 'claude-opus-4-x'] },\n { id: 'codex-sdk', label: 'Codex SDK', models: ['gpt-5.5'] },\n { id: 'grok-build-acp', label: 'Grok (build-acp)', models: ['grok-build'] },\n];\nconst PERMISSION_MODES = ['default', 'acceptEdits', 'plan', 'bypassPermissions'];\nconst STEPS = ['服务器', '名字', 'Runtime', '模型', '参数', '确认'];\n\ntype Phase = 'form' | 'creating' | 'done' | 'unconfirmed' | 'error';\n\nexport function CreateNodeWizard({\n networkId,\n onClose,\n onCreated,\n}: {\n networkId?: string;\n onClose: () => void;\n onCreated?: (result: unknown) => void;\n}) {\n const [step, setStep] = useState(0);\n const [daemonNodeId, setDaemonNodeId] = useState<string | null>(null);\n // (#338 wizard-runtime-filter) keep the full daemon row so the Runtime\n // step can disable runtimes the chosen daemon doesn't declare support\n // for. Hub-side enforcement still wins; this is UX surfacing.\n const [daemon, setDaemon] = useState<DaemonOption | null>(null);\n const [name, setName] = useState('');\n const [runtimeId, setRuntimeId] = useState(RUNTIMES[0].id);\n const [model, setModel] = useState('');\n const [permissionMode, setPermissionMode] = useState('default');\n const [maxTurns, setMaxTurns] = useState('');\n const [budget, setBudget] = useState('');\n const [timeout, setTimeout] = useState('');\n const [phase, setPhase] = useState<Phase>('form');\n const [msg, setMsg] = useState('');\n const [childUp, setChildUp] = useState(false);\n const { networkId: ctxNetworkId } = useNetworkId();\n const netId = networkId || ctxNetworkId;\n\n // Escape closes the wizard (unless a create is mid-flight, so a stray key\n // can't drop the dialog while the request is settling).\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape' && phase !== 'creating') onClose(); };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [onClose, phase]);\n\n // After dispatch, confirm the child actually came up by watching the node\n // list for it to register (RFC-026 progress signal — get_create_request is\n // daemon-only, so the dashboard confirms via /api/hub/status). Polls ~24s.\n useEffect(() => {\n if (phase !== 'done' || childUp) return;\n let alive = true;\n let tries = 0;\n const want = name.trim();\n const tick = async () => {\n tries += 1;\n try {\n const url = netId ? `/api/hub/status?network_id=${encodeURIComponent(netId)}` : '/api/hub/status';\n const r = await fetch(url, { cache: 'no-store' });\n const d = await r.json().catch(() => ({}));\n const list = Array.isArray(d?.sessions) ? d.sessions : Array.isArray(d) ? d : [];\n if (alive && list.some((s: { alias?: string }) => s?.alias === want)) { setChildUp(true); return; }\n } catch { /* transient — keep polling */ }\n if (alive && tries < 16) window.setTimeout(tick, 1500);\n };\n const t = window.setTimeout(tick, 1200);\n return () => { alive = false; window.clearTimeout(t); };\n }, [phase, childUp, netId, name]);\n\n const runtime = RUNTIMES.find(r => r.id === runtimeId) || RUNTIMES[0];\n const nameValid = name.trim().length > 0;\n const canNext =\n (step === 0 && Boolean(daemonNodeId)) || // step 0: must have chosen a daemon\n (step === 1 && nameValid) || // step 1: name non-empty\n (step >= 2 && step < STEPS.length); // later steps: nothing required to advance\n const busy = phase === 'creating';\n\n async function handleCreate() {\n setPhase('creating');\n setMsg('');\n const numOrUndef = (v: string) => (v.trim() === '' ? undefined : Number(v));\n const node_spec = {\n name: name.trim(),\n runtime: runtimeId,\n ...(model ? { model } : {}),\n flags: {\n permissionMode,\n maxTurns: numOrUndef(maxTurns),\n budget: numOrUndef(budget),\n timeout: numOrUndef(timeout),\n },\n };\n try {\n const r = await fetch('/api/anet/node-create', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n node_spec,\n ...(daemonNodeId ? { daemon_node_id: daemonNodeId } : {}),\n ...(networkId ? { network_id: networkId } : {}),\n }),\n });\n const data = await r.json().catch(() => ({}));\n if (r.ok && data?.ok) {\n setPhase('done');\n setMsg('创建请求已下发,节点正在拉起…');\n onCreated?.(data.result);\n } else if (data?.unconfirmed) {\n setPhase('unconfirmed');\n setMsg(`后端 create_node 未就绪:${data?.error || '不可用'}(测试 hub 可能未含 #299)`);\n } else {\n setPhase('error');\n setMsg(data?.error ? `创建失败:${data.error}` : '创建失败');\n }\n } catch (e) {\n setPhase('error');\n setMsg(`创建失败:${e instanceof Error ? e.message : '网络错误'}`);\n }\n }\n\n const inputCls =\n 'w-full rounded-md border border-[#26262b] bg-[#0e0e10] px-3 py-2 text-sm text-gray-200 focus:border-cyan-600 focus:outline-none';\n\n return (\n <>\n <div className=\"fixed inset-0 bg-black/50 z-40\" onClick={onClose} aria-hidden />\n <div\n role=\"dialog\"\n aria-label=\"新建节点\"\n // RFC-026 §9.4 responsive: mobile single-screen (full width minus\n // gutter, taller); desktop ~3-col-friendly width when picker is shown.\n 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\"\n >\n {/* Header */}\n <div className=\"flex items-center justify-between border-b border-[#26262b] px-4 py-3\">\n <div className=\"text-sm font-semibold text-white\">新建节点</div>\n <button onClick={onClose} aria-label=\"关闭\" className=\"inline-flex h-8 w-8 items-center justify-center rounded-md text-gray-500 hover:bg-white/5 hover:text-white\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden>\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n {/* Step indicator */}\n <div className=\"flex items-center gap-1.5 px-4 pt-3\">\n {STEPS.map((label, i) => (\n <div key={label} className=\"flex flex-1 flex-col items-center gap-1\">\n <div className={`h-1 w-full rounded-full ${i <= step ? 'bg-cyan-500' : 'bg-[#26262b]'}`} />\n <span className={`text-[10px] ${i === step ? 'text-cyan-300' : 'text-gray-600'}`}>{label}</span>\n </div>\n ))}\n </div>\n\n {/* Body */}\n <div className=\"min-h-[180px] px-4 py-4\">\n {phase !== 'form' ? (\n <div className=\"flex h-[180px] flex-col items-center justify-center gap-3 text-center\">\n {busy && (\n <svg className=\"h-7 w-7 animate-spin text-cyan-400\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden>\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-90\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z\" />\n </svg>\n )}\n <div className={`text-sm ${phase === 'done' ? 'text-green-300' : phase === 'error' ? 'text-red-300' : phase === 'unconfirmed' ? 'text-amber-300' : 'text-gray-300'}`}>\n {busy ? '正在创建…' : phase === 'done' && childUp ? `✓ ${name.trim()} 已上线` : msg}\n </div>\n {/* Real progress: poll the node list for the child to register\n (派单→fork→注册→✓). */}\n {phase === 'done' && (childUp ? (\n <p className=\"text-[11px] text-green-500/80\">节点已注册,已出现在节点列表。</p>\n ) : (\n <p className=\"inline-flex items-center gap-1.5 text-[11px] text-gray-500\">\n <svg className=\"h-3 w-3 animate-spin\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden>\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-90\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z\" />\n </svg>\n 正在监测 {name.trim()} 注册…(最长 ~24s)\n </p>\n ))}\n </div>\n ) : (\n <>\n {step === 0 && (\n <div className=\"space-y-2\">\n <span className=\"text-xs text-gray-400\">在哪台机器上创建</span>\n <HostSupervisorPicker\n networkId={netId || undefined}\n value={daemonNodeId}\n onChange={(id, d) => {\n setDaemonNodeId(id);\n setDaemon(d);\n // (#338 wizard-runtime-filter) If the current runtime\n // pick isn't supported by the new daemon, reset so\n // the user is forced to re-pick on step 2. Otherwise\n // they could land on step 5 (确认) with an\n // already-invalid combo that only hub rejection\n // surfaces.\n const supported = d?.runtimes_supported;\n if (supported && supported.length > 0 && !supported.includes(runtimeId)) {\n setRuntimeId(supported[0]);\n setModel('');\n }\n }}\n />\n {!daemonNodeId && (\n <p className=\"text-[11px] text-gray-600\">\n 没选服务器之前无法继续;如果列表是空的,按提示在目标机器上跑 <code className=\"rounded bg-black/40 px-1 py-0.5\">anet daemon up &lt;name&gt;</code>。\n </p>\n )}\n </div>\n )}\n {step === 1 && (\n <label className=\"block space-y-1.5\">\n <span className=\"text-xs text-gray-400\">节点名字</span>\n <input autoFocus value={name} onChange={e => setName(e.target.value)} placeholder=\"例如 my-agent-1\" className={inputCls} />\n {!nameValid && <span className=\"text-[11px] text-gray-600\">名字不能为空</span>}\n </label>\n )}\n {step === 2 && (\n <div className=\"space-y-2\">\n <span className=\"text-xs text-gray-400\">\n Runtime{daemon ? `(${daemon.alias} 支持)` : ''}\n </span>\n {RUNTIMES.map(r => {\n // (#338 wizard-runtime-filter) Permissive when the\n // daemon didn't publish runtimes_supported at all\n // (pre-PR3 daemons OR daemons not yet upgraded) — hub\n // still validates. Restrictive only when the daemon\n // explicitly told us its supported set.\n const supported = daemon?.runtimes_supported;\n const disabled = Array.isArray(supported) && supported.length > 0 && !supported.includes(r.id);\n const selected = runtimeId === r.id;\n return (\n <button\n key={r.id}\n type=\"button\"\n disabled={disabled}\n onClick={() => { if (!disabled) { setRuntimeId(r.id); setModel(''); } }}\n title={disabled ? `${daemon?.alias || '该 daemon'} 未声明支持此 runtime` : undefined}\n className={`flex w-full items-center justify-between rounded-md border px-3 py-2 text-sm transition-colors ${\n disabled\n ? 'border-[#1c1c1f] bg-[#0a0a0c] text-gray-600 cursor-not-allowed'\n : selected\n ? 'border-cyan-600 bg-cyan-900/15 text-cyan-200'\n : 'border-[#26262b] bg-[#0e0e10] text-gray-300 hover:border-[#3a3a41]'\n }`}\n >\n <span>\n {r.label}\n {disabled && <span className=\"ml-2 text-[10px] text-gray-700\">该 daemon 不支持</span>}\n </span>\n {selected && !disabled && (\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n )}\n </button>\n );\n })}\n </div>\n )}\n {step === 3 && (\n <label className=\"block space-y-1.5\">\n <span className=\"text-xs text-gray-400\">模型({runtime.label})</span>\n <select value={model} onChange={e => setModel(e.target.value)} className={inputCls}>\n <option value=\"\">默认</option>\n {runtime.models.map(m => <option key={m} value={m}>{m}</option>)}\n </select>\n </label>\n )}\n {step === 4 && (\n <div className=\"space-y-3\">\n <label className=\"block space-y-1.5\">\n <span className=\"text-xs text-gray-400\">permissionMode</span>\n <select value={permissionMode} onChange={e => setPermissionMode(e.target.value)} className={inputCls}>\n {PERMISSION_MODES.map(m => <option key={m} value={m}>{m}</option>)}\n </select>\n </label>\n <div className=\"grid grid-cols-3 gap-2\">\n <label className=\"space-y-1\"><span className=\"text-[11px] text-gray-500\">maxTurns</span><input inputMode=\"numeric\" value={maxTurns} onChange={e => setMaxTurns(e.target.value)} className={inputCls} /></label>\n <label className=\"space-y-1\"><span className=\"text-[11px] text-gray-500\">budget</span><input inputMode=\"numeric\" value={budget} onChange={e => setBudget(e.target.value)} className={inputCls} /></label>\n <label className=\"space-y-1\"><span className=\"text-[11px] text-gray-500\">timeout</span><input inputMode=\"numeric\" value={timeout} onChange={e => setTimeout(e.target.value)} className={inputCls} /></label>\n </div>\n </div>\n )}\n {step === 5 && (\n <div className=\"space-y-2 text-sm\">\n <div className=\"rounded-md border border-[#26262b] bg-[#0e0e10] divide-y divide-[#1c1c1f]\">\n {[\n ['服务器', daemonNodeId ? `${daemonNodeId.slice(0, 24)}…` : '—'],\n ['名字', name.trim() || '—'],\n ['Runtime', runtime.label],\n ['模型', model || '默认'],\n ['permissionMode', permissionMode],\n ['maxTurns / budget / timeout', `${maxTurns || '—'} / ${budget || '—'} / ${timeout || '—'}`],\n ].map(([k, v]) => (\n <div key={k} className=\"flex items-start justify-between gap-3 px-3 py-2\">\n <span className=\"shrink-0 text-gray-500 text-xs\">{k}</span>\n <span className=\"text-right text-gray-200 text-xs break-all\">{v}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n </>\n )}\n </div>\n\n {/* Footer nav */}\n {phase === 'form' ? (\n <div className=\"flex items-center justify-between border-t border-[#26262b] px-4 py-3\">\n <button type=\"button\" onClick={() => (step === 0 ? onClose() : setStep(step - 1))} className=\"rounded-md px-3 py-1.5 text-sm text-gray-400 hover:text-gray-200\">\n {step === 0 ? '取消' : '上一步'}\n </button>\n {step < STEPS.length - 1 ? (\n <button type=\"button\" disabled={!canNext} onClick={() => setStep(step + 1)} className={`rounded-md px-4 py-1.5 text-sm font-medium ${canNext ? 'bg-cyan-600 text-white hover:bg-cyan-500' : 'bg-[#1c1c1f] text-gray-600 cursor-not-allowed'}`}>\n 下一步\n </button>\n ) : (\n <button type=\"button\" onClick={handleCreate} className=\"rounded-md bg-green-600 px-4 py-1.5 text-sm font-medium text-white hover:bg-green-500\">\n 创建节点\n </button>\n )}\n </div>\n ) : (\n <div className=\"flex items-center justify-end border-t border-[#26262b] px-4 py-3\">\n <button type=\"button\" onClick={onClose} className=\"rounded-md bg-[#1c1c1f] px-4 py-1.5 text-sm text-gray-200 hover:bg-[#26262b]\">\n {phase === 'done' ? '完成' : '关闭'}\n </button>\n {(phase === 'error' || phase === 'unconfirmed') && (\n <button type=\"button\" onClick={() => setPhase('form')} className=\"ml-2 rounded-md bg-cyan-600 px-4 py-1.5 text-sm text-white hover:bg-cyan-500\">返回修改</button>\n )}\n </div>\n )}\n </div>\n </>\n );\n}\n","'use client';\n\nimport { useEffect, useState } from 'react';\n\n/**\n * PR4 #338 — host_supervisor daemon picker (RFC-026 §9.4 locked mockup).\n *\n * Three states (the only branching the wizard ever sees):\n *\n * count=0 → onboarding: explain what a daemon is + give the install command.\n * No daemon = nothing to dispatch to; create flow is blocked here\n * until the user runs `anet daemon init <name>` somewhere.\n *\n * count=1 → auto-pick: just show \"using <alias>\" + a quiet `换一个 →` link\n * (which switches to the picker view if the user really wants).\n *\n * count≥2 → picker grid: cards for each daemon w/ runtimes + alert chip,\n * click selects. Desktop = up to 3 columns; mobile = single column.\n *\n * Data shape mirrors `/api/anet/host-supervisors`, which in turn mirrors the\n * hub's GET /api/host-supervisors (#338 PR2 — needs commhub-server@0.9.0-preview.8+).\n * On `unconfirmed` (older hub), we degrade honestly to an upgrade hint — never\n * show a fake empty list. Per [[feedback_doc_capability_claim_verify_code_path]].\n */\n\nexport interface DaemonOption {\n // Hub canonical key is `daemon_node_id` (PR2 v2 §9.2 contract). We keep the\n // same name end-to-end so the value the wizard passes back to create_node\n // as `daemon_node_id` doesn't need a rename layer.\n daemon_node_id: string;\n alias: string;\n hostname?: string | null;\n online?: boolean;\n last_seen_at?: string | null;\n runtimes_supported?: string[];\n host_telemetry?: {\n alert_level?: 'green' | 'yellow' | 'red' | 'gray';\n cpu_cores?: number | null;\n mem_gb?: number | null;\n ip_internal?: string | null;\n };\n}\n\ninterface PickResponse {\n ok: boolean;\n unconfirmed?: boolean;\n error?: string;\n count: number;\n daemons: DaemonOption[];\n selected?: string | null;\n}\n\ntype LoadState = 'loading' | 'ready' | 'error' | 'unconfirmed';\n\nexport function HostSupervisorPicker({\n networkId,\n value,\n onChange,\n}: {\n networkId?: string | null;\n value: string | null;\n // (#338 wizard-runtime-filter) passes the full daemon row alongside the\n // id so the wizard can filter the Runtime step by daemon.runtimes_supported\n // — disabling combos the hub would reject anyway and surfacing why upfront.\n onChange: (nodeId: string | null, daemon: DaemonOption | null) => void;\n}) {\n const [state, setState] = useState<LoadState>('loading');\n const [daemons, setDaemons] = useState<DaemonOption[]>([]);\n const [errMsg, setErrMsg] = useState('');\n const [forcePicker, setForcePicker] = useState(false);\n\n useEffect(() => {\n let alive = true;\n setState('loading');\n setErrMsg('');\n const url = networkId\n ? `/api/anet/host-supervisors?network_id=${encodeURIComponent(networkId)}`\n : '/api/anet/host-supervisors';\n fetch(url, { cache: 'no-store' })\n .then(r => r.json().then(d => ({ status: r.status, body: d as PickResponse })))\n .then(({ status, body }) => {\n if (!alive) return;\n if (status === 501 || body?.unconfirmed) {\n setState('unconfirmed');\n setErrMsg(body?.error || 'hub /api/host-supervisors unavailable — upgrade to >=0.9.0-preview.8');\n setDaemons([]);\n return;\n }\n if (!body?.ok) {\n setState('error');\n setErrMsg(body?.error || `hub ${status}`);\n setDaemons([]);\n return;\n }\n const list = Array.isArray(body.daemons) ? body.daemons : [];\n setDaemons(list);\n setState('ready');\n // count=1 auto-pick: preselect the only daemon. count≥2 leaves the\n // selection to the user (parent value stays null until click).\n if (list.length === 1 && !value) onChange(list[0].daemon_node_id, list[0]);\n })\n .catch(e => {\n if (!alive) return;\n setState('error');\n setErrMsg(e instanceof Error ? e.message : String(e));\n setDaemons([]);\n });\n return () => { alive = false; };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [networkId]);\n\n // ───── render branches ──────────────────────────────────────────────\n\n if (state === 'loading') {\n return (\n <div className=\"flex items-center gap-2 rounded-md border border-[#26262b] bg-[#0e0e10] px-3 py-3 text-xs text-gray-500\">\n <svg className=\"h-3.5 w-3.5 animate-spin\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden>\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path className=\"opacity-90\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z\" />\n </svg>\n 正在查询可用的 host_supervisor 节点…\n </div>\n );\n }\n\n if (state === 'unconfirmed') {\n return (\n <div className=\"rounded-md border border-amber-700/40 bg-amber-900/10 px-3 py-3 text-xs text-amber-200\">\n <div className=\"font-semibold mb-1\">hub 暂未升级</div>\n <div className=\"text-amber-200/80\">{errMsg}</div>\n <div className=\"mt-1 text-[11px] text-amber-200/60\">\n 升级到 <code className=\"rounded bg-black/40 px-1 py-0.5\">@sleep2agi/commhub-server@0.9.0-preview.8</code> 后选服务器功能才会出现。\n </div>\n </div>\n );\n }\n\n if (state === 'error') {\n return (\n <div className=\"rounded-md border border-red-700/40 bg-red-900/10 px-3 py-3 text-xs text-red-200\">\n 查询 host_supervisor 节点失败:{errMsg}\n </div>\n );\n }\n\n // count=0 — onboarding\n if (daemons.length === 0) {\n return (\n <div className=\"rounded-md border border-[#26262b] bg-[#0e0e10] px-3 py-4 text-xs text-gray-300\">\n <div className=\"text-sm font-semibold text-gray-200\">还没有可用的 host_supervisor 节点</div>\n <p className=\"mt-1 text-gray-500\">\n 要在某台机器上创建节点,先在那台机器上跑一次 daemon 初始化命令:\n </p>\n <pre className=\"mt-2 overflow-x-auto rounded bg-black/40 p-2 text-[11px] text-cyan-300\">{`# 任选一台目标机器(你的笔记本 / 一台服务器都行)\nanet daemon up my-daemon`}</pre>\n <p className=\"mt-2 text-gray-500\">\n 注册成功后这里会自动出现,无需刷新。\n </p>\n </div>\n );\n }\n\n // count=1 — auto-pick (collapsed). User can opt into picker via \"换一个 →\".\n if (daemons.length === 1 && !forcePicker) {\n const d = daemons[0];\n return (\n <div className=\"rounded-md border border-cyan-700/40 bg-cyan-900/10 px-3 py-3 text-xs text-cyan-100\">\n <div className=\"flex items-center justify-between gap-2\">\n <div>\n <span className=\"text-cyan-400/80\">将在</span>{' '}\n <span className=\"font-semibold\">{d.alias}</span>\n <span className=\"text-cyan-300/60\"> ({d.hostname || '—'}) </span>\n <span className=\"text-cyan-400/80\">上创建</span>\n </div>\n {/* Single-daemon networks can still let the user enter picker view; */}\n {/* useful if they want to see telemetry before committing. */}\n <button\n type=\"button\"\n onClick={() => setForcePicker(true)}\n className=\"text-[11px] text-cyan-400 hover:text-cyan-200 underline-offset-2 hover:underline\"\n >\n 详情 →\n </button>\n </div>\n <RuntimeList runtimes={d.runtimes_supported} className=\"mt-1\" />\n </div>\n );\n }\n\n // count≥2 (or forcePicker=true) — grid picker. Desktop up to 3 columns,\n // mobile = single column. Locked per RFC-026 §9.4 mockup.\n return (\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between text-xs text-gray-400\">\n <span>选择一台 host_supervisor 节点({daemons.length} 台在线)</span>\n {forcePicker && daemons.length === 1 && (\n <button\n type=\"button\"\n onClick={() => setForcePicker(false)}\n className=\"text-[11px] text-gray-500 hover:text-gray-300\"\n >\n ← 折叠\n </button>\n )}\n </div>\n <div className=\"grid grid-cols-1 gap-2 md:grid-cols-2 lg:grid-cols-3\">\n {daemons.map(d => (\n <DaemonCard\n key={d.daemon_node_id}\n daemon={d}\n selected={d.daemon_node_id === value}\n onClick={() => onChange(d.daemon_node_id, d)}\n />\n ))}\n </div>\n </div>\n );\n}\n\n// ───── subcomponents ──────────────────────────────────────────────────\n\nfunction DaemonCard({\n daemon,\n selected,\n onClick,\n}: {\n daemon: DaemonOption;\n selected: boolean;\n onClick: () => void;\n}) {\n const alert = daemon.host_telemetry?.alert_level || 'gray';\n return (\n <button\n type=\"button\"\n onClick={onClick}\n aria-pressed={selected}\n className={`flex w-full flex-col gap-1.5 rounded-md border px-3 py-2.5 text-left text-xs transition-colors ${\n selected\n ? 'border-cyan-600 bg-cyan-900/15 text-cyan-100'\n : 'border-[#26262b] bg-[#0e0e10] text-gray-300 hover:border-[#3a3a41]'\n }`}\n >\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"truncate font-semibold\">{daemon.alias}</span>\n <AlertChip level={alert} />\n </div>\n <div className=\"truncate text-[11px] text-gray-500\">{daemon.hostname || '—'}</div>\n <RuntimeList runtimes={daemon.runtimes_supported} />\n {(daemon.host_telemetry?.cpu_cores != null || daemon.host_telemetry?.mem_gb != null) && (\n <div className=\"flex gap-3 text-[10px] text-gray-500\">\n {daemon.host_telemetry?.cpu_cores != null && <span>{daemon.host_telemetry.cpu_cores} 核</span>}\n {daemon.host_telemetry?.mem_gb != null && <span>{daemon.host_telemetry.mem_gb} GB</span>}\n </div>\n )}\n </button>\n );\n}\n\nfunction RuntimeList({ runtimes, className = '' }: { runtimes?: string[]; className?: string }) {\n if (!runtimes || runtimes.length === 0) {\n return <div className={`text-[10px] text-gray-600 ${className}`}>runtimes_supported: —</div>;\n }\n return (\n <div className={`flex flex-wrap gap-1 ${className}`}>\n {runtimes.map(r => (\n <span key={r} className=\"rounded bg-[#1c1c1f] px-1.5 py-0.5 text-[10px] text-gray-400\">{r}</span>\n ))}\n </div>\n );\n}\n\nfunction AlertChip({ level }: { level: 'green' | 'yellow' | 'red' | 'gray' }) {\n const cls = {\n green: 'bg-green-600/20 text-green-300 border-green-700/40',\n yellow: 'bg-amber-600/20 text-amber-300 border-amber-700/40',\n red: 'bg-red-600/20 text-red-300 border-red-700/40',\n gray: 'bg-gray-600/20 text-gray-400 border-gray-700/40',\n }[level];\n const label = { green: '正常', yellow: '注意', red: '警报', gray: '离线' }[level];\n return (\n <span className={`rounded border px-1.5 py-0.5 text-[10px] ${cls}`}>{label}</span>\n );\n}\n","'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\n// RFC-027 PR2 — per-node ⋮ lifecycle menu + stop/delete modals.\n//\n// State-aware menu items (RFC-027 §3.1 table):\n// active → 重启 / 停止 / 删除\n// stopping/deleting → loading (all disabled,菜单 surfaces \"请稍候\")\n// stopped → 启动 / 删除 (停止 灰掉 — already stopped)\n// stop_failed → 启动 / 删除 (warn — operator should investigate)\n//\n// Stop modal: low-friction confirm (RFC-027 §3.3)\n// Delete modal: alias-input confirm + force-on-in-flight checkbox\n// (RFC-027 §3.2; mirrors hub's confirm_alias gate + force semantics).\n//\n// Error propagation per 通信龙 PR2 requirement: structured payloads\n// from hub (node_not_active / cannot_delete_daemon_via_delete_node /\n// node_busy_in_flight / confirm_alias_mismatch / forbidden_cross_tenant)\n// land in `lastError` with their real fields surfaced in the UI — no\n// generic \"操作失败\".\n//\n// React rules-of-hooks: all hooks declared BEFORE early returns.\n\nexport type LifecycleState =\n | 'active'\n | 'stopping'\n | 'stopped'\n | 'stop_failed'\n | 'deleting'\n | string; // forward-compat for unknown server values\n\nexport interface NodeLifecycleMenuProps {\n nodeId: string;\n alias: string;\n lifecycleState: LifecycleState | null | undefined;\n networkId?: string | null;\n /** Called when a lifecycle op completes successfully (caller refreshes nodes list). */\n onCompleted?: () => void;\n}\n\ntype LifecycleAction = 'restart' | 'stop' | 'delete';\n\ntype ApiReply = {\n ok?: boolean;\n error?: string;\n message?: string;\n in_flight_count?: number;\n hint?: string;\n lifecycle_state?: string;\n unconfirmed?: boolean;\n [k: string]: unknown;\n};\n\nconst normalizeState = (s: LifecycleState | null | undefined): LifecycleState =>\n (typeof s === 'string' && s.length > 0 ? s : 'active');\n\nasync function callLifecycle(\n action: LifecycleAction,\n body: Record<string, unknown>,\n): Promise<ApiReply & { httpStatus: number }> {\n try {\n const r = await fetch('/api/anet/node-lifecycle', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ action, ...body }),\n });\n const data = (await r.json().catch(() => ({}))) as ApiReply;\n return { ...data, httpStatus: r.status };\n } catch (e: unknown) {\n return {\n ok: false,\n error: 'network_error',\n message: e instanceof Error ? e.message : String(e),\n httpStatus: 0,\n };\n }\n}\n\nexport function NodeLifecycleMenu({\n nodeId,\n alias,\n lifecycleState,\n networkId,\n onCompleted,\n}: NodeLifecycleMenuProps) {\n // All hooks above any early return (avoid hooks-order regression that\n // bit the mobile app at v0.1.29; 通信龙 explicit call-out for PR2).\n const [menuOpen, setMenuOpen] = useState(false);\n const [stopModal, setStopModal] = useState(false);\n const [deleteModal, setDeleteModal] = useState(false);\n const [restartBusy, setRestartBusy] = useState(false);\n const [lastError, setLastError] = useState<ApiReply | null>(null);\n const menuRef = useRef<HTMLDivElement | null>(null);\n\n // Outside-click + Escape close the menu (focus management).\n useEffect(() => {\n if (!menuOpen) return;\n const onDoc = (e: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) setMenuOpen(false);\n };\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') setMenuOpen(false); };\n document.addEventListener('mousedown', onDoc);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('mousedown', onDoc);\n document.removeEventListener('keydown', onKey);\n };\n }, [menuOpen]);\n\n const onRestart = useCallback(async () => {\n setMenuOpen(false);\n setLastError(null);\n setRestartBusy(true);\n const r = await callLifecycle('restart', {\n node_id: nodeId,\n ...(networkId ? { network_id: networkId } : {}),\n });\n setRestartBusy(false);\n if (r.ok) {\n onCompleted?.();\n return;\n }\n setLastError(r);\n }, [nodeId, networkId, onCompleted]);\n\n const state = normalizeState(lifecycleState);\n const isLoading = state === 'stopping' || state === 'deleting';\n const isActive = state === 'active';\n const isStopped = state === 'stopped' || state === 'stop_failed';\n\n // Menu items per RFC-027 §3.1 table.\n const items: Array<{ label: string; key: string; danger?: boolean; onClick: () => void; disabled?: boolean }> = [];\n if (isLoading) {\n items.push({\n label: state === 'stopping' ? '停止中…' : '删除中…',\n key: 'loading', disabled: true, onClick: () => {},\n });\n } else if (isActive) {\n items.push({ label: restartBusy ? '重启中…' : '重启节点', key: 'restart', disabled: restartBusy, onClick: onRestart });\n items.push({ label: '停止节点', key: 'stop', onClick: () => { setMenuOpen(false); setStopModal(true); } });\n items.push({ label: '删除节点', key: 'delete', danger: true, onClick: () => { setMenuOpen(false); setDeleteModal(true); } });\n } else if (isStopped) {\n // stopped + stop_failed: \"启动\" = restart_node (hub resets lifecycle_state→active on success per PR1.2a)\n items.push({ label: restartBusy ? '启动中…' : '启动节点', key: 'restart', disabled: restartBusy, onClick: onRestart });\n items.push({ label: '删除节点', key: 'delete', danger: true, onClick: () => { setMenuOpen(false); setDeleteModal(true); } });\n } else {\n // Unknown state — surface read-only badge, no destructive action.\n items.push({\n label: `状态 ${state} (不识别)`,\n key: 'unknown', disabled: true, onClick: () => {},\n });\n }\n\n return (\n <div ref={menuRef} className=\"relative inline-block\" onClick={e => e.stopPropagation()}>\n <button\n type=\"button\"\n aria-label={`节点 ${alias} 生命周期操作`}\n aria-haspopup=\"menu\"\n aria-expanded={menuOpen}\n onClick={() => setMenuOpen(v => !v)}\n className=\"inline-flex h-8 w-8 items-center justify-center rounded-md text-gray-400 hover:bg-white/5 hover:text-white focus:outline-none focus:ring-1 focus:ring-cyan-500/50\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden>\n <circle cx=\"12\" cy=\"5\" r=\"1.6\" />\n <circle cx=\"12\" cy=\"12\" r=\"1.6\" />\n <circle cx=\"12\" cy=\"19\" r=\"1.6\" />\n </svg>\n </button>\n {menuOpen && (\n <div role=\"menu\" className=\"absolute right-0 z-40 mt-1 w-44 overflow-hidden rounded-md border border-[#26262b] bg-[#161618] shadow-xl\">\n {items.map(item => (\n <button\n key={item.key}\n type=\"button\"\n role=\"menuitem\"\n disabled={item.disabled}\n onClick={item.onClick}\n className={`block w-full px-3 py-2 text-left text-sm transition-colors ${\n item.disabled\n ? 'text-gray-600 cursor-not-allowed'\n : item.danger\n ? 'text-red-300 hover:bg-red-900/20'\n : 'text-gray-200 hover:bg-white/5'\n }`}\n >\n {item.label}\n </button>\n ))}\n </div>\n )}\n\n {/* Last error inline (under the button) — pass-through hub's structured fields */}\n {lastError && lastError.ok === false && !stopModal && !deleteModal && (\n <div className=\"absolute right-0 z-40 mt-1 w-72 rounded-md border border-red-700/40 bg-red-900/20 px-3 py-2 text-xs text-red-200\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"font-semibold\">{lastError.error || 'error'}</div>\n {lastError.message ? <div className=\"mt-0.5 text-red-300/80\">{lastError.message}</div> : null}\n {typeof lastError.in_flight_count === 'number' && (\n <div className=\"mt-0.5 text-red-300/80\">in-flight: {lastError.in_flight_count}</div>\n )}\n {lastError.hint ? <div className=\"mt-1 text-red-300/60\">{lastError.hint}</div> : null}\n </div>\n <button type=\"button\" onClick={() => setLastError(null)} className=\"shrink-0 text-red-400 hover:text-red-200\" aria-label=\"关闭\">×</button>\n </div>\n </div>\n )}\n\n {stopModal && (\n <StopNodeModal\n alias={alias}\n nodeId={nodeId}\n networkId={networkId}\n onClose={() => setStopModal(false)}\n onCompleted={() => { setStopModal(false); onCompleted?.(); }}\n />\n )}\n {deleteModal && (\n <DeleteNodeModal\n alias={alias}\n nodeId={nodeId}\n networkId={networkId}\n onClose={() => setDeleteModal(false)}\n onCompleted={() => { setDeleteModal(false); onCompleted?.(); }}\n />\n )}\n </div>\n );\n}\n\n// ──────────────────────────────────────────────────────────────────────\n\ninterface ModalProps {\n alias: string;\n nodeId: string;\n networkId?: string | null;\n onClose: () => void;\n onCompleted: () => void;\n}\n\nfunction StopNodeModal({ alias, nodeId, networkId, onClose, onCompleted }: ModalProps) {\n const [busy, setBusy] = useState(false);\n const [force, setForce] = useState(false);\n const [reply, setReply] = useState<ApiReply | null>(null);\n\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape' && !busy) onClose(); };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [onClose, busy]);\n\n const inFlight = reply && typeof reply.in_flight_count === 'number' ? reply.in_flight_count : 0;\n\n const onConfirm = async () => {\n setBusy(true);\n setReply(null);\n const r = await callLifecycle('stop', {\n node_id: nodeId,\n ...(networkId ? { network_id: networkId } : {}),\n ...(force ? { force: true } : {}),\n });\n setBusy(false);\n if (r.ok) { onCompleted(); return; }\n setReply(r);\n };\n\n return (\n <>\n <div className=\"fixed inset-0 z-40 bg-black/50\" onClick={busy ? undefined : onClose} aria-hidden />\n <div role=\"dialog\" aria-label={`停止节点 ${alias}`} className=\"fixed left-1/2 top-1/2 z-50 w-[min(92vw,420px)] -translate-x-1/2 -translate-y-1/2 rounded-xl border border-[#26262b] bg-[#161618] shadow-2xl\">\n <div className=\"flex items-center justify-between border-b border-[#26262b] px-4 py-3\">\n <div className=\"text-sm font-semibold text-white\">停止节点</div>\n <button onClick={busy ? undefined : onClose} aria-label=\"关闭\" className=\"text-gray-500 hover:text-white\">×</button>\n </div>\n <div className=\"space-y-3 px-4 py-4\">\n <div className=\"text-sm text-gray-300\">\n 将停止 <span className=\"font-mono text-cyan-300\">{alias}</span> 子进程(SIGTERM,~10s 内)。配置目录保留,可通过「启动」恢复。\n </div>\n {/* Surface hub's structured payload field-by-field; never collapse to generic */}\n {reply && reply.ok === false && (\n <div className=\"rounded-md border border-red-700/40 bg-red-900/20 px-3 py-2 text-xs text-red-200\">\n <div className=\"font-semibold\">{reply.error}</div>\n {reply.message ? <div className=\"mt-0.5 text-red-300/80\">{reply.message}</div> : null}\n {typeof reply.in_flight_count === 'number' && (\n <div className=\"mt-0.5 text-red-300/80\">\n 当前 in-flight 任务: {reply.in_flight_count}\n </div>\n )}\n {reply.hint ? <div className=\"mt-1 text-red-300/60\">{reply.hint}</div> : null}\n </div>\n )}\n {(inFlight > 0 || force) && (\n <label className=\"flex items-start gap-2 rounded-md border border-amber-700/40 bg-amber-900/10 px-3 py-2 text-xs text-amber-200\">\n <input\n type=\"checkbox\"\n checked={force}\n onChange={e => setForce(e.target.checked)}\n className=\"mt-0.5\"\n />\n <span>\n <span className=\"font-semibold text-amber-300\">强制停止</span>{inFlight > 0 ? `(会丢弃 ${inFlight} 条待处理任务)` : '(覆盖 in-flight 拒绝;hub 会写 audit 行)'}\n </span>\n </label>\n )}\n </div>\n <div className=\"flex items-center justify-end gap-2 border-t border-[#26262b] px-4 py-3\">\n <button type=\"button\" disabled={busy} onClick={onClose} className=\"rounded-md px-3 py-1.5 text-sm text-gray-400 hover:text-gray-200 disabled:opacity-50\">取消</button>\n <button\n type=\"button\"\n disabled={busy || (inFlight > 0 && !force)}\n onClick={onConfirm}\n className=\"rounded-md bg-cyan-600 px-4 py-1.5 text-sm font-medium text-white hover:bg-cyan-500 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {busy ? '停止中…' : '确认停止'}\n </button>\n </div>\n </div>\n </>\n );\n}\n\nfunction DeleteNodeModal({ alias, nodeId, networkId, onClose, onCompleted }: ModalProps) {\n const [busy, setBusy] = useState(false);\n const [confirmInput, setConfirmInput] = useState('');\n const [force, setForce] = useState(false);\n const [keepConfig, setKeepConfig] = useState(false);\n const [reply, setReply] = useState<ApiReply | null>(null);\n\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape' && !busy) onClose(); };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [onClose, busy]);\n\n const inFlight = reply && typeof reply.in_flight_count === 'number' ? reply.in_flight_count : 0;\n const confirmValid = confirmInput === alias;\n\n const onConfirm = async () => {\n if (!confirmValid) return;\n setBusy(true);\n setReply(null);\n const r = await callLifecycle('delete', {\n node_id: nodeId,\n confirm_alias: confirmInput,\n ...(networkId ? { network_id: networkId } : {}),\n ...(force ? { force: true } : {}),\n ...(keepConfig ? { delete_config: false } : {}),\n });\n setBusy(false);\n if (r.ok) { onCompleted(); return; }\n setReply(r);\n };\n\n return (\n <>\n <div className=\"fixed inset-0 z-40 bg-black/50\" onClick={busy ? undefined : onClose} aria-hidden />\n <div role=\"dialog\" aria-label={`删除节点 ${alias}`} className=\"fixed left-1/2 top-1/2 z-50 w-[min(94vw,480px)] -translate-x-1/2 -translate-y-1/2 rounded-xl border border-red-700/40 bg-[#161618] shadow-2xl\">\n <div className=\"flex items-center justify-between border-b border-[#26262b] px-4 py-3\">\n <div className=\"text-sm font-semibold text-red-300\">删除节点</div>\n <button onClick={busy ? undefined : onClose} aria-label=\"关闭\" className=\"text-gray-500 hover:text-white\">×</button>\n </div>\n <div className=\"space-y-3 px-4 py-4 text-sm text-gray-300\">\n <div>这将:</div>\n <ul className=\"list-inside list-disc space-y-1 pl-2 text-xs text-gray-400\">\n <li>停止 <span className=\"font-mono text-cyan-300\">{alias}</span> 子进程(SIGTERM ~10s)</li>\n <li>从 hub 注销该节点</li>\n <li>撤销该节点的 ntok</li>\n {!keepConfig && <li>配置文件备份到 <code className=\"text-amber-300\">~/.anet/deleted/&lt;ts&gt;-{alias}/</code>(30 天后自动清除)</li>}\n {keepConfig && <li className=\"text-amber-300\">配置文件保留原地(不备份不清理 — 你勾选了「保留配置」)</li>}\n </ul>\n\n {/* Surface hub's structured payload field-by-field */}\n {reply && reply.ok === false && (\n <div className=\"rounded-md border border-red-700/40 bg-red-900/20 px-3 py-2 text-xs text-red-200\">\n <div className=\"font-semibold\">{reply.error}</div>\n {reply.message ? <div className=\"mt-0.5 text-red-300/80\">{reply.message}</div> : null}\n {typeof reply.in_flight_count === 'number' && (\n <div className=\"mt-0.5 text-red-300/80\">当前 in-flight 任务: {reply.in_flight_count}</div>\n )}\n {reply.hint ? <div className=\"mt-1 text-red-300/60\">{reply.hint}</div> : null}\n </div>\n )}\n\n {(inFlight > 0 || force) && (\n <label className=\"flex items-start gap-2 rounded-md border border-amber-700/40 bg-amber-900/10 px-3 py-2 text-xs text-amber-200\">\n <input\n type=\"checkbox\"\n checked={force}\n onChange={e => setForce(e.target.checked)}\n className=\"mt-0.5\"\n />\n <span>\n <span className=\"font-semibold text-amber-300\">强制删除</span>{inFlight > 0 ? `(会丢弃 ${inFlight} 条待处理任务)` : '(覆盖 in-flight 拒绝)'}\n </span>\n </label>\n )}\n\n <label className=\"flex items-center gap-2 text-xs text-gray-400\">\n <input type=\"checkbox\" checked={keepConfig} onChange={e => setKeepConfig(e.target.checked)} />\n 保留配置目录(不备份;高级用法)\n </label>\n\n <label className=\"block space-y-1\">\n <span className=\"text-xs text-gray-400\">输入节点名字 <span className=\"font-mono text-cyan-300\">{alias}</span> 确认</span>\n <input\n autoFocus\n value={confirmInput}\n onChange={e => setConfirmInput(e.target.value)}\n placeholder={alias}\n className=\"w-full rounded-md border border-[#26262b] bg-[#0e0e10] px-3 py-2 text-sm text-gray-200 focus:border-red-500 focus:outline-none\"\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n spellCheck={false}\n />\n {confirmInput && !confirmValid && (\n <span className=\"text-[11px] text-red-400\">名字不匹配(区分大小写)</span>\n )}\n </label>\n </div>\n <div className=\"flex items-center justify-end gap-2 border-t border-[#26262b] px-4 py-3\">\n <button type=\"button\" disabled={busy} onClick={onClose} className=\"rounded-md px-3 py-1.5 text-sm text-gray-400 hover:text-gray-200 disabled:opacity-50\">取消</button>\n <button\n type=\"button\"\n disabled={busy || !confirmValid || (inFlight > 0 && !force)}\n onClick={onConfirm}\n className=\"rounded-md bg-red-600 px-4 py-1.5 text-sm font-medium text-white hover:bg-red-500 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {busy ? '删除中…' : `删除 ${alias}`}\n </button>\n </div>\n </div>\n </>\n );\n}\n"],"names":["HostSupervisorPicker","networkId","value","onChange","state","setState","daemons","setDaemons","errMsg","setErrMsg","forcePicker","setForcePicker","alive","url","encodeURIComponent","fetch","cache","then","r","json","d","status","body","unconfirmed","error","ok","list","Array","isArray","length","daemon_node_id","catch","e","Error","message","String","className","viewBox","fill","cx","cy","stroke","strokeWidth","alias","hostname","type","onClick","RuntimeList","runtimes","runtimes_supported","map","DaemonCard","daemon","selected","alert","host_telemetry","alert_level","AlertChip","level","cpu_cores","mem_gb","cls","green","yellow","red","gray","label"],"mappings":"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"}
@@ -7,9 +7,9 @@ globalThis.__BUILD_MANIFEST = {
7
7
  "static/chunks/03~yq9q893hmn.js"
8
8
  ],
9
9
  "lowPriorityFiles": [
10
- "static/S9Q_U9UD2ZJQPBZjZgrZy/_buildManifest.js",
11
- "static/S9Q_U9UD2ZJQPBZjZgrZy/_ssgManifest.js",
12
- "static/S9Q_U9UD2ZJQPBZjZgrZy/_clientMiddlewareManifest.js"
10
+ "static/3WnbjoWrJbRnQkx4ilgVm/_buildManifest.js",
11
+ "static/3WnbjoWrJbRnQkx4ilgVm/_ssgManifest.js",
12
+ "static/3WnbjoWrJbRnQkx4ilgVm/_clientMiddlewareManifest.js"
13
13
  ],
14
14
  "rootMainFiles": [
15
15
  "static/chunks/12xixbh.66y8a.js",