fleetlens 0.12.1 → 0.12.3
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 +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/changelog/page.js +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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/page.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 +1 -1
- package/app/apps/web/.next/server/app/usage/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/usage/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/chunks/packages_0c-sz9n._.js +1 -1
- package/app/apps/web/.next/server/chunks/packages_0wywuu.._.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]__0exckd4._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/_0xu2pvc._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0txtsv5._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_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 +3 -0
- 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/0htgc_hr1bw67.js +1 -0
- package/app/apps/web/.next/static/chunks/{0~e7pnd7ot84w.js → 0lziv8y_6yp5w.js} +1 -1
- package/app/apps/web/app/layout.tsx +14 -6
- package/app/apps/web/app/projects/[slug]/page.tsx +3 -4
- package/app/apps/web/components/live-sessions-widget.tsx +1 -1
- package/app/apps/web/lib/changelog-data.generated.ts +1 -1
- package/app/apps/web/package.json +1 -1
- package/app/apps/web/tsconfig.tsbuildinfo +1 -1
- package/dist/daemon-worker.js +29 -17
- package/dist/index.js +150 -82
- package/package.json +1 -1
- package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_12.endt._.js +0 -3
- package/app/apps/web/.next/static/chunks/03_7wmpodz36t.js +0 -1
- /package/app/apps/web/.next/static/{rrY-ephAArv8tjJOXD622 → 7kQ9mNICnVHhf4-LmSGcy}/_buildManifest.js +0 -0
- /package/app/apps/web/.next/static/{rrY-ephAArv8tjJOXD622 → 7kQ9mNICnVHhf4-LmSGcy}/_clientMiddlewareManifest.js +0 -0
- /package/app/apps/web/.next/static/{rrY-ephAArv8tjJOXD622 → 7kQ9mNICnVHhf4-LmSGcy}/_ssgManifest.js +0 -0
package/dist/daemon-worker.js
CHANGED
|
@@ -1824,6 +1824,14 @@ function foldWorkflowAgentTime(activeSegments, spans) {
|
|
|
1824
1824
|
const airTimeMs = merged.reduce((n, s) => n + (s.endMs - s.startMs), 0);
|
|
1825
1825
|
return { activeSegments: merged, airTimeMs };
|
|
1826
1826
|
}
|
|
1827
|
+
async function applySubagentUsage(meta, rawLines, f) {
|
|
1828
|
+
const sessionId = sessionIdFromFileName(f.fileName);
|
|
1829
|
+
const projectDirPath = path.dirname(f.fullPath);
|
|
1830
|
+
const fallbackDay = meta.firstTimestamp ? toLocalDay(Date.parse(meta.firstTimestamp)) : void 0;
|
|
1831
|
+
const { usage, perDay: perDayTokens } = await computeSessionUsageWithSubagents(rawLines, projectDirPath, sessionId, fallbackDay);
|
|
1832
|
+
meta.totalUsage = usage;
|
|
1833
|
+
meta.dailyBreakdown = mergeDailyTokens(meta.dailyBreakdown, perDayTokens, usage);
|
|
1834
|
+
}
|
|
1827
1835
|
async function getCachedMeta(f) {
|
|
1828
1836
|
const cached = metaCache.get(f.fullPath);
|
|
1829
1837
|
if (cached && cached.mtimeMs === f.mtimeMs && cached.sizeBytes === f.sizeBytes) {
|
|
@@ -1832,12 +1840,9 @@ async function getCachedMeta(f) {
|
|
|
1832
1840
|
try {
|
|
1833
1841
|
const rawLines = await readJsonlFile(f.fullPath);
|
|
1834
1842
|
const { meta } = parseTranscript(rawLines);
|
|
1843
|
+
await applySubagentUsage(meta, rawLines, f);
|
|
1835
1844
|
const sessionId = sessionIdFromFileName(f.fileName);
|
|
1836
1845
|
const projectDirPath = path.dirname(f.fullPath);
|
|
1837
|
-
const fallbackDay = meta.firstTimestamp ? toLocalDay(Date.parse(meta.firstTimestamp)) : void 0;
|
|
1838
|
-
const { usage, perDay: perDayTokens } = await computeSessionUsageWithSubagents(rawLines, projectDirPath, sessionId, fallbackDay);
|
|
1839
|
-
meta.totalUsage = usage;
|
|
1840
|
-
meta.dailyBreakdown = mergeDailyTokens(meta.dailyBreakdown, perDayTokens, usage);
|
|
1841
1846
|
const wf = await scanWorkflowAggregate(projectDirPath, sessionId);
|
|
1842
1847
|
const full = {
|
|
1843
1848
|
...meta,
|
|
@@ -1863,6 +1868,7 @@ async function getCachedDetail(f) {
|
|
|
1863
1868
|
const rawLines = await readJsonlFile(f.fullPath);
|
|
1864
1869
|
const { meta, events } = parseTranscript(rawLines);
|
|
1865
1870
|
const sessionId = sessionIdFromFileName(f.fileName);
|
|
1871
|
+
await applySubagentUsage(meta, rawLines, f);
|
|
1866
1872
|
const wf = await scanWorkflowAggregate(path.dirname(f.fullPath), sessionId);
|
|
1867
1873
|
const detail = {
|
|
1868
1874
|
...meta,
|
|
@@ -5361,6 +5367,20 @@ init_fs();
|
|
|
5361
5367
|
import { readFileSync as readFileSync4, readdirSync, writeFileSync as writeFileSync2, renameSync, chmodSync, mkdirSync as mkdirSync3, existsSync as existsSync2 } from "node:fs";
|
|
5362
5368
|
import { dirname as dirname2, join as join3 } from "node:path";
|
|
5363
5369
|
var digestsDirCached = null;
|
|
5370
|
+
function parseDigestFile(path7, expectedVersion) {
|
|
5371
|
+
try {
|
|
5372
|
+
const parsed = JSON.parse(readFileSync4(path7, "utf8"));
|
|
5373
|
+
if (!parsed || typeof parsed !== "object")
|
|
5374
|
+
return null;
|
|
5375
|
+
if (parsed.version !== expectedVersion)
|
|
5376
|
+
return null;
|
|
5377
|
+
if (!Array.isArray(parsed.shipped))
|
|
5378
|
+
return null;
|
|
5379
|
+
return parsed;
|
|
5380
|
+
} catch {
|
|
5381
|
+
return null;
|
|
5382
|
+
}
|
|
5383
|
+
}
|
|
5364
5384
|
function digestsDir() {
|
|
5365
5385
|
if (digestsDirCached)
|
|
5366
5386
|
return digestsDirCached;
|
|
@@ -5391,11 +5411,7 @@ function readDayDigest(date) {
|
|
|
5391
5411
|
const p = dayDigestPath(date);
|
|
5392
5412
|
if (!existsSync2(p))
|
|
5393
5413
|
return null;
|
|
5394
|
-
|
|
5395
|
-
return JSON.parse(readFileSync4(p, "utf8"));
|
|
5396
|
-
} catch {
|
|
5397
|
-
return null;
|
|
5398
|
-
}
|
|
5414
|
+
return parseDigestFile(p, CURRENT_DAY_DIGEST_SCHEMA_VERSION);
|
|
5399
5415
|
}
|
|
5400
5416
|
var TODAY_TTL_MS = 10 * 60 * 1e3;
|
|
5401
5417
|
var todayCache = null;
|
|
@@ -5428,11 +5444,7 @@ function readWeekDigest(monday) {
|
|
|
5428
5444
|
const p = weekDigestPath(monday);
|
|
5429
5445
|
if (!existsSync2(p))
|
|
5430
5446
|
return null;
|
|
5431
|
-
|
|
5432
|
-
return JSON.parse(readFileSync4(p, "utf8"));
|
|
5433
|
-
} catch {
|
|
5434
|
-
return null;
|
|
5435
|
-
}
|
|
5447
|
+
return parseDigestFile(p, CURRENT_WEEK_DIGEST_SCHEMA_VERSION);
|
|
5436
5448
|
}
|
|
5437
5449
|
var CURRENT_WEEK_TTL_MS = 10 * 60 * 1e3;
|
|
5438
5450
|
var currentWeekCache = null;
|
|
@@ -15146,14 +15158,14 @@ async function getUpdateAvailability() {
|
|
|
15146
15158
|
if (isDevMode()) return null;
|
|
15147
15159
|
const latest = await fetchLatestVersion();
|
|
15148
15160
|
if (latest === null) return {
|
|
15149
|
-
current: "0.12.
|
|
15161
|
+
current: "0.12.3",
|
|
15150
15162
|
latest: null,
|
|
15151
15163
|
updateAvailable: false
|
|
15152
15164
|
};
|
|
15153
15165
|
return {
|
|
15154
|
-
current: "0.12.
|
|
15166
|
+
current: "0.12.3",
|
|
15155
15167
|
latest,
|
|
15156
|
-
updateAvailable: shouldUpdate("0.12.
|
|
15168
|
+
updateAvailable: shouldUpdate("0.12.3", latest)
|
|
15157
15169
|
};
|
|
15158
15170
|
}
|
|
15159
15171
|
|
package/dist/index.js
CHANGED
|
@@ -12,19 +12,27 @@ var __export = (target, all) => {
|
|
|
12
12
|
// src/pid.ts
|
|
13
13
|
import { readFileSync, writeFileSync, mkdirSync, unlinkSync } from "node:fs";
|
|
14
14
|
import { dirname } from "node:path";
|
|
15
|
-
function writePid(filePath, pid, port) {
|
|
15
|
+
function writePid(filePath, pid, port, version) {
|
|
16
16
|
mkdirSync(dirname(filePath), { recursive: true });
|
|
17
|
-
|
|
17
|
+
let content = String(pid);
|
|
18
|
+
if (port != null) {
|
|
19
|
+
content += `:${port}`;
|
|
20
|
+
if (version) content += `:${version}`;
|
|
21
|
+
}
|
|
18
22
|
writeFileSync(filePath, content, "utf8");
|
|
19
23
|
}
|
|
20
24
|
function readPid(filePath) {
|
|
21
25
|
try {
|
|
22
26
|
const content = readFileSync(filePath, "utf8").trim();
|
|
23
|
-
const [pidStr, portStr] = content.split(":");
|
|
27
|
+
const [pidStr, portStr, versionStr] = content.split(":");
|
|
24
28
|
const pid = parseInt(pidStr, 10);
|
|
25
29
|
if (Number.isNaN(pid)) return null;
|
|
26
30
|
const port = portStr ? parseInt(portStr, 10) : void 0;
|
|
27
|
-
return {
|
|
31
|
+
return {
|
|
32
|
+
pid,
|
|
33
|
+
port: Number.isNaN(port) ? void 0 : port,
|
|
34
|
+
version: versionStr || void 0
|
|
35
|
+
};
|
|
28
36
|
} catch {
|
|
29
37
|
return null;
|
|
30
38
|
}
|
|
@@ -1841,6 +1849,14 @@ function foldWorkflowAgentTime(activeSegments, spans) {
|
|
|
1841
1849
|
const airTimeMs = merged.reduce((n, s) => n + (s.endMs - s.startMs), 0);
|
|
1842
1850
|
return { activeSegments: merged, airTimeMs };
|
|
1843
1851
|
}
|
|
1852
|
+
async function applySubagentUsage(meta, rawLines, f) {
|
|
1853
|
+
const sessionId = sessionIdFromFileName(f.fileName);
|
|
1854
|
+
const projectDirPath = path.dirname(f.fullPath);
|
|
1855
|
+
const fallbackDay = meta.firstTimestamp ? toLocalDay(Date.parse(meta.firstTimestamp)) : void 0;
|
|
1856
|
+
const { usage: usage2, perDay: perDayTokens } = await computeSessionUsageWithSubagents(rawLines, projectDirPath, sessionId, fallbackDay);
|
|
1857
|
+
meta.totalUsage = usage2;
|
|
1858
|
+
meta.dailyBreakdown = mergeDailyTokens(meta.dailyBreakdown, perDayTokens, usage2);
|
|
1859
|
+
}
|
|
1844
1860
|
async function getCachedMeta(f) {
|
|
1845
1861
|
const cached = metaCache.get(f.fullPath);
|
|
1846
1862
|
if (cached && cached.mtimeMs === f.mtimeMs && cached.sizeBytes === f.sizeBytes) {
|
|
@@ -1849,12 +1865,9 @@ async function getCachedMeta(f) {
|
|
|
1849
1865
|
try {
|
|
1850
1866
|
const rawLines = await readJsonlFile(f.fullPath);
|
|
1851
1867
|
const { meta } = parseTranscript(rawLines);
|
|
1868
|
+
await applySubagentUsage(meta, rawLines, f);
|
|
1852
1869
|
const sessionId = sessionIdFromFileName(f.fileName);
|
|
1853
1870
|
const projectDirPath = path.dirname(f.fullPath);
|
|
1854
|
-
const fallbackDay = meta.firstTimestamp ? toLocalDay(Date.parse(meta.firstTimestamp)) : void 0;
|
|
1855
|
-
const { usage: usage2, perDay: perDayTokens } = await computeSessionUsageWithSubagents(rawLines, projectDirPath, sessionId, fallbackDay);
|
|
1856
|
-
meta.totalUsage = usage2;
|
|
1857
|
-
meta.dailyBreakdown = mergeDailyTokens(meta.dailyBreakdown, perDayTokens, usage2);
|
|
1858
1871
|
const wf = await scanWorkflowAggregate(projectDirPath, sessionId);
|
|
1859
1872
|
const full = {
|
|
1860
1873
|
...meta,
|
|
@@ -1880,6 +1893,7 @@ async function getCachedDetail(f) {
|
|
|
1880
1893
|
const rawLines = await readJsonlFile(f.fullPath);
|
|
1881
1894
|
const { meta, events } = parseTranscript(rawLines);
|
|
1882
1895
|
const sessionId = sessionIdFromFileName(f.fileName);
|
|
1896
|
+
await applySubagentUsage(meta, rawLines, f);
|
|
1883
1897
|
const wf = await scanWorkflowAggregate(path.dirname(f.fullPath), sessionId);
|
|
1884
1898
|
const detail = {
|
|
1885
1899
|
...meta,
|
|
@@ -4468,7 +4482,9 @@ var init_fs = __esm({
|
|
|
4468
4482
|
// src/server.ts
|
|
4469
4483
|
var server_exports = {};
|
|
4470
4484
|
__export(server_exports, {
|
|
4485
|
+
ensureCurrentServer: () => ensureCurrentServer,
|
|
4471
4486
|
getServerStatus: () => getServerStatus,
|
|
4487
|
+
isServerStale: () => isServerStale,
|
|
4472
4488
|
openBrowser: () => openBrowser,
|
|
4473
4489
|
startServer: () => startServer,
|
|
4474
4490
|
stopServer: () => stopServer
|
|
@@ -4486,10 +4502,42 @@ function getServerStatus() {
|
|
|
4486
4502
|
cleanStalePid(PID_FILE);
|
|
4487
4503
|
const entry = readPid(PID_FILE);
|
|
4488
4504
|
if (entry !== null && isProcessAlive(entry.pid)) {
|
|
4489
|
-
return { running: true, pid: entry.pid, port: entry.port ?? DEFAULT_PORT };
|
|
4505
|
+
return { running: true, pid: entry.pid, port: entry.port ?? DEFAULT_PORT, version: entry.version };
|
|
4490
4506
|
}
|
|
4491
4507
|
return { running: false };
|
|
4492
4508
|
}
|
|
4509
|
+
function isServerStale(status2) {
|
|
4510
|
+
return status2.running === true && status2.version !== "0.12.3";
|
|
4511
|
+
}
|
|
4512
|
+
async function ensureCurrentServer(opts = {}) {
|
|
4513
|
+
const status2 = getServerStatus();
|
|
4514
|
+
if (status2.running && !isServerStale(status2)) {
|
|
4515
|
+
return { pid: status2.pid, port: status2.port, restarted: false };
|
|
4516
|
+
}
|
|
4517
|
+
if (!status2.running) {
|
|
4518
|
+
const result = await startServer({ port: opts.port });
|
|
4519
|
+
return { ...result, restarted: false };
|
|
4520
|
+
}
|
|
4521
|
+
const previousVersion = status2.version;
|
|
4522
|
+
const oldPid = status2.pid;
|
|
4523
|
+
const port = opts.port ?? status2.port;
|
|
4524
|
+
stopServer();
|
|
4525
|
+
await waitForPortFree(port, 5e3);
|
|
4526
|
+
if (await checkPort(port)) {
|
|
4527
|
+
try {
|
|
4528
|
+
process.kill(oldPid, "SIGKILL");
|
|
4529
|
+
} catch {
|
|
4530
|
+
}
|
|
4531
|
+
await waitForPortFree(port, 3e3);
|
|
4532
|
+
}
|
|
4533
|
+
try {
|
|
4534
|
+
const result = await startServer({ port });
|
|
4535
|
+
return { ...result, restarted: true, previousVersion };
|
|
4536
|
+
} catch (err) {
|
|
4537
|
+
if (isProcessAlive(oldPid)) writePid(PID_FILE, oldPid, port, previousVersion);
|
|
4538
|
+
throw err;
|
|
4539
|
+
}
|
|
4540
|
+
}
|
|
4493
4541
|
async function startServer(opts = {}) {
|
|
4494
4542
|
const port = opts.port ?? (parseInt(process.env.CCLENS_PORT ?? "", 10) || DEFAULT_PORT);
|
|
4495
4543
|
const serverJs = join2(appDir(), "server.js");
|
|
@@ -4515,7 +4563,7 @@ async function startServer(opts = {}) {
|
|
|
4515
4563
|
});
|
|
4516
4564
|
child.unref();
|
|
4517
4565
|
const pid = child.pid;
|
|
4518
|
-
writePid(PID_FILE, pid, port);
|
|
4566
|
+
writePid(PID_FILE, pid, port, "0.12.3");
|
|
4519
4567
|
await waitForHealth(`http://localhost:${port}`, 1e4);
|
|
4520
4568
|
return { pid, port };
|
|
4521
4569
|
}
|
|
@@ -4543,6 +4591,13 @@ async function checkPort(port) {
|
|
|
4543
4591
|
server.listen(port, "localhost");
|
|
4544
4592
|
});
|
|
4545
4593
|
}
|
|
4594
|
+
async function waitForPortFree(port, timeoutMs) {
|
|
4595
|
+
const start2 = Date.now();
|
|
4596
|
+
while (Date.now() - start2 < timeoutMs) {
|
|
4597
|
+
if (!await checkPort(port)) return;
|
|
4598
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
4599
|
+
}
|
|
4600
|
+
}
|
|
4546
4601
|
async function waitForHealth(url, timeoutMs) {
|
|
4547
4602
|
const start2 = Date.now();
|
|
4548
4603
|
while (Date.now() - start2 < timeoutMs) {
|
|
@@ -4868,9 +4923,9 @@ Installed: ${PACKAGE_NAME}@${verify.installedVersion} at ${verify.installedPath
|
|
|
4868
4923
|
console.warn(
|
|
4869
4924
|
` \u2022 reinstall in the correct Node env: 'npm install -g ${PACKAGE_NAME}@latest'`
|
|
4870
4925
|
);
|
|
4871
|
-
} else if (verify.installedVersion !== "0.12.
|
|
4926
|
+
} else if (verify.installedVersion !== "0.12.3") {
|
|
4872
4927
|
console.log(
|
|
4873
|
-
` \u2192 This process is still running ${"0.12.
|
|
4928
|
+
` \u2192 This process is still running ${"0.12.3"}. Next invocation will use ${verify.installedVersion}.`
|
|
4874
4929
|
);
|
|
4875
4930
|
}
|
|
4876
4931
|
}
|
|
@@ -4905,14 +4960,14 @@ async function getUpdateAvailability() {
|
|
|
4905
4960
|
if (isDevMode()) return null;
|
|
4906
4961
|
const latest = await fetchLatestVersion();
|
|
4907
4962
|
if (latest === null) return {
|
|
4908
|
-
current: "0.12.
|
|
4963
|
+
current: "0.12.3",
|
|
4909
4964
|
latest: null,
|
|
4910
4965
|
updateAvailable: false
|
|
4911
4966
|
};
|
|
4912
4967
|
return {
|
|
4913
|
-
current: "0.12.
|
|
4968
|
+
current: "0.12.3",
|
|
4914
4969
|
latest,
|
|
4915
|
-
updateAvailable: shouldUpdate("0.12.
|
|
4970
|
+
updateAvailable: shouldUpdate("0.12.3", latest)
|
|
4916
4971
|
};
|
|
4917
4972
|
}
|
|
4918
4973
|
async function checkForUpdate() {
|
|
@@ -5002,7 +5057,7 @@ async function restartServices(state) {
|
|
|
5002
5057
|
}
|
|
5003
5058
|
async function forceUpdate() {
|
|
5004
5059
|
const latest = await fetchLatestVersion();
|
|
5005
|
-
const current = "0.12.
|
|
5060
|
+
const current = "0.12.3";
|
|
5006
5061
|
if (latest === null) {
|
|
5007
5062
|
console.error("Could not reach npm registry. Check your network.");
|
|
5008
5063
|
process.exit(1);
|
|
@@ -5053,24 +5108,23 @@ async function start(args2) {
|
|
|
5053
5108
|
await checkForUpdate();
|
|
5054
5109
|
} catch {
|
|
5055
5110
|
}
|
|
5056
|
-
const status2 = getServerStatus();
|
|
5057
5111
|
let serverUrl;
|
|
5058
5112
|
let serverPid;
|
|
5059
|
-
|
|
5060
|
-
serverUrl = `http://localhost:${status2.port}`;
|
|
5061
|
-
serverPid = status2.pid;
|
|
5062
|
-
console.log(`Server: already running on ${serverUrl} (PID ${serverPid})`);
|
|
5063
|
-
} else {
|
|
5113
|
+
try {
|
|
5064
5114
|
console.log("Starting Fleetlens...");
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
console.log(
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5115
|
+
const result = await ensureCurrentServer({ port });
|
|
5116
|
+
serverUrl = `http://localhost:${result.port}`;
|
|
5117
|
+
serverPid = result.pid;
|
|
5118
|
+
if (result.restarted) {
|
|
5119
|
+
console.log(
|
|
5120
|
+
`Server: restarted on ${serverUrl} (PID ${serverPid}) \u2014 replaced stale ${result.previousVersion ?? "unknown"} server`
|
|
5121
|
+
);
|
|
5122
|
+
} else {
|
|
5123
|
+
console.log(`Server: running on ${serverUrl} (PID ${serverPid})`);
|
|
5073
5124
|
}
|
|
5125
|
+
} catch (err) {
|
|
5126
|
+
console.error(`Failed to start server: ${err.message}`);
|
|
5127
|
+
process.exit(1);
|
|
5074
5128
|
}
|
|
5075
5129
|
if (!noDaemon) {
|
|
5076
5130
|
const daemon2 = startDaemonSilent();
|
|
@@ -5143,7 +5197,13 @@ async function status() {
|
|
|
5143
5197
|
const server = getServerStatus();
|
|
5144
5198
|
if (server.running) {
|
|
5145
5199
|
const url = `http://localhost:${server.port}`;
|
|
5146
|
-
|
|
5200
|
+
const ver = server.version ?? "unknown";
|
|
5201
|
+
console.log(`Server: running on ${url} (PID ${server.pid}, v${ver})`);
|
|
5202
|
+
if (isServerStale(server)) {
|
|
5203
|
+
console.log(
|
|
5204
|
+
` \u26A0 serving stale ${ver} (CLI is ${"0.12.3"}) \u2014 run 'fleetlens start' to restart on the current version`
|
|
5205
|
+
);
|
|
5206
|
+
}
|
|
5147
5207
|
} else {
|
|
5148
5208
|
console.log("Server: not running");
|
|
5149
5209
|
}
|
|
@@ -5181,31 +5241,23 @@ async function web(args2) {
|
|
|
5181
5241
|
const positional = args2.filter((a) => !a.startsWith("--"));
|
|
5182
5242
|
const rawPath = positional[0] ?? "";
|
|
5183
5243
|
const path7 = rawPath.startsWith("/") ? rawPath : rawPath ? `/${rawPath}` : "";
|
|
5184
|
-
|
|
5185
|
-
if (status2.running) {
|
|
5186
|
-
const url = `http://localhost:${status2.port}${path7}`;
|
|
5187
|
-
if (open) {
|
|
5188
|
-
console.log(`Opening ${url}`);
|
|
5189
|
-
openBrowser(url);
|
|
5190
|
-
} else {
|
|
5191
|
-
console.log(`Dashboard ready at ${url} (re-run with --open to launch it automatically).`);
|
|
5192
|
-
}
|
|
5193
|
-
return;
|
|
5194
|
-
}
|
|
5195
|
-
console.log("fleetlens is not running. Starting server...");
|
|
5244
|
+
let result;
|
|
5196
5245
|
try {
|
|
5197
|
-
|
|
5198
|
-
const url = `http://localhost:${result.port}${path7}`;
|
|
5199
|
-
console.log(`fleetlens running on ${url} (PID ${result.pid})`);
|
|
5200
|
-
if (open) {
|
|
5201
|
-
openBrowser(url);
|
|
5202
|
-
} else {
|
|
5203
|
-
console.log(`Open ${url} in your browser, or re-run with --open to launch it automatically.`);
|
|
5204
|
-
}
|
|
5246
|
+
result = await ensureCurrentServer({});
|
|
5205
5247
|
} catch (err) {
|
|
5206
5248
|
console.error(`Failed to start: ${err.message}`);
|
|
5207
5249
|
process.exit(1);
|
|
5208
5250
|
}
|
|
5251
|
+
const url = `http://localhost:${result.port}${path7}`;
|
|
5252
|
+
if (result.restarted) {
|
|
5253
|
+
console.log(`fleetlens restarted on http://localhost:${result.port} (PID ${result.pid}) \u2014 replaced stale ${result.previousVersion ?? "unknown"} server`);
|
|
5254
|
+
}
|
|
5255
|
+
if (open) {
|
|
5256
|
+
console.log(`Opening ${url}`);
|
|
5257
|
+
openBrowser(url);
|
|
5258
|
+
} else {
|
|
5259
|
+
console.log(`Dashboard ready at ${url} (re-run with --open to launch it automatically).`);
|
|
5260
|
+
}
|
|
5209
5261
|
}
|
|
5210
5262
|
var init_web = __esm({
|
|
5211
5263
|
"src/commands/web.ts"() {
|
|
@@ -5498,9 +5550,9 @@ var init_pricing = __esm({
|
|
|
5498
5550
|
function fmtNum(n) {
|
|
5499
5551
|
return n.toLocaleString("en-US");
|
|
5500
5552
|
}
|
|
5501
|
-
function fmtCost(cost) {
|
|
5553
|
+
function fmtCost(cost, partial = false) {
|
|
5502
5554
|
if (cost === null) return "\u2014";
|
|
5503
|
-
return
|
|
5555
|
+
return `${partial ? "\u2265" : ""}$${cost.toFixed(2)}`;
|
|
5504
5556
|
}
|
|
5505
5557
|
function pad(s, width, align = "right") {
|
|
5506
5558
|
if (align === "left") return s.padEnd(width);
|
|
@@ -5523,9 +5575,9 @@ function renderTable(rows, title) {
|
|
|
5523
5575
|
].join(" ");
|
|
5524
5576
|
lines.push(`${DIM2}${header}${RESET2}`);
|
|
5525
5577
|
lines.push(`${DIM2}${"\u2500".repeat(header.length)}${RESET2}`);
|
|
5526
|
-
let
|
|
5578
|
+
let costIncomplete = false;
|
|
5527
5579
|
for (const r of rows) {
|
|
5528
|
-
if (r.cost === null)
|
|
5580
|
+
if (r.cost === null || r.costPartial) costIncomplete = true;
|
|
5529
5581
|
lines.push([
|
|
5530
5582
|
pad(r.date, 12, "left"),
|
|
5531
5583
|
pad(r.models, 20, "left"),
|
|
@@ -5534,7 +5586,7 @@ function renderTable(rows, title) {
|
|
|
5534
5586
|
pad(fmtNum(r.cacheCreate), 14),
|
|
5535
5587
|
pad(fmtNum(r.cacheRead), 14),
|
|
5536
5588
|
pad(fmtNum(r.totalTokens), 14),
|
|
5537
|
-
pad(fmtCost(r.cost), 12)
|
|
5589
|
+
pad(fmtCost(r.cost, r.costPartial), 12)
|
|
5538
5590
|
].join(" "));
|
|
5539
5591
|
}
|
|
5540
5592
|
const totals = rows.reduce(
|
|
@@ -5544,9 +5596,10 @@ function renderTable(rows, title) {
|
|
|
5544
5596
|
cacheCreate: acc.cacheCreate + r.cacheCreate,
|
|
5545
5597
|
cacheRead: acc.cacheRead + r.cacheRead,
|
|
5546
5598
|
totalTokens: acc.totalTokens + r.totalTokens,
|
|
5547
|
-
cost:
|
|
5599
|
+
cost: acc.cost + (r.cost ?? 0),
|
|
5600
|
+
anyCost: acc.anyCost || r.cost !== null
|
|
5548
5601
|
}),
|
|
5549
|
-
{ input: 0, output: 0, cacheCreate: 0, cacheRead: 0, totalTokens: 0, cost: 0 }
|
|
5602
|
+
{ input: 0, output: 0, cacheCreate: 0, cacheRead: 0, totalTokens: 0, cost: 0, anyCost: false }
|
|
5550
5603
|
);
|
|
5551
5604
|
lines.push(`${DIM2}${"\u2500".repeat(header.length)}${RESET2}`);
|
|
5552
5605
|
lines.push(
|
|
@@ -5558,12 +5611,14 @@ function renderTable(rows, title) {
|
|
|
5558
5611
|
pad(fmtNum(totals.cacheCreate), 14),
|
|
5559
5612
|
pad(fmtNum(totals.cacheRead), 14),
|
|
5560
5613
|
pad(fmtNum(totals.totalTokens), 14),
|
|
5561
|
-
pad(fmtCost(totals.cost), 12)
|
|
5614
|
+
pad(totals.anyCost ? fmtCost(totals.cost, costIncomplete) : fmtCost(null), 12)
|
|
5562
5615
|
].join(" ")}${RESET2}`
|
|
5563
5616
|
);
|
|
5564
|
-
if (
|
|
5617
|
+
if (costIncomplete) {
|
|
5565
5618
|
lines.push("");
|
|
5566
|
-
lines.push(
|
|
5619
|
+
lines.push(
|
|
5620
|
+
`${DIM2} Cost covers priced usage only \u2014 "\u2014" = no priced sessions that day, "\u2265" = lower bound (some sessions had unknown pricing).${RESET2}`
|
|
5621
|
+
);
|
|
5567
5622
|
}
|
|
5568
5623
|
lines.push("");
|
|
5569
5624
|
return lines.join("\n");
|
|
@@ -5616,6 +5671,9 @@ async function printStats(sinceDate) {
|
|
|
5616
5671
|
console.log(` ${todaySessions} sessions today \xB7 ${serverLine}`);
|
|
5617
5672
|
console.log("");
|
|
5618
5673
|
}
|
|
5674
|
+
function displayModel(raw) {
|
|
5675
|
+
return raw.replace(/-\d{8}$/, "").replace(/^claude-/, "");
|
|
5676
|
+
}
|
|
5619
5677
|
function aggregateByDay(sessions) {
|
|
5620
5678
|
const byDay = /* @__PURE__ */ new Map();
|
|
5621
5679
|
for (const s of sessions) {
|
|
@@ -5623,12 +5681,14 @@ function aggregateByDay(sessions) {
|
|
|
5623
5681
|
if (!byDay.has(day2)) byDay.set(day2, { sessions: [], models: /* @__PURE__ */ new Set() });
|
|
5624
5682
|
const bucket = byDay.get(day2);
|
|
5625
5683
|
bucket.sessions.push(s);
|
|
5626
|
-
if (s.model) bucket.models.add(s.model
|
|
5684
|
+
if (s.model) bucket.models.add(displayModel(s.model));
|
|
5627
5685
|
}
|
|
5628
5686
|
const sorted = [...byDay.entries()].sort((a, b) => b[0].localeCompare(a[0]));
|
|
5629
5687
|
return sorted.map(([date, { sessions: sessions2, models }]) => {
|
|
5630
5688
|
const usage2 = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
5631
5689
|
let cost = 0;
|
|
5690
|
+
let anyPriced = false;
|
|
5691
|
+
let anyUnpriced = false;
|
|
5632
5692
|
for (const s of sessions2) {
|
|
5633
5693
|
usage2.input += s.totalUsage.input;
|
|
5634
5694
|
usage2.output += s.totalUsage.output;
|
|
@@ -5636,11 +5696,15 @@ function aggregateByDay(sessions) {
|
|
|
5636
5696
|
usage2.cacheWrite += s.totalUsage.cacheWrite;
|
|
5637
5697
|
if (s.model) {
|
|
5638
5698
|
const c = estimateCost(s.model, s.totalUsage);
|
|
5639
|
-
if (c !== null
|
|
5640
|
-
|
|
5699
|
+
if (c !== null) {
|
|
5700
|
+
cost += c;
|
|
5701
|
+
anyPriced = true;
|
|
5702
|
+
} else {
|
|
5703
|
+
anyUnpriced = true;
|
|
5704
|
+
}
|
|
5641
5705
|
}
|
|
5642
5706
|
}
|
|
5643
|
-
const modelNames = [...models].
|
|
5707
|
+
const modelNames = [...models].join(", ");
|
|
5644
5708
|
return {
|
|
5645
5709
|
date,
|
|
5646
5710
|
models: modelNames || "\u2014",
|
|
@@ -5649,7 +5713,8 @@ function aggregateByDay(sessions) {
|
|
|
5649
5713
|
cacheCreate: usage2.cacheWrite,
|
|
5650
5714
|
cacheRead: usage2.cacheRead,
|
|
5651
5715
|
totalTokens: usage2.input + usage2.output + usage2.cacheRead + usage2.cacheWrite,
|
|
5652
|
-
cost
|
|
5716
|
+
cost: anyPriced ? cost : null,
|
|
5717
|
+
costPartial: anyPriced && anyUnpriced
|
|
5653
5718
|
};
|
|
5654
5719
|
});
|
|
5655
5720
|
}
|
|
@@ -6474,6 +6539,20 @@ var init_dist2 = __esm({
|
|
|
6474
6539
|
// ../entries/dist/digest-fs.js
|
|
6475
6540
|
import { readFileSync as readFileSync7, readdirSync, writeFileSync as writeFileSync3, renameSync, chmodSync, mkdirSync as mkdirSync4, existsSync as existsSync5 } from "node:fs";
|
|
6476
6541
|
import { dirname as dirname6, join as join6 } from "node:path";
|
|
6542
|
+
function parseDigestFile(path7, expectedVersion) {
|
|
6543
|
+
try {
|
|
6544
|
+
const parsed = JSON.parse(readFileSync7(path7, "utf8"));
|
|
6545
|
+
if (!parsed || typeof parsed !== "object")
|
|
6546
|
+
return null;
|
|
6547
|
+
if (parsed.version !== expectedVersion)
|
|
6548
|
+
return null;
|
|
6549
|
+
if (!Array.isArray(parsed.shipped))
|
|
6550
|
+
return null;
|
|
6551
|
+
return parsed;
|
|
6552
|
+
} catch {
|
|
6553
|
+
return null;
|
|
6554
|
+
}
|
|
6555
|
+
}
|
|
6477
6556
|
function digestsDir() {
|
|
6478
6557
|
if (digestsDirCached)
|
|
6479
6558
|
return digestsDirCached;
|
|
@@ -6513,11 +6592,7 @@ function readDayDigest(date) {
|
|
|
6513
6592
|
const p = dayDigestPath(date);
|
|
6514
6593
|
if (!existsSync5(p))
|
|
6515
6594
|
return null;
|
|
6516
|
-
|
|
6517
|
-
return JSON.parse(readFileSync7(p, "utf8"));
|
|
6518
|
-
} catch {
|
|
6519
|
-
return null;
|
|
6520
|
-
}
|
|
6595
|
+
return parseDigestFile(p, CURRENT_DAY_DIGEST_SCHEMA_VERSION);
|
|
6521
6596
|
}
|
|
6522
6597
|
function getTodayDigestFromCache(date, nowMs) {
|
|
6523
6598
|
if (!todayCache)
|
|
@@ -6553,11 +6628,7 @@ function readWeekDigest(monday) {
|
|
|
6553
6628
|
const p = weekDigestPath(monday);
|
|
6554
6629
|
if (!existsSync5(p))
|
|
6555
6630
|
return null;
|
|
6556
|
-
|
|
6557
|
-
return JSON.parse(readFileSync7(p, "utf8"));
|
|
6558
|
-
} catch {
|
|
6559
|
-
return null;
|
|
6560
|
-
}
|
|
6631
|
+
return parseDigestFile(p, CURRENT_WEEK_DIGEST_SCHEMA_VERSION);
|
|
6561
6632
|
}
|
|
6562
6633
|
function listWeekDigestKeys() {
|
|
6563
6634
|
const dir = join6(digestsDir(), "week");
|
|
@@ -6594,11 +6665,7 @@ function readMonthDigest(yearMonth) {
|
|
|
6594
6665
|
const p = monthDigestPath(yearMonth);
|
|
6595
6666
|
if (!existsSync5(p))
|
|
6596
6667
|
return null;
|
|
6597
|
-
|
|
6598
|
-
return JSON.parse(readFileSync7(p, "utf8"));
|
|
6599
|
-
} catch {
|
|
6600
|
-
return null;
|
|
6601
|
-
}
|
|
6668
|
+
return parseDigestFile(p, CURRENT_MONTH_DIGEST_SCHEMA_VERSION);
|
|
6602
6669
|
}
|
|
6603
6670
|
function listMonthDigestKeys() {
|
|
6604
6671
|
const dir = join6(digestsDir(), "month");
|
|
@@ -6623,6 +6690,7 @@ var init_digest_fs = __esm({
|
|
|
6623
6690
|
"../entries/dist/digest-fs.js"() {
|
|
6624
6691
|
"use strict";
|
|
6625
6692
|
init_fs();
|
|
6693
|
+
init_types();
|
|
6626
6694
|
digestsDirCached = null;
|
|
6627
6695
|
TODAY_TTL_MS = 10 * 60 * 1e3;
|
|
6628
6696
|
todayCache = null;
|
|
@@ -17626,7 +17694,7 @@ async function main() {
|
|
|
17626
17694
|
case "version":
|
|
17627
17695
|
case "--version":
|
|
17628
17696
|
case "-v":
|
|
17629
|
-
console.log(`fleetlens ${"0.12.
|
|
17697
|
+
console.log(`fleetlens ${"0.12.3"}`);
|
|
17630
17698
|
break;
|
|
17631
17699
|
case "help":
|
|
17632
17700
|
case "--help":
|