@caupulican/pi-adaptative 0.81.39 → 0.81.41

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 (884) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/README.md +2 -0
  3. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts +2 -0
  4. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts.map +1 -1
  5. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js +3 -0
  6. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js.map +1 -1
  7. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.ts +4 -0
  8. package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts +9 -0
  9. package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts.map +1 -1
  10. package/dist/bundled-resources/extensions/tmux-agent-manager/index.js +290 -107
  11. package/dist/bundled-resources/extensions/tmux-agent-manager/index.js.map +1 -1
  12. package/dist/bundled-resources/extensions/tmux-agent-manager/index.ts +357 -122
  13. package/dist/bundled-resources/skills/tool-call-repair/references/repair-catalogue.md +2 -2
  14. package/dist/cli/args.d.ts +4 -0
  15. package/dist/cli/args.d.ts.map +1 -1
  16. package/dist/cli/args.js +31 -1
  17. package/dist/cli/args.js.map +1 -1
  18. package/dist/core/agent-directory-layout.d.ts +15 -0
  19. package/dist/core/agent-directory-layout.d.ts.map +1 -0
  20. package/dist/core/agent-directory-layout.js +72 -0
  21. package/dist/core/agent-directory-layout.js.map +1 -0
  22. package/dist/core/agent-paths.d.ts +25 -2
  23. package/dist/core/agent-paths.d.ts.map +1 -1
  24. package/dist/core/agent-paths.js +79 -4
  25. package/dist/core/agent-paths.js.map +1 -1
  26. package/dist/core/agent-session-contracts.d.ts +293 -0
  27. package/dist/core/agent-session-contracts.d.ts.map +1 -0
  28. package/dist/core/agent-session-contracts.js +26 -0
  29. package/dist/core/agent-session-contracts.js.map +1 -0
  30. package/dist/core/agent-session-runtime.d.ts +52 -8
  31. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  32. package/dist/core/agent-session-runtime.js +400 -79
  33. package/dist/core/agent-session-runtime.js.map +1 -1
  34. package/dist/core/agent-session-services.d.ts +1 -0
  35. package/dist/core/agent-session-services.d.ts.map +1 -1
  36. package/dist/core/agent-session-services.js +1 -0
  37. package/dist/core/agent-session-services.js.map +1 -1
  38. package/dist/core/agent-session.d.ts +74 -518
  39. package/dist/core/agent-session.d.ts.map +1 -1
  40. package/dist/core/agent-session.js +370 -1432
  41. package/dist/core/agent-session.js.map +1 -1
  42. package/dist/core/auth-storage.d.ts.map +1 -1
  43. package/dist/core/auth-storage.js +3 -1
  44. package/dist/core/auth-storage.js.map +1 -1
  45. package/dist/core/autonomy/approval-gate.d.ts +3 -2
  46. package/dist/core/autonomy/approval-gate.d.ts.map +1 -1
  47. package/dist/core/autonomy/approval-gate.js +6 -28
  48. package/dist/core/autonomy/approval-gate.js.map +1 -1
  49. package/dist/core/autonomy/bounded-completion.d.ts +1 -1
  50. package/dist/core/autonomy/bounded-completion.d.ts.map +1 -1
  51. package/dist/core/autonomy/bounded-completion.js +1 -1
  52. package/dist/core/autonomy/bounded-completion.js.map +1 -1
  53. package/dist/core/autonomy/contracts.d.ts +20 -12
  54. package/dist/core/autonomy/contracts.d.ts.map +1 -1
  55. package/dist/core/autonomy/contracts.js.map +1 -1
  56. package/dist/core/autonomy/foreground-envelope.d.ts +8 -2
  57. package/dist/core/autonomy/foreground-envelope.d.ts.map +1 -1
  58. package/dist/core/autonomy/foreground-envelope.js +8 -25
  59. package/dist/core/autonomy/foreground-envelope.js.map +1 -1
  60. package/dist/core/autonomy/gates.d.ts.map +1 -1
  61. package/dist/core/autonomy/gates.js +8 -10
  62. package/dist/core/autonomy/gates.js.map +1 -1
  63. package/dist/core/autonomy/lane-private-paths.d.ts +2 -0
  64. package/dist/core/autonomy/lane-private-paths.d.ts.map +1 -0
  65. package/dist/core/autonomy/lane-private-paths.js +16 -0
  66. package/dist/core/autonomy/lane-private-paths.js.map +1 -0
  67. package/dist/core/autonomy/lane-tool-surface.d.ts +10 -0
  68. package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
  69. package/dist/core/autonomy/lane-tool-surface.js +48 -9
  70. package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
  71. package/dist/core/autonomy/lane-tracker.d.ts +14 -0
  72. package/dist/core/autonomy/lane-tracker.d.ts.map +1 -1
  73. package/dist/core/autonomy/lane-tracker.js +38 -0
  74. package/dist/core/autonomy/lane-tracker.js.map +1 -1
  75. package/dist/core/autonomy/risk-assessment.d.ts +1 -2
  76. package/dist/core/autonomy/risk-assessment.d.ts.map +1 -1
  77. package/dist/core/autonomy/risk-assessment.js +1 -123
  78. package/dist/core/autonomy/risk-assessment.js.map +1 -1
  79. package/dist/core/autonomy/session-lane-record.d.ts +4 -4
  80. package/dist/core/autonomy/session-lane-record.d.ts.map +1 -1
  81. package/dist/core/autonomy/session-lane-record.js +16 -29
  82. package/dist/core/autonomy/session-lane-record.js.map +1 -1
  83. package/dist/core/autonomy/telemetry-events.d.ts +1 -1
  84. package/dist/core/autonomy/telemetry-events.d.ts.map +1 -1
  85. package/dist/core/autonomy/telemetry-events.js +1 -1
  86. package/dist/core/autonomy/telemetry-events.js.map +1 -1
  87. package/dist/core/autonomy-telemetry.d.ts +7 -7
  88. package/dist/core/autonomy-telemetry.d.ts.map +1 -1
  89. package/dist/core/autonomy-telemetry.js +9 -9
  90. package/dist/core/autonomy-telemetry.js.map +1 -1
  91. package/dist/core/background-lane-controller.d.ts +56 -236
  92. package/dist/core/background-lane-controller.d.ts.map +1 -1
  93. package/dist/core/background-lane-controller.js +141 -1273
  94. package/dist/core/background-lane-controller.js.map +1 -1
  95. package/dist/core/bedrock-sso-login.d.ts +16 -0
  96. package/dist/core/bedrock-sso-login.d.ts.map +1 -0
  97. package/dist/core/bedrock-sso-login.js +98 -0
  98. package/dist/core/bedrock-sso-login.js.map +1 -0
  99. package/dist/core/capability-contract.d.ts +4 -0
  100. package/dist/core/capability-contract.d.ts.map +1 -0
  101. package/dist/core/capability-contract.js +28 -0
  102. package/dist/core/capability-contract.js.map +1 -0
  103. package/dist/core/compaction-controller.d.ts +90 -0
  104. package/dist/core/compaction-controller.d.ts.map +1 -0
  105. package/dist/core/compaction-controller.js +452 -0
  106. package/dist/core/compaction-controller.js.map +1 -0
  107. package/dist/core/compaction-support.d.ts +13 -17
  108. package/dist/core/compaction-support.d.ts.map +1 -1
  109. package/dist/core/compaction-support.js +3 -3
  110. package/dist/core/compaction-support.js.map +1 -1
  111. package/dist/core/context/context-artifacts.d.ts +6 -2
  112. package/dist/core/context/context-artifacts.d.ts.map +1 -1
  113. package/dist/core/context/context-artifacts.js +34 -2
  114. package/dist/core/context/context-artifacts.js.map +1 -1
  115. package/dist/core/context/context-store-retention.d.ts +8 -2
  116. package/dist/core/context/context-store-retention.d.ts.map +1 -1
  117. package/dist/core/context/context-store-retention.js +158 -35
  118. package/dist/core/context/context-store-retention.js.map +1 -1
  119. package/dist/core/context/okf-memory.d.ts.map +1 -1
  120. package/dist/core/context/okf-memory.js +9 -11
  121. package/dist/core/context/okf-memory.js.map +1 -1
  122. package/dist/core/context/sqlite-runtime-index.d.ts.map +1 -1
  123. package/dist/core/context/sqlite-runtime-index.js +6 -8
  124. package/dist/core/context/sqlite-runtime-index.js.map +1 -1
  125. package/dist/core/context-gc.d.ts +3 -0
  126. package/dist/core/context-gc.d.ts.map +1 -1
  127. package/dist/core/context-gc.js +10 -5
  128. package/dist/core/context-gc.js.map +1 -1
  129. package/dist/core/context-pipeline.d.ts +1 -1
  130. package/dist/core/context-pipeline.d.ts.map +1 -1
  131. package/dist/core/context-pipeline.js +16 -37
  132. package/dist/core/context-pipeline.js.map +1 -1
  133. package/dist/core/cost/cost-summary.d.ts.map +1 -1
  134. package/dist/core/cost/cost-summary.js +5 -3
  135. package/dist/core/cost/cost-summary.js.map +1 -1
  136. package/dist/core/cost/daily-usage.d.ts.map +1 -1
  137. package/dist/core/cost/daily-usage.js +4 -5
  138. package/dist/core/cost/daily-usage.js.map +1 -1
  139. package/dist/core/default-tool-surface.d.ts.map +1 -1
  140. package/dist/core/default-tool-surface.js +2 -0
  141. package/dist/core/default-tool-surface.js.map +1 -1
  142. package/dist/core/delegation/managed-lane-controller.d.ts +34 -0
  143. package/dist/core/delegation/managed-lane-controller.d.ts.map +1 -0
  144. package/dist/core/delegation/managed-lane-controller.js +217 -0
  145. package/dist/core/delegation/managed-lane-controller.js.map +1 -0
  146. package/dist/core/delegation/session-worker-claim.d.ts +44 -0
  147. package/dist/core/delegation/session-worker-claim.d.ts.map +1 -0
  148. package/dist/core/delegation/session-worker-claim.js +98 -0
  149. package/dist/core/delegation/session-worker-claim.js.map +1 -0
  150. package/dist/core/delegation/worker-actions.d.ts +7 -5
  151. package/dist/core/delegation/worker-actions.d.ts.map +1 -1
  152. package/dist/core/delegation/worker-actions.js +20 -4
  153. package/dist/core/delegation/worker-actions.js.map +1 -1
  154. package/dist/core/delegation/{worker-result.d.ts → worker-claim.d.ts} +13 -13
  155. package/dist/core/delegation/worker-claim.d.ts.map +1 -0
  156. package/dist/core/delegation/{worker-result.js → worker-claim.js} +61 -51
  157. package/dist/core/delegation/worker-claim.js.map +1 -0
  158. package/dist/core/delegation/worker-delegation-controller.d.ts +110 -0
  159. package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -0
  160. package/dist/core/delegation/worker-delegation-controller.js +861 -0
  161. package/dist/core/delegation/worker-delegation-controller.js.map +1 -0
  162. package/dist/core/delegation/worker-delegation-request.d.ts +11 -0
  163. package/dist/core/delegation/worker-delegation-request.d.ts.map +1 -0
  164. package/dist/core/delegation/worker-delegation-request.js +2 -0
  165. package/dist/core/delegation/worker-delegation-request.js.map +1 -0
  166. package/dist/core/delegation/worker-dispatch-scheduler.d.ts +40 -0
  167. package/dist/core/delegation/worker-dispatch-scheduler.d.ts.map +1 -0
  168. package/dist/core/delegation/worker-dispatch-scheduler.js +93 -0
  169. package/dist/core/delegation/worker-dispatch-scheduler.js.map +1 -0
  170. package/dist/core/delegation/worker-execution-policy.d.ts +62 -0
  171. package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -0
  172. package/dist/core/delegation/worker-execution-policy.js +160 -0
  173. package/dist/core/delegation/worker-execution-policy.js.map +1 -0
  174. package/dist/core/delegation/worker-lane-projection.d.ts +14 -0
  175. package/dist/core/delegation/worker-lane-projection.d.ts.map +1 -0
  176. package/dist/core/delegation/worker-lane-projection.js +100 -0
  177. package/dist/core/delegation/worker-lane-projection.js.map +1 -0
  178. package/dist/core/delegation/worker-lifecycle.d.ts +97 -0
  179. package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -0
  180. package/dist/core/delegation/worker-lifecycle.js +339 -0
  181. package/dist/core/delegation/worker-lifecycle.js.map +1 -0
  182. package/dist/core/delegation/worker-notification-coordinator.d.ts +36 -0
  183. package/dist/core/delegation/worker-notification-coordinator.d.ts.map +1 -0
  184. package/dist/core/delegation/worker-notification-coordinator.js +90 -0
  185. package/dist/core/delegation/worker-notification-coordinator.js.map +1 -0
  186. package/dist/core/delegation/worker-profile-resolver.d.ts +55 -0
  187. package/dist/core/delegation/worker-profile-resolver.d.ts.map +1 -0
  188. package/dist/core/delegation/worker-profile-resolver.js +113 -0
  189. package/dist/core/delegation/worker-profile-resolver.js.map +1 -0
  190. package/dist/core/delegation/worker-runner.d.ts +25 -14
  191. package/dist/core/delegation/worker-runner.d.ts.map +1 -1
  192. package/dist/core/delegation/worker-runner.js +122 -53
  193. package/dist/core/delegation/worker-runner.js.map +1 -1
  194. package/dist/core/delegation/worker-task-label.d.ts +3 -0
  195. package/dist/core/delegation/worker-task-label.d.ts.map +1 -0
  196. package/dist/core/delegation/worker-task-label.js +11 -0
  197. package/dist/core/delegation/worker-task-label.js.map +1 -0
  198. package/dist/core/doctor.d.ts +8 -0
  199. package/dist/core/doctor.d.ts.map +1 -1
  200. package/dist/core/doctor.js +32 -1
  201. package/dist/core/doctor.js.map +1 -1
  202. package/dist/core/extension-import-authority.d.ts +6 -0
  203. package/dist/core/extension-import-authority.d.ts.map +1 -0
  204. package/dist/core/extension-import-authority.js +10 -0
  205. package/dist/core/extension-import-authority.js.map +1 -0
  206. package/dist/core/extensions/index.d.ts +1 -1
  207. package/dist/core/extensions/index.d.ts.map +1 -1
  208. package/dist/core/extensions/index.js.map +1 -1
  209. package/dist/core/extensions/loader.d.ts +5 -1
  210. package/dist/core/extensions/loader.d.ts.map +1 -1
  211. package/dist/core/extensions/loader.js +52 -18
  212. package/dist/core/extensions/loader.js.map +1 -1
  213. package/dist/core/extensions/runner.d.ts +3 -0
  214. package/dist/core/extensions/runner.d.ts.map +1 -1
  215. package/dist/core/extensions/runner.js +20 -5
  216. package/dist/core/extensions/runner.js.map +1 -1
  217. package/dist/core/extensions/stale-context.d.ts +2 -0
  218. package/dist/core/extensions/stale-context.d.ts.map +1 -0
  219. package/dist/core/extensions/stale-context.js +2 -0
  220. package/dist/core/extensions/stale-context.js.map +1 -0
  221. package/dist/core/extensions/storage.d.ts +8 -0
  222. package/dist/core/extensions/storage.d.ts.map +1 -0
  223. package/dist/core/extensions/storage.js +28 -0
  224. package/dist/core/extensions/storage.js.map +1 -0
  225. package/dist/core/extensions/types.d.ts +78 -21
  226. package/dist/core/extensions/types.d.ts.map +1 -1
  227. package/dist/core/extensions/types.js.map +1 -1
  228. package/dist/core/failure-corpus.d.ts +1 -15
  229. package/dist/core/failure-corpus.d.ts.map +1 -1
  230. package/dist/core/failure-corpus.js +9 -37
  231. package/dist/core/failure-corpus.js.map +1 -1
  232. package/dist/core/foreground-recovery-controller.d.ts +53 -0
  233. package/dist/core/foreground-recovery-controller.d.ts.map +1 -0
  234. package/dist/core/foreground-recovery-controller.js +111 -0
  235. package/dist/core/foreground-recovery-controller.js.map +1 -0
  236. package/dist/core/gateways/channel-provider.d.ts +3 -0
  237. package/dist/core/gateways/channel-provider.d.ts.map +1 -1
  238. package/dist/core/gateways/channel-provider.js +31 -6
  239. package/dist/core/gateways/channel-provider.js.map +1 -1
  240. package/dist/core/goal-loop-controller.d.ts +14 -9
  241. package/dist/core/goal-loop-controller.d.ts.map +1 -1
  242. package/dist/core/goal-loop-controller.js +47 -75
  243. package/dist/core/goal-loop-controller.js.map +1 -1
  244. package/dist/core/goals/compact-goal-context.d.ts +11 -0
  245. package/dist/core/goals/compact-goal-context.d.ts.map +1 -0
  246. package/dist/core/goals/compact-goal-context.js +59 -0
  247. package/dist/core/goals/compact-goal-context.js.map +1 -0
  248. package/dist/core/goals/goal-acceptance.d.ts +11 -0
  249. package/dist/core/goals/goal-acceptance.d.ts.map +1 -0
  250. package/dist/core/goals/goal-acceptance.js +27 -0
  251. package/dist/core/goals/goal-acceptance.js.map +1 -0
  252. package/dist/core/goals/goal-auto-continue-controller.d.ts +28 -0
  253. package/dist/core/goals/goal-auto-continue-controller.d.ts.map +1 -0
  254. package/dist/core/goals/goal-auto-continue-controller.js +90 -0
  255. package/dist/core/goals/goal-auto-continue-controller.js.map +1 -0
  256. package/dist/core/goals/goal-continuation-controller.d.ts +2 -2
  257. package/dist/core/goals/goal-continuation-controller.d.ts.map +1 -1
  258. package/dist/core/goals/goal-continuation-controller.js +52 -11
  259. package/dist/core/goals/goal-continuation-controller.js.map +1 -1
  260. package/dist/core/goals/goal-continuation-defaults.d.ts +4 -29
  261. package/dist/core/goals/goal-continuation-defaults.d.ts.map +1 -1
  262. package/dist/core/goals/goal-continuation-defaults.js +4 -32
  263. package/dist/core/goals/goal-continuation-defaults.js.map +1 -1
  264. package/dist/core/goals/goal-continuation-prompt.d.ts +8 -18
  265. package/dist/core/goals/goal-continuation-prompt.d.ts.map +1 -1
  266. package/dist/core/goals/goal-continuation-prompt.js +9 -179
  267. package/dist/core/goals/goal-continuation-prompt.js.map +1 -1
  268. package/dist/core/goals/goal-lifecycle.d.ts +43 -0
  269. package/dist/core/goals/goal-lifecycle.d.ts.map +1 -0
  270. package/dist/core/goals/goal-lifecycle.js +102 -0
  271. package/dist/core/goals/goal-lifecycle.js.map +1 -0
  272. package/dist/core/goals/goal-record.d.ts +17 -0
  273. package/dist/core/goals/goal-record.d.ts.map +1 -0
  274. package/dist/core/goals/goal-record.js +31 -0
  275. package/dist/core/goals/goal-record.js.map +1 -0
  276. package/dist/core/goals/goal-runtime-snapshot.d.ts +11 -9
  277. package/dist/core/goals/goal-runtime-snapshot.d.ts.map +1 -1
  278. package/dist/core/goals/goal-runtime-snapshot.js +10 -8
  279. package/dist/core/goals/goal-runtime-snapshot.js.map +1 -1
  280. package/dist/core/goals/goal-session-controller.d.ts +42 -0
  281. package/dist/core/goals/goal-session-controller.d.ts.map +1 -0
  282. package/dist/core/goals/goal-session-controller.js +128 -0
  283. package/dist/core/goals/goal-session-controller.js.map +1 -0
  284. package/dist/core/goals/goal-state.d.ts +46 -25
  285. package/dist/core/goals/goal-state.d.ts.map +1 -1
  286. package/dist/core/goals/goal-state.js +91 -24
  287. package/dist/core/goals/goal-state.js.map +1 -1
  288. package/dist/core/goals/goal-tool-core.d.ts +9 -10
  289. package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
  290. package/dist/core/goals/goal-tool-core.js +60 -75
  291. package/dist/core/goals/goal-tool-core.js.map +1 -1
  292. package/dist/core/goals/session-goal-state.d.ts +20 -12
  293. package/dist/core/goals/session-goal-state.d.ts.map +1 -1
  294. package/dist/core/goals/session-goal-state.js +133 -33
  295. package/dist/core/goals/session-goal-state.js.map +1 -1
  296. package/dist/core/human-input-controller.d.ts +47 -0
  297. package/dist/core/human-input-controller.d.ts.map +1 -0
  298. package/dist/core/human-input-controller.js +181 -0
  299. package/dist/core/human-input-controller.js.map +1 -0
  300. package/dist/core/human-input.d.ts +100 -0
  301. package/dist/core/human-input.d.ts.map +1 -0
  302. package/dist/core/human-input.js +362 -0
  303. package/dist/core/human-input.js.map +1 -0
  304. package/dist/core/index.d.ts +9 -1
  305. package/dist/core/index.d.ts.map +1 -1
  306. package/dist/core/index.js +9 -1
  307. package/dist/core/index.js.map +1 -1
  308. package/dist/core/{telemetry.d.ts → install-telemetry.d.ts} +1 -1
  309. package/dist/core/install-telemetry.d.ts.map +1 -0
  310. package/dist/core/{telemetry.js → install-telemetry.js} +1 -1
  311. package/dist/core/install-telemetry.js.map +1 -0
  312. package/dist/core/keybindings.d.ts +17 -1
  313. package/dist/core/keybindings.d.ts.map +1 -1
  314. package/dist/core/keybindings.js +24 -6
  315. package/dist/core/keybindings.js.map +1 -1
  316. package/dist/core/learning/learning-audit.d.ts +2 -4
  317. package/dist/core/learning/learning-audit.d.ts.map +1 -1
  318. package/dist/core/learning/learning-audit.js +9 -29
  319. package/dist/core/learning/learning-audit.js.map +1 -1
  320. package/dist/core/learning/learning-gate.d.ts.map +1 -1
  321. package/dist/core/learning/learning-gate.js +1 -6
  322. package/dist/core/learning/learning-gate.js.map +1 -1
  323. package/dist/core/learning/session-learning-decision.d.ts +2 -4
  324. package/dist/core/learning/session-learning-decision.d.ts.map +1 -1
  325. package/dist/core/learning/session-learning-decision.js +9 -29
  326. package/dist/core/learning/session-learning-decision.js.map +1 -1
  327. package/dist/core/local-runtime-controller.d.ts +1 -1
  328. package/dist/core/local-runtime-controller.d.ts.map +1 -1
  329. package/dist/core/local-runtime-controller.js.map +1 -1
  330. package/dist/core/memory-controller.d.ts.map +1 -1
  331. package/dist/core/memory-controller.js +4 -4
  332. package/dist/core/memory-controller.js.map +1 -1
  333. package/dist/core/model-capability.d.ts +0 -19
  334. package/dist/core/model-capability.d.ts.map +1 -1
  335. package/dist/core/model-capability.js +1 -19
  336. package/dist/core/model-capability.js.map +1 -1
  337. package/dist/core/model-registry.d.ts +6 -1
  338. package/dist/core/model-registry.d.ts.map +1 -1
  339. package/dist/core/model-registry.js +13 -5
  340. package/dist/core/model-registry.js.map +1 -1
  341. package/dist/core/model-resolver.d.ts +17 -2
  342. package/dist/core/model-resolver.d.ts.map +1 -1
  343. package/dist/core/model-resolver.js +38 -25
  344. package/dist/core/model-resolver.js.map +1 -1
  345. package/dist/core/model-router/intent-classifier.d.ts +1 -4
  346. package/dist/core/model-router/intent-classifier.d.ts.map +1 -1
  347. package/dist/core/model-router/intent-classifier.js +1 -156
  348. package/dist/core/model-router/intent-classifier.js.map +1 -1
  349. package/dist/core/model-router-controller.d.ts +1 -1
  350. package/dist/core/model-router-controller.d.ts.map +1 -1
  351. package/dist/core/model-router-controller.js +2 -2
  352. package/dist/core/model-router-controller.js.map +1 -1
  353. package/dist/core/model-selection-controller.d.ts +5 -5
  354. package/dist/core/model-selection-controller.d.ts.map +1 -1
  355. package/dist/core/model-selection-controller.js.map +1 -1
  356. package/dist/core/model-tool-protocol.d.ts +23 -0
  357. package/dist/core/model-tool-protocol.d.ts.map +1 -0
  358. package/dist/core/model-tool-protocol.js +43 -0
  359. package/dist/core/model-tool-protocol.js.map +1 -0
  360. package/dist/core/models/adaptation-store.d.ts +4 -6
  361. package/dist/core/models/adaptation-store.d.ts.map +1 -1
  362. package/dist/core/models/adaptation-store.js +95 -83
  363. package/dist/core/models/adaptation-store.js.map +1 -1
  364. package/dist/core/models/fitness-store.d.ts +2 -12
  365. package/dist/core/models/fitness-store.d.ts.map +1 -1
  366. package/dist/core/models/fitness-store.js +84 -57
  367. package/dist/core/models/fitness-store.js.map +1 -1
  368. package/dist/core/models/host-state-store.d.ts +34 -0
  369. package/dist/core/models/host-state-store.d.ts.map +1 -0
  370. package/dist/core/models/host-state-store.js +86 -0
  371. package/dist/core/models/host-state-store.js.map +1 -0
  372. package/dist/core/orchestration/agent-resume.d.ts +24 -0
  373. package/dist/core/orchestration/agent-resume.d.ts.map +1 -0
  374. package/dist/core/orchestration/agent-resume.js +90 -0
  375. package/dist/core/orchestration/agent-resume.js.map +1 -0
  376. package/dist/core/orchestration/capability-gateway.d.ts +61 -0
  377. package/dist/core/orchestration/capability-gateway.d.ts.map +1 -0
  378. package/dist/core/orchestration/capability-gateway.js +152 -0
  379. package/dist/core/orchestration/capability-gateway.js.map +1 -0
  380. package/dist/core/orchestration/contracts.d.ts +343 -0
  381. package/dist/core/orchestration/contracts.d.ts.map +1 -0
  382. package/dist/core/orchestration/contracts.js +135 -0
  383. package/dist/core/orchestration/contracts.js.map +1 -0
  384. package/dist/core/orchestration/delegation-ledger.d.ts +56 -0
  385. package/dist/core/orchestration/delegation-ledger.d.ts.map +1 -0
  386. package/dist/core/orchestration/delegation-ledger.js +200 -0
  387. package/dist/core/orchestration/delegation-ledger.js.map +1 -0
  388. package/dist/core/orchestration/event-store.d.ts +83 -0
  389. package/dist/core/orchestration/event-store.d.ts.map +1 -0
  390. package/dist/core/orchestration/event-store.js +560 -0
  391. package/dist/core/orchestration/event-store.js.map +1 -0
  392. package/dist/core/orchestration/lane-tool-manifests.d.ts +9 -0
  393. package/dist/core/orchestration/lane-tool-manifests.d.ts.map +1 -0
  394. package/dist/core/orchestration/lane-tool-manifests.js +37 -0
  395. package/dist/core/orchestration/lane-tool-manifests.js.map +1 -0
  396. package/dist/core/orchestration/model-binding.d.ts +15 -0
  397. package/dist/core/orchestration/model-binding.d.ts.map +1 -0
  398. package/dist/core/orchestration/model-binding.js +29 -0
  399. package/dist/core/orchestration/model-binding.js.map +1 -0
  400. package/dist/core/orchestration/policy-compiler.d.ts +49 -0
  401. package/dist/core/orchestration/policy-compiler.d.ts.map +1 -0
  402. package/dist/core/orchestration/policy-compiler.js +191 -0
  403. package/dist/core/orchestration/policy-compiler.js.map +1 -0
  404. package/dist/core/orchestration/policy-gate.d.ts +18 -0
  405. package/dist/core/orchestration/policy-gate.d.ts.map +1 -0
  406. package/dist/core/orchestration/policy-gate.js +24 -0
  407. package/dist/core/orchestration/policy-gate.js.map +1 -0
  408. package/dist/core/orchestration/profile-registry.d.ts +51 -0
  409. package/dist/core/orchestration/profile-registry.d.ts.map +1 -0
  410. package/dist/core/orchestration/profile-registry.js +393 -0
  411. package/dist/core/orchestration/profile-registry.js.map +1 -0
  412. package/dist/core/orchestration/profile-store.d.ts +31 -0
  413. package/dist/core/orchestration/profile-store.d.ts.map +1 -0
  414. package/dist/core/orchestration/profile-store.js +136 -0
  415. package/dist/core/orchestration/profile-store.js.map +1 -0
  416. package/dist/core/orchestration/risk-budget.d.ts +9 -0
  417. package/dist/core/orchestration/risk-budget.d.ts.map +1 -0
  418. package/dist/core/orchestration/risk-budget.js +48 -0
  419. package/dist/core/orchestration/risk-budget.js.map +1 -0
  420. package/dist/core/orchestration/task-runtime.d.ts +168 -0
  421. package/dist/core/orchestration/task-runtime.d.ts.map +1 -0
  422. package/dist/core/orchestration/task-runtime.js +1600 -0
  423. package/dist/core/orchestration/task-runtime.js.map +1 -0
  424. package/dist/core/orchestration/work-state-projection.d.ts +32 -0
  425. package/dist/core/orchestration/work-state-projection.d.ts.map +1 -0
  426. package/dist/core/orchestration/work-state-projection.js +116 -0
  427. package/dist/core/orchestration/work-state-projection.js.map +1 -0
  428. package/dist/core/orchestration/worker-execution-contract.d.ts +21 -0
  429. package/dist/core/orchestration/worker-execution-contract.d.ts.map +1 -0
  430. package/dist/core/orchestration/worker-execution-contract.js +179 -0
  431. package/dist/core/orchestration/worker-execution-contract.js.map +1 -0
  432. package/dist/core/orchestration/worker-result-adapter.d.ts +21 -0
  433. package/dist/core/orchestration/worker-result-adapter.d.ts.map +1 -0
  434. package/dist/core/orchestration/worker-result-adapter.js +109 -0
  435. package/dist/core/orchestration/worker-result-adapter.js.map +1 -0
  436. package/dist/core/package-manager.d.ts.map +1 -1
  437. package/dist/core/package-manager.js +20 -3
  438. package/dist/core/package-manager.js.map +1 -1
  439. package/dist/core/process-identity.d.ts +11 -0
  440. package/dist/core/process-identity.d.ts.map +1 -0
  441. package/dist/core/process-identity.js +26 -0
  442. package/dist/core/process-identity.js.map +1 -0
  443. package/dist/core/process-matrix/codes.d.ts +14 -3
  444. package/dist/core/process-matrix/codes.d.ts.map +1 -1
  445. package/dist/core/process-matrix/codes.js.map +1 -1
  446. package/dist/core/process-matrix/resume-launcher.d.ts +26 -0
  447. package/dist/core/process-matrix/resume-launcher.d.ts.map +1 -0
  448. package/dist/core/process-matrix/resume-launcher.js +62 -0
  449. package/dist/core/process-matrix/resume-launcher.js.map +1 -0
  450. package/dist/core/process-matrix/runtime.d.ts +37 -22
  451. package/dist/core/process-matrix/runtime.d.ts.map +1 -1
  452. package/dist/core/process-matrix/runtime.js +399 -76
  453. package/dist/core/process-matrix/runtime.js.map +1 -1
  454. package/dist/core/process-matrix/store.d.ts +5 -2
  455. package/dist/core/process-matrix/store.d.ts.map +1 -1
  456. package/dist/core/process-matrix/store.js +123 -14
  457. package/dist/core/process-matrix/store.js.map +1 -1
  458. package/dist/core/process-matrix/supervisor.d.ts +10 -7
  459. package/dist/core/process-matrix/supervisor.d.ts.map +1 -1
  460. package/dist/core/process-matrix/supervisor.js +45 -14
  461. package/dist/core/process-matrix/supervisor.js.map +1 -1
  462. package/dist/core/profile-filter-controller.d.ts +8 -1
  463. package/dist/core/profile-filter-controller.d.ts.map +1 -1
  464. package/dist/core/profile-filter-controller.js +23 -5
  465. package/dist/core/profile-filter-controller.js.map +1 -1
  466. package/dist/core/profile-registry.d.ts.map +1 -1
  467. package/dist/core/profile-registry.js +6 -8
  468. package/dist/core/profile-registry.js.map +1 -1
  469. package/dist/core/prompt-templates.d.ts +1 -0
  470. package/dist/core/prompt-templates.d.ts.map +1 -1
  471. package/dist/core/prompt-templates.js +18 -29
  472. package/dist/core/prompt-templates.js.map +1 -1
  473. package/dist/core/reflection-controller.d.ts +5 -5
  474. package/dist/core/reflection-controller.d.ts.map +1 -1
  475. package/dist/core/reflection-controller.js +5 -2
  476. package/dist/core/reflection-controller.js.map +1 -1
  477. package/dist/core/reload-blockers.d.ts.map +1 -1
  478. package/dist/core/reload-blockers.js +6 -8
  479. package/dist/core/reload-blockers.js.map +1 -1
  480. package/dist/core/request-auth.d.ts +7 -0
  481. package/dist/core/request-auth.d.ts.map +1 -0
  482. package/dist/core/request-auth.js +8 -0
  483. package/dist/core/request-auth.js.map +1 -0
  484. package/dist/core/research/evidence-bundle.d.ts.map +1 -1
  485. package/dist/core/research/evidence-bundle.js +1 -6
  486. package/dist/core/research/evidence-bundle.js.map +1 -1
  487. package/dist/core/research/lane-model-resolver.d.ts +33 -0
  488. package/dist/core/research/lane-model-resolver.d.ts.map +1 -0
  489. package/dist/core/research/lane-model-resolver.js +65 -0
  490. package/dist/core/research/lane-model-resolver.js.map +1 -0
  491. package/dist/core/research/model-fitness-controller.d.ts +38 -0
  492. package/dist/core/research/model-fitness-controller.d.ts.map +1 -0
  493. package/dist/core/research/model-fitness-controller.js +106 -0
  494. package/dist/core/research/model-fitness-controller.js.map +1 -0
  495. package/dist/core/research/model-fitness.d.ts +1 -1
  496. package/dist/core/research/model-fitness.d.ts.map +1 -1
  497. package/dist/core/research/model-fitness.js +4 -4
  498. package/dist/core/research/model-fitness.js.map +1 -1
  499. package/dist/core/research/research-gate.d.ts.map +1 -1
  500. package/dist/core/research/research-gate.js +7 -7
  501. package/dist/core/research/research-gate.js.map +1 -1
  502. package/dist/core/research/research-lane-controller.d.ts +62 -0
  503. package/dist/core/research/research-lane-controller.d.ts.map +1 -0
  504. package/dist/core/research/research-lane-controller.js +292 -0
  505. package/dist/core/research/research-lane-controller.js.map +1 -0
  506. package/dist/core/research/session-evidence-bundle.d.ts +2 -4
  507. package/dist/core/research/session-evidence-bundle.d.ts.map +1 -1
  508. package/dist/core/research/session-evidence-bundle.js +10 -46
  509. package/dist/core/research/session-evidence-bundle.js.map +1 -1
  510. package/dist/core/resource-loader.d.ts.map +1 -1
  511. package/dist/core/resource-loader.js +23 -8
  512. package/dist/core/resource-loader.js.map +1 -1
  513. package/dist/core/risk-classifier.d.ts +6 -0
  514. package/dist/core/risk-classifier.d.ts.map +1 -0
  515. package/dist/core/risk-classifier.js +233 -0
  516. package/dist/core/risk-classifier.js.map +1 -0
  517. package/dist/core/runtime-builder.d.ts +41 -23
  518. package/dist/core/runtime-builder.d.ts.map +1 -1
  519. package/dist/core/runtime-builder.js +365 -253
  520. package/dist/core/runtime-builder.js.map +1 -1
  521. package/dist/core/sdk.d.ts +6 -3
  522. package/dist/core/sdk.d.ts.map +1 -1
  523. package/dist/core/sdk.js +68 -25
  524. package/dist/core/sdk.js.map +1 -1
  525. package/dist/core/secrets/credential-exposure-guard.d.ts +9 -0
  526. package/dist/core/secrets/credential-exposure-guard.d.ts.map +1 -0
  527. package/dist/core/secrets/credential-exposure-guard.js +241 -0
  528. package/dist/core/secrets/credential-exposure-guard.js.map +1 -0
  529. package/dist/core/secrets/secret-dotenv.d.ts +27 -0
  530. package/dist/core/secrets/secret-dotenv.d.ts.map +1 -0
  531. package/dist/core/secrets/secret-dotenv.js +183 -0
  532. package/dist/core/secrets/secret-dotenv.js.map +1 -0
  533. package/dist/core/secrets/secret-vault-format.d.ts +112 -0
  534. package/dist/core/secrets/secret-vault-format.d.ts.map +1 -0
  535. package/dist/core/secrets/secret-vault-format.js +397 -0
  536. package/dist/core/secrets/secret-vault-format.js.map +1 -0
  537. package/dist/core/secrets/secret-vault.d.ts +72 -0
  538. package/dist/core/secrets/secret-vault.d.ts.map +1 -0
  539. package/dist/core/secrets/secret-vault.js +671 -0
  540. package/dist/core/secrets/secret-vault.js.map +1 -0
  541. package/dist/core/session-analytics.d.ts +4 -23
  542. package/dist/core/session-analytics.d.ts.map +1 -1
  543. package/dist/core/session-analytics.js +67 -70
  544. package/dist/core/session-analytics.js.map +1 -1
  545. package/dist/core/session-image-store.d.ts +33 -0
  546. package/dist/core/session-image-store.d.ts.map +1 -0
  547. package/dist/core/session-image-store.js +283 -0
  548. package/dist/core/session-image-store.js.map +1 -0
  549. package/dist/core/session-role.d.ts +11 -4
  550. package/dist/core/session-role.d.ts.map +1 -1
  551. package/dist/core/session-role.js +24 -5
  552. package/dist/core/session-role.js.map +1 -1
  553. package/dist/core/session-snapshot.d.ts +34 -0
  554. package/dist/core/session-snapshot.d.ts.map +1 -0
  555. package/dist/core/session-snapshot.js +68 -0
  556. package/dist/core/session-snapshot.js.map +1 -0
  557. package/dist/core/session-supervision-runtime.d.ts +31 -0
  558. package/dist/core/session-supervision-runtime.d.ts.map +1 -0
  559. package/dist/core/session-supervision-runtime.js +97 -0
  560. package/dist/core/session-supervision-runtime.js.map +1 -0
  561. package/dist/core/session-tree-navigator.d.ts +4 -6
  562. package/dist/core/session-tree-navigator.d.ts.map +1 -1
  563. package/dist/core/session-tree-navigator.js +4 -1
  564. package/dist/core/session-tree-navigator.js.map +1 -1
  565. package/dist/core/settings-manager.d.ts +10 -5
  566. package/dist/core/settings-manager.d.ts.map +1 -1
  567. package/dist/core/settings-manager.js +81 -29
  568. package/dist/core/settings-manager.js.map +1 -1
  569. package/dist/core/slash-commands.d.ts.map +1 -1
  570. package/dist/core/slash-commands.js +2 -2
  571. package/dist/core/slash-commands.js.map +1 -1
  572. package/dist/core/tasks/session-task-state.d.ts +2 -4
  573. package/dist/core/tasks/session-task-state.d.ts.map +1 -1
  574. package/dist/core/tasks/session-task-state.js +10 -28
  575. package/dist/core/tasks/session-task-state.js.map +1 -1
  576. package/dist/core/tasks/task-projection.d.ts +20 -0
  577. package/dist/core/tasks/task-projection.d.ts.map +1 -0
  578. package/dist/core/tasks/task-projection.js +47 -0
  579. package/dist/core/tasks/task-projection.js.map +1 -0
  580. package/dist/core/tasks/task-state.d.ts +4 -0
  581. package/dist/core/tasks/task-state.d.ts.map +1 -1
  582. package/dist/core/tasks/task-state.js +28 -11
  583. package/dist/core/tasks/task-state.js.map +1 -1
  584. package/dist/core/tool-capability-policy.d.ts +13 -0
  585. package/dist/core/tool-capability-policy.d.ts.map +1 -0
  586. package/dist/core/tool-capability-policy.js +86 -0
  587. package/dist/core/tool-capability-policy.js.map +1 -0
  588. package/dist/core/tool-gate-controller.d.ts.map +1 -1
  589. package/dist/core/tool-gate-controller.js +8 -2
  590. package/dist/core/tool-gate-controller.js.map +1 -1
  591. package/dist/core/tool-protocol-controller.d.ts +89 -0
  592. package/dist/core/tool-protocol-controller.d.ts.map +1 -0
  593. package/dist/core/tool-protocol-controller.js +512 -0
  594. package/dist/core/tool-protocol-controller.js.map +1 -0
  595. package/dist/core/tool-recovery-log-records.d.ts +2 -3
  596. package/dist/core/tool-recovery-log-records.d.ts.map +1 -1
  597. package/dist/core/tool-recovery-log-records.js +9 -35
  598. package/dist/core/tool-recovery-log-records.js.map +1 -1
  599. package/dist/core/tool-recovery-stats.d.ts +21 -1
  600. package/dist/core/tool-recovery-stats.d.ts.map +1 -1
  601. package/dist/core/tool-recovery-stats.js.map +1 -1
  602. package/dist/core/tool-selection/tool-performance-store.d.ts +3 -7
  603. package/dist/core/tool-selection/tool-performance-store.d.ts.map +1 -1
  604. package/dist/core/tool-selection/tool-performance-store.js +97 -138
  605. package/dist/core/tool-selection/tool-performance-store.js.map +1 -1
  606. package/dist/core/tools/ask-question.d.ts +124 -0
  607. package/dist/core/tools/ask-question.d.ts.map +1 -0
  608. package/dist/core/tools/ask-question.js +693 -0
  609. package/dist/core/tools/ask-question.js.map +1 -0
  610. package/dist/core/tools/bash.d.ts +5 -0
  611. package/dist/core/tools/bash.d.ts.map +1 -1
  612. package/dist/core/tools/bash.js +59 -5
  613. package/dist/core/tools/bash.js.map +1 -1
  614. package/dist/core/tools/delegate-status.d.ts +31 -3
  615. package/dist/core/tools/delegate-status.d.ts.map +1 -1
  616. package/dist/core/tools/delegate-status.js +148 -29
  617. package/dist/core/tools/delegate-status.js.map +1 -1
  618. package/dist/core/tools/delegate.d.ts +15 -13
  619. package/dist/core/tools/delegate.d.ts.map +1 -1
  620. package/dist/core/tools/delegate.js +106 -23
  621. package/dist/core/tools/delegate.js.map +1 -1
  622. package/dist/core/tools/extensionify.d.ts.map +1 -1
  623. package/dist/core/tools/extensionify.js +1 -0
  624. package/dist/core/tools/extensionify.js.map +1 -1
  625. package/dist/core/tools/git-filter.d.ts +1 -8
  626. package/dist/core/tools/git-filter.d.ts.map +1 -1
  627. package/dist/core/tools/git-filter.js +2 -63
  628. package/dist/core/tools/git-filter.js.map +1 -1
  629. package/dist/core/tools/goal.d.ts +10 -8
  630. package/dist/core/tools/goal.d.ts.map +1 -1
  631. package/dist/core/tools/goal.js +106 -28
  632. package/dist/core/tools/goal.js.map +1 -1
  633. package/dist/core/tools/index.d.ts +1 -0
  634. package/dist/core/tools/index.d.ts.map +1 -1
  635. package/dist/core/tools/index.js +1 -0
  636. package/dist/core/tools/index.js.map +1 -1
  637. package/dist/core/tools/model-fitness.d.ts.map +1 -1
  638. package/dist/core/tools/model-fitness.js +2 -2
  639. package/dist/core/tools/model-fitness.js.map +1 -1
  640. package/dist/core/tools/orchestration-panel.d.ts +40 -0
  641. package/dist/core/tools/orchestration-panel.d.ts.map +1 -0
  642. package/dist/core/tools/orchestration-panel.js +124 -0
  643. package/dist/core/tools/orchestration-panel.js.map +1 -0
  644. package/dist/core/tools/output-accumulator.d.ts +11 -0
  645. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  646. package/dist/core/tools/output-accumulator.js +36 -3
  647. package/dist/core/tools/output-accumulator.js.map +1 -1
  648. package/dist/core/tools/python.d.ts +2 -0
  649. package/dist/core/tools/python.d.ts.map +1 -1
  650. package/dist/core/tools/python.js +3 -1
  651. package/dist/core/tools/python.js.map +1 -1
  652. package/dist/core/tools/read.d.ts.map +1 -1
  653. package/dist/core/tools/read.js +1 -1
  654. package/dist/core/tools/read.js.map +1 -1
  655. package/dist/core/tools/run-process.d.ts +26 -0
  656. package/dist/core/tools/run-process.d.ts.map +1 -0
  657. package/dist/core/tools/run-process.js +138 -0
  658. package/dist/core/tools/run-process.js.map +1 -0
  659. package/dist/core/tools/search-command-guard.d.ts +14 -0
  660. package/dist/core/tools/search-command-guard.d.ts.map +1 -0
  661. package/dist/core/tools/search-command-guard.js +333 -0
  662. package/dist/core/tools/search-command-guard.js.map +1 -0
  663. package/dist/core/tools/secret-store.d.ts +38 -0
  664. package/dist/core/tools/secret-store.d.ts.map +1 -0
  665. package/dist/core/tools/secret-store.js +412 -0
  666. package/dist/core/tools/secret-store.js.map +1 -0
  667. package/dist/core/tools/shell-command-parser.d.ts +16 -0
  668. package/dist/core/tools/shell-command-parser.d.ts.map +1 -0
  669. package/dist/core/tools/shell-command-parser.js +113 -0
  670. package/dist/core/tools/shell-command-parser.js.map +1 -0
  671. package/dist/core/tools/task-steps.d.ts +2 -0
  672. package/dist/core/tools/task-steps.d.ts.map +1 -1
  673. package/dist/core/tools/task-steps.js +99 -0
  674. package/dist/core/tools/task-steps.js.map +1 -1
  675. package/dist/core/tools/tmux-dispatch.d.ts +3 -5
  676. package/dist/core/tools/tmux-dispatch.d.ts.map +1 -1
  677. package/dist/core/tools/tmux-dispatch.js +4 -4
  678. package/dist/core/tools/tmux-dispatch.js.map +1 -1
  679. package/dist/core/tools/windows-shell-engine.d.ts.map +1 -1
  680. package/dist/core/tools/windows-shell-engine.js +4 -6
  681. package/dist/core/tools/windows-shell-engine.js.map +1 -1
  682. package/dist/core/util/atomic-file.d.ts +6 -2
  683. package/dist/core/util/atomic-file.d.ts.map +1 -1
  684. package/dist/core/util/atomic-file.js +4 -4
  685. package/dist/core/util/atomic-file.js.map +1 -1
  686. package/dist/core/util/bounded-jsonl.d.ts +10 -0
  687. package/dist/core/util/bounded-jsonl.d.ts.map +1 -0
  688. package/dist/core/util/bounded-jsonl.js +75 -0
  689. package/dist/core/util/bounded-jsonl.js.map +1 -0
  690. package/dist/core/util/value-guards.d.ts +5 -0
  691. package/dist/core/util/value-guards.d.ts.map +1 -0
  692. package/dist/core/util/value-guards.js +12 -0
  693. package/dist/core/util/value-guards.js.map +1 -0
  694. package/dist/core/worktree-sync/store.d.ts +3 -3
  695. package/dist/core/worktree-sync/store.d.ts.map +1 -1
  696. package/dist/core/worktree-sync/store.js +10 -5
  697. package/dist/core/worktree-sync/store.js.map +1 -1
  698. package/dist/index.d.ts +15 -4
  699. package/dist/index.d.ts.map +1 -1
  700. package/dist/index.js +14 -3
  701. package/dist/index.js.map +1 -1
  702. package/dist/main.d.ts.map +1 -1
  703. package/dist/main.js +149 -51
  704. package/dist/main.js.map +1 -1
  705. package/dist/migrations.d.ts +4 -6
  706. package/dist/migrations.d.ts.map +1 -1
  707. package/dist/migrations.js +186 -28
  708. package/dist/migrations.js.map +1 -1
  709. package/dist/modes/interactive/auth-dialogs-controller.d.ts +4 -0
  710. package/dist/modes/interactive/auth-dialogs-controller.d.ts.map +1 -1
  711. package/dist/modes/interactive/auth-dialogs-controller.js +60 -1
  712. package/dist/modes/interactive/auth-dialogs-controller.js.map +1 -1
  713. package/dist/modes/interactive/clipboard-input.d.ts +7 -1
  714. package/dist/modes/interactive/clipboard-input.d.ts.map +1 -1
  715. package/dist/modes/interactive/clipboard-input.js +44 -6
  716. package/dist/modes/interactive/clipboard-input.js.map +1 -1
  717. package/dist/modes/interactive/components/activity-lane.d.ts +55 -0
  718. package/dist/modes/interactive/components/activity-lane.d.ts.map +1 -0
  719. package/dist/modes/interactive/components/activity-lane.js +304 -0
  720. package/dist/modes/interactive/components/activity-lane.js.map +1 -0
  721. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  722. package/dist/modes/interactive/components/assistant-message.js +19 -10
  723. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  724. package/dist/modes/interactive/components/expandable-text.d.ts +12 -0
  725. package/dist/modes/interactive/components/expandable-text.d.ts.map +1 -0
  726. package/dist/modes/interactive/components/expandable-text.js +17 -0
  727. package/dist/modes/interactive/components/expandable-text.js.map +1 -0
  728. package/dist/modes/interactive/components/extension-editor.d.ts +15 -1
  729. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  730. package/dist/modes/interactive/components/extension-editor.js +30 -21
  731. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  732. package/dist/modes/interactive/components/extension-input.d.ts +1 -0
  733. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  734. package/dist/modes/interactive/components/extension-input.js +6 -1
  735. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  736. package/dist/modes/interactive/components/scoped-models-selector.d.ts +2 -2
  737. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  738. package/dist/modes/interactive/components/scoped-models-selector.js +23 -14
  739. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  740. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  741. package/dist/modes/interactive/components/settings-selector.js +6 -6
  742. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  743. package/dist/modes/interactive/components/tool-execution.d.ts +19 -11
  744. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  745. package/dist/modes/interactive/components/tool-execution.js +53 -20
  746. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  747. package/dist/modes/interactive/components/tool-group.d.ts.map +1 -1
  748. package/dist/modes/interactive/components/tool-group.js +3 -0
  749. package/dist/modes/interactive/components/tool-group.js.map +1 -1
  750. package/dist/modes/interactive/components/usage-action-selector.d.ts +16 -0
  751. package/dist/modes/interactive/components/usage-action-selector.d.ts.map +1 -0
  752. package/dist/modes/interactive/components/usage-action-selector.js +46 -0
  753. package/dist/modes/interactive/components/usage-action-selector.js.map +1 -0
  754. package/dist/modes/interactive/config-backup.d.ts.map +1 -1
  755. package/dist/modes/interactive/config-backup.js +5 -4
  756. package/dist/modes/interactive/config-backup.js.map +1 -1
  757. package/dist/modes/interactive/extension-ui-host.d.ts +14 -0
  758. package/dist/modes/interactive/extension-ui-host.d.ts.map +1 -1
  759. package/dist/modes/interactive/extension-ui-host.js +77 -15
  760. package/dist/modes/interactive/extension-ui-host.js.map +1 -1
  761. package/dist/modes/interactive/external-editor.d.ts +15 -0
  762. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  763. package/dist/modes/interactive/external-editor.js +27 -19
  764. package/dist/modes/interactive/external-editor.js.map +1 -1
  765. package/dist/modes/interactive/history-reload-math.d.ts +6 -2
  766. package/dist/modes/interactive/history-reload-math.d.ts.map +1 -1
  767. package/dist/modes/interactive/history-reload-math.js +10 -5
  768. package/dist/modes/interactive/history-reload-math.js.map +1 -1
  769. package/dist/modes/interactive/interactive-event-controller.d.ts +74 -0
  770. package/dist/modes/interactive/interactive-event-controller.d.ts.map +1 -0
  771. package/dist/modes/interactive/interactive-event-controller.js +328 -0
  772. package/dist/modes/interactive/interactive-event-controller.js.map +1 -0
  773. package/dist/modes/interactive/interactive-mode.d.ts +22 -24
  774. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  775. package/dist/modes/interactive/interactive-mode.js +245 -595
  776. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  777. package/dist/modes/interactive/key-handlers.d.ts.map +1 -1
  778. package/dist/modes/interactive/key-handlers.js +1 -1
  779. package/dist/modes/interactive/key-handlers.js.map +1 -1
  780. package/dist/modes/interactive/loaded-resources-view.d.ts +20 -0
  781. package/dist/modes/interactive/loaded-resources-view.d.ts.map +1 -0
  782. package/dist/modes/interactive/loaded-resources-view.js +147 -0
  783. package/dist/modes/interactive/loaded-resources-view.js.map +1 -0
  784. package/dist/modes/interactive/profile-menu-controller.d.ts.map +1 -1
  785. package/dist/modes/interactive/profile-menu-controller.js +7 -7
  786. package/dist/modes/interactive/profile-menu-controller.js.map +1 -1
  787. package/dist/modes/interactive/report-commands.d.ts.map +1 -1
  788. package/dist/modes/interactive/report-commands.js +21 -0
  789. package/dist/modes/interactive/report-commands.js.map +1 -1
  790. package/dist/modes/interactive/resource-display.d.ts.map +1 -1
  791. package/dist/modes/interactive/resource-display.js +8 -2
  792. package/dist/modes/interactive/resource-display.js.map +1 -1
  793. package/dist/modes/interactive/resource-shell-commands.d.ts +1 -5
  794. package/dist/modes/interactive/resource-shell-commands.d.ts.map +1 -1
  795. package/dist/modes/interactive/resource-shell-commands.js +0 -5
  796. package/dist/modes/interactive/resource-shell-commands.js.map +1 -1
  797. package/dist/modes/interactive/session-flow-commands.d.ts +27 -8
  798. package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
  799. package/dist/modes/interactive/session-flow-commands.js +150 -64
  800. package/dist/modes/interactive/session-flow-commands.js.map +1 -1
  801. package/dist/modes/interactive/session-io-commands.d.ts.map +1 -1
  802. package/dist/modes/interactive/session-io-commands.js +16 -6
  803. package/dist/modes/interactive/session-io-commands.js.map +1 -1
  804. package/dist/modes/interactive/session-replacement-errors.d.ts +7 -0
  805. package/dist/modes/interactive/session-replacement-errors.d.ts.map +1 -0
  806. package/dist/modes/interactive/session-replacement-errors.js +15 -0
  807. package/dist/modes/interactive/session-replacement-errors.js.map +1 -0
  808. package/dist/modes/interactive/startup-checks.d.ts.map +1 -1
  809. package/dist/modes/interactive/startup-checks.js +1 -1
  810. package/dist/modes/interactive/startup-checks.js.map +1 -1
  811. package/dist/modes/interactive/usage-commands.d.ts +34 -0
  812. package/dist/modes/interactive/usage-commands.d.ts.map +1 -0
  813. package/dist/modes/interactive/usage-commands.js +225 -0
  814. package/dist/modes/interactive/usage-commands.js.map +1 -0
  815. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  816. package/dist/modes/rpc/rpc-mode.js +82 -23
  817. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  818. package/dist/modes/rpc/rpc-types.d.ts +15 -0
  819. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  820. package/dist/modes/rpc/rpc-types.js +138 -1
  821. package/dist/modes/rpc/rpc-types.js.map +1 -1
  822. package/dist/utils/clipboard-image.d.ts.map +1 -1
  823. package/dist/utils/clipboard-image.js +2 -13
  824. package/dist/utils/clipboard-image.js.map +1 -1
  825. package/dist/utils/clipboard-native.d.ts +1 -0
  826. package/dist/utils/clipboard-native.d.ts.map +1 -1
  827. package/dist/utils/clipboard-native.js.map +1 -1
  828. package/dist/utils/clipboard.d.ts +1 -0
  829. package/dist/utils/clipboard.d.ts.map +1 -1
  830. package/dist/utils/clipboard.js +52 -1
  831. package/dist/utils/clipboard.js.map +1 -1
  832. package/dist/utils/platform.d.ts +3 -0
  833. package/dist/utils/platform.d.ts.map +1 -0
  834. package/dist/utils/platform.js +8 -0
  835. package/dist/utils/platform.js.map +1 -0
  836. package/dist/utils/shell.d.ts.map +1 -1
  837. package/dist/utils/shell.js +5 -3
  838. package/dist/utils/shell.js.map +1 -1
  839. package/dist/utils/version-check.d.ts.map +1 -1
  840. package/dist/utils/version-check.js +3 -1
  841. package/dist/utils/version-check.js.map +1 -1
  842. package/dist/utils/work-directory.d.ts +11 -0
  843. package/dist/utils/work-directory.d.ts.map +1 -1
  844. package/dist/utils/work-directory.js +30 -9
  845. package/dist/utils/work-directory.js.map +1 -1
  846. package/docs/UI_POLISH_ORCHESTRATION.md +38 -0
  847. package/docs/UI_QUALITY_ORCHESTRATION.md +28 -0
  848. package/docs/docs.json +4 -0
  849. package/docs/extensions.md +62 -2
  850. package/docs/harness-architecture.md +156 -0
  851. package/docs/keybindings.md +11 -1
  852. package/docs/process-matrix.md +59 -26
  853. package/docs/providers.md +9 -1
  854. package/docs/rpc.md +45 -2
  855. package/docs/sessions.md +15 -0
  856. package/docs/settings.md +125 -11
  857. package/docs/task-steps.md +8 -0
  858. package/docs/telemetry.md +19 -0
  859. package/docs/tmux-agent-manager.md +10 -3
  860. package/docs/ui-reference/README.md +9 -0
  861. package/docs/ui-reference/orchestration-after.txt +14 -0
  862. package/docs/ui-reference/orchestration-before.txt +13 -0
  863. package/docs/ui-reference/orchestration-reference.txt +16 -0
  864. package/docs/usage.md +22 -2
  865. package/docs/work-directory.md +19 -8
  866. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  867. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  868. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  869. package/examples/extensions/question.ts +34 -245
  870. package/examples/extensions/questionnaire.ts +41 -407
  871. package/examples/extensions/sandbox/package-lock.json +2 -2
  872. package/examples/extensions/sandbox/package.json +1 -1
  873. package/examples/extensions/with-deps/package-lock.json +2 -2
  874. package/examples/extensions/with-deps/package.json +1 -1
  875. package/npm-shrinkwrap.json +13 -13
  876. package/package.json +4 -4
  877. package/dist/core/delegation/session-worker-result.d.ts +0 -46
  878. package/dist/core/delegation/session-worker-result.d.ts.map +0 -1
  879. package/dist/core/delegation/session-worker-result.js +0 -113
  880. package/dist/core/delegation/session-worker-result.js.map +0 -1
  881. package/dist/core/delegation/worker-result.d.ts.map +0 -1
  882. package/dist/core/delegation/worker-result.js.map +0 -1
  883. package/dist/core/telemetry.d.ts.map +0 -1
  884. package/dist/core/telemetry.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-vault.js","sourceRoot":"","sources":["../../../src/core/secrets/secret-vault.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { constants, promises as fs, type Stats } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport { managedSecretEnvDir, secretsDir, secretVaultFile } from \"../agent-paths.ts\";\nimport { redactKnownSecrets } from \"../security/secret-text.ts\";\nimport { withFileLock, writeFileAtomic } from \"../util/atomic-file.ts\";\nimport { MAX_DOTENV_DOCUMENT_BYTES, parseDotenvDocument } from \"./secret-dotenv.ts\";\nimport {\n\tassertPassphrase,\n\tcreateVaultKdf,\n\tDEFAULT_SCRYPT_N,\n\tdecryptPayload,\n\tderiveKey,\n\tMANAGED_ENV_HEADER_PREFIX,\n\tMAX_BINDINGS_PER_PROFILE,\n\tMAX_PROFILES,\n\tMAX_VARIABLES_PER_PROFILE,\n\tMAX_VAULT_FILE_BYTES,\n\tparseEnvelope,\n\tprofileSummary,\n\ttype SecretBindingResolution,\n\ttype SecretBindingSummary,\n\ttype SecretEnvDestinationState,\n\ttype SecretMaterializationResult,\n\ttype SecretProfileSummary,\n\ttype SecretRemovalResult,\n\ttype SecretVariableValue,\n\tSecretVaultError,\n\ttype SecretVaultOptions,\n\tsameKdf,\n\tscrubPayload,\n\tserializeEnvelope,\n\tserializeVariableValues,\n\tVAULT_MARKER,\n\ttype VaultKdf,\n\ttype VaultPayload,\n\tvalidateBindingEnvFile,\n\tvalidateBindingWorkspace,\n\tvalidateDescription,\n\tvalidateDotenvProfileDocument,\n\tvalidateProfileId,\n\tvalidateScryptN,\n\tvalidateSecretValue,\n\tvalidateVariableName,\n} from \"./secret-vault-format.ts\";\n\nexport type {\n\tSecretBindingResolution,\n\tSecretBindingSummary,\n\tSecretEnvDestinationState,\n\tSecretMaterializationResult,\n\tSecretProfileSummary,\n\tSecretRemovalResult,\n\tSecretVariableValue,\n\tSecretVaultErrorCode,\n\tSecretVaultOptions,\n} from \"./secret-vault-format.ts\";\nexport {\n\tMAX_BINDINGS_PER_PROFILE,\n\tMAX_VARIABLES_PER_PROFILE,\n\tSECRET_DESCRIPTION_MAX_CHARS,\n\tSECRET_PRINTABLE_METADATA_PATTERN,\n\tSECRET_PROFILE_ID_MAX_CHARS,\n\tSECRET_PROFILE_ID_PATTERN,\n\tSECRET_VARIABLE_NAME_MAX_CHARS,\n\tSECRET_VARIABLE_NAME_PATTERN,\n\tSecretVaultError,\n} from \"./secret-vault-format.ts\";\n\nfunction nodeErrorCode(error: unknown): string | undefined {\n\treturn typeof error === \"object\" && error !== null && \"code\" in error && typeof error.code === \"string\"\n\t\t? error.code\n\t\t: undefined;\n}\n\nasync function lstatIfExists(path: string): Promise<Stats | undefined> {\n\ttry {\n\t\treturn await fs.lstat(path);\n\t} catch (error) {\n\t\tif (nodeErrorCode(error) === \"ENOENT\") return undefined;\n\t\tthrow error;\n\t}\n}\n\nasync function readBoundedRegularFile(\n\tfilePath: string,\n\tmaxBytes: number,\n\tlabel: \"Secret vault\" | \"Dotenv file\",\n): Promise<string> {\n\tconst before = await fs.lstat(filePath);\n\tif (before.isSymbolicLink()) throw new SecretVaultError(\"symlink_refused\", `${label} symlinks are refused.`);\n\tif (!before.isFile()) {\n\t\tthrow new SecretVaultError(\n\t\t\tlabel === \"Secret vault\" ? \"vault_corrupt\" : \"destination_invalid\",\n\t\t\t`${label} path is not a regular file.`,\n\t\t);\n\t}\n\tif (before.size > maxBytes) {\n\t\tthrow new SecretVaultError(\n\t\t\tlabel === \"Secret vault\" ? \"vault_too_large\" : \"invalid_dotenv\",\n\t\t\t`${label} exceeds its ${label === \"Secret vault\" ? \"4 MiB\" : \"512 KiB\"} limit.`,\n\t\t);\n\t}\n\tconst handle = await fs.open(filePath, constants.O_RDONLY);\n\ttry {\n\t\tconst opened = await handle.stat();\n\t\tif ((before.dev !== opened.dev || before.ino !== opened.ino) && before.ino !== 0 && opened.ino !== 0) {\n\t\t\tthrow new SecretVaultError(\"symlink_refused\", \"Secret vault changed while it was being opened.\");\n\t\t}\n\t\tconst output = Buffer.alloc(Math.min(maxBytes + 1, before.size + 1));\n\t\tlet offset = 0;\n\t\twhile (offset < output.byteLength) {\n\t\t\tconst { bytesRead } = await handle.read(output, offset, output.byteLength - offset, null);\n\t\t\tif (bytesRead === 0) break;\n\t\t\toffset += bytesRead;\n\t\t}\n\t\tif (offset > before.size || offset > maxBytes) {\n\t\t\toutput.fill(0);\n\t\t\tthrow new SecretVaultError(\n\t\t\t\tlabel === \"Secret vault\" ? \"vault_too_large\" : \"invalid_dotenv\",\n\t\t\t\t`${label} grew beyond its limit while being read.`,\n\t\t\t);\n\t\t}\n\t\tconst text = output.toString(\"utf8\", 0, offset);\n\t\toutput.fill(0);\n\t\treturn text;\n\t} finally {\n\t\tawait handle.close();\n\t}\n}\n\nasync function readBoundedFile(filePath: string): Promise<string> {\n\treturn readBoundedRegularFile(filePath, MAX_VAULT_FILE_BYTES, \"Secret vault\");\n}\n\nasync function readFilePrefix(filePath: string, maxBytes: number): Promise<string> {\n\tconst handle = await fs.open(filePath, constants.O_RDONLY);\n\ttry {\n\t\tconst output = Buffer.alloc(maxBytes);\n\t\tconst { bytesRead } = await handle.read(output, 0, output.byteLength, 0);\n\t\tconst text = output.toString(\"utf8\", 0, bytesRead);\n\t\toutput.fill(0);\n\t\treturn text;\n\t} finally {\n\t\tawait handle.close();\n\t}\n}\n\nasync function ensurePrivateDirectory(path: string): Promise<void> {\n\tconst existing = await lstatIfExists(path);\n\tif (existing?.isSymbolicLink()) {\n\t\tthrow new SecretVaultError(\"symlink_refused\", \"Secret storage directory symlinks are refused.\");\n\t}\n\tif (existing && !existing.isDirectory()) {\n\t\tthrow new SecretVaultError(\"destination_invalid\", \"Secret storage path is not a directory.\");\n\t}\n\tawait fs.mkdir(path, { recursive: true, mode: 0o700 });\n\tif (process.platform !== \"win32\") await fs.chmod(path, 0o700);\n}\n\nasync function enforcePrivateFileMode(path: string): Promise<void> {\n\tif (process.platform !== \"win32\") await fs.chmod(path, 0o600);\n}\n\ninterface CachedSecretVariable {\n\tname: string;\n\tvalue: string;\n}\n\ninterface CachedSecretProfile {\n\tprofile: string;\n\tbindings: SecretBindingSummary[];\n\tvariables: CachedSecretVariable[];\n}\n\nfunction isPathInside(root: string, target: string): boolean {\n\tconst fromRoot = relative(root, target);\n\treturn fromRoot === \"\" || (!fromRoot.startsWith(`..${sep}`) && fromRoot !== \"..\" && !isAbsolute(fromRoot));\n}\n\nfunction escapeRegExp(value: string): string {\n\treturn value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Encrypted generic credential vault. Only the derived key is retained in memory, until this\n * process explicitly locks the vault or exits. The native model-facing tool receives summaries,\n * never decrypted values or materialization paths.\n */\nexport class SecretVault {\n\treadonly vaultPath: string;\n\treadonly materializedDir: string;\n\tprivate readonly rootDir: string;\n\tprivate readonly scryptN: number;\n\tprivate readonly now: () => Date;\n\tprivate readonly onEnvironmentChanged: (() => void) | undefined;\n\tprivate cachedKey: Buffer | undefined;\n\tprivate cachedKdf: VaultKdf | undefined;\n\tprivate cachedProfiles: CachedSecretProfile[] = [];\n\tprivate readonly activeProfilesByWorkspace = new Map<string, string>();\n\n\tconstructor(options: SecretVaultOptions) {\n\t\tthis.rootDir = secretsDir(options.agentDir);\n\t\tthis.vaultPath = secretVaultFile(options.agentDir);\n\t\tthis.materializedDir = managedSecretEnvDir(options.agentDir);\n\t\tthis.scryptN = validateScryptN(options.scryptN ?? DEFAULT_SCRYPT_N);\n\t\tthis.now = options.now ?? (() => new Date());\n\t\tthis.onEnvironmentChanged = options.onEnvironmentChanged;\n\t}\n\n\tstatic forAgentDir(agentDir: string): SecretVault {\n\t\treturn new SecretVault({ agentDir });\n\t}\n\n\tget isUnlocked(): boolean {\n\t\treturn this.cachedKey !== undefined;\n\t}\n\n\tasync exists(): Promise<boolean> {\n\t\tconst existing = await lstatIfExists(this.vaultPath);\n\t\tif (existing?.isSymbolicLink()) {\n\t\t\tthrow new SecretVaultError(\"symlink_refused\", \"Secret vault symlinks are refused.\");\n\t\t}\n\t\treturn existing !== undefined;\n\t}\n\n\tlock(): void {\n\t\tthis.cachedKey?.fill(0);\n\t\tthis.cachedKey = undefined;\n\t\tthis.cachedKdf = undefined;\n\t\tthis.clearSecretCache();\n\t\tthis.activeProfilesByWorkspace.clear();\n\t\tthis.notifyEnvironmentChanged();\n\t}\n\n\t/** Environment for the nearest explicitly activated profile covering cwd. */\n\tgetEnvironmentForCwd(cwd: string): NodeJS.ProcessEnv {\n\t\tconst match = this.resolveCachedProfile(cwd);\n\t\tif (!match) return {};\n\t\treturn Object.fromEntries(match.profile.variables.map((variable) => [variable.name, variable.value]));\n\t}\n\n\thasEnvironmentForCwd(cwd: string): boolean {\n\t\treturn this.resolveCachedProfile(cwd) !== undefined;\n\t}\n\n\t/** Remove exact unlocked vault values and high-confidence credential shapes from model-facing text. */\n\tredactSensitiveText(text: string): string {\n\t\tlet redacted = redactKnownSecrets(text);\n\t\tconst values = [\n\t\t\t...new Set(\n\t\t\t\tthis.cachedProfiles\n\t\t\t\t\t.flatMap((profile) => profile.variables.map((variable) => variable.value))\n\t\t\t\t\t.filter(Boolean),\n\t\t\t),\n\t\t].sort((left, right) => right.length - left.length);\n\t\tfor (const value of values) {\n\t\t\tif (value.length >= 4) {\n\t\t\t\tredacted = redacted.split(value).join(\"[REDACTED]\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst bounded = new RegExp(`(^|[\\\\s=:;,])${escapeRegExp(value)}(?=$|[\\\\s,;])`, \"g\");\n\t\t\tredacted = redacted.replace(bounded, (_match, prefix: string) => `${prefix}[REDACTED]`);\n\t\t}\n\t\treturn redacted;\n\t}\n\n\tasync initialize(passphrase: string): Promise<void> {\n\t\tassertPassphrase(passphrase, true);\n\t\tawait ensurePrivateDirectory(this.rootDir);\n\t\tawait withFileLock(this.vaultPath, async () => {\n\t\t\tif (await lstatIfExists(this.vaultPath)) {\n\t\t\t\tthrow new SecretVaultError(\"already_initialized\", \"Secret vault is already initialized.\");\n\t\t\t}\n\t\t\tconst kdf = createVaultKdf(this.scryptN);\n\t\t\tconst key = await deriveKey(passphrase, kdf);\n\t\t\tconst payload: VaultPayload = { marker: VAULT_MARKER, profiles: [] };\n\t\t\ttry {\n\t\t\t\tawait this.writeEnvelope(kdf, payload, key);\n\t\t\t\tthis.replaceCachedKey(key, kdf);\n\t\t\t} catch (error) {\n\t\t\t\tkey.fill(0);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t});\n\t}\n\n\tasync unlock(passphrase: string): Promise<void> {\n\t\tassertPassphrase(passphrase, false);\n\t\tif (!(await this.exists())) throw new SecretVaultError(\"not_initialized\", \"Secret vault is not initialized.\");\n\t\tconst envelope = parseEnvelope(await readBoundedFile(this.vaultPath));\n\t\tconst key = await deriveKey(passphrase, envelope.kdf);\n\t\tlet payload: VaultPayload | undefined;\n\t\ttry {\n\t\t\tconst environmentBefore = this.activeEnvironmentFingerprint();\n\t\t\tpayload = decryptPayload(envelope.payload, key);\n\t\t\tthis.replaceCachedKey(key, envelope.kdf);\n\t\t\tthis.refreshSecretCache(payload);\n\t\t\tif (environmentBefore !== this.activeEnvironmentFingerprint()) this.notifyEnvironmentChanged();\n\t\t} catch (error) {\n\t\t\tkey.fill(0);\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\tif (payload) scrubPayload(payload);\n\t\t}\n\t}\n\n\tasync listProfiles(): Promise<SecretProfileSummary[]> {\n\t\treturn this.withPayload((payload) => payload.profiles.map(profileSummary), false);\n\t}\n\n\tasync upsertProfile(\n\t\tprofile: string,\n\t\tdescription: string | undefined,\n\t\tvalues: readonly SecretVariableValue[],\n\t): Promise<SecretProfileSummary> {\n\t\tif (values.length === 0) {\n\t\t\tthrow new SecretVaultError(\"invalid_variable\", \"At least one environment variable is required.\");\n\t\t}\n\t\tconst seenNames = new Set<string>();\n\t\tconst normalizedValues = values.map((entry) => {\n\t\t\tconst name = validateVariableName(entry.name);\n\t\t\tif (seenNames.has(name)) {\n\t\t\t\tthrow new SecretVaultError(\"invalid_variable\", `Environment variable ${name} is duplicated.`);\n\t\t\t}\n\t\t\tseenNames.add(name);\n\t\t\treturn { name, value: validateSecretValue(entry.value) };\n\t\t});\n\t\treturn this.storeProfileDocument(\n\t\t\tprofile,\n\t\t\tdescription,\n\t\t\tserializeVariableValues(normalizedValues),\n\t\t\tundefined,\n\t\t\ttrue,\n\t\t);\n\t}\n\n\tasync replaceProfileDocument(\n\t\tprofile: string,\n\t\tdescription: string | undefined,\n\t\tdocument: string,\n\t\tbinding?: { workspace: string; envFile: string },\n\t): Promise<SecretProfileSummary> {\n\t\treturn this.storeProfileDocument(profile, description, document, binding, false);\n\t}\n\n\tasync getProfileDocument(profile: string): Promise<string | undefined> {\n\t\tconst normalizedProfile = validateProfileId(profile);\n\t\treturn this.withPayload(\n\t\t\t(payload) => payload.profiles.find((candidate) => candidate.profile === normalizedProfile)?.dotenv,\n\t\t\tfalse,\n\t\t);\n\t}\n\n\tasync readOwnerDotenv(destination: string): Promise<string> {\n\t\tthis.assertDestination(destination);\n\t\treturn readBoundedRegularFile(destination, MAX_DOTENV_DOCUMENT_BYTES, \"Dotenv file\");\n\t}\n\n\tasync removeProfile(profile: string, variableNames?: readonly string[]): Promise<SecretRemovalResult> {\n\t\tconst normalizedProfile = validateProfileId(profile);\n\t\tconst normalizedNames = variableNames?.map(validateVariableName);\n\t\tif (normalizedNames && new Set(normalizedNames).size !== normalizedNames.length) {\n\t\t\tthrow new SecretVaultError(\"invalid_variable\", \"Environment variable removals are duplicated.\");\n\t\t}\n\t\tlet managedMaterializationRemoved = false;\n\t\tlet boundMaterializationsRemoved = 0;\n\t\tconst result = await this.withPayload(async (payload) => {\n\t\t\tconst index = payload.profiles.findIndex((candidate) => candidate.profile === normalizedProfile);\n\t\t\tconst record = payload.profiles[index];\n\t\t\tif (!record) throw new SecretVaultError(\"profile_missing\", \"Secret profile does not exist.\");\n\t\t\tconst variables = validateDotenvProfileDocument(record.dotenv).variables;\n\t\t\tlet removedProfile: boolean;\n\t\t\tlet removedVariableNames: string[];\n\t\t\tlet remaining: SecretVariableValue[] = [];\n\t\t\tif (normalizedNames === undefined) {\n\t\t\t\tremovedProfile = true;\n\t\t\t\tremovedVariableNames = variables.map((variable) => variable.name);\n\t\t\t} else {\n\t\t\t\tif (normalizedNames.length === 0) {\n\t\t\t\t\tthrow new SecretVaultError(\"invalid_variable\", \"Select at least one environment variable to remove.\");\n\t\t\t\t}\n\t\t\t\tconst requested = new Set(normalizedNames);\n\t\t\t\tremovedVariableNames = variables\n\t\t\t\t\t.filter((variable) => requested.has(variable.name))\n\t\t\t\t\t.map((variable) => variable.name);\n\t\t\t\tif (removedVariableNames.length !== requested.size) {\n\t\t\t\t\tthrow new SecretVaultError(\n\t\t\t\t\t\t\"invalid_variable\",\n\t\t\t\t\t\t\"One or more requested environment variables do not exist.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tremaining = variables.filter((variable) => !requested.has(variable.name));\n\t\t\t\tremovedProfile = remaining.length === 0;\n\t\t\t}\n\n\t\t\t// Validate the complete mutation before removing any recoverable materialization.\n\t\t\tmanagedMaterializationRemoved = await this.removeManagedMaterialization(normalizedProfile);\n\t\t\tboundMaterializationsRemoved = await this.removeBoundMaterializations(record);\n\t\t\tif (removedProfile) payload.profiles.splice(index, 1);\n\t\t\telse {\n\t\t\t\trecord.dotenv = serializeVariableValues(remaining);\n\t\t\t\trecord.updatedAt = this.now().toISOString();\n\t\t\t}\n\t\t\treturn { removedProfile, removedVariableNames };\n\t\t}, true);\n\t\tthis.deactivateProfile(normalizedProfile);\n\t\treturn {\n\t\t\tprofile: normalizedProfile,\n\t\t\t...result,\n\t\t\tmanagedMaterializationRemoved,\n\t\t\tboundMaterializationsRemoved,\n\t\t};\n\t}\n\n\tgetManagedEnvPath(profile: string): string {\n\t\treturn join(this.materializedDir, `${validateProfileId(profile)}.env`);\n\t}\n\n\tresolveBindingTarget(\n\t\tworkspace: string,\n\t\tenvFile: string,\n\t): {\n\t\tworkspace: string;\n\t\tenvFile: string;\n\t\tdestination: string;\n\t} {\n\t\tconst normalizedWorkspace = validateBindingWorkspace(resolve(workspace));\n\t\tconst normalizedEnvFile = validateBindingEnvFile(envFile);\n\t\tconst destination = resolve(normalizedWorkspace, normalizedEnvFile);\n\t\tif (!isPathInside(normalizedWorkspace, destination)) {\n\t\t\tthrow new SecretVaultError(\"destination_invalid\", \"Credential target must stay inside its workspace.\");\n\t\t}\n\t\treturn { workspace: normalizedWorkspace, envFile: normalizedEnvFile, destination };\n\t}\n\n\tasync resolveBindingForWorkspace(cwd: string, profile?: string): Promise<SecretBindingResolution> {\n\t\tconst normalizedCwd = resolve(cwd);\n\t\tconst normalizedProfile = profile === undefined ? undefined : validateProfileId(profile);\n\t\treturn this.withPayload((payload) => {\n\t\t\tconst matches = payload.profiles.flatMap((candidate) => {\n\t\t\t\tif (normalizedProfile !== undefined && candidate.profile !== normalizedProfile) return [];\n\t\t\t\tconst binding = candidate.bindings\n\t\t\t\t\t.filter((entry) => isPathInside(entry.workspace, normalizedCwd))\n\t\t\t\t\t.sort((left, right) => right.workspace.length - left.workspace.length)[0];\n\t\t\t\tif (!binding) return [];\n\t\t\t\treturn [{ candidate, binding }];\n\t\t\t});\n\t\t\tif (matches.length === 0) {\n\t\t\t\tthrow new SecretVaultError(\n\t\t\t\t\t\"binding_missing\",\n\t\t\t\t\tnormalizedProfile\n\t\t\t\t\t\t? `Secret profile ${normalizedProfile} is not bound to this workspace.`\n\t\t\t\t\t\t: \"No secret profile is bound to this workspace.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst longestRoot = Math.max(...matches.map((match) => match.binding.workspace.length));\n\t\t\tconst nearest = matches.filter((match) => match.binding.workspace.length === longestRoot);\n\t\t\tlet selected = nearest[0];\n\t\t\tif (nearest.length > 1) {\n\t\t\t\tconst active = nearest.find(\n\t\t\t\t\t(match) => this.activeProfilesByWorkspace.get(match.binding.workspace) === match.candidate.profile,\n\t\t\t\t);\n\t\t\t\tif (!active) {\n\t\t\t\t\tthrow new SecretVaultError(\n\t\t\t\t\t\t\"ambiguous_binding\",\n\t\t\t\t\t\t\"Multiple secret profiles apply to this workspace; select one by profile name.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tselected = active;\n\t\t\t}\n\t\t\tconst parsed = validateDotenvProfileDocument(selected.candidate.dotenv);\n\t\t\treturn {\n\t\t\t\tprofile: selected.candidate.profile,\n\t\t\t\t...selected.binding,\n\t\t\t\tdestination: resolve(selected.binding.workspace, selected.binding.envFile),\n\t\t\t\tvariableNames: parsed.variables.map((variable) => variable.name),\n\t\t\t};\n\t\t}, false);\n\t}\n\n\tasync inspectEnvDestination(destination: string, profile: string): Promise<SecretEnvDestinationState> {\n\t\tvalidateProfileId(profile);\n\t\tthis.assertDestination(destination);\n\t\tconst existing = await lstatIfExists(destination);\n\t\tif (!existing) return \"missing\";\n\t\tif (existing.isSymbolicLink()) {\n\t\t\tthrow new SecretVaultError(\"symlink_refused\", \"Secret dotenv destination symlinks are refused.\");\n\t\t}\n\t\tif (!existing.isFile()) {\n\t\t\tthrow new SecretVaultError(\"destination_invalid\", \"Secret dotenv destination is not a regular file.\");\n\t\t}\n\t\tconst firstLine = (await readFilePrefix(destination, 512)).split(/\\r?\\n/, 1)[0] ?? \"\";\n\t\tif (firstLine === `${MANAGED_ENV_HEADER_PREFIX}${profile}`) return \"managed-profile\";\n\t\tif (firstLine.startsWith(MANAGED_ENV_HEADER_PREFIX)) return \"managed-other\";\n\t\treturn \"unmanaged\";\n\t}\n\n\tasync materializeEnv(\n\t\tprofile: string,\n\t\tdestination: string,\n\t\toptions: {\n\t\t\tactivationWorkspace?: string;\n\t\t\tallowReplaceUnmanaged?: boolean;\n\t\t\texpectedUnmanagedContent?: string;\n\t\t\tmanaged?: boolean;\n\t\t} = {},\n\t): Promise<SecretMaterializationResult> {\n\t\tconst normalizedProfile = validateProfileId(profile);\n\t\tthis.assertDestination(destination);\n\t\tconst previousState = await this.inspectEnvDestination(destination, normalizedProfile);\n\t\tawait this.assertReplaceableDestination(destination, previousState, options);\n\t\tif (options.managed) {\n\t\t\tif (resolve(destination) !== resolve(this.getManagedEnvPath(normalizedProfile))) {\n\t\t\t\tthrow new SecretVaultError(\"destination_invalid\", \"Managed dotenv destination is not canonical.\");\n\t\t\t}\n\t\t\tawait ensurePrivateDirectory(this.materializedDir);\n\t\t} else {\n\t\t\tconst parent = await lstatIfExists(dirname(destination));\n\t\t\tif (!parent?.isDirectory()) {\n\t\t\t\tthrow new SecretVaultError(\"destination_invalid\", \"Dotenv destination directory does not exist.\");\n\t\t\t}\n\t\t}\n\t\treturn this.withPayload(async (payload) => {\n\t\t\tconst record = payload.profiles.find((candidate) => candidate.profile === normalizedProfile);\n\t\t\tif (!record) throw new SecretVaultError(\"profile_missing\", \"Secret profile does not exist.\");\n\t\t\tconst binding = record.bindings.find(\n\t\t\t\t(candidate) => resolve(candidate.workspace, candidate.envFile) === resolve(destination),\n\t\t\t);\n\t\t\tconst activationCwd = options.activationWorkspace ? resolve(options.activationWorkspace) : undefined;\n\t\t\tconst activationBinding = activationCwd\n\t\t\t\t? record.bindings\n\t\t\t\t\t\t.filter((candidate) => isPathInside(candidate.workspace, activationCwd))\n\t\t\t\t\t\t.sort((left, right) => right.workspace.length - left.workspace.length)[0]\n\t\t\t\t: binding;\n\t\t\tif (activationCwd && !activationBinding) {\n\t\t\t\tthrow new SecretVaultError(\n\t\t\t\t\t\"binding_missing\",\n\t\t\t\t\t`Secret profile ${normalizedProfile} is not bound to this workspace.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (binding && !options.managed) await this.assertBoundDestinationParent(binding, destination);\n\t\t\tconst currentState = await this.inspectEnvDestination(destination, normalizedProfile);\n\t\t\tawait this.assertReplaceableDestination(destination, currentState, options);\n\t\t\tconst variableNames = validateDotenvProfileDocument(record.dotenv).variables.map((variable) => variable.name);\n\t\t\tconst body = record.dotenv.endsWith(\"\\n\") ? record.dotenv : `${record.dotenv}\\n`;\n\t\t\tlet dotenv = `${MANAGED_ENV_HEADER_PREFIX}${normalizedProfile}\\n# Generated by Pi. Do not edit, inspect, source as shell code, or commit.\\n${body}`;\n\t\t\ttry {\n\t\t\t\tawait writeFileAtomic(destination, dotenv, { mode: 0o600 });\n\t\t\t\tawait enforcePrivateFileMode(destination);\n\t\t\t\tif (activationBinding) {\n\t\t\t\t\tthis.activeProfilesByWorkspace.set(activationBinding.workspace, normalizedProfile);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tdotenv = \"\";\n\t\t\t}\n\t\t\treturn { profile: normalizedProfile, variableNames, previousState: currentState };\n\t\t}, false);\n\t}\n\n\tprivate async storeProfileDocument(\n\t\tprofile: string,\n\t\tdescription: string | undefined,\n\t\tdocument: string,\n\t\tbinding: { workspace: string; envFile: string } | undefined,\n\t\tmerge: boolean,\n\t): Promise<SecretProfileSummary> {\n\t\tconst normalizedProfile = validateProfileId(profile);\n\t\tconst normalizedDescription = validateDescription(description);\n\t\tconst parsedDocument = validateDotenvProfileDocument(document);\n\t\tconst target = binding ? this.resolveBindingTarget(binding.workspace, binding.envFile) : undefined;\n\t\tconst normalizedBinding = target ? { workspace: target.workspace, envFile: target.envFile } : undefined;\n\n\t\tconst summary = await this.withPayload(async (payload) => {\n\t\t\tlet record = payload.profiles.find((candidate) => candidate.profile === normalizedProfile);\n\t\t\tconst timestamp = this.now().toISOString();\n\t\t\tif (!record && payload.profiles.length >= MAX_PROFILES) {\n\t\t\t\tthrow new SecretVaultError(\"profile_limit\", `Secret vault supports at most ${MAX_PROFILES} profiles.`);\n\t\t\t}\n\t\t\tconst nextBindings = record?.bindings.map((entry) => ({ ...entry })) ?? [];\n\t\t\tif (normalizedBinding) {\n\t\t\t\tconst next = { ...normalizedBinding, updatedAt: timestamp };\n\t\t\t\tconst existingIndex = nextBindings.findIndex((entry) => entry.workspace === normalizedBinding.workspace);\n\t\t\t\tif (existingIndex === -1) nextBindings.push(next);\n\t\t\t\telse nextBindings[existingIndex] = next;\n\t\t\t\tif (nextBindings.length > MAX_BINDINGS_PER_PROFILE) {\n\t\t\t\t\tthrow new SecretVaultError(\n\t\t\t\t\t\t\"profile_limit\",\n\t\t\t\t\t\t`A secret profile supports at most ${MAX_BINDINGS_PER_PROFILE} workspace bindings.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet nextDocument = parsedDocument.document;\n\t\t\tif (merge && record) {\n\t\t\t\tconst merged = new Map(\n\t\t\t\t\tvalidateDotenvProfileDocument(record.dotenv).variables.map((variable) => [\n\t\t\t\t\t\tvariable.name,\n\t\t\t\t\t\tvariable.value,\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t\tfor (const variable of parsedDocument.variables) merged.set(variable.name, variable.value);\n\t\t\t\tif (merged.size > MAX_VARIABLES_PER_PROFILE) {\n\t\t\t\t\tthrow new SecretVaultError(\n\t\t\t\t\t\t\"variable_limit\",\n\t\t\t\t\t\t`A secret profile supports at most ${MAX_VARIABLES_PER_PROFILE} variables.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tnextDocument = serializeVariableValues([...merged].map(([name, value]) => ({ name, value })));\n\t\t\t}\n\n\t\t\tif (record) {\n\t\t\t\tawait this.removeManagedMaterialization(normalizedProfile);\n\t\t\t\tawait this.removeBoundMaterializations(record);\n\t\t\t} else {\n\t\t\t\trecord = {\n\t\t\t\t\tprofile: normalizedProfile,\n\t\t\t\t\tcreatedAt: timestamp,\n\t\t\t\t\tupdatedAt: timestamp,\n\t\t\t\t\tdotenv: nextDocument,\n\t\t\t\t\tbindings: [],\n\t\t\t\t};\n\t\t\t\tpayload.profiles.push(record);\n\t\t\t}\n\t\t\tif (normalizedDescription !== undefined) record.description = normalizedDescription;\n\t\t\trecord.dotenv = nextDocument;\n\t\t\trecord.bindings = nextBindings.sort(\n\t\t\t\t(left, right) => left.workspace.localeCompare(right.workspace) || left.envFile.localeCompare(right.envFile),\n\t\t\t);\n\t\t\trecord.updatedAt = timestamp;\n\t\t\tpayload.profiles.sort((left, right) => left.profile.localeCompare(right.profile));\n\t\t\treturn profileSummary(record);\n\t\t}, true);\n\t\tthis.deactivateProfile(normalizedProfile);\n\t\treturn summary;\n\t}\n\n\tprivate async assertReplaceableDestination(\n\t\tdestination: string,\n\t\tstate: SecretEnvDestinationState,\n\t\toptions: { allowReplaceUnmanaged?: boolean; expectedUnmanagedContent?: string },\n\t): Promise<void> {\n\t\tif (state === \"managed-other\") {\n\t\t\tthrow new SecretVaultError(\n\t\t\t\t\"destination_conflict\",\n\t\t\t\t\"Destination already contains a file managed for another secret profile.\",\n\t\t\t);\n\t\t}\n\t\tif (state !== \"unmanaged\") return;\n\t\tif (!options.allowReplaceUnmanaged || options.expectedUnmanagedContent === undefined) {\n\t\t\tthrow new SecretVaultError(\n\t\t\t\t\"destination_conflict\",\n\t\t\t\t\"Destination already contains an unmanaged file that was not reviewed for replacement.\",\n\t\t\t);\n\t\t}\n\t\tif ((await this.readOwnerDotenv(destination)) !== options.expectedUnmanagedContent) {\n\t\t\tthrow new SecretVaultError(\n\t\t\t\t\"destination_conflict\",\n\t\t\t\t\"The reviewed dotenv file changed before replacement and was preserved.\",\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate async assertBoundDestinationParent(binding: SecretBindingSummary, destination: string): Promise<void> {\n\t\ttry {\n\t\t\tconst [workspace, parent] = await Promise.all([\n\t\t\t\tfs.realpath(binding.workspace),\n\t\t\t\tfs.realpath(dirname(destination)),\n\t\t\t]);\n\t\t\tif (isPathInside(workspace, parent)) return;\n\t\t} catch {\n\t\t\t// Collapse filesystem detail so a model-facing failure cannot disclose unrelated paths.\n\t\t}\n\t\tthrow new SecretVaultError(\n\t\t\t\"destination_invalid\",\n\t\t\t\"Credential destination resolves outside its bound workspace or cannot be verified.\",\n\t\t);\n\t}\n\n\tprivate assertDestination(destination: string): void {\n\t\tif (!isAbsolute(destination) || resolve(destination) === resolve(this.vaultPath)) {\n\t\t\tthrow new SecretVaultError(\n\t\t\t\t\"destination_invalid\",\n\t\t\t\t\"Secret dotenv destination must be an absolute non-vault path.\",\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate replaceCachedKey(key: Buffer, kdf: VaultKdf): void {\n\t\tthis.cachedKey?.fill(0);\n\t\tthis.cachedKey = key;\n\t\tthis.cachedKdf = { ...kdf };\n\t}\n\n\tprivate clearSecretCache(): void {\n\t\tfor (const profile of this.cachedProfiles) {\n\t\t\tfor (const variable of profile.variables) variable.value = \"\";\n\t\t}\n\t\tthis.cachedProfiles = [];\n\t}\n\n\tprivate deactivateProfile(profile: string): void {\n\t\tlet changed = false;\n\t\tfor (const [workspace, activeProfile] of this.activeProfilesByWorkspace) {\n\t\t\tif (activeProfile !== profile) continue;\n\t\t\tthis.activeProfilesByWorkspace.delete(workspace);\n\t\t\tchanged = true;\n\t\t}\n\t\tconst cached = this.cachedProfiles.find((candidate) => candidate.profile === profile);\n\t\tif (cached) {\n\t\t\tfor (const variable of cached.variables) variable.value = \"\";\n\t\t\tcached.variables = [];\n\t\t}\n\t\tif (changed) this.notifyEnvironmentChanged();\n\t}\n\n\tprivate notifyEnvironmentChanged(): void {\n\t\ttry {\n\t\t\tthis.onEnvironmentChanged?.();\n\t\t} catch {\n\t\t\t// Credential state changes remain authoritative even if host cleanup is best-effort.\n\t\t}\n\t}\n\n\tprivate activeEnvironmentFingerprint(): string {\n\t\tconst hash = createHash(\"sha256\");\n\t\tfor (const profile of this.cachedProfiles) {\n\t\t\tconst activeBindings = profile.bindings\n\t\t\t\t.filter((binding) => this.activeProfilesByWorkspace.get(binding.workspace) === profile.profile)\n\t\t\t\t.sort((left, right) => left.workspace.localeCompare(right.workspace));\n\t\t\tif (activeBindings.length === 0) continue;\n\t\t\thash.update(`${profile.profile.length}:${profile.profile}`);\n\t\t\tfor (const binding of activeBindings) hash.update(`${binding.workspace.length}:${binding.workspace}`);\n\t\t\tfor (const variable of profile.variables) {\n\t\t\t\thash.update(`${variable.name.length}:${variable.name}${variable.value.length}:${variable.value}`);\n\t\t\t}\n\t\t}\n\t\treturn hash.digest(\"hex\");\n\t}\n\n\tprivate refreshSecretCache(payload: VaultPayload): void {\n\t\tthis.clearSecretCache();\n\t\tthis.cachedProfiles = payload.profiles.map((profile) => ({\n\t\t\tprofile: profile.profile,\n\t\t\tbindings: profile.bindings.map((binding) => ({ ...binding })),\n\t\t\tvariables: profile.bindings.some(\n\t\t\t\t(binding) => this.activeProfilesByWorkspace.get(binding.workspace) === profile.profile,\n\t\t\t)\n\t\t\t\t? parseDotenvDocument(profile.dotenv).variables.map((variable) => ({ ...variable }))\n\t\t\t\t: [],\n\t\t}));\n\t\tfor (const [workspace, profile] of this.activeProfilesByWorkspace) {\n\t\t\tconst stillBound = this.cachedProfiles.some(\n\t\t\t\t(candidate) =>\n\t\t\t\t\tcandidate.profile === profile && candidate.bindings.some((binding) => binding.workspace === workspace),\n\t\t\t);\n\t\t\tif (!stillBound) this.activeProfilesByWorkspace.delete(workspace);\n\t\t}\n\t}\n\n\tprivate resolveCachedProfile(\n\t\tcwd: string,\n\t): { profile: CachedSecretProfile; binding: SecretBindingSummary } | undefined {\n\t\tconst resolvedCwd = resolve(cwd);\n\t\treturn this.cachedProfiles\n\t\t\t.flatMap((profile) => {\n\t\t\t\tconst binding = profile.bindings\n\t\t\t\t\t.filter((candidate) => isPathInside(candidate.workspace, resolvedCwd))\n\t\t\t\t\t.sort((left, right) => right.workspace.length - left.workspace.length)[0];\n\t\t\t\treturn binding ? [{ profile, binding }] : [];\n\t\t\t})\n\t\t\t.filter((match) => this.activeProfilesByWorkspace.get(match.binding.workspace) === match.profile.profile)\n\t\t\t.sort((left, right) => right.binding.workspace.length - left.binding.workspace.length)[0];\n\t}\n\n\tprivate requireUnlocked(): { key: Buffer; kdf: VaultKdf } {\n\t\tif (!this.cachedKey || !this.cachedKdf) {\n\t\t\tthrow new SecretVaultError(\"not_unlocked\", \"Secret vault is locked.\");\n\t\t}\n\t\treturn { key: this.cachedKey, kdf: this.cachedKdf };\n\t}\n\n\tprivate async withPayload<T>(operation: (payload: VaultPayload) => T | Promise<T>, write: boolean): Promise<T> {\n\t\treturn withFileLock(this.vaultPath, async () => {\n\t\t\tconst environmentBefore = this.activeEnvironmentFingerprint();\n\t\t\tconst { key, kdf } = this.requireUnlocked();\n\t\t\tif (!(await lstatIfExists(this.vaultPath))) {\n\t\t\t\tthrow new SecretVaultError(\"not_initialized\", \"Secret vault is not initialized.\");\n\t\t\t}\n\t\t\tconst envelope = parseEnvelope(await readBoundedFile(this.vaultPath));\n\t\t\tif (!sameKdf(kdf, envelope.kdf)) {\n\t\t\t\tthis.lock();\n\t\t\t\tthrow new SecretVaultError(\"unlock_failed\", \"Secret vault changed and must be unlocked again.\");\n\t\t\t}\n\t\t\tconst payload = decryptPayload(envelope.payload, key);\n\t\t\ttry {\n\t\t\t\tconst result = await operation(payload);\n\t\t\t\tif (write) await this.writeEnvelope(kdf, payload, key);\n\t\t\t\tthis.refreshSecretCache(payload);\n\t\t\t\tif (environmentBefore !== this.activeEnvironmentFingerprint()) this.notifyEnvironmentChanged();\n\t\t\t\treturn result;\n\t\t\t} finally {\n\t\t\t\tscrubPayload(payload);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate async writeEnvelope(kdf: VaultKdf, payload: VaultPayload, key: Buffer): Promise<void> {\n\t\tlet serialized = serializeEnvelope(kdf, payload, key);\n\t\ttry {\n\t\t\tawait writeFileAtomic(this.vaultPath, serialized, { mode: 0o600 });\n\t\t\tawait enforcePrivateFileMode(this.vaultPath);\n\t\t} finally {\n\t\t\tserialized = \"\";\n\t\t}\n\t}\n\n\tprivate async removeBoundMaterializations(record: {\n\t\tprofile: string;\n\t\tbindings: SecretBindingSummary[];\n\t}): Promise<number> {\n\t\tlet removed = 0;\n\t\tfor (const binding of record.bindings) {\n\t\t\tconst destination = resolve(binding.workspace, binding.envFile);\n\t\t\tconst existing = await lstatIfExists(destination);\n\t\t\tif (!existing) continue;\n\t\t\tconst state = await this.inspectEnvDestination(destination, record.profile);\n\t\t\tif (state !== \"managed-profile\") continue;\n\t\t\tawait fs.unlink(destination);\n\t\t\tremoved++;\n\t\t}\n\t\treturn removed;\n\t}\n\n\tprivate async removeManagedMaterialization(profile: string): Promise<boolean> {\n\t\tconst path = this.getManagedEnvPath(profile);\n\t\tconst existing = await lstatIfExists(path);\n\t\tif (!existing) return false;\n\t\tif (existing.isSymbolicLink()) {\n\t\t\tthrow new SecretVaultError(\"symlink_refused\", \"Managed dotenv symlinks are refused.\");\n\t\t}\n\t\tif (!existing.isFile()) {\n\t\t\tthrow new SecretVaultError(\"destination_invalid\", \"Managed dotenv path is not a regular file.\");\n\t\t}\n\t\tconst state = await this.inspectEnvDestination(path, profile);\n\t\tif (state !== \"managed-profile\") return false;\n\t\tawait fs.unlink(path);\n\t\treturn true;\n\t}\n}\n"]}
@@ -7,36 +7,17 @@
7
7
  * subtree spend" (footer roll-up, print-mode child reporting), the daily cross-session totals, the
8
8
  * /context window estimate, and HTML/JSONL export of the current branch.
9
9
  */
10
- import type { AgentMessage, AgentState } from "@caupulican/pi-agent-core";
10
+ import { type AgentMessage, type AgentState } from "@caupulican/pi-agent-core";
11
11
  import { type SessionManager } from "@caupulican/pi-agent-core/node";
12
- import type { Model, ToolArgumentExecutionOutcome, ToolArgumentTeachState, ToolArgumentValidationTelemetryEvent, Usage } from "@caupulican/pi-ai";
13
- import { type SessionStats, type SpawnedUsageTotals } from "./agent-session.ts";
12
+ import type { Model, Usage } from "@caupulican/pi-ai";
13
+ import { type SessionStats, type SpawnedUsageTotals } from "./agent-session-contracts.ts";
14
14
  import { type SessionCostSummary } from "./cost/cost-summary.ts";
15
15
  import { type DailyUsageTotals } from "./cost/daily-usage.ts";
16
16
  import type { ContextUsage, ToolDefinition } from "./extensions/index.ts";
17
17
  import type { SettingsManager } from "./settings-manager.ts";
18
18
  import { type ToolArgumentValidationLogRecord } from "./tool-recovery-log-records.ts";
19
+ import { type ToolArgumentValidationStats } from "./tool-recovery-stats.ts";
19
20
  export declare const TOOL_ARGUMENT_VALIDATION_CUSTOM_TYPE = "tool_argument_validation";
20
- export interface ToolArgumentValidationTeachEfficacy {
21
- recurrenceBefore: number;
22
- recurrenceAfter: number;
23
- repairedThenSucceeded: number;
24
- repairedThenFailed: number;
25
- repairedThenNotRun: number;
26
- }
27
- export interface ToolArgumentValidationStats {
28
- clean: number;
29
- repaired: number;
30
- bounced: number;
31
- failureModes: Record<string, number>;
32
- repairsApplied: Record<string, number>;
33
- taught: Record<ToolArgumentTeachState, number>;
34
- executionOutcome: Record<ToolArgumentExecutionOutcome, number>;
35
- teachEfficacy: Record<string, ToolArgumentValidationTeachEfficacy>;
36
- }
37
- export interface ToolArgumentValidationRecord extends ToolArgumentValidationTelemetryEvent {
38
- version: 1;
39
- }
40
21
  export interface SessionAnalyticsDeps {
41
22
  /** Live agent state — assistant-message usage and message counts are read from here. */
42
23
  getState(): AgentState;
@@ -1 +1 @@
1
- {"version":3,"file":"session-analytics.d.ts","sourceRoot":"","sources":["../../src/core/session-analytics.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Session usage / cost / stats accounting, context-window usage, and session export.\n *\n * Extracted verbatim from agent-session.ts (god-file decomposition). Read-only over the session\n * except for its two owned memo caches (`_spawnedUsageCache`, `_dailyUsageCache`) — it never mutates\n * agent or session state. Single source of truth for \"how much did this session and its spawned\n * subtree spend\" (footer roll-up, print-mode child reporting), the daily cross-session totals, the\n * /context window estimate, and HTML/JSONL export of the current branch.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { AgentMessage, AgentState } from \"@caupulican/pi-agent-core\";\nimport {\n\tCURRENT_SESSION_VERSION,\n\tcalculateContextTokens,\n\testimateContextTokens,\n\tgetLatestCompactionEntry,\n\ttype SessionEntry,\n\ttype SessionHeader,\n\ttype SessionManager,\n} from \"@caupulican/pi-agent-core/node\";\nimport type {\n\tAssistantMessage,\n\tModel,\n\tToolArgumentExecutionOutcome,\n\tToolArgumentTeachState,\n\tToolArgumentValidationTelemetryEvent,\n\tUsage,\n} from \"@caupulican/pi-ai\";\nimport { getSessionsDir } from \"../config.ts\";\nimport { theme } from \"../modes/interactive/theme/theme.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport {\n\ttype SessionStats,\n\tSPAWNED_USAGE_CUSTOM_TYPE,\n\ttype SpawnedUsageReport,\n\ttype SpawnedUsageTotals,\n} from \"./agent-session.ts\";\nimport {\n\taccumulateCurrentSessionCostsFromEntries,\n\ttype CurrentSessionCostAccumulator,\n\tcreateCurrentSessionCostAccumulator,\n\tcreateSessionCostSummary,\n\ttype SessionCostSummary,\n} from \"./cost/cost-summary.ts\";\nimport {\n\taggregateDailyUsageFromSessionFiles,\n\taggregateDailyUsageFromSessionRoot,\n\ttype DailyUsageTotals,\n\tformatDailyUsageBreakdown,\n\tgetLocalDayWindow,\n} from \"./cost/daily-usage.ts\";\nimport { exportSessionToHtml, type ToolHtmlRenderer } from \"./export-html/index.ts\";\nimport { createToolHtmlRenderer } from \"./export-html/tool-renderer.ts\";\nimport type { ContextUsage, ToolDefinition } from \"./extensions/index.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\nimport {\n\tisToolArgumentValidationLogRecord,\n\ttype ToolArgumentValidationLogRecord,\n} from \"./tool-recovery-log-records.ts\";\nimport {\n\tconsumeToolArgumentValidationRecord,\n\tcreateEmptyToolArgumentValidationStats,\n\tgetToolRecoveryRecordSequence,\n\treadPersistedToolRecoveryStats,\n} from \"./tool-recovery-stats.ts\";\n\nexport const TOOL_ARGUMENT_VALIDATION_CUSTOM_TYPE = \"tool_argument_validation\";\n\nexport interface ToolArgumentValidationTeachEfficacy {\n\trecurrenceBefore: number;\n\trecurrenceAfter: number;\n\trepairedThenSucceeded: number;\n\trepairedThenFailed: number;\n\trepairedThenNotRun: number;\n}\n\nexport interface ToolArgumentValidationStats {\n\tclean: number;\n\trepaired: number;\n\tbounced: number;\n\tfailureModes: Record<string, number>;\n\trepairsApplied: Record<string, number>;\n\ttaught: Record<ToolArgumentTeachState, number>;\n\texecutionOutcome: Record<ToolArgumentExecutionOutcome, number>;\n\tteachEfficacy: Record<string, ToolArgumentValidationTeachEfficacy>;\n}\n\nexport interface ToolArgumentValidationRecord extends ToolArgumentValidationTelemetryEvent {\n\tversion: 1;\n}\n\nexport interface SessionAnalyticsDeps {\n\t/** Live agent state — assistant-message usage and message counts are read from here. */\n\tgetState(): AgentState;\n\t/** All messages (agent state view) — used for context-window estimation and last-assistant text. */\n\tgetMessages(): AgentMessage[];\n\t/** Current session model — its context window bounds the /context estimate. */\n\tgetModel(): Model<any> | undefined;\n\t/** Session log — entries feed spawned-usage roll-up, daily totals, branch export. */\n\tgetSessionManager(): SessionManager;\n\t/** Settings — the export theme is read here. */\n\tgetSettingsManager(): SettingsManager;\n\t/** Resolve a tool definition for the HTML export's custom-tool renderer. */\n\tgetToolDefinition(name: string): ToolDefinition | undefined;\n\t/** Sidecar recovery telemetry log; read on demand so turn handling never writes session custom entries. */\n\tgetToolRecoveryEventLogPath(): string;\n}\n\nexport class SessionAnalytics {\n\t/** Incremental aggregate over append-ordered session entries. */\n\tprivate _currentSessionCostCache?: {\n\t\tentryCount: number;\n\t\taccumulator: CurrentSessionCostAccumulator;\n\t};\n\t/** Memoized daily usage totals with a short TTL, keyed by the resolved scope dir and local-day window. */\n\tprivate _dailyUsageCache?: {\n\t\tsessionDir: string;\n\t\twindowStartMs: number;\n\t\twindowEndMs: number;\n\t\texpiresAt: number;\n\t\ttotals: DailyUsageTotals;\n\t};\n\t/** Memoized full cost summary. The footer renders on every streamed delta and keystroke, so\n\t * rescanning a long session log there turns redraw into O(entries) work per frame. */\n\tprivate _costSummaryCache?: {\n\t\tentryCount: number;\n\t\tdailyTotals: DailyUsageTotals;\n\t\twindowStartMs: number;\n\t\twindowEndMs: number;\n\t\tsummary: SessionCostSummary;\n\t};\n\t/** Cumulative stats initialized once from persisted telemetry, then updated without retaining record details. */\n\tprivate _toolArgumentValidationStats: ToolArgumentValidationStats | undefined;\n\t/** Incremental context-usage state keyed by the append-only branch leaf. */\n\tprivate _postCompactionUsageCache?: {\n\t\tleafId: string | null;\n\t\thasCompaction: boolean;\n\t\thasPostCompactionUsage: boolean;\n\t};\n\n\tprivate readonly deps: SessionAnalyticsDeps;\n\n\tconstructor(deps: SessionAnalyticsDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\tgetSessionStats(): SessionStats {\n\t\tconst state = this.deps.getState();\n\t\tconst userMessages = state.messages.filter((m) => m.role === \"user\").length;\n\t\tconst assistantMessages = state.messages.filter((m) => m.role === \"assistant\").length;\n\t\tconst toolResults = state.messages.filter((m) => m.role === \"toolResult\").length;\n\n\t\tlet toolCalls = 0;\n\t\tlet totalInput = 0;\n\t\tlet totalOutput = 0;\n\t\tlet totalCacheRead = 0;\n\t\tlet totalCacheWrite = 0;\n\t\tlet totalCost = 0;\n\n\t\tfor (const message of state.messages) {\n\t\t\tif (message.role === \"assistant\") {\n\t\t\t\tconst assistantMsg = message as AssistantMessage;\n\t\t\t\ttoolCalls += assistantMsg.content.filter((c) => c.type === \"toolCall\").length;\n\t\t\t\ttotalInput += assistantMsg.usage.input;\n\t\t\t\ttotalOutput += assistantMsg.usage.output;\n\t\t\t\ttotalCacheRead += assistantMsg.usage.cacheRead;\n\t\t\t\ttotalCacheWrite += assistantMsg.usage.cacheWrite;\n\t\t\t\ttotalCost += assistantMsg.usage.cost.total;\n\t\t\t}\n\t\t}\n\n\t\tconst toolArgumentValidation = this.getToolArgumentValidationStats();\n\t\tconst compactionGates = this.getCompactionGateStats();\n\n\t\treturn {\n\t\t\tsessionFile: this.deps.getSessionManager().getSessionFile(),\n\t\t\tsessionId: this.deps.getSessionManager().getSessionId(),\n\t\t\tuserMessages,\n\t\t\tassistantMessages,\n\t\t\ttoolCalls,\n\t\t\ttoolResults,\n\t\t\ttotalMessages: state.messages.length,\n\t\t\ttokens: {\n\t\t\t\tinput: totalInput,\n\t\t\t\toutput: totalOutput,\n\t\t\t\tcacheRead: totalCacheRead,\n\t\t\t\tcacheWrite: totalCacheWrite,\n\t\t\t\ttotal: totalInput + totalOutput + totalCacheRead + totalCacheWrite,\n\t\t\t},\n\t\t\tcost: totalCost,\n\t\t\tcontextUsage: this.getContextUsage(),\n\t\t\ttoolArgumentValidation,\n\t\t\tcompactionGates,\n\t\t};\n\t}\n\n\tgetCompactionGateStats(): SessionStats[\"compactionGates\"] {\n\t\tlet gateFailures = 0;\n\t\tlet deterministicGapFills = 0;\n\t\tlet compactionsWithGateFailures = 0;\n\t\tfor (const entry of this.deps.getSessionManager().getEntries()) {\n\t\t\tif (entry.type !== \"compaction\") continue;\n\t\t\tconst details = entry.details;\n\t\t\tif (!details || typeof details !== \"object\") continue;\n\t\t\tconst rawGateFailures = (details as { verificationGateFailures?: unknown }).verificationGateFailures;\n\t\t\tconst rawGapFills = (details as { deterministicGapFills?: unknown }).deterministicGapFills;\n\t\t\tconst entryGateFailures =\n\t\t\t\ttypeof rawGateFailures === \"number\" && Number.isFinite(rawGateFailures) ? rawGateFailures : 0;\n\t\t\tconst entryGapFills = typeof rawGapFills === \"number\" && Number.isFinite(rawGapFills) ? rawGapFills : 0;\n\t\t\tgateFailures += entryGateFailures;\n\t\t\tdeterministicGapFills += entryGapFills;\n\t\t\tif (entryGateFailures > 0) compactionsWithGateFailures++;\n\t\t}\n\t\treturn { gateFailures, deterministicGapFills, compactionsWithGateFailures };\n\t}\n\n\trecordToolArgumentValidation(record: ToolArgumentValidationLogRecord): void {\n\t\tconst stats = this.getToolArgumentValidationStats();\n\t\tconsumeToolArgumentValidationRecord(stats, record);\n\t\tthis._toolArgumentValidationStats = stats;\n\t}\n\n\tprivate readToolArgumentValidationSidecarRecords(): ToolArgumentValidationLogRecord[] {\n\t\tconst filePath = this.deps.getToolRecoveryEventLogPath();\n\t\tif (!existsSync(filePath)) return [];\n\t\tconst records: ToolArgumentValidationLogRecord[] = [];\n\t\ttry {\n\t\t\tconst sessionId = this.deps.getSessionManager().getSessionId();\n\t\t\tfor (const line of readFileSync(filePath, \"utf-8\").split(\"\\n\")) {\n\t\t\t\tif (line.trim().length === 0) continue;\n\t\t\t\tconst parsed = JSON.parse(line) as unknown;\n\t\t\t\tif (!isToolArgumentValidationLogRecord(parsed) || parsed.sessionId !== sessionId) continue;\n\t\t\t\trecords.push(parsed);\n\t\t\t}\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t\treturn records;\n\t}\n\n\tgetToolArgumentValidationStats(): ToolArgumentValidationStats {\n\t\tif (this._toolArgumentValidationStats) return structuredClone(this._toolArgumentValidationStats);\n\t\tconst eventLogPath = this.deps.getToolRecoveryEventLogPath();\n\t\tconst sessionId = this.deps.getSessionManager().getSessionId();\n\t\tconst persisted = readPersistedToolRecoveryStats(eventLogPath, sessionId);\n\t\tconst stats = persisted ? structuredClone(persisted.stats) : createEmptyToolArgumentValidationStats();\n\t\tconst seen = new Set<string>();\n\t\tconst consume = (record: ToolArgumentValidationRecord, key: string): void => {\n\t\t\tif (seen.has(key)) return;\n\t\t\tseen.add(key);\n\t\t\tconsumeToolArgumentValidationRecord(stats, record);\n\t\t};\n\n\t\tfor (const entry of this.deps.getSessionManager().getEntries()) {\n\t\t\tif (entry.type !== \"custom\" || entry.customType !== TOOL_ARGUMENT_VALIDATION_CUSTOM_TYPE) continue;\n\t\t\tconst record = entry.data as ToolArgumentValidationRecord | undefined;\n\t\t\tif (!record || record.version !== 1) continue;\n\t\t\tconsume(record, `legacy:${entry.id}`);\n\t\t}\n\t\tfor (const record of this.readToolArgumentValidationSidecarRecords()) {\n\t\t\tif (\n\t\t\t\tpersisted &&\n\t\t\t\trecord.sessionId === sessionId &&\n\t\t\t\tgetToolRecoveryRecordSequence(record) <= persisted.lastRecordSequence\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconsume(record, record.recordId);\n\t\t}\n\n\t\tthis._toolArgumentValidationStats = stats;\n\t\treturn structuredClone(stats);\n\t}\n\n\t/**\n\t * Cumulative usage (full breakdown) for this session's entire spawn subtree: its own\n\t * assistant messages PLUS every `spawned_usage` report it has rolled up. Single source of\n\t * truth for \"how much did this session and everything it spawned spend\" — used by print-mode\n\t * to emit a child's total so a spawner can roll it up via {@link addSpawnedUsage}.\n\t *\n\t * Including the `spawned_usage` reports is what keeps the single-hop invariant intact: a child\n\t * that itself spawned grandchildren must report own + sub-usage in one number, or the parent\n\t * silently under-counts the grandchildren.\n\t */\n\tgetCumulativeUsage(): Usage {\n\t\tlet input = 0;\n\t\tlet output = 0;\n\t\tlet cacheRead = 0;\n\t\tlet cacheWrite = 0;\n\t\tlet totalTokens = 0;\n\t\tlet costInput = 0;\n\t\tlet costOutput = 0;\n\t\tlet costCacheRead = 0;\n\t\tlet costCacheWrite = 0;\n\t\tlet costTotal = 0;\n\t\tconst add = (usage: Usage) => {\n\t\t\tinput += usage.input;\n\t\t\toutput += usage.output;\n\t\t\tcacheRead += usage.cacheRead;\n\t\t\tcacheWrite += usage.cacheWrite;\n\t\t\ttotalTokens += usage.totalTokens;\n\t\t\tcostInput += usage.cost.input;\n\t\t\tcostOutput += usage.cost.output;\n\t\t\tcostCacheRead += usage.cost.cacheRead;\n\t\t\tcostCacheWrite += usage.cost.cacheWrite;\n\t\t\tcostTotal += usage.cost.total;\n\t\t};\n\t\tfor (const message of this.deps.getState().messages) {\n\t\t\tif (message.role !== \"assistant\") continue;\n\t\t\tconst usage = (message as AssistantMessage).usage;\n\t\t\tif (!usage) continue;\n\t\t\tadd(usage);\n\t\t}\n\t\t// Roll up usage this session attributed to its own spawned children (single-hop).\n\t\tconst seenSpawnedReportIds = new Set<string>();\n\t\tfor (const entry of this.deps.getSessionManager().getEntries()) {\n\t\t\tif (entry.type !== \"custom\" || entry.customType !== SPAWNED_USAGE_CUSTOM_TYPE) continue;\n\t\t\tconst data = entry.data as SpawnedUsageReport | undefined;\n\t\t\tif (!data?.usage) continue;\n\t\t\tif (data.reportId) {\n\t\t\t\tif (seenSpawnedReportIds.has(data.reportId)) continue;\n\t\t\t\tseenSpawnedReportIds.add(data.reportId);\n\t\t\t}\n\t\t\tadd(data.usage);\n\t\t}\n\t\treturn {\n\t\t\tinput,\n\t\t\toutput,\n\t\t\tcacheRead,\n\t\t\tcacheWrite,\n\t\t\ttotalTokens,\n\t\t\tcost: {\n\t\t\t\tinput: costInput,\n\t\t\t\toutput: costOutput,\n\t\t\t\tcacheRead: costCacheRead,\n\t\t\t\tcacheWrite: costCacheWrite,\n\t\t\t\ttotal: costTotal,\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Record usage spent by a spawned/subagent session so the footer can roll it into the\n\t * displayed cost. Persisted as a `CustomEntry` (`customType: \"spawned_usage\"`, Model A) so\n\t * it survives reload and is reconstructed exactly like main usage; a new/forked session\n\t * starts fresh because it owns a new log file.\n\t *\n\t * Idempotent on `opts.reportId`: a re-report (retry, duplicate `agent_end`) with a\n\t * previously-seen id is ignored, so cost cannot be double-counted. Honors the single-hop\n\t * invariant documented on {@link SpawnedUsageReport}.\n\t *\n\t * @returns the id of the appended entry, or `undefined` if the report was a duplicate.\n\t */\n\taddSpawnedUsage(\n\t\tusage: Usage,\n\t\topts?: { label?: string; sourceSessionId?: string; reportId?: string },\n\t): string | undefined {\n\t\tconst reportId = opts?.reportId;\n\t\tif (reportId && this.getCurrentSessionCostTotals().seenSubagentReportIds.has(reportId)) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst report: SpawnedUsageReport = {\n\t\t\tusage,\n\t\t\tlabel: opts?.label,\n\t\t\tsourceSessionId: opts?.sourceSessionId,\n\t\t\treportId,\n\t\t};\n\t\tconst entryId = this.deps.getSessionManager().appendCustomEntry(SPAWNED_USAGE_CUSTOM_TYPE, report);\n\t\tif (reportId) this.getCurrentSessionCostTotals();\n\t\treturn entryId;\n\t}\n\n\tprivate getCurrentSessionCostTotals(): CurrentSessionCostAccumulator {\n\t\tconst sessionManager = this.deps.getSessionManager();\n\t\tconst entryCount = sessionManager.getEntryCount?.() ?? sessionManager.getEntries().length;\n\t\tlet cache = this._currentSessionCostCache;\n\t\tconst getEntriesSince = sessionManager.getEntriesSince?.bind(sessionManager);\n\t\tif (!cache || entryCount < cache.entryCount || !getEntriesSince) {\n\t\t\tcache = {\n\t\t\t\tentryCount,\n\t\t\t\taccumulator: accumulateCurrentSessionCostsFromEntries(\n\t\t\t\t\tcreateCurrentSessionCostAccumulator(),\n\t\t\t\t\tsessionManager.getEntries(),\n\t\t\t\t),\n\t\t\t};\n\t\t\tthis._currentSessionCostCache = cache;\n\t\t} else if (entryCount > cache.entryCount) {\n\t\t\taccumulateCurrentSessionCostsFromEntries(cache.accumulator, getEntriesSince(cache.entryCount));\n\t\t\tcache.entryCount = entryCount;\n\t\t}\n\t\treturn cache.accumulator;\n\t}\n\n\t/**\n\t * Aggregate all recorded spawned-usage reports (see {@link addSpawnedUsage}). The append-ordered\n\t * accumulator processes only new entries, so repeated turns do not rescan the full session.\n\t */\n\tgetSpawnedUsage(): SpawnedUsageTotals {\n\t\tconst current = this.getCurrentSessionCostTotals();\n\t\treturn { cost: current.subagentCost, reports: current.subagentReports };\n\t}\n\n\tgetCostSummary(now = new Date()): SessionCostSummary {\n\t\tconst sessionManager = this.deps.getSessionManager();\n\t\tconst entryCount = sessionManager.getEntryCount?.() ?? sessionManager.getEntries().length;\n\t\tconst window = getLocalDayWindow(now);\n\t\tconst dailyTotals = this.getDailyUsageTotals(now);\n\t\tconst cached = this._costSummaryCache;\n\t\tif (\n\t\t\tcached?.entryCount === entryCount &&\n\t\t\tcached.dailyTotals === dailyTotals &&\n\t\t\tcached.windowStartMs === window.startMs &&\n\t\t\tcached.windowEndMs === window.endMs\n\t\t) {\n\t\t\treturn cached.summary;\n\t\t}\n\t\tconst summary = createSessionCostSummary({\n\t\t\tcurrentTotals: this.getCurrentSessionCostTotals(),\n\t\t\tdailyTotals,\n\t\t\ttodayWindow: window,\n\t\t});\n\t\tthis._costSummaryCache = {\n\t\t\tentryCount,\n\t\t\tdailyTotals,\n\t\t\twindowStartMs: window.startMs,\n\t\t\twindowEndMs: window.endMs,\n\t\t\tsummary,\n\t\t};\n\t\treturn summary;\n\t}\n\n\tgetDailyUsageTotals(now = new Date()): DailyUsageTotals {\n\t\tconst sessionManager = this.deps.getSessionManager();\n\t\tconst sessionDir = sessionManager.getSessionDir();\n\t\tconst scope = sessionManager.usesDefaultSessionDir() ? getSessionsDir() : sessionDir;\n\t\tconst nowMs = now.getTime();\n\t\tconst window = getLocalDayWindow(now);\n\t\tif (\n\t\t\tthis._dailyUsageCache?.sessionDir === scope &&\n\t\t\tthis._dailyUsageCache.windowStartMs === window.startMs &&\n\t\t\tthis._dailyUsageCache.windowEndMs === window.endMs &&\n\t\t\tthis._dailyUsageCache.expiresAt > nowMs\n\t\t) {\n\t\t\treturn this._dailyUsageCache.totals;\n\t\t}\n\t\tconst sessionFile = sessionManager.getSessionFile();\n\t\tconst liveSession = sessionFile ? { filePath: sessionFile, entries: sessionManager.getEntries() } : undefined;\n\t\tconst totals = sessionManager.usesDefaultSessionDir()\n\t\t\t? aggregateDailyUsageFromSessionRoot(scope, window, liveSession)\n\t\t\t: aggregateDailyUsageFromSessionFiles(sessionDir, window, liveSession);\n\t\tthis._dailyUsageCache = {\n\t\t\tsessionDir: scope,\n\t\t\twindowStartMs: window.startMs,\n\t\t\twindowEndMs: window.endMs,\n\t\t\texpiresAt: Math.min(nowMs + 10_000, window.endMs),\n\t\t\ttotals,\n\t\t};\n\t\treturn totals;\n\t}\n\n\tgetDailyUsageBreakdown(formatLabel?: (label: string) => string, now = new Date()): string {\n\t\treturn formatDailyUsageBreakdown(this.getDailyUsageTotals(now), formatLabel);\n\t}\n\n\tprivate getPostCompactionUsageState(): { hasCompaction: boolean; hasPostCompactionUsage: boolean } {\n\t\tconst sessionManager = this.deps.getSessionManager();\n\t\tconst indexedSessionManager = sessionManager as unknown as {\n\t\t\tgetLeafId?: () => string | null;\n\t\t\tgetEntry?: (id: string) => SessionEntry | undefined;\n\t\t};\n\t\tconst getLeafId = indexedSessionManager.getLeafId?.bind(sessionManager);\n\t\tconst getEntry = indexedSessionManager.getEntry?.bind(sessionManager);\n\t\tconst leafId = getLeafId?.();\n\t\tif (getLeafId && getEntry && leafId !== undefined) {\n\t\t\tif (this._postCompactionUsageCache?.leafId === leafId) {\n\t\t\t\treturn { ...this._postCompactionUsageCache };\n\t\t\t}\n\t\t\tconst appended: SessionEntry[] = [];\n\t\t\tconst cachedLeafId = this._postCompactionUsageCache?.leafId;\n\t\t\tlet currentId = leafId;\n\t\t\tconst seen = new Set<string>();\n\t\t\twhile (currentId !== null && currentId !== cachedLeafId && !seen.has(currentId)) {\n\t\t\t\tseen.add(currentId);\n\t\t\t\tconst entry = getEntry(currentId);\n\t\t\t\tif (!entry) break;\n\t\t\t\tappended.push(entry);\n\t\t\t\tcurrentId = entry.parentId;\n\t\t\t}\n\t\t\tconst extendsCachedBranch = this._postCompactionUsageCache !== undefined && currentId === cachedLeafId;\n\t\t\tconst state = extendsCachedBranch\n\t\t\t\t? { ...this._postCompactionUsageCache! }\n\t\t\t\t: { leafId: null, hasCompaction: false, hasPostCompactionUsage: false };\n\t\t\tif (!extendsCachedBranch && currentId !== null) {\n\t\t\t\twhile (currentId !== null && !seen.has(currentId)) {\n\t\t\t\t\tseen.add(currentId);\n\t\t\t\t\tconst entry = getEntry(currentId);\n\t\t\t\t\tif (!entry) break;\n\t\t\t\t\tappended.push(entry);\n\t\t\t\t\tcurrentId = entry.parentId;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (let index = appended.length - 1; index >= 0; index--) {\n\t\t\t\tconst entry = appended[index];\n\t\t\t\tif (entry.type === \"compaction\") {\n\t\t\t\t\tstate.hasCompaction = true;\n\t\t\t\t\tstate.hasPostCompactionUsage = false;\n\t\t\t\t} else if (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\t\t\tconst assistant = entry.message;\n\t\t\t\t\tif (assistant.stopReason !== \"aborted\" && assistant.stopReason !== \"error\" && state.hasCompaction) {\n\t\t\t\t\t\tstate.hasPostCompactionUsage = calculateContextTokens(assistant.usage) > 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tstate.leafId = leafId;\n\t\t\tthis._postCompactionUsageCache = state;\n\t\t\treturn { ...state };\n\t\t}\n\n\t\tconst branchEntries = sessionManager.getBranch();\n\t\tconst latestCompaction = getLatestCompactionEntry(branchEntries);\n\t\tif (!latestCompaction) return { hasCompaction: false, hasPostCompactionUsage: false };\n\t\tconst compactionIndex = branchEntries.lastIndexOf(latestCompaction);\n\t\tfor (let index = branchEntries.length - 1; index > compactionIndex; index--) {\n\t\t\tconst entry = branchEntries[index];\n\t\t\tif (entry.type !== \"message\" || entry.message.role !== \"assistant\") continue;\n\t\t\tconst assistant = entry.message;\n\t\t\tif (assistant.stopReason === \"aborted\" || assistant.stopReason === \"error\") continue;\n\t\t\treturn { hasCompaction: true, hasPostCompactionUsage: calculateContextTokens(assistant.usage) > 0 };\n\t\t}\n\t\treturn { hasCompaction: true, hasPostCompactionUsage: false };\n\t}\n\n\tgetContextUsage(): ContextUsage | undefined {\n\t\tconst model = this.deps.getModel();\n\t\tif (!model) return undefined;\n\n\t\tconst contextWindow = model.contextWindow ?? 0;\n\t\tif (contextWindow <= 0) return undefined;\n\n\t\t// After compaction, the last assistant usage reflects pre-compaction context size.\n\t\t// Walk backward only to the nearest compaction instead of rebuilding the whole branch on\n\t\t// every footer invalidation; the distance is bounded by the live post-compaction context.\n\t\tconst compactionState = this.getPostCompactionUsageState();\n\t\tif (compactionState.hasCompaction && !compactionState.hasPostCompactionUsage) {\n\t\t\treturn { tokens: null, contextWindow, percent: null };\n\t\t}\n\n\t\tconst estimate = estimateContextTokens(this.deps.getMessages());\n\t\tconst percent = (estimate.tokens / contextWindow) * 100;\n\n\t\treturn {\n\t\t\ttokens: estimate.tokens,\n\t\t\tcontextWindow,\n\t\t\tpercent,\n\t\t};\n\t}\n\n\t/**\n\t * Export session to HTML.\n\t * @param outputPath Optional output path (defaults to session directory)\n\t * @returns Path to exported file\n\t */\n\tasync exportToHtml(outputPath?: string): Promise<string> {\n\t\tconst sessionManager = this.deps.getSessionManager();\n\t\tconst themeName = this.deps.getSettingsManager().getTheme();\n\n\t\t// Create tool renderer if we have an extension runner (for custom tool HTML rendering)\n\t\tconst toolRenderer: ToolHtmlRenderer = createToolHtmlRenderer({\n\t\t\tgetToolDefinition: (name) => this.deps.getToolDefinition(name),\n\t\t\ttheme,\n\t\t\tcwd: sessionManager.getCwd(),\n\t\t});\n\n\t\treturn await exportSessionToHtml(sessionManager, this.deps.getState(), {\n\t\t\toutputPath,\n\t\t\tthemeName,\n\t\t\ttoolRenderer,\n\t\t});\n\t}\n\n\t/**\n\t * Export the current session branch to a JSONL file.\n\t * Writes the session header followed by all entries on the current branch path.\n\t * @param outputPath Target file path. If omitted, generates a timestamped file in cwd.\n\t * @returns The resolved output file path.\n\t */\n\texportToJsonl(outputPath?: string): string {\n\t\tconst sessionManager = this.deps.getSessionManager();\n\t\tconst filePath = resolvePath(\n\t\t\toutputPath ?? `session-${new Date().toISOString().replace(/[:.]/g, \"-\")}.jsonl`,\n\t\t\tprocess.cwd(),\n\t\t);\n\t\tconst dir = dirname(filePath);\n\t\tif (!existsSync(dir)) {\n\t\t\tmkdirSync(dir, { recursive: true });\n\t\t}\n\n\t\tconst header: SessionHeader = {\n\t\t\ttype: \"session\",\n\t\t\tversion: CURRENT_SESSION_VERSION,\n\t\t\tid: sessionManager.getSessionId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tcwd: sessionManager.getCwd(),\n\t\t};\n\n\t\tconst branchEntries = sessionManager.getBranch();\n\t\tconst lines = [JSON.stringify(header)];\n\n\t\t// Re-chain parentIds to form a linear sequence\n\t\tlet prevId: string | null = null;\n\t\tfor (const entry of branchEntries) {\n\t\t\tconst linear = { ...entry, parentId: prevId };\n\t\t\tlines.push(JSON.stringify(linear));\n\t\t\tprevId = entry.id;\n\t\t}\n\n\t\twriteFileSync(filePath, `${lines.join(\"\\n\")}\\n`);\n\t\treturn filePath;\n\t}\n\n\t/**\n\t * Get text content of last assistant message.\n\t * Useful for /copy command.\n\t * @returns Text content, or undefined if no assistant message exists\n\t */\n\tgetLastAssistantText(): string | undefined {\n\t\tconst lastAssistant = this.deps\n\t\t\t.getMessages()\n\t\t\t.slice()\n\t\t\t.reverse()\n\t\t\t.find((m) => {\n\t\t\t\tif (m.role !== \"assistant\") return false;\n\t\t\t\tconst msg = m as AssistantMessage;\n\t\t\t\t// Skip aborted messages with no content\n\t\t\t\tif (msg.stopReason === \"aborted\" && msg.content.length === 0) return false;\n\t\t\t\treturn true;\n\t\t\t});\n\n\t\tif (!lastAssistant) return undefined;\n\n\t\tlet text = \"\";\n\t\tfor (const content of (lastAssistant as AssistantMessage).content) {\n\t\t\tif (content.type === \"text\") {\n\t\t\t\ttext += content.text;\n\t\t\t}\n\t\t}\n\n\t\treturn text.trim() || undefined;\n\t}\n}\n"]}
1
+ {"version":3,"file":"session-analytics.d.ts","sourceRoot":"","sources":["../../src/core/session-analytics.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Session usage / cost / stats accounting, context-window usage, and session export.\n *\n * Extracted verbatim from agent-session.ts (god-file decomposition). Read-only over the session\n * except for its two owned memo caches (`_spawnedUsageCache`, `_dailyUsageCache`) — it never mutates\n * agent or session state. Single source of truth for \"how much did this session and its spawned\n * subtree spend\" (footer roll-up, print-mode child reporting), the daily cross-session totals, the\n * /context window estimate, and HTML/JSONL export of the current branch.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport {\n\ttype AgentMessage,\n\ttype AgentState,\n\taddUsage,\n\tcreateEmptyUsage,\n\tgetSessionEntryUsage,\n} from \"@caupulican/pi-agent-core\";\nimport {\n\tCURRENT_SESSION_VERSION,\n\tcalculateContextTokens,\n\testimateContextTokens,\n\tgetLatestCompactionEntry,\n\ttype SessionEntry,\n\ttype SessionHeader,\n\ttype SessionManager,\n} from \"@caupulican/pi-agent-core/node\";\nimport type { AssistantMessage, Model, Usage } from \"@caupulican/pi-ai\";\nimport { getSessionsDir } from \"../config.ts\";\nimport { theme } from \"../modes/interactive/theme/theme.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport {\n\ttype CompactionGateCheckStats,\n\ttype SessionStats,\n\tSPAWNED_USAGE_CUSTOM_TYPE,\n\ttype SpawnedUsageReport,\n\ttype SpawnedUsageTotals,\n} from \"./agent-session-contracts.ts\";\nimport {\n\taccumulateCurrentSessionCostsFromEntries,\n\ttype CurrentSessionCostAccumulator,\n\tcreateCurrentSessionCostAccumulator,\n\tcreateSessionCostSummary,\n\ttype SessionCostSummary,\n} from \"./cost/cost-summary.ts\";\nimport {\n\taggregateDailyUsageFromSessionFiles,\n\taggregateDailyUsageFromSessionRoot,\n\ttype DailyUsageTotals,\n\tformatDailyUsageBreakdown,\n\tgetLocalDayWindow,\n} from \"./cost/daily-usage.ts\";\nimport { exportSessionToHtml, type ToolHtmlRenderer } from \"./export-html/index.ts\";\nimport { createToolHtmlRenderer } from \"./export-html/tool-renderer.ts\";\nimport type { ContextUsage, ToolDefinition } from \"./extensions/index.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\nimport {\n\tisToolArgumentValidationLogRecord,\n\ttype ToolArgumentValidationLogRecord,\n} from \"./tool-recovery-log-records.ts\";\nimport {\n\tconsumeToolArgumentValidationRecord,\n\tcreateEmptyToolArgumentValidationStats,\n\tgetToolRecoveryRecordSequence,\n\treadPersistedToolRecoveryStats,\n\ttype ToolArgumentValidationRecord,\n\ttype ToolArgumentValidationStats,\n} from \"./tool-recovery-stats.ts\";\n\nexport const TOOL_ARGUMENT_VALIDATION_CUSTOM_TYPE = \"tool_argument_validation\";\n\nexport interface SessionAnalyticsDeps {\n\t/** Live agent state — assistant-message usage and message counts are read from here. */\n\tgetState(): AgentState;\n\t/** All messages (agent state view) — used for context-window estimation and last-assistant text. */\n\tgetMessages(): AgentMessage[];\n\t/** Current session model — its context window bounds the /context estimate. */\n\tgetModel(): Model<any> | undefined;\n\t/** Session log — entries feed spawned-usage roll-up, daily totals, branch export. */\n\tgetSessionManager(): SessionManager;\n\t/** Settings — the export theme is read here. */\n\tgetSettingsManager(): SettingsManager;\n\t/** Resolve a tool definition for the HTML export's custom-tool renderer. */\n\tgetToolDefinition(name: string): ToolDefinition | undefined;\n\t/** Sidecar recovery telemetry log; read on demand so turn handling never writes session custom entries. */\n\tgetToolRecoveryEventLogPath(): string;\n}\n\nexport class SessionAnalytics {\n\t/** Incremental aggregate over append-ordered session entries. */\n\tprivate _currentSessionCostCache?: {\n\t\tentryCount: number;\n\t\taccumulator: CurrentSessionCostAccumulator;\n\t};\n\t/** Memoized daily usage totals with a short TTL, keyed by the resolved scope dir and local-day window. */\n\tprivate _dailyUsageCache?: {\n\t\tsessionDir: string;\n\t\twindowStartMs: number;\n\t\twindowEndMs: number;\n\t\texpiresAt: number;\n\t\ttotals: DailyUsageTotals;\n\t};\n\t/** Memoized full cost summary. The footer renders on every streamed delta and keystroke, so\n\t * rescanning a long session log there turns redraw into O(entries) work per frame. */\n\tprivate _costSummaryCache?: {\n\t\tentryCount: number;\n\t\tdailyTotals: DailyUsageTotals;\n\t\twindowStartMs: number;\n\t\twindowEndMs: number;\n\t\tsummary: SessionCostSummary;\n\t};\n\t/** Cumulative stats initialized once from persisted telemetry, then updated without retaining record details. */\n\tprivate _toolArgumentValidationStats: ToolArgumentValidationStats | undefined;\n\t/** Incremental context-usage state keyed by the append-only branch leaf. */\n\tprivate _postCompactionUsageCache?: {\n\t\tleafId: string | null;\n\t\thasCompaction: boolean;\n\t\thasPostCompactionUsage: boolean;\n\t};\n\n\tprivate readonly deps: SessionAnalyticsDeps;\n\n\tconstructor(deps: SessionAnalyticsDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\tgetSessionStats(): SessionStats {\n\t\tlet userMessages = 0;\n\t\tlet assistantMessages = 0;\n\t\tlet toolResults = 0;\n\t\tlet totalMessages = 0;\n\t\tlet toolCalls = 0;\n\t\tconst usage = createEmptyUsage();\n\n\t\tfor (const entry of this.deps.getSessionManager().getEntries()) {\n\t\t\tconst entryUsage = getSessionEntryUsage(entry);\n\t\t\tif (entryUsage) addUsage(usage, entryUsage);\n\t\t\tif (entry.type !== \"message\") continue;\n\t\t\ttotalMessages++;\n\t\t\tconst message = entry.message;\n\t\t\tif (message.role === \"user\") {\n\t\t\t\tuserMessages++;\n\t\t\t} else if (message.role === \"toolResult\") {\n\t\t\t\ttoolResults++;\n\t\t\t} else if (message.role === \"assistant\") {\n\t\t\t\tassistantMessages++;\n\t\t\t\tconst assistantMsg = message;\n\t\t\t\ttoolCalls += assistantMsg.content.filter((c) => c.type === \"toolCall\").length;\n\t\t\t}\n\t\t}\n\n\t\tconst toolArgumentValidation = this.getToolArgumentValidationStats();\n\t\tconst compactionGates = this.getCompactionGateStats();\n\n\t\treturn {\n\t\t\tsessionFile: this.deps.getSessionManager().getSessionFile(),\n\t\t\tsessionId: this.deps.getSessionManager().getSessionId(),\n\t\t\tuserMessages,\n\t\t\tassistantMessages,\n\t\t\ttoolCalls,\n\t\t\ttoolResults,\n\t\t\ttotalMessages,\n\t\t\ttokens: {\n\t\t\t\tinput: usage.input,\n\t\t\t\toutput: usage.output,\n\t\t\t\tcacheRead: usage.cacheRead,\n\t\t\t\tcacheWrite: usage.cacheWrite,\n\t\t\t\ttotal: usage.input + usage.output + usage.cacheRead + usage.cacheWrite,\n\t\t\t},\n\t\t\tcost: usage.cost.total,\n\t\t\tcontextUsage: this.getContextUsage(),\n\t\t\ttoolArgumentValidation,\n\t\t\tcompactionGates,\n\t\t};\n\t}\n\n\tgetCompactionGateStats(): SessionStats[\"compactionGates\"] {\n\t\tlet gateFailures = 0;\n\t\tlet deterministicGapFills = 0;\n\t\tlet compactionsWithGateFailures = 0;\n\t\tconst checks = new Map<string, CompactionGateCheckStats>();\n\t\tfor (const entry of this.deps.getSessionManager().getEntries()) {\n\t\t\tif (entry.type !== \"compaction\") continue;\n\t\t\tconst details = entry.details;\n\t\t\tif (!details || typeof details !== \"object\") continue;\n\t\t\tconst rawGateFailures = (details as { verificationGateFailures?: unknown }).verificationGateFailures;\n\t\t\tconst rawGapFills = (details as { deterministicGapFills?: unknown }).deterministicGapFills;\n\t\t\tconst rawChecks = (details as { verificationGateChecks?: unknown }).verificationGateChecks;\n\t\t\tconst entryGateFailures =\n\t\t\t\ttypeof rawGateFailures === \"number\" && Number.isFinite(rawGateFailures) ? rawGateFailures : 0;\n\t\t\tconst entryGapFills = typeof rawGapFills === \"number\" && Number.isFinite(rawGapFills) ? rawGapFills : 0;\n\t\t\tgateFailures += entryGateFailures;\n\t\t\tdeterministicGapFills += entryGapFills;\n\t\t\tif (entryGateFailures > 0) compactionsWithGateFailures++;\n\t\t\tif (rawChecks && typeof rawChecks === \"object\" && !Array.isArray(rawChecks)) {\n\t\t\t\tfor (const [check, rawStats] of Object.entries(rawChecks)) {\n\t\t\t\t\tif (!rawStats || typeof rawStats !== \"object\" || Array.isArray(rawStats)) continue;\n\t\t\t\t\tconst stats = rawStats as Record<string, unknown>;\n\t\t\t\t\tconst failures = stats.failures;\n\t\t\t\t\tif (typeof failures !== \"number\" || !Number.isFinite(failures) || failures <= 0) continue;\n\t\t\t\t\tconst current = checks.get(check) ?? { failures: 0 };\n\t\t\t\t\tcurrent.failures += failures;\n\t\t\t\t\tif (typeof stats.minScore === \"number\" && Number.isFinite(stats.minScore)) {\n\t\t\t\t\t\tcurrent.minScore = Math.min(current.minScore ?? stats.minScore, stats.minScore);\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof stats.maxScore === \"number\" && Number.isFinite(stats.maxScore)) {\n\t\t\t\t\t\tcurrent.maxScore = Math.max(current.maxScore ?? stats.maxScore, stats.maxScore);\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof stats.threshold === \"number\" && Number.isFinite(stats.threshold)) {\n\t\t\t\t\t\tcurrent.threshold = stats.threshold;\n\t\t\t\t\t}\n\t\t\t\t\tif (stats.comparator === \"minimum\" || stats.comparator === \"maximum\") {\n\t\t\t\t\t\tcurrent.comparator = stats.comparator;\n\t\t\t\t\t}\n\t\t\t\t\tchecks.set(check, current);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn { gateFailures, deterministicGapFills, compactionsWithGateFailures, checks: Object.fromEntries(checks) };\n\t}\n\n\trecordToolArgumentValidation(record: ToolArgumentValidationLogRecord): void {\n\t\tconst stats = this.getToolArgumentValidationStats();\n\t\tconsumeToolArgumentValidationRecord(stats, record);\n\t\tthis._toolArgumentValidationStats = stats;\n\t}\n\n\tprivate readToolArgumentValidationSidecarRecords(): ToolArgumentValidationLogRecord[] {\n\t\tconst filePath = this.deps.getToolRecoveryEventLogPath();\n\t\tif (!existsSync(filePath)) return [];\n\t\tconst records: ToolArgumentValidationLogRecord[] = [];\n\t\ttry {\n\t\t\tconst sessionId = this.deps.getSessionManager().getSessionId();\n\t\t\tfor (const line of readFileSync(filePath, \"utf-8\").split(\"\\n\")) {\n\t\t\t\tif (line.trim().length === 0) continue;\n\t\t\t\tconst parsed = JSON.parse(line) as unknown;\n\t\t\t\tif (!isToolArgumentValidationLogRecord(parsed) || parsed.sessionId !== sessionId) continue;\n\t\t\t\trecords.push(parsed);\n\t\t\t}\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t\treturn records;\n\t}\n\n\tgetToolArgumentValidationStats(): ToolArgumentValidationStats {\n\t\tif (this._toolArgumentValidationStats) return structuredClone(this._toolArgumentValidationStats);\n\t\tconst eventLogPath = this.deps.getToolRecoveryEventLogPath();\n\t\tconst sessionId = this.deps.getSessionManager().getSessionId();\n\t\tconst persisted = readPersistedToolRecoveryStats(eventLogPath, sessionId);\n\t\tconst stats = persisted ? structuredClone(persisted.stats) : createEmptyToolArgumentValidationStats();\n\t\tconst seen = new Set<string>();\n\t\tconst consume = (record: ToolArgumentValidationRecord, key: string): void => {\n\t\t\tif (seen.has(key)) return;\n\t\t\tseen.add(key);\n\t\t\tconsumeToolArgumentValidationRecord(stats, record);\n\t\t};\n\n\t\tfor (const entry of this.deps.getSessionManager().getEntries()) {\n\t\t\tif (entry.type !== \"custom\" || entry.customType !== TOOL_ARGUMENT_VALIDATION_CUSTOM_TYPE) continue;\n\t\t\tconst record = entry.data as ToolArgumentValidationRecord | undefined;\n\t\t\tif (!record || record.version !== 1) continue;\n\t\t\tconsume(record, `legacy:${entry.id}`);\n\t\t}\n\t\tfor (const record of this.readToolArgumentValidationSidecarRecords()) {\n\t\t\tif (\n\t\t\t\tpersisted &&\n\t\t\t\trecord.sessionId === sessionId &&\n\t\t\t\tgetToolRecoveryRecordSequence(record) <= persisted.lastRecordSequence\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconsume(record, record.recordId);\n\t\t}\n\n\t\tthis._toolArgumentValidationStats = stats;\n\t\treturn structuredClone(stats);\n\t}\n\n\t/**\n\t * Cumulative usage (full breakdown) for this session's entire spawn subtree: its own\n\t * assistant messages PLUS every `spawned_usage` report it has rolled up. Single source of\n\t * truth for \"how much did this session and everything it spawned spend\" — used by print-mode\n\t * to emit a child's total so a spawner can roll it up via {@link addSpawnedUsage}.\n\t *\n\t * Including the `spawned_usage` reports is what keeps the single-hop invariant intact: a child\n\t * that itself spawned grandchildren must report own + sub-usage in one number, or the parent\n\t * silently under-counts the grandchildren.\n\t */\n\tgetCumulativeUsage(): Usage {\n\t\tconst total = createEmptyUsage();\n\t\tconst entries = this.deps.getSessionManager().getEntries();\n\t\tfor (const entry of entries) {\n\t\t\tconst usage = getSessionEntryUsage(entry);\n\t\t\tif (usage) addUsage(total, usage);\n\t\t}\n\t\t// Roll up usage this session attributed to its own spawned children (single-hop).\n\t\tconst seenSpawnedReportIds = new Set<string>();\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.type !== \"custom\" || entry.customType !== SPAWNED_USAGE_CUSTOM_TYPE) continue;\n\t\t\tconst data = entry.data as SpawnedUsageReport | undefined;\n\t\t\tif (!data?.usage) continue;\n\t\t\tif (data.reportId) {\n\t\t\t\tif (seenSpawnedReportIds.has(data.reportId)) continue;\n\t\t\t\tseenSpawnedReportIds.add(data.reportId);\n\t\t\t}\n\t\t\taddUsage(total, data.usage);\n\t\t}\n\t\treturn total;\n\t}\n\n\t/**\n\t * Record usage spent by a spawned/subagent session so the footer can roll it into the\n\t * displayed cost. Persisted as a `CustomEntry` (`customType: \"spawned_usage\"`, Model A) so\n\t * it survives reload and is reconstructed exactly like main usage; a new/forked session\n\t * starts fresh because it owns a new log file.\n\t *\n\t * Idempotent on `opts.reportId`: a re-report (retry, duplicate `agent_end`) with a\n\t * previously-seen id is ignored, so cost cannot be double-counted. Honors the single-hop\n\t * invariant documented on {@link SpawnedUsageReport}.\n\t *\n\t * @returns the id of the appended entry, or `undefined` if the report was a duplicate.\n\t */\n\taddSpawnedUsage(\n\t\tusage: Usage,\n\t\topts?: { label?: string; sourceSessionId?: string; reportId?: string },\n\t): string | undefined {\n\t\tconst reportId = opts?.reportId;\n\t\tif (reportId && this.getCurrentSessionCostTotals().seenSubagentReportIds.has(reportId)) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst report: SpawnedUsageReport = {\n\t\t\tusage,\n\t\t\tlabel: opts?.label,\n\t\t\tsourceSessionId: opts?.sourceSessionId,\n\t\t\treportId,\n\t\t};\n\t\tconst entryId = this.deps.getSessionManager().appendCustomEntry(SPAWNED_USAGE_CUSTOM_TYPE, report);\n\t\tif (reportId) this.getCurrentSessionCostTotals();\n\t\treturn entryId;\n\t}\n\n\tprivate getCurrentSessionCostTotals(): CurrentSessionCostAccumulator {\n\t\tconst sessionManager = this.deps.getSessionManager();\n\t\tconst entryCount = sessionManager.getEntryCount?.() ?? sessionManager.getEntries().length;\n\t\tlet cache = this._currentSessionCostCache;\n\t\tconst getEntriesSince = sessionManager.getEntriesSince?.bind(sessionManager);\n\t\tif (!cache || entryCount < cache.entryCount || !getEntriesSince) {\n\t\t\tcache = {\n\t\t\t\tentryCount,\n\t\t\t\taccumulator: accumulateCurrentSessionCostsFromEntries(\n\t\t\t\t\tcreateCurrentSessionCostAccumulator(),\n\t\t\t\t\tsessionManager.getEntries(),\n\t\t\t\t),\n\t\t\t};\n\t\t\tthis._currentSessionCostCache = cache;\n\t\t} else if (entryCount > cache.entryCount) {\n\t\t\taccumulateCurrentSessionCostsFromEntries(cache.accumulator, getEntriesSince(cache.entryCount));\n\t\t\tcache.entryCount = entryCount;\n\t\t}\n\t\treturn cache.accumulator;\n\t}\n\n\t/**\n\t * Aggregate all recorded spawned-usage reports (see {@link addSpawnedUsage}). The append-ordered\n\t * accumulator processes only new entries, so repeated turns do not rescan the full session.\n\t */\n\tgetSpawnedUsage(): SpawnedUsageTotals {\n\t\tconst current = this.getCurrentSessionCostTotals();\n\t\treturn { cost: current.subagentCost, reports: current.subagentReports };\n\t}\n\n\tgetCostSummary(now = new Date()): SessionCostSummary {\n\t\tconst sessionManager = this.deps.getSessionManager();\n\t\tconst entryCount = sessionManager.getEntryCount?.() ?? sessionManager.getEntries().length;\n\t\tconst window = getLocalDayWindow(now);\n\t\tconst dailyTotals = this.getDailyUsageTotals(now);\n\t\tconst cached = this._costSummaryCache;\n\t\tif (\n\t\t\tcached?.entryCount === entryCount &&\n\t\t\tcached.dailyTotals === dailyTotals &&\n\t\t\tcached.windowStartMs === window.startMs &&\n\t\t\tcached.windowEndMs === window.endMs\n\t\t) {\n\t\t\treturn cached.summary;\n\t\t}\n\t\tconst summary = createSessionCostSummary({\n\t\t\tcurrentTotals: this.getCurrentSessionCostTotals(),\n\t\t\tdailyTotals,\n\t\t\ttodayWindow: window,\n\t\t});\n\t\tthis._costSummaryCache = {\n\t\t\tentryCount,\n\t\t\tdailyTotals,\n\t\t\twindowStartMs: window.startMs,\n\t\t\twindowEndMs: window.endMs,\n\t\t\tsummary,\n\t\t};\n\t\treturn summary;\n\t}\n\n\tgetDailyUsageTotals(now = new Date()): DailyUsageTotals {\n\t\tconst sessionManager = this.deps.getSessionManager();\n\t\tconst sessionDir = sessionManager.getSessionDir();\n\t\tconst scope = sessionManager.usesDefaultSessionDir() ? getSessionsDir() : sessionDir;\n\t\tconst nowMs = now.getTime();\n\t\tconst window = getLocalDayWindow(now);\n\t\tif (\n\t\t\tthis._dailyUsageCache?.sessionDir === scope &&\n\t\t\tthis._dailyUsageCache.windowStartMs === window.startMs &&\n\t\t\tthis._dailyUsageCache.windowEndMs === window.endMs &&\n\t\t\tthis._dailyUsageCache.expiresAt > nowMs\n\t\t) {\n\t\t\treturn this._dailyUsageCache.totals;\n\t\t}\n\t\tconst sessionFile = sessionManager.getSessionFile();\n\t\tconst liveSession = sessionFile ? { filePath: sessionFile, entries: sessionManager.getEntries() } : undefined;\n\t\tconst totals = sessionManager.usesDefaultSessionDir()\n\t\t\t? aggregateDailyUsageFromSessionRoot(scope, window, liveSession)\n\t\t\t: aggregateDailyUsageFromSessionFiles(sessionDir, window, liveSession);\n\t\tthis._dailyUsageCache = {\n\t\t\tsessionDir: scope,\n\t\t\twindowStartMs: window.startMs,\n\t\t\twindowEndMs: window.endMs,\n\t\t\texpiresAt: Math.min(nowMs + 10_000, window.endMs),\n\t\t\ttotals,\n\t\t};\n\t\treturn totals;\n\t}\n\n\tgetDailyUsageBreakdown(formatLabel?: (label: string) => string, now = new Date()): string {\n\t\treturn formatDailyUsageBreakdown(this.getDailyUsageTotals(now), formatLabel);\n\t}\n\n\tprivate getPostCompactionUsageState(): { hasCompaction: boolean; hasPostCompactionUsage: boolean } {\n\t\tconst sessionManager = this.deps.getSessionManager();\n\t\tconst indexedSessionManager = sessionManager as unknown as {\n\t\t\tgetLeafId?: () => string | null;\n\t\t\tgetEntry?: (id: string) => SessionEntry | undefined;\n\t\t};\n\t\tconst getLeafId = indexedSessionManager.getLeafId?.bind(sessionManager);\n\t\tconst getEntry = indexedSessionManager.getEntry?.bind(sessionManager);\n\t\tconst leafId = getLeafId?.();\n\t\tif (getLeafId && getEntry && leafId !== undefined) {\n\t\t\tif (this._postCompactionUsageCache?.leafId === leafId) {\n\t\t\t\treturn { ...this._postCompactionUsageCache };\n\t\t\t}\n\t\t\tconst appended: SessionEntry[] = [];\n\t\t\tconst cachedLeafId = this._postCompactionUsageCache?.leafId;\n\t\t\tlet currentId = leafId;\n\t\t\tconst seen = new Set<string>();\n\t\t\twhile (currentId !== null && currentId !== cachedLeafId && !seen.has(currentId)) {\n\t\t\t\tseen.add(currentId);\n\t\t\t\tconst entry = getEntry(currentId);\n\t\t\t\tif (!entry) break;\n\t\t\t\tappended.push(entry);\n\t\t\t\tcurrentId = entry.parentId;\n\t\t\t}\n\t\t\tconst extendsCachedBranch = this._postCompactionUsageCache !== undefined && currentId === cachedLeafId;\n\t\t\tconst state = extendsCachedBranch\n\t\t\t\t? { ...this._postCompactionUsageCache! }\n\t\t\t\t: { leafId: null, hasCompaction: false, hasPostCompactionUsage: false };\n\t\t\tif (!extendsCachedBranch && currentId !== null) {\n\t\t\t\twhile (currentId !== null && !seen.has(currentId)) {\n\t\t\t\t\tseen.add(currentId);\n\t\t\t\t\tconst entry = getEntry(currentId);\n\t\t\t\t\tif (!entry) break;\n\t\t\t\t\tappended.push(entry);\n\t\t\t\t\tcurrentId = entry.parentId;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (let index = appended.length - 1; index >= 0; index--) {\n\t\t\t\tconst entry = appended[index];\n\t\t\t\tif (entry.type === \"compaction\") {\n\t\t\t\t\tstate.hasCompaction = true;\n\t\t\t\t\tstate.hasPostCompactionUsage = false;\n\t\t\t\t} else if (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\t\t\tconst assistant = entry.message;\n\t\t\t\t\tif (assistant.stopReason !== \"aborted\" && assistant.stopReason !== \"error\" && state.hasCompaction) {\n\t\t\t\t\t\tstate.hasPostCompactionUsage = calculateContextTokens(assistant.usage) > 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tstate.leafId = leafId;\n\t\t\tthis._postCompactionUsageCache = state;\n\t\t\treturn { ...state };\n\t\t}\n\n\t\tconst branchEntries = sessionManager.getBranch();\n\t\tconst latestCompaction = getLatestCompactionEntry(branchEntries);\n\t\tif (!latestCompaction) return { hasCompaction: false, hasPostCompactionUsage: false };\n\t\tconst compactionIndex = branchEntries.lastIndexOf(latestCompaction);\n\t\tfor (let index = branchEntries.length - 1; index > compactionIndex; index--) {\n\t\t\tconst entry = branchEntries[index];\n\t\t\tif (entry.type !== \"message\" || entry.message.role !== \"assistant\") continue;\n\t\t\tconst assistant = entry.message;\n\t\t\tif (assistant.stopReason === \"aborted\" || assistant.stopReason === \"error\") continue;\n\t\t\treturn { hasCompaction: true, hasPostCompactionUsage: calculateContextTokens(assistant.usage) > 0 };\n\t\t}\n\t\treturn { hasCompaction: true, hasPostCompactionUsage: false };\n\t}\n\n\tgetContextUsage(): ContextUsage | undefined {\n\t\tconst model = this.deps.getModel();\n\t\tif (!model) return undefined;\n\n\t\tconst contextWindow = model.contextWindow ?? 0;\n\t\tif (contextWindow <= 0) return undefined;\n\n\t\t// After compaction, the last assistant usage reflects pre-compaction context size.\n\t\t// Walk backward only to the nearest compaction instead of rebuilding the whole branch on\n\t\t// every footer invalidation; the distance is bounded by the live post-compaction context.\n\t\tconst compactionState = this.getPostCompactionUsageState();\n\t\tif (compactionState.hasCompaction && !compactionState.hasPostCompactionUsage) {\n\t\t\treturn { tokens: null, contextWindow, percent: null };\n\t\t}\n\n\t\tconst estimate = estimateContextTokens(this.deps.getMessages());\n\t\tconst percent = (estimate.tokens / contextWindow) * 100;\n\n\t\treturn {\n\t\t\ttokens: estimate.tokens,\n\t\t\tcontextWindow,\n\t\t\tpercent,\n\t\t};\n\t}\n\n\t/**\n\t * Export session to HTML.\n\t * @param outputPath Optional output path (defaults to session directory)\n\t * @returns Path to exported file\n\t */\n\tasync exportToHtml(outputPath?: string): Promise<string> {\n\t\tconst sessionManager = this.deps.getSessionManager();\n\t\tconst themeName = this.deps.getSettingsManager().getTheme();\n\n\t\t// Create tool renderer if we have an extension runner (for custom tool HTML rendering)\n\t\tconst toolRenderer: ToolHtmlRenderer = createToolHtmlRenderer({\n\t\t\tgetToolDefinition: (name) => this.deps.getToolDefinition(name),\n\t\t\ttheme,\n\t\t\tcwd: sessionManager.getCwd(),\n\t\t});\n\n\t\treturn await exportSessionToHtml(sessionManager, this.deps.getState(), {\n\t\t\toutputPath,\n\t\t\tthemeName,\n\t\t\ttoolRenderer,\n\t\t});\n\t}\n\n\t/**\n\t * Export the current session branch to a JSONL file.\n\t * Writes the session header followed by all entries on the current branch path.\n\t * @param outputPath Target file path. If omitted, generates a timestamped file in cwd.\n\t * @returns The resolved output file path.\n\t */\n\texportToJsonl(outputPath?: string): string {\n\t\tconst sessionManager = this.deps.getSessionManager();\n\t\tconst filePath = resolvePath(\n\t\t\toutputPath ?? `session-${new Date().toISOString().replace(/[:.]/g, \"-\")}.jsonl`,\n\t\t\tprocess.cwd(),\n\t\t);\n\t\tconst dir = dirname(filePath);\n\t\tif (!existsSync(dir)) {\n\t\t\tmkdirSync(dir, { recursive: true });\n\t\t}\n\n\t\tconst header: SessionHeader = {\n\t\t\ttype: \"session\",\n\t\t\tversion: CURRENT_SESSION_VERSION,\n\t\t\tid: sessionManager.getSessionId(),\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tcwd: sessionManager.getCwd(),\n\t\t};\n\n\t\tconst branchEntries = sessionManager.getBranch();\n\t\tconst lines = [JSON.stringify(header)];\n\n\t\t// Re-chain parentIds to form a linear sequence\n\t\tlet prevId: string | null = null;\n\t\tfor (const entry of branchEntries) {\n\t\t\tconst linear = { ...entry, parentId: prevId };\n\t\t\tlines.push(JSON.stringify(linear));\n\t\t\tprevId = entry.id;\n\t\t}\n\n\t\twriteFileSync(filePath, `${lines.join(\"\\n\")}\\n`);\n\t\treturn filePath;\n\t}\n\n\t/**\n\t * Get text content of last assistant message.\n\t * Useful for /copy command.\n\t * @returns Text content, or undefined if no assistant message exists\n\t */\n\tgetLastAssistantText(): string | undefined {\n\t\tconst lastAssistant = this.deps\n\t\t\t.getMessages()\n\t\t\t.slice()\n\t\t\t.reverse()\n\t\t\t.find((m) => {\n\t\t\t\tif (m.role !== \"assistant\") return false;\n\t\t\t\tconst msg = m as AssistantMessage;\n\t\t\t\t// Skip aborted messages with no content\n\t\t\t\tif (msg.stopReason === \"aborted\" && msg.content.length === 0) return false;\n\t\t\t\treturn true;\n\t\t\t});\n\n\t\tif (!lastAssistant) return undefined;\n\n\t\tlet text = \"\";\n\t\tfor (const content of (lastAssistant as AssistantMessage).content) {\n\t\t\tif (content.type === \"text\") {\n\t\t\t\ttext += content.text;\n\t\t\t}\n\t\t}\n\n\t\treturn text.trim() || undefined;\n\t}\n}\n"]}
@@ -9,11 +9,12 @@
9
9
  */
10
10
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
11
11
  import { dirname } from "node:path";
12
+ import { addUsage, createEmptyUsage, getSessionEntryUsage, } from "@caupulican/pi-agent-core";
12
13
  import { CURRENT_SESSION_VERSION, calculateContextTokens, estimateContextTokens, getLatestCompactionEntry, } from "@caupulican/pi-agent-core/node";
13
14
  import { getSessionsDir } from "../config.js";
14
15
  import { theme } from "../modes/interactive/theme/theme.js";
15
16
  import { resolvePath } from "../utils/paths.js";
16
- import { SPAWNED_USAGE_CUSTOM_TYPE, } from "./agent-session.js";
17
+ import { SPAWNED_USAGE_CUSTOM_TYPE, } from "./agent-session-contracts.js";
17
18
  import { accumulateCurrentSessionCostsFromEntries, createCurrentSessionCostAccumulator, createSessionCostSummary, } from "./cost/cost-summary.js";
18
19
  import { aggregateDailyUsageFromSessionFiles, aggregateDailyUsageFromSessionRoot, formatDailyUsageBreakdown, getLocalDayWindow, } from "./cost/daily-usage.js";
19
20
  import { exportSessionToHtml } from "./export-html/index.js";
@@ -38,25 +39,30 @@ export class SessionAnalytics {
38
39
  this.deps = deps;
39
40
  }
40
41
  getSessionStats() {
41
- const state = this.deps.getState();
42
- const userMessages = state.messages.filter((m) => m.role === "user").length;
43
- const assistantMessages = state.messages.filter((m) => m.role === "assistant").length;
44
- const toolResults = state.messages.filter((m) => m.role === "toolResult").length;
42
+ let userMessages = 0;
43
+ let assistantMessages = 0;
44
+ let toolResults = 0;
45
+ let totalMessages = 0;
45
46
  let toolCalls = 0;
46
- let totalInput = 0;
47
- let totalOutput = 0;
48
- let totalCacheRead = 0;
49
- let totalCacheWrite = 0;
50
- let totalCost = 0;
51
- for (const message of state.messages) {
52
- if (message.role === "assistant") {
47
+ const usage = createEmptyUsage();
48
+ for (const entry of this.deps.getSessionManager().getEntries()) {
49
+ const entryUsage = getSessionEntryUsage(entry);
50
+ if (entryUsage)
51
+ addUsage(usage, entryUsage);
52
+ if (entry.type !== "message")
53
+ continue;
54
+ totalMessages++;
55
+ const message = entry.message;
56
+ if (message.role === "user") {
57
+ userMessages++;
58
+ }
59
+ else if (message.role === "toolResult") {
60
+ toolResults++;
61
+ }
62
+ else if (message.role === "assistant") {
63
+ assistantMessages++;
53
64
  const assistantMsg = message;
54
65
  toolCalls += assistantMsg.content.filter((c) => c.type === "toolCall").length;
55
- totalInput += assistantMsg.usage.input;
56
- totalOutput += assistantMsg.usage.output;
57
- totalCacheRead += assistantMsg.usage.cacheRead;
58
- totalCacheWrite += assistantMsg.usage.cacheWrite;
59
- totalCost += assistantMsg.usage.cost.total;
60
66
  }
61
67
  }
62
68
  const toolArgumentValidation = this.getToolArgumentValidationStats();
@@ -68,15 +74,15 @@ export class SessionAnalytics {
68
74
  assistantMessages,
69
75
  toolCalls,
70
76
  toolResults,
71
- totalMessages: state.messages.length,
77
+ totalMessages,
72
78
  tokens: {
73
- input: totalInput,
74
- output: totalOutput,
75
- cacheRead: totalCacheRead,
76
- cacheWrite: totalCacheWrite,
77
- total: totalInput + totalOutput + totalCacheRead + totalCacheWrite,
79
+ input: usage.input,
80
+ output: usage.output,
81
+ cacheRead: usage.cacheRead,
82
+ cacheWrite: usage.cacheWrite,
83
+ total: usage.input + usage.output + usage.cacheRead + usage.cacheWrite,
78
84
  },
79
- cost: totalCost,
85
+ cost: usage.cost.total,
80
86
  contextUsage: this.getContextUsage(),
81
87
  toolArgumentValidation,
82
88
  compactionGates,
@@ -86,6 +92,7 @@ export class SessionAnalytics {
86
92
  let gateFailures = 0;
87
93
  let deterministicGapFills = 0;
88
94
  let compactionsWithGateFailures = 0;
95
+ const checks = new Map();
89
96
  for (const entry of this.deps.getSessionManager().getEntries()) {
90
97
  if (entry.type !== "compaction")
91
98
  continue;
@@ -94,14 +101,40 @@ export class SessionAnalytics {
94
101
  continue;
95
102
  const rawGateFailures = details.verificationGateFailures;
96
103
  const rawGapFills = details.deterministicGapFills;
104
+ const rawChecks = details.verificationGateChecks;
97
105
  const entryGateFailures = typeof rawGateFailures === "number" && Number.isFinite(rawGateFailures) ? rawGateFailures : 0;
98
106
  const entryGapFills = typeof rawGapFills === "number" && Number.isFinite(rawGapFills) ? rawGapFills : 0;
99
107
  gateFailures += entryGateFailures;
100
108
  deterministicGapFills += entryGapFills;
101
109
  if (entryGateFailures > 0)
102
110
  compactionsWithGateFailures++;
111
+ if (rawChecks && typeof rawChecks === "object" && !Array.isArray(rawChecks)) {
112
+ for (const [check, rawStats] of Object.entries(rawChecks)) {
113
+ if (!rawStats || typeof rawStats !== "object" || Array.isArray(rawStats))
114
+ continue;
115
+ const stats = rawStats;
116
+ const failures = stats.failures;
117
+ if (typeof failures !== "number" || !Number.isFinite(failures) || failures <= 0)
118
+ continue;
119
+ const current = checks.get(check) ?? { failures: 0 };
120
+ current.failures += failures;
121
+ if (typeof stats.minScore === "number" && Number.isFinite(stats.minScore)) {
122
+ current.minScore = Math.min(current.minScore ?? stats.minScore, stats.minScore);
123
+ }
124
+ if (typeof stats.maxScore === "number" && Number.isFinite(stats.maxScore)) {
125
+ current.maxScore = Math.max(current.maxScore ?? stats.maxScore, stats.maxScore);
126
+ }
127
+ if (typeof stats.threshold === "number" && Number.isFinite(stats.threshold)) {
128
+ current.threshold = stats.threshold;
129
+ }
130
+ if (stats.comparator === "minimum" || stats.comparator === "maximum") {
131
+ current.comparator = stats.comparator;
132
+ }
133
+ checks.set(check, current);
134
+ }
135
+ }
103
136
  }
104
- return { gateFailures, deterministicGapFills, compactionsWithGateFailures };
137
+ return { gateFailures, deterministicGapFills, compactionsWithGateFailures, checks: Object.fromEntries(checks) };
105
138
  }
106
139
  recordToolArgumentValidation(record) {
107
140
  const stats = this.getToolArgumentValidationStats();
@@ -173,39 +206,16 @@ export class SessionAnalytics {
173
206
  * silently under-counts the grandchildren.
174
207
  */
175
208
  getCumulativeUsage() {
176
- let input = 0;
177
- let output = 0;
178
- let cacheRead = 0;
179
- let cacheWrite = 0;
180
- let totalTokens = 0;
181
- let costInput = 0;
182
- let costOutput = 0;
183
- let costCacheRead = 0;
184
- let costCacheWrite = 0;
185
- let costTotal = 0;
186
- const add = (usage) => {
187
- input += usage.input;
188
- output += usage.output;
189
- cacheRead += usage.cacheRead;
190
- cacheWrite += usage.cacheWrite;
191
- totalTokens += usage.totalTokens;
192
- costInput += usage.cost.input;
193
- costOutput += usage.cost.output;
194
- costCacheRead += usage.cost.cacheRead;
195
- costCacheWrite += usage.cost.cacheWrite;
196
- costTotal += usage.cost.total;
197
- };
198
- for (const message of this.deps.getState().messages) {
199
- if (message.role !== "assistant")
200
- continue;
201
- const usage = message.usage;
202
- if (!usage)
203
- continue;
204
- add(usage);
209
+ const total = createEmptyUsage();
210
+ const entries = this.deps.getSessionManager().getEntries();
211
+ for (const entry of entries) {
212
+ const usage = getSessionEntryUsage(entry);
213
+ if (usage)
214
+ addUsage(total, usage);
205
215
  }
206
216
  // Roll up usage this session attributed to its own spawned children (single-hop).
207
217
  const seenSpawnedReportIds = new Set();
208
- for (const entry of this.deps.getSessionManager().getEntries()) {
218
+ for (const entry of entries) {
209
219
  if (entry.type !== "custom" || entry.customType !== SPAWNED_USAGE_CUSTOM_TYPE)
210
220
  continue;
211
221
  const data = entry.data;
@@ -216,22 +226,9 @@ export class SessionAnalytics {
216
226
  continue;
217
227
  seenSpawnedReportIds.add(data.reportId);
218
228
  }
219
- add(data.usage);
229
+ addUsage(total, data.usage);
220
230
  }
221
- return {
222
- input,
223
- output,
224
- cacheRead,
225
- cacheWrite,
226
- totalTokens,
227
- cost: {
228
- input: costInput,
229
- output: costOutput,
230
- cacheRead: costCacheRead,
231
- cacheWrite: costCacheWrite,
232
- total: costTotal,
233
- },
234
- };
231
+ return total;
235
232
  }
236
233
  /**
237
234
  * Record usage spent by a spawned/subagent session so the footer can roll it into the