@a5c-ai/babysitter-observer-dashboard 5.0.1-staging.7a8768ec

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 (513) hide show
  1. package/.next/BUILD_ID +1 -0
  2. package/.next/app-path-routes-manifest.json +16 -0
  3. package/.next/build-manifest.json +23 -0
  4. package/.next/export-marker.json +6 -0
  5. package/.next/fallback-build-manifest.json +13 -0
  6. package/.next/images-manifest.json +68 -0
  7. package/.next/next-minimal-server.js.nft.json +1 -0
  8. package/.next/next-server.js.nft.json +1 -0
  9. package/.next/package.json +1 -0
  10. package/.next/prerender-manifest.json +114 -0
  11. package/.next/required-server-files.json +334 -0
  12. package/.next/routes-manifest.json +139 -0
  13. package/.next/server/app/_global-error/page/app-paths-manifest.json +3 -0
  14. package/.next/server/app/_global-error/page/build-manifest.json +19 -0
  15. package/.next/server/app/_global-error/page/next-font-manifest.json +6 -0
  16. package/.next/server/app/_global-error/page/react-loadable-manifest.json +1 -0
  17. package/.next/server/app/_global-error/page/server-reference-manifest.json +4 -0
  18. package/.next/server/app/_global-error/page.js +9 -0
  19. package/.next/server/app/_global-error/page.js.map +5 -0
  20. package/.next/server/app/_global-error/page.js.nft.json +1 -0
  21. package/.next/server/app/_global-error/page_client-reference-manifest.js +3 -0
  22. package/.next/server/app/_global-error.html +1 -0
  23. package/.next/server/app/_global-error.meta +15 -0
  24. package/.next/server/app/_global-error.rsc +14 -0
  25. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +5 -0
  26. package/.next/server/app/_global-error.segments/_full.segment.rsc +14 -0
  27. package/.next/server/app/_global-error.segments/_head.segment.rsc +5 -0
  28. package/.next/server/app/_global-error.segments/_index.segment.rsc +5 -0
  29. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -0
  30. package/.next/server/app/_not-found/page/app-paths-manifest.json +3 -0
  31. package/.next/server/app/_not-found/page/build-manifest.json +19 -0
  32. package/.next/server/app/_not-found/page/next-font-manifest.json +6 -0
  33. package/.next/server/app/_not-found/page/react-loadable-manifest.json +1 -0
  34. package/.next/server/app/_not-found/page/server-reference-manifest.json +4 -0
  35. package/.next/server/app/_not-found/page.js +13 -0
  36. package/.next/server/app/_not-found/page.js.map +5 -0
  37. package/.next/server/app/_not-found/page.js.nft.json +1 -0
  38. package/.next/server/app/_not-found/page_client-reference-manifest.js +3 -0
  39. package/.next/server/app/_not-found.html +1 -0
  40. package/.next/server/app/_not-found.meta +16 -0
  41. package/.next/server/app/_not-found.rsc +19 -0
  42. package/.next/server/app/_not-found.segments/_full.segment.rsc +19 -0
  43. package/.next/server/app/_not-found.segments/_head.segment.rsc +6 -0
  44. package/.next/server/app/_not-found.segments/_index.segment.rsc +8 -0
  45. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +6 -0
  46. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +5 -0
  47. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -0
  48. package/.next/server/app/api/config/route/app-paths-manifest.json +3 -0
  49. package/.next/server/app/api/config/route/build-manifest.json +9 -0
  50. package/.next/server/app/api/config/route/server-reference-manifest.json +4 -0
  51. package/.next/server/app/api/config/route.js +8 -0
  52. package/.next/server/app/api/config/route.js.map +5 -0
  53. package/.next/server/app/api/config/route.js.nft.json +1 -0
  54. package/.next/server/app/api/config/route_client-reference-manifest.js +3 -0
  55. package/.next/server/app/api/digest/route/app-paths-manifest.json +3 -0
  56. package/.next/server/app/api/digest/route/build-manifest.json +9 -0
  57. package/.next/server/app/api/digest/route/server-reference-manifest.json +4 -0
  58. package/.next/server/app/api/digest/route.js +9 -0
  59. package/.next/server/app/api/digest/route.js.map +5 -0
  60. package/.next/server/app/api/digest/route.js.nft.json +1 -0
  61. package/.next/server/app/api/digest/route_client-reference-manifest.js +3 -0
  62. package/.next/server/app/api/runs/[runId]/events/route/app-paths-manifest.json +3 -0
  63. package/.next/server/app/api/runs/[runId]/events/route/build-manifest.json +9 -0
  64. package/.next/server/app/api/runs/[runId]/events/route/server-reference-manifest.json +4 -0
  65. package/.next/server/app/api/runs/[runId]/events/route.js +8 -0
  66. package/.next/server/app/api/runs/[runId]/events/route.js.map +5 -0
  67. package/.next/server/app/api/runs/[runId]/events/route.js.nft.json +1 -0
  68. package/.next/server/app/api/runs/[runId]/events/route_client-reference-manifest.js +3 -0
  69. package/.next/server/app/api/runs/[runId]/route/app-paths-manifest.json +3 -0
  70. package/.next/server/app/api/runs/[runId]/route/build-manifest.json +9 -0
  71. package/.next/server/app/api/runs/[runId]/route/server-reference-manifest.json +4 -0
  72. package/.next/server/app/api/runs/[runId]/route.js +9 -0
  73. package/.next/server/app/api/runs/[runId]/route.js.map +5 -0
  74. package/.next/server/app/api/runs/[runId]/route.js.nft.json +1 -0
  75. package/.next/server/app/api/runs/[runId]/route_client-reference-manifest.js +3 -0
  76. package/.next/server/app/api/runs/[runId]/tasks/[effectId]/route/app-paths-manifest.json +3 -0
  77. package/.next/server/app/api/runs/[runId]/tasks/[effectId]/route/build-manifest.json +9 -0
  78. package/.next/server/app/api/runs/[runId]/tasks/[effectId]/route/server-reference-manifest.json +4 -0
  79. package/.next/server/app/api/runs/[runId]/tasks/[effectId]/route.js +8 -0
  80. package/.next/server/app/api/runs/[runId]/tasks/[effectId]/route.js.map +5 -0
  81. package/.next/server/app/api/runs/[runId]/tasks/[effectId]/route.js.nft.json +1 -0
  82. package/.next/server/app/api/runs/[runId]/tasks/[effectId]/route_client-reference-manifest.js +3 -0
  83. package/.next/server/app/api/runs/route/app-paths-manifest.json +3 -0
  84. package/.next/server/app/api/runs/route/build-manifest.json +9 -0
  85. package/.next/server/app/api/runs/route/server-reference-manifest.json +4 -0
  86. package/.next/server/app/api/runs/route.js +9 -0
  87. package/.next/server/app/api/runs/route.js.map +5 -0
  88. package/.next/server/app/api/runs/route.js.nft.json +1 -0
  89. package/.next/server/app/api/runs/route_client-reference-manifest.js +3 -0
  90. package/.next/server/app/api/stream/route/app-paths-manifest.json +3 -0
  91. package/.next/server/app/api/stream/route/build-manifest.json +9 -0
  92. package/.next/server/app/api/stream/route/server-reference-manifest.json +4 -0
  93. package/.next/server/app/api/stream/route.js +8 -0
  94. package/.next/server/app/api/stream/route.js.map +5 -0
  95. package/.next/server/app/api/stream/route.js.nft.json +1 -0
  96. package/.next/server/app/api/stream/route_client-reference-manifest.js +3 -0
  97. package/.next/server/app/api/test/route/app-paths-manifest.json +3 -0
  98. package/.next/server/app/api/test/route/build-manifest.json +9 -0
  99. package/.next/server/app/api/test/route/server-reference-manifest.json +4 -0
  100. package/.next/server/app/api/test/route.js +6 -0
  101. package/.next/server/app/api/test/route.js.map +5 -0
  102. package/.next/server/app/api/test/route.js.nft.json +1 -0
  103. package/.next/server/app/api/test/route_client-reference-manifest.js +3 -0
  104. package/.next/server/app/api/version/route/app-paths-manifest.json +3 -0
  105. package/.next/server/app/api/version/route/build-manifest.json +9 -0
  106. package/.next/server/app/api/version/route/server-reference-manifest.json +4 -0
  107. package/.next/server/app/api/version/route.js +7 -0
  108. package/.next/server/app/api/version/route.js.map +5 -0
  109. package/.next/server/app/api/version/route.js.nft.json +1 -0
  110. package/.next/server/app/api/version/route_client-reference-manifest.js +3 -0
  111. package/.next/server/app/icon.svg/route/app-paths-manifest.json +3 -0
  112. package/.next/server/app/icon.svg/route/build-manifest.json +9 -0
  113. package/.next/server/app/icon.svg/route.js +7 -0
  114. package/.next/server/app/icon.svg/route.js.map +5 -0
  115. package/.next/server/app/icon.svg/route.js.nft.json +1 -0
  116. package/.next/server/app/icon.svg.body +20 -0
  117. package/.next/server/app/icon.svg.meta +1 -0
  118. package/.next/server/app/index.html +1 -0
  119. package/.next/server/app/index.meta +14 -0
  120. package/.next/server/app/index.rsc +21 -0
  121. package/.next/server/app/index.segments/__PAGE__.segment.rsc +9 -0
  122. package/.next/server/app/index.segments/_full.segment.rsc +21 -0
  123. package/.next/server/app/index.segments/_head.segment.rsc +6 -0
  124. package/.next/server/app/index.segments/_index.segment.rsc +8 -0
  125. package/.next/server/app/index.segments/_tree.segment.rsc +2 -0
  126. package/.next/server/app/page/app-paths-manifest.json +3 -0
  127. package/.next/server/app/page/build-manifest.json +19 -0
  128. package/.next/server/app/page/next-font-manifest.json +6 -0
  129. package/.next/server/app/page/react-loadable-manifest.json +1 -0
  130. package/.next/server/app/page/server-reference-manifest.json +17 -0
  131. package/.next/server/app/page.js +15 -0
  132. package/.next/server/app/page.js.map +5 -0
  133. package/.next/server/app/page.js.nft.json +1 -0
  134. package/.next/server/app/page_client-reference-manifest.js +3 -0
  135. package/.next/server/app/runs/[runId]/page/app-paths-manifest.json +3 -0
  136. package/.next/server/app/runs/[runId]/page/build-manifest.json +19 -0
  137. package/.next/server/app/runs/[runId]/page/next-font-manifest.json +6 -0
  138. package/.next/server/app/runs/[runId]/page/react-loadable-manifest.json +22 -0
  139. package/.next/server/app/runs/[runId]/page/server-reference-manifest.json +17 -0
  140. package/.next/server/app/runs/[runId]/page.js +15 -0
  141. package/.next/server/app/runs/[runId]/page.js.map +5 -0
  142. package/.next/server/app/runs/[runId]/page.js.nft.json +1 -0
  143. package/.next/server/app/runs/[runId]/page_client-reference-manifest.js +3 -0
  144. package/.next/server/app-paths-manifest.json +16 -0
  145. package/.next/server/chunks/01oi_server_app_api_runs_[runId]_tasks_[effectId]_route_actions_0r72yai.js +3 -0
  146. package/.next/server/chunks/01oi_server_app_api_runs_[runId]_tasks_[effectId]_route_actions_0r72yai.js.map +1 -0
  147. package/.next/server/chunks/0h.v__next-internal_server_app_api_runs_[runId]_events_route_actions_0~msldk.js +3 -0
  148. package/.next/server/chunks/0h.v__next-internal_server_app_api_runs_[runId]_events_route_actions_0~msldk.js.map +1 -0
  149. package/.next/server/chunks/0h.v__next-internal_server_app_api_runs_[runId]_route_actions_09iz0n6.js +3 -0
  150. package/.next/server/chunks/0h.v__next-internal_server_app_api_runs_[runId]_route_actions_09iz0n6.js.map +1 -0
  151. package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_config_route_actions_0~eypoa.js +3 -0
  152. package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_config_route_actions_0~eypoa.js.map +1 -0
  153. package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_digest_route_actions_04jj5zs.js +3 -0
  154. package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_digest_route_actions_04jj5zs.js.map +1 -0
  155. package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_runs_route_actions_0~-t-o4.js +3 -0
  156. package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_runs_route_actions_0~-t-o4.js.map +1 -0
  157. package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_stream_route_actions_0fkmv2_.js +3 -0
  158. package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_stream_route_actions_0fkmv2_.js.map +1 -0
  159. package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_test_route_actions_00ugava.js +3 -0
  160. package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_test_route_actions_00ugava.js.map +1 -0
  161. package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_version_route_actions_0~v3ojm.js +3 -0
  162. package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_version_route_actions_0~v3ojm.js.map +1 -0
  163. package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_icon_svg_route_actions_0yypxkm.js +3 -0
  164. package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_icon_svg_route_actions_0yypxkm.js.map +1 -0
  165. package/.next/server/chunks/[root-of-the-server]__0.6bt.6._.js +3 -0
  166. package/.next/server/chunks/[root-of-the-server]__0.6bt.6._.js.map +1 -0
  167. package/.next/server/chunks/[root-of-the-server]__08kwev1._.js +3 -0
  168. package/.next/server/chunks/[root-of-the-server]__08kwev1._.js.map +1 -0
  169. package/.next/server/chunks/[root-of-the-server]__096el.d._.js +3 -0
  170. package/.next/server/chunks/[root-of-the-server]__096el.d._.js.map +1 -0
  171. package/.next/server/chunks/[root-of-the-server]__0_bmt4z._.js +3 -0
  172. package/.next/server/chunks/[root-of-the-server]__0_bmt4z._.js.map +1 -0
  173. package/.next/server/chunks/[root-of-the-server]__0_ln2d2._.js +3 -0
  174. package/.next/server/chunks/[root-of-the-server]__0_ln2d2._.js.map +1 -0
  175. package/.next/server/chunks/[root-of-the-server]__0al3v65._.js +3 -0
  176. package/.next/server/chunks/[root-of-the-server]__0al3v65._.js.map +1 -0
  177. package/.next/server/chunks/[root-of-the-server]__0gf516b._.js +3 -0
  178. package/.next/server/chunks/[root-of-the-server]__0gf516b._.js.map +1 -0
  179. package/.next/server/chunks/[root-of-the-server]__0kdfw4x._.js +3 -0
  180. package/.next/server/chunks/[root-of-the-server]__0kdfw4x._.js.map +1 -0
  181. package/.next/server/chunks/[root-of-the-server]__0pxt00h._.js +3 -0
  182. package/.next/server/chunks/[root-of-the-server]__0pxt00h._.js.map +1 -0
  183. package/.next/server/chunks/[root-of-the-server]__0rubnza._.js +3 -0
  184. package/.next/server/chunks/[root-of-the-server]__0rubnza._.js.map +1 -0
  185. package/.next/server/chunks/[root-of-the-server]__0tn9iud._.js +3 -0
  186. package/.next/server/chunks/[root-of-the-server]__0tn9iud._.js.map +1 -0
  187. package/.next/server/chunks/[root-of-the-server]__0ws5o6i._.js +3 -0
  188. package/.next/server/chunks/[root-of-the-server]__0ws5o6i._.js.map +1 -0
  189. package/.next/server/chunks/[turbopack]_runtime.js +903 -0
  190. package/.next/server/chunks/[turbopack]_runtime.js.map +11 -0
  191. package/.next/server/chunks/node_modules_next_04~_e52._.js +13 -0
  192. package/.next/server/chunks/node_modules_next_04~_e52._.js.map +1 -0
  193. package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0nyyph-.js +9 -0
  194. package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0nyyph-.js.map +1 -0
  195. package/.next/server/chunks/packages_observer-dashboard_src_lib_02.vvb.._.js +3 -0
  196. package/.next/server/chunks/packages_observer-dashboard_src_lib_02.vvb.._.js.map +1 -0
  197. package/.next/server/chunks/packages_observer-dashboard_src_lib_0rqgpk0._.js +3 -0
  198. package/.next/server/chunks/packages_observer-dashboard_src_lib_0rqgpk0._.js.map +1 -0
  199. package/.next/server/chunks/ssr/0juq_observer-dashboard__next-internal_server_app__global-error_page_actions_0ekoxmy.js +3 -0
  200. package/.next/server/chunks/ssr/0juq_observer-dashboard__next-internal_server_app__global-error_page_actions_0ekoxmy.js.map +1 -0
  201. package/.next/server/chunks/ssr/0juq_observer-dashboard__next-internal_server_app__not-found_page_actions_09b3ti3.js +3 -0
  202. package/.next/server/chunks/ssr/0juq_observer-dashboard__next-internal_server_app__not-found_page_actions_09b3ti3.js.map +1 -0
  203. package/.next/server/chunks/ssr/[root-of-the-server]__006f7~t._.js +4 -0
  204. package/.next/server/chunks/ssr/[root-of-the-server]__006f7~t._.js.map +1 -0
  205. package/.next/server/chunks/ssr/[root-of-the-server]__02jgvbi._.js +3 -0
  206. package/.next/server/chunks/ssr/[root-of-the-server]__02jgvbi._.js.map +1 -0
  207. package/.next/server/chunks/ssr/[root-of-the-server]__04j8t~1._.js +3 -0
  208. package/.next/server/chunks/ssr/[root-of-the-server]__04j8t~1._.js.map +1 -0
  209. package/.next/server/chunks/ssr/[root-of-the-server]__09c~s.0._.js +33 -0
  210. package/.next/server/chunks/ssr/[root-of-the-server]__09c~s.0._.js.map +1 -0
  211. package/.next/server/chunks/ssr/[root-of-the-server]__0cpy61n._.js +3 -0
  212. package/.next/server/chunks/ssr/[root-of-the-server]__0cpy61n._.js.map +1 -0
  213. package/.next/server/chunks/ssr/[root-of-the-server]__0cwa32j._.js +3 -0
  214. package/.next/server/chunks/ssr/[root-of-the-server]__0cwa32j._.js.map +1 -0
  215. package/.next/server/chunks/ssr/[root-of-the-server]__0fk_g0j._.js +19 -0
  216. package/.next/server/chunks/ssr/[root-of-the-server]__0fk_g0j._.js.map +1 -0
  217. package/.next/server/chunks/ssr/[root-of-the-server]__0pddpic._.js +3 -0
  218. package/.next/server/chunks/ssr/[root-of-the-server]__0pddpic._.js.map +1 -0
  219. package/.next/server/chunks/ssr/[root-of-the-server]__0pvtneq._.js +3 -0
  220. package/.next/server/chunks/ssr/[root-of-the-server]__0pvtneq._.js.map +1 -0
  221. package/.next/server/chunks/ssr/[root-of-the-server]__0xc-2vm._.js +3 -0
  222. package/.next/server/chunks/ssr/[root-of-the-server]__0xc-2vm._.js.map +1 -0
  223. package/.next/server/chunks/ssr/[root-of-the-server]__10xgshr._.js +33 -0
  224. package/.next/server/chunks/ssr/[root-of-the-server]__10xgshr._.js.map +1 -0
  225. package/.next/server/chunks/ssr/[turbopack]_runtime.js +903 -0
  226. package/.next/server/chunks/ssr/[turbopack]_runtime.js.map +11 -0
  227. package/.next/server/chunks/ssr/_00yo1im._.js +3 -0
  228. package/.next/server/chunks/ssr/_00yo1im._.js.map +1 -0
  229. package/.next/server/chunks/ssr/_03sbc.o._.js +3 -0
  230. package/.next/server/chunks/ssr/_03sbc.o._.js.map +1 -0
  231. package/.next/server/chunks/ssr/_04z5ea0._.js +3 -0
  232. package/.next/server/chunks/ssr/_04z5ea0._.js.map +1 -0
  233. package/.next/server/chunks/ssr/_0gmb3g_._.js +3 -0
  234. package/.next/server/chunks/ssr/_0gmb3g_._.js.map +1 -0
  235. package/.next/server/chunks/ssr/_0okz9j8._.js +6 -0
  236. package/.next/server/chunks/ssr/_0okz9j8._.js.map +1 -0
  237. package/.next/server/chunks/ssr/_0wrbwro._.js +6 -0
  238. package/.next/server/chunks/ssr/_0wrbwro._.js.map +1 -0
  239. package/.next/server/chunks/ssr/node_modules_09w7yel._.js +33 -0
  240. package/.next/server/chunks/ssr/node_modules_09w7yel._.js.map +1 -0
  241. package/.next/server/chunks/ssr/node_modules_next_dist_0avqw4q._.js +3 -0
  242. package/.next/server/chunks/ssr/node_modules_next_dist_0avqw4q._.js.map +1 -0
  243. package/.next/server/chunks/ssr/node_modules_next_dist_0h9llsw._.js +6 -0
  244. package/.next/server/chunks/ssr/node_modules_next_dist_0h9llsw._.js.map +1 -0
  245. package/.next/server/chunks/ssr/node_modules_next_dist_0i_._k3._.js +3 -0
  246. package/.next/server/chunks/ssr/node_modules_next_dist_0i_._k3._.js.map +1 -0
  247. package/.next/server/chunks/ssr/node_modules_next_dist_client_components_0ee1czk._.js +3 -0
  248. package/.next/server/chunks/ssr/node_modules_next_dist_client_components_0ee1czk._.js.map +1 -0
  249. package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_0lgvd_..js +3 -0
  250. package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_0lgvd_..js.map +1 -0
  251. package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_unauthorized_0cjv-23.js +3 -0
  252. package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_unauthorized_0cjv-23.js.map +1 -0
  253. package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0amzg6z.js +4 -0
  254. package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0amzg6z.js.map +1 -0
  255. package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0dw1x0d.js +4 -0
  256. package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0dw1x0d.js.map +1 -0
  257. package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0rc3ul_.js +4 -0
  258. package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0rc3ul_.js.map +1 -0
  259. package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_10iomok.js +4 -0
  260. package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_10iomok.js.map +1 -0
  261. package/.next/server/chunks/ssr/packages_observer-dashboard_0~a2tmu._.js +3 -0
  262. package/.next/server/chunks/ssr/packages_observer-dashboard_0~a2tmu._.js.map +1 -0
  263. package/.next/server/chunks/ssr/packages_observer-dashboard_src_0f.ozc-._.js +3 -0
  264. package/.next/server/chunks/ssr/packages_observer-dashboard_src_0f.ozc-._.js.map +1 -0
  265. package/.next/server/chunks/ssr/packages_observer-dashboard_src_components_providers_tsx_03_vrrn._.js +7 -0
  266. package/.next/server/chunks/ssr/packages_observer-dashboard_src_components_providers_tsx_03_vrrn._.js.map +1 -0
  267. package/.next/server/functions-config-manifest.json +4 -0
  268. package/.next/server/interception-route-rewrite-manifest.js +1 -0
  269. package/.next/server/middleware-build-manifest.js +23 -0
  270. package/.next/server/middleware-manifest.json +6 -0
  271. package/.next/server/next-font-manifest.js +1 -0
  272. package/.next/server/next-font-manifest.json +6 -0
  273. package/.next/server/pages/404.html +1 -0
  274. package/.next/server/pages/500.html +1 -0
  275. package/.next/server/pages-manifest.json +4 -0
  276. package/.next/server/prefetch-hints.json +1 -0
  277. package/.next/server/server-reference-manifest.js +1 -0
  278. package/.next/server/server-reference-manifest.json +24 -0
  279. package/.next/static/MvfPly4ZXHqaveDVOG1qq/_buildManifest.js +11 -0
  280. package/.next/static/MvfPly4ZXHqaveDVOG1qq/_clientMiddlewareManifest.js +1 -0
  281. package/.next/static/MvfPly4ZXHqaveDVOG1qq/_ssgManifest.js +1 -0
  282. package/.next/static/chunks/00c87uqn~kk2z.js +1 -0
  283. package/.next/static/chunks/01xlw8hd842-c.js +1 -0
  284. package/.next/static/chunks/02p9dpa.0oxiz.js +1 -0
  285. package/.next/static/chunks/034i63v_muq~d.js +1 -0
  286. package/.next/static/chunks/03mo-6~4pxdio.js +1 -0
  287. package/.next/static/chunks/03~yq9q893hmn.js +1 -0
  288. package/.next/static/chunks/04dm5qn77.fc2.js +1 -0
  289. package/.next/static/chunks/07uz2g0_38qia.js +4 -0
  290. package/.next/static/chunks/08nqnwvixoxnk.js +2 -0
  291. package/.next/static/chunks/0d3shmwh5_nmn.js +1 -0
  292. package/.next/static/chunks/0e_wyjw3nx.a..js +1 -0
  293. package/.next/static/chunks/0mstyq17cbf8-.js +1 -0
  294. package/.next/static/chunks/0ntuxw9.how-q.js +1 -0
  295. package/.next/static/chunks/0t3uzajv1qzmo.js +1 -0
  296. package/.next/static/chunks/0u~_nwr5-v.xp.js +1 -0
  297. package/.next/static/chunks/0wxcxh6eyzams.js +1 -0
  298. package/.next/static/chunks/0x6y7yt4kiddp.css +1 -0
  299. package/.next/static/chunks/0z6-vonyxr0dn.js +4 -0
  300. package/.next/static/chunks/0ze4gu236oq96.js +31 -0
  301. package/.next/static/chunks/0zwozael9msy1.js +1 -0
  302. package/.next/static/chunks/10qd__0r7a~.l.js +1 -0
  303. package/.next/static/chunks/11jh_u1ynmatg.js +1 -0
  304. package/.next/static/chunks/13xer3cb9shu-.js +5 -0
  305. package/.next/static/chunks/142zlnch_xmgd.js +1 -0
  306. package/.next/static/chunks/144kcri75qczu.js +1 -0
  307. package/.next/static/chunks/turbopack-0-ww6fe7b37qt.js +1 -0
  308. package/.next/static/media/icon.08ljfy7xai2x_.svg +20 -0
  309. package/LICENSE +21 -0
  310. package/README.md +490 -0
  311. package/next.config.mjs +25 -0
  312. package/package.json +104 -0
  313. package/postcss.config.mjs +8 -0
  314. package/src/app/actions/__tests__/approve-breakpoint.test.ts +246 -0
  315. package/src/app/actions/approve-breakpoint.ts +145 -0
  316. package/src/app/api/config/route.ts +137 -0
  317. package/src/app/api/digest/route.ts +45 -0
  318. package/src/app/api/runs/[runId]/events/route.ts +56 -0
  319. package/src/app/api/runs/[runId]/route.ts +84 -0
  320. package/src/app/api/runs/[runId]/tasks/[effectId]/route.ts +44 -0
  321. package/src/app/api/runs/route.ts +48 -0
  322. package/src/app/api/stream/route.ts +136 -0
  323. package/src/app/api/test/route.ts +1 -0
  324. package/src/app/api/version/route.ts +57 -0
  325. package/src/app/globals.css +555 -0
  326. package/src/app/icon.svg +20 -0
  327. package/src/app/layout.tsx +39 -0
  328. package/src/app/not-found.tsx +16 -0
  329. package/src/app/page.tsx +120 -0
  330. package/src/app/runs/[runId]/page.tsx +279 -0
  331. package/src/cli.ts +271 -0
  332. package/src/components/breakpoint/__tests__/breakpoint-approval.test.tsx +212 -0
  333. package/src/components/breakpoint/__tests__/breakpoint-panel.test.tsx +130 -0
  334. package/src/components/breakpoint/__tests__/file-preview.test.tsx +313 -0
  335. package/src/components/breakpoint/breakpoint-approval.tsx +138 -0
  336. package/src/components/breakpoint/breakpoint-panel.tsx +95 -0
  337. package/src/components/breakpoint/file-preview.tsx +215 -0
  338. package/src/components/dashboard/.gitkeep +0 -0
  339. package/src/components/dashboard/__tests__/breakpoint-banner.test.tsx +177 -0
  340. package/src/components/dashboard/__tests__/catch-up-banner.test.tsx +141 -0
  341. package/src/components/dashboard/__tests__/executive-summary-banner.test.tsx +164 -0
  342. package/src/components/dashboard/__tests__/kpi-grid.test.tsx +101 -0
  343. package/src/components/dashboard/__tests__/pagination-controls.test.tsx +125 -0
  344. package/src/components/dashboard/__tests__/project-accordion.test.tsx +97 -0
  345. package/src/components/dashboard/__tests__/project-list-view.test.tsx +174 -0
  346. package/src/components/dashboard/__tests__/project-search-input.test.tsx +110 -0
  347. package/src/components/dashboard/__tests__/project-section-header.test.tsx +91 -0
  348. package/src/components/dashboard/__tests__/project-section.test.tsx +151 -0
  349. package/src/components/dashboard/__tests__/run-card.test.tsx +164 -0
  350. package/src/components/dashboard/__tests__/run-filter-bar.test.tsx +109 -0
  351. package/src/components/dashboard/__tests__/run-list.test.tsx +123 -0
  352. package/src/components/dashboard/__tests__/search-filter.test.tsx +150 -0
  353. package/src/components/dashboard/__tests__/virtualized-run-list.test.tsx +179 -0
  354. package/src/components/dashboard/breakpoint-banner.tsx +301 -0
  355. package/src/components/dashboard/catch-up-banner.tsx +88 -0
  356. package/src/components/dashboard/executive-summary-banner.tsx +174 -0
  357. package/src/components/dashboard/global-search.tsx +323 -0
  358. package/src/components/dashboard/kpi-grid.tsx +140 -0
  359. package/src/components/dashboard/pagination-controls.tsx +100 -0
  360. package/src/components/dashboard/project-accordion.tsx +72 -0
  361. package/src/components/dashboard/project-health-card.tsx +536 -0
  362. package/src/components/dashboard/project-list-view.tsx +246 -0
  363. package/src/components/dashboard/project-search-input.tsx +41 -0
  364. package/src/components/dashboard/project-section-header.tsx +73 -0
  365. package/src/components/dashboard/project-section.tsx +89 -0
  366. package/src/components/dashboard/run-card.tsx +218 -0
  367. package/src/components/dashboard/run-filter-bar.tsx +100 -0
  368. package/src/components/dashboard/run-list.tsx +77 -0
  369. package/src/components/dashboard/search-filter.tsx +69 -0
  370. package/src/components/dashboard/virtualized-run-list.tsx +130 -0
  371. package/src/components/details/.gitkeep +0 -0
  372. package/src/components/details/__tests__/agent-panel.test.tsx +236 -0
  373. package/src/components/details/__tests__/json-tree.test.tsx +347 -0
  374. package/src/components/details/__tests__/log-viewer.test.tsx +168 -0
  375. package/src/components/details/__tests__/task-detail.test.tsx +212 -0
  376. package/src/components/details/__tests__/timing-panel.test.tsx +271 -0
  377. package/src/components/details/agent-panel.tsx +234 -0
  378. package/src/components/details/json-tree/categorize.ts +131 -0
  379. package/src/components/details/json-tree/index.tsx +120 -0
  380. package/src/components/details/json-tree/json-node.tsx +223 -0
  381. package/src/components/details/json-tree/smart-summary.tsx +596 -0
  382. package/src/components/details/json-tree/tree-controls.tsx +47 -0
  383. package/src/components/details/json-tree.tsx +9 -0
  384. package/src/components/details/log-viewer.tsx +140 -0
  385. package/src/components/details/task-detail.tsx +114 -0
  386. package/src/components/details/timing-panel.tsx +247 -0
  387. package/src/components/events/.gitkeep +0 -0
  388. package/src/components/events/__tests__/event-item.test.tsx +211 -0
  389. package/src/components/events/__tests__/event-stream.test.tsx +225 -0
  390. package/src/components/events/event-item.tsx +121 -0
  391. package/src/components/events/event-stream.tsx +260 -0
  392. package/src/components/notifications/.gitkeep +0 -0
  393. package/src/components/notifications/__tests__/notification-panel.test.tsx +287 -0
  394. package/src/components/notifications/__tests__/notification-provider.test.tsx +585 -0
  395. package/src/components/notifications/__tests__/toast-stack.test.tsx +217 -0
  396. package/src/components/notifications/notification-panel.tsx +124 -0
  397. package/src/components/notifications/notification-provider.tsx +175 -0
  398. package/src/components/notifications/toast-stack.tsx +75 -0
  399. package/src/components/pipeline/.gitkeep +0 -0
  400. package/src/components/pipeline/__tests__/parallel-group.test.tsx +88 -0
  401. package/src/components/pipeline/__tests__/pipeline-view.test.tsx +345 -0
  402. package/src/components/pipeline/__tests__/step-card.test.tsx +330 -0
  403. package/src/components/pipeline/parallel-group.tsx +39 -0
  404. package/src/components/pipeline/pipeline-view.tsx +197 -0
  405. package/src/components/pipeline/step-card.tsx +166 -0
  406. package/src/components/providers/event-stream-provider.tsx +29 -0
  407. package/src/components/providers.tsx +24 -0
  408. package/src/components/shared/.gitkeep +0 -0
  409. package/src/components/shared/__tests__/empty-state.test.tsx +49 -0
  410. package/src/components/shared/__tests__/friendly-id.test.tsx +47 -0
  411. package/src/components/shared/__tests__/kbd.test.tsx +45 -0
  412. package/src/components/shared/__tests__/kind-badge.test.tsx +71 -0
  413. package/src/components/shared/__tests__/metrics-row.test.tsx +74 -0
  414. package/src/components/shared/__tests__/outcome-banner.test.tsx +71 -0
  415. package/src/components/shared/__tests__/progress-bar.test.tsx +89 -0
  416. package/src/components/shared/__tests__/session-pill.test.tsx +62 -0
  417. package/src/components/shared/__tests__/settings-modal.test.tsx +201 -0
  418. package/src/components/shared/__tests__/shortcuts-help.test.tsx +103 -0
  419. package/src/components/shared/__tests__/status-badge.test.tsx +98 -0
  420. package/src/components/shared/__tests__/theme-provider.test.tsx +100 -0
  421. package/src/components/shared/__tests__/truncated-id.test.tsx +53 -0
  422. package/src/components/shared/app-footer.tsx +80 -0
  423. package/src/components/shared/app-header.tsx +160 -0
  424. package/src/components/shared/empty-state.tsx +18 -0
  425. package/src/components/shared/error-boundary.tsx +81 -0
  426. package/src/components/shared/friendly-id.tsx +48 -0
  427. package/src/components/shared/kbd.tsx +15 -0
  428. package/src/components/shared/kind-badge.tsx +51 -0
  429. package/src/components/shared/metrics-row.tsx +106 -0
  430. package/src/components/shared/outcome-banner.tsx +56 -0
  431. package/src/components/shared/progress-bar.tsx +42 -0
  432. package/src/components/shared/session-pill.tsx +69 -0
  433. package/src/components/shared/settings-modal.tsx +509 -0
  434. package/src/components/shared/shortcuts-help.tsx +113 -0
  435. package/src/components/shared/status-badge.tsx +110 -0
  436. package/src/components/shared/theme-provider.tsx +46 -0
  437. package/src/components/shared/truncated-id.tsx +51 -0
  438. package/src/components/ui/.gitkeep +0 -0
  439. package/src/components/ui/__tests__/accordion.test.tsx +96 -0
  440. package/src/components/ui/__tests__/badge.test.tsx +69 -0
  441. package/src/components/ui/__tests__/button.test.tsx +113 -0
  442. package/src/components/ui/__tests__/tabs.test.tsx +75 -0
  443. package/src/components/ui/__tests__/tooltip.test.tsx +90 -0
  444. package/src/components/ui/accordion.tsx +61 -0
  445. package/src/components/ui/badge.tsx +25 -0
  446. package/src/components/ui/button.tsx +40 -0
  447. package/src/components/ui/card.tsx +21 -0
  448. package/src/components/ui/scroll-area.tsx +35 -0
  449. package/src/components/ui/separator.tsx +24 -0
  450. package/src/components/ui/tabs.tsx +64 -0
  451. package/src/components/ui/tooltip.tsx +37 -0
  452. package/src/hooks/.gitkeep +0 -0
  453. package/src/hooks/__tests__/use-animated-number.test.ts +184 -0
  454. package/src/hooks/__tests__/use-batched-updates.test.ts +315 -0
  455. package/src/hooks/__tests__/use-event-stream.test.ts +243 -0
  456. package/src/hooks/__tests__/use-keyboard.test.ts +217 -0
  457. package/src/hooks/__tests__/use-notifications.test.ts +230 -0
  458. package/src/hooks/__tests__/use-polling.test.ts +274 -0
  459. package/src/hooks/__tests__/use-project-runs.test.ts +163 -0
  460. package/src/hooks/__tests__/use-projects.test.ts +248 -0
  461. package/src/hooks/__tests__/use-run-dashboard.test.ts +168 -0
  462. package/src/hooks/__tests__/use-run-detail.test.ts +273 -0
  463. package/src/hooks/__tests__/use-smart-polling.test.ts +305 -0
  464. package/src/hooks/use-animated-number.ts +87 -0
  465. package/src/hooks/use-batched-updates.ts +150 -0
  466. package/src/hooks/use-event-stream.ts +150 -0
  467. package/src/hooks/use-keyboard.ts +45 -0
  468. package/src/hooks/use-notifications.ts +82 -0
  469. package/src/hooks/use-persisted-state.ts +60 -0
  470. package/src/hooks/use-polling.ts +60 -0
  471. package/src/hooks/use-project-runs.ts +51 -0
  472. package/src/hooks/use-projects.ts +26 -0
  473. package/src/hooks/use-run-dashboard.ts +207 -0
  474. package/src/hooks/use-run-detail.ts +77 -0
  475. package/src/hooks/use-smart-polling.ts +144 -0
  476. package/src/lib/.gitkeep +0 -0
  477. package/src/lib/__tests__/cn.test.ts +69 -0
  478. package/src/lib/__tests__/config-loader.test.ts +210 -0
  479. package/src/lib/__tests__/config.test.ts +561 -0
  480. package/src/lib/__tests__/error-handler.test.ts +143 -0
  481. package/src/lib/__tests__/fetcher.test.ts +517 -0
  482. package/src/lib/__tests__/global-registry.test.ts +214 -0
  483. package/src/lib/__tests__/parser.test.ts +1532 -0
  484. package/src/lib/__tests__/path-resolver.test.ts +112 -0
  485. package/src/lib/__tests__/run-cache.test.ts +591 -0
  486. package/src/lib/__tests__/server-init.test.ts +512 -0
  487. package/src/lib/__tests__/source-discovery.test.ts +246 -0
  488. package/src/lib/__tests__/utils.test.ts +160 -0
  489. package/src/lib/__tests__/watcher.test.ts +227 -0
  490. package/src/lib/cn.ts +6 -0
  491. package/src/lib/config-loader.ts +195 -0
  492. package/src/lib/config.ts +20 -0
  493. package/src/lib/error-handler.ts +76 -0
  494. package/src/lib/fetcher.ts +394 -0
  495. package/src/lib/global-registry.ts +117 -0
  496. package/src/lib/parser.ts +794 -0
  497. package/src/lib/path-resolver.ts +16 -0
  498. package/src/lib/run-cache.ts +404 -0
  499. package/src/lib/server-init.ts +226 -0
  500. package/src/lib/services/__tests__/run-query-service.test.ts +819 -0
  501. package/src/lib/services/run-query-service.ts +286 -0
  502. package/src/lib/source-discovery.ts +216 -0
  503. package/src/lib/utils.ts +103 -0
  504. package/src/lib/watcher.ts +265 -0
  505. package/src/test/fixtures.ts +269 -0
  506. package/src/test/mocks/handlers.ts +110 -0
  507. package/src/test/mocks/server.ts +17 -0
  508. package/src/test/setup.ts +200 -0
  509. package/src/test/test-utils.tsx +36 -0
  510. package/src/types/.gitkeep +0 -0
  511. package/src/types/breakpoint.ts +17 -0
  512. package/src/types/index.ts +214 -0
  513. package/tsconfig.json +50 -0
@@ -0,0 +1,100 @@
1
+ "use client";
2
+ import { ArrowUpDown, Clock } from "lucide-react";
3
+ import { cn } from "@/lib/cn";
4
+ import type { DashboardSortMode, DashboardStatusFilter } from "@/hooks/use-run-dashboard";
5
+
6
+ const filters: { label: string; value: DashboardStatusFilter }[] = [
7
+ { label: "All", value: "all" },
8
+ { label: "Running", value: "waiting" },
9
+ { label: "Stale", value: "stale" },
10
+ { label: "Completed", value: "completed" },
11
+ { label: "Failed", value: "failed" },
12
+ ];
13
+
14
+ export interface RunFilterBarProps {
15
+ statusFilter: DashboardStatusFilter;
16
+ onStatusFilterChange: (value: DashboardStatusFilter) => void;
17
+ filterCounts: Record<DashboardStatusFilter, number>;
18
+ sortMode: DashboardSortMode;
19
+ onSortModeToggle: () => void;
20
+ filteredProjectCount: number;
21
+ }
22
+
23
+ export function RunFilterBar({
24
+ statusFilter,
25
+ onStatusFilterChange,
26
+ filterCounts,
27
+ sortMode,
28
+ onSortModeToggle,
29
+ filteredProjectCount,
30
+ }: RunFilterBarProps) {
31
+ return (
32
+ <div className="mb-5">
33
+ <div data-testid="filter-bar" className="flex items-center gap-1">
34
+ {filters.map((f) => {
35
+ const count = filterCounts[f.value] ?? 0;
36
+ // Hide Stale filter pill when there are no stale runs
37
+ if (f.value === "stale" && count === 0) return null;
38
+ return (
39
+ <button
40
+ key={f.value}
41
+ data-testid={`filter-pill-${f.value}`}
42
+ aria-pressed={statusFilter === f.value}
43
+ onClick={() => onStatusFilterChange(f.value)}
44
+ className={cn(
45
+ "rounded-md px-3 py-1.5 min-h-[44px] text-xs font-medium transition-all inline-flex items-center gap-1.5",
46
+ statusFilter === f.value
47
+ ? f.value === "stale"
48
+ ? "bg-zinc-500/10 text-zinc-500"
49
+ : "bg-primary/10 text-primary shadow-neon-glow-primary-xs"
50
+ : "text-foreground-muted hover:text-foreground-secondary hover:bg-background-secondary"
51
+ )}
52
+ >
53
+ {f.label}
54
+ {count > 0 && (
55
+ <span className={cn(
56
+ "rounded-full px-1.5 py-px text-xs leading-tight font-semibold tabular-nums",
57
+ statusFilter === f.value
58
+ ? f.value === "stale"
59
+ ? "bg-zinc-500/20 text-zinc-500"
60
+ : "bg-primary/20 text-primary"
61
+ : "bg-background-secondary text-foreground-muted"
62
+ )}>
63
+ {count}
64
+ </span>
65
+ )}
66
+ </button>
67
+ );
68
+ })}
69
+ {/* Sort toggle + Project count */}
70
+ <div className="ml-auto flex items-center gap-2">
71
+ <button
72
+ data-testid="sort-toggle"
73
+ onClick={onSortModeToggle}
74
+ className={cn(
75
+ "rounded-md px-2.5 py-1.5 min-h-[44px] text-xs font-medium inline-flex items-center gap-1.5",
76
+ "transition-all duration-200 ease-in-out",
77
+ sortMode === "status"
78
+ ? "bg-warning/10 border border-warning/30 text-warning hover:bg-warning/15 hover:border-warning/40 shadow-sm"
79
+ : "bg-primary/10 border border-primary/30 text-primary hover:bg-primary/15 hover:border-primary/40 shadow-sm"
80
+ )}
81
+ title={sortMode === "status"
82
+ ? "Currently sorting by status priority (active first, then failed, then completed). Click to switch to chronological activity view."
83
+ : "Currently sorting by most recent activity (newest updates first). Click to switch to status-grouped view."
84
+ }
85
+ >
86
+ {sortMode === "status" ? (
87
+ <ArrowUpDown className="h-3 w-3 transition-transform duration-200" />
88
+ ) : (
89
+ <Clock className="h-3 w-3 transition-transform duration-200" />
90
+ )}
91
+ {sortMode === "status" ? "By Status" : "By Activity"}
92
+ </button>
93
+ <span data-testid="project-count" className="text-xs text-foreground-muted tabular-nums">
94
+ {filteredProjectCount} project{filteredProjectCount !== 1 ? "s" : ""}
95
+ </span>
96
+ </div>
97
+ </div>
98
+ </div>
99
+ );
100
+ }
@@ -0,0 +1,77 @@
1
+ "use client";
2
+ import { useState } from "react";
3
+ import { RunCard } from "./run-card";
4
+ import { VirtualizedRunList } from "./virtualized-run-list";
5
+ import { ProjectSection } from "./project-section";
6
+ import { EmptyState } from "@/components/shared/empty-state";
7
+ import type { Run } from "@/types";
8
+
9
+ interface RunListProps {
10
+ runs: Run[];
11
+ selectedIndex?: number;
12
+ groupByProject?: boolean;
13
+ }
14
+
15
+ export function RunList({ runs, selectedIndex, groupByProject = false }: RunListProps) {
16
+ const [pageSize] = useState(10);
17
+ const [currentPage, setCurrentPage] = useState(0);
18
+
19
+ if (runs.length === 0) {
20
+ return <EmptyState />;
21
+ }
22
+
23
+ if (groupByProject) {
24
+ // Group runs by projectName
25
+ const grouped = runs.reduce((acc, run) => {
26
+ const project = run.projectName || "Unknown Project";
27
+ if (!acc[project]) {
28
+ acc[project] = [];
29
+ }
30
+ acc[project].push(run);
31
+ return acc;
32
+ }, {} as Record<string, Run[]>);
33
+
34
+ const projectEntries = Object.entries(grouped).sort(([a], [b]) => a.localeCompare(b));
35
+
36
+ return (
37
+ <div className="flex flex-col gap-3">
38
+ {projectEntries.map(([projectName, projectRuns]) => {
39
+ const hasActiveRuns = projectRuns.some(r => r.status === "waiting" || r.status === "pending");
40
+ return (
41
+ <ProjectSection
42
+ key={projectName}
43
+ projectName={projectName}
44
+ runs={projectRuns}
45
+ defaultExpanded={hasActiveRuns}
46
+ />
47
+ );
48
+ })}
49
+ </div>
50
+ );
51
+ }
52
+
53
+ // Flat list with pagination + virtualization
54
+ const _totalPages = Math.ceil(runs.length / pageSize);
55
+ const displayedRuns = runs.slice(0, (currentPage + 1) * pageSize);
56
+ const hasMore = displayedRuns.length < runs.length;
57
+
58
+ return (
59
+ <div className="flex flex-col gap-2">
60
+ <VirtualizedRunList
61
+ runs={displayedRuns}
62
+ maxHeight={800}
63
+ renderItem={(run, i) => (
64
+ <RunCard run={run} selected={i === selectedIndex} />
65
+ )}
66
+ />
67
+ {hasMore && (
68
+ <button
69
+ onClick={() => setCurrentPage(currentPage + 1)}
70
+ className="mt-2 px-4 py-2 text-sm text-foreground-secondary hover:text-foreground hover:bg-background-secondary transition-colors rounded-md"
71
+ >
72
+ Show more ({runs.length - displayedRuns.length} remaining)
73
+ </button>
74
+ )}
75
+ </div>
76
+ );
77
+ }
@@ -0,0 +1,69 @@
1
+ "use client";
2
+ import { Search, FolderOpen } from "lucide-react";
3
+ import { cn } from "@/lib/cn";
4
+ import type { RunStatus } from "@/types";
5
+
6
+ const filters: { label: string; value: RunStatus | "all" }[] = [
7
+ { label: "All", value: "all" },
8
+ { label: "Running", value: "waiting" },
9
+ { label: "Completed", value: "completed" },
10
+ { label: "Failed", value: "failed" },
11
+ ];
12
+
13
+ interface SearchFilterProps {
14
+ search: string;
15
+ onSearchChange: (value: string) => void;
16
+ statusFilter: RunStatus | "all";
17
+ onStatusFilterChange: (value: RunStatus | "all") => void;
18
+ searchRef?: React.RefObject<HTMLInputElement>;
19
+ groupByProject?: boolean;
20
+ onGroupByProjectChange?: (value: boolean) => void;
21
+ }
22
+
23
+ export function SearchFilter({ search, onSearchChange, statusFilter, onStatusFilterChange, searchRef, groupByProject = false, onGroupByProjectChange }: SearchFilterProps) {
24
+ return (
25
+ <div className="flex items-center gap-3">
26
+ <div className="relative flex-1 max-w-sm">
27
+ <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-foreground-muted" />
28
+ <input
29
+ ref={searchRef}
30
+ type="text"
31
+ placeholder="Search runs..."
32
+ value={search}
33
+ onChange={(e) => onSearchChange(e.target.value)}
34
+ className="h-9 w-full rounded-md border border-border bg-background-secondary pl-9 pr-3 text-sm text-foreground placeholder:text-foreground-muted focus:outline-none focus:ring-2 focus:ring-primary/40 focus:border-primary/30 focus:shadow-neon-glow-primary-focus transition-all"
35
+ />
36
+ </div>
37
+ <div className="flex items-center gap-1">
38
+ {filters.map((f) => (
39
+ <button
40
+ key={f.value}
41
+ onClick={() => onStatusFilterChange(f.value)}
42
+ className={cn(
43
+ "rounded-md px-3 py-1.5 min-h-[44px] text-xs font-medium transition-all",
44
+ statusFilter === f.value
45
+ ? "bg-primary/15 text-primary shadow-neon-glow-primary-ring"
46
+ : "text-foreground-muted hover:text-foreground-secondary hover:bg-background-secondary"
47
+ )}
48
+ >
49
+ {f.label}
50
+ </button>
51
+ ))}
52
+ </div>
53
+ {onGroupByProjectChange && (
54
+ <button
55
+ onClick={() => onGroupByProjectChange(!groupByProject)}
56
+ className={cn(
57
+ "flex items-center gap-1.5 rounded-md px-3 py-1.5 min-h-[44px] text-xs font-medium transition-all",
58
+ groupByProject
59
+ ? "bg-primary/15 text-primary shadow-neon-glow-primary-ring"
60
+ : "text-foreground-muted hover:text-foreground-secondary hover:bg-background-secondary"
61
+ )}
62
+ >
63
+ <FolderOpen className="h-3.5 w-3.5" />
64
+ Group
65
+ </button>
66
+ )}
67
+ </div>
68
+ );
69
+ }
@@ -0,0 +1,130 @@
1
+ "use client";
2
+ import { useRef, useMemo, useCallback } from "react";
3
+ import { useVirtualizer } from "@tanstack/react-virtual";
4
+ import { RunCard } from "./run-card";
5
+ import type { Run } from "@/types";
6
+
7
+ /** Estimated height of a single RunCard in pixels (used for initial measurement) */
8
+ const ESTIMATED_CARD_HEIGHT = 140;
9
+
10
+ /** Number of items to render outside the visible area for smooth scrolling */
11
+ const OVERSCAN_COUNT = 3;
12
+
13
+ /** Threshold below which we skip virtualization (overhead not worthwhile) */
14
+ const VIRTUALIZATION_THRESHOLD = 15;
15
+
16
+ interface VirtualizedRunListProps {
17
+ /** Runs to display — must be pre-sorted by caller */
18
+ runs: Run[];
19
+ /** Optional className applied to the scroll container */
20
+ className?: string;
21
+ /** Maximum height for the scroll container. Defaults to 600px. */
22
+ maxHeight?: number;
23
+ /** Optional render wrapper per-item (e.g. to add time overlays in activity mode) */
24
+ renderItem?: (run: Run, index: number) => React.ReactNode;
25
+ }
26
+
27
+ /**
28
+ * Virtualized run card list using @tanstack/react-virtual.
29
+ *
30
+ * - Only renders visible cards plus a small overscan buffer.
31
+ * - Uses stable sort keys (run.runId) to prevent reordering flash.
32
+ * - Preserves scroll position when new runs are prepended by adjusting
33
+ * the scroll offset.
34
+ * - Falls back to a simple flat list when the item count is below the
35
+ * VIRTUALIZATION_THRESHOLD to avoid unnecessary overhead.
36
+ */
37
+ export function VirtualizedRunList({
38
+ runs,
39
+ className,
40
+ maxHeight = 600,
41
+ renderItem,
42
+ }: VirtualizedRunListProps) {
43
+ const parentRef = useRef<HTMLDivElement>(null);
44
+
45
+ // Memoize the runs array to prevent unnecessary virtualizer recalculations.
46
+ // The caller provides runs pre-sorted (by status or activity), and we use
47
+ // runId as the stable key (via getItemKey) to prevent reordering flash
48
+ // during rapid updates. This ensures React can reconcile virtual items
49
+ // by identity rather than by position.
50
+ const stableSortedRuns = useMemo(() => runs, [runs]);
51
+
52
+ // Map of runId -> index for O(1) lookup during key extraction.
53
+ const getItemKey = useCallback(
54
+ (index: number) => stableSortedRuns[index]?.runId ?? index,
55
+ [stableSortedRuns]
56
+ );
57
+
58
+ const virtualizer = useVirtualizer({
59
+ count: stableSortedRuns.length,
60
+ getScrollElement: () => parentRef.current,
61
+ estimateSize: () => ESTIMATED_CARD_HEIGHT,
62
+ overscan: OVERSCAN_COUNT,
63
+ getItemKey,
64
+ });
65
+
66
+ // For small lists, skip virtualization entirely to avoid overhead.
67
+ if (stableSortedRuns.length < VIRTUALIZATION_THRESHOLD) {
68
+ return (
69
+ <div className={className} data-testid="run-list-flat">
70
+ <div className="flex flex-col gap-2">
71
+ {stableSortedRuns.map((run, index) =>
72
+ renderItem ? (
73
+ <div key={run.runId}>{renderItem(run, index)}</div>
74
+ ) : (
75
+ <RunCard key={run.runId} run={run} />
76
+ )
77
+ )}
78
+ </div>
79
+ </div>
80
+ );
81
+ }
82
+
83
+ const virtualItems = virtualizer.getVirtualItems();
84
+
85
+ return (
86
+ <div
87
+ ref={parentRef}
88
+ className={className}
89
+ data-testid="run-list-virtualized"
90
+ style={{
91
+ maxHeight,
92
+ overflow: "auto",
93
+ // Contain layout for paint performance
94
+ contain: "strict",
95
+ }}
96
+ >
97
+ <div
98
+ style={{
99
+ height: `${virtualizer.getTotalSize()}px`,
100
+ width: "100%",
101
+ position: "relative",
102
+ }}
103
+ >
104
+ {virtualItems.map((virtualRow) => {
105
+ const run = stableSortedRuns[virtualRow.index];
106
+ if (!run) return null;
107
+
108
+ return (
109
+ <div
110
+ key={virtualRow.key}
111
+ data-index={virtualRow.index}
112
+ ref={virtualizer.measureElement}
113
+ style={{
114
+ position: "absolute",
115
+ top: 0,
116
+ left: 0,
117
+ width: "100%",
118
+ transform: `translateY(${virtualRow.start}px)`,
119
+ }}
120
+ >
121
+ <div style={{ paddingBottom: 8 }}>
122
+ {renderItem ? renderItem(run, virtualRow.index) : <RunCard run={run} />}
123
+ </div>
124
+ </div>
125
+ );
126
+ })}
127
+ </div>
128
+ </div>
129
+ );
130
+ }
File without changes
@@ -0,0 +1,236 @@
1
+ import React from 'react';
2
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
3
+ import { render, screen, setupUser } from '@/test/test-utils';
4
+ import { AgentPanel } from '../agent-panel';
5
+ import { createMockTaskDetail } from '@/test/fixtures';
6
+
7
+ // Mock clipboard
8
+ beforeEach(() => {
9
+ Object.defineProperty(navigator, 'clipboard', {
10
+ writable: true,
11
+ configurable: true,
12
+ value: {
13
+ writeText: vi.fn().mockResolvedValue(undefined),
14
+ readText: vi.fn().mockResolvedValue(''),
15
+ write: vi.fn().mockResolvedValue(undefined),
16
+ read: vi.fn().mockResolvedValue([]),
17
+ addEventListener: vi.fn(),
18
+ removeEventListener: vi.fn(),
19
+ dispatchEvent: vi.fn().mockReturnValue(false),
20
+ },
21
+ });
22
+ });
23
+
24
+ describe('AgentPanel', () => {
25
+ it('renders null task state with placeholder message', () => {
26
+ render(<AgentPanel task={null} />);
27
+ expect(screen.getByText('Select a task to view details')).toBeInTheDocument();
28
+ });
29
+
30
+ it('renders task title from task.title', () => {
31
+ const task = createMockTaskDetail({ title: 'My Cool Task' });
32
+ render(<AgentPanel task={task} />);
33
+ expect(screen.getByText('My Cool Task')).toBeInTheDocument();
34
+ });
35
+
36
+ it('falls back to task.label when title is empty', () => {
37
+ const task = createMockTaskDetail({ title: '', label: 'label-fallback' });
38
+ render(<AgentPanel task={task} />);
39
+ expect(screen.getByText('label-fallback')).toBeInTheDocument();
40
+ });
41
+
42
+ it('falls back to effectId when title and label are empty', () => {
43
+ const task = createMockTaskDetail({ effectId: 'eff-123', title: '', label: '' });
44
+ render(<AgentPanel task={task} />);
45
+ expect(screen.getByText('eff-123')).toBeInTheDocument();
46
+ });
47
+
48
+ it('renders kind badge and status badge', () => {
49
+ const task = createMockTaskDetail({ kind: 'agent', status: 'resolved' });
50
+ render(<AgentPanel task={task} />);
51
+ // KindBadge renders the kind text uppercased
52
+ expect(screen.getByText('agent')).toBeInTheDocument();
53
+ // StatusBadge renders "Done" for resolved
54
+ expect(screen.getByText('Done')).toBeInTheDocument();
55
+ });
56
+
57
+ it('renders invocationKey via TruncatedId', () => {
58
+ const task = createMockTaskDetail({ invocationKey: 'inv-abcdef1234' });
59
+ render(<AgentPanel task={task} />);
60
+ // TruncatedId renders last 4 chars with "..." prefix
61
+ expect(screen.getByText('...1234')).toBeInTheDocument();
62
+ });
63
+
64
+ it('renders description from input.description when no agent prompt', () => {
65
+ const task = createMockTaskDetail({
66
+ input: { description: 'This is a task description' },
67
+ taskDef: {},
68
+ });
69
+ render(<AgentPanel task={task} />);
70
+ expect(screen.getByText('Description')).toBeInTheDocument();
71
+ expect(screen.getByText('This is a task description')).toBeInTheDocument();
72
+ });
73
+
74
+ it('truncates long descriptions at 500 chars', () => {
75
+ const longDesc = 'A'.repeat(600);
76
+ const task = createMockTaskDetail({
77
+ input: { description: longDesc },
78
+ taskDef: {},
79
+ });
80
+ render(<AgentPanel task={task} />);
81
+ expect(screen.getByText('Description')).toBeInTheDocument();
82
+ const descEl = screen.getByText(/^A+\.\.\.$/);
83
+ expect(descEl.textContent).toHaveLength(503); // 500 chars + "..."
84
+ });
85
+
86
+ it('does not render description when agent prompt is present', () => {
87
+ const task = createMockTaskDetail({
88
+ input: { description: 'hidden description' },
89
+ taskDef: {
90
+ agent: {
91
+ prompt: {
92
+ role: 'Developer',
93
+ task: 'Build a thing',
94
+ instructions: ['Step 1'],
95
+ },
96
+ },
97
+ },
98
+ });
99
+ render(<AgentPanel task={task} />);
100
+ expect(screen.queryByText('Description')).not.toBeInTheDocument();
101
+ expect(screen.queryByText('hidden description')).not.toBeInTheDocument();
102
+ });
103
+
104
+ it('renders agent prompt role, task, and instructions', () => {
105
+ const task = createMockTaskDetail({
106
+ taskDef: {
107
+ agent: {
108
+ prompt: {
109
+ role: 'Senior Engineer',
110
+ task: 'Refactor the module',
111
+ instructions: ['Read the code', 'Write tests', 'Submit PR'],
112
+ },
113
+ },
114
+ },
115
+ });
116
+ render(<AgentPanel task={task} />);
117
+ expect(screen.getByText('Role')).toBeInTheDocument();
118
+ expect(screen.getByText('Senior Engineer')).toBeInTheDocument();
119
+ expect(screen.getByText('Task')).toBeInTheDocument();
120
+ expect(screen.getByText('Refactor the module')).toBeInTheDocument();
121
+ expect(screen.getByText('Instructions')).toBeInTheDocument();
122
+ expect(screen.getByText('Read the code')).toBeInTheDocument();
123
+ expect(screen.getByText('Write tests')).toBeInTheDocument();
124
+ expect(screen.getByText('Submit PR')).toBeInTheDocument();
125
+ });
126
+
127
+ it('renders numbered instructions', () => {
128
+ const task = createMockTaskDetail({
129
+ taskDef: {
130
+ agent: {
131
+ prompt: {
132
+ role: 'Dev',
133
+ task: 'Do work',
134
+ instructions: ['First', 'Second'],
135
+ },
136
+ },
137
+ },
138
+ });
139
+ render(<AgentPanel task={task} />);
140
+ expect(screen.getByText('1')).toBeInTheDocument();
141
+ expect(screen.getByText('2')).toBeInTheDocument();
142
+ });
143
+
144
+ it('renders result status badge when result has status', () => {
145
+ const task = createMockTaskDetail({
146
+ result: { status: 'ok', output: 'done' },
147
+ });
148
+ render(<AgentPanel task={task} />);
149
+ expect(screen.getByText('Result')).toBeInTheDocument();
150
+ // StatusBadge for "resolved" renders "Done"
151
+ expect(screen.getAllByText('Done').length).toBeGreaterThanOrEqual(1);
152
+ });
153
+
154
+ it('renders error section when resultError is present', () => {
155
+ const task = createMockTaskDetail({
156
+ result: { error: { name: 'TypeError', message: 'null is not an object' } },
157
+ });
158
+ render(<AgentPanel task={task} />);
159
+ expect(screen.getByText('Error')).toBeInTheDocument();
160
+ expect(screen.getByText('TypeError: null is not an object')).toBeInTheDocument();
161
+ });
162
+
163
+ it('renders error section from task.error', () => {
164
+ const task = createMockTaskDetail({
165
+ error: { name: 'RuntimeError', message: 'Something broke', stack: 'at line 42' },
166
+ result: undefined,
167
+ });
168
+ render(<AgentPanel task={task} />);
169
+ expect(screen.getByText('Error')).toBeInTheDocument();
170
+ expect(screen.getByText('RuntimeError: Something broke')).toBeInTheDocument();
171
+ });
172
+
173
+ it('expands stack trace on click', async () => {
174
+ const user = setupUser();
175
+ const task = createMockTaskDetail({
176
+ error: { name: 'Err', message: 'Msg', stack: 'Error at file.ts:10\n at run()' },
177
+ result: undefined,
178
+ });
179
+ render(<AgentPanel task={task} />);
180
+
181
+ expect(screen.queryByText('Error at file.ts:10')).not.toBeInTheDocument();
182
+
183
+ const stackBtn = screen.getByText('Stack Trace');
184
+ await user.click(stackBtn);
185
+
186
+ expect(screen.getByText(/Error at file\.ts:10/)).toBeInTheDocument();
187
+ });
188
+
189
+ it('renders result output section', () => {
190
+ const task = createMockTaskDetail({
191
+ result: { result: { value: 42 } },
192
+ });
193
+ render(<AgentPanel task={task} />);
194
+ expect(screen.getByText('Output')).toBeInTheDocument();
195
+ });
196
+
197
+ it('shows expand button for long output and expands on click', async () => {
198
+ const user = setupUser();
199
+ const longValue = 'x'.repeat(600);
200
+ const task = createMockTaskDetail({
201
+ result: { result: longValue },
202
+ });
203
+ render(<AgentPanel task={task} />);
204
+
205
+ // Should show truncated + expand button
206
+ const expandBtn = screen.getByText(/Expand/);
207
+ expect(expandBtn).toBeInTheDocument();
208
+
209
+ await user.click(expandBtn);
210
+
211
+ // After expanding, collapse button should appear
212
+ expect(screen.getByText('Collapse')).toBeInTheDocument();
213
+ });
214
+
215
+ it('renders copy button for error section', () => {
216
+ const task = createMockTaskDetail({
217
+ error: { name: 'Err', message: 'Broken' },
218
+ result: undefined,
219
+ });
220
+ render(<AgentPanel task={task} />);
221
+ const copyButtons = screen.getAllByTitle('Copy to clipboard');
222
+ expect(copyButtons.length).toBeGreaterThanOrEqual(1);
223
+ });
224
+
225
+ it('renders with minimal task data (no input, no result, no error)', () => {
226
+ const task = createMockTaskDetail({
227
+ input: undefined,
228
+ result: undefined,
229
+ error: undefined,
230
+ taskDef: undefined,
231
+ });
232
+ render(<AgentPanel task={task} />);
233
+ // Should still render the title
234
+ expect(screen.getByText(task.title)).toBeInTheDocument();
235
+ });
236
+ });