chainlesschain 0.163.3 → 0.163.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 (209) hide show
  1. package/package.json +3 -2
  2. package/scripts/command-lifecycle-report.mjs +330 -38
  3. package/src/assets/web-panel/assets/{AIOps-DIY6KxV-.js → AIOps-Cv2EE1Zy.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-BXH0muPt.js → ActionButton-CcpxMLuW.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-D39w8vmg.js → Analytics-DE8mJoMI.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-CUU1zvLs.js → AppLayout-DKn9dk9L.js} +5 -5
  7. package/src/assets/web-panel/assets/{Artifacts-D8azHO3T.js → Artifacts-Cp3mG3Py.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-D0tAwXTg.js → Audit-zvsQfF2C.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-C29mhJll.js → BackgroundAgents-Bi85SsjN.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-D6Aa1Gro.js → Backup-Cw47Dj6s.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-B1uoHbPQ.js → BaseInput-C5Ip2afH.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-Bs4DLOR5.js → Chat-C0iAFkJv.js} +5 -5
  13. package/src/assets/web-panel/assets/{ChatBubbleRenderer-DUYIBSle.js → ChatBubbleRenderer-BV9Wv7wO.js} +1 -1
  14. package/src/assets/web-panel/assets/{Checkbox-CNcBPEa4.js → Checkbox-3KZZCiAF.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-CIY89763.js → Codegen-C8OMbBAz.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-CsPYFmgo.js → Col-B-MB84LJ.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-BBocEge4.js → Community-DpR7Dxao.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-TQ8Ux0Lf.js → Compact-CyDtz0OS.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-DfBsZTft.js → Compliance-5tiRa2An.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-Cg-I6FVH.js → Cowork-DnQaKZ5x.js} +4 -4
  21. package/src/assets/web-panel/assets/{Cron-DTQzfRTp.js → Cron-BaWfoEDf.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-DGxEKGpR.js → Crosschain-Bu0HoHhb.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-DLZ1RDSr.js → DID-31zk8upX.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-XneICKNI.js → Dashboard-BmVne-e2.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-BRU00J1-.js → Dropdown-B4PkoOWd.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-BzCbJuAy.js → EmailListRenderer-BZ6tyFtI.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-D7BRyNBG.js → FamilyGuardDashboard-Osozn4Ds.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-D9DeFIhW.js → Federation-DaH8TOAP.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-6rAtA9Ko.js → FormItemContext-tbU0uwis.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-8Hqy80pU.js → GenericCardRenderer-Df8LQBrL.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-Cmvkj1rt.js → Git-DsMB6-14.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-BRiQUjjw.js → Governance-BnH0dZzd.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-CKN_EzVf.js → Inference-DhnN1N_P.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-BCDHwpwQ.js → KnowledgeGraph-DnNshAgn.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-DK9ovhaB.js → Logs-BmBFX3_N.js} +2 -2
  36. package/src/assets/web-panel/assets/{MarkdownRenderer-D53pHiHy.js → MarkdownRenderer-DCslfQU3.js} +1 -1
  37. package/src/assets/web-panel/assets/{Marketplace-BILPGakp.js → Marketplace-CPEgWDc3.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-DTVCOr9-.js → McpTools-C36qjgF9.js} +5 -5
  39. package/src/assets/web-panel/assets/{Memory-Hzc1iow4.js → Memory-tNHvrgqN.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-GXfgnGYV.js → MobileBridge-Xaf6cKjc.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-B-3TJWsS.js → MobileProjects-D2E5TTeO.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-DwSJMWtK.js → Mtc-D4AJ2dwV.js} +4 -4
  43. package/src/assets/web-panel/assets/{MtcAudit-D2uxf-DA.js → MtcAudit-Df-gtn2_.js} +4 -4
  44. package/src/assets/web-panel/assets/{Multisig-DG6kbKK0.js → Multisig-DTCHLWld.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-f5p49EDU.js → NLProgramming-DruZ_1Jb.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-FUgHyzSD.js → Notes-Dx3pdGDs.js} +4 -4
  47. package/src/assets/web-panel/assets/{NotificationSettings-DCHGee7e.js → NotificationSettings-Bi3L69oL.js} +1 -1
  48. package/src/assets/web-panel/assets/{OrderTableRenderer-Dm6LlIoa.js → OrderTableRenderer-BHY33m7C.js} +1 -1
  49. package/src/assets/web-panel/assets/{Organization-BawA7qAg.js → Organization-BG2ZVEV-.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-D6a5wZU1.js → Overflow-Viwtg4Mn.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-K8WavwnA.js → P2P-Clm_yc1Z.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-4JAJYaqx.js → PdhVaultBrowser-NKmmDiOw.js} +5 -5
  53. package/src/assets/web-panel/assets/{Permissions-BDWvi8PD.js → Permissions-DIL8u9Nk.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-DF_K4E9i.js → PersonalDataHub-B-jM4wt-.js} +4 -4
  55. package/src/assets/web-panel/assets/{Pipeline-BYeZlesI.js → Pipeline-627I__H5.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-BIHlgnIc.js → Privacy-2DN2qrkW.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-Cvf-6B5P.js → ProjectInit-CN4wC0sF.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-CnwfJrRz.js → ProjectSettings-K35vsh5H.js} +2 -2
  59. package/src/assets/web-panel/assets/Projects-B_wQadhX.js +1 -0
  60. package/src/assets/web-panel/assets/{Providers-CxC7JuYv.js → Providers-MckaQUhQ.js} +1 -1
  61. package/src/assets/web-panel/assets/{QrScannerModal-VLf3gAfL.js → QrScannerModal-BS3mtA_O.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-B5vGjRiF.js → QuickAsk-BHp_nofL.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend--UW4iYs-.js → Recommend-DlmnPuZj.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-DMSPcfKR.js → RemoteSession-tsyFbvpy.js} +2 -2
  65. package/src/assets/web-panel/assets/{Reputation-kQXlEHmj.js → Reputation-Ba1iWv2D.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-CxGu3pit.js → Row-NnlGC--f.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-Bi5lo8MZ.js → RssFeed-CjThSIRv.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-Cq_H5RTh.js → Search-CojUyC5x.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-YFbmkaQS.js → Security-c-sxeJEc.js} +3 -3
  70. package/src/assets/web-panel/assets/{Services-DLOGdaLm.js → Services-CtcKEEmF.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-CteIxb3D.js → Skeleton-CIBBXflN.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-CccopaIZ.js → Skills-D1XOOK9n.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-AzfEQKX1.js → Sla-hRfEp5Sn.js} +1 -1
  74. package/src/assets/web-panel/assets/{SpeechSettings-ekGo5l77.js → SpeechSettings-Dexb1f_6.js} +1 -1
  75. package/src/assets/web-panel/assets/{SyncSettings-BmZmAgYH.js → SyncSettings-BJsSFGYy.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-D7q3Z4uL.js → Tasks-CfSZ8A1L.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-CX1Tgeka.js → Templates-idDf47W-.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-Zc59jF4i.js → Tenant-C-UsX6w6.js} +1 -1
  79. package/src/assets/web-panel/assets/{Terminal-CXOD7y83.js → Terminal-BgJtX5n1.js} +2 -2
  80. package/src/assets/web-panel/assets/{TimelineRenderer-B1aBHPBo.js → TimelineRenderer-DP0BLKTl.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-zALlOq_U.js → Tokens-LwCzqETp.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-CQfJMXaq.js → Trigger-D_9tVch0.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-BU0RcM-w.js → Trust-BH2UlEWh.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-IFZ3HsbH.js → UkeySign-CIpD0nYb.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-BzslgW0v.js → VideoEditing-9ShhYxK_.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-BZAcQNS6.js → Wallet-C7afGNIG.js} +4 -4
  87. package/src/assets/web-panel/assets/{WebAuthn-CBK1DMi0.js → WebAuthn-bUKn6i5R.js} +3 -3
  88. package/src/assets/web-panel/assets/{WorkflowEditor-BlMTPzO-.js → WorkflowEditor-CxgQaGyp.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-B51-8QVn.js → chat-DMVkmJwx.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-504RTByU.js → colors-CDzQh5nS.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-C-GP6IQM.js → compact-item-C51kEF4D.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-DOkIj7ID.js → createContext-BTk9bXBn.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-CdwPwYj8.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-DN7V-_FW.js → hasIn-CMje33rb.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-CKTfZyfU.js → index-0Auljb10.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-D9LyiN-L.js → index-B0-zMtKA.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-DEMPUVa3.js → index-BAfY7m7i.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-Bkxhaeta.js → index-BBz9LIMS.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-7jIqHbzw.js → index-BCRvG9lq.js} +1 -1
  100. package/src/assets/web-panel/assets/index-BEeOdfEe.js +1 -0
  101. package/src/assets/web-panel/assets/index-BTe0TOu6.js +1 -0
  102. package/src/assets/web-panel/assets/{index-P2mfY27Z.js → index-BTlsE8Df.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DAOpQvl_.js → index-BVePe_Rf.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CYopNjcJ.js → index-BW4F5YDF.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-B_vGU-Js.js → index-BXQBPLyE.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-kt_5rfcZ.js → index-BeEaAEIp.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-Cao5DZy7.js → index-BtlEqHLP.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DA2f1UV3.js → index-BzCkNylB.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-B2-x9bS8.js → index-C1oZQmAA.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-D1phyca8.js → index-C1oZReaY.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-FcV8J_Qz.js → index-C4rQCS8T.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-C3TSohzc.js → index-C5IWTMVl.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-CySTJKeq.js → index-CCLj9hcD.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-C9_48OzU.js → index-CDLkNkLj.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-so8eIIxF.js → index-Cd0hmPxD.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CX78k-qf.js → index-CfC-piWZ.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-DE-hmI2l.js → index-CtM8OT_7.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-kAqQXfP6.js → index-CvSeVzqe.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-C0k_Nqg9.js → index-CwGPwjUu.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CP2A226L.js → index-CypsfcEq.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-CfiEM64n.js → index-D9rC-fGW.js} +3 -3
  122. package/src/assets/web-panel/assets/{index-yYTQZypF.js → index-DJfnCuMq.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-f4Bo4KXm.js → index-DRG-aqOs.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-By6u5IV1.js → index-DRLQyp2A.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-ConjaJro.js → index-DgivOKHA.js} +1 -1
  126. package/src/assets/web-panel/assets/{index--n-ZciV3.js → index-DpcrFxMI.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CqcLo5WV.js → index-DqU9njjT.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-CUhQpiYv.js → index-Ld_4mFmC.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-C4DV_5uA.js → index-OS-vfbTA.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-DaA__-q1.js → index-h31MwrME.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BFIFJ5Dr.js → index-hg_emBsi.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-C8UltbXK.js → index-togc_uYn.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-et5JIPHO.js → index-x53Vf7la.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-CPYEIdpV.js → initDefaultProps-vrA8K-ac.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-Cjim9pxs.js → motion-ByEzwIAl.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-DuU-cgz3.js → move-Ck4AWjw-.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-DJHNAkta.js → mtc-parser-6p0l9SrB.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-DSQBgdBj.js → omit-B1CUPQ6R.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-CTmT_j5m.js → pickAttrs-B1STg1iW.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-Lfm6v-r4.js → placementArrow-DTTllkBV.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-CgrcPcDi.js → responsiveObserve-AIrrCfBb.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-CuE3110i.js → slide-C_fPMjdR.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-DiK5nbpf.js → statusUtils-D5ow2yIP.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-DPEJdQaZ.js → styleChecker-Dy3hEA--.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-CnnodGmp.js → useFlexGapSupport-WfzcfSh4.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-DWF84Yav.js → useFs-CKSejfas.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-a5b5Dw2f.js → usePersonalDataHub-od3zpPBN.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-DAluzXOq.js → vnode-DRD_2DFA.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-Dokg7uAZ.js → zoom-DmNrEtgf.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/command-help-index.json +1 -1
  152. package/src/commands/agenda.js +52 -6
  153. package/src/commands/artifacts.js +98 -0
  154. package/src/commands/cowork.js +24 -12
  155. package/src/commands/mcp.js +1 -1
  156. package/src/commands/review.js +221 -22
  157. package/src/commands/routine.js +40 -10
  158. package/src/commands/session-mcp-recovery.js +5 -5
  159. package/src/data/changelog.json +27 -1
  160. package/src/gateways/ws/ws-agent-handler.js +492 -14
  161. package/src/harness/jsonl-session-store.js +39 -1
  162. package/src/harness/mcp-client.js +172 -29
  163. package/src/harness/prompt-compressor.js +24 -0
  164. package/src/harness/provider-backed-compaction.js +205 -0
  165. package/src/lib/agent-schedule-store.js +197 -4
  166. package/src/lib/app-preview.js +3 -0
  167. package/src/lib/command-lifecycle-report.js +1340 -145
  168. package/src/lib/cowork-cron.js +243 -25
  169. package/src/lib/delivery-coordinator.js +30 -5
  170. package/src/lib/delivery-production-adapter.js +1777 -0
  171. package/src/lib/delivery-production-runner.js +240 -0
  172. package/src/lib/durable-security-store.js +29 -17
  173. package/src/lib/execution-trace/trace-context.cjs +179 -0
  174. package/src/lib/execution-trace/trace-context.js +8 -175
  175. package/src/lib/mcp-call-ledger-store.js +58 -6
  176. package/src/lib/mcp-host-recovery-runtime.js +2 -0
  177. package/src/lib/mcp-ledger-recovery-admission.js +39 -3
  178. package/src/lib/mcp-recovery-adjudication.js +256 -19
  179. package/src/lib/mcp-sandbox-policy.js +29 -0
  180. package/src/lib/mcp-stdio-capsule-builder-worker.cjs +495 -0
  181. package/src/lib/mcp-stdio-executable-identity.js +33 -2
  182. package/src/lib/mcp-stdio-immutable-vfs-resolver.cjs +830 -0
  183. package/src/lib/mcp-stdio-package-materialization.js +721 -333
  184. package/src/lib/micro-compact.js +11 -5
  185. package/src/lib/observability/index.js +2 -0
  186. package/src/lib/observability/otlp-exporter.js +2 -2
  187. package/src/lib/packer/pack-update-applier.js +8 -1
  188. package/src/lib/packer/pkg-config-generator.js +34 -0
  189. package/src/lib/process-execution-broker/index.js +48 -8
  190. package/src/lib/process-execution-broker/platform-sandbox.js +82 -1
  191. package/src/lib/routine-store.js +76 -3
  192. package/src/lib/scheduler-kernel/agenda-adapter.js +542 -0
  193. package/src/lib/scheduler-kernel/contract.js +315 -0
  194. package/src/lib/scheduler-kernel/cowork-cron-adapter.js +774 -0
  195. package/src/lib/scheduler-kernel/routine-adapter.js +517 -0
  196. package/src/lib/scheduler-kernel/runtime.js +527 -0
  197. package/src/lib/scheduler-kernel/store.js +1455 -0
  198. package/src/lib/session-host-lease.js +403 -30
  199. package/src/lib/session-message-provenance.js +4 -1
  200. package/src/lib/session-persistence-failure.js +4 -1
  201. package/src/lib/sub-agent-context.js +8 -0
  202. package/src/repl/agent-repl.js +309 -43
  203. package/src/runtime/agent-core.js +1079 -105
  204. package/src/runtime/headless-runner.js +260 -166
  205. package/src/runtime/headless-stream.js +254 -25
  206. package/src/assets/web-panel/assets/Projects-b-jPXzF4.js +0 -1
  207. package/src/assets/web-panel/assets/devWarning-kB0nCNwN.js +0 -1
  208. package/src/assets/web-panel/assets/index-Bya64sZE.js +0 -1
  209. package/src/assets/web-panel/assets/index-D_FWpDZM.js +0 -1
@@ -16,6 +16,7 @@ import { isProxy } from "node:util/types";
16
16
  import WebSocket from "ws";
17
17
  import { safeJsonParse } from "../lib/safe-json.js";
18
18
  import {
19
+ enforceMcpStdioCapsuleHostSandboxPolicy,
19
20
  MCP_SANDBOX_POLICY_INVALID_CODE,
20
21
  normalizeMcpSandboxPolicy,
21
22
  readMcpStdioCwd,
@@ -40,7 +41,7 @@ import {
40
41
  verifyMcpStdioApprovedWorkingDirectory,
41
42
  } from "../lib/mcp-stdio-execution-authority.js";
42
43
  import {
43
- MCP_STDIO_CAPSULE_CODE_SNAPSHOT_BOUNDARY,
44
+ MCP_STDIO_CAPSULE_REQUIRED_BOUNDARIES,
44
45
  prepareMcpStdioExecutableIdentity,
45
46
  } from "../lib/mcp-stdio-executable-identity.js";
46
47
  import { resolveMcpStdioSandboxContext } from "../lib/mcp-stdio-workspace-authority.js";
@@ -611,6 +612,102 @@ function mcpTransportError(code, message, details = {}) {
611
612
  return error;
612
613
  }
613
614
 
615
+ function dispatchMcpToolRequest(options, metadata, dispatch) {
616
+ const admission = options?.dispatchAdmission ?? null;
617
+ if (metadata.method !== "tools/call" || admission === null) {
618
+ return dispatch();
619
+ }
620
+ if (typeof admission !== "function") {
621
+ throw mcpTransportError(
622
+ "CC_MCP_DISPATCH_ADMISSION_INVALID",
623
+ "MCP tool dispatch authority is invalid",
624
+ {
625
+ transport: metadata.transport,
626
+ dispatched: false,
627
+ outcomeUnknown: false,
628
+ },
629
+ );
630
+ }
631
+
632
+ let admissionOpen = true;
633
+ let dispatched = false;
634
+ let dispatchResult;
635
+ const admittedDispatch = () => {
636
+ if (!admissionOpen || dispatched) {
637
+ throw mcpTransportError(
638
+ "CC_MCP_DISPATCH_ADMISSION_INVALID",
639
+ "MCP tool dispatch authority invoked its one-shot send outside the admission window",
640
+ { transport: metadata.transport },
641
+ );
642
+ }
643
+ dispatched = true;
644
+ dispatchResult = dispatch();
645
+ return dispatchResult;
646
+ };
647
+
648
+ try {
649
+ const admissionResult = admission(
650
+ Object.freeze({ ...metadata }),
651
+ admittedDispatch,
652
+ );
653
+ if (!dispatched) {
654
+ throw mcpTransportError(
655
+ "CC_MCP_DISPATCH_ADMISSION_REQUIRED",
656
+ "MCP tool dispatch authority did not synchronously admit the request",
657
+ { transport: metadata.transport },
658
+ );
659
+ }
660
+ if (admissionResult !== dispatchResult) {
661
+ throw mcpTransportError(
662
+ "CC_MCP_DISPATCH_AUTHORITY_OUTCOME_UNKNOWN",
663
+ "MCP tool dispatch started, but the host did not synchronously return the admitted send",
664
+ {
665
+ transport: metadata.transport,
666
+ dispatched: true,
667
+ outcomeUnknown: true,
668
+ },
669
+ );
670
+ }
671
+ return dispatchResult;
672
+ } catch (cause) {
673
+ if (!dispatched) {
674
+ if (safeRpcProperty(cause, "dispatched") === false) throw cause;
675
+ const causeCode = safeRpcProperty(cause, "code");
676
+ const error = mcpTransportError(
677
+ typeof causeCode === "string" && causeCode.startsWith("CC_")
678
+ ? causeCode
679
+ : "CC_MCP_DISPATCH_NOT_ADMITTED",
680
+ "MCP tool request was not dispatched because host authority denied admission",
681
+ {
682
+ transport: metadata.transport,
683
+ dispatched: false,
684
+ outcomeUnknown: false,
685
+ },
686
+ );
687
+ error.cause = cause;
688
+ throw error;
689
+ }
690
+ if (safeRpcProperty(cause, "outcomeUnknown") === true) {
691
+ throw cause;
692
+ }
693
+ const error = mcpTransportError(
694
+ "CC_MCP_DISPATCH_AUTHORITY_OUTCOME_UNKNOWN",
695
+ "MCP tool dispatch started, but the host could not durably confirm its dispatch authority",
696
+ {
697
+ transport: metadata.transport,
698
+ dispatched: true,
699
+ outcomeUnknown: true,
700
+ },
701
+ );
702
+ error.cause = cause;
703
+ throw error;
704
+ } finally {
705
+ // An admission callback must invoke the send before returning. This also
706
+ // prevents an async callback from retaining a usable dispatch capability.
707
+ admissionOpen = false;
708
+ }
709
+ }
710
+
614
711
  function mcpWebSocketPayloadTooLargeError(
615
712
  serverName,
616
713
  { transport, url, limitBytes, closeCode = 1009 },
@@ -1973,6 +2070,17 @@ export class MCPClient extends EventEmitter {
1973
2070
  stdioExecutableIdentityDigest = prepared.identityDigest;
1974
2071
  stdioCapsuleSandboxExecutionContract =
1975
2072
  prepared.sandboxExecutionContract || null;
2073
+ if (stdioCapsuleSandboxExecutionContract) {
2074
+ runtimeConfig = {
2075
+ ...runtimeConfig,
2076
+ sandboxPolicy: enforceMcpStdioCapsuleHostSandboxPolicy(
2077
+ sourceConfig.sandboxPolicy,
2078
+ {
2079
+ label: `MCP stdio server "${name}" capsule sandboxPolicy`,
2080
+ },
2081
+ ),
2082
+ };
2083
+ }
1976
2084
  }
1977
2085
  const connectionHeaders = await this._connectionHeaders(
1978
2086
  name,
@@ -2394,17 +2502,13 @@ export class MCPClient extends EventEmitter {
2394
2502
  // Broker's Job Object boundary so an unexpectedly exiting MCP root
2395
2503
  // cannot orphan grandchildren before taskkill can enumerate them.
2396
2504
  detached: process.platform !== "win32",
2397
- ...(process.platform === "win32" ||
2398
- stdioCapsuleSandboxExecutionContract
2505
+ ...(stdioCapsuleSandboxExecutionContract
2399
2506
  ? {
2400
- requiredBoundaries: [
2401
- ...(process.platform === "win32" ? ["process-tree"] : []),
2402
- ...(stdioCapsuleSandboxExecutionContract
2403
- ? [MCP_STDIO_CAPSULE_CODE_SNAPSHOT_BOUNDARY]
2404
- : []),
2405
- ],
2507
+ requiredBoundaries: MCP_STDIO_CAPSULE_REQUIRED_BOUNDARIES,
2406
2508
  }
2407
- : {}),
2509
+ : process.platform === "win32"
2510
+ ? { requiredBoundaries: ["process-tree"] }
2511
+ : {}),
2408
2512
  pluginId: config.pluginId,
2409
2513
  pluginVersion: config.pluginVersion,
2410
2514
  pluginSource: config.pluginSource,
@@ -2427,11 +2531,15 @@ export class MCPClient extends EventEmitter {
2427
2531
  process.cwd(),
2428
2532
  )
2429
2533
  : null);
2534
+ const effectiveRuntimeSandboxBoundaries = new Set([
2535
+ ...(spawnOptions.requiredBoundaries || []),
2536
+ ...(config.sandboxPolicy?.requiredBoundaries || []),
2537
+ ]);
2430
2538
  const capsuleUsesLinuxProcessTreeSandbox =
2431
2539
  Boolean(stdioCapsuleSandboxExecutionContract) &&
2432
2540
  process.platform === "linux" &&
2433
- sourceConfig.sandboxPolicy?.requiredBoundaries?.some((boundary) =>
2434
- ["filesystem", "network", "process-tree"].includes(boundary),
2541
+ MCP_STDIO_CAPSULE_REQUIRED_BOUNDARIES.every((boundary) =>
2542
+ effectiveRuntimeSandboxBoundaries.has(boundary),
2435
2543
  );
2436
2544
  const capsuleUsesPosixProcessGroup =
2437
2545
  Boolean(stdioCapsuleSandboxExecutionContract) &&
@@ -2895,7 +3003,7 @@ export class MCPClient extends EventEmitter {
2895
3003
  * @param {string} serverName - Server name
2896
3004
  * @param {string} toolName - Tool name
2897
3005
  * @param {object} args - Tool arguments
2898
- * @param {{signal?: AbortSignal}} options - Host-owned cancellation
3006
+ * @param {{signal?: AbortSignal, dispatchAdmission?: Function}} options - Host-owned cancellation and dispatch authority
2899
3007
  */
2900
3008
  async callTool(serverName, toolName, args = {}, options = {}) {
2901
3009
  if (options?.signal?.aborted) {
@@ -3381,8 +3489,19 @@ export class MCPClient extends EventEmitter {
3381
3489
  }
3382
3490
 
3383
3491
  try {
3384
- dispatched = true;
3385
- entry.process.stdin.write(message + "\n");
3492
+ dispatchMcpToolRequest(
3493
+ options,
3494
+ {
3495
+ serverName,
3496
+ method,
3497
+ transport: entry.transportKind || "stdio",
3498
+ requestId: id,
3499
+ },
3500
+ () => {
3501
+ dispatched = true;
3502
+ return entry.process.stdin.write(message + "\n");
3503
+ },
3504
+ );
3386
3505
  } catch (err) {
3387
3506
  settle(reject, err);
3388
3507
  }
@@ -3499,13 +3618,26 @@ export class MCPClient extends EventEmitter {
3499
3618
  );
3500
3619
  };
3501
3620
  try {
3502
- dispatched = true;
3503
- entry.socket.send(message, (cause) => {
3504
- if (!cause) return;
3505
- failDispatch();
3506
- });
3507
- } catch {
3508
- failDispatch();
3621
+ dispatchMcpToolRequest(
3622
+ options,
3623
+ {
3624
+ serverName,
3625
+ method,
3626
+ transport: entry.transportKind || "ws",
3627
+ requestId: id,
3628
+ },
3629
+ () => {
3630
+ dispatched = true;
3631
+ return entry.socket.send(message, (cause) => {
3632
+ if (!cause) return;
3633
+ failDispatch();
3634
+ });
3635
+ },
3636
+ );
3637
+ } catch (error) {
3638
+ if (error?.outcomeUnknown === true) settle(reject, error);
3639
+ else if (!dispatched) settle(reject, error);
3640
+ else failDispatch();
3509
3641
  }
3510
3642
  });
3511
3643
  }
@@ -3843,13 +3975,24 @@ export class MCPClient extends EventEmitter {
3843
3975
 
3844
3976
  try {
3845
3977
  throwIfAborted();
3846
- const responsePromise = _deps.fetch(entry.httpUrl, {
3847
- method: "POST",
3848
- headers,
3849
- body,
3850
- ...(controller ? { signal: controller.signal } : {}),
3851
- });
3852
- if (request) request.dispatched = true;
3978
+ const responsePromise = dispatchMcpToolRequest(
3979
+ options,
3980
+ {
3981
+ serverName,
3982
+ method,
3983
+ transport: entry.transportKind || "http",
3984
+ requestId: id,
3985
+ },
3986
+ () => {
3987
+ if (request) request.dispatched = true;
3988
+ return _deps.fetch(entry.httpUrl, {
3989
+ method: "POST",
3990
+ headers,
3991
+ body,
3992
+ ...(controller ? { signal: controller.signal } : {}),
3993
+ });
3994
+ },
3995
+ );
3853
3996
  const response = await responsePromise;
3854
3997
  if (request) request.response = response;
3855
3998
  throwIfAborted();
@@ -11,6 +11,7 @@
11
11
 
12
12
  import { createHash } from "node:crypto";
13
13
  import { feature, featureVariant } from "../lib/feature-flags.js";
14
+ import { isAbortError } from "../lib/abort-utils.js";
14
15
  import {
15
16
  DURABLE_SYSTEM_MESSAGE_KINDS,
16
17
  getDurableSystemMessageProvenance,
@@ -566,6 +567,8 @@ export class PromptCompressor {
566
567
  let degradedReason = null;
567
568
  let rawSummary;
568
569
  let summaryUsage = null;
570
+ let summaryUsageUnknown = false;
571
+ let summaryUsageUnknownReason = null;
569
572
  let summaryProvider = null;
570
573
  let summaryModel = null;
571
574
  try {
@@ -592,6 +595,12 @@ export class PromptCompressor {
592
595
  usage.cache_creation_tokens,
593
596
  ) || 0,
594
597
  };
598
+ } else if (queryResult.usageOutcome !== "not-billable") {
599
+ // Standard provider adapters return an explicit `usage` field. A
600
+ // successful response without it is still a paid call whose amount
601
+ // is unknown; never let a hard budget silently count it as zero.
602
+ summaryUsageUnknown = true;
603
+ summaryUsageUnknownReason = "provider_usage_not_reported";
595
604
  }
596
605
  summaryProvider = queryResult.provider || null;
597
606
  summaryModel = queryResult.model || null;
@@ -599,9 +608,18 @@ export class PromptCompressor {
599
608
  rawSummary = queryResult;
600
609
  }
601
610
  } catch (error) {
611
+ // Cancellation is authoritative. Treating AbortError as an ordinary
612
+ // provider failure would manufacture an extractive summary after Stop and
613
+ // let callers apply/persist it even though the operation was cancelled.
614
+ if (isAbortError(error)) throw error;
602
615
  degraded = true;
603
616
  summaryMode = "extractive-fallback";
604
617
  degradedReason = `llm_query_failed:${boundedFailureMessage(error)}`;
618
+ // A transport exception does not prove that the provider rejected the
619
+ // request before billing it. Keep that uncertainty explicit so a hard
620
+ // budget can latch instead of silently accounting the call as $0.
621
+ summaryUsageUnknown = true;
622
+ summaryUsageUnknownReason = "provider_transport_outcome_unknown";
605
623
  }
606
624
  if (!degraded) {
607
625
  try {
@@ -644,6 +662,12 @@ export class PromptCompressor {
644
662
  summaryInputChars: prompt.length,
645
663
  summaryInputLimit: this.summaryInputMaxChars,
646
664
  ...(summaryUsage ? { summaryUsage } : {}),
665
+ ...(summaryUsageUnknown
666
+ ? {
667
+ summaryUsageUnknown: true,
668
+ summaryUsageUnknownReason,
669
+ }
670
+ : {}),
647
671
  ...(summaryProvider ? { summaryProvider } : {}),
648
672
  ...(summaryModel ? { summaryModel } : {}),
649
673
  },
@@ -0,0 +1,205 @@
1
+ import {
2
+ estimateMessagesTokens,
3
+ PromptCompressor,
4
+ sanitizeToolPairs,
5
+ } from "./prompt-compressor.js";
6
+
7
+ const DEFAULT_MAX_OUTPUT_TOKENS = 2048;
8
+ const MIN_MAX_OUTPUT_TOKENS = 256;
9
+ const MAX_MAX_OUTPUT_TOKENS = 4096;
10
+ const MANUAL_MAX_MESSAGES = 4;
11
+
12
+ function boundedMaxOutputTokens(value) {
13
+ const parsed = Math.trunc(Number(value));
14
+ if (!Number.isFinite(parsed) || parsed <= 0) {
15
+ return DEFAULT_MAX_OUTPUT_TOKENS;
16
+ }
17
+ return Math.min(
18
+ MAX_MAX_OUTPUT_TOKENS,
19
+ Math.max(MIN_MAX_OUTPUT_TOKENS, parsed),
20
+ );
21
+ }
22
+
23
+ function tokenCount(value) {
24
+ const parsed = Number(value);
25
+ return Number.isFinite(parsed) && parsed > 0 ? Math.trunc(parsed) : 0;
26
+ }
27
+
28
+ function responseSummary(response) {
29
+ if (typeof response === "string") return response;
30
+ return response?.message?.content ?? response?.content ?? "";
31
+ }
32
+
33
+ function preserveCompletedExchange(originalMessages, compactedMessages) {
34
+ if (originalMessages.at(-1)?.role === "user") return compactedMessages;
35
+ let lastUserIndex = -1;
36
+ for (let index = originalMessages.length - 1; index >= 0; index -= 1) {
37
+ if (originalMessages[index]?.role === "user") {
38
+ lastUserIndex = index;
39
+ break;
40
+ }
41
+ }
42
+ if (lastUserIndex < 0) return compactedMessages;
43
+
44
+ const completedExchange = originalMessages.slice(lastUserIndex);
45
+ const exchangeMessages = new Set(completedExchange);
46
+ const prefix = compactedMessages.filter(
47
+ (message) => !exchangeMessages.has(message),
48
+ );
49
+ return sanitizeToolPairs([...prefix, ...completedExchange]);
50
+ }
51
+
52
+ /**
53
+ * Convert PromptCompressor's provider-neutral summary accounting into the
54
+ * token-usage wire shape shared by the agent hosts.
55
+ */
56
+ export function compactionTokenUsage(stats) {
57
+ const usage = stats?.summaryUsage;
58
+ if (!usage || typeof usage !== "object") return null;
59
+ return {
60
+ input_tokens: tokenCount(usage.inputTokens),
61
+ output_tokens: tokenCount(usage.outputTokens),
62
+ cache_read_input_tokens: tokenCount(usage.cacheReadTokens),
63
+ cache_creation_input_tokens: tokenCount(usage.cacheCreationTokens),
64
+ };
65
+ }
66
+
67
+ /**
68
+ * Build one provider-backed semantic compaction operation.
69
+ *
70
+ * The provider request is deliberately tool-free. A missing provider adapter,
71
+ * transport error, or malformed summary is handled by PromptCompressor's
72
+ * structured extractive handoff, so every host gets the same safe degradation
73
+ * contract instead of falling back to positional truncation.
74
+ */
75
+ export async function compactConversationWithProvider(messages, options = {}) {
76
+ const originalMessages = Array.isArray(messages) ? [...messages] : [];
77
+ const provider = options.provider || null;
78
+ const model = options.model || null;
79
+ const maxOutputTokens = boundedMaxOutputTokens(options.maxOutputTokens);
80
+ const chatFn = options.chatFn;
81
+ const llmQuery =
82
+ typeof options.llmQuery === "function"
83
+ ? options.llmQuery
84
+ : async (prompt) => {
85
+ if (typeof chatFn !== "function") {
86
+ throw new Error("provider adapter unavailable");
87
+ }
88
+ const response = await chatFn([{ role: "user", content: prompt }], {
89
+ ...(options.chatOptions || {}),
90
+ provider,
91
+ model,
92
+ baseUrl: options.baseUrl,
93
+ apiKey: options.apiKey,
94
+ signal: options.signal,
95
+ contextEngine: null,
96
+ enabledToolNames: [],
97
+ extraToolDefinitions: [],
98
+ hostManagedToolPolicy: null,
99
+ onToken: undefined,
100
+ onStall: undefined,
101
+ onStreamRetry: undefined,
102
+ maxOutputTokens,
103
+ });
104
+ return {
105
+ summary: responseSummary(response),
106
+ usage: response?.usage || null,
107
+ provider,
108
+ model,
109
+ };
110
+ };
111
+
112
+ const compressor =
113
+ options.compressor ||
114
+ new PromptCompressor({
115
+ model,
116
+ provider,
117
+ llmQuery,
118
+ ...(options.force === true
119
+ ? { maxMessages: options.maxMessages || MANUAL_MAX_MESSAGES }
120
+ : options.maxMessages
121
+ ? { maxMessages: options.maxMessages }
122
+ : {}),
123
+ ...(options.maxTokens ? { maxTokens: options.maxTokens } : {}),
124
+ summaryInputMaxChars: options.summaryInputMaxChars,
125
+ });
126
+ if (
127
+ options.onlyIfNeeded === true &&
128
+ !compressor.shouldAutoCompact(originalMessages)
129
+ ) {
130
+ const originalTokens = estimateMessagesTokens(originalMessages);
131
+ return {
132
+ messages: originalMessages,
133
+ stats: {
134
+ strategy: "none",
135
+ originalMessages: originalMessages.length,
136
+ compressedMessages: originalMessages.length,
137
+ originalTokens,
138
+ compressedTokens: originalTokens,
139
+ saved: 0,
140
+ ratio: 1,
141
+ trimmed: 0,
142
+ },
143
+ degradedEvent: null,
144
+ usageEvent: null,
145
+ usageUnknownEvent: null,
146
+ };
147
+ }
148
+ const result = await compressor.compress(originalMessages, {
149
+ preserveToolPairs: true,
150
+ ...(typeof options.isPinned === "function"
151
+ ? { isPinned: options.isPinned }
152
+ : {}),
153
+ });
154
+ const compactedMessages =
155
+ options.preserveCompletedExchange === true
156
+ ? preserveCompletedExchange(originalMessages, result.messages)
157
+ : result.messages;
158
+ const originalTokens = estimateMessagesTokens(originalMessages);
159
+ const compressedTokens = estimateMessagesTokens(compactedMessages);
160
+ const stats = {
161
+ ...result.stats,
162
+ originalMessages: originalMessages.length,
163
+ compressedMessages: compactedMessages.length,
164
+ originalTokens,
165
+ compressedTokens,
166
+ saved: originalTokens - compressedTokens,
167
+ ratio: originalTokens > 0 ? compressedTokens / originalTokens : 1,
168
+ trimmed: Math.max(0, originalMessages.length - compactedMessages.length),
169
+ };
170
+ const usage = compactionTokenUsage(stats);
171
+ const usageUnknownEvent =
172
+ stats.summaryUsageUnknown === true
173
+ ? {
174
+ provider: stats.summaryProvider || provider,
175
+ model: stats.summaryModel || model,
176
+ source: "semantic-compaction",
177
+ reason:
178
+ stats.summaryUsageUnknownReason ||
179
+ "provider_transport_outcome_unknown",
180
+ usageOutcome: "unknown",
181
+ }
182
+ : null;
183
+
184
+ return {
185
+ messages: compactedMessages,
186
+ stats,
187
+ degradedEvent:
188
+ stats.degraded === true
189
+ ? {
190
+ reason: stats.degradedReason || "semantic-summary-degraded",
191
+ summaryMode: stats.summaryMode || "extractive-fallback",
192
+ stats,
193
+ }
194
+ : null,
195
+ usageEvent: usage
196
+ ? {
197
+ provider: stats.summaryProvider || provider,
198
+ model: stats.summaryModel || model,
199
+ usage,
200
+ source: "semantic-compaction",
201
+ }
202
+ : null,
203
+ usageUnknownEvent,
204
+ };
205
+ }