fleetlens 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/apps/web/.next/BUILD_ID +1 -1
- package/app/apps/web/.next/app-path-routes-manifest.json +1 -0
- package/app/apps/web/.next/build-manifest.json +5 -5
- package/app/apps/web/.next/prerender-manifest.json +3 -3
- package/app/apps/web/.next/routes-manifest.json +6 -0
- package/app/apps/web/.next/server/app/_global-error/page/build-manifest.json +2 -2
- package/app/apps/web/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- 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/build-manifest.json +2 -2
- package/app/apps/web/.next/server/app/_not-found/page.js +1 -1
- package/app/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/api/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/jobs/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/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/changelog/page/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/changelog/page/build-manifest.json +17 -0
- package/app/apps/web/.next/server/app/changelog/page/next-font-manifest.json +6 -0
- package/app/apps/web/.next/server/app/changelog/page/react-loadable-manifest.json +1 -0
- package/app/apps/web/.next/server/app/changelog/page/server-reference-manifest.json +4 -0
- package/app/apps/web/.next/server/app/changelog/page.js +17 -0
- package/app/apps/web/.next/server/app/changelog/page.js.map +5 -0
- package/app/apps/web/.next/server/app/changelog/page.js.nft.json +1 -0
- package/app/apps/web/.next/server/app/changelog/page_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/day/[date]/page/build-manifest.json +2 -2
- package/app/apps/web/.next/server/app/day/[date]/page.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/build-manifest.json +2 -2
- package/app/apps/web/.next/server/app/day/page.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/build-manifest.json +2 -2
- package/app/apps/web/.next/server/app/digest/[date]/page.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/build-manifest.json +2 -2
- package/app/apps/web/.next/server/app/digest/page.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/build-manifest.json +2 -2
- package/app/apps/web/.next/server/app/insights/[key]/page.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/build-manifest.json +2 -2
- package/app/apps/web/.next/server/app/insights/page.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/build-manifest.json +2 -2
- package/app/apps/web/.next/server/app/page.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/build-manifest.json +2 -2
- package/app/apps/web/.next/server/app/parallelism/page.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/projects/[slug]/page/build-manifest.json +2 -2
- package/app/apps/web/.next/server/app/projects/[slug]/page.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/build-manifest.json +2 -2
- package/app/apps/web/.next/server/app/projects/page.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/build-manifest.json +2 -2
- package/app/apps/web/.next/server/app/runs/page.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/build-manifest.json +2 -2
- package/app/apps/web/.next/server/app/sessions/[id]/page.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/build-manifest.json +2 -2
- package/app/apps/web/.next/server/app/sessions/page.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/build-manifest.json +2 -2
- package/app/apps/web/.next/server/app/settings/page.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/usage/page/build-manifest.json +2 -2
- package/app/apps/web/.next/server/app/usage/page.js +1 -1
- package/app/apps/web/.next/server/app/usage/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/usage/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app-paths-manifest.json +1 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0.z48ue._.js +1 -1
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0dctov1._.js +2 -2
- package/app/apps/web/.next/server/chunks/packages_09hmrqx._.js +1 -1
- package/app/apps/web/.next/server/chunks/packages_118y1lp._.js +1 -1
- package/app/apps/web/.next/server/chunks/packages_parser_dist_fs_122oe0-.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0vvlth5._.js → [root-of-the-server]__02~v50d._.js} +2 -2
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__09rjz7_._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0r4tks8._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0ytdqxt._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/_0xu2pvc._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_changelog_page_actions_12_04gy.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0txtsv5._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_changelog-mark-read_tsx_0hm41sv._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_0m67-xi._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0uwo3v3.js +4 -0
- package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_10_oegc._.js +1 -1
- package/app/apps/web/.next/server/middleware-build-manifest.js +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/05b689hq3x49w.js +1 -0
- package/app/apps/web/.next/static/chunks/0cxyt4-24..b7.js +14 -0
- package/app/apps/web/.next/static/chunks/{0mykrrv810ra-.js → 0kjot8367asxe.js} +1 -1
- package/app/apps/web/.next/static/chunks/{turbopack-0_p36yduv.waj.js → turbopack-00w.w1u3c~d-6.js} +1 -1
- package/app/apps/web/app/changelog/page.tsx +238 -0
- package/app/apps/web/app/layout.tsx +2 -0
- package/app/apps/web/components/changelog-icon.tsx +62 -0
- package/app/apps/web/components/changelog-mark-read.tsx +12 -0
- package/app/apps/web/components/sidebar.tsx +7 -0
- package/app/apps/web/lib/calibration-data.ts +4 -64
- package/app/apps/web/lib/changelog-data.generated.ts +3 -0
- package/app/apps/web/lib/changelog.ts +67 -0
- package/app/apps/web/lib/cycle-peaks.test.ts +185 -0
- package/app/apps/web/lib/cycle-peaks.ts +104 -0
- package/app/apps/web/package.json +1 -1
- package/app/apps/web/tsconfig.tsbuildinfo +1 -1
- package/dist/daemon-worker.js +574 -38
- package/dist/index.js +601 -65
- package/package.json +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0v.6dx0._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_usage-data_ts_0xtv99n._.js +0 -3
- package/app/apps/web/.next/static/chunks/09gdxttgu~.aj.js +0 -14
- /package/app/apps/web/.next/static/{qYW0u_NOmV0v7lf7xZc6x → u6-8f8u1tspYCacGAz53R}/_buildManifest.js +0 -0
- /package/app/apps/web/.next/static/{qYW0u_NOmV0v7lf7xZc6x → u6-8f8u1tspYCacGAz53R}/_clientMiddlewareManifest.js +0 -0
- /package/app/apps/web/.next/static/{qYW0u_NOmV0v7lf7xZc6x → u6-8f8u1tspYCacGAz53R}/_ssgManifest.js +0 -0
package/dist/index.js
CHANGED
|
@@ -454,9 +454,9 @@ Installed: ${PACKAGE_NAME}@${verify.installedVersion} at ${verify.installedPath
|
|
|
454
454
|
console.warn(
|
|
455
455
|
` \u2022 reinstall in the correct Node env: 'npm install -g ${PACKAGE_NAME}@latest'`
|
|
456
456
|
);
|
|
457
|
-
} else if (verify.installedVersion !== "0.
|
|
457
|
+
} else if (verify.installedVersion !== "0.9.0") {
|
|
458
458
|
console.log(
|
|
459
|
-
` \u2192 This process is still running ${"0.
|
|
459
|
+
` \u2192 This process is still running ${"0.9.0"}. Next invocation will use ${verify.installedVersion}.`
|
|
460
460
|
);
|
|
461
461
|
}
|
|
462
462
|
}
|
|
@@ -492,7 +492,7 @@ async function checkForUpdate() {
|
|
|
492
492
|
if (process.env.__FLEETLENS_UPDATED === "1" || process.env.__CCLENS_UPDATED === "1") return;
|
|
493
493
|
const latest = await fetchLatestVersion();
|
|
494
494
|
if (latest === null) return;
|
|
495
|
-
const current = "0.
|
|
495
|
+
const current = "0.9.0";
|
|
496
496
|
if (!shouldUpdate(current, latest)) return;
|
|
497
497
|
console.log(`Updating ${PACKAGE_NAME} ${current} \u2192 ${latest}...`);
|
|
498
498
|
await stopRunningServices();
|
|
@@ -574,7 +574,7 @@ async function restartServices(state) {
|
|
|
574
574
|
}
|
|
575
575
|
async function forceUpdate() {
|
|
576
576
|
const latest = await fetchLatestVersion();
|
|
577
|
-
const current = "0.
|
|
577
|
+
const current = "0.9.0";
|
|
578
578
|
if (latest === null) {
|
|
579
579
|
console.error("Could not reach npm registry. Check your network.");
|
|
580
580
|
process.exit(1);
|
|
@@ -747,10 +747,10 @@ async function web(args2) {
|
|
|
747
747
|
const noOpen = args2.includes("--no-open");
|
|
748
748
|
const positional = args2.filter((a) => !a.startsWith("--"));
|
|
749
749
|
const rawPath = positional[0] ?? "";
|
|
750
|
-
const
|
|
750
|
+
const path5 = rawPath.startsWith("/") ? rawPath : rawPath ? `/${rawPath}` : "";
|
|
751
751
|
const status2 = getServerStatus();
|
|
752
752
|
if (status2.running) {
|
|
753
|
-
const url = `http://localhost:${status2.port}${
|
|
753
|
+
const url = `http://localhost:${status2.port}${path5}`;
|
|
754
754
|
console.log(noOpen ? `Server running at ${url}` : `Opening ${url}`);
|
|
755
755
|
if (!noOpen) openBrowser(url);
|
|
756
756
|
return;
|
|
@@ -758,7 +758,7 @@ async function web(args2) {
|
|
|
758
758
|
console.log("fleetlens is not running. Starting server...");
|
|
759
759
|
try {
|
|
760
760
|
const result = await startServer({});
|
|
761
|
-
const url = `http://localhost:${result.port}${
|
|
761
|
+
const url = `http://localhost:${result.port}${path5}`;
|
|
762
762
|
console.log(`fleetlens running on ${url} (PID ${result.pid})`);
|
|
763
763
|
if (!noOpen) openBrowser(url);
|
|
764
764
|
} catch (err) {
|
|
@@ -816,9 +816,9 @@ function readFromCredentialsFile() {
|
|
|
816
816
|
join4(homedir3(), ".claude", ".credentials.json"),
|
|
817
817
|
join4(homedir3(), ".config", "claude", "credentials.json")
|
|
818
818
|
];
|
|
819
|
-
for (const
|
|
819
|
+
for (const path5 of candidates) {
|
|
820
820
|
try {
|
|
821
|
-
const blob = readFileSync5(
|
|
821
|
+
const blob = readFileSync5(path5, "utf8");
|
|
822
822
|
const creds = extractCredentials(blob);
|
|
823
823
|
if (creds) return creds;
|
|
824
824
|
} catch {
|
|
@@ -1556,7 +1556,7 @@ function getAgentMetadata(kind) {
|
|
|
1556
1556
|
function isAgentKind(s) {
|
|
1557
1557
|
return typeof s === "string" && KNOWN_AGENT_KINDS.has(s);
|
|
1558
1558
|
}
|
|
1559
|
-
var CLAUDE_CODE_METADATA, CODEX_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
|
|
1559
|
+
var CLAUDE_CODE_METADATA, CODEX_METADATA, GEMINI_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
|
|
1560
1560
|
var init_agent_metadata = __esm({
|
|
1561
1561
|
"../parser/dist/agent-metadata.js"() {
|
|
1562
1562
|
"use strict";
|
|
@@ -1574,9 +1574,17 @@ var init_agent_metadata = __esm({
|
|
|
1574
1574
|
accentColor: "rgb(16, 163, 127)",
|
|
1575
1575
|
iconChar: "\u25C6"
|
|
1576
1576
|
};
|
|
1577
|
+
GEMINI_METADATA = {
|
|
1578
|
+
kind: "gemini",
|
|
1579
|
+
displayName: "Gemini CLI",
|
|
1580
|
+
shortLabel: "Gemini",
|
|
1581
|
+
accentColor: "rgb(124, 92, 246)",
|
|
1582
|
+
iconChar: "\u273A"
|
|
1583
|
+
};
|
|
1577
1584
|
agentMetadata = [
|
|
1578
1585
|
CLAUDE_CODE_METADATA,
|
|
1579
|
-
CODEX_METADATA
|
|
1586
|
+
CODEX_METADATA,
|
|
1587
|
+
GEMINI_METADATA
|
|
1580
1588
|
];
|
|
1581
1589
|
KNOWN_AGENT_KINDS = new Set(agentMetadata.map((m) => m.kind));
|
|
1582
1590
|
}
|
|
@@ -3360,10 +3368,510 @@ var init_codex = __esm({
|
|
|
3360
3368
|
}
|
|
3361
3369
|
});
|
|
3362
3370
|
|
|
3371
|
+
// ../parser/dist/gemini.js
|
|
3372
|
+
import { promises as fs3 } from "node:fs";
|
|
3373
|
+
import os3 from "node:os";
|
|
3374
|
+
import path3 from "node:path";
|
|
3375
|
+
async function safeReaddir2(p) {
|
|
3376
|
+
return fs3.readdir(p).catch(() => []);
|
|
3377
|
+
}
|
|
3378
|
+
async function listSessionFiles(root) {
|
|
3379
|
+
const out = [];
|
|
3380
|
+
const slugs = await safeReaddir2(root);
|
|
3381
|
+
for (const slug of slugs) {
|
|
3382
|
+
const chatsDir = path3.join(root, slug, "chats");
|
|
3383
|
+
const entries2 = await safeReaddir2(chatsDir);
|
|
3384
|
+
for (const entry of entries2) {
|
|
3385
|
+
if (!SESSION_FILE_RE.test(entry))
|
|
3386
|
+
continue;
|
|
3387
|
+
const full = path3.join(chatsDir, entry);
|
|
3388
|
+
const stat = await fs3.stat(full).catch(() => null);
|
|
3389
|
+
if (!stat || !stat.isFile())
|
|
3390
|
+
continue;
|
|
3391
|
+
const filenameId = entry.replace(/\.(jsonl|json)$/, "").split("-").pop() ?? entry;
|
|
3392
|
+
out.push({
|
|
3393
|
+
filePath: full,
|
|
3394
|
+
slug,
|
|
3395
|
+
filenameId,
|
|
3396
|
+
format: entry.endsWith(".jsonl") ? "jsonl" : "legacy-json",
|
|
3397
|
+
mtimeMs: stat.mtimeMs,
|
|
3398
|
+
sizeBytes: stat.size
|
|
3399
|
+
});
|
|
3400
|
+
}
|
|
3401
|
+
}
|
|
3402
|
+
return out;
|
|
3403
|
+
}
|
|
3404
|
+
async function loadSlugToCwd() {
|
|
3405
|
+
const stat = await fs3.stat(GEMINI_PROJECTS_FILE).catch(() => null);
|
|
3406
|
+
if (!stat)
|
|
3407
|
+
return /* @__PURE__ */ new Map();
|
|
3408
|
+
if (projectsCache && projectsCache.mtimeMs === stat.mtimeMs) {
|
|
3409
|
+
return projectsCache.slugToCwd;
|
|
3410
|
+
}
|
|
3411
|
+
const raw = await fs3.readFile(GEMINI_PROJECTS_FILE, "utf8").catch(() => "");
|
|
3412
|
+
let parsed;
|
|
3413
|
+
try {
|
|
3414
|
+
parsed = JSON.parse(raw);
|
|
3415
|
+
} catch {
|
|
3416
|
+
parsed = {};
|
|
3417
|
+
}
|
|
3418
|
+
const slugToCwd = /* @__PURE__ */ new Map();
|
|
3419
|
+
for (const [cwd, slug] of Object.entries(parsed.projects ?? {})) {
|
|
3420
|
+
if (typeof slug === "string")
|
|
3421
|
+
slugToCwd.set(slug, cwd);
|
|
3422
|
+
}
|
|
3423
|
+
projectsCache = { mtimeMs: stat.mtimeMs, slugToCwd };
|
|
3424
|
+
return slugToCwd;
|
|
3425
|
+
}
|
|
3426
|
+
function isRewindMarker(o) {
|
|
3427
|
+
return !!o && typeof o === "object" && "$rewindTo" in o;
|
|
3428
|
+
}
|
|
3429
|
+
function isSetMarker(o) {
|
|
3430
|
+
return !!o && typeof o === "object" && "$set" in o;
|
|
3431
|
+
}
|
|
3432
|
+
function isMessageRecord(o) {
|
|
3433
|
+
return !!o && typeof o === "object" && typeof o.id === "string" && typeof o.type === "string";
|
|
3434
|
+
}
|
|
3435
|
+
async function readAndReplay(file) {
|
|
3436
|
+
const raw = await fs3.readFile(file.filePath, "utf8");
|
|
3437
|
+
if (file.format === "legacy-json") {
|
|
3438
|
+
let blob;
|
|
3439
|
+
try {
|
|
3440
|
+
blob = JSON.parse(raw);
|
|
3441
|
+
} catch {
|
|
3442
|
+
return { meta: {}, messages: [] };
|
|
3443
|
+
}
|
|
3444
|
+
const meta2 = {
|
|
3445
|
+
sessionId: typeof blob.sessionId === "string" ? blob.sessionId : void 0,
|
|
3446
|
+
projectHash: typeof blob.projectHash === "string" ? blob.projectHash : void 0,
|
|
3447
|
+
startTime: typeof blob.startTime === "string" ? blob.startTime : void 0,
|
|
3448
|
+
lastUpdated: typeof blob.lastUpdated === "string" ? blob.lastUpdated : void 0,
|
|
3449
|
+
summary: typeof blob.summary === "string" ? blob.summary : void 0
|
|
3450
|
+
};
|
|
3451
|
+
const msgs = Array.isArray(blob.messages) ? blob.messages : [];
|
|
3452
|
+
const messages2 = msgs.filter(isMessageRecord);
|
|
3453
|
+
return { meta: meta2, messages: messages2 };
|
|
3454
|
+
}
|
|
3455
|
+
const meta = {};
|
|
3456
|
+
const byId = /* @__PURE__ */ new Map();
|
|
3457
|
+
const order = [];
|
|
3458
|
+
for (const line of raw.split("\n")) {
|
|
3459
|
+
const trimmed = line.trim();
|
|
3460
|
+
if (!trimmed)
|
|
3461
|
+
continue;
|
|
3462
|
+
let obj;
|
|
3463
|
+
try {
|
|
3464
|
+
obj = JSON.parse(trimmed);
|
|
3465
|
+
} catch {
|
|
3466
|
+
continue;
|
|
3467
|
+
}
|
|
3468
|
+
if (isRewindMarker(obj)) {
|
|
3469
|
+
const target = obj.$rewindTo;
|
|
3470
|
+
const idx = order.indexOf(target);
|
|
3471
|
+
if (idx >= 0) {
|
|
3472
|
+
for (const id of order.slice(idx))
|
|
3473
|
+
byId.delete(id);
|
|
3474
|
+
order.length = idx;
|
|
3475
|
+
}
|
|
3476
|
+
continue;
|
|
3477
|
+
}
|
|
3478
|
+
if (isSetMarker(obj)) {
|
|
3479
|
+
Object.assign(meta, obj.$set);
|
|
3480
|
+
continue;
|
|
3481
|
+
}
|
|
3482
|
+
if (isMessageRecord(obj)) {
|
|
3483
|
+
if (!byId.has(obj.id))
|
|
3484
|
+
order.push(obj.id);
|
|
3485
|
+
byId.set(obj.id, obj);
|
|
3486
|
+
continue;
|
|
3487
|
+
}
|
|
3488
|
+
if (typeof obj === "object" && obj !== null) {
|
|
3489
|
+
const m = obj;
|
|
3490
|
+
if (typeof m.sessionId === "string" && !meta.sessionId) {
|
|
3491
|
+
meta.sessionId = m.sessionId;
|
|
3492
|
+
if (typeof m.projectHash === "string")
|
|
3493
|
+
meta.projectHash = m.projectHash;
|
|
3494
|
+
if (typeof m.startTime === "string")
|
|
3495
|
+
meta.startTime = m.startTime;
|
|
3496
|
+
if (typeof m.lastUpdated === "string")
|
|
3497
|
+
meta.lastUpdated = m.lastUpdated;
|
|
3498
|
+
if (typeof m.summary === "string")
|
|
3499
|
+
meta.summary = m.summary;
|
|
3500
|
+
}
|
|
3501
|
+
}
|
|
3502
|
+
}
|
|
3503
|
+
const messages = [];
|
|
3504
|
+
for (const id of order) {
|
|
3505
|
+
const m = byId.get(id);
|
|
3506
|
+
if (m)
|
|
3507
|
+
messages.push(m);
|
|
3508
|
+
}
|
|
3509
|
+
return { meta, messages };
|
|
3510
|
+
}
|
|
3511
|
+
function emptyUsage2() {
|
|
3512
|
+
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
3513
|
+
}
|
|
3514
|
+
function previewOf2(text) {
|
|
3515
|
+
return text.replace(/\s+/g, " ").trim().slice(0, 200);
|
|
3516
|
+
}
|
|
3517
|
+
function flattenContent(c) {
|
|
3518
|
+
if (!c)
|
|
3519
|
+
return "";
|
|
3520
|
+
if (typeof c === "string")
|
|
3521
|
+
return c;
|
|
3522
|
+
const parts = Array.isArray(c) ? c : [c];
|
|
3523
|
+
const out = [];
|
|
3524
|
+
for (const p of parts) {
|
|
3525
|
+
if (!p || typeof p !== "object")
|
|
3526
|
+
continue;
|
|
3527
|
+
const part = p;
|
|
3528
|
+
if (typeof part.text === "string") {
|
|
3529
|
+
out.push(part.text);
|
|
3530
|
+
continue;
|
|
3531
|
+
}
|
|
3532
|
+
const fr = part.functionResponse;
|
|
3533
|
+
if (fr) {
|
|
3534
|
+
const resp = fr.response;
|
|
3535
|
+
if (typeof resp === "string") {
|
|
3536
|
+
out.push(resp);
|
|
3537
|
+
} else if (resp && typeof resp === "object") {
|
|
3538
|
+
const r = resp;
|
|
3539
|
+
if (typeof r.output === "string")
|
|
3540
|
+
out.push(r.output);
|
|
3541
|
+
else if (typeof r.error === "string")
|
|
3542
|
+
out.push(`error: ${r.error}`);
|
|
3543
|
+
else
|
|
3544
|
+
out.push(JSON.stringify(r));
|
|
3545
|
+
}
|
|
3546
|
+
}
|
|
3547
|
+
}
|
|
3548
|
+
return out.join("\n");
|
|
3549
|
+
}
|
|
3550
|
+
function truncate3(s, n) {
|
|
3551
|
+
return s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
|
|
3552
|
+
}
|
|
3553
|
+
async function parseSession(file) {
|
|
3554
|
+
const { meta: metaRec, messages } = await readAndReplay(file);
|
|
3555
|
+
const slugToCwd = await loadSlugToCwd();
|
|
3556
|
+
const cwd = slugToCwd.get(file.slug);
|
|
3557
|
+
const events = [];
|
|
3558
|
+
const totalUsage = emptyUsage2();
|
|
3559
|
+
let firstTimestamp;
|
|
3560
|
+
let lastTimestamp;
|
|
3561
|
+
let model;
|
|
3562
|
+
let toolCallCount = 0;
|
|
3563
|
+
let turnCount = 0;
|
|
3564
|
+
let firstUserPreview;
|
|
3565
|
+
let lastUserPreview;
|
|
3566
|
+
let lastAgentPreview;
|
|
3567
|
+
const tsMs = [];
|
|
3568
|
+
let idx = 0;
|
|
3569
|
+
function pushEvent(e) {
|
|
3570
|
+
events.push(e);
|
|
3571
|
+
if (e.timestamp && e.role !== "meta") {
|
|
3572
|
+
if (!firstTimestamp)
|
|
3573
|
+
firstTimestamp = e.timestamp;
|
|
3574
|
+
lastTimestamp = e.timestamp;
|
|
3575
|
+
const ms = Date.parse(e.timestamp);
|
|
3576
|
+
if (Number.isFinite(ms))
|
|
3577
|
+
tsMs.push(ms);
|
|
3578
|
+
}
|
|
3579
|
+
}
|
|
3580
|
+
for (const msg of messages) {
|
|
3581
|
+
const ts = msg.timestamp;
|
|
3582
|
+
if (msg.type === "user") {
|
|
3583
|
+
const text = flattenContent(msg.displayContent ?? msg.content);
|
|
3584
|
+
const preview = previewOf2(text);
|
|
3585
|
+
if (text) {
|
|
3586
|
+
if (!firstUserPreview)
|
|
3587
|
+
firstUserPreview = preview;
|
|
3588
|
+
lastUserPreview = preview;
|
|
3589
|
+
turnCount += 1;
|
|
3590
|
+
}
|
|
3591
|
+
pushEvent({
|
|
3592
|
+
index: idx++,
|
|
3593
|
+
timestamp: ts,
|
|
3594
|
+
role: "user",
|
|
3595
|
+
rawType: "gemini/user",
|
|
3596
|
+
preview,
|
|
3597
|
+
blocks: text ? [{ type: "text", text }] : [],
|
|
3598
|
+
messageId: msg.id,
|
|
3599
|
+
raw: msg
|
|
3600
|
+
});
|
|
3601
|
+
continue;
|
|
3602
|
+
}
|
|
3603
|
+
if (msg.type === "gemini") {
|
|
3604
|
+
if (typeof msg.model === "string")
|
|
3605
|
+
model = msg.model;
|
|
3606
|
+
const text = flattenContent(msg.content);
|
|
3607
|
+
const preview = previewOf2(text);
|
|
3608
|
+
if (text)
|
|
3609
|
+
lastAgentPreview = preview;
|
|
3610
|
+
let usage2;
|
|
3611
|
+
if (msg.tokens) {
|
|
3612
|
+
const t = msg.tokens;
|
|
3613
|
+
const u = {
|
|
3614
|
+
input: t.input ?? 0,
|
|
3615
|
+
output: t.output ?? 0,
|
|
3616
|
+
cacheRead: t.cached ?? 0,
|
|
3617
|
+
cacheWrite: 0
|
|
3618
|
+
};
|
|
3619
|
+
usage2 = u;
|
|
3620
|
+
totalUsage.input += u.input;
|
|
3621
|
+
totalUsage.output += u.output;
|
|
3622
|
+
totalUsage.cacheRead += u.cacheRead;
|
|
3623
|
+
}
|
|
3624
|
+
for (const th of msg.thoughts ?? []) {
|
|
3625
|
+
const thText = [th.subject, th.description].filter(Boolean).join(": ");
|
|
3626
|
+
if (!thText)
|
|
3627
|
+
continue;
|
|
3628
|
+
pushEvent({
|
|
3629
|
+
index: idx++,
|
|
3630
|
+
timestamp: th.timestamp ?? ts,
|
|
3631
|
+
role: "agent-thinking",
|
|
3632
|
+
rawType: "gemini/thought",
|
|
3633
|
+
preview: previewOf2(thText),
|
|
3634
|
+
blocks: [{ type: "thinking", thinking: thText }],
|
|
3635
|
+
model,
|
|
3636
|
+
raw: th
|
|
3637
|
+
});
|
|
3638
|
+
}
|
|
3639
|
+
if (text) {
|
|
3640
|
+
pushEvent({
|
|
3641
|
+
index: idx++,
|
|
3642
|
+
timestamp: ts,
|
|
3643
|
+
role: "agent",
|
|
3644
|
+
rawType: "gemini/agent",
|
|
3645
|
+
preview,
|
|
3646
|
+
blocks: [{ type: "text", text }],
|
|
3647
|
+
messageId: msg.id,
|
|
3648
|
+
model,
|
|
3649
|
+
usage: usage2,
|
|
3650
|
+
raw: msg
|
|
3651
|
+
});
|
|
3652
|
+
} else if (usage2) {
|
|
3653
|
+
pushEvent({
|
|
3654
|
+
index: idx++,
|
|
3655
|
+
timestamp: ts,
|
|
3656
|
+
role: "agent",
|
|
3657
|
+
rawType: "gemini/agent",
|
|
3658
|
+
preview: "",
|
|
3659
|
+
blocks: [],
|
|
3660
|
+
messageId: msg.id,
|
|
3661
|
+
model,
|
|
3662
|
+
usage: usage2,
|
|
3663
|
+
raw: msg
|
|
3664
|
+
});
|
|
3665
|
+
}
|
|
3666
|
+
for (const tc of msg.toolCalls ?? []) {
|
|
3667
|
+
toolCallCount += 1;
|
|
3668
|
+
const argsStr = tc.args ? JSON.stringify(tc.args) : "";
|
|
3669
|
+
pushEvent({
|
|
3670
|
+
index: idx++,
|
|
3671
|
+
timestamp: tc.timestamp ?? ts,
|
|
3672
|
+
role: "tool-call",
|
|
3673
|
+
rawType: "gemini/tool_call",
|
|
3674
|
+
preview: `${tc.name}(${truncate3(argsStr, 80)})`,
|
|
3675
|
+
blocks: [{ type: "tool_use", id: tc.id, name: tc.name, input: tc.args ?? {} }],
|
|
3676
|
+
toolName: tc.name,
|
|
3677
|
+
toolUseId: tc.id,
|
|
3678
|
+
model,
|
|
3679
|
+
raw: tc
|
|
3680
|
+
});
|
|
3681
|
+
const status2 = (tc.status ?? "").toLowerCase();
|
|
3682
|
+
const isTerminal = status2 === "success" || status2 === "error" || status2 === "cancelled";
|
|
3683
|
+
if (isTerminal) {
|
|
3684
|
+
const resultText = flattenContent(tc.result);
|
|
3685
|
+
pushEvent({
|
|
3686
|
+
index: idx++,
|
|
3687
|
+
timestamp: tc.timestamp ?? ts,
|
|
3688
|
+
role: "tool-result",
|
|
3689
|
+
rawType: "gemini/tool_result",
|
|
3690
|
+
preview: previewOf2(resultText),
|
|
3691
|
+
blocks: [
|
|
3692
|
+
{
|
|
3693
|
+
type: "tool_result",
|
|
3694
|
+
tool_use_id: tc.id,
|
|
3695
|
+
content: resultText,
|
|
3696
|
+
is_error: status2 === "error" || status2 === "cancelled"
|
|
3697
|
+
}
|
|
3698
|
+
],
|
|
3699
|
+
toolUseId: tc.id,
|
|
3700
|
+
toolResult: resultText,
|
|
3701
|
+
raw: tc
|
|
3702
|
+
});
|
|
3703
|
+
}
|
|
3704
|
+
}
|
|
3705
|
+
continue;
|
|
3706
|
+
}
|
|
3707
|
+
if (msg.type === "info" || msg.type === "warning" || msg.type === "error") {
|
|
3708
|
+
const text = flattenContent(msg.content);
|
|
3709
|
+
pushEvent({
|
|
3710
|
+
index: idx++,
|
|
3711
|
+
timestamp: ts,
|
|
3712
|
+
role: "meta",
|
|
3713
|
+
rawType: `gemini/${msg.type}`,
|
|
3714
|
+
preview: previewOf2(text),
|
|
3715
|
+
blocks: text ? [{ type: "text", text }] : [],
|
|
3716
|
+
raw: msg
|
|
3717
|
+
});
|
|
3718
|
+
continue;
|
|
3719
|
+
}
|
|
3720
|
+
}
|
|
3721
|
+
const startMs = firstTimestamp ? Date.parse(firstTimestamp) : void 0;
|
|
3722
|
+
if (startMs !== void 0 && Number.isFinite(startMs)) {
|
|
3723
|
+
let prevMs;
|
|
3724
|
+
for (const ev of events) {
|
|
3725
|
+
if (!ev.timestamp)
|
|
3726
|
+
continue;
|
|
3727
|
+
const ms = Date.parse(ev.timestamp);
|
|
3728
|
+
if (!Number.isFinite(ms))
|
|
3729
|
+
continue;
|
|
3730
|
+
ev.tOffsetMs = Math.max(0, ms - startMs);
|
|
3731
|
+
if (prevMs !== void 0)
|
|
3732
|
+
ev.gapMs = Math.max(0, ms - prevMs);
|
|
3733
|
+
prevMs = ms;
|
|
3734
|
+
}
|
|
3735
|
+
}
|
|
3736
|
+
const activeSegments = computeActiveSegments3(tsMs);
|
|
3737
|
+
const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
|
|
3738
|
+
const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
|
|
3739
|
+
const sessionId = metaRec.sessionId ?? file.filenameId;
|
|
3740
|
+
const projectName = cwd ? canonicalProjectName(cwd) : file.slug;
|
|
3741
|
+
const projectDir = cwd ? cwd.replace(/^\//, "-").replace(/\//g, "-") : file.slug;
|
|
3742
|
+
const meta = {
|
|
3743
|
+
agent: "gemini",
|
|
3744
|
+
id: sessionId,
|
|
3745
|
+
filePath: file.filePath,
|
|
3746
|
+
projectName,
|
|
3747
|
+
projectDir,
|
|
3748
|
+
sessionId,
|
|
3749
|
+
firstTimestamp,
|
|
3750
|
+
lastTimestamp,
|
|
3751
|
+
durationMs: durationMs && Number.isFinite(durationMs) ? durationMs : void 0,
|
|
3752
|
+
eventCount: events.length,
|
|
3753
|
+
model,
|
|
3754
|
+
cwd,
|
|
3755
|
+
totalUsage,
|
|
3756
|
+
status: "idle",
|
|
3757
|
+
firstUserPreview,
|
|
3758
|
+
lastUserPreview,
|
|
3759
|
+
lastAgentPreview,
|
|
3760
|
+
toolCallCount,
|
|
3761
|
+
turnCount,
|
|
3762
|
+
airTimeMs,
|
|
3763
|
+
activeSegments
|
|
3764
|
+
};
|
|
3765
|
+
return { meta, events };
|
|
3766
|
+
}
|
|
3767
|
+
function computeActiveSegments3(tsMs) {
|
|
3768
|
+
if (tsMs.length === 0)
|
|
3769
|
+
return [];
|
|
3770
|
+
const sorted = [...tsMs].sort((a, b) => a - b);
|
|
3771
|
+
const out = [];
|
|
3772
|
+
let segStart = sorted[0];
|
|
3773
|
+
let segEnd = sorted[0];
|
|
3774
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
3775
|
+
if (sorted[i] - segEnd > IDLE_GAP_MS2) {
|
|
3776
|
+
out.push({ startMs: segStart, endMs: segEnd });
|
|
3777
|
+
segStart = sorted[i];
|
|
3778
|
+
}
|
|
3779
|
+
segEnd = sorted[i];
|
|
3780
|
+
}
|
|
3781
|
+
out.push({ startMs: segStart, endMs: segEnd });
|
|
3782
|
+
return out;
|
|
3783
|
+
}
|
|
3784
|
+
function clearGeminiCaches() {
|
|
3785
|
+
metaCache3.clear();
|
|
3786
|
+
detailCache3.clear();
|
|
3787
|
+
projectsCache = null;
|
|
3788
|
+
}
|
|
3789
|
+
async function listGeminiSessions(opts = {}) {
|
|
3790
|
+
const root = opts.root ?? DEFAULT_GEMINI_ROOT;
|
|
3791
|
+
const files = await listSessionFiles(root);
|
|
3792
|
+
const out = [];
|
|
3793
|
+
for (const file of files) {
|
|
3794
|
+
const cached = metaCache3.get(file.filePath);
|
|
3795
|
+
if (cached && cached.mtimeMs === file.mtimeMs && cached.sizeBytes === file.sizeBytes) {
|
|
3796
|
+
out.push(cached.meta);
|
|
3797
|
+
continue;
|
|
3798
|
+
}
|
|
3799
|
+
try {
|
|
3800
|
+
const { meta } = await parseSession(file);
|
|
3801
|
+
metaCache3.set(file.filePath, {
|
|
3802
|
+
meta,
|
|
3803
|
+
mtimeMs: file.mtimeMs,
|
|
3804
|
+
sizeBytes: file.sizeBytes
|
|
3805
|
+
});
|
|
3806
|
+
out.push(meta);
|
|
3807
|
+
} catch {
|
|
3808
|
+
}
|
|
3809
|
+
}
|
|
3810
|
+
out.sort((a, b) => (b.firstTimestamp ?? "").localeCompare(a.firstTimestamp ?? ""));
|
|
3811
|
+
if (opts.limit !== void 0)
|
|
3812
|
+
return out.slice(0, opts.limit);
|
|
3813
|
+
return out;
|
|
3814
|
+
}
|
|
3815
|
+
async function getGeminiSession(id, opts = {}) {
|
|
3816
|
+
const root = opts.root ?? DEFAULT_GEMINI_ROOT;
|
|
3817
|
+
const files = await listSessionFiles(root);
|
|
3818
|
+
let chosen;
|
|
3819
|
+
for (const file of files) {
|
|
3820
|
+
if (file.filenameId === id || id.startsWith(file.filenameId)) {
|
|
3821
|
+
chosen = file;
|
|
3822
|
+
break;
|
|
3823
|
+
}
|
|
3824
|
+
}
|
|
3825
|
+
if (!chosen) {
|
|
3826
|
+
for (const file of files) {
|
|
3827
|
+
const { meta: meta2 } = await parseSession(file).catch(() => ({ meta: { id: "" } }));
|
|
3828
|
+
if (meta2.id === id) {
|
|
3829
|
+
chosen = file;
|
|
3830
|
+
break;
|
|
3831
|
+
}
|
|
3832
|
+
}
|
|
3833
|
+
}
|
|
3834
|
+
if (!chosen)
|
|
3835
|
+
return null;
|
|
3836
|
+
const cached = detailCache3.get(chosen.filePath);
|
|
3837
|
+
if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes) {
|
|
3838
|
+
return cached.detail;
|
|
3839
|
+
}
|
|
3840
|
+
const { meta, events } = await parseSession(chosen);
|
|
3841
|
+
const detail = { ...meta, events };
|
|
3842
|
+
detailCache3.set(chosen.filePath, {
|
|
3843
|
+
detail,
|
|
3844
|
+
mtimeMs: chosen.mtimeMs,
|
|
3845
|
+
sizeBytes: chosen.sizeBytes
|
|
3846
|
+
});
|
|
3847
|
+
return detail;
|
|
3848
|
+
}
|
|
3849
|
+
function geminiSessionLocalDay(meta) {
|
|
3850
|
+
if (!meta.firstTimestamp)
|
|
3851
|
+
return void 0;
|
|
3852
|
+
const ms = Date.parse(meta.firstTimestamp);
|
|
3853
|
+
return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
|
|
3854
|
+
}
|
|
3855
|
+
var DEFAULT_GEMINI_ROOT, GEMINI_PROJECTS_FILE, SESSION_FILE_RE, IDLE_GAP_MS2, projectsCache, metaCache3, detailCache3;
|
|
3856
|
+
var init_gemini = __esm({
|
|
3857
|
+
"../parser/dist/gemini.js"() {
|
|
3858
|
+
"use strict";
|
|
3859
|
+
init_analytics();
|
|
3860
|
+
DEFAULT_GEMINI_ROOT = path3.join(os3.homedir(), ".gemini", "tmp");
|
|
3861
|
+
GEMINI_PROJECTS_FILE = path3.join(os3.homedir(), ".gemini", "projects.json");
|
|
3862
|
+
SESSION_FILE_RE = /^session-.+\.(jsonl|json)$/;
|
|
3863
|
+
IDLE_GAP_MS2 = 3 * 60 * 1e3;
|
|
3864
|
+
projectsCache = null;
|
|
3865
|
+
metaCache3 = /* @__PURE__ */ new Map();
|
|
3866
|
+
detailCache3 = /* @__PURE__ */ new Map();
|
|
3867
|
+
}
|
|
3868
|
+
});
|
|
3869
|
+
|
|
3363
3870
|
// ../parser/dist/fs.js
|
|
3364
3871
|
var fs_exports = {};
|
|
3365
3872
|
__export(fs_exports, {
|
|
3366
3873
|
DEFAULT_CODEX_ROOT: () => DEFAULT_CODEX_ROOT,
|
|
3874
|
+
DEFAULT_GEMINI_ROOT: () => DEFAULT_GEMINI_ROOT,
|
|
3367
3875
|
DEFAULT_ROOT: () => DEFAULT_ROOT,
|
|
3368
3876
|
agentSources: () => agentSources,
|
|
3369
3877
|
buildCalibrationCurve: () => buildCalibrationCurve,
|
|
@@ -3372,14 +3880,17 @@ __export(fs_exports, {
|
|
|
3372
3880
|
codexSessionLocalDay: () => codexSessionLocalDay,
|
|
3373
3881
|
decodeProjectName: () => decodeProjectName,
|
|
3374
3882
|
findTeamLead: () => findTeamLead,
|
|
3883
|
+
geminiSessionLocalDay: () => geminiSessionLocalDay,
|
|
3375
3884
|
getAgentSource: () => getAgentSource,
|
|
3376
3885
|
getAnySession: () => getAnySession,
|
|
3377
3886
|
getCodexSession: () => getCodexSession,
|
|
3887
|
+
getGeminiSession: () => getGeminiSession,
|
|
3378
3888
|
getLatestCodexUsage: () => getLatestCodexUsage,
|
|
3379
3889
|
getSession: () => getSession,
|
|
3380
3890
|
invalidateFile: () => invalidateFile,
|
|
3381
3891
|
listAllSessions: () => listAllSessions,
|
|
3382
3892
|
listCodexSessions: () => listCodexSessions,
|
|
3893
|
+
listGeminiSessions: () => listGeminiSessions,
|
|
3383
3894
|
listProjects: () => listProjects,
|
|
3384
3895
|
listSessions: () => listSessions,
|
|
3385
3896
|
loadCalibrationCurve: () => loadCalibrationCurve,
|
|
@@ -3391,15 +3902,16 @@ __export(fs_exports, {
|
|
|
3391
3902
|
sessionIdFromFileName: () => sessionIdFromFileName,
|
|
3392
3903
|
walkJsonlFiles: () => walkJsonlFiles
|
|
3393
3904
|
});
|
|
3394
|
-
import { promises as
|
|
3395
|
-
import
|
|
3396
|
-
import
|
|
3905
|
+
import { promises as fs4 } from "node:fs";
|
|
3906
|
+
import os4 from "node:os";
|
|
3907
|
+
import path4 from "node:path";
|
|
3397
3908
|
function cacheStats() {
|
|
3398
3909
|
return claudeCodeCacheStats();
|
|
3399
3910
|
}
|
|
3400
3911
|
function clearCaches() {
|
|
3401
3912
|
clearClaudeCodeCaches();
|
|
3402
3913
|
clearCodexCaches();
|
|
3914
|
+
clearGeminiCaches();
|
|
3403
3915
|
}
|
|
3404
3916
|
function invalidateFile(fullPath) {
|
|
3405
3917
|
invalidateClaudeCodeFile(fullPath);
|
|
@@ -3428,7 +3940,7 @@ async function getAnySession(id) {
|
|
|
3428
3940
|
async function loadUsageByDay(start2, end) {
|
|
3429
3941
|
let raw;
|
|
3430
3942
|
try {
|
|
3431
|
-
raw = await
|
|
3943
|
+
raw = await fs4.readFile(USAGE_LOG2, "utf8");
|
|
3432
3944
|
} catch {
|
|
3433
3945
|
return { by_day: [] };
|
|
3434
3946
|
}
|
|
@@ -3473,7 +3985,7 @@ async function loadUsageByDay(start2, end) {
|
|
|
3473
3985
|
async function loadCalibrationSnapshots() {
|
|
3474
3986
|
let raw;
|
|
3475
3987
|
try {
|
|
3476
|
-
raw = await
|
|
3988
|
+
raw = await fs4.readFile(USAGE_LOG2, "utf8");
|
|
3477
3989
|
} catch {
|
|
3478
3990
|
return [];
|
|
3479
3991
|
}
|
|
@@ -3631,7 +4143,7 @@ async function loadCalibrationCurve(tier = "pro-max-20x", root = DEFAULT_ROOT, g
|
|
|
3631
4143
|
]);
|
|
3632
4144
|
return buildCalibrationCurve(events, snapshots, tier, granularityMin);
|
|
3633
4145
|
}
|
|
3634
|
-
var codexSource, agentSources, USAGE_LOG2;
|
|
4146
|
+
var codexSource, geminiSource, agentSources, USAGE_LOG2;
|
|
3635
4147
|
var init_fs = __esm({
|
|
3636
4148
|
"../parser/dist/fs.js"() {
|
|
3637
4149
|
"use strict";
|
|
@@ -3640,8 +4152,10 @@ var init_fs = __esm({
|
|
|
3640
4152
|
init_calibration();
|
|
3641
4153
|
init_claude_code();
|
|
3642
4154
|
init_codex();
|
|
4155
|
+
init_gemini();
|
|
3643
4156
|
init_claude_code();
|
|
3644
4157
|
init_codex();
|
|
4158
|
+
init_gemini();
|
|
3645
4159
|
codexSource = {
|
|
3646
4160
|
...CODEX_METADATA,
|
|
3647
4161
|
defaultRoot: DEFAULT_CODEX_ROOT,
|
|
@@ -3663,8 +4177,18 @@ var init_fs = __esm({
|
|
|
3663
4177
|
};
|
|
3664
4178
|
}
|
|
3665
4179
|
};
|
|
3666
|
-
|
|
3667
|
-
|
|
4180
|
+
geminiSource = {
|
|
4181
|
+
...GEMINI_METADATA,
|
|
4182
|
+
defaultRoot: DEFAULT_GEMINI_ROOT,
|
|
4183
|
+
async listSessions(opts) {
|
|
4184
|
+
return listGeminiSessions(opts);
|
|
4185
|
+
},
|
|
4186
|
+
async getSession(id) {
|
|
4187
|
+
return getGeminiSession(id);
|
|
4188
|
+
}
|
|
4189
|
+
};
|
|
4190
|
+
agentSources = [claudeCodeSource, codexSource, geminiSource];
|
|
4191
|
+
USAGE_LOG2 = path4.join(os4.homedir(), ".cclens", "usage.jsonl");
|
|
3668
4192
|
}
|
|
3669
4193
|
});
|
|
3670
4194
|
|
|
@@ -4161,7 +4685,7 @@ var init_trivial = __esm({
|
|
|
4161
4685
|
});
|
|
4162
4686
|
|
|
4163
4687
|
// ../entries/dist/build.js
|
|
4164
|
-
var
|
|
4688
|
+
var IDLE_GAP_MS3;
|
|
4165
4689
|
var init_build = __esm({
|
|
4166
4690
|
"../entries/dist/build.js"() {
|
|
4167
4691
|
"use strict";
|
|
@@ -4169,7 +4693,7 @@ var init_build = __esm({
|
|
|
4169
4693
|
init_types();
|
|
4170
4694
|
init_signals();
|
|
4171
4695
|
init_trivial();
|
|
4172
|
-
|
|
4696
|
+
IDLE_GAP_MS3 = 3 * 60 * 1e3;
|
|
4173
4697
|
}
|
|
4174
4698
|
});
|
|
4175
4699
|
|
|
@@ -4203,11 +4727,11 @@ function digestsDir() {
|
|
|
4203
4727
|
digestsDirCached = envOverride ?? join6(homedir5(), ".cclens", "digests");
|
|
4204
4728
|
return digestsDirCached;
|
|
4205
4729
|
}
|
|
4206
|
-
function __setDigestsDirForTest(
|
|
4207
|
-
digestsDirCached =
|
|
4208
|
-
mkdirSync3(join6(
|
|
4209
|
-
mkdirSync3(join6(
|
|
4210
|
-
mkdirSync3(join6(
|
|
4730
|
+
function __setDigestsDirForTest(path5) {
|
|
4731
|
+
digestsDirCached = path5;
|
|
4732
|
+
mkdirSync3(join6(path5, "day"), { recursive: true });
|
|
4733
|
+
mkdirSync3(join6(path5, "week"), { recursive: true });
|
|
4734
|
+
mkdirSync3(join6(path5, "month"), { recursive: true });
|
|
4211
4735
|
}
|
|
4212
4736
|
function dayDigestPath(date) {
|
|
4213
4737
|
return join6(digestsDir(), "day", `${date}.json`);
|
|
@@ -4394,9 +4918,9 @@ function entriesDir() {
|
|
|
4394
4918
|
entriesDirCached = envOverride ?? join7(homedir6(), ".cclens", "entries");
|
|
4395
4919
|
return entriesDirCached;
|
|
4396
4920
|
}
|
|
4397
|
-
function __setEntriesDirForTest(
|
|
4398
|
-
entriesDirCached =
|
|
4399
|
-
mkdirSync4(
|
|
4921
|
+
function __setEntriesDirForTest(path5) {
|
|
4922
|
+
entriesDirCached = path5;
|
|
4923
|
+
mkdirSync4(path5, { recursive: true });
|
|
4400
4924
|
}
|
|
4401
4925
|
function pathFor(sessionId, localDay) {
|
|
4402
4926
|
return join7(entriesDir(), `${entryKey(sessionId, localDay)}.json`);
|
|
@@ -4931,8 +5455,8 @@ var init_parseUtil = __esm({
|
|
|
4931
5455
|
init_errors();
|
|
4932
5456
|
init_en();
|
|
4933
5457
|
makeIssue = (params) => {
|
|
4934
|
-
const { data, path:
|
|
4935
|
-
const fullPath = [...
|
|
5458
|
+
const { data, path: path5, errorMaps, issueData } = params;
|
|
5459
|
+
const fullPath = [...path5, ...issueData.path || []];
|
|
4936
5460
|
const fullIssue = {
|
|
4937
5461
|
...issueData,
|
|
4938
5462
|
path: fullPath
|
|
@@ -5240,11 +5764,11 @@ var init_types2 = __esm({
|
|
|
5240
5764
|
init_parseUtil();
|
|
5241
5765
|
init_util();
|
|
5242
5766
|
ParseInputLazyPath = class {
|
|
5243
|
-
constructor(parent, value,
|
|
5767
|
+
constructor(parent, value, path5, key) {
|
|
5244
5768
|
this._cachedPath = [];
|
|
5245
5769
|
this.parent = parent;
|
|
5246
5770
|
this.data = value;
|
|
5247
|
-
this._path =
|
|
5771
|
+
this._path = path5;
|
|
5248
5772
|
this._key = key;
|
|
5249
5773
|
}
|
|
5250
5774
|
get path() {
|
|
@@ -8765,15 +9289,15 @@ function newRunId(kind) {
|
|
|
8765
9289
|
function tracePath(runId) {
|
|
8766
9290
|
return join8(RUNS_DIR, `${runId}.jsonl`);
|
|
8767
9291
|
}
|
|
8768
|
-
function safeAppend(
|
|
9292
|
+
function safeAppend(path5, line) {
|
|
8769
9293
|
try {
|
|
8770
|
-
appendFileSync2(
|
|
9294
|
+
appendFileSync2(path5, line);
|
|
8771
9295
|
} catch {
|
|
8772
9296
|
}
|
|
8773
9297
|
}
|
|
8774
|
-
function safeWrite(
|
|
9298
|
+
function safeWrite(path5, line) {
|
|
8775
9299
|
try {
|
|
8776
|
-
writeFileSync4(
|
|
9300
|
+
writeFileSync4(path5, line);
|
|
8777
9301
|
} catch {
|
|
8778
9302
|
}
|
|
8779
9303
|
}
|
|
@@ -9113,8 +9637,8 @@ function spendPath() {
|
|
|
9113
9637
|
spendPathCached = join9(homedir8(), ".cclens", "llm-spend.jsonl");
|
|
9114
9638
|
return spendPathCached;
|
|
9115
9639
|
}
|
|
9116
|
-
function __setSpendPathForTest(
|
|
9117
|
-
spendPathCached =
|
|
9640
|
+
function __setSpendPathForTest(path5) {
|
|
9641
|
+
spendPathCached = path5;
|
|
9118
9642
|
}
|
|
9119
9643
|
function appendSpend(record) {
|
|
9120
9644
|
const p = spendPath();
|
|
@@ -9165,8 +9689,8 @@ function lockPath() {
|
|
|
9165
9689
|
lockPathCached = join10(homedir9(), ".cclens", "llm-interactive.lock");
|
|
9166
9690
|
return lockPathCached;
|
|
9167
9691
|
}
|
|
9168
|
-
function __setInteractiveLockPathForTest(
|
|
9169
|
-
lockPathCached =
|
|
9692
|
+
function __setInteractiveLockPathForTest(path5) {
|
|
9693
|
+
lockPathCached = path5;
|
|
9170
9694
|
}
|
|
9171
9695
|
function touchLock() {
|
|
9172
9696
|
writeFileSync5(lockPath(), String(process.pid), "utf8");
|
|
@@ -9323,8 +9847,8 @@ function settingsPath() {
|
|
|
9323
9847
|
settingsPathCached = join11(homedir10(), ".cclens", "settings.json");
|
|
9324
9848
|
return settingsPathCached;
|
|
9325
9849
|
}
|
|
9326
|
-
function __setSettingsPathForTest(
|
|
9327
|
-
settingsPathCached =
|
|
9850
|
+
function __setSettingsPathForTest(path5) {
|
|
9851
|
+
settingsPathCached = path5;
|
|
9328
9852
|
}
|
|
9329
9853
|
function toDisk(s) {
|
|
9330
9854
|
return {
|
|
@@ -9788,6 +10312,7 @@ var dist_exports = {};
|
|
|
9788
10312
|
__export(dist_exports, {
|
|
9789
10313
|
CLAUDE_CODE_METADATA: () => CLAUDE_CODE_METADATA,
|
|
9790
10314
|
CODEX_METADATA: () => CODEX_METADATA,
|
|
10315
|
+
GEMINI_METADATA: () => GEMINI_METADATA,
|
|
9791
10316
|
PRICES: () => PRICES,
|
|
9792
10317
|
RATE_PER_PCT: () => RATE_PER_PCT,
|
|
9793
10318
|
RATE_PER_PCT_5H: () => RATE_PER_PCT_5H,
|
|
@@ -10021,7 +10546,7 @@ function rollupOutcomeDay(entries2) {
|
|
|
10021
10546
|
return "exploratory";
|
|
10022
10547
|
return "trivial";
|
|
10023
10548
|
}
|
|
10024
|
-
function
|
|
10549
|
+
function truncate4(s, max) {
|
|
10025
10550
|
if (s.length <= max)
|
|
10026
10551
|
return s;
|
|
10027
10552
|
return s.slice(0, max - 1).trimEnd() + "\u2026";
|
|
@@ -10077,7 +10602,7 @@ function computeDaySignals(entries2) {
|
|
|
10077
10602
|
type,
|
|
10078
10603
|
count: v.count,
|
|
10079
10604
|
sample_description: v.sample_description,
|
|
10080
|
-
sample_prompt_preview:
|
|
10605
|
+
sample_prompt_preview: truncate4(v.sample_prompt_preview, 200)
|
|
10081
10606
|
}));
|
|
10082
10607
|
const frameCounts = /* @__PURE__ */ new Map();
|
|
10083
10608
|
for (const s of signalsList) {
|
|
@@ -10096,7 +10621,7 @@ function computeDaySignals(entries2) {
|
|
|
10096
10621
|
if ((e.first_user ?? "").length > 0)
|
|
10097
10622
|
verbosity_distribution[s.verbosity] += 1;
|
|
10098
10623
|
for (const ref of s.external_refs) {
|
|
10099
|
-
external_refs.push({ session_id: e.session_id, kind: ref.kind, preview:
|
|
10624
|
+
external_refs.push({ session_id: e.session_id, kind: ref.kind, preview: truncate4(ref.preview, 200) });
|
|
10100
10625
|
}
|
|
10101
10626
|
const ints = e.numbers.interrupts ?? 0;
|
|
10102
10627
|
interrupts += ints;
|
|
@@ -10969,7 +11494,7 @@ function computeInteractionModes(entries2) {
|
|
|
10969
11494
|
date: entry.local_day,
|
|
10970
11495
|
project_display: prettyProject3(entry.project),
|
|
10971
11496
|
type: sa.type,
|
|
10972
|
-
prompt_preview:
|
|
11497
|
+
prompt_preview: truncate5(sa.prompt_preview, 200)
|
|
10973
11498
|
});
|
|
10974
11499
|
}
|
|
10975
11500
|
const skillExamples = [];
|
|
@@ -10986,7 +11511,7 @@ function computeInteractionModes(entries2) {
|
|
|
10986
11511
|
skillExamples.push({
|
|
10987
11512
|
date: e.local_day,
|
|
10988
11513
|
skill,
|
|
10989
|
-
first_user_preview:
|
|
11514
|
+
first_user_preview: truncate5(e.first_user, 200)
|
|
10990
11515
|
});
|
|
10991
11516
|
}
|
|
10992
11517
|
}
|
|
@@ -11003,7 +11528,7 @@ function computeInteractionModes(entries2) {
|
|
|
11003
11528
|
project_display: prettyProject3(longestTurnEntry.project),
|
|
11004
11529
|
active_min: longestTurnEntry.numbers.active_min,
|
|
11005
11530
|
top_tools: longestTurnEntry.top_tools.slice(0, 5),
|
|
11006
|
-
first_user_preview:
|
|
11531
|
+
first_user_preview: truncate5(longestTurnEntry.first_user, 200)
|
|
11007
11532
|
} : null;
|
|
11008
11533
|
const tools_per_turn = turn_count > 0 ? tools_total / turn_count : 0;
|
|
11009
11534
|
const label = tools_per_turn < 5 ? "rapid" : tools_per_turn < 15 ? "mixed" : "batch";
|
|
@@ -11034,7 +11559,7 @@ function computeInteractionModes(entries2) {
|
|
|
11034
11559
|
}
|
|
11035
11560
|
};
|
|
11036
11561
|
}
|
|
11037
|
-
function
|
|
11562
|
+
function truncate5(s, max) {
|
|
11038
11563
|
if (s.length <= max)
|
|
11039
11564
|
return s;
|
|
11040
11565
|
return s.slice(0, max - 1).trimEnd() + "\u2026";
|
|
@@ -11081,7 +11606,7 @@ function computeWorkingShapes(dayDigests, entriesByDay = /* @__PURE__ */ new Map
|
|
|
11081
11606
|
evidence_subagent = {
|
|
11082
11607
|
type: sa.type,
|
|
11083
11608
|
description: sa.description,
|
|
11084
|
-
prompt_preview:
|
|
11609
|
+
prompt_preview: truncate5(sa.prompt_preview, 200)
|
|
11085
11610
|
};
|
|
11086
11611
|
}
|
|
11087
11612
|
const project_display = repEntry ? prettyProject3(repEntry.project) : dd.projects[0]?.display_name ?? "";
|
|
@@ -11092,7 +11617,7 @@ function computeWorkingShapes(dayDigests, entriesByDay = /* @__PURE__ */ new Map
|
|
|
11092
11617
|
outcome: dayOutcome.get(dd.key) ?? null,
|
|
11093
11618
|
helpfulness: dayHelp.get(dd.key) ?? null,
|
|
11094
11619
|
evidence_subagent,
|
|
11095
|
-
evidence_first_user: repEntry?.first_user ?
|
|
11620
|
+
evidence_first_user: repEntry?.first_user ? truncate5(repEntry.first_user, 200) : null,
|
|
11096
11621
|
day_signature: dd.day_signature ?? null
|
|
11097
11622
|
};
|
|
11098
11623
|
});
|
|
@@ -11167,7 +11692,7 @@ function computeInteractionGrammar(dayDigests, entriesByDay = /* @__PURE__ */ ne
|
|
|
11167
11692
|
date: day2,
|
|
11168
11693
|
session_id: ref.session_id,
|
|
11169
11694
|
ref_kind: ref.kind,
|
|
11170
|
-
preview:
|
|
11695
|
+
preview: truncate5(ref.preview, 200)
|
|
11171
11696
|
});
|
|
11172
11697
|
}
|
|
11173
11698
|
total_interrupts += signals.comm_style.steering.interrupts;
|
|
@@ -11239,7 +11764,7 @@ function computeInteractionGrammar(dayDigests, entriesByDay = /* @__PURE__ */ ne
|
|
|
11239
11764
|
count: v.count,
|
|
11240
11765
|
days: [...v.days].sort(),
|
|
11241
11766
|
sample_description: v.sample_description,
|
|
11242
|
-
sample_prompt_preview:
|
|
11767
|
+
sample_prompt_preview: truncate5(v.sample_prompt_preview, 200)
|
|
11243
11768
|
})),
|
|
11244
11769
|
threads,
|
|
11245
11770
|
communication_style: {
|
|
@@ -11887,7 +12412,7 @@ function activeMs(timestamps) {
|
|
|
11887
12412
|
let active = 0;
|
|
11888
12413
|
for (let i = 1; i < ts.length; i++) {
|
|
11889
12414
|
const dt = ts[i] - ts[i - 1];
|
|
11890
|
-
if (dt <
|
|
12415
|
+
if (dt < IDLE_GAP_MS4)
|
|
11891
12416
|
active += dt;
|
|
11892
12417
|
}
|
|
11893
12418
|
return active;
|
|
@@ -12058,7 +12583,7 @@ function buildSessionSlice(entry, events, daySignature) {
|
|
|
12058
12583
|
let intEnd = sortedTs[0];
|
|
12059
12584
|
for (let i = 1; i < sortedTs.length; i++) {
|
|
12060
12585
|
const dt = sortedTs[i] - intEnd;
|
|
12061
|
-
if (dt >=
|
|
12586
|
+
if (dt >= IDLE_GAP_MS4) {
|
|
12062
12587
|
intervals.push({
|
|
12063
12588
|
start_min: fmtMin(intStart - sliceStartMs),
|
|
12064
12589
|
end_min: fmtMin(intEnd - sliceStartMs)
|
|
@@ -12455,14 +12980,14 @@ async function generateTopSession(slice, opts = {}) {
|
|
|
12455
12980
|
void lastModel;
|
|
12456
12981
|
}
|
|
12457
12982
|
}
|
|
12458
|
-
var
|
|
12983
|
+
var IDLE_GAP_MS4, LONG_AUTONOMOUS_MIN, N_USER, N_FIRST_AGENT, N_LAST_AGENT, N_USER_TURN1, N_SUBAGENT, SHELL_NOISE, INTERRUPT_RE2, PR_TITLE_RE, PinResponseSchema, TopSessionResponseSchema, SYSTEM_PROMPT5, TOP_SESSION_SYSTEM_PROMPT, DEFAULT_MODEL5, defaultCallLLMTopSession, validateTopSession;
|
|
12459
12984
|
var init_top_sessions = __esm({
|
|
12460
12985
|
"../entries/dist/top-sessions.js"() {
|
|
12461
12986
|
"use strict";
|
|
12462
12987
|
init_zod();
|
|
12463
12988
|
init_signals();
|
|
12464
12989
|
init_llm_runner();
|
|
12465
|
-
|
|
12990
|
+
IDLE_GAP_MS4 = 3 * 60 * 1e3;
|
|
12466
12991
|
LONG_AUTONOMOUS_MIN = 20;
|
|
12467
12992
|
N_USER = 150;
|
|
12468
12993
|
N_FIRST_AGENT = 150;
|
|
@@ -14018,6 +14543,7 @@ async function buildCyclePeaksForPush(planTier, loadCurve) {
|
|
|
14018
14543
|
const HOUR = 36e5;
|
|
14019
14544
|
const nowMs = Date.now();
|
|
14020
14545
|
const peaksFor = (cycleKey, realKey, predKey, maxCycles) => {
|
|
14546
|
+
const TOLERANCE_MS = cycleKey === "cycle_end_7d" ? 12 * HOUR : 0;
|
|
14021
14547
|
const byCycle = /* @__PURE__ */ new Map();
|
|
14022
14548
|
for (const p of dump.curve) {
|
|
14023
14549
|
const k = p[cycleKey];
|
|
@@ -14029,8 +14555,18 @@ async function buildCyclePeaksForPush(planTier, loadCurve) {
|
|
|
14029
14555
|
arr.push(p);
|
|
14030
14556
|
byCycle.set(bucket, arr);
|
|
14031
14557
|
}
|
|
14032
|
-
const
|
|
14558
|
+
const merged = [];
|
|
14033
14559
|
for (const [endMs, points] of Array.from(byCycle.entries()).sort((a, b) => a[0] - b[0])) {
|
|
14560
|
+
const last = merged[merged.length - 1];
|
|
14561
|
+
if (last && endMs - last.endMs <= TOLERANCE_MS) {
|
|
14562
|
+
last.endMs = endMs;
|
|
14563
|
+
last.points.push(...points);
|
|
14564
|
+
} else {
|
|
14565
|
+
merged.push({ endMs, points: [...points] });
|
|
14566
|
+
}
|
|
14567
|
+
}
|
|
14568
|
+
const out = [];
|
|
14569
|
+
for (const { endMs, points } of merged) {
|
|
14034
14570
|
let peak = 0;
|
|
14035
14571
|
let source = "predicted";
|
|
14036
14572
|
for (const p of points) {
|
|
@@ -14526,9 +15062,9 @@ function listTraceFiles() {
|
|
|
14526
15062
|
if (!existsSync12(RUNS_DIR2)) return [];
|
|
14527
15063
|
const entries2 = readdirSync3(RUNS_DIR2).filter((f) => f.endsWith(".jsonl"));
|
|
14528
15064
|
return entries2.map((f) => {
|
|
14529
|
-
const
|
|
14530
|
-
const st = statSync4(
|
|
14531
|
-
return { runId: f.replace(/\.jsonl$/, ""), path:
|
|
15065
|
+
const path5 = join17(RUNS_DIR2, f);
|
|
15066
|
+
const st = statSync4(path5);
|
|
15067
|
+
return { runId: f.replace(/\.jsonl$/, ""), path: path5, mtimeMs: st.mtimeMs };
|
|
14532
15068
|
}).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
14533
15069
|
}
|
|
14534
15070
|
function resolveRunId(arg) {
|
|
@@ -14550,8 +15086,8 @@ function resolveRunId(arg) {
|
|
|
14550
15086
|
}
|
|
14551
15087
|
return null;
|
|
14552
15088
|
}
|
|
14553
|
-
function readTrace(
|
|
14554
|
-
return readFileSync15(
|
|
15089
|
+
function readTrace(path5) {
|
|
15090
|
+
return readFileSync15(path5, "utf-8").split("\n").filter((l) => l.trim()).map((l) => {
|
|
14555
15091
|
try {
|
|
14556
15092
|
return JSON.parse(l);
|
|
14557
15093
|
} catch {
|
|
@@ -14732,7 +15268,7 @@ async function main() {
|
|
|
14732
15268
|
case "version":
|
|
14733
15269
|
case "--version":
|
|
14734
15270
|
case "-v":
|
|
14735
|
-
console.log(`fleetlens ${"0.
|
|
15271
|
+
console.log(`fleetlens ${"0.9.0"}`);
|
|
14736
15272
|
break;
|
|
14737
15273
|
case "help":
|
|
14738
15274
|
case "--help":
|