fleetlens 0.4.0 → 0.6.0
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/app/apps/web/.next/BUILD_ID +1 -1
- package/app/apps/web/.next/app-path-routes-manifest.json +16 -7
- package/app/apps/web/.next/build-manifest.json +7 -7
- package/app/apps/web/.next/prerender-manifest.json +3 -3
- package/app/apps/web/.next/required-server-files.json +2 -1
- package/app/apps/web/.next/routes-manifest.json +86 -24
- package/app/apps/web/.next/server/app/_global-error/page/build-manifest.json +4 -4
- package/app/apps/web/.next/server/app/_global-error/page.js +1 -1
- package/app/apps/web/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/_global-error.html +1 -1
- package/app/apps/web/.next/server/app/_global-error.rsc +7 -7
- package/app/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
- package/app/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/app/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
- package/app/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
- package/app/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/app/apps/web/.next/server/app/_not-found/page/build-manifest.json +4 -4
- package/app/apps/web/.next/server/app/_not-found/page.js +5 -4
- package/app/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/api/digest/day/[date]/route/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js +9 -0
- package/app/apps/web/.next/server/app/api/{insights/saved/[key] → digest/day/[date]}/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/day/[date]/route_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js +9 -0
- package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js.nft.json +1 -0
- package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/api/digest/month-index/route/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/api/digest/month-index/route.js +7 -0
- package/app/apps/web/.next/server/app/api/{insights/months-index → digest/month-index}/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/{insights/pdf/[key] → digest/month-index}/route_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js +9 -0
- package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js.nft.json +1 -0
- package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/api/digest/week-index/route/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/api/digest/week-index/route.js +7 -0
- package/app/apps/web/.next/server/app/api/{insights/weeks-index → digest/week-index}/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/week-index/route_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/api/jobs/route/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/api/jobs/route.js +6 -0
- package/app/apps/web/.next/server/app/api/jobs/route.js.nft.json +1 -0
- package/app/apps/web/.next/server/app/api/jobs/route_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/api/runs/[runId]/route/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/api/runs/[runId]/route/build-manifest.json +9 -0
- package/app/apps/web/.next/server/app/api/runs/[runId]/route.js +6 -0
- package/app/apps/web/.next/server/app/api/{insights/saved → runs/[runId]}/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/runs/[runId]/route_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route/build-manifest.json +9 -0
- package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route/server-reference-manifest.json +4 -0
- package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route.js +6 -0
- package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route.js.map +5 -0
- package/app/apps/web/.next/server/app/api/{insights/pdf/[key] → runs/[runId]/stream}/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/api/runs/route/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/api/runs/route/build-manifest.json +9 -0
- package/app/apps/web/.next/server/app/api/runs/route/server-reference-manifest.json +4 -0
- package/app/apps/web/.next/server/app/api/runs/route.js +6 -0
- package/app/apps/web/.next/server/app/api/runs/route.js.map +5 -0
- package/app/apps/web/.next/server/app/api/{insights → runs}/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/runs/route_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/api/settings/route/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/api/settings/route/build-manifest.json +9 -0
- package/app/apps/web/.next/server/app/api/settings/route/server-reference-manifest.json +4 -0
- package/app/apps/web/.next/server/app/api/settings/route.js +10 -0
- package/app/apps/web/.next/server/app/api/settings/route.js.map +5 -0
- package/app/apps/web/.next/server/app/api/settings/route.js.nft.json +1 -0
- package/app/apps/web/.next/server/app/api/{insights → settings}/route_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/day/[date]/page/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/{insights/print/[key] → day/[date]}/page/build-manifest.json +4 -4
- package/app/apps/web/.next/server/app/day/[date]/page/server-reference-manifest.json +4 -0
- package/app/apps/web/.next/server/app/day/[date]/page.js +18 -0
- package/app/apps/web/.next/server/app/day/[date]/page.js.map +5 -0
- package/app/apps/web/.next/server/app/day/[date]/page.js.nft.json +1 -0
- package/app/apps/web/.next/server/app/day/[date]/page_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/day/page/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/day/page/build-manifest.json +17 -0
- package/app/apps/web/.next/server/app/day/page/next-font-manifest.json +6 -0
- package/app/apps/web/.next/server/app/day/page/react-loadable-manifest.json +1 -0
- package/app/apps/web/.next/server/app/day/page/server-reference-manifest.json +4 -0
- package/app/apps/web/.next/server/app/{insights/print/[key] → day}/page.js +11 -10
- package/app/apps/web/.next/server/app/day/page.js.map +5 -0
- package/app/apps/web/.next/server/app/day/page.js.nft.json +1 -0
- package/app/apps/web/.next/server/app/day/page_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/digest/[date]/page/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/digest/[date]/page/build-manifest.json +17 -0
- package/app/apps/web/.next/server/app/digest/[date]/page/next-font-manifest.json +6 -0
- package/app/apps/web/.next/server/app/digest/[date]/page/react-loadable-manifest.json +1 -0
- package/app/apps/web/.next/server/app/digest/[date]/page/server-reference-manifest.json +4 -0
- package/app/apps/web/.next/server/app/digest/[date]/page.js +17 -0
- package/app/apps/web/.next/server/app/digest/[date]/page.js.map +5 -0
- package/app/apps/web/.next/server/app/digest/[date]/page.js.nft.json +1 -0
- package/app/apps/web/.next/server/app/digest/[date]/page_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/digest/page/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/digest/page/build-manifest.json +17 -0
- package/app/apps/web/.next/server/app/digest/page/next-font-manifest.json +6 -0
- package/app/apps/web/.next/server/app/digest/page/react-loadable-manifest.json +1 -0
- package/app/apps/web/.next/server/app/digest/page/server-reference-manifest.json +4 -0
- package/app/apps/web/.next/server/app/digest/page.js +17 -0
- package/app/apps/web/.next/server/app/digest/page.js.map +5 -0
- package/app/apps/web/.next/server/app/digest/page.js.nft.json +1 -0
- package/app/apps/web/.next/server/app/digest/page_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/insights/[key]/page/build-manifest.json +4 -4
- package/app/apps/web/.next/server/app/insights/[key]/page.js +7 -5
- package/app/apps/web/.next/server/app/insights/[key]/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/insights/[key]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/insights/page/build-manifest.json +4 -4
- package/app/apps/web/.next/server/app/insights/page.js +7 -5
- package/app/apps/web/.next/server/app/insights/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/insights/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/page/build-manifest.json +4 -4
- package/app/apps/web/.next/server/app/page.js +7 -6
- package/app/apps/web/.next/server/app/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/parallelism/page/build-manifest.json +4 -4
- package/app/apps/web/.next/server/app/parallelism/page.js +6 -5
- package/app/apps/web/.next/server/app/parallelism/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/parallelism/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/projects/[slug]/page/build-manifest.json +4 -4
- package/app/apps/web/.next/server/app/projects/[slug]/page.js +6 -5
- package/app/apps/web/.next/server/app/projects/[slug]/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/projects/[slug]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/projects/page/build-manifest.json +4 -4
- package/app/apps/web/.next/server/app/projects/page.js +5 -4
- package/app/apps/web/.next/server/app/projects/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/runs/page/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/runs/page/build-manifest.json +17 -0
- package/app/apps/web/.next/server/app/runs/page/next-font-manifest.json +6 -0
- package/app/apps/web/.next/server/app/runs/page/react-loadable-manifest.json +1 -0
- package/app/apps/web/.next/server/app/runs/page/server-reference-manifest.json +4 -0
- package/app/apps/web/.next/server/app/runs/page.js +17 -0
- package/app/apps/web/.next/server/app/runs/page.js.map +5 -0
- package/app/apps/web/.next/server/app/runs/page.js.nft.json +1 -0
- package/app/apps/web/.next/server/app/runs/page_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/sessions/[id]/page/build-manifest.json +4 -4
- package/app/apps/web/.next/server/app/sessions/[id]/page.js +5 -4
- package/app/apps/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/sessions/page/build-manifest.json +4 -4
- package/app/apps/web/.next/server/app/sessions/page.js +5 -4
- package/app/apps/web/.next/server/app/sessions/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/settings/page/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/settings/page/build-manifest.json +17 -0
- package/app/apps/web/.next/server/app/settings/page/next-font-manifest.json +6 -0
- package/app/apps/web/.next/server/app/settings/page/react-loadable-manifest.json +1 -0
- package/app/apps/web/.next/server/app/settings/page/server-reference-manifest.json +4 -0
- package/app/apps/web/.next/server/app/settings/page.js +18 -0
- package/app/apps/web/.next/server/app/settings/page.js.map +5 -0
- package/app/apps/web/.next/server/app/settings/page.js.nft.json +1 -0
- package/app/apps/web/.next/server/app/settings/page_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/usage/page/build-manifest.json +4 -4
- package/app/apps/web/.next/server/app/usage/page.js +6 -5
- package/app/apps/web/.next/server/app/usage/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/usage/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app-paths-manifest.json +16 -7
- package/app/apps/web/.next/server/chunks/02dz_web__next-internal_server_app_api_digest_week_[startDate]_route_actions_0klqqsh.js +3 -0
- package/app/apps/web/.next/server/chunks/09og__next-internal_server_app_api_digest_month_[yearMonth]_route_actions_0i4ielu.js +3 -0
- package/app/apps/web/.next/server/chunks/[externals]__0o43ejh._.js +3 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0-vgrh1._.js +3 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__00n3f9y._.js +3 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__02zukjw._.js +3 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__067~im1._.js +6 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__06b4cj-._.js +3 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0_8zh-i._.js +9 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0e8n_x4._.js +3 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0ej_p3s._.js +9 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0jprdks._.js +9 -0
- package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_digest_day_[date]_route_actions_09sxie5.js +3 -0
- package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_digest_month-index_route_actions_0wldpbu.js +3 -0
- package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_digest_week-index_route_actions_12c2wj2.js +3 -0
- package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_jobs_route_actions_08kx~8-.js +3 -0
- package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_runs_[runId]_route_actions_0dfcghc.js +3 -0
- package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_runs_[runId]_stream_route_actions_0.8e8-k.js +3 -0
- package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_runs_route_actions_0xyx82f.js +3 -0
- package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_settings_route_actions_0.xv7sx.js +3 -0
- package/app/apps/web/.next/server/chunks/node_modules_next_036my~r._.js +49 -0
- package/app/apps/web/.next/server/chunks/packages_0e7q9u_._.js +3 -0
- package/app/apps/web/.next/server/chunks/packages_0n6p2ot._.js +3 -0
- package/app/apps/web/.next/server/chunks/packages_entries_dist_node_0bckr7-.js +379 -0
- package/app/apps/web/.next/server/chunks/packages_parser_dist_fs_0bc7ptm.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0-1_njm._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0-94ji~._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__13xpdx0._.js → [root-of-the-server]__03uoeiw._.js} +2 -2
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0_6.inc._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0d~2~le._.js +8 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0gio_ck._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__08.d5ia._.js → [root-of-the-server]__0jdyefm._.js} +10 -10
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0ln9jsw._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0z45d0g._.js → [root-of-the-server]__0lz4a~g._.js} +2 -48
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0o1_g.~._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0r4tks8._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0rvzdnx._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0euu8sa._.js → [root-of-the-server]__0u39afl._.js} +2 -2
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0u5d7de._.js +12 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0w52fbc._.js +3 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0wwa6gh._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0xy1qim._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0~_8vff._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__10srpu0._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__11v.eqw._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/_02s1n-x._.js +8 -0
- package/app/apps/web/.next/server/chunks/ssr/_0fjbf--._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/_0jw2sm7._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/_0wj750k._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/_0woap-3._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/{_0xies90._.js → _0xu2pvc._.js} +2 -2
- package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_day_[date]_page_actions_0u2kxb..js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_day_page_actions_1042maj.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_digest_[date]_page_actions_0olu967.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_digest_page_actions_0bl.eil.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_runs_page_actions_0485qy7.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_settings_page_actions_0f6epye.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_app_day_[date]_day-view_tsx_0wjoe1u._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_app_settings_ai-features-form_tsx_01p699p._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0b-4-4j._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0ly1xes._.js +6 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0txtsv5._.js +16 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0xs658s._.js +10 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_runs-live-board_tsx_0r6dkdq._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_usage-charts-dashboard_tsx_0bgr_uv._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_usage-data_ts_0xtv99n._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/node_modules_0i2xw~e._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_0e1izl_._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0d3d4wn.js +4 -0
- package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0edz1ko.js +4 -0
- package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0eq.n-n.js +4 -0
- package/app/apps/web/.next/server/chunks/ssr/{node_modules_next_dist_esm_build_templates_app-page_0vz7_px.js → node_modules_next_dist_esm_build_templates_app-page_0hcvt-s.js} +3 -3
- package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0nd5zu0.js +4 -0
- package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_11j1qy0.js +4 -0
- package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_12n1lw_.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/packages_entries_dist_node_0_271yr.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_0-jvt~a._.js +1 -1
- package/app/apps/web/.next/server/functions-config-manifest.json +11 -6
- package/app/apps/web/.next/server/middleware-build-manifest.js +7 -7
- package/app/apps/web/.next/server/pages/500.html +1 -1
- package/app/apps/web/.next/server/server-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/server-reference-manifest.json +1 -1
- package/app/apps/web/.next/static/chunks/0-yc2_pjxwwuq.js +1 -0
- package/app/apps/web/.next/static/chunks/0257pdz1-imal.js +2 -0
- package/app/apps/web/.next/static/chunks/05m.oz3kmf1p7.js +1 -0
- package/app/apps/web/.next/static/chunks/{0pqt~8bl3ukh4.js → 073081qv4uyn8.js} +1 -1
- package/app/apps/web/.next/static/chunks/{0018dy-m-kusj.js → 07lbm-sdh9c2j.js} +1 -1
- package/app/apps/web/.next/static/chunks/0858bgw2i4vob.js +1 -0
- package/app/apps/web/.next/static/chunks/0_7303jr0sf0w.js +10 -0
- package/app/apps/web/.next/static/chunks/0byz8fqw.exef.js +1 -0
- package/app/apps/web/.next/static/chunks/0coa1800xqgfj.js +1 -0
- package/app/apps/web/.next/static/chunks/0fs3gxea5h0s3.css +1 -0
- package/app/apps/web/.next/static/chunks/0k1psab.bybh9.js +14 -0
- package/app/apps/web/.next/static/chunks/0k9pksi_i.odf.js +1 -0
- package/app/apps/web/.next/static/chunks/0m62vx92~0_0d.js +1 -0
- package/app/apps/web/.next/static/chunks/0mc8aa8z.0-5l.js +8 -0
- package/app/apps/web/.next/static/chunks/0mykrrv810ra-.js +31 -0
- package/app/apps/web/.next/static/chunks/0o9ayt8sknubd.js +1 -0
- package/app/apps/web/.next/static/chunks/0osdgl2.9cl1q.js +6 -0
- package/app/apps/web/.next/static/chunks/0xfu09fn_358k.js +4 -0
- package/app/apps/web/.next/static/chunks/171za22fv684..js +6 -0
- package/app/apps/web/.next/static/chunks/17u2ww8ya5dv1.js +6 -0
- package/app/apps/web/.next/static/chunks/{turbopack-169w-1._23ra_.js → turbopack-0_p36yduv.waj.js} +1 -1
- package/app/apps/web/app/api/digest/day/[date]/route.ts +152 -0
- package/app/apps/web/app/api/digest/month/[yearMonth]/route.ts +147 -0
- package/app/apps/web/app/api/digest/month-index/route.ts +103 -0
- package/app/apps/web/app/api/digest/week/[startDate]/route.ts +149 -0
- package/app/apps/web/app/api/{insights/weeks-index → digest/week-index}/route.ts +45 -33
- package/app/apps/web/app/api/jobs/route.ts +8 -0
- package/app/apps/web/app/api/runs/[runId]/route.ts +64 -0
- package/app/apps/web/app/api/runs/[runId]/stream/route.ts +154 -0
- package/app/apps/web/app/api/runs/route.ts +266 -0
- package/app/apps/web/app/api/settings/route.ts +35 -0
- package/app/apps/web/app/day/[date]/day-view.tsx +193 -0
- package/app/apps/web/app/day/[date]/page.tsx +175 -0
- package/app/apps/web/app/day/page.tsx +8 -0
- package/app/apps/web/app/digest/[date]/page.tsx +15 -0
- package/app/apps/web/app/digest/page.tsx +7 -0
- package/app/apps/web/app/insights/[key]/page.tsx +106 -48
- package/app/apps/web/app/insights/page.tsx +133 -3
- package/app/apps/web/app/layout.tsx +23 -3
- package/app/apps/web/app/page.tsx +33 -4
- package/app/apps/web/app/parallelism/gantt-chart.tsx +67 -1
- package/app/apps/web/app/parallelism/page.tsx +8 -278
- package/app/apps/web/app/projects/[slug]/page.tsx +153 -0
- package/app/apps/web/app/projects/page.tsx +49 -4
- package/app/apps/web/app/projects/projects-view.tsx +79 -68
- package/app/apps/web/app/runs/page.tsx +21 -0
- package/app/apps/web/app/sessions/[id]/page.tsx +12 -1
- package/app/apps/web/app/sessions/[id]/session-view.tsx +569 -21
- package/app/apps/web/app/sessions/page.tsx +19 -3
- package/app/apps/web/app/sessions/sessions-grid.tsx +172 -131
- package/app/apps/web/app/settings/ai-features-form.tsx +45 -0
- package/app/apps/web/app/settings/page.tsx +20 -0
- package/app/apps/web/app/usage/page.tsx +45 -3
- package/app/apps/web/components/auto-generate-yesterday.tsx +96 -0
- package/app/apps/web/components/backfill-drawer.tsx +309 -0
- package/app/apps/web/components/dashboard-view.tsx +4 -2
- package/app/apps/web/components/date-nav.tsx +385 -0
- package/app/apps/web/components/day-digest-view.tsx +180 -0
- package/app/apps/web/components/day-digest.tsx +489 -0
- package/app/apps/web/components/flag-chip.tsx +54 -0
- package/app/apps/web/components/goal-bar.tsx +63 -0
- package/app/apps/web/components/heatmap.tsx +78 -1
- package/app/apps/web/components/helpfulness-sparkline.tsx +82 -0
- package/app/apps/web/components/insights-history.tsx +211 -0
- package/app/apps/web/components/insights-top-bar.tsx +216 -0
- package/app/apps/web/components/job-queue-widget.tsx +274 -0
- package/app/apps/web/components/live-sessions-widget.tsx +38 -3
- package/app/apps/web/components/month-digest-view.tsx +138 -0
- package/app/apps/web/components/month-digest.tsx +216 -0
- package/app/apps/web/components/outcome-mix-row.tsx +37 -0
- package/app/apps/web/components/outcome-pill.tsx +101 -0
- package/app/apps/web/components/previous-cycles-trend.tsx +155 -0
- package/app/apps/web/components/recent-days-panel.tsx +83 -0
- package/app/apps/web/components/runs-live-board.tsx +513 -0
- package/app/apps/web/components/sidebar.tsx +38 -4
- package/app/apps/web/components/usage-chart-range.tsx +58 -6
- package/app/apps/web/components/usage-chart.tsx +94 -7
- package/app/apps/web/components/usage-charts-dashboard.tsx +20 -1
- package/app/apps/web/components/week-digest-view.tsx +226 -0
- package/app/apps/web/components/week-digest.tsx +2128 -0
- package/app/apps/web/components/yesterday-hero.tsx +110 -0
- package/app/apps/web/lib/auto-week-fire.ts +37 -0
- package/app/apps/web/lib/calibration-data.ts +171 -0
- package/app/apps/web/lib/entries-index.ts +174 -0
- package/app/apps/web/lib/entries.ts +72 -0
- package/app/apps/web/lib/inflight-coalesce.test.ts +43 -0
- package/app/apps/web/lib/inflight-coalesce.ts +19 -0
- package/app/apps/web/lib/jobs.ts +170 -0
- package/app/apps/web/lib/usage-data.ts +37 -0
- package/app/apps/web/lib/validate-settings.test.ts +25 -0
- package/app/apps/web/lib/validate-settings.ts +9 -0
- package/app/apps/web/next.config.ts +1 -1
- package/app/apps/web/package.json +4 -2
- package/app/apps/web/server.js +1 -1
- package/app/apps/web/tsconfig.tsbuildinfo +1 -1
- package/app/apps/web/vitest.config.ts +9 -0
- package/dist/daemon-worker.js +1758 -713
- package/dist/index.js +11308 -1888
- package/package.json +4 -1
- package/app/apps/web/.next/server/app/api/insights/months-index/route/app-paths-manifest.json +0 -3
- package/app/apps/web/.next/server/app/api/insights/months-index/route.js +0 -7
- package/app/apps/web/.next/server/app/api/insights/months-index/route_client-reference-manifest.js +0 -3
- package/app/apps/web/.next/server/app/api/insights/pdf/[key]/route/app-paths-manifest.json +0 -3
- package/app/apps/web/.next/server/app/api/insights/pdf/[key]/route.js +0 -6
- package/app/apps/web/.next/server/app/api/insights/route/app-paths-manifest.json +0 -3
- package/app/apps/web/.next/server/app/api/insights/route.js +0 -8
- package/app/apps/web/.next/server/app/api/insights/saved/[key]/route/app-paths-manifest.json +0 -3
- package/app/apps/web/.next/server/app/api/insights/saved/[key]/route.js +0 -6
- package/app/apps/web/.next/server/app/api/insights/saved/[key]/route_client-reference-manifest.js +0 -3
- package/app/apps/web/.next/server/app/api/insights/saved/route/app-paths-manifest.json +0 -3
- package/app/apps/web/.next/server/app/api/insights/saved/route.js +0 -6
- package/app/apps/web/.next/server/app/api/insights/saved/route_client-reference-manifest.js +0 -3
- package/app/apps/web/.next/server/app/api/insights/weeks-index/route/app-paths-manifest.json +0 -3
- package/app/apps/web/.next/server/app/api/insights/weeks-index/route.js +0 -7
- package/app/apps/web/.next/server/app/api/insights/weeks-index/route_client-reference-manifest.js +0 -3
- package/app/apps/web/.next/server/app/insights/print/[key]/page/app-paths-manifest.json +0 -3
- package/app/apps/web/.next/server/app/insights/print/[key]/page.js.nft.json +0 -1
- package/app/apps/web/.next/server/app/insights/print/[key]/page_client-reference-manifest.js +0 -3
- package/app/apps/web/.next/server/chunks/02dz_web__next-internal_server_app_api_insights_months-index_route_actions_0~h~zci.js +0 -3
- package/app/apps/web/.next/server/chunks/02dz_web__next-internal_server_app_api_insights_saved_[key]_route_actions_0a5j9yw.js +0 -3
- package/app/apps/web/.next/server/chunks/02dz_web__next-internal_server_app_api_insights_weeks-index_route_actions_0hh-1c7.js +0 -3
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0.hmj0z._.js +0 -3
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__01h_g-p._.js +0 -3
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0nh-z10._.js +0 -3
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0ri7q~r._.js +0 -3
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0rr1~~x._.js +0 -3
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0s0gv.0._.js +0 -3
- package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_insights_pdf_[key]_route_actions_0lu-lnx.js +0 -3
- package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_insights_route_actions_0h8l5lz.js +0 -3
- package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_insights_saved_route_actions_13rlblw.js +0 -3
- package/app/apps/web/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_00t2xj6.js +0 -68
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0.tsxpj._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__00z7zlm._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__08pen0k._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0b323~k._.js +0 -8
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0gx-4qa._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0wv27wt._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__13itnvx._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/_09n75_5._.js +0 -8
- package/app/apps/web/.next/server/chunks/ssr/_0r~__0v._.js +0 -12
- package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_insights_print_[key]_page_actions_0a853fw.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/apps_web_app_parallelism_08vub.0._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_06j3c.0._.js +0 -8
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0bbo_pd._.js +0 -8
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_insight-report_tsx_13q2a-c._.js +0 -12
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_insights-view_tsx_11730ta._.js +0 -6
- package/app/apps/web/.next/server/chunks/ssr/node_modules_lucide-react_dist_esm_icons_0nqz8dw._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_0t-hj0x._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_analytics_0k4dgst.js +0 -3
- package/app/apps/web/.next/static/chunks/028_pmk40b69_.js +0 -6
- package/app/apps/web/.next/static/chunks/03.mv4y4.w-vb.js +0 -6
- package/app/apps/web/.next/static/chunks/03_7xtpi9sv4g.js +0 -4
- package/app/apps/web/.next/static/chunks/03g5dw5eskotd.js +0 -6
- package/app/apps/web/.next/static/chunks/063oimt30jeo9.js +0 -10
- package/app/apps/web/.next/static/chunks/08c1pcrocqq5s.js +0 -6
- package/app/apps/web/.next/static/chunks/0e-wrhqh4h3r5.js +0 -2
- package/app/apps/web/.next/static/chunks/0fc6dk2qtokwh.js +0 -1
- package/app/apps/web/.next/static/chunks/0i7er7_bfab36.js +0 -10
- package/app/apps/web/.next/static/chunks/0ipytyi01h0ta.js +0 -1
- package/app/apps/web/.next/static/chunks/0lsznd4_avzhv.js +0 -6
- package/app/apps/web/.next/static/chunks/0lty3v_i9mde7.js +0 -1
- package/app/apps/web/.next/static/chunks/0vekjjj4pidlz.css +0 -1
- package/app/apps/web/.next/static/chunks/137uw2-qbro07.js +0 -31
- package/app/apps/web/app/api/insights/months-index/route.ts +0 -80
- package/app/apps/web/app/api/insights/pdf/[key]/route.ts +0 -45
- package/app/apps/web/app/api/insights/route.ts +0 -508
- package/app/apps/web/app/api/insights/saved/[key]/route.ts +0 -11
- package/app/apps/web/app/api/insights/saved/route.ts +0 -9
- package/app/apps/web/app/insights/print/[key]/page.tsx +0 -73
- package/app/apps/web/components/insight-report.tsx +0 -1031
- package/app/apps/web/components/insights-view.tsx +0 -647
- package/app/apps/web/lib/ai/insights-prompt.ts +0 -71
- package/app/apps/web/lib/ai/saved-reports.ts +0 -83
- /package/app/apps/web/.next/server/app/api/{insights/months-index → digest/day/[date]}/route/build-manifest.json +0 -0
- /package/app/apps/web/.next/server/app/api/{insights/months-index → digest/day/[date]}/route/server-reference-manifest.json +0 -0
- /package/app/apps/web/.next/server/app/api/{insights/months-index → digest/day/[date]}/route.js.map +0 -0
- /package/app/apps/web/.next/server/app/api/{insights → digest/month/[yearMonth]}/route/build-manifest.json +0 -0
- /package/app/apps/web/.next/server/app/api/{insights → digest/month/[yearMonth]}/route/server-reference-manifest.json +0 -0
- /package/app/apps/web/.next/server/app/api/{insights → digest/month/[yearMonth]}/route.js.map +0 -0
- /package/app/apps/web/.next/server/app/api/{insights/pdf/[key] → digest/month-index}/route/build-manifest.json +0 -0
- /package/app/apps/web/.next/server/app/api/{insights/pdf/[key] → digest/month-index}/route/server-reference-manifest.json +0 -0
- /package/app/apps/web/.next/server/app/api/{insights/pdf/[key] → digest/month-index}/route.js.map +0 -0
- /package/app/apps/web/.next/server/app/api/{insights/saved → digest/week/[startDate]}/route/build-manifest.json +0 -0
- /package/app/apps/web/.next/server/app/api/{insights/saved → digest/week/[startDate]}/route/server-reference-manifest.json +0 -0
- /package/app/apps/web/.next/server/app/api/{insights/saved → digest/week/[startDate]}/route.js.map +0 -0
- /package/app/apps/web/.next/server/app/api/{insights/saved/[key] → digest/week-index}/route/build-manifest.json +0 -0
- /package/app/apps/web/.next/server/app/api/{insights/saved/[key] → digest/week-index}/route/server-reference-manifest.json +0 -0
- /package/app/apps/web/.next/server/app/api/{insights/saved/[key] → digest/week-index}/route.js.map +0 -0
- /package/app/apps/web/.next/server/app/api/{insights/weeks-index → jobs}/route/build-manifest.json +0 -0
- /package/app/apps/web/.next/server/app/api/{insights/weeks-index → jobs}/route/server-reference-manifest.json +0 -0
- /package/app/apps/web/.next/server/app/api/{insights/weeks-index → jobs}/route.js.map +0 -0
- /package/app/apps/web/.next/server/app/{insights/print/[key]/page → api/runs/[runId]/route}/server-reference-manifest.json +0 -0
- /package/app/apps/web/.next/server/app/{insights/print/[key]/page.js.map → api/runs/[runId]/route.js.map} +0 -0
- /package/app/apps/web/.next/server/app/{insights/print/[key] → day/[date]}/page/next-font-manifest.json +0 -0
- /package/app/apps/web/.next/server/app/{insights/print/[key] → day/[date]}/page/react-loadable-manifest.json +0 -0
- /package/app/apps/web/.next/static/{G_4ofKI9v9ARC_lb9JILZ → 8tTWPvUhtatZEoocIhamh}/_buildManifest.js +0 -0
- /package/app/apps/web/.next/static/{G_4ofKI9v9ARC_lb9JILZ → 8tTWPvUhtatZEoocIhamh}/_clientMiddlewareManifest.js +0 -0
- /package/app/apps/web/.next/static/{G_4ofKI9v9ARC_lb9JILZ → 8tTWPvUhtatZEoocIhamh}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import { existsSync, readFileSync, readdirSync, statSync, openSync, readSync, closeSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
|
|
6
|
+
export const runtime = "nodejs";
|
|
7
|
+
export const dynamic = "force-dynamic";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* GET /api/runs?since=24h
|
|
11
|
+
*
|
|
12
|
+
* Mirrors `fleetlens runs --json`. Returns a snapshot of currently-running
|
|
13
|
+
* LLM subprocesses (week_digest / top_session / day_digest / entry_enrich)
|
|
14
|
+
* plus aggregated token spend in the requested window.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const KIND_MARKERS: Array<{ kind: string; marker: RegExp }> = [
|
|
18
|
+
{ kind: "week_digest", marker: /weekly retrospective writer/i },
|
|
19
|
+
{ kind: "top_session", marker: /editorial perception layer for ONE session/i },
|
|
20
|
+
{ kind: "day_digest", marker: /single local day into a short, honest narrative/i },
|
|
21
|
+
{ kind: "entry_enrich", marker: /per[- ]entry|enrich.{0,40}entry|brief_summary/i },
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
function detectKind(cmdline: string): string {
|
|
25
|
+
for (const { kind, marker } of KIND_MARKERS) {
|
|
26
|
+
if (marker.test(cmdline)) return kind;
|
|
27
|
+
}
|
|
28
|
+
return "unknown";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function parseModel(cmdline: string): string {
|
|
32
|
+
const m = cmdline.match(/--model\s+(\S+)/);
|
|
33
|
+
return m ? m[1]! : "?";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
type ActiveRun = {
|
|
37
|
+
pid: number;
|
|
38
|
+
kind: string;
|
|
39
|
+
model: string;
|
|
40
|
+
elapsed_s: number;
|
|
41
|
+
cpu_time: string;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
function etimeToSec(s: string): number {
|
|
45
|
+
const m = s.match(/^(?:(\d+)-)?(?:(\d+):)?(\d+):(\d+)$/);
|
|
46
|
+
if (!m) return 0;
|
|
47
|
+
const [, dStr, hStr, mStr, secStr] = m;
|
|
48
|
+
return Number(dStr ?? 0) * 86400 + Number(hStr ?? 0) * 3600 + Number(mStr ?? 0) * 60 + Number(secStr ?? 0);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function listActiveRuns(): ActiveRun[] {
|
|
52
|
+
let out: string;
|
|
53
|
+
try {
|
|
54
|
+
out = execSync("ps -axww -o pid,etime,time,command", { encoding: "utf-8" });
|
|
55
|
+
} catch {
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
const runs: ActiveRun[] = [];
|
|
59
|
+
for (const line of out.split("\n")) {
|
|
60
|
+
if (!line.includes("claude -p")) continue;
|
|
61
|
+
if (!line.includes("--append-system-prompt")) continue;
|
|
62
|
+
if (line.includes("grep")) continue;
|
|
63
|
+
const m = line.trim().match(/^(\d+)\s+(\S+)\s+([\d:.]+)\s+(.+)$/);
|
|
64
|
+
if (!m) continue;
|
|
65
|
+
const [, pidStr, etimeStr, cputime, command] = m;
|
|
66
|
+
runs.push({
|
|
67
|
+
pid: Number(pidStr),
|
|
68
|
+
kind: detectKind(command!),
|
|
69
|
+
model: parseModel(command!),
|
|
70
|
+
elapsed_s: etimeToSec(etimeStr!),
|
|
71
|
+
cpu_time: cputime!,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return runs.sort((a, b) => a.elapsed_s - b.elapsed_s);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const SPEND_PATH = join(homedir(), ".cclens", "llm-spend.jsonl");
|
|
78
|
+
|
|
79
|
+
type CompletedRun = {
|
|
80
|
+
ts: string;
|
|
81
|
+
kind: string;
|
|
82
|
+
ref: string;
|
|
83
|
+
model: string;
|
|
84
|
+
input_tokens: number;
|
|
85
|
+
output_tokens: number;
|
|
86
|
+
cost_usd: number;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
function readSpend(sinceMs: number): CompletedRun[] {
|
|
90
|
+
if (!existsSync(SPEND_PATH)) return [];
|
|
91
|
+
const lines = readFileSync(SPEND_PATH, "utf-8").split("\n").filter(l => l.trim());
|
|
92
|
+
const out: CompletedRun[] = [];
|
|
93
|
+
for (const line of lines) {
|
|
94
|
+
try {
|
|
95
|
+
const r = JSON.parse(line);
|
|
96
|
+
const ts = Date.parse(r.ts);
|
|
97
|
+
if (Number.isNaN(ts) || ts < sinceMs) continue;
|
|
98
|
+
out.push({
|
|
99
|
+
ts: r.ts,
|
|
100
|
+
kind: r.kind ?? "?",
|
|
101
|
+
ref: r.ref ?? "",
|
|
102
|
+
model: r.model ?? "?",
|
|
103
|
+
input_tokens: r.input_tokens ?? 0,
|
|
104
|
+
output_tokens: r.output_tokens ?? 0,
|
|
105
|
+
cost_usd: r.cost_usd ?? 0,
|
|
106
|
+
});
|
|
107
|
+
} catch { /* skip */ }
|
|
108
|
+
}
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function parseSince(s: string | null): number {
|
|
113
|
+
if (!s) return Date.now() - 24 * 3_600_000;
|
|
114
|
+
const m = s.match(/^(\d+)([smhd])$/);
|
|
115
|
+
if (m) {
|
|
116
|
+
const n = Number(m[1]);
|
|
117
|
+
const unit = m[2];
|
|
118
|
+
const mult = unit === "s" ? 1000 : unit === "m" ? 60_000 : unit === "h" ? 3_600_000 : 86_400_000;
|
|
119
|
+
return Date.now() - n * mult;
|
|
120
|
+
}
|
|
121
|
+
const t = Date.parse(s);
|
|
122
|
+
if (!Number.isNaN(t)) return t;
|
|
123
|
+
return Date.now() - 24 * 3_600_000;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const RUNS_DIR = join(homedir(), ".cclens", "llm-runs");
|
|
127
|
+
|
|
128
|
+
type TraceSummary = {
|
|
129
|
+
run_id: string;
|
|
130
|
+
kind: string;
|
|
131
|
+
model: string;
|
|
132
|
+
pid: number | null;
|
|
133
|
+
started_at: string;
|
|
134
|
+
ended_at: string | null;
|
|
135
|
+
elapsed_ms: number | null;
|
|
136
|
+
exit_code: number | null;
|
|
137
|
+
status: "running" | "ok" | "error" | "unknown";
|
|
138
|
+
content_chars: number | null;
|
|
139
|
+
output_tokens: number | null;
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
function listRecentTraces(limit: number): TraceSummary[] {
|
|
143
|
+
if (!existsSync(RUNS_DIR)) return [];
|
|
144
|
+
const files = readdirSync(RUNS_DIR)
|
|
145
|
+
.filter(f => f.endsWith(".jsonl"))
|
|
146
|
+
.map(f => ({ id: f.replace(/\.jsonl$/, ""), path: join(RUNS_DIR, f), mtime: statSync(join(RUNS_DIR, f)).mtimeMs }))
|
|
147
|
+
.sort((a, b) => b.mtime - a.mtime)
|
|
148
|
+
.slice(0, limit);
|
|
149
|
+
|
|
150
|
+
const out: TraceSummary[] = [];
|
|
151
|
+
for (const f of files) {
|
|
152
|
+
let start: { ts?: string; kind?: string; model?: string } | null = null;
|
|
153
|
+
let spawned: { pid?: number } | null = null;
|
|
154
|
+
let end: { ts?: string; elapsed_ms?: number; exit_code?: number; content_chars?: number; output_tokens?: number } | null = null;
|
|
155
|
+
let spawnError: { ts?: string } | null = null;
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
// Read first ~16KB (start + spawned + maybe payload) and last ~4KB (end record)
|
|
159
|
+
const stat = statSync(f.path);
|
|
160
|
+
const headSize = Math.min(16_384, stat.size);
|
|
161
|
+
const tailSize = Math.min(4_096, stat.size);
|
|
162
|
+
const buf = Buffer.alloc(headSize);
|
|
163
|
+
const fd = openSync(f.path, "r");
|
|
164
|
+
try {
|
|
165
|
+
readSync(fd, buf, 0, headSize, 0);
|
|
166
|
+
} finally {
|
|
167
|
+
closeSync(fd);
|
|
168
|
+
}
|
|
169
|
+
const head = buf.toString("utf-8");
|
|
170
|
+
// Parse every _meta record visible in head — start, spawned, AND end /
|
|
171
|
+
// spawn_error. Previously end/spawn_error were only checked in the tail
|
|
172
|
+
// block, which got skipped when the file fit entirely in headSize. That
|
|
173
|
+
// left small completed traces (~10-15KB entry-enrich files) stuck at
|
|
174
|
+
// status="running" forever, even though their end record was already in
|
|
175
|
+
// the head buffer.
|
|
176
|
+
for (const line of head.split("\n")) {
|
|
177
|
+
if (!line.trim()) continue;
|
|
178
|
+
try {
|
|
179
|
+
const obj = JSON.parse(line) as { _meta?: { type?: string; ts?: string; kind?: string; model?: string; pid?: number; elapsed_ms?: number; exit_code?: number; content_chars?: number; output_tokens?: number } };
|
|
180
|
+
const t = obj._meta?.type;
|
|
181
|
+
if (t === "start") start = obj._meta!;
|
|
182
|
+
else if (t === "spawned") spawned = obj._meta!;
|
|
183
|
+
else if (t === "end") end = obj._meta!;
|
|
184
|
+
else if (t === "spawn_error") spawnError = obj._meta!;
|
|
185
|
+
} catch { /* skip */ }
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (!end && !spawnError && stat.size > headSize) {
|
|
189
|
+
const tailBuf = Buffer.alloc(tailSize);
|
|
190
|
+
const fd2 = openSync(f.path, "r");
|
|
191
|
+
try {
|
|
192
|
+
readSync(fd2, tailBuf, 0, tailSize, stat.size - tailSize);
|
|
193
|
+
} finally {
|
|
194
|
+
closeSync(fd2);
|
|
195
|
+
}
|
|
196
|
+
const tail = tailBuf.toString("utf-8");
|
|
197
|
+
for (const line of tail.split("\n").reverse()) {
|
|
198
|
+
if (!line.trim()) continue;
|
|
199
|
+
try {
|
|
200
|
+
const obj = JSON.parse(line) as { _meta?: { type?: string; ts?: string; elapsed_ms?: number; exit_code?: number; content_chars?: number; output_tokens?: number } };
|
|
201
|
+
if (obj._meta?.type === "end") { end = obj._meta; break; }
|
|
202
|
+
if (obj._meta?.type === "spawn_error") { spawnError = obj._meta; break; }
|
|
203
|
+
} catch { /* skip */ }
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
} catch { /* skip */ }
|
|
207
|
+
|
|
208
|
+
const status: TraceSummary["status"] =
|
|
209
|
+
end ? (end.exit_code === 0 ? "ok" : "error")
|
|
210
|
+
: spawnError ? "error"
|
|
211
|
+
: start ? "running"
|
|
212
|
+
: "unknown";
|
|
213
|
+
|
|
214
|
+
out.push({
|
|
215
|
+
run_id: f.id,
|
|
216
|
+
kind: start?.kind ?? "?",
|
|
217
|
+
model: start?.model ?? "?",
|
|
218
|
+
pid: spawned?.pid ?? null,
|
|
219
|
+
started_at: start?.ts ?? "",
|
|
220
|
+
ended_at: end?.ts ?? null,
|
|
221
|
+
elapsed_ms: end?.elapsed_ms ?? null,
|
|
222
|
+
exit_code: end?.exit_code ?? null,
|
|
223
|
+
status,
|
|
224
|
+
content_chars: end?.content_chars ?? null,
|
|
225
|
+
output_tokens: end?.output_tokens ?? null,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
return out;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export async function GET(req: Request): Promise<Response> {
|
|
232
|
+
const url = new URL(req.url);
|
|
233
|
+
const sinceMs = parseSince(url.searchParams.get("since"));
|
|
234
|
+
const traceLimit = Number(url.searchParams.get("trace_limit") ?? "30");
|
|
235
|
+
const active = listActiveRuns();
|
|
236
|
+
const completed = readSpend(sinceMs);
|
|
237
|
+
const traces = listRecentTraces(traceLimit);
|
|
238
|
+
|
|
239
|
+
type Totals = { ops: number; input_tokens: number; output_tokens: number; cost_usd: number };
|
|
240
|
+
const totals: Totals = { ops: completed.length, input_tokens: 0, output_tokens: 0, cost_usd: 0 };
|
|
241
|
+
const byKind: Record<string, Totals> = {};
|
|
242
|
+
for (const r of completed) {
|
|
243
|
+
totals.input_tokens += r.input_tokens;
|
|
244
|
+
totals.output_tokens += r.output_tokens;
|
|
245
|
+
totals.cost_usd += r.cost_usd;
|
|
246
|
+
const k = byKind[r.kind] ?? { ops: 0, input_tokens: 0, output_tokens: 0, cost_usd: 0 };
|
|
247
|
+
k.ops += 1;
|
|
248
|
+
k.input_tokens += r.input_tokens;
|
|
249
|
+
k.output_tokens += r.output_tokens;
|
|
250
|
+
k.cost_usd += r.cost_usd;
|
|
251
|
+
byKind[r.kind] = k;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return new Response(JSON.stringify({
|
|
255
|
+
generated_at: new Date().toISOString(),
|
|
256
|
+
active,
|
|
257
|
+
completed_since_ms: sinceMs,
|
|
258
|
+
totals,
|
|
259
|
+
by_kind: byKind,
|
|
260
|
+
completed,
|
|
261
|
+
traces,
|
|
262
|
+
}, null, 2), {
|
|
263
|
+
status: 200,
|
|
264
|
+
headers: { "content-type": "application/json" },
|
|
265
|
+
});
|
|
266
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import { readSettings, writeSettings, monthToDateSpend } from "@claude-lens/entries/node";
|
|
3
|
+
import { SettingsUpdateSchema } from "@/lib/validate-settings";
|
|
4
|
+
|
|
5
|
+
export const runtime = "nodejs";
|
|
6
|
+
|
|
7
|
+
export async function GET() {
|
|
8
|
+
return NextResponse.json({
|
|
9
|
+
settings: readSettings(),
|
|
10
|
+
month_to_date_spend_usd: monthToDateSpend(),
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function PUT(req: Request) {
|
|
15
|
+
let raw: unknown;
|
|
16
|
+
try {
|
|
17
|
+
raw = await req.json();
|
|
18
|
+
} catch {
|
|
19
|
+
return NextResponse.json({ error: "invalid JSON body" }, { status: 400 });
|
|
20
|
+
}
|
|
21
|
+
const parsed = SettingsUpdateSchema.safeParse(raw);
|
|
22
|
+
if (!parsed.success) {
|
|
23
|
+
return NextResponse.json(
|
|
24
|
+
{ error: "schema validation failed", issues: parsed.error.issues },
|
|
25
|
+
{ status: 400 },
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
// Preserve other on-disk fields (model, monthlyBudgetUsd) — UI no longer edits
|
|
29
|
+
// them, but the settings module and queue still read them. Only enabled flips.
|
|
30
|
+
const current = readSettings();
|
|
31
|
+
writeSettings({
|
|
32
|
+
ai_features: { ...current.ai_features, enabled: parsed.data.ai_features.enabled },
|
|
33
|
+
});
|
|
34
|
+
return NextResponse.json({ ok: true });
|
|
35
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { ChevronDown, ChevronRight, Layers } from "lucide-react";
|
|
5
|
+
import type { DayDigest, Entry } from "@claude-lens/entries";
|
|
6
|
+
import type { GanttDay, ParallelismBurst } from "@claude-lens/parser";
|
|
7
|
+
import { DayDigestView } from "@/components/day-digest-view";
|
|
8
|
+
import { GanttChart, type SessionEntrySummary } from "../../parallelism/gantt-chart";
|
|
9
|
+
import { BackfillDrawer, type BackfillRow } from "@/components/backfill-drawer";
|
|
10
|
+
import { DateNav, type DayInfo } from "@/components/date-nav";
|
|
11
|
+
|
|
12
|
+
export function DayView({
|
|
13
|
+
date,
|
|
14
|
+
today,
|
|
15
|
+
prev,
|
|
16
|
+
next,
|
|
17
|
+
initial,
|
|
18
|
+
entries,
|
|
19
|
+
aiEnabled,
|
|
20
|
+
gantt,
|
|
21
|
+
bursts,
|
|
22
|
+
sessionEntries,
|
|
23
|
+
backfillRows,
|
|
24
|
+
dayStats,
|
|
25
|
+
}: {
|
|
26
|
+
date: string;
|
|
27
|
+
today: string;
|
|
28
|
+
prev: string;
|
|
29
|
+
next: string | null;
|
|
30
|
+
initial: DayDigest | null;
|
|
31
|
+
entries: Entry[];
|
|
32
|
+
aiEnabled: boolean;
|
|
33
|
+
gantt: GanttDay;
|
|
34
|
+
bursts: ParallelismBurst[];
|
|
35
|
+
sessionEntries: Record<string, SessionEntrySummary>;
|
|
36
|
+
backfillRows: BackfillRow[];
|
|
37
|
+
dayStats: DayInfo[];
|
|
38
|
+
}) {
|
|
39
|
+
const [drawerOpen, setDrawerOpen] = useState(false);
|
|
40
|
+
// Narrative section is suppressed when every entry is `skipped_trivial` —
|
|
41
|
+
// that's a "warm-up only" day with nothing to summarize, so the section
|
|
42
|
+
// would just be a header above an empty placeholder. Keep the timeline
|
|
43
|
+
// accessible via its own collapsible.
|
|
44
|
+
const allTrivial = entries.length > 0
|
|
45
|
+
&& entries.every((e) => e.enrichment.status === "skipped_trivial");
|
|
46
|
+
const hasNarrative = entries.length > 0 && !allTrivial;
|
|
47
|
+
const hasTimeline = gantt.sessions.length > 0;
|
|
48
|
+
|
|
49
|
+
const fmtDate = new Date(`${date}T12:00:00`).toLocaleDateString("en-US", {
|
|
50
|
+
weekday: "long", month: "long", day: "numeric", year: "numeric",
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const pendingCount = backfillRows.filter((r) => r.status === "pending").length;
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<>
|
|
57
|
+
<nav
|
|
58
|
+
style={{
|
|
59
|
+
padding: "14px 40px",
|
|
60
|
+
display: "flex",
|
|
61
|
+
gap: 12,
|
|
62
|
+
fontSize: 12,
|
|
63
|
+
borderBottom: "1px solid var(--af-border-subtle)",
|
|
64
|
+
alignItems: "center",
|
|
65
|
+
flexWrap: "wrap",
|
|
66
|
+
}}
|
|
67
|
+
>
|
|
68
|
+
<DateNav
|
|
69
|
+
date={date}
|
|
70
|
+
today={today}
|
|
71
|
+
prevDay={prev}
|
|
72
|
+
nextDay={next ?? undefined}
|
|
73
|
+
dayStats={dayStats}
|
|
74
|
+
/>
|
|
75
|
+
|
|
76
|
+
<button
|
|
77
|
+
type="button"
|
|
78
|
+
onClick={() => setDrawerOpen(true)}
|
|
79
|
+
style={{
|
|
80
|
+
marginLeft: "auto",
|
|
81
|
+
display: "inline-flex",
|
|
82
|
+
alignItems: "center",
|
|
83
|
+
gap: 5,
|
|
84
|
+
padding: "5px 10px",
|
|
85
|
+
background: "transparent",
|
|
86
|
+
border: "1px solid var(--af-border-subtle)",
|
|
87
|
+
borderRadius: 6,
|
|
88
|
+
fontSize: 11,
|
|
89
|
+
color: "var(--af-text-secondary)",
|
|
90
|
+
cursor: "pointer",
|
|
91
|
+
}}
|
|
92
|
+
title="Open the backfill multi-select drawer"
|
|
93
|
+
>
|
|
94
|
+
<Layers size={12} />
|
|
95
|
+
Backfill digests
|
|
96
|
+
{pendingCount > 0 && (
|
|
97
|
+
<span
|
|
98
|
+
style={{
|
|
99
|
+
fontSize: 10,
|
|
100
|
+
color: "#ed8936",
|
|
101
|
+
fontWeight: 700,
|
|
102
|
+
}}
|
|
103
|
+
>
|
|
104
|
+
{pendingCount}
|
|
105
|
+
</span>
|
|
106
|
+
)}
|
|
107
|
+
</button>
|
|
108
|
+
</nav>
|
|
109
|
+
|
|
110
|
+
{!hasNarrative && !hasTimeline ? (
|
|
111
|
+
<div
|
|
112
|
+
style={{
|
|
113
|
+
padding: "60px 40px",
|
|
114
|
+
textAlign: "center",
|
|
115
|
+
color: "var(--af-text-secondary)",
|
|
116
|
+
}}
|
|
117
|
+
>
|
|
118
|
+
<div style={{ fontSize: 14, marginBottom: 6 }}>{fmtDate}</div>
|
|
119
|
+
<div style={{ fontSize: 13, color: "var(--af-text-tertiary)" }}>
|
|
120
|
+
No Claude Code activity on this day.
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
) : (
|
|
124
|
+
<div style={{ display: "flex", flexDirection: "column", gap: 0 }}>
|
|
125
|
+
{hasNarrative && (
|
|
126
|
+
<Section label="Narrative" defaultOpen>
|
|
127
|
+
<DayDigestView
|
|
128
|
+
initial={initial}
|
|
129
|
+
entries={entries}
|
|
130
|
+
date={date}
|
|
131
|
+
aiEnabled={aiEnabled}
|
|
132
|
+
/>
|
|
133
|
+
</Section>
|
|
134
|
+
)}
|
|
135
|
+
{hasTimeline && (
|
|
136
|
+
<Section label="Timeline & concurrency" defaultOpen>
|
|
137
|
+
<div style={{ padding: "8px 40px 40px" }}>
|
|
138
|
+
<GanttChart gantt={gantt} bursts={bursts} sessionEntries={sessionEntries} />
|
|
139
|
+
</div>
|
|
140
|
+
</Section>
|
|
141
|
+
)}
|
|
142
|
+
</div>
|
|
143
|
+
)}
|
|
144
|
+
|
|
145
|
+
<BackfillDrawer
|
|
146
|
+
open={drawerOpen}
|
|
147
|
+
onClose={() => setDrawerOpen(false)}
|
|
148
|
+
rows={backfillRows}
|
|
149
|
+
aiEnabled={aiEnabled}
|
|
150
|
+
/>
|
|
151
|
+
</>
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function Section({
|
|
156
|
+
label,
|
|
157
|
+
defaultOpen = true,
|
|
158
|
+
children,
|
|
159
|
+
}: {
|
|
160
|
+
label: string;
|
|
161
|
+
defaultOpen?: boolean;
|
|
162
|
+
children: React.ReactNode;
|
|
163
|
+
}) {
|
|
164
|
+
const [open, setOpen] = useState(defaultOpen);
|
|
165
|
+
return (
|
|
166
|
+
<div style={{ borderBottom: "1px solid var(--af-border-subtle)" }}>
|
|
167
|
+
<button
|
|
168
|
+
type="button"
|
|
169
|
+
onClick={() => setOpen((v) => !v)}
|
|
170
|
+
style={{
|
|
171
|
+
width: "100%",
|
|
172
|
+
padding: "12px 40px",
|
|
173
|
+
background: "transparent",
|
|
174
|
+
border: "none",
|
|
175
|
+
textAlign: "left",
|
|
176
|
+
display: "flex",
|
|
177
|
+
alignItems: "center",
|
|
178
|
+
gap: 8,
|
|
179
|
+
cursor: "pointer",
|
|
180
|
+
fontSize: 11,
|
|
181
|
+
fontWeight: 700,
|
|
182
|
+
color: "var(--af-text-tertiary)",
|
|
183
|
+
textTransform: "uppercase",
|
|
184
|
+
letterSpacing: "0.08em",
|
|
185
|
+
}}
|
|
186
|
+
>
|
|
187
|
+
{open ? <ChevronDown size={13} /> : <ChevronRight size={13} />}
|
|
188
|
+
{label}
|
|
189
|
+
</button>
|
|
190
|
+
{open && <div>{children}</div>}
|
|
191
|
+
</div>
|
|
192
|
+
);
|
|
193
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { listSessions, getSession } from "@/lib/data";
|
|
2
|
+
import {
|
|
3
|
+
buildGanttDay,
|
|
4
|
+
computeParallelismBursts,
|
|
5
|
+
computeBurstsFromSessions,
|
|
6
|
+
dailyActivity,
|
|
7
|
+
type GanttDay,
|
|
8
|
+
type ParallelismBurst,
|
|
9
|
+
} from "@claude-lens/parser";
|
|
10
|
+
import { toLocalDay as toLocalDayParser } from "@claude-lens/parser";
|
|
11
|
+
import { readDayDigest, listEntriesForDay } from "@claude-lens/entries/fs";
|
|
12
|
+
import { readSettings, buildDeterministicDigest, getTodayDigestFromCache } from "@claude-lens/entries/node";
|
|
13
|
+
import type { DayDigest } from "@claude-lens/entries";
|
|
14
|
+
import { isValidDate, todayLocal, toLocalDay } from "@/lib/entries";
|
|
15
|
+
import { buildEntriesIndex } from "@/lib/entries-index";
|
|
16
|
+
import type { SessionEntrySummary } from "../../parallelism/gantt-chart";
|
|
17
|
+
import type { BackfillRow } from "@/components/backfill-drawer";
|
|
18
|
+
import type { DayInfo } from "@/components/date-nav";
|
|
19
|
+
import { DayView } from "./day-view";
|
|
20
|
+
import Link from "next/link";
|
|
21
|
+
import { notFound } from "next/navigation";
|
|
22
|
+
|
|
23
|
+
export const dynamic = "force-dynamic";
|
|
24
|
+
|
|
25
|
+
const BACKFILL_DAYS = 30;
|
|
26
|
+
|
|
27
|
+
function addDays(date: string, n: number): string {
|
|
28
|
+
const [y, m, d] = date.split("-").map(Number);
|
|
29
|
+
const dt = new Date(y!, (m ?? 1) - 1, d, 12);
|
|
30
|
+
dt.setDate(dt.getDate() + n);
|
|
31
|
+
return `${dt.getFullYear()}-${String(dt.getMonth() + 1).padStart(2, "0")}-${String(dt.getDate()).padStart(2, "0")}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function buildBackfillRows(): BackfillRow[] {
|
|
35
|
+
const out: BackfillRow[] = [];
|
|
36
|
+
const now = Date.now();
|
|
37
|
+
for (let i = 0; i < BACKFILL_DAYS; i++) {
|
|
38
|
+
const d = toLocalDay(now - i * 86_400_000);
|
|
39
|
+
const entries = listEntriesForDay(d);
|
|
40
|
+
const digest = readDayDigest(d);
|
|
41
|
+
const status: BackfillRow["status"] = entries.length === 0 ? "empty"
|
|
42
|
+
: digest && digest.headline ? "generated"
|
|
43
|
+
: "pending";
|
|
44
|
+
const label = i === 0 ? "Today"
|
|
45
|
+
: i === 1 ? "Yesterday"
|
|
46
|
+
: new Date(`${d}T12:00:00`).toLocaleDateString("en-US", {
|
|
47
|
+
weekday: "short", month: "short", day: "numeric",
|
|
48
|
+
});
|
|
49
|
+
out.push({
|
|
50
|
+
date: d,
|
|
51
|
+
day_label: label,
|
|
52
|
+
entry_count: entries.length,
|
|
53
|
+
pr_count: entries.reduce((s, e) => s + e.pr_titles.length, 0),
|
|
54
|
+
status,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export default async function DayPage({
|
|
61
|
+
params,
|
|
62
|
+
}: {
|
|
63
|
+
params: Promise<{ date: string }>;
|
|
64
|
+
}) {
|
|
65
|
+
const { date } = await params;
|
|
66
|
+
if (!isValidDate(date)) return notFound();
|
|
67
|
+
|
|
68
|
+
const today = todayLocal();
|
|
69
|
+
if (date > today) {
|
|
70
|
+
return (
|
|
71
|
+
<div style={{ padding: "40px" }}>
|
|
72
|
+
<h1>Future date</h1>
|
|
73
|
+
<p>Day views only exist for past and current days.</p>
|
|
74
|
+
<Link href={`/day/${today}`}>Go to today →</Link>
|
|
75
|
+
</div>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ---- Narrative side (digest + entries) ----
|
|
80
|
+
const settings = readSettings();
|
|
81
|
+
const aiEnabled = settings.ai_features.enabled;
|
|
82
|
+
const entries = listEntriesForDay(date);
|
|
83
|
+
// Today's digest lives only in the 10-min in-memory TTL cache — never on disk.
|
|
84
|
+
// Falling back to deterministic-only would erase the LLM narrative the user
|
|
85
|
+
// just generated; the today branch reads the cache instead of disk.
|
|
86
|
+
let initial: DayDigest | null = date === today
|
|
87
|
+
? getTodayDigestFromCache(date, Date.now())
|
|
88
|
+
: readDayDigest(date);
|
|
89
|
+
if (!initial && entries.length > 0) initial = buildDeterministicDigest(date, entries);
|
|
90
|
+
|
|
91
|
+
// ---- Timeline side (Gantt) ----
|
|
92
|
+
const [y, m, d] = date.split("-").map(Number) as [number, number, number];
|
|
93
|
+
const dayStartMs = new Date(y, m - 1, d).getTime();
|
|
94
|
+
const dayEndMs = new Date(y, m - 1, d + 1).getTime();
|
|
95
|
+
const filterStartMs = dayStartMs - 24 * 60 * 60 * 1000;
|
|
96
|
+
const filterEndMs = dayEndMs + 24 * 60 * 60 * 1000;
|
|
97
|
+
const allSessions = await listSessions();
|
|
98
|
+
const candidates = allSessions.filter((s) => {
|
|
99
|
+
if (!s.firstTimestamp) return false;
|
|
100
|
+
const startMs = Date.parse(s.firstTimestamp);
|
|
101
|
+
if (Number.isNaN(startMs)) return false;
|
|
102
|
+
const endMs = s.lastTimestamp ? Date.parse(s.lastTimestamp) : startMs;
|
|
103
|
+
return endMs >= filterStartMs && startMs <= filterEndMs;
|
|
104
|
+
});
|
|
105
|
+
const details = (
|
|
106
|
+
await Promise.all(candidates.slice(0, 80).map((s) => getSession(s.id)))
|
|
107
|
+
).filter((d): d is NonNullable<typeof d> => !!d);
|
|
108
|
+
const gantt: GanttDay = buildGanttDay(details, date);
|
|
109
|
+
const bursts: ParallelismBurst[] = computeParallelismBursts(gantt);
|
|
110
|
+
|
|
111
|
+
const entriesIndex = await buildEntriesIndex();
|
|
112
|
+
const sessionEntries: Record<string, SessionEntrySummary> = {};
|
|
113
|
+
for (const s of gantt.sessions) {
|
|
114
|
+
const list = entriesIndex.bySession.get(s.id) ?? [];
|
|
115
|
+
const e = list.find((e) => e.local_day === date);
|
|
116
|
+
if (!e) continue;
|
|
117
|
+
sessionEntries[s.id] = {
|
|
118
|
+
outcome: e.enrichment.outcome ?? null,
|
|
119
|
+
briefSummary: e.enrichment.brief_summary ?? null,
|
|
120
|
+
enrichmentStatus: e.enrichment.status,
|
|
121
|
+
localDay: e.local_day,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const prev = addDays(date, -1);
|
|
126
|
+
const next = addDays(date, 1);
|
|
127
|
+
const backfillRows = buildBackfillRows();
|
|
128
|
+
|
|
129
|
+
// Calendar popover stats: per-day activity + parallelism stats so the
|
|
130
|
+
// calendar tints by airtime and dots days with concurrency bursts.
|
|
131
|
+
const buckets = dailyActivity(allSessions);
|
|
132
|
+
const allBursts = computeBurstsFromSessions(allSessions);
|
|
133
|
+
type DayBurstAgg = { totalMs: number; count: number; peak: number };
|
|
134
|
+
const burstsByDay = new Map<string, DayBurstAgg>();
|
|
135
|
+
for (const b of allBursts) {
|
|
136
|
+
const day = toLocalDayParser(b.startMs);
|
|
137
|
+
const e = burstsByDay.get(day) ?? { totalMs: 0, count: 0, peak: 0 };
|
|
138
|
+
e.totalMs += b.endMs - b.startMs;
|
|
139
|
+
e.count += 1;
|
|
140
|
+
if (b.peak > e.peak) e.peak = b.peak;
|
|
141
|
+
burstsByDay.set(day, e);
|
|
142
|
+
}
|
|
143
|
+
const dayKeys = new Set<string>();
|
|
144
|
+
for (const b of buckets) if (b.sessions > 0) dayKeys.add(b.date);
|
|
145
|
+
for (const d of burstsByDay.keys()) dayKeys.add(d);
|
|
146
|
+
const dayStats: DayInfo[] = Array.from(dayKeys).map((dt) => {
|
|
147
|
+
const a = buckets.find((b) => b.date === dt);
|
|
148
|
+
const burst = burstsByDay.get(dt);
|
|
149
|
+
return {
|
|
150
|
+
date: dt,
|
|
151
|
+
sessions: a?.sessions ?? 0,
|
|
152
|
+
airTimeMs: a?.airTimeMs ?? 0,
|
|
153
|
+
parallelMs: burst?.totalMs ?? 0,
|
|
154
|
+
burstCount: burst?.count ?? 0,
|
|
155
|
+
peakConcurrency: burst?.peak ?? 0,
|
|
156
|
+
};
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
return (
|
|
160
|
+
<DayView
|
|
161
|
+
date={date}
|
|
162
|
+
today={today}
|
|
163
|
+
prev={prev}
|
|
164
|
+
next={next <= today ? next : null}
|
|
165
|
+
initial={initial}
|
|
166
|
+
entries={entries}
|
|
167
|
+
aiEnabled={aiEnabled}
|
|
168
|
+
gantt={gantt}
|
|
169
|
+
bursts={bursts}
|
|
170
|
+
sessionEntries={sessionEntries}
|
|
171
|
+
backfillRows={backfillRows}
|
|
172
|
+
dayStats={dayStats}
|
|
173
|
+
/>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { redirect } from "next/navigation";
|
|
2
|
+
import { isValidDate } from "@/lib/entries";
|
|
3
|
+
import { notFound } from "next/navigation";
|
|
4
|
+
|
|
5
|
+
export const dynamic = "force-dynamic";
|
|
6
|
+
|
|
7
|
+
export default async function LegacyDigestRedirect({
|
|
8
|
+
params,
|
|
9
|
+
}: {
|
|
10
|
+
params: Promise<{ date: string }>;
|
|
11
|
+
}) {
|
|
12
|
+
const { date } = await params;
|
|
13
|
+
if (!isValidDate(date)) return notFound();
|
|
14
|
+
redirect(`/day/${date}`);
|
|
15
|
+
}
|