@sleep2agi/agent-network-dashboard 0.4.6-preview.2 → 0.4.6-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 (159) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +3 -3
  3. package/.next/diagnostics/route-bundle-stats.json +4 -4
  4. package/.next/fallback-build-manifest.json +3 -3
  5. package/.next/prerender-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_client-reference-manifest.js +1 -1
  23. package/.next/server/app/admin.html +2 -2
  24. package/.next/server/app/admin.rsc +2 -2
  25. package/.next/server/app/admin.segments/_full.segment.rsc +2 -2
  26. package/.next/server/app/admin.segments/_head.segment.rsc +1 -1
  27. package/.next/server/app/admin.segments/_index.segment.rsc +2 -2
  28. package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
  29. package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +1 -1
  30. package/.next/server/app/admin.segments/admin.segment.rsc +1 -1
  31. package/.next/server/app/index.html +2 -2
  32. package/.next/server/app/index.rsc +3 -3
  33. package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  34. package/.next/server/app/index.segments/_full.segment.rsc +3 -3
  35. package/.next/server/app/index.segments/_head.segment.rsc +1 -1
  36. package/.next/server/app/index.segments/_index.segment.rsc +2 -2
  37. package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  38. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  39. package/.next/server/app/login.html +2 -2
  40. package/.next/server/app/login.rsc +3 -3
  41. package/.next/server/app/login.segments/_full.segment.rsc +3 -3
  42. package/.next/server/app/login.segments/_head.segment.rsc +1 -1
  43. package/.next/server/app/login.segments/_index.segment.rsc +2 -2
  44. package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  45. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
  46. package/.next/server/app/login.segments/login.segment.rsc +1 -1
  47. package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
  48. package/.next/server/app/logs.html +2 -2
  49. package/.next/server/app/logs.rsc +2 -2
  50. package/.next/server/app/logs.segments/_full.segment.rsc +2 -2
  51. package/.next/server/app/logs.segments/_head.segment.rsc +1 -1
  52. package/.next/server/app/logs.segments/_index.segment.rsc +2 -2
  53. package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
  54. package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +1 -1
  55. package/.next/server/app/logs.segments/logs.segment.rsc +1 -1
  56. package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
  57. package/.next/server/app/messages.html +2 -2
  58. package/.next/server/app/messages.rsc +2 -2
  59. package/.next/server/app/messages.segments/_full.segment.rsc +2 -2
  60. package/.next/server/app/messages.segments/_head.segment.rsc +1 -1
  61. package/.next/server/app/messages.segments/_index.segment.rsc +2 -2
  62. package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
  63. package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +1 -1
  64. package/.next/server/app/messages.segments/messages.segment.rsc +1 -1
  65. package/.next/server/app/node/page_client-reference-manifest.js +1 -1
  66. package/.next/server/app/node.html +2 -2
  67. package/.next/server/app/node.rsc +2 -2
  68. package/.next/server/app/node.segments/_full.segment.rsc +2 -2
  69. package/.next/server/app/node.segments/_head.segment.rsc +1 -1
  70. package/.next/server/app/node.segments/_index.segment.rsc +2 -2
  71. package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
  72. package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +1 -1
  73. package/.next/server/app/node.segments/node.segment.rsc +1 -1
  74. package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
  75. package/.next/server/app/nodes.html +2 -2
  76. package/.next/server/app/nodes.rsc +2 -2
  77. package/.next/server/app/nodes.segments/_full.segment.rsc +2 -2
  78. package/.next/server/app/nodes.segments/_head.segment.rsc +1 -1
  79. package/.next/server/app/nodes.segments/_index.segment.rsc +2 -2
  80. package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
  81. package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +1 -1
  82. package/.next/server/app/nodes.segments/nodes.segment.rsc +1 -1
  83. package/.next/server/app/page_client-reference-manifest.js +1 -1
  84. package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
  85. package/.next/server/app/server-logs.html +2 -2
  86. package/.next/server/app/server-logs.rsc +2 -2
  87. package/.next/server/app/server-logs.segments/_full.segment.rsc +2 -2
  88. package/.next/server/app/server-logs.segments/_head.segment.rsc +1 -1
  89. package/.next/server/app/server-logs.segments/_index.segment.rsc +2 -2
  90. package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
  91. package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +1 -1
  92. package/.next/server/app/server-logs.segments/server-logs.segment.rsc +1 -1
  93. package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
  94. package/.next/server/app/settings/networks.html +2 -2
  95. package/.next/server/app/settings/networks.rsc +2 -2
  96. package/.next/server/app/settings/networks.segments/_full.segment.rsc +2 -2
  97. package/.next/server/app/settings/networks.segments/_head.segment.rsc +1 -1
  98. package/.next/server/app/settings/networks.segments/_index.segment.rsc +2 -2
  99. package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
  100. package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +1 -1
  101. package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +1 -1
  102. package/.next/server/app/settings/networks.segments/settings.segment.rsc +1 -1
  103. package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  104. package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
  105. package/.next/server/app/settings/tokens.html +2 -2
  106. package/.next/server/app/settings/tokens.rsc +2 -2
  107. package/.next/server/app/settings/tokens.segments/_full.segment.rsc +2 -2
  108. package/.next/server/app/settings/tokens.segments/_head.segment.rsc +1 -1
  109. package/.next/server/app/settings/tokens.segments/_index.segment.rsc +2 -2
  110. package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
  111. package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +1 -1
  112. package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +1 -1
  113. package/.next/server/app/settings/tokens.segments/settings.segment.rsc +1 -1
  114. package/.next/server/app/settings.html +2 -2
  115. package/.next/server/app/settings.rsc +3 -3
  116. package/.next/server/app/settings.segments/_full.segment.rsc +3 -3
  117. package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  118. package/.next/server/app/settings.segments/_index.segment.rsc +2 -2
  119. package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  120. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +2 -2
  121. package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
  122. package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
  123. package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
  124. package/.next/server/app/tasks.html +2 -2
  125. package/.next/server/app/tasks.rsc +2 -2
  126. package/.next/server/app/tasks.segments/_full.segment.rsc +2 -2
  127. package/.next/server/app/tasks.segments/_head.segment.rsc +1 -1
  128. package/.next/server/app/tasks.segments/_index.segment.rsc +2 -2
  129. package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
  130. package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +1 -1
  131. package/.next/server/app/tasks.segments/tasks.segment.rsc +1 -1
  132. package/.next/server/chunks/ssr/_0nne7mz._.js +1 -1
  133. package/.next/server/chunks/ssr/_0nne7mz._.js.map +1 -1
  134. package/.next/server/chunks/ssr/app_0aum_g5._.js +1 -1
  135. package/.next/server/chunks/ssr/app_0aum_g5._.js.map +1 -1
  136. package/.next/server/chunks/ssr/app_0esuljp._.js +1 -1
  137. package/.next/server/chunks/ssr/app_0esuljp._.js.map +1 -1
  138. package/.next/server/middleware-build-manifest.js +3 -3
  139. package/.next/server/pages/404.html +2 -2
  140. package/.next/server/pages/500.html +1 -1
  141. package/.next/server/server-reference-manifest.js +1 -1
  142. package/.next/server/server-reference-manifest.json +1 -1
  143. package/.next/static/chunks/{0od70ylwpxjld.js → 04p678v0aui~f.js} +1 -1
  144. package/.next/static/chunks/07epshqd2k_l_.js +1 -0
  145. package/.next/static/chunks/09n9xs.6dvvo2.css +2 -0
  146. package/.next/static/chunks/{03tdotf7ifdxm.js → 0sxaea_g05hbz.js} +1 -1
  147. package/.next/trace +2 -2
  148. package/.next/trace-build +1 -1
  149. package/app/components/TopoGraph.tsx +139 -33
  150. package/app/components/types.ts +4 -0
  151. package/app/lib/vendorIdentity.ts +145 -0
  152. package/package.json +1 -1
  153. package/scripts/topo-layout-test.mjs +112 -0
  154. package/scripts/topo-vendor-test.mjs +96 -0
  155. package/.next/static/chunks/0bd~fi9sar8di.js +0 -1
  156. package/.next/static/chunks/0ux36eo4a-0ry.css +0 -2
  157. /package/.next/static/{cnPvCZlSAHV4OCtuXKMlY → q2pRPNeRoK1vOr1EX-qOG}/_buildManifest.js +0 -0
  158. /package/.next/static/{cnPvCZlSAHV4OCtuXKMlY → q2pRPNeRoK1vOr1EX-qOG}/_clientMiddlewareManifest.js +0 -0
  159. /package/.next/static/{cnPvCZlSAHV4OCtuXKMlY → q2pRPNeRoK1vOr1EX-qOG}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,65822,e=>{"use strict";var s=e.i(83599),a=e.i(58963);let t=async e=>{let s=await fetch(e);if(401===s.status)throw window.location.assign("/login"),Error("unauthorized");return s.json()},r={refreshInterval:5e3,dedupingInterval:3e3};function n(e,s){if(!s)return e;let a=e.includes("?")?"&":"?";return`${e}${a}network_id=${encodeURIComponent(s)}`}e.s(["useAnetConfig",0,function(){let{data:e}=(0,s.default)("/api/anet/config",t,{refreshInterval:3e4});return{config:e||null}},"useHealth",0,function(){let{data:e,error:a}=(0,s.default)("/api/hub/health",t,r);return{health:e||null,error:a}},"useLicense",0,function(){let{data:e,error:a}=(0,s.default)("/api/hub/license",t,{refreshInterval:6e4});return{license:e?.ok?e:null,error:a}},"useMessages",0,function(e=100){let{networkId:l}=(0,a.useNetworkId)(),{data:i,error:c,isLoading:d}=(0,s.default)(n(`/api/hub/messages?limit=${e}`,l),t,r);return{messages:i?.messages||[],error:c,isLoading:d}},"useSessions",0,function(){let{networkId:e}=(0,a.useNetworkId)(),{data:l,error:i,isLoading:c}=(0,s.default)(n("/api/hub/status",e),t,r);return{sessions:l?.sessions||[],hint:l?._hint,error:i,isLoading:c}},"useStats",0,function(){let{networkId:e}=(0,a.useNetworkId)(),{data:l,error:i}=(0,s.default)(n("/api/hub/stats",e),t,r);return{stats:l?.ok?l:null,error:i}},"useTasks",0,function(e){let{networkId:l}=(0,a.useNetworkId)(),i=new URLSearchParams({limit:"100",...e}).toString(),{data:c,error:d,isLoading:o}=(0,s.default)(n(`/api/hub/tasks?${i}`,l),t,r);return{tasks:c?.tasks||[],count:c?.count??0,source:c?.source,error:d,isLoading:o}}])},94867,e=>{"use strict";e.s(["DASHBOARD_VERSION",0,"0.4.6-preview.2"],94867)},32545,e=>{"use strict";var s=e.i(18050),a=e.i(71645),t=e.i(22016),r=e.i(65822),n=e.i(94867);e.s(["default",0,function(){let{config:e}=(0,r.useAnetConfig)(),{health:l}=(0,r.useHealth)(),{license:i}=(0,r.useLicense)(),[c,d]=(0,a.useState)(""),[o,x]=(0,a.useState)(""),[m,h]=(0,a.useState)(""),[g,u]=(0,a.useState)(""),[p,N]=(0,a.useState)(""),b="flex flex-col gap-1 sm:flex-row sm:items-start sm:justify-between",j="break-all sm:max-w-[320px] sm:text-right";return(0,s.jsxs)("div",{className:"min-h-screen bg-[#0a0a1a] text-gray-100 p-4 sm:p-6 font-mono",children:[(0,s.jsx)("h1",{className:"text-2xl font-bold text-white mb-3 lg:ml-0 ml-10",children:"Settings"}),(0,s.jsx)("nav",{className:"mb-8 flex flex-wrap gap-1 text-xs",children:[{href:"#connection",label:"Connection"},{href:"#account",label:"Account"},{href:"#resources",label:"Resources"}].map(e=>(0,s.jsx)("a",{href:e.href,className:"rounded-md px-2.5 py-1 text-gray-500 hover:text-cyan-300 hover:bg-cyan-500/10 transition-colors",children:e.label},e.href))}),(0,s.jsxs)("div",{className:"max-w-2xl space-y-10",children:[(0,s.jsxs)("div",{id:"connection",className:"space-y-4 scroll-mt-6",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,s.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Connection"}),(0,s.jsx)("div",{className:"flex-1 h-px bg-[#2a2a4a]"})]}),(0,s.jsxs)("section",{className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"CommHub Connection"}),(0,s.jsxs)("div",{className:"space-y-3 text-sm",children:[(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500 shrink-0",children:"Hub URL"}),(0,s.jsx)("span",{className:`text-cyan-300 ${j}`,children:e?.hub||"not configured"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Config Source"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:e?.source==="file"?"Local file (~/.anet/config.json)":e?.source==="runtime-env"?"Vercel env vars":"Missing"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Auth Token"}),(0,s.jsx)("span",{className:`${e?.tokenConfigured?"text-green-400":"text-red-400"} ${j}`,children:e?.tokenConfigured?`Configured (${e.tokenPreview})`:"Not configured"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Server Auth"}),(0,s.jsx)("span",{className:`${l?.auth==="enabled"?"text-green-400":"text-yellow-400"} sm:text-right`,children:l?.auth||"--"})]}),e?.error&&(0,s.jsx)("div",{className:"border-t border-[#2a2a4a] pt-3 text-xs text-gray-600",children:e.error})]})]}),(0,s.jsxs)("section",{className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Server Info"}),(0,s.jsxs)("div",{className:"space-y-3 text-sm",children:[(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Version"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:l?.version||"--"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Sessions"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:l?.sessions??"--"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsxs)("span",{className:"text-gray-500",children:["SSE streams ",(0,s.jsx)("span",{className:"text-gray-600",children:"· server"})]}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:l?.sse_connections??"--"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Uptime"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:l?.uptime?`${Math.floor(l.uptime/3600)}h ${Math.floor(l.uptime%3600/60)}m`:"--"})]})]})]}),(0,s.jsxs)("section",{className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Dashboard"}),(0,s.jsxs)("div",{className:"space-y-3 text-sm",children:[(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Version"}),(0,s.jsx)("span",{className:`text-gray-300 font-mono ${j}`,title:"From package.json @sleep2agi/agent-network-dashboard",children:n.DASHBOARD_VERSION})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Data Layer"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:"SWR (5s refresh, 3s dedup)"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Pages"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:"Overview, Tasks, Nodes, Messages, Networks, Audit, Server Logs, Admin, Settings"})]})]})]})]}),(0,s.jsxs)("div",{id:"account",className:"space-y-4 scroll-mt-6",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,s.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Account"}),(0,s.jsx)("div",{className:"flex-1 h-px bg-[#2a2a4a]"})]}),(0,s.jsxs)("section",{className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5",children:[(0,s.jsxs)("h2",{className:"text-sm font-semibold text-gray-300 mb-4 flex items-center gap-2",children:["License",i?.license&&(0,s.jsxs)("span",{className:`inline-flex items-center gap-1.5 text-[10px] font-medium px-2 py-0.5 rounded-full border ${"pro"===i.license.type?"text-green-300 bg-green-500/10 border-green-500/30":i.license.days_left<=7?"text-red-300 bg-red-500/10 border-red-500/30":"text-amber-300 bg-amber-500/10 border-amber-500/30"}`,children:[(0,s.jsx)("span",{"aria-hidden":!0,className:"w-1.5 h-1.5 rounded-full bg-current"}),i.license.type,i.license.days_left?` \xb7 ${i.license.days_left}d left`:""]})]}),i?.license?(0,s.jsxs)("div",{className:"space-y-3 text-sm",children:[i.license.days_left<=7&&(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-red-400 font-medium",children:"⚠ Expiring soon"}),(0,s.jsxs)("span",{className:"text-red-400",children:[i.license.days_left," days left"]})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Expires"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:i.license.expires_at})]}),i.limits&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Max Agents"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:i.limits.max_agents})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Max Networks"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:i.limits.max_networks})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Tasks/Day"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:i.limits.max_tasks_day})]})]}),(0,s.jsxs)("div",{className:"pt-3 border-t border-[#2a2a4a]",children:[(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)("input",{type:"text",value:c,onChange:e=>d(e.target.value),placeholder:"anet-XXXX-XXXX-XXXX-XXXX",className:"flex-1 bg-[#0a0a15] border border-[#2a2a4a] rounded px-3 py-2 text-xs text-white placeholder-gray-600 focus:outline-none"}),(0,s.jsx)("button",{onClick:async()=>{if(!c.trim())return;let e=await fetch("/api/hub/license",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:c})}),s=await e.json();x(s.ok?`Activated: ${s.type}`:`Failed: ${s.error}`),s.ok&&d(""),setTimeout(()=>x(""),5e3)},className:"px-3 py-2 bg-cyan-600 hover:bg-cyan-500 text-white text-xs rounded transition-colors",children:"Activate"})]}),o&&(0,s.jsx)("div",{className:`mt-2 text-xs ${o.startsWith("Failed")?"text-red-400":"text-green-400"}`,children:o})]})]}):(0,s.jsx)("div",{className:"text-xs text-gray-600",children:"License info not available"})]}),(0,s.jsxs)("section",{className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Change Password"}),(0,s.jsxs)("div",{className:"space-y-3",children:[(0,s.jsx)("input",{type:"password",value:m,onChange:e=>h(e.target.value),placeholder:"Current password",className:"w-full bg-[#0a0a15] border border-[#2a2a4a] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-cyan-500/50 focus:outline-none"}),(0,s.jsx)("input",{type:"password",value:g,onChange:e=>u(e.target.value),placeholder:"New password",className:"w-full bg-[#0a0a15] border border-[#2a2a4a] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-cyan-500/50 focus:outline-none"}),(0,s.jsx)("button",{onClick:async()=>{if(!m||!g)return;let e=sessionStorage.getItem("anet_v3_auth");if(!e)return void N("Not logged in with V3 auth");let{token:s}=JSON.parse(e),a=await fetch("/api/hub/auth",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"change_password",token:s,current_password:m,new_password:g})}),t=await a.json();if(N(t.ok?"Password changed":`Failed: ${t.error}`),t.ok){if(t.token){let s=JSON.parse(e);sessionStorage.setItem("anet_v3_auth",JSON.stringify({...s,token:t.token}))}h(""),u("")}setTimeout(()=>N(""),5e3)},disabled:!m||!g,className:"px-4 py-2 bg-cyan-600 hover:bg-cyan-500 disabled:bg-gray-800 disabled:text-gray-600 text-white text-sm rounded-lg transition-colors",children:"Change Password"})]}),p&&(0,s.jsx)("div",{className:`mt-2 text-xs ${p.startsWith("Failed")?"text-red-400":"text-green-400"}`,children:p})]}),(0,s.jsxs)("section",{className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Sign out"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mb-3",children:"Signing out clears your dashboard session cookie. You'll return to the login page."}),(0,s.jsx)("button",{onClick:async()=>{await fetch("/api/auth/logout",{method:"POST"}).catch(()=>{}),window.location.assign("/login")},className:"px-4 py-2 bg-transparent hover:bg-[#1a1a2a] text-gray-300 text-sm rounded-lg border border-[#2a2a4a] hover:border-[#3a3a5a] transition-colors",children:"Sign out"})]})]}),(0,s.jsxs)("div",{id:"resources",className:"space-y-4 scroll-mt-6",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,s.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Resources"}),(0,s.jsx)("div",{className:"flex-1 h-px bg-[#2a2a4a]"})]}),(0,s.jsxs)("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4",children:[(0,s.jsxs)(t.default,{href:"/settings/tokens",className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5 hover:border-cyan-500/30 transition-colors",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300",children:"API Tokens"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-2",children:"Create and manage tokens for CLI access."}),(0,s.jsx)("span",{className:"text-xs text-cyan-400 mt-3 inline-block",children:"Manage →"})]}),(0,s.jsxs)(t.default,{href:"/settings/networks",className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5 hover:border-cyan-500/30 transition-colors",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300",children:"Networks"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-2",children:"Create, manage, and delete agent networks."}),(0,s.jsx)("span",{className:"text-xs text-cyan-400 mt-3 inline-block",children:"Manage →"})]})]})]})]})]})}])}]);
1
+ (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,65822,e=>{"use strict";var s=e.i(83599),a=e.i(58963);let t=async e=>{let s=await fetch(e);if(401===s.status)throw window.location.assign("/login"),Error("unauthorized");return s.json()},r={refreshInterval:5e3,dedupingInterval:3e3};function n(e,s){if(!s)return e;let a=e.includes("?")?"&":"?";return`${e}${a}network_id=${encodeURIComponent(s)}`}e.s(["useAnetConfig",0,function(){let{data:e}=(0,s.default)("/api/anet/config",t,{refreshInterval:3e4});return{config:e||null}},"useHealth",0,function(){let{data:e,error:a}=(0,s.default)("/api/hub/health",t,r);return{health:e||null,error:a}},"useLicense",0,function(){let{data:e,error:a}=(0,s.default)("/api/hub/license",t,{refreshInterval:6e4});return{license:e?.ok?e:null,error:a}},"useMessages",0,function(e=100){let{networkId:l}=(0,a.useNetworkId)(),{data:i,error:c,isLoading:d}=(0,s.default)(n(`/api/hub/messages?limit=${e}`,l),t,r);return{messages:i?.messages||[],error:c,isLoading:d}},"useSessions",0,function(){let{networkId:e}=(0,a.useNetworkId)(),{data:l,error:i,isLoading:c}=(0,s.default)(n("/api/hub/status",e),t,r);return{sessions:l?.sessions||[],hint:l?._hint,error:i,isLoading:c}},"useStats",0,function(){let{networkId:e}=(0,a.useNetworkId)(),{data:l,error:i}=(0,s.default)(n("/api/hub/stats",e),t,r);return{stats:l?.ok?l:null,error:i}},"useTasks",0,function(e){let{networkId:l}=(0,a.useNetworkId)(),i=new URLSearchParams({limit:"100",...e}).toString(),{data:c,error:d,isLoading:o}=(0,s.default)(n(`/api/hub/tasks?${i}`,l),t,r);return{tasks:c?.tasks||[],count:c?.count??0,source:c?.source,error:d,isLoading:o}}])},94867,e=>{"use strict";e.s(["DASHBOARD_VERSION",0,"0.4.6-preview.4"],94867)},32545,e=>{"use strict";var s=e.i(18050),a=e.i(71645),t=e.i(22016),r=e.i(65822),n=e.i(94867);e.s(["default",0,function(){let{config:e}=(0,r.useAnetConfig)(),{health:l}=(0,r.useHealth)(),{license:i}=(0,r.useLicense)(),[c,d]=(0,a.useState)(""),[o,x]=(0,a.useState)(""),[m,h]=(0,a.useState)(""),[g,u]=(0,a.useState)(""),[p,N]=(0,a.useState)(""),b="flex flex-col gap-1 sm:flex-row sm:items-start sm:justify-between",j="break-all sm:max-w-[320px] sm:text-right";return(0,s.jsxs)("div",{className:"min-h-screen bg-[#0a0a1a] text-gray-100 p-4 sm:p-6 font-mono",children:[(0,s.jsx)("h1",{className:"text-2xl font-bold text-white mb-3 lg:ml-0 ml-10",children:"Settings"}),(0,s.jsx)("nav",{className:"mb-8 flex flex-wrap gap-1 text-xs",children:[{href:"#connection",label:"Connection"},{href:"#account",label:"Account"},{href:"#resources",label:"Resources"}].map(e=>(0,s.jsx)("a",{href:e.href,className:"rounded-md px-2.5 py-1 text-gray-500 hover:text-cyan-300 hover:bg-cyan-500/10 transition-colors",children:e.label},e.href))}),(0,s.jsxs)("div",{className:"max-w-2xl space-y-10",children:[(0,s.jsxs)("div",{id:"connection",className:"space-y-4 scroll-mt-6",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,s.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Connection"}),(0,s.jsx)("div",{className:"flex-1 h-px bg-[#2a2a4a]"})]}),(0,s.jsxs)("section",{className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"CommHub Connection"}),(0,s.jsxs)("div",{className:"space-y-3 text-sm",children:[(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500 shrink-0",children:"Hub URL"}),(0,s.jsx)("span",{className:`text-cyan-300 ${j}`,children:e?.hub||"not configured"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Config Source"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:e?.source==="file"?"Local file (~/.anet/config.json)":e?.source==="runtime-env"?"Vercel env vars":"Missing"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Auth Token"}),(0,s.jsx)("span",{className:`${e?.tokenConfigured?"text-green-400":"text-red-400"} ${j}`,children:e?.tokenConfigured?`Configured (${e.tokenPreview})`:"Not configured"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Server Auth"}),(0,s.jsx)("span",{className:`${l?.auth==="enabled"?"text-green-400":"text-yellow-400"} sm:text-right`,children:l?.auth||"--"})]}),e?.error&&(0,s.jsx)("div",{className:"border-t border-[#2a2a4a] pt-3 text-xs text-gray-600",children:e.error})]})]}),(0,s.jsxs)("section",{className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Server Info"}),(0,s.jsxs)("div",{className:"space-y-3 text-sm",children:[(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Version"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:l?.version||"--"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Sessions"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:l?.sessions??"--"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsxs)("span",{className:"text-gray-500",children:["SSE streams ",(0,s.jsx)("span",{className:"text-gray-600",children:"· server"})]}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:l?.sse_connections??"--"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Uptime"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:l?.uptime?`${Math.floor(l.uptime/3600)}h ${Math.floor(l.uptime%3600/60)}m`:"--"})]})]})]}),(0,s.jsxs)("section",{className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Dashboard"}),(0,s.jsxs)("div",{className:"space-y-3 text-sm",children:[(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Version"}),(0,s.jsx)("span",{className:`text-gray-300 font-mono ${j}`,title:"From package.json @sleep2agi/agent-network-dashboard",children:n.DASHBOARD_VERSION})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Data Layer"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:"SWR (5s refresh, 3s dedup)"})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Pages"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:"Overview, Tasks, Nodes, Messages, Networks, Audit, Server Logs, Admin, Settings"})]})]})]})]}),(0,s.jsxs)("div",{id:"account",className:"space-y-4 scroll-mt-6",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,s.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Account"}),(0,s.jsx)("div",{className:"flex-1 h-px bg-[#2a2a4a]"})]}),(0,s.jsxs)("section",{className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5",children:[(0,s.jsxs)("h2",{className:"text-sm font-semibold text-gray-300 mb-4 flex items-center gap-2",children:["License",i?.license&&(0,s.jsxs)("span",{className:`inline-flex items-center gap-1.5 text-[10px] font-medium px-2 py-0.5 rounded-full border ${"pro"===i.license.type?"text-green-300 bg-green-500/10 border-green-500/30":i.license.days_left<=7?"text-red-300 bg-red-500/10 border-red-500/30":"text-amber-300 bg-amber-500/10 border-amber-500/30"}`,children:[(0,s.jsx)("span",{"aria-hidden":!0,className:"w-1.5 h-1.5 rounded-full bg-current"}),i.license.type,i.license.days_left?` \xb7 ${i.license.days_left}d left`:""]})]}),i?.license?(0,s.jsxs)("div",{className:"space-y-3 text-sm",children:[i.license.days_left<=7&&(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-red-400 font-medium",children:"⚠ Expiring soon"}),(0,s.jsxs)("span",{className:"text-red-400",children:[i.license.days_left," days left"]})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Expires"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:i.license.expires_at})]}),i.limits&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Max Agents"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:i.limits.max_agents})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Max Networks"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:i.limits.max_networks})]}),(0,s.jsxs)("div",{className:b,children:[(0,s.jsx)("span",{className:"text-gray-500",children:"Tasks/Day"}),(0,s.jsx)("span",{className:`text-gray-300 ${j}`,children:i.limits.max_tasks_day})]})]}),(0,s.jsxs)("div",{className:"pt-3 border-t border-[#2a2a4a]",children:[(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)("input",{type:"text",value:c,onChange:e=>d(e.target.value),placeholder:"anet-XXXX-XXXX-XXXX-XXXX",className:"flex-1 bg-[#0a0a15] border border-[#2a2a4a] rounded px-3 py-2 text-xs text-white placeholder-gray-600 focus:outline-none"}),(0,s.jsx)("button",{onClick:async()=>{if(!c.trim())return;let e=await fetch("/api/hub/license",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:c})}),s=await e.json();x(s.ok?`Activated: ${s.type}`:`Failed: ${s.error}`),s.ok&&d(""),setTimeout(()=>x(""),5e3)},className:"px-3 py-2 bg-cyan-600 hover:bg-cyan-500 text-white text-xs rounded transition-colors",children:"Activate"})]}),o&&(0,s.jsx)("div",{className:`mt-2 text-xs ${o.startsWith("Failed")?"text-red-400":"text-green-400"}`,children:o})]})]}):(0,s.jsx)("div",{className:"text-xs text-gray-600",children:"License info not available"})]}),(0,s.jsxs)("section",{className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Change Password"}),(0,s.jsxs)("div",{className:"space-y-3",children:[(0,s.jsx)("input",{type:"password",value:m,onChange:e=>h(e.target.value),placeholder:"Current password",className:"w-full bg-[#0a0a15] border border-[#2a2a4a] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-cyan-500/50 focus:outline-none"}),(0,s.jsx)("input",{type:"password",value:g,onChange:e=>u(e.target.value),placeholder:"New password",className:"w-full bg-[#0a0a15] border border-[#2a2a4a] rounded-lg px-3 py-2 text-sm text-white placeholder-gray-600 focus:border-cyan-500/50 focus:outline-none"}),(0,s.jsx)("button",{onClick:async()=>{if(!m||!g)return;let e=sessionStorage.getItem("anet_v3_auth");if(!e)return void N("Not logged in with V3 auth");let{token:s}=JSON.parse(e),a=await fetch("/api/hub/auth",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"change_password",token:s,current_password:m,new_password:g})}),t=await a.json();if(N(t.ok?"Password changed":`Failed: ${t.error}`),t.ok){if(t.token){let s=JSON.parse(e);sessionStorage.setItem("anet_v3_auth",JSON.stringify({...s,token:t.token}))}h(""),u("")}setTimeout(()=>N(""),5e3)},disabled:!m||!g,className:"px-4 py-2 bg-cyan-600 hover:bg-cyan-500 disabled:bg-gray-800 disabled:text-gray-600 text-white text-sm rounded-lg transition-colors",children:"Change Password"})]}),p&&(0,s.jsx)("div",{className:`mt-2 text-xs ${p.startsWith("Failed")?"text-red-400":"text-green-400"}`,children:p})]}),(0,s.jsxs)("section",{className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Sign out"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mb-3",children:"Signing out clears your dashboard session cookie. You'll return to the login page."}),(0,s.jsx)("button",{onClick:async()=>{await fetch("/api/auth/logout",{method:"POST"}).catch(()=>{}),window.location.assign("/login")},className:"px-4 py-2 bg-transparent hover:bg-[#1a1a2a] text-gray-300 text-sm rounded-lg border border-[#2a2a4a] hover:border-[#3a3a5a] transition-colors",children:"Sign out"})]})]}),(0,s.jsxs)("div",{id:"resources",className:"space-y-4 scroll-mt-6",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,s.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Resources"}),(0,s.jsx)("div",{className:"flex-1 h-px bg-[#2a2a4a]"})]}),(0,s.jsxs)("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4",children:[(0,s.jsxs)(t.default,{href:"/settings/tokens",className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5 hover:border-cyan-500/30 transition-colors",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300",children:"API Tokens"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-2",children:"Create and manage tokens for CLI access."}),(0,s.jsx)("span",{className:"text-xs text-cyan-400 mt-3 inline-block",children:"Manage →"})]}),(0,s.jsxs)(t.default,{href:"/settings/networks",className:"bg-[#111128] border border-[#2a2a4a] rounded-xl p-5 hover:border-cyan-500/30 transition-colors",children:[(0,s.jsx)("h2",{className:"text-sm font-semibold text-gray-300",children:"Networks"}),(0,s.jsx)("p",{className:"text-xs text-gray-500 mt-2",children:"Create, manage, and delete agent networks."}),(0,s.jsx)("span",{className:"text-xs text-cyan-400 mt-3 inline-block",children:"Manage →"})]})]})]})]})]})}])}]);
package/.next/trace CHANGED
@@ -1,2 +1,2 @@
1
- [{"name":"generate-buildid","duration":313,"timestamp":412609065411,"id":4,"parentId":1,"tags":{},"startTime":1778784094890,"traceId":"7e7f11a41fcc6acd"},{"name":"load-custom-routes","duration":545,"timestamp":412609065874,"id":5,"parentId":1,"tags":{},"startTime":1778784094891,"traceId":"7e7f11a41fcc6acd"},{"name":"create-dist-dir","duration":298,"timestamp":412609066469,"id":6,"parentId":1,"tags":{},"startTime":1778784094891,"traceId":"7e7f11a41fcc6acd"},{"name":"clean","duration":480,"timestamp":412609067484,"id":7,"parentId":1,"tags":{},"startTime":1778784094892,"traceId":"7e7f11a41fcc6acd"},{"name":"discover-routes","duration":9363,"timestamp":412609153234,"id":8,"parentId":1,"tags":{},"startTime":1778784094978,"traceId":"7e7f11a41fcc6acd"},{"name":"create-root-mapping","duration":109,"timestamp":412609162664,"id":9,"parentId":1,"tags":{},"startTime":1778784094987,"traceId":"7e7f11a41fcc6acd"},{"name":"generate-route-types","duration":34219,"timestamp":412609165287,"id":10,"parentId":1,"tags":{},"startTime":1778784094990,"traceId":"7e7f11a41fcc6acd"},{"name":"public-dir-conflict-check","duration":122,"timestamp":412609199716,"id":11,"parentId":1,"tags":{},"startTime":1778784095024,"traceId":"7e7f11a41fcc6acd"},{"name":"generate-routes-manifest","duration":5180,"timestamp":412609199981,"id":12,"parentId":1,"tags":{},"startTime":1778784095025,"traceId":"7e7f11a41fcc6acd"},{"name":"run-turbopack","duration":9499844,"timestamp":412609211735,"id":14,"parentId":1,"tags":{},"startTime":1778784095036,"traceId":"7e7f11a41fcc6acd"},{"name":"turbopack-build-events","duration":134,"timestamp":412609519993,"id":15,"parentId":1,"tags":{},"startTime":1778784095345,"traceId":"7e7f11a41fcc6acd"},{"name":"run-typescript","duration":10631519,"timestamp":412618744595,"id":16,"parentId":1,"tags":{},"startTime":1778784104569,"traceId":"7e7f11a41fcc6acd"},{"name":"generate-required-server-files","duration":2937,"timestamp":412629377053,"id":18,"parentId":1,"tags":{},"startTime":1778784115202,"traceId":"7e7f11a41fcc6acd"},{"name":"check-static-error-page","duration":16209,"timestamp":412629454093,"id":20,"parentId":19,"tags":{},"startTime":1778784115279,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":380158,"timestamp":412629473049,"id":62,"parentId":22,"tags":{},"startTime":1778784115298,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":396734,"timestamp":412629456599,"id":22,"parentId":19,"tags":{"page":"/_global-error"},"startTime":1778784115281,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":493652,"timestamp":412629472552,"id":61,"parentId":21,"tags":{},"startTime":1778784115297,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":512022,"timestamp":412629455346,"id":21,"parentId":19,"tags":{"page":"/_not-found"},"startTime":1778784115280,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":504066,"timestamp":412629473319,"id":64,"parentId":26,"tags":{},"startTime":1778784115298,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":516080,"timestamp":412629461379,"id":26,"parentId":19,"tags":{"page":"/api/auth/logout"},"startTime":1778784115286,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":539419,"timestamp":412629473163,"id":63,"parentId":25,"tags":{},"startTime":1778784115298,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":553038,"timestamp":412629459608,"id":25,"parentId":19,"tags":{"page":"/api/auth/login"},"startTime":1778784115284,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":544740,"timestamp":412629473436,"id":67,"parentId":29,"tags":{},"startTime":1778784115298,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":556527,"timestamp":412629461717,"id":29,"parentId":19,"tags":{"page":"/api/hub/auth"},"startTime":1778784115286,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":545017,"timestamp":412629473398,"id":66,"parentId":28,"tags":{},"startTime":1778784115298,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":556830,"timestamp":412629461623,"id":28,"parentId":19,"tags":{"page":"/api/hub/audit-log"},"startTime":1778784115286,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":552688,"timestamp":412629473505,"id":69,"parentId":32,"tags":{},"startTime":1778784115298,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":563674,"timestamp":412629462585,"id":32,"parentId":19,"tags":{"page":"/api/hub/health"},"startTime":1778784115287,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":568945,"timestamp":412629473606,"id":70,"parentId":33,"tags":{},"startTime":1778784115298,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":579931,"timestamp":412629462683,"id":33,"parentId":19,"tags":{"page":"/api/hub/inbox"},"startTime":1778784115287,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":580788,"timestamp":412629473655,"id":71,"parentId":34,"tags":{},"startTime":1778784115298,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":591744,"timestamp":412629462772,"id":34,"parentId":19,"tags":{"page":"/api/hub/license"},"startTime":1778784115287,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":581175,"timestamp":412629473471,"id":68,"parentId":30,"tags":{},"startTime":1778784115298,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":592465,"timestamp":412629462206,"id":30,"parentId":19,"tags":{"page":"/api/hub/broadcast"},"startTime":1778784115287,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":593549,"timestamp":412629473673,"id":72,"parentId":35,"tags":{},"startTime":1778784115298,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":604421,"timestamp":412629462862,"id":35,"parentId":19,"tags":{"page":"/api/hub/messages"},"startTime":1778784115288,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":593676,"timestamp":412629473731,"id":73,"parentId":36,"tags":{},"startTime":1778784115298,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":604143,"timestamp":412629463291,"id":36,"parentId":19,"tags":{"page":"/api/hub/networks"},"startTime":1778784115288,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":598304,"timestamp":412629473759,"id":74,"parentId":37,"tags":{},"startTime":1778784115298,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":608708,"timestamp":412629463435,"id":37,"parentId":19,"tags":{"page":"/api/hub/nodes"},"startTime":1778784115288,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":598986,"timestamp":412629473361,"id":65,"parentId":27,"tags":{},"startTime":1778784115298,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":610854,"timestamp":412629461524,"id":27,"parentId":19,"tags":{"page":"/api/auth/v3"},"startTime":1778784115286,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":599520,"timestamp":412629473771,"id":75,"parentId":38,"tags":{},"startTime":1778784115298,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":609801,"timestamp":412629463539,"id":38,"parentId":19,"tags":{"page":"/api/hub/register"},"startTime":1778784115288,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":601267,"timestamp":412629473781,"id":76,"parentId":39,"tags":{},"startTime":1778784115298,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":611482,"timestamp":412629463610,"id":39,"parentId":19,"tags":{"page":"/api/hub/send"},"startTime":1778784115288,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":605464,"timestamp":412629473790,"id":77,"parentId":40,"tags":{},"startTime":1778784115298,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":615636,"timestamp":412629463683,"id":40,"parentId":19,"tags":{"page":"/api/hub/server-logs"},"startTime":1778784115288,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":605894,"timestamp":412629473806,"id":79,"parentId":42,"tags":{},"startTime":1778784115298,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":615901,"timestamp":412629463831,"id":42,"parentId":19,"tags":{"page":"/api/hub/stats"},"startTime":1778784115289,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":607821,"timestamp":412629473798,"id":78,"parentId":41,"tags":{},"startTime":1778784115298,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":617904,"timestamp":412629463757,"id":41,"parentId":19,"tags":{"page":"/api/hub/session"},"startTime":1778784115288,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":612364,"timestamp":412629473841,"id":82,"parentId":45,"tags":{},"startTime":1778784115299,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":621315,"timestamp":412629464948,"id":45,"parentId":19,"tags":{"page":"/api/hub/tasks"},"startTime":1778784115290,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":614149,"timestamp":412629473831,"id":81,"parentId":44,"tags":{},"startTime":1778784115299,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":624089,"timestamp":412629463989,"id":44,"parentId":19,"tags":{"page":"/api/hub/task-events"},"startTime":1778784115289,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":614426,"timestamp":412629473815,"id":80,"parentId":43,"tags":{},"startTime":1778784115299,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":624360,"timestamp":412629463908,"id":43,"parentId":19,"tags":{"page":"/api/hub/status"},"startTime":1778784115289,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":619359,"timestamp":412629473847,"id":83,"parentId":46,"tags":{},"startTime":1778784115299,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":628127,"timestamp":412629465151,"id":46,"parentId":19,"tags":{"page":"/api/hub/tmux"},"startTime":1778784115290,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":621305,"timestamp":412629473859,"id":85,"parentId":48,"tags":{},"startTime":1778784115299,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":629899,"timestamp":412629465330,"id":48,"parentId":19,"tags":{"page":"/favicon.ico"},"startTime":1778784115290,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":621864,"timestamp":412629473853,"id":84,"parentId":47,"tags":{},"startTime":1778784115299,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":630509,"timestamp":412629465254,"id":47,"parentId":19,"tags":{"page":"/api/hub/tokens"},"startTime":1778784115290,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":620800,"timestamp":412629478246,"id":86,"parentId":24,"tags":{},"startTime":1778784115303,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":642134,"timestamp":412629456985,"id":24,"parentId":19,"tags":{"page":"/api/anet/config"},"startTime":1778784115282,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":624996,"timestamp":412629478944,"id":87,"parentId":31,"tags":{},"startTime":1778784115304,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":641708,"timestamp":412629462329,"id":31,"parentId":19,"tags":{"page":"/api/hub/events"},"startTime":1778784115287,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":588094,"timestamp":412629522840,"id":90,"parentId":50,"tags":{},"startTime":1778784115348,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":645145,"timestamp":412629465850,"id":50,"parentId":19,"tags":{"page":"/logs"},"startTime":1778784115291,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":594974,"timestamp":412629522851,"id":91,"parentId":51,"tags":{},"startTime":1778784115348,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":651899,"timestamp":412629465990,"id":51,"parentId":19,"tags":{"page":"/messages"},"startTime":1778784115291,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":605266,"timestamp":412629522859,"id":92,"parentId":52,"tags":{},"startTime":1778784115348,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":661975,"timestamp":412629466226,"id":52,"parentId":19,"tags":{"page":"/node"},"startTime":1778784115291,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":608832,"timestamp":412629522870,"id":93,"parentId":53,"tags":{},"startTime":1778784115348,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":665334,"timestamp":412629466430,"id":53,"parentId":19,"tags":{"page":"/nodes"},"startTime":1778784115291,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":615708,"timestamp":412629522880,"id":94,"parentId":55,"tags":{},"startTime":1778784115348,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":671412,"timestamp":412629467240,"id":55,"parentId":19,"tags":{"page":"/server-logs"},"startTime":1778784115292,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":622059,"timestamp":412629522887,"id":95,"parentId":56,"tags":{},"startTime":1778784115348,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":677612,"timestamp":412629467436,"id":56,"parentId":19,"tags":{"page":"/settings/networks"},"startTime":1778784115292,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":624377,"timestamp":412629522827,"id":89,"parentId":49,"tags":{},"startTime":1778784115348,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":681546,"timestamp":412629465706,"id":49,"parentId":19,"tags":{"page":"/login"},"startTime":1778784115290,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":629252,"timestamp":412629522898,"id":96,"parentId":58,"tags":{},"startTime":1778784115348,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":682373,"timestamp":412629469836,"id":58,"parentId":19,"tags":{"page":"/settings/tokens"},"startTime":1778784115295,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":634801,"timestamp":412629522909,"id":97,"parentId":59,"tags":{},"startTime":1778784115348,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":687821,"timestamp":412629469952,"id":59,"parentId":19,"tags":{"page":"/tasks/[id]"},"startTime":1778784115295,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":639284,"timestamp":412629522786,"id":88,"parentId":23,"tags":{},"startTime":1778784115347,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":705331,"timestamp":412629456809,"id":23,"parentId":19,"tags":{"page":"/admin"},"startTime":1778784115282,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":640611,"timestamp":412629522932,"id":99,"parentId":54,"tags":{},"startTime":1778784115348,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":696930,"timestamp":412629466660,"id":54,"parentId":19,"tags":{"page":"/"},"startTime":1778784115291,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":645584,"timestamp":412629522918,"id":98,"parentId":60,"tags":{},"startTime":1778784115348,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":698479,"timestamp":412629470079,"id":60,"parentId":19,"tags":{"page":"/tasks"},"startTime":1778784115295,"traceId":"7e7f11a41fcc6acd"},{"name":"is-page-static","duration":645709,"timestamp":412629522943,"id":100,"parentId":57,"tags":{},"startTime":1778784115348,"traceId":"7e7f11a41fcc6acd"},{"name":"check-page","duration":699356,"timestamp":412629469315,"id":57,"parentId":19,"tags":{"page":"/settings"},"startTime":1778784115294,"traceId":"7e7f11a41fcc6acd"},{"name":"static-check","duration":715585,"timestamp":412629453127,"id":19,"parentId":1,"tags":{},"startTime":1778784115278,"traceId":"7e7f11a41fcc6acd"},{"name":"write-routes-manifest","duration":473,"timestamp":412630177244,"id":102,"parentId":1,"tags":{},"startTime":1778784116002,"traceId":"7e7f11a41fcc6acd"},{"name":"load-dotenv","duration":60,"timestamp":412630190337,"id":105,"parentId":104,"tags":{},"startTime":1778784116015,"traceId":"7e7f11a41fcc6acd"},{"name":"run-export-path-map","duration":731,"timestamp":412630193718,"id":106,"parentId":104,"tags":{},"startTime":1778784116018,"traceId":"7e7f11a41fcc6acd"},{"name":"next-export","duration":629207,"timestamp":412630188996,"id":104,"parentId":1,"tags":{},"startTime":1778784116014,"traceId":"7e7f11a41fcc6acd"},{"name":"move-exported-app-not-found-","duration":981,"timestamp":412630822051,"id":107,"parentId":103,"tags":{},"startTime":1778784116647,"traceId":"7e7f11a41fcc6acd"},{"name":"move-exported-app-global-error-","duration":466,"timestamp":412630823163,"id":108,"parentId":103,"tags":{},"startTime":1778784116648,"traceId":"7e7f11a41fcc6acd"}]
2
- [{"name":"static-generation","duration":645196,"timestamp":412630183144,"id":103,"parentId":1,"tags":{},"startTime":1778784116008,"traceId":"7e7f11a41fcc6acd"},{"name":"write-routes-manifest","duration":507,"timestamp":412630828573,"id":109,"parentId":1,"tags":{},"startTime":1778784116653,"traceId":"7e7f11a41fcc6acd"},{"name":"print-tree-view","duration":3928,"timestamp":412630836900,"id":110,"parentId":1,"tags":{},"startTime":1778784116662,"traceId":"7e7f11a41fcc6acd"},{"name":"write-route-bundle-stats","duration":20805,"timestamp":412630840874,"id":111,"parentId":1,"tags":{},"startTime":1778784116666,"traceId":"7e7f11a41fcc6acd"},{"name":"telemetry-flush","duration":280535,"timestamp":412630861734,"id":112,"parentId":1,"tags":{},"startTime":1778784116686,"traceId":"7e7f11a41fcc6acd"},{"name":"next-build","duration":22128906,"timestamp":412609013410,"id":1,"tags":{"buildMode":"default","version":"16.2.3","bundler":"turbopack","has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1778784094838,"traceId":"7e7f11a41fcc6acd"}]
1
+ [{"name":"generate-buildid","duration":292,"timestamp":416861402401,"id":4,"parentId":1,"tags":{},"startTime":1778788347227,"traceId":"a47bdb9bd1bc6ec6"},{"name":"load-custom-routes","duration":524,"timestamp":416861402843,"id":5,"parentId":1,"tags":{},"startTime":1778788347228,"traceId":"a47bdb9bd1bc6ec6"},{"name":"create-dist-dir","duration":319,"timestamp":416861403411,"id":6,"parentId":1,"tags":{},"startTime":1778788347228,"traceId":"a47bdb9bd1bc6ec6"},{"name":"clean","duration":504,"timestamp":416861404434,"id":7,"parentId":1,"tags":{},"startTime":1778788347229,"traceId":"a47bdb9bd1bc6ec6"},{"name":"discover-routes","duration":21358,"timestamp":416861493033,"id":8,"parentId":1,"tags":{},"startTime":1778788347318,"traceId":"a47bdb9bd1bc6ec6"},{"name":"create-root-mapping","duration":128,"timestamp":416861514457,"id":9,"parentId":1,"tags":{},"startTime":1778788347339,"traceId":"a47bdb9bd1bc6ec6"},{"name":"generate-route-types","duration":22648,"timestamp":416861516998,"id":10,"parentId":1,"tags":{},"startTime":1778788347342,"traceId":"a47bdb9bd1bc6ec6"},{"name":"public-dir-conflict-check","duration":112,"timestamp":416861539835,"id":11,"parentId":1,"tags":{},"startTime":1778788347365,"traceId":"a47bdb9bd1bc6ec6"},{"name":"generate-routes-manifest","duration":4923,"timestamp":416861540120,"id":12,"parentId":1,"tags":{},"startTime":1778788347365,"traceId":"a47bdb9bd1bc6ec6"},{"name":"run-turbopack","duration":9469000,"timestamp":416861550985,"id":14,"parentId":1,"tags":{},"startTime":1778788347376,"traceId":"a47bdb9bd1bc6ec6"},{"name":"turbopack-build-events","duration":93,"timestamp":416861910104,"id":15,"parentId":1,"tags":{},"startTime":1778788347735,"traceId":"a47bdb9bd1bc6ec6"},{"name":"run-typescript","duration":8837699,"timestamp":416871033411,"id":16,"parentId":1,"tags":{},"startTime":1778788356858,"traceId":"a47bdb9bd1bc6ec6"},{"name":"generate-required-server-files","duration":2498,"timestamp":416879872058,"id":18,"parentId":1,"tags":{},"startTime":1778788365697,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-static-error-page","duration":16241,"timestamp":416879947238,"id":20,"parentId":19,"tags":{},"startTime":1778788365772,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":341637,"timestamp":416879966380,"id":62,"parentId":22,"tags":{},"startTime":1778788365791,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":358590,"timestamp":416879949565,"id":22,"parentId":19,"tags":{"page":"/_global-error"},"startTime":1778788365774,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":418199,"timestamp":416879966464,"id":63,"parentId":25,"tags":{},"startTime":1778788365791,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":430819,"timestamp":416879953919,"id":25,"parentId":19,"tags":{"page":"/api/auth/login"},"startTime":1778788365779,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":424674,"timestamp":416879966644,"id":65,"parentId":27,"tags":{},"startTime":1778788365791,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":437182,"timestamp":416879954196,"id":27,"parentId":19,"tags":{"page":"/api/auth/v3"},"startTime":1778788365779,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":452108,"timestamp":416879966679,"id":66,"parentId":28,"tags":{},"startTime":1778788365791,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":464550,"timestamp":416879954298,"id":28,"parentId":19,"tags":{"page":"/api/hub/audit-log"},"startTime":1778788365779,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":463803,"timestamp":416879966715,"id":67,"parentId":29,"tags":{},"startTime":1778788365791,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":476204,"timestamp":416879954386,"id":29,"parentId":19,"tags":{"page":"/api/hub/auth"},"startTime":1778788365779,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":464130,"timestamp":416879966604,"id":64,"parentId":26,"tags":{},"startTime":1778788365791,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":476661,"timestamp":416879954099,"id":26,"parentId":19,"tags":{"page":"/api/auth/logout"},"startTime":1778788365779,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":468504,"timestamp":416879966749,"id":68,"parentId":30,"tags":{},"startTime":1778788365791,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":480729,"timestamp":416879954594,"id":30,"parentId":19,"tags":{"page":"/api/hub/broadcast"},"startTime":1778788365779,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":468712,"timestamp":416879966787,"id":69,"parentId":32,"tags":{},"startTime":1778788365791,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":480603,"timestamp":416879954919,"id":32,"parentId":19,"tags":{"page":"/api/hub/health"},"startTime":1778788365780,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":471044,"timestamp":416879966890,"id":70,"parentId":33,"tags":{},"startTime":1778788365792,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":482951,"timestamp":416879955031,"id":33,"parentId":19,"tags":{"page":"/api/hub/inbox"},"startTime":1778788365780,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":473264,"timestamp":416879966936,"id":71,"parentId":34,"tags":{},"startTime":1778788365792,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":485133,"timestamp":416879955117,"id":34,"parentId":19,"tags":{"page":"/api/hub/license"},"startTime":1778788365780,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":476391,"timestamp":416879966021,"id":61,"parentId":21,"tags":{},"startTime":1778788365791,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":494145,"timestamp":416879948309,"id":21,"parentId":19,"tags":{"page":"/_not-found"},"startTime":1778788365773,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":475710,"timestamp":416879966953,"id":72,"parentId":35,"tags":{},"startTime":1778788365792,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":487493,"timestamp":416879955196,"id":35,"parentId":19,"tags":{"page":"/api/hub/messages"},"startTime":1778788365780,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":477778,"timestamp":416879967025,"id":73,"parentId":36,"tags":{},"startTime":1778788365792,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":489294,"timestamp":416879955554,"id":36,"parentId":19,"tags":{"page":"/api/hub/networks"},"startTime":1778788365780,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":479101,"timestamp":416879967064,"id":75,"parentId":38,"tags":{},"startTime":1778788365792,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":490430,"timestamp":416879955772,"id":38,"parentId":19,"tags":{"page":"/api/hub/register"},"startTime":1778788365780,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":481210,"timestamp":416879967070,"id":76,"parentId":39,"tags":{},"startTime":1778788365792,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":492490,"timestamp":416879955830,"id":39,"parentId":19,"tags":{"page":"/api/hub/send"},"startTime":1778788365781,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":483055,"timestamp":416879967076,"id":77,"parentId":40,"tags":{},"startTime":1778788365792,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":494275,"timestamp":416879955892,"id":40,"parentId":19,"tags":{"page":"/api/hub/server-logs"},"startTime":1778788365781,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":485488,"timestamp":416879967082,"id":78,"parentId":41,"tags":{},"startTime":1778788365792,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":496669,"timestamp":416879955954,"id":41,"parentId":19,"tags":{"page":"/api/hub/session"},"startTime":1778788365781,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":487160,"timestamp":416879967088,"id":79,"parentId":42,"tags":{},"startTime":1778788365792,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":498250,"timestamp":416879956032,"id":42,"parentId":19,"tags":{"page":"/api/hub/stats"},"startTime":1778788365781,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":487941,"timestamp":416879967093,"id":80,"parentId":43,"tags":{},"startTime":1778788365792,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":498971,"timestamp":416879956107,"id":43,"parentId":19,"tags":{"page":"/api/hub/status"},"startTime":1778788365781,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":491351,"timestamp":416879967104,"id":82,"parentId":45,"tags":{},"startTime":1778788365792,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":502268,"timestamp":416879956232,"id":45,"parentId":19,"tags":{"page":"/api/hub/tasks"},"startTime":1778788365781,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":491556,"timestamp":416879967099,"id":81,"parentId":44,"tags":{},"startTime":1778788365792,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":502508,"timestamp":416879956172,"id":44,"parentId":19,"tags":{"page":"/api/hub/task-events"},"startTime":1778788365781,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":496637,"timestamp":416879967114,"id":84,"parentId":47,"tags":{},"startTime":1778788365792,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":507431,"timestamp":416879956376,"id":47,"parentId":19,"tags":{"page":"/api/hub/tokens"},"startTime":1778788365781,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":500721,"timestamp":416879967109,"id":83,"parentId":46,"tags":{},"startTime":1778788365792,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":511571,"timestamp":416879956312,"id":46,"parentId":19,"tags":{"page":"/api/hub/tmux"},"startTime":1778788365781,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":502031,"timestamp":416879967119,"id":85,"parentId":48,"tags":{},"startTime":1778788365792,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":512752,"timestamp":416879956458,"id":48,"parentId":19,"tags":{"page":"/favicon.ico"},"startTime":1778788365781,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":502608,"timestamp":416879970350,"id":87,"parentId":31,"tags":{},"startTime":1778788365795,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":518332,"timestamp":416879954687,"id":31,"parentId":19,"tags":{"page":"/api/hub/events"},"startTime":1778788365779,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":503649,"timestamp":416879969578,"id":86,"parentId":24,"tags":{},"startTime":1778788365794,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":522330,"timestamp":416879950936,"id":24,"parentId":19,"tags":{"page":"/api/anet/config"},"startTime":1778788365776,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":541708,"timestamp":416879967055,"id":74,"parentId":37,"tags":{},"startTime":1778788365792,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":553151,"timestamp":416879955677,"id":37,"parentId":19,"tags":{"page":"/api/hub/nodes"},"startTime":1778788365780,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":520322,"timestamp":416879995931,"id":90,"parentId":50,"tags":{},"startTime":1778788365821,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":559399,"timestamp":416879956928,"id":50,"parentId":19,"tags":{"page":"/logs"},"startTime":1778788365782,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":521903,"timestamp":416879995920,"id":89,"parentId":49,"tags":{},"startTime":1778788365821,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":561072,"timestamp":416879956801,"id":49,"parentId":19,"tags":{"page":"/login"},"startTime":1778788365781,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":524848,"timestamp":416879995937,"id":91,"parentId":51,"tags":{},"startTime":1778788365821,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":563751,"timestamp":416879957077,"id":51,"parentId":19,"tags":{"page":"/messages"},"startTime":1778788365782,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":527555,"timestamp":416879995880,"id":88,"parentId":23,"tags":{},"startTime":1778788365821,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":572752,"timestamp":416879950729,"id":23,"parentId":19,"tags":{"page":"/admin"},"startTime":1778788365775,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":529143,"timestamp":416879995945,"id":92,"parentId":52,"tags":{},"startTime":1778788365821,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":567874,"timestamp":416879957255,"id":52,"parentId":19,"tags":{"page":"/node"},"startTime":1778788365782,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":532362,"timestamp":416879995953,"id":93,"parentId":53,"tags":{},"startTime":1778788365821,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":570947,"timestamp":416879957431,"id":53,"parentId":19,"tags":{"page":"/nodes"},"startTime":1778788365782,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":536118,"timestamp":416879995967,"id":95,"parentId":56,"tags":{},"startTime":1778788365821,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":570845,"timestamp":416879961292,"id":56,"parentId":19,"tags":{"page":"/settings/networks"},"startTime":1778788365786,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":536522,"timestamp":416879995959,"id":94,"parentId":55,"tags":{},"startTime":1778788365821,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":571481,"timestamp":416879961093,"id":55,"parentId":19,"tags":{"page":"/server-logs"},"startTime":1778788365786,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":538487,"timestamp":416879995976,"id":96,"parentId":58,"tags":{},"startTime":1778788365821,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":574093,"timestamp":416879962989,"id":58,"parentId":19,"tags":{"page":"/settings/tokens"},"startTime":1778788365788,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":543769,"timestamp":416879996035,"id":99,"parentId":54,"tags":{},"startTime":1778788365821,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":580240,"timestamp":416879959604,"id":54,"parentId":19,"tags":{"page":"/"},"startTime":1778788365784,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":546581,"timestamp":416879995981,"id":97,"parentId":59,"tags":{},"startTime":1778788365821,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":579463,"timestamp":416879963146,"id":59,"parentId":19,"tags":{"page":"/tasks/[id]"},"startTime":1778788365788,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":549584,"timestamp":416879996042,"id":100,"parentId":57,"tags":{},"startTime":1778788365821,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":584249,"timestamp":416879961418,"id":57,"parentId":19,"tags":{"page":"/settings"},"startTime":1778788365786,"traceId":"a47bdb9bd1bc6ec6"},{"name":"is-page-static","duration":550047,"timestamp":416879995991,"id":98,"parentId":60,"tags":{},"startTime":1778788365821,"traceId":"a47bdb9bd1bc6ec6"},{"name":"check-page","duration":582831,"timestamp":416879963247,"id":60,"parentId":19,"tags":{"page":"/tasks"},"startTime":1778788365788,"traceId":"a47bdb9bd1bc6ec6"},{"name":"static-check","duration":599692,"timestamp":416879946421,"id":19,"parentId":1,"tags":{},"startTime":1778788365771,"traceId":"a47bdb9bd1bc6ec6"},{"name":"write-routes-manifest","duration":531,"timestamp":416880552347,"id":102,"parentId":1,"tags":{},"startTime":1778788366377,"traceId":"a47bdb9bd1bc6ec6"},{"name":"load-dotenv","duration":60,"timestamp":416880565654,"id":105,"parentId":104,"tags":{},"startTime":1778788366390,"traceId":"a47bdb9bd1bc6ec6"},{"name":"run-export-path-map","duration":734,"timestamp":416880568454,"id":106,"parentId":104,"tags":{},"startTime":1778788366393,"traceId":"a47bdb9bd1bc6ec6"},{"name":"next-export","duration":600302,"timestamp":416880564332,"id":104,"parentId":1,"tags":{},"startTime":1778788366389,"traceId":"a47bdb9bd1bc6ec6"},{"name":"move-exported-app-not-found-","duration":752,"timestamp":416881168700,"id":107,"parentId":103,"tags":{},"startTime":1778788366993,"traceId":"a47bdb9bd1bc6ec6"},{"name":"move-exported-app-global-error-","duration":928,"timestamp":416881169600,"id":108,"parentId":103,"tags":{},"startTime":1778788366994,"traceId":"a47bdb9bd1bc6ec6"}]
2
+ [{"name":"static-generation","duration":617382,"timestamp":416880558022,"id":103,"parentId":1,"tags":{},"startTime":1778788366383,"traceId":"a47bdb9bd1bc6ec6"},{"name":"write-routes-manifest","duration":527,"timestamp":416881175611,"id":109,"parentId":1,"tags":{},"startTime":1778788367000,"traceId":"a47bdb9bd1bc6ec6"},{"name":"print-tree-view","duration":4917,"timestamp":416881185744,"id":110,"parentId":1,"tags":{},"startTime":1778788367010,"traceId":"a47bdb9bd1bc6ec6"},{"name":"write-route-bundle-stats","duration":13041,"timestamp":416881190701,"id":111,"parentId":1,"tags":{},"startTime":1778788367015,"traceId":"a47bdb9bd1bc6ec6"},{"name":"telemetry-flush","duration":146462,"timestamp":416881203781,"id":112,"parentId":1,"tags":{},"startTime":1778788367028,"traceId":"a47bdb9bd1bc6ec6"},{"name":"next-build","duration":20000035,"timestamp":416861350248,"id":1,"tags":{"buildMode":"default","version":"16.2.3","bundler":"turbopack","has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1778788347175,"traceId":"a47bdb9bd1bc6ec6"}]
package/.next/trace-build CHANGED
@@ -1 +1 @@
1
- [{"name":"run-turbopack","duration":9499844,"timestamp":412609211735,"id":14,"parentId":1,"tags":{},"startTime":1778784095036,"traceId":"7e7f11a41fcc6acd"},{"name":"turbopack-build-events","duration":134,"timestamp":412609519993,"id":15,"parentId":1,"tags":{},"startTime":1778784095345,"traceId":"7e7f11a41fcc6acd"},{"name":"run-typescript","duration":10631519,"timestamp":412618744595,"id":16,"parentId":1,"tags":{},"startTime":1778784104569,"traceId":"7e7f11a41fcc6acd"},{"name":"static-check","duration":715585,"timestamp":412629453127,"id":19,"parentId":1,"tags":{},"startTime":1778784115278,"traceId":"7e7f11a41fcc6acd"},{"name":"static-generation","duration":645196,"timestamp":412630183144,"id":103,"parentId":1,"tags":{},"startTime":1778784116008,"traceId":"7e7f11a41fcc6acd"},{"name":"telemetry-flush","duration":280535,"timestamp":412630861734,"id":112,"parentId":1,"tags":{},"startTime":1778784116686,"traceId":"7e7f11a41fcc6acd"},{"name":"next-build","duration":22128906,"timestamp":412609013410,"id":1,"tags":{"buildMode":"default","version":"16.2.3","bundler":"turbopack","has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1778784094838,"traceId":"7e7f11a41fcc6acd"}]
1
+ [{"name":"run-turbopack","duration":9469000,"timestamp":416861550985,"id":14,"parentId":1,"tags":{},"startTime":1778788347376,"traceId":"a47bdb9bd1bc6ec6"},{"name":"turbopack-build-events","duration":93,"timestamp":416861910104,"id":15,"parentId":1,"tags":{},"startTime":1778788347735,"traceId":"a47bdb9bd1bc6ec6"},{"name":"run-typescript","duration":8837699,"timestamp":416871033411,"id":16,"parentId":1,"tags":{},"startTime":1778788356858,"traceId":"a47bdb9bd1bc6ec6"},{"name":"static-check","duration":599692,"timestamp":416879946421,"id":19,"parentId":1,"tags":{},"startTime":1778788365771,"traceId":"a47bdb9bd1bc6ec6"},{"name":"static-generation","duration":617382,"timestamp":416880558022,"id":103,"parentId":1,"tags":{},"startTime":1778788366383,"traceId":"a47bdb9bd1bc6ec6"},{"name":"telemetry-flush","duration":146462,"timestamp":416881203781,"id":112,"parentId":1,"tags":{},"startTime":1778788367028,"traceId":"a47bdb9bd1bc6ec6"},{"name":"next-build","duration":20000035,"timestamp":416861350248,"id":1,"tags":{"buildMode":"default","version":"16.2.3","bundler":"turbopack","has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1778788347175,"traceId":"a47bdb9bd1bc6ec6"}]
@@ -4,6 +4,7 @@ import { useEffect, useMemo, useRef, useState } from 'react';
4
4
  import { Session } from './types';
5
5
  import { aliasAvatarColors, aliasInitial } from './AliasAvatar';
6
6
  import { ChatPopover } from './ChatPopover';
7
+ import { vendorForModel, runtimeIdentity, identityLine } from '../lib/vendorIdentity';
7
8
 
8
9
  interface MessageFlow {
9
10
  from_alias: string;
@@ -290,6 +291,22 @@ export function TopoGraph({ sessions, sseSessions }: TopoGraphProps) {
290
291
  const brand = useBrand();
291
292
  const isIntern = brand === 'intern';
292
293
  const [messages, setMessages] = useState<MessageFlow[]>([]);
294
+ // Issue #87: ring | grid layout toggle. Ring is the tiered-radial default;
295
+ // grid arranges nodes in an N×M grid (better for 30+ nodes). Persisted to
296
+ // localStorage like the zoom/pan view state. Declared above nodePositions
297
+ // since that useMemo branches on it.
298
+ const [layout, setLayout] = useState<'ring' | 'grid'>('ring');
299
+ useEffect(() => {
300
+ try {
301
+ const saved = localStorage.getItem('anet-topo-layout');
302
+ if (saved === 'grid' || saved === 'ring') setLayout(saved);
303
+ } catch {}
304
+ }, []);
305
+ const toggleLayout = () => setLayout(prev => {
306
+ const next = prev === 'ring' ? 'grid' : 'ring';
307
+ try { localStorage.setItem('anet-topo-layout', next); } catch {}
308
+ return next;
309
+ });
293
310
 
294
311
  useEffect(() => {
295
312
  const fetchMessages = async () => {
@@ -329,6 +346,42 @@ export function TopoGraph({ sessions, sseSessions }: TopoGraphProps) {
329
346
  const offline = sessions.filter(s => s.status === 'offline' && !sseCount(s)).sort(byAlias);
330
347
  const positions: Record<string, Point> = {};
331
348
 
349
+ if (layout === 'grid') {
350
+ // Issue #87: N×M grid layout. All nodes share one sorted array (online
351
+ // first, then offline) so same-prefix aliases land in adjacent cells
352
+ // (#83 prefix-grouping synergy). cols = ⌈√N⌉; the last partial row is
353
+ // centred. Grid spans an inset box so node labels don't clip the edge.
354
+ const all = [...online, ...offline];
355
+ const n = all.length;
356
+ const cols = Math.max(1, Math.ceil(Math.sqrt(n)));
357
+ const rows = Math.max(1, Math.ceil(n / cols));
358
+ const gx0 = 150, gx1 = 850, gy0 = 120, gy1 = 560;
359
+ const cellW = (gx1 - gx0) / cols;
360
+ const cellH = (gy1 - gy0) / rows;
361
+ all.forEach((s, i) => {
362
+ const row = Math.floor(i / cols);
363
+ const col = i % cols;
364
+ const rowCount = row === rows - 1 ? n - row * cols : cols;
365
+ const rowInset = ((cols - rowCount) * cellW) / 2;
366
+ positions[s.alias] = {
367
+ x: gx0 + rowInset + (col + 0.5) * cellW,
368
+ y: gy0 + (row + 0.5) * cellH,
369
+ };
370
+ });
371
+ const links = buildFlowLinks(messages, positions);
372
+ const active = new Set<string>();
373
+ links.forEach(link => { active.add(link.from); active.add(link.to); });
374
+ const groupKeys = computeGroupKeys([...online, ...offline].map(s => s.alias));
375
+ return {
376
+ onlineNodes: online,
377
+ offlineNodes: offline,
378
+ nodePositions: positions,
379
+ flowLinks: links,
380
+ activeAliases: active,
381
+ groupKeys,
382
+ };
383
+ }
384
+
332
385
  // Round 97 (issue #50) + 98 (issue #61): three layout modes by N.
333
386
  // N ≤ 8 → single ring (r=220)
334
387
  // 8 < N ≤ 14 → two rings (inner r=175, outer r=260, half-step rot)
@@ -406,7 +459,7 @@ export function TopoGraph({ sessions, sseSessions }: TopoGraphProps) {
406
459
  activeAliases: active,
407
460
  groupKeys,
408
461
  };
409
- }, [messages, sessions, sseSessions]);
462
+ }, [messages, sessions, sseSessions, layout]);
410
463
 
411
464
  const workingCount = onlineNodes.filter(s => s.status === 'working').length;
412
465
  // Round 109 (Vincent 4582 P0): hover-gated labels above this node count
@@ -555,7 +608,25 @@ export function TopoGraph({ sessions, sseSessions }: TopoGraphProps) {
555
608
  <div className="text-xs uppercase text-gray-600 tracking-wider">Network Topology</div>
556
609
  <h2 className="text-lg text-white font-semibold">Command mesh</h2>
557
610
  </div>
558
- <div className="flex flex-wrap gap-2 text-xs">
611
+ <div className="flex flex-wrap items-center gap-2 text-xs">
612
+ {/* Issue #87: ring | grid layout toggle — segmented control,
613
+ persisted to localStorage anet-topo-layout. */}
614
+ <div className="inline-flex rounded-md border border-gray-500/25 overflow-hidden" role="group" aria-label="Topology layout">
615
+ <button
616
+ onClick={() => { if (layout !== 'ring') toggleLayout(); }}
617
+ aria-pressed={layout === 'ring'}
618
+ className={`px-2.5 py-1 transition-colors ${layout === 'ring' ? 'bg-cyan-500/15 text-cyan-300' : 'text-gray-500 hover:text-gray-400'}`}
619
+ >
620
+ Ring
621
+ </button>
622
+ <button
623
+ onClick={() => { if (layout !== 'grid') toggleLayout(); }}
624
+ aria-pressed={layout === 'grid'}
625
+ className={`px-2.5 py-1 border-l border-gray-500/25 transition-colors ${layout === 'grid' ? 'bg-cyan-500/15 text-cyan-300' : 'text-gray-500 hover:text-gray-400'}`}
626
+ >
627
+ Grid
628
+ </button>
629
+ </div>
559
630
  <span className="px-2.5 py-1 rounded-md bg-green-500/10 text-green-300 border border-green-500/20">
560
631
  {workingCount} working
561
632
  </span>
@@ -624,6 +695,10 @@ export function TopoGraph({ sessions, sseSessions }: TopoGraphProps) {
624
695
  {/* Round 103 (issue #81): everything inside this <g> zooms + pans
625
696
  together. transform order = translate then scale. */}
626
697
  <g transform={`translate(${view.x} ${view.y}) scale(${view.zoom})`}>
698
+ {/* Issue #87: radar/ring ambiance renders only in ring layout —
699
+ grid mode drops it so the concentric rings don't sit behind a
700
+ rectangular grid. */}
701
+ {layout === 'ring' && (<>
627
702
  <circle cx={cx} cy={cy} r="330" fill="url(#topo-radar)" />
628
703
 
629
704
  {/* Round 45: subtle star field — 24 deterministic dots scattered
@@ -705,12 +780,13 @@ export function TopoGraph({ sessions, sseSessions }: TopoGraphProps) {
705
780
  opacity={isLight ? 0.35 : 0.18}
706
781
  />
707
782
  ))}
783
+ </>)}
708
784
 
709
785
  {/* hub links — round 46: idle spokes now have animated
710
786
  stroke-dashoffset so dashes flow outward from the hub
711
787
  ("command relay" feel). Active spokes carrying live message
712
788
  flow stay as solid bright strokes. */}
713
- {onlineNodes.map((session, idx) => {
789
+ {layout === 'ring' && onlineNodes.map((session, idx) => {
714
790
  const pos = nodePositions[session.alias];
715
791
  if (!pos) return null;
716
792
  const path = curvePath({ x: cx, y: cy }, pos, 0);
@@ -775,7 +851,7 @@ export function TopoGraph({ sessions, sseSessions }: TopoGraphProps) {
775
851
  visually; two outward pulses keep the "signal source" idea
776
852
  from r17. Light theme gets a paler core to avoid hot-spotting
777
853
  the bg. */}
778
- <g>
854
+ {layout === 'ring' && (<g>
779
855
  {/* static grounding halo — sits underneath, low opacity */}
780
856
  <circle
781
857
  cx={cx} cy={cy} r="18"
@@ -795,7 +871,7 @@ export function TopoGraph({ sessions, sseSessions }: TopoGraphProps) {
795
871
  {/* core — 20px diameter, larger inner highlight reads as a "lit lamp" */}
796
872
  <circle cx={cx} cy={cy} r="10" fill={isLight ? '#059669' : '#10b981'} />
797
873
  <circle cx={cx} cy={cy} r="5" fill="#d1fae5" opacity="0.9" />
798
- </g>
874
+ </g>)}
799
875
 
800
876
  {/* agent nodes */}
801
877
  {[...onlineNodes, ...offlineNodes].map(session => {
@@ -833,6 +909,10 @@ export function TopoGraph({ sessions, sseSessions }: TopoGraphProps) {
833
909
  onPointerLeave={() => denseLayout && setHoveredAlias(prev => (prev === session.alias ? null : prev))}
834
910
  onClick={() => setChatAlias(session.alias)}
835
911
  >
912
+ {/* Issue #96: native hover tooltip — "Vendor · model · Runtime".
913
+ Falls back to just the alias when the node reports no
914
+ model/runtime. */}
915
+ <title>{identityLine(session.model, session.runtime) || session.alias}</title>
836
916
  {isActive && (
837
917
  <circle cx={pos.x} cy={pos.y} r={radius + 14} fill={status.primary} opacity={isLight ? 0.08 : 0.12}>
838
918
  <animate attributeName="r" values={`${radius + 8};${radius + 22};${radius + 8}`} dur="2.4s" repeatCount="indefinite" />
@@ -850,33 +930,26 @@ export function TopoGraph({ sessions, sseSessions }: TopoGraphProps) {
850
930
  strokeDasharray={isOnline ? 'none' : '5 5'}
851
931
  filter={isOnline && !isLight ? 'url(#topo-glow)' : undefined}
852
932
  />
853
- {/* Round 99 (issue #79): node "avatar" hue-hashed
854
- initials circle inside the status ring. Round 100:
855
- when brand=intern, swap the initials for the 书小生
856
- mascot image (asset from 群星马 task 51dd0d1d). The
857
- image already has a transparent bg so it sits cleanly
858
- on the node's dark/light fill; the outer status ring
859
- still carries working/idle/etc. */}
933
+ {/* Issue #96: node "avatar" is now driven by the model
934
+ vendor. Decision order:
935
+ 1. ?brand=intern flag, or an intern-aliased node with
936
+ no model field 书生 coin (preserves #79).
937
+ 2. vendor has a packaged logo asset that logo image
938
+ (intern-s1-* models land here via vendorForModel).
939
+ 3. known vendor, logo asset not shipped yet → a
940
+ vendor-tinted monogram (spec-mandated fallback).
941
+ 4. unknown vendor / null model → the prefix-group
942
+ hue-hashed initial (#83/#99 behaviour, unchanged). */}
860
943
  {(() => {
861
944
  const ar = isOnline ? 14 : 10;
862
- // Round 108 (issue #79 reopened): show the 书小生 avatar
863
- // coin for any agent whose alias marks it as an Intern /
864
- // 书生 runtime — not only under the global ?brand=intern
865
- // flag. Vincent 4565: a fleet of 书生N号 nodes should SHOW
866
- // 书生, not a generic "书" initial. ?brand=intern still
867
- // forces the coin on every node (full brand showcase).
868
- const isInternNode = isIntern || /书生|书小生|intern/i.test(session.alias);
869
- if (isInternNode) {
870
- // Round 102: self-contained "avatar coin" — 书小生 figure
871
- // keyed off its white background and composited onto a
872
- // cream circular backplate. The cream coin gives the
873
- // dark-haired figure consistent contrast on BOTH the
874
- // dark cyber theme and light theme. Render at the node
875
- // diameter so the coin fills inside the status ring.
876
- const size = radius * 2;
945
+ const size = radius * 2;
946
+ const vendor = vendorForModel(session.model);
947
+ const internByAlias = /书生|书小生|intern/i.test(session.alias);
948
+
949
+ if (isIntern || internByAlias || vendor.logo) {
877
950
  return (
878
951
  <image
879
- href="/intern_avatar.png"
952
+ href={vendor.logo ?? '/intern_avatar.png'}
880
953
  x={pos.x - size / 2}
881
954
  y={pos.y - size / 2}
882
955
  width={size}
@@ -885,12 +958,25 @@ export function TopoGraph({ sessions, sseSessions }: TopoGraphProps) {
885
958
  />
886
959
  );
887
960
  }
961
+ if (vendor.id !== 'unknown') {
962
+ // Known model house, logo asset not in public/vendors/
963
+ // yet — vendor-tinted monogram stands in.
964
+ return (
965
+ <>
966
+ <circle cx={pos.x} cy={pos.y} r={ar} fill={vendor.mono.bg} stroke={vendor.mono.ring} strokeWidth="1" />
967
+ <text
968
+ x={pos.x} y={pos.y} dy="0.34em" textAnchor="middle"
969
+ fill={vendor.mono.text} fontSize={isOnline ? 14 : 10}
970
+ fontFamily="monospace" fontWeight="700"
971
+ >
972
+ {vendor.initial}
973
+ </text>
974
+ </>
975
+ );
976
+ }
888
977
  // Round 106 (issue #83): hue keyed to the prefix group,
889
- // not the full alias — every 通信* node shares one color,
890
- // every 研究员* another, so teams cluster visually even
891
- // when the tier layout spreads them across rings.
978
+ // not the full alias — every 通信* node shares one color.
892
979
  const c = aliasAvatarColors(groupKeys[session.alias] || session.alias);
893
- const fs = isOnline ? 14 : 10;
894
980
  return (
895
981
  <>
896
982
  <circle cx={pos.x} cy={pos.y} r={ar} fill={c.bg} stroke={c.ring} strokeWidth="1" />
@@ -900,7 +986,7 @@ export function TopoGraph({ sessions, sseSessions }: TopoGraphProps) {
900
986
  dy="0.34em"
901
987
  textAnchor="middle"
902
988
  fill={c.text}
903
- fontSize={fs}
989
+ fontSize={isOnline ? 14 : 10}
904
990
  fontFamily="monospace"
905
991
  fontWeight="700"
906
992
  >
@@ -909,6 +995,26 @@ export function TopoGraph({ sessions, sseSessions }: TopoGraphProps) {
909
995
  </>
910
996
  );
911
997
  })()}
998
+ {/* Issue #96: runtime badge — small corner glyph marking the
999
+ execution shell (CLI / SDK / HTTP API). Sits bottom-right
1000
+ of the avatar; colours kept off the working/idle/offline
1001
+ status hues. Absent when the node reports no runtime. */}
1002
+ {(() => {
1003
+ const rt = runtimeIdentity(session.runtime);
1004
+ if (!rt) return null;
1005
+ const br = isOnline ? 7 : 5.5;
1006
+ const bx = pos.x + radius * 0.72;
1007
+ const by = pos.y + radius * 0.72;
1008
+ const icon = br * 2 * 0.62;
1009
+ return (
1010
+ <g style={{ pointerEvents: 'none' }}>
1011
+ <circle cx={bx} cy={by} r={br} fill={pal.containerBg} stroke={rt.color} strokeWidth="1.5" />
1012
+ <g transform={`translate(${bx - icon / 2} ${by - icon / 2}) scale(${icon / 24})`}>
1013
+ <path d={rt.iconPath} fill="none" stroke={rt.color} strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" />
1014
+ </g>
1015
+ </g>
1016
+ );
1017
+ })()}
912
1018
  {session.status === 'working' && (
913
1019
  // working pulse — small dot just inside the status ring,
914
1020
  // above the avatar text. Was a 18px horizontal bar at
@@ -12,6 +12,10 @@ export interface Session {
12
12
  last_seen_at?: string;
13
13
  config_path?: string;
14
14
  network_id?: string;
15
+ // #96: model vendor + execution runtime. Added to /api/status sessions in
16
+ // commhub-server 0.8.1-preview.0; null on older nodes / older hubs.
17
+ model?: string | null;
18
+ runtime?: string | null;
15
19
  }
16
20
 
17
21
  export interface Health {