fleetlens 0.11.2 → 0.12.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/app-path-routes-manifest.json +3 -0
- package/app/apps/web/.next/build-manifest.json +3 -3
- package/app/apps/web/.next/prerender-manifest.json +3 -3
- package/app/apps/web/.next/routes-manifest.json +22 -0
- package/app/apps/web/.next/server/app/_global-error.html +1 -1
- package/app/apps/web/.next/server/app/_global-error.rsc +1 -1
- package/app/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/app/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/app/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/app/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- 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.js +2 -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 +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 +2 -2
- 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 +2 -2
- 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 +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 +2 -2
- 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 +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 +1 -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 +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/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/api/pdf/[key]/route/build-manifest.json +9 -0
- package/app/apps/web/.next/server/app/api/pdf/[key]/route/server-reference-manifest.json +4 -0
- package/app/apps/web/.next/server/app/api/pdf/[key]/route.js +10 -0
- package/app/apps/web/.next/server/app/api/pdf/[key]/route.js.map +5 -0
- package/app/apps/web/.next/server/app/api/pdf/[key]/route.js.nft.json +1 -0
- package/app/apps/web/.next/server/app/api/pdf/[key]/route_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/api/runs/[runId]/route.js +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 +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 +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 +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 +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/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/api/workflow-agent/route/build-manifest.json +9 -0
- package/app/apps/web/.next/server/app/api/workflow-agent/route/server-reference-manifest.json +4 -0
- package/app/apps/web/.next/server/app/api/workflow-agent/route.js +7 -0
- package/app/apps/web/.next/server/app/api/workflow-agent/route.js.map +5 -0
- package/app/apps/web/.next/server/app/api/workflow-agent/route.js.nft.json +1 -0
- package/app/apps/web/.next/server/app/api/workflow-agent/route_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/changelog/page.js +2 -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.js +2 -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.js +2 -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.js +2 -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.js +2 -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.js +2 -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.js +2 -1
- 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.js +2 -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.js +2 -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/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/print/[key]/page/build-manifest.json +17 -0
- package/app/apps/web/.next/server/app/print/[key]/page/next-font-manifest.json +6 -0
- package/app/apps/web/.next/server/app/print/[key]/page/react-loadable-manifest.json +1 -0
- package/app/apps/web/.next/server/app/print/[key]/page/server-reference-manifest.json +4 -0
- package/app/apps/web/.next/server/app/print/[key]/page.js +19 -0
- package/app/apps/web/.next/server/app/print/[key]/page.js.map +5 -0
- package/app/apps/web/.next/server/app/print/[key]/page.js.nft.json +1 -0
- package/app/apps/web/.next/server/app/print/[key]/page_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/projects/[slug]/page.js +2 -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.js +2 -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.js +2 -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.js +2 -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.js +2 -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.js +2 -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.js +2 -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.js +2 -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/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0455vu3._.js +2 -2
- package/app/apps/web/.next/server/chunks/{[root-of-the-server]__0_8zh-i._.js → [root-of-the-server]__04j3tng._.js} +2 -2
- package/app/apps/web/.next/server/chunks/{[root-of-the-server]__0jprdks._.js → [root-of-the-server]__0cnh3k4._.js} +2 -2
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0e.f-t.._.js +3 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0kc9e1n._.js +3 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0y5p73y._.js +3 -0
- package/app/apps/web/.next/server/chunks/{[root-of-the-server]__0ej_p3s._.js → [root-of-the-server]__132eosx._.js} +2 -2
- package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_pdf_[key]_route_actions_0intcw9.js +3 -0
- package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_workflow-agent_route_actions_0gxw9tv.js +3 -0
- package/app/apps/web/.next/server/chunks/packages_entries_dist_node_0bckr7-.js +1 -1
- package/app/apps/web/.next/server/chunks/packages_parser_dist_06d9se1._.js +3 -0
- package/app/apps/web/.next/server/chunks/packages_parser_dist_10ihc3~._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__04eq6z2._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__04il6m2._.js +11 -0
- 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]__0n-ax-5._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0o03ymy._.js +2 -2
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0rvzdnx._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0z7mg0b._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0~.f_3z._.js +12 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__136-0me._.js +8 -0
- package/app/apps/web/.next/server/chunks/ssr/_0cgg5zi._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/_0jw2sm7._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/_0kajk31._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/_0w.cv64._.js +8 -0
- package/app/apps/web/.next/server/chunks/ssr/_0xu2pvc._.js +1 -1
- 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__next-internal_server_app_print_[key]_page_actions_0_ygul-.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_01d-iwx._.js +6 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_week-digest_tsx_0c9ha31._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_0k0tl52._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_changelog_ts_0n7_p1d._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_changelog_ts_0nb5_-s._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_07orc4m.js +4 -0
- package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_12.endt._.js +1 -1
- package/app/apps/web/.next/server/edge/chunks/[root-of-the-server]__0.sx~id._.js +11 -0
- package/app/apps/web/.next/server/edge/chunks/node_modules_next_dist_esm_build_templates_edge-wrapper_0p1t1z8.js +3 -0
- package/app/apps/web/.next/server/edge/chunks/turbopack-node_modules_next_dist_esm_build_templates_edge-wrapper_0mw-sqe.js +3 -0
- package/app/apps/web/.next/server/functions-config-manifest.json +4 -1
- package/app/apps/web/.next/server/middleware-build-manifest.js +3 -3
- package/app/apps/web/.next/server/middleware-manifest.json +30 -2
- 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/00xkqnvk4-d1-.js +10 -0
- package/app/apps/web/.next/static/chunks/03_7wmpodz36t.js +1 -0
- package/app/apps/web/.next/static/chunks/0716x58e1_2c5.js +1 -0
- package/app/apps/web/.next/static/chunks/0nnjldasalwdu.js +4 -0
- package/app/apps/web/.next/static/chunks/0okg13phslr1..js +4 -0
- package/app/apps/web/.next/static/chunks/0vf-3rauafbek.js +6 -0
- package/app/apps/web/.next/static/chunks/0vl27-vjob2_9.js +6 -0
- package/app/apps/web/.next/static/chunks/0yo458-7577lr.js +1 -0
- package/app/apps/web/.next/static/chunks/14bjditmmrn7l.js +1 -0
- package/app/apps/web/.next/static/rrY-ephAArv8tjJOXD622/_clientMiddlewareManifest.js +6 -0
- package/app/apps/web/app/api/events/route.ts +50 -2
- package/app/apps/web/app/api/pdf/[key]/route.ts +199 -0
- package/app/apps/web/app/api/workflow-agent/route.ts +27 -0
- package/app/apps/web/app/insights/[key]/page.tsx +4 -1
- package/app/apps/web/app/layout.tsx +23 -1
- package/app/apps/web/app/page.tsx +24 -1
- package/app/apps/web/app/print/[key]/page.tsx +91 -0
- package/app/apps/web/app/projects/[slug]/page.tsx +6 -7
- package/app/apps/web/app/projects/page.tsx +2 -3
- package/app/apps/web/app/sessions/[id]/session-view.tsx +1297 -19
- package/app/apps/web/app/sessions/sessions-grid.tsx +10 -1
- package/app/apps/web/components/dashboard-view.tsx +2 -1
- package/app/apps/web/components/export-pdf-button.tsx +76 -0
- package/app/apps/web/components/month-digest-view.tsx +10 -0
- package/app/apps/web/components/week-digest-view.tsx +10 -0
- package/app/apps/web/lib/changelog-data.generated.ts +1 -1
- package/app/apps/web/lib/entries-index.ts +5 -4
- package/app/apps/web/lib/find-chrome.ts +71 -0
- package/app/apps/web/middleware.ts +22 -0
- package/app/apps/web/package.json +1 -1
- package/app/apps/web/tsconfig.tsbuildinfo +1 -1
- package/dist/daemon-worker.js +1716 -281
- package/dist/index.js +1617 -195
- package/package.json +1 -1
- package/app/apps/web/.next/server/chunks/packages_parser_dist_04rh1zd._.js +0 -3
- package/app/apps/web/.next/server/chunks/packages_parser_dist_0ndsxe6._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0_xpuh7._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0d~2~le._.js +0 -8
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0w52fbc._.js +0 -12
- package/app/apps/web/.next/server/chunks/ssr/_02s1n-x._.js +0 -8
- package/app/apps/web/.next/server/chunks/ssr/_0fjbf--._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0ly1xes._.js +0 -6
- package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_0af94gl._.js +0 -3
- package/app/apps/web/.next/static/chunks/0.3mqbj24kwtc.js +0 -6
- package/app/apps/web/.next/static/chunks/0byz8fqw.exef.js +0 -1
- package/app/apps/web/.next/static/chunks/0l3ck.awv~4t7.js +0 -1
- package/app/apps/web/.next/static/chunks/0lxuac2v0_gdl.js +0 -6
- package/app/apps/web/.next/static/chunks/0m62vx92~0_0d.js +0 -1
- package/app/apps/web/.next/static/chunks/0rtba0saz74e1.js +0 -10
- package/app/apps/web/.next/static/chunks/0s4eyofh28l~u.js +0 -1
- package/app/apps/web/.next/static/chunks/0uev~g~qvbjv9.js +0 -4
- package/app/apps/web/.next/static/m6ibRSdAu8jD10VBA2OFH/_clientMiddlewareManifest.js +0 -1
- /package/app/apps/web/.next/static/{m6ibRSdAu8jD10VBA2OFH → rrY-ephAArv8tjJOXD622}/_buildManifest.js +0 -0
- /package/app/apps/web/.next/static/{m6ibRSdAu8jD10VBA2OFH → rrY-ephAArv8tjJOXD622}/_ssgManifest.js +0 -0
package/dist/index.js
CHANGED
|
@@ -92,6 +92,16 @@ function findConductorWorkspace(projectName) {
|
|
|
92
92
|
const canonicalEndIdx = m.index + m[0].length - workspaceName.length - 1 - trailingSlash;
|
|
93
93
|
return { canonicalEndIdx, workspaceName };
|
|
94
94
|
}
|
|
95
|
+
function findSupersetWorkspace(projectName) {
|
|
96
|
+
const idx = projectName.indexOf(SUPERSET_MARKER);
|
|
97
|
+
if (idx < 0)
|
|
98
|
+
return null;
|
|
99
|
+
const segs = projectName.slice(idx + SUPERSET_MARKER.length).split("/").filter(Boolean);
|
|
100
|
+
if (segs.length === 0)
|
|
101
|
+
return null;
|
|
102
|
+
const workspaceName = UUID_SEG_RE.test(segs[0]) ? segs[1] ?? segs[0] : segs[0];
|
|
103
|
+
return { canonical: projectName.slice(0, idx) + SUPERSET_MARKER + workspaceName, workspaceName };
|
|
104
|
+
}
|
|
95
105
|
function canonicalProjectName(projectName) {
|
|
96
106
|
const normalized = projectName.replace(/\/{2,}/g, "/");
|
|
97
107
|
const wt = findWorktreeMarker(normalized);
|
|
@@ -100,6 +110,9 @@ function canonicalProjectName(projectName) {
|
|
|
100
110
|
const cd = findConductorWorkspace(normalized);
|
|
101
111
|
if (cd)
|
|
102
112
|
return normalized.slice(0, cd.canonicalEndIdx);
|
|
113
|
+
const ss = findSupersetWorkspace(normalized);
|
|
114
|
+
if (ss)
|
|
115
|
+
return ss.canonical;
|
|
103
116
|
return normalized;
|
|
104
117
|
}
|
|
105
118
|
function worktreeName(projectName) {
|
|
@@ -113,8 +126,16 @@ function worktreeName(projectName) {
|
|
|
113
126
|
const cd = findConductorWorkspace(normalized);
|
|
114
127
|
if (cd)
|
|
115
128
|
return cd.workspaceName;
|
|
129
|
+
const ss = findSupersetWorkspace(normalized);
|
|
130
|
+
if (ss)
|
|
131
|
+
return ss.workspaceName;
|
|
116
132
|
return null;
|
|
117
133
|
}
|
|
134
|
+
function projectRepoName(projectName) {
|
|
135
|
+
const canonical = canonicalProjectName(projectName);
|
|
136
|
+
const segs = canonical.replace(/\/+$/, "").split("/").filter(Boolean);
|
|
137
|
+
return segs[segs.length - 1] || canonical;
|
|
138
|
+
}
|
|
118
139
|
function makeDay(date) {
|
|
119
140
|
return {
|
|
120
141
|
date,
|
|
@@ -155,7 +176,19 @@ function dailyActivity(sessions) {
|
|
|
155
176
|
};
|
|
156
177
|
for (const s of sessions) {
|
|
157
178
|
const startDay = sessionDay(s);
|
|
158
|
-
if (
|
|
179
|
+
if (s.dailyBreakdown && s.dailyBreakdown.length > 0) {
|
|
180
|
+
for (const d of s.dailyBreakdown) {
|
|
181
|
+
const bucket = touchBucket(d.day);
|
|
182
|
+
bucket.toolCalls += d.toolCalls;
|
|
183
|
+
bucket.turns += d.turns;
|
|
184
|
+
bucket.tokens.input += d.tokens.input;
|
|
185
|
+
bucket.tokens.output += d.tokens.output;
|
|
186
|
+
bucket.tokens.cacheRead += d.tokens.cacheRead;
|
|
187
|
+
bucket.tokens.cacheWrite += d.tokens.cacheWrite;
|
|
188
|
+
}
|
|
189
|
+
if (startDay)
|
|
190
|
+
touchBucket(startDay).durationMs += s.durationMs ?? 0;
|
|
191
|
+
} else if (startDay) {
|
|
159
192
|
const bucket = touchBucket(startDay);
|
|
160
193
|
bucket.toolCalls += s.toolCallCount ?? 0;
|
|
161
194
|
bucket.turns += s.turnCount ?? 0;
|
|
@@ -165,31 +198,30 @@ function dailyActivity(sessions) {
|
|
|
165
198
|
bucket.tokens.cacheWrite += s.totalUsage.cacheWrite;
|
|
166
199
|
bucket.durationMs += s.durationMs ?? 0;
|
|
167
200
|
}
|
|
201
|
+
const presenceDays = /* @__PURE__ */ new Set();
|
|
168
202
|
const segments = s.activeSegments;
|
|
169
203
|
if (segments && segments.length > 0) {
|
|
170
|
-
const touchedDays = /* @__PURE__ */ new Set();
|
|
171
204
|
for (const seg of segments) {
|
|
172
205
|
let cur = seg.startMs;
|
|
173
206
|
while (cur < seg.endMs) {
|
|
174
207
|
const day2 = toLocalDay(cur);
|
|
175
|
-
|
|
208
|
+
presenceDays.add(day2);
|
|
176
209
|
const d = new Date(cur);
|
|
177
210
|
d.setHours(24, 0, 0, 0);
|
|
178
211
|
const dayEndMs = Math.min(d.getTime(), seg.endMs);
|
|
179
|
-
|
|
180
|
-
bucket.airTimeMs += dayEndMs - cur;
|
|
212
|
+
touchBucket(day2).airTimeMs += dayEndMs - cur;
|
|
181
213
|
cur = dayEndMs;
|
|
182
214
|
}
|
|
183
215
|
}
|
|
184
|
-
for (const day2 of touchedDays) {
|
|
185
|
-
const bucket = touchBucket(day2);
|
|
186
|
-
bucket.sessions++;
|
|
187
|
-
}
|
|
188
216
|
} else if (startDay) {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
bucket.airTimeMs += s.airTimeMs ?? 0;
|
|
217
|
+
presenceDays.add(startDay);
|
|
218
|
+
touchBucket(startDay).airTimeMs += s.airTimeMs ?? 0;
|
|
192
219
|
}
|
|
220
|
+
if (s.dailyBreakdown)
|
|
221
|
+
for (const d of s.dailyBreakdown)
|
|
222
|
+
presenceDays.add(d.day);
|
|
223
|
+
for (const day2 of presenceDays)
|
|
224
|
+
touchBucket(day2).sessions++;
|
|
193
225
|
}
|
|
194
226
|
const range = minDay && maxDay ? daysBetween(minDay, maxDay) : [];
|
|
195
227
|
const out = [];
|
|
@@ -534,13 +566,13 @@ function summarizeBursts(bursts) {
|
|
|
534
566
|
function groupByProject(sessions) {
|
|
535
567
|
const map = /* @__PURE__ */ new Map();
|
|
536
568
|
for (const s of sessions) {
|
|
537
|
-
const
|
|
538
|
-
const key =
|
|
569
|
+
const repo = projectRepoName(s.projectName);
|
|
570
|
+
const key = repo;
|
|
539
571
|
let cur = map.get(key);
|
|
540
572
|
if (!cur) {
|
|
541
573
|
cur = {
|
|
542
|
-
projectDir:
|
|
543
|
-
projectName:
|
|
574
|
+
projectDir: repo,
|
|
575
|
+
projectName: repo,
|
|
544
576
|
sessions: [],
|
|
545
577
|
rawProjectDirs: [],
|
|
546
578
|
worktreeCount: 0,
|
|
@@ -582,7 +614,7 @@ function groupByProject(sessions) {
|
|
|
582
614
|
}
|
|
583
615
|
return Array.from(map.values()).sort((a, b) => (b.lastActiveMs ?? 0) - (a.lastActiveMs ?? 0));
|
|
584
616
|
}
|
|
585
|
-
var BLANK_USAGE, WORKTREE_MARKERS, CONDUCTOR_RE, PR_CREATE_RE, PR_NUMBER_RE, TITLE_FLAG_RE;
|
|
617
|
+
var BLANK_USAGE, WORKTREE_MARKERS, CONDUCTOR_RE, SUPERSET_MARKER, UUID_SEG_RE, PR_CREATE_RE, PR_NUMBER_RE, TITLE_FLAG_RE;
|
|
586
618
|
var init_analytics = __esm({
|
|
587
619
|
"../parser/dist/analytics.js"() {
|
|
588
620
|
"use strict";
|
|
@@ -593,6 +625,8 @@ var init_analytics = __esm({
|
|
|
593
625
|
"/claude/worktrees/"
|
|
594
626
|
];
|
|
595
627
|
CONDUCTOR_RE = /\/conductor\/workspaces\/[^/]+\/([^/]+)(?:\/|$)/;
|
|
628
|
+
SUPERSET_MARKER = "/.superset/worktrees/";
|
|
629
|
+
UUID_SEG_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
596
630
|
PR_CREATE_RE = /gh\s+pr\s+create\b/i;
|
|
597
631
|
PR_NUMBER_RE = /#(\d+)/;
|
|
598
632
|
TITLE_FLAG_RE = /--title\s+["']([^"']+)["']/;
|
|
@@ -606,7 +640,7 @@ function getAgentMetadata(kind) {
|
|
|
606
640
|
function isAgentKind(s) {
|
|
607
641
|
return typeof s === "string" && KNOWN_AGENT_KINDS.has(s);
|
|
608
642
|
}
|
|
609
|
-
var CLAUDE_CODE_METADATA, CODEX_METADATA, GEMINI_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
|
|
643
|
+
var CLAUDE_CODE_METADATA, CODEX_METADATA, GEMINI_METADATA, ANTIGRAVITY_METADATA, COWORK_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
|
|
610
644
|
var init_agent_metadata = __esm({
|
|
611
645
|
"../parser/dist/agent-metadata.js"() {
|
|
612
646
|
"use strict";
|
|
@@ -631,10 +665,26 @@ var init_agent_metadata = __esm({
|
|
|
631
665
|
accentColor: "rgb(124, 92, 246)",
|
|
632
666
|
iconChar: "\u273A"
|
|
633
667
|
};
|
|
668
|
+
ANTIGRAVITY_METADATA = {
|
|
669
|
+
kind: "antigravity",
|
|
670
|
+
displayName: "Antigravity",
|
|
671
|
+
shortLabel: "Agy",
|
|
672
|
+
accentColor: "rgb(236, 72, 153)",
|
|
673
|
+
iconChar: "\u23C3"
|
|
674
|
+
};
|
|
675
|
+
COWORK_METADATA = {
|
|
676
|
+
kind: "cowork",
|
|
677
|
+
displayName: "Cowork",
|
|
678
|
+
shortLabel: "Cowork",
|
|
679
|
+
accentColor: "rgb(217, 119, 87)",
|
|
680
|
+
iconChar: "\u2318"
|
|
681
|
+
};
|
|
634
682
|
agentMetadata = [
|
|
635
683
|
CLAUDE_CODE_METADATA,
|
|
636
684
|
CODEX_METADATA,
|
|
637
|
-
GEMINI_METADATA
|
|
685
|
+
GEMINI_METADATA,
|
|
686
|
+
ANTIGRAVITY_METADATA,
|
|
687
|
+
COWORK_METADATA
|
|
638
688
|
];
|
|
639
689
|
KNOWN_AGENT_KINDS = new Set(agentMetadata.map((m) => m.kind));
|
|
640
690
|
}
|
|
@@ -1216,9 +1266,31 @@ function parseTranscript(rawLines) {
|
|
|
1216
1266
|
let linesAdded = 0;
|
|
1217
1267
|
let linesRemoved = 0;
|
|
1218
1268
|
const filesEdited = /* @__PURE__ */ new Set();
|
|
1269
|
+
const perDay = /* @__PURE__ */ new Map();
|
|
1270
|
+
const fallbackDay = startMs !== void 0 ? toLocalDay(startMs) : void 0;
|
|
1271
|
+
const dayBucket = (ts) => {
|
|
1272
|
+
let day2;
|
|
1273
|
+
if (ts) {
|
|
1274
|
+
const ms = Date.parse(ts);
|
|
1275
|
+
if (!Number.isNaN(ms))
|
|
1276
|
+
day2 = toLocalDay(ms);
|
|
1277
|
+
}
|
|
1278
|
+
day2 = day2 ?? fallbackDay;
|
|
1279
|
+
if (!day2)
|
|
1280
|
+
return void 0;
|
|
1281
|
+
let b = perDay.get(day2);
|
|
1282
|
+
if (!b) {
|
|
1283
|
+
b = { toolCalls: 0, turns: 0, tokens: { ...BLANK_USAGE2 } };
|
|
1284
|
+
perDay.set(day2, b);
|
|
1285
|
+
}
|
|
1286
|
+
return b;
|
|
1287
|
+
};
|
|
1219
1288
|
for (const e of events) {
|
|
1220
1289
|
if (e.role === "tool-call") {
|
|
1221
1290
|
toolCallCount++;
|
|
1291
|
+
const tcDay = dayBucket(e.timestamp);
|
|
1292
|
+
if (tcDay)
|
|
1293
|
+
tcDay.toolCalls++;
|
|
1222
1294
|
const toolBlock = e.blocks.find((b) => b && b.type === "tool_use");
|
|
1223
1295
|
if (toolBlock) {
|
|
1224
1296
|
const input = toolBlock.input ?? {};
|
|
@@ -1255,6 +1327,9 @@ function parseTranscript(rawLines) {
|
|
|
1255
1327
|
firstUserPreview = e.teammateMessage ? e.teammateMessage.body : e.preview;
|
|
1256
1328
|
}
|
|
1257
1329
|
turnCount++;
|
|
1330
|
+
const turnDay = dayBucket(e.timestamp);
|
|
1331
|
+
if (turnDay)
|
|
1332
|
+
turnDay.turns++;
|
|
1258
1333
|
lastUserPreview = e.preview;
|
|
1259
1334
|
}
|
|
1260
1335
|
}
|
|
@@ -1296,6 +1371,14 @@ function parseTranscript(rawLines) {
|
|
|
1296
1371
|
totalUsage.output += u.output;
|
|
1297
1372
|
totalUsage.cacheRead += u.cacheRead;
|
|
1298
1373
|
totalUsage.cacheWrite += u.cacheWrite;
|
|
1374
|
+
const ts = typeof o.timestamp === "string" ? o.timestamp : void 0;
|
|
1375
|
+
const b = dayBucket(ts);
|
|
1376
|
+
if (b) {
|
|
1377
|
+
b.tokens.input += u.input;
|
|
1378
|
+
b.tokens.output += u.output;
|
|
1379
|
+
b.tokens.cacheRead += u.cacheRead;
|
|
1380
|
+
b.tokens.cacheWrite += u.cacheWrite;
|
|
1381
|
+
}
|
|
1299
1382
|
}
|
|
1300
1383
|
}
|
|
1301
1384
|
}
|
|
@@ -1319,6 +1402,7 @@ function parseTranscript(rawLines) {
|
|
|
1319
1402
|
lastAgentPreview,
|
|
1320
1403
|
toolCallCount,
|
|
1321
1404
|
turnCount,
|
|
1405
|
+
dailyBreakdown: Array.from(perDay.entries()).map(([day2, v]) => ({ day: day2, toolCalls: v.toolCalls, turns: v.turns, tokens: v.tokens })).sort((a, b) => a.day.localeCompare(b.day)),
|
|
1322
1406
|
airTimeMs,
|
|
1323
1407
|
activeSegments,
|
|
1324
1408
|
linesAdded,
|
|
@@ -1337,6 +1421,7 @@ var init_parser = __esm({
|
|
|
1337
1421
|
"../parser/dist/parser.js"() {
|
|
1338
1422
|
"use strict";
|
|
1339
1423
|
init_user_input();
|
|
1424
|
+
init_analytics();
|
|
1340
1425
|
BLANK_USAGE2 = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
1341
1426
|
TEAMMATE_MSG_RE = /^\s*<teammate-message\s+teammate_id="([^"]+)"[^>]*>([\s\S]*?)<\/teammate-message>/;
|
|
1342
1427
|
}
|
|
@@ -1610,7 +1695,7 @@ async function loadCalibrationEvents(root = DEFAULT_ROOT) {
|
|
|
1610
1695
|
out.sort((a, b) => a.ts.localeCompare(b.ts));
|
|
1611
1696
|
return out;
|
|
1612
1697
|
}
|
|
1613
|
-
function aggregateUsageFromLines(lines, seenKeys, usage2) {
|
|
1698
|
+
function aggregateUsageFromLines(lines, seenKeys, usage2, perDay, fallbackDay) {
|
|
1614
1699
|
for (const raw of lines) {
|
|
1615
1700
|
if (!raw || typeof raw !== "object")
|
|
1616
1701
|
continue;
|
|
@@ -1630,35 +1715,131 @@ function aggregateUsageFromLines(lines, seenKeys, usage2) {
|
|
|
1630
1715
|
const u = m.usage;
|
|
1631
1716
|
if (u) {
|
|
1632
1717
|
const toNum = (v) => typeof v === "number" ? v : 0;
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1718
|
+
const inp = toNum(u.input_tokens);
|
|
1719
|
+
const out = toNum(u.output_tokens);
|
|
1720
|
+
const cr = toNum(u.cache_read_input_tokens);
|
|
1721
|
+
const cw = toNum(u.cache_creation_input_tokens);
|
|
1722
|
+
usage2.input += inp;
|
|
1723
|
+
usage2.output += out;
|
|
1724
|
+
usage2.cacheRead += cr;
|
|
1725
|
+
usage2.cacheWrite += cw;
|
|
1726
|
+
if (perDay) {
|
|
1727
|
+
let day2;
|
|
1728
|
+
const ts = typeof r.timestamp === "string" ? r.timestamp : void 0;
|
|
1729
|
+
if (ts) {
|
|
1730
|
+
const ms = Date.parse(ts);
|
|
1731
|
+
if (!Number.isNaN(ms))
|
|
1732
|
+
day2 = toLocalDay(ms);
|
|
1733
|
+
}
|
|
1734
|
+
day2 = day2 ?? fallbackDay;
|
|
1735
|
+
if (day2) {
|
|
1736
|
+
let d = perDay.get(day2);
|
|
1737
|
+
if (!d) {
|
|
1738
|
+
d = { ...BLANK_USAGE3 };
|
|
1739
|
+
perDay.set(day2, d);
|
|
1740
|
+
}
|
|
1741
|
+
d.input += inp;
|
|
1742
|
+
d.output += out;
|
|
1743
|
+
d.cacheRead += cr;
|
|
1744
|
+
d.cacheWrite += cw;
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1637
1747
|
}
|
|
1638
1748
|
}
|
|
1639
1749
|
}
|
|
1640
|
-
async function computeSessionUsageWithSubagents(parentLines, projectDirPath, sessionId) {
|
|
1750
|
+
async function computeSessionUsageWithSubagents(parentLines, projectDirPath, sessionId, fallbackDay) {
|
|
1641
1751
|
const usage2 = { ...BLANK_USAGE3 };
|
|
1642
1752
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
1643
|
-
|
|
1753
|
+
const perDay = /* @__PURE__ */ new Map();
|
|
1754
|
+
aggregateUsageFromLines(parentLines, seenKeys, usage2, perDay, fallbackDay);
|
|
1644
1755
|
const subagentsDir = path.join(projectDirPath, sessionId, "subagents");
|
|
1645
1756
|
let entries2;
|
|
1646
1757
|
try {
|
|
1647
1758
|
entries2 = await fs.readdir(subagentsDir);
|
|
1648
1759
|
} catch {
|
|
1649
|
-
return usage2;
|
|
1760
|
+
return { usage: usage2, perDay };
|
|
1650
1761
|
}
|
|
1651
1762
|
const jsonlFiles = entries2.filter((f) => f.endsWith(".jsonl"));
|
|
1652
1763
|
if (jsonlFiles.length === 0)
|
|
1653
|
-
return usage2;
|
|
1764
|
+
return { usage: usage2, perDay };
|
|
1654
1765
|
await Promise.all(jsonlFiles.map(async (f) => {
|
|
1655
1766
|
try {
|
|
1656
1767
|
const lines = await readJsonlFile(path.join(subagentsDir, f));
|
|
1657
|
-
aggregateUsageFromLines(lines, seenKeys, usage2);
|
|
1768
|
+
aggregateUsageFromLines(lines, seenKeys, usage2, perDay, fallbackDay);
|
|
1658
1769
|
} catch {
|
|
1659
1770
|
}
|
|
1660
1771
|
}));
|
|
1661
|
-
return usage2;
|
|
1772
|
+
return { usage: usage2, perDay };
|
|
1773
|
+
}
|
|
1774
|
+
function mergeDailyTokens(base, perDayTokens, totalUsage) {
|
|
1775
|
+
const counts = new Map((base ?? []).map((d) => [d.day, d]));
|
|
1776
|
+
const days = /* @__PURE__ */ new Set([...counts.keys(), ...perDayTokens.keys()]);
|
|
1777
|
+
const out = [...days].sort((a, b) => a.localeCompare(b)).map((day2) => ({
|
|
1778
|
+
day: day2,
|
|
1779
|
+
toolCalls: counts.get(day2)?.toolCalls ?? 0,
|
|
1780
|
+
turns: counts.get(day2)?.turns ?? 0,
|
|
1781
|
+
tokens: { ...perDayTokens.get(day2) ?? BLANK_USAGE3 }
|
|
1782
|
+
}));
|
|
1783
|
+
if (out.length > 0) {
|
|
1784
|
+
const summed = out.reduce((a, r) => ({
|
|
1785
|
+
input: a.input + r.tokens.input,
|
|
1786
|
+
output: a.output + r.tokens.output,
|
|
1787
|
+
cacheRead: a.cacheRead + r.tokens.cacheRead,
|
|
1788
|
+
cacheWrite: a.cacheWrite + r.tokens.cacheWrite
|
|
1789
|
+
}), { ...BLANK_USAGE3 });
|
|
1790
|
+
const first = out[0].tokens;
|
|
1791
|
+
first.input += totalUsage.input - summed.input;
|
|
1792
|
+
first.output += totalUsage.output - summed.output;
|
|
1793
|
+
first.cacheRead += totalUsage.cacheRead - summed.cacheRead;
|
|
1794
|
+
first.cacheWrite += totalUsage.cacheWrite - summed.cacheWrite;
|
|
1795
|
+
}
|
|
1796
|
+
return out;
|
|
1797
|
+
}
|
|
1798
|
+
async function scanWorkflowAggregate(projectDirPath, sessionId) {
|
|
1799
|
+
const dir = path.join(projectDirPath, sessionId, "workflows");
|
|
1800
|
+
let entries2;
|
|
1801
|
+
try {
|
|
1802
|
+
entries2 = await fs.readdir(dir);
|
|
1803
|
+
} catch {
|
|
1804
|
+
return { workflowCount: 0, spawnedAgentCount: 0, spans: [] };
|
|
1805
|
+
}
|
|
1806
|
+
const jsonFiles = entries2.filter((f) => f.startsWith("wf_") && f.endsWith(".json"));
|
|
1807
|
+
if (jsonFiles.length === 0)
|
|
1808
|
+
return { workflowCount: 0, spawnedAgentCount: 0, spans: [] };
|
|
1809
|
+
let spawnedAgentCount = 0;
|
|
1810
|
+
const spans = [];
|
|
1811
|
+
const parsed = await Promise.all(jsonFiles.map(async (f) => {
|
|
1812
|
+
try {
|
|
1813
|
+
const j = JSON.parse(await fs.readFile(path.join(dir, f), "utf8"));
|
|
1814
|
+
if (typeof j.agentCount === "number")
|
|
1815
|
+
spawnedAgentCount += j.agentCount;
|
|
1816
|
+
if (typeof j.startTime === "number" && typeof j.durationMs === "number" && j.durationMs > 0) {
|
|
1817
|
+
spans.push({ startMs: j.startTime, endMs: j.startTime + j.durationMs });
|
|
1818
|
+
}
|
|
1819
|
+
return true;
|
|
1820
|
+
} catch {
|
|
1821
|
+
return false;
|
|
1822
|
+
}
|
|
1823
|
+
}));
|
|
1824
|
+
return { workflowCount: parsed.filter(Boolean).length, spawnedAgentCount, spans };
|
|
1825
|
+
}
|
|
1826
|
+
function foldWorkflowAgentTime(activeSegments, spans) {
|
|
1827
|
+
if (spans.length === 0)
|
|
1828
|
+
return {};
|
|
1829
|
+
const all = [...activeSegments ?? [], ...spans].filter((s) => s.endMs > s.startMs).sort((a, b) => a.startMs - b.startMs);
|
|
1830
|
+
if (all.length === 0)
|
|
1831
|
+
return {};
|
|
1832
|
+
const merged = [{ ...all[0] }];
|
|
1833
|
+
for (let i = 1; i < all.length; i++) {
|
|
1834
|
+
const cur = all[i];
|
|
1835
|
+
const last = merged[merged.length - 1];
|
|
1836
|
+
if (cur.startMs <= last.endMs)
|
|
1837
|
+
last.endMs = Math.max(last.endMs, cur.endMs);
|
|
1838
|
+
else
|
|
1839
|
+
merged.push({ ...cur });
|
|
1840
|
+
}
|
|
1841
|
+
const airTimeMs = merged.reduce((n, s) => n + (s.endMs - s.startMs), 0);
|
|
1842
|
+
return { activeSegments: merged, airTimeMs };
|
|
1662
1843
|
}
|
|
1663
1844
|
async function getCachedMeta(f) {
|
|
1664
1845
|
const cached = metaCache.get(f.fullPath);
|
|
@@ -1670,13 +1851,19 @@ async function getCachedMeta(f) {
|
|
|
1670
1851
|
const { meta } = parseTranscript(rawLines);
|
|
1671
1852
|
const sessionId = sessionIdFromFileName(f.fileName);
|
|
1672
1853
|
const projectDirPath = path.dirname(f.fullPath);
|
|
1673
|
-
meta.
|
|
1854
|
+
const fallbackDay = meta.firstTimestamp ? toLocalDay(Date.parse(meta.firstTimestamp)) : void 0;
|
|
1855
|
+
const { usage: usage2, perDay: perDayTokens } = await computeSessionUsageWithSubagents(rawLines, projectDirPath, sessionId, fallbackDay);
|
|
1856
|
+
meta.totalUsage = usage2;
|
|
1857
|
+
meta.dailyBreakdown = mergeDailyTokens(meta.dailyBreakdown, perDayTokens, usage2);
|
|
1858
|
+
const wf = await scanWorkflowAggregate(projectDirPath, sessionId);
|
|
1674
1859
|
const full = {
|
|
1675
1860
|
...meta,
|
|
1676
1861
|
id: sessionId,
|
|
1677
1862
|
filePath: f.fullPath,
|
|
1678
1863
|
projectDir: f.projectDir,
|
|
1679
|
-
projectName: meta.cwd ?? decodeProjectName(f.projectDir)
|
|
1864
|
+
projectName: meta.cwd ?? decodeProjectName(f.projectDir),
|
|
1865
|
+
...wf.workflowCount > 0 ? { workflowCount: wf.workflowCount, spawnedAgentCount: wf.spawnedAgentCount } : {},
|
|
1866
|
+
...foldWorkflowAgentTime(meta.activeSegments, wf.spans)
|
|
1680
1867
|
};
|
|
1681
1868
|
metaCache.set(f.fullPath, { meta: full, mtimeMs: f.mtimeMs, sizeBytes: f.sizeBytes });
|
|
1682
1869
|
return full;
|
|
@@ -1692,13 +1879,17 @@ async function getCachedDetail(f) {
|
|
|
1692
1879
|
try {
|
|
1693
1880
|
const rawLines = await readJsonlFile(f.fullPath);
|
|
1694
1881
|
const { meta, events } = parseTranscript(rawLines);
|
|
1882
|
+
const sessionId = sessionIdFromFileName(f.fileName);
|
|
1883
|
+
const wf = await scanWorkflowAggregate(path.dirname(f.fullPath), sessionId);
|
|
1695
1884
|
const detail = {
|
|
1696
1885
|
...meta,
|
|
1697
|
-
id:
|
|
1886
|
+
id: sessionId,
|
|
1698
1887
|
filePath: f.fullPath,
|
|
1699
1888
|
projectDir: f.projectDir,
|
|
1700
1889
|
projectName: meta.cwd ?? decodeProjectName(f.projectDir),
|
|
1701
|
-
events
|
|
1890
|
+
events,
|
|
1891
|
+
...wf.workflowCount > 0 ? { workflowCount: wf.workflowCount, spawnedAgentCount: wf.spawnedAgentCount } : {},
|
|
1892
|
+
...foldWorkflowAgentTime(meta.activeSegments, wf.spans)
|
|
1702
1893
|
};
|
|
1703
1894
|
detailCache.set(f.fullPath, { detail, mtimeMs: f.mtimeMs, sizeBytes: f.sizeBytes });
|
|
1704
1895
|
const metaOnly = { ...detail };
|
|
@@ -1730,8 +1921,18 @@ async function getSession(id, opts = {}) {
|
|
|
1730
1921
|
return detail;
|
|
1731
1922
|
const sessionStartMs = detail.firstTimestamp ? Date.parse(detail.firstTimestamp) : void 0;
|
|
1732
1923
|
const subagentsDir = path.join(path.dirname(hit.fullPath), sessionIdFromFileName(hit.fileName), "subagents");
|
|
1733
|
-
const
|
|
1734
|
-
|
|
1924
|
+
const workflowsDir = path.join(path.dirname(hit.fullPath), sessionIdFromFileName(hit.fileName), "workflows");
|
|
1925
|
+
const [subagents, workflows] = await Promise.all([
|
|
1926
|
+
loadSubagents(subagentsDir, sessionStartMs, detail.events),
|
|
1927
|
+
loadWorkflows(workflowsDir, sessionStartMs, detail.events)
|
|
1928
|
+
]);
|
|
1929
|
+
const spawnedAgentCount = workflows.reduce((n, w) => n + w.agentCount, 0);
|
|
1930
|
+
return {
|
|
1931
|
+
...detail,
|
|
1932
|
+
subagents,
|
|
1933
|
+
workflows,
|
|
1934
|
+
...workflows.length > 0 ? { workflowCount: workflows.length, spawnedAgentCount } : {}
|
|
1935
|
+
};
|
|
1735
1936
|
}
|
|
1736
1937
|
function summarizeSubagentLines(lines) {
|
|
1737
1938
|
let startMs;
|
|
@@ -1921,6 +2122,248 @@ async function loadSubagents(dir, sessionStartMs, parentEvents) {
|
|
|
1921
2122
|
}));
|
|
1922
2123
|
return runs2.filter((r) => r !== null).sort((a, b) => (a.startMs ?? 0) - (b.startMs ?? 0));
|
|
1923
2124
|
}
|
|
2125
|
+
async function loadWorkflows(dir, sessionStartMs, parentEvents) {
|
|
2126
|
+
let entries2;
|
|
2127
|
+
try {
|
|
2128
|
+
entries2 = await fs.readdir(dir);
|
|
2129
|
+
} catch {
|
|
2130
|
+
return [];
|
|
2131
|
+
}
|
|
2132
|
+
const jsonFiles = entries2.filter((f) => f.startsWith("wf_") && f.endsWith(".json"));
|
|
2133
|
+
if (jsonFiles.length === 0)
|
|
2134
|
+
return [];
|
|
2135
|
+
const dispatches = [];
|
|
2136
|
+
for (const e of parentEvents) {
|
|
2137
|
+
if (e.role !== "tool-call" || e.toolName !== "Workflow")
|
|
2138
|
+
continue;
|
|
2139
|
+
const tsMs = e.timestamp ? Date.parse(e.timestamp) : NaN;
|
|
2140
|
+
if (Number.isNaN(tsMs))
|
|
2141
|
+
continue;
|
|
2142
|
+
for (const b of e.blocks) {
|
|
2143
|
+
if (b?.type !== "tool_use" || b.name !== "Workflow")
|
|
2144
|
+
continue;
|
|
2145
|
+
dispatches.push({ toolUseId: b.id, parentUuid: e.uuid ?? "", tsMs });
|
|
2146
|
+
}
|
|
2147
|
+
}
|
|
2148
|
+
dispatches.sort((a, b) => a.tsMs - b.tsMs);
|
|
2149
|
+
const matchDispatch = (startMs) => {
|
|
2150
|
+
if (startMs === void 0 || dispatches.length === 0)
|
|
2151
|
+
return void 0;
|
|
2152
|
+
const TOLERANCE_MS = 6e4;
|
|
2153
|
+
let before;
|
|
2154
|
+
let beforeDelta = Infinity;
|
|
2155
|
+
let nearest;
|
|
2156
|
+
let nearestDelta = Infinity;
|
|
2157
|
+
for (const d of dispatches) {
|
|
2158
|
+
const delta = Math.abs(startMs - d.tsMs);
|
|
2159
|
+
if (delta > TOLERANCE_MS)
|
|
2160
|
+
continue;
|
|
2161
|
+
if (delta < nearestDelta) {
|
|
2162
|
+
nearest = d;
|
|
2163
|
+
nearestDelta = delta;
|
|
2164
|
+
}
|
|
2165
|
+
if (d.tsMs <= startMs && delta < beforeDelta) {
|
|
2166
|
+
before = d;
|
|
2167
|
+
beforeDelta = delta;
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
return before ?? nearest;
|
|
2171
|
+
};
|
|
2172
|
+
const num2 = (v) => typeof v === "number" ? v : void 0;
|
|
2173
|
+
const str = (v) => typeof v === "string" && v.length > 0 ? v : void 0;
|
|
2174
|
+
const runs2 = await Promise.all(jsonFiles.map(async (f) => {
|
|
2175
|
+
let j;
|
|
2176
|
+
try {
|
|
2177
|
+
j = JSON.parse(await fs.readFile(path.join(dir, f), "utf8"));
|
|
2178
|
+
} catch {
|
|
2179
|
+
return null;
|
|
2180
|
+
}
|
|
2181
|
+
const runId = str(j.runId) ?? f.replace(/\.json$/, "");
|
|
2182
|
+
const startMs = num2(j.startTime);
|
|
2183
|
+
const durationMs = num2(j.durationMs);
|
|
2184
|
+
const endMs = startMs !== void 0 && durationMs !== void 0 ? startMs + durationMs : void 0;
|
|
2185
|
+
const startTOffsetMs = sessionStartMs !== void 0 && startMs !== void 0 ? Math.max(0, startMs - sessionStartMs) : void 0;
|
|
2186
|
+
const endTOffsetMs = sessionStartMs !== void 0 && endMs !== void 0 ? Math.max(0, endMs - sessionStartMs) : void 0;
|
|
2187
|
+
const phases = Array.isArray(j.phases) ? j.phases.filter((p) => !!p && typeof p === "object" && typeof p.title === "string").map((p) => ({ title: p.title, detail: str(p.detail) })) : [];
|
|
2188
|
+
const logs = Array.isArray(j.logs) ? j.logs.filter((l) => typeof l === "string") : [];
|
|
2189
|
+
const cap = (v, n) => {
|
|
2190
|
+
const s = str(v);
|
|
2191
|
+
return s === void 0 ? void 0 : s.length > n ? s.slice(0, n) + "\u2026" : s;
|
|
2192
|
+
};
|
|
2193
|
+
const progress = Array.isArray(j.workflowProgress) ? j.workflowProgress : [];
|
|
2194
|
+
const agents = progress.filter((e) => !!e && typeof e === "object" && e.type === "workflow_agent").map((e) => ({
|
|
2195
|
+
index: num2(e.index) ?? 0,
|
|
2196
|
+
label: str(e.label) ?? "(agent)",
|
|
2197
|
+
phaseIndex: num2(e.phaseIndex),
|
|
2198
|
+
phaseTitle: str(e.phaseTitle),
|
|
2199
|
+
agentId: str(e.agentId),
|
|
2200
|
+
model: str(e.model),
|
|
2201
|
+
state: str(e.state),
|
|
2202
|
+
startedAt: num2(e.startedAt),
|
|
2203
|
+
durationMs: num2(e.durationMs),
|
|
2204
|
+
tokens: num2(e.tokens),
|
|
2205
|
+
toolCalls: num2(e.toolCalls),
|
|
2206
|
+
lastToolSummary: cap(e.lastToolSummary, 200),
|
|
2207
|
+
promptPreview: cap(e.promptPreview, 600),
|
|
2208
|
+
resultPreview: cap(e.resultPreview, 600)
|
|
2209
|
+
})).sort((a, b) => a.index - b.index);
|
|
2210
|
+
const parent = matchDispatch(startMs);
|
|
2211
|
+
return {
|
|
2212
|
+
runId,
|
|
2213
|
+
name: str(j.workflowName) ?? runId,
|
|
2214
|
+
description: str(j.summary),
|
|
2215
|
+
status: str(j.status) ?? "unknown",
|
|
2216
|
+
agentCount: num2(j.agentCount) ?? 0,
|
|
2217
|
+
toolCallCount: num2(j.totalToolCalls) ?? 0,
|
|
2218
|
+
totalTokens: num2(j.totalTokens) ?? 0,
|
|
2219
|
+
durationMs,
|
|
2220
|
+
startMs,
|
|
2221
|
+
endMs,
|
|
2222
|
+
startTOffsetMs,
|
|
2223
|
+
endTOffsetMs,
|
|
2224
|
+
model: str(j.defaultModel),
|
|
2225
|
+
phases,
|
|
2226
|
+
logs,
|
|
2227
|
+
agents,
|
|
2228
|
+
parentToolUseId: parent?.toolUseId,
|
|
2229
|
+
parentUuid: parent?.parentUuid
|
|
2230
|
+
};
|
|
2231
|
+
}));
|
|
2232
|
+
return runs2.filter((r) => r !== null).sort((a, b) => (a.startMs ?? 0) - (b.startMs ?? 0));
|
|
2233
|
+
}
|
|
2234
|
+
function salientToolInput(input) {
|
|
2235
|
+
if (!input || typeof input !== "object")
|
|
2236
|
+
return "";
|
|
2237
|
+
const o = input;
|
|
2238
|
+
const pick = (k) => typeof o[k] === "string" ? o[k] : void 0;
|
|
2239
|
+
return pick("command") ?? pick("file_path") ?? pick("path") ?? pick("pattern") ?? pick("url") ?? pick("description") ?? pick("query") ?? pick("prompt") ?? pick("old_string") ?? JSON.stringify(o);
|
|
2240
|
+
}
|
|
2241
|
+
async function loadWorkflowAgentDetail(sessionId, runId, agentId, opts = {}) {
|
|
2242
|
+
const { root = DEFAULT_ROOT } = opts;
|
|
2243
|
+
if (!/^[\w.-]+$/.test(runId) || !/^[\w.-]+$/.test(agentId))
|
|
2244
|
+
return null;
|
|
2245
|
+
const files = await walkJsonlFiles(root);
|
|
2246
|
+
const hit = files.find((f) => sessionIdFromFileName(f.fileName) === sessionId);
|
|
2247
|
+
if (!hit)
|
|
2248
|
+
return null;
|
|
2249
|
+
const file = path.join(path.dirname(hit.fullPath), sessionId, "subagents", "workflows", runId, `agent-${agentId}.jsonl`);
|
|
2250
|
+
let lines;
|
|
2251
|
+
try {
|
|
2252
|
+
lines = await readJsonlFile(file);
|
|
2253
|
+
} catch {
|
|
2254
|
+
return null;
|
|
2255
|
+
}
|
|
2256
|
+
const errored = /* @__PURE__ */ new Set();
|
|
2257
|
+
for (const raw of lines) {
|
|
2258
|
+
if (!raw || typeof raw !== "object")
|
|
2259
|
+
continue;
|
|
2260
|
+
const content = raw.message?.content;
|
|
2261
|
+
if (!Array.isArray(content))
|
|
2262
|
+
continue;
|
|
2263
|
+
for (const b of content) {
|
|
2264
|
+
if (b && typeof b === "object" && b.type === "tool_result" && b.is_error === true && typeof b.tool_use_id === "string") {
|
|
2265
|
+
errored.add(b.tool_use_id);
|
|
2266
|
+
}
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2269
|
+
const steps = [];
|
|
2270
|
+
const toolCounts = /* @__PURE__ */ new Map();
|
|
2271
|
+
const totalUsage = { ...BLANK_USAGE3 };
|
|
2272
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2273
|
+
let prompt;
|
|
2274
|
+
let finalText;
|
|
2275
|
+
let model;
|
|
2276
|
+
let assistantMessageCount = 0;
|
|
2277
|
+
let eventCount = 0;
|
|
2278
|
+
let startMs;
|
|
2279
|
+
let endMs;
|
|
2280
|
+
for (const raw of lines) {
|
|
2281
|
+
if (!raw || typeof raw !== "object")
|
|
2282
|
+
continue;
|
|
2283
|
+
const r = raw;
|
|
2284
|
+
eventCount++;
|
|
2285
|
+
const ts = typeof r.timestamp === "string" ? Date.parse(r.timestamp) : NaN;
|
|
2286
|
+
if (!Number.isNaN(ts)) {
|
|
2287
|
+
if (startMs === void 0 || ts < startMs)
|
|
2288
|
+
startMs = ts;
|
|
2289
|
+
if (endMs === void 0 || ts > endMs)
|
|
2290
|
+
endMs = ts;
|
|
2291
|
+
}
|
|
2292
|
+
if (prompt === void 0 && r.type === "user" && (r.parentUuid === null || r.parentUuid === void 0)) {
|
|
2293
|
+
const c = r.message?.content;
|
|
2294
|
+
if (typeof c === "string")
|
|
2295
|
+
prompt = c;
|
|
2296
|
+
else if (Array.isArray(c)) {
|
|
2297
|
+
const t = c.find((b) => b && typeof b === "object" && b.type === "text");
|
|
2298
|
+
if (t?.text)
|
|
2299
|
+
prompt = t.text;
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
if (r.type !== "assistant")
|
|
2303
|
+
continue;
|
|
2304
|
+
const m = r.message;
|
|
2305
|
+
if (!m)
|
|
2306
|
+
continue;
|
|
2307
|
+
if (!model && typeof m.model === "string")
|
|
2308
|
+
model = m.model;
|
|
2309
|
+
const mid = typeof m.id === "string" ? m.id : void 0;
|
|
2310
|
+
const rid = typeof r.requestId === "string" ? r.requestId : void 0;
|
|
2311
|
+
const key = mid != null && rid != null ? `${mid}:${rid}` : void 0;
|
|
2312
|
+
const fresh = key ? !seen.has(key) : true;
|
|
2313
|
+
if (key && fresh)
|
|
2314
|
+
seen.add(key);
|
|
2315
|
+
if (fresh) {
|
|
2316
|
+
assistantMessageCount++;
|
|
2317
|
+
const u = m.usage;
|
|
2318
|
+
if (u) {
|
|
2319
|
+
const n = (v) => typeof v === "number" ? v : 0;
|
|
2320
|
+
totalUsage.input += n(u.input_tokens);
|
|
2321
|
+
totalUsage.output += n(u.output_tokens);
|
|
2322
|
+
totalUsage.cacheRead += n(u.cache_read_input_tokens);
|
|
2323
|
+
totalUsage.cacheWrite += n(u.cache_creation_input_tokens);
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2326
|
+
const content = m.content;
|
|
2327
|
+
if (!Array.isArray(content))
|
|
2328
|
+
continue;
|
|
2329
|
+
for (const b of content) {
|
|
2330
|
+
if (!b || typeof b !== "object")
|
|
2331
|
+
continue;
|
|
2332
|
+
if (b.type === "text" && typeof b.text === "string") {
|
|
2333
|
+
finalText = b.text;
|
|
2334
|
+
} else if (b.type === "tool_use" && typeof b.name === "string") {
|
|
2335
|
+
toolCounts.set(b.name, (toolCounts.get(b.name) ?? 0) + 1);
|
|
2336
|
+
if (steps.length < 2e3) {
|
|
2337
|
+
const salient = salientToolInput(b.input);
|
|
2338
|
+
const preview = salient.replace(/\s+/g, " ").trim().slice(0, 160);
|
|
2339
|
+
const full = salient.length > 4e3 ? salient.slice(0, 4e3) + "\u2026" : salient;
|
|
2340
|
+
steps.push({
|
|
2341
|
+
index: steps.length + 1,
|
|
2342
|
+
tool: b.name,
|
|
2343
|
+
preview,
|
|
2344
|
+
// Only carry `full` when it adds something over the one-line preview.
|
|
2345
|
+
full: full.length > preview.length || full.includes("\n") ? full : void 0,
|
|
2346
|
+
isError: typeof b.id === "string" && errored.has(b.id)
|
|
2347
|
+
});
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
const toolCalls = Array.from(toolCounts.entries()).map(([name, count]) => ({ name, count })).sort((a, b) => b.count - a.count);
|
|
2353
|
+
return {
|
|
2354
|
+
agentId,
|
|
2355
|
+
prompt,
|
|
2356
|
+
finalText,
|
|
2357
|
+
steps,
|
|
2358
|
+
toolCalls,
|
|
2359
|
+
toolCallCount: steps.length,
|
|
2360
|
+
assistantMessageCount,
|
|
2361
|
+
eventCount,
|
|
2362
|
+
totalUsage,
|
|
2363
|
+
model,
|
|
2364
|
+
durationMs: startMs !== void 0 && endMs !== void 0 ? endMs - startMs : void 0
|
|
2365
|
+
};
|
|
2366
|
+
}
|
|
1924
2367
|
async function listProjects(root = DEFAULT_ROOT) {
|
|
1925
2368
|
const files = await walkJsonlFiles(root);
|
|
1926
2369
|
const byRawDir = /* @__PURE__ */ new Map();
|
|
@@ -1942,10 +2385,10 @@ async function listProjects(root = DEFAULT_ROOT) {
|
|
|
1942
2385
|
const canonicalMap = /* @__PURE__ */ new Map();
|
|
1943
2386
|
for (const [rawDir, { count, lastActiveMs }] of byRawDir) {
|
|
1944
2387
|
const cwdOrDecoded = cwdForProject(rawDir) ?? decodeProjectName(rawDir);
|
|
1945
|
-
const
|
|
2388
|
+
const repo = projectRepoName(cwdOrDecoded);
|
|
1946
2389
|
const wt = worktreeName(cwdOrDecoded);
|
|
1947
|
-
const agg = canonicalMap.get(
|
|
1948
|
-
canonicalName:
|
|
2390
|
+
const agg = canonicalMap.get(repo) ?? {
|
|
2391
|
+
canonicalName: repo,
|
|
1949
2392
|
count: 0,
|
|
1950
2393
|
lastActiveMs: 0,
|
|
1951
2394
|
worktreeBranches: /* @__PURE__ */ new Set()
|
|
@@ -1955,7 +2398,7 @@ async function listProjects(root = DEFAULT_ROOT) {
|
|
|
1955
2398
|
agg.lastActiveMs = lastActiveMs;
|
|
1956
2399
|
if (wt)
|
|
1957
2400
|
agg.worktreeBranches.add(wt);
|
|
1958
|
-
canonicalMap.set(
|
|
2401
|
+
canonicalMap.set(repo, agg);
|
|
1959
2402
|
}
|
|
1960
2403
|
return Array.from(canonicalMap.values()).map((a) => ({
|
|
1961
2404
|
projectDir: a.canonicalName,
|
|
@@ -2919,11 +3362,404 @@ async function listGeminiSessions(opts = {}) {
|
|
|
2919
3362
|
continue;
|
|
2920
3363
|
}
|
|
2921
3364
|
try {
|
|
2922
|
-
const { meta } = await parseSession(file);
|
|
2923
|
-
metaCache3.set(file.filePath, {
|
|
3365
|
+
const { meta } = await parseSession(file);
|
|
3366
|
+
metaCache3.set(file.filePath, {
|
|
3367
|
+
meta,
|
|
3368
|
+
mtimeMs: file.mtimeMs,
|
|
3369
|
+
sizeBytes: file.sizeBytes
|
|
3370
|
+
});
|
|
3371
|
+
out.push(meta);
|
|
3372
|
+
} catch {
|
|
3373
|
+
}
|
|
3374
|
+
}
|
|
3375
|
+
out.sort((a, b) => (b.firstTimestamp ?? "").localeCompare(a.firstTimestamp ?? ""));
|
|
3376
|
+
if (opts.limit !== void 0)
|
|
3377
|
+
return out.slice(0, opts.limit);
|
|
3378
|
+
return out;
|
|
3379
|
+
}
|
|
3380
|
+
async function getGeminiSession(id, opts = {}) {
|
|
3381
|
+
const root = opts.root ?? DEFAULT_GEMINI_ROOT;
|
|
3382
|
+
const files = await listSessionFiles(root);
|
|
3383
|
+
let chosen;
|
|
3384
|
+
for (const file of files) {
|
|
3385
|
+
if (file.filenameId === id || id.startsWith(file.filenameId)) {
|
|
3386
|
+
chosen = file;
|
|
3387
|
+
break;
|
|
3388
|
+
}
|
|
3389
|
+
}
|
|
3390
|
+
if (!chosen) {
|
|
3391
|
+
for (const file of files) {
|
|
3392
|
+
const { meta: meta2 } = await parseSession(file).catch(() => ({ meta: { id: "" } }));
|
|
3393
|
+
if (meta2.id === id) {
|
|
3394
|
+
chosen = file;
|
|
3395
|
+
break;
|
|
3396
|
+
}
|
|
3397
|
+
}
|
|
3398
|
+
}
|
|
3399
|
+
if (!chosen)
|
|
3400
|
+
return null;
|
|
3401
|
+
const cached = detailCache3.get(chosen.filePath);
|
|
3402
|
+
if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes) {
|
|
3403
|
+
return cached.detail;
|
|
3404
|
+
}
|
|
3405
|
+
const { meta, events } = await parseSession(chosen);
|
|
3406
|
+
const detail = { ...meta, events };
|
|
3407
|
+
detailCache3.set(chosen.filePath, {
|
|
3408
|
+
detail,
|
|
3409
|
+
mtimeMs: chosen.mtimeMs,
|
|
3410
|
+
sizeBytes: chosen.sizeBytes
|
|
3411
|
+
});
|
|
3412
|
+
return detail;
|
|
3413
|
+
}
|
|
3414
|
+
function geminiSessionLocalDay(meta) {
|
|
3415
|
+
if (!meta.firstTimestamp)
|
|
3416
|
+
return void 0;
|
|
3417
|
+
const ms = Date.parse(meta.firstTimestamp);
|
|
3418
|
+
return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
|
|
3419
|
+
}
|
|
3420
|
+
var DEFAULT_GEMINI_ROOT, GEMINI_PROJECTS_FILE, SESSION_FILE_RE, IDLE_GAP_MS2, projectsCache, metaCache3, detailCache3;
|
|
3421
|
+
var init_gemini = __esm({
|
|
3422
|
+
"../parser/dist/gemini.js"() {
|
|
3423
|
+
"use strict";
|
|
3424
|
+
init_analytics();
|
|
3425
|
+
init_user_input();
|
|
3426
|
+
DEFAULT_GEMINI_ROOT = path3.join(os3.homedir(), ".gemini", "tmp");
|
|
3427
|
+
GEMINI_PROJECTS_FILE = path3.join(os3.homedir(), ".gemini", "projects.json");
|
|
3428
|
+
SESSION_FILE_RE = /^session-.+\.(jsonl|json)$/;
|
|
3429
|
+
IDLE_GAP_MS2 = 3 * 60 * 1e3;
|
|
3430
|
+
projectsCache = null;
|
|
3431
|
+
metaCache3 = /* @__PURE__ */ new Map();
|
|
3432
|
+
detailCache3 = /* @__PURE__ */ new Map();
|
|
3433
|
+
}
|
|
3434
|
+
});
|
|
3435
|
+
|
|
3436
|
+
// ../parser/dist/antigravity.js
|
|
3437
|
+
import { promises as fs4 } from "node:fs";
|
|
3438
|
+
import os4 from "node:os";
|
|
3439
|
+
import path4 from "node:path";
|
|
3440
|
+
async function safeReaddir3(p) {
|
|
3441
|
+
return fs4.readdir(p).catch(() => []);
|
|
3442
|
+
}
|
|
3443
|
+
async function loadSlugToCwd2(root) {
|
|
3444
|
+
const historyFile = path4.join(root, "history.jsonl");
|
|
3445
|
+
const stat = await fs4.stat(historyFile).catch(() => null);
|
|
3446
|
+
if (!stat)
|
|
3447
|
+
return /* @__PURE__ */ new Map();
|
|
3448
|
+
if (historyCache && historyCache.mtimeMs === stat.mtimeMs) {
|
|
3449
|
+
return historyCache.slugToCwd;
|
|
3450
|
+
}
|
|
3451
|
+
const raw = await fs4.readFile(historyFile, "utf8").catch(() => "");
|
|
3452
|
+
const slugToCwd = /* @__PURE__ */ new Map();
|
|
3453
|
+
for (const line of raw.split("\n")) {
|
|
3454
|
+
const trimmed = line.trim();
|
|
3455
|
+
if (!trimmed)
|
|
3456
|
+
continue;
|
|
3457
|
+
try {
|
|
3458
|
+
const parsed = JSON.parse(trimmed);
|
|
3459
|
+
if (parsed.conversationId && parsed.workspace) {
|
|
3460
|
+
slugToCwd.set(parsed.conversationId, parsed.workspace);
|
|
3461
|
+
}
|
|
3462
|
+
} catch {
|
|
3463
|
+
}
|
|
3464
|
+
}
|
|
3465
|
+
historyCache = { mtimeMs: stat.mtimeMs, slugToCwd };
|
|
3466
|
+
return slugToCwd;
|
|
3467
|
+
}
|
|
3468
|
+
async function listSessionFiles2(root) {
|
|
3469
|
+
const slugToCwd = await loadSlugToCwd2(root);
|
|
3470
|
+
const out = [];
|
|
3471
|
+
const brainDir = path4.join(root, "brain");
|
|
3472
|
+
const entries2 = await safeReaddir3(brainDir);
|
|
3473
|
+
for (const entry of entries2) {
|
|
3474
|
+
const transcriptPath = path4.join(brainDir, entry, ".system_generated", "logs", "transcript.jsonl");
|
|
3475
|
+
const stat = await fs4.stat(transcriptPath).catch(() => null);
|
|
3476
|
+
if (stat && stat.isFile()) {
|
|
3477
|
+
out.push({
|
|
3478
|
+
filePath: transcriptPath,
|
|
3479
|
+
conversationId: entry,
|
|
3480
|
+
cwd: slugToCwd.get(entry),
|
|
3481
|
+
mtimeMs: stat.mtimeMs,
|
|
3482
|
+
sizeBytes: stat.size
|
|
3483
|
+
});
|
|
3484
|
+
}
|
|
3485
|
+
}
|
|
3486
|
+
return out;
|
|
3487
|
+
}
|
|
3488
|
+
function emptyUsage3() {
|
|
3489
|
+
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
3490
|
+
}
|
|
3491
|
+
function previewOf3(text) {
|
|
3492
|
+
return text.replace(/\s+/g, " ").trim().slice(0, 200);
|
|
3493
|
+
}
|
|
3494
|
+
function truncate4(s, n) {
|
|
3495
|
+
return s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
|
|
3496
|
+
}
|
|
3497
|
+
async function parseSession2(file) {
|
|
3498
|
+
const raw = await fs4.readFile(file.filePath, "utf8");
|
|
3499
|
+
const events = [];
|
|
3500
|
+
const totalUsage = emptyUsage3();
|
|
3501
|
+
let firstTimestamp;
|
|
3502
|
+
let lastTimestamp;
|
|
3503
|
+
let model;
|
|
3504
|
+
let toolCallCount = 0;
|
|
3505
|
+
let turnCount = 0;
|
|
3506
|
+
let firstUserPreview;
|
|
3507
|
+
let lastUserPreview;
|
|
3508
|
+
let lastAgentPreview;
|
|
3509
|
+
const tsMs = [];
|
|
3510
|
+
let idx = 0;
|
|
3511
|
+
function pushEvent(e) {
|
|
3512
|
+
events.push(e);
|
|
3513
|
+
if (e.timestamp && e.role !== "meta") {
|
|
3514
|
+
if (!firstTimestamp)
|
|
3515
|
+
firstTimestamp = e.timestamp;
|
|
3516
|
+
lastTimestamp = e.timestamp;
|
|
3517
|
+
const ms = Date.parse(e.timestamp);
|
|
3518
|
+
if (Number.isFinite(ms))
|
|
3519
|
+
tsMs.push(ms);
|
|
3520
|
+
}
|
|
3521
|
+
}
|
|
3522
|
+
const pendingToolCalls = [];
|
|
3523
|
+
const parsedObjects = [];
|
|
3524
|
+
const indexMap = /* @__PURE__ */ new Map();
|
|
3525
|
+
for (const line of raw.split("\n")) {
|
|
3526
|
+
const trimmed = line.trim();
|
|
3527
|
+
if (!trimmed)
|
|
3528
|
+
continue;
|
|
3529
|
+
try {
|
|
3530
|
+
const obj = JSON.parse(trimmed);
|
|
3531
|
+
const stepIdx = obj.step_index;
|
|
3532
|
+
if (typeof stepIdx === "number") {
|
|
3533
|
+
if (indexMap.has(stepIdx)) {
|
|
3534
|
+
parsedObjects[indexMap.get(stepIdx)] = obj;
|
|
3535
|
+
} else {
|
|
3536
|
+
indexMap.set(stepIdx, parsedObjects.length);
|
|
3537
|
+
parsedObjects.push(obj);
|
|
3538
|
+
}
|
|
3539
|
+
} else {
|
|
3540
|
+
parsedObjects.push(obj);
|
|
3541
|
+
}
|
|
3542
|
+
} catch {
|
|
3543
|
+
}
|
|
3544
|
+
}
|
|
3545
|
+
for (const eventObj of parsedObjects) {
|
|
3546
|
+
const ts = eventObj.created_at || eventObj.timestamp;
|
|
3547
|
+
if (eventObj.type === "USER_INPUT") {
|
|
3548
|
+
if (typeof eventObj.content === "string") {
|
|
3549
|
+
const matchNoNeed = eventObj.content.match(/Model Selection` from .*? to (.*?)\.\s*No need to/);
|
|
3550
|
+
if (matchNoNeed) {
|
|
3551
|
+
let rawModel = matchNoNeed[1].trim();
|
|
3552
|
+
rawModel = rawModel.replace(/\s*\(.*?\)\s*$/, "").trim();
|
|
3553
|
+
model = rawModel;
|
|
3554
|
+
} else {
|
|
3555
|
+
const matchDot = eventObj.content.match(/Model Selection` from .*? to ([^\n]+)/);
|
|
3556
|
+
if (matchDot) {
|
|
3557
|
+
let rawModel = matchDot[1].trim();
|
|
3558
|
+
if (rawModel.endsWith(".")) {
|
|
3559
|
+
rawModel = rawModel.slice(0, -1).trim();
|
|
3560
|
+
}
|
|
3561
|
+
rawModel = rawModel.replace(/\s*\(.*?\)\s*$/, "").trim();
|
|
3562
|
+
model = rawModel;
|
|
3563
|
+
}
|
|
3564
|
+
}
|
|
3565
|
+
}
|
|
3566
|
+
let text2 = eventObj.content || "";
|
|
3567
|
+
const requestMatch = text2.match(/<USER_REQUEST>([\s\S]*?)<\/USER_REQUEST>/);
|
|
3568
|
+
if (requestMatch) {
|
|
3569
|
+
text2 = requestMatch[1].trim();
|
|
3570
|
+
}
|
|
3571
|
+
const preview = previewOf3(text2);
|
|
3572
|
+
const isHidden = isFrameworkInjectedUserInput(text2);
|
|
3573
|
+
if (text2 && !isHidden) {
|
|
3574
|
+
if (!firstUserPreview)
|
|
3575
|
+
firstUserPreview = preview;
|
|
3576
|
+
lastUserPreview = preview;
|
|
3577
|
+
turnCount += 1;
|
|
3578
|
+
}
|
|
3579
|
+
pushEvent({
|
|
3580
|
+
index: idx++,
|
|
3581
|
+
timestamp: ts,
|
|
3582
|
+
role: "user",
|
|
3583
|
+
rawType: "antigravity/user",
|
|
3584
|
+
preview,
|
|
3585
|
+
blocks: text2 ? [{ type: "text", text: text2 }] : [],
|
|
3586
|
+
messageId: eventObj.step_index?.toString(),
|
|
3587
|
+
raw: eventObj
|
|
3588
|
+
});
|
|
3589
|
+
continue;
|
|
3590
|
+
}
|
|
3591
|
+
if (eventObj.type === "PLANNER_RESPONSE") {
|
|
3592
|
+
const thinking = eventObj.thinking;
|
|
3593
|
+
const content = eventObj.content;
|
|
3594
|
+
if (thinking) {
|
|
3595
|
+
pushEvent({
|
|
3596
|
+
index: idx++,
|
|
3597
|
+
timestamp: ts,
|
|
3598
|
+
role: "agent-thinking",
|
|
3599
|
+
rawType: "antigravity/thought",
|
|
3600
|
+
preview: previewOf3(thinking),
|
|
3601
|
+
blocks: [{ type: "thinking", thinking }],
|
|
3602
|
+
model,
|
|
3603
|
+
raw: eventObj
|
|
3604
|
+
});
|
|
3605
|
+
}
|
|
3606
|
+
if (content) {
|
|
3607
|
+
const preview = previewOf3(content);
|
|
3608
|
+
lastAgentPreview = preview;
|
|
3609
|
+
pushEvent({
|
|
3610
|
+
index: idx++,
|
|
3611
|
+
timestamp: ts,
|
|
3612
|
+
role: "agent",
|
|
3613
|
+
rawType: "antigravity/agent",
|
|
3614
|
+
preview,
|
|
3615
|
+
blocks: [{ type: "text", text: content }],
|
|
3616
|
+
messageId: eventObj.step_index?.toString(),
|
|
3617
|
+
model,
|
|
3618
|
+
raw: eventObj
|
|
3619
|
+
});
|
|
3620
|
+
}
|
|
3621
|
+
const toolCalls = eventObj.tool_calls || [];
|
|
3622
|
+
for (let cIdx = 0; cIdx < toolCalls.length; cIdx++) {
|
|
3623
|
+
const tc = toolCalls[cIdx];
|
|
3624
|
+
toolCallCount += 1;
|
|
3625
|
+
const toolUseId = `tool-${eventObj.step_index}-${cIdx}`;
|
|
3626
|
+
const argsStr = tc.args ? JSON.stringify(tc.args) : "";
|
|
3627
|
+
pendingToolCalls.push({ id: toolUseId, name: tc.name });
|
|
3628
|
+
pushEvent({
|
|
3629
|
+
index: idx++,
|
|
3630
|
+
timestamp: ts,
|
|
3631
|
+
role: "tool-call",
|
|
3632
|
+
rawType: "antigravity/tool_call",
|
|
3633
|
+
preview: `${tc.name}(${truncate4(argsStr, 80)})`,
|
|
3634
|
+
blocks: [{ type: "tool_use", id: toolUseId, name: tc.name, input: tc.args || {} }],
|
|
3635
|
+
toolName: tc.name,
|
|
3636
|
+
toolUseId,
|
|
3637
|
+
model,
|
|
3638
|
+
raw: tc
|
|
3639
|
+
});
|
|
3640
|
+
}
|
|
3641
|
+
continue;
|
|
3642
|
+
}
|
|
3643
|
+
if (eventObj.source === "MODEL" && eventObj.type !== "PLANNER_RESPONSE" && eventObj.type !== "ERROR_MESSAGE" && pendingToolCalls.length > 0) {
|
|
3644
|
+
const matchedCall = pendingToolCalls.shift();
|
|
3645
|
+
const toolUseId = matchedCall ? matchedCall.id : `tool-${eventObj.step_index}-unknown`;
|
|
3646
|
+
const contentStr = typeof eventObj.content === "string" ? eventObj.content : JSON.stringify(eventObj.content || "");
|
|
3647
|
+
const isError = eventObj.status === "ERROR" || eventObj.status === "FAILED" || eventObj.status === "CANCELED" || !!eventObj.error;
|
|
3648
|
+
pushEvent({
|
|
3649
|
+
index: idx++,
|
|
3650
|
+
timestamp: ts,
|
|
3651
|
+
role: "tool-result",
|
|
3652
|
+
rawType: "antigravity/tool_result",
|
|
3653
|
+
preview: previewOf3(contentStr),
|
|
3654
|
+
blocks: [{
|
|
3655
|
+
type: "tool_result",
|
|
3656
|
+
tool_use_id: toolUseId,
|
|
3657
|
+
content: contentStr,
|
|
3658
|
+
is_error: isError
|
|
3659
|
+
}],
|
|
3660
|
+
toolUseId,
|
|
3661
|
+
toolResult: contentStr,
|
|
3662
|
+
raw: eventObj
|
|
3663
|
+
});
|
|
3664
|
+
continue;
|
|
3665
|
+
}
|
|
3666
|
+
const text = eventObj.content || eventObj.error || "";
|
|
3667
|
+
pushEvent({
|
|
3668
|
+
index: idx++,
|
|
3669
|
+
timestamp: ts,
|
|
3670
|
+
role: "meta",
|
|
3671
|
+
rawType: `antigravity/${eventObj.type?.toLowerCase() || "unknown"}`,
|
|
3672
|
+
preview: previewOf3(text),
|
|
3673
|
+
blocks: text ? [{ type: "text", text }] : [],
|
|
3674
|
+
raw: eventObj
|
|
3675
|
+
});
|
|
3676
|
+
}
|
|
3677
|
+
const startMs = firstTimestamp ? Date.parse(firstTimestamp) : void 0;
|
|
3678
|
+
if (startMs !== void 0 && Number.isFinite(startMs)) {
|
|
3679
|
+
let prevMs;
|
|
3680
|
+
for (const ev of events) {
|
|
3681
|
+
if (!ev.timestamp)
|
|
3682
|
+
continue;
|
|
3683
|
+
const ms = Date.parse(ev.timestamp);
|
|
3684
|
+
if (!Number.isFinite(ms))
|
|
3685
|
+
continue;
|
|
3686
|
+
ev.tOffsetMs = Math.max(0, ms - startMs);
|
|
3687
|
+
if (prevMs !== void 0)
|
|
3688
|
+
ev.gapMs = Math.max(0, ms - prevMs);
|
|
3689
|
+
prevMs = ms;
|
|
3690
|
+
}
|
|
3691
|
+
}
|
|
3692
|
+
const activeSegments = computeActiveSegments4(tsMs);
|
|
3693
|
+
const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
|
|
3694
|
+
const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
|
|
3695
|
+
const sessionId = file.conversationId;
|
|
3696
|
+
const cwd = file.cwd;
|
|
3697
|
+
const projectName = cwd ? canonicalProjectName(cwd) : file.conversationId;
|
|
3698
|
+
const projectDir = cwd ? cwd.replace(/^\//, "-").replace(/\//g, "-") : file.conversationId;
|
|
3699
|
+
const meta = {
|
|
3700
|
+
agent: "antigravity",
|
|
3701
|
+
id: sessionId,
|
|
3702
|
+
filePath: file.filePath,
|
|
3703
|
+
projectName,
|
|
3704
|
+
projectDir,
|
|
3705
|
+
sessionId,
|
|
3706
|
+
firstTimestamp,
|
|
3707
|
+
lastTimestamp,
|
|
3708
|
+
durationMs: durationMs && Number.isFinite(durationMs) ? durationMs : void 0,
|
|
3709
|
+
eventCount: events.length,
|
|
3710
|
+
model,
|
|
3711
|
+
cwd,
|
|
3712
|
+
totalUsage,
|
|
3713
|
+
status: "idle",
|
|
3714
|
+
firstUserPreview,
|
|
3715
|
+
lastUserPreview,
|
|
3716
|
+
lastAgentPreview,
|
|
3717
|
+
toolCallCount,
|
|
3718
|
+
turnCount,
|
|
3719
|
+
airTimeMs,
|
|
3720
|
+
activeSegments
|
|
3721
|
+
};
|
|
3722
|
+
return { meta, events };
|
|
3723
|
+
}
|
|
3724
|
+
function computeActiveSegments4(tsMs) {
|
|
3725
|
+
if (tsMs.length === 0)
|
|
3726
|
+
return [];
|
|
3727
|
+
const sorted = [...tsMs].sort((a, b) => a - b);
|
|
3728
|
+
const out = [];
|
|
3729
|
+
let segStart = sorted[0];
|
|
3730
|
+
let segEnd = sorted[0];
|
|
3731
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
3732
|
+
if (sorted[i] - segEnd > IDLE_GAP_MS3) {
|
|
3733
|
+
out.push({ startMs: segStart, endMs: segEnd });
|
|
3734
|
+
segStart = sorted[i];
|
|
3735
|
+
}
|
|
3736
|
+
segEnd = sorted[i];
|
|
3737
|
+
}
|
|
3738
|
+
out.push({ startMs: segStart, endMs: segEnd });
|
|
3739
|
+
return out;
|
|
3740
|
+
}
|
|
3741
|
+
function clearAntigravityCaches() {
|
|
3742
|
+
metaCache4.clear();
|
|
3743
|
+
detailCache4.clear();
|
|
3744
|
+
historyCache = null;
|
|
3745
|
+
}
|
|
3746
|
+
async function listAntigravitySessions(opts = {}) {
|
|
3747
|
+
const root = opts.root ?? DEFAULT_ANTIGRAVITY_ROOT;
|
|
3748
|
+
const files = await listSessionFiles2(root);
|
|
3749
|
+
const out = [];
|
|
3750
|
+
for (const file of files) {
|
|
3751
|
+
const cached = metaCache4.get(file.filePath);
|
|
3752
|
+
if (cached && cached.mtimeMs === file.mtimeMs && cached.sizeBytes === file.sizeBytes && cached.cwd === file.cwd) {
|
|
3753
|
+
out.push(cached.meta);
|
|
3754
|
+
continue;
|
|
3755
|
+
}
|
|
3756
|
+
try {
|
|
3757
|
+
const { meta } = await parseSession2(file);
|
|
3758
|
+
metaCache4.set(file.filePath, {
|
|
2924
3759
|
meta,
|
|
2925
3760
|
mtimeMs: file.mtimeMs,
|
|
2926
|
-
sizeBytes: file.sizeBytes
|
|
3761
|
+
sizeBytes: file.sizeBytes,
|
|
3762
|
+
cwd: file.cwd
|
|
2927
3763
|
});
|
|
2928
3764
|
out.push(meta);
|
|
2929
3765
|
} catch {
|
|
@@ -2934,59 +3770,274 @@ async function listGeminiSessions(opts = {}) {
|
|
|
2934
3770
|
return out.slice(0, opts.limit);
|
|
2935
3771
|
return out;
|
|
2936
3772
|
}
|
|
2937
|
-
async function
|
|
2938
|
-
const root = opts.root ??
|
|
2939
|
-
const files = await
|
|
3773
|
+
async function getAntigravitySession(id, opts = {}) {
|
|
3774
|
+
const root = opts.root ?? DEFAULT_ANTIGRAVITY_ROOT;
|
|
3775
|
+
const files = await listSessionFiles2(root);
|
|
2940
3776
|
let chosen;
|
|
2941
3777
|
for (const file of files) {
|
|
2942
|
-
if (file.
|
|
3778
|
+
if (file.conversationId === id) {
|
|
2943
3779
|
chosen = file;
|
|
2944
3780
|
break;
|
|
2945
3781
|
}
|
|
2946
3782
|
}
|
|
2947
|
-
if (!chosen) {
|
|
2948
|
-
for (const file of files) {
|
|
2949
|
-
const { meta: meta2 } = await parseSession(file).catch(() => ({ meta: { id: "" } }));
|
|
2950
|
-
if (meta2.id === id) {
|
|
2951
|
-
chosen = file;
|
|
2952
|
-
break;
|
|
2953
|
-
}
|
|
2954
|
-
}
|
|
2955
|
-
}
|
|
2956
3783
|
if (!chosen)
|
|
2957
3784
|
return null;
|
|
2958
|
-
const cached =
|
|
2959
|
-
if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes) {
|
|
3785
|
+
const cached = detailCache4.get(chosen.filePath);
|
|
3786
|
+
if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes && cached.cwd === chosen.cwd) {
|
|
2960
3787
|
return cached.detail;
|
|
2961
3788
|
}
|
|
2962
|
-
const { meta, events } = await
|
|
3789
|
+
const { meta, events } = await parseSession2(chosen);
|
|
2963
3790
|
const detail = { ...meta, events };
|
|
2964
|
-
|
|
3791
|
+
detailCache4.set(chosen.filePath, {
|
|
2965
3792
|
detail,
|
|
2966
3793
|
mtimeMs: chosen.mtimeMs,
|
|
2967
|
-
sizeBytes: chosen.sizeBytes
|
|
3794
|
+
sizeBytes: chosen.sizeBytes,
|
|
3795
|
+
cwd: chosen.cwd
|
|
2968
3796
|
});
|
|
2969
3797
|
return detail;
|
|
2970
3798
|
}
|
|
2971
|
-
function
|
|
3799
|
+
function antigravitySessionLocalDay(meta) {
|
|
2972
3800
|
if (!meta.firstTimestamp)
|
|
2973
3801
|
return void 0;
|
|
2974
3802
|
const ms = Date.parse(meta.firstTimestamp);
|
|
2975
3803
|
return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
|
|
2976
3804
|
}
|
|
2977
|
-
var
|
|
2978
|
-
var
|
|
2979
|
-
"../parser/dist/
|
|
3805
|
+
var DEFAULT_ANTIGRAVITY_ROOT, IDLE_GAP_MS3, historyCache, metaCache4, detailCache4;
|
|
3806
|
+
var init_antigravity = __esm({
|
|
3807
|
+
"../parser/dist/antigravity.js"() {
|
|
2980
3808
|
"use strict";
|
|
2981
3809
|
init_analytics();
|
|
2982
3810
|
init_user_input();
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
3811
|
+
DEFAULT_ANTIGRAVITY_ROOT = path4.join(os4.homedir(), ".gemini", "antigravity-cli");
|
|
3812
|
+
IDLE_GAP_MS3 = 3 * 60 * 1e3;
|
|
3813
|
+
historyCache = null;
|
|
3814
|
+
metaCache4 = /* @__PURE__ */ new Map();
|
|
3815
|
+
detailCache4 = /* @__PURE__ */ new Map();
|
|
3816
|
+
}
|
|
3817
|
+
});
|
|
3818
|
+
|
|
3819
|
+
// ../parser/dist/cowork.js
|
|
3820
|
+
import { promises as fs5 } from "node:fs";
|
|
3821
|
+
import os5 from "node:os";
|
|
3822
|
+
import path5 from "node:path";
|
|
3823
|
+
function defaultCoworkRoot() {
|
|
3824
|
+
const home = os5.homedir();
|
|
3825
|
+
if (process.platform === "darwin") {
|
|
3826
|
+
return path5.join(home, "Library", "Application Support", "Claude", "local-agent-mode-sessions");
|
|
3827
|
+
}
|
|
3828
|
+
if (process.platform === "win32") {
|
|
3829
|
+
const appData = process.env.APPDATA ?? path5.join(home, "AppData", "Roaming");
|
|
3830
|
+
return path5.join(appData, "Claude", "local-agent-mode-sessions");
|
|
3831
|
+
}
|
|
3832
|
+
return path5.join(home, ".config", "Claude", "local-agent-mode-sessions");
|
|
3833
|
+
}
|
|
3834
|
+
async function safeReaddir4(p) {
|
|
3835
|
+
return fs5.readdir(p).catch(() => []);
|
|
3836
|
+
}
|
|
3837
|
+
async function statMs(p) {
|
|
3838
|
+
const s = await fs5.stat(p).catch(() => null);
|
|
3839
|
+
return s ? s.mtimeMs : 0;
|
|
3840
|
+
}
|
|
3841
|
+
async function listSessionFiles3(root) {
|
|
3842
|
+
const out = [];
|
|
3843
|
+
const accounts = await safeReaddir4(root);
|
|
3844
|
+
for (const accountId of accounts) {
|
|
3845
|
+
const accountDir = path5.join(root, accountId);
|
|
3846
|
+
const workspaces = await safeReaddir4(accountDir);
|
|
3847
|
+
for (const workspaceId of workspaces) {
|
|
3848
|
+
const workspaceDir = path5.join(accountDir, workspaceId);
|
|
3849
|
+
const spacesMtimeMs = await statMs(path5.join(workspaceDir, "spaces.json"));
|
|
3850
|
+
const entries2 = await safeReaddir4(workspaceDir);
|
|
3851
|
+
for (const entry of entries2) {
|
|
3852
|
+
if (!SESSION_ID_RE.test(entry))
|
|
3853
|
+
continue;
|
|
3854
|
+
const auditPath = path5.join(workspaceDir, entry, "audit.jsonl");
|
|
3855
|
+
const auditStat = await fs5.stat(auditPath).catch(() => null);
|
|
3856
|
+
if (!auditStat || !auditStat.isFile() || auditStat.size === 0)
|
|
3857
|
+
continue;
|
|
3858
|
+
const metaPath = path5.join(workspaceDir, `${entry}.json`);
|
|
3859
|
+
const metaMtimeMs = await statMs(metaPath);
|
|
3860
|
+
out.push({
|
|
3861
|
+
sessionId: entry,
|
|
3862
|
+
auditPath,
|
|
3863
|
+
metaPath,
|
|
3864
|
+
workspaceDir,
|
|
3865
|
+
auditMtimeMs: auditStat.mtimeMs,
|
|
3866
|
+
auditSize: auditStat.size,
|
|
3867
|
+
metaMtimeMs,
|
|
3868
|
+
spacesMtimeMs
|
|
3869
|
+
});
|
|
3870
|
+
}
|
|
3871
|
+
}
|
|
3872
|
+
}
|
|
3873
|
+
return out;
|
|
3874
|
+
}
|
|
3875
|
+
async function loadSpacesForWorkspace(workspaceDir) {
|
|
3876
|
+
const spacesPath = path5.join(workspaceDir, "spaces.json");
|
|
3877
|
+
const stat = await fs5.stat(spacesPath).catch(() => null);
|
|
3878
|
+
if (!stat)
|
|
3879
|
+
return /* @__PURE__ */ new Map();
|
|
3880
|
+
const cached = spacesCache.get(workspaceDir);
|
|
3881
|
+
if (cached && cached.mtimeMs === stat.mtimeMs)
|
|
3882
|
+
return cached.spaceIdToPath;
|
|
3883
|
+
const raw = await fs5.readFile(spacesPath, "utf8").catch(() => "");
|
|
3884
|
+
const out = /* @__PURE__ */ new Map();
|
|
3885
|
+
try {
|
|
3886
|
+
const parsed = JSON.parse(raw);
|
|
3887
|
+
for (const space of parsed.spaces ?? []) {
|
|
3888
|
+
const id = typeof space.id === "string" ? space.id : void 0;
|
|
3889
|
+
const folders = Array.isArray(space.folders) ? space.folders : [];
|
|
3890
|
+
const first = folders[0];
|
|
3891
|
+
const folderPath = typeof first?.path === "string" ? first.path : void 0;
|
|
3892
|
+
if (id && folderPath)
|
|
3893
|
+
out.set(id, folderPath);
|
|
3894
|
+
}
|
|
3895
|
+
} catch {
|
|
3896
|
+
}
|
|
3897
|
+
spacesCache.set(workspaceDir, { mtimeMs: stat.mtimeMs, spaceIdToPath: out });
|
|
3898
|
+
return out;
|
|
3899
|
+
}
|
|
3900
|
+
async function readCoworkMeta(metaPath) {
|
|
3901
|
+
const raw = await fs5.readFile(metaPath, "utf8").catch(() => "");
|
|
3902
|
+
if (!raw)
|
|
3903
|
+
return {};
|
|
3904
|
+
try {
|
|
3905
|
+
const j = JSON.parse(raw);
|
|
3906
|
+
return {
|
|
3907
|
+
spaceId: typeof j.spaceId === "string" ? j.spaceId : void 0,
|
|
3908
|
+
userSelectedFolders: Array.isArray(j.userSelectedFolders) ? j.userSelectedFolders.filter((s) => typeof s === "string") : void 0,
|
|
3909
|
+
cwd: typeof j.cwd === "string" ? j.cwd : void 0,
|
|
3910
|
+
model: typeof j.model === "string" ? j.model : void 0,
|
|
3911
|
+
title: typeof j.title === "string" ? j.title : void 0,
|
|
3912
|
+
createdAt: typeof j.createdAt === "number" ? j.createdAt : void 0,
|
|
3913
|
+
lastActivityAt: typeof j.lastActivityAt === "number" ? j.lastActivityAt : void 0
|
|
3914
|
+
};
|
|
3915
|
+
} catch {
|
|
3916
|
+
return {};
|
|
3917
|
+
}
|
|
3918
|
+
}
|
|
3919
|
+
function resolveProject(meta, spaceIdToPath) {
|
|
3920
|
+
let projectPath;
|
|
3921
|
+
if (meta.spaceId)
|
|
3922
|
+
projectPath = spaceIdToPath.get(meta.spaceId);
|
|
3923
|
+
if (!projectPath && meta.userSelectedFolders && meta.userSelectedFolders.length > 0) {
|
|
3924
|
+
projectPath = meta.userSelectedFolders[0];
|
|
3925
|
+
}
|
|
3926
|
+
if (!projectPath) {
|
|
3927
|
+
return { projectName: "cowork:unspaced", projectDir: "cowork-unspaced" };
|
|
3928
|
+
}
|
|
3929
|
+
return {
|
|
3930
|
+
projectName: canonicalProjectName(projectPath),
|
|
3931
|
+
projectDir: projectPath.replace(/^\//, "-").replace(/\//g, "-"),
|
|
3932
|
+
cwd: projectPath
|
|
3933
|
+
};
|
|
3934
|
+
}
|
|
3935
|
+
async function readJsonl2(filePath) {
|
|
3936
|
+
const raw = await fs5.readFile(filePath, "utf8");
|
|
3937
|
+
const out = [];
|
|
3938
|
+
for (const line of raw.split("\n")) {
|
|
3939
|
+
const trimmed = line.trim();
|
|
3940
|
+
if (!trimmed)
|
|
3941
|
+
continue;
|
|
3942
|
+
try {
|
|
3943
|
+
out.push(JSON.parse(trimmed));
|
|
3944
|
+
} catch {
|
|
3945
|
+
}
|
|
3946
|
+
}
|
|
3947
|
+
return out;
|
|
3948
|
+
}
|
|
3949
|
+
async function parseCoworkSession(file) {
|
|
3950
|
+
const [lines, coworkMeta, spaceIdToPath] = await Promise.all([
|
|
3951
|
+
readJsonl2(file.auditPath),
|
|
3952
|
+
readCoworkMeta(file.metaPath),
|
|
3953
|
+
loadSpacesForWorkspace(file.workspaceDir)
|
|
3954
|
+
]);
|
|
3955
|
+
const { meta: baseMeta, events } = parseTranscript(lines);
|
|
3956
|
+
const { projectName, projectDir, cwd } = resolveProject(coworkMeta, spaceIdToPath);
|
|
3957
|
+
const meta = {
|
|
3958
|
+
...baseMeta,
|
|
3959
|
+
agent: "cowork",
|
|
3960
|
+
id: file.sessionId,
|
|
3961
|
+
sessionId: file.sessionId,
|
|
3962
|
+
filePath: file.auditPath,
|
|
3963
|
+
projectName,
|
|
3964
|
+
projectDir,
|
|
3965
|
+
cwd: cwd ?? baseMeta.cwd,
|
|
3966
|
+
model: baseMeta.model ?? coworkMeta.model
|
|
3967
|
+
};
|
|
3968
|
+
return { meta, events };
|
|
3969
|
+
}
|
|
3970
|
+
function cacheKeyFor(file) {
|
|
3971
|
+
return {
|
|
3972
|
+
auditMtimeMs: file.auditMtimeMs,
|
|
3973
|
+
auditSize: file.auditSize,
|
|
3974
|
+
metaMtimeMs: file.metaMtimeMs,
|
|
3975
|
+
spacesMtimeMs: file.spacesMtimeMs
|
|
3976
|
+
};
|
|
3977
|
+
}
|
|
3978
|
+
function cacheKeyMatches(a, b) {
|
|
3979
|
+
return a.auditMtimeMs === b.auditMtimeMs && a.auditSize === b.auditSize && a.metaMtimeMs === b.metaMtimeMs && a.spacesMtimeMs === b.spacesMtimeMs;
|
|
3980
|
+
}
|
|
3981
|
+
function clearCoworkCaches() {
|
|
3982
|
+
metaCache5.clear();
|
|
3983
|
+
detailCache5.clear();
|
|
3984
|
+
spacesCache.clear();
|
|
3985
|
+
}
|
|
3986
|
+
async function listCoworkSessions(opts = {}) {
|
|
3987
|
+
const root = opts.root ?? DEFAULT_COWORK_ROOT;
|
|
3988
|
+
const files = await listSessionFiles3(root);
|
|
3989
|
+
const out = [];
|
|
3990
|
+
for (const file of files) {
|
|
3991
|
+
const key = cacheKeyFor(file);
|
|
3992
|
+
const cached = metaCache5.get(file.auditPath);
|
|
3993
|
+
if (cached && cacheKeyMatches(cached.key, key)) {
|
|
3994
|
+
out.push(cached.meta);
|
|
3995
|
+
continue;
|
|
3996
|
+
}
|
|
3997
|
+
try {
|
|
3998
|
+
const { meta } = await parseCoworkSession(file);
|
|
3999
|
+
metaCache5.set(file.auditPath, { meta, key });
|
|
4000
|
+
out.push(meta);
|
|
4001
|
+
} catch {
|
|
4002
|
+
}
|
|
4003
|
+
}
|
|
4004
|
+
out.sort((a, b) => (b.firstTimestamp ?? "").localeCompare(a.firstTimestamp ?? ""));
|
|
4005
|
+
if (opts.limit !== void 0)
|
|
4006
|
+
return out.slice(0, opts.limit);
|
|
4007
|
+
return out;
|
|
4008
|
+
}
|
|
4009
|
+
async function getCoworkSession(id, opts = {}) {
|
|
4010
|
+
const root = opts.root ?? DEFAULT_COWORK_ROOT;
|
|
4011
|
+
const files = await listSessionFiles3(root);
|
|
4012
|
+
const file = files.find((f) => f.sessionId === id);
|
|
4013
|
+
if (!file)
|
|
4014
|
+
return null;
|
|
4015
|
+
const key = cacheKeyFor(file);
|
|
4016
|
+
const cached = detailCache5.get(file.auditPath);
|
|
4017
|
+
if (cached && cacheKeyMatches(cached.key, key))
|
|
4018
|
+
return cached.detail;
|
|
4019
|
+
const { meta, events } = await parseCoworkSession(file);
|
|
4020
|
+
const detail = { ...meta, events };
|
|
4021
|
+
detailCache5.set(file.auditPath, { detail, key });
|
|
4022
|
+
return detail;
|
|
4023
|
+
}
|
|
4024
|
+
function coworkSessionLocalDay(meta) {
|
|
4025
|
+
if (!meta.firstTimestamp)
|
|
4026
|
+
return void 0;
|
|
4027
|
+
const ms = Date.parse(meta.firstTimestamp);
|
|
4028
|
+
return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
|
|
4029
|
+
}
|
|
4030
|
+
var DEFAULT_COWORK_ROOT, SESSION_ID_RE, spacesCache, metaCache5, detailCache5;
|
|
4031
|
+
var init_cowork = __esm({
|
|
4032
|
+
"../parser/dist/cowork.js"() {
|
|
4033
|
+
"use strict";
|
|
4034
|
+
init_analytics();
|
|
4035
|
+
init_parser();
|
|
4036
|
+
DEFAULT_COWORK_ROOT = defaultCoworkRoot();
|
|
4037
|
+
SESSION_ID_RE = /^local_[0-9a-f-]+$/;
|
|
4038
|
+
spacesCache = /* @__PURE__ */ new Map();
|
|
4039
|
+
metaCache5 = /* @__PURE__ */ new Map();
|
|
4040
|
+
detailCache5 = /* @__PURE__ */ new Map();
|
|
2990
4041
|
}
|
|
2991
4042
|
});
|
|
2992
4043
|
|
|
@@ -3034,11 +4085,14 @@ var init_team_wire = __esm({
|
|
|
3034
4085
|
// ../parser/dist/fs.js
|
|
3035
4086
|
var fs_exports = {};
|
|
3036
4087
|
__export(fs_exports, {
|
|
4088
|
+
DEFAULT_ANTIGRAVITY_ROOT: () => DEFAULT_ANTIGRAVITY_ROOT,
|
|
3037
4089
|
DEFAULT_CODEX_ROOT: () => DEFAULT_CODEX_ROOT,
|
|
4090
|
+
DEFAULT_COWORK_ROOT: () => DEFAULT_COWORK_ROOT,
|
|
3038
4091
|
DEFAULT_GEMINI_ROOT: () => DEFAULT_GEMINI_ROOT,
|
|
3039
4092
|
DEFAULT_ROOT: () => DEFAULT_ROOT,
|
|
3040
4093
|
RICH_ROLLUP_SCHEMA_VERSION: () => RICH_ROLLUP_SCHEMA_VERSION,
|
|
3041
4094
|
agentSources: () => agentSources,
|
|
4095
|
+
antigravitySessionLocalDay: () => antigravitySessionLocalDay,
|
|
3042
4096
|
buildCalibrationCurve: () => buildCalibrationCurve,
|
|
3043
4097
|
cacheStats: () => cacheStats,
|
|
3044
4098
|
cclensHome: () => cclensHome,
|
|
@@ -3046,19 +4100,24 @@ __export(fs_exports, {
|
|
|
3046
4100
|
clearCaches: () => clearCaches,
|
|
3047
4101
|
clearTeamConfig: () => clearTeamConfig,
|
|
3048
4102
|
codexSessionLocalDay: () => codexSessionLocalDay,
|
|
4103
|
+
coworkSessionLocalDay: () => coworkSessionLocalDay,
|
|
3049
4104
|
decodeProjectName: () => decodeProjectName,
|
|
3050
4105
|
findTeamLead: () => findTeamLead,
|
|
3051
4106
|
geminiSessionLocalDay: () => geminiSessionLocalDay,
|
|
3052
4107
|
getAgentSource: () => getAgentSource,
|
|
4108
|
+
getAntigravitySession: () => getAntigravitySession,
|
|
3053
4109
|
getAnySession: () => getAnySession,
|
|
3054
4110
|
getCodexSession: () => getCodexSession,
|
|
4111
|
+
getCoworkSession: () => getCoworkSession,
|
|
3055
4112
|
getGeminiSession: () => getGeminiSession,
|
|
3056
4113
|
getLatestCodexUsage: () => getLatestCodexUsage,
|
|
3057
4114
|
getSession: () => getSession,
|
|
3058
4115
|
invalidateFile: () => invalidateFile,
|
|
3059
4116
|
isFleetlensRuntimeDir: () => isFleetlensRuntimeDir,
|
|
3060
4117
|
listAllSessions: () => listAllSessions,
|
|
4118
|
+
listAntigravitySessions: () => listAntigravitySessions,
|
|
3061
4119
|
listCodexSessions: () => listCodexSessions,
|
|
4120
|
+
listCoworkSessions: () => listCoworkSessions,
|
|
3062
4121
|
listGeminiSessions: () => listGeminiSessions,
|
|
3063
4122
|
listProjects: () => listProjects,
|
|
3064
4123
|
listSessions: () => listSessions,
|
|
@@ -3067,20 +4126,21 @@ __export(fs_exports, {
|
|
|
3067
4126
|
loadCalibrationSnapshots: () => loadCalibrationSnapshots,
|
|
3068
4127
|
loadTeamForSession: () => loadTeamForSession,
|
|
3069
4128
|
loadUsageByDay: () => loadUsageByDay,
|
|
4129
|
+
loadWorkflowAgentDetail: () => loadWorkflowAgentDetail,
|
|
3070
4130
|
readJsonlFile: () => readJsonlFile,
|
|
3071
4131
|
readTeamConfig: () => readTeamConfig,
|
|
3072
4132
|
sessionIdFromFileName: () => sessionIdFromFileName,
|
|
3073
4133
|
walkJsonlFiles: () => walkJsonlFiles,
|
|
3074
4134
|
writeTeamConfig: () => writeTeamConfig
|
|
3075
4135
|
});
|
|
3076
|
-
import { promises as
|
|
3077
|
-
import
|
|
3078
|
-
import
|
|
4136
|
+
import { promises as fs6 } from "node:fs";
|
|
4137
|
+
import os6 from "node:os";
|
|
4138
|
+
import path6 from "node:path";
|
|
3079
4139
|
function cclensHome() {
|
|
3080
|
-
return process.env.CCLENS_HOME ||
|
|
4140
|
+
return process.env.CCLENS_HOME || path6.join(os6.homedir(), ".cclens");
|
|
3081
4141
|
}
|
|
3082
4142
|
function cclensPath(...parts) {
|
|
3083
|
-
return
|
|
4143
|
+
return path6.join(cclensHome(), ...parts);
|
|
3084
4144
|
}
|
|
3085
4145
|
function cacheStats() {
|
|
3086
4146
|
return claudeCodeCacheStats();
|
|
@@ -3089,6 +4149,8 @@ function clearCaches() {
|
|
|
3089
4149
|
clearClaudeCodeCaches();
|
|
3090
4150
|
clearCodexCaches();
|
|
3091
4151
|
clearGeminiCaches();
|
|
4152
|
+
clearAntigravityCaches();
|
|
4153
|
+
clearCoworkCaches();
|
|
3092
4154
|
}
|
|
3093
4155
|
function invalidateFile(fullPath) {
|
|
3094
4156
|
invalidateClaudeCodeFile(fullPath);
|
|
@@ -3120,7 +4182,7 @@ function usageLogPath() {
|
|
|
3120
4182
|
async function loadUsageByDay(start2, end) {
|
|
3121
4183
|
let raw;
|
|
3122
4184
|
try {
|
|
3123
|
-
raw = await
|
|
4185
|
+
raw = await fs6.readFile(usageLogPath(), "utf8");
|
|
3124
4186
|
} catch {
|
|
3125
4187
|
return { by_day: [] };
|
|
3126
4188
|
}
|
|
@@ -3165,7 +4227,7 @@ async function loadUsageByDay(start2, end) {
|
|
|
3165
4227
|
async function loadCalibrationSnapshots() {
|
|
3166
4228
|
let raw;
|
|
3167
4229
|
try {
|
|
3168
|
-
raw = await
|
|
4230
|
+
raw = await fs6.readFile(usageLogPath(), "utf8");
|
|
3169
4231
|
} catch {
|
|
3170
4232
|
return [];
|
|
3171
4233
|
}
|
|
@@ -3323,7 +4385,7 @@ async function loadCalibrationCurve(tier = "pro-max-20x", root = DEFAULT_ROOT, g
|
|
|
3323
4385
|
]);
|
|
3324
4386
|
return buildCalibrationCurve(events, snapshots, tier, granularityMin);
|
|
3325
4387
|
}
|
|
3326
|
-
var codexSource, geminiSource, agentSources;
|
|
4388
|
+
var codexSource, geminiSource, antigravitySource, coworkSource, agentSources;
|
|
3327
4389
|
var init_fs = __esm({
|
|
3328
4390
|
"../parser/dist/fs.js"() {
|
|
3329
4391
|
"use strict";
|
|
@@ -3333,9 +4395,13 @@ var init_fs = __esm({
|
|
|
3333
4395
|
init_claude_code();
|
|
3334
4396
|
init_codex();
|
|
3335
4397
|
init_gemini();
|
|
4398
|
+
init_antigravity();
|
|
4399
|
+
init_cowork();
|
|
3336
4400
|
init_claude_code();
|
|
3337
4401
|
init_codex();
|
|
3338
4402
|
init_gemini();
|
|
4403
|
+
init_antigravity();
|
|
4404
|
+
init_cowork();
|
|
3339
4405
|
init_team_config();
|
|
3340
4406
|
init_team_wire();
|
|
3341
4407
|
codexSource = {
|
|
@@ -3369,7 +4435,33 @@ var init_fs = __esm({
|
|
|
3369
4435
|
return getGeminiSession(id);
|
|
3370
4436
|
}
|
|
3371
4437
|
};
|
|
3372
|
-
|
|
4438
|
+
antigravitySource = {
|
|
4439
|
+
...ANTIGRAVITY_METADATA,
|
|
4440
|
+
defaultRoot: DEFAULT_ANTIGRAVITY_ROOT,
|
|
4441
|
+
async listSessions(opts) {
|
|
4442
|
+
return listAntigravitySessions(opts);
|
|
4443
|
+
},
|
|
4444
|
+
async getSession(id) {
|
|
4445
|
+
return getAntigravitySession(id);
|
|
4446
|
+
}
|
|
4447
|
+
};
|
|
4448
|
+
coworkSource = {
|
|
4449
|
+
...COWORK_METADATA,
|
|
4450
|
+
defaultRoot: DEFAULT_COWORK_ROOT,
|
|
4451
|
+
async listSessions(opts) {
|
|
4452
|
+
return listCoworkSessions(opts);
|
|
4453
|
+
},
|
|
4454
|
+
async getSession(id) {
|
|
4455
|
+
return getCoworkSession(id);
|
|
4456
|
+
}
|
|
4457
|
+
};
|
|
4458
|
+
agentSources = [
|
|
4459
|
+
claudeCodeSource,
|
|
4460
|
+
codexSource,
|
|
4461
|
+
geminiSource,
|
|
4462
|
+
antigravitySource,
|
|
4463
|
+
coworkSource
|
|
4464
|
+
];
|
|
3373
4465
|
}
|
|
3374
4466
|
});
|
|
3375
4467
|
|
|
@@ -3442,11 +4534,11 @@ function stopServer() {
|
|
|
3442
4534
|
}
|
|
3443
4535
|
async function checkPort(port) {
|
|
3444
4536
|
const { createServer } = await import("node:net");
|
|
3445
|
-
return new Promise((
|
|
4537
|
+
return new Promise((resolve3) => {
|
|
3446
4538
|
const server = createServer();
|
|
3447
|
-
server.once("error", () =>
|
|
4539
|
+
server.once("error", () => resolve3(true));
|
|
3448
4540
|
server.once("listening", () => {
|
|
3449
|
-
server.close(() =>
|
|
4541
|
+
server.close(() => resolve3(false));
|
|
3450
4542
|
});
|
|
3451
4543
|
server.listen(port, "localhost");
|
|
3452
4544
|
});
|
|
@@ -3776,9 +4868,9 @@ Installed: ${PACKAGE_NAME}@${verify.installedVersion} at ${verify.installedPath
|
|
|
3776
4868
|
console.warn(
|
|
3777
4869
|
` \u2022 reinstall in the correct Node env: 'npm install -g ${PACKAGE_NAME}@latest'`
|
|
3778
4870
|
);
|
|
3779
|
-
} else if (verify.installedVersion !== "0.
|
|
4871
|
+
} else if (verify.installedVersion !== "0.12.1") {
|
|
3780
4872
|
console.log(
|
|
3781
|
-
` \u2192 This process is still running ${"0.
|
|
4873
|
+
` \u2192 This process is still running ${"0.12.1"}. Next invocation will use ${verify.installedVersion}.`
|
|
3782
4874
|
);
|
|
3783
4875
|
}
|
|
3784
4876
|
}
|
|
@@ -3813,14 +4905,14 @@ async function getUpdateAvailability() {
|
|
|
3813
4905
|
if (isDevMode()) return null;
|
|
3814
4906
|
const latest = await fetchLatestVersion();
|
|
3815
4907
|
if (latest === null) return {
|
|
3816
|
-
current: "0.
|
|
4908
|
+
current: "0.12.1",
|
|
3817
4909
|
latest: null,
|
|
3818
4910
|
updateAvailable: false
|
|
3819
4911
|
};
|
|
3820
4912
|
return {
|
|
3821
|
-
current: "0.
|
|
4913
|
+
current: "0.12.1",
|
|
3822
4914
|
latest,
|
|
3823
|
-
updateAvailable: shouldUpdate("0.
|
|
4915
|
+
updateAvailable: shouldUpdate("0.12.1", latest)
|
|
3824
4916
|
};
|
|
3825
4917
|
}
|
|
3826
4918
|
async function checkForUpdate() {
|
|
@@ -3910,7 +5002,7 @@ async function restartServices(state) {
|
|
|
3910
5002
|
}
|
|
3911
5003
|
async function forceUpdate() {
|
|
3912
5004
|
const latest = await fetchLatestVersion();
|
|
3913
|
-
const current = "0.
|
|
5005
|
+
const current = "0.12.1";
|
|
3914
5006
|
if (latest === null) {
|
|
3915
5007
|
console.error("Could not reach npm registry. Check your network.");
|
|
3916
5008
|
process.exit(1);
|
|
@@ -4088,10 +5180,10 @@ async function web(args2) {
|
|
|
4088
5180
|
const open = args2.includes("--open");
|
|
4089
5181
|
const positional = args2.filter((a) => !a.startsWith("--"));
|
|
4090
5182
|
const rawPath = positional[0] ?? "";
|
|
4091
|
-
const
|
|
5183
|
+
const path7 = rawPath.startsWith("/") ? rawPath : rawPath ? `/${rawPath}` : "";
|
|
4092
5184
|
const status2 = getServerStatus();
|
|
4093
5185
|
if (status2.running) {
|
|
4094
|
-
const url = `http://localhost:${status2.port}${
|
|
5186
|
+
const url = `http://localhost:${status2.port}${path7}`;
|
|
4095
5187
|
if (open) {
|
|
4096
5188
|
console.log(`Opening ${url}`);
|
|
4097
5189
|
openBrowser(url);
|
|
@@ -4103,7 +5195,7 @@ async function web(args2) {
|
|
|
4103
5195
|
console.log("fleetlens is not running. Starting server...");
|
|
4104
5196
|
try {
|
|
4105
5197
|
const result = await startServer({});
|
|
4106
|
-
const url = `http://localhost:${result.port}${
|
|
5198
|
+
const url = `http://localhost:${result.port}${path7}`;
|
|
4107
5199
|
console.log(`fleetlens running on ${url} (PID ${result.pid})`);
|
|
4108
5200
|
if (open) {
|
|
4109
5201
|
openBrowser(url);
|
|
@@ -4165,9 +5257,9 @@ function readFromCredentialsFile() {
|
|
|
4165
5257
|
join5(homedir2(), ".claude", ".credentials.json"),
|
|
4166
5258
|
join5(homedir2(), ".config", "claude", "credentials.json")
|
|
4167
5259
|
];
|
|
4168
|
-
for (const
|
|
5260
|
+
for (const path7 of candidates) {
|
|
4169
5261
|
try {
|
|
4170
|
-
const blob = readFileSync6(
|
|
5262
|
+
const blob = readFileSync6(path7, "utf8");
|
|
4171
5263
|
const creds = extractCredentials(blob);
|
|
4172
5264
|
if (creds) return creds;
|
|
4173
5265
|
} catch {
|
|
@@ -5100,8 +6192,10 @@ var init_aggregate = __esm({
|
|
|
5100
6192
|
// ../parser/dist/index.js
|
|
5101
6193
|
var dist_exports = {};
|
|
5102
6194
|
__export(dist_exports, {
|
|
6195
|
+
ANTIGRAVITY_METADATA: () => ANTIGRAVITY_METADATA,
|
|
5103
6196
|
CLAUDE_CODE_METADATA: () => CLAUDE_CODE_METADATA,
|
|
5104
6197
|
CODEX_METADATA: () => CODEX_METADATA,
|
|
6198
|
+
COWORK_METADATA: () => COWORK_METADATA,
|
|
5105
6199
|
GEMINI_METADATA: () => GEMINI_METADATA,
|
|
5106
6200
|
PRICES: () => PRICES,
|
|
5107
6201
|
RATE_PER_PCT: () => RATE_PER_PCT,
|
|
@@ -5142,6 +6236,7 @@ __export(dist_exports, {
|
|
|
5142
6236
|
predictUtilization: () => predictUtilization,
|
|
5143
6237
|
priorCalendarMonth: () => priorCalendarMonth,
|
|
5144
6238
|
priorCalendarWeek: () => priorCalendarWeek,
|
|
6239
|
+
projectRepoName: () => projectRepoName,
|
|
5145
6240
|
rowPrimaryIndex: () => rowPrimaryIndex,
|
|
5146
6241
|
sessionAirTimeMs: () => sessionAirTimeMs,
|
|
5147
6242
|
sessionDay: () => sessionDay,
|
|
@@ -5345,7 +6440,7 @@ var init_trivial = __esm({
|
|
|
5345
6440
|
});
|
|
5346
6441
|
|
|
5347
6442
|
// ../entries/dist/build.js
|
|
5348
|
-
var
|
|
6443
|
+
var IDLE_GAP_MS4;
|
|
5349
6444
|
var init_build = __esm({
|
|
5350
6445
|
"../entries/dist/build.js"() {
|
|
5351
6446
|
"use strict";
|
|
@@ -5353,7 +6448,7 @@ var init_build = __esm({
|
|
|
5353
6448
|
init_types();
|
|
5354
6449
|
init_signals();
|
|
5355
6450
|
init_trivial();
|
|
5356
|
-
|
|
6451
|
+
IDLE_GAP_MS4 = 3 * 60 * 1e3;
|
|
5357
6452
|
}
|
|
5358
6453
|
});
|
|
5359
6454
|
|
|
@@ -5386,11 +6481,11 @@ function digestsDir() {
|
|
|
5386
6481
|
digestsDirCached = envOverride ?? cclensPath("digests");
|
|
5387
6482
|
return digestsDirCached;
|
|
5388
6483
|
}
|
|
5389
|
-
function __setDigestsDirForTest(
|
|
5390
|
-
digestsDirCached =
|
|
5391
|
-
mkdirSync4(join6(
|
|
5392
|
-
mkdirSync4(join6(
|
|
5393
|
-
mkdirSync4(join6(
|
|
6484
|
+
function __setDigestsDirForTest(path7) {
|
|
6485
|
+
digestsDirCached = path7;
|
|
6486
|
+
mkdirSync4(join6(path7, "day"), { recursive: true });
|
|
6487
|
+
mkdirSync4(join6(path7, "week"), { recursive: true });
|
|
6488
|
+
mkdirSync4(join6(path7, "month"), { recursive: true });
|
|
5394
6489
|
}
|
|
5395
6490
|
function dayDigestPath(date) {
|
|
5396
6491
|
return join6(digestsDir(), "day", `${date}.json`);
|
|
@@ -5577,9 +6672,9 @@ function entriesDir() {
|
|
|
5577
6672
|
entriesDirCached = envOverride ?? cclensPath("entries");
|
|
5578
6673
|
return entriesDirCached;
|
|
5579
6674
|
}
|
|
5580
|
-
function __setEntriesDirForTest(
|
|
5581
|
-
entriesDirCached =
|
|
5582
|
-
mkdirSync5(
|
|
6675
|
+
function __setEntriesDirForTest(path7) {
|
|
6676
|
+
entriesDirCached = path7;
|
|
6677
|
+
mkdirSync5(path7, { recursive: true });
|
|
5583
6678
|
}
|
|
5584
6679
|
function pathFor(sessionId, localDay) {
|
|
5585
6680
|
return join7(entriesDir(), `${entryKey(sessionId, localDay)}.json`);
|
|
@@ -6115,8 +7210,8 @@ var init_parseUtil = __esm({
|
|
|
6115
7210
|
init_errors();
|
|
6116
7211
|
init_en();
|
|
6117
7212
|
makeIssue = (params) => {
|
|
6118
|
-
const { data, path:
|
|
6119
|
-
const fullPath = [...
|
|
7213
|
+
const { data, path: path7, errorMaps, issueData } = params;
|
|
7214
|
+
const fullPath = [...path7, ...issueData.path || []];
|
|
6120
7215
|
const fullIssue = {
|
|
6121
7216
|
...issueData,
|
|
6122
7217
|
path: fullPath
|
|
@@ -6424,11 +7519,11 @@ var init_types3 = __esm({
|
|
|
6424
7519
|
init_parseUtil();
|
|
6425
7520
|
init_util();
|
|
6426
7521
|
ParseInputLazyPath = class {
|
|
6427
|
-
constructor(parent, value,
|
|
7522
|
+
constructor(parent, value, path7, key) {
|
|
6428
7523
|
this._cachedPath = [];
|
|
6429
7524
|
this.parent = parent;
|
|
6430
7525
|
this.data = value;
|
|
6431
|
-
this._path =
|
|
7526
|
+
this._path = path7;
|
|
6432
7527
|
this._key = key;
|
|
6433
7528
|
}
|
|
6434
7529
|
get path() {
|
|
@@ -10086,10 +11181,10 @@ function snapshotAllTranscripts() {
|
|
|
10086
11181
|
}
|
|
10087
11182
|
return out;
|
|
10088
11183
|
}
|
|
10089
|
-
function readJsonlCwd(
|
|
11184
|
+
function readJsonlCwd(path7, maxLines = 8) {
|
|
10090
11185
|
let raw;
|
|
10091
11186
|
try {
|
|
10092
|
-
raw = readFileSync9(
|
|
11187
|
+
raw = readFileSync9(path7, "utf8");
|
|
10093
11188
|
} catch {
|
|
10094
11189
|
return void 0;
|
|
10095
11190
|
}
|
|
@@ -10143,10 +11238,10 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
|
|
|
10143
11238
|
}
|
|
10144
11239
|
throw new TmuxRunError(`timeout waiting for claude to create the session transcript (cwd: ${targetCwd})`);
|
|
10145
11240
|
}
|
|
10146
|
-
function parseTranscript2(
|
|
11241
|
+
function parseTranscript2(path7, defaultModel) {
|
|
10147
11242
|
let raw;
|
|
10148
11243
|
try {
|
|
10149
|
-
raw = readFileSync9(
|
|
11244
|
+
raw = readFileSync9(path7, "utf8");
|
|
10150
11245
|
} catch {
|
|
10151
11246
|
return { assembled: "", inputTokens: 0, outputTokens: 0, modelUsed: defaultModel, done: false };
|
|
10152
11247
|
}
|
|
@@ -10275,15 +11370,15 @@ function newRunId(kind) {
|
|
|
10275
11370
|
function tracePath(runId) {
|
|
10276
11371
|
return join9(RUNS_DIR, `${runId}.jsonl`);
|
|
10277
11372
|
}
|
|
10278
|
-
function safeAppend(
|
|
11373
|
+
function safeAppend(path7, line) {
|
|
10279
11374
|
try {
|
|
10280
|
-
appendFileSync2(
|
|
11375
|
+
appendFileSync2(path7, line);
|
|
10281
11376
|
} catch {
|
|
10282
11377
|
}
|
|
10283
11378
|
}
|
|
10284
|
-
function safeWrite(
|
|
11379
|
+
function safeWrite(path7, line) {
|
|
10285
11380
|
try {
|
|
10286
|
-
writeFileSync6(
|
|
11381
|
+
writeFileSync6(path7, line);
|
|
10287
11382
|
} catch {
|
|
10288
11383
|
}
|
|
10289
11384
|
}
|
|
@@ -10361,7 +11456,7 @@ async function runClaudeSubprocess(args2) {
|
|
|
10361
11456
|
return runClaudePrintMode(args2);
|
|
10362
11457
|
}
|
|
10363
11458
|
function runClaudePrintMode(args2) {
|
|
10364
|
-
return new Promise((
|
|
11459
|
+
return new Promise((resolve3, reject) => {
|
|
10365
11460
|
ensureRunsDir();
|
|
10366
11461
|
const kind = detectKindFromSystemPrompt(args2.systemPrompt);
|
|
10367
11462
|
const runId = newRunId(kind);
|
|
@@ -10492,7 +11587,7 @@ ${args2.reminder}` : args2.userPrompt;
|
|
|
10492
11587
|
reject(new Error(`claude exited ${code}: ${stderr.trim().slice(0, 300)}`));
|
|
10493
11588
|
return;
|
|
10494
11589
|
}
|
|
10495
|
-
|
|
11590
|
+
resolve3({ content: buffer, input_tokens: inputTokens, output_tokens: outputTokens, model: modelUsed });
|
|
10496
11591
|
});
|
|
10497
11592
|
proc.on("error", (err) => {
|
|
10498
11593
|
safeAppend(trace, JSON.stringify({ _meta: { type: "spawn_error", run_id: runId, ts: (/* @__PURE__ */ new Date()).toISOString(), error: err.message } }) + "\n");
|
|
@@ -10697,8 +11792,8 @@ function spendPath() {
|
|
|
10697
11792
|
spendPathCached = cclensPath("llm-spend.jsonl");
|
|
10698
11793
|
return spendPathCached;
|
|
10699
11794
|
}
|
|
10700
|
-
function __setSpendPathForTest(
|
|
10701
|
-
spendPathCached =
|
|
11795
|
+
function __setSpendPathForTest(path7) {
|
|
11796
|
+
spendPathCached = path7;
|
|
10702
11797
|
}
|
|
10703
11798
|
function appendSpend(record) {
|
|
10704
11799
|
const p = spendPath();
|
|
@@ -10748,8 +11843,8 @@ function lockPath() {
|
|
|
10748
11843
|
lockPathCached = cclensPath("llm-interactive.lock");
|
|
10749
11844
|
return lockPathCached;
|
|
10750
11845
|
}
|
|
10751
|
-
function __setInteractiveLockPathForTest(
|
|
10752
|
-
lockPathCached =
|
|
11846
|
+
function __setInteractiveLockPathForTest(path7) {
|
|
11847
|
+
lockPathCached = path7;
|
|
10753
11848
|
}
|
|
10754
11849
|
function touchLock() {
|
|
10755
11850
|
writeFileSync7(lockPath(), String(process.pid), "utf8");
|
|
@@ -10832,10 +11927,10 @@ async function runEnrichmentQueue(settings, opts = {}) {
|
|
|
10832
11927
|
if (monthToDateSpend() >= budget)
|
|
10833
11928
|
return { skipped: "budget_cap_reached" };
|
|
10834
11929
|
const queue = listEntriesWithStatus(["pending", "error"]).filter((e) => (e.enrichment.retry_count ?? 0) < MAX_RETRY_COUNT);
|
|
10835
|
-
const
|
|
11930
|
+
const todayLocal2 = toLocalDay2(now());
|
|
10836
11931
|
let enriched = 0, errors = 0, skipped = 0;
|
|
10837
11932
|
for (const entry of queue) {
|
|
10838
|
-
if (entry.local_day ===
|
|
11933
|
+
if (entry.local_day === todayLocal2) {
|
|
10839
11934
|
skipped++;
|
|
10840
11935
|
continue;
|
|
10841
11936
|
}
|
|
@@ -10906,8 +12001,8 @@ function settingsPath() {
|
|
|
10906
12001
|
settingsPathCached = cclensPath("settings.json");
|
|
10907
12002
|
return settingsPathCached;
|
|
10908
12003
|
}
|
|
10909
|
-
function __setSettingsPathForTest(
|
|
10910
|
-
settingsPathCached =
|
|
12004
|
+
function __setSettingsPathForTest(path7) {
|
|
12005
|
+
settingsPathCached = path7;
|
|
10911
12006
|
}
|
|
10912
12007
|
function toDisk(s) {
|
|
10913
12008
|
return {
|
|
@@ -11144,7 +12239,7 @@ function rollupOutcomeDay(entries2) {
|
|
|
11144
12239
|
return "exploratory";
|
|
11145
12240
|
return "trivial";
|
|
11146
12241
|
}
|
|
11147
|
-
function
|
|
12242
|
+
function truncate5(s, max) {
|
|
11148
12243
|
if (s.length <= max)
|
|
11149
12244
|
return s;
|
|
11150
12245
|
return s.slice(0, max - 1).trimEnd() + "\u2026";
|
|
@@ -11200,7 +12295,7 @@ function computeDaySignals(entries2) {
|
|
|
11200
12295
|
type,
|
|
11201
12296
|
count: v.count,
|
|
11202
12297
|
sample_description: v.sample_description,
|
|
11203
|
-
sample_prompt_preview:
|
|
12298
|
+
sample_prompt_preview: truncate5(v.sample_prompt_preview, 200)
|
|
11204
12299
|
}));
|
|
11205
12300
|
const frameCounts = /* @__PURE__ */ new Map();
|
|
11206
12301
|
for (const s of signalsList) {
|
|
@@ -11219,7 +12314,7 @@ function computeDaySignals(entries2) {
|
|
|
11219
12314
|
if ((e.first_user ?? "").length > 0)
|
|
11220
12315
|
verbosity_distribution[s.verbosity] += 1;
|
|
11221
12316
|
for (const ref of s.external_refs) {
|
|
11222
|
-
external_refs.push({ session_id: e.session_id, kind: ref.kind, preview:
|
|
12317
|
+
external_refs.push({ session_id: e.session_id, kind: ref.kind, preview: truncate5(ref.preview, 200) });
|
|
11223
12318
|
}
|
|
11224
12319
|
const ints = e.numbers.interrupts ?? 0;
|
|
11225
12320
|
interrupts += ints;
|
|
@@ -12092,7 +13187,7 @@ function computeInteractionModes(entries2) {
|
|
|
12092
13187
|
date: entry.local_day,
|
|
12093
13188
|
project_display: prettyProject3(entry.project),
|
|
12094
13189
|
type: sa.type,
|
|
12095
|
-
prompt_preview:
|
|
13190
|
+
prompt_preview: truncate6(sa.prompt_preview, 200)
|
|
12096
13191
|
});
|
|
12097
13192
|
}
|
|
12098
13193
|
const skillExamples = [];
|
|
@@ -12109,7 +13204,7 @@ function computeInteractionModes(entries2) {
|
|
|
12109
13204
|
skillExamples.push({
|
|
12110
13205
|
date: e.local_day,
|
|
12111
13206
|
skill,
|
|
12112
|
-
first_user_preview:
|
|
13207
|
+
first_user_preview: truncate6(e.first_user, 200)
|
|
12113
13208
|
});
|
|
12114
13209
|
}
|
|
12115
13210
|
}
|
|
@@ -12126,7 +13221,7 @@ function computeInteractionModes(entries2) {
|
|
|
12126
13221
|
project_display: prettyProject3(longestTurnEntry.project),
|
|
12127
13222
|
active_min: longestTurnEntry.numbers.active_min,
|
|
12128
13223
|
top_tools: longestTurnEntry.top_tools.slice(0, 5),
|
|
12129
|
-
first_user_preview:
|
|
13224
|
+
first_user_preview: truncate6(longestTurnEntry.first_user, 200)
|
|
12130
13225
|
} : null;
|
|
12131
13226
|
const tools_per_turn = turn_count > 0 ? tools_total / turn_count : 0;
|
|
12132
13227
|
const label = tools_per_turn < 5 ? "rapid" : tools_per_turn < 15 ? "mixed" : "batch";
|
|
@@ -12157,7 +13252,7 @@ function computeInteractionModes(entries2) {
|
|
|
12157
13252
|
}
|
|
12158
13253
|
};
|
|
12159
13254
|
}
|
|
12160
|
-
function
|
|
13255
|
+
function truncate6(s, max) {
|
|
12161
13256
|
if (s.length <= max)
|
|
12162
13257
|
return s;
|
|
12163
13258
|
return s.slice(0, max - 1).trimEnd() + "\u2026";
|
|
@@ -12204,7 +13299,7 @@ function computeWorkingShapes(dayDigests, entriesByDay = /* @__PURE__ */ new Map
|
|
|
12204
13299
|
evidence_subagent = {
|
|
12205
13300
|
type: sa.type,
|
|
12206
13301
|
description: sa.description,
|
|
12207
|
-
prompt_preview:
|
|
13302
|
+
prompt_preview: truncate6(sa.prompt_preview, 200)
|
|
12208
13303
|
};
|
|
12209
13304
|
}
|
|
12210
13305
|
const project_display = repEntry ? prettyProject3(repEntry.project) : dd.projects[0]?.display_name ?? "";
|
|
@@ -12215,7 +13310,7 @@ function computeWorkingShapes(dayDigests, entriesByDay = /* @__PURE__ */ new Map
|
|
|
12215
13310
|
outcome: dayOutcome.get(dd.key) ?? null,
|
|
12216
13311
|
helpfulness: dayHelp.get(dd.key) ?? null,
|
|
12217
13312
|
evidence_subagent,
|
|
12218
|
-
evidence_first_user: repEntry?.first_user ?
|
|
13313
|
+
evidence_first_user: repEntry?.first_user ? truncate6(repEntry.first_user, 200) : null,
|
|
12219
13314
|
day_signature: dd.day_signature ?? null
|
|
12220
13315
|
};
|
|
12221
13316
|
});
|
|
@@ -12290,7 +13385,7 @@ function computeInteractionGrammar(dayDigests, entriesByDay = /* @__PURE__ */ ne
|
|
|
12290
13385
|
date: day2,
|
|
12291
13386
|
session_id: ref.session_id,
|
|
12292
13387
|
ref_kind: ref.kind,
|
|
12293
|
-
preview:
|
|
13388
|
+
preview: truncate6(ref.preview, 200)
|
|
12294
13389
|
});
|
|
12295
13390
|
}
|
|
12296
13391
|
total_interrupts += signals.comm_style.steering.interrupts;
|
|
@@ -12362,7 +13457,7 @@ function computeInteractionGrammar(dayDigests, entriesByDay = /* @__PURE__ */ ne
|
|
|
12362
13457
|
count: v.count,
|
|
12363
13458
|
days: [...v.days].sort(),
|
|
12364
13459
|
sample_description: v.sample_description,
|
|
12365
|
-
sample_prompt_preview:
|
|
13460
|
+
sample_prompt_preview: truncate6(v.sample_prompt_preview, 200)
|
|
12366
13461
|
})),
|
|
12367
13462
|
threads,
|
|
12368
13463
|
communication_style: {
|
|
@@ -13010,7 +14105,7 @@ function activeMs(timestamps) {
|
|
|
13010
14105
|
let active = 0;
|
|
13011
14106
|
for (let i = 1; i < ts.length; i++) {
|
|
13012
14107
|
const dt = ts[i] - ts[i - 1];
|
|
13013
|
-
if (dt <
|
|
14108
|
+
if (dt < IDLE_GAP_MS5)
|
|
13014
14109
|
active += dt;
|
|
13015
14110
|
}
|
|
13016
14111
|
return active;
|
|
@@ -13181,7 +14276,7 @@ function buildSessionSlice(entry, events, daySignature) {
|
|
|
13181
14276
|
let intEnd = sortedTs[0];
|
|
13182
14277
|
for (let i = 1; i < sortedTs.length; i++) {
|
|
13183
14278
|
const dt = sortedTs[i] - intEnd;
|
|
13184
|
-
if (dt >=
|
|
14279
|
+
if (dt >= IDLE_GAP_MS5) {
|
|
13185
14280
|
intervals.push({
|
|
13186
14281
|
start_min: fmtMin(intStart - sliceStartMs),
|
|
13187
14282
|
end_min: fmtMin(intEnd - sliceStartMs)
|
|
@@ -13578,14 +14673,14 @@ async function generateTopSession(slice, opts = {}) {
|
|
|
13578
14673
|
void lastModel;
|
|
13579
14674
|
}
|
|
13580
14675
|
}
|
|
13581
|
-
var
|
|
14676
|
+
var IDLE_GAP_MS5, LONG_AUTONOMOUS_MIN, N_USER, N_FIRST_AGENT, N_LAST_AGENT, N_USER_TURN1, N_SUBAGENT, SHELL_NOISE, INTERRUPT_RE2, PR_TITLE_RE, PinResponseSchema, TopSessionResponseSchema, SYSTEM_PROMPT5, TOP_SESSION_SYSTEM_PROMPT, DEFAULT_MODEL5, defaultCallLLMTopSession, validateTopSession;
|
|
13582
14677
|
var init_top_sessions = __esm({
|
|
13583
14678
|
"../entries/dist/top-sessions.js"() {
|
|
13584
14679
|
"use strict";
|
|
13585
14680
|
init_zod();
|
|
13586
14681
|
init_signals();
|
|
13587
14682
|
init_llm_runner();
|
|
13588
|
-
|
|
14683
|
+
IDLE_GAP_MS5 = 3 * 60 * 1e3;
|
|
13589
14684
|
LONG_AUTONOMOUS_MIN = 20;
|
|
13590
14685
|
N_USER = 150;
|
|
13591
14686
|
N_FIRST_AGENT = 150;
|
|
@@ -14104,6 +15199,10 @@ async function* runMonthDigestPipeline(yearMonth, opts) {
|
|
|
14104
15199
|
} else {
|
|
14105
15200
|
digest2.is_live = true;
|
|
14106
15201
|
setCurrentMonthDigestInCache(yearMonth, digest2, now());
|
|
15202
|
+
if (opts.force === true) {
|
|
15203
|
+
writeMonthDigest(digest2);
|
|
15204
|
+
yield { type: "saved", path: `~/.cclens/digests/month/${yearMonth}.json` };
|
|
15205
|
+
}
|
|
14107
15206
|
}
|
|
14108
15207
|
yield { type: "digest", digest: digest2 };
|
|
14109
15208
|
} finally {
|
|
@@ -14719,16 +15818,12 @@ function bucketToRollup(b) {
|
|
|
14719
15818
|
};
|
|
14720
15819
|
}
|
|
14721
15820
|
function buildRollupsForRange(sessions, sinceDay) {
|
|
14722
|
-
const buckets = dailyActivity(sessions);
|
|
14723
15821
|
const startCounts = /* @__PURE__ */ new Map();
|
|
14724
15822
|
for (const s of sessions) {
|
|
14725
15823
|
const d = sessionDay(s);
|
|
14726
15824
|
if (d) startCounts.set(d, (startCounts.get(d) ?? 0) + 1);
|
|
14727
15825
|
}
|
|
14728
|
-
return
|
|
14729
|
-
...bucketToRollup(b),
|
|
14730
|
-
sessions: startCounts.get(b.date) ?? 0
|
|
14731
|
-
}));
|
|
15826
|
+
return dailyActivity(sessions).filter((b) => !sinceDay || b.date >= sinceDay).map((b) => ({ ...bucketToRollup(b), uniqueSessions: startCounts.get(b.date) ?? 0 }));
|
|
14732
15827
|
}
|
|
14733
15828
|
function dayBoundsMs(day2) {
|
|
14734
15829
|
const [y, m, d] = day2.split("-").map(Number);
|
|
@@ -14754,7 +15849,7 @@ function sessionTouchesDay(s, day2) {
|
|
|
14754
15849
|
}
|
|
14755
15850
|
return sessionDay(s) === day2;
|
|
14756
15851
|
}
|
|
14757
|
-
function buildRichRollupBlocks(day2, daySessions, entries2, privateProjects) {
|
|
15852
|
+
function buildRichRollupBlocks(day2, daySessions, entries2, privateProjects, resolveRepo) {
|
|
14758
15853
|
const bounds = dayBoundsMs(day2);
|
|
14759
15854
|
const clippedSessions = [];
|
|
14760
15855
|
for (const s of daySessions) {
|
|
@@ -14764,16 +15859,40 @@ function buildRichRollupBlocks(day2, daySessions, entries2, privateProjects) {
|
|
|
14764
15859
|
}
|
|
14765
15860
|
const bursts = computeBurstsFromSessions(clippedSessions);
|
|
14766
15861
|
const stats = summarizeBursts(bursts);
|
|
15862
|
+
const repoForEntry = (e) => {
|
|
15863
|
+
if (resolveRepo) {
|
|
15864
|
+
const own = resolveRepo(e.project);
|
|
15865
|
+
if (own) return own;
|
|
15866
|
+
const counts = /* @__PURE__ */ new Map();
|
|
15867
|
+
for (const d of e.edited_dirs ?? []) {
|
|
15868
|
+
const r = resolveRepo(d);
|
|
15869
|
+
if (r) counts.set(r, (counts.get(r) ?? 0) + 1);
|
|
15870
|
+
}
|
|
15871
|
+
const dominant = [...counts.entries()].sort((a, b) => b[1] - a[1])[0]?.[0];
|
|
15872
|
+
if (dominant) return dominant;
|
|
15873
|
+
}
|
|
15874
|
+
return e.github_repos?.length === 1 ? e.github_repos[0] : null;
|
|
15875
|
+
};
|
|
15876
|
+
const sessionRepo = /* @__PURE__ */ new Map();
|
|
15877
|
+
for (const e of entries2) {
|
|
15878
|
+
if (privateProjects.has(projectRepoName(e.project)) || privateProjects.has(e.project)) continue;
|
|
15879
|
+
const r = repoForEntry(e);
|
|
15880
|
+
if (r) sessionRepo.set(e.session_id, r);
|
|
15881
|
+
}
|
|
14767
15882
|
const projects = /* @__PURE__ */ new Map();
|
|
14768
15883
|
for (const s of clippedSessions) {
|
|
14769
|
-
const
|
|
14770
|
-
|
|
15884
|
+
const canonical = canonicalProjectName(s.projectName);
|
|
15885
|
+
const name = projectRepoName(s.projectName);
|
|
15886
|
+
if (privateProjects.has(name) || privateProjects.has(canonical)) continue;
|
|
15887
|
+
const repo = resolveRepo?.(canonical) ?? sessionRepo.get(s.id);
|
|
15888
|
+
const key = repo ?? name;
|
|
14771
15889
|
const ms = s.activeSegments.reduce((sum, seg) => sum + (seg.endMs - seg.startMs), 0);
|
|
14772
|
-
const cur = projects.get(
|
|
15890
|
+
const cur = projects.get(key) ?? { project: name, agentTimeMs: 0, sessions: 0, ...repo ? { resolved: repo } : {} };
|
|
14773
15891
|
cur.agentTimeMs += ms;
|
|
14774
15892
|
cur.sessions += 1;
|
|
14775
|
-
projects.set(
|
|
15893
|
+
projects.set(key, cur);
|
|
14776
15894
|
}
|
|
15895
|
+
const projectRepos = /* @__PURE__ */ new Map();
|
|
14777
15896
|
const workingShapes = /* @__PURE__ */ new Map();
|
|
14778
15897
|
const skills = /* @__PURE__ */ new Map();
|
|
14779
15898
|
const subagents = /* @__PURE__ */ new Map();
|
|
@@ -14787,12 +15906,12 @@ function buildRichRollupBlocks(day2, daySessions, entries2, privateProjects) {
|
|
|
14787
15906
|
let longTotalMin = 0;
|
|
14788
15907
|
let longMaxSingleMin = 0;
|
|
14789
15908
|
for (const e of entries2) {
|
|
14790
|
-
if (privateProjects.has(e.project)) continue;
|
|
15909
|
+
if (privateProjects.has(projectRepoName(e.project)) || privateProjects.has(e.project)) continue;
|
|
14791
15910
|
const shape = e.signals?.working_shape ?? null;
|
|
14792
15911
|
if (shape) {
|
|
14793
15912
|
const cur = workingShapes.get(shape) ?? { sessions: 0, agentTimeMs: 0 };
|
|
14794
15913
|
cur.sessions += 1;
|
|
14795
|
-
cur.agentTimeMs += e.numbers.active_min * 6e4;
|
|
15914
|
+
cur.agentTimeMs += Math.round(e.numbers.active_min * 6e4);
|
|
14796
15915
|
workingShapes.set(shape, cur);
|
|
14797
15916
|
}
|
|
14798
15917
|
for (const [name, count] of Object.entries(e.skills)) {
|
|
@@ -14807,6 +15926,12 @@ function buildRichRollupBlocks(day2, daySessions, entries2, privateProjects) {
|
|
|
14807
15926
|
prs += e.numbers.prs;
|
|
14808
15927
|
commits += e.numbers.commits;
|
|
14809
15928
|
pushes += e.numbers.pushes;
|
|
15929
|
+
if (e.github_repos?.length) {
|
|
15930
|
+
const key = sessionRepo.get(e.session_id) ?? projectRepoName(e.project);
|
|
15931
|
+
const set = projectRepos.get(key) ?? /* @__PURE__ */ new Set();
|
|
15932
|
+
for (const r of e.github_repos) set.add(r);
|
|
15933
|
+
projectRepos.set(key, set);
|
|
15934
|
+
}
|
|
14810
15935
|
if (e.flags.includes("long_autonomous")) {
|
|
14811
15936
|
longCount += 1;
|
|
14812
15937
|
longTotalMin += e.numbers.active_min;
|
|
@@ -14814,11 +15939,21 @@ function buildRichRollupBlocks(day2, daySessions, entries2, privateProjects) {
|
|
|
14814
15939
|
}
|
|
14815
15940
|
}
|
|
14816
15941
|
return {
|
|
14817
|
-
projects: Array.from(projects.entries()).map(([
|
|
15942
|
+
projects: Array.from(projects.entries()).map(([key, v]) => {
|
|
15943
|
+
const extras = [...projectRepos.get(key) ?? []].filter((r) => r !== v.resolved);
|
|
15944
|
+
const repos = v.resolved ? [v.resolved, ...extras] : extras;
|
|
15945
|
+
return {
|
|
15946
|
+
project: v.project,
|
|
15947
|
+
agentTimeMs: v.agentTimeMs,
|
|
15948
|
+
sessions: v.sessions,
|
|
15949
|
+
...repos.length ? { githubRepos: repos.slice(0, 5) } : {}
|
|
15950
|
+
};
|
|
15951
|
+
}).sort((a, b) => b.agentTimeMs - a.agentTimeMs),
|
|
14818
15952
|
workingShapes: Array.from(workingShapes.entries()).map(([shape, v]) => ({ shape, ...v })).sort((a, b) => b.sessions - a.sessions),
|
|
14819
15953
|
concurrencyPeak: stats.peakConcurrent,
|
|
14820
15954
|
parallelMinutes: Math.round(stats.totalParallelMs / 6e4),
|
|
14821
|
-
|
|
15955
|
+
// Wire schema requires integer minutes (active_min is a float).
|
|
15956
|
+
longAutonomous: { count: longCount, totalMin: Math.round(longTotalMin), maxSingleMin: Math.round(longMaxSingleMin) },
|
|
14822
15957
|
toolErrors,
|
|
14823
15958
|
skillsLoaded: Array.from(skills.entries()).map(([name, sessions]) => ({ name, sessions })).sort((a, b) => b.sessions - a.sessions),
|
|
14824
15959
|
subagentsDispatched: Array.from(subagents.entries()).map(([type, count]) => ({ type, count })).sort((a, b) => b.count - a.count),
|
|
@@ -14847,10 +15982,10 @@ function buildEnrichedExtras(entries2) {
|
|
|
14847
15982
|
}
|
|
14848
15983
|
return { outcomeMix, helpfulnessMix, goalMix };
|
|
14849
15984
|
}
|
|
14850
|
-
function buildRichBlocksForDay(day2, daySessions, privateProjects, enrichmentOptIn) {
|
|
15985
|
+
function buildRichBlocksForDay(day2, daySessions, privateProjects, enrichmentOptIn, resolveRepo) {
|
|
14851
15986
|
const entries2 = listEntriesForDay(day2);
|
|
14852
15987
|
if (entries2.length === 0) return void 0;
|
|
14853
|
-
const rich = buildRichRollupBlocks(day2, daySessions, entries2, privateProjects);
|
|
15988
|
+
const rich = buildRichRollupBlocks(day2, daySessions, entries2, privateProjects, resolveRepo);
|
|
14854
15989
|
const enriched = enrichmentOptIn ? buildEnrichedExtras(entries2) : void 0;
|
|
14855
15990
|
return enriched ? { rich, enriched } : { rich };
|
|
14856
15991
|
}
|
|
@@ -14859,10 +15994,11 @@ function buildIngestPayload(inputs) {
|
|
|
14859
15994
|
return {
|
|
14860
15995
|
ingestId: randomUUID2(),
|
|
14861
15996
|
observedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14862
|
-
...richRollup || inputs.enrichedExtras ? { schemaVersion: RICH_ROLLUP_SCHEMA_VERSION } : {},
|
|
15997
|
+
...richRollup || inputs.enrichedExtras || inputs.artifactSignals ? { schemaVersion: RICH_ROLLUP_SCHEMA_VERSION } : {},
|
|
14863
15998
|
...inputs.rollup ? { dailyRollup: inputs.rollup } : {},
|
|
14864
15999
|
...richRollup ? { richRollup } : {},
|
|
14865
16000
|
...inputs.enrichedExtras ? { enrichedExtras: inputs.enrichedExtras } : {},
|
|
16001
|
+
...inputs.artifactSignals ? { artifactSignals: inputs.artifactSignals } : {},
|
|
14866
16002
|
...inputs.usageSnapshot ? { usageSnapshot: inputs.usageSnapshot } : {},
|
|
14867
16003
|
...inputs.planTier ? { planTier: inputs.planTier } : {},
|
|
14868
16004
|
...inputs.cyclePeaks ? { cyclePeaks: inputs.cyclePeaks } : {}
|
|
@@ -14894,15 +16030,83 @@ var init_push = __esm({
|
|
|
14894
16030
|
}
|
|
14895
16031
|
});
|
|
14896
16032
|
|
|
16033
|
+
// src/team/git-remote.ts
|
|
16034
|
+
import { existsSync as existsSync12, readFileSync as readFileSync13, statSync as statSync3 } from "node:fs";
|
|
16035
|
+
import { dirname as dirname9, isAbsolute, join as join10, resolve } from "node:path";
|
|
16036
|
+
function parseGithubRemote(url) {
|
|
16037
|
+
const m = url.trim().match(GITHUB_URL_RE);
|
|
16038
|
+
return m ? `${m[1]}/${m[2]}`.toLowerCase() : null;
|
|
16039
|
+
}
|
|
16040
|
+
function originUrl(configText) {
|
|
16041
|
+
let inOrigin = false;
|
|
16042
|
+
for (const line of configText.split("\n")) {
|
|
16043
|
+
const t = line.trim();
|
|
16044
|
+
if (t.startsWith("[")) {
|
|
16045
|
+
inOrigin = /^\[remote\s+"origin"\]/.test(t);
|
|
16046
|
+
continue;
|
|
16047
|
+
}
|
|
16048
|
+
if (!inOrigin) continue;
|
|
16049
|
+
const m = t.match(/^url\s*=\s*(.+)$/);
|
|
16050
|
+
if (m) return m[1].trim();
|
|
16051
|
+
}
|
|
16052
|
+
return null;
|
|
16053
|
+
}
|
|
16054
|
+
function gitConfigPathFor(dir) {
|
|
16055
|
+
const dotGit = join10(dir, ".git");
|
|
16056
|
+
const st = statSync3(dotGit, { throwIfNoEntry: false });
|
|
16057
|
+
if (!st) return null;
|
|
16058
|
+
if (st.isDirectory()) return join10(dotGit, "config");
|
|
16059
|
+
const m = readFileSync13(dotGit, "utf8").match(/^gitdir:\s*(.+)\s*$/m);
|
|
16060
|
+
if (!m) return null;
|
|
16061
|
+
const gd = isAbsolute(m[1]) ? m[1] : resolve(dir, m[1]);
|
|
16062
|
+
const commondirFile = join10(gd, "commondir");
|
|
16063
|
+
if (existsSync12(commondirFile)) {
|
|
16064
|
+
const common = readFileSync13(commondirFile, "utf8").trim();
|
|
16065
|
+
return join10(isAbsolute(common) ? common : resolve(gd, common), "config");
|
|
16066
|
+
}
|
|
16067
|
+
return join10(gd, "config");
|
|
16068
|
+
}
|
|
16069
|
+
function createRepoResolver() {
|
|
16070
|
+
const cache = /* @__PURE__ */ new Map();
|
|
16071
|
+
return (dir) => {
|
|
16072
|
+
if (!dir || !isAbsolute(dir)) return null;
|
|
16073
|
+
const hit = cache.get(dir);
|
|
16074
|
+
if (hit !== void 0) return hit;
|
|
16075
|
+
let repo = null;
|
|
16076
|
+
try {
|
|
16077
|
+
for (let d = dir; ; d = dirname9(d)) {
|
|
16078
|
+
const config = gitConfigPathFor(d);
|
|
16079
|
+
if (config && existsSync12(config)) {
|
|
16080
|
+
const url = originUrl(readFileSync13(config, "utf8"));
|
|
16081
|
+
repo = url ? parseGithubRemote(url) : null;
|
|
16082
|
+
break;
|
|
16083
|
+
}
|
|
16084
|
+
if (d === dirname9(d)) break;
|
|
16085
|
+
}
|
|
16086
|
+
} catch {
|
|
16087
|
+
repo = null;
|
|
16088
|
+
}
|
|
16089
|
+
cache.set(dir, repo);
|
|
16090
|
+
return repo;
|
|
16091
|
+
};
|
|
16092
|
+
}
|
|
16093
|
+
var GITHUB_URL_RE;
|
|
16094
|
+
var init_git_remote = __esm({
|
|
16095
|
+
"src/team/git-remote.ts"() {
|
|
16096
|
+
"use strict";
|
|
16097
|
+
GITHUB_URL_RE = /github\.com[:/]([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+?)(?:\.git)?$/;
|
|
16098
|
+
}
|
|
16099
|
+
});
|
|
16100
|
+
|
|
14897
16101
|
// src/team/queue.ts
|
|
14898
|
-
import { readFileSync as
|
|
14899
|
-
import { dirname as
|
|
16102
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync9, appendFileSync as appendFileSync4, statSync as statSync4, mkdirSync as mkdirSync10 } from "node:fs";
|
|
16103
|
+
import { dirname as dirname10 } from "node:path";
|
|
14900
16104
|
function enqueuePayload(payload, queuePath = QUEUE_PATH) {
|
|
14901
|
-
mkdirSync10(
|
|
16105
|
+
mkdirSync10(dirname10(queuePath), { recursive: true });
|
|
14902
16106
|
const entry = { payload, enqueuedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
14903
16107
|
appendFileSync4(queuePath, JSON.stringify(entry) + "\n", "utf8");
|
|
14904
16108
|
try {
|
|
14905
|
-
const { size } =
|
|
16109
|
+
const { size } = statSync4(queuePath);
|
|
14906
16110
|
if (size > MAX_SIZE_BYTES) {
|
|
14907
16111
|
pruneOldest(queuePath);
|
|
14908
16112
|
}
|
|
@@ -14912,7 +16116,7 @@ function enqueuePayload(payload, queuePath = QUEUE_PATH) {
|
|
|
14912
16116
|
function dequeuePayloads(queuePath = QUEUE_PATH) {
|
|
14913
16117
|
let lines;
|
|
14914
16118
|
try {
|
|
14915
|
-
lines =
|
|
16119
|
+
lines = readFileSync14(queuePath, "utf8").trim().split("\n").filter(Boolean);
|
|
14916
16120
|
} catch {
|
|
14917
16121
|
return [];
|
|
14918
16122
|
}
|
|
@@ -14933,7 +16137,7 @@ function dequeuePayloads(queuePath = QUEUE_PATH) {
|
|
|
14933
16137
|
function pruneOldest(queuePath) {
|
|
14934
16138
|
let lines;
|
|
14935
16139
|
try {
|
|
14936
|
-
lines =
|
|
16140
|
+
lines = readFileSync14(queuePath, "utf8").trim().split("\n").filter(Boolean);
|
|
14937
16141
|
} catch {
|
|
14938
16142
|
return;
|
|
14939
16143
|
}
|
|
@@ -14952,8 +16156,8 @@ var init_queue2 = __esm({
|
|
|
14952
16156
|
});
|
|
14953
16157
|
|
|
14954
16158
|
// src/usage/profile.ts
|
|
14955
|
-
import { existsSync as
|
|
14956
|
-
import { dirname as
|
|
16159
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync11, readFileSync as readFileSync15, writeFileSync as writeFileSync10 } from "node:fs";
|
|
16160
|
+
import { dirname as dirname11 } from "node:path";
|
|
14957
16161
|
function mapRateLimitTier(rateLimitTier) {
|
|
14958
16162
|
switch (rateLimitTier) {
|
|
14959
16163
|
case "default_claude_pro":
|
|
@@ -14993,9 +16197,9 @@ async function fetchProfile(nowMs = Date.now()) {
|
|
|
14993
16197
|
};
|
|
14994
16198
|
}
|
|
14995
16199
|
function readCachedProfile(cachePath) {
|
|
14996
|
-
if (!
|
|
16200
|
+
if (!existsSync13(cachePath)) return null;
|
|
14997
16201
|
try {
|
|
14998
|
-
const raw = JSON.parse(
|
|
16202
|
+
const raw = JSON.parse(readFileSync15(cachePath, "utf8"));
|
|
14999
16203
|
if (typeof raw.fetchedAtMs !== "number" || !raw.profile) return null;
|
|
15000
16204
|
return raw;
|
|
15001
16205
|
} catch {
|
|
@@ -15003,7 +16207,7 @@ function readCachedProfile(cachePath) {
|
|
|
15003
16207
|
}
|
|
15004
16208
|
}
|
|
15005
16209
|
function writeCachedProfile(cachePath, profile, nowMs = Date.now()) {
|
|
15006
|
-
mkdirSync11(
|
|
16210
|
+
mkdirSync11(dirname11(cachePath), { recursive: true });
|
|
15007
16211
|
writeFileSync10(
|
|
15008
16212
|
cachePath,
|
|
15009
16213
|
JSON.stringify({ fetchedAtMs: nowMs, profile }, null, 2),
|
|
@@ -15185,11 +16389,11 @@ var init_backfill = __esm({
|
|
|
15185
16389
|
|
|
15186
16390
|
// src/team/last-push.ts
|
|
15187
16391
|
import { writeFileSync as writeFileSync11, unlinkSync as unlinkSync5, mkdirSync as mkdirSync12 } from "node:fs";
|
|
15188
|
-
import { join as
|
|
16392
|
+
import { join as join11 } from "node:path";
|
|
15189
16393
|
function write(record, dir) {
|
|
15190
16394
|
const d = dir ?? cclensHome();
|
|
15191
16395
|
mkdirSync12(d, { recursive: true });
|
|
15192
|
-
writeFileSync11(
|
|
16396
|
+
writeFileSync11(join11(d, LAST_PUSH_FILE), JSON.stringify(record, null, 2), { mode: 384 });
|
|
15193
16397
|
}
|
|
15194
16398
|
function writeLastPushSuccess(payload, dir) {
|
|
15195
16399
|
write({ pushedAt: (/* @__PURE__ */ new Date()).toISOString(), ok: true, payload }, dir);
|
|
@@ -15200,7 +16404,7 @@ function writeLastPushFailure(payload, error, dir) {
|
|
|
15200
16404
|
function clearLastPush(dir) {
|
|
15201
16405
|
const d = dir ?? cclensHome();
|
|
15202
16406
|
try {
|
|
15203
|
-
unlinkSync5(
|
|
16407
|
+
unlinkSync5(join11(d, LAST_PUSH_FILE));
|
|
15204
16408
|
} catch {
|
|
15205
16409
|
}
|
|
15206
16410
|
}
|
|
@@ -15213,6 +16417,194 @@ var init_last_push = __esm({
|
|
|
15213
16417
|
}
|
|
15214
16418
|
});
|
|
15215
16419
|
|
|
16420
|
+
// src/perception/file-probe.ts
|
|
16421
|
+
var file_probe_exports = {};
|
|
16422
|
+
__export(file_probe_exports, {
|
|
16423
|
+
pathHash: () => pathHash,
|
|
16424
|
+
probeArtifactSignals: () => probeArtifactSignals
|
|
16425
|
+
});
|
|
16426
|
+
import { createHash } from "node:crypto";
|
|
16427
|
+
import { existsSync as existsSync14, readdirSync as readdirSync4, statSync as statSync5 } from "node:fs";
|
|
16428
|
+
import { homedir as homedir4 } from "node:os";
|
|
16429
|
+
import { join as join12, relative, resolve as resolve2, sep } from "node:path";
|
|
16430
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
16431
|
+
function pathHash(relPath) {
|
|
16432
|
+
return createHash("sha256").update(relPath.split(sep).join("/")).digest("hex").slice(0, 32);
|
|
16433
|
+
}
|
|
16434
|
+
function defaultScanRoots(extraRoots = []) {
|
|
16435
|
+
const roots = [];
|
|
16436
|
+
const home = join12(homedir4(), ".claude");
|
|
16437
|
+
if (existsSync14(home)) roots.push({ root: home, label: "user" });
|
|
16438
|
+
for (const e of extraRoots) {
|
|
16439
|
+
const r = resolve2(e, ".claude");
|
|
16440
|
+
if (existsSync14(r) && r !== home) roots.push({ root: r, label: "project" });
|
|
16441
|
+
}
|
|
16442
|
+
return roots;
|
|
16443
|
+
}
|
|
16444
|
+
function listMarkdownFiles(dir) {
|
|
16445
|
+
if (!existsSync14(dir)) return [];
|
|
16446
|
+
const out = [];
|
|
16447
|
+
let entries2;
|
|
16448
|
+
try {
|
|
16449
|
+
entries2 = readdirSync4(dir);
|
|
16450
|
+
} catch {
|
|
16451
|
+
return [];
|
|
16452
|
+
}
|
|
16453
|
+
for (const name of entries2) {
|
|
16454
|
+
if (name.startsWith(".")) continue;
|
|
16455
|
+
const full = join12(dir, name);
|
|
16456
|
+
let stat;
|
|
16457
|
+
try {
|
|
16458
|
+
stat = statSync5(full);
|
|
16459
|
+
} catch {
|
|
16460
|
+
continue;
|
|
16461
|
+
}
|
|
16462
|
+
if (stat.isDirectory()) {
|
|
16463
|
+
out.push(...listMarkdownFiles(full));
|
|
16464
|
+
} else if (stat.isFile() && name.endsWith(".md")) {
|
|
16465
|
+
out.push(full);
|
|
16466
|
+
}
|
|
16467
|
+
}
|
|
16468
|
+
return out;
|
|
16469
|
+
}
|
|
16470
|
+
function firstSeenDateOf(file) {
|
|
16471
|
+
try {
|
|
16472
|
+
const out = execFileSync2(
|
|
16473
|
+
"git",
|
|
16474
|
+
["log", "--diff-filter=A", "--follow", "--format=%cs", "--", file],
|
|
16475
|
+
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd: dirname12(file) }
|
|
16476
|
+
).trim().split("\n").filter(Boolean);
|
|
16477
|
+
if (out.length > 0) return out[out.length - 1];
|
|
16478
|
+
} catch {
|
|
16479
|
+
}
|
|
16480
|
+
try {
|
|
16481
|
+
const s = statSync5(file);
|
|
16482
|
+
return new Date((s.birthtime || s.mtime).getTime()).toISOString().slice(0, 10);
|
|
16483
|
+
} catch {
|
|
16484
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
16485
|
+
}
|
|
16486
|
+
}
|
|
16487
|
+
function dirname12(p) {
|
|
16488
|
+
const i = p.lastIndexOf(sep);
|
|
16489
|
+
return i < 0 ? "." : p.slice(0, i);
|
|
16490
|
+
}
|
|
16491
|
+
function detectGitEmail(cwd) {
|
|
16492
|
+
try {
|
|
16493
|
+
return execFileSync2("git", ["config", "user.email"], {
|
|
16494
|
+
encoding: "utf8",
|
|
16495
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
16496
|
+
cwd
|
|
16497
|
+
}).trim() || null;
|
|
16498
|
+
} catch {
|
|
16499
|
+
return null;
|
|
16500
|
+
}
|
|
16501
|
+
}
|
|
16502
|
+
function todayLocal() {
|
|
16503
|
+
const d = /* @__PURE__ */ new Date();
|
|
16504
|
+
const y = d.getFullYear();
|
|
16505
|
+
const m = String(d.getMonth() + 1).padStart(2, "0");
|
|
16506
|
+
const day2 = String(d.getDate()).padStart(2, "0");
|
|
16507
|
+
return `${y}-${m}-${day2}`;
|
|
16508
|
+
}
|
|
16509
|
+
function scanAuthored(roots, subdir, day2) {
|
|
16510
|
+
const out = [];
|
|
16511
|
+
for (const r of roots) {
|
|
16512
|
+
const dir = join12(r.root, subdir);
|
|
16513
|
+
if (!existsSync14(dir)) continue;
|
|
16514
|
+
for (const f of listMarkdownFiles(dir)) {
|
|
16515
|
+
const firstSeen = firstSeenDateOf(f);
|
|
16516
|
+
if (firstSeen !== day2) continue;
|
|
16517
|
+
const rel = relative(dir, f);
|
|
16518
|
+
out.push({ pathHash: pathHash(`${r.label}:${subdir}:${rel}`), firstSeenDate: firstSeen });
|
|
16519
|
+
}
|
|
16520
|
+
}
|
|
16521
|
+
return out;
|
|
16522
|
+
}
|
|
16523
|
+
function scanEdited(roots, day2) {
|
|
16524
|
+
const out = [];
|
|
16525
|
+
for (const r of roots) {
|
|
16526
|
+
const dir = join12(r.root, "skills");
|
|
16527
|
+
if (!existsSync14(dir)) continue;
|
|
16528
|
+
for (const f of listMarkdownFiles(dir)) {
|
|
16529
|
+
const firstSeen = firstSeenDateOf(f);
|
|
16530
|
+
if (firstSeen === day2) continue;
|
|
16531
|
+
let stat;
|
|
16532
|
+
try {
|
|
16533
|
+
stat = statSync5(f);
|
|
16534
|
+
} catch {
|
|
16535
|
+
continue;
|
|
16536
|
+
}
|
|
16537
|
+
const mtimeDay = new Date(stat.mtime.getTime()).toISOString().slice(0, 10);
|
|
16538
|
+
if (mtimeDay !== day2) continue;
|
|
16539
|
+
const rel = relative(dir, f);
|
|
16540
|
+
out.push({ pathHash: pathHash(`${r.label}:skills:${rel}`), lineDelta: 0 });
|
|
16541
|
+
}
|
|
16542
|
+
}
|
|
16543
|
+
return out;
|
|
16544
|
+
}
|
|
16545
|
+
function claudemdLineDelta(extraRoots, authorEmail, day2) {
|
|
16546
|
+
let delta = 0;
|
|
16547
|
+
const candidates = [];
|
|
16548
|
+
for (const e of extraRoots) {
|
|
16549
|
+
const f = resolve2(e, "CLAUDE.md");
|
|
16550
|
+
if (existsSync14(f)) candidates.push(f);
|
|
16551
|
+
}
|
|
16552
|
+
const homeClaudeMd = join12(homedir4(), "CLAUDE.md");
|
|
16553
|
+
if (existsSync14(homeClaudeMd)) candidates.push(homeClaudeMd);
|
|
16554
|
+
for (const file of candidates) {
|
|
16555
|
+
try {
|
|
16556
|
+
const out = execFileSync2(
|
|
16557
|
+
"git",
|
|
16558
|
+
["log", "--numstat", "--format=COMMIT %cs %ae", "--", file],
|
|
16559
|
+
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd: dirname12(file) }
|
|
16560
|
+
);
|
|
16561
|
+
let currentDate = "";
|
|
16562
|
+
let currentEmail = "";
|
|
16563
|
+
for (const line of out.split("\n")) {
|
|
16564
|
+
if (line.startsWith("COMMIT ")) {
|
|
16565
|
+
const parts = line.slice("COMMIT ".length).trim().split(/\s+/);
|
|
16566
|
+
currentDate = parts[0] ?? "";
|
|
16567
|
+
currentEmail = parts.slice(1).join(" ");
|
|
16568
|
+
} else if (currentDate === day2 && line.trim().length > 0) {
|
|
16569
|
+
if (authorEmail && currentEmail !== authorEmail) continue;
|
|
16570
|
+
const parts = line.split(/\s+/);
|
|
16571
|
+
const added = Number(parts[0]);
|
|
16572
|
+
const removed = Number(parts[1]);
|
|
16573
|
+
if (Number.isFinite(added) && Number.isFinite(removed)) {
|
|
16574
|
+
delta += added - removed;
|
|
16575
|
+
}
|
|
16576
|
+
}
|
|
16577
|
+
}
|
|
16578
|
+
} catch {
|
|
16579
|
+
}
|
|
16580
|
+
}
|
|
16581
|
+
return delta;
|
|
16582
|
+
}
|
|
16583
|
+
function probeArtifactSignals(opts = {}) {
|
|
16584
|
+
const day2 = opts.day ?? todayLocal();
|
|
16585
|
+
const roots = defaultScanRoots(opts.extraRoots);
|
|
16586
|
+
const skillsAuthored = scanAuthored(roots, "skills", day2);
|
|
16587
|
+
const subagentsAuthored = scanAuthored(roots, "agents", day2);
|
|
16588
|
+
const slashCommandsAuthored = scanAuthored(roots, "commands", day2);
|
|
16589
|
+
const skillsEdited = scanEdited(roots, day2);
|
|
16590
|
+
const authorEmail = opts.authorEmail ?? detectGitEmail(opts.extraRoots?.[0] ?? process.cwd()) ?? void 0;
|
|
16591
|
+
const claudemd = claudemdLineDelta(opts.extraRoots ?? [], authorEmail, day2);
|
|
16592
|
+
const empty = skillsAuthored.length === 0 && subagentsAuthored.length === 0 && slashCommandsAuthored.length === 0 && skillsEdited.length === 0 && claudemd === 0;
|
|
16593
|
+
if (empty) return null;
|
|
16594
|
+
return {
|
|
16595
|
+
skillsAuthored,
|
|
16596
|
+
skillsEdited,
|
|
16597
|
+
subagentsAuthored,
|
|
16598
|
+
slashCommandsAuthored,
|
|
16599
|
+
claudemdLineDelta: claudemd
|
|
16600
|
+
};
|
|
16601
|
+
}
|
|
16602
|
+
var init_file_probe = __esm({
|
|
16603
|
+
"src/perception/file-probe.ts"() {
|
|
16604
|
+
"use strict";
|
|
16605
|
+
}
|
|
16606
|
+
});
|
|
16607
|
+
|
|
15216
16608
|
// src/team/commands.ts
|
|
15217
16609
|
async function dispatchCommand(command2, config, log) {
|
|
15218
16610
|
switch (command2.type) {
|
|
@@ -15230,6 +16622,7 @@ async function dispatchCommand(command2, config, log) {
|
|
|
15230
16622
|
async function runActivityBackfill(command2, config, log) {
|
|
15231
16623
|
const { listSessions: listSessions2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
15232
16624
|
const { toLocalDay: toLocalDay4 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
|
|
16625
|
+
const { probeArtifactSignals: probeArtifactSignals2 } = await Promise.resolve().then(() => (init_file_probe(), file_probe_exports));
|
|
15233
16626
|
const days = command2.params.days;
|
|
15234
16627
|
const todayMs = Date.now();
|
|
15235
16628
|
const targetDayMs = todayMs - (days - 1) * 24 * 60 * 60 * 1e3;
|
|
@@ -15255,9 +16648,24 @@ async function runActivityBackfill(command2, config, log) {
|
|
|
15255
16648
|
summary: { pushed: 0, fromDay: targetDay }
|
|
15256
16649
|
};
|
|
15257
16650
|
}
|
|
16651
|
+
const privateProjects = new Set(config.privateProjects ?? []);
|
|
16652
|
+
const enrichmentOptIn = !!config.enrichmentOptIn;
|
|
16653
|
+
const resolveRepo = createRepoResolver();
|
|
15258
16654
|
let pushed = 0;
|
|
15259
16655
|
for (const rollup of rollups) {
|
|
15260
|
-
const
|
|
16656
|
+
const daySessions = sessions.filter((s) => sessionTouchesDay(s, rollup.day));
|
|
16657
|
+
const richBlocks = buildRichBlocksForDay(rollup.day, daySessions, privateProjects, enrichmentOptIn, resolveRepo);
|
|
16658
|
+
let artifactSignals = null;
|
|
16659
|
+
try {
|
|
16660
|
+
artifactSignals = probeArtifactSignals2({ day: rollup.day, extraRoots: [process.cwd()] });
|
|
16661
|
+
} catch {
|
|
16662
|
+
}
|
|
16663
|
+
const payload = buildIngestPayload({
|
|
16664
|
+
rollup,
|
|
16665
|
+
richExtras: richBlocks?.rich,
|
|
16666
|
+
enrichedExtras: richBlocks?.enriched,
|
|
16667
|
+
artifactSignals: artifactSignals ?? void 0
|
|
16668
|
+
});
|
|
15261
16669
|
const result = await pushToTeamServer(config, payload);
|
|
15262
16670
|
if (!result.ok) {
|
|
15263
16671
|
return {
|
|
@@ -15281,6 +16689,7 @@ var init_commands = __esm({
|
|
|
15281
16689
|
"src/team/commands.ts"() {
|
|
15282
16690
|
"use strict";
|
|
15283
16691
|
init_push();
|
|
16692
|
+
init_git_remote();
|
|
15284
16693
|
}
|
|
15285
16694
|
});
|
|
15286
16695
|
|
|
@@ -15388,6 +16797,8 @@ async function runTeamSync(log = noopLog2, configOverride, options = {}) {
|
|
|
15388
16797
|
let lastPushedDay;
|
|
15389
16798
|
const privateProjects = new Set(config.privateProjects ?? []);
|
|
15390
16799
|
const enrichmentOptIn = !!config.enrichmentOptIn;
|
|
16800
|
+
const resolveRepo = createRepoResolver();
|
|
16801
|
+
const { probeArtifactSignals: probeArtifactSignals2 } = await Promise.resolve().then(() => (init_file_probe(), file_probe_exports));
|
|
15391
16802
|
for (let i = 0; i < rollups.length; i++) {
|
|
15392
16803
|
const rollup = rollups[i];
|
|
15393
16804
|
const isLatest = i === rollups.length - 1;
|
|
@@ -15396,12 +16807,22 @@ async function runTeamSync(log = noopLog2, configOverride, options = {}) {
|
|
|
15396
16807
|
rollup.day,
|
|
15397
16808
|
daySessions,
|
|
15398
16809
|
privateProjects,
|
|
15399
|
-
enrichmentOptIn
|
|
16810
|
+
enrichmentOptIn,
|
|
16811
|
+
resolveRepo
|
|
15400
16812
|
);
|
|
16813
|
+
let artifactSignals = null;
|
|
16814
|
+
try {
|
|
16815
|
+
artifactSignals = probeArtifactSignals2({
|
|
16816
|
+
day: rollup.day,
|
|
16817
|
+
extraRoots: [process.cwd()]
|
|
16818
|
+
});
|
|
16819
|
+
} catch {
|
|
16820
|
+
}
|
|
15401
16821
|
const payload = buildIngestPayload({
|
|
15402
16822
|
rollup,
|
|
15403
16823
|
richExtras: richBlocks?.rich,
|
|
15404
16824
|
enrichedExtras: richBlocks?.enriched,
|
|
16825
|
+
artifactSignals: artifactSignals ?? void 0,
|
|
15405
16826
|
usageSnapshot: isLatest ? usageSnapshot : void 0,
|
|
15406
16827
|
planTier,
|
|
15407
16828
|
// Same rationale as usageSnapshot — current cycle data only on the
|
|
@@ -15522,6 +16943,7 @@ var init_sync = __esm({
|
|
|
15522
16943
|
"use strict";
|
|
15523
16944
|
init_config();
|
|
15524
16945
|
init_push();
|
|
16946
|
+
init_git_remote();
|
|
15525
16947
|
init_queue2();
|
|
15526
16948
|
init_backfill();
|
|
15527
16949
|
init_last_push();
|
|
@@ -15677,11 +17099,11 @@ var logs_exports = {};
|
|
|
15677
17099
|
__export(logs_exports, {
|
|
15678
17100
|
teamLogs: () => teamLogs
|
|
15679
17101
|
});
|
|
15680
|
-
import { readFileSync as
|
|
17102
|
+
import { readFileSync as readFileSync16 } from "node:fs";
|
|
15681
17103
|
async function teamLogs() {
|
|
15682
17104
|
const logPath = cclensPath("daemon.log");
|
|
15683
17105
|
try {
|
|
15684
|
-
const lines =
|
|
17106
|
+
const lines = readFileSync16(logPath, "utf8").trim().split("\n");
|
|
15685
17107
|
const teamLines = lines.filter((l) => l.includes("team "));
|
|
15686
17108
|
if (teamLines.length === 0) {
|
|
15687
17109
|
console.log("No team-related log entries found.");
|
|
@@ -15787,8 +17209,8 @@ __export(runs_exports, {
|
|
|
15787
17209
|
runs: () => runs
|
|
15788
17210
|
});
|
|
15789
17211
|
import { execSync as execSync2 } from "node:child_process";
|
|
15790
|
-
import { existsSync as
|
|
15791
|
-
import { join as
|
|
17212
|
+
import { existsSync as existsSync15, readFileSync as readFileSync17, readdirSync as readdirSync5, statSync as statSync6 } from "node:fs";
|
|
17213
|
+
import { join as join13 } from "node:path";
|
|
15792
17214
|
async function runs(args2) {
|
|
15793
17215
|
const json = args2.includes("--json");
|
|
15794
17216
|
const watch = args2.includes("--watch");
|
|
@@ -15872,8 +17294,8 @@ function listActiveRuns() {
|
|
|
15872
17294
|
return runs2.sort((a, b) => a.elapsed_s - b.elapsed_s);
|
|
15873
17295
|
}
|
|
15874
17296
|
function readSpend(sinceMs) {
|
|
15875
|
-
if (!
|
|
15876
|
-
const lines =
|
|
17297
|
+
if (!existsSync15(SPEND_PATH)) return [];
|
|
17298
|
+
const lines = readFileSync17(SPEND_PATH, "utf-8").split("\n").filter((l) => l.trim());
|
|
15877
17299
|
const out = [];
|
|
15878
17300
|
for (const line of lines) {
|
|
15879
17301
|
try {
|
|
@@ -15994,23 +17416,23 @@ function ageLabel(ms) {
|
|
|
15994
17416
|
return `${Math.floor(ms / 864e5)}d`;
|
|
15995
17417
|
}
|
|
15996
17418
|
function listTraceFiles() {
|
|
15997
|
-
if (!
|
|
15998
|
-
const entries2 =
|
|
17419
|
+
if (!existsSync15(RUNS_DIR2)) return [];
|
|
17420
|
+
const entries2 = readdirSync5(RUNS_DIR2).filter((f) => f.endsWith(".jsonl"));
|
|
15999
17421
|
return entries2.map((f) => {
|
|
16000
|
-
const
|
|
16001
|
-
const st =
|
|
16002
|
-
return { runId: f.replace(/\.jsonl$/, ""), path:
|
|
17422
|
+
const path7 = join13(RUNS_DIR2, f);
|
|
17423
|
+
const st = statSync6(path7);
|
|
17424
|
+
return { runId: f.replace(/\.jsonl$/, ""), path: path7, mtimeMs: st.mtimeMs };
|
|
16003
17425
|
}).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
16004
17426
|
}
|
|
16005
17427
|
function resolveRunId(arg) {
|
|
16006
|
-
if (!
|
|
17428
|
+
if (!existsSync15(RUNS_DIR2)) return null;
|
|
16007
17429
|
if (arg === "latest") {
|
|
16008
17430
|
const all2 = listTraceFiles();
|
|
16009
17431
|
if (all2.length === 0) return null;
|
|
16010
17432
|
return { runId: all2[0].runId, path: all2[0].path };
|
|
16011
17433
|
}
|
|
16012
|
-
const exact =
|
|
16013
|
-
if (
|
|
17434
|
+
const exact = join13(RUNS_DIR2, `${arg}.jsonl`);
|
|
17435
|
+
if (existsSync15(exact)) return { runId: arg, path: exact };
|
|
16014
17436
|
const all = listTraceFiles();
|
|
16015
17437
|
const matches = all.filter((r) => r.runId.includes(arg));
|
|
16016
17438
|
if (matches.length === 1) return { runId: matches[0].runId, path: matches[0].path };
|
|
@@ -16021,8 +17443,8 @@ function resolveRunId(arg) {
|
|
|
16021
17443
|
}
|
|
16022
17444
|
return null;
|
|
16023
17445
|
}
|
|
16024
|
-
function readTrace(
|
|
16025
|
-
return
|
|
17446
|
+
function readTrace(path7) {
|
|
17447
|
+
return readFileSync17(path7, "utf-8").split("\n").filter((l) => l.trim()).map((l) => {
|
|
16026
17448
|
try {
|
|
16027
17449
|
return JSON.parse(l);
|
|
16028
17450
|
} catch {
|
|
@@ -16034,7 +17456,7 @@ async function inspect(arg, follow, json) {
|
|
|
16034
17456
|
const r = resolveRunId(arg);
|
|
16035
17457
|
if (!r) {
|
|
16036
17458
|
console.error(`run not found: ${arg}`);
|
|
16037
|
-
if (
|
|
17459
|
+
if (existsSync15(RUNS_DIR2)) {
|
|
16038
17460
|
const all = listTraceFiles().slice(0, 5);
|
|
16039
17461
|
if (all.length > 0) {
|
|
16040
17462
|
console.error(`
|
|
@@ -16054,13 +17476,13 @@ recent runs:`);
|
|
|
16054
17476
|
const events = readTrace(r.path);
|
|
16055
17477
|
printTrace(r.runId, events);
|
|
16056
17478
|
if (!follow) return;
|
|
16057
|
-
let lastSize =
|
|
17479
|
+
let lastSize = statSync6(r.path).size;
|
|
16058
17480
|
let lastIdx = events.length;
|
|
16059
17481
|
console.log("\n \u27F6 following \xB7 ^C to quit\n");
|
|
16060
17482
|
process.on("SIGINT", () => process.exit(0));
|
|
16061
17483
|
while (true) {
|
|
16062
17484
|
await new Promise((res) => setTimeout(res, 500));
|
|
16063
|
-
const st =
|
|
17485
|
+
const st = statSync6(r.path);
|
|
16064
17486
|
if (st.size === lastSize) continue;
|
|
16065
17487
|
lastSize = st.size;
|
|
16066
17488
|
const all = readTrace(r.path);
|
|
@@ -16204,7 +17626,7 @@ async function main() {
|
|
|
16204
17626
|
case "version":
|
|
16205
17627
|
case "--version":
|
|
16206
17628
|
case "-v":
|
|
16207
|
-
console.log(`fleetlens ${"0.
|
|
17629
|
+
console.log(`fleetlens ${"0.12.1"}`);
|
|
16208
17630
|
break;
|
|
16209
17631
|
case "help":
|
|
16210
17632
|
case "--help":
|