@sleep2agi/agent-network-dashboard 0.6.3-preview.43 → 0.6.3-preview.45

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 (246) hide show
  1. package/.next/BUILD_COMMIT +1 -0
  2. package/.next/BUILD_ID +1 -1
  3. package/.next/build-manifest.json +3 -3
  4. package/.next/diagnostics/route-bundle-stats.json +78 -78
  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.js.nft.json +1 -1
  14. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  15. package/.next/server/app/_not-found.html +2 -2
  16. package/.next/server/app/_not-found.rsc +12 -12
  17. package/.next/server/app/_not-found.segments/_full.segment.rsc +12 -12
  18. package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  19. package/.next/server/app/_not-found.segments/_index.segment.rsc +7 -7
  20. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  21. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  22. package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  23. package/.next/server/app/admin/page.js.nft.json +1 -1
  24. package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
  25. package/.next/server/app/admin.html +2 -2
  26. package/.next/server/app/admin.rsc +14 -14
  27. package/.next/server/app/admin.segments/_full.segment.rsc +14 -14
  28. package/.next/server/app/admin.segments/_head.segment.rsc +4 -4
  29. package/.next/server/app/admin.segments/_index.segment.rsc +7 -7
  30. package/.next/server/app/admin.segments/_tree.segment.rsc +1 -1
  31. package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +4 -4
  32. package/.next/server/app/admin.segments/admin.segment.rsc +3 -3
  33. package/.next/server/app/index.html +2 -2
  34. package/.next/server/app/index.rsc +14 -14
  35. package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
  36. package/.next/server/app/index.segments/_full.segment.rsc +14 -14
  37. package/.next/server/app/index.segments/_head.segment.rsc +4 -4
  38. package/.next/server/app/index.segments/_index.segment.rsc +7 -7
  39. package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  40. package/.next/server/app/login/page.js.nft.json +1 -1
  41. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  42. package/.next/server/app/login.html +2 -2
  43. package/.next/server/app/login.rsc +14 -14
  44. package/.next/server/app/login.segments/_full.segment.rsc +14 -14
  45. package/.next/server/app/login.segments/_head.segment.rsc +4 -4
  46. package/.next/server/app/login.segments/_index.segment.rsc +7 -7
  47. package/.next/server/app/login.segments/_tree.segment.rsc +1 -1
  48. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
  49. package/.next/server/app/login.segments/login.segment.rsc +3 -3
  50. package/.next/server/app/logs/page.js.nft.json +1 -1
  51. package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
  52. package/.next/server/app/logs.html +2 -2
  53. package/.next/server/app/logs.rsc +14 -14
  54. package/.next/server/app/logs.segments/_full.segment.rsc +14 -14
  55. package/.next/server/app/logs.segments/_head.segment.rsc +4 -4
  56. package/.next/server/app/logs.segments/_index.segment.rsc +7 -7
  57. package/.next/server/app/logs.segments/_tree.segment.rsc +1 -1
  58. package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +4 -4
  59. package/.next/server/app/logs.segments/logs.segment.rsc +3 -3
  60. package/.next/server/app/messages/page.js.nft.json +1 -1
  61. package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
  62. package/.next/server/app/messages.html +2 -2
  63. package/.next/server/app/messages.rsc +14 -14
  64. package/.next/server/app/messages.segments/_full.segment.rsc +14 -14
  65. package/.next/server/app/messages.segments/_head.segment.rsc +4 -4
  66. package/.next/server/app/messages.segments/_index.segment.rsc +7 -7
  67. package/.next/server/app/messages.segments/_tree.segment.rsc +1 -1
  68. package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +4 -4
  69. package/.next/server/app/messages.segments/messages.segment.rsc +3 -3
  70. package/.next/server/app/node/page.js.nft.json +1 -1
  71. package/.next/server/app/node/page_client-reference-manifest.js +1 -1
  72. package/.next/server/app/node.html +2 -2
  73. package/.next/server/app/node.rsc +14 -14
  74. package/.next/server/app/node.segments/_full.segment.rsc +14 -14
  75. package/.next/server/app/node.segments/_head.segment.rsc +4 -4
  76. package/.next/server/app/node.segments/_index.segment.rsc +7 -7
  77. package/.next/server/app/node.segments/_tree.segment.rsc +1 -1
  78. package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +4 -4
  79. package/.next/server/app/node.segments/node.segment.rsc +3 -3
  80. package/.next/server/app/nodes/page.js.nft.json +1 -1
  81. package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
  82. package/.next/server/app/nodes.html +2 -2
  83. package/.next/server/app/nodes.rsc +14 -14
  84. package/.next/server/app/nodes.segments/_full.segment.rsc +14 -14
  85. package/.next/server/app/nodes.segments/_head.segment.rsc +4 -4
  86. package/.next/server/app/nodes.segments/_index.segment.rsc +7 -7
  87. package/.next/server/app/nodes.segments/_tree.segment.rsc +1 -1
  88. package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +4 -4
  89. package/.next/server/app/nodes.segments/nodes.segment.rsc +3 -3
  90. package/.next/server/app/page.js.nft.json +1 -1
  91. package/.next/server/app/page_client-reference-manifest.js +1 -1
  92. package/.next/server/app/providers/page.js.nft.json +1 -1
  93. package/.next/server/app/providers/page_client-reference-manifest.js +1 -1
  94. package/.next/server/app/providers.html +2 -2
  95. package/.next/server/app/providers.rsc +14 -14
  96. package/.next/server/app/providers.segments/_full.segment.rsc +14 -14
  97. package/.next/server/app/providers.segments/_head.segment.rsc +4 -4
  98. package/.next/server/app/providers.segments/_index.segment.rsc +7 -7
  99. package/.next/server/app/providers.segments/_tree.segment.rsc +1 -1
  100. package/.next/server/app/providers.segments/providers/__PAGE__.segment.rsc +4 -4
  101. package/.next/server/app/providers.segments/providers.segment.rsc +3 -3
  102. package/.next/server/app/server-logs/page.js.nft.json +1 -1
  103. package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
  104. package/.next/server/app/server-logs.html +2 -2
  105. package/.next/server/app/server-logs.rsc +14 -14
  106. package/.next/server/app/server-logs.segments/_full.segment.rsc +14 -14
  107. package/.next/server/app/server-logs.segments/_head.segment.rsc +4 -4
  108. package/.next/server/app/server-logs.segments/_index.segment.rsc +7 -7
  109. package/.next/server/app/server-logs.segments/_tree.segment.rsc +1 -1
  110. package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +4 -4
  111. package/.next/server/app/server-logs.segments/server-logs.segment.rsc +3 -3
  112. package/.next/server/app/servers/page.js.nft.json +1 -1
  113. package/.next/server/app/servers/page_client-reference-manifest.js +1 -1
  114. package/.next/server/app/servers.html +2 -2
  115. package/.next/server/app/servers.rsc +14 -14
  116. package/.next/server/app/servers.segments/_full.segment.rsc +14 -14
  117. package/.next/server/app/servers.segments/_head.segment.rsc +4 -4
  118. package/.next/server/app/servers.segments/_index.segment.rsc +7 -7
  119. package/.next/server/app/servers.segments/_tree.segment.rsc +1 -1
  120. package/.next/server/app/servers.segments/servers/__PAGE__.segment.rsc +4 -4
  121. package/.next/server/app/servers.segments/servers.segment.rsc +3 -3
  122. package/.next/server/app/settings/networks/page.js.nft.json +1 -1
  123. package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
  124. package/.next/server/app/settings/networks.html +2 -2
  125. package/.next/server/app/settings/networks.rsc +14 -14
  126. package/.next/server/app/settings/networks.segments/_full.segment.rsc +14 -14
  127. package/.next/server/app/settings/networks.segments/_head.segment.rsc +4 -4
  128. package/.next/server/app/settings/networks.segments/_index.segment.rsc +7 -7
  129. package/.next/server/app/settings/networks.segments/_tree.segment.rsc +1 -1
  130. package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +4 -4
  131. package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +3 -3
  132. package/.next/server/app/settings/networks.segments/settings.segment.rsc +3 -3
  133. package/.next/server/app/settings/page.js.nft.json +1 -1
  134. package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  135. package/.next/server/app/settings/tokens/page.js.nft.json +1 -1
  136. package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
  137. package/.next/server/app/settings/tokens.html +2 -2
  138. package/.next/server/app/settings/tokens.rsc +14 -14
  139. package/.next/server/app/settings/tokens.segments/_full.segment.rsc +14 -14
  140. package/.next/server/app/settings/tokens.segments/_head.segment.rsc +4 -4
  141. package/.next/server/app/settings/tokens.segments/_index.segment.rsc +7 -7
  142. package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +1 -1
  143. package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +4 -4
  144. package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +3 -3
  145. package/.next/server/app/settings/tokens.segments/settings.segment.rsc +3 -3
  146. package/.next/server/app/settings.html +2 -2
  147. package/.next/server/app/settings.rsc +14 -14
  148. package/.next/server/app/settings.segments/_full.segment.rsc +14 -14
  149. package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
  150. package/.next/server/app/settings.segments/_index.segment.rsc +7 -7
  151. package/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
  152. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
  153. package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
  154. package/.next/server/app/tasks/[id]/page.js.nft.json +1 -1
  155. package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
  156. package/.next/server/app/tasks/page.js.nft.json +1 -1
  157. package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
  158. package/.next/server/app/tasks.html +2 -2
  159. package/.next/server/app/tasks.rsc +14 -14
  160. package/.next/server/app/tasks.segments/_full.segment.rsc +14 -14
  161. package/.next/server/app/tasks.segments/_head.segment.rsc +4 -4
  162. package/.next/server/app/tasks.segments/_index.segment.rsc +7 -7
  163. package/.next/server/app/tasks.segments/_tree.segment.rsc +1 -1
  164. package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +4 -4
  165. package/.next/server/app/tasks.segments/tasks.segment.rsc +3 -3
  166. package/.next/server/chunks/ssr/[root-of-the-server]__0jns048._.js +3 -0
  167. package/.next/server/chunks/ssr/[root-of-the-server]__0jns048._.js.map +1 -0
  168. package/.next/server/chunks/ssr/[root-of-the-server]__0va6h-y._.js +3 -3
  169. package/.next/server/chunks/ssr/[root-of-the-server]__0va6h-y._.js.map +1 -1
  170. package/.next/server/chunks/ssr/{[root-of-the-server]__056tw5g._.js → [root-of-the-server]__0z0lvdf._.js} +2 -2
  171. package/.next/server/chunks/ssr/[root-of-the-server]__0z0lvdf._.js.map +1 -0
  172. package/.next/server/chunks/ssr/[root-of-the-server]__13svd64._.js +3 -0
  173. package/.next/server/chunks/ssr/[root-of-the-server]__13svd64._.js.map +1 -0
  174. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_0f4savf._.js +3 -3
  175. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_0f4savf._.js.map +1 -1
  176. package/.next/server/chunks/ssr/{dash-492_agent-network-dashboard_app_12yiaen._.js → dash-492_agent-network-dashboard_app_07foku.._.js} +2 -2
  177. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_07foku.._.js.map +1 -0
  178. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_0fv9~x1._.js +1 -1
  179. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_0fv9~x1._.js.map +1 -1
  180. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_0jey2is._.js +3 -0
  181. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_0jey2is._.js.map +1 -0
  182. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_0tbukk6._.js +3 -0
  183. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_0tbukk6._.js.map +1 -0
  184. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_10nv4wt._.js +3 -0
  185. package/.next/server/chunks/ssr/{dash-492_agent-network-dashboard_app_02~ml1y._.js.map → dash-492_agent-network-dashboard_app_10nv4wt._.js.map} +1 -1
  186. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_components_07gcm8v._.js +3 -3
  187. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_components_07gcm8v._.js.map +1 -1
  188. package/.next/server/middleware-build-manifest.js +3 -3
  189. package/.next/server/pages/404.html +2 -2
  190. package/.next/server/pages/500.html +1 -1
  191. package/.next/static/chunks/0.t9q6b8-tp7o.js +1 -0
  192. package/.next/static/chunks/{07hmiozabjis~.js → 00.lep~gx75xc.js} +1 -1
  193. package/.next/static/chunks/0casvy.vqveum.js +7 -0
  194. package/.next/static/chunks/0e3gktr80d3im.js +2 -0
  195. package/.next/static/chunks/0gv~xarphwy7~.js +1 -0
  196. package/.next/static/chunks/0jgo1j.i.wd5q.js +7 -0
  197. package/.next/static/chunks/0k_3kdj.1c2m5.js +1 -0
  198. package/.next/static/chunks/0uj3h67aerffm.js +1 -0
  199. package/.next/static/chunks/0~rml5aiu3yw7.js +7 -0
  200. package/.next/static/chunks/0~v0m8f1.aob5.js +4 -0
  201. package/.next/static/chunks/16._eot2r-z1r.js +1 -0
  202. package/.next/static/chunks/16kecv_vyjyyv.js +1 -0
  203. package/.next/trace +2 -2
  204. package/.next/trace-build +1 -1
  205. package/app/components/ChatPopover.tsx +9 -2
  206. package/app/components/HealthBanner.tsx +21 -2
  207. package/app/components/Sidebar.tsx +21 -2
  208. package/app/components/StatsBar.tsx +32 -14
  209. package/app/components/TaskChatPanel.tsx +11 -3
  210. package/app/components/TopoGraph.tsx +25 -11
  211. package/app/lib/presence.ts +98 -0
  212. package/app/page.tsx +23 -14
  213. package/package.json +1 -1
  214. package/tests/e2e-515-presence-predicate.spec.ts +75 -0
  215. package/tests/e2e-515-presence.spec.ts +148 -0
  216. package/tests/e2e-53-blind-vs-empty.spec.ts +262 -0
  217. package/tests/e2e-53-presence-status.spec.ts +52 -0
  218. package/.next/server/chunks/ssr/[root-of-the-server]__056tw5g._.js.map +0 -1
  219. package/.next/server/chunks/ssr/[root-of-the-server]__06g2-qq._.js +0 -3
  220. package/.next/server/chunks/ssr/[root-of-the-server]__06g2-qq._.js.map +0 -1
  221. package/.next/server/chunks/ssr/[root-of-the-server]__0qv41lg._.js +0 -3
  222. package/.next/server/chunks/ssr/[root-of-the-server]__0qv41lg._.js.map +0 -1
  223. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_02~ml1y._.js +0 -3
  224. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_04nejob._.js +0 -3
  225. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_04nejob._.js.map +0 -1
  226. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_0kehfih._.js +0 -3
  227. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_0kehfih._.js.map +0 -1
  228. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_0vvr81v._.js +0 -3
  229. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_0vvr81v._.js.map +0 -1
  230. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_0~9qq2o._.js +0 -3
  231. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_0~9qq2o._.js.map +0 -1
  232. package/.next/server/chunks/ssr/dash-492_agent-network-dashboard_app_12yiaen._.js.map +0 -1
  233. package/.next/static/chunks/00kg.oomong9m.js +0 -1
  234. package/.next/static/chunks/02a6-zbyr.zoy.js +0 -2
  235. package/.next/static/chunks/06ww0tn_jfcfd.js +0 -1
  236. package/.next/static/chunks/0_90al8hntttb.js +0 -1
  237. package/.next/static/chunks/0idb.71vziyhz.js +0 -7
  238. package/.next/static/chunks/0qw7i_y5i75.q.js +0 -1
  239. package/.next/static/chunks/0szzm0ma-335n.js +0 -4
  240. package/.next/static/chunks/0xxfl.bqy.bd4.js +0 -7
  241. package/.next/static/chunks/0yscbgm2a_d1u.js +0 -1
  242. package/.next/static/chunks/0zj956.f-k1jj.js +0 -7
  243. package/.next/static/chunks/17ns4oqzib99e.js +0 -1
  244. /package/.next/static/{BXw6vds1QR_zb-M-KgpT7 → EEoQxe-lggOsAx0h8hIFx}/_buildManifest.js +0 -0
  245. /package/.next/static/{BXw6vds1QR_zb-M-KgpT7 → EEoQxe-lggOsAx0h8hIFx}/_clientMiddlewareManifest.js +0 -0
  246. /package/.next/static/{BXw6vds1QR_zb-M-KgpT7 → EEoQxe-lggOsAx0h8hIFx}/_ssgManifest.js +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../../../dash-492/agent-network-dashboard/node_modules/next/src/server/route-modules/app-page/module.compiled.js","../../../../../../dash-492/agent-network-dashboard/node_modules/next/src/server/route-modules/app-page/vendored/ssr/react-jsx-runtime.ts","../../../../../../dash-492/agent-network-dashboard/node_modules/next/src/server/route-modules/app-page/vendored/ssr/react.ts","../../../../../../dash-492/agent-network-dashboard/node_modules/next/src/server/route-modules/app-page/vendored/contexts/app-router-context.ts","../../../../../../dash-492/agent-network-dashboard/node_modules/next/src/server/route-modules/app-page/vendored/ssr/react-server-dom-turbopack-client.ts","../../../../../../dash-492/agent-network-dashboard/node_modules/next/src/server/route-modules/app-page/vendored/contexts/hooks-client-context.ts","../../../../../../dash-492/agent-network-dashboard/node_modules/next/src/server/route-modules/app-page/vendored/contexts/server-inserted-html.ts","../../../../../../dash-492/agent-network-dashboard/app/lib/time.ts","../../../../../../dash-492/agent-network-dashboard/app/lib/network-context.tsx","../../../../../../dash-492/agent-network-dashboard/app/lib/chat-unread.ts","../../../../../../dash-492/agent-network-dashboard/app/lib/chat-mute.ts","../../../../../../dash-492/agent-network-dashboard/app/components/ThemeSwitcher.tsx","../../../../../../dash-492/agent-network-dashboard/app/components/ServersDrawer.tsx"],"sourcesContent":["if (process.env.NEXT_RUNTIME === 'edge') {\n module.exports = require('next/dist/server/route-modules/app-page/module.js')\n} else {\n if (process.env.__NEXT_EXPERIMENTAL_REACT) {\n if (process.env.NODE_ENV === 'development') {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo-experimental.runtime.dev.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page-experimental.runtime.dev.js')\n }\n } else {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page-experimental.runtime.prod.js')\n }\n }\n } else {\n if (process.env.NODE_ENV === 'development') {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo.runtime.dev.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page.runtime.dev.js')\n }\n } else {\n if (process.env.TURBOPACK) {\n module.exports = require('next/dist/compiled/next-server/app-page-turbo.runtime.prod.js')\n } else {\n module.exports = require('next/dist/compiled/next-server/app-page.runtime.prod.js')\n }\n }\n }\n}\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['react-ssr']!.ReactJsxRuntime\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['react-ssr']!.React\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['contexts'].AppRouterContext\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['react-ssr']!.ReactServerDOMTurbopackClient\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['contexts'].HooksClientContext\n","module.exports = (\n require('../../module.compiled') as typeof import('../../module.compiled')\n).vendored['contexts'].ServerInsertedHtml\n","/** Shared timestamp helpers for hub-sourced data.\n *\n * Background — the CommHub serialises timestamps SQL-style without a\n * zone (\"2026-05-15 06:00:28\"), but some test data uses full ISO\n * (\"…T06:00:28Z\"). `Date.parse` on bare SQL is **local-time** in every\n * browser the dashboard supports, so a UTC+8 operator silently sees\n * every timestamp 8 h older than reality (Round 35 dug this out via\n * the `isGhost` filter mis-fire).\n *\n * Round 38 / Loop consolidates parsing — TopoGraph (R35), ChatPopover\n * (R37) and utils.ts::timeAgo all mirrored the same SQL→UTC rewrite;\n * one source of truth here. */\n\n/** Parse a hub timestamp to ms-since-epoch, treating SQL-style strings\n * as UTC. ISO strings (with `T`) bypass the rewrite and are parsed as-is.\n * Returns null for empty / unparseable input. */\nexport function parseHubTime(dateStr: string | null | undefined): number | null {\n if (!dateStr) return null;\n const iso = dateStr.includes('T') ? dateStr : dateStr.replace(' ', 'T') + 'Z';\n const t = Date.parse(iso);\n return Number.isFinite(t) ? t : null;\n}\n\n/** Format `dateStr` as a short relative-time string (\"6m ago\" / \"2h ago\").\n * Future timestamps (clock skew) collapse to \"just now\". Returns null when\n * the input doesn't parse — callers can decide on a fallback. */\nexport function relativeAgo(dateStr: string | null | undefined): string | null {\n const t = parseHubTime(dateStr);\n if (t === null) return null;\n const s = Math.floor((Date.now() - t) / 1000);\n if (s < 0) return 'just now';\n if (s < 60) return `${s}s ago`;\n if (s < 3600) return `${Math.floor(s / 60)}m ago`;\n if (s < 86400) return `${Math.floor(s / 3600)}h ago`;\n return `${Math.floor(s / 86400)}d ago`;\n}\n\n/** Loop R7 (跨面一致性): WeChat-style contextual timestamp shared by the\n * chat panel (R3) and /messages dividers. zh locales keep the native\n * wording (昨天/星期X); others get Intl output (\"Yesterday\"/\"Tue\").\n * Today → \"14:32\" · yesterday → \"昨天 14:32\" · <7d → \"星期二 14:32\" ·\n * this year → \"7月16日 14:32\" · older adds the year. */\nexport function formatWeChatTime(value: string | null | undefined): string {\n const t = parseHubTime(value);\n if (t === null) return '';\n const d = new Date(t);\n const now = new Date();\n const zh = typeof navigator !== 'undefined' && (navigator.language || '').toLowerCase().startsWith('zh');\n const hm = `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;\n const startOfDay = (x: Date) => new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime();\n const dayDiff = Math.round((startOfDay(now) - startOfDay(d)) / 86400000);\n if (dayDiff === 0) return hm;\n if (dayDiff === 1) return zh ? `昨天 ${hm}` : `Yesterday ${hm}`;\n if (dayDiff > 1 && dayDiff < 7) {\n const wd = new Intl.DateTimeFormat(zh ? 'zh-CN' : undefined, { weekday: zh ? 'long' : 'short' }).format(d);\n return `${wd} ${hm}`;\n }\n const md = new Intl.DateTimeFormat(zh ? 'zh-CN' : undefined, {\n month: zh ? 'long' : 'short', day: 'numeric',\n ...(d.getFullYear() !== now.getFullYear() ? { year: 'numeric' } : {}),\n }).format(d);\n return `${md} ${hm}`;\n}\n","'use client';\n\nimport { createContext, useContext, useState, useEffect, ReactNode } from 'react';\n\ninterface NetworkContextType {\n networkId: string;\n setNetworkId: (id: string) => void;\n}\n\nconst NetworkContext = createContext<NetworkContextType>({ networkId: '', setNetworkId: () => {} });\n\nexport function NetworkProvider({ children }: { children: ReactNode }) {\n const [networkId, setNetworkId] = useState('');\n\n useEffect(() => {\n const saved = sessionStorage.getItem('anet_network_id');\n // Hydration-safe restore (see UserBar note).\n // eslint-disable-next-line react-hooks/set-state-in-effect\n if (saved) setNetworkId(saved);\n }, []);\n\n const setAndPersist = (id: string) => {\n setNetworkId(id);\n sessionStorage.setItem('anet_network_id', id);\n };\n\n return (\n <NetworkContext.Provider value={{ networkId, setNetworkId: setAndPersist }}>\n {children}\n </NetworkContext.Provider>\n );\n}\n\nexport function useNetworkId() {\n return useContext(NetworkContext);\n}\n","'use client';\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport useSWR from 'swr';\nimport { useNetworkId } from './network-context';\nimport { isMuted, useMuteVersion } from './chat-mute';\n\nconst STORAGE_PREFIX = 'anet_chat_read_v1:';\nconst UNREAD_EVENT = 'anet-chat-read-updated';\n\ninterface ChatMessage {\n from_alias?: string | null;\n to_alias?: string | null;\n created_at?: string | null;\n}\n\n/** Senders/recipients that mean \"the dashboard user\" in hub data. The chat\n * panel uses the same set to decide which bubbles are \"You\". */\nconst USERISH = new Set(['', 'dashboard', 'admin', 'api', 'hub']);\nconst isUserish = (v?: string | null) => USERISH.has((v || '').trim().toLowerCase());\n\ninterface ReadMap {\n [alias: string]: string;\n}\n\nfunction storageKey(networkId: string) {\n return `${STORAGE_PREFIX}${networkId || 'global'}`;\n}\n\nfunction parseHubTime(value?: string | null): number {\n if (!value) return 0;\n const normalized = value.includes('T') ? value : value.replace(' ', 'T');\n const withZone = /Z$|[+-]\\d{2}:\\d{2}$/.test(normalized) ? normalized : `${normalized}Z`;\n const ts = Date.parse(withZone);\n return Number.isFinite(ts) ? ts : 0;\n}\n\n// Loop R8 (Vincent: 未读数字角标): last-read moved sessionStorage →\n// localStorage so read state survives refresh/new tabs/restart (微信预期).\n// One-time migration pulls any old session value forward.\nconst BASELINE_KEY = '__baseline';\n\nfunction readStoredMap(networkId: string): ReadMap {\n if (typeof window === 'undefined') return {};\n try {\n let raw = window.localStorage.getItem(storageKey(networkId));\n if (!raw) {\n raw = window.sessionStorage.getItem(storageKey(networkId));\n if (raw) window.localStorage.setItem(storageKey(networkId), raw);\n }\n const parsed = raw ? JSON.parse(raw) : {};\n const map: ReadMap = parsed && typeof parsed === 'object' ? parsed : {};\n // R8 first-visit floor, written SYNCHRONOUSLY on first read: an async\n // (useEffect) baseline lost the race against the first SWR render and\n // let a badge storm flash — and stick, since nothing re-triggered the\n // count. Ensuring it here means no compute can ever see a missing\n // baseline. No event dispatch: every hook instance does the same\n // idempotent write.\n if (!map[BASELINE_KEY]) {\n map[BASELINE_KEY] = new Date().toISOString();\n window.localStorage.setItem(storageKey(networkId), JSON.stringify(map));\n }\n return map;\n } catch {\n return {};\n }\n}\n\nfunction writeStoredMap(networkId: string, next: ReadMap) {\n if (typeof window === 'undefined') return;\n try {\n window.localStorage.setItem(storageKey(networkId), JSON.stringify(next));\n window.dispatchEvent(new CustomEvent(UNREAD_EVENT, { detail: { networkId } }));\n } catch {}\n}\n\nconst fetcher = async (url: string) => {\n const res = await fetch(url);\n if (res.status === 401) {\n window.location.assign('/login');\n throw new Error('unauthorized');\n }\n return res.json();\n};\n\nfunction withNetwork(url: string, networkId: string): string {\n if (!networkId) return url;\n const sep = url.includes('?') ? '&' : '?';\n return `${url}${sep}network_id=${encodeURIComponent(networkId)}`;\n}\n\nexport function markChatRead(alias: string, networkId: string) {\n if (!alias) return;\n const current = readStoredMap(networkId);\n writeStoredMap(networkId, {\n ...current,\n [alias]: new Date().toISOString(),\n });\n}\n\nexport function useChatUnread() {\n const { networkId } = useNetworkId();\n // Messages are the ONLY count source: the hub mirrors every task reply as\n // a message to the originator (verified live: replied task + same-second\n // message, both present), so counting tasks too double-counted every\n // reply (E2E showed 4 where 2 was right).\n const { data: messagesData } = useSWR<{ messages?: ChatMessage[] }>(\n withNetwork('/api/hub/messages?limit=200', networkId),\n fetcher,\n { refreshInterval: 5000, dedupingInterval: 3000 },\n );\n const [readVersion, setReadVersion] = useState(0);\n\n useEffect(() => {\n const onStorage = (event: StorageEvent) => {\n if (event.key && event.key !== storageKey(networkId)) return;\n setReadVersion((v) => (typeof v === 'number' ? v + 1 : 1));\n };\n const onUnreadUpdate = (event: Event) => {\n const detail = (event as CustomEvent<{ networkId?: string }>).detail;\n if (detail?.networkId !== undefined && detail.networkId !== networkId) return;\n setReadVersion((v) => (typeof v === 'number' ? v + 1 : 1));\n };\n window.addEventListener('storage', onStorage);\n window.addEventListener(UNREAD_EVENT, onUnreadUpdate);\n return () => {\n window.removeEventListener('storage', onStorage);\n window.removeEventListener(UNREAD_EVENT, onUnreadUpdate);\n };\n }, [networkId, setReadVersion]);\n\n const readMap = useMemo(() => {\n void readVersion;\n return readStoredMap(networkId);\n }, [networkId, readVersion]);\n\n const unreadMap = useMemo(() => {\n // R8: count EVERY unread item per alias (Vincent: \"有几条消息显示数字\"),\n // not just a latest-activity boolean. A message from the alias counts;\n // a task's REPLY counts once when it lands after last-read. Self-sent\n // items never count (they're keyed by the counterpart alias).\n const counts = new Map<string, number>();\n // R28 (微信排序): recency tiebreak for Overview/Nodes — but ONLY for\n // conversations the user has actually OPENED (read-map entry). On this\n // fleet agents constantly report to 'admin'; counting those yanked\n // never-opened agents to the front on every report (measured: 2 cards\n // jumped 39→1 / 60→3 in one 6s window). WeChat's list holds YOUR\n // conversations — same rule here keeps the grid calm.\n const lastActivity = new Map<string, number>();\n const opened = new Set(Object.keys(readMap).filter((k) => k !== BASELINE_KEY));\n const baseline = parseHubTime(readMap[BASELINE_KEY]);\n const bump = (alias: string, at: number) => {\n if (opened.has(alias) && at > (lastActivity.get(alias) || 0)) lastActivity.set(alias, at);\n const readAt = Math.max(parseHubTime(readMap[alias]), baseline);\n if (at > readAt) counts.set(alias, (counts.get(alias) || 0) + 1);\n };\n // Scope: only the USER'S conversation — a badge on X means \"X has\n // something FOR YOU\". Fleet chatter (X's messages to other agents)\n // must NOT inflate it.\n for (const message of messagesData?.messages || []) {\n const alias = message.from_alias?.trim();\n if (!alias || isUserish(alias)) continue; // own sends never count\n if (!isUserish(message.to_alias)) continue; // must be addressed to the user\n const at = parseHubTime(message.created_at);\n if (at) bump(alias, at);\n }\n return { counts, lastActivity };\n }, [messagesData, readMap]);\n\n const hasUnread = useCallback((alias?: string | null) => {\n if (!alias) return false;\n return (unreadMap.counts.get(alias) || 0) > 0;\n }, [unreadMap]);\n\n const unreadCount = useCallback((alias?: string | null) => {\n if (!alias) return 0;\n return unreadMap.counts.get(alias) || 0;\n }, [unreadMap]);\n\n const lastActivityAt = useCallback((alias?: string | null) => {\n if (!alias) return 0;\n return unreadMap.lastActivity.get(alias) || 0;\n }, [unreadMap]);\n\n // R34: muted conversations are excluded from the global count (WeChat\n // semantics); hasMutedUnread lets entry badges fall back to a dot.\n const muteVersion = useMuteVersion();\n const { totalUnread, hasMutedUnread } = useMemo(() => {\n void muteVersion;\n let t = 0;\n let mutedAny = false;\n for (const [alias, n] of unreadMap.counts) {\n if (isMuted(alias)) { if (n > 0) mutedAny = true; continue; }\n t += n;\n }\n return { totalUnread: t, hasMutedUnread: mutedAny };\n }, [unreadMap, muteVersion]);\n\n const clearUnread = useCallback((alias: string) => {\n markChatRead(alias, networkId);\n }, [networkId]);\n\n return { unreadMap, hasUnread, unreadCount, lastActivityAt, totalUnread, hasMutedUnread, clearUnread };\n}\n\n/** WeChat badge label: 1-99 as-is, above → \"99+\"; 0/negative → '' (hide). */\nexport function badgeLabel(n: number): string {\n if (n <= 0) return '';\n return n > 99 ? '99+' : String(n);\n}\n","'use client';\n\nimport { useSyncExternalStore } from 'react';\n\n/* Loop R34 (微信消息免打扰, 克制版): per-conversation mute. Muted\n * conversations keep their red badge but show a DOT instead of the count,\n * and their unreads are excluded from the global total (WeChat semantics).\n * Same storage/reactivity pattern as chat-drafts. */\n\nconst STORE_KEY = 'anet_chat_mute_v1';\nconst MUTE_EVENT = 'anet-chat-mute-updated';\n\nfunction readSet(): Set<string> {\n if (typeof window === 'undefined') return new Set();\n try {\n const parsed = JSON.parse(window.localStorage.getItem(STORE_KEY) || '[]');\n return new Set(Array.isArray(parsed) ? parsed : []);\n } catch {\n return new Set();\n }\n}\n\nexport function isMuted(alias?: string | null): boolean {\n if (!alias) return false;\n return readSet().has(alias);\n}\n\nexport function toggleMute(alias: string) {\n if (typeof window === 'undefined' || !alias) return;\n try {\n const s = readSet();\n if (s.has(alias)) s.delete(alias);\n else s.add(alias);\n window.localStorage.setItem(STORE_KEY, JSON.stringify([...s]));\n window.dispatchEvent(new Event(MUTE_EVENT));\n } catch {}\n}\n\nlet version = 0;\nfunction subscribe(callback: () => void) {\n const bump = () => { version++; callback(); };\n window.addEventListener(MUTE_EVENT, bump);\n window.addEventListener('storage', bump);\n return () => {\n window.removeEventListener(MUTE_EVENT, bump);\n window.removeEventListener('storage', bump);\n };\n}\n\nexport function useMuted(alias?: string | null): boolean {\n return useSyncExternalStore(subscribe, () => (alias ? isMuted(alias) : false), () => false);\n}\n\n/** Monotonic version for callers that use plain isMuted() inside render\n * loops (map callbacks can't call hooks). */\nexport function useMuteVersion(): number {\n return useSyncExternalStore(subscribe, () => version, () => 0);\n}\n","'use client';\n\nimport { useEffect } from 'react';\n\n// #217 S6 — verified themes: cyber (dark), light (white), and slack\n// (Vincent 2026-07-16 via api channel: \"其他的就搞成那种 Slack 方式吧…快速搞一个\"\n// — Slack-style is now the DEFAULT look; the network/topology page keeps its\n// showcase visuals, see TopoGraph's data-skin exemption).\n//\n// Mechanism: `slack` is implemented as a SKIN on top of the light theme —\n// applyTheme sets `data-theme=\"light\"` (so every existing light compat-shim\n// in globals.css applies unchanged) plus `data-skin=\"slack\"` which the\n// slack-only overrides key on (aubergine rail, Slack-blue accent, de-noise).\n// This keeps the fast first version to globals.css + three tiny component\n// touches instead of a full hex→token sweep (that sweep stays scheduled as\n// redesign Phase 0 next version).\n\nexport const THEMES = new Set(['cyber', 'light', 'slack']);\n\n/** Apply a theme choice to <html>. Single owner of the data-theme/data-skin\n * contract — Settings and Cmd+K call this too, so the skin attribute can\n * never desync from the theme attribute. */\nexport function applyTheme(t: string) {\n if (typeof document === 'undefined') return;\n const el = document.documentElement;\n if (t === 'slack') {\n el.setAttribute('data-theme', 'light');\n el.setAttribute('data-skin', 'slack');\n } else {\n el.setAttribute('data-theme', t);\n el.removeAttribute('data-skin');\n }\n}\n\nexport function ThemeProvider({ children }: { children: React.ReactNode }) {\n useEffect(() => {\n if (typeof document === 'undefined') return;\n // ROLLBACK (Vincent 07-20): the classic dark theme is the default again\n // — he prefers the original look and doesn't want a Slack copy as the\n // face of the product. 'slack' stays available as an explicit Settings\n // choice until the original agent-network theme replaces it. Users who\n // explicitly picked a theme keep their pick; everyone else returns to\n // cyber automatically (the slack-default window never wrote storage).\n let t = 'cyber';\n try {\n const saved = localStorage.getItem('anet-theme');\n if (saved && THEMES.has(saved)) t = saved;\n } catch {}\n applyTheme(t);\n }, []);\n return <>{children}</>;\n}\n","'use client';\n\nimport { useEffect, useState } from 'react';\nimport useSWR from 'swr';\n\n/** Issue #119 — server-side panel listing the hub's hosts + CPU/RAM bars.\n *\n * Steps 1+2 (SDK马 host telemetry + CommHub aggregation) shipped with\n * commhub-server v0.8.1-preview.2. Step 3 (this file, Round 20 of the\n * dashboard /loop) swaps the original mock seed for a SWR fetch of\n * `/api/hub/servers` (which proxies to the hub's `/api/servers`).\n *\n * Collapsed by default to a thin vertical icon strip so it never competes\n * with the topology graph for horizontal real-estate. State persists to\n * localStorage just like the other dashboard drawers.\n *\n * Backward-compat: if the upstream hub predates v0.8.1-preview.2 the\n * proxy returns `{ servers: [], unavailable: true }`. The drawer\n * surfaces a friendly \"not yet available\" hint instead of an empty list,\n * so old hubs don't read as \"something broke\".\n */\n\ninterface ServerAgent {\n alias: string;\n runtime: string | null;\n status: 'working' | 'idle' | 'offline';\n last_seen_at?: string | null;\n progress?: number | null; // 0..1\n}\n\ninterface ServerCard {\n hostname: string;\n ip?: string | null;\n cpu_load_1min: number | null;\n cpu_cores: number;\n mem_used_gb: number | null;\n mem_total_gb: number | null;\n /** Hero 1 v0.10.0: disk usage. Optional — older hubs don't report. */\n disk_used_gb?: number | null;\n disk_total_gb?: number | null;\n /** Hero 1 v0.10.0: short history for sparklines (5-min sliding window).\n * Each is the rolling 1-min average sampled at ~30s cadence (so ~10\n * data points for 5-min). Optional — older hubs don't report. */\n cpu_history?: number[];\n mem_history?: number[];\n /** v0.10.2 RFC-014 — disk usage 5-min rolling history. Optional;\n * older agent-node (< 2.4.1-preview.0) doesn't ship it. */\n disk_history?: number[];\n /** Hero 2 v0.10.0: per-server agent rollup. Optional — older hubs\n * send only aggregate agent_count. */\n agents?: ServerAgent[];\n agent_count: number;\n status: 'online' | 'offline';\n note?: string;\n}\n\ninterface ServersResponse {\n servers: ServerCard[];\n unavailable?: boolean;\n}\n\nconst fetcher = async (url: string): Promise<ServersResponse> => {\n const res = await fetch(url);\n if (res.status === 401) {\n if (typeof window !== 'undefined') window.location.assign('/login');\n throw new Error('unauthorized');\n }\n if (!res.ok) throw new Error(`hub ${res.status}`);\n return res.json();\n};\n\n// Bar tint by usage — green ≤60%, amber 60–85%, red >85%. Keeps the eye\n// going to whichever box is actually about to tip over.\nfunction barTint(pct: number) {\n if (pct >= 85) return { fill: '#ef4444', track: 'rgb(239 68 68 / 0.16)' };\n if (pct >= 60) return { fill: '#f59e0b', track: 'rgb(245 158 11 / 0.16)' };\n return { fill: '#10b981', track: 'rgb(16 185 129 / 0.16)' };\n}\n\nfunction Bar({ pct, label }: { pct: number; label: string }) {\n const t = barTint(pct);\n const clamped = Math.max(0, Math.min(100, pct));\n return (\n <div className=\"space-y-0.5\">\n <div className=\"flex justify-between text-[10px] text-[var(--fg-muted)] font-mono\">\n <span>{label}</span>\n <span className=\"tabular-nums\">{Math.round(clamped)}%</span>\n </div>\n <div className=\"h-1.5 rounded-full overflow-hidden\" style={{ background: t.track }}>\n <div\n className=\"h-full transition-[width] duration-300 ease-out\"\n style={{ width: `${clamped}%`, background: t.fill }}\n />\n </div>\n </div>\n );\n}\n\n/** Hero 1 v0.10.0 — inline SVG sparkline for 5-min rolling history.\n * Zero-dep (no recharts). Renders a stroked polyline + filled area.\n * Values are percentages (0..100); clamps inside. */\nfunction Sparkline({ values, tint, label }: { values: number[]; tint: string; label: string }) {\n if (!values || values.length < 2) return null;\n const w = 100, h = 18;\n const max = 100;\n const stride = w / Math.max(1, values.length - 1);\n const pts = values.map((v, i) => {\n const x = i * stride;\n const y = h - (Math.max(0, Math.min(max, v)) / max) * h;\n return `${x.toFixed(1)},${y.toFixed(1)}`;\n });\n const polyline = pts.join(' ');\n const area = `M0,${h} L${pts.join(' L')} L${w},${h} Z`;\n return (\n <svg\n width=\"100%\" height={h} viewBox={`0 0 ${w} ${h}`}\n preserveAspectRatio=\"none\" aria-label={`${label} 5-min history`}\n data-server-sparkline={label}\n >\n <path d={area} fill={tint} opacity=\"0.18\" />\n <polyline points={polyline} fill=\"none\" stroke={tint} strokeWidth=\"1.2\" />\n </svg>\n );\n}\n\n/** Hero 1 v0.10.0 — single health badge derived from the worst of\n * CPU / Mem / Disk percentages. Green ≤60%, amber 60-85%, red >85%\n * (same thresholds as Bar). Returns null when no percentages available\n * (e.g. offline server) so the card layout reads \"n/a · offline\" instead. */\nfunction HealthBadge({ cpu, mem, disk }: { cpu: number | null; mem: number | null; disk: number | null }) {\n const vals = [cpu, mem, disk].filter((v): v is number => typeof v === 'number');\n if (vals.length === 0) return null;\n const worst = Math.max(...vals);\n const t = barTint(worst);\n const status = worst >= 85 ? 'red' : worst >= 60 ? 'amber' : 'green';\n return (\n <span\n className=\"inline-block w-2 h-2 rounded-full shrink-0\"\n style={{ background: t.fill, boxShadow: `0 0 0 2px ${t.track}` }}\n data-server-health-badge={status}\n title={`worst: ${Math.round(worst)}%`}\n />\n );\n}\n\n/** Hero 2 v0.10.0 — per-server expandable agent list. Renders compact\n * rows: alias · runtime · status chip · last_seen relative. progress\n * bar appears when an agent reports progress (0..1). When the upstream\n * hub doesn't report agents[], the row falls through to a small\n * \"agent list pending hub upgrade\" hint. */\nfunction AgentList({ agents }: { agents?: ServerAgent[] }) {\n if (!agents || agents.length === 0) {\n return (\n <div className=\"text-[9px] text-[var(--fg-dim)] font-mono italic px-1 py-1\" data-server-agents-missing=\"true\">\n {/* #157 fix — copy update. Pre-#157 the placeholder read\n \"agent rollup pending hub ≥ 0.8.2-preview\". commhub-server@\n 0.8.2 is LIVE in prod (Vincent screenshot 5560 verified) but\n still doesn't ship `agents[]`. Version-specific text was\n misleading — implied upgrade-needed when hub already\n crossed the threshold. New copy drops the version pinning\n and just states the data-shape: hub hasn't reported the\n agent rollup for this server (could be hub-side feature\n gap or session-source gap). data-server-agents-missing\n attr surfaces the gate for tests. */}\n agent rollup not reported by hub\n </div>\n );\n }\n return (\n <ul className=\"space-y-1\" data-server-agent-list>\n {agents.map(a => {\n const statusColor =\n a.status === 'working' ? '#10b981' :\n a.status === 'idle' ? '#06b6d4' : '#6b7280';\n return (\n <li\n key={a.alias}\n className=\"flex items-center gap-1.5 text-[10px] font-mono\"\n data-server-agent={a.alias}\n >\n <span className=\"w-1.5 h-1.5 rounded-full shrink-0\" style={{ background: statusColor }} />\n <span className=\"font-semibold truncate\" style={{ color: 'var(--fg)' }}>{a.alias}</span>\n {a.runtime && (\n <span className=\"text-[9px] text-[var(--fg-dim)] shrink-0\">· {a.runtime}</span>\n )}\n {typeof a.progress === 'number' && a.progress > 0 && (\n <span className=\"ml-auto text-[9px] tabular-nums text-[var(--fg-muted)]\">\n {Math.round(a.progress * 100)}%\n </span>\n )}\n </li>\n );\n })}\n </ul>\n );\n}\n\nfunction useServers(enabled = true) {\n const { data, error } = useSWR<ServersResponse>(\n enabled ? '/api/hub/servers' : null,\n fetcher,\n { refreshInterval: 5000, dedupingInterval: 3000 },\n );\n const servers = data?.servers ?? [];\n const unavailable = data?.unavailable === true;\n const onlineCount = servers.filter(s => s.status === 'online').length;\n const loading = enabled && !data && !error;\n return { data, error, servers, unavailable, onlineCount, loading };\n}\n\nexport function ServersPanel({ enabled = true, className = '' }: { enabled?: boolean; className?: string }) {\n const [expanded, setExpanded] = useState<Set<string>>(new Set());\n useEffect(() => {\n try {\n const raw = localStorage.getItem('anet-servers-drawer-expanded');\n // Expanded server rows are a client-only sticky preference; hydrate once\n // after mount so SSR stays deterministic.\n // eslint-disable-next-line react-hooks/set-state-in-effect\n if (raw) setExpanded(new Set(JSON.parse(raw)));\n } catch {}\n }, []);\n const toggleExpanded = (hostname: string) => setExpanded(prev => {\n const next = new Set(prev);\n if (next.has(hostname)) next.delete(hostname); else next.add(hostname);\n try { localStorage.setItem('anet-servers-drawer-expanded', JSON.stringify([...next])); } catch {}\n return next;\n });\n\n const { data, error, servers, unavailable, loading } = useServers(enabled);\n\n return (\n <div className={`min-h-0 overflow-y-auto px-2 py-2 space-y-2 ${className}`} data-servers-body>\n {loading && (\n <div className=\"text-[10px] text-[var(--fg-muted)] font-mono text-center py-4\">\n loading servers…\n </div>\n )}\n {error && !data && (\n <div className=\"rounded-md border px-2.5 py-2 text-[10px] font-mono\"\n style={{ background: 'rgb(239 68 68 / 0.06)', borderColor: 'rgb(239 68 68 / 0.25)', color: '#ef4444' }}>\n hub unreachable · retrying every 5s\n </div>\n )}\n {unavailable && (\n <div className=\"text-[10px] text-[var(--fg-muted)] font-mono text-center py-3 leading-relaxed\">\n host telemetry not available<br/>\n <span className=\"text-[var(--fg-dim)]\">upgrade commhub-server ≥ 0.8.1-preview.2</span>\n </div>\n )}\n {!loading && !error && !unavailable && servers.length === 0 && (\n <div className=\"text-[10px] text-[var(--fg-muted)] font-mono text-center py-4\">\n no servers reporting yet\n </div>\n )}\n {servers.map(s => {\n const offline = s.status === 'offline';\n const cpuPct = s.cpu_load_1min != null && s.cpu_cores > 0 ? (s.cpu_load_1min / s.cpu_cores) * 100 : null;\n const memPct = s.mem_used_gb != null && s.mem_total_gb != null && s.mem_total_gb > 0 ? (s.mem_used_gb / s.mem_total_gb) * 100 : null;\n const diskPct = s.disk_used_gb != null && s.disk_total_gb != null && s.disk_total_gb > 0 ? (s.disk_used_gb / s.disk_total_gb) * 100 : null;\n const isExpanded = expanded.has(s.hostname);\n return (\n <div\n key={s.hostname}\n className=\"rounded-lg border px-2.5 py-2 space-y-1.5\"\n style={{\n background: 'var(--bg)',\n borderColor: 'var(--border)',\n opacity: offline ? 0.55 : 1,\n }}\n data-server-card={s.hostname}\n data-server-expanded={isExpanded ? 'true' : 'false'}\n title={s.ip ? `${s.hostname} · ${s.ip}` : s.hostname}\n >\n {/* v0.10.0 Hero 1+2: header row — click toggles expanded\n detail view (sparklines + disk + agent rollup). */}\n <button\n type=\"button\"\n onClick={() => toggleExpanded(s.hostname)}\n aria-expanded={isExpanded}\n className=\"w-full flex items-center justify-between gap-2 text-left\"\n data-server-card-toggle={s.hostname}\n >\n <div className=\"min-w-0 flex items-center gap-1.5\">\n {/* Hero 1 health badge — worst-of CPU/Mem/Disk */}\n {!offline && <HealthBadge cpu={cpuPct} mem={memPct} disk={diskPct} />}\n <span className=\"font-mono text-[12px] font-semibold truncate\" style={{ color: 'var(--fg)' }}>{s.hostname}</span>\n {s.note && <span className=\"text-[9px] text-[var(--fg-dim)]\">({s.note})</span>}\n </div>\n <span className=\"flex items-center gap-1 shrink-0\">\n <span className=\"text-[10px] text-[var(--fg-muted)] font-mono tabular-nums\">\n {s.agent_count}&nbsp;agent{s.agent_count === 1 ? '' : 's'}\n </span>\n {/* Chevron — rotates 90° on expanded */}\n <svg\n width=\"10\" height=\"10\" viewBox=\"0 0 10 10\"\n style={{ transform: isExpanded ? 'rotate(90deg)' : 'rotate(0deg)', transition: 'transform 150ms ease-out' }}\n aria-hidden\n >\n <path d=\"M3 1.5L7 5L3 8.5\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </span>\n </button>\n {!offline && cpuPct != null && (\n <Bar pct={cpuPct} label={`CPU ${s.cpu_load_1min!.toFixed(2)}/${s.cpu_cores}`} />\n )}\n {!offline && memPct != null && (\n <Bar pct={memPct} label={`RAM ${s.mem_used_gb!.toFixed(1)}/${s.mem_total_gb!.toFixed(1)}G`} />\n )}\n {offline && (\n <div className=\"text-[10px] text-[var(--fg-dim)] font-mono italic\">CPU n/a · RAM n/a · offline</div>\n )}\n {/* v0.10.0 Hero 1+2: expanded detail — disk bar +\n 5-min sparklines + agent rollup. Visible only when\n the user clicks the card. Renders gracefully when\n upstream hub hasn't shipped optional fields. */}\n {isExpanded && !offline && (\n <div className=\"pt-1 mt-1 border-t space-y-1.5\" style={{ borderColor: 'var(--border)' }}>\n {diskPct != null ? (\n <Bar pct={diskPct} label={`DISK ${s.disk_used_gb!.toFixed(1)}/${s.disk_total_gb!.toFixed(1)}G`} />\n ) : (\n /* #157 sibling fix — same misleading version-pin copy\n dropped at the disk-metric placeholder. Same\n rationale as the agent-rollup copy above. */\n <div className=\"text-[9px] text-[var(--fg-dim)] font-mono italic\" data-server-disk-missing=\"true\">disk metric not reported by hub</div>\n )}\n {s.cpu_history && s.cpu_history.length >= 2 && (\n <div className=\"space-y-0.5\">\n <div className=\"text-[9px] text-[var(--fg-muted)] font-mono\">CPU · 5-min</div>\n <Sparkline values={s.cpu_history} tint=\"#10b981\" label=\"CPU\" />\n </div>\n )}\n {s.mem_history && s.mem_history.length >= 2 && (\n <div className=\"space-y-0.5\">\n <div className=\"text-[9px] text-[var(--fg-muted)] font-mono\">RAM · 5-min</div>\n <Sparkline values={s.mem_history} tint=\"#06b6d4\" label=\"MEM\" />\n </div>\n )}\n {/* v0.10.2 RFC-014 §7 close gate #3 — disk usage\n 5-min curve. Amber tint matches the disk bar\n tier convention (DISK > CPU/Mem in alert-\n priority hierarchy since disk-full is a hard\n failure mode). Render only when agent-node\n 2.4.1-preview.0+ has shipped disk_history;\n backward-compat handles older agents silently\n (no sparkline, no broken state). */}\n {s.disk_history && s.disk_history.length >= 2 && (\n <div className=\"space-y-0.5\">\n <div className=\"text-[9px] text-[var(--fg-muted)] font-mono\">DISK · 5-min</div>\n <Sparkline values={s.disk_history} tint=\"#f59e0b\" label=\"DISK\" />\n </div>\n )}\n <div className=\"pt-1\">\n <div className=\"text-[9px] text-[var(--fg-muted)] font-mono mb-0.5\">agents</div>\n <AgentList agents={s.agents} />\n </div>\n </div>\n )}\n </div>\n );\n })}\n {servers.length > 0 && (\n <div className=\"pt-1 text-[9px] text-[var(--fg-dim)] font-mono text-center\">\n live · refreshing every 5s\n </div>\n )}\n </div>\n );\n}\n\nexport function ServersDrawer() {\n const [open, setOpen] = useState(false);\n // Drawer state is per-user-machine — persist like the other dashboard\n // sticky toggles (`anet-topo-layout`, `anet-topo-view`, etc.).\n useEffect(() => {\n // Drawer openness is persisted in localStorage and can only be restored on\n // the client after mount.\n // eslint-disable-next-line react-hooks/set-state-in-effect\n try { if (localStorage.getItem('anet-servers-drawer') === '1') setOpen(true); } catch {}\n }, []);\n const toggle = () => setOpen(prev => {\n const next = !prev;\n try { localStorage.setItem('anet-servers-drawer', next ? '1' : '0'); } catch {}\n return next;\n });\n\n // Round 20 / #119 step 3 final delivery — real SWR fetch. 5s refresh\n // matches the other live drawers (HealthBanner, Sidebar) so an operator\n // sees host telemetry update in roughly the same beat as session state.\n // Only poll while expanded — collapsed icon strip doesn't need fresh data.\n const { servers, onlineCount } = useServers(open);\n\n return (\n <aside\n className=\"fixed right-0 top-20 z-40 hidden lg:flex flex-col rounded-l-xl border border-r-0 shadow-xl shadow-black/30 anet-fade-in\"\n style={{\n background: 'var(--bg-secondary)',\n borderColor: 'var(--border)',\n width: open ? 296 : 40,\n maxHeight: 'calc(100vh - 6rem)',\n transition: 'width 200ms ease-out',\n }}\n aria-label=\"Servers panel\"\n >\n <button\n onClick={toggle}\n aria-expanded={open}\n aria-label={open ? 'Collapse servers panel' : 'Expand servers panel'}\n className=\"flex items-center gap-2 px-2.5 py-2 border-b text-[11px] font-semibold tracking-wide select-none\"\n style={{ color: 'var(--fg)', borderColor: 'var(--border)' }}\n >\n <svg className=\"w-4 h-4 shrink-0\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"6\" rx=\"1.5\" />\n <rect x=\"3\" y=\"14\" width=\"18\" height=\"6\" rx=\"1.5\" />\n <circle cx=\"7\" cy=\"7\" r=\"0.7\" fill=\"currentColor\" />\n <circle cx=\"7\" cy=\"17\" r=\"0.7\" fill=\"currentColor\" />\n </svg>\n {open && (\n <>\n <span className=\"flex-1 text-left\">Servers</span>\n <span className=\"text-[10px] text-[var(--fg-muted)] font-mono\">{onlineCount}/{servers.length}</span>\n </>\n )}\n </button>\n\n {open && (\n <ServersPanel enabled={open} className=\"flex-1\" />\n )}\n </aside>\n );\n}\n"],"names":["process","env","NEXT_RUNTIME","module","exports","require","__NEXT_EXPERIMENTAL_REACT","NODE_ENV","TURBOPACK","vendored","ReactJsxRuntime","React","AppRouterContext","ReactServerDOMTurbopackClient","HooksClientContext","ServerInsertedHtml","parseHubTime","dateStr","iso","includes","replace","t","Date","parse","Number","isFinite","relativeAgo","s","Math","floor","now","formatWeChatTime","value","d","zh","navigator","language","toLowerCase","startsWith","hm","String","getHours","padStart","getMinutes","startOfDay","x","getFullYear","getMonth","getDate","getTime","dayDiff","round","wd","Intl","DateTimeFormat","undefined","weekday","format","md","month","day","year","NetworkContext","networkId","setNetworkId","NetworkProvider","children","saved","sessionStorage","getItem","setAndPersist","id","setItem","Provider","useNetworkId","STORE_KEY","MUTE_EVENT","readSet","Set","isMuted","alias","has","toggleMute","version","subscribe","callback","bump","window","addEventListener","removeEventListener","useMuted","useMuteVersion","THEMES","applyTheme","document","el","documentElement","setAttribute","removeAttribute","ThemeProvider","localStorage","fetcher","url","res","fetch","status","Error","ok","json","barTint","pct","fill","track","Bar","label","clamped","max","min","className","style","background","width","Sparkline","values","tint","length","w","h","stride","pts","map","v","i","y","toFixed","polyline","join","area","height","viewBox","preserveAspectRatio","opacity","points","stroke","strokeWidth","HealthBadge","cpu","mem","disk","vals","filter","worst","boxShadow","title","AgentList","agents","a","statusColor","color","runtime","progress","useServers","enabled","data","error","refreshInterval","dedupingInterval","servers","unavailable","onlineCount","loading","ServersPanel","expanded","setExpanded","raw","JSON","toggleExpanded","hostname","prev","next","delete","add","stringify","borderColor","offline","cpuPct","cpu_load_1min","cpu_cores","memPct","mem_used_gb","mem_total_gb","diskPct","disk_used_gb","disk_total_gb","isExpanded","ip","type","onClick","note","agent_count","transform","transition","strokeLinecap","strokeLinejoin","cpu_history","mem_history","disk_history","ServersDrawer","open","setOpen","toggle","maxHeight","rx","cx","cy","r"],"mappings":"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","ignoreList":[0,1,2,3,4,5,6]}
@@ -1,3 +0,0 @@
1
- module.exports=[50227,(a,b,c)=>{b.exports=a.x("node:path",()=>require("node:path"))},99462,a=>{"use strict";var b=a.i(98005);a.s(["previewContent",0,function(a){return a&&a.replace(/!\[([^\]]*)\]\([^)]*\)/g,"$1").replace(/\[([^\]]+)\]\([^)]*\)/g,"$1").replace(/`([^`]+)`/g,"$1").replace(/\s+/g," ").trim()||"--"},"timeAgo",0,function(a){return(0,b.relativeAgo)(a)??"--"}])},72405,12180,a=>{"use strict";var b=a.i(5400),c=a.i(82956);let d="anet-avatars-updated",e=[];function f(a){return a&&(({})[a]||function(a){if(!e.length)return"";let b=5381;for(let c=0;c<a.length;c++)b=(b<<5)+b+a.charCodeAt(c)>>>0;return e[b%e.length]}(a))||""}let g=0;function h(a){let b=()=>{g++,a()};return window.addEventListener(d,b),window.addEventListener("storage",b),()=>{window.removeEventListener(d,b),window.removeEventListener("storage",b)}}function i(a){return(0,c.useSyncExternalStore)(h,()=>f(a),()=>"")}a.s(["getAvatarUrl",0,f,"setAvatarUrl",0,function(a,b){},"useAvatarUrl",0,i,"useAvatarsVersion",0,function(){return(0,c.useSyncExternalStore)(h,()=>g,()=>0)}],12180);let j=[180,200,220,270,300,330,30,90];function k(a){let b=0;for(let c=0;c<a.length;c++)b=31*b+a.charCodeAt(c)>>>0;let c=j[b%j.length];return{bg:`hsl(${c} 55% 22%)`,ring:`hsl(${c} 60% 45%)`,text:`hsl(${c} 80% 78%)`}}function l(a){return a?(a.trim().match(/[\p{L}\p{N}]/u)?.[0]||a.trim()[0]||"·").toUpperCase():"·"}a.s(["AliasAvatar",0,function({alias:a,size:d=28,className:e=""}){let f=i(a),[g,h]=(0,c.useState)("loading"),[j,m]=(0,c.useState)(f);if(f!==j&&(m(f),h("loading")),f&&"error"!==g)return(0,b.jsx)("span",{className:`anet-alias-avatar relative inline-flex shrink-0 overflow-hidden rounded-full border border-[var(--border)] ${"loading"===g?"animate-pulse bg-[var(--bg-elevated)]":""} ${e}`,style:{width:d,height:d},title:a,"aria-hidden":!0,children:(0,b.jsx)("img",{src:f,alt:"",loading:"lazy",onLoad:()=>h("ready"),onError:()=>h("error"),className:`h-full w-full rounded-full object-cover transition-opacity duration-150 ${"ready"===g?"opacity-100":"opacity-0"}`})});if(/\bgrok\b|grok-build|grok测试员|grok-demo/i.test(a))return(0,b.jsx)("span",{className:`anet-alias-avatar inline-flex items-center justify-center rounded-full border border-emerald-500/45 bg-emerald-950/70 shrink-0 ${e}`,style:{width:d,height:d,backgroundImage:"url(/vendors/grok.svg)",backgroundPosition:"center",backgroundRepeat:"no-repeat",backgroundSize:"68% 68%"},title:a,"aria-hidden":!0});let n=k(a),o=Math.max(9,Math.round(.42*d));return(0,b.jsx)("span",{className:`anet-alias-avatar inline-flex items-center justify-center rounded-full border shrink-0 font-semibold ${e}`,style:{width:d,height:d,fontSize:o,backgroundColor:n.bg,borderColor:n.ring,color:n.text},title:a,"aria-hidden":!0,children:l(a)})},"aliasAvatarColors",0,k,"aliasInitial",0,l],72405)},99038,a=>{"use strict";var b=a.i(5400),c=a.i(82956),d=a.i(66860);let e={nodes:{title:"No agents in this network",sub:"Agent sessions will appear here once they connect to the CommHub."},tasks:{title:"No tasks yet",sub:"Tasks will appear here when agents send them via CommHub."},messages:{title:"No messages",sub:"Messages between agents will appear here."},logs:{title:"No audit logs",sub:"Events will appear here when users register, login, or perform actions."},tokens:{title:"No API tokens",sub:"Create one to authenticate CLI tools and external integrations."},networks:{title:"No networks found",sub:"Create one or sign in with V3 auth to see your networks."},generic:{title:"Nothing here yet",sub:"Data will appear here once available."}};function f({variant:a,size:c}){let d={width:c,height:c},e={fill:"none",stroke:"currentColor",strokeWidth:1.25,strokeLinecap:"round",strokeLinejoin:"round"};switch(a){case"nodes":return(0,b.jsx)("svg",{viewBox:"0 0 64 64",...d,children:(0,b.jsxs)("g",{...e,children:[(0,b.jsx)("circle",{cx:"32",cy:"14",r:"4"}),(0,b.jsx)("circle",{cx:"14",cy:"44",r:"4"}),(0,b.jsx)("circle",{cx:"50",cy:"44",r:"4"}),(0,b.jsx)("line",{x1:"32",y1:"18",x2:"14",y2:"40",strokeDasharray:"3 3",opacity:"0.6"}),(0,b.jsx)("line",{x1:"32",y1:"18",x2:"50",y2:"40",strokeDasharray:"3 3",opacity:"0.6"}),(0,b.jsx)("line",{x1:"18",y1:"44",x2:"46",y2:"44",strokeDasharray:"3 3",opacity:"0.6"})]})});case"tasks":return(0,b.jsx)("svg",{viewBox:"0 0 64 64",...d,children:(0,b.jsxs)("g",{...e,children:[(0,b.jsx)("rect",{x:"14",y:"14",width:"36",height:"6",rx:"1.5"}),(0,b.jsx)("rect",{x:"14",y:"26",width:"36",height:"6",rx:"1.5",opacity:"0.6"}),(0,b.jsx)("rect",{x:"14",y:"38",width:"36",height:"6",rx:"1.5",opacity:"0.35"})]})});case"messages":return(0,b.jsx)("svg",{viewBox:"0 0 64 64",...d,children:(0,b.jsxs)("g",{...e,children:[(0,b.jsx)("path",{d:"M14 18 h36 a3 3 0 0 1 3 3 v18 a3 3 0 0 1 -3 3 h-18 l-8 6 v-6 h-10 a3 3 0 0 1 -3 -3 v-18 a3 3 0 0 1 3 -3 z"}),(0,b.jsx)("line",{x1:"22",y1:"28",x2:"42",y2:"28",opacity:"0.5"}),(0,b.jsx)("line",{x1:"22",y1:"34",x2:"36",y2:"34",opacity:"0.5"})]})});case"logs":return(0,b.jsx)("svg",{viewBox:"0 0 64 64",...d,children:(0,b.jsxs)("g",{...e,children:[(0,b.jsx)("path",{d:"M18 12 h22 l8 8 v32 a2 2 0 0 1 -2 2 h-28 a2 2 0 0 1 -2 -2 v-38 a2 2 0 0 1 2 -2 z"}),(0,b.jsx)("path",{d:"M40 12 v8 h8",opacity:"0.6"}),(0,b.jsx)("line",{x1:"24",y1:"32",x2:"40",y2:"32",opacity:"0.55"}),(0,b.jsx)("line",{x1:"24",y1:"38",x2:"40",y2:"38",opacity:"0.4"}),(0,b.jsx)("line",{x1:"24",y1:"44",x2:"34",y2:"44",opacity:"0.25"})]})});case"tokens":return(0,b.jsx)("svg",{viewBox:"0 0 64 64",...d,children:(0,b.jsxs)("g",{...e,children:[(0,b.jsx)("circle",{cx:"22",cy:"32",r:"8"}),(0,b.jsx)("line",{x1:"30",y1:"32",x2:"54",y2:"32"}),(0,b.jsx)("line",{x1:"44",y1:"32",x2:"44",y2:"38"}),(0,b.jsx)("line",{x1:"50",y1:"32",x2:"50",y2:"40"})]})});case"networks":return(0,b.jsx)("svg",{viewBox:"0 0 64 64",...d,children:(0,b.jsxs)("g",{...e,children:[(0,b.jsx)("circle",{cx:"32",cy:"32",r:"18"}),(0,b.jsx)("ellipse",{cx:"32",cy:"32",rx:"18",ry:"9",opacity:"0.55"}),(0,b.jsx)("line",{x1:"14",y1:"32",x2:"50",y2:"32",opacity:"0.55"}),(0,b.jsx)("line",{x1:"32",y1:"14",x2:"32",y2:"50",opacity:"0.55"})]})});default:return(0,b.jsx)("svg",{viewBox:"0 0 64 64",...d,children:(0,b.jsxs)("g",{...e,children:[(0,b.jsx)("circle",{cx:"32",cy:"32",r:"14",strokeDasharray:"3 3",opacity:"0.6"}),(0,b.jsx)("circle",{cx:"32",cy:"32",r:"3"})]})})}}function g({variant:a="generic",title:c,sub:h,cta:i,compact:j=!1}){let k=e[a],l=c??k.title,m=h??k.sub;return(0,b.jsxs)("div",{className:`text-center ${j?"py-8":"py-16"} px-4`,role:"status",children:[(0,b.jsx)("div",{className:"anet-empty-glyph inline-flex items-center justify-center mb-4 text-gray-500","aria-hidden":!0,children:(0,b.jsx)(f,{variant:a,size:j?40:56})}),(0,b.jsx)("h3",{className:`font-medium text-gray-300 ${j?"text-sm":"text-base"}`,children:l}),m&&(0,b.jsx)("p",{className:`text-gray-500 ${j?"text-xs mt-1.5":"text-sm mt-2"} max-w-md mx-auto leading-relaxed`,children:m}),i&&(0,b.jsx)("div",{className:"mt-4",children:i.href?(0,b.jsxs)(d.default,{href:i.href,className:"inline-flex items-center gap-1.5 text-sm font-medium text-cyan-400 hover:text-cyan-300",children:[i.label,(0,b.jsx)("span",{"aria-hidden":!0,children:"→"})]}):(0,b.jsxs)("button",{onClick:i.onClick,className:"inline-flex items-center gap-1.5 text-sm font-medium text-cyan-400 hover:text-cyan-300",children:[i.label,(0,b.jsx)("span",{"aria-hidden":!0,children:"→"})]})})]})}function h({children:a}){return(0,b.jsx)("div",{className:"max-w-2xl mx-auto rounded-xl border border-[#26262b] bg-[#161618] shadow-lg shadow-black/20",children:a})}function i({cmd:a}){let[d,e]=(0,c.useState)(!1),f=async()=>{try{await navigator.clipboard.writeText(a),e(!0),setTimeout(()=>e(!1),1800)}catch{}};return(0,b.jsxs)("div",{className:"anet-empty-cmd flex items-start sm:items-center gap-2 bg-[#0e0e10] border border-[#26262b] rounded-lg pl-4 pr-1.5 py-1.5 text-xs sm:text-sm",children:[(0,b.jsx)("code",{className:"text-cyan-300 font-mono select-all min-w-0 break-all sm:break-normal",children:a}),(0,b.jsx)("button",{type:"button",onClick:f,"aria-label":d?"Copied":"Copy command",className:"shrink-0 rounded-md px-2 py-1.5 text-[11px] text-gray-500 hover:text-gray-200 hover:bg-[#1c1c1f] transition-colors",children:d?(0,b.jsxs)("span",{className:"flex items-center gap-1 text-green-400",children:[(0,b.jsx)("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:(0,b.jsx)("path",{d:"M20 6 9 17l-5-5"})}),"Copied"]}):(0,b.jsxs)("span",{className:"flex items-center gap-1",children:[(0,b.jsxs)("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,b.jsx)("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),(0,b.jsx)("path",{d:"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"})]}),"Copy"]})})]})}a.s(["EmptyState",0,g,"NodesEmptyState",0,function({hint:a,taskHistoryCount:c=0}){return a?.global_count?(0,b.jsx)(h,{children:(0,b.jsx)(g,{variant:"nodes",title:"No agents in this network",sub:`Server has ${a.global_count} nodes globally, but none are registered to the current network. Switch network or contact admin.`})}):c>0?(0,b.jsx)(h,{children:(0,b.jsx)(g,{variant:"nodes",title:"No agents online",sub:`Every agent in this network is currently offline. ${c.toLocaleString()} task${1===c?"":"s"} in history — they may have finished their work or disconnected.`,cta:{label:"View task history",href:"/tasks"}})}):(0,b.jsx)(h,{children:(0,b.jsxs)("div",{className:"text-center py-16 px-4",role:"status",children:[(0,b.jsx)("div",{className:"anet-empty-glyph inline-flex items-center justify-center mb-4 text-gray-500","aria-hidden":!0,children:(0,b.jsx)("svg",{viewBox:"0 0 64 64",width:56,height:56,children:(0,b.jsxs)("g",{stroke:"currentColor",strokeWidth:"1.5",fill:"none",children:[(0,b.jsx)("rect",{x:"10",y:"20",width:"44",height:"28",rx:"2"}),(0,b.jsx)("rect",{x:"20",y:"32",width:"6",height:"8",opacity:"0.5"}),(0,b.jsx)("rect",{x:"32",y:"32",width:"6",height:"8",opacity:"0.5"}),(0,b.jsx)("rect",{x:"44",y:"32",width:"4",height:"8",opacity:"0.5"}),(0,b.jsx)("line",{x1:"10",y1:"26",x2:"54",y2:"26",opacity:"0.4"}),(0,b.jsx)("circle",{cx:"14",cy:"23",r:"0.8",fill:"currentColor"})]})})}),(0,b.jsx)("h3",{className:"font-medium text-gray-300 text-base",children:"Spin up your first agent"}),(0,b.jsx)("p",{className:"text-gray-500 text-sm mt-2 max-w-md mx-auto leading-relaxed",children:"Run this in a fresh terminal to register an agent with this CommHub:"}),(0,b.jsx)("div",{className:"mt-4 inline-block",children:(0,b.jsx)(i,{cmd:"npx --yes @sleep2agi/agent-network init"})}),(0,b.jsx)("p",{className:"text-gray-600 text-xs mt-3 max-w-md mx-auto",children:"Once the agent connects, it appears here automatically within a few seconds — no refresh needed."}),(0,b.jsx)("div",{className:"mt-3",children:(0,b.jsxs)("a",{href:"https://anet.sh",target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-1.5 text-xs font-medium text-gray-500 hover:text-cyan-300",children:["Full quickstart guide",(0,b.jsx)("span",{"aria-hidden":!0,children:"→"})]})})]})})}])},86176,a=>{"use strict";a.s(["DASHBOARD_VERSION",0,"0.6.3-preview.43"],86176)}];
2
-
3
- //# sourceMappingURL=%5Broot-of-the-server%5D__0qv41lg._.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../../../dash-492/agent-network-dashboard/app/components/utils.ts","../../../../../../dash-492/agent-network-dashboard/app/components/AliasAvatar.tsx","../../../../../../dash-492/agent-network-dashboard/app/lib/avatars.ts","../../../../../../dash-492/agent-network-dashboard/app/components/EmptyState.tsx","../../../../../../dash-492/agent-network-dashboard/package.json.%5Bjson%5D.mjs","../../../../../../dash-492/agent-network-dashboard/app/lib/version.ts"],"sourcesContent":["/** Round 82: strip the most common markdown markup from agent-to-agent\n * task / message bodies so single-line table previews read cleanly.\n * Full original content stays in the expanded row / drawer / title=. */\nexport function previewContent(raw: string | null | undefined): string {\n if (!raw) return '--';\n return raw\n .replace(/!\\[([^\\]]*)\\]\\([^)]*\\)/g, '$1') // images: ![alt](src) → alt\n .replace(/\\[([^\\]]+)\\]\\([^)]*\\)/g, '$1') // links: [text](href) → text\n .replace(/`([^`]+)`/g, '$1') // inline code: `x` → x\n .replace(/\\s+/g, ' ') // collapse whitespace\n .trim() || '--';\n}\n\n// Round 44 / Loop: timeAgo now delegates to the shared lib/time helper.\n// The old in-line `replace + 'Z'` parse appended a Z to already-ISO\n// inputs (producing \"…ZZ\", browser-fragile) — strict-superset semantics\n// preserved for SQL-style inputs, fixed for ISO. Plus a 'just now' fallback\n// when clock skew puts the timestamp in the future. Five callers benefit:\n// /admin · /logs · /settings/networks · InboxPanel · /messages.\nimport { relativeAgo } from '../lib/time';\nexport function timeAgo(dateStr: string): string {\n return relativeAgo(dateStr) ?? '--';\n}\n\nexport function statusColor(status: string, hasSse: boolean): string {\n if (hasSse && status === 'working') return 'bg-green-500';\n if (hasSse && status === 'idle') return 'bg-emerald-400';\n if (hasSse) return 'bg-blue-400';\n if (status === 'offline') return 'bg-gray-500';\n return 'bg-yellow-400';\n}\n","'use client';\n\nimport { useState } from 'react';\nimport { useAvatarUrl } from '../lib/avatars';\n\n/** Hue-hashed avatar pill for agent aliases. Same alias → same color across\n * every page (Messages, Nodes, TopoGraph). Use the `size` prop for inline\n * pills (16/20) vs card headers (28). Round 21 introduced the palette;\n * round 22 promotes it from app/messages to a shared component. */\n\nconst AVATAR_HUES = [180, 200, 220, 270, 300, 330, 30, 90];\n\nexport function aliasAvatarColors(alias: string): { bg: string; ring: string; text: string } {\n let h = 0;\n for (let i = 0; i < alias.length; i++) h = (h * 31 + alias.charCodeAt(i)) >>> 0;\n const hue = AVATAR_HUES[h % AVATAR_HUES.length];\n return {\n bg: `hsl(${hue} 55% 22%)`,\n ring: `hsl(${hue} 60% 45%)`,\n text: `hsl(${hue} 80% 78%)`,\n };\n}\n\nexport function aliasInitial(alias?: string): string {\n if (!alias) return '·';\n const ch = alias.trim().match(/[\\p{L}\\p{N}]/u)?.[0] || alias.trim()[0] || '·';\n return ch.toUpperCase();\n}\n\nfunction isGrokAlias(alias: string) {\n return /\\bgrok\\b|grok-build|grok测试员|grok-demo/i.test(alias);\n}\n\ninterface AliasAvatarProps {\n alias: string;\n size?: number;\n className?: string;\n}\n\nexport function AliasAvatar({ alias, size = 28, className = '' }: AliasAvatarProps) {\n // R24 (Vincent: 头像换血): a custom image (user-set or designed default)\n // wins over every generated style — ONE seam, all 13 avatar surfaces.\n // Shimmer while loading, silent fallback to the pill on error.\n const url = useAvatarUrl(alias);\n const [imgState, setImgState] = useState<'loading' | 'ready' | 'error'>('loading');\n // Reset when the url changes — React's endorsed adjust-during-render\n // pattern (no effect, no extra commit).\n const [prevUrl, setPrevUrl] = useState(url);\n if (url !== prevUrl) { setPrevUrl(url); setImgState('loading'); }\n if (url && imgState !== 'error') {\n return (\n <span\n className={`anet-alias-avatar relative inline-flex shrink-0 overflow-hidden rounded-full border border-[var(--border)] ${imgState === 'loading' ? 'animate-pulse bg-[var(--bg-elevated)]' : ''} ${className}`}\n style={{ width: size, height: size }}\n title={alias}\n aria-hidden\n >\n {/* eslint-disable-next-line @next/next/no-img-element */}\n <img\n src={url}\n alt=\"\"\n loading=\"lazy\"\n onLoad={() => setImgState('ready')}\n onError={() => setImgState('error')}\n className={`h-full w-full rounded-full object-cover transition-opacity duration-150 ${imgState === 'ready' ? 'opacity-100' : 'opacity-0'}`}\n />\n </span>\n );\n }\n if (isGrokAlias(alias)) {\n return (\n <span\n className={`anet-alias-avatar inline-flex items-center justify-center rounded-full border border-emerald-500/45 bg-emerald-950/70 shrink-0 ${className}`}\n style={{\n width: size,\n height: size,\n backgroundImage: 'url(/vendors/grok.svg)',\n backgroundPosition: 'center',\n backgroundRepeat: 'no-repeat',\n backgroundSize: '68% 68%',\n }}\n title={alias}\n aria-hidden\n />\n );\n }\n\n const c = aliasAvatarColors(alias);\n const fs = Math.max(9, Math.round(size * 0.42));\n return (\n <span\n className={`anet-alias-avatar inline-flex items-center justify-center rounded-full border shrink-0 font-semibold ${className}`}\n style={{\n width: size,\n height: size,\n fontSize: fs,\n backgroundColor: c.bg,\n borderColor: c.ring,\n color: c.text,\n }}\n title={alias}\n aria-hidden\n >\n {aliasInitial(alias)}\n </span>\n );\n}\n","'use client';\n\nimport { useSyncExternalStore } from 'react';\n\n/* Loop R24 (Vincent 亲点: 头像换血) — custom avatar infrastructure.\n *\n * Resolution order, per alias:\n * 1. user override — localStorage map, settable in the node settings UI\n * 2. designed default — /avatars/manifest.json (static, alias → image URL);\n * the design-side illustration set lands there later with ZERO code\n * change (drop files under public/avatars/ + list them in the manifest)\n * 3. shared pool — manifest \"_pool\": [\"/avatars/…\", …]; aliases without an\n * explicit entry get a stable hash-picked illustration from the pool\n * 4. '' → caller falls back to the hue-hashed initial pill\n *\n * Hub-side persistence (cross-device) needs an RFC-024 whitelist extension\n * (`avatar_url` is not an editable flag today — update would return\n * invalid_patch); when the hub grows it, hydrate the store from the hub here\n * without touching any consumer.\n */\n\nconst STORE_KEY = 'anet_avatars_v1';\nconst AVATAR_EVENT = 'anet-avatars-updated';\n\nlet manifest: Record<string, string> | null = null;\nlet pool: string[] = [];\nlet manifestRequested = false;\n\n/* Stable per-alias index so a given agent keeps the same pool avatar across\n * sessions/devices (djb2 over code units — no Math.random, no ordering). */\nfunction poolPick(alias: string): string {\n if (!pool.length) return '';\n let h = 5381;\n for (let i = 0; i < alias.length; i++) h = ((h << 5) + h + alias.charCodeAt(i)) >>> 0;\n return pool[h % pool.length];\n}\n\nfunction fetchManifestOnce() {\n if (manifestRequested || typeof window === 'undefined') return;\n manifestRequested = true;\n fetch('/avatars/manifest.json', { cache: 'no-cache' })\n .then((r) => (r.ok ? r.json() : null))\n .then((j) => {\n if (j && typeof j === 'object' && !Array.isArray(j)) {\n const clean: Record<string, string> = {};\n for (const [k, v] of Object.entries(j as Record<string, unknown>)) {\n if (k.startsWith('_')) continue; // meta keys (\"_pool\", …)\n if (typeof v === 'string' && v.startsWith('/')) clean[k] = v;\n }\n const rawPool = (j as Record<string, unknown>)._pool;\n pool = Array.isArray(rawPool)\n ? rawPool.filter((p): p is string => typeof p === 'string' && p.startsWith('/'))\n : [];\n manifest = clean;\n window.dispatchEvent(new Event(AVATAR_EVENT));\n }\n })\n .catch(() => {});\n}\n\nfunction readMap(): Record<string, string> {\n if (typeof window === 'undefined') return {};\n try {\n const parsed = JSON.parse(window.localStorage.getItem(STORE_KEY) || '{}');\n return parsed && typeof parsed === 'object' ? parsed : {};\n } catch {\n return {};\n }\n}\n\nexport function getAvatarUrl(alias?: string | null): string {\n if (!alias) return '';\n return readMap()[alias] || manifest?.[alias] || poolPick(alias) || '';\n}\n\n/** Empty/whitespace url removes the override (falls back to manifest/pill). */\nexport function setAvatarUrl(alias: string, url: string) {\n if (typeof window === 'undefined' || !alias) return;\n try {\n const m = readMap();\n if (url.trim()) m[alias] = url.trim();\n else delete m[alias];\n window.localStorage.setItem(STORE_KEY, JSON.stringify(m));\n window.dispatchEvent(new Event(AVATAR_EVENT));\n } catch {}\n}\n\nlet version = 0;\nfunction subscribe(callback: () => void) {\n fetchManifestOnce();\n const bump = () => { version++; callback(); };\n window.addEventListener(AVATAR_EVENT, bump);\n window.addEventListener('storage', bump);\n return () => {\n window.removeEventListener(AVATAR_EVENT, bump);\n window.removeEventListener('storage', bump);\n };\n}\n\n/** Monotonic version for callers that resolve many aliases via plain\n * getAvatarUrl() inside render loops (map callbacks can't call hooks —\n * same idiom as chat-mute's useMuteVersion). Subscribing also kicks off\n * the lazy manifest fetch and re-renders the caller when it lands. */\nexport function useAvatarsVersion(): number {\n return useSyncExternalStore(subscribe, () => version, () => 0);\n}\n\nexport function useAvatarUrl(alias?: string | null): string {\n return useSyncExternalStore(subscribe, () => getAvatarUrl(alias), () => '');\n}\n","'use client';\n\nimport { useState } from 'react';\nimport Link from 'next/link';\n\nexport type EmptyVariant = 'nodes' | 'tasks' | 'messages' | 'logs' | 'tokens' | 'networks' | 'generic';\n\ninterface EmptyStateProps {\n /** Picks the icon glyph and default copy if title/sub omitted. */\n variant?: EmptyVariant;\n /** Optional override headline. */\n title?: string;\n /** Optional override sub-copy. */\n sub?: string;\n /** Optional CTA: text + href (internal) or onClick. */\n cta?: { label: string; href?: string; onClick?: () => void };\n /** Compact mode for in-card empty states (smaller padding). */\n compact?: boolean;\n}\n\nconst DEFAULTS: Record<EmptyVariant, { title: string; sub: string }> = {\n nodes: { title: 'No agents in this network', sub: 'Agent sessions will appear here once they connect to the CommHub.' },\n tasks: { title: 'No tasks yet', sub: 'Tasks will appear here when agents send them via CommHub.' },\n messages: { title: 'No messages', sub: 'Messages between agents will appear here.' },\n logs: { title: 'No audit logs', sub: 'Events will appear here when users register, login, or perform actions.' },\n tokens: { title: 'No API tokens', sub: 'Create one to authenticate CLI tools and external integrations.' },\n networks: { title: 'No networks found', sub: 'Create one or sign in with V3 auth to see your networks.' },\n generic: { title: 'Nothing here yet', sub: 'Data will appear here once available.' },\n};\n\n/**\n * Minimal monochrome SVG glyphs per variant. No filled shapes, no gradients,\n * no AI-decoration — just thin-stroke line art that fades into the page.\n * 64×64 viewBox; rendered at 56×56 (compact 40×40).\n */\nfunction Glyph({ variant, size }: { variant: EmptyVariant; size: number }) {\n const s = { width: size, height: size };\n const baseProps = {\n fill: 'none',\n stroke: 'currentColor',\n strokeWidth: 1.25,\n strokeLinecap: 'round' as const,\n strokeLinejoin: 'round' as const,\n };\n\n switch (variant) {\n case 'nodes':\n // Mesh with dashed edges = \"nodes will land here\"\n return (\n <svg viewBox=\"0 0 64 64\" {...s}>\n <g {...baseProps}>\n <circle cx=\"32\" cy=\"14\" r=\"4\" />\n <circle cx=\"14\" cy=\"44\" r=\"4\" />\n <circle cx=\"50\" cy=\"44\" r=\"4\" />\n <line x1=\"32\" y1=\"18\" x2=\"14\" y2=\"40\" strokeDasharray=\"3 3\" opacity=\"0.6\" />\n <line x1=\"32\" y1=\"18\" x2=\"50\" y2=\"40\" strokeDasharray=\"3 3\" opacity=\"0.6\" />\n <line x1=\"18\" y1=\"44\" x2=\"46\" y2=\"44\" strokeDasharray=\"3 3\" opacity=\"0.6\" />\n </g>\n </svg>\n );\n case 'tasks':\n // Empty checkbox list\n return (\n <svg viewBox=\"0 0 64 64\" {...s}>\n <g {...baseProps}>\n <rect x=\"14\" y=\"14\" width=\"36\" height=\"6\" rx=\"1.5\" />\n <rect x=\"14\" y=\"26\" width=\"36\" height=\"6\" rx=\"1.5\" opacity=\"0.6\" />\n <rect x=\"14\" y=\"38\" width=\"36\" height=\"6\" rx=\"1.5\" opacity=\"0.35\" />\n </g>\n </svg>\n );\n case 'messages':\n // Speech bubble outline\n return (\n <svg viewBox=\"0 0 64 64\" {...s}>\n <g {...baseProps}>\n <path d=\"M14 18 h36 a3 3 0 0 1 3 3 v18 a3 3 0 0 1 -3 3 h-18 l-8 6 v-6 h-10 a3 3 0 0 1 -3 -3 v-18 a3 3 0 0 1 3 -3 z\" />\n <line x1=\"22\" y1=\"28\" x2=\"42\" y2=\"28\" opacity=\"0.5\" />\n <line x1=\"22\" y1=\"34\" x2=\"36\" y2=\"34\" opacity=\"0.5\" />\n </g>\n </svg>\n );\n case 'logs':\n // Document with lines\n return (\n <svg viewBox=\"0 0 64 64\" {...s}>\n <g {...baseProps}>\n <path d=\"M18 12 h22 l8 8 v32 a2 2 0 0 1 -2 2 h-28 a2 2 0 0 1 -2 -2 v-38 a2 2 0 0 1 2 -2 z\" />\n <path d=\"M40 12 v8 h8\" opacity=\"0.6\" />\n <line x1=\"24\" y1=\"32\" x2=\"40\" y2=\"32\" opacity=\"0.55\" />\n <line x1=\"24\" y1=\"38\" x2=\"40\" y2=\"38\" opacity=\"0.4\" />\n <line x1=\"24\" y1=\"44\" x2=\"34\" y2=\"44\" opacity=\"0.25\" />\n </g>\n </svg>\n );\n case 'tokens':\n // Key outline\n return (\n <svg viewBox=\"0 0 64 64\" {...s}>\n <g {...baseProps}>\n <circle cx=\"22\" cy=\"32\" r=\"8\" />\n <line x1=\"30\" y1=\"32\" x2=\"54\" y2=\"32\" />\n <line x1=\"44\" y1=\"32\" x2=\"44\" y2=\"38\" />\n <line x1=\"50\" y1=\"32\" x2=\"50\" y2=\"40\" />\n </g>\n </svg>\n );\n case 'networks':\n // Globe-ish concentric ovals\n return (\n <svg viewBox=\"0 0 64 64\" {...s}>\n <g {...baseProps}>\n <circle cx=\"32\" cy=\"32\" r=\"18\" />\n <ellipse cx=\"32\" cy=\"32\" rx=\"18\" ry=\"9\" opacity=\"0.55\" />\n <line x1=\"14\" y1=\"32\" x2=\"50\" y2=\"32\" opacity=\"0.55\" />\n <line x1=\"32\" y1=\"14\" x2=\"32\" y2=\"50\" opacity=\"0.55\" />\n </g>\n </svg>\n );\n case 'generic':\n default:\n // Soft sparkle outline\n return (\n <svg viewBox=\"0 0 64 64\" {...s}>\n <g {...baseProps}>\n <circle cx=\"32\" cy=\"32\" r=\"14\" strokeDasharray=\"3 3\" opacity=\"0.6\" />\n <circle cx=\"32\" cy=\"32\" r=\"3\" />\n </g>\n </svg>\n );\n }\n}\n\nexport function EmptyState({ variant = 'generic', title, sub, cta, compact = false }: EmptyStateProps) {\n const d = DEFAULTS[variant];\n const headline = title ?? d.title;\n const subcopy = sub ?? d.sub;\n const iconSize = compact ? 40 : 56;\n\n return (\n <div className={`text-center ${compact ? 'py-8' : 'py-16'} px-4`} role=\"status\">\n <div className=\"anet-empty-glyph inline-flex items-center justify-center mb-4 text-gray-500\" aria-hidden>\n <Glyph variant={variant} size={iconSize} />\n </div>\n <h3 className={`font-medium text-gray-300 ${compact ? 'text-sm' : 'text-base'}`}>{headline}</h3>\n {subcopy && (\n <p className={`text-gray-500 ${compact ? 'text-xs mt-1.5' : 'text-sm mt-2'} max-w-md mx-auto leading-relaxed`}>\n {subcopy}\n </p>\n )}\n {cta && (\n <div className=\"mt-4\">\n {cta.href ? (\n <Link href={cta.href} className=\"inline-flex items-center gap-1.5 text-sm font-medium text-cyan-400 hover:text-cyan-300\">\n {cta.label}\n <span aria-hidden>→</span>\n </Link>\n ) : (\n <button onClick={cta.onClick} className=\"inline-flex items-center gap-1.5 text-sm font-medium text-cyan-400 hover:text-cyan-300\">\n {cta.label}\n <span aria-hidden>→</span>\n </button>\n )}\n </div>\n )}\n </div>\n );\n}\n\n/** Round 105 (issue #90): centered card shell so the Overview empty state\n * reads as an intentional, layout-aligned card instead of bare text\n * floating in the content column. */\nfunction EmptyCard({ children }: { children: React.ReactNode }) {\n return (\n <div className=\"max-w-2xl mx-auto rounded-xl border border-[#26262b] bg-[#161618] shadow-lg shadow-black/20\">\n {children}\n </div>\n );\n}\n\n/**\n * Overview-specific variant. Three cases:\n * 1. network-mismatch — agents exist globally, none in this network\n * 2. agents-offline — 0 registered now BUT task history exists, so this\n * is NOT a first run (round 105 / issue #90: showing \"Spin up your\n * first agent\" next to \"acked: 499\" was misleading)\n * 3. true first-run — 0 agents, 0 history → quickstart command\n */\nexport function NodesEmptyState({\n hint,\n taskHistoryCount = 0,\n}: {\n hint?: { global_count?: number; filtered_network?: string };\n taskHistoryCount?: number;\n}) {\n if (hint?.global_count) {\n return (\n <EmptyCard>\n <EmptyState\n variant=\"nodes\"\n title=\"No agents in this network\"\n sub={`Server has ${hint.global_count} nodes globally, but none are registered to the current network. Switch network or contact admin.`}\n />\n </EmptyCard>\n );\n }\n\n // Round 105 (issue #90): there's task history but no agents online right\n // now — they finished or disconnected. Don't pitch a first-run setup;\n // point at the history instead.\n if (taskHistoryCount > 0) {\n return (\n <EmptyCard>\n <EmptyState\n variant=\"nodes\"\n title=\"No agents online\"\n sub={`Every agent in this network is currently offline. ${taskHistoryCount.toLocaleString()} task${taskHistoryCount === 1 ? '' : 's'} in history — they may have finished their work or disconnected.`}\n cta={{ label: 'View task history', href: '/tasks' }}\n />\n </EmptyCard>\n );\n }\n\n // Round 52: true empty state (zero agents anywhere) — show the\n // quickstart command inline so users don't have to leave the dashboard\n // to figure out how to spin up their first agent.\n return (\n <EmptyCard>\n <div className=\"text-center py-16 px-4\" role=\"status\">\n <div className=\"anet-empty-glyph inline-flex items-center justify-center mb-4 text-gray-500\" aria-hidden>\n <svg viewBox=\"0 0 64 64\" width={56} height={56}>\n <g stroke=\"currentColor\" strokeWidth=\"1.5\" fill=\"none\">\n <rect x=\"10\" y=\"20\" width=\"44\" height=\"28\" rx=\"2\" />\n <rect x=\"20\" y=\"32\" width=\"6\" height=\"8\" opacity=\"0.5\" />\n <rect x=\"32\" y=\"32\" width=\"6\" height=\"8\" opacity=\"0.5\" />\n <rect x=\"44\" y=\"32\" width=\"4\" height=\"8\" opacity=\"0.5\" />\n <line x1=\"10\" y1=\"26\" x2=\"54\" y2=\"26\" opacity=\"0.4\" />\n <circle cx=\"14\" cy=\"23\" r=\"0.8\" fill=\"currentColor\" />\n </g>\n </svg>\n </div>\n <h3 className=\"font-medium text-gray-300 text-base\">Spin up your first agent</h3>\n <p className=\"text-gray-500 text-sm mt-2 max-w-md mx-auto leading-relaxed\">\n Run this in a fresh terminal to register an agent with this CommHub:\n </p>\n <div className=\"mt-4 inline-block\">\n <QuickstartCommand cmd=\"npx --yes @sleep2agi/agent-network init\" />\n </div>\n {/* #214 F6: expectation management — without this line, users\n copy the command and stare at an empty screen not knowing\n what to wait for. The page polls every 5s, so the node\n really does appear by itself. */}\n <p className=\"text-gray-600 text-xs mt-3 max-w-md mx-auto\">\n Once the agent connects, it appears here automatically within a\n few seconds — no refresh needed.\n </p>\n <div className=\"mt-3\">\n <a\n href=\"https://anet.sh\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"inline-flex items-center gap-1.5 text-xs font-medium text-gray-500 hover:text-cyan-300\"\n >\n Full quickstart guide\n <span aria-hidden>→</span>\n </a>\n </div>\n </div>\n </EmptyCard>\n );\n}\n\n/** Code block + inline copy button used by the empty-Overview first-run\n * CTA. State lives here so the parent stays stateless. */\nfunction QuickstartCommand({ cmd }: { cmd: string }) {\n const [copied, setCopied] = useState(false);\n const onCopy = async () => {\n try {\n await navigator.clipboard.writeText(cmd);\n setCopied(true);\n setTimeout(() => setCopied(false), 1800);\n } catch {}\n };\n return (\n <div className=\"anet-empty-cmd flex items-start sm:items-center gap-2 bg-[#0e0e10] border border-[#26262b] rounded-lg pl-4 pr-1.5 py-1.5 text-xs sm:text-sm\">\n {/* #209 R44: long quickstart commands (e.g. the `npm install -g …`\n variant) overflowed the empty-state card horizontally on phones\n because <code> defaults to white-space:pre. break-all on mobile\n lets them wrap inside the box; sm: up restores normal wrapping\n so desktop monospace lines stay clean. items-start on phones\n aligns the Copy button to the top so a wrapped 2-line command\n doesn't bottom-anchor the button. */}\n <code className=\"text-cyan-300 font-mono select-all min-w-0 break-all sm:break-normal\">{cmd}</code>\n <button\n type=\"button\"\n onClick={onCopy}\n aria-label={copied ? 'Copied' : 'Copy command'}\n className=\"shrink-0 rounded-md px-2 py-1.5 text-[11px] text-gray-500 hover:text-gray-200 hover:bg-[#1c1c1f] transition-colors\"\n >\n {copied ? (\n <span className=\"flex items-center gap-1 text-green-400\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n Copied\n </span>\n ) : (\n <span className=\"flex items-center gap-1\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\" />\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\" />\n </svg>\n Copy\n </span>\n )}\n </button>\n </div>\n );\n}\n","\"use turbopack no side effects\";\nexport default {\"name\":\"@sleep2agi/agent-network-dashboard\",\"version\":\"0.6.3-preview.43\",\"description\":\"Agent Network Dashboard — Web UI for managing AI Agent networks\",\"main\":\"apps/desktop/electron/main.cjs\",\"scripts\":{\"dev\":\"next dev\",\"build\":\"next build\",\"postbuild\":\"node scripts/stamp-build-commit.mjs\",\"start\":\"next start\",\"lint\":\"eslint\",\"app:android:init\":\"npx cap add android\",\"app:android:sync\":\"npx cap sync android\",\"app:android:open\":\"npx cap open android\",\"app:ios:init\":\"npx cap add ios\",\"app:ios:sync\":\"npx cap sync ios\",\"app:ios:open\":\"npx cap open ios\",\"app:desktop\":\"electron apps/desktop/electron/main.cjs\",\"app:desktop:pack\":\"electron-builder --config electron-builder.json\",\"prepublishOnly\":\"[ -f .next/BUILD_ID ] || (echo 'prepublishOnly: .next/BUILD_ID missing — run npm run build first (see commit 05c1ebf body for R224 chunk-500 root cause)' >&2 && exit 1)\",\"avatars:check\":\"node scripts/check-avatars.mjs\"},\"bin\":{\"agent-network-dashboard\":\"./bin/start.js\"},\"homepage\":\"https://anet.sh\",\"repository\":{\"type\":\"git\",\"url\":\"https://github.com/sleep2agi/agent-network-dashboard\"},\"bugs\":{\"url\":\"https://github.com/sleep2agi/agent-network-dashboard/issues\"},\"author\":\"sleep2agi\",\"license\":\"Apache-2.0\",\"publishConfig\":{\"access\":\"public\"},\"dependencies\":{\"@capacitor/core\":\"^7.4.4\",\"next\":\"16.2.3\",\"pinyin-pro\":\"^3.28.1\",\"react\":\"19.2.4\",\"react-dom\":\"19.2.4\",\"react-markdown\":\"^10.1.0\",\"remark-gfm\":\"^4.0.1\",\"swr\":\"^2.4.1\"},\"devDependencies\":{\"@capacitor/android\":\"^7.4.4\",\"@capacitor/cli\":\"^7.4.4\",\"@capacitor/ios\":\"^7.4.4\",\"@playwright/test\":\"^1.59.1\",\"@tailwindcss/postcss\":\"^4\",\"@types/node\":\"^20\",\"@types/react\":\"^19\",\"@types/react-dom\":\"^19\",\"electron\":\"^39.2.6\",\"electron-builder\":\"^26.0.12\",\"eslint\":\"^9\",\"eslint-config-next\":\"16.2.3\",\"tailwindcss\":\"^4\",\"typescript\":\"^5\"}};\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInR1cmJvcGFjazovLy9kYXNoLTQ5Mi9hZ2VudC1uZXR3b3JrLWRhc2hib2FyZC9wYWNrYWdlLmpzb24iXSwic291cmNlc0NvbnRlbnQiOlsie1wibmFtZVwiOlwiQHNsZWVwMmFnaS9hZ2VudC1uZXR3b3JrLWRhc2hib2FyZFwiLFwidmVyc2lvblwiOlwiMC42LjMtcHJldmlldy40M1wiLFwiZGVzY3JpcHRpb25cIjpcIkFnZW50IE5ldHdvcmsgRGFzaGJvYXJkIOKAlCBXZWIgVUkgZm9yIG1hbmFnaW5nIEFJIEFnZW50IG5ldHdvcmtzXCIsXCJtYWluXCI6XCJhcHBzL2Rlc2t0b3AvZWxlY3Ryb24vbWFpbi5janNcIixcInNjcmlwdHNcIjp7XCJkZXZcIjpcIm5leHQgZGV2XCIsXCJidWlsZFwiOlwibmV4dCBidWlsZFwiLFwicG9zdGJ1aWxkXCI6XCJub2RlIHNjcmlwdHMvc3RhbXAtYnVpbGQtY29tbWl0Lm1qc1wiLFwic3RhcnRcIjpcIm5leHQgc3RhcnRcIixcImxpbnRcIjpcImVzbGludFwiLFwiYXBwOmFuZHJvaWQ6aW5pdFwiOlwibnB4IGNhcCBhZGQgYW5kcm9pZFwiLFwiYXBwOmFuZHJvaWQ6c3luY1wiOlwibnB4IGNhcCBzeW5jIGFuZHJvaWRcIixcImFwcDphbmRyb2lkOm9wZW5cIjpcIm5weCBjYXAgb3BlbiBhbmRyb2lkXCIsXCJhcHA6aW9zOmluaXRcIjpcIm5weCBjYXAgYWRkIGlvc1wiLFwiYXBwOmlvczpzeW5jXCI6XCJucHggY2FwIHN5bmMgaW9zXCIsXCJhcHA6aW9zOm9wZW5cIjpcIm5weCBjYXAgb3BlbiBpb3NcIixcImFwcDpkZXNrdG9wXCI6XCJlbGVjdHJvbiBhcHBzL2Rlc2t0b3AvZWxlY3Ryb24vbWFpbi5janNcIixcImFwcDpkZXNrdG9wOnBhY2tcIjpcImVsZWN0cm9uLWJ1aWxkZXIgLS1jb25maWcgZWxlY3Ryb24tYnVpbGRlci5qc29uXCIsXCJwcmVwdWJsaXNoT25seVwiOlwiWyAtZiAubmV4dC9CVUlMRF9JRCBdIHx8IChlY2hvICdwcmVwdWJsaXNoT25seTogLm5leHQvQlVJTERfSUQgbWlzc2luZyDigJQgcnVuIG5wbSBydW4gYnVpbGQgZmlyc3QgKHNlZSBjb21taXQgMDVjMWViZiBib2R5IGZvciBSMjI0IGNodW5rLTUwMCByb290IGNhdXNlKScgPiYyICYmIGV4aXQgMSlcIixcImF2YXRhcnM6Y2hlY2tcIjpcIm5vZGUgc2NyaXB0cy9jaGVjay1hdmF0YXJzLm1qc1wifSxcImJpblwiOntcImFnZW50LW5ldHdvcmstZGFzaGJvYXJkXCI6XCIuL2Jpbi9zdGFydC5qc1wifSxcImhvbWVwYWdlXCI6XCJodHRwczovL2FuZXQuc2hcIixcInJlcG9zaXRvcnlcIjp7XCJ0eXBlXCI6XCJnaXRcIixcInVybFwiOlwiaHR0cHM6Ly9naXRodWIuY29tL3NsZWVwMmFnaS9hZ2VudC1uZXR3b3JrLWRhc2hib2FyZFwifSxcImJ1Z3NcIjp7XCJ1cmxcIjpcImh0dHBzOi8vZ2l0aHViLmNvbS9zbGVlcDJhZ2kvYWdlbnQtbmV0d29yay1kYXNoYm9hcmQvaXNzdWVzXCJ9LFwiYXV0aG9yXCI6XCJzbGVlcDJhZ2lcIixcImxpY2Vuc2VcIjpcIkFwYWNoZS0yLjBcIixcInB1Ymxpc2hDb25maWdcIjp7XCJhY2Nlc3NcIjpcInB1YmxpY1wifSxcImRlcGVuZGVuY2llc1wiOntcIkBjYXBhY2l0b3IvY29yZVwiOlwiXjcuNC40XCIsXCJuZXh0XCI6XCIxNi4yLjNcIixcInBpbnlpbi1wcm9cIjpcIl4zLjI4LjFcIixcInJlYWN0XCI6XCIxOS4yLjRcIixcInJlYWN0LWRvbVwiOlwiMTkuMi40XCIsXCJyZWFjdC1tYXJrZG93blwiOlwiXjEwLjEuMFwiLFwicmVtYXJrLWdmbVwiOlwiXjQuMC4xXCIsXCJzd3JcIjpcIl4yLjQuMVwifSxcImRldkRlcGVuZGVuY2llc1wiOntcIkBjYXBhY2l0b3IvYW5kcm9pZFwiOlwiXjcuNC40XCIsXCJAY2FwYWNpdG9yL2NsaVwiOlwiXjcuNC40XCIsXCJAY2FwYWNpdG9yL2lvc1wiOlwiXjcuNC40XCIsXCJAcGxheXdyaWdodC90ZXN0XCI6XCJeMS41OS4xXCIsXCJAdGFpbHdpbmRjc3MvcG9zdGNzc1wiOlwiXjRcIixcIkB0eXBlcy9ub2RlXCI6XCJeMjBcIixcIkB0eXBlcy9yZWFjdFwiOlwiXjE5XCIsXCJAdHlwZXMvcmVhY3QtZG9tXCI6XCJeMTlcIixcImVsZWN0cm9uXCI6XCJeMzkuMi42XCIsXCJlbGVjdHJvbi1idWlsZGVyXCI6XCJeMjYuMC4xMlwiLFwiZXNsaW50XCI6XCJeOVwiLFwiZXNsaW50LWNvbmZpZy1uZXh0XCI6XCIxNi4yLjNcIixcInRhaWx3aW5kY3NzXCI6XCJeNFwiLFwidHlwZXNjcmlwdFwiOlwiXjVcIn19Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBIn0=","/** Dashboard package version sourced from package.json at build time.\n * Importing JSON requires `resolveJsonModule: true` in tsconfig, which\n * Next sets by default. Bumping is automated by the publish flow, so this\n * surfaces the real preview number in Settings → Dashboard. */\nimport pkg from '../../package.json' assert { type: 'json' };\n\nexport const DASHBOARD_VERSION: string = pkg.version;\n"],"names":["previewContent","raw","replace","trim","timeAgo","dateStr","statusColor","status","hasSse","STORE_KEY","AVATAR_EVENT","manifest","pool","manifestRequested","poolPick","alias","length","h","i","charCodeAt","fetchManifestOnce","readMap","getAvatarUrl","setAvatarUrl","url","version","subscribe","callback","bump","window","addEventListener","removeEventListener","useAvatarsVersion","useAvatarUrl","DEFAULTS","nodes","title","sub","tasks","messages","logs","tokens","networks","generic","Glyph","variant","size","s","width","height","baseProps","fill","stroke","strokeWidth","strokeLinecap","strokeLinejoin","viewBox","cx","cy","r","x1","y1","x2","y2","strokeDasharray","opacity","x","y","rx","d","ry","EmptyState","cta","compact","headline","subcopy","iconSize","className","role","href","label","onClick","EmptyCard","children","NodesEmptyState","hint","taskHistoryCount","global_count","toLocaleString","QuickstartCommand","cmd","target","rel","copied","setCopied","onCopy","navigator","clipboard","writeText","setTimeout","type"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- module.exports=[21487,a=>{"use strict";var b=a.i(10571),c=a.i(53705);let d=async a=>{let b=await fetch(a);if(401===b.status)throw window.location.assign("/login"),Error("unauthorized");return b.json()},e={refreshInterval:5e3,dedupingInterval:3e3};function f(a,b){if(!b)return a;let c=a.includes("?")?"&":"?";return`${a}${c}network_id=${encodeURIComponent(b)}`}a.s(["useAnetConfig",0,function(){let{data:a}=(0,b.default)("/api/anet/config",d,{refreshInterval:3e4});return{config:a||null}},"useHealth",0,function(){let{data:a,error:c}=(0,b.default)("/api/hub/health",d,e);return{health:a||null,error:c}},"useMessages",0,function(a=100){let{networkId:g}=(0,c.useNetworkId)(),{data:h,error:i,isLoading:j}=(0,b.default)(f(`/api/hub/messages?limit=${a}`,g),d,{...e,keepPreviousData:!0});return{messages:h?.messages||[],error:i,isLoading:j}},"useNodeLifecycle",0,function(){let{networkId:a}=(0,c.useNetworkId)(),{data:g,error:h,mutate:i}=(0,b.default)(f("/api/hub/nodes",a),d,e),j={},k={},l={};for(let a of g?.nodes??[])a.alias&&"string"==typeof a.lifecycle_state&&(j[a.alias]=a.lifecycle_state),a.alias&&"string"==typeof a.node_id&&(k[a.alias]=a.node_id),a.alias&&(l[a.alias]={display_name:"string"==typeof a.display_name?a.display_name:null,team:"string"==typeof a.team?a.team:null,tags:Array.isArray(a.tags)?a.tags:[],attrs_revision:"number"==typeof a.attrs_revision?a.attrs_revision:0});return{lifecycleByAlias:j,nodeIdByAlias:k,attrsByAlias:l,error:h,refreshNodes:i}},"useSessions",0,function(){let{networkId:a}=(0,c.useNetworkId)(),{data:g,error:h,isLoading:i}=(0,b.default)(f("/api/hub/status",a),d,e);return{sessions:g?.sessions||[],hint:g?._hint,error:h,isLoading:i}},"useStats",0,function(){let{networkId:a}=(0,c.useNetworkId)(),{data:g,error:h}=(0,b.default)(f("/api/hub/stats",a),d,e);return{stats:g?.ok?g:null,error:h}},"useTasks",0,function(a){let{networkId:g}=(0,c.useNetworkId)(),h=new URLSearchParams({limit:"100",...a}).toString(),{data:i,error:j,isLoading:k}=(0,b.default)(f(`/api/hub/tasks?${h}`,g),d,e);return{tasks:i?.tasks||[],count:i?.count??0,source:i?.source,error:j,isLoading:k}}])},86176,a=>{"use strict";a.s(["DASHBOARD_VERSION",0,"0.6.3-preview.43"],86176)},93924,a=>{"use strict";var b=a.i(5400),c=a.i(82956),d=a.i(66860),e=a.i(21487),f=a.i(19315),g=a.i(86176);a.s(["default",0,function(){let{config:a}=(0,e.useAnetConfig)(),{health:h,error:i}=(0,e.useHealth)(),[j,k]=(0,c.useState)(()=>"cyber"),[l,m]=(0,c.useState)(""),[n,o]=(0,c.useState)(""),[p,q]=(0,c.useState)(""),r="flex flex-col gap-1 sm:flex-row sm:items-start sm:justify-between",s="break-all sm:max-w-[320px] sm:text-right";return(0,b.jsxs)("div",{className:"min-h-screen bg-[#0b0b0d] text-gray-100 p-4 sm:p-6",children:[(0,b.jsx)("h1",{className:"text-2xl font-bold text-white mb-3 lg:ml-0 ml-10",children:"Settings"}),(0,b.jsx)("nav",{className:"mb-4 sm:mb-8 flex flex-wrap gap-2 text-xs",children:[{href:"#appearance",label:"Appearance"},{href:"#connection",label:"Connection"},{href:"#account",label:"Account"},{href:"#resources",label:"Resources"}].map(a=>(0,b.jsx)("a",{href:a.href,className:"inline-flex min-h-[44px] items-center rounded-md border border-[#26262b] bg-[#0e0e10]/60 px-3 py-2 text-gray-400 hover:border-cyan-500/50 hover:text-cyan-300 hover:bg-cyan-500/10 transition-colors",children:a.label},a.href))}),(0,b.jsxs)("div",{className:"max-w-2xl space-y-10",children:[(0,b.jsxs)("div",{id:"appearance",className:"space-y-4 scroll-mt-6",children:[(0,b.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,b.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Appearance"}),(0,b.jsx)("div",{className:"flex-1 h-px bg-[#26262b]"})]}),(0,b.jsxs)("section",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-5",children:[(0,b.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Theme"}),(0,b.jsx)("div",{className:"grid grid-cols-2 gap-3",children:[{id:"cyber",label:"Dark",swatch:"#0b0b0d"},{id:"light",label:"Light",swatch:"#f6f7f9"},{id:"slack",label:"Slack",swatch:"#3f0e40"}].map(a=>(0,b.jsxs)("button",{onClick:()=>{try{localStorage.setItem("anet-theme",a.id)}catch{}(0,f.applyTheme)(a.id),k(a.id)},"aria-pressed":j===a.id,className:`flex items-center gap-3 rounded-lg border px-4 py-3 text-sm transition-colors ${j===a.id?"border-cyan-500/60 bg-cyan-500/10 text-gray-100":"border-[#26262b] text-gray-400 hover:border-[#3a3a41]"}`,children:[(0,b.jsx)("span",{"aria-hidden":!0,className:"inline-block w-5 h-5 rounded-full border border-black/20 shrink-0",style:{backgroundColor:a.swatch}}),a.label,j===a.id&&(0,b.jsx)("svg",{"aria-hidden":!0,className:"ml-auto w-4 h-4 text-cyan-400",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",children:(0,b.jsx)("path",{d:"M20 6 9 17l-5-5"})})]},a.id))})]})]}),(0,b.jsxs)("div",{id:"connection",className:"space-y-4 scroll-mt-6",children:[(0,b.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,b.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Connection"}),(0,b.jsx)("div",{className:"flex-1 h-px bg-[#26262b]"})]}),(0,b.jsxs)("section",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-5",children:[(0,b.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"CommHub Connection"}),(0,b.jsxs)("div",{className:"space-y-3 text-sm",children:[(0,b.jsxs)("div",{className:r,children:[(0,b.jsx)("span",{className:"text-gray-500 shrink-0",children:"Hub URL"}),(0,b.jsx)("span",{className:`text-cyan-300 ${s}`,children:a?.hub||"not configured"})]}),(0,b.jsxs)("div",{className:r,children:[(0,b.jsx)("span",{className:"text-gray-500",children:"Config Source"}),(0,b.jsx)("span",{className:`text-gray-300 ${s}`,children:a?.source==="file"?"Local file (~/.anet/config.json)":a?.source==="runtime-env"?"Vercel env vars":"Missing"})]}),(0,b.jsxs)("div",{className:r,children:[(0,b.jsx)("span",{className:"text-gray-500",children:"Auth Token"}),(0,b.jsx)("span",{className:`${a?.tokenConfigured?"text-green-400":"text-red-400"} ${s}`,children:a?.tokenConfigured?`Configured (${a.tokenPreview})`:"Not configured"})]}),(0,b.jsxs)("div",{className:r,children:[(0,b.jsx)("span",{className:"text-gray-500",children:"Server Auth"}),(0,b.jsx)("span",{className:`${h?.auth==="enabled"?"text-green-400":"text-yellow-400"} sm:text-right`,children:h?.auth||"--"})]}),a?.error&&(0,b.jsx)("div",{className:"border-t border-[#26262b] pt-3 text-xs text-gray-500",children:a.error}),(i||h?.ok===!1)&&(0,b.jsxs)("div",{className:"border-t border-red-500/20 pt-3 text-xs space-y-1.5",role:"alert",children:[(0,b.jsx)("div",{className:"text-red-300 font-medium",children:"CommHub unreachable — how to recover:"}),(0,b.jsxs)("div",{className:"text-gray-400",children:["1. Check the hub process on the server: ",(0,b.jsx)("code",{className:"font-mono bg-[#0e0e10] border border-[#1c1c1f] rounded px-1.5 py-0.5",children:"anet hub status"})]}),(0,b.jsxs)("div",{className:"text-gray-400",children:["2. Start it if stopped: ",(0,b.jsx)("code",{className:"font-mono bg-[#0e0e10] border border-[#1c1c1f] rounded px-1.5 py-0.5",children:"anet hub start"})]}),(0,b.jsx)("div",{className:"text-gray-400",children:"3. Confirm the Hub URL above matches where the hub actually listens."})]})]})]}),(0,b.jsxs)("section",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-5",children:[(0,b.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Server Info"}),(0,b.jsxs)("div",{className:"space-y-3 text-sm",children:[(0,b.jsxs)("div",{className:r,children:[(0,b.jsx)("span",{className:"text-gray-500",children:"Version"}),(0,b.jsx)("span",{className:`text-gray-300 ${s}`,children:h?.version||"--"})]}),(0,b.jsxs)("div",{className:r,children:[(0,b.jsx)("span",{className:"text-gray-500",children:"Sessions"}),(0,b.jsx)("span",{className:`text-gray-300 ${s}`,children:h?.sessions??"--"})]}),(0,b.jsxs)("div",{className:r,children:[(0,b.jsxs)("span",{className:"text-gray-500",children:["SSE streams ",(0,b.jsx)("span",{className:"text-gray-600",children:"· server"})]}),(0,b.jsx)("span",{className:`text-gray-300 ${s}`,children:h?.sse_connections??"--"})]}),(0,b.jsxs)("div",{className:r,children:[(0,b.jsx)("span",{className:"text-gray-500",children:"Uptime"}),(0,b.jsx)("span",{className:`text-gray-300 ${s}`,children:h?.uptime?`${Math.floor(h.uptime/3600)}h ${Math.floor(h.uptime%3600/60)}m`:"--"})]})]})]}),(0,b.jsxs)("section",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-5",children:[(0,b.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Dashboard"}),(0,b.jsxs)("div",{className:"space-y-3 text-sm",children:[(0,b.jsxs)("div",{className:r,children:[(0,b.jsx)("span",{className:"text-gray-500",children:"Version"}),(0,b.jsx)("span",{className:`text-gray-300 font-mono ${s}`,title:"From package.json @sleep2agi/agent-network-dashboard",children:g.DASHBOARD_VERSION})]}),(0,b.jsxs)("div",{className:r,children:[(0,b.jsx)("span",{className:"text-gray-500",children:"Data Layer"}),(0,b.jsx)("span",{className:`text-gray-300 ${s}`,children:"SWR (5s refresh, 3s dedup)"})]}),(0,b.jsxs)("div",{className:r,children:[(0,b.jsx)("span",{className:"text-gray-500",children:"Pages"}),(0,b.jsx)("span",{className:`text-gray-300 ${s}`,children:"Overview, Tasks, Nodes, Messages, Networks, Audit, Server Logs, Admin, Settings"})]})]})]})]}),(0,b.jsxs)("div",{id:"account",className:"space-y-4 scroll-mt-6",children:[(0,b.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,b.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Account"}),(0,b.jsx)("div",{className:"flex-1 h-px bg-[#26262b]"})]}),(0,b.jsxs)("section",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-5",children:[(0,b.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Change Password"}),(0,b.jsxs)("div",{className:"space-y-3",children:[(0,b.jsx)("input",{type:"password",value:l,onChange:a=>m(a.target.value),placeholder:"Current password",className:"w-full bg-[#0e0e10] border border-[#26262b] rounded-lg px-3 py-2 text-base sm:text-sm text-white placeholder-gray-600 focus:border-cyan-500/50 focus:outline-none"}),(0,b.jsx)("input",{type:"password",value:n,onChange:a=>o(a.target.value),placeholder:"New password",className:"w-full bg-[#0e0e10] border border-[#26262b] rounded-lg px-3 py-2 text-base sm:text-sm text-white placeholder-gray-600 focus:border-cyan-500/50 focus:outline-none"}),(0,b.jsx)("button",{onClick:async()=>{if(!l||!n)return;let a=sessionStorage.getItem("anet_v3_auth");if(!a)return void q("Not logged in with V3 auth");let{token:b}=JSON.parse(a),c=await fetch("/api/hub/auth",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"change_password",token:b,current_password:l,new_password:n})}),d=await c.json();if(q(d.ok?"Password changed":`Failed: ${d.error}`),d.ok){if(d.token){let b=JSON.parse(a);sessionStorage.setItem("anet_v3_auth",JSON.stringify({...b,token:d.token}))}m(""),o("")}setTimeout(()=>q(""),5e3)},disabled:!l||!n,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,b.jsx)("div",{className:`mt-2 text-xs ${p.startsWith("Failed")?"text-red-400":"text-green-400"}`,children:p})]}),(0,b.jsxs)("section",{className:"bg-[#161618] border border-[#26262b] rounded-xl p-5",children:[(0,b.jsx)("h2",{className:"text-sm font-semibold text-gray-300 mb-4",children:"Sign out"}),(0,b.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,b.jsx)("button",{onClick:async()=>{await fetch("/api/auth/logout",{method:"POST"}).catch(()=>{}),window.location.assign("/login")},className:"px-4 py-2 bg-transparent hover:bg-[#1c1c1f] text-gray-300 text-sm rounded-lg border border-[#26262b] hover:border-[#3a3a41] transition-colors",children:"Sign out"})]})]}),(0,b.jsxs)("div",{id:"resources",className:"space-y-4 scroll-mt-6",children:[(0,b.jsxs)("div",{className:"flex items-center gap-2 px-1",children:[(0,b.jsx)("div",{className:"text-[11px] uppercase tracking-[0.14em] text-gray-400 font-semibold",children:"Resources"}),(0,b.jsx)("div",{className:"flex-1 h-px bg-[#26262b]"})]}),(0,b.jsxs)("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4",children:[(0,b.jsxs)(d.default,{href:"/settings/tokens",className:"bg-[#161618] border border-[#26262b] rounded-xl p-5 hover:border-cyan-500/30 transition-colors",children:[(0,b.jsx)("h2",{className:"text-sm font-semibold text-gray-300",children:"API Tokens"}),(0,b.jsx)("p",{className:"text-xs text-gray-500 mt-2",children:"Create and manage tokens for CLI access."}),(0,b.jsx)("span",{className:"text-xs text-cyan-400 mt-3 inline-block",children:"Manage →"})]}),(0,b.jsxs)(d.default,{href:"/settings/networks",className:"bg-[#161618] border border-[#26262b] rounded-xl p-5 hover:border-cyan-500/30 transition-colors",children:[(0,b.jsx)("h2",{className:"text-sm font-semibold text-gray-300",children:"Networks"}),(0,b.jsx)("p",{className:"text-xs text-gray-500 mt-2",children:"Create, manage, and delete agent networks."}),(0,b.jsx)("span",{className:"text-xs text-cyan-400 mt-3 inline-block",children:"Manage →"})]}),(0,b.jsxs)(d.default,{href:"/settings/providers",className:"bg-[#161618] border border-[#26262b] rounded-xl p-5 hover:border-cyan-500/30 transition-colors",children:[(0,b.jsx)("h2",{className:"text-sm font-semibold text-gray-300",children:"Model Providers"}),(0,b.jsx)("p",{className:"text-xs text-gray-500 mt-2",children:"Configure model providers and per-server reachability."}),(0,b.jsx)("span",{className:"text-xs text-cyan-400 mt-3 inline-block",children:"Manage →"})]}),(0,b.jsxs)(d.default,{href:"/messages",className:"bg-[#161618] border border-[#26262b] rounded-xl p-5 hover:border-cyan-500/30 transition-colors",children:[(0,b.jsx)("h2",{className:"text-sm font-semibold text-gray-300",children:"Messages"}),(0,b.jsx)("p",{className:"text-xs text-gray-500 mt-2",children:"Global timeline of CommHub messages across all agents."}),(0,b.jsx)("span",{className:"text-xs text-cyan-400 mt-3 inline-block",children:"Open →"})]}),(0,b.jsxs)(d.default,{href:"/logs",className:"bg-[#161618] border border-[#26262b] rounded-xl p-5 hover:border-cyan-500/30 transition-colors",children:[(0,b.jsx)("h2",{className:"text-sm font-semibold text-gray-300",children:"Audit Log"}),(0,b.jsx)("p",{className:"text-xs text-gray-500 mt-2",children:"Authentication, token rotations, and admin actions."}),(0,b.jsx)("span",{className:"text-xs text-cyan-400 mt-3 inline-block",children:"Open →"})]}),(0,b.jsxs)(d.default,{href:"/server-logs",className:"bg-[#161618] border border-[#26262b] rounded-xl p-5 hover:border-cyan-500/30 transition-colors",children:[(0,b.jsx)("h2",{className:"text-sm font-semibold text-gray-300",children:"Server Logs"}),(0,b.jsx)("p",{className:"text-xs text-gray-500 mt-2",children:"Live stdout / stderr from the CommHub server."}),(0,b.jsx)("span",{className:"text-xs text-cyan-400 mt-3 inline-block",children:"Open →"})]})]})]})]})]})}])}];
2
-
3
- //# sourceMappingURL=dash-492_agent-network-dashboard_app_02~ml1y._.js.map
@@ -1,3 +0,0 @@
1
- module.exports=[21487,a=>{"use strict";var b=a.i(10571),c=a.i(53705);let d=async a=>{let b=await fetch(a);if(401===b.status)throw window.location.assign("/login"),Error("unauthorized");return b.json()},e={refreshInterval:5e3,dedupingInterval:3e3};function f(a,b){if(!b)return a;let c=a.includes("?")?"&":"?";return`${a}${c}network_id=${encodeURIComponent(b)}`}a.s(["useAnetConfig",0,function(){let{data:a}=(0,b.default)("/api/anet/config",d,{refreshInterval:3e4});return{config:a||null}},"useHealth",0,function(){let{data:a,error:c}=(0,b.default)("/api/hub/health",d,e);return{health:a||null,error:c}},"useMessages",0,function(a=100){let{networkId:g}=(0,c.useNetworkId)(),{data:h,error:i,isLoading:j}=(0,b.default)(f(`/api/hub/messages?limit=${a}`,g),d,{...e,keepPreviousData:!0});return{messages:h?.messages||[],error:i,isLoading:j}},"useNodeLifecycle",0,function(){let{networkId:a}=(0,c.useNetworkId)(),{data:g,error:h,mutate:i}=(0,b.default)(f("/api/hub/nodes",a),d,e),j={},k={},l={};for(let a of g?.nodes??[])a.alias&&"string"==typeof a.lifecycle_state&&(j[a.alias]=a.lifecycle_state),a.alias&&"string"==typeof a.node_id&&(k[a.alias]=a.node_id),a.alias&&(l[a.alias]={display_name:"string"==typeof a.display_name?a.display_name:null,team:"string"==typeof a.team?a.team:null,tags:Array.isArray(a.tags)?a.tags:[],attrs_revision:"number"==typeof a.attrs_revision?a.attrs_revision:0});return{lifecycleByAlias:j,nodeIdByAlias:k,attrsByAlias:l,error:h,refreshNodes:i}},"useSessions",0,function(){let{networkId:a}=(0,c.useNetworkId)(),{data:g,error:h,isLoading:i}=(0,b.default)(f("/api/hub/status",a),d,e);return{sessions:g?.sessions||[],hint:g?._hint,error:h,isLoading:i}},"useStats",0,function(){let{networkId:a}=(0,c.useNetworkId)(),{data:g,error:h}=(0,b.default)(f("/api/hub/stats",a),d,e);return{stats:g?.ok?g:null,error:h}},"useTasks",0,function(a){let{networkId:g}=(0,c.useNetworkId)(),h=new URLSearchParams({limit:"100",...a}).toString(),{data:i,error:j,isLoading:k}=(0,b.default)(f(`/api/hub/tasks?${h}`,g),d,e);return{tasks:i?.tasks||[],count:i?.count??0,source:i?.source,error:j,isLoading:k}}])},9878,a=>{"use strict";var b=a.i(5400),c=a.i(82956);let d=new Set(["png","jpg","jpeg","gif","webp","mp4","webm","mov"]),e=new Set(["image/png","image/jpeg","image/gif","image/webp"]),f=new Set(["video/mp4","video/webm"]),g=/^[A-Za-z0-9_-]{8,64}$/;async function h(a){let b=await fetch(`/api/hub/files/${encodeURIComponent(a)}`,{credentials:"include"});if(!b.ok)throw Error(`HTTP ${b.status}`);let c=b.headers.get("x-verified-type"),d=c&&(e.has(c)||f.has(c))?c:null,g=await b.blob(),h=d?new Blob([g],{type:d}):g;return{blobUrl:URL.createObjectURL(h),verifiedType:d,blob:h}}function i(a){let b=a.lastIndexOf(".");return b>=0?a.slice(b+1).toLowerCase():""}function j({fileId:a,name:d,size:f,onNotInlineable:g}){let i="number"==typeof f&&f<=5242880,[k,l]=(0,c.useState)(null),[m,n]=(0,c.useState)(!1),[o,p]=(0,c.useState)(!1),q=(0,c.useRef)(g);q.current=g;let r=(0,c.useCallback)(async()=>{if(!m&&!k){n(!0);try{let{blobUrl:b,verifiedType:c}=await h(a);if(!c||!e.has(c)){URL.revokeObjectURL(b),q.current();return}l(b)}catch{p(!0)}finally{n(!1)}}},[a,m,k]);return((0,c.useEffect)(()=>{i&&r()},[i,r]),(0,c.useEffect)(()=>{if(k)return()=>URL.revokeObjectURL(k)},[k]),o)?(0,b.jsx)("div",{className:"mt-2 rounded-lg border border-amber-500/20 bg-amber-500/5 px-3 py-2 text-sm text-amber-200",children:"图片加载失败 · 请点击下方下载按钮查看"}):k?(0,b.jsx)("div",{className:"mt-2 overflow-hidden rounded-lg border border-white/10 bg-black/20",children:(0,b.jsx)("img",{src:k,alt:d,className:"block max-h-[50vh] w-auto max-w-full cursor-zoom-in object-contain",onClick:()=>window.open(k,"_blank","noopener")})}):(0,b.jsxs)("button",{type:"button",onClick:r,disabled:m,className:"mt-2 flex w-full items-center gap-2 rounded-lg border border-cyan-500/20 bg-cyan-500/5 px-3 py-2 text-left text-sm text-cyan-100 transition hover:border-cyan-400/40 hover:bg-cyan-500/10 disabled:cursor-wait disabled:opacity-60",children:[(0,b.jsx)("span",{"aria-hidden":!0,className:"text-lg",children:"🖼️"}),(0,b.jsx)("span",{className:"min-w-0 flex-1 truncate",children:d}),(0,b.jsx)("span",{className:"shrink-0 text-xs text-cyan-300",children:m?"加载中…":"点击查看"})]})}function k({fileId:a,name:d,onNotInlineable:e}){let[g,i]=(0,c.useState)(null),[j,l]=(0,c.useState)(!1),[m,n]=(0,c.useState)(!1),o=(0,c.useRef)(e);o.current=e;let p=(0,c.useCallback)(async()=>{if(!j&&!g){l(!0);try{let{blobUrl:b,verifiedType:c}=await h(a);if(!c||!f.has(c)){URL.revokeObjectURL(b),o.current();return}i(b)}catch{n(!0)}finally{l(!1)}}},[a,j,g]);return((0,c.useEffect)(()=>{if(g)return()=>URL.revokeObjectURL(g)},[g]),m)?(0,b.jsx)("div",{className:"mt-2 rounded-lg border border-amber-500/20 bg-amber-500/5 px-3 py-2 text-sm text-amber-200",children:"视频加载失败 · 请点击下方下载按钮查看"}):g?(0,b.jsx)("div",{className:"mt-2 overflow-hidden rounded-lg border border-white/10 bg-black/20",children:(0,b.jsx)("video",{src:g,controls:!0,autoPlay:!0,className:"block max-h-[50vh] w-full",children:"您的浏览器不支持内联视频播放,请下载后查看。"})}):(0,b.jsxs)("button",{type:"button",onClick:p,disabled:j,className:"mt-2 flex w-full items-center gap-2 rounded-lg border border-cyan-500/20 bg-cyan-500/5 px-3 py-2 text-left text-sm text-cyan-100 transition hover:border-cyan-400/40 hover:bg-cyan-500/10 disabled:cursor-wait disabled:opacity-60",children:[(0,b.jsx)("span",{"aria-hidden":!0,className:"text-lg",children:"🎬"}),(0,b.jsx)("span",{className:"min-w-0 flex-1 truncate",children:d}),(0,b.jsx)("span",{className:"shrink-0 text-xs text-cyan-300",children:j?"加载中…":"▶ 播放"})]})}a.s(["AttachmentBlock",0,function({attachment:a}){var h,l;let m,n,[o,p]=(0,c.useState)(!1),[q,r]=(0,c.useState)(null),[s,t]=(0,c.useState)(!1),u=function(a){if("string"!=typeof a||0===a.length)return"file";let b=a.replace(/[/\\]/g,"_").replace(/[\r\n\t\0]/g,"_");for(;b.startsWith(".");)b=b.slice(1);return b.length>200&&(b=b.slice(0,200)),b||"file"}(a.name),v="string"!=typeof(h=a.mime)?"":h.replace(/[^a-zA-Z0-9./+-]/g,"").slice(0,100),w="number"!=typeof(l=a.size)||!Number.isFinite(l)||l<0?"":l<1024?`${l} B`:l<1048576?`${(l/1024).toFixed(1)} KB`:l<0x40000000?`${(l/1024/1024).toFixed(1)} MB`:`${(l/1024/1024/1024).toFixed(2)} GB`,x=(m=(v||"").toLowerCase(),n=(u.split(".").pop()||"").toLowerCase(),m.startsWith("image/")?"🖼️":m.startsWith("video/")?"🎬":m.startsWith("audio/")?"🎵":m.includes("pdf")||"pdf"===n?"📄":["ppt","pptx"].includes(n)?"📊":["doc","docx"].includes(n)?"📝":["xls","xlsx","csv"].includes(n)?"📈":["zip","tar","gz","rar","7z"].includes(n)?"📦":"📎"),y="string"==typeof a.file_id&&g.test(a.file_id),z=y&&!s&&function(a,b){if(e.has(b)||f.has(b))return!0;let c=i(a);return""!==c&&d.has(c)}(u,v),A=i(u),B=z?f.has(v)||["mp4","webm","mov"].includes(A)?"video":"image":null;async function C(){if(!y||!a.file_id)return;r(null),p(!0);let b=null;try{let c=await fetch(`/api/hub/files/${encodeURIComponent(a.file_id)}`,{credentials:"include"});if(!c.ok)throw Error(`HTTP ${c.status}`);let d=await c.blob();b=URL.createObjectURL(d);let e=document.createElement("a");e.href=b,e.download=u,e.rel="noopener",document.body.appendChild(e),e.click(),document.body.removeChild(e)}catch(a){r(a instanceof Error?a.message:String(a))}finally{b&&URL.revokeObjectURL(b),p(!1)}}return y?(0,b.jsxs)("div",{className:"mt-2 flex flex-col",children:["image"===B&&a.file_id&&(0,b.jsx)(j,{fileId:a.file_id,name:u,size:"number"==typeof a.size?a.size:void 0,onNotInlineable:()=>t(!0)}),"video"===B&&a.file_id&&(0,b.jsx)(k,{fileId:a.file_id,name:u,onNotInlineable:()=>t(!0)}),(0,b.jsxs)("button",{type:"button",onClick:C,disabled:o,className:"flex w-full items-center gap-2 rounded-lg border border-cyan-500/20 bg-cyan-500/5 px-3 py-2 text-left text-sm text-cyan-100 transition hover:border-cyan-400/40 hover:bg-cyan-500/10 disabled:cursor-wait disabled:opacity-60 mt-2 first:mt-0",title:`Download ${u}`,children:[(0,b.jsx)("span",{"aria-hidden":!0,className:"text-lg",children:x}),(0,b.jsx)("span",{className:"min-w-0 flex-1 truncate",children:u}),w&&(0,b.jsx)("span",{className:"shrink-0 text-xs text-neutral-400",children:w}),v&&(0,b.jsx)("span",{className:"shrink-0 rounded bg-white/5 px-1.5 py-0.5 text-[10px] text-neutral-400",children:v}),(0,b.jsx)("span",{className:"shrink-0 text-xs text-cyan-300",children:o?"下载中…":q?`⚠ ${q}`:"↓ 下载"})]})]}):(0,b.jsxs)("div",{className:"mt-2 flex items-center gap-2 rounded-lg border border-white/10 bg-white/5 px-3 py-2 text-sm text-neutral-300",children:[(0,b.jsx)("span",{"aria-hidden":!0,children:x}),(0,b.jsx)("span",{className:"min-w-0 flex-1 truncate",children:u}),w&&(0,b.jsx)("span",{className:"shrink-0 text-xs text-neutral-500",children:w}),(0,b.jsx)("span",{className:"shrink-0 text-xs text-neutral-500",title:"Attachment has no file_id — single-host path only. Ask the sender to re-upload.",children:"(host-local)"})]})},"extractAttachments",0,function(a){if(!a||"object"!=typeof a)return[];let b=a.meta;if(!b&&"string"==typeof a.meta_json&&a.meta_json.length>0)try{b=JSON.parse(a.meta_json)}catch{return[]}if(!b||"object"!=typeof b)return[];let c=b.attachments;return Array.isArray(c)?c.filter(a=>!!a&&"object"==typeof a).map(a=>({file_id:"string"==typeof a.file_id?a.file_id:void 0,path:"string"==typeof a.path?a.path:void 0,name:"string"==typeof a.name?a.name:void 0,mime:"string"==typeof a.mime?a.mime:void 0,size:"number"==typeof a.size?a.size:void 0,type:"string"==typeof a.type?a.type:void 0})):[]}])},78604,68088,a=>{"use strict";var b=a.i(82956);let c=new Set;function d(a){return c.add(a),()=>void c.delete(a)}a.s(["pinyinMatch",0,function(a,b){let c=b.trim().toLowerCase();return!!(!c||a.toLowerCase().includes(c))||!1},"usePinyinReady",0,function(){return(0,b.useSyncExternalStore)(d,()=>!1,()=>!1)}],78604),a.s(["t",0,function(a,b){return"u">typeof navigator&&(navigator.language||"").toLowerCase().startsWith("zh")?a:b}],68088)}];
2
-
3
- //# sourceMappingURL=dash-492_agent-network-dashboard_app_04nejob._.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../../../dash-492/agent-network-dashboard/app/lib/hooks.ts","../../../../../../dash-492/agent-network-dashboard/app/components/AttachmentBlock.tsx","../../../../../../dash-492/agent-network-dashboard/app/lib/pinyin-match.ts","../../../../../../dash-492/agent-network-dashboard/app/lib/ui-lang.ts"],"sourcesContent":["import useSWR from 'swr';\nimport { Session, Health, AnetConfig } from '../components/types';\nimport { useNetworkId } from './network-context';\n\nconst fetcher = async (url: string) => {\n const res = await fetch(url);\n if (res.status === 401) {\n window.location.assign('/login');\n throw new Error('unauthorized');\n }\n return res.json();\n};\n\nconst SWR_OPTIONS = { refreshInterval: 5000, dedupingInterval: 3000 };\n\n/** Append network_id to URL if set */\nfunction withNetwork(url: string, networkId: string): string {\n if (!networkId) return url;\n const sep = url.includes('?') ? '&' : '?';\n return `${url}${sep}network_id=${encodeURIComponent(networkId)}`;\n}\n\nexport function useSessions() {\n const { networkId } = useNetworkId();\n const { data, error, isLoading } = useSWR<{ sessions: Session[]; _hint?: { global_count?: number; filtered_network?: string } }>(\n withNetwork('/api/hub/status', networkId),\n fetcher,\n SWR_OPTIONS,\n );\n return { sessions: data?.sessions || [], hint: data?._hint, error, isLoading };\n}\n\n// RFC-027 PR2 — alias → lifecycle_state map sourced from /api/nodes\n// (commhub-server preview.12+). /api/status reads from `sessions` which\n// doesn't carry lifecycle_state; /api/nodes does. Cheap secondary\n// fetch, same SWR cadence as useSessions; merged client-side by alias.\n// Absent alias → caller defaults to 'active'.\ninterface NodeAttrsSnapshot {\n display_name: string | null;\n team: string | null;\n tags: string[];\n attrs_revision: number;\n}\ninterface NodesResp { nodes?: Array<{\n alias?: string;\n node_id?: string;\n lifecycle_state?: string | null;\n // #492 goal-item-3: node display attributes (hub PR #497). Legacy\n // rows read as null/[]/0 respectively — no guard needed by callers.\n display_name?: string | null;\n team?: string | null;\n tags?: string[];\n attrs_revision?: number;\n}>; }\nexport function useNodeLifecycle() {\n const { networkId } = useNetworkId();\n const { data, error, mutate } = useSWR<NodesResp>(\n withNetwork('/api/hub/nodes', networkId),\n fetcher,\n SWR_OPTIONS,\n );\n const lifecycleByAlias: Record<string, string> = {};\n const nodeIdByAlias: Record<string, string> = {};\n const attrsByAlias: Record<string, NodeAttrsSnapshot> = {};\n for (const n of data?.nodes ?? []) {\n if (n.alias && typeof n.lifecycle_state === 'string') lifecycleByAlias[n.alias] = n.lifecycle_state;\n if (n.alias && typeof n.node_id === 'string') nodeIdByAlias[n.alias] = n.node_id;\n if (n.alias) {\n attrsByAlias[n.alias] = {\n display_name: typeof n.display_name === 'string' ? n.display_name : null,\n team: typeof n.team === 'string' ? n.team : null,\n tags: Array.isArray(n.tags) ? n.tags : [],\n attrs_revision: typeof n.attrs_revision === 'number' ? n.attrs_revision : 0,\n };\n }\n }\n return { lifecycleByAlias, nodeIdByAlias, attrsByAlias, error, refreshNodes: mutate };\n}\nexport type { NodeAttrsSnapshot };\n\nexport function useHealth() {\n const { data, error } = useSWR<Health>('/api/hub/health', fetcher, SWR_OPTIONS);\n return { health: data || null, error };\n}\n\nexport function useAnetConfig() {\n const { data } = useSWR<AnetConfig>('/api/anet/config', fetcher, { refreshInterval: 30000 });\n return { config: data || null };\n}\n\nexport function useTasks(params?: Record<string, string>) {\n const { networkId } = useNetworkId();\n const query = new URLSearchParams({ limit: '100', ...params }).toString();\n const { data, error, isLoading } = useSWR(\n withNetwork(`/api/hub/tasks?${query}`, networkId),\n fetcher,\n SWR_OPTIONS,\n );\n return {\n tasks: data?.tasks || [],\n count: data?.count ?? 0,\n source: data?.source,\n error,\n isLoading,\n };\n}\n\nexport function useStats() {\n const { networkId } = useNetworkId();\n const { data, error } = useSWR(withNetwork('/api/hub/stats', networkId), fetcher, SWR_OPTIONS);\n return { stats: data?.ok ? data : null, error };\n}\n\nexport function useMessages(limit = 100) {\n const { networkId } = useNetworkId();\n // keepPreviousData: /messages grows `limit` when the user asks for older\n // history (#217 M5) — without it the key change would blank the list and\n // flash the skeleton while the bigger page is in flight.\n const { data, error, isLoading } = useSWR(\n withNetwork(`/api/hub/messages?limit=${limit}`, networkId),\n fetcher,\n { ...SWR_OPTIONS, keepPreviousData: true },\n );\n return { messages: data?.messages || [], error, isLoading };\n}\n","'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\n// ── #492 preview half — inline image/video display ───────────────\n//\n// See docs/design-492-inline-preview.md for the full design rationale\n// (通信龙 v2 review approved the \"never inline\" structure).\n//\n// The proxy at /api/hub/files/[fileId] ALWAYS returns bytes with\n// `Content-Disposition: attachment` + `nosniff`. It also stamps a\n// `X-Verified-Type` header when the file matches a magic-bytes-verified\n// safe-media type. Client:\n// 1. Fetches via the download proxy (browser downloads bytes to memory)\n// 2. Reads `X-Verified-Type` — if absent, falls back to download card\n// 3. Constructs `new Blob([bytes], {type: X-Verified-Type})`\n// 4. `URL.createObjectURL(blob)` → `<img>` / `<video>` src\n//\n// The blob URL is a browser-owned handle, isolated from the dashboard\n// origin. A whitelist bug can degrade rendering (image won't load) but\n// can NEVER become an XSS on the dashboard origin.\n\n/** Client-side ext hint — used ONLY to decide whether it's worth\n * fetching the file to try the preview. The SERVER decides\n * authoritatively whether to expose `X-Verified-Type` via magic\n * bytes; this list just avoids fetching a PDF just to learn it\n * isn't inline-able. Under-selection here = missed preview\n * opportunity (only a UX cost). Over-selection = wasted fetch that\n * falls back to card (only a bandwidth cost). Nothing security. */\nconst PREVIEW_HINT_EXTS = new Set([\n 'png', 'jpg', 'jpeg', 'gif', 'webp',\n 'mp4', 'webm', 'mov', // .mov may or may not verify as mp4; server decides\n]);\n\nconst IMAGE_MIMES = new Set(['image/png', 'image/jpeg', 'image/gif', 'image/webp']);\nconst VIDEO_MIMES = new Set(['video/mp4', 'video/webm']);\n\n/** Auto-load images below this size. Larger images render as a\n * click-to-load card to protect mobile bandwidth. Vincent uses this\n * on his phone; a full 12 MiB image auto-loading over a random\n * cellular connection is not the right default. */\nconst IMAGE_AUTOLOAD_MAX_BYTES = 5 * 1024 * 1024;\n\n/**\n * #492 attachment descriptor as it appears in `meta.attachments[]` on\n * inbound tasks/messages. All fields are UNTRUSTED — the upload side\n * chose the name / mime, so treat every string as arbitrary bytes.\n * We render them as plain text, sanitize before use, and never let\n * them influence a URL beyond the strictly-regexed `file_id`.\n */\nexport interface Attachment {\n file_id?: string;\n path?: string;\n name?: string;\n mime?: string;\n size?: number;\n type?: string;\n}\n\n/** Same regex the download proxy uses. Duplicated intentionally — we\n * don't want to bundle a server import into the client. Any change\n * must be made in both places.\n * Mirrors `app/api/hub/files/[fileId]/route.ts:FILE_ID_REGEX`.\n */\nconst FILE_ID_REGEX = /^[A-Za-z0-9_-]{8,64}$/;\n\n/**\n * Sanitize a filename for display AND for the download-attribute on\n * the synthesized anchor. The upload side controls this bytes — we\n * strip anything that would break shell / display / disposition\n * headers. Also clamp length so a 4 KB path can't wall-of-text the\n * bubble.\n *\n * Kept intentionally narrow:\n * - `/` and `\\` → `_` (defeat path traversal in `<a download>`)\n * - control chars (CR/LF/TAB/NUL) → `_`\n * - leading `.` stripped (avoid hidden-file leak on download)\n * - clamp to 200 chars\n * - if empty after all that → `\"file\"` fallback\n */\nfunction sanitizeName(raw: unknown): string {\n if (typeof raw !== 'string' || raw.length === 0) return 'file';\n let s = raw\n .replace(/[/\\\\]/g, '_')\n .replace(/[\\r\\n\\t\\0]/g, '_');\n while (s.startsWith('.')) s = s.slice(1);\n if (s.length > 200) s = s.slice(0, 200);\n return s || 'file';\n}\n\n/**\n * Whitelist the mime for display. Everything outside a conservative\n * set of characters is stripped. Empty → falsy render (block hides\n * the mime chip rather than showing junk).\n */\nfunction sanitizeMime(raw: unknown): string {\n if (typeof raw !== 'string') return '';\n return raw.replace(/[^a-zA-Z0-9./+-]/g, '').slice(0, 100);\n}\n\n/**\n * Format a byte count as `\"12.4 KB\"`. Defensive on non-numeric input.\n * Empty string when the size is missing / negative — the block just\n * omits the size chip in that case.\n */\nfunction formatBytes(bytes: unknown): string {\n if (typeof bytes !== 'number' || !Number.isFinite(bytes) || bytes < 0) return '';\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / 1024 / 1024).toFixed(1)} MB`;\n return `${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB`;\n}\n\n/** Emoji icon by MIME family — informational only, not load-bearing. */\nfunction iconFor(mime: string, name: string): string {\n const lc = (mime || '').toLowerCase();\n const ext = (name.split('.').pop() || '').toLowerCase();\n if (lc.startsWith('image/')) return '🖼️';\n if (lc.startsWith('video/')) return '🎬';\n if (lc.startsWith('audio/')) return '🎵';\n if (lc.includes('pdf') || ext === 'pdf') return '📄';\n if (['ppt', 'pptx'].includes(ext)) return '📊';\n if (['doc', 'docx'].includes(ext)) return '📝';\n if (['xls', 'xlsx', 'csv'].includes(ext)) return '📈';\n if (['zip', 'tar', 'gz', 'rar', '7z'].includes(ext)) return '📦';\n return '📎';\n}\n\n/**\n * Render one attachment as a clickable download block.\n *\n * Click path (#492 hard gate — must produce a byte-identical file):\n * 1. `fetch('/api/hub/files/<file_id>', {credentials:'include'})`\n * — same-origin, session cookie carries auth; the server-side\n * proxy attaches the Bearer token so nothing sensitive is on\n * the client wire OR in browser history / logs.\n * 2. Response body → `blob()` (byte-preserving).\n * 3. `URL.createObjectURL(blob)` → transient blob: URL.\n * 4. Synthetic `<a href=\"blob:\" download=\"<sanitized-name>\">` +\n * programmatic click → browser starts the download using the\n * sanitized filename.\n * 5. `URL.revokeObjectURL()` in a `finally` so the blob is GC'd\n * even if the click flow throws mid-way.\n *\n * If the attachment has no `file_id` (a legacy path-only attachment\n * from a single-host feishu adapter that predates cross-host upload),\n * we render an informational block with the path visible but no\n * download button — the block honestly signals \"can't fetch this\n * cross-host, needs re-upload\".\n *\n * Errors surface via a small inline error string, not `alert()`, so\n * the chat scroll position isn't lost. Two seconds of visible\n * feedback is enough for the user to see + retry.\n */\n/** Shared blob-URL fetcher — returns {blobUrl, verifiedType} or\n * throws. Used by both InlineImage/InlineVideo (for preview) and\n * the download button (for the save-to-disk flow). Caller owns the\n * returned blobUrl lifecycle (must revoke). */\nasync function fetchVerified(fileId: string): Promise<{ blobUrl: string; verifiedType: string | null; blob: Blob }> {\n const res = await fetch(`/api/hub/files/${encodeURIComponent(fileId)}`, {\n credentials: 'include',\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n // Header lookup is case-insensitive; Next's Response uses this pattern.\n const verifiedType = res.headers.get('x-verified-type');\n // Only trust the whitelist values — anything else is dropped so a\n // future server bug can't smuggle an arbitrary type in.\n const trusted =\n verifiedType && (IMAGE_MIMES.has(verifiedType) || VIDEO_MIMES.has(verifiedType))\n ? verifiedType\n : null;\n const rawBlob = await res.blob();\n const blob = trusted ? new Blob([rawBlob], { type: trusted }) : rawBlob;\n return { blobUrl: URL.createObjectURL(blob), verifiedType: trusted, blob };\n}\n\n/** Filename extension helper — lowercase, no dot, empty for extensionless. */\nfunction extOf(name: string): string {\n const i = name.lastIndexOf('.');\n return i >= 0 ? name.slice(i + 1).toLowerCase() : '';\n}\n\n/** True when it's worth trying an inline preview (client-side hint\n * only — server decides authoritatively). */\nfunction shouldTryPreview(name: string, mime: string): boolean {\n if (IMAGE_MIMES.has(mime) || VIDEO_MIMES.has(mime)) return true;\n const ext = extOf(name);\n return ext !== '' && PREVIEW_HINT_EXTS.has(ext);\n}\n\n/**\n * Inline image preview. Auto-loads for images below\n * IMAGE_AUTOLOAD_MAX_BYTES; renders a click-to-load card for larger\n * images (mobile bandwidth protection). If the server doesn't return\n * `X-Verified-Type` in the whitelist, or if the fetch fails, calls\n * `onNotInlineable` so the parent falls back to the download card.\n */\nfunction InlineImage({\n fileId,\n name,\n size,\n onNotInlineable,\n}: {\n fileId: string;\n name: string;\n size: number | undefined;\n onNotInlineable: () => void;\n}) {\n const autoLoad = typeof size === 'number' && size <= IMAGE_AUTOLOAD_MAX_BYTES;\n const [blobUrl, setBlobUrl] = useState<string | null>(null);\n const [loading, setLoading] = useState(false);\n const [failed, setFailed] = useState(false);\n const notInlineableRef = useRef(onNotInlineable);\n notInlineableRef.current = onNotInlineable;\n\n const load = useCallback(async () => {\n if (loading || blobUrl) return;\n setLoading(true);\n try {\n const { blobUrl: url, verifiedType } = await fetchVerified(fileId);\n if (!verifiedType || !IMAGE_MIMES.has(verifiedType)) {\n // Server declined — the file's real type isn't a safe image.\n // Release the URL immediately and hand off to the download card.\n URL.revokeObjectURL(url);\n notInlineableRef.current();\n return;\n }\n setBlobUrl(url);\n } catch {\n setFailed(true);\n } finally {\n setLoading(false);\n }\n }, [fileId, loading, blobUrl]);\n\n useEffect(() => {\n if (autoLoad) void load();\n }, [autoLoad, load]);\n\n // Revoke on unmount OR when blobUrl replaced.\n useEffect(() => {\n if (!blobUrl) return;\n return () => URL.revokeObjectURL(blobUrl);\n }, [blobUrl]);\n\n if (failed) {\n return (\n <div className=\"mt-2 rounded-lg border border-amber-500/20 bg-amber-500/5 px-3 py-2 text-sm text-amber-200\">\n 图片加载失败 · 请点击下方下载按钮查看\n </div>\n );\n }\n\n if (blobUrl) {\n return (\n <div className=\"mt-2 overflow-hidden rounded-lg border border-white/10 bg-black/20\">\n {/* eslint-disable-next-line @next/next/no-img-element -- blob: URL, next/image can't handle */}\n <img\n src={blobUrl}\n alt={name}\n className=\"block max-h-[50vh] w-auto max-w-full cursor-zoom-in object-contain\"\n // \"Open in new tab\" satisfies the \"点开大图\" acceptance gate\n // without threading blob URLs through the multi-image\n // TaskChatPanel lightbox (that integration is a follow-up).\n onClick={() => window.open(blobUrl, '_blank', 'noopener')}\n />\n </div>\n );\n }\n\n // Not loaded yet — either loading spinner or click-to-load card.\n return (\n <button\n type=\"button\"\n onClick={load}\n disabled={loading}\n className=\"mt-2 flex w-full items-center gap-2 rounded-lg border border-cyan-500/20 bg-cyan-500/5 px-3 py-2 text-left text-sm text-cyan-100 transition hover:border-cyan-400/40 hover:bg-cyan-500/10 disabled:cursor-wait disabled:opacity-60\"\n >\n <span aria-hidden className=\"text-lg\">🖼️</span>\n <span className=\"min-w-0 flex-1 truncate\">{name}</span>\n <span className=\"shrink-0 text-xs text-cyan-300\">\n {loading ? '加载中…' : '点击查看'}\n </span>\n </button>\n );\n}\n\n/**\n * Inline video preview. NEVER auto-loads — 5 videos on-screen at\n * 12 MiB each = 60 MiB memory spike. Renders a poster card that\n * fetches + creates the blob only on click, then swaps to\n * `<video controls autoplay>`.\n *\n * Trade-off (per design doc §5.2): blob URL means full file\n * downloaded before first byte plays; there's no range/seek. Fine\n * under the current 12 MiB hub cap; if the cap ever rises, this\n * component needs a real streaming source (server-side signed URL\n * with byte-range support), not a blob.\n */\nfunction InlineVideo({\n fileId,\n name,\n onNotInlineable,\n}: {\n fileId: string;\n name: string;\n onNotInlineable: () => void;\n}) {\n const [blobUrl, setBlobUrl] = useState<string | null>(null);\n const [loading, setLoading] = useState(false);\n const [failed, setFailed] = useState(false);\n const notInlineableRef = useRef(onNotInlineable);\n notInlineableRef.current = onNotInlineable;\n\n const load = useCallback(async () => {\n if (loading || blobUrl) return;\n setLoading(true);\n try {\n const { blobUrl: url, verifiedType } = await fetchVerified(fileId);\n if (!verifiedType || !VIDEO_MIMES.has(verifiedType)) {\n URL.revokeObjectURL(url);\n notInlineableRef.current();\n return;\n }\n setBlobUrl(url);\n } catch {\n setFailed(true);\n } finally {\n setLoading(false);\n }\n }, [fileId, loading, blobUrl]);\n\n useEffect(() => {\n if (!blobUrl) return;\n return () => URL.revokeObjectURL(blobUrl);\n }, [blobUrl]);\n\n if (failed) {\n return (\n <div className=\"mt-2 rounded-lg border border-amber-500/20 bg-amber-500/5 px-3 py-2 text-sm text-amber-200\">\n 视频加载失败 · 请点击下方下载按钮查看\n </div>\n );\n }\n\n if (blobUrl) {\n return (\n <div className=\"mt-2 overflow-hidden rounded-lg border border-white/10 bg-black/20\">\n <video\n src={blobUrl}\n controls\n autoPlay\n className=\"block max-h-[50vh] w-full\"\n >\n 您的浏览器不支持内联视频播放,请下载后查看。\n </video>\n </div>\n );\n }\n\n return (\n <button\n type=\"button\"\n onClick={load}\n disabled={loading}\n className=\"mt-2 flex w-full items-center gap-2 rounded-lg border border-cyan-500/20 bg-cyan-500/5 px-3 py-2 text-left text-sm text-cyan-100 transition hover:border-cyan-400/40 hover:bg-cyan-500/10 disabled:cursor-wait disabled:opacity-60\"\n >\n <span aria-hidden className=\"text-lg\">🎬</span>\n <span className=\"min-w-0 flex-1 truncate\">{name}</span>\n <span className=\"shrink-0 text-xs text-cyan-300\">\n {loading ? '加载中…' : '▶ 播放'}\n </span>\n </button>\n );\n}\n\nexport function AttachmentBlock({ attachment }: { attachment: Attachment }) {\n const [downloading, setDownloading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n // Ext-based hint says \"try preview\" — set to false after the\n // server declines (no X-Verified-Type) or after a hard fetch\n // failure. Once false, only the download card renders.\n const [previewGivenUp, setPreviewGivenUp] = useState(false);\n\n const safeName = sanitizeName(attachment.name);\n const safeMime = sanitizeMime(attachment.mime);\n const safeSize = formatBytes(attachment.size);\n const icon = iconFor(safeMime, safeName);\n\n const hasValidFileId =\n typeof attachment.file_id === 'string' && FILE_ID_REGEX.test(attachment.file_id);\n\n const tryPreview = hasValidFileId && !previewGivenUp && shouldTryPreview(safeName, safeMime);\n const ext = extOf(safeName);\n // Client hint only — server verifies. We just pick which preview\n // component to try first. If the ext is ambiguous (e.g. missing),\n // default to image since image detection is cheap and safe.\n const previewKind: 'image' | 'video' | null = tryPreview\n ? (VIDEO_MIMES.has(safeMime) || ['mp4', 'webm', 'mov'].includes(ext) ? 'video' : 'image')\n : null;\n\n async function handleDownload() {\n if (!hasValidFileId || !attachment.file_id) return;\n setError(null);\n setDownloading(true);\n let objectUrl: string | null = null;\n try {\n const res = await fetch(\n `/api/hub/files/${encodeURIComponent(attachment.file_id)}`,\n { credentials: 'include' },\n );\n if (!res.ok) {\n throw new Error(`HTTP ${res.status}`);\n }\n const blob = await res.blob();\n objectUrl = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = objectUrl;\n a.download = safeName;\n // rel=\"noopener\" — belt on the synthetic click.\n a.rel = 'noopener';\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n } catch (e: unknown) {\n setError(e instanceof Error ? e.message : String(e));\n } finally {\n if (objectUrl) URL.revokeObjectURL(objectUrl);\n setDownloading(false);\n }\n }\n\n // path-only attachment (legacy) — no download button, just an\n // informational tile so the user knows what was sent even if we\n // can't fetch it.\n if (!hasValidFileId) {\n return (\n <div className=\"mt-2 flex items-center gap-2 rounded-lg border border-white/10 bg-white/5 px-3 py-2 text-sm text-neutral-300\">\n <span aria-hidden>{icon}</span>\n <span className=\"min-w-0 flex-1 truncate\">{safeName}</span>\n {safeSize && <span className=\"shrink-0 text-xs text-neutral-500\">{safeSize}</span>}\n <span\n className=\"shrink-0 text-xs text-neutral-500\"\n title=\"Attachment has no file_id — single-host path only. Ask the sender to re-upload.\"\n >\n (host-local)\n </span>\n </div>\n );\n }\n\n return (\n <div className=\"mt-2 flex flex-col\">\n {/* Inline preview: rendered when ext hint suggests media and the\n server hasn't declined yet. On decline (`onNotInlineable`) or\n hard failure, we drop back to just the download card below. */}\n {previewKind === 'image' && attachment.file_id && (\n <InlineImage\n fileId={attachment.file_id}\n name={safeName}\n size={typeof attachment.size === 'number' ? attachment.size : undefined}\n onNotInlineable={() => setPreviewGivenUp(true)}\n />\n )}\n {previewKind === 'video' && attachment.file_id && (\n <InlineVideo\n fileId={attachment.file_id}\n name={safeName}\n onNotInlineable={() => setPreviewGivenUp(true)}\n />\n )}\n {/* Download card — always available for save-to-disk, even when\n the preview is shown. Users still need a way to save a copy\n off the ephemeral blob URL. */}\n <button\n type=\"button\"\n onClick={handleDownload}\n disabled={downloading}\n className=\"flex w-full items-center gap-2 rounded-lg border border-cyan-500/20 bg-cyan-500/5 px-3 py-2 text-left text-sm text-cyan-100 transition hover:border-cyan-400/40 hover:bg-cyan-500/10 disabled:cursor-wait disabled:opacity-60 mt-2 first:mt-0\"\n title={`Download ${safeName}`}\n >\n <span aria-hidden className=\"text-lg\">{icon}</span>\n <span className=\"min-w-0 flex-1 truncate\">{safeName}</span>\n {safeSize && <span className=\"shrink-0 text-xs text-neutral-400\">{safeSize}</span>}\n {safeMime && (\n <span className=\"shrink-0 rounded bg-white/5 px-1.5 py-0.5 text-[10px] text-neutral-400\">\n {safeMime}\n </span>\n )}\n <span className=\"shrink-0 text-xs text-cyan-300\">\n {downloading ? '下载中…' : error ? `⚠ ${error}` : '↓ 下载'}\n </span>\n </button>\n </div>\n );\n}\n\n/**\n * Parse `attachments[]` from a message-like row. Accepts both the\n * pre-parsed `meta.attachments` shape and the raw `meta_json` string\n * shape (hub returns the latter from `SELECT *` on the tasks table\n * because SQLite stores meta_json as TEXT).\n *\n * Returns `[]` for anything that isn't a shape-valid array of objects\n * — never throws. Callers can render freely without try/catch.\n */\nexport function extractAttachments(row: unknown): Attachment[] {\n if (!row || typeof row !== 'object') return [];\n const record = row as Record<string, unknown>;\n\n // Try pre-parsed `meta` first.\n let meta: unknown = record.meta;\n\n // Fall back to `meta_json` (raw TEXT column).\n if (!meta && typeof record.meta_json === 'string' && record.meta_json.length > 0) {\n try {\n meta = JSON.parse(record.meta_json);\n } catch {\n return [];\n }\n }\n\n if (!meta || typeof meta !== 'object') return [];\n const metaObj = meta as Record<string, unknown>;\n const raw = metaObj.attachments;\n if (!Array.isArray(raw)) return [];\n\n return raw\n .filter((a): a is Record<string, unknown> => !!a && typeof a === 'object')\n .map((a) => ({\n file_id: typeof a.file_id === 'string' ? a.file_id : undefined,\n path: typeof a.path === 'string' ? a.path : undefined,\n name: typeof a.name === 'string' ? a.name : undefined,\n mime: typeof a.mime === 'string' ? a.mime : undefined,\n size: typeof a.size === 'number' ? a.size : undefined,\n type: typeof a.type === 'string' ? a.type : undefined,\n }));\n}\n","'use client';\n\nimport { useSyncExternalStore } from 'react';\n\n/* Loop R25: one pinyin matcher for every search surface (chat @-mentions,\n * /nodes, /messages). pinyin-pro stays a LAZY chunk — the dict loads on the\n * first non-empty filter, never on page load. Matching = substring OR full\n * pinyin OR initials, cached per string. Callers pair pinyinMatch() with\n * usePinyinReady() so results upgrade in place once the dict arrives. */\n\ntype PinyinFn = (text: string) => [string, string];\n\nlet py: PinyinFn | null = null;\nlet loadStarted = false;\nconst listeners = new Set<() => void>();\nconst cache = new Map<string, [string, string]>();\n\nfunction ensureLoaded() {\n if (py || loadStarted || typeof window === 'undefined') return;\n loadStarted = true;\n import('pinyin-pro')\n .then((m) => {\n py = (text: string) => [\n m.pinyin(text, { toneType: 'none', type: 'array' }).join('').toLowerCase(),\n m.pinyin(text, { pattern: 'first', toneType: 'none', type: 'array' }).join('').toLowerCase(),\n ];\n listeners.forEach((l) => l());\n })\n .catch(() => { loadStarted = false; });\n}\n\nexport function pinyinMatch(text: string, filter: string): boolean {\n const f = filter.trim().toLowerCase();\n if (!f) return true;\n if (text.toLowerCase().includes(f)) return true;\n ensureLoaded();\n if (!py) return false;\n let entry = cache.get(text);\n if (!entry) { entry = py(text); cache.set(text, entry); }\n return entry[0].includes(f) || entry[1].includes(f);\n}\n\nfunction subscribeReady(callback: () => void) {\n listeners.add(callback);\n return () => void listeners.delete(callback);\n}\n\n/** True once the pinyin dict is loaded — subscribe so the component\n * re-filters when lazy loading completes mid-typing. */\nexport function usePinyinReady(): boolean {\n return useSyncExternalStore(subscribeReady, () => Boolean(py), () => false);\n}\n","'use client';\n\n// Loop R18 (R3 i18n 还债, scoped): the WeChat-loop rounds introduced\n// user-visible Chinese strings (pill, drafts, search, lightbox, retry).\n// English-locale users saw mixed-language chrome. All call sites render\n// only after client interaction/data (never in SSR HTML), so a plain\n// navigator.language check is hydration-safe here.\nexport function isZh(): boolean {\n return typeof navigator !== 'undefined' && (navigator.language || '').toLowerCase().startsWith('zh');\n}\n\nexport function t(zh: string, en: string): string {\n return isZh() ? zh : en;\n}\n"],"names":["fetcher","url","res","fetch","status","window","location","assign","Error","json","SWR_OPTIONS","refreshInterval","dedupingInterval","withNetwork","networkId","sep","includes","encodeURIComponent","useSessions","data","error","isLoading","sessions","hint","_hint","useNodeLifecycle","mutate","lifecycleByAlias","nodeIdByAlias","attrsByAlias","n","nodes","alias","lifecycle_state","node_id","display_name","team","tags","Array","isArray","attrs_revision","refreshNodes","useHealth","health","useAnetConfig","config","useTasks","params","query","URLSearchParams","limit","toString","tasks","count","source","useStats","stats","ok","useMessages","keepPreviousData","messages","PREVIEW_HINT_EXTS","Set","IMAGE_MIMES","VIDEO_MIMES","IMAGE_AUTOLOAD_MAX_BYTES","FILE_ID_REGEX","sanitizeName","raw","length","s","replace","startsWith","slice","sanitizeMime","formatBytes","bytes","Number","isFinite","toFixed","iconFor","mime","name","lc","toLowerCase","ext","split","pop","fetchVerified","fileId","credentials","verifiedType","headers","get","trusted","has","rawBlob","blob","Blob","type","blobUrl","URL","createObjectURL","extOf","i","lastIndexOf","shouldTryPreview","InlineImage","size","onNotInlineable","autoLoad","setBlobUrl","loading","setLoading","failed","setFailed","notInlineableRef","current","load","revokeObjectURL","className","src","alt","onClick","open","disabled","InlineVideo","controls","autoPlay","AttachmentBlock","attachment","downloading","setDownloading","setError","previewGivenUp","setPreviewGivenUp","safeName","safeMime","safeSize","icon","hasValidFileId","file_id","test","tryPreview","previewKind","handleDownload","objectUrl","a","document","createElement","href","download","rel","body","appendChild","click","removeChild","e","message","String","title","undefined","extractAttachments","row","record","meta","meta_json","JSON","parse","metaObj","attachments","filter","map","path","py","loadStarted","listeners","cache","Map","ensureLoaded","pinyinMatch","text","f","trim","entry","set","subscribeReady","callback","add","delete","usePinyinReady","Boolean"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- module.exports=[21487,a=>{"use strict";var b=a.i(10571),c=a.i(53705);let d=async a=>{let b=await fetch(a);if(401===b.status)throw window.location.assign("/login"),Error("unauthorized");return b.json()},e={refreshInterval:5e3,dedupingInterval:3e3};function f(a,b){if(!b)return a;let c=a.includes("?")?"&":"?";return`${a}${c}network_id=${encodeURIComponent(b)}`}a.s(["useAnetConfig",0,function(){let{data:a}=(0,b.default)("/api/anet/config",d,{refreshInterval:3e4});return{config:a||null}},"useHealth",0,function(){let{data:a,error:c}=(0,b.default)("/api/hub/health",d,e);return{health:a||null,error:c}},"useMessages",0,function(a=100){let{networkId:g}=(0,c.useNetworkId)(),{data:h,error:i,isLoading:j}=(0,b.default)(f(`/api/hub/messages?limit=${a}`,g),d,{...e,keepPreviousData:!0});return{messages:h?.messages||[],error:i,isLoading:j}},"useNodeLifecycle",0,function(){let{networkId:a}=(0,c.useNetworkId)(),{data:g,error:h,mutate:i}=(0,b.default)(f("/api/hub/nodes",a),d,e),j={},k={},l={};for(let a of g?.nodes??[])a.alias&&"string"==typeof a.lifecycle_state&&(j[a.alias]=a.lifecycle_state),a.alias&&"string"==typeof a.node_id&&(k[a.alias]=a.node_id),a.alias&&(l[a.alias]={display_name:"string"==typeof a.display_name?a.display_name:null,team:"string"==typeof a.team?a.team:null,tags:Array.isArray(a.tags)?a.tags:[],attrs_revision:"number"==typeof a.attrs_revision?a.attrs_revision:0});return{lifecycleByAlias:j,nodeIdByAlias:k,attrsByAlias:l,error:h,refreshNodes:i}},"useSessions",0,function(){let{networkId:a}=(0,c.useNetworkId)(),{data:g,error:h,isLoading:i}=(0,b.default)(f("/api/hub/status",a),d,e);return{sessions:g?.sessions||[],hint:g?._hint,error:h,isLoading:i}},"useStats",0,function(){let{networkId:a}=(0,c.useNetworkId)(),{data:g,error:h}=(0,b.default)(f("/api/hub/stats",a),d,e);return{stats:g?.ok?g:null,error:h}},"useTasks",0,function(a){let{networkId:g}=(0,c.useNetworkId)(),h=new URLSearchParams({limit:"100",...a}).toString(),{data:i,error:j,isLoading:k}=(0,b.default)(f(`/api/hub/tasks?${h}`,g),d,e);return{tasks:i?.tasks||[],count:i?.count??0,source:i?.source,error:j,isLoading:k}}])},78604,68088,a=>{"use strict";var b=a.i(82956);let c=new Set;function d(a){return c.add(a),()=>void c.delete(a)}a.s(["pinyinMatch",0,function(a,b){let c=b.trim().toLowerCase();return!!(!c||a.toLowerCase().includes(c))||!1},"usePinyinReady",0,function(){return(0,b.useSyncExternalStore)(d,()=>!1,()=>!1)}],78604),a.s(["t",0,function(a,b){return"u">typeof navigator&&(navigator.language||"").toLowerCase().startsWith("zh")?a:b}],68088)},9878,a=>{"use strict";var b=a.i(5400),c=a.i(82956);let d=new Set(["png","jpg","jpeg","gif","webp","mp4","webm","mov"]),e=new Set(["image/png","image/jpeg","image/gif","image/webp"]),f=new Set(["video/mp4","video/webm"]),g=/^[A-Za-z0-9_-]{8,64}$/;async function h(a){let b=await fetch(`/api/hub/files/${encodeURIComponent(a)}`,{credentials:"include"});if(!b.ok)throw Error(`HTTP ${b.status}`);let c=b.headers.get("x-verified-type"),d=c&&(e.has(c)||f.has(c))?c:null,g=await b.blob(),h=d?new Blob([g],{type:d}):g;return{blobUrl:URL.createObjectURL(h),verifiedType:d,blob:h}}function i(a){let b=a.lastIndexOf(".");return b>=0?a.slice(b+1).toLowerCase():""}function j({fileId:a,name:d,size:f,onNotInlineable:g}){let i="number"==typeof f&&f<=5242880,[k,l]=(0,c.useState)(null),[m,n]=(0,c.useState)(!1),[o,p]=(0,c.useState)(!1),q=(0,c.useRef)(g);q.current=g;let r=(0,c.useCallback)(async()=>{if(!m&&!k){n(!0);try{let{blobUrl:b,verifiedType:c}=await h(a);if(!c||!e.has(c)){URL.revokeObjectURL(b),q.current();return}l(b)}catch{p(!0)}finally{n(!1)}}},[a,m,k]);return((0,c.useEffect)(()=>{i&&r()},[i,r]),(0,c.useEffect)(()=>{if(k)return()=>URL.revokeObjectURL(k)},[k]),o)?(0,b.jsx)("div",{className:"mt-2 rounded-lg border border-amber-500/20 bg-amber-500/5 px-3 py-2 text-sm text-amber-200",children:"图片加载失败 · 请点击下方下载按钮查看"}):k?(0,b.jsx)("div",{className:"mt-2 overflow-hidden rounded-lg border border-white/10 bg-black/20",children:(0,b.jsx)("img",{src:k,alt:d,className:"block max-h-[50vh] w-auto max-w-full cursor-zoom-in object-contain",onClick:()=>window.open(k,"_blank","noopener")})}):(0,b.jsxs)("button",{type:"button",onClick:r,disabled:m,className:"mt-2 flex w-full items-center gap-2 rounded-lg border border-cyan-500/20 bg-cyan-500/5 px-3 py-2 text-left text-sm text-cyan-100 transition hover:border-cyan-400/40 hover:bg-cyan-500/10 disabled:cursor-wait disabled:opacity-60",children:[(0,b.jsx)("span",{"aria-hidden":!0,className:"text-lg",children:"🖼️"}),(0,b.jsx)("span",{className:"min-w-0 flex-1 truncate",children:d}),(0,b.jsx)("span",{className:"shrink-0 text-xs text-cyan-300",children:m?"加载中…":"点击查看"})]})}function k({fileId:a,name:d,onNotInlineable:e}){let[g,i]=(0,c.useState)(null),[j,l]=(0,c.useState)(!1),[m,n]=(0,c.useState)(!1),o=(0,c.useRef)(e);o.current=e;let p=(0,c.useCallback)(async()=>{if(!j&&!g){l(!0);try{let{blobUrl:b,verifiedType:c}=await h(a);if(!c||!f.has(c)){URL.revokeObjectURL(b),o.current();return}i(b)}catch{n(!0)}finally{l(!1)}}},[a,j,g]);return((0,c.useEffect)(()=>{if(g)return()=>URL.revokeObjectURL(g)},[g]),m)?(0,b.jsx)("div",{className:"mt-2 rounded-lg border border-amber-500/20 bg-amber-500/5 px-3 py-2 text-sm text-amber-200",children:"视频加载失败 · 请点击下方下载按钮查看"}):g?(0,b.jsx)("div",{className:"mt-2 overflow-hidden rounded-lg border border-white/10 bg-black/20",children:(0,b.jsx)("video",{src:g,controls:!0,autoPlay:!0,className:"block max-h-[50vh] w-full",children:"您的浏览器不支持内联视频播放,请下载后查看。"})}):(0,b.jsxs)("button",{type:"button",onClick:p,disabled:j,className:"mt-2 flex w-full items-center gap-2 rounded-lg border border-cyan-500/20 bg-cyan-500/5 px-3 py-2 text-left text-sm text-cyan-100 transition hover:border-cyan-400/40 hover:bg-cyan-500/10 disabled:cursor-wait disabled:opacity-60",children:[(0,b.jsx)("span",{"aria-hidden":!0,className:"text-lg",children:"🎬"}),(0,b.jsx)("span",{className:"min-w-0 flex-1 truncate",children:d}),(0,b.jsx)("span",{className:"shrink-0 text-xs text-cyan-300",children:j?"加载中…":"▶ 播放"})]})}a.s(["AttachmentBlock",0,function({attachment:a}){var h,l;let m,n,[o,p]=(0,c.useState)(!1),[q,r]=(0,c.useState)(null),[s,t]=(0,c.useState)(!1),u=function(a){if("string"!=typeof a||0===a.length)return"file";let b=a.replace(/[/\\]/g,"_").replace(/[\r\n\t\0]/g,"_");for(;b.startsWith(".");)b=b.slice(1);return b.length>200&&(b=b.slice(0,200)),b||"file"}(a.name),v="string"!=typeof(h=a.mime)?"":h.replace(/[^a-zA-Z0-9./+-]/g,"").slice(0,100),w="number"!=typeof(l=a.size)||!Number.isFinite(l)||l<0?"":l<1024?`${l} B`:l<1048576?`${(l/1024).toFixed(1)} KB`:l<0x40000000?`${(l/1024/1024).toFixed(1)} MB`:`${(l/1024/1024/1024).toFixed(2)} GB`,x=(m=(v||"").toLowerCase(),n=(u.split(".").pop()||"").toLowerCase(),m.startsWith("image/")?"🖼️":m.startsWith("video/")?"🎬":m.startsWith("audio/")?"🎵":m.includes("pdf")||"pdf"===n?"📄":["ppt","pptx"].includes(n)?"📊":["doc","docx"].includes(n)?"📝":["xls","xlsx","csv"].includes(n)?"📈":["zip","tar","gz","rar","7z"].includes(n)?"📦":"📎"),y="string"==typeof a.file_id&&g.test(a.file_id),z=y&&!s&&function(a,b){if(e.has(b)||f.has(b))return!0;let c=i(a);return""!==c&&d.has(c)}(u,v),A=i(u),B=z?f.has(v)||["mp4","webm","mov"].includes(A)?"video":"image":null;async function C(){if(!y||!a.file_id)return;r(null),p(!0);let b=null;try{let c=await fetch(`/api/hub/files/${encodeURIComponent(a.file_id)}`,{credentials:"include"});if(!c.ok)throw Error(`HTTP ${c.status}`);let d=await c.blob();b=URL.createObjectURL(d);let e=document.createElement("a");e.href=b,e.download=u,e.rel="noopener",document.body.appendChild(e),e.click(),document.body.removeChild(e)}catch(a){r(a instanceof Error?a.message:String(a))}finally{b&&URL.revokeObjectURL(b),p(!1)}}return y?(0,b.jsxs)("div",{className:"mt-2 flex flex-col",children:["image"===B&&a.file_id&&(0,b.jsx)(j,{fileId:a.file_id,name:u,size:"number"==typeof a.size?a.size:void 0,onNotInlineable:()=>t(!0)}),"video"===B&&a.file_id&&(0,b.jsx)(k,{fileId:a.file_id,name:u,onNotInlineable:()=>t(!0)}),(0,b.jsxs)("button",{type:"button",onClick:C,disabled:o,className:"flex w-full items-center gap-2 rounded-lg border border-cyan-500/20 bg-cyan-500/5 px-3 py-2 text-left text-sm text-cyan-100 transition hover:border-cyan-400/40 hover:bg-cyan-500/10 disabled:cursor-wait disabled:opacity-60 mt-2 first:mt-0",title:`Download ${u}`,children:[(0,b.jsx)("span",{"aria-hidden":!0,className:"text-lg",children:x}),(0,b.jsx)("span",{className:"min-w-0 flex-1 truncate",children:u}),w&&(0,b.jsx)("span",{className:"shrink-0 text-xs text-neutral-400",children:w}),v&&(0,b.jsx)("span",{className:"shrink-0 rounded bg-white/5 px-1.5 py-0.5 text-[10px] text-neutral-400",children:v}),(0,b.jsx)("span",{className:"shrink-0 text-xs text-cyan-300",children:o?"下载中…":q?`⚠ ${q}`:"↓ 下载"})]})]}):(0,b.jsxs)("div",{className:"mt-2 flex items-center gap-2 rounded-lg border border-white/10 bg-white/5 px-3 py-2 text-sm text-neutral-300",children:[(0,b.jsx)("span",{"aria-hidden":!0,children:x}),(0,b.jsx)("span",{className:"min-w-0 flex-1 truncate",children:u}),w&&(0,b.jsx)("span",{className:"shrink-0 text-xs text-neutral-500",children:w}),(0,b.jsx)("span",{className:"shrink-0 text-xs text-neutral-500",title:"Attachment has no file_id — single-host path only. Ask the sender to re-upload.",children:"(host-local)"})]})},"extractAttachments",0,function(a){if(!a||"object"!=typeof a)return[];let b=a.meta;if(!b&&"string"==typeof a.meta_json&&a.meta_json.length>0)try{b=JSON.parse(a.meta_json)}catch{return[]}if(!b||"object"!=typeof b)return[];let c=b.attachments;return Array.isArray(c)?c.filter(a=>!!a&&"object"==typeof a).map(a=>({file_id:"string"==typeof a.file_id?a.file_id:void 0,path:"string"==typeof a.path?a.path:void 0,name:"string"==typeof a.name?a.name:void 0,mime:"string"==typeof a.mime?a.mime:void 0,size:"number"==typeof a.size?a.size:void 0,type:"string"==typeof a.type?a.type:void 0})):[]}])}];
2
-
3
- //# sourceMappingURL=dash-492_agent-network-dashboard_app_0kehfih._.js.map