fleetlens 0.16.6 → 0.16.8
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]/messages/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/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/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/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.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/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]__0-zxvif._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__01wj6p0._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0f3q8gt._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0ygwqfa._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0z0wa91._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__12s3gv9._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/_0k8yioi._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_0epqfet._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_0~aj0~u._.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/01ky0t_.38u4u.js +14 -0
- package/app/apps/web/.next/static/chunks/0d~6j~aj2vr1t.js +1 -0
- package/app/apps/web/.next/static/chunks/{0-z49mtd-zwgv.js → 0~opjw4gew2-w.js} +1 -1
- package/app/apps/web/app/settings/page.tsx +1 -1
- package/app/apps/web/app/usage/page.tsx +178 -13
- package/app/apps/web/components/menubar-install-banner.tsx +1 -1
- package/app/apps/web/components/menubar-install.tsx +1 -1
- package/app/apps/web/components/usage-chart-range.tsx +9 -3
- package/app/apps/web/components/usage-chart.tsx +9 -3
- package/app/apps/web/components/usage-charts-dashboard.tsx +10 -3
- package/app/apps/web/lib/changelog-data.generated.ts +1 -1
- package/app/apps/web/lib/format.test.ts +10 -0
- package/app/apps/web/lib/format.ts +6 -4
- package/app/apps/web/lib/usage-data.ts +11 -0
- package/app/apps/web/lib/usage-display.test.ts +79 -0
- package/app/apps/web/lib/usage-display.ts +59 -0
- package/app/apps/web/package.json +1 -1
- package/app/apps/web/tsconfig.tsbuildinfo +1 -1
- package/dist/daemon-worker.js +994 -328
- package/dist/index.js +1085 -413
- package/menubar/FleetlensMenubar.app/Contents/Info.plist +2 -2
- package/menubar/FleetlensMenubar.app/Contents/MacOS/FleetlensMenubar +0 -0
- package/package.json +1 -1
- package/app/apps/web/.next/static/chunks/0rrcj195v1nd..js +0 -1
- package/app/apps/web/.next/static/chunks/1350ox0.qybjo.js +0 -14
- /package/app/apps/web/.next/static/{8slBxbEObd72azKwDvtmy → yxbgwGc3dXx7HY0GSHJeG}/_buildManifest.js +0 -0
- /package/app/apps/web/.next/static/{8slBxbEObd72azKwDvtmy → yxbgwGc3dXx7HY0GSHJeG}/_clientMiddlewareManifest.js +0 -0
- /package/app/apps/web/.next/static/{8slBxbEObd72azKwDvtmy → yxbgwGc3dXx7HY0GSHJeG}/_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, GROK_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
|
|
678
|
+
var CLAUDE_CODE_METADATA, CODEX_METADATA, COPILOT_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";
|
|
@@ -693,6 +693,13 @@ var init_agent_metadata = __esm({
|
|
|
693
693
|
accentColor: "rgb(16, 163, 127)",
|
|
694
694
|
iconChar: "\u25C6"
|
|
695
695
|
};
|
|
696
|
+
COPILOT_METADATA = {
|
|
697
|
+
kind: "copilot",
|
|
698
|
+
displayName: "GitHub Copilot CLI",
|
|
699
|
+
shortLabel: "Copilot",
|
|
700
|
+
accentColor: "rgb(137, 87, 229)",
|
|
701
|
+
iconChar: "\u221E"
|
|
702
|
+
};
|
|
696
703
|
GEMINI_METADATA = {
|
|
697
704
|
kind: "gemini",
|
|
698
705
|
displayName: "Gemini CLI",
|
|
@@ -732,6 +739,7 @@ var init_agent_metadata = __esm({
|
|
|
732
739
|
agentMetadata = [
|
|
733
740
|
CLAUDE_CODE_METADATA,
|
|
734
741
|
CODEX_METADATA,
|
|
742
|
+
COPILOT_METADATA,
|
|
735
743
|
GEMINI_METADATA,
|
|
736
744
|
ANTIGRAVITY_METADATA,
|
|
737
745
|
COWORK_METADATA,
|
|
@@ -1593,11 +1601,11 @@ function defaultBranch(commonDir) {
|
|
|
1593
1601
|
}
|
|
1594
1602
|
return void 0;
|
|
1595
1603
|
}
|
|
1596
|
-
function readGitFolder(
|
|
1597
|
-
if (!existsSync(
|
|
1604
|
+
function readGitFolder(path11) {
|
|
1605
|
+
if (!existsSync(path11))
|
|
1598
1606
|
return { exists: false, isWorktree: false };
|
|
1599
1607
|
try {
|
|
1600
|
-
const git = nearestDotGit(realpathOrSelf(
|
|
1608
|
+
const git = nearestDotGit(realpathOrSelf(path11));
|
|
1601
1609
|
if (!git)
|
|
1602
1610
|
return { exists: true, isWorktree: false };
|
|
1603
1611
|
const projectRoot = projectRootFromCommonDir(git.commonDir);
|
|
@@ -3379,24 +3387,442 @@ var init_codex = __esm({
|
|
|
3379
3387
|
}
|
|
3380
3388
|
});
|
|
3381
3389
|
|
|
3382
|
-
// ../parser/dist/
|
|
3390
|
+
// ../parser/dist/copilot.js
|
|
3383
3391
|
import { promises as fs3 } from "node:fs";
|
|
3384
3392
|
import os3 from "node:os";
|
|
3385
3393
|
import path3 from "node:path";
|
|
3386
|
-
|
|
3387
|
-
return
|
|
3394
|
+
function recordOf(value) {
|
|
3395
|
+
return typeof value === "object" && value !== null ? value : void 0;
|
|
3396
|
+
}
|
|
3397
|
+
function stringOf(value) {
|
|
3398
|
+
return typeof value === "string" ? value : void 0;
|
|
3399
|
+
}
|
|
3400
|
+
function numberOf2(value) {
|
|
3401
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
3402
|
+
}
|
|
3403
|
+
function emptyUsage2() {
|
|
3404
|
+
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
3405
|
+
}
|
|
3406
|
+
function previewOf2(value) {
|
|
3407
|
+
const text = typeof value === "string" ? value : JSON.stringify(value ?? "");
|
|
3408
|
+
return text.replace(/\s+/g, " ").trim().slice(0, 200);
|
|
3409
|
+
}
|
|
3410
|
+
function tokenCount(details, key) {
|
|
3411
|
+
return numberOf2(recordOf(details?.[key])?.tokenCount);
|
|
3412
|
+
}
|
|
3413
|
+
function syntheticProjectDir(cwd) {
|
|
3414
|
+
return cwd ? cwd.replace(/^\//, "-").replace(/\//g, "-") : "(unknown)";
|
|
3388
3415
|
}
|
|
3389
3416
|
async function listSessionFiles(root) {
|
|
3417
|
+
const entries2 = await fs3.readdir(root, { withFileTypes: true }).catch(() => []);
|
|
3418
|
+
const out = [];
|
|
3419
|
+
for (const entry of entries2) {
|
|
3420
|
+
if (!entry.isDirectory())
|
|
3421
|
+
continue;
|
|
3422
|
+
const filePath = path3.join(root, entry.name, "events.jsonl");
|
|
3423
|
+
const stat = await fs3.stat(filePath).catch(() => null);
|
|
3424
|
+
if (!stat?.isFile())
|
|
3425
|
+
continue;
|
|
3426
|
+
out.push({
|
|
3427
|
+
filePath,
|
|
3428
|
+
sessionId: entry.name,
|
|
3429
|
+
mtimeMs: stat.mtimeMs,
|
|
3430
|
+
sizeBytes: stat.size
|
|
3431
|
+
});
|
|
3432
|
+
}
|
|
3433
|
+
return out;
|
|
3434
|
+
}
|
|
3435
|
+
async function readJsonl2(filePath) {
|
|
3436
|
+
const raw = await fs3.readFile(filePath, "utf8");
|
|
3437
|
+
const out = [];
|
|
3438
|
+
for (const line of raw.split("\n")) {
|
|
3439
|
+
const trimmed = line.trim();
|
|
3440
|
+
if (!trimmed)
|
|
3441
|
+
continue;
|
|
3442
|
+
try {
|
|
3443
|
+
out.push(JSON.parse(trimmed));
|
|
3444
|
+
} catch {
|
|
3445
|
+
}
|
|
3446
|
+
}
|
|
3447
|
+
return out;
|
|
3448
|
+
}
|
|
3449
|
+
function computeActiveSegments3(timestamps) {
|
|
3450
|
+
const sorted = [...new Set(timestamps)].sort((a, b) => a - b);
|
|
3451
|
+
if (sorted.length === 0)
|
|
3452
|
+
return [];
|
|
3453
|
+
const segments = [];
|
|
3454
|
+
let start2 = sorted[0];
|
|
3455
|
+
let end = start2;
|
|
3456
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
3457
|
+
const next = sorted[i];
|
|
3458
|
+
if (next - end > IDLE_GAP_MS2) {
|
|
3459
|
+
segments.push({ startMs: start2, endMs: end });
|
|
3460
|
+
start2 = next;
|
|
3461
|
+
}
|
|
3462
|
+
end = next;
|
|
3463
|
+
}
|
|
3464
|
+
segments.push({ startMs: start2, endMs: end });
|
|
3465
|
+
return segments;
|
|
3466
|
+
}
|
|
3467
|
+
function parseSession(file, lines) {
|
|
3468
|
+
const records = lines.map(recordOf).filter((line) => line !== void 0);
|
|
3469
|
+
const executionCallIds = /* @__PURE__ */ new Set();
|
|
3470
|
+
for (const record of records) {
|
|
3471
|
+
if (record.type !== "tool.execution_start")
|
|
3472
|
+
continue;
|
|
3473
|
+
const callId = stringOf(recordOf(record.data)?.toolCallId);
|
|
3474
|
+
if (callId)
|
|
3475
|
+
executionCallIds.add(callId);
|
|
3476
|
+
}
|
|
3477
|
+
const events = [];
|
|
3478
|
+
const timestamps = [];
|
|
3479
|
+
const totalUsage = emptyUsage2();
|
|
3480
|
+
let firstMs;
|
|
3481
|
+
let lastMs;
|
|
3482
|
+
let cwd;
|
|
3483
|
+
let repository;
|
|
3484
|
+
let gitBranch;
|
|
3485
|
+
let model;
|
|
3486
|
+
let firstUserPreview;
|
|
3487
|
+
let lastUserPreview;
|
|
3488
|
+
let lastAgentPreview;
|
|
3489
|
+
let toolCallCount = 0;
|
|
3490
|
+
let turnCount = 0;
|
|
3491
|
+
let observedOutput = 0;
|
|
3492
|
+
let sawShutdown = false;
|
|
3493
|
+
let linesAdded;
|
|
3494
|
+
let linesRemoved;
|
|
3495
|
+
let filesEdited;
|
|
3496
|
+
let idx = 0;
|
|
3497
|
+
function push(event) {
|
|
3498
|
+
events.push({ index: idx++, ...event });
|
|
3499
|
+
}
|
|
3500
|
+
for (const obj of records) {
|
|
3501
|
+
const type = stringOf(obj.type) ?? "";
|
|
3502
|
+
const data = recordOf(obj.data) ?? {};
|
|
3503
|
+
const timestamp = stringOf(obj.timestamp);
|
|
3504
|
+
if (timestamp) {
|
|
3505
|
+
const ms = Date.parse(timestamp);
|
|
3506
|
+
if (Number.isFinite(ms)) {
|
|
3507
|
+
timestamps.push(ms);
|
|
3508
|
+
firstMs = firstMs === void 0 ? ms : Math.min(firstMs, ms);
|
|
3509
|
+
lastMs = lastMs === void 0 ? ms : Math.max(lastMs, ms);
|
|
3510
|
+
}
|
|
3511
|
+
}
|
|
3512
|
+
if (type === "session.start") {
|
|
3513
|
+
const context = recordOf(data.context);
|
|
3514
|
+
cwd = stringOf(context?.cwd) ?? cwd;
|
|
3515
|
+
repository = stringOf(context?.repository) ?? repository;
|
|
3516
|
+
gitBranch = stringOf(context?.branch) ?? gitBranch;
|
|
3517
|
+
push({
|
|
3518
|
+
timestamp,
|
|
3519
|
+
role: "meta",
|
|
3520
|
+
rawType: type,
|
|
3521
|
+
preview: "Copilot session started",
|
|
3522
|
+
blocks: [],
|
|
3523
|
+
raw: obj
|
|
3524
|
+
});
|
|
3525
|
+
continue;
|
|
3526
|
+
}
|
|
3527
|
+
if (type === "session.model_change") {
|
|
3528
|
+
const selected = stringOf(data.newModel);
|
|
3529
|
+
if (selected && selected !== "auto")
|
|
3530
|
+
model = selected;
|
|
3531
|
+
} else if (type === "session.auto_mode_resolved") {
|
|
3532
|
+
model = stringOf(data.chosenModel) ?? model;
|
|
3533
|
+
} else if (type === "assistant.turn_start" || type === "assistant.message") {
|
|
3534
|
+
model = stringOf(data.model) ?? model;
|
|
3535
|
+
}
|
|
3536
|
+
if (type === "system.message") {
|
|
3537
|
+
push({
|
|
3538
|
+
timestamp,
|
|
3539
|
+
role: "system",
|
|
3540
|
+
rawType: type,
|
|
3541
|
+
preview: "Copilot system instructions",
|
|
3542
|
+
blocks: [],
|
|
3543
|
+
raw: obj
|
|
3544
|
+
});
|
|
3545
|
+
continue;
|
|
3546
|
+
}
|
|
3547
|
+
if (type === "user.message") {
|
|
3548
|
+
const text = stringOf(data.content) ?? "";
|
|
3549
|
+
const preview = previewOf2(text);
|
|
3550
|
+
if (text && !isFrameworkInjectedUserInput(text)) {
|
|
3551
|
+
firstUserPreview ??= preview;
|
|
3552
|
+
lastUserPreview = preview;
|
|
3553
|
+
turnCount += 1;
|
|
3554
|
+
}
|
|
3555
|
+
push({
|
|
3556
|
+
timestamp,
|
|
3557
|
+
role: "user",
|
|
3558
|
+
rawType: type,
|
|
3559
|
+
preview,
|
|
3560
|
+
blocks: text ? [{ type: "text", text }] : [],
|
|
3561
|
+
raw: obj
|
|
3562
|
+
});
|
|
3563
|
+
continue;
|
|
3564
|
+
}
|
|
3565
|
+
if (type === "assistant.message") {
|
|
3566
|
+
const text = stringOf(data.content) ?? "";
|
|
3567
|
+
const outputTokens = numberOf2(data.outputTokens) ?? 0;
|
|
3568
|
+
observedOutput += outputTokens;
|
|
3569
|
+
if (text) {
|
|
3570
|
+
const preview = previewOf2(text);
|
|
3571
|
+
lastAgentPreview = preview;
|
|
3572
|
+
push({
|
|
3573
|
+
timestamp,
|
|
3574
|
+
role: "agent",
|
|
3575
|
+
rawType: type,
|
|
3576
|
+
messageId: stringOf(data.messageId),
|
|
3577
|
+
preview,
|
|
3578
|
+
blocks: [{ type: "text", text }],
|
|
3579
|
+
model,
|
|
3580
|
+
raw: obj
|
|
3581
|
+
});
|
|
3582
|
+
}
|
|
3583
|
+
const requests = Array.isArray(data.toolRequests) ? data.toolRequests : [];
|
|
3584
|
+
for (const requestValue of requests) {
|
|
3585
|
+
const request = recordOf(requestValue);
|
|
3586
|
+
if (!request)
|
|
3587
|
+
continue;
|
|
3588
|
+
const callId = stringOf(request.toolCallId);
|
|
3589
|
+
if (callId && executionCallIds.has(callId))
|
|
3590
|
+
continue;
|
|
3591
|
+
const name = stringOf(request.name) ?? "(unknown)";
|
|
3592
|
+
const input = recordOf(request.arguments) ?? request.arguments ?? null;
|
|
3593
|
+
toolCallCount += 1;
|
|
3594
|
+
push({
|
|
3595
|
+
timestamp,
|
|
3596
|
+
role: "tool-call",
|
|
3597
|
+
rawType: "assistant.message/tool_request",
|
|
3598
|
+
preview: `${name}(${previewOf2(input).slice(0, 80)})`,
|
|
3599
|
+
blocks: [{ type: "tool_use", id: callId ?? `copilot-${idx}`, name, input }],
|
|
3600
|
+
toolName: name,
|
|
3601
|
+
toolUseId: callId,
|
|
3602
|
+
model,
|
|
3603
|
+
raw: obj
|
|
3604
|
+
});
|
|
3605
|
+
}
|
|
3606
|
+
continue;
|
|
3607
|
+
}
|
|
3608
|
+
if (type === "tool.execution_start") {
|
|
3609
|
+
const callId = stringOf(data.toolCallId);
|
|
3610
|
+
const name = stringOf(data.toolName) ?? "(unknown)";
|
|
3611
|
+
const input = data.arguments ?? null;
|
|
3612
|
+
toolCallCount += 1;
|
|
3613
|
+
push({
|
|
3614
|
+
timestamp,
|
|
3615
|
+
role: "tool-call",
|
|
3616
|
+
rawType: type,
|
|
3617
|
+
preview: `${name}(${previewOf2(input).slice(0, 80)})`,
|
|
3618
|
+
blocks: [{ type: "tool_use", id: callId ?? `copilot-${idx}`, name, input }],
|
|
3619
|
+
toolName: name,
|
|
3620
|
+
toolUseId: callId,
|
|
3621
|
+
model: stringOf(data.model) ?? model,
|
|
3622
|
+
raw: obj
|
|
3623
|
+
});
|
|
3624
|
+
continue;
|
|
3625
|
+
}
|
|
3626
|
+
if (type === "tool.execution_complete") {
|
|
3627
|
+
const callId = stringOf(data.toolCallId);
|
|
3628
|
+
const resultRecord = recordOf(data.result);
|
|
3629
|
+
const result = resultRecord && "content" in resultRecord ? resultRecord.content : data.result;
|
|
3630
|
+
const success = data.success !== false;
|
|
3631
|
+
push({
|
|
3632
|
+
timestamp,
|
|
3633
|
+
role: "tool-result",
|
|
3634
|
+
rawType: type,
|
|
3635
|
+
preview: previewOf2(result),
|
|
3636
|
+
blocks: [{ type: "tool_result", tool_use_id: callId ?? "", content: result, is_error: !success }],
|
|
3637
|
+
toolUseId: callId,
|
|
3638
|
+
toolResult: data.result,
|
|
3639
|
+
raw: obj
|
|
3640
|
+
});
|
|
3641
|
+
continue;
|
|
3642
|
+
}
|
|
3643
|
+
if (type === "assistant.reasoning") {
|
|
3644
|
+
const text = stringOf(data.content) ?? "";
|
|
3645
|
+
push({
|
|
3646
|
+
timestamp,
|
|
3647
|
+
role: "agent-thinking",
|
|
3648
|
+
rawType: type,
|
|
3649
|
+
preview: previewOf2(text),
|
|
3650
|
+
blocks: text ? [{ type: "thinking", thinking: text }] : [],
|
|
3651
|
+
model,
|
|
3652
|
+
raw: obj
|
|
3653
|
+
});
|
|
3654
|
+
continue;
|
|
3655
|
+
}
|
|
3656
|
+
if (type === "session.shutdown") {
|
|
3657
|
+
sawShutdown = true;
|
|
3658
|
+
model = stringOf(data.currentModel) ?? model;
|
|
3659
|
+
const details = recordOf(data.tokenDetails);
|
|
3660
|
+
totalUsage.input = tokenCount(details, "input") ?? totalUsage.input;
|
|
3661
|
+
totalUsage.output = tokenCount(details, "output") ?? observedOutput;
|
|
3662
|
+
totalUsage.cacheRead = tokenCount(details, "cache_read") ?? totalUsage.cacheRead;
|
|
3663
|
+
totalUsage.cacheWrite = tokenCount(details, "cache_write") ?? totalUsage.cacheWrite;
|
|
3664
|
+
const changes = recordOf(data.codeChanges);
|
|
3665
|
+
linesAdded = numberOf2(changes?.linesAdded);
|
|
3666
|
+
linesRemoved = numberOf2(changes?.linesRemoved);
|
|
3667
|
+
const modified = changes?.filesModified;
|
|
3668
|
+
filesEdited = Array.isArray(modified) ? modified.length : void 0;
|
|
3669
|
+
}
|
|
3670
|
+
push({
|
|
3671
|
+
timestamp,
|
|
3672
|
+
role: "meta",
|
|
3673
|
+
rawType: type,
|
|
3674
|
+
preview: "",
|
|
3675
|
+
blocks: [],
|
|
3676
|
+
raw: obj
|
|
3677
|
+
});
|
|
3678
|
+
}
|
|
3679
|
+
if (totalUsage.output === 0)
|
|
3680
|
+
totalUsage.output = observedOutput;
|
|
3681
|
+
if (totalUsage.input || totalUsage.output || totalUsage.cacheRead || totalUsage.cacheWrite) {
|
|
3682
|
+
const usageEvent = [...events].reverse().find((event) => event.role === "agent" || event.role === "agent-thinking" || event.role === "tool-call");
|
|
3683
|
+
if (usageEvent) {
|
|
3684
|
+
usageEvent.messageId = `copilot-${file.sessionId}-total`;
|
|
3685
|
+
usageEvent.usage = { ...totalUsage };
|
|
3686
|
+
}
|
|
3687
|
+
}
|
|
3688
|
+
const firstTimestamp = firstMs === void 0 ? void 0 : new Date(firstMs).toISOString();
|
|
3689
|
+
const lastTimestamp = lastMs === void 0 ? void 0 : new Date(lastMs).toISOString();
|
|
3690
|
+
if (firstMs !== void 0) {
|
|
3691
|
+
let previousMs;
|
|
3692
|
+
for (const event of events) {
|
|
3693
|
+
if (!event.timestamp)
|
|
3694
|
+
continue;
|
|
3695
|
+
const ms = Date.parse(event.timestamp);
|
|
3696
|
+
if (!Number.isFinite(ms))
|
|
3697
|
+
continue;
|
|
3698
|
+
event.tOffsetMs = Math.max(0, ms - firstMs);
|
|
3699
|
+
if (previousMs !== void 0)
|
|
3700
|
+
event.gapMs = Math.max(0, ms - previousMs);
|
|
3701
|
+
previousMs = ms;
|
|
3702
|
+
}
|
|
3703
|
+
}
|
|
3704
|
+
const activeSegments = computeActiveSegments3(timestamps);
|
|
3705
|
+
const airTimeMs = activeSegments.reduce((sum, segment) => sum + segment.endMs - segment.startMs, 0);
|
|
3706
|
+
const project = cwd ? resolveProjectIdentity(cwd) : void 0;
|
|
3707
|
+
const repoName = project?.repoName ?? repository?.split("/").filter(Boolean).at(-1);
|
|
3708
|
+
const meta = {
|
|
3709
|
+
agent: "copilot",
|
|
3710
|
+
id: file.sessionId,
|
|
3711
|
+
filePath: file.filePath,
|
|
3712
|
+
projectName: project?.projectName ?? cwd ?? "(unknown)",
|
|
3713
|
+
worktreeName: project?.worktreeName,
|
|
3714
|
+
repoName,
|
|
3715
|
+
projectDir: syntheticProjectDir(cwd),
|
|
3716
|
+
sessionId: file.sessionId,
|
|
3717
|
+
firstTimestamp,
|
|
3718
|
+
lastTimestamp,
|
|
3719
|
+
lastActivityMs: file.mtimeMs,
|
|
3720
|
+
durationMs: firstMs !== void 0 && lastMs !== void 0 ? lastMs - firstMs : void 0,
|
|
3721
|
+
eventCount: events.length,
|
|
3722
|
+
model,
|
|
3723
|
+
cwd,
|
|
3724
|
+
gitBranch,
|
|
3725
|
+
totalUsage,
|
|
3726
|
+
status: sawShutdown || Date.now() - file.mtimeMs > IDLE_GAP_MS2 ? "idle" : "running",
|
|
3727
|
+
firstUserPreview,
|
|
3728
|
+
lastUserPreview,
|
|
3729
|
+
lastAgentPreview,
|
|
3730
|
+
toolCallCount,
|
|
3731
|
+
turnCount,
|
|
3732
|
+
linesAdded,
|
|
3733
|
+
linesRemoved,
|
|
3734
|
+
filesEdited,
|
|
3735
|
+
airTimeMs,
|
|
3736
|
+
activeSegments
|
|
3737
|
+
};
|
|
3738
|
+
return { meta, events };
|
|
3739
|
+
}
|
|
3740
|
+
function clearCopilotCaches() {
|
|
3741
|
+
metaCache3.clear();
|
|
3742
|
+
detailCache3.clear();
|
|
3743
|
+
}
|
|
3744
|
+
async function scanCopilot(root) {
|
|
3745
|
+
const files = await listSessionFiles(root);
|
|
3746
|
+
const out = [];
|
|
3747
|
+
for (const file of files) {
|
|
3748
|
+
const cached = metaCache3.get(file.filePath);
|
|
3749
|
+
if (cached && cached.mtimeMs === file.mtimeMs && cached.sizeBytes === file.sizeBytes) {
|
|
3750
|
+
out.push({ file, meta: cached.meta });
|
|
3751
|
+
continue;
|
|
3752
|
+
}
|
|
3753
|
+
try {
|
|
3754
|
+
const lines = await readJsonl2(file.filePath);
|
|
3755
|
+
const { meta } = parseSession(file, lines);
|
|
3756
|
+
metaCache3.set(file.filePath, { meta, mtimeMs: file.mtimeMs, sizeBytes: file.sizeBytes });
|
|
3757
|
+
out.push({ file, meta });
|
|
3758
|
+
} catch {
|
|
3759
|
+
}
|
|
3760
|
+
}
|
|
3761
|
+
return out;
|
|
3762
|
+
}
|
|
3763
|
+
async function listCopilotSessions(opts = {}) {
|
|
3764
|
+
const root = opts.root ?? DEFAULT_COPILOT_ROOT;
|
|
3765
|
+
const sessions = (await scanCopilot(root)).map((entry) => entry.meta);
|
|
3766
|
+
sessions.sort((a, b) => (b.firstTimestamp ?? "").localeCompare(a.firstTimestamp ?? ""));
|
|
3767
|
+
return opts.limit === void 0 ? sessions : sessions.slice(0, opts.limit);
|
|
3768
|
+
}
|
|
3769
|
+
async function getCopilotSession(id, opts = {}) {
|
|
3770
|
+
const root = opts.root ?? DEFAULT_COPILOT_ROOT;
|
|
3771
|
+
const entry = (await scanCopilot(root)).find((candidate) => candidate.meta.id === id);
|
|
3772
|
+
if (!entry)
|
|
3773
|
+
return null;
|
|
3774
|
+
const cached = detailCache3.get(entry.file.filePath);
|
|
3775
|
+
if (cached && cached.mtimeMs === entry.file.mtimeMs && cached.sizeBytes === entry.file.sizeBytes) {
|
|
3776
|
+
return cached.detail;
|
|
3777
|
+
}
|
|
3778
|
+
const lines = await readJsonl2(entry.file.filePath);
|
|
3779
|
+
const { meta, events } = parseSession(entry.file, lines);
|
|
3780
|
+
const detail = { ...meta, events };
|
|
3781
|
+
detailCache3.set(entry.file.filePath, {
|
|
3782
|
+
detail,
|
|
3783
|
+
mtimeMs: entry.file.mtimeMs,
|
|
3784
|
+
sizeBytes: entry.file.sizeBytes
|
|
3785
|
+
});
|
|
3786
|
+
return detail;
|
|
3787
|
+
}
|
|
3788
|
+
function copilotSessionLocalDay(meta) {
|
|
3789
|
+
if (!meta.firstTimestamp)
|
|
3790
|
+
return void 0;
|
|
3791
|
+
const ms = Date.parse(meta.firstTimestamp);
|
|
3792
|
+
return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
|
|
3793
|
+
}
|
|
3794
|
+
var DEFAULT_COPILOT_ROOT, IDLE_GAP_MS2, metaCache3, detailCache3;
|
|
3795
|
+
var init_copilot = __esm({
|
|
3796
|
+
"../parser/dist/copilot.js"() {
|
|
3797
|
+
"use strict";
|
|
3798
|
+
init_analytics();
|
|
3799
|
+
init_git_project();
|
|
3800
|
+
init_user_input();
|
|
3801
|
+
DEFAULT_COPILOT_ROOT = path3.join(os3.homedir(), ".copilot", "session-state");
|
|
3802
|
+
IDLE_GAP_MS2 = 3 * 60 * 1e3;
|
|
3803
|
+
metaCache3 = /* @__PURE__ */ new Map();
|
|
3804
|
+
detailCache3 = /* @__PURE__ */ new Map();
|
|
3805
|
+
}
|
|
3806
|
+
});
|
|
3807
|
+
|
|
3808
|
+
// ../parser/dist/gemini.js
|
|
3809
|
+
import { promises as fs4 } from "node:fs";
|
|
3810
|
+
import os4 from "node:os";
|
|
3811
|
+
import path4 from "node:path";
|
|
3812
|
+
async function safeReaddir2(p) {
|
|
3813
|
+
return fs4.readdir(p).catch(() => []);
|
|
3814
|
+
}
|
|
3815
|
+
async function listSessionFiles2(root) {
|
|
3390
3816
|
const out = [];
|
|
3391
3817
|
const slugs = await safeReaddir2(root);
|
|
3392
3818
|
for (const slug of slugs) {
|
|
3393
|
-
const chatsDir =
|
|
3819
|
+
const chatsDir = path4.join(root, slug, "chats");
|
|
3394
3820
|
const entries2 = await safeReaddir2(chatsDir);
|
|
3395
3821
|
for (const entry of entries2) {
|
|
3396
3822
|
if (!SESSION_FILE_RE.test(entry))
|
|
3397
3823
|
continue;
|
|
3398
|
-
const full =
|
|
3399
|
-
const stat = await
|
|
3824
|
+
const full = path4.join(chatsDir, entry);
|
|
3825
|
+
const stat = await fs4.stat(full).catch(() => null);
|
|
3400
3826
|
if (!stat || !stat.isFile())
|
|
3401
3827
|
continue;
|
|
3402
3828
|
const filenameId = entry.replace(/\.(jsonl|json)$/, "").split("-").pop() ?? entry;
|
|
@@ -3413,13 +3839,13 @@ async function listSessionFiles(root) {
|
|
|
3413
3839
|
return out;
|
|
3414
3840
|
}
|
|
3415
3841
|
async function loadSlugToCwd() {
|
|
3416
|
-
const stat = await
|
|
3842
|
+
const stat = await fs4.stat(GEMINI_PROJECTS_FILE).catch(() => null);
|
|
3417
3843
|
if (!stat)
|
|
3418
3844
|
return /* @__PURE__ */ new Map();
|
|
3419
3845
|
if (projectsCache && projectsCache.mtimeMs === stat.mtimeMs) {
|
|
3420
3846
|
return projectsCache.slugToCwd;
|
|
3421
3847
|
}
|
|
3422
|
-
const raw = await
|
|
3848
|
+
const raw = await fs4.readFile(GEMINI_PROJECTS_FILE, "utf8").catch(() => "");
|
|
3423
3849
|
let parsed;
|
|
3424
3850
|
try {
|
|
3425
3851
|
parsed = JSON.parse(raw);
|
|
@@ -3444,7 +3870,7 @@ function isMessageRecord(o) {
|
|
|
3444
3870
|
return !!o && typeof o === "object" && typeof o.id === "string" && typeof o.type === "string";
|
|
3445
3871
|
}
|
|
3446
3872
|
async function readAndReplay(file) {
|
|
3447
|
-
const raw = await
|
|
3873
|
+
const raw = await fs4.readFile(file.filePath, "utf8");
|
|
3448
3874
|
if (file.format === "legacy-json") {
|
|
3449
3875
|
let blob;
|
|
3450
3876
|
try {
|
|
@@ -3519,10 +3945,10 @@ async function readAndReplay(file) {
|
|
|
3519
3945
|
}
|
|
3520
3946
|
return { meta, messages };
|
|
3521
3947
|
}
|
|
3522
|
-
function
|
|
3948
|
+
function emptyUsage3() {
|
|
3523
3949
|
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
3524
3950
|
}
|
|
3525
|
-
function
|
|
3951
|
+
function previewOf3(text) {
|
|
3526
3952
|
return text.replace(/\s+/g, " ").trim().slice(0, 200);
|
|
3527
3953
|
}
|
|
3528
3954
|
function flattenContent(c) {
|
|
@@ -3561,12 +3987,12 @@ function flattenContent(c) {
|
|
|
3561
3987
|
function truncate3(s, n) {
|
|
3562
3988
|
return s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
|
|
3563
3989
|
}
|
|
3564
|
-
async function
|
|
3990
|
+
async function parseSession2(file) {
|
|
3565
3991
|
const { meta: metaRec, messages } = await readAndReplay(file);
|
|
3566
3992
|
const slugToCwd = await loadSlugToCwd();
|
|
3567
3993
|
const cwd = slugToCwd.get(file.slug);
|
|
3568
3994
|
const events = [];
|
|
3569
|
-
const totalUsage =
|
|
3995
|
+
const totalUsage = emptyUsage3();
|
|
3570
3996
|
let firstTimestamp;
|
|
3571
3997
|
let lastTimestamp;
|
|
3572
3998
|
let model;
|
|
@@ -3592,7 +4018,7 @@ async function parseSession(file) {
|
|
|
3592
4018
|
const ts = msg.timestamp;
|
|
3593
4019
|
if (msg.type === "user") {
|
|
3594
4020
|
const text = flattenContent(msg.displayContent ?? msg.content);
|
|
3595
|
-
const preview =
|
|
4021
|
+
const preview = previewOf3(text);
|
|
3596
4022
|
const isHidden = isFrameworkInjectedUserInput(text);
|
|
3597
4023
|
if (text && !isHidden) {
|
|
3598
4024
|
if (!firstUserPreview)
|
|
@@ -3616,7 +4042,7 @@ async function parseSession(file) {
|
|
|
3616
4042
|
if (typeof msg.model === "string")
|
|
3617
4043
|
model = msg.model;
|
|
3618
4044
|
const text = flattenContent(msg.content);
|
|
3619
|
-
const preview =
|
|
4045
|
+
const preview = previewOf3(text);
|
|
3620
4046
|
if (text)
|
|
3621
4047
|
lastAgentPreview = preview;
|
|
3622
4048
|
let usage2;
|
|
@@ -3642,7 +4068,7 @@ async function parseSession(file) {
|
|
|
3642
4068
|
timestamp: th.timestamp ?? ts,
|
|
3643
4069
|
role: "agent-thinking",
|
|
3644
4070
|
rawType: "gemini/thought",
|
|
3645
|
-
preview:
|
|
4071
|
+
preview: previewOf3(thText),
|
|
3646
4072
|
blocks: [{ type: "thinking", thinking: thText }],
|
|
3647
4073
|
model,
|
|
3648
4074
|
raw: th
|
|
@@ -3699,7 +4125,7 @@ async function parseSession(file) {
|
|
|
3699
4125
|
timestamp: tc.timestamp ?? ts,
|
|
3700
4126
|
role: "tool-result",
|
|
3701
4127
|
rawType: "gemini/tool_result",
|
|
3702
|
-
preview:
|
|
4128
|
+
preview: previewOf3(resultText),
|
|
3703
4129
|
blocks: [
|
|
3704
4130
|
{
|
|
3705
4131
|
type: "tool_result",
|
|
@@ -3723,7 +4149,7 @@ async function parseSession(file) {
|
|
|
3723
4149
|
timestamp: ts,
|
|
3724
4150
|
role: "meta",
|
|
3725
4151
|
rawType: `gemini/${msg.type}`,
|
|
3726
|
-
preview:
|
|
4152
|
+
preview: previewOf3(text),
|
|
3727
4153
|
blocks: text ? [{ type: "text", text }] : [],
|
|
3728
4154
|
raw: msg
|
|
3729
4155
|
});
|
|
@@ -3745,7 +4171,7 @@ async function parseSession(file) {
|
|
|
3745
4171
|
prevMs = ms;
|
|
3746
4172
|
}
|
|
3747
4173
|
}
|
|
3748
|
-
const activeSegments =
|
|
4174
|
+
const activeSegments = computeActiveSegments4(tsMs);
|
|
3749
4175
|
const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
|
|
3750
4176
|
const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
|
|
3751
4177
|
const sessionId = metaRec.sessionId ?? file.filenameId;
|
|
@@ -3779,7 +4205,7 @@ async function parseSession(file) {
|
|
|
3779
4205
|
};
|
|
3780
4206
|
return { meta, events };
|
|
3781
4207
|
}
|
|
3782
|
-
function
|
|
4208
|
+
function computeActiveSegments4(tsMs) {
|
|
3783
4209
|
if (tsMs.length === 0)
|
|
3784
4210
|
return [];
|
|
3785
4211
|
const sorted = [...tsMs].sort((a, b) => a - b);
|
|
@@ -3787,7 +4213,7 @@ function computeActiveSegments3(tsMs) {
|
|
|
3787
4213
|
let segStart = sorted[0];
|
|
3788
4214
|
let segEnd = sorted[0];
|
|
3789
4215
|
for (let i = 1; i < sorted.length; i++) {
|
|
3790
|
-
if (sorted[i] - segEnd >
|
|
4216
|
+
if (sorted[i] - segEnd > IDLE_GAP_MS3) {
|
|
3791
4217
|
out.push({ startMs: segStart, endMs: segEnd });
|
|
3792
4218
|
segStart = sorted[i];
|
|
3793
4219
|
}
|
|
@@ -3797,23 +4223,23 @@ function computeActiveSegments3(tsMs) {
|
|
|
3797
4223
|
return out;
|
|
3798
4224
|
}
|
|
3799
4225
|
function clearGeminiCaches() {
|
|
3800
|
-
|
|
3801
|
-
|
|
4226
|
+
metaCache4.clear();
|
|
4227
|
+
detailCache4.clear();
|
|
3802
4228
|
projectsCache = null;
|
|
3803
4229
|
}
|
|
3804
4230
|
async function listGeminiSessions(opts = {}) {
|
|
3805
4231
|
const root = opts.root ?? DEFAULT_GEMINI_ROOT;
|
|
3806
|
-
const files = await
|
|
4232
|
+
const files = await listSessionFiles2(root);
|
|
3807
4233
|
const out = [];
|
|
3808
4234
|
for (const file of files) {
|
|
3809
|
-
const cached =
|
|
4235
|
+
const cached = metaCache4.get(file.filePath);
|
|
3810
4236
|
if (cached && cached.mtimeMs === file.mtimeMs && cached.sizeBytes === file.sizeBytes) {
|
|
3811
4237
|
out.push(cached.meta);
|
|
3812
4238
|
continue;
|
|
3813
4239
|
}
|
|
3814
4240
|
try {
|
|
3815
|
-
const { meta } = await
|
|
3816
|
-
|
|
4241
|
+
const { meta } = await parseSession2(file);
|
|
4242
|
+
metaCache4.set(file.filePath, {
|
|
3817
4243
|
meta,
|
|
3818
4244
|
mtimeMs: file.mtimeMs,
|
|
3819
4245
|
sizeBytes: file.sizeBytes
|
|
@@ -3829,7 +4255,7 @@ async function listGeminiSessions(opts = {}) {
|
|
|
3829
4255
|
}
|
|
3830
4256
|
async function getGeminiSession(id, opts = {}) {
|
|
3831
4257
|
const root = opts.root ?? DEFAULT_GEMINI_ROOT;
|
|
3832
|
-
const files = await
|
|
4258
|
+
const files = await listSessionFiles2(root);
|
|
3833
4259
|
let chosen;
|
|
3834
4260
|
for (const file of files) {
|
|
3835
4261
|
if (file.filenameId === id || id.startsWith(file.filenameId)) {
|
|
@@ -3839,7 +4265,7 @@ async function getGeminiSession(id, opts = {}) {
|
|
|
3839
4265
|
}
|
|
3840
4266
|
if (!chosen) {
|
|
3841
4267
|
for (const file of files) {
|
|
3842
|
-
const { meta: meta2 } = await
|
|
4268
|
+
const { meta: meta2 } = await parseSession2(file).catch(() => ({ meta: { id: "" } }));
|
|
3843
4269
|
if (meta2.id === id) {
|
|
3844
4270
|
chosen = file;
|
|
3845
4271
|
break;
|
|
@@ -3848,13 +4274,13 @@ async function getGeminiSession(id, opts = {}) {
|
|
|
3848
4274
|
}
|
|
3849
4275
|
if (!chosen)
|
|
3850
4276
|
return null;
|
|
3851
|
-
const cached =
|
|
4277
|
+
const cached = detailCache4.get(chosen.filePath);
|
|
3852
4278
|
if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes) {
|
|
3853
4279
|
return cached.detail;
|
|
3854
4280
|
}
|
|
3855
|
-
const { meta, events } = await
|
|
4281
|
+
const { meta, events } = await parseSession2(chosen);
|
|
3856
4282
|
const detail = { ...meta, events };
|
|
3857
|
-
|
|
4283
|
+
detailCache4.set(chosen.filePath, {
|
|
3858
4284
|
detail,
|
|
3859
4285
|
mtimeMs: chosen.mtimeMs,
|
|
3860
4286
|
sizeBytes: chosen.sizeBytes
|
|
@@ -3867,39 +4293,39 @@ function geminiSessionLocalDay(meta) {
|
|
|
3867
4293
|
const ms = Date.parse(meta.firstTimestamp);
|
|
3868
4294
|
return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
|
|
3869
4295
|
}
|
|
3870
|
-
var DEFAULT_GEMINI_ROOT, GEMINI_PROJECTS_FILE, SESSION_FILE_RE,
|
|
4296
|
+
var DEFAULT_GEMINI_ROOT, GEMINI_PROJECTS_FILE, SESSION_FILE_RE, IDLE_GAP_MS3, projectsCache, metaCache4, detailCache4;
|
|
3871
4297
|
var init_gemini = __esm({
|
|
3872
4298
|
"../parser/dist/gemini.js"() {
|
|
3873
4299
|
"use strict";
|
|
3874
4300
|
init_analytics();
|
|
3875
4301
|
init_git_project();
|
|
3876
4302
|
init_user_input();
|
|
3877
|
-
DEFAULT_GEMINI_ROOT =
|
|
3878
|
-
GEMINI_PROJECTS_FILE =
|
|
4303
|
+
DEFAULT_GEMINI_ROOT = path4.join(os4.homedir(), ".gemini", "tmp");
|
|
4304
|
+
GEMINI_PROJECTS_FILE = path4.join(os4.homedir(), ".gemini", "projects.json");
|
|
3879
4305
|
SESSION_FILE_RE = /^session-.+\.(jsonl|json)$/;
|
|
3880
|
-
|
|
4306
|
+
IDLE_GAP_MS3 = 3 * 60 * 1e3;
|
|
3881
4307
|
projectsCache = null;
|
|
3882
|
-
|
|
3883
|
-
|
|
4308
|
+
metaCache4 = /* @__PURE__ */ new Map();
|
|
4309
|
+
detailCache4 = /* @__PURE__ */ new Map();
|
|
3884
4310
|
}
|
|
3885
4311
|
});
|
|
3886
4312
|
|
|
3887
4313
|
// ../parser/dist/antigravity.js
|
|
3888
|
-
import { promises as
|
|
3889
|
-
import
|
|
3890
|
-
import
|
|
4314
|
+
import { promises as fs5 } from "node:fs";
|
|
4315
|
+
import os5 from "node:os";
|
|
4316
|
+
import path5 from "node:path";
|
|
3891
4317
|
async function safeReaddir3(p) {
|
|
3892
|
-
return
|
|
4318
|
+
return fs5.readdir(p).catch(() => []);
|
|
3893
4319
|
}
|
|
3894
4320
|
async function loadSlugToCwd2(root) {
|
|
3895
|
-
const historyFile =
|
|
3896
|
-
const stat = await
|
|
4321
|
+
const historyFile = path5.join(root, "history.jsonl");
|
|
4322
|
+
const stat = await fs5.stat(historyFile).catch(() => null);
|
|
3897
4323
|
if (!stat)
|
|
3898
4324
|
return /* @__PURE__ */ new Map();
|
|
3899
4325
|
if (historyCache && historyCache.mtimeMs === stat.mtimeMs) {
|
|
3900
4326
|
return historyCache.slugToCwd;
|
|
3901
4327
|
}
|
|
3902
|
-
const raw = await
|
|
4328
|
+
const raw = await fs5.readFile(historyFile, "utf8").catch(() => "");
|
|
3903
4329
|
const slugToCwd = /* @__PURE__ */ new Map();
|
|
3904
4330
|
for (const line of raw.split("\n")) {
|
|
3905
4331
|
const trimmed = line.trim();
|
|
@@ -3916,14 +4342,14 @@ async function loadSlugToCwd2(root) {
|
|
|
3916
4342
|
historyCache = { mtimeMs: stat.mtimeMs, slugToCwd };
|
|
3917
4343
|
return slugToCwd;
|
|
3918
4344
|
}
|
|
3919
|
-
async function
|
|
4345
|
+
async function listSessionFiles3(root) {
|
|
3920
4346
|
const slugToCwd = await loadSlugToCwd2(root);
|
|
3921
4347
|
const out = [];
|
|
3922
|
-
const brainDir =
|
|
4348
|
+
const brainDir = path5.join(root, "brain");
|
|
3923
4349
|
const entries2 = await safeReaddir3(brainDir);
|
|
3924
4350
|
for (const entry of entries2) {
|
|
3925
|
-
const transcriptPath =
|
|
3926
|
-
const stat = await
|
|
4351
|
+
const transcriptPath = path5.join(brainDir, entry, ".system_generated", "logs", "transcript.jsonl");
|
|
4352
|
+
const stat = await fs5.stat(transcriptPath).catch(() => null);
|
|
3927
4353
|
if (stat && stat.isFile()) {
|
|
3928
4354
|
out.push({
|
|
3929
4355
|
filePath: transcriptPath,
|
|
@@ -3936,19 +4362,19 @@ async function listSessionFiles2(root) {
|
|
|
3936
4362
|
}
|
|
3937
4363
|
return out;
|
|
3938
4364
|
}
|
|
3939
|
-
function
|
|
4365
|
+
function emptyUsage4() {
|
|
3940
4366
|
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
3941
4367
|
}
|
|
3942
|
-
function
|
|
4368
|
+
function previewOf4(text) {
|
|
3943
4369
|
return text.replace(/\s+/g, " ").trim().slice(0, 200);
|
|
3944
4370
|
}
|
|
3945
4371
|
function truncate4(s, n) {
|
|
3946
4372
|
return s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
|
|
3947
4373
|
}
|
|
3948
|
-
async function
|
|
3949
|
-
const raw = await
|
|
4374
|
+
async function parseSession3(file) {
|
|
4375
|
+
const raw = await fs5.readFile(file.filePath, "utf8");
|
|
3950
4376
|
const events = [];
|
|
3951
|
-
const totalUsage =
|
|
4377
|
+
const totalUsage = emptyUsage4();
|
|
3952
4378
|
let firstTimestamp;
|
|
3953
4379
|
let lastTimestamp;
|
|
3954
4380
|
let model;
|
|
@@ -4020,7 +4446,7 @@ async function parseSession2(file) {
|
|
|
4020
4446
|
if (requestMatch) {
|
|
4021
4447
|
text2 = requestMatch[1].trim();
|
|
4022
4448
|
}
|
|
4023
|
-
const preview =
|
|
4449
|
+
const preview = previewOf4(text2);
|
|
4024
4450
|
const isHidden = isFrameworkInjectedUserInput(text2);
|
|
4025
4451
|
if (text2 && !isHidden) {
|
|
4026
4452
|
if (!firstUserPreview)
|
|
@@ -4049,14 +4475,14 @@ async function parseSession2(file) {
|
|
|
4049
4475
|
timestamp: ts,
|
|
4050
4476
|
role: "agent-thinking",
|
|
4051
4477
|
rawType: "antigravity/thought",
|
|
4052
|
-
preview:
|
|
4478
|
+
preview: previewOf4(thinking),
|
|
4053
4479
|
blocks: [{ type: "thinking", thinking }],
|
|
4054
4480
|
model,
|
|
4055
4481
|
raw: eventObj
|
|
4056
4482
|
});
|
|
4057
4483
|
}
|
|
4058
4484
|
if (content) {
|
|
4059
|
-
const preview =
|
|
4485
|
+
const preview = previewOf4(content);
|
|
4060
4486
|
lastAgentPreview = preview;
|
|
4061
4487
|
pushEvent({
|
|
4062
4488
|
index: idx++,
|
|
@@ -4102,7 +4528,7 @@ async function parseSession2(file) {
|
|
|
4102
4528
|
timestamp: ts,
|
|
4103
4529
|
role: "tool-result",
|
|
4104
4530
|
rawType: "antigravity/tool_result",
|
|
4105
|
-
preview:
|
|
4531
|
+
preview: previewOf4(contentStr),
|
|
4106
4532
|
blocks: [{
|
|
4107
4533
|
type: "tool_result",
|
|
4108
4534
|
tool_use_id: toolUseId,
|
|
@@ -4121,7 +4547,7 @@ async function parseSession2(file) {
|
|
|
4121
4547
|
timestamp: ts,
|
|
4122
4548
|
role: "meta",
|
|
4123
4549
|
rawType: `antigravity/${eventObj.type?.toLowerCase() || "unknown"}`,
|
|
4124
|
-
preview:
|
|
4550
|
+
preview: previewOf4(text),
|
|
4125
4551
|
blocks: text ? [{ type: "text", text }] : [],
|
|
4126
4552
|
raw: eventObj
|
|
4127
4553
|
});
|
|
@@ -4141,7 +4567,7 @@ async function parseSession2(file) {
|
|
|
4141
4567
|
prevMs = ms;
|
|
4142
4568
|
}
|
|
4143
4569
|
}
|
|
4144
|
-
const activeSegments =
|
|
4570
|
+
const activeSegments = computeActiveSegments5(tsMs);
|
|
4145
4571
|
const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
|
|
4146
4572
|
const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
|
|
4147
4573
|
const sessionId = file.conversationId;
|
|
@@ -4176,7 +4602,7 @@ async function parseSession2(file) {
|
|
|
4176
4602
|
};
|
|
4177
4603
|
return { meta, events };
|
|
4178
4604
|
}
|
|
4179
|
-
function
|
|
4605
|
+
function computeActiveSegments5(tsMs) {
|
|
4180
4606
|
if (tsMs.length === 0)
|
|
4181
4607
|
return [];
|
|
4182
4608
|
const sorted = [...tsMs].sort((a, b) => a - b);
|
|
@@ -4184,7 +4610,7 @@ function computeActiveSegments4(tsMs) {
|
|
|
4184
4610
|
let segStart = sorted[0];
|
|
4185
4611
|
let segEnd = sorted[0];
|
|
4186
4612
|
for (let i = 1; i < sorted.length; i++) {
|
|
4187
|
-
if (sorted[i] - segEnd >
|
|
4613
|
+
if (sorted[i] - segEnd > IDLE_GAP_MS4) {
|
|
4188
4614
|
out.push({ startMs: segStart, endMs: segEnd });
|
|
4189
4615
|
segStart = sorted[i];
|
|
4190
4616
|
}
|
|
@@ -4194,23 +4620,23 @@ function computeActiveSegments4(tsMs) {
|
|
|
4194
4620
|
return out;
|
|
4195
4621
|
}
|
|
4196
4622
|
function clearAntigravityCaches() {
|
|
4197
|
-
|
|
4198
|
-
|
|
4623
|
+
metaCache5.clear();
|
|
4624
|
+
detailCache5.clear();
|
|
4199
4625
|
historyCache = null;
|
|
4200
4626
|
}
|
|
4201
4627
|
async function listAntigravitySessions(opts = {}) {
|
|
4202
4628
|
const root = opts.root ?? DEFAULT_ANTIGRAVITY_ROOT;
|
|
4203
|
-
const files = await
|
|
4629
|
+
const files = await listSessionFiles3(root);
|
|
4204
4630
|
const out = [];
|
|
4205
4631
|
for (const file of files) {
|
|
4206
|
-
const cached =
|
|
4632
|
+
const cached = metaCache5.get(file.filePath);
|
|
4207
4633
|
if (cached && cached.mtimeMs === file.mtimeMs && cached.sizeBytes === file.sizeBytes && cached.cwd === file.cwd) {
|
|
4208
4634
|
out.push(cached.meta);
|
|
4209
4635
|
continue;
|
|
4210
4636
|
}
|
|
4211
4637
|
try {
|
|
4212
|
-
const { meta } = await
|
|
4213
|
-
|
|
4638
|
+
const { meta } = await parseSession3(file);
|
|
4639
|
+
metaCache5.set(file.filePath, {
|
|
4214
4640
|
meta,
|
|
4215
4641
|
mtimeMs: file.mtimeMs,
|
|
4216
4642
|
sizeBytes: file.sizeBytes,
|
|
@@ -4227,7 +4653,7 @@ async function listAntigravitySessions(opts = {}) {
|
|
|
4227
4653
|
}
|
|
4228
4654
|
async function getAntigravitySession(id, opts = {}) {
|
|
4229
4655
|
const root = opts.root ?? DEFAULT_ANTIGRAVITY_ROOT;
|
|
4230
|
-
const files = await
|
|
4656
|
+
const files = await listSessionFiles3(root);
|
|
4231
4657
|
let chosen;
|
|
4232
4658
|
for (const file of files) {
|
|
4233
4659
|
if (file.conversationId === id) {
|
|
@@ -4237,13 +4663,13 @@ async function getAntigravitySession(id, opts = {}) {
|
|
|
4237
4663
|
}
|
|
4238
4664
|
if (!chosen)
|
|
4239
4665
|
return null;
|
|
4240
|
-
const cached =
|
|
4666
|
+
const cached = detailCache5.get(chosen.filePath);
|
|
4241
4667
|
if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes && cached.cwd === chosen.cwd) {
|
|
4242
4668
|
return cached.detail;
|
|
4243
4669
|
}
|
|
4244
|
-
const { meta, events } = await
|
|
4670
|
+
const { meta, events } = await parseSession3(chosen);
|
|
4245
4671
|
const detail = { ...meta, events };
|
|
4246
|
-
|
|
4672
|
+
detailCache5.set(chosen.filePath, {
|
|
4247
4673
|
detail,
|
|
4248
4674
|
mtimeMs: chosen.mtimeMs,
|
|
4249
4675
|
sizeBytes: chosen.sizeBytes,
|
|
@@ -4257,61 +4683,61 @@ function antigravitySessionLocalDay(meta) {
|
|
|
4257
4683
|
const ms = Date.parse(meta.firstTimestamp);
|
|
4258
4684
|
return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
|
|
4259
4685
|
}
|
|
4260
|
-
var DEFAULT_ANTIGRAVITY_ROOT,
|
|
4686
|
+
var DEFAULT_ANTIGRAVITY_ROOT, IDLE_GAP_MS4, historyCache, metaCache5, detailCache5;
|
|
4261
4687
|
var init_antigravity = __esm({
|
|
4262
4688
|
"../parser/dist/antigravity.js"() {
|
|
4263
4689
|
"use strict";
|
|
4264
4690
|
init_analytics();
|
|
4265
4691
|
init_git_project();
|
|
4266
4692
|
init_user_input();
|
|
4267
|
-
DEFAULT_ANTIGRAVITY_ROOT =
|
|
4268
|
-
|
|
4693
|
+
DEFAULT_ANTIGRAVITY_ROOT = path5.join(os5.homedir(), ".gemini", "antigravity-cli");
|
|
4694
|
+
IDLE_GAP_MS4 = 3 * 60 * 1e3;
|
|
4269
4695
|
historyCache = null;
|
|
4270
|
-
|
|
4271
|
-
|
|
4696
|
+
metaCache5 = /* @__PURE__ */ new Map();
|
|
4697
|
+
detailCache5 = /* @__PURE__ */ new Map();
|
|
4272
4698
|
}
|
|
4273
4699
|
});
|
|
4274
4700
|
|
|
4275
4701
|
// ../parser/dist/cowork.js
|
|
4276
|
-
import { promises as
|
|
4277
|
-
import
|
|
4278
|
-
import
|
|
4702
|
+
import { promises as fs6 } from "node:fs";
|
|
4703
|
+
import os6 from "node:os";
|
|
4704
|
+
import path6 from "node:path";
|
|
4279
4705
|
function defaultCoworkRoot() {
|
|
4280
|
-
const home =
|
|
4706
|
+
const home = os6.homedir();
|
|
4281
4707
|
if (process.platform === "darwin") {
|
|
4282
|
-
return
|
|
4708
|
+
return path6.join(home, "Library", "Application Support", "Claude", "local-agent-mode-sessions");
|
|
4283
4709
|
}
|
|
4284
4710
|
if (process.platform === "win32") {
|
|
4285
|
-
const appData = process.env.APPDATA ??
|
|
4286
|
-
return
|
|
4711
|
+
const appData = process.env.APPDATA ?? path6.join(home, "AppData", "Roaming");
|
|
4712
|
+
return path6.join(appData, "Claude", "local-agent-mode-sessions");
|
|
4287
4713
|
}
|
|
4288
|
-
return
|
|
4714
|
+
return path6.join(home, ".config", "Claude", "local-agent-mode-sessions");
|
|
4289
4715
|
}
|
|
4290
4716
|
async function safeReaddir4(p) {
|
|
4291
|
-
return
|
|
4717
|
+
return fs6.readdir(p).catch(() => []);
|
|
4292
4718
|
}
|
|
4293
4719
|
async function statMs(p) {
|
|
4294
|
-
const s = await
|
|
4720
|
+
const s = await fs6.stat(p).catch(() => null);
|
|
4295
4721
|
return s ? s.mtimeMs : 0;
|
|
4296
4722
|
}
|
|
4297
|
-
async function
|
|
4723
|
+
async function listSessionFiles4(root) {
|
|
4298
4724
|
const out = [];
|
|
4299
4725
|
const accounts = await safeReaddir4(root);
|
|
4300
4726
|
for (const accountId of accounts) {
|
|
4301
|
-
const accountDir =
|
|
4727
|
+
const accountDir = path6.join(root, accountId);
|
|
4302
4728
|
const workspaces = await safeReaddir4(accountDir);
|
|
4303
4729
|
for (const workspaceId of workspaces) {
|
|
4304
|
-
const workspaceDir =
|
|
4305
|
-
const spacesMtimeMs = await statMs(
|
|
4730
|
+
const workspaceDir = path6.join(accountDir, workspaceId);
|
|
4731
|
+
const spacesMtimeMs = await statMs(path6.join(workspaceDir, "spaces.json"));
|
|
4306
4732
|
const entries2 = await safeReaddir4(workspaceDir);
|
|
4307
4733
|
for (const entry of entries2) {
|
|
4308
4734
|
if (!SESSION_ID_RE.test(entry))
|
|
4309
4735
|
continue;
|
|
4310
|
-
const auditPath =
|
|
4311
|
-
const auditStat = await
|
|
4736
|
+
const auditPath = path6.join(workspaceDir, entry, "audit.jsonl");
|
|
4737
|
+
const auditStat = await fs6.stat(auditPath).catch(() => null);
|
|
4312
4738
|
if (!auditStat || !auditStat.isFile() || auditStat.size === 0)
|
|
4313
4739
|
continue;
|
|
4314
|
-
const metaPath =
|
|
4740
|
+
const metaPath = path6.join(workspaceDir, `${entry}.json`);
|
|
4315
4741
|
const metaMtimeMs = await statMs(metaPath);
|
|
4316
4742
|
out.push({
|
|
4317
4743
|
sessionId: entry,
|
|
@@ -4329,14 +4755,14 @@ async function listSessionFiles3(root) {
|
|
|
4329
4755
|
return out;
|
|
4330
4756
|
}
|
|
4331
4757
|
async function loadSpacesForWorkspace(workspaceDir) {
|
|
4332
|
-
const spacesPath =
|
|
4333
|
-
const stat = await
|
|
4758
|
+
const spacesPath = path6.join(workspaceDir, "spaces.json");
|
|
4759
|
+
const stat = await fs6.stat(spacesPath).catch(() => null);
|
|
4334
4760
|
if (!stat)
|
|
4335
4761
|
return /* @__PURE__ */ new Map();
|
|
4336
4762
|
const cached = spacesCache.get(workspaceDir);
|
|
4337
4763
|
if (cached && cached.mtimeMs === stat.mtimeMs)
|
|
4338
4764
|
return cached.spaceIdToPath;
|
|
4339
|
-
const raw = await
|
|
4765
|
+
const raw = await fs6.readFile(spacesPath, "utf8").catch(() => "");
|
|
4340
4766
|
const out = /* @__PURE__ */ new Map();
|
|
4341
4767
|
try {
|
|
4342
4768
|
const parsed = JSON.parse(raw);
|
|
@@ -4354,7 +4780,7 @@ async function loadSpacesForWorkspace(workspaceDir) {
|
|
|
4354
4780
|
return out;
|
|
4355
4781
|
}
|
|
4356
4782
|
async function readCoworkMeta(metaPath) {
|
|
4357
|
-
const raw = await
|
|
4783
|
+
const raw = await fs6.readFile(metaPath, "utf8").catch(() => "");
|
|
4358
4784
|
if (!raw)
|
|
4359
4785
|
return {};
|
|
4360
4786
|
try {
|
|
@@ -4390,8 +4816,8 @@ function resolveProject(meta, spaceIdToPath) {
|
|
|
4390
4816
|
cwd: projectPath
|
|
4391
4817
|
};
|
|
4392
4818
|
}
|
|
4393
|
-
async function
|
|
4394
|
-
const raw = await
|
|
4819
|
+
async function readJsonl3(filePath) {
|
|
4820
|
+
const raw = await fs6.readFile(filePath, "utf8");
|
|
4395
4821
|
const out = [];
|
|
4396
4822
|
for (const line of raw.split("\n")) {
|
|
4397
4823
|
const trimmed = line.trim();
|
|
@@ -4527,7 +4953,7 @@ function buildCoworkSubagents(subagentGroups, allLines, sessionStartMs) {
|
|
|
4527
4953
|
}
|
|
4528
4954
|
async function parseCoworkSession(file) {
|
|
4529
4955
|
const [lines, coworkMeta, spaceIdToPath] = await Promise.all([
|
|
4530
|
-
|
|
4956
|
+
readJsonl3(file.auditPath),
|
|
4531
4957
|
readCoworkMeta(file.metaPath),
|
|
4532
4958
|
loadSpacesForWorkspace(file.workspaceDir)
|
|
4533
4959
|
]);
|
|
@@ -4562,24 +4988,24 @@ function cacheKeyMatches(a, b) {
|
|
|
4562
4988
|
return a.auditMtimeMs === b.auditMtimeMs && a.auditSize === b.auditSize && a.metaMtimeMs === b.metaMtimeMs && a.spacesMtimeMs === b.spacesMtimeMs;
|
|
4563
4989
|
}
|
|
4564
4990
|
function clearCoworkCaches() {
|
|
4565
|
-
|
|
4566
|
-
|
|
4991
|
+
metaCache6.clear();
|
|
4992
|
+
detailCache6.clear();
|
|
4567
4993
|
spacesCache.clear();
|
|
4568
4994
|
}
|
|
4569
4995
|
async function listCoworkSessions(opts = {}) {
|
|
4570
4996
|
const root = opts.root ?? DEFAULT_COWORK_ROOT;
|
|
4571
|
-
const files = await
|
|
4997
|
+
const files = await listSessionFiles4(root);
|
|
4572
4998
|
const out = [];
|
|
4573
4999
|
for (const file of files) {
|
|
4574
5000
|
const key = cacheKeyFor(file);
|
|
4575
|
-
const cached =
|
|
5001
|
+
const cached = metaCache6.get(file.auditPath);
|
|
4576
5002
|
if (cached && cacheKeyMatches(cached.key, key)) {
|
|
4577
5003
|
out.push(cached.meta);
|
|
4578
5004
|
continue;
|
|
4579
5005
|
}
|
|
4580
5006
|
try {
|
|
4581
5007
|
const { meta } = await parseCoworkSession(file);
|
|
4582
|
-
|
|
5008
|
+
metaCache6.set(file.auditPath, { meta, key });
|
|
4583
5009
|
out.push(meta);
|
|
4584
5010
|
} catch {
|
|
4585
5011
|
}
|
|
@@ -4591,12 +5017,12 @@ async function listCoworkSessions(opts = {}) {
|
|
|
4591
5017
|
}
|
|
4592
5018
|
async function getCoworkSession(id, opts = {}) {
|
|
4593
5019
|
const root = opts.root ?? DEFAULT_COWORK_ROOT;
|
|
4594
|
-
const files = await
|
|
5020
|
+
const files = await listSessionFiles4(root);
|
|
4595
5021
|
const file = files.find((f) => f.sessionId === id);
|
|
4596
5022
|
if (!file)
|
|
4597
5023
|
return null;
|
|
4598
5024
|
const key = cacheKeyFor(file);
|
|
4599
|
-
const cached =
|
|
5025
|
+
const cached = detailCache6.get(file.auditPath);
|
|
4600
5026
|
if (cached && cacheKeyMatches(cached.key, key))
|
|
4601
5027
|
return cached.detail;
|
|
4602
5028
|
const { meta, events, subagents } = await parseCoworkSession(file);
|
|
@@ -4605,10 +5031,10 @@ async function getCoworkSession(id, opts = {}) {
|
|
|
4605
5031
|
events,
|
|
4606
5032
|
...subagents.length ? { subagents } : {}
|
|
4607
5033
|
};
|
|
4608
|
-
|
|
5034
|
+
detailCache6.set(file.auditPath, { detail, key });
|
|
4609
5035
|
return detail;
|
|
4610
5036
|
}
|
|
4611
|
-
var DEFAULT_COWORK_ROOT, SESSION_ID_RE, spacesCache,
|
|
5037
|
+
var DEFAULT_COWORK_ROOT, SESSION_ID_RE, spacesCache, metaCache6, detailCache6;
|
|
4612
5038
|
var init_cowork = __esm({
|
|
4613
5039
|
"../parser/dist/cowork.js"() {
|
|
4614
5040
|
"use strict";
|
|
@@ -4618,24 +5044,24 @@ var init_cowork = __esm({
|
|
|
4618
5044
|
DEFAULT_COWORK_ROOT = defaultCoworkRoot();
|
|
4619
5045
|
SESSION_ID_RE = /^local_[0-9a-f-]+$/;
|
|
4620
5046
|
spacesCache = /* @__PURE__ */ new Map();
|
|
4621
|
-
|
|
4622
|
-
|
|
5047
|
+
metaCache6 = /* @__PURE__ */ new Map();
|
|
5048
|
+
detailCache6 = /* @__PURE__ */ new Map();
|
|
4623
5049
|
}
|
|
4624
5050
|
});
|
|
4625
5051
|
|
|
4626
5052
|
// ../parser/dist/grok.js
|
|
4627
|
-
import { promises as
|
|
4628
|
-
import
|
|
4629
|
-
import
|
|
5053
|
+
import { promises as fs7 } from "node:fs";
|
|
5054
|
+
import os7 from "node:os";
|
|
5055
|
+
import path7 from "node:path";
|
|
4630
5056
|
function resolveDefaultGrokRoot() {
|
|
4631
|
-
const home = process.env.GROK_HOME ||
|
|
4632
|
-
return
|
|
5057
|
+
const home = process.env.GROK_HOME || path7.join(os7.homedir(), ".grok");
|
|
5058
|
+
return path7.join(home, "sessions");
|
|
4633
5059
|
}
|
|
4634
5060
|
async function safeReaddir5(p) {
|
|
4635
|
-
return
|
|
5061
|
+
return fs7.readdir(p).catch(() => []);
|
|
4636
5062
|
}
|
|
4637
5063
|
async function safeReadJson(p) {
|
|
4638
|
-
const raw = await
|
|
5064
|
+
const raw = await fs7.readFile(p, "utf8").catch(() => null);
|
|
4639
5065
|
if (raw == null)
|
|
4640
5066
|
return null;
|
|
4641
5067
|
try {
|
|
@@ -4645,8 +5071,8 @@ async function safeReadJson(p) {
|
|
|
4645
5071
|
}
|
|
4646
5072
|
}
|
|
4647
5073
|
async function resolveEncodedCwd(groupDir, encoded) {
|
|
4648
|
-
const cwdFile =
|
|
4649
|
-
const fromFile = await
|
|
5074
|
+
const cwdFile = path7.join(groupDir, ".cwd");
|
|
5075
|
+
const fromFile = await fs7.readFile(cwdFile, "utf8").catch(() => null);
|
|
4650
5076
|
if (fromFile && fromFile.trim())
|
|
4651
5077
|
return fromFile.trim();
|
|
4652
5078
|
try {
|
|
@@ -4661,8 +5087,8 @@ async function listSessionDirs(root) {
|
|
|
4661
5087
|
for (const group of groups) {
|
|
4662
5088
|
if (group === "session_search.sqlite" || group.startsWith("."))
|
|
4663
5089
|
continue;
|
|
4664
|
-
const groupDir =
|
|
4665
|
-
const groupStat = await
|
|
5090
|
+
const groupDir = path7.join(root, group);
|
|
5091
|
+
const groupStat = await fs7.stat(groupDir).catch(() => null);
|
|
4666
5092
|
if (!groupStat?.isDirectory())
|
|
4667
5093
|
continue;
|
|
4668
5094
|
const decodedCwd = await resolveEncodedCwd(groupDir, group);
|
|
@@ -4670,14 +5096,14 @@ async function listSessionDirs(root) {
|
|
|
4670
5096
|
for (const entry of entries2) {
|
|
4671
5097
|
if (entry === "prompt_history.jsonl" || entry.startsWith("."))
|
|
4672
5098
|
continue;
|
|
4673
|
-
const dirPath =
|
|
4674
|
-
const summaryPath =
|
|
4675
|
-
const updatesPath =
|
|
4676
|
-
const signalsCandidate =
|
|
5099
|
+
const dirPath = path7.join(groupDir, entry);
|
|
5100
|
+
const summaryPath = path7.join(dirPath, "summary.json");
|
|
5101
|
+
const updatesPath = path7.join(dirPath, "updates.jsonl");
|
|
5102
|
+
const signalsCandidate = path7.join(dirPath, "signals.json");
|
|
4677
5103
|
const [summaryStat, updatesStat, signalsStat] = await Promise.all([
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
|
|
5104
|
+
fs7.stat(summaryPath).catch(() => null),
|
|
5105
|
+
fs7.stat(updatesPath).catch(() => null),
|
|
5106
|
+
fs7.stat(signalsCandidate).catch(() => null)
|
|
4681
5107
|
]);
|
|
4682
5108
|
if (!summaryStat?.isFile())
|
|
4683
5109
|
continue;
|
|
@@ -4698,10 +5124,10 @@ async function listSessionDirs(root) {
|
|
|
4698
5124
|
}
|
|
4699
5125
|
return out;
|
|
4700
5126
|
}
|
|
4701
|
-
function
|
|
5127
|
+
function emptyUsage5() {
|
|
4702
5128
|
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
4703
5129
|
}
|
|
4704
|
-
function
|
|
5130
|
+
function previewOf5(text) {
|
|
4705
5131
|
return text.replace(/\s+/g, " ").trim().slice(0, 200);
|
|
4706
5132
|
}
|
|
4707
5133
|
function truncate5(s, n) {
|
|
@@ -4815,7 +5241,7 @@ function lineTimestampIso(line) {
|
|
|
4815
5241
|
}
|
|
4816
5242
|
return void 0;
|
|
4817
5243
|
}
|
|
4818
|
-
function
|
|
5244
|
+
function computeActiveSegments6(tsMs) {
|
|
4819
5245
|
if (tsMs.length === 0)
|
|
4820
5246
|
return [];
|
|
4821
5247
|
const sorted = [...tsMs].sort((a, b) => a - b);
|
|
@@ -4824,7 +5250,7 @@ function computeActiveSegments5(tsMs) {
|
|
|
4824
5250
|
let segEnd = sorted[0];
|
|
4825
5251
|
for (let i = 1; i < sorted.length; i++) {
|
|
4826
5252
|
const t = sorted[i];
|
|
4827
|
-
if (t - segEnd >
|
|
5253
|
+
if (t - segEnd > IDLE_GAP_MS5) {
|
|
4828
5254
|
out.push({ startMs: segStart, endMs: segEnd });
|
|
4829
5255
|
segStart = t;
|
|
4830
5256
|
}
|
|
@@ -4833,17 +5259,17 @@ function computeActiveSegments5(tsMs) {
|
|
|
4833
5259
|
out.push({ startMs: segStart, endMs: segEnd });
|
|
4834
5260
|
return out;
|
|
4835
5261
|
}
|
|
4836
|
-
async function
|
|
5262
|
+
async function parseSession4(dir) {
|
|
4837
5263
|
const [summary, signals, updatesRaw] = await Promise.all([
|
|
4838
5264
|
safeReadJson(dir.summaryPath),
|
|
4839
5265
|
dir.signalsPath ? safeReadJson(dir.signalsPath) : Promise.resolve(null),
|
|
4840
|
-
|
|
5266
|
+
fs7.readFile(dir.updatesPath, "utf8").catch(() => "")
|
|
4841
5267
|
]);
|
|
4842
5268
|
const sessionId = summary?.info?.id ?? dir.sessionId;
|
|
4843
5269
|
const cwd = summary?.info?.cwd ?? dir.decodedCwd;
|
|
4844
5270
|
let model = summary?.current_model_id ?? signals?.primaryModelId ?? signals?.modelsUsed?.[0];
|
|
4845
5271
|
const events = [];
|
|
4846
|
-
const totalUsage =
|
|
5272
|
+
const totalUsage = emptyUsage5();
|
|
4847
5273
|
if (signals?.contextTokensUsed && signals.contextTokensUsed > 0) {
|
|
4848
5274
|
totalUsage.input = signals.contextTokensUsed;
|
|
4849
5275
|
}
|
|
@@ -4877,7 +5303,7 @@ async function parseSession3(dir) {
|
|
|
4877
5303
|
if (!buf)
|
|
4878
5304
|
return;
|
|
4879
5305
|
const text = buf.texts.join("");
|
|
4880
|
-
const preview =
|
|
5306
|
+
const preview = previewOf5(text);
|
|
4881
5307
|
if (buf.kind === "user") {
|
|
4882
5308
|
const isHidden = !text || isFrameworkInjectedUserInput(text);
|
|
4883
5309
|
if (text && !isHidden) {
|
|
@@ -5037,7 +5463,7 @@ async function parseSession3(dir) {
|
|
|
5037
5463
|
timestamp: ts,
|
|
5038
5464
|
role: "tool-result",
|
|
5039
5465
|
rawType: "grok/tool_result",
|
|
5040
|
-
preview:
|
|
5466
|
+
preview: previewOf5(resultText),
|
|
5041
5467
|
blocks: [
|
|
5042
5468
|
{
|
|
5043
5469
|
type: "tool_result",
|
|
@@ -5086,7 +5512,7 @@ async function parseSession3(dir) {
|
|
|
5086
5512
|
prevMs = ms;
|
|
5087
5513
|
}
|
|
5088
5514
|
}
|
|
5089
|
-
const activeSegments =
|
|
5515
|
+
const activeSegments = computeActiveSegments6(tsMs);
|
|
5090
5516
|
const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
|
|
5091
5517
|
const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
|
|
5092
5518
|
const project = cwd ? resolveProjectIdentity(cwd) : void 0;
|
|
@@ -5095,7 +5521,7 @@ async function parseSession3(dir) {
|
|
|
5095
5521
|
if (!firstUserPreview) {
|
|
5096
5522
|
const title = summary?.generated_title || summary?.session_summary;
|
|
5097
5523
|
if (title)
|
|
5098
|
-
firstUserPreview =
|
|
5524
|
+
firstUserPreview = previewOf5(title);
|
|
5099
5525
|
}
|
|
5100
5526
|
const spawnedAgentCount = await countSubagentChildren(dir.dirPath);
|
|
5101
5527
|
const meta = {
|
|
@@ -5132,38 +5558,38 @@ async function parseSession3(dir) {
|
|
|
5132
5558
|
return { meta, events, sessionKind: summary?.session_kind };
|
|
5133
5559
|
}
|
|
5134
5560
|
async function countSubagentChildren(dirPath) {
|
|
5135
|
-
const subRoot =
|
|
5561
|
+
const subRoot = path7.join(dirPath, "subagents");
|
|
5136
5562
|
const entries2 = await safeReaddir5(subRoot);
|
|
5137
5563
|
let n = 0;
|
|
5138
5564
|
for (const e of entries2) {
|
|
5139
|
-
const st = await
|
|
5565
|
+
const st = await fs7.stat(path7.join(subRoot, e)).catch(() => null);
|
|
5140
5566
|
if (st?.isDirectory())
|
|
5141
5567
|
n += 1;
|
|
5142
5568
|
}
|
|
5143
5569
|
return n;
|
|
5144
5570
|
}
|
|
5145
5571
|
async function loadGrokSubagents(parentDir, parentStartMs) {
|
|
5146
|
-
const subRoot =
|
|
5572
|
+
const subRoot = path7.join(parentDir.dirPath, "subagents");
|
|
5147
5573
|
const entries2 = await safeReaddir5(subRoot);
|
|
5148
|
-
const groupDir =
|
|
5574
|
+
const groupDir = path7.dirname(parentDir.dirPath);
|
|
5149
5575
|
const runs2 = [];
|
|
5150
5576
|
for (const entry of entries2) {
|
|
5151
|
-
const metaPath =
|
|
5577
|
+
const metaPath = path7.join(subRoot, entry, "meta.json");
|
|
5152
5578
|
const meta = await safeReadJson(metaPath);
|
|
5153
5579
|
if (!meta)
|
|
5154
5580
|
continue;
|
|
5155
5581
|
const childId = meta.child_session_id ?? meta.subagent_id ?? entry;
|
|
5156
|
-
const childDir =
|
|
5582
|
+
const childDir = path7.join(groupDir, childId);
|
|
5157
5583
|
const [childSummary, childSignals] = await Promise.all([
|
|
5158
|
-
safeReadJson(
|
|
5159
|
-
safeReadJson(
|
|
5584
|
+
safeReadJson(path7.join(childDir, "summary.json")),
|
|
5585
|
+
safeReadJson(path7.join(childDir, "signals.json"))
|
|
5160
5586
|
]);
|
|
5161
5587
|
const startMs = childSummary?.created_at ? Date.parse(childSummary.created_at) : void 0;
|
|
5162
5588
|
const endIso = childSummary?.last_active_at ?? childSummary?.updated_at;
|
|
5163
5589
|
const endMs = endIso ? Date.parse(endIso) : void 0;
|
|
5164
5590
|
const startOk = startMs !== void 0 && Number.isFinite(startMs) ? startMs : void 0;
|
|
5165
5591
|
const endOk = endMs !== void 0 && Number.isFinite(endMs) ? endMs : void 0;
|
|
5166
|
-
const usage2 =
|
|
5592
|
+
const usage2 = emptyUsage5();
|
|
5167
5593
|
if (childSignals?.contextTokensUsed)
|
|
5168
5594
|
usage2.input = childSignals.contextTokensUsed;
|
|
5169
5595
|
runs2.push({
|
|
@@ -5186,8 +5612,8 @@ async function loadGrokSubagents(parentDir, parentStartMs) {
|
|
|
5186
5612
|
return runs2;
|
|
5187
5613
|
}
|
|
5188
5614
|
function clearGrokCaches() {
|
|
5189
|
-
|
|
5190
|
-
|
|
5615
|
+
metaCache7.clear();
|
|
5616
|
+
detailCache7.clear();
|
|
5191
5617
|
}
|
|
5192
5618
|
async function listGrokSessions(opts = {}) {
|
|
5193
5619
|
const root = opts.root ?? resolveDefaultGrokRoot();
|
|
@@ -5197,16 +5623,16 @@ async function listGrokSessions(opts = {}) {
|
|
|
5197
5623
|
const summaryPeek = await safeReadJson(dir.summaryPath);
|
|
5198
5624
|
if (summaryPeek?.session_kind === "subagent")
|
|
5199
5625
|
continue;
|
|
5200
|
-
const cached =
|
|
5626
|
+
const cached = metaCache7.get(dir.dirPath);
|
|
5201
5627
|
if (cached && cached.mtimeMs === dir.mtimeMs && cached.sizeBytes === dir.sizeBytes) {
|
|
5202
5628
|
out.push(cached.meta);
|
|
5203
5629
|
continue;
|
|
5204
5630
|
}
|
|
5205
5631
|
try {
|
|
5206
|
-
const { meta, sessionKind } = await
|
|
5632
|
+
const { meta, sessionKind } = await parseSession4(dir);
|
|
5207
5633
|
if (sessionKind === "subagent")
|
|
5208
5634
|
continue;
|
|
5209
|
-
|
|
5635
|
+
metaCache7.set(dir.dirPath, {
|
|
5210
5636
|
meta,
|
|
5211
5637
|
mtimeMs: dir.mtimeMs,
|
|
5212
5638
|
sizeBytes: dir.sizeBytes
|
|
@@ -5227,10 +5653,10 @@ async function getGrokSession(id, opts = {}) {
|
|
|
5227
5653
|
if (!chosen) {
|
|
5228
5654
|
for (const dir of dirs) {
|
|
5229
5655
|
try {
|
|
5230
|
-
const { meta: meta2, events: events2 } = await
|
|
5656
|
+
const { meta: meta2, events: events2 } = await parseSession4(dir);
|
|
5231
5657
|
if (meta2.id === id) {
|
|
5232
5658
|
const detail2 = { ...meta2, events: events2 };
|
|
5233
|
-
|
|
5659
|
+
detailCache7.set(dir.dirPath, {
|
|
5234
5660
|
detail: detail2,
|
|
5235
5661
|
mtimeMs: dir.mtimeMs,
|
|
5236
5662
|
sizeBytes: dir.sizeBytes
|
|
@@ -5242,11 +5668,11 @@ async function getGrokSession(id, opts = {}) {
|
|
|
5242
5668
|
}
|
|
5243
5669
|
return null;
|
|
5244
5670
|
}
|
|
5245
|
-
const cached =
|
|
5671
|
+
const cached = detailCache7.get(chosen.dirPath);
|
|
5246
5672
|
if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes) {
|
|
5247
5673
|
return cached.detail;
|
|
5248
5674
|
}
|
|
5249
|
-
const { meta, events } = await
|
|
5675
|
+
const { meta, events } = await parseSession4(chosen);
|
|
5250
5676
|
const parentStartMs = meta.firstTimestamp ? Date.parse(meta.firstTimestamp) : void 0;
|
|
5251
5677
|
const subagents = await loadGrokSubagents(chosen, parentStartMs !== void 0 && Number.isFinite(parentStartMs) ? parentStartMs : void 0);
|
|
5252
5678
|
const detail = {
|
|
@@ -5254,12 +5680,12 @@ async function getGrokSession(id, opts = {}) {
|
|
|
5254
5680
|
events,
|
|
5255
5681
|
...subagents.length > 0 ? { subagents, spawnedAgentCount: subagents.length } : {}
|
|
5256
5682
|
};
|
|
5257
|
-
|
|
5683
|
+
detailCache7.set(chosen.dirPath, {
|
|
5258
5684
|
detail,
|
|
5259
5685
|
mtimeMs: chosen.mtimeMs,
|
|
5260
5686
|
sizeBytes: chosen.sizeBytes
|
|
5261
5687
|
});
|
|
5262
|
-
|
|
5688
|
+
metaCache7.set(chosen.dirPath, {
|
|
5263
5689
|
meta: {
|
|
5264
5690
|
...meta,
|
|
5265
5691
|
...subagents.length > 0 ? { spawnedAgentCount: subagents.length } : {}
|
|
@@ -5275,17 +5701,17 @@ function grokSessionLocalDay(meta) {
|
|
|
5275
5701
|
const ms = Date.parse(meta.firstTimestamp);
|
|
5276
5702
|
return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
|
|
5277
5703
|
}
|
|
5278
|
-
var DEFAULT_GROK_ROOT,
|
|
5704
|
+
var DEFAULT_GROK_ROOT, IDLE_GAP_MS5, metaCache7, detailCache7;
|
|
5279
5705
|
var init_grok = __esm({
|
|
5280
5706
|
"../parser/dist/grok.js"() {
|
|
5281
5707
|
"use strict";
|
|
5282
5708
|
init_analytics();
|
|
5283
5709
|
init_git_project();
|
|
5284
5710
|
init_user_input();
|
|
5285
|
-
DEFAULT_GROK_ROOT =
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5711
|
+
DEFAULT_GROK_ROOT = path7.join(os7.homedir(), ".grok", "sessions");
|
|
5712
|
+
IDLE_GAP_MS5 = 3 * 60 * 1e3;
|
|
5713
|
+
metaCache7 = /* @__PURE__ */ new Map();
|
|
5714
|
+
detailCache7 = /* @__PURE__ */ new Map();
|
|
5289
5715
|
}
|
|
5290
5716
|
});
|
|
5291
5717
|
|
|
@@ -5346,6 +5772,7 @@ var fs_exports = {};
|
|
|
5346
5772
|
__export(fs_exports, {
|
|
5347
5773
|
DEFAULT_ANTIGRAVITY_ROOT: () => DEFAULT_ANTIGRAVITY_ROOT,
|
|
5348
5774
|
DEFAULT_CODEX_ROOT: () => DEFAULT_CODEX_ROOT,
|
|
5775
|
+
DEFAULT_COPILOT_ROOT: () => DEFAULT_COPILOT_ROOT,
|
|
5349
5776
|
DEFAULT_COWORK_ROOT: () => DEFAULT_COWORK_ROOT,
|
|
5350
5777
|
DEFAULT_GEMINI_ROOT: () => DEFAULT_GEMINI_ROOT,
|
|
5351
5778
|
DEFAULT_GROK_ROOT: () => DEFAULT_GROK_ROOT,
|
|
@@ -5362,6 +5789,7 @@ __export(fs_exports, {
|
|
|
5362
5789
|
clearGrokCaches: () => clearGrokCaches,
|
|
5363
5790
|
clearTeamConfig: () => clearTeamConfig,
|
|
5364
5791
|
codexSessionLocalDay: () => codexSessionLocalDay,
|
|
5792
|
+
copilotSessionLocalDay: () => copilotSessionLocalDay,
|
|
5365
5793
|
decodeProjectName: () => decodeProjectName,
|
|
5366
5794
|
findTeamLead: () => findTeamLead,
|
|
5367
5795
|
geminiSessionLocalDay: () => geminiSessionLocalDay,
|
|
@@ -5369,6 +5797,7 @@ __export(fs_exports, {
|
|
|
5369
5797
|
getAntigravitySession: () => getAntigravitySession,
|
|
5370
5798
|
getAnySession: () => getAnySession,
|
|
5371
5799
|
getCodexSession: () => getCodexSession,
|
|
5800
|
+
getCopilotSession: () => getCopilotSession,
|
|
5372
5801
|
getCoworkSession: () => getCoworkSession,
|
|
5373
5802
|
getGeminiSession: () => getGeminiSession,
|
|
5374
5803
|
getGrokSession: () => getGrokSession,
|
|
@@ -5380,6 +5809,7 @@ __export(fs_exports, {
|
|
|
5380
5809
|
listAllSessions: () => listAllSessions,
|
|
5381
5810
|
listAntigravitySessions: () => listAntigravitySessions,
|
|
5382
5811
|
listCodexSessions: () => listCodexSessions,
|
|
5812
|
+
listCopilotSessions: () => listCopilotSessions,
|
|
5383
5813
|
listCoworkSessions: () => listCoworkSessions,
|
|
5384
5814
|
listGeminiSessions: () => listGeminiSessions,
|
|
5385
5815
|
listGrokSessions: () => listGrokSessions,
|
|
@@ -5402,14 +5832,14 @@ __export(fs_exports, {
|
|
|
5402
5832
|
walkJsonlFiles: () => walkJsonlFiles,
|
|
5403
5833
|
writeTeamConfig: () => writeTeamConfig
|
|
5404
5834
|
});
|
|
5405
|
-
import { promises as
|
|
5406
|
-
import
|
|
5407
|
-
import
|
|
5835
|
+
import { promises as fs8, existsSync as existsSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync3, appendFileSync, mkdirSync as mkdirSync3 } from "node:fs";
|
|
5836
|
+
import os8 from "node:os";
|
|
5837
|
+
import path8 from "node:path";
|
|
5408
5838
|
function cclensHome() {
|
|
5409
|
-
return process.env.CCLENS_HOME ||
|
|
5839
|
+
return process.env.CCLENS_HOME || path8.join(os8.homedir(), ".cclens");
|
|
5410
5840
|
}
|
|
5411
5841
|
function cclensPath(...parts) {
|
|
5412
|
-
return
|
|
5842
|
+
return path8.join(cclensHome(), ...parts);
|
|
5413
5843
|
}
|
|
5414
5844
|
function cacheStats() {
|
|
5415
5845
|
return claudeCodeCacheStats();
|
|
@@ -5417,6 +5847,7 @@ function cacheStats() {
|
|
|
5417
5847
|
function clearCaches() {
|
|
5418
5848
|
clearClaudeCodeCaches();
|
|
5419
5849
|
clearCodexCaches();
|
|
5850
|
+
clearCopilotCaches();
|
|
5420
5851
|
clearGeminiCaches();
|
|
5421
5852
|
clearAntigravityCaches();
|
|
5422
5853
|
clearCoworkCaches();
|
|
@@ -5451,7 +5882,7 @@ function usageLogPath() {
|
|
|
5451
5882
|
}
|
|
5452
5883
|
function appendUsageSnapshot(snapshot) {
|
|
5453
5884
|
const p = usageLogPath();
|
|
5454
|
-
mkdirSync3(
|
|
5885
|
+
mkdirSync3(path8.dirname(p), { recursive: true });
|
|
5455
5886
|
appendFileSync(p, JSON.stringify(snapshot) + "\n", "utf8");
|
|
5456
5887
|
}
|
|
5457
5888
|
function pruneUsageAgent(agent) {
|
|
@@ -5467,13 +5898,13 @@ function pruneUsageAgent(agent) {
|
|
|
5467
5898
|
return true;
|
|
5468
5899
|
}
|
|
5469
5900
|
});
|
|
5470
|
-
mkdirSync3(
|
|
5901
|
+
mkdirSync3(path8.dirname(p), { recursive: true });
|
|
5471
5902
|
writeFileSync3(p, kept.join("\n") + (kept.length ? "\n" : ""), "utf8");
|
|
5472
5903
|
}
|
|
5473
5904
|
async function loadUsageByDay(start2, end) {
|
|
5474
5905
|
let raw;
|
|
5475
5906
|
try {
|
|
5476
|
-
raw = await
|
|
5907
|
+
raw = await fs8.readFile(usageLogPath(), "utf8");
|
|
5477
5908
|
} catch {
|
|
5478
5909
|
return { by_day: [] };
|
|
5479
5910
|
}
|
|
@@ -5518,7 +5949,7 @@ async function loadUsageByDay(start2, end) {
|
|
|
5518
5949
|
async function loadCalibrationSnapshots() {
|
|
5519
5950
|
let raw;
|
|
5520
5951
|
try {
|
|
5521
|
-
raw = await
|
|
5952
|
+
raw = await fs8.readFile(usageLogPath(), "utf8");
|
|
5522
5953
|
} catch {
|
|
5523
5954
|
return [];
|
|
5524
5955
|
}
|
|
@@ -5682,7 +6113,7 @@ async function loadCalibrationCurve(tier = "pro-max-20x", root = DEFAULT_ROOT, g
|
|
|
5682
6113
|
]);
|
|
5683
6114
|
return buildCalibrationCurve(events, snapshots, tier, granularityMin);
|
|
5684
6115
|
}
|
|
5685
|
-
var codexSource, geminiSource, antigravitySource, coworkSource, grokSource, agentSources;
|
|
6116
|
+
var codexSource, copilotSource, geminiSource, antigravitySource, coworkSource, grokSource, agentSources;
|
|
5686
6117
|
var init_fs = __esm({
|
|
5687
6118
|
"../parser/dist/fs.js"() {
|
|
5688
6119
|
"use strict";
|
|
@@ -5691,6 +6122,7 @@ var init_fs = __esm({
|
|
|
5691
6122
|
init_calibration();
|
|
5692
6123
|
init_claude_code();
|
|
5693
6124
|
init_codex();
|
|
6125
|
+
init_copilot();
|
|
5694
6126
|
init_gemini();
|
|
5695
6127
|
init_antigravity();
|
|
5696
6128
|
init_cowork();
|
|
@@ -5698,6 +6130,7 @@ var init_fs = __esm({
|
|
|
5698
6130
|
init_claude_code();
|
|
5699
6131
|
init_git_project();
|
|
5700
6132
|
init_codex();
|
|
6133
|
+
init_copilot();
|
|
5701
6134
|
init_gemini();
|
|
5702
6135
|
init_antigravity();
|
|
5703
6136
|
init_cowork();
|
|
@@ -5714,6 +6147,16 @@ var init_fs = __esm({
|
|
|
5714
6147
|
return getCodexSession(id);
|
|
5715
6148
|
}
|
|
5716
6149
|
};
|
|
6150
|
+
copilotSource = {
|
|
6151
|
+
...COPILOT_METADATA,
|
|
6152
|
+
defaultRoot: DEFAULT_COPILOT_ROOT,
|
|
6153
|
+
async listSessions(opts) {
|
|
6154
|
+
return listCopilotSessions(opts);
|
|
6155
|
+
},
|
|
6156
|
+
async getSession(id, opts) {
|
|
6157
|
+
return getCopilotSession(id, opts);
|
|
6158
|
+
}
|
|
6159
|
+
};
|
|
5717
6160
|
geminiSource = {
|
|
5718
6161
|
...GEMINI_METADATA,
|
|
5719
6162
|
defaultRoot: DEFAULT_GEMINI_ROOT,
|
|
@@ -5758,6 +6201,7 @@ var init_fs = __esm({
|
|
|
5758
6201
|
agentSources = [
|
|
5759
6202
|
claudeCodeSource,
|
|
5760
6203
|
codexSource,
|
|
6204
|
+
copilotSource,
|
|
5761
6205
|
geminiSource,
|
|
5762
6206
|
antigravitySource,
|
|
5763
6207
|
coworkSource,
|
|
@@ -5797,9 +6241,9 @@ function onDiskVersion() {
|
|
|
5797
6241
|
try {
|
|
5798
6242
|
const here = dirname3(fileURLToPath(import.meta.url));
|
|
5799
6243
|
const pkg = JSON.parse(readFileSync5(join3(here, "..", "package.json"), "utf8"));
|
|
5800
|
-
return pkg.version ?? "0.16.
|
|
6244
|
+
return pkg.version ?? "0.16.8";
|
|
5801
6245
|
} catch {
|
|
5802
|
-
return "0.16.
|
|
6246
|
+
return "0.16.8";
|
|
5803
6247
|
}
|
|
5804
6248
|
}
|
|
5805
6249
|
function getServerStatus() {
|
|
@@ -5811,7 +6255,7 @@ function getServerStatus() {
|
|
|
5811
6255
|
return { running: false };
|
|
5812
6256
|
}
|
|
5813
6257
|
function isServerStale(status2) {
|
|
5814
|
-
return status2.running === true && status2.version !== "0.16.
|
|
6258
|
+
return status2.running === true && status2.version !== "0.16.8";
|
|
5815
6259
|
}
|
|
5816
6260
|
async function ensureCurrentServer(opts = {}) {
|
|
5817
6261
|
const status2 = getServerStatus();
|
|
@@ -6250,9 +6694,9 @@ Installed: ${PACKAGE_NAME}@${verify.installedVersion} at ${verify.installedPath
|
|
|
6250
6694
|
console.warn(
|
|
6251
6695
|
` \u2022 reinstall in the correct Node env: 'npm install -g ${PACKAGE_NAME}@latest'`
|
|
6252
6696
|
);
|
|
6253
|
-
} else if (verify.installedVersion !== "0.16.
|
|
6697
|
+
} else if (verify.installedVersion !== "0.16.8") {
|
|
6254
6698
|
console.log(
|
|
6255
|
-
` \u2192 This process is still running ${"0.16.
|
|
6699
|
+
` \u2192 This process is still running ${"0.16.8"}. Next invocation will use ${verify.installedVersion}.`
|
|
6256
6700
|
);
|
|
6257
6701
|
}
|
|
6258
6702
|
}
|
|
@@ -6287,14 +6731,14 @@ async function getUpdateAvailability() {
|
|
|
6287
6731
|
if (isDevMode()) return null;
|
|
6288
6732
|
const latest = await fetchLatestVersion();
|
|
6289
6733
|
if (latest === null) return {
|
|
6290
|
-
current: "0.16.
|
|
6734
|
+
current: "0.16.8",
|
|
6291
6735
|
latest: null,
|
|
6292
6736
|
updateAvailable: false
|
|
6293
6737
|
};
|
|
6294
6738
|
return {
|
|
6295
|
-
current: "0.16.
|
|
6739
|
+
current: "0.16.8",
|
|
6296
6740
|
latest,
|
|
6297
|
-
updateAvailable: shouldUpdate("0.16.
|
|
6741
|
+
updateAvailable: shouldUpdate("0.16.8", latest)
|
|
6298
6742
|
};
|
|
6299
6743
|
}
|
|
6300
6744
|
async function checkForUpdate() {
|
|
@@ -6384,7 +6828,7 @@ async function restartServices(state) {
|
|
|
6384
6828
|
}
|
|
6385
6829
|
async function forceUpdate() {
|
|
6386
6830
|
const latest = await fetchLatestVersion();
|
|
6387
|
-
const current = "0.16.
|
|
6831
|
+
const current = "0.16.8";
|
|
6388
6832
|
if (latest === null) {
|
|
6389
6833
|
console.error("Could not reach npm registry. Check your network.");
|
|
6390
6834
|
process.exit(1);
|
|
@@ -6797,7 +7241,7 @@ async function status() {
|
|
|
6797
7241
|
console.log(`Server: running on ${url} (PID ${server.pid}, v${ver})`);
|
|
6798
7242
|
if (isServerStale(server)) {
|
|
6799
7243
|
console.log(
|
|
6800
|
-
` \u26A0 serving stale ${ver} (CLI is ${"0.16.
|
|
7244
|
+
` \u26A0 serving stale ${ver} (CLI is ${"0.16.8"}) \u2014 run 'fleetlens start' to restart on the current version`
|
|
6801
7245
|
);
|
|
6802
7246
|
}
|
|
6803
7247
|
} else {
|
|
@@ -6836,7 +7280,7 @@ async function web(args2) {
|
|
|
6836
7280
|
const open = args2.includes("--open");
|
|
6837
7281
|
const positional = args2.filter((a) => !a.startsWith("--"));
|
|
6838
7282
|
const rawPath = positional[0] ?? "";
|
|
6839
|
-
const
|
|
7283
|
+
const path11 = rawPath.startsWith("/") ? rawPath : rawPath ? `/${rawPath}` : "";
|
|
6840
7284
|
let result;
|
|
6841
7285
|
try {
|
|
6842
7286
|
result = await ensureCurrentServer({});
|
|
@@ -6844,7 +7288,7 @@ async function web(args2) {
|
|
|
6844
7288
|
console.error(`Failed to start: ${err.message}`);
|
|
6845
7289
|
process.exit(1);
|
|
6846
7290
|
}
|
|
6847
|
-
const url = `http://localhost:${result.port}${
|
|
7291
|
+
const url = `http://localhost:${result.port}${path11}`;
|
|
6848
7292
|
if (result.restarted) {
|
|
6849
7293
|
console.log(`fleetlens restarted on http://localhost:${result.port} (PID ${result.pid}) \u2014 replaced stale ${result.previousVersion ?? "unknown"} server`);
|
|
6850
7294
|
}
|
|
@@ -6905,9 +7349,9 @@ function readFromCredentialsFile() {
|
|
|
6905
7349
|
join7(homedir4(), ".claude", ".credentials.json"),
|
|
6906
7350
|
join7(homedir4(), ".config", "claude", "credentials.json")
|
|
6907
7351
|
];
|
|
6908
|
-
for (const
|
|
7352
|
+
for (const path11 of candidates) {
|
|
6909
7353
|
try {
|
|
6910
|
-
const blob = readFileSync10(
|
|
7354
|
+
const blob = readFileSync10(path11, "utf8");
|
|
6911
7355
|
const creds = extractCredentials(blob);
|
|
6912
7356
|
if (creds) return creds;
|
|
6913
7357
|
} catch {
|
|
@@ -7031,13 +7475,13 @@ var init_api = __esm({
|
|
|
7031
7475
|
|
|
7032
7476
|
// src/usage/grok.ts
|
|
7033
7477
|
import { existsSync as existsSync8, readFileSync as readFileSync11 } from "node:fs";
|
|
7034
|
-
import
|
|
7035
|
-
import
|
|
7478
|
+
import os9 from "node:os";
|
|
7479
|
+
import path9 from "node:path";
|
|
7036
7480
|
function grokHome() {
|
|
7037
|
-
return process.env.GROK_HOME ||
|
|
7481
|
+
return process.env.GROK_HOME || path9.join(os9.homedir(), ".grok");
|
|
7038
7482
|
}
|
|
7039
7483
|
function authPath() {
|
|
7040
|
-
return
|
|
7484
|
+
return path9.join(grokHome(), "auth.json");
|
|
7041
7485
|
}
|
|
7042
7486
|
function loadAuthEntry() {
|
|
7043
7487
|
const p = authPath();
|
|
@@ -7253,15 +7697,15 @@ import {
|
|
|
7253
7697
|
readFileSync as readFileSync12,
|
|
7254
7698
|
writeFileSync as writeFileSync6
|
|
7255
7699
|
} from "node:fs";
|
|
7256
|
-
import
|
|
7257
|
-
import
|
|
7700
|
+
import os10 from "node:os";
|
|
7701
|
+
import path10 from "node:path";
|
|
7258
7702
|
function codexHome() {
|
|
7259
7703
|
const env = process.env.CODEX_HOME?.trim();
|
|
7260
7704
|
if (env) return env;
|
|
7261
|
-
return
|
|
7705
|
+
return path10.join(os10.homedir(), ".codex");
|
|
7262
7706
|
}
|
|
7263
7707
|
function authPath2() {
|
|
7264
|
-
return
|
|
7708
|
+
return path10.join(codexHome(), "auth.json");
|
|
7265
7709
|
}
|
|
7266
7710
|
function loadAuth() {
|
|
7267
7711
|
const p = authPath2();
|
|
@@ -7376,7 +7820,7 @@ function authHeaders2(accessToken, accountId) {
|
|
|
7376
7820
|
}
|
|
7377
7821
|
return headers;
|
|
7378
7822
|
}
|
|
7379
|
-
function
|
|
7823
|
+
function numberOf3(v) {
|
|
7380
7824
|
if (typeof v === "number" && Number.isFinite(v)) return v;
|
|
7381
7825
|
if (typeof v === "string" && v.trim()) {
|
|
7382
7826
|
const n = Number(v);
|
|
@@ -7386,21 +7830,21 @@ function numberOf2(v) {
|
|
|
7386
7830
|
}
|
|
7387
7831
|
function windowSeconds(raw) {
|
|
7388
7832
|
if (!raw) return void 0;
|
|
7389
|
-
const sec =
|
|
7833
|
+
const sec = numberOf3(raw.limit_window_seconds);
|
|
7390
7834
|
if (sec !== void 0) return sec;
|
|
7391
|
-
const minutes =
|
|
7835
|
+
const minutes = numberOf3(raw.window_minutes);
|
|
7392
7836
|
if (minutes !== void 0) return minutes * 60;
|
|
7393
7837
|
return void 0;
|
|
7394
7838
|
}
|
|
7395
7839
|
function normalizeWindow2(raw, headerPercent, nowMs) {
|
|
7396
|
-
const used =
|
|
7840
|
+
const used = numberOf3(raw?.used_percent) ?? headerPercent;
|
|
7397
7841
|
if (used === void 0) return null;
|
|
7398
7842
|
let resetsAt = null;
|
|
7399
|
-
const resetUnix =
|
|
7843
|
+
const resetUnix = numberOf3(raw?.reset_at) ?? numberOf3(raw?.resets_at);
|
|
7400
7844
|
if (resetUnix !== void 0) {
|
|
7401
7845
|
resetsAt = new Date(resetUnix * 1e3).toISOString();
|
|
7402
7846
|
} else {
|
|
7403
|
-
const after =
|
|
7847
|
+
const after = numberOf3(raw?.reset_after_seconds);
|
|
7404
7848
|
if (after !== void 0) {
|
|
7405
7849
|
resetsAt = new Date(nowMs + after * 1e3).toISOString();
|
|
7406
7850
|
}
|
|
@@ -7416,8 +7860,8 @@ function parseCodexWhamUsage(body, headers = {}, nowMs = Date.now()) {
|
|
|
7416
7860
|
}
|
|
7417
7861
|
const b = body;
|
|
7418
7862
|
const rateLimit = b.rate_limit && typeof b.rate_limit === "object" ? b.rate_limit : {};
|
|
7419
|
-
const headerPrimary =
|
|
7420
|
-
const headerSecondary =
|
|
7863
|
+
const headerPrimary = numberOf3(headers["x-codex-primary-used-percent"]);
|
|
7864
|
+
const headerSecondary = numberOf3(headers["x-codex-secondary-used-percent"]);
|
|
7421
7865
|
const primary = rateLimit.primary_window && typeof rateLimit.primary_window === "object" ? rateLimit.primary_window : null;
|
|
7422
7866
|
const secondary = rateLimit.secondary_window && typeof rateLimit.secondary_window === "object" ? rateLimit.secondary_window : null;
|
|
7423
7867
|
const candidates = [
|
|
@@ -7533,6 +7977,214 @@ var init_codex2 = __esm({
|
|
|
7533
7977
|
}
|
|
7534
7978
|
});
|
|
7535
7979
|
|
|
7980
|
+
// src/usage/copilot.ts
|
|
7981
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
7982
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
7983
|
+
import { dirname as dirname8, join as join8 } from "node:path";
|
|
7984
|
+
function recordOf2(value) {
|
|
7985
|
+
return typeof value === "object" && value !== null ? value : void 0;
|
|
7986
|
+
}
|
|
7987
|
+
function numberOf4(value) {
|
|
7988
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
7989
|
+
}
|
|
7990
|
+
function clampPercent(value) {
|
|
7991
|
+
return Math.min(100, Math.max(0, value));
|
|
7992
|
+
}
|
|
7993
|
+
function nextCopilotMonthlyReset(nowMs = Date.now()) {
|
|
7994
|
+
const now = new Date(nowMs);
|
|
7995
|
+
return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() + 1, 1)).toISOString();
|
|
7996
|
+
}
|
|
7997
|
+
function quotaResetDate(value, nowMs) {
|
|
7998
|
+
const parsed = typeof value === "string" ? Date.parse(value) : Number.NaN;
|
|
7999
|
+
return Number.isFinite(parsed) && parsed > nowMs + 6e4 ? new Date(parsed).toISOString() : nextCopilotMonthlyReset(nowMs);
|
|
8000
|
+
}
|
|
8001
|
+
function parseCopilotQuota(body, nowMs = Date.now()) {
|
|
8002
|
+
const root = recordOf2(body);
|
|
8003
|
+
const snapshots = recordOf2(root?.quotaSnapshots);
|
|
8004
|
+
if (!snapshots) {
|
|
8005
|
+
throw new CopilotApiError("Copilot quota response missing quotaSnapshots", "parse");
|
|
8006
|
+
}
|
|
8007
|
+
const chat = recordOf2(snapshots.chat);
|
|
8008
|
+
const legacy = recordOf2(snapshots.premium_interactions);
|
|
8009
|
+
const chatLimit = numberOf4(chat?.entitlementRequests);
|
|
8010
|
+
const quota = chat && (chatLimit !== void 0 && chatLimit > 0 || chat.isUnlimitedEntitlement === true) ? chat : legacy;
|
|
8011
|
+
if (!quota) {
|
|
8012
|
+
throw new CopilotApiError("Copilot quota response has no chat allowance", "parse");
|
|
8013
|
+
}
|
|
8014
|
+
const unlimited = quota.isUnlimitedEntitlement === true;
|
|
8015
|
+
const remainingPercent = numberOf4(quota.remainingPercentage);
|
|
8016
|
+
const utilization = unlimited ? null : remainingPercent === void 0 ? null : clampPercent(100 - remainingPercent);
|
|
8017
|
+
const limit = numberOf4(quota.entitlementRequests) ?? null;
|
|
8018
|
+
const used = numberOf4(quota.usedRequests) ?? null;
|
|
8019
|
+
const unit = quota.tokenBasedBilling === true ? "ai-credits" : "premium-requests";
|
|
8020
|
+
return {
|
|
8021
|
+
captured_at: new Date(nowMs).toISOString(),
|
|
8022
|
+
agent: "copilot",
|
|
8023
|
+
five_hour: { utilization: null, resets_at: null },
|
|
8024
|
+
seven_day: { utilization: null, resets_at: null },
|
|
8025
|
+
monthly: {
|
|
8026
|
+
utilization,
|
|
8027
|
+
resets_at: quotaResetDate(quota.resetDate, nowMs)
|
|
8028
|
+
},
|
|
8029
|
+
monthly_quota: {
|
|
8030
|
+
used,
|
|
8031
|
+
limit,
|
|
8032
|
+
remaining: used !== null && limit !== null ? Math.max(0, limit - used) : null,
|
|
8033
|
+
unit,
|
|
8034
|
+
unlimited
|
|
8035
|
+
},
|
|
8036
|
+
seven_day_opus: null,
|
|
8037
|
+
seven_day_sonnet: null,
|
|
8038
|
+
seven_day_oauth_apps: null,
|
|
8039
|
+
seven_day_cowork: null,
|
|
8040
|
+
extra_usage: null,
|
|
8041
|
+
plan_type: unit === "ai-credits" ? "AI credits" : "premium requests"
|
|
8042
|
+
};
|
|
8043
|
+
}
|
|
8044
|
+
function rpcFrame(message) {
|
|
8045
|
+
const body = Buffer.from(JSON.stringify(message), "utf8");
|
|
8046
|
+
return Buffer.concat([
|
|
8047
|
+
Buffer.from(`Content-Length: ${body.length}\r
|
|
8048
|
+
\r
|
|
8049
|
+
`, "ascii"),
|
|
8050
|
+
body
|
|
8051
|
+
]);
|
|
8052
|
+
}
|
|
8053
|
+
function resolveCopilotCliPath() {
|
|
8054
|
+
const configured = process.env.COPILOT_CLI_PATH?.trim();
|
|
8055
|
+
if (configured) return configured;
|
|
8056
|
+
const sibling = join8(dirname8(process.execPath), process.platform === "win32" ? "copilot.cmd" : "copilot");
|
|
8057
|
+
return existsSync10(sibling) ? sibling : process.platform === "win32" ? "copilot.cmd" : "copilot";
|
|
8058
|
+
}
|
|
8059
|
+
async function requestQuota(child) {
|
|
8060
|
+
const decoder = new ContentLengthDecoder();
|
|
8061
|
+
const pending = /* @__PURE__ */ new Map();
|
|
8062
|
+
let nextId = 1;
|
|
8063
|
+
const rejectAll = (error) => {
|
|
8064
|
+
for (const waiter of pending.values()) waiter.reject(error);
|
|
8065
|
+
pending.clear();
|
|
8066
|
+
};
|
|
8067
|
+
child.stdout.on("data", (chunk2) => {
|
|
8068
|
+
try {
|
|
8069
|
+
for (const value of decoder.push(chunk2)) {
|
|
8070
|
+
const message = recordOf2(value);
|
|
8071
|
+
const id = numberOf4(message?.id);
|
|
8072
|
+
if (id === void 0) continue;
|
|
8073
|
+
const waiter = pending.get(id);
|
|
8074
|
+
if (!waiter) continue;
|
|
8075
|
+
pending.delete(id);
|
|
8076
|
+
const rpcError = recordOf2(message?.error);
|
|
8077
|
+
if (rpcError) {
|
|
8078
|
+
waiter.reject(new CopilotApiError(
|
|
8079
|
+
typeof rpcError.message === "string" ? rpcError.message : "Copilot RPC request failed",
|
|
8080
|
+
"protocol"
|
|
8081
|
+
));
|
|
8082
|
+
} else {
|
|
8083
|
+
waiter.resolve(message?.result);
|
|
8084
|
+
}
|
|
8085
|
+
}
|
|
8086
|
+
} catch (error) {
|
|
8087
|
+
rejectAll(error);
|
|
8088
|
+
}
|
|
8089
|
+
});
|
|
8090
|
+
const exited = new Promise((_, reject) => {
|
|
8091
|
+
child.once("error", (error) => {
|
|
8092
|
+
reject(new CopilotApiError(
|
|
8093
|
+
error.message,
|
|
8094
|
+
error.code === "ENOENT" ? "no_cli" : "protocol"
|
|
8095
|
+
));
|
|
8096
|
+
});
|
|
8097
|
+
child.once("exit", (code) => {
|
|
8098
|
+
reject(new CopilotApiError(`Copilot RPC exited before responding (code ${code ?? "unknown"})`, "protocol"));
|
|
8099
|
+
});
|
|
8100
|
+
});
|
|
8101
|
+
const request = (method, params = {}) => {
|
|
8102
|
+
const id = nextId++;
|
|
8103
|
+
const response = new Promise((resolve4, reject) => {
|
|
8104
|
+
pending.set(id, { resolve: resolve4, reject });
|
|
8105
|
+
child.stdin.write(rpcFrame({ jsonrpc: "2.0", id, method, params }));
|
|
8106
|
+
});
|
|
8107
|
+
return Promise.race([response, exited]);
|
|
8108
|
+
};
|
|
8109
|
+
await request("connect", {});
|
|
8110
|
+
return request("account.getQuota", {});
|
|
8111
|
+
}
|
|
8112
|
+
async function fetchCopilotUsage() {
|
|
8113
|
+
const cliPath = resolveCopilotCliPath();
|
|
8114
|
+
const child = spawn3(cliPath, ["--headless", "--no-auto-update", "--stdio", "--log-level", "none"], {
|
|
8115
|
+
cwd: process.cwd(),
|
|
8116
|
+
env: process.env,
|
|
8117
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
8118
|
+
windowsHide: true,
|
|
8119
|
+
shell: process.platform === "win32"
|
|
8120
|
+
});
|
|
8121
|
+
let stderr = "";
|
|
8122
|
+
child.stderr.on("data", (chunk2) => {
|
|
8123
|
+
stderr = (stderr + chunk2.toString("utf8")).slice(-2e3);
|
|
8124
|
+
});
|
|
8125
|
+
const timeout = new Promise((_, reject) => {
|
|
8126
|
+
const handle = setTimeout(() => {
|
|
8127
|
+
reject(new CopilotApiError("Timed out reading Copilot quota", "timeout"));
|
|
8128
|
+
}, RPC_TIMEOUT_MS);
|
|
8129
|
+
handle.unref();
|
|
8130
|
+
});
|
|
8131
|
+
try {
|
|
8132
|
+
const body = await Promise.race([requestQuota(child), timeout]);
|
|
8133
|
+
return parseCopilotQuota(body);
|
|
8134
|
+
} catch (error) {
|
|
8135
|
+
if (error instanceof CopilotApiError) {
|
|
8136
|
+
const message = `${error.message} ${stderr}`.toLowerCase();
|
|
8137
|
+
if (message.includes("not logged") || message.includes("authentication")) {
|
|
8138
|
+
throw new CopilotApiError("Copilot not logged in. Run `copilot login`.", "no_auth");
|
|
8139
|
+
}
|
|
8140
|
+
throw error;
|
|
8141
|
+
}
|
|
8142
|
+
throw new CopilotApiError(error.message, "protocol");
|
|
8143
|
+
} finally {
|
|
8144
|
+
child.kill();
|
|
8145
|
+
}
|
|
8146
|
+
}
|
|
8147
|
+
var RPC_TIMEOUT_MS, CopilotApiError, ContentLengthDecoder;
|
|
8148
|
+
var init_copilot2 = __esm({
|
|
8149
|
+
"src/usage/copilot.ts"() {
|
|
8150
|
+
"use strict";
|
|
8151
|
+
RPC_TIMEOUT_MS = 1e4;
|
|
8152
|
+
CopilotApiError = class extends Error {
|
|
8153
|
+
constructor(message, code) {
|
|
8154
|
+
super(message);
|
|
8155
|
+
this.code = code;
|
|
8156
|
+
}
|
|
8157
|
+
};
|
|
8158
|
+
ContentLengthDecoder = class {
|
|
8159
|
+
buffer = Buffer.alloc(0);
|
|
8160
|
+
push(chunk2) {
|
|
8161
|
+
this.buffer = Buffer.concat([this.buffer, chunk2]);
|
|
8162
|
+
const messages = [];
|
|
8163
|
+
while (true) {
|
|
8164
|
+
const headerEnd = this.buffer.indexOf("\r\n\r\n");
|
|
8165
|
+
if (headerEnd === -1) break;
|
|
8166
|
+
const header = this.buffer.subarray(0, headerEnd).toString("ascii");
|
|
8167
|
+
const match = header.match(/(?:^|\r\n)Content-Length:\s*(\d+)/i);
|
|
8168
|
+
if (!match) {
|
|
8169
|
+
throw new CopilotApiError("Copilot RPC response missing Content-Length", "protocol");
|
|
8170
|
+
}
|
|
8171
|
+
const length = Number(match[1]);
|
|
8172
|
+
const bodyStart = headerEnd + 4;
|
|
8173
|
+
if (this.buffer.length < bodyStart + length) break;
|
|
8174
|
+
const body = this.buffer.subarray(bodyStart, bodyStart + length).toString("utf8");
|
|
8175
|
+
this.buffer = this.buffer.subarray(bodyStart + length);
|
|
8176
|
+
try {
|
|
8177
|
+
messages.push(JSON.parse(body));
|
|
8178
|
+
} catch {
|
|
8179
|
+
throw new CopilotApiError("Copilot RPC returned invalid JSON", "protocol");
|
|
8180
|
+
}
|
|
8181
|
+
}
|
|
8182
|
+
return messages;
|
|
8183
|
+
}
|
|
8184
|
+
};
|
|
8185
|
+
}
|
|
8186
|
+
});
|
|
8187
|
+
|
|
7536
8188
|
// src/usage/format.ts
|
|
7537
8189
|
function formatUsage(snapshot) {
|
|
7538
8190
|
const rows = [
|
|
@@ -7872,6 +8524,51 @@ var usage_exports = {};
|
|
|
7872
8524
|
__export(usage_exports, {
|
|
7873
8525
|
usage: () => usage
|
|
7874
8526
|
});
|
|
8527
|
+
async function saveAuxiliarySnapshots() {
|
|
8528
|
+
let saved = 0;
|
|
8529
|
+
for (const source of agentSources) {
|
|
8530
|
+
if (source.kind === "claude-code" || !source.usagePoller) continue;
|
|
8531
|
+
try {
|
|
8532
|
+
const partial = await source.usagePoller();
|
|
8533
|
+
if (!partial) continue;
|
|
8534
|
+
appendSnapshot(USAGE_LOG2, {
|
|
8535
|
+
...partial,
|
|
8536
|
+
seven_day_opus: null,
|
|
8537
|
+
seven_day_sonnet: null,
|
|
8538
|
+
seven_day_oauth_apps: null,
|
|
8539
|
+
seven_day_cowork: null,
|
|
8540
|
+
extra_usage: null
|
|
8541
|
+
});
|
|
8542
|
+
saved += 1;
|
|
8543
|
+
} catch {
|
|
8544
|
+
}
|
|
8545
|
+
}
|
|
8546
|
+
try {
|
|
8547
|
+
appendSnapshot(USAGE_LOG2, await fetchCodexUsage());
|
|
8548
|
+
saved += 1;
|
|
8549
|
+
} catch (err) {
|
|
8550
|
+
if (!(err instanceof CodexApiError) || err.code !== "no_auth" && err.code !== "api_key_only") {
|
|
8551
|
+
console.warn(`codex usage: ${err.message}`);
|
|
8552
|
+
}
|
|
8553
|
+
}
|
|
8554
|
+
try {
|
|
8555
|
+
appendSnapshot(USAGE_LOG2, await fetchCopilotUsage());
|
|
8556
|
+
saved += 1;
|
|
8557
|
+
} catch (err) {
|
|
8558
|
+
if (!(err instanceof CopilotApiError) || err.code !== "no_cli" && err.code !== "no_auth") {
|
|
8559
|
+
console.warn(`copilot usage: ${err.message}`);
|
|
8560
|
+
}
|
|
8561
|
+
}
|
|
8562
|
+
try {
|
|
8563
|
+
appendSnapshot(USAGE_LOG2, await fetchGrokUsage());
|
|
8564
|
+
saved += 1;
|
|
8565
|
+
} catch (err) {
|
|
8566
|
+
if (!(err instanceof GrokApiError) || err.code !== "no_auth" && err.code !== "not_weekly") {
|
|
8567
|
+
console.warn(`grok usage: ${err.message}`);
|
|
8568
|
+
}
|
|
8569
|
+
}
|
|
8570
|
+
return saved;
|
|
8571
|
+
}
|
|
7875
8572
|
async function usage(args2) {
|
|
7876
8573
|
if (args2.includes("--help") || args2.includes("-h")) {
|
|
7877
8574
|
console.log(`fleetlens usage \u2014 plan utilization snapshot
|
|
@@ -7888,54 +8585,27 @@ Usage:
|
|
|
7888
8585
|
return;
|
|
7889
8586
|
}
|
|
7890
8587
|
const save = args2.includes("--save");
|
|
8588
|
+
let snapshot;
|
|
7891
8589
|
try {
|
|
7892
|
-
|
|
8590
|
+
snapshot = await fetchUsage();
|
|
7893
8591
|
if (save) appendSnapshot(USAGE_LOG2, snapshot);
|
|
7894
8592
|
process.stdout.write(formatUsage(snapshot));
|
|
7895
|
-
if (save) {
|
|
7896
|
-
for (const source of agentSources) {
|
|
7897
|
-
if (source.kind === "claude-code" || !source.usagePoller) continue;
|
|
7898
|
-
try {
|
|
7899
|
-
const partial = await source.usagePoller();
|
|
7900
|
-
if (!partial) continue;
|
|
7901
|
-
appendSnapshot(USAGE_LOG2, {
|
|
7902
|
-
...partial,
|
|
7903
|
-
seven_day_opus: null,
|
|
7904
|
-
seven_day_sonnet: null,
|
|
7905
|
-
seven_day_oauth_apps: null,
|
|
7906
|
-
seven_day_cowork: null,
|
|
7907
|
-
extra_usage: null
|
|
7908
|
-
});
|
|
7909
|
-
} catch {
|
|
7910
|
-
}
|
|
7911
|
-
}
|
|
7912
|
-
try {
|
|
7913
|
-
appendSnapshot(USAGE_LOG2, await fetchCodexUsage());
|
|
7914
|
-
} catch (err) {
|
|
7915
|
-
if (err instanceof CodexApiError && (err.code === "no_auth" || err.code === "api_key_only")) {
|
|
7916
|
-
} else {
|
|
7917
|
-
console.warn(
|
|
7918
|
-
`codex usage: ${err.message}`
|
|
7919
|
-
);
|
|
7920
|
-
}
|
|
7921
|
-
}
|
|
7922
|
-
try {
|
|
7923
|
-
appendSnapshot(USAGE_LOG2, await fetchGrokUsage());
|
|
7924
|
-
} catch (err) {
|
|
7925
|
-
if (err instanceof GrokApiError && err.code === "no_auth") {
|
|
7926
|
-
} else {
|
|
7927
|
-
console.warn(`grok usage: ${err.message}`);
|
|
7928
|
-
}
|
|
7929
|
-
}
|
|
7930
|
-
}
|
|
7931
|
-
process.stdout.write("\n (tip: run with --history for the daily token/cost table)\n");
|
|
7932
8593
|
} catch (err) {
|
|
7933
|
-
if (err instanceof UsageApiError) {
|
|
8594
|
+
if (!save || !(err instanceof UsageApiError)) {
|
|
8595
|
+
if (!(err instanceof UsageApiError)) throw err;
|
|
7934
8596
|
console.error(`Error: ${err.message}`);
|
|
7935
|
-
process.
|
|
8597
|
+
process.exitCode = 1;
|
|
8598
|
+
return;
|
|
7936
8599
|
}
|
|
7937
|
-
|
|
8600
|
+
const saved = await saveAuxiliarySnapshots();
|
|
8601
|
+
if (saved === 0) {
|
|
8602
|
+
console.error(`Error: ${err.message}`);
|
|
8603
|
+
process.exitCode = 1;
|
|
8604
|
+
}
|
|
8605
|
+
return;
|
|
7938
8606
|
}
|
|
8607
|
+
if (save) await saveAuxiliarySnapshots();
|
|
8608
|
+
process.stdout.write("\n (tip: run with --history for the daily token/cost table)\n");
|
|
7939
8609
|
}
|
|
7940
8610
|
var USAGE_LOG2;
|
|
7941
8611
|
var init_usage = __esm({
|
|
@@ -7944,6 +8614,7 @@ var init_usage = __esm({
|
|
|
7944
8614
|
init_api();
|
|
7945
8615
|
init_grok2();
|
|
7946
8616
|
init_codex2();
|
|
8617
|
+
init_copilot2();
|
|
7947
8618
|
init_format();
|
|
7948
8619
|
init_storage();
|
|
7949
8620
|
init_fs();
|
|
@@ -8438,6 +9109,7 @@ __export(dist_exports, {
|
|
|
8438
9109
|
ANTIGRAVITY_METADATA: () => ANTIGRAVITY_METADATA,
|
|
8439
9110
|
CLAUDE_CODE_METADATA: () => CLAUDE_CODE_METADATA,
|
|
8440
9111
|
CODEX_METADATA: () => CODEX_METADATA,
|
|
9112
|
+
COPILOT_METADATA: () => COPILOT_METADATA,
|
|
8441
9113
|
COWORK_METADATA: () => COWORK_METADATA,
|
|
8442
9114
|
GEMINI_METADATA: () => GEMINI_METADATA,
|
|
8443
9115
|
GROK_METADATA: () => GROK_METADATA,
|
|
@@ -8854,7 +9526,7 @@ function closeTurn(t, closed, cwd) {
|
|
|
8854
9526
|
let active = 0;
|
|
8855
9527
|
for (let i = 1; i < ts.length; i++) {
|
|
8856
9528
|
const dt = ts[i] - ts[i - 1];
|
|
8857
|
-
if (dt <
|
|
9529
|
+
if (dt < IDLE_GAP_MS6)
|
|
8858
9530
|
active += dt;
|
|
8859
9531
|
}
|
|
8860
9532
|
closed.push({
|
|
@@ -9051,7 +9723,7 @@ function aggregateDay(dayEvents, _sessionFallbackProject) {
|
|
|
9051
9723
|
let activeMs2 = 0;
|
|
9052
9724
|
for (let i = 1; i < tsSorted.length; i++) {
|
|
9053
9725
|
const dt = tsSorted[i] - tsSorted[i - 1];
|
|
9054
|
-
if (dt <
|
|
9726
|
+
if (dt < IDLE_GAP_MS6)
|
|
9055
9727
|
activeMs2 += dt;
|
|
9056
9728
|
}
|
|
9057
9729
|
const tsSortedStrings = dayEvents.map((e) => e.timestamp).filter((t) => !!t).sort();
|
|
@@ -9238,7 +9910,7 @@ function buildEntries(sessionDetail) {
|
|
|
9238
9910
|
entries2.sort((a, b) => a.local_day.localeCompare(b.local_day));
|
|
9239
9911
|
return entries2;
|
|
9240
9912
|
}
|
|
9241
|
-
var
|
|
9913
|
+
var IDLE_GAP_MS6, INTERRUPT_RE2, PR_TITLE_RE, BASH_CHAIN_SPLIT_RE, SHELL_NOISE, IMAGE_BLOCK_RE;
|
|
9242
9914
|
var init_build = __esm({
|
|
9243
9915
|
"../entries/dist/build.js"() {
|
|
9244
9916
|
"use strict";
|
|
@@ -9246,7 +9918,7 @@ var init_build = __esm({
|
|
|
9246
9918
|
init_types();
|
|
9247
9919
|
init_signals();
|
|
9248
9920
|
init_trivial();
|
|
9249
|
-
|
|
9921
|
+
IDLE_GAP_MS6 = 3 * 60 * 1e3;
|
|
9250
9922
|
INTERRUPT_RE2 = /\[request interrupted|interrupted by user/i;
|
|
9251
9923
|
PR_TITLE_RE = /--title\s+["']([^"']+)["']/;
|
|
9252
9924
|
BASH_CHAIN_SPLIT_RE = /\|\||&&|;|\|/;
|
|
@@ -9275,11 +9947,11 @@ var init_dist2 = __esm({
|
|
|
9275
9947
|
});
|
|
9276
9948
|
|
|
9277
9949
|
// ../entries/dist/digest-fs.js
|
|
9278
|
-
import { readFileSync as readFileSync13, readdirSync, writeFileSync as writeFileSync7, renameSync as renameSync2, chmodSync, mkdirSync as mkdirSync6, existsSync as
|
|
9279
|
-
import { dirname as
|
|
9280
|
-
function parseDigestFile(
|
|
9950
|
+
import { readFileSync as readFileSync13, readdirSync, writeFileSync as writeFileSync7, renameSync as renameSync2, chmodSync, mkdirSync as mkdirSync6, existsSync as existsSync11 } from "node:fs";
|
|
9951
|
+
import { dirname as dirname9, join as join9 } from "node:path";
|
|
9952
|
+
function parseDigestFile(path11, expectedVersion) {
|
|
9281
9953
|
try {
|
|
9282
|
-
const parsed = JSON.parse(readFileSync13(
|
|
9954
|
+
const parsed = JSON.parse(readFileSync13(path11, "utf8"));
|
|
9283
9955
|
if (!parsed || typeof parsed !== "object")
|
|
9284
9956
|
return null;
|
|
9285
9957
|
if (parsed.version !== expectedVersion)
|
|
@@ -9298,24 +9970,24 @@ function digestsDir() {
|
|
|
9298
9970
|
digestsDirCached = envOverride ?? cclensPath("digests");
|
|
9299
9971
|
return digestsDirCached;
|
|
9300
9972
|
}
|
|
9301
|
-
function __setDigestsDirForTest(
|
|
9302
|
-
digestsDirCached =
|
|
9303
|
-
mkdirSync6(
|
|
9304
|
-
mkdirSync6(
|
|
9305
|
-
mkdirSync6(
|
|
9973
|
+
function __setDigestsDirForTest(path11) {
|
|
9974
|
+
digestsDirCached = path11;
|
|
9975
|
+
mkdirSync6(join9(path11, "day"), { recursive: true });
|
|
9976
|
+
mkdirSync6(join9(path11, "week"), { recursive: true });
|
|
9977
|
+
mkdirSync6(join9(path11, "month"), { recursive: true });
|
|
9306
9978
|
}
|
|
9307
9979
|
function dayDigestPath(date) {
|
|
9308
|
-
return
|
|
9980
|
+
return join9(digestsDir(), "day", `${date}.json`);
|
|
9309
9981
|
}
|
|
9310
9982
|
function weekDigestPath(monday) {
|
|
9311
|
-
return
|
|
9983
|
+
return join9(digestsDir(), "week", `${monday}.json`);
|
|
9312
9984
|
}
|
|
9313
9985
|
function monthDigestPath(yearMonth) {
|
|
9314
|
-
return
|
|
9986
|
+
return join9(digestsDir(), "month", `${yearMonth}.json`);
|
|
9315
9987
|
}
|
|
9316
9988
|
function writeDayDigest(digest2) {
|
|
9317
9989
|
const final = dayDigestPath(digest2.key);
|
|
9318
|
-
mkdirSync6(
|
|
9990
|
+
mkdirSync6(dirname9(final), { recursive: true });
|
|
9319
9991
|
const tmp = `${final}.tmp`;
|
|
9320
9992
|
writeFileSync7(tmp, JSON.stringify(digest2, null, 2), "utf8");
|
|
9321
9993
|
if (process.platform !== "win32") {
|
|
@@ -9328,7 +10000,7 @@ function writeDayDigest(digest2) {
|
|
|
9328
10000
|
}
|
|
9329
10001
|
function readDayDigest(date) {
|
|
9330
10002
|
const p = dayDigestPath(date);
|
|
9331
|
-
if (!
|
|
10003
|
+
if (!existsSync11(p))
|
|
9332
10004
|
return null;
|
|
9333
10005
|
return parseDigestFile(p, CURRENT_DAY_DIGEST_SCHEMA_VERSION);
|
|
9334
10006
|
}
|
|
@@ -9351,7 +10023,7 @@ function __clearTodayCacheForTest() {
|
|
|
9351
10023
|
}
|
|
9352
10024
|
function writeWeekDigest(digest2) {
|
|
9353
10025
|
const final = weekDigestPath(digest2.key);
|
|
9354
|
-
mkdirSync6(
|
|
10026
|
+
mkdirSync6(dirname9(final), { recursive: true });
|
|
9355
10027
|
const tmp = `${final}.tmp`;
|
|
9356
10028
|
writeFileSync7(tmp, JSON.stringify(digest2, null, 2), "utf8");
|
|
9357
10029
|
if (process.platform !== "win32") {
|
|
@@ -9364,13 +10036,13 @@ function writeWeekDigest(digest2) {
|
|
|
9364
10036
|
}
|
|
9365
10037
|
function readWeekDigest(monday) {
|
|
9366
10038
|
const p = weekDigestPath(monday);
|
|
9367
|
-
if (!
|
|
10039
|
+
if (!existsSync11(p))
|
|
9368
10040
|
return null;
|
|
9369
10041
|
return parseDigestFile(p, CURRENT_WEEK_DIGEST_SCHEMA_VERSION);
|
|
9370
10042
|
}
|
|
9371
10043
|
function listWeekDigestKeys() {
|
|
9372
|
-
const dir =
|
|
9373
|
-
if (!
|
|
10044
|
+
const dir = join9(digestsDir(), "week");
|
|
10045
|
+
if (!existsSync11(dir))
|
|
9374
10046
|
return [];
|
|
9375
10047
|
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));
|
|
9376
10048
|
}
|
|
@@ -9388,7 +10060,7 @@ function setCurrentWeekDigestInCache(monday, digest2, nowMs) {
|
|
|
9388
10060
|
}
|
|
9389
10061
|
function writeMonthDigest(digest2) {
|
|
9390
10062
|
const final = monthDigestPath(digest2.key);
|
|
9391
|
-
mkdirSync6(
|
|
10063
|
+
mkdirSync6(dirname9(final), { recursive: true });
|
|
9392
10064
|
const tmp = `${final}.tmp`;
|
|
9393
10065
|
writeFileSync7(tmp, JSON.stringify(digest2, null, 2), "utf8");
|
|
9394
10066
|
if (process.platform !== "win32") {
|
|
@@ -9401,13 +10073,13 @@ function writeMonthDigest(digest2) {
|
|
|
9401
10073
|
}
|
|
9402
10074
|
function readMonthDigest(yearMonth) {
|
|
9403
10075
|
const p = monthDigestPath(yearMonth);
|
|
9404
|
-
if (!
|
|
10076
|
+
if (!existsSync11(p))
|
|
9405
10077
|
return null;
|
|
9406
10078
|
return parseDigestFile(p, CURRENT_MONTH_DIGEST_SCHEMA_VERSION);
|
|
9407
10079
|
}
|
|
9408
10080
|
function listMonthDigestKeys() {
|
|
9409
|
-
const dir =
|
|
9410
|
-
if (!
|
|
10081
|
+
const dir = join9(digestsDir(), "month");
|
|
10082
|
+
if (!existsSync11(dir))
|
|
9411
10083
|
return [];
|
|
9412
10084
|
return readdirSync(dir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length)).filter((k) => /^\d{4}-\d{2}$/.test(k));
|
|
9413
10085
|
}
|
|
@@ -9469,9 +10141,9 @@ __export(fs_exports2, {
|
|
|
9469
10141
|
writeMonthDigest: () => writeMonthDigest,
|
|
9470
10142
|
writeWeekDigest: () => writeWeekDigest
|
|
9471
10143
|
});
|
|
9472
|
-
import { readFileSync as readFileSync14, readdirSync as readdirSync2, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, renameSync as renameSync3, existsSync as
|
|
10144
|
+
import { readFileSync as readFileSync14, readdirSync as readdirSync2, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, renameSync as renameSync3, existsSync as existsSync12 } from "node:fs";
|
|
9473
10145
|
import { randomBytes } from "node:crypto";
|
|
9474
|
-
import { join as
|
|
10146
|
+
import { join as join10 } from "node:path";
|
|
9475
10147
|
function entriesDir() {
|
|
9476
10148
|
if (entriesDirCached)
|
|
9477
10149
|
return entriesDirCached;
|
|
@@ -9479,12 +10151,12 @@ function entriesDir() {
|
|
|
9479
10151
|
entriesDirCached = envOverride ?? cclensPath("entries");
|
|
9480
10152
|
return entriesDirCached;
|
|
9481
10153
|
}
|
|
9482
|
-
function __setEntriesDirForTest(
|
|
9483
|
-
entriesDirCached =
|
|
9484
|
-
mkdirSync7(
|
|
10154
|
+
function __setEntriesDirForTest(path11) {
|
|
10155
|
+
entriesDirCached = path11;
|
|
10156
|
+
mkdirSync7(path11, { recursive: true });
|
|
9485
10157
|
}
|
|
9486
10158
|
function pathFor(sessionId, localDay2) {
|
|
9487
|
-
return
|
|
10159
|
+
return join10(entriesDir(), `${entryKey(sessionId, localDay2)}.json`);
|
|
9488
10160
|
}
|
|
9489
10161
|
function tmpPathFor(final) {
|
|
9490
10162
|
return `${final}.tmp.${process.pid}.${randomBytes(4).toString("hex")}`;
|
|
@@ -9528,17 +10200,17 @@ function writeEntryPreservingEnrichment(fresh) {
|
|
|
9528
10200
|
}
|
|
9529
10201
|
function readEntry(sessionId, localDay2) {
|
|
9530
10202
|
const p = pathFor(sessionId, localDay2);
|
|
9531
|
-
if (!
|
|
10203
|
+
if (!existsSync12(p))
|
|
9532
10204
|
return null;
|
|
9533
10205
|
const raw = readFileSync14(p, "utf8");
|
|
9534
10206
|
return JSON.parse(raw);
|
|
9535
10207
|
}
|
|
9536
10208
|
function entryExists(sessionId, localDay2) {
|
|
9537
|
-
return
|
|
10209
|
+
return existsSync12(pathFor(sessionId, localDay2));
|
|
9538
10210
|
}
|
|
9539
10211
|
function listEntryKeys() {
|
|
9540
10212
|
const dir = entriesDir();
|
|
9541
|
-
if (!
|
|
10213
|
+
if (!existsSync12(dir))
|
|
9542
10214
|
return [];
|
|
9543
10215
|
return readdirSync2(dir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length));
|
|
9544
10216
|
}
|
|
@@ -10020,8 +10692,8 @@ var init_parseUtil = __esm({
|
|
|
10020
10692
|
init_errors();
|
|
10021
10693
|
init_en();
|
|
10022
10694
|
makeIssue = (params) => {
|
|
10023
|
-
const { data, path:
|
|
10024
|
-
const fullPath = [...
|
|
10695
|
+
const { data, path: path11, errorMaps, issueData } = params;
|
|
10696
|
+
const fullPath = [...path11, ...issueData.path || []];
|
|
10025
10697
|
const fullIssue = {
|
|
10026
10698
|
...issueData,
|
|
10027
10699
|
path: fullPath
|
|
@@ -10329,11 +11001,11 @@ var init_types3 = __esm({
|
|
|
10329
11001
|
init_parseUtil();
|
|
10330
11002
|
init_util();
|
|
10331
11003
|
ParseInputLazyPath = class {
|
|
10332
|
-
constructor(parent, value,
|
|
11004
|
+
constructor(parent, value, path11, key) {
|
|
10333
11005
|
this._cachedPath = [];
|
|
10334
11006
|
this.parent = parent;
|
|
10335
11007
|
this.data = value;
|
|
10336
|
-
this._path =
|
|
11008
|
+
this._path = path11;
|
|
10337
11009
|
this._key = key;
|
|
10338
11010
|
}
|
|
10339
11011
|
get path() {
|
|
@@ -13817,8 +14489,8 @@ RESPOND WITH ONLY VALID JSON (no prose, no code fence):
|
|
|
13817
14489
|
});
|
|
13818
14490
|
|
|
13819
14491
|
// ../entries/dist/tmux-runner.js
|
|
13820
|
-
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync9, existsSync as
|
|
13821
|
-
import { join as
|
|
14492
|
+
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync9, existsSync as existsSync13, readdirSync as readdirSync3, realpathSync as realpathSync5, readFileSync as readFileSync15, unlinkSync as unlinkSync3, renameSync as renameSync4 } from "node:fs";
|
|
14493
|
+
import { join as join11 } from "node:path";
|
|
13822
14494
|
import { homedir as homedir5 } from "node:os";
|
|
13823
14495
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
13824
14496
|
function which(bin) {
|
|
@@ -13835,13 +14507,13 @@ function tmuxRunnerAvailable() {
|
|
|
13835
14507
|
return { ok: true };
|
|
13836
14508
|
}
|
|
13837
14509
|
function runtimeCwd() {
|
|
13838
|
-
const dir =
|
|
13839
|
-
if (!
|
|
14510
|
+
const dir = join11(homedir5(), ".cclens", "runtime");
|
|
14511
|
+
if (!existsSync13(dir))
|
|
13840
14512
|
mkdirSync8(dir, { recursive: true });
|
|
13841
14513
|
return realpathSync5(dir);
|
|
13842
14514
|
}
|
|
13843
14515
|
function ensureRuntimeCwdTrusted(cwd) {
|
|
13844
|
-
const cfgPath =
|
|
14516
|
+
const cfgPath = join11(homedir5(), ".claude.json");
|
|
13845
14517
|
let cfg;
|
|
13846
14518
|
try {
|
|
13847
14519
|
cfg = JSON.parse(readFileSync15(cfgPath, "utf8"));
|
|
@@ -13886,9 +14558,9 @@ async function runClaudeUnderTmuxImpl(args2) {
|
|
|
13886
14558
|
ensureRuntimeCwdTrusted(cwd);
|
|
13887
14559
|
const runId = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
13888
14560
|
const sessionName = `cclens-${runId}`;
|
|
13889
|
-
const systemFile =
|
|
13890
|
-
const userFile =
|
|
13891
|
-
const wrapper =
|
|
14561
|
+
const systemFile = join11(cwd, `system-${runId}.txt`);
|
|
14562
|
+
const userFile = join11(cwd, `user-${runId}.txt`);
|
|
14563
|
+
const wrapper = join11(cwd, `run-${runId}.sh`);
|
|
13892
14564
|
writeFileSync9(systemFile, args2.systemPrompt);
|
|
13893
14565
|
writeFileSync9(userFile, args2.reminder ? `${args2.userPrompt}
|
|
13894
14566
|
|
|
@@ -13907,10 +14579,10 @@ exec ${shellEscape(claudeBin)} \\
|
|
|
13907
14579
|
"$USR"
|
|
13908
14580
|
`, { mode: 493 });
|
|
13909
14581
|
const existingBefore = snapshotAllTranscripts();
|
|
13910
|
-
const
|
|
13911
|
-
if (
|
|
14582
|
+
const spawn5 = spawnSync2(tmuxBin, ["new-session", "-d", "-s", sessionName, "-x", "140", "-y", "50", "-c", cwd, wrapper], { encoding: "utf8" });
|
|
14583
|
+
if (spawn5.status !== 0) {
|
|
13912
14584
|
cleanup(cwd, runId, tmuxBin, sessionName);
|
|
13913
|
-
throw new TmuxRunError(`tmux new-session failed: ${
|
|
14585
|
+
throw new TmuxRunError(`tmux new-session failed: ${spawn5.stderr.trim()}`);
|
|
13914
14586
|
}
|
|
13915
14587
|
const onAbort = () => {
|
|
13916
14588
|
try {
|
|
@@ -13977,7 +14649,7 @@ function snapshotAllTranscripts() {
|
|
|
13977
14649
|
return out;
|
|
13978
14650
|
}
|
|
13979
14651
|
for (const sub of subs) {
|
|
13980
|
-
const dir =
|
|
14652
|
+
const dir = join11(root, sub);
|
|
13981
14653
|
let files;
|
|
13982
14654
|
try {
|
|
13983
14655
|
files = readdirSync3(dir);
|
|
@@ -13986,15 +14658,15 @@ function snapshotAllTranscripts() {
|
|
|
13986
14658
|
}
|
|
13987
14659
|
for (const f of files) {
|
|
13988
14660
|
if (f.endsWith(".jsonl"))
|
|
13989
|
-
out.add(
|
|
14661
|
+
out.add(join11(dir, f));
|
|
13990
14662
|
}
|
|
13991
14663
|
}
|
|
13992
14664
|
return out;
|
|
13993
14665
|
}
|
|
13994
|
-
function readJsonlCwd(
|
|
14666
|
+
function readJsonlCwd(path11, maxLines = 8) {
|
|
13995
14667
|
let raw;
|
|
13996
14668
|
try {
|
|
13997
|
-
raw = readFileSync15(
|
|
14669
|
+
raw = readFileSync15(path11, "utf8");
|
|
13998
14670
|
} catch {
|
|
13999
14671
|
return void 0;
|
|
14000
14672
|
}
|
|
@@ -14027,7 +14699,7 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
|
|
|
14027
14699
|
subs = [];
|
|
14028
14700
|
}
|
|
14029
14701
|
for (const sub of subs) {
|
|
14030
|
-
const dir =
|
|
14702
|
+
const dir = join11(root, sub);
|
|
14031
14703
|
let files;
|
|
14032
14704
|
try {
|
|
14033
14705
|
files = readdirSync3(dir);
|
|
@@ -14037,7 +14709,7 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
|
|
|
14037
14709
|
for (const f of files) {
|
|
14038
14710
|
if (!f.endsWith(".jsonl"))
|
|
14039
14711
|
continue;
|
|
14040
|
-
const full =
|
|
14712
|
+
const full = join11(dir, f);
|
|
14041
14713
|
if (existingBefore.has(full))
|
|
14042
14714
|
continue;
|
|
14043
14715
|
if (readJsonlCwd(full) === targetCwd)
|
|
@@ -14048,10 +14720,10 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
|
|
|
14048
14720
|
}
|
|
14049
14721
|
throw new TmuxRunError(`timeout waiting for claude to create the session transcript (cwd: ${targetCwd})`);
|
|
14050
14722
|
}
|
|
14051
|
-
function parseTranscript2(
|
|
14723
|
+
function parseTranscript2(path11, defaultModel) {
|
|
14052
14724
|
let raw;
|
|
14053
14725
|
try {
|
|
14054
|
-
raw = readFileSync15(
|
|
14726
|
+
raw = readFileSync15(path11, "utf8");
|
|
14055
14727
|
} catch {
|
|
14056
14728
|
return { assembled: "", inputTokens: 0, outputTokens: 0, modelUsed: defaultModel, done: false };
|
|
14057
14729
|
}
|
|
@@ -14111,7 +14783,7 @@ function cleanup(cwd, runId, tmuxBin, sessionName, transcriptPath) {
|
|
|
14111
14783
|
}
|
|
14112
14784
|
for (const f of [`system-${runId}.txt`, `user-${runId}.txt`, `run-${runId}.sh`]) {
|
|
14113
14785
|
try {
|
|
14114
|
-
unlinkSync3(
|
|
14786
|
+
unlinkSync3(join11(cwd, f));
|
|
14115
14787
|
} catch {
|
|
14116
14788
|
}
|
|
14117
14789
|
}
|
|
@@ -14139,17 +14811,17 @@ var init_tmux_runner = __esm({
|
|
|
14139
14811
|
}
|
|
14140
14812
|
};
|
|
14141
14813
|
mutex = Promise.resolve();
|
|
14142
|
-
PROJECTS_ROOT = () =>
|
|
14814
|
+
PROJECTS_ROOT = () => join11(homedir5(), ".claude", "projects");
|
|
14143
14815
|
}
|
|
14144
14816
|
});
|
|
14145
14817
|
|
|
14146
14818
|
// ../entries/dist/llm-runner.js
|
|
14147
|
-
import { spawn as
|
|
14148
|
-
import { mkdirSync as mkdirSync9, appendFileSync as appendFileSync3, writeFileSync as writeFileSync10, existsSync as
|
|
14149
|
-
import { join as
|
|
14819
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
14820
|
+
import { mkdirSync as mkdirSync9, appendFileSync as appendFileSync3, writeFileSync as writeFileSync10, existsSync as existsSync14 } from "node:fs";
|
|
14821
|
+
import { join as join12 } from "node:path";
|
|
14150
14822
|
import { randomUUID } from "node:crypto";
|
|
14151
14823
|
function ensureRunsDir() {
|
|
14152
|
-
if (!
|
|
14824
|
+
if (!existsSync14(RUNS_DIR)) {
|
|
14153
14825
|
try {
|
|
14154
14826
|
mkdirSync9(RUNS_DIR, { recursive: true });
|
|
14155
14827
|
} catch {
|
|
@@ -14178,17 +14850,17 @@ function newRunId(kind) {
|
|
|
14178
14850
|
return `${ts}_${kind}_${short}`;
|
|
14179
14851
|
}
|
|
14180
14852
|
function tracePath(runId) {
|
|
14181
|
-
return
|
|
14853
|
+
return join12(RUNS_DIR, `${runId}.jsonl`);
|
|
14182
14854
|
}
|
|
14183
|
-
function safeAppend(
|
|
14855
|
+
function safeAppend(path11, line) {
|
|
14184
14856
|
try {
|
|
14185
|
-
appendFileSync3(
|
|
14857
|
+
appendFileSync3(path11, line);
|
|
14186
14858
|
} catch {
|
|
14187
14859
|
}
|
|
14188
14860
|
}
|
|
14189
|
-
function safeWrite(
|
|
14861
|
+
function safeWrite(path11, line) {
|
|
14190
14862
|
try {
|
|
14191
|
-
writeFileSync10(
|
|
14863
|
+
writeFileSync10(path11, line);
|
|
14192
14864
|
} catch {
|
|
14193
14865
|
}
|
|
14194
14866
|
}
|
|
@@ -14321,7 +14993,7 @@ function runClaudePrintMode(args2) {
|
|
|
14321
14993
|
"--append-system-prompt",
|
|
14322
14994
|
args2.systemPrompt
|
|
14323
14995
|
];
|
|
14324
|
-
const proc =
|
|
14996
|
+
const proc = spawn4("claude", claudeArgs, { stdio: ["pipe", "pipe", "pipe"], env: { ...process.env } });
|
|
14325
14997
|
safeAppend(trace, JSON.stringify({ _meta: { type: "spawned", run_id: runId, pid: proc.pid } }) + "\n");
|
|
14326
14998
|
const stdinPayload = args2.reminder ? `${args2.userPrompt}
|
|
14327
14999
|
|
|
@@ -14594,25 +15266,25 @@ var init_enrich2 = __esm({
|
|
|
14594
15266
|
});
|
|
14595
15267
|
|
|
14596
15268
|
// ../entries/dist/budget.js
|
|
14597
|
-
import { appendFileSync as appendFileSync4, readFileSync as readFileSync16, existsSync as
|
|
14598
|
-
import { dirname as
|
|
15269
|
+
import { appendFileSync as appendFileSync4, readFileSync as readFileSync16, existsSync as existsSync15, mkdirSync as mkdirSync10 } from "node:fs";
|
|
15270
|
+
import { dirname as dirname10 } from "node:path";
|
|
14599
15271
|
function spendPath() {
|
|
14600
15272
|
if (spendPathCached)
|
|
14601
15273
|
return spendPathCached;
|
|
14602
15274
|
spendPathCached = cclensPath("llm-spend.jsonl");
|
|
14603
15275
|
return spendPathCached;
|
|
14604
15276
|
}
|
|
14605
|
-
function __setSpendPathForTest(
|
|
14606
|
-
spendPathCached =
|
|
15277
|
+
function __setSpendPathForTest(path11) {
|
|
15278
|
+
spendPathCached = path11;
|
|
14607
15279
|
}
|
|
14608
15280
|
function appendSpend(record) {
|
|
14609
15281
|
const p = spendPath();
|
|
14610
|
-
mkdirSync10(
|
|
15282
|
+
mkdirSync10(dirname10(p), { recursive: true });
|
|
14611
15283
|
appendFileSync4(p, JSON.stringify(record) + "\n", { encoding: "utf8" });
|
|
14612
15284
|
}
|
|
14613
15285
|
function monthToDateSpend(now = /* @__PURE__ */ new Date()) {
|
|
14614
15286
|
const p = spendPath();
|
|
14615
|
-
if (!
|
|
15287
|
+
if (!existsSync15(p))
|
|
14616
15288
|
return 0;
|
|
14617
15289
|
const year = now.getUTCFullYear();
|
|
14618
15290
|
const month2 = now.getUTCMonth();
|
|
@@ -14646,15 +15318,15 @@ var init_budget = __esm({
|
|
|
14646
15318
|
});
|
|
14647
15319
|
|
|
14648
15320
|
// ../entries/dist/pipeline-lock.js
|
|
14649
|
-
import { writeFileSync as writeFileSync11, unlinkSync as unlinkSync4, existsSync as
|
|
15321
|
+
import { writeFileSync as writeFileSync11, unlinkSync as unlinkSync4, existsSync as existsSync16, readFileSync as readFileSync17, statSync as statSync3 } from "node:fs";
|
|
14650
15322
|
function lockPath() {
|
|
14651
15323
|
if (lockPathCached)
|
|
14652
15324
|
return lockPathCached;
|
|
14653
15325
|
lockPathCached = cclensPath("llm-interactive.lock");
|
|
14654
15326
|
return lockPathCached;
|
|
14655
15327
|
}
|
|
14656
|
-
function __setInteractiveLockPathForTest(
|
|
14657
|
-
lockPathCached =
|
|
15328
|
+
function __setInteractiveLockPathForTest(path11) {
|
|
15329
|
+
lockPathCached = path11;
|
|
14658
15330
|
}
|
|
14659
15331
|
function touchLock() {
|
|
14660
15332
|
writeFileSync11(lockPath(), String(process.pid), "utf8");
|
|
@@ -14691,7 +15363,7 @@ function pidAlive(pid) {
|
|
|
14691
15363
|
}
|
|
14692
15364
|
function interactiveLockFresh(nowMs) {
|
|
14693
15365
|
const p = lockPath();
|
|
14694
|
-
if (!
|
|
15366
|
+
if (!existsSync16(p))
|
|
14695
15367
|
return false;
|
|
14696
15368
|
try {
|
|
14697
15369
|
const mtime = statSync3(p).mtimeMs;
|
|
@@ -14803,16 +15475,16 @@ var init_queue = __esm({
|
|
|
14803
15475
|
});
|
|
14804
15476
|
|
|
14805
15477
|
// ../entries/dist/settings.js
|
|
14806
|
-
import { readFileSync as readFileSync18, writeFileSync as writeFileSync12, renameSync as renameSync5, chmodSync as chmodSync2, mkdirSync as mkdirSync11, existsSync as
|
|
14807
|
-
import { dirname as
|
|
15478
|
+
import { readFileSync as readFileSync18, writeFileSync as writeFileSync12, renameSync as renameSync5, chmodSync as chmodSync2, mkdirSync as mkdirSync11, existsSync as existsSync17 } from "node:fs";
|
|
15479
|
+
import { dirname as dirname11 } from "node:path";
|
|
14808
15480
|
function settingsPath() {
|
|
14809
15481
|
if (settingsPathCached)
|
|
14810
15482
|
return settingsPathCached;
|
|
14811
15483
|
settingsPathCached = cclensPath("settings.json");
|
|
14812
15484
|
return settingsPathCached;
|
|
14813
15485
|
}
|
|
14814
|
-
function __setSettingsPathForTest(
|
|
14815
|
-
settingsPathCached =
|
|
15486
|
+
function __setSettingsPathForTest(path11) {
|
|
15487
|
+
settingsPathCached = path11;
|
|
14816
15488
|
}
|
|
14817
15489
|
function toDisk(s) {
|
|
14818
15490
|
return {
|
|
@@ -14839,7 +15511,7 @@ function fromDisk(d) {
|
|
|
14839
15511
|
}
|
|
14840
15512
|
function readSettings() {
|
|
14841
15513
|
const p = settingsPath();
|
|
14842
|
-
if (!
|
|
15514
|
+
if (!existsSync17(p))
|
|
14843
15515
|
return DEFAULT_SETTINGS;
|
|
14844
15516
|
try {
|
|
14845
15517
|
const raw = readFileSync18(p, "utf8");
|
|
@@ -14850,7 +15522,7 @@ function readSettings() {
|
|
|
14850
15522
|
}
|
|
14851
15523
|
function writeSettings(s) {
|
|
14852
15524
|
const p = settingsPath();
|
|
14853
|
-
mkdirSync11(
|
|
15525
|
+
mkdirSync11(dirname11(p), { recursive: true });
|
|
14854
15526
|
const tmp = `${p}.tmp`;
|
|
14855
15527
|
writeFileSync12(tmp, JSON.stringify(toDisk(s), null, 2), { encoding: "utf8" });
|
|
14856
15528
|
if (process.platform !== "win32") {
|
|
@@ -16915,7 +17587,7 @@ function activeMs(timestamps) {
|
|
|
16915
17587
|
let active = 0;
|
|
16916
17588
|
for (let i = 1; i < ts.length; i++) {
|
|
16917
17589
|
const dt = ts[i] - ts[i - 1];
|
|
16918
|
-
if (dt <
|
|
17590
|
+
if (dt < IDLE_GAP_MS7)
|
|
16919
17591
|
active += dt;
|
|
16920
17592
|
}
|
|
16921
17593
|
return active;
|
|
@@ -17086,7 +17758,7 @@ function buildSessionSlice(entry, events, daySignature) {
|
|
|
17086
17758
|
let intEnd = sortedTs[0];
|
|
17087
17759
|
for (let i = 1; i < sortedTs.length; i++) {
|
|
17088
17760
|
const dt = sortedTs[i] - intEnd;
|
|
17089
|
-
if (dt >=
|
|
17761
|
+
if (dt >= IDLE_GAP_MS7) {
|
|
17090
17762
|
intervals.push({
|
|
17091
17763
|
start_min: fmtMin(intStart - sliceStartMs),
|
|
17092
17764
|
end_min: fmtMin(intEnd - sliceStartMs)
|
|
@@ -17483,14 +18155,14 @@ async function generateTopSession(slice, opts = {}) {
|
|
|
17483
18155
|
void lastModel;
|
|
17484
18156
|
}
|
|
17485
18157
|
}
|
|
17486
|
-
var
|
|
18158
|
+
var IDLE_GAP_MS7, 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;
|
|
17487
18159
|
var init_top_sessions = __esm({
|
|
17488
18160
|
"../entries/dist/top-sessions.js"() {
|
|
17489
18161
|
"use strict";
|
|
17490
18162
|
init_zod();
|
|
17491
18163
|
init_signals();
|
|
17492
18164
|
init_llm_runner();
|
|
17493
|
-
|
|
18165
|
+
IDLE_GAP_MS7 = 3 * 60 * 1e3;
|
|
17494
18166
|
LONG_AUTONOMOUS_MIN = 20;
|
|
17495
18167
|
N_USER = 150;
|
|
17496
18168
|
N_FIRST_AGENT = 150;
|
|
@@ -18032,8 +18704,8 @@ var init_digest_month_pipeline = __esm({
|
|
|
18032
18704
|
});
|
|
18033
18705
|
|
|
18034
18706
|
// ../entries/dist/credentials.js
|
|
18035
|
-
import { writeFileSync as writeFileSync13, readFileSync as readFileSync19, renameSync as renameSync6, chmodSync as chmodSync3, mkdirSync as mkdirSync12, existsSync as
|
|
18036
|
-
import { dirname as
|
|
18707
|
+
import { writeFileSync as writeFileSync13, readFileSync as readFileSync19, renameSync as renameSync6, chmodSync as chmodSync3, mkdirSync as mkdirSync12, existsSync as existsSync18, unlinkSync as unlinkSync5 } from "node:fs";
|
|
18708
|
+
import { dirname as dirname12 } from "node:path";
|
|
18037
18709
|
async function fetchZaiUsage(candidate) {
|
|
18038
18710
|
const key = candidate.trim();
|
|
18039
18711
|
if (!key)
|
|
@@ -18103,7 +18775,7 @@ function credentialsPath() {
|
|
|
18103
18775
|
}
|
|
18104
18776
|
function readCredentials() {
|
|
18105
18777
|
const p = credentialsPath();
|
|
18106
|
-
if (!
|
|
18778
|
+
if (!existsSync18(p))
|
|
18107
18779
|
return {};
|
|
18108
18780
|
try {
|
|
18109
18781
|
const raw = readFileSync19(p, "utf8");
|
|
@@ -18129,7 +18801,7 @@ function writeZaiKey(apiKey) {
|
|
|
18129
18801
|
const store = readCredentials();
|
|
18130
18802
|
store.zai = { ...store.zai ?? {}, apiKey };
|
|
18131
18803
|
const p = credentialsPath();
|
|
18132
|
-
mkdirSync12(
|
|
18804
|
+
mkdirSync12(dirname12(p), { recursive: true });
|
|
18133
18805
|
const tmp = `${p}.tmp`;
|
|
18134
18806
|
writeFileSync13(tmp, JSON.stringify(store, null, 2), { encoding: "utf8" });
|
|
18135
18807
|
if (process.platform !== "win32") {
|
|
@@ -18736,9 +19408,9 @@ var menubar_exports = {};
|
|
|
18736
19408
|
__export(menubar_exports, {
|
|
18737
19409
|
menubar: () => menubar
|
|
18738
19410
|
});
|
|
18739
|
-
import { existsSync as
|
|
19411
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync13, cpSync, rmSync as rmSync2, readdirSync as readdirSync4, writeFileSync as writeFileSync14, realpathSync as realpathSync6 } from "node:fs";
|
|
18740
19412
|
import { homedir as homedir6 } from "node:os";
|
|
18741
|
-
import { join as
|
|
19413
|
+
import { join as join13, dirname as dirname13 } from "node:path";
|
|
18742
19414
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
18743
19415
|
import { execFile as execFile2 } from "node:child_process";
|
|
18744
19416
|
import { promisify as promisify2 } from "node:util";
|
|
@@ -18746,8 +19418,8 @@ function isMac2() {
|
|
|
18746
19418
|
return process.platform === "darwin";
|
|
18747
19419
|
}
|
|
18748
19420
|
function bundledAppPath() {
|
|
18749
|
-
const here =
|
|
18750
|
-
return
|
|
19421
|
+
const here = dirname13(fileURLToPath3(import.meta.url));
|
|
19422
|
+
return join13(here, "..", "menubar", APP_BUNDLE);
|
|
18751
19423
|
}
|
|
18752
19424
|
function resolveScriptPath2() {
|
|
18753
19425
|
const argv1 = process.argv[1] ?? "";
|
|
@@ -18768,7 +19440,7 @@ function writeCliLaunchFile() {
|
|
|
18768
19440
|
}
|
|
18769
19441
|
}
|
|
18770
19442
|
function installedAppPath() {
|
|
18771
|
-
return
|
|
19443
|
+
return join13(homedir6(), "Applications", APP_BUNDLE);
|
|
18772
19444
|
}
|
|
18773
19445
|
async function isRunning() {
|
|
18774
19446
|
try {
|
|
@@ -18778,8 +19450,8 @@ async function isRunning() {
|
|
|
18778
19450
|
return false;
|
|
18779
19451
|
}
|
|
18780
19452
|
}
|
|
18781
|
-
async function launchApp(
|
|
18782
|
-
await execFileAsync2("open", ["-a",
|
|
19453
|
+
async function launchApp(path11) {
|
|
19454
|
+
await execFileAsync2("open", ["-a", path11]);
|
|
18783
19455
|
}
|
|
18784
19456
|
async function quitApp() {
|
|
18785
19457
|
await execFileAsync2("osascript", ["-e", `tell application "${BUNDLE_EXEC}" to quit`]).catch(
|
|
@@ -18800,14 +19472,14 @@ async function installMenubar(opts) {
|
|
|
18800
19472
|
return;
|
|
18801
19473
|
}
|
|
18802
19474
|
const src = bundledAppPath();
|
|
18803
|
-
if (!
|
|
19475
|
+
if (!existsSync19(src)) {
|
|
18804
19476
|
console.error(
|
|
18805
19477
|
`Bundled widget not found at ${src}.
|
|
18806
19478
|
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.`
|
|
18807
19479
|
);
|
|
18808
19480
|
process.exit(1);
|
|
18809
19481
|
}
|
|
18810
|
-
const destDir =
|
|
19482
|
+
const destDir = join13(homedir6(), "Applications");
|
|
18811
19483
|
mkdirSync13(destDir, { recursive: true });
|
|
18812
19484
|
const dest = installedAppPath();
|
|
18813
19485
|
if (await isRunning()) {
|
|
@@ -18842,7 +19514,7 @@ async function uninstallMenubar() {
|
|
|
18842
19514
|
await new Promise((r) => setTimeout(r, 300));
|
|
18843
19515
|
}
|
|
18844
19516
|
const dest = installedAppPath();
|
|
18845
|
-
if (
|
|
19517
|
+
if (existsSync19(dest)) {
|
|
18846
19518
|
rmSync2(dest, { recursive: true, force: true });
|
|
18847
19519
|
console.log(`Removed ${dest}`);
|
|
18848
19520
|
} else {
|
|
@@ -18856,7 +19528,7 @@ async function openMenubar() {
|
|
|
18856
19528
|
return;
|
|
18857
19529
|
}
|
|
18858
19530
|
const dest = installedAppPath();
|
|
18859
|
-
if (!
|
|
19531
|
+
if (!existsSync19(dest)) {
|
|
18860
19532
|
console.log("Widget not installed yet. Run `fleetlens menubar install` first.");
|
|
18861
19533
|
return;
|
|
18862
19534
|
}
|
|
@@ -18873,15 +19545,15 @@ async function statusMenubar() {
|
|
|
18873
19545
|
return;
|
|
18874
19546
|
}
|
|
18875
19547
|
const dest = installedAppPath();
|
|
18876
|
-
const installed =
|
|
19548
|
+
const installed = existsSync19(dest);
|
|
18877
19549
|
const running = await isRunning();
|
|
18878
|
-
const bundled =
|
|
19550
|
+
const bundled = existsSync19(bundledAppPath());
|
|
18879
19551
|
console.log(`Menu bar widget: ${installed ? "installed" : "not installed"}${installed ? ` (${dest})` : ""}`);
|
|
18880
19552
|
console.log(`Running: ${running ? "yes" : "no"}`);
|
|
18881
19553
|
console.log(`Bundled in CLI: ${bundled ? "yes" : "no \u2014 this build ships without the widget"}`);
|
|
18882
19554
|
if (installed) {
|
|
18883
19555
|
try {
|
|
18884
|
-
const apps = readdirSync4(
|
|
19556
|
+
const apps = readdirSync4(join13(homedir6(), "Applications"));
|
|
18885
19557
|
const ours = apps.find((a) => a === APP_BUNDLE);
|
|
18886
19558
|
console.log(`App bundle: ${ours ? "present in ~/Applications" : "missing"}`);
|
|
18887
19559
|
} catch {
|
|
@@ -18965,7 +19637,7 @@ var init_config = __esm({
|
|
|
18965
19637
|
|
|
18966
19638
|
// src/perception/build-entries.ts
|
|
18967
19639
|
import { statSync as statSync4, readFileSync as readFileSync20 } from "node:fs";
|
|
18968
|
-
import { basename as basename2, dirname as
|
|
19640
|
+
import { basename as basename2, dirname as dirname14 } from "node:path";
|
|
18969
19641
|
function decodeProjectDirName(projectDir) {
|
|
18970
19642
|
if (projectDir.startsWith("-")) {
|
|
18971
19643
|
return "/" + projectDir.slice(1).replace(/-/g, "/");
|
|
@@ -18985,7 +19657,7 @@ function buildEntriesForFile(filePath) {
|
|
|
18985
19657
|
if (rawLines.length === 0) return null;
|
|
18986
19658
|
const { meta, events } = parseTranscript(rawLines);
|
|
18987
19659
|
const fileName = basename2(filePath);
|
|
18988
|
-
const projectDir = basename2(
|
|
19660
|
+
const projectDir = basename2(dirname14(filePath));
|
|
18989
19661
|
const sessionId = fileName.replace(/\.jsonl$/, "");
|
|
18990
19662
|
const sd = {
|
|
18991
19663
|
...meta,
|
|
@@ -19239,7 +19911,7 @@ function buildIngestPayload(inputs) {
|
|
|
19239
19911
|
return {
|
|
19240
19912
|
ingestId: randomUUID2(),
|
|
19241
19913
|
observedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19242
|
-
cliVersion: "0.16.
|
|
19914
|
+
cliVersion: "0.16.8",
|
|
19243
19915
|
...richRollup || inputs.enrichedExtras || inputs.artifactSignals ? { schemaVersion: RICH_ROLLUP_SCHEMA_VERSION } : {},
|
|
19244
19916
|
...inputs.rollup ? { dailyRollup: inputs.rollup } : {},
|
|
19245
19917
|
...richRollup ? { richRollup } : {},
|
|
@@ -19280,8 +19952,8 @@ var init_push = __esm({
|
|
|
19280
19952
|
});
|
|
19281
19953
|
|
|
19282
19954
|
// src/team/git-remote.ts
|
|
19283
|
-
import { existsSync as
|
|
19284
|
-
import { dirname as
|
|
19955
|
+
import { existsSync as existsSync20, readFileSync as readFileSync21, statSync as statSync5 } from "node:fs";
|
|
19956
|
+
import { dirname as dirname15, isAbsolute as isAbsolute2, join as join14, resolve as resolve2 } from "node:path";
|
|
19285
19957
|
function parseGithubRemote(url) {
|
|
19286
19958
|
const m = url.trim().match(GITHUB_URL_RE);
|
|
19287
19959
|
return m ? `${m[1]}/${m[2]}`.toLowerCase() : null;
|
|
@@ -19301,19 +19973,19 @@ function originUrl2(configText) {
|
|
|
19301
19973
|
return null;
|
|
19302
19974
|
}
|
|
19303
19975
|
function gitConfigPathFor(dir) {
|
|
19304
|
-
const dotGit =
|
|
19976
|
+
const dotGit = join14(dir, ".git");
|
|
19305
19977
|
const st = statSync5(dotGit, { throwIfNoEntry: false });
|
|
19306
19978
|
if (!st) return null;
|
|
19307
|
-
if (st.isDirectory()) return
|
|
19979
|
+
if (st.isDirectory()) return join14(dotGit, "config");
|
|
19308
19980
|
const m = readFileSync21(dotGit, "utf8").match(/^gitdir:\s*(.+)\s*$/m);
|
|
19309
19981
|
if (!m) return null;
|
|
19310
19982
|
const gd = isAbsolute2(m[1]) ? m[1] : resolve2(dir, m[1]);
|
|
19311
|
-
const commondirFile =
|
|
19312
|
-
if (
|
|
19983
|
+
const commondirFile = join14(gd, "commondir");
|
|
19984
|
+
if (existsSync20(commondirFile)) {
|
|
19313
19985
|
const common = readFileSync21(commondirFile, "utf8").trim();
|
|
19314
|
-
return
|
|
19986
|
+
return join14(isAbsolute2(common) ? common : resolve2(gd, common), "config");
|
|
19315
19987
|
}
|
|
19316
|
-
return
|
|
19988
|
+
return join14(gd, "config");
|
|
19317
19989
|
}
|
|
19318
19990
|
function createRepoResolver() {
|
|
19319
19991
|
const cache = /* @__PURE__ */ new Map();
|
|
@@ -19323,14 +19995,14 @@ function createRepoResolver() {
|
|
|
19323
19995
|
if (hit !== void 0) return hit;
|
|
19324
19996
|
let repo = null;
|
|
19325
19997
|
try {
|
|
19326
|
-
for (let d = dir; ; d =
|
|
19998
|
+
for (let d = dir; ; d = dirname15(d)) {
|
|
19327
19999
|
const config = gitConfigPathFor(d);
|
|
19328
|
-
if (config &&
|
|
20000
|
+
if (config && existsSync20(config)) {
|
|
19329
20001
|
const url = originUrl2(readFileSync21(config, "utf8"));
|
|
19330
20002
|
repo = url ? parseGithubRemote(url) : null;
|
|
19331
20003
|
break;
|
|
19332
20004
|
}
|
|
19333
|
-
if (d ===
|
|
20005
|
+
if (d === dirname15(d)) break;
|
|
19334
20006
|
}
|
|
19335
20007
|
} catch {
|
|
19336
20008
|
repo = null;
|
|
@@ -19349,9 +20021,9 @@ var init_git_remote = __esm({
|
|
|
19349
20021
|
|
|
19350
20022
|
// src/team/queue.ts
|
|
19351
20023
|
import { readFileSync as readFileSync22, writeFileSync as writeFileSync15, appendFileSync as appendFileSync5, statSync as statSync6, mkdirSync as mkdirSync14 } from "node:fs";
|
|
19352
|
-
import { dirname as
|
|
20024
|
+
import { dirname as dirname16 } from "node:path";
|
|
19353
20025
|
function enqueuePayload(payload, queuePath = QUEUE_PATH) {
|
|
19354
|
-
mkdirSync14(
|
|
20026
|
+
mkdirSync14(dirname16(queuePath), { recursive: true });
|
|
19355
20027
|
const entry = { payload, enqueuedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
19356
20028
|
appendFileSync5(queuePath, JSON.stringify(entry) + "\n", "utf8");
|
|
19357
20029
|
try {
|
|
@@ -19405,8 +20077,8 @@ var init_queue2 = __esm({
|
|
|
19405
20077
|
});
|
|
19406
20078
|
|
|
19407
20079
|
// src/usage/profile.ts
|
|
19408
|
-
import { existsSync as
|
|
19409
|
-
import { dirname as
|
|
20080
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync15, readFileSync as readFileSync23, writeFileSync as writeFileSync16 } from "node:fs";
|
|
20081
|
+
import { dirname as dirname17 } from "node:path";
|
|
19410
20082
|
function mapRateLimitTier(rateLimitTier) {
|
|
19411
20083
|
switch (rateLimitTier) {
|
|
19412
20084
|
case "default_claude_pro":
|
|
@@ -19446,7 +20118,7 @@ async function fetchProfile(nowMs = Date.now()) {
|
|
|
19446
20118
|
};
|
|
19447
20119
|
}
|
|
19448
20120
|
function readCachedProfile(cachePath) {
|
|
19449
|
-
if (!
|
|
20121
|
+
if (!existsSync21(cachePath)) return null;
|
|
19450
20122
|
try {
|
|
19451
20123
|
const raw = JSON.parse(readFileSync23(cachePath, "utf8"));
|
|
19452
20124
|
if (typeof raw.fetchedAtMs !== "number" || !raw.profile) return null;
|
|
@@ -19456,7 +20128,7 @@ function readCachedProfile(cachePath) {
|
|
|
19456
20128
|
}
|
|
19457
20129
|
}
|
|
19458
20130
|
function writeCachedProfile(cachePath, profile, nowMs = Date.now()) {
|
|
19459
|
-
mkdirSync15(
|
|
20131
|
+
mkdirSync15(dirname17(cachePath), { recursive: true });
|
|
19460
20132
|
writeFileSync16(
|
|
19461
20133
|
cachePath,
|
|
19462
20134
|
JSON.stringify({ fetchedAtMs: nowMs, profile }, null, 2),
|
|
@@ -19670,11 +20342,11 @@ var init_sync_log = __esm({
|
|
|
19670
20342
|
|
|
19671
20343
|
// src/team/last-push.ts
|
|
19672
20344
|
import { writeFileSync as writeFileSync17, unlinkSync as unlinkSync6, mkdirSync as mkdirSync16 } from "node:fs";
|
|
19673
|
-
import { join as
|
|
20345
|
+
import { join as join15 } from "node:path";
|
|
19674
20346
|
function write(record, dir) {
|
|
19675
20347
|
const d = dir ?? cclensHome();
|
|
19676
20348
|
mkdirSync16(d, { recursive: true });
|
|
19677
|
-
writeFileSync17(
|
|
20349
|
+
writeFileSync17(join15(d, LAST_PUSH_FILE), JSON.stringify(record, null, 2), { mode: 384 });
|
|
19678
20350
|
}
|
|
19679
20351
|
function writeLastPushSuccess(payload, dir) {
|
|
19680
20352
|
write({ pushedAt: (/* @__PURE__ */ new Date()).toISOString(), ok: true, payload }, dir);
|
|
@@ -19685,7 +20357,7 @@ function writeLastPushFailure(payload, error, dir) {
|
|
|
19685
20357
|
function clearLastPush(dir) {
|
|
19686
20358
|
const d = dir ?? cclensHome();
|
|
19687
20359
|
try {
|
|
19688
|
-
unlinkSync6(
|
|
20360
|
+
unlinkSync6(join15(d, LAST_PUSH_FILE));
|
|
19689
20361
|
} catch {
|
|
19690
20362
|
}
|
|
19691
20363
|
}
|
|
@@ -19705,25 +20377,25 @@ __export(file_probe_exports, {
|
|
|
19705
20377
|
probeArtifactSignals: () => probeArtifactSignals
|
|
19706
20378
|
});
|
|
19707
20379
|
import { createHash } from "node:crypto";
|
|
19708
|
-
import { existsSync as
|
|
20380
|
+
import { existsSync as existsSync22, readdirSync as readdirSync5, statSync as statSync7 } from "node:fs";
|
|
19709
20381
|
import { homedir as homedir7 } from "node:os";
|
|
19710
|
-
import { join as
|
|
20382
|
+
import { join as join16, relative, resolve as resolve3, sep } from "node:path";
|
|
19711
20383
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
19712
20384
|
function pathHash(relPath) {
|
|
19713
20385
|
return createHash("sha256").update(relPath.split(sep).join("/")).digest("hex").slice(0, 32);
|
|
19714
20386
|
}
|
|
19715
20387
|
function defaultScanRoots(extraRoots = []) {
|
|
19716
20388
|
const roots = [];
|
|
19717
|
-
const home =
|
|
19718
|
-
if (
|
|
20389
|
+
const home = join16(homedir7(), ".claude");
|
|
20390
|
+
if (existsSync22(home)) roots.push({ root: home, label: "user" });
|
|
19719
20391
|
for (const e of extraRoots) {
|
|
19720
20392
|
const r = resolve3(e, ".claude");
|
|
19721
|
-
if (
|
|
20393
|
+
if (existsSync22(r) && r !== home) roots.push({ root: r, label: "project" });
|
|
19722
20394
|
}
|
|
19723
20395
|
return roots;
|
|
19724
20396
|
}
|
|
19725
20397
|
function listMarkdownFiles(dir) {
|
|
19726
|
-
if (!
|
|
20398
|
+
if (!existsSync22(dir)) return [];
|
|
19727
20399
|
const out = [];
|
|
19728
20400
|
let entries2;
|
|
19729
20401
|
try {
|
|
@@ -19733,7 +20405,7 @@ function listMarkdownFiles(dir) {
|
|
|
19733
20405
|
}
|
|
19734
20406
|
for (const name of entries2) {
|
|
19735
20407
|
if (name.startsWith(".")) continue;
|
|
19736
|
-
const full =
|
|
20408
|
+
const full = join16(dir, name);
|
|
19737
20409
|
let stat;
|
|
19738
20410
|
try {
|
|
19739
20411
|
stat = statSync7(full);
|
|
@@ -19753,7 +20425,7 @@ function firstSeenDateOf(file) {
|
|
|
19753
20425
|
const out = execFileSync3(
|
|
19754
20426
|
"git",
|
|
19755
20427
|
["log", "--diff-filter=A", "--follow", "--format=%cs", "--", file],
|
|
19756
|
-
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd:
|
|
20428
|
+
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd: dirname18(file) }
|
|
19757
20429
|
).trim().split("\n").filter(Boolean);
|
|
19758
20430
|
if (out.length > 0) return out[out.length - 1];
|
|
19759
20431
|
} catch {
|
|
@@ -19765,7 +20437,7 @@ function firstSeenDateOf(file) {
|
|
|
19765
20437
|
return todayLocal();
|
|
19766
20438
|
}
|
|
19767
20439
|
}
|
|
19768
|
-
function
|
|
20440
|
+
function dirname18(p) {
|
|
19769
20441
|
const i = p.lastIndexOf(sep);
|
|
19770
20442
|
return i < 0 ? "." : p.slice(0, i);
|
|
19771
20443
|
}
|
|
@@ -19792,8 +20464,8 @@ function todayLocal() {
|
|
|
19792
20464
|
function scanAuthored(roots, subdir, day2) {
|
|
19793
20465
|
const out = [];
|
|
19794
20466
|
for (const r of roots) {
|
|
19795
|
-
const dir =
|
|
19796
|
-
if (!
|
|
20467
|
+
const dir = join16(r.root, subdir);
|
|
20468
|
+
if (!existsSync22(dir)) continue;
|
|
19797
20469
|
for (const f of listMarkdownFiles(dir)) {
|
|
19798
20470
|
const firstSeen = firstSeenDateOf(f);
|
|
19799
20471
|
if (firstSeen !== day2) continue;
|
|
@@ -19806,8 +20478,8 @@ function scanAuthored(roots, subdir, day2) {
|
|
|
19806
20478
|
function scanEdited(roots, day2) {
|
|
19807
20479
|
const out = [];
|
|
19808
20480
|
for (const r of roots) {
|
|
19809
|
-
const dir =
|
|
19810
|
-
if (!
|
|
20481
|
+
const dir = join16(r.root, "skills");
|
|
20482
|
+
if (!existsSync22(dir)) continue;
|
|
19811
20483
|
for (const f of listMarkdownFiles(dir)) {
|
|
19812
20484
|
const firstSeen = firstSeenDateOf(f);
|
|
19813
20485
|
if (firstSeen === day2) continue;
|
|
@@ -19830,16 +20502,16 @@ function claudemdLineDelta(extraRoots, authorEmail, day2) {
|
|
|
19830
20502
|
const candidates = [];
|
|
19831
20503
|
for (const e of extraRoots) {
|
|
19832
20504
|
const f = resolve3(e, "CLAUDE.md");
|
|
19833
|
-
if (
|
|
20505
|
+
if (existsSync22(f)) candidates.push(f);
|
|
19834
20506
|
}
|
|
19835
|
-
const homeClaudeMd =
|
|
19836
|
-
if (
|
|
20507
|
+
const homeClaudeMd = join16(homedir7(), "CLAUDE.md");
|
|
20508
|
+
if (existsSync22(homeClaudeMd)) candidates.push(homeClaudeMd);
|
|
19837
20509
|
for (const file of candidates) {
|
|
19838
20510
|
try {
|
|
19839
20511
|
const out = execFileSync3(
|
|
19840
20512
|
"git",
|
|
19841
20513
|
["log", "--numstat", "--format=COMMIT %cs %ae", "--", file],
|
|
19842
|
-
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd:
|
|
20514
|
+
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd: dirname18(file) }
|
|
19843
20515
|
);
|
|
19844
20516
|
let currentDate = "";
|
|
19845
20517
|
let currentEmail = "";
|
|
@@ -20855,8 +21527,8 @@ __export(runs_exports, {
|
|
|
20855
21527
|
runs: () => runs
|
|
20856
21528
|
});
|
|
20857
21529
|
import { execSync as execSync2 } from "node:child_process";
|
|
20858
|
-
import { existsSync as
|
|
20859
|
-
import { join as
|
|
21530
|
+
import { existsSync as existsSync23, readFileSync as readFileSync26, readdirSync as readdirSync6, statSync as statSync8 } from "node:fs";
|
|
21531
|
+
import { join as join17 } from "node:path";
|
|
20860
21532
|
async function runs(args2) {
|
|
20861
21533
|
const json = args2.includes("--json");
|
|
20862
21534
|
const watch = args2.includes("--watch");
|
|
@@ -20940,7 +21612,7 @@ function listActiveRuns() {
|
|
|
20940
21612
|
return runs2.sort((a, b) => a.elapsed_s - b.elapsed_s);
|
|
20941
21613
|
}
|
|
20942
21614
|
function readSpend(sinceMs) {
|
|
20943
|
-
if (!
|
|
21615
|
+
if (!existsSync23(SPEND_PATH)) return [];
|
|
20944
21616
|
const lines = readFileSync26(SPEND_PATH, "utf-8").split("\n").filter((l) => l.trim());
|
|
20945
21617
|
const out = [];
|
|
20946
21618
|
for (const line of lines) {
|
|
@@ -21062,23 +21734,23 @@ function ageLabel(ms) {
|
|
|
21062
21734
|
return `${Math.floor(ms / 864e5)}d`;
|
|
21063
21735
|
}
|
|
21064
21736
|
function listTraceFiles() {
|
|
21065
|
-
if (!
|
|
21737
|
+
if (!existsSync23(RUNS_DIR2)) return [];
|
|
21066
21738
|
const entries2 = readdirSync6(RUNS_DIR2).filter((f) => f.endsWith(".jsonl"));
|
|
21067
21739
|
return entries2.map((f) => {
|
|
21068
|
-
const
|
|
21069
|
-
const st = statSync8(
|
|
21070
|
-
return { runId: f.replace(/\.jsonl$/, ""), path:
|
|
21740
|
+
const path11 = join17(RUNS_DIR2, f);
|
|
21741
|
+
const st = statSync8(path11);
|
|
21742
|
+
return { runId: f.replace(/\.jsonl$/, ""), path: path11, mtimeMs: st.mtimeMs };
|
|
21071
21743
|
}).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
21072
21744
|
}
|
|
21073
21745
|
function resolveRunId(arg) {
|
|
21074
|
-
if (!
|
|
21746
|
+
if (!existsSync23(RUNS_DIR2)) return null;
|
|
21075
21747
|
if (arg === "latest") {
|
|
21076
21748
|
const all2 = listTraceFiles();
|
|
21077
21749
|
if (all2.length === 0) return null;
|
|
21078
21750
|
return { runId: all2[0].runId, path: all2[0].path };
|
|
21079
21751
|
}
|
|
21080
|
-
const exact =
|
|
21081
|
-
if (
|
|
21752
|
+
const exact = join17(RUNS_DIR2, `${arg}.jsonl`);
|
|
21753
|
+
if (existsSync23(exact)) return { runId: arg, path: exact };
|
|
21082
21754
|
const all = listTraceFiles();
|
|
21083
21755
|
const matches = all.filter((r) => r.runId.includes(arg));
|
|
21084
21756
|
if (matches.length === 1) return { runId: matches[0].runId, path: matches[0].path };
|
|
@@ -21089,8 +21761,8 @@ function resolveRunId(arg) {
|
|
|
21089
21761
|
}
|
|
21090
21762
|
return null;
|
|
21091
21763
|
}
|
|
21092
|
-
function readTrace(
|
|
21093
|
-
return readFileSync26(
|
|
21764
|
+
function readTrace(path11) {
|
|
21765
|
+
return readFileSync26(path11, "utf-8").split("\n").filter((l) => l.trim()).map((l) => {
|
|
21094
21766
|
try {
|
|
21095
21767
|
return JSON.parse(l);
|
|
21096
21768
|
} catch {
|
|
@@ -21102,7 +21774,7 @@ async function inspect(arg, follow, json) {
|
|
|
21102
21774
|
const r = resolveRunId(arg);
|
|
21103
21775
|
if (!r) {
|
|
21104
21776
|
console.error(`run not found: ${arg}`);
|
|
21105
|
-
if (
|
|
21777
|
+
if (existsSync23(RUNS_DIR2)) {
|
|
21106
21778
|
const all = listTraceFiles().slice(0, 5);
|
|
21107
21779
|
if (all.length > 0) {
|
|
21108
21780
|
console.error(`
|
|
@@ -21282,7 +21954,7 @@ async function main() {
|
|
|
21282
21954
|
case "version":
|
|
21283
21955
|
case "--version":
|
|
21284
21956
|
case "-v":
|
|
21285
|
-
console.log(`fleetlens ${"0.16.
|
|
21957
|
+
console.log(`fleetlens ${"0.16.8"}`);
|
|
21286
21958
|
break;
|
|
21287
21959
|
case "help":
|
|
21288
21960
|
case "--help":
|