@askexenow/exe-os 0.9.270 → 0.9.272

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.
Files changed (311) hide show
  1. package/dist/active-agent-BDYXURXQ.js +26 -0
  2. package/dist/active-agent-YWBGAKGU.js +25 -0
  3. package/dist/agentic-ontology-56VHSVS3.js +25 -0
  4. package/dist/backfill-metadata-G46ABBVR.js +597 -0
  5. package/dist/backfill-metadata-VAV27KJK.js +597 -0
  6. package/dist/behaviors-USUTDXVA.js +25 -0
  7. package/dist/bin/agentic-ontology-backfill.js +5 -5
  8. package/dist/bin/agentic-reflection-backfill.js +6 -6
  9. package/dist/bin/agentic-semantic-label.js +5 -5
  10. package/dist/bin/backfill-conversations.js +4 -4
  11. package/dist/bin/backfill-responses.js +4 -4
  12. package/dist/bin/backfill-vectors.js +5 -5
  13. package/dist/bin/bulk-sync-postgres.js +6 -6
  14. package/dist/bin/cc-doctor.js +4 -4
  15. package/dist/bin/cleanup-stale-review-tasks.js +10 -10
  16. package/dist/bin/cli.js +16 -16
  17. package/dist/bin/exe-agent-config.js +3 -3
  18. package/dist/bin/exe-agent.js +4 -4
  19. package/dist/bin/exe-assign.js +5 -5
  20. package/dist/bin/exe-boot.js +17 -17
  21. package/dist/bin/exe-call.js +4 -4
  22. package/dist/bin/exe-cloud.js +4 -4
  23. package/dist/bin/exe-dispatch.js +10 -10
  24. package/dist/bin/exe-doctor.js +1 -1
  25. package/dist/bin/exe-export-behaviors.js +7 -7
  26. package/dist/bin/exe-forget.js +6 -6
  27. package/dist/bin/exe-gateway.js +7 -7
  28. package/dist/bin/exe-healthcheck.js +4 -4
  29. package/dist/bin/exe-heartbeat.js +10 -10
  30. package/dist/bin/exe-kill.js +13 -13
  31. package/dist/bin/exe-launch-agent.js +37 -19
  32. package/dist/bin/exe-new-employee.js +6 -6
  33. package/dist/bin/exe-pending-messages.js +11 -11
  34. package/dist/bin/exe-pending-notifications.js +10 -10
  35. package/dist/bin/exe-pending-reviews.js +10 -10
  36. package/dist/bin/exe-rename.js +4 -4
  37. package/dist/bin/exe-review.js +12 -12
  38. package/dist/bin/exe-search.js +5 -5
  39. package/dist/bin/exe-session-cleanup.js +15 -15
  40. package/dist/bin/exe-settings.js +5 -5
  41. package/dist/bin/exe-start-codex.js +11 -11
  42. package/dist/bin/exe-start-opencode.js +8 -8
  43. package/dist/bin/exe-status.js +11 -11
  44. package/dist/bin/exe-team.js +3 -3
  45. package/dist/bin/git-sweep.js +11 -11
  46. package/dist/bin/graph-backfill.js +4 -4
  47. package/dist/bin/graph-export.js +5 -5
  48. package/dist/bin/import-history.js +7 -7
  49. package/dist/bin/install.js +6 -6
  50. package/dist/bin/intercom-check.js +4 -4
  51. package/dist/bin/mcp-sessions.js +2 -2
  52. package/dist/bin/orchestration-metrics.js +4 -4
  53. package/dist/bin/postgres-agentic-reflection-backfill.js +2 -2
  54. package/dist/bin/postgres-agentic-semantic-backfill.js +1 -1
  55. package/dist/bin/scan-tasks.js +10 -10
  56. package/dist/bin/setup.js +1 -1
  57. package/dist/bin/shard-migrate.js +4 -4
  58. package/dist/bin/stack-update.js +10 -3
  59. package/dist/bin/vps-health-gate.js +1 -1
  60. package/dist/capacity-monitor-IFVRCIM7.js +49 -0
  61. package/dist/capacity-monitor-Q47GBDSY.js +49 -0
  62. package/dist/catchup-brief-RP4QHXNT.js +151 -0
  63. package/dist/catchup-brief-TKA6TEK4.js +151 -0
  64. package/dist/chunk-23KJ2LXY.js +58 -0
  65. package/dist/chunk-2NQQP3FF.js +630 -0
  66. package/dist/chunk-3FU5I3KV.js +526 -0
  67. package/dist/chunk-46IEEKPU.js +13696 -0
  68. package/dist/chunk-57UAFTO2.js +3958 -0
  69. package/dist/chunk-5AS622MM.js +3958 -0
  70. package/dist/chunk-62DEE65H.js +371 -0
  71. package/dist/chunk-64T6DFSS.js +447 -0
  72. package/dist/chunk-6BWDP63Z.js +197 -0
  73. package/dist/chunk-6GPYL7TX.js +214 -0
  74. package/dist/chunk-6KWLUVFL.js +54 -0
  75. package/dist/chunk-6N5ISWBF.js +1148 -0
  76. package/dist/chunk-6OD7PVMC.js +333 -0
  77. package/dist/chunk-7ET5CYTD.js +382 -0
  78. package/dist/chunk-7IWLKR6N.js +76 -0
  79. package/dist/chunk-7OEUOJL5.js +1021 -0
  80. package/dist/chunk-AIRJTKDK.js +204 -0
  81. package/dist/chunk-ATJ3NXDP.js +244 -0
  82. package/dist/chunk-B5IS7LE4.js +128 -0
  83. package/dist/chunk-BKINEQVI.js +244 -0
  84. package/dist/chunk-BOJV6NI3.js +128 -0
  85. package/dist/chunk-BPHWI6N2.js +284 -0
  86. package/dist/chunk-BXCQWWJP.js +185 -0
  87. package/dist/chunk-BZ6K7AY3.js +50 -0
  88. package/dist/chunk-C54KIFLS.js +214 -0
  89. package/dist/chunk-C6OYEJJI.js +260 -0
  90. package/dist/chunk-CHBHR5W6.js +3556 -0
  91. package/dist/chunk-D2T3272U.js +171 -0
  92. package/dist/chunk-DCHEIVGT.js +221 -0
  93. package/dist/chunk-DHIBLMSP.js +30 -0
  94. package/dist/chunk-E2AF2WYY.js +346 -0
  95. package/dist/chunk-E2KZEZZW.js +1090 -0
  96. package/dist/chunk-E4KWB4WM.js +348 -0
  97. package/dist/chunk-ENU7URWK.js +1073 -0
  98. package/dist/chunk-EZ7KAZMC.js +132 -0
  99. package/dist/chunk-F4FSSHR4.js +1073 -0
  100. package/dist/chunk-FPXU56FG.js +346 -0
  101. package/dist/chunk-FY7HHR5I.js +128 -0
  102. package/dist/chunk-G2S2UMU4.js +159 -0
  103. package/dist/chunk-G33BHQCO.js +70 -0
  104. package/dist/chunk-GJQTL7RX.js +127 -0
  105. package/dist/chunk-GLCKDEM2.js +97 -0
  106. package/dist/chunk-GMA34SXV.js +240 -0
  107. package/dist/chunk-GVAVEBYR.js +2091 -0
  108. package/dist/chunk-HOSJTLBQ.js +513 -0
  109. package/dist/chunk-IBMTSEZC.js +230 -0
  110. package/dist/chunk-IC6HVAS3.js +56 -0
  111. package/dist/chunk-IDFJNO44.js +1051 -0
  112. package/dist/chunk-ILFJMEY5.js +97 -0
  113. package/dist/chunk-ISQAOSL3.js +1921 -0
  114. package/dist/chunk-J6V2DCZK.js +382 -0
  115. package/dist/chunk-JP4CLFLR.js +1148 -0
  116. package/dist/chunk-JTIOZHWG.js +58 -0
  117. package/dist/chunk-KDICWAYV.js +1345 -0
  118. package/dist/chunk-KOBIB6WG.js +159 -0
  119. package/dist/chunk-KQFDDQB6.js +13696 -0
  120. package/dist/chunk-KZNSOHCB.js +280 -0
  121. package/dist/chunk-LVMBYP3C.js +171 -0
  122. package/dist/chunk-M2WQW5NC.js +227 -0
  123. package/dist/chunk-MY6SP5NZ.js +551 -0
  124. package/dist/chunk-N2ACW2ZG.js +363 -0
  125. package/dist/chunk-NSMJDATI.js +495 -0
  126. package/dist/chunk-NSQ5JE23.js +1090 -0
  127. package/dist/chunk-NZL567WG.js +81 -0
  128. package/dist/chunk-O5OMH6LI.js +244 -0
  129. package/dist/chunk-O7YO7E2G.js +1512 -0
  130. package/dist/chunk-OBUV3W7L.js +163 -0
  131. package/dist/chunk-OLDS7LJN.js +495 -0
  132. package/dist/chunk-OO2I22RX.js +38 -0
  133. package/dist/chunk-OPUUT33V.js +447 -0
  134. package/dist/chunk-OT3VMTKB.js +50 -0
  135. package/dist/chunk-P6RVIOVA.js +157 -0
  136. package/dist/chunk-PUA5564C.js +210 -0
  137. package/dist/chunk-PUQLKLQX.js +731 -0
  138. package/dist/chunk-QROKS65G.js +76 -0
  139. package/dist/chunk-R54I2N2T.js +818 -0
  140. package/dist/chunk-RCFYQHUP.js +818 -0
  141. package/dist/chunk-RJTND4YS.js +284 -0
  142. package/dist/chunk-SBLHQMMZ.js +81 -0
  143. package/dist/chunk-SG2ANG5C.js +123 -0
  144. package/dist/chunk-SVFNKSZV.js +333 -0
  145. package/dist/chunk-TAQT2DC7.js +330 -0
  146. package/dist/chunk-TB7HFW7M.js +127 -0
  147. package/dist/chunk-UUKDAIH2.js +731 -0
  148. package/dist/chunk-V6VEFEEH.js +1345 -0
  149. package/dist/chunk-VIO2ALGH.js +290 -0
  150. package/dist/chunk-VKCUSNJW.js +377 -0
  151. package/dist/chunk-VRPPJFIQ.js +1921 -0
  152. package/dist/chunk-WP3PVBBP.js +204 -0
  153. package/dist/chunk-WQEUY7DC.js +129 -0
  154. package/dist/chunk-WXMXUKCA.js +262 -0
  155. package/dist/chunk-X2WBH2IO.js +297 -0
  156. package/dist/chunk-X33TSJNO.js +394 -0
  157. package/dist/chunk-X7MMI2UI.js +89 -0
  158. package/dist/chunk-XG3BQZIK.js +85 -0
  159. package/dist/chunk-XIKBIAOS.js +75 -0
  160. package/dist/chunk-XPEB545Q.js +54 -0
  161. package/dist/chunk-XWH2MLWS.js +330 -0
  162. package/dist/chunk-YH7V73XW.js +89 -0
  163. package/dist/chunk-YMLM5D65.js +135 -0
  164. package/dist/chunk-YNJPRQ6J.js +377 -0
  165. package/dist/chunk-YSNEHBI6.js +551 -0
  166. package/dist/chunk-ZD6BMW2K.js +33 -0
  167. package/dist/chunk-ZKG5IYCG.js +668 -0
  168. package/dist/chunk-ZU4K7ZNX.js +197 -0
  169. package/dist/co-activation-HZMJC34P.js +72 -0
  170. package/dist/co-occurrence-AVYXRV4L.js +74 -0
  171. package/dist/core-memory-NPJCVUMF.js +110 -0
  172. package/dist/core-memory-OKGXL33Z.js +110 -0
  173. package/dist/crdt-sync-ZCH55JNR.js +33 -0
  174. package/dist/crm-webhook-6OMVUUGR.js +10 -0
  175. package/dist/crm-webhook-UCWF3XDB.js +10 -0
  176. package/dist/cto-delegation-gate-JFZFZGC2.js +206 -0
  177. package/dist/cto-delegation-gate-K32M4GVM.js +206 -0
  178. package/dist/daemon-orchestration-2Q7BYOHC.js +135 -0
  179. package/dist/daemon-orchestration-4RJ2CZJL.js +135 -0
  180. package/dist/db-backup-5GA2YFDX.js +33 -0
  181. package/dist/dreaming-I6KXO6E2.js +32 -0
  182. package/dist/dreaming-NJBK5ILR.js +32 -0
  183. package/dist/exe-drift-VSMIMHL4.js +68 -0
  184. package/dist/exe-export-DVHHIA6Y.js +73 -0
  185. package/dist/exe-export-GIVQDENS.js +73 -0
  186. package/dist/exe-import-7N46LSMQ.js +76 -0
  187. package/dist/exe-import-FINYUV5T.js +76 -0
  188. package/dist/exe-key-H45JY44F.js +579 -0
  189. package/dist/exe-key-MAEQGTB7.js +579 -0
  190. package/dist/exe-snapshot-3TEM3BFD.js +164 -0
  191. package/dist/exe-snapshot-HECGUHL3.js +164 -0
  192. package/dist/fast-db-init-3CNTADVO.js +7 -0
  193. package/dist/fast-db-init-HXCS2AP5.js +7 -0
  194. package/dist/gateway/index.js +8 -8
  195. package/dist/git-staleness-YCEBBIVK.js +110 -0
  196. package/dist/git-task-sweep-H34STRNT.js +40 -0
  197. package/dist/git-task-sweep-YL7NLDCK.js +40 -0
  198. package/dist/global-procedures-IHZM6C2K.js +20 -0
  199. package/dist/graph-auto-extract-RZQ3MHP2.js +162 -0
  200. package/dist/hooks/bug-report-worker.js +12 -12
  201. package/dist/hooks/codex-stop-task-finalizer.js +12 -12
  202. package/dist/hooks/commit-complete.js +12 -12
  203. package/dist/hooks/error-recall.js +6 -6
  204. package/dist/hooks/exe-heartbeat-hook.js +3 -3
  205. package/dist/hooks/ingest.js +6 -6
  206. package/dist/hooks/instructions-loaded.js +4 -4
  207. package/dist/hooks/manifest.json +19 -19
  208. package/dist/hooks/notification.js +4 -4
  209. package/dist/hooks/post-compact.js +11 -11
  210. package/dist/hooks/post-tool-combined.js +5 -5
  211. package/dist/hooks/pre-compact.js +12 -12
  212. package/dist/hooks/pre-tool-use.js +15 -15
  213. package/dist/hooks/prompt-submit.js +21 -21
  214. package/dist/hooks/session-end.js +16 -16
  215. package/dist/hooks/session-start.js +10 -10
  216. package/dist/hooks/stop.js +15 -15
  217. package/dist/hooks/subagent-stop.js +11 -11
  218. package/dist/hooks/summary-worker.js +15 -15
  219. package/dist/index.js +18 -18
  220. package/dist/installer-4EW5ZDGD.js +296 -0
  221. package/dist/installer-B2JTQO55.js +38 -0
  222. package/dist/installer-MIL352T7.js +342 -0
  223. package/dist/lib/agent-config.js +9 -3
  224. package/dist/lib/cloud-sync.js +4 -4
  225. package/dist/lib/consolidation.js +5 -5
  226. package/dist/lib/database.js +2 -2
  227. package/dist/lib/db.js +2 -2
  228. package/dist/lib/employee-templates.js +4 -4
  229. package/dist/lib/employees.js +2 -2
  230. package/dist/lib/exe-daemon.js +34 -34
  231. package/dist/lib/hybrid-search.js +5 -5
  232. package/dist/lib/identity.js +2 -2
  233. package/dist/lib/messaging.js +10 -10
  234. package/dist/lib/reminders.js +3 -3
  235. package/dist/lib/schedules.js +5 -5
  236. package/dist/lib/session-registry.js +4 -4
  237. package/dist/lib/skill-learning.js +4 -4
  238. package/dist/lib/store.js +4 -4
  239. package/dist/lib/task-router.js +3 -3
  240. package/dist/lib/tasks.js +11 -11
  241. package/dist/lib/tmux-routing.js +9 -9
  242. package/dist/lib/token-spend.js +3 -3
  243. package/dist/mcp/register-tools.js +54 -54
  244. package/dist/mcp/server.js +55 -55
  245. package/dist/mcp/tools/complete-reminder.js +4 -4
  246. package/dist/mcp/tools/create-reminder.js +4 -4
  247. package/dist/mcp/tools/create-task.js +13 -13
  248. package/dist/mcp/tools/deactivate-behavior.js +5 -5
  249. package/dist/mcp/tools/list-reminders.js +4 -4
  250. package/dist/mcp/tools/list-tasks.js +13 -13
  251. package/dist/mcp/tools/send-message.js +12 -12
  252. package/dist/mcp/tools/update-task.js +12 -12
  253. package/dist/mcp-http-config-OJQR246S.js +27 -0
  254. package/dist/memory-cards-IPULSQFA.js +174 -0
  255. package/dist/memory-graph-extractor-3TZZOKHY.js +17 -0
  256. package/dist/memory-poisoning-defense-SGUGR5YJ.js +225 -0
  257. package/dist/memory-reflection-H3WGCEM6.js +238 -0
  258. package/dist/notifications-VWPO6NJF.js +45 -0
  259. package/dist/notifications-WCSRQN2V.js +45 -0
  260. package/dist/orchestration-events-O5PSDEIO.js +25 -0
  261. package/dist/orchestrator-RAPEJUOI.js +33 -0
  262. package/dist/orchestrator-XPG6LJAI.js +33 -0
  263. package/dist/pipeline-router-5NT6FUC3.js +13 -0
  264. package/dist/pipeline-router-KSUXONDT.js +13 -0
  265. package/dist/plan-limits-53NXLNDQ.js +26 -0
  266. package/dist/project-boot-ITN3FZMM.js +299 -0
  267. package/dist/projection-worker-27XX5M2W.js +964 -0
  268. package/dist/reranker-GU7L2PJX.js +19 -0
  269. package/dist/reranker-TZEXIJAN.js +19 -0
  270. package/dist/review-polling-FA2J2Q5O.js +124 -0
  271. package/dist/review-polling-MLS4BQ3N.js +124 -0
  272. package/dist/runtime/index.js +12 -12
  273. package/dist/session-events-WWGF3B2N.js +36 -0
  274. package/dist/session-events-ZHXXAH6B.js +36 -0
  275. package/dist/session-kill-telemetry-O4TJHHOZ.js +29 -0
  276. package/dist/session-scope-CQXB7VMH.js +86 -0
  277. package/dist/session-scope-HHUMJYF6.js +86 -0
  278. package/dist/setup-wizard-UM2RHSBJ.js +12 -0
  279. package/dist/skill-refinement-MJPOHYD5.js +157 -0
  280. package/dist/skill-refinement-NVUBRK22.js +157 -0
  281. package/dist/stack-release-2KSOYDIV.js +712 -0
  282. package/dist/stack-release-BAPCXMXW.js +713 -0
  283. package/dist/stack-release-W4TWTEZP.js +731 -0
  284. package/dist/stack-update-QQA64STQ.js +52 -0
  285. package/dist/steward-gate-VLE7OCKO.js +13 -0
  286. package/dist/task-enforcement-FUHDL6UR.js +391 -0
  287. package/dist/task-enforcement-QL3K4N3F.js +391 -0
  288. package/dist/task-scope-TZYMB634.js +35 -0
  289. package/dist/task-scope-ZVLUBS4C.js +35 -0
  290. package/dist/tasks-crud-4MSLJWXE.js +77 -0
  291. package/dist/tasks-crud-HIPXKRKX.js +77 -0
  292. package/dist/tasks-notify-7JBUNE7R.js +38 -0
  293. package/dist/tasks-notify-UPIJ3L4O.js +38 -0
  294. package/dist/tasks-review-5SJSFTUB.js +47 -0
  295. package/dist/tasks-review-JHSYBR5I.js +47 -0
  296. package/dist/telemetry-upload-BSGOXGUP.js +739 -0
  297. package/dist/telemetry-upload-LTX3C5HZ.js +739 -0
  298. package/dist/token-budget-2CDWQU3Q.js +84 -0
  299. package/dist/tool-telemetry-7YS7EN7B.js +17 -0
  300. package/dist/tui/App.js +17 -17
  301. package/dist/tui-data-GDGBOS6G.js +258 -0
  302. package/dist/tui-data-VXF2RBVM.js +258 -0
  303. package/dist/wiki-acl-MJIMXRQV.js +111 -0
  304. package/dist/worker-gate-WQGTZOSM.js +21 -0
  305. package/dist/worker-gate-X2YDTKTL.js +21 -0
  306. package/dist/workflow-engine-CYXRZXBM.js +28 -0
  307. package/dist/workflow-engine-KMLAXVA4.js +28 -0
  308. package/dist/worktree-NLSKVRNC.js +26 -0
  309. package/dist/worktree-sweep-44TMEPLE.js +19 -0
  310. package/package.json +1 -1
  311. package/release-notes.json +26 -40
@@ -0,0 +1,280 @@
1
+ import {
2
+ recordOrchestrationEventBestEffort
3
+ } from "./chunk-2NQQP3FF.js";
4
+
5
+ // src/lib/worktree.ts
6
+ import { execSync } from "child_process";
7
+ import { existsSync, readFileSync, appendFileSync, mkdirSync, realpathSync } from "fs";
8
+ import path from "path";
9
+ var GIT_TIMEOUT_MS = 1e4;
10
+ function getGitRoot(dir) {
11
+ try {
12
+ const root = execSync("git rev-parse --show-toplevel", {
13
+ cwd: dir,
14
+ encoding: "utf-8",
15
+ timeout: GIT_TIMEOUT_MS,
16
+ stdio: ["pipe", "pipe", "pipe"]
17
+ }).trim();
18
+ return realpath(root);
19
+ } catch {
20
+ return null;
21
+ }
22
+ }
23
+ function getMainRepoRoot(dir) {
24
+ try {
25
+ const commonDir = execSync(
26
+ "git rev-parse --path-format=absolute --git-common-dir",
27
+ { cwd: dir, encoding: "utf-8", timeout: GIT_TIMEOUT_MS, stdio: ["pipe", "pipe", "pipe"] }
28
+ ).trim();
29
+ return realpath(path.dirname(commonDir));
30
+ } catch {
31
+ return null;
32
+ }
33
+ }
34
+ function worktreePath(repoRoot, employeeName, instance) {
35
+ const label = instanceLabel(employeeName, instance);
36
+ return path.join(repoRoot, ".worktrees", label);
37
+ }
38
+ function worktreeBranch(employeeName, instance, taskSlug) {
39
+ const label = instanceLabel(employeeName, instance);
40
+ if (taskSlug) {
41
+ const slug = taskSlug.slice(0, 40).replace(/[^a-z0-9-]/gi, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").toLowerCase();
42
+ return `${label}-${slug}`;
43
+ }
44
+ return `${label}-work`;
45
+ }
46
+ function instanceLabel(name, instance) {
47
+ return instance != null && instance > 0 ? `${name}${instance}` : name;
48
+ }
49
+ function ensureWorktree(projectDir, employeeName, instance) {
50
+ const repoRoot = getGitRoot(projectDir);
51
+ if (!repoRoot) return null;
52
+ const wtPath = worktreePath(repoRoot, employeeName, instance);
53
+ const branch = worktreeBranch(employeeName, instance);
54
+ if (existsSync(path.join(wtPath, ".git"))) {
55
+ recordOrchestrationEventBestEffort({
56
+ eventType: "worktree.reused",
57
+ source: "worktree.ensureWorktree",
58
+ agentId: employeeName,
59
+ instanceId: instance != null ? String(instance) : null,
60
+ payload: { branch }
61
+ });
62
+ return wtPath;
63
+ }
64
+ const worktreesDir = path.join(repoRoot, ".worktrees");
65
+ mkdirSync(worktreesDir, { recursive: true });
66
+ ensureGitignoreEntry(repoRoot, "/.worktrees/");
67
+ try {
68
+ execSync("git worktree prune", {
69
+ cwd: repoRoot,
70
+ encoding: "utf-8",
71
+ timeout: GIT_TIMEOUT_MS,
72
+ stdio: ["pipe", "pipe", "pipe"]
73
+ });
74
+ } catch {
75
+ }
76
+ const branchExists = branchExistsLocally(repoRoot, branch);
77
+ try {
78
+ if (branchExists) {
79
+ execSync(`git worktree add "${wtPath}" "${branch}"`, {
80
+ cwd: repoRoot,
81
+ encoding: "utf-8",
82
+ timeout: GIT_TIMEOUT_MS,
83
+ stdio: ["pipe", "pipe", "pipe"]
84
+ });
85
+ } else {
86
+ execSync(`git worktree add "${wtPath}" -b "${branch}" HEAD`, {
87
+ cwd: repoRoot,
88
+ encoding: "utf-8",
89
+ timeout: GIT_TIMEOUT_MS,
90
+ stdio: ["pipe", "pipe", "pipe"]
91
+ });
92
+ }
93
+ recordOrchestrationEventBestEffort({
94
+ eventType: "worktree.created",
95
+ source: "worktree.ensureWorktree",
96
+ agentId: employeeName,
97
+ instanceId: instance != null ? String(instance) : null,
98
+ payload: { branch, reusedBranch: branchExists }
99
+ });
100
+ return wtPath;
101
+ } catch (err) {
102
+ recordOrchestrationEventBestEffort({
103
+ eventType: "worktree.failed",
104
+ source: "worktree.ensureWorktree",
105
+ severity: "warn",
106
+ agentId: employeeName,
107
+ instanceId: instance != null ? String(instance) : null,
108
+ errorCode: err instanceof Error ? err.name : "worktree_create_failed",
109
+ payload: { branch }
110
+ });
111
+ process.stderr.write(
112
+ `[worktree] Failed to create worktree for ${employeeName}: ${err instanceof Error ? err.message : String(err)}
113
+ `
114
+ );
115
+ return null;
116
+ }
117
+ }
118
+ function isWorktreeDirty(wtPath) {
119
+ try {
120
+ const status = execSync("git status --porcelain", {
121
+ cwd: wtPath,
122
+ encoding: "utf-8",
123
+ timeout: GIT_TIMEOUT_MS,
124
+ stdio: ["pipe", "pipe", "pipe"]
125
+ }).trim();
126
+ return status.length > 0;
127
+ } catch {
128
+ return true;
129
+ }
130
+ }
131
+ function cleanupWorktree(projectDir, employeeName, instance) {
132
+ const repoRoot = getMainRepoRoot(projectDir);
133
+ if (!repoRoot) return { cleaned: false, reason: "not a git repo" };
134
+ const wtPath = worktreePath(repoRoot, employeeName, instance);
135
+ const branch = worktreeBranch(employeeName, instance);
136
+ if (!existsSync(wtPath)) {
137
+ recordOrchestrationEventBestEffort({
138
+ eventType: "worktree.skipped",
139
+ source: "worktree.cleanupWorktree",
140
+ agentId: employeeName,
141
+ instanceId: instance != null ? String(instance) : null,
142
+ payload: { reason: "worktree does not exist", branch }
143
+ });
144
+ return { cleaned: false, reason: "worktree does not exist" };
145
+ }
146
+ if (isWorktreeDirty(wtPath)) {
147
+ recordOrchestrationEventBestEffort({
148
+ eventType: "worktree.skipped",
149
+ source: "worktree.cleanupWorktree",
150
+ agentId: employeeName,
151
+ instanceId: instance != null ? String(instance) : null,
152
+ payload: { reason: "worktree has uncommitted changes", branch }
153
+ });
154
+ return { cleaned: false, reason: "worktree has uncommitted changes" };
155
+ }
156
+ const mainBranch = detectMainBranch(repoRoot);
157
+ if (!mainBranch) {
158
+ recordOrchestrationEventBestEffort({
159
+ eventType: "worktree.skipped",
160
+ source: "worktree.cleanupWorktree",
161
+ agentId: employeeName,
162
+ instanceId: instance != null ? String(instance) : null,
163
+ payload: { reason: "could not determine main branch", branch }
164
+ });
165
+ return { cleaned: false, reason: "could not determine main branch" };
166
+ }
167
+ if (!isBranchMerged(repoRoot, branch, mainBranch)) {
168
+ recordOrchestrationEventBestEffort({
169
+ eventType: "worktree.skipped",
170
+ source: "worktree.cleanupWorktree",
171
+ agentId: employeeName,
172
+ instanceId: instance != null ? String(instance) : null,
173
+ payload: { reason: "branch not merged", branch, mainBranch }
174
+ });
175
+ return { cleaned: false, reason: `branch ${branch} not merged into ${mainBranch}` };
176
+ }
177
+ try {
178
+ execSync(`git worktree remove "${wtPath}"`, {
179
+ cwd: repoRoot,
180
+ encoding: "utf-8",
181
+ timeout: GIT_TIMEOUT_MS,
182
+ stdio: ["pipe", "pipe", "pipe"]
183
+ });
184
+ } catch (err) {
185
+ recordOrchestrationEventBestEffort({
186
+ eventType: "worktree.failed",
187
+ source: "worktree.cleanupWorktree",
188
+ severity: "warn",
189
+ agentId: employeeName,
190
+ instanceId: instance != null ? String(instance) : null,
191
+ errorCode: err instanceof Error ? err.name : "worktree_remove_failed",
192
+ payload: { branch, mainBranch }
193
+ });
194
+ return {
195
+ cleaned: false,
196
+ reason: `git worktree remove failed: ${err instanceof Error ? err.message : String(err)}`
197
+ };
198
+ }
199
+ try {
200
+ execSync(`git branch -d "${branch}"`, {
201
+ cwd: repoRoot,
202
+ encoding: "utf-8",
203
+ timeout: GIT_TIMEOUT_MS,
204
+ stdio: ["pipe", "pipe", "pipe"]
205
+ });
206
+ } catch {
207
+ }
208
+ recordOrchestrationEventBestEffort({
209
+ eventType: "worktree.pruned",
210
+ source: "worktree.cleanupWorktree",
211
+ agentId: employeeName,
212
+ instanceId: instance != null ? String(instance) : null,
213
+ payload: { branch, mainBranch }
214
+ });
215
+ return { cleaned: true, reason: `worktree and branch ${branch} removed (merged into ${mainBranch})` };
216
+ }
217
+ function branchExistsLocally(repoRoot, branch) {
218
+ try {
219
+ execSync(`git rev-parse --verify "refs/heads/${branch}"`, {
220
+ cwd: repoRoot,
221
+ encoding: "utf-8",
222
+ timeout: GIT_TIMEOUT_MS,
223
+ stdio: ["pipe", "pipe", "pipe"]
224
+ });
225
+ return true;
226
+ } catch {
227
+ return false;
228
+ }
229
+ }
230
+ function detectMainBranch(repoRoot) {
231
+ for (const candidate of ["main", "master"]) {
232
+ if (branchExistsLocally(repoRoot, candidate)) return candidate;
233
+ }
234
+ return null;
235
+ }
236
+ function isBranchMerged(repoRoot, branch, into) {
237
+ try {
238
+ const merged = execSync(`git branch --merged "${into}"`, {
239
+ cwd: repoRoot,
240
+ encoding: "utf-8",
241
+ timeout: GIT_TIMEOUT_MS,
242
+ stdio: ["pipe", "pipe", "pipe"]
243
+ });
244
+ return merged.split("\n").map((l) => l.replace(/^[*+]?\s+/, "").trim()).includes(branch);
245
+ } catch {
246
+ return false;
247
+ }
248
+ }
249
+ function realpath(p) {
250
+ try {
251
+ return realpathSync(p);
252
+ } catch {
253
+ return p;
254
+ }
255
+ }
256
+ function ensureGitignoreEntry(repoRoot, entry) {
257
+ try {
258
+ const gitignorePath = path.join(repoRoot, ".gitignore");
259
+ if (existsSync(gitignorePath)) {
260
+ const content = readFileSync(gitignorePath, "utf-8");
261
+ if (content.includes(entry)) return;
262
+ appendFileSync(gitignorePath, `
263
+ # Agent worktrees (exe-os)
264
+ ${entry}
265
+ `);
266
+ } else {
267
+ }
268
+ } catch {
269
+ }
270
+ }
271
+
272
+ export {
273
+ getGitRoot,
274
+ getMainRepoRoot,
275
+ worktreePath,
276
+ worktreeBranch,
277
+ ensureWorktree,
278
+ isWorktreeDirty,
279
+ cleanupWorktree
280
+ };
@@ -0,0 +1,171 @@
1
+ import {
2
+ writeMemoryViaDaemon
3
+ } from "./chunk-OSXQTCW5.js";
4
+
5
+ // src/lib/auto-checkpoint.ts
6
+ var FILE_RE = /(?:^|\s)([\w./-]+\.(?:ts|tsx|js|jsx|json|md|yml|yaml|sql|go|py|css|scss|html|sh))(?:\b|$)/g;
7
+ var DECISION_RE = /\b(decision:|decided:|we decided|founder directive|captured in .*architecture|source of truth)\b/i;
8
+ function asString(value, fallback = "") {
9
+ if (value == null) return fallback;
10
+ return String(value);
11
+ }
12
+ function compactLine(text, max = 220) {
13
+ return text.replace(/\s+/g, " ").trim().slice(0, max);
14
+ }
15
+ function topEntries(counts, limit) {
16
+ return [...counts.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, limit).map(([name, count]) => `${name}(${count})`);
17
+ }
18
+ function buildAutoCheckpoint(input) {
19
+ const maxSamples = input.maxSamples ?? 8;
20
+ const projectCounts = /* @__PURE__ */ new Map();
21
+ const toolCounts = /* @__PURE__ */ new Map();
22
+ const files = /* @__PURE__ */ new Set();
23
+ const errors = [];
24
+ const samples = [];
25
+ const decisionTexts = [];
26
+ for (const row of input.memories) {
27
+ const tool = asString(row.tool_name, "unknown");
28
+ const project = asString(row.project_name, input.projectName || "unknown");
29
+ const raw = asString(row.raw_text);
30
+ const hasError = row.has_error === 1 || row.has_error === true;
31
+ toolCounts.set(tool, (toolCounts.get(tool) ?? 0) + 1);
32
+ projectCounts.set(project, (projectCounts.get(project) ?? 0) + 1);
33
+ if (hasError && errors.length < 5) errors.push(compactLine(raw, 180));
34
+ if (samples.length < maxSamples && raw.length > 30) {
35
+ samples.push(`[${tool}] ${compactLine(raw)}`);
36
+ }
37
+ if (DECISION_RE.test(raw) && decisionTexts.length < 5) {
38
+ decisionTexts.push(`AUTO DECISION CANDIDATE [${input.agentId}]: ${compactLine(raw, 500)}`);
39
+ }
40
+ for (const match of raw.matchAll(FILE_RE)) {
41
+ if (match[1]) files.add(match[1]);
42
+ if (files.size >= 20) break;
43
+ }
44
+ }
45
+ const taskLines = (input.tasks ?? []).slice(0, 10).map((task) => {
46
+ const status = asString(task.status, "unknown");
47
+ const priority = asString(task.priority, "?").toUpperCase();
48
+ const title = asString(task.title, "untitled");
49
+ const taskFile = asString(task.task_file);
50
+ return `- [${status}/${priority}] ${title}${taskFile ? ` (${taskFile})` : ""}`;
51
+ });
52
+ const parts = [
53
+ `CONTEXT CHECKPOINT [auto:${input.reason}]`,
54
+ `Agent: ${input.agentId} (${input.agentRole})`,
55
+ `Session: ${input.sessionId}`,
56
+ `Project: ${input.projectName}`,
57
+ `Time: ${(/* @__PURE__ */ new Date()).toISOString()}`,
58
+ "",
59
+ "## Recent Activity",
60
+ `- Memories scanned: ${input.memories.length}`,
61
+ `- Projects: ${topEntries(projectCounts, 5).join(", ") || input.projectName}`,
62
+ `- Tools: ${topEntries(toolCounts, 8).join(", ") || "none"}`
63
+ ];
64
+ if (taskLines.length > 0) {
65
+ parts.push("", "## Open / Active Tasks", ...taskLines);
66
+ }
67
+ if (files.size > 0) {
68
+ parts.push("", "## Files Mentioned", ...[...files].slice(0, 20).map((f) => `- ${f}`));
69
+ }
70
+ if (samples.length > 0) {
71
+ parts.push("", "## Important Recent Traces", ...samples.map((s) => `- ${s}`));
72
+ }
73
+ if (errors.length > 0) {
74
+ parts.push("", "## Errors / Risks", ...errors.map((e) => `- ${e}`));
75
+ }
76
+ if (decisionTexts.length > 0) {
77
+ parts.push("", "## Decision Candidates", ...decisionTexts.map((d) => `- ${d.replace(/^AUTO DECISION CANDIDATE \\[[^\\]]+\\]: /, "")}`));
78
+ }
79
+ return {
80
+ checkpointText: parts.join("\n"),
81
+ decisionTexts
82
+ };
83
+ }
84
+
85
+ // src/lib/checkpoint-orchestrator.ts
86
+ function toolNameForReason(reason) {
87
+ switch (reason) {
88
+ case "periodic":
89
+ return "auto-summary";
90
+ case "session-end":
91
+ return "SessionEnd";
92
+ case "pre-compact":
93
+ return "pre-compact-hook";
94
+ case "capacity-signal":
95
+ return "auto-checkpoint";
96
+ }
97
+ }
98
+ function importanceForReason(reason, override) {
99
+ if (override !== void 0) return override;
100
+ switch (reason) {
101
+ case "periodic":
102
+ return 7;
103
+ case "session-end":
104
+ case "pre-compact":
105
+ case "capacity-signal":
106
+ return 8;
107
+ }
108
+ }
109
+ function buildContinuityCheckpoint(input) {
110
+ const { checkpointText, decisionTexts } = buildAutoCheckpoint({
111
+ agentId: input.agentId,
112
+ agentRole: input.agentRole,
113
+ sessionId: input.sessionId,
114
+ projectName: input.projectName,
115
+ reason: input.reason,
116
+ memories: input.memories ?? [],
117
+ tasks: input.tasks ?? [],
118
+ maxSamples: input.maxSamples
119
+ });
120
+ const extra = input.extraSections?.filter((section) => section.trim().length > 0) ?? [];
121
+ return {
122
+ checkpointText: extra.length > 0 ? `${checkpointText}
123
+
124
+ ${extra.join("\n\n")}` : checkpointText,
125
+ decisionTexts
126
+ };
127
+ }
128
+ async function writeContinuityCheckpoint(input) {
129
+ const result = buildContinuityCheckpoint(input);
130
+ const now = (/* @__PURE__ */ new Date()).toISOString();
131
+ await writeMemoryViaDaemon({
132
+ raw_text: result.checkpointText,
133
+ agent_id: input.agentId,
134
+ agent_role: input.agentRole,
135
+ session_id: input.sessionId,
136
+ tool_name: toolNameForReason(input.reason),
137
+ project_name: input.projectName,
138
+ timestamp: now,
139
+ importance: importanceForReason(input.reason, input.importance),
140
+ task_id: input.taskId,
141
+ memory_type: "checkpoint"
142
+ });
143
+ const decisionLimit = input.reason === "periodic" ? 3 : 5;
144
+ for (const decisionText of result.decisionTexts.slice(0, decisionLimit)) {
145
+ await writeMemoryViaDaemon({
146
+ raw_text: decisionText,
147
+ agent_id: input.agentId,
148
+ agent_role: input.agentRole,
149
+ session_id: input.sessionId,
150
+ tool_name: "auto-decision",
151
+ project_name: input.projectName,
152
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
153
+ importance: 8,
154
+ memory_type: "decision"
155
+ });
156
+ }
157
+ return result;
158
+ }
159
+ async function checkpointActiveTask(input) {
160
+ const { writeCheckpoint } = await import("./lib/tasks.js");
161
+ await writeCheckpoint({
162
+ taskId: input.taskId,
163
+ step: input.step ?? "pre-compaction-checkpoint",
164
+ contextSummary: `Auto-checkpoint before context compaction. Task: ${input.taskTitle}. Session: ${input.sessionId}. Project: ${input.projectName}.`
165
+ });
166
+ }
167
+
168
+ export {
169
+ writeContinuityCheckpoint,
170
+ checkpointActiveTask
171
+ };
@@ -0,0 +1,227 @@
1
+ import {
2
+ getClient
3
+ } from "./chunk-CHBHR5W6.js";
4
+
5
+ // src/lib/token-spend.ts
6
+ import { readdir, stat } from "fs/promises";
7
+ import { createReadStream } from "fs";
8
+ import { createInterface } from "readline";
9
+ import path from "path";
10
+ import os from "os";
11
+ var MODEL_PRICING = {
12
+ // Opus 4.5+ ($5/$25 — Anthropic price drop from original Opus 4)
13
+ "claude-opus-4-7": { input: 5 / 1e6, output: 25 / 1e6, cacheRead: 0.5 / 1e6, cacheWrite: 6.25 / 1e6 },
14
+ "claude-opus-4-6": { input: 5 / 1e6, output: 25 / 1e6, cacheRead: 0.5 / 1e6, cacheWrite: 6.25 / 1e6 },
15
+ "claude-opus-4-5": { input: 5 / 1e6, output: 25 / 1e6, cacheRead: 0.5 / 1e6, cacheWrite: 6.25 / 1e6 },
16
+ // Opus 4.0/4.1 (legacy $15/$75)
17
+ "claude-opus-4-1": { input: 15 / 1e6, output: 75 / 1e6, cacheRead: 1.5 / 1e6, cacheWrite: 18.75 / 1e6 },
18
+ "claude-opus-4": { input: 15 / 1e6, output: 75 / 1e6, cacheRead: 1.5 / 1e6, cacheWrite: 18.75 / 1e6 },
19
+ // Sonnet 4.x
20
+ "claude-sonnet-4": { input: 3 / 1e6, output: 15 / 1e6, cacheRead: 0.3 / 1e6, cacheWrite: 3.75 / 1e6 },
21
+ // Sonnet 3.7/3.5
22
+ "claude-3-7-sonnet": { input: 3 / 1e6, output: 15 / 1e6, cacheRead: 0.3 / 1e6, cacheWrite: 3.75 / 1e6 },
23
+ "claude-3-5-sonnet": { input: 3 / 1e6, output: 15 / 1e6, cacheRead: 0.3 / 1e6, cacheWrite: 3.75 / 1e6 },
24
+ // Haiku 4.5
25
+ "claude-haiku-4-5": { input: 1 / 1e6, output: 5 / 1e6, cacheRead: 0.1 / 1e6, cacheWrite: 1.25 / 1e6 },
26
+ // Haiku 3.5
27
+ "claude-3-5-haiku": { input: 0.8 / 1e6, output: 4 / 1e6, cacheRead: 0.08 / 1e6, cacheWrite: 1 / 1e6 },
28
+ // Opus 3
29
+ "claude-3-opus": { input: 15 / 1e6, output: 75 / 1e6, cacheRead: 1.5 / 1e6, cacheWrite: 18.75 / 1e6 },
30
+ // Sonnet 3
31
+ "claude-3-sonnet": { input: 3 / 1e6, output: 15 / 1e6, cacheRead: 0.3 / 1e6, cacheWrite: 3.75 / 1e6 },
32
+ // Haiku 3
33
+ "claude-3-haiku": { input: 0.25 / 1e6, output: 1.25 / 1e6, cacheRead: 0.03 / 1e6, cacheWrite: 0.3 / 1e6 }
34
+ };
35
+ var DEFAULT_PRICING = MODEL_PRICING["claude-sonnet-4"];
36
+ var CACHE_TTL_MS = 5 * 60 * 1e3;
37
+ var JSONL_INDEX_TTL_MS = 5 * 60 * 1e3;
38
+ var USAGE_CACHE_MAX_ENTRIES = 1e4;
39
+ var _spendCache = /* @__PURE__ */ new Map();
40
+ var _spendInFlight = /* @__PURE__ */ new Map();
41
+ var _usageCache = /* @__PURE__ */ new Map();
42
+ var _usageInFlight = /* @__PURE__ */ new Map();
43
+ var _jsonlPathIndex = null;
44
+ function yieldToEventLoop() {
45
+ return new Promise((resolve) => setImmediate(resolve));
46
+ }
47
+ function getPricing(model) {
48
+ if (MODEL_PRICING[model]) return MODEL_PRICING[model];
49
+ const stripped = model.replace(/-\d{8}$/, "");
50
+ if (MODEL_PRICING[stripped]) return MODEL_PRICING[stripped];
51
+ const sortedKeys = Object.keys(MODEL_PRICING).sort((a, b) => b.length - a.length);
52
+ for (const key of sortedKeys) {
53
+ if (model.includes(key)) return MODEL_PRICING[key];
54
+ }
55
+ return DEFAULT_PRICING;
56
+ }
57
+ async function getAgentSpend(period = "7d") {
58
+ const cached = _spendCache.get(period);
59
+ if (cached && Date.now() < cached.expires) {
60
+ return cached.result;
61
+ }
62
+ const inFlight = _spendInFlight.get(period);
63
+ if (inFlight) return inFlight;
64
+ const promise = computeAgentSpend(period).finally(() => _spendInFlight.delete(period));
65
+ _spendInFlight.set(period, promise);
66
+ return promise;
67
+ }
68
+ async function computeAgentSpend(period) {
69
+ const cutoff = periodToCutoff(period);
70
+ const client = getClient();
71
+ const dbResult = await client.execute({
72
+ sql: `SELECT session_uuid, agent_id FROM session_agent_map WHERE started_at >= ?`,
73
+ args: [cutoff]
74
+ });
75
+ if (dbResult.rows.length === 0) return [];
76
+ const sessionAgent = /* @__PURE__ */ new Map();
77
+ for (const row of dbResult.rows) {
78
+ sessionAgent.set(row.session_uuid, row.agent_id);
79
+ }
80
+ const jsonlPaths = await getClaudeSessionJsonlIndex();
81
+ if (jsonlPaths.size === 0) return [];
82
+ const agentTotals = /* @__PURE__ */ new Map();
83
+ let processed = 0;
84
+ for (const [sessionUuid, agentId] of sessionAgent) {
85
+ const jsonlPath = jsonlPaths.get(sessionUuid);
86
+ if (!jsonlPath) continue;
87
+ try {
88
+ const usage = await extractSessionUsageCached(jsonlPath);
89
+ if (usage.input === 0 && usage.output === 0) continue;
90
+ const totals = agentTotals.get(agentId) ?? {
91
+ input: 0,
92
+ output: 0,
93
+ cacheRead: 0,
94
+ cacheCreate: 0,
95
+ costUSD: 0,
96
+ sessions: /* @__PURE__ */ new Set()
97
+ };
98
+ totals.input += usage.input;
99
+ totals.output += usage.output;
100
+ totals.cacheRead += usage.cacheRead;
101
+ totals.cacheCreate += usage.cacheCreate;
102
+ totals.costUSD += usage.costUSD;
103
+ totals.sessions.add(sessionUuid);
104
+ agentTotals.set(agentId, totals);
105
+ } catch {
106
+ }
107
+ processed++;
108
+ if (processed % 25 === 0) await yieldToEventLoop();
109
+ }
110
+ const result = Array.from(agentTotals.entries()).map(([agentId, t]) => ({
111
+ agentId,
112
+ inputTokens: t.input,
113
+ outputTokens: t.output,
114
+ cacheReadTokens: t.cacheRead,
115
+ cacheCreationTokens: t.cacheCreate,
116
+ costUSD: t.costUSD,
117
+ sessions: t.sessions.size,
118
+ period
119
+ })).sort((a, b) => b.costUSD - a.costUSD);
120
+ _spendCache.set(period, { result, expires: Date.now() + CACHE_TTL_MS });
121
+ return result;
122
+ }
123
+ async function getClaudeSessionJsonlIndex() {
124
+ if (_jsonlPathIndex && Date.now() < _jsonlPathIndex.expires) {
125
+ return _jsonlPathIndex.paths;
126
+ }
127
+ const claudeDir = path.join(os.homedir(), ".claude", "projects");
128
+ const paths = /* @__PURE__ */ new Map();
129
+ let projectDirs = [];
130
+ try {
131
+ const entries = await readdir(claudeDir, { withFileTypes: true });
132
+ projectDirs = entries.filter((entry) => entry.isDirectory()).map((entry) => path.join(claudeDir, entry.name));
133
+ } catch {
134
+ _jsonlPathIndex = { expires: Date.now() + JSONL_INDEX_TTL_MS, paths };
135
+ return paths;
136
+ }
137
+ let scanned = 0;
138
+ for (const dir of projectDirs) {
139
+ try {
140
+ const files = await readdir(dir);
141
+ for (const file of files) {
142
+ if (!file.endsWith(".jsonl")) continue;
143
+ paths.set(file.slice(0, -".jsonl".length), path.join(dir, file));
144
+ }
145
+ } catch {
146
+ }
147
+ scanned++;
148
+ if (scanned % 25 === 0) await yieldToEventLoop();
149
+ }
150
+ _jsonlPathIndex = { expires: Date.now() + JSONL_INDEX_TTL_MS, paths };
151
+ return paths;
152
+ }
153
+ async function extractSessionUsageCached(jsonlPath) {
154
+ const st = await stat(jsonlPath);
155
+ const cached = _usageCache.get(jsonlPath);
156
+ if (cached && cached.mtimeMs === st.mtimeMs && cached.size === st.size) {
157
+ return cached.usage;
158
+ }
159
+ const existing = _usageInFlight.get(jsonlPath);
160
+ if (existing) return existing;
161
+ const promise = extractSessionUsage(jsonlPath).then((usage) => {
162
+ _usageCache.set(jsonlPath, { mtimeMs: st.mtimeMs, size: st.size, usage });
163
+ pruneUsageCache();
164
+ return usage;
165
+ }).finally(() => _usageInFlight.delete(jsonlPath));
166
+ _usageInFlight.set(jsonlPath, promise);
167
+ return promise;
168
+ }
169
+ function pruneUsageCache() {
170
+ if (_usageCache.size <= USAGE_CACHE_MAX_ENTRIES) return;
171
+ const overflow = _usageCache.size - USAGE_CACHE_MAX_ENTRIES;
172
+ let removed = 0;
173
+ for (const key of _usageCache.keys()) {
174
+ _usageCache.delete(key);
175
+ removed++;
176
+ if (removed >= overflow) break;
177
+ }
178
+ }
179
+ async function extractSessionUsage(jsonlPath) {
180
+ let input = 0;
181
+ let output = 0;
182
+ let cacheRead = 0;
183
+ let cacheCreate = 0;
184
+ let costUSD = 0;
185
+ const seenMessageIds = /* @__PURE__ */ new Set();
186
+ const rl = createInterface({
187
+ input: createReadStream(jsonlPath, { encoding: "utf8" }),
188
+ crlfDelay: Infinity
189
+ });
190
+ for await (const line of rl) {
191
+ if (!line.includes('"type":"assistant"')) continue;
192
+ try {
193
+ const record = JSON.parse(line);
194
+ if (record.type !== "assistant") continue;
195
+ const messageId = record.message?.id;
196
+ if (messageId) {
197
+ if (seenMessageIds.has(messageId)) continue;
198
+ seenMessageIds.add(messageId);
199
+ }
200
+ const usage = record.message?.usage;
201
+ if (!usage) continue;
202
+ const model = record.message?.model ?? "";
203
+ const pricing = getPricing(model);
204
+ const inp = usage.input_tokens ?? 0;
205
+ const out = usage.output_tokens ?? 0;
206
+ const cr = usage.cache_read_input_tokens ?? 0;
207
+ const cc = usage.cache_creation_input_tokens ?? 0;
208
+ input += inp;
209
+ output += out;
210
+ cacheRead += cr;
211
+ cacheCreate += cc;
212
+ if (pricing) {
213
+ costUSD += inp * pricing.input + out * pricing.output + cr * pricing.cacheRead + cc * pricing.cacheWrite;
214
+ }
215
+ } catch {
216
+ }
217
+ }
218
+ return { input, output, cacheRead, cacheCreate, costUSD };
219
+ }
220
+ function periodToCutoff(period) {
221
+ const ms = { "24h": 864e5, "7d": 6048e5, "30d": 2592e6 }[period];
222
+ return new Date(Date.now() - ms).toISOString();
223
+ }
224
+
225
+ export {
226
+ getAgentSpend
227
+ };