chainlesschain 0.163.6 → 0.163.7

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 (218) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/assets/{AIOps-DDIUofA8.js → AIOps-axqQfwv8.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-Bm-5xYRn.js → ActionButton-DV-Ro0By.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-D5UH4ljI.js → Analytics-Bt72WEVu.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-D_ifjOOP.js → AppLayout-BtepG55E.js} +5 -5
  6. package/src/assets/web-panel/assets/{Artifacts-BY1mXdC7.js → Artifacts-B7KaJ7S_.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-Bujr4Ml3.js → Audit-FNFaUg7A.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-sioKSTcC.js → BackgroundAgents-DFb6J2wQ.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-DDOAK8RK.js → Backup-CC7YBhyj.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-CtCsVVke.js → BaseInput-RkgTNVtj.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-DpNj0vnd.js → Chat-hHEmGZy-.js} +4 -4
  12. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CZta3Ftr.js → ChatBubbleRenderer-CAP9YhHv.js} +1 -1
  13. package/src/assets/web-panel/assets/{Checkbox-DoHVNSXq.js → Checkbox-z5wXOQP1.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-DlVl7Qmv.js → Codegen-DVaDJnxy.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-GIqoPYty.js → Col-CJmaRDR5.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-CIAPEVji.js → Community-DF29_2bI.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-BN7JiI_h.js → Compact-DtkQkBzn.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-CqUWCM9B.js → Compliance-xoHDxp7I.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-A4iPp7A4.js → Cowork-BUm-R7ht.js} +3 -3
  20. package/src/assets/web-panel/assets/{Cron-B2zeXXWb.js → Cron-Cgl14ZkB.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-BR2xmWr8.js → Crosschain-BNcbmoqh.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-BzFDjrIv.js → DID-Bwja0Zo9.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-DKtDo3yA.js → Dashboard-Bk5XjEdJ.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-RNx43_YG.js → Dropdown-Ci36Oitq.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-SwMt4Rcy.js → EmailListRenderer--U04ZN4q.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-CsYebZ4X.js → FamilyGuardDashboard-B2gNPR2s.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-BmRKvBTy.js → Federation-C4KghYn7.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-CVxGTA-0.js → FormItemContext-QL7x_Q_0.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-x2iXpyB7.js → GenericCardRenderer-F3Ryltwm.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-DfqbkiOP.js → Git-2HassK5k.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-RuHyyj5O.js → Governance-DoBIp7oe.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-Bn7uZ7rI.js → Inference--W01QhZ-.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-DlP7XefZ.js → KnowledgeGraph-DmvwqGpT.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-BYNdOiCd.js → Logs-BBJ4yAel.js} +2 -2
  35. package/src/assets/web-panel/assets/{MarkdownRenderer-aMtgN-R6.js → MarkdownRenderer-BLCZMzhJ.js} +1 -1
  36. package/src/assets/web-panel/assets/{Marketplace-JQYmDqM8.js → Marketplace-D5lNngSI.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-Cyx4yZ-9.js → McpTools-CkEVOMKH.js} +4 -4
  38. package/src/assets/web-panel/assets/{Memory-VDuGZTN2.js → Memory-B1Ow1xVE.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-_yKo97gi.js → MobileBridge-SgYbUfb6.js} +1 -1
  40. package/src/assets/web-panel/assets/{MobileProjects-CXRXW3q7.js → MobileProjects-BWdOvQAj.js} +1 -1
  41. package/src/assets/web-panel/assets/{Mtc-acTGtfLH.js → Mtc-DcTXSSma.js} +5 -5
  42. package/src/assets/web-panel/assets/{MtcAudit-ClpjXfkY.js → MtcAudit-Dt3WG4oj.js} +4 -4
  43. package/src/assets/web-panel/assets/{Multisig-_6Tn3o96.js → Multisig-B9B38UZx.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-CK7pbZzP.js → NLProgramming-B0S4GGvG.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-Czy6V_P8.js → Notes-DZ5U58Ng.js} +3 -3
  46. package/src/assets/web-panel/assets/{NotificationSettings-Cqx-UVv3.js → NotificationSettings-PjL5ZW34.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-C69WDxGy.js → OrderTableRenderer-DrAX2ESt.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-DFnA9vLQ.js → Organization-Cv1GYs-c.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-ReZkk2yT.js → Overflow-Bbkp_PL3.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-DzjSI0aI.js → P2P-BD8QUgoZ.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-DKTf5xIP.js → PdhVaultBrowser-BO-2PeaB.js} +3 -3
  52. package/src/assets/web-panel/assets/{Permissions-DhQ5klhR.js → Permissions-D_OPVa02.js} +4 -4
  53. package/src/assets/web-panel/assets/{PersonalDataHub-CUL1iHrW.js → PersonalDataHub-mh-pEmaB.js} +4 -4
  54. package/src/assets/web-panel/assets/{Pipeline-DU88iu4N.js → Pipeline-6JC2EDdb.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-Bw-sYfyK.js → Privacy-CUshzUAG.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-Bq3Q5y0z.js → ProjectInit-Cs2Aalri.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-C8spzpho.js → ProjectSettings-1ak49tcj.js} +2 -2
  58. package/src/assets/web-panel/assets/Projects-BV4oApsm.js +1 -0
  59. package/src/assets/web-panel/assets/{Providers-Bf4eTP9W.js → Providers-CXXxvafH.js} +1 -1
  60. package/src/assets/web-panel/assets/{QrScannerModal-Dme9BDU1.js → QrScannerModal-PTcDsF58.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-CIXfv1rE.js → QuickAsk-CDwucrJw.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-CIxvdeZ-.js → Recommend-CJlLVRXR.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-C6k7MExI.js → RemoteSession-DlN-ETsO.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-CISDz2bl.js → Reputation-DI23LR6m.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-CdnDxXyf.js → Row-Cl7UQMrM.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-C-QpRHsl.js → RssFeed-CexHNfh8.js} +3 -3
  67. package/src/assets/web-panel/assets/{Search-DBjaGzSn.js → Search-BneBWvRN.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-CQKukOeE.js → Security-DX7Phgrp.js} +4 -4
  69. package/src/assets/web-panel/assets/{Services-DZz86jWb.js → Services-BWXO8Mte.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-jb8RMK0d.js → Skeleton-DCyOjKPJ.js} +1 -1
  71. package/src/assets/web-panel/assets/{Skills-CdY76fZG.js → Skills-CXqERsTB.js} +1 -1
  72. package/src/assets/web-panel/assets/{Sla-C_CSiZX9.js → Sla-bhbrbz8E.js} +1 -1
  73. package/src/assets/web-panel/assets/SpeechSettings-3IPU0HBZ.js +1 -0
  74. package/src/assets/web-panel/assets/{SyncSettings-qvimGO0O.js → SyncSettings-DBNTQLbM.js} +2 -2
  75. package/src/assets/web-panel/assets/{Tasks-Dng5LPJC.js → Tasks-quP0bkN-.js} +1 -1
  76. package/src/assets/web-panel/assets/{Templates-Bwqq5Wll.js → Templates-BouWmgho.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-DNWuwP7Z.js → Tenant-qv0D9s7z.js} +1 -1
  78. package/src/assets/web-panel/assets/{Terminal-B-6Othpp.js → Terminal-BxvbE8BB.js} +2 -2
  79. package/src/assets/web-panel/assets/{TimelineRenderer-DKpKZfzx.js → TimelineRenderer-D-IeLnJ2.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-DzfGMd2J.js → Tokens-CFMKKyVG.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger-BXwUi74J.js → Trigger-L8as3UuJ.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-BNzUq4ui.js → Trust-MxmA4VZG.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-BYugxww4.js → UkeySign-C0VvJYRi.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-DdauhtSJ.js → VideoEditing-Bf5QZj8N.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-CSC9bCe_.js → Wallet-BIJ9riRz.js} +4 -4
  86. package/src/assets/web-panel/assets/{WebAuthn-Q8AN3bTO.js → WebAuthn-B8p9Mhkw.js} +5 -5
  87. package/src/assets/web-panel/assets/{WorkflowEditor-d-LBGCuA.js → WorkflowEditor-BVsuaPen.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-BLVDCgsZ.js → chat-BfkjoKpV.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-BZlPSEHl.js → colors-DeAlsWK8.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-IWseP6R6.js → compact-item-Cs97bz5j.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-DnVRV3Ao.js → createContext-BqbG60LH.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-DPty0mGN.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-DLQZA_Wn.js → hasIn-i_RY0b1X.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-B_N4-Gq9.js → index-0-agYlWL.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-DB0MJgF_.js → index-79V_zv1s.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-BOZJBTWZ.js → index-B-3tEpTc.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-DUq0c7gq.js → index-B-JVTrpr.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-Dy0R5ZED.js → index-B1CbOH1i.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-Bxp7uDD8.js → index-B5UkyA3c.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DpVrK6fr.js → index-BESLFt4q.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CT9vVN-X.js → index-BOVkf1K3.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-DOoQpuQY.js → index-BYUVuwKt.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-CINJQEj6.js → index-BcUXAB2s.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CarMTIyQ.js → index-BkBi5TmC.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-C5dgnilC.js → index-Bm7lLR4c.js} +1 -1
  106. package/src/assets/web-panel/assets/index-Bt7g0Vq_.js +1 -0
  107. package/src/assets/web-panel/assets/{index-CbQNL0ue.js → index-BuLQobzW.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-CpBaJ3TD.js → index-CE2VtTlp.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-jWb70ZgZ.js → index-CED2PL_y.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-BEu2lMBy.js → index-CG3PRyAL.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DocEhinm.js → index-CIG8fQ2_.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-D_LQodeJ.js → index-COdGA-8n.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-DZpYeqrh.js → index-CeWoNHau.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-gt8bNefW.js → index-Cf3WCLmy.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-N_GoWZX4.js → index-CgsqdnRV.js} +1 -1
  116. package/src/assets/web-panel/assets/index-ChVT0p9u.js +1 -0
  117. package/src/assets/web-panel/assets/{index-CZDekj7T.js → index-D2B4VPyP.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-YSw_gxlZ.js → index-D9evtvg2.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DTbxp4UH.js → index-DUUrv141.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Bbj2NS_I.js → index-DiSkx4UB.js} +3 -3
  121. package/src/assets/web-panel/assets/{index-BZs5bBnk.js → index-Dk2qouAz.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DalA0TKC.js → index-Dk7-v4hP.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-1jeAudHd.js → index-DmbfhJUP.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-C1ifZtXo.js → index-DqBgBpgp.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-BhA3QEni.js → index-PT_5sBMA.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-BSjilZ9L.js → index-U4f5izHz.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-C2FqfMvU.js → index-YXgLng0K.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-COev0W2g.js → index-ZxO_-E8a.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-M7wxfAbm.js → index-dIHr4B_u.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-DjWnONdy.js → index-gyFpvL7l.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-Dkwsi1Kn.js → index-s1opAL-M.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-hwVDeoC0.js → index-yObj1O4n.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-Co67Kqmb.js → initDefaultProps-C9h9yKL3.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-BMOxQSF_.js → motion-BvmLsPdu.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-C5fWDw-N.js → move-CoL4ekU1.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-BJevpL0e.js → mtc-parser-C4pMy6xV.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-BCzNU8s6.js → omit-DPuJfNxx.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-CybWvDPk.js → pickAttrs-D0KEeaK2.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-BMWS9HnW.js → placementArrow-BpkyINxt.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-BoL2UnGY.js → responsiveObserve-DQI_wOq8.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-DWNfXraU.js → slide-DYfdDiRg.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-BquTM3tX.js → statusUtils-B5dtvb0D.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-BEkCleim.js → styleChecker-CF310mSj.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-Oecnq7EA.js → useFlexGapSupport-D1Qp4BLp.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-CkDffJ4F.js → useFs-C7_iyvJK.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-qbvKXesB.js → usePersonalDataHub-DZUt_fIm.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-C6v8n6mA.js → vnode-D3dsi0lZ.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-4CTeFILV.js → zoom-WdbOlvdQ.js} +1 -1
  149. package/src/assets/web-panel/index.html +1 -1
  150. package/src/command-help-index.json +2 -2
  151. package/src/commands/agent.js +90 -1
  152. package/src/commands/chat.js +11 -2
  153. package/src/commands/compact.js +106 -23
  154. package/src/commands/loop.js +28 -10
  155. package/src/commands/routine.js +1 -1
  156. package/src/commands/scheduler-daemon.js +359 -2
  157. package/src/commands/session-observability.js +305 -0
  158. package/src/commands/session.js +38 -0
  159. package/src/data/changelog.json +14 -1
  160. package/src/gateways/ws/ws-agent-handler.js +439 -5
  161. package/src/harness/jsonl-session-store.js +463 -125
  162. package/src/harness/prompt-compressor.js +86 -13
  163. package/src/harness/provider-backed-compaction.js +100 -27
  164. package/src/lib/advisor-runtime.js +3 -1
  165. package/src/lib/agent-schedule-store.js +414 -4
  166. package/src/lib/agent-team/team-adjudication.js +40 -1
  167. package/src/lib/automation-engine.js +494 -0
  168. package/src/lib/background-agent-supervisor.js +793 -215
  169. package/src/lib/background-command-argv.js +24 -0
  170. package/src/lib/background-interaction-journal.js +361 -52
  171. package/src/lib/background-interaction-resolver.js +32 -0
  172. package/src/lib/background-launch-profile.js +2 -0
  173. package/src/lib/causal-observability.js +2661 -0
  174. package/src/lib/chat-session-admission.js +76 -0
  175. package/src/lib/cost-budget.js +5 -7
  176. package/src/lib/cowork/ab-comparator-cli.js +11 -0
  177. package/src/lib/cowork/debate-review-cli.js +12 -0
  178. package/src/lib/cowork-adapter.js +159 -38
  179. package/src/lib/cowork-cron.js +357 -1
  180. package/src/lib/cowork-task-runner.js +112 -17
  181. package/src/lib/delivery-coordinator.js +142 -0
  182. package/src/lib/direct-model-usage.js +121 -0
  183. package/src/lib/file-lines.js +183 -47
  184. package/src/lib/llm-pricing.js +12 -17
  185. package/src/lib/loop.js +26 -2
  186. package/src/lib/routine-store.js +380 -21
  187. package/src/lib/runtime-usage-ledger.js +182 -0
  188. package/src/lib/scheduler-kernel/agenda-adapter.js +308 -3
  189. package/src/lib/scheduler-kernel/automation-adapter.js +410 -8
  190. package/src/lib/scheduler-kernel/automation-event-adapter.js +36 -0
  191. package/src/lib/scheduler-kernel/cowork-cron-adapter.js +285 -3
  192. package/src/lib/scheduler-kernel/loop-adapter.js +541 -6
  193. package/src/lib/scheduler-kernel/migration-admin.js +346 -0
  194. package/src/lib/scheduler-kernel/migration-rollback-admin.js +932 -0
  195. package/src/lib/scheduler-kernel/routine-adapter.js +394 -20
  196. package/src/lib/scheduler-kernel/runtime.js +63 -1
  197. package/src/lib/scheduler-kernel/source-locator-path.js +142 -0
  198. package/src/lib/scheduler-kernel/store.js +2586 -85
  199. package/src/lib/session-host-lease.js +171 -2
  200. package/src/lib/session-host-snapshot.js +14 -3
  201. package/src/lib/session-persistence-failure.js +1 -0
  202. package/src/lib/session-tail.js +179 -34
  203. package/src/lib/session-transcript-structure.js +96 -0
  204. package/src/lib/sub-agent-context.js +328 -22
  205. package/src/lib/ws-agent-handler.js +4 -1
  206. package/src/repl/agent-repl.js +732 -91
  207. package/src/repl/chat-repl.js +5 -1
  208. package/src/runtime/agent-core.js +1272 -207
  209. package/src/runtime/fallback-model.js +5 -0
  210. package/src/runtime/headless-runner.js +324 -82
  211. package/src/runtime/headless-stream.js +232 -26
  212. package/src/runtime/policies/agent-policy.js +4 -0
  213. package/src/workers/background-agent-worker.js +403 -96
  214. package/src/assets/web-panel/assets/Projects-Dd-xuPIc.js +0 -1
  215. package/src/assets/web-panel/assets/SpeechSettings-C7tT9iad.js +0 -1
  216. package/src/assets/web-panel/assets/devWarning-Jzu62CLC.js +0 -1
  217. package/src/assets/web-panel/assets/index-Zb2MeDSy.js +0 -1
  218. package/src/assets/web-panel/assets/index-fikqml4k.js +0 -1
@@ -0,0 +1,76 @@
1
+ import {
2
+ readVerifiedProjection,
3
+ resolveSessionAuthority,
4
+ } from "../harness/jsonl-session-store.js";
5
+
6
+ export const CHAT_CALL_LEDGER_UNSUPPORTED = "CC_CHAT_CALL_LEDGER_UNSUPPORTED";
7
+ export const CHAT_SESSION_NOT_FOUND = "CC_CHAT_SESSION_NOT_FOUND";
8
+ export const CHAT_SESSION_UNAVAILABLE = "CC_CHAT_SESSION_UNAVAILABLE";
9
+
10
+ function admissionError(code, message) {
11
+ const error = new Error(message);
12
+ error.code = code;
13
+ return error;
14
+ }
15
+
16
+ function sessionDeclaresProtectedUsage(sessionId, projectionReader) {
17
+ return projectionReader(sessionId, () => {
18
+ let protectedUsage = false;
19
+ let sessionStartSeen = false;
20
+ return {
21
+ accept(event) {
22
+ if (event?.type !== "session_start" || sessionStartSeen) return;
23
+ sessionStartSeen = true;
24
+ const data =
25
+ event.data &&
26
+ typeof event.data === "object" &&
27
+ !Array.isArray(event.data)
28
+ ? event.data
29
+ : {};
30
+ protectedUsage = [
31
+ "observabilityScope",
32
+ "usageTelemetryProtocol",
33
+ "usageTelemetryVersion",
34
+ ].some((field) => Object.hasOwn(data, field));
35
+ },
36
+ finish() {
37
+ return protectedUsage;
38
+ },
39
+ };
40
+ });
41
+ }
42
+
43
+ /**
44
+ * Admit only an explicitly present, readable and fully verified legacy session.
45
+ * Interactive chat cannot yet durably bracket its provider calls, so any scope
46
+ * or call-ledger declaration must fail before the REPL appends or spends.
47
+ */
48
+ export function assertChatSessionUsageAdmission(
49
+ sessionReference,
50
+ {
51
+ resolveAuthority = resolveSessionAuthority,
52
+ readProjection = readVerifiedProjection,
53
+ } = {},
54
+ ) {
55
+ if (!sessionReference) return;
56
+ const authority = resolveAuthority(sessionReference);
57
+ if (!authority) {
58
+ throw admissionError(
59
+ CHAT_SESSION_NOT_FOUND,
60
+ "Interactive chat session was not found",
61
+ );
62
+ }
63
+ if (!authority.readable) {
64
+ throw admissionError(
65
+ CHAT_SESSION_UNAVAILABLE,
66
+ "Interactive chat session is not readable and cannot be resumed safely",
67
+ );
68
+ }
69
+ if (!sessionDeclaresProtectedUsage(authority.id, readProjection)) {
70
+ return authority.id;
71
+ }
72
+ throw admissionError(
73
+ CHAT_CALL_LEDGER_UNSUPPORTED,
74
+ "Scoped call-ledger sessions are not supported by interactive chat; use agent mode or an IDE host with usage-ledger support",
75
+ );
76
+ }
@@ -19,11 +19,6 @@
19
19
 
20
20
  import { estimateCost } from "./llm-pricing.js";
21
21
 
22
- const round = (n, dp = 6) => {
23
- const f = Math.pow(10, dp);
24
- return Math.round((Number(n) + Number.EPSILON) * f) / f;
25
- };
26
-
27
22
  /** Parse a `--max-budget-usd` value into a positive number, or null when unset. */
28
23
  export function parseBudgetUsd(value) {
29
24
  if (value == null || value === "") return null;
@@ -94,7 +89,10 @@ export class CostBudget {
94
89
  // otherwise treat the record as unpriced.
95
90
  const cost = Number(est.totalCost);
96
91
  if (Number.isFinite(cost) && cost >= 0) {
97
- this.spentUsd = round(this.spentUsd + cost);
92
+ // Preserve sub-microdollar charges. Formatting belongs at the UI edge;
93
+ // rounding here can turn a positive paid call into zero and disable a
94
+ // sufficiently small hard budget.
95
+ this.spentUsd += cost;
98
96
  this.priced = true;
99
97
  } else {
100
98
  this.sawUnpriced = true;
@@ -114,7 +112,7 @@ export class CostBudget {
114
112
  remaining() {
115
113
  return this.limitUsd == null
116
114
  ? Infinity
117
- : Math.max(0, round(this.limitUsd - this.spentUsd));
115
+ : Math.max(0, this.limitUsd - this.spentUsd);
118
116
  }
119
117
 
120
118
  /**
@@ -10,6 +10,10 @@ import { runPeerGroup } from "./agent-group-runner.js";
10
10
 
11
11
  const DEFAULT_CRITERIA = ["quality", "performance", "readability"];
12
12
 
13
+ function throwRuntimeLedgerFailure(error) {
14
+ if (error?.runtimeLedgerPersistence === true) throw error;
15
+ }
16
+
13
17
  const VARIANT_PROFILES = [
14
18
  {
15
19
  name: "conservative",
@@ -84,6 +88,12 @@ export async function compare({
84
88
  },
85
89
  });
86
90
 
91
+ // Ordinary variant failures remain comparable, but a host ledger failure
92
+ // must escape before judging can spend again or a partial result is emitted.
93
+ for (const outcome of runResult.results) {
94
+ throwRuntimeLedgerFailure(outcome.error);
95
+ }
96
+
87
97
  const generatedVariants = runResult.results.map((r) => {
88
98
  if (r.ok) return r.value;
89
99
  const profile = r.peer.payload.profile;
@@ -135,6 +145,7 @@ REASON: (1-2 sentence justification)`;
135
145
  winner = parseWinner(judgement) || generatedVariants[0]?.name || "unknown";
136
146
  reason = parseReason(judgement) || "See detailed scores above.";
137
147
  } catch (err) {
148
+ throwRuntimeLedgerFailure(err);
138
149
  reason = `Scoring error: ${err.message}`;
139
150
  }
140
151
 
@@ -10,6 +10,10 @@ import { runPeerGroup } from "./agent-group-runner.js";
10
10
 
11
11
  const DEFAULT_PERSPECTIVES = ["performance", "security", "maintainability"];
12
12
 
13
+ function throwRuntimeLedgerFailure(error) {
14
+ if (error?.runtimeLedgerPersistence === true) throw error;
15
+ }
16
+
13
17
  const PERSPECTIVE_PROMPTS = {
14
18
  performance: {
15
19
  role: "Performance Reviewer",
@@ -96,6 +100,13 @@ export async function startDebate({
96
100
  },
97
101
  });
98
102
 
103
+ // Peer groups intentionally turn ordinary reviewer failures into result
104
+ // rows. A durable usage-ledger failure is host-terminal, not review content:
105
+ // let the REPL latch stop this and every later paid call.
106
+ for (const outcome of runResult.results) {
107
+ throwRuntimeLedgerFailure(outcome.error);
108
+ }
109
+
99
110
  const reviews = runResult.results.map((r) => {
100
111
  if (r.ok) return r.value;
101
112
  return {
@@ -142,6 +153,7 @@ export async function startDebate({
142
153
  finalVerdict = extractVerdict(summary);
143
154
  consensusScore = extractConsensusScore(summary);
144
155
  } catch (err) {
156
+ throwRuntimeLedgerFailure(err);
145
157
  summary = `Moderator error: ${err.message}`;
146
158
  }
147
159
 
@@ -11,6 +11,86 @@ import { LLMProviderRegistry, BUILT_IN_PROVIDERS } from "./llm-providers.js";
11
11
  import { loadConfig } from "./config-manager.js";
12
12
  import { applyConfigLlmDefaults } from "./llm-config-defaults.js";
13
13
 
14
+ function plainUsage(value) {
15
+ return value && typeof value === "object" && !Array.isArray(value)
16
+ ? value
17
+ : null;
18
+ }
19
+
20
+ function normalizeOllamaUsage(data) {
21
+ if (
22
+ !Object.hasOwn(data, "prompt_eval_count") ||
23
+ !Object.hasOwn(data, "eval_count")
24
+ ) {
25
+ return null;
26
+ }
27
+ return {
28
+ input_tokens: data.prompt_eval_count,
29
+ output_tokens: data.eval_count,
30
+ cache_read_input_tokens: 0,
31
+ cache_creation_input_tokens: 0,
32
+ };
33
+ }
34
+
35
+ function normalizeAnthropicUsage(value) {
36
+ const usage = plainUsage(value);
37
+ if (!usage) return null;
38
+ // Keep malformed provider fields malformed so the canonical ledger projects
39
+ // the call as unknown instead of manufacturing a known zero settlement.
40
+ return {
41
+ input_tokens: usage.input_tokens,
42
+ output_tokens: usage.output_tokens,
43
+ cache_read_input_tokens: Object.hasOwn(usage, "cache_read_input_tokens")
44
+ ? usage.cache_read_input_tokens
45
+ : 0,
46
+ cache_creation_input_tokens: Object.hasOwn(
47
+ usage,
48
+ "cache_creation_input_tokens",
49
+ )
50
+ ? usage.cache_creation_input_tokens
51
+ : 0,
52
+ };
53
+ }
54
+
55
+ function normalizeOpenAiUsage(value) {
56
+ const usage = plainUsage(value);
57
+ if (!usage) return null;
58
+ // OpenAI/volcengine report cached prompt tokens under the nested detail;
59
+ // DeepSeek reports the same quantity as prompt_cache_hit_tokens. In both
60
+ // cases prompt_tokens includes the cached prefix, so persist only the
61
+ // uncached remainder as input_tokens.
62
+ const detailed = Number(usage.prompt_tokens_details?.cached_tokens);
63
+ const deepseek = Number(usage.prompt_cache_hit_tokens);
64
+ const cached =
65
+ Number.isFinite(detailed) && detailed > 0
66
+ ? detailed
67
+ : Number.isFinite(deepseek) && deepseek > 0
68
+ ? deepseek
69
+ : 0;
70
+ const input =
71
+ typeof usage.prompt_tokens === "number" && typeof cached === "number"
72
+ ? usage.prompt_tokens - cached
73
+ : usage.prompt_tokens;
74
+ return {
75
+ input_tokens: input,
76
+ output_tokens: usage.completion_tokens,
77
+ cache_read_input_tokens: cached,
78
+ cache_creation_input_tokens: 0,
79
+ };
80
+ }
81
+
82
+ function chatEnvelope(content, usage = null) {
83
+ return {
84
+ content: typeof content === "string" ? content : "",
85
+ ...(usage ? { usage } : {}),
86
+ };
87
+ }
88
+
89
+ async function invokeChatCall(callWrapper, provider, model, call) {
90
+ if (!callWrapper) return call();
91
+ return callWrapper({ call, provider, model });
92
+ }
93
+
14
94
  /**
15
95
  * Create a chat completion function that routes through the active LLM provider.
16
96
  *
@@ -26,6 +106,10 @@ import { applyConfigLlmDefaults } from "./llm-config-defaults.js";
26
106
  * @param {string} [options.model] - Model name override
27
107
  * @param {string} [options.baseUrl] - Base URL override
28
108
  * @param {string} [options.apiKey] - API key override
109
+ * @param {(request: {call: function, provider: string, model: string}) => Promise<object>} [options.callWrapper]
110
+ * Optional host boundary around each real provider call. The callback
111
+ * resolves to a private `{content, usage?}` envelope; callers still
112
+ * receive only the response string.
29
113
  * @returns {(messages: object[], opts?: object) => Promise<string>}
30
114
  */
31
115
  export function createChatFn(options = {}) {
@@ -47,25 +131,40 @@ export function createChatFn(options = {}) {
47
131
  const model =
48
132
  resolved.model || process.env.LLM_MODEL || providerDef.models[0];
49
133
  const baseUrl = resolved.baseUrl || providerDef.baseUrl;
134
+ const callWrapper = resolved.callWrapper || null;
135
+ if (callWrapper !== null && typeof callWrapper !== "function") {
136
+ throw new TypeError("cowork callWrapper must be a function");
137
+ }
50
138
 
51
139
  return async function chat(messages, opts = {}) {
52
140
  const currentModel = opts.model || model;
53
141
  const maxTokens = opts.maxTokens || 2048;
54
142
 
55
143
  if (provider === "ollama") {
56
- const res = await fetch(`${baseUrl}/api/chat`, {
57
- method: "POST",
58
- headers: { "Content-Type": "application/json" },
59
- body: JSON.stringify({
60
- model: currentModel,
61
- messages,
62
- stream: false,
63
- options: { num_predict: maxTokens },
64
- }),
65
- });
66
- if (!res.ok) throw new Error(`Ollama error: ${res.status}`);
67
- const data = await res.json();
68
- return data.message?.content || "";
144
+ const envelope = await invokeChatCall(
145
+ callWrapper,
146
+ provider,
147
+ currentModel,
148
+ async () => {
149
+ const res = await fetch(`${baseUrl}/api/chat`, {
150
+ method: "POST",
151
+ headers: { "Content-Type": "application/json" },
152
+ body: JSON.stringify({
153
+ model: currentModel,
154
+ messages,
155
+ stream: false,
156
+ options: { num_predict: maxTokens },
157
+ }),
158
+ });
159
+ if (!res.ok) throw new Error(`Ollama error: ${res.status}`);
160
+ const data = await res.json();
161
+ return chatEnvelope(
162
+ data.message?.content,
163
+ normalizeOllamaUsage(data),
164
+ );
165
+ },
166
+ );
167
+ return typeof envelope === "string" ? envelope : envelope?.content || "";
69
168
  }
70
169
 
71
170
  if (provider === "anthropic") {
@@ -82,39 +181,61 @@ export function createChatFn(options = {}) {
82
181
  if (systemMsgs.length > 0) {
83
182
  body.system = systemMsgs.map((m) => m.content).join("\n");
84
183
  }
85
- const res = await fetch(`${baseUrl}/messages`, {
86
- method: "POST",
87
- headers: {
88
- "Content-Type": "application/json",
89
- "x-api-key": key,
90
- "anthropic-version": "2023-06-01",
184
+ const envelope = await invokeChatCall(
185
+ callWrapper,
186
+ provider,
187
+ currentModel,
188
+ async () => {
189
+ const res = await fetch(`${baseUrl}/messages`, {
190
+ method: "POST",
191
+ headers: {
192
+ "Content-Type": "application/json",
193
+ "x-api-key": key,
194
+ "anthropic-version": "2023-06-01",
195
+ },
196
+ body: JSON.stringify(body),
197
+ });
198
+ if (!res.ok) throw new Error(`Anthropic error: ${res.status}`);
199
+ const data = await res.json();
200
+ return chatEnvelope(
201
+ data.content?.[0]?.text,
202
+ normalizeAnthropicUsage(data.usage),
203
+ );
91
204
  },
92
- body: JSON.stringify(body),
93
- });
94
- if (!res.ok) throw new Error(`Anthropic error: ${res.status}`);
95
- const data = await res.json();
96
- return data.content?.[0]?.text || "";
205
+ );
206
+ return typeof envelope === "string" ? envelope : envelope?.content || "";
97
207
  }
98
208
 
99
209
  // OpenAI-compatible (openai, deepseek, dashscope, mistral, gemini)
100
210
  const key = resolved.apiKey || process.env[providerDef.apiKeyEnv];
101
211
  if (!key) throw new Error(`${providerDef.apiKeyEnv} not set`);
102
212
 
103
- const res = await fetch(`${baseUrl}/chat/completions`, {
104
- method: "POST",
105
- headers: {
106
- "Content-Type": "application/json",
107
- Authorization: `Bearer ${key}`,
213
+ const envelope = await invokeChatCall(
214
+ callWrapper,
215
+ provider,
216
+ currentModel,
217
+ async () => {
218
+ const res = await fetch(`${baseUrl}/chat/completions`, {
219
+ method: "POST",
220
+ headers: {
221
+ "Content-Type": "application/json",
222
+ Authorization: `Bearer ${key}`,
223
+ },
224
+ body: JSON.stringify({
225
+ model: currentModel,
226
+ messages,
227
+ max_tokens: maxTokens,
228
+ }),
229
+ });
230
+ if (!res.ok) throw new Error(`API error: ${res.status}`);
231
+ const data = await res.json();
232
+ return chatEnvelope(
233
+ data.choices?.[0]?.message?.content,
234
+ normalizeOpenAiUsage(data.usage),
235
+ );
108
236
  },
109
- body: JSON.stringify({
110
- model: currentModel,
111
- messages,
112
- max_tokens: maxTokens,
113
- }),
114
- });
115
- if (!res.ok) throw new Error(`API error: ${res.status}`);
116
- const data = await res.json();
117
- return data.choices?.[0]?.message?.content || "";
237
+ );
238
+ return typeof envelope === "string" ? envelope : envelope?.content || "";
118
239
  };
119
240
  }
120
241