chainlesschain 0.165.3 → 0.165.5

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 (214) hide show
  1. package/README.md +151 -29
  2. package/package.json +2 -2
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-BiHNUlbU.js → AIOps-CEeYTeDB.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-D-UFjDRQ.js → ActionButton-BeRUQ3V2.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-DazVsDgW.js → Analytics-DrV718XF.js} +3 -3
  7. package/src/assets/web-panel/assets/{AppLayout-DXh9UfNJ.js → AppLayout-Cd2Frt7Q.js} +5 -5
  8. package/src/assets/web-panel/assets/{Artifacts-CZ6tsceY.js → Artifacts-CUJMlORU.js} +1 -1
  9. package/src/assets/web-panel/assets/{Audit-RyxnBr_h.js → Audit-CXJcfT6p.js} +1 -1
  10. package/src/assets/web-panel/assets/{BackgroundAgents-BWS51Q6X.js → BackgroundAgents-DOv6Z7H9.js} +1 -1
  11. package/src/assets/web-panel/assets/{Backup-BRtPcUul.js → Backup-BwdDyBI0.js} +1 -1
  12. package/src/assets/web-panel/assets/{BaseInput-CGd4vZYY.js → BaseInput-BmLn4kYH.js} +1 -1
  13. package/src/assets/web-panel/assets/{Chat-h8ijVwCg.js → Chat-COg8pAW2.js} +4 -4
  14. package/src/assets/web-panel/assets/ChatBubbleRenderer-4gGkdGgA.js +1 -0
  15. package/src/assets/web-panel/assets/{Checkbox-NyF6dPl8.js → Checkbox-BCP4uoU8.js} +1 -1
  16. package/src/assets/web-panel/assets/{Codegen-Ci4OOxr5.js → Codegen-pRt6Y9JI.js} +1 -1
  17. package/src/assets/web-panel/assets/{Col-CwTkc9BM.js → Col-DLaprKhS.js} +1 -1
  18. package/src/assets/web-panel/assets/{Community-DW_tM82m.js → Community-DyATsz5f.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compact-DEvHRV4S.js → Compact-BXAaupZK.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compliance-BbjBEEfD.js → Compliance-DpcJBELr.js} +1 -1
  21. package/src/assets/web-panel/assets/{Cowork-10IXBaBa.js → Cowork-DG4EFWyd.js} +2 -2
  22. package/src/assets/web-panel/assets/{Cron-BZkbpd5I.js → Cron-F6Oy5n2P.js} +2 -2
  23. package/src/assets/web-panel/assets/{Crosschain-CFQ8L_6v.js → Crosschain-BOdgtalX.js} +1 -1
  24. package/src/assets/web-panel/assets/{DID-BDF6AkXe.js → DID-DT1dSkjH.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dashboard-CoOdWMi4.js → Dashboard-NBUIqWzC.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dropdown-DEsGmu8Y.js → Dropdown-CSpHeMYB.js} +1 -1
  27. package/src/assets/web-panel/assets/{EmailListRenderer-BS89SWlK.js → EmailListRenderer-CEG0xISr.js} +1 -1
  28. package/src/assets/web-panel/assets/{FamilyGuardDashboard-C1FpCHiI.js → FamilyGuardDashboard-BTZ0BZna.js} +1 -1
  29. package/src/assets/web-panel/assets/{Federation-BzvpVmLA.js → Federation-BuuCTn2V.js} +1 -1
  30. package/src/assets/web-panel/assets/{FormItemContext-BeC259PQ.js → FormItemContext-KAVceevk.js} +1 -1
  31. package/src/assets/web-panel/assets/{GenericCardRenderer-azgG3bmV.js → GenericCardRenderer-DnHpcQvW.js} +1 -1
  32. package/src/assets/web-panel/assets/{Git-BmSSowc5.js → Git-C_B_0HwB.js} +2 -2
  33. package/src/assets/web-panel/assets/{Governance-CTBCSyQZ.js → Governance-DPSZuzuu.js} +1 -1
  34. package/src/assets/web-panel/assets/{Inference-DA5xyk4a.js → Inference-BV-06V7q.js} +1 -1
  35. package/src/assets/web-panel/assets/{KnowledgeGraph-D1gPHNig.js → KnowledgeGraph-wpDuupn6.js} +1 -1
  36. package/src/assets/web-panel/assets/{Logs-BPmLf1AR.js → Logs-Bseca1_I.js} +2 -2
  37. package/src/assets/web-panel/assets/{MarkdownRenderer-SVLOg49H.js → MarkdownRenderer-B4RLp2zs.js} +1 -1
  38. package/src/assets/web-panel/assets/{Marketplace-DtUFcR0E.js → Marketplace-d3kM4DDL.js} +1 -1
  39. package/src/assets/web-panel/assets/{McpTools-DS_kqBv-.js → McpTools-DQ_xZ23i.js} +3 -3
  40. package/src/assets/web-panel/assets/{Memory-Fvh7XL7V.js → Memory-CRIeYO4L.js} +2 -2
  41. package/src/assets/web-panel/assets/{MobileBridge-C7itAP45.js → MobileBridge-BsllIa9l.js} +1 -1
  42. package/src/assets/web-panel/assets/MobileProjects-BUuQy30X.js +1 -0
  43. package/src/assets/web-panel/assets/{Mtc-B57MiNLK.js → Mtc-BOFDIzrC.js} +6 -6
  44. package/src/assets/web-panel/assets/{MtcAudit-BXfCUcM7.js → MtcAudit-BQg-vyvG.js} +5 -5
  45. package/src/assets/web-panel/assets/{Multisig-yaJ-ZcF6.js → Multisig-Bo1jrPdN.js} +3 -3
  46. package/src/assets/web-panel/assets/{NLProgramming-CoaUCKrO.js → NLProgramming-Bmod8alw.js} +1 -1
  47. package/src/assets/web-panel/assets/{Notes-BKLM_65R.js → Notes-CGGFL8w-.js} +3 -3
  48. package/src/assets/web-panel/assets/{NotificationSettings-DoDtK9uZ.js → NotificationSettings-BsZvCJxC.js} +1 -1
  49. package/src/assets/web-panel/assets/{OrderTableRenderer-BJ28TGr-.js → OrderTableRenderer-C1-Quo_h.js} +1 -1
  50. package/src/assets/web-panel/assets/{Organization-MuGsdoIb.js → Organization-BjOeDYOi.js} +4 -4
  51. package/src/assets/web-panel/assets/{Overflow-BLUN9J4R.js → Overflow-DwVV3l5A.js} +1 -1
  52. package/src/assets/web-panel/assets/{P2P-DWuoBUPd.js → P2P-Cu3DQT9W.js} +2 -2
  53. package/src/assets/web-panel/assets/{PdhVaultBrowser-CUi37YPj.js → PdhVaultBrowser-Cg0gR7dH.js} +3 -3
  54. package/src/assets/web-panel/assets/{Permissions-BYQg2pcr.js → Permissions-CsAXxRN5.js} +4 -4
  55. package/src/assets/web-panel/assets/{PersonalDataHub-CAxoV2xu.js → PersonalDataHub-C-nNmnYp.js} +6 -6
  56. package/src/assets/web-panel/assets/{Pipeline-B33wGvIO.js → Pipeline-BOnW7nNc.js} +1 -1
  57. package/src/assets/web-panel/assets/{Privacy-A8yXTORP.js → Privacy-ClLSyGKt.js} +1 -1
  58. package/src/assets/web-panel/assets/{ProjectInit-D49I2I1O.js → ProjectInit-DuLvjjq7.js} +2 -2
  59. package/src/assets/web-panel/assets/{ProjectSettings-Ci73jJDw.js → ProjectSettings-DQYYbDD9.js} +2 -2
  60. package/src/assets/web-panel/assets/{Projects-CF-yD6Cn.js → Projects-Drw8MBGK.js} +1 -1
  61. package/src/assets/web-panel/assets/Providers-ckqHQe6K.js +1 -0
  62. package/src/assets/web-panel/assets/{QrScannerModal-Brza0ykJ.js → QrScannerModal-DW5BXk-G.js} +1 -1
  63. package/src/assets/web-panel/assets/{QuickAsk-DFydhjxL.js → QuickAsk-DDLnhNTp.js} +1 -1
  64. package/src/assets/web-panel/assets/{Recommend-DLF8_NhA.js → Recommend-PJQ2C91U.js} +1 -1
  65. package/src/assets/web-panel/assets/{RemoteSession-dyuStW3x.js → RemoteSession-s6wmda34.js} +3 -3
  66. package/src/assets/web-panel/assets/{Reputation-5F3tA6yw.js → Reputation-DC2sb-I3.js} +1 -1
  67. package/src/assets/web-panel/assets/{Row-Ca2A57S5.js → Row-hPGk1eGj.js} +1 -1
  68. package/src/assets/web-panel/assets/{RssFeed-B0bxBkq_.js → RssFeed-RIvfZql0.js} +3 -3
  69. package/src/assets/web-panel/assets/{Search-CFNvHalZ.js → Search-DFg1G1eR.js} +1 -1
  70. package/src/assets/web-panel/assets/{Security-DSoH3Hav.js → Security-D6H5p8Dp.js} +4 -4
  71. package/src/assets/web-panel/assets/{Services-BHpfEmBQ.js → Services-nxYiFV_w.js} +2 -2
  72. package/src/assets/web-panel/assets/{Skeleton-Dsh-QNmn.js → Skeleton-BmgFNAdB.js} +1 -1
  73. package/src/assets/web-panel/assets/{Skills-BhT1NkSU.js → Skills-CsaaD2av.js} +1 -1
  74. package/src/assets/web-panel/assets/{Sla-DY9snPeJ.js → Sla-yM5y9yvK.js} +1 -1
  75. package/src/assets/web-panel/assets/{SpeechSettings-CWaX0_Cx.js → SpeechSettings-DPy1XMYh.js} +1 -1
  76. package/src/assets/web-panel/assets/{SyncSettings-B690y_TC.js → SyncSettings-CFVhEyyr.js} +2 -2
  77. package/src/assets/web-panel/assets/{Tasks-2N-w3zWd.js → Tasks-DdO02Inn.js} +1 -1
  78. package/src/assets/web-panel/assets/{Templates-BjwQOQYC.js → Templates-Eo2d8Llu.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tenant-CUqHErxY.js → Tenant-ChESOXgy.js} +1 -1
  80. package/src/assets/web-panel/assets/{Terminal-C13rXvNy.js → Terminal-BJ7oDxTI.js} +2 -2
  81. package/src/assets/web-panel/assets/TimelineRenderer-hWX0fUvz.js +1 -0
  82. package/src/assets/web-panel/assets/{Tokens-BXHLGXYC.js → Tokens-DVBZQnd-.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trigger-1e5i65o3.js → Trigger-D89cQfVq.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trust-FLGqNHs5.js → Trust-BIVSb4-V.js} +1 -1
  85. package/src/assets/web-panel/assets/{UkeySign-BbaR_LJB.js → UkeySign-B58gWopl.js} +1 -1
  86. package/src/assets/web-panel/assets/{VideoEditing-NOp4RIov.js → VideoEditing-DhHI7bmG.js} +1 -1
  87. package/src/assets/web-panel/assets/{Wallet-B7DW7bG4.js → Wallet-C4FheWS_.js} +3 -3
  88. package/src/assets/web-panel/assets/{WebAuthn-BptSUWix.js → WebAuthn-DnPRq-Bx.js} +5 -5
  89. package/src/assets/web-panel/assets/{WorkflowEditor-CAJnDOXS.js → WorkflowEditor-BerRPjpJ.js} +1 -1
  90. package/src/assets/web-panel/assets/{chat-I8LgG1-Z.js → chat-BzZ52iKr.js} +1 -1
  91. package/src/assets/web-panel/assets/{colors-CWe7SOVD.js → colors-BI_E4BAn.js} +1 -1
  92. package/src/assets/web-panel/assets/{compact-item-Cx3u3CA3.js → compact-item-d50mr3yk.js} +1 -1
  93. package/src/assets/web-panel/assets/{createContext-CgD5ArwY.js → createContext-C6FsQ1IH.js} +1 -1
  94. package/src/assets/web-panel/assets/devWarning-CagEcIex.js +1 -0
  95. package/src/assets/web-panel/assets/{hasIn-BfQWiXN8.js → hasIn-DLZEMgLP.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-BuEQSorC.js → index-9H_M2jju.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-BiI-xPRH.js → index-A5CDWP7y.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-DAVy98u7.js → index-AHr7ryWf.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BUAR7RY-.js → index-B81mo1Et.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DlIyt1qF.js → index-BAE3hwev.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-Dcdm_Z2c.js → index-BB9SqVSt.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CWZ3REg6.js → index-BRGx3w6T.js} +3 -3
  103. package/src/assets/web-panel/assets/{index-B6yChzt1.js → index-BTpIOTfR.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DeizoQVZ.js → index-BZjjdQ62.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-e8BM1yY1.js → index-BcSUl9fA.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-CNYFQxAW.js → index-BeM4hfht.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DGMYTN5W.js → index-Bmr_vxXD.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-BREnPKGo.js → index-BoNZlzhQ.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-B1cX4Rxu.js → index-C3k8kevG.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-3iKP9OTJ.js → index-CLoTQr0W.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-C1UjHdgZ.js → index-CO8DAF7U.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-Cy_cCJlr.js → index-CRN5TRTQ.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-C0nDKhWv.js → index-CUaEHfQ0.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-DslTuqro.js → index-CVzuawCX.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-CAUnl4Jv.js → index-CdKt9fOd.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CMu16vPC.js → index-CgkoH3_g.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-C-rIKccl.js → index-CjuKZBqJ.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-Bx7BNIRH.js → index-Co7s9LsB.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-Doc0Ftpd.js → index-D-aBumtY.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Cd79NQAx.js → index-DE0V6cp-.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-V-kIHzAV.js → index-DY4j5zkF.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-Bi24S7Dw.js → index-Dec0Kf_Z.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-DCJEY2T0.js → index-DoFtCVZ7.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-C0ztiqtB.js → index-DqkbHHg8.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-CcX4FSPf.js → index-DsscwxPE.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CdRkCwm4.js → index-GXE0D8Nx.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-DmgtY58H.js → index-IPkwSAW_.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-CQDKYbnv.js → index-KNGgO4Wm.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-87gMxqhN.js → index-Pvf30m8Q.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-DmrdUwzU.js → index-Q5Tn735s.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-DFb-XIKy.js → index-TWG-_D1M.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-DsQcURkA.js → index-Y2-q7QLm.js} +1 -1
  133. package/src/assets/web-panel/assets/index-pzT9PpOU.js +1 -0
  134. package/src/assets/web-panel/assets/index-z1kFadaX.js +1 -0
  135. package/src/assets/web-panel/assets/{initDefaultProps-DiBszVdG.js → initDefaultProps-D-4Hzgej.js} +1 -1
  136. package/src/assets/web-panel/assets/{motion-BGIFFozv.js → motion-D4Wl4xU7.js} +1 -1
  137. package/src/assets/web-panel/assets/{move-D5W7mp7B.js → move-Cd5eQvL0.js} +1 -1
  138. package/src/assets/web-panel/assets/{mtc-parser-JFIlxJ7F.js → mtc-parser-B4ilslCW.js} +1 -1
  139. package/src/assets/web-panel/assets/{omit-CQ3o6LIU.js → omit-Ckarx-tf.js} +1 -1
  140. package/src/assets/web-panel/assets/parsers-YNLm7sQ0.js +4 -0
  141. package/src/assets/web-panel/assets/{pickAttrs-R8MIlXo3.js → pickAttrs-QJ0bpCmc.js} +1 -1
  142. package/src/assets/web-panel/assets/{placementArrow-sW7ylSky.js → placementArrow-CKHm-tq8.js} +1 -1
  143. package/src/assets/web-panel/assets/{responsiveObserve-Cnl39Vbz.js → responsiveObserve-CV6a_w_Y.js} +1 -1
  144. package/src/assets/web-panel/assets/{slide-sn8tFd14.js → slide-mHpeQFgk.js} +1 -1
  145. package/src/assets/web-panel/assets/{statusUtils-IKKY_QxZ.js → statusUtils-DIaQNQWA.js} +1 -1
  146. package/src/assets/web-panel/assets/{styleChecker-BNpV4Nqs.js → styleChecker-PJpzavV8.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFlexGapSupport-BWyT_eoU.js → useFlexGapSupport-BH7zTw8S.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFs-D09p6_U9.js → useFs-BDNG3JDd.js} +1 -1
  149. package/src/assets/web-panel/assets/{usePersonalDataHub-CzW3TkJZ.js → usePersonalDataHub-CY2VWdUg.js} +1 -1
  150. package/src/assets/web-panel/assets/{vnode-3s3WoAKB.js → vnode-D0kw9jhz.js} +1 -1
  151. package/src/assets/web-panel/assets/{zoom-Cjy_673s.js → zoom-B5g7TN7r.js} +1 -1
  152. package/src/assets/web-panel/index.html +1 -1
  153. package/src/command-help-index.json +3 -3
  154. package/src/commands/agent.js +105 -35
  155. package/src/commands/artifacts.js +598 -33
  156. package/src/commands/cowork.js +200 -5
  157. package/src/commands/session-budget.js +155 -0
  158. package/src/commands/session-location.js +968 -1
  159. package/src/commands/session.js +23 -2
  160. package/src/data/changelog.json +28 -2
  161. package/src/gateways/ws/artifact-protocol.js +77 -13
  162. package/src/gateways/ws/message-dispatcher.js +57 -0
  163. package/src/gateways/ws/session-protocol.js +391 -24
  164. package/src/gateways/ws/ws-agent-handler.js +191 -14
  165. package/src/gateways/ws/ws-server.js +14 -3
  166. package/src/gateways/ws/ws-session-gateway.js +101 -5
  167. package/src/harness/jsonl-session-store.js +1210 -0
  168. package/src/lib/agent-team/team-runner.js +43 -13
  169. package/src/lib/artifact-access-ledger.js +462 -0
  170. package/src/lib/artifact-cleanup-ledger.js +861 -0
  171. package/src/lib/artifact-deletion-ledger.js +678 -0
  172. package/src/lib/artifact-recovery.js +970 -0
  173. package/src/lib/artifact-store.js +256 -51
  174. package/src/lib/artifact-workbench-projection.js +171 -0
  175. package/src/lib/command-lifecycle-report.js +8 -4
  176. package/src/lib/cowork-adapter.js +9 -5
  177. package/src/lib/cowork-task-runner.js +20 -0
  178. package/src/lib/cowork-workflow.js +178 -20
  179. package/src/lib/direct-model-usage.js +62 -22
  180. package/src/lib/dynamic-workflow-runtime.js +3592 -112
  181. package/src/lib/execution-location-result-apply.js +339 -0
  182. package/src/lib/execution-location-result-artifact.js +271 -0
  183. package/src/lib/execution-location-result-review.js +253 -0
  184. package/src/lib/execution-location-result-store.js +331 -0
  185. package/src/lib/execution-location-result.js +617 -0
  186. package/src/lib/execution-location-target.js +240 -3
  187. package/src/lib/managed-tool-checkpoint.js +47 -4
  188. package/src/lib/mcp-stdio-executable-identity.js +16 -0
  189. package/src/lib/mcp-stdio-native-code-policy.js +74 -0
  190. package/src/lib/mcp-stdio-package-materialization.js +12 -3
  191. package/src/lib/process-execution-broker/index.js +112 -0
  192. package/src/lib/process-execution-broker/platform-sandbox.js +57 -3
  193. package/src/lib/process-execution-broker/workspace-transaction.js +29 -0
  194. package/src/lib/session-budget-production-root.js +376 -0
  195. package/src/lib/session-budget-runtime.js +109 -18
  196. package/src/lib/session-budget-usage.js +63 -0
  197. package/src/lib/session-host-snapshot.js +19 -2
  198. package/src/lib/session-projection.js +126 -10
  199. package/src/lib/session-resource-budget.js +766 -105
  200. package/src/lib/sub-agent-context.js +69 -22
  201. package/src/lib/web-ui-server.js +12 -1
  202. package/src/repl/agent-repl.js +237 -16
  203. package/src/runtime/agent-core.js +135 -0
  204. package/src/runtime/headless-runner.js +135 -46
  205. package/src/runtime/headless-stream.js +133 -25
  206. package/src/runtime/policies/agent-policy.js +10 -0
  207. package/src/assets/web-panel/assets/ChatBubbleRenderer-D7tcdDS9.js +0 -1
  208. package/src/assets/web-panel/assets/MobileProjects-DGbP36-3.js +0 -1
  209. package/src/assets/web-panel/assets/Providers-D-etEhg5.js +0 -1
  210. package/src/assets/web-panel/assets/TimelineRenderer-CpbWcya_.js +0 -1
  211. package/src/assets/web-panel/assets/devWarning-DLv_872g.js +0 -1
  212. package/src/assets/web-panel/assets/index-CdiGCibe.js +0 -1
  213. package/src/assets/web-panel/assets/index-D_0z-gyz.js +0 -1
  214. package/src/assets/web-panel/assets/parsers-UEvh_ShA.js +0 -4
@@ -109,8 +109,10 @@ import { buildPermissionDecision } from "../lib/permission-decision.js";
109
109
  import { resolveSandboxPolicyPath } from "../lib/agent-sandbox.js";
110
110
  import {
111
111
  beginManagedToolCheckpoint,
112
+ managedToolCheckpointBinding,
112
113
  settleManagedToolCheckpoint,
113
114
  } from "../lib/managed-tool-checkpoint.js";
115
+ import { sessionBudgetAdmissionError } from "../lib/session-budget-production-root.js";
114
116
  import {
115
117
  createMcpCallLedger,
116
118
  McpEffect,
@@ -3570,6 +3572,35 @@ export async function executeTool(name, args, context = {}) {
3570
3572
  }
3571
3573
  }
3572
3574
 
3575
+ let sessionBudgetTool = null;
3576
+ if (typeof context.sessionBudget?.beginTool === "function") {
3577
+ const toolBinding = JSON.stringify({
3578
+ sessionId: context.sessionId || null,
3579
+ turnId: context.turnId || null,
3580
+ toolCallId: context.toolCallId || randomUUID(),
3581
+ tool: name,
3582
+ });
3583
+ const toolBudgetId = `tool:${createHash("sha256")
3584
+ .update(toolBinding, "utf8")
3585
+ .digest("hex")
3586
+ .slice(0, 48)}`;
3587
+ sessionBudgetTool = context.sessionBudget.beginTool({
3588
+ id: toolBudgetId,
3589
+ kind: String(name || "tool").slice(0, 128),
3590
+ });
3591
+ if (!sessionBudgetTool?.ok) {
3592
+ return {
3593
+ error: `Session budget blocked tool execution: ${sessionBudgetTool?.reason || "session-aborted"}`,
3594
+ code: "CC_SESSION_BUDGET_EXHAUSTED",
3595
+ budgetReason: sessionBudgetTool?.reason || "session-aborted",
3596
+ policy: {
3597
+ decision: "blocked",
3598
+ via: "session-budget",
3599
+ },
3600
+ };
3601
+ }
3602
+ }
3603
+
3573
3604
  const startTime = Date.now();
3574
3605
  let toolResult;
3575
3606
  try {
@@ -3598,6 +3629,7 @@ export async function executeTool(name, args, context = {}) {
3598
3629
  strictUsageTelemetry: context.strictUsageTelemetry === true,
3599
3630
  onUsageBoundary: context.onUsageBoundary || null,
3600
3631
  onUsageSettlement: context.onUsageSettlement || null,
3632
+ onProviderReceipt: context.onProviderReceipt || null,
3601
3633
  onToolCallBoundary: context.onToolCallBoundary || null,
3602
3634
  onToolCallSettlement: context.onToolCallSettlement || null,
3603
3635
  backgroundUsageFailureState: context.backgroundUsageFailureState || null,
@@ -3661,6 +3693,8 @@ export async function executeTool(name, args, context = {}) {
3661
3693
  }
3662
3694
  }
3663
3695
  throw err;
3696
+ } finally {
3697
+ sessionBudgetTool?.end?.();
3664
3698
  }
3665
3699
 
3666
3700
  const durationMs = Date.now() - startTime;
@@ -5014,6 +5048,7 @@ async function executeToolInner(
5014
5048
  strictUsageTelemetry = false,
5015
5049
  onUsageBoundary = null,
5016
5050
  onUsageSettlement = null,
5051
+ onProviderReceipt = null,
5017
5052
  onToolCallBoundary = null,
5018
5053
  onToolCallSettlement = null,
5019
5054
  backgroundUsageFailureState = null,
@@ -5676,6 +5711,18 @@ async function executeToolInner(
5676
5711
  },
5677
5712
  { cwd },
5678
5713
  );
5714
+ if (
5715
+ pluginBinInvocation.runtime === "native" &&
5716
+ backgroundPlatform !== "linux"
5717
+ ) {
5718
+ const unsupportedNativeError = new Error(
5719
+ `strict native Plugin bins require the Linux descriptor-bound ELF loader closure; ${backgroundPlatform} native loading is unsupported`,
5720
+ );
5721
+ unsupportedNativeError.code =
5722
+ "ERR_PLUGIN_NATIVE_SANDBOX_PLATFORM_UNSUPPORTED";
5723
+ unsupportedNativeError.pluginBinFailClosed = true;
5724
+ throw unsupportedNativeError;
5725
+ }
5679
5726
  if (
5680
5727
  backgroundPlatform === "linux" ||
5681
5728
  (backgroundPlatform === "win32" &&
@@ -6763,6 +6810,7 @@ async function executeToolInner(
6763
6810
  strictUsageTelemetry,
6764
6811
  onUsageBoundary,
6765
6812
  onUsageSettlement,
6813
+ onProviderReceipt,
6766
6814
  onToolCallBoundary,
6767
6815
  onToolCallSettlement,
6768
6816
  backgroundUsageFailureState,
@@ -7689,6 +7737,15 @@ async function executeToolInner(
7689
7737
  projectSkillUsage(event),
7690
7738
  )
7691
7739
  : null;
7740
+ const observeSkillReceipt =
7741
+ strictUsageTelemetry === true &&
7742
+ typeof onProviderReceipt === "function"
7743
+ ? (event) =>
7744
+ _notifyStrictProviderReceipt(
7745
+ onProviderReceipt,
7746
+ projectSkillUsage(event),
7747
+ )
7748
+ : null;
7692
7749
  const projectSkillTool = (event) => ({
7693
7750
  ...event,
7694
7751
  attribution: event?.attribution || projectSkillUsage({}).attribution,
@@ -7781,6 +7838,9 @@ async function executeToolInner(
7781
7838
  strictUsageTelemetry: true,
7782
7839
  onUsageBoundary: observeSkillBoundary,
7783
7840
  onUsageSettlement: observeSkillSettlement,
7841
+ ...(observeSkillReceipt
7842
+ ? { onProviderReceipt: observeSkillReceipt }
7843
+ : {}),
7784
7844
  onToolCallBoundary: observeSkillToolBoundary,
7785
7845
  onToolCallSettlement: observeSkillToolSettlement,
7786
7846
  }
@@ -9642,6 +9702,20 @@ async function _executeSpawnSubAgent(args, ctx) {
9642
9702
  }
9643
9703
  }
9644
9704
  : null;
9705
+ const observeSubagentReceipt =
9706
+ ctx.strictUsageTelemetry === true &&
9707
+ typeof ctx.onProviderReceipt === "function"
9708
+ ? (event) => {
9709
+ try {
9710
+ return _notifyStrictProviderReceipt(
9711
+ ctx.onProviderReceipt,
9712
+ projectSubagentUsage(event),
9713
+ );
9714
+ } catch (error) {
9715
+ throw latchBackgroundUsageFailure(error);
9716
+ }
9717
+ }
9718
+ : null;
9645
9719
  const projectSubagentTool = (event) => ({
9646
9720
  ...event,
9647
9721
  attribution:
@@ -9751,6 +9825,9 @@ async function _executeSpawnSubAgent(args, ctx) {
9751
9825
  strictUsageTelemetry: true,
9752
9826
  onUsageBoundary: observeSubagentBoundary,
9753
9827
  onUsageSettlement: observeSubagentSettlement,
9828
+ ...(observeSubagentReceipt
9829
+ ? { onProviderReceipt: observeSubagentReceipt }
9830
+ : {}),
9754
9831
  onToolCallBoundary: observeSubagentToolBoundary,
9755
9832
  onToolCallSettlement: observeSubagentToolSettlement,
9756
9833
  }
@@ -12093,6 +12170,38 @@ function _notifyStrictUsageSettlement(observer, settlement) {
12093
12170
  }
12094
12171
  }
12095
12172
 
12173
+ function _notifyStrictProviderReceipt(observer, receipt) {
12174
+ if (typeof observer !== "function") return;
12175
+ let observation;
12176
+ try {
12177
+ observation = observer(receipt);
12178
+ } catch (error) {
12179
+ throw _runtimeUsageBoundaryFailure(
12180
+ error,
12181
+ "CC_USAGE_RECEIPT_PERSISTENCE_FAILED",
12182
+ "Child provider receipt persistence failed",
12183
+ );
12184
+ }
12185
+ let isThenable = false;
12186
+ try {
12187
+ isThenable = Boolean(observation && typeof observation.then === "function");
12188
+ } catch (error) {
12189
+ throw _runtimeUsageBoundaryFailure(
12190
+ error,
12191
+ "CC_USAGE_RECEIPT_OBSERVER_ASYNC",
12192
+ "Child provider receipt observer must be synchronous",
12193
+ );
12194
+ }
12195
+ if (isThenable) {
12196
+ void Promise.resolve(observation).catch(() => {});
12197
+ throw _runtimeUsageBoundaryFailure(
12198
+ null,
12199
+ "CC_USAGE_RECEIPT_OBSERVER_ASYNC",
12200
+ "Child provider receipt observer must be synchronous",
12201
+ );
12202
+ }
12203
+ }
12204
+
12096
12205
  function _notifyStrictToolObserver(observer, event, phase) {
12097
12206
  const upper = phase.toUpperCase();
12098
12207
  if (typeof observer !== "function") {
@@ -12757,6 +12866,9 @@ export async function* agentLoop(messages, options) {
12757
12866
  ...(typeof options.onUsageSettlement === "function"
12758
12867
  ? { onUsageSettlement: options.onUsageSettlement }
12759
12868
  : {}),
12869
+ ...(typeof options.onProviderReceipt === "function"
12870
+ ? { onProviderReceipt: options.onProviderReceipt }
12871
+ : {}),
12760
12872
  ...(typeof options.onStreamRetry === "function"
12761
12873
  ? { onStreamRetry: options.onStreamRetry }
12762
12874
  : {}),
@@ -12773,6 +12885,7 @@ export async function* agentLoop(messages, options) {
12773
12885
  strictUsageTelemetry: options.strictUsageTelemetry === true,
12774
12886
  onUsageBoundary: options.onUsageBoundary || null,
12775
12887
  onUsageSettlement: options.onUsageSettlement || null,
12888
+ onProviderReceipt: options.onProviderReceipt || null,
12776
12889
  onToolCallBoundary: options.onToolCallBoundary || null,
12777
12890
  onToolCallSettlement: options.onToolCallSettlement || null,
12778
12891
  parentMessages: messages, // pass parent messages for sub-agent auto-condensation
@@ -13013,6 +13126,21 @@ export async function* agentLoop(messages, options) {
13013
13126
  let emptyThinkingReprompted = false;
13014
13127
 
13015
13128
  while (budget.hasRemaining()) {
13129
+ if (typeof toolContext.sessionBudget?.consumeTurn === "function") {
13130
+ const turnBudgetId = `turn:${createHash("sha256")
13131
+ .update(`${runId}:t${budget.consumed + 1}`, "utf8")
13132
+ .digest("hex")
13133
+ .slice(0, 48)}`;
13134
+ const admission = toolContext.sessionBudget.consumeTurn({
13135
+ id: turnBudgetId,
13136
+ });
13137
+ if (!admission?.ok) {
13138
+ throw sessionBudgetAdmissionError(
13139
+ admission?.reason,
13140
+ `turn ${budget.consumed + 1}`,
13141
+ );
13142
+ }
13143
+ }
13016
13144
  budget.consume();
13017
13145
  throwIfAborted(signal);
13018
13146
 
@@ -14205,6 +14333,13 @@ export async function* agentLoop(messages, options) {
14205
14333
  tool_use_id: call.id,
14206
14334
  turn_id: `${runId}:t${budget.consumed}`,
14207
14335
  ...(workflowBinding || {}),
14336
+ ...(managedCheckpointHandle
14337
+ ? {
14338
+ managedCheckpointBinding: managedToolCheckpointBinding(
14339
+ managedCheckpointHandle,
14340
+ ),
14341
+ }
14342
+ : {}),
14208
14343
  };
14209
14344
  // The event yield is a host persistence boundary. A detached child's
14210
14345
  // fatal usage write can settle while the consumer handles it; fence
@@ -120,6 +120,16 @@ import {
120
120
  import executionBroker from "../lib/process-execution-broker/index.js";
121
121
  import { extractPluginUsageAttribution } from "../lib/plugin-usage-attribution.js";
122
122
  import { formatManagedCheckpointEvent } from "../lib/managed-checkpoint-render.js";
123
+ import {
124
+ openProductionSessionBudgetRoot,
125
+ sessionBudgetAdmissionError,
126
+ } from "../lib/session-budget-production-root.js";
127
+ import {
128
+ beginSessionBudgetUsage,
129
+ markSessionBudgetUsageUnknown,
130
+ recordSessionBudgetUsage,
131
+ rejectSessionBudgetUsageUnknown,
132
+ } from "../lib/session-budget-usage.js";
123
133
 
124
134
  const goalBrokerRunner = executionBroker.spawnSync.bind(executionBroker);
125
135
 
@@ -466,11 +476,12 @@ async function withHeadlessSessionHostLease(options, deps, task) {
466
476
  deps.acquireSessionHostLease ||
467
477
  (!hasInjectedSessionStore ? acquireSessionHostLease : null);
468
478
  let lease = null;
479
+ let budgetRoot = null;
469
480
  try {
470
481
  if (authoritySessionId && typeof acquireHostLease === "function") {
471
482
  lease = acquireHostLease(authoritySessionId, { hostKind: "headless" });
472
483
  }
473
- const scopedOptions = lease?.signal
484
+ let scopedOptions = lease?.signal
474
485
  ? {
475
486
  ...options,
476
487
  signal: options.signal
@@ -478,12 +489,28 @@ async function withHeadlessSessionHostLease(options, deps, task) {
478
489
  : lease.signal,
479
490
  }
480
491
  : options;
492
+ budgetRoot = openProductionSessionBudgetRoot(
493
+ authoritySessionId,
494
+ options.sessionBudgetRoot,
495
+ {
496
+ persist: resolution.persist,
497
+ signal: scopedOptions.signal || null,
498
+ table: options.sessionBudgetRoot?.table,
499
+ open: deps.openSessionBudget,
500
+ store: deps.sessionBudgetStore,
501
+ registry: deps.sessionBudgetRegistry,
502
+ },
503
+ );
504
+ if (budgetRoot.enabled) {
505
+ scopedOptions = { ...scopedOptions, ...budgetRoot.options };
506
+ }
481
507
  return await task(scopedOptions, {
482
508
  ...deps,
483
509
  [HEADLESS_SESSION_RESOLUTION]: resolution,
484
510
  [HEADLESS_SESSION_HOST_LEASE]: lease,
485
511
  });
486
512
  } finally {
513
+ budgetRoot?.close?.();
487
514
  lease?.release?.();
488
515
  }
489
516
  }
@@ -773,8 +800,9 @@ async function runAgentHeadlessInWorkspace(
773
800
  const loaded = loadHooks({ cwd, settingsFile: options.settingsFile });
774
801
  // Fold in installed plugins' hooks/hooks.json (Phase 3.3c) — plugins ADD
775
802
  // to the user's settings hooks, never replace them.
776
- const { mergePluginHooks } =
777
- await import("../lib/plugin-runtime/hooks.js");
803
+ const { mergePluginHooks } = await import(
804
+ "../lib/plugin-runtime/hooks.js"
805
+ );
778
806
  const effectiveHooks = mergePluginHooks(
779
807
  attachAuthorityErrors(loaded.hooks, loaded.authorityErrors),
780
808
  { cwd },
@@ -815,8 +843,9 @@ async function runAgentHeadlessInWorkspace(
815
843
  // the run, so no explicit restore is needed.
816
844
  if (!hermeticExecution) {
817
845
  try {
818
- const { applyPluginBinPath } =
819
- await import("../lib/plugin-runtime/bin.js");
846
+ const { applyPluginBinPath } = await import(
847
+ "../lib/plugin-runtime/bin.js"
848
+ );
820
849
  applyPluginBinPath({ cwd });
821
850
  } catch {
822
851
  /* best-effort — plugin bin PATH never blocks a headless run */
@@ -827,8 +856,9 @@ async function runAgentHeadlessInWorkspace(
827
856
  // keys not already set; the process exits at the end so no restore is needed.
828
857
  if (!hermeticExecution) {
829
858
  try {
830
- const { applyPluginSettingsEnv } =
831
- await import("../lib/plugin-runtime/settings.js");
859
+ const { applyPluginSettingsEnv } = await import(
860
+ "../lib/plugin-runtime/settings.js"
861
+ );
832
862
  applyPluginSettingsEnv({ cwd });
833
863
  } catch {
834
864
  /* best-effort — plugin settings never block a headless run */
@@ -961,8 +991,9 @@ async function runAgentHeadlessInWorkspace(
961
991
  if (isHeadlessConfigCommand(prompt)) {
962
992
  const cm = await import("../lib/config-manager.js");
963
993
  const { getConfigPath } = await import("../lib/paths.js");
964
- const { runConfigDirective } =
965
- await import("../lib/headless-config-command.js");
994
+ const { runConfigDirective } = await import(
995
+ "../lib/headless-config-command.js"
996
+ );
966
997
  const { text, isError } = runConfigDirective(prompt, {
967
998
  configManager: cm,
968
999
  getConfigPath,
@@ -1038,8 +1069,9 @@ async function runAgentHeadlessInWorkspace(
1038
1069
  model = macro.model;
1039
1070
  writeErr(` command: model → ${model}\n`);
1040
1071
  try {
1041
- const { maybeWarnDeprecatedModel } =
1042
- await import("../lib/model-deprecation.js");
1072
+ const { maybeWarnDeprecatedModel } = await import(
1073
+ "../lib/model-deprecation.js"
1074
+ );
1043
1075
  maybeWarnDeprecatedModel({ model });
1044
1076
  } catch {
1045
1077
  // deprecation notice is best-effort
@@ -1076,8 +1108,9 @@ async function runAgentHeadlessInWorkspace(
1076
1108
 
1077
1109
  // ── Permission + tool resolution ──────────────────────────────────────
1078
1110
  if (managedSettings) {
1079
- const { assertManagedPermissionMode } =
1080
- await import("../lib/settings-loader.cjs");
1111
+ const { assertManagedPermissionMode } = await import(
1112
+ "../lib/settings-loader.cjs"
1113
+ );
1081
1114
  assertManagedPermissionMode(options.permissionMode, managedSettings);
1082
1115
  }
1083
1116
  const perm = resolvePermissionMode(options.permissionMode);
@@ -1533,8 +1566,9 @@ async function runAgentHeadlessInWorkspace(
1533
1566
  : null;
1534
1567
  if (!hermeticExecution && !instructionExcludes) {
1535
1568
  try {
1536
- const { readStringArraySetting } =
1537
- await import("../lib/settings-loader.cjs");
1569
+ const { readStringArraySetting } = await import(
1570
+ "../lib/settings-loader.cjs"
1571
+ );
1538
1572
  const fromSettings = readStringArraySetting("instructionExcludes", {
1539
1573
  cwd,
1540
1574
  settingsFile: options.settingsFile,
@@ -1588,8 +1622,9 @@ async function runAgentHeadlessInWorkspace(
1588
1622
  // settings.json UserPromptSubmit hooks. block → abort the run; context → inject.
1589
1623
  if (settingsHooks) {
1590
1624
  try {
1591
- const { runUserPromptSubmitHooks } =
1592
- await import("../lib/settings-hook-events.js");
1625
+ const { runUserPromptSubmitHooks } = await import(
1626
+ "../lib/settings-hook-events.js"
1627
+ );
1593
1628
  const ups = runUserPromptSubmitHooks(settingsHooks, {
1594
1629
  prompt: userContent,
1595
1630
  cwd,
@@ -1619,8 +1654,9 @@ async function runAgentHeadlessInWorkspace(
1619
1654
  let instructionsLoadedContext = null;
1620
1655
  if (settingsHooks && _loadedInstructions) {
1621
1656
  try {
1622
- const { runInstructionsLoadedHooks } =
1623
- await import("../lib/settings-hook-events.js");
1657
+ const { runInstructionsLoadedHooks } = await import(
1658
+ "../lib/settings-hook-events.js"
1659
+ );
1624
1660
  instructionsLoadedContext = runInstructionsLoadedHooks(settingsHooks, {
1625
1661
  files: _loadedInstructions.files,
1626
1662
  cwd,
@@ -1635,8 +1671,9 @@ async function runAgentHeadlessInWorkspace(
1635
1671
  let sessionStartContext = null;
1636
1672
  if (settingsHooks) {
1637
1673
  try {
1638
- const { runSessionStartHooks } =
1639
- await import("../lib/settings-hook-events.js");
1674
+ const { runSessionStartHooks } = await import(
1675
+ "../lib/settings-hook-events.js"
1676
+ );
1640
1677
  sessionStartContext = runSessionStartHooks(settingsHooks, {
1641
1678
  source: resumeId ? "resume" : "startup",
1642
1679
  cwd,
@@ -1654,8 +1691,9 @@ async function runAgentHeadlessInWorkspace(
1654
1691
  // back up" — e.g. re-run a workspace sanity check. Observe-only, best-effort.
1655
1692
  if (settingsHooks && resumeId && history.length > 0) {
1656
1693
  try {
1657
- const { runObserveHooks } =
1658
- await import("../lib/settings-hook-events.js");
1694
+ const { runObserveHooks } = await import(
1695
+ "../lib/settings-hook-events.js"
1696
+ );
1659
1697
  runObserveHooks(
1660
1698
  settingsHooks,
1661
1699
  "SessionResume",
@@ -1886,8 +1924,9 @@ async function runAgentHeadlessInWorkspace(
1886
1924
  // --add-dir → workspaceRootDirs = [cwd] and this is a no-op. Best-effort.
1887
1925
  if (hostMcp?.mcpClient && additionalDirectories.length > 0) {
1888
1926
  try {
1889
- const { notifyMcpRootsChanged, workspaceRootDirs } =
1890
- await import("../repl/add-dir.js");
1927
+ const { notifyMcpRootsChanged, workspaceRootDirs } = await import(
1928
+ "../repl/add-dir.js"
1929
+ );
1891
1930
  notifyMcpRootsChanged(
1892
1931
  [hostMcp.mcpClient],
1893
1932
  workspaceRootDirs(options.cwd || process.cwd(), additionalDirectories),
@@ -1995,8 +2034,9 @@ async function runAgentHeadlessInWorkspace(
1995
2034
  error.code = "CC_REMOTE_APPROVAL_GATE_UNAVAILABLE";
1996
2035
  throw error;
1997
2036
  }
1998
- const { startHeadlessRemoteApproval } =
1999
- await import("../lib/remote-approval-bridge.js");
2037
+ const { startHeadlessRemoteApproval } = await import(
2038
+ "../lib/remote-approval-bridge.js"
2039
+ );
2000
2040
  _remoteApproval = await (
2001
2041
  deps.startHeadlessRemoteApproval || startHeadlessRemoteApproval
2002
2042
  )({
@@ -2025,8 +2065,9 @@ async function runAgentHeadlessInWorkspace(
2025
2065
  let _collectorEnabled = false;
2026
2066
  if (!hermeticExecution) {
2027
2067
  try {
2028
- const { isOtlpCollectorEnabled } =
2029
- await import("../lib/observability/index.js");
2068
+ const { isOtlpCollectorEnabled } = await import(
2069
+ "../lib/observability/index.js"
2070
+ );
2030
2071
  _collectorEnabled = isOtlpCollectorEnabled();
2031
2072
  } catch {
2032
2073
  _collectorEnabled = false;
@@ -2034,8 +2075,9 @@ async function runAgentHeadlessInWorkspace(
2034
2075
  }
2035
2076
  if (!hermeticExecution && (options.otlp || _collectorEnabled)) {
2036
2077
  try {
2037
- const { TelemetryRecorder } =
2038
- await import("../lib/telemetry/span-recorder.js");
2078
+ const { TelemetryRecorder } = await import(
2079
+ "../lib/telemetry/span-recorder.js"
2080
+ );
2039
2081
  _otlpRecorder = new TelemetryRecorder({ serviceName: "cc-agent" });
2040
2082
  } catch {
2041
2083
  _otlpRecorder = null; // telemetry is best-effort, never blocks the run
@@ -2049,8 +2091,9 @@ async function runAgentHeadlessInWorkspace(
2049
2091
  let _hookSupervisor = null;
2050
2092
  if (settingsHooks) {
2051
2093
  try {
2052
- const { AsyncHookSupervisor } =
2053
- await import("../lib/async-hook-supervisor.js");
2094
+ const { AsyncHookSupervisor } = await import(
2095
+ "../lib/async-hook-supervisor.js"
2096
+ );
2054
2097
  _hookSupervisor = new AsyncHookSupervisor({
2055
2098
  persistStats: true,
2056
2099
  // Durably park failed-rewake signals keyed by session so a crash before
@@ -2161,6 +2204,7 @@ async function runAgentHeadlessInWorkspace(
2161
2204
  additionalDirectories,
2162
2205
  sandbox: options.sandbox || null,
2163
2206
  sessionId,
2207
+ sessionBudget: options.sessionBudget || null,
2164
2208
  // Content-free continuity metadata from the same verified sample used for
2165
2209
  // replay history and MCP recovery authority.
2166
2210
  sessionHostSnapshot: canonicalResume?.snapshot || null,
@@ -2373,8 +2417,9 @@ async function runAgentHeadlessInWorkspace(
2373
2417
  if (options.goal !== undefined && options.goal !== false) {
2374
2418
  try {
2375
2419
  const explicitId = typeof options.goal === "string" ? options.goal : null;
2376
- const { resolveActiveGoal, linkSession } =
2377
- await import("../lib/goal-store.js");
2420
+ const { resolveActiveGoal, linkSession } = await import(
2421
+ "../lib/goal-store.js"
2422
+ );
2378
2423
  const goal = (deps.resolveActiveGoal || resolveActiveGoal)({
2379
2424
  explicitId,
2380
2425
  sessionId,
@@ -2502,8 +2547,9 @@ async function runAgentHeadlessInWorkspace(
2502
2547
  let _asyncStopHandled = false;
2503
2548
  const _settleAsyncStop = async () => {
2504
2549
  if (!settingsHooks || !_hookSupervisor) return { rewakes: [], results: [] };
2505
- const { dispatchAsyncHooks } =
2506
- await import("../lib/settings-hook-events.js");
2550
+ const { dispatchAsyncHooks } = await import(
2551
+ "../lib/settings-hook-events.js"
2552
+ );
2507
2553
  dispatchAsyncHooks(
2508
2554
  settingsHooks,
2509
2555
  "Stop",
@@ -2554,6 +2600,7 @@ async function runAgentHeadlessInWorkspace(
2554
2600
  provider,
2555
2601
  model,
2556
2602
  source: "model",
2603
+ sessionBudget: options.sessionBudget || null,
2557
2604
  call: () =>
2558
2605
  chatWithTools([{ role: "user", content: judgePrompt }], {
2559
2606
  model,
@@ -2935,6 +2982,11 @@ async function runAgentHeadlessInWorkspace(
2935
2982
  ),
2936
2983
  );
2937
2984
  }
2985
+ beginSessionBudgetUsage(
2986
+ options.sessionBudget,
2987
+ event,
2988
+ "headless provider call",
2989
+ );
2938
2990
  break;
2939
2991
  }
2940
2992
  case "model-usage-unknown":
@@ -2948,6 +3000,10 @@ async function runAgentHeadlessInWorkspace(
2948
3000
  ),
2949
3001
  );
2950
3002
  }
3003
+ const budgetUsageUnknown = markSessionBudgetUsageUnknown(
3004
+ options.sessionBudget,
3005
+ event,
3006
+ );
2951
3007
  if (event.type === "compaction-usage-unknown") {
2952
3008
  endReason = "compaction-usage-unknown";
2953
3009
  stopForCompactionUsageUnknown = true;
@@ -2960,6 +3016,14 @@ async function runAgentHeadlessInWorkspace(
2960
3016
  usage_outcome: "unknown",
2961
3017
  });
2962
3018
  }
3019
+ if (budgetUsageUnknown) {
3020
+ rejectSessionBudgetUsageUnknown(
3021
+ event,
3022
+ event.type === "compaction-usage-unknown"
3023
+ ? "headless semantic compaction"
3024
+ : "headless provider call",
3025
+ );
3026
+ }
2963
3027
  break;
2964
3028
  }
2965
3029
  case "token-usage": {
@@ -2969,6 +3033,11 @@ async function runAgentHeadlessInWorkspace(
2969
3033
  store.appendTokenUsage(sessionId, persistedUsage),
2970
3034
  );
2971
3035
  }
3036
+ recordSessionBudgetUsage(
3037
+ options.sessionBudget,
3038
+ event,
3039
+ "headless usage settlement",
3040
+ );
2972
3041
  if (!event.attribution) {
2973
3042
  usage.input_tokens += event.usage?.input_tokens || 0;
2974
3043
  usage.output_tokens += event.usage?.output_tokens || 0;
@@ -3222,12 +3291,25 @@ async function runAgentHeadlessInWorkspace(
3222
3291
  } catch (err) {
3223
3292
  const runtimeLedgerPersistenceFailed =
3224
3293
  err?.runtimeLedgerPersistence === true;
3294
+ const sessionBudgetFailed =
3295
+ err?.code === "CC_SESSION_BUDGET_EXHAUSTED" ||
3296
+ err?.code === "CC_SESSION_BUDGET_USAGE_UNKNOWN" ||
3297
+ options.sessionBudget?.signal?.aborted === true;
3225
3298
  const message = runtimeLedgerPersistenceFailed
3226
3299
  ? RUNTIME_LEDGER_PERSISTENCE_FAILURE_MESSAGE
3227
- : err?.message || String(err);
3300
+ : err?.code === "CC_SESSION_BUDGET_USAGE_UNKNOWN"
3301
+ ? err.message
3302
+ : sessionBudgetFailed
3303
+ ? sessionBudgetAdmissionError(
3304
+ options.sessionBudget?.reason?.() || err?.budgetReason,
3305
+ "run",
3306
+ ).message
3307
+ : err?.message || String(err);
3228
3308
  const errorSubtype = runtimeLedgerPersistenceFailed
3229
3309
  ? "error_persistence"
3230
- : "error";
3310
+ : sessionBudgetFailed
3311
+ ? "error_session_budget"
3312
+ : "error";
3231
3313
  if (isStream) {
3232
3314
  emitStream({
3233
3315
  type: "result",
@@ -3258,7 +3340,10 @@ async function runAgentHeadlessInWorkspace(
3258
3340
  // Provider/transport failures get their own exit code (5) so CI can tell
3259
3341
  // "the model call failed" from "the run itself errored" (1).
3260
3342
  loopFailureOutcome = {
3261
- exitCode: runtimeLedgerPersistenceFailed ? 1 : classifyLoopError(err),
3343
+ exitCode:
3344
+ runtimeLedgerPersistenceFailed || sessionBudgetFailed
3345
+ ? 1
3346
+ : classifyLoopError(err),
3262
3347
  result: message,
3263
3348
  isError: true,
3264
3349
  };
@@ -3298,8 +3383,9 @@ async function runAgentHeadlessInWorkspace(
3298
3383
  await cleanupDeadline.run("settings-hooks", async () => {
3299
3384
  if (settingsHooks) {
3300
3385
  try {
3301
- const { runObserveHooks, dispatchAsyncHooks } =
3302
- await import("../lib/settings-hook-events.js");
3386
+ const { runObserveHooks, dispatchAsyncHooks } = await import(
3387
+ "../lib/settings-hook-events.js"
3388
+ );
3303
3389
  const stopPayload = {
3304
3390
  reason: pipeState.closed ? "pipe_closed" : endReason,
3305
3391
  cwd,
@@ -3497,6 +3583,7 @@ async function runAgentHeadlessInWorkspace(
3497
3583
  provider,
3498
3584
  model,
3499
3585
  source: "model",
3586
+ sessionBudget: options.sessionBudget || null,
3500
3587
  call: () =>
3501
3588
  chatWithTools([{ role: "user", content: assessPrompt }], {
3502
3589
  model,
@@ -3561,8 +3648,9 @@ async function runAgentHeadlessInWorkspace(
3561
3648
  emitStream({ type: "denials_summary", count: denials.length, denials });
3562
3649
  }
3563
3650
  try {
3564
- const { appendRecentDenials } =
3565
- await import("../lib/permission-denial-store.js");
3651
+ const { appendRecentDenials } = await import(
3652
+ "../lib/permission-denial-store.js"
3653
+ );
3566
3654
  appendRecentDenials(denials, {
3567
3655
  sessionId,
3568
3656
  permissionMode: options.permissionMode || "default",
@@ -3633,8 +3721,9 @@ async function runAgentHeadlessInWorkspace(
3633
3721
  }
3634
3722
  if (_collectorEnabled) {
3635
3723
  try {
3636
- const { exportTelemetryRecorder } =
3637
- await import("../lib/observability/index.js");
3724
+ const { exportTelemetryRecorder } = await import(
3725
+ "../lib/observability/index.js"
3726
+ );
3638
3727
  exportTelemetryRecorder(_otlpRecorder);
3639
3728
  } catch {
3640
3729
  // Telemetry is observational only and never changes the agent result.