fleetlens 0.16.0 → 0.16.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/apps/web/.next/BUILD_ID +1 -1
- package/app/apps/web/.next/build-manifest.json +3 -3
- package/app/apps/web/.next/prerender-manifest.json +3 -3
- 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/agent/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/agent/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/api/agent/chats/[id]/events/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/agent/chats/[id]/messages/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/agent/chats/[id]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/agent/chats/[id]/stop/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/agent/chats/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/agent/index/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/agent/mcp/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/agent/suggestions/route.js.nft.json +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.nft.json +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.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.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/projects/open-folder/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/runs/[runId]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/runs/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/settings/credentials/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/autostart/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/team/onboarding/start/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/team/sync-projects/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/workflow-agent/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/changelog/page.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.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/print/[key]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/projects/[slug]/page.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/onboarding/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/team/onboarding/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 +2 -1
- package/app/apps/web/.next/server/app/usage/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/usage/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__02faosk._.js +3 -3
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__09cgmam._.js +2 -2
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0tk8p3d._.js +2 -2
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0u6pamj._.js +2 -2
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__12jomao._.js +2 -2
- package/app/apps/web/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0sr4wr_.js +1 -1
- package/app/apps/web/.next/server/chunks/packages_parser_dist_06d9se1._.js +1 -1
- package/app/apps/web/.next/server/chunks/packages_parser_dist_10ihc3~._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0f3q8gt._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__11xp-1u._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/_0k8yioi._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_0epqfet._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_app_sessions_[id]_session-view_tsx_0-9t5~.._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_app_sessions_sessions-grid_tsx_0bri5x.._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0x014hn._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_usage-charts-dashboard_tsx_0bgr_uv._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_changelog_ts_0n7_p1d._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_changelog_ts_0nb5_-s._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_0mx_509._.js +1 -1
- package/app/apps/web/.next/server/middleware-build-manifest.js +3 -3
- package/app/apps/web/.next/server/middleware-manifest.json +5 -5
- package/app/apps/web/.next/server/pages/500.html +1 -1
- package/app/apps/web/.next/server/server-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/server-reference-manifest.json +1 -1
- package/app/apps/web/.next/static/chunks/0jes0m38a9ib_.js +14 -0
- package/app/apps/web/.next/static/chunks/{07bzlfv97o1ig.js → 0p5ee8wje3zi~.js} +1 -1
- package/app/apps/web/.next/static/chunks/{0_0~~ipv90vm3.js → 0rrcj195v1nd..js} +1 -1
- package/app/apps/web/.next/static/chunks/{0awkd5df28gvj.js → 0~uugvb4izjd2.js} +1 -1
- package/app/apps/web/app/sessions/[id]/session-view.tsx +6 -2
- package/app/apps/web/app/sessions/sessions-grid.tsx +5 -1
- package/app/apps/web/app/usage/page.tsx +166 -2
- package/app/apps/web/components/agent-badge.tsx +3 -0
- package/app/apps/web/components/agent-icon.tsx +42 -4
- package/app/apps/web/components/menubar-install-banner.tsx +2 -1
- package/app/apps/web/components/usage-charts-dashboard.tsx +9 -1
- package/app/apps/web/lib/agent/run.ts +24 -5
- package/app/apps/web/lib/changelog-data.generated.ts +1 -1
- package/app/apps/web/package.json +1 -1
- package/app/apps/web/public/agent-icons/grok.svg +8 -0
- package/app/apps/web/tsconfig.tsbuildinfo +1 -1
- package/dist/daemon-worker.js +1173 -123
- package/dist/index.js +1230 -167
- package/menubar/FleetlensMenubar.app/Contents/Info.plist +2 -2
- package/menubar/FleetlensMenubar.app/Contents/MacOS/FleetlensMenubar +0 -0
- package/menubar/FleetlensMenubar.app/Contents/Resources/grok.svg +8 -0
- package/menubar/FleetlensMenubar.app/Contents/_CodeSignature/CodeResources +11 -0
- package/package.json +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0ns6ydi._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0r4tks8._.js +0 -3
- package/app/apps/web/.next/static/chunks/0mry~475v0fa3.js +0 -14
- /package/app/apps/web/.next/static/{bTww6lPxII4wde65VQDrF → q_fQaCe85j7F9VawBRe81}/_buildManifest.js +0 -0
- /package/app/apps/web/.next/static/{bTww6lPxII4wde65VQDrF → q_fQaCe85j7F9VawBRe81}/_clientMiddlewareManifest.js +0 -0
- /package/app/apps/web/.next/static/{bTww6lPxII4wde65VQDrF → q_fQaCe85j7F9VawBRe81}/_ssgManifest.js +0 -0
package/dist/index.js
CHANGED
|
@@ -675,7 +675,7 @@ function getAgentMetadata(kind) {
|
|
|
675
675
|
function isAgentKind(s) {
|
|
676
676
|
return typeof s === "string" && KNOWN_AGENT_KINDS.has(s);
|
|
677
677
|
}
|
|
678
|
-
var CLAUDE_CODE_METADATA, CODEX_METADATA, GEMINI_METADATA, ANTIGRAVITY_METADATA, COWORK_METADATA, ZAI_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
|
|
678
|
+
var CLAUDE_CODE_METADATA, CODEX_METADATA, GEMINI_METADATA, ANTIGRAVITY_METADATA, COWORK_METADATA, ZAI_METADATA, GROK_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
|
|
679
679
|
var init_agent_metadata = __esm({
|
|
680
680
|
"../parser/dist/agent-metadata.js"() {
|
|
681
681
|
"use strict";
|
|
@@ -721,13 +721,22 @@ var init_agent_metadata = __esm({
|
|
|
721
721
|
accentColor: "rgb(59, 130, 246)",
|
|
722
722
|
iconChar: "Z"
|
|
723
723
|
};
|
|
724
|
+
GROK_METADATA = {
|
|
725
|
+
kind: "grok",
|
|
726
|
+
displayName: "Grok Build",
|
|
727
|
+
shortLabel: "Grok",
|
|
728
|
+
// Slate-400 — visible on dark Fleetlens chrome and still fine on light.
|
|
729
|
+
accentColor: "rgb(100, 116, 139)",
|
|
730
|
+
iconChar: "\u25C8"
|
|
731
|
+
};
|
|
724
732
|
agentMetadata = [
|
|
725
733
|
CLAUDE_CODE_METADATA,
|
|
726
734
|
CODEX_METADATA,
|
|
727
735
|
GEMINI_METADATA,
|
|
728
736
|
ANTIGRAVITY_METADATA,
|
|
729
737
|
COWORK_METADATA,
|
|
730
|
-
ZAI_METADATA
|
|
738
|
+
ZAI_METADATA,
|
|
739
|
+
GROK_METADATA
|
|
731
740
|
];
|
|
732
741
|
KNOWN_AGENT_KINDS = new Set(agentMetadata.map((m) => m.kind));
|
|
733
742
|
}
|
|
@@ -1584,11 +1593,11 @@ function defaultBranch(commonDir) {
|
|
|
1584
1593
|
}
|
|
1585
1594
|
return void 0;
|
|
1586
1595
|
}
|
|
1587
|
-
function readGitFolder(
|
|
1588
|
-
if (!existsSync(
|
|
1596
|
+
function readGitFolder(path9) {
|
|
1597
|
+
if (!existsSync(path9))
|
|
1589
1598
|
return { exists: false, isWorktree: false };
|
|
1590
1599
|
try {
|
|
1591
|
-
const git = nearestDotGit(realpathOrSelf(
|
|
1600
|
+
const git = nearestDotGit(realpathOrSelf(path9));
|
|
1592
1601
|
if (!git)
|
|
1593
1602
|
return { exists: true, isWorktree: false };
|
|
1594
1603
|
const projectRoot = projectRootFromCommonDir(git.commonDir);
|
|
@@ -2844,6 +2853,11 @@ function parseRollout(file, lines) {
|
|
|
2844
2853
|
let lastUserPreview;
|
|
2845
2854
|
let lastAgentPreview;
|
|
2846
2855
|
const tsMs = [];
|
|
2856
|
+
let threadSource;
|
|
2857
|
+
let rootSessionId;
|
|
2858
|
+
let parentThreadId;
|
|
2859
|
+
let agentNickname;
|
|
2860
|
+
let agentPath;
|
|
2847
2861
|
let idx = 0;
|
|
2848
2862
|
for (const line of lines) {
|
|
2849
2863
|
if (typeof line !== "object" || line === null)
|
|
@@ -2864,6 +2878,16 @@ function parseRollout(file, lines) {
|
|
|
2864
2878
|
if (type === "session_meta") {
|
|
2865
2879
|
if (typeof payload.cwd === "string")
|
|
2866
2880
|
cwd = payload.cwd;
|
|
2881
|
+
if (threadSource === void 0 && typeof payload.thread_source === "string")
|
|
2882
|
+
threadSource = payload.thread_source;
|
|
2883
|
+
if (rootSessionId === void 0 && typeof payload.session_id === "string")
|
|
2884
|
+
rootSessionId = payload.session_id;
|
|
2885
|
+
if (parentThreadId === void 0 && typeof payload.parent_thread_id === "string")
|
|
2886
|
+
parentThreadId = payload.parent_thread_id;
|
|
2887
|
+
if (agentNickname === void 0 && typeof payload.agent_nickname === "string")
|
|
2888
|
+
agentNickname = payload.agent_nickname;
|
|
2889
|
+
if (agentPath === void 0 && typeof payload.agent_path === "string")
|
|
2890
|
+
agentPath = payload.agent_path;
|
|
2867
2891
|
continue;
|
|
2868
2892
|
}
|
|
2869
2893
|
if (type === "turn_context") {
|
|
@@ -3067,7 +3091,7 @@ function parseRollout(file, lines) {
|
|
|
3067
3091
|
airTimeMs,
|
|
3068
3092
|
activeSegments
|
|
3069
3093
|
};
|
|
3070
|
-
return { meta, events };
|
|
3094
|
+
return { meta, events, threadSource, rootSessionId, parentThreadId, agentNickname, agentPath };
|
|
3071
3095
|
}
|
|
3072
3096
|
function numberOf(v) {
|
|
3073
3097
|
return typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
@@ -3105,28 +3129,112 @@ function clearCodexCaches() {
|
|
|
3105
3129
|
metaCache2.clear();
|
|
3106
3130
|
detailCache2.clear();
|
|
3107
3131
|
}
|
|
3108
|
-
async function
|
|
3109
|
-
const root = opts.root ?? DEFAULT_CODEX_ROOT;
|
|
3132
|
+
async function scanAllCodex(root) {
|
|
3110
3133
|
const files = await listRolloutFiles(root);
|
|
3111
3134
|
const out = [];
|
|
3112
3135
|
for (const file of files) {
|
|
3113
3136
|
const cached = metaCache2.get(file.filePath);
|
|
3114
3137
|
if (cached && cached.mtimeMs === file.mtimeMs && cached.sizeBytes === file.sizeBytes) {
|
|
3115
|
-
out.push(
|
|
3138
|
+
out.push({
|
|
3139
|
+
file,
|
|
3140
|
+
meta: cached.meta,
|
|
3141
|
+
threadSource: cached.threadSource,
|
|
3142
|
+
rootSessionId: cached.rootSessionId,
|
|
3143
|
+
parentThreadId: cached.parentThreadId,
|
|
3144
|
+
agentNickname: cached.agentNickname,
|
|
3145
|
+
agentPath: cached.agentPath
|
|
3146
|
+
});
|
|
3116
3147
|
continue;
|
|
3117
3148
|
}
|
|
3118
3149
|
try {
|
|
3119
3150
|
const lines = await readJsonl(file.filePath);
|
|
3120
|
-
const
|
|
3151
|
+
const parsed = parseRollout(file, lines);
|
|
3121
3152
|
metaCache2.set(file.filePath, {
|
|
3122
|
-
meta,
|
|
3153
|
+
meta: parsed.meta,
|
|
3123
3154
|
mtimeMs: file.mtimeMs,
|
|
3124
|
-
sizeBytes: file.sizeBytes
|
|
3155
|
+
sizeBytes: file.sizeBytes,
|
|
3156
|
+
threadSource: parsed.threadSource,
|
|
3157
|
+
rootSessionId: parsed.rootSessionId,
|
|
3158
|
+
parentThreadId: parsed.parentThreadId,
|
|
3159
|
+
agentNickname: parsed.agentNickname,
|
|
3160
|
+
agentPath: parsed.agentPath
|
|
3161
|
+
});
|
|
3162
|
+
out.push({
|
|
3163
|
+
file,
|
|
3164
|
+
meta: parsed.meta,
|
|
3165
|
+
threadSource: parsed.threadSource,
|
|
3166
|
+
rootSessionId: parsed.rootSessionId,
|
|
3167
|
+
parentThreadId: parsed.parentThreadId,
|
|
3168
|
+
agentNickname: parsed.agentNickname,
|
|
3169
|
+
agentPath: parsed.agentPath
|
|
3125
3170
|
});
|
|
3126
|
-
out.push(meta);
|
|
3127
3171
|
} catch {
|
|
3128
3172
|
}
|
|
3129
3173
|
}
|
|
3174
|
+
return out;
|
|
3175
|
+
}
|
|
3176
|
+
function buildSubagentRun(entry, parentStartMs) {
|
|
3177
|
+
const meta = entry.meta;
|
|
3178
|
+
const startMs = meta.firstTimestamp ? Date.parse(meta.firstTimestamp) : void 0;
|
|
3179
|
+
const endMs = meta.lastTimestamp ? Date.parse(meta.lastTimestamp) : void 0;
|
|
3180
|
+
const startOk = startMs !== void 0 && Number.isFinite(startMs) ? startMs : void 0;
|
|
3181
|
+
const endOk = endMs !== void 0 && Number.isFinite(endMs) ? endMs : void 0;
|
|
3182
|
+
return {
|
|
3183
|
+
agentId: meta.id,
|
|
3184
|
+
agentType: entry.agentNickname ?? entry.agentPath ?? "subagent",
|
|
3185
|
+
description: entry.agentPath ?? entry.agentNickname ?? meta.id,
|
|
3186
|
+
startMs: startOk,
|
|
3187
|
+
endMs: endOk,
|
|
3188
|
+
durationMs: meta.durationMs,
|
|
3189
|
+
startTOffsetMs: parentStartMs !== void 0 && startOk !== void 0 ? Math.max(0, startOk - parentStartMs) : void 0,
|
|
3190
|
+
endTOffsetMs: parentStartMs !== void 0 && endOk !== void 0 ? Math.max(0, endOk - parentStartMs) : void 0,
|
|
3191
|
+
eventCount: meta.eventCount,
|
|
3192
|
+
totalUsage: meta.totalUsage,
|
|
3193
|
+
model: meta.model,
|
|
3194
|
+
toolCallCount: meta.toolCallCount,
|
|
3195
|
+
finalPreview: meta.lastAgentPreview
|
|
3196
|
+
};
|
|
3197
|
+
}
|
|
3198
|
+
async function listCodexSessions(opts = {}) {
|
|
3199
|
+
const root = opts.root ?? DEFAULT_CODEX_ROOT;
|
|
3200
|
+
const all = await scanAllCodex(root);
|
|
3201
|
+
const subagentsByRoot = /* @__PURE__ */ new Map();
|
|
3202
|
+
for (const entry of all) {
|
|
3203
|
+
if (entry.threadSource !== "subagent" || !entry.rootSessionId)
|
|
3204
|
+
continue;
|
|
3205
|
+
const list = subagentsByRoot.get(entry.rootSessionId);
|
|
3206
|
+
if (list)
|
|
3207
|
+
list.push(entry);
|
|
3208
|
+
else
|
|
3209
|
+
subagentsByRoot.set(entry.rootSessionId, [entry]);
|
|
3210
|
+
}
|
|
3211
|
+
const out = [];
|
|
3212
|
+
for (const entry of all) {
|
|
3213
|
+
if (entry.threadSource === "subagent")
|
|
3214
|
+
continue;
|
|
3215
|
+
const children = subagentsByRoot.get(entry.meta.id);
|
|
3216
|
+
if (!children || children.length === 0) {
|
|
3217
|
+
out.push(entry.meta);
|
|
3218
|
+
continue;
|
|
3219
|
+
}
|
|
3220
|
+
const merged = {
|
|
3221
|
+
...entry.meta,
|
|
3222
|
+
spawnedAgentCount: children.length,
|
|
3223
|
+
totalUsage: {
|
|
3224
|
+
input: entry.meta.totalUsage.input + children.reduce((s, c) => s + c.meta.totalUsage.input, 0),
|
|
3225
|
+
output: entry.meta.totalUsage.output + children.reduce((s, c) => s + c.meta.totalUsage.output, 0),
|
|
3226
|
+
cacheRead: entry.meta.totalUsage.cacheRead + children.reduce((s, c) => s + c.meta.totalUsage.cacheRead, 0),
|
|
3227
|
+
cacheWrite: entry.meta.totalUsage.cacheWrite + children.reduce((s, c) => s + c.meta.totalUsage.cacheWrite, 0)
|
|
3228
|
+
},
|
|
3229
|
+
toolCallCount: (entry.meta.toolCallCount ?? 0) + children.reduce((s, c) => s + (c.meta.toolCallCount ?? 0), 0)
|
|
3230
|
+
};
|
|
3231
|
+
for (const c of children) {
|
|
3232
|
+
if (c.meta.lastTimestamp && (!merged.lastTimestamp || c.meta.lastTimestamp > merged.lastTimestamp)) {
|
|
3233
|
+
merged.lastTimestamp = c.meta.lastTimestamp;
|
|
3234
|
+
}
|
|
3235
|
+
}
|
|
3236
|
+
out.push(merged);
|
|
3237
|
+
}
|
|
3130
3238
|
out.sort((a, b) => (b.firstTimestamp ?? "").localeCompare(a.firstTimestamp ?? ""));
|
|
3131
3239
|
if (opts.limit !== void 0)
|
|
3132
3240
|
return out.slice(0, opts.limit);
|
|
@@ -3134,17 +3242,41 @@ async function listCodexSessions(opts = {}) {
|
|
|
3134
3242
|
}
|
|
3135
3243
|
async function getCodexSession(id, opts = {}) {
|
|
3136
3244
|
const root = opts.root ?? DEFAULT_CODEX_ROOT;
|
|
3137
|
-
const
|
|
3138
|
-
const
|
|
3139
|
-
if (!
|
|
3140
|
-
|
|
3245
|
+
const all = await scanAllCodex(root);
|
|
3246
|
+
const rootEntry = all.find((a) => a.meta.id === id && a.threadSource !== "subagent");
|
|
3247
|
+
if (!rootEntry) {
|
|
3248
|
+
const direct = all.find((a) => a.meta.id === id);
|
|
3249
|
+
if (!direct)
|
|
3250
|
+
return null;
|
|
3251
|
+
const cached2 = detailCache2.get(direct.file.filePath);
|
|
3252
|
+
if (cached2 && cached2.mtimeMs === direct.file.mtimeMs && cached2.sizeBytes === direct.file.sizeBytes) {
|
|
3253
|
+
return cached2.detail;
|
|
3254
|
+
}
|
|
3255
|
+
const lines2 = await readJsonl(direct.file.filePath);
|
|
3256
|
+
const { meta: meta2, events: events2 } = parseRollout(direct.file, lines2);
|
|
3257
|
+
const detail2 = { ...meta2, events: events2 };
|
|
3258
|
+
detailCache2.set(direct.file.filePath, {
|
|
3259
|
+
detail: detail2,
|
|
3260
|
+
mtimeMs: direct.file.mtimeMs,
|
|
3261
|
+
sizeBytes: direct.file.sizeBytes
|
|
3262
|
+
});
|
|
3263
|
+
return detail2;
|
|
3264
|
+
}
|
|
3265
|
+
const file = rootEntry.file;
|
|
3141
3266
|
const cached = detailCache2.get(file.filePath);
|
|
3142
3267
|
if (cached && cached.mtimeMs === file.mtimeMs && cached.sizeBytes === file.sizeBytes) {
|
|
3143
3268
|
return cached.detail;
|
|
3144
3269
|
}
|
|
3145
3270
|
const lines = await readJsonl(file.filePath);
|
|
3146
3271
|
const { meta, events } = parseRollout(file, lines);
|
|
3147
|
-
const
|
|
3272
|
+
const children = all.filter((a) => a.threadSource === "subagent" && a.rootSessionId === id);
|
|
3273
|
+
const parentStartMs = meta.firstTimestamp ? Date.parse(meta.firstTimestamp) : void 0;
|
|
3274
|
+
const subagents = children.map((c) => buildSubagentRun(c, parentStartMs)).sort((a, b) => (a.startMs ?? 0) - (b.startMs ?? 0));
|
|
3275
|
+
const detail = {
|
|
3276
|
+
...meta,
|
|
3277
|
+
events,
|
|
3278
|
+
...subagents.length > 0 ? { subagents, spawnedAgentCount: subagents.length } : {}
|
|
3279
|
+
};
|
|
3148
3280
|
detailCache2.set(file.filePath, {
|
|
3149
3281
|
detail,
|
|
3150
3282
|
mtimeMs: file.mtimeMs,
|
|
@@ -4469,6 +4601,672 @@ var init_cowork = __esm({
|
|
|
4469
4601
|
}
|
|
4470
4602
|
});
|
|
4471
4603
|
|
|
4604
|
+
// ../parser/dist/grok.js
|
|
4605
|
+
import { promises as fs6 } from "node:fs";
|
|
4606
|
+
import os6 from "node:os";
|
|
4607
|
+
import path6 from "node:path";
|
|
4608
|
+
function resolveDefaultGrokRoot() {
|
|
4609
|
+
const home = process.env.GROK_HOME || path6.join(os6.homedir(), ".grok");
|
|
4610
|
+
return path6.join(home, "sessions");
|
|
4611
|
+
}
|
|
4612
|
+
async function safeReaddir5(p) {
|
|
4613
|
+
return fs6.readdir(p).catch(() => []);
|
|
4614
|
+
}
|
|
4615
|
+
async function safeReadJson(p) {
|
|
4616
|
+
const raw = await fs6.readFile(p, "utf8").catch(() => null);
|
|
4617
|
+
if (raw == null)
|
|
4618
|
+
return null;
|
|
4619
|
+
try {
|
|
4620
|
+
return JSON.parse(raw);
|
|
4621
|
+
} catch {
|
|
4622
|
+
return null;
|
|
4623
|
+
}
|
|
4624
|
+
}
|
|
4625
|
+
async function resolveEncodedCwd(groupDir, encoded) {
|
|
4626
|
+
const cwdFile = path6.join(groupDir, ".cwd");
|
|
4627
|
+
const fromFile = await fs6.readFile(cwdFile, "utf8").catch(() => null);
|
|
4628
|
+
if (fromFile && fromFile.trim())
|
|
4629
|
+
return fromFile.trim();
|
|
4630
|
+
try {
|
|
4631
|
+
return decodeURIComponent(encoded);
|
|
4632
|
+
} catch {
|
|
4633
|
+
return encoded;
|
|
4634
|
+
}
|
|
4635
|
+
}
|
|
4636
|
+
async function listSessionDirs(root) {
|
|
4637
|
+
const out = [];
|
|
4638
|
+
const groups = await safeReaddir5(root);
|
|
4639
|
+
for (const group of groups) {
|
|
4640
|
+
if (group === "session_search.sqlite" || group.startsWith("."))
|
|
4641
|
+
continue;
|
|
4642
|
+
const groupDir = path6.join(root, group);
|
|
4643
|
+
const groupStat = await fs6.stat(groupDir).catch(() => null);
|
|
4644
|
+
if (!groupStat?.isDirectory())
|
|
4645
|
+
continue;
|
|
4646
|
+
const decodedCwd = await resolveEncodedCwd(groupDir, group);
|
|
4647
|
+
const entries2 = await safeReaddir5(groupDir);
|
|
4648
|
+
for (const entry of entries2) {
|
|
4649
|
+
if (entry === "prompt_history.jsonl" || entry.startsWith("."))
|
|
4650
|
+
continue;
|
|
4651
|
+
const dirPath = path6.join(groupDir, entry);
|
|
4652
|
+
const summaryPath = path6.join(dirPath, "summary.json");
|
|
4653
|
+
const updatesPath = path6.join(dirPath, "updates.jsonl");
|
|
4654
|
+
const signalsCandidate = path6.join(dirPath, "signals.json");
|
|
4655
|
+
const [summaryStat, updatesStat, signalsStat] = await Promise.all([
|
|
4656
|
+
fs6.stat(summaryPath).catch(() => null),
|
|
4657
|
+
fs6.stat(updatesPath).catch(() => null),
|
|
4658
|
+
fs6.stat(signalsCandidate).catch(() => null)
|
|
4659
|
+
]);
|
|
4660
|
+
if (!summaryStat?.isFile())
|
|
4661
|
+
continue;
|
|
4662
|
+
const mtimeMs = Math.max(summaryStat.mtimeMs, updatesStat?.mtimeMs ?? 0);
|
|
4663
|
+
const sizeBytes = (updatesStat?.size ?? 0) + summaryStat.size;
|
|
4664
|
+
out.push({
|
|
4665
|
+
dirPath,
|
|
4666
|
+
updatesPath,
|
|
4667
|
+
summaryPath,
|
|
4668
|
+
signalsPath: signalsStat?.isFile() ? signalsCandidate : null,
|
|
4669
|
+
sessionId: entry,
|
|
4670
|
+
groupName: group,
|
|
4671
|
+
decodedCwd,
|
|
4672
|
+
mtimeMs,
|
|
4673
|
+
sizeBytes
|
|
4674
|
+
});
|
|
4675
|
+
}
|
|
4676
|
+
}
|
|
4677
|
+
return out;
|
|
4678
|
+
}
|
|
4679
|
+
function emptyUsage4() {
|
|
4680
|
+
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
4681
|
+
}
|
|
4682
|
+
function previewOf4(text) {
|
|
4683
|
+
return text.replace(/\s+/g, " ").trim().slice(0, 200);
|
|
4684
|
+
}
|
|
4685
|
+
function truncate5(s, n) {
|
|
4686
|
+
return s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
|
|
4687
|
+
}
|
|
4688
|
+
function textFromContent2(content) {
|
|
4689
|
+
if (!content)
|
|
4690
|
+
return "";
|
|
4691
|
+
if (typeof content === "string")
|
|
4692
|
+
return content;
|
|
4693
|
+
if (typeof content.text === "string")
|
|
4694
|
+
return content.text;
|
|
4695
|
+
return "";
|
|
4696
|
+
}
|
|
4697
|
+
function toolResultText(update2) {
|
|
4698
|
+
const items = update2.content;
|
|
4699
|
+
if (Array.isArray(items)) {
|
|
4700
|
+
const parts = [];
|
|
4701
|
+
for (const item of items) {
|
|
4702
|
+
if (!item || typeof item !== "object")
|
|
4703
|
+
continue;
|
|
4704
|
+
if (typeof item.text === "string" && item.text) {
|
|
4705
|
+
parts.push(item.text);
|
|
4706
|
+
continue;
|
|
4707
|
+
}
|
|
4708
|
+
const inner = item.content;
|
|
4709
|
+
if (typeof inner === "string" && inner)
|
|
4710
|
+
parts.push(inner);
|
|
4711
|
+
else if (inner && typeof inner === "object" && typeof inner.text === "string") {
|
|
4712
|
+
parts.push(inner.text);
|
|
4713
|
+
}
|
|
4714
|
+
}
|
|
4715
|
+
if (parts.length)
|
|
4716
|
+
return parts.join("\n");
|
|
4717
|
+
}
|
|
4718
|
+
const raw = update2.rawOutput;
|
|
4719
|
+
if (raw == null)
|
|
4720
|
+
return "";
|
|
4721
|
+
if (typeof raw === "string")
|
|
4722
|
+
return raw;
|
|
4723
|
+
if (typeof raw === "object") {
|
|
4724
|
+
const r = raw;
|
|
4725
|
+
if (typeof r.output_for_prompt === "string")
|
|
4726
|
+
return r.output_for_prompt;
|
|
4727
|
+
if (typeof r.summary_for_prompt === "string")
|
|
4728
|
+
return r.summary_for_prompt;
|
|
4729
|
+
if (r.Content && typeof r.Content === "object") {
|
|
4730
|
+
const c = r.Content;
|
|
4731
|
+
if (typeof c.content === "string")
|
|
4732
|
+
return c.content;
|
|
4733
|
+
}
|
|
4734
|
+
if (r.TodosUpdated && typeof r.TodosUpdated === "object") {
|
|
4735
|
+
const t = r.TodosUpdated;
|
|
4736
|
+
if (typeof t.summary_for_prompt === "string")
|
|
4737
|
+
return t.summary_for_prompt;
|
|
4738
|
+
}
|
|
4739
|
+
if (Array.isArray(r.stdout) || Array.isArray(r.output)) {
|
|
4740
|
+
try {
|
|
4741
|
+
return JSON.stringify({
|
|
4742
|
+
type: r.type,
|
|
4743
|
+
exit_code: r.exit_code,
|
|
4744
|
+
note: "binary/stdout omitted"
|
|
4745
|
+
});
|
|
4746
|
+
} catch {
|
|
4747
|
+
return "";
|
|
4748
|
+
}
|
|
4749
|
+
}
|
|
4750
|
+
try {
|
|
4751
|
+
return JSON.stringify(raw);
|
|
4752
|
+
} catch {
|
|
4753
|
+
return "";
|
|
4754
|
+
}
|
|
4755
|
+
}
|
|
4756
|
+
return String(raw);
|
|
4757
|
+
}
|
|
4758
|
+
function toolNameOf(update2) {
|
|
4759
|
+
const meta = update2._meta;
|
|
4760
|
+
if (meta && typeof meta === "object") {
|
|
4761
|
+
const xai = meta["x.ai/tool"];
|
|
4762
|
+
if (xai && typeof xai === "object") {
|
|
4763
|
+
const name = xai.name;
|
|
4764
|
+
if (typeof name === "string" && name)
|
|
4765
|
+
return name;
|
|
4766
|
+
}
|
|
4767
|
+
}
|
|
4768
|
+
if (typeof update2.title === "string" && update2.title) {
|
|
4769
|
+
if (!update2.title.includes(" ") && !update2.title.includes("`"))
|
|
4770
|
+
return update2.title;
|
|
4771
|
+
return update2.title;
|
|
4772
|
+
}
|
|
4773
|
+
return "tool";
|
|
4774
|
+
}
|
|
4775
|
+
function statusOf(update2) {
|
|
4776
|
+
const s = update2.status;
|
|
4777
|
+
if (typeof s === "string")
|
|
4778
|
+
return s;
|
|
4779
|
+
if (s && typeof s === "object" && typeof s.status === "string")
|
|
4780
|
+
return s.status;
|
|
4781
|
+
return void 0;
|
|
4782
|
+
}
|
|
4783
|
+
function lineTimestampIso(line) {
|
|
4784
|
+
const meta = line.params?._meta;
|
|
4785
|
+
const agentMs = meta && typeof meta.agentTimestampMs === "number" ? meta.agentTimestampMs : void 0;
|
|
4786
|
+
if (agentMs != null && Number.isFinite(agentMs)) {
|
|
4787
|
+
return new Date(agentMs).toISOString();
|
|
4788
|
+
}
|
|
4789
|
+
const ts = line.timestamp;
|
|
4790
|
+
if (typeof ts === "number" && Number.isFinite(ts)) {
|
|
4791
|
+
const ms = ts > 1e12 ? ts : ts * 1e3;
|
|
4792
|
+
return new Date(ms).toISOString();
|
|
4793
|
+
}
|
|
4794
|
+
return void 0;
|
|
4795
|
+
}
|
|
4796
|
+
function computeActiveSegments5(tsMs) {
|
|
4797
|
+
if (tsMs.length === 0)
|
|
4798
|
+
return [];
|
|
4799
|
+
const sorted = [...tsMs].sort((a, b) => a - b);
|
|
4800
|
+
const out = [];
|
|
4801
|
+
let segStart = sorted[0];
|
|
4802
|
+
let segEnd = sorted[0];
|
|
4803
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
4804
|
+
const t = sorted[i];
|
|
4805
|
+
if (t - segEnd > IDLE_GAP_MS4) {
|
|
4806
|
+
out.push({ startMs: segStart, endMs: segEnd });
|
|
4807
|
+
segStart = t;
|
|
4808
|
+
}
|
|
4809
|
+
segEnd = t;
|
|
4810
|
+
}
|
|
4811
|
+
out.push({ startMs: segStart, endMs: segEnd });
|
|
4812
|
+
return out;
|
|
4813
|
+
}
|
|
4814
|
+
async function parseSession3(dir) {
|
|
4815
|
+
const [summary, signals, updatesRaw] = await Promise.all([
|
|
4816
|
+
safeReadJson(dir.summaryPath),
|
|
4817
|
+
dir.signalsPath ? safeReadJson(dir.signalsPath) : Promise.resolve(null),
|
|
4818
|
+
fs6.readFile(dir.updatesPath, "utf8").catch(() => "")
|
|
4819
|
+
]);
|
|
4820
|
+
const sessionId = summary?.info?.id ?? dir.sessionId;
|
|
4821
|
+
const cwd = summary?.info?.cwd ?? dir.decodedCwd;
|
|
4822
|
+
let model = summary?.current_model_id ?? signals?.primaryModelId ?? signals?.modelsUsed?.[0];
|
|
4823
|
+
const events = [];
|
|
4824
|
+
const totalUsage = emptyUsage4();
|
|
4825
|
+
if (signals?.contextTokensUsed && signals.contextTokensUsed > 0) {
|
|
4826
|
+
totalUsage.input = signals.contextTokensUsed;
|
|
4827
|
+
}
|
|
4828
|
+
let firstTimestamp;
|
|
4829
|
+
let lastTimestamp;
|
|
4830
|
+
let toolCallCount = 0;
|
|
4831
|
+
let turnCount = 0;
|
|
4832
|
+
let firstUserPreview;
|
|
4833
|
+
let lastUserPreview;
|
|
4834
|
+
let lastAgentPreview;
|
|
4835
|
+
const tsMs = [];
|
|
4836
|
+
let idx = 0;
|
|
4837
|
+
const completedToolResults = /* @__PURE__ */ new Set();
|
|
4838
|
+
let maxTotalTokens = 0;
|
|
4839
|
+
function noteTs(ts, role) {
|
|
4840
|
+
if (!ts || role === "meta")
|
|
4841
|
+
return;
|
|
4842
|
+
if (!firstTimestamp)
|
|
4843
|
+
firstTimestamp = ts;
|
|
4844
|
+
lastTimestamp = ts;
|
|
4845
|
+
const ms = Date.parse(ts);
|
|
4846
|
+
if (Number.isFinite(ms))
|
|
4847
|
+
tsMs.push(ms);
|
|
4848
|
+
}
|
|
4849
|
+
function pushEvent(e) {
|
|
4850
|
+
events.push(e);
|
|
4851
|
+
noteTs(e.timestamp, e.role);
|
|
4852
|
+
}
|
|
4853
|
+
let buf = null;
|
|
4854
|
+
function flushBuf() {
|
|
4855
|
+
if (!buf)
|
|
4856
|
+
return;
|
|
4857
|
+
const text = buf.texts.join("");
|
|
4858
|
+
const preview = previewOf4(text);
|
|
4859
|
+
if (buf.kind === "user") {
|
|
4860
|
+
const isHidden = !text || isFrameworkInjectedUserInput(text);
|
|
4861
|
+
if (text && !isHidden) {
|
|
4862
|
+
if (!firstUserPreview)
|
|
4863
|
+
firstUserPreview = preview;
|
|
4864
|
+
lastUserPreview = preview;
|
|
4865
|
+
turnCount += 1;
|
|
4866
|
+
}
|
|
4867
|
+
if (text) {
|
|
4868
|
+
pushEvent({
|
|
4869
|
+
index: idx++,
|
|
4870
|
+
timestamp: buf.firstTs,
|
|
4871
|
+
role: "user",
|
|
4872
|
+
rawType: "grok/user_message",
|
|
4873
|
+
preview,
|
|
4874
|
+
blocks: [{ type: "text", text }],
|
|
4875
|
+
messageId: buf.promptId,
|
|
4876
|
+
raw: buf.raw.length === 1 ? buf.raw[0] : buf.raw
|
|
4877
|
+
});
|
|
4878
|
+
}
|
|
4879
|
+
} else if (buf.kind === "agent") {
|
|
4880
|
+
if (text)
|
|
4881
|
+
lastAgentPreview = preview;
|
|
4882
|
+
if (text) {
|
|
4883
|
+
pushEvent({
|
|
4884
|
+
index: idx++,
|
|
4885
|
+
timestamp: buf.firstTs,
|
|
4886
|
+
role: "agent",
|
|
4887
|
+
rawType: "grok/agent_message",
|
|
4888
|
+
preview,
|
|
4889
|
+
blocks: [{ type: "text", text }],
|
|
4890
|
+
messageId: buf.promptId,
|
|
4891
|
+
model: buf.model ?? model,
|
|
4892
|
+
raw: buf.raw.length === 1 ? buf.raw[0] : buf.raw
|
|
4893
|
+
});
|
|
4894
|
+
}
|
|
4895
|
+
} else if (buf.kind === "thought") {
|
|
4896
|
+
if (text) {
|
|
4897
|
+
pushEvent({
|
|
4898
|
+
index: idx++,
|
|
4899
|
+
timestamp: buf.firstTs,
|
|
4900
|
+
role: "agent-thinking",
|
|
4901
|
+
rawType: "grok/agent_thought",
|
|
4902
|
+
preview,
|
|
4903
|
+
blocks: [{ type: "thinking", thinking: text }],
|
|
4904
|
+
messageId: buf.promptId,
|
|
4905
|
+
model: buf.model ?? model,
|
|
4906
|
+
raw: buf.raw.length === 1 ? buf.raw[0] : buf.raw
|
|
4907
|
+
});
|
|
4908
|
+
}
|
|
4909
|
+
}
|
|
4910
|
+
buf = null;
|
|
4911
|
+
}
|
|
4912
|
+
function appendChunk(kind, text, ts, promptId, modelId, raw) {
|
|
4913
|
+
if (!text && kind === "user")
|
|
4914
|
+
return;
|
|
4915
|
+
if (buf && buf.kind !== kind)
|
|
4916
|
+
flushBuf();
|
|
4917
|
+
if (!buf) {
|
|
4918
|
+
buf = {
|
|
4919
|
+
kind,
|
|
4920
|
+
texts: [],
|
|
4921
|
+
firstTs: ts,
|
|
4922
|
+
lastTs: ts,
|
|
4923
|
+
model: modelId,
|
|
4924
|
+
promptId,
|
|
4925
|
+
raw: []
|
|
4926
|
+
};
|
|
4927
|
+
}
|
|
4928
|
+
if (text)
|
|
4929
|
+
buf.texts.push(text);
|
|
4930
|
+
buf.lastTs = ts ?? buf.lastTs;
|
|
4931
|
+
if (modelId)
|
|
4932
|
+
buf.model = modelId;
|
|
4933
|
+
if (promptId)
|
|
4934
|
+
buf.promptId = promptId;
|
|
4935
|
+
buf.raw.push(raw);
|
|
4936
|
+
}
|
|
4937
|
+
const lines = updatesRaw.split("\n");
|
|
4938
|
+
for (const line of lines) {
|
|
4939
|
+
const trimmed = line.trim();
|
|
4940
|
+
if (!trimmed)
|
|
4941
|
+
continue;
|
|
4942
|
+
let obj;
|
|
4943
|
+
try {
|
|
4944
|
+
obj = JSON.parse(trimmed);
|
|
4945
|
+
} catch {
|
|
4946
|
+
continue;
|
|
4947
|
+
}
|
|
4948
|
+
const update2 = obj.params?.update;
|
|
4949
|
+
if (!update2 || typeof update2 !== "object")
|
|
4950
|
+
continue;
|
|
4951
|
+
const st = update2.sessionUpdate;
|
|
4952
|
+
if (!st)
|
|
4953
|
+
continue;
|
|
4954
|
+
const ts = lineTimestampIso(obj);
|
|
4955
|
+
const lineMeta = obj.params?._meta ?? {};
|
|
4956
|
+
const updateMeta = update2._meta ?? {};
|
|
4957
|
+
const promptId = typeof lineMeta.promptId === "string" && lineMeta.promptId || typeof updateMeta.promptId === "string" && updateMeta.promptId || void 0;
|
|
4958
|
+
const modelId = typeof updateMeta.modelId === "string" && updateMeta.modelId || typeof lineMeta.modelId === "string" && lineMeta.modelId || void 0;
|
|
4959
|
+
if (modelId)
|
|
4960
|
+
model = modelId;
|
|
4961
|
+
const totalTok = lineMeta.totalTokens;
|
|
4962
|
+
if (typeof totalTok === "number" && totalTok > maxTotalTokens) {
|
|
4963
|
+
maxTotalTokens = totalTok;
|
|
4964
|
+
}
|
|
4965
|
+
if (st === "user_message_chunk") {
|
|
4966
|
+
const text = textFromContent2(update2.content);
|
|
4967
|
+
appendChunk("user", text, ts, promptId, modelId, obj);
|
|
4968
|
+
continue;
|
|
4969
|
+
}
|
|
4970
|
+
if (st === "agent_message_chunk") {
|
|
4971
|
+
const text = textFromContent2(update2.content);
|
|
4972
|
+
appendChunk("agent", text, ts, promptId, modelId, obj);
|
|
4973
|
+
continue;
|
|
4974
|
+
}
|
|
4975
|
+
if (st === "agent_thought_chunk") {
|
|
4976
|
+
const text = textFromContent2(update2.content);
|
|
4977
|
+
appendChunk("thought", text, ts, promptId, modelId, obj);
|
|
4978
|
+
continue;
|
|
4979
|
+
}
|
|
4980
|
+
flushBuf();
|
|
4981
|
+
if (st === "tool_call") {
|
|
4982
|
+
const toolCallId = typeof update2.toolCallId === "string" ? update2.toolCallId : `grok-${idx}`;
|
|
4983
|
+
const name = toolNameOf(update2);
|
|
4984
|
+
const input = update2.rawInput ?? {};
|
|
4985
|
+
const argsStr = input ? JSON.stringify(input) : "";
|
|
4986
|
+
toolCallCount += 1;
|
|
4987
|
+
pushEvent({
|
|
4988
|
+
index: idx++,
|
|
4989
|
+
timestamp: ts,
|
|
4990
|
+
role: "tool-call",
|
|
4991
|
+
rawType: "grok/tool_call",
|
|
4992
|
+
preview: `${name}(${truncate5(argsStr, 80)})`,
|
|
4993
|
+
blocks: [{ type: "tool_use", id: toolCallId, name, input }],
|
|
4994
|
+
toolName: name,
|
|
4995
|
+
toolUseId: toolCallId,
|
|
4996
|
+
model,
|
|
4997
|
+
raw: obj
|
|
4998
|
+
});
|
|
4999
|
+
continue;
|
|
5000
|
+
}
|
|
5001
|
+
if (st === "tool_call_update") {
|
|
5002
|
+
const status2 = statusOf(update2);
|
|
5003
|
+
if (status2 !== "completed" && status2 !== "failed" && status2 !== "error" && status2 !== "cancelled") {
|
|
5004
|
+
continue;
|
|
5005
|
+
}
|
|
5006
|
+
const toolCallId = typeof update2.toolCallId === "string" ? update2.toolCallId : "";
|
|
5007
|
+
if (toolCallId && completedToolResults.has(toolCallId))
|
|
5008
|
+
continue;
|
|
5009
|
+
if (toolCallId)
|
|
5010
|
+
completedToolResults.add(toolCallId);
|
|
5011
|
+
const resultText = toolResultText(update2);
|
|
5012
|
+
const isError = status2 === "failed" || status2 === "error" || status2 === "cancelled";
|
|
5013
|
+
pushEvent({
|
|
5014
|
+
index: idx++,
|
|
5015
|
+
timestamp: ts,
|
|
5016
|
+
role: "tool-result",
|
|
5017
|
+
rawType: "grok/tool_result",
|
|
5018
|
+
preview: previewOf4(resultText),
|
|
5019
|
+
blocks: [
|
|
5020
|
+
{
|
|
5021
|
+
type: "tool_result",
|
|
5022
|
+
tool_use_id: toolCallId,
|
|
5023
|
+
content: resultText,
|
|
5024
|
+
is_error: isError || void 0
|
|
5025
|
+
}
|
|
5026
|
+
],
|
|
5027
|
+
toolUseId: toolCallId || void 0,
|
|
5028
|
+
toolResult: resultText,
|
|
5029
|
+
raw: obj
|
|
5030
|
+
});
|
|
5031
|
+
continue;
|
|
5032
|
+
}
|
|
5033
|
+
if (st === "turn_completed") {
|
|
5034
|
+
continue;
|
|
5035
|
+
}
|
|
5036
|
+
}
|
|
5037
|
+
flushBuf();
|
|
5038
|
+
if (totalUsage.input === 0 && maxTotalTokens > 0) {
|
|
5039
|
+
totalUsage.input = maxTotalTokens;
|
|
5040
|
+
}
|
|
5041
|
+
if (!firstTimestamp && summary?.created_at)
|
|
5042
|
+
firstTimestamp = summary.created_at;
|
|
5043
|
+
if (!lastTimestamp) {
|
|
5044
|
+
lastTimestamp = summary?.last_active_at ?? summary?.updated_at ?? firstTimestamp;
|
|
5045
|
+
}
|
|
5046
|
+
if (signals?.toolCallCount != null && signals.toolCallCount > toolCallCount) {
|
|
5047
|
+
toolCallCount = signals.toolCallCount;
|
|
5048
|
+
}
|
|
5049
|
+
if (signals?.turnCount != null && signals.turnCount > turnCount) {
|
|
5050
|
+
turnCount = signals.turnCount;
|
|
5051
|
+
}
|
|
5052
|
+
const startMs = firstTimestamp ? Date.parse(firstTimestamp) : void 0;
|
|
5053
|
+
if (startMs !== void 0 && Number.isFinite(startMs)) {
|
|
5054
|
+
let prevMs;
|
|
5055
|
+
for (const ev of events) {
|
|
5056
|
+
if (!ev.timestamp)
|
|
5057
|
+
continue;
|
|
5058
|
+
const ms = Date.parse(ev.timestamp);
|
|
5059
|
+
if (!Number.isFinite(ms))
|
|
5060
|
+
continue;
|
|
5061
|
+
ev.tOffsetMs = Math.max(0, ms - startMs);
|
|
5062
|
+
if (prevMs !== void 0)
|
|
5063
|
+
ev.gapMs = Math.max(0, ms - prevMs);
|
|
5064
|
+
prevMs = ms;
|
|
5065
|
+
}
|
|
5066
|
+
}
|
|
5067
|
+
const activeSegments = computeActiveSegments5(tsMs);
|
|
5068
|
+
const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
|
|
5069
|
+
const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
|
|
5070
|
+
const project = cwd ? resolveProjectIdentity(cwd) : void 0;
|
|
5071
|
+
const projectName = project?.projectName ?? cwd ?? dir.decodedCwd;
|
|
5072
|
+
const projectDir = dir.groupName || (cwd ? encodeURIComponent(cwd) : "(unknown)");
|
|
5073
|
+
if (!firstUserPreview) {
|
|
5074
|
+
const title = summary?.generated_title || summary?.session_summary;
|
|
5075
|
+
if (title)
|
|
5076
|
+
firstUserPreview = previewOf4(title);
|
|
5077
|
+
}
|
|
5078
|
+
const spawnedAgentCount = await countSubagentChildren(dir.dirPath);
|
|
5079
|
+
const meta = {
|
|
5080
|
+
agent: "grok",
|
|
5081
|
+
id: sessionId,
|
|
5082
|
+
filePath: dir.updatesPath,
|
|
5083
|
+
projectName,
|
|
5084
|
+
worktreeName: project?.worktreeName,
|
|
5085
|
+
repoName: project?.repoName,
|
|
5086
|
+
projectDir,
|
|
5087
|
+
sessionId,
|
|
5088
|
+
firstTimestamp,
|
|
5089
|
+
lastTimestamp,
|
|
5090
|
+
lastActivityMs: lastTimestamp ? Date.parse(lastTimestamp) : void 0,
|
|
5091
|
+
durationMs: durationMs && Number.isFinite(durationMs) ? durationMs : void 0,
|
|
5092
|
+
eventCount: events.length,
|
|
5093
|
+
model,
|
|
5094
|
+
cwd,
|
|
5095
|
+
gitBranch: summary?.head_branch,
|
|
5096
|
+
agentName: summary?.agent_name,
|
|
5097
|
+
totalUsage,
|
|
5098
|
+
status: "idle",
|
|
5099
|
+
firstUserPreview,
|
|
5100
|
+
lastUserPreview,
|
|
5101
|
+
lastAgentPreview,
|
|
5102
|
+
toolCallCount,
|
|
5103
|
+
turnCount,
|
|
5104
|
+
linesAdded: signals?.agentLinesAdded,
|
|
5105
|
+
linesRemoved: signals?.agentLinesRemoved,
|
|
5106
|
+
airTimeMs,
|
|
5107
|
+
activeSegments,
|
|
5108
|
+
...spawnedAgentCount > 0 ? { spawnedAgentCount } : {}
|
|
5109
|
+
};
|
|
5110
|
+
return { meta, events, sessionKind: summary?.session_kind };
|
|
5111
|
+
}
|
|
5112
|
+
async function countSubagentChildren(dirPath) {
|
|
5113
|
+
const subRoot = path6.join(dirPath, "subagents");
|
|
5114
|
+
const entries2 = await safeReaddir5(subRoot);
|
|
5115
|
+
let n = 0;
|
|
5116
|
+
for (const e of entries2) {
|
|
5117
|
+
const st = await fs6.stat(path6.join(subRoot, e)).catch(() => null);
|
|
5118
|
+
if (st?.isDirectory())
|
|
5119
|
+
n += 1;
|
|
5120
|
+
}
|
|
5121
|
+
return n;
|
|
5122
|
+
}
|
|
5123
|
+
async function loadGrokSubagents(parentDir, parentStartMs) {
|
|
5124
|
+
const subRoot = path6.join(parentDir.dirPath, "subagents");
|
|
5125
|
+
const entries2 = await safeReaddir5(subRoot);
|
|
5126
|
+
const groupDir = path6.dirname(parentDir.dirPath);
|
|
5127
|
+
const runs2 = [];
|
|
5128
|
+
for (const entry of entries2) {
|
|
5129
|
+
const metaPath = path6.join(subRoot, entry, "meta.json");
|
|
5130
|
+
const meta = await safeReadJson(metaPath);
|
|
5131
|
+
if (!meta)
|
|
5132
|
+
continue;
|
|
5133
|
+
const childId = meta.child_session_id ?? meta.subagent_id ?? entry;
|
|
5134
|
+
const childDir = path6.join(groupDir, childId);
|
|
5135
|
+
const [childSummary, childSignals] = await Promise.all([
|
|
5136
|
+
safeReadJson(path6.join(childDir, "summary.json")),
|
|
5137
|
+
safeReadJson(path6.join(childDir, "signals.json"))
|
|
5138
|
+
]);
|
|
5139
|
+
const startMs = childSummary?.created_at ? Date.parse(childSummary.created_at) : void 0;
|
|
5140
|
+
const endIso = childSummary?.last_active_at ?? childSummary?.updated_at;
|
|
5141
|
+
const endMs = endIso ? Date.parse(endIso) : void 0;
|
|
5142
|
+
const startOk = startMs !== void 0 && Number.isFinite(startMs) ? startMs : void 0;
|
|
5143
|
+
const endOk = endMs !== void 0 && Number.isFinite(endMs) ? endMs : void 0;
|
|
5144
|
+
const usage2 = emptyUsage4();
|
|
5145
|
+
if (childSignals?.contextTokensUsed)
|
|
5146
|
+
usage2.input = childSignals.contextTokensUsed;
|
|
5147
|
+
runs2.push({
|
|
5148
|
+
agentId: childId,
|
|
5149
|
+
agentType: meta.subagent_type ?? childSummary?.agent_name ?? "subagent",
|
|
5150
|
+
description: meta.description && meta.description.trim() || childSummary?.generated_title || childSummary?.session_summary || childId,
|
|
5151
|
+
startMs: startOk,
|
|
5152
|
+
endMs: endOk,
|
|
5153
|
+
durationMs: startOk !== void 0 && endOk !== void 0 ? Math.max(0, endOk - startOk) : void 0,
|
|
5154
|
+
startTOffsetMs: parentStartMs !== void 0 && startOk !== void 0 ? Math.max(0, startOk - parentStartMs) : void 0,
|
|
5155
|
+
endTOffsetMs: parentStartMs !== void 0 && endOk !== void 0 ? Math.max(0, endOk - parentStartMs) : void 0,
|
|
5156
|
+
eventCount: childSummary?.num_messages ?? childSummary?.num_chat_messages ?? 0,
|
|
5157
|
+
totalUsage: usage2,
|
|
5158
|
+
prompt: typeof meta.prompt === "string" ? meta.prompt : void 0,
|
|
5159
|
+
model: childSummary?.current_model_id ?? childSignals?.primaryModelId,
|
|
5160
|
+
toolCallCount: childSignals?.toolCallCount
|
|
5161
|
+
});
|
|
5162
|
+
}
|
|
5163
|
+
runs2.sort((a, b) => (a.startMs ?? 0) - (b.startMs ?? 0));
|
|
5164
|
+
return runs2;
|
|
5165
|
+
}
|
|
5166
|
+
function clearGrokCaches() {
|
|
5167
|
+
metaCache6.clear();
|
|
5168
|
+
detailCache6.clear();
|
|
5169
|
+
}
|
|
5170
|
+
async function listGrokSessions(opts = {}) {
|
|
5171
|
+
const root = opts.root ?? resolveDefaultGrokRoot();
|
|
5172
|
+
const dirs = await listSessionDirs(root);
|
|
5173
|
+
const out = [];
|
|
5174
|
+
for (const dir of dirs) {
|
|
5175
|
+
const summaryPeek = await safeReadJson(dir.summaryPath);
|
|
5176
|
+
if (summaryPeek?.session_kind === "subagent")
|
|
5177
|
+
continue;
|
|
5178
|
+
const cached = metaCache6.get(dir.dirPath);
|
|
5179
|
+
if (cached && cached.mtimeMs === dir.mtimeMs && cached.sizeBytes === dir.sizeBytes) {
|
|
5180
|
+
out.push(cached.meta);
|
|
5181
|
+
continue;
|
|
5182
|
+
}
|
|
5183
|
+
try {
|
|
5184
|
+
const { meta, sessionKind } = await parseSession3(dir);
|
|
5185
|
+
if (sessionKind === "subagent")
|
|
5186
|
+
continue;
|
|
5187
|
+
metaCache6.set(dir.dirPath, {
|
|
5188
|
+
meta,
|
|
5189
|
+
mtimeMs: dir.mtimeMs,
|
|
5190
|
+
sizeBytes: dir.sizeBytes
|
|
5191
|
+
});
|
|
5192
|
+
out.push(meta);
|
|
5193
|
+
} catch {
|
|
5194
|
+
}
|
|
5195
|
+
}
|
|
5196
|
+
out.sort((a, b) => (b.firstTimestamp ?? "").localeCompare(a.firstTimestamp ?? ""));
|
|
5197
|
+
if (opts.limit !== void 0)
|
|
5198
|
+
return out.slice(0, opts.limit);
|
|
5199
|
+
return out;
|
|
5200
|
+
}
|
|
5201
|
+
async function getGrokSession(id, opts = {}) {
|
|
5202
|
+
const root = opts.root ?? resolveDefaultGrokRoot();
|
|
5203
|
+
const dirs = await listSessionDirs(root);
|
|
5204
|
+
const chosen = dirs.find((d) => d.sessionId === id);
|
|
5205
|
+
if (!chosen) {
|
|
5206
|
+
for (const dir of dirs) {
|
|
5207
|
+
try {
|
|
5208
|
+
const { meta: meta2, events: events2 } = await parseSession3(dir);
|
|
5209
|
+
if (meta2.id === id) {
|
|
5210
|
+
const detail2 = { ...meta2, events: events2 };
|
|
5211
|
+
detailCache6.set(dir.dirPath, {
|
|
5212
|
+
detail: detail2,
|
|
5213
|
+
mtimeMs: dir.mtimeMs,
|
|
5214
|
+
sizeBytes: dir.sizeBytes
|
|
5215
|
+
});
|
|
5216
|
+
return detail2;
|
|
5217
|
+
}
|
|
5218
|
+
} catch {
|
|
5219
|
+
}
|
|
5220
|
+
}
|
|
5221
|
+
return null;
|
|
5222
|
+
}
|
|
5223
|
+
const cached = detailCache6.get(chosen.dirPath);
|
|
5224
|
+
if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes) {
|
|
5225
|
+
return cached.detail;
|
|
5226
|
+
}
|
|
5227
|
+
const { meta, events } = await parseSession3(chosen);
|
|
5228
|
+
const parentStartMs = meta.firstTimestamp ? Date.parse(meta.firstTimestamp) : void 0;
|
|
5229
|
+
const subagents = await loadGrokSubagents(chosen, parentStartMs !== void 0 && Number.isFinite(parentStartMs) ? parentStartMs : void 0);
|
|
5230
|
+
const detail = {
|
|
5231
|
+
...meta,
|
|
5232
|
+
events,
|
|
5233
|
+
...subagents.length > 0 ? { subagents, spawnedAgentCount: subagents.length } : {}
|
|
5234
|
+
};
|
|
5235
|
+
detailCache6.set(chosen.dirPath, {
|
|
5236
|
+
detail,
|
|
5237
|
+
mtimeMs: chosen.mtimeMs,
|
|
5238
|
+
sizeBytes: chosen.sizeBytes
|
|
5239
|
+
});
|
|
5240
|
+
metaCache6.set(chosen.dirPath, {
|
|
5241
|
+
meta: {
|
|
5242
|
+
...meta,
|
|
5243
|
+
...subagents.length > 0 ? { spawnedAgentCount: subagents.length } : {}
|
|
5244
|
+
},
|
|
5245
|
+
mtimeMs: chosen.mtimeMs,
|
|
5246
|
+
sizeBytes: chosen.sizeBytes
|
|
5247
|
+
});
|
|
5248
|
+
return detail;
|
|
5249
|
+
}
|
|
5250
|
+
function grokSessionLocalDay(meta) {
|
|
5251
|
+
if (!meta.firstTimestamp)
|
|
5252
|
+
return void 0;
|
|
5253
|
+
const ms = Date.parse(meta.firstTimestamp);
|
|
5254
|
+
return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
|
|
5255
|
+
}
|
|
5256
|
+
var DEFAULT_GROK_ROOT, IDLE_GAP_MS4, metaCache6, detailCache6;
|
|
5257
|
+
var init_grok = __esm({
|
|
5258
|
+
"../parser/dist/grok.js"() {
|
|
5259
|
+
"use strict";
|
|
5260
|
+
init_analytics();
|
|
5261
|
+
init_git_project();
|
|
5262
|
+
init_user_input();
|
|
5263
|
+
DEFAULT_GROK_ROOT = path6.join(os6.homedir(), ".grok", "sessions");
|
|
5264
|
+
IDLE_GAP_MS4 = 3 * 60 * 1e3;
|
|
5265
|
+
metaCache6 = /* @__PURE__ */ new Map();
|
|
5266
|
+
detailCache6 = /* @__PURE__ */ new Map();
|
|
5267
|
+
}
|
|
5268
|
+
});
|
|
5269
|
+
|
|
4472
5270
|
// ../parser/dist/team-config.js
|
|
4473
5271
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, unlinkSync as unlinkSync2, mkdirSync as mkdirSync2, renameSync } from "node:fs";
|
|
4474
5272
|
import { join as join2 } from "node:path";
|
|
@@ -4528,6 +5326,7 @@ __export(fs_exports, {
|
|
|
4528
5326
|
DEFAULT_CODEX_ROOT: () => DEFAULT_CODEX_ROOT,
|
|
4529
5327
|
DEFAULT_COWORK_ROOT: () => DEFAULT_COWORK_ROOT,
|
|
4530
5328
|
DEFAULT_GEMINI_ROOT: () => DEFAULT_GEMINI_ROOT,
|
|
5329
|
+
DEFAULT_GROK_ROOT: () => DEFAULT_GROK_ROOT,
|
|
4531
5330
|
DEFAULT_ROOT: () => DEFAULT_ROOT,
|
|
4532
5331
|
RICH_ROLLUP_SCHEMA_VERSION: () => RICH_ROLLUP_SCHEMA_VERSION,
|
|
4533
5332
|
agentSources: () => agentSources,
|
|
@@ -4538,6 +5337,7 @@ __export(fs_exports, {
|
|
|
4538
5337
|
cclensHome: () => cclensHome,
|
|
4539
5338
|
cclensPath: () => cclensPath,
|
|
4540
5339
|
clearCaches: () => clearCaches,
|
|
5340
|
+
clearGrokCaches: () => clearGrokCaches,
|
|
4541
5341
|
clearTeamConfig: () => clearTeamConfig,
|
|
4542
5342
|
codexSessionLocalDay: () => codexSessionLocalDay,
|
|
4543
5343
|
decodeProjectName: () => decodeProjectName,
|
|
@@ -4549,8 +5349,10 @@ __export(fs_exports, {
|
|
|
4549
5349
|
getCodexSession: () => getCodexSession,
|
|
4550
5350
|
getCoworkSession: () => getCoworkSession,
|
|
4551
5351
|
getGeminiSession: () => getGeminiSession,
|
|
5352
|
+
getGrokSession: () => getGrokSession,
|
|
4552
5353
|
getLatestCodexUsage: () => getLatestCodexUsage,
|
|
4553
5354
|
getSession: () => getSession,
|
|
5355
|
+
grokSessionLocalDay: () => grokSessionLocalDay,
|
|
4554
5356
|
invalidateFile: () => invalidateFile,
|
|
4555
5357
|
isFleetlensRuntimeDir: () => isFleetlensRuntimeDir,
|
|
4556
5358
|
listAllSessions: () => listAllSessions,
|
|
@@ -4558,6 +5360,7 @@ __export(fs_exports, {
|
|
|
4558
5360
|
listCodexSessions: () => listCodexSessions,
|
|
4559
5361
|
listCoworkSessions: () => listCoworkSessions,
|
|
4560
5362
|
listGeminiSessions: () => listGeminiSessions,
|
|
5363
|
+
listGrokSessions: () => listGrokSessions,
|
|
4561
5364
|
listProjects: () => listProjects,
|
|
4562
5365
|
listSessions: () => listSessions,
|
|
4563
5366
|
loadCalibrationCurve: () => loadCalibrationCurve,
|
|
@@ -4570,20 +5373,21 @@ __export(fs_exports, {
|
|
|
4570
5373
|
readGitFolder: () => readGitFolder,
|
|
4571
5374
|
readJsonlFile: () => readJsonlFile,
|
|
4572
5375
|
readTeamConfig: () => readTeamConfig,
|
|
5376
|
+
resolveDefaultGrokRoot: () => resolveDefaultGrokRoot,
|
|
4573
5377
|
resolveProjectIdentity: () => resolveProjectIdentity,
|
|
4574
5378
|
sessionIdFromFileName: () => sessionIdFromFileName,
|
|
4575
5379
|
shouldSyncProject: () => shouldSyncProject,
|
|
4576
5380
|
walkJsonlFiles: () => walkJsonlFiles,
|
|
4577
5381
|
writeTeamConfig: () => writeTeamConfig
|
|
4578
5382
|
});
|
|
4579
|
-
import { promises as
|
|
4580
|
-
import
|
|
4581
|
-
import
|
|
5383
|
+
import { promises as fs7, existsSync as existsSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync3, appendFileSync, mkdirSync as mkdirSync3 } from "node:fs";
|
|
5384
|
+
import os7 from "node:os";
|
|
5385
|
+
import path7 from "node:path";
|
|
4582
5386
|
function cclensHome() {
|
|
4583
|
-
return process.env.CCLENS_HOME ||
|
|
5387
|
+
return process.env.CCLENS_HOME || path7.join(os7.homedir(), ".cclens");
|
|
4584
5388
|
}
|
|
4585
5389
|
function cclensPath(...parts) {
|
|
4586
|
-
return
|
|
5390
|
+
return path7.join(cclensHome(), ...parts);
|
|
4587
5391
|
}
|
|
4588
5392
|
function cacheStats() {
|
|
4589
5393
|
return claudeCodeCacheStats();
|
|
@@ -4594,6 +5398,7 @@ function clearCaches() {
|
|
|
4594
5398
|
clearGeminiCaches();
|
|
4595
5399
|
clearAntigravityCaches();
|
|
4596
5400
|
clearCoworkCaches();
|
|
5401
|
+
clearGrokCaches();
|
|
4597
5402
|
}
|
|
4598
5403
|
function invalidateFile(fullPath) {
|
|
4599
5404
|
invalidateClaudeCodeFile(fullPath);
|
|
@@ -4624,7 +5429,7 @@ function usageLogPath() {
|
|
|
4624
5429
|
}
|
|
4625
5430
|
function appendUsageSnapshot(snapshot) {
|
|
4626
5431
|
const p = usageLogPath();
|
|
4627
|
-
mkdirSync3(
|
|
5432
|
+
mkdirSync3(path7.dirname(p), { recursive: true });
|
|
4628
5433
|
appendFileSync(p, JSON.stringify(snapshot) + "\n", "utf8");
|
|
4629
5434
|
}
|
|
4630
5435
|
function pruneUsageAgent(agent) {
|
|
@@ -4640,13 +5445,13 @@ function pruneUsageAgent(agent) {
|
|
|
4640
5445
|
return true;
|
|
4641
5446
|
}
|
|
4642
5447
|
});
|
|
4643
|
-
mkdirSync3(
|
|
5448
|
+
mkdirSync3(path7.dirname(p), { recursive: true });
|
|
4644
5449
|
writeFileSync3(p, kept.join("\n") + (kept.length ? "\n" : ""), "utf8");
|
|
4645
5450
|
}
|
|
4646
5451
|
async function loadUsageByDay(start2, end) {
|
|
4647
5452
|
let raw;
|
|
4648
5453
|
try {
|
|
4649
|
-
raw = await
|
|
5454
|
+
raw = await fs7.readFile(usageLogPath(), "utf8");
|
|
4650
5455
|
} catch {
|
|
4651
5456
|
return { by_day: [] };
|
|
4652
5457
|
}
|
|
@@ -4691,7 +5496,7 @@ async function loadUsageByDay(start2, end) {
|
|
|
4691
5496
|
async function loadCalibrationSnapshots() {
|
|
4692
5497
|
let raw;
|
|
4693
5498
|
try {
|
|
4694
|
-
raw = await
|
|
5499
|
+
raw = await fs7.readFile(usageLogPath(), "utf8");
|
|
4695
5500
|
} catch {
|
|
4696
5501
|
return [];
|
|
4697
5502
|
}
|
|
@@ -4855,7 +5660,7 @@ async function loadCalibrationCurve(tier = "pro-max-20x", root = DEFAULT_ROOT, g
|
|
|
4855
5660
|
]);
|
|
4856
5661
|
return buildCalibrationCurve(events, snapshots, tier, granularityMin);
|
|
4857
5662
|
}
|
|
4858
|
-
var codexSource, geminiSource, antigravitySource, coworkSource, agentSources;
|
|
5663
|
+
var codexSource, geminiSource, antigravitySource, coworkSource, grokSource, agentSources;
|
|
4859
5664
|
var init_fs = __esm({
|
|
4860
5665
|
"../parser/dist/fs.js"() {
|
|
4861
5666
|
"use strict";
|
|
@@ -4867,12 +5672,14 @@ var init_fs = __esm({
|
|
|
4867
5672
|
init_gemini();
|
|
4868
5673
|
init_antigravity();
|
|
4869
5674
|
init_cowork();
|
|
5675
|
+
init_grok();
|
|
4870
5676
|
init_claude_code();
|
|
4871
5677
|
init_git_project();
|
|
4872
5678
|
init_codex();
|
|
4873
5679
|
init_gemini();
|
|
4874
5680
|
init_antigravity();
|
|
4875
5681
|
init_cowork();
|
|
5682
|
+
init_grok();
|
|
4876
5683
|
init_team_config();
|
|
4877
5684
|
init_team_wire();
|
|
4878
5685
|
codexSource = {
|
|
@@ -4926,12 +5733,24 @@ var init_fs = __esm({
|
|
|
4926
5733
|
return getCoworkSession(id);
|
|
4927
5734
|
}
|
|
4928
5735
|
};
|
|
5736
|
+
grokSource = {
|
|
5737
|
+
...GROK_METADATA,
|
|
5738
|
+
// Display default; list/get re-resolve GROK_HOME at call time internally.
|
|
5739
|
+
defaultRoot: DEFAULT_GROK_ROOT,
|
|
5740
|
+
async listSessions(opts) {
|
|
5741
|
+
return listGrokSessions(opts);
|
|
5742
|
+
},
|
|
5743
|
+
async getSession(id, opts) {
|
|
5744
|
+
return getGrokSession(id, opts);
|
|
5745
|
+
}
|
|
5746
|
+
};
|
|
4929
5747
|
agentSources = [
|
|
4930
5748
|
claudeCodeSource,
|
|
4931
5749
|
codexSource,
|
|
4932
5750
|
geminiSource,
|
|
4933
5751
|
antigravitySource,
|
|
4934
|
-
coworkSource
|
|
5752
|
+
coworkSource,
|
|
5753
|
+
grokSource
|
|
4935
5754
|
];
|
|
4936
5755
|
}
|
|
4937
5756
|
});
|
|
@@ -4967,9 +5786,9 @@ function onDiskVersion() {
|
|
|
4967
5786
|
try {
|
|
4968
5787
|
const here = dirname3(fileURLToPath(import.meta.url));
|
|
4969
5788
|
const pkg = JSON.parse(readFileSync5(join3(here, "..", "package.json"), "utf8"));
|
|
4970
|
-
return pkg.version ?? "0.16.
|
|
5789
|
+
return pkg.version ?? "0.16.2";
|
|
4971
5790
|
} catch {
|
|
4972
|
-
return "0.16.
|
|
5791
|
+
return "0.16.2";
|
|
4973
5792
|
}
|
|
4974
5793
|
}
|
|
4975
5794
|
function getServerStatus() {
|
|
@@ -4981,7 +5800,7 @@ function getServerStatus() {
|
|
|
4981
5800
|
return { running: false };
|
|
4982
5801
|
}
|
|
4983
5802
|
function isServerStale(status2) {
|
|
4984
|
-
return status2.running === true && status2.version !== "0.16.
|
|
5803
|
+
return status2.running === true && status2.version !== "0.16.2";
|
|
4985
5804
|
}
|
|
4986
5805
|
async function ensureCurrentServer(opts = {}) {
|
|
4987
5806
|
const status2 = getServerStatus();
|
|
@@ -5420,9 +6239,9 @@ Installed: ${PACKAGE_NAME}@${verify.installedVersion} at ${verify.installedPath
|
|
|
5420
6239
|
console.warn(
|
|
5421
6240
|
` \u2022 reinstall in the correct Node env: 'npm install -g ${PACKAGE_NAME}@latest'`
|
|
5422
6241
|
);
|
|
5423
|
-
} else if (verify.installedVersion !== "0.16.
|
|
6242
|
+
} else if (verify.installedVersion !== "0.16.2") {
|
|
5424
6243
|
console.log(
|
|
5425
|
-
` \u2192 This process is still running ${"0.16.
|
|
6244
|
+
` \u2192 This process is still running ${"0.16.2"}. Next invocation will use ${verify.installedVersion}.`
|
|
5426
6245
|
);
|
|
5427
6246
|
}
|
|
5428
6247
|
}
|
|
@@ -5457,14 +6276,14 @@ async function getUpdateAvailability() {
|
|
|
5457
6276
|
if (isDevMode()) return null;
|
|
5458
6277
|
const latest = await fetchLatestVersion();
|
|
5459
6278
|
if (latest === null) return {
|
|
5460
|
-
current: "0.16.
|
|
6279
|
+
current: "0.16.2",
|
|
5461
6280
|
latest: null,
|
|
5462
6281
|
updateAvailable: false
|
|
5463
6282
|
};
|
|
5464
6283
|
return {
|
|
5465
|
-
current: "0.16.
|
|
6284
|
+
current: "0.16.2",
|
|
5466
6285
|
latest,
|
|
5467
|
-
updateAvailable: shouldUpdate("0.16.
|
|
6286
|
+
updateAvailable: shouldUpdate("0.16.2", latest)
|
|
5468
6287
|
};
|
|
5469
6288
|
}
|
|
5470
6289
|
async function checkForUpdate() {
|
|
@@ -5554,7 +6373,7 @@ async function restartServices(state) {
|
|
|
5554
6373
|
}
|
|
5555
6374
|
async function forceUpdate() {
|
|
5556
6375
|
const latest = await fetchLatestVersion();
|
|
5557
|
-
const current = "0.16.
|
|
6376
|
+
const current = "0.16.2";
|
|
5558
6377
|
if (latest === null) {
|
|
5559
6378
|
console.error("Could not reach npm registry. Check your network.");
|
|
5560
6379
|
process.exit(1);
|
|
@@ -5967,7 +6786,7 @@ async function status() {
|
|
|
5967
6786
|
console.log(`Server: running on ${url} (PID ${server.pid}, v${ver})`);
|
|
5968
6787
|
if (isServerStale(server)) {
|
|
5969
6788
|
console.log(
|
|
5970
|
-
` \u26A0 serving stale ${ver} (CLI is ${"0.16.
|
|
6789
|
+
` \u26A0 serving stale ${ver} (CLI is ${"0.16.2"}) \u2014 run 'fleetlens start' to restart on the current version`
|
|
5971
6790
|
);
|
|
5972
6791
|
}
|
|
5973
6792
|
} else {
|
|
@@ -6006,7 +6825,7 @@ async function web(args2) {
|
|
|
6006
6825
|
const open = args2.includes("--open");
|
|
6007
6826
|
const positional = args2.filter((a) => !a.startsWith("--"));
|
|
6008
6827
|
const rawPath = positional[0] ?? "";
|
|
6009
|
-
const
|
|
6828
|
+
const path9 = rawPath.startsWith("/") ? rawPath : rawPath ? `/${rawPath}` : "";
|
|
6010
6829
|
let result;
|
|
6011
6830
|
try {
|
|
6012
6831
|
result = await ensureCurrentServer({});
|
|
@@ -6014,7 +6833,7 @@ async function web(args2) {
|
|
|
6014
6833
|
console.error(`Failed to start: ${err.message}`);
|
|
6015
6834
|
process.exit(1);
|
|
6016
6835
|
}
|
|
6017
|
-
const url = `http://localhost:${result.port}${
|
|
6836
|
+
const url = `http://localhost:${result.port}${path9}`;
|
|
6018
6837
|
if (result.restarted) {
|
|
6019
6838
|
console.log(`fleetlens restarted on http://localhost:${result.port} (PID ${result.pid}) \u2014 replaced stale ${result.previousVersion ?? "unknown"} server`);
|
|
6020
6839
|
}
|
|
@@ -6075,9 +6894,9 @@ function readFromCredentialsFile() {
|
|
|
6075
6894
|
join7(homedir4(), ".claude", ".credentials.json"),
|
|
6076
6895
|
join7(homedir4(), ".config", "claude", "credentials.json")
|
|
6077
6896
|
];
|
|
6078
|
-
for (const
|
|
6897
|
+
for (const path9 of candidates) {
|
|
6079
6898
|
try {
|
|
6080
|
-
const blob = readFileSync10(
|
|
6899
|
+
const blob = readFileSync10(path9, "utf8");
|
|
6081
6900
|
const creds = extractCredentials(blob);
|
|
6082
6901
|
if (creds) return creds;
|
|
6083
6902
|
} catch {
|
|
@@ -6199,6 +7018,224 @@ var init_api = __esm({
|
|
|
6199
7018
|
}
|
|
6200
7019
|
});
|
|
6201
7020
|
|
|
7021
|
+
// src/usage/grok.ts
|
|
7022
|
+
import { existsSync as existsSync8, readFileSync as readFileSync11 } from "node:fs";
|
|
7023
|
+
import os8 from "node:os";
|
|
7024
|
+
import path8 from "node:path";
|
|
7025
|
+
function grokHome() {
|
|
7026
|
+
return process.env.GROK_HOME || path8.join(os8.homedir(), ".grok");
|
|
7027
|
+
}
|
|
7028
|
+
function authPath() {
|
|
7029
|
+
return path8.join(grokHome(), "auth.json");
|
|
7030
|
+
}
|
|
7031
|
+
function loadAuthEntry() {
|
|
7032
|
+
const p = authPath();
|
|
7033
|
+
if (!existsSync8(p)) {
|
|
7034
|
+
throw new GrokApiError("Grok not logged in. Run `grok login`.", "no_auth");
|
|
7035
|
+
}
|
|
7036
|
+
let raw;
|
|
7037
|
+
try {
|
|
7038
|
+
raw = JSON.parse(readFileSync11(p, "utf8"));
|
|
7039
|
+
} catch {
|
|
7040
|
+
throw new GrokApiError("Grok auth.json is unreadable. Run `grok login`.", "no_auth");
|
|
7041
|
+
}
|
|
7042
|
+
for (const [entryKey2, entry] of Object.entries(raw)) {
|
|
7043
|
+
const token = typeof entry?.key === "string" ? entry.key.trim() : "";
|
|
7044
|
+
if (token) return { token, entry, entryKey: entryKey2 };
|
|
7045
|
+
}
|
|
7046
|
+
throw new GrokApiError("Grok auth has no access token. Run `grok login`.", "no_auth");
|
|
7047
|
+
}
|
|
7048
|
+
function needsRefresh(entry) {
|
|
7049
|
+
const exp = entry.expires_at;
|
|
7050
|
+
if (!exp) return false;
|
|
7051
|
+
const ms = Date.parse(exp);
|
|
7052
|
+
if (!Number.isFinite(ms)) return false;
|
|
7053
|
+
return Date.now() >= ms - REFRESH_BUFFER_MS;
|
|
7054
|
+
}
|
|
7055
|
+
async function refreshAccessToken(entry) {
|
|
7056
|
+
const refresh = entry.refresh_token?.trim();
|
|
7057
|
+
if (!refresh) return null;
|
|
7058
|
+
const clientId = entry.oidc_client_id?.trim() || DEFAULT_CLIENT_ID;
|
|
7059
|
+
const body = new URLSearchParams({
|
|
7060
|
+
grant_type: "refresh_token",
|
|
7061
|
+
client_id: clientId,
|
|
7062
|
+
refresh_token: refresh
|
|
7063
|
+
});
|
|
7064
|
+
let res;
|
|
7065
|
+
try {
|
|
7066
|
+
res = await fetch(REFRESH_URL, {
|
|
7067
|
+
method: "POST",
|
|
7068
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
7069
|
+
body: body.toString()
|
|
7070
|
+
});
|
|
7071
|
+
} catch {
|
|
7072
|
+
return null;
|
|
7073
|
+
}
|
|
7074
|
+
if (!res.ok) return null;
|
|
7075
|
+
try {
|
|
7076
|
+
const j = await res.json();
|
|
7077
|
+
if (typeof j.access_token !== "string" || !j.access_token) return null;
|
|
7078
|
+
try {
|
|
7079
|
+
const p = authPath();
|
|
7080
|
+
const raw = JSON.parse(readFileSync11(p, "utf8"));
|
|
7081
|
+
for (const key of Object.keys(raw)) {
|
|
7082
|
+
if (raw[key]?.key === entry.key || raw[key]?.refresh_token === refresh) {
|
|
7083
|
+
raw[key] = {
|
|
7084
|
+
...raw[key],
|
|
7085
|
+
key: j.access_token,
|
|
7086
|
+
refresh_token: j.refresh_token ?? raw[key].refresh_token,
|
|
7087
|
+
expires_at: typeof j.expires_in === "number" ? new Date(Date.now() + j.expires_in * 1e3).toISOString() : raw[key].expires_at
|
|
7088
|
+
};
|
|
7089
|
+
break;
|
|
7090
|
+
}
|
|
7091
|
+
}
|
|
7092
|
+
const { writeFileSync: writeFileSync17 } = await import("node:fs");
|
|
7093
|
+
writeFileSync17(p, JSON.stringify(raw, null, 2), "utf8");
|
|
7094
|
+
} catch {
|
|
7095
|
+
}
|
|
7096
|
+
return j.access_token;
|
|
7097
|
+
} catch {
|
|
7098
|
+
return null;
|
|
7099
|
+
}
|
|
7100
|
+
}
|
|
7101
|
+
function authHeaders(token) {
|
|
7102
|
+
return {
|
|
7103
|
+
Authorization: `Bearer ${token.trim()}`,
|
|
7104
|
+
"X-XAI-Token-Auth": TOKEN_AUTH,
|
|
7105
|
+
Accept: "application/json",
|
|
7106
|
+
"User-Agent": "fleetlens"
|
|
7107
|
+
};
|
|
7108
|
+
}
|
|
7109
|
+
function parseGrokCreditsConfig(body) {
|
|
7110
|
+
if (!body || typeof body !== "object") {
|
|
7111
|
+
throw new GrokApiError("Grok billing response missing body", "parse");
|
|
7112
|
+
}
|
|
7113
|
+
const config = body.config;
|
|
7114
|
+
if (!config || typeof config !== "object") {
|
|
7115
|
+
throw new GrokApiError("Grok billing response missing config", "parse");
|
|
7116
|
+
}
|
|
7117
|
+
const period = config.currentPeriod;
|
|
7118
|
+
if (!period || typeof period !== "object") {
|
|
7119
|
+
throw new GrokApiError("Grok billing response missing currentPeriod", "parse");
|
|
7120
|
+
}
|
|
7121
|
+
const periodType = typeof period.type === "string" ? period.type.trim() : "";
|
|
7122
|
+
if (!periodType) {
|
|
7123
|
+
throw new GrokApiError("Grok billing period type missing", "parse");
|
|
7124
|
+
}
|
|
7125
|
+
let utilization = 0;
|
|
7126
|
+
if (config.creditUsagePercent !== void 0 && config.creditUsagePercent !== null) {
|
|
7127
|
+
const n = Number(config.creditUsagePercent);
|
|
7128
|
+
if (!Number.isFinite(n)) {
|
|
7129
|
+
throw new GrokApiError("Grok creditUsagePercent is not a number", "parse");
|
|
7130
|
+
}
|
|
7131
|
+
utilization = Math.min(100, Math.max(0, n));
|
|
7132
|
+
}
|
|
7133
|
+
const end = typeof period.end === "string" && period.end ? new Date(period.end).toISOString() : null;
|
|
7134
|
+
let onDemandCap = 0;
|
|
7135
|
+
const cap = config.onDemandCap;
|
|
7136
|
+
if (cap && typeof cap === "object" && "val" in cap) {
|
|
7137
|
+
const v = Number(cap.val);
|
|
7138
|
+
if (Number.isFinite(v)) onDemandCap = v;
|
|
7139
|
+
}
|
|
7140
|
+
return {
|
|
7141
|
+
utilization,
|
|
7142
|
+
resets_at: end && !Number.isNaN(Date.parse(end)) ? end : null,
|
|
7143
|
+
period_type: periodType,
|
|
7144
|
+
on_demand_cap: onDemandCap
|
|
7145
|
+
};
|
|
7146
|
+
}
|
|
7147
|
+
async function fetchJson(url, token) {
|
|
7148
|
+
let res;
|
|
7149
|
+
try {
|
|
7150
|
+
res = await fetch(url, { headers: authHeaders(token) });
|
|
7151
|
+
} catch (err) {
|
|
7152
|
+
throw new GrokApiError(
|
|
7153
|
+
`Network error reaching Grok billing: ${err.message}`,
|
|
7154
|
+
"network"
|
|
7155
|
+
);
|
|
7156
|
+
}
|
|
7157
|
+
let body = null;
|
|
7158
|
+
try {
|
|
7159
|
+
body = await res.json();
|
|
7160
|
+
} catch {
|
|
7161
|
+
}
|
|
7162
|
+
return { status: res.status, body };
|
|
7163
|
+
}
|
|
7164
|
+
async function fetchGrokUsage() {
|
|
7165
|
+
const loaded = loadAuthEntry();
|
|
7166
|
+
const entry = loaded.entry;
|
|
7167
|
+
let token = loaded.token;
|
|
7168
|
+
if (needsRefresh(entry)) {
|
|
7169
|
+
const refreshed = await refreshAccessToken(entry);
|
|
7170
|
+
if (refreshed) token = refreshed;
|
|
7171
|
+
}
|
|
7172
|
+
let { status: status2, body } = await fetchJson(CREDITS_URL, token);
|
|
7173
|
+
if (status2 === 401 || status2 === 403) {
|
|
7174
|
+
const refreshed = await refreshAccessToken(entry);
|
|
7175
|
+
if (refreshed) {
|
|
7176
|
+
token = refreshed;
|
|
7177
|
+
({ status: status2, body } = await fetchJson(CREDITS_URL, token));
|
|
7178
|
+
}
|
|
7179
|
+
}
|
|
7180
|
+
if (status2 < 200 || status2 >= 300) {
|
|
7181
|
+
throw new GrokApiError(
|
|
7182
|
+
`Grok billing returned HTTP ${status2}`,
|
|
7183
|
+
status2 === 401 || status2 === 403 ? "no_auth" : "http"
|
|
7184
|
+
);
|
|
7185
|
+
}
|
|
7186
|
+
const credits = parseGrokCreditsConfig(body);
|
|
7187
|
+
if (credits.period_type !== WEEKLY_PERIOD) {
|
|
7188
|
+
throw new GrokApiError(
|
|
7189
|
+
`Grok period is ${credits.period_type}, not weekly`,
|
|
7190
|
+
"not_weekly"
|
|
7191
|
+
);
|
|
7192
|
+
}
|
|
7193
|
+
let planType = null;
|
|
7194
|
+
try {
|
|
7195
|
+
const settings = await fetchJson(SETTINGS_URL, token);
|
|
7196
|
+
if (settings.status >= 200 && settings.status < 300 && settings.body && typeof settings.body === "object") {
|
|
7197
|
+
const tier = settings.body.subscription_tier_display;
|
|
7198
|
+
if (typeof tier === "string" && tier.trim()) planType = tier.trim();
|
|
7199
|
+
}
|
|
7200
|
+
} catch {
|
|
7201
|
+
}
|
|
7202
|
+
return {
|
|
7203
|
+
captured_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7204
|
+
agent: "grok",
|
|
7205
|
+
// No 5-hour window — menubar / strip show "—" on the top line.
|
|
7206
|
+
five_hour: { utilization: null, resets_at: null },
|
|
7207
|
+
seven_day: {
|
|
7208
|
+
utilization: credits.utilization,
|
|
7209
|
+
resets_at: credits.resets_at
|
|
7210
|
+
},
|
|
7211
|
+
seven_day_opus: null,
|
|
7212
|
+
seven_day_sonnet: null,
|
|
7213
|
+
seven_day_oauth_apps: null,
|
|
7214
|
+
seven_day_cowork: null,
|
|
7215
|
+
extra_usage: null,
|
|
7216
|
+
plan_type: planType
|
|
7217
|
+
};
|
|
7218
|
+
}
|
|
7219
|
+
var CREDITS_URL, SETTINGS_URL, REFRESH_URL, TOKEN_AUTH, DEFAULT_CLIENT_ID, WEEKLY_PERIOD, REFRESH_BUFFER_MS, GrokApiError;
|
|
7220
|
+
var init_grok2 = __esm({
|
|
7221
|
+
"src/usage/grok.ts"() {
|
|
7222
|
+
"use strict";
|
|
7223
|
+
CREDITS_URL = "https://cli-chat-proxy.grok.com/v1/billing?format=credits";
|
|
7224
|
+
SETTINGS_URL = "https://cli-chat-proxy.grok.com/v1/settings";
|
|
7225
|
+
REFRESH_URL = "https://auth.x.ai/oauth2/token";
|
|
7226
|
+
TOKEN_AUTH = "xai-grok-cli";
|
|
7227
|
+
DEFAULT_CLIENT_ID = "b1a00492-073a-47ea-816f-4c329264a828";
|
|
7228
|
+
WEEKLY_PERIOD = "USAGE_PERIOD_TYPE_WEEKLY";
|
|
7229
|
+
REFRESH_BUFFER_MS = 5 * 60 * 1e3;
|
|
7230
|
+
GrokApiError = class extends Error {
|
|
7231
|
+
constructor(message, code) {
|
|
7232
|
+
super(message);
|
|
7233
|
+
this.code = code;
|
|
7234
|
+
}
|
|
7235
|
+
};
|
|
7236
|
+
}
|
|
7237
|
+
});
|
|
7238
|
+
|
|
6202
7239
|
// src/usage/format.ts
|
|
6203
7240
|
function formatUsage(snapshot) {
|
|
6204
7241
|
const rows = [
|
|
@@ -6558,6 +7595,30 @@ Usage:
|
|
|
6558
7595
|
const snapshot = await fetchUsage();
|
|
6559
7596
|
if (save) appendSnapshot(USAGE_LOG2, snapshot);
|
|
6560
7597
|
process.stdout.write(formatUsage(snapshot));
|
|
7598
|
+
if (save) {
|
|
7599
|
+
for (const source of agentSources) {
|
|
7600
|
+
if (source.kind === "claude-code" || !source.usagePoller) continue;
|
|
7601
|
+
try {
|
|
7602
|
+
const partial = await source.usagePoller();
|
|
7603
|
+
if (!partial) continue;
|
|
7604
|
+
appendSnapshot(USAGE_LOG2, {
|
|
7605
|
+
...partial,
|
|
7606
|
+
seven_day_opus: null,
|
|
7607
|
+
seven_day_sonnet: null,
|
|
7608
|
+
seven_day_oauth_apps: null,
|
|
7609
|
+
seven_day_cowork: null,
|
|
7610
|
+
extra_usage: null
|
|
7611
|
+
});
|
|
7612
|
+
} catch {
|
|
7613
|
+
}
|
|
7614
|
+
}
|
|
7615
|
+
try {
|
|
7616
|
+
appendSnapshot(USAGE_LOG2, await fetchGrokUsage());
|
|
7617
|
+
} catch (err) {
|
|
7618
|
+
if (!(err instanceof GrokApiError && err.code === "no_auth")) {
|
|
7619
|
+
}
|
|
7620
|
+
}
|
|
7621
|
+
}
|
|
6561
7622
|
process.stdout.write("\n (tip: run with --history for the daily token/cost table)\n");
|
|
6562
7623
|
} catch (err) {
|
|
6563
7624
|
if (err instanceof UsageApiError) {
|
|
@@ -6572,6 +7633,7 @@ var init_usage = __esm({
|
|
|
6572
7633
|
"src/commands/usage.ts"() {
|
|
6573
7634
|
"use strict";
|
|
6574
7635
|
init_api();
|
|
7636
|
+
init_grok2();
|
|
6575
7637
|
init_format();
|
|
6576
7638
|
init_storage();
|
|
6577
7639
|
init_fs();
|
|
@@ -7068,6 +8130,7 @@ __export(dist_exports, {
|
|
|
7068
8130
|
CODEX_METADATA: () => CODEX_METADATA,
|
|
7069
8131
|
COWORK_METADATA: () => COWORK_METADATA,
|
|
7070
8132
|
GEMINI_METADATA: () => GEMINI_METADATA,
|
|
8133
|
+
GROK_METADATA: () => GROK_METADATA,
|
|
7071
8134
|
PRICES: () => PRICES,
|
|
7072
8135
|
RATE_PER_PCT: () => RATE_PER_PCT,
|
|
7073
8136
|
RATE_PER_PCT_5H: () => RATE_PER_PCT_5H,
|
|
@@ -7481,7 +8544,7 @@ function closeTurn(t, closed, cwd) {
|
|
|
7481
8544
|
let active = 0;
|
|
7482
8545
|
for (let i = 1; i < ts.length; i++) {
|
|
7483
8546
|
const dt = ts[i] - ts[i - 1];
|
|
7484
|
-
if (dt <
|
|
8547
|
+
if (dt < IDLE_GAP_MS5)
|
|
7485
8548
|
active += dt;
|
|
7486
8549
|
}
|
|
7487
8550
|
closed.push({
|
|
@@ -7678,7 +8741,7 @@ function aggregateDay(dayEvents, _sessionFallbackProject) {
|
|
|
7678
8741
|
let activeMs2 = 0;
|
|
7679
8742
|
for (let i = 1; i < tsSorted.length; i++) {
|
|
7680
8743
|
const dt = tsSorted[i] - tsSorted[i - 1];
|
|
7681
|
-
if (dt <
|
|
8744
|
+
if (dt < IDLE_GAP_MS5)
|
|
7682
8745
|
activeMs2 += dt;
|
|
7683
8746
|
}
|
|
7684
8747
|
const tsSortedStrings = dayEvents.map((e) => e.timestamp).filter((t) => !!t).sort();
|
|
@@ -7865,7 +8928,7 @@ function buildEntries(sessionDetail) {
|
|
|
7865
8928
|
entries2.sort((a, b) => a.local_day.localeCompare(b.local_day));
|
|
7866
8929
|
return entries2;
|
|
7867
8930
|
}
|
|
7868
|
-
var
|
|
8931
|
+
var IDLE_GAP_MS5, INTERRUPT_RE2, PR_TITLE_RE, BASH_CHAIN_SPLIT_RE, SHELL_NOISE, IMAGE_BLOCK_RE;
|
|
7869
8932
|
var init_build = __esm({
|
|
7870
8933
|
"../entries/dist/build.js"() {
|
|
7871
8934
|
"use strict";
|
|
@@ -7873,7 +8936,7 @@ var init_build = __esm({
|
|
|
7873
8936
|
init_types();
|
|
7874
8937
|
init_signals();
|
|
7875
8938
|
init_trivial();
|
|
7876
|
-
|
|
8939
|
+
IDLE_GAP_MS5 = 3 * 60 * 1e3;
|
|
7877
8940
|
INTERRUPT_RE2 = /\[request interrupted|interrupted by user/i;
|
|
7878
8941
|
PR_TITLE_RE = /--title\s+["']([^"']+)["']/;
|
|
7879
8942
|
BASH_CHAIN_SPLIT_RE = /\|\||&&|;|\|/;
|
|
@@ -7902,11 +8965,11 @@ var init_dist2 = __esm({
|
|
|
7902
8965
|
});
|
|
7903
8966
|
|
|
7904
8967
|
// ../entries/dist/digest-fs.js
|
|
7905
|
-
import { readFileSync as
|
|
8968
|
+
import { readFileSync as readFileSync12, readdirSync, writeFileSync as writeFileSync6, renameSync as renameSync2, chmodSync, mkdirSync as mkdirSync6, existsSync as existsSync9 } from "node:fs";
|
|
7906
8969
|
import { dirname as dirname8, join as join8 } from "node:path";
|
|
7907
|
-
function parseDigestFile(
|
|
8970
|
+
function parseDigestFile(path9, expectedVersion) {
|
|
7908
8971
|
try {
|
|
7909
|
-
const parsed = JSON.parse(
|
|
8972
|
+
const parsed = JSON.parse(readFileSync12(path9, "utf8"));
|
|
7910
8973
|
if (!parsed || typeof parsed !== "object")
|
|
7911
8974
|
return null;
|
|
7912
8975
|
if (parsed.version !== expectedVersion)
|
|
@@ -7925,11 +8988,11 @@ function digestsDir() {
|
|
|
7925
8988
|
digestsDirCached = envOverride ?? cclensPath("digests");
|
|
7926
8989
|
return digestsDirCached;
|
|
7927
8990
|
}
|
|
7928
|
-
function __setDigestsDirForTest(
|
|
7929
|
-
digestsDirCached =
|
|
7930
|
-
mkdirSync6(join8(
|
|
7931
|
-
mkdirSync6(join8(
|
|
7932
|
-
mkdirSync6(join8(
|
|
8991
|
+
function __setDigestsDirForTest(path9) {
|
|
8992
|
+
digestsDirCached = path9;
|
|
8993
|
+
mkdirSync6(join8(path9, "day"), { recursive: true });
|
|
8994
|
+
mkdirSync6(join8(path9, "week"), { recursive: true });
|
|
8995
|
+
mkdirSync6(join8(path9, "month"), { recursive: true });
|
|
7933
8996
|
}
|
|
7934
8997
|
function dayDigestPath(date) {
|
|
7935
8998
|
return join8(digestsDir(), "day", `${date}.json`);
|
|
@@ -7955,7 +9018,7 @@ function writeDayDigest(digest2) {
|
|
|
7955
9018
|
}
|
|
7956
9019
|
function readDayDigest(date) {
|
|
7957
9020
|
const p = dayDigestPath(date);
|
|
7958
|
-
if (!
|
|
9021
|
+
if (!existsSync9(p))
|
|
7959
9022
|
return null;
|
|
7960
9023
|
return parseDigestFile(p, CURRENT_DAY_DIGEST_SCHEMA_VERSION);
|
|
7961
9024
|
}
|
|
@@ -7991,13 +9054,13 @@ function writeWeekDigest(digest2) {
|
|
|
7991
9054
|
}
|
|
7992
9055
|
function readWeekDigest(monday) {
|
|
7993
9056
|
const p = weekDigestPath(monday);
|
|
7994
|
-
if (!
|
|
9057
|
+
if (!existsSync9(p))
|
|
7995
9058
|
return null;
|
|
7996
9059
|
return parseDigestFile(p, CURRENT_WEEK_DIGEST_SCHEMA_VERSION);
|
|
7997
9060
|
}
|
|
7998
9061
|
function listWeekDigestKeys() {
|
|
7999
9062
|
const dir = join8(digestsDir(), "week");
|
|
8000
|
-
if (!
|
|
9063
|
+
if (!existsSync9(dir))
|
|
8001
9064
|
return [];
|
|
8002
9065
|
return readdirSync(dir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length)).filter((k) => /^\d{4}-\d{2}-\d{2}$/.test(k));
|
|
8003
9066
|
}
|
|
@@ -8028,13 +9091,13 @@ function writeMonthDigest(digest2) {
|
|
|
8028
9091
|
}
|
|
8029
9092
|
function readMonthDigest(yearMonth) {
|
|
8030
9093
|
const p = monthDigestPath(yearMonth);
|
|
8031
|
-
if (!
|
|
9094
|
+
if (!existsSync9(p))
|
|
8032
9095
|
return null;
|
|
8033
9096
|
return parseDigestFile(p, CURRENT_MONTH_DIGEST_SCHEMA_VERSION);
|
|
8034
9097
|
}
|
|
8035
9098
|
function listMonthDigestKeys() {
|
|
8036
9099
|
const dir = join8(digestsDir(), "month");
|
|
8037
|
-
if (!
|
|
9100
|
+
if (!existsSync9(dir))
|
|
8038
9101
|
return [];
|
|
8039
9102
|
return readdirSync(dir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length)).filter((k) => /^\d{4}-\d{2}$/.test(k));
|
|
8040
9103
|
}
|
|
@@ -8096,7 +9159,7 @@ __export(fs_exports2, {
|
|
|
8096
9159
|
writeMonthDigest: () => writeMonthDigest,
|
|
8097
9160
|
writeWeekDigest: () => writeWeekDigest
|
|
8098
9161
|
});
|
|
8099
|
-
import { readFileSync as
|
|
9162
|
+
import { readFileSync as readFileSync13, readdirSync as readdirSync2, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7, renameSync as renameSync3, existsSync as existsSync10 } from "node:fs";
|
|
8100
9163
|
import { randomBytes } from "node:crypto";
|
|
8101
9164
|
import { join as join9 } from "node:path";
|
|
8102
9165
|
function entriesDir() {
|
|
@@ -8106,9 +9169,9 @@ function entriesDir() {
|
|
|
8106
9169
|
entriesDirCached = envOverride ?? cclensPath("entries");
|
|
8107
9170
|
return entriesDirCached;
|
|
8108
9171
|
}
|
|
8109
|
-
function __setEntriesDirForTest(
|
|
8110
|
-
entriesDirCached =
|
|
8111
|
-
mkdirSync7(
|
|
9172
|
+
function __setEntriesDirForTest(path9) {
|
|
9173
|
+
entriesDirCached = path9;
|
|
9174
|
+
mkdirSync7(path9, { recursive: true });
|
|
8112
9175
|
}
|
|
8113
9176
|
function pathFor(sessionId, localDay2) {
|
|
8114
9177
|
return join9(entriesDir(), `${entryKey(sessionId, localDay2)}.json`);
|
|
@@ -8155,17 +9218,17 @@ function writeEntryPreservingEnrichment(fresh) {
|
|
|
8155
9218
|
}
|
|
8156
9219
|
function readEntry(sessionId, localDay2) {
|
|
8157
9220
|
const p = pathFor(sessionId, localDay2);
|
|
8158
|
-
if (!
|
|
9221
|
+
if (!existsSync10(p))
|
|
8159
9222
|
return null;
|
|
8160
|
-
const raw =
|
|
9223
|
+
const raw = readFileSync13(p, "utf8");
|
|
8161
9224
|
return JSON.parse(raw);
|
|
8162
9225
|
}
|
|
8163
9226
|
function entryExists(sessionId, localDay2) {
|
|
8164
|
-
return
|
|
9227
|
+
return existsSync10(pathFor(sessionId, localDay2));
|
|
8165
9228
|
}
|
|
8166
9229
|
function listEntryKeys() {
|
|
8167
9230
|
const dir = entriesDir();
|
|
8168
|
-
if (!
|
|
9231
|
+
if (!existsSync10(dir))
|
|
8169
9232
|
return [];
|
|
8170
9233
|
return readdirSync2(dir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length));
|
|
8171
9234
|
}
|
|
@@ -8647,8 +9710,8 @@ var init_parseUtil = __esm({
|
|
|
8647
9710
|
init_errors();
|
|
8648
9711
|
init_en();
|
|
8649
9712
|
makeIssue = (params) => {
|
|
8650
|
-
const { data, path:
|
|
8651
|
-
const fullPath = [...
|
|
9713
|
+
const { data, path: path9, errorMaps, issueData } = params;
|
|
9714
|
+
const fullPath = [...path9, ...issueData.path || []];
|
|
8652
9715
|
const fullIssue = {
|
|
8653
9716
|
...issueData,
|
|
8654
9717
|
path: fullPath
|
|
@@ -8956,11 +10019,11 @@ var init_types3 = __esm({
|
|
|
8956
10019
|
init_parseUtil();
|
|
8957
10020
|
init_util();
|
|
8958
10021
|
ParseInputLazyPath = class {
|
|
8959
|
-
constructor(parent, value,
|
|
10022
|
+
constructor(parent, value, path9, key) {
|
|
8960
10023
|
this._cachedPath = [];
|
|
8961
10024
|
this.parent = parent;
|
|
8962
10025
|
this.data = value;
|
|
8963
|
-
this._path =
|
|
10026
|
+
this._path = path9;
|
|
8964
10027
|
this._key = key;
|
|
8965
10028
|
}
|
|
8966
10029
|
get path() {
|
|
@@ -12444,7 +13507,7 @@ RESPOND WITH ONLY VALID JSON (no prose, no code fence):
|
|
|
12444
13507
|
});
|
|
12445
13508
|
|
|
12446
13509
|
// ../entries/dist/tmux-runner.js
|
|
12447
|
-
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync8, existsSync as
|
|
13510
|
+
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync8, existsSync as existsSync11, readdirSync as readdirSync3, realpathSync as realpathSync5, readFileSync as readFileSync14, unlinkSync as unlinkSync3, renameSync as renameSync4 } from "node:fs";
|
|
12448
13511
|
import { join as join10 } from "node:path";
|
|
12449
13512
|
import { homedir as homedir5 } from "node:os";
|
|
12450
13513
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
@@ -12463,7 +13526,7 @@ function tmuxRunnerAvailable() {
|
|
|
12463
13526
|
}
|
|
12464
13527
|
function runtimeCwd() {
|
|
12465
13528
|
const dir = join10(homedir5(), ".cclens", "runtime");
|
|
12466
|
-
if (!
|
|
13529
|
+
if (!existsSync11(dir))
|
|
12467
13530
|
mkdirSync8(dir, { recursive: true });
|
|
12468
13531
|
return realpathSync5(dir);
|
|
12469
13532
|
}
|
|
@@ -12471,7 +13534,7 @@ function ensureRuntimeCwdTrusted(cwd) {
|
|
|
12471
13534
|
const cfgPath = join10(homedir5(), ".claude.json");
|
|
12472
13535
|
let cfg;
|
|
12473
13536
|
try {
|
|
12474
|
-
cfg = JSON.parse(
|
|
13537
|
+
cfg = JSON.parse(readFileSync14(cfgPath, "utf8"));
|
|
12475
13538
|
} catch {
|
|
12476
13539
|
return;
|
|
12477
13540
|
}
|
|
@@ -12618,10 +13681,10 @@ function snapshotAllTranscripts() {
|
|
|
12618
13681
|
}
|
|
12619
13682
|
return out;
|
|
12620
13683
|
}
|
|
12621
|
-
function readJsonlCwd(
|
|
13684
|
+
function readJsonlCwd(path9, maxLines = 8) {
|
|
12622
13685
|
let raw;
|
|
12623
13686
|
try {
|
|
12624
|
-
raw =
|
|
13687
|
+
raw = readFileSync14(path9, "utf8");
|
|
12625
13688
|
} catch {
|
|
12626
13689
|
return void 0;
|
|
12627
13690
|
}
|
|
@@ -12675,10 +13738,10 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
|
|
|
12675
13738
|
}
|
|
12676
13739
|
throw new TmuxRunError(`timeout waiting for claude to create the session transcript (cwd: ${targetCwd})`);
|
|
12677
13740
|
}
|
|
12678
|
-
function parseTranscript2(
|
|
13741
|
+
function parseTranscript2(path9, defaultModel) {
|
|
12679
13742
|
let raw;
|
|
12680
13743
|
try {
|
|
12681
|
-
raw =
|
|
13744
|
+
raw = readFileSync14(path9, "utf8");
|
|
12682
13745
|
} catch {
|
|
12683
13746
|
return { assembled: "", inputTokens: 0, outputTokens: 0, modelUsed: defaultModel, done: false };
|
|
12684
13747
|
}
|
|
@@ -12772,11 +13835,11 @@ var init_tmux_runner = __esm({
|
|
|
12772
13835
|
|
|
12773
13836
|
// ../entries/dist/llm-runner.js
|
|
12774
13837
|
import { spawn as spawn3 } from "node:child_process";
|
|
12775
|
-
import { mkdirSync as mkdirSync9, appendFileSync as appendFileSync3, writeFileSync as writeFileSync9, existsSync as
|
|
13838
|
+
import { mkdirSync as mkdirSync9, appendFileSync as appendFileSync3, writeFileSync as writeFileSync9, existsSync as existsSync12 } from "node:fs";
|
|
12776
13839
|
import { join as join11 } from "node:path";
|
|
12777
13840
|
import { randomUUID } from "node:crypto";
|
|
12778
13841
|
function ensureRunsDir() {
|
|
12779
|
-
if (!
|
|
13842
|
+
if (!existsSync12(RUNS_DIR)) {
|
|
12780
13843
|
try {
|
|
12781
13844
|
mkdirSync9(RUNS_DIR, { recursive: true });
|
|
12782
13845
|
} catch {
|
|
@@ -12807,15 +13870,15 @@ function newRunId(kind) {
|
|
|
12807
13870
|
function tracePath(runId) {
|
|
12808
13871
|
return join11(RUNS_DIR, `${runId}.jsonl`);
|
|
12809
13872
|
}
|
|
12810
|
-
function safeAppend(
|
|
13873
|
+
function safeAppend(path9, line) {
|
|
12811
13874
|
try {
|
|
12812
|
-
appendFileSync3(
|
|
13875
|
+
appendFileSync3(path9, line);
|
|
12813
13876
|
} catch {
|
|
12814
13877
|
}
|
|
12815
13878
|
}
|
|
12816
|
-
function safeWrite(
|
|
13879
|
+
function safeWrite(path9, line) {
|
|
12817
13880
|
try {
|
|
12818
|
-
writeFileSync9(
|
|
13881
|
+
writeFileSync9(path9, line);
|
|
12819
13882
|
} catch {
|
|
12820
13883
|
}
|
|
12821
13884
|
}
|
|
@@ -13221,7 +14284,7 @@ var init_enrich2 = __esm({
|
|
|
13221
14284
|
});
|
|
13222
14285
|
|
|
13223
14286
|
// ../entries/dist/budget.js
|
|
13224
|
-
import { appendFileSync as appendFileSync4, readFileSync as
|
|
14287
|
+
import { appendFileSync as appendFileSync4, readFileSync as readFileSync15, existsSync as existsSync13, mkdirSync as mkdirSync10 } from "node:fs";
|
|
13225
14288
|
import { dirname as dirname9 } from "node:path";
|
|
13226
14289
|
function spendPath() {
|
|
13227
14290
|
if (spendPathCached)
|
|
@@ -13229,8 +14292,8 @@ function spendPath() {
|
|
|
13229
14292
|
spendPathCached = cclensPath("llm-spend.jsonl");
|
|
13230
14293
|
return spendPathCached;
|
|
13231
14294
|
}
|
|
13232
|
-
function __setSpendPathForTest(
|
|
13233
|
-
spendPathCached =
|
|
14295
|
+
function __setSpendPathForTest(path9) {
|
|
14296
|
+
spendPathCached = path9;
|
|
13234
14297
|
}
|
|
13235
14298
|
function appendSpend(record) {
|
|
13236
14299
|
const p = spendPath();
|
|
@@ -13239,12 +14302,12 @@ function appendSpend(record) {
|
|
|
13239
14302
|
}
|
|
13240
14303
|
function monthToDateSpend(now = /* @__PURE__ */ new Date()) {
|
|
13241
14304
|
const p = spendPath();
|
|
13242
|
-
if (!
|
|
14305
|
+
if (!existsSync13(p))
|
|
13243
14306
|
return 0;
|
|
13244
14307
|
const year = now.getUTCFullYear();
|
|
13245
14308
|
const month2 = now.getUTCMonth();
|
|
13246
14309
|
let total = 0;
|
|
13247
|
-
const raw =
|
|
14310
|
+
const raw = readFileSync15(p, "utf8");
|
|
13248
14311
|
for (const line of raw.split("\n")) {
|
|
13249
14312
|
if (!line)
|
|
13250
14313
|
continue;
|
|
@@ -13273,15 +14336,15 @@ var init_budget = __esm({
|
|
|
13273
14336
|
});
|
|
13274
14337
|
|
|
13275
14338
|
// ../entries/dist/pipeline-lock.js
|
|
13276
|
-
import { writeFileSync as writeFileSync10, unlinkSync as unlinkSync4, existsSync as
|
|
14339
|
+
import { writeFileSync as writeFileSync10, unlinkSync as unlinkSync4, existsSync as existsSync14, readFileSync as readFileSync16, statSync as statSync3 } from "node:fs";
|
|
13277
14340
|
function lockPath() {
|
|
13278
14341
|
if (lockPathCached)
|
|
13279
14342
|
return lockPathCached;
|
|
13280
14343
|
lockPathCached = cclensPath("llm-interactive.lock");
|
|
13281
14344
|
return lockPathCached;
|
|
13282
14345
|
}
|
|
13283
|
-
function __setInteractiveLockPathForTest(
|
|
13284
|
-
lockPathCached =
|
|
14346
|
+
function __setInteractiveLockPathForTest(path9) {
|
|
14347
|
+
lockPathCached = path9;
|
|
13285
14348
|
}
|
|
13286
14349
|
function touchLock() {
|
|
13287
14350
|
writeFileSync10(lockPath(), String(process.pid), "utf8");
|
|
@@ -13318,13 +14381,13 @@ function pidAlive(pid) {
|
|
|
13318
14381
|
}
|
|
13319
14382
|
function interactiveLockFresh(nowMs) {
|
|
13320
14383
|
const p = lockPath();
|
|
13321
|
-
if (!
|
|
14384
|
+
if (!existsSync14(p))
|
|
13322
14385
|
return false;
|
|
13323
14386
|
try {
|
|
13324
14387
|
const mtime = statSync3(p).mtimeMs;
|
|
13325
14388
|
if (nowMs - mtime > STALE_MS)
|
|
13326
14389
|
return false;
|
|
13327
|
-
const pid = Number(
|
|
14390
|
+
const pid = Number(readFileSync16(p, "utf8").trim());
|
|
13328
14391
|
if (!Number.isFinite(pid) || pid <= 0)
|
|
13329
14392
|
return false;
|
|
13330
14393
|
if (!pidAlive(pid))
|
|
@@ -13430,7 +14493,7 @@ var init_queue = __esm({
|
|
|
13430
14493
|
});
|
|
13431
14494
|
|
|
13432
14495
|
// ../entries/dist/settings.js
|
|
13433
|
-
import { readFileSync as
|
|
14496
|
+
import { readFileSync as readFileSync17, writeFileSync as writeFileSync11, renameSync as renameSync5, chmodSync as chmodSync2, mkdirSync as mkdirSync11, existsSync as existsSync15 } from "node:fs";
|
|
13434
14497
|
import { dirname as dirname10 } from "node:path";
|
|
13435
14498
|
function settingsPath() {
|
|
13436
14499
|
if (settingsPathCached)
|
|
@@ -13438,8 +14501,8 @@ function settingsPath() {
|
|
|
13438
14501
|
settingsPathCached = cclensPath("settings.json");
|
|
13439
14502
|
return settingsPathCached;
|
|
13440
14503
|
}
|
|
13441
|
-
function __setSettingsPathForTest(
|
|
13442
|
-
settingsPathCached =
|
|
14504
|
+
function __setSettingsPathForTest(path9) {
|
|
14505
|
+
settingsPathCached = path9;
|
|
13443
14506
|
}
|
|
13444
14507
|
function toDisk(s) {
|
|
13445
14508
|
return {
|
|
@@ -13466,10 +14529,10 @@ function fromDisk(d) {
|
|
|
13466
14529
|
}
|
|
13467
14530
|
function readSettings() {
|
|
13468
14531
|
const p = settingsPath();
|
|
13469
|
-
if (!
|
|
14532
|
+
if (!existsSync15(p))
|
|
13470
14533
|
return DEFAULT_SETTINGS;
|
|
13471
14534
|
try {
|
|
13472
|
-
const raw =
|
|
14535
|
+
const raw = readFileSync17(p, "utf8");
|
|
13473
14536
|
return fromDisk(JSON.parse(raw));
|
|
13474
14537
|
} catch {
|
|
13475
14538
|
return DEFAULT_SETTINGS;
|
|
@@ -13676,7 +14739,7 @@ function rollupOutcomeDay(entries2) {
|
|
|
13676
14739
|
return "exploratory";
|
|
13677
14740
|
return "trivial";
|
|
13678
14741
|
}
|
|
13679
|
-
function
|
|
14742
|
+
function truncate6(s, max) {
|
|
13680
14743
|
if (s.length <= max)
|
|
13681
14744
|
return s;
|
|
13682
14745
|
return s.slice(0, max - 1).trimEnd() + "\u2026";
|
|
@@ -13732,7 +14795,7 @@ function computeDaySignals(entries2) {
|
|
|
13732
14795
|
type,
|
|
13733
14796
|
count: v.count,
|
|
13734
14797
|
sample_description: v.sample_description,
|
|
13735
|
-
sample_prompt_preview:
|
|
14798
|
+
sample_prompt_preview: truncate6(v.sample_prompt_preview, 200)
|
|
13736
14799
|
}));
|
|
13737
14800
|
const frameCounts = /* @__PURE__ */ new Map();
|
|
13738
14801
|
for (const s of signalsList) {
|
|
@@ -13751,7 +14814,7 @@ function computeDaySignals(entries2) {
|
|
|
13751
14814
|
if ((e.first_user ?? "").length > 0)
|
|
13752
14815
|
verbosity_distribution[s.verbosity] += 1;
|
|
13753
14816
|
for (const ref of s.external_refs) {
|
|
13754
|
-
external_refs.push({ session_id: e.session_id, kind: ref.kind, preview:
|
|
14817
|
+
external_refs.push({ session_id: e.session_id, kind: ref.kind, preview: truncate6(ref.preview, 200) });
|
|
13755
14818
|
}
|
|
13756
14819
|
const ints = e.numbers.interrupts ?? 0;
|
|
13757
14820
|
interrupts += ints;
|
|
@@ -14624,7 +15687,7 @@ function computeInteractionModes(entries2) {
|
|
|
14624
15687
|
date: entry.local_day,
|
|
14625
15688
|
project_display: prettyProject3(entry.project),
|
|
14626
15689
|
type: sa.type,
|
|
14627
|
-
prompt_preview:
|
|
15690
|
+
prompt_preview: truncate7(sa.prompt_preview, 200)
|
|
14628
15691
|
});
|
|
14629
15692
|
}
|
|
14630
15693
|
const skillExamples = [];
|
|
@@ -14641,7 +15704,7 @@ function computeInteractionModes(entries2) {
|
|
|
14641
15704
|
skillExamples.push({
|
|
14642
15705
|
date: e.local_day,
|
|
14643
15706
|
skill,
|
|
14644
|
-
first_user_preview:
|
|
15707
|
+
first_user_preview: truncate7(e.first_user, 200)
|
|
14645
15708
|
});
|
|
14646
15709
|
}
|
|
14647
15710
|
}
|
|
@@ -14658,7 +15721,7 @@ function computeInteractionModes(entries2) {
|
|
|
14658
15721
|
project_display: prettyProject3(longestTurnEntry.project),
|
|
14659
15722
|
active_min: longestTurnEntry.numbers.active_min,
|
|
14660
15723
|
top_tools: longestTurnEntry.top_tools.slice(0, 5),
|
|
14661
|
-
first_user_preview:
|
|
15724
|
+
first_user_preview: truncate7(longestTurnEntry.first_user, 200)
|
|
14662
15725
|
} : null;
|
|
14663
15726
|
const tools_per_turn = turn_count > 0 ? tools_total / turn_count : 0;
|
|
14664
15727
|
const label = tools_per_turn < 5 ? "rapid" : tools_per_turn < 15 ? "mixed" : "batch";
|
|
@@ -14689,7 +15752,7 @@ function computeInteractionModes(entries2) {
|
|
|
14689
15752
|
}
|
|
14690
15753
|
};
|
|
14691
15754
|
}
|
|
14692
|
-
function
|
|
15755
|
+
function truncate7(s, max) {
|
|
14693
15756
|
if (s.length <= max)
|
|
14694
15757
|
return s;
|
|
14695
15758
|
return s.slice(0, max - 1).trimEnd() + "\u2026";
|
|
@@ -14736,7 +15799,7 @@ function computeWorkingShapes(dayDigests, entriesByDay = /* @__PURE__ */ new Map
|
|
|
14736
15799
|
evidence_subagent = {
|
|
14737
15800
|
type: sa.type,
|
|
14738
15801
|
description: sa.description,
|
|
14739
|
-
prompt_preview:
|
|
15802
|
+
prompt_preview: truncate7(sa.prompt_preview, 200)
|
|
14740
15803
|
};
|
|
14741
15804
|
}
|
|
14742
15805
|
const project_display = repEntry ? prettyProject3(repEntry.project) : dd.projects[0]?.display_name ?? "";
|
|
@@ -14747,7 +15810,7 @@ function computeWorkingShapes(dayDigests, entriesByDay = /* @__PURE__ */ new Map
|
|
|
14747
15810
|
outcome: dayOutcome.get(dd.key) ?? null,
|
|
14748
15811
|
helpfulness: dayHelp.get(dd.key) ?? null,
|
|
14749
15812
|
evidence_subagent,
|
|
14750
|
-
evidence_first_user: repEntry?.first_user ?
|
|
15813
|
+
evidence_first_user: repEntry?.first_user ? truncate7(repEntry.first_user, 200) : null,
|
|
14751
15814
|
day_signature: dd.day_signature ?? null
|
|
14752
15815
|
};
|
|
14753
15816
|
});
|
|
@@ -14822,7 +15885,7 @@ function computeInteractionGrammar(dayDigests, entriesByDay = /* @__PURE__ */ ne
|
|
|
14822
15885
|
date: day2,
|
|
14823
15886
|
session_id: ref.session_id,
|
|
14824
15887
|
ref_kind: ref.kind,
|
|
14825
|
-
preview:
|
|
15888
|
+
preview: truncate7(ref.preview, 200)
|
|
14826
15889
|
});
|
|
14827
15890
|
}
|
|
14828
15891
|
total_interrupts += signals.comm_style.steering.interrupts;
|
|
@@ -14894,7 +15957,7 @@ function computeInteractionGrammar(dayDigests, entriesByDay = /* @__PURE__ */ ne
|
|
|
14894
15957
|
count: v.count,
|
|
14895
15958
|
days: [...v.days].sort(),
|
|
14896
15959
|
sample_description: v.sample_description,
|
|
14897
|
-
sample_prompt_preview:
|
|
15960
|
+
sample_prompt_preview: truncate7(v.sample_prompt_preview, 200)
|
|
14898
15961
|
})),
|
|
14899
15962
|
threads,
|
|
14900
15963
|
communication_style: {
|
|
@@ -15542,7 +16605,7 @@ function activeMs(timestamps) {
|
|
|
15542
16605
|
let active = 0;
|
|
15543
16606
|
for (let i = 1; i < ts.length; i++) {
|
|
15544
16607
|
const dt = ts[i] - ts[i - 1];
|
|
15545
|
-
if (dt <
|
|
16608
|
+
if (dt < IDLE_GAP_MS6)
|
|
15546
16609
|
active += dt;
|
|
15547
16610
|
}
|
|
15548
16611
|
return active;
|
|
@@ -15713,7 +16776,7 @@ function buildSessionSlice(entry, events, daySignature) {
|
|
|
15713
16776
|
let intEnd = sortedTs[0];
|
|
15714
16777
|
for (let i = 1; i < sortedTs.length; i++) {
|
|
15715
16778
|
const dt = sortedTs[i] - intEnd;
|
|
15716
|
-
if (dt >=
|
|
16779
|
+
if (dt >= IDLE_GAP_MS6) {
|
|
15717
16780
|
intervals.push({
|
|
15718
16781
|
start_min: fmtMin(intStart - sliceStartMs),
|
|
15719
16782
|
end_min: fmtMin(intEnd - sliceStartMs)
|
|
@@ -16110,14 +17173,14 @@ async function generateTopSession(slice, opts = {}) {
|
|
|
16110
17173
|
void lastModel;
|
|
16111
17174
|
}
|
|
16112
17175
|
}
|
|
16113
|
-
var
|
|
17176
|
+
var IDLE_GAP_MS6, LONG_AUTONOMOUS_MIN, N_USER, N_FIRST_AGENT, N_LAST_AGENT, N_USER_TURN1, N_SUBAGENT, SHELL_NOISE2, INTERRUPT_RE3, PR_TITLE_RE2, PinResponseSchema, TopSessionResponseSchema, SYSTEM_PROMPT5, TOP_SESSION_SYSTEM_PROMPT, DEFAULT_MODEL5, defaultCallLLMTopSession, validateTopSession;
|
|
16114
17177
|
var init_top_sessions = __esm({
|
|
16115
17178
|
"../entries/dist/top-sessions.js"() {
|
|
16116
17179
|
"use strict";
|
|
16117
17180
|
init_zod();
|
|
16118
17181
|
init_signals();
|
|
16119
17182
|
init_llm_runner();
|
|
16120
|
-
|
|
17183
|
+
IDLE_GAP_MS6 = 3 * 60 * 1e3;
|
|
16121
17184
|
LONG_AUTONOMOUS_MIN = 20;
|
|
16122
17185
|
N_USER = 150;
|
|
16123
17186
|
N_FIRST_AGENT = 150;
|
|
@@ -16659,7 +17722,7 @@ var init_digest_month_pipeline = __esm({
|
|
|
16659
17722
|
});
|
|
16660
17723
|
|
|
16661
17724
|
// ../entries/dist/credentials.js
|
|
16662
|
-
import { writeFileSync as writeFileSync12, readFileSync as
|
|
17725
|
+
import { writeFileSync as writeFileSync12, readFileSync as readFileSync18, renameSync as renameSync6, chmodSync as chmodSync3, mkdirSync as mkdirSync12, existsSync as existsSync16, unlinkSync as unlinkSync5 } from "node:fs";
|
|
16663
17726
|
import { dirname as dirname11 } from "node:path";
|
|
16664
17727
|
async function fetchZaiUsage(candidate) {
|
|
16665
17728
|
const key = candidate.trim();
|
|
@@ -16730,10 +17793,10 @@ function credentialsPath() {
|
|
|
16730
17793
|
}
|
|
16731
17794
|
function readCredentials() {
|
|
16732
17795
|
const p = credentialsPath();
|
|
16733
|
-
if (!
|
|
17796
|
+
if (!existsSync16(p))
|
|
16734
17797
|
return {};
|
|
16735
17798
|
try {
|
|
16736
|
-
const raw =
|
|
17799
|
+
const raw = readFileSync18(p, "utf8");
|
|
16737
17800
|
return JSON.parse(raw);
|
|
16738
17801
|
} catch {
|
|
16739
17802
|
return {};
|
|
@@ -17363,7 +18426,7 @@ var menubar_exports = {};
|
|
|
17363
18426
|
__export(menubar_exports, {
|
|
17364
18427
|
menubar: () => menubar
|
|
17365
18428
|
});
|
|
17366
|
-
import { existsSync as
|
|
18429
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync13, cpSync, rmSync as rmSync2, readdirSync as readdirSync4, writeFileSync as writeFileSync13, realpathSync as realpathSync6 } from "node:fs";
|
|
17367
18430
|
import { homedir as homedir6 } from "node:os";
|
|
17368
18431
|
import { join as join12, dirname as dirname12 } from "node:path";
|
|
17369
18432
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
@@ -17405,8 +18468,8 @@ async function isRunning() {
|
|
|
17405
18468
|
return false;
|
|
17406
18469
|
}
|
|
17407
18470
|
}
|
|
17408
|
-
async function launchApp(
|
|
17409
|
-
await execFileAsync2("open", ["-a",
|
|
18471
|
+
async function launchApp(path9) {
|
|
18472
|
+
await execFileAsync2("open", ["-a", path9]);
|
|
17410
18473
|
}
|
|
17411
18474
|
async function quitApp() {
|
|
17412
18475
|
await execFileAsync2("osascript", ["-e", `tell application "${BUNDLE_EXEC}" to quit`]).catch(
|
|
@@ -17427,7 +18490,7 @@ async function installMenubar(opts) {
|
|
|
17427
18490
|
return;
|
|
17428
18491
|
}
|
|
17429
18492
|
const src = bundledAppPath();
|
|
17430
|
-
if (!
|
|
18493
|
+
if (!existsSync17(src)) {
|
|
17431
18494
|
console.error(
|
|
17432
18495
|
`Bundled widget not found at ${src}.
|
|
17433
18496
|
This install was probably built without the menubar artifact. Run \`node apps/menubar/build-app.sh && cp -R apps/menubar/dist/FleetlensMenubar.app packages/cli/menubar/\` and rebuild.`
|
|
@@ -17469,7 +18532,7 @@ async function uninstallMenubar() {
|
|
|
17469
18532
|
await new Promise((r) => setTimeout(r, 300));
|
|
17470
18533
|
}
|
|
17471
18534
|
const dest = installedAppPath();
|
|
17472
|
-
if (
|
|
18535
|
+
if (existsSync17(dest)) {
|
|
17473
18536
|
rmSync2(dest, { recursive: true, force: true });
|
|
17474
18537
|
console.log(`Removed ${dest}`);
|
|
17475
18538
|
} else {
|
|
@@ -17483,7 +18546,7 @@ async function openMenubar() {
|
|
|
17483
18546
|
return;
|
|
17484
18547
|
}
|
|
17485
18548
|
const dest = installedAppPath();
|
|
17486
|
-
if (!
|
|
18549
|
+
if (!existsSync17(dest)) {
|
|
17487
18550
|
console.log("Widget not installed yet. Run `fleetlens menubar install` first.");
|
|
17488
18551
|
return;
|
|
17489
18552
|
}
|
|
@@ -17500,9 +18563,9 @@ async function statusMenubar() {
|
|
|
17500
18563
|
return;
|
|
17501
18564
|
}
|
|
17502
18565
|
const dest = installedAppPath();
|
|
17503
|
-
const installed =
|
|
18566
|
+
const installed = existsSync17(dest);
|
|
17504
18567
|
const running = await isRunning();
|
|
17505
|
-
const bundled =
|
|
18568
|
+
const bundled = existsSync17(bundledAppPath());
|
|
17506
18569
|
console.log(`Menu bar widget: ${installed ? "installed" : "not installed"}${installed ? ` (${dest})` : ""}`);
|
|
17507
18570
|
console.log(`Running: ${running ? "yes" : "no"}`);
|
|
17508
18571
|
console.log(`Bundled in CLI: ${bundled ? "yes" : "no \u2014 this build ships without the widget"}`);
|
|
@@ -17591,7 +18654,7 @@ var init_config = __esm({
|
|
|
17591
18654
|
});
|
|
17592
18655
|
|
|
17593
18656
|
// src/perception/build-entries.ts
|
|
17594
|
-
import { statSync as statSync4, readFileSync as
|
|
18657
|
+
import { statSync as statSync4, readFileSync as readFileSync19 } from "node:fs";
|
|
17595
18658
|
import { basename as basename2, dirname as dirname13 } from "node:path";
|
|
17596
18659
|
function decodeProjectDirName(projectDir) {
|
|
17597
18660
|
if (projectDir.startsWith("-")) {
|
|
@@ -17601,7 +18664,7 @@ function decodeProjectDirName(projectDir) {
|
|
|
17601
18664
|
}
|
|
17602
18665
|
function buildEntriesForFile(filePath) {
|
|
17603
18666
|
const stat = statSync4(filePath);
|
|
17604
|
-
const raw =
|
|
18667
|
+
const raw = readFileSync19(filePath, "utf8");
|
|
17605
18668
|
const rawLines = raw.split("\n").filter(Boolean).map((l) => {
|
|
17606
18669
|
try {
|
|
17607
18670
|
return JSON.parse(l);
|
|
@@ -17866,7 +18929,7 @@ function buildIngestPayload(inputs) {
|
|
|
17866
18929
|
return {
|
|
17867
18930
|
ingestId: randomUUID2(),
|
|
17868
18931
|
observedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
17869
|
-
cliVersion: "0.16.
|
|
18932
|
+
cliVersion: "0.16.2",
|
|
17870
18933
|
...richRollup || inputs.enrichedExtras || inputs.artifactSignals ? { schemaVersion: RICH_ROLLUP_SCHEMA_VERSION } : {},
|
|
17871
18934
|
...inputs.rollup ? { dailyRollup: inputs.rollup } : {},
|
|
17872
18935
|
...richRollup ? { richRollup } : {},
|
|
@@ -17907,7 +18970,7 @@ var init_push = __esm({
|
|
|
17907
18970
|
});
|
|
17908
18971
|
|
|
17909
18972
|
// src/team/git-remote.ts
|
|
17910
|
-
import { existsSync as
|
|
18973
|
+
import { existsSync as existsSync18, readFileSync as readFileSync20, statSync as statSync5 } from "node:fs";
|
|
17911
18974
|
import { dirname as dirname14, isAbsolute as isAbsolute2, join as join13, resolve as resolve2 } from "node:path";
|
|
17912
18975
|
function parseGithubRemote(url) {
|
|
17913
18976
|
const m = url.trim().match(GITHUB_URL_RE);
|
|
@@ -17932,12 +18995,12 @@ function gitConfigPathFor(dir) {
|
|
|
17932
18995
|
const st = statSync5(dotGit, { throwIfNoEntry: false });
|
|
17933
18996
|
if (!st) return null;
|
|
17934
18997
|
if (st.isDirectory()) return join13(dotGit, "config");
|
|
17935
|
-
const m =
|
|
18998
|
+
const m = readFileSync20(dotGit, "utf8").match(/^gitdir:\s*(.+)\s*$/m);
|
|
17936
18999
|
if (!m) return null;
|
|
17937
19000
|
const gd = isAbsolute2(m[1]) ? m[1] : resolve2(dir, m[1]);
|
|
17938
19001
|
const commondirFile = join13(gd, "commondir");
|
|
17939
|
-
if (
|
|
17940
|
-
const common =
|
|
19002
|
+
if (existsSync18(commondirFile)) {
|
|
19003
|
+
const common = readFileSync20(commondirFile, "utf8").trim();
|
|
17941
19004
|
return join13(isAbsolute2(common) ? common : resolve2(gd, common), "config");
|
|
17942
19005
|
}
|
|
17943
19006
|
return join13(gd, "config");
|
|
@@ -17952,8 +19015,8 @@ function createRepoResolver() {
|
|
|
17952
19015
|
try {
|
|
17953
19016
|
for (let d = dir; ; d = dirname14(d)) {
|
|
17954
19017
|
const config = gitConfigPathFor(d);
|
|
17955
|
-
if (config &&
|
|
17956
|
-
const url = originUrl2(
|
|
19018
|
+
if (config && existsSync18(config)) {
|
|
19019
|
+
const url = originUrl2(readFileSync20(config, "utf8"));
|
|
17957
19020
|
repo = url ? parseGithubRemote(url) : null;
|
|
17958
19021
|
break;
|
|
17959
19022
|
}
|
|
@@ -17975,7 +19038,7 @@ var init_git_remote = __esm({
|
|
|
17975
19038
|
});
|
|
17976
19039
|
|
|
17977
19040
|
// src/team/queue.ts
|
|
17978
|
-
import { readFileSync as
|
|
19041
|
+
import { readFileSync as readFileSync21, writeFileSync as writeFileSync14, appendFileSync as appendFileSync5, statSync as statSync6, mkdirSync as mkdirSync14 } from "node:fs";
|
|
17979
19042
|
import { dirname as dirname15 } from "node:path";
|
|
17980
19043
|
function enqueuePayload(payload, queuePath = QUEUE_PATH) {
|
|
17981
19044
|
mkdirSync14(dirname15(queuePath), { recursive: true });
|
|
@@ -17992,7 +19055,7 @@ function enqueuePayload(payload, queuePath = QUEUE_PATH) {
|
|
|
17992
19055
|
function dequeuePayloads(queuePath = QUEUE_PATH) {
|
|
17993
19056
|
let lines;
|
|
17994
19057
|
try {
|
|
17995
|
-
lines =
|
|
19058
|
+
lines = readFileSync21(queuePath, "utf8").trim().split("\n").filter(Boolean);
|
|
17996
19059
|
} catch {
|
|
17997
19060
|
return [];
|
|
17998
19061
|
}
|
|
@@ -18013,7 +19076,7 @@ function dequeuePayloads(queuePath = QUEUE_PATH) {
|
|
|
18013
19076
|
function pruneOldest(queuePath) {
|
|
18014
19077
|
let lines;
|
|
18015
19078
|
try {
|
|
18016
|
-
lines =
|
|
19079
|
+
lines = readFileSync21(queuePath, "utf8").trim().split("\n").filter(Boolean);
|
|
18017
19080
|
} catch {
|
|
18018
19081
|
return;
|
|
18019
19082
|
}
|
|
@@ -18032,7 +19095,7 @@ var init_queue2 = __esm({
|
|
|
18032
19095
|
});
|
|
18033
19096
|
|
|
18034
19097
|
// src/usage/profile.ts
|
|
18035
|
-
import { existsSync as
|
|
19098
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync15, readFileSync as readFileSync22, writeFileSync as writeFileSync15 } from "node:fs";
|
|
18036
19099
|
import { dirname as dirname16 } from "node:path";
|
|
18037
19100
|
function mapRateLimitTier(rateLimitTier) {
|
|
18038
19101
|
switch (rateLimitTier) {
|
|
@@ -18073,9 +19136,9 @@ async function fetchProfile(nowMs = Date.now()) {
|
|
|
18073
19136
|
};
|
|
18074
19137
|
}
|
|
18075
19138
|
function readCachedProfile(cachePath) {
|
|
18076
|
-
if (!
|
|
19139
|
+
if (!existsSync19(cachePath)) return null;
|
|
18077
19140
|
try {
|
|
18078
|
-
const raw = JSON.parse(
|
|
19141
|
+
const raw = JSON.parse(readFileSync22(cachePath, "utf8"));
|
|
18079
19142
|
if (typeof raw.fetchedAtMs !== "number" || !raw.profile) return null;
|
|
18080
19143
|
return raw;
|
|
18081
19144
|
} catch {
|
|
@@ -18264,11 +19327,11 @@ var init_backfill = __esm({
|
|
|
18264
19327
|
});
|
|
18265
19328
|
|
|
18266
19329
|
// src/team/sync-log.ts
|
|
18267
|
-
import { readFileSync as
|
|
19330
|
+
import { readFileSync as readFileSync23 } from "node:fs";
|
|
18268
19331
|
function readPendingSyncLog(watermark) {
|
|
18269
19332
|
let raw;
|
|
18270
19333
|
try {
|
|
18271
|
-
raw =
|
|
19334
|
+
raw = readFileSync23(cclensPath("daemon.log"), "utf8");
|
|
18272
19335
|
} catch {
|
|
18273
19336
|
return { lines: [] };
|
|
18274
19337
|
}
|
|
@@ -18332,7 +19395,7 @@ __export(file_probe_exports, {
|
|
|
18332
19395
|
probeArtifactSignals: () => probeArtifactSignals
|
|
18333
19396
|
});
|
|
18334
19397
|
import { createHash } from "node:crypto";
|
|
18335
|
-
import { existsSync as
|
|
19398
|
+
import { existsSync as existsSync20, readdirSync as readdirSync5, statSync as statSync7 } from "node:fs";
|
|
18336
19399
|
import { homedir as homedir7 } from "node:os";
|
|
18337
19400
|
import { join as join15, relative, resolve as resolve3, sep } from "node:path";
|
|
18338
19401
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
@@ -18342,15 +19405,15 @@ function pathHash(relPath) {
|
|
|
18342
19405
|
function defaultScanRoots(extraRoots = []) {
|
|
18343
19406
|
const roots = [];
|
|
18344
19407
|
const home = join15(homedir7(), ".claude");
|
|
18345
|
-
if (
|
|
19408
|
+
if (existsSync20(home)) roots.push({ root: home, label: "user" });
|
|
18346
19409
|
for (const e of extraRoots) {
|
|
18347
19410
|
const r = resolve3(e, ".claude");
|
|
18348
|
-
if (
|
|
19411
|
+
if (existsSync20(r) && r !== home) roots.push({ root: r, label: "project" });
|
|
18349
19412
|
}
|
|
18350
19413
|
return roots;
|
|
18351
19414
|
}
|
|
18352
19415
|
function listMarkdownFiles(dir) {
|
|
18353
|
-
if (!
|
|
19416
|
+
if (!existsSync20(dir)) return [];
|
|
18354
19417
|
const out = [];
|
|
18355
19418
|
let entries2;
|
|
18356
19419
|
try {
|
|
@@ -18420,7 +19483,7 @@ function scanAuthored(roots, subdir, day2) {
|
|
|
18420
19483
|
const out = [];
|
|
18421
19484
|
for (const r of roots) {
|
|
18422
19485
|
const dir = join15(r.root, subdir);
|
|
18423
|
-
if (!
|
|
19486
|
+
if (!existsSync20(dir)) continue;
|
|
18424
19487
|
for (const f of listMarkdownFiles(dir)) {
|
|
18425
19488
|
const firstSeen = firstSeenDateOf(f);
|
|
18426
19489
|
if (firstSeen !== day2) continue;
|
|
@@ -18434,7 +19497,7 @@ function scanEdited(roots, day2) {
|
|
|
18434
19497
|
const out = [];
|
|
18435
19498
|
for (const r of roots) {
|
|
18436
19499
|
const dir = join15(r.root, "skills");
|
|
18437
|
-
if (!
|
|
19500
|
+
if (!existsSync20(dir)) continue;
|
|
18438
19501
|
for (const f of listMarkdownFiles(dir)) {
|
|
18439
19502
|
const firstSeen = firstSeenDateOf(f);
|
|
18440
19503
|
if (firstSeen === day2) continue;
|
|
@@ -18457,10 +19520,10 @@ function claudemdLineDelta(extraRoots, authorEmail, day2) {
|
|
|
18457
19520
|
const candidates = [];
|
|
18458
19521
|
for (const e of extraRoots) {
|
|
18459
19522
|
const f = resolve3(e, "CLAUDE.md");
|
|
18460
|
-
if (
|
|
19523
|
+
if (existsSync20(f)) candidates.push(f);
|
|
18461
19524
|
}
|
|
18462
19525
|
const homeClaudeMd = join15(homedir7(), "CLAUDE.md");
|
|
18463
|
-
if (
|
|
19526
|
+
if (existsSync20(homeClaudeMd)) candidates.push(homeClaudeMd);
|
|
18464
19527
|
for (const file of candidates) {
|
|
18465
19528
|
try {
|
|
18466
19529
|
const out = execFileSync3(
|
|
@@ -19350,11 +20413,11 @@ var logs_exports = {};
|
|
|
19350
20413
|
__export(logs_exports, {
|
|
19351
20414
|
teamLogs: () => teamLogs
|
|
19352
20415
|
});
|
|
19353
|
-
import { readFileSync as
|
|
20416
|
+
import { readFileSync as readFileSync24 } from "node:fs";
|
|
19354
20417
|
async function teamLogs() {
|
|
19355
20418
|
const logPath = cclensPath("daemon.log");
|
|
19356
20419
|
try {
|
|
19357
|
-
const lines =
|
|
20420
|
+
const lines = readFileSync24(logPath, "utf8").trim().split("\n");
|
|
19358
20421
|
const teamLines = lines.filter((l) => l.includes("[sync] ") || l.includes("team "));
|
|
19359
20422
|
if (teamLines.length === 0) {
|
|
19360
20423
|
console.log("No team-related log entries found.");
|
|
@@ -19482,7 +20545,7 @@ __export(runs_exports, {
|
|
|
19482
20545
|
runs: () => runs
|
|
19483
20546
|
});
|
|
19484
20547
|
import { execSync as execSync2 } from "node:child_process";
|
|
19485
|
-
import { existsSync as
|
|
20548
|
+
import { existsSync as existsSync21, readFileSync as readFileSync25, readdirSync as readdirSync6, statSync as statSync8 } from "node:fs";
|
|
19486
20549
|
import { join as join16 } from "node:path";
|
|
19487
20550
|
async function runs(args2) {
|
|
19488
20551
|
const json = args2.includes("--json");
|
|
@@ -19567,8 +20630,8 @@ function listActiveRuns() {
|
|
|
19567
20630
|
return runs2.sort((a, b) => a.elapsed_s - b.elapsed_s);
|
|
19568
20631
|
}
|
|
19569
20632
|
function readSpend(sinceMs) {
|
|
19570
|
-
if (!
|
|
19571
|
-
const lines =
|
|
20633
|
+
if (!existsSync21(SPEND_PATH)) return [];
|
|
20634
|
+
const lines = readFileSync25(SPEND_PATH, "utf-8").split("\n").filter((l) => l.trim());
|
|
19572
20635
|
const out = [];
|
|
19573
20636
|
for (const line of lines) {
|
|
19574
20637
|
try {
|
|
@@ -19689,23 +20752,23 @@ function ageLabel(ms) {
|
|
|
19689
20752
|
return `${Math.floor(ms / 864e5)}d`;
|
|
19690
20753
|
}
|
|
19691
20754
|
function listTraceFiles() {
|
|
19692
|
-
if (!
|
|
20755
|
+
if (!existsSync21(RUNS_DIR2)) return [];
|
|
19693
20756
|
const entries2 = readdirSync6(RUNS_DIR2).filter((f) => f.endsWith(".jsonl"));
|
|
19694
20757
|
return entries2.map((f) => {
|
|
19695
|
-
const
|
|
19696
|
-
const st = statSync8(
|
|
19697
|
-
return { runId: f.replace(/\.jsonl$/, ""), path:
|
|
20758
|
+
const path9 = join16(RUNS_DIR2, f);
|
|
20759
|
+
const st = statSync8(path9);
|
|
20760
|
+
return { runId: f.replace(/\.jsonl$/, ""), path: path9, mtimeMs: st.mtimeMs };
|
|
19698
20761
|
}).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
19699
20762
|
}
|
|
19700
20763
|
function resolveRunId(arg) {
|
|
19701
|
-
if (!
|
|
20764
|
+
if (!existsSync21(RUNS_DIR2)) return null;
|
|
19702
20765
|
if (arg === "latest") {
|
|
19703
20766
|
const all2 = listTraceFiles();
|
|
19704
20767
|
if (all2.length === 0) return null;
|
|
19705
20768
|
return { runId: all2[0].runId, path: all2[0].path };
|
|
19706
20769
|
}
|
|
19707
20770
|
const exact = join16(RUNS_DIR2, `${arg}.jsonl`);
|
|
19708
|
-
if (
|
|
20771
|
+
if (existsSync21(exact)) return { runId: arg, path: exact };
|
|
19709
20772
|
const all = listTraceFiles();
|
|
19710
20773
|
const matches = all.filter((r) => r.runId.includes(arg));
|
|
19711
20774
|
if (matches.length === 1) return { runId: matches[0].runId, path: matches[0].path };
|
|
@@ -19716,8 +20779,8 @@ function resolveRunId(arg) {
|
|
|
19716
20779
|
}
|
|
19717
20780
|
return null;
|
|
19718
20781
|
}
|
|
19719
|
-
function readTrace(
|
|
19720
|
-
return
|
|
20782
|
+
function readTrace(path9) {
|
|
20783
|
+
return readFileSync25(path9, "utf-8").split("\n").filter((l) => l.trim()).map((l) => {
|
|
19721
20784
|
try {
|
|
19722
20785
|
return JSON.parse(l);
|
|
19723
20786
|
} catch {
|
|
@@ -19729,7 +20792,7 @@ async function inspect(arg, follow, json) {
|
|
|
19729
20792
|
const r = resolveRunId(arg);
|
|
19730
20793
|
if (!r) {
|
|
19731
20794
|
console.error(`run not found: ${arg}`);
|
|
19732
|
-
if (
|
|
20795
|
+
if (existsSync21(RUNS_DIR2)) {
|
|
19733
20796
|
const all = listTraceFiles().slice(0, 5);
|
|
19734
20797
|
if (all.length > 0) {
|
|
19735
20798
|
console.error(`
|
|
@@ -19909,7 +20972,7 @@ async function main() {
|
|
|
19909
20972
|
case "version":
|
|
19910
20973
|
case "--version":
|
|
19911
20974
|
case "-v":
|
|
19912
|
-
console.log(`fleetlens ${"0.16.
|
|
20975
|
+
console.log(`fleetlens ${"0.16.2"}`);
|
|
19913
20976
|
break;
|
|
19914
20977
|
case "help":
|
|
19915
20978
|
case "--help":
|
|
@@ -19936,7 +20999,7 @@ Advanced:
|
|
|
19936
20999
|
start --no-daemon Start only the web server (no daemon)
|
|
19937
21000
|
daemon <start|stop|status|logs> Manage the usage daemon by itself
|
|
19938
21001
|
autostart <install|uninstall|status> Run the usage daemon at login (macOS launchd)
|
|
19939
|
-
menubar <install|uninstall|open|status> Native macOS menu bar widget (Claude/Codex/Z.ai usage)
|
|
21002
|
+
menubar <install|uninstall|open|status> Native macOS menu bar widget (Claude/Codex/Z.ai plan usage; Grok sessions on the dashboard)
|
|
19940
21003
|
|
|
19941
21004
|
Team:
|
|
19942
21005
|
team join <url> <token> Pair with a team server (browser setup)
|