fleetlens 0.15.2 → 0.15.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/apps/web/.next/BUILD_ID +1 -1
- package/app/apps/web/.next/app-path-routes-manifest.json +3 -0
- 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/routes-manifest.json +18 -0
- package/app/apps/web/.next/server/app/_global-error.html +1 -1
- package/app/apps/web/.next/server/app/_global-error.rsc +1 -1
- package/app/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/app/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/app/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/app/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/app/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/app/apps/web/.next/server/app/_not-found/page.js +1 -1
- package/app/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/api/ask/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/month-index/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/digest/week-index/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/menubar/route/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/api/menubar/route/build-manifest.json +9 -0
- package/app/apps/web/.next/server/app/api/menubar/route/server-reference-manifest.json +4 -0
- package/app/apps/web/.next/server/app/api/menubar/route.js +6 -0
- package/app/apps/web/.next/server/app/api/menubar/route.js.map +5 -0
- package/app/apps/web/.next/server/app/api/menubar/route.js.nft.json +1 -0
- package/app/apps/web/.next/server/app/api/menubar/route_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/api/pdf/[key]/route.js +1 -1
- package/app/apps/web/.next/server/app/api/pdf/[key]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/projects/open-folder/route/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/api/projects/open-folder/route/build-manifest.json +9 -0
- package/app/apps/web/.next/server/app/api/projects/open-folder/route/server-reference-manifest.json +4 -0
- package/app/apps/web/.next/server/app/api/projects/open-folder/route.js +7 -0
- package/app/apps/web/.next/server/app/api/projects/open-folder/route.js.map +5 -0
- package/app/apps/web/.next/server/app/api/projects/open-folder/route.js.nft.json +1 -0
- package/app/apps/web/.next/server/app/api/projects/open-folder/route_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/api/runs/[runId]/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/api/settings/credentials/route/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/app/api/settings/credentials/route/build-manifest.json +9 -0
- package/app/apps/web/.next/server/app/api/settings/credentials/route/server-reference-manifest.json +4 -0
- package/app/apps/web/.next/server/app/api/settings/credentials/route.js +10 -0
- package/app/apps/web/.next/server/app/api/settings/credentials/route.js.map +5 -0
- package/app/apps/web/.next/server/app/api/settings/credentials/route.js.nft.json +1 -0
- package/app/apps/web/.next/server/app/api/settings/credentials/route_client-reference-manifest.js +3 -0
- package/app/apps/web/.next/server/app/api/settings/route.js +4 -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 +1 -1
- package/app/apps/web/.next/server/app/changelog/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/changelog/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/day/[date]/page.js +1 -1
- package/app/apps/web/.next/server/app/day/[date]/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/day/[date]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/day/page.js +1 -1
- package/app/apps/web/.next/server/app/day/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/day/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/digest/[date]/page.js +1 -1
- package/app/apps/web/.next/server/app/digest/[date]/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/digest/[date]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/digest/page.js +1 -1
- package/app/apps/web/.next/server/app/digest/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/digest/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/insights/[key]/page.js +1 -1
- package/app/apps/web/.next/server/app/insights/[key]/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/insights/[key]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/insights/page.js +1 -1
- package/app/apps/web/.next/server/app/insights/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/insights/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/page.js +1 -1
- package/app/apps/web/.next/server/app/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/parallelism/page.js +1 -1
- package/app/apps/web/.next/server/app/parallelism/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/parallelism/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/print/[key]/page.js +1 -1
- package/app/apps/web/.next/server/app/print/[key]/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/print/[key]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/projects/[slug]/page.js +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 +1 -1
- package/app/apps/web/.next/server/app/projects/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/runs/page.js +1 -1
- package/app/apps/web/.next/server/app/runs/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/runs/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/sessions/[id]/page.js +1 -1
- package/app/apps/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/sessions/page.js +1 -1
- package/app/apps/web/.next/server/app/sessions/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/settings/page.js +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/team/onboarding/page.js +1 -1
- package/app/apps/web/.next/server/app/team/onboarding/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/team/onboarding/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/team/page.js +1 -1
- package/app/apps/web/.next/server/app/team/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/team/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/usage/page.js +1 -1
- package/app/apps/web/.next/server/app/usage/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/usage/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app-paths-manifest.json +3 -0
- package/app/apps/web/.next/server/chunks/02dz_web__next-internal_server_app_api_projects_open-folder_route_actions_0m~419c.js +3 -0
- package/app/apps/web/.next/server/chunks/02dz_web__next-internal_server_app_api_settings_credentials_route_actions_04an_i2.js +3 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__05z0pcw._.js +3 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0_nle98._.js +3 -0
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0b5r~-1._.js +3 -0
- package/app/apps/web/.next/server/chunks/{[root-of-the-server]__0a0~7d6._.js → [root-of-the-server]__0t7i-hy._.js} +2 -2
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__12iid50._.js +3 -0
- package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_menubar_route_actions_0xep8_i.js +3 -0
- package/app/apps/web/.next/server/chunks/{node_modules_next_036my~r._.js → node_modules_next_04~_e52._.js} +5 -5
- package/app/apps/web/.next/server/chunks/packages_entries_dist_node_0bckr7-.js +14 -14
- package/app/apps/web/.next/server/chunks/packages_parser_dist_06d9se1._.js +1 -1
- package/app/apps/web/.next/server/chunks/packages_parser_dist_10ihc3~._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0.zquoa._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__03svi~4._.js +8 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__04eq6z2._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__04il6m2._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__08l86e-._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__09rjz7_._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0ar_8wr._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__10~b4bf._.js → [root-of-the-server]__0blm9gz._.js} +3 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0e.gxk3._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0g-tomj._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0i.q-1h._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0k1x-c9._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0lz4a~g._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0nr2~y1._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0o1_g.~._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0p1x6v2._.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]__0rvzdnx._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0stu~~r._.js +1 -1
- 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]__0u39afl._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0ufi3.w._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0xy1qim._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0~.f_3z._.js +3 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__10srpu0._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__10xgshr._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/_02r-a1a._.js +8 -0
- package/app/apps/web/.next/server/chunks/ssr/_0k62ejd._.js +8 -0
- package/app/apps/web/.next/server/chunks/ssr/{_0xu2pvc._.js → _0k8yioi._.js} +2 -2
- package/app/apps/web/.next/server/chunks/ssr/{_0wj750k._.js → _0t~mx7w._.js} +2 -2
- package/app/apps/web/.next/server/chunks/ssr/{_0kajk31._.js → _0whg~r-._.js} +2 -2
- package/app/apps/web/.next/server/chunks/ssr/_13jdm1g._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_0~aj0~u._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_app_sessions_sessions-grid_tsx_0bri5x.._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0x014hn._.js +16 -0
- package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_changelog_ts_0n7_p1d._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_changelog_ts_0nb5_-s._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/node_modules_lucide-react_dist_esm_icons_12vc-v-._.js +3 -0
- 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_0mx_509._.js +1 -1
- package/app/apps/web/.next/server/functions-config-manifest.json +3 -0
- package/app/apps/web/.next/server/middleware-build-manifest.js +3 -3
- package/app/apps/web/.next/server/middleware-manifest.json +5 -5
- package/app/apps/web/.next/server/pages/500.html +1 -1
- package/app/apps/web/.next/server/server-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/server-reference-manifest.json +1 -1
- package/app/apps/web/.next/static/chunks/0-z49mtd-zwgv.js +1 -0
- package/app/apps/web/.next/static/chunks/043slkg3juwck.js +1 -0
- package/app/apps/web/.next/static/chunks/{0~qdw1b2uz._5.js → 044mtrzh7d7va.js} +3 -3
- package/app/apps/web/.next/static/chunks/05b0dn.r00hq1.js +1 -0
- package/app/apps/web/.next/static/chunks/{14vx702c32kn6.js → 0_0~~ipv90vm3.js} +1 -1
- package/app/apps/web/.next/static/chunks/0awkd5df28gvj.js +6 -0
- package/app/apps/web/.next/static/chunks/{0m7dd-2zd9vl2.js → 0eoc4yy0s0gpe.js} +1 -1
- package/app/apps/web/.next/static/chunks/0g0hv.dt-de9g.js +14 -0
- package/app/apps/web/.next/static/chunks/0rsp61c8wb.sx.js +6 -0
- package/app/apps/web/.next/static/chunks/{03rd.3cc_t~yf.js → 0s~0-8l~_kqnf.js} +1 -1
- package/app/apps/web/.next/static/chunks/0t2on1dhydyb2.css +1 -0
- package/app/apps/web/.next/static/chunks/0y3448zrint0k.js +6 -0
- package/app/apps/web/app/api/menubar/route.ts +66 -0
- package/app/apps/web/app/api/projects/open-folder/route.ts +60 -0
- package/app/apps/web/app/api/settings/credentials/route.ts +45 -0
- package/app/apps/web/app/layout.tsx +2 -0
- package/app/apps/web/app/projects/[slug]/local-folders-button.tsx +406 -0
- package/app/apps/web/app/projects/[slug]/page.tsx +155 -20
- package/app/apps/web/app/projects/page.tsx +2 -2
- package/app/apps/web/app/sessions/[id]/page.tsx +4 -1
- package/app/apps/web/app/sessions/[id]/session-view/header-stats.tsx +81 -0
- package/app/apps/web/app/sessions/[id]/session-view.tsx +11 -0
- package/app/apps/web/app/sessions/sessions-grid.tsx +56 -25
- package/app/apps/web/app/settings/page.tsx +26 -0
- package/app/apps/web/app/usage/page.tsx +80 -0
- package/app/apps/web/components/menubar-install-banner.tsx +117 -0
- package/app/apps/web/components/menubar-install.tsx +107 -0
- package/app/apps/web/components/zai-credentials-form.tsx +116 -0
- package/app/apps/web/lib/changelog-data.generated.ts +1 -1
- package/app/apps/web/lib/entries-index.ts +4 -4
- package/app/apps/web/lib/menubar-data.ts +50 -0
- package/app/apps/web/lib/usage-data.ts +4 -0
- package/app/apps/web/package.json +1 -1
- package/app/apps/web/tsconfig.tsbuildinfo +1 -1
- package/dist/daemon-worker.js +640 -240
- package/dist/index.js +938 -283
- package/package.json +3 -2
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__065lib8._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0a7n44-._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0c00i76._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0lhwp-k._.js +0 -8
- package/app/apps/web/.next/server/chunks/ssr/_0s3n5mz._.js +0 -8
- package/app/apps/web/.next/server/chunks/ssr/_12mbgs5._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/apps_web_0q2x4a~._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0b-4-4j._.js +0 -8
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0txtsv5._.js +0 -16
- package/app/apps/web/.next/server/chunks/ssr/node_modules_lucide-react_dist_esm_icons_0cepfi8._.js +0 -3
- package/app/apps/web/.next/static/chunks/00a9oyw~h5i1p.js +0 -1
- package/app/apps/web/.next/static/chunks/03gy1evbn94qu.js +0 -6
- package/app/apps/web/.next/static/chunks/040s42ypidk7s.css +0 -1
- package/app/apps/web/.next/static/chunks/0d2x-wfu.m0-z.js +0 -6
- package/app/apps/web/.next/static/chunks/0i77er85v.rj..js +0 -1
- package/app/apps/web/.next/static/chunks/0nqklmbs5s3ax.js +0 -6
- package/app/apps/web/.next/static/chunks/0tirv_vo6q8uc.js +0 -1
- package/app/apps/web/.next/static/chunks/0u6gxpqhl0gc7.js +0 -14
- /package/app/apps/web/.next/static/{mTj8nKiazosAKJec15dLe → nmAGY0LiBgXuibWTKZ1RD}/_buildManifest.js +0 -0
- /package/app/apps/web/.next/static/{mTj8nKiazosAKJec15dLe → nmAGY0LiBgXuibWTKZ1RD}/_clientMiddlewareManifest.js +0 -0
- /package/app/apps/web/.next/static/{mTj8nKiazosAKJec15dLe → nmAGY0LiBgXuibWTKZ1RD}/_ssgManifest.js +0 -0
package/dist/index.js
CHANGED
|
@@ -148,11 +148,22 @@ function worktreeName(projectName) {
|
|
|
148
148
|
return ss.workspaceName;
|
|
149
149
|
return null;
|
|
150
150
|
}
|
|
151
|
-
function
|
|
151
|
+
function projectKey(projectName) {
|
|
152
152
|
const canonical = canonicalProjectName(projectName);
|
|
153
153
|
const segs = canonical.replace(/\/+$/, "").split("/").filter(Boolean);
|
|
154
154
|
return segs[segs.length - 1] || canonical;
|
|
155
155
|
}
|
|
156
|
+
function sessionProjectKey(s) {
|
|
157
|
+
return s.repoName ?? projectKey(s.projectName);
|
|
158
|
+
}
|
|
159
|
+
function buildProjectKeyResolver(sessions) {
|
|
160
|
+
const alias = /* @__PURE__ */ new Map();
|
|
161
|
+
for (const s of sessions) {
|
|
162
|
+
if (s.repoName)
|
|
163
|
+
alias.set(projectKey(s.projectName), s.repoName);
|
|
164
|
+
}
|
|
165
|
+
return (s) => s.repoName ?? alias.get(projectKey(s.projectName)) ?? projectKey(s.projectName);
|
|
166
|
+
}
|
|
156
167
|
function makeDay(date) {
|
|
157
168
|
return {
|
|
158
169
|
date,
|
|
@@ -587,8 +598,9 @@ function summarizeBursts(bursts) {
|
|
|
587
598
|
}
|
|
588
599
|
function groupByProject(sessions) {
|
|
589
600
|
const map = /* @__PURE__ */ new Map();
|
|
601
|
+
const keyOf = buildProjectKeyResolver(sessions);
|
|
590
602
|
for (const s of sessions) {
|
|
591
|
-
const repo =
|
|
603
|
+
const repo = keyOf(s);
|
|
592
604
|
const key = repo;
|
|
593
605
|
let cur = map.get(key);
|
|
594
606
|
if (!cur) {
|
|
@@ -617,7 +629,7 @@ function groupByProject(sessions) {
|
|
|
617
629
|
p.metrics = highLevelMetrics(p.sessions);
|
|
618
630
|
const wtNames = /* @__PURE__ */ new Set();
|
|
619
631
|
for (const s of p.sessions) {
|
|
620
|
-
const wt = worktreeName(s.projectName);
|
|
632
|
+
const wt = s.worktreeName ?? worktreeName(s.projectName) ?? (s.cwd ? worktreeName(s.cwd) : null);
|
|
621
633
|
if (wt)
|
|
622
634
|
wtNames.add(wt);
|
|
623
635
|
}
|
|
@@ -636,7 +648,7 @@ function groupByProject(sessions) {
|
|
|
636
648
|
}
|
|
637
649
|
return Array.from(map.values()).sort((a, b) => (b.lastActiveMs ?? 0) - (a.lastActiveMs ?? 0));
|
|
638
650
|
}
|
|
639
|
-
var BLANK_USAGE, WORKTREE_MARKERS, CONDUCTOR_RE, SUPERSET_MARKER, UUID_SEG_RE, PR_CREATE_RE, PR_NUMBER_RE, TITLE_FLAG_RE;
|
|
651
|
+
var BLANK_USAGE, WORKTREE_MARKERS, CONDUCTOR_RE, SUPERSET_MARKER, UUID_SEG_RE, projectRepoName, PR_CREATE_RE, PR_NUMBER_RE, TITLE_FLAG_RE;
|
|
640
652
|
var init_analytics = __esm({
|
|
641
653
|
"../parser/dist/analytics.js"() {
|
|
642
654
|
"use strict";
|
|
@@ -649,6 +661,7 @@ var init_analytics = __esm({
|
|
|
649
661
|
CONDUCTOR_RE = /\/conductor\/workspaces\/[^/]+\/([^/]+)(?:\/|$)/;
|
|
650
662
|
SUPERSET_MARKER = "/.superset/worktrees/";
|
|
651
663
|
UUID_SEG_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
664
|
+
projectRepoName = projectKey;
|
|
652
665
|
PR_CREATE_RE = /gh\s+pr\s+create\b/i;
|
|
653
666
|
PR_NUMBER_RE = /#(\d+)/;
|
|
654
667
|
TITLE_FLAG_RE = /--title\s+["']([^"']+)["']/;
|
|
@@ -662,7 +675,7 @@ function getAgentMetadata(kind) {
|
|
|
662
675
|
function isAgentKind(s) {
|
|
663
676
|
return typeof s === "string" && KNOWN_AGENT_KINDS.has(s);
|
|
664
677
|
}
|
|
665
|
-
var CLAUDE_CODE_METADATA, CODEX_METADATA, GEMINI_METADATA, ANTIGRAVITY_METADATA, COWORK_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
|
|
678
|
+
var CLAUDE_CODE_METADATA, CODEX_METADATA, GEMINI_METADATA, ANTIGRAVITY_METADATA, COWORK_METADATA, ZAI_METADATA, agentMetadata, KNOWN_AGENT_KINDS;
|
|
666
679
|
var init_agent_metadata = __esm({
|
|
667
680
|
"../parser/dist/agent-metadata.js"() {
|
|
668
681
|
"use strict";
|
|
@@ -701,12 +714,20 @@ var init_agent_metadata = __esm({
|
|
|
701
714
|
accentColor: "rgb(217, 119, 87)",
|
|
702
715
|
iconChar: "\u2318"
|
|
703
716
|
};
|
|
717
|
+
ZAI_METADATA = {
|
|
718
|
+
kind: "zai",
|
|
719
|
+
displayName: "Z.ai",
|
|
720
|
+
shortLabel: "Z.ai",
|
|
721
|
+
accentColor: "rgb(59, 130, 246)",
|
|
722
|
+
iconChar: "Z"
|
|
723
|
+
};
|
|
704
724
|
agentMetadata = [
|
|
705
725
|
CLAUDE_CODE_METADATA,
|
|
706
726
|
CODEX_METADATA,
|
|
707
727
|
GEMINI_METADATA,
|
|
708
728
|
ANTIGRAVITY_METADATA,
|
|
709
|
-
COWORK_METADATA
|
|
729
|
+
COWORK_METADATA,
|
|
730
|
+
ZAI_METADATA
|
|
710
731
|
];
|
|
711
732
|
KNOWN_AGENT_KINDS = new Set(agentMetadata.map((m) => m.kind));
|
|
712
733
|
}
|
|
@@ -1447,6 +1468,187 @@ var init_parser = __esm({
|
|
|
1447
1468
|
}
|
|
1448
1469
|
});
|
|
1449
1470
|
|
|
1471
|
+
// ../parser/dist/git-project.js
|
|
1472
|
+
import { existsSync, readFileSync as readFileSync2, realpathSync, statSync } from "node:fs";
|
|
1473
|
+
import { homedir } from "node:os";
|
|
1474
|
+
import { basename, dirname as dirname2, isAbsolute, join, resolve } from "node:path";
|
|
1475
|
+
function resolveGitDir(root, dotGitText) {
|
|
1476
|
+
const m = dotGitText.match(/^gitdir:\s*(.+)\s*$/m);
|
|
1477
|
+
if (!m)
|
|
1478
|
+
return void 0;
|
|
1479
|
+
const gitDir = m[1].trim();
|
|
1480
|
+
return isAbsolute(gitDir) ? gitDir : resolve(root, gitDir);
|
|
1481
|
+
}
|
|
1482
|
+
function resolveCommonDir(gitDir) {
|
|
1483
|
+
const file = join(gitDir, "commondir");
|
|
1484
|
+
if (!existsSync(file))
|
|
1485
|
+
return void 0;
|
|
1486
|
+
const common = readFileSync2(file, "utf8").trim();
|
|
1487
|
+
if (!common)
|
|
1488
|
+
return void 0;
|
|
1489
|
+
return isAbsolute(common) ? common : resolve(gitDir, common);
|
|
1490
|
+
}
|
|
1491
|
+
function dotGitInfoFor(root) {
|
|
1492
|
+
const dotGit = join(root, ".git");
|
|
1493
|
+
const st = statSync(dotGit, { throwIfNoEntry: false });
|
|
1494
|
+
if (!st)
|
|
1495
|
+
return null;
|
|
1496
|
+
if (st.isDirectory())
|
|
1497
|
+
return { root, gitDir: dotGit, commonDir: dotGit };
|
|
1498
|
+
const gitDir = resolveGitDir(root, readFileSync2(dotGit, "utf8"));
|
|
1499
|
+
if (!gitDir)
|
|
1500
|
+
return { root };
|
|
1501
|
+
return { root, gitDir, commonDir: resolveCommonDir(gitDir) };
|
|
1502
|
+
}
|
|
1503
|
+
function walkBoundary(start2) {
|
|
1504
|
+
const home = realpathOrSelf(homedir());
|
|
1505
|
+
return start2 === home || start2.startsWith(`${home}/`) ? home : void 0;
|
|
1506
|
+
}
|
|
1507
|
+
function nearestDotGit(start2) {
|
|
1508
|
+
if (!start2 || !isAbsolute(start2))
|
|
1509
|
+
return null;
|
|
1510
|
+
const boundary = walkBoundary(start2);
|
|
1511
|
+
for (let dir = start2.replace(/\/+$/, "") || start2; ; dir = dirname2(dir)) {
|
|
1512
|
+
if (dir === boundary)
|
|
1513
|
+
return null;
|
|
1514
|
+
const info = dotGitInfoFor(dir);
|
|
1515
|
+
if (info)
|
|
1516
|
+
return info;
|
|
1517
|
+
const parent = dirname2(dir);
|
|
1518
|
+
if (parent === dir)
|
|
1519
|
+
return null;
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
function originUrl(configText) {
|
|
1523
|
+
let inOrigin = false;
|
|
1524
|
+
for (const line of configText.split("\n")) {
|
|
1525
|
+
const t = line.trim();
|
|
1526
|
+
if (t.startsWith("[")) {
|
|
1527
|
+
inOrigin = /^\[remote\s+"origin"\]/.test(t);
|
|
1528
|
+
continue;
|
|
1529
|
+
}
|
|
1530
|
+
if (!inOrigin)
|
|
1531
|
+
continue;
|
|
1532
|
+
const m = t.match(/^url\s*=\s*(.+)$/);
|
|
1533
|
+
if (m)
|
|
1534
|
+
return m[1].trim();
|
|
1535
|
+
}
|
|
1536
|
+
return void 0;
|
|
1537
|
+
}
|
|
1538
|
+
function parseRemote(url) {
|
|
1539
|
+
const m = url.match(REMOTE_URL_RE);
|
|
1540
|
+
if (!m)
|
|
1541
|
+
return void 0;
|
|
1542
|
+
const host = m[1];
|
|
1543
|
+
const segs = m[2].split("/").filter(Boolean);
|
|
1544
|
+
if (segs.length < 2)
|
|
1545
|
+
return void 0;
|
|
1546
|
+
const name = segs[segs.length - 1];
|
|
1547
|
+
const owner = segs.slice(0, -1).join("/");
|
|
1548
|
+
return { host, owner, name, url, webUrl: `https://${host}/${owner}/${name}` };
|
|
1549
|
+
}
|
|
1550
|
+
function remoteFor(git) {
|
|
1551
|
+
const dir = git.commonDir ?? git.gitDir;
|
|
1552
|
+
if (!dir)
|
|
1553
|
+
return void 0;
|
|
1554
|
+
const config = join(dir, "config");
|
|
1555
|
+
if (!existsSync(config))
|
|
1556
|
+
return void 0;
|
|
1557
|
+
const url = originUrl(readFileSync2(config, "utf8"));
|
|
1558
|
+
return url ? parseRemote(url) : void 0;
|
|
1559
|
+
}
|
|
1560
|
+
function headBranch(gitDir) {
|
|
1561
|
+
if (!gitDir)
|
|
1562
|
+
return void 0;
|
|
1563
|
+
const head = join(gitDir, "HEAD");
|
|
1564
|
+
if (!existsSync(head))
|
|
1565
|
+
return void 0;
|
|
1566
|
+
const t = readFileSync2(head, "utf8").trim();
|
|
1567
|
+
const m = t.match(/^ref:\s*refs\/heads\/(.+)$/);
|
|
1568
|
+
return m ? m[1] : `detached @ ${t.slice(0, 7)}`;
|
|
1569
|
+
}
|
|
1570
|
+
function defaultBranch(commonDir) {
|
|
1571
|
+
if (!commonDir)
|
|
1572
|
+
return void 0;
|
|
1573
|
+
const head = join(commonDir, "refs", "remotes", "origin", "HEAD");
|
|
1574
|
+
if (existsSync(head)) {
|
|
1575
|
+
const m = readFileSync2(head, "utf8").trim().match(/refs\/remotes\/origin\/(.+)$/);
|
|
1576
|
+
if (m)
|
|
1577
|
+
return m[1];
|
|
1578
|
+
}
|
|
1579
|
+
const packed = join(commonDir, "packed-refs");
|
|
1580
|
+
if (existsSync(packed)) {
|
|
1581
|
+
const m = readFileSync2(packed, "utf8").match(/refs\/remotes\/origin\/(\S+)/);
|
|
1582
|
+
if (m && m[1] !== "HEAD")
|
|
1583
|
+
return m[1];
|
|
1584
|
+
}
|
|
1585
|
+
return void 0;
|
|
1586
|
+
}
|
|
1587
|
+
function readGitFolder(path7) {
|
|
1588
|
+
if (!existsSync(path7))
|
|
1589
|
+
return { exists: false, isWorktree: false };
|
|
1590
|
+
try {
|
|
1591
|
+
const git = nearestDotGit(realpathOrSelf(path7));
|
|
1592
|
+
if (!git)
|
|
1593
|
+
return { exists: true, isWorktree: false };
|
|
1594
|
+
const projectRoot = projectRootFromCommonDir(git.commonDir);
|
|
1595
|
+
const isWorktree = !!projectRoot && realpathOrSelf(projectRoot) !== realpathOrSelf(git.root);
|
|
1596
|
+
return {
|
|
1597
|
+
exists: true,
|
|
1598
|
+
isWorktree,
|
|
1599
|
+
branch: headBranch(git.gitDir),
|
|
1600
|
+
defaultBranch: defaultBranch(git.commonDir),
|
|
1601
|
+
remote: remoteFor(git)
|
|
1602
|
+
};
|
|
1603
|
+
} catch {
|
|
1604
|
+
return { exists: true, isWorktree: false };
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
function projectRootFromCommonDir(commonDir) {
|
|
1608
|
+
if (!commonDir)
|
|
1609
|
+
return void 0;
|
|
1610
|
+
return basename(commonDir) === ".git" ? dirname2(commonDir) : void 0;
|
|
1611
|
+
}
|
|
1612
|
+
function realpathOrSelf(p) {
|
|
1613
|
+
try {
|
|
1614
|
+
return realpathSync(p);
|
|
1615
|
+
} catch {
|
|
1616
|
+
return p;
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
function resolveProjectIdentity(cwd) {
|
|
1620
|
+
const normalized = realpathOrSelf(cwd.replace(/\/{2,}/g, "/"));
|
|
1621
|
+
try {
|
|
1622
|
+
const git = nearestDotGit(normalized);
|
|
1623
|
+
if (git) {
|
|
1624
|
+
const projectRoot = realpathOrSelf(projectRootFromCommonDir(git.commonDir) ?? git.root);
|
|
1625
|
+
const gitRoot = realpathOrSelf(git.root);
|
|
1626
|
+
const wt2 = projectRoot !== gitRoot ? worktreeName(normalized) ?? basename(git.root) : void 0;
|
|
1627
|
+
const identity = { projectName: projectRoot };
|
|
1628
|
+
if (wt2)
|
|
1629
|
+
identity.worktreeName = wt2;
|
|
1630
|
+
const remote = remoteFor(git);
|
|
1631
|
+
if (remote) {
|
|
1632
|
+
identity.remote = remote;
|
|
1633
|
+
identity.repoName = remote.name;
|
|
1634
|
+
}
|
|
1635
|
+
return identity;
|
|
1636
|
+
}
|
|
1637
|
+
} catch {
|
|
1638
|
+
}
|
|
1639
|
+
const projectName = canonicalProjectName(normalized);
|
|
1640
|
+
const wt = worktreeName(normalized) ?? void 0;
|
|
1641
|
+
return wt ? { projectName, worktreeName: wt } : { projectName };
|
|
1642
|
+
}
|
|
1643
|
+
var REMOTE_URL_RE;
|
|
1644
|
+
var init_git_project = __esm({
|
|
1645
|
+
"../parser/dist/git-project.js"() {
|
|
1646
|
+
"use strict";
|
|
1647
|
+
init_analytics();
|
|
1648
|
+
REMOTE_URL_RE = /^(?:(?:https?|ssh|git):\/\/)?(?:[^@/]+@)?([^/:]+)[:/](.+?)(?:\.git)?\/?$/;
|
|
1649
|
+
}
|
|
1650
|
+
});
|
|
1651
|
+
|
|
1450
1652
|
// ../parser/dist/team.js
|
|
1451
1653
|
function groupByTeam(sessions, details) {
|
|
1452
1654
|
const byTeam = /* @__PURE__ */ new Map();
|
|
@@ -1915,12 +2117,16 @@ async function getCachedMeta(f) {
|
|
|
1915
2117
|
const sessionId = sessionIdFromFileName(f.fileName);
|
|
1916
2118
|
const projectDirPath = path.dirname(f.fullPath);
|
|
1917
2119
|
const wf = await scanWorkflowAggregate(projectDirPath, sessionId);
|
|
2120
|
+
const cwd = meta.cwd ?? decodeProjectName(f.projectDir);
|
|
2121
|
+
const project = resolveProjectIdentity(cwd);
|
|
1918
2122
|
const full = {
|
|
1919
2123
|
...meta,
|
|
1920
2124
|
id: sessionId,
|
|
1921
2125
|
filePath: f.fullPath,
|
|
1922
2126
|
projectDir: f.projectDir,
|
|
1923
|
-
projectName:
|
|
2127
|
+
projectName: project.projectName,
|
|
2128
|
+
worktreeName: project.worktreeName,
|
|
2129
|
+
repoName: project.repoName,
|
|
1924
2130
|
...wf.workflowCount > 0 ? { workflowCount: wf.workflowCount, spawnedAgentCount: wf.spawnedAgentCount } : {},
|
|
1925
2131
|
...foldWorkflowAgentTime(meta.activeSegments, wf.spans)
|
|
1926
2132
|
};
|
|
@@ -1941,12 +2147,16 @@ async function getCachedDetail(f) {
|
|
|
1941
2147
|
const sessionId = sessionIdFromFileName(f.fileName);
|
|
1942
2148
|
await applySubagentUsage(meta, rawLines, f);
|
|
1943
2149
|
const wf = await scanWorkflowAggregate(path.dirname(f.fullPath), sessionId);
|
|
2150
|
+
const cwd = meta.cwd ?? decodeProjectName(f.projectDir);
|
|
2151
|
+
const project = resolveProjectIdentity(cwd);
|
|
1944
2152
|
const detail = {
|
|
1945
2153
|
...meta,
|
|
1946
2154
|
id: sessionId,
|
|
1947
2155
|
filePath: f.fullPath,
|
|
1948
2156
|
projectDir: f.projectDir,
|
|
1949
|
-
projectName:
|
|
2157
|
+
projectName: project.projectName,
|
|
2158
|
+
worktreeName: project.worktreeName,
|
|
2159
|
+
repoName: project.repoName,
|
|
1950
2160
|
events,
|
|
1951
2161
|
...wf.workflowCount > 0 ? { workflowCount: wf.workflowCount, spawnedAgentCount: wf.spawnedAgentCount } : {},
|
|
1952
2162
|
...foldWorkflowAgentTime(meta.activeSegments, wf.spans)
|
|
@@ -2438,19 +2648,25 @@ async function listProjects(root = DEFAULT_ROOT) {
|
|
|
2438
2648
|
cur.lastActiveMs = f.mtimeMs;
|
|
2439
2649
|
byRawDir.set(f.projectDir, cur);
|
|
2440
2650
|
}
|
|
2441
|
-
const
|
|
2651
|
+
const cachedIdentityForProject = (dir) => {
|
|
2442
2652
|
for (const [, entry] of metaCache.entries()) {
|
|
2443
|
-
if (entry.meta.projectDir === dir
|
|
2444
|
-
return
|
|
2653
|
+
if (entry.meta.projectDir === dir) {
|
|
2654
|
+
return {
|
|
2655
|
+
cwd: entry.meta.cwd,
|
|
2656
|
+
projectName: entry.meta.projectName,
|
|
2657
|
+
worktreeName: entry.meta.worktreeName
|
|
2658
|
+
};
|
|
2445
2659
|
}
|
|
2446
2660
|
}
|
|
2447
2661
|
return void 0;
|
|
2448
2662
|
};
|
|
2449
2663
|
const canonicalMap = /* @__PURE__ */ new Map();
|
|
2450
2664
|
for (const [rawDir, { count, lastActiveMs }] of byRawDir) {
|
|
2451
|
-
const
|
|
2452
|
-
const
|
|
2453
|
-
const
|
|
2665
|
+
const cached = cachedIdentityForProject(rawDir);
|
|
2666
|
+
const cwdOrDecoded = cached?.cwd ?? decodeProjectName(rawDir);
|
|
2667
|
+
const projectName = cached?.projectName ?? canonicalProjectName(cwdOrDecoded);
|
|
2668
|
+
const wt = cached?.worktreeName ?? worktreeName(cwdOrDecoded) ?? void 0;
|
|
2669
|
+
const repo = projectKey(projectName);
|
|
2454
2670
|
const agg = canonicalMap.get(repo) ?? {
|
|
2455
2671
|
canonicalName: repo,
|
|
2456
2672
|
count: 0,
|
|
@@ -2516,6 +2732,7 @@ var init_claude_code = __esm({
|
|
|
2516
2732
|
"use strict";
|
|
2517
2733
|
init_parser();
|
|
2518
2734
|
init_analytics();
|
|
2735
|
+
init_git_project();
|
|
2519
2736
|
init_team();
|
|
2520
2737
|
init_agent_metadata();
|
|
2521
2738
|
init_calibration();
|
|
@@ -2822,13 +3039,16 @@ function parseRollout(file, lines) {
|
|
|
2822
3039
|
const activeSegments = computeActiveSegments2(tsMs);
|
|
2823
3040
|
const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
|
|
2824
3041
|
const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
|
|
2825
|
-
const
|
|
3042
|
+
const project = cwd ? resolveProjectIdentity(cwd) : void 0;
|
|
3043
|
+
const projectName = project?.projectName ?? "(unknown)";
|
|
2826
3044
|
const projectDir = cwd ? cwd.replace(/^\//, "-").replace(/\//g, "-") : "(unknown)";
|
|
2827
3045
|
const meta = {
|
|
2828
3046
|
agent: "codex",
|
|
2829
3047
|
id: file.sessionId,
|
|
2830
3048
|
filePath: file.filePath,
|
|
2831
3049
|
projectName,
|
|
3050
|
+
worktreeName: project?.worktreeName,
|
|
3051
|
+
repoName: project?.repoName,
|
|
2832
3052
|
projectDir,
|
|
2833
3053
|
sessionId: file.sessionId,
|
|
2834
3054
|
firstTimestamp,
|
|
@@ -2960,13 +3180,16 @@ async function getLatestCodexUsage(opts = {}) {
|
|
|
2960
3180
|
const fiveResetUnix = numberOf(primary?.resets_at);
|
|
2961
3181
|
const sevenResetUnix = numberOf(secondary?.resets_at);
|
|
2962
3182
|
const planType = typeof rl.plan_type === "string" ? rl.plan_type : null;
|
|
3183
|
+
const nowMs = Date.now();
|
|
3184
|
+
const fiveExpired = fiveResetUnix !== void 0 && nowMs > fiveResetUnix * 1e3;
|
|
3185
|
+
const sevenExpired = sevenResetUnix !== void 0 && nowMs > sevenResetUnix * 1e3;
|
|
2963
3186
|
return {
|
|
2964
3187
|
five_hour: {
|
|
2965
|
-
utilization: fivePct ?? null,
|
|
3188
|
+
utilization: fiveExpired ? 0 : fivePct ?? null,
|
|
2966
3189
|
resets_at: fiveResetUnix !== void 0 ? new Date(fiveResetUnix * 1e3).toISOString() : null
|
|
2967
3190
|
},
|
|
2968
3191
|
seven_day: {
|
|
2969
|
-
utilization: sevenPct ?? null,
|
|
3192
|
+
utilization: sevenExpired ? 0 : sevenPct ?? null,
|
|
2970
3193
|
resets_at: sevenResetUnix !== void 0 ? new Date(sevenResetUnix * 1e3).toISOString() : null
|
|
2971
3194
|
},
|
|
2972
3195
|
plan_type: planType,
|
|
@@ -2987,6 +3210,7 @@ var init_codex = __esm({
|
|
|
2987
3210
|
"../parser/dist/codex.js"() {
|
|
2988
3211
|
"use strict";
|
|
2989
3212
|
init_analytics();
|
|
3213
|
+
init_git_project();
|
|
2990
3214
|
init_user_input();
|
|
2991
3215
|
DEFAULT_CODEX_ROOT = path2.join(os2.homedir(), ".codex", "sessions");
|
|
2992
3216
|
ROLLOUT_RE = /^rollout-(\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2})-([0-9a-f-]+)\.jsonl$/;
|
|
@@ -3366,13 +3590,16 @@ async function parseSession(file) {
|
|
|
3366
3590
|
const airTimeMs = activeSegments.reduce((acc, s) => acc + (s.endMs - s.startMs), 0);
|
|
3367
3591
|
const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
|
|
3368
3592
|
const sessionId = metaRec.sessionId ?? file.filenameId;
|
|
3369
|
-
const
|
|
3593
|
+
const project = cwd ? resolveProjectIdentity(cwd) : void 0;
|
|
3594
|
+
const projectName = project?.projectName ?? file.slug;
|
|
3370
3595
|
const projectDir = cwd ? cwd.replace(/^\//, "-").replace(/\//g, "-") : file.slug;
|
|
3371
3596
|
const meta = {
|
|
3372
3597
|
agent: "gemini",
|
|
3373
3598
|
id: sessionId,
|
|
3374
3599
|
filePath: file.filePath,
|
|
3375
3600
|
projectName,
|
|
3601
|
+
worktreeName: project?.worktreeName,
|
|
3602
|
+
repoName: project?.repoName,
|
|
3376
3603
|
projectDir,
|
|
3377
3604
|
sessionId,
|
|
3378
3605
|
firstTimestamp,
|
|
@@ -3486,6 +3713,7 @@ var init_gemini = __esm({
|
|
|
3486
3713
|
"../parser/dist/gemini.js"() {
|
|
3487
3714
|
"use strict";
|
|
3488
3715
|
init_analytics();
|
|
3716
|
+
init_git_project();
|
|
3489
3717
|
init_user_input();
|
|
3490
3718
|
DEFAULT_GEMINI_ROOT = path3.join(os3.homedir(), ".gemini", "tmp");
|
|
3491
3719
|
GEMINI_PROJECTS_FILE = path3.join(os3.homedir(), ".gemini", "projects.json");
|
|
@@ -3759,13 +3987,16 @@ async function parseSession2(file) {
|
|
|
3759
3987
|
const durationMs = firstTimestamp && lastTimestamp ? Date.parse(lastTimestamp) - Date.parse(firstTimestamp) : void 0;
|
|
3760
3988
|
const sessionId = file.conversationId;
|
|
3761
3989
|
const cwd = file.cwd;
|
|
3762
|
-
const
|
|
3990
|
+
const project = cwd ? resolveProjectIdentity(cwd) : void 0;
|
|
3991
|
+
const projectName = project?.projectName ?? file.conversationId;
|
|
3763
3992
|
const projectDir = cwd ? cwd.replace(/^\//, "-").replace(/\//g, "-") : file.conversationId;
|
|
3764
3993
|
const meta = {
|
|
3765
3994
|
agent: "antigravity",
|
|
3766
3995
|
id: sessionId,
|
|
3767
3996
|
filePath: file.filePath,
|
|
3768
3997
|
projectName,
|
|
3998
|
+
worktreeName: project?.worktreeName,
|
|
3999
|
+
repoName: project?.repoName,
|
|
3769
4000
|
projectDir,
|
|
3770
4001
|
sessionId,
|
|
3771
4002
|
firstTimestamp,
|
|
@@ -3872,6 +4103,7 @@ var init_antigravity = __esm({
|
|
|
3872
4103
|
"../parser/dist/antigravity.js"() {
|
|
3873
4104
|
"use strict";
|
|
3874
4105
|
init_analytics();
|
|
4106
|
+
init_git_project();
|
|
3875
4107
|
init_user_input();
|
|
3876
4108
|
DEFAULT_ANTIGRAVITY_ROOT = path4.join(os4.homedir(), ".gemini", "antigravity-cli");
|
|
3877
4109
|
IDLE_GAP_MS3 = 3 * 60 * 1e3;
|
|
@@ -3991,8 +4223,10 @@ function resolveProject(meta, spaceIdToPath) {
|
|
|
3991
4223
|
if (!projectPath) {
|
|
3992
4224
|
return { projectName: "cowork:unspaced", projectDir: "cowork-unspaced" };
|
|
3993
4225
|
}
|
|
4226
|
+
const project = resolveProjectIdentity(projectPath);
|
|
3994
4227
|
return {
|
|
3995
|
-
projectName:
|
|
4228
|
+
projectName: project.projectName,
|
|
4229
|
+
worktreeName: project.worktreeName,
|
|
3996
4230
|
projectDir: projectPath.replace(/^\//, "-").replace(/\//g, "-"),
|
|
3997
4231
|
cwd: projectPath
|
|
3998
4232
|
};
|
|
@@ -4219,8 +4453,8 @@ var DEFAULT_COWORK_ROOT, SESSION_ID_RE, spacesCache, metaCache5, detailCache5;
|
|
|
4219
4453
|
var init_cowork = __esm({
|
|
4220
4454
|
"../parser/dist/cowork.js"() {
|
|
4221
4455
|
"use strict";
|
|
4222
|
-
init_analytics();
|
|
4223
4456
|
init_claude_code();
|
|
4457
|
+
init_git_project();
|
|
4224
4458
|
init_parser();
|
|
4225
4459
|
DEFAULT_COWORK_ROOT = defaultCoworkRoot();
|
|
4226
4460
|
SESSION_ID_RE = /^local_[0-9a-f-]+$/;
|
|
@@ -4231,21 +4465,21 @@ var init_cowork = __esm({
|
|
|
4231
4465
|
});
|
|
4232
4466
|
|
|
4233
4467
|
// ../parser/dist/team-config.js
|
|
4234
|
-
import { readFileSync as
|
|
4235
|
-
import { join } from "node:path";
|
|
4236
|
-
function shouldSyncProject(
|
|
4468
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, unlinkSync as unlinkSync2, mkdirSync as mkdirSync2, renameSync } from "node:fs";
|
|
4469
|
+
import { join as join2 } from "node:path";
|
|
4470
|
+
function shouldSyncProject(projectKey2, sp) {
|
|
4237
4471
|
if (!sp)
|
|
4238
4472
|
return true;
|
|
4239
|
-
if (sp.excluded.includes(
|
|
4473
|
+
if (sp.excluded.includes(projectKey2))
|
|
4240
4474
|
return false;
|
|
4241
|
-
if (sp.included.includes(
|
|
4475
|
+
if (sp.included.includes(projectKey2))
|
|
4242
4476
|
return true;
|
|
4243
4477
|
return sp.autoIncludeNew;
|
|
4244
4478
|
}
|
|
4245
4479
|
function readTeamConfig(dir) {
|
|
4246
4480
|
const d = dir ?? cclensHome();
|
|
4247
4481
|
try {
|
|
4248
|
-
return JSON.parse(
|
|
4482
|
+
return JSON.parse(readFileSync3(join2(d, CONFIG_FILE), "utf8"));
|
|
4249
4483
|
} catch {
|
|
4250
4484
|
return null;
|
|
4251
4485
|
}
|
|
@@ -4253,14 +4487,14 @@ function readTeamConfig(dir) {
|
|
|
4253
4487
|
function writeTeamConfig(config, dir) {
|
|
4254
4488
|
const d = dir ?? cclensHome();
|
|
4255
4489
|
mkdirSync2(d, { recursive: true });
|
|
4256
|
-
const tmp =
|
|
4490
|
+
const tmp = join2(d, `${CONFIG_FILE}.${process.pid}.tmp`);
|
|
4257
4491
|
writeFileSync2(tmp, JSON.stringify(config, null, 2), { mode: 384 });
|
|
4258
|
-
renameSync(tmp,
|
|
4492
|
+
renameSync(tmp, join2(d, CONFIG_FILE));
|
|
4259
4493
|
}
|
|
4260
4494
|
function clearTeamConfig(dir) {
|
|
4261
4495
|
const d = dir ?? cclensHome();
|
|
4262
4496
|
try {
|
|
4263
|
-
unlinkSync2(
|
|
4497
|
+
unlinkSync2(join2(d, CONFIG_FILE));
|
|
4264
4498
|
} catch {
|
|
4265
4499
|
}
|
|
4266
4500
|
}
|
|
@@ -4293,6 +4527,7 @@ __export(fs_exports, {
|
|
|
4293
4527
|
RICH_ROLLUP_SCHEMA_VERSION: () => RICH_ROLLUP_SCHEMA_VERSION,
|
|
4294
4528
|
agentSources: () => agentSources,
|
|
4295
4529
|
antigravitySessionLocalDay: () => antigravitySessionLocalDay,
|
|
4530
|
+
appendUsageSnapshot: () => appendUsageSnapshot,
|
|
4296
4531
|
buildCalibrationCurve: () => buildCalibrationCurve,
|
|
4297
4532
|
cacheStats: () => cacheStats,
|
|
4298
4533
|
cclensHome: () => cclensHome,
|
|
@@ -4326,14 +4561,17 @@ __export(fs_exports, {
|
|
|
4326
4561
|
loadTeamForSession: () => loadTeamForSession,
|
|
4327
4562
|
loadUsageByDay: () => loadUsageByDay,
|
|
4328
4563
|
loadWorkflowAgentDetail: () => loadWorkflowAgentDetail,
|
|
4564
|
+
pruneUsageAgent: () => pruneUsageAgent,
|
|
4565
|
+
readGitFolder: () => readGitFolder,
|
|
4329
4566
|
readJsonlFile: () => readJsonlFile,
|
|
4330
4567
|
readTeamConfig: () => readTeamConfig,
|
|
4568
|
+
resolveProjectIdentity: () => resolveProjectIdentity,
|
|
4331
4569
|
sessionIdFromFileName: () => sessionIdFromFileName,
|
|
4332
4570
|
shouldSyncProject: () => shouldSyncProject,
|
|
4333
4571
|
walkJsonlFiles: () => walkJsonlFiles,
|
|
4334
4572
|
writeTeamConfig: () => writeTeamConfig
|
|
4335
4573
|
});
|
|
4336
|
-
import { promises as fs6 } from "node:fs";
|
|
4574
|
+
import { promises as fs6, existsSync as existsSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync3, appendFileSync, mkdirSync as mkdirSync3 } from "node:fs";
|
|
4337
4575
|
import os6 from "node:os";
|
|
4338
4576
|
import path6 from "node:path";
|
|
4339
4577
|
function cclensHome() {
|
|
@@ -4379,6 +4617,27 @@ async function getAnySession(id) {
|
|
|
4379
4617
|
function usageLogPath() {
|
|
4380
4618
|
return cclensPath("usage.jsonl");
|
|
4381
4619
|
}
|
|
4620
|
+
function appendUsageSnapshot(snapshot) {
|
|
4621
|
+
const p = usageLogPath();
|
|
4622
|
+
mkdirSync3(path6.dirname(p), { recursive: true });
|
|
4623
|
+
appendFileSync(p, JSON.stringify(snapshot) + "\n", "utf8");
|
|
4624
|
+
}
|
|
4625
|
+
function pruneUsageAgent(agent) {
|
|
4626
|
+
const p = usageLogPath();
|
|
4627
|
+
if (!existsSync2(p))
|
|
4628
|
+
return;
|
|
4629
|
+
const kept = readFileSync4(p, "utf8").split("\n").filter((line) => {
|
|
4630
|
+
if (!line.trim())
|
|
4631
|
+
return false;
|
|
4632
|
+
try {
|
|
4633
|
+
return JSON.parse(line).agent !== agent;
|
|
4634
|
+
} catch {
|
|
4635
|
+
return true;
|
|
4636
|
+
}
|
|
4637
|
+
});
|
|
4638
|
+
mkdirSync3(path6.dirname(p), { recursive: true });
|
|
4639
|
+
writeFileSync3(p, kept.join("\n") + (kept.length ? "\n" : ""), "utf8");
|
|
4640
|
+
}
|
|
4382
4641
|
async function loadUsageByDay(start2, end) {
|
|
4383
4642
|
let raw;
|
|
4384
4643
|
try {
|
|
@@ -4603,6 +4862,7 @@ var init_fs = __esm({
|
|
|
4603
4862
|
init_antigravity();
|
|
4604
4863
|
init_cowork();
|
|
4605
4864
|
init_claude_code();
|
|
4865
|
+
init_git_project();
|
|
4606
4866
|
init_codex();
|
|
4607
4867
|
init_gemini();
|
|
4608
4868
|
init_antigravity();
|
|
@@ -4681,13 +4941,13 @@ __export(server_exports, {
|
|
|
4681
4941
|
stopServer: () => stopServer
|
|
4682
4942
|
});
|
|
4683
4943
|
import { spawn } from "node:child_process";
|
|
4684
|
-
import { join as
|
|
4944
|
+
import { join as join3, dirname as dirname3 } from "node:path";
|
|
4685
4945
|
import { fileURLToPath } from "node:url";
|
|
4686
|
-
import { existsSync } from "node:fs";
|
|
4687
|
-
import { homedir } from "node:os";
|
|
4946
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
4947
|
+
import { homedir as homedir2 } from "node:os";
|
|
4688
4948
|
function appDir() {
|
|
4689
|
-
const here =
|
|
4690
|
-
return
|
|
4949
|
+
const here = dirname3(fileURLToPath(import.meta.url));
|
|
4950
|
+
return join3(here, "..", "app", "apps", "web");
|
|
4691
4951
|
}
|
|
4692
4952
|
function getServerStatus() {
|
|
4693
4953
|
cleanStalePid(PID_FILE, SERVER_MARKERS);
|
|
@@ -4698,7 +4958,7 @@ function getServerStatus() {
|
|
|
4698
4958
|
return { running: false };
|
|
4699
4959
|
}
|
|
4700
4960
|
function isServerStale(status2) {
|
|
4701
|
-
return status2.running === true && status2.version !== "0.15.
|
|
4961
|
+
return status2.running === true && status2.version !== "0.15.4";
|
|
4702
4962
|
}
|
|
4703
4963
|
async function ensureCurrentServer(opts = {}) {
|
|
4704
4964
|
const status2 = getServerStatus();
|
|
@@ -4731,15 +4991,15 @@ async function ensureCurrentServer(opts = {}) {
|
|
|
4731
4991
|
}
|
|
4732
4992
|
async function startServer(opts = {}) {
|
|
4733
4993
|
const port = opts.port ?? (parseInt(process.env.CCLENS_PORT ?? "", 10) || DEFAULT_PORT);
|
|
4734
|
-
const serverJs =
|
|
4735
|
-
if (!
|
|
4994
|
+
const serverJs = join3(appDir(), "server.js");
|
|
4995
|
+
if (!existsSync3(serverJs)) {
|
|
4736
4996
|
throw new Error(`Server not found at ${serverJs}. Reinstall with: npm install -g fleetlens`);
|
|
4737
4997
|
}
|
|
4738
4998
|
const portInUse = await checkPort(port);
|
|
4739
4999
|
if (portInUse) {
|
|
4740
5000
|
throw new Error(`Port ${port} is in use. Use --port to specify a different port.`);
|
|
4741
5001
|
}
|
|
4742
|
-
const dataDir =
|
|
5002
|
+
const dataDir = join3(homedir2(), ".claude", "projects");
|
|
4743
5003
|
const child = spawn(process.execPath, [serverJs], {
|
|
4744
5004
|
detached: true,
|
|
4745
5005
|
stdio: "ignore",
|
|
@@ -4754,7 +5014,7 @@ async function startServer(opts = {}) {
|
|
|
4754
5014
|
});
|
|
4755
5015
|
child.unref();
|
|
4756
5016
|
const pid = child.pid;
|
|
4757
|
-
writePid(PID_FILE, pid, port, "0.15.
|
|
5017
|
+
writePid(PID_FILE, pid, port, "0.15.4");
|
|
4758
5018
|
await waitForHealth(`http://localhost:${port}`, 3e4);
|
|
4759
5019
|
return { pid, port };
|
|
4760
5020
|
}
|
|
@@ -4773,11 +5033,11 @@ function stopServer() {
|
|
|
4773
5033
|
}
|
|
4774
5034
|
async function checkPort(port) {
|
|
4775
5035
|
const { createServer } = await import("node:net");
|
|
4776
|
-
return new Promise((
|
|
5036
|
+
return new Promise((resolve4) => {
|
|
4777
5037
|
const server = createServer();
|
|
4778
|
-
server.once("error", () =>
|
|
5038
|
+
server.once("error", () => resolve4(true));
|
|
4779
5039
|
server.once("listening", () => {
|
|
4780
|
-
server.close(() =>
|
|
5040
|
+
server.close(() => resolve4(false));
|
|
4781
5041
|
});
|
|
4782
5042
|
server.listen(port, "localhost");
|
|
4783
5043
|
});
|
|
@@ -4823,17 +5083,18 @@ __export(storage_exports, {
|
|
|
4823
5083
|
appendSnapshot: () => appendSnapshot,
|
|
4824
5084
|
latestClaudeCodeSnapshot: () => latestClaudeCodeSnapshot,
|
|
4825
5085
|
latestSnapshot: () => latestSnapshot,
|
|
5086
|
+
pruneAgent: () => pruneAgent,
|
|
4826
5087
|
readSnapshots: () => readSnapshots
|
|
4827
5088
|
});
|
|
4828
|
-
import { appendFileSync, mkdirSync as
|
|
4829
|
-
import { dirname as
|
|
5089
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync4 } from "node:fs";
|
|
5090
|
+
import { dirname as dirname4 } from "node:path";
|
|
4830
5091
|
function appendSnapshot(filePath, snapshot) {
|
|
4831
|
-
|
|
4832
|
-
|
|
5092
|
+
mkdirSync4(dirname4(filePath), { recursive: true });
|
|
5093
|
+
appendFileSync2(filePath, JSON.stringify(snapshot) + "\n", "utf8");
|
|
4833
5094
|
}
|
|
4834
5095
|
function readSnapshots(filePath) {
|
|
4835
|
-
if (!
|
|
4836
|
-
const content =
|
|
5096
|
+
if (!existsSync4(filePath)) return [];
|
|
5097
|
+
const content = readFileSync5(filePath, "utf8");
|
|
4837
5098
|
const snapshots = [];
|
|
4838
5099
|
for (const line of content.split("\n")) {
|
|
4839
5100
|
if (!line.trim()) continue;
|
|
@@ -4848,6 +5109,19 @@ function latestSnapshot(filePath) {
|
|
|
4848
5109
|
const all = readSnapshots(filePath);
|
|
4849
5110
|
return all.length > 0 ? all[all.length - 1] : null;
|
|
4850
5111
|
}
|
|
5112
|
+
function pruneAgent(filePath, agent) {
|
|
5113
|
+
if (!existsSync4(filePath)) return;
|
|
5114
|
+
const kept = readFileSync5(filePath, "utf8").split("\n").filter((line) => {
|
|
5115
|
+
if (!line.trim()) return false;
|
|
5116
|
+
try {
|
|
5117
|
+
return JSON.parse(line).agent !== agent;
|
|
5118
|
+
} catch {
|
|
5119
|
+
return true;
|
|
5120
|
+
}
|
|
5121
|
+
});
|
|
5122
|
+
mkdirSync4(dirname4(filePath), { recursive: true });
|
|
5123
|
+
writeFileSync4(filePath, kept.join("\n") + (kept.length ? "\n" : ""), "utf8");
|
|
5124
|
+
}
|
|
4851
5125
|
function latestClaudeCodeSnapshot(filePath) {
|
|
4852
5126
|
const all = readSnapshots(filePath);
|
|
4853
5127
|
for (let i = all.length - 1; i >= 0; i--) {
|
|
@@ -4871,9 +5145,9 @@ __export(daemon_exports, {
|
|
|
4871
5145
|
stopDaemonSilent: () => stopDaemonSilent
|
|
4872
5146
|
});
|
|
4873
5147
|
import { spawn as spawn2 } from "node:child_process";
|
|
4874
|
-
import { join as
|
|
5148
|
+
import { join as join4, dirname as dirname5 } from "node:path";
|
|
4875
5149
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
4876
|
-
import { existsSync as
|
|
5150
|
+
import { existsSync as existsSync5, statSync as statSync2, readFileSync as readFileSync6 } from "node:fs";
|
|
4877
5151
|
function startDaemonSilent() {
|
|
4878
5152
|
cleanStalePid(DAEMON_PID, DAEMON_MARKERS);
|
|
4879
5153
|
const existing = readPid(DAEMON_PID);
|
|
@@ -4881,7 +5155,7 @@ function startDaemonSilent() {
|
|
|
4881
5155
|
return { started: false, pid: existing.pid, alreadyRunning: true };
|
|
4882
5156
|
}
|
|
4883
5157
|
const script = workerPath();
|
|
4884
|
-
if (!
|
|
5158
|
+
if (!existsSync5(script)) {
|
|
4885
5159
|
return {
|
|
4886
5160
|
started: false,
|
|
4887
5161
|
pid: null,
|
|
@@ -4915,7 +5189,7 @@ function getDaemonStatusInfo() {
|
|
|
4915
5189
|
const running = entry !== null && isProcessAlive(entry.pid, DAEMON_MARKERS);
|
|
4916
5190
|
const latest = latestSnapshot(USAGE_LOG);
|
|
4917
5191
|
const lastSnapshotAgeMs = latest ? Date.now() - new Date(latest.captured_at).getTime() : null;
|
|
4918
|
-
const usageLogSize =
|
|
5192
|
+
const usageLogSize = existsSync5(USAGE_LOG) ? statSync2(USAGE_LOG).size : null;
|
|
4919
5193
|
return {
|
|
4920
5194
|
running,
|
|
4921
5195
|
pid: running ? entry.pid : null,
|
|
@@ -4925,8 +5199,8 @@ function getDaemonStatusInfo() {
|
|
|
4925
5199
|
};
|
|
4926
5200
|
}
|
|
4927
5201
|
function workerPath() {
|
|
4928
|
-
const here =
|
|
4929
|
-
return
|
|
5202
|
+
const here = dirname5(fileURLToPath2(import.meta.url));
|
|
5203
|
+
return join4(here, "daemon-worker.js");
|
|
4930
5204
|
}
|
|
4931
5205
|
async function daemon(args2) {
|
|
4932
5206
|
const sub = args2[0] ?? "status";
|
|
@@ -4991,11 +5265,11 @@ function daemonStatus() {
|
|
|
4991
5265
|
}
|
|
4992
5266
|
}
|
|
4993
5267
|
function daemonLogs() {
|
|
4994
|
-
if (!
|
|
5268
|
+
if (!existsSync5(DAEMON_LOG)) {
|
|
4995
5269
|
console.log("No daemon logs yet.");
|
|
4996
5270
|
return;
|
|
4997
5271
|
}
|
|
4998
|
-
const content =
|
|
5272
|
+
const content = readFileSync6(DAEMON_LOG, "utf8");
|
|
4999
5273
|
const lines = content.trim().split("\n").slice(-20);
|
|
5000
5274
|
for (const line of lines) process.stdout.write(line + "\n");
|
|
5001
5275
|
}
|
|
@@ -5015,8 +5289,8 @@ var init_daemon = __esm({
|
|
|
5015
5289
|
|
|
5016
5290
|
// src/updater.ts
|
|
5017
5291
|
import { execSync, spawnSync } from "node:child_process";
|
|
5018
|
-
import { existsSync as
|
|
5019
|
-
import { dirname as
|
|
5292
|
+
import { existsSync as existsSync6, readFileSync as readFileSync7, realpathSync as realpathSync2 } from "node:fs";
|
|
5293
|
+
import { dirname as dirname6, join as join5 } from "node:path";
|
|
5020
5294
|
function shouldUpdate(local, remote) {
|
|
5021
5295
|
const l = local.split(".").map(Number);
|
|
5022
5296
|
const r = remote.split(".").map(Number);
|
|
@@ -5058,15 +5332,15 @@ function verifyInstalledVersion() {
|
|
|
5058
5332
|
encoding: "utf8",
|
|
5059
5333
|
timeout: 5e3
|
|
5060
5334
|
}).trim();
|
|
5061
|
-
const pkgPath =
|
|
5062
|
-
const pkg = JSON.parse(
|
|
5335
|
+
const pkgPath = join5(globalRoot, PACKAGE_NAME, "package.json");
|
|
5336
|
+
const pkg = JSON.parse(readFileSync7(pkgPath, "utf8"));
|
|
5063
5337
|
if (!pkg.version) {
|
|
5064
5338
|
return { ok: false, reason: `no version field in ${pkgPath}` };
|
|
5065
5339
|
}
|
|
5066
5340
|
return {
|
|
5067
5341
|
ok: true,
|
|
5068
5342
|
installedVersion: pkg.version,
|
|
5069
|
-
installedPath:
|
|
5343
|
+
installedPath: join5(globalRoot, PACKAGE_NAME)
|
|
5070
5344
|
};
|
|
5071
5345
|
} catch (err) {
|
|
5072
5346
|
return { ok: false, reason: err.message };
|
|
@@ -5123,28 +5397,28 @@ Installed: ${PACKAGE_NAME}@${verify.installedVersion} at ${verify.installedPath
|
|
|
5123
5397
|
console.warn(
|
|
5124
5398
|
` \u2022 reinstall in the correct Node env: 'npm install -g ${PACKAGE_NAME}@latest'`
|
|
5125
5399
|
);
|
|
5126
|
-
} else if (verify.installedVersion !== "0.15.
|
|
5400
|
+
} else if (verify.installedVersion !== "0.15.4") {
|
|
5127
5401
|
console.log(
|
|
5128
|
-
` \u2192 This process is still running ${"0.15.
|
|
5402
|
+
` \u2192 This process is still running ${"0.15.4"}. Next invocation will use ${verify.installedVersion}.`
|
|
5129
5403
|
);
|
|
5130
5404
|
}
|
|
5131
5405
|
}
|
|
5132
5406
|
function resolvesIntoPackage(binPath, packagePath) {
|
|
5133
5407
|
try {
|
|
5134
|
-
const real =
|
|
5408
|
+
const real = realpathSync2(binPath);
|
|
5135
5409
|
if (real.startsWith(packagePath)) return true;
|
|
5136
5410
|
} catch {
|
|
5137
5411
|
}
|
|
5138
|
-
const binPrefix =
|
|
5139
|
-
const installPrefix =
|
|
5412
|
+
const binPrefix = dirname6(dirname6(binPath));
|
|
5413
|
+
const installPrefix = dirname6(dirname6(dirname6(packagePath)));
|
|
5140
5414
|
return binPrefix === installPrefix;
|
|
5141
5415
|
}
|
|
5142
5416
|
function reExec() {
|
|
5143
5417
|
const verify = verifyInstalledVersion();
|
|
5144
5418
|
let script = process.argv[1] ?? "";
|
|
5145
5419
|
if (verify.ok) {
|
|
5146
|
-
const candidate =
|
|
5147
|
-
if (
|
|
5420
|
+
const candidate = join5(verify.installedPath, "dist", "index.js");
|
|
5421
|
+
if (existsSync6(candidate)) script = candidate;
|
|
5148
5422
|
}
|
|
5149
5423
|
const result = spawnSync(process.argv[0], [script, ...process.argv.slice(2)], {
|
|
5150
5424
|
stdio: "inherit",
|
|
@@ -5160,14 +5434,14 @@ async function getUpdateAvailability() {
|
|
|
5160
5434
|
if (isDevMode()) return null;
|
|
5161
5435
|
const latest = await fetchLatestVersion();
|
|
5162
5436
|
if (latest === null) return {
|
|
5163
|
-
current: "0.15.
|
|
5437
|
+
current: "0.15.4",
|
|
5164
5438
|
latest: null,
|
|
5165
5439
|
updateAvailable: false
|
|
5166
5440
|
};
|
|
5167
5441
|
return {
|
|
5168
|
-
current: "0.15.
|
|
5442
|
+
current: "0.15.4",
|
|
5169
5443
|
latest,
|
|
5170
|
-
updateAvailable: shouldUpdate("0.15.
|
|
5444
|
+
updateAvailable: shouldUpdate("0.15.4", latest)
|
|
5171
5445
|
};
|
|
5172
5446
|
}
|
|
5173
5447
|
async function checkForUpdate() {
|
|
@@ -5257,7 +5531,7 @@ async function restartServices(state) {
|
|
|
5257
5531
|
}
|
|
5258
5532
|
async function forceUpdate() {
|
|
5259
5533
|
const latest = await fetchLatestVersion();
|
|
5260
|
-
const current = "0.15.
|
|
5534
|
+
const current = "0.15.4";
|
|
5261
5535
|
if (latest === null) {
|
|
5262
5536
|
console.error("Could not reach npm registry. Check your network.");
|
|
5263
5537
|
process.exit(1);
|
|
@@ -5309,27 +5583,27 @@ __export(autostart_exports, {
|
|
|
5309
5583
|
maybePromptAutostart: () => maybePromptAutostart,
|
|
5310
5584
|
recordOptOut: () => recordOptOut
|
|
5311
5585
|
});
|
|
5312
|
-
import { existsSync as
|
|
5313
|
-
import { homedir as
|
|
5314
|
-
import { join as
|
|
5586
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync5, writeFileSync as writeFileSync5, rmSync, readFileSync as readFileSync8, realpathSync as realpathSync3 } from "node:fs";
|
|
5587
|
+
import { homedir as homedir3 } from "node:os";
|
|
5588
|
+
import { join as join6, dirname as dirname7 } from "node:path";
|
|
5315
5589
|
import { execFile } from "node:child_process";
|
|
5316
5590
|
import { promisify } from "node:util";
|
|
5317
5591
|
import { createInterface } from "node:readline";
|
|
5318
5592
|
function plistPath() {
|
|
5319
|
-
return
|
|
5593
|
+
return join6(homedir3(), "Library", "LaunchAgents", `${LABEL}.plist`);
|
|
5320
5594
|
}
|
|
5321
5595
|
function isMac() {
|
|
5322
5596
|
return process.platform === "darwin";
|
|
5323
5597
|
}
|
|
5324
5598
|
function isAutostartInstalled() {
|
|
5325
|
-
return isMac() &&
|
|
5599
|
+
return isMac() && existsSync7(plistPath());
|
|
5326
5600
|
}
|
|
5327
5601
|
function isStalePlistContent(content) {
|
|
5328
5602
|
return content.includes("<string>daemon</string>");
|
|
5329
5603
|
}
|
|
5330
5604
|
function installedPlistIsStale() {
|
|
5331
5605
|
try {
|
|
5332
|
-
return isStalePlistContent(
|
|
5606
|
+
return isStalePlistContent(readFileSync8(plistPath(), "utf8"));
|
|
5333
5607
|
} catch {
|
|
5334
5608
|
return false;
|
|
5335
5609
|
}
|
|
@@ -5337,7 +5611,7 @@ function installedPlistIsStale() {
|
|
|
5337
5611
|
function resolveScriptPath() {
|
|
5338
5612
|
const argv1 = process.argv[1] ?? "";
|
|
5339
5613
|
try {
|
|
5340
|
-
return
|
|
5614
|
+
return realpathSync3(argv1);
|
|
5341
5615
|
} catch {
|
|
5342
5616
|
return argv1;
|
|
5343
5617
|
}
|
|
@@ -5380,8 +5654,8 @@ async function installAutostart() {
|
|
|
5380
5654
|
const scriptPath = resolveScriptPath();
|
|
5381
5655
|
const logPath = cclensPath("daemon-autostart.log");
|
|
5382
5656
|
const p = plistPath();
|
|
5383
|
-
|
|
5384
|
-
|
|
5657
|
+
mkdirSync5(dirname7(p), { recursive: true });
|
|
5658
|
+
writeFileSync5(p, buildPlist({ nodePath, scriptPath, logPath }), "utf8");
|
|
5385
5659
|
await runLaunchctl(["unload", p]).catch(() => {
|
|
5386
5660
|
});
|
|
5387
5661
|
await runLaunchctl(["load", "-w", p]);
|
|
@@ -5401,7 +5675,7 @@ async function uninstallAutostart() {
|
|
|
5401
5675
|
}
|
|
5402
5676
|
const p = plistPath();
|
|
5403
5677
|
recordOptOut();
|
|
5404
|
-
if (!
|
|
5678
|
+
if (!existsSync7(p)) {
|
|
5405
5679
|
console.log("Autostart is not installed \u2014 nothing to remove. Noted your opt-out; team join won't enable it.");
|
|
5406
5680
|
return;
|
|
5407
5681
|
}
|
|
@@ -5434,7 +5708,7 @@ async function statusAutostart() {
|
|
|
5434
5708
|
return;
|
|
5435
5709
|
}
|
|
5436
5710
|
const p = plistPath();
|
|
5437
|
-
const present =
|
|
5711
|
+
const present = existsSync7(p);
|
|
5438
5712
|
let loaded = false;
|
|
5439
5713
|
try {
|
|
5440
5714
|
const { stdout } = await execFileAsync("launchctl", ["list"]);
|
|
@@ -5449,7 +5723,7 @@ function promptFlagPath() {
|
|
|
5449
5723
|
}
|
|
5450
5724
|
function readFlags() {
|
|
5451
5725
|
try {
|
|
5452
|
-
return JSON.parse(
|
|
5726
|
+
return JSON.parse(readFileSync8(promptFlagPath(), "utf8"));
|
|
5453
5727
|
} catch {
|
|
5454
5728
|
return {};
|
|
5455
5729
|
}
|
|
@@ -5457,8 +5731,8 @@ function readFlags() {
|
|
|
5457
5731
|
function writeFlags(patch) {
|
|
5458
5732
|
const p = promptFlagPath();
|
|
5459
5733
|
try {
|
|
5460
|
-
|
|
5461
|
-
|
|
5734
|
+
mkdirSync5(dirname7(p), { recursive: true });
|
|
5735
|
+
writeFileSync5(p, JSON.stringify({ ...readFlags(), ...patch }, null, 2), "utf8");
|
|
5462
5736
|
} catch {
|
|
5463
5737
|
}
|
|
5464
5738
|
}
|
|
@@ -5475,13 +5749,13 @@ function recordOptOut() {
|
|
|
5475
5749
|
writeFlags({ optedOut: true });
|
|
5476
5750
|
}
|
|
5477
5751
|
function promptYesNo(question, defaultYes) {
|
|
5478
|
-
return new Promise((
|
|
5752
|
+
return new Promise((resolve4) => {
|
|
5479
5753
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
5480
5754
|
rl.question(question, (answer) => {
|
|
5481
5755
|
rl.close();
|
|
5482
5756
|
const a = answer.trim().toLowerCase();
|
|
5483
|
-
if (a === "") return
|
|
5484
|
-
|
|
5757
|
+
if (a === "") return resolve4(defaultYes);
|
|
5758
|
+
resolve4(a === "y" || a === "yes");
|
|
5485
5759
|
});
|
|
5486
5760
|
});
|
|
5487
5761
|
}
|
|
@@ -5670,7 +5944,7 @@ async function status() {
|
|
|
5670
5944
|
console.log(`Server: running on ${url} (PID ${server.pid}, v${ver})`);
|
|
5671
5945
|
if (isServerStale(server)) {
|
|
5672
5946
|
console.log(
|
|
5673
|
-
` \u26A0 serving stale ${ver} (CLI is ${"0.15.
|
|
5947
|
+
` \u26A0 serving stale ${ver} (CLI is ${"0.15.4"}) \u2014 run 'fleetlens start' to restart on the current version`
|
|
5674
5948
|
);
|
|
5675
5949
|
}
|
|
5676
5950
|
} else {
|
|
@@ -5752,9 +6026,9 @@ var init_update = __esm({
|
|
|
5752
6026
|
|
|
5753
6027
|
// src/usage/token.ts
|
|
5754
6028
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
5755
|
-
import { readFileSync as
|
|
5756
|
-
import { homedir as
|
|
5757
|
-
import { join as
|
|
6029
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
6030
|
+
import { homedir as homedir4, platform } from "node:os";
|
|
6031
|
+
import { join as join7 } from "node:path";
|
|
5758
6032
|
function readOAuthCredentials() {
|
|
5759
6033
|
if (platform() === "darwin") {
|
|
5760
6034
|
return readFromMacKeychain() ?? readFromCredentialsFile();
|
|
@@ -5775,12 +6049,12 @@ function readFromMacKeychain() {
|
|
|
5775
6049
|
}
|
|
5776
6050
|
function readFromCredentialsFile() {
|
|
5777
6051
|
const candidates = [
|
|
5778
|
-
|
|
5779
|
-
|
|
6052
|
+
join7(homedir4(), ".claude", ".credentials.json"),
|
|
6053
|
+
join7(homedir4(), ".config", "claude", "credentials.json")
|
|
5780
6054
|
];
|
|
5781
6055
|
for (const path7 of candidates) {
|
|
5782
6056
|
try {
|
|
5783
|
-
const blob =
|
|
6057
|
+
const blob = readFileSync9(path7, "utf8");
|
|
5784
6058
|
const creds = extractCredentials(blob);
|
|
5785
6059
|
if (creds) return creds;
|
|
5786
6060
|
} catch {
|
|
@@ -6775,11 +7049,13 @@ __export(dist_exports, {
|
|
|
6775
7049
|
RATE_PER_PCT: () => RATE_PER_PCT,
|
|
6776
7050
|
RATE_PER_PCT_5H: () => RATE_PER_PCT_5H,
|
|
6777
7051
|
RATE_PER_PCT_7D: () => RATE_PER_PCT_7D,
|
|
7052
|
+
ZAI_METADATA: () => ZAI_METADATA,
|
|
6778
7053
|
agentMetadata: () => agentMetadata,
|
|
6779
7054
|
aggregateConcurrency: () => aggregateConcurrency,
|
|
6780
7055
|
buildGanttDay: () => buildGanttDay,
|
|
6781
7056
|
buildMegaRows: () => buildMegaRows,
|
|
6782
7057
|
buildPresentation: () => buildPresentation,
|
|
7058
|
+
buildProjectKeyResolver: () => buildProjectKeyResolver,
|
|
6783
7059
|
buildSpendIndex: () => buildSpendIndex,
|
|
6784
7060
|
calendarMonth: () => calendarMonth,
|
|
6785
7061
|
calendarWeek: () => calendarWeek,
|
|
@@ -6808,10 +7084,12 @@ __export(dist_exports, {
|
|
|
6808
7084
|
predictAnchored: () => predictAnchored,
|
|
6809
7085
|
priorCalendarMonth: () => priorCalendarMonth,
|
|
6810
7086
|
priorCalendarWeek: () => priorCalendarWeek,
|
|
7087
|
+
projectKey: () => projectKey,
|
|
6811
7088
|
projectRepoName: () => projectRepoName,
|
|
6812
7089
|
rowPrimaryIndex: () => rowPrimaryIndex,
|
|
6813
7090
|
sessionAirTimeMs: () => sessionAirTimeMs,
|
|
6814
7091
|
sessionDay: () => sessionDay,
|
|
7092
|
+
sessionProjectKey: () => sessionProjectKey,
|
|
6815
7093
|
stripFrameworkBoilerplate: () => stripFrameworkBoilerplate,
|
|
6816
7094
|
summarizeBursts: () => summarizeBursts,
|
|
6817
7095
|
toLocalDay: () => toLocalDay,
|
|
@@ -7426,6 +7704,7 @@ function buildEntries(sessionDetail) {
|
|
|
7426
7704
|
const entries2 = [];
|
|
7427
7705
|
const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7428
7706
|
const sessionFallbackProject = canonicalProjectName(sessionDetail.projectName ?? "");
|
|
7707
|
+
const trustSessionProject = !!sessionDetail.worktreeName;
|
|
7429
7708
|
for (const [local_day, dayEvents] of byDay) {
|
|
7430
7709
|
if (dayEvents.length === 0)
|
|
7431
7710
|
continue;
|
|
@@ -7490,7 +7769,7 @@ function buildEntries(sessionDetail) {
|
|
|
7490
7769
|
const finalAgentRaw = agg.finalAgent ?? "";
|
|
7491
7770
|
const final_agent = trunc(minimizeImages(finalAgentRaw), 400);
|
|
7492
7771
|
let project = sessionFallbackProject;
|
|
7493
|
-
if (agg.cwdCounts.size > 0) {
|
|
7772
|
+
if (!trustSessionProject && agg.cwdCounts.size > 0) {
|
|
7494
7773
|
const best = [...agg.cwdCounts.entries()].sort((a, b) => b[1] - a[1])[0];
|
|
7495
7774
|
project = canonicalProjectName(best[0]);
|
|
7496
7775
|
}
|
|
@@ -7600,11 +7879,11 @@ var init_dist2 = __esm({
|
|
|
7600
7879
|
});
|
|
7601
7880
|
|
|
7602
7881
|
// ../entries/dist/digest-fs.js
|
|
7603
|
-
import { readFileSync as
|
|
7604
|
-
import { dirname as
|
|
7882
|
+
import { readFileSync as readFileSync10, readdirSync, writeFileSync as writeFileSync6, renameSync as renameSync2, chmodSync, mkdirSync as mkdirSync6, existsSync as existsSync8 } from "node:fs";
|
|
7883
|
+
import { dirname as dirname8, join as join8 } from "node:path";
|
|
7605
7884
|
function parseDigestFile(path7, expectedVersion) {
|
|
7606
7885
|
try {
|
|
7607
|
-
const parsed = JSON.parse(
|
|
7886
|
+
const parsed = JSON.parse(readFileSync10(path7, "utf8"));
|
|
7608
7887
|
if (!parsed || typeof parsed !== "object")
|
|
7609
7888
|
return null;
|
|
7610
7889
|
if (parsed.version !== expectedVersion)
|
|
@@ -7625,24 +7904,24 @@ function digestsDir() {
|
|
|
7625
7904
|
}
|
|
7626
7905
|
function __setDigestsDirForTest(path7) {
|
|
7627
7906
|
digestsDirCached = path7;
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
|
|
7907
|
+
mkdirSync6(join8(path7, "day"), { recursive: true });
|
|
7908
|
+
mkdirSync6(join8(path7, "week"), { recursive: true });
|
|
7909
|
+
mkdirSync6(join8(path7, "month"), { recursive: true });
|
|
7631
7910
|
}
|
|
7632
7911
|
function dayDigestPath(date) {
|
|
7633
|
-
return
|
|
7912
|
+
return join8(digestsDir(), "day", `${date}.json`);
|
|
7634
7913
|
}
|
|
7635
7914
|
function weekDigestPath(monday) {
|
|
7636
|
-
return
|
|
7915
|
+
return join8(digestsDir(), "week", `${monday}.json`);
|
|
7637
7916
|
}
|
|
7638
7917
|
function monthDigestPath(yearMonth) {
|
|
7639
|
-
return
|
|
7918
|
+
return join8(digestsDir(), "month", `${yearMonth}.json`);
|
|
7640
7919
|
}
|
|
7641
7920
|
function writeDayDigest(digest2) {
|
|
7642
7921
|
const final = dayDigestPath(digest2.key);
|
|
7643
|
-
|
|
7922
|
+
mkdirSync6(dirname8(final), { recursive: true });
|
|
7644
7923
|
const tmp = `${final}.tmp`;
|
|
7645
|
-
|
|
7924
|
+
writeFileSync6(tmp, JSON.stringify(digest2, null, 2), "utf8");
|
|
7646
7925
|
if (process.platform !== "win32") {
|
|
7647
7926
|
try {
|
|
7648
7927
|
chmodSync(tmp, 384);
|
|
@@ -7653,7 +7932,7 @@ function writeDayDigest(digest2) {
|
|
|
7653
7932
|
}
|
|
7654
7933
|
function readDayDigest(date) {
|
|
7655
7934
|
const p = dayDigestPath(date);
|
|
7656
|
-
if (!
|
|
7935
|
+
if (!existsSync8(p))
|
|
7657
7936
|
return null;
|
|
7658
7937
|
return parseDigestFile(p, CURRENT_DAY_DIGEST_SCHEMA_VERSION);
|
|
7659
7938
|
}
|
|
@@ -7676,9 +7955,9 @@ function __clearTodayCacheForTest() {
|
|
|
7676
7955
|
}
|
|
7677
7956
|
function writeWeekDigest(digest2) {
|
|
7678
7957
|
const final = weekDigestPath(digest2.key);
|
|
7679
|
-
|
|
7958
|
+
mkdirSync6(dirname8(final), { recursive: true });
|
|
7680
7959
|
const tmp = `${final}.tmp`;
|
|
7681
|
-
|
|
7960
|
+
writeFileSync6(tmp, JSON.stringify(digest2, null, 2), "utf8");
|
|
7682
7961
|
if (process.platform !== "win32") {
|
|
7683
7962
|
try {
|
|
7684
7963
|
chmodSync(tmp, 384);
|
|
@@ -7689,13 +7968,13 @@ function writeWeekDigest(digest2) {
|
|
|
7689
7968
|
}
|
|
7690
7969
|
function readWeekDigest(monday) {
|
|
7691
7970
|
const p = weekDigestPath(monday);
|
|
7692
|
-
if (!
|
|
7971
|
+
if (!existsSync8(p))
|
|
7693
7972
|
return null;
|
|
7694
7973
|
return parseDigestFile(p, CURRENT_WEEK_DIGEST_SCHEMA_VERSION);
|
|
7695
7974
|
}
|
|
7696
7975
|
function listWeekDigestKeys() {
|
|
7697
|
-
const dir =
|
|
7698
|
-
if (!
|
|
7976
|
+
const dir = join8(digestsDir(), "week");
|
|
7977
|
+
if (!existsSync8(dir))
|
|
7699
7978
|
return [];
|
|
7700
7979
|
return readdirSync(dir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length)).filter((k) => /^\d{4}-\d{2}-\d{2}$/.test(k));
|
|
7701
7980
|
}
|
|
@@ -7713,9 +7992,9 @@ function setCurrentWeekDigestInCache(monday, digest2, nowMs) {
|
|
|
7713
7992
|
}
|
|
7714
7993
|
function writeMonthDigest(digest2) {
|
|
7715
7994
|
const final = monthDigestPath(digest2.key);
|
|
7716
|
-
|
|
7995
|
+
mkdirSync6(dirname8(final), { recursive: true });
|
|
7717
7996
|
const tmp = `${final}.tmp`;
|
|
7718
|
-
|
|
7997
|
+
writeFileSync6(tmp, JSON.stringify(digest2, null, 2), "utf8");
|
|
7719
7998
|
if (process.platform !== "win32") {
|
|
7720
7999
|
try {
|
|
7721
8000
|
chmodSync(tmp, 384);
|
|
@@ -7726,13 +8005,13 @@ function writeMonthDigest(digest2) {
|
|
|
7726
8005
|
}
|
|
7727
8006
|
function readMonthDigest(yearMonth) {
|
|
7728
8007
|
const p = monthDigestPath(yearMonth);
|
|
7729
|
-
if (!
|
|
8008
|
+
if (!existsSync8(p))
|
|
7730
8009
|
return null;
|
|
7731
8010
|
return parseDigestFile(p, CURRENT_MONTH_DIGEST_SCHEMA_VERSION);
|
|
7732
8011
|
}
|
|
7733
8012
|
function listMonthDigestKeys() {
|
|
7734
|
-
const dir =
|
|
7735
|
-
if (!
|
|
8013
|
+
const dir = join8(digestsDir(), "month");
|
|
8014
|
+
if (!existsSync8(dir))
|
|
7736
8015
|
return [];
|
|
7737
8016
|
return readdirSync(dir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length)).filter((k) => /^\d{4}-\d{2}$/.test(k));
|
|
7738
8017
|
}
|
|
@@ -7794,9 +8073,9 @@ __export(fs_exports2, {
|
|
|
7794
8073
|
writeMonthDigest: () => writeMonthDigest,
|
|
7795
8074
|
writeWeekDigest: () => writeWeekDigest
|
|
7796
8075
|
});
|
|
7797
|
-
import { readFileSync as
|
|
8076
|
+
import { readFileSync as readFileSync11, readdirSync as readdirSync2, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7, renameSync as renameSync3, existsSync as existsSync9 } from "node:fs";
|
|
7798
8077
|
import { randomBytes } from "node:crypto";
|
|
7799
|
-
import { join as
|
|
8078
|
+
import { join as join9 } from "node:path";
|
|
7800
8079
|
function entriesDir() {
|
|
7801
8080
|
if (entriesDirCached)
|
|
7802
8081
|
return entriesDirCached;
|
|
@@ -7806,21 +8085,21 @@ function entriesDir() {
|
|
|
7806
8085
|
}
|
|
7807
8086
|
function __setEntriesDirForTest(path7) {
|
|
7808
8087
|
entriesDirCached = path7;
|
|
7809
|
-
|
|
8088
|
+
mkdirSync7(path7, { recursive: true });
|
|
7810
8089
|
}
|
|
7811
8090
|
function pathFor(sessionId, localDay2) {
|
|
7812
|
-
return
|
|
8091
|
+
return join9(entriesDir(), `${entryKey(sessionId, localDay2)}.json`);
|
|
7813
8092
|
}
|
|
7814
8093
|
function tmpPathFor(final) {
|
|
7815
8094
|
return `${final}.tmp.${process.pid}.${randomBytes(4).toString("hex")}`;
|
|
7816
8095
|
}
|
|
7817
8096
|
function writeEntry(entry) {
|
|
7818
8097
|
const dir = entriesDir();
|
|
7819
|
-
|
|
8098
|
+
mkdirSync7(dir, { recursive: true });
|
|
7820
8099
|
const final = pathFor(entry.session_id, entry.local_day);
|
|
7821
8100
|
const tmp = tmpPathFor(final);
|
|
7822
8101
|
const json = JSON.stringify(entry, null, 2);
|
|
7823
|
-
|
|
8102
|
+
writeFileSync7(tmp, json, { encoding: "utf8" });
|
|
7824
8103
|
renameSync3(tmp, final);
|
|
7825
8104
|
}
|
|
7826
8105
|
function enrichmentInputHash(e) {
|
|
@@ -7840,7 +8119,7 @@ function enrichmentInputHash(e) {
|
|
|
7840
8119
|
}
|
|
7841
8120
|
function writeEntryPreservingEnrichment(fresh) {
|
|
7842
8121
|
const dir = entriesDir();
|
|
7843
|
-
|
|
8122
|
+
mkdirSync7(dir, { recursive: true });
|
|
7844
8123
|
const final = pathFor(fresh.session_id, fresh.local_day);
|
|
7845
8124
|
const existing = readEntry(fresh.session_id, fresh.local_day);
|
|
7846
8125
|
let toWrite = fresh;
|
|
@@ -7848,22 +8127,22 @@ function writeEntryPreservingEnrichment(fresh) {
|
|
|
7848
8127
|
toWrite = { ...fresh, enrichment: existing.enrichment };
|
|
7849
8128
|
}
|
|
7850
8129
|
const tmp = tmpPathFor(final);
|
|
7851
|
-
|
|
8130
|
+
writeFileSync7(tmp, JSON.stringify(toWrite, null, 2), { encoding: "utf8" });
|
|
7852
8131
|
renameSync3(tmp, final);
|
|
7853
8132
|
}
|
|
7854
8133
|
function readEntry(sessionId, localDay2) {
|
|
7855
8134
|
const p = pathFor(sessionId, localDay2);
|
|
7856
|
-
if (!
|
|
8135
|
+
if (!existsSync9(p))
|
|
7857
8136
|
return null;
|
|
7858
|
-
const raw =
|
|
8137
|
+
const raw = readFileSync11(p, "utf8");
|
|
7859
8138
|
return JSON.parse(raw);
|
|
7860
8139
|
}
|
|
7861
8140
|
function entryExists(sessionId, localDay2) {
|
|
7862
|
-
return
|
|
8141
|
+
return existsSync9(pathFor(sessionId, localDay2));
|
|
7863
8142
|
}
|
|
7864
8143
|
function listEntryKeys() {
|
|
7865
8144
|
const dir = entriesDir();
|
|
7866
|
-
if (!
|
|
8145
|
+
if (!existsSync9(dir))
|
|
7867
8146
|
return [];
|
|
7868
8147
|
return readdirSync2(dir).filter((f) => f.endsWith(".json")).map((f) => f.slice(0, -".json".length));
|
|
7869
8148
|
}
|
|
@@ -12142,9 +12421,9 @@ RESPOND WITH ONLY VALID JSON (no prose, no code fence):
|
|
|
12142
12421
|
});
|
|
12143
12422
|
|
|
12144
12423
|
// ../entries/dist/tmux-runner.js
|
|
12145
|
-
import { mkdirSync as
|
|
12146
|
-
import { join as
|
|
12147
|
-
import { homedir as
|
|
12424
|
+
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync8, existsSync as existsSync10, readdirSync as readdirSync3, realpathSync as realpathSync4, readFileSync as readFileSync12, unlinkSync as unlinkSync3, renameSync as renameSync4 } from "node:fs";
|
|
12425
|
+
import { join as join10 } from "node:path";
|
|
12426
|
+
import { homedir as homedir5 } from "node:os";
|
|
12148
12427
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
12149
12428
|
function which(bin) {
|
|
12150
12429
|
const r = spawnSync2("/usr/bin/env", ["which", bin], { encoding: "utf8" });
|
|
@@ -12160,16 +12439,16 @@ function tmuxRunnerAvailable() {
|
|
|
12160
12439
|
return { ok: true };
|
|
12161
12440
|
}
|
|
12162
12441
|
function runtimeCwd() {
|
|
12163
|
-
const dir =
|
|
12164
|
-
if (!
|
|
12165
|
-
|
|
12166
|
-
return
|
|
12442
|
+
const dir = join10(homedir5(), ".cclens", "runtime");
|
|
12443
|
+
if (!existsSync10(dir))
|
|
12444
|
+
mkdirSync8(dir, { recursive: true });
|
|
12445
|
+
return realpathSync4(dir);
|
|
12167
12446
|
}
|
|
12168
12447
|
function ensureRuntimeCwdTrusted(cwd) {
|
|
12169
|
-
const cfgPath =
|
|
12448
|
+
const cfgPath = join10(homedir5(), ".claude.json");
|
|
12170
12449
|
let cfg;
|
|
12171
12450
|
try {
|
|
12172
|
-
cfg = JSON.parse(
|
|
12451
|
+
cfg = JSON.parse(readFileSync12(cfgPath, "utf8"));
|
|
12173
12452
|
} catch {
|
|
12174
12453
|
return;
|
|
12175
12454
|
}
|
|
@@ -12184,7 +12463,7 @@ function ensureRuntimeCwdTrusted(cwd) {
|
|
|
12184
12463
|
cfg.projects = projects;
|
|
12185
12464
|
const tmp = `${cfgPath}.cclens-tmp-${process.pid}`;
|
|
12186
12465
|
try {
|
|
12187
|
-
|
|
12466
|
+
writeFileSync8(tmp, JSON.stringify(cfg, null, 2));
|
|
12188
12467
|
renameSync4(tmp, cfgPath);
|
|
12189
12468
|
} catch {
|
|
12190
12469
|
try {
|
|
@@ -12211,16 +12490,16 @@ async function runClaudeUnderTmuxImpl(args2) {
|
|
|
12211
12490
|
ensureRuntimeCwdTrusted(cwd);
|
|
12212
12491
|
const runId = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
12213
12492
|
const sessionName = `cclens-${runId}`;
|
|
12214
|
-
const systemFile =
|
|
12215
|
-
const userFile =
|
|
12216
|
-
const wrapper =
|
|
12217
|
-
|
|
12218
|
-
|
|
12493
|
+
const systemFile = join10(cwd, `system-${runId}.txt`);
|
|
12494
|
+
const userFile = join10(cwd, `user-${runId}.txt`);
|
|
12495
|
+
const wrapper = join10(cwd, `run-${runId}.sh`);
|
|
12496
|
+
writeFileSync8(systemFile, args2.systemPrompt);
|
|
12497
|
+
writeFileSync8(userFile, args2.reminder ? `${args2.userPrompt}
|
|
12219
12498
|
|
|
12220
12499
|
---
|
|
12221
12500
|
|
|
12222
12501
|
${args2.reminder}` : args2.userPrompt);
|
|
12223
|
-
|
|
12502
|
+
writeFileSync8(wrapper, `#!/bin/bash
|
|
12224
12503
|
SYS="$(cat ${shellEscape(systemFile)})"
|
|
12225
12504
|
USR="$(cat ${shellEscape(userFile)})"
|
|
12226
12505
|
exec ${shellEscape(claudeBin)} \\
|
|
@@ -12302,7 +12581,7 @@ function snapshotAllTranscripts() {
|
|
|
12302
12581
|
return out;
|
|
12303
12582
|
}
|
|
12304
12583
|
for (const sub of subs) {
|
|
12305
|
-
const dir =
|
|
12584
|
+
const dir = join10(root, sub);
|
|
12306
12585
|
let files;
|
|
12307
12586
|
try {
|
|
12308
12587
|
files = readdirSync3(dir);
|
|
@@ -12311,7 +12590,7 @@ function snapshotAllTranscripts() {
|
|
|
12311
12590
|
}
|
|
12312
12591
|
for (const f of files) {
|
|
12313
12592
|
if (f.endsWith(".jsonl"))
|
|
12314
|
-
out.add(
|
|
12593
|
+
out.add(join10(dir, f));
|
|
12315
12594
|
}
|
|
12316
12595
|
}
|
|
12317
12596
|
return out;
|
|
@@ -12319,7 +12598,7 @@ function snapshotAllTranscripts() {
|
|
|
12319
12598
|
function readJsonlCwd(path7, maxLines = 8) {
|
|
12320
12599
|
let raw;
|
|
12321
12600
|
try {
|
|
12322
|
-
raw =
|
|
12601
|
+
raw = readFileSync12(path7, "utf8");
|
|
12323
12602
|
} catch {
|
|
12324
12603
|
return void 0;
|
|
12325
12604
|
}
|
|
@@ -12352,7 +12631,7 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
|
|
|
12352
12631
|
subs = [];
|
|
12353
12632
|
}
|
|
12354
12633
|
for (const sub of subs) {
|
|
12355
|
-
const dir =
|
|
12634
|
+
const dir = join10(root, sub);
|
|
12356
12635
|
let files;
|
|
12357
12636
|
try {
|
|
12358
12637
|
files = readdirSync3(dir);
|
|
@@ -12362,7 +12641,7 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
|
|
|
12362
12641
|
for (const f of files) {
|
|
12363
12642
|
if (!f.endsWith(".jsonl"))
|
|
12364
12643
|
continue;
|
|
12365
|
-
const full =
|
|
12644
|
+
const full = join10(dir, f);
|
|
12366
12645
|
if (existingBefore.has(full))
|
|
12367
12646
|
continue;
|
|
12368
12647
|
if (readJsonlCwd(full) === targetCwd)
|
|
@@ -12376,7 +12655,7 @@ async function discoverTranscript(targetCwd, existingBefore, startMs, timeoutMs,
|
|
|
12376
12655
|
function parseTranscript2(path7, defaultModel) {
|
|
12377
12656
|
let raw;
|
|
12378
12657
|
try {
|
|
12379
|
-
raw =
|
|
12658
|
+
raw = readFileSync12(path7, "utf8");
|
|
12380
12659
|
} catch {
|
|
12381
12660
|
return { assembled: "", inputTokens: 0, outputTokens: 0, modelUsed: defaultModel, done: false };
|
|
12382
12661
|
}
|
|
@@ -12436,7 +12715,7 @@ function cleanup(cwd, runId, tmuxBin, sessionName, transcriptPath) {
|
|
|
12436
12715
|
}
|
|
12437
12716
|
for (const f of [`system-${runId}.txt`, `user-${runId}.txt`, `run-${runId}.sh`]) {
|
|
12438
12717
|
try {
|
|
12439
|
-
unlinkSync3(
|
|
12718
|
+
unlinkSync3(join10(cwd, f));
|
|
12440
12719
|
} catch {
|
|
12441
12720
|
}
|
|
12442
12721
|
}
|
|
@@ -12464,19 +12743,19 @@ var init_tmux_runner = __esm({
|
|
|
12464
12743
|
}
|
|
12465
12744
|
};
|
|
12466
12745
|
mutex = Promise.resolve();
|
|
12467
|
-
PROJECTS_ROOT = () =>
|
|
12746
|
+
PROJECTS_ROOT = () => join10(homedir5(), ".claude", "projects");
|
|
12468
12747
|
}
|
|
12469
12748
|
});
|
|
12470
12749
|
|
|
12471
12750
|
// ../entries/dist/llm-runner.js
|
|
12472
12751
|
import { spawn as spawn3 } from "node:child_process";
|
|
12473
|
-
import { mkdirSync as
|
|
12474
|
-
import { join as
|
|
12752
|
+
import { mkdirSync as mkdirSync9, appendFileSync as appendFileSync3, writeFileSync as writeFileSync9, existsSync as existsSync11 } from "node:fs";
|
|
12753
|
+
import { join as join11 } from "node:path";
|
|
12475
12754
|
import { randomUUID } from "node:crypto";
|
|
12476
12755
|
function ensureRunsDir() {
|
|
12477
|
-
if (!
|
|
12756
|
+
if (!existsSync11(RUNS_DIR)) {
|
|
12478
12757
|
try {
|
|
12479
|
-
|
|
12758
|
+
mkdirSync9(RUNS_DIR, { recursive: true });
|
|
12480
12759
|
} catch {
|
|
12481
12760
|
}
|
|
12482
12761
|
}
|
|
@@ -12503,17 +12782,17 @@ function newRunId(kind) {
|
|
|
12503
12782
|
return `${ts}_${kind}_${short}`;
|
|
12504
12783
|
}
|
|
12505
12784
|
function tracePath(runId) {
|
|
12506
|
-
return
|
|
12785
|
+
return join11(RUNS_DIR, `${runId}.jsonl`);
|
|
12507
12786
|
}
|
|
12508
12787
|
function safeAppend(path7, line) {
|
|
12509
12788
|
try {
|
|
12510
|
-
|
|
12789
|
+
appendFileSync3(path7, line);
|
|
12511
12790
|
} catch {
|
|
12512
12791
|
}
|
|
12513
12792
|
}
|
|
12514
12793
|
function safeWrite(path7, line) {
|
|
12515
12794
|
try {
|
|
12516
|
-
|
|
12795
|
+
writeFileSync9(path7, line);
|
|
12517
12796
|
} catch {
|
|
12518
12797
|
}
|
|
12519
12798
|
}
|
|
@@ -12591,7 +12870,7 @@ async function runClaudeSubprocess(args2) {
|
|
|
12591
12870
|
return runClaudePrintMode(args2);
|
|
12592
12871
|
}
|
|
12593
12872
|
function runClaudePrintMode(args2) {
|
|
12594
|
-
return new Promise((
|
|
12873
|
+
return new Promise((resolve4, reject) => {
|
|
12595
12874
|
ensureRunsDir();
|
|
12596
12875
|
const kind = detectKindFromSystemPrompt(args2.systemPrompt);
|
|
12597
12876
|
const runId = newRunId(kind);
|
|
@@ -12722,7 +13001,7 @@ ${args2.reminder}` : args2.userPrompt;
|
|
|
12722
13001
|
reject(new Error(`claude exited ${code}: ${stderr.trim().slice(0, 300)}`));
|
|
12723
13002
|
return;
|
|
12724
13003
|
}
|
|
12725
|
-
|
|
13004
|
+
resolve4({ content: buffer, input_tokens: inputTokens, output_tokens: outputTokens, model: modelUsed });
|
|
12726
13005
|
});
|
|
12727
13006
|
proc.on("error", (err) => {
|
|
12728
13007
|
safeAppend(trace, JSON.stringify({ _meta: { type: "spawn_error", run_id: runId, ts: (/* @__PURE__ */ new Date()).toISOString(), error: err.message } }) + "\n");
|
|
@@ -12919,8 +13198,8 @@ var init_enrich2 = __esm({
|
|
|
12919
13198
|
});
|
|
12920
13199
|
|
|
12921
13200
|
// ../entries/dist/budget.js
|
|
12922
|
-
import { appendFileSync as
|
|
12923
|
-
import { dirname as
|
|
13201
|
+
import { appendFileSync as appendFileSync4, readFileSync as readFileSync13, existsSync as existsSync12, mkdirSync as mkdirSync10 } from "node:fs";
|
|
13202
|
+
import { dirname as dirname9 } from "node:path";
|
|
12924
13203
|
function spendPath() {
|
|
12925
13204
|
if (spendPathCached)
|
|
12926
13205
|
return spendPathCached;
|
|
@@ -12932,17 +13211,17 @@ function __setSpendPathForTest(path7) {
|
|
|
12932
13211
|
}
|
|
12933
13212
|
function appendSpend(record) {
|
|
12934
13213
|
const p = spendPath();
|
|
12935
|
-
|
|
12936
|
-
|
|
13214
|
+
mkdirSync10(dirname9(p), { recursive: true });
|
|
13215
|
+
appendFileSync4(p, JSON.stringify(record) + "\n", { encoding: "utf8" });
|
|
12937
13216
|
}
|
|
12938
13217
|
function monthToDateSpend(now = /* @__PURE__ */ new Date()) {
|
|
12939
13218
|
const p = spendPath();
|
|
12940
|
-
if (!
|
|
13219
|
+
if (!existsSync12(p))
|
|
12941
13220
|
return 0;
|
|
12942
13221
|
const year = now.getUTCFullYear();
|
|
12943
13222
|
const month2 = now.getUTCMonth();
|
|
12944
13223
|
let total = 0;
|
|
12945
|
-
const raw =
|
|
13224
|
+
const raw = readFileSync13(p, "utf8");
|
|
12946
13225
|
for (const line of raw.split("\n")) {
|
|
12947
13226
|
if (!line)
|
|
12948
13227
|
continue;
|
|
@@ -12971,7 +13250,7 @@ var init_budget = __esm({
|
|
|
12971
13250
|
});
|
|
12972
13251
|
|
|
12973
13252
|
// ../entries/dist/pipeline-lock.js
|
|
12974
|
-
import { writeFileSync as
|
|
13253
|
+
import { writeFileSync as writeFileSync10, unlinkSync as unlinkSync4, existsSync as existsSync13, readFileSync as readFileSync14, statSync as statSync3 } from "node:fs";
|
|
12975
13254
|
function lockPath() {
|
|
12976
13255
|
if (lockPathCached)
|
|
12977
13256
|
return lockPathCached;
|
|
@@ -12982,7 +13261,7 @@ function __setInteractiveLockPathForTest(path7) {
|
|
|
12982
13261
|
lockPathCached = path7;
|
|
12983
13262
|
}
|
|
12984
13263
|
function touchLock() {
|
|
12985
|
-
|
|
13264
|
+
writeFileSync10(lockPath(), String(process.pid), "utf8");
|
|
12986
13265
|
}
|
|
12987
13266
|
function writeInteractiveLock() {
|
|
12988
13267
|
touchLock();
|
|
@@ -13016,13 +13295,13 @@ function pidAlive(pid) {
|
|
|
13016
13295
|
}
|
|
13017
13296
|
function interactiveLockFresh(nowMs) {
|
|
13018
13297
|
const p = lockPath();
|
|
13019
|
-
if (!
|
|
13298
|
+
if (!existsSync13(p))
|
|
13020
13299
|
return false;
|
|
13021
13300
|
try {
|
|
13022
|
-
const mtime =
|
|
13301
|
+
const mtime = statSync3(p).mtimeMs;
|
|
13023
13302
|
if (nowMs - mtime > STALE_MS)
|
|
13024
13303
|
return false;
|
|
13025
|
-
const pid = Number(
|
|
13304
|
+
const pid = Number(readFileSync14(p, "utf8").trim());
|
|
13026
13305
|
if (!Number.isFinite(pid) || pid <= 0)
|
|
13027
13306
|
return false;
|
|
13028
13307
|
if (!pidAlive(pid))
|
|
@@ -13128,8 +13407,8 @@ var init_queue = __esm({
|
|
|
13128
13407
|
});
|
|
13129
13408
|
|
|
13130
13409
|
// ../entries/dist/settings.js
|
|
13131
|
-
import { readFileSync as
|
|
13132
|
-
import { dirname as
|
|
13410
|
+
import { readFileSync as readFileSync15, writeFileSync as writeFileSync11, renameSync as renameSync5, chmodSync as chmodSync2, mkdirSync as mkdirSync11, existsSync as existsSync14 } from "node:fs";
|
|
13411
|
+
import { dirname as dirname10 } from "node:path";
|
|
13133
13412
|
function settingsPath() {
|
|
13134
13413
|
if (settingsPathCached)
|
|
13135
13414
|
return settingsPathCached;
|
|
@@ -13164,10 +13443,10 @@ function fromDisk(d) {
|
|
|
13164
13443
|
}
|
|
13165
13444
|
function readSettings() {
|
|
13166
13445
|
const p = settingsPath();
|
|
13167
|
-
if (!
|
|
13446
|
+
if (!existsSync14(p))
|
|
13168
13447
|
return DEFAULT_SETTINGS;
|
|
13169
13448
|
try {
|
|
13170
|
-
const raw =
|
|
13449
|
+
const raw = readFileSync15(p, "utf8");
|
|
13171
13450
|
return fromDisk(JSON.parse(raw));
|
|
13172
13451
|
} catch {
|
|
13173
13452
|
return DEFAULT_SETTINGS;
|
|
@@ -13175,9 +13454,9 @@ function readSettings() {
|
|
|
13175
13454
|
}
|
|
13176
13455
|
function writeSettings(s) {
|
|
13177
13456
|
const p = settingsPath();
|
|
13178
|
-
|
|
13457
|
+
mkdirSync11(dirname10(p), { recursive: true });
|
|
13179
13458
|
const tmp = `${p}.tmp`;
|
|
13180
|
-
|
|
13459
|
+
writeFileSync11(tmp, JSON.stringify(toDisk(s), null, 2), { encoding: "utf8" });
|
|
13181
13460
|
if (process.platform !== "win32") {
|
|
13182
13461
|
chmodSync2(tmp, 384);
|
|
13183
13462
|
}
|
|
@@ -16356,6 +16635,142 @@ var init_digest_month_pipeline = __esm({
|
|
|
16356
16635
|
}
|
|
16357
16636
|
});
|
|
16358
16637
|
|
|
16638
|
+
// ../entries/dist/credentials.js
|
|
16639
|
+
import { writeFileSync as writeFileSync12, readFileSync as readFileSync16, renameSync as renameSync6, chmodSync as chmodSync3, mkdirSync as mkdirSync12, existsSync as existsSync15, unlinkSync as unlinkSync5 } from "node:fs";
|
|
16640
|
+
import { dirname as dirname11 } from "node:path";
|
|
16641
|
+
async function fetchZaiUsage(candidate) {
|
|
16642
|
+
const key = candidate.trim();
|
|
16643
|
+
if (!key)
|
|
16644
|
+
throw new Error("empty key");
|
|
16645
|
+
const res = await fetch(ZAI_QUOTA_ENDPOINT, {
|
|
16646
|
+
headers: { Authorization: key, "Accept-Language": "en-US,en" }
|
|
16647
|
+
});
|
|
16648
|
+
if (!res.ok) {
|
|
16649
|
+
throw new Error(`Z.ai rejected the key (${res.status} ${res.statusText})`);
|
|
16650
|
+
}
|
|
16651
|
+
const body = await res.json().catch(() => {
|
|
16652
|
+
throw new Error("Z.ai returned an unparseable response");
|
|
16653
|
+
});
|
|
16654
|
+
if (body.code !== void 0 && body.code !== 200) {
|
|
16655
|
+
throw new Error(`Z.ai rejected the key (code ${body.code})`);
|
|
16656
|
+
}
|
|
16657
|
+
if (body.success === false) {
|
|
16658
|
+
throw new Error("Z.ai rejected the key");
|
|
16659
|
+
}
|
|
16660
|
+
const limits = body.data?.limits ?? [];
|
|
16661
|
+
let fiveHour = null;
|
|
16662
|
+
let sevenDay = null;
|
|
16663
|
+
let webSearch = null;
|
|
16664
|
+
for (const limit of limits) {
|
|
16665
|
+
const type = limit.type;
|
|
16666
|
+
if (type === "TIME_LIMIT") {
|
|
16667
|
+
const pct2 = typeof limit.percentage === "number" ? limit.percentage : null;
|
|
16668
|
+
webSearch = { used: pct2, limit: pct2 !== null ? 100 : null };
|
|
16669
|
+
continue;
|
|
16670
|
+
}
|
|
16671
|
+
if (type !== "TOKENS_LIMIT")
|
|
16672
|
+
continue;
|
|
16673
|
+
const unit = limit.unit;
|
|
16674
|
+
const pct = typeof limit.percentage === "number" ? limit.percentage : null;
|
|
16675
|
+
const resetsAt = typeof limit.nextResetTime === "number" ? new Date(limit.nextResetTime).toISOString() : null;
|
|
16676
|
+
const window = { utilization: pct, resets_at: resetsAt };
|
|
16677
|
+
if (unit === 6)
|
|
16678
|
+
sevenDay = sevenDay ?? window;
|
|
16679
|
+
else
|
|
16680
|
+
fiveHour = fiveHour ?? window;
|
|
16681
|
+
}
|
|
16682
|
+
return {
|
|
16683
|
+
captured_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16684
|
+
agent: "zai",
|
|
16685
|
+
five_hour: fiveHour ?? { utilization: null, resets_at: null },
|
|
16686
|
+
seven_day: sevenDay ?? { utilization: null, resets_at: null },
|
|
16687
|
+
seven_day_opus: null,
|
|
16688
|
+
seven_day_sonnet: null,
|
|
16689
|
+
seven_day_oauth_apps: null,
|
|
16690
|
+
seven_day_cowork: null,
|
|
16691
|
+
extra_usage: null,
|
|
16692
|
+
plan_type: body.data?.level ?? null,
|
|
16693
|
+
web_search_quota: webSearch ?? null
|
|
16694
|
+
};
|
|
16695
|
+
}
|
|
16696
|
+
async function validateAndSnapshotZaiKey(key) {
|
|
16697
|
+
const snap = await fetchZaiUsage(key);
|
|
16698
|
+
appendUsageSnapshot(snap);
|
|
16699
|
+
return snap;
|
|
16700
|
+
}
|
|
16701
|
+
function deleteZaiKeyAndPrune() {
|
|
16702
|
+
deleteZaiKey();
|
|
16703
|
+
pruneUsageAgent("zai");
|
|
16704
|
+
}
|
|
16705
|
+
function credentialsPath() {
|
|
16706
|
+
return cclensPath("credentials.json");
|
|
16707
|
+
}
|
|
16708
|
+
function readCredentials() {
|
|
16709
|
+
const p = credentialsPath();
|
|
16710
|
+
if (!existsSync15(p))
|
|
16711
|
+
return {};
|
|
16712
|
+
try {
|
|
16713
|
+
const raw = readFileSync16(p, "utf8");
|
|
16714
|
+
return JSON.parse(raw);
|
|
16715
|
+
} catch {
|
|
16716
|
+
return {};
|
|
16717
|
+
}
|
|
16718
|
+
}
|
|
16719
|
+
function readCredentialsMasked() {
|
|
16720
|
+
const store = readCredentials();
|
|
16721
|
+
if (!store.zai?.apiKey)
|
|
16722
|
+
return {};
|
|
16723
|
+
const key = store.zai.apiKey;
|
|
16724
|
+
const hint = key.length > 12 ? `${key.slice(0, 6)}\u2026${key.slice(-6)}` : `${key.slice(0, 6)}\u2026`;
|
|
16725
|
+
return { zai: { configured: true, hint } };
|
|
16726
|
+
}
|
|
16727
|
+
function writeZaiKey(apiKey) {
|
|
16728
|
+
apiKey = apiKey.trim();
|
|
16729
|
+
if (!apiKey) {
|
|
16730
|
+
deleteZaiKey();
|
|
16731
|
+
return;
|
|
16732
|
+
}
|
|
16733
|
+
const store = readCredentials();
|
|
16734
|
+
store.zai = { ...store.zai ?? {}, apiKey };
|
|
16735
|
+
const p = credentialsPath();
|
|
16736
|
+
mkdirSync12(dirname11(p), { recursive: true });
|
|
16737
|
+
const tmp = `${p}.tmp`;
|
|
16738
|
+
writeFileSync12(tmp, JSON.stringify(store, null, 2), { encoding: "utf8" });
|
|
16739
|
+
if (process.platform !== "win32") {
|
|
16740
|
+
chmodSync3(tmp, 384);
|
|
16741
|
+
}
|
|
16742
|
+
renameSync6(tmp, p);
|
|
16743
|
+
}
|
|
16744
|
+
function deleteZaiKey() {
|
|
16745
|
+
const store = readCredentials();
|
|
16746
|
+
delete store.zai;
|
|
16747
|
+
const p = credentialsPath();
|
|
16748
|
+
if (Object.keys(store).length === 0) {
|
|
16749
|
+
try {
|
|
16750
|
+
unlinkSync5(p);
|
|
16751
|
+
} catch {
|
|
16752
|
+
}
|
|
16753
|
+
return;
|
|
16754
|
+
}
|
|
16755
|
+
const tmp = `${p}.tmp`;
|
|
16756
|
+
writeFileSync12(tmp, JSON.stringify(store, null, 2), { encoding: "utf8" });
|
|
16757
|
+
if (process.platform !== "win32") {
|
|
16758
|
+
chmodSync3(tmp, 384);
|
|
16759
|
+
}
|
|
16760
|
+
renameSync6(tmp, p);
|
|
16761
|
+
}
|
|
16762
|
+
function hasZaiKey() {
|
|
16763
|
+
return !!readCredentials().zai?.apiKey;
|
|
16764
|
+
}
|
|
16765
|
+
var ZAI_QUOTA_ENDPOINT;
|
|
16766
|
+
var init_credentials = __esm({
|
|
16767
|
+
"../entries/dist/credentials.js"() {
|
|
16768
|
+
"use strict";
|
|
16769
|
+
init_fs();
|
|
16770
|
+
ZAI_QUOTA_ENDPOINT = "https://api.z.ai/api/monitor/usage/quota/limit";
|
|
16771
|
+
}
|
|
16772
|
+
});
|
|
16773
|
+
|
|
16359
16774
|
// ../entries/dist/node.js
|
|
16360
16775
|
var node_exports = {};
|
|
16361
16776
|
__export(node_exports, {
|
|
@@ -16386,19 +16801,25 @@ __export(node_exports, {
|
|
|
16386
16801
|
computeInteractionGrammar: () => computeInteractionGrammar,
|
|
16387
16802
|
computeInteractionModes: () => computeInteractionModes,
|
|
16388
16803
|
computeWorkingShapes: () => computeWorkingShapes,
|
|
16804
|
+
deleteZaiKey: () => deleteZaiKey,
|
|
16805
|
+
deleteZaiKeyAndPrune: () => deleteZaiKeyAndPrune,
|
|
16389
16806
|
enrichEntry: () => enrichEntry,
|
|
16807
|
+
fetchZaiUsage: () => fetchZaiUsage,
|
|
16390
16808
|
generateDayDigest: () => generateDayDigest,
|
|
16391
16809
|
generateMonthDigest: () => generateMonthDigest,
|
|
16392
16810
|
generateWeekDigest: () => generateWeekDigest,
|
|
16393
16811
|
getCurrentMonthDigestFromCache: () => getCurrentMonthDigestFromCache,
|
|
16394
16812
|
getCurrentWeekDigestFromCache: () => getCurrentWeekDigestFromCache,
|
|
16395
16813
|
getTodayDigestFromCache: () => getTodayDigestFromCache,
|
|
16814
|
+
hasZaiKey: () => hasZaiKey,
|
|
16396
16815
|
interactiveLockFresh: () => interactiveLockFresh,
|
|
16397
16816
|
listMonthDigestKeys: () => listMonthDigestKeys,
|
|
16398
16817
|
listWeekDigestKeys: () => listWeekDigestKeys,
|
|
16399
16818
|
mondayFor: () => mondayFor,
|
|
16400
16819
|
mondaysInMonth: () => mondaysInMonth,
|
|
16401
16820
|
monthToDateSpend: () => monthToDateSpend,
|
|
16821
|
+
readCredentials: () => readCredentials,
|
|
16822
|
+
readCredentialsMasked: () => readCredentialsMasked,
|
|
16402
16823
|
readDayDigest: () => readDayDigest,
|
|
16403
16824
|
readMonthDigest: () => readMonthDigest,
|
|
16404
16825
|
readSettings: () => readSettings,
|
|
@@ -16413,12 +16834,14 @@ __export(node_exports, {
|
|
|
16413
16834
|
setCurrentWeekDigestInCache: () => setCurrentWeekDigestInCache,
|
|
16414
16835
|
setTodayDigestInCache: () => setTodayDigestInCache,
|
|
16415
16836
|
tmuxRunnerAvailable: () => tmuxRunnerAvailable,
|
|
16837
|
+
validateAndSnapshotZaiKey: () => validateAndSnapshotZaiKey,
|
|
16416
16838
|
weekDates: () => weekDates,
|
|
16417
16839
|
writeDayDigest: () => writeDayDigest,
|
|
16418
16840
|
writeInteractiveLock: () => writeInteractiveLock,
|
|
16419
16841
|
writeMonthDigest: () => writeMonthDigest,
|
|
16420
16842
|
writeSettings: () => writeSettings,
|
|
16421
|
-
writeWeekDigest: () => writeWeekDigest
|
|
16843
|
+
writeWeekDigest: () => writeWeekDigest,
|
|
16844
|
+
writeZaiKey: () => writeZaiKey
|
|
16422
16845
|
});
|
|
16423
16846
|
var init_node = __esm({
|
|
16424
16847
|
"../entries/dist/node.js"() {
|
|
@@ -16440,6 +16863,7 @@ var init_node = __esm({
|
|
|
16440
16863
|
init_digest_month_pipeline();
|
|
16441
16864
|
init_tmux_runner();
|
|
16442
16865
|
init_digest_fs();
|
|
16866
|
+
init_credentials();
|
|
16443
16867
|
}
|
|
16444
16868
|
});
|
|
16445
16869
|
|
|
@@ -16909,6 +17333,230 @@ var init_digest = __esm({
|
|
|
16909
17333
|
}
|
|
16910
17334
|
});
|
|
16911
17335
|
|
|
17336
|
+
// src/commands/menubar.ts
|
|
17337
|
+
var menubar_exports = {};
|
|
17338
|
+
__export(menubar_exports, {
|
|
17339
|
+
menubar: () => menubar
|
|
17340
|
+
});
|
|
17341
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync13, cpSync, rmSync as rmSync2, readdirSync as readdirSync4, writeFileSync as writeFileSync13, realpathSync as realpathSync5 } from "node:fs";
|
|
17342
|
+
import { homedir as homedir6 } from "node:os";
|
|
17343
|
+
import { join as join12, dirname as dirname12 } from "node:path";
|
|
17344
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
17345
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
17346
|
+
import { promisify as promisify2 } from "node:util";
|
|
17347
|
+
function isMac2() {
|
|
17348
|
+
return process.platform === "darwin";
|
|
17349
|
+
}
|
|
17350
|
+
function bundledAppPath() {
|
|
17351
|
+
const here = dirname12(fileURLToPath3(import.meta.url));
|
|
17352
|
+
return join12(here, "..", "menubar", APP_BUNDLE);
|
|
17353
|
+
}
|
|
17354
|
+
function resolveScriptPath2() {
|
|
17355
|
+
const argv1 = process.argv[1] ?? "";
|
|
17356
|
+
try {
|
|
17357
|
+
return realpathSync5(argv1);
|
|
17358
|
+
} catch {
|
|
17359
|
+
return argv1;
|
|
17360
|
+
}
|
|
17361
|
+
}
|
|
17362
|
+
function writeCliLaunchFile() {
|
|
17363
|
+
try {
|
|
17364
|
+
writeFileSync13(
|
|
17365
|
+
cclensPath("cli-launch.json"),
|
|
17366
|
+
JSON.stringify({ node: process.execPath, script: resolveScriptPath2() }),
|
|
17367
|
+
"utf8"
|
|
17368
|
+
);
|
|
17369
|
+
} catch {
|
|
17370
|
+
}
|
|
17371
|
+
}
|
|
17372
|
+
function installedAppPath() {
|
|
17373
|
+
return join12(homedir6(), "Applications", APP_BUNDLE);
|
|
17374
|
+
}
|
|
17375
|
+
async function isRunning() {
|
|
17376
|
+
try {
|
|
17377
|
+
const { stdout } = await execFileAsync2("pgrep", ["-x", BUNDLE_EXEC]);
|
|
17378
|
+
return stdout.trim().length > 0;
|
|
17379
|
+
} catch {
|
|
17380
|
+
return false;
|
|
17381
|
+
}
|
|
17382
|
+
}
|
|
17383
|
+
async function launchApp(path7) {
|
|
17384
|
+
await execFileAsync2("open", ["-a", path7]);
|
|
17385
|
+
}
|
|
17386
|
+
async function quitApp() {
|
|
17387
|
+
await execFileAsync2("osascript", ["-e", `tell application "${BUNDLE_EXEC}" to quit`]).catch(
|
|
17388
|
+
() => {
|
|
17389
|
+
}
|
|
17390
|
+
);
|
|
17391
|
+
await execFileAsync2("pkill", ["-x", BUNDLE_EXEC]).catch(() => {
|
|
17392
|
+
});
|
|
17393
|
+
}
|
|
17394
|
+
async function setLoginItem(enabled, appPath) {
|
|
17395
|
+
const script = enabled ? `tell application "System Events" to make login item at end with properties {path:"${appPath}", hidden:false}` : `tell application "System Events" to delete login item "${APP_BUNDLE.replace(".app", "")}"`;
|
|
17396
|
+
await execFileAsync2("osascript", ["-e", script]).catch(() => {
|
|
17397
|
+
});
|
|
17398
|
+
}
|
|
17399
|
+
async function installMenubar(opts) {
|
|
17400
|
+
if (!isMac2()) {
|
|
17401
|
+
console.log(NON_MAC_MSG2);
|
|
17402
|
+
return;
|
|
17403
|
+
}
|
|
17404
|
+
const src = bundledAppPath();
|
|
17405
|
+
if (!existsSync16(src)) {
|
|
17406
|
+
console.error(
|
|
17407
|
+
`Bundled widget not found at ${src}.
|
|
17408
|
+
This install was probably built without the menubar artifact. Run \`node apps/menubar/build-app.sh && cp -R apps/menubar/dist/FleetlensMenubar.app packages/cli/menubar/\` and rebuild.`
|
|
17409
|
+
);
|
|
17410
|
+
process.exit(1);
|
|
17411
|
+
}
|
|
17412
|
+
const destDir = join12(homedir6(), "Applications");
|
|
17413
|
+
mkdirSync13(destDir, { recursive: true });
|
|
17414
|
+
const dest = installedAppPath();
|
|
17415
|
+
if (await isRunning()) {
|
|
17416
|
+
console.log("Stopping the running widget\u2026");
|
|
17417
|
+
await quitApp();
|
|
17418
|
+
await new Promise((r) => setTimeout(r, 400));
|
|
17419
|
+
}
|
|
17420
|
+
rmSync2(dest, { recursive: true, force: true });
|
|
17421
|
+
cpSync(src, dest, { recursive: true });
|
|
17422
|
+
writeCliLaunchFile();
|
|
17423
|
+
console.log(`Installed \u2192 ${dest}`);
|
|
17424
|
+
if (opts.login) {
|
|
17425
|
+
await setLoginItem(true, dest);
|
|
17426
|
+
console.log("Login item enabled (launches at login).");
|
|
17427
|
+
}
|
|
17428
|
+
if (opts.open) {
|
|
17429
|
+
await launchApp(dest);
|
|
17430
|
+
console.log("Opened \u2014 check your menu bar (gauge icon on the right side).");
|
|
17431
|
+
} else {
|
|
17432
|
+
console.log(`Launch with: open -a "${dest}"`);
|
|
17433
|
+
}
|
|
17434
|
+
}
|
|
17435
|
+
async function uninstallMenubar() {
|
|
17436
|
+
if (!isMac2()) {
|
|
17437
|
+
console.log(NON_MAC_MSG2);
|
|
17438
|
+
return;
|
|
17439
|
+
}
|
|
17440
|
+
await setLoginItem(false, installedAppPath());
|
|
17441
|
+
if (await isRunning()) {
|
|
17442
|
+
console.log("Quitting the running widget\u2026");
|
|
17443
|
+
await quitApp();
|
|
17444
|
+
await new Promise((r) => setTimeout(r, 300));
|
|
17445
|
+
}
|
|
17446
|
+
const dest = installedAppPath();
|
|
17447
|
+
if (existsSync16(dest)) {
|
|
17448
|
+
rmSync2(dest, { recursive: true, force: true });
|
|
17449
|
+
console.log(`Removed ${dest}`);
|
|
17450
|
+
} else {
|
|
17451
|
+
console.log("Widget is not installed \u2014 nothing to remove.");
|
|
17452
|
+
}
|
|
17453
|
+
console.log("Login item cleared (if it was set).");
|
|
17454
|
+
}
|
|
17455
|
+
async function openMenubar() {
|
|
17456
|
+
if (!isMac2()) {
|
|
17457
|
+
console.log(NON_MAC_MSG2);
|
|
17458
|
+
return;
|
|
17459
|
+
}
|
|
17460
|
+
const dest = installedAppPath();
|
|
17461
|
+
if (!existsSync16(dest)) {
|
|
17462
|
+
console.log("Widget not installed yet. Run `fleetlens menubar install` first.");
|
|
17463
|
+
return;
|
|
17464
|
+
}
|
|
17465
|
+
if (await isRunning()) {
|
|
17466
|
+
console.log("Widget is already running.");
|
|
17467
|
+
return;
|
|
17468
|
+
}
|
|
17469
|
+
await launchApp(dest);
|
|
17470
|
+
console.log("Opened \u2014 check your menu bar.");
|
|
17471
|
+
}
|
|
17472
|
+
async function statusMenubar() {
|
|
17473
|
+
if (!isMac2()) {
|
|
17474
|
+
console.log(`Menu bar widget: macOS-only (not available on ${process.platform}).`);
|
|
17475
|
+
return;
|
|
17476
|
+
}
|
|
17477
|
+
const dest = installedAppPath();
|
|
17478
|
+
const installed = existsSync16(dest);
|
|
17479
|
+
const running = await isRunning();
|
|
17480
|
+
const bundled = existsSync16(bundledAppPath());
|
|
17481
|
+
console.log(`Menu bar widget: ${installed ? "installed" : "not installed"}${installed ? ` (${dest})` : ""}`);
|
|
17482
|
+
console.log(`Running: ${running ? "yes" : "no"}`);
|
|
17483
|
+
console.log(`Bundled in CLI: ${bundled ? "yes" : "no \u2014 this build ships without the widget"}`);
|
|
17484
|
+
if (installed) {
|
|
17485
|
+
try {
|
|
17486
|
+
const apps = readdirSync4(join12(homedir6(), "Applications"));
|
|
17487
|
+
const ours = apps.find((a) => a === APP_BUNDLE);
|
|
17488
|
+
console.log(`App bundle: ${ours ? "present in ~/Applications" : "missing"}`);
|
|
17489
|
+
} catch {
|
|
17490
|
+
}
|
|
17491
|
+
}
|
|
17492
|
+
}
|
|
17493
|
+
async function menubar(args2) {
|
|
17494
|
+
const sub = args2[0] ?? "status";
|
|
17495
|
+
const flags = args2.slice(1);
|
|
17496
|
+
const noOpen = flags.includes("--no-open");
|
|
17497
|
+
const noLogin = flags.includes("--no-login");
|
|
17498
|
+
switch (sub) {
|
|
17499
|
+
case "install": {
|
|
17500
|
+
await installMenubar({ open: !noOpen, login: !noLogin });
|
|
17501
|
+
break;
|
|
17502
|
+
}
|
|
17503
|
+
case "uninstall":
|
|
17504
|
+
case "remove":
|
|
17505
|
+
await uninstallMenubar();
|
|
17506
|
+
break;
|
|
17507
|
+
case "open":
|
|
17508
|
+
case "start":
|
|
17509
|
+
await openMenubar();
|
|
17510
|
+
break;
|
|
17511
|
+
case "stop":
|
|
17512
|
+
case "quit":
|
|
17513
|
+
if (await isRunning()) {
|
|
17514
|
+
await quitApp();
|
|
17515
|
+
console.log("Stopped.");
|
|
17516
|
+
} else {
|
|
17517
|
+
console.log("Widget is not running.");
|
|
17518
|
+
}
|
|
17519
|
+
break;
|
|
17520
|
+
case "status":
|
|
17521
|
+
await statusMenubar();
|
|
17522
|
+
break;
|
|
17523
|
+
case "help":
|
|
17524
|
+
case "--help":
|
|
17525
|
+
case "-h":
|
|
17526
|
+
console.log(`Usage: fleetlens menubar <install|uninstall|open|stop|status>
|
|
17527
|
+
|
|
17528
|
+
install [--no-open] [--no-login] Copy the native macOS menu bar widget to
|
|
17529
|
+
~/Applications and launch it. Registers a
|
|
17530
|
+
login item by default.
|
|
17531
|
+
uninstall Quit + remove the widget, clear login item.
|
|
17532
|
+
open Launch the installed widget.
|
|
17533
|
+
stop Quit the running widget.
|
|
17534
|
+
status Show install/running/bundled state.
|
|
17535
|
+
|
|
17536
|
+
The widget tails ~/.cclens/usage.jsonl and shows live Claude Code / Codex
|
|
17537
|
+
plan utilization in the menu bar. Click it for a popover, or "Dashboard" to
|
|
17538
|
+
open http://localhost:3321.`);
|
|
17539
|
+
break;
|
|
17540
|
+
default:
|
|
17541
|
+
console.error(
|
|
17542
|
+
`Unknown menubar subcommand: ${sub}
|
|
17543
|
+
Usage: fleetlens menubar <install|uninstall|open|stop|status>`
|
|
17544
|
+
);
|
|
17545
|
+
process.exit(1);
|
|
17546
|
+
}
|
|
17547
|
+
}
|
|
17548
|
+
var execFileAsync2, APP_BUNDLE, BUNDLE_EXEC, NON_MAC_MSG2;
|
|
17549
|
+
var init_menubar = __esm({
|
|
17550
|
+
"src/commands/menubar.ts"() {
|
|
17551
|
+
"use strict";
|
|
17552
|
+
init_fs();
|
|
17553
|
+
execFileAsync2 = promisify2(execFile2);
|
|
17554
|
+
APP_BUNDLE = "FleetlensMenubar.app";
|
|
17555
|
+
BUNDLE_EXEC = "FleetlensMenubar";
|
|
17556
|
+
NON_MAC_MSG2 = "The Fleetlens menu bar widget is a native macOS app and is macOS-only. On Linux/Windows, keep using the dashboard at the printed URL.";
|
|
17557
|
+
}
|
|
17558
|
+
});
|
|
17559
|
+
|
|
16912
17560
|
// src/team/config.ts
|
|
16913
17561
|
var init_config = __esm({
|
|
16914
17562
|
"src/team/config.ts"() {
|
|
@@ -16918,8 +17566,8 @@ var init_config = __esm({
|
|
|
16918
17566
|
});
|
|
16919
17567
|
|
|
16920
17568
|
// src/perception/build-entries.ts
|
|
16921
|
-
import { statSync as
|
|
16922
|
-
import { basename, dirname as
|
|
17569
|
+
import { statSync as statSync4, readFileSync as readFileSync17 } from "node:fs";
|
|
17570
|
+
import { basename as basename2, dirname as dirname13 } from "node:path";
|
|
16923
17571
|
function decodeProjectDirName(projectDir) {
|
|
16924
17572
|
if (projectDir.startsWith("-")) {
|
|
16925
17573
|
return "/" + projectDir.slice(1).replace(/-/g, "/");
|
|
@@ -16927,8 +17575,8 @@ function decodeProjectDirName(projectDir) {
|
|
|
16927
17575
|
return projectDir.replace(/-/g, "/");
|
|
16928
17576
|
}
|
|
16929
17577
|
function buildEntriesForFile(filePath) {
|
|
16930
|
-
const stat =
|
|
16931
|
-
const raw =
|
|
17578
|
+
const stat = statSync4(filePath);
|
|
17579
|
+
const raw = readFileSync17(filePath, "utf8");
|
|
16932
17580
|
const rawLines = raw.split("\n").filter(Boolean).map((l) => {
|
|
16933
17581
|
try {
|
|
16934
17582
|
return JSON.parse(l);
|
|
@@ -16938,8 +17586,8 @@ function buildEntriesForFile(filePath) {
|
|
|
16938
17586
|
}).filter((x) => x !== null);
|
|
16939
17587
|
if (rawLines.length === 0) return null;
|
|
16940
17588
|
const { meta, events } = parseTranscript(rawLines);
|
|
16941
|
-
const fileName =
|
|
16942
|
-
const projectDir =
|
|
17589
|
+
const fileName = basename2(filePath);
|
|
17590
|
+
const projectDir = basename2(dirname13(filePath));
|
|
16943
17591
|
const sessionId = fileName.replace(/\.jsonl$/, "");
|
|
16944
17592
|
const sd = {
|
|
16945
17593
|
...meta,
|
|
@@ -17025,7 +17673,7 @@ function clipSegmentsToDay(segments, bounds) {
|
|
|
17025
17673
|
}
|
|
17026
17674
|
function filterSyncedSessions(sessions, syncProjects) {
|
|
17027
17675
|
if (!syncProjects) return sessions;
|
|
17028
|
-
return sessions.filter((s) => shouldSyncProject(
|
|
17676
|
+
return sessions.filter((s) => shouldSyncProject(projectKey(s.projectName), syncProjects));
|
|
17029
17677
|
}
|
|
17030
17678
|
function sessionTouchesDay(s, day2) {
|
|
17031
17679
|
const bounds = dayBoundsMs(day2);
|
|
@@ -17066,7 +17714,7 @@ function buildRichRollupBlocks(day2, daySessions, entries2, resolveRepo) {
|
|
|
17066
17714
|
const projects = /* @__PURE__ */ new Map();
|
|
17067
17715
|
for (const s of clippedSessions) {
|
|
17068
17716
|
const canonical = canonicalProjectName(s.projectName);
|
|
17069
|
-
const name =
|
|
17717
|
+
const name = projectKey(s.projectName);
|
|
17070
17718
|
const repo = resolveRepo?.(canonical) ?? sessionRepo.get(s.id);
|
|
17071
17719
|
const key = repo ?? name;
|
|
17072
17720
|
const ms = s.activeSegments.reduce((sum, seg) => sum + (seg.endMs - seg.startMs), 0);
|
|
@@ -17109,7 +17757,7 @@ function buildRichRollupBlocks(day2, daySessions, entries2, resolveRepo) {
|
|
|
17109
17757
|
commits += e.numbers.commits;
|
|
17110
17758
|
pushes += e.numbers.pushes;
|
|
17111
17759
|
if (e.github_repos?.length) {
|
|
17112
|
-
const key = sessionRepo.get(e.session_id) ??
|
|
17760
|
+
const key = sessionRepo.get(e.session_id) ?? projectKey(e.project);
|
|
17113
17761
|
const set = projectRepos.get(key) ?? /* @__PURE__ */ new Set();
|
|
17114
17762
|
for (const r of e.github_repos) set.add(r);
|
|
17115
17763
|
projectRepos.set(key, set);
|
|
@@ -17193,7 +17841,7 @@ function buildIngestPayload(inputs) {
|
|
|
17193
17841
|
return {
|
|
17194
17842
|
ingestId: randomUUID2(),
|
|
17195
17843
|
observedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
17196
|
-
cliVersion: "0.15.
|
|
17844
|
+
cliVersion: "0.15.4",
|
|
17197
17845
|
...richRollup || inputs.enrichedExtras || inputs.artifactSignals ? { schemaVersion: RICH_ROLLUP_SCHEMA_VERSION } : {},
|
|
17198
17846
|
...inputs.rollup ? { dailyRollup: inputs.rollup } : {},
|
|
17199
17847
|
...richRollup ? { richRollup } : {},
|
|
@@ -17234,13 +17882,13 @@ var init_push = __esm({
|
|
|
17234
17882
|
});
|
|
17235
17883
|
|
|
17236
17884
|
// src/team/git-remote.ts
|
|
17237
|
-
import { existsSync as
|
|
17238
|
-
import { dirname as
|
|
17885
|
+
import { existsSync as existsSync17, readFileSync as readFileSync18, statSync as statSync5 } from "node:fs";
|
|
17886
|
+
import { dirname as dirname14, isAbsolute as isAbsolute2, join as join13, resolve as resolve2 } from "node:path";
|
|
17239
17887
|
function parseGithubRemote(url) {
|
|
17240
17888
|
const m = url.trim().match(GITHUB_URL_RE);
|
|
17241
17889
|
return m ? `${m[1]}/${m[2]}`.toLowerCase() : null;
|
|
17242
17890
|
}
|
|
17243
|
-
function
|
|
17891
|
+
function originUrl2(configText) {
|
|
17244
17892
|
let inOrigin = false;
|
|
17245
17893
|
for (const line of configText.split("\n")) {
|
|
17246
17894
|
const t = line.trim();
|
|
@@ -17255,36 +17903,36 @@ function originUrl(configText) {
|
|
|
17255
17903
|
return null;
|
|
17256
17904
|
}
|
|
17257
17905
|
function gitConfigPathFor(dir) {
|
|
17258
|
-
const dotGit =
|
|
17259
|
-
const st =
|
|
17906
|
+
const dotGit = join13(dir, ".git");
|
|
17907
|
+
const st = statSync5(dotGit, { throwIfNoEntry: false });
|
|
17260
17908
|
if (!st) return null;
|
|
17261
|
-
if (st.isDirectory()) return
|
|
17262
|
-
const m =
|
|
17909
|
+
if (st.isDirectory()) return join13(dotGit, "config");
|
|
17910
|
+
const m = readFileSync18(dotGit, "utf8").match(/^gitdir:\s*(.+)\s*$/m);
|
|
17263
17911
|
if (!m) return null;
|
|
17264
|
-
const gd =
|
|
17265
|
-
const commondirFile =
|
|
17266
|
-
if (
|
|
17267
|
-
const common =
|
|
17268
|
-
return
|
|
17912
|
+
const gd = isAbsolute2(m[1]) ? m[1] : resolve2(dir, m[1]);
|
|
17913
|
+
const commondirFile = join13(gd, "commondir");
|
|
17914
|
+
if (existsSync17(commondirFile)) {
|
|
17915
|
+
const common = readFileSync18(commondirFile, "utf8").trim();
|
|
17916
|
+
return join13(isAbsolute2(common) ? common : resolve2(gd, common), "config");
|
|
17269
17917
|
}
|
|
17270
|
-
return
|
|
17918
|
+
return join13(gd, "config");
|
|
17271
17919
|
}
|
|
17272
17920
|
function createRepoResolver() {
|
|
17273
17921
|
const cache = /* @__PURE__ */ new Map();
|
|
17274
17922
|
return (dir) => {
|
|
17275
|
-
if (!dir || !
|
|
17923
|
+
if (!dir || !isAbsolute2(dir)) return null;
|
|
17276
17924
|
const hit = cache.get(dir);
|
|
17277
17925
|
if (hit !== void 0) return hit;
|
|
17278
17926
|
let repo = null;
|
|
17279
17927
|
try {
|
|
17280
|
-
for (let d = dir; ; d =
|
|
17928
|
+
for (let d = dir; ; d = dirname14(d)) {
|
|
17281
17929
|
const config = gitConfigPathFor(d);
|
|
17282
|
-
if (config &&
|
|
17283
|
-
const url =
|
|
17930
|
+
if (config && existsSync17(config)) {
|
|
17931
|
+
const url = originUrl2(readFileSync18(config, "utf8"));
|
|
17284
17932
|
repo = url ? parseGithubRemote(url) : null;
|
|
17285
17933
|
break;
|
|
17286
17934
|
}
|
|
17287
|
-
if (d ===
|
|
17935
|
+
if (d === dirname14(d)) break;
|
|
17288
17936
|
}
|
|
17289
17937
|
} catch {
|
|
17290
17938
|
repo = null;
|
|
@@ -17302,14 +17950,14 @@ var init_git_remote = __esm({
|
|
|
17302
17950
|
});
|
|
17303
17951
|
|
|
17304
17952
|
// src/team/queue.ts
|
|
17305
|
-
import { readFileSync as
|
|
17306
|
-
import { dirname as
|
|
17953
|
+
import { readFileSync as readFileSync19, writeFileSync as writeFileSync14, appendFileSync as appendFileSync5, statSync as statSync6, mkdirSync as mkdirSync14 } from "node:fs";
|
|
17954
|
+
import { dirname as dirname15 } from "node:path";
|
|
17307
17955
|
function enqueuePayload(payload, queuePath = QUEUE_PATH) {
|
|
17308
|
-
|
|
17956
|
+
mkdirSync14(dirname15(queuePath), { recursive: true });
|
|
17309
17957
|
const entry = { payload, enqueuedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
17310
|
-
|
|
17958
|
+
appendFileSync5(queuePath, JSON.stringify(entry) + "\n", "utf8");
|
|
17311
17959
|
try {
|
|
17312
|
-
const { size } =
|
|
17960
|
+
const { size } = statSync6(queuePath);
|
|
17313
17961
|
if (size > MAX_SIZE_BYTES) {
|
|
17314
17962
|
pruneOldest(queuePath);
|
|
17315
17963
|
}
|
|
@@ -17319,7 +17967,7 @@ function enqueuePayload(payload, queuePath = QUEUE_PATH) {
|
|
|
17319
17967
|
function dequeuePayloads(queuePath = QUEUE_PATH) {
|
|
17320
17968
|
let lines;
|
|
17321
17969
|
try {
|
|
17322
|
-
lines =
|
|
17970
|
+
lines = readFileSync19(queuePath, "utf8").trim().split("\n").filter(Boolean);
|
|
17323
17971
|
} catch {
|
|
17324
17972
|
return [];
|
|
17325
17973
|
}
|
|
@@ -17334,18 +17982,18 @@ function dequeuePayloads(queuePath = QUEUE_PATH) {
|
|
|
17334
17982
|
} catch {
|
|
17335
17983
|
}
|
|
17336
17984
|
}
|
|
17337
|
-
|
|
17985
|
+
writeFileSync14(queuePath, "", "utf8");
|
|
17338
17986
|
return valid.map((e) => e.payload);
|
|
17339
17987
|
}
|
|
17340
17988
|
function pruneOldest(queuePath) {
|
|
17341
17989
|
let lines;
|
|
17342
17990
|
try {
|
|
17343
|
-
lines =
|
|
17991
|
+
lines = readFileSync19(queuePath, "utf8").trim().split("\n").filter(Boolean);
|
|
17344
17992
|
} catch {
|
|
17345
17993
|
return;
|
|
17346
17994
|
}
|
|
17347
17995
|
const keep = lines.slice(Math.floor(lines.length / 2));
|
|
17348
|
-
|
|
17996
|
+
writeFileSync14(queuePath, keep.join("\n") + "\n", "utf8");
|
|
17349
17997
|
}
|
|
17350
17998
|
var QUEUE_PATH, MAX_SIZE_BYTES, MAX_AGE_MS;
|
|
17351
17999
|
var init_queue2 = __esm({
|
|
@@ -17359,8 +18007,8 @@ var init_queue2 = __esm({
|
|
|
17359
18007
|
});
|
|
17360
18008
|
|
|
17361
18009
|
// src/usage/profile.ts
|
|
17362
|
-
import { existsSync as
|
|
17363
|
-
import { dirname as
|
|
18010
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync15, readFileSync as readFileSync20, writeFileSync as writeFileSync15 } from "node:fs";
|
|
18011
|
+
import { dirname as dirname16 } from "node:path";
|
|
17364
18012
|
function mapRateLimitTier(rateLimitTier) {
|
|
17365
18013
|
switch (rateLimitTier) {
|
|
17366
18014
|
case "default_claude_pro":
|
|
@@ -17400,9 +18048,9 @@ async function fetchProfile(nowMs = Date.now()) {
|
|
|
17400
18048
|
};
|
|
17401
18049
|
}
|
|
17402
18050
|
function readCachedProfile(cachePath) {
|
|
17403
|
-
if (!
|
|
18051
|
+
if (!existsSync18(cachePath)) return null;
|
|
17404
18052
|
try {
|
|
17405
|
-
const raw = JSON.parse(
|
|
18053
|
+
const raw = JSON.parse(readFileSync20(cachePath, "utf8"));
|
|
17406
18054
|
if (typeof raw.fetchedAtMs !== "number" || !raw.profile) return null;
|
|
17407
18055
|
return raw;
|
|
17408
18056
|
} catch {
|
|
@@ -17410,8 +18058,8 @@ function readCachedProfile(cachePath) {
|
|
|
17410
18058
|
}
|
|
17411
18059
|
}
|
|
17412
18060
|
function writeCachedProfile(cachePath, profile, nowMs = Date.now()) {
|
|
17413
|
-
|
|
17414
|
-
|
|
18061
|
+
mkdirSync15(dirname16(cachePath), { recursive: true });
|
|
18062
|
+
writeFileSync15(
|
|
17415
18063
|
cachePath,
|
|
17416
18064
|
JSON.stringify({ fetchedAtMs: nowMs, profile }, null, 2),
|
|
17417
18065
|
{ mode: 384 }
|
|
@@ -17591,11 +18239,11 @@ var init_backfill = __esm({
|
|
|
17591
18239
|
});
|
|
17592
18240
|
|
|
17593
18241
|
// src/team/sync-log.ts
|
|
17594
|
-
import { readFileSync as
|
|
18242
|
+
import { readFileSync as readFileSync21 } from "node:fs";
|
|
17595
18243
|
function readPendingSyncLog(watermark) {
|
|
17596
18244
|
let raw;
|
|
17597
18245
|
try {
|
|
17598
|
-
raw =
|
|
18246
|
+
raw = readFileSync21(cclensPath("daemon.log"), "utf8");
|
|
17599
18247
|
} catch {
|
|
17600
18248
|
return { lines: [] };
|
|
17601
18249
|
}
|
|
@@ -17623,12 +18271,12 @@ var init_sync_log = __esm({
|
|
|
17623
18271
|
});
|
|
17624
18272
|
|
|
17625
18273
|
// src/team/last-push.ts
|
|
17626
|
-
import { writeFileSync as
|
|
17627
|
-
import { join as
|
|
18274
|
+
import { writeFileSync as writeFileSync16, unlinkSync as unlinkSync6, mkdirSync as mkdirSync16 } from "node:fs";
|
|
18275
|
+
import { join as join14 } from "node:path";
|
|
17628
18276
|
function write(record, dir) {
|
|
17629
18277
|
const d = dir ?? cclensHome();
|
|
17630
|
-
|
|
17631
|
-
|
|
18278
|
+
mkdirSync16(d, { recursive: true });
|
|
18279
|
+
writeFileSync16(join14(d, LAST_PUSH_FILE), JSON.stringify(record, null, 2), { mode: 384 });
|
|
17632
18280
|
}
|
|
17633
18281
|
function writeLastPushSuccess(payload, dir) {
|
|
17634
18282
|
write({ pushedAt: (/* @__PURE__ */ new Date()).toISOString(), ok: true, payload }, dir);
|
|
@@ -17639,7 +18287,7 @@ function writeLastPushFailure(payload, error, dir) {
|
|
|
17639
18287
|
function clearLastPush(dir) {
|
|
17640
18288
|
const d = dir ?? cclensHome();
|
|
17641
18289
|
try {
|
|
17642
|
-
|
|
18290
|
+
unlinkSync6(join14(d, LAST_PUSH_FILE));
|
|
17643
18291
|
} catch {
|
|
17644
18292
|
}
|
|
17645
18293
|
}
|
|
@@ -17659,38 +18307,38 @@ __export(file_probe_exports, {
|
|
|
17659
18307
|
probeArtifactSignals: () => probeArtifactSignals
|
|
17660
18308
|
});
|
|
17661
18309
|
import { createHash } from "node:crypto";
|
|
17662
|
-
import { existsSync as
|
|
17663
|
-
import { homedir as
|
|
17664
|
-
import { join as
|
|
18310
|
+
import { existsSync as existsSync19, readdirSync as readdirSync5, statSync as statSync7 } from "node:fs";
|
|
18311
|
+
import { homedir as homedir7 } from "node:os";
|
|
18312
|
+
import { join as join15, relative, resolve as resolve3, sep } from "node:path";
|
|
17665
18313
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
17666
18314
|
function pathHash(relPath) {
|
|
17667
18315
|
return createHash("sha256").update(relPath.split(sep).join("/")).digest("hex").slice(0, 32);
|
|
17668
18316
|
}
|
|
17669
18317
|
function defaultScanRoots(extraRoots = []) {
|
|
17670
18318
|
const roots = [];
|
|
17671
|
-
const home =
|
|
17672
|
-
if (
|
|
18319
|
+
const home = join15(homedir7(), ".claude");
|
|
18320
|
+
if (existsSync19(home)) roots.push({ root: home, label: "user" });
|
|
17673
18321
|
for (const e of extraRoots) {
|
|
17674
|
-
const r =
|
|
17675
|
-
if (
|
|
18322
|
+
const r = resolve3(e, ".claude");
|
|
18323
|
+
if (existsSync19(r) && r !== home) roots.push({ root: r, label: "project" });
|
|
17676
18324
|
}
|
|
17677
18325
|
return roots;
|
|
17678
18326
|
}
|
|
17679
18327
|
function listMarkdownFiles(dir) {
|
|
17680
|
-
if (!
|
|
18328
|
+
if (!existsSync19(dir)) return [];
|
|
17681
18329
|
const out = [];
|
|
17682
18330
|
let entries2;
|
|
17683
18331
|
try {
|
|
17684
|
-
entries2 =
|
|
18332
|
+
entries2 = readdirSync5(dir);
|
|
17685
18333
|
} catch {
|
|
17686
18334
|
return [];
|
|
17687
18335
|
}
|
|
17688
18336
|
for (const name of entries2) {
|
|
17689
18337
|
if (name.startsWith(".")) continue;
|
|
17690
|
-
const full =
|
|
18338
|
+
const full = join15(dir, name);
|
|
17691
18339
|
let stat;
|
|
17692
18340
|
try {
|
|
17693
|
-
stat =
|
|
18341
|
+
stat = statSync7(full);
|
|
17694
18342
|
} catch {
|
|
17695
18343
|
continue;
|
|
17696
18344
|
}
|
|
@@ -17707,19 +18355,19 @@ function firstSeenDateOf(file) {
|
|
|
17707
18355
|
const out = execFileSync3(
|
|
17708
18356
|
"git",
|
|
17709
18357
|
["log", "--diff-filter=A", "--follow", "--format=%cs", "--", file],
|
|
17710
|
-
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd:
|
|
18358
|
+
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd: dirname17(file) }
|
|
17711
18359
|
).trim().split("\n").filter(Boolean);
|
|
17712
18360
|
if (out.length > 0) return out[out.length - 1];
|
|
17713
18361
|
} catch {
|
|
17714
18362
|
}
|
|
17715
18363
|
try {
|
|
17716
|
-
const s =
|
|
18364
|
+
const s = statSync7(file);
|
|
17717
18365
|
return localDay(s.birthtime || s.mtime);
|
|
17718
18366
|
} catch {
|
|
17719
18367
|
return todayLocal();
|
|
17720
18368
|
}
|
|
17721
18369
|
}
|
|
17722
|
-
function
|
|
18370
|
+
function dirname17(p) {
|
|
17723
18371
|
const i = p.lastIndexOf(sep);
|
|
17724
18372
|
return i < 0 ? "." : p.slice(0, i);
|
|
17725
18373
|
}
|
|
@@ -17746,8 +18394,8 @@ function todayLocal() {
|
|
|
17746
18394
|
function scanAuthored(roots, subdir, day2) {
|
|
17747
18395
|
const out = [];
|
|
17748
18396
|
for (const r of roots) {
|
|
17749
|
-
const dir =
|
|
17750
|
-
if (!
|
|
18397
|
+
const dir = join15(r.root, subdir);
|
|
18398
|
+
if (!existsSync19(dir)) continue;
|
|
17751
18399
|
for (const f of listMarkdownFiles(dir)) {
|
|
17752
18400
|
const firstSeen = firstSeenDateOf(f);
|
|
17753
18401
|
if (firstSeen !== day2) continue;
|
|
@@ -17760,14 +18408,14 @@ function scanAuthored(roots, subdir, day2) {
|
|
|
17760
18408
|
function scanEdited(roots, day2) {
|
|
17761
18409
|
const out = [];
|
|
17762
18410
|
for (const r of roots) {
|
|
17763
|
-
const dir =
|
|
17764
|
-
if (!
|
|
18411
|
+
const dir = join15(r.root, "skills");
|
|
18412
|
+
if (!existsSync19(dir)) continue;
|
|
17765
18413
|
for (const f of listMarkdownFiles(dir)) {
|
|
17766
18414
|
const firstSeen = firstSeenDateOf(f);
|
|
17767
18415
|
if (firstSeen === day2) continue;
|
|
17768
18416
|
let stat;
|
|
17769
18417
|
try {
|
|
17770
|
-
stat =
|
|
18418
|
+
stat = statSync7(f);
|
|
17771
18419
|
} catch {
|
|
17772
18420
|
continue;
|
|
17773
18421
|
}
|
|
@@ -17783,17 +18431,17 @@ function claudemdLineDelta(extraRoots, authorEmail, day2) {
|
|
|
17783
18431
|
let delta = 0;
|
|
17784
18432
|
const candidates = [];
|
|
17785
18433
|
for (const e of extraRoots) {
|
|
17786
|
-
const f =
|
|
17787
|
-
if (
|
|
18434
|
+
const f = resolve3(e, "CLAUDE.md");
|
|
18435
|
+
if (existsSync19(f)) candidates.push(f);
|
|
17788
18436
|
}
|
|
17789
|
-
const homeClaudeMd =
|
|
17790
|
-
if (
|
|
18437
|
+
const homeClaudeMd = join15(homedir7(), "CLAUDE.md");
|
|
18438
|
+
if (existsSync19(homeClaudeMd)) candidates.push(homeClaudeMd);
|
|
17791
18439
|
for (const file of candidates) {
|
|
17792
18440
|
try {
|
|
17793
18441
|
const out = execFileSync3(
|
|
17794
18442
|
"git",
|
|
17795
18443
|
["log", "--numstat", "--format=COMMIT %cs %ae", "--", file],
|
|
17796
|
-
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd:
|
|
18444
|
+
{ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], cwd: dirname17(file) }
|
|
17797
18445
|
);
|
|
17798
18446
|
let currentDate = "";
|
|
17799
18447
|
let currentEmail = "";
|
|
@@ -17857,8 +18505,8 @@ async function dispatchCommand(command2, config, log) {
|
|
|
17857
18505
|
}
|
|
17858
18506
|
}
|
|
17859
18507
|
async function runActivityBackfill(command2, config, log) {
|
|
17860
|
-
const { listSessions: listSessions2, shouldSyncProject: shouldSyncProject2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
17861
|
-
const { toLocalDay: toLocalDay4,
|
|
18508
|
+
const { listSessions: listSessions2, resolveProjectIdentity: resolveProjectIdentity2, shouldSyncProject: shouldSyncProject2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
18509
|
+
const { toLocalDay: toLocalDay4, projectKey: projectKey2 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
|
|
17862
18510
|
const { probeArtifactSignals: probeArtifactSignals2 } = await Promise.resolve().then(() => (init_file_probe(), file_probe_exports));
|
|
17863
18511
|
const days = command2.params.days;
|
|
17864
18512
|
const todayMs = Date.now();
|
|
@@ -17892,7 +18540,7 @@ async function runActivityBackfill(command2, config, log) {
|
|
|
17892
18540
|
const richBlocks = buildRichBlocksForDay(rollup.day, daySessions, resolveRepo);
|
|
17893
18541
|
let artifactSignals = null;
|
|
17894
18542
|
try {
|
|
17895
|
-
const cwdAllowed = shouldSyncProject2(
|
|
18543
|
+
const cwdAllowed = shouldSyncProject2(projectKey2(resolveProjectIdentity2(process.cwd()).projectName), config.syncProjects);
|
|
17896
18544
|
artifactSignals = probeArtifactSignals2({ day: rollup.day, extraRoots: cwdAllowed ? [process.cwd()] : [] });
|
|
17897
18545
|
} catch {
|
|
17898
18546
|
}
|
|
@@ -18044,7 +18692,7 @@ async function runTeamSync(log = noopLog2, configOverride, options = {}) {
|
|
|
18044
18692
|
try {
|
|
18045
18693
|
resetEnsuredSessions();
|
|
18046
18694
|
const { listSessions: listSessions2, loadCalibrationCurve: loadCalibrationCurve2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
|
|
18047
|
-
const { toLocalDay: toLocalDay4
|
|
18695
|
+
const { toLocalDay: toLocalDay4 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
|
|
18048
18696
|
const today = toLocalDay4(Date.now());
|
|
18049
18697
|
let patches = {};
|
|
18050
18698
|
const persistConfig = (patch) => {
|
|
@@ -18231,7 +18879,7 @@ async function runTeamSync(log = noopLog2, configOverride, options = {}) {
|
|
|
18231
18879
|
} : void 0;
|
|
18232
18880
|
let artifactSignals = null;
|
|
18233
18881
|
try {
|
|
18234
|
-
const cwdAllowed = shouldSyncProject(
|
|
18882
|
+
const cwdAllowed = shouldSyncProject(projectKey(resolveProjectIdentity(process.cwd()).projectName), config.syncProjects);
|
|
18235
18883
|
artifactSignals = probeArtifactSignals2({ day: rollup.day, extraRoots: cwdAllowed ? [process.cwd()] : [] });
|
|
18236
18884
|
} catch {
|
|
18237
18885
|
}
|
|
@@ -18429,6 +19077,7 @@ var init_sync = __esm({
|
|
|
18429
19077
|
init_last_push();
|
|
18430
19078
|
init_commands();
|
|
18431
19079
|
init_profile();
|
|
19080
|
+
init_dist();
|
|
18432
19081
|
init_fs();
|
|
18433
19082
|
inFlightCommands = /* @__PURE__ */ new Set();
|
|
18434
19083
|
USAGE_LOG4 = cclensPath("usage.jsonl");
|
|
@@ -18443,10 +19092,10 @@ var daemon_log_exports = {};
|
|
|
18443
19092
|
__export(daemon_log_exports, {
|
|
18444
19093
|
appendDaemonLogLine: () => appendDaemonLogLine
|
|
18445
19094
|
});
|
|
18446
|
-
import { appendFileSync as
|
|
19095
|
+
import { appendFileSync as appendFileSync6 } from "node:fs";
|
|
18447
19096
|
function appendDaemonLogLine(level, msg) {
|
|
18448
19097
|
try {
|
|
18449
|
-
|
|
19098
|
+
appendFileSync6(
|
|
18450
19099
|
cclensPath("daemon.log"),
|
|
18451
19100
|
`${(/* @__PURE__ */ new Date()).toISOString()} ${level.toUpperCase()} ${msg}
|
|
18452
19101
|
`,
|
|
@@ -18659,11 +19308,11 @@ var logs_exports = {};
|
|
|
18659
19308
|
__export(logs_exports, {
|
|
18660
19309
|
teamLogs: () => teamLogs
|
|
18661
19310
|
});
|
|
18662
|
-
import { readFileSync as
|
|
19311
|
+
import { readFileSync as readFileSync22 } from "node:fs";
|
|
18663
19312
|
async function teamLogs() {
|
|
18664
19313
|
const logPath = cclensPath("daemon.log");
|
|
18665
19314
|
try {
|
|
18666
|
-
const lines =
|
|
19315
|
+
const lines = readFileSync22(logPath, "utf8").trim().split("\n");
|
|
18667
19316
|
const teamLines = lines.filter((l) => l.includes("[sync] ") || l.includes("team "));
|
|
18668
19317
|
if (teamLines.length === 0) {
|
|
18669
19318
|
console.log("No team-related log entries found.");
|
|
@@ -18791,8 +19440,8 @@ __export(runs_exports, {
|
|
|
18791
19440
|
runs: () => runs
|
|
18792
19441
|
});
|
|
18793
19442
|
import { execSync as execSync2 } from "node:child_process";
|
|
18794
|
-
import { existsSync as
|
|
18795
|
-
import { join as
|
|
19443
|
+
import { existsSync as existsSync20, readFileSync as readFileSync23, readdirSync as readdirSync6, statSync as statSync8 } from "node:fs";
|
|
19444
|
+
import { join as join16 } from "node:path";
|
|
18796
19445
|
async function runs(args2) {
|
|
18797
19446
|
const json = args2.includes("--json");
|
|
18798
19447
|
const watch = args2.includes("--watch");
|
|
@@ -18876,8 +19525,8 @@ function listActiveRuns() {
|
|
|
18876
19525
|
return runs2.sort((a, b) => a.elapsed_s - b.elapsed_s);
|
|
18877
19526
|
}
|
|
18878
19527
|
function readSpend(sinceMs) {
|
|
18879
|
-
if (!
|
|
18880
|
-
const lines =
|
|
19528
|
+
if (!existsSync20(SPEND_PATH)) return [];
|
|
19529
|
+
const lines = readFileSync23(SPEND_PATH, "utf-8").split("\n").filter((l) => l.trim());
|
|
18881
19530
|
const out = [];
|
|
18882
19531
|
for (const line of lines) {
|
|
18883
19532
|
try {
|
|
@@ -18998,23 +19647,23 @@ function ageLabel(ms) {
|
|
|
18998
19647
|
return `${Math.floor(ms / 864e5)}d`;
|
|
18999
19648
|
}
|
|
19000
19649
|
function listTraceFiles() {
|
|
19001
|
-
if (!
|
|
19002
|
-
const entries2 =
|
|
19650
|
+
if (!existsSync20(RUNS_DIR2)) return [];
|
|
19651
|
+
const entries2 = readdirSync6(RUNS_DIR2).filter((f) => f.endsWith(".jsonl"));
|
|
19003
19652
|
return entries2.map((f) => {
|
|
19004
|
-
const path7 =
|
|
19005
|
-
const st =
|
|
19653
|
+
const path7 = join16(RUNS_DIR2, f);
|
|
19654
|
+
const st = statSync8(path7);
|
|
19006
19655
|
return { runId: f.replace(/\.jsonl$/, ""), path: path7, mtimeMs: st.mtimeMs };
|
|
19007
19656
|
}).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
19008
19657
|
}
|
|
19009
19658
|
function resolveRunId(arg) {
|
|
19010
|
-
if (!
|
|
19659
|
+
if (!existsSync20(RUNS_DIR2)) return null;
|
|
19011
19660
|
if (arg === "latest") {
|
|
19012
19661
|
const all2 = listTraceFiles();
|
|
19013
19662
|
if (all2.length === 0) return null;
|
|
19014
19663
|
return { runId: all2[0].runId, path: all2[0].path };
|
|
19015
19664
|
}
|
|
19016
|
-
const exact =
|
|
19017
|
-
if (
|
|
19665
|
+
const exact = join16(RUNS_DIR2, `${arg}.jsonl`);
|
|
19666
|
+
if (existsSync20(exact)) return { runId: arg, path: exact };
|
|
19018
19667
|
const all = listTraceFiles();
|
|
19019
19668
|
const matches = all.filter((r) => r.runId.includes(arg));
|
|
19020
19669
|
if (matches.length === 1) return { runId: matches[0].runId, path: matches[0].path };
|
|
@@ -19026,7 +19675,7 @@ function resolveRunId(arg) {
|
|
|
19026
19675
|
return null;
|
|
19027
19676
|
}
|
|
19028
19677
|
function readTrace(path7) {
|
|
19029
|
-
return
|
|
19678
|
+
return readFileSync23(path7, "utf-8").split("\n").filter((l) => l.trim()).map((l) => {
|
|
19030
19679
|
try {
|
|
19031
19680
|
return JSON.parse(l);
|
|
19032
19681
|
} catch {
|
|
@@ -19038,7 +19687,7 @@ async function inspect(arg, follow, json) {
|
|
|
19038
19687
|
const r = resolveRunId(arg);
|
|
19039
19688
|
if (!r) {
|
|
19040
19689
|
console.error(`run not found: ${arg}`);
|
|
19041
|
-
if (
|
|
19690
|
+
if (existsSync20(RUNS_DIR2)) {
|
|
19042
19691
|
const all = listTraceFiles().slice(0, 5);
|
|
19043
19692
|
if (all.length > 0) {
|
|
19044
19693
|
console.error(`
|
|
@@ -19058,13 +19707,13 @@ recent runs:`);
|
|
|
19058
19707
|
const events = readTrace(r.path);
|
|
19059
19708
|
printTrace(r.runId, events);
|
|
19060
19709
|
if (!follow) return;
|
|
19061
|
-
let lastSize =
|
|
19710
|
+
let lastSize = statSync8(r.path).size;
|
|
19062
19711
|
let lastIdx = events.length;
|
|
19063
19712
|
console.log("\n \u27F6 following \xB7 ^C to quit\n");
|
|
19064
19713
|
process.on("SIGINT", () => process.exit(0));
|
|
19065
19714
|
while (true) {
|
|
19066
19715
|
await new Promise((res) => setTimeout(res, 500));
|
|
19067
|
-
const st =
|
|
19716
|
+
const st = statSync8(r.path);
|
|
19068
19717
|
if (st.size === lastSize) continue;
|
|
19069
19718
|
lastSize = st.size;
|
|
19070
19719
|
const all = readTrace(r.path);
|
|
@@ -19200,6 +19849,11 @@ async function main() {
|
|
|
19200
19849
|
await autostart2(args.slice(1));
|
|
19201
19850
|
break;
|
|
19202
19851
|
}
|
|
19852
|
+
case "menubar": {
|
|
19853
|
+
const { menubar: menubar2 } = await Promise.resolve().then(() => (init_menubar(), menubar_exports));
|
|
19854
|
+
await menubar2(args.slice(1));
|
|
19855
|
+
break;
|
|
19856
|
+
}
|
|
19203
19857
|
case "team": {
|
|
19204
19858
|
const { team: team2 } = await Promise.resolve().then(() => (init_team2(), team_exports));
|
|
19205
19859
|
await team2(args.slice(1));
|
|
@@ -19213,7 +19867,7 @@ async function main() {
|
|
|
19213
19867
|
case "version":
|
|
19214
19868
|
case "--version":
|
|
19215
19869
|
case "-v":
|
|
19216
|
-
console.log(`fleetlens ${"0.15.
|
|
19870
|
+
console.log(`fleetlens ${"0.15.4"}`);
|
|
19217
19871
|
break;
|
|
19218
19872
|
case "help":
|
|
19219
19873
|
case "--help":
|
|
@@ -19240,6 +19894,7 @@ Advanced:
|
|
|
19240
19894
|
start --no-daemon Start only the web server (no daemon)
|
|
19241
19895
|
daemon <start|stop|status|logs> Manage the usage daemon by itself
|
|
19242
19896
|
autostart <install|uninstall|status> Run the usage daemon at login (macOS launchd)
|
|
19897
|
+
menubar <install|uninstall|open|status> Native macOS menu bar widget (Claude/Codex/Z.ai usage)
|
|
19243
19898
|
|
|
19244
19899
|
Team:
|
|
19245
19900
|
team join <url> <token> Pair with a team server (browser setup)
|