fleetlens 0.10.0 → 0.10.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 +2 -2
- package/app/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/api/ask/route.js +4 -3
- 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 +3 -4
- 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 +3 -4
- 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 +3 -3
- 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 +3 -4
- 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 +3 -3
- 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 +2 -3
- 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 +1 -1
- package/app/apps/web/.next/server/app/api/jobs/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/runs/[runId]/route.js +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 +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 +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/route.js +3 -4
- package/app/apps/web/.next/server/app/api/settings/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/changelog/page.js +2 -2
- 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 +2 -2
- 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 +2 -2
- 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 +2 -2
- 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 +2 -2
- 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 +2 -2
- 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 +2 -2
- 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 +2 -2
- 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 +2 -2
- package/app/apps/web/.next/server/app/parallelism/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/parallelism/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/projects/[slug]/page.js +2 -2
- 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 +2 -2
- 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 +2 -2
- 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 +2 -2
- 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 +2 -2
- 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 +2 -2
- package/app/apps/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/usage/page.js +2 -2
- 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/[externals]__09v47rg._.js +3 -0
- package/app/apps/web/.next/server/chunks/[externals]__0o43ejh._.js +3 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__00n3f9y._.js +1 -1
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__02px2mk._.js +3 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__02zukjw._.js +1 -1
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0455vu3._.js +5 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__067~im1._.js +2 -2
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__06b4cj-._.js +1 -1
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__08agijy._.js +3 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0_8zh-i._.js +9 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0ej_p3s._.js +9 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0i06ito._.js +3 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0jprdks._.js +9 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0vm_41a._.js +3 -0
- package/app/apps/web/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0ck.78s.js +4 -4
- package/app/apps/web/.next/server/chunks/packages_0c-sz9n._.js +3 -0
- package/app/apps/web/.next/server/chunks/packages_0wywuu.._.js +3 -0
- package/app/apps/web/.next/server/chunks/packages_entries_dist_node_0bckr7-.js +27 -13
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0r4tks8._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0s4dg1y._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0w52fbc._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0yv0m0q._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/_0xu2pvc._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0txtsv5._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_0m67-xi._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/packages_entries_dist_node_0_271yr.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_12.endt._.js +3 -0
- package/app/apps/web/.next/server/middleware-build-manifest.js +3 -3
- 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/{09--oejbzw3q-.js → 0g8ujtb0lp._9.js} +1 -1
- package/app/apps/web/.next/static/chunks/0~n2a9f52wju9.js +14 -0
- package/app/apps/web/app/api/ask/route.ts +124 -111
- package/app/apps/web/app/api/events/route.ts +3 -4
- package/app/apps/web/app/api/runs/[runId]/route.ts +2 -2
- package/app/apps/web/app/api/runs/[runId]/stream/route.ts +3 -2
- package/app/apps/web/app/api/runs/route.ts +8 -4
- package/app/apps/web/app/sessions/[id]/session-view.tsx +31 -0
- package/app/apps/web/components/job-queue-widget.tsx +11 -8
- package/app/apps/web/lib/calibration-data.ts +2 -4
- package/app/apps/web/lib/changelog-data.generated.ts +1 -1
- package/app/apps/web/lib/entries-index.ts +2 -2
- package/app/apps/web/lib/jobs.ts +3 -5
- package/app/apps/web/lib/usage-data.ts +3 -4
- package/app/apps/web/package.json +1 -1
- package/app/apps/web/tsconfig.tsbuildinfo +1 -1
- package/dist/daemon-worker.js +476 -79
- package/dist/index.js +4368 -3959
- package/package.json +1 -1
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__07qxzx4._.js +0 -9
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0fu2xfy._.js +0 -5
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0gfd42k._.js +0 -9
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0i.m8y0._.js +0 -3
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0iy5aqy._.js +0 -9
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0nh7-nf._.js +0 -3
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0nvdffv._.js +0 -3
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0op9af~._.js +0 -3
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0s2~c3g._.js +0 -3
- package/app/apps/web/.next/server/chunks/packages_09wmnv.._.js +0 -3
- package/app/apps/web/.next/server/chunks/packages_0o6.gpk._.js +0 -3
- package/app/apps/web/.next/server/chunks/packages_parser_dist_fs_122oe0-.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0sp6.jt._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_10_oegc._.js +0 -3
- package/app/apps/web/.next/static/chunks/0qcu452dr~edz.js +0 -14
- /package/app/apps/web/.next/static/{L0Dy1hOQrZjV9l0TNulvk → sxcMbKfZ5XgVXYN4QHOHd}/_buildManifest.js +0 -0
- /package/app/apps/web/.next/static/{L0Dy1hOQrZjV9l0TNulvk → sxcMbKfZ5XgVXYN4QHOHd}/_clientMiddlewareManifest.js +0 -0
- /package/app/apps/web/.next/static/{L0Dy1hOQrZjV9l0TNulvk → sxcMbKfZ5XgVXYN4QHOHd}/_ssgManifest.js +0 -0
package/dist/daemon-worker.js
CHANGED
|
@@ -1152,6 +1152,7 @@ function parseTranscript(rawLines) {
|
|
|
1152
1152
|
let sessionId = "";
|
|
1153
1153
|
let cwd;
|
|
1154
1154
|
let gitBranch;
|
|
1155
|
+
let entrypoint;
|
|
1155
1156
|
let teamName;
|
|
1156
1157
|
let agentName;
|
|
1157
1158
|
let hasTeamCreate = false;
|
|
@@ -1220,6 +1221,8 @@ function parseTranscript(rawLines) {
|
|
|
1220
1221
|
cwd = o.cwd;
|
|
1221
1222
|
if (typeof o.gitBranch === "string" && !gitBranch)
|
|
1222
1223
|
gitBranch = o.gitBranch;
|
|
1224
|
+
if (typeof o.entrypoint === "string" && !entrypoint)
|
|
1225
|
+
entrypoint = o.entrypoint;
|
|
1223
1226
|
if (typeof o.teamName === "string" && !teamName)
|
|
1224
1227
|
teamName = o.teamName;
|
|
1225
1228
|
if (typeof o.agentName === "string" && !agentName)
|
|
@@ -1257,6 +1260,7 @@ function parseTranscript(rawLines) {
|
|
|
1257
1260
|
model,
|
|
1258
1261
|
cwd,
|
|
1259
1262
|
gitBranch,
|
|
1263
|
+
entrypoint,
|
|
1260
1264
|
totalUsage,
|
|
1261
1265
|
status: "idle",
|
|
1262
1266
|
firstUserPreview,
|
|
@@ -2937,6 +2941,8 @@ __export(fs_exports, {
|
|
|
2937
2941
|
agentSources: () => agentSources,
|
|
2938
2942
|
buildCalibrationCurve: () => buildCalibrationCurve,
|
|
2939
2943
|
cacheStats: () => cacheStats,
|
|
2944
|
+
cclensHome: () => cclensHome,
|
|
2945
|
+
cclensPath: () => cclensPath,
|
|
2940
2946
|
clearCaches: () => clearCaches,
|
|
2941
2947
|
codexSessionLocalDay: () => codexSessionLocalDay,
|
|
2942
2948
|
decodeProjectName: () => decodeProjectName,
|
|
@@ -2966,6 +2972,12 @@ __export(fs_exports, {
|
|
|
2966
2972
|
import { promises as fs4 } from "node:fs";
|
|
2967
2973
|
import os4 from "node:os";
|
|
2968
2974
|
import path4 from "node:path";
|
|
2975
|
+
function cclensHome() {
|
|
2976
|
+
return process.env.CCLENS_HOME || path4.join(os4.homedir(), ".cclens");
|
|
2977
|
+
}
|
|
2978
|
+
function cclensPath(...parts) {
|
|
2979
|
+
return path4.join(cclensHome(), ...parts);
|
|
2980
|
+
}
|
|
2969
2981
|
function cacheStats() {
|
|
2970
2982
|
return claudeCodeCacheStats();
|
|
2971
2983
|
}
|
|
@@ -2998,10 +3010,13 @@ async function getAnySession(id) {
|
|
|
2998
3010
|
}
|
|
2999
3011
|
return null;
|
|
3000
3012
|
}
|
|
3013
|
+
function usageLogPath() {
|
|
3014
|
+
return cclensPath("usage.jsonl");
|
|
3015
|
+
}
|
|
3001
3016
|
async function loadUsageByDay(start, end) {
|
|
3002
3017
|
let raw;
|
|
3003
3018
|
try {
|
|
3004
|
-
raw = await fs4.readFile(
|
|
3019
|
+
raw = await fs4.readFile(usageLogPath(), "utf8");
|
|
3005
3020
|
} catch {
|
|
3006
3021
|
return { by_day: [] };
|
|
3007
3022
|
}
|
|
@@ -3046,7 +3061,7 @@ async function loadUsageByDay(start, end) {
|
|
|
3046
3061
|
async function loadCalibrationSnapshots() {
|
|
3047
3062
|
let raw;
|
|
3048
3063
|
try {
|
|
3049
|
-
raw = await fs4.readFile(
|
|
3064
|
+
raw = await fs4.readFile(usageLogPath(), "utf8");
|
|
3050
3065
|
} catch {
|
|
3051
3066
|
return [];
|
|
3052
3067
|
}
|
|
@@ -3204,7 +3219,7 @@ async function loadCalibrationCurve(tier = "pro-max-20x", root = DEFAULT_ROOT, g
|
|
|
3204
3219
|
]);
|
|
3205
3220
|
return buildCalibrationCurve(events, snapshots, tier, granularityMin);
|
|
3206
3221
|
}
|
|
3207
|
-
var codexSource, geminiSource, agentSources
|
|
3222
|
+
var codexSource, geminiSource, agentSources;
|
|
3208
3223
|
var init_fs = __esm({
|
|
3209
3224
|
"../parser/dist/fs.js"() {
|
|
3210
3225
|
"use strict";
|
|
@@ -3249,7 +3264,6 @@ var init_fs = __esm({
|
|
|
3249
3264
|
}
|
|
3250
3265
|
};
|
|
3251
3266
|
agentSources = [claudeCodeSource, codexSource, geminiSource];
|
|
3252
|
-
USAGE_LOG = path4.join(os4.homedir(), ".cclens", "usage.jsonl");
|
|
3253
3267
|
}
|
|
3254
3268
|
});
|
|
3255
3269
|
|
|
@@ -3725,9 +3739,8 @@ var init_dist = __esm({
|
|
|
3725
3739
|
});
|
|
3726
3740
|
|
|
3727
3741
|
// src/daemon-worker.ts
|
|
3728
|
-
import { appendFileSync as appendFileSync5, mkdirSync as
|
|
3729
|
-
import { dirname as
|
|
3730
|
-
import { homedir as homedir13 } from "node:os";
|
|
3742
|
+
import { appendFileSync as appendFileSync5, mkdirSync as mkdirSync12 } from "node:fs";
|
|
3743
|
+
import { dirname as dirname8 } from "node:path";
|
|
3731
3744
|
|
|
3732
3745
|
// src/usage/token.ts
|
|
3733
3746
|
import { execFileSync } from "node:child_process";
|
|
@@ -3908,26 +3921,23 @@ function nextIntervalMs(current, outcome) {
|
|
|
3908
3921
|
return Math.min(Math.max(current, BASE_INTERVAL_MS) * 2, MAX_INTERVAL_MS);
|
|
3909
3922
|
}
|
|
3910
3923
|
|
|
3911
|
-
// src/team/sync.ts
|
|
3912
|
-
import { homedir as homedir4 } from "node:os";
|
|
3913
|
-
import { join as join4 } from "node:path";
|
|
3914
|
-
|
|
3915
3924
|
// src/team/config.ts
|
|
3925
|
+
init_fs();
|
|
3916
3926
|
import { readFileSync as readFileSync3, writeFileSync, unlinkSync, mkdirSync as mkdirSync2 } from "node:fs";
|
|
3917
3927
|
import { join as join2 } from "node:path";
|
|
3918
|
-
import { homedir as homedir2 } from "node:os";
|
|
3919
|
-
var DEFAULT_DIR = join2(homedir2(), ".cclens");
|
|
3920
3928
|
var CONFIG_FILE = "team.json";
|
|
3921
|
-
function readTeamConfig(dir
|
|
3929
|
+
function readTeamConfig(dir) {
|
|
3930
|
+
const d = dir ?? cclensHome();
|
|
3922
3931
|
try {
|
|
3923
|
-
return JSON.parse(readFileSync3(join2(
|
|
3932
|
+
return JSON.parse(readFileSync3(join2(d, CONFIG_FILE), "utf8"));
|
|
3924
3933
|
} catch {
|
|
3925
3934
|
return null;
|
|
3926
3935
|
}
|
|
3927
3936
|
}
|
|
3928
|
-
function writeTeamConfig(config, dir
|
|
3929
|
-
|
|
3930
|
-
|
|
3937
|
+
function writeTeamConfig(config, dir) {
|
|
3938
|
+
const d = dir ?? cclensHome();
|
|
3939
|
+
mkdirSync2(d, { recursive: true });
|
|
3940
|
+
writeFileSync(join2(d, CONFIG_FILE), JSON.stringify(config, null, 2), { mode: 384 });
|
|
3931
3941
|
}
|
|
3932
3942
|
|
|
3933
3943
|
// src/team/push.ts
|
|
@@ -4003,10 +4013,10 @@ async function pushToTeamServer(config, payload) {
|
|
|
4003
4013
|
}
|
|
4004
4014
|
|
|
4005
4015
|
// src/team/queue.ts
|
|
4016
|
+
init_fs();
|
|
4006
4017
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, appendFileSync as appendFileSync2, statSync, mkdirSync as mkdirSync3 } from "node:fs";
|
|
4007
|
-
import {
|
|
4008
|
-
|
|
4009
|
-
var QUEUE_PATH = join3(homedir3(), ".cclens", "ingest-queue.jsonl");
|
|
4018
|
+
import { dirname as dirname2 } from "node:path";
|
|
4019
|
+
var QUEUE_PATH = cclensPath("ingest-queue.jsonl");
|
|
4010
4020
|
var MAX_SIZE_BYTES = 10 * 1024 * 1024;
|
|
4011
4021
|
var MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
4012
4022
|
function enqueuePayload(payload, queuePath = QUEUE_PATH) {
|
|
@@ -4129,8 +4139,9 @@ async function getPlanTier(cachePath, nowMs = Date.now(), fetcher = fetchProfile
|
|
|
4129
4139
|
}
|
|
4130
4140
|
|
|
4131
4141
|
// src/team/sync.ts
|
|
4132
|
-
|
|
4133
|
-
var
|
|
4142
|
+
init_fs();
|
|
4143
|
+
var USAGE_LOG = cclensPath("usage.jsonl");
|
|
4144
|
+
var PROFILE_CACHE = cclensPath("profile.json");
|
|
4134
4145
|
var noopLog = () => {
|
|
4135
4146
|
};
|
|
4136
4147
|
async function runTeamSync(log3 = noopLog, configOverride) {
|
|
@@ -4142,7 +4153,7 @@ async function runTeamSync(log3 = noopLog, configOverride) {
|
|
|
4142
4153
|
const today = toLocalDay3(Date.now());
|
|
4143
4154
|
const sessions = await listSessions2({ limit: 1e4 });
|
|
4144
4155
|
const rollups = buildRollupsForRange(sessions, config.lastSyncedDay);
|
|
4145
|
-
const usageSnapshot = readLatestUsageSnapshotForWire(
|
|
4156
|
+
const usageSnapshot = readLatestUsageSnapshotForWire(USAGE_LOG) ?? void 0;
|
|
4146
4157
|
const planTier = await getPlanTier(PROFILE_CACHE).catch(() => null) ?? void 0;
|
|
4147
4158
|
const cyclePeaks = await buildCyclePeaksForPush(planTier, loadCalibrationCurve2);
|
|
4148
4159
|
if (rollups.length === 0) {
|
|
@@ -5057,28 +5068,28 @@ function buildEntries(sessionDetail) {
|
|
|
5057
5068
|
}
|
|
5058
5069
|
|
|
5059
5070
|
// ../entries/dist/fs.js
|
|
5071
|
+
init_fs();
|
|
5060
5072
|
import { readFileSync as readFileSync7, readdirSync as readdirSync2, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, renameSync as renameSync2, existsSync as existsSync4 } from "node:fs";
|
|
5061
5073
|
import { randomBytes } from "node:crypto";
|
|
5062
|
-
import { join as
|
|
5063
|
-
import { homedir as homedir6 } from "node:os";
|
|
5074
|
+
import { join as join4 } from "node:path";
|
|
5064
5075
|
|
|
5065
5076
|
// ../entries/dist/digest-fs.js
|
|
5077
|
+
init_fs();
|
|
5066
5078
|
import { readFileSync as readFileSync6, readdirSync, writeFileSync as writeFileSync4, renameSync, chmodSync, mkdirSync as mkdirSync5, existsSync as existsSync3 } from "node:fs";
|
|
5067
|
-
import { dirname as dirname4, join as
|
|
5068
|
-
import { homedir as homedir5 } from "node:os";
|
|
5079
|
+
import { dirname as dirname4, join as join3 } from "node:path";
|
|
5069
5080
|
var digestsDirCached = null;
|
|
5070
5081
|
function digestsDir() {
|
|
5071
5082
|
if (digestsDirCached)
|
|
5072
5083
|
return digestsDirCached;
|
|
5073
5084
|
const envOverride = process.env.CCLENS_DIGESTS_DIR;
|
|
5074
|
-
digestsDirCached = envOverride ??
|
|
5085
|
+
digestsDirCached = envOverride ?? cclensPath("digests");
|
|
5075
5086
|
return digestsDirCached;
|
|
5076
5087
|
}
|
|
5077
5088
|
function dayDigestPath(date) {
|
|
5078
|
-
return
|
|
5089
|
+
return join3(digestsDir(), "day", `${date}.json`);
|
|
5079
5090
|
}
|
|
5080
5091
|
function weekDigestPath(monday) {
|
|
5081
|
-
return
|
|
5092
|
+
return join3(digestsDir(), "week", `${monday}.json`);
|
|
5082
5093
|
}
|
|
5083
5094
|
function writeDayDigest(digest) {
|
|
5084
5095
|
const final = dayDigestPath(digest.key);
|
|
@@ -5162,11 +5173,11 @@ function entriesDir() {
|
|
|
5162
5173
|
if (entriesDirCached)
|
|
5163
5174
|
return entriesDirCached;
|
|
5164
5175
|
const envOverride = process.env.CCLENS_ENTRIES_DIR;
|
|
5165
|
-
entriesDirCached = envOverride ??
|
|
5176
|
+
entriesDirCached = envOverride ?? cclensPath("entries");
|
|
5166
5177
|
return entriesDirCached;
|
|
5167
5178
|
}
|
|
5168
5179
|
function pathFor(sessionId, localDay) {
|
|
5169
|
-
return
|
|
5180
|
+
return join4(entriesDir(), `${entryKey(sessionId, localDay)}.json`);
|
|
5170
5181
|
}
|
|
5171
5182
|
function tmpPathFor(final) {
|
|
5172
5183
|
return `${final}.tmp.${process.pid}.${randomBytes(4).toString("hex")}`;
|
|
@@ -5239,14 +5250,14 @@ function listEntriesForDay(localDay) {
|
|
|
5239
5250
|
}
|
|
5240
5251
|
|
|
5241
5252
|
// src/perception/state.ts
|
|
5253
|
+
init_fs();
|
|
5242
5254
|
import { existsSync as existsSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync6, mkdirSync as mkdirSync7, renameSync as renameSync3 } from "node:fs";
|
|
5243
|
-
import { dirname as dirname5
|
|
5244
|
-
import { homedir as homedir7 } from "node:os";
|
|
5255
|
+
import { dirname as dirname5 } from "node:path";
|
|
5245
5256
|
var STALE_MS = 15 * 60 * 1e3;
|
|
5246
5257
|
var pathCached = null;
|
|
5247
5258
|
function statePath() {
|
|
5248
5259
|
if (pathCached) return pathCached;
|
|
5249
|
-
pathCached =
|
|
5260
|
+
pathCached = cclensPath("perception-state.json");
|
|
5250
5261
|
return pathCached;
|
|
5251
5262
|
}
|
|
5252
5263
|
function readState() {
|
|
@@ -5296,17 +5307,17 @@ function updateCheckpoint(jsonlPath, cp) {
|
|
|
5296
5307
|
|
|
5297
5308
|
// src/perception/scan.ts
|
|
5298
5309
|
import { readdirSync as readdirSync3 } from "node:fs";
|
|
5299
|
-
import { join as
|
|
5300
|
-
import { homedir as
|
|
5310
|
+
import { join as join5 } from "node:path";
|
|
5311
|
+
import { homedir as homedir2 } from "node:os";
|
|
5301
5312
|
async function listAllSessionJsonls(root) {
|
|
5302
|
-
const projectsRoot = root ??
|
|
5313
|
+
const projectsRoot = root ?? join5(homedir2(), ".claude", "projects");
|
|
5303
5314
|
const out = [];
|
|
5304
5315
|
try {
|
|
5305
5316
|
for (const project of readdirSync3(projectsRoot)) {
|
|
5306
|
-
const dir =
|
|
5317
|
+
const dir = join5(projectsRoot, project);
|
|
5307
5318
|
try {
|
|
5308
5319
|
for (const f of readdirSync3(dir)) {
|
|
5309
|
-
if (f.endsWith(".jsonl")) out.push(
|
|
5320
|
+
if (f.endsWith(".jsonl")) out.push(join5(dir, f));
|
|
5310
5321
|
}
|
|
5311
5322
|
} catch {
|
|
5312
5323
|
}
|
|
@@ -9547,16 +9558,332 @@ ${turns || "(none \u2014 the user text was filtered out as non-human)"}`;
|
|
|
9547
9558
|
var ENRICHMENT_SYSTEM_PROMPT = SYSTEM_PROMPT;
|
|
9548
9559
|
|
|
9549
9560
|
// ../entries/dist/llm-runner.js
|
|
9561
|
+
init_fs();
|
|
9550
9562
|
import { spawn } from "node:child_process";
|
|
9551
|
-
import { mkdirSync as
|
|
9552
|
-
import {
|
|
9553
|
-
import { join as join9 } from "node:path";
|
|
9563
|
+
import { mkdirSync as mkdirSync9, appendFileSync as appendFileSync3, writeFileSync as writeFileSync8, existsSync as existsSync7 } from "node:fs";
|
|
9564
|
+
import { join as join7 } from "node:path";
|
|
9554
9565
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
9555
|
-
|
|
9566
|
+
|
|
9567
|
+
// ../entries/dist/tmux-runner.js
|
|
9568
|
+
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync7, existsSync as existsSync6, readdirSync as readdirSync4, realpathSync, readFileSync as readFileSync10, unlinkSync as unlinkSync2, renameSync as renameSync4 } from "node:fs";
|
|
9569
|
+
import { join as join6 } from "node:path";
|
|
9570
|
+
import { homedir as homedir3 } from "node:os";
|
|
9571
|
+
import { spawnSync } from "node:child_process";
|
|
9572
|
+
var TmuxUnavailableError = class extends Error {
|
|
9573
|
+
constructor(message) {
|
|
9574
|
+
super(message);
|
|
9575
|
+
this.name = "TmuxUnavailableError";
|
|
9576
|
+
}
|
|
9577
|
+
};
|
|
9578
|
+
var TmuxRunError = class extends Error {
|
|
9579
|
+
constructor(message) {
|
|
9580
|
+
super(message);
|
|
9581
|
+
this.name = "TmuxRunError";
|
|
9582
|
+
}
|
|
9583
|
+
};
|
|
9584
|
+
function which(bin) {
|
|
9585
|
+
const r = spawnSync("/usr/bin/env", ["which", bin], { encoding: "utf8" });
|
|
9586
|
+
if (r.status === 0)
|
|
9587
|
+
return r.stdout.trim() || void 0;
|
|
9588
|
+
return void 0;
|
|
9589
|
+
}
|
|
9590
|
+
function tmuxRunnerAvailable() {
|
|
9591
|
+
if (!which("tmux"))
|
|
9592
|
+
return { ok: false, reason: "tmux not on PATH" };
|
|
9593
|
+
if (!which("claude"))
|
|
9594
|
+
return { ok: false, reason: "claude not on PATH" };
|
|
9595
|
+
return { ok: true };
|
|
9596
|
+
}
|
|
9597
|
+
function runtimeCwd() {
|
|
9598
|
+
const dir = join6(homedir3(), ".cclens", "runtime");
|
|
9599
|
+
if (!existsSync6(dir))
|
|
9600
|
+
mkdirSync8(dir, { recursive: true });
|
|
9601
|
+
return realpathSync(dir);
|
|
9602
|
+
}
|
|
9603
|
+
function ensureRuntimeCwdTrusted(cwd) {
|
|
9604
|
+
const cfgPath = join6(homedir3(), ".claude.json");
|
|
9605
|
+
let cfg;
|
|
9606
|
+
try {
|
|
9607
|
+
cfg = JSON.parse(readFileSync10(cfgPath, "utf8"));
|
|
9608
|
+
} catch {
|
|
9609
|
+
return;
|
|
9610
|
+
}
|
|
9611
|
+
const projects = cfg.projects ?? {};
|
|
9612
|
+
const cur = projects[cwd];
|
|
9613
|
+
if (cur && cur.hasTrustDialogAccepted === true)
|
|
9614
|
+
return;
|
|
9615
|
+
projects[cwd] = {
|
|
9616
|
+
...cur ?? {},
|
|
9617
|
+
hasTrustDialogAccepted: true
|
|
9618
|
+
};
|
|
9619
|
+
cfg.projects = projects;
|
|
9620
|
+
const tmp = `${cfgPath}.cclens-tmp-${process.pid}`;
|
|
9621
|
+
try {
|
|
9622
|
+
writeFileSync7(tmp, JSON.stringify(cfg, null, 2));
|
|
9623
|
+
renameSync4(tmp, cfgPath);
|
|
9624
|
+
} catch {
|
|
9625
|
+
try {
|
|
9626
|
+
unlinkSync2(tmp);
|
|
9627
|
+
} catch {
|
|
9628
|
+
}
|
|
9629
|
+
}
|
|
9630
|
+
}
|
|
9631
|
+
var mutex = Promise.resolve();
|
|
9632
|
+
function runClaudeUnderTmux(args) {
|
|
9633
|
+
const next = mutex.then(() => runClaudeUnderTmuxImpl(args));
|
|
9634
|
+
mutex = next.catch(() => void 0);
|
|
9635
|
+
return next;
|
|
9636
|
+
}
|
|
9637
|
+
async function runClaudeUnderTmuxImpl(args) {
|
|
9638
|
+
const tmuxBin = args.tmuxBin ?? which("tmux");
|
|
9639
|
+
if (!tmuxBin)
|
|
9640
|
+
throw new TmuxUnavailableError("tmux not on PATH");
|
|
9641
|
+
const claudeBin = args.claudeBin ?? which("claude");
|
|
9642
|
+
if (!claudeBin)
|
|
9643
|
+
throw new TmuxUnavailableError("claude not on PATH");
|
|
9644
|
+
if (args.signal?.aborted)
|
|
9645
|
+
throw new TmuxRunError("aborted before spawn");
|
|
9646
|
+
const cwd = runtimeCwd();
|
|
9647
|
+
ensureRuntimeCwdTrusted(cwd);
|
|
9648
|
+
const runId = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
9649
|
+
const sessionName = `cclens-${runId}`;
|
|
9650
|
+
const systemFile = join6(cwd, `system-${runId}.txt`);
|
|
9651
|
+
const userFile = join6(cwd, `user-${runId}.txt`);
|
|
9652
|
+
const wrapper = join6(cwd, `run-${runId}.sh`);
|
|
9653
|
+
writeFileSync7(systemFile, args.systemPrompt);
|
|
9654
|
+
writeFileSync7(userFile, args.reminder ? `${args.userPrompt}
|
|
9655
|
+
|
|
9656
|
+
---
|
|
9657
|
+
|
|
9658
|
+
${args.reminder}` : args.userPrompt);
|
|
9659
|
+
writeFileSync7(wrapper, `#!/bin/bash
|
|
9660
|
+
SYS="$(cat ${shellEscape(systemFile)})"
|
|
9661
|
+
USR="$(cat ${shellEscape(userFile)})"
|
|
9662
|
+
exec ${shellEscape(claudeBin)} \\
|
|
9663
|
+
--model ${shellEscape(args.model)} \\
|
|
9664
|
+
--strict-mcp-config --mcp-config '{"mcpServers":{}}' \\
|
|
9665
|
+
--disable-slash-commands \\
|
|
9666
|
+
--effort medium \\
|
|
9667
|
+
--append-system-prompt "$SYS" \\
|
|
9668
|
+
"$USR"
|
|
9669
|
+
`, { mode: 493 });
|
|
9670
|
+
const existingBefore = snapshotAllTranscripts();
|
|
9671
|
+
const spawn2 = spawnSync(tmuxBin, ["new-session", "-d", "-s", sessionName, "-x", "140", "-y", "50", "-c", cwd, wrapper], { encoding: "utf8" });
|
|
9672
|
+
if (spawn2.status !== 0) {
|
|
9673
|
+
cleanup(cwd, runId, tmuxBin, sessionName);
|
|
9674
|
+
throw new TmuxRunError(`tmux new-session failed: ${spawn2.stderr.trim()}`);
|
|
9675
|
+
}
|
|
9676
|
+
const onAbort = () => {
|
|
9677
|
+
try {
|
|
9678
|
+
spawnSync(tmuxBin, ["kill-session", "-t", sessionName], { stdio: "ignore" });
|
|
9679
|
+
} catch {
|
|
9680
|
+
}
|
|
9681
|
+
};
|
|
9682
|
+
args.signal?.addEventListener("abort", onAbort, { once: true });
|
|
9683
|
+
const startMs = Date.now();
|
|
9684
|
+
const timeoutMs = args.timeoutMs ?? 12e4;
|
|
9685
|
+
let lastReportedKb = -1;
|
|
9686
|
+
let lastEmittedLength = 0;
|
|
9687
|
+
try {
|
|
9688
|
+
const transcriptPath = await discoverTranscript(cwd, existingBefore, startMs, timeoutMs, args.signal);
|
|
9689
|
+
while (Date.now() - startMs < timeoutMs) {
|
|
9690
|
+
if (args.signal?.aborted)
|
|
9691
|
+
throw new TmuxRunError("aborted");
|
|
9692
|
+
const { assembled, inputTokens, outputTokens, modelUsed, done } = parseTranscript2(transcriptPath, args.model);
|
|
9693
|
+
if (args.onProgress) {
|
|
9694
|
+
const kb = Math.floor(assembled.length / 1024);
|
|
9695
|
+
if (kb > lastReportedKb) {
|
|
9696
|
+
lastReportedKb = kb;
|
|
9697
|
+
args.onProgress({ bytes: assembled.length, elapsedMs: Date.now() - startMs });
|
|
9698
|
+
}
|
|
9699
|
+
}
|
|
9700
|
+
if (args.onDelta && assembled.length > lastEmittedLength) {
|
|
9701
|
+
const chunk = assembled.slice(lastEmittedLength);
|
|
9702
|
+
lastEmittedLength = assembled.length;
|
|
9703
|
+
try {
|
|
9704
|
+
args.onDelta(chunk);
|
|
9705
|
+
} catch {
|
|
9706
|
+
}
|
|
9707
|
+
}
|
|
9708
|
+
if (done && assembled.length > 0) {
|
|
9709
|
+
return {
|
|
9710
|
+
content: assembled,
|
|
9711
|
+
input_tokens: inputTokens,
|
|
9712
|
+
output_tokens: outputTokens,
|
|
9713
|
+
model: modelUsed
|
|
9714
|
+
};
|
|
9715
|
+
}
|
|
9716
|
+
await sleep(500);
|
|
9717
|
+
}
|
|
9718
|
+
throw new TmuxRunError(`timeout after ${timeoutMs}ms waiting for assistant turn`);
|
|
9719
|
+
} finally {
|
|
9720
|
+
args.signal?.removeEventListener("abort", onAbort);
|
|
9721
|
+
cleanup(cwd, runId, tmuxBin, sessionName);
|
|
9722
|
+
}
|
|
9723
|
+
}
|
|
9724
|
+
function num(v) {
|
|
9725
|
+
return typeof v === "number" ? v : 0;
|
|
9726
|
+
}
|
|
9727
|
+
function sleep(ms) {
|
|
9728
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
9729
|
+
}
|
|
9730
|
+
var PROJECTS_ROOT = () => join6(homedir3(), ".claude", "projects");
|
|
9731
|
+
function snapshotAllTranscripts() {
|
|
9732
|
+
const out = /* @__PURE__ */ new Set();
|
|
9733
|
+
const root = PROJECTS_ROOT();
|
|
9734
|
+
let subs;
|
|
9735
|
+
try {
|
|
9736
|
+
subs = readdirSync4(root);
|
|
9737
|
+
} catch {
|
|
9738
|
+
return out;
|
|
9739
|
+
}
|
|
9740
|
+
for (const sub of subs) {
|
|
9741
|
+
const dir = join6(root, sub);
|
|
9742
|
+
let files;
|
|
9743
|
+
try {
|
|
9744
|
+
files = readdirSync4(dir);
|
|
9745
|
+
} catch {
|
|
9746
|
+
continue;
|
|
9747
|
+
}
|
|
9748
|
+
for (const f of files) {
|
|
9749
|
+
if (f.endsWith(".jsonl"))
|
|
9750
|
+
out.add(join6(dir, f));
|
|
9751
|
+
}
|
|
9752
|
+
}
|
|
9753
|
+
return out;
|
|
9754
|
+
}
|
|
9755
|
+
function readJsonlCwd(path5, maxLines = 8) {
|
|
9756
|
+
let raw;
|
|
9757
|
+
try {
|
|
9758
|
+
raw = readFileSync10(path5, "utf8");
|
|
9759
|
+
} catch {
|
|
9760
|
+
return void 0;
|
|
9761
|
+
}
|
|
9762
|
+
let count = 0;
|
|
9763
|
+
for (const line of raw.split("\n")) {
|
|
9764
|
+
const t = line.trim();
|
|
9765
|
+
if (!t)
|
|
9766
|
+
continue;
|
|
9767
|
+
count++;
|
|
9768
|
+
try {
|
|
9769
|
+
const o = JSON.parse(t);
|
|
9770
|
+
if (typeof o.cwd === "string")
|
|
9771
|
+
return o.cwd;
|
|
9772
|
+
} catch {
|
|
9773
|
+
}
|
|
9774
|
+
if (count >= maxLines)
|
|
9775
|
+
break;
|
|
9776
|
+
}
|
|
9777
|
+
return void 0;
|
|
9778
|
+
}
|
|
9779
|
+
async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs, signal) {
|
|
9780
|
+
while (Date.now() - startMs < timeoutMs) {
|
|
9781
|
+
if (signal?.aborted)
|
|
9782
|
+
throw new TmuxRunError("aborted");
|
|
9783
|
+
const root = PROJECTS_ROOT();
|
|
9784
|
+
let subs;
|
|
9785
|
+
try {
|
|
9786
|
+
subs = readdirSync4(root);
|
|
9787
|
+
} catch {
|
|
9788
|
+
subs = [];
|
|
9789
|
+
}
|
|
9790
|
+
for (const sub of subs) {
|
|
9791
|
+
const dir = join6(root, sub);
|
|
9792
|
+
let files;
|
|
9793
|
+
try {
|
|
9794
|
+
files = readdirSync4(dir);
|
|
9795
|
+
} catch {
|
|
9796
|
+
continue;
|
|
9797
|
+
}
|
|
9798
|
+
for (const f of files) {
|
|
9799
|
+
if (!f.endsWith(".jsonl"))
|
|
9800
|
+
continue;
|
|
9801
|
+
const full = join6(dir, f);
|
|
9802
|
+
if (existingBefore.has(full))
|
|
9803
|
+
continue;
|
|
9804
|
+
if (readJsonlCwd(full) === targetCwd)
|
|
9805
|
+
return full;
|
|
9806
|
+
}
|
|
9807
|
+
}
|
|
9808
|
+
await sleep(300);
|
|
9809
|
+
}
|
|
9810
|
+
throw new TmuxRunError(`timeout waiting for claude to create the session transcript (cwd: ${targetCwd})`);
|
|
9811
|
+
}
|
|
9812
|
+
function parseTranscript2(path5, defaultModel) {
|
|
9813
|
+
let raw;
|
|
9814
|
+
try {
|
|
9815
|
+
raw = readFileSync10(path5, "utf8");
|
|
9816
|
+
} catch {
|
|
9817
|
+
return { assembled: "", inputTokens: 0, outputTokens: 0, modelUsed: defaultModel, done: false };
|
|
9818
|
+
}
|
|
9819
|
+
let assembled = "";
|
|
9820
|
+
let inputTokens = 0;
|
|
9821
|
+
let outputTokens = 0;
|
|
9822
|
+
let modelUsed = defaultModel;
|
|
9823
|
+
let done = false;
|
|
9824
|
+
for (const line of raw.split("\n")) {
|
|
9825
|
+
const t = line.trim();
|
|
9826
|
+
if (!t)
|
|
9827
|
+
continue;
|
|
9828
|
+
let o;
|
|
9829
|
+
try {
|
|
9830
|
+
o = JSON.parse(t);
|
|
9831
|
+
} catch {
|
|
9832
|
+
continue;
|
|
9833
|
+
}
|
|
9834
|
+
if (o.type !== "assistant")
|
|
9835
|
+
continue;
|
|
9836
|
+
const m = o.message;
|
|
9837
|
+
if (!m)
|
|
9838
|
+
continue;
|
|
9839
|
+
const mm = m.model;
|
|
9840
|
+
if (mm)
|
|
9841
|
+
modelUsed = mm;
|
|
9842
|
+
const content = m.content;
|
|
9843
|
+
if (Array.isArray(content)) {
|
|
9844
|
+
for (const block of content) {
|
|
9845
|
+
if (block.type === "text" && typeof block.text === "string") {
|
|
9846
|
+
assembled += block.text;
|
|
9847
|
+
}
|
|
9848
|
+
}
|
|
9849
|
+
}
|
|
9850
|
+
const usage = m.usage;
|
|
9851
|
+
if (usage) {
|
|
9852
|
+
inputTokens = num(usage.input_tokens) + num(usage.cache_creation_input_tokens) + num(usage.cache_read_input_tokens);
|
|
9853
|
+
outputTokens = num(usage.output_tokens);
|
|
9854
|
+
}
|
|
9855
|
+
if (m.stop_reason === "end_turn") {
|
|
9856
|
+
done = true;
|
|
9857
|
+
}
|
|
9858
|
+
}
|
|
9859
|
+
return { assembled, inputTokens, outputTokens, modelUsed, done };
|
|
9860
|
+
}
|
|
9861
|
+
function cleanup(cwd, runId, tmuxBin, sessionName) {
|
|
9862
|
+
try {
|
|
9863
|
+
spawnSync(tmuxBin, ["kill-session", "-t", sessionName], { stdio: "ignore" });
|
|
9864
|
+
} catch {
|
|
9865
|
+
}
|
|
9866
|
+
if (process.env.FLEETLENS_TMUX_KEEP_WRAPPER !== "1") {
|
|
9867
|
+
for (const f of [`system-${runId}.txt`, `user-${runId}.txt`, `run-${runId}.sh`]) {
|
|
9868
|
+
try {
|
|
9869
|
+
unlinkSync2(join6(cwd, f));
|
|
9870
|
+
} catch {
|
|
9871
|
+
}
|
|
9872
|
+
}
|
|
9873
|
+
}
|
|
9874
|
+
}
|
|
9875
|
+
function shellEscape(s) {
|
|
9876
|
+
if (/^[A-Za-z0-9_./-]+$/.test(s))
|
|
9877
|
+
return s;
|
|
9878
|
+
return `'${s.replace(/'/g, `'"'"'`)}'`;
|
|
9879
|
+
}
|
|
9880
|
+
|
|
9881
|
+
// ../entries/dist/llm-runner.js
|
|
9882
|
+
var RUNS_DIR = cclensPath("llm-runs");
|
|
9556
9883
|
function ensureRunsDir() {
|
|
9557
|
-
if (!
|
|
9884
|
+
if (!existsSync7(RUNS_DIR)) {
|
|
9558
9885
|
try {
|
|
9559
|
-
|
|
9886
|
+
mkdirSync9(RUNS_DIR, { recursive: true });
|
|
9560
9887
|
} catch {
|
|
9561
9888
|
}
|
|
9562
9889
|
}
|
|
@@ -9583,7 +9910,7 @@ function newRunId(kind) {
|
|
|
9583
9910
|
return `${ts}_${kind}_${short}`;
|
|
9584
9911
|
}
|
|
9585
9912
|
function tracePath(runId) {
|
|
9586
|
-
return
|
|
9913
|
+
return join7(RUNS_DIR, `${runId}.jsonl`);
|
|
9587
9914
|
}
|
|
9588
9915
|
function safeAppend(path5, line) {
|
|
9589
9916
|
try {
|
|
@@ -9593,11 +9920,84 @@ function safeAppend(path5, line) {
|
|
|
9593
9920
|
}
|
|
9594
9921
|
function safeWrite(path5, line) {
|
|
9595
9922
|
try {
|
|
9596
|
-
|
|
9923
|
+
writeFileSync8(path5, line);
|
|
9597
9924
|
} catch {
|
|
9598
9925
|
}
|
|
9599
9926
|
}
|
|
9600
|
-
function runClaudeSubprocess(args) {
|
|
9927
|
+
async function runClaudeSubprocess(args) {
|
|
9928
|
+
if (process.env.FLEETLENS_FORCE_PRINT_MODE !== "1") {
|
|
9929
|
+
const avail = tmuxRunnerAvailable();
|
|
9930
|
+
if (avail.ok) {
|
|
9931
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
9932
|
+
const kind = detectKindFromSystemPrompt(args.systemPrompt);
|
|
9933
|
+
const runId = newRunId(kind);
|
|
9934
|
+
const trace = tracePath(runId);
|
|
9935
|
+
ensureRunsDir();
|
|
9936
|
+
safeWrite(trace, JSON.stringify({
|
|
9937
|
+
_meta: {
|
|
9938
|
+
type: "start",
|
|
9939
|
+
run_id: runId,
|
|
9940
|
+
kind,
|
|
9941
|
+
model: args.model,
|
|
9942
|
+
ts: startedAt,
|
|
9943
|
+
runtime: "tmux",
|
|
9944
|
+
user_prompt_chars: args.userPrompt.length,
|
|
9945
|
+
reminder_chars: args.reminder?.length ?? 0
|
|
9946
|
+
}
|
|
9947
|
+
}) + "\n");
|
|
9948
|
+
safeAppend(trace, JSON.stringify({
|
|
9949
|
+
_meta: {
|
|
9950
|
+
type: "payload",
|
|
9951
|
+
run_id: runId,
|
|
9952
|
+
system_prompt: args.systemPrompt,
|
|
9953
|
+
user_prompt: args.userPrompt,
|
|
9954
|
+
reminder: args.reminder ?? null
|
|
9955
|
+
}
|
|
9956
|
+
}) + "\n");
|
|
9957
|
+
try {
|
|
9958
|
+
const startMs = Date.now();
|
|
9959
|
+
const res = await runClaudeUnderTmux({
|
|
9960
|
+
systemPrompt: args.systemPrompt,
|
|
9961
|
+
model: args.model,
|
|
9962
|
+
userPrompt: args.userPrompt,
|
|
9963
|
+
reminder: args.reminder,
|
|
9964
|
+
onProgress: args.onProgress
|
|
9965
|
+
});
|
|
9966
|
+
safeAppend(trace, JSON.stringify({
|
|
9967
|
+
_meta: {
|
|
9968
|
+
type: "end",
|
|
9969
|
+
run_id: runId,
|
|
9970
|
+
runtime: "tmux",
|
|
9971
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9972
|
+
elapsed_ms: Date.now() - startMs,
|
|
9973
|
+
// tmux runs have no subprocess exit code (the session is killed
|
|
9974
|
+
// by cleanup). Stamp 0 on success so /api/runs renders them
|
|
9975
|
+
// as `ok` rather than `error`.
|
|
9976
|
+
exit_code: 0,
|
|
9977
|
+
content_chars: res.content.length,
|
|
9978
|
+
input_tokens: res.input_tokens,
|
|
9979
|
+
output_tokens: res.output_tokens,
|
|
9980
|
+
model_used: res.model
|
|
9981
|
+
}
|
|
9982
|
+
}) + "\n");
|
|
9983
|
+
return res;
|
|
9984
|
+
} catch (err) {
|
|
9985
|
+
const isExpected = err instanceof TmuxUnavailableError || err instanceof TmuxRunError;
|
|
9986
|
+
safeAppend(trace, JSON.stringify({
|
|
9987
|
+
_meta: {
|
|
9988
|
+
type: "tmux_fallback",
|
|
9989
|
+
run_id: runId,
|
|
9990
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9991
|
+
error: err.message,
|
|
9992
|
+
expected: isExpected
|
|
9993
|
+
}
|
|
9994
|
+
}) + "\n");
|
|
9995
|
+
}
|
|
9996
|
+
}
|
|
9997
|
+
}
|
|
9998
|
+
return runClaudePrintMode(args);
|
|
9999
|
+
}
|
|
10000
|
+
function runClaudePrintMode(args) {
|
|
9601
10001
|
return new Promise((resolve, reject) => {
|
|
9602
10002
|
ensureRunsDir();
|
|
9603
10003
|
const kind = detectKindFromSystemPrompt(args.systemPrompt);
|
|
@@ -9908,29 +10308,29 @@ function applyEnrichmentError(entry, errorMessage, model, costUsd, generatedAt,
|
|
|
9908
10308
|
}
|
|
9909
10309
|
|
|
9910
10310
|
// ../entries/dist/budget.js
|
|
9911
|
-
|
|
9912
|
-
import {
|
|
9913
|
-
import {
|
|
10311
|
+
init_fs();
|
|
10312
|
+
import { appendFileSync as appendFileSync4, readFileSync as readFileSync11, existsSync as existsSync8, mkdirSync as mkdirSync10 } from "node:fs";
|
|
10313
|
+
import { dirname as dirname7 } from "node:path";
|
|
9914
10314
|
var spendPathCached = null;
|
|
9915
10315
|
function spendPath() {
|
|
9916
10316
|
if (spendPathCached)
|
|
9917
10317
|
return spendPathCached;
|
|
9918
|
-
spendPathCached =
|
|
10318
|
+
spendPathCached = cclensPath("llm-spend.jsonl");
|
|
9919
10319
|
return spendPathCached;
|
|
9920
10320
|
}
|
|
9921
10321
|
function appendSpend(record) {
|
|
9922
10322
|
const p = spendPath();
|
|
9923
|
-
|
|
10323
|
+
mkdirSync10(dirname7(p), { recursive: true });
|
|
9924
10324
|
appendFileSync4(p, JSON.stringify(record) + "\n", { encoding: "utf8" });
|
|
9925
10325
|
}
|
|
9926
10326
|
function monthToDateSpend(now = /* @__PURE__ */ new Date()) {
|
|
9927
10327
|
const p = spendPath();
|
|
9928
|
-
if (!
|
|
10328
|
+
if (!existsSync8(p))
|
|
9929
10329
|
return 0;
|
|
9930
10330
|
const year = now.getUTCFullYear();
|
|
9931
10331
|
const month = now.getUTCMonth();
|
|
9932
10332
|
let total = 0;
|
|
9933
|
-
const raw =
|
|
10333
|
+
const raw = readFileSync11(p, "utf8");
|
|
9934
10334
|
for (const line of raw.split("\n")) {
|
|
9935
10335
|
if (!line)
|
|
9936
10336
|
continue;
|
|
@@ -9951,9 +10351,8 @@ function monthToDateSpend(now = /* @__PURE__ */ new Date()) {
|
|
|
9951
10351
|
}
|
|
9952
10352
|
|
|
9953
10353
|
// ../entries/dist/pipeline-lock.js
|
|
9954
|
-
|
|
9955
|
-
import {
|
|
9956
|
-
import { homedir as homedir11 } from "node:os";
|
|
10354
|
+
init_fs();
|
|
10355
|
+
import { writeFileSync as writeFileSync9, unlinkSync as unlinkSync3, existsSync as existsSync9, readFileSync as readFileSync12, statSync as statSync3 } from "node:fs";
|
|
9957
10356
|
var STALE_MS2 = 60 * 1e3;
|
|
9958
10357
|
var HEARTBEAT_MS = 30 * 1e3;
|
|
9959
10358
|
var lockPathCached = null;
|
|
@@ -9961,11 +10360,11 @@ var heartbeat = null;
|
|
|
9961
10360
|
function lockPath() {
|
|
9962
10361
|
if (lockPathCached)
|
|
9963
10362
|
return lockPathCached;
|
|
9964
|
-
lockPathCached =
|
|
10363
|
+
lockPathCached = cclensPath("llm-interactive.lock");
|
|
9965
10364
|
return lockPathCached;
|
|
9966
10365
|
}
|
|
9967
10366
|
function touchLock() {
|
|
9968
|
-
|
|
10367
|
+
writeFileSync9(lockPath(), String(process.pid), "utf8");
|
|
9969
10368
|
}
|
|
9970
10369
|
function writeInteractiveLock() {
|
|
9971
10370
|
touchLock();
|
|
@@ -9985,7 +10384,7 @@ function removeInteractiveLock() {
|
|
|
9985
10384
|
heartbeat = null;
|
|
9986
10385
|
}
|
|
9987
10386
|
try {
|
|
9988
|
-
|
|
10387
|
+
unlinkSync3(lockPath());
|
|
9989
10388
|
} catch {
|
|
9990
10389
|
}
|
|
9991
10390
|
}
|
|
@@ -9999,13 +10398,13 @@ function pidAlive(pid) {
|
|
|
9999
10398
|
}
|
|
10000
10399
|
function interactiveLockFresh(nowMs) {
|
|
10001
10400
|
const p = lockPath();
|
|
10002
|
-
if (!
|
|
10401
|
+
if (!existsSync9(p))
|
|
10003
10402
|
return false;
|
|
10004
10403
|
try {
|
|
10005
10404
|
const mtime = statSync3(p).mtimeMs;
|
|
10006
10405
|
if (nowMs - mtime > STALE_MS2)
|
|
10007
10406
|
return false;
|
|
10008
|
-
const pid = Number(
|
|
10407
|
+
const pid = Number(readFileSync12(p, "utf8").trim());
|
|
10009
10408
|
if (!Number.isFinite(pid) || pid <= 0)
|
|
10010
10409
|
return false;
|
|
10011
10410
|
if (!pidAlive(pid))
|
|
@@ -10020,9 +10419,8 @@ function interactiveLockFresh(nowMs) {
|
|
|
10020
10419
|
var THIRTY_MIN_MS = 30 * 60 * 1e3;
|
|
10021
10420
|
|
|
10022
10421
|
// ../entries/dist/settings.js
|
|
10023
|
-
import { readFileSync as
|
|
10024
|
-
|
|
10025
|
-
import { homedir as homedir12 } from "node:os";
|
|
10422
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync10, renameSync as renameSync5, chmodSync as chmodSync2, mkdirSync as mkdirSync11, existsSync as existsSync10 } from "node:fs";
|
|
10423
|
+
init_fs();
|
|
10026
10424
|
var DEFAULT_SETTINGS = {
|
|
10027
10425
|
ai_features: {
|
|
10028
10426
|
enabled: true,
|
|
@@ -10036,7 +10434,7 @@ var settingsPathCached = null;
|
|
|
10036
10434
|
function settingsPath() {
|
|
10037
10435
|
if (settingsPathCached)
|
|
10038
10436
|
return settingsPathCached;
|
|
10039
|
-
settingsPathCached =
|
|
10437
|
+
settingsPathCached = cclensPath("settings.json");
|
|
10040
10438
|
return settingsPathCached;
|
|
10041
10439
|
}
|
|
10042
10440
|
function fromDisk(d) {
|
|
@@ -10053,10 +10451,10 @@ function fromDisk(d) {
|
|
|
10053
10451
|
}
|
|
10054
10452
|
function readSettings() {
|
|
10055
10453
|
const p = settingsPath();
|
|
10056
|
-
if (!
|
|
10454
|
+
if (!existsSync10(p))
|
|
10057
10455
|
return DEFAULT_SETTINGS;
|
|
10058
10456
|
try {
|
|
10059
|
-
const raw =
|
|
10457
|
+
const raw = readFileSync13(p, "utf8");
|
|
10060
10458
|
return fromDisk(JSON.parse(raw));
|
|
10061
10459
|
} catch {
|
|
10062
10460
|
return DEFAULT_SETTINGS;
|
|
@@ -12779,11 +13177,10 @@ async function backfillYesterdayDigest(opts = {}) {
|
|
|
12779
13177
|
}
|
|
12780
13178
|
|
|
12781
13179
|
// src/daemon-worker.ts
|
|
12782
|
-
var
|
|
12783
|
-
var
|
|
12784
|
-
var DAEMON_LOG = join13(STATE_DIR, "daemon.log");
|
|
13180
|
+
var USAGE_LOG2 = cclensPath("usage.jsonl");
|
|
13181
|
+
var DAEMON_LOG = cclensPath("daemon.log");
|
|
12785
13182
|
var WATCHDOG_INTERVAL_MS = 5 * 1e3;
|
|
12786
|
-
|
|
13183
|
+
mkdirSync12(dirname8(USAGE_LOG2), { recursive: true });
|
|
12787
13184
|
function log2(level, message) {
|
|
12788
13185
|
const line = `${(/* @__PURE__ */ new Date()).toISOString()} ${level.toUpperCase()} ${message}
|
|
12789
13186
|
`;
|
|
@@ -12836,7 +13233,7 @@ async function tick() {
|
|
|
12836
13233
|
seven_day_cowork: null,
|
|
12837
13234
|
extra_usage: null
|
|
12838
13235
|
};
|
|
12839
|
-
appendSnapshot(
|
|
13236
|
+
appendSnapshot(USAGE_LOG2, snapshot);
|
|
12840
13237
|
log2(
|
|
12841
13238
|
"info",
|
|
12842
13239
|
`${source.kind} snapshot 5h=${snapshot.five_hour.utilization}% 7d=${snapshot.seven_day.utilization}%`
|
|
@@ -12847,7 +13244,7 @@ async function tick() {
|
|
|
12847
13244
|
}
|
|
12848
13245
|
try {
|
|
12849
13246
|
const snapshot = await fetchUsage();
|
|
12850
|
-
appendSnapshot(
|
|
13247
|
+
appendSnapshot(USAGE_LOG2, snapshot);
|
|
12851
13248
|
log2(
|
|
12852
13249
|
"info",
|
|
12853
13250
|
`claude-code snapshot 5h=${snapshot.five_hour.utilization}% 7d=${snapshot.seven_day.utilization}%`
|
|
@@ -12873,7 +13270,7 @@ function scheduleAfter(now, outcome) {
|
|
|
12873
13270
|
}
|
|
12874
13271
|
nextPollAtMs = now + currentIntervalMs;
|
|
12875
13272
|
}
|
|
12876
|
-
function
|
|
13273
|
+
function sleep2(ms) {
|
|
12877
13274
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
12878
13275
|
}
|
|
12879
13276
|
async function runLoop() {
|
|
@@ -12906,7 +13303,7 @@ async function runLoop() {
|
|
|
12906
13303
|
}
|
|
12907
13304
|
await runTeamSync(log2);
|
|
12908
13305
|
}
|
|
12909
|
-
await
|
|
13306
|
+
await sleep2(WATCHDOG_INTERVAL_MS);
|
|
12910
13307
|
}
|
|
12911
13308
|
}
|
|
12912
13309
|
log2(
|