@a5c-ai/babysitter-observer-dashboard 5.0.1-staging.05ee168a

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/EABLIK_sdQGd8BsGP793M/_buildManifest.js +11 -0
  280. package/.next/static/EABLIK_sdQGd8BsGP793M/_clientMiddlewareManifest.js +1 -0
  281. package/.next/static/EABLIK_sdQGd8BsGP793M/_ssgManifest.js +1 -0
  282. package/.next/static/chunks/0.syqclhhnw~3.js +4 -0
  283. package/.next/static/chunks/01xlw8hd842-c.js +1 -0
  284. package/.next/static/chunks/034i63v_muq~d.js +1 -0
  285. package/.next/static/chunks/03mo-6~4pxdio.js +1 -0
  286. package/.next/static/chunks/03~yq9q893hmn.js +1 -0
  287. package/.next/static/chunks/04dm5qn77.fc2.js +1 -0
  288. package/.next/static/chunks/07uz2g0_38qia.js +4 -0
  289. package/.next/static/chunks/08nqnwvixoxnk.js +2 -0
  290. package/.next/static/chunks/09fqccrs830-n.js +1 -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/0jgju7iyqhzfr.js +1 -0
  294. package/.next/static/chunks/0mstyq17cbf8-.js +1 -0
  295. package/.next/static/chunks/0ntuxw9.how-q.js +1 -0
  296. package/.next/static/chunks/0t3uzajv1qzmo.js +1 -0
  297. package/.next/static/chunks/0tk7tld3z8q_b.js +1 -0
  298. package/.next/static/chunks/0u~_nwr5-v.xp.js +1 -0
  299. package/.next/static/chunks/0x6y7yt4kiddp.css +1 -0
  300. package/.next/static/chunks/0ze4gu236oq96.js +31 -0
  301. package/.next/static/chunks/0zwozael9msy1.js +1 -0
  302. package/.next/static/chunks/0~nsmwzvlcp_3.js +1 -0
  303. package/.next/static/chunks/10qd__0r7a~.l.js +1 -0
  304. package/.next/static/chunks/11jh_u1ynmatg.js +1 -0
  305. package/.next/static/chunks/144kcri75qczu.js +1 -0
  306. package/.next/static/chunks/170fc9ko4~0_4.js +5 -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,286 @@
1
+ import { getConfig as defaultGetConfig } from "@/lib/config-loader";
2
+ import { discoverAllRunDirs as defaultDiscoverAllRunDirs } from "@/lib/source-discovery";
3
+ import {
4
+ getProjectSummaries as defaultGetProjectSummaries,
5
+ getRunCached as defaultGetRunCached,
6
+ discoverAndCacheAll as defaultDiscoverAndCacheAll,
7
+ } from "@/lib/run-cache";
8
+ import type { Run, ProjectSummary } from "@/types";
9
+ import type { ObserverConfig, WatchSource } from "@/lib/config-loader";
10
+ import type { DiscoveredRun } from "@/lib/source-discovery";
11
+
12
+ // ---------------------------------------------------------------------------
13
+ // Query parameter types
14
+ // ---------------------------------------------------------------------------
15
+
16
+ export type SortMode = "status" | "activity";
17
+
18
+ export interface RunQueryParams {
19
+ limit: number;
20
+ offset: number;
21
+ search: string;
22
+ status: string;
23
+ sort: SortMode;
24
+ }
25
+
26
+ export type ProjectsQueryParams = Record<string, never>;
27
+
28
+ export interface ProjectRunsQueryParams extends RunQueryParams {
29
+ project: string;
30
+ }
31
+
32
+ // ---------------------------------------------------------------------------
33
+ // Response types
34
+ // ---------------------------------------------------------------------------
35
+
36
+ /** A run with events stripped to reduce payload size. */
37
+ export interface LightRun extends Omit<Run, "events"> {
38
+ events: never[];
39
+ totalEvents: number;
40
+ }
41
+
42
+ export interface ProjectsResponse {
43
+ projects: ProjectSummary[];
44
+ recentCompletionWindowMs: number;
45
+ }
46
+
47
+ export interface RunsListResponse {
48
+ runs: LightRun[];
49
+ totalCount: number;
50
+ project?: string;
51
+ }
52
+
53
+ // ---------------------------------------------------------------------------
54
+ // Shared utilities
55
+ // ---------------------------------------------------------------------------
56
+
57
+ /**
58
+ * Returns a numeric sort priority for a run:
59
+ * 0 = Active non-stale (waiting/pending where !isStale)
60
+ * 1 = Stale runs (isStale === true)
61
+ * 2 = Failed runs
62
+ * 3 = Completed runs
63
+ */
64
+ export function runSortPriority(run: Run): number {
65
+ const isActive = run.status === "waiting" || run.status === "pending";
66
+ if (isActive && !run.isStale) return 0;
67
+ if (run.isStale) return 1;
68
+ if (run.status === "failed") return 2;
69
+ return 3;
70
+ }
71
+
72
+ /** Sort runs in-place based on the chosen sort mode.
73
+ *
74
+ * Uses runId as a final tiebreaker to guarantee deterministic ordering
75
+ * even when multiple runs share the same priority and updatedAt timestamp.
76
+ * This prevents list items from visually jumping positions during rapid
77
+ * updates (the "morning chaos" scenario).
78
+ */
79
+ export function sortRuns(runs: Run[], sort: SortMode): void {
80
+ if (sort === "activity") {
81
+ // Simple updatedAt DESC -- most recent activity first, no tier grouping.
82
+ // runId tiebreaker ensures stable order for runs with identical timestamps.
83
+ runs.sort((a, b) => {
84
+ const cmp = (b.updatedAt || "").localeCompare(a.updatedAt || "");
85
+ if (cmp !== 0) return cmp;
86
+ return a.runId.localeCompare(b.runId);
87
+ });
88
+ } else {
89
+ // Default: sort by priority tier, then by updatedAt DESC within tier,
90
+ // with runId as a final tiebreaker for deterministic ordering.
91
+ runs.sort((a, b) => {
92
+ const pa = runSortPriority(a);
93
+ const pb = runSortPriority(b);
94
+ if (pa !== pb) return pa - pb;
95
+ const cmp = (b.updatedAt || "").localeCompare(a.updatedAt || "");
96
+ if (cmp !== 0) return cmp;
97
+ return a.runId.localeCompare(b.runId);
98
+ });
99
+ }
100
+ }
101
+
102
+ /** Apply search filter -- returns a new array. */
103
+ export function filterBySearch(runs: Run[], search: string): Run[] {
104
+ if (!search) return runs;
105
+ const searchLower = search.toLowerCase();
106
+ return runs.filter(
107
+ (r) =>
108
+ r.runId.toLowerCase().includes(searchLower) ||
109
+ r.processId.toLowerCase().includes(searchLower) ||
110
+ (r.projectName || "").toLowerCase().includes(searchLower) ||
111
+ r.status.toLowerCase().includes(searchLower) ||
112
+ r.tasks.some(
113
+ (t) =>
114
+ t.title.toLowerCase().includes(searchLower) ||
115
+ t.label.toLowerCase().includes(searchLower) ||
116
+ (t.error?.message || "").toLowerCase().includes(searchLower) ||
117
+ (t.error?.name || "").toLowerCase().includes(searchLower)
118
+ )
119
+ );
120
+ }
121
+
122
+ /** Apply status filter -- returns a new array. */
123
+ export function filterByStatus(runs: Run[], status: string): Run[] {
124
+ if (!status) return runs;
125
+ return runs.filter((r) => {
126
+ if (status === "waiting") return r.status === "waiting" || r.status === "pending";
127
+ return r.status === status;
128
+ });
129
+ }
130
+
131
+ /** Apply retention filter -- keeps active/stale runs regardless of age. */
132
+ export function filterByRetention(runs: Run[], retentionDays: number): Run[] {
133
+ const retentionCutoff = Date.now() - retentionDays * 24 * 60 * 60 * 1000;
134
+ return runs.filter((r) => {
135
+ const isActive = r.status === "waiting" || r.status === "pending" || r.isStale;
136
+ if (isActive) return true;
137
+ return new Date(r.updatedAt || "").getTime() >= retentionCutoff;
138
+ });
139
+ }
140
+
141
+ /** Paginate an array: returns a new slice. */
142
+ export function paginate<T>(items: T[], offset: number, limit: number): T[] {
143
+ if (limit > 0) {
144
+ return items.slice(offset, offset + limit);
145
+ }
146
+ return items;
147
+ }
148
+
149
+ /** Strip events from runs to reduce payload. */
150
+ export function toLightRuns(runs: Run[]): LightRun[] {
151
+ return runs.map(({ events, ...rest }) => ({
152
+ ...rest,
153
+ events: [] as never[],
154
+ totalEvents: events.length,
155
+ }));
156
+ }
157
+
158
+ // ---------------------------------------------------------------------------
159
+ // Dependency injection interface
160
+ // ---------------------------------------------------------------------------
161
+
162
+ export interface RunQueryDeps {
163
+ getConfig: () => Promise<ObserverConfig>;
164
+ discoverAllRunDirs: () => Promise<DiscoveredRun[]>;
165
+ getProjectSummaries: () => ProjectSummary[];
166
+ getRunCached: (runDir: string, source: WatchSource, projectName: string) => Promise<Run>;
167
+ discoverAndCacheAll: () => Promise<void>;
168
+ }
169
+
170
+ const defaultDeps: RunQueryDeps = {
171
+ getConfig: defaultGetConfig,
172
+ discoverAllRunDirs: defaultDiscoverAllRunDirs,
173
+ getProjectSummaries: defaultGetProjectSummaries,
174
+ getRunCached: defaultGetRunCached,
175
+ discoverAndCacheAll: defaultDiscoverAndCacheAll,
176
+ };
177
+
178
+ // ---------------------------------------------------------------------------
179
+ // RunQueryService
180
+ // ---------------------------------------------------------------------------
181
+
182
+ export class RunQueryService {
183
+ private deps: RunQueryDeps;
184
+
185
+ constructor(deps?: Partial<RunQueryDeps>) {
186
+ this.deps = { ...defaultDeps, ...deps };
187
+ }
188
+
189
+ /**
190
+ * Mode: "projects" -- return lightweight project summaries.
191
+ * Always re-discovers to ensure all projects appear (debounced internally).
192
+ */
193
+ async listProjects(_params?: ProjectsQueryParams): Promise<ProjectsResponse> {
194
+ await this.deps.discoverAndCacheAll();
195
+ const config = await this.deps.getConfig();
196
+ const projects = this.deps.getProjectSummaries();
197
+
198
+ // Filter out hidden projects
199
+ const hiddenSet = new Set(config.hiddenProjects);
200
+ const visibleProjects = projects.filter((p) => !hiddenSet.has(p.projectName));
201
+
202
+ // Apply retention filter: exclude projects whose latest update is older than retentionDays
203
+ const retentionCutoff = Date.now() - config.retentionDays * 24 * 60 * 60 * 1000;
204
+ const retainedProjects = visibleProjects.filter(
205
+ (p) =>
206
+ // Always keep projects with active or stale runs regardless of age
207
+ p.activeRuns > 0 ||
208
+ p.staleRuns > 0 ||
209
+ new Date(p.latestUpdate).getTime() >= retentionCutoff
210
+ );
211
+
212
+ // Sort projects: active runs first, then by latest update, with
213
+ // projectName tiebreaker for deterministic ordering during rapid updates.
214
+ retainedProjects.sort((a, b) => {
215
+ if (a.activeRuns > 0 && b.activeRuns === 0) return -1;
216
+ if (a.activeRuns === 0 && b.activeRuns > 0) return 1;
217
+ const cmp = b.latestUpdate.localeCompare(a.latestUpdate);
218
+ if (cmp !== 0) return cmp;
219
+ return a.projectName.localeCompare(b.projectName);
220
+ });
221
+
222
+ return {
223
+ projects: retainedProjects,
224
+ recentCompletionWindowMs: config.recentCompletionWindowMs,
225
+ };
226
+ }
227
+
228
+ /**
229
+ * Mode: "project" -- return paginated runs for a specific project.
230
+ */
231
+ async listProjectRuns(params: ProjectRunsQueryParams): Promise<RunsListResponse> {
232
+ const { project, sort, status, search, limit, offset } = params;
233
+ const config = await this.deps.getConfig();
234
+ const allRuns = await this.deps.discoverAllRunDirs();
235
+
236
+ // Use cached runs for better performance
237
+ const runs = await Promise.all(
238
+ allRuns
239
+ .filter((r) => r.projectName === project)
240
+ .map(async ({ runDir, source, projectName }) => {
241
+ return await this.deps.getRunCached(runDir, source, projectName);
242
+ })
243
+ );
244
+
245
+ // Apply retention, sort, status filter, search, paginate
246
+ let filtered = filterByRetention(runs, config.retentionDays);
247
+ sortRuns(filtered, sort);
248
+ filtered = filterByStatus(filtered, status);
249
+ filtered = filterBySearch(filtered, search);
250
+
251
+ const totalCount = filtered.length;
252
+ const page = paginate(filtered, offset, limit);
253
+
254
+ return {
255
+ runs: toLightRuns(page),
256
+ totalCount,
257
+ project,
258
+ };
259
+ }
260
+
261
+ /**
262
+ * Default mode -- return all runs with totalCount.
263
+ */
264
+ async listAllRuns(params: RunQueryParams): Promise<RunsListResponse> {
265
+ const { sort, search, limit, offset } = params;
266
+ const allRuns = await this.deps.discoverAllRunDirs();
267
+
268
+ const runs = await Promise.all(
269
+ allRuns.map(async ({ runDir, source, projectName }) => {
270
+ return await this.deps.getRunCached(runDir, source, projectName);
271
+ })
272
+ );
273
+
274
+ // Sort, search, paginate (no retention filter on "all runs" -- matches original)
275
+ sortRuns(runs, sort);
276
+ let filtered = filterBySearch(runs, search);
277
+
278
+ const totalCount = filtered.length;
279
+ filtered = paginate(filtered, offset, limit);
280
+
281
+ return {
282
+ runs: toLightRuns(filtered),
283
+ totalCount,
284
+ };
285
+ }
286
+ }
@@ -0,0 +1,216 @@
1
+ import { promises as fs } from "fs";
2
+ import path from "path";
3
+ import { isNotFoundError, getConfig, type WatchSource } from "./config-loader";
4
+
5
+ export interface DiscoveredRun {
6
+ runDir: string;
7
+ source: WatchSource;
8
+ projectName: string; // e.g. "hockey_7_shifts", "podcast-intel"
9
+ projectPath: string; // full path to the project directory
10
+ }
11
+
12
+ // Discover all .a5c/runs/ directories within a source
13
+ async function discoverRunsInSource(source: WatchSource): Promise<string[]> {
14
+ const results: string[] = [];
15
+
16
+ async function scan(dir: string, currentDepth: number) {
17
+ try {
18
+ // Check if this directory itself IS an .a5c/runs dir (depth=0 means direct path)
19
+ if (source.depth === 0) {
20
+ const entries = await fs.readdir(dir, { withFileTypes: true });
21
+ return entries
22
+ .filter((e) => e.isDirectory())
23
+ .map((e) => path.join(dir, e.name));
24
+ }
25
+
26
+ // Check for .a5c/runs/ at this level
27
+ const runsPath = path.join(dir, ".a5c", "runs");
28
+ try {
29
+ const stat = await fs.stat(runsPath);
30
+ if (stat.isDirectory()) {
31
+ results.push(runsPath);
32
+ }
33
+ } catch {
34
+ // Expected: no .a5c/runs directory at this level — skip silently
35
+ }
36
+
37
+ // Recurse into subdirectories if within depth
38
+ if (currentDepth < source.depth) {
39
+ const entries = await fs.readdir(dir, { withFileTypes: true });
40
+ for (const entry of entries) {
41
+ if (
42
+ entry.isDirectory() &&
43
+ !entry.name.startsWith(".") &&
44
+ entry.name !== "node_modules"
45
+ ) {
46
+ await scan(path.join(dir, entry.name), currentDepth + 1);
47
+ }
48
+ }
49
+ }
50
+ } catch (err) {
51
+ if (!isNotFoundError(err)) {
52
+ console.warn(`[config] Cannot scan directory ${dir} (depth=${currentDepth}):`, err);
53
+ }
54
+ }
55
+ }
56
+
57
+ if (source.depth === 0) {
58
+ // Direct .a5c/runs path — just return runs inside it
59
+ try {
60
+ const entries = await fs.readdir(source.path, { withFileTypes: true });
61
+ return entries
62
+ .filter((e) => e.isDirectory())
63
+ .map((e) => path.join(source.path, e.name));
64
+ } catch (err) {
65
+ console.warn(`[config] Cannot list runs in direct source ${source.path}:`, err);
66
+ return [];
67
+ }
68
+ }
69
+
70
+ await scan(source.path, 0);
71
+ return results;
72
+ }
73
+
74
+ // Extract project name from a .a5c/runs/ path
75
+ function extractProjectName(runsDir: string): { projectName: string; projectPath: string } {
76
+ // runsDir is like /path/to/project/.a5c/runs
77
+ // projectPath is /path/to/project
78
+ const a5cDir = path.dirname(runsDir); // .a5c
79
+ const projectPath = path.dirname(a5cDir); // project dir
80
+ const projectName = path.basename(projectPath);
81
+ return { projectName, projectPath };
82
+ }
83
+
84
+ // Cache discovery results to avoid repeated filesystem scanning
85
+ let discoveryCache: DiscoveredRun[] = [];
86
+ let discoveryCacheTime = 0;
87
+ const DISCOVERY_CACHE_TTL = 10000; // 10s — watcher handles real-time changes
88
+
89
+ // Force re-discovery on next call (called when new runs are detected by watcher)
90
+ export function invalidateDiscoveryCache(): void {
91
+ discoveryCache = [];
92
+ discoveryCacheTime = 0;
93
+ }
94
+
95
+ // Get all run directories across all sources
96
+ export async function discoverAllRunDirs(): Promise<DiscoveredRun[]> {
97
+ const now = Date.now();
98
+ if (discoveryCache.length > 0 && now - discoveryCacheTime < DISCOVERY_CACHE_TTL) {
99
+ return discoveryCache;
100
+ }
101
+
102
+ const config = await getConfig();
103
+ const allRuns: DiscoveredRun[] = [];
104
+
105
+ for (const source of config.sources) {
106
+ if (source.depth === 0) {
107
+ // Direct runs directory — list subdirs as individual runs
108
+ // Project name: prefer run.json's projectName, fall back to source label or path
109
+ const fallbackProjectName = source.label || path.basename(source.path);
110
+ try {
111
+ const entries = await fs.readdir(source.path, { withFileTypes: true });
112
+ for (const entry of entries) {
113
+ if (entry.isDirectory()) {
114
+ // Try to read projectName from run.json for more accurate project grouping
115
+ let projectName = fallbackProjectName;
116
+ try {
117
+ const runJsonPath = path.join(source.path, entry.name, "run.json");
118
+ const content = await fs.readFile(runJsonPath, "utf-8");
119
+ const json = JSON.parse(content);
120
+ if (json.projectName) {
121
+ projectName = json.projectName;
122
+ }
123
+ } catch (err) {
124
+ // run.json missing is expected for new runs; warn only on parse/permission errors
125
+ if (!isNotFoundError(err)) {
126
+ console.warn(`[config] Failed to read run.json in ${path.join(source.path, entry.name)} — using fallback project name:`, err);
127
+ }
128
+ }
129
+ allRuns.push({
130
+ runDir: path.join(source.path, entry.name),
131
+ source,
132
+ projectName,
133
+ projectPath: source.path,
134
+ });
135
+ }
136
+ }
137
+ } catch (err) {
138
+ console.warn(`[config] Source directory not accessible ${source.path}:`, err);
139
+ }
140
+ } else {
141
+ // Discover .a5c/runs/ directories within depth
142
+ const runsDirs = await discoverRunsInSource(source);
143
+ for (const runsDir of runsDirs) {
144
+ const { projectName, projectPath } = extractProjectName(runsDir);
145
+ try {
146
+ const entries = await fs.readdir(runsDir, { withFileTypes: true });
147
+ for (const entry of entries) {
148
+ if (entry.isDirectory()) {
149
+ allRuns.push({
150
+ runDir: path.join(runsDir, entry.name),
151
+ source,
152
+ projectName,
153
+ projectPath,
154
+ });
155
+ }
156
+ }
157
+ } catch (err) {
158
+ console.warn(`[config] Cannot read runs directory ${runsDir}:`, err);
159
+ }
160
+ }
161
+ }
162
+ }
163
+
164
+ // Deduplicate by runId (basename of runDir). When the same run ID appears
165
+ // under multiple .a5c/runs/ directories (e.g. a "ghost" .a5c created by a
166
+ // task execution in a subdirectory), keep the first occurrence — which is
167
+ // the shallowest/earliest discovered and typically the one with full data
168
+ // (run.json + journal).
169
+ const seenRunIds = new Map<string, DiscoveredRun>();
170
+ for (const run of allRuns) {
171
+ const runId = path.basename(run.runDir);
172
+ if (!seenRunIds.has(runId)) {
173
+ seenRunIds.set(runId, run);
174
+ } else {
175
+ // Prefer the run directory that has a run.json (i.e. the real one)
176
+ const existing = seenRunIds.get(runId)!;
177
+ const existingHasRunJson = await fs.access(path.join(existing.runDir, "run.json")).then(() => true, () => false);
178
+ if (!existingHasRunJson) {
179
+ const candidateHasRunJson = await fs.access(path.join(run.runDir, "run.json")).then(() => true, () => false);
180
+ if (candidateHasRunJson) {
181
+ seenRunIds.set(runId, run);
182
+ }
183
+ }
184
+ }
185
+ }
186
+
187
+ const result = Array.from(seenRunIds.values());
188
+ discoveryCache = result;
189
+ discoveryCacheTime = Date.now();
190
+ return result;
191
+ }
192
+
193
+ // Discover all .a5c/runs/ parent directories (including empty ones).
194
+ // Used by the watcher to set up watches on directories that don't have runs yet,
195
+ // so that the very first run in a new project is detected immediately.
196
+ export async function discoverAllRunsParentDirs(): Promise<string[]> {
197
+ const config = await getConfig();
198
+ const allDirs: string[] = [];
199
+
200
+ for (const source of config.sources) {
201
+ if (source.depth === 0) {
202
+ // Direct runs path — watch the source path itself
203
+ try {
204
+ await fs.access(source.path);
205
+ allDirs.push(source.path);
206
+ } catch (err) {
207
+ console.warn(`[config] Watch source path not accessible ${source.path}:`, err);
208
+ }
209
+ } else {
210
+ const runsDirs = await discoverRunsInSource(source);
211
+ allDirs.push(...runsDirs);
212
+ }
213
+ }
214
+
215
+ return allDirs;
216
+ }
@@ -0,0 +1,103 @@
1
+ export function formatDuration(ms: number | undefined | null): string {
2
+ if (ms == null || ms < 0) return "\u2014";
3
+ if (ms === 0) return "<1s";
4
+ if (ms < 1000) return `${ms}ms`;
5
+ const seconds = Math.floor(ms / 1000);
6
+ if (seconds < 60) return `${seconds}s`;
7
+ const minutes = Math.floor(seconds / 60);
8
+ const remainingSeconds = seconds % 60;
9
+ if (minutes < 60) return `${minutes}m ${remainingSeconds}s`;
10
+ const hours = Math.floor(minutes / 60);
11
+ const remainingMinutes = minutes % 60;
12
+ return `${hours}h ${remainingMinutes}m`;
13
+ }
14
+
15
+ export function formatTimestamp(iso: string | undefined): string {
16
+ if (!iso) return "\u2014";
17
+ try {
18
+ const d = new Date(iso);
19
+ return d.toLocaleTimeString("en-US", {
20
+ hour12: false,
21
+ hour: "2-digit",
22
+ minute: "2-digit",
23
+ second: "2-digit",
24
+ });
25
+ } catch {
26
+ return "\u2014";
27
+ }
28
+ }
29
+
30
+ export function formatRelativeTime(iso: string | undefined): string {
31
+ if (!iso) return "";
32
+ try {
33
+ const diff = Date.now() - new Date(iso).getTime();
34
+ if (diff < 0) return "just now";
35
+ if (diff < 5000) return "just now";
36
+ if (diff < 60000) return `${Math.floor(diff / 1000)}s ago`;
37
+ if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`;
38
+ if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`;
39
+ return `${Math.floor(diff / 86400000)}d ago`;
40
+ } catch {
41
+ return "";
42
+ }
43
+ }
44
+
45
+ export function truncateId(id: string, len: number = 12): string {
46
+ if (!id) return "\u2014";
47
+ if (id.length <= len) return id;
48
+ return id.slice(0, len) + "...";
49
+ }
50
+
51
+ export function getStatusColor(status: string): string {
52
+ switch (status) {
53
+ case "completed":
54
+ case "resolved":
55
+ case "ok":
56
+ return "text-success";
57
+ case "failed":
58
+ case "error":
59
+ return "text-error";
60
+ case "waiting":
61
+ case "pending":
62
+ return "text-pending";
63
+ case "running":
64
+ case "requested":
65
+ return "text-info";
66
+ default:
67
+ return "text-foreground-muted";
68
+ }
69
+ }
70
+
71
+ export function getStatusBg(status: string): string {
72
+ switch (status) {
73
+ case "completed":
74
+ case "resolved":
75
+ case "ok":
76
+ return "bg-success-muted";
77
+ case "failed":
78
+ case "error":
79
+ return "bg-error-muted";
80
+ case "waiting":
81
+ case "pending":
82
+ return "bg-pending-muted";
83
+ case "running":
84
+ case "requested":
85
+ return "bg-info-muted";
86
+ default:
87
+ return "bg-muted";
88
+ }
89
+ }
90
+
91
+ export function formatShortId(id: string, chars: number = 4): string {
92
+ if (!id) return '—';
93
+ if (id.length <= chars) return id;
94
+ return '...' + id.slice(-chars);
95
+ }
96
+
97
+ export function friendlyProcessName(processId: string): string {
98
+ if (!processId) return '';
99
+ return processId
100
+ .split(/[-/]/)
101
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
102
+ .join(' ');
103
+ }