@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,246 @@
1
+ "use client";
2
+ import {
3
+ FolderOpen,
4
+ Activity,
5
+ Eye,
6
+ Clock,
7
+ History,
8
+ ChevronDown,
9
+ ChevronUp,
10
+ } from "lucide-react";
11
+ import { cn } from "@/lib/cn";
12
+ import { ErrorBoundary } from "@/components/shared/error-boundary";
13
+ import { ProjectHealthCard } from "./project-health-card";
14
+ import type { ProjectSummary, RunStatus } from "@/types";
15
+ import type { DashboardSortMode, DashboardStatusFilter } from "@/hooks/use-run-dashboard";
16
+
17
+ // ---------------------------------------------------------------------------
18
+ // Loading skeleton
19
+ // ---------------------------------------------------------------------------
20
+
21
+ function LoadingSkeleton() {
22
+ return (
23
+ <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 items-start">
24
+ {[1, 2, 3].map((i) => (
25
+ <div key={i} className="rounded-lg border border-border bg-card p-4 animate-pulse">
26
+ <div className="flex items-center gap-2 mb-3">
27
+ <div className="h-2.5 w-2.5 rounded-full bg-foreground-muted/20" />
28
+ <div className="h-4 w-32 rounded bg-foreground-muted/10" />
29
+ </div>
30
+ <div className="h-1.5 w-full rounded-full bg-foreground-muted/10 mb-3" />
31
+ <div className="flex items-center gap-3">
32
+ <div className="h-5 w-16 rounded-full bg-foreground-muted/10" />
33
+ <div className="h-5 w-16 rounded-full bg-foreground-muted/10" />
34
+ <div className="h-3 w-12 rounded bg-foreground-muted/10" />
35
+ </div>
36
+ </div>
37
+ ))}
38
+ </div>
39
+ );
40
+ }
41
+
42
+ // ---------------------------------------------------------------------------
43
+ // Error banner
44
+ // ---------------------------------------------------------------------------
45
+
46
+ function ErrorBanner({ error }: { error: string }) {
47
+ return (
48
+ <div data-testid="error-banner" className="rounded-lg border border-error/20 bg-error-muted p-4 text-sm text-error">
49
+ Failed to load projects: {error}
50
+ </div>
51
+ );
52
+ }
53
+
54
+ // ---------------------------------------------------------------------------
55
+ // Empty state (no projects matching filter)
56
+ // ---------------------------------------------------------------------------
57
+
58
+ function NoProjectsState() {
59
+ return (
60
+ <div data-testid="empty-state" className="text-center py-16">
61
+ <FolderOpen className="h-10 w-10 text-foreground-muted/30 mx-auto mb-3" />
62
+ <p className="text-sm text-foreground-muted mb-1">No projects found</p>
63
+ <p className="text-xs text-foreground-muted/60">
64
+ Configure watch sources in{" "}
65
+ <button
66
+ onClick={() => window.dispatchEvent(new CustomEvent("open-settings"))}
67
+ className="text-primary hover:underline"
68
+ >
69
+ Settings
70
+ </button>{" "}
71
+ or edit <span className="font-mono">~/.a5c/observer.json</span>
72
+ </p>
73
+ </div>
74
+ );
75
+ }
76
+
77
+ // ---------------------------------------------------------------------------
78
+ // Idle empty state (no active and no history runs)
79
+ // ---------------------------------------------------------------------------
80
+
81
+ function IdleEmptyState() {
82
+ return (
83
+ <div data-testid="idle-empty-state" className="text-center py-16">
84
+ <Eye className="h-10 w-10 text-foreground-muted/30 mx-auto mb-3" />
85
+ <p className="text-sm text-foreground-muted mb-1">All quiet — no active orchestration runs</p>
86
+ <p className="text-xs text-foreground-muted/60">
87
+ Runs will appear here when babysitter processes are started
88
+ </p>
89
+ </div>
90
+ );
91
+ }
92
+
93
+ // ---------------------------------------------------------------------------
94
+ // ProjectListView (public)
95
+ // ---------------------------------------------------------------------------
96
+
97
+ export interface ProjectListViewProps {
98
+ loading: boolean;
99
+ error: string | null | undefined;
100
+ filteredProjects: ProjectSummary[];
101
+ activeProjects: ProjectSummary[];
102
+ historyProjects: ProjectSummary[];
103
+ statusFilter: DashboardStatusFilter;
104
+ sortMode: DashboardSortMode;
105
+ cardStatusFilter: RunStatus | "all";
106
+ historyCollapsed: boolean;
107
+ onHistoryCollapsedChange: (value: boolean | ((prev: boolean) => boolean)) => void;
108
+ onHideProject?: (projectName: string) => void;
109
+ }
110
+
111
+ export function ProjectListView({
112
+ loading,
113
+ error,
114
+ filteredProjects,
115
+ activeProjects,
116
+ historyProjects,
117
+ statusFilter,
118
+ sortMode,
119
+ cardStatusFilter,
120
+ historyCollapsed,
121
+ onHistoryCollapsedChange,
122
+ onHideProject,
123
+ }: ProjectListViewProps) {
124
+ if (loading) {
125
+ return <LoadingSkeleton />;
126
+ }
127
+
128
+ if (error) {
129
+ return <ErrorBanner error={error} />;
130
+ }
131
+
132
+ if (filteredProjects.length === 0) {
133
+ return <NoProjectsState />;
134
+ }
135
+
136
+ return (
137
+ <div className="flex flex-col gap-8">
138
+ {/* Idle empty state: no active and no history runs at all */}
139
+ {activeProjects.length === 0 && historyProjects.length === 0 && (
140
+ <IdleEmptyState />
141
+ )}
142
+
143
+ {/* Idle with history: no active/recent runs but has history */}
144
+ {activeProjects.length === 0 && historyProjects.length > 0 && (statusFilter === "all" || statusFilter === "stale") && (
145
+ <div data-testid="idle-with-history-banner" className="flex items-center gap-2 px-3 py-2 rounded-md bg-background-secondary/50 border border-border w-fit">
146
+ <Activity className="h-3.5 w-3.5 text-foreground-muted/50" />
147
+ <span className="text-xs text-foreground-muted">
148
+ {sortMode === "activity" ? "No activity in the last 24 hours" : "No runs in progress"}
149
+ </span>
150
+ </div>
151
+ )}
152
+
153
+ {/* Active / Recent section */}
154
+ {activeProjects.length > 0 && (statusFilter === "all" || statusFilter === "stale" || statusFilter === "waiting") && (
155
+ <ErrorBoundary section="Active Runs">
156
+ <section data-testid="active-runs-section">
157
+ <div className="flex items-center gap-2 mb-3">
158
+ {sortMode === "activity" ? (
159
+ <Clock className="h-4 w-4 text-primary" />
160
+ ) : (
161
+ <Activity className="h-4 w-4 text-warning animate-pulse-dot" />
162
+ )}
163
+ <h2 className="text-sm font-semibold text-foreground">
164
+ {sortMode === "activity" ? "Recent Activity" : "In Progress"}
165
+ </h2>
166
+ <span className={cn(
167
+ "rounded-full px-2 py-px text-xs font-semibold tabular-nums",
168
+ sortMode === "activity"
169
+ ? "bg-primary/10 border border-primary/20 text-primary"
170
+ : "bg-warning/10 border border-warning/20 text-warning"
171
+ )}>
172
+ {activeProjects.length}
173
+ </span>
174
+ </div>
175
+ <div data-testid="project-grid-active" className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 items-start">
176
+ {activeProjects.map((project) => (
177
+ <ProjectHealthCard
178
+ key={project.projectName}
179
+ project={project}
180
+ statusFilter={cardStatusFilter}
181
+ sortMode={sortMode}
182
+ onHide={onHideProject}
183
+ />
184
+ ))}
185
+ </div>
186
+ </section>
187
+ </ErrorBoundary>
188
+ )}
189
+
190
+ {/* When filter is "completed" or "failed", show filteredProjects directly without sectioning */}
191
+ {(statusFilter === "completed" || statusFilter === "failed") && (
192
+ <ErrorBoundary section="Filtered Results">
193
+ <div data-testid="project-grid-filtered" className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 items-start">
194
+ {filteredProjects.map((project) => (
195
+ <ProjectHealthCard
196
+ key={project.projectName}
197
+ project={project}
198
+ statusFilter={cardStatusFilter}
199
+ sortMode={sortMode}
200
+ />
201
+ ))}
202
+ </div>
203
+ </ErrorBoundary>
204
+ )}
205
+
206
+ {/* History / Earlier section */}
207
+ {historyProjects.length > 0 && (statusFilter === "all" || statusFilter === "stale") && (
208
+ <ErrorBoundary section="Recent History">
209
+ <section data-testid="recent-history-section">
210
+ <button
211
+ onClick={() => onHistoryCollapsedChange((v) => !v)}
212
+ className="flex items-center gap-2 mb-3 group w-fit"
213
+ >
214
+ <History className="h-4 w-4 text-foreground-muted/70" />
215
+ <h2 className="text-sm font-semibold text-foreground-muted group-hover:text-foreground-secondary transition-colors">
216
+ {sortMode === "activity" ? "Earlier" : "Recent History"}
217
+ </h2>
218
+ <span className="rounded-full bg-background-secondary border border-border px-2 py-px text-xs font-semibold text-foreground-muted tabular-nums">
219
+ {historyProjects.length}
220
+ </span>
221
+ {historyCollapsed ? (
222
+ <ChevronDown className="h-3.5 w-3.5 text-foreground-muted/60 group-hover:text-foreground-muted transition-colors" />
223
+ ) : (
224
+ <ChevronUp className="h-3.5 w-3.5 text-foreground-muted/60 group-hover:text-foreground-muted transition-colors" />
225
+ )}
226
+ </button>
227
+ {!historyCollapsed && (
228
+ <div className="opacity-70">
229
+ <div data-testid="project-grid-history" className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 items-start">
230
+ {historyProjects.map((project) => (
231
+ <ProjectHealthCard
232
+ key={project.projectName}
233
+ project={project}
234
+ statusFilter={cardStatusFilter}
235
+ sortMode={sortMode}
236
+ />
237
+ ))}
238
+ </div>
239
+ </div>
240
+ )}
241
+ </section>
242
+ </ErrorBoundary>
243
+ )}
244
+ </div>
245
+ );
246
+ }
@@ -0,0 +1,41 @@
1
+ 'use client';
2
+ import { useState, useEffect } from 'react';
3
+ import { Search } from 'lucide-react';
4
+ import { cn } from '@/lib/cn';
5
+
6
+ interface ProjectSearchInputProps {
7
+ onSearch: (value: string) => void;
8
+ debounceMs?: number;
9
+ className?: string;
10
+ placeholder?: string;
11
+ }
12
+
13
+ export function ProjectSearchInput({
14
+ onSearch,
15
+ debounceMs = 300,
16
+ className,
17
+ placeholder = 'Filter runs...'
18
+ }: ProjectSearchInputProps) {
19
+ const [value, setValue] = useState('');
20
+
21
+ useEffect(() => {
22
+ const timer = setTimeout(() => {
23
+ onSearch(value);
24
+ }, debounceMs);
25
+
26
+ return () => clearTimeout(timer);
27
+ }, [value, debounceMs, onSearch]);
28
+
29
+ return (
30
+ <div className={cn('relative', className)}>
31
+ <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-foreground-muted" />
32
+ <input
33
+ type="text"
34
+ value={value}
35
+ onChange={(e) => setValue(e.target.value)}
36
+ placeholder={placeholder}
37
+ className="w-full rounded-md border border-border bg-background px-9 py-2 text-xs text-foreground placeholder:text-foreground-muted focus:border-primary/30 focus:outline-none focus:ring-2 focus:ring-primary/40 focus:shadow-neon-glow-primary-focus transition-all"
38
+ />
39
+ </div>
40
+ );
41
+ }
@@ -0,0 +1,73 @@
1
+ "use client";
2
+ import { cn } from "@/lib/cn";
3
+
4
+ interface ProjectSectionHeaderProps {
5
+ projectName: string;
6
+ activeRuns: number;
7
+ completedRuns: number;
8
+ failedRuns: number;
9
+ totalRuns: number;
10
+ latestUpdate?: string;
11
+ className?: string;
12
+ }
13
+
14
+ function formatRelativeTime(iso: string | undefined): string {
15
+ if (!iso) return "";
16
+ try {
17
+ const now = Date.now();
18
+ const then = new Date(iso).getTime();
19
+ const diffMs = now - then;
20
+ if (diffMs < 0) return "just now";
21
+ const diffSec = Math.floor(diffMs / 1000);
22
+ if (diffSec < 60) return `${diffSec}s ago`;
23
+ const diffMin = Math.floor(diffSec / 60);
24
+ if (diffMin < 60) return `${diffMin}m ago`;
25
+ const diffHr = Math.floor(diffMin / 60);
26
+ if (diffHr < 24) return `${diffHr}h ago`;
27
+ const diffDays = Math.floor(diffHr / 24);
28
+ return `${diffDays}d ago`;
29
+ } catch {
30
+ return "";
31
+ }
32
+ }
33
+
34
+ export function ProjectSectionHeader({
35
+ projectName,
36
+ activeRuns,
37
+ completedRuns,
38
+ failedRuns,
39
+ totalRuns,
40
+ latestUpdate,
41
+ className,
42
+ }: ProjectSectionHeaderProps) {
43
+ return (
44
+ <div className={cn("flex flex-1 items-center gap-3 min-w-0", className)}>
45
+ <span className="font-semibold text-sm text-foreground truncate border-l-2 border-primary pl-2 transition-all hover:neon-text-subtle">
46
+ {projectName}
47
+ </span>
48
+
49
+ <div className="flex items-center gap-1.5 shrink-0">
50
+ {activeRuns > 0 && (
51
+ <span className="inline-flex items-center rounded-full bg-warning-muted px-2 py-0.5 text-[11px] font-medium text-warning shadow-neon-glow-warning-xs">
52
+ {activeRuns} active
53
+ </span>
54
+ )}
55
+ {completedRuns > 0 && (
56
+ <span className="inline-flex items-center rounded-full bg-success-muted px-2 py-0.5 text-[11px] font-medium text-success">
57
+ {completedRuns} completed
58
+ </span>
59
+ )}
60
+ {failedRuns > 0 && (
61
+ <span className="inline-flex items-center rounded-full bg-error-muted px-2 py-0.5 text-[11px] font-medium text-error shadow-neon-glow-error-xs">
62
+ {failedRuns} failed
63
+ </span>
64
+ )}
65
+ </div>
66
+
67
+ <span className="ml-auto text-xs leading-tight text-foreground-muted shrink-0 tabular-nums">
68
+ {totalRuns} run{totalRuns !== 1 ? "s" : ""}
69
+ {latestUpdate && ` \u00b7 ${formatRelativeTime(latestUpdate)}`}
70
+ </span>
71
+ </div>
72
+ );
73
+ }
@@ -0,0 +1,89 @@
1
+ "use client";
2
+ import { useState, useCallback } from "react";
3
+ import { Loader2 } from "lucide-react";
4
+ import { RunCard } from "./run-card";
5
+ import { VirtualizedRunList } from "./virtualized-run-list";
6
+ import { PaginationControls } from "./pagination-controls";
7
+ import { ProjectSearchInput } from "./project-search-input";
8
+ import { useProjectRuns } from "@/hooks/use-project-runs";
9
+ import type { Run } from "@/types";
10
+
11
+ interface ProjectSectionProps {
12
+ projectName: string;
13
+ runs: Run[];
14
+ selectedIndex?: number;
15
+ defaultExpanded?: boolean;
16
+ statusFilter?: string;
17
+ enabled?: boolean;
18
+ }
19
+
20
+ const PAGE_SIZE = 10;
21
+
22
+ export function ProjectSection({
23
+ projectName,
24
+ runs: _initialRuns,
25
+ selectedIndex,
26
+ defaultExpanded: _defaultExpanded = false,
27
+ statusFilter,
28
+ enabled = true,
29
+ }: ProjectSectionProps) {
30
+ const [page, setPage] = useState(0);
31
+ const [search, setSearch] = useState("");
32
+
33
+ const { runs: fetchedRuns, totalCount, loading } = useProjectRuns(
34
+ projectName,
35
+ {
36
+ limit: PAGE_SIZE,
37
+ offset: page * PAGE_SIZE,
38
+ search,
39
+ status: statusFilter && statusFilter !== "all" ? statusFilter : undefined,
40
+ enabled,
41
+ }
42
+ );
43
+
44
+ // Use fetched runs
45
+ const displayRuns = fetchedRuns;
46
+
47
+ const handleSearch = useCallback((value: string) => {
48
+ setSearch(value);
49
+ setPage(0);
50
+ }, []);
51
+
52
+ const handlePageChange = useCallback((newPage: number) => {
53
+ setPage(newPage);
54
+ }, []);
55
+
56
+ return (
57
+ <div>
58
+ <ProjectSearchInput
59
+ onSearch={handleSearch}
60
+ placeholder="Search by run ID, process, task, or error..."
61
+ className="mb-3"
62
+ />
63
+ {loading && displayRuns.length === 0 ? (
64
+ <div className="flex items-center justify-center py-6">
65
+ <Loader2 className="h-4 w-4 animate-spin text-primary" />
66
+ </div>
67
+ ) : displayRuns.length === 0 ? (
68
+ <div className="text-xs text-foreground-muted text-center py-4">
69
+ No runs found
70
+ </div>
71
+ ) : (
72
+ <VirtualizedRunList
73
+ runs={displayRuns}
74
+ maxHeight={600}
75
+ renderItem={(run, i) => (
76
+ <RunCard run={run} selected={i === selectedIndex} />
77
+ )}
78
+ />
79
+ )}
80
+ <PaginationControls
81
+ currentPage={page}
82
+ totalItems={totalCount}
83
+ itemsPerPage={PAGE_SIZE}
84
+ onPageChange={handlePageChange}
85
+ className="mt-3"
86
+ />
87
+ </div>
88
+ );
89
+ }
@@ -0,0 +1,218 @@
1
+ "use client";
2
+ import { memo } from "react";
3
+ import Link from "next/link";
4
+ import { cn } from "@/lib/cn";
5
+ import { Card } from "@/components/ui/card";
6
+ import { StatusBadge } from "@/components/shared/status-badge";
7
+ import { SessionPill } from "@/components/shared/session-pill";
8
+ import { TruncatedId } from "@/components/shared/truncated-id";
9
+ import { ProgressBar } from "@/components/shared/progress-bar";
10
+ import { formatDuration, friendlyProcessName, formatRelativeTime } from "@/lib/utils";
11
+ import type { Run } from "@/types";
12
+ import { Clock, Layers, Hand, AlertCircle, Tag, ExternalLink } from "lucide-react";
13
+
14
+ interface RunCardProps {
15
+ run: Run;
16
+ selected?: boolean;
17
+ }
18
+
19
+ /** Map run status to progress bar variant */
20
+ function progressVariant(status: Run["status"]): "default" | "success" | "error" | "warning" {
21
+ switch (status) {
22
+ case "completed":
23
+ return "success";
24
+ case "failed":
25
+ return "error";
26
+ case "waiting":
27
+ return "warning";
28
+ default:
29
+ return "default";
30
+ }
31
+ }
32
+
33
+ /** Compute display progress: completed runs always show 100% */
34
+ function displayProgress(run: Run): number {
35
+ if (run.status === "completed") return 100;
36
+ if (run.totalTasks > 0) return Math.round((run.completedTasks / run.totalTasks) * 100);
37
+ return 0;
38
+ }
39
+
40
+ /** Format stale time: "Stale (2h ago)", "Stale (1d ago)" */
41
+ function formatStaleTime(updatedAt: string): string {
42
+ const relative = formatRelativeTime(updatedAt);
43
+ return relative ? `Stale (${relative})` : "Stale";
44
+ }
45
+
46
+ /**
47
+ * Shallow comparison of Run props to prevent unnecessary re-renders.
48
+ * Checks key fields that affect visual output rather than deep-comparing
49
+ * the entire run object (which includes tasks[] and events[]).
50
+ */
51
+ function runCardPropsAreEqual(prev: RunCardProps, next: RunCardProps): boolean {
52
+ if (prev.selected !== next.selected) return false;
53
+ const a = prev.run;
54
+ const b = next.run;
55
+ return (
56
+ a.runId === b.runId &&
57
+ a.status === b.status &&
58
+ a.updatedAt === b.updatedAt &&
59
+ a.completedTasks === b.completedTasks &&
60
+ a.totalTasks === b.totalTasks &&
61
+ a.duration === b.duration &&
62
+ a.isStale === b.isStale &&
63
+ a.waitingKind === b.waitingKind &&
64
+ a.breakpointQuestion === b.breakpointQuestion &&
65
+ a.failedStep === b.failedStep &&
66
+ a.failureMessage === b.failureMessage
67
+ );
68
+ }
69
+
70
+ export const RunCard = memo(function RunCard({ run, selected }: RunCardProps) {
71
+ const progress = displayProgress(run);
72
+ const isActive = run.status === "waiting" || run.status === "pending";
73
+ const isStale = run.isStale === true;
74
+
75
+ // Find the first breakpoint task that is waiting for approval
76
+ const pendingBreakpoint = run.tasks.find(
77
+ (t) => t.kind === "breakpoint" && t.status === "requested"
78
+ );
79
+ // Prefer run-level breakpointQuestion, fall back to task-level
80
+ const breakpointQuestion = run.breakpointQuestion ?? pendingBreakpoint?.breakpointQuestion;
81
+
82
+ // A breakpoint is active if: there's a pending breakpoint task OR the run is waiting on a breakpoint
83
+ const hasActiveBreakpoint = !isStale && (
84
+ !!pendingBreakpoint ||
85
+ (run.status === "waiting" && run.waitingKind === "breakpoint")
86
+ );
87
+
88
+ // Failure point text: prefer run-level failedStep, then construct from failureMessage
89
+ const failedStep = run.status === "failed"
90
+ ? run.failedStep || (run.failureMessage ? `${run.failureMessage}` : undefined)
91
+ : undefined;
92
+
93
+ return (
94
+ <Link href={`/runs/${run.runId}`}>
95
+ <Card className={cn(
96
+ "cursor-pointer p-4 transition-all card-hover-lift",
97
+ "hover:shadow-md",
98
+ selected && "ring-1 ring-primary shadow-glow-primary",
99
+ isActive && !isStale && !hasActiveBreakpoint && "border-[var(--border-hover)]",
100
+ hasActiveBreakpoint && "border-warning/40 shadow-glow-warning ring-1 ring-warning/20 animate-breakpoint-glow",
101
+ isStale && "opacity-50"
102
+ )}>
103
+ <div className="flex items-start justify-between gap-3">
104
+ <div className="flex-1 min-w-0">
105
+ {/* Row 1: Title on its own row for readability */}
106
+ <div className="flex items-center gap-2 mb-1.5">
107
+ <span className={cn(
108
+ "h-2 w-2 rounded-full shrink-0",
109
+ isStale
110
+ ? "bg-zinc-500"
111
+ : hasActiveBreakpoint ? "bg-warning shadow-[0_0_8px_var(--warning)] animate-pulse-dot" :
112
+ run.status === "completed" ? "bg-success shadow-[0_0_6px_var(--success)]" :
113
+ run.status === "failed" ? "bg-error shadow-[0_0_6px_var(--error)]" :
114
+ run.status === "waiting" ? "bg-warning shadow-[0_0_6px_var(--warning)] animate-pulse-dot" :
115
+ "bg-pending"
116
+ )} />
117
+ <span className="text-lg font-semibold italic font-serif text-foreground truncate">
118
+ {friendlyProcessName(run.processId)}
119
+ </span>
120
+ {hasActiveBreakpoint && (
121
+ <span className="inline-flex items-center gap-1 rounded-full bg-warning/15 border border-warning/30 px-2.5 py-1 text-[11px] leading-tight font-bold text-warning uppercase tracking-[0.12em] shrink-0 animate-pulse-dot">
122
+ <Hand className="h-2.5 w-2.5" />
123
+ Approval Required
124
+ </span>
125
+ )}
126
+ </div>
127
+ {/* Row 2: Status badges and tags */}
128
+ <div className="flex items-center gap-2 flex-wrap mb-1">
129
+ <StatusBadge
130
+ status={run.status}
131
+ waitingKind={run.waitingKind}
132
+ isStale={isStale}
133
+ />
134
+ {isStale && (
135
+ <span className="inline-flex items-center rounded-full bg-zinc-500/10 border border-zinc-500/20 px-2 py-0.5 text-xs leading-tight font-medium text-zinc-500 shrink-0">
136
+ {formatStaleTime(run.updatedAt)}
137
+ </span>
138
+ )}
139
+ <TruncatedId id={run.runId} chars={4} className="text-foreground-secondary" />
140
+ {run.projectName && (
141
+ <span className="inline-flex items-center gap-1 rounded-full bg-background-secondary px-2 py-0.5 text-xs leading-tight font-medium text-foreground-muted shrink-0">
142
+ <Tag className="h-2.5 w-2.5" />
143
+ {run.projectName}
144
+ </span>
145
+ )}
146
+ </div>
147
+ {/* Inline failure point for failed runs */}
148
+ {failedStep && (
149
+ <div className="flex items-center gap-1.5 mt-2 px-2 py-1 rounded-md bg-error-muted border border-error/20 border-l-2 border-l-error shadow-glow-error">
150
+ <AlertCircle className="h-3.5 w-3.5 text-error shrink-0" />
151
+ <span className="text-xs text-error truncate">
152
+ Failed at: {failedStep.length > 80 ? failedStep.slice(0, 80) + "..." : failedStep}
153
+ </span>
154
+ </div>
155
+ )}
156
+ {/* Breakpoint question panel — prominent display */}
157
+ {hasActiveBreakpoint && breakpointQuestion && (
158
+ <div className="mt-2 px-3 py-2 rounded-md bg-warning-muted border border-warning/25 border-l-2 border-l-warning shadow-breakpoint-glow">
159
+ <div className="flex items-start gap-2">
160
+ <Hand className="h-4 w-4 text-warning shrink-0 mt-0.5 animate-pulse-dot" />
161
+ <div className="flex-1 min-w-0">
162
+ <span className="text-xs font-bold text-warning uppercase tracking-wider block mb-0.5">
163
+ Awaiting approval
164
+ </span>
165
+ <span className="text-sm text-foreground leading-snug block">
166
+ {breakpointQuestion}
167
+ </span>
168
+ </div>
169
+ <span className={cn(
170
+ "shrink-0 inline-flex items-center gap-1 px-2 py-1 rounded-md",
171
+ "bg-warning/10 border border-warning/20",
172
+ "text-xs font-semibold text-warning",
173
+ "hover:bg-warning/20 transition-colors"
174
+ )}>
175
+ Review & Approve
176
+ <ExternalLink className="h-2.5 w-2.5" />
177
+ </span>
178
+ </div>
179
+ </div>
180
+ )}
181
+ {/* Breakpoint without question text — still show indicator */}
182
+ {hasActiveBreakpoint && !breakpointQuestion && (
183
+ <div className="flex items-center gap-2 mt-2 px-3 py-2 rounded-md bg-warning-muted border border-warning/25 border-l-2 border-l-warning shadow-breakpoint-glow">
184
+ <Hand className="h-4 w-4 text-warning shrink-0 animate-pulse-dot" />
185
+ <span className="text-xs font-semibold text-warning">
186
+ Approval needed
187
+ </span>
188
+ <span className={cn(
189
+ "ml-auto shrink-0 inline-flex items-center gap-1 px-2 py-1 rounded-md",
190
+ "bg-warning/10 border border-warning/20",
191
+ "text-xs font-semibold text-warning"
192
+ )}>
193
+ Review & Approve
194
+ <ExternalLink className="h-2.5 w-2.5" />
195
+ </span>
196
+ </div>
197
+ )}
198
+ <div className="flex items-center gap-3 mt-2 text-xs text-foreground-muted">
199
+ <SessionPill sessionId={run.sessionId} active={isActive && !isStale} />
200
+ <span className="inline-flex items-center gap-1">
201
+ <Layers className="h-3 w-3" />
202
+ {run.completedTasks}/{run.totalTasks} tasks
203
+ </span>
204
+ <span className="inline-flex items-center gap-1">
205
+ <Clock className="h-3 w-3" />
206
+ {formatDuration(run.duration)}
207
+ </span>
208
+ </div>
209
+ </div>
210
+ </div>
211
+ {/* Task 1.8 — Show progress bar for ALL runs, not just active */}
212
+ {run.totalTasks > 0 && (
213
+ <ProgressBar value={progress} variant={progressVariant(run.status)} glow={isActive && !isStale} className="mt-4" />
214
+ )}
215
+ </Card>
216
+ </Link>
217
+ );
218
+ }, runCardPropsAreEqual);