chainlesschain 0.163.2 → 0.163.3

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 (185) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/assets/{AIOps-DnGsmsqJ.js → AIOps-DIY6KxV-.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-CrO6fcQ7.js → ActionButton-BXH0muPt.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-DsBdOaP2.js → Analytics-D39w8vmg.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-DmQslKUB.js → AppLayout-CUU1zvLs.js} +5 -5
  6. package/src/assets/web-panel/assets/{Artifacts-BvyrT_QQ.js → Artifacts-D8azHO3T.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-prndoLiC.js → Audit-D0tAwXTg.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-DOTFyA55.js → BackgroundAgents-C29mhJll.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-9zOnPp_8.js → Backup-D6Aa1Gro.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-C4PC6sAG.js → BaseInput-B1uoHbPQ.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-BBAF-W9v.js → Chat-Bs4DLOR5.js} +6 -6
  12. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CWhvvloO.js → ChatBubbleRenderer-DUYIBSle.js} +1 -1
  13. package/src/assets/web-panel/assets/{Checkbox-BI9iculd.js → Checkbox-CNcBPEa4.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-3DP9BCKb.js → Codegen-CIY89763.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-df-2TnJX.js → Col-CsPYFmgo.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-CHs8gG_A.js → Community-BBocEge4.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-CDfF6q7V.js → Compact-TQ8Ux0Lf.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-CthrDnO7.js → Compliance-DfBsZTft.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-HjIqsWJw.js → Cowork-Cg-I6FVH.js} +2 -2
  20. package/src/assets/web-panel/assets/{Cron-BKc196fb.js → Cron-DTQzfRTp.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-CJnjdc8W.js → Crosschain-DGxEKGpR.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-BHUy-8Q2.js → DID-DLZ1RDSr.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-QDB7sKeY.js → Dashboard-XneICKNI.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-DStcVK11.js → Dropdown-BRU00J1-.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-BwSUskMJ.js → EmailListRenderer-BzCbJuAy.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DgF_kurT.js → FamilyGuardDashboard-D7BRyNBG.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-k8wvv-wN.js → Federation-D9DeFIhW.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-C11qoq2r.js → FormItemContext-6rAtA9Ko.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-BIIpr9kg.js → GenericCardRenderer-8Hqy80pU.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-BlA1exTe.js → Git-Cmvkj1rt.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-CYa1ZYM4.js → Governance-BRiQUjjw.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-6_kKVIt6.js → Inference-CKN_EzVf.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-CB4AwxYy.js → KnowledgeGraph-BCDHwpwQ.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-xf7nHFAe.js → Logs-DK9ovhaB.js} +2 -2
  35. package/src/assets/web-panel/assets/MarkdownRenderer-D53pHiHy.js +1 -0
  36. package/src/assets/web-panel/assets/{Marketplace-aPg8e4Jt.js → Marketplace-BILPGakp.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-C-TNlVUf.js → McpTools-DTVCOr9-.js} +5 -5
  38. package/src/assets/web-panel/assets/{Memory-DMTPIpGa.js → Memory-Hzc1iow4.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-BxyvveRq.js → MobileBridge-GXfgnGYV.js} +1 -1
  40. package/src/assets/web-panel/assets/{MobileProjects-DyPCrAyQ.js → MobileProjects-B-3TJWsS.js} +1 -1
  41. package/src/assets/web-panel/assets/{Mtc-BdhqNXp6.js → Mtc-DwSJMWtK.js} +5 -5
  42. package/src/assets/web-panel/assets/{MtcAudit-Cz-HFxzW.js → MtcAudit-D2uxf-DA.js} +5 -5
  43. package/src/assets/web-panel/assets/{Multisig-CIUaFNsx.js → Multisig-DG6kbKK0.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-CWe6-J17.js → NLProgramming-f5p49EDU.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-vYAKeviU.js → Notes-FUgHyzSD.js} +3 -3
  46. package/src/assets/web-panel/assets/{NotificationSettings-DQL9-2d7.js → NotificationSettings-DCHGee7e.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-DnXj1jBn.js → OrderTableRenderer-Dm6LlIoa.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-B3spU8AN.js → Organization-BawA7qAg.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-DgEwo7vm.js → Overflow-D6a5wZU1.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-hujMRH8X.js → P2P-K8WavwnA.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-C_qhdg9h.js → PdhVaultBrowser-4JAJYaqx.js} +3 -3
  52. package/src/assets/web-panel/assets/{Permissions-vp7LMcSf.js → Permissions-BDWvi8PD.js} +4 -4
  53. package/src/assets/web-panel/assets/{PersonalDataHub-Dxr5Hgnq.js → PersonalDataHub-DF_K4E9i.js} +3 -3
  54. package/src/assets/web-panel/assets/{Pipeline-DEPZqqH4.js → Pipeline-BYeZlesI.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-DTpDiKPe.js → Privacy-BIHlgnIc.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-jDJsRWmF.js → ProjectInit-Cvf-6B5P.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-Dhor5RWH.js → ProjectSettings-CnwfJrRz.js} +2 -2
  58. package/src/assets/web-panel/assets/Projects-b-jPXzF4.js +1 -0
  59. package/src/assets/web-panel/assets/{Providers-BGs47s1a.js → Providers-CxC7JuYv.js} +1 -1
  60. package/src/assets/web-panel/assets/{QrScannerModal-CjIw-wIb.js → QrScannerModal-VLf3gAfL.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-DX6jcqoi.js → QuickAsk-B5vGjRiF.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-DopXkhar.js → Recommend--UW4iYs-.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-BLvqJE9c.js → RemoteSession-DMSPcfKR.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-DhRj2Me7.js → Reputation-kQXlEHmj.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-DQ53vuPq.js → Row-CxGu3pit.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-BslvwiBD.js → RssFeed-Bi5lo8MZ.js} +2 -2
  67. package/src/assets/web-panel/assets/{Search-DJKBDNKZ.js → Search-Cq_H5RTh.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-COhpxHER.js → Security-YFbmkaQS.js} +3 -3
  69. package/src/assets/web-panel/assets/{Services-dbulD6cI.js → Services-DLOGdaLm.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-ciIVNfhC.js → Skeleton-CteIxb3D.js} +1 -1
  71. package/src/assets/web-panel/assets/{Skills-AiRTkTCk.js → Skills-CccopaIZ.js} +1 -1
  72. package/src/assets/web-panel/assets/{Sla-DDMcWYBc.js → Sla-AzfEQKX1.js} +1 -1
  73. package/src/assets/web-panel/assets/{SpeechSettings-BPxWbpXO.js → SpeechSettings-ekGo5l77.js} +1 -1
  74. package/src/assets/web-panel/assets/{SyncSettings-BoEOXCyg.js → SyncSettings-BmZmAgYH.js} +2 -2
  75. package/src/assets/web-panel/assets/Tasks-D7q3Z4uL.js +1 -0
  76. package/src/assets/web-panel/assets/{Templates-UowY8Ixe.js → Templates-CX1Tgeka.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-DauSLQXN.js → Tenant-Zc59jF4i.js} +1 -1
  78. package/src/assets/web-panel/assets/{Terminal-DBj7Jneq.js → Terminal-CXOD7y83.js} +2 -2
  79. package/src/assets/web-panel/assets/{TimelineRenderer-UMrPwoZC.js → TimelineRenderer-B1aBHPBo.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-4ea96-bn.js → Tokens-zALlOq_U.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger--ISCqt4b.js → Trigger-CQfJMXaq.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-D4GVimRJ.js → Trust-BU0RcM-w.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-Ci-nXRQc.js → UkeySign-IFZ3HsbH.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-Cjk7mKPw.js → VideoEditing-BzslgW0v.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-BgOLOO3Z.js → Wallet-BZAcQNS6.js} +2 -2
  86. package/src/assets/web-panel/assets/{WebAuthn-CCX0K29i.js → WebAuthn-CBK1DMi0.js} +4 -4
  87. package/src/assets/web-panel/assets/{WorkflowEditor-Ch3zgIsE.js → WorkflowEditor-BlMTPzO-.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-DKOU_2Vb.js → chat-B51-8QVn.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-6OVo4u3C.js → colors-504RTByU.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-BH78Hlsq.js → compact-item-C-GP6IQM.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-CFRpSbbC.js → createContext-DOkIj7ID.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-kB0nCNwN.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-DNQhgcVi.js → hasIn-DN7V-_FW.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-dDkoL4Pe.js → index--n-ZciV3.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-CaYqY35Z.js → index-7jIqHbzw.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-BYrnm5Ob.js → index-B2-x9bS8.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-sm7W8AXy.js → index-BFIFJ5Dr.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-DKN2noIF.js → index-B_vGU-Js.js} +1 -1
  99. package/src/assets/web-panel/assets/{index--rq90rL9.js → index-Bkxhaeta.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CFPJ8yzF.js → index-By6u5IV1.js} +1 -1
  101. package/src/assets/web-panel/assets/index-Bya64sZE.js +1 -0
  102. package/src/assets/web-panel/assets/{index-caye7AOE.js → index-C0k_Nqg9.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BxRy5LPR.js → index-C3TSohzc.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-BepBTpa8.js → index-C4DV_5uA.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-D84id2Y4.js → index-C8UltbXK.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-Y9MJv28e.js → index-C9_48OzU.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-Bb6kDrUx.js → index-CKTfZyfU.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-CrcLHN2F.js → index-CP2A226L.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-CkNEMANR.js → index-CUhQpiYv.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-Cu3L4r5l.js → index-CX78k-qf.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DaDgdJYj.js → index-CYopNjcJ.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-Du0rnksC.js → index-Cao5DZy7.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-BaVE6E8y.js → index-CfiEM64n.js} +3 -3
  114. package/src/assets/web-panel/assets/{index-BujsOZfc.js → index-ConjaJro.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-hPY0fFrd.js → index-CqcLo5WV.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-BDSR7ecX.js → index-CySTJKeq.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-BHa4WyTZ.js → index-D1phyca8.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-nbfHl1oV.js → index-D9LyiN-L.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-CkqHgG-b.js → index-DA2f1UV3.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Eag8e_mA.js → index-DAOpQvl_.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-cdf7fd7d.js → index-DE-hmI2l.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-bKm3TUDp.js → index-DEMPUVa3.js} +1 -1
  123. package/src/assets/web-panel/assets/index-D_FWpDZM.js +1 -0
  124. package/src/assets/web-panel/assets/{index-7TC3S8SN.js → index-DaA__-q1.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-DvHGtNnF.js → index-FcV8J_Qz.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-B_Z-YoxX.js → index-P2mfY27Z.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-AuBhLqOm.js → index-et5JIPHO.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-D3RtTT4K.js → index-f4Bo4KXm.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-CNuCHHQT.js → index-kAqQXfP6.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-BkN3iTTp.js → index-kt_5rfcZ.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BnnXQot_.js → index-so8eIIxF.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-HNGGVF6o.js → index-yYTQZypF.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-BZ9w6jPL.js → initDefaultProps-CPYEIdpV.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-BnwUiOho.js → motion-Cjim9pxs.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-ByUKJnNm.js → move-DuU-cgz3.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-V7yK1KEl.js → mtc-parser-DJHNAkta.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-BEXBBt4j.js → omit-DSQBgdBj.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-qDm_46Gi.js → pickAttrs-CTmT_j5m.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-BIbhEo_0.js → placementArrow-Lfm6v-r4.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-NbPbDgA_.js → responsiveObserve-CgrcPcDi.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-BnUWglZ0.js → slide-CuE3110i.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-BX8_wZI5.js → statusUtils-DiK5nbpf.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-BV4OycQX.js → styleChecker-DPEJdQaZ.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-Od_H5llY.js → useFlexGapSupport-CnnodGmp.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-BWI-PyiX.js → useFs-DWF84Yav.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-BqMuhG3g.js → usePersonalDataHub-a5b5Dw2f.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-DNd23z6f.js → vnode-DAluzXOq.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-Cjaxnm7l.js → zoom-Dokg7uAZ.js} +1 -1
  149. package/src/assets/web-panel/index.html +1 -1
  150. package/src/command-help-index.json +1 -1
  151. package/src/commands/agenda.js +6 -5
  152. package/src/commands/agent.js +237 -75
  153. package/src/commands/agents.js +6 -0
  154. package/src/commands/background-session.js +11 -1
  155. package/src/commands/mcp.js +217 -30
  156. package/src/data/changelog.json +14 -1
  157. package/src/harness/mcp-client.js +242 -42
  158. package/src/harness/worktree-isolator.js +26 -3
  159. package/src/lib/agent-worktree.js +41 -2
  160. package/src/lib/background-agent-supervisor.js +790 -186
  161. package/src/lib/background-command-argv.js +318 -0
  162. package/src/lib/background-launch-profile.js +1 -0
  163. package/src/lib/background-phase-reporter.js +22 -2
  164. package/src/lib/background-worktree-policy.js +109 -0
  165. package/src/lib/cowork-mcp-tools.js +51 -6
  166. package/src/lib/cowork-task-runner.js +1 -0
  167. package/src/lib/mcp-headers-helper.js +76 -8
  168. package/src/lib/mcp-sandbox-policy.js +155 -0
  169. package/src/lib/mcp-stdio-execution-authority.js +163 -0
  170. package/src/lib/mcp-stdio-workspace-authority.js +252 -0
  171. package/src/lib/plugin-runtime/sandbox-policy.js +42 -2
  172. package/src/lib/process-execution-broker/index.js +179 -104
  173. package/src/lib/process-execution-broker/platform-sandbox.js +942 -168
  174. package/src/lib/process-tree-termination.js +17 -1
  175. package/src/lib/skill-mcp.js +65 -4
  176. package/src/lib/web-fetch.js +4 -4
  177. package/src/runtime/agent-runtime.js +61 -8
  178. package/src/runtime/mcp-config.js +235 -28
  179. package/src/workers/background-agent-worker.js +492 -71
  180. package/src/assets/web-panel/assets/MarkdownRenderer-Bf3DEqP6.js +0 -1
  181. package/src/assets/web-panel/assets/Projects-08xUDZGt.js +0 -1
  182. package/src/assets/web-panel/assets/Tasks-CEYFJwmr.js +0 -1
  183. package/src/assets/web-panel/assets/devWarning-DEMblAIm.js +0 -1
  184. package/src/assets/web-panel/assets/index-BTvq-36D.js +0 -1
  185. package/src/assets/web-panel/assets/index-hUpvk6Jl.js +0 -1
@@ -23,6 +23,22 @@ function childHasClosed(child, observedClose) {
23
23
  );
24
24
  }
25
25
 
26
+ /**
27
+ * Whether another PID/PGID based termination attempt is still identity-safe.
28
+ * Once the owned root is known closed, its numeric pid can be reused by an
29
+ * unrelated process tree. A caller may retain fail-closed uncertainty, but it
30
+ * must never send a later signal through that stale identity.
31
+ */
32
+ export function shouldRetryOwnedProcessTreeTermination(child, result) {
33
+ if (result?.confirmed === true) return false;
34
+ if (result?.closed === true) return false;
35
+ if (child?.exitCode !== null && child?.exitCode !== undefined) return false;
36
+ if (child?.signalCode !== null && child?.signalCode !== undefined) {
37
+ return false;
38
+ }
39
+ return true;
40
+ }
41
+
26
42
  function posixGroupIsGone(pid, kill) {
27
43
  try {
28
44
  kill(-pid, 0);
@@ -224,7 +240,7 @@ export async function terminateOwnedProcessTree(child, options = {}) {
224
240
  await waitForConfirmation(graceMs);
225
241
  }
226
242
 
227
- if (!confirmed()) {
243
+ if (!confirmed() && !closed()) {
228
244
  escalated = true;
229
245
  const attempt = request(true);
230
246
  hardRequested = attempt.requested;
@@ -32,6 +32,47 @@ import {
32
32
  issueMcpStdioExecutionAuthority,
33
33
  } from "./mcp-stdio-execution-authority.js";
34
34
  import { MCP_STDIO_RUNTIME_KINDS } from "./mcp-stdio-executable-identity.js";
35
+ import { isProxy } from "node:util/types";
36
+ import {
37
+ MCP_SANDBOX_POLICY_INVALID_CODE,
38
+ normalizeMcpSandboxPolicy,
39
+ readMcpStdioCwd,
40
+ } from "./mcp-sandbox-policy.js";
41
+
42
+ function invalidSandboxPolicy(message) {
43
+ const error = new TypeError(message);
44
+ error.code = MCP_SANDBOX_POLICY_INVALID_CODE;
45
+ return error;
46
+ }
47
+
48
+ function sandboxPolicyFromEntry(entry) {
49
+ if (!entry || typeof entry !== "object" || isProxy(entry)) {
50
+ throw invalidSandboxPolicy(
51
+ "skill MCP server config must be a non-Proxy object",
52
+ );
53
+ }
54
+ const descriptor = Object.getOwnPropertyDescriptor(entry, "sandboxPolicy");
55
+ if (!descriptor) return null;
56
+ if (!("value" in descriptor)) {
57
+ throw invalidSandboxPolicy(
58
+ "skill MCP server sandboxPolicy must be an own data property",
59
+ );
60
+ }
61
+ return normalizeMcpSandboxPolicy(descriptor.value, {
62
+ label: "skill MCP server sandboxPolicy",
63
+ });
64
+ }
65
+
66
+ function safeServerName(entry) {
67
+ if (!entry || typeof entry !== "object" || isProxy(entry)) return "(invalid)";
68
+ const descriptor = Object.getOwnPropertyDescriptor(entry, "name");
69
+ return descriptor &&
70
+ "value" in descriptor &&
71
+ typeof descriptor.value === "string" &&
72
+ descriptor.value.length > 0
73
+ ? descriptor.value
74
+ : "(invalid)";
75
+ }
35
76
 
36
77
  /**
37
78
  * Parse MCP server declarations from a SKILL.md body.
@@ -77,6 +118,10 @@ export function parseSkillMcpServers(body) {
77
118
  */
78
119
  export function validateMcpServerConfig(entry) {
79
120
  if (!entry || typeof entry !== "object") return null;
121
+ const sandboxPolicy = sandboxPolicyFromEntry(entry);
122
+ const { cwd } = readMcpStdioCwd(entry, {
123
+ label: "skill MCP server config",
124
+ });
80
125
  if (typeof entry.name !== "string" || entry.name.trim().length === 0) {
81
126
  return null;
82
127
  }
@@ -102,9 +147,8 @@ export function validateMcpServerConfig(entry) {
102
147
  } else if (entry.runtimeKind !== undefined) {
103
148
  return null;
104
149
  }
105
- if (typeof entry.cwd === "string" && entry.cwd.length > 0) {
106
- normalized.cwd = entry.cwd;
107
- }
150
+ if (cwd) normalized.cwd = cwd;
151
+ if (sandboxPolicy) normalized.sandboxPolicy = sandboxPolicy;
108
152
  return Object.freeze(normalized);
109
153
  }
110
154
 
@@ -131,7 +175,19 @@ export async function mountSkillMcpServers(mcpClient, skill, opts = {}) {
131
175
  }
132
176
 
133
177
  for (const server of declared) {
134
- const normalized = validateMcpServerConfig(server);
178
+ let normalized;
179
+ try {
180
+ normalized = validateMcpServerConfig(server);
181
+ } catch (error) {
182
+ const name = safeServerName(server);
183
+ const message = error?.message || String(error);
184
+ skipped.push({ name, error: message });
185
+ opts.onWarn?.(
186
+ `[skill-mcp] Skipped "${name}" for skill "${skill?.id || skill?.name}": ${message}`,
187
+ error,
188
+ );
189
+ continue;
190
+ }
135
191
  if (!normalized) {
136
192
  const name = server?.name || "(invalid)";
137
193
  skipped.push({ name, error: "invalid config" });
@@ -157,6 +213,7 @@ export async function mountSkillMcpServers(mcpClient, skill, opts = {}) {
157
213
  runtimeKind: normalized.runtimeKind || null,
158
214
  cwd: normalized.cwd || null,
159
215
  envKeys: Object.keys(normalized.env || {}).sort(),
216
+ sandboxPolicy: normalized.sandboxPolicy || null,
160
217
  })) === true;
161
218
  } catch (error) {
162
219
  const message = error?.message || String(error);
@@ -182,6 +239,10 @@ export async function mountSkillMcpServers(mcpClient, skill, opts = {}) {
182
239
  config,
183
240
  approvalKind: "explicit-config",
184
241
  approvalSource: `skill:${skill?.id || skill?.name || "unknown"}:${normalized.name}`,
242
+ workspaceBinding:
243
+ typeof mcpClient.executionWorkspaceBinding === "function"
244
+ ? mcpClient.executionWorkspaceBinding()
245
+ : null,
185
246
  });
186
247
  await mcpClient.connect(normalized.name, config);
187
248
  mounted.push(normalized.name);
@@ -5,10 +5,10 @@
5
5
  * private/loopback hosts unless explicitly allowlisted.
6
6
  */
7
7
 
8
- import http from "http";
9
- import https from "https";
10
- import { lookup as dnsLookup } from "dns";
11
- import { URL } from "url";
8
+ import http from "node:http";
9
+ import https from "node:https";
10
+ import { lookup as dnsLookup } from "node:dns";
11
+ import { URL } from "node:url";
12
12
 
13
13
  const DEFAULT_MAX_BYTES = 2_000_000;
14
14
  const DEFAULT_TIMEOUT_MS = 15_000;
@@ -29,6 +29,7 @@ import { findProjectRoot, loadProjectConfig } from "../lib/project-detector.js";
29
29
  import { loadConfig } from "../lib/config-manager.js";
30
30
  import { collectWorkspacePluginBinSandboxPolicy } from "../lib/plugin-runtime/bin.js";
31
31
  import { issueMcpStdioExecutionAuthority } from "../lib/mcp-stdio-execution-authority.js";
32
+ import { registerHostHooksV2Workspace } from "../lib/hooks-v2-workspace-context.js";
32
33
 
33
34
  const {
34
35
  DEFAULT_ALLOWED_MCP_SERVER_NAMES,
@@ -71,7 +72,8 @@ export class AgentRuntime {
71
72
  ((options) => new WSSessionManager(options)),
72
73
  createPtyManager:
73
74
  deps.createPtyManager || ((options) => new PtyManager(options)),
74
- createMcpClient: deps.createMcpClient || (() => new MCPClient()),
75
+ createMcpClient:
76
+ deps.createMcpClient || ((options) => new MCPClient(options)),
75
77
  createMcpServerConfig:
76
78
  deps.createMcpServerConfig || ((db) => new MCPServerConfig(db)),
77
79
  mcpServerRegistry:
@@ -81,6 +83,8 @@ export class AgentRuntime {
81
83
  findProjectRoot: deps.findProjectRoot || findProjectRoot,
82
84
  loadProjectConfig: deps.loadProjectConfig || loadProjectConfig,
83
85
  loadConfig: deps.loadConfig || loadConfig,
86
+ loadAgentBundle: deps.loadAgentBundle || null,
87
+ resolveAgentBundle: deps.resolveAgentBundle || null,
84
88
  openBrowser: deps.openBrowser || openBrowser,
85
89
  runTurn: deps.runTurn || null,
86
90
  logger: deps.logger || logger,
@@ -226,6 +230,8 @@ export class AgentRuntime {
226
230
  host = "0.0.0.0";
227
231
  }
228
232
 
233
+ const mcpWorkspaceRoot = path.resolve(project || process.cwd());
234
+
229
235
  let db = null;
230
236
  let rawDb = null;
231
237
  try {
@@ -243,6 +249,7 @@ export class AgentRuntime {
243
249
  const appConfig = this.deps.loadConfig();
244
250
  const mcpClient = await this._initializeCodingAgentMcpClient(rawDb, {
245
251
  logger: runtimeLogger,
252
+ workspaceRoot: mcpWorkspaceRoot,
246
253
  });
247
254
 
248
255
  // Deep Agents Deploy: load agent bundle if --bundle provided.
@@ -252,10 +259,17 @@ export class AgentRuntime {
252
259
  let bundleMcpClient = mcpClient;
253
260
  if (this.policy.bundlePath) {
254
261
  try {
255
- const { loadBundle } =
256
- await import("@chainlesschain/session-core/agent-bundle-loader");
257
- const { resolveBundle } =
258
- await import("@chainlesschain/session-core/agent-bundle-resolver");
262
+ let loadBundle = this.deps.loadAgentBundle;
263
+ let resolveBundle = this.deps.resolveAgentBundle;
264
+ if (
265
+ typeof loadBundle !== "function" ||
266
+ typeof resolveBundle !== "function"
267
+ ) {
268
+ ({ loadBundle } =
269
+ await import("@chainlesschain/session-core/agent-bundle-loader"));
270
+ ({ resolveBundle } =
271
+ await import("@chainlesschain/session-core/agent-bundle-resolver"));
272
+ }
259
273
  const bundle = loadBundle(this.policy.bundlePath);
260
274
  bundleResolved = resolveBundle(bundle);
261
275
 
@@ -266,8 +280,10 @@ export class AgentRuntime {
266
280
  ([, cfg]) => cfg && cfg.command,
267
281
  );
268
282
  if (entries.length > 0) {
283
+ const mcpWorkspace =
284
+ this._resolveCodingAgentMcpWorkspace(mcpWorkspaceRoot);
269
285
  if (!bundleMcpClient) {
270
- bundleMcpClient = this.deps.createMcpClient();
286
+ bundleMcpClient = this._createCodingAgentMcpClient(mcpWorkspace);
271
287
  }
272
288
  for (const [name, cfg] of entries) {
273
289
  try {
@@ -278,6 +294,7 @@ export class AgentRuntime {
278
294
  config: authorizedConfig,
279
295
  approvalKind: "explicit-config",
280
296
  approvalSource: `agent-bundle:${path.resolve(this.policy.bundlePath)}`,
297
+ workspaceRoot: mcpWorkspace.workspaceRoot,
281
298
  });
282
299
  await bundleMcpClient.connect(name, authorizedConfig);
283
300
  } catch (mcpErr) {
@@ -484,6 +501,7 @@ export class AgentRuntime {
484
501
  const appConfig = this.deps.loadConfig();
485
502
  const mcpClient = await this._initializeCodingAgentMcpClient(rawDb, {
486
503
  logger: runtimeLogger,
504
+ workspaceRoot: workspacePolicyCwd,
487
505
  });
488
506
  const sessionManager = this.deps.createSessionManager({
489
507
  db,
@@ -766,10 +784,27 @@ export class AgentRuntime {
766
784
  const trustedMcpServers = createTrustedMcpServerMap(
767
785
  this.deps.mcpServerRegistry,
768
786
  );
787
+ const mcpWorkspace = this._resolveCodingAgentMcpWorkspace(
788
+ options.workspaceRoot || this.policy?.project || process.cwd(),
789
+ );
769
790
  const configStore = this.deps.createMcpServerConfig(db);
770
791
  const autoConnectServers =
771
792
  typeof configStore?.getAutoConnect === "function"
772
- ? configStore.getAutoConnect()
793
+ ? configStore.getAutoConnect({
794
+ cwd: mcpWorkspace.workspaceRoot,
795
+ onInvalidRow: (error, row) => {
796
+ const rawName = row?.display_name || row?.name || "unknown";
797
+ const safeName = String(rawName).replace(/[\r\n]/g, " ");
798
+ const reason = String(
799
+ error?.code || error?.message || "invalid configuration",
800
+ ).replace(/[\r\n]/g, " ");
801
+ options.logger?.log?.(
802
+ chalk.yellow(
803
+ ` Warning: MCP server "${safeName}" was skipped: ${reason}`,
804
+ ),
805
+ );
806
+ },
807
+ })
773
808
  : [];
774
809
  const eligibleServers = autoConnectServers.filter(
775
810
  (server) =>
@@ -787,7 +822,7 @@ export class AgentRuntime {
787
822
  return null;
788
823
  }
789
824
 
790
- const mcpClient = this.deps.createMcpClient();
825
+ const mcpClient = this._createCodingAgentMcpClient(mcpWorkspace);
791
826
  let connectedCount = 0;
792
827
 
793
828
  for (const server of eligibleServers) {
@@ -800,6 +835,7 @@ export class AgentRuntime {
800
835
  config: authorizedServer,
801
836
  approvalKind: "registered-config",
802
837
  approvalSource: `${server.configScope || "user"}:${server.configSource || "database"}:${server.name}`,
838
+ workspaceRoot: mcpWorkspace.workspaceRoot,
803
839
  });
804
840
  }
805
841
  await mcpClient.connect(server.name, authorizedServer);
@@ -822,4 +858,21 @@ export class AgentRuntime {
822
858
 
823
859
  return mcpClient;
824
860
  }
861
+
862
+ _resolveCodingAgentMcpWorkspace(workspaceRoot) {
863
+ const workspaceBinding = registerHostHooksV2Workspace(
864
+ path.resolve(workspaceRoot || process.cwd()),
865
+ );
866
+ return Object.freeze({
867
+ workspaceBinding,
868
+ workspaceRoot: workspaceBinding.workspaceRoot,
869
+ });
870
+ }
871
+
872
+ _createCodingAgentMcpClient(workspace) {
873
+ return this.deps.createMcpClient({
874
+ workspaceBinding: workspace.workspaceBinding,
875
+ roots: [workspace.workspaceRoot],
876
+ });
877
+ }
825
878
  }