fleetlens 0.16.0 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/apps/web/.next/BUILD_ID +1 -1
- package/app/apps/web/.next/build-manifest.json +3 -3
- package/app/apps/web/.next/prerender-manifest.json +3 -3
- package/app/apps/web/.next/server/app/_global-error.html +1 -1
- package/app/apps/web/.next/server/app/_global-error.rsc +1 -1
- package/app/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/app/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/app/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/app/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/app/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/app/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/agent/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/agent/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/api/agent/chats/[id]/events/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/agent/chats/[id]/messages/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/agent/chats/[id]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/agent/chats/[id]/stop/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/agent/chats/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/agent/index/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/agent/mcp/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/agent/suggestions/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/ask/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/month-index/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/week-index/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/events/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/jobs/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/pdf/[key]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/projects/open-folder/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/runs/[runId]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/runs/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/settings/credentials/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/settings/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/team/autostart/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/team/onboarding/start/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/team/sync-projects/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/workflow-agent/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/changelog/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/changelog/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/day/[date]/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/day/[date]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/day/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/day/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/digest/[date]/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/digest/[date]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/digest/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/digest/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/insights/[key]/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/insights/[key]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/insights/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/insights/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/parallelism/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/parallelism/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/print/[key]/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/print/[key]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/projects/[slug]/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/projects/[slug]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/projects/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/runs/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/runs/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/sessions/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/team/onboarding/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/team/onboarding/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/team/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/team/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/usage/page.js +2 -1
- package/app/apps/web/.next/server/app/usage/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/usage/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0sr4wr_.js +1 -1
- package/app/apps/web/.next/server/chunks/packages_parser_dist_06d9se1._.js +1 -1
- package/app/apps/web/.next/server/chunks/packages_parser_dist_10ihc3~._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0f3q8gt._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__11xp-1u._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/_0k8yioi._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_0epqfet._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_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/0at6brbse8wn2.js +14 -0
- package/app/apps/web/.next/static/chunks/{0_0~~ipv90vm3.js → 0rrcj195v1nd..js} +1 -1
- package/app/apps/web/app/usage/page.tsx +166 -2
- package/app/apps/web/components/agent-badge.tsx +3 -0
- package/app/apps/web/components/agent-icon.tsx +42 -4
- package/app/apps/web/components/menubar-install-banner.tsx +2 -1
- package/app/apps/web/components/usage-charts-dashboard.tsx +9 -1
- package/app/apps/web/lib/changelog-data.generated.ts +1 -1
- package/app/apps/web/package.json +1 -1
- package/app/apps/web/public/agent-icons/grok.svg +8 -0
- package/app/apps/web/tsconfig.tsbuildinfo +1 -1
- package/dist/daemon-worker.js +1037 -110
- package/dist/index.js +1094 -154
- package/menubar/FleetlensMenubar.app/Contents/Info.plist +2 -2
- package/menubar/FleetlensMenubar.app/Contents/MacOS/FleetlensMenubar +0 -0
- package/menubar/FleetlensMenubar.app/Contents/Resources/grok.svg +8 -0
- package/menubar/FleetlensMenubar.app/Contents/_CodeSignature/CodeResources +11 -0
- package/package.json +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0ns6ydi._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0r4tks8._.js +0 -3
- package/app/apps/web/.next/static/chunks/0mry~475v0fa3.js +0 -14
- /package/app/apps/web/.next/static/{bTww6lPxII4wde65VQDrF → d1mwRtSMG-R7wb8o9KxM3}/_buildManifest.js +0 -0
- /package/app/apps/web/.next/static/{bTww6lPxII4wde65VQDrF → d1mwRtSMG-R7wb8o9KxM3}/_clientMiddlewareManifest.js +0 -0
- /package/app/apps/web/.next/static/{bTww6lPxII4wde65VQDrF → d1mwRtSMG-R7wb8o9KxM3}/_ssgManifest.js +0 -0
package/dist/index.js
CHANGED
|
@@ -675,7 +675,7 @@ function getAgentMetadata(kind) {
|
|
|
675
675
|
function isAgentKind(s) {
|
|
676
676
|
return typeof s === "string" && KNOWN_AGENT_KINDS.has(s);
|
|
677
677
|
}
|
|
678
|
-
var CLAUDE_CODE_METADATA, CODEX_METADATA, GEMINI_METADATA, ANTIGRAVITY_METADATA, COWORK_METADATA, ZAI_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
|
|
678
|
+
var CLAUDE_CODE_METADATA, CODEX_METADATA, GEMINI_METADATA, ANTIGRAVITY_METADATA, COWORK_METADATA, ZAI_METADATA, GROK_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
|
|
679
679
|
var init_agent_metadata = __esm({
|
|
680
680
|
"../parser/dist/agent-metadata.js"() {
|
|
681
681
|
"use strict";
|
|
@@ -721,13 +721,22 @@ var init_agent_metadata = __esm({
|
|
|
721
721
|
accentColor: "rgb(59, 130, 246)",
|
|
722
722
|
iconChar: "Z"
|
|
723
723
|
};
|
|
724
|
+
GROK_METADATA = {
|
|
725
|
+
kind: "grok",
|
|
726
|
+
displayName: "Grok Build",
|
|
727
|
+
shortLabel: "Grok",
|
|
728
|
+
// Slate-400 — visible on dark Fleetlens chrome and still fine on light.
|
|
729
|
+
accentColor: "rgb(100, 116, 139)",
|
|
730
|
+
iconChar: "\u25C8"
|
|
731
|
+
};
|
|
724
732
|
agentMetadata = [
|
|
725
733
|
CLAUDE_CODE_METADATA,
|
|
726
734
|
CODEX_METADATA,
|
|
727
735
|
GEMINI_METADATA,
|
|
728
736
|
ANTIGRAVITY_METADATA,
|
|
729
737
|
COWORK_METADATA,
|
|
730
|
-
ZAI_METADATA
|
|
738
|
+
ZAI_METADATA,
|
|
739
|
+
GROK_METADATA
|
|
731
740
|
];
|
|
732
741
|
KNOWN_AGENT_KINDS = new Set(agentMetadata.map((m) => m.kind));
|
|
733
742
|
}
|
|
@@ -1584,11 +1593,11 @@ function defaultBranch(commonDir) {
|
|
|
1584
1593
|
}
|
|
1585
1594
|
return void 0;
|
|
1586
1595
|
}
|
|
1587
|
-
function readGitFolder(
|
|
1588
|
-
if (!existsSync(
|
|
1596
|
+
function readGitFolder(path9) {
|
|
1597
|
+
if (!existsSync(path9))
|
|
1589
1598
|
return { exists: false, isWorktree: false };
|
|
1590
1599
|
try {
|
|
1591
|
-
const git = nearestDotGit(realpathOrSelf(
|
|
1600
|
+
const git = nearestDotGit(realpathOrSelf(path9));
|
|
1592
1601
|
if (!git)
|
|
1593
1602
|
return { exists: true, isWorktree: false };
|
|
1594
1603
|
const projectRoot = projectRootFromCommonDir(git.commonDir);
|
|
@@ -4469,6 +4478,672 @@ var init_cowork = __esm({
|
|
|
4469
4478
|
}
|
|
4470
4479
|
});
|
|
4471
4480
|
|
|
4481
|
+
// ../parser/dist/grok.js
|
|
4482
|
+
import { promises as fs6 } from "node:fs";
|
|
4483
|
+
import os6 from "node:os";
|
|
4484
|
+
import path6 from "node:path";
|
|
4485
|
+
function resolveDefaultGrokRoot() {
|
|
4486
|
+
const home = process.env.GROK_HOME || path6.join(os6.homedir(), ".grok");
|
|
4487
|
+
return path6.join(home, "sessions");
|
|
4488
|
+
}
|
|
4489
|
+
async function safeReaddir5(p) {
|
|
4490
|
+
return fs6.readdir(p).catch(() => []);
|
|
4491
|
+
}
|
|
4492
|
+
async function safeReadJson(p) {
|
|
4493
|
+
const raw = await fs6.readFile(p, "utf8").catch(() => null);
|
|
4494
|
+
if (raw == null)
|
|
4495
|
+
return null;
|
|
4496
|
+
try {
|
|
4497
|
+
return JSON.parse(raw);
|
|
4498
|
+
} catch {
|
|
4499
|
+
return null;
|
|
4500
|
+
}
|
|
4501
|
+
}
|
|
4502
|
+
async function resolveEncodedCwd(groupDir, encoded) {
|
|
4503
|
+
const cwdFile = path6.join(groupDir, ".cwd");
|
|
4504
|
+
const fromFile = await fs6.readFile(cwdFile, "utf8").catch(() => null);
|
|
4505
|
+
if (fromFile && fromFile.trim())
|
|
4506
|
+
return fromFile.trim();
|
|
4507
|
+
try {
|
|
4508
|
+
return decodeURIComponent(encoded);
|
|
4509
|
+
} catch {
|
|
4510
|
+
return encoded;
|
|
4511
|
+
}
|
|
4512
|
+
}
|
|
4513
|
+
async function listSessionDirs(root) {
|
|
4514
|
+
const out = [];
|
|
4515
|
+
const groups = await safeReaddir5(root);
|
|
4516
|
+
for (const group of groups) {
|
|
4517
|
+
if (group === "session_search.sqlite" || group.startsWith("."))
|
|
4518
|
+
continue;
|
|
4519
|
+
const groupDir = path6.join(root, group);
|
|
4520
|
+
const groupStat = await fs6.stat(groupDir).catch(() => null);
|
|
4521
|
+
if (!groupStat?.isDirectory())
|
|
4522
|
+
continue;
|
|
4523
|
+
const decodedCwd = await resolveEncodedCwd(groupDir, group);
|
|
4524
|
+
const entries2 = await safeReaddir5(groupDir);
|
|
4525
|
+
for (const entry of entries2) {
|
|
4526
|
+
if (entry === "prompt_history.jsonl" || entry.startsWith("."))
|
|
4527
|
+
continue;
|
|
4528
|
+
const dirPath = path6.join(groupDir, entry);
|
|
4529
|
+
const summaryPath = path6.join(dirPath, "summary.json");
|
|
4530
|
+
const updatesPath = path6.join(dirPath, "updates.jsonl");
|
|
4531
|
+
const signalsCandidate = path6.join(dirPath, "signals.json");
|
|
4532
|
+
const [summaryStat, updatesStat, signalsStat] = await Promise.all([
|
|
4533
|
+
fs6.stat(summaryPath).catch(() => null),
|
|
4534
|
+
fs6.stat(updatesPath).catch(() => null),
|
|
4535
|
+
fs6.stat(signalsCandidate).catch(() => null)
|
|
4536
|
+
]);
|
|
4537
|
+
if (!summaryStat?.isFile())
|
|
4538
|
+
continue;
|
|
4539
|
+
const mtimeMs = Math.max(summaryStat.mtimeMs, updatesStat?.mtimeMs ?? 0);
|
|
4540
|
+
const sizeBytes = (updatesStat?.size ?? 0) + summaryStat.size;
|
|
4541
|
+
out.push({
|
|
4542
|
+
dirPath,
|
|
4543
|
+
updatesPath,
|
|
4544
|
+
summaryPath,
|
|
4545
|
+
signalsPath: signalsStat?.isFile() ? signalsCandidate : null,
|
|
4546
|
+
sessionId: entry,
|
|
4547
|
+
groupName: group,
|
|
4548
|
+
decodedCwd,
|
|
4549
|
+
mtimeMs,
|
|
4550
|
+
sizeBytes
|
|
4551
|
+
});
|
|
4552
|
+
}
|
|
4553
|
+
}
|
|
4554
|
+
return out;
|
|
4555
|
+
}
|
|
4556
|
+
function emptyUsage4() {
|
|
4557
|
+
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
4558
|
+
}
|
|
4559
|
+
function previewOf4(text) {
|
|
4560
|
+
return text.replace(/\s+/g, " ").trim().slice(0, 200);
|
|
4561
|
+
}
|
|
4562
|
+
function truncate5(s, n) {
|
|
4563
|
+
return s.length <= n ? s : s.slice(0, n - 1) + "\u2026";
|
|
4564
|
+
}
|
|
4565
|
+
function textFromContent2(content) {
|
|
4566
|
+
if (!content)
|
|
4567
|
+
return "";
|
|
4568
|
+
if (typeof content === "string")
|
|
4569
|
+
return content;
|
|
4570
|
+
if (typeof content.text === "string")
|
|
4571
|
+
return content.text;
|
|
4572
|
+
return "";
|
|
4573
|
+
}
|
|
4574
|
+
function toolResultText(update2) {
|
|
4575
|
+
const items = update2.content;
|
|
4576
|
+
if (Array.isArray(items)) {
|
|
4577
|
+
const parts = [];
|
|
4578
|
+
for (const item of items) {
|
|
4579
|
+
if (!item || typeof item !== "object")
|
|
4580
|
+
continue;
|
|
4581
|
+
if (typeof item.text === "string" && item.text) {
|
|
4582
|
+
parts.push(item.text);
|
|
4583
|
+
continue;
|
|
4584
|
+
}
|
|
4585
|
+
const inner = item.content;
|
|
4586
|
+
if (typeof inner === "string" && inner)
|
|
4587
|
+
parts.push(inner);
|
|
4588
|
+
else if (inner && typeof inner === "object" && typeof inner.text === "string") {
|
|
4589
|
+
parts.push(inner.text);
|
|
4590
|
+
}
|
|
4591
|
+
}
|
|
4592
|
+
if (parts.length)
|
|
4593
|
+
return parts.join("\n");
|
|
4594
|
+
}
|
|
4595
|
+
const raw = update2.rawOutput;
|
|
4596
|
+
if (raw == null)
|
|
4597
|
+
return "";
|
|
4598
|
+
if (typeof raw === "string")
|
|
4599
|
+
return raw;
|
|
4600
|
+
if (typeof raw === "object") {
|
|
4601
|
+
const r = raw;
|
|
4602
|
+
if (typeof r.output_for_prompt === "string")
|
|
4603
|
+
return r.output_for_prompt;
|
|
4604
|
+
if (typeof r.summary_for_prompt === "string")
|
|
4605
|
+
return r.summary_for_prompt;
|
|
4606
|
+
if (r.Content && typeof r.Content === "object") {
|
|
4607
|
+
const c = r.Content;
|
|
4608
|
+
if (typeof c.content === "string")
|
|
4609
|
+
return c.content;
|
|
4610
|
+
}
|
|
4611
|
+
if (r.TodosUpdated && typeof r.TodosUpdated === "object") {
|
|
4612
|
+
const t = r.TodosUpdated;
|
|
4613
|
+
if (typeof t.summary_for_prompt === "string")
|
|
4614
|
+
return t.summary_for_prompt;
|
|
4615
|
+
}
|
|
4616
|
+
if (Array.isArray(r.stdout) || Array.isArray(r.output)) {
|
|
4617
|
+
try {
|
|
4618
|
+
return JSON.stringify({
|
|
4619
|
+
type: r.type,
|
|
4620
|
+
exit_code: r.exit_code,
|
|
4621
|
+
note: "binary/stdout omitted"
|
|
4622
|
+
});
|
|
4623
|
+
} catch {
|
|
4624
|
+
return "";
|
|
4625
|
+
}
|
|
4626
|
+
}
|
|
4627
|
+
try {
|
|
4628
|
+
return JSON.stringify(raw);
|
|
4629
|
+
} catch {
|
|
4630
|
+
return "";
|
|
4631
|
+
}
|
|
4632
|
+
}
|
|
4633
|
+
return String(raw);
|
|
4634
|
+
}
|
|
4635
|
+
function toolNameOf(update2) {
|
|
4636
|
+
const meta = update2._meta;
|
|
4637
|
+
if (meta && typeof meta === "object") {
|
|
4638
|
+
const xai = meta["x.ai/tool"];
|
|
4639
|
+
if (xai && typeof xai === "object") {
|
|
4640
|
+
const name = xai.name;
|
|
4641
|
+
if (typeof name === "string" && name)
|
|
4642
|
+
return name;
|
|
4643
|
+
}
|
|
4644
|
+
}
|
|
4645
|
+
if (typeof update2.title === "string" && update2.title) {
|
|
4646
|
+
if (!update2.title.includes(" ") && !update2.title.includes("`"))
|
|
4647
|
+
return update2.title;
|
|
4648
|
+
return update2.title;
|
|
4649
|
+
}
|
|
4650
|
+
return "tool";
|
|
4651
|
+
}
|
|
4652
|
+
function statusOf(update2) {
|
|
4653
|
+
const s = update2.status;
|
|
4654
|
+
if (typeof s === "string")
|
|
4655
|
+
return s;
|
|
4656
|
+
if (s && typeof s === "object" && typeof s.status === "string")
|
|
4657
|
+
return s.status;
|
|
4658
|
+
return void 0;
|
|
4659
|
+
}
|
|
4660
|
+
function lineTimestampIso(line) {
|
|
4661
|
+
const meta = line.params?._meta;
|
|
4662
|
+
const agentMs = meta && typeof meta.agentTimestampMs === "number" ? meta.agentTimestampMs : void 0;
|
|
4663
|
+
if (agentMs != null && Number.isFinite(agentMs)) {
|
|
4664
|
+
return new Date(agentMs).toISOString();
|
|
4665
|
+
}
|
|
4666
|
+
const ts = line.timestamp;
|
|
4667
|
+
if (typeof ts === "number" && Number.isFinite(ts)) {
|
|
4668
|
+
const ms = ts > 1e12 ? ts : ts * 1e3;
|
|
4669
|
+
return new Date(ms).toISOString();
|
|
4670
|
+
}
|
|
4671
|
+
return void 0;
|
|
4672
|
+
}
|
|
4673
|
+
function computeActiveSegments5(tsMs) {
|
|
4674
|
+
if (tsMs.length === 0)
|
|
4675
|
+
return [];
|
|
4676
|
+
const sorted = [...tsMs].sort((a, b) => a - b);
|
|
4677
|
+
const out = [];
|
|
4678
|
+
let segStart = sorted[0];
|
|
4679
|
+
let segEnd = sorted[0];
|
|
4680
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
4681
|
+
const t = sorted[i];
|
|
4682
|
+
if (t - segEnd > IDLE_GAP_MS4) {
|
|
4683
|
+
out.push({ startMs: segStart, endMs: segEnd });
|
|
4684
|
+
segStart = t;
|
|
4685
|
+
}
|
|
4686
|
+
segEnd = t;
|
|
4687
|
+
}
|
|
4688
|
+
out.push({ startMs: segStart, endMs: segEnd });
|
|
4689
|
+
return out;
|
|
4690
|
+
}
|
|
4691
|
+
async function parseSession3(dir) {
|
|
4692
|
+
const [summary, signals, updatesRaw] = await Promise.all([
|
|
4693
|
+
safeReadJson(dir.summaryPath),
|
|
4694
|
+
dir.signalsPath ? safeReadJson(dir.signalsPath) : Promise.resolve(null),
|
|
4695
|
+
fs6.readFile(dir.updatesPath, "utf8").catch(() => "")
|
|
4696
|
+
]);
|
|
4697
|
+
const sessionId = summary?.info?.id ?? dir.sessionId;
|
|
4698
|
+
const cwd = summary?.info?.cwd ?? dir.decodedCwd;
|
|
4699
|
+
let model = summary?.current_model_id ?? signals?.primaryModelId ?? signals?.modelsUsed?.[0];
|
|
4700
|
+
const events = [];
|
|
4701
|
+
const totalUsage = emptyUsage4();
|
|
4702
|
+
if (signals?.contextTokensUsed && signals.contextTokensUsed > 0) {
|
|
4703
|
+
totalUsage.input = signals.contextTokensUsed;
|
|
4704
|
+
}
|
|
4705
|
+
let firstTimestamp;
|
|
4706
|
+
let lastTimestamp;
|
|
4707
|
+
let toolCallCount = 0;
|
|
4708
|
+
let turnCount = 0;
|
|
4709
|
+
let firstUserPreview;
|
|
4710
|
+
let lastUserPreview;
|
|
4711
|
+
let lastAgentPreview;
|
|
4712
|
+
const tsMs = [];
|
|
4713
|
+
let idx = 0;
|
|
4714
|
+
const completedToolResults = /* @__PURE__ */ new Set();
|
|
4715
|
+
let maxTotalTokens = 0;
|
|
4716
|
+
function noteTs(ts, role) {
|
|
4717
|
+
if (!ts || role === "meta")
|
|
4718
|
+
return;
|
|
4719
|
+
if (!firstTimestamp)
|
|
4720
|
+
firstTimestamp = ts;
|
|
4721
|
+
lastTimestamp = ts;
|
|
4722
|
+
const ms = Date.parse(ts);
|
|
4723
|
+
if (Number.isFinite(ms))
|
|
4724
|
+
tsMs.push(ms);
|
|
4725
|
+
}
|
|
4726
|
+
function pushEvent(e) {
|
|
4727
|
+
events.push(e);
|
|
4728
|
+
noteTs(e.timestamp, e.role);
|
|
4729
|
+
}
|
|
4730
|
+
let buf = null;
|
|
4731
|
+
function flushBuf() {
|
|
4732
|
+
if (!buf)
|
|
4733
|
+
return;
|
|
4734
|
+
const text = buf.texts.join("");
|
|
4735
|
+
const preview = previewOf4(text);
|
|
4736
|
+
if (buf.kind === "user") {
|
|
4737
|
+
const isHidden = !text || isFrameworkInjectedUserInput(text);
|
|
4738
|
+
if (text && !isHidden) {
|
|
4739
|
+
if (!firstUserPreview)
|
|
4740
|
+
firstUserPreview = preview;
|
|
4741
|
+
lastUserPreview = preview;
|
|
4742
|
+
turnCount += 1;
|
|
4743
|
+
}
|
|
4744
|
+
if (text) {
|
|
4745
|
+
pushEvent({
|
|
4746
|
+
index: idx++,
|
|
4747
|
+
timestamp: buf.firstTs,
|
|
4748
|
+
role: "user",
|
|
4749
|
+
rawType: "grok/user_message",
|
|
4750
|
+
preview,
|
|
4751
|
+
blocks: [{ type: "text", text }],
|
|
4752
|
+
messageId: buf.promptId,
|
|
4753
|
+
raw: buf.raw.length === 1 ? buf.raw[0] : buf.raw
|
|
4754
|
+
});
|
|
4755
|
+
}
|
|
4756
|
+
} else if (buf.kind === "agent") {
|
|
4757
|
+
if (text)
|
|
4758
|
+
lastAgentPreview = preview;
|
|
4759
|
+
if (text) {
|
|
4760
|
+
pushEvent({
|
|
4761
|
+
index: idx++,
|
|
4762
|
+
timestamp: buf.firstTs,
|
|
4763
|
+
role: "agent",
|
|
4764
|
+
rawType: "grok/agent_message",
|
|
4765
|
+
preview,
|
|
4766
|
+
blocks: [{ type: "text", text }],
|
|
4767
|
+
messageId: buf.promptId,
|
|
4768
|
+
model: buf.model ?? model,
|
|
4769
|
+
raw: buf.raw.length === 1 ? buf.raw[0] : buf.raw
|
|
4770
|
+
});
|
|
4771
|
+
}
|
|
4772
|
+
} else if (buf.kind === "thought") {
|
|
4773
|
+
if (text) {
|
|
4774
|
+
pushEvent({
|
|
4775
|
+
index: idx++,
|
|
4776
|
+
timestamp: buf.firstTs,
|
|
4777
|
+
role: "agent-thinking",
|
|
4778
|
+
rawType: "grok/agent_thought",
|
|
4779
|
+
preview,
|
|
4780
|
+
blocks: [{ type: "thinking", thinking: text }],
|
|
4781
|
+
messageId: buf.promptId,
|
|
4782
|
+
model: buf.model ?? model,
|
|
4783
|
+
raw: buf.raw.length === 1 ? buf.raw[0] : buf.raw
|
|
4784
|
+
});
|
|
4785
|
+
}
|
|
4786
|
+
}
|
|
4787
|
+
buf = null;
|
|
4788
|
+
}
|
|
4789
|
+
function appendChunk(kind, text, ts, promptId, modelId, raw) {
|
|
4790
|
+
if (!text && kind === "user")
|
|
4791
|
+
return;
|
|
4792
|
+
if (buf && buf.kind !== kind)
|
|
4793
|
+
flushBuf();
|
|
4794
|
+
if (!buf) {
|
|
4795
|
+
buf = {
|
|
4796
|
+
kind,
|
|
4797
|
+
texts: [],
|
|
4798
|
+
firstTs: ts,
|
|
4799
|
+
lastTs: ts,
|
|
4800
|
+
model: modelId,
|
|
4801
|
+
promptId,
|
|
4802
|
+
raw: []
|
|
4803
|
+
};
|
|
4804
|
+
}
|
|
4805
|
+
if (text)
|
|
4806
|
+
buf.texts.push(text);
|
|
4807
|
+
buf.lastTs = ts ?? buf.lastTs;
|
|
4808
|
+
if (modelId)
|
|
4809
|
+
buf.model = modelId;
|
|
4810
|
+
if (promptId)
|
|
4811
|
+
buf.promptId = promptId;
|
|
4812
|
+
buf.raw.push(raw);
|
|
4813
|
+
}
|
|
4814
|
+
const lines = updatesRaw.split("\n");
|
|
4815
|
+
for (const line of lines) {
|
|
4816
|
+
const trimmed = line.trim();
|
|
4817
|
+
if (!trimmed)
|
|
4818
|
+
continue;
|
|
4819
|
+
let obj;
|
|
4820
|
+
try {
|
|
4821
|
+
obj = JSON.parse(trimmed);
|
|
4822
|
+
} catch {
|
|
4823
|
+
continue;
|
|
4824
|
+
}
|
|
4825
|
+
const update2 = obj.params?.update;
|
|
4826
|
+
if (!update2 || typeof update2 !== "object")
|
|
4827
|
+
continue;
|
|
4828
|
+
const st = update2.sessionUpdate;
|
|
4829
|
+
if (!st)
|
|
4830
|
+
continue;
|
|
4831
|
+
const ts = lineTimestampIso(obj);
|
|
4832
|
+
const lineMeta = obj.params?._meta ?? {};
|
|
4833
|
+
const updateMeta = update2._meta ?? {};
|
|
4834
|
+
const promptId = typeof lineMeta.promptId === "string" && lineMeta.promptId || typeof updateMeta.promptId === "string" && updateMeta.promptId || void 0;
|
|
4835
|
+
const modelId = typeof updateMeta.modelId === "string" && updateMeta.modelId || typeof lineMeta.modelId === "string" && lineMeta.modelId || void 0;
|
|
4836
|
+
if (modelId)
|
|
4837
|
+
model = modelId;
|
|
4838
|
+
const totalTok = lineMeta.totalTokens;
|
|
4839
|
+
if (typeof totalTok === "number" && totalTok > maxTotalTokens) {
|
|
4840
|
+
maxTotalTokens = totalTok;
|
|
4841
|
+
}
|
|
4842
|
+
if (st === "user_message_chunk") {
|
|
4843
|
+
const text = textFromContent2(update2.content);
|
|
4844
|
+
appendChunk("user", text, ts, promptId, modelId, obj);
|
|
4845
|
+
continue;
|
|
4846
|
+
}
|
|
4847
|
+
if (st === "agent_message_chunk") {
|
|
4848
|
+
const text = textFromContent2(update2.content);
|
|
4849
|
+
appendChunk("agent", text, ts, promptId, modelId, obj);
|
|
4850
|
+
continue;
|
|
4851
|
+
}
|
|
4852
|
+
if (st === "agent_thought_chunk") {
|
|
4853
|
+
const text = textFromContent2(update2.content);
|
|
4854
|
+
appendChunk("thought", text, ts, promptId, modelId, obj);
|
|
4855
|
+
continue;
|
|
4856
|
+
}
|
|
4857
|
+
flushBuf();
|
|
4858
|
+
if (st === "tool_call") {
|
|
4859
|
+
const toolCallId = typeof update2.toolCallId === "string" ? update2.toolCallId : `grok-${idx}`;
|
|
4860
|
+
const name = toolNameOf(update2);
|
|
4861
|
+
const input = update2.rawInput ?? {};
|
|
4862
|
+
const argsStr = input ? JSON.stringify(input) : "";
|
|
4863
|
+
toolCallCount += 1;
|
|
4864
|
+
pushEvent({
|
|
4865
|
+
index: idx++,
|
|
4866
|
+
timestamp: ts,
|
|
4867
|
+
role: "tool-call",
|
|
4868
|
+
rawType: "grok/tool_call",
|
|
4869
|
+
preview: `${name}(${truncate5(argsStr, 80)})`,
|
|
4870
|
+
blocks: [{ type: "tool_use", id: toolCallId, name, input }],
|
|
4871
|
+
toolName: name,
|
|
4872
|
+
toolUseId: toolCallId,
|
|
4873
|
+
model,
|
|
4874
|
+
raw: obj
|
|
4875
|
+
});
|
|
4876
|
+
continue;
|
|
4877
|
+
}
|
|
4878
|
+
if (st === "tool_call_update") {
|
|
4879
|
+
const status2 = statusOf(update2);
|
|
4880
|
+
if (status2 !== "completed" && status2 !== "failed" && status2 !== "error" && status2 !== "cancelled") {
|
|
4881
|
+
continue;
|
|
4882
|
+
}
|
|
4883
|
+
const toolCallId = typeof update2.toolCallId === "string" ? update2.toolCallId : "";
|
|
4884
|
+
if (toolCallId && completedToolResults.has(toolCallId))
|
|
4885
|
+
continue;
|
|
4886
|
+
if (toolCallId)
|
|
4887
|
+
completedToolResults.add(toolCallId);
|
|
4888
|
+
const resultText = toolResultText(update2);
|
|
4889
|
+
const isError = status2 === "failed" || status2 === "error" || status2 === "cancelled";
|
|
4890
|
+
pushEvent({
|
|
4891
|
+
index: idx++,
|
|
4892
|
+
timestamp: ts,
|
|
4893
|
+
role: "tool-result",
|
|
4894
|
+
rawType: "grok/tool_result",
|
|
4895
|
+
preview: previewOf4(resultText),
|
|
4896
|
+
blocks: [
|
|
4897
|
+
{
|
|
4898
|
+
type: "tool_result",
|
|
4899
|
+
tool_use_id: toolCallId,
|
|
4900
|
+
content: resultText,
|
|
4901
|
+
is_error: isError || void 0
|
|
4902
|
+
}
|
|
4903
|
+
],
|
|
4904
|
+
toolUseId: toolCallId || void 0,
|
|
4905
|
+
toolResult: resultText,
|
|
4906
|
+
raw: obj
|
|
4907
|
+
});
|
|
4908
|
+
continue;
|
|
4909
|
+
}
|
|
4910
|
+
if (st === "turn_completed") {
|
|
4911
|
+
continue;
|
|
4912
|
+
}
|
|
4913
|
+
}
|
|
4914
|
+
flushBuf();
|
|
4915
|
+
if (totalUsage.input === 0 && maxTotalTokens > 0) {
|
|
4916
|
+
totalUsage.input = maxTotalTokens;
|
|
4917
|
+
}
|
|
4918
|
+
if (!firstTimestamp && summary?.created_at)
|
|
4919
|
+
firstTimestamp = summary.created_at;
|
|
4920
|
+
if (!lastTimestamp) {
|
|
4921
|
+
lastTimestamp = summary?.last_active_at ?? summary?.updated_at ?? firstTimestamp;
|
|
4922
|
+
}
|
|
4923
|
+
if (signals?.toolCallCount != null && signals.toolCallCount > toolCallCount) {
|
|
4924
|
+
toolCallCount = signals.toolCallCount;
|
|
4925
|
+
}
|
|
4926
|
+
if (signals?.turnCount != null && signals.turnCount > turnCount) {
|
|
4927
|
+
turnCount = signals.turnCount;
|
|
4928
|
+
}
|
|
4929
|
+
const startMs = firstTimestamp ? Date.parse(firstTimestamp) : void 0;
|
|
4930
|
+
if (startMs !== void 0 && Number.isFinite(startMs)) {
|
|
4931
|
+
let prevMs;
|
|
4932
|
+
for (const ev of events) {
|
|
4933
|
+
if (!ev.timestamp)
|
|
4934
|
+
continue;
|
|
4935
|
+
const ms = Date.parse(ev.timestamp);
|
|
4936
|
+
if (!Number.isFinite(ms))
|
|
4937
|
+
continue;
|
|
4938
|
+
ev.tOffsetMs = Math.max(0, ms - startMs);
|
|
4939
|
+
if (prevMs !== void 0)
|
|
4940
|
+
ev.gapMs = Math.max(0, ms - prevMs);
|
|
4941
|
+
prevMs = ms;
|
|
4942
|
+
}
|
|
4943
|
+
}
|
|
4944
|
+
const activeSegments = computeActiveSegments5(tsMs);
|
|
4945
|
+
const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
|
|
4946
|
+
const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
|
|
4947
|
+
const project = cwd ? resolveProjectIdentity(cwd) : void 0;
|
|
4948
|
+
const projectName = project?.projectName ?? cwd ?? dir.decodedCwd;
|
|
4949
|
+
const projectDir = dir.groupName || (cwd ? encodeURIComponent(cwd) : "(unknown)");
|
|
4950
|
+
if (!firstUserPreview) {
|
|
4951
|
+
const title = summary?.generated_title || summary?.session_summary;
|
|
4952
|
+
if (title)
|
|
4953
|
+
firstUserPreview = previewOf4(title);
|
|
4954
|
+
}
|
|
4955
|
+
const spawnedAgentCount = await countSubagentChildren(dir.dirPath);
|
|
4956
|
+
const meta = {
|
|
4957
|
+
agent: "grok",
|
|
4958
|
+
id: sessionId,
|
|
4959
|
+
filePath: dir.updatesPath,
|
|
4960
|
+
projectName,
|
|
4961
|
+
worktreeName: project?.worktreeName,
|
|
4962
|
+
repoName: project?.repoName,
|
|
4963
|
+
projectDir,
|
|
4964
|
+
sessionId,
|
|
4965
|
+
firstTimestamp,
|
|
4966
|
+
lastTimestamp,
|
|
4967
|
+
lastActivityMs: lastTimestamp ? Date.parse(lastTimestamp) : void 0,
|
|
4968
|
+
durationMs: durationMs && Number.isFinite(durationMs) ? durationMs : void 0,
|
|
4969
|
+
eventCount: events.length,
|
|
4970
|
+
model,
|
|
4971
|
+
cwd,
|
|
4972
|
+
gitBranch: summary?.head_branch,
|
|
4973
|
+
agentName: summary?.agent_name,
|
|
4974
|
+
totalUsage,
|
|
4975
|
+
status: "idle",
|
|
4976
|
+
firstUserPreview,
|
|
4977
|
+
lastUserPreview,
|
|
4978
|
+
lastAgentPreview,
|
|
4979
|
+
toolCallCount,
|
|
4980
|
+
turnCount,
|
|
4981
|
+
linesAdded: signals?.agentLinesAdded,
|
|
4982
|
+
linesRemoved: signals?.agentLinesRemoved,
|
|
4983
|
+
airTimeMs,
|
|
4984
|
+
activeSegments,
|
|
4985
|
+
...spawnedAgentCount > 0 ? { spawnedAgentCount } : {}
|
|
4986
|
+
};
|
|
4987
|
+
return { meta, events, sessionKind: summary?.session_kind };
|
|
4988
|
+
}
|
|
4989
|
+
async function countSubagentChildren(dirPath) {
|
|
4990
|
+
const subRoot = path6.join(dirPath, "subagents");
|
|
4991
|
+
const entries2 = await safeReaddir5(subRoot);
|
|
4992
|
+
let n = 0;
|
|
4993
|
+
for (const e of entries2) {
|
|
4994
|
+
const st = await fs6.stat(path6.join(subRoot, e)).catch(() => null);
|
|
4995
|
+
if (st?.isDirectory())
|
|
4996
|
+
n += 1;
|
|
4997
|
+
}
|
|
4998
|
+
return n;
|
|
4999
|
+
}
|
|
5000
|
+
async function loadGrokSubagents(parentDir, parentStartMs) {
|
|
5001
|
+
const subRoot = path6.join(parentDir.dirPath, "subagents");
|
|
5002
|
+
const entries2 = await safeReaddir5(subRoot);
|
|
5003
|
+
const groupDir = path6.dirname(parentDir.dirPath);
|
|
5004
|
+
const runs2 = [];
|
|
5005
|
+
for (const entry of entries2) {
|
|
5006
|
+
const metaPath = path6.join(subRoot, entry, "meta.json");
|
|
5007
|
+
const meta = await safeReadJson(metaPath);
|
|
5008
|
+
if (!meta)
|
|
5009
|
+
continue;
|
|
5010
|
+
const childId = meta.child_session_id ?? meta.subagent_id ?? entry;
|
|
5011
|
+
const childDir = path6.join(groupDir, childId);
|
|
5012
|
+
const [childSummary, childSignals] = await Promise.all([
|
|
5013
|
+
safeReadJson(path6.join(childDir, "summary.json")),
|
|
5014
|
+
safeReadJson(path6.join(childDir, "signals.json"))
|
|
5015
|
+
]);
|
|
5016
|
+
const startMs = childSummary?.created_at ? Date.parse(childSummary.created_at) : void 0;
|
|
5017
|
+
const endIso = childSummary?.last_active_at ?? childSummary?.updated_at;
|
|
5018
|
+
const endMs = endIso ? Date.parse(endIso) : void 0;
|
|
5019
|
+
const startOk = startMs !== void 0 && Number.isFinite(startMs) ? startMs : void 0;
|
|
5020
|
+
const endOk = endMs !== void 0 && Number.isFinite(endMs) ? endMs : void 0;
|
|
5021
|
+
const usage2 = emptyUsage4();
|
|
5022
|
+
if (childSignals?.contextTokensUsed)
|
|
5023
|
+
usage2.input = childSignals.contextTokensUsed;
|
|
5024
|
+
runs2.push({
|
|
5025
|
+
agentId: childId,
|
|
5026
|
+
agentType: meta.subagent_type ?? childSummary?.agent_name ?? "subagent",
|
|
5027
|
+
description: meta.description && meta.description.trim() || childSummary?.generated_title || childSummary?.session_summary || childId,
|
|
5028
|
+
startMs: startOk,
|
|
5029
|
+
endMs: endOk,
|
|
5030
|
+
durationMs: startOk !== void 0 && endOk !== void 0 ? Math.max(0, endOk - startOk) : void 0,
|
|
5031
|
+
startTOffsetMs: parentStartMs !== void 0 && startOk !== void 0 ? Math.max(0, startOk - parentStartMs) : void 0,
|
|
5032
|
+
endTOffsetMs: parentStartMs !== void 0 && endOk !== void 0 ? Math.max(0, endOk - parentStartMs) : void 0,
|
|
5033
|
+
eventCount: childSummary?.num_messages ?? childSummary?.num_chat_messages ?? 0,
|
|
5034
|
+
totalUsage: usage2,
|
|
5035
|
+
prompt: typeof meta.prompt === "string" ? meta.prompt : void 0,
|
|
5036
|
+
model: childSummary?.current_model_id ?? childSignals?.primaryModelId,
|
|
5037
|
+
toolCallCount: childSignals?.toolCallCount
|
|
5038
|
+
});
|
|
5039
|
+
}
|
|
5040
|
+
runs2.sort((a, b) => (a.startMs ?? 0) - (b.startMs ?? 0));
|
|
5041
|
+
return runs2;
|
|
5042
|
+
}
|
|
5043
|
+
function clearGrokCaches() {
|
|
5044
|
+
metaCache6.clear();
|
|
5045
|
+
detailCache6.clear();
|
|
5046
|
+
}
|
|
5047
|
+
async function listGrokSessions(opts = {}) {
|
|
5048
|
+
const root = opts.root ?? resolveDefaultGrokRoot();
|
|
5049
|
+
const dirs = await listSessionDirs(root);
|
|
5050
|
+
const out = [];
|
|
5051
|
+
for (const dir of dirs) {
|
|
5052
|
+
const summaryPeek = await safeReadJson(dir.summaryPath);
|
|
5053
|
+
if (summaryPeek?.session_kind === "subagent")
|
|
5054
|
+
continue;
|
|
5055
|
+
const cached = metaCache6.get(dir.dirPath);
|
|
5056
|
+
if (cached && cached.mtimeMs === dir.mtimeMs && cached.sizeBytes === dir.sizeBytes) {
|
|
5057
|
+
out.push(cached.meta);
|
|
5058
|
+
continue;
|
|
5059
|
+
}
|
|
5060
|
+
try {
|
|
5061
|
+
const { meta, sessionKind } = await parseSession3(dir);
|
|
5062
|
+
if (sessionKind === "subagent")
|
|
5063
|
+
continue;
|
|
5064
|
+
metaCache6.set(dir.dirPath, {
|
|
5065
|
+
meta,
|
|
5066
|
+
mtimeMs: dir.mtimeMs,
|
|
5067
|
+
sizeBytes: dir.sizeBytes
|
|
5068
|
+
});
|
|
5069
|
+
out.push(meta);
|
|
5070
|
+
} catch {
|
|
5071
|
+
}
|
|
5072
|
+
}
|
|
5073
|
+
out.sort((a, b) => (b.firstTimestamp ?? "").localeCompare(a.firstTimestamp ?? ""));
|
|
5074
|
+
if (opts.limit !== void 0)
|
|
5075
|
+
return out.slice(0, opts.limit);
|
|
5076
|
+
return out;
|
|
5077
|
+
}
|
|
5078
|
+
async function getGrokSession(id, opts = {}) {
|
|
5079
|
+
const root = opts.root ?? resolveDefaultGrokRoot();
|
|
5080
|
+
const dirs = await listSessionDirs(root);
|
|
5081
|
+
const chosen = dirs.find((d) => d.sessionId === id);
|
|
5082
|
+
if (!chosen) {
|
|
5083
|
+
for (const dir of dirs) {
|
|
5084
|
+
try {
|
|
5085
|
+
const { meta: meta2, events: events2 } = await parseSession3(dir);
|
|
5086
|
+
if (meta2.id === id) {
|
|
5087
|
+
const detail2 = { ...meta2, events: events2 };
|
|
5088
|
+
detailCache6.set(dir.dirPath, {
|
|
5089
|
+
detail: detail2,
|
|
5090
|
+
mtimeMs: dir.mtimeMs,
|
|
5091
|
+
sizeBytes: dir.sizeBytes
|
|
5092
|
+
});
|
|
5093
|
+
return detail2;
|
|
5094
|
+
}
|
|
5095
|
+
} catch {
|
|
5096
|
+
}
|
|
5097
|
+
}
|
|
5098
|
+
return null;
|
|
5099
|
+
}
|
|
5100
|
+
const cached = detailCache6.get(chosen.dirPath);
|
|
5101
|
+
if (cached && cached.mtimeMs === chosen.mtimeMs && cached.sizeBytes === chosen.sizeBytes) {
|
|
5102
|
+
return cached.detail;
|
|
5103
|
+
}
|
|
5104
|
+
const { meta, events } = await parseSession3(chosen);
|
|
5105
|
+
const parentStartMs = meta.firstTimestamp ? Date.parse(meta.firstTimestamp) : void 0;
|
|
5106
|
+
const subagents = await loadGrokSubagents(chosen, parentStartMs !== void 0 && Number.isFinite(parentStartMs) ? parentStartMs : void 0);
|
|
5107
|
+
const detail = {
|
|
5108
|
+
...meta,
|
|
5109
|
+
events,
|
|
5110
|
+
...subagents.length > 0 ? { subagents, spawnedAgentCount: subagents.length } : {}
|
|
5111
|
+
};
|
|
5112
|
+
detailCache6.set(chosen.dirPath, {
|
|
5113
|
+
detail,
|
|
5114
|
+
mtimeMs: chosen.mtimeMs,
|
|
5115
|
+
sizeBytes: chosen.sizeBytes
|
|
5116
|
+
});
|
|
5117
|
+
metaCache6.set(chosen.dirPath, {
|
|
5118
|
+
meta: {
|
|
5119
|
+
...meta,
|
|
5120
|
+
...subagents.length > 0 ? { spawnedAgentCount: subagents.length } : {}
|
|
5121
|
+
},
|
|
5122
|
+
mtimeMs: chosen.mtimeMs,
|
|
5123
|
+
sizeBytes: chosen.sizeBytes
|
|
5124
|
+
});
|
|
5125
|
+
return detail;
|
|
5126
|
+
}
|
|
5127
|
+
function grokSessionLocalDay(meta) {
|
|
5128
|
+
if (!meta.firstTimestamp)
|
|
5129
|
+
return void 0;
|
|
5130
|
+
const ms = Date.parse(meta.firstTimestamp);
|
|
5131
|
+
return Number.isFinite(ms) ? toLocalDay(ms) : void 0;
|
|
5132
|
+
}
|
|
5133
|
+
var DEFAULT_GROK_ROOT, IDLE_GAP_MS4, metaCache6, detailCache6;
|
|
5134
|
+
var init_grok = __esm({
|
|
5135
|
+
"../parser/dist/grok.js"() {
|
|
5136
|
+
"use strict";
|
|
5137
|
+
init_analytics();
|
|
5138
|
+
init_git_project();
|
|
5139
|
+
init_user_input();
|
|
5140
|
+
DEFAULT_GROK_ROOT = path6.join(os6.homedir(), ".grok", "sessions");
|
|
5141
|
+
IDLE_GAP_MS4 = 3 * 60 * 1e3;
|
|
5142
|
+
metaCache6 = /* @__PURE__ */ new Map();
|
|
5143
|
+
detailCache6 = /* @__PURE__ */ new Map();
|
|
5144
|
+
}
|
|
5145
|
+
});
|
|
5146
|
+
|
|
4472
5147
|
// ../parser/dist/team-config.js
|
|
4473
5148
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, unlinkSync as unlinkSync2, mkdirSync as mkdirSync2, renameSync } from "node:fs";
|
|
4474
5149
|
import { join as join2 } from "node:path";
|
|
@@ -4528,6 +5203,7 @@ __export(fs_exports, {
|
|
|
4528
5203
|
DEFAULT_CODEX_ROOT: () => DEFAULT_CODEX_ROOT,
|
|
4529
5204
|
DEFAULT_COWORK_ROOT: () => DEFAULT_COWORK_ROOT,
|
|
4530
5205
|
DEFAULT_GEMINI_ROOT: () => DEFAULT_GEMINI_ROOT,
|
|
5206
|
+
DEFAULT_GROK_ROOT: () => DEFAULT_GROK_ROOT,
|
|
4531
5207
|
DEFAULT_ROOT: () => DEFAULT_ROOT,
|
|
4532
5208
|
RICH_ROLLUP_SCHEMA_VERSION: () => RICH_ROLLUP_SCHEMA_VERSION,
|
|
4533
5209
|
agentSources: () => agentSources,
|
|
@@ -4538,6 +5214,7 @@ __export(fs_exports, {
|
|
|
4538
5214
|
cclensHome: () => cclensHome,
|
|
4539
5215
|
cclensPath: () => cclensPath,
|
|
4540
5216
|
clearCaches: () => clearCaches,
|
|
5217
|
+
clearGrokCaches: () => clearGrokCaches,
|
|
4541
5218
|
clearTeamConfig: () => clearTeamConfig,
|
|
4542
5219
|
codexSessionLocalDay: () => codexSessionLocalDay,
|
|
4543
5220
|
decodeProjectName: () => decodeProjectName,
|
|
@@ -4549,8 +5226,10 @@ __export(fs_exports, {
|
|
|
4549
5226
|
getCodexSession: () => getCodexSession,
|
|
4550
5227
|
getCoworkSession: () => getCoworkSession,
|
|
4551
5228
|
getGeminiSession: () => getGeminiSession,
|
|
5229
|
+
getGrokSession: () => getGrokSession,
|
|
4552
5230
|
getLatestCodexUsage: () => getLatestCodexUsage,
|
|
4553
5231
|
getSession: () => getSession,
|
|
5232
|
+
grokSessionLocalDay: () => grokSessionLocalDay,
|
|
4554
5233
|
invalidateFile: () => invalidateFile,
|
|
4555
5234
|
isFleetlensRuntimeDir: () => isFleetlensRuntimeDir,
|
|
4556
5235
|
listAllSessions: () => listAllSessions,
|
|
@@ -4558,6 +5237,7 @@ __export(fs_exports, {
|
|
|
4558
5237
|
listCodexSessions: () => listCodexSessions,
|
|
4559
5238
|
listCoworkSessions: () => listCoworkSessions,
|
|
4560
5239
|
listGeminiSessions: () => listGeminiSessions,
|
|
5240
|
+
listGrokSessions: () => listGrokSessions,
|
|
4561
5241
|
listProjects: () => listProjects,
|
|
4562
5242
|
listSessions: () => listSessions,
|
|
4563
5243
|
loadCalibrationCurve: () => loadCalibrationCurve,
|
|
@@ -4570,20 +5250,21 @@ __export(fs_exports, {
|
|
|
4570
5250
|
readGitFolder: () => readGitFolder,
|
|
4571
5251
|
readJsonlFile: () => readJsonlFile,
|
|
4572
5252
|
readTeamConfig: () => readTeamConfig,
|
|
5253
|
+
resolveDefaultGrokRoot: () => resolveDefaultGrokRoot,
|
|
4573
5254
|
resolveProjectIdentity: () => resolveProjectIdentity,
|
|
4574
5255
|
sessionIdFromFileName: () => sessionIdFromFileName,
|
|
4575
5256
|
shouldSyncProject: () => shouldSyncProject,
|
|
4576
5257
|
walkJsonlFiles: () => walkJsonlFiles,
|
|
4577
5258
|
writeTeamConfig: () => writeTeamConfig
|
|
4578
5259
|
});
|
|
4579
|
-
import { promises as
|
|
4580
|
-
import
|
|
4581
|
-
import
|
|
5260
|
+
import { promises as fs7, existsSync as existsSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync3, appendFileSync, mkdirSync as mkdirSync3 } from "node:fs";
|
|
5261
|
+
import os7 from "node:os";
|
|
5262
|
+
import path7 from "node:path";
|
|
4582
5263
|
function cclensHome() {
|
|
4583
|
-
return process.env.CCLENS_HOME ||
|
|
5264
|
+
return process.env.CCLENS_HOME || path7.join(os7.homedir(), ".cclens");
|
|
4584
5265
|
}
|
|
4585
5266
|
function cclensPath(...parts) {
|
|
4586
|
-
return
|
|
5267
|
+
return path7.join(cclensHome(), ...parts);
|
|
4587
5268
|
}
|
|
4588
5269
|
function cacheStats() {
|
|
4589
5270
|
return claudeCodeCacheStats();
|
|
@@ -4594,6 +5275,7 @@ function clearCaches() {
|
|
|
4594
5275
|
clearGeminiCaches();
|
|
4595
5276
|
clearAntigravityCaches();
|
|
4596
5277
|
clearCoworkCaches();
|
|
5278
|
+
clearGrokCaches();
|
|
4597
5279
|
}
|
|
4598
5280
|
function invalidateFile(fullPath) {
|
|
4599
5281
|
invalidateClaudeCodeFile(fullPath);
|
|
@@ -4624,7 +5306,7 @@ function usageLogPath() {
|
|
|
4624
5306
|
}
|
|
4625
5307
|
function appendUsageSnapshot(snapshot) {
|
|
4626
5308
|
const p = usageLogPath();
|
|
4627
|
-
mkdirSync3(
|
|
5309
|
+
mkdirSync3(path7.dirname(p), { recursive: true });
|
|
4628
5310
|
appendFileSync(p, JSON.stringify(snapshot) + "\n", "utf8");
|
|
4629
5311
|
}
|
|
4630
5312
|
function pruneUsageAgent(agent) {
|
|
@@ -4640,13 +5322,13 @@ function pruneUsageAgent(agent) {
|
|
|
4640
5322
|
return true;
|
|
4641
5323
|
}
|
|
4642
5324
|
});
|
|
4643
|
-
mkdirSync3(
|
|
5325
|
+
mkdirSync3(path7.dirname(p), { recursive: true });
|
|
4644
5326
|
writeFileSync3(p, kept.join("\n") + (kept.length ? "\n" : ""), "utf8");
|
|
4645
5327
|
}
|
|
4646
5328
|
async function loadUsageByDay(start2, end) {
|
|
4647
5329
|
let raw;
|
|
4648
5330
|
try {
|
|
4649
|
-
raw = await
|
|
5331
|
+
raw = await fs7.readFile(usageLogPath(), "utf8");
|
|
4650
5332
|
} catch {
|
|
4651
5333
|
return { by_day: [] };
|
|
4652
5334
|
}
|
|
@@ -4691,7 +5373,7 @@ async function loadUsageByDay(start2, end) {
|
|
|
4691
5373
|
async function loadCalibrationSnapshots() {
|
|
4692
5374
|
let raw;
|
|
4693
5375
|
try {
|
|
4694
|
-
raw = await
|
|
5376
|
+
raw = await fs7.readFile(usageLogPath(), "utf8");
|
|
4695
5377
|
} catch {
|
|
4696
5378
|
return [];
|
|
4697
5379
|
}
|
|
@@ -4855,7 +5537,7 @@ async function loadCalibrationCurve(tier = "pro-max-20x", root = DEFAULT_ROOT, g
|
|
|
4855
5537
|
]);
|
|
4856
5538
|
return buildCalibrationCurve(events, snapshots, tier, granularityMin);
|
|
4857
5539
|
}
|
|
4858
|
-
var codexSource, geminiSource, antigravitySource, coworkSource, agentSources;
|
|
5540
|
+
var codexSource, geminiSource, antigravitySource, coworkSource, grokSource, agentSources;
|
|
4859
5541
|
var init_fs = __esm({
|
|
4860
5542
|
"../parser/dist/fs.js"() {
|
|
4861
5543
|
"use strict";
|
|
@@ -4867,12 +5549,14 @@ var init_fs = __esm({
|
|
|
4867
5549
|
init_gemini();
|
|
4868
5550
|
init_antigravity();
|
|
4869
5551
|
init_cowork();
|
|
5552
|
+
init_grok();
|
|
4870
5553
|
init_claude_code();
|
|
4871
5554
|
init_git_project();
|
|
4872
5555
|
init_codex();
|
|
4873
5556
|
init_gemini();
|
|
4874
5557
|
init_antigravity();
|
|
4875
5558
|
init_cowork();
|
|
5559
|
+
init_grok();
|
|
4876
5560
|
init_team_config();
|
|
4877
5561
|
init_team_wire();
|
|
4878
5562
|
codexSource = {
|
|
@@ -4926,12 +5610,24 @@ var init_fs = __esm({
|
|
|
4926
5610
|
return getCoworkSession(id);
|
|
4927
5611
|
}
|
|
4928
5612
|
};
|
|
5613
|
+
grokSource = {
|
|
5614
|
+
...GROK_METADATA,
|
|
5615
|
+
// Display default; list/get re-resolve GROK_HOME at call time internally.
|
|
5616
|
+
defaultRoot: DEFAULT_GROK_ROOT,
|
|
5617
|
+
async listSessions(opts) {
|
|
5618
|
+
return listGrokSessions(opts);
|
|
5619
|
+
},
|
|
5620
|
+
async getSession(id, opts) {
|
|
5621
|
+
return getGrokSession(id, opts);
|
|
5622
|
+
}
|
|
5623
|
+
};
|
|
4929
5624
|
agentSources = [
|
|
4930
5625
|
claudeCodeSource,
|
|
4931
5626
|
codexSource,
|
|
4932
5627
|
geminiSource,
|
|
4933
5628
|
antigravitySource,
|
|
4934
|
-
coworkSource
|
|
5629
|
+
coworkSource,
|
|
5630
|
+
grokSource
|
|
4935
5631
|
];
|
|
4936
5632
|
}
|
|
4937
5633
|
});
|
|
@@ -4967,9 +5663,9 @@ function onDiskVersion() {
|
|
|
4967
5663
|
try {
|
|
4968
5664
|
const here = dirname3(fileURLToPath(import.meta.url));
|
|
4969
5665
|
const pkg = JSON.parse(readFileSync5(join3(here, "..", "package.json"), "utf8"));
|
|
4970
|
-
return pkg.version ?? "0.16.
|
|
5666
|
+
return pkg.version ?? "0.16.1";
|
|
4971
5667
|
} catch {
|
|
4972
|
-
return "0.16.
|
|
5668
|
+
return "0.16.1";
|
|
4973
5669
|
}
|
|
4974
5670
|
}
|
|
4975
5671
|
function getServerStatus() {
|
|
@@ -4981,7 +5677,7 @@ function getServerStatus() {
|
|
|
4981
5677
|
return { running: false };
|
|
4982
5678
|
}
|
|
4983
5679
|
function isServerStale(status2) {
|
|
4984
|
-
return status2.running === true && status2.version !== "0.16.
|
|
5680
|
+
return status2.running === true && status2.version !== "0.16.1";
|
|
4985
5681
|
}
|
|
4986
5682
|
async function ensureCurrentServer(opts = {}) {
|
|
4987
5683
|
const status2 = getServerStatus();
|
|
@@ -5420,9 +6116,9 @@ Installed: ${PACKAGE_NAME}@${verify.installedVersion} at ${verify.installedPath
|
|
|
5420
6116
|
console.warn(
|
|
5421
6117
|
` \u2022 reinstall in the correct Node env: 'npm install -g ${PACKAGE_NAME}@latest'`
|
|
5422
6118
|
);
|
|
5423
|
-
} else if (verify.installedVersion !== "0.16.
|
|
6119
|
+
} else if (verify.installedVersion !== "0.16.1") {
|
|
5424
6120
|
console.log(
|
|
5425
|
-
` \u2192 This process is still running ${"0.16.
|
|
6121
|
+
` \u2192 This process is still running ${"0.16.1"}. Next invocation will use ${verify.installedVersion}.`
|
|
5426
6122
|
);
|
|
5427
6123
|
}
|
|
5428
6124
|
}
|
|
@@ -5457,14 +6153,14 @@ async function getUpdateAvailability() {
|
|
|
5457
6153
|
if (isDevMode()) return null;
|
|
5458
6154
|
const latest = await fetchLatestVersion();
|
|
5459
6155
|
if (latest === null) return {
|
|
5460
|
-
current: "0.16.
|
|
6156
|
+
current: "0.16.1",
|
|
5461
6157
|
latest: null,
|
|
5462
6158
|
updateAvailable: false
|
|
5463
6159
|
};
|
|
5464
6160
|
return {
|
|
5465
|
-
current: "0.16.
|
|
6161
|
+
current: "0.16.1",
|
|
5466
6162
|
latest,
|
|
5467
|
-
updateAvailable: shouldUpdate("0.16.
|
|
6163
|
+
updateAvailable: shouldUpdate("0.16.1", latest)
|
|
5468
6164
|
};
|
|
5469
6165
|
}
|
|
5470
6166
|
async function checkForUpdate() {
|
|
@@ -5554,7 +6250,7 @@ async function restartServices(state) {
|
|
|
5554
6250
|
}
|
|
5555
6251
|
async function forceUpdate() {
|
|
5556
6252
|
const latest = await fetchLatestVersion();
|
|
5557
|
-
const current = "0.16.
|
|
6253
|
+
const current = "0.16.1";
|
|
5558
6254
|
if (latest === null) {
|
|
5559
6255
|
console.error("Could not reach npm registry. Check your network.");
|
|
5560
6256
|
process.exit(1);
|
|
@@ -5967,7 +6663,7 @@ async function status() {
|
|
|
5967
6663
|
console.log(`Server: running on ${url} (PID ${server.pid}, v${ver})`);
|
|
5968
6664
|
if (isServerStale(server)) {
|
|
5969
6665
|
console.log(
|
|
5970
|
-
` \u26A0 serving stale ${ver} (CLI is ${"0.16.
|
|
6666
|
+
` \u26A0 serving stale ${ver} (CLI is ${"0.16.1"}) \u2014 run 'fleetlens start' to restart on the current version`
|
|
5971
6667
|
);
|
|
5972
6668
|
}
|
|
5973
6669
|
} else {
|
|
@@ -6006,7 +6702,7 @@ async function web(args2) {
|
|
|
6006
6702
|
const open = args2.includes("--open");
|
|
6007
6703
|
const positional = args2.filter((a) => !a.startsWith("--"));
|
|
6008
6704
|
const rawPath = positional[0] ?? "";
|
|
6009
|
-
const
|
|
6705
|
+
const path9 = rawPath.startsWith("/") ? rawPath : rawPath ? `/${rawPath}` : "";
|
|
6010
6706
|
let result;
|
|
6011
6707
|
try {
|
|
6012
6708
|
result = await ensureCurrentServer({});
|
|
@@ -6014,7 +6710,7 @@ async function web(args2) {
|
|
|
6014
6710
|
console.error(`Failed to start: ${err.message}`);
|
|
6015
6711
|
process.exit(1);
|
|
6016
6712
|
}
|
|
6017
|
-
const url = `http://localhost:${result.port}${
|
|
6713
|
+
const url = `http://localhost:${result.port}${path9}`;
|
|
6018
6714
|
if (result.restarted) {
|
|
6019
6715
|
console.log(`fleetlens restarted on http://localhost:${result.port} (PID ${result.pid}) \u2014 replaced stale ${result.previousVersion ?? "unknown"} server`);
|
|
6020
6716
|
}
|
|
@@ -6075,9 +6771,9 @@ function readFromCredentialsFile() {
|
|
|
6075
6771
|
join7(homedir4(), ".claude", ".credentials.json"),
|
|
6076
6772
|
join7(homedir4(), ".config", "claude", "credentials.json")
|
|
6077
6773
|
];
|
|
6078
|
-
for (const
|
|
6774
|
+
for (const path9 of candidates) {
|
|
6079
6775
|
try {
|
|
6080
|
-
const blob = readFileSync10(
|
|
6776
|
+
const blob = readFileSync10(path9, "utf8");
|
|
6081
6777
|
const creds = extractCredentials(blob);
|
|
6082
6778
|
if (creds) return creds;
|
|
6083
6779
|
} catch {
|
|
@@ -6199,6 +6895,224 @@ var init_api = __esm({
|
|
|
6199
6895
|
}
|
|
6200
6896
|
});
|
|
6201
6897
|
|
|
6898
|
+
// src/usage/grok.ts
|
|
6899
|
+
import { existsSync as existsSync8, readFileSync as readFileSync11 } from "node:fs";
|
|
6900
|
+
import os8 from "node:os";
|
|
6901
|
+
import path8 from "node:path";
|
|
6902
|
+
function grokHome() {
|
|
6903
|
+
return process.env.GROK_HOME || path8.join(os8.homedir(), ".grok");
|
|
6904
|
+
}
|
|
6905
|
+
function authPath() {
|
|
6906
|
+
return path8.join(grokHome(), "auth.json");
|
|
6907
|
+
}
|
|
6908
|
+
function loadAuthEntry() {
|
|
6909
|
+
const p = authPath();
|
|
6910
|
+
if (!existsSync8(p)) {
|
|
6911
|
+
throw new GrokApiError("Grok not logged in. Run `grok login`.", "no_auth");
|
|
6912
|
+
}
|
|
6913
|
+
let raw;
|
|
6914
|
+
try {
|
|
6915
|
+
raw = JSON.parse(readFileSync11(p, "utf8"));
|
|
6916
|
+
} catch {
|
|
6917
|
+
throw new GrokApiError("Grok auth.json is unreadable. Run `grok login`.", "no_auth");
|
|
6918
|
+
}
|
|
6919
|
+
for (const [entryKey2, entry] of Object.entries(raw)) {
|
|
6920
|
+
const token = typeof entry?.key === "string" ? entry.key.trim() : "";
|
|
6921
|
+
if (token) return { token, entry, entryKey: entryKey2 };
|
|
6922
|
+
}
|
|
6923
|
+
throw new GrokApiError("Grok auth has no access token. Run `grok login`.", "no_auth");
|
|
6924
|
+
}
|
|
6925
|
+
function needsRefresh(entry) {
|
|
6926
|
+
const exp = entry.expires_at;
|
|
6927
|
+
if (!exp) return false;
|
|
6928
|
+
const ms = Date.parse(exp);
|
|
6929
|
+
if (!Number.isFinite(ms)) return false;
|
|
6930
|
+
return Date.now() >= ms - REFRESH_BUFFER_MS;
|
|
6931
|
+
}
|
|
6932
|
+
async function refreshAccessToken(entry) {
|
|
6933
|
+
const refresh = entry.refresh_token?.trim();
|
|
6934
|
+
if (!refresh) return null;
|
|
6935
|
+
const clientId = entry.oidc_client_id?.trim() || DEFAULT_CLIENT_ID;
|
|
6936
|
+
const body = new URLSearchParams({
|
|
6937
|
+
grant_type: "refresh_token",
|
|
6938
|
+
client_id: clientId,
|
|
6939
|
+
refresh_token: refresh
|
|
6940
|
+
});
|
|
6941
|
+
let res;
|
|
6942
|
+
try {
|
|
6943
|
+
res = await fetch(REFRESH_URL, {
|
|
6944
|
+
method: "POST",
|
|
6945
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
6946
|
+
body: body.toString()
|
|
6947
|
+
});
|
|
6948
|
+
} catch {
|
|
6949
|
+
return null;
|
|
6950
|
+
}
|
|
6951
|
+
if (!res.ok) return null;
|
|
6952
|
+
try {
|
|
6953
|
+
const j = await res.json();
|
|
6954
|
+
if (typeof j.access_token !== "string" || !j.access_token) return null;
|
|
6955
|
+
try {
|
|
6956
|
+
const p = authPath();
|
|
6957
|
+
const raw = JSON.parse(readFileSync11(p, "utf8"));
|
|
6958
|
+
for (const key of Object.keys(raw)) {
|
|
6959
|
+
if (raw[key]?.key === entry.key || raw[key]?.refresh_token === refresh) {
|
|
6960
|
+
raw[key] = {
|
|
6961
|
+
...raw[key],
|
|
6962
|
+
key: j.access_token,
|
|
6963
|
+
refresh_token: j.refresh_token ?? raw[key].refresh_token,
|
|
6964
|
+
expires_at: typeof j.expires_in === "number" ? new Date(Date.now() + j.expires_in * 1e3).toISOString() : raw[key].expires_at
|
|
6965
|
+
};
|
|
6966
|
+
break;
|
|
6967
|
+
}
|
|
6968
|
+
}
|
|
6969
|
+
const { writeFileSync: writeFileSync17 } = await import("node:fs");
|
|
6970
|
+
writeFileSync17(p, JSON.stringify(raw, null, 2), "utf8");
|
|
6971
|
+
} catch {
|
|
6972
|
+
}
|
|
6973
|
+
return j.access_token;
|
|
6974
|
+
} catch {
|
|
6975
|
+
return null;
|
|
6976
|
+
}
|
|
6977
|
+
}
|
|
6978
|
+
function authHeaders(token) {
|
|
6979
|
+
return {
|
|
6980
|
+
Authorization: `Bearer ${token.trim()}`,
|
|
6981
|
+
"X-XAI-Token-Auth": TOKEN_AUTH,
|
|
6982
|
+
Accept: "application/json",
|
|
6983
|
+
"User-Agent": "fleetlens"
|
|
6984
|
+
};
|
|
6985
|
+
}
|
|
6986
|
+
function parseGrokCreditsConfig(body) {
|
|
6987
|
+
if (!body || typeof body !== "object") {
|
|
6988
|
+
throw new GrokApiError("Grok billing response missing body", "parse");
|
|
6989
|
+
}
|
|
6990
|
+
const config = body.config;
|
|
6991
|
+
if (!config || typeof config !== "object") {
|
|
6992
|
+
throw new GrokApiError("Grok billing response missing config", "parse");
|
|
6993
|
+
}
|
|
6994
|
+
const period = config.currentPeriod;
|
|
6995
|
+
if (!period || typeof period !== "object") {
|
|
6996
|
+
throw new GrokApiError("Grok billing response missing currentPeriod", "parse");
|
|
6997
|
+
}
|
|
6998
|
+
const periodType = typeof period.type === "string" ? period.type.trim() : "";
|
|
6999
|
+
if (!periodType) {
|
|
7000
|
+
throw new GrokApiError("Grok billing period type missing", "parse");
|
|
7001
|
+
}
|
|
7002
|
+
let utilization = 0;
|
|
7003
|
+
if (config.creditUsagePercent !== void 0 && config.creditUsagePercent !== null) {
|
|
7004
|
+
const n = Number(config.creditUsagePercent);
|
|
7005
|
+
if (!Number.isFinite(n)) {
|
|
7006
|
+
throw new GrokApiError("Grok creditUsagePercent is not a number", "parse");
|
|
7007
|
+
}
|
|
7008
|
+
utilization = Math.min(100, Math.max(0, n));
|
|
7009
|
+
}
|
|
7010
|
+
const end = typeof period.end === "string" && period.end ? new Date(period.end).toISOString() : null;
|
|
7011
|
+
let onDemandCap = 0;
|
|
7012
|
+
const cap = config.onDemandCap;
|
|
7013
|
+
if (cap && typeof cap === "object" && "val" in cap) {
|
|
7014
|
+
const v = Number(cap.val);
|
|
7015
|
+
if (Number.isFinite(v)) onDemandCap = v;
|
|
7016
|
+
}
|
|
7017
|
+
return {
|
|
7018
|
+
utilization,
|
|
7019
|
+
resets_at: end && !Number.isNaN(Date.parse(end)) ? end : null,
|
|
7020
|
+
period_type: periodType,
|
|
7021
|
+
on_demand_cap: onDemandCap
|
|
7022
|
+
};
|
|
7023
|
+
}
|
|
7024
|
+
async function fetchJson(url, token) {
|
|
7025
|
+
let res;
|
|
7026
|
+
try {
|
|
7027
|
+
res = await fetch(url, { headers: authHeaders(token) });
|
|
7028
|
+
} catch (err) {
|
|
7029
|
+
throw new GrokApiError(
|
|
7030
|
+
`Network error reaching Grok billing: ${err.message}`,
|
|
7031
|
+
"network"
|
|
7032
|
+
);
|
|
7033
|
+
}
|
|
7034
|
+
let body = null;
|
|
7035
|
+
try {
|
|
7036
|
+
body = await res.json();
|
|
7037
|
+
} catch {
|
|
7038
|
+
}
|
|
7039
|
+
return { status: res.status, body };
|
|
7040
|
+
}
|
|
7041
|
+
async function fetchGrokUsage() {
|
|
7042
|
+
const loaded = loadAuthEntry();
|
|
7043
|
+
const entry = loaded.entry;
|
|
7044
|
+
let token = loaded.token;
|
|
7045
|
+
if (needsRefresh(entry)) {
|
|
7046
|
+
const refreshed = await refreshAccessToken(entry);
|
|
7047
|
+
if (refreshed) token = refreshed;
|
|
7048
|
+
}
|
|
7049
|
+
let { status: status2, body } = await fetchJson(CREDITS_URL, token);
|
|
7050
|
+
if (status2 === 401 || status2 === 403) {
|
|
7051
|
+
const refreshed = await refreshAccessToken(entry);
|
|
7052
|
+
if (refreshed) {
|
|
7053
|
+
token = refreshed;
|
|
7054
|
+
({ status: status2, body } = await fetchJson(CREDITS_URL, token));
|
|
7055
|
+
}
|
|
7056
|
+
}
|
|
7057
|
+
if (status2 < 200 || status2 >= 300) {
|
|
7058
|
+
throw new GrokApiError(
|
|
7059
|
+
`Grok billing returned HTTP ${status2}`,
|
|
7060
|
+
status2 === 401 || status2 === 403 ? "no_auth" : "http"
|
|
7061
|
+
);
|
|
7062
|
+
}
|
|
7063
|
+
const credits = parseGrokCreditsConfig(body);
|
|
7064
|
+
if (credits.period_type !== WEEKLY_PERIOD) {
|
|
7065
|
+
throw new GrokApiError(
|
|
7066
|
+
`Grok period is ${credits.period_type}, not weekly`,
|
|
7067
|
+
"not_weekly"
|
|
7068
|
+
);
|
|
7069
|
+
}
|
|
7070
|
+
let planType = null;
|
|
7071
|
+
try {
|
|
7072
|
+
const settings = await fetchJson(SETTINGS_URL, token);
|
|
7073
|
+
if (settings.status >= 200 && settings.status < 300 && settings.body && typeof settings.body === "object") {
|
|
7074
|
+
const tier = settings.body.subscription_tier_display;
|
|
7075
|
+
if (typeof tier === "string" && tier.trim()) planType = tier.trim();
|
|
7076
|
+
}
|
|
7077
|
+
} catch {
|
|
7078
|
+
}
|
|
7079
|
+
return {
|
|
7080
|
+
captured_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7081
|
+
agent: "grok",
|
|
7082
|
+
// No 5-hour window — menubar / strip show "—" on the top line.
|
|
7083
|
+
five_hour: { utilization: null, resets_at: null },
|
|
7084
|
+
seven_day: {
|
|
7085
|
+
utilization: credits.utilization,
|
|
7086
|
+
resets_at: credits.resets_at
|
|
7087
|
+
},
|
|
7088
|
+
seven_day_opus: null,
|
|
7089
|
+
seven_day_sonnet: null,
|
|
7090
|
+
seven_day_oauth_apps: null,
|
|
7091
|
+
seven_day_cowork: null,
|
|
7092
|
+
extra_usage: null,
|
|
7093
|
+
plan_type: planType
|
|
7094
|
+
};
|
|
7095
|
+
}
|
|
7096
|
+
var CREDITS_URL, SETTINGS_URL, REFRESH_URL, TOKEN_AUTH, DEFAULT_CLIENT_ID, WEEKLY_PERIOD, REFRESH_BUFFER_MS, GrokApiError;
|
|
7097
|
+
var init_grok2 = __esm({
|
|
7098
|
+
"src/usage/grok.ts"() {
|
|
7099
|
+
"use strict";
|
|
7100
|
+
CREDITS_URL = "https://cli-chat-proxy.grok.com/v1/billing?format=credits";
|
|
7101
|
+
SETTINGS_URL = "https://cli-chat-proxy.grok.com/v1/settings";
|
|
7102
|
+
REFRESH_URL = "https://auth.x.ai/oauth2/token";
|
|
7103
|
+
TOKEN_AUTH = "xai-grok-cli";
|
|
7104
|
+
DEFAULT_CLIENT_ID = "b1a00492-073a-47ea-816f-4c329264a828";
|
|
7105
|
+
WEEKLY_PERIOD = "USAGE_PERIOD_TYPE_WEEKLY";
|
|
7106
|
+
REFRESH_BUFFER_MS = 5 * 60 * 1e3;
|
|
7107
|
+
GrokApiError = class extends Error {
|
|
7108
|
+
constructor(message, code) {
|
|
7109
|
+
super(message);
|
|
7110
|
+
this.code = code;
|
|
7111
|
+
}
|
|
7112
|
+
};
|
|
7113
|
+
}
|
|
7114
|
+
});
|
|
7115
|
+
|
|
6202
7116
|
// src/usage/format.ts
|
|
6203
7117
|
function formatUsage(snapshot) {
|
|
6204
7118
|
const rows = [
|
|
@@ -6558,6 +7472,30 @@ Usage:
|
|
|
6558
7472
|
const snapshot = await fetchUsage();
|
|
6559
7473
|
if (save) appendSnapshot(USAGE_LOG2, snapshot);
|
|
6560
7474
|
process.stdout.write(formatUsage(snapshot));
|
|
7475
|
+
if (save) {
|
|
7476
|
+
for (const source of agentSources) {
|
|
7477
|
+
if (source.kind === "claude-code" || !source.usagePoller) continue;
|
|
7478
|
+
try {
|
|
7479
|
+
const partial = await source.usagePoller();
|
|
7480
|
+
if (!partial) continue;
|
|
7481
|
+
appendSnapshot(USAGE_LOG2, {
|
|
7482
|
+
...partial,
|
|
7483
|
+
seven_day_opus: null,
|
|
7484
|
+
seven_day_sonnet: null,
|
|
7485
|
+
seven_day_oauth_apps: null,
|
|
7486
|
+
seven_day_cowork: null,
|
|
7487
|
+
extra_usage: null
|
|
7488
|
+
});
|
|
7489
|
+
} catch {
|
|
7490
|
+
}
|
|
7491
|
+
}
|
|
7492
|
+
try {
|
|
7493
|
+
appendSnapshot(USAGE_LOG2, await fetchGrokUsage());
|
|
7494
|
+
} catch (err) {
|
|
7495
|
+
if (!(err instanceof GrokApiError && err.code === "no_auth")) {
|
|
7496
|
+
}
|
|
7497
|
+
}
|
|
7498
|
+
}
|
|
6561
7499
|
process.stdout.write("\n (tip: run with --history for the daily token/cost table)\n");
|
|
6562
7500
|
} catch (err) {
|
|
6563
7501
|
if (err instanceof UsageApiError) {
|
|
@@ -6572,6 +7510,7 @@ var init_usage = __esm({
|
|
|
6572
7510
|
"src/commands/usage.ts"() {
|
|
6573
7511
|
"use strict";
|
|
6574
7512
|
init_api();
|
|
7513
|
+
init_grok2();
|
|
6575
7514
|
init_format();
|
|
6576
7515
|
init_storage();
|
|
6577
7516
|
init_fs();
|
|
@@ -7068,6 +8007,7 @@ __export(dist_exports, {
|
|
|
7068
8007
|
CODEX_METADATA: () => CODEX_METADATA,
|
|
7069
8008
|
COWORK_METADATA: () => COWORK_METADATA,
|
|
7070
8009
|
GEMINI_METADATA: () => GEMINI_METADATA,
|
|
8010
|
+
GROK_METADATA: () => GROK_METADATA,
|
|
7071
8011
|
PRICES: () => PRICES,
|
|
7072
8012
|
RATE_PER_PCT: () => RATE_PER_PCT,
|
|
7073
8013
|
RATE_PER_PCT_5H: () => RATE_PER_PCT_5H,
|
|
@@ -7481,7 +8421,7 @@ function closeTurn(t, closed, cwd) {
|
|
|
7481
8421
|
let active = 0;
|
|
7482
8422
|
for (let i = 1; i < ts.length; i++) {
|
|
7483
8423
|
const dt = ts[i] - ts[i - 1];
|
|
7484
|
-
if (dt <
|
|
8424
|
+
if (dt < IDLE_GAP_MS5)
|
|
7485
8425
|
active += dt;
|
|
7486
8426
|
}
|
|
7487
8427
|
closed.push({
|
|
@@ -7678,7 +8618,7 @@ function aggregateDay(dayEvents, _sessionFallbackProject) {
|
|
|
7678
8618
|
let activeMs2 = 0;
|
|
7679
8619
|
for (let i = 1; i < tsSorted.length; i++) {
|
|
7680
8620
|
const dt = tsSorted[i] - tsSorted[i - 1];
|
|
7681
|
-
if (dt <
|
|
8621
|
+
if (dt < IDLE_GAP_MS5)
|
|
7682
8622
|
activeMs2 += dt;
|
|
7683
8623
|
}
|
|
7684
8624
|
const tsSortedStrings = dayEvents.map((e) => e.timestamp).filter((t) => !!t).sort();
|
|
@@ -7865,7 +8805,7 @@ function buildEntries(sessionDetail) {
|
|
|
7865
8805
|
entries2.sort((a, b) => a.local_day.localeCompare(b.local_day));
|
|
7866
8806
|
return entries2;
|
|
7867
8807
|
}
|
|
7868
|
-
var
|
|
8808
|
+
var IDLE_GAP_MS5, INTERRUPT_RE2, PR_TITLE_RE, BASH_CHAIN_SPLIT_RE, SHELL_NOISE, IMAGE_BLOCK_RE;
|
|
7869
8809
|
var init_build = __esm({
|
|
7870
8810
|
"../entries/dist/build.js"() {
|
|
7871
8811
|
"use strict";
|
|
@@ -7873,7 +8813,7 @@ var init_build = __esm({
|
|
|
7873
8813
|
init_types();
|
|
7874
8814
|
init_signals();
|
|
7875
8815
|
init_trivial();
|
|
7876
|
-
|
|
8816
|
+
IDLE_GAP_MS5 = 3 * 60 * 1e3;
|
|
7877
8817
|
INTERRUPT_RE2 = /\[request interrupted|interrupted by user/i;
|
|
7878
8818
|
PR_TITLE_RE = /--title\s+["']([^"']+)["']/;
|
|
7879
8819
|
BASH_CHAIN_SPLIT_RE = /\|\||&&|;|\|/;
|
|
@@ -7902,11 +8842,11 @@ var init_dist2 = __esm({
|
|
|
7902
8842
|
});
|
|
7903
8843
|
|
|
7904
8844
|
// ../entries/dist/digest-fs.js
|
|
7905
|
-
import { readFileSync as
|
|
8845
|
+
import { readFileSync as readFileSync12, readdirSync, writeFileSync as writeFileSync6, renameSync as renameSync2, chmodSync, mkdirSync as mkdirSync6, existsSync as existsSync9 } from "node:fs";
|
|
7906
8846
|
import { dirname as dirname8, join as join8 } from "node:path";
|
|
7907
|
-
function parseDigestFile(
|
|
8847
|
+
function parseDigestFile(path9, expectedVersion) {
|
|
7908
8848
|
try {
|
|
7909
|
-
const parsed = JSON.parse(
|
|
8849
|
+
const parsed = JSON.parse(readFileSync12(path9, "utf8"));
|
|
7910
8850
|
if (!parsed || typeof parsed !== "object")
|
|
7911
8851
|
return null;
|
|
7912
8852
|
if (parsed.version !== expectedVersion)
|
|
@@ -7925,11 +8865,11 @@ function digestsDir() {
|
|
|
7925
8865
|
digestsDirCached = envOverride ?? cclensPath("digests");
|
|
7926
8866
|
return digestsDirCached;
|
|
7927
8867
|
}
|
|
7928
|
-
function __setDigestsDirForTest(
|
|
7929
|
-
digestsDirCached =
|
|
7930
|
-
mkdirSync6(join8(
|
|
7931
|
-
mkdirSync6(join8(
|
|
7932
|
-
mkdirSync6(join8(
|
|
8868
|
+
function __setDigestsDirForTest(path9) {
|
|
8869
|
+
digestsDirCached = path9;
|
|
8870
|
+
mkdirSync6(join8(path9, "day"), { recursive: true });
|
|
8871
|
+
mkdirSync6(join8(path9, "week"), { recursive: true });
|
|
8872
|
+
mkdirSync6(join8(path9, "month"), { recursive: true });
|
|
7933
8873
|
}
|
|
7934
8874
|
function dayDigestPath(date) {
|
|
7935
8875
|
return join8(digestsDir(), "day", `${date}.json`);
|
|
@@ -7955,7 +8895,7 @@ function writeDayDigest(digest2) {
|
|
|
7955
8895
|
}
|
|
7956
8896
|
function readDayDigest(date) {
|
|
7957
8897
|
const p = dayDigestPath(date);
|
|
7958
|
-
if (!
|
|
8898
|
+
if (!existsSync9(p))
|
|
7959
8899
|
return null;
|
|
7960
8900
|
return parseDigestFile(p, CURRENT_DAY_DIGEST_SCHEMA_VERSION);
|
|
7961
8901
|
}
|
|
@@ -7991,13 +8931,13 @@ function writeWeekDigest(digest2) {
|
|
|
7991
8931
|
}
|
|
7992
8932
|
function readWeekDigest(monday) {
|
|
7993
8933
|
const p = weekDigestPath(monday);
|
|
7994
|
-
if (!
|
|
8934
|
+
if (!existsSync9(p))
|
|
7995
8935
|
return null;
|
|
7996
8936
|
return parseDigestFile(p, CURRENT_WEEK_DIGEST_SCHEMA_VERSION);
|
|
7997
8937
|
}
|
|
7998
8938
|
function listWeekDigestKeys() {
|
|
7999
8939
|
const dir = join8(digestsDir(), "week");
|
|
8000
|
-
if (!
|
|
8940
|
+
if (!existsSync9(dir))
|
|
8001
8941
|
return [];
|
|
8002
8942
|
return readdirSync(dir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length)).filter((k) => /^\d{4}-\d{2}-\d{2}$/.test(k));
|
|
8003
8943
|
}
|
|
@@ -8028,13 +8968,13 @@ function writeMonthDigest(digest2) {
|
|
|
8028
8968
|
}
|
|
8029
8969
|
function readMonthDigest(yearMonth) {
|
|
8030
8970
|
const p = monthDigestPath(yearMonth);
|
|
8031
|
-
if (!
|
|
8971
|
+
if (!existsSync9(p))
|
|
8032
8972
|
return null;
|
|
8033
8973
|
return parseDigestFile(p, CURRENT_MONTH_DIGEST_SCHEMA_VERSION);
|
|
8034
8974
|
}
|
|
8035
8975
|
function listMonthDigestKeys() {
|
|
8036
8976
|
const dir = join8(digestsDir(), "month");
|
|
8037
|
-
if (!
|
|
8977
|
+
if (!existsSync9(dir))
|
|
8038
8978
|
return [];
|
|
8039
8979
|
return readdirSync(dir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length)).filter((k) => /^\d{4}-\d{2}$/.test(k));
|
|
8040
8980
|
}
|
|
@@ -8096,7 +9036,7 @@ __export(fs_exports2, {
|
|
|
8096
9036
|
writeMonthDigest: () => writeMonthDigest,
|
|
8097
9037
|
writeWeekDigest: () => writeWeekDigest
|
|
8098
9038
|
});
|
|
8099
|
-
import { readFileSync as
|
|
9039
|
+
import { readFileSync as readFileSync13, readdirSync as readdirSync2, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7, renameSync as renameSync3, existsSync as existsSync10 } from "node:fs";
|
|
8100
9040
|
import { randomBytes } from "node:crypto";
|
|
8101
9041
|
import { join as join9 } from "node:path";
|
|
8102
9042
|
function entriesDir() {
|
|
@@ -8106,9 +9046,9 @@ function entriesDir() {
|
|
|
8106
9046
|
entriesDirCached = envOverride ?? cclensPath("entries");
|
|
8107
9047
|
return entriesDirCached;
|
|
8108
9048
|
}
|
|
8109
|
-
function __setEntriesDirForTest(
|
|
8110
|
-
entriesDirCached =
|
|
8111
|
-
mkdirSync7(
|
|
9049
|
+
function __setEntriesDirForTest(path9) {
|
|
9050
|
+
entriesDirCached = path9;
|
|
9051
|
+
mkdirSync7(path9, { recursive: true });
|
|
8112
9052
|
}
|
|
8113
9053
|
function pathFor(sessionId, localDay2) {
|
|
8114
9054
|
return join9(entriesDir(), `${entryKey(sessionId, localDay2)}.json`);
|
|
@@ -8155,17 +9095,17 @@ function writeEntryPreservingEnrichment(fresh) {
|
|
|
8155
9095
|
}
|
|
8156
9096
|
function readEntry(sessionId, localDay2) {
|
|
8157
9097
|
const p = pathFor(sessionId, localDay2);
|
|
8158
|
-
if (!
|
|
9098
|
+
if (!existsSync10(p))
|
|
8159
9099
|
return null;
|
|
8160
|
-
const raw =
|
|
9100
|
+
const raw = readFileSync13(p, "utf8");
|
|
8161
9101
|
return JSON.parse(raw);
|
|
8162
9102
|
}
|
|
8163
9103
|
function entryExists(sessionId, localDay2) {
|
|
8164
|
-
return
|
|
9104
|
+
return existsSync10(pathFor(sessionId, localDay2));
|
|
8165
9105
|
}
|
|
8166
9106
|
function listEntryKeys() {
|
|
8167
9107
|
const dir = entriesDir();
|
|
8168
|
-
if (!
|
|
9108
|
+
if (!existsSync10(dir))
|
|
8169
9109
|
return [];
|
|
8170
9110
|
return readdirSync2(dir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length));
|
|
8171
9111
|
}
|
|
@@ -8647,8 +9587,8 @@ var init_parseUtil = __esm({
|
|
|
8647
9587
|
init_errors();
|
|
8648
9588
|
init_en();
|
|
8649
9589
|
makeIssue = (params) => {
|
|
8650
|
-
const { data, path:
|
|
8651
|
-
const fullPath = [...
|
|
9590
|
+
const { data, path: path9, errorMaps, issueData } = params;
|
|
9591
|
+
const fullPath = [...path9, ...issueData.path || []];
|
|
8652
9592
|
const fullIssue = {
|
|
8653
9593
|
...issueData,
|
|
8654
9594
|
path: fullPath
|
|
@@ -8956,11 +9896,11 @@ var init_types3 = __esm({
|
|
|
8956
9896
|
init_parseUtil();
|
|
8957
9897
|
init_util();
|
|
8958
9898
|
ParseInputLazyPath = class {
|
|
8959
|
-
constructor(parent, value,
|
|
9899
|
+
constructor(parent, value, path9, key) {
|
|
8960
9900
|
this._cachedPath = [];
|
|
8961
9901
|
this.parent = parent;
|
|
8962
9902
|
this.data = value;
|
|
8963
|
-
this._path =
|
|
9903
|
+
this._path = path9;
|
|
8964
9904
|
this._key = key;
|
|
8965
9905
|
}
|
|
8966
9906
|
get path() {
|
|
@@ -12444,7 +13384,7 @@ RESPOND WITH ONLY VALID JSON (no prose, no code fence):
|
|
|
12444
13384
|
});
|
|
12445
13385
|
|
|
12446
13386
|
// ../entries/dist/tmux-runner.js
|
|
12447
|
-
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync8, existsSync as
|
|
13387
|
+
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync8, existsSync as existsSync11, readdirSync as readdirSync3, realpathSync as realpathSync5, readFileSync as readFileSync14, unlinkSync as unlinkSync3, renameSync as renameSync4 } from "node:fs";
|
|
12448
13388
|
import { join as join10 } from "node:path";
|
|
12449
13389
|
import { homedir as homedir5 } from "node:os";
|
|
12450
13390
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
@@ -12463,7 +13403,7 @@ function tmuxRunnerAvailable() {
|
|
|
12463
13403
|
}
|
|
12464
13404
|
function runtimeCwd() {
|
|
12465
13405
|
const dir = join10(homedir5(), ".cclens", "runtime");
|
|
12466
|
-
if (!
|
|
13406
|
+
if (!existsSync11(dir))
|
|
12467
13407
|
mkdirSync8(dir, { recursive: true });
|
|
12468
13408
|
return realpathSync5(dir);
|
|
12469
13409
|
}
|
|
@@ -12471,7 +13411,7 @@ function ensureRuntimeCwdTrusted(cwd) {
|
|
|
12471
13411
|
const cfgPath = join10(homedir5(), ".claude.json");
|
|
12472
13412
|
let cfg;
|
|
12473
13413
|
try {
|
|
12474
|
-
cfg = JSON.parse(
|
|
13414
|
+
cfg = JSON.parse(readFileSync14(cfgPath, "utf8"));
|
|
12475
13415
|
} catch {
|
|
12476
13416
|
return;
|
|
12477
13417
|
}
|
|
@@ -12618,10 +13558,10 @@ function snapshotAllTranscripts() {
|
|
|
12618
13558
|
}
|
|
12619
13559
|
return out;
|
|
12620
13560
|
}
|
|
12621
|
-
function readJsonlCwd(
|
|
13561
|
+
function readJsonlCwd(path9, maxLines = 8) {
|
|
12622
13562
|
let raw;
|
|
12623
13563
|
try {
|
|
12624
|
-
raw =
|
|
13564
|
+
raw = readFileSync14(path9, "utf8");
|
|
12625
13565
|
} catch {
|
|
12626
13566
|
return void 0;
|
|
12627
13567
|
}
|
|
@@ -12675,10 +13615,10 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
|
|
|
12675
13615
|
}
|
|
12676
13616
|
throw new TmuxRunError(`timeout waiting for claude to create the session transcript (cwd: ${targetCwd})`);
|
|
12677
13617
|
}
|
|
12678
|
-
function parseTranscript2(
|
|
13618
|
+
function parseTranscript2(path9, defaultModel) {
|
|
12679
13619
|
let raw;
|
|
12680
13620
|
try {
|
|
12681
|
-
raw =
|
|
13621
|
+
raw = readFileSync14(path9, "utf8");
|
|
12682
13622
|
} catch {
|
|
12683
13623
|
return { assembled: "", inputTokens: 0, outputTokens: 0, modelUsed: defaultModel, done: false };
|
|
12684
13624
|
}
|
|
@@ -12772,11 +13712,11 @@ var init_tmux_runner = __esm({
|
|
|
12772
13712
|
|
|
12773
13713
|
// ../entries/dist/llm-runner.js
|
|
12774
13714
|
import { spawn as spawn3 } from "node:child_process";
|
|
12775
|
-
import { mkdirSync as mkdirSync9, appendFileSync as appendFileSync3, writeFileSync as writeFileSync9, existsSync as
|
|
13715
|
+
import { mkdirSync as mkdirSync9, appendFileSync as appendFileSync3, writeFileSync as writeFileSync9, existsSync as existsSync12 } from "node:fs";
|
|
12776
13716
|
import { join as join11 } from "node:path";
|
|
12777
13717
|
import { randomUUID } from "node:crypto";
|
|
12778
13718
|
function ensureRunsDir() {
|
|
12779
|
-
if (!
|
|
13719
|
+
if (!existsSync12(RUNS_DIR)) {
|
|
12780
13720
|
try {
|
|
12781
13721
|
mkdirSync9(RUNS_DIR, { recursive: true });
|
|
12782
13722
|
} catch {
|
|
@@ -12807,15 +13747,15 @@ function newRunId(kind) {
|
|
|
12807
13747
|
function tracePath(runId) {
|
|
12808
13748
|
return join11(RUNS_DIR, `${runId}.jsonl`);
|
|
12809
13749
|
}
|
|
12810
|
-
function safeAppend(
|
|
13750
|
+
function safeAppend(path9, line) {
|
|
12811
13751
|
try {
|
|
12812
|
-
appendFileSync3(
|
|
13752
|
+
appendFileSync3(path9, line);
|
|
12813
13753
|
} catch {
|
|
12814
13754
|
}
|
|
12815
13755
|
}
|
|
12816
|
-
function safeWrite(
|
|
13756
|
+
function safeWrite(path9, line) {
|
|
12817
13757
|
try {
|
|
12818
|
-
writeFileSync9(
|
|
13758
|
+
writeFileSync9(path9, line);
|
|
12819
13759
|
} catch {
|
|
12820
13760
|
}
|
|
12821
13761
|
}
|
|
@@ -13221,7 +14161,7 @@ var init_enrich2 = __esm({
|
|
|
13221
14161
|
});
|
|
13222
14162
|
|
|
13223
14163
|
// ../entries/dist/budget.js
|
|
13224
|
-
import { appendFileSync as appendFileSync4, readFileSync as
|
|
14164
|
+
import { appendFileSync as appendFileSync4, readFileSync as readFileSync15, existsSync as existsSync13, mkdirSync as mkdirSync10 } from "node:fs";
|
|
13225
14165
|
import { dirname as dirname9 } from "node:path";
|
|
13226
14166
|
function spendPath() {
|
|
13227
14167
|
if (spendPathCached)
|
|
@@ -13229,8 +14169,8 @@ function spendPath() {
|
|
|
13229
14169
|
spendPathCached = cclensPath("llm-spend.jsonl");
|
|
13230
14170
|
return spendPathCached;
|
|
13231
14171
|
}
|
|
13232
|
-
function __setSpendPathForTest(
|
|
13233
|
-
spendPathCached =
|
|
14172
|
+
function __setSpendPathForTest(path9) {
|
|
14173
|
+
spendPathCached = path9;
|
|
13234
14174
|
}
|
|
13235
14175
|
function appendSpend(record) {
|
|
13236
14176
|
const p = spendPath();
|
|
@@ -13239,12 +14179,12 @@ function appendSpend(record) {
|
|
|
13239
14179
|
}
|
|
13240
14180
|
function monthToDateSpend(now = /* @__PURE__ */ new Date()) {
|
|
13241
14181
|
const p = spendPath();
|
|
13242
|
-
if (!
|
|
14182
|
+
if (!existsSync13(p))
|
|
13243
14183
|
return 0;
|
|
13244
14184
|
const year = now.getUTCFullYear();
|
|
13245
14185
|
const month2 = now.getUTCMonth();
|
|
13246
14186
|
let total = 0;
|
|
13247
|
-
const raw =
|
|
14187
|
+
const raw = readFileSync15(p, "utf8");
|
|
13248
14188
|
for (const line of raw.split("\n")) {
|
|
13249
14189
|
if (!line)
|
|
13250
14190
|
continue;
|
|
@@ -13273,15 +14213,15 @@ var init_budget = __esm({
|
|
|
13273
14213
|
});
|
|
13274
14214
|
|
|
13275
14215
|
// ../entries/dist/pipeline-lock.js
|
|
13276
|
-
import { writeFileSync as writeFileSync10, unlinkSync as unlinkSync4, existsSync as
|
|
14216
|
+
import { writeFileSync as writeFileSync10, unlinkSync as unlinkSync4, existsSync as existsSync14, readFileSync as readFileSync16, statSync as statSync3 } from "node:fs";
|
|
13277
14217
|
function lockPath() {
|
|
13278
14218
|
if (lockPathCached)
|
|
13279
14219
|
return lockPathCached;
|
|
13280
14220
|
lockPathCached = cclensPath("llm-interactive.lock");
|
|
13281
14221
|
return lockPathCached;
|
|
13282
14222
|
}
|
|
13283
|
-
function __setInteractiveLockPathForTest(
|
|
13284
|
-
lockPathCached =
|
|
14223
|
+
function __setInteractiveLockPathForTest(path9) {
|
|
14224
|
+
lockPathCached = path9;
|
|
13285
14225
|
}
|
|
13286
14226
|
function touchLock() {
|
|
13287
14227
|
writeFileSync10(lockPath(), String(process.pid), "utf8");
|
|
@@ -13318,13 +14258,13 @@ function pidAlive(pid) {
|
|
|
13318
14258
|
}
|
|
13319
14259
|
function interactiveLockFresh(nowMs) {
|
|
13320
14260
|
const p = lockPath();
|
|
13321
|
-
if (!
|
|
14261
|
+
if (!existsSync14(p))
|
|
13322
14262
|
return false;
|
|
13323
14263
|
try {
|
|
13324
14264
|
const mtime = statSync3(p).mtimeMs;
|
|
13325
14265
|
if (nowMs - mtime > STALE_MS)
|
|
13326
14266
|
return false;
|
|
13327
|
-
const pid = Number(
|
|
14267
|
+
const pid = Number(readFileSync16(p, "utf8").trim());
|
|
13328
14268
|
if (!Number.isFinite(pid) || pid <= 0)
|
|
13329
14269
|
return false;
|
|
13330
14270
|
if (!pidAlive(pid))
|
|
@@ -13430,7 +14370,7 @@ var init_queue = __esm({
|
|
|
13430
14370
|
});
|
|
13431
14371
|
|
|
13432
14372
|
// ../entries/dist/settings.js
|
|
13433
|
-
import { readFileSync as
|
|
14373
|
+
import { readFileSync as readFileSync17, writeFileSync as writeFileSync11, renameSync as renameSync5, chmodSync as chmodSync2, mkdirSync as mkdirSync11, existsSync as existsSync15 } from "node:fs";
|
|
13434
14374
|
import { dirname as dirname10 } from "node:path";
|
|
13435
14375
|
function settingsPath() {
|
|
13436
14376
|
if (settingsPathCached)
|
|
@@ -13438,8 +14378,8 @@ function settingsPath() {
|
|
|
13438
14378
|
settingsPathCached = cclensPath("settings.json");
|
|
13439
14379
|
return settingsPathCached;
|
|
13440
14380
|
}
|
|
13441
|
-
function __setSettingsPathForTest(
|
|
13442
|
-
settingsPathCached =
|
|
14381
|
+
function __setSettingsPathForTest(path9) {
|
|
14382
|
+
settingsPathCached = path9;
|
|
13443
14383
|
}
|
|
13444
14384
|
function toDisk(s) {
|
|
13445
14385
|
return {
|
|
@@ -13466,10 +14406,10 @@ function fromDisk(d) {
|
|
|
13466
14406
|
}
|
|
13467
14407
|
function readSettings() {
|
|
13468
14408
|
const p = settingsPath();
|
|
13469
|
-
if (!
|
|
14409
|
+
if (!existsSync15(p))
|
|
13470
14410
|
return DEFAULT_SETTINGS;
|
|
13471
14411
|
try {
|
|
13472
|
-
const raw =
|
|
14412
|
+
const raw = readFileSync17(p, "utf8");
|
|
13473
14413
|
return fromDisk(JSON.parse(raw));
|
|
13474
14414
|
} catch {
|
|
13475
14415
|
return DEFAULT_SETTINGS;
|
|
@@ -13676,7 +14616,7 @@ function rollupOutcomeDay(entries2) {
|
|
|
13676
14616
|
return "exploratory";
|
|
13677
14617
|
return "trivial";
|
|
13678
14618
|
}
|
|
13679
|
-
function
|
|
14619
|
+
function truncate6(s, max) {
|
|
13680
14620
|
if (s.length <= max)
|
|
13681
14621
|
return s;
|
|
13682
14622
|
return s.slice(0, max - 1).trimEnd() + "\u2026";
|
|
@@ -13732,7 +14672,7 @@ function computeDaySignals(entries2) {
|
|
|
13732
14672
|
type,
|
|
13733
14673
|
count: v.count,
|
|
13734
14674
|
sample_description: v.sample_description,
|
|
13735
|
-
sample_prompt_preview:
|
|
14675
|
+
sample_prompt_preview: truncate6(v.sample_prompt_preview, 200)
|
|
13736
14676
|
}));
|
|
13737
14677
|
const frameCounts = /* @__PURE__ */ new Map();
|
|
13738
14678
|
for (const s of signalsList) {
|
|
@@ -13751,7 +14691,7 @@ function computeDaySignals(entries2) {
|
|
|
13751
14691
|
if ((e.first_user ?? "").length > 0)
|
|
13752
14692
|
verbosity_distribution[s.verbosity] += 1;
|
|
13753
14693
|
for (const ref of s.external_refs) {
|
|
13754
|
-
external_refs.push({ session_id: e.session_id, kind: ref.kind, preview:
|
|
14694
|
+
external_refs.push({ session_id: e.session_id, kind: ref.kind, preview: truncate6(ref.preview, 200) });
|
|
13755
14695
|
}
|
|
13756
14696
|
const ints = e.numbers.interrupts ?? 0;
|
|
13757
14697
|
interrupts += ints;
|
|
@@ -14624,7 +15564,7 @@ function computeInteractionModes(entries2) {
|
|
|
14624
15564
|
date: entry.local_day,
|
|
14625
15565
|
project_display: prettyProject3(entry.project),
|
|
14626
15566
|
type: sa.type,
|
|
14627
|
-
prompt_preview:
|
|
15567
|
+
prompt_preview: truncate7(sa.prompt_preview, 200)
|
|
14628
15568
|
});
|
|
14629
15569
|
}
|
|
14630
15570
|
const skillExamples = [];
|
|
@@ -14641,7 +15581,7 @@ function computeInteractionModes(entries2) {
|
|
|
14641
15581
|
skillExamples.push({
|
|
14642
15582
|
date: e.local_day,
|
|
14643
15583
|
skill,
|
|
14644
|
-
first_user_preview:
|
|
15584
|
+
first_user_preview: truncate7(e.first_user, 200)
|
|
14645
15585
|
});
|
|
14646
15586
|
}
|
|
14647
15587
|
}
|
|
@@ -14658,7 +15598,7 @@ function computeInteractionModes(entries2) {
|
|
|
14658
15598
|
project_display: prettyProject3(longestTurnEntry.project),
|
|
14659
15599
|
active_min: longestTurnEntry.numbers.active_min,
|
|
14660
15600
|
top_tools: longestTurnEntry.top_tools.slice(0, 5),
|
|
14661
|
-
first_user_preview:
|
|
15601
|
+
first_user_preview: truncate7(longestTurnEntry.first_user, 200)
|
|
14662
15602
|
} : null;
|
|
14663
15603
|
const tools_per_turn = turn_count > 0 ? tools_total / turn_count : 0;
|
|
14664
15604
|
const label = tools_per_turn < 5 ? "rapid" : tools_per_turn < 15 ? "mixed" : "batch";
|
|
@@ -14689,7 +15629,7 @@ function computeInteractionModes(entries2) {
|
|
|
14689
15629
|
}
|
|
14690
15630
|
};
|
|
14691
15631
|
}
|
|
14692
|
-
function
|
|
15632
|
+
function truncate7(s, max) {
|
|
14693
15633
|
if (s.length <= max)
|
|
14694
15634
|
return s;
|
|
14695
15635
|
return s.slice(0, max - 1).trimEnd() + "\u2026";
|
|
@@ -14736,7 +15676,7 @@ function computeWorkingShapes(dayDigests, entriesByDay = /* @__PURE__ */ new Map
|
|
|
14736
15676
|
evidence_subagent = {
|
|
14737
15677
|
type: sa.type,
|
|
14738
15678
|
description: sa.description,
|
|
14739
|
-
prompt_preview:
|
|
15679
|
+
prompt_preview: truncate7(sa.prompt_preview, 200)
|
|
14740
15680
|
};
|
|
14741
15681
|
}
|
|
14742
15682
|
const project_display = repEntry ? prettyProject3(repEntry.project) : dd.projects[0]?.display_name ?? "";
|
|
@@ -14747,7 +15687,7 @@ function computeWorkingShapes(dayDigests, entriesByDay = /* @__PURE__ */ new Map
|
|
|
14747
15687
|
outcome: dayOutcome.get(dd.key) ?? null,
|
|
14748
15688
|
helpfulness: dayHelp.get(dd.key) ?? null,
|
|
14749
15689
|
evidence_subagent,
|
|
14750
|
-
evidence_first_user: repEntry?.first_user ?
|
|
15690
|
+
evidence_first_user: repEntry?.first_user ? truncate7(repEntry.first_user, 200) : null,
|
|
14751
15691
|
day_signature: dd.day_signature ?? null
|
|
14752
15692
|
};
|
|
14753
15693
|
});
|
|
@@ -14822,7 +15762,7 @@ function computeInteractionGrammar(dayDigests, entriesByDay = /* @__PURE__ */ ne
|
|
|
14822
15762
|
date: day2,
|
|
14823
15763
|
session_id: ref.session_id,
|
|
14824
15764
|
ref_kind: ref.kind,
|
|
14825
|
-
preview:
|
|
15765
|
+
preview: truncate7(ref.preview, 200)
|
|
14826
15766
|
});
|
|
14827
15767
|
}
|
|
14828
15768
|
total_interrupts += signals.comm_style.steering.interrupts;
|
|
@@ -14894,7 +15834,7 @@ function computeInteractionGrammar(dayDigests, entriesByDay = /* @__PURE__ */ ne
|
|
|
14894
15834
|
count: v.count,
|
|
14895
15835
|
days: [...v.days].sort(),
|
|
14896
15836
|
sample_description: v.sample_description,
|
|
14897
|
-
sample_prompt_preview:
|
|
15837
|
+
sample_prompt_preview: truncate7(v.sample_prompt_preview, 200)
|
|
14898
15838
|
})),
|
|
14899
15839
|
threads,
|
|
14900
15840
|
communication_style: {
|
|
@@ -15542,7 +16482,7 @@ function activeMs(timestamps) {
|
|
|
15542
16482
|
let active = 0;
|
|
15543
16483
|
for (let i = 1; i < ts.length; i++) {
|
|
15544
16484
|
const dt = ts[i] - ts[i - 1];
|
|
15545
|
-
if (dt <
|
|
16485
|
+
if (dt < IDLE_GAP_MS6)
|
|
15546
16486
|
active += dt;
|
|
15547
16487
|
}
|
|
15548
16488
|
return active;
|
|
@@ -15713,7 +16653,7 @@ function buildSessionSlice(entry, events, daySignature) {
|
|
|
15713
16653
|
let intEnd = sortedTs[0];
|
|
15714
16654
|
for (let i = 1; i < sortedTs.length; i++) {
|
|
15715
16655
|
const dt = sortedTs[i] - intEnd;
|
|
15716
|
-
if (dt >=
|
|
16656
|
+
if (dt >= IDLE_GAP_MS6) {
|
|
15717
16657
|
intervals.push({
|
|
15718
16658
|
start_min: fmtMin(intStart - sliceStartMs),
|
|
15719
16659
|
end_min: fmtMin(intEnd - sliceStartMs)
|
|
@@ -16110,14 +17050,14 @@ async function generateTopSession(slice, opts = {}) {
|
|
|
16110
17050
|
void lastModel;
|
|
16111
17051
|
}
|
|
16112
17052
|
}
|
|
16113
|
-
var
|
|
17053
|
+
var IDLE_GAP_MS6, LONG_AUTONOMOUS_MIN, N_USER, N_FIRST_AGENT, N_LAST_AGENT, N_USER_TURN1, N_SUBAGENT, SHELL_NOISE2, INTERRUPT_RE3, PR_TITLE_RE2, PinResponseSchema, TopSessionResponseSchema, SYSTEM_PROMPT5, TOP_SESSION_SYSTEM_PROMPT, DEFAULT_MODEL5, defaultCallLLMTopSession, validateTopSession;
|
|
16114
17054
|
var init_top_sessions = __esm({
|
|
16115
17055
|
"../entries/dist/top-sessions.js"() {
|
|
16116
17056
|
"use strict";
|
|
16117
17057
|
init_zod();
|
|
16118
17058
|
init_signals();
|
|
16119
17059
|
init_llm_runner();
|
|
16120
|
-
|
|
17060
|
+
IDLE_GAP_MS6 = 3 * 60 * 1e3;
|
|
16121
17061
|
LONG_AUTONOMOUS_MIN = 20;
|
|
16122
17062
|
N_USER = 150;
|
|
16123
17063
|
N_FIRST_AGENT = 150;
|
|
@@ -16659,7 +17599,7 @@ var init_digest_month_pipeline = __esm({
|
|
|
16659
17599
|
});
|
|
16660
17600
|
|
|
16661
17601
|
// ../entries/dist/credentials.js
|
|
16662
|
-
import { writeFileSync as writeFileSync12, readFileSync as
|
|
17602
|
+
import { writeFileSync as writeFileSync12, readFileSync as readFileSync18, renameSync as renameSync6, chmodSync as chmodSync3, mkdirSync as mkdirSync12, existsSync as existsSync16, unlinkSync as unlinkSync5 } from "node:fs";
|
|
16663
17603
|
import { dirname as dirname11 } from "node:path";
|
|
16664
17604
|
async function fetchZaiUsage(candidate) {
|
|
16665
17605
|
const key = candidate.trim();
|
|
@@ -16730,10 +17670,10 @@ function credentialsPath() {
|
|
|
16730
17670
|
}
|
|
16731
17671
|
function readCredentials() {
|
|
16732
17672
|
const p = credentialsPath();
|
|
16733
|
-
if (!
|
|
17673
|
+
if (!existsSync16(p))
|
|
16734
17674
|
return {};
|
|
16735
17675
|
try {
|
|
16736
|
-
const raw =
|
|
17676
|
+
const raw = readFileSync18(p, "utf8");
|
|
16737
17677
|
return JSON.parse(raw);
|
|
16738
17678
|
} catch {
|
|
16739
17679
|
return {};
|
|
@@ -17363,7 +18303,7 @@ var menubar_exports = {};
|
|
|
17363
18303
|
__export(menubar_exports, {
|
|
17364
18304
|
menubar: () => menubar
|
|
17365
18305
|
});
|
|
17366
|
-
import { existsSync as
|
|
18306
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync13, cpSync, rmSync as rmSync2, readdirSync as readdirSync4, writeFileSync as writeFileSync13, realpathSync as realpathSync6 } from "node:fs";
|
|
17367
18307
|
import { homedir as homedir6 } from "node:os";
|
|
17368
18308
|
import { join as join12, dirname as dirname12 } from "node:path";
|
|
17369
18309
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
@@ -17405,8 +18345,8 @@ async function isRunning() {
|
|
|
17405
18345
|
return false;
|
|
17406
18346
|
}
|
|
17407
18347
|
}
|
|
17408
|
-
async function launchApp(
|
|
17409
|
-
await execFileAsync2("open", ["-a",
|
|
18348
|
+
async function launchApp(path9) {
|
|
18349
|
+
await execFileAsync2("open", ["-a", path9]);
|
|
17410
18350
|
}
|
|
17411
18351
|
async function quitApp() {
|
|
17412
18352
|
await execFileAsync2("osascript", ["-e", `tell application "${BUNDLE_EXEC}" to quit`]).catch(
|
|
@@ -17427,7 +18367,7 @@ async function installMenubar(opts) {
|
|
|
17427
18367
|
return;
|
|
17428
18368
|
}
|
|
17429
18369
|
const src = bundledAppPath();
|
|
17430
|
-
if (!
|
|
18370
|
+
if (!existsSync17(src)) {
|
|
17431
18371
|
console.error(
|
|
17432
18372
|
`Bundled widget not found at ${src}.
|
|
17433
18373
|
This install was probably built without the menubar artifact. Run \`node apps/menubar/build-app.sh && cp -R apps/menubar/dist/FleetlensMenubar.app packages/cli/menubar/\` and rebuild.`
|
|
@@ -17469,7 +18409,7 @@ async function uninstallMenubar() {
|
|
|
17469
18409
|
await new Promise((r) => setTimeout(r, 300));
|
|
17470
18410
|
}
|
|
17471
18411
|
const dest = installedAppPath();
|
|
17472
|
-
if (
|
|
18412
|
+
if (existsSync17(dest)) {
|
|
17473
18413
|
rmSync2(dest, { recursive: true, force: true });
|
|
17474
18414
|
console.log(`Removed ${dest}`);
|
|
17475
18415
|
} else {
|
|
@@ -17483,7 +18423,7 @@ async function openMenubar() {
|
|
|
17483
18423
|
return;
|
|
17484
18424
|
}
|
|
17485
18425
|
const dest = installedAppPath();
|
|
17486
|
-
if (!
|
|
18426
|
+
if (!existsSync17(dest)) {
|
|
17487
18427
|
console.log("Widget not installed yet. Run `fleetlens menubar install` first.");
|
|
17488
18428
|
return;
|
|
17489
18429
|
}
|
|
@@ -17500,9 +18440,9 @@ async function statusMenubar() {
|
|
|
17500
18440
|
return;
|
|
17501
18441
|
}
|
|
17502
18442
|
const dest = installedAppPath();
|
|
17503
|
-
const installed =
|
|
18443
|
+
const installed = existsSync17(dest);
|
|
17504
18444
|
const running = await isRunning();
|
|
17505
|
-
const bundled =
|
|
18445
|
+
const bundled = existsSync17(bundledAppPath());
|
|
17506
18446
|
console.log(`Menu bar widget: ${installed ? "installed" : "not installed"}${installed ? ` (${dest})` : ""}`);
|
|
17507
18447
|
console.log(`Running: ${running ? "yes" : "no"}`);
|
|
17508
18448
|
console.log(`Bundled in CLI: ${bundled ? "yes" : "no \u2014 this build ships without the widget"}`);
|
|
@@ -17591,7 +18531,7 @@ var init_config = __esm({
|
|
|
17591
18531
|
});
|
|
17592
18532
|
|
|
17593
18533
|
// src/perception/build-entries.ts
|
|
17594
|
-
import { statSync as statSync4, readFileSync as
|
|
18534
|
+
import { statSync as statSync4, readFileSync as readFileSync19 } from "node:fs";
|
|
17595
18535
|
import { basename as basename2, dirname as dirname13 } from "node:path";
|
|
17596
18536
|
function decodeProjectDirName(projectDir) {
|
|
17597
18537
|
if (projectDir.startsWith("-")) {
|
|
@@ -17601,7 +18541,7 @@ function decodeProjectDirName(projectDir) {
|
|
|
17601
18541
|
}
|
|
17602
18542
|
function buildEntriesForFile(filePath) {
|
|
17603
18543
|
const stat = statSync4(filePath);
|
|
17604
|
-
const raw =
|
|
18544
|
+
const raw = readFileSync19(filePath, "utf8");
|
|
17605
18545
|
const rawLines = raw.split("\n").filter(Boolean).map((l) => {
|
|
17606
18546
|
try {
|
|
17607
18547
|
return JSON.parse(l);
|
|
@@ -17866,7 +18806,7 @@ function buildIngestPayload(inputs) {
|
|
|
17866
18806
|
return {
|
|
17867
18807
|
ingestId: randomUUID2(),
|
|
17868
18808
|
observedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
17869
|
-
cliVersion: "0.16.
|
|
18809
|
+
cliVersion: "0.16.1",
|
|
17870
18810
|
...richRollup || inputs.enrichedExtras || inputs.artifactSignals ? { schemaVersion: RICH_ROLLUP_SCHEMA_VERSION } : {},
|
|
17871
18811
|
...inputs.rollup ? { dailyRollup: inputs.rollup } : {},
|
|
17872
18812
|
...richRollup ? { richRollup } : {},
|
|
@@ -17907,7 +18847,7 @@ var init_push = __esm({
|
|
|
17907
18847
|
});
|
|
17908
18848
|
|
|
17909
18849
|
// src/team/git-remote.ts
|
|
17910
|
-
import { existsSync as
|
|
18850
|
+
import { existsSync as existsSync18, readFileSync as readFileSync20, statSync as statSync5 } from "node:fs";
|
|
17911
18851
|
import { dirname as dirname14, isAbsolute as isAbsolute2, join as join13, resolve as resolve2 } from "node:path";
|
|
17912
18852
|
function parseGithubRemote(url) {
|
|
17913
18853
|
const m = url.trim().match(GITHUB_URL_RE);
|
|
@@ -17932,12 +18872,12 @@ function gitConfigPathFor(dir) {
|
|
|
17932
18872
|
const st = statSync5(dotGit, { throwIfNoEntry: false });
|
|
17933
18873
|
if (!st) return null;
|
|
17934
18874
|
if (st.isDirectory()) return join13(dotGit, "config");
|
|
17935
|
-
const m =
|
|
18875
|
+
const m = readFileSync20(dotGit, "utf8").match(/^gitdir:\s*(.+)\s*$/m);
|
|
17936
18876
|
if (!m) return null;
|
|
17937
18877
|
const gd = isAbsolute2(m[1]) ? m[1] : resolve2(dir, m[1]);
|
|
17938
18878
|
const commondirFile = join13(gd, "commondir");
|
|
17939
|
-
if (
|
|
17940
|
-
const common =
|
|
18879
|
+
if (existsSync18(commondirFile)) {
|
|
18880
|
+
const common = readFileSync20(commondirFile, "utf8").trim();
|
|
17941
18881
|
return join13(isAbsolute2(common) ? common : resolve2(gd, common), "config");
|
|
17942
18882
|
}
|
|
17943
18883
|
return join13(gd, "config");
|
|
@@ -17952,8 +18892,8 @@ function createRepoResolver() {
|
|
|
17952
18892
|
try {
|
|
17953
18893
|
for (let d = dir; ; d = dirname14(d)) {
|
|
17954
18894
|
const config = gitConfigPathFor(d);
|
|
17955
|
-
if (config &&
|
|
17956
|
-
const url = originUrl2(
|
|
18895
|
+
if (config && existsSync18(config)) {
|
|
18896
|
+
const url = originUrl2(readFileSync20(config, "utf8"));
|
|
17957
18897
|
repo = url ? parseGithubRemote(url) : null;
|
|
17958
18898
|
break;
|
|
17959
18899
|
}
|
|
@@ -17975,7 +18915,7 @@ var init_git_remote = __esm({
|
|
|
17975
18915
|
});
|
|
17976
18916
|
|
|
17977
18917
|
// src/team/queue.ts
|
|
17978
|
-
import { readFileSync as
|
|
18918
|
+
import { readFileSync as readFileSync21, writeFileSync as writeFileSync14, appendFileSync as appendFileSync5, statSync as statSync6, mkdirSync as mkdirSync14 } from "node:fs";
|
|
17979
18919
|
import { dirname as dirname15 } from "node:path";
|
|
17980
18920
|
function enqueuePayload(payload, queuePath = QUEUE_PATH) {
|
|
17981
18921
|
mkdirSync14(dirname15(queuePath), { recursive: true });
|
|
@@ -17992,7 +18932,7 @@ function enqueuePayload(payload, queuePath = QUEUE_PATH) {
|
|
|
17992
18932
|
function dequeuePayloads(queuePath = QUEUE_PATH) {
|
|
17993
18933
|
let lines;
|
|
17994
18934
|
try {
|
|
17995
|
-
lines =
|
|
18935
|
+
lines = readFileSync21(queuePath, "utf8").trim().split("\n").filter(Boolean);
|
|
17996
18936
|
} catch {
|
|
17997
18937
|
return [];
|
|
17998
18938
|
}
|
|
@@ -18013,7 +18953,7 @@ function dequeuePayloads(queuePath = QUEUE_PATH) {
|
|
|
18013
18953
|
function pruneOldest(queuePath) {
|
|
18014
18954
|
let lines;
|
|
18015
18955
|
try {
|
|
18016
|
-
lines =
|
|
18956
|
+
lines = readFileSync21(queuePath, "utf8").trim().split("\n").filter(Boolean);
|
|
18017
18957
|
} catch {
|
|
18018
18958
|
return;
|
|
18019
18959
|
}
|
|
@@ -18032,7 +18972,7 @@ var init_queue2 = __esm({
|
|
|
18032
18972
|
});
|
|
18033
18973
|
|
|
18034
18974
|
// src/usage/profile.ts
|
|
18035
|
-
import { existsSync as
|
|
18975
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync15, readFileSync as readFileSync22, writeFileSync as writeFileSync15 } from "node:fs";
|
|
18036
18976
|
import { dirname as dirname16 } from "node:path";
|
|
18037
18977
|
function mapRateLimitTier(rateLimitTier) {
|
|
18038
18978
|
switch (rateLimitTier) {
|
|
@@ -18073,9 +19013,9 @@ async function fetchProfile(nowMs = Date.now()) {
|
|
|
18073
19013
|
};
|
|
18074
19014
|
}
|
|
18075
19015
|
function readCachedProfile(cachePath) {
|
|
18076
|
-
if (!
|
|
19016
|
+
if (!existsSync19(cachePath)) return null;
|
|
18077
19017
|
try {
|
|
18078
|
-
const raw = JSON.parse(
|
|
19018
|
+
const raw = JSON.parse(readFileSync22(cachePath, "utf8"));
|
|
18079
19019
|
if (typeof raw.fetchedAtMs !== "number" || !raw.profile) return null;
|
|
18080
19020
|
return raw;
|
|
18081
19021
|
} catch {
|
|
@@ -18264,11 +19204,11 @@ var init_backfill = __esm({
|
|
|
18264
19204
|
});
|
|
18265
19205
|
|
|
18266
19206
|
// src/team/sync-log.ts
|
|
18267
|
-
import { readFileSync as
|
|
19207
|
+
import { readFileSync as readFileSync23 } from "node:fs";
|
|
18268
19208
|
function readPendingSyncLog(watermark) {
|
|
18269
19209
|
let raw;
|
|
18270
19210
|
try {
|
|
18271
|
-
raw =
|
|
19211
|
+
raw = readFileSync23(cclensPath("daemon.log"), "utf8");
|
|
18272
19212
|
} catch {
|
|
18273
19213
|
return { lines: [] };
|
|
18274
19214
|
}
|
|
@@ -18332,7 +19272,7 @@ __export(file_probe_exports, {
|
|
|
18332
19272
|
probeArtifactSignals: () => probeArtifactSignals
|
|
18333
19273
|
});
|
|
18334
19274
|
import { createHash } from "node:crypto";
|
|
18335
|
-
import { existsSync as
|
|
19275
|
+
import { existsSync as existsSync20, readdirSync as readdirSync5, statSync as statSync7 } from "node:fs";
|
|
18336
19276
|
import { homedir as homedir7 } from "node:os";
|
|
18337
19277
|
import { join as join15, relative, resolve as resolve3, sep } from "node:path";
|
|
18338
19278
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
@@ -18342,15 +19282,15 @@ function pathHash(relPath) {
|
|
|
18342
19282
|
function defaultScanRoots(extraRoots = []) {
|
|
18343
19283
|
const roots = [];
|
|
18344
19284
|
const home = join15(homedir7(), ".claude");
|
|
18345
|
-
if (
|
|
19285
|
+
if (existsSync20(home)) roots.push({ root: home, label: "user" });
|
|
18346
19286
|
for (const e of extraRoots) {
|
|
18347
19287
|
const r = resolve3(e, ".claude");
|
|
18348
|
-
if (
|
|
19288
|
+
if (existsSync20(r) && r !== home) roots.push({ root: r, label: "project" });
|
|
18349
19289
|
}
|
|
18350
19290
|
return roots;
|
|
18351
19291
|
}
|
|
18352
19292
|
function listMarkdownFiles(dir) {
|
|
18353
|
-
if (!
|
|
19293
|
+
if (!existsSync20(dir)) return [];
|
|
18354
19294
|
const out = [];
|
|
18355
19295
|
let entries2;
|
|
18356
19296
|
try {
|
|
@@ -18420,7 +19360,7 @@ function scanAuthored(roots, subdir, day2) {
|
|
|
18420
19360
|
const out = [];
|
|
18421
19361
|
for (const r of roots) {
|
|
18422
19362
|
const dir = join15(r.root, subdir);
|
|
18423
|
-
if (!
|
|
19363
|
+
if (!existsSync20(dir)) continue;
|
|
18424
19364
|
for (const f of listMarkdownFiles(dir)) {
|
|
18425
19365
|
const firstSeen = firstSeenDateOf(f);
|
|
18426
19366
|
if (firstSeen !== day2) continue;
|
|
@@ -18434,7 +19374,7 @@ function scanEdited(roots, day2) {
|
|
|
18434
19374
|
const out = [];
|
|
18435
19375
|
for (const r of roots) {
|
|
18436
19376
|
const dir = join15(r.root, "skills");
|
|
18437
|
-
if (!
|
|
19377
|
+
if (!existsSync20(dir)) continue;
|
|
18438
19378
|
for (const f of listMarkdownFiles(dir)) {
|
|
18439
19379
|
const firstSeen = firstSeenDateOf(f);
|
|
18440
19380
|
if (firstSeen === day2) continue;
|
|
@@ -18457,10 +19397,10 @@ function claudemdLineDelta(extraRoots, authorEmail, day2) {
|
|
|
18457
19397
|
const candidates = [];
|
|
18458
19398
|
for (const e of extraRoots) {
|
|
18459
19399
|
const f = resolve3(e, "CLAUDE.md");
|
|
18460
|
-
if (
|
|
19400
|
+
if (existsSync20(f)) candidates.push(f);
|
|
18461
19401
|
}
|
|
18462
19402
|
const homeClaudeMd = join15(homedir7(), "CLAUDE.md");
|
|
18463
|
-
if (
|
|
19403
|
+
if (existsSync20(homeClaudeMd)) candidates.push(homeClaudeMd);
|
|
18464
19404
|
for (const file of candidates) {
|
|
18465
19405
|
try {
|
|
18466
19406
|
const out = execFileSync3(
|
|
@@ -19350,11 +20290,11 @@ var logs_exports = {};
|
|
|
19350
20290
|
__export(logs_exports, {
|
|
19351
20291
|
teamLogs: () => teamLogs
|
|
19352
20292
|
});
|
|
19353
|
-
import { readFileSync as
|
|
20293
|
+
import { readFileSync as readFileSync24 } from "node:fs";
|
|
19354
20294
|
async function teamLogs() {
|
|
19355
20295
|
const logPath = cclensPath("daemon.log");
|
|
19356
20296
|
try {
|
|
19357
|
-
const lines =
|
|
20297
|
+
const lines = readFileSync24(logPath, "utf8").trim().split("\n");
|
|
19358
20298
|
const teamLines = lines.filter((l) => l.includes("[sync] ") || l.includes("team "));
|
|
19359
20299
|
if (teamLines.length === 0) {
|
|
19360
20300
|
console.log("No team-related log entries found.");
|
|
@@ -19482,7 +20422,7 @@ __export(runs_exports, {
|
|
|
19482
20422
|
runs: () => runs
|
|
19483
20423
|
});
|
|
19484
20424
|
import { execSync as execSync2 } from "node:child_process";
|
|
19485
|
-
import { existsSync as
|
|
20425
|
+
import { existsSync as existsSync21, readFileSync as readFileSync25, readdirSync as readdirSync6, statSync as statSync8 } from "node:fs";
|
|
19486
20426
|
import { join as join16 } from "node:path";
|
|
19487
20427
|
async function runs(args2) {
|
|
19488
20428
|
const json = args2.includes("--json");
|
|
@@ -19567,8 +20507,8 @@ function listActiveRuns() {
|
|
|
19567
20507
|
return runs2.sort((a, b) => a.elapsed_s - b.elapsed_s);
|
|
19568
20508
|
}
|
|
19569
20509
|
function readSpend(sinceMs) {
|
|
19570
|
-
if (!
|
|
19571
|
-
const lines =
|
|
20510
|
+
if (!existsSync21(SPEND_PATH)) return [];
|
|
20511
|
+
const lines = readFileSync25(SPEND_PATH, "utf-8").split("\n").filter((l) => l.trim());
|
|
19572
20512
|
const out = [];
|
|
19573
20513
|
for (const line of lines) {
|
|
19574
20514
|
try {
|
|
@@ -19689,23 +20629,23 @@ function ageLabel(ms) {
|
|
|
19689
20629
|
return `${Math.floor(ms / 864e5)}d`;
|
|
19690
20630
|
}
|
|
19691
20631
|
function listTraceFiles() {
|
|
19692
|
-
if (!
|
|
20632
|
+
if (!existsSync21(RUNS_DIR2)) return [];
|
|
19693
20633
|
const entries2 = readdirSync6(RUNS_DIR2).filter((f) => f.endsWith(".jsonl"));
|
|
19694
20634
|
return entries2.map((f) => {
|
|
19695
|
-
const
|
|
19696
|
-
const st = statSync8(
|
|
19697
|
-
return { runId: f.replace(/\.jsonl$/, ""), path:
|
|
20635
|
+
const path9 = join16(RUNS_DIR2, f);
|
|
20636
|
+
const st = statSync8(path9);
|
|
20637
|
+
return { runId: f.replace(/\.jsonl$/, ""), path: path9, mtimeMs: st.mtimeMs };
|
|
19698
20638
|
}).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
19699
20639
|
}
|
|
19700
20640
|
function resolveRunId(arg) {
|
|
19701
|
-
if (!
|
|
20641
|
+
if (!existsSync21(RUNS_DIR2)) return null;
|
|
19702
20642
|
if (arg === "latest") {
|
|
19703
20643
|
const all2 = listTraceFiles();
|
|
19704
20644
|
if (all2.length === 0) return null;
|
|
19705
20645
|
return { runId: all2[0].runId, path: all2[0].path };
|
|
19706
20646
|
}
|
|
19707
20647
|
const exact = join16(RUNS_DIR2, `${arg}.jsonl`);
|
|
19708
|
-
if (
|
|
20648
|
+
if (existsSync21(exact)) return { runId: arg, path: exact };
|
|
19709
20649
|
const all = listTraceFiles();
|
|
19710
20650
|
const matches = all.filter((r) => r.runId.includes(arg));
|
|
19711
20651
|
if (matches.length === 1) return { runId: matches[0].runId, path: matches[0].path };
|
|
@@ -19716,8 +20656,8 @@ function resolveRunId(arg) {
|
|
|
19716
20656
|
}
|
|
19717
20657
|
return null;
|
|
19718
20658
|
}
|
|
19719
|
-
function readTrace(
|
|
19720
|
-
return
|
|
20659
|
+
function readTrace(path9) {
|
|
20660
|
+
return readFileSync25(path9, "utf-8").split("\n").filter((l) => l.trim()).map((l) => {
|
|
19721
20661
|
try {
|
|
19722
20662
|
return JSON.parse(l);
|
|
19723
20663
|
} catch {
|
|
@@ -19729,7 +20669,7 @@ async function inspect(arg, follow, json) {
|
|
|
19729
20669
|
const r = resolveRunId(arg);
|
|
19730
20670
|
if (!r) {
|
|
19731
20671
|
console.error(`run not found: ${arg}`);
|
|
19732
|
-
if (
|
|
20672
|
+
if (existsSync21(RUNS_DIR2)) {
|
|
19733
20673
|
const all = listTraceFiles().slice(0, 5);
|
|
19734
20674
|
if (all.length > 0) {
|
|
19735
20675
|
console.error(`
|
|
@@ -19909,7 +20849,7 @@ async function main() {
|
|
|
19909
20849
|
case "version":
|
|
19910
20850
|
case "--version":
|
|
19911
20851
|
case "-v":
|
|
19912
|
-
console.log(`fleetlens ${"0.16.
|
|
20852
|
+
console.log(`fleetlens ${"0.16.1"}`);
|
|
19913
20853
|
break;
|
|
19914
20854
|
case "help":
|
|
19915
20855
|
case "--help":
|
|
@@ -19936,7 +20876,7 @@ Advanced:
|
|
|
19936
20876
|
start --no-daemon Start only the web server (no daemon)
|
|
19937
20877
|
daemon <start|stop|status|logs> Manage the usage daemon by itself
|
|
19938
20878
|
autostart <install|uninstall|status> Run the usage daemon at login (macOS launchd)
|
|
19939
|
-
menubar <install|uninstall|open|status> Native macOS menu bar widget (Claude/Codex/Z.ai usage)
|
|
20879
|
+
menubar <install|uninstall|open|status> Native macOS menu bar widget (Claude/Codex/Z.ai plan usage; Grok sessions on the dashboard)
|
|
19940
20880
|
|
|
19941
20881
|
Team:
|
|
19942
20882
|
team join <url> <token> Pair with a team server (browser setup)
|