@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.
- package/.next/BUILD_ID +1 -0
- package/.next/app-path-routes-manifest.json +16 -0
- package/.next/build-manifest.json +23 -0
- package/.next/export-marker.json +6 -0
- package/.next/fallback-build-manifest.json +13 -0
- package/.next/images-manifest.json +68 -0
- package/.next/next-minimal-server.js.nft.json +1 -0
- package/.next/next-server.js.nft.json +1 -0
- package/.next/package.json +1 -0
- package/.next/prerender-manifest.json +114 -0
- package/.next/required-server-files.json +334 -0
- package/.next/routes-manifest.json +139 -0
- package/.next/server/app/_global-error/page/app-paths-manifest.json +3 -0
- package/.next/server/app/_global-error/page/build-manifest.json +19 -0
- package/.next/server/app/_global-error/page/next-font-manifest.json +6 -0
- package/.next/server/app/_global-error/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/_global-error/page/server-reference-manifest.json +4 -0
- package/.next/server/app/_global-error/page.js +9 -0
- package/.next/server/app/_global-error/page.js.map +5 -0
- package/.next/server/app/_global-error/page.js.nft.json +1 -0
- package/.next/server/app/_global-error/page_client-reference-manifest.js +3 -0
- package/.next/server/app/_global-error.html +1 -0
- package/.next/server/app/_global-error.meta +15 -0
- package/.next/server/app/_global-error.rsc +14 -0
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +5 -0
- package/.next/server/app/_global-error.segments/_full.segment.rsc +14 -0
- package/.next/server/app/_global-error.segments/_head.segment.rsc +5 -0
- package/.next/server/app/_global-error.segments/_index.segment.rsc +5 -0
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -0
- package/.next/server/app/_not-found/page/app-paths-manifest.json +3 -0
- package/.next/server/app/_not-found/page/build-manifest.json +19 -0
- package/.next/server/app/_not-found/page/next-font-manifest.json +6 -0
- package/.next/server/app/_not-found/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/_not-found/page/server-reference-manifest.json +4 -0
- package/.next/server/app/_not-found/page.js +13 -0
- package/.next/server/app/_not-found/page.js.map +5 -0
- package/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/.next/server/app/_not-found/page_client-reference-manifest.js +3 -0
- package/.next/server/app/_not-found.html +1 -0
- package/.next/server/app/_not-found.meta +16 -0
- package/.next/server/app/_not-found.rsc +19 -0
- package/.next/server/app/_not-found.segments/_full.segment.rsc +19 -0
- package/.next/server/app/_not-found.segments/_head.segment.rsc +6 -0
- package/.next/server/app/_not-found.segments/_index.segment.rsc +8 -0
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +6 -0
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +5 -0
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -0
- package/.next/server/app/api/config/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/config/route/build-manifest.json +9 -0
- package/.next/server/app/api/config/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/config/route.js +8 -0
- package/.next/server/app/api/config/route.js.map +5 -0
- package/.next/server/app/api/config/route.js.nft.json +1 -0
- package/.next/server/app/api/config/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/digest/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/digest/route/build-manifest.json +9 -0
- package/.next/server/app/api/digest/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/digest/route.js +9 -0
- package/.next/server/app/api/digest/route.js.map +5 -0
- package/.next/server/app/api/digest/route.js.nft.json +1 -0
- package/.next/server/app/api/digest/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/runs/[runId]/events/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/runs/[runId]/events/route/build-manifest.json +9 -0
- package/.next/server/app/api/runs/[runId]/events/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/runs/[runId]/events/route.js +8 -0
- package/.next/server/app/api/runs/[runId]/events/route.js.map +5 -0
- package/.next/server/app/api/runs/[runId]/events/route.js.nft.json +1 -0
- package/.next/server/app/api/runs/[runId]/events/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/runs/[runId]/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/runs/[runId]/route/build-manifest.json +9 -0
- package/.next/server/app/api/runs/[runId]/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/runs/[runId]/route.js +9 -0
- package/.next/server/app/api/runs/[runId]/route.js.map +5 -0
- package/.next/server/app/api/runs/[runId]/route.js.nft.json +1 -0
- package/.next/server/app/api/runs/[runId]/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/runs/[runId]/tasks/[effectId]/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/runs/[runId]/tasks/[effectId]/route/build-manifest.json +9 -0
- package/.next/server/app/api/runs/[runId]/tasks/[effectId]/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/runs/[runId]/tasks/[effectId]/route.js +8 -0
- package/.next/server/app/api/runs/[runId]/tasks/[effectId]/route.js.map +5 -0
- package/.next/server/app/api/runs/[runId]/tasks/[effectId]/route.js.nft.json +1 -0
- package/.next/server/app/api/runs/[runId]/tasks/[effectId]/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/runs/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/runs/route/build-manifest.json +9 -0
- package/.next/server/app/api/runs/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/runs/route.js +9 -0
- package/.next/server/app/api/runs/route.js.map +5 -0
- package/.next/server/app/api/runs/route.js.nft.json +1 -0
- package/.next/server/app/api/runs/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/stream/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/stream/route/build-manifest.json +9 -0
- package/.next/server/app/api/stream/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/stream/route.js +8 -0
- package/.next/server/app/api/stream/route.js.map +5 -0
- package/.next/server/app/api/stream/route.js.nft.json +1 -0
- package/.next/server/app/api/stream/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/test/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/test/route/build-manifest.json +9 -0
- package/.next/server/app/api/test/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/test/route.js +6 -0
- package/.next/server/app/api/test/route.js.map +5 -0
- package/.next/server/app/api/test/route.js.nft.json +1 -0
- package/.next/server/app/api/test/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/version/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/version/route/build-manifest.json +9 -0
- package/.next/server/app/api/version/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/version/route.js +7 -0
- package/.next/server/app/api/version/route.js.map +5 -0
- package/.next/server/app/api/version/route.js.nft.json +1 -0
- package/.next/server/app/api/version/route_client-reference-manifest.js +3 -0
- package/.next/server/app/icon.svg/route/app-paths-manifest.json +3 -0
- package/.next/server/app/icon.svg/route/build-manifest.json +9 -0
- package/.next/server/app/icon.svg/route.js +7 -0
- package/.next/server/app/icon.svg/route.js.map +5 -0
- package/.next/server/app/icon.svg/route.js.nft.json +1 -0
- package/.next/server/app/icon.svg.body +20 -0
- package/.next/server/app/icon.svg.meta +1 -0
- package/.next/server/app/index.html +1 -0
- package/.next/server/app/index.meta +14 -0
- package/.next/server/app/index.rsc +21 -0
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +9 -0
- package/.next/server/app/index.segments/_full.segment.rsc +21 -0
- package/.next/server/app/index.segments/_head.segment.rsc +6 -0
- package/.next/server/app/index.segments/_index.segment.rsc +8 -0
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -0
- package/.next/server/app/page/app-paths-manifest.json +3 -0
- package/.next/server/app/page/build-manifest.json +19 -0
- package/.next/server/app/page/next-font-manifest.json +6 -0
- package/.next/server/app/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/page/server-reference-manifest.json +17 -0
- package/.next/server/app/page.js +15 -0
- package/.next/server/app/page.js.map +5 -0
- package/.next/server/app/page.js.nft.json +1 -0
- package/.next/server/app/page_client-reference-manifest.js +3 -0
- package/.next/server/app/runs/[runId]/page/app-paths-manifest.json +3 -0
- package/.next/server/app/runs/[runId]/page/build-manifest.json +19 -0
- package/.next/server/app/runs/[runId]/page/next-font-manifest.json +6 -0
- package/.next/server/app/runs/[runId]/page/react-loadable-manifest.json +22 -0
- package/.next/server/app/runs/[runId]/page/server-reference-manifest.json +17 -0
- package/.next/server/app/runs/[runId]/page.js +15 -0
- package/.next/server/app/runs/[runId]/page.js.map +5 -0
- package/.next/server/app/runs/[runId]/page.js.nft.json +1 -0
- package/.next/server/app/runs/[runId]/page_client-reference-manifest.js +3 -0
- package/.next/server/app-paths-manifest.json +16 -0
- package/.next/server/chunks/01oi_server_app_api_runs_[runId]_tasks_[effectId]_route_actions_0r72yai.js +3 -0
- package/.next/server/chunks/01oi_server_app_api_runs_[runId]_tasks_[effectId]_route_actions_0r72yai.js.map +1 -0
- package/.next/server/chunks/0h.v__next-internal_server_app_api_runs_[runId]_events_route_actions_0~msldk.js +3 -0
- package/.next/server/chunks/0h.v__next-internal_server_app_api_runs_[runId]_events_route_actions_0~msldk.js.map +1 -0
- package/.next/server/chunks/0h.v__next-internal_server_app_api_runs_[runId]_route_actions_09iz0n6.js +3 -0
- package/.next/server/chunks/0h.v__next-internal_server_app_api_runs_[runId]_route_actions_09iz0n6.js.map +1 -0
- package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_config_route_actions_0~eypoa.js +3 -0
- package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_config_route_actions_0~eypoa.js.map +1 -0
- package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_digest_route_actions_04jj5zs.js +3 -0
- package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_digest_route_actions_04jj5zs.js.map +1 -0
- package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_runs_route_actions_0~-t-o4.js +3 -0
- package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_runs_route_actions_0~-t-o4.js.map +1 -0
- package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_stream_route_actions_0fkmv2_.js +3 -0
- package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_stream_route_actions_0fkmv2_.js.map +1 -0
- package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_test_route_actions_00ugava.js +3 -0
- package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_test_route_actions_00ugava.js.map +1 -0
- package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_version_route_actions_0~v3ojm.js +3 -0
- package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_api_version_route_actions_0~v3ojm.js.map +1 -0
- package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_icon_svg_route_actions_0yypxkm.js +3 -0
- package/.next/server/chunks/0juq_observer-dashboard__next-internal_server_app_icon_svg_route_actions_0yypxkm.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0.6bt.6._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0.6bt.6._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__08kwev1._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__08kwev1._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__096el.d._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__096el.d._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0_bmt4z._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0_bmt4z._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0_ln2d2._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0_ln2d2._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0al3v65._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0al3v65._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0gf516b._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0gf516b._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0kdfw4x._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0kdfw4x._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0pxt00h._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0pxt00h._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0rubnza._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0rubnza._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0tn9iud._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0tn9iud._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0ws5o6i._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0ws5o6i._.js.map +1 -0
- package/.next/server/chunks/[turbopack]_runtime.js +903 -0
- package/.next/server/chunks/[turbopack]_runtime.js.map +11 -0
- package/.next/server/chunks/node_modules_next_04~_e52._.js +13 -0
- package/.next/server/chunks/node_modules_next_04~_e52._.js.map +1 -0
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0nyyph-.js +9 -0
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0nyyph-.js.map +1 -0
- package/.next/server/chunks/packages_observer-dashboard_src_lib_02.vvb.._.js +3 -0
- package/.next/server/chunks/packages_observer-dashboard_src_lib_02.vvb.._.js.map +1 -0
- package/.next/server/chunks/packages_observer-dashboard_src_lib_0rqgpk0._.js +3 -0
- package/.next/server/chunks/packages_observer-dashboard_src_lib_0rqgpk0._.js.map +1 -0
- package/.next/server/chunks/ssr/0juq_observer-dashboard__next-internal_server_app__global-error_page_actions_0ekoxmy.js +3 -0
- package/.next/server/chunks/ssr/0juq_observer-dashboard__next-internal_server_app__global-error_page_actions_0ekoxmy.js.map +1 -0
- package/.next/server/chunks/ssr/0juq_observer-dashboard__next-internal_server_app__not-found_page_actions_09b3ti3.js +3 -0
- package/.next/server/chunks/ssr/0juq_observer-dashboard__next-internal_server_app__not-found_page_actions_09b3ti3.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__006f7~t._.js +4 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__006f7~t._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__02jgvbi._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__02jgvbi._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__04j8t~1._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__04j8t~1._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__09c~s.0._.js +33 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__09c~s.0._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0cpy61n._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0cpy61n._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0cwa32j._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0cwa32j._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0fk_g0j._.js +19 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0fk_g0j._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0pddpic._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0pddpic._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0pvtneq._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0pvtneq._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0xc-2vm._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0xc-2vm._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__10xgshr._.js +33 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__10xgshr._.js.map +1 -0
- package/.next/server/chunks/ssr/[turbopack]_runtime.js +903 -0
- package/.next/server/chunks/ssr/[turbopack]_runtime.js.map +11 -0
- package/.next/server/chunks/ssr/_00yo1im._.js +3 -0
- package/.next/server/chunks/ssr/_00yo1im._.js.map +1 -0
- package/.next/server/chunks/ssr/_03sbc.o._.js +3 -0
- package/.next/server/chunks/ssr/_03sbc.o._.js.map +1 -0
- package/.next/server/chunks/ssr/_04z5ea0._.js +3 -0
- package/.next/server/chunks/ssr/_04z5ea0._.js.map +1 -0
- package/.next/server/chunks/ssr/_0gmb3g_._.js +3 -0
- package/.next/server/chunks/ssr/_0gmb3g_._.js.map +1 -0
- package/.next/server/chunks/ssr/_0okz9j8._.js +6 -0
- package/.next/server/chunks/ssr/_0okz9j8._.js.map +1 -0
- package/.next/server/chunks/ssr/_0wrbwro._.js +6 -0
- package/.next/server/chunks/ssr/_0wrbwro._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_09w7yel._.js +33 -0
- package/.next/server/chunks/ssr/node_modules_09w7yel._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_0avqw4q._.js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_0avqw4q._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_0h9llsw._.js +6 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_0h9llsw._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_0i_._k3._.js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_0i_._k3._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_0ee1czk._.js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_0ee1czk._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_0lgvd_..js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_0lgvd_..js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_unauthorized_0cjv-23.js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_unauthorized_0cjv-23.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0amzg6z.js +4 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0amzg6z.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0dw1x0d.js +4 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0dw1x0d.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0rc3ul_.js +4 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0rc3ul_.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_10iomok.js +4 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_10iomok.js.map +1 -0
- package/.next/server/chunks/ssr/packages_observer-dashboard_0~a2tmu._.js +3 -0
- package/.next/server/chunks/ssr/packages_observer-dashboard_0~a2tmu._.js.map +1 -0
- package/.next/server/chunks/ssr/packages_observer-dashboard_src_0f.ozc-._.js +3 -0
- package/.next/server/chunks/ssr/packages_observer-dashboard_src_0f.ozc-._.js.map +1 -0
- package/.next/server/chunks/ssr/packages_observer-dashboard_src_components_providers_tsx_03_vrrn._.js +7 -0
- package/.next/server/chunks/ssr/packages_observer-dashboard_src_components_providers_tsx_03_vrrn._.js.map +1 -0
- package/.next/server/functions-config-manifest.json +4 -0
- package/.next/server/interception-route-rewrite-manifest.js +1 -0
- package/.next/server/middleware-build-manifest.js +23 -0
- package/.next/server/middleware-manifest.json +6 -0
- package/.next/server/next-font-manifest.js +1 -0
- package/.next/server/next-font-manifest.json +6 -0
- package/.next/server/pages/404.html +1 -0
- package/.next/server/pages/500.html +1 -0
- package/.next/server/pages-manifest.json +4 -0
- package/.next/server/prefetch-hints.json +1 -0
- package/.next/server/server-reference-manifest.js +1 -0
- package/.next/server/server-reference-manifest.json +24 -0
- package/.next/static/MvfPly4ZXHqaveDVOG1qq/_buildManifest.js +11 -0
- package/.next/static/MvfPly4ZXHqaveDVOG1qq/_clientMiddlewareManifest.js +1 -0
- package/.next/static/MvfPly4ZXHqaveDVOG1qq/_ssgManifest.js +1 -0
- package/.next/static/chunks/00c87uqn~kk2z.js +1 -0
- package/.next/static/chunks/01xlw8hd842-c.js +1 -0
- package/.next/static/chunks/02p9dpa.0oxiz.js +1 -0
- package/.next/static/chunks/034i63v_muq~d.js +1 -0
- package/.next/static/chunks/03mo-6~4pxdio.js +1 -0
- package/.next/static/chunks/03~yq9q893hmn.js +1 -0
- package/.next/static/chunks/04dm5qn77.fc2.js +1 -0
- package/.next/static/chunks/07uz2g0_38qia.js +4 -0
- package/.next/static/chunks/08nqnwvixoxnk.js +2 -0
- package/.next/static/chunks/0d3shmwh5_nmn.js +1 -0
- package/.next/static/chunks/0e_wyjw3nx.a..js +1 -0
- package/.next/static/chunks/0mstyq17cbf8-.js +1 -0
- package/.next/static/chunks/0ntuxw9.how-q.js +1 -0
- package/.next/static/chunks/0t3uzajv1qzmo.js +1 -0
- package/.next/static/chunks/0u~_nwr5-v.xp.js +1 -0
- package/.next/static/chunks/0wxcxh6eyzams.js +1 -0
- package/.next/static/chunks/0x6y7yt4kiddp.css +1 -0
- package/.next/static/chunks/0z6-vonyxr0dn.js +4 -0
- package/.next/static/chunks/0ze4gu236oq96.js +31 -0
- package/.next/static/chunks/0zwozael9msy1.js +1 -0
- package/.next/static/chunks/10qd__0r7a~.l.js +1 -0
- package/.next/static/chunks/11jh_u1ynmatg.js +1 -0
- package/.next/static/chunks/13xer3cb9shu-.js +5 -0
- package/.next/static/chunks/142zlnch_xmgd.js +1 -0
- package/.next/static/chunks/144kcri75qczu.js +1 -0
- package/.next/static/chunks/turbopack-0-ww6fe7b37qt.js +1 -0
- package/.next/static/media/icon.08ljfy7xai2x_.svg +20 -0
- package/LICENSE +21 -0
- package/README.md +490 -0
- package/next.config.mjs +25 -0
- package/package.json +104 -0
- package/postcss.config.mjs +8 -0
- package/src/app/actions/__tests__/approve-breakpoint.test.ts +246 -0
- package/src/app/actions/approve-breakpoint.ts +145 -0
- package/src/app/api/config/route.ts +137 -0
- package/src/app/api/digest/route.ts +45 -0
- package/src/app/api/runs/[runId]/events/route.ts +56 -0
- package/src/app/api/runs/[runId]/route.ts +84 -0
- package/src/app/api/runs/[runId]/tasks/[effectId]/route.ts +44 -0
- package/src/app/api/runs/route.ts +48 -0
- package/src/app/api/stream/route.ts +136 -0
- package/src/app/api/test/route.ts +1 -0
- package/src/app/api/version/route.ts +57 -0
- package/src/app/globals.css +555 -0
- package/src/app/icon.svg +20 -0
- package/src/app/layout.tsx +39 -0
- package/src/app/not-found.tsx +16 -0
- package/src/app/page.tsx +120 -0
- package/src/app/runs/[runId]/page.tsx +279 -0
- package/src/cli.ts +271 -0
- package/src/components/breakpoint/__tests__/breakpoint-approval.test.tsx +212 -0
- package/src/components/breakpoint/__tests__/breakpoint-panel.test.tsx +130 -0
- package/src/components/breakpoint/__tests__/file-preview.test.tsx +313 -0
- package/src/components/breakpoint/breakpoint-approval.tsx +138 -0
- package/src/components/breakpoint/breakpoint-panel.tsx +95 -0
- package/src/components/breakpoint/file-preview.tsx +215 -0
- package/src/components/dashboard/.gitkeep +0 -0
- package/src/components/dashboard/__tests__/breakpoint-banner.test.tsx +177 -0
- package/src/components/dashboard/__tests__/catch-up-banner.test.tsx +141 -0
- package/src/components/dashboard/__tests__/executive-summary-banner.test.tsx +164 -0
- package/src/components/dashboard/__tests__/kpi-grid.test.tsx +101 -0
- package/src/components/dashboard/__tests__/pagination-controls.test.tsx +125 -0
- package/src/components/dashboard/__tests__/project-accordion.test.tsx +97 -0
- package/src/components/dashboard/__tests__/project-list-view.test.tsx +174 -0
- package/src/components/dashboard/__tests__/project-search-input.test.tsx +110 -0
- package/src/components/dashboard/__tests__/project-section-header.test.tsx +91 -0
- package/src/components/dashboard/__tests__/project-section.test.tsx +151 -0
- package/src/components/dashboard/__tests__/run-card.test.tsx +164 -0
- package/src/components/dashboard/__tests__/run-filter-bar.test.tsx +109 -0
- package/src/components/dashboard/__tests__/run-list.test.tsx +123 -0
- package/src/components/dashboard/__tests__/search-filter.test.tsx +150 -0
- package/src/components/dashboard/__tests__/virtualized-run-list.test.tsx +179 -0
- package/src/components/dashboard/breakpoint-banner.tsx +301 -0
- package/src/components/dashboard/catch-up-banner.tsx +88 -0
- package/src/components/dashboard/executive-summary-banner.tsx +174 -0
- package/src/components/dashboard/global-search.tsx +323 -0
- package/src/components/dashboard/kpi-grid.tsx +140 -0
- package/src/components/dashboard/pagination-controls.tsx +100 -0
- package/src/components/dashboard/project-accordion.tsx +72 -0
- package/src/components/dashboard/project-health-card.tsx +536 -0
- package/src/components/dashboard/project-list-view.tsx +246 -0
- package/src/components/dashboard/project-search-input.tsx +41 -0
- package/src/components/dashboard/project-section-header.tsx +73 -0
- package/src/components/dashboard/project-section.tsx +89 -0
- package/src/components/dashboard/run-card.tsx +218 -0
- package/src/components/dashboard/run-filter-bar.tsx +100 -0
- package/src/components/dashboard/run-list.tsx +77 -0
- package/src/components/dashboard/search-filter.tsx +69 -0
- package/src/components/dashboard/virtualized-run-list.tsx +130 -0
- package/src/components/details/.gitkeep +0 -0
- package/src/components/details/__tests__/agent-panel.test.tsx +236 -0
- package/src/components/details/__tests__/json-tree.test.tsx +347 -0
- package/src/components/details/__tests__/log-viewer.test.tsx +168 -0
- package/src/components/details/__tests__/task-detail.test.tsx +212 -0
- package/src/components/details/__tests__/timing-panel.test.tsx +271 -0
- package/src/components/details/agent-panel.tsx +234 -0
- package/src/components/details/json-tree/categorize.ts +131 -0
- package/src/components/details/json-tree/index.tsx +120 -0
- package/src/components/details/json-tree/json-node.tsx +223 -0
- package/src/components/details/json-tree/smart-summary.tsx +596 -0
- package/src/components/details/json-tree/tree-controls.tsx +47 -0
- package/src/components/details/json-tree.tsx +9 -0
- package/src/components/details/log-viewer.tsx +140 -0
- package/src/components/details/task-detail.tsx +114 -0
- package/src/components/details/timing-panel.tsx +247 -0
- package/src/components/events/.gitkeep +0 -0
- package/src/components/events/__tests__/event-item.test.tsx +211 -0
- package/src/components/events/__tests__/event-stream.test.tsx +225 -0
- package/src/components/events/event-item.tsx +121 -0
- package/src/components/events/event-stream.tsx +260 -0
- package/src/components/notifications/.gitkeep +0 -0
- package/src/components/notifications/__tests__/notification-panel.test.tsx +287 -0
- package/src/components/notifications/__tests__/notification-provider.test.tsx +585 -0
- package/src/components/notifications/__tests__/toast-stack.test.tsx +217 -0
- package/src/components/notifications/notification-panel.tsx +124 -0
- package/src/components/notifications/notification-provider.tsx +175 -0
- package/src/components/notifications/toast-stack.tsx +75 -0
- package/src/components/pipeline/.gitkeep +0 -0
- package/src/components/pipeline/__tests__/parallel-group.test.tsx +88 -0
- package/src/components/pipeline/__tests__/pipeline-view.test.tsx +345 -0
- package/src/components/pipeline/__tests__/step-card.test.tsx +330 -0
- package/src/components/pipeline/parallel-group.tsx +39 -0
- package/src/components/pipeline/pipeline-view.tsx +197 -0
- package/src/components/pipeline/step-card.tsx +166 -0
- package/src/components/providers/event-stream-provider.tsx +29 -0
- package/src/components/providers.tsx +24 -0
- package/src/components/shared/.gitkeep +0 -0
- package/src/components/shared/__tests__/empty-state.test.tsx +49 -0
- package/src/components/shared/__tests__/friendly-id.test.tsx +47 -0
- package/src/components/shared/__tests__/kbd.test.tsx +45 -0
- package/src/components/shared/__tests__/kind-badge.test.tsx +71 -0
- package/src/components/shared/__tests__/metrics-row.test.tsx +74 -0
- package/src/components/shared/__tests__/outcome-banner.test.tsx +71 -0
- package/src/components/shared/__tests__/progress-bar.test.tsx +89 -0
- package/src/components/shared/__tests__/session-pill.test.tsx +62 -0
- package/src/components/shared/__tests__/settings-modal.test.tsx +201 -0
- package/src/components/shared/__tests__/shortcuts-help.test.tsx +103 -0
- package/src/components/shared/__tests__/status-badge.test.tsx +98 -0
- package/src/components/shared/__tests__/theme-provider.test.tsx +100 -0
- package/src/components/shared/__tests__/truncated-id.test.tsx +53 -0
- package/src/components/shared/app-footer.tsx +80 -0
- package/src/components/shared/app-header.tsx +160 -0
- package/src/components/shared/empty-state.tsx +18 -0
- package/src/components/shared/error-boundary.tsx +81 -0
- package/src/components/shared/friendly-id.tsx +48 -0
- package/src/components/shared/kbd.tsx +15 -0
- package/src/components/shared/kind-badge.tsx +51 -0
- package/src/components/shared/metrics-row.tsx +106 -0
- package/src/components/shared/outcome-banner.tsx +56 -0
- package/src/components/shared/progress-bar.tsx +42 -0
- package/src/components/shared/session-pill.tsx +69 -0
- package/src/components/shared/settings-modal.tsx +509 -0
- package/src/components/shared/shortcuts-help.tsx +113 -0
- package/src/components/shared/status-badge.tsx +110 -0
- package/src/components/shared/theme-provider.tsx +46 -0
- package/src/components/shared/truncated-id.tsx +51 -0
- package/src/components/ui/.gitkeep +0 -0
- package/src/components/ui/__tests__/accordion.test.tsx +96 -0
- package/src/components/ui/__tests__/badge.test.tsx +69 -0
- package/src/components/ui/__tests__/button.test.tsx +113 -0
- package/src/components/ui/__tests__/tabs.test.tsx +75 -0
- package/src/components/ui/__tests__/tooltip.test.tsx +90 -0
- package/src/components/ui/accordion.tsx +61 -0
- package/src/components/ui/badge.tsx +25 -0
- package/src/components/ui/button.tsx +40 -0
- package/src/components/ui/card.tsx +21 -0
- package/src/components/ui/scroll-area.tsx +35 -0
- package/src/components/ui/separator.tsx +24 -0
- package/src/components/ui/tabs.tsx +64 -0
- package/src/components/ui/tooltip.tsx +37 -0
- package/src/hooks/.gitkeep +0 -0
- package/src/hooks/__tests__/use-animated-number.test.ts +184 -0
- package/src/hooks/__tests__/use-batched-updates.test.ts +315 -0
- package/src/hooks/__tests__/use-event-stream.test.ts +243 -0
- package/src/hooks/__tests__/use-keyboard.test.ts +217 -0
- package/src/hooks/__tests__/use-notifications.test.ts +230 -0
- package/src/hooks/__tests__/use-polling.test.ts +274 -0
- package/src/hooks/__tests__/use-project-runs.test.ts +163 -0
- package/src/hooks/__tests__/use-projects.test.ts +248 -0
- package/src/hooks/__tests__/use-run-dashboard.test.ts +168 -0
- package/src/hooks/__tests__/use-run-detail.test.ts +273 -0
- package/src/hooks/__tests__/use-smart-polling.test.ts +305 -0
- package/src/hooks/use-animated-number.ts +87 -0
- package/src/hooks/use-batched-updates.ts +150 -0
- package/src/hooks/use-event-stream.ts +150 -0
- package/src/hooks/use-keyboard.ts +45 -0
- package/src/hooks/use-notifications.ts +82 -0
- package/src/hooks/use-persisted-state.ts +60 -0
- package/src/hooks/use-polling.ts +60 -0
- package/src/hooks/use-project-runs.ts +51 -0
- package/src/hooks/use-projects.ts +26 -0
- package/src/hooks/use-run-dashboard.ts +207 -0
- package/src/hooks/use-run-detail.ts +77 -0
- package/src/hooks/use-smart-polling.ts +144 -0
- package/src/lib/.gitkeep +0 -0
- package/src/lib/__tests__/cn.test.ts +69 -0
- package/src/lib/__tests__/config-loader.test.ts +210 -0
- package/src/lib/__tests__/config.test.ts +561 -0
- package/src/lib/__tests__/error-handler.test.ts +143 -0
- package/src/lib/__tests__/fetcher.test.ts +517 -0
- package/src/lib/__tests__/global-registry.test.ts +214 -0
- package/src/lib/__tests__/parser.test.ts +1532 -0
- package/src/lib/__tests__/path-resolver.test.ts +112 -0
- package/src/lib/__tests__/run-cache.test.ts +591 -0
- package/src/lib/__tests__/server-init.test.ts +512 -0
- package/src/lib/__tests__/source-discovery.test.ts +246 -0
- package/src/lib/__tests__/utils.test.ts +160 -0
- package/src/lib/__tests__/watcher.test.ts +227 -0
- package/src/lib/cn.ts +6 -0
- package/src/lib/config-loader.ts +195 -0
- package/src/lib/config.ts +20 -0
- package/src/lib/error-handler.ts +76 -0
- package/src/lib/fetcher.ts +394 -0
- package/src/lib/global-registry.ts +117 -0
- package/src/lib/parser.ts +794 -0
- package/src/lib/path-resolver.ts +16 -0
- package/src/lib/run-cache.ts +404 -0
- package/src/lib/server-init.ts +226 -0
- package/src/lib/services/__tests__/run-query-service.test.ts +819 -0
- package/src/lib/services/run-query-service.ts +286 -0
- package/src/lib/source-discovery.ts +216 -0
- package/src/lib/utils.ts +103 -0
- package/src/lib/watcher.ts +265 -0
- package/src/test/fixtures.ts +269 -0
- package/src/test/mocks/handlers.ts +110 -0
- package/src/test/mocks/server.ts +17 -0
- package/src/test/setup.ts +200 -0
- package/src/test/test-utils.tsx +36 -0
- package/src/types/.gitkeep +0 -0
- package/src/types/breakpoint.ts +17 -0
- package/src/types/index.ts +214 -0
- package/tsconfig.json +50 -0
package/src/app/page.tsx
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useRunDashboard } from "@/hooks/use-run-dashboard";
|
|
3
|
+
import { BreakpointBanner } from "@/components/dashboard/breakpoint-banner";
|
|
4
|
+
import { CatchUpBanner } from "@/components/dashboard/catch-up-banner";
|
|
5
|
+
import { ExecutiveSummaryBanner } from "@/components/dashboard/executive-summary-banner";
|
|
6
|
+
import { KpiGrid } from "@/components/dashboard/kpi-grid";
|
|
7
|
+
import { RunFilterBar } from "@/components/dashboard/run-filter-bar";
|
|
8
|
+
import { ProjectListView } from "@/components/dashboard/project-list-view";
|
|
9
|
+
import { ErrorBoundary } from "@/components/shared/error-boundary";
|
|
10
|
+
import { GlobalSearch } from "@/components/dashboard/global-search";
|
|
11
|
+
|
|
12
|
+
export default function DashboardPage() {
|
|
13
|
+
const {
|
|
14
|
+
projects,
|
|
15
|
+
loading,
|
|
16
|
+
error,
|
|
17
|
+
metrics,
|
|
18
|
+
allBreakpointRuns,
|
|
19
|
+
summaryMetrics,
|
|
20
|
+
bannerFingerprint,
|
|
21
|
+
bannerDismissed,
|
|
22
|
+
filterCounts,
|
|
23
|
+
filteredProjects,
|
|
24
|
+
activeProjects,
|
|
25
|
+
historyProjects,
|
|
26
|
+
statusFilter,
|
|
27
|
+
sortMode,
|
|
28
|
+
historyCollapsed,
|
|
29
|
+
cardStatusFilter,
|
|
30
|
+
hasStaleRuns,
|
|
31
|
+
catchUp,
|
|
32
|
+
setStatusFilter,
|
|
33
|
+
setSortMode,
|
|
34
|
+
setHistoryCollapsed,
|
|
35
|
+
setDismissedFingerprint,
|
|
36
|
+
toggleMetricFilter,
|
|
37
|
+
handleHideProject,
|
|
38
|
+
} = useRunDashboard();
|
|
39
|
+
|
|
40
|
+
const showBanners = !loading && !error && projects.length > 0;
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<div className="bg-gradient-brand flex-1">
|
|
44
|
+
<div className="mx-auto max-w-[1600px] px-6 py-6">
|
|
45
|
+
{/* Global Search */}
|
|
46
|
+
<GlobalSearch />
|
|
47
|
+
|
|
48
|
+
{/* Executive Summary Banner */}
|
|
49
|
+
{showBanners && (
|
|
50
|
+
<ErrorBoundary section="Executive Summary">
|
|
51
|
+
<ExecutiveSummaryBanner
|
|
52
|
+
metrics={summaryMetrics}
|
|
53
|
+
onFilterChange={setStatusFilter}
|
|
54
|
+
dismissed={bannerDismissed}
|
|
55
|
+
onDismiss={() => setDismissedFingerprint(bannerFingerprint)}
|
|
56
|
+
/>
|
|
57
|
+
</ErrorBoundary>
|
|
58
|
+
)}
|
|
59
|
+
|
|
60
|
+
{/* KPI Metrics Row */}
|
|
61
|
+
{showBanners && (
|
|
62
|
+
<ErrorBoundary section="KPI Metrics">
|
|
63
|
+
<KpiGrid
|
|
64
|
+
metrics={metrics}
|
|
65
|
+
statusFilter={statusFilter}
|
|
66
|
+
hasStaleRuns={hasStaleRuns}
|
|
67
|
+
onToggleFilter={toggleMetricFilter}
|
|
68
|
+
/>
|
|
69
|
+
</ErrorBoundary>
|
|
70
|
+
)}
|
|
71
|
+
|
|
72
|
+
{/* Catch-up mode banner — shown when burst of SSE updates detected */}
|
|
73
|
+
{catchUp.active && (
|
|
74
|
+
<CatchUpBanner
|
|
75
|
+
catchUp={catchUp}
|
|
76
|
+
summary={{
|
|
77
|
+
failedRuns: summaryMetrics.failedRuns,
|
|
78
|
+
completedRuns: summaryMetrics.completedRuns,
|
|
79
|
+
pendingBreakpoints: summaryMetrics.pendingBreakpoints,
|
|
80
|
+
}}
|
|
81
|
+
/>
|
|
82
|
+
)}
|
|
83
|
+
|
|
84
|
+
{/* Global Breakpoint Banner — pinned with sticky positioning */}
|
|
85
|
+
{!loading && !error && allBreakpointRuns.length > 0 && (
|
|
86
|
+
<ErrorBoundary section="Breakpoint Banner">
|
|
87
|
+
<div className="sticky top-0 z-40">
|
|
88
|
+
<BreakpointBanner breakpointRuns={allBreakpointRuns} />
|
|
89
|
+
</div>
|
|
90
|
+
</ErrorBoundary>
|
|
91
|
+
)}
|
|
92
|
+
|
|
93
|
+
{/* Filter pills + sort toggle */}
|
|
94
|
+
<RunFilterBar
|
|
95
|
+
statusFilter={statusFilter}
|
|
96
|
+
onStatusFilterChange={setStatusFilter}
|
|
97
|
+
filterCounts={filterCounts}
|
|
98
|
+
sortMode={sortMode}
|
|
99
|
+
onSortModeToggle={() => setSortMode((prev) => prev === "status" ? "activity" : "status")}
|
|
100
|
+
filteredProjectCount={filteredProjects.length}
|
|
101
|
+
/>
|
|
102
|
+
|
|
103
|
+
{/* Project cards content */}
|
|
104
|
+
<ProjectListView
|
|
105
|
+
loading={loading}
|
|
106
|
+
error={error}
|
|
107
|
+
filteredProjects={filteredProjects}
|
|
108
|
+
activeProjects={activeProjects}
|
|
109
|
+
historyProjects={historyProjects}
|
|
110
|
+
statusFilter={statusFilter}
|
|
111
|
+
sortMode={sortMode}
|
|
112
|
+
cardStatusFilter={cardStatusFilter}
|
|
113
|
+
historyCollapsed={historyCollapsed}
|
|
114
|
+
onHistoryCollapsedChange={setHistoryCollapsed}
|
|
115
|
+
onHideProject={handleHideProject}
|
|
116
|
+
/>
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useState, useCallback, useMemo } from "react";
|
|
3
|
+
import { useRouter } from "next/navigation";
|
|
4
|
+
import dynamic from "next/dynamic";
|
|
5
|
+
import { useRunDetail } from "@/hooks/use-run-detail";
|
|
6
|
+
import { useKeyboard } from "@/hooks/use-keyboard";
|
|
7
|
+
import { OutcomeBanner } from "@/components/shared/outcome-banner";
|
|
8
|
+
import { MetricsRow } from "@/components/shared/metrics-row";
|
|
9
|
+
import { useNotificationContext } from "@/components/notifications/notification-provider";
|
|
10
|
+
import { cn } from "@/lib/cn";
|
|
11
|
+
import { Loader2, X, ArrowLeft } from "lucide-react";
|
|
12
|
+
import type { JournalEvent, EffectRequestedPayload } from "@/types";
|
|
13
|
+
|
|
14
|
+
/* -------------------------------------------------------------------------- */
|
|
15
|
+
/* Loading skeletons for lazy-loaded route panels */
|
|
16
|
+
/* -------------------------------------------------------------------------- */
|
|
17
|
+
|
|
18
|
+
function PipelineSkeleton() {
|
|
19
|
+
return (
|
|
20
|
+
<div className="flex flex-col h-full animate-pulse p-4 space-y-3">
|
|
21
|
+
<div className="h-5 w-40 rounded bg-foreground-muted/10" />
|
|
22
|
+
<div className="h-2 w-full rounded-full bg-foreground-muted/10" />
|
|
23
|
+
<div className="space-y-2 mt-4">
|
|
24
|
+
{[1, 2, 3, 4].map((i) => (
|
|
25
|
+
<div key={i} className="h-16 rounded-lg bg-foreground-muted/10" />
|
|
26
|
+
))}
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function EventStreamSkeleton() {
|
|
33
|
+
return (
|
|
34
|
+
<div className="flex flex-col h-full animate-pulse p-3 space-y-2">
|
|
35
|
+
<div className="h-4 w-24 rounded bg-foreground-muted/10" />
|
|
36
|
+
<div className="h-8 w-full rounded bg-foreground-muted/10" />
|
|
37
|
+
<div className="space-y-1.5 mt-2">
|
|
38
|
+
{[1, 2, 3, 4, 5].map((i) => (
|
|
39
|
+
<div key={i} className="h-10 rounded bg-foreground-muted/10" />
|
|
40
|
+
))}
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function DetailPanelSkeleton() {
|
|
47
|
+
return (
|
|
48
|
+
<div className="flex flex-col h-full animate-pulse p-4 space-y-3">
|
|
49
|
+
<div className="h-8 w-full rounded bg-foreground-muted/10" />
|
|
50
|
+
<div className="h-4 w-3/4 rounded bg-foreground-muted/10" />
|
|
51
|
+
<div className="h-4 w-1/2 rounded bg-foreground-muted/10" />
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* -------------------------------------------------------------------------- */
|
|
57
|
+
/* Lazy-loaded heavy route panels */
|
|
58
|
+
/* -------------------------------------------------------------------------- */
|
|
59
|
+
|
|
60
|
+
const PipelineView = dynamic(
|
|
61
|
+
() => import("@/components/pipeline/pipeline-view").then((mod) => ({ default: mod.PipelineView })),
|
|
62
|
+
{ ssr: false, loading: PipelineSkeleton }
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const EventStream = dynamic(
|
|
66
|
+
() => import("@/components/events/event-stream").then((mod) => ({ default: mod.EventStream })),
|
|
67
|
+
{ ssr: false, loading: EventStreamSkeleton }
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const TaskDetailPanel = dynamic(
|
|
71
|
+
() => import("@/components/details/task-detail").then((mod) => ({ default: mod.TaskDetailPanel })),
|
|
72
|
+
{ ssr: false, loading: DetailPanelSkeleton }
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
export default function RunDetailPage({ params }: { params: { runId: string } }) {
|
|
76
|
+
const { runId } = params;
|
|
77
|
+
const router = useRouter();
|
|
78
|
+
const { run, loading, error, hasBreakpointWaiting: _hasBreakpointWaiting } = useRunDetail(runId);
|
|
79
|
+
const { notifications: _notifications, dismiss: _dismiss, notify: _notify } = useNotificationContext();
|
|
80
|
+
const [selectedEffectId, setSelectedEffectId] = useState<string | null>(null);
|
|
81
|
+
const [showDetail, setShowDetail] = useState(false);
|
|
82
|
+
const [showEventStream, setShowEventStream] = useState(true);
|
|
83
|
+
const [activeTab, setActiveTab] = useState("agent");
|
|
84
|
+
|
|
85
|
+
const handleSelectEffect = useCallback((effectId: string) => {
|
|
86
|
+
setSelectedEffectId(effectId);
|
|
87
|
+
setShowDetail(true);
|
|
88
|
+
|
|
89
|
+
// Auto-switch to breakpoint tab when selecting a breakpoint task
|
|
90
|
+
const task = run?.tasks.find((t) => t.effectId === effectId);
|
|
91
|
+
if (task?.kind === "breakpoint") {
|
|
92
|
+
setActiveTab("breakpoint");
|
|
93
|
+
}
|
|
94
|
+
}, [run?.tasks]);
|
|
95
|
+
|
|
96
|
+
const handleEventClick = useCallback((event: JournalEvent) => {
|
|
97
|
+
const payload = event.payload as unknown as EffectRequestedPayload;
|
|
98
|
+
if (payload?.effectId) {
|
|
99
|
+
handleSelectEffect(payload.effectId);
|
|
100
|
+
}
|
|
101
|
+
}, [handleSelectEffect]);
|
|
102
|
+
|
|
103
|
+
const tasks = useMemo(() => run?.tasks || [], [run?.tasks]);
|
|
104
|
+
|
|
105
|
+
// Determine if the currently selected task is a waiting breakpoint
|
|
106
|
+
const selectedTask = useMemo(() => {
|
|
107
|
+
if (!selectedEffectId) return null;
|
|
108
|
+
return tasks.find((t) => t.effectId === selectedEffectId) || null;
|
|
109
|
+
}, [tasks, selectedEffectId]);
|
|
110
|
+
|
|
111
|
+
const moveDown = useCallback(() => {
|
|
112
|
+
if (!tasks.length) return;
|
|
113
|
+
const currentIdx = selectedEffectId
|
|
114
|
+
? tasks.findIndex((t) => t.effectId === selectedEffectId)
|
|
115
|
+
: -1;
|
|
116
|
+
const nextIdx = Math.min(currentIdx + 1, tasks.length - 1);
|
|
117
|
+
handleSelectEffect(tasks[nextIdx].effectId);
|
|
118
|
+
}, [tasks, selectedEffectId, handleSelectEffect]);
|
|
119
|
+
|
|
120
|
+
const moveUp = useCallback(() => {
|
|
121
|
+
if (!tasks.length) return;
|
|
122
|
+
const currentIdx = selectedEffectId
|
|
123
|
+
? tasks.findIndex((t) => t.effectId === selectedEffectId)
|
|
124
|
+
: tasks.length;
|
|
125
|
+
const prevIdx = Math.max(currentIdx - 1, 0);
|
|
126
|
+
handleSelectEffect(tasks[prevIdx].effectId);
|
|
127
|
+
}, [tasks, selectedEffectId, handleSelectEffect]);
|
|
128
|
+
|
|
129
|
+
const goBack = useCallback(() => {
|
|
130
|
+
if (showDetail) {
|
|
131
|
+
setShowDetail(false);
|
|
132
|
+
setSelectedEffectId(null);
|
|
133
|
+
} else {
|
|
134
|
+
router.push("/");
|
|
135
|
+
}
|
|
136
|
+
}, [showDetail, router]);
|
|
137
|
+
|
|
138
|
+
const toggleEventStream = useCallback(() => {
|
|
139
|
+
setShowEventStream((v) => !v);
|
|
140
|
+
}, []);
|
|
141
|
+
|
|
142
|
+
const openSelected = useCallback(() => {
|
|
143
|
+
if (selectedEffectId && !showDetail) {
|
|
144
|
+
setShowDetail(true);
|
|
145
|
+
} else if (!selectedEffectId && tasks.length > 0) {
|
|
146
|
+
handleSelectEffect(tasks[0].effectId);
|
|
147
|
+
}
|
|
148
|
+
}, [selectedEffectId, showDetail, tasks, handleSelectEffect]);
|
|
149
|
+
|
|
150
|
+
const switchTab = useCallback((key: string) => {
|
|
151
|
+
if (!showDetail) return;
|
|
152
|
+
const tabKeys: Record<string, string> = {
|
|
153
|
+
"1": "agent",
|
|
154
|
+
"2": "timing",
|
|
155
|
+
"3": "logs",
|
|
156
|
+
"4": "data",
|
|
157
|
+
"5": "breakpoint",
|
|
158
|
+
};
|
|
159
|
+
const tab = tabKeys[key];
|
|
160
|
+
if (tab) {
|
|
161
|
+
if (tab === "breakpoint" && selectedTask?.kind !== "breakpoint") return;
|
|
162
|
+
setActiveTab(tab);
|
|
163
|
+
}
|
|
164
|
+
}, [selectedTask, showDetail]);
|
|
165
|
+
|
|
166
|
+
useKeyboard([
|
|
167
|
+
{ key: "j", action: moveDown, description: "Next item" },
|
|
168
|
+
{ key: "k", action: moveUp, description: "Previous item" },
|
|
169
|
+
{ key: "Enter", action: openSelected, description: "Open selected" },
|
|
170
|
+
{ key: "Escape", action: goBack, description: "Go back / Close" },
|
|
171
|
+
{ key: "e", action: toggleEventStream, description: "Toggle event stream" },
|
|
172
|
+
{ key: "1", action: () => switchTab("1"), description: "Agent tab" },
|
|
173
|
+
{ key: "2", action: () => switchTab("2"), description: "Timing tab" },
|
|
174
|
+
{ key: "3", action: () => switchTab("3"), description: "Logs tab" },
|
|
175
|
+
{ key: "4", action: () => switchTab("4"), description: "Data tab" },
|
|
176
|
+
{ key: "5", action: () => switchTab("5"), description: "Approval tab" },
|
|
177
|
+
]);
|
|
178
|
+
|
|
179
|
+
if (loading && !run) {
|
|
180
|
+
return (
|
|
181
|
+
<div className="flex items-center justify-center flex-1">
|
|
182
|
+
<Loader2 className="h-6 w-6 animate-spin text-foreground-muted" />
|
|
183
|
+
</div>
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (error || !run) {
|
|
188
|
+
return (
|
|
189
|
+
<div className="flex items-center justify-center flex-1">
|
|
190
|
+
<div data-testid="run-error-message" className="rounded-lg border border-error/20 bg-error-muted p-4 text-sm text-error">
|
|
191
|
+
{error || "Run not found"}
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return (
|
|
198
|
+
<div className="flex flex-col flex-1 bg-background">
|
|
199
|
+
{/* Navigation header with back button */}
|
|
200
|
+
<div className="flex items-center gap-3 px-4 py-2 border-b border-border bg-background-secondary/40">
|
|
201
|
+
<button
|
|
202
|
+
onClick={() => router.push("/")}
|
|
203
|
+
className="inline-flex items-center gap-1.5 rounded-md border border-border px-2.5 py-1 min-h-[44px] text-xs font-medium text-foreground-muted hover:text-foreground hover:border-primary/50 hover:shadow-neon-glow-primary-ring transition-all duration-200"
|
|
204
|
+
>
|
|
205
|
+
<ArrowLeft className="h-3.5 w-3.5" />
|
|
206
|
+
Dashboard
|
|
207
|
+
</button>
|
|
208
|
+
<span className="text-xs text-foreground-muted">/</span>
|
|
209
|
+
<span className="text-xs font-mono text-foreground-secondary">{run.runId.slice(0, 8)}...</span>
|
|
210
|
+
{run.processId && (
|
|
211
|
+
<>
|
|
212
|
+
<span className="text-xs text-foreground-muted">/</span>
|
|
213
|
+
<span className="text-xs text-foreground-secondary">{run.processId}</span>
|
|
214
|
+
</>
|
|
215
|
+
)}
|
|
216
|
+
</div>
|
|
217
|
+
|
|
218
|
+
{/* Outcome Banner - Top of page */}
|
|
219
|
+
<OutcomeBanner run={run} />
|
|
220
|
+
|
|
221
|
+
{/* Metrics Row - Summary stats for all run statuses */}
|
|
222
|
+
<MetricsRow run={run} />
|
|
223
|
+
|
|
224
|
+
<div className="flex flex-col lg:flex-row flex-1 overflow-hidden">
|
|
225
|
+
{/* Pipeline - Left panel */}
|
|
226
|
+
<div className={cn(
|
|
227
|
+
"border-b lg:border-b-0 lg:border-r border-border transition-panel bg-card/50 backdrop-blur-sm",
|
|
228
|
+
showDetail ? "lg:w-[35%]" : showEventStream ? "lg:w-[60%]" : "w-full",
|
|
229
|
+
)}>
|
|
230
|
+
<PipelineView
|
|
231
|
+
run={run}
|
|
232
|
+
selectedEffectId={selectedEffectId}
|
|
233
|
+
onSelectEffect={handleSelectEffect}
|
|
234
|
+
runStatus={run.status}
|
|
235
|
+
/>
|
|
236
|
+
</div>
|
|
237
|
+
|
|
238
|
+
{/* Task Detail - Center panel (shown when task selected) */}
|
|
239
|
+
{showDetail && (
|
|
240
|
+
<div className={cn(
|
|
241
|
+
"border-b lg:border-b-0 lg:border-r border-border transition-panel bg-card/50 backdrop-blur-sm overflow-hidden flex flex-col",
|
|
242
|
+
showEventStream ? "lg:w-[30%]" : "lg:w-[65%]",
|
|
243
|
+
)}>
|
|
244
|
+
<div data-testid="task-detail-header" className="flex items-center justify-between p-3 border-b border-border bg-background-secondary/40">
|
|
245
|
+
<h3 className="text-xs font-medium text-foreground-muted uppercase tracking-wider">Task Detail</h3>
|
|
246
|
+
<button
|
|
247
|
+
data-testid="close-detail-btn"
|
|
248
|
+
onClick={() => { setShowDetail(false); setSelectedEffectId(null); }}
|
|
249
|
+
className="inline-flex items-center gap-1.5 rounded-md border border-primary/20 px-2.5 py-1 min-h-[44px] text-xs font-medium text-foreground-muted hover:text-primary hover:border-primary/50 hover:shadow-neon-glow-primary-ring transition-all duration-200"
|
|
250
|
+
>
|
|
251
|
+
<X className="h-3.5 w-3.5" />
|
|
252
|
+
Close
|
|
253
|
+
</button>
|
|
254
|
+
</div>
|
|
255
|
+
<TaskDetailPanel
|
|
256
|
+
runId={runId}
|
|
257
|
+
effectId={selectedEffectId}
|
|
258
|
+
activeTab={activeTab}
|
|
259
|
+
onTabChange={setActiveTab}
|
|
260
|
+
runDuration={run.duration}
|
|
261
|
+
allTasks={run.tasks}
|
|
262
|
+
/>
|
|
263
|
+
</div>
|
|
264
|
+
)}
|
|
265
|
+
|
|
266
|
+
{/* Event Stream - Right panel */}
|
|
267
|
+
{showEventStream && (
|
|
268
|
+
<div className={cn(
|
|
269
|
+
"transition-panel bg-card/50 backdrop-blur-sm",
|
|
270
|
+
showDetail ? "lg:w-[35%]" : "lg:w-[40%]",
|
|
271
|
+
)}>
|
|
272
|
+
<EventStream events={run.events} onEventClick={handleEventClick} />
|
|
273
|
+
</div>
|
|
274
|
+
)}
|
|
275
|
+
</div>
|
|
276
|
+
|
|
277
|
+
</div>
|
|
278
|
+
);
|
|
279
|
+
}
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CLI entry point for the babysitter observer dashboard.
|
|
5
|
+
*
|
|
6
|
+
* Parses command-line flags, maps them to environment variables,
|
|
7
|
+
* then execs into `next dev` or `next start`.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* npx ts-node src/cli.ts --port 4800 --watch-dir /tmp/runs --poll-interval 5000 --theme light
|
|
11
|
+
* npx ts-node src/cli.ts --production --port 4800
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { execSync } from "child_process";
|
|
15
|
+
import { readFileSync, existsSync } from "fs";
|
|
16
|
+
import { resolve } from "path";
|
|
17
|
+
|
|
18
|
+
interface CliOptions {
|
|
19
|
+
port?: string;
|
|
20
|
+
watchDir?: string;
|
|
21
|
+
pollInterval?: string;
|
|
22
|
+
theme?: string;
|
|
23
|
+
dev?: boolean;
|
|
24
|
+
help?: boolean;
|
|
25
|
+
version?: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Injected at build time by esbuild define. Falls back to reading package.json
|
|
29
|
+
// at runtime for development (ts-node) usage.
|
|
30
|
+
declare const __CLI_VERSION__: string | undefined;
|
|
31
|
+
|
|
32
|
+
function getVersion(): string {
|
|
33
|
+
if (typeof __CLI_VERSION__ !== "undefined") {
|
|
34
|
+
return __CLI_VERSION__;
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
const pkgPath = resolve(__dirname, "..", "package.json");
|
|
38
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
39
|
+
return pkg.version || "unknown";
|
|
40
|
+
} catch {
|
|
41
|
+
return "unknown";
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function printUsage(): void {
|
|
46
|
+
const usage = `
|
|
47
|
+
babysitter-observer-dashboard — CLI for the observer dashboard
|
|
48
|
+
|
|
49
|
+
Usage:
|
|
50
|
+
observer [options]
|
|
51
|
+
|
|
52
|
+
Options:
|
|
53
|
+
--port <number> Port to listen on (default: 4800)
|
|
54
|
+
--watch-dir <path> Directory to watch for .a5c/runs (default: cwd)
|
|
55
|
+
--poll-interval <ms> Polling interval in milliseconds (default: 2000)
|
|
56
|
+
--theme <dark|light> Default UI theme (default: dark)
|
|
57
|
+
--dev Run in dev mode (next dev) instead of production
|
|
58
|
+
--version, -v Show version number
|
|
59
|
+
--help Show this help message
|
|
60
|
+
|
|
61
|
+
Environment variable mapping:
|
|
62
|
+
--port -> OBSERVER_PORT
|
|
63
|
+
--watch-dir -> OBSERVER_WATCH_DIR
|
|
64
|
+
--poll-interval -> OBSERVER_POLL_INTERVAL
|
|
65
|
+
--theme -> OBSERVER_DEFAULT_THEME
|
|
66
|
+
|
|
67
|
+
Examples:
|
|
68
|
+
# Start dashboard on port 3002 watching a specific directory
|
|
69
|
+
observer --port 3002 --watch-dir /home/user/projects
|
|
70
|
+
|
|
71
|
+
# Start with light theme
|
|
72
|
+
observer --theme light
|
|
73
|
+
`.trim();
|
|
74
|
+
|
|
75
|
+
console.log(usage);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function parseArgs(argv: string[]): CliOptions {
|
|
79
|
+
const opts: CliOptions = {};
|
|
80
|
+
// Skip first two entries: node binary and script path
|
|
81
|
+
const args = argv.slice(2);
|
|
82
|
+
|
|
83
|
+
for (let i = 0; i < args.length; i++) {
|
|
84
|
+
const arg = args[i];
|
|
85
|
+
|
|
86
|
+
switch (arg) {
|
|
87
|
+
case "--port":
|
|
88
|
+
i++;
|
|
89
|
+
opts.port = args[i];
|
|
90
|
+
if (!opts.port || isNaN(Number(opts.port))) {
|
|
91
|
+
console.error("Error: --port requires a numeric value");
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
break;
|
|
95
|
+
|
|
96
|
+
case "--watch-dir":
|
|
97
|
+
i++;
|
|
98
|
+
opts.watchDir = args[i];
|
|
99
|
+
if (!opts.watchDir) {
|
|
100
|
+
console.error("Error: --watch-dir requires a path value");
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
break;
|
|
104
|
+
|
|
105
|
+
case "--poll-interval":
|
|
106
|
+
i++;
|
|
107
|
+
opts.pollInterval = args[i];
|
|
108
|
+
if (!opts.pollInterval || isNaN(Number(opts.pollInterval))) {
|
|
109
|
+
console.error("Error: --poll-interval requires a numeric value (ms)");
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
break;
|
|
113
|
+
|
|
114
|
+
case "--theme":
|
|
115
|
+
i++;
|
|
116
|
+
opts.theme = args[i];
|
|
117
|
+
if (opts.theme !== "dark" && opts.theme !== "light") {
|
|
118
|
+
console.error('Error: --theme must be "dark" or "light"');
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
break;
|
|
122
|
+
|
|
123
|
+
case "--dev":
|
|
124
|
+
opts.dev = true;
|
|
125
|
+
break;
|
|
126
|
+
|
|
127
|
+
case "--production":
|
|
128
|
+
// Legacy flag — production is now the default, so this is a no-op
|
|
129
|
+
break;
|
|
130
|
+
|
|
131
|
+
case "--version":
|
|
132
|
+
case "-v":
|
|
133
|
+
opts.version = true;
|
|
134
|
+
break;
|
|
135
|
+
|
|
136
|
+
case "--help":
|
|
137
|
+
case "-h":
|
|
138
|
+
opts.help = true;
|
|
139
|
+
break;
|
|
140
|
+
|
|
141
|
+
default:
|
|
142
|
+
console.error(`Unknown flag: ${arg}`);
|
|
143
|
+
console.error('Run with --help for usage information.');
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return opts;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Locate the `next` binary across all installation scenarios.
|
|
153
|
+
*
|
|
154
|
+
* npm may hoist dependencies to a parent node_modules (e.g. when this
|
|
155
|
+
* package is installed via npx or as a dependency of another project).
|
|
156
|
+
* We try several strategies before giving up:
|
|
157
|
+
*
|
|
158
|
+
* 1. require.resolve — honours Node's module resolution & hoisting
|
|
159
|
+
* 2. Local node_modules/.bin — classic non-hoisted layout
|
|
160
|
+
* 3. Walk up the directory tree — covers deep-nested workspaces
|
|
161
|
+
* 4. Bare "next" — last resort, assumes it is on $PATH
|
|
162
|
+
*/
|
|
163
|
+
function findNextBin(): string {
|
|
164
|
+
const projectRoot = resolve(__dirname, "..");
|
|
165
|
+
|
|
166
|
+
// Method 1: Use require.resolve to find next's package.json (handles hoisting).
|
|
167
|
+
// We derive the .bin/next wrapper path (not dist/bin/next) because the wrapper
|
|
168
|
+
// is cross-platform: on Unix it has a shebang, on Windows there is a .cmd peer.
|
|
169
|
+
try {
|
|
170
|
+
const nextPkgPath = require.resolve("next/package.json", {
|
|
171
|
+
paths: [projectRoot],
|
|
172
|
+
});
|
|
173
|
+
// nextPkgPath => .../node_modules/next/package.json
|
|
174
|
+
// Go up to the containing node_modules directory, then into .bin
|
|
175
|
+
const nodeModulesDir = resolve(nextPkgPath, "..", "..");
|
|
176
|
+
const binPath = resolve(nodeModulesDir, ".bin", "next");
|
|
177
|
+
if (existsSync(binPath) || existsSync(binPath + ".cmd")) {
|
|
178
|
+
return binPath;
|
|
179
|
+
}
|
|
180
|
+
} catch {
|
|
181
|
+
// next is not resolvable from projectRoot — continue to fallbacks
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Method 2: Check the local node_modules/.bin (non-hoisted layout)
|
|
185
|
+
const localBin = resolve(projectRoot, "node_modules", ".bin", "next");
|
|
186
|
+
if (existsSync(localBin)) {
|
|
187
|
+
return localBin;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Method 3: Walk up the directory tree looking for node_modules/.bin/next
|
|
191
|
+
let current = projectRoot;
|
|
192
|
+
while (true) {
|
|
193
|
+
const candidate = resolve(current, "node_modules", ".bin", "next");
|
|
194
|
+
if (existsSync(candidate)) {
|
|
195
|
+
return candidate;
|
|
196
|
+
}
|
|
197
|
+
const parent = resolve(current, "..");
|
|
198
|
+
if (parent === current) {
|
|
199
|
+
break; // reached filesystem root
|
|
200
|
+
}
|
|
201
|
+
current = parent;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Method 4: Fall back to bare "next" and hope it is on PATH
|
|
205
|
+
return "next";
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function main(): void {
|
|
209
|
+
const opts = parseArgs(process.argv);
|
|
210
|
+
|
|
211
|
+
if (opts.version) {
|
|
212
|
+
console.log(`babysitter-observer-dashboard v${getVersion()}`);
|
|
213
|
+
process.exit(0);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (opts.help) {
|
|
217
|
+
printUsage();
|
|
218
|
+
process.exit(0);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Map CLI flags to environment variables
|
|
222
|
+
if (opts.port) {
|
|
223
|
+
process.env.OBSERVER_PORT = opts.port;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Default watch directory to the user's cwd (not the package root, which is
|
|
227
|
+
// where Next.js will run). Without this, the config falls back to
|
|
228
|
+
// process.cwd() inside the Next.js process, which points at the package
|
|
229
|
+
// root — useless for npx / global installs.
|
|
230
|
+
process.env.OBSERVER_WATCH_DIR = opts.watchDir || process.cwd();
|
|
231
|
+
|
|
232
|
+
if (opts.pollInterval) {
|
|
233
|
+
process.env.OBSERVER_POLL_INTERVAL = opts.pollInterval;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (opts.theme) {
|
|
237
|
+
process.env.OBSERVER_DEFAULT_THEME = opts.theme;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Determine the Next.js command — use local binary for global installs
|
|
241
|
+
const port = opts.port || process.env.OBSERVER_PORT || "4800";
|
|
242
|
+
const nextBin = findNextBin();
|
|
243
|
+
const nextCmd = opts.dev
|
|
244
|
+
? `"${nextBin}" dev --port ${port}`
|
|
245
|
+
: `"${nextBin}" start --port ${port}`;
|
|
246
|
+
|
|
247
|
+
console.log(`Starting observer: ${nextCmd}`);
|
|
248
|
+
|
|
249
|
+
if (opts.watchDir) {
|
|
250
|
+
console.log(` Watch directory: ${opts.watchDir}`);
|
|
251
|
+
}
|
|
252
|
+
if (opts.pollInterval) {
|
|
253
|
+
console.log(` Poll interval: ${opts.pollInterval}ms`);
|
|
254
|
+
}
|
|
255
|
+
if (opts.theme) {
|
|
256
|
+
console.log(` Theme: ${opts.theme}`);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
try {
|
|
260
|
+
execSync(nextCmd, {
|
|
261
|
+
env: process.env,
|
|
262
|
+
stdio: "inherit",
|
|
263
|
+
cwd: resolve(__dirname, ".."),
|
|
264
|
+
});
|
|
265
|
+
} catch {
|
|
266
|
+
// next dev exits with non-zero on SIGINT/SIGTERM — that is normal
|
|
267
|
+
process.exit(0);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
main();
|