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/daemon-worker.js
CHANGED
|
@@ -607,7 +607,7 @@ function getAgentMetadata(kind) {
|
|
|
607
607
|
function isAgentKind(s) {
|
|
608
608
|
return typeof s === "string" && KNOWN_AGENT_KINDS.has(s);
|
|
609
609
|
}
|
|
610
|
-
var CLAUDE_CODE_METADATA, CODEX_METADATA, GEMINI_METADATA, ANTIGRAVITY_METADATA, COWORK_METADATA, ZAI_METADATA, GROK_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
|
|
610
|
+
var CLAUDE_CODE_METADATA, CODEX_METADATA, COPILOT_METADATA, GEMINI_METADATA, ANTIGRAVITY_METADATA, COWORK_METADATA, ZAI_METADATA, GROK_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
|
|
611
611
|
var init_agent_metadata = __esm({
|
|
612
612
|
"../parser/dist/agent-metadata.js"() {
|
|
613
613
|
"use strict";
|
|
@@ -625,6 +625,13 @@ var init_agent_metadata = __esm({
|
|
|
625
625
|
accentColor: "rgb(16, 163, 127)",
|
|
626
626
|
iconChar: "\u25C6"
|
|
627
627
|
};
|
|
628
|
+
COPILOT_METADATA = {
|
|
629
|
+
kind: "copilot",
|
|
630
|
+
displayName: "GitHub Copilot CLI",
|
|
631
|
+
shortLabel: "Copilot",
|
|
632
|
+
accentColor: "rgb(137, 87, 229)",
|
|
633
|
+
iconChar: "\u221E"
|
|
634
|
+
};
|
|
628
635
|
GEMINI_METADATA = {
|
|
629
636
|
kind: "gemini",
|
|
630
637
|
displayName: "Gemini CLI",
|
|
@@ -664,6 +671,7 @@ var init_agent_metadata = __esm({
|
|
|
664
671
|
agentMetadata = [
|
|
665
672
|
CLAUDE_CODE_METADATA,
|
|
666
673
|
CODEX_METADATA,
|
|
674
|
+
COPILOT_METADATA,
|
|
667
675
|
GEMINI_METADATA,
|
|
668
676
|
ANTIGRAVITY_METADATA,
|
|
669
677
|
COWORK_METADATA,
|
|
@@ -1525,11 +1533,11 @@ function defaultBranch(commonDir) {
|
|
|
1525
1533
|
}
|
|
1526
1534
|
return void 0;
|
|
1527
1535
|
}
|
|
1528
|
-
function readGitFolder(
|
|
1529
|
-
if (!existsSync(
|
|
1536
|
+
function readGitFolder(path11) {
|
|
1537
|
+
if (!existsSync(path11))
|
|
1530
1538
|
return { exists: false, isWorktree: false };
|
|
1531
1539
|
try {
|
|
1532
|
-
const git = nearestDotGit(realpathOrSelf(
|
|
1540
|
+
const git = nearestDotGit(realpathOrSelf(path11));
|
|
1533
1541
|
if (!git)
|
|
1534
1542
|
return { exists: true, isWorktree: false };
|
|
1535
1543
|
const projectRoot = projectRootFromCommonDir(git.commonDir);
|
|
@@ -3311,24 +3319,442 @@ var init_codex = __esm({
|
|
|
3311
3319
|
}
|
|
3312
3320
|
});
|
|
3313
3321
|
|
|
3314
|
-
// ../parser/dist/
|
|
3322
|
+
// ../parser/dist/copilot.js
|
|
3315
3323
|
import { promises as fs3 } from "node:fs";
|
|
3316
3324
|
import os3 from "node:os";
|
|
3317
3325
|
import path3 from "node:path";
|
|
3318
|
-
|
|
3319
|
-
return
|
|
3326
|
+
function recordOf(value) {
|
|
3327
|
+
return typeof value === "object" && value !== null ? value : void 0;
|
|
3328
|
+
}
|
|
3329
|
+
function stringOf(value) {
|
|
3330
|
+
return typeof value === "string" ? value : void 0;
|
|
3331
|
+
}
|
|
3332
|
+
function numberOf2(value) {
|
|
3333
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
3334
|
+
}
|
|
3335
|
+
function emptyUsage2() {
|
|
3336
|
+
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
3337
|
+
}
|
|
3338
|
+
function previewOf2(value) {
|
|
3339
|
+
const text = typeof value === "string" ? value : JSON.stringify(value ?? "");
|
|
3340
|
+
return text.replace(/\s+/g, " ").trim().slice(0, 200);
|
|
3341
|
+
}
|
|
3342
|
+
function tokenCount(details, key) {
|
|
3343
|
+
return numberOf2(recordOf(details?.[key])?.tokenCount);
|
|
3344
|
+
}
|
|
3345
|
+
function syntheticProjectDir(cwd) {
|
|
3346
|
+
return cwd ? cwd.replace(/^\//, "-").replace(/\//g, "-") : "(unknown)";
|
|
3320
3347
|
}
|
|
3321
3348
|
async function listSessionFiles(root) {
|
|
3349
|
+
const entries = await fs3.readdir(root, { withFileTypes: true }).catch(() => []);
|
|
3350
|
+
const out = [];
|
|
3351
|
+
for (const entry of entries) {
|
|
3352
|
+
if (!entry.isDirectory())
|
|
3353
|
+
continue;
|
|
3354
|
+
const filePath = path3.join(root, entry.name, "events.jsonl");
|
|
3355
|
+
const stat = await fs3.stat(filePath).catch(() => null);
|
|
3356
|
+
if (!stat?.isFile())
|
|
3357
|
+
continue;
|
|
3358
|
+
out.push({
|
|
3359
|
+
filePath,
|
|
3360
|
+
sessionId: entry.name,
|
|
3361
|
+
mtimeMs: stat.mtimeMs,
|
|
3362
|
+
sizeBytes: stat.size
|
|
3363
|
+
});
|
|
3364
|
+
}
|
|
3365
|
+
return out;
|
|
3366
|
+
}
|
|
3367
|
+
async function readJsonl2(filePath) {
|
|
3368
|
+
const raw = await fs3.readFile(filePath, "utf8");
|
|
3369
|
+
const out = [];
|
|
3370
|
+
for (const line of raw.split("\n")) {
|
|
3371
|
+
const trimmed = line.trim();
|
|
3372
|
+
if (!trimmed)
|
|
3373
|
+
continue;
|
|
3374
|
+
try {
|
|
3375
|
+
out.push(JSON.parse(trimmed));
|
|
3376
|
+
} catch {
|
|
3377
|
+
}
|
|
3378
|
+
}
|
|
3379
|
+
return out;
|
|
3380
|
+
}
|
|
3381
|
+
function computeActiveSegments3(timestamps) {
|
|
3382
|
+
const sorted = [...new Set(timestamps)].sort((a, b) => a - b);
|
|
3383
|
+
if (sorted.length === 0)
|
|
3384
|
+
return [];
|
|
3385
|
+
const segments = [];
|
|
3386
|
+
let start = sorted[0];
|
|
3387
|
+
let end = start;
|
|
3388
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
3389
|
+
const next = sorted[i];
|
|
3390
|
+
if (next - end > IDLE_GAP_MS2) {
|
|
3391
|
+
segments.push({ startMs: start, endMs: end });
|
|
3392
|
+
start = next;
|
|
3393
|
+
}
|
|
3394
|
+
end = next;
|
|
3395
|
+
}
|
|
3396
|
+
segments.push({ startMs: start, endMs: end });
|
|
3397
|
+
return segments;
|
|
3398
|
+
}
|
|
3399
|
+
function parseSession(file, lines) {
|
|
3400
|
+
const records = lines.map(recordOf).filter((line) => line !== void 0);
|
|
3401
|
+
const executionCallIds = /* @__PURE__ */ new Set();
|
|
3402
|
+
for (const record of records) {
|
|
3403
|
+
if (record.type !== "tool.execution_start")
|
|
3404
|
+
continue;
|
|
3405
|
+
const callId = stringOf(recordOf(record.data)?.toolCallId);
|
|
3406
|
+
if (callId)
|
|
3407
|
+
executionCallIds.add(callId);
|
|
3408
|
+
}
|
|
3409
|
+
const events = [];
|
|
3410
|
+
const timestamps = [];
|
|
3411
|
+
const totalUsage = emptyUsage2();
|
|
3412
|
+
let firstMs;
|
|
3413
|
+
let lastMs;
|
|
3414
|
+
let cwd;
|
|
3415
|
+
let repository;
|
|
3416
|
+
let gitBranch;
|
|
3417
|
+
let model;
|
|
3418
|
+
let firstUserPreview;
|
|
3419
|
+
let lastUserPreview;
|
|
3420
|
+
let lastAgentPreview;
|
|
3421
|
+
let toolCallCount = 0;
|
|
3422
|
+
let turnCount = 0;
|
|
3423
|
+
let observedOutput = 0;
|
|
3424
|
+
let sawShutdown = false;
|
|
3425
|
+
let linesAdded;
|
|
3426
|
+
let linesRemoved;
|
|
3427
|
+
let filesEdited;
|
|
3428
|
+
let idx = 0;
|
|
3429
|
+
function push(event) {
|
|
3430
|
+
events.push({ index: idx++, ...event });
|
|
3431
|
+
}
|
|
3432
|
+
for (const obj of records) {
|
|
3433
|
+
const type = stringOf(obj.type) ?? "";
|
|
3434
|
+
const data = recordOf(obj.data) ?? {};
|
|
3435
|
+
const timestamp = stringOf(obj.timestamp);
|
|
3436
|
+
if (timestamp) {
|
|
3437
|
+
const ms = Date.parse(timestamp);
|
|
3438
|
+
if (Number.isFinite(ms)) {
|
|
3439
|
+
timestamps.push(ms);
|
|
3440
|
+
firstMs = firstMs === void 0 ? ms : Math.min(firstMs, ms);
|
|
3441
|
+
lastMs = lastMs === void 0 ? ms : Math.max(lastMs, ms);
|
|
3442
|
+
}
|
|
3443
|
+
}
|
|
3444
|
+
if (type === "session.start") {
|
|
3445
|
+
const context = recordOf(data.context);
|
|
3446
|
+
cwd = stringOf(context?.cwd) ?? cwd;
|
|
3447
|
+
repository = stringOf(context?.repository) ?? repository;
|
|
3448
|
+
gitBranch = stringOf(context?.branch) ?? gitBranch;
|
|
3449
|
+
push({
|
|
3450
|
+
timestamp,
|
|
3451
|
+
role: "meta",
|
|
3452
|
+
rawType: type,
|
|
3453
|
+
preview: "Copilot session started",
|
|
3454
|
+
blocks: [],
|
|
3455
|
+
raw: obj
|
|
3456
|
+
});
|
|
3457
|
+
continue;
|
|
3458
|
+
}
|
|
3459
|
+
if (type === "session.model_change") {
|
|
3460
|
+
const selected = stringOf(data.newModel);
|
|
3461
|
+
if (selected && selected !== "auto")
|
|
3462
|
+
model = selected;
|
|
3463
|
+
} else if (type === "session.auto_mode_resolved") {
|
|
3464
|
+
model = stringOf(data.chosenModel) ?? model;
|
|
3465
|
+
} else if (type === "assistant.turn_start" || type === "assistant.message") {
|
|
3466
|
+
model = stringOf(data.model) ?? model;
|
|
3467
|
+
}
|
|
3468
|
+
if (type === "system.message") {
|
|
3469
|
+
push({
|
|
3470
|
+
timestamp,
|
|
3471
|
+
role: "system",
|
|
3472
|
+
rawType: type,
|
|
3473
|
+
preview: "Copilot system instructions",
|
|
3474
|
+
blocks: [],
|
|
3475
|
+
raw: obj
|
|
3476
|
+
});
|
|
3477
|
+
continue;
|
|
3478
|
+
}
|
|
3479
|
+
if (type === "user.message") {
|
|
3480
|
+
const text = stringOf(data.content) ?? "";
|
|
3481
|
+
const preview = previewOf2(text);
|
|
3482
|
+
if (text && !isFrameworkInjectedUserInput(text)) {
|
|
3483
|
+
firstUserPreview ??= preview;
|
|
3484
|
+
lastUserPreview = preview;
|
|
3485
|
+
turnCount += 1;
|
|
3486
|
+
}
|
|
3487
|
+
push({
|
|
3488
|
+
timestamp,
|
|
3489
|
+
role: "user",
|
|
3490
|
+
rawType: type,
|
|
3491
|
+
preview,
|
|
3492
|
+
blocks: text ? [{ type: "text", text }] : [],
|
|
3493
|
+
raw: obj
|
|
3494
|
+
});
|
|
3495
|
+
continue;
|
|
3496
|
+
}
|
|
3497
|
+
if (type === "assistant.message") {
|
|
3498
|
+
const text = stringOf(data.content) ?? "";
|
|
3499
|
+
const outputTokens = numberOf2(data.outputTokens) ?? 0;
|
|
3500
|
+
observedOutput += outputTokens;
|
|
3501
|
+
if (text) {
|
|
3502
|
+
const preview = previewOf2(text);
|
|
3503
|
+
lastAgentPreview = preview;
|
|
3504
|
+
push({
|
|
3505
|
+
timestamp,
|
|
3506
|
+
role: "agent",
|
|
3507
|
+
rawType: type,
|
|
3508
|
+
messageId: stringOf(data.messageId),
|
|
3509
|
+
preview,
|
|
3510
|
+
blocks: [{ type: "text", text }],
|
|
3511
|
+
model,
|
|
3512
|
+
raw: obj
|
|
3513
|
+
});
|
|
3514
|
+
}
|
|
3515
|
+
const requests = Array.isArray(data.toolRequests) ? data.toolRequests : [];
|
|
3516
|
+
for (const requestValue of requests) {
|
|
3517
|
+
const request = recordOf(requestValue);
|
|
3518
|
+
if (!request)
|
|
3519
|
+
continue;
|
|
3520
|
+
const callId = stringOf(request.toolCallId);
|
|
3521
|
+
if (callId && executionCallIds.has(callId))
|
|
3522
|
+
continue;
|
|
3523
|
+
const name = stringOf(request.name) ?? "(unknown)";
|
|
3524
|
+
const input = recordOf(request.arguments) ?? request.arguments ?? null;
|
|
3525
|
+
toolCallCount += 1;
|
|
3526
|
+
push({
|
|
3527
|
+
timestamp,
|
|
3528
|
+
role: "tool-call",
|
|
3529
|
+
rawType: "assistant.message/tool_request",
|
|
3530
|
+
preview: `${name}(${previewOf2(input).slice(0, 80)})`,
|
|
3531
|
+
blocks: [{ type: "tool_use", id: callId ?? `copilot-${idx}`, name, input }],
|
|
3532
|
+
toolName: name,
|
|
3533
|
+
toolUseId: callId,
|
|
3534
|
+
model,
|
|
3535
|
+
raw: obj
|
|
3536
|
+
});
|
|
3537
|
+
}
|
|
3538
|
+
continue;
|
|
3539
|
+
}
|
|
3540
|
+
if (type === "tool.execution_start") {
|
|
3541
|
+
const callId = stringOf(data.toolCallId);
|
|
3542
|
+
const name = stringOf(data.toolName) ?? "(unknown)";
|
|
3543
|
+
const input = data.arguments ?? null;
|
|
3544
|
+
toolCallCount += 1;
|
|
3545
|
+
push({
|
|
3546
|
+
timestamp,
|
|
3547
|
+
role: "tool-call",
|
|
3548
|
+
rawType: type,
|
|
3549
|
+
preview: `${name}(${previewOf2(input).slice(0, 80)})`,
|
|
3550
|
+
blocks: [{ type: "tool_use", id: callId ?? `copilot-${idx}`, name, input }],
|
|
3551
|
+
toolName: name,
|
|
3552
|
+
toolUseId: callId,
|
|
3553
|
+
model: stringOf(data.model) ?? model,
|
|
3554
|
+
raw: obj
|
|
3555
|
+
});
|
|
3556
|
+
continue;
|
|
3557
|
+
}
|
|
3558
|
+
if (type === "tool.execution_complete") {
|
|
3559
|
+
const callId = stringOf(data.toolCallId);
|
|
3560
|
+
const resultRecord = recordOf(data.result);
|
|
3561
|
+
const result = resultRecord && "content" in resultRecord ? resultRecord.content : data.result;
|
|
3562
|
+
const success = data.success !== false;
|
|
3563
|
+
push({
|
|
3564
|
+
timestamp,
|
|
3565
|
+
role: "tool-result",
|
|
3566
|
+
rawType: type,
|
|
3567
|
+
preview: previewOf2(result),
|
|
3568
|
+
blocks: [{ type: "tool_result", tool_use_id: callId ?? "", content: result, is_error: !success }],
|
|
3569
|
+
toolUseId: callId,
|
|
3570
|
+
toolResult: data.result,
|
|
3571
|
+
raw: obj
|
|
3572
|
+
});
|
|
3573
|
+
continue;
|
|
3574
|
+
}
|
|
3575
|
+
if (type === "assistant.reasoning") {
|
|
3576
|
+
const text = stringOf(data.content) ?? "";
|
|
3577
|
+
push({
|
|
3578
|
+
timestamp,
|
|
3579
|
+
role: "agent-thinking",
|
|
3580
|
+
rawType: type,
|
|
3581
|
+
preview: previewOf2(text),
|
|
3582
|
+
blocks: text ? [{ type: "thinking", thinking: text }] : [],
|
|
3583
|
+
model,
|
|
3584
|
+
raw: obj
|
|
3585
|
+
});
|
|
3586
|
+
continue;
|
|
3587
|
+
}
|
|
3588
|
+
if (type === "session.shutdown") {
|
|
3589
|
+
sawShutdown = true;
|
|
3590
|
+
model = stringOf(data.currentModel) ?? model;
|
|
3591
|
+
const details = recordOf(data.tokenDetails);
|
|
3592
|
+
totalUsage.input = tokenCount(details, "input") ?? totalUsage.input;
|
|
3593
|
+
totalUsage.output = tokenCount(details, "output") ?? observedOutput;
|
|
3594
|
+
totalUsage.cacheRead = tokenCount(details, "cache_read") ?? totalUsage.cacheRead;
|
|
3595
|
+
totalUsage.cacheWrite = tokenCount(details, "cache_write") ?? totalUsage.cacheWrite;
|
|
3596
|
+
const changes = recordOf(data.codeChanges);
|
|
3597
|
+
linesAdded = numberOf2(changes?.linesAdded);
|
|
3598
|
+
linesRemoved = numberOf2(changes?.linesRemoved);
|
|
3599
|
+
const modified = changes?.filesModified;
|
|
3600
|
+
filesEdited = Array.isArray(modified) ? modified.length : void 0;
|
|
3601
|
+
}
|
|
3602
|
+
push({
|
|
3603
|
+
timestamp,
|
|
3604
|
+
role: "meta",
|
|
3605
|
+
rawType: type,
|
|
3606
|
+
preview: "",
|
|
3607
|
+
blocks: [],
|
|
3608
|
+
raw: obj
|
|
3609
|
+
});
|
|
3610
|
+
}
|
|
3611
|
+
if (totalUsage.output === 0)
|
|
3612
|
+
totalUsage.output = observedOutput;
|
|
3613
|
+
if (totalUsage.input || totalUsage.output || totalUsage.cacheRead || totalUsage.cacheWrite) {
|
|
3614
|
+
const usageEvent = [...events].reverse().find((event) => event.role === "agent" || event.role === "agent-thinking" || event.role === "tool-call");
|
|
3615
|
+
if (usageEvent) {
|
|
3616
|
+
usageEvent.messageId = `copilot-${file.sessionId}-total`;
|
|
3617
|
+
usageEvent.usage = { ...totalUsage };
|
|
3618
|
+
}
|
|
3619
|
+
}
|
|
3620
|
+
const firstTimestamp = firstMs === void 0 ? void 0 : new Date(firstMs).toISOString();
|
|
3621
|
+
const lastTimestamp = lastMs === void 0 ? void 0 : new Date(lastMs).toISOString();
|
|
3622
|
+
if (firstMs !== void 0) {
|
|
3623
|
+
let previousMs;
|
|
3624
|
+
for (const event of events) {
|
|
3625
|
+
if (!event.timestamp)
|
|
3626
|
+
continue;
|
|
3627
|
+
const ms = Date.parse(event.timestamp);
|
|
3628
|
+
if (!Number.isFinite(ms))
|
|
3629
|
+
continue;
|
|
3630
|
+
event.tOffsetMs = Math.max(0, ms - firstMs);
|
|
3631
|
+
if (previousMs !== void 0)
|
|
3632
|
+
event.gapMs = Math.max(0, ms - previousMs);
|
|
3633
|
+
previousMs = ms;
|
|
3634
|
+
}
|
|
3635
|
+
}
|
|
3636
|
+
const activeSegments = computeActiveSegments3(timestamps);
|
|
3637
|
+
const airTimeMs = activeSegments.reduce((sum, segment) => sum + segment.endMs - segment.startMs, 0);
|
|
3638
|
+
const project = cwd ? resolveProjectIdentity(cwd) : void 0;
|
|
3639
|
+
const repoName = project?.repoName ?? repository?.split("/").filter(Boolean).at(-1);
|
|
3640
|
+
const meta = {
|
|
3641
|
+
agent: "copilot",
|
|
3642
|
+
id: file.sessionId,
|
|
3643
|
+
filePath: file.filePath,
|
|
3644
|
+
projectName: project?.projectName ?? cwd ?? "(unknown)",
|
|
3645
|
+
worktreeName: project?.worktreeName,
|
|
3646
|
+
repoName,
|
|
3647
|
+
projectDir: syntheticProjectDir(cwd),
|
|
3648
|
+
sessionId: file.sessionId,
|
|
3649
|
+
firstTimestamp,
|
|
3650
|
+
lastTimestamp,
|
|
3651
|
+
lastActivityMs: file.mtimeMs,
|
|
3652
|
+
durationMs: firstMs !== void 0 && lastMs !== void 0 ? lastMs - firstMs : void 0,
|
|
3653
|
+
eventCount: events.length,
|
|
3654
|
+
model,
|
|
3655
|
+
cwd,
|
|
3656
|
+
gitBranch,
|
|
3657
|
+
totalUsage,
|
|
3658
|
+
status: sawShutdown || Date.now() - file.mtimeMs > IDLE_GAP_MS2 ? "idle" : "running",
|
|
3659
|
+
firstUserPreview,
|
|
3660
|
+
lastUserPreview,
|
|
3661
|
+
lastAgentPreview,
|
|
3662
|
+
toolCallCount,
|
|
3663
|
+
turnCount,
|
|
3664
|
+
linesAdded,
|
|
3665
|
+
linesRemoved,
|
|
3666
|
+
filesEdited,
|
|
3667
|
+
airTimeMs,
|
|
3668
|
+
activeSegments
|
|
3669
|
+
};
|
|
3670
|
+
return { meta, events };
|
|
3671
|
+
}
|
|
3672
|
+
function clearCopilotCaches() {
|
|
3673
|
+
metaCache3.clear();
|
|
3674
|
+
detailCache3.clear();
|
|
3675
|
+
}
|
|
3676
|
+
async function scanCopilot(root) {
|
|
3677
|
+
const files = await listSessionFiles(root);
|
|
3678
|
+
const out = [];
|
|
3679
|
+
for (const file of files) {
|
|
3680
|
+
const cached = metaCache3.get(file.filePath);
|
|
3681
|
+
if (cached && cached.mtimeMs === file.mtimeMs && cached.sizeBytes === file.sizeBytes) {
|
|
3682
|
+
out.push({ file, meta: cached.meta });
|
|
3683
|
+
continue;
|
|
3684
|
+
}
|
|
3685
|
+
try {
|
|
3686
|
+
const lines = await readJsonl2(file.filePath);
|
|
3687
|
+
const { meta } = parseSession(file, lines);
|
|
3688
|
+
metaCache3.set(file.filePath, { meta, mtimeMs: file.mtimeMs, sizeBytes: file.sizeBytes });
|
|
3689
|
+
out.push({ file, meta });
|
|
3690
|
+
} catch {
|
|
3691
|
+
}
|
|
3692
|
+
}
|
|
3693
|
+
return out;
|
|
3694
|
+
}
|
|
3695
|
+
async function listCopilotSessions(opts = {}) {
|
|
3696
|
+
const root = opts.root ?? DEFAULT_COPILOT_ROOT;
|
|
3697
|
+
const sessions = (await scanCopilot(root)).map((entry) => entry.meta);
|
|
3698
|
+
sessions.sort((a, b) => (b.firstTimestamp ?? "").localeCompare(a.firstTimestamp ?? ""));
|
|
3699
|
+
return opts.limit === void 0 ? sessions : sessions.slice(0, opts.limit);
|
|
3700
|
+
}
|
|
3701
|
+
async function getCopilotSession(id, opts = {}) {
|
|
3702
|
+
const root = opts.root ?? DEFAULT_COPILOT_ROOT;
|
|
3703
|
+
const entry = (await scanCopilot(root)).find((candidate) => candidate.meta.id === id);
|
|
3704
|
+
if (!entry)
|
|
3705
|
+
return null;
|
|
3706
|
+
const cached = detailCache3.get(entry.file.filePath);
|
|
3707
|
+
if (cached && cached.mtimeMs === entry.file.mtimeMs && cached.sizeBytes === entry.file.sizeBytes) {
|
|
3708
|
+
return cached.detail;
|
|
3709
|
+
}
|
|
3710
|
+
const lines = await readJsonl2(entry.file.filePath);
|
|
3711
|
+
const { meta, events } = parseSession(entry.file, lines);
|
|
3712
|
+
const detail = { ...meta, events };
|
|
3713
|
+
detailCache3.set(entry.file.filePath, {
|
|
3714
|
+
detail,
|
|
3715
|
+
mtimeMs: entry.file.mtimeMs,
|
|
3716
|
+
sizeBytes: entry.file.sizeBytes
|
|
3717
|
+
});
|
|
3718
|
+
return detail;
|
|
3719
|
+
}
|
|
3720
|
+
function copilotSessionLocalDay(meta) {
|
|
3721
|
+
if (!meta.firstTimestamp)
|
|
3722
|
+
return void 0;
|
|
3723
|
+
const ms = Date.parse(meta.firstTimestamp);
|
|
3724
|
+
return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
|
|
3725
|
+
}
|
|
3726
|
+
var DEFAULT_COPILOT_ROOT, IDLE_GAP_MS2, metaCache3, detailCache3;
|
|
3727
|
+
var init_copilot = __esm({
|
|
3728
|
+
"../parser/dist/copilot.js"() {
|
|
3729
|
+
"use strict";
|
|
3730
|
+
init_analytics();
|
|
3731
|
+
init_git_project();
|
|
3732
|
+
init_user_input();
|
|
3733
|
+
DEFAULT_COPILOT_ROOT = path3.join(os3.homedir(), ".copilot", "session-state");
|
|
3734
|
+
IDLE_GAP_MS2 = 3 * 60 * 1e3;
|
|
3735
|
+
metaCache3 = /* @__PURE__ */ new Map();
|
|
3736
|
+
detailCache3 = /* @__PURE__ */ new Map();
|
|
3737
|
+
}
|
|
3738
|
+
});
|
|
3739
|
+
|
|
3740
|
+
// ../parser/dist/gemini.js
|
|
3741
|
+
import { promises as fs4 } from "node:fs";
|
|
3742
|
+
import os4 from "node:os";
|
|
3743
|
+
import path4 from "node:path";
|
|
3744
|
+
async function safeReaddir2(p) {
|
|
3745
|
+
return fs4.readdir(p).catch(() => []);
|
|
3746
|
+
}
|
|
3747
|
+
async function listSessionFiles2(root) {
|
|
3322
3748
|
const out = [];
|
|
3323
3749
|
const slugs = await safeReaddir2(root);
|
|
3324
3750
|
for (const slug of slugs) {
|
|
3325
|
-
const chatsDir =
|
|
3751
|
+
const chatsDir = path4.join(root, slug, "chats");
|
|
3326
3752
|
const entries = await safeReaddir2(chatsDir);
|
|
3327
3753
|
for (const entry of entries) {
|
|
3328
3754
|
if (!SESSION_FILE_RE.test(entry))
|
|
3329
3755
|
continue;
|
|
3330
|
-
const full =
|
|
3331
|
-
const stat = await
|
|
3756
|
+
const full = path4.join(chatsDir, entry);
|
|
3757
|
+
const stat = await fs4.stat(full).catch(() => null);
|
|
3332
3758
|
if (!stat || !stat.isFile())
|
|
3333
3759
|
continue;
|
|
3334
3760
|
const filenameId = entry.replace(/\.(jsonl|json)$/, "").split("-").pop() ?? entry;
|
|
@@ -3345,13 +3771,13 @@ async function listSessionFiles(root) {
|
|
|
3345
3771
|
return out;
|
|
3346
3772
|
}
|
|
3347
3773
|
async function loadSlugToCwd() {
|
|
3348
|
-
const stat = await
|
|
3774
|
+
const stat = await fs4.stat(GEMINI_PROJECTS_FILE).catch(() => null);
|
|
3349
3775
|
if (!stat)
|
|
3350
3776
|
return /* @__PURE__ */ new Map();
|
|
3351
3777
|
if (projectsCache && projectsCache.mtimeMs === stat.mtimeMs) {
|
|
3352
3778
|
return projectsCache.slugToCwd;
|
|
3353
3779
|
}
|
|
3354
|
-
const raw = await
|
|
3780
|
+
const raw = await fs4.readFile(GEMINI_PROJECTS_FILE, "utf8").catch(() => "");
|
|
3355
3781
|
let parsed;
|
|
3356
3782
|
try {
|
|
3357
3783
|
parsed = JSON.parse(raw);
|
|
@@ -3376,7 +3802,7 @@ function isMessageRecord(o) {
|
|
|
3376
3802
|
return !!o && typeof o === "object" && typeof o.id === "string" && typeof o.type === "string";
|
|
3377
3803
|
}
|
|
3378
3804
|
async function readAndReplay(file) {
|
|
3379
|
-
const raw = await
|
|
3805
|
+
const raw = await fs4.readFile(file.filePath, "utf8");
|
|
3380
3806
|
if (file.format === "legacy-json") {
|
|
3381
3807
|
let blob;
|
|
3382
3808
|
try {
|
|
@@ -3451,10 +3877,10 @@ async function readAndReplay(file) {
|
|
|
3451
3877
|
}
|
|
3452
3878
|
return { meta, messages };
|
|
3453
3879
|
}
|
|
3454
|
-
function
|
|
3880
|
+
function emptyUsage3() {
|
|
3455
3881
|
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
3456
3882
|
}
|
|
3457
|
-
function
|
|
3883
|
+
function previewOf3(text) {
|
|
3458
3884
|
return text.replace(/\s+/g, " ").trim().slice(0, 200);
|
|
3459
3885
|
}
|
|
3460
3886
|
function flattenContent(c) {
|
|
@@ -3493,12 +3919,12 @@ function flattenContent(c) {
|
|
|
3493
3919
|
function truncate3(s, n) {
|
|
3494
3920
|
return s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
|
|
3495
3921
|
}
|
|
3496
|
-
async function
|
|
3922
|
+
async function parseSession2(file) {
|
|
3497
3923
|
const { meta: metaRec, messages } = await readAndReplay(file);
|
|
3498
3924
|
const slugToCwd = await loadSlugToCwd();
|
|
3499
3925
|
const cwd = slugToCwd.get(file.slug);
|
|
3500
3926
|
const events = [];
|
|
3501
|
-
const totalUsage =
|
|
3927
|
+
const totalUsage = emptyUsage3();
|
|
3502
3928
|
let firstTimestamp;
|
|
3503
3929
|
let lastTimestamp;
|
|
3504
3930
|
let model;
|
|
@@ -3524,7 +3950,7 @@ async function parseSession(file) {
|
|
|
3524
3950
|
const ts = msg.timestamp;
|
|
3525
3951
|
if (msg.type === "user") {
|
|
3526
3952
|
const text = flattenContent(msg.displayContent ?? msg.content);
|
|
3527
|
-
const preview =
|
|
3953
|
+
const preview = previewOf3(text);
|
|
3528
3954
|
const isHidden = isFrameworkInjectedUserInput(text);
|
|
3529
3955
|
if (text && !isHidden) {
|
|
3530
3956
|
if (!firstUserPreview)
|
|
@@ -3548,7 +3974,7 @@ async function parseSession(file) {
|
|
|
3548
3974
|
if (typeof msg.model === "string")
|
|
3549
3975
|
model = msg.model;
|
|
3550
3976
|
const text = flattenContent(msg.content);
|
|
3551
|
-
const preview =
|
|
3977
|
+
const preview = previewOf3(text);
|
|
3552
3978
|
if (text)
|
|
3553
3979
|
lastAgentPreview = preview;
|
|
3554
3980
|
let usage;
|
|
@@ -3574,7 +4000,7 @@ async function parseSession(file) {
|
|
|
3574
4000
|
timestamp: th.timestamp ?? ts,
|
|
3575
4001
|
role: "agent-thinking",
|
|
3576
4002
|
rawType: "gemini/thought",
|
|
3577
|
-
preview:
|
|
4003
|
+
preview: previewOf3(thText),
|
|
3578
4004
|
blocks: [{ type: "thinking", thinking: thText }],
|
|
3579
4005
|
model,
|
|
3580
4006
|
raw: th
|
|
@@ -3631,7 +4057,7 @@ async function parseSession(file) {
|
|
|
3631
4057
|
timestamp: tc.timestamp ?? ts,
|
|
3632
4058
|
role: "tool-result",
|
|
3633
4059
|
rawType: "gemini/tool_result",
|
|
3634
|
-
preview:
|
|
4060
|
+
preview: previewOf3(resultText),
|
|
3635
4061
|
blocks: [
|
|
3636
4062
|
{
|
|
3637
4063
|
type: "tool_result",
|
|
@@ -3655,7 +4081,7 @@ async function parseSession(file) {
|
|
|
3655
4081
|
timestamp: ts,
|
|
3656
4082
|
role: "meta",
|
|
3657
4083
|
rawType: `gemini/${msg.type}`,
|
|
3658
|
-
preview:
|
|
4084
|
+
preview: previewOf3(text),
|
|
3659
4085
|
blocks: text ? [{ type: "text", text }] : [],
|
|
3660
4086
|
raw: msg
|
|
3661
4087
|
});
|
|
@@ -3677,7 +4103,7 @@ async function parseSession(file) {
|
|
|
3677
4103
|
prevMs = ms;
|
|
3678
4104
|
}
|
|
3679
4105
|
}
|
|
3680
|
-
const activeSegments =
|
|
4106
|
+
const activeSegments = computeActiveSegments4(tsMs);
|
|
3681
4107
|
const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
|
|
3682
4108
|
const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
|
|
3683
4109
|
const sessionId = metaRec.sessionId ?? file.filenameId;
|
|
@@ -3711,7 +4137,7 @@ async function parseSession(file) {
|
|
|
3711
4137
|
};
|
|
3712
4138
|
return { meta, events };
|
|
3713
4139
|
}
|
|
3714
|
-
function
|
|
4140
|
+
function computeActiveSegments4(tsMs) {
|
|
3715
4141
|
if (tsMs.length === 0)
|
|
3716
4142
|
return [];
|
|
3717
4143
|
const sorted = [...tsMs].sort((a, b) => a - b);
|
|
@@ -3719,7 +4145,7 @@ function computeActiveSegments3(tsMs) {
|
|
|
3719
4145
|
let segStart = sorted[0];
|
|
3720
4146
|
let segEnd = sorted[0];
|
|
3721
4147
|
for (let i = 1; i < sorted.length; i++) {
|
|
3722
|
-
if (sorted[i] - segEnd >
|
|
4148
|
+
if (sorted[i] - segEnd > IDLE_GAP_MS3) {
|
|
3723
4149
|
out.push({ startMs: segStart, endMs: segEnd });
|
|
3724
4150
|
segStart = sorted[i];
|
|
3725
4151
|
}
|
|
@@ -3729,23 +4155,23 @@ function computeActiveSegments3(tsMs) {
|
|
|
3729
4155
|
return out;
|
|
3730
4156
|
}
|
|
3731
4157
|
function clearGeminiCaches() {
|
|
3732
|
-
|
|
3733
|
-
|
|
4158
|
+
metaCache4.clear();
|
|
4159
|
+
detailCache4.clear();
|
|
3734
4160
|
projectsCache = null;
|
|
3735
4161
|
}
|
|
3736
4162
|
async function listGeminiSessions(opts = {}) {
|
|
3737
4163
|
const root = opts.root ?? DEFAULT_GEMINI_ROOT;
|
|
3738
|
-
const files = await
|
|
4164
|
+
const files = await listSessionFiles2(root);
|
|
3739
4165
|
const out = [];
|
|
3740
4166
|
for (const file of files) {
|
|
3741
|
-
const cached =
|
|
4167
|
+
const cached = metaCache4.get(file.filePath);
|
|
3742
4168
|
if (cached && cached.mtimeMs === file.mtimeMs && cached.sizeBytes === file.sizeBytes) {
|
|
3743
4169
|
out.push(cached.meta);
|
|
3744
4170
|
continue;
|
|
3745
4171
|
}
|
|
3746
4172
|
try {
|
|
3747
|
-
const { meta } = await
|
|
3748
|
-
|
|
4173
|
+
const { meta } = await parseSession2(file);
|
|
4174
|
+
metaCache4.set(file.filePath, {
|
|
3749
4175
|
meta,
|
|
3750
4176
|
mtimeMs: file.mtimeMs,
|
|
3751
4177
|
sizeBytes: file.sizeBytes
|
|
@@ -3761,7 +4187,7 @@ async function listGeminiSessions(opts = {}) {
|
|
|
3761
4187
|
}
|
|
3762
4188
|
async function getGeminiSession(id, opts = {}) {
|
|
3763
4189
|
const root = opts.root ?? DEFAULT_GEMINI_ROOT;
|
|
3764
|
-
const files = await
|
|
4190
|
+
const files = await listSessionFiles2(root);
|
|
3765
4191
|
let chosen;
|
|
3766
4192
|
for (const file of files) {
|
|
3767
4193
|
if (file.filenameId === id || id.startsWith(file.filenameId)) {
|
|
@@ -3771,7 +4197,7 @@ async function getGeminiSession(id, opts = {}) {
|
|
|
3771
4197
|
}
|
|
3772
4198
|
if (!chosen) {
|
|
3773
4199
|
for (const file of files) {
|
|
3774
|
-
const { meta: meta2 } = await
|
|
4200
|
+
const { meta: meta2 } = await parseSession2(file).catch(() => ({ meta: { id: "" } }));
|
|
3775
4201
|
if (meta2.id === id) {
|
|
3776
4202
|
chosen = file;
|
|
3777
4203
|
break;
|
|
@@ -3780,13 +4206,13 @@ async function getGeminiSession(id, opts = {}) {
|
|
|
3780
4206
|
}
|
|
3781
4207
|
if (!chosen)
|
|
3782
4208
|
return null;
|
|
3783
|
-
const cached =
|
|
4209
|
+
const cached = detailCache4.get(chosen.filePath);
|
|
3784
4210
|
if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes) {
|
|
3785
4211
|
return cached.detail;
|
|
3786
4212
|
}
|
|
3787
|
-
const { meta, events } = await
|
|
4213
|
+
const { meta, events } = await parseSession2(chosen);
|
|
3788
4214
|
const detail = { ...meta, events };
|
|
3789
|
-
|
|
4215
|
+
detailCache4.set(chosen.filePath, {
|
|
3790
4216
|
detail,
|
|
3791
4217
|
mtimeMs: chosen.mtimeMs,
|
|
3792
4218
|
sizeBytes: chosen.sizeBytes
|
|
@@ -3799,39 +4225,39 @@ function geminiSessionLocalDay(meta) {
|
|
|
3799
4225
|
const ms = Date.parse(meta.firstTimestamp);
|
|
3800
4226
|
return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
|
|
3801
4227
|
}
|
|
3802
|
-
var DEFAULT_GEMINI_ROOT, GEMINI_PROJECTS_FILE, SESSION_FILE_RE,
|
|
4228
|
+
var DEFAULT_GEMINI_ROOT, GEMINI_PROJECTS_FILE, SESSION_FILE_RE, IDLE_GAP_MS3, projectsCache, metaCache4, detailCache4;
|
|
3803
4229
|
var init_gemini = __esm({
|
|
3804
4230
|
"../parser/dist/gemini.js"() {
|
|
3805
4231
|
"use strict";
|
|
3806
4232
|
init_analytics();
|
|
3807
4233
|
init_git_project();
|
|
3808
4234
|
init_user_input();
|
|
3809
|
-
DEFAULT_GEMINI_ROOT =
|
|
3810
|
-
GEMINI_PROJECTS_FILE =
|
|
4235
|
+
DEFAULT_GEMINI_ROOT = path4.join(os4.homedir(), ".gemini", "tmp");
|
|
4236
|
+
GEMINI_PROJECTS_FILE = path4.join(os4.homedir(), ".gemini", "projects.json");
|
|
3811
4237
|
SESSION_FILE_RE = /^session-.+\.(jsonl|json)$/;
|
|
3812
|
-
|
|
4238
|
+
IDLE_GAP_MS3 = 3 * 60 * 1e3;
|
|
3813
4239
|
projectsCache = null;
|
|
3814
|
-
|
|
3815
|
-
|
|
4240
|
+
metaCache4 = /* @__PURE__ */ new Map();
|
|
4241
|
+
detailCache4 = /* @__PURE__ */ new Map();
|
|
3816
4242
|
}
|
|
3817
4243
|
});
|
|
3818
4244
|
|
|
3819
4245
|
// ../parser/dist/antigravity.js
|
|
3820
|
-
import { promises as
|
|
3821
|
-
import
|
|
3822
|
-
import
|
|
4246
|
+
import { promises as fs5 } from "node:fs";
|
|
4247
|
+
import os5 from "node:os";
|
|
4248
|
+
import path5 from "node:path";
|
|
3823
4249
|
async function safeReaddir3(p) {
|
|
3824
|
-
return
|
|
4250
|
+
return fs5.readdir(p).catch(() => []);
|
|
3825
4251
|
}
|
|
3826
4252
|
async function loadSlugToCwd2(root) {
|
|
3827
|
-
const historyFile =
|
|
3828
|
-
const stat = await
|
|
4253
|
+
const historyFile = path5.join(root, "history.jsonl");
|
|
4254
|
+
const stat = await fs5.stat(historyFile).catch(() => null);
|
|
3829
4255
|
if (!stat)
|
|
3830
4256
|
return /* @__PURE__ */ new Map();
|
|
3831
4257
|
if (historyCache && historyCache.mtimeMs === stat.mtimeMs) {
|
|
3832
4258
|
return historyCache.slugToCwd;
|
|
3833
4259
|
}
|
|
3834
|
-
const raw = await
|
|
4260
|
+
const raw = await fs5.readFile(historyFile, "utf8").catch(() => "");
|
|
3835
4261
|
const slugToCwd = /* @__PURE__ */ new Map();
|
|
3836
4262
|
for (const line of raw.split("\n")) {
|
|
3837
4263
|
const trimmed = line.trim();
|
|
@@ -3848,14 +4274,14 @@ async function loadSlugToCwd2(root) {
|
|
|
3848
4274
|
historyCache = { mtimeMs: stat.mtimeMs, slugToCwd };
|
|
3849
4275
|
return slugToCwd;
|
|
3850
4276
|
}
|
|
3851
|
-
async function
|
|
4277
|
+
async function listSessionFiles3(root) {
|
|
3852
4278
|
const slugToCwd = await loadSlugToCwd2(root);
|
|
3853
4279
|
const out = [];
|
|
3854
|
-
const brainDir =
|
|
4280
|
+
const brainDir = path5.join(root, "brain");
|
|
3855
4281
|
const entries = await safeReaddir3(brainDir);
|
|
3856
4282
|
for (const entry of entries) {
|
|
3857
|
-
const transcriptPath =
|
|
3858
|
-
const stat = await
|
|
4283
|
+
const transcriptPath = path5.join(brainDir, entry, ".system_generated", "logs", "transcript.jsonl");
|
|
4284
|
+
const stat = await fs5.stat(transcriptPath).catch(() => null);
|
|
3859
4285
|
if (stat && stat.isFile()) {
|
|
3860
4286
|
out.push({
|
|
3861
4287
|
filePath: transcriptPath,
|
|
@@ -3868,19 +4294,19 @@ async function listSessionFiles2(root) {
|
|
|
3868
4294
|
}
|
|
3869
4295
|
return out;
|
|
3870
4296
|
}
|
|
3871
|
-
function
|
|
4297
|
+
function emptyUsage4() {
|
|
3872
4298
|
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
3873
4299
|
}
|
|
3874
|
-
function
|
|
4300
|
+
function previewOf4(text) {
|
|
3875
4301
|
return text.replace(/\s+/g, " ").trim().slice(0, 200);
|
|
3876
4302
|
}
|
|
3877
4303
|
function truncate4(s, n) {
|
|
3878
4304
|
return s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
|
|
3879
4305
|
}
|
|
3880
|
-
async function
|
|
3881
|
-
const raw = await
|
|
4306
|
+
async function parseSession3(file) {
|
|
4307
|
+
const raw = await fs5.readFile(file.filePath, "utf8");
|
|
3882
4308
|
const events = [];
|
|
3883
|
-
const totalUsage =
|
|
4309
|
+
const totalUsage = emptyUsage4();
|
|
3884
4310
|
let firstTimestamp;
|
|
3885
4311
|
let lastTimestamp;
|
|
3886
4312
|
let model;
|
|
@@ -3952,7 +4378,7 @@ async function parseSession2(file) {
|
|
|
3952
4378
|
if (requestMatch) {
|
|
3953
4379
|
text2 = requestMatch[1].trim();
|
|
3954
4380
|
}
|
|
3955
|
-
const preview =
|
|
4381
|
+
const preview = previewOf4(text2);
|
|
3956
4382
|
const isHidden = isFrameworkInjectedUserInput(text2);
|
|
3957
4383
|
if (text2 && !isHidden) {
|
|
3958
4384
|
if (!firstUserPreview)
|
|
@@ -3981,14 +4407,14 @@ async function parseSession2(file) {
|
|
|
3981
4407
|
timestamp: ts,
|
|
3982
4408
|
role: "agent-thinking",
|
|
3983
4409
|
rawType: "antigravity/thought",
|
|
3984
|
-
preview:
|
|
4410
|
+
preview: previewOf4(thinking),
|
|
3985
4411
|
blocks: [{ type: "thinking", thinking }],
|
|
3986
4412
|
model,
|
|
3987
4413
|
raw: eventObj
|
|
3988
4414
|
});
|
|
3989
4415
|
}
|
|
3990
4416
|
if (content) {
|
|
3991
|
-
const preview =
|
|
4417
|
+
const preview = previewOf4(content);
|
|
3992
4418
|
lastAgentPreview = preview;
|
|
3993
4419
|
pushEvent({
|
|
3994
4420
|
index: idx++,
|
|
@@ -4034,7 +4460,7 @@ async function parseSession2(file) {
|
|
|
4034
4460
|
timestamp: ts,
|
|
4035
4461
|
role: "tool-result",
|
|
4036
4462
|
rawType: "antigravity/tool_result",
|
|
4037
|
-
preview:
|
|
4463
|
+
preview: previewOf4(contentStr),
|
|
4038
4464
|
blocks: [{
|
|
4039
4465
|
type: "tool_result",
|
|
4040
4466
|
tool_use_id: toolUseId,
|
|
@@ -4053,7 +4479,7 @@ async function parseSession2(file) {
|
|
|
4053
4479
|
timestamp: ts,
|
|
4054
4480
|
role: "meta",
|
|
4055
4481
|
rawType: `antigravity/${eventObj.type?.toLowerCase() || "unknown"}`,
|
|
4056
|
-
preview:
|
|
4482
|
+
preview: previewOf4(text),
|
|
4057
4483
|
blocks: text ? [{ type: "text", text }] : [],
|
|
4058
4484
|
raw: eventObj
|
|
4059
4485
|
});
|
|
@@ -4073,7 +4499,7 @@ async function parseSession2(file) {
|
|
|
4073
4499
|
prevMs = ms;
|
|
4074
4500
|
}
|
|
4075
4501
|
}
|
|
4076
|
-
const activeSegments =
|
|
4502
|
+
const activeSegments = computeActiveSegments5(tsMs);
|
|
4077
4503
|
const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
|
|
4078
4504
|
const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
|
|
4079
4505
|
const sessionId = file.conversationId;
|
|
@@ -4108,7 +4534,7 @@ async function parseSession2(file) {
|
|
|
4108
4534
|
};
|
|
4109
4535
|
return { meta, events };
|
|
4110
4536
|
}
|
|
4111
|
-
function
|
|
4537
|
+
function computeActiveSegments5(tsMs) {
|
|
4112
4538
|
if (tsMs.length === 0)
|
|
4113
4539
|
return [];
|
|
4114
4540
|
const sorted = [...tsMs].sort((a, b) => a - b);
|
|
@@ -4116,7 +4542,7 @@ function computeActiveSegments4(tsMs) {
|
|
|
4116
4542
|
let segStart = sorted[0];
|
|
4117
4543
|
let segEnd = sorted[0];
|
|
4118
4544
|
for (let i = 1; i < sorted.length; i++) {
|
|
4119
|
-
if (sorted[i] - segEnd >
|
|
4545
|
+
if (sorted[i] - segEnd > IDLE_GAP_MS4) {
|
|
4120
4546
|
out.push({ startMs: segStart, endMs: segEnd });
|
|
4121
4547
|
segStart = sorted[i];
|
|
4122
4548
|
}
|
|
@@ -4126,23 +4552,23 @@ function computeActiveSegments4(tsMs) {
|
|
|
4126
4552
|
return out;
|
|
4127
4553
|
}
|
|
4128
4554
|
function clearAntigravityCaches() {
|
|
4129
|
-
|
|
4130
|
-
|
|
4555
|
+
metaCache5.clear();
|
|
4556
|
+
detailCache5.clear();
|
|
4131
4557
|
historyCache = null;
|
|
4132
4558
|
}
|
|
4133
4559
|
async function listAntigravitySessions(opts = {}) {
|
|
4134
4560
|
const root = opts.root ?? DEFAULT_ANTIGRAVITY_ROOT;
|
|
4135
|
-
const files = await
|
|
4561
|
+
const files = await listSessionFiles3(root);
|
|
4136
4562
|
const out = [];
|
|
4137
4563
|
for (const file of files) {
|
|
4138
|
-
const cached =
|
|
4564
|
+
const cached = metaCache5.get(file.filePath);
|
|
4139
4565
|
if (cached && cached.mtimeMs === file.mtimeMs && cached.sizeBytes === file.sizeBytes && cached.cwd === file.cwd) {
|
|
4140
4566
|
out.push(cached.meta);
|
|
4141
4567
|
continue;
|
|
4142
4568
|
}
|
|
4143
4569
|
try {
|
|
4144
|
-
const { meta } = await
|
|
4145
|
-
|
|
4570
|
+
const { meta } = await parseSession3(file);
|
|
4571
|
+
metaCache5.set(file.filePath, {
|
|
4146
4572
|
meta,
|
|
4147
4573
|
mtimeMs: file.mtimeMs,
|
|
4148
4574
|
sizeBytes: file.sizeBytes,
|
|
@@ -4159,7 +4585,7 @@ async function listAntigravitySessions(opts = {}) {
|
|
|
4159
4585
|
}
|
|
4160
4586
|
async function getAntigravitySession(id, opts = {}) {
|
|
4161
4587
|
const root = opts.root ?? DEFAULT_ANTIGRAVITY_ROOT;
|
|
4162
|
-
const files = await
|
|
4588
|
+
const files = await listSessionFiles3(root);
|
|
4163
4589
|
let chosen;
|
|
4164
4590
|
for (const file of files) {
|
|
4165
4591
|
if (file.conversationId === id) {
|
|
@@ -4169,13 +4595,13 @@ async function getAntigravitySession(id, opts = {}) {
|
|
|
4169
4595
|
}
|
|
4170
4596
|
if (!chosen)
|
|
4171
4597
|
return null;
|
|
4172
|
-
const cached =
|
|
4598
|
+
const cached = detailCache5.get(chosen.filePath);
|
|
4173
4599
|
if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes && cached.cwd === chosen.cwd) {
|
|
4174
4600
|
return cached.detail;
|
|
4175
4601
|
}
|
|
4176
|
-
const { meta, events } = await
|
|
4602
|
+
const { meta, events } = await parseSession3(chosen);
|
|
4177
4603
|
const detail = { ...meta, events };
|
|
4178
|
-
|
|
4604
|
+
detailCache5.set(chosen.filePath, {
|
|
4179
4605
|
detail,
|
|
4180
4606
|
mtimeMs: chosen.mtimeMs,
|
|
4181
4607
|
sizeBytes: chosen.sizeBytes,
|
|
@@ -4189,61 +4615,61 @@ function antigravitySessionLocalDay(meta) {
|
|
|
4189
4615
|
const ms = Date.parse(meta.firstTimestamp);
|
|
4190
4616
|
return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
|
|
4191
4617
|
}
|
|
4192
|
-
var DEFAULT_ANTIGRAVITY_ROOT,
|
|
4618
|
+
var DEFAULT_ANTIGRAVITY_ROOT, IDLE_GAP_MS4, historyCache, metaCache5, detailCache5;
|
|
4193
4619
|
var init_antigravity = __esm({
|
|
4194
4620
|
"../parser/dist/antigravity.js"() {
|
|
4195
4621
|
"use strict";
|
|
4196
4622
|
init_analytics();
|
|
4197
4623
|
init_git_project();
|
|
4198
4624
|
init_user_input();
|
|
4199
|
-
DEFAULT_ANTIGRAVITY_ROOT =
|
|
4200
|
-
|
|
4625
|
+
DEFAULT_ANTIGRAVITY_ROOT = path5.join(os5.homedir(), ".gemini", "antigravity-cli");
|
|
4626
|
+
IDLE_GAP_MS4 = 3 * 60 * 1e3;
|
|
4201
4627
|
historyCache = null;
|
|
4202
|
-
|
|
4203
|
-
|
|
4628
|
+
metaCache5 = /* @__PURE__ */ new Map();
|
|
4629
|
+
detailCache5 = /* @__PURE__ */ new Map();
|
|
4204
4630
|
}
|
|
4205
4631
|
});
|
|
4206
4632
|
|
|
4207
4633
|
// ../parser/dist/cowork.js
|
|
4208
|
-
import { promises as
|
|
4209
|
-
import
|
|
4210
|
-
import
|
|
4634
|
+
import { promises as fs6 } from "node:fs";
|
|
4635
|
+
import os6 from "node:os";
|
|
4636
|
+
import path6 from "node:path";
|
|
4211
4637
|
function defaultCoworkRoot() {
|
|
4212
|
-
const home =
|
|
4638
|
+
const home = os6.homedir();
|
|
4213
4639
|
if (process.platform === "darwin") {
|
|
4214
|
-
return
|
|
4640
|
+
return path6.join(home, "Library", "Application Support", "Claude", "local-agent-mode-sessions");
|
|
4215
4641
|
}
|
|
4216
4642
|
if (process.platform === "win32") {
|
|
4217
|
-
const appData = process.env.APPDATA ??
|
|
4218
|
-
return
|
|
4643
|
+
const appData = process.env.APPDATA ?? path6.join(home, "AppData", "Roaming");
|
|
4644
|
+
return path6.join(appData, "Claude", "local-agent-mode-sessions");
|
|
4219
4645
|
}
|
|
4220
|
-
return
|
|
4646
|
+
return path6.join(home, ".config", "Claude", "local-agent-mode-sessions");
|
|
4221
4647
|
}
|
|
4222
4648
|
async function safeReaddir4(p) {
|
|
4223
|
-
return
|
|
4649
|
+
return fs6.readdir(p).catch(() => []);
|
|
4224
4650
|
}
|
|
4225
4651
|
async function statMs(p) {
|
|
4226
|
-
const s = await
|
|
4652
|
+
const s = await fs6.stat(p).catch(() => null);
|
|
4227
4653
|
return s ? s.mtimeMs : 0;
|
|
4228
4654
|
}
|
|
4229
|
-
async function
|
|
4655
|
+
async function listSessionFiles4(root) {
|
|
4230
4656
|
const out = [];
|
|
4231
4657
|
const accounts = await safeReaddir4(root);
|
|
4232
4658
|
for (const accountId of accounts) {
|
|
4233
|
-
const accountDir =
|
|
4659
|
+
const accountDir = path6.join(root, accountId);
|
|
4234
4660
|
const workspaces = await safeReaddir4(accountDir);
|
|
4235
4661
|
for (const workspaceId of workspaces) {
|
|
4236
|
-
const workspaceDir =
|
|
4237
|
-
const spacesMtimeMs = await statMs(
|
|
4662
|
+
const workspaceDir = path6.join(accountDir, workspaceId);
|
|
4663
|
+
const spacesMtimeMs = await statMs(path6.join(workspaceDir, "spaces.json"));
|
|
4238
4664
|
const entries = await safeReaddir4(workspaceDir);
|
|
4239
4665
|
for (const entry of entries) {
|
|
4240
4666
|
if (!SESSION_ID_RE.test(entry))
|
|
4241
4667
|
continue;
|
|
4242
|
-
const auditPath =
|
|
4243
|
-
const auditStat = await
|
|
4668
|
+
const auditPath = path6.join(workspaceDir, entry, "audit.jsonl");
|
|
4669
|
+
const auditStat = await fs6.stat(auditPath).catch(() => null);
|
|
4244
4670
|
if (!auditStat || !auditStat.isFile() || auditStat.size === 0)
|
|
4245
4671
|
continue;
|
|
4246
|
-
const metaPath =
|
|
4672
|
+
const metaPath = path6.join(workspaceDir, `${entry}.json`);
|
|
4247
4673
|
const metaMtimeMs = await statMs(metaPath);
|
|
4248
4674
|
out.push({
|
|
4249
4675
|
sessionId: entry,
|
|
@@ -4261,14 +4687,14 @@ async function listSessionFiles3(root) {
|
|
|
4261
4687
|
return out;
|
|
4262
4688
|
}
|
|
4263
4689
|
async function loadSpacesForWorkspace(workspaceDir) {
|
|
4264
|
-
const spacesPath =
|
|
4265
|
-
const stat = await
|
|
4690
|
+
const spacesPath = path6.join(workspaceDir, "spaces.json");
|
|
4691
|
+
const stat = await fs6.stat(spacesPath).catch(() => null);
|
|
4266
4692
|
if (!stat)
|
|
4267
4693
|
return /* @__PURE__ */ new Map();
|
|
4268
4694
|
const cached = spacesCache.get(workspaceDir);
|
|
4269
4695
|
if (cached && cached.mtimeMs === stat.mtimeMs)
|
|
4270
4696
|
return cached.spaceIdToPath;
|
|
4271
|
-
const raw = await
|
|
4697
|
+
const raw = await fs6.readFile(spacesPath, "utf8").catch(() => "");
|
|
4272
4698
|
const out = /* @__PURE__ */ new Map();
|
|
4273
4699
|
try {
|
|
4274
4700
|
const parsed = JSON.parse(raw);
|
|
@@ -4286,7 +4712,7 @@ async function loadSpacesForWorkspace(workspaceDir) {
|
|
|
4286
4712
|
return out;
|
|
4287
4713
|
}
|
|
4288
4714
|
async function readCoworkMeta(metaPath) {
|
|
4289
|
-
const raw = await
|
|
4715
|
+
const raw = await fs6.readFile(metaPath, "utf8").catch(() => "");
|
|
4290
4716
|
if (!raw)
|
|
4291
4717
|
return {};
|
|
4292
4718
|
try {
|
|
@@ -4322,8 +4748,8 @@ function resolveProject(meta, spaceIdToPath) {
|
|
|
4322
4748
|
cwd: projectPath
|
|
4323
4749
|
};
|
|
4324
4750
|
}
|
|
4325
|
-
async function
|
|
4326
|
-
const raw = await
|
|
4751
|
+
async function readJsonl3(filePath) {
|
|
4752
|
+
const raw = await fs6.readFile(filePath, "utf8");
|
|
4327
4753
|
const out = [];
|
|
4328
4754
|
for (const line of raw.split("\n")) {
|
|
4329
4755
|
const trimmed = line.trim();
|
|
@@ -4459,7 +4885,7 @@ function buildCoworkSubagents(subagentGroups, allLines, sessionStartMs) {
|
|
|
4459
4885
|
}
|
|
4460
4886
|
async function parseCoworkSession(file) {
|
|
4461
4887
|
const [lines, coworkMeta, spaceIdToPath] = await Promise.all([
|
|
4462
|
-
|
|
4888
|
+
readJsonl3(file.auditPath),
|
|
4463
4889
|
readCoworkMeta(file.metaPath),
|
|
4464
4890
|
loadSpacesForWorkspace(file.workspaceDir)
|
|
4465
4891
|
]);
|
|
@@ -4494,24 +4920,24 @@ function cacheKeyMatches(a, b) {
|
|
|
4494
4920
|
return a.auditMtimeMs === b.auditMtimeMs && a.auditSize === b.auditSize && a.metaMtimeMs === b.metaMtimeMs && a.spacesMtimeMs === b.spacesMtimeMs;
|
|
4495
4921
|
}
|
|
4496
4922
|
function clearCoworkCaches() {
|
|
4497
|
-
|
|
4498
|
-
|
|
4923
|
+
metaCache6.clear();
|
|
4924
|
+
detailCache6.clear();
|
|
4499
4925
|
spacesCache.clear();
|
|
4500
4926
|
}
|
|
4501
4927
|
async function listCoworkSessions(opts = {}) {
|
|
4502
4928
|
const root = opts.root ?? DEFAULT_COWORK_ROOT;
|
|
4503
|
-
const files = await
|
|
4929
|
+
const files = await listSessionFiles4(root);
|
|
4504
4930
|
const out = [];
|
|
4505
4931
|
for (const file of files) {
|
|
4506
4932
|
const key = cacheKeyFor(file);
|
|
4507
|
-
const cached =
|
|
4933
|
+
const cached = metaCache6.get(file.auditPath);
|
|
4508
4934
|
if (cached && cacheKeyMatches(cached.key, key)) {
|
|
4509
4935
|
out.push(cached.meta);
|
|
4510
4936
|
continue;
|
|
4511
4937
|
}
|
|
4512
4938
|
try {
|
|
4513
4939
|
const { meta } = await parseCoworkSession(file);
|
|
4514
|
-
|
|
4940
|
+
metaCache6.set(file.auditPath, { meta, key });
|
|
4515
4941
|
out.push(meta);
|
|
4516
4942
|
} catch {
|
|
4517
4943
|
}
|
|
@@ -4523,12 +4949,12 @@ async function listCoworkSessions(opts = {}) {
|
|
|
4523
4949
|
}
|
|
4524
4950
|
async function getCoworkSession(id, opts = {}) {
|
|
4525
4951
|
const root = opts.root ?? DEFAULT_COWORK_ROOT;
|
|
4526
|
-
const files = await
|
|
4952
|
+
const files = await listSessionFiles4(root);
|
|
4527
4953
|
const file = files.find((f) => f.sessionId === id);
|
|
4528
4954
|
if (!file)
|
|
4529
4955
|
return null;
|
|
4530
4956
|
const key = cacheKeyFor(file);
|
|
4531
|
-
const cached =
|
|
4957
|
+
const cached = detailCache6.get(file.auditPath);
|
|
4532
4958
|
if (cached && cacheKeyMatches(cached.key, key))
|
|
4533
4959
|
return cached.detail;
|
|
4534
4960
|
const { meta, events, subagents } = await parseCoworkSession(file);
|
|
@@ -4537,10 +4963,10 @@ async function getCoworkSession(id, opts = {}) {
|
|
|
4537
4963
|
events,
|
|
4538
4964
|
...subagents.length ? { subagents } : {}
|
|
4539
4965
|
};
|
|
4540
|
-
|
|
4966
|
+
detailCache6.set(file.auditPath, { detail, key });
|
|
4541
4967
|
return detail;
|
|
4542
4968
|
}
|
|
4543
|
-
var DEFAULT_COWORK_ROOT, SESSION_ID_RE, spacesCache,
|
|
4969
|
+
var DEFAULT_COWORK_ROOT, SESSION_ID_RE, spacesCache, metaCache6, detailCache6;
|
|
4544
4970
|
var init_cowork = __esm({
|
|
4545
4971
|
"../parser/dist/cowork.js"() {
|
|
4546
4972
|
"use strict";
|
|
@@ -4550,24 +4976,24 @@ var init_cowork = __esm({
|
|
|
4550
4976
|
DEFAULT_COWORK_ROOT = defaultCoworkRoot();
|
|
4551
4977
|
SESSION_ID_RE = /^local_[0-9a-f-]+$/;
|
|
4552
4978
|
spacesCache = /* @__PURE__ */ new Map();
|
|
4553
|
-
|
|
4554
|
-
|
|
4979
|
+
metaCache6 = /* @__PURE__ */ new Map();
|
|
4980
|
+
detailCache6 = /* @__PURE__ */ new Map();
|
|
4555
4981
|
}
|
|
4556
4982
|
});
|
|
4557
4983
|
|
|
4558
4984
|
// ../parser/dist/grok.js
|
|
4559
|
-
import { promises as
|
|
4560
|
-
import
|
|
4561
|
-
import
|
|
4985
|
+
import { promises as fs7 } from "node:fs";
|
|
4986
|
+
import os7 from "node:os";
|
|
4987
|
+
import path7 from "node:path";
|
|
4562
4988
|
function resolveDefaultGrokRoot() {
|
|
4563
|
-
const home = process.env.GROK_HOME ||
|
|
4564
|
-
return
|
|
4989
|
+
const home = process.env.GROK_HOME || path7.join(os7.homedir(), ".grok");
|
|
4990
|
+
return path7.join(home, "sessions");
|
|
4565
4991
|
}
|
|
4566
4992
|
async function safeReaddir5(p) {
|
|
4567
|
-
return
|
|
4993
|
+
return fs7.readdir(p).catch(() => []);
|
|
4568
4994
|
}
|
|
4569
4995
|
async function safeReadJson(p) {
|
|
4570
|
-
const raw = await
|
|
4996
|
+
const raw = await fs7.readFile(p, "utf8").catch(() => null);
|
|
4571
4997
|
if (raw == null)
|
|
4572
4998
|
return null;
|
|
4573
4999
|
try {
|
|
@@ -4577,8 +5003,8 @@ async function safeReadJson(p) {
|
|
|
4577
5003
|
}
|
|
4578
5004
|
}
|
|
4579
5005
|
async function resolveEncodedCwd(groupDir, encoded) {
|
|
4580
|
-
const cwdFile =
|
|
4581
|
-
const fromFile = await
|
|
5006
|
+
const cwdFile = path7.join(groupDir, ".cwd");
|
|
5007
|
+
const fromFile = await fs7.readFile(cwdFile, "utf8").catch(() => null);
|
|
4582
5008
|
if (fromFile && fromFile.trim())
|
|
4583
5009
|
return fromFile.trim();
|
|
4584
5010
|
try {
|
|
@@ -4593,8 +5019,8 @@ async function listSessionDirs(root) {
|
|
|
4593
5019
|
for (const group of groups) {
|
|
4594
5020
|
if (group === "session_search.sqlite" || group.startsWith("."))
|
|
4595
5021
|
continue;
|
|
4596
|
-
const groupDir =
|
|
4597
|
-
const groupStat = await
|
|
5022
|
+
const groupDir = path7.join(root, group);
|
|
5023
|
+
const groupStat = await fs7.stat(groupDir).catch(() => null);
|
|
4598
5024
|
if (!groupStat?.isDirectory())
|
|
4599
5025
|
continue;
|
|
4600
5026
|
const decodedCwd = await resolveEncodedCwd(groupDir, group);
|
|
@@ -4602,14 +5028,14 @@ async function listSessionDirs(root) {
|
|
|
4602
5028
|
for (const entry of entries) {
|
|
4603
5029
|
if (entry === "prompt_history.jsonl" || entry.startsWith("."))
|
|
4604
5030
|
continue;
|
|
4605
|
-
const dirPath =
|
|
4606
|
-
const summaryPath =
|
|
4607
|
-
const updatesPath =
|
|
4608
|
-
const signalsCandidate =
|
|
5031
|
+
const dirPath = path7.join(groupDir, entry);
|
|
5032
|
+
const summaryPath = path7.join(dirPath, "summary.json");
|
|
5033
|
+
const updatesPath = path7.join(dirPath, "updates.jsonl");
|
|
5034
|
+
const signalsCandidate = path7.join(dirPath, "signals.json");
|
|
4609
5035
|
const [summaryStat, updatesStat, signalsStat] = await Promise.all([
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
5036
|
+
fs7.stat(summaryPath).catch(() => null),
|
|
5037
|
+
fs7.stat(updatesPath).catch(() => null),
|
|
5038
|
+
fs7.stat(signalsCandidate).catch(() => null)
|
|
4613
5039
|
]);
|
|
4614
5040
|
if (!summaryStat?.isFile())
|
|
4615
5041
|
continue;
|
|
@@ -4630,10 +5056,10 @@ async function listSessionDirs(root) {
|
|
|
4630
5056
|
}
|
|
4631
5057
|
return out;
|
|
4632
5058
|
}
|
|
4633
|
-
function
|
|
5059
|
+
function emptyUsage5() {
|
|
4634
5060
|
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
4635
5061
|
}
|
|
4636
|
-
function
|
|
5062
|
+
function previewOf5(text) {
|
|
4637
5063
|
return text.replace(/\s+/g, " ").trim().slice(0, 200);
|
|
4638
5064
|
}
|
|
4639
5065
|
function truncate5(s, n) {
|
|
@@ -4747,7 +5173,7 @@ function lineTimestampIso(line) {
|
|
|
4747
5173
|
}
|
|
4748
5174
|
return void 0;
|
|
4749
5175
|
}
|
|
4750
|
-
function
|
|
5176
|
+
function computeActiveSegments6(tsMs) {
|
|
4751
5177
|
if (tsMs.length === 0)
|
|
4752
5178
|
return [];
|
|
4753
5179
|
const sorted = [...tsMs].sort((a, b) => a - b);
|
|
@@ -4756,7 +5182,7 @@ function computeActiveSegments5(tsMs) {
|
|
|
4756
5182
|
let segEnd = sorted[0];
|
|
4757
5183
|
for (let i = 1; i < sorted.length; i++) {
|
|
4758
5184
|
const t = sorted[i];
|
|
4759
|
-
if (t - segEnd >
|
|
5185
|
+
if (t - segEnd > IDLE_GAP_MS5) {
|
|
4760
5186
|
out.push({ startMs: segStart, endMs: segEnd });
|
|
4761
5187
|
segStart = t;
|
|
4762
5188
|
}
|
|
@@ -4765,17 +5191,17 @@ function computeActiveSegments5(tsMs) {
|
|
|
4765
5191
|
out.push({ startMs: segStart, endMs: segEnd });
|
|
4766
5192
|
return out;
|
|
4767
5193
|
}
|
|
4768
|
-
async function
|
|
5194
|
+
async function parseSession4(dir) {
|
|
4769
5195
|
const [summary, signals, updatesRaw] = await Promise.all([
|
|
4770
5196
|
safeReadJson(dir.summaryPath),
|
|
4771
5197
|
dir.signalsPath ? safeReadJson(dir.signalsPath) : Promise.resolve(null),
|
|
4772
|
-
|
|
5198
|
+
fs7.readFile(dir.updatesPath, "utf8").catch(() => "")
|
|
4773
5199
|
]);
|
|
4774
5200
|
const sessionId = summary?.info?.id ?? dir.sessionId;
|
|
4775
5201
|
const cwd = summary?.info?.cwd ?? dir.decodedCwd;
|
|
4776
5202
|
let model = summary?.current_model_id ?? signals?.primaryModelId ?? signals?.modelsUsed?.[0];
|
|
4777
5203
|
const events = [];
|
|
4778
|
-
const totalUsage =
|
|
5204
|
+
const totalUsage = emptyUsage5();
|
|
4779
5205
|
if (signals?.contextTokensUsed && signals.contextTokensUsed > 0) {
|
|
4780
5206
|
totalUsage.input = signals.contextTokensUsed;
|
|
4781
5207
|
}
|
|
@@ -4809,7 +5235,7 @@ async function parseSession3(dir) {
|
|
|
4809
5235
|
if (!buf)
|
|
4810
5236
|
return;
|
|
4811
5237
|
const text = buf.texts.join("");
|
|
4812
|
-
const preview =
|
|
5238
|
+
const preview = previewOf5(text);
|
|
4813
5239
|
if (buf.kind === "user") {
|
|
4814
5240
|
const isHidden = !text || isFrameworkInjectedUserInput(text);
|
|
4815
5241
|
if (text && !isHidden) {
|
|
@@ -4969,7 +5395,7 @@ async function parseSession3(dir) {
|
|
|
4969
5395
|
timestamp: ts,
|
|
4970
5396
|
role: "tool-result",
|
|
4971
5397
|
rawType: "grok/tool_result",
|
|
4972
|
-
preview:
|
|
5398
|
+
preview: previewOf5(resultText),
|
|
4973
5399
|
blocks: [
|
|
4974
5400
|
{
|
|
4975
5401
|
type: "tool_result",
|
|
@@ -5018,7 +5444,7 @@ async function parseSession3(dir) {
|
|
|
5018
5444
|
prevMs = ms;
|
|
5019
5445
|
}
|
|
5020
5446
|
}
|
|
5021
|
-
const activeSegments =
|
|
5447
|
+
const activeSegments = computeActiveSegments6(tsMs);
|
|
5022
5448
|
const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
|
|
5023
5449
|
const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
|
|
5024
5450
|
const project = cwd ? resolveProjectIdentity(cwd) : void 0;
|
|
@@ -5027,7 +5453,7 @@ async function parseSession3(dir) {
|
|
|
5027
5453
|
if (!firstUserPreview) {
|
|
5028
5454
|
const title = summary?.generated_title || summary?.session_summary;
|
|
5029
5455
|
if (title)
|
|
5030
|
-
firstUserPreview =
|
|
5456
|
+
firstUserPreview = previewOf5(title);
|
|
5031
5457
|
}
|
|
5032
5458
|
const spawnedAgentCount = await countSubagentChildren(dir.dirPath);
|
|
5033
5459
|
const meta = {
|
|
@@ -5064,38 +5490,38 @@ async function parseSession3(dir) {
|
|
|
5064
5490
|
return { meta, events, sessionKind: summary?.session_kind };
|
|
5065
5491
|
}
|
|
5066
5492
|
async function countSubagentChildren(dirPath) {
|
|
5067
|
-
const subRoot =
|
|
5493
|
+
const subRoot = path7.join(dirPath, "subagents");
|
|
5068
5494
|
const entries = await safeReaddir5(subRoot);
|
|
5069
5495
|
let n = 0;
|
|
5070
5496
|
for (const e of entries) {
|
|
5071
|
-
const st = await
|
|
5497
|
+
const st = await fs7.stat(path7.join(subRoot, e)).catch(() => null);
|
|
5072
5498
|
if (st?.isDirectory())
|
|
5073
5499
|
n += 1;
|
|
5074
5500
|
}
|
|
5075
5501
|
return n;
|
|
5076
5502
|
}
|
|
5077
5503
|
async function loadGrokSubagents(parentDir, parentStartMs) {
|
|
5078
|
-
const subRoot =
|
|
5504
|
+
const subRoot = path7.join(parentDir.dirPath, "subagents");
|
|
5079
5505
|
const entries = await safeReaddir5(subRoot);
|
|
5080
|
-
const groupDir =
|
|
5506
|
+
const groupDir = path7.dirname(parentDir.dirPath);
|
|
5081
5507
|
const runs = [];
|
|
5082
5508
|
for (const entry of entries) {
|
|
5083
|
-
const metaPath =
|
|
5509
|
+
const metaPath = path7.join(subRoot, entry, "meta.json");
|
|
5084
5510
|
const meta = await safeReadJson(metaPath);
|
|
5085
5511
|
if (!meta)
|
|
5086
5512
|
continue;
|
|
5087
5513
|
const childId = meta.child_session_id ?? meta.subagent_id ?? entry;
|
|
5088
|
-
const childDir =
|
|
5514
|
+
const childDir = path7.join(groupDir, childId);
|
|
5089
5515
|
const [childSummary, childSignals] = await Promise.all([
|
|
5090
|
-
safeReadJson(
|
|
5091
|
-
safeReadJson(
|
|
5516
|
+
safeReadJson(path7.join(childDir, "summary.json")),
|
|
5517
|
+
safeReadJson(path7.join(childDir, "signals.json"))
|
|
5092
5518
|
]);
|
|
5093
5519
|
const startMs = childSummary?.created_at ? Date.parse(childSummary.created_at) : void 0;
|
|
5094
5520
|
const endIso = childSummary?.last_active_at ?? childSummary?.updated_at;
|
|
5095
5521
|
const endMs = endIso ? Date.parse(endIso) : void 0;
|
|
5096
5522
|
const startOk = startMs !== void 0 && Number.isFinite(startMs) ? startMs : void 0;
|
|
5097
5523
|
const endOk = endMs !== void 0 && Number.isFinite(endMs) ? endMs : void 0;
|
|
5098
|
-
const usage =
|
|
5524
|
+
const usage = emptyUsage5();
|
|
5099
5525
|
if (childSignals?.contextTokensUsed)
|
|
5100
5526
|
usage.input = childSignals.contextTokensUsed;
|
|
5101
5527
|
runs.push({
|
|
@@ -5118,8 +5544,8 @@ async function loadGrokSubagents(parentDir, parentStartMs) {
|
|
|
5118
5544
|
return runs;
|
|
5119
5545
|
}
|
|
5120
5546
|
function clearGrokCaches() {
|
|
5121
|
-
|
|
5122
|
-
|
|
5547
|
+
metaCache7.clear();
|
|
5548
|
+
detailCache7.clear();
|
|
5123
5549
|
}
|
|
5124
5550
|
async function listGrokSessions(opts = {}) {
|
|
5125
5551
|
const root = opts.root ?? resolveDefaultGrokRoot();
|
|
@@ -5129,16 +5555,16 @@ async function listGrokSessions(opts = {}) {
|
|
|
5129
5555
|
const summaryPeek = await safeReadJson(dir.summaryPath);
|
|
5130
5556
|
if (summaryPeek?.session_kind === "subagent")
|
|
5131
5557
|
continue;
|
|
5132
|
-
const cached =
|
|
5558
|
+
const cached = metaCache7.get(dir.dirPath);
|
|
5133
5559
|
if (cached && cached.mtimeMs === dir.mtimeMs && cached.sizeBytes === dir.sizeBytes) {
|
|
5134
5560
|
out.push(cached.meta);
|
|
5135
5561
|
continue;
|
|
5136
5562
|
}
|
|
5137
5563
|
try {
|
|
5138
|
-
const { meta, sessionKind } = await
|
|
5564
|
+
const { meta, sessionKind } = await parseSession4(dir);
|
|
5139
5565
|
if (sessionKind === "subagent")
|
|
5140
5566
|
continue;
|
|
5141
|
-
|
|
5567
|
+
metaCache7.set(dir.dirPath, {
|
|
5142
5568
|
meta,
|
|
5143
5569
|
mtimeMs: dir.mtimeMs,
|
|
5144
5570
|
sizeBytes: dir.sizeBytes
|
|
@@ -5159,10 +5585,10 @@ async function getGrokSession(id, opts = {}) {
|
|
|
5159
5585
|
if (!chosen) {
|
|
5160
5586
|
for (const dir of dirs) {
|
|
5161
5587
|
try {
|
|
5162
|
-
const { meta: meta2, events: events2 } = await
|
|
5588
|
+
const { meta: meta2, events: events2 } = await parseSession4(dir);
|
|
5163
5589
|
if (meta2.id === id) {
|
|
5164
5590
|
const detail2 = { ...meta2, events: events2 };
|
|
5165
|
-
|
|
5591
|
+
detailCache7.set(dir.dirPath, {
|
|
5166
5592
|
detail: detail2,
|
|
5167
5593
|
mtimeMs: dir.mtimeMs,
|
|
5168
5594
|
sizeBytes: dir.sizeBytes
|
|
@@ -5174,11 +5600,11 @@ async function getGrokSession(id, opts = {}) {
|
|
|
5174
5600
|
}
|
|
5175
5601
|
return null;
|
|
5176
5602
|
}
|
|
5177
|
-
const cached =
|
|
5603
|
+
const cached = detailCache7.get(chosen.dirPath);
|
|
5178
5604
|
if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes) {
|
|
5179
5605
|
return cached.detail;
|
|
5180
5606
|
}
|
|
5181
|
-
const { meta, events } = await
|
|
5607
|
+
const { meta, events } = await parseSession4(chosen);
|
|
5182
5608
|
const parentStartMs = meta.firstTimestamp ? Date.parse(meta.firstTimestamp) : void 0;
|
|
5183
5609
|
const subagents = await loadGrokSubagents(chosen, parentStartMs !== void 0 && Number.isFinite(parentStartMs) ? parentStartMs : void 0);
|
|
5184
5610
|
const detail = {
|
|
@@ -5186,12 +5612,12 @@ async function getGrokSession(id, opts = {}) {
|
|
|
5186
5612
|
events,
|
|
5187
5613
|
...subagents.length > 0 ? { subagents, spawnedAgentCount: subagents.length } : {}
|
|
5188
5614
|
};
|
|
5189
|
-
|
|
5615
|
+
detailCache7.set(chosen.dirPath, {
|
|
5190
5616
|
detail,
|
|
5191
5617
|
mtimeMs: chosen.mtimeMs,
|
|
5192
5618
|
sizeBytes: chosen.sizeBytes
|
|
5193
5619
|
});
|
|
5194
|
-
|
|
5620
|
+
metaCache7.set(chosen.dirPath, {
|
|
5195
5621
|
meta: {
|
|
5196
5622
|
...meta,
|
|
5197
5623
|
...subagents.length > 0 ? { spawnedAgentCount: subagents.length } : {}
|
|
@@ -5207,17 +5633,17 @@ function grokSessionLocalDay(meta) {
|
|
|
5207
5633
|
const ms = Date.parse(meta.firstTimestamp);
|
|
5208
5634
|
return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
|
|
5209
5635
|
}
|
|
5210
|
-
var DEFAULT_GROK_ROOT,
|
|
5636
|
+
var DEFAULT_GROK_ROOT, IDLE_GAP_MS5, metaCache7, detailCache7;
|
|
5211
5637
|
var init_grok = __esm({
|
|
5212
5638
|
"../parser/dist/grok.js"() {
|
|
5213
5639
|
"use strict";
|
|
5214
5640
|
init_analytics();
|
|
5215
5641
|
init_git_project();
|
|
5216
5642
|
init_user_input();
|
|
5217
|
-
DEFAULT_GROK_ROOT =
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5643
|
+
DEFAULT_GROK_ROOT = path7.join(os7.homedir(), ".grok", "sessions");
|
|
5644
|
+
IDLE_GAP_MS5 = 3 * 60 * 1e3;
|
|
5645
|
+
metaCache7 = /* @__PURE__ */ new Map();
|
|
5646
|
+
detailCache7 = /* @__PURE__ */ new Map();
|
|
5221
5647
|
}
|
|
5222
5648
|
});
|
|
5223
5649
|
|
|
@@ -5278,6 +5704,7 @@ var fs_exports = {};
|
|
|
5278
5704
|
__export(fs_exports, {
|
|
5279
5705
|
DEFAULT_ANTIGRAVITY_ROOT: () => DEFAULT_ANTIGRAVITY_ROOT,
|
|
5280
5706
|
DEFAULT_CODEX_ROOT: () => DEFAULT_CODEX_ROOT,
|
|
5707
|
+
DEFAULT_COPILOT_ROOT: () => DEFAULT_COPILOT_ROOT,
|
|
5281
5708
|
DEFAULT_COWORK_ROOT: () => DEFAULT_COWORK_ROOT,
|
|
5282
5709
|
DEFAULT_GEMINI_ROOT: () => DEFAULT_GEMINI_ROOT,
|
|
5283
5710
|
DEFAULT_GROK_ROOT: () => DEFAULT_GROK_ROOT,
|
|
@@ -5294,6 +5721,7 @@ __export(fs_exports, {
|
|
|
5294
5721
|
clearGrokCaches: () => clearGrokCaches,
|
|
5295
5722
|
clearTeamConfig: () => clearTeamConfig,
|
|
5296
5723
|
codexSessionLocalDay: () => codexSessionLocalDay,
|
|
5724
|
+
copilotSessionLocalDay: () => copilotSessionLocalDay,
|
|
5297
5725
|
decodeProjectName: () => decodeProjectName,
|
|
5298
5726
|
findTeamLead: () => findTeamLead,
|
|
5299
5727
|
geminiSessionLocalDay: () => geminiSessionLocalDay,
|
|
@@ -5301,6 +5729,7 @@ __export(fs_exports, {
|
|
|
5301
5729
|
getAntigravitySession: () => getAntigravitySession,
|
|
5302
5730
|
getAnySession: () => getAnySession,
|
|
5303
5731
|
getCodexSession: () => getCodexSession,
|
|
5732
|
+
getCopilotSession: () => getCopilotSession,
|
|
5304
5733
|
getCoworkSession: () => getCoworkSession,
|
|
5305
5734
|
getGeminiSession: () => getGeminiSession,
|
|
5306
5735
|
getGrokSession: () => getGrokSession,
|
|
@@ -5312,6 +5741,7 @@ __export(fs_exports, {
|
|
|
5312
5741
|
listAllSessions: () => listAllSessions,
|
|
5313
5742
|
listAntigravitySessions: () => listAntigravitySessions,
|
|
5314
5743
|
listCodexSessions: () => listCodexSessions,
|
|
5744
|
+
listCopilotSessions: () => listCopilotSessions,
|
|
5315
5745
|
listCoworkSessions: () => listCoworkSessions,
|
|
5316
5746
|
listGeminiSessions: () => listGeminiSessions,
|
|
5317
5747
|
listGrokSessions: () => listGrokSessions,
|
|
@@ -5334,14 +5764,14 @@ __export(fs_exports, {
|
|
|
5334
5764
|
walkJsonlFiles: () => walkJsonlFiles,
|
|
5335
5765
|
writeTeamConfig: () => writeTeamConfig
|
|
5336
5766
|
});
|
|
5337
|
-
import { promises as
|
|
5338
|
-
import
|
|
5339
|
-
import
|
|
5767
|
+
import { promises as fs8, existsSync as existsSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync2, appendFileSync, mkdirSync as mkdirSync2 } from "node:fs";
|
|
5768
|
+
import os8 from "node:os";
|
|
5769
|
+
import path8 from "node:path";
|
|
5340
5770
|
function cclensHome() {
|
|
5341
|
-
return process.env.CCLENS_HOME ||
|
|
5771
|
+
return process.env.CCLENS_HOME || path8.join(os8.homedir(), ".cclens");
|
|
5342
5772
|
}
|
|
5343
5773
|
function cclensPath(...parts) {
|
|
5344
|
-
return
|
|
5774
|
+
return path8.join(cclensHome(), ...parts);
|
|
5345
5775
|
}
|
|
5346
5776
|
function cacheStats() {
|
|
5347
5777
|
return claudeCodeCacheStats();
|
|
@@ -5349,6 +5779,7 @@ function cacheStats() {
|
|
|
5349
5779
|
function clearCaches() {
|
|
5350
5780
|
clearClaudeCodeCaches();
|
|
5351
5781
|
clearCodexCaches();
|
|
5782
|
+
clearCopilotCaches();
|
|
5352
5783
|
clearGeminiCaches();
|
|
5353
5784
|
clearAntigravityCaches();
|
|
5354
5785
|
clearCoworkCaches();
|
|
@@ -5383,7 +5814,7 @@ function usageLogPath() {
|
|
|
5383
5814
|
}
|
|
5384
5815
|
function appendUsageSnapshot(snapshot) {
|
|
5385
5816
|
const p = usageLogPath();
|
|
5386
|
-
mkdirSync2(
|
|
5817
|
+
mkdirSync2(path8.dirname(p), { recursive: true });
|
|
5387
5818
|
appendFileSync(p, JSON.stringify(snapshot) + "\n", "utf8");
|
|
5388
5819
|
}
|
|
5389
5820
|
function pruneUsageAgent(agent) {
|
|
@@ -5399,13 +5830,13 @@ function pruneUsageAgent(agent) {
|
|
|
5399
5830
|
return true;
|
|
5400
5831
|
}
|
|
5401
5832
|
});
|
|
5402
|
-
mkdirSync2(
|
|
5833
|
+
mkdirSync2(path8.dirname(p), { recursive: true });
|
|
5403
5834
|
writeFileSync2(p, kept.join("\n") + (kept.length ? "\n" : ""), "utf8");
|
|
5404
5835
|
}
|
|
5405
5836
|
async function loadUsageByDay(start, end) {
|
|
5406
5837
|
let raw;
|
|
5407
5838
|
try {
|
|
5408
|
-
raw = await
|
|
5839
|
+
raw = await fs8.readFile(usageLogPath(), "utf8");
|
|
5409
5840
|
} catch {
|
|
5410
5841
|
return { by_day: [] };
|
|
5411
5842
|
}
|
|
@@ -5450,7 +5881,7 @@ async function loadUsageByDay(start, end) {
|
|
|
5450
5881
|
async function loadCalibrationSnapshots() {
|
|
5451
5882
|
let raw;
|
|
5452
5883
|
try {
|
|
5453
|
-
raw = await
|
|
5884
|
+
raw = await fs8.readFile(usageLogPath(), "utf8");
|
|
5454
5885
|
} catch {
|
|
5455
5886
|
return [];
|
|
5456
5887
|
}
|
|
@@ -5614,7 +6045,7 @@ async function loadCalibrationCurve(tier = "pro-max-20x", root = DEFAULT_ROOT, g
|
|
|
5614
6045
|
]);
|
|
5615
6046
|
return buildCalibrationCurve(events, snapshots, tier, granularityMin);
|
|
5616
6047
|
}
|
|
5617
|
-
var codexSource, geminiSource, antigravitySource, coworkSource, grokSource, agentSources;
|
|
6048
|
+
var codexSource, copilotSource, geminiSource, antigravitySource, coworkSource, grokSource, agentSources;
|
|
5618
6049
|
var init_fs = __esm({
|
|
5619
6050
|
"../parser/dist/fs.js"() {
|
|
5620
6051
|
"use strict";
|
|
@@ -5623,6 +6054,7 @@ var init_fs = __esm({
|
|
|
5623
6054
|
init_calibration();
|
|
5624
6055
|
init_claude_code();
|
|
5625
6056
|
init_codex();
|
|
6057
|
+
init_copilot();
|
|
5626
6058
|
init_gemini();
|
|
5627
6059
|
init_antigravity();
|
|
5628
6060
|
init_cowork();
|
|
@@ -5630,6 +6062,7 @@ var init_fs = __esm({
|
|
|
5630
6062
|
init_claude_code();
|
|
5631
6063
|
init_git_project();
|
|
5632
6064
|
init_codex();
|
|
6065
|
+
init_copilot();
|
|
5633
6066
|
init_gemini();
|
|
5634
6067
|
init_antigravity();
|
|
5635
6068
|
init_cowork();
|
|
@@ -5646,6 +6079,16 @@ var init_fs = __esm({
|
|
|
5646
6079
|
return getCodexSession(id);
|
|
5647
6080
|
}
|
|
5648
6081
|
};
|
|
6082
|
+
copilotSource = {
|
|
6083
|
+
...COPILOT_METADATA,
|
|
6084
|
+
defaultRoot: DEFAULT_COPILOT_ROOT,
|
|
6085
|
+
async listSessions(opts) {
|
|
6086
|
+
return listCopilotSessions(opts);
|
|
6087
|
+
},
|
|
6088
|
+
async getSession(id, opts) {
|
|
6089
|
+
return getCopilotSession(id, opts);
|
|
6090
|
+
}
|
|
6091
|
+
};
|
|
5649
6092
|
geminiSource = {
|
|
5650
6093
|
...GEMINI_METADATA,
|
|
5651
6094
|
defaultRoot: DEFAULT_GEMINI_ROOT,
|
|
@@ -5690,6 +6133,7 @@ var init_fs = __esm({
|
|
|
5690
6133
|
agentSources = [
|
|
5691
6134
|
claudeCodeSource,
|
|
5692
6135
|
codexSource,
|
|
6136
|
+
copilotSource,
|
|
5693
6137
|
geminiSource,
|
|
5694
6138
|
antigravitySource,
|
|
5695
6139
|
coworkSource,
|
|
@@ -5699,14 +6143,14 @@ var init_fs = __esm({
|
|
|
5699
6143
|
});
|
|
5700
6144
|
|
|
5701
6145
|
// src/usage/storage.ts
|
|
5702
|
-
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync4, existsSync as
|
|
5703
|
-
import { dirname as
|
|
6146
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync4, existsSync as existsSync7 } from "node:fs";
|
|
6147
|
+
import { dirname as dirname3 } from "node:path";
|
|
5704
6148
|
function appendSnapshot(filePath, snapshot) {
|
|
5705
|
-
mkdirSync3(
|
|
6149
|
+
mkdirSync3(dirname3(filePath), { recursive: true });
|
|
5706
6150
|
appendFileSync2(filePath, JSON.stringify(snapshot) + "\n", "utf8");
|
|
5707
6151
|
}
|
|
5708
6152
|
function readSnapshots(filePath) {
|
|
5709
|
-
if (!
|
|
6153
|
+
if (!existsSync7(filePath)) return [];
|
|
5710
6154
|
const content = readFileSync8(filePath, "utf8");
|
|
5711
6155
|
const snapshots = [];
|
|
5712
6156
|
for (const line of content.split("\n")) {
|
|
@@ -5719,7 +6163,7 @@ function readSnapshots(filePath) {
|
|
|
5719
6163
|
return snapshots;
|
|
5720
6164
|
}
|
|
5721
6165
|
function pruneAgent(filePath, agent) {
|
|
5722
|
-
if (!
|
|
6166
|
+
if (!existsSync7(filePath)) return;
|
|
5723
6167
|
const kept = readFileSync8(filePath, "utf8").split("\n").filter((line) => {
|
|
5724
6168
|
if (!line.trim()) return false;
|
|
5725
6169
|
try {
|
|
@@ -5728,7 +6172,7 @@ function pruneAgent(filePath, agent) {
|
|
|
5728
6172
|
return true;
|
|
5729
6173
|
}
|
|
5730
6174
|
});
|
|
5731
|
-
mkdirSync3(
|
|
6175
|
+
mkdirSync3(dirname3(filePath), { recursive: true });
|
|
5732
6176
|
writeFileSync4(filePath, kept.join("\n") + (kept.length ? "\n" : ""), "utf8");
|
|
5733
6177
|
}
|
|
5734
6178
|
function latestClaudeCodeSnapshot(filePath) {
|
|
@@ -6156,6 +6600,7 @@ __export(dist_exports, {
|
|
|
6156
6600
|
ANTIGRAVITY_METADATA: () => ANTIGRAVITY_METADATA,
|
|
6157
6601
|
CLAUDE_CODE_METADATA: () => CLAUDE_CODE_METADATA,
|
|
6158
6602
|
CODEX_METADATA: () => CODEX_METADATA,
|
|
6603
|
+
COPILOT_METADATA: () => COPILOT_METADATA,
|
|
6159
6604
|
COWORK_METADATA: () => COWORK_METADATA,
|
|
6160
6605
|
GEMINI_METADATA: () => GEMINI_METADATA,
|
|
6161
6606
|
GROK_METADATA: () => GROK_METADATA,
|
|
@@ -6232,25 +6677,25 @@ __export(file_probe_exports, {
|
|
|
6232
6677
|
probeArtifactSignals: () => probeArtifactSignals
|
|
6233
6678
|
});
|
|
6234
6679
|
import { createHash } from "node:crypto";
|
|
6235
|
-
import { existsSync as
|
|
6680
|
+
import { existsSync as existsSync12, readdirSync as readdirSync3, statSync as statSync5 } from "node:fs";
|
|
6236
6681
|
import { homedir as homedir3 } from "node:os";
|
|
6237
|
-
import { join as
|
|
6682
|
+
import { join as join9, relative, resolve as resolve3, sep } from "node:path";
|
|
6238
6683
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
6239
6684
|
function pathHash(relPath) {
|
|
6240
6685
|
return createHash("sha256").update(relPath.split(sep).join("/")).digest("hex").slice(0, 32);
|
|
6241
6686
|
}
|
|
6242
6687
|
function defaultScanRoots(extraRoots = []) {
|
|
6243
6688
|
const roots = [];
|
|
6244
|
-
const home =
|
|
6245
|
-
if (
|
|
6689
|
+
const home = join9(homedir3(), ".claude");
|
|
6690
|
+
if (existsSync12(home)) roots.push({ root: home, label: "user" });
|
|
6246
6691
|
for (const e of extraRoots) {
|
|
6247
6692
|
const r = resolve3(e, ".claude");
|
|
6248
|
-
if (
|
|
6693
|
+
if (existsSync12(r) && r !== home) roots.push({ root: r, label: "project" });
|
|
6249
6694
|
}
|
|
6250
6695
|
return roots;
|
|
6251
6696
|
}
|
|
6252
6697
|
function listMarkdownFiles(dir) {
|
|
6253
|
-
if (!
|
|
6698
|
+
if (!existsSync12(dir)) return [];
|
|
6254
6699
|
const out = [];
|
|
6255
6700
|
let entries;
|
|
6256
6701
|
try {
|
|
@@ -6260,7 +6705,7 @@ function listMarkdownFiles(dir) {
|
|
|
6260
6705
|
}
|
|
6261
6706
|
for (const name of entries) {
|
|
6262
6707
|
if (name.startsWith(".")) continue;
|
|
6263
|
-
const full =
|
|
6708
|
+
const full = join9(dir, name);
|
|
6264
6709
|
let stat;
|
|
6265
6710
|
try {
|
|
6266
6711
|
stat = statSync5(full);
|
|
@@ -6280,7 +6725,7 @@ function firstSeenDateOf(file) {
|
|
|
6280
6725
|
const out = execFileSync2(
|
|
6281
6726
|
"git",
|
|
6282
6727
|
["log", "--diff-filter=A", "--follow", "--format=%cs", "--", file],
|
|
6283
|
-
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd:
|
|
6728
|
+
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd: dirname9(file) }
|
|
6284
6729
|
).trim().split("\n").filter(Boolean);
|
|
6285
6730
|
if (out.length > 0) return out[out.length - 1];
|
|
6286
6731
|
} catch {
|
|
@@ -6292,7 +6737,7 @@ function firstSeenDateOf(file) {
|
|
|
6292
6737
|
return todayLocal();
|
|
6293
6738
|
}
|
|
6294
6739
|
}
|
|
6295
|
-
function
|
|
6740
|
+
function dirname9(p) {
|
|
6296
6741
|
const i = p.lastIndexOf(sep);
|
|
6297
6742
|
return i < 0 ? "." : p.slice(0, i);
|
|
6298
6743
|
}
|
|
@@ -6319,8 +6764,8 @@ function todayLocal() {
|
|
|
6319
6764
|
function scanAuthored(roots, subdir, day) {
|
|
6320
6765
|
const out = [];
|
|
6321
6766
|
for (const r of roots) {
|
|
6322
|
-
const dir =
|
|
6323
|
-
if (!
|
|
6767
|
+
const dir = join9(r.root, subdir);
|
|
6768
|
+
if (!existsSync12(dir)) continue;
|
|
6324
6769
|
for (const f of listMarkdownFiles(dir)) {
|
|
6325
6770
|
const firstSeen = firstSeenDateOf(f);
|
|
6326
6771
|
if (firstSeen !== day) continue;
|
|
@@ -6333,8 +6778,8 @@ function scanAuthored(roots, subdir, day) {
|
|
|
6333
6778
|
function scanEdited(roots, day) {
|
|
6334
6779
|
const out = [];
|
|
6335
6780
|
for (const r of roots) {
|
|
6336
|
-
const dir =
|
|
6337
|
-
if (!
|
|
6781
|
+
const dir = join9(r.root, "skills");
|
|
6782
|
+
if (!existsSync12(dir)) continue;
|
|
6338
6783
|
for (const f of listMarkdownFiles(dir)) {
|
|
6339
6784
|
const firstSeen = firstSeenDateOf(f);
|
|
6340
6785
|
if (firstSeen === day) continue;
|
|
@@ -6357,16 +6802,16 @@ function claudemdLineDelta(extraRoots, authorEmail, day) {
|
|
|
6357
6802
|
const candidates = [];
|
|
6358
6803
|
for (const e of extraRoots) {
|
|
6359
6804
|
const f = resolve3(e, "CLAUDE.md");
|
|
6360
|
-
if (
|
|
6805
|
+
if (existsSync12(f)) candidates.push(f);
|
|
6361
6806
|
}
|
|
6362
|
-
const homeClaudeMd =
|
|
6363
|
-
if (
|
|
6807
|
+
const homeClaudeMd = join9(homedir3(), "CLAUDE.md");
|
|
6808
|
+
if (existsSync12(homeClaudeMd)) candidates.push(homeClaudeMd);
|
|
6364
6809
|
for (const file of candidates) {
|
|
6365
6810
|
try {
|
|
6366
6811
|
const out = execFileSync2(
|
|
6367
6812
|
"git",
|
|
6368
6813
|
["log", "--numstat", "--format=COMMIT %cs %ae", "--", file],
|
|
6369
|
-
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd:
|
|
6814
|
+
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd: dirname9(file) }
|
|
6370
6815
|
);
|
|
6371
6816
|
let currentDate = "";
|
|
6372
6817
|
let currentEmail = "";
|
|
@@ -6416,9 +6861,9 @@ var init_file_probe = __esm({
|
|
|
6416
6861
|
});
|
|
6417
6862
|
|
|
6418
6863
|
// src/daemon-worker.ts
|
|
6419
|
-
import { spawn as
|
|
6420
|
-
import { closeSync, existsSync as
|
|
6421
|
-
import { dirname as
|
|
6864
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
6865
|
+
import { closeSync, existsSync as existsSync19, mkdirSync as mkdirSync14, openSync, readFileSync as readFileSync21, writeFileSync as writeFileSync15 } from "node:fs";
|
|
6866
|
+
import { dirname as dirname12, join as join13 } from "node:path";
|
|
6422
6867
|
import { fileURLToPath } from "node:url";
|
|
6423
6868
|
|
|
6424
6869
|
// src/usage/token.ts
|
|
@@ -6449,9 +6894,9 @@ function readFromCredentialsFile() {
|
|
|
6449
6894
|
join(homedir(), ".claude", ".credentials.json"),
|
|
6450
6895
|
join(homedir(), ".config", "claude", "credentials.json")
|
|
6451
6896
|
];
|
|
6452
|
-
for (const
|
|
6897
|
+
for (const path11 of candidates) {
|
|
6453
6898
|
try {
|
|
6454
|
-
const blob = readFileSync(
|
|
6899
|
+
const blob = readFileSync(path11, "utf8");
|
|
6455
6900
|
const creds = extractCredentials(blob);
|
|
6456
6901
|
if (creds) return creds;
|
|
6457
6902
|
} catch {
|
|
@@ -6665,8 +7110,8 @@ async function fetchZaiUsage() {
|
|
|
6665
7110
|
|
|
6666
7111
|
// src/usage/grok.ts
|
|
6667
7112
|
import { existsSync as existsSync4, readFileSync as readFileSync6 } from "node:fs";
|
|
6668
|
-
import
|
|
6669
|
-
import
|
|
7113
|
+
import os9 from "node:os";
|
|
7114
|
+
import path9 from "node:path";
|
|
6670
7115
|
var CREDITS_URL = "https://cli-chat-proxy.grok.com/v1/billing?format=credits";
|
|
6671
7116
|
var SETTINGS_URL = "https://cli-chat-proxy.grok.com/v1/settings";
|
|
6672
7117
|
var REFRESH_URL = "https://auth.x.ai/oauth2/token";
|
|
@@ -6681,10 +7126,10 @@ var GrokApiError = class extends Error {
|
|
|
6681
7126
|
}
|
|
6682
7127
|
};
|
|
6683
7128
|
function grokHome() {
|
|
6684
|
-
return process.env.GROK_HOME ||
|
|
7129
|
+
return process.env.GROK_HOME || path9.join(os9.homedir(), ".grok");
|
|
6685
7130
|
}
|
|
6686
7131
|
function authPath() {
|
|
6687
|
-
return
|
|
7132
|
+
return path9.join(grokHome(), "auth.json");
|
|
6688
7133
|
}
|
|
6689
7134
|
function loadAuthEntry() {
|
|
6690
7135
|
const p = authPath();
|
|
@@ -6881,8 +7326,8 @@ import {
|
|
|
6881
7326
|
readFileSync as readFileSync7,
|
|
6882
7327
|
writeFileSync as writeFileSync3
|
|
6883
7328
|
} from "node:fs";
|
|
6884
|
-
import
|
|
6885
|
-
import
|
|
7329
|
+
import os10 from "node:os";
|
|
7330
|
+
import path10 from "node:path";
|
|
6886
7331
|
var USAGE_URL = "https://chatgpt.com/backend-api/wham/usage";
|
|
6887
7332
|
var REFRESH_URL2 = "https://auth.openai.com/oauth/token";
|
|
6888
7333
|
var CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
@@ -6898,10 +7343,10 @@ var CodexApiError = class extends Error {
|
|
|
6898
7343
|
function codexHome() {
|
|
6899
7344
|
const env = process.env.CODEX_HOME?.trim();
|
|
6900
7345
|
if (env) return env;
|
|
6901
|
-
return
|
|
7346
|
+
return path10.join(os10.homedir(), ".codex");
|
|
6902
7347
|
}
|
|
6903
7348
|
function authPath2() {
|
|
6904
|
-
return
|
|
7349
|
+
return path10.join(codexHome(), "auth.json");
|
|
6905
7350
|
}
|
|
6906
7351
|
function loadAuth() {
|
|
6907
7352
|
const p = authPath2();
|
|
@@ -7016,7 +7461,7 @@ function authHeaders2(accessToken, accountId) {
|
|
|
7016
7461
|
}
|
|
7017
7462
|
return headers;
|
|
7018
7463
|
}
|
|
7019
|
-
function
|
|
7464
|
+
function numberOf3(v) {
|
|
7020
7465
|
if (typeof v === "number" && Number.isFinite(v)) return v;
|
|
7021
7466
|
if (typeof v === "string" && v.trim()) {
|
|
7022
7467
|
const n = Number(v);
|
|
@@ -7026,21 +7471,21 @@ function numberOf2(v) {
|
|
|
7026
7471
|
}
|
|
7027
7472
|
function windowSeconds(raw) {
|
|
7028
7473
|
if (!raw) return void 0;
|
|
7029
|
-
const sec =
|
|
7474
|
+
const sec = numberOf3(raw.limit_window_seconds);
|
|
7030
7475
|
if (sec !== void 0) return sec;
|
|
7031
|
-
const minutes =
|
|
7476
|
+
const minutes = numberOf3(raw.window_minutes);
|
|
7032
7477
|
if (minutes !== void 0) return minutes * 60;
|
|
7033
7478
|
return void 0;
|
|
7034
7479
|
}
|
|
7035
7480
|
function normalizeWindow2(raw, headerPercent, nowMs) {
|
|
7036
|
-
const used =
|
|
7481
|
+
const used = numberOf3(raw?.used_percent) ?? headerPercent;
|
|
7037
7482
|
if (used === void 0) return null;
|
|
7038
7483
|
let resetsAt = null;
|
|
7039
|
-
const resetUnix =
|
|
7484
|
+
const resetUnix = numberOf3(raw?.reset_at) ?? numberOf3(raw?.resets_at);
|
|
7040
7485
|
if (resetUnix !== void 0) {
|
|
7041
7486
|
resetsAt = new Date(resetUnix * 1e3).toISOString();
|
|
7042
7487
|
} else {
|
|
7043
|
-
const after =
|
|
7488
|
+
const after = numberOf3(raw?.reset_after_seconds);
|
|
7044
7489
|
if (after !== void 0) {
|
|
7045
7490
|
resetsAt = new Date(nowMs + after * 1e3).toISOString();
|
|
7046
7491
|
}
|
|
@@ -7056,8 +7501,8 @@ function parseCodexWhamUsage(body, headers = {}, nowMs = Date.now()) {
|
|
|
7056
7501
|
}
|
|
7057
7502
|
const b = body;
|
|
7058
7503
|
const rateLimit = b.rate_limit && typeof b.rate_limit === "object" ? b.rate_limit : {};
|
|
7059
|
-
const headerPrimary =
|
|
7060
|
-
const headerSecondary =
|
|
7504
|
+
const headerPrimary = numberOf3(headers["x-codex-primary-used-percent"]);
|
|
7505
|
+
const headerSecondary = numberOf3(headers["x-codex-secondary-used-percent"]);
|
|
7061
7506
|
const primary = rateLimit.primary_window && typeof rateLimit.primary_window === "object" ? rateLimit.primary_window : null;
|
|
7062
7507
|
const secondary = rateLimit.secondary_window && typeof rateLimit.secondary_window === "object" ? rateLimit.secondary_window : null;
|
|
7063
7508
|
const candidates = [
|
|
@@ -7155,6 +7600,208 @@ async function fetchCodexUsage() {
|
|
|
7155
7600
|
};
|
|
7156
7601
|
}
|
|
7157
7602
|
|
|
7603
|
+
// src/usage/copilot.ts
|
|
7604
|
+
import { spawn } from "node:child_process";
|
|
7605
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
7606
|
+
import { dirname as dirname2, join as join4 } from "node:path";
|
|
7607
|
+
var RPC_TIMEOUT_MS = 1e4;
|
|
7608
|
+
var CopilotApiError = class extends Error {
|
|
7609
|
+
constructor(message, code) {
|
|
7610
|
+
super(message);
|
|
7611
|
+
this.code = code;
|
|
7612
|
+
}
|
|
7613
|
+
};
|
|
7614
|
+
function recordOf2(value) {
|
|
7615
|
+
return typeof value === "object" && value !== null ? value : void 0;
|
|
7616
|
+
}
|
|
7617
|
+
function numberOf4(value) {
|
|
7618
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
7619
|
+
}
|
|
7620
|
+
function clampPercent(value) {
|
|
7621
|
+
return Math.min(100, Math.max(0, value));
|
|
7622
|
+
}
|
|
7623
|
+
function nextCopilotMonthlyReset(nowMs = Date.now()) {
|
|
7624
|
+
const now = new Date(nowMs);
|
|
7625
|
+
return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() + 1, 1)).toISOString();
|
|
7626
|
+
}
|
|
7627
|
+
function quotaResetDate(value, nowMs) {
|
|
7628
|
+
const parsed = typeof value === "string" ? Date.parse(value) : Number.NaN;
|
|
7629
|
+
return Number.isFinite(parsed) && parsed > nowMs + 6e4 ? new Date(parsed).toISOString() : nextCopilotMonthlyReset(nowMs);
|
|
7630
|
+
}
|
|
7631
|
+
function parseCopilotQuota(body, nowMs = Date.now()) {
|
|
7632
|
+
const root = recordOf2(body);
|
|
7633
|
+
const snapshots = recordOf2(root?.quotaSnapshots);
|
|
7634
|
+
if (!snapshots) {
|
|
7635
|
+
throw new CopilotApiError("Copilot quota response missing quotaSnapshots", "parse");
|
|
7636
|
+
}
|
|
7637
|
+
const chat = recordOf2(snapshots.chat);
|
|
7638
|
+
const legacy = recordOf2(snapshots.premium_interactions);
|
|
7639
|
+
const chatLimit = numberOf4(chat?.entitlementRequests);
|
|
7640
|
+
const quota = chat && (chatLimit !== void 0 && chatLimit > 0 || chat.isUnlimitedEntitlement === true) ? chat : legacy;
|
|
7641
|
+
if (!quota) {
|
|
7642
|
+
throw new CopilotApiError("Copilot quota response has no chat allowance", "parse");
|
|
7643
|
+
}
|
|
7644
|
+
const unlimited = quota.isUnlimitedEntitlement === true;
|
|
7645
|
+
const remainingPercent = numberOf4(quota.remainingPercentage);
|
|
7646
|
+
const utilization = unlimited ? null : remainingPercent === void 0 ? null : clampPercent(100 - remainingPercent);
|
|
7647
|
+
const limit = numberOf4(quota.entitlementRequests) ?? null;
|
|
7648
|
+
const used = numberOf4(quota.usedRequests) ?? null;
|
|
7649
|
+
const unit = quota.tokenBasedBilling === true ? "ai-credits" : "premium-requests";
|
|
7650
|
+
return {
|
|
7651
|
+
captured_at: new Date(nowMs).toISOString(),
|
|
7652
|
+
agent: "copilot",
|
|
7653
|
+
five_hour: { utilization: null, resets_at: null },
|
|
7654
|
+
seven_day: { utilization: null, resets_at: null },
|
|
7655
|
+
monthly: {
|
|
7656
|
+
utilization,
|
|
7657
|
+
resets_at: quotaResetDate(quota.resetDate, nowMs)
|
|
7658
|
+
},
|
|
7659
|
+
monthly_quota: {
|
|
7660
|
+
used,
|
|
7661
|
+
limit,
|
|
7662
|
+
remaining: used !== null && limit !== null ? Math.max(0, limit - used) : null,
|
|
7663
|
+
unit,
|
|
7664
|
+
unlimited
|
|
7665
|
+
},
|
|
7666
|
+
seven_day_opus: null,
|
|
7667
|
+
seven_day_sonnet: null,
|
|
7668
|
+
seven_day_oauth_apps: null,
|
|
7669
|
+
seven_day_cowork: null,
|
|
7670
|
+
extra_usage: null,
|
|
7671
|
+
plan_type: unit === "ai-credits" ? "AI credits" : "premium requests"
|
|
7672
|
+
};
|
|
7673
|
+
}
|
|
7674
|
+
var ContentLengthDecoder = class {
|
|
7675
|
+
buffer = Buffer.alloc(0);
|
|
7676
|
+
push(chunk2) {
|
|
7677
|
+
this.buffer = Buffer.concat([this.buffer, chunk2]);
|
|
7678
|
+
const messages = [];
|
|
7679
|
+
while (true) {
|
|
7680
|
+
const headerEnd = this.buffer.indexOf("\r\n\r\n");
|
|
7681
|
+
if (headerEnd === -1) break;
|
|
7682
|
+
const header = this.buffer.subarray(0, headerEnd).toString("ascii");
|
|
7683
|
+
const match = header.match(/(?:^|\r\n)Content-Length:\s*(\d+)/i);
|
|
7684
|
+
if (!match) {
|
|
7685
|
+
throw new CopilotApiError("Copilot RPC response missing Content-Length", "protocol");
|
|
7686
|
+
}
|
|
7687
|
+
const length = Number(match[1]);
|
|
7688
|
+
const bodyStart = headerEnd + 4;
|
|
7689
|
+
if (this.buffer.length < bodyStart + length) break;
|
|
7690
|
+
const body = this.buffer.subarray(bodyStart, bodyStart + length).toString("utf8");
|
|
7691
|
+
this.buffer = this.buffer.subarray(bodyStart + length);
|
|
7692
|
+
try {
|
|
7693
|
+
messages.push(JSON.parse(body));
|
|
7694
|
+
} catch {
|
|
7695
|
+
throw new CopilotApiError("Copilot RPC returned invalid JSON", "protocol");
|
|
7696
|
+
}
|
|
7697
|
+
}
|
|
7698
|
+
return messages;
|
|
7699
|
+
}
|
|
7700
|
+
};
|
|
7701
|
+
function rpcFrame(message) {
|
|
7702
|
+
const body = Buffer.from(JSON.stringify(message), "utf8");
|
|
7703
|
+
return Buffer.concat([
|
|
7704
|
+
Buffer.from(`Content-Length: ${body.length}\r
|
|
7705
|
+
\r
|
|
7706
|
+
`, "ascii"),
|
|
7707
|
+
body
|
|
7708
|
+
]);
|
|
7709
|
+
}
|
|
7710
|
+
function resolveCopilotCliPath() {
|
|
7711
|
+
const configured = process.env.COPILOT_CLI_PATH?.trim();
|
|
7712
|
+
if (configured) return configured;
|
|
7713
|
+
const sibling = join4(dirname2(process.execPath), process.platform === "win32" ? "copilot.cmd" : "copilot");
|
|
7714
|
+
return existsSync6(sibling) ? sibling : process.platform === "win32" ? "copilot.cmd" : "copilot";
|
|
7715
|
+
}
|
|
7716
|
+
async function requestQuota(child) {
|
|
7717
|
+
const decoder = new ContentLengthDecoder();
|
|
7718
|
+
const pending = /* @__PURE__ */ new Map();
|
|
7719
|
+
let nextId = 1;
|
|
7720
|
+
const rejectAll = (error) => {
|
|
7721
|
+
for (const waiter of pending.values()) waiter.reject(error);
|
|
7722
|
+
pending.clear();
|
|
7723
|
+
};
|
|
7724
|
+
child.stdout.on("data", (chunk2) => {
|
|
7725
|
+
try {
|
|
7726
|
+
for (const value of decoder.push(chunk2)) {
|
|
7727
|
+
const message = recordOf2(value);
|
|
7728
|
+
const id = numberOf4(message?.id);
|
|
7729
|
+
if (id === void 0) continue;
|
|
7730
|
+
const waiter = pending.get(id);
|
|
7731
|
+
if (!waiter) continue;
|
|
7732
|
+
pending.delete(id);
|
|
7733
|
+
const rpcError = recordOf2(message?.error);
|
|
7734
|
+
if (rpcError) {
|
|
7735
|
+
waiter.reject(new CopilotApiError(
|
|
7736
|
+
typeof rpcError.message === "string" ? rpcError.message : "Copilot RPC request failed",
|
|
7737
|
+
"protocol"
|
|
7738
|
+
));
|
|
7739
|
+
} else {
|
|
7740
|
+
waiter.resolve(message?.result);
|
|
7741
|
+
}
|
|
7742
|
+
}
|
|
7743
|
+
} catch (error) {
|
|
7744
|
+
rejectAll(error);
|
|
7745
|
+
}
|
|
7746
|
+
});
|
|
7747
|
+
const exited = new Promise((_, reject) => {
|
|
7748
|
+
child.once("error", (error) => {
|
|
7749
|
+
reject(new CopilotApiError(
|
|
7750
|
+
error.message,
|
|
7751
|
+
error.code === "ENOENT" ? "no_cli" : "protocol"
|
|
7752
|
+
));
|
|
7753
|
+
});
|
|
7754
|
+
child.once("exit", (code) => {
|
|
7755
|
+
reject(new CopilotApiError(`Copilot RPC exited before responding (code ${code ?? "unknown"})`, "protocol"));
|
|
7756
|
+
});
|
|
7757
|
+
});
|
|
7758
|
+
const request = (method, params = {}) => {
|
|
7759
|
+
const id = nextId++;
|
|
7760
|
+
const response = new Promise((resolve4, reject) => {
|
|
7761
|
+
pending.set(id, { resolve: resolve4, reject });
|
|
7762
|
+
child.stdin.write(rpcFrame({ jsonrpc: "2.0", id, method, params }));
|
|
7763
|
+
});
|
|
7764
|
+
return Promise.race([response, exited]);
|
|
7765
|
+
};
|
|
7766
|
+
await request("connect", {});
|
|
7767
|
+
return request("account.getQuota", {});
|
|
7768
|
+
}
|
|
7769
|
+
async function fetchCopilotUsage() {
|
|
7770
|
+
const cliPath = resolveCopilotCliPath();
|
|
7771
|
+
const child = spawn(cliPath, ["--headless", "--no-auto-update", "--stdio", "--log-level", "none"], {
|
|
7772
|
+
cwd: process.cwd(),
|
|
7773
|
+
env: process.env,
|
|
7774
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
7775
|
+
windowsHide: true,
|
|
7776
|
+
shell: process.platform === "win32"
|
|
7777
|
+
});
|
|
7778
|
+
let stderr = "";
|
|
7779
|
+
child.stderr.on("data", (chunk2) => {
|
|
7780
|
+
stderr = (stderr + chunk2.toString("utf8")).slice(-2e3);
|
|
7781
|
+
});
|
|
7782
|
+
const timeout = new Promise((_, reject) => {
|
|
7783
|
+
const handle = setTimeout(() => {
|
|
7784
|
+
reject(new CopilotApiError("Timed out reading Copilot quota", "timeout"));
|
|
7785
|
+
}, RPC_TIMEOUT_MS);
|
|
7786
|
+
handle.unref();
|
|
7787
|
+
});
|
|
7788
|
+
try {
|
|
7789
|
+
const body = await Promise.race([requestQuota(child), timeout]);
|
|
7790
|
+
return parseCopilotQuota(body);
|
|
7791
|
+
} catch (error) {
|
|
7792
|
+
if (error instanceof CopilotApiError) {
|
|
7793
|
+
const message = `${error.message} ${stderr}`.toLowerCase();
|
|
7794
|
+
if (message.includes("not logged") || message.includes("authentication")) {
|
|
7795
|
+
throw new CopilotApiError("Copilot not logged in. Run `copilot login`.", "no_auth");
|
|
7796
|
+
}
|
|
7797
|
+
throw error;
|
|
7798
|
+
}
|
|
7799
|
+
throw new CopilotApiError(error.message, "protocol");
|
|
7800
|
+
} finally {
|
|
7801
|
+
child.kill();
|
|
7802
|
+
}
|
|
7803
|
+
}
|
|
7804
|
+
|
|
7158
7805
|
// src/daemon-worker.ts
|
|
7159
7806
|
init_storage();
|
|
7160
7807
|
init_fs();
|
|
@@ -7196,9 +7843,9 @@ import { randomUUID } from "node:crypto";
|
|
|
7196
7843
|
|
|
7197
7844
|
// ../entries/dist/fs.js
|
|
7198
7845
|
init_fs();
|
|
7199
|
-
import { readFileSync as readFileSync10, readdirSync as readdirSync2, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, renameSync as renameSync3, existsSync as
|
|
7846
|
+
import { readFileSync as readFileSync10, readdirSync as readdirSync2, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, renameSync as renameSync3, existsSync as existsSync9 } from "node:fs";
|
|
7200
7847
|
import { randomBytes } from "node:crypto";
|
|
7201
|
-
import { join as
|
|
7848
|
+
import { join as join6 } from "node:path";
|
|
7202
7849
|
|
|
7203
7850
|
// ../entries/dist/types.js
|
|
7204
7851
|
var CURRENT_ENTRY_SCHEMA_VERSION = 2;
|
|
@@ -7271,12 +7918,12 @@ var PROMPT_FRAME_ORIGIN = {
|
|
|
7271
7918
|
|
|
7272
7919
|
// ../entries/dist/digest-fs.js
|
|
7273
7920
|
init_fs();
|
|
7274
|
-
import { readFileSync as readFileSync9, readdirSync, writeFileSync as writeFileSync5, renameSync as renameSync2, chmodSync, mkdirSync as mkdirSync4, existsSync as
|
|
7275
|
-
import { dirname as
|
|
7921
|
+
import { readFileSync as readFileSync9, readdirSync, writeFileSync as writeFileSync5, renameSync as renameSync2, chmodSync, mkdirSync as mkdirSync4, existsSync as existsSync8 } from "node:fs";
|
|
7922
|
+
import { dirname as dirname4, join as join5 } from "node:path";
|
|
7276
7923
|
var digestsDirCached = null;
|
|
7277
|
-
function parseDigestFile(
|
|
7924
|
+
function parseDigestFile(path11, expectedVersion) {
|
|
7278
7925
|
try {
|
|
7279
|
-
const parsed = JSON.parse(readFileSync9(
|
|
7926
|
+
const parsed = JSON.parse(readFileSync9(path11, "utf8"));
|
|
7280
7927
|
if (!parsed || typeof parsed !== "object")
|
|
7281
7928
|
return null;
|
|
7282
7929
|
if (parsed.version !== expectedVersion)
|
|
@@ -7296,14 +7943,14 @@ function digestsDir() {
|
|
|
7296
7943
|
return digestsDirCached;
|
|
7297
7944
|
}
|
|
7298
7945
|
function dayDigestPath(date) {
|
|
7299
|
-
return
|
|
7946
|
+
return join5(digestsDir(), "day", `${date}.json`);
|
|
7300
7947
|
}
|
|
7301
7948
|
function weekDigestPath(monday) {
|
|
7302
|
-
return
|
|
7949
|
+
return join5(digestsDir(), "week", `${monday}.json`);
|
|
7303
7950
|
}
|
|
7304
7951
|
function writeDayDigest(digest) {
|
|
7305
7952
|
const final = dayDigestPath(digest.key);
|
|
7306
|
-
mkdirSync4(
|
|
7953
|
+
mkdirSync4(dirname4(final), { recursive: true });
|
|
7307
7954
|
const tmp = `${final}.tmp`;
|
|
7308
7955
|
writeFileSync5(tmp, JSON.stringify(digest, null, 2), "utf8");
|
|
7309
7956
|
if (process.platform !== "win32") {
|
|
@@ -7316,7 +7963,7 @@ function writeDayDigest(digest) {
|
|
|
7316
7963
|
}
|
|
7317
7964
|
function readDayDigest(date) {
|
|
7318
7965
|
const p = dayDigestPath(date);
|
|
7319
|
-
if (!
|
|
7966
|
+
if (!existsSync8(p))
|
|
7320
7967
|
return null;
|
|
7321
7968
|
return parseDigestFile(p, CURRENT_DAY_DIGEST_SCHEMA_VERSION);
|
|
7322
7969
|
}
|
|
@@ -7336,7 +7983,7 @@ function setTodayDigestInCache(date, digest, nowMs) {
|
|
|
7336
7983
|
}
|
|
7337
7984
|
function writeWeekDigest(digest) {
|
|
7338
7985
|
const final = weekDigestPath(digest.key);
|
|
7339
|
-
mkdirSync4(
|
|
7986
|
+
mkdirSync4(dirname4(final), { recursive: true });
|
|
7340
7987
|
const tmp = `${final}.tmp`;
|
|
7341
7988
|
writeFileSync5(tmp, JSON.stringify(digest, null, 2), "utf8");
|
|
7342
7989
|
if (process.platform !== "win32") {
|
|
@@ -7349,7 +7996,7 @@ function writeWeekDigest(digest) {
|
|
|
7349
7996
|
}
|
|
7350
7997
|
function readWeekDigest(monday) {
|
|
7351
7998
|
const p = weekDigestPath(monday);
|
|
7352
|
-
if (!
|
|
7999
|
+
if (!existsSync8(p))
|
|
7353
8000
|
return null;
|
|
7354
8001
|
return parseDigestFile(p, CURRENT_WEEK_DIGEST_SCHEMA_VERSION);
|
|
7355
8002
|
}
|
|
@@ -7379,7 +8026,7 @@ function entriesDir() {
|
|
|
7379
8026
|
return entriesDirCached;
|
|
7380
8027
|
}
|
|
7381
8028
|
function pathFor(sessionId, localDay2) {
|
|
7382
|
-
return
|
|
8029
|
+
return join6(entriesDir(), `${entryKey(sessionId, localDay2)}.json`);
|
|
7383
8030
|
}
|
|
7384
8031
|
function tmpPathFor(final) {
|
|
7385
8032
|
return `${final}.tmp.${process.pid}.${randomBytes(4).toString("hex")}`;
|
|
@@ -7427,17 +8074,17 @@ function writeEntryPreservingEnrichment(fresh) {
|
|
|
7427
8074
|
}
|
|
7428
8075
|
function readEntry(sessionId, localDay2) {
|
|
7429
8076
|
const p = pathFor(sessionId, localDay2);
|
|
7430
|
-
if (!
|
|
8077
|
+
if (!existsSync9(p))
|
|
7431
8078
|
return null;
|
|
7432
8079
|
const raw = readFileSync10(p, "utf8");
|
|
7433
8080
|
return JSON.parse(raw);
|
|
7434
8081
|
}
|
|
7435
8082
|
function entryExists(sessionId, localDay2) {
|
|
7436
|
-
return
|
|
8083
|
+
return existsSync9(pathFor(sessionId, localDay2));
|
|
7437
8084
|
}
|
|
7438
8085
|
function listEntryKeys() {
|
|
7439
8086
|
const dir = entriesDir();
|
|
7440
|
-
if (!
|
|
8087
|
+
if (!existsSync9(dir))
|
|
7441
8088
|
return [];
|
|
7442
8089
|
return readdirSync2(dir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length));
|
|
7443
8090
|
}
|
|
@@ -7457,7 +8104,7 @@ function listEntriesForDay(localDay2) {
|
|
|
7457
8104
|
// src/perception/build-entries.ts
|
|
7458
8105
|
init_dist();
|
|
7459
8106
|
import { statSync as statSync2, readFileSync as readFileSync11 } from "node:fs";
|
|
7460
|
-
import { basename as basename2, dirname as
|
|
8107
|
+
import { basename as basename2, dirname as dirname5 } from "node:path";
|
|
7461
8108
|
|
|
7462
8109
|
// ../entries/dist/signals.js
|
|
7463
8110
|
init_dist();
|
|
@@ -7690,7 +8337,7 @@ function viewEvent(ev) {
|
|
|
7690
8337
|
cwd: rawCwd
|
|
7691
8338
|
};
|
|
7692
8339
|
}
|
|
7693
|
-
var
|
|
8340
|
+
var IDLE_GAP_MS6 = 3 * 60 * 1e3;
|
|
7694
8341
|
var INTERRUPT_RE2 = /\[request interrupted|interrupted by user/i;
|
|
7695
8342
|
var PR_TITLE_RE = /--title\s+["']([^"']+)["']/;
|
|
7696
8343
|
var BASH_CHAIN_SPLIT_RE = /\|\||&&|;|\|/;
|
|
@@ -7802,7 +8449,7 @@ function closeTurn(t, closed, cwd) {
|
|
|
7802
8449
|
let active = 0;
|
|
7803
8450
|
for (let i = 1; i < ts.length; i++) {
|
|
7804
8451
|
const dt = ts[i] - ts[i - 1];
|
|
7805
|
-
if (dt <
|
|
8452
|
+
if (dt < IDLE_GAP_MS6)
|
|
7806
8453
|
active += dt;
|
|
7807
8454
|
}
|
|
7808
8455
|
closed.push({
|
|
@@ -7999,7 +8646,7 @@ function aggregateDay(dayEvents, _sessionFallbackProject) {
|
|
|
7999
8646
|
let activeMs2 = 0;
|
|
8000
8647
|
for (let i = 1; i < tsSorted.length; i++) {
|
|
8001
8648
|
const dt = tsSorted[i] - tsSorted[i - 1];
|
|
8002
|
-
if (dt <
|
|
8649
|
+
if (dt < IDLE_GAP_MS6)
|
|
8003
8650
|
activeMs2 += dt;
|
|
8004
8651
|
}
|
|
8005
8652
|
const tsSortedStrings = dayEvents.map((e) => e.timestamp).filter((t) => !!t).sort();
|
|
@@ -8207,7 +8854,7 @@ function buildEntriesForFile(filePath) {
|
|
|
8207
8854
|
if (rawLines.length === 0) return null;
|
|
8208
8855
|
const { meta, events } = parseTranscript(rawLines);
|
|
8209
8856
|
const fileName = basename2(filePath);
|
|
8210
|
-
const projectDir = basename2(
|
|
8857
|
+
const projectDir = basename2(dirname5(filePath));
|
|
8211
8858
|
const sessionId = fileName.replace(/\.jsonl$/, "");
|
|
8212
8859
|
const sd = {
|
|
8213
8860
|
...meta,
|
|
@@ -8457,7 +9104,7 @@ function buildIngestPayload(inputs) {
|
|
|
8457
9104
|
return {
|
|
8458
9105
|
ingestId: randomUUID(),
|
|
8459
9106
|
observedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8460
|
-
cliVersion: "0.16.
|
|
9107
|
+
cliVersion: "0.16.8",
|
|
8461
9108
|
...richRollup || inputs.enrichedExtras || inputs.artifactSignals ? { schemaVersion: RICH_ROLLUP_SCHEMA_VERSION } : {},
|
|
8462
9109
|
...inputs.rollup ? { dailyRollup: inputs.rollup } : {},
|
|
8463
9110
|
...richRollup ? { richRollup } : {},
|
|
@@ -8484,8 +9131,8 @@ async function pushToTeamServer(config, payload) {
|
|
|
8484
9131
|
}
|
|
8485
9132
|
|
|
8486
9133
|
// src/team/git-remote.ts
|
|
8487
|
-
import { existsSync as
|
|
8488
|
-
import { dirname as
|
|
9134
|
+
import { existsSync as existsSync10, readFileSync as readFileSync12, statSync as statSync3 } from "node:fs";
|
|
9135
|
+
import { dirname as dirname6, isAbsolute as isAbsolute2, join as join7, resolve as resolve2 } from "node:path";
|
|
8489
9136
|
var GITHUB_URL_RE = /github\.com[:/]([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+?)(?:\.git)?$/;
|
|
8490
9137
|
function parseGithubRemote(url) {
|
|
8491
9138
|
const m = url.trim().match(GITHUB_URL_RE);
|
|
@@ -8506,19 +9153,19 @@ function originUrl2(configText) {
|
|
|
8506
9153
|
return null;
|
|
8507
9154
|
}
|
|
8508
9155
|
function gitConfigPathFor(dir) {
|
|
8509
|
-
const dotGit =
|
|
9156
|
+
const dotGit = join7(dir, ".git");
|
|
8510
9157
|
const st = statSync3(dotGit, { throwIfNoEntry: false });
|
|
8511
9158
|
if (!st) return null;
|
|
8512
|
-
if (st.isDirectory()) return
|
|
9159
|
+
if (st.isDirectory()) return join7(dotGit, "config");
|
|
8513
9160
|
const m = readFileSync12(dotGit, "utf8").match(/^gitdir:\s*(.+)\s*$/m);
|
|
8514
9161
|
if (!m) return null;
|
|
8515
9162
|
const gd = isAbsolute2(m[1]) ? m[1] : resolve2(dir, m[1]);
|
|
8516
|
-
const commondirFile =
|
|
8517
|
-
if (
|
|
9163
|
+
const commondirFile = join7(gd, "commondir");
|
|
9164
|
+
if (existsSync10(commondirFile)) {
|
|
8518
9165
|
const common = readFileSync12(commondirFile, "utf8").trim();
|
|
8519
|
-
return
|
|
9166
|
+
return join7(isAbsolute2(common) ? common : resolve2(gd, common), "config");
|
|
8520
9167
|
}
|
|
8521
|
-
return
|
|
9168
|
+
return join7(gd, "config");
|
|
8522
9169
|
}
|
|
8523
9170
|
function createRepoResolver() {
|
|
8524
9171
|
const cache = /* @__PURE__ */ new Map();
|
|
@@ -8528,14 +9175,14 @@ function createRepoResolver() {
|
|
|
8528
9175
|
if (hit !== void 0) return hit;
|
|
8529
9176
|
let repo = null;
|
|
8530
9177
|
try {
|
|
8531
|
-
for (let d = dir; ; d =
|
|
9178
|
+
for (let d = dir; ; d = dirname6(d)) {
|
|
8532
9179
|
const config = gitConfigPathFor(d);
|
|
8533
|
-
if (config &&
|
|
9180
|
+
if (config && existsSync10(config)) {
|
|
8534
9181
|
const url = originUrl2(readFileSync12(config, "utf8"));
|
|
8535
9182
|
repo = url ? parseGithubRemote(url) : null;
|
|
8536
9183
|
break;
|
|
8537
9184
|
}
|
|
8538
|
-
if (d ===
|
|
9185
|
+
if (d === dirname6(d)) break;
|
|
8539
9186
|
}
|
|
8540
9187
|
} catch {
|
|
8541
9188
|
repo = null;
|
|
@@ -8548,12 +9195,12 @@ function createRepoResolver() {
|
|
|
8548
9195
|
// src/team/queue.ts
|
|
8549
9196
|
init_fs();
|
|
8550
9197
|
import { readFileSync as readFileSync13, writeFileSync as writeFileSync7, appendFileSync as appendFileSync4, statSync as statSync4, mkdirSync as mkdirSync6 } from "node:fs";
|
|
8551
|
-
import { dirname as
|
|
9198
|
+
import { dirname as dirname7 } from "node:path";
|
|
8552
9199
|
var QUEUE_PATH = cclensPath("ingest-queue.jsonl");
|
|
8553
9200
|
var MAX_SIZE_BYTES = 10 * 1024 * 1024;
|
|
8554
9201
|
var MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
8555
9202
|
function enqueuePayload(payload, queuePath = QUEUE_PATH) {
|
|
8556
|
-
mkdirSync6(
|
|
9203
|
+
mkdirSync6(dirname7(queuePath), { recursive: true });
|
|
8557
9204
|
const entry = { payload, enqueuedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
8558
9205
|
appendFileSync4(queuePath, JSON.stringify(entry) + "\n", "utf8");
|
|
8559
9206
|
try {
|
|
@@ -8601,8 +9248,8 @@ init_storage();
|
|
|
8601
9248
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
8602
9249
|
|
|
8603
9250
|
// src/usage/profile.ts
|
|
8604
|
-
import { existsSync as
|
|
8605
|
-
import { dirname as
|
|
9251
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync7, readFileSync as readFileSync14, writeFileSync as writeFileSync8 } from "node:fs";
|
|
9252
|
+
import { dirname as dirname8 } from "node:path";
|
|
8606
9253
|
var PROFILE_ENDPOINT = "https://api.anthropic.com/api/oauth/profile";
|
|
8607
9254
|
var BETA_HEADER2 = "oauth-2025-04-20";
|
|
8608
9255
|
var PROFILE_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -8645,7 +9292,7 @@ async function fetchProfile(nowMs = Date.now()) {
|
|
|
8645
9292
|
};
|
|
8646
9293
|
}
|
|
8647
9294
|
function readCachedProfile(cachePath) {
|
|
8648
|
-
if (!
|
|
9295
|
+
if (!existsSync11(cachePath)) return null;
|
|
8649
9296
|
try {
|
|
8650
9297
|
const raw = JSON.parse(readFileSync14(cachePath, "utf8"));
|
|
8651
9298
|
if (typeof raw.fetchedAtMs !== "number" || !raw.profile) return null;
|
|
@@ -8655,7 +9302,7 @@ function readCachedProfile(cachePath) {
|
|
|
8655
9302
|
}
|
|
8656
9303
|
}
|
|
8657
9304
|
function writeCachedProfile(cachePath, profile, nowMs = Date.now()) {
|
|
8658
|
-
mkdirSync7(
|
|
9305
|
+
mkdirSync7(dirname8(cachePath), { recursive: true });
|
|
8659
9306
|
writeFileSync8(
|
|
8660
9307
|
cachePath,
|
|
8661
9308
|
JSON.stringify({ fetchedAtMs: nowMs, profile }, null, 2),
|
|
@@ -8843,12 +9490,12 @@ function readPendingSyncLog(watermark) {
|
|
|
8843
9490
|
// src/team/last-push.ts
|
|
8844
9491
|
init_fs();
|
|
8845
9492
|
import { writeFileSync as writeFileSync9, unlinkSync as unlinkSync2, mkdirSync as mkdirSync8 } from "node:fs";
|
|
8846
|
-
import { join as
|
|
9493
|
+
import { join as join8 } from "node:path";
|
|
8847
9494
|
var LAST_PUSH_FILE = "team-last-push.json";
|
|
8848
9495
|
function write(record, dir) {
|
|
8849
9496
|
const d = dir ?? cclensHome();
|
|
8850
9497
|
mkdirSync8(d, { recursive: true });
|
|
8851
|
-
writeFileSync9(
|
|
9498
|
+
writeFileSync9(join8(d, LAST_PUSH_FILE), JSON.stringify(record, null, 2), { mode: 384 });
|
|
8852
9499
|
}
|
|
8853
9500
|
function writeLastPushSuccess(payload, dir) {
|
|
8854
9501
|
write({ pushedAt: (/* @__PURE__ */ new Date()).toISOString(), ok: true, payload }, dir);
|
|
@@ -9448,8 +10095,8 @@ init_fs();
|
|
|
9448
10095
|
|
|
9449
10096
|
// src/perception/state.ts
|
|
9450
10097
|
init_fs();
|
|
9451
|
-
import { existsSync as
|
|
9452
|
-
import { dirname as
|
|
10098
|
+
import { existsSync as existsSync13, readFileSync as readFileSync16, writeFileSync as writeFileSync10, mkdirSync as mkdirSync9, renameSync as renameSync4 } from "node:fs";
|
|
10099
|
+
import { dirname as dirname10 } from "node:path";
|
|
9453
10100
|
var STALE_MS = 15 * 60 * 1e3;
|
|
9454
10101
|
var pathCached = null;
|
|
9455
10102
|
function statePath() {
|
|
@@ -9459,7 +10106,7 @@ function statePath() {
|
|
|
9459
10106
|
}
|
|
9460
10107
|
function readState() {
|
|
9461
10108
|
const p = statePath();
|
|
9462
|
-
if (!
|
|
10109
|
+
if (!existsSync13(p)) {
|
|
9463
10110
|
return {
|
|
9464
10111
|
sweep_in_progress: false,
|
|
9465
10112
|
last_sweep_started_at: null,
|
|
@@ -9472,7 +10119,7 @@ function readState() {
|
|
|
9472
10119
|
}
|
|
9473
10120
|
function writeState(s) {
|
|
9474
10121
|
const p = statePath();
|
|
9475
|
-
mkdirSync9(
|
|
10122
|
+
mkdirSync9(dirname10(p), { recursive: true });
|
|
9476
10123
|
const tmp = `${p}.tmp`;
|
|
9477
10124
|
writeFileSync10(tmp, JSON.stringify(s, null, 2), "utf8");
|
|
9478
10125
|
renameSync4(tmp, p);
|
|
@@ -9504,17 +10151,17 @@ function updateCheckpoint(jsonlPath, cp) {
|
|
|
9504
10151
|
|
|
9505
10152
|
// src/perception/scan.ts
|
|
9506
10153
|
import { readdirSync as readdirSync4 } from "node:fs";
|
|
9507
|
-
import { join as
|
|
10154
|
+
import { join as join10 } from "node:path";
|
|
9508
10155
|
import { homedir as homedir4 } from "node:os";
|
|
9509
10156
|
async function listAllSessionJsonls(root) {
|
|
9510
|
-
const projectsRoot = root ??
|
|
10157
|
+
const projectsRoot = root ?? join10(homedir4(), ".claude", "projects");
|
|
9511
10158
|
const out = [];
|
|
9512
10159
|
try {
|
|
9513
10160
|
for (const project of readdirSync4(projectsRoot)) {
|
|
9514
|
-
const dir =
|
|
10161
|
+
const dir = join10(projectsRoot, project);
|
|
9515
10162
|
try {
|
|
9516
10163
|
for (const f of readdirSync4(dir)) {
|
|
9517
|
-
if (f.endsWith(".jsonl")) out.push(
|
|
10164
|
+
if (f.endsWith(".jsonl")) out.push(join10(dir, f));
|
|
9518
10165
|
}
|
|
9519
10166
|
} catch {
|
|
9520
10167
|
}
|
|
@@ -10075,8 +10722,8 @@ function getErrorMap() {
|
|
|
10075
10722
|
|
|
10076
10723
|
// ../../node_modules/zod/v3/helpers/parseUtil.js
|
|
10077
10724
|
var makeIssue = (params) => {
|
|
10078
|
-
const { data, path:
|
|
10079
|
-
const fullPath = [...
|
|
10725
|
+
const { data, path: path11, errorMaps, issueData } = params;
|
|
10726
|
+
const fullPath = [...path11, ...issueData.path || []];
|
|
10080
10727
|
const fullIssue = {
|
|
10081
10728
|
...issueData,
|
|
10082
10729
|
path: fullPath
|
|
@@ -10192,11 +10839,11 @@ var errorUtil;
|
|
|
10192
10839
|
|
|
10193
10840
|
// ../../node_modules/zod/v3/types.js
|
|
10194
10841
|
var ParseInputLazyPath = class {
|
|
10195
|
-
constructor(parent, value,
|
|
10842
|
+
constructor(parent, value, path11, key) {
|
|
10196
10843
|
this._cachedPath = [];
|
|
10197
10844
|
this.parent = parent;
|
|
10198
10845
|
this.data = value;
|
|
10199
|
-
this._path =
|
|
10846
|
+
this._path = path11;
|
|
10200
10847
|
this._key = key;
|
|
10201
10848
|
}
|
|
10202
10849
|
get path() {
|
|
@@ -13729,14 +14376,14 @@ var ENRICHMENT_SYSTEM_PROMPT = SYSTEM_PROMPT;
|
|
|
13729
14376
|
|
|
13730
14377
|
// ../entries/dist/llm-runner.js
|
|
13731
14378
|
init_fs();
|
|
13732
|
-
import { spawn } from "node:child_process";
|
|
13733
|
-
import { mkdirSync as mkdirSync11, appendFileSync as appendFileSync5, writeFileSync as writeFileSync12, existsSync as
|
|
13734
|
-
import { join as
|
|
14379
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
14380
|
+
import { mkdirSync as mkdirSync11, appendFileSync as appendFileSync5, writeFileSync as writeFileSync12, existsSync as existsSync15 } from "node:fs";
|
|
14381
|
+
import { join as join12 } from "node:path";
|
|
13735
14382
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
13736
14383
|
|
|
13737
14384
|
// ../entries/dist/tmux-runner.js
|
|
13738
|
-
import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync11, existsSync as
|
|
13739
|
-
import { join as
|
|
14385
|
+
import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync11, existsSync as existsSync14, readdirSync as readdirSync5, realpathSync as realpathSync2, readFileSync as readFileSync17, unlinkSync as unlinkSync3, renameSync as renameSync5 } from "node:fs";
|
|
14386
|
+
import { join as join11 } from "node:path";
|
|
13740
14387
|
import { homedir as homedir5 } from "node:os";
|
|
13741
14388
|
import { spawnSync } from "node:child_process";
|
|
13742
14389
|
var TmuxUnavailableError = class extends Error {
|
|
@@ -13765,13 +14412,13 @@ function tmuxRunnerAvailable() {
|
|
|
13765
14412
|
return { ok: true };
|
|
13766
14413
|
}
|
|
13767
14414
|
function runtimeCwd() {
|
|
13768
|
-
const dir =
|
|
13769
|
-
if (!
|
|
14415
|
+
const dir = join11(homedir5(), ".cclens", "runtime");
|
|
14416
|
+
if (!existsSync14(dir))
|
|
13770
14417
|
mkdirSync10(dir, { recursive: true });
|
|
13771
14418
|
return realpathSync2(dir);
|
|
13772
14419
|
}
|
|
13773
14420
|
function ensureRuntimeCwdTrusted(cwd) {
|
|
13774
|
-
const cfgPath =
|
|
14421
|
+
const cfgPath = join11(homedir5(), ".claude.json");
|
|
13775
14422
|
let cfg;
|
|
13776
14423
|
try {
|
|
13777
14424
|
cfg = JSON.parse(readFileSync17(cfgPath, "utf8"));
|
|
@@ -13817,9 +14464,9 @@ async function runClaudeUnderTmuxImpl(args) {
|
|
|
13817
14464
|
ensureRuntimeCwdTrusted(cwd);
|
|
13818
14465
|
const runId = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
13819
14466
|
const sessionName = `cclens-${runId}`;
|
|
13820
|
-
const systemFile =
|
|
13821
|
-
const userFile =
|
|
13822
|
-
const wrapper =
|
|
14467
|
+
const systemFile = join11(cwd, `system-${runId}.txt`);
|
|
14468
|
+
const userFile = join11(cwd, `user-${runId}.txt`);
|
|
14469
|
+
const wrapper = join11(cwd, `run-${runId}.sh`);
|
|
13823
14470
|
writeFileSync11(systemFile, args.systemPrompt);
|
|
13824
14471
|
writeFileSync11(userFile, args.reminder ? `${args.userPrompt}
|
|
13825
14472
|
|
|
@@ -13838,10 +14485,10 @@ exec ${shellEscape(claudeBin)} \\
|
|
|
13838
14485
|
"$USR"
|
|
13839
14486
|
`, { mode: 493 });
|
|
13840
14487
|
const existingBefore = snapshotAllTranscripts();
|
|
13841
|
-
const
|
|
13842
|
-
if (
|
|
14488
|
+
const spawn4 = spawnSync(tmuxBin, ["new-session", "-d", "-s", sessionName, "-x", "140", "-y", "50", "-c", cwd, wrapper], { encoding: "utf8" });
|
|
14489
|
+
if (spawn4.status !== 0) {
|
|
13843
14490
|
cleanup(cwd, runId, tmuxBin, sessionName);
|
|
13844
|
-
throw new TmuxRunError(`tmux new-session failed: ${
|
|
14491
|
+
throw new TmuxRunError(`tmux new-session failed: ${spawn4.stderr.trim()}`);
|
|
13845
14492
|
}
|
|
13846
14493
|
const onAbort = () => {
|
|
13847
14494
|
try {
|
|
@@ -13898,7 +14545,7 @@ function num(v) {
|
|
|
13898
14545
|
function sleep(ms) {
|
|
13899
14546
|
return new Promise((r) => setTimeout(r, ms));
|
|
13900
14547
|
}
|
|
13901
|
-
var PROJECTS_ROOT = () =>
|
|
14548
|
+
var PROJECTS_ROOT = () => join11(homedir5(), ".claude", "projects");
|
|
13902
14549
|
function snapshotAllTranscripts() {
|
|
13903
14550
|
const out = /* @__PURE__ */ new Set();
|
|
13904
14551
|
const root = PROJECTS_ROOT();
|
|
@@ -13909,7 +14556,7 @@ function snapshotAllTranscripts() {
|
|
|
13909
14556
|
return out;
|
|
13910
14557
|
}
|
|
13911
14558
|
for (const sub of subs) {
|
|
13912
|
-
const dir =
|
|
14559
|
+
const dir = join11(root, sub);
|
|
13913
14560
|
let files;
|
|
13914
14561
|
try {
|
|
13915
14562
|
files = readdirSync5(dir);
|
|
@@ -13918,15 +14565,15 @@ function snapshotAllTranscripts() {
|
|
|
13918
14565
|
}
|
|
13919
14566
|
for (const f of files) {
|
|
13920
14567
|
if (f.endsWith(".jsonl"))
|
|
13921
|
-
out.add(
|
|
14568
|
+
out.add(join11(dir, f));
|
|
13922
14569
|
}
|
|
13923
14570
|
}
|
|
13924
14571
|
return out;
|
|
13925
14572
|
}
|
|
13926
|
-
function readJsonlCwd(
|
|
14573
|
+
function readJsonlCwd(path11, maxLines = 8) {
|
|
13927
14574
|
let raw;
|
|
13928
14575
|
try {
|
|
13929
|
-
raw = readFileSync17(
|
|
14576
|
+
raw = readFileSync17(path11, "utf8");
|
|
13930
14577
|
} catch {
|
|
13931
14578
|
return void 0;
|
|
13932
14579
|
}
|
|
@@ -13959,7 +14606,7 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
|
|
|
13959
14606
|
subs = [];
|
|
13960
14607
|
}
|
|
13961
14608
|
for (const sub of subs) {
|
|
13962
|
-
const dir =
|
|
14609
|
+
const dir = join11(root, sub);
|
|
13963
14610
|
let files;
|
|
13964
14611
|
try {
|
|
13965
14612
|
files = readdirSync5(dir);
|
|
@@ -13969,7 +14616,7 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
|
|
|
13969
14616
|
for (const f of files) {
|
|
13970
14617
|
if (!f.endsWith(".jsonl"))
|
|
13971
14618
|
continue;
|
|
13972
|
-
const full =
|
|
14619
|
+
const full = join11(dir, f);
|
|
13973
14620
|
if (existingBefore.has(full))
|
|
13974
14621
|
continue;
|
|
13975
14622
|
if (readJsonlCwd(full) === targetCwd)
|
|
@@ -13980,10 +14627,10 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
|
|
|
13980
14627
|
}
|
|
13981
14628
|
throw new TmuxRunError(`timeout waiting for claude to create the session transcript (cwd: ${targetCwd})`);
|
|
13982
14629
|
}
|
|
13983
|
-
function parseTranscript2(
|
|
14630
|
+
function parseTranscript2(path11, defaultModel) {
|
|
13984
14631
|
let raw;
|
|
13985
14632
|
try {
|
|
13986
|
-
raw = readFileSync17(
|
|
14633
|
+
raw = readFileSync17(path11, "utf8");
|
|
13987
14634
|
} catch {
|
|
13988
14635
|
return { assembled: "", inputTokens: 0, outputTokens: 0, modelUsed: defaultModel, done: false };
|
|
13989
14636
|
}
|
|
@@ -14043,7 +14690,7 @@ function cleanup(cwd, runId, tmuxBin, sessionName, transcriptPath) {
|
|
|
14043
14690
|
}
|
|
14044
14691
|
for (const f of [`system-${runId}.txt`, `user-${runId}.txt`, `run-${runId}.sh`]) {
|
|
14045
14692
|
try {
|
|
14046
|
-
unlinkSync3(
|
|
14693
|
+
unlinkSync3(join11(cwd, f));
|
|
14047
14694
|
} catch {
|
|
14048
14695
|
}
|
|
14049
14696
|
}
|
|
@@ -14058,7 +14705,7 @@ function shellEscape(s) {
|
|
|
14058
14705
|
// ../entries/dist/llm-runner.js
|
|
14059
14706
|
var RUNS_DIR = cclensPath("llm-runs");
|
|
14060
14707
|
function ensureRunsDir() {
|
|
14061
|
-
if (!
|
|
14708
|
+
if (!existsSync15(RUNS_DIR)) {
|
|
14062
14709
|
try {
|
|
14063
14710
|
mkdirSync11(RUNS_DIR, { recursive: true });
|
|
14064
14711
|
} catch {
|
|
@@ -14087,17 +14734,17 @@ function newRunId(kind) {
|
|
|
14087
14734
|
return `${ts}_${kind}_${short}`;
|
|
14088
14735
|
}
|
|
14089
14736
|
function tracePath(runId) {
|
|
14090
|
-
return
|
|
14737
|
+
return join12(RUNS_DIR, `${runId}.jsonl`);
|
|
14091
14738
|
}
|
|
14092
|
-
function safeAppend(
|
|
14739
|
+
function safeAppend(path11, line) {
|
|
14093
14740
|
try {
|
|
14094
|
-
appendFileSync5(
|
|
14741
|
+
appendFileSync5(path11, line);
|
|
14095
14742
|
} catch {
|
|
14096
14743
|
}
|
|
14097
14744
|
}
|
|
14098
|
-
function safeWrite(
|
|
14745
|
+
function safeWrite(path11, line) {
|
|
14099
14746
|
try {
|
|
14100
|
-
writeFileSync12(
|
|
14747
|
+
writeFileSync12(path11, line);
|
|
14101
14748
|
} catch {
|
|
14102
14749
|
}
|
|
14103
14750
|
}
|
|
@@ -14230,7 +14877,7 @@ function runClaudePrintMode(args) {
|
|
|
14230
14877
|
"--append-system-prompt",
|
|
14231
14878
|
args.systemPrompt
|
|
14232
14879
|
];
|
|
14233
|
-
const proc =
|
|
14880
|
+
const proc = spawn2("claude", claudeArgs, { stdio: ["pipe", "pipe", "pipe"], env: { ...process.env } });
|
|
14234
14881
|
safeAppend(trace, JSON.stringify({ _meta: { type: "spawned", run_id: runId, pid: proc.pid } }) + "\n");
|
|
14235
14882
|
const stdinPayload = args.reminder ? `${args.userPrompt}
|
|
14236
14883
|
|
|
@@ -14486,8 +15133,8 @@ function applyEnrichmentError(entry, errorMessage, model, costUsd, generatedAt,
|
|
|
14486
15133
|
|
|
14487
15134
|
// ../entries/dist/budget.js
|
|
14488
15135
|
init_fs();
|
|
14489
|
-
import { appendFileSync as appendFileSync6, readFileSync as readFileSync18, existsSync as
|
|
14490
|
-
import { dirname as
|
|
15136
|
+
import { appendFileSync as appendFileSync6, readFileSync as readFileSync18, existsSync as existsSync16, mkdirSync as mkdirSync12 } from "node:fs";
|
|
15137
|
+
import { dirname as dirname11 } from "node:path";
|
|
14491
15138
|
var spendPathCached = null;
|
|
14492
15139
|
function spendPath() {
|
|
14493
15140
|
if (spendPathCached)
|
|
@@ -14497,12 +15144,12 @@ function spendPath() {
|
|
|
14497
15144
|
}
|
|
14498
15145
|
function appendSpend(record) {
|
|
14499
15146
|
const p = spendPath();
|
|
14500
|
-
mkdirSync12(
|
|
15147
|
+
mkdirSync12(dirname11(p), { recursive: true });
|
|
14501
15148
|
appendFileSync6(p, JSON.stringify(record) + "\n", { encoding: "utf8" });
|
|
14502
15149
|
}
|
|
14503
15150
|
function monthToDateSpend(now = /* @__PURE__ */ new Date()) {
|
|
14504
15151
|
const p = spendPath();
|
|
14505
|
-
if (!
|
|
15152
|
+
if (!existsSync16(p))
|
|
14506
15153
|
return 0;
|
|
14507
15154
|
const year = now.getUTCFullYear();
|
|
14508
15155
|
const month = now.getUTCMonth();
|
|
@@ -14529,7 +15176,7 @@ function monthToDateSpend(now = /* @__PURE__ */ new Date()) {
|
|
|
14529
15176
|
|
|
14530
15177
|
// ../entries/dist/pipeline-lock.js
|
|
14531
15178
|
init_fs();
|
|
14532
|
-
import { writeFileSync as writeFileSync13, unlinkSync as unlinkSync4, existsSync as
|
|
15179
|
+
import { writeFileSync as writeFileSync13, unlinkSync as unlinkSync4, existsSync as existsSync17, readFileSync as readFileSync19, statSync as statSync7 } from "node:fs";
|
|
14533
15180
|
var STALE_MS2 = 60 * 1e3;
|
|
14534
15181
|
var HEARTBEAT_MS = 30 * 1e3;
|
|
14535
15182
|
var lockPathCached = null;
|
|
@@ -14575,7 +15222,7 @@ function pidAlive(pid) {
|
|
|
14575
15222
|
}
|
|
14576
15223
|
function interactiveLockFresh(nowMs) {
|
|
14577
15224
|
const p = lockPath();
|
|
14578
|
-
if (!
|
|
15225
|
+
if (!existsSync17(p))
|
|
14579
15226
|
return false;
|
|
14580
15227
|
try {
|
|
14581
15228
|
const mtime = statSync7(p).mtimeMs;
|
|
@@ -14596,7 +15243,7 @@ function interactiveLockFresh(nowMs) {
|
|
|
14596
15243
|
var THIRTY_MIN_MS = 30 * 60 * 1e3;
|
|
14597
15244
|
|
|
14598
15245
|
// ../entries/dist/settings.js
|
|
14599
|
-
import { readFileSync as readFileSync20, writeFileSync as writeFileSync14, renameSync as renameSync6, chmodSync as chmodSync2, mkdirSync as mkdirSync13, existsSync as
|
|
15246
|
+
import { readFileSync as readFileSync20, writeFileSync as writeFileSync14, renameSync as renameSync6, chmodSync as chmodSync2, mkdirSync as mkdirSync13, existsSync as existsSync18 } from "node:fs";
|
|
14600
15247
|
init_fs();
|
|
14601
15248
|
var DEFAULT_SETTINGS = {
|
|
14602
15249
|
ai_features: {
|
|
@@ -14628,7 +15275,7 @@ function fromDisk(d) {
|
|
|
14628
15275
|
}
|
|
14629
15276
|
function readSettings() {
|
|
14630
15277
|
const p = settingsPath();
|
|
14631
|
-
if (!
|
|
15278
|
+
if (!existsSync18(p))
|
|
14632
15279
|
return DEFAULT_SETTINGS;
|
|
14633
15280
|
try {
|
|
14634
15281
|
const raw = readFileSync20(p, "utf8");
|
|
@@ -16302,7 +16949,7 @@ var MonthDigestResponseSchema = external_exports.object({
|
|
|
16302
16949
|
}).passthrough();
|
|
16303
16950
|
|
|
16304
16951
|
// ../entries/dist/top-sessions.js
|
|
16305
|
-
var
|
|
16952
|
+
var IDLE_GAP_MS7 = 3 * 60 * 1e3;
|
|
16306
16953
|
var LONG_AUTONOMOUS_MIN = 20;
|
|
16307
16954
|
var N_USER = 150;
|
|
16308
16955
|
var N_FIRST_AGENT = 150;
|
|
@@ -16333,7 +16980,7 @@ function activeMs(timestamps) {
|
|
|
16333
16980
|
let active = 0;
|
|
16334
16981
|
for (let i = 1; i < ts.length; i++) {
|
|
16335
16982
|
const dt = ts[i] - ts[i - 1];
|
|
16336
|
-
if (dt <
|
|
16983
|
+
if (dt < IDLE_GAP_MS7)
|
|
16337
16984
|
active += dt;
|
|
16338
16985
|
}
|
|
16339
16986
|
return active;
|
|
@@ -16507,7 +17154,7 @@ function buildSessionSlice(entry, events, daySignature) {
|
|
|
16507
17154
|
let intEnd = sortedTs[0];
|
|
16508
17155
|
for (let i = 1; i < sortedTs.length; i++) {
|
|
16509
17156
|
const dt = sortedTs[i] - intEnd;
|
|
16510
|
-
if (dt >=
|
|
17157
|
+
if (dt >= IDLE_GAP_MS7) {
|
|
16511
17158
|
intervals.push({
|
|
16512
17159
|
start_min: fmtMin(intStart - sliceStartMs),
|
|
16513
17160
|
end_min: fmtMin(intEnd - sliceStartMs)
|
|
@@ -17391,14 +18038,14 @@ async function getUpdateAvailability() {
|
|
|
17391
18038
|
if (isDevMode()) return null;
|
|
17392
18039
|
const latest = await fetchLatestVersion();
|
|
17393
18040
|
if (latest === null) return {
|
|
17394
|
-
current: "0.16.
|
|
18041
|
+
current: "0.16.8",
|
|
17395
18042
|
latest: null,
|
|
17396
18043
|
updateAvailable: false
|
|
17397
18044
|
};
|
|
17398
18045
|
return {
|
|
17399
|
-
current: "0.16.
|
|
18046
|
+
current: "0.16.8",
|
|
17400
18047
|
latest,
|
|
17401
|
-
updateAvailable: shouldUpdate("0.16.
|
|
18048
|
+
updateAvailable: shouldUpdate("0.16.8", latest)
|
|
17402
18049
|
};
|
|
17403
18050
|
}
|
|
17404
18051
|
|
|
@@ -17408,11 +18055,12 @@ var DAEMON_LOG = cclensPath("daemon.log");
|
|
|
17408
18055
|
var UPDATE_STATE = cclensPath("daemon-update.json");
|
|
17409
18056
|
var WATCHDOG_INTERVAL_MS = 5 * 1e3;
|
|
17410
18057
|
var AUTO_UPDATE_INTERVAL_MS = 6 * 60 * 60 * 1e3;
|
|
17411
|
-
mkdirSync14(
|
|
18058
|
+
mkdirSync14(dirname12(USAGE_LOG3), { recursive: true });
|
|
17412
18059
|
function log2(level, message) {
|
|
17413
18060
|
appendDaemonLogLine(level, message);
|
|
17414
18061
|
}
|
|
17415
18062
|
var nextPollAtMs = 0;
|
|
18063
|
+
var nextAuxPollAtMs = 0;
|
|
17416
18064
|
var nextTeamSyncAtMs = 0;
|
|
17417
18065
|
var firstTeamSync = true;
|
|
17418
18066
|
var currentIntervalMs = BASE_INTERVAL_MS;
|
|
@@ -17466,7 +18114,7 @@ function nextUpdateCheckFromState(nowMs) {
|
|
|
17466
18114
|
}
|
|
17467
18115
|
var nextUpdateCheckAtMs = nextUpdateCheckFromState(Date.now());
|
|
17468
18116
|
function cliEntryPath() {
|
|
17469
|
-
return
|
|
18117
|
+
return join13(dirname12(fileURLToPath(import.meta.url)), "index.js");
|
|
17470
18118
|
}
|
|
17471
18119
|
async function runDaemonUpdateCheck() {
|
|
17472
18120
|
if (process.env.FLEETLENS_DAEMON_AUTO_UPDATE === "0") {
|
|
@@ -17498,7 +18146,7 @@ async function runDaemonUpdateCheck() {
|
|
|
17498
18146
|
return;
|
|
17499
18147
|
}
|
|
17500
18148
|
const entry = cliEntryPath();
|
|
17501
|
-
if (!
|
|
18149
|
+
if (!existsSync19(entry)) {
|
|
17502
18150
|
log2("warn", `update check found ${availability.latest}, but CLI entry is missing at ${entry}`);
|
|
17503
18151
|
return;
|
|
17504
18152
|
}
|
|
@@ -17507,7 +18155,7 @@ async function runDaemonUpdateCheck() {
|
|
|
17507
18155
|
logFd = openSync(DAEMON_LOG, "a");
|
|
17508
18156
|
} catch {
|
|
17509
18157
|
}
|
|
17510
|
-
const child =
|
|
18158
|
+
const child = spawn3(process.execPath, [entry, "update"], {
|
|
17511
18159
|
detached: true,
|
|
17512
18160
|
stdio: ["ignore", logFd, logFd],
|
|
17513
18161
|
env: { ...process.env, FLEETLENS_UPDATE_SOURCE: "daemon" }
|
|
@@ -17537,7 +18185,7 @@ async function runDaemonUpdateCheck() {
|
|
|
17537
18185
|
nextUpdateCheckAtMs = Date.now() + AUTO_UPDATE_INTERVAL_MS;
|
|
17538
18186
|
}
|
|
17539
18187
|
}
|
|
17540
|
-
async function
|
|
18188
|
+
async function pollAuxiliaryUsage() {
|
|
17541
18189
|
for (const source of agentSources) {
|
|
17542
18190
|
if (source.kind === "claude-code") continue;
|
|
17543
18191
|
if (!source.usagePoller) continue;
|
|
@@ -17577,6 +18225,18 @@ async function tick() {
|
|
|
17577
18225
|
log2("warn", `zai poll failed: ${err.message}`);
|
|
17578
18226
|
}
|
|
17579
18227
|
}
|
|
18228
|
+
try {
|
|
18229
|
+
const copilotSnapshot = await fetchCopilotUsage();
|
|
18230
|
+
appendSnapshot(USAGE_LOG3, copilotSnapshot);
|
|
18231
|
+
const monthly = copilotSnapshot.monthly?.utilization;
|
|
18232
|
+
log2("info", `copilot snapshot monthly=${monthly === null || monthly === void 0 ? "\u2014" : `${monthly}%`}`);
|
|
18233
|
+
} catch (err) {
|
|
18234
|
+
if (err instanceof CopilotApiError && err.code === "no_cli") {
|
|
18235
|
+
pruneAgent(USAGE_LOG3, "copilot");
|
|
18236
|
+
} else if (!(err instanceof CopilotApiError && err.code === "no_auth")) {
|
|
18237
|
+
log2("warn", `copilot poll failed: ${err.message}`);
|
|
18238
|
+
}
|
|
18239
|
+
}
|
|
17580
18240
|
try {
|
|
17581
18241
|
const codexSnapshot = await fetchCodexUsage();
|
|
17582
18242
|
appendSnapshot(USAGE_LOG3, codexSnapshot);
|
|
@@ -17608,6 +18268,8 @@ async function tick() {
|
|
|
17608
18268
|
log2("warn", `grok poll failed: ${err.message}`);
|
|
17609
18269
|
}
|
|
17610
18270
|
}
|
|
18271
|
+
}
|
|
18272
|
+
async function pollClaudeUsage() {
|
|
17611
18273
|
try {
|
|
17612
18274
|
const snapshot = await fetchUsage();
|
|
17613
18275
|
appendSnapshot(USAGE_LOG3, snapshot);
|
|
@@ -17642,6 +18304,10 @@ function sleep2(ms) {
|
|
|
17642
18304
|
async function runLoop() {
|
|
17643
18305
|
while (true) {
|
|
17644
18306
|
const now = Date.now();
|
|
18307
|
+
if (now >= nextAuxPollAtMs) {
|
|
18308
|
+
await pollAuxiliaryUsage();
|
|
18309
|
+
nextAuxPollAtMs = Date.now() + BASE_INTERVAL_MS;
|
|
18310
|
+
}
|
|
17645
18311
|
if (now >= nextPollAtMs) {
|
|
17646
18312
|
if (nextPollAtMs > 0 && now - nextPollAtMs > currentIntervalMs) {
|
|
17647
18313
|
log2(
|
|
@@ -17664,7 +18330,7 @@ async function runLoop() {
|
|
|
17664
18330
|
log2("info", "token refreshed; resuming polls");
|
|
17665
18331
|
waitingForRefresh = false;
|
|
17666
18332
|
}
|
|
17667
|
-
const outcome = await
|
|
18333
|
+
const outcome = await pollClaudeUsage();
|
|
17668
18334
|
scheduleAfter(Date.now(), outcome);
|
|
17669
18335
|
}
|
|
17670
18336
|
}
|