@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,39 @@
1
+ "use client";
2
+ import { memo } from "react";
3
+ import { cn } from "@/lib/cn";
4
+ import { GitBranch } from "lucide-react";
5
+ import type { ReactNode } from "react";
6
+
7
+ interface ParallelGroupProps {
8
+ children: ReactNode;
9
+ count: number;
10
+ className?: string;
11
+ }
12
+
13
+ /**
14
+ * Visual wrapper that groups tasks detected as running in parallel.
15
+ * Shows a dashed border container with a "parallel" label and renders
16
+ * the grouped StepCards inside.
17
+ */
18
+ export const ParallelGroup = memo(function ParallelGroup({ children, count, className }: ParallelGroupProps) {
19
+ return (
20
+ <div
21
+ className={cn(
22
+ "relative rounded-lg border border-dashed border-secondary/20 bg-secondary/[0.03] p-3 pt-7",
23
+ className
24
+ )}
25
+ >
26
+ {/* Label */}
27
+ <div className="absolute top-1.5 left-2.5 flex items-center gap-1 text-xs leading-tight font-medium text-info uppercase tracking-wider select-none">
28
+ <GitBranch className="h-3 w-3 text-info" />
29
+ <span>parallel</span>
30
+ <span className="text-foreground-muted">&middot; {count} tasks</span>
31
+ </div>
32
+
33
+ {/* Grouped task cards */}
34
+ <div className="flex flex-col gap-2">
35
+ {children}
36
+ </div>
37
+ </div>
38
+ );
39
+ });
@@ -0,0 +1,197 @@
1
+ "use client";
2
+ import { useMemo, useState, memo } from "react";
3
+ import { StepCard } from "./step-card";
4
+ import { ParallelGroup } from "./parallel-group";
5
+ import { ProgressBar } from "@/components/shared/progress-bar";
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 { formatDuration, friendlyProcessName } from "@/lib/utils";
10
+ import { ScrollArea } from "@/components/ui/scroll-area";
11
+ import type { Run, TaskEffect } from "@/types";
12
+ import { ChevronRight, Clock, Layers, ChevronDown } from "lucide-react";
13
+ import Link from "next/link";
14
+
15
+ /** Threshold in ms -- tasks requested within this window are considered parallel */
16
+ const PARALLEL_THRESHOLD_MS = 100;
17
+
18
+ /**
19
+ * A pipeline entry is either a single task or a group of tasks
20
+ * that were requested in parallel.
21
+ */
22
+ type PipelineEntry =
23
+ | { type: "single"; task: TaskEffect }
24
+ | { type: "parallel"; tasks: TaskEffect[] };
25
+
26
+ /**
27
+ * Detect parallel task groups.
28
+ *
29
+ * Two tasks are considered parallel when they share the same stepId prefix
30
+ * (the portion before the first `.`) OR their requestedAt timestamps are
31
+ * within PARALLEL_THRESHOLD_MS of each other.
32
+ *
33
+ * The algorithm walks the task list (sorted by requestedAt) and greedily
34
+ * merges adjacent tasks that satisfy either condition into a group.
35
+ */
36
+ function groupParallelTasks(tasks: TaskEffect[]): PipelineEntry[] {
37
+ if (tasks.length === 0) return [];
38
+
39
+ const sorted = [...tasks].sort(
40
+ (a, b) => new Date(a.requestedAt).getTime() - new Date(b.requestedAt).getTime()
41
+ );
42
+
43
+ const entries: PipelineEntry[] = [];
44
+ let currentGroup: TaskEffect[] = [sorted[0]];
45
+
46
+ for (let i = 1; i < sorted.length; i++) {
47
+ const prev = currentGroup[currentGroup.length - 1];
48
+ const curr = sorted[i];
49
+
50
+ const prevTime = new Date(prev.requestedAt).getTime();
51
+ const currTime = new Date(curr.requestedAt).getTime();
52
+ const timeDelta = Math.abs(currTime - prevTime);
53
+
54
+ const prevStepPrefix = prev.stepId.split(".")[0];
55
+ const currStepPrefix = curr.stepId.split(".")[0];
56
+ const sameStepPrefix = prevStepPrefix === currStepPrefix;
57
+
58
+ if (sameStepPrefix || timeDelta <= PARALLEL_THRESHOLD_MS) {
59
+ currentGroup.push(curr);
60
+ } else {
61
+ // Flush the accumulated group
62
+ if (currentGroup.length === 1) {
63
+ entries.push({ type: "single", task: currentGroup[0] });
64
+ } else {
65
+ entries.push({ type: "parallel", tasks: currentGroup });
66
+ }
67
+ currentGroup = [curr];
68
+ }
69
+ }
70
+
71
+ // Flush remaining group
72
+ if (currentGroup.length === 1) {
73
+ entries.push({ type: "single", task: currentGroup[0] });
74
+ } else {
75
+ entries.push({ type: "parallel", tasks: currentGroup });
76
+ }
77
+
78
+ return entries;
79
+ }
80
+
81
+ interface PipelineViewProps {
82
+ run: Run;
83
+ selectedEffectId: string | null;
84
+ onSelectEffect: (effectId: string) => void;
85
+ runStatus?: string;
86
+ }
87
+
88
+ const INITIAL_TASK_LIMIT = 20;
89
+
90
+ export const PipelineView = memo(function PipelineView({ run, selectedEffectId, onSelectEffect, runStatus }: PipelineViewProps) {
91
+ const effectiveStatus = runStatus ?? run.status;
92
+ const isReviewMode = effectiveStatus === "completed" || effectiveStatus === "failed";
93
+ const isRunning = effectiveStatus === "requested" || effectiveStatus === "waiting";
94
+ const progress = run.totalTasks > 0 ? Math.round((run.completedTasks / run.totalTasks) * 100) : 0;
95
+ const [showAllTasks, setShowAllTasks] = useState(false);
96
+
97
+ const pipelineEntries = useMemo(() => groupParallelTasks(run.tasks), [run.tasks]);
98
+ const hasMore = pipelineEntries.length > INITIAL_TASK_LIMIT;
99
+ const visibleEntries = showAllTasks || !hasMore ? pipelineEntries : pipelineEntries.slice(0, INITIAL_TASK_LIMIT);
100
+
101
+ return (
102
+ <div data-testid="pipeline-view" className="flex flex-col h-full">
103
+ {/* Header with breadcrumb — sticky so it's always visible */}
104
+ <div className="shrink-0 sticky top-0 z-20 border-b border-border p-4 pb-3 bg-card/95 backdrop-blur-sm">
105
+ {/* Breadcrumb navigation — prominent for easy back-navigation */}
106
+ <nav data-testid="pipeline-breadcrumb" className="flex items-center gap-1.5 mb-2 text-sm">
107
+ <Link href="/" className="text-foreground-muted hover:text-primary transition-colors font-semibold">
108
+ Projects
109
+ </Link>
110
+ <ChevronRight className="h-3.5 w-3.5 text-foreground-muted/50" />
111
+ <span className="text-foreground-secondary font-semibold">
112
+ {run.projectName || friendlyProcessName(run.processId)}
113
+ </span>
114
+ <ChevronRight className="h-3.5 w-3.5 text-foreground-muted/50" />
115
+ <TruncatedId id={run.runId} chars={4} className="text-foreground font-medium" />
116
+ <StatusBadge status={run.status} className="ml-1" />
117
+ </nav>
118
+ <div className="flex items-center gap-4 text-xs text-foreground-muted mb-3">
119
+ <SessionPill sessionId={run.sessionId} active={run.status === "waiting"} />
120
+ <span className="inline-flex items-center gap-1">
121
+ <Layers className="h-3 w-3" />
122
+ {run.completedTasks}/{run.totalTasks} tasks
123
+ </span>
124
+ <span className="inline-flex items-center gap-1">
125
+ <Clock className="h-3 w-3" />
126
+ {formatDuration(run.duration)}
127
+ </span>
128
+ </div>
129
+ <div className="flex items-center gap-3">
130
+ <div className="flex-1">
131
+ <ProgressBar value={progress} glow={isRunning} />
132
+ </div>
133
+ <span className="text-xs leading-tight text-foreground-muted tabular-nums shrink-0">{progress}%</span>
134
+ </div>
135
+ </div>
136
+
137
+ {/* Step list */}
138
+ <ScrollArea className="flex-1 relative">
139
+ {/* Subtle top gradient for depth — brand magenta/cyan */}
140
+ <div className="sticky top-0 z-10 h-3 bg-gradient-to-b from-primary/[0.06] via-secondary/[0.03] to-transparent pointer-events-none" />
141
+ <div className="flex flex-col gap-2 px-4 pb-4">
142
+ {(() => {
143
+ let stepCounter = 0;
144
+ return visibleEntries.map((entry) => {
145
+ if (entry.type === "single") {
146
+ stepCounter++;
147
+ return (
148
+ <StepCard
149
+ key={entry.task.effectId}
150
+ task={entry.task}
151
+ runId={run.runId}
152
+ onSelect={onSelectEffect}
153
+ isSelected={selectedEffectId === entry.task.effectId}
154
+ defaultExpanded={isReviewMode}
155
+ stepNumber={stepCounter}
156
+ />
157
+ );
158
+ }
159
+
160
+ // Parallel group — all share the same step number
161
+ stepCounter++;
162
+ const groupKey = entry.tasks.map((t) => t.effectId).join("|");
163
+ return (
164
+ <ParallelGroup key={groupKey} count={entry.tasks.length}>
165
+ {entry.tasks.map((task) => (
166
+ <StepCard
167
+ key={task.effectId}
168
+ task={task}
169
+ runId={run.runId}
170
+ onSelect={onSelectEffect}
171
+ isSelected={selectedEffectId === task.effectId}
172
+ defaultExpanded={isReviewMode}
173
+ stepNumber={stepCounter}
174
+ />
175
+ ))}
176
+ </ParallelGroup>
177
+ );
178
+ });
179
+ })()}
180
+ {hasMore && !showAllTasks && (
181
+ <button
182
+ data-testid="show-all-tasks-btn"
183
+ onClick={() => setShowAllTasks(true)}
184
+ className="w-full flex items-center justify-center gap-1.5 rounded-md border border-border bg-background-secondary/50 py-2 text-xs text-foreground-muted hover:text-foreground hover:bg-background-secondary transition-colors"
185
+ >
186
+ <ChevronDown className="h-3.5 w-3.5" />
187
+ Show all {pipelineEntries.length} tasks
188
+ </button>
189
+ )}
190
+ {run.tasks.length === 0 && (
191
+ <div className="text-sm text-foreground-muted text-center py-8">No tasks yet</div>
192
+ )}
193
+ </div>
194
+ </ScrollArea>
195
+ </div>
196
+ );
197
+ });
@@ -0,0 +1,166 @@
1
+ "use client";
2
+ import { useState, useEffect, memo } from "react";
3
+ import { cn } from "@/lib/cn";
4
+ import { StatusBadge } from "@/components/shared/status-badge";
5
+ import { KindBadge } from "@/components/shared/kind-badge";
6
+ import { formatDuration } from "@/lib/utils";
7
+ import { TruncatedId } from "@/components/shared/truncated-id";
8
+ import type { TaskEffect } from "@/types";
9
+ import { ChevronDown, Clock, Hand } from "lucide-react";
10
+
11
+ interface StepCardProps {
12
+ task: TaskEffect;
13
+ runId: string;
14
+ onSelect: (effectId: string) => void;
15
+ isSelected: boolean;
16
+ defaultExpanded?: boolean;
17
+ /** 1-based step number for display */
18
+ stepNumber?: number;
19
+ }
20
+
21
+ export const StepCard = memo(function StepCard({ task, runId: _runId, onSelect, isSelected, defaultExpanded = false, stepNumber }: StepCardProps) {
22
+ const [expanded, setExpanded] = useState(defaultExpanded);
23
+ const isRunning = task.status === "requested";
24
+ const isBreakpointWaiting = task.kind === "breakpoint" && task.status === "requested";
25
+ const borderColor = isBreakpointWaiting ? "border-l-warning shadow-step-inset-warning" :
26
+ task.status === "resolved" ? "border-l-success" :
27
+ task.status === "error" ? "border-l-error" :
28
+ isRunning ? "border-l-info shadow-step-inset-cyan" : "border-l-pending/30";
29
+
30
+ // Live elapsed time counter for running tasks
31
+ const [elapsedMs, setElapsedMs] = useState<number>(0);
32
+
33
+ useEffect(() => {
34
+ if (!isRunning || !task.requestedAt) {
35
+ return;
36
+ }
37
+
38
+ // Calculate initial elapsed time
39
+ const calculateElapsed = () => {
40
+ const requestedTime = new Date(task.requestedAt).getTime();
41
+ const now = Date.now();
42
+ return now - requestedTime;
43
+ };
44
+
45
+ // Set initial value
46
+ setElapsedMs(calculateElapsed());
47
+
48
+ // Update every second
49
+ const interval = setInterval(() => {
50
+ setElapsedMs(calculateElapsed());
51
+ }, 1000);
52
+
53
+ return () => clearInterval(interval);
54
+ }, [isRunning, task.requestedAt]);
55
+
56
+ return (
57
+ <div
58
+ data-testid={`step-card-${task.effectId}`}
59
+ data-status={task.status}
60
+ data-selected={String(isSelected)}
61
+ className={cn(
62
+ "w-full text-left rounded-lg border border-card-border bg-card transition-all duration-150",
63
+ "hover:bg-[var(--card-hover)] border-l-[3px]",
64
+ borderColor,
65
+ isSelected && "border-l-primary bg-primary-muted shadow-step-selected",
66
+ isBreakpointWaiting && "animate-breakpoint-glow"
67
+ )}
68
+ >
69
+ <button
70
+ onClick={() => onSelect(task.effectId)}
71
+ className="w-full text-left p-3"
72
+ >
73
+ <div className="flex items-center justify-between gap-2">
74
+ <div className="flex items-center gap-2 min-w-0">
75
+ {isBreakpointWaiting ? (
76
+ <Hand className="h-3.5 w-3.5 text-warning animate-pulse-dot shrink-0 drop-shadow-[var(--drop-glow-warning)]" />
77
+ ) : isRunning ? (
78
+ <div className="h-2 w-2 rounded-full bg-info animate-pulse-dot shrink-0 shadow-step-running-dot" />
79
+ ) : null}
80
+ {stepNumber && (
81
+ <span className="flex-shrink-0 w-5 h-5 rounded-full bg-background-tertiary text-xs font-mono text-foreground-muted flex items-center justify-center">
82
+ {stepNumber}
83
+ </span>
84
+ )}
85
+ <span className="text-sm font-medium text-foreground truncate">{task.title}</span>
86
+ </div>
87
+ <div className="flex items-center gap-2 shrink-0">
88
+ <KindBadge kind={task.kind} />
89
+ <StatusBadge status={task.status} />
90
+ </div>
91
+ </div>
92
+ {isBreakpointWaiting ? (
93
+ <div className="flex items-center gap-1 mt-1.5 text-xs text-warning">
94
+ <Hand className="h-3 w-3 shrink-0 drop-shadow-[var(--drop-glow-warning-sm)]" />
95
+ <span className="font-medium">Your approval is needed</span>
96
+ <span className="font-mono text-warning animate-pulse">{formatDuration(elapsedMs)}</span>
97
+ </div>
98
+ ) : (task.duration || isRunning) ? (
99
+ <div className="flex items-center gap-1 mt-1.5 text-xs text-foreground-muted">
100
+ <Clock className="h-3 w-3 shrink-0" />
101
+ <span className="whitespace-nowrap">
102
+ {isRunning ? (
103
+ <span className="animate-pulse font-mono text-info/80">running {formatDuration(elapsedMs)}...</span>
104
+ ) : (
105
+ <span className="font-mono">{formatDuration(task.duration)}</span>
106
+ )}
107
+ </span>
108
+ </div>
109
+ ) : null}
110
+ </button>
111
+
112
+ {/* Expand/collapse toggle */}
113
+ <div className="flex items-center border-t border-card-border">
114
+ <button
115
+ onClick={(e) => { e.stopPropagation(); setExpanded((v) => !v); }}
116
+ className="flex items-center justify-center px-3 py-2 text-foreground-muted hover:text-primary hover:bg-primary-muted rounded-b-lg transition-colors w-full"
117
+ aria-label={expanded ? "Collapse details" : "Expand details"}
118
+ >
119
+ <ChevronDown className={cn("h-4 w-4 transition-transform duration-200", !expanded && "-rotate-90")} />
120
+ </button>
121
+ </div>
122
+
123
+ {/* Expanded detail */}
124
+ <div
125
+ className={cn(
126
+ "grid transition-[grid-template-rows,opacity] duration-200 ease-out",
127
+ expanded ? "grid-rows-[1fr] opacity-100" : "grid-rows-[0fr] opacity-0"
128
+ )}
129
+ >
130
+ <div className="overflow-hidden">
131
+ <div className="px-3 pb-3 text-xs text-foreground-muted space-y-1.5 border-t border-card-border">
132
+ <div className="flex items-center gap-2 pt-2">
133
+ <span className="text-foreground-secondary font-medium">Step:</span>
134
+ <TruncatedId id={task.stepId} chars={4} />
135
+ </div>
136
+ {task.duration != null && (
137
+ <div className="flex items-center gap-2">
138
+ <span className="text-foreground-secondary font-medium">
139
+ {task.kind === "breakpoint" ? "Approval time:" : "Duration:"}
140
+ </span>
141
+ <span>{formatDuration(task.duration)}</span>
142
+ </div>
143
+ )}
144
+ {task.requestedAt && (
145
+ <div className="flex items-center gap-2">
146
+ <span className="text-foreground-secondary font-medium">Requested:</span>
147
+ <span>{new Date(task.requestedAt).toLocaleTimeString()}</span>
148
+ </div>
149
+ )}
150
+ {task.resolvedAt && (
151
+ <div className="flex items-center gap-2">
152
+ <span className="text-foreground-secondary font-medium">Resolved:</span>
153
+ <span>{new Date(task.resolvedAt).toLocaleTimeString()}</span>
154
+ </div>
155
+ )}
156
+ {task.error && (
157
+ <div className="mt-2 rounded bg-error-muted p-2 text-error">
158
+ <span className="font-medium">{task.error.name}:</span> {task.error.message}
159
+ </div>
160
+ )}
161
+ </div>
162
+ </div>
163
+ </div>
164
+ </div>
165
+ );
166
+ });
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { createContext, useContext } from "react";
3
+ import { useEventStream, StreamEvent } from "@/hooks/use-event-stream";
4
+
5
+ interface EventStreamContextValue {
6
+ connected: boolean;
7
+ lastEvent: StreamEvent | null;
8
+ error: string | null;
9
+ }
10
+
11
+ const EventStreamContext = createContext<EventStreamContextValue | null>(null);
12
+
13
+ export function EventStreamProvider({ children }: { children: React.ReactNode }) {
14
+ const { connected, lastEvent, error } = useEventStream();
15
+
16
+ return (
17
+ <EventStreamContext.Provider value={{ connected, lastEvent, error }}>
18
+ {children}
19
+ </EventStreamContext.Provider>
20
+ );
21
+ }
22
+
23
+ export function useEventStreamContext() {
24
+ const context = useContext(EventStreamContext);
25
+ if (!context) {
26
+ throw new Error("useEventStreamContext must be used within EventStreamProvider");
27
+ }
28
+ return context;
29
+ }
@@ -0,0 +1,24 @@
1
+ "use client";
2
+ import { ThemeProvider } from "@/components/shared/theme-provider";
3
+ import { NotificationProvider } from "@/components/notifications/notification-provider";
4
+ import { EventStreamProvider } from "@/components/providers/event-stream-provider";
5
+ import { ShortcutsHelp } from "@/components/shared/shortcuts-help";
6
+ import { AppHeader } from "@/components/shared/app-header";
7
+ import { AppFooter } from "@/components/shared/app-footer";
8
+
9
+ export function Providers({ children }: { children: React.ReactNode }) {
10
+ return (
11
+ <ThemeProvider>
12
+ <NotificationProvider>
13
+ <EventStreamProvider>
14
+ <div className="flex flex-col min-h-screen">
15
+ <AppHeader />
16
+ <main id="main-content" className="flex-1 flex flex-col">{children}</main>
17
+ <AppFooter />
18
+ </div>
19
+ <ShortcutsHelp />
20
+ </EventStreamProvider>
21
+ </NotificationProvider>
22
+ </ThemeProvider>
23
+ );
24
+ }
File without changes
@@ -0,0 +1,49 @@
1
+ import React from 'react';
2
+ import { describe, it, expect } from 'vitest';
3
+ import { render, screen } from '@/test/test-utils';
4
+ import { EmptyState } from '../empty-state';
5
+
6
+ describe('EmptyState', () => {
7
+ it('renders without crashing', () => {
8
+ render(<EmptyState />);
9
+ expect(screen.getByText('No runs found')).toBeInTheDocument();
10
+ });
11
+
12
+ it('renders default title', () => {
13
+ render(<EmptyState />);
14
+ expect(screen.getByText('No runs found')).toBeInTheDocument();
15
+ });
16
+
17
+ it('renders default description', () => {
18
+ render(<EmptyState />);
19
+ expect(screen.getByText('Start a babysitter run to see it here.')).toBeInTheDocument();
20
+ });
21
+
22
+ it('renders custom title', () => {
23
+ render(<EmptyState title="Nothing here" />);
24
+ expect(screen.getByText('Nothing here')).toBeInTheDocument();
25
+ });
26
+
27
+ it('renders custom description', () => {
28
+ render(<EmptyState description="Try adding some data." />);
29
+ expect(screen.getByText('Try adding some data.')).toBeInTheDocument();
30
+ });
31
+
32
+ it('renders the Inbox icon', () => {
33
+ const { container } = render(<EmptyState />);
34
+ const svg = container.querySelector('svg');
35
+ expect(svg).toBeInTheDocument();
36
+ });
37
+
38
+ it('applies custom className', () => {
39
+ const { container } = render(<EmptyState className="my-custom" />);
40
+ const wrapper = container.firstChild as HTMLElement;
41
+ expect(wrapper.className).toContain('my-custom');
42
+ });
43
+
44
+ it('renders custom title and description together', () => {
45
+ render(<EmptyState title="Empty" description="Custom desc" />);
46
+ expect(screen.getByText('Empty')).toBeInTheDocument();
47
+ expect(screen.getByText('Custom desc')).toBeInTheDocument();
48
+ });
49
+ });
@@ -0,0 +1,47 @@
1
+ import React from 'react';
2
+ import { describe, it, expect, vi } from 'vitest';
3
+ import { render, screen } from '@/test/test-utils';
4
+ import userEvent from '@testing-library/user-event';
5
+ import { FriendlyId } from '../friendly-id';
6
+
7
+ describe('FriendlyId', () => {
8
+ it('renders without crashing', () => {
9
+ render(<FriendlyId id="abc123def456" />);
10
+ // formatShortId("abc123def456") defaults to 4 chars => "...f456"
11
+ expect(screen.getByText('...f456')).toBeInTheDocument();
12
+ });
13
+
14
+ it('renders truncated ID using formatShortId', () => {
15
+ render(<FriendlyId id="my-long-test-id" />);
16
+ expect(screen.getByText('...t-id')).toBeInTheDocument();
17
+ });
18
+
19
+ it('renders as a button element', () => {
20
+ render(<FriendlyId id="test-id" />);
21
+ expect(screen.getByRole('button')).toBeInTheDocument();
22
+ });
23
+
24
+ it('copies full ID to clipboard on click', async () => {
25
+ const user = userEvent.setup();
26
+ const writeTextSpy = vi.spyOn(navigator.clipboard, 'writeText');
27
+ render(<FriendlyId id="full-id-for-copy" />);
28
+ const btn = screen.getByRole('button');
29
+ await user.click(btn);
30
+ expect(writeTextSpy).toHaveBeenCalledWith('full-id-for-copy');
31
+ });
32
+
33
+ it('applies copied class after clicking', async () => {
34
+ const user = userEvent.setup();
35
+ render(<FriendlyId id="some-id" />);
36
+ const btn = screen.getByRole('button');
37
+ await user.click(btn);
38
+ // After copying, button gets 'text-primary' class to indicate copied state
39
+ expect(btn.className).toContain('text-primary');
40
+ });
41
+
42
+ it('applies custom className', () => {
43
+ const { container } = render(<FriendlyId id="test" className="my-class" />);
44
+ const btn = container.querySelector('button');
45
+ expect(btn?.className).toContain('my-class');
46
+ });
47
+ });
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+ import { describe, it, expect } from 'vitest';
3
+ import { render, screen } from '@/test/test-utils';
4
+ import { Kbd } from '../kbd';
5
+
6
+ describe('Kbd', () => {
7
+ it('renders without crashing', () => {
8
+ render(<Kbd>K</Kbd>);
9
+ expect(screen.getByText('K')).toBeInTheDocument();
10
+ });
11
+
12
+ it('renders the children text', () => {
13
+ render(<Kbd>Enter</Kbd>);
14
+ expect(screen.getByText('Enter')).toBeInTheDocument();
15
+ });
16
+
17
+ it('renders as a <kbd> element', () => {
18
+ const { container } = render(<Kbd>A</Kbd>);
19
+ const kbd = container.querySelector('kbd');
20
+ expect(kbd).toBeInTheDocument();
21
+ expect(kbd?.textContent).toBe('A');
22
+ });
23
+
24
+ it('applies default styling classes', () => {
25
+ const { container } = render(<Kbd>X</Kbd>);
26
+ const kbd = container.querySelector('kbd') as HTMLElement;
27
+ expect(kbd.className).toContain('inline-flex');
28
+ expect(kbd.className).toContain('font-mono');
29
+ });
30
+
31
+ it('applies custom className', () => {
32
+ const { container } = render(<Kbd className="extra-class">M</Kbd>);
33
+ const kbd = container.querySelector('kbd') as HTMLElement;
34
+ expect(kbd.className).toContain('extra-class');
35
+ });
36
+
37
+ it('renders complex children', () => {
38
+ render(
39
+ <Kbd>
40
+ <span>Ctrl</span>
41
+ </Kbd>,
42
+ );
43
+ expect(screen.getByText('Ctrl')).toBeInTheDocument();
44
+ });
45
+ });
@@ -0,0 +1,71 @@
1
+ import React from 'react';
2
+ import { describe, it, expect } from 'vitest';
3
+ import { render, screen } from '@/test/test-utils';
4
+ import { KindBadge } from '../kind-badge';
5
+
6
+ describe('KindBadge', () => {
7
+ it('renders without crashing', () => {
8
+ render(<KindBadge kind="node" />);
9
+ expect(screen.getByText('node')).toBeInTheDocument();
10
+ });
11
+
12
+ it('renders "agent" kind with correct text', () => {
13
+ render(<KindBadge kind="agent" />);
14
+ expect(screen.getByText('agent')).toBeInTheDocument();
15
+ });
16
+
17
+ it('renders "node" kind with correct text', () => {
18
+ render(<KindBadge kind="node" />);
19
+ expect(screen.getByText('node')).toBeInTheDocument();
20
+ });
21
+
22
+ it('renders "shell" kind with correct text', () => {
23
+ render(<KindBadge kind="shell" />);
24
+ expect(screen.getByText('shell')).toBeInTheDocument();
25
+ });
26
+
27
+ it('renders "skill" kind with correct text', () => {
28
+ render(<KindBadge kind="skill" />);
29
+ expect(screen.getByText('skill')).toBeInTheDocument();
30
+ });
31
+
32
+ it('renders "breakpoint" kind with "approval" display text', () => {
33
+ render(<KindBadge kind="breakpoint" />);
34
+ expect(screen.getByText('approval')).toBeInTheDocument();
35
+ });
36
+
37
+ it('renders "sleep" kind with correct text', () => {
38
+ render(<KindBadge kind="sleep" />);
39
+ expect(screen.getByText('sleep')).toBeInTheDocument();
40
+ });
41
+
42
+ it('renders an SVG icon alongside the kind text', () => {
43
+ const { container } = render(<KindBadge kind="agent" />);
44
+ const svg = container.querySelector('svg');
45
+ expect(svg).toBeInTheDocument();
46
+ });
47
+
48
+ it('applies agent color class for agent kind', () => {
49
+ const { container } = render(<KindBadge kind="agent" />);
50
+ const badge = container.firstChild as HTMLElement;
51
+ expect(badge.className).toContain('text-primary');
52
+ });
53
+
54
+ it('applies warning color class for node kind', () => {
55
+ const { container } = render(<KindBadge kind="node" />);
56
+ const badge = container.firstChild as HTMLElement;
57
+ expect(badge.className).toContain('text-warning');
58
+ });
59
+
60
+ it('applies info color class for skill kind', () => {
61
+ const { container } = render(<KindBadge kind="skill" />);
62
+ const badge = container.firstChild as HTMLElement;
63
+ expect(badge.className).toContain('text-info');
64
+ });
65
+
66
+ it('applies custom className', () => {
67
+ const { container } = render(<KindBadge kind="agent" className="extra-cls" />);
68
+ const badge = container.firstChild as HTMLElement;
69
+ expect(badge.className).toContain('extra-cls');
70
+ });
71
+ });