fleetlens 0.9.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 +2 -3
- 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 +2 -3
- 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 +2 -3
- 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]__0fpbr8-._.js → [externals]__0o43ejh._.js} +2 -2
- 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]__0e8n_x4._.js → [root-of-the-server]__08agijy._.js} +2 -2
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0_8zh-i._.js +3 -3
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0ej_p3s._.js +2 -2
- package/app/apps/web/.next/server/chunks/{[root-of-the-server]__0-vgrh1._.js → [root-of-the-server]__0i06ito._.js} +2 -2
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0jprdks._.js +2 -2
- 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]__0d~2~le._.js +1 -1
- 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 +3 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0tejjy_._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0w52fbc._.js +3 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0yv0m0q._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/_0jw2sm7._.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_0ly1xes._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0txtsv5._.js +2 -2
- 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_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/04a36uhu~p_z-.css +1 -0
- package/app/apps/web/.next/static/chunks/{0q2vd~aj.1hpz.js → 0g8ujtb0lp._9.js} +3 -3
- package/app/apps/web/.next/static/chunks/0l3ck.awv~4t7.js +1 -0
- package/app/apps/web/.next/static/chunks/{171za22fv684..js → 0lxuac2v0_gdl.js} +2 -2
- package/app/apps/web/.next/static/chunks/0n0n.0279ot6c.js +1 -0
- package/app/apps/web/.next/static/chunks/0uev~g~qvbjv9.js +4 -0
- 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/components/previous-cycles-trend.tsx +26 -11
- package/app/apps/web/components/usage-chart.tsx +35 -37
- package/app/apps/web/components/usage-gauges.tsx +18 -12
- package/app/apps/web/components/usage-sidebar.tsx +23 -12
- 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/lib/utilization-tone.ts +74 -0
- package/app/apps/web/package.json +1 -1
- package/app/apps/web/tsconfig.tsbuildinfo +1 -1
- package/dist/daemon-worker.js +609 -110
- package/dist/index.js +5312 -4802
- package/package.json +1 -1
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0.z48ue._.js +0 -3
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0dctov1._.js +0 -5
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0op9af~._.js +0 -3
- package/app/apps/web/.next/server/chunks/packages_09hmrqx._.js +0 -3
- package/app/apps/web/.next/server/chunks/packages_118y1lp._.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/[root-of-the-server]__0ytdqxt._.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/05m.oz3kmf1p7.js +0 -1
- package/app/apps/web/.next/static/chunks/07-fq4im3pmjp.js +0 -4
- package/app/apps/web/.next/static/chunks/0cxyt4-24..b7.js +0 -14
- package/app/apps/web/.next/static/chunks/0o9ayt8sknubd.js +0 -1
- package/app/apps/web/.next/static/chunks/0wfbj5zr~az.z.css +0 -1
- /package/app/apps/web/.next/static/{u6-8f8u1tspYCacGAz53R → sxcMbKfZ5XgVXYN4QHOHd}/_buildManifest.js +0 -0
- /package/app/apps/web/.next/static/{u6-8f8u1tspYCacGAz53R → sxcMbKfZ5XgVXYN4QHOHd}/_clientMiddlewareManifest.js +0 -0
- /package/app/apps/web/.next/static/{u6-8f8u1tspYCacGAz53R → sxcMbKfZ5XgVXYN4QHOHd}/_ssgManifest.js +0 -0
package/dist/daemon-worker.js
CHANGED
|
@@ -32,21 +32,37 @@ function findWorktreeMarker(projectName) {
|
|
|
32
32
|
}
|
|
33
33
|
return null;
|
|
34
34
|
}
|
|
35
|
+
function findConductorWorkspace(projectName) {
|
|
36
|
+
const m = CONDUCTOR_RE.exec(projectName);
|
|
37
|
+
if (!m)
|
|
38
|
+
return null;
|
|
39
|
+
const workspaceName = m[1];
|
|
40
|
+
const trailingSlash = m[0].endsWith("/") ? 1 : 0;
|
|
41
|
+
const canonicalEndIdx = m.index + m[0].length - workspaceName.length - 1 - trailingSlash;
|
|
42
|
+
return { canonicalEndIdx, workspaceName };
|
|
43
|
+
}
|
|
35
44
|
function canonicalProjectName(projectName) {
|
|
36
45
|
const normalized = projectName.replace(/\/{2,}/g, "/");
|
|
37
|
-
const
|
|
38
|
-
if (
|
|
39
|
-
return normalized.slice(0,
|
|
46
|
+
const wt = findWorktreeMarker(normalized);
|
|
47
|
+
if (wt)
|
|
48
|
+
return normalized.slice(0, wt.idx);
|
|
49
|
+
const cd = findConductorWorkspace(normalized);
|
|
50
|
+
if (cd)
|
|
51
|
+
return normalized.slice(0, cd.canonicalEndIdx);
|
|
40
52
|
return normalized;
|
|
41
53
|
}
|
|
42
54
|
function worktreeName(projectName) {
|
|
43
55
|
const normalized = projectName.replace(/\/{2,}/g, "/");
|
|
44
|
-
const
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
56
|
+
const wt = findWorktreeMarker(normalized);
|
|
57
|
+
if (wt) {
|
|
58
|
+
const tail = normalized.slice(wt.idx + wt.marker.length);
|
|
59
|
+
const slash = tail.indexOf("/");
|
|
60
|
+
return slash >= 0 ? tail.slice(0, slash) : tail;
|
|
61
|
+
}
|
|
62
|
+
const cd = findConductorWorkspace(normalized);
|
|
63
|
+
if (cd)
|
|
64
|
+
return cd.workspaceName;
|
|
65
|
+
return null;
|
|
50
66
|
}
|
|
51
67
|
function makeDay(date) {
|
|
52
68
|
return {
|
|
@@ -515,7 +531,7 @@ function groupByProject(sessions) {
|
|
|
515
531
|
}
|
|
516
532
|
return Array.from(map.values()).sort((a, b) => (b.lastActiveMs ?? 0) - (a.lastActiveMs ?? 0));
|
|
517
533
|
}
|
|
518
|
-
var BLANK_USAGE, WORKTREE_MARKERS, PR_CREATE_RE, PR_NUMBER_RE, TITLE_FLAG_RE;
|
|
534
|
+
var BLANK_USAGE, WORKTREE_MARKERS, CONDUCTOR_RE, PR_CREATE_RE, PR_NUMBER_RE, TITLE_FLAG_RE;
|
|
519
535
|
var init_analytics = __esm({
|
|
520
536
|
"../parser/dist/analytics.js"() {
|
|
521
537
|
"use strict";
|
|
@@ -525,6 +541,7 @@ var init_analytics = __esm({
|
|
|
525
541
|
"/.worktrees/",
|
|
526
542
|
"/claude/worktrees/"
|
|
527
543
|
];
|
|
544
|
+
CONDUCTOR_RE = /\/conductor\/workspaces\/[^/]+\/([^/]+)(?:\/|$)/;
|
|
528
545
|
PR_CREATE_RE = /gh\s+pr\s+create\b/i;
|
|
529
546
|
PR_NUMBER_RE = /#(\d+)/;
|
|
530
547
|
TITLE_FLAG_RE = /--title\s+["']([^"']+)["']/;
|
|
@@ -757,10 +774,64 @@ var init_calibration = __esm({
|
|
|
757
774
|
}
|
|
758
775
|
});
|
|
759
776
|
|
|
777
|
+
// ../parser/dist/user-input.js
|
|
778
|
+
function stripFrameworkBoilerplate(rawText) {
|
|
779
|
+
if (!rawText)
|
|
780
|
+
return rawText;
|
|
781
|
+
let out = rawText;
|
|
782
|
+
for (const re of STRIPPABLE_WRAPPERS) {
|
|
783
|
+
out = out.replace(re, "");
|
|
784
|
+
}
|
|
785
|
+
return out.trim();
|
|
786
|
+
}
|
|
787
|
+
function isFrameworkInjectedUserInput(rawText) {
|
|
788
|
+
if (!rawText)
|
|
789
|
+
return false;
|
|
790
|
+
const stripped = stripFrameworkBoilerplate(rawText);
|
|
791
|
+
if (!stripped)
|
|
792
|
+
return true;
|
|
793
|
+
for (const prefix of ENTIRELY_INJECTED_PREFIXES) {
|
|
794
|
+
if (stripped.startsWith(prefix))
|
|
795
|
+
return true;
|
|
796
|
+
}
|
|
797
|
+
return false;
|
|
798
|
+
}
|
|
799
|
+
var STRIPPABLE_WRAPPERS, ENTIRELY_INJECTED_PREFIXES;
|
|
800
|
+
var init_user_input = __esm({
|
|
801
|
+
"../parser/dist/user-input.js"() {
|
|
802
|
+
"use strict";
|
|
803
|
+
STRIPPABLE_WRAPPERS = [
|
|
804
|
+
/<system_instruction\b[^>]*>[\s\S]*?<\/system_instruction>\s*/gi
|
|
805
|
+
];
|
|
806
|
+
ENTIRELY_INJECTED_PREFIXES = [
|
|
807
|
+
"<command-name>",
|
|
808
|
+
"<local-command-stdout>",
|
|
809
|
+
"<local-command-caveat>",
|
|
810
|
+
"<task-notification>",
|
|
811
|
+
"Base directory for this skill:"
|
|
812
|
+
];
|
|
813
|
+
}
|
|
814
|
+
});
|
|
815
|
+
|
|
760
816
|
// ../parser/dist/parser.js
|
|
761
817
|
function cleanText(s) {
|
|
762
818
|
return s.replace(/<[^>]+>/g, "").replace(/\s+/g, " ").trim();
|
|
763
819
|
}
|
|
820
|
+
function extractRawUserText(rawMsg) {
|
|
821
|
+
const c = rawMsg?.content;
|
|
822
|
+
if (typeof c === "string")
|
|
823
|
+
return c;
|
|
824
|
+
if (Array.isArray(c)) {
|
|
825
|
+
for (const block of c) {
|
|
826
|
+
if (block && typeof block === "object") {
|
|
827
|
+
const b = block;
|
|
828
|
+
if (b.type === "text" && typeof b.text === "string")
|
|
829
|
+
return b.text;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
return "";
|
|
834
|
+
}
|
|
764
835
|
function truncate(s, n = 200) {
|
|
765
836
|
const one = cleanText(s);
|
|
766
837
|
return one.length > n ? one.slice(0, n - 1) + "\u2026" : one;
|
|
@@ -859,7 +930,8 @@ function toEvent(raw, index) {
|
|
|
859
930
|
const msg = r.message ?? {};
|
|
860
931
|
const c = msg.content;
|
|
861
932
|
if (typeof c === "string") {
|
|
862
|
-
const
|
|
933
|
+
const cleaned = stripFrameworkBoilerplate(c);
|
|
934
|
+
const tm = classifyTeammateMessage(cleaned);
|
|
863
935
|
return {
|
|
864
936
|
index,
|
|
865
937
|
uuid,
|
|
@@ -867,8 +939,8 @@ function toEvent(raw, index) {
|
|
|
867
939
|
timestamp,
|
|
868
940
|
role: "user",
|
|
869
941
|
rawType,
|
|
870
|
-
preview: truncate(
|
|
871
|
-
blocks: [{ type: "text", text:
|
|
942
|
+
preview: truncate(cleaned, 200),
|
|
943
|
+
blocks: cleaned ? [{ type: "text", text: cleaned }] : [],
|
|
872
944
|
raw,
|
|
873
945
|
teammateMessage: tm
|
|
874
946
|
};
|
|
@@ -892,7 +964,9 @@ function toEvent(raw, index) {
|
|
|
892
964
|
};
|
|
893
965
|
}
|
|
894
966
|
const textBlock = c.find((b) => b?.type === "text");
|
|
895
|
-
const
|
|
967
|
+
const cleanedText = textBlock ? stripFrameworkBoilerplate(textBlock.text) : "";
|
|
968
|
+
const cleanedBlocks = textBlock ? c.map((b) => b === textBlock ? { type: "text", text: cleanedText } : b) : c;
|
|
969
|
+
const tm = cleanedText ? classifyTeammateMessage(cleanedText) : void 0;
|
|
896
970
|
return {
|
|
897
971
|
index,
|
|
898
972
|
uuid,
|
|
@@ -900,8 +974,8 @@ function toEvent(raw, index) {
|
|
|
900
974
|
timestamp,
|
|
901
975
|
role: "user",
|
|
902
976
|
rawType,
|
|
903
|
-
preview:
|
|
904
|
-
blocks:
|
|
977
|
+
preview: cleanedText ? truncate(cleanedText, 200) : truncate(JSON.stringify(c), 200),
|
|
978
|
+
blocks: cleanedBlocks,
|
|
905
979
|
raw,
|
|
906
980
|
teammateMessage: tm
|
|
907
981
|
};
|
|
@@ -1078,6 +1152,7 @@ function parseTranscript(rawLines) {
|
|
|
1078
1152
|
let sessionId = "";
|
|
1079
1153
|
let cwd;
|
|
1080
1154
|
let gitBranch;
|
|
1155
|
+
let entrypoint;
|
|
1081
1156
|
let teamName;
|
|
1082
1157
|
let agentName;
|
|
1083
1158
|
let hasTeamCreate = false;
|
|
@@ -1121,8 +1196,8 @@ function parseTranscript(rawLines) {
|
|
|
1121
1196
|
}
|
|
1122
1197
|
if (e.role === "user") {
|
|
1123
1198
|
const rawMsg = e.raw?.message;
|
|
1124
|
-
const rawContent =
|
|
1125
|
-
const isHidden =
|
|
1199
|
+
const rawContent = extractRawUserText(rawMsg);
|
|
1200
|
+
const isHidden = isFrameworkInjectedUserInput(rawContent);
|
|
1126
1201
|
const isTeamNoise = e.teammateMessage !== void 0 && !agentName;
|
|
1127
1202
|
if (!isHidden && !isTeamNoise) {
|
|
1128
1203
|
if (!firstUserPreview) {
|
|
@@ -1146,6 +1221,8 @@ function parseTranscript(rawLines) {
|
|
|
1146
1221
|
cwd = o.cwd;
|
|
1147
1222
|
if (typeof o.gitBranch === "string" && !gitBranch)
|
|
1148
1223
|
gitBranch = o.gitBranch;
|
|
1224
|
+
if (typeof o.entrypoint === "string" && !entrypoint)
|
|
1225
|
+
entrypoint = o.entrypoint;
|
|
1149
1226
|
if (typeof o.teamName === "string" && !teamName)
|
|
1150
1227
|
teamName = o.teamName;
|
|
1151
1228
|
if (typeof o.agentName === "string" && !agentName)
|
|
@@ -1183,6 +1260,7 @@ function parseTranscript(rawLines) {
|
|
|
1183
1260
|
model,
|
|
1184
1261
|
cwd,
|
|
1185
1262
|
gitBranch,
|
|
1263
|
+
entrypoint,
|
|
1186
1264
|
totalUsage,
|
|
1187
1265
|
status: "idle",
|
|
1188
1266
|
firstUserPreview,
|
|
@@ -1207,6 +1285,7 @@ var BLANK_USAGE2, TEAMMATE_MSG_RE;
|
|
|
1207
1285
|
var init_parser = __esm({
|
|
1208
1286
|
"../parser/dist/parser.js"() {
|
|
1209
1287
|
"use strict";
|
|
1288
|
+
init_user_input();
|
|
1210
1289
|
BLANK_USAGE2 = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
1211
1290
|
TEAMMATE_MSG_RE = /^\s*<teammate-message\s+teammate_id="([^"]+)"[^>]*>([\s\S]*?)<\/teammate-message>/;
|
|
1212
1291
|
}
|
|
@@ -2025,7 +2104,8 @@ function parseRollout(file, lines) {
|
|
|
2025
2104
|
if (type === "event_msg" && subtype === "user_message") {
|
|
2026
2105
|
const text = typeof payload.message === "string" ? payload.message : "";
|
|
2027
2106
|
const preview = previewOf(text);
|
|
2028
|
-
|
|
2107
|
+
const isHidden = isFrameworkInjectedUserInput(text);
|
|
2108
|
+
if (text && !isHidden) {
|
|
2029
2109
|
if (!firstUserPreview)
|
|
2030
2110
|
firstUserPreview = preview;
|
|
2031
2111
|
lastUserPreview = preview;
|
|
@@ -2342,6 +2422,7 @@ var init_codex = __esm({
|
|
|
2342
2422
|
"../parser/dist/codex.js"() {
|
|
2343
2423
|
"use strict";
|
|
2344
2424
|
init_analytics();
|
|
2425
|
+
init_user_input();
|
|
2345
2426
|
DEFAULT_CODEX_ROOT = path2.join(os2.homedir(), ".codex", "sessions");
|
|
2346
2427
|
ROLLOUT_RE = /^rollout-(\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2})-([0-9a-f-]+)\.jsonl$/;
|
|
2347
2428
|
IDLE_GAP_MS = 3 * 60 * 1e3;
|
|
@@ -2564,7 +2645,8 @@ async function parseSession(file) {
|
|
|
2564
2645
|
if (msg.type === "user") {
|
|
2565
2646
|
const text = flattenContent(msg.displayContent ?? msg.content);
|
|
2566
2647
|
const preview = previewOf2(text);
|
|
2567
|
-
|
|
2648
|
+
const isHidden = isFrameworkInjectedUserInput(text);
|
|
2649
|
+
if (text && !isHidden) {
|
|
2568
2650
|
if (!firstUserPreview)
|
|
2569
2651
|
firstUserPreview = preview;
|
|
2570
2652
|
lastUserPreview = preview;
|
|
@@ -2839,6 +2921,7 @@ var init_gemini = __esm({
|
|
|
2839
2921
|
"../parser/dist/gemini.js"() {
|
|
2840
2922
|
"use strict";
|
|
2841
2923
|
init_analytics();
|
|
2924
|
+
init_user_input();
|
|
2842
2925
|
DEFAULT_GEMINI_ROOT = path3.join(os3.homedir(), ".gemini", "tmp");
|
|
2843
2926
|
GEMINI_PROJECTS_FILE = path3.join(os3.homedir(), ".gemini", "projects.json");
|
|
2844
2927
|
SESSION_FILE_RE = /^session-.+\.(jsonl|json)$/;
|
|
@@ -2858,6 +2941,8 @@ __export(fs_exports, {
|
|
|
2858
2941
|
agentSources: () => agentSources,
|
|
2859
2942
|
buildCalibrationCurve: () => buildCalibrationCurve,
|
|
2860
2943
|
cacheStats: () => cacheStats,
|
|
2944
|
+
cclensHome: () => cclensHome,
|
|
2945
|
+
cclensPath: () => cclensPath,
|
|
2861
2946
|
clearCaches: () => clearCaches,
|
|
2862
2947
|
codexSessionLocalDay: () => codexSessionLocalDay,
|
|
2863
2948
|
decodeProjectName: () => decodeProjectName,
|
|
@@ -2887,6 +2972,12 @@ __export(fs_exports, {
|
|
|
2887
2972
|
import { promises as fs4 } from "node:fs";
|
|
2888
2973
|
import os4 from "node:os";
|
|
2889
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
|
+
}
|
|
2890
2981
|
function cacheStats() {
|
|
2891
2982
|
return claudeCodeCacheStats();
|
|
2892
2983
|
}
|
|
@@ -2919,10 +3010,13 @@ async function getAnySession(id) {
|
|
|
2919
3010
|
}
|
|
2920
3011
|
return null;
|
|
2921
3012
|
}
|
|
3013
|
+
function usageLogPath() {
|
|
3014
|
+
return cclensPath("usage.jsonl");
|
|
3015
|
+
}
|
|
2922
3016
|
async function loadUsageByDay(start, end) {
|
|
2923
3017
|
let raw;
|
|
2924
3018
|
try {
|
|
2925
|
-
raw = await fs4.readFile(
|
|
3019
|
+
raw = await fs4.readFile(usageLogPath(), "utf8");
|
|
2926
3020
|
} catch {
|
|
2927
3021
|
return { by_day: [] };
|
|
2928
3022
|
}
|
|
@@ -2967,7 +3061,7 @@ async function loadUsageByDay(start, end) {
|
|
|
2967
3061
|
async function loadCalibrationSnapshots() {
|
|
2968
3062
|
let raw;
|
|
2969
3063
|
try {
|
|
2970
|
-
raw = await fs4.readFile(
|
|
3064
|
+
raw = await fs4.readFile(usageLogPath(), "utf8");
|
|
2971
3065
|
} catch {
|
|
2972
3066
|
return [];
|
|
2973
3067
|
}
|
|
@@ -3125,7 +3219,7 @@ async function loadCalibrationCurve(tier = "pro-max-20x", root = DEFAULT_ROOT, g
|
|
|
3125
3219
|
]);
|
|
3126
3220
|
return buildCalibrationCurve(events, snapshots, tier, granularityMin);
|
|
3127
3221
|
}
|
|
3128
|
-
var codexSource, geminiSource, agentSources
|
|
3222
|
+
var codexSource, geminiSource, agentSources;
|
|
3129
3223
|
var init_fs = __esm({
|
|
3130
3224
|
"../parser/dist/fs.js"() {
|
|
3131
3225
|
"use strict";
|
|
@@ -3170,7 +3264,6 @@ var init_fs = __esm({
|
|
|
3170
3264
|
}
|
|
3171
3265
|
};
|
|
3172
3266
|
agentSources = [claudeCodeSource, codexSource, geminiSource];
|
|
3173
|
-
USAGE_LOG = path4.join(os4.homedir(), ".cclens", "usage.jsonl");
|
|
3174
3267
|
}
|
|
3175
3268
|
});
|
|
3176
3269
|
|
|
@@ -3339,7 +3432,13 @@ function buildPresentation(events) {
|
|
|
3339
3432
|
return false;
|
|
3340
3433
|
if (e.role === "user") {
|
|
3341
3434
|
const txt = firstTextOfBlocks(e.blocks) ?? "";
|
|
3342
|
-
if (
|
|
3435
|
+
if (e.blocks.length === 0 || !txt.trim())
|
|
3436
|
+
return false;
|
|
3437
|
+
if (SLASH_COMMAND_RE.test(txt))
|
|
3438
|
+
return true;
|
|
3439
|
+
if (TASK_NOTIFICATION_RE.test(txt))
|
|
3440
|
+
return true;
|
|
3441
|
+
if (isFrameworkInjectedUserInput(txt))
|
|
3343
3442
|
return false;
|
|
3344
3443
|
}
|
|
3345
3444
|
return true;
|
|
@@ -3467,13 +3566,13 @@ function buildPresentation(events) {
|
|
|
3467
3566
|
}
|
|
3468
3567
|
return rows;
|
|
3469
3568
|
}
|
|
3470
|
-
var INTERRUPT_RE, RATE_LIMIT_RE,
|
|
3569
|
+
var INTERRUPT_RE, RATE_LIMIT_RE, SLASH_COMMAND_RE, TASK_NOTIFICATION_RE;
|
|
3471
3570
|
var init_presentation = __esm({
|
|
3472
3571
|
"../parser/dist/presentation.js"() {
|
|
3473
3572
|
"use strict";
|
|
3573
|
+
init_user_input();
|
|
3474
3574
|
INTERRUPT_RE = /\[request interrupted|interrupted by user/i;
|
|
3475
3575
|
RATE_LIMIT_RE = /rate.?limit|overloaded_error|api error|Error sending message/i;
|
|
3476
|
-
SKILL_CONTENT_RE = /^Base directory for this skill:/;
|
|
3477
3576
|
SLASH_COMMAND_RE = /<command-name>(\/[^<\s]+)<\/command-name>(?:[\s\S]*?<command-args>([\s\S]*?)<\/command-args>)?/;
|
|
3478
3577
|
TASK_NOTIFICATION_RE = /<task-notification>/;
|
|
3479
3578
|
}
|
|
@@ -3607,6 +3706,7 @@ __export(dist_exports, {
|
|
|
3607
3706
|
groupSnapsByCycle: () => groupSnapsByCycle,
|
|
3608
3707
|
highLevelMetrics: () => highLevelMetrics,
|
|
3609
3708
|
isAgentKind: () => isAgentKind,
|
|
3709
|
+
isFrameworkInjectedUserInput: () => isFrameworkInjectedUserInput,
|
|
3610
3710
|
last4CompletedWeeks: () => last4CompletedWeeks,
|
|
3611
3711
|
modelFamily: () => modelFamily,
|
|
3612
3712
|
parseTranscript: () => parseTranscript,
|
|
@@ -3617,6 +3717,7 @@ __export(dist_exports, {
|
|
|
3617
3717
|
rowPrimaryIndex: () => rowPrimaryIndex,
|
|
3618
3718
|
sessionAirTimeMs: () => sessionAirTimeMs,
|
|
3619
3719
|
sessionDay: () => sessionDay,
|
|
3720
|
+
stripFrameworkBoilerplate: () => stripFrameworkBoilerplate,
|
|
3620
3721
|
summarizeBursts: () => summarizeBursts,
|
|
3621
3722
|
toLocalDay: () => toLocalDay,
|
|
3622
3723
|
userSoloRate: () => userSoloRate,
|
|
@@ -3627,6 +3728,7 @@ var init_dist = __esm({
|
|
|
3627
3728
|
"use strict";
|
|
3628
3729
|
init_types();
|
|
3629
3730
|
init_parser();
|
|
3731
|
+
init_user_input();
|
|
3630
3732
|
init_presentation();
|
|
3631
3733
|
init_analytics();
|
|
3632
3734
|
init_aggregate();
|
|
@@ -3637,9 +3739,8 @@ var init_dist = __esm({
|
|
|
3637
3739
|
});
|
|
3638
3740
|
|
|
3639
3741
|
// src/daemon-worker.ts
|
|
3640
|
-
import { appendFileSync as appendFileSync5, mkdirSync as
|
|
3641
|
-
import { dirname as
|
|
3642
|
-
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";
|
|
3643
3744
|
|
|
3644
3745
|
// src/usage/token.ts
|
|
3645
3746
|
import { execFileSync } from "node:child_process";
|
|
@@ -3799,9 +3900,13 @@ function readSnapshots(filePath) {
|
|
|
3799
3900
|
}
|
|
3800
3901
|
return snapshots;
|
|
3801
3902
|
}
|
|
3802
|
-
function
|
|
3903
|
+
function latestClaudeCodeSnapshot(filePath) {
|
|
3803
3904
|
const all = readSnapshots(filePath);
|
|
3804
|
-
|
|
3905
|
+
for (let i = all.length - 1; i >= 0; i--) {
|
|
3906
|
+
const s = all[i];
|
|
3907
|
+
if (!s.agent || s.agent === "claude-code") return s;
|
|
3908
|
+
}
|
|
3909
|
+
return null;
|
|
3805
3910
|
}
|
|
3806
3911
|
|
|
3807
3912
|
// src/daemon-worker.ts
|
|
@@ -3816,26 +3921,23 @@ function nextIntervalMs(current, outcome) {
|
|
|
3816
3921
|
return Math.min(Math.max(current, BASE_INTERVAL_MS) * 2, MAX_INTERVAL_MS);
|
|
3817
3922
|
}
|
|
3818
3923
|
|
|
3819
|
-
// src/team/sync.ts
|
|
3820
|
-
import { homedir as homedir4 } from "node:os";
|
|
3821
|
-
import { join as join4 } from "node:path";
|
|
3822
|
-
|
|
3823
3924
|
// src/team/config.ts
|
|
3925
|
+
init_fs();
|
|
3824
3926
|
import { readFileSync as readFileSync3, writeFileSync, unlinkSync, mkdirSync as mkdirSync2 } from "node:fs";
|
|
3825
3927
|
import { join as join2 } from "node:path";
|
|
3826
|
-
import { homedir as homedir2 } from "node:os";
|
|
3827
|
-
var DEFAULT_DIR = join2(homedir2(), ".cclens");
|
|
3828
3928
|
var CONFIG_FILE = "team.json";
|
|
3829
|
-
function readTeamConfig(dir
|
|
3929
|
+
function readTeamConfig(dir) {
|
|
3930
|
+
const d = dir ?? cclensHome();
|
|
3830
3931
|
try {
|
|
3831
|
-
return JSON.parse(readFileSync3(join2(
|
|
3932
|
+
return JSON.parse(readFileSync3(join2(d, CONFIG_FILE), "utf8"));
|
|
3832
3933
|
} catch {
|
|
3833
3934
|
return null;
|
|
3834
3935
|
}
|
|
3835
3936
|
}
|
|
3836
|
-
function writeTeamConfig(config, dir
|
|
3837
|
-
|
|
3838
|
-
|
|
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 });
|
|
3839
3941
|
}
|
|
3840
3942
|
|
|
3841
3943
|
// src/team/push.ts
|
|
@@ -3843,7 +3945,7 @@ init_dist();
|
|
|
3843
3945
|
import { randomUUID } from "node:crypto";
|
|
3844
3946
|
var SNAPSHOT_FRESHNESS_MS = 10 * 60 * 1e3;
|
|
3845
3947
|
function readLatestUsageSnapshotForWire(filePath, nowMs = Date.now()) {
|
|
3846
|
-
const raw =
|
|
3948
|
+
const raw = latestClaudeCodeSnapshot(filePath);
|
|
3847
3949
|
if (!raw) return null;
|
|
3848
3950
|
const capturedMs = Date.parse(raw.captured_at);
|
|
3849
3951
|
if (Number.isNaN(capturedMs)) return null;
|
|
@@ -3911,10 +4013,10 @@ async function pushToTeamServer(config, payload) {
|
|
|
3911
4013
|
}
|
|
3912
4014
|
|
|
3913
4015
|
// src/team/queue.ts
|
|
4016
|
+
init_fs();
|
|
3914
4017
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, appendFileSync as appendFileSync2, statSync, mkdirSync as mkdirSync3 } from "node:fs";
|
|
3915
|
-
import {
|
|
3916
|
-
|
|
3917
|
-
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");
|
|
3918
4020
|
var MAX_SIZE_BYTES = 10 * 1024 * 1024;
|
|
3919
4021
|
var MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
3920
4022
|
function enqueuePayload(payload, queuePath = QUEUE_PATH) {
|
|
@@ -4037,8 +4139,9 @@ async function getPlanTier(cachePath, nowMs = Date.now(), fetcher = fetchProfile
|
|
|
4037
4139
|
}
|
|
4038
4140
|
|
|
4039
4141
|
// src/team/sync.ts
|
|
4040
|
-
|
|
4041
|
-
var
|
|
4142
|
+
init_fs();
|
|
4143
|
+
var USAGE_LOG = cclensPath("usage.jsonl");
|
|
4144
|
+
var PROFILE_CACHE = cclensPath("profile.json");
|
|
4042
4145
|
var noopLog = () => {
|
|
4043
4146
|
};
|
|
4044
4147
|
async function runTeamSync(log3 = noopLog, configOverride) {
|
|
@@ -4050,7 +4153,7 @@ async function runTeamSync(log3 = noopLog, configOverride) {
|
|
|
4050
4153
|
const today = toLocalDay3(Date.now());
|
|
4051
4154
|
const sessions = await listSessions2({ limit: 1e4 });
|
|
4052
4155
|
const rollups = buildRollupsForRange(sessions, config.lastSyncedDay);
|
|
4053
|
-
const usageSnapshot = readLatestUsageSnapshotForWire(
|
|
4156
|
+
const usageSnapshot = readLatestUsageSnapshotForWire(USAGE_LOG) ?? void 0;
|
|
4054
4157
|
const planTier = await getPlanTier(PROFILE_CACHE).catch(() => null) ?? void 0;
|
|
4055
4158
|
const cyclePeaks = await buildCyclePeaksForPush(planTier, loadCalibrationCurve2);
|
|
4056
4159
|
if (rollups.length === 0) {
|
|
@@ -4264,17 +4367,21 @@ var PROMPT_FRAME_ORIGIN = {
|
|
|
4264
4367
|
};
|
|
4265
4368
|
|
|
4266
4369
|
// ../entries/dist/signals.js
|
|
4370
|
+
init_dist();
|
|
4267
4371
|
var TEAMMATE_RE = /^<teammate-message\b/;
|
|
4268
4372
|
var SKILL_LOAD_RE = /^Base directory for this skill:/;
|
|
4269
4373
|
var SLASH_COMMAND_RE2 = /^<command-name>|^<local-command-stdout>/;
|
|
4270
4374
|
function classifyUserInputSource(text) {
|
|
4271
4375
|
if (!text)
|
|
4272
4376
|
return "human";
|
|
4273
|
-
|
|
4377
|
+
const stripped = stripFrameworkBoilerplate(text);
|
|
4378
|
+
if (!stripped)
|
|
4379
|
+
return "system_instruction";
|
|
4380
|
+
if (TEAMMATE_RE.test(stripped))
|
|
4274
4381
|
return "teammate";
|
|
4275
|
-
if (SKILL_LOAD_RE.test(
|
|
4382
|
+
if (SKILL_LOAD_RE.test(stripped))
|
|
4276
4383
|
return "skill_load";
|
|
4277
|
-
if (SLASH_COMMAND_RE2.test(
|
|
4384
|
+
if (SLASH_COMMAND_RE2.test(stripped))
|
|
4278
4385
|
return "slash_command";
|
|
4279
4386
|
return "human";
|
|
4280
4387
|
}
|
|
@@ -4663,7 +4770,7 @@ function aggregateDay(dayEvents, _sessionFallbackProject) {
|
|
|
4663
4770
|
closeTurn(cur, closed, eventCwd);
|
|
4664
4771
|
}
|
|
4665
4772
|
cur = newTurn(tsMs, text);
|
|
4666
|
-
if (!firstUser && text &&
|
|
4773
|
+
if (!firstUser && text && classifyUserInputSource(text) === "human") {
|
|
4667
4774
|
firstUser = text;
|
|
4668
4775
|
}
|
|
4669
4776
|
} else {
|
|
@@ -4907,7 +5014,13 @@ function buildEntries(sessionDetail) {
|
|
|
4907
5014
|
return classifyUserInputSource(text) === "human";
|
|
4908
5015
|
}).map((ev) => blockText(ev.blocks) || ev.preview || "").join("\n");
|
|
4909
5016
|
const satisfaction_signals = countSatisfactionSignals(humanText);
|
|
4910
|
-
const user_input_sources = {
|
|
5017
|
+
const user_input_sources = {
|
|
5018
|
+
human: 0,
|
|
5019
|
+
teammate: 0,
|
|
5020
|
+
skill_load: 0,
|
|
5021
|
+
slash_command: 0,
|
|
5022
|
+
system_instruction: 0
|
|
5023
|
+
};
|
|
4911
5024
|
for (const ev of dayEvents) {
|
|
4912
5025
|
const v = viewEvent(ev);
|
|
4913
5026
|
if (v.rawType !== "user")
|
|
@@ -4955,28 +5068,28 @@ function buildEntries(sessionDetail) {
|
|
|
4955
5068
|
}
|
|
4956
5069
|
|
|
4957
5070
|
// ../entries/dist/fs.js
|
|
5071
|
+
init_fs();
|
|
4958
5072
|
import { readFileSync as readFileSync7, readdirSync as readdirSync2, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, renameSync as renameSync2, existsSync as existsSync4 } from "node:fs";
|
|
4959
5073
|
import { randomBytes } from "node:crypto";
|
|
4960
|
-
import { join as
|
|
4961
|
-
import { homedir as homedir6 } from "node:os";
|
|
5074
|
+
import { join as join4 } from "node:path";
|
|
4962
5075
|
|
|
4963
5076
|
// ../entries/dist/digest-fs.js
|
|
5077
|
+
init_fs();
|
|
4964
5078
|
import { readFileSync as readFileSync6, readdirSync, writeFileSync as writeFileSync4, renameSync, chmodSync, mkdirSync as mkdirSync5, existsSync as existsSync3 } from "node:fs";
|
|
4965
|
-
import { dirname as dirname4, join as
|
|
4966
|
-
import { homedir as homedir5 } from "node:os";
|
|
5079
|
+
import { dirname as dirname4, join as join3 } from "node:path";
|
|
4967
5080
|
var digestsDirCached = null;
|
|
4968
5081
|
function digestsDir() {
|
|
4969
5082
|
if (digestsDirCached)
|
|
4970
5083
|
return digestsDirCached;
|
|
4971
5084
|
const envOverride = process.env.CCLENS_DIGESTS_DIR;
|
|
4972
|
-
digestsDirCached = envOverride ??
|
|
5085
|
+
digestsDirCached = envOverride ?? cclensPath("digests");
|
|
4973
5086
|
return digestsDirCached;
|
|
4974
5087
|
}
|
|
4975
5088
|
function dayDigestPath(date) {
|
|
4976
|
-
return
|
|
5089
|
+
return join3(digestsDir(), "day", `${date}.json`);
|
|
4977
5090
|
}
|
|
4978
5091
|
function weekDigestPath(monday) {
|
|
4979
|
-
return
|
|
5092
|
+
return join3(digestsDir(), "week", `${monday}.json`);
|
|
4980
5093
|
}
|
|
4981
5094
|
function writeDayDigest(digest) {
|
|
4982
5095
|
const final = dayDigestPath(digest.key);
|
|
@@ -5060,11 +5173,11 @@ function entriesDir() {
|
|
|
5060
5173
|
if (entriesDirCached)
|
|
5061
5174
|
return entriesDirCached;
|
|
5062
5175
|
const envOverride = process.env.CCLENS_ENTRIES_DIR;
|
|
5063
|
-
entriesDirCached = envOverride ??
|
|
5176
|
+
entriesDirCached = envOverride ?? cclensPath("entries");
|
|
5064
5177
|
return entriesDirCached;
|
|
5065
5178
|
}
|
|
5066
5179
|
function pathFor(sessionId, localDay) {
|
|
5067
|
-
return
|
|
5180
|
+
return join4(entriesDir(), `${entryKey(sessionId, localDay)}.json`);
|
|
5068
5181
|
}
|
|
5069
5182
|
function tmpPathFor(final) {
|
|
5070
5183
|
return `${final}.tmp.${process.pid}.${randomBytes(4).toString("hex")}`;
|
|
@@ -5137,14 +5250,14 @@ function listEntriesForDay(localDay) {
|
|
|
5137
5250
|
}
|
|
5138
5251
|
|
|
5139
5252
|
// src/perception/state.ts
|
|
5253
|
+
init_fs();
|
|
5140
5254
|
import { existsSync as existsSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync6, mkdirSync as mkdirSync7, renameSync as renameSync3 } from "node:fs";
|
|
5141
|
-
import { dirname as dirname5
|
|
5142
|
-
import { homedir as homedir7 } from "node:os";
|
|
5255
|
+
import { dirname as dirname5 } from "node:path";
|
|
5143
5256
|
var STALE_MS = 15 * 60 * 1e3;
|
|
5144
5257
|
var pathCached = null;
|
|
5145
5258
|
function statePath() {
|
|
5146
5259
|
if (pathCached) return pathCached;
|
|
5147
|
-
pathCached =
|
|
5260
|
+
pathCached = cclensPath("perception-state.json");
|
|
5148
5261
|
return pathCached;
|
|
5149
5262
|
}
|
|
5150
5263
|
function readState() {
|
|
@@ -5194,17 +5307,17 @@ function updateCheckpoint(jsonlPath, cp) {
|
|
|
5194
5307
|
|
|
5195
5308
|
// src/perception/scan.ts
|
|
5196
5309
|
import { readdirSync as readdirSync3 } from "node:fs";
|
|
5197
|
-
import { join as
|
|
5198
|
-
import { homedir as
|
|
5310
|
+
import { join as join5 } from "node:path";
|
|
5311
|
+
import { homedir as homedir2 } from "node:os";
|
|
5199
5312
|
async function listAllSessionJsonls(root) {
|
|
5200
|
-
const projectsRoot = root ??
|
|
5313
|
+
const projectsRoot = root ?? join5(homedir2(), ".claude", "projects");
|
|
5201
5314
|
const out = [];
|
|
5202
5315
|
try {
|
|
5203
5316
|
for (const project of readdirSync3(projectsRoot)) {
|
|
5204
|
-
const dir =
|
|
5317
|
+
const dir = join5(projectsRoot, project);
|
|
5205
5318
|
try {
|
|
5206
5319
|
for (const f of readdirSync3(dir)) {
|
|
5207
|
-
if (f.endsWith(".jsonl")) out.push(
|
|
5320
|
+
if (f.endsWith(".jsonl")) out.push(join5(dir, f));
|
|
5208
5321
|
}
|
|
5209
5322
|
} catch {
|
|
5210
5323
|
}
|
|
@@ -9445,16 +9558,332 @@ ${turns || "(none \u2014 the user text was filtered out as non-human)"}`;
|
|
|
9445
9558
|
var ENRICHMENT_SYSTEM_PROMPT = SYSTEM_PROMPT;
|
|
9446
9559
|
|
|
9447
9560
|
// ../entries/dist/llm-runner.js
|
|
9561
|
+
init_fs();
|
|
9448
9562
|
import { spawn } from "node:child_process";
|
|
9449
|
-
import { mkdirSync as
|
|
9450
|
-
import {
|
|
9451
|
-
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";
|
|
9452
9565
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
9453
|
-
|
|
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");
|
|
9454
9883
|
function ensureRunsDir() {
|
|
9455
|
-
if (!
|
|
9884
|
+
if (!existsSync7(RUNS_DIR)) {
|
|
9456
9885
|
try {
|
|
9457
|
-
|
|
9886
|
+
mkdirSync9(RUNS_DIR, { recursive: true });
|
|
9458
9887
|
} catch {
|
|
9459
9888
|
}
|
|
9460
9889
|
}
|
|
@@ -9481,7 +9910,7 @@ function newRunId(kind) {
|
|
|
9481
9910
|
return `${ts}_${kind}_${short}`;
|
|
9482
9911
|
}
|
|
9483
9912
|
function tracePath(runId) {
|
|
9484
|
-
return
|
|
9913
|
+
return join7(RUNS_DIR, `${runId}.jsonl`);
|
|
9485
9914
|
}
|
|
9486
9915
|
function safeAppend(path5, line) {
|
|
9487
9916
|
try {
|
|
@@ -9491,11 +9920,84 @@ function safeAppend(path5, line) {
|
|
|
9491
9920
|
}
|
|
9492
9921
|
function safeWrite(path5, line) {
|
|
9493
9922
|
try {
|
|
9494
|
-
|
|
9923
|
+
writeFileSync8(path5, line);
|
|
9495
9924
|
} catch {
|
|
9496
9925
|
}
|
|
9497
9926
|
}
|
|
9498
|
-
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) {
|
|
9499
10001
|
return new Promise((resolve, reject) => {
|
|
9500
10002
|
ensureRunsDir();
|
|
9501
10003
|
const kind = detectKindFromSystemPrompt(args.systemPrompt);
|
|
@@ -9806,29 +10308,29 @@ function applyEnrichmentError(entry, errorMessage, model, costUsd, generatedAt,
|
|
|
9806
10308
|
}
|
|
9807
10309
|
|
|
9808
10310
|
// ../entries/dist/budget.js
|
|
9809
|
-
|
|
9810
|
-
import {
|
|
9811
|
-
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";
|
|
9812
10314
|
var spendPathCached = null;
|
|
9813
10315
|
function spendPath() {
|
|
9814
10316
|
if (spendPathCached)
|
|
9815
10317
|
return spendPathCached;
|
|
9816
|
-
spendPathCached =
|
|
10318
|
+
spendPathCached = cclensPath("llm-spend.jsonl");
|
|
9817
10319
|
return spendPathCached;
|
|
9818
10320
|
}
|
|
9819
10321
|
function appendSpend(record) {
|
|
9820
10322
|
const p = spendPath();
|
|
9821
|
-
|
|
10323
|
+
mkdirSync10(dirname7(p), { recursive: true });
|
|
9822
10324
|
appendFileSync4(p, JSON.stringify(record) + "\n", { encoding: "utf8" });
|
|
9823
10325
|
}
|
|
9824
10326
|
function monthToDateSpend(now = /* @__PURE__ */ new Date()) {
|
|
9825
10327
|
const p = spendPath();
|
|
9826
|
-
if (!
|
|
10328
|
+
if (!existsSync8(p))
|
|
9827
10329
|
return 0;
|
|
9828
10330
|
const year = now.getUTCFullYear();
|
|
9829
10331
|
const month = now.getUTCMonth();
|
|
9830
10332
|
let total = 0;
|
|
9831
|
-
const raw =
|
|
10333
|
+
const raw = readFileSync11(p, "utf8");
|
|
9832
10334
|
for (const line of raw.split("\n")) {
|
|
9833
10335
|
if (!line)
|
|
9834
10336
|
continue;
|
|
@@ -9849,9 +10351,8 @@ function monthToDateSpend(now = /* @__PURE__ */ new Date()) {
|
|
|
9849
10351
|
}
|
|
9850
10352
|
|
|
9851
10353
|
// ../entries/dist/pipeline-lock.js
|
|
9852
|
-
|
|
9853
|
-
import {
|
|
9854
|
-
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";
|
|
9855
10356
|
var STALE_MS2 = 60 * 1e3;
|
|
9856
10357
|
var HEARTBEAT_MS = 30 * 1e3;
|
|
9857
10358
|
var lockPathCached = null;
|
|
@@ -9859,11 +10360,11 @@ var heartbeat = null;
|
|
|
9859
10360
|
function lockPath() {
|
|
9860
10361
|
if (lockPathCached)
|
|
9861
10362
|
return lockPathCached;
|
|
9862
|
-
lockPathCached =
|
|
10363
|
+
lockPathCached = cclensPath("llm-interactive.lock");
|
|
9863
10364
|
return lockPathCached;
|
|
9864
10365
|
}
|
|
9865
10366
|
function touchLock() {
|
|
9866
|
-
|
|
10367
|
+
writeFileSync9(lockPath(), String(process.pid), "utf8");
|
|
9867
10368
|
}
|
|
9868
10369
|
function writeInteractiveLock() {
|
|
9869
10370
|
touchLock();
|
|
@@ -9883,7 +10384,7 @@ function removeInteractiveLock() {
|
|
|
9883
10384
|
heartbeat = null;
|
|
9884
10385
|
}
|
|
9885
10386
|
try {
|
|
9886
|
-
|
|
10387
|
+
unlinkSync3(lockPath());
|
|
9887
10388
|
} catch {
|
|
9888
10389
|
}
|
|
9889
10390
|
}
|
|
@@ -9897,13 +10398,13 @@ function pidAlive(pid) {
|
|
|
9897
10398
|
}
|
|
9898
10399
|
function interactiveLockFresh(nowMs) {
|
|
9899
10400
|
const p = lockPath();
|
|
9900
|
-
if (!
|
|
10401
|
+
if (!existsSync9(p))
|
|
9901
10402
|
return false;
|
|
9902
10403
|
try {
|
|
9903
10404
|
const mtime = statSync3(p).mtimeMs;
|
|
9904
10405
|
if (nowMs - mtime > STALE_MS2)
|
|
9905
10406
|
return false;
|
|
9906
|
-
const pid = Number(
|
|
10407
|
+
const pid = Number(readFileSync12(p, "utf8").trim());
|
|
9907
10408
|
if (!Number.isFinite(pid) || pid <= 0)
|
|
9908
10409
|
return false;
|
|
9909
10410
|
if (!pidAlive(pid))
|
|
@@ -9918,9 +10419,8 @@ function interactiveLockFresh(nowMs) {
|
|
|
9918
10419
|
var THIRTY_MIN_MS = 30 * 60 * 1e3;
|
|
9919
10420
|
|
|
9920
10421
|
// ../entries/dist/settings.js
|
|
9921
|
-
import { readFileSync as
|
|
9922
|
-
|
|
9923
|
-
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();
|
|
9924
10424
|
var DEFAULT_SETTINGS = {
|
|
9925
10425
|
ai_features: {
|
|
9926
10426
|
enabled: true,
|
|
@@ -9934,7 +10434,7 @@ var settingsPathCached = null;
|
|
|
9934
10434
|
function settingsPath() {
|
|
9935
10435
|
if (settingsPathCached)
|
|
9936
10436
|
return settingsPathCached;
|
|
9937
|
-
settingsPathCached =
|
|
10437
|
+
settingsPathCached = cclensPath("settings.json");
|
|
9938
10438
|
return settingsPathCached;
|
|
9939
10439
|
}
|
|
9940
10440
|
function fromDisk(d) {
|
|
@@ -9951,10 +10451,10 @@ function fromDisk(d) {
|
|
|
9951
10451
|
}
|
|
9952
10452
|
function readSettings() {
|
|
9953
10453
|
const p = settingsPath();
|
|
9954
|
-
if (!
|
|
10454
|
+
if (!existsSync10(p))
|
|
9955
10455
|
return DEFAULT_SETTINGS;
|
|
9956
10456
|
try {
|
|
9957
|
-
const raw =
|
|
10457
|
+
const raw = readFileSync13(p, "utf8");
|
|
9958
10458
|
return fromDisk(JSON.parse(raw));
|
|
9959
10459
|
} catch {
|
|
9960
10460
|
return DEFAULT_SETTINGS;
|
|
@@ -12677,11 +13177,10 @@ async function backfillYesterdayDigest(opts = {}) {
|
|
|
12677
13177
|
}
|
|
12678
13178
|
|
|
12679
13179
|
// src/daemon-worker.ts
|
|
12680
|
-
var
|
|
12681
|
-
var
|
|
12682
|
-
var DAEMON_LOG = join13(STATE_DIR, "daemon.log");
|
|
13180
|
+
var USAGE_LOG2 = cclensPath("usage.jsonl");
|
|
13181
|
+
var DAEMON_LOG = cclensPath("daemon.log");
|
|
12683
13182
|
var WATCHDOG_INTERVAL_MS = 5 * 1e3;
|
|
12684
|
-
|
|
13183
|
+
mkdirSync12(dirname8(USAGE_LOG2), { recursive: true });
|
|
12685
13184
|
function log2(level, message) {
|
|
12686
13185
|
const line = `${(/* @__PURE__ */ new Date()).toISOString()} ${level.toUpperCase()} ${message}
|
|
12687
13186
|
`;
|
|
@@ -12734,7 +13233,7 @@ async function tick() {
|
|
|
12734
13233
|
seven_day_cowork: null,
|
|
12735
13234
|
extra_usage: null
|
|
12736
13235
|
};
|
|
12737
|
-
appendSnapshot(
|
|
13236
|
+
appendSnapshot(USAGE_LOG2, snapshot);
|
|
12738
13237
|
log2(
|
|
12739
13238
|
"info",
|
|
12740
13239
|
`${source.kind} snapshot 5h=${snapshot.five_hour.utilization}% 7d=${snapshot.seven_day.utilization}%`
|
|
@@ -12745,7 +13244,7 @@ async function tick() {
|
|
|
12745
13244
|
}
|
|
12746
13245
|
try {
|
|
12747
13246
|
const snapshot = await fetchUsage();
|
|
12748
|
-
appendSnapshot(
|
|
13247
|
+
appendSnapshot(USAGE_LOG2, snapshot);
|
|
12749
13248
|
log2(
|
|
12750
13249
|
"info",
|
|
12751
13250
|
`claude-code snapshot 5h=${snapshot.five_hour.utilization}% 7d=${snapshot.seven_day.utilization}%`
|
|
@@ -12771,7 +13270,7 @@ function scheduleAfter(now, outcome) {
|
|
|
12771
13270
|
}
|
|
12772
13271
|
nextPollAtMs = now + currentIntervalMs;
|
|
12773
13272
|
}
|
|
12774
|
-
function
|
|
13273
|
+
function sleep2(ms) {
|
|
12775
13274
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
12776
13275
|
}
|
|
12777
13276
|
async function runLoop() {
|
|
@@ -12804,7 +13303,7 @@ async function runLoop() {
|
|
|
12804
13303
|
}
|
|
12805
13304
|
await runTeamSync(log2);
|
|
12806
13305
|
}
|
|
12807
|
-
await
|
|
13306
|
+
await sleep2(WATCHDOG_INTERVAL_MS);
|
|
12808
13307
|
}
|
|
12809
13308
|
}
|
|
12810
13309
|
log2(
|