fleetlens 0.11.2 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/apps/web/.next/BUILD_ID +1 -1
- package/app/apps/web/.next/app-path-routes-manifest.json +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.nft.json +1 -1
- package/app/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/api/ask/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js +1 -1
- package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js +1 -1
- package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/month-index/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js +1 -1
- package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/week-index/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/events/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/jobs/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/pdf/[key]/route/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.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/runs/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/settings/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/team-config/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/workflow-agent/route/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.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.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.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.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.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.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.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.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.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 +18 -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.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.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.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.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.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.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.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.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_04rh1zd._.js +1 -1
- package/app/apps/web/.next/server/chunks/packages_parser_dist_0ndsxe6._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0_xpuh7._.js → [root-of-the-server]__03y~03u._.js} +2 -2
- 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]__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_0af94gl._.js +1 -1
- 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/WH20Ct_NdpZTKsqI_yquG/_clientMiddlewareManifest.js +6 -0
- package/app/apps/web/.next/static/chunks/00xkqnvk4-d1-.js +10 -0
- package/app/apps/web/.next/static/chunks/0716x58e1_2c5.js +1 -0
- package/app/apps/web/.next/static/chunks/{0s4eyofh28l~u.js → 0ck03i0l4zeun.js} +1 -1
- 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/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 +1592 -252
- package/dist/index.js +1495 -168
- package/package.json +1 -1
- 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/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/0uev~g~qvbjv9.js +0 -4
- package/app/apps/web/.next/static/m6ibRSdAu8jD10VBA2OFH/_clientMiddlewareManifest.js +0 -1
- /package/app/apps/web/.next/static/{m6ibRSdAu8jD10VBA2OFH → WH20Ct_NdpZTKsqI_yquG}/_buildManifest.js +0 -0
- /package/app/apps/web/.next/static/{m6ibRSdAu8jD10VBA2OFH → WH20Ct_NdpZTKsqI_yquG}/_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,
|
|
@@ -534,13 +555,13 @@ function summarizeBursts(bursts) {
|
|
|
534
555
|
function groupByProject(sessions) {
|
|
535
556
|
const map = /* @__PURE__ */ new Map();
|
|
536
557
|
for (const s of sessions) {
|
|
537
|
-
const
|
|
538
|
-
const key =
|
|
558
|
+
const repo = projectRepoName(s.projectName);
|
|
559
|
+
const key = repo;
|
|
539
560
|
let cur = map.get(key);
|
|
540
561
|
if (!cur) {
|
|
541
562
|
cur = {
|
|
542
|
-
projectDir:
|
|
543
|
-
projectName:
|
|
563
|
+
projectDir: repo,
|
|
564
|
+
projectName: repo,
|
|
544
565
|
sessions: [],
|
|
545
566
|
rawProjectDirs: [],
|
|
546
567
|
worktreeCount: 0,
|
|
@@ -582,7 +603,7 @@ function groupByProject(sessions) {
|
|
|
582
603
|
}
|
|
583
604
|
return Array.from(map.values()).sort((a, b) => (b.lastActiveMs ?? 0) - (a.lastActiveMs ?? 0));
|
|
584
605
|
}
|
|
585
|
-
var BLANK_USAGE, WORKTREE_MARKERS, CONDUCTOR_RE, PR_CREATE_RE, PR_NUMBER_RE, TITLE_FLAG_RE;
|
|
606
|
+
var BLANK_USAGE, WORKTREE_MARKERS, CONDUCTOR_RE, SUPERSET_MARKER, UUID_SEG_RE, PR_CREATE_RE, PR_NUMBER_RE, TITLE_FLAG_RE;
|
|
586
607
|
var init_analytics = __esm({
|
|
587
608
|
"../parser/dist/analytics.js"() {
|
|
588
609
|
"use strict";
|
|
@@ -593,6 +614,8 @@ var init_analytics = __esm({
|
|
|
593
614
|
"/claude/worktrees/"
|
|
594
615
|
];
|
|
595
616
|
CONDUCTOR_RE = /\/conductor\/workspaces\/[^/]+\/([^/]+)(?:\/|$)/;
|
|
617
|
+
SUPERSET_MARKER = "/.superset/worktrees/";
|
|
618
|
+
UUID_SEG_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
596
619
|
PR_CREATE_RE = /gh\s+pr\s+create\b/i;
|
|
597
620
|
PR_NUMBER_RE = /#(\d+)/;
|
|
598
621
|
TITLE_FLAG_RE = /--title\s+["']([^"']+)["']/;
|
|
@@ -606,7 +629,7 @@ function getAgentMetadata(kind) {
|
|
|
606
629
|
function isAgentKind(s) {
|
|
607
630
|
return typeof s === "string" && KNOWN_AGENT_KINDS.has(s);
|
|
608
631
|
}
|
|
609
|
-
var CLAUDE_CODE_METADATA, CODEX_METADATA, GEMINI_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
|
|
632
|
+
var CLAUDE_CODE_METADATA, CODEX_METADATA, GEMINI_METADATA, ANTIGRAVITY_METADATA, COWORK_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
|
|
610
633
|
var init_agent_metadata = __esm({
|
|
611
634
|
"../parser/dist/agent-metadata.js"() {
|
|
612
635
|
"use strict";
|
|
@@ -631,10 +654,26 @@ var init_agent_metadata = __esm({
|
|
|
631
654
|
accentColor: "rgb(124, 92, 246)",
|
|
632
655
|
iconChar: "\u273A"
|
|
633
656
|
};
|
|
657
|
+
ANTIGRAVITY_METADATA = {
|
|
658
|
+
kind: "antigravity",
|
|
659
|
+
displayName: "Antigravity",
|
|
660
|
+
shortLabel: "Agy",
|
|
661
|
+
accentColor: "rgb(236, 72, 153)",
|
|
662
|
+
iconChar: "\u23C3"
|
|
663
|
+
};
|
|
664
|
+
COWORK_METADATA = {
|
|
665
|
+
kind: "cowork",
|
|
666
|
+
displayName: "Cowork",
|
|
667
|
+
shortLabel: "Cowork",
|
|
668
|
+
accentColor: "rgb(217, 119, 87)",
|
|
669
|
+
iconChar: "\u2318"
|
|
670
|
+
};
|
|
634
671
|
agentMetadata = [
|
|
635
672
|
CLAUDE_CODE_METADATA,
|
|
636
673
|
CODEX_METADATA,
|
|
637
|
-
GEMINI_METADATA
|
|
674
|
+
GEMINI_METADATA,
|
|
675
|
+
ANTIGRAVITY_METADATA,
|
|
676
|
+
COWORK_METADATA
|
|
638
677
|
];
|
|
639
678
|
KNOWN_AGENT_KINDS = new Set(agentMetadata.map((m) => m.kind));
|
|
640
679
|
}
|
|
@@ -1660,6 +1699,52 @@ async function computeSessionUsageWithSubagents(parentLines, projectDirPath, ses
|
|
|
1660
1699
|
}));
|
|
1661
1700
|
return usage2;
|
|
1662
1701
|
}
|
|
1702
|
+
async function scanWorkflowAggregate(projectDirPath, sessionId) {
|
|
1703
|
+
const dir = path.join(projectDirPath, sessionId, "workflows");
|
|
1704
|
+
let entries2;
|
|
1705
|
+
try {
|
|
1706
|
+
entries2 = await fs.readdir(dir);
|
|
1707
|
+
} catch {
|
|
1708
|
+
return { workflowCount: 0, spawnedAgentCount: 0, spans: [] };
|
|
1709
|
+
}
|
|
1710
|
+
const jsonFiles = entries2.filter((f) => f.startsWith("wf_") && f.endsWith(".json"));
|
|
1711
|
+
if (jsonFiles.length === 0)
|
|
1712
|
+
return { workflowCount: 0, spawnedAgentCount: 0, spans: [] };
|
|
1713
|
+
let spawnedAgentCount = 0;
|
|
1714
|
+
const spans = [];
|
|
1715
|
+
const parsed = await Promise.all(jsonFiles.map(async (f) => {
|
|
1716
|
+
try {
|
|
1717
|
+
const j = JSON.parse(await fs.readFile(path.join(dir, f), "utf8"));
|
|
1718
|
+
if (typeof j.agentCount === "number")
|
|
1719
|
+
spawnedAgentCount += j.agentCount;
|
|
1720
|
+
if (typeof j.startTime === "number" && typeof j.durationMs === "number" && j.durationMs > 0) {
|
|
1721
|
+
spans.push({ startMs: j.startTime, endMs: j.startTime + j.durationMs });
|
|
1722
|
+
}
|
|
1723
|
+
return true;
|
|
1724
|
+
} catch {
|
|
1725
|
+
return false;
|
|
1726
|
+
}
|
|
1727
|
+
}));
|
|
1728
|
+
return { workflowCount: parsed.filter(Boolean).length, spawnedAgentCount, spans };
|
|
1729
|
+
}
|
|
1730
|
+
function foldWorkflowAgentTime(activeSegments, spans) {
|
|
1731
|
+
if (spans.length === 0)
|
|
1732
|
+
return {};
|
|
1733
|
+
const all = [...activeSegments ?? [], ...spans].filter((s) => s.endMs > s.startMs).sort((a, b) => a.startMs - b.startMs);
|
|
1734
|
+
if (all.length === 0)
|
|
1735
|
+
return {};
|
|
1736
|
+
const merged = [{ ...all[0] }];
|
|
1737
|
+
for (let i = 1; i < all.length; i++) {
|
|
1738
|
+
const cur = all[i];
|
|
1739
|
+
const last = merged[merged.length - 1];
|
|
1740
|
+
if (cur.startMs <= last.endMs)
|
|
1741
|
+
last.endMs = Math.max(last.endMs, cur.endMs);
|
|
1742
|
+
else
|
|
1743
|
+
merged.push({ ...cur });
|
|
1744
|
+
}
|
|
1745
|
+
const airTimeMs = merged.reduce((n, s) => n + (s.endMs - s.startMs), 0);
|
|
1746
|
+
return { activeSegments: merged, airTimeMs };
|
|
1747
|
+
}
|
|
1663
1748
|
async function getCachedMeta(f) {
|
|
1664
1749
|
const cached = metaCache.get(f.fullPath);
|
|
1665
1750
|
if (cached && cached.mtimeMs === f.mtimeMs && cached.sizeBytes === f.sizeBytes) {
|
|
@@ -1671,12 +1756,15 @@ async function getCachedMeta(f) {
|
|
|
1671
1756
|
const sessionId = sessionIdFromFileName(f.fileName);
|
|
1672
1757
|
const projectDirPath = path.dirname(f.fullPath);
|
|
1673
1758
|
meta.totalUsage = await computeSessionUsageWithSubagents(rawLines, projectDirPath, sessionId);
|
|
1759
|
+
const wf = await scanWorkflowAggregate(projectDirPath, sessionId);
|
|
1674
1760
|
const full = {
|
|
1675
1761
|
...meta,
|
|
1676
1762
|
id: sessionId,
|
|
1677
1763
|
filePath: f.fullPath,
|
|
1678
1764
|
projectDir: f.projectDir,
|
|
1679
|
-
projectName: meta.cwd ?? decodeProjectName(f.projectDir)
|
|
1765
|
+
projectName: meta.cwd ?? decodeProjectName(f.projectDir),
|
|
1766
|
+
...wf.workflowCount > 0 ? { workflowCount: wf.workflowCount, spawnedAgentCount: wf.spawnedAgentCount } : {},
|
|
1767
|
+
...foldWorkflowAgentTime(meta.activeSegments, wf.spans)
|
|
1680
1768
|
};
|
|
1681
1769
|
metaCache.set(f.fullPath, { meta: full, mtimeMs: f.mtimeMs, sizeBytes: f.sizeBytes });
|
|
1682
1770
|
return full;
|
|
@@ -1692,13 +1780,17 @@ async function getCachedDetail(f) {
|
|
|
1692
1780
|
try {
|
|
1693
1781
|
const rawLines = await readJsonlFile(f.fullPath);
|
|
1694
1782
|
const { meta, events } = parseTranscript(rawLines);
|
|
1783
|
+
const sessionId = sessionIdFromFileName(f.fileName);
|
|
1784
|
+
const wf = await scanWorkflowAggregate(path.dirname(f.fullPath), sessionId);
|
|
1695
1785
|
const detail = {
|
|
1696
1786
|
...meta,
|
|
1697
|
-
id:
|
|
1787
|
+
id: sessionId,
|
|
1698
1788
|
filePath: f.fullPath,
|
|
1699
1789
|
projectDir: f.projectDir,
|
|
1700
1790
|
projectName: meta.cwd ?? decodeProjectName(f.projectDir),
|
|
1701
|
-
events
|
|
1791
|
+
events,
|
|
1792
|
+
...wf.workflowCount > 0 ? { workflowCount: wf.workflowCount, spawnedAgentCount: wf.spawnedAgentCount } : {},
|
|
1793
|
+
...foldWorkflowAgentTime(meta.activeSegments, wf.spans)
|
|
1702
1794
|
};
|
|
1703
1795
|
detailCache.set(f.fullPath, { detail, mtimeMs: f.mtimeMs, sizeBytes: f.sizeBytes });
|
|
1704
1796
|
const metaOnly = { ...detail };
|
|
@@ -1730,8 +1822,18 @@ async function getSession(id, opts = {}) {
|
|
|
1730
1822
|
return detail;
|
|
1731
1823
|
const sessionStartMs = detail.firstTimestamp ? Date.parse(detail.firstTimestamp) : void 0;
|
|
1732
1824
|
const subagentsDir = path.join(path.dirname(hit.fullPath), sessionIdFromFileName(hit.fileName), "subagents");
|
|
1733
|
-
const
|
|
1734
|
-
|
|
1825
|
+
const workflowsDir = path.join(path.dirname(hit.fullPath), sessionIdFromFileName(hit.fileName), "workflows");
|
|
1826
|
+
const [subagents, workflows] = await Promise.all([
|
|
1827
|
+
loadSubagents(subagentsDir, sessionStartMs, detail.events),
|
|
1828
|
+
loadWorkflows(workflowsDir, sessionStartMs, detail.events)
|
|
1829
|
+
]);
|
|
1830
|
+
const spawnedAgentCount = workflows.reduce((n, w) => n + w.agentCount, 0);
|
|
1831
|
+
return {
|
|
1832
|
+
...detail,
|
|
1833
|
+
subagents,
|
|
1834
|
+
workflows,
|
|
1835
|
+
...workflows.length > 0 ? { workflowCount: workflows.length, spawnedAgentCount } : {}
|
|
1836
|
+
};
|
|
1735
1837
|
}
|
|
1736
1838
|
function summarizeSubagentLines(lines) {
|
|
1737
1839
|
let startMs;
|
|
@@ -1921,6 +2023,248 @@ async function loadSubagents(dir, sessionStartMs, parentEvents) {
|
|
|
1921
2023
|
}));
|
|
1922
2024
|
return runs2.filter((r) => r !== null).sort((a, b) => (a.startMs ?? 0) - (b.startMs ?? 0));
|
|
1923
2025
|
}
|
|
2026
|
+
async function loadWorkflows(dir, sessionStartMs, parentEvents) {
|
|
2027
|
+
let entries2;
|
|
2028
|
+
try {
|
|
2029
|
+
entries2 = await fs.readdir(dir);
|
|
2030
|
+
} catch {
|
|
2031
|
+
return [];
|
|
2032
|
+
}
|
|
2033
|
+
const jsonFiles = entries2.filter((f) => f.startsWith("wf_") && f.endsWith(".json"));
|
|
2034
|
+
if (jsonFiles.length === 0)
|
|
2035
|
+
return [];
|
|
2036
|
+
const dispatches = [];
|
|
2037
|
+
for (const e of parentEvents) {
|
|
2038
|
+
if (e.role !== "tool-call" || e.toolName !== "Workflow")
|
|
2039
|
+
continue;
|
|
2040
|
+
const tsMs = e.timestamp ? Date.parse(e.timestamp) : NaN;
|
|
2041
|
+
if (Number.isNaN(tsMs))
|
|
2042
|
+
continue;
|
|
2043
|
+
for (const b of e.blocks) {
|
|
2044
|
+
if (b?.type !== "tool_use" || b.name !== "Workflow")
|
|
2045
|
+
continue;
|
|
2046
|
+
dispatches.push({ toolUseId: b.id, parentUuid: e.uuid ?? "", tsMs });
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
dispatches.sort((a, b) => a.tsMs - b.tsMs);
|
|
2050
|
+
const matchDispatch = (startMs) => {
|
|
2051
|
+
if (startMs === void 0 || dispatches.length === 0)
|
|
2052
|
+
return void 0;
|
|
2053
|
+
const TOLERANCE_MS = 6e4;
|
|
2054
|
+
let before;
|
|
2055
|
+
let beforeDelta = Infinity;
|
|
2056
|
+
let nearest;
|
|
2057
|
+
let nearestDelta = Infinity;
|
|
2058
|
+
for (const d of dispatches) {
|
|
2059
|
+
const delta = Math.abs(startMs - d.tsMs);
|
|
2060
|
+
if (delta > TOLERANCE_MS)
|
|
2061
|
+
continue;
|
|
2062
|
+
if (delta < nearestDelta) {
|
|
2063
|
+
nearest = d;
|
|
2064
|
+
nearestDelta = delta;
|
|
2065
|
+
}
|
|
2066
|
+
if (d.tsMs <= startMs && delta < beforeDelta) {
|
|
2067
|
+
before = d;
|
|
2068
|
+
beforeDelta = delta;
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
return before ?? nearest;
|
|
2072
|
+
};
|
|
2073
|
+
const num2 = (v) => typeof v === "number" ? v : void 0;
|
|
2074
|
+
const str = (v) => typeof v === "string" && v.length > 0 ? v : void 0;
|
|
2075
|
+
const runs2 = await Promise.all(jsonFiles.map(async (f) => {
|
|
2076
|
+
let j;
|
|
2077
|
+
try {
|
|
2078
|
+
j = JSON.parse(await fs.readFile(path.join(dir, f), "utf8"));
|
|
2079
|
+
} catch {
|
|
2080
|
+
return null;
|
|
2081
|
+
}
|
|
2082
|
+
const runId = str(j.runId) ?? f.replace(/\.json$/, "");
|
|
2083
|
+
const startMs = num2(j.startTime);
|
|
2084
|
+
const durationMs = num2(j.durationMs);
|
|
2085
|
+
const endMs = startMs !== void 0 && durationMs !== void 0 ? startMs + durationMs : void 0;
|
|
2086
|
+
const startTOffsetMs = sessionStartMs !== void 0 && startMs !== void 0 ? Math.max(0, startMs - sessionStartMs) : void 0;
|
|
2087
|
+
const endTOffsetMs = sessionStartMs !== void 0 && endMs !== void 0 ? Math.max(0, endMs - sessionStartMs) : void 0;
|
|
2088
|
+
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) })) : [];
|
|
2089
|
+
const logs = Array.isArray(j.logs) ? j.logs.filter((l) => typeof l === "string") : [];
|
|
2090
|
+
const cap = (v, n) => {
|
|
2091
|
+
const s = str(v);
|
|
2092
|
+
return s === void 0 ? void 0 : s.length > n ? s.slice(0, n) + "\u2026" : s;
|
|
2093
|
+
};
|
|
2094
|
+
const progress = Array.isArray(j.workflowProgress) ? j.workflowProgress : [];
|
|
2095
|
+
const agents = progress.filter((e) => !!e && typeof e === "object" && e.type === "workflow_agent").map((e) => ({
|
|
2096
|
+
index: num2(e.index) ?? 0,
|
|
2097
|
+
label: str(e.label) ?? "(agent)",
|
|
2098
|
+
phaseIndex: num2(e.phaseIndex),
|
|
2099
|
+
phaseTitle: str(e.phaseTitle),
|
|
2100
|
+
agentId: str(e.agentId),
|
|
2101
|
+
model: str(e.model),
|
|
2102
|
+
state: str(e.state),
|
|
2103
|
+
startedAt: num2(e.startedAt),
|
|
2104
|
+
durationMs: num2(e.durationMs),
|
|
2105
|
+
tokens: num2(e.tokens),
|
|
2106
|
+
toolCalls: num2(e.toolCalls),
|
|
2107
|
+
lastToolSummary: cap(e.lastToolSummary, 200),
|
|
2108
|
+
promptPreview: cap(e.promptPreview, 600),
|
|
2109
|
+
resultPreview: cap(e.resultPreview, 600)
|
|
2110
|
+
})).sort((a, b) => a.index - b.index);
|
|
2111
|
+
const parent = matchDispatch(startMs);
|
|
2112
|
+
return {
|
|
2113
|
+
runId,
|
|
2114
|
+
name: str(j.workflowName) ?? runId,
|
|
2115
|
+
description: str(j.summary),
|
|
2116
|
+
status: str(j.status) ?? "unknown",
|
|
2117
|
+
agentCount: num2(j.agentCount) ?? 0,
|
|
2118
|
+
toolCallCount: num2(j.totalToolCalls) ?? 0,
|
|
2119
|
+
totalTokens: num2(j.totalTokens) ?? 0,
|
|
2120
|
+
durationMs,
|
|
2121
|
+
startMs,
|
|
2122
|
+
endMs,
|
|
2123
|
+
startTOffsetMs,
|
|
2124
|
+
endTOffsetMs,
|
|
2125
|
+
model: str(j.defaultModel),
|
|
2126
|
+
phases,
|
|
2127
|
+
logs,
|
|
2128
|
+
agents,
|
|
2129
|
+
parentToolUseId: parent?.toolUseId,
|
|
2130
|
+
parentUuid: parent?.parentUuid
|
|
2131
|
+
};
|
|
2132
|
+
}));
|
|
2133
|
+
return runs2.filter((r) => r !== null).sort((a, b) => (a.startMs ?? 0) - (b.startMs ?? 0));
|
|
2134
|
+
}
|
|
2135
|
+
function salientToolInput(input) {
|
|
2136
|
+
if (!input || typeof input !== "object")
|
|
2137
|
+
return "";
|
|
2138
|
+
const o = input;
|
|
2139
|
+
const pick = (k) => typeof o[k] === "string" ? o[k] : void 0;
|
|
2140
|
+
return pick("command") ?? pick("file_path") ?? pick("path") ?? pick("pattern") ?? pick("url") ?? pick("description") ?? pick("query") ?? pick("prompt") ?? pick("old_string") ?? JSON.stringify(o);
|
|
2141
|
+
}
|
|
2142
|
+
async function loadWorkflowAgentDetail(sessionId, runId, agentId, opts = {}) {
|
|
2143
|
+
const { root = DEFAULT_ROOT } = opts;
|
|
2144
|
+
if (!/^[\w.-]+$/.test(runId) || !/^[\w.-]+$/.test(agentId))
|
|
2145
|
+
return null;
|
|
2146
|
+
const files = await walkJsonlFiles(root);
|
|
2147
|
+
const hit = files.find((f) => sessionIdFromFileName(f.fileName) === sessionId);
|
|
2148
|
+
if (!hit)
|
|
2149
|
+
return null;
|
|
2150
|
+
const file = path.join(path.dirname(hit.fullPath), sessionId, "subagents", "workflows", runId, `agent-${agentId}.jsonl`);
|
|
2151
|
+
let lines;
|
|
2152
|
+
try {
|
|
2153
|
+
lines = await readJsonlFile(file);
|
|
2154
|
+
} catch {
|
|
2155
|
+
return null;
|
|
2156
|
+
}
|
|
2157
|
+
const errored = /* @__PURE__ */ new Set();
|
|
2158
|
+
for (const raw of lines) {
|
|
2159
|
+
if (!raw || typeof raw !== "object")
|
|
2160
|
+
continue;
|
|
2161
|
+
const content = raw.message?.content;
|
|
2162
|
+
if (!Array.isArray(content))
|
|
2163
|
+
continue;
|
|
2164
|
+
for (const b of content) {
|
|
2165
|
+
if (b && typeof b === "object" && b.type === "tool_result" && b.is_error === true && typeof b.tool_use_id === "string") {
|
|
2166
|
+
errored.add(b.tool_use_id);
|
|
2167
|
+
}
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
const steps = [];
|
|
2171
|
+
const toolCounts = /* @__PURE__ */ new Map();
|
|
2172
|
+
const totalUsage = { ...BLANK_USAGE3 };
|
|
2173
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2174
|
+
let prompt;
|
|
2175
|
+
let finalText;
|
|
2176
|
+
let model;
|
|
2177
|
+
let assistantMessageCount = 0;
|
|
2178
|
+
let eventCount = 0;
|
|
2179
|
+
let startMs;
|
|
2180
|
+
let endMs;
|
|
2181
|
+
for (const raw of lines) {
|
|
2182
|
+
if (!raw || typeof raw !== "object")
|
|
2183
|
+
continue;
|
|
2184
|
+
const r = raw;
|
|
2185
|
+
eventCount++;
|
|
2186
|
+
const ts = typeof r.timestamp === "string" ? Date.parse(r.timestamp) : NaN;
|
|
2187
|
+
if (!Number.isNaN(ts)) {
|
|
2188
|
+
if (startMs === void 0 || ts < startMs)
|
|
2189
|
+
startMs = ts;
|
|
2190
|
+
if (endMs === void 0 || ts > endMs)
|
|
2191
|
+
endMs = ts;
|
|
2192
|
+
}
|
|
2193
|
+
if (prompt === void 0 && r.type === "user" && (r.parentUuid === null || r.parentUuid === void 0)) {
|
|
2194
|
+
const c = r.message?.content;
|
|
2195
|
+
if (typeof c === "string")
|
|
2196
|
+
prompt = c;
|
|
2197
|
+
else if (Array.isArray(c)) {
|
|
2198
|
+
const t = c.find((b) => b && typeof b === "object" && b.type === "text");
|
|
2199
|
+
if (t?.text)
|
|
2200
|
+
prompt = t.text;
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
if (r.type !== "assistant")
|
|
2204
|
+
continue;
|
|
2205
|
+
const m = r.message;
|
|
2206
|
+
if (!m)
|
|
2207
|
+
continue;
|
|
2208
|
+
if (!model && typeof m.model === "string")
|
|
2209
|
+
model = m.model;
|
|
2210
|
+
const mid = typeof m.id === "string" ? m.id : void 0;
|
|
2211
|
+
const rid = typeof r.requestId === "string" ? r.requestId : void 0;
|
|
2212
|
+
const key = mid != null && rid != null ? `${mid}:${rid}` : void 0;
|
|
2213
|
+
const fresh = key ? !seen.has(key) : true;
|
|
2214
|
+
if (key && fresh)
|
|
2215
|
+
seen.add(key);
|
|
2216
|
+
if (fresh) {
|
|
2217
|
+
assistantMessageCount++;
|
|
2218
|
+
const u = m.usage;
|
|
2219
|
+
if (u) {
|
|
2220
|
+
const n = (v) => typeof v === "number" ? v : 0;
|
|
2221
|
+
totalUsage.input += n(u.input_tokens);
|
|
2222
|
+
totalUsage.output += n(u.output_tokens);
|
|
2223
|
+
totalUsage.cacheRead += n(u.cache_read_input_tokens);
|
|
2224
|
+
totalUsage.cacheWrite += n(u.cache_creation_input_tokens);
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
const content = m.content;
|
|
2228
|
+
if (!Array.isArray(content))
|
|
2229
|
+
continue;
|
|
2230
|
+
for (const b of content) {
|
|
2231
|
+
if (!b || typeof b !== "object")
|
|
2232
|
+
continue;
|
|
2233
|
+
if (b.type === "text" && typeof b.text === "string") {
|
|
2234
|
+
finalText = b.text;
|
|
2235
|
+
} else if (b.type === "tool_use" && typeof b.name === "string") {
|
|
2236
|
+
toolCounts.set(b.name, (toolCounts.get(b.name) ?? 0) + 1);
|
|
2237
|
+
if (steps.length < 2e3) {
|
|
2238
|
+
const salient = salientToolInput(b.input);
|
|
2239
|
+
const preview = salient.replace(/\s+/g, " ").trim().slice(0, 160);
|
|
2240
|
+
const full = salient.length > 4e3 ? salient.slice(0, 4e3) + "\u2026" : salient;
|
|
2241
|
+
steps.push({
|
|
2242
|
+
index: steps.length + 1,
|
|
2243
|
+
tool: b.name,
|
|
2244
|
+
preview,
|
|
2245
|
+
// Only carry `full` when it adds something over the one-line preview.
|
|
2246
|
+
full: full.length > preview.length || full.includes("\n") ? full : void 0,
|
|
2247
|
+
isError: typeof b.id === "string" && errored.has(b.id)
|
|
2248
|
+
});
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
const toolCalls = Array.from(toolCounts.entries()).map(([name, count]) => ({ name, count })).sort((a, b) => b.count - a.count);
|
|
2254
|
+
return {
|
|
2255
|
+
agentId,
|
|
2256
|
+
prompt,
|
|
2257
|
+
finalText,
|
|
2258
|
+
steps,
|
|
2259
|
+
toolCalls,
|
|
2260
|
+
toolCallCount: steps.length,
|
|
2261
|
+
assistantMessageCount,
|
|
2262
|
+
eventCount,
|
|
2263
|
+
totalUsage,
|
|
2264
|
+
model,
|
|
2265
|
+
durationMs: startMs !== void 0 && endMs !== void 0 ? endMs - startMs : void 0
|
|
2266
|
+
};
|
|
2267
|
+
}
|
|
1924
2268
|
async function listProjects(root = DEFAULT_ROOT) {
|
|
1925
2269
|
const files = await walkJsonlFiles(root);
|
|
1926
2270
|
const byRawDir = /* @__PURE__ */ new Map();
|
|
@@ -1942,10 +2286,10 @@ async function listProjects(root = DEFAULT_ROOT) {
|
|
|
1942
2286
|
const canonicalMap = /* @__PURE__ */ new Map();
|
|
1943
2287
|
for (const [rawDir, { count, lastActiveMs }] of byRawDir) {
|
|
1944
2288
|
const cwdOrDecoded = cwdForProject(rawDir) ?? decodeProjectName(rawDir);
|
|
1945
|
-
const
|
|
2289
|
+
const repo = projectRepoName(cwdOrDecoded);
|
|
1946
2290
|
const wt = worktreeName(cwdOrDecoded);
|
|
1947
|
-
const agg = canonicalMap.get(
|
|
1948
|
-
canonicalName:
|
|
2291
|
+
const agg = canonicalMap.get(repo) ?? {
|
|
2292
|
+
canonicalName: repo,
|
|
1949
2293
|
count: 0,
|
|
1950
2294
|
lastActiveMs: 0,
|
|
1951
2295
|
worktreeBranches: /* @__PURE__ */ new Set()
|
|
@@ -1955,7 +2299,7 @@ async function listProjects(root = DEFAULT_ROOT) {
|
|
|
1955
2299
|
agg.lastActiveMs = lastActiveMs;
|
|
1956
2300
|
if (wt)
|
|
1957
2301
|
agg.worktreeBranches.add(wt);
|
|
1958
|
-
canonicalMap.set(
|
|
2302
|
+
canonicalMap.set(repo, agg);
|
|
1959
2303
|
}
|
|
1960
2304
|
return Array.from(canonicalMap.values()).map((a) => ({
|
|
1961
2305
|
projectDir: a.canonicalName,
|
|
@@ -2913,17 +3257,410 @@ async function listGeminiSessions(opts = {}) {
|
|
|
2913
3257
|
const files = await listSessionFiles(root);
|
|
2914
3258
|
const out = [];
|
|
2915
3259
|
for (const file of files) {
|
|
2916
|
-
const cached = metaCache3.get(file.filePath);
|
|
2917
|
-
if (cached && cached.mtimeMs === file.mtimeMs && cached.sizeBytes === file.sizeBytes) {
|
|
3260
|
+
const cached = metaCache3.get(file.filePath);
|
|
3261
|
+
if (cached && cached.mtimeMs === file.mtimeMs && cached.sizeBytes === file.sizeBytes) {
|
|
3262
|
+
out.push(cached.meta);
|
|
3263
|
+
continue;
|
|
3264
|
+
}
|
|
3265
|
+
try {
|
|
3266
|
+
const { meta } = await parseSession(file);
|
|
3267
|
+
metaCache3.set(file.filePath, {
|
|
3268
|
+
meta,
|
|
3269
|
+
mtimeMs: file.mtimeMs,
|
|
3270
|
+
sizeBytes: file.sizeBytes
|
|
3271
|
+
});
|
|
3272
|
+
out.push(meta);
|
|
3273
|
+
} catch {
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
3276
|
+
out.sort((a, b) => (b.firstTimestamp ?? "").localeCompare(a.firstTimestamp ?? ""));
|
|
3277
|
+
if (opts.limit !== void 0)
|
|
3278
|
+
return out.slice(0, opts.limit);
|
|
3279
|
+
return out;
|
|
3280
|
+
}
|
|
3281
|
+
async function getGeminiSession(id, opts = {}) {
|
|
3282
|
+
const root = opts.root ?? DEFAULT_GEMINI_ROOT;
|
|
3283
|
+
const files = await listSessionFiles(root);
|
|
3284
|
+
let chosen;
|
|
3285
|
+
for (const file of files) {
|
|
3286
|
+
if (file.filenameId === id || id.startsWith(file.filenameId)) {
|
|
3287
|
+
chosen = file;
|
|
3288
|
+
break;
|
|
3289
|
+
}
|
|
3290
|
+
}
|
|
3291
|
+
if (!chosen) {
|
|
3292
|
+
for (const file of files) {
|
|
3293
|
+
const { meta: meta2 } = await parseSession(file).catch(() => ({ meta: { id: "" } }));
|
|
3294
|
+
if (meta2.id === id) {
|
|
3295
|
+
chosen = file;
|
|
3296
|
+
break;
|
|
3297
|
+
}
|
|
3298
|
+
}
|
|
3299
|
+
}
|
|
3300
|
+
if (!chosen)
|
|
3301
|
+
return null;
|
|
3302
|
+
const cached = detailCache3.get(chosen.filePath);
|
|
3303
|
+
if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes) {
|
|
3304
|
+
return cached.detail;
|
|
3305
|
+
}
|
|
3306
|
+
const { meta, events } = await parseSession(chosen);
|
|
3307
|
+
const detail = { ...meta, events };
|
|
3308
|
+
detailCache3.set(chosen.filePath, {
|
|
3309
|
+
detail,
|
|
3310
|
+
mtimeMs: chosen.mtimeMs,
|
|
3311
|
+
sizeBytes: chosen.sizeBytes
|
|
3312
|
+
});
|
|
3313
|
+
return detail;
|
|
3314
|
+
}
|
|
3315
|
+
function geminiSessionLocalDay(meta) {
|
|
3316
|
+
if (!meta.firstTimestamp)
|
|
3317
|
+
return void 0;
|
|
3318
|
+
const ms = Date.parse(meta.firstTimestamp);
|
|
3319
|
+
return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
|
|
3320
|
+
}
|
|
3321
|
+
var DEFAULT_GEMINI_ROOT, GEMINI_PROJECTS_FILE, SESSION_FILE_RE, IDLE_GAP_MS2, projectsCache, metaCache3, detailCache3;
|
|
3322
|
+
var init_gemini = __esm({
|
|
3323
|
+
"../parser/dist/gemini.js"() {
|
|
3324
|
+
"use strict";
|
|
3325
|
+
init_analytics();
|
|
3326
|
+
init_user_input();
|
|
3327
|
+
DEFAULT_GEMINI_ROOT = path3.join(os3.homedir(), ".gemini", "tmp");
|
|
3328
|
+
GEMINI_PROJECTS_FILE = path3.join(os3.homedir(), ".gemini", "projects.json");
|
|
3329
|
+
SESSION_FILE_RE = /^session-.+\.(jsonl|json)$/;
|
|
3330
|
+
IDLE_GAP_MS2 = 3 * 60 * 1e3;
|
|
3331
|
+
projectsCache = null;
|
|
3332
|
+
metaCache3 = /* @__PURE__ */ new Map();
|
|
3333
|
+
detailCache3 = /* @__PURE__ */ new Map();
|
|
3334
|
+
}
|
|
3335
|
+
});
|
|
3336
|
+
|
|
3337
|
+
// ../parser/dist/antigravity.js
|
|
3338
|
+
import { promises as fs4 } from "node:fs";
|
|
3339
|
+
import os4 from "node:os";
|
|
3340
|
+
import path4 from "node:path";
|
|
3341
|
+
async function safeReaddir3(p) {
|
|
3342
|
+
return fs4.readdir(p).catch(() => []);
|
|
3343
|
+
}
|
|
3344
|
+
async function loadSlugToCwd2(root) {
|
|
3345
|
+
const historyFile = path4.join(root, "history.jsonl");
|
|
3346
|
+
const stat = await fs4.stat(historyFile).catch(() => null);
|
|
3347
|
+
if (!stat)
|
|
3348
|
+
return /* @__PURE__ */ new Map();
|
|
3349
|
+
if (historyCache && historyCache.mtimeMs === stat.mtimeMs) {
|
|
3350
|
+
return historyCache.slugToCwd;
|
|
3351
|
+
}
|
|
3352
|
+
const raw = await fs4.readFile(historyFile, "utf8").catch(() => "");
|
|
3353
|
+
const slugToCwd = /* @__PURE__ */ new Map();
|
|
3354
|
+
for (const line of raw.split("\n")) {
|
|
3355
|
+
const trimmed = line.trim();
|
|
3356
|
+
if (!trimmed)
|
|
3357
|
+
continue;
|
|
3358
|
+
try {
|
|
3359
|
+
const parsed = JSON.parse(trimmed);
|
|
3360
|
+
if (parsed.conversationId && parsed.workspace) {
|
|
3361
|
+
slugToCwd.set(parsed.conversationId, parsed.workspace);
|
|
3362
|
+
}
|
|
3363
|
+
} catch {
|
|
3364
|
+
}
|
|
3365
|
+
}
|
|
3366
|
+
historyCache = { mtimeMs: stat.mtimeMs, slugToCwd };
|
|
3367
|
+
return slugToCwd;
|
|
3368
|
+
}
|
|
3369
|
+
async function listSessionFiles2(root) {
|
|
3370
|
+
const slugToCwd = await loadSlugToCwd2(root);
|
|
3371
|
+
const out = [];
|
|
3372
|
+
const brainDir = path4.join(root, "brain");
|
|
3373
|
+
const entries2 = await safeReaddir3(brainDir);
|
|
3374
|
+
for (const entry of entries2) {
|
|
3375
|
+
const transcriptPath = path4.join(brainDir, entry, ".system_generated", "logs", "transcript.jsonl");
|
|
3376
|
+
const stat = await fs4.stat(transcriptPath).catch(() => null);
|
|
3377
|
+
if (stat && stat.isFile()) {
|
|
3378
|
+
out.push({
|
|
3379
|
+
filePath: transcriptPath,
|
|
3380
|
+
conversationId: entry,
|
|
3381
|
+
cwd: slugToCwd.get(entry),
|
|
3382
|
+
mtimeMs: stat.mtimeMs,
|
|
3383
|
+
sizeBytes: stat.size
|
|
3384
|
+
});
|
|
3385
|
+
}
|
|
3386
|
+
}
|
|
3387
|
+
return out;
|
|
3388
|
+
}
|
|
3389
|
+
function emptyUsage3() {
|
|
3390
|
+
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
3391
|
+
}
|
|
3392
|
+
function previewOf3(text) {
|
|
3393
|
+
return text.replace(/\s+/g, " ").trim().slice(0, 200);
|
|
3394
|
+
}
|
|
3395
|
+
function truncate4(s, n) {
|
|
3396
|
+
return s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
|
|
3397
|
+
}
|
|
3398
|
+
async function parseSession2(file) {
|
|
3399
|
+
const raw = await fs4.readFile(file.filePath, "utf8");
|
|
3400
|
+
const events = [];
|
|
3401
|
+
const totalUsage = emptyUsage3();
|
|
3402
|
+
let firstTimestamp;
|
|
3403
|
+
let lastTimestamp;
|
|
3404
|
+
let model;
|
|
3405
|
+
let toolCallCount = 0;
|
|
3406
|
+
let turnCount = 0;
|
|
3407
|
+
let firstUserPreview;
|
|
3408
|
+
let lastUserPreview;
|
|
3409
|
+
let lastAgentPreview;
|
|
3410
|
+
const tsMs = [];
|
|
3411
|
+
let idx = 0;
|
|
3412
|
+
function pushEvent(e) {
|
|
3413
|
+
events.push(e);
|
|
3414
|
+
if (e.timestamp && e.role !== "meta") {
|
|
3415
|
+
if (!firstTimestamp)
|
|
3416
|
+
firstTimestamp = e.timestamp;
|
|
3417
|
+
lastTimestamp = e.timestamp;
|
|
3418
|
+
const ms = Date.parse(e.timestamp);
|
|
3419
|
+
if (Number.isFinite(ms))
|
|
3420
|
+
tsMs.push(ms);
|
|
3421
|
+
}
|
|
3422
|
+
}
|
|
3423
|
+
const pendingToolCalls = [];
|
|
3424
|
+
const parsedObjects = [];
|
|
3425
|
+
const indexMap = /* @__PURE__ */ new Map();
|
|
3426
|
+
for (const line of raw.split("\n")) {
|
|
3427
|
+
const trimmed = line.trim();
|
|
3428
|
+
if (!trimmed)
|
|
3429
|
+
continue;
|
|
3430
|
+
try {
|
|
3431
|
+
const obj = JSON.parse(trimmed);
|
|
3432
|
+
const stepIdx = obj.step_index;
|
|
3433
|
+
if (typeof stepIdx === "number") {
|
|
3434
|
+
if (indexMap.has(stepIdx)) {
|
|
3435
|
+
parsedObjects[indexMap.get(stepIdx)] = obj;
|
|
3436
|
+
} else {
|
|
3437
|
+
indexMap.set(stepIdx, parsedObjects.length);
|
|
3438
|
+
parsedObjects.push(obj);
|
|
3439
|
+
}
|
|
3440
|
+
} else {
|
|
3441
|
+
parsedObjects.push(obj);
|
|
3442
|
+
}
|
|
3443
|
+
} catch {
|
|
3444
|
+
}
|
|
3445
|
+
}
|
|
3446
|
+
for (const eventObj of parsedObjects) {
|
|
3447
|
+
const ts = eventObj.created_at || eventObj.timestamp;
|
|
3448
|
+
if (eventObj.type === "USER_INPUT") {
|
|
3449
|
+
if (typeof eventObj.content === "string") {
|
|
3450
|
+
const matchNoNeed = eventObj.content.match(/Model Selection` from .*? to (.*?)\.\s*No need to/);
|
|
3451
|
+
if (matchNoNeed) {
|
|
3452
|
+
let rawModel = matchNoNeed[1].trim();
|
|
3453
|
+
rawModel = rawModel.replace(/\s*\(.*?\)\s*$/, "").trim();
|
|
3454
|
+
model = rawModel;
|
|
3455
|
+
} else {
|
|
3456
|
+
const matchDot = eventObj.content.match(/Model Selection` from .*? to ([^\n]+)/);
|
|
3457
|
+
if (matchDot) {
|
|
3458
|
+
let rawModel = matchDot[1].trim();
|
|
3459
|
+
if (rawModel.endsWith(".")) {
|
|
3460
|
+
rawModel = rawModel.slice(0, -1).trim();
|
|
3461
|
+
}
|
|
3462
|
+
rawModel = rawModel.replace(/\s*\(.*?\)\s*$/, "").trim();
|
|
3463
|
+
model = rawModel;
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
}
|
|
3467
|
+
let text2 = eventObj.content || "";
|
|
3468
|
+
const requestMatch = text2.match(/<USER_REQUEST>([\s\S]*?)<\/USER_REQUEST>/);
|
|
3469
|
+
if (requestMatch) {
|
|
3470
|
+
text2 = requestMatch[1].trim();
|
|
3471
|
+
}
|
|
3472
|
+
const preview = previewOf3(text2);
|
|
3473
|
+
const isHidden = isFrameworkInjectedUserInput(text2);
|
|
3474
|
+
if (text2 && !isHidden) {
|
|
3475
|
+
if (!firstUserPreview)
|
|
3476
|
+
firstUserPreview = preview;
|
|
3477
|
+
lastUserPreview = preview;
|
|
3478
|
+
turnCount += 1;
|
|
3479
|
+
}
|
|
3480
|
+
pushEvent({
|
|
3481
|
+
index: idx++,
|
|
3482
|
+
timestamp: ts,
|
|
3483
|
+
role: "user",
|
|
3484
|
+
rawType: "antigravity/user",
|
|
3485
|
+
preview,
|
|
3486
|
+
blocks: text2 ? [{ type: "text", text: text2 }] : [],
|
|
3487
|
+
messageId: eventObj.step_index?.toString(),
|
|
3488
|
+
raw: eventObj
|
|
3489
|
+
});
|
|
3490
|
+
continue;
|
|
3491
|
+
}
|
|
3492
|
+
if (eventObj.type === "PLANNER_RESPONSE") {
|
|
3493
|
+
const thinking = eventObj.thinking;
|
|
3494
|
+
const content = eventObj.content;
|
|
3495
|
+
if (thinking) {
|
|
3496
|
+
pushEvent({
|
|
3497
|
+
index: idx++,
|
|
3498
|
+
timestamp: ts,
|
|
3499
|
+
role: "agent-thinking",
|
|
3500
|
+
rawType: "antigravity/thought",
|
|
3501
|
+
preview: previewOf3(thinking),
|
|
3502
|
+
blocks: [{ type: "thinking", thinking }],
|
|
3503
|
+
model,
|
|
3504
|
+
raw: eventObj
|
|
3505
|
+
});
|
|
3506
|
+
}
|
|
3507
|
+
if (content) {
|
|
3508
|
+
const preview = previewOf3(content);
|
|
3509
|
+
lastAgentPreview = preview;
|
|
3510
|
+
pushEvent({
|
|
3511
|
+
index: idx++,
|
|
3512
|
+
timestamp: ts,
|
|
3513
|
+
role: "agent",
|
|
3514
|
+
rawType: "antigravity/agent",
|
|
3515
|
+
preview,
|
|
3516
|
+
blocks: [{ type: "text", text: content }],
|
|
3517
|
+
messageId: eventObj.step_index?.toString(),
|
|
3518
|
+
model,
|
|
3519
|
+
raw: eventObj
|
|
3520
|
+
});
|
|
3521
|
+
}
|
|
3522
|
+
const toolCalls = eventObj.tool_calls || [];
|
|
3523
|
+
for (let cIdx = 0; cIdx < toolCalls.length; cIdx++) {
|
|
3524
|
+
const tc = toolCalls[cIdx];
|
|
3525
|
+
toolCallCount += 1;
|
|
3526
|
+
const toolUseId = `tool-${eventObj.step_index}-${cIdx}`;
|
|
3527
|
+
const argsStr = tc.args ? JSON.stringify(tc.args) : "";
|
|
3528
|
+
pendingToolCalls.push({ id: toolUseId, name: tc.name });
|
|
3529
|
+
pushEvent({
|
|
3530
|
+
index: idx++,
|
|
3531
|
+
timestamp: ts,
|
|
3532
|
+
role: "tool-call",
|
|
3533
|
+
rawType: "antigravity/tool_call",
|
|
3534
|
+
preview: `${tc.name}(${truncate4(argsStr, 80)})`,
|
|
3535
|
+
blocks: [{ type: "tool_use", id: toolUseId, name: tc.name, input: tc.args || {} }],
|
|
3536
|
+
toolName: tc.name,
|
|
3537
|
+
toolUseId,
|
|
3538
|
+
model,
|
|
3539
|
+
raw: tc
|
|
3540
|
+
});
|
|
3541
|
+
}
|
|
3542
|
+
continue;
|
|
3543
|
+
}
|
|
3544
|
+
if (eventObj.source === "MODEL" && eventObj.type !== "PLANNER_RESPONSE" && eventObj.type !== "ERROR_MESSAGE" && pendingToolCalls.length > 0) {
|
|
3545
|
+
const matchedCall = pendingToolCalls.shift();
|
|
3546
|
+
const toolUseId = matchedCall ? matchedCall.id : `tool-${eventObj.step_index}-unknown`;
|
|
3547
|
+
const contentStr = typeof eventObj.content === "string" ? eventObj.content : JSON.stringify(eventObj.content || "");
|
|
3548
|
+
const isError = eventObj.status === "ERROR" || eventObj.status === "FAILED" || eventObj.status === "CANCELED" || !!eventObj.error;
|
|
3549
|
+
pushEvent({
|
|
3550
|
+
index: idx++,
|
|
3551
|
+
timestamp: ts,
|
|
3552
|
+
role: "tool-result",
|
|
3553
|
+
rawType: "antigravity/tool_result",
|
|
3554
|
+
preview: previewOf3(contentStr),
|
|
3555
|
+
blocks: [{
|
|
3556
|
+
type: "tool_result",
|
|
3557
|
+
tool_use_id: toolUseId,
|
|
3558
|
+
content: contentStr,
|
|
3559
|
+
is_error: isError
|
|
3560
|
+
}],
|
|
3561
|
+
toolUseId,
|
|
3562
|
+
toolResult: contentStr,
|
|
3563
|
+
raw: eventObj
|
|
3564
|
+
});
|
|
3565
|
+
continue;
|
|
3566
|
+
}
|
|
3567
|
+
const text = eventObj.content || eventObj.error || "";
|
|
3568
|
+
pushEvent({
|
|
3569
|
+
index: idx++,
|
|
3570
|
+
timestamp: ts,
|
|
3571
|
+
role: "meta",
|
|
3572
|
+
rawType: `antigravity/${eventObj.type?.toLowerCase() || "unknown"}`,
|
|
3573
|
+
preview: previewOf3(text),
|
|
3574
|
+
blocks: text ? [{ type: "text", text }] : [],
|
|
3575
|
+
raw: eventObj
|
|
3576
|
+
});
|
|
3577
|
+
}
|
|
3578
|
+
const startMs = firstTimestamp ? Date.parse(firstTimestamp) : void 0;
|
|
3579
|
+
if (startMs !== void 0 && Number.isFinite(startMs)) {
|
|
3580
|
+
let prevMs;
|
|
3581
|
+
for (const ev of events) {
|
|
3582
|
+
if (!ev.timestamp)
|
|
3583
|
+
continue;
|
|
3584
|
+
const ms = Date.parse(ev.timestamp);
|
|
3585
|
+
if (!Number.isFinite(ms))
|
|
3586
|
+
continue;
|
|
3587
|
+
ev.tOffsetMs = Math.max(0, ms - startMs);
|
|
3588
|
+
if (prevMs !== void 0)
|
|
3589
|
+
ev.gapMs = Math.max(0, ms - prevMs);
|
|
3590
|
+
prevMs = ms;
|
|
3591
|
+
}
|
|
3592
|
+
}
|
|
3593
|
+
const activeSegments = computeActiveSegments4(tsMs);
|
|
3594
|
+
const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
|
|
3595
|
+
const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
|
|
3596
|
+
const sessionId = file.conversationId;
|
|
3597
|
+
const cwd = file.cwd;
|
|
3598
|
+
const projectName = cwd ? canonicalProjectName(cwd) : file.conversationId;
|
|
3599
|
+
const projectDir = cwd ? cwd.replace(/^\//, "-").replace(/\//g, "-") : file.conversationId;
|
|
3600
|
+
const meta = {
|
|
3601
|
+
agent: "antigravity",
|
|
3602
|
+
id: sessionId,
|
|
3603
|
+
filePath: file.filePath,
|
|
3604
|
+
projectName,
|
|
3605
|
+
projectDir,
|
|
3606
|
+
sessionId,
|
|
3607
|
+
firstTimestamp,
|
|
3608
|
+
lastTimestamp,
|
|
3609
|
+
durationMs: durationMs && Number.isFinite(durationMs) ? durationMs : void 0,
|
|
3610
|
+
eventCount: events.length,
|
|
3611
|
+
model,
|
|
3612
|
+
cwd,
|
|
3613
|
+
totalUsage,
|
|
3614
|
+
status: "idle",
|
|
3615
|
+
firstUserPreview,
|
|
3616
|
+
lastUserPreview,
|
|
3617
|
+
lastAgentPreview,
|
|
3618
|
+
toolCallCount,
|
|
3619
|
+
turnCount,
|
|
3620
|
+
airTimeMs,
|
|
3621
|
+
activeSegments
|
|
3622
|
+
};
|
|
3623
|
+
return { meta, events };
|
|
3624
|
+
}
|
|
3625
|
+
function computeActiveSegments4(tsMs) {
|
|
3626
|
+
if (tsMs.length === 0)
|
|
3627
|
+
return [];
|
|
3628
|
+
const sorted = [...tsMs].sort((a, b) => a - b);
|
|
3629
|
+
const out = [];
|
|
3630
|
+
let segStart = sorted[0];
|
|
3631
|
+
let segEnd = sorted[0];
|
|
3632
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
3633
|
+
if (sorted[i] - segEnd > IDLE_GAP_MS3) {
|
|
3634
|
+
out.push({ startMs: segStart, endMs: segEnd });
|
|
3635
|
+
segStart = sorted[i];
|
|
3636
|
+
}
|
|
3637
|
+
segEnd = sorted[i];
|
|
3638
|
+
}
|
|
3639
|
+
out.push({ startMs: segStart, endMs: segEnd });
|
|
3640
|
+
return out;
|
|
3641
|
+
}
|
|
3642
|
+
function clearAntigravityCaches() {
|
|
3643
|
+
metaCache4.clear();
|
|
3644
|
+
detailCache4.clear();
|
|
3645
|
+
historyCache = null;
|
|
3646
|
+
}
|
|
3647
|
+
async function listAntigravitySessions(opts = {}) {
|
|
3648
|
+
const root = opts.root ?? DEFAULT_ANTIGRAVITY_ROOT;
|
|
3649
|
+
const files = await listSessionFiles2(root);
|
|
3650
|
+
const out = [];
|
|
3651
|
+
for (const file of files) {
|
|
3652
|
+
const cached = metaCache4.get(file.filePath);
|
|
3653
|
+
if (cached && cached.mtimeMs === file.mtimeMs && cached.sizeBytes === file.sizeBytes && cached.cwd === file.cwd) {
|
|
2918
3654
|
out.push(cached.meta);
|
|
2919
3655
|
continue;
|
|
2920
3656
|
}
|
|
2921
3657
|
try {
|
|
2922
|
-
const { meta } = await
|
|
2923
|
-
|
|
3658
|
+
const { meta } = await parseSession2(file);
|
|
3659
|
+
metaCache4.set(file.filePath, {
|
|
2924
3660
|
meta,
|
|
2925
3661
|
mtimeMs: file.mtimeMs,
|
|
2926
|
-
sizeBytes: file.sizeBytes
|
|
3662
|
+
sizeBytes: file.sizeBytes,
|
|
3663
|
+
cwd: file.cwd
|
|
2927
3664
|
});
|
|
2928
3665
|
out.push(meta);
|
|
2929
3666
|
} catch {
|
|
@@ -2934,59 +3671,274 @@ async function listGeminiSessions(opts = {}) {
|
|
|
2934
3671
|
return out.slice(0, opts.limit);
|
|
2935
3672
|
return out;
|
|
2936
3673
|
}
|
|
2937
|
-
async function
|
|
2938
|
-
const root = opts.root ??
|
|
2939
|
-
const files = await
|
|
3674
|
+
async function getAntigravitySession(id, opts = {}) {
|
|
3675
|
+
const root = opts.root ?? DEFAULT_ANTIGRAVITY_ROOT;
|
|
3676
|
+
const files = await listSessionFiles2(root);
|
|
2940
3677
|
let chosen;
|
|
2941
3678
|
for (const file of files) {
|
|
2942
|
-
if (file.
|
|
3679
|
+
if (file.conversationId === id) {
|
|
2943
3680
|
chosen = file;
|
|
2944
3681
|
break;
|
|
2945
3682
|
}
|
|
2946
3683
|
}
|
|
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
3684
|
if (!chosen)
|
|
2957
3685
|
return null;
|
|
2958
|
-
const cached =
|
|
2959
|
-
if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes) {
|
|
3686
|
+
const cached = detailCache4.get(chosen.filePath);
|
|
3687
|
+
if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes && cached.cwd === chosen.cwd) {
|
|
2960
3688
|
return cached.detail;
|
|
2961
3689
|
}
|
|
2962
|
-
const { meta, events } = await
|
|
3690
|
+
const { meta, events } = await parseSession2(chosen);
|
|
2963
3691
|
const detail = { ...meta, events };
|
|
2964
|
-
|
|
3692
|
+
detailCache4.set(chosen.filePath, {
|
|
2965
3693
|
detail,
|
|
2966
3694
|
mtimeMs: chosen.mtimeMs,
|
|
2967
|
-
sizeBytes: chosen.sizeBytes
|
|
3695
|
+
sizeBytes: chosen.sizeBytes,
|
|
3696
|
+
cwd: chosen.cwd
|
|
2968
3697
|
});
|
|
2969
3698
|
return detail;
|
|
2970
3699
|
}
|
|
2971
|
-
function
|
|
3700
|
+
function antigravitySessionLocalDay(meta) {
|
|
2972
3701
|
if (!meta.firstTimestamp)
|
|
2973
3702
|
return void 0;
|
|
2974
3703
|
const ms = Date.parse(meta.firstTimestamp);
|
|
2975
3704
|
return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
|
|
2976
3705
|
}
|
|
2977
|
-
var
|
|
2978
|
-
var
|
|
2979
|
-
"../parser/dist/
|
|
3706
|
+
var DEFAULT_ANTIGRAVITY_ROOT, IDLE_GAP_MS3, historyCache, metaCache4, detailCache4;
|
|
3707
|
+
var init_antigravity = __esm({
|
|
3708
|
+
"../parser/dist/antigravity.js"() {
|
|
2980
3709
|
"use strict";
|
|
2981
3710
|
init_analytics();
|
|
2982
3711
|
init_user_input();
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
3712
|
+
DEFAULT_ANTIGRAVITY_ROOT = path4.join(os4.homedir(), ".gemini", "antigravity-cli");
|
|
3713
|
+
IDLE_GAP_MS3 = 3 * 60 * 1e3;
|
|
3714
|
+
historyCache = null;
|
|
3715
|
+
metaCache4 = /* @__PURE__ */ new Map();
|
|
3716
|
+
detailCache4 = /* @__PURE__ */ new Map();
|
|
3717
|
+
}
|
|
3718
|
+
});
|
|
3719
|
+
|
|
3720
|
+
// ../parser/dist/cowork.js
|
|
3721
|
+
import { promises as fs5 } from "node:fs";
|
|
3722
|
+
import os5 from "node:os";
|
|
3723
|
+
import path5 from "node:path";
|
|
3724
|
+
function defaultCoworkRoot() {
|
|
3725
|
+
const home = os5.homedir();
|
|
3726
|
+
if (process.platform === "darwin") {
|
|
3727
|
+
return path5.join(home, "Library", "Application Support", "Claude", "local-agent-mode-sessions");
|
|
3728
|
+
}
|
|
3729
|
+
if (process.platform === "win32") {
|
|
3730
|
+
const appData = process.env.APPDATA ?? path5.join(home, "AppData", "Roaming");
|
|
3731
|
+
return path5.join(appData, "Claude", "local-agent-mode-sessions");
|
|
3732
|
+
}
|
|
3733
|
+
return path5.join(home, ".config", "Claude", "local-agent-mode-sessions");
|
|
3734
|
+
}
|
|
3735
|
+
async function safeReaddir4(p) {
|
|
3736
|
+
return fs5.readdir(p).catch(() => []);
|
|
3737
|
+
}
|
|
3738
|
+
async function statMs(p) {
|
|
3739
|
+
const s = await fs5.stat(p).catch(() => null);
|
|
3740
|
+
return s ? s.mtimeMs : 0;
|
|
3741
|
+
}
|
|
3742
|
+
async function listSessionFiles3(root) {
|
|
3743
|
+
const out = [];
|
|
3744
|
+
const accounts = await safeReaddir4(root);
|
|
3745
|
+
for (const accountId of accounts) {
|
|
3746
|
+
const accountDir = path5.join(root, accountId);
|
|
3747
|
+
const workspaces = await safeReaddir4(accountDir);
|
|
3748
|
+
for (const workspaceId of workspaces) {
|
|
3749
|
+
const workspaceDir = path5.join(accountDir, workspaceId);
|
|
3750
|
+
const spacesMtimeMs = await statMs(path5.join(workspaceDir, "spaces.json"));
|
|
3751
|
+
const entries2 = await safeReaddir4(workspaceDir);
|
|
3752
|
+
for (const entry of entries2) {
|
|
3753
|
+
if (!SESSION_ID_RE.test(entry))
|
|
3754
|
+
continue;
|
|
3755
|
+
const auditPath = path5.join(workspaceDir, entry, "audit.jsonl");
|
|
3756
|
+
const auditStat = await fs5.stat(auditPath).catch(() => null);
|
|
3757
|
+
if (!auditStat || !auditStat.isFile() || auditStat.size === 0)
|
|
3758
|
+
continue;
|
|
3759
|
+
const metaPath = path5.join(workspaceDir, `${entry}.json`);
|
|
3760
|
+
const metaMtimeMs = await statMs(metaPath);
|
|
3761
|
+
out.push({
|
|
3762
|
+
sessionId: entry,
|
|
3763
|
+
auditPath,
|
|
3764
|
+
metaPath,
|
|
3765
|
+
workspaceDir,
|
|
3766
|
+
auditMtimeMs: auditStat.mtimeMs,
|
|
3767
|
+
auditSize: auditStat.size,
|
|
3768
|
+
metaMtimeMs,
|
|
3769
|
+
spacesMtimeMs
|
|
3770
|
+
});
|
|
3771
|
+
}
|
|
3772
|
+
}
|
|
3773
|
+
}
|
|
3774
|
+
return out;
|
|
3775
|
+
}
|
|
3776
|
+
async function loadSpacesForWorkspace(workspaceDir) {
|
|
3777
|
+
const spacesPath = path5.join(workspaceDir, "spaces.json");
|
|
3778
|
+
const stat = await fs5.stat(spacesPath).catch(() => null);
|
|
3779
|
+
if (!stat)
|
|
3780
|
+
return /* @__PURE__ */ new Map();
|
|
3781
|
+
const cached = spacesCache.get(workspaceDir);
|
|
3782
|
+
if (cached && cached.mtimeMs === stat.mtimeMs)
|
|
3783
|
+
return cached.spaceIdToPath;
|
|
3784
|
+
const raw = await fs5.readFile(spacesPath, "utf8").catch(() => "");
|
|
3785
|
+
const out = /* @__PURE__ */ new Map();
|
|
3786
|
+
try {
|
|
3787
|
+
const parsed = JSON.parse(raw);
|
|
3788
|
+
for (const space of parsed.spaces ?? []) {
|
|
3789
|
+
const id = typeof space.id === "string" ? space.id : void 0;
|
|
3790
|
+
const folders = Array.isArray(space.folders) ? space.folders : [];
|
|
3791
|
+
const first = folders[0];
|
|
3792
|
+
const folderPath = typeof first?.path === "string" ? first.path : void 0;
|
|
3793
|
+
if (id && folderPath)
|
|
3794
|
+
out.set(id, folderPath);
|
|
3795
|
+
}
|
|
3796
|
+
} catch {
|
|
3797
|
+
}
|
|
3798
|
+
spacesCache.set(workspaceDir, { mtimeMs: stat.mtimeMs, spaceIdToPath: out });
|
|
3799
|
+
return out;
|
|
3800
|
+
}
|
|
3801
|
+
async function readCoworkMeta(metaPath) {
|
|
3802
|
+
const raw = await fs5.readFile(metaPath, "utf8").catch(() => "");
|
|
3803
|
+
if (!raw)
|
|
3804
|
+
return {};
|
|
3805
|
+
try {
|
|
3806
|
+
const j = JSON.parse(raw);
|
|
3807
|
+
return {
|
|
3808
|
+
spaceId: typeof j.spaceId === "string" ? j.spaceId : void 0,
|
|
3809
|
+
userSelectedFolders: Array.isArray(j.userSelectedFolders) ? j.userSelectedFolders.filter((s) => typeof s === "string") : void 0,
|
|
3810
|
+
cwd: typeof j.cwd === "string" ? j.cwd : void 0,
|
|
3811
|
+
model: typeof j.model === "string" ? j.model : void 0,
|
|
3812
|
+
title: typeof j.title === "string" ? j.title : void 0,
|
|
3813
|
+
createdAt: typeof j.createdAt === "number" ? j.createdAt : void 0,
|
|
3814
|
+
lastActivityAt: typeof j.lastActivityAt === "number" ? j.lastActivityAt : void 0
|
|
3815
|
+
};
|
|
3816
|
+
} catch {
|
|
3817
|
+
return {};
|
|
3818
|
+
}
|
|
3819
|
+
}
|
|
3820
|
+
function resolveProject(meta, spaceIdToPath) {
|
|
3821
|
+
let projectPath;
|
|
3822
|
+
if (meta.spaceId)
|
|
3823
|
+
projectPath = spaceIdToPath.get(meta.spaceId);
|
|
3824
|
+
if (!projectPath && meta.userSelectedFolders && meta.userSelectedFolders.length > 0) {
|
|
3825
|
+
projectPath = meta.userSelectedFolders[0];
|
|
3826
|
+
}
|
|
3827
|
+
if (!projectPath) {
|
|
3828
|
+
return { projectName: "cowork:unspaced", projectDir: "cowork-unspaced" };
|
|
3829
|
+
}
|
|
3830
|
+
return {
|
|
3831
|
+
projectName: canonicalProjectName(projectPath),
|
|
3832
|
+
projectDir: projectPath.replace(/^\//, "-").replace(/\//g, "-"),
|
|
3833
|
+
cwd: projectPath
|
|
3834
|
+
};
|
|
3835
|
+
}
|
|
3836
|
+
async function readJsonl2(filePath) {
|
|
3837
|
+
const raw = await fs5.readFile(filePath, "utf8");
|
|
3838
|
+
const out = [];
|
|
3839
|
+
for (const line of raw.split("\n")) {
|
|
3840
|
+
const trimmed = line.trim();
|
|
3841
|
+
if (!trimmed)
|
|
3842
|
+
continue;
|
|
3843
|
+
try {
|
|
3844
|
+
out.push(JSON.parse(trimmed));
|
|
3845
|
+
} catch {
|
|
3846
|
+
}
|
|
3847
|
+
}
|
|
3848
|
+
return out;
|
|
3849
|
+
}
|
|
3850
|
+
async function parseCoworkSession(file) {
|
|
3851
|
+
const [lines, coworkMeta, spaceIdToPath] = await Promise.all([
|
|
3852
|
+
readJsonl2(file.auditPath),
|
|
3853
|
+
readCoworkMeta(file.metaPath),
|
|
3854
|
+
loadSpacesForWorkspace(file.workspaceDir)
|
|
3855
|
+
]);
|
|
3856
|
+
const { meta: baseMeta, events } = parseTranscript(lines);
|
|
3857
|
+
const { projectName, projectDir, cwd } = resolveProject(coworkMeta, spaceIdToPath);
|
|
3858
|
+
const meta = {
|
|
3859
|
+
...baseMeta,
|
|
3860
|
+
agent: "cowork",
|
|
3861
|
+
id: file.sessionId,
|
|
3862
|
+
sessionId: file.sessionId,
|
|
3863
|
+
filePath: file.auditPath,
|
|
3864
|
+
projectName,
|
|
3865
|
+
projectDir,
|
|
3866
|
+
cwd: cwd ?? baseMeta.cwd,
|
|
3867
|
+
model: baseMeta.model ?? coworkMeta.model
|
|
3868
|
+
};
|
|
3869
|
+
return { meta, events };
|
|
3870
|
+
}
|
|
3871
|
+
function cacheKeyFor(file) {
|
|
3872
|
+
return {
|
|
3873
|
+
auditMtimeMs: file.auditMtimeMs,
|
|
3874
|
+
auditSize: file.auditSize,
|
|
3875
|
+
metaMtimeMs: file.metaMtimeMs,
|
|
3876
|
+
spacesMtimeMs: file.spacesMtimeMs
|
|
3877
|
+
};
|
|
3878
|
+
}
|
|
3879
|
+
function cacheKeyMatches(a, b) {
|
|
3880
|
+
return a.auditMtimeMs === b.auditMtimeMs && a.auditSize === b.auditSize && a.metaMtimeMs === b.metaMtimeMs && a.spacesMtimeMs === b.spacesMtimeMs;
|
|
3881
|
+
}
|
|
3882
|
+
function clearCoworkCaches() {
|
|
3883
|
+
metaCache5.clear();
|
|
3884
|
+
detailCache5.clear();
|
|
3885
|
+
spacesCache.clear();
|
|
3886
|
+
}
|
|
3887
|
+
async function listCoworkSessions(opts = {}) {
|
|
3888
|
+
const root = opts.root ?? DEFAULT_COWORK_ROOT;
|
|
3889
|
+
const files = await listSessionFiles3(root);
|
|
3890
|
+
const out = [];
|
|
3891
|
+
for (const file of files) {
|
|
3892
|
+
const key = cacheKeyFor(file);
|
|
3893
|
+
const cached = metaCache5.get(file.auditPath);
|
|
3894
|
+
if (cached && cacheKeyMatches(cached.key, key)) {
|
|
3895
|
+
out.push(cached.meta);
|
|
3896
|
+
continue;
|
|
3897
|
+
}
|
|
3898
|
+
try {
|
|
3899
|
+
const { meta } = await parseCoworkSession(file);
|
|
3900
|
+
metaCache5.set(file.auditPath, { meta, key });
|
|
3901
|
+
out.push(meta);
|
|
3902
|
+
} catch {
|
|
3903
|
+
}
|
|
3904
|
+
}
|
|
3905
|
+
out.sort((a, b) => (b.firstTimestamp ?? "").localeCompare(a.firstTimestamp ?? ""));
|
|
3906
|
+
if (opts.limit !== void 0)
|
|
3907
|
+
return out.slice(0, opts.limit);
|
|
3908
|
+
return out;
|
|
3909
|
+
}
|
|
3910
|
+
async function getCoworkSession(id, opts = {}) {
|
|
3911
|
+
const root = opts.root ?? DEFAULT_COWORK_ROOT;
|
|
3912
|
+
const files = await listSessionFiles3(root);
|
|
3913
|
+
const file = files.find((f) => f.sessionId === id);
|
|
3914
|
+
if (!file)
|
|
3915
|
+
return null;
|
|
3916
|
+
const key = cacheKeyFor(file);
|
|
3917
|
+
const cached = detailCache5.get(file.auditPath);
|
|
3918
|
+
if (cached && cacheKeyMatches(cached.key, key))
|
|
3919
|
+
return cached.detail;
|
|
3920
|
+
const { meta, events } = await parseCoworkSession(file);
|
|
3921
|
+
const detail = { ...meta, events };
|
|
3922
|
+
detailCache5.set(file.auditPath, { detail, key });
|
|
3923
|
+
return detail;
|
|
3924
|
+
}
|
|
3925
|
+
function coworkSessionLocalDay(meta) {
|
|
3926
|
+
if (!meta.firstTimestamp)
|
|
3927
|
+
return void 0;
|
|
3928
|
+
const ms = Date.parse(meta.firstTimestamp);
|
|
3929
|
+
return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
|
|
3930
|
+
}
|
|
3931
|
+
var DEFAULT_COWORK_ROOT, SESSION_ID_RE, spacesCache, metaCache5, detailCache5;
|
|
3932
|
+
var init_cowork = __esm({
|
|
3933
|
+
"../parser/dist/cowork.js"() {
|
|
3934
|
+
"use strict";
|
|
3935
|
+
init_analytics();
|
|
3936
|
+
init_parser();
|
|
3937
|
+
DEFAULT_COWORK_ROOT = defaultCoworkRoot();
|
|
3938
|
+
SESSION_ID_RE = /^local_[0-9a-f-]+$/;
|
|
3939
|
+
spacesCache = /* @__PURE__ */ new Map();
|
|
3940
|
+
metaCache5 = /* @__PURE__ */ new Map();
|
|
3941
|
+
detailCache5 = /* @__PURE__ */ new Map();
|
|
2990
3942
|
}
|
|
2991
3943
|
});
|
|
2992
3944
|
|
|
@@ -3034,11 +3986,14 @@ var init_team_wire = __esm({
|
|
|
3034
3986
|
// ../parser/dist/fs.js
|
|
3035
3987
|
var fs_exports = {};
|
|
3036
3988
|
__export(fs_exports, {
|
|
3989
|
+
DEFAULT_ANTIGRAVITY_ROOT: () => DEFAULT_ANTIGRAVITY_ROOT,
|
|
3037
3990
|
DEFAULT_CODEX_ROOT: () => DEFAULT_CODEX_ROOT,
|
|
3991
|
+
DEFAULT_COWORK_ROOT: () => DEFAULT_COWORK_ROOT,
|
|
3038
3992
|
DEFAULT_GEMINI_ROOT: () => DEFAULT_GEMINI_ROOT,
|
|
3039
3993
|
DEFAULT_ROOT: () => DEFAULT_ROOT,
|
|
3040
3994
|
RICH_ROLLUP_SCHEMA_VERSION: () => RICH_ROLLUP_SCHEMA_VERSION,
|
|
3041
3995
|
agentSources: () => agentSources,
|
|
3996
|
+
antigravitySessionLocalDay: () => antigravitySessionLocalDay,
|
|
3042
3997
|
buildCalibrationCurve: () => buildCalibrationCurve,
|
|
3043
3998
|
cacheStats: () => cacheStats,
|
|
3044
3999
|
cclensHome: () => cclensHome,
|
|
@@ -3046,19 +4001,24 @@ __export(fs_exports, {
|
|
|
3046
4001
|
clearCaches: () => clearCaches,
|
|
3047
4002
|
clearTeamConfig: () => clearTeamConfig,
|
|
3048
4003
|
codexSessionLocalDay: () => codexSessionLocalDay,
|
|
4004
|
+
coworkSessionLocalDay: () => coworkSessionLocalDay,
|
|
3049
4005
|
decodeProjectName: () => decodeProjectName,
|
|
3050
4006
|
findTeamLead: () => findTeamLead,
|
|
3051
4007
|
geminiSessionLocalDay: () => geminiSessionLocalDay,
|
|
3052
4008
|
getAgentSource: () => getAgentSource,
|
|
4009
|
+
getAntigravitySession: () => getAntigravitySession,
|
|
3053
4010
|
getAnySession: () => getAnySession,
|
|
3054
4011
|
getCodexSession: () => getCodexSession,
|
|
4012
|
+
getCoworkSession: () => getCoworkSession,
|
|
3055
4013
|
getGeminiSession: () => getGeminiSession,
|
|
3056
4014
|
getLatestCodexUsage: () => getLatestCodexUsage,
|
|
3057
4015
|
getSession: () => getSession,
|
|
3058
4016
|
invalidateFile: () => invalidateFile,
|
|
3059
4017
|
isFleetlensRuntimeDir: () => isFleetlensRuntimeDir,
|
|
3060
4018
|
listAllSessions: () => listAllSessions,
|
|
4019
|
+
listAntigravitySessions: () => listAntigravitySessions,
|
|
3061
4020
|
listCodexSessions: () => listCodexSessions,
|
|
4021
|
+
listCoworkSessions: () => listCoworkSessions,
|
|
3062
4022
|
listGeminiSessions: () => listGeminiSessions,
|
|
3063
4023
|
listProjects: () => listProjects,
|
|
3064
4024
|
listSessions: () => listSessions,
|
|
@@ -3067,20 +4027,21 @@ __export(fs_exports, {
|
|
|
3067
4027
|
loadCalibrationSnapshots: () => loadCalibrationSnapshots,
|
|
3068
4028
|
loadTeamForSession: () => loadTeamForSession,
|
|
3069
4029
|
loadUsageByDay: () => loadUsageByDay,
|
|
4030
|
+
loadWorkflowAgentDetail: () => loadWorkflowAgentDetail,
|
|
3070
4031
|
readJsonlFile: () => readJsonlFile,
|
|
3071
4032
|
readTeamConfig: () => readTeamConfig,
|
|
3072
4033
|
sessionIdFromFileName: () => sessionIdFromFileName,
|
|
3073
4034
|
walkJsonlFiles: () => walkJsonlFiles,
|
|
3074
4035
|
writeTeamConfig: () => writeTeamConfig
|
|
3075
4036
|
});
|
|
3076
|
-
import { promises as
|
|
3077
|
-
import
|
|
3078
|
-
import
|
|
4037
|
+
import { promises as fs6 } from "node:fs";
|
|
4038
|
+
import os6 from "node:os";
|
|
4039
|
+
import path6 from "node:path";
|
|
3079
4040
|
function cclensHome() {
|
|
3080
|
-
return process.env.CCLENS_HOME ||
|
|
4041
|
+
return process.env.CCLENS_HOME || path6.join(os6.homedir(), ".cclens");
|
|
3081
4042
|
}
|
|
3082
4043
|
function cclensPath(...parts) {
|
|
3083
|
-
return
|
|
4044
|
+
return path6.join(cclensHome(), ...parts);
|
|
3084
4045
|
}
|
|
3085
4046
|
function cacheStats() {
|
|
3086
4047
|
return claudeCodeCacheStats();
|
|
@@ -3089,6 +4050,8 @@ function clearCaches() {
|
|
|
3089
4050
|
clearClaudeCodeCaches();
|
|
3090
4051
|
clearCodexCaches();
|
|
3091
4052
|
clearGeminiCaches();
|
|
4053
|
+
clearAntigravityCaches();
|
|
4054
|
+
clearCoworkCaches();
|
|
3092
4055
|
}
|
|
3093
4056
|
function invalidateFile(fullPath) {
|
|
3094
4057
|
invalidateClaudeCodeFile(fullPath);
|
|
@@ -3120,7 +4083,7 @@ function usageLogPath() {
|
|
|
3120
4083
|
async function loadUsageByDay(start2, end) {
|
|
3121
4084
|
let raw;
|
|
3122
4085
|
try {
|
|
3123
|
-
raw = await
|
|
4086
|
+
raw = await fs6.readFile(usageLogPath(), "utf8");
|
|
3124
4087
|
} catch {
|
|
3125
4088
|
return { by_day: [] };
|
|
3126
4089
|
}
|
|
@@ -3165,7 +4128,7 @@ async function loadUsageByDay(start2, end) {
|
|
|
3165
4128
|
async function loadCalibrationSnapshots() {
|
|
3166
4129
|
let raw;
|
|
3167
4130
|
try {
|
|
3168
|
-
raw = await
|
|
4131
|
+
raw = await fs6.readFile(usageLogPath(), "utf8");
|
|
3169
4132
|
} catch {
|
|
3170
4133
|
return [];
|
|
3171
4134
|
}
|
|
@@ -3323,7 +4286,7 @@ async function loadCalibrationCurve(tier = "pro-max-20x", root = DEFAULT_ROOT, g
|
|
|
3323
4286
|
]);
|
|
3324
4287
|
return buildCalibrationCurve(events, snapshots, tier, granularityMin);
|
|
3325
4288
|
}
|
|
3326
|
-
var codexSource, geminiSource, agentSources;
|
|
4289
|
+
var codexSource, geminiSource, antigravitySource, coworkSource, agentSources;
|
|
3327
4290
|
var init_fs = __esm({
|
|
3328
4291
|
"../parser/dist/fs.js"() {
|
|
3329
4292
|
"use strict";
|
|
@@ -3333,9 +4296,13 @@ var init_fs = __esm({
|
|
|
3333
4296
|
init_claude_code();
|
|
3334
4297
|
init_codex();
|
|
3335
4298
|
init_gemini();
|
|
4299
|
+
init_antigravity();
|
|
4300
|
+
init_cowork();
|
|
3336
4301
|
init_claude_code();
|
|
3337
4302
|
init_codex();
|
|
3338
4303
|
init_gemini();
|
|
4304
|
+
init_antigravity();
|
|
4305
|
+
init_cowork();
|
|
3339
4306
|
init_team_config();
|
|
3340
4307
|
init_team_wire();
|
|
3341
4308
|
codexSource = {
|
|
@@ -3369,7 +4336,33 @@ var init_fs = __esm({
|
|
|
3369
4336
|
return getGeminiSession(id);
|
|
3370
4337
|
}
|
|
3371
4338
|
};
|
|
3372
|
-
|
|
4339
|
+
antigravitySource = {
|
|
4340
|
+
...ANTIGRAVITY_METADATA,
|
|
4341
|
+
defaultRoot: DEFAULT_ANTIGRAVITY_ROOT,
|
|
4342
|
+
async listSessions(opts) {
|
|
4343
|
+
return listAntigravitySessions(opts);
|
|
4344
|
+
},
|
|
4345
|
+
async getSession(id) {
|
|
4346
|
+
return getAntigravitySession(id);
|
|
4347
|
+
}
|
|
4348
|
+
};
|
|
4349
|
+
coworkSource = {
|
|
4350
|
+
...COWORK_METADATA,
|
|
4351
|
+
defaultRoot: DEFAULT_COWORK_ROOT,
|
|
4352
|
+
async listSessions(opts) {
|
|
4353
|
+
return listCoworkSessions(opts);
|
|
4354
|
+
},
|
|
4355
|
+
async getSession(id) {
|
|
4356
|
+
return getCoworkSession(id);
|
|
4357
|
+
}
|
|
4358
|
+
};
|
|
4359
|
+
agentSources = [
|
|
4360
|
+
claudeCodeSource,
|
|
4361
|
+
codexSource,
|
|
4362
|
+
geminiSource,
|
|
4363
|
+
antigravitySource,
|
|
4364
|
+
coworkSource
|
|
4365
|
+
];
|
|
3373
4366
|
}
|
|
3374
4367
|
});
|
|
3375
4368
|
|
|
@@ -3442,11 +4435,11 @@ function stopServer() {
|
|
|
3442
4435
|
}
|
|
3443
4436
|
async function checkPort(port) {
|
|
3444
4437
|
const { createServer } = await import("node:net");
|
|
3445
|
-
return new Promise((
|
|
4438
|
+
return new Promise((resolve3) => {
|
|
3446
4439
|
const server = createServer();
|
|
3447
|
-
server.once("error", () =>
|
|
4440
|
+
server.once("error", () => resolve3(true));
|
|
3448
4441
|
server.once("listening", () => {
|
|
3449
|
-
server.close(() =>
|
|
4442
|
+
server.close(() => resolve3(false));
|
|
3450
4443
|
});
|
|
3451
4444
|
server.listen(port, "localhost");
|
|
3452
4445
|
});
|
|
@@ -3776,9 +4769,9 @@ Installed: ${PACKAGE_NAME}@${verify.installedVersion} at ${verify.installedPath
|
|
|
3776
4769
|
console.warn(
|
|
3777
4770
|
` \u2022 reinstall in the correct Node env: 'npm install -g ${PACKAGE_NAME}@latest'`
|
|
3778
4771
|
);
|
|
3779
|
-
} else if (verify.installedVersion !== "0.
|
|
4772
|
+
} else if (verify.installedVersion !== "0.12.0") {
|
|
3780
4773
|
console.log(
|
|
3781
|
-
` \u2192 This process is still running ${"0.
|
|
4774
|
+
` \u2192 This process is still running ${"0.12.0"}. Next invocation will use ${verify.installedVersion}.`
|
|
3782
4775
|
);
|
|
3783
4776
|
}
|
|
3784
4777
|
}
|
|
@@ -3813,14 +4806,14 @@ async function getUpdateAvailability() {
|
|
|
3813
4806
|
if (isDevMode()) return null;
|
|
3814
4807
|
const latest = await fetchLatestVersion();
|
|
3815
4808
|
if (latest === null) return {
|
|
3816
|
-
current: "0.
|
|
4809
|
+
current: "0.12.0",
|
|
3817
4810
|
latest: null,
|
|
3818
4811
|
updateAvailable: false
|
|
3819
4812
|
};
|
|
3820
4813
|
return {
|
|
3821
|
-
current: "0.
|
|
4814
|
+
current: "0.12.0",
|
|
3822
4815
|
latest,
|
|
3823
|
-
updateAvailable: shouldUpdate("0.
|
|
4816
|
+
updateAvailable: shouldUpdate("0.12.0", latest)
|
|
3824
4817
|
};
|
|
3825
4818
|
}
|
|
3826
4819
|
async function checkForUpdate() {
|
|
@@ -3910,7 +4903,7 @@ async function restartServices(state) {
|
|
|
3910
4903
|
}
|
|
3911
4904
|
async function forceUpdate() {
|
|
3912
4905
|
const latest = await fetchLatestVersion();
|
|
3913
|
-
const current = "0.
|
|
4906
|
+
const current = "0.12.0";
|
|
3914
4907
|
if (latest === null) {
|
|
3915
4908
|
console.error("Could not reach npm registry. Check your network.");
|
|
3916
4909
|
process.exit(1);
|
|
@@ -4088,10 +5081,10 @@ async function web(args2) {
|
|
|
4088
5081
|
const open = args2.includes("--open");
|
|
4089
5082
|
const positional = args2.filter((a) => !a.startsWith("--"));
|
|
4090
5083
|
const rawPath = positional[0] ?? "";
|
|
4091
|
-
const
|
|
5084
|
+
const path7 = rawPath.startsWith("/") ? rawPath : rawPath ? `/${rawPath}` : "";
|
|
4092
5085
|
const status2 = getServerStatus();
|
|
4093
5086
|
if (status2.running) {
|
|
4094
|
-
const url = `http://localhost:${status2.port}${
|
|
5087
|
+
const url = `http://localhost:${status2.port}${path7}`;
|
|
4095
5088
|
if (open) {
|
|
4096
5089
|
console.log(`Opening ${url}`);
|
|
4097
5090
|
openBrowser(url);
|
|
@@ -4103,7 +5096,7 @@ async function web(args2) {
|
|
|
4103
5096
|
console.log("fleetlens is not running. Starting server...");
|
|
4104
5097
|
try {
|
|
4105
5098
|
const result = await startServer({});
|
|
4106
|
-
const url = `http://localhost:${result.port}${
|
|
5099
|
+
const url = `http://localhost:${result.port}${path7}`;
|
|
4107
5100
|
console.log(`fleetlens running on ${url} (PID ${result.pid})`);
|
|
4108
5101
|
if (open) {
|
|
4109
5102
|
openBrowser(url);
|
|
@@ -4165,9 +5158,9 @@ function readFromCredentialsFile() {
|
|
|
4165
5158
|
join5(homedir2(), ".claude", ".credentials.json"),
|
|
4166
5159
|
join5(homedir2(), ".config", "claude", "credentials.json")
|
|
4167
5160
|
];
|
|
4168
|
-
for (const
|
|
5161
|
+
for (const path7 of candidates) {
|
|
4169
5162
|
try {
|
|
4170
|
-
const blob = readFileSync6(
|
|
5163
|
+
const blob = readFileSync6(path7, "utf8");
|
|
4171
5164
|
const creds = extractCredentials(blob);
|
|
4172
5165
|
if (creds) return creds;
|
|
4173
5166
|
} catch {
|
|
@@ -5100,8 +6093,10 @@ var init_aggregate = __esm({
|
|
|
5100
6093
|
// ../parser/dist/index.js
|
|
5101
6094
|
var dist_exports = {};
|
|
5102
6095
|
__export(dist_exports, {
|
|
6096
|
+
ANTIGRAVITY_METADATA: () => ANTIGRAVITY_METADATA,
|
|
5103
6097
|
CLAUDE_CODE_METADATA: () => CLAUDE_CODE_METADATA,
|
|
5104
6098
|
CODEX_METADATA: () => CODEX_METADATA,
|
|
6099
|
+
COWORK_METADATA: () => COWORK_METADATA,
|
|
5105
6100
|
GEMINI_METADATA: () => GEMINI_METADATA,
|
|
5106
6101
|
PRICES: () => PRICES,
|
|
5107
6102
|
RATE_PER_PCT: () => RATE_PER_PCT,
|
|
@@ -5142,6 +6137,7 @@ __export(dist_exports, {
|
|
|
5142
6137
|
predictUtilization: () => predictUtilization,
|
|
5143
6138
|
priorCalendarMonth: () => priorCalendarMonth,
|
|
5144
6139
|
priorCalendarWeek: () => priorCalendarWeek,
|
|
6140
|
+
projectRepoName: () => projectRepoName,
|
|
5145
6141
|
rowPrimaryIndex: () => rowPrimaryIndex,
|
|
5146
6142
|
sessionAirTimeMs: () => sessionAirTimeMs,
|
|
5147
6143
|
sessionDay: () => sessionDay,
|
|
@@ -5345,7 +6341,7 @@ var init_trivial = __esm({
|
|
|
5345
6341
|
});
|
|
5346
6342
|
|
|
5347
6343
|
// ../entries/dist/build.js
|
|
5348
|
-
var
|
|
6344
|
+
var IDLE_GAP_MS4;
|
|
5349
6345
|
var init_build = __esm({
|
|
5350
6346
|
"../entries/dist/build.js"() {
|
|
5351
6347
|
"use strict";
|
|
@@ -5353,7 +6349,7 @@ var init_build = __esm({
|
|
|
5353
6349
|
init_types();
|
|
5354
6350
|
init_signals();
|
|
5355
6351
|
init_trivial();
|
|
5356
|
-
|
|
6352
|
+
IDLE_GAP_MS4 = 3 * 60 * 1e3;
|
|
5357
6353
|
}
|
|
5358
6354
|
});
|
|
5359
6355
|
|
|
@@ -5386,11 +6382,11 @@ function digestsDir() {
|
|
|
5386
6382
|
digestsDirCached = envOverride ?? cclensPath("digests");
|
|
5387
6383
|
return digestsDirCached;
|
|
5388
6384
|
}
|
|
5389
|
-
function __setDigestsDirForTest(
|
|
5390
|
-
digestsDirCached =
|
|
5391
|
-
mkdirSync4(join6(
|
|
5392
|
-
mkdirSync4(join6(
|
|
5393
|
-
mkdirSync4(join6(
|
|
6385
|
+
function __setDigestsDirForTest(path7) {
|
|
6386
|
+
digestsDirCached = path7;
|
|
6387
|
+
mkdirSync4(join6(path7, "day"), { recursive: true });
|
|
6388
|
+
mkdirSync4(join6(path7, "week"), { recursive: true });
|
|
6389
|
+
mkdirSync4(join6(path7, "month"), { recursive: true });
|
|
5394
6390
|
}
|
|
5395
6391
|
function dayDigestPath(date) {
|
|
5396
6392
|
return join6(digestsDir(), "day", `${date}.json`);
|
|
@@ -5577,9 +6573,9 @@ function entriesDir() {
|
|
|
5577
6573
|
entriesDirCached = envOverride ?? cclensPath("entries");
|
|
5578
6574
|
return entriesDirCached;
|
|
5579
6575
|
}
|
|
5580
|
-
function __setEntriesDirForTest(
|
|
5581
|
-
entriesDirCached =
|
|
5582
|
-
mkdirSync5(
|
|
6576
|
+
function __setEntriesDirForTest(path7) {
|
|
6577
|
+
entriesDirCached = path7;
|
|
6578
|
+
mkdirSync5(path7, { recursive: true });
|
|
5583
6579
|
}
|
|
5584
6580
|
function pathFor(sessionId, localDay) {
|
|
5585
6581
|
return join7(entriesDir(), `${entryKey(sessionId, localDay)}.json`);
|
|
@@ -6115,8 +7111,8 @@ var init_parseUtil = __esm({
|
|
|
6115
7111
|
init_errors();
|
|
6116
7112
|
init_en();
|
|
6117
7113
|
makeIssue = (params) => {
|
|
6118
|
-
const { data, path:
|
|
6119
|
-
const fullPath = [...
|
|
7114
|
+
const { data, path: path7, errorMaps, issueData } = params;
|
|
7115
|
+
const fullPath = [...path7, ...issueData.path || []];
|
|
6120
7116
|
const fullIssue = {
|
|
6121
7117
|
...issueData,
|
|
6122
7118
|
path: fullPath
|
|
@@ -6424,11 +7420,11 @@ var init_types3 = __esm({
|
|
|
6424
7420
|
init_parseUtil();
|
|
6425
7421
|
init_util();
|
|
6426
7422
|
ParseInputLazyPath = class {
|
|
6427
|
-
constructor(parent, value,
|
|
7423
|
+
constructor(parent, value, path7, key) {
|
|
6428
7424
|
this._cachedPath = [];
|
|
6429
7425
|
this.parent = parent;
|
|
6430
7426
|
this.data = value;
|
|
6431
|
-
this._path =
|
|
7427
|
+
this._path = path7;
|
|
6432
7428
|
this._key = key;
|
|
6433
7429
|
}
|
|
6434
7430
|
get path() {
|
|
@@ -10086,10 +11082,10 @@ function snapshotAllTranscripts() {
|
|
|
10086
11082
|
}
|
|
10087
11083
|
return out;
|
|
10088
11084
|
}
|
|
10089
|
-
function readJsonlCwd(
|
|
11085
|
+
function readJsonlCwd(path7, maxLines = 8) {
|
|
10090
11086
|
let raw;
|
|
10091
11087
|
try {
|
|
10092
|
-
raw = readFileSync9(
|
|
11088
|
+
raw = readFileSync9(path7, "utf8");
|
|
10093
11089
|
} catch {
|
|
10094
11090
|
return void 0;
|
|
10095
11091
|
}
|
|
@@ -10143,10 +11139,10 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
|
|
|
10143
11139
|
}
|
|
10144
11140
|
throw new TmuxRunError(`timeout waiting for claude to create the session transcript (cwd: ${targetCwd})`);
|
|
10145
11141
|
}
|
|
10146
|
-
function parseTranscript2(
|
|
11142
|
+
function parseTranscript2(path7, defaultModel) {
|
|
10147
11143
|
let raw;
|
|
10148
11144
|
try {
|
|
10149
|
-
raw = readFileSync9(
|
|
11145
|
+
raw = readFileSync9(path7, "utf8");
|
|
10150
11146
|
} catch {
|
|
10151
11147
|
return { assembled: "", inputTokens: 0, outputTokens: 0, modelUsed: defaultModel, done: false };
|
|
10152
11148
|
}
|
|
@@ -10275,15 +11271,15 @@ function newRunId(kind) {
|
|
|
10275
11271
|
function tracePath(runId) {
|
|
10276
11272
|
return join9(RUNS_DIR, `${runId}.jsonl`);
|
|
10277
11273
|
}
|
|
10278
|
-
function safeAppend(
|
|
11274
|
+
function safeAppend(path7, line) {
|
|
10279
11275
|
try {
|
|
10280
|
-
appendFileSync2(
|
|
11276
|
+
appendFileSync2(path7, line);
|
|
10281
11277
|
} catch {
|
|
10282
11278
|
}
|
|
10283
11279
|
}
|
|
10284
|
-
function safeWrite(
|
|
11280
|
+
function safeWrite(path7, line) {
|
|
10285
11281
|
try {
|
|
10286
|
-
writeFileSync6(
|
|
11282
|
+
writeFileSync6(path7, line);
|
|
10287
11283
|
} catch {
|
|
10288
11284
|
}
|
|
10289
11285
|
}
|
|
@@ -10361,7 +11357,7 @@ async function runClaudeSubprocess(args2) {
|
|
|
10361
11357
|
return runClaudePrintMode(args2);
|
|
10362
11358
|
}
|
|
10363
11359
|
function runClaudePrintMode(args2) {
|
|
10364
|
-
return new Promise((
|
|
11360
|
+
return new Promise((resolve3, reject) => {
|
|
10365
11361
|
ensureRunsDir();
|
|
10366
11362
|
const kind = detectKindFromSystemPrompt(args2.systemPrompt);
|
|
10367
11363
|
const runId = newRunId(kind);
|
|
@@ -10492,7 +11488,7 @@ ${args2.reminder}` : args2.userPrompt;
|
|
|
10492
11488
|
reject(new Error(`claude exited ${code}: ${stderr.trim().slice(0, 300)}`));
|
|
10493
11489
|
return;
|
|
10494
11490
|
}
|
|
10495
|
-
|
|
11491
|
+
resolve3({ content: buffer, input_tokens: inputTokens, output_tokens: outputTokens, model: modelUsed });
|
|
10496
11492
|
});
|
|
10497
11493
|
proc.on("error", (err) => {
|
|
10498
11494
|
safeAppend(trace, JSON.stringify({ _meta: { type: "spawn_error", run_id: runId, ts: (/* @__PURE__ */ new Date()).toISOString(), error: err.message } }) + "\n");
|
|
@@ -10697,8 +11693,8 @@ function spendPath() {
|
|
|
10697
11693
|
spendPathCached = cclensPath("llm-spend.jsonl");
|
|
10698
11694
|
return spendPathCached;
|
|
10699
11695
|
}
|
|
10700
|
-
function __setSpendPathForTest(
|
|
10701
|
-
spendPathCached =
|
|
11696
|
+
function __setSpendPathForTest(path7) {
|
|
11697
|
+
spendPathCached = path7;
|
|
10702
11698
|
}
|
|
10703
11699
|
function appendSpend(record) {
|
|
10704
11700
|
const p = spendPath();
|
|
@@ -10748,8 +11744,8 @@ function lockPath() {
|
|
|
10748
11744
|
lockPathCached = cclensPath("llm-interactive.lock");
|
|
10749
11745
|
return lockPathCached;
|
|
10750
11746
|
}
|
|
10751
|
-
function __setInteractiveLockPathForTest(
|
|
10752
|
-
lockPathCached =
|
|
11747
|
+
function __setInteractiveLockPathForTest(path7) {
|
|
11748
|
+
lockPathCached = path7;
|
|
10753
11749
|
}
|
|
10754
11750
|
function touchLock() {
|
|
10755
11751
|
writeFileSync7(lockPath(), String(process.pid), "utf8");
|
|
@@ -10832,10 +11828,10 @@ async function runEnrichmentQueue(settings, opts = {}) {
|
|
|
10832
11828
|
if (monthToDateSpend() >= budget)
|
|
10833
11829
|
return { skipped: "budget_cap_reached" };
|
|
10834
11830
|
const queue = listEntriesWithStatus(["pending", "error"]).filter((e) => (e.enrichment.retry_count ?? 0) < MAX_RETRY_COUNT);
|
|
10835
|
-
const
|
|
11831
|
+
const todayLocal2 = toLocalDay2(now());
|
|
10836
11832
|
let enriched = 0, errors = 0, skipped = 0;
|
|
10837
11833
|
for (const entry of queue) {
|
|
10838
|
-
if (entry.local_day ===
|
|
11834
|
+
if (entry.local_day === todayLocal2) {
|
|
10839
11835
|
skipped++;
|
|
10840
11836
|
continue;
|
|
10841
11837
|
}
|
|
@@ -10906,8 +11902,8 @@ function settingsPath() {
|
|
|
10906
11902
|
settingsPathCached = cclensPath("settings.json");
|
|
10907
11903
|
return settingsPathCached;
|
|
10908
11904
|
}
|
|
10909
|
-
function __setSettingsPathForTest(
|
|
10910
|
-
settingsPathCached =
|
|
11905
|
+
function __setSettingsPathForTest(path7) {
|
|
11906
|
+
settingsPathCached = path7;
|
|
10911
11907
|
}
|
|
10912
11908
|
function toDisk(s) {
|
|
10913
11909
|
return {
|
|
@@ -11144,7 +12140,7 @@ function rollupOutcomeDay(entries2) {
|
|
|
11144
12140
|
return "exploratory";
|
|
11145
12141
|
return "trivial";
|
|
11146
12142
|
}
|
|
11147
|
-
function
|
|
12143
|
+
function truncate5(s, max) {
|
|
11148
12144
|
if (s.length <= max)
|
|
11149
12145
|
return s;
|
|
11150
12146
|
return s.slice(0, max - 1).trimEnd() + "\u2026";
|
|
@@ -11200,7 +12196,7 @@ function computeDaySignals(entries2) {
|
|
|
11200
12196
|
type,
|
|
11201
12197
|
count: v.count,
|
|
11202
12198
|
sample_description: v.sample_description,
|
|
11203
|
-
sample_prompt_preview:
|
|
12199
|
+
sample_prompt_preview: truncate5(v.sample_prompt_preview, 200)
|
|
11204
12200
|
}));
|
|
11205
12201
|
const frameCounts = /* @__PURE__ */ new Map();
|
|
11206
12202
|
for (const s of signalsList) {
|
|
@@ -11219,7 +12215,7 @@ function computeDaySignals(entries2) {
|
|
|
11219
12215
|
if ((e.first_user ?? "").length > 0)
|
|
11220
12216
|
verbosity_distribution[s.verbosity] += 1;
|
|
11221
12217
|
for (const ref of s.external_refs) {
|
|
11222
|
-
external_refs.push({ session_id: e.session_id, kind: ref.kind, preview:
|
|
12218
|
+
external_refs.push({ session_id: e.session_id, kind: ref.kind, preview: truncate5(ref.preview, 200) });
|
|
11223
12219
|
}
|
|
11224
12220
|
const ints = e.numbers.interrupts ?? 0;
|
|
11225
12221
|
interrupts += ints;
|
|
@@ -12092,7 +13088,7 @@ function computeInteractionModes(entries2) {
|
|
|
12092
13088
|
date: entry.local_day,
|
|
12093
13089
|
project_display: prettyProject3(entry.project),
|
|
12094
13090
|
type: sa.type,
|
|
12095
|
-
prompt_preview:
|
|
13091
|
+
prompt_preview: truncate6(sa.prompt_preview, 200)
|
|
12096
13092
|
});
|
|
12097
13093
|
}
|
|
12098
13094
|
const skillExamples = [];
|
|
@@ -12109,7 +13105,7 @@ function computeInteractionModes(entries2) {
|
|
|
12109
13105
|
skillExamples.push({
|
|
12110
13106
|
date: e.local_day,
|
|
12111
13107
|
skill,
|
|
12112
|
-
first_user_preview:
|
|
13108
|
+
first_user_preview: truncate6(e.first_user, 200)
|
|
12113
13109
|
});
|
|
12114
13110
|
}
|
|
12115
13111
|
}
|
|
@@ -12126,7 +13122,7 @@ function computeInteractionModes(entries2) {
|
|
|
12126
13122
|
project_display: prettyProject3(longestTurnEntry.project),
|
|
12127
13123
|
active_min: longestTurnEntry.numbers.active_min,
|
|
12128
13124
|
top_tools: longestTurnEntry.top_tools.slice(0, 5),
|
|
12129
|
-
first_user_preview:
|
|
13125
|
+
first_user_preview: truncate6(longestTurnEntry.first_user, 200)
|
|
12130
13126
|
} : null;
|
|
12131
13127
|
const tools_per_turn = turn_count > 0 ? tools_total / turn_count : 0;
|
|
12132
13128
|
const label = tools_per_turn < 5 ? "rapid" : tools_per_turn < 15 ? "mixed" : "batch";
|
|
@@ -12157,7 +13153,7 @@ function computeInteractionModes(entries2) {
|
|
|
12157
13153
|
}
|
|
12158
13154
|
};
|
|
12159
13155
|
}
|
|
12160
|
-
function
|
|
13156
|
+
function truncate6(s, max) {
|
|
12161
13157
|
if (s.length <= max)
|
|
12162
13158
|
return s;
|
|
12163
13159
|
return s.slice(0, max - 1).trimEnd() + "\u2026";
|
|
@@ -12204,7 +13200,7 @@ function computeWorkingShapes(dayDigests, entriesByDay = /* @__PURE__ */ new Map
|
|
|
12204
13200
|
evidence_subagent = {
|
|
12205
13201
|
type: sa.type,
|
|
12206
13202
|
description: sa.description,
|
|
12207
|
-
prompt_preview:
|
|
13203
|
+
prompt_preview: truncate6(sa.prompt_preview, 200)
|
|
12208
13204
|
};
|
|
12209
13205
|
}
|
|
12210
13206
|
const project_display = repEntry ? prettyProject3(repEntry.project) : dd.projects[0]?.display_name ?? "";
|
|
@@ -12215,7 +13211,7 @@ function computeWorkingShapes(dayDigests, entriesByDay = /* @__PURE__ */ new Map
|
|
|
12215
13211
|
outcome: dayOutcome.get(dd.key) ?? null,
|
|
12216
13212
|
helpfulness: dayHelp.get(dd.key) ?? null,
|
|
12217
13213
|
evidence_subagent,
|
|
12218
|
-
evidence_first_user: repEntry?.first_user ?
|
|
13214
|
+
evidence_first_user: repEntry?.first_user ? truncate6(repEntry.first_user, 200) : null,
|
|
12219
13215
|
day_signature: dd.day_signature ?? null
|
|
12220
13216
|
};
|
|
12221
13217
|
});
|
|
@@ -12290,7 +13286,7 @@ function computeInteractionGrammar(dayDigests, entriesByDay = /* @__PURE__ */ ne
|
|
|
12290
13286
|
date: day2,
|
|
12291
13287
|
session_id: ref.session_id,
|
|
12292
13288
|
ref_kind: ref.kind,
|
|
12293
|
-
preview:
|
|
13289
|
+
preview: truncate6(ref.preview, 200)
|
|
12294
13290
|
});
|
|
12295
13291
|
}
|
|
12296
13292
|
total_interrupts += signals.comm_style.steering.interrupts;
|
|
@@ -12362,7 +13358,7 @@ function computeInteractionGrammar(dayDigests, entriesByDay = /* @__PURE__ */ ne
|
|
|
12362
13358
|
count: v.count,
|
|
12363
13359
|
days: [...v.days].sort(),
|
|
12364
13360
|
sample_description: v.sample_description,
|
|
12365
|
-
sample_prompt_preview:
|
|
13361
|
+
sample_prompt_preview: truncate6(v.sample_prompt_preview, 200)
|
|
12366
13362
|
})),
|
|
12367
13363
|
threads,
|
|
12368
13364
|
communication_style: {
|
|
@@ -13010,7 +14006,7 @@ function activeMs(timestamps) {
|
|
|
13010
14006
|
let active = 0;
|
|
13011
14007
|
for (let i = 1; i < ts.length; i++) {
|
|
13012
14008
|
const dt = ts[i] - ts[i - 1];
|
|
13013
|
-
if (dt <
|
|
14009
|
+
if (dt < IDLE_GAP_MS5)
|
|
13014
14010
|
active += dt;
|
|
13015
14011
|
}
|
|
13016
14012
|
return active;
|
|
@@ -13181,7 +14177,7 @@ function buildSessionSlice(entry, events, daySignature) {
|
|
|
13181
14177
|
let intEnd = sortedTs[0];
|
|
13182
14178
|
for (let i = 1; i < sortedTs.length; i++) {
|
|
13183
14179
|
const dt = sortedTs[i] - intEnd;
|
|
13184
|
-
if (dt >=
|
|
14180
|
+
if (dt >= IDLE_GAP_MS5) {
|
|
13185
14181
|
intervals.push({
|
|
13186
14182
|
start_min: fmtMin(intStart - sliceStartMs),
|
|
13187
14183
|
end_min: fmtMin(intEnd - sliceStartMs)
|
|
@@ -13578,14 +14574,14 @@ async function generateTopSession(slice, opts = {}) {
|
|
|
13578
14574
|
void lastModel;
|
|
13579
14575
|
}
|
|
13580
14576
|
}
|
|
13581
|
-
var
|
|
14577
|
+
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
14578
|
var init_top_sessions = __esm({
|
|
13583
14579
|
"../entries/dist/top-sessions.js"() {
|
|
13584
14580
|
"use strict";
|
|
13585
14581
|
init_zod();
|
|
13586
14582
|
init_signals();
|
|
13587
14583
|
init_llm_runner();
|
|
13588
|
-
|
|
14584
|
+
IDLE_GAP_MS5 = 3 * 60 * 1e3;
|
|
13589
14585
|
LONG_AUTONOMOUS_MIN = 20;
|
|
13590
14586
|
N_USER = 150;
|
|
13591
14587
|
N_FIRST_AGENT = 150;
|
|
@@ -14104,6 +15100,10 @@ async function* runMonthDigestPipeline(yearMonth, opts) {
|
|
|
14104
15100
|
} else {
|
|
14105
15101
|
digest2.is_live = true;
|
|
14106
15102
|
setCurrentMonthDigestInCache(yearMonth, digest2, now());
|
|
15103
|
+
if (opts.force === true) {
|
|
15104
|
+
writeMonthDigest(digest2);
|
|
15105
|
+
yield { type: "saved", path: `~/.cclens/digests/month/${yearMonth}.json` };
|
|
15106
|
+
}
|
|
14107
15107
|
}
|
|
14108
15108
|
yield { type: "digest", digest: digest2 };
|
|
14109
15109
|
} finally {
|
|
@@ -14754,7 +15754,7 @@ function sessionTouchesDay(s, day2) {
|
|
|
14754
15754
|
}
|
|
14755
15755
|
return sessionDay(s) === day2;
|
|
14756
15756
|
}
|
|
14757
|
-
function buildRichRollupBlocks(day2, daySessions, entries2, privateProjects) {
|
|
15757
|
+
function buildRichRollupBlocks(day2, daySessions, entries2, privateProjects, resolveRepo) {
|
|
14758
15758
|
const bounds = dayBoundsMs(day2);
|
|
14759
15759
|
const clippedSessions = [];
|
|
14760
15760
|
for (const s of daySessions) {
|
|
@@ -14764,16 +15764,40 @@ function buildRichRollupBlocks(day2, daySessions, entries2, privateProjects) {
|
|
|
14764
15764
|
}
|
|
14765
15765
|
const bursts = computeBurstsFromSessions(clippedSessions);
|
|
14766
15766
|
const stats = summarizeBursts(bursts);
|
|
15767
|
+
const repoForEntry = (e) => {
|
|
15768
|
+
if (resolveRepo) {
|
|
15769
|
+
const own = resolveRepo(e.project);
|
|
15770
|
+
if (own) return own;
|
|
15771
|
+
const counts = /* @__PURE__ */ new Map();
|
|
15772
|
+
for (const d of e.edited_dirs ?? []) {
|
|
15773
|
+
const r = resolveRepo(d);
|
|
15774
|
+
if (r) counts.set(r, (counts.get(r) ?? 0) + 1);
|
|
15775
|
+
}
|
|
15776
|
+
const dominant = [...counts.entries()].sort((a, b) => b[1] - a[1])[0]?.[0];
|
|
15777
|
+
if (dominant) return dominant;
|
|
15778
|
+
}
|
|
15779
|
+
return e.github_repos?.length === 1 ? e.github_repos[0] : null;
|
|
15780
|
+
};
|
|
15781
|
+
const sessionRepo = /* @__PURE__ */ new Map();
|
|
15782
|
+
for (const e of entries2) {
|
|
15783
|
+
if (privateProjects.has(projectRepoName(e.project)) || privateProjects.has(e.project)) continue;
|
|
15784
|
+
const r = repoForEntry(e);
|
|
15785
|
+
if (r) sessionRepo.set(e.session_id, r);
|
|
15786
|
+
}
|
|
14767
15787
|
const projects = /* @__PURE__ */ new Map();
|
|
14768
15788
|
for (const s of clippedSessions) {
|
|
14769
|
-
const
|
|
14770
|
-
|
|
15789
|
+
const canonical = canonicalProjectName(s.projectName);
|
|
15790
|
+
const name = projectRepoName(s.projectName);
|
|
15791
|
+
if (privateProjects.has(name) || privateProjects.has(canonical)) continue;
|
|
15792
|
+
const repo = resolveRepo?.(canonical) ?? sessionRepo.get(s.id);
|
|
15793
|
+
const key = repo ?? name;
|
|
14771
15794
|
const ms = s.activeSegments.reduce((sum, seg) => sum + (seg.endMs - seg.startMs), 0);
|
|
14772
|
-
const cur = projects.get(
|
|
15795
|
+
const cur = projects.get(key) ?? { project: name, agentTimeMs: 0, sessions: 0, ...repo ? { resolved: repo } : {} };
|
|
14773
15796
|
cur.agentTimeMs += ms;
|
|
14774
15797
|
cur.sessions += 1;
|
|
14775
|
-
projects.set(
|
|
15798
|
+
projects.set(key, cur);
|
|
14776
15799
|
}
|
|
15800
|
+
const projectRepos = /* @__PURE__ */ new Map();
|
|
14777
15801
|
const workingShapes = /* @__PURE__ */ new Map();
|
|
14778
15802
|
const skills = /* @__PURE__ */ new Map();
|
|
14779
15803
|
const subagents = /* @__PURE__ */ new Map();
|
|
@@ -14787,12 +15811,12 @@ function buildRichRollupBlocks(day2, daySessions, entries2, privateProjects) {
|
|
|
14787
15811
|
let longTotalMin = 0;
|
|
14788
15812
|
let longMaxSingleMin = 0;
|
|
14789
15813
|
for (const e of entries2) {
|
|
14790
|
-
if (privateProjects.has(e.project)) continue;
|
|
15814
|
+
if (privateProjects.has(projectRepoName(e.project)) || privateProjects.has(e.project)) continue;
|
|
14791
15815
|
const shape = e.signals?.working_shape ?? null;
|
|
14792
15816
|
if (shape) {
|
|
14793
15817
|
const cur = workingShapes.get(shape) ?? { sessions: 0, agentTimeMs: 0 };
|
|
14794
15818
|
cur.sessions += 1;
|
|
14795
|
-
cur.agentTimeMs += e.numbers.active_min * 6e4;
|
|
15819
|
+
cur.agentTimeMs += Math.round(e.numbers.active_min * 6e4);
|
|
14796
15820
|
workingShapes.set(shape, cur);
|
|
14797
15821
|
}
|
|
14798
15822
|
for (const [name, count] of Object.entries(e.skills)) {
|
|
@@ -14807,6 +15831,12 @@ function buildRichRollupBlocks(day2, daySessions, entries2, privateProjects) {
|
|
|
14807
15831
|
prs += e.numbers.prs;
|
|
14808
15832
|
commits += e.numbers.commits;
|
|
14809
15833
|
pushes += e.numbers.pushes;
|
|
15834
|
+
if (e.github_repos?.length) {
|
|
15835
|
+
const key = sessionRepo.get(e.session_id) ?? projectRepoName(e.project);
|
|
15836
|
+
const set = projectRepos.get(key) ?? /* @__PURE__ */ new Set();
|
|
15837
|
+
for (const r of e.github_repos) set.add(r);
|
|
15838
|
+
projectRepos.set(key, set);
|
|
15839
|
+
}
|
|
14810
15840
|
if (e.flags.includes("long_autonomous")) {
|
|
14811
15841
|
longCount += 1;
|
|
14812
15842
|
longTotalMin += e.numbers.active_min;
|
|
@@ -14814,11 +15844,21 @@ function buildRichRollupBlocks(day2, daySessions, entries2, privateProjects) {
|
|
|
14814
15844
|
}
|
|
14815
15845
|
}
|
|
14816
15846
|
return {
|
|
14817
|
-
projects: Array.from(projects.entries()).map(([
|
|
15847
|
+
projects: Array.from(projects.entries()).map(([key, v]) => {
|
|
15848
|
+
const extras = [...projectRepos.get(key) ?? []].filter((r) => r !== v.resolved);
|
|
15849
|
+
const repos = v.resolved ? [v.resolved, ...extras] : extras;
|
|
15850
|
+
return {
|
|
15851
|
+
project: v.project,
|
|
15852
|
+
agentTimeMs: v.agentTimeMs,
|
|
15853
|
+
sessions: v.sessions,
|
|
15854
|
+
...repos.length ? { githubRepos: repos.slice(0, 5) } : {}
|
|
15855
|
+
};
|
|
15856
|
+
}).sort((a, b) => b.agentTimeMs - a.agentTimeMs),
|
|
14818
15857
|
workingShapes: Array.from(workingShapes.entries()).map(([shape, v]) => ({ shape, ...v })).sort((a, b) => b.sessions - a.sessions),
|
|
14819
15858
|
concurrencyPeak: stats.peakConcurrent,
|
|
14820
15859
|
parallelMinutes: Math.round(stats.totalParallelMs / 6e4),
|
|
14821
|
-
|
|
15860
|
+
// Wire schema requires integer minutes (active_min is a float).
|
|
15861
|
+
longAutonomous: { count: longCount, totalMin: Math.round(longTotalMin), maxSingleMin: Math.round(longMaxSingleMin) },
|
|
14822
15862
|
toolErrors,
|
|
14823
15863
|
skillsLoaded: Array.from(skills.entries()).map(([name, sessions]) => ({ name, sessions })).sort((a, b) => b.sessions - a.sessions),
|
|
14824
15864
|
subagentsDispatched: Array.from(subagents.entries()).map(([type, count]) => ({ type, count })).sort((a, b) => b.count - a.count),
|
|
@@ -14847,10 +15887,10 @@ function buildEnrichedExtras(entries2) {
|
|
|
14847
15887
|
}
|
|
14848
15888
|
return { outcomeMix, helpfulnessMix, goalMix };
|
|
14849
15889
|
}
|
|
14850
|
-
function buildRichBlocksForDay(day2, daySessions, privateProjects, enrichmentOptIn) {
|
|
15890
|
+
function buildRichBlocksForDay(day2, daySessions, privateProjects, enrichmentOptIn, resolveRepo) {
|
|
14851
15891
|
const entries2 = listEntriesForDay(day2);
|
|
14852
15892
|
if (entries2.length === 0) return void 0;
|
|
14853
|
-
const rich = buildRichRollupBlocks(day2, daySessions, entries2, privateProjects);
|
|
15893
|
+
const rich = buildRichRollupBlocks(day2, daySessions, entries2, privateProjects, resolveRepo);
|
|
14854
15894
|
const enriched = enrichmentOptIn ? buildEnrichedExtras(entries2) : void 0;
|
|
14855
15895
|
return enriched ? { rich, enriched } : { rich };
|
|
14856
15896
|
}
|
|
@@ -14859,10 +15899,11 @@ function buildIngestPayload(inputs) {
|
|
|
14859
15899
|
return {
|
|
14860
15900
|
ingestId: randomUUID2(),
|
|
14861
15901
|
observedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14862
|
-
...richRollup || inputs.enrichedExtras ? { schemaVersion: RICH_ROLLUP_SCHEMA_VERSION } : {},
|
|
15902
|
+
...richRollup || inputs.enrichedExtras || inputs.artifactSignals ? { schemaVersion: RICH_ROLLUP_SCHEMA_VERSION } : {},
|
|
14863
15903
|
...inputs.rollup ? { dailyRollup: inputs.rollup } : {},
|
|
14864
15904
|
...richRollup ? { richRollup } : {},
|
|
14865
15905
|
...inputs.enrichedExtras ? { enrichedExtras: inputs.enrichedExtras } : {},
|
|
15906
|
+
...inputs.artifactSignals ? { artifactSignals: inputs.artifactSignals } : {},
|
|
14866
15907
|
...inputs.usageSnapshot ? { usageSnapshot: inputs.usageSnapshot } : {},
|
|
14867
15908
|
...inputs.planTier ? { planTier: inputs.planTier } : {},
|
|
14868
15909
|
...inputs.cyclePeaks ? { cyclePeaks: inputs.cyclePeaks } : {}
|
|
@@ -14894,15 +15935,83 @@ var init_push = __esm({
|
|
|
14894
15935
|
}
|
|
14895
15936
|
});
|
|
14896
15937
|
|
|
15938
|
+
// src/team/git-remote.ts
|
|
15939
|
+
import { existsSync as existsSync12, readFileSync as readFileSync13, statSync as statSync3 } from "node:fs";
|
|
15940
|
+
import { dirname as dirname9, isAbsolute, join as join10, resolve } from "node:path";
|
|
15941
|
+
function parseGithubRemote(url) {
|
|
15942
|
+
const m = url.trim().match(GITHUB_URL_RE);
|
|
15943
|
+
return m ? `${m[1]}/${m[2]}`.toLowerCase() : null;
|
|
15944
|
+
}
|
|
15945
|
+
function originUrl(configText) {
|
|
15946
|
+
let inOrigin = false;
|
|
15947
|
+
for (const line of configText.split("\n")) {
|
|
15948
|
+
const t = line.trim();
|
|
15949
|
+
if (t.startsWith("[")) {
|
|
15950
|
+
inOrigin = /^\[remote\s+"origin"\]/.test(t);
|
|
15951
|
+
continue;
|
|
15952
|
+
}
|
|
15953
|
+
if (!inOrigin) continue;
|
|
15954
|
+
const m = t.match(/^url\s*=\s*(.+)$/);
|
|
15955
|
+
if (m) return m[1].trim();
|
|
15956
|
+
}
|
|
15957
|
+
return null;
|
|
15958
|
+
}
|
|
15959
|
+
function gitConfigPathFor(dir) {
|
|
15960
|
+
const dotGit = join10(dir, ".git");
|
|
15961
|
+
const st = statSync3(dotGit, { throwIfNoEntry: false });
|
|
15962
|
+
if (!st) return null;
|
|
15963
|
+
if (st.isDirectory()) return join10(dotGit, "config");
|
|
15964
|
+
const m = readFileSync13(dotGit, "utf8").match(/^gitdir:\s*(.+)\s*$/m);
|
|
15965
|
+
if (!m) return null;
|
|
15966
|
+
const gd = isAbsolute(m[1]) ? m[1] : resolve(dir, m[1]);
|
|
15967
|
+
const commondirFile = join10(gd, "commondir");
|
|
15968
|
+
if (existsSync12(commondirFile)) {
|
|
15969
|
+
const common = readFileSync13(commondirFile, "utf8").trim();
|
|
15970
|
+
return join10(isAbsolute(common) ? common : resolve(gd, common), "config");
|
|
15971
|
+
}
|
|
15972
|
+
return join10(gd, "config");
|
|
15973
|
+
}
|
|
15974
|
+
function createRepoResolver() {
|
|
15975
|
+
const cache = /* @__PURE__ */ new Map();
|
|
15976
|
+
return (dir) => {
|
|
15977
|
+
if (!dir || !isAbsolute(dir)) return null;
|
|
15978
|
+
const hit = cache.get(dir);
|
|
15979
|
+
if (hit !== void 0) return hit;
|
|
15980
|
+
let repo = null;
|
|
15981
|
+
try {
|
|
15982
|
+
for (let d = dir; ; d = dirname9(d)) {
|
|
15983
|
+
const config = gitConfigPathFor(d);
|
|
15984
|
+
if (config && existsSync12(config)) {
|
|
15985
|
+
const url = originUrl(readFileSync13(config, "utf8"));
|
|
15986
|
+
repo = url ? parseGithubRemote(url) : null;
|
|
15987
|
+
break;
|
|
15988
|
+
}
|
|
15989
|
+
if (d === dirname9(d)) break;
|
|
15990
|
+
}
|
|
15991
|
+
} catch {
|
|
15992
|
+
repo = null;
|
|
15993
|
+
}
|
|
15994
|
+
cache.set(dir, repo);
|
|
15995
|
+
return repo;
|
|
15996
|
+
};
|
|
15997
|
+
}
|
|
15998
|
+
var GITHUB_URL_RE;
|
|
15999
|
+
var init_git_remote = __esm({
|
|
16000
|
+
"src/team/git-remote.ts"() {
|
|
16001
|
+
"use strict";
|
|
16002
|
+
GITHUB_URL_RE = /github\.com[:/]([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+?)(?:\.git)?$/;
|
|
16003
|
+
}
|
|
16004
|
+
});
|
|
16005
|
+
|
|
14897
16006
|
// src/team/queue.ts
|
|
14898
|
-
import { readFileSync as
|
|
14899
|
-
import { dirname as
|
|
16007
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync9, appendFileSync as appendFileSync4, statSync as statSync4, mkdirSync as mkdirSync10 } from "node:fs";
|
|
16008
|
+
import { dirname as dirname10 } from "node:path";
|
|
14900
16009
|
function enqueuePayload(payload, queuePath = QUEUE_PATH) {
|
|
14901
|
-
mkdirSync10(
|
|
16010
|
+
mkdirSync10(dirname10(queuePath), { recursive: true });
|
|
14902
16011
|
const entry = { payload, enqueuedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
14903
16012
|
appendFileSync4(queuePath, JSON.stringify(entry) + "\n", "utf8");
|
|
14904
16013
|
try {
|
|
14905
|
-
const { size } =
|
|
16014
|
+
const { size } = statSync4(queuePath);
|
|
14906
16015
|
if (size > MAX_SIZE_BYTES) {
|
|
14907
16016
|
pruneOldest(queuePath);
|
|
14908
16017
|
}
|
|
@@ -14912,7 +16021,7 @@ function enqueuePayload(payload, queuePath = QUEUE_PATH) {
|
|
|
14912
16021
|
function dequeuePayloads(queuePath = QUEUE_PATH) {
|
|
14913
16022
|
let lines;
|
|
14914
16023
|
try {
|
|
14915
|
-
lines =
|
|
16024
|
+
lines = readFileSync14(queuePath, "utf8").trim().split("\n").filter(Boolean);
|
|
14916
16025
|
} catch {
|
|
14917
16026
|
return [];
|
|
14918
16027
|
}
|
|
@@ -14933,7 +16042,7 @@ function dequeuePayloads(queuePath = QUEUE_PATH) {
|
|
|
14933
16042
|
function pruneOldest(queuePath) {
|
|
14934
16043
|
let lines;
|
|
14935
16044
|
try {
|
|
14936
|
-
lines =
|
|
16045
|
+
lines = readFileSync14(queuePath, "utf8").trim().split("\n").filter(Boolean);
|
|
14937
16046
|
} catch {
|
|
14938
16047
|
return;
|
|
14939
16048
|
}
|
|
@@ -14952,8 +16061,8 @@ var init_queue2 = __esm({
|
|
|
14952
16061
|
});
|
|
14953
16062
|
|
|
14954
16063
|
// src/usage/profile.ts
|
|
14955
|
-
import { existsSync as
|
|
14956
|
-
import { dirname as
|
|
16064
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync11, readFileSync as readFileSync15, writeFileSync as writeFileSync10 } from "node:fs";
|
|
16065
|
+
import { dirname as dirname11 } from "node:path";
|
|
14957
16066
|
function mapRateLimitTier(rateLimitTier) {
|
|
14958
16067
|
switch (rateLimitTier) {
|
|
14959
16068
|
case "default_claude_pro":
|
|
@@ -14993,9 +16102,9 @@ async function fetchProfile(nowMs = Date.now()) {
|
|
|
14993
16102
|
};
|
|
14994
16103
|
}
|
|
14995
16104
|
function readCachedProfile(cachePath) {
|
|
14996
|
-
if (!
|
|
16105
|
+
if (!existsSync13(cachePath)) return null;
|
|
14997
16106
|
try {
|
|
14998
|
-
const raw = JSON.parse(
|
|
16107
|
+
const raw = JSON.parse(readFileSync15(cachePath, "utf8"));
|
|
14999
16108
|
if (typeof raw.fetchedAtMs !== "number" || !raw.profile) return null;
|
|
15000
16109
|
return raw;
|
|
15001
16110
|
} catch {
|
|
@@ -15003,7 +16112,7 @@ function readCachedProfile(cachePath) {
|
|
|
15003
16112
|
}
|
|
15004
16113
|
}
|
|
15005
16114
|
function writeCachedProfile(cachePath, profile, nowMs = Date.now()) {
|
|
15006
|
-
mkdirSync11(
|
|
16115
|
+
mkdirSync11(dirname11(cachePath), { recursive: true });
|
|
15007
16116
|
writeFileSync10(
|
|
15008
16117
|
cachePath,
|
|
15009
16118
|
JSON.stringify({ fetchedAtMs: nowMs, profile }, null, 2),
|
|
@@ -15185,11 +16294,11 @@ var init_backfill = __esm({
|
|
|
15185
16294
|
|
|
15186
16295
|
// src/team/last-push.ts
|
|
15187
16296
|
import { writeFileSync as writeFileSync11, unlinkSync as unlinkSync5, mkdirSync as mkdirSync12 } from "node:fs";
|
|
15188
|
-
import { join as
|
|
16297
|
+
import { join as join11 } from "node:path";
|
|
15189
16298
|
function write(record, dir) {
|
|
15190
16299
|
const d = dir ?? cclensHome();
|
|
15191
16300
|
mkdirSync12(d, { recursive: true });
|
|
15192
|
-
writeFileSync11(
|
|
16301
|
+
writeFileSync11(join11(d, LAST_PUSH_FILE), JSON.stringify(record, null, 2), { mode: 384 });
|
|
15193
16302
|
}
|
|
15194
16303
|
function writeLastPushSuccess(payload, dir) {
|
|
15195
16304
|
write({ pushedAt: (/* @__PURE__ */ new Date()).toISOString(), ok: true, payload }, dir);
|
|
@@ -15200,7 +16309,7 @@ function writeLastPushFailure(payload, error, dir) {
|
|
|
15200
16309
|
function clearLastPush(dir) {
|
|
15201
16310
|
const d = dir ?? cclensHome();
|
|
15202
16311
|
try {
|
|
15203
|
-
unlinkSync5(
|
|
16312
|
+
unlinkSync5(join11(d, LAST_PUSH_FILE));
|
|
15204
16313
|
} catch {
|
|
15205
16314
|
}
|
|
15206
16315
|
}
|
|
@@ -15213,6 +16322,194 @@ var init_last_push = __esm({
|
|
|
15213
16322
|
}
|
|
15214
16323
|
});
|
|
15215
16324
|
|
|
16325
|
+
// src/perception/file-probe.ts
|
|
16326
|
+
var file_probe_exports = {};
|
|
16327
|
+
__export(file_probe_exports, {
|
|
16328
|
+
pathHash: () => pathHash,
|
|
16329
|
+
probeArtifactSignals: () => probeArtifactSignals
|
|
16330
|
+
});
|
|
16331
|
+
import { createHash } from "node:crypto";
|
|
16332
|
+
import { existsSync as existsSync14, readdirSync as readdirSync4, statSync as statSync5 } from "node:fs";
|
|
16333
|
+
import { homedir as homedir4 } from "node:os";
|
|
16334
|
+
import { join as join12, relative, resolve as resolve2, sep } from "node:path";
|
|
16335
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
16336
|
+
function pathHash(relPath) {
|
|
16337
|
+
return createHash("sha256").update(relPath.split(sep).join("/")).digest("hex").slice(0, 32);
|
|
16338
|
+
}
|
|
16339
|
+
function defaultScanRoots(extraRoots = []) {
|
|
16340
|
+
const roots = [];
|
|
16341
|
+
const home = join12(homedir4(), ".claude");
|
|
16342
|
+
if (existsSync14(home)) roots.push({ root: home, label: "user" });
|
|
16343
|
+
for (const e of extraRoots) {
|
|
16344
|
+
const r = resolve2(e, ".claude");
|
|
16345
|
+
if (existsSync14(r) && r !== home) roots.push({ root: r, label: "project" });
|
|
16346
|
+
}
|
|
16347
|
+
return roots;
|
|
16348
|
+
}
|
|
16349
|
+
function listMarkdownFiles(dir) {
|
|
16350
|
+
if (!existsSync14(dir)) return [];
|
|
16351
|
+
const out = [];
|
|
16352
|
+
let entries2;
|
|
16353
|
+
try {
|
|
16354
|
+
entries2 = readdirSync4(dir);
|
|
16355
|
+
} catch {
|
|
16356
|
+
return [];
|
|
16357
|
+
}
|
|
16358
|
+
for (const name of entries2) {
|
|
16359
|
+
if (name.startsWith(".")) continue;
|
|
16360
|
+
const full = join12(dir, name);
|
|
16361
|
+
let stat;
|
|
16362
|
+
try {
|
|
16363
|
+
stat = statSync5(full);
|
|
16364
|
+
} catch {
|
|
16365
|
+
continue;
|
|
16366
|
+
}
|
|
16367
|
+
if (stat.isDirectory()) {
|
|
16368
|
+
out.push(...listMarkdownFiles(full));
|
|
16369
|
+
} else if (stat.isFile() && name.endsWith(".md")) {
|
|
16370
|
+
out.push(full);
|
|
16371
|
+
}
|
|
16372
|
+
}
|
|
16373
|
+
return out;
|
|
16374
|
+
}
|
|
16375
|
+
function firstSeenDateOf(file) {
|
|
16376
|
+
try {
|
|
16377
|
+
const out = execFileSync2(
|
|
16378
|
+
"git",
|
|
16379
|
+
["log", "--diff-filter=A", "--follow", "--format=%cs", "--", file],
|
|
16380
|
+
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd: dirname12(file) }
|
|
16381
|
+
).trim().split("\n").filter(Boolean);
|
|
16382
|
+
if (out.length > 0) return out[out.length - 1];
|
|
16383
|
+
} catch {
|
|
16384
|
+
}
|
|
16385
|
+
try {
|
|
16386
|
+
const s = statSync5(file);
|
|
16387
|
+
return new Date((s.birthtime || s.mtime).getTime()).toISOString().slice(0, 10);
|
|
16388
|
+
} catch {
|
|
16389
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
16390
|
+
}
|
|
16391
|
+
}
|
|
16392
|
+
function dirname12(p) {
|
|
16393
|
+
const i = p.lastIndexOf(sep);
|
|
16394
|
+
return i < 0 ? "." : p.slice(0, i);
|
|
16395
|
+
}
|
|
16396
|
+
function detectGitEmail(cwd) {
|
|
16397
|
+
try {
|
|
16398
|
+
return execFileSync2("git", ["config", "user.email"], {
|
|
16399
|
+
encoding: "utf8",
|
|
16400
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
16401
|
+
cwd
|
|
16402
|
+
}).trim() || null;
|
|
16403
|
+
} catch {
|
|
16404
|
+
return null;
|
|
16405
|
+
}
|
|
16406
|
+
}
|
|
16407
|
+
function todayLocal() {
|
|
16408
|
+
const d = /* @__PURE__ */ new Date();
|
|
16409
|
+
const y = d.getFullYear();
|
|
16410
|
+
const m = String(d.getMonth() + 1).padStart(2, "0");
|
|
16411
|
+
const day2 = String(d.getDate()).padStart(2, "0");
|
|
16412
|
+
return `${y}-${m}-${day2}`;
|
|
16413
|
+
}
|
|
16414
|
+
function scanAuthored(roots, subdir, day2) {
|
|
16415
|
+
const out = [];
|
|
16416
|
+
for (const r of roots) {
|
|
16417
|
+
const dir = join12(r.root, subdir);
|
|
16418
|
+
if (!existsSync14(dir)) continue;
|
|
16419
|
+
for (const f of listMarkdownFiles(dir)) {
|
|
16420
|
+
const firstSeen = firstSeenDateOf(f);
|
|
16421
|
+
if (firstSeen !== day2) continue;
|
|
16422
|
+
const rel = relative(dir, f);
|
|
16423
|
+
out.push({ pathHash: pathHash(`${r.label}:${subdir}:${rel}`), firstSeenDate: firstSeen });
|
|
16424
|
+
}
|
|
16425
|
+
}
|
|
16426
|
+
return out;
|
|
16427
|
+
}
|
|
16428
|
+
function scanEdited(roots, day2) {
|
|
16429
|
+
const out = [];
|
|
16430
|
+
for (const r of roots) {
|
|
16431
|
+
const dir = join12(r.root, "skills");
|
|
16432
|
+
if (!existsSync14(dir)) continue;
|
|
16433
|
+
for (const f of listMarkdownFiles(dir)) {
|
|
16434
|
+
const firstSeen = firstSeenDateOf(f);
|
|
16435
|
+
if (firstSeen === day2) continue;
|
|
16436
|
+
let stat;
|
|
16437
|
+
try {
|
|
16438
|
+
stat = statSync5(f);
|
|
16439
|
+
} catch {
|
|
16440
|
+
continue;
|
|
16441
|
+
}
|
|
16442
|
+
const mtimeDay = new Date(stat.mtime.getTime()).toISOString().slice(0, 10);
|
|
16443
|
+
if (mtimeDay !== day2) continue;
|
|
16444
|
+
const rel = relative(dir, f);
|
|
16445
|
+
out.push({ pathHash: pathHash(`${r.label}:skills:${rel}`), lineDelta: 0 });
|
|
16446
|
+
}
|
|
16447
|
+
}
|
|
16448
|
+
return out;
|
|
16449
|
+
}
|
|
16450
|
+
function claudemdLineDelta(extraRoots, authorEmail, day2) {
|
|
16451
|
+
let delta = 0;
|
|
16452
|
+
const candidates = [];
|
|
16453
|
+
for (const e of extraRoots) {
|
|
16454
|
+
const f = resolve2(e, "CLAUDE.md");
|
|
16455
|
+
if (existsSync14(f)) candidates.push(f);
|
|
16456
|
+
}
|
|
16457
|
+
const homeClaudeMd = join12(homedir4(), "CLAUDE.md");
|
|
16458
|
+
if (existsSync14(homeClaudeMd)) candidates.push(homeClaudeMd);
|
|
16459
|
+
for (const file of candidates) {
|
|
16460
|
+
try {
|
|
16461
|
+
const out = execFileSync2(
|
|
16462
|
+
"git",
|
|
16463
|
+
["log", "--numstat", "--format=COMMIT %cs %ae", "--", file],
|
|
16464
|
+
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd: dirname12(file) }
|
|
16465
|
+
);
|
|
16466
|
+
let currentDate = "";
|
|
16467
|
+
let currentEmail = "";
|
|
16468
|
+
for (const line of out.split("\n")) {
|
|
16469
|
+
if (line.startsWith("COMMIT ")) {
|
|
16470
|
+
const parts = line.slice("COMMIT ".length).trim().split(/\s+/);
|
|
16471
|
+
currentDate = parts[0] ?? "";
|
|
16472
|
+
currentEmail = parts.slice(1).join(" ");
|
|
16473
|
+
} else if (currentDate === day2 && line.trim().length > 0) {
|
|
16474
|
+
if (authorEmail && currentEmail !== authorEmail) continue;
|
|
16475
|
+
const parts = line.split(/\s+/);
|
|
16476
|
+
const added = Number(parts[0]);
|
|
16477
|
+
const removed = Number(parts[1]);
|
|
16478
|
+
if (Number.isFinite(added) && Number.isFinite(removed)) {
|
|
16479
|
+
delta += added - removed;
|
|
16480
|
+
}
|
|
16481
|
+
}
|
|
16482
|
+
}
|
|
16483
|
+
} catch {
|
|
16484
|
+
}
|
|
16485
|
+
}
|
|
16486
|
+
return delta;
|
|
16487
|
+
}
|
|
16488
|
+
function probeArtifactSignals(opts = {}) {
|
|
16489
|
+
const day2 = opts.day ?? todayLocal();
|
|
16490
|
+
const roots = defaultScanRoots(opts.extraRoots);
|
|
16491
|
+
const skillsAuthored = scanAuthored(roots, "skills", day2);
|
|
16492
|
+
const subagentsAuthored = scanAuthored(roots, "agents", day2);
|
|
16493
|
+
const slashCommandsAuthored = scanAuthored(roots, "commands", day2);
|
|
16494
|
+
const skillsEdited = scanEdited(roots, day2);
|
|
16495
|
+
const authorEmail = opts.authorEmail ?? detectGitEmail(opts.extraRoots?.[0] ?? process.cwd()) ?? void 0;
|
|
16496
|
+
const claudemd = claudemdLineDelta(opts.extraRoots ?? [], authorEmail, day2);
|
|
16497
|
+
const empty = skillsAuthored.length === 0 && subagentsAuthored.length === 0 && slashCommandsAuthored.length === 0 && skillsEdited.length === 0 && claudemd === 0;
|
|
16498
|
+
if (empty) return null;
|
|
16499
|
+
return {
|
|
16500
|
+
skillsAuthored,
|
|
16501
|
+
skillsEdited,
|
|
16502
|
+
subagentsAuthored,
|
|
16503
|
+
slashCommandsAuthored,
|
|
16504
|
+
claudemdLineDelta: claudemd
|
|
16505
|
+
};
|
|
16506
|
+
}
|
|
16507
|
+
var init_file_probe = __esm({
|
|
16508
|
+
"src/perception/file-probe.ts"() {
|
|
16509
|
+
"use strict";
|
|
16510
|
+
}
|
|
16511
|
+
});
|
|
16512
|
+
|
|
15216
16513
|
// src/team/commands.ts
|
|
15217
16514
|
async function dispatchCommand(command2, config, log) {
|
|
15218
16515
|
switch (command2.type) {
|
|
@@ -15230,6 +16527,7 @@ async function dispatchCommand(command2, config, log) {
|
|
|
15230
16527
|
async function runActivityBackfill(command2, config, log) {
|
|
15231
16528
|
const { listSessions: listSessions2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
15232
16529
|
const { toLocalDay: toLocalDay4 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
|
|
16530
|
+
const { probeArtifactSignals: probeArtifactSignals2 } = await Promise.resolve().then(() => (init_file_probe(), file_probe_exports));
|
|
15233
16531
|
const days = command2.params.days;
|
|
15234
16532
|
const todayMs = Date.now();
|
|
15235
16533
|
const targetDayMs = todayMs - (days - 1) * 24 * 60 * 60 * 1e3;
|
|
@@ -15255,9 +16553,24 @@ async function runActivityBackfill(command2, config, log) {
|
|
|
15255
16553
|
summary: { pushed: 0, fromDay: targetDay }
|
|
15256
16554
|
};
|
|
15257
16555
|
}
|
|
16556
|
+
const privateProjects = new Set(config.privateProjects ?? []);
|
|
16557
|
+
const enrichmentOptIn = !!config.enrichmentOptIn;
|
|
16558
|
+
const resolveRepo = createRepoResolver();
|
|
15258
16559
|
let pushed = 0;
|
|
15259
16560
|
for (const rollup of rollups) {
|
|
15260
|
-
const
|
|
16561
|
+
const daySessions = sessions.filter((s) => sessionTouchesDay(s, rollup.day));
|
|
16562
|
+
const richBlocks = buildRichBlocksForDay(rollup.day, daySessions, privateProjects, enrichmentOptIn, resolveRepo);
|
|
16563
|
+
let artifactSignals = null;
|
|
16564
|
+
try {
|
|
16565
|
+
artifactSignals = probeArtifactSignals2({ day: rollup.day, extraRoots: [process.cwd()] });
|
|
16566
|
+
} catch {
|
|
16567
|
+
}
|
|
16568
|
+
const payload = buildIngestPayload({
|
|
16569
|
+
rollup,
|
|
16570
|
+
richExtras: richBlocks?.rich,
|
|
16571
|
+
enrichedExtras: richBlocks?.enriched,
|
|
16572
|
+
artifactSignals: artifactSignals ?? void 0
|
|
16573
|
+
});
|
|
15261
16574
|
const result = await pushToTeamServer(config, payload);
|
|
15262
16575
|
if (!result.ok) {
|
|
15263
16576
|
return {
|
|
@@ -15281,6 +16594,7 @@ var init_commands = __esm({
|
|
|
15281
16594
|
"src/team/commands.ts"() {
|
|
15282
16595
|
"use strict";
|
|
15283
16596
|
init_push();
|
|
16597
|
+
init_git_remote();
|
|
15284
16598
|
}
|
|
15285
16599
|
});
|
|
15286
16600
|
|
|
@@ -15388,6 +16702,8 @@ async function runTeamSync(log = noopLog2, configOverride, options = {}) {
|
|
|
15388
16702
|
let lastPushedDay;
|
|
15389
16703
|
const privateProjects = new Set(config.privateProjects ?? []);
|
|
15390
16704
|
const enrichmentOptIn = !!config.enrichmentOptIn;
|
|
16705
|
+
const resolveRepo = createRepoResolver();
|
|
16706
|
+
const { probeArtifactSignals: probeArtifactSignals2 } = await Promise.resolve().then(() => (init_file_probe(), file_probe_exports));
|
|
15391
16707
|
for (let i = 0; i < rollups.length; i++) {
|
|
15392
16708
|
const rollup = rollups[i];
|
|
15393
16709
|
const isLatest = i === rollups.length - 1;
|
|
@@ -15396,12 +16712,22 @@ async function runTeamSync(log = noopLog2, configOverride, options = {}) {
|
|
|
15396
16712
|
rollup.day,
|
|
15397
16713
|
daySessions,
|
|
15398
16714
|
privateProjects,
|
|
15399
|
-
enrichmentOptIn
|
|
16715
|
+
enrichmentOptIn,
|
|
16716
|
+
resolveRepo
|
|
15400
16717
|
);
|
|
16718
|
+
let artifactSignals = null;
|
|
16719
|
+
try {
|
|
16720
|
+
artifactSignals = probeArtifactSignals2({
|
|
16721
|
+
day: rollup.day,
|
|
16722
|
+
extraRoots: [process.cwd()]
|
|
16723
|
+
});
|
|
16724
|
+
} catch {
|
|
16725
|
+
}
|
|
15401
16726
|
const payload = buildIngestPayload({
|
|
15402
16727
|
rollup,
|
|
15403
16728
|
richExtras: richBlocks?.rich,
|
|
15404
16729
|
enrichedExtras: richBlocks?.enriched,
|
|
16730
|
+
artifactSignals: artifactSignals ?? void 0,
|
|
15405
16731
|
usageSnapshot: isLatest ? usageSnapshot : void 0,
|
|
15406
16732
|
planTier,
|
|
15407
16733
|
// Same rationale as usageSnapshot — current cycle data only on the
|
|
@@ -15522,6 +16848,7 @@ var init_sync = __esm({
|
|
|
15522
16848
|
"use strict";
|
|
15523
16849
|
init_config();
|
|
15524
16850
|
init_push();
|
|
16851
|
+
init_git_remote();
|
|
15525
16852
|
init_queue2();
|
|
15526
16853
|
init_backfill();
|
|
15527
16854
|
init_last_push();
|
|
@@ -15677,11 +17004,11 @@ var logs_exports = {};
|
|
|
15677
17004
|
__export(logs_exports, {
|
|
15678
17005
|
teamLogs: () => teamLogs
|
|
15679
17006
|
});
|
|
15680
|
-
import { readFileSync as
|
|
17007
|
+
import { readFileSync as readFileSync16 } from "node:fs";
|
|
15681
17008
|
async function teamLogs() {
|
|
15682
17009
|
const logPath = cclensPath("daemon.log");
|
|
15683
17010
|
try {
|
|
15684
|
-
const lines =
|
|
17011
|
+
const lines = readFileSync16(logPath, "utf8").trim().split("\n");
|
|
15685
17012
|
const teamLines = lines.filter((l) => l.includes("team "));
|
|
15686
17013
|
if (teamLines.length === 0) {
|
|
15687
17014
|
console.log("No team-related log entries found.");
|
|
@@ -15787,8 +17114,8 @@ __export(runs_exports, {
|
|
|
15787
17114
|
runs: () => runs
|
|
15788
17115
|
});
|
|
15789
17116
|
import { execSync as execSync2 } from "node:child_process";
|
|
15790
|
-
import { existsSync as
|
|
15791
|
-
import { join as
|
|
17117
|
+
import { existsSync as existsSync15, readFileSync as readFileSync17, readdirSync as readdirSync5, statSync as statSync6 } from "node:fs";
|
|
17118
|
+
import { join as join13 } from "node:path";
|
|
15792
17119
|
async function runs(args2) {
|
|
15793
17120
|
const json = args2.includes("--json");
|
|
15794
17121
|
const watch = args2.includes("--watch");
|
|
@@ -15872,8 +17199,8 @@ function listActiveRuns() {
|
|
|
15872
17199
|
return runs2.sort((a, b) => a.elapsed_s - b.elapsed_s);
|
|
15873
17200
|
}
|
|
15874
17201
|
function readSpend(sinceMs) {
|
|
15875
|
-
if (!
|
|
15876
|
-
const lines =
|
|
17202
|
+
if (!existsSync15(SPEND_PATH)) return [];
|
|
17203
|
+
const lines = readFileSync17(SPEND_PATH, "utf-8").split("\n").filter((l) => l.trim());
|
|
15877
17204
|
const out = [];
|
|
15878
17205
|
for (const line of lines) {
|
|
15879
17206
|
try {
|
|
@@ -15994,23 +17321,23 @@ function ageLabel(ms) {
|
|
|
15994
17321
|
return `${Math.floor(ms / 864e5)}d`;
|
|
15995
17322
|
}
|
|
15996
17323
|
function listTraceFiles() {
|
|
15997
|
-
if (!
|
|
15998
|
-
const entries2 =
|
|
17324
|
+
if (!existsSync15(RUNS_DIR2)) return [];
|
|
17325
|
+
const entries2 = readdirSync5(RUNS_DIR2).filter((f) => f.endsWith(".jsonl"));
|
|
15999
17326
|
return entries2.map((f) => {
|
|
16000
|
-
const
|
|
16001
|
-
const st =
|
|
16002
|
-
return { runId: f.replace(/\.jsonl$/, ""), path:
|
|
17327
|
+
const path7 = join13(RUNS_DIR2, f);
|
|
17328
|
+
const st = statSync6(path7);
|
|
17329
|
+
return { runId: f.replace(/\.jsonl$/, ""), path: path7, mtimeMs: st.mtimeMs };
|
|
16003
17330
|
}).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
16004
17331
|
}
|
|
16005
17332
|
function resolveRunId(arg) {
|
|
16006
|
-
if (!
|
|
17333
|
+
if (!existsSync15(RUNS_DIR2)) return null;
|
|
16007
17334
|
if (arg === "latest") {
|
|
16008
17335
|
const all2 = listTraceFiles();
|
|
16009
17336
|
if (all2.length === 0) return null;
|
|
16010
17337
|
return { runId: all2[0].runId, path: all2[0].path };
|
|
16011
17338
|
}
|
|
16012
|
-
const exact =
|
|
16013
|
-
if (
|
|
17339
|
+
const exact = join13(RUNS_DIR2, `${arg}.jsonl`);
|
|
17340
|
+
if (existsSync15(exact)) return { runId: arg, path: exact };
|
|
16014
17341
|
const all = listTraceFiles();
|
|
16015
17342
|
const matches = all.filter((r) => r.runId.includes(arg));
|
|
16016
17343
|
if (matches.length === 1) return { runId: matches[0].runId, path: matches[0].path };
|
|
@@ -16021,8 +17348,8 @@ function resolveRunId(arg) {
|
|
|
16021
17348
|
}
|
|
16022
17349
|
return null;
|
|
16023
17350
|
}
|
|
16024
|
-
function readTrace(
|
|
16025
|
-
return
|
|
17351
|
+
function readTrace(path7) {
|
|
17352
|
+
return readFileSync17(path7, "utf-8").split("\n").filter((l) => l.trim()).map((l) => {
|
|
16026
17353
|
try {
|
|
16027
17354
|
return JSON.parse(l);
|
|
16028
17355
|
} catch {
|
|
@@ -16034,7 +17361,7 @@ async function inspect(arg, follow, json) {
|
|
|
16034
17361
|
const r = resolveRunId(arg);
|
|
16035
17362
|
if (!r) {
|
|
16036
17363
|
console.error(`run not found: ${arg}`);
|
|
16037
|
-
if (
|
|
17364
|
+
if (existsSync15(RUNS_DIR2)) {
|
|
16038
17365
|
const all = listTraceFiles().slice(0, 5);
|
|
16039
17366
|
if (all.length > 0) {
|
|
16040
17367
|
console.error(`
|
|
@@ -16054,13 +17381,13 @@ recent runs:`);
|
|
|
16054
17381
|
const events = readTrace(r.path);
|
|
16055
17382
|
printTrace(r.runId, events);
|
|
16056
17383
|
if (!follow) return;
|
|
16057
|
-
let lastSize =
|
|
17384
|
+
let lastSize = statSync6(r.path).size;
|
|
16058
17385
|
let lastIdx = events.length;
|
|
16059
17386
|
console.log("\n \u27F6 following \xB7 ^C to quit\n");
|
|
16060
17387
|
process.on("SIGINT", () => process.exit(0));
|
|
16061
17388
|
while (true) {
|
|
16062
17389
|
await new Promise((res) => setTimeout(res, 500));
|
|
16063
|
-
const st =
|
|
17390
|
+
const st = statSync6(r.path);
|
|
16064
17391
|
if (st.size === lastSize) continue;
|
|
16065
17392
|
lastSize = st.size;
|
|
16066
17393
|
const all = readTrace(r.path);
|
|
@@ -16204,7 +17531,7 @@ async function main() {
|
|
|
16204
17531
|
case "version":
|
|
16205
17532
|
case "--version":
|
|
16206
17533
|
case "-v":
|
|
16207
|
-
console.log(`fleetlens ${"0.
|
|
17534
|
+
console.log(`fleetlens ${"0.12.0"}`);
|
|
16208
17535
|
break;
|
|
16209
17536
|
case "help":
|
|
16210
17537
|
case "--help":
|