@sleep2agi/agent-network-dashboard 0.5.3-preview.256 → 0.5.3-preview.259

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 (161) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +3 -3
  3. package/.next/diagnostics/route-bundle-stats.json +5 -5
  4. package/.next/fallback-build-manifest.json +3 -3
  5. package/.next/server/app/_global-error.html +1 -1
  6. package/.next/server/app/_global-error.rsc +1 -1
  7. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  8. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  12. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  13. package/.next/server/app/_not-found.html +2 -2
  14. package/.next/server/app/_not-found.rsc +2 -2
  15. package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  16. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  17. package/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  18. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  19. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  20. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  21. package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
  22. package/.next/server/app/admin.html +2 -2
  23. package/.next/server/app/admin.rsc +2 -2
  24. package/.next/server/app/admin.segments/_full.segment.rsc +2 -2
  25. package/.next/server/app/admin.segments/_head.segment.rsc +1 -1
  26. package/.next/server/app/admin.segments/_index.segment.rsc +2 -2
  27. package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
  28. package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +1 -1
  29. package/.next/server/app/admin.segments/admin.segment.rsc +1 -1
  30. package/.next/server/app/index.html +2 -2
  31. package/.next/server/app/index.rsc +3 -3
  32. package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  33. package/.next/server/app/index.segments/_full.segment.rsc +3 -3
  34. package/.next/server/app/index.segments/_head.segment.rsc +1 -1
  35. package/.next/server/app/index.segments/_index.segment.rsc +2 -2
  36. package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  37. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  38. package/.next/server/app/login.html +2 -2
  39. package/.next/server/app/login.rsc +3 -3
  40. package/.next/server/app/login.segments/_full.segment.rsc +3 -3
  41. package/.next/server/app/login.segments/_head.segment.rsc +1 -1
  42. package/.next/server/app/login.segments/_index.segment.rsc +2 -2
  43. package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  44. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
  45. package/.next/server/app/login.segments/login.segment.rsc +1 -1
  46. package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
  47. package/.next/server/app/logs.html +2 -2
  48. package/.next/server/app/logs.rsc +2 -2
  49. package/.next/server/app/logs.segments/_full.segment.rsc +2 -2
  50. package/.next/server/app/logs.segments/_head.segment.rsc +1 -1
  51. package/.next/server/app/logs.segments/_index.segment.rsc +2 -2
  52. package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
  53. package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +1 -1
  54. package/.next/server/app/logs.segments/logs.segment.rsc +1 -1
  55. package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
  56. package/.next/server/app/messages.html +2 -2
  57. package/.next/server/app/messages.rsc +2 -2
  58. package/.next/server/app/messages.segments/_full.segment.rsc +2 -2
  59. package/.next/server/app/messages.segments/_head.segment.rsc +1 -1
  60. package/.next/server/app/messages.segments/_index.segment.rsc +2 -2
  61. package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
  62. package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +1 -1
  63. package/.next/server/app/messages.segments/messages.segment.rsc +1 -1
  64. package/.next/server/app/node/page_client-reference-manifest.js +1 -1
  65. package/.next/server/app/node.html +2 -2
  66. package/.next/server/app/node.rsc +2 -2
  67. package/.next/server/app/node.segments/_full.segment.rsc +2 -2
  68. package/.next/server/app/node.segments/_head.segment.rsc +1 -1
  69. package/.next/server/app/node.segments/_index.segment.rsc +2 -2
  70. package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
  71. package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +1 -1
  72. package/.next/server/app/node.segments/node.segment.rsc +1 -1
  73. package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
  74. package/.next/server/app/nodes.html +2 -2
  75. package/.next/server/app/nodes.rsc +2 -2
  76. package/.next/server/app/nodes.segments/_full.segment.rsc +2 -2
  77. package/.next/server/app/nodes.segments/_head.segment.rsc +1 -1
  78. package/.next/server/app/nodes.segments/_index.segment.rsc +2 -2
  79. package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
  80. package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +1 -1
  81. package/.next/server/app/nodes.segments/nodes.segment.rsc +1 -1
  82. package/.next/server/app/page_client-reference-manifest.js +1 -1
  83. package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
  84. package/.next/server/app/server-logs.html +2 -2
  85. package/.next/server/app/server-logs.rsc +2 -2
  86. package/.next/server/app/server-logs.segments/_full.segment.rsc +2 -2
  87. package/.next/server/app/server-logs.segments/_head.segment.rsc +1 -1
  88. package/.next/server/app/server-logs.segments/_index.segment.rsc +2 -2
  89. package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
  90. package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +1 -1
  91. package/.next/server/app/server-logs.segments/server-logs.segment.rsc +1 -1
  92. package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
  93. package/.next/server/app/settings/networks.html +2 -2
  94. package/.next/server/app/settings/networks.rsc +2 -2
  95. package/.next/server/app/settings/networks.segments/_full.segment.rsc +2 -2
  96. package/.next/server/app/settings/networks.segments/_head.segment.rsc +1 -1
  97. package/.next/server/app/settings/networks.segments/_index.segment.rsc +2 -2
  98. package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
  99. package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +1 -1
  100. package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +1 -1
  101. package/.next/server/app/settings/networks.segments/settings.segment.rsc +1 -1
  102. package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  103. package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
  104. package/.next/server/app/settings/tokens.html +2 -2
  105. package/.next/server/app/settings/tokens.rsc +2 -2
  106. package/.next/server/app/settings/tokens.segments/_full.segment.rsc +2 -2
  107. package/.next/server/app/settings/tokens.segments/_head.segment.rsc +1 -1
  108. package/.next/server/app/settings/tokens.segments/_index.segment.rsc +2 -2
  109. package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
  110. package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +1 -1
  111. package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +1 -1
  112. package/.next/server/app/settings/tokens.segments/settings.segment.rsc +1 -1
  113. package/.next/server/app/settings.html +2 -2
  114. package/.next/server/app/settings.rsc +3 -3
  115. package/.next/server/app/settings.segments/_full.segment.rsc +3 -3
  116. package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  117. package/.next/server/app/settings.segments/_index.segment.rsc +2 -2
  118. package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  119. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +2 -2
  120. package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
  121. package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
  122. package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
  123. package/.next/server/app/tasks.html +2 -2
  124. package/.next/server/app/tasks.rsc +2 -2
  125. package/.next/server/app/tasks.segments/_full.segment.rsc +2 -2
  126. package/.next/server/app/tasks.segments/_head.segment.rsc +1 -1
  127. package/.next/server/app/tasks.segments/_index.segment.rsc +2 -2
  128. package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
  129. package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +1 -1
  130. package/.next/server/app/tasks.segments/tasks.segment.rsc +1 -1
  131. package/.next/server/chunks/[root-of-the-server]__0tx8s8i._.js +1 -1
  132. package/.next/server/chunks/[root-of-the-server]__0tx8s8i._.js.map +1 -1
  133. package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js +1 -1
  134. package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js.map +1 -1
  135. package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js +2 -2
  136. package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js.map +1 -1
  137. package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js +1 -1
  138. package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js.map +1 -1
  139. package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js +1 -1
  140. package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js.map +1 -1
  141. package/.next/server/middleware-build-manifest.js +3 -3
  142. package/.next/server/pages/404.html +2 -2
  143. package/.next/server/pages/500.html +1 -1
  144. package/.next/static/chunks/{0mbz6_9.awtny.js → 0-j8-e_dqejm7.js} +2 -2
  145. package/.next/static/chunks/{0ypxu9tjas5ii.js → 0rfv0i6s6p5w..js} +1 -1
  146. package/.next/static/chunks/{0lz0d3xp-akmx.js → 0ysm~dy.6klf4.js} +1 -1
  147. package/.next/static/chunks/{0xu6mniq9hov9.js → 0y~ndc96dgfdi.js} +1 -1
  148. package/.next/static/chunks/{0-7ma47rnbr6l.css → 16-7qr7qx9zrz.css} +1 -1
  149. package/.next/trace +2 -2
  150. package/.next/trace-build +1 -1
  151. package/app/api/hub/servers/route.ts +3 -29
  152. package/app/components/TopoGraph.tsx +20 -2
  153. package/app/globals.css +25 -0
  154. package/app/lib/serverDedupe.ts +122 -0
  155. package/package.json +1 -1
  156. package/scripts/p157-rc2-dedup-test.mjs +110 -0
  157. package/scripts/topo-animation-temporal-modes-catalog-test.mjs +4 -5
  158. package/scripts/topo-chrome-strip-entrance-animation-test.mjs +115 -0
  159. /package/.next/static/{iXL-5CIRUR5NRzD1e0XT- → OLU9smG22aFJt6Y2nEBbV}/_buildManifest.js +0 -0
  160. /package/.next/static/{iXL-5CIRUR5NRzD1e0XT- → OLU9smG22aFJt6Y2nEBbV}/_clientMiddlewareManifest.js +0 -0
  161. /package/.next/static/{iXL-5CIRUR5NRzD1e0XT- → OLU9smG22aFJt6Y2nEBbV}/_ssgManifest.js +0 -0
package/.next/trace CHANGED
@@ -1,2 +1,2 @@
1
- [{"name":"generate-buildid","duration":266,"timestamp":418083711657,"id":4,"parentId":1,"tags":{},"startTime":1779226055958,"traceId":"81a58f90c730f8ed"},{"name":"load-custom-routes","duration":676,"timestamp":418083712155,"id":5,"parentId":1,"tags":{},"startTime":1779226055958,"traceId":"81a58f90c730f8ed"},{"name":"create-dist-dir","duration":925,"timestamp":418083712881,"id":6,"parentId":1,"tags":{},"startTime":1779226055959,"traceId":"81a58f90c730f8ed"},{"name":"clean","duration":37290,"timestamp":418083714700,"id":7,"parentId":1,"tags":{},"startTime":1779226055961,"traceId":"81a58f90c730f8ed"},{"name":"discover-routes","duration":23540,"timestamp":418083836376,"id":8,"parentId":1,"tags":{},"startTime":1779226056083,"traceId":"81a58f90c730f8ed"},{"name":"create-root-mapping","duration":151,"timestamp":418083859981,"id":9,"parentId":1,"tags":{},"startTime":1779226056106,"traceId":"81a58f90c730f8ed"},{"name":"generate-route-types","duration":25881,"timestamp":418083862886,"id":10,"parentId":1,"tags":{},"startTime":1779226056109,"traceId":"81a58f90c730f8ed"},{"name":"public-dir-conflict-check","duration":97,"timestamp":418083888855,"id":11,"parentId":1,"tags":{},"startTime":1779226056135,"traceId":"81a58f90c730f8ed"},{"name":"generate-routes-manifest","duration":5230,"timestamp":418083889114,"id":12,"parentId":1,"tags":{},"startTime":1779226056135,"traceId":"81a58f90c730f8ed"},{"name":"run-turbopack","duration":6652953,"timestamp":418083901259,"id":14,"parentId":1,"tags":{},"startTime":1779226056148,"traceId":"81a58f90c730f8ed"},{"name":"turbopack-build-events","duration":106,"timestamp":418084218074,"id":15,"parentId":1,"tags":{},"startTime":1779226056464,"traceId":"81a58f90c730f8ed"},{"name":"run-typescript","duration":10647715,"timestamp":418090563521,"id":16,"parentId":1,"tags":{},"startTime":1779226062810,"traceId":"81a58f90c730f8ed"},{"name":"generate-required-server-files","duration":3110,"timestamp":418101212607,"id":18,"parentId":1,"tags":{},"startTime":1779226073459,"traceId":"81a58f90c730f8ed"},{"name":"check-static-error-page","duration":14188,"timestamp":418101452325,"id":20,"parentId":19,"tags":{},"startTime":1779226073699,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":648589,"timestamp":418101470151,"id":65,"parentId":22,"tags":{},"startTime":1779226073716,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":664235,"timestamp":418101454696,"id":22,"parentId":19,"tags":{"page":"/_global-error"},"startTime":1779226073701,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":686281,"timestamp":418101470941,"id":70,"parentId":29,"tags":{},"startTime":1779226073717,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":699163,"timestamp":418101458172,"id":29,"parentId":19,"tags":{"page":"/api/hub/auth"},"startTime":1779226073704,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":688015,"timestamp":418101470325,"id":66,"parentId":25,"tags":{},"startTime":1779226073717,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":700849,"timestamp":418101457568,"id":25,"parentId":19,"tags":{"page":"/api/auth/login"},"startTime":1779226073704,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":693174,"timestamp":418101471368,"id":73,"parentId":33,"tags":{},"startTime":1779226073718,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":705707,"timestamp":418101458904,"id":33,"parentId":19,"tags":{"page":"/api/hub/inbox"},"startTime":1779226073705,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":731249,"timestamp":418101471187,"id":72,"parentId":32,"tags":{},"startTime":1779226073717,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":743751,"timestamp":418101458778,"id":32,"parentId":19,"tags":{"page":"/api/hub/health"},"startTime":1779226073705,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":731311,"timestamp":418101471451,"id":74,"parentId":34,"tags":{},"startTime":1779226073718,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":743769,"timestamp":418101459041,"id":34,"parentId":19,"tags":{"page":"/api/hub/license"},"startTime":1779226073705,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":741366,"timestamp":418101471494,"id":76,"parentId":36,"tags":{},"startTime":1779226073718,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":753448,"timestamp":418101459502,"id":36,"parentId":19,"tags":{"page":"/api/hub/networks"},"startTime":1779226073706,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":752656,"timestamp":418101471475,"id":75,"parentId":35,"tags":{},"startTime":1779226073718,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":765056,"timestamp":418101459147,"id":35,"parentId":19,"tags":{"page":"/api/hub/messages"},"startTime":1779226073705,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":752931,"timestamp":418101471520,"id":77,"parentId":37,"tags":{},"startTime":1779226073718,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":764874,"timestamp":418101459619,"id":37,"parentId":19,"tags":{"page":"/api/hub/nodes"},"startTime":1779226073706,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":758733,"timestamp":418101471538,"id":78,"parentId":38,"tags":{},"startTime":1779226073718,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":770630,"timestamp":418101459712,"id":38,"parentId":19,"tags":{"page":"/api/hub/register"},"startTime":1779226073706,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":760114,"timestamp":418101470442,"id":67,"parentId":26,"tags":{},"startTime":1779226073717,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":772830,"timestamp":418101457764,"id":26,"parentId":19,"tags":{"page":"/api/auth/logout"},"startTime":1779226073704,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":762186,"timestamp":418101471548,"id":79,"parentId":39,"tags":{},"startTime":1779226073718,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":774009,"timestamp":418101459773,"id":39,"parentId":19,"tags":{"page":"/api/hub/send"},"startTime":1779226073706,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":766809,"timestamp":418101471584,"id":82,"parentId":44,"tags":{},"startTime":1779226073718,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":777844,"timestamp":418101460596,"id":44,"parentId":19,"tags":{"page":"/api/hub/session"},"startTime":1779226073707,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":771609,"timestamp":418101470563,"id":68,"parentId":27,"tags":{},"startTime":1779226073717,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":784332,"timestamp":418101457888,"id":27,"parentId":19,"tags":{"page":"/api/auth/v3"},"startTime":1779226073704,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":775483,"timestamp":418101471597,"id":83,"parentId":45,"tags":{},"startTime":1779226073718,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":786421,"timestamp":418101460717,"id":45,"parentId":19,"tags":{"page":"/api/hub/stats"},"startTime":1779226073707,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":776412,"timestamp":418101471624,"id":85,"parentId":47,"tags":{},"startTime":1779226073718,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":787154,"timestamp":418101460929,"id":47,"parentId":19,"tags":{"page":"/api/hub/task-events"},"startTime":1779226073707,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":778545,"timestamp":418101471562,"id":80,"parentId":40,"tags":{},"startTime":1779226073718,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":790185,"timestamp":418101459980,"id":40,"parentId":19,"tags":{"page":"/api/hub/server-logs"},"startTime":1779226073706,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":785506,"timestamp":418101471633,"id":86,"parentId":48,"tags":{},"startTime":1779226073718,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":794407,"timestamp":418101462779,"id":48,"parentId":19,"tags":{"page":"/api/hub/tasks"},"startTime":1779226073709,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":786323,"timestamp":418101471645,"id":87,"parentId":49,"tags":{},"startTime":1779226073718,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":794995,"timestamp":418101463033,"id":49,"parentId":19,"tags":{"page":"/api/hub/tmux"},"startTime":1779226073709,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":789696,"timestamp":418101470677,"id":69,"parentId":28,"tags":{},"startTime":1779226073717,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":802379,"timestamp":418101458037,"id":28,"parentId":19,"tags":{"page":"/api/hub/audit-log"},"startTime":1779226073704,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":789338,"timestamp":418101471610,"id":84,"parentId":46,"tags":{},"startTime":1779226073718,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":800172,"timestamp":418101460818,"id":46,"parentId":19,"tags":{"page":"/api/hub/status"},"startTime":1779226073707,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":794684,"timestamp":418101469810,"id":64,"parentId":21,"tags":{},"startTime":1779226073716,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":810996,"timestamp":418101453542,"id":21,"parentId":19,"tags":{"page":"/_not-found"},"startTime":1779226073700,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":794608,"timestamp":418101471665,"id":89,"parentId":51,"tags":{},"startTime":1779226073718,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":803084,"timestamp":418101463250,"id":51,"parentId":19,"tags":{"page":"/favicon.ico"},"startTime":1779226073710,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":798007,"timestamp":418101471657,"id":88,"parentId":50,"tags":{},"startTime":1779226073718,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":806547,"timestamp":418101463158,"id":50,"parentId":19,"tags":{"page":"/api/hub/tokens"},"startTime":1779226073709,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":801503,"timestamp":418101471575,"id":81,"parentId":42,"tags":{},"startTime":1779226073718,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":812855,"timestamp":418101460283,"id":42,"parentId":19,"tags":{"page":"/api/hub/server/[hostname]/health"},"startTime":1779226073707,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":787599,"timestamp":418101485680,"id":91,"parentId":31,"tags":{},"startTime":1779226073732,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":814833,"timestamp":418101458492,"id":31,"parentId":19,"tags":{"page":"/api/hub/events"},"startTime":1779226073705,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":796687,"timestamp":418101478485,"id":90,"parentId":24,"tags":{},"startTime":1779226073725,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":820007,"timestamp":418101455211,"id":24,"parentId":19,"tags":{"page":"/api/anet/config"},"startTime":1779226073701,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":780263,"timestamp":418101495090,"id":93,"parentId":43,"tags":{},"startTime":1779226073741,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":815001,"timestamp":418101460384,"id":43,"parentId":19,"tags":{"page":"/api/hub/servers"},"startTime":1779226073707,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":818213,"timestamp":418101471119,"id":71,"parentId":30,"tags":{},"startTime":1779226073717,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":831064,"timestamp":418101458353,"id":30,"parentId":19,"tags":{"page":"/api/hub/broadcast"},"startTime":1779226073705,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":844571,"timestamp":418101497684,"id":98,"parentId":55,"tags":{},"startTime":1779226073744,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":878140,"timestamp":418101464211,"id":55,"parentId":19,"tags":{"page":"/node"},"startTime":1779226073710,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":853018,"timestamp":418101497708,"id":100,"parentId":58,"tags":{},"startTime":1779226073744,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":885577,"timestamp":418101465221,"id":58,"parentId":19,"tags":{"page":"/server-logs"},"startTime":1779226073711,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":860397,"timestamp":418101497696,"id":99,"parentId":56,"tags":{},"startTime":1779226073744,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":893738,"timestamp":418101464432,"id":56,"parentId":19,"tags":{"page":"/nodes"},"startTime":1779226073711,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":861128,"timestamp":418101497817,"id":101,"parentId":59,"tags":{},"startTime":1779226073744,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":893596,"timestamp":418101465440,"id":59,"parentId":19,"tags":{"page":"/settings/networks"},"startTime":1779226073712,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":870187,"timestamp":418101497837,"id":102,"parentId":61,"tags":{},"startTime":1779226073744,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":905962,"timestamp":418101466116,"id":61,"parentId":19,"tags":{"page":"/settings/tokens"},"startTime":1779226073712,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":876293,"timestamp":418101497849,"id":103,"parentId":62,"tags":{},"startTime":1779226073744,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":910180,"timestamp":418101466230,"id":62,"parentId":19,"tags":{"page":"/tasks/[id]"},"startTime":1779226073713,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":878962,"timestamp":418101497663,"id":96,"parentId":53,"tags":{},"startTime":1779226073744,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":912859,"timestamp":418101463811,"id":53,"parentId":19,"tags":{"page":"/logs"},"startTime":1779226073710,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":878900,"timestamp":418101497857,"id":104,"parentId":63,"tags":{},"startTime":1779226073744,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":910442,"timestamp":418101466341,"id":63,"parentId":19,"tags":{"page":"/tasks"},"startTime":1779226073713,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":893786,"timestamp":418101486683,"id":92,"parentId":41,"tags":{},"startTime":1779226073733,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":920435,"timestamp":418101460084,"id":41,"parentId":19,"tags":{"page":"/api/hub/server/[hostname]/agents"},"startTime":1779226073706,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":854755,"timestamp":418101527759,"id":105,"parentId":57,"tags":{},"startTime":1779226073774,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":917898,"timestamp":418101464663,"id":57,"parentId":19,"tags":{"page":"/"},"startTime":1779226073711,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":846271,"timestamp":418101538388,"id":106,"parentId":60,"tags":{},"startTime":1779226073785,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":919061,"timestamp":418101465645,"id":60,"parentId":19,"tags":{"page":"/settings"},"startTime":1779226073712,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":888241,"timestamp":418101497608,"id":94,"parentId":23,"tags":{},"startTime":1779226073744,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":930988,"timestamp":418101454905,"id":23,"parentId":19,"tags":{"page":"/admin"},"startTime":1779226073701,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":891101,"timestamp":418101497671,"id":97,"parentId":54,"tags":{},"startTime":1779226073744,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":924829,"timestamp":418101463988,"id":54,"parentId":19,"tags":{"page":"/messages"},"startTime":1779226073710,"traceId":"81a58f90c730f8ed"},{"name":"is-page-static","duration":899950,"timestamp":418101497649,"id":95,"parentId":52,"tags":{},"startTime":1779226073744,"traceId":"81a58f90c730f8ed"},{"name":"check-page","duration":934020,"timestamp":418101463641,"id":52,"parentId":19,"tags":{"page":"/login"},"startTime":1779226073710,"traceId":"81a58f90c730f8ed"},{"name":"static-check","duration":946599,"timestamp":418101451105,"id":19,"parentId":1,"tags":{},"startTime":1779226073697,"traceId":"81a58f90c730f8ed"}]
2
- [{"name":"write-routes-manifest","duration":853,"timestamp":418102411886,"id":108,"parentId":1,"tags":{},"startTime":1779226074658,"traceId":"81a58f90c730f8ed"},{"name":"load-dotenv","duration":58,"timestamp":418102427373,"id":111,"parentId":110,"tags":{},"startTime":1779226074674,"traceId":"81a58f90c730f8ed"},{"name":"run-export-path-map","duration":569,"timestamp":418102430391,"id":112,"parentId":110,"tags":{},"startTime":1779226074677,"traceId":"81a58f90c730f8ed"},{"name":"next-export","duration":707782,"timestamp":418102426062,"id":110,"parentId":1,"tags":{},"startTime":1779226074672,"traceId":"81a58f90c730f8ed"},{"name":"move-exported-app-not-found-","duration":889,"timestamp":418103137532,"id":113,"parentId":109,"tags":{},"startTime":1779226075384,"traceId":"81a58f90c730f8ed"},{"name":"move-exported-app-global-error-","duration":570,"timestamp":418103138568,"id":114,"parentId":109,"tags":{},"startTime":1779226075385,"traceId":"81a58f90c730f8ed"},{"name":"static-generation","duration":723405,"timestamp":418102418037,"id":109,"parentId":1,"tags":{},"startTime":1779226074664,"traceId":"81a58f90c730f8ed"},{"name":"write-routes-manifest","duration":660,"timestamp":418103141753,"id":115,"parentId":1,"tags":{},"startTime":1779226075388,"traceId":"81a58f90c730f8ed"},{"name":"print-tree-view","duration":5284,"timestamp":418103154849,"id":116,"parentId":1,"tags":{},"startTime":1779226075401,"traceId":"81a58f90c730f8ed"},{"name":"write-route-bundle-stats","duration":16679,"timestamp":418103160182,"id":117,"parentId":1,"tags":{},"startTime":1779226075406,"traceId":"81a58f90c730f8ed"},{"name":"telemetry-flush","duration":20477,"timestamp":418103176911,"id":118,"parentId":1,"tags":{},"startTime":1779226075423,"traceId":"81a58f90c730f8ed"},{"name":"next-build","duration":19537658,"timestamp":418083659786,"id":1,"tags":{"buildMode":"default","version":"16.2.3","bundler":"turbopack","has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1779226055906,"traceId":"81a58f90c730f8ed"}]
1
+ [{"name":"generate-buildid","duration":340,"timestamp":518868817545,"id":4,"parentId":1,"tags":{},"startTime":1779326841064,"traceId":"6f84d0e609888c2a"},{"name":"load-custom-routes","duration":561,"timestamp":518868818072,"id":5,"parentId":1,"tags":{},"startTime":1779326841064,"traceId":"6f84d0e609888c2a"},{"name":"create-dist-dir","duration":1034,"timestamp":518868818709,"id":6,"parentId":1,"tags":{},"startTime":1779326841065,"traceId":"6f84d0e609888c2a"},{"name":"clean","duration":43132,"timestamp":518868820545,"id":7,"parentId":1,"tags":{},"startTime":1779326841067,"traceId":"6f84d0e609888c2a"},{"name":"discover-routes","duration":11959,"timestamp":518868959736,"id":8,"parentId":1,"tags":{},"startTime":1779326841206,"traceId":"6f84d0e609888c2a"},{"name":"create-root-mapping","duration":141,"timestamp":518868971766,"id":9,"parentId":1,"tags":{},"startTime":1779326841218,"traceId":"6f84d0e609888c2a"},{"name":"generate-route-types","duration":39732,"timestamp":518868974560,"id":10,"parentId":1,"tags":{},"startTime":1779326841221,"traceId":"6f84d0e609888c2a"},{"name":"public-dir-conflict-check","duration":108,"timestamp":518869014405,"id":11,"parentId":1,"tags":{},"startTime":1779326841261,"traceId":"6f84d0e609888c2a"},{"name":"generate-routes-manifest","duration":5510,"timestamp":518869014639,"id":12,"parentId":1,"tags":{},"startTime":1779326841261,"traceId":"6f84d0e609888c2a"},{"name":"run-turbopack","duration":8909891,"timestamp":518869029106,"id":14,"parentId":1,"tags":{},"startTime":1779326841275,"traceId":"6f84d0e609888c2a"},{"name":"turbopack-build-events","duration":100,"timestamp":518869385427,"id":15,"parentId":1,"tags":{},"startTime":1779326841632,"traceId":"6f84d0e609888c2a"},{"name":"run-typescript","duration":11637384,"timestamp":518877952747,"id":16,"parentId":1,"tags":{},"startTime":1779326850199,"traceId":"6f84d0e609888c2a"},{"name":"generate-required-server-files","duration":3138,"timestamp":518889591539,"id":18,"parentId":1,"tags":{},"startTime":1779326861838,"traceId":"6f84d0e609888c2a"},{"name":"check-static-error-page","duration":15188,"timestamp":518889803490,"id":20,"parentId":19,"tags":{},"startTime":1779326862050,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":580953,"timestamp":518889822504,"id":65,"parentId":22,"tags":{},"startTime":1779326862069,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":596823,"timestamp":518889806848,"id":22,"parentId":19,"tags":{"page":"/_global-error"},"startTime":1779326862053,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":736391,"timestamp":518889822600,"id":66,"parentId":25,"tags":{},"startTime":1779326862069,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":748916,"timestamp":518889810208,"id":25,"parentId":19,"tags":{"page":"/api/auth/login"},"startTime":1779326862056,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":763733,"timestamp":518889822200,"id":64,"parentId":21,"tags":{},"startTime":1779326862068,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":781635,"timestamp":518889805235,"id":21,"parentId":19,"tags":{"page":"/_not-found"},"startTime":1779326862052,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":764011,"timestamp":518889823116,"id":71,"parentId":30,"tags":{},"startTime":1779326862069,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":776229,"timestamp":518889810941,"id":30,"parentId":19,"tags":{"page":"/api/hub/broadcast"},"startTime":1779326862057,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":772508,"timestamp":518889823178,"id":72,"parentId":32,"tags":{},"startTime":1779326862069,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":784401,"timestamp":518889811363,"id":32,"parentId":19,"tags":{"page":"/api/hub/health"},"startTime":1779326862058,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":788341,"timestamp":518889823432,"id":74,"parentId":34,"tags":{},"startTime":1779326862070,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":800198,"timestamp":518889811658,"id":34,"parentId":19,"tags":{"page":"/api/hub/license"},"startTime":1779326862058,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":796291,"timestamp":518889823463,"id":75,"parentId":35,"tags":{},"startTime":1779326862070,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":808025,"timestamp":518889811800,"id":35,"parentId":19,"tags":{"page":"/api/hub/messages"},"startTime":1779326862058,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":800829,"timestamp":518889823512,"id":77,"parentId":37,"tags":{},"startTime":1779326862070,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":811956,"timestamp":518889812448,"id":37,"parentId":19,"tags":{"page":"/api/hub/nodes"},"startTime":1779326862059,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":805875,"timestamp":518889823526,"id":78,"parentId":38,"tags":{},"startTime":1779326862070,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":816915,"timestamp":518889812542,"id":38,"parentId":19,"tags":{"page":"/api/hub/register"},"startTime":1779326862059,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":810153,"timestamp":518889823541,"id":79,"parentId":39,"tags":{},"startTime":1779326862070,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":821135,"timestamp":518889812615,"id":39,"parentId":19,"tags":{"page":"/api/hub/send"},"startTime":1779326862059,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":813388,"timestamp":518889823484,"id":76,"parentId":36,"tags":{},"startTime":1779326862070,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":824631,"timestamp":518889812296,"id":36,"parentId":19,"tags":{"page":"/api/hub/networks"},"startTime":1779326862059,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":818674,"timestamp":518889823555,"id":80,"parentId":40,"tags":{},"startTime":1779326862070,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":829605,"timestamp":518889812679,"id":40,"parentId":19,"tags":{"page":"/api/hub/server-logs"},"startTime":1779326862059,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":819779,"timestamp":518889823576,"id":82,"parentId":44,"tags":{},"startTime":1779326862070,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":830016,"timestamp":518889813384,"id":44,"parentId":19,"tags":{"page":"/api/hub/session"},"startTime":1779326862060,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":824596,"timestamp":518889823588,"id":83,"parentId":45,"tags":{},"startTime":1779326862070,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":834700,"timestamp":518889813528,"id":45,"parentId":19,"tags":{"page":"/api/hub/stats"},"startTime":1779326862060,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":829548,"timestamp":518889823599,"id":84,"parentId":46,"tags":{},"startTime":1779326862070,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":839581,"timestamp":518889813620,"id":46,"parentId":19,"tags":{"page":"/api/hub/status"},"startTime":1779326862060,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":834090,"timestamp":518889823607,"id":85,"parentId":47,"tags":{},"startTime":1779326862070,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":844053,"timestamp":518889813696,"id":47,"parentId":19,"tags":{"page":"/api/hub/task-events"},"startTime":1779326862060,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":838547,"timestamp":518889823639,"id":86,"parentId":48,"tags":{},"startTime":1779326862070,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":848486,"timestamp":518889813765,"id":48,"parentId":19,"tags":{"page":"/api/hub/tasks"},"startTime":1779326862060,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":844880,"timestamp":518889823652,"id":87,"parentId":49,"tags":{},"startTime":1779326862070,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":853162,"timestamp":518889815410,"id":49,"parentId":19,"tags":{"page":"/api/hub/tmux"},"startTime":1779326862062,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":848962,"timestamp":518889823567,"id":81,"parentId":42,"tags":{},"startTime":1779326862070,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":859654,"timestamp":518889812936,"id":42,"parentId":19,"tags":{"page":"/api/hub/server/[hostname]/health"},"startTime":1779326862059,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":849073,"timestamp":518889823665,"id":88,"parentId":50,"tags":{},"startTime":1779326862070,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":857244,"timestamp":518889815532,"id":50,"parentId":19,"tags":{"page":"/api/hub/tokens"},"startTime":1779326862062,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":852776,"timestamp":518889827589,"id":90,"parentId":24,"tags":{},"startTime":1779326862074,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":872864,"timestamp":518889807559,"id":24,"parentId":19,"tags":{"page":"/api/anet/config"},"startTime":1779326862054,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":854676,"timestamp":518889828748,"id":91,"parentId":31,"tags":{},"startTime":1779326862075,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":872385,"timestamp":518889811086,"id":31,"parentId":19,"tags":{"page":"/api/hub/events"},"startTime":1779326862057,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":865511,"timestamp":518889823675,"id":89,"parentId":51,"tags":{},"startTime":1779326862070,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":873633,"timestamp":518889815609,"id":51,"parentId":19,"tags":{"page":"/favicon.ico"},"startTime":1779326862062,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":864235,"timestamp":518889829616,"id":92,"parentId":41,"tags":{},"startTime":1779326862076,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":881159,"timestamp":518889812741,"id":41,"parentId":19,"tags":{"page":"/api/hub/server/[hostname]/agents"},"startTime":1779326862059,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":866192,"timestamp":518889830738,"id":93,"parentId":43,"tags":{},"startTime":1779326862077,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":883886,"timestamp":518889813090,"id":43,"parentId":19,"tags":{"page":"/api/hub/servers"},"startTime":1779326862059,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":899959,"timestamp":518889822971,"id":70,"parentId":29,"tags":{},"startTime":1779326862069,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":912252,"timestamp":518889810793,"id":29,"parentId":19,"tags":{"page":"/api/hub/auth"},"startTime":1779326862057,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":915547,"timestamp":518889822801,"id":69,"parentId":28,"tags":{},"startTime":1779326862069,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":927762,"timestamp":518889810665,"id":28,"parentId":19,"tags":{"page":"/api/hub/audit-log"},"startTime":1779326862057,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":958481,"timestamp":518889822669,"id":67,"parentId":26,"tags":{},"startTime":1779326862069,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":970836,"timestamp":518889810402,"id":26,"parentId":19,"tags":{"page":"/api/auth/logout"},"startTime":1779326862057,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":966322,"timestamp":518889832924,"id":94,"parentId":23,"tags":{},"startTime":1779326862079,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":992197,"timestamp":518889807157,"id":23,"parentId":19,"tags":{"page":"/admin"},"startTime":1779326862053,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":980663,"timestamp":518889823356,"id":73,"parentId":33,"tags":{},"startTime":1779326862070,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":992574,"timestamp":518889811516,"id":33,"parentId":19,"tags":{"page":"/api/hub/inbox"},"startTime":1779326862058,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":970044,"timestamp":518889837148,"id":99,"parentId":56,"tags":{},"startTime":1779326862083,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":990751,"timestamp":518889816492,"id":56,"parentId":19,"tags":{"page":"/nodes"},"startTime":1779326862063,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":984073,"timestamp":518889837336,"id":101,"parentId":59,"tags":{},"startTime":1779326862084,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":1004033,"timestamp":518889817448,"id":59,"parentId":19,"tags":{"page":"/settings/networks"},"startTime":1779326862064,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":989599,"timestamp":518889832953,"id":95,"parentId":52,"tags":{},"startTime":1779326862079,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":1006741,"timestamp":518889815894,"id":52,"parentId":19,"tags":{"page":"/login"},"startTime":1779326862062,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":988022,"timestamp":518889837199,"id":100,"parentId":58,"tags":{},"startTime":1779326862083,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":1008232,"timestamp":518889817039,"id":58,"parentId":19,"tags":{"page":"/server-logs"},"startTime":1779326862063,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":994075,"timestamp":518889837359,"id":102,"parentId":61,"tags":{},"startTime":1779326862084,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":1013408,"timestamp":518889818101,"id":61,"parentId":19,"tags":{"page":"/settings/tokens"},"startTime":1779326862064,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":987162,"timestamp":518889851237,"id":105,"parentId":60,"tags":{},"startTime":1779326862098,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":1020797,"timestamp":518889817653,"id":60,"parentId":19,"tags":{"page":"/settings"},"startTime":1779326862064,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":1003986,"timestamp":518889837381,"id":104,"parentId":63,"tags":{},"startTime":1779326862084,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":1022988,"timestamp":518889818435,"id":63,"parentId":19,"tags":{"page":"/tasks"},"startTime":1779326862065,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":1012291,"timestamp":518889832964,"id":96,"parentId":53,"tags":{},"startTime":1779326862079,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":1029264,"timestamp":518889816037,"id":53,"parentId":19,"tags":{"page":"/logs"},"startTime":1779326862062,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":1010459,"timestamp":518889837369,"id":103,"parentId":62,"tags":{},"startTime":1779326862084,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":1029614,"timestamp":518889818263,"id":62,"parentId":19,"tags":{"page":"/tasks/[id]"},"startTime":1779326862065,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":983224,"timestamp":518889867651,"id":106,"parentId":57,"tags":{},"startTime":1779326862114,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":1034266,"timestamp":518889816663,"id":57,"parentId":19,"tags":{"page":"/"},"startTime":1779326862063,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":1062692,"timestamp":518889822735,"id":68,"parentId":27,"tags":{},"startTime":1779326862069,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":1075005,"timestamp":518889810524,"id":27,"parentId":19,"tags":{"page":"/api/auth/v3"},"startTime":1779326862057,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":1062044,"timestamp":518889832992,"id":98,"parentId":55,"tags":{},"startTime":1779326862079,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":1078785,"timestamp":518889816336,"id":55,"parentId":19,"tags":{"page":"/node"},"startTime":1779326862063,"traceId":"6f84d0e609888c2a"},{"name":"is-page-static","duration":1064539,"timestamp":518889832978,"id":97,"parentId":54,"tags":{},"startTime":1779326862079,"traceId":"6f84d0e609888c2a"},{"name":"check-page","duration":1081401,"timestamp":518889816182,"id":54,"parentId":19,"tags":{"page":"/messages"},"startTime":1779326862062,"traceId":"6f84d0e609888c2a"},{"name":"static-check","duration":1095343,"timestamp":518889802289,"id":19,"parentId":1,"tags":{},"startTime":1779326862049,"traceId":"6f84d0e609888c2a"}]
2
+ [{"name":"write-routes-manifest","duration":531,"timestamp":518890911039,"id":108,"parentId":1,"tags":{},"startTime":1779326863157,"traceId":"6f84d0e609888c2a"},{"name":"load-dotenv","duration":66,"timestamp":518890925745,"id":111,"parentId":110,"tags":{},"startTime":1779326863172,"traceId":"6f84d0e609888c2a"},{"name":"run-export-path-map","duration":707,"timestamp":518890931593,"id":112,"parentId":110,"tags":{},"startTime":1779326863178,"traceId":"6f84d0e609888c2a"},{"name":"next-export","duration":691284,"timestamp":518890924284,"id":110,"parentId":1,"tags":{},"startTime":1779326863171,"traceId":"6f84d0e609888c2a"},{"name":"move-exported-app-not-found-","duration":618,"timestamp":518891619421,"id":113,"parentId":109,"tags":{},"startTime":1779326863866,"traceId":"6f84d0e609888c2a"},{"name":"move-exported-app-global-error-","duration":392,"timestamp":518891620158,"id":114,"parentId":109,"tags":{},"startTime":1779326863866,"traceId":"6f84d0e609888c2a"},{"name":"static-generation","duration":706506,"timestamp":518890916245,"id":109,"parentId":1,"tags":{},"startTime":1779326863163,"traceId":"6f84d0e609888c2a"},{"name":"write-routes-manifest","duration":1317,"timestamp":518891623114,"id":115,"parentId":1,"tags":{},"startTime":1779326863869,"traceId":"6f84d0e609888c2a"},{"name":"print-tree-view","duration":5127,"timestamp":518891646953,"id":116,"parentId":1,"tags":{},"startTime":1779326863893,"traceId":"6f84d0e609888c2a"},{"name":"write-route-bundle-stats","duration":17218,"timestamp":518891652120,"id":117,"parentId":1,"tags":{},"startTime":1779326863898,"traceId":"6f84d0e609888c2a"},{"name":"telemetry-flush","duration":12703,"timestamp":518891669384,"id":118,"parentId":1,"tags":{},"startTime":1779326863916,"traceId":"6f84d0e609888c2a"},{"name":"next-build","duration":22930244,"timestamp":518868751895,"id":1,"tags":{"buildMode":"default","version":"16.2.3","bundler":"turbopack","has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1779326840998,"traceId":"6f84d0e609888c2a"}]
package/.next/trace-build CHANGED
@@ -1 +1 @@
1
- [{"name":"run-turbopack","duration":6652953,"timestamp":418083901259,"id":14,"parentId":1,"tags":{},"startTime":1779226056148,"traceId":"81a58f90c730f8ed"},{"name":"turbopack-build-events","duration":106,"timestamp":418084218074,"id":15,"parentId":1,"tags":{},"startTime":1779226056464,"traceId":"81a58f90c730f8ed"},{"name":"run-typescript","duration":10647715,"timestamp":418090563521,"id":16,"parentId":1,"tags":{},"startTime":1779226062810,"traceId":"81a58f90c730f8ed"},{"name":"static-check","duration":946599,"timestamp":418101451105,"id":19,"parentId":1,"tags":{},"startTime":1779226073697,"traceId":"81a58f90c730f8ed"},{"name":"static-generation","duration":723405,"timestamp":418102418037,"id":109,"parentId":1,"tags":{},"startTime":1779226074664,"traceId":"81a58f90c730f8ed"},{"name":"telemetry-flush","duration":20477,"timestamp":418103176911,"id":118,"parentId":1,"tags":{},"startTime":1779226075423,"traceId":"81a58f90c730f8ed"},{"name":"next-build","duration":19537658,"timestamp":418083659786,"id":1,"tags":{"buildMode":"default","version":"16.2.3","bundler":"turbopack","has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1779226055906,"traceId":"81a58f90c730f8ed"}]
1
+ [{"name":"run-turbopack","duration":8909891,"timestamp":518869029106,"id":14,"parentId":1,"tags":{},"startTime":1779326841275,"traceId":"6f84d0e609888c2a"},{"name":"turbopack-build-events","duration":100,"timestamp":518869385427,"id":15,"parentId":1,"tags":{},"startTime":1779326841632,"traceId":"6f84d0e609888c2a"},{"name":"run-typescript","duration":11637384,"timestamp":518877952747,"id":16,"parentId":1,"tags":{},"startTime":1779326850199,"traceId":"6f84d0e609888c2a"},{"name":"static-check","duration":1095343,"timestamp":518889802289,"id":19,"parentId":1,"tags":{},"startTime":1779326862049,"traceId":"6f84d0e609888c2a"},{"name":"static-generation","duration":706506,"timestamp":518890916245,"id":109,"parentId":1,"tags":{},"startTime":1779326863163,"traceId":"6f84d0e609888c2a"},{"name":"telemetry-flush","duration":12703,"timestamp":518891669384,"id":118,"parentId":1,"tags":{},"startTime":1779326863916,"traceId":"6f84d0e609888c2a"},{"name":"next-build","duration":22930244,"timestamp":518868751895,"id":1,"tags":{"buildMode":"default","version":"16.2.3","bundler":"turbopack","has-custom-webpack-config":"false","use-build-worker":"true"},"startTime":1779326840998,"traceId":"6f84d0e609888c2a"}]
@@ -1,4 +1,5 @@
1
1
  import { requireDashboardAuth, getV3UserToken } from '@/app/lib/dashboard-auth';
2
+ import { dedupeByHostname, parseHubTime, type HubServerRow } from '@/app/lib/serverDedupe';
2
3
 
3
4
  const HUB_URL = process.env.COMMHUB_URL || 'http://127.0.0.1:9200';
4
5
 
@@ -32,35 +33,8 @@ async function hubHeaders(): Promise<Record<string, string>> {
32
33
  * field in 0.8.1-preview.5.
33
34
  */
34
35
 
35
- interface HubServerRow {
36
- hostname: string;
37
- ip?: string | null;
38
- agent_count?: number;
39
- cpu_load_1min?: number | null;
40
- cpu_cores?: number | null;
41
- mem_used_gb?: number | null;
42
- mem_total_gb?: number | null;
43
- mem_avail_gb?: number | null;
44
- disk_used_gb?: number | null;
45
- disk_total_gb?: number | null;
46
- cpu_history?: number[];
47
- mem_history?: number[];
48
- agents?: unknown[];
49
- last_seen?: string | null;
50
- status?: 'online' | 'offline';
51
- note?: string;
52
- }
53
-
54
36
  function freshnessStatus(lastSeen: string | null | undefined): 'online' | 'offline' {
55
- if (!lastSeen) return 'offline';
56
- // commhub-server@0.8.1-preview.5 reports last_seen in "YYYY-MM-DD
57
- // HH:MM:SS" (space-separated, no timezone). Treat as UTC so all
58
- // clients agree regardless of their local zone. If a later hub
59
- // upgrade switches to ISO 8601 with explicit timezone, Date.parse
60
- // will accept either format and the +'Z' suffix is harmless.
61
- const iso = lastSeen.includes('T') ? lastSeen : lastSeen.replace(' ', 'T');
62
- const withTz = /[zZ]|[+-]\d{2}:?\d{2}$/.test(iso) ? iso : iso + 'Z';
63
- const t = Date.parse(withTz);
37
+ const t = parseHubTime(lastSeen);
64
38
  if (Number.isNaN(t)) return 'offline';
65
39
  // 90s freshness window — wider than the agent-node 30s report
66
40
  // cadence to absorb network latency + clock drift between client
@@ -117,7 +91,7 @@ export async function GET() {
117
91
  ? raw.servers
118
92
  : [];
119
93
  return Response.json({
120
- servers: rows.map(normalizeServer),
94
+ servers: dedupeByHostname(rows).map(normalizeServer),
121
95
  unavailable: raw?.unavailable === true,
122
96
  });
123
97
  } catch (e: unknown) {
@@ -5304,7 +5304,10 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
5304
5304
  /* R742 — entrance family +1 member: title-block joins
5305
5305
  canvas root as 2nd one-shot-mount surface. Staggered
5306
5306
  choreography: canvas 0-600ms, title-block 200-700ms. */
5307
- { mode: "one-shot-mount", family: "entrance", members: 2, examples: ["canvas root", "title-block"] },
5307
+ /* R743 entrance family +1 → 3 members: chrome strip joins
5308
+ canvas root + title-block, completing the entrance trio.
5309
+ 3-stage cascade: 0-600 / 200-700 / 400-900 ms. */
5310
+ { mode: "one-shot-mount", family: "entrance", members: 3, examples: ["canvas root", "title-block", "chrome strip"] },
5308
5311
  ])}
5309
5312
  data-topo-pinned-aspect={(() => {
5310
5313
  const aspects: string[] = [];
@@ -16909,7 +16912,22 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
16909
16912
  for the overlap-test (chrome is HTML overlay on top of
16910
16913
  the SVG, not part of the viewBox 1000x680 surface; ring
16911
16914
  r=325 / grid gx0 layout untouched). */}
16912
- <div className="absolute bottom-4 right-4 flex items-center gap-2 text-xs select-none" data-topo-chrome>
16915
+ {/* Round 743 / Loop chrome strip joins entrance family as 3rd
16916
+ one-shot-mount member, completing the entrance TRIO. Three-
16917
+ stage cascading "settle in" wave:
16918
+ R740 canvas 0 → 600 ms scale 0.99→1, opacity 0.8→1
16919
+ R742 title-block 200 → 700 ms translateY -4→0, opacity 0.7→1
16920
+ R743 chrome strip 400 → 900 ms translateX 8→0, opacity 0.7→1
16921
+ Each stage starts 200 ms after the prior — the canvas
16922
+ arrives, the heading writes in, then the chrome strip slides
16923
+ in from the right edge. translateX (not translateY) because
16924
+ the chrome strip lives at the right edge — sliding in from
16925
+ its own edge reads as "docking into place".
16926
+ Chrome strip wrapper is plain HTML with no existing
16927
+ animation, so a simple single-animation class suffices (no
16928
+ compound needed, unlike R742's title-block). Gated by
16929
+ reducedMotion at JSX level. See globals.css R743 block. */}
16930
+ <div className={`absolute bottom-4 right-4 flex items-center gap-2 text-xs select-none${reducedMotion ? '' : ' anet-topo-chrome-strip-entrance'}`} data-topo-chrome data-topo-chrome-entrance={reducedMotion ? 'false' : 'true'}>
16913
16931
  {/* #113: node size — S / M / L segmented control (Vincent 4727).
16914
16932
  R154: stable data-* hooks for tests + focus-visible ring so
16915
16933
  keyboard navigation lands somewhere visible against the
package/app/globals.css CHANGED
@@ -1748,6 +1748,31 @@ body {
1748
1748
  .anet-topo-title-block-entrance { animation: none; }
1749
1749
  }
1750
1750
 
1751
+ /* Round 743 — chrome strip entrance, 3rd member of the entrance family,
1752
+ completing the entrance TRIO. Three-stage cascade:
1753
+ R740 canvas 0 → 600 ms scale 0.99→1, opacity 0.8→1
1754
+ R742 title-block 200 → 700 ms translateY -4→0, opacity 0.7→1
1755
+ R743 chrome strip 400 → 900 ms translateX 8→0, opacity 0.7→1
1756
+ Each stage offset +200 ms. translateX (not translateY) because the
1757
+ chrome strip docks at the canvas right edge — sliding in from its
1758
+ own edge reads as "docking into place".
1759
+
1760
+ The chrome strip wrapper div has no other animation, so a plain
1761
+ single-animation class works here (no compound needed like R742's
1762
+ title-block which collided with R706 envelope-breath). One-shot —
1763
+ no `infinite`, runs once per mount. prefers-reduced-motion JSX gate
1764
+ + CSS @media guard. */
1765
+ @keyframes anet-topo-chrome-strip-entrance-kf {
1766
+ 0% { transform: translateX(8px); opacity: 0.7; }
1767
+ 100% { transform: translateX(0); opacity: 1; }
1768
+ }
1769
+ .anet-topo-chrome-strip-entrance {
1770
+ animation: anet-topo-chrome-strip-entrance-kf 500ms ease-out 400ms backwards;
1771
+ }
1772
+ @media (prefers-reduced-motion: reduce) {
1773
+ .anet-topo-chrome-strip-entrance { animation: none; }
1774
+ }
1775
+
1751
1776
  /* Round 707 — chrome Layout wrapper at-rest breath at 17 s. Slowest tier
1752
1777
  among HTML chrome respiratory anchors (sibling to R703 zoom-level 9 s
1753
1778
  in the chrome strip's data tier; this 17 s lands in the chrome strip's
@@ -0,0 +1,122 @@
1
+ /**
2
+ * #157 RC#2 — host telemetry row dedup for the Servers panel.
3
+ *
4
+ * The CommHub /api/servers endpoint keys host telemetry by (hostname,
5
+ * ip): a machine whose agents report over more than one interface
6
+ * yields one row per IP. Live data caught `iZrj93pr2rcf5r2y9uo1oyZ`
7
+ * twice — once at the Docker-bridge IP (carrying cpu/mem telemetry)
8
+ * and once at loopback (telemetry null) — so the panel showed the same
9
+ * physical host as two cards with split agent counts.
10
+ *
11
+ * Extracted from the /api/hub/servers route handler so the merge can
12
+ * be unit-tested against a mock fixture independently of the proxy.
13
+ */
14
+
15
+ export interface HubServerRow {
16
+ hostname: string;
17
+ ip?: string | null;
18
+ agent_count?: number;
19
+ cpu_load_1min?: number | null;
20
+ cpu_cores?: number | null;
21
+ mem_used_gb?: number | null;
22
+ mem_total_gb?: number | null;
23
+ mem_avail_gb?: number | null;
24
+ disk_used_gb?: number | null;
25
+ disk_total_gb?: number | null;
26
+ cpu_history?: number[];
27
+ mem_history?: number[];
28
+ agents?: unknown[];
29
+ last_seen?: string | null;
30
+ status?: 'online' | 'offline';
31
+ note?: string;
32
+ }
33
+
34
+ /**
35
+ * Parse a hub timestamp to epoch ms. CommHub reports last_seen as
36
+ * "YYYY-MM-DD HH:MM:SS" (space-separated, no timezone) — treat as UTC
37
+ * so all clients agree regardless of local zone. ISO 8601 with an
38
+ * explicit offset also parses cleanly (the +'Z' is only appended when
39
+ * no zone is present). Returns NaN for missing / unparseable input.
40
+ */
41
+ export function parseHubTime(ts: string | null | undefined): number {
42
+ if (!ts) return NaN;
43
+ const iso = ts.includes('T') ? ts : ts.replace(' ', 'T');
44
+ const withTz = /[zZ]|[+-]\d{2}:?\d{2}$/.test(iso) ? iso : iso + 'Z';
45
+ return Date.parse(withTz);
46
+ }
47
+
48
+ /**
49
+ * Collapse rows that share a hostname into one card.
50
+ *
51
+ * Dedup keys on hostname, not IP: a hostname is the machine identity,
52
+ * whereas an IP can be shared across hosts behind NAT (two distinct
53
+ * hostnames can surface as the same public IP) or differ per interface
54
+ * on one host. Merge rule for a multi-row hostname:
55
+ * - agent_count = sum across rows (one host's total fan-out)
56
+ * - telemetry = freshest-non-null per field — walk rows newest
57
+ * last_seen first, take the first row that actually
58
+ * reports each field, so a stale-but-telemetried row
59
+ * still contributes cpu/mem when the freshest row's
60
+ * values are null
61
+ * - last_seen = newest across rows
62
+ * - agents[] = union, dedup by alias
63
+ *
64
+ * Sentinel hostnames that are not real identities — empty or the
65
+ * literal "unknown" the hub emits when an agent never resolved its
66
+ * host — are passed through untouched: merging two distinct unknown
67
+ * machines into one card would be worse than showing both.
68
+ */
69
+ export function dedupeByHostname(rows: HubServerRow[]): HubServerRow[] {
70
+ const groups = new Map<string, HubServerRow[]>();
71
+ const passthrough: HubServerRow[] = [];
72
+ for (const row of rows) {
73
+ const h = row.hostname;
74
+ if (!h || h === 'unknown') { passthrough.push(row); continue; }
75
+ const bucket = groups.get(h) ?? [];
76
+ bucket.push(row);
77
+ groups.set(h, bucket);
78
+ }
79
+ const merged: HubServerRow[] = [];
80
+ for (const bucket of groups.values()) {
81
+ if (bucket.length === 1) { merged.push(bucket[0]); continue; }
82
+ // Freshest last_seen first. NaN (missing timestamp) sorts last.
83
+ const sorted = [...bucket].sort((a, b) => {
84
+ const ta = parseHubTime(a.last_seen), tb = parseHubTime(b.last_seen);
85
+ return (Number.isNaN(tb) ? -Infinity : tb) - (Number.isNaN(ta) ? -Infinity : ta);
86
+ });
87
+ const coalesce = <K extends keyof HubServerRow>(key: K): HubServerRow[K] | undefined => {
88
+ for (const r of sorted) {
89
+ const v = r[key];
90
+ if (v != null) return v;
91
+ }
92
+ return undefined;
93
+ };
94
+ const agentMap = new Map<string, unknown>();
95
+ for (const r of sorted) {
96
+ if (!Array.isArray(r.agents)) continue;
97
+ for (const a of r.agents) {
98
+ const key = (a as { alias?: string })?.alias ?? JSON.stringify(a);
99
+ if (!agentMap.has(key)) agentMap.set(key, a);
100
+ }
101
+ }
102
+ merged.push({
103
+ hostname: sorted[0].hostname,
104
+ ip: coalesce('ip') ?? null,
105
+ agent_count: bucket.reduce((sum, r) => sum + (r.agent_count ?? 0), 0),
106
+ cpu_load_1min: coalesce('cpu_load_1min') ?? null,
107
+ cpu_cores: coalesce('cpu_cores') ?? null,
108
+ mem_used_gb: coalesce('mem_used_gb') ?? null,
109
+ mem_total_gb: coalesce('mem_total_gb') ?? null,
110
+ mem_avail_gb: coalesce('mem_avail_gb') ?? null,
111
+ disk_used_gb: coalesce('disk_used_gb') ?? null,
112
+ disk_total_gb: coalesce('disk_total_gb') ?? null,
113
+ cpu_history: coalesce('cpu_history'),
114
+ mem_history: coalesce('mem_history'),
115
+ agents: agentMap.size > 0 ? [...agentMap.values()] : undefined,
116
+ last_seen: coalesce('last_seen') ?? null,
117
+ status: coalesce('status'),
118
+ note: coalesce('note'),
119
+ });
120
+ }
121
+ return [...merged, ...passthrough];
122
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sleep2agi/agent-network-dashboard",
3
- "version": "0.5.3-preview.256",
3
+ "version": "0.5.3-preview.259",
4
4
  "description": "Agent Network Dashboard \u2014 Web UI for managing AI Agent networks",
5
5
  "scripts": {
6
6
  "dev": "next dev",
@@ -0,0 +1,110 @@
1
+ /* #157 RC#2 verification — Servers panel hostname dedup.
2
+ *
3
+ * Bug (Vincent 5560 + live re-probe 2026-05-20): the hub /api/servers
4
+ * endpoint keys host telemetry by (hostname, ip), so a machine whose
5
+ * agents report over more than one interface surfaces as multiple
6
+ * rows. `iZrj93pr2rcf5r2y9uo1oyZ` appeared twice — Docker-bridge IP
7
+ * (telemetry-bearing) + loopback (telemetry null) — splitting its
8
+ * agent count across two cards.
9
+ *
10
+ * Fix: `dedupeByHostname` in app/lib/serverDedupe.ts, applied in the
11
+ * /api/hub/servers proxy before normalizeServer.
12
+ *
13
+ * Two legs:
14
+ * A. mock fixture — compile serverDedupe.ts, run a crafted payload
15
+ * that exercises every branch (multi-row merge, telemetry
16
+ * coalesce, NAT-shared IP NOT merged, `unknown` passthrough,
17
+ * agents[] union).
18
+ * B. real payload — GET the running dashboard proxy and assert no
19
+ * hostname appears twice + counts are summed.
20
+ */
21
+ import { execSync } from 'node:child_process';
22
+ import { readFileSync, renameSync, mkdirSync } from 'node:fs';
23
+ import { pathToFileURL } from 'node:url';
24
+
25
+ let failed = 0;
26
+ const ok = (name, cond, detail = '') => {
27
+ if (cond) { console.log(` ✅ ${name}`); }
28
+ else { console.log(` ❌ ${name}${detail ? ' — ' + detail : ''}`); failed++; }
29
+ };
30
+
31
+ // ── Leg A: mock fixture against the real dedup module ──────────────
32
+ console.log('Leg A — mock fixture (compiled serverDedupe.ts):');
33
+ const OUT = '/tmp/p157-rc2-dedupe';
34
+ mkdirSync(OUT, { recursive: true });
35
+ execSync(
36
+ `npx tsc app/lib/serverDedupe.ts --outDir ${OUT} --module es2022 --target es2022 --moduleResolution bundler --skipLibCheck`,
37
+ { stdio: 'inherit' },
38
+ );
39
+ renameSync(`${OUT}/serverDedupe.js`, `${OUT}/serverDedupe.mjs`);
40
+ const { dedupeByHostname } = await import(pathToFileURL(`${OUT}/serverDedupe.mjs`).href);
41
+
42
+ const fixture = [
43
+ // same hostname, two interfaces — bridge row fresh + telemetried,
44
+ // loopback row staler + telemetry null
45
+ { hostname: 'host-A', ip: '172.17.0.2', agent_count: 29, last_seen: '2026-05-20 04:41:46',
46
+ cpu_load_1min: 1.49, cpu_cores: 8, mem_used_gb: 22.6, mem_total_gb: 32,
47
+ agents: [{ alias: 'a1' }, { alias: 'a2' }] },
48
+ { hostname: 'host-A', ip: '127.0.0.1', agent_count: 38, last_seen: '2026-05-20 04:41:43',
49
+ cpu_load_1min: null, mem_used_gb: null,
50
+ agents: [{ alias: 'a2' }, { alias: 'a3' }] },
51
+ // NAT-shared public IP, distinct hostnames — must NOT merge
52
+ { hostname: 'host-B', ip: '223.167.142.73', agent_count: 5, last_seen: '2026-05-18 02:34:16' },
53
+ { hostname: 'host-C', ip: '223.167.142.73', agent_count: 2, last_seen: '2026-05-13 16:44:41' },
54
+ // sentinel hostname — two distinct unknown machines, pass through both
55
+ { hostname: 'unknown', ip: '127.0.0.1', agent_count: 2, last_seen: '2026-05-16 08:40:14' },
56
+ { hostname: 'unknown', ip: '10.0.0.9', agent_count: 1, last_seen: '2026-05-16 09:00:00' },
57
+ ];
58
+ const out = dedupeByHostname(fixture);
59
+ const byHost = (h) => out.filter(r => r.hostname === h);
60
+ const hostA = byHost('host-A')[0];
61
+
62
+ ok('host-A collapses 2 rows → 1', byHost('host-A').length === 1, `got ${byHost('host-A').length}`);
63
+ ok('host-A agent_count summed 29+38=67', hostA?.agent_count === 67, `got ${hostA?.agent_count}`);
64
+ ok('host-A telemetry coalesced from bridge row (cpu 1.49)', hostA?.cpu_load_1min === 1.49, `got ${hostA?.cpu_load_1min}`);
65
+ ok('host-A mem coalesced (22.6)', hostA?.mem_used_gb === 22.6, `got ${hostA?.mem_used_gb}`);
66
+ ok('host-A last_seen = freshest (04:41:46)', hostA?.last_seen === '2026-05-20 04:41:46', `got ${hostA?.last_seen}`);
67
+ ok('host-A agents[] unioned + dedup by alias (a1,a2,a3)',
68
+ hostA?.agents?.length === 3 &&
69
+ new Set(hostA.agents.map(a => a.alias)).size === 3,
70
+ `got ${JSON.stringify(hostA?.agents)}`);
71
+ ok('host-B + host-C NOT merged despite shared IP', byHost('host-B').length === 1 && byHost('host-C').length === 1);
72
+ ok('two `unknown` rows both pass through (not merged)', byHost('unknown').length === 2, `got ${byHost('unknown').length}`);
73
+ ok('total rows: 1 (A) + 1 (B) + 1 (C) + 2 (unknown) = 5', out.length === 5, `got ${out.length}`);
74
+
75
+ // idempotency — running dedup on already-deduped output is a no-op
76
+ const twice = dedupeByHostname(out);
77
+ ok('idempotent — dedup(dedup(x)) === dedup(x)', twice.length === out.length);
78
+
79
+ // ── Leg B: real payload through the running dashboard proxy ─────────
80
+ console.log('\nLeg B — real payload (live /api/hub/servers proxy):');
81
+ let TOKEN;
82
+ try {
83
+ TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
84
+ } catch {
85
+ console.log(' ⚠️ no anet config — skipping live leg');
86
+ }
87
+ if (TOKEN) {
88
+ const res = await fetch('http://127.0.0.1:3000/api/hub/servers', {
89
+ headers: { cookie: `anet_dashboard_session=v3:${TOKEN}` },
90
+ });
91
+ ok('proxy returns 200', res.status === 200, `status ${res.status}`);
92
+ const body = await res.json();
93
+ const servers = body.servers ?? [];
94
+ ok('proxy returns servers[]', Array.isArray(servers) && servers.length > 0, `got ${servers.length}`);
95
+ const counts = {};
96
+ for (const s of servers) counts[s.hostname] = (counts[s.hostname] ?? 0) + 1;
97
+ const dups = Object.entries(counts).filter(([h, n]) => n > 1 && h !== 'unknown' && h !== '');
98
+ ok('no real hostname appears twice', dups.length === 0, `dups: ${JSON.stringify(dups)}`);
99
+ const izrj = servers.find(s => s.hostname?.startsWith('iZrj93pr'));
100
+ if (izrj) {
101
+ ok('iZrj93pr… host present as single card', true);
102
+ ok('iZrj93pr… has telemetry after coalesce (cpu non-null)', izrj.cpu_load_1min != null, `cpu ${izrj.cpu_load_1min}`);
103
+ console.log(` ℹ️ iZrj93pr… merged: agent_count=${izrj.agent_count}, cpu=${izrj.cpu_load_1min}, ip=${izrj.ip}`);
104
+ } else {
105
+ console.log(' ℹ️ iZrj93pr… not in current live payload (hub state changed) — structural dup check still authoritative');
106
+ }
107
+ }
108
+
109
+ console.log(`\n${failed === 0 ? '✅ ALL GREEN' : `❌ ${failed} FAILED`}`);
110
+ process.exit(failed === 0 ? 0 : 1);
@@ -129,12 +129,11 @@ const results = {
129
129
  one_shot_entrance_pair: oneShot?.family === 'entrance',
130
130
  inf_rest_matches_rolodex_count: infRest?.members === rolodexAnchorCount,
131
131
  inf_sweep_matches_trio_count: infSweep?.members === scanBeamTrioAnchorCount,
132
- /* R742 entrance family grew from 1 → 2 members (title-block joined
133
- * canvas root). The R741-time invariant `=== 1` is invalidated;
134
- * widen to `>= 1` (entrance family is at least one member) and add
135
- * a separate `oneShot_count_is_2` reflecting the post-R742 reality. */
132
+ /* Entrance family has grown: R740 solo (1)R742 pair (2) → R743
133
+ * trio (3). The cardinality assertion tracks the current snapshot;
134
+ * one_shot_count_at_least_1 is the stable invariant. */
136
135
  one_shot_count_at_least_1: (oneShot?.members ?? 0) >= 1,
137
- one_shot_count_is_2: oneShot?.members === 2,
136
+ one_shot_count_is_3: oneShot?.members === 3,
138
137
  };
139
138
  const ok = Object.values(results).every(Boolean);
140
139
  console.log(`${ok ? '✅' : '❌'} R741 animation temporal modes catalog (8th meta-doc — octagon, lifecycle dimension):`,