fleetlens 0.12.3 → 0.13.1
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/build-manifest.json +8 -8
- package/app/apps/web/.next/prerender-manifest.json +3 -3
- package/app/apps/web/.next/server/app/_global-error/page/build-manifest.json +5 -5
- 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 +5 -5
- package/app/apps/web/.next/server/app/_not-found/page.js +1 -1
- 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/ask/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js +1 -1
- package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js +1 -1
- package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/month-index/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js +1 -1
- package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/week-index/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/events/route.js +2 -1
- package/app/apps/web/.next/server/app/api/events/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/jobs/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/pdf/[key]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/runs/[runId]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/runs/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/settings/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/team-config/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/workflow-agent/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/changelog/page/build-manifest.json +5 -5
- package/app/apps/web/.next/server/app/changelog/page.js +1 -1
- package/app/apps/web/.next/server/app/changelog/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/changelog/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/day/[date]/page/build-manifest.json +5 -5
- package/app/apps/web/.next/server/app/day/[date]/page.js +1 -1
- package/app/apps/web/.next/server/app/day/[date]/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/day/[date]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/day/page/build-manifest.json +5 -5
- package/app/apps/web/.next/server/app/day/page.js +1 -1
- package/app/apps/web/.next/server/app/day/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/day/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/digest/[date]/page/build-manifest.json +5 -5
- package/app/apps/web/.next/server/app/digest/[date]/page.js +1 -1
- package/app/apps/web/.next/server/app/digest/[date]/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/digest/[date]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/digest/page/build-manifest.json +5 -5
- package/app/apps/web/.next/server/app/digest/page.js +1 -1
- package/app/apps/web/.next/server/app/digest/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/digest/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/insights/[key]/page/build-manifest.json +5 -5
- package/app/apps/web/.next/server/app/insights/[key]/page.js +1 -1
- 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 +5 -5
- package/app/apps/web/.next/server/app/insights/page.js +3 -2
- 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 +5 -5
- package/app/apps/web/.next/server/app/page.js +1 -1
- 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 +5 -5
- package/app/apps/web/.next/server/app/parallelism/page.js +1 -1
- 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/print/[key]/page/build-manifest.json +5 -5
- package/app/apps/web/.next/server/app/print/[key]/page.js +1 -1
- package/app/apps/web/.next/server/app/print/[key]/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/print/[key]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/projects/[slug]/page/build-manifest.json +5 -5
- package/app/apps/web/.next/server/app/projects/[slug]/page.js +1 -1
- 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 +5 -5
- package/app/apps/web/.next/server/app/projects/page.js +1 -1
- 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/build-manifest.json +5 -5
- package/app/apps/web/.next/server/app/runs/page.js +1 -1
- package/app/apps/web/.next/server/app/runs/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/runs/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/sessions/[id]/page/build-manifest.json +5 -5
- package/app/apps/web/.next/server/app/sessions/[id]/page.js +1 -1
- 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 +5 -5
- package/app/apps/web/.next/server/app/sessions/page.js +1 -1
- 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/build-manifest.json +5 -5
- package/app/apps/web/.next/server/app/settings/page.js +1 -1
- package/app/apps/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/team/page/build-manifest.json +5 -5
- package/app/apps/web/.next/server/app/team/page.js +1 -1
- package/app/apps/web/.next/server/app/team/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/team/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/usage/page/build-manifest.json +5 -5
- package/app/apps/web/.next/server/app/usage/page.js +1 -1
- 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/chunks/[externals]__0rv9ct5._.js +3 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0gril0u._.js +9 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0n79hpm._.js +9 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0~utv~v._.js +9 -0
- package/app/apps/web/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_02bw8.n.js +5 -0
- package/app/apps/web/.next/server/chunks/packages_parser_dist_06d9se1._.js +1 -1
- package/app/apps/web/.next/server/chunks/packages_parser_dist_10ihc3~._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0exckd4._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0-1_njm._.js → [root-of-the-server]__0k1x-c9._.js} +2 -2
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0lhwp-k._.js +8 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0n-ax-5._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0o03ymy._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0~.f_3z._.js +3 -3
- package/app/apps/web/.next/server/chunks/ssr/_0kajk31._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/_0s3n5mz._.js +8 -0
- package/app/apps/web/.next/server/chunks/ssr/_0xu2pvc._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/{_0jw2sm7._.js → _12mbgs5._.js} +2 -2
- package/app/apps/web/.next/server/chunks/ssr/apps_web_0.mu7c7._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_app_day_[date]_day-view_tsx_0wjoe1u._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_app_insights_page_tsx_071kwyw._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_app_sessions_sessions-grid_tsx_0bri5x.._.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_0c-tpft._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0l6hsch._.js +6 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0txtsv5._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_changelog_ts_0n7_p1d._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_changelog_ts_0nb5_-s._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/node_modules_lucide-react_dist_esm_icons_0cepfi8._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/packages_entries_dist_node_0_271yr.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_0mx_509._.js +1 -1
- package/app/apps/web/.next/server/middleware-build-manifest.js +8 -8
- package/app/apps/web/.next/server/middleware-manifest.json +5 -5
- 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/02bv_ejzhhzvp.js +10 -0
- package/app/apps/web/.next/static/chunks/{07lbm-sdh9c2j.js → 0389wb_f0j78j.js} +1 -1
- package/app/apps/web/.next/static/chunks/03gy1evbn94qu.js +6 -0
- package/app/apps/web/.next/static/chunks/03rd.3cc_t~yf.js +4 -0
- package/app/apps/web/.next/static/chunks/{12jvvc_w.cb45.css → 083~hzkv577.5.css} +1 -1
- package/app/apps/web/.next/static/chunks/{0osdgl2.9cl1q.js → 0d2x-wfu.m0-z.js} +1 -1
- package/app/apps/web/.next/static/chunks/{0lziv8y_6yp5w.js → 0e_fzy0n8ij-o.js} +1 -1
- package/app/apps/web/.next/static/chunks/{0l4e3as18eexy.js → 0g223u9amib0q.js} +1 -1
- package/app/apps/web/.next/static/chunks/{0h3.-_s-k0mj3.js → 0i.hc~2bj0_3d.js} +1 -1
- package/app/apps/web/.next/static/chunks/0m7dd-2zd9vl2.js +4 -0
- package/app/apps/web/.next/static/chunks/0nqklmbs5s3ax.js +6 -0
- package/app/apps/web/.next/static/chunks/{073081qv4uyn8.js → 0p--hzrway8~3.js} +1 -1
- package/app/apps/web/.next/static/chunks/0q8dg4txlzno0.js +1 -0
- package/app/apps/web/.next/static/chunks/{0gblp_v.kiu-..js → 0qv-gw888_5nu.js} +1 -1
- package/app/apps/web/.next/static/chunks/{14bjditmmrn7l.js → 0tirv_vo6q8uc.js} +1 -1
- package/app/apps/web/.next/static/chunks/{0qmh5da6gfm56.js → 0vz4~a~~hq399.js} +1 -1
- package/app/apps/web/.next/static/chunks/{13po66tt.68f3.js → 0wwcx42ng8i2e.js} +3 -3
- package/app/apps/web/.next/static/chunks/{0n0n.0279ot6c.js → 14vx702c32kn6.js} +1 -1
- package/app/apps/web/.next/static/chunks/{turbopack-0lb9w090w5ezx.js → turbopack-0mxu3~9vk.brh.js} +1 -1
- package/app/apps/web/app/api/digest/_shared/digest-route-helpers.ts +178 -0
- package/app/apps/web/app/api/digest/day/[date]/route.ts +34 -128
- package/app/apps/web/app/api/digest/month/[yearMonth]/route.ts +36 -121
- package/app/apps/web/app/api/digest/week/[startDate]/route.ts +36 -123
- package/app/apps/web/app/api/events/route.ts +47 -4
- package/app/apps/web/app/globals.css +23 -0
- package/app/apps/web/app/insights/page.tsx +20 -5
- package/app/apps/web/app/layout.tsx +1 -0
- package/app/apps/web/app/page.tsx +1 -1
- package/app/apps/web/app/parallelism/burst-detail-modal.tsx +637 -0
- package/app/apps/web/app/parallelism/concurrency-info-modal.tsx +228 -0
- package/app/apps/web/app/parallelism/gantt-chart-utils.ts +49 -0
- package/app/apps/web/app/parallelism/gantt-chart.tsx +16 -902
- package/app/apps/web/app/projects/[slug]/page.tsx +1 -1
- package/app/apps/web/app/sessions/[id]/session-view/colors.ts +31 -0
- package/app/apps/web/app/sessions/[id]/session-view/debug-list.tsx +78 -0
- package/app/apps/web/app/sessions/[id]/session-view/drawer.tsx +414 -0
- package/app/apps/web/app/sessions/[id]/session-view/entry-day-strip.tsx +124 -0
- package/app/apps/web/app/sessions/[id]/session-view/header-stats.tsx +217 -0
- package/app/apps/web/app/sessions/[id]/session-view/helpers.ts +135 -0
- package/app/apps/web/app/sessions/[id]/session-view/subagent-drawer.tsx +339 -0
- package/app/apps/web/app/sessions/[id]/session-view/token-stats.tsx +111 -0
- package/app/apps/web/app/sessions/[id]/session-view/tooltip.tsx +63 -0
- package/app/apps/web/app/sessions/[id]/session-view/types.ts +46 -0
- package/app/apps/web/app/sessions/[id]/session-view/workflows-shared.tsx +104 -0
- package/app/apps/web/app/sessions/[id]/session-view.tsx +701 -1577
- package/app/apps/web/app/sessions/[id]/team-tab/minimap-hover-card.tsx +201 -0
- package/app/apps/web/app/sessions/[id]/team-tab/minimap-idle-band.tsx +53 -0
- package/app/apps/web/app/sessions/[id]/team-tab/minimap-shared.ts +20 -0
- package/app/apps/web/app/sessions/[id]/team-tab/team-minimap.tsx +10 -265
- package/app/apps/web/app/sessions/sessions-grid.tsx +43 -19
- package/app/apps/web/components/digest-actions.tsx +103 -0
- package/app/apps/web/components/job-queue-widget.tsx +1 -1
- package/app/apps/web/components/live-badge.tsx +11 -3
- package/app/apps/web/components/live-sessions-widget.tsx +9 -3
- package/app/apps/web/components/month-digest-view.tsx +19 -64
- package/app/apps/web/components/outcome-pill.tsx +24 -4
- package/app/apps/web/components/searchable-select.tsx +215 -0
- package/app/apps/web/components/tail-mode.tsx +39 -8
- package/app/apps/web/components/week-digest-view.tsx +16 -71
- package/app/apps/web/lib/changelog-data.generated.ts +1 -1
- package/app/apps/web/lib/entries-index.ts +7 -8
- package/app/apps/web/lib/entries.ts +0 -9
- package/app/apps/web/lib/format.test.ts +221 -0
- package/app/apps/web/lib/utilization-tone.test.ts +56 -0
- package/app/apps/web/package.json +1 -1
- package/app/apps/web/tsconfig.tsbuildinfo +1 -1
- package/dist/daemon-worker.js +83 -45
- package/dist/index.js +452 -198
- package/package.json +1 -1
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0455vu3._.js +0 -5
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__04j3tng._.js +0 -9
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0cnh3k4._.js +0 -9
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__132eosx._.js +0 -9
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__136-0me._.js +0 -8
- package/app/apps/web/.next/server/chunks/ssr/_0w.cv64._.js +0 -8
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_01d-iwx._.js +0 -6
- package/app/apps/web/.next/server/chunks/ssr/node_modules_lucide-react_dist_esm_icons_0-lmm4p._.js +0 -3
- package/app/apps/web/.next/static/chunks/00xkqnvk4-d1-.js +0 -10
- package/app/apps/web/.next/static/chunks/0htgc_hr1bw67.js +0 -1
- package/app/apps/web/.next/static/chunks/0nnjldasalwdu.js +0 -4
- package/app/apps/web/.next/static/chunks/0okg13phslr1..js +0 -4
- package/app/apps/web/.next/static/chunks/0vf-3rauafbek.js +0 -6
- package/app/apps/web/.next/static/chunks/0vl27-vjob2_9.js +0 -6
- /package/app/apps/web/.next/static/{7kQ9mNICnVHhf4-LmSGcy → VEfemGVAQ0xCHjj15orZU}/_buildManifest.js +0 -0
- /package/app/apps/web/.next/static/{7kQ9mNICnVHhf4-LmSGcy → VEfemGVAQ0xCHjj15orZU}/_clientMiddlewareManifest.js +0 -0
- /package/app/apps/web/.next/static/{7kQ9mNICnVHhf4-LmSGcy → VEfemGVAQ0xCHjj15orZU}/_ssgManifest.js +0 -0
package/dist/index.js
CHANGED
|
@@ -289,23 +289,28 @@ function detectParallelRuns(sessions, minActive = 2) {
|
|
|
289
289
|
const points = computeParallelism(sessions);
|
|
290
290
|
const runs2 = [];
|
|
291
291
|
let cur = null;
|
|
292
|
+
let curIds = null;
|
|
292
293
|
for (const p of points) {
|
|
293
294
|
if (p.active >= minActive) {
|
|
294
295
|
if (!cur) {
|
|
295
|
-
|
|
296
|
+
curIds = new Set(p.sessions);
|
|
297
|
+
cur = { startMs: p.atMs, endMs: p.atMs, peak: p.active, sessions: Array.from(curIds) };
|
|
296
298
|
} else {
|
|
297
299
|
cur.endMs = p.atMs;
|
|
298
300
|
if (p.active > cur.peak)
|
|
299
301
|
cur.peak = p.active;
|
|
300
302
|
for (const sid of p.sessions) {
|
|
301
|
-
if (!
|
|
303
|
+
if (!curIds.has(sid)) {
|
|
304
|
+
curIds.add(sid);
|
|
302
305
|
cur.sessions.push(sid);
|
|
306
|
+
}
|
|
303
307
|
}
|
|
304
308
|
}
|
|
305
309
|
} else if (cur) {
|
|
306
310
|
cur.endMs = p.atMs;
|
|
307
311
|
runs2.push(cur);
|
|
308
312
|
cur = null;
|
|
313
|
+
curIds = null;
|
|
309
314
|
}
|
|
310
315
|
}
|
|
311
316
|
if (cur)
|
|
@@ -715,23 +720,6 @@ function eventDollars(ev) {
|
|
|
715
720
|
const p = PRICES[ev.family];
|
|
716
721
|
return (ev.input * p.input + ev.output * p.output + ev.cacheRead * p.cacheRead + ev.cache_1h * p.cache_1h + ev.cache_5m * p.cache_5m) / 1e6;
|
|
717
722
|
}
|
|
718
|
-
function dollarsInWindow(events, startMs, endMs) {
|
|
719
|
-
let total = 0;
|
|
720
|
-
for (const ev of events) {
|
|
721
|
-
const t = Date.parse(ev.ts);
|
|
722
|
-
if (t < startMs)
|
|
723
|
-
continue;
|
|
724
|
-
if (t >= endMs)
|
|
725
|
-
break;
|
|
726
|
-
total += eventDollars(ev);
|
|
727
|
-
}
|
|
728
|
-
return total;
|
|
729
|
-
}
|
|
730
|
-
function predictUtilization(events, startMs, endMs, ratePerPct) {
|
|
731
|
-
if (ratePerPct <= 0)
|
|
732
|
-
return 0;
|
|
733
|
-
return dollarsInWindow(events, startMs, endMs) / ratePerPct;
|
|
734
|
-
}
|
|
735
723
|
function buildSpendIndex(events) {
|
|
736
724
|
const sorted = events.map((e) => ({ e, t: Date.parse(e.ts) })).filter((x) => !Number.isNaN(x.t)).sort((a, b) => a.t - b.t);
|
|
737
725
|
const ts = new Float64Array(sorted.length);
|
|
@@ -917,7 +905,14 @@ var init_user_input = __esm({
|
|
|
917
905
|
"<local-command-stdout>",
|
|
918
906
|
"<local-command-caveat>",
|
|
919
907
|
"<task-notification>",
|
|
920
|
-
"Base directory for this skill:"
|
|
908
|
+
"Base directory for this skill:",
|
|
909
|
+
// Harness-authored lines that arrive with role:"user" but are not the
|
|
910
|
+
// human typing. The post-compact continuation is Claude Code restating the
|
|
911
|
+
// summarized conversation; the Stop-hook notice is a skill (e.g. /goal)
|
|
912
|
+
// keeping the turn alive. Neither is a real user message, so they must not
|
|
913
|
+
// render as "User" rows or count toward digest "top user instructions".
|
|
914
|
+
"This session is being continued from a previous conversation",
|
|
915
|
+
"A session-scoped Stop hook is now active"
|
|
921
916
|
];
|
|
922
917
|
}
|
|
923
918
|
});
|
|
@@ -1131,9 +1126,19 @@ function parseTranscript(rawLines) {
|
|
|
1131
1126
|
if (ev)
|
|
1132
1127
|
events.push(ev);
|
|
1133
1128
|
}
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
const
|
|
1129
|
+
let startMs;
|
|
1130
|
+
let endMs;
|
|
1131
|
+
for (const e of events) {
|
|
1132
|
+
if (!e.timestamp)
|
|
1133
|
+
continue;
|
|
1134
|
+
const ms = Date.parse(e.timestamp);
|
|
1135
|
+
if (Number.isNaN(ms))
|
|
1136
|
+
continue;
|
|
1137
|
+
if (startMs === void 0 || ms < startMs)
|
|
1138
|
+
startMs = ms;
|
|
1139
|
+
if (endMs === void 0 || ms > endMs)
|
|
1140
|
+
endMs = ms;
|
|
1141
|
+
}
|
|
1137
1142
|
const firstTs = startMs !== void 0 ? new Date(startMs).toISOString() : void 0;
|
|
1138
1143
|
const lastTs = endMs !== void 0 ? new Date(endMs).toISOString() : void 0;
|
|
1139
1144
|
for (const ev of events) {
|
|
@@ -1367,12 +1372,10 @@ function parseTranscript(rawLines) {
|
|
|
1367
1372
|
if (typeof m.model === "string" && !model)
|
|
1368
1373
|
model = m.model;
|
|
1369
1374
|
const mid = typeof m.id === "string" ? m.id : void 0;
|
|
1370
|
-
|
|
1371
|
-
const dedupKey = mid != null ? `${mid}:${rid ?? ""}` : void 0;
|
|
1372
|
-
if (dedupKey && seenMessageIds.has(dedupKey))
|
|
1375
|
+
if (mid && seenMessageIds.has(mid))
|
|
1373
1376
|
continue;
|
|
1374
|
-
if (
|
|
1375
|
-
seenMessageIds.add(
|
|
1377
|
+
if (mid)
|
|
1378
|
+
seenMessageIds.add(mid);
|
|
1376
1379
|
const u = extractUsage(m.usage);
|
|
1377
1380
|
if (u) {
|
|
1378
1381
|
totalUsage.input += u.input;
|
|
@@ -1831,6 +1834,40 @@ async function scanWorkflowAggregate(projectDirPath, sessionId) {
|
|
|
1831
1834
|
}));
|
|
1832
1835
|
return { workflowCount: parsed.filter(Boolean).length, spawnedAgentCount, spans };
|
|
1833
1836
|
}
|
|
1837
|
+
async function dirNewestMtimeMs(dir, depth) {
|
|
1838
|
+
let entries2;
|
|
1839
|
+
try {
|
|
1840
|
+
entries2 = await fs.readdir(dir, { withFileTypes: true });
|
|
1841
|
+
} catch {
|
|
1842
|
+
return 0;
|
|
1843
|
+
}
|
|
1844
|
+
const vals = await Promise.all(entries2.map(async (e) => {
|
|
1845
|
+
const p = path.join(dir, e.name);
|
|
1846
|
+
try {
|
|
1847
|
+
if (e.isDirectory())
|
|
1848
|
+
return depth > 0 ? await dirNewestMtimeMs(p, depth - 1) : 0;
|
|
1849
|
+
return (await fs.stat(p)).mtimeMs;
|
|
1850
|
+
} catch {
|
|
1851
|
+
return 0;
|
|
1852
|
+
}
|
|
1853
|
+
}));
|
|
1854
|
+
return vals.reduce((a, b) => Math.max(a, b), 0);
|
|
1855
|
+
}
|
|
1856
|
+
async function newestNestedActivityMs(projectDirPath, sessionId) {
|
|
1857
|
+
const base = path.join(projectDirPath, sessionId);
|
|
1858
|
+
const [subM, wfM] = await Promise.all([
|
|
1859
|
+
dirNewestMtimeMs(path.join(base, "subagents"), 2),
|
|
1860
|
+
dirNewestMtimeMs(path.join(base, "workflows"), 0)
|
|
1861
|
+
]);
|
|
1862
|
+
const newest = Math.max(subM, wfM);
|
|
1863
|
+
return newest > 0 ? newest : void 0;
|
|
1864
|
+
}
|
|
1865
|
+
async function withLastActivity(meta, f) {
|
|
1866
|
+
const nested = await newestNestedActivityMs(path.dirname(f.fullPath), meta.id);
|
|
1867
|
+
const baseMs = meta.lastTimestamp ? Date.parse(meta.lastTimestamp) : 0;
|
|
1868
|
+
const lastActivityMs = Math.max(Number.isFinite(baseMs) ? baseMs : 0, nested ?? 0);
|
|
1869
|
+
return lastActivityMs > 0 ? { ...meta, lastActivityMs } : meta;
|
|
1870
|
+
}
|
|
1834
1871
|
function foldWorkflowAgentTime(activeSegments, spans) {
|
|
1835
1872
|
if (spans.length === 0)
|
|
1836
1873
|
return {};
|
|
@@ -1921,7 +1958,10 @@ async function listSessions(opts = {}) {
|
|
|
1921
1958
|
files = files.filter((f) => f.projectDir === projectDir);
|
|
1922
1959
|
files.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
1923
1960
|
const sliced = files.slice(0, limit);
|
|
1924
|
-
const metas = await Promise.all(sliced.map((f) =>
|
|
1961
|
+
const metas = await Promise.all(sliced.map(async (f) => {
|
|
1962
|
+
const m = await getCachedMeta(f);
|
|
1963
|
+
return m ? withLastActivity(m, f) : null;
|
|
1964
|
+
}));
|
|
1925
1965
|
return metas.filter((m) => m !== null);
|
|
1926
1966
|
}
|
|
1927
1967
|
async function getSession(id, opts = {}) {
|
|
@@ -1941,12 +1981,13 @@ async function getSession(id, opts = {}) {
|
|
|
1941
1981
|
loadWorkflows(workflowsDir, sessionStartMs, detail.events)
|
|
1942
1982
|
]);
|
|
1943
1983
|
const spawnedAgentCount = workflows.reduce((n, w) => n + w.agentCount, 0);
|
|
1944
|
-
|
|
1984
|
+
const result = {
|
|
1945
1985
|
...detail,
|
|
1946
1986
|
subagents,
|
|
1947
1987
|
workflows,
|
|
1948
1988
|
...workflows.length > 0 ? { workflowCount: workflows.length, spawnedAgentCount } : {}
|
|
1949
1989
|
};
|
|
1990
|
+
return withLastActivity(result, hit);
|
|
1950
1991
|
}
|
|
1951
1992
|
function summarizeSubagentLines(lines) {
|
|
1952
1993
|
let startMs;
|
|
@@ -3556,7 +3597,8 @@ async function parseSession2(file) {
|
|
|
3556
3597
|
} catch {
|
|
3557
3598
|
}
|
|
3558
3599
|
}
|
|
3559
|
-
for (const
|
|
3600
|
+
for (const rawObj of parsedObjects) {
|
|
3601
|
+
const eventObj = rawObj;
|
|
3560
3602
|
const ts = eventObj.created_at || eventObj.timestamp;
|
|
3561
3603
|
if (eventObj.type === "USER_INPUT") {
|
|
3562
3604
|
if (typeof eventObj.content === "string") {
|
|
@@ -4035,12 +4077,6 @@ async function getCoworkSession(id, opts = {}) {
|
|
|
4035
4077
|
detailCache5.set(file.auditPath, { detail, key });
|
|
4036
4078
|
return detail;
|
|
4037
4079
|
}
|
|
4038
|
-
function coworkSessionLocalDay(meta) {
|
|
4039
|
-
if (!meta.firstTimestamp)
|
|
4040
|
-
return void 0;
|
|
4041
|
-
const ms = Date.parse(meta.firstTimestamp);
|
|
4042
|
-
return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
|
|
4043
|
-
}
|
|
4044
4080
|
var DEFAULT_COWORK_ROOT, SESSION_ID_RE, spacesCache, metaCache5, detailCache5;
|
|
4045
4081
|
var init_cowork = __esm({
|
|
4046
4082
|
"../parser/dist/cowork.js"() {
|
|
@@ -4114,7 +4150,6 @@ __export(fs_exports, {
|
|
|
4114
4150
|
clearCaches: () => clearCaches,
|
|
4115
4151
|
clearTeamConfig: () => clearTeamConfig,
|
|
4116
4152
|
codexSessionLocalDay: () => codexSessionLocalDay,
|
|
4117
|
-
coworkSessionLocalDay: () => coworkSessionLocalDay,
|
|
4118
4153
|
decodeProjectName: () => decodeProjectName,
|
|
4119
4154
|
findTeamLead: () => findTeamLead,
|
|
4120
4155
|
geminiSessionLocalDay: () => geminiSessionLocalDay,
|
|
@@ -4219,7 +4254,7 @@ async function loadUsageByDay(start2, end) {
|
|
|
4219
4254
|
if (ms < startMs)
|
|
4220
4255
|
continue;
|
|
4221
4256
|
if (ms > endMs)
|
|
4222
|
-
|
|
4257
|
+
continue;
|
|
4223
4258
|
const key = toLocalDay(ms);
|
|
4224
4259
|
const util2 = snap.five_hour?.utilization ?? 0;
|
|
4225
4260
|
const cur2 = byDay.get(key) ?? 0;
|
|
@@ -4507,7 +4542,7 @@ function getServerStatus() {
|
|
|
4507
4542
|
return { running: false };
|
|
4508
4543
|
}
|
|
4509
4544
|
function isServerStale(status2) {
|
|
4510
|
-
return status2.running === true && status2.version !== "0.
|
|
4545
|
+
return status2.running === true && status2.version !== "0.13.1";
|
|
4511
4546
|
}
|
|
4512
4547
|
async function ensureCurrentServer(opts = {}) {
|
|
4513
4548
|
const status2 = getServerStatus();
|
|
@@ -4563,7 +4598,7 @@ async function startServer(opts = {}) {
|
|
|
4563
4598
|
});
|
|
4564
4599
|
child.unref();
|
|
4565
4600
|
const pid = child.pid;
|
|
4566
|
-
writePid(PID_FILE, pid, port, "0.
|
|
4601
|
+
writePid(PID_FILE, pid, port, "0.13.1");
|
|
4567
4602
|
await waitForHealth(`http://localhost:${port}`, 1e4);
|
|
4568
4603
|
return { pid, port };
|
|
4569
4604
|
}
|
|
@@ -4923,9 +4958,9 @@ Installed: ${PACKAGE_NAME}@${verify.installedVersion} at ${verify.installedPath
|
|
|
4923
4958
|
console.warn(
|
|
4924
4959
|
` \u2022 reinstall in the correct Node env: 'npm install -g ${PACKAGE_NAME}@latest'`
|
|
4925
4960
|
);
|
|
4926
|
-
} else if (verify.installedVersion !== "0.
|
|
4961
|
+
} else if (verify.installedVersion !== "0.13.1") {
|
|
4927
4962
|
console.log(
|
|
4928
|
-
` \u2192 This process is still running ${"0.
|
|
4963
|
+
` \u2192 This process is still running ${"0.13.1"}. Next invocation will use ${verify.installedVersion}.`
|
|
4929
4964
|
);
|
|
4930
4965
|
}
|
|
4931
4966
|
}
|
|
@@ -4960,14 +4995,14 @@ async function getUpdateAvailability() {
|
|
|
4960
4995
|
if (isDevMode()) return null;
|
|
4961
4996
|
const latest = await fetchLatestVersion();
|
|
4962
4997
|
if (latest === null) return {
|
|
4963
|
-
current: "0.
|
|
4998
|
+
current: "0.13.1",
|
|
4964
4999
|
latest: null,
|
|
4965
5000
|
updateAvailable: false
|
|
4966
5001
|
};
|
|
4967
5002
|
return {
|
|
4968
|
-
current: "0.
|
|
5003
|
+
current: "0.13.1",
|
|
4969
5004
|
latest,
|
|
4970
|
-
updateAvailable: shouldUpdate("0.
|
|
5005
|
+
updateAvailable: shouldUpdate("0.13.1", latest)
|
|
4971
5006
|
};
|
|
4972
5007
|
}
|
|
4973
5008
|
async function checkForUpdate() {
|
|
@@ -5057,7 +5092,7 @@ async function restartServices(state) {
|
|
|
5057
5092
|
}
|
|
5058
5093
|
async function forceUpdate() {
|
|
5059
5094
|
const latest = await fetchLatestVersion();
|
|
5060
|
-
const current = "0.
|
|
5095
|
+
const current = "0.13.1";
|
|
5061
5096
|
if (latest === null) {
|
|
5062
5097
|
console.error("Could not reach npm registry. Check your network.");
|
|
5063
5098
|
process.exit(1);
|
|
@@ -5094,6 +5129,215 @@ var init_updater = __esm({
|
|
|
5094
5129
|
}
|
|
5095
5130
|
});
|
|
5096
5131
|
|
|
5132
|
+
// src/commands/autostart.ts
|
|
5133
|
+
var autostart_exports = {};
|
|
5134
|
+
__export(autostart_exports, {
|
|
5135
|
+
autostart: () => autostart,
|
|
5136
|
+
buildPlist: () => buildPlist,
|
|
5137
|
+
dismissPrompt: () => dismissPrompt,
|
|
5138
|
+
installAutostart: () => installAutostart,
|
|
5139
|
+
isAutostartInstalled: () => isAutostartInstalled,
|
|
5140
|
+
isPromptDismissed: () => isPromptDismissed,
|
|
5141
|
+
maybePromptAutostart: () => maybePromptAutostart
|
|
5142
|
+
});
|
|
5143
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync4, writeFileSync as writeFileSync3, rmSync, readFileSync as readFileSync6, realpathSync as realpathSync2 } from "node:fs";
|
|
5144
|
+
import { homedir as homedir2 } from "node:os";
|
|
5145
|
+
import { join as join5, dirname as dirname6 } from "node:path";
|
|
5146
|
+
import { execFile } from "node:child_process";
|
|
5147
|
+
import { promisify } from "node:util";
|
|
5148
|
+
import { createInterface } from "node:readline";
|
|
5149
|
+
function plistPath() {
|
|
5150
|
+
return join5(homedir2(), "Library", "LaunchAgents", `${LABEL}.plist`);
|
|
5151
|
+
}
|
|
5152
|
+
function isMac() {
|
|
5153
|
+
return process.platform === "darwin";
|
|
5154
|
+
}
|
|
5155
|
+
function isAutostartInstalled() {
|
|
5156
|
+
return isMac() && existsSync5(plistPath());
|
|
5157
|
+
}
|
|
5158
|
+
function resolveScriptPath() {
|
|
5159
|
+
const argv1 = process.argv[1] ?? "";
|
|
5160
|
+
try {
|
|
5161
|
+
return realpathSync2(argv1);
|
|
5162
|
+
} catch {
|
|
5163
|
+
return argv1;
|
|
5164
|
+
}
|
|
5165
|
+
}
|
|
5166
|
+
function buildPlist(opts) {
|
|
5167
|
+
const { nodePath, scriptPath, logPath } = opts;
|
|
5168
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
5169
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
5170
|
+
<plist version="1.0">
|
|
5171
|
+
<dict>
|
|
5172
|
+
<key>Label</key>
|
|
5173
|
+
<string>${LABEL}</string>
|
|
5174
|
+
<key>ProgramArguments</key>
|
|
5175
|
+
<array>
|
|
5176
|
+
<string>${nodePath}</string>
|
|
5177
|
+
<string>${scriptPath}</string>
|
|
5178
|
+
<string>daemon</string>
|
|
5179
|
+
<string>start</string>
|
|
5180
|
+
</array>
|
|
5181
|
+
<key>RunAtLoad</key>
|
|
5182
|
+
<true/>
|
|
5183
|
+
<key>ProcessType</key>
|
|
5184
|
+
<string>Background</string>
|
|
5185
|
+
<key>StandardOutPath</key>
|
|
5186
|
+
<string>${logPath}</string>
|
|
5187
|
+
<key>StandardErrorPath</key>
|
|
5188
|
+
<string>${logPath}</string>
|
|
5189
|
+
</dict>
|
|
5190
|
+
</plist>
|
|
5191
|
+
`;
|
|
5192
|
+
}
|
|
5193
|
+
async function runLaunchctl(args2) {
|
|
5194
|
+
await execFileAsync("launchctl", args2);
|
|
5195
|
+
}
|
|
5196
|
+
async function installAutostart() {
|
|
5197
|
+
if (!isMac()) {
|
|
5198
|
+
console.log(NON_MAC_MSG);
|
|
5199
|
+
return false;
|
|
5200
|
+
}
|
|
5201
|
+
const nodePath = process.execPath;
|
|
5202
|
+
const scriptPath = resolveScriptPath();
|
|
5203
|
+
const logPath = cclensPath("daemon-autostart.log");
|
|
5204
|
+
const p = plistPath();
|
|
5205
|
+
mkdirSync4(dirname6(p), { recursive: true });
|
|
5206
|
+
writeFileSync3(p, buildPlist({ nodePath, scriptPath, logPath }), "utf8");
|
|
5207
|
+
await runLaunchctl(["unload", p]).catch(() => {
|
|
5208
|
+
});
|
|
5209
|
+
await runLaunchctl(["load", "-w", p]);
|
|
5210
|
+
console.log("Autostart installed \u2014 the Fleetlens usage daemon will start at login.");
|
|
5211
|
+
console.log(` LaunchAgent: ${p}`);
|
|
5212
|
+
console.log(` Runs: ${nodePath} ${scriptPath} daemon start`);
|
|
5213
|
+
console.log(
|
|
5214
|
+
" Note: the Node path above is baked in. If you upgrade or switch Node (e.g. via nvm), re-run `fleetlens autostart install`."
|
|
5215
|
+
);
|
|
5216
|
+
return true;
|
|
5217
|
+
}
|
|
5218
|
+
async function uninstallAutostart() {
|
|
5219
|
+
if (!isMac()) {
|
|
5220
|
+
console.log(NON_MAC_MSG);
|
|
5221
|
+
return;
|
|
5222
|
+
}
|
|
5223
|
+
const p = plistPath();
|
|
5224
|
+
if (!existsSync5(p)) {
|
|
5225
|
+
console.log("Autostart is not installed \u2014 nothing to remove.");
|
|
5226
|
+
return;
|
|
5227
|
+
}
|
|
5228
|
+
await runLaunchctl(["unload", "-w", p]).catch(() => {
|
|
5229
|
+
});
|
|
5230
|
+
rmSync(p, { force: true });
|
|
5231
|
+
console.log(`Autostart removed (${p}). The daemon will no longer start at login.`);
|
|
5232
|
+
}
|
|
5233
|
+
async function statusAutostart() {
|
|
5234
|
+
if (!isMac()) {
|
|
5235
|
+
console.log("Autostart: macOS-only (not available on this platform).");
|
|
5236
|
+
return;
|
|
5237
|
+
}
|
|
5238
|
+
const p = plistPath();
|
|
5239
|
+
const present = existsSync5(p);
|
|
5240
|
+
let loaded = false;
|
|
5241
|
+
try {
|
|
5242
|
+
const { stdout } = await execFileAsync("launchctl", ["list"]);
|
|
5243
|
+
loaded = stdout.includes(LABEL);
|
|
5244
|
+
} catch {
|
|
5245
|
+
}
|
|
5246
|
+
console.log(`Autostart: ${present ? "installed" : "not installed"}${present ? ` (${p})` : ""}`);
|
|
5247
|
+
console.log(`launchd: ${loaded ? "loaded" : "not loaded"}`);
|
|
5248
|
+
}
|
|
5249
|
+
function promptFlagPath() {
|
|
5250
|
+
return cclensPath("autostart.json");
|
|
5251
|
+
}
|
|
5252
|
+
function isPromptDismissed() {
|
|
5253
|
+
try {
|
|
5254
|
+
const j = JSON.parse(readFileSync6(promptFlagPath(), "utf8"));
|
|
5255
|
+
return j.promptDismissed === true;
|
|
5256
|
+
} catch {
|
|
5257
|
+
return false;
|
|
5258
|
+
}
|
|
5259
|
+
}
|
|
5260
|
+
function dismissPrompt() {
|
|
5261
|
+
const p = promptFlagPath();
|
|
5262
|
+
try {
|
|
5263
|
+
mkdirSync4(dirname6(p), { recursive: true });
|
|
5264
|
+
writeFileSync3(p, JSON.stringify({ promptDismissed: true }, null, 2), "utf8");
|
|
5265
|
+
} catch {
|
|
5266
|
+
}
|
|
5267
|
+
}
|
|
5268
|
+
function promptYesNo(question, defaultYes) {
|
|
5269
|
+
return new Promise((resolve3) => {
|
|
5270
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
5271
|
+
rl.question(question, (answer) => {
|
|
5272
|
+
rl.close();
|
|
5273
|
+
const a = answer.trim().toLowerCase();
|
|
5274
|
+
if (a === "") return resolve3(defaultYes);
|
|
5275
|
+
resolve3(a === "y" || a === "yes");
|
|
5276
|
+
});
|
|
5277
|
+
});
|
|
5278
|
+
}
|
|
5279
|
+
async function maybePromptAutostart(opts) {
|
|
5280
|
+
try {
|
|
5281
|
+
if (!isMac()) return;
|
|
5282
|
+
if (!opts.daemonStarted) return;
|
|
5283
|
+
if (process.env.__FLEETLENS_UPDATED) return;
|
|
5284
|
+
if (!process.stdin.isTTY) return;
|
|
5285
|
+
if (isAutostartInstalled()) return;
|
|
5286
|
+
if (isPromptDismissed()) return;
|
|
5287
|
+
console.log("");
|
|
5288
|
+
console.log("Tip: keep the Fleetlens usage daemon running after you restart your Mac?");
|
|
5289
|
+
console.log(" This installs a launchd LaunchAgent that runs `fleetlens daemon start`");
|
|
5290
|
+
console.log(" at login (daemon only \u2014 not the dashboard server).");
|
|
5291
|
+
const yes = await promptYesNo("Set that up now? [Y/n] ", true);
|
|
5292
|
+
if (yes) {
|
|
5293
|
+
await installAutostart();
|
|
5294
|
+
return;
|
|
5295
|
+
}
|
|
5296
|
+
const dismiss = await promptYesNo("OK. Don't ask again? [y/N] ", false);
|
|
5297
|
+
if (dismiss) {
|
|
5298
|
+
dismissPrompt();
|
|
5299
|
+
console.log("Got it \u2014 I won't ask again. Run `fleetlens autostart install` anytime.");
|
|
5300
|
+
}
|
|
5301
|
+
} catch {
|
|
5302
|
+
}
|
|
5303
|
+
}
|
|
5304
|
+
async function autostart(args2) {
|
|
5305
|
+
const sub = args2[0] ?? "status";
|
|
5306
|
+
switch (sub) {
|
|
5307
|
+
case "install":
|
|
5308
|
+
await installAutostart();
|
|
5309
|
+
break;
|
|
5310
|
+
case "uninstall":
|
|
5311
|
+
case "remove":
|
|
5312
|
+
await uninstallAutostart();
|
|
5313
|
+
break;
|
|
5314
|
+
case "status":
|
|
5315
|
+
await statusAutostart();
|
|
5316
|
+
break;
|
|
5317
|
+
case "help":
|
|
5318
|
+
case "--help":
|
|
5319
|
+
case "-h":
|
|
5320
|
+
console.log("Usage: fleetlens autostart <install|uninstall|status>");
|
|
5321
|
+
break;
|
|
5322
|
+
default:
|
|
5323
|
+
console.error(
|
|
5324
|
+
`Unknown autostart subcommand: ${sub}
|
|
5325
|
+
Usage: fleetlens autostart <install|uninstall|status>`
|
|
5326
|
+
);
|
|
5327
|
+
process.exit(1);
|
|
5328
|
+
}
|
|
5329
|
+
}
|
|
5330
|
+
var execFileAsync, LABEL, NON_MAC_MSG;
|
|
5331
|
+
var init_autostart = __esm({
|
|
5332
|
+
"src/commands/autostart.ts"() {
|
|
5333
|
+
"use strict";
|
|
5334
|
+
init_fs();
|
|
5335
|
+
execFileAsync = promisify(execFile);
|
|
5336
|
+
LABEL = "com.fleetlens.daemon";
|
|
5337
|
+
NON_MAC_MSG = "autostart uses a macOS launchd LaunchAgent and is macOS-only for now. On other platforms, add `fleetlens daemon start` to your login items manually.";
|
|
5338
|
+
}
|
|
5339
|
+
});
|
|
5340
|
+
|
|
5097
5341
|
// src/commands/start.ts
|
|
5098
5342
|
var start_exports = {};
|
|
5099
5343
|
__export(start_exports, {
|
|
@@ -5126,12 +5370,15 @@ async function start(args2) {
|
|
|
5126
5370
|
console.error(`Failed to start server: ${err.message}`);
|
|
5127
5371
|
process.exit(1);
|
|
5128
5372
|
}
|
|
5373
|
+
let daemonRunning = false;
|
|
5129
5374
|
if (!noDaemon) {
|
|
5130
5375
|
const daemon2 = startDaemonSilent();
|
|
5131
5376
|
if (daemon2.alreadyRunning) {
|
|
5132
5377
|
console.log(`Daemon: already running (PID ${daemon2.pid})`);
|
|
5378
|
+
daemonRunning = true;
|
|
5133
5379
|
} else if (daemon2.started) {
|
|
5134
5380
|
console.log(`Daemon: started (PID ${daemon2.pid})`);
|
|
5381
|
+
daemonRunning = true;
|
|
5135
5382
|
} else {
|
|
5136
5383
|
console.warn(`Daemon: failed to start \u2014 ${daemon2.error}`);
|
|
5137
5384
|
}
|
|
@@ -5142,6 +5389,7 @@ async function start(args2) {
|
|
|
5142
5389
|
console.log(`
|
|
5143
5390
|
Open ${serverUrl} in your browser, or re-run with --open to launch it automatically.`);
|
|
5144
5391
|
}
|
|
5392
|
+
await maybePromptAutostart({ daemonStarted: daemonRunning });
|
|
5145
5393
|
}
|
|
5146
5394
|
var init_start = __esm({
|
|
5147
5395
|
"src/commands/start.ts"() {
|
|
@@ -5149,6 +5397,7 @@ var init_start = __esm({
|
|
|
5149
5397
|
init_server();
|
|
5150
5398
|
init_updater();
|
|
5151
5399
|
init_daemon();
|
|
5400
|
+
init_autostart();
|
|
5152
5401
|
}
|
|
5153
5402
|
});
|
|
5154
5403
|
|
|
@@ -5201,7 +5450,7 @@ async function status() {
|
|
|
5201
5450
|
console.log(`Server: running on ${url} (PID ${server.pid}, v${ver})`);
|
|
5202
5451
|
if (isServerStale(server)) {
|
|
5203
5452
|
console.log(
|
|
5204
|
-
` \u26A0 serving stale ${ver} (CLI is ${"0.
|
|
5453
|
+
` \u26A0 serving stale ${ver} (CLI is ${"0.13.1"}) \u2014 run 'fleetlens start' to restart on the current version`
|
|
5205
5454
|
);
|
|
5206
5455
|
}
|
|
5207
5456
|
} else {
|
|
@@ -5283,9 +5532,9 @@ var init_update = __esm({
|
|
|
5283
5532
|
|
|
5284
5533
|
// src/usage/token.ts
|
|
5285
5534
|
import { execFileSync } from "node:child_process";
|
|
5286
|
-
import { readFileSync as
|
|
5287
|
-
import { homedir as
|
|
5288
|
-
import { join as
|
|
5535
|
+
import { readFileSync as readFileSync7 } from "node:fs";
|
|
5536
|
+
import { homedir as homedir3, platform } from "node:os";
|
|
5537
|
+
import { join as join6 } from "node:path";
|
|
5289
5538
|
function readOAuthCredentials() {
|
|
5290
5539
|
if (platform() === "darwin") {
|
|
5291
5540
|
return readFromMacKeychain() ?? readFromCredentialsFile();
|
|
@@ -5306,12 +5555,12 @@ function readFromMacKeychain() {
|
|
|
5306
5555
|
}
|
|
5307
5556
|
function readFromCredentialsFile() {
|
|
5308
5557
|
const candidates = [
|
|
5309
|
-
|
|
5310
|
-
|
|
5558
|
+
join6(homedir3(), ".claude", ".credentials.json"),
|
|
5559
|
+
join6(homedir3(), ".config", "claude", "credentials.json")
|
|
5311
5560
|
];
|
|
5312
5561
|
for (const path7 of candidates) {
|
|
5313
5562
|
try {
|
|
5314
|
-
const blob =
|
|
5563
|
+
const blob = readFileSync7(path7, "utf8");
|
|
5315
5564
|
const creds = extractCredentials(blob);
|
|
5316
5565
|
if (creds) return creds;
|
|
5317
5566
|
} catch {
|
|
@@ -6285,7 +6534,6 @@ __export(dist_exports, {
|
|
|
6285
6534
|
detectParallelRuns: () => detectParallelRuns,
|
|
6286
6535
|
detectPrMarkers: () => detectPrMarkers,
|
|
6287
6536
|
dollarsInRange: () => dollarsInRange,
|
|
6288
|
-
dollarsInWindow: () => dollarsInWindow,
|
|
6289
6537
|
eventDollars: () => eventDollars,
|
|
6290
6538
|
getAgentMetadata: () => getAgentMetadata,
|
|
6291
6539
|
groupByProject: () => groupByProject,
|
|
@@ -6298,7 +6546,6 @@ __export(dist_exports, {
|
|
|
6298
6546
|
modelFamily: () => modelFamily,
|
|
6299
6547
|
parseTranscript: () => parseTranscript,
|
|
6300
6548
|
predictAnchored: () => predictAnchored,
|
|
6301
|
-
predictUtilization: () => predictUtilization,
|
|
6302
6549
|
priorCalendarMonth: () => priorCalendarMonth,
|
|
6303
6550
|
priorCalendarWeek: () => priorCalendarWeek,
|
|
6304
6551
|
projectRepoName: () => projectRepoName,
|
|
@@ -6537,11 +6784,11 @@ var init_dist2 = __esm({
|
|
|
6537
6784
|
});
|
|
6538
6785
|
|
|
6539
6786
|
// ../entries/dist/digest-fs.js
|
|
6540
|
-
import { readFileSync as
|
|
6541
|
-
import { dirname as
|
|
6787
|
+
import { readFileSync as readFileSync8, readdirSync, writeFileSync as writeFileSync4, renameSync, chmodSync, mkdirSync as mkdirSync5, existsSync as existsSync6 } from "node:fs";
|
|
6788
|
+
import { dirname as dirname7, join as join7 } from "node:path";
|
|
6542
6789
|
function parseDigestFile(path7, expectedVersion) {
|
|
6543
6790
|
try {
|
|
6544
|
-
const parsed = JSON.parse(
|
|
6791
|
+
const parsed = JSON.parse(readFileSync8(path7, "utf8"));
|
|
6545
6792
|
if (!parsed || typeof parsed !== "object")
|
|
6546
6793
|
return null;
|
|
6547
6794
|
if (parsed.version !== expectedVersion)
|
|
@@ -6562,24 +6809,24 @@ function digestsDir() {
|
|
|
6562
6809
|
}
|
|
6563
6810
|
function __setDigestsDirForTest(path7) {
|
|
6564
6811
|
digestsDirCached = path7;
|
|
6565
|
-
|
|
6566
|
-
|
|
6567
|
-
|
|
6812
|
+
mkdirSync5(join7(path7, "day"), { recursive: true });
|
|
6813
|
+
mkdirSync5(join7(path7, "week"), { recursive: true });
|
|
6814
|
+
mkdirSync5(join7(path7, "month"), { recursive: true });
|
|
6568
6815
|
}
|
|
6569
6816
|
function dayDigestPath(date) {
|
|
6570
|
-
return
|
|
6817
|
+
return join7(digestsDir(), "day", `${date}.json`);
|
|
6571
6818
|
}
|
|
6572
6819
|
function weekDigestPath(monday) {
|
|
6573
|
-
return
|
|
6820
|
+
return join7(digestsDir(), "week", `${monday}.json`);
|
|
6574
6821
|
}
|
|
6575
6822
|
function monthDigestPath(yearMonth) {
|
|
6576
|
-
return
|
|
6823
|
+
return join7(digestsDir(), "month", `${yearMonth}.json`);
|
|
6577
6824
|
}
|
|
6578
6825
|
function writeDayDigest(digest2) {
|
|
6579
6826
|
const final = dayDigestPath(digest2.key);
|
|
6580
|
-
|
|
6827
|
+
mkdirSync5(dirname7(final), { recursive: true });
|
|
6581
6828
|
const tmp = `${final}.tmp`;
|
|
6582
|
-
|
|
6829
|
+
writeFileSync4(tmp, JSON.stringify(digest2, null, 2), "utf8");
|
|
6583
6830
|
if (process.platform !== "win32") {
|
|
6584
6831
|
try {
|
|
6585
6832
|
chmodSync(tmp, 384);
|
|
@@ -6590,7 +6837,7 @@ function writeDayDigest(digest2) {
|
|
|
6590
6837
|
}
|
|
6591
6838
|
function readDayDigest(date) {
|
|
6592
6839
|
const p = dayDigestPath(date);
|
|
6593
|
-
if (!
|
|
6840
|
+
if (!existsSync6(p))
|
|
6594
6841
|
return null;
|
|
6595
6842
|
return parseDigestFile(p, CURRENT_DAY_DIGEST_SCHEMA_VERSION);
|
|
6596
6843
|
}
|
|
@@ -6613,9 +6860,9 @@ function __clearTodayCacheForTest() {
|
|
|
6613
6860
|
}
|
|
6614
6861
|
function writeWeekDigest(digest2) {
|
|
6615
6862
|
const final = weekDigestPath(digest2.key);
|
|
6616
|
-
|
|
6863
|
+
mkdirSync5(dirname7(final), { recursive: true });
|
|
6617
6864
|
const tmp = `${final}.tmp`;
|
|
6618
|
-
|
|
6865
|
+
writeFileSync4(tmp, JSON.stringify(digest2, null, 2), "utf8");
|
|
6619
6866
|
if (process.platform !== "win32") {
|
|
6620
6867
|
try {
|
|
6621
6868
|
chmodSync(tmp, 384);
|
|
@@ -6626,13 +6873,13 @@ function writeWeekDigest(digest2) {
|
|
|
6626
6873
|
}
|
|
6627
6874
|
function readWeekDigest(monday) {
|
|
6628
6875
|
const p = weekDigestPath(monday);
|
|
6629
|
-
if (!
|
|
6876
|
+
if (!existsSync6(p))
|
|
6630
6877
|
return null;
|
|
6631
6878
|
return parseDigestFile(p, CURRENT_WEEK_DIGEST_SCHEMA_VERSION);
|
|
6632
6879
|
}
|
|
6633
6880
|
function listWeekDigestKeys() {
|
|
6634
|
-
const dir =
|
|
6635
|
-
if (!
|
|
6881
|
+
const dir = join7(digestsDir(), "week");
|
|
6882
|
+
if (!existsSync6(dir))
|
|
6636
6883
|
return [];
|
|
6637
6884
|
return readdirSync(dir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length)).filter((k) => /^\d{4}-\d{2}-\d{2}$/.test(k));
|
|
6638
6885
|
}
|
|
@@ -6650,9 +6897,9 @@ function setCurrentWeekDigestInCache(monday, digest2, nowMs) {
|
|
|
6650
6897
|
}
|
|
6651
6898
|
function writeMonthDigest(digest2) {
|
|
6652
6899
|
const final = monthDigestPath(digest2.key);
|
|
6653
|
-
|
|
6900
|
+
mkdirSync5(dirname7(final), { recursive: true });
|
|
6654
6901
|
const tmp = `${final}.tmp`;
|
|
6655
|
-
|
|
6902
|
+
writeFileSync4(tmp, JSON.stringify(digest2, null, 2), "utf8");
|
|
6656
6903
|
if (process.platform !== "win32") {
|
|
6657
6904
|
try {
|
|
6658
6905
|
chmodSync(tmp, 384);
|
|
@@ -6663,13 +6910,13 @@ function writeMonthDigest(digest2) {
|
|
|
6663
6910
|
}
|
|
6664
6911
|
function readMonthDigest(yearMonth) {
|
|
6665
6912
|
const p = monthDigestPath(yearMonth);
|
|
6666
|
-
if (!
|
|
6913
|
+
if (!existsSync6(p))
|
|
6667
6914
|
return null;
|
|
6668
6915
|
return parseDigestFile(p, CURRENT_MONTH_DIGEST_SCHEMA_VERSION);
|
|
6669
6916
|
}
|
|
6670
6917
|
function listMonthDigestKeys() {
|
|
6671
|
-
const dir =
|
|
6672
|
-
if (!
|
|
6918
|
+
const dir = join7(digestsDir(), "month");
|
|
6919
|
+
if (!existsSync6(dir))
|
|
6673
6920
|
return [];
|
|
6674
6921
|
return readdirSync(dir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length)).filter((k) => /^\d{4}-\d{2}$/.test(k));
|
|
6675
6922
|
}
|
|
@@ -6730,9 +6977,9 @@ __export(fs_exports2, {
|
|
|
6730
6977
|
writeMonthDigest: () => writeMonthDigest,
|
|
6731
6978
|
writeWeekDigest: () => writeWeekDigest
|
|
6732
6979
|
});
|
|
6733
|
-
import { readFileSync as
|
|
6980
|
+
import { readFileSync as readFileSync9, readdirSync as readdirSync2, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, renameSync as renameSync2, existsSync as existsSync7 } from "node:fs";
|
|
6734
6981
|
import { randomBytes } from "node:crypto";
|
|
6735
|
-
import { join as
|
|
6982
|
+
import { join as join8 } from "node:path";
|
|
6736
6983
|
function entriesDir() {
|
|
6737
6984
|
if (entriesDirCached)
|
|
6738
6985
|
return entriesDirCached;
|
|
@@ -6742,21 +6989,21 @@ function entriesDir() {
|
|
|
6742
6989
|
}
|
|
6743
6990
|
function __setEntriesDirForTest(path7) {
|
|
6744
6991
|
entriesDirCached = path7;
|
|
6745
|
-
|
|
6992
|
+
mkdirSync6(path7, { recursive: true });
|
|
6746
6993
|
}
|
|
6747
6994
|
function pathFor(sessionId, localDay) {
|
|
6748
|
-
return
|
|
6995
|
+
return join8(entriesDir(), `${entryKey(sessionId, localDay)}.json`);
|
|
6749
6996
|
}
|
|
6750
6997
|
function tmpPathFor(final) {
|
|
6751
6998
|
return `${final}.tmp.${process.pid}.${randomBytes(4).toString("hex")}`;
|
|
6752
6999
|
}
|
|
6753
7000
|
function writeEntry(entry) {
|
|
6754
7001
|
const dir = entriesDir();
|
|
6755
|
-
|
|
7002
|
+
mkdirSync6(dir, { recursive: true });
|
|
6756
7003
|
const final = pathFor(entry.session_id, entry.local_day);
|
|
6757
7004
|
const tmp = tmpPathFor(final);
|
|
6758
7005
|
const json = JSON.stringify(entry, null, 2);
|
|
6759
|
-
|
|
7006
|
+
writeFileSync5(tmp, json, { encoding: "utf8" });
|
|
6760
7007
|
renameSync2(tmp, final);
|
|
6761
7008
|
}
|
|
6762
7009
|
function enrichmentInputHash(e) {
|
|
@@ -6776,7 +7023,7 @@ function enrichmentInputHash(e) {
|
|
|
6776
7023
|
}
|
|
6777
7024
|
function writeEntryPreservingEnrichment(fresh) {
|
|
6778
7025
|
const dir = entriesDir();
|
|
6779
|
-
|
|
7026
|
+
mkdirSync6(dir, { recursive: true });
|
|
6780
7027
|
const final = pathFor(fresh.session_id, fresh.local_day);
|
|
6781
7028
|
const existing = readEntry(fresh.session_id, fresh.local_day);
|
|
6782
7029
|
let toWrite = fresh;
|
|
@@ -6784,19 +7031,19 @@ function writeEntryPreservingEnrichment(fresh) {
|
|
|
6784
7031
|
toWrite = { ...fresh, enrichment: existing.enrichment };
|
|
6785
7032
|
}
|
|
6786
7033
|
const tmp = tmpPathFor(final);
|
|
6787
|
-
|
|
7034
|
+
writeFileSync5(tmp, JSON.stringify(toWrite, null, 2), { encoding: "utf8" });
|
|
6788
7035
|
renameSync2(tmp, final);
|
|
6789
7036
|
}
|
|
6790
7037
|
function readEntry(sessionId, localDay) {
|
|
6791
7038
|
const p = pathFor(sessionId, localDay);
|
|
6792
|
-
if (!
|
|
7039
|
+
if (!existsSync7(p))
|
|
6793
7040
|
return null;
|
|
6794
|
-
const raw =
|
|
7041
|
+
const raw = readFileSync9(p, "utf8");
|
|
6795
7042
|
return JSON.parse(raw);
|
|
6796
7043
|
}
|
|
6797
7044
|
function listEntryKeys() {
|
|
6798
7045
|
const dir = entriesDir();
|
|
6799
|
-
if (!
|
|
7046
|
+
if (!existsSync7(dir))
|
|
6800
7047
|
return [];
|
|
6801
7048
|
return readdirSync2(dir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length));
|
|
6802
7049
|
}
|
|
@@ -11075,9 +11322,9 @@ RESPOND WITH ONLY VALID JSON (no prose, no code fence):
|
|
|
11075
11322
|
});
|
|
11076
11323
|
|
|
11077
11324
|
// ../entries/dist/tmux-runner.js
|
|
11078
|
-
import { mkdirSync as
|
|
11079
|
-
import { join as
|
|
11080
|
-
import { homedir as
|
|
11325
|
+
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync6, existsSync as existsSync8, readdirSync as readdirSync3, realpathSync as realpathSync3, readFileSync as readFileSync10, unlinkSync as unlinkSync3, renameSync as renameSync3 } from "node:fs";
|
|
11326
|
+
import { join as join9 } from "node:path";
|
|
11327
|
+
import { homedir as homedir4 } from "node:os";
|
|
11081
11328
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
11082
11329
|
function which(bin) {
|
|
11083
11330
|
const r = spawnSync2("/usr/bin/env", ["which", bin], { encoding: "utf8" });
|
|
@@ -11093,16 +11340,16 @@ function tmuxRunnerAvailable() {
|
|
|
11093
11340
|
return { ok: true };
|
|
11094
11341
|
}
|
|
11095
11342
|
function runtimeCwd() {
|
|
11096
|
-
const dir =
|
|
11097
|
-
if (!
|
|
11098
|
-
|
|
11099
|
-
return
|
|
11343
|
+
const dir = join9(homedir4(), ".cclens", "runtime");
|
|
11344
|
+
if (!existsSync8(dir))
|
|
11345
|
+
mkdirSync7(dir, { recursive: true });
|
|
11346
|
+
return realpathSync3(dir);
|
|
11100
11347
|
}
|
|
11101
11348
|
function ensureRuntimeCwdTrusted(cwd) {
|
|
11102
|
-
const cfgPath =
|
|
11349
|
+
const cfgPath = join9(homedir4(), ".claude.json");
|
|
11103
11350
|
let cfg;
|
|
11104
11351
|
try {
|
|
11105
|
-
cfg = JSON.parse(
|
|
11352
|
+
cfg = JSON.parse(readFileSync10(cfgPath, "utf8"));
|
|
11106
11353
|
} catch {
|
|
11107
11354
|
return;
|
|
11108
11355
|
}
|
|
@@ -11117,7 +11364,7 @@ function ensureRuntimeCwdTrusted(cwd) {
|
|
|
11117
11364
|
cfg.projects = projects;
|
|
11118
11365
|
const tmp = `${cfgPath}.cclens-tmp-${process.pid}`;
|
|
11119
11366
|
try {
|
|
11120
|
-
|
|
11367
|
+
writeFileSync6(tmp, JSON.stringify(cfg, null, 2));
|
|
11121
11368
|
renameSync3(tmp, cfgPath);
|
|
11122
11369
|
} catch {
|
|
11123
11370
|
try {
|
|
@@ -11144,16 +11391,16 @@ async function runClaudeUnderTmuxImpl(args2) {
|
|
|
11144
11391
|
ensureRuntimeCwdTrusted(cwd);
|
|
11145
11392
|
const runId = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
11146
11393
|
const sessionName = `cclens-${runId}`;
|
|
11147
|
-
const systemFile =
|
|
11148
|
-
const userFile =
|
|
11149
|
-
const wrapper =
|
|
11150
|
-
|
|
11151
|
-
|
|
11394
|
+
const systemFile = join9(cwd, `system-${runId}.txt`);
|
|
11395
|
+
const userFile = join9(cwd, `user-${runId}.txt`);
|
|
11396
|
+
const wrapper = join9(cwd, `run-${runId}.sh`);
|
|
11397
|
+
writeFileSync6(systemFile, args2.systemPrompt);
|
|
11398
|
+
writeFileSync6(userFile, args2.reminder ? `${args2.userPrompt}
|
|
11152
11399
|
|
|
11153
11400
|
---
|
|
11154
11401
|
|
|
11155
11402
|
${args2.reminder}` : args2.userPrompt);
|
|
11156
|
-
|
|
11403
|
+
writeFileSync6(wrapper, `#!/bin/bash
|
|
11157
11404
|
SYS="$(cat ${shellEscape(systemFile)})"
|
|
11158
11405
|
USR="$(cat ${shellEscape(userFile)})"
|
|
11159
11406
|
exec ${shellEscape(claudeBin)} \\
|
|
@@ -11235,7 +11482,7 @@ function snapshotAllTranscripts() {
|
|
|
11235
11482
|
return out;
|
|
11236
11483
|
}
|
|
11237
11484
|
for (const sub of subs) {
|
|
11238
|
-
const dir =
|
|
11485
|
+
const dir = join9(root, sub);
|
|
11239
11486
|
let files;
|
|
11240
11487
|
try {
|
|
11241
11488
|
files = readdirSync3(dir);
|
|
@@ -11244,7 +11491,7 @@ function snapshotAllTranscripts() {
|
|
|
11244
11491
|
}
|
|
11245
11492
|
for (const f of files) {
|
|
11246
11493
|
if (f.endsWith(".jsonl"))
|
|
11247
|
-
out.add(
|
|
11494
|
+
out.add(join9(dir, f));
|
|
11248
11495
|
}
|
|
11249
11496
|
}
|
|
11250
11497
|
return out;
|
|
@@ -11252,7 +11499,7 @@ function snapshotAllTranscripts() {
|
|
|
11252
11499
|
function readJsonlCwd(path7, maxLines = 8) {
|
|
11253
11500
|
let raw;
|
|
11254
11501
|
try {
|
|
11255
|
-
raw =
|
|
11502
|
+
raw = readFileSync10(path7, "utf8");
|
|
11256
11503
|
} catch {
|
|
11257
11504
|
return void 0;
|
|
11258
11505
|
}
|
|
@@ -11285,7 +11532,7 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
|
|
|
11285
11532
|
subs = [];
|
|
11286
11533
|
}
|
|
11287
11534
|
for (const sub of subs) {
|
|
11288
|
-
const dir =
|
|
11535
|
+
const dir = join9(root, sub);
|
|
11289
11536
|
let files;
|
|
11290
11537
|
try {
|
|
11291
11538
|
files = readdirSync3(dir);
|
|
@@ -11295,7 +11542,7 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
|
|
|
11295
11542
|
for (const f of files) {
|
|
11296
11543
|
if (!f.endsWith(".jsonl"))
|
|
11297
11544
|
continue;
|
|
11298
|
-
const full =
|
|
11545
|
+
const full = join9(dir, f);
|
|
11299
11546
|
if (existingBefore.has(full))
|
|
11300
11547
|
continue;
|
|
11301
11548
|
if (readJsonlCwd(full) === targetCwd)
|
|
@@ -11309,7 +11556,7 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
|
|
|
11309
11556
|
function parseTranscript2(path7, defaultModel) {
|
|
11310
11557
|
let raw;
|
|
11311
11558
|
try {
|
|
11312
|
-
raw =
|
|
11559
|
+
raw = readFileSync10(path7, "utf8");
|
|
11313
11560
|
} catch {
|
|
11314
11561
|
return { assembled: "", inputTokens: 0, outputTokens: 0, modelUsed: defaultModel, done: false };
|
|
11315
11562
|
}
|
|
@@ -11369,7 +11616,7 @@ function cleanup(cwd, runId, tmuxBin, sessionName, transcriptPath) {
|
|
|
11369
11616
|
}
|
|
11370
11617
|
for (const f of [`system-${runId}.txt`, `user-${runId}.txt`, `run-${runId}.sh`]) {
|
|
11371
11618
|
try {
|
|
11372
|
-
unlinkSync3(
|
|
11619
|
+
unlinkSync3(join9(cwd, f));
|
|
11373
11620
|
} catch {
|
|
11374
11621
|
}
|
|
11375
11622
|
}
|
|
@@ -11397,19 +11644,19 @@ var init_tmux_runner = __esm({
|
|
|
11397
11644
|
}
|
|
11398
11645
|
};
|
|
11399
11646
|
mutex = Promise.resolve();
|
|
11400
|
-
PROJECTS_ROOT = () =>
|
|
11647
|
+
PROJECTS_ROOT = () => join9(homedir4(), ".claude", "projects");
|
|
11401
11648
|
}
|
|
11402
11649
|
});
|
|
11403
11650
|
|
|
11404
11651
|
// ../entries/dist/llm-runner.js
|
|
11405
11652
|
import { spawn as spawn3 } from "node:child_process";
|
|
11406
|
-
import { mkdirSync as
|
|
11407
|
-
import { join as
|
|
11653
|
+
import { mkdirSync as mkdirSync8, appendFileSync as appendFileSync2, writeFileSync as writeFileSync7, existsSync as existsSync9 } from "node:fs";
|
|
11654
|
+
import { join as join10 } from "node:path";
|
|
11408
11655
|
import { randomUUID } from "node:crypto";
|
|
11409
11656
|
function ensureRunsDir() {
|
|
11410
|
-
if (!
|
|
11657
|
+
if (!existsSync9(RUNS_DIR)) {
|
|
11411
11658
|
try {
|
|
11412
|
-
|
|
11659
|
+
mkdirSync8(RUNS_DIR, { recursive: true });
|
|
11413
11660
|
} catch {
|
|
11414
11661
|
}
|
|
11415
11662
|
}
|
|
@@ -11436,7 +11683,7 @@ function newRunId(kind) {
|
|
|
11436
11683
|
return `${ts}_${kind}_${short}`;
|
|
11437
11684
|
}
|
|
11438
11685
|
function tracePath(runId) {
|
|
11439
|
-
return
|
|
11686
|
+
return join10(RUNS_DIR, `${runId}.jsonl`);
|
|
11440
11687
|
}
|
|
11441
11688
|
function safeAppend(path7, line) {
|
|
11442
11689
|
try {
|
|
@@ -11446,7 +11693,7 @@ function safeAppend(path7, line) {
|
|
|
11446
11693
|
}
|
|
11447
11694
|
function safeWrite(path7, line) {
|
|
11448
11695
|
try {
|
|
11449
|
-
|
|
11696
|
+
writeFileSync7(path7, line);
|
|
11450
11697
|
} catch {
|
|
11451
11698
|
}
|
|
11452
11699
|
}
|
|
@@ -11852,8 +12099,8 @@ var init_enrich2 = __esm({
|
|
|
11852
12099
|
});
|
|
11853
12100
|
|
|
11854
12101
|
// ../entries/dist/budget.js
|
|
11855
|
-
import { appendFileSync as appendFileSync3, readFileSync as
|
|
11856
|
-
import { dirname as
|
|
12102
|
+
import { appendFileSync as appendFileSync3, readFileSync as readFileSync11, existsSync as existsSync10, mkdirSync as mkdirSync9 } from "node:fs";
|
|
12103
|
+
import { dirname as dirname8 } from "node:path";
|
|
11857
12104
|
function spendPath() {
|
|
11858
12105
|
if (spendPathCached)
|
|
11859
12106
|
return spendPathCached;
|
|
@@ -11865,17 +12112,17 @@ function __setSpendPathForTest(path7) {
|
|
|
11865
12112
|
}
|
|
11866
12113
|
function appendSpend(record) {
|
|
11867
12114
|
const p = spendPath();
|
|
11868
|
-
|
|
12115
|
+
mkdirSync9(dirname8(p), { recursive: true });
|
|
11869
12116
|
appendFileSync3(p, JSON.stringify(record) + "\n", { encoding: "utf8" });
|
|
11870
12117
|
}
|
|
11871
12118
|
function monthToDateSpend(now = /* @__PURE__ */ new Date()) {
|
|
11872
12119
|
const p = spendPath();
|
|
11873
|
-
if (!
|
|
12120
|
+
if (!existsSync10(p))
|
|
11874
12121
|
return 0;
|
|
11875
12122
|
const year = now.getUTCFullYear();
|
|
11876
12123
|
const month2 = now.getUTCMonth();
|
|
11877
12124
|
let total = 0;
|
|
11878
|
-
const raw =
|
|
12125
|
+
const raw = readFileSync11(p, "utf8");
|
|
11879
12126
|
for (const line of raw.split("\n")) {
|
|
11880
12127
|
if (!line)
|
|
11881
12128
|
continue;
|
|
@@ -11904,7 +12151,7 @@ var init_budget = __esm({
|
|
|
11904
12151
|
});
|
|
11905
12152
|
|
|
11906
12153
|
// ../entries/dist/pipeline-lock.js
|
|
11907
|
-
import { writeFileSync as
|
|
12154
|
+
import { writeFileSync as writeFileSync8, unlinkSync as unlinkSync4, existsSync as existsSync11, readFileSync as readFileSync12, statSync as statSync2 } from "node:fs";
|
|
11908
12155
|
function lockPath() {
|
|
11909
12156
|
if (lockPathCached)
|
|
11910
12157
|
return lockPathCached;
|
|
@@ -11915,7 +12162,7 @@ function __setInteractiveLockPathForTest(path7) {
|
|
|
11915
12162
|
lockPathCached = path7;
|
|
11916
12163
|
}
|
|
11917
12164
|
function touchLock() {
|
|
11918
|
-
|
|
12165
|
+
writeFileSync8(lockPath(), String(process.pid), "utf8");
|
|
11919
12166
|
}
|
|
11920
12167
|
function writeInteractiveLock() {
|
|
11921
12168
|
touchLock();
|
|
@@ -11949,13 +12196,13 @@ function pidAlive(pid) {
|
|
|
11949
12196
|
}
|
|
11950
12197
|
function interactiveLockFresh(nowMs) {
|
|
11951
12198
|
const p = lockPath();
|
|
11952
|
-
if (!
|
|
12199
|
+
if (!existsSync11(p))
|
|
11953
12200
|
return false;
|
|
11954
12201
|
try {
|
|
11955
12202
|
const mtime = statSync2(p).mtimeMs;
|
|
11956
12203
|
if (nowMs - mtime > STALE_MS)
|
|
11957
12204
|
return false;
|
|
11958
|
-
const pid = Number(
|
|
12205
|
+
const pid = Number(readFileSync12(p, "utf8").trim());
|
|
11959
12206
|
if (!Number.isFinite(pid) || pid <= 0)
|
|
11960
12207
|
return false;
|
|
11961
12208
|
if (!pidAlive(pid))
|
|
@@ -12061,8 +12308,8 @@ var init_queue = __esm({
|
|
|
12061
12308
|
});
|
|
12062
12309
|
|
|
12063
12310
|
// ../entries/dist/settings.js
|
|
12064
|
-
import { readFileSync as
|
|
12065
|
-
import { dirname as
|
|
12311
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync9, renameSync as renameSync4, chmodSync as chmodSync2, mkdirSync as mkdirSync10, existsSync as existsSync12 } from "node:fs";
|
|
12312
|
+
import { dirname as dirname9 } from "node:path";
|
|
12066
12313
|
function settingsPath() {
|
|
12067
12314
|
if (settingsPathCached)
|
|
12068
12315
|
return settingsPathCached;
|
|
@@ -12097,10 +12344,10 @@ function fromDisk(d) {
|
|
|
12097
12344
|
}
|
|
12098
12345
|
function readSettings() {
|
|
12099
12346
|
const p = settingsPath();
|
|
12100
|
-
if (!
|
|
12347
|
+
if (!existsSync12(p))
|
|
12101
12348
|
return DEFAULT_SETTINGS;
|
|
12102
12349
|
try {
|
|
12103
|
-
const raw =
|
|
12350
|
+
const raw = readFileSync13(p, "utf8");
|
|
12104
12351
|
return fromDisk(JSON.parse(raw));
|
|
12105
12352
|
} catch {
|
|
12106
12353
|
return DEFAULT_SETTINGS;
|
|
@@ -12108,9 +12355,9 @@ function readSettings() {
|
|
|
12108
12355
|
}
|
|
12109
12356
|
function writeSettings(s) {
|
|
12110
12357
|
const p = settingsPath();
|
|
12111
|
-
|
|
12358
|
+
mkdirSync10(dirname9(p), { recursive: true });
|
|
12112
12359
|
const tmp = `${p}.tmp`;
|
|
12113
|
-
|
|
12360
|
+
writeFileSync9(tmp, JSON.stringify(toDisk(s), null, 2), { encoding: "utf8" });
|
|
12114
12361
|
if (process.platform !== "win32") {
|
|
12115
12362
|
chmodSync2(tmp, 384);
|
|
12116
12363
|
}
|
|
@@ -16062,6 +16309,7 @@ function buildIngestPayload(inputs) {
|
|
|
16062
16309
|
return {
|
|
16063
16310
|
ingestId: randomUUID2(),
|
|
16064
16311
|
observedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16312
|
+
cliVersion: "0.13.1",
|
|
16065
16313
|
...richRollup || inputs.enrichedExtras || inputs.artifactSignals ? { schemaVersion: RICH_ROLLUP_SCHEMA_VERSION } : {},
|
|
16066
16314
|
...inputs.rollup ? { dailyRollup: inputs.rollup } : {},
|
|
16067
16315
|
...richRollup ? { richRollup } : {},
|
|
@@ -16099,8 +16347,8 @@ var init_push = __esm({
|
|
|
16099
16347
|
});
|
|
16100
16348
|
|
|
16101
16349
|
// src/team/git-remote.ts
|
|
16102
|
-
import { existsSync as
|
|
16103
|
-
import { dirname as
|
|
16350
|
+
import { existsSync as existsSync13, readFileSync as readFileSync14, statSync as statSync3 } from "node:fs";
|
|
16351
|
+
import { dirname as dirname10, isAbsolute, join as join11, resolve } from "node:path";
|
|
16104
16352
|
function parseGithubRemote(url) {
|
|
16105
16353
|
const m = url.trim().match(GITHUB_URL_RE);
|
|
16106
16354
|
return m ? `${m[1]}/${m[2]}`.toLowerCase() : null;
|
|
@@ -16120,19 +16368,19 @@ function originUrl(configText) {
|
|
|
16120
16368
|
return null;
|
|
16121
16369
|
}
|
|
16122
16370
|
function gitConfigPathFor(dir) {
|
|
16123
|
-
const dotGit =
|
|
16371
|
+
const dotGit = join11(dir, ".git");
|
|
16124
16372
|
const st = statSync3(dotGit, { throwIfNoEntry: false });
|
|
16125
16373
|
if (!st) return null;
|
|
16126
|
-
if (st.isDirectory()) return
|
|
16127
|
-
const m =
|
|
16374
|
+
if (st.isDirectory()) return join11(dotGit, "config");
|
|
16375
|
+
const m = readFileSync14(dotGit, "utf8").match(/^gitdir:\s*(.+)\s*$/m);
|
|
16128
16376
|
if (!m) return null;
|
|
16129
16377
|
const gd = isAbsolute(m[1]) ? m[1] : resolve(dir, m[1]);
|
|
16130
|
-
const commondirFile =
|
|
16131
|
-
if (
|
|
16132
|
-
const common =
|
|
16133
|
-
return
|
|
16378
|
+
const commondirFile = join11(gd, "commondir");
|
|
16379
|
+
if (existsSync13(commondirFile)) {
|
|
16380
|
+
const common = readFileSync14(commondirFile, "utf8").trim();
|
|
16381
|
+
return join11(isAbsolute(common) ? common : resolve(gd, common), "config");
|
|
16134
16382
|
}
|
|
16135
|
-
return
|
|
16383
|
+
return join11(gd, "config");
|
|
16136
16384
|
}
|
|
16137
16385
|
function createRepoResolver() {
|
|
16138
16386
|
const cache = /* @__PURE__ */ new Map();
|
|
@@ -16142,14 +16390,14 @@ function createRepoResolver() {
|
|
|
16142
16390
|
if (hit !== void 0) return hit;
|
|
16143
16391
|
let repo = null;
|
|
16144
16392
|
try {
|
|
16145
|
-
for (let d = dir; ; d =
|
|
16393
|
+
for (let d = dir; ; d = dirname10(d)) {
|
|
16146
16394
|
const config = gitConfigPathFor(d);
|
|
16147
|
-
if (config &&
|
|
16148
|
-
const url = originUrl(
|
|
16395
|
+
if (config && existsSync13(config)) {
|
|
16396
|
+
const url = originUrl(readFileSync14(config, "utf8"));
|
|
16149
16397
|
repo = url ? parseGithubRemote(url) : null;
|
|
16150
16398
|
break;
|
|
16151
16399
|
}
|
|
16152
|
-
if (d ===
|
|
16400
|
+
if (d === dirname10(d)) break;
|
|
16153
16401
|
}
|
|
16154
16402
|
} catch {
|
|
16155
16403
|
repo = null;
|
|
@@ -16167,10 +16415,10 @@ var init_git_remote = __esm({
|
|
|
16167
16415
|
});
|
|
16168
16416
|
|
|
16169
16417
|
// src/team/queue.ts
|
|
16170
|
-
import { readFileSync as
|
|
16171
|
-
import { dirname as
|
|
16418
|
+
import { readFileSync as readFileSync15, writeFileSync as writeFileSync10, appendFileSync as appendFileSync4, statSync as statSync4, mkdirSync as mkdirSync11 } from "node:fs";
|
|
16419
|
+
import { dirname as dirname11 } from "node:path";
|
|
16172
16420
|
function enqueuePayload(payload, queuePath = QUEUE_PATH) {
|
|
16173
|
-
|
|
16421
|
+
mkdirSync11(dirname11(queuePath), { recursive: true });
|
|
16174
16422
|
const entry = { payload, enqueuedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
16175
16423
|
appendFileSync4(queuePath, JSON.stringify(entry) + "\n", "utf8");
|
|
16176
16424
|
try {
|
|
@@ -16184,7 +16432,7 @@ function enqueuePayload(payload, queuePath = QUEUE_PATH) {
|
|
|
16184
16432
|
function dequeuePayloads(queuePath = QUEUE_PATH) {
|
|
16185
16433
|
let lines;
|
|
16186
16434
|
try {
|
|
16187
|
-
lines =
|
|
16435
|
+
lines = readFileSync15(queuePath, "utf8").trim().split("\n").filter(Boolean);
|
|
16188
16436
|
} catch {
|
|
16189
16437
|
return [];
|
|
16190
16438
|
}
|
|
@@ -16199,18 +16447,18 @@ function dequeuePayloads(queuePath = QUEUE_PATH) {
|
|
|
16199
16447
|
} catch {
|
|
16200
16448
|
}
|
|
16201
16449
|
}
|
|
16202
|
-
|
|
16450
|
+
writeFileSync10(queuePath, "", "utf8");
|
|
16203
16451
|
return valid.map((e) => e.payload);
|
|
16204
16452
|
}
|
|
16205
16453
|
function pruneOldest(queuePath) {
|
|
16206
16454
|
let lines;
|
|
16207
16455
|
try {
|
|
16208
|
-
lines =
|
|
16456
|
+
lines = readFileSync15(queuePath, "utf8").trim().split("\n").filter(Boolean);
|
|
16209
16457
|
} catch {
|
|
16210
16458
|
return;
|
|
16211
16459
|
}
|
|
16212
16460
|
const keep = lines.slice(Math.floor(lines.length / 2));
|
|
16213
|
-
|
|
16461
|
+
writeFileSync10(queuePath, keep.join("\n") + "\n", "utf8");
|
|
16214
16462
|
}
|
|
16215
16463
|
var QUEUE_PATH, MAX_SIZE_BYTES, MAX_AGE_MS;
|
|
16216
16464
|
var init_queue2 = __esm({
|
|
@@ -16224,8 +16472,8 @@ var init_queue2 = __esm({
|
|
|
16224
16472
|
});
|
|
16225
16473
|
|
|
16226
16474
|
// src/usage/profile.ts
|
|
16227
|
-
import { existsSync as
|
|
16228
|
-
import { dirname as
|
|
16475
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync12, readFileSync as readFileSync16, writeFileSync as writeFileSync11 } from "node:fs";
|
|
16476
|
+
import { dirname as dirname12 } from "node:path";
|
|
16229
16477
|
function mapRateLimitTier(rateLimitTier) {
|
|
16230
16478
|
switch (rateLimitTier) {
|
|
16231
16479
|
case "default_claude_pro":
|
|
@@ -16265,9 +16513,9 @@ async function fetchProfile(nowMs = Date.now()) {
|
|
|
16265
16513
|
};
|
|
16266
16514
|
}
|
|
16267
16515
|
function readCachedProfile(cachePath) {
|
|
16268
|
-
if (!
|
|
16516
|
+
if (!existsSync14(cachePath)) return null;
|
|
16269
16517
|
try {
|
|
16270
|
-
const raw = JSON.parse(
|
|
16518
|
+
const raw = JSON.parse(readFileSync16(cachePath, "utf8"));
|
|
16271
16519
|
if (typeof raw.fetchedAtMs !== "number" || !raw.profile) return null;
|
|
16272
16520
|
return raw;
|
|
16273
16521
|
} catch {
|
|
@@ -16275,8 +16523,8 @@ function readCachedProfile(cachePath) {
|
|
|
16275
16523
|
}
|
|
16276
16524
|
}
|
|
16277
16525
|
function writeCachedProfile(cachePath, profile, nowMs = Date.now()) {
|
|
16278
|
-
|
|
16279
|
-
|
|
16526
|
+
mkdirSync12(dirname12(cachePath), { recursive: true });
|
|
16527
|
+
writeFileSync11(
|
|
16280
16528
|
cachePath,
|
|
16281
16529
|
JSON.stringify({ fetchedAtMs: nowMs, profile }, null, 2),
|
|
16282
16530
|
{ mode: 384 }
|
|
@@ -16456,12 +16704,12 @@ var init_backfill = __esm({
|
|
|
16456
16704
|
});
|
|
16457
16705
|
|
|
16458
16706
|
// src/team/last-push.ts
|
|
16459
|
-
import { writeFileSync as
|
|
16460
|
-
import { join as
|
|
16707
|
+
import { writeFileSync as writeFileSync12, unlinkSync as unlinkSync5, mkdirSync as mkdirSync13 } from "node:fs";
|
|
16708
|
+
import { join as join12 } from "node:path";
|
|
16461
16709
|
function write(record, dir) {
|
|
16462
16710
|
const d = dir ?? cclensHome();
|
|
16463
|
-
|
|
16464
|
-
|
|
16711
|
+
mkdirSync13(d, { recursive: true });
|
|
16712
|
+
writeFileSync12(join12(d, LAST_PUSH_FILE), JSON.stringify(record, null, 2), { mode: 384 });
|
|
16465
16713
|
}
|
|
16466
16714
|
function writeLastPushSuccess(payload, dir) {
|
|
16467
16715
|
write({ pushedAt: (/* @__PURE__ */ new Date()).toISOString(), ok: true, payload }, dir);
|
|
@@ -16472,7 +16720,7 @@ function writeLastPushFailure(payload, error, dir) {
|
|
|
16472
16720
|
function clearLastPush(dir) {
|
|
16473
16721
|
const d = dir ?? cclensHome();
|
|
16474
16722
|
try {
|
|
16475
|
-
unlinkSync5(
|
|
16723
|
+
unlinkSync5(join12(d, LAST_PUSH_FILE));
|
|
16476
16724
|
} catch {
|
|
16477
16725
|
}
|
|
16478
16726
|
}
|
|
@@ -16492,25 +16740,25 @@ __export(file_probe_exports, {
|
|
|
16492
16740
|
probeArtifactSignals: () => probeArtifactSignals
|
|
16493
16741
|
});
|
|
16494
16742
|
import { createHash } from "node:crypto";
|
|
16495
|
-
import { existsSync as
|
|
16496
|
-
import { homedir as
|
|
16497
|
-
import { join as
|
|
16743
|
+
import { existsSync as existsSync15, readdirSync as readdirSync4, statSync as statSync5 } from "node:fs";
|
|
16744
|
+
import { homedir as homedir5 } from "node:os";
|
|
16745
|
+
import { join as join13, relative, resolve as resolve2, sep } from "node:path";
|
|
16498
16746
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
16499
16747
|
function pathHash(relPath) {
|
|
16500
16748
|
return createHash("sha256").update(relPath.split(sep).join("/")).digest("hex").slice(0, 32);
|
|
16501
16749
|
}
|
|
16502
16750
|
function defaultScanRoots(extraRoots = []) {
|
|
16503
16751
|
const roots = [];
|
|
16504
|
-
const home =
|
|
16505
|
-
if (
|
|
16752
|
+
const home = join13(homedir5(), ".claude");
|
|
16753
|
+
if (existsSync15(home)) roots.push({ root: home, label: "user" });
|
|
16506
16754
|
for (const e of extraRoots) {
|
|
16507
16755
|
const r = resolve2(e, ".claude");
|
|
16508
|
-
if (
|
|
16756
|
+
if (existsSync15(r) && r !== home) roots.push({ root: r, label: "project" });
|
|
16509
16757
|
}
|
|
16510
16758
|
return roots;
|
|
16511
16759
|
}
|
|
16512
16760
|
function listMarkdownFiles(dir) {
|
|
16513
|
-
if (!
|
|
16761
|
+
if (!existsSync15(dir)) return [];
|
|
16514
16762
|
const out = [];
|
|
16515
16763
|
let entries2;
|
|
16516
16764
|
try {
|
|
@@ -16520,7 +16768,7 @@ function listMarkdownFiles(dir) {
|
|
|
16520
16768
|
}
|
|
16521
16769
|
for (const name of entries2) {
|
|
16522
16770
|
if (name.startsWith(".")) continue;
|
|
16523
|
-
const full =
|
|
16771
|
+
const full = join13(dir, name);
|
|
16524
16772
|
let stat;
|
|
16525
16773
|
try {
|
|
16526
16774
|
stat = statSync5(full);
|
|
@@ -16540,7 +16788,7 @@ function firstSeenDateOf(file) {
|
|
|
16540
16788
|
const out = execFileSync2(
|
|
16541
16789
|
"git",
|
|
16542
16790
|
["log", "--diff-filter=A", "--follow", "--format=%cs", "--", file],
|
|
16543
|
-
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd:
|
|
16791
|
+
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd: dirname13(file) }
|
|
16544
16792
|
).trim().split("\n").filter(Boolean);
|
|
16545
16793
|
if (out.length > 0) return out[out.length - 1];
|
|
16546
16794
|
} catch {
|
|
@@ -16552,7 +16800,7 @@ function firstSeenDateOf(file) {
|
|
|
16552
16800
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
16553
16801
|
}
|
|
16554
16802
|
}
|
|
16555
|
-
function
|
|
16803
|
+
function dirname13(p) {
|
|
16556
16804
|
const i = p.lastIndexOf(sep);
|
|
16557
16805
|
return i < 0 ? "." : p.slice(0, i);
|
|
16558
16806
|
}
|
|
@@ -16577,8 +16825,8 @@ function todayLocal() {
|
|
|
16577
16825
|
function scanAuthored(roots, subdir, day2) {
|
|
16578
16826
|
const out = [];
|
|
16579
16827
|
for (const r of roots) {
|
|
16580
|
-
const dir =
|
|
16581
|
-
if (!
|
|
16828
|
+
const dir = join13(r.root, subdir);
|
|
16829
|
+
if (!existsSync15(dir)) continue;
|
|
16582
16830
|
for (const f of listMarkdownFiles(dir)) {
|
|
16583
16831
|
const firstSeen = firstSeenDateOf(f);
|
|
16584
16832
|
if (firstSeen !== day2) continue;
|
|
@@ -16591,8 +16839,8 @@ function scanAuthored(roots, subdir, day2) {
|
|
|
16591
16839
|
function scanEdited(roots, day2) {
|
|
16592
16840
|
const out = [];
|
|
16593
16841
|
for (const r of roots) {
|
|
16594
|
-
const dir =
|
|
16595
|
-
if (!
|
|
16842
|
+
const dir = join13(r.root, "skills");
|
|
16843
|
+
if (!existsSync15(dir)) continue;
|
|
16596
16844
|
for (const f of listMarkdownFiles(dir)) {
|
|
16597
16845
|
const firstSeen = firstSeenDateOf(f);
|
|
16598
16846
|
if (firstSeen === day2) continue;
|
|
@@ -16615,16 +16863,16 @@ function claudemdLineDelta(extraRoots, authorEmail, day2) {
|
|
|
16615
16863
|
const candidates = [];
|
|
16616
16864
|
for (const e of extraRoots) {
|
|
16617
16865
|
const f = resolve2(e, "CLAUDE.md");
|
|
16618
|
-
if (
|
|
16866
|
+
if (existsSync15(f)) candidates.push(f);
|
|
16619
16867
|
}
|
|
16620
|
-
const homeClaudeMd =
|
|
16621
|
-
if (
|
|
16868
|
+
const homeClaudeMd = join13(homedir5(), "CLAUDE.md");
|
|
16869
|
+
if (existsSync15(homeClaudeMd)) candidates.push(homeClaudeMd);
|
|
16622
16870
|
for (const file of candidates) {
|
|
16623
16871
|
try {
|
|
16624
16872
|
const out = execFileSync2(
|
|
16625
16873
|
"git",
|
|
16626
16874
|
["log", "--numstat", "--format=COMMIT %cs %ae", "--", file],
|
|
16627
|
-
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd:
|
|
16875
|
+
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd: dirname13(file) }
|
|
16628
16876
|
);
|
|
16629
16877
|
let currentDate = "";
|
|
16630
16878
|
let currentEmail = "";
|
|
@@ -17167,11 +17415,11 @@ var logs_exports = {};
|
|
|
17167
17415
|
__export(logs_exports, {
|
|
17168
17416
|
teamLogs: () => teamLogs
|
|
17169
17417
|
});
|
|
17170
|
-
import { readFileSync as
|
|
17418
|
+
import { readFileSync as readFileSync17 } from "node:fs";
|
|
17171
17419
|
async function teamLogs() {
|
|
17172
17420
|
const logPath = cclensPath("daemon.log");
|
|
17173
17421
|
try {
|
|
17174
|
-
const lines =
|
|
17422
|
+
const lines = readFileSync17(logPath, "utf8").trim().split("\n");
|
|
17175
17423
|
const teamLines = lines.filter((l) => l.includes("team "));
|
|
17176
17424
|
if (teamLines.length === 0) {
|
|
17177
17425
|
console.log("No team-related log entries found.");
|
|
@@ -17277,8 +17525,8 @@ __export(runs_exports, {
|
|
|
17277
17525
|
runs: () => runs
|
|
17278
17526
|
});
|
|
17279
17527
|
import { execSync as execSync2 } from "node:child_process";
|
|
17280
|
-
import { existsSync as
|
|
17281
|
-
import { join as
|
|
17528
|
+
import { existsSync as existsSync16, readFileSync as readFileSync18, readdirSync as readdirSync5, statSync as statSync6 } from "node:fs";
|
|
17529
|
+
import { join as join14 } from "node:path";
|
|
17282
17530
|
async function runs(args2) {
|
|
17283
17531
|
const json = args2.includes("--json");
|
|
17284
17532
|
const watch = args2.includes("--watch");
|
|
@@ -17362,8 +17610,8 @@ function listActiveRuns() {
|
|
|
17362
17610
|
return runs2.sort((a, b) => a.elapsed_s - b.elapsed_s);
|
|
17363
17611
|
}
|
|
17364
17612
|
function readSpend(sinceMs) {
|
|
17365
|
-
if (!
|
|
17366
|
-
const lines =
|
|
17613
|
+
if (!existsSync16(SPEND_PATH)) return [];
|
|
17614
|
+
const lines = readFileSync18(SPEND_PATH, "utf-8").split("\n").filter((l) => l.trim());
|
|
17367
17615
|
const out = [];
|
|
17368
17616
|
for (const line of lines) {
|
|
17369
17617
|
try {
|
|
@@ -17484,23 +17732,23 @@ function ageLabel(ms) {
|
|
|
17484
17732
|
return `${Math.floor(ms / 864e5)}d`;
|
|
17485
17733
|
}
|
|
17486
17734
|
function listTraceFiles() {
|
|
17487
|
-
if (!
|
|
17735
|
+
if (!existsSync16(RUNS_DIR2)) return [];
|
|
17488
17736
|
const entries2 = readdirSync5(RUNS_DIR2).filter((f) => f.endsWith(".jsonl"));
|
|
17489
17737
|
return entries2.map((f) => {
|
|
17490
|
-
const path7 =
|
|
17738
|
+
const path7 = join14(RUNS_DIR2, f);
|
|
17491
17739
|
const st = statSync6(path7);
|
|
17492
17740
|
return { runId: f.replace(/\.jsonl$/, ""), path: path7, mtimeMs: st.mtimeMs };
|
|
17493
17741
|
}).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
17494
17742
|
}
|
|
17495
17743
|
function resolveRunId(arg) {
|
|
17496
|
-
if (!
|
|
17744
|
+
if (!existsSync16(RUNS_DIR2)) return null;
|
|
17497
17745
|
if (arg === "latest") {
|
|
17498
17746
|
const all2 = listTraceFiles();
|
|
17499
17747
|
if (all2.length === 0) return null;
|
|
17500
17748
|
return { runId: all2[0].runId, path: all2[0].path };
|
|
17501
17749
|
}
|
|
17502
|
-
const exact =
|
|
17503
|
-
if (
|
|
17750
|
+
const exact = join14(RUNS_DIR2, `${arg}.jsonl`);
|
|
17751
|
+
if (existsSync16(exact)) return { runId: arg, path: exact };
|
|
17504
17752
|
const all = listTraceFiles();
|
|
17505
17753
|
const matches = all.filter((r) => r.runId.includes(arg));
|
|
17506
17754
|
if (matches.length === 1) return { runId: matches[0].runId, path: matches[0].path };
|
|
@@ -17512,7 +17760,7 @@ function resolveRunId(arg) {
|
|
|
17512
17760
|
return null;
|
|
17513
17761
|
}
|
|
17514
17762
|
function readTrace(path7) {
|
|
17515
|
-
return
|
|
17763
|
+
return readFileSync18(path7, "utf-8").split("\n").filter((l) => l.trim()).map((l) => {
|
|
17516
17764
|
try {
|
|
17517
17765
|
return JSON.parse(l);
|
|
17518
17766
|
} catch {
|
|
@@ -17524,7 +17772,7 @@ async function inspect(arg, follow, json) {
|
|
|
17524
17772
|
const r = resolveRunId(arg);
|
|
17525
17773
|
if (!r) {
|
|
17526
17774
|
console.error(`run not found: ${arg}`);
|
|
17527
|
-
if (
|
|
17775
|
+
if (existsSync16(RUNS_DIR2)) {
|
|
17528
17776
|
const all = listTraceFiles().slice(0, 5);
|
|
17529
17777
|
if (all.length > 0) {
|
|
17530
17778
|
console.error(`
|
|
@@ -17681,6 +17929,11 @@ async function main() {
|
|
|
17681
17929
|
await daemon2(args.slice(1));
|
|
17682
17930
|
break;
|
|
17683
17931
|
}
|
|
17932
|
+
case "autostart": {
|
|
17933
|
+
const { autostart: autostart2 } = await Promise.resolve().then(() => (init_autostart(), autostart_exports));
|
|
17934
|
+
await autostart2(args.slice(1));
|
|
17935
|
+
break;
|
|
17936
|
+
}
|
|
17684
17937
|
case "team": {
|
|
17685
17938
|
const { team: team2 } = await Promise.resolve().then(() => (init_team2(), team_exports));
|
|
17686
17939
|
await team2(args.slice(1));
|
|
@@ -17694,7 +17947,7 @@ async function main() {
|
|
|
17694
17947
|
case "version":
|
|
17695
17948
|
case "--version":
|
|
17696
17949
|
case "-v":
|
|
17697
|
-
console.log(`fleetlens ${"0.
|
|
17950
|
+
console.log(`fleetlens ${"0.13.1"}`);
|
|
17698
17951
|
break;
|
|
17699
17952
|
case "help":
|
|
17700
17953
|
case "--help":
|
|
@@ -17720,6 +17973,7 @@ Advanced:
|
|
|
17720
17973
|
web [page] [--open] Print dashboard URL without auto-starting daemon (pass --open to also launch browser)
|
|
17721
17974
|
start --no-daemon Start only the web server (no daemon)
|
|
17722
17975
|
daemon <start|stop|status|logs> Manage the usage daemon by itself
|
|
17976
|
+
autostart <install|uninstall|status> Run the usage daemon at login (macOS launchd)
|
|
17723
17977
|
|
|
17724
17978
|
Team:
|
|
17725
17979
|
team join <url> <token> Pair with a team server
|