chainlesschain 0.163.8 → 0.165.1

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 (240) hide show
  1. package/package.json +7 -4
  2. package/scripts/macos-mcp-launcher-build.mjs +317 -0
  3. package/scripts/macos-mcp-launcher-postinstall.sh +54 -0
  4. package/scripts/macos-mcp-launcher-preinstall.sh +61 -0
  5. package/src/assets/web-panel/.build-hash +1 -1
  6. package/src/assets/web-panel/assets/{AIOps-CavM7W3k.js → AIOps-CYxFDrcm.js} +1 -1
  7. package/src/assets/web-panel/assets/{ActionButton-CUvZGabQ.js → ActionButton-CPBtdiU2.js} +1 -1
  8. package/src/assets/web-panel/assets/{Analytics-DeBnWnbe.js → Analytics-Dayq7Dp7.js} +3 -3
  9. package/src/assets/web-panel/assets/{AppLayout-DbI5kxvd.js → AppLayout-6U7bPb2s.js} +4 -4
  10. package/src/assets/web-panel/assets/{Artifacts-D93bigKm.js → Artifacts-D2Iqg_3D.js} +1 -1
  11. package/src/assets/web-panel/assets/{Audit-CBNvfUZa.js → Audit-CdoOB7WV.js} +1 -1
  12. package/src/assets/web-panel/assets/{BackgroundAgents-CJLyh_YU.js → BackgroundAgents-DrnAVB8w.js} +1 -1
  13. package/src/assets/web-panel/assets/{Backup-D_0yoehD.js → Backup-CesMi5cy.js} +1 -1
  14. package/src/assets/web-panel/assets/{BaseInput-TJxmbObW.js → BaseInput-DaX9ptax.js} +1 -1
  15. package/src/assets/web-panel/assets/{Chat-CE0dto1q.js → Chat-OrwOPxDS.js} +5 -5
  16. package/src/assets/web-panel/assets/{ChatBubbleRenderer-CZ5-yYiD.js → ChatBubbleRenderer-CvPZFRxM.js} +1 -1
  17. package/src/assets/web-panel/assets/{Checkbox-Ck1RVIVo.js → Checkbox-DiHbcysC.js} +1 -1
  18. package/src/assets/web-panel/assets/{Codegen-qpoyf6DK.js → Codegen-CbgCkaBJ.js} +1 -1
  19. package/src/assets/web-panel/assets/{Col-DUyPWjIE.js → Col-Du5hgrh4.js} +1 -1
  20. package/src/assets/web-panel/assets/{Community-D_S1BemS.js → Community-DsPOBW-p.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compact-BjxeK-Gc.js → Compact-BwHIFkNC.js} +1 -1
  22. package/src/assets/web-panel/assets/{Compliance-Dd3CEJsu.js → Compliance-BvrDQSgd.js} +1 -1
  23. package/src/assets/web-panel/assets/{Cowork-B4QG7-ad.js → Cowork-gwAE6arx.js} +3 -3
  24. package/src/assets/web-panel/assets/{Cron-BtZnids5.js → Cron-DW-0l4uF.js} +2 -2
  25. package/src/assets/web-panel/assets/{Crosschain-CHPfCBFD.js → Crosschain-j-NsLesB.js} +1 -1
  26. package/src/assets/web-panel/assets/{DID-DT8DCEOK.js → DID-CibVEBOI.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dashboard-COQab5_U.js → Dashboard-W4z9vSfe.js} +2 -2
  28. package/src/assets/web-panel/assets/{Dropdown-BY1PsQuU.js → Dropdown-DAcrkKxG.js} +1 -1
  29. package/src/assets/web-panel/assets/{EmailListRenderer-CsuAuaq3.js → EmailListRenderer-6GXah-89.js} +1 -1
  30. package/src/assets/web-panel/assets/{FamilyGuardDashboard-BqpinD-j.js → FamilyGuardDashboard-TKDCq8Ku.js} +1 -1
  31. package/src/assets/web-panel/assets/{Federation-D0gkfQFv.js → Federation-BXBLlcNm.js} +1 -1
  32. package/src/assets/web-panel/assets/{FormItemContext-BqgE-axK.js → FormItemContext-BoJJBkG3.js} +1 -1
  33. package/src/assets/web-panel/assets/{GenericCardRenderer-D0hJ2KvC.js → GenericCardRenderer-okjsl46v.js} +1 -1
  34. package/src/assets/web-panel/assets/{Git-CmMB0uPY.js → Git-Rvs7i6nn.js} +2 -2
  35. package/src/assets/web-panel/assets/{Governance-BnVEI0Dk.js → Governance-CHSUxXXS.js} +1 -1
  36. package/src/assets/web-panel/assets/{Inference-YTAMihRP.js → Inference-V3BlfxsB.js} +1 -1
  37. package/src/assets/web-panel/assets/{KnowledgeGraph-0ax7VHop.js → KnowledgeGraph-C_NlD4aR.js} +1 -1
  38. package/src/assets/web-panel/assets/{Logs-B9TRcokL.js → Logs-Nn4LNxhA.js} +2 -2
  39. package/src/assets/web-panel/assets/MarkdownRenderer-SVAgNnkt.js +1 -0
  40. package/src/assets/web-panel/assets/{Marketplace-B6CSuD_H.js → Marketplace-DEmjFcg-.js} +1 -1
  41. package/src/assets/web-panel/assets/{McpTools-CjMXvOVU.js → McpTools-DlopXipI.js} +3 -3
  42. package/src/assets/web-panel/assets/{Memory-CXRF71U3.js → Memory-BG3ynX60.js} +2 -2
  43. package/src/assets/web-panel/assets/{MobileBridge-DQgNp_oS.js → MobileBridge-DeRzWOfT.js} +1 -1
  44. package/src/assets/web-panel/assets/{MobileProjects-DlPwcCbq.js → MobileProjects-Tyd3o2A0.js} +1 -1
  45. package/src/assets/web-panel/assets/{Mtc-6hDTRPe1.js → Mtc-BoPbOv1C.js} +2 -2
  46. package/src/assets/web-panel/assets/{MtcAudit-BlVHU1DS.js → MtcAudit-un-rTHp7.js} +2 -2
  47. package/src/assets/web-panel/assets/{Multisig-DP9pzEbV.js → Multisig-Ds0oveEB.js} +3 -3
  48. package/src/assets/web-panel/assets/{NLProgramming-Djorh8EV.js → NLProgramming-D09JI-yY.js} +1 -1
  49. package/src/assets/web-panel/assets/{Notes-oLZ-JkUg.js → Notes-DTRhiKJn.js} +4 -4
  50. package/src/assets/web-panel/assets/{NotificationSettings-Cg288VH3.js → NotificationSettings-BAnnNCim.js} +1 -1
  51. package/src/assets/web-panel/assets/OrderTableRenderer-Yr-1fSYi.js +1 -0
  52. package/src/assets/web-panel/assets/{Organization-CBdo-bHs.js → Organization-S9EAolpj.js} +4 -4
  53. package/src/assets/web-panel/assets/{Overflow-qZdnVumx.js → Overflow-CqcLKqJ8.js} +1 -1
  54. package/src/assets/web-panel/assets/{P2P-D4kNfGNQ.js → P2P-Dw0F9EcU.js} +2 -2
  55. package/src/assets/web-panel/assets/{PdhVaultBrowser-DnlMemM7.js → PdhVaultBrowser-BDRwUevN.js} +5 -5
  56. package/src/assets/web-panel/assets/{Permissions-DHucHFBJ.js → Permissions-D3_c3nKB.js} +4 -4
  57. package/src/assets/web-panel/assets/{PersonalDataHub-BovlOIPR.js → PersonalDataHub-CxdMV98x.js} +4 -4
  58. package/src/assets/web-panel/assets/{Pipeline-Deru3CQY.js → Pipeline-CgjNQFLI.js} +1 -1
  59. package/src/assets/web-panel/assets/{Privacy-Bq5oTTbU.js → Privacy-BHghIIht.js} +1 -1
  60. package/src/assets/web-panel/assets/{ProjectInit-BfzxVWAz.js → ProjectInit-De6pqaKM.js} +2 -2
  61. package/src/assets/web-panel/assets/{ProjectSettings-CKC6XBtH.js → ProjectSettings-Bg4ZkNYQ.js} +2 -2
  62. package/src/assets/web-panel/assets/Projects-CP8vPvzs.js +1 -0
  63. package/src/assets/web-panel/assets/{Providers-C_jx4TWX.js → Providers-CUnHbNf-.js} +1 -1
  64. package/src/assets/web-panel/assets/{QrScannerModal-BdIHeVGC.js → QrScannerModal-DA2f3Wts.js} +1 -1
  65. package/src/assets/web-panel/assets/{QuickAsk-BwZwAcPD.js → QuickAsk-C1FeHDqp.js} +1 -1
  66. package/src/assets/web-panel/assets/{Recommend-BNTt0L-m.js → Recommend-B5guaUMN.js} +1 -1
  67. package/src/assets/web-panel/assets/RemoteSession-PDADSds3.js +5 -0
  68. package/src/assets/web-panel/assets/{Reputation-D6VpG32B.js → Reputation-eTlRhgvK.js} +1 -1
  69. package/src/assets/web-panel/assets/{Row-D_74OvQQ.js → Row-D7AqSGY0.js} +1 -1
  70. package/src/assets/web-panel/assets/{RssFeed-BTr0a-BQ.js → RssFeed-JiuLm4Ja.js} +3 -3
  71. package/src/assets/web-panel/assets/{Search-C3MCFoNU.js → Search-CwruahW3.js} +1 -1
  72. package/src/assets/web-panel/assets/{Security-CqW9aJ6s.js → Security-CdhqaR0b.js} +4 -4
  73. package/src/assets/web-panel/assets/{Services-Cw5GNaHF.js → Services-CU0ZIlcT.js} +2 -2
  74. package/src/assets/web-panel/assets/{Skeleton-DZps5qeY.js → Skeleton-CtduPfAb.js} +1 -1
  75. package/src/assets/web-panel/assets/{Skills-C6NQ1znT.js → Skills-CROXm6AY.js} +1 -1
  76. package/src/assets/web-panel/assets/{Sla-DFP8G2Sh.js → Sla-DiZiABFD.js} +1 -1
  77. package/src/assets/web-panel/assets/{SpeechSettings-ESt6MB6v.js → SpeechSettings-B5pLcXUw.js} +1 -1
  78. package/src/assets/web-panel/assets/{SyncSettings-BHnN98aM.js → SyncSettings-DBX6J1Oe.js} +2 -2
  79. package/src/assets/web-panel/assets/{Tasks-NiSCaOf-.js → Tasks-BLyRJd3-.js} +1 -1
  80. package/src/assets/web-panel/assets/{Templates-DsKFhW2C.js → Templates-BKa5qzmk.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tenant-CQ0E0ze5.js → Tenant-DnD3a4M6.js} +1 -1
  82. package/src/assets/web-panel/assets/{Terminal-D_rBu_by.js → Terminal-DEitQeTb.js} +2 -2
  83. package/src/assets/web-panel/assets/{TimelineRenderer-D3Vm4Po4.js → TimelineRenderer-CjHggTDq.js} +1 -1
  84. package/src/assets/web-panel/assets/{Tokens-DNTxRH6q.js → Tokens-CsGT7sfl.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trigger-Dgprz1ms.js → Trigger-yr4rFDrW.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trust-B2rUnVBD.js → Trust-CLvu1Sjp.js} +1 -1
  87. package/src/assets/web-panel/assets/{UkeySign-DEGQNc6_.js → UkeySign-B0m7yUP8.js} +1 -1
  88. package/src/assets/web-panel/assets/{VideoEditing-jlsAx3Eh.js → VideoEditing-C0VvP4lc.js} +1 -1
  89. package/src/assets/web-panel/assets/{Wallet-8jQih1ij.js → Wallet-kllBAG1M.js} +4 -4
  90. package/src/assets/web-panel/assets/{WebAuthn-XLeO6xIB.js → WebAuthn-C54UQNLx.js} +3 -3
  91. package/src/assets/web-panel/assets/{WorkflowEditor-De_dgDAG.js → WorkflowEditor-B7y8qSvU.js} +1 -1
  92. package/src/assets/web-panel/assets/{chat-CI19R_Sk.js → chat-DRzTh8CJ.js} +1 -1
  93. package/src/assets/web-panel/assets/{colors-DsYTOYN3.js → colors-BSMwSnCx.js} +1 -1
  94. package/src/assets/web-panel/assets/{compact-item-CM3-t_Qr.js → compact-item-BTg602H5.js} +1 -1
  95. package/src/assets/web-panel/assets/{createContext-BjxlBRZv.js → createContext-B6EGsdvp.js} +1 -1
  96. package/src/assets/web-panel/assets/devWarning-Dol8jLEP.js +1 -0
  97. package/src/assets/web-panel/assets/{hasIn-RDaWX_4i.js → hasIn-DDKqJ8RD.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-nAH87mQP.js → index-323Hhxxt.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-DIUnNOjG.js → index-BICn3Qh1.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DyIWssPC.js → index-BMuGd2--.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DX7tuWVJ.js → index-BRqt4fO-.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-Cd3euP_4.js → index-BVTAl5N2.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-Cpqm1qfU.js → index-BsR7Y2NG.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DcPFB8qJ.js → index-Bx044qDj.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-Cd9OJhHG.js → index-C1GFfuqN.js} +1 -1
  106. package/src/assets/web-panel/assets/index-C3QX5tOl.js +1 -0
  107. package/src/assets/web-panel/assets/{index-B-Z8eFUJ.js → index-C66NpWy5.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-BlT2VAEK.js → index-CDTvsX8t.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Dsij_KsN.js → index-CGNklbP6.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-C4gkzxkw.js → index-CHfLYwcW.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-D6sm5-Xq.js → index-CNxg61YP.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-C0yx-jtQ.js → index-CQlHFN_g.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-CjTrRt13.js → index-CUEU48o1.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-B7WBt_4T.js → index-CWGax2QW.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-IeiL9RKc.js → index-C_JzIXUq.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CnHH7bnD.js → index-Cf23wVMs.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-BKJr-TZp.js → index-CmAInUkX.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CiECJi-Q.js → index-CmAubjDi.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-BCnZyIMA.js → index-Co7oM1qr.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Drlnwr8F.js → index-CwPUZbMI.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-9R6BxAr0.js → index-D1naNj4U.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-BGqqJfL0.js → index-D5CsBShd.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-Bi46Xu4u.js → index-DBT3YeQ9.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DXXtGMUJ.js → index-DLdrHhML.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-B0PMlbMs.js → index-Dc77VR3H.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-D0zcy54x.js → index-Dfv2lKu3.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-BN6UPD2E.js → index-DiW0sDkz.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-Dxge-xWl.js → index-DpTHIRfZ.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-CyOGN6a5.js → index-DqFXGzzC.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-B9O9YyWE.js → index-XFe-1twF.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BHNYPO0b.js → index-p2HYn89m.js} +3 -3
  132. package/src/assets/web-panel/assets/{index-CVQMeiwH.js → index-pqfux8vZ.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-pPL66J85.js → index-rjzk9z1Q.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-DoQA0-52.js → index-th2ihDc0.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-B5REnKt8.js → index-u2YVld9W.js} +1 -1
  136. package/src/assets/web-panel/assets/index-xYybvEic.js +1 -0
  137. package/src/assets/web-panel/assets/{initDefaultProps-BTL88of4.js → initDefaultProps-C3Djh9fa.js} +1 -1
  138. package/src/assets/web-panel/assets/{motion-BUB2pXwB.js → motion-BzqFmbSe.js} +1 -1
  139. package/src/assets/web-panel/assets/{move-egCkkOMm.js → move-DJo_FFaW.js} +1 -1
  140. package/src/assets/web-panel/assets/{mtc-parser-DAWhZC8c.js → mtc-parser-_tlTiBvk.js} +1 -1
  141. package/src/assets/web-panel/assets/{omit-CvOxe_6d.js → omit-CB2ZyxUg.js} +1 -1
  142. package/src/assets/web-panel/assets/{pickAttrs-DZUSLZ5Z.js → pickAttrs-DZwIFD4u.js} +1 -1
  143. package/src/assets/web-panel/assets/{placementArrow-BERxGNMY.js → placementArrow-DxZY0dgk.js} +1 -1
  144. package/src/assets/web-panel/assets/{responsiveObserve-DZuDfZ9n.js → responsiveObserve-CzzGt7GL.js} +1 -1
  145. package/src/assets/web-panel/assets/{slide-DO756sgI.js → slide-BaIK52yz.js} +1 -1
  146. package/src/assets/web-panel/assets/{statusUtils-BRQlIz28.js → statusUtils-3-FHu9_M.js} +1 -1
  147. package/src/assets/web-panel/assets/{styleChecker-DCSfdybl.js → styleChecker-BkRT68fK.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFlexGapSupport-LD8dWVve.js → useFlexGapSupport-DHYwKS-s.js} +1 -1
  149. package/src/assets/web-panel/assets/{useFs-BX9uW2LK.js → useFs-DVVUhV8p.js} +1 -1
  150. package/src/assets/web-panel/assets/{usePersonalDataHub-BPSlPuHU.js → usePersonalDataHub-CkrFKAzQ.js} +1 -1
  151. package/src/assets/web-panel/assets/{vnode-BmOILC9V.js → vnode-BuBLFz0c.js} +1 -1
  152. package/src/assets/web-panel/assets/{zoom-1iKowKGg.js → zoom-kpm6LtXU.js} +1 -1
  153. package/src/assets/web-panel/index.html +1 -1
  154. package/src/command-help-index.json +3 -3
  155. package/src/commands/cowork.js +418 -41
  156. package/src/commands/permissions.js +240 -16
  157. package/src/commands/plugin.js +1293 -56
  158. package/src/commands/session-location.js +276 -0
  159. package/src/commands/session.js +2 -0
  160. package/src/data/changelog.json +28 -2
  161. package/src/gateways/ws/action-protocol.js +316 -17
  162. package/src/gateways/ws/message-dispatcher.js +30 -0
  163. package/src/gateways/ws/remote-session-protocol.js +565 -35
  164. package/src/gateways/ws/ws-agent-handler.js +12 -0
  165. package/src/gateways/ws/ws-approval-gate.js +5 -0
  166. package/src/gateways/ws/ws-server.js +510 -50
  167. package/src/harness/jsonl-session-store.js +341 -24
  168. package/src/harness/mcp-client.js +8 -1
  169. package/src/harness/remote-session-audit.js +2 -0
  170. package/src/harness/remote-session-crypto.js +929 -21
  171. package/src/harness/remote-session-registry.js +945 -24
  172. package/src/harness/session-list-index.js +233 -14
  173. package/src/lib/agent-authority.js +6 -0
  174. package/src/lib/auto-mode-config.js +98 -3
  175. package/src/lib/background-agent-keeper-client.js +248 -0
  176. package/src/lib/background-agent-keeper-protocol.js +291 -0
  177. package/src/lib/background-agent-supervisor.js +1357 -85
  178. package/src/lib/background-interaction-resolver.js +12 -0
  179. package/src/lib/background-session-transport.js +23 -6
  180. package/src/lib/background-turn-bootstrap-protocol.js +190 -0
  181. package/src/lib/cowork-workflow.js +1188 -76
  182. package/src/lib/delivery-production-adapter.js +38 -2
  183. package/src/lib/dynamic-workflow-facade.js +1736 -0
  184. package/src/lib/execution-location-contract.js +551 -0
  185. package/src/lib/execution-location-runtime.js +130 -0
  186. package/src/lib/ide-context.js +94 -6
  187. package/src/lib/mcp-stdio-package-materialization.js +166 -14
  188. package/src/lib/packer/pkg-config-generator.js +2 -0
  189. package/src/lib/permission-authority.js +77 -0
  190. package/src/lib/permission-side-effect-center.js +495 -0
  191. package/src/lib/plugin-runtime/install.js +514 -13
  192. package/src/lib/plugin-runtime/marketplace-artifact-readback.js +900 -0
  193. package/src/lib/plugin-runtime/marketplace-catalog.js +1181 -0
  194. package/src/lib/plugin-runtime/marketplace-impact.js +408 -0
  195. package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1567 -0
  196. package/src/lib/plugin-security.js +60 -3
  197. package/src/lib/process-execution-broker/index.js +1095 -57
  198. package/src/lib/process-execution-broker/linux-bwrap-descriptor-launch.js +375 -0
  199. package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +90 -16
  200. package/src/lib/process-execution-broker/linux-generic-bwrap.js +159 -18
  201. package/src/lib/process-execution-broker/macos-mcp-launcher-contract.js +278 -0
  202. package/src/lib/process-execution-broker/macos-mcp-launcher-protocol.json +23 -0
  203. package/src/lib/process-execution-broker/macos-mcp-launcher.c +1497 -0
  204. package/src/lib/process-execution-broker/mcp-fd-entry-bootstrap.js +37 -0
  205. package/src/lib/process-execution-broker/platform-sandbox.js +2330 -279
  206. package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
  207. package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
  208. package/src/lib/process-execution-broker/windows-sandbox.cs +50 -4
  209. package/src/lib/public-ide-capability-manifest.js +3 -0
  210. package/src/lib/remote-approval-bridge.js +777 -34
  211. package/src/lib/remote-control.js +2 -0
  212. package/src/lib/remote-membership-authority.js +632 -0
  213. package/src/lib/remote-membership-coordinator.js +2973 -0
  214. package/src/lib/remote-membership-host-store.js +1799 -0
  215. package/src/lib/runtime-provenance-ledger.js +171 -46
  216. package/src/lib/scoped-permission-store.js +369 -0
  217. package/src/lib/session-anti-rollback-anchor.js +262 -5
  218. package/src/lib/shell-approval.js +169 -6
  219. package/src/lib/sub-agent-context.js +4 -0
  220. package/src/lib/with-file-lock.js +73 -38
  221. package/src/lib/workflow-definition-contract.js +149 -0
  222. package/src/repl/agent-repl.js +111 -36
  223. package/src/repl/chat-repl.js +2 -0
  224. package/src/repl/clipboard-image.js +735 -16
  225. package/src/repl/ide-status.js +1 -1
  226. package/src/repl/prompt-interactions.js +59 -6
  227. package/src/repl/remote-approval.js +29 -7
  228. package/src/runtime/agent-core.js +1182 -155
  229. package/src/runtime/headless-runner.js +52 -30
  230. package/src/runtime/headless-stream.js +51 -28
  231. package/src/workers/background-agent-keeper.js +689 -0
  232. package/src/workers/background-agent-worker.js +365 -13
  233. package/src/workers/background-turn-bootstrap.js +170 -0
  234. package/src/assets/web-panel/assets/MarkdownRenderer-yySN5YNM.js +0 -1
  235. package/src/assets/web-panel/assets/OrderTableRenderer-Bb1O3Ofr.js +0 -1
  236. package/src/assets/web-panel/assets/Projects-CMolGhae.js +0 -1
  237. package/src/assets/web-panel/assets/RemoteSession-Biyn2-Ro.js +0 -5
  238. package/src/assets/web-panel/assets/devWarning-S1ld2LwU.js +0 -1
  239. package/src/assets/web-panel/assets/index-Drz6yq0m.js +0 -1
  240. package/src/assets/web-panel/assets/index-uWiUs7S_.js +0 -1
@@ -0,0 +1,551 @@
1
+ import {
2
+ EXECUTION_LOCATION,
3
+ clampPermissionsForLocation,
4
+ normalizeExecutionLocation,
5
+ redactCredentialRefs,
6
+ } from "./execution-location.js";
7
+
8
+ export const EXECUTION_LOCATION_BINDING_SCHEMA =
9
+ "cc-execution-location-binding/v1";
10
+ export const EXECUTION_LOCATION_CATALOG_SCHEMA =
11
+ "cc-execution-location-catalog/v1";
12
+ export const EXECUTION_LOCATION_HANDOFF_FACTS_SCHEMA =
13
+ "cc-execution-location-handoff-facts/v1";
14
+ export const EXECUTION_LOCATION_HANDOFF_SCHEMA =
15
+ "cc-execution-location-handoff/v1";
16
+
17
+ const FORBIDDEN_SECRET_KEYS = new Set([
18
+ "apikey",
19
+ "credentialvalue",
20
+ "password",
21
+ "privatekey",
22
+ "secret",
23
+ "token",
24
+ "value",
25
+ ]);
26
+ const NETWORK_POLICIES = new Set([
27
+ "offline",
28
+ "restricted",
29
+ "unrestricted",
30
+ "unknown",
31
+ ]);
32
+ const SANDBOX_STRENGTHS = new Set(["strong", "partial", "none", "unknown"]);
33
+ const DATA_BOUNDARY_KINDS = new Set([
34
+ "working-directory",
35
+ "repository",
36
+ "declared",
37
+ "unknown",
38
+ ]);
39
+ const HANDOFF_STRATEGIES = new Set(["commit", "stash", "patch", "none"]);
40
+ const CREDENTIAL_SOURCES = new Set([
41
+ "config",
42
+ "env",
43
+ "environment",
44
+ "keychain",
45
+ "local-provider",
46
+ "managed-secret",
47
+ "none",
48
+ "not-observed",
49
+ "unknown",
50
+ ]);
51
+
52
+ function stringValue(value, { max = 256, nullable = true } = {}) {
53
+ if (value == null && nullable) return null;
54
+ if (typeof value !== "string") throw new TypeError("expected a string");
55
+ const output = value.trim();
56
+ if (!output || output.length > max || /[\u0000-\u001f\u007f]/u.test(output)) {
57
+ throw new TypeError(
58
+ "string is empty, too long, or contains control characters",
59
+ );
60
+ }
61
+ return output;
62
+ }
63
+
64
+ function safeString(value, options) {
65
+ try {
66
+ return stringValue(value, options);
67
+ } catch {
68
+ return null;
69
+ }
70
+ }
71
+
72
+ function enumValue(value, allowed, fallback = "unknown") {
73
+ const normalized = safeString(value)?.toLowerCase();
74
+ return allowed.has(normalized) ? normalized : fallback;
75
+ }
76
+
77
+ function containsForbiddenSecretMaterial(value, seen = new Set()) {
78
+ if (!value || typeof value !== "object") return false;
79
+ if (seen.has(value)) return true;
80
+ seen.add(value);
81
+ if (Array.isArray(value)) {
82
+ return value.some((item) => containsForbiddenSecretMaterial(item, seen));
83
+ }
84
+ for (const [key, child] of Object.entries(value)) {
85
+ if (FORBIDDEN_SECRET_KEYS.has(key.toLowerCase()) && child != null) {
86
+ return true;
87
+ }
88
+ if (containsForbiddenSecretMaterial(child, seen)) return true;
89
+ }
90
+ return false;
91
+ }
92
+
93
+ function normalizeNames(values, { max = 64 } = {}) {
94
+ const output = [];
95
+ for (const value of Array.isArray(values) ? values : []) {
96
+ const name = safeString(value, { max });
97
+ if (name && /^[A-Za-z0-9_.:/@+-]+$/u.test(name) && !output.includes(name)) {
98
+ output.push(name);
99
+ }
100
+ }
101
+ return output.sort();
102
+ }
103
+
104
+ function normalizeDataBoundary(value) {
105
+ const input = value && typeof value === "object" ? value : {};
106
+ return {
107
+ kind: enumValue(input.kind, DATA_BOUNDARY_KINDS),
108
+ root: safeString(input.root, { max: 4096 }),
109
+ };
110
+ }
111
+
112
+ function normalizeGitSource(value) {
113
+ const input = value && typeof value === "object" ? value : {};
114
+ return {
115
+ root: safeString(input.root, { max: 4096 }),
116
+ head: safeString(input.head, { max: 512 }),
117
+ commit: safeString(input.commit, { max: 128 }),
118
+ };
119
+ }
120
+
121
+ function normalizeCredentials(value) {
122
+ if (containsForbiddenSecretMaterial(value)) {
123
+ throw new TypeError(
124
+ "credential values are forbidden in execution-location data",
125
+ );
126
+ }
127
+ return redactCredentialRefs(value).map((credential) =>
128
+ Object.freeze({
129
+ name: safeString(credential.name),
130
+ source: enumValue(credential.source, CREDENTIAL_SOURCES),
131
+ scope: safeString(credential.scope),
132
+ }),
133
+ );
134
+ }
135
+
136
+ export function createExecutionLocationBinding(input = {}) {
137
+ if (!input || typeof input !== "object" || Array.isArray(input)) {
138
+ throw new TypeError("execution location binding input must be an object");
139
+ }
140
+ if (containsForbiddenSecretMaterial(input)) {
141
+ throw new TypeError(
142
+ "secret material is forbidden in execution-location data",
143
+ );
144
+ }
145
+ const location = normalizeExecutionLocation(input.location);
146
+ const requestedPermissions =
147
+ input.permissions && typeof input.permissions === "object"
148
+ ? input.permissions
149
+ : {};
150
+ const permissionGrant = clampPermissionsForLocation(
151
+ location,
152
+ requestedPermissions,
153
+ );
154
+ const cwd = safeString(input.source?.cwd, { max: 4096 });
155
+ const git = normalizeGitSource(input.source?.git);
156
+ const boundary = normalizeDataBoundary(input.policy?.dataBoundary);
157
+ return Object.freeze({
158
+ schema: EXECUTION_LOCATION_BINDING_SCHEMA,
159
+ location,
160
+ observedAt: safeString(input.observedAt, { max: 64 }),
161
+ observed: input.observed === true,
162
+ signals: Object.freeze(normalizeNames(input.signals)),
163
+ source: Object.freeze({ cwd, git: Object.freeze(git) }),
164
+ runtime: Object.freeze({
165
+ platform: safeString(input.runtime?.platform, { max: 64 }),
166
+ arch: safeString(input.runtime?.arch, { max: 64 }),
167
+ nodeVersion: safeString(input.runtime?.nodeVersion, { max: 64 }),
168
+ tools: Object.freeze(normalizeNames(input.runtime?.tools)),
169
+ }),
170
+ model: Object.freeze({
171
+ provider: safeString(input.model?.provider),
172
+ name: safeString(input.model?.name),
173
+ credentialSource: enumValue(
174
+ input.model?.credentialSource,
175
+ CREDENTIAL_SOURCES,
176
+ "not-observed",
177
+ ),
178
+ }),
179
+ credentials: Object.freeze(normalizeCredentials(input.credentials)),
180
+ permissions: Object.freeze({
181
+ status:
182
+ input.permissions?.status === "declared" ? "declared" : "not-observed",
183
+ ...permissionGrant,
184
+ }),
185
+ policy: Object.freeze({
186
+ network: enumValue(input.policy?.network, NETWORK_POLICIES),
187
+ sandbox: enumValue(input.policy?.sandbox, SANDBOX_STRENGTHS),
188
+ dataBoundary: Object.freeze(boundary),
189
+ }),
190
+ extension:
191
+ location === EXECUTION_LOCATION.CONTAINER ? "chainlesschain" : null,
192
+ controlPlane: Object.freeze({
193
+ remoteControl: "controls-local-execution-only",
194
+ }),
195
+ });
196
+ }
197
+
198
+ export function normalizeExecutionLocationBinding(value) {
199
+ if (value?.schema !== EXECUTION_LOCATION_BINDING_SCHEMA) {
200
+ throw new TypeError(
201
+ `execution location binding must use ${EXECUTION_LOCATION_BINDING_SCHEMA}`,
202
+ );
203
+ }
204
+ return createExecutionLocationBinding(value);
205
+ }
206
+
207
+ const LOCATION_PROFILES = Object.freeze({
208
+ [EXECUTION_LOCATION.LOCAL]: {
209
+ label: "Local",
210
+ executor: "local-process",
211
+ launch: "available",
212
+ resume: "available",
213
+ startup: "immediate",
214
+ continuity: "host-process-dependent",
215
+ cost: "local-resource",
216
+ connectors: ["local-files", "local-git"],
217
+ },
218
+ [EXECUTION_LOCATION.WSL]: {
219
+ label: "WSL",
220
+ executor: "ambient-only",
221
+ launch: "not-implemented",
222
+ resume: "not-implemented",
223
+ startup: "requires-existing-wsl-session",
224
+ continuity: "wsl-host-dependent",
225
+ cost: "local-resource",
226
+ connectors: ["wsl-files", "wsl-git"],
227
+ },
228
+ [EXECUTION_LOCATION.SSH]: {
229
+ label: "SSH",
230
+ executor: "ssh-adapter",
231
+ launch: "requires-configuration",
232
+ resume: "requires-configuration",
233
+ startup: "target-and-auth-required",
234
+ continuity: "remote-host-dependent",
235
+ cost: "remote-host-dependent",
236
+ connectors: ["ssh"],
237
+ },
238
+ [EXECUTION_LOCATION.CONTAINER]: {
239
+ label: "Container",
240
+ executor: "docker-adapter",
241
+ launch: "requires-configuration",
242
+ resume: "requires-configuration",
243
+ startup: "image-and-runtime-required",
244
+ continuity: "container-lifecycle-dependent",
245
+ cost: "runtime-dependent",
246
+ connectors: ["docker"],
247
+ extension: "chainlesschain",
248
+ },
249
+ [EXECUTION_LOCATION.CLOUD]: {
250
+ label: "Cloud",
251
+ executor: "self-hosted-handoff",
252
+ launch: "requires-configuration",
253
+ resume: "not-implemented",
254
+ startup: "provider-and-auth-required",
255
+ continuity: "provider-dependent",
256
+ cost: "provider-dependent",
257
+ connectors: ["self-hosted-cloud-handoff"],
258
+ },
259
+ });
260
+
261
+ function catalogEntry(location, current) {
262
+ const profile = LOCATION_PROFILES[location];
263
+ const isCurrent = current.location === location;
264
+ return Object.freeze({
265
+ location,
266
+ label: profile.label,
267
+ availability: isCurrent
268
+ ? "current"
269
+ : profile.launch === "not-implemented"
270
+ ? "unavailable"
271
+ : "requires-configuration",
272
+ current: isCurrent,
273
+ extension: profile.extension || null,
274
+ source: isCurrent ? current.source : null,
275
+ supportedTools: isCurrent ? current.runtime.tools : Object.freeze([]),
276
+ model: isCurrent
277
+ ? current.model
278
+ : Object.freeze({
279
+ provider: null,
280
+ name: null,
281
+ credentialSource: "unknown",
282
+ }),
283
+ permissions: isCurrent
284
+ ? current.permissions
285
+ : Object.freeze({ status: "unknown" }),
286
+ policy: isCurrent
287
+ ? current.policy
288
+ : Object.freeze({
289
+ network: "unknown",
290
+ sandbox: "unknown",
291
+ dataBoundary: Object.freeze({ kind: "unknown", root: null }),
292
+ }),
293
+ startup: profile.startup,
294
+ continuity: profile.continuity,
295
+ cost: profile.cost,
296
+ connectors: Object.freeze([...profile.connectors]),
297
+ capabilities: Object.freeze({
298
+ execute: isCurrent ? "available" : profile.launch,
299
+ launch: profile.launch,
300
+ resume: profile.resume,
301
+ handoffPreview: "available",
302
+ }),
303
+ mechanism: profile.executor,
304
+ });
305
+ }
306
+
307
+ export function buildExecutionLocationCatalog(binding) {
308
+ const current = normalizeExecutionLocationBinding(binding);
309
+ const locations = [
310
+ EXECUTION_LOCATION.LOCAL,
311
+ EXECUTION_LOCATION.WSL,
312
+ EXECUTION_LOCATION.SSH,
313
+ EXECUTION_LOCATION.CONTAINER,
314
+ EXECUTION_LOCATION.CLOUD,
315
+ ];
316
+ return Object.freeze({
317
+ schema: EXECUTION_LOCATION_CATALOG_SCHEMA,
318
+ currentLocation: current.location,
319
+ currentBinding: current,
320
+ controlPlane: Object.freeze({
321
+ remoteControl: Object.freeze({
322
+ executionLocation: false,
323
+ meaning:
324
+ "remote UI control of execution that remains on the local host",
325
+ }),
326
+ }),
327
+ locations: Object.freeze(
328
+ locations.map((location) => catalogEntry(location, current)),
329
+ ),
330
+ });
331
+ }
332
+
333
+ function pushUnique(output, value) {
334
+ if (!output.includes(value)) output.push(value);
335
+ }
336
+
337
+ function validDigest(value) {
338
+ return typeof value === "string" && /^sha256:[a-f0-9]{64}$/u.test(value);
339
+ }
340
+
341
+ function validReference(value) {
342
+ return (
343
+ typeof value === "string" &&
344
+ /^[A-Za-z0-9][A-Za-z0-9._/@:+-]{2,255}$/u.test(value)
345
+ );
346
+ }
347
+
348
+ export function buildExecutionLocationHandoffPreview(input = {}) {
349
+ const source = normalizeExecutionLocationBinding(input.sourceBinding);
350
+ const target = normalizeExecutionLocation(input.target);
351
+ const facts =
352
+ input.facts && typeof input.facts === "object" ? input.facts : {};
353
+ const expectedAuthority =
354
+ input.sourceAuthority && typeof input.sourceAuthority === "object"
355
+ ? input.sourceAuthority
356
+ : {};
357
+ const blockers = [];
358
+ const warnings = [];
359
+
360
+ if (facts.schema !== EXECUTION_LOCATION_HANDOFF_FACTS_SCHEMA) {
361
+ pushUnique(blockers, "handoff-facts-schema-invalid");
362
+ }
363
+ if (target === EXECUTION_LOCATION.UNKNOWN) {
364
+ pushUnique(blockers, "target-location-unknown");
365
+ }
366
+ if (containsForbiddenSecretMaterial(facts)) {
367
+ pushUnique(blockers, "credential-value-present");
368
+ }
369
+
370
+ const factsAuthority =
371
+ facts.authority && typeof facts.authority === "object"
372
+ ? facts.authority
373
+ : {};
374
+ const expectedSessionId = safeString(expectedAuthority.sessionId);
375
+ const expectedHeadHash = safeString(expectedAuthority.headHash, { max: 64 });
376
+ const expectedEventCount = Number(expectedAuthority.eventCount);
377
+ const factsSessionId = safeString(factsAuthority.sessionId);
378
+ const factsHeadHash = safeString(factsAuthority.headHash, { max: 64 });
379
+ const factsEventCount = Number(factsAuthority.eventCount);
380
+ const expectedAuthorityValid =
381
+ expectedSessionId != null &&
382
+ /^[a-f0-9]{64}$/u.test(expectedHeadHash || "") &&
383
+ Number.isSafeInteger(expectedEventCount) &&
384
+ expectedEventCount > 0;
385
+ const factsAuthorityValid =
386
+ factsSessionId != null &&
387
+ /^[a-f0-9]{64}$/u.test(factsHeadHash || "") &&
388
+ Number.isSafeInteger(factsEventCount) &&
389
+ factsEventCount > 0;
390
+ if (!expectedAuthorityValid || !factsAuthorityValid) {
391
+ pushUnique(blockers, "session-authority-evidence-missing");
392
+ } else if (
393
+ factsSessionId !== expectedSessionId ||
394
+ factsHeadHash !== expectedHeadHash ||
395
+ factsEventCount !== expectedEventCount
396
+ ) {
397
+ pushUnique(blockers, "session-authority-evidence-mismatch");
398
+ }
399
+
400
+ const targetEvidence =
401
+ facts.target && typeof facts.target === "object" ? facts.target : {};
402
+ const crossingLocation = target !== source.location;
403
+ if (
404
+ crossingLocation &&
405
+ (targetEvidence.configured !== true ||
406
+ !validReference(targetEvidence.evidenceId))
407
+ ) {
408
+ pushUnique(blockers, "target-configuration-evidence-missing");
409
+ }
410
+ const targetNetwork = enumValue(
411
+ targetEvidence.networkPolicy,
412
+ NETWORK_POLICIES,
413
+ );
414
+ const targetSandbox = enumValue(
415
+ targetEvidence.sandboxStrength,
416
+ SANDBOX_STRENGTHS,
417
+ );
418
+ const targetBoundary = normalizeDataBoundary(targetEvidence.dataBoundary);
419
+ if (crossingLocation && targetNetwork === "unknown") {
420
+ pushUnique(blockers, "target-network-policy-unknown");
421
+ }
422
+ if (crossingLocation && targetSandbox === "unknown") {
423
+ pushUnique(blockers, "target-sandbox-strength-unknown");
424
+ }
425
+ if (crossingLocation && targetBoundary.kind === "unknown") {
426
+ pushUnique(blockers, "target-data-boundary-unknown");
427
+ }
428
+
429
+ const git = facts.git && typeof facts.git === "object" ? facts.git : {};
430
+ const gitStatus = ["clean", "dirty"].includes(git.status)
431
+ ? git.status
432
+ : "unknown";
433
+ const sourceCommit = safeString(source.source.git.commit, { max: 128 });
434
+ const baseCommit = safeString(git.baseCommit, { max: 128 });
435
+ const strategy = HANDOFF_STRATEGIES.has(facts.strategy?.kind)
436
+ ? facts.strategy.kind
437
+ : "none";
438
+ const strategyRef = safeString(facts.strategy?.ref, { max: 256 });
439
+ const strategyDigest = safeString(facts.strategy?.artifactDigest, {
440
+ max: 80,
441
+ });
442
+ if (gitStatus === "unknown") {
443
+ pushUnique(blockers, "git-state-unknown");
444
+ } else if (!sourceCommit || baseCommit !== sourceCommit) {
445
+ pushUnique(blockers, "git-base-commit-mismatch");
446
+ } else if (gitStatus === "clean") {
447
+ if (strategy !== "commit" || strategyRef !== sourceCommit) {
448
+ pushUnique(blockers, "clean-worktree-commit-missing");
449
+ }
450
+ } else if (!(
451
+ (strategy === "stash" && validReference(strategyRef)) ||
452
+ (strategy === "patch" && validDigest(strategyDigest))
453
+ )) {
454
+ pushUnique(blockers, "dirty-worktree-without-stash-or-patch");
455
+ }
456
+
457
+ if (facts.summary?.included !== true || !validDigest(facts.summary?.digest)) {
458
+ pushUnique(blockers, "session-summary-missing");
459
+ }
460
+ if (
461
+ facts.permissions?.included !== true ||
462
+ !validDigest(facts.permissions?.digest)
463
+ ) {
464
+ pushUnique(blockers, "permission-handoff-missing");
465
+ }
466
+
467
+ const artifacts = [];
468
+ if (!Array.isArray(facts.artifacts)) {
469
+ pushUnique(blockers, "artifact-inventory-missing");
470
+ }
471
+ for (const item of Array.isArray(facts.artifacts) ? facts.artifacts : []) {
472
+ const name = safeString(item?.name);
473
+ const digest = safeString(item?.digest, { max: 80 });
474
+ if (name && validDigest(digest)) {
475
+ artifacts.push(Object.freeze({ name, digest }));
476
+ } else pushUnique(blockers, "artifact-evidence-invalid");
477
+ }
478
+ if (
479
+ strategy === "patch" &&
480
+ validDigest(strategyDigest) &&
481
+ !artifacts.some((artifact) => artifact.digest === strategyDigest)
482
+ ) {
483
+ pushUnique(blockers, "patch-artifact-not-in-inventory");
484
+ }
485
+ if (!Array.isArray(facts.credentials)) {
486
+ pushUnique(blockers, "credential-inventory-missing");
487
+ }
488
+ const credentials = containsForbiddenSecretMaterial(facts.credentials)
489
+ ? []
490
+ : normalizeCredentials(facts.credentials);
491
+ const requiredCapabilities = normalizeNames(facts.requiredCapabilities);
492
+ const evidencedCapabilities = normalizeNames(targetEvidence.capabilities);
493
+ for (const capability of requiredCapabilities) {
494
+ if (!evidencedCapabilities.includes(capability)) {
495
+ pushUnique(blockers, `target-capability-unavailable:${capability}`);
496
+ }
497
+ }
498
+ if (credentials.length > 0) {
499
+ warnings.push(
500
+ "credential references require target-side re-authorization; values are never transferred",
501
+ );
502
+ }
503
+
504
+ return Object.freeze({
505
+ schema: EXECUTION_LOCATION_HANDOFF_SCHEMA,
506
+ allowed: blockers.length === 0,
507
+ source: Object.freeze({
508
+ location: source.location,
509
+ sessionBindingSchema: source.schema,
510
+ authority: Object.freeze({
511
+ sessionId: expectedSessionId,
512
+ headHash: expectedHeadHash,
513
+ eventCount: Number.isSafeInteger(expectedEventCount)
514
+ ? expectedEventCount
515
+ : null,
516
+ }),
517
+ git: source.source.git,
518
+ policy: source.policy,
519
+ }),
520
+ target: Object.freeze({
521
+ location: target,
522
+ configured: targetEvidence.configured === true,
523
+ evidenceId: safeString(targetEvidence.evidenceId),
524
+ networkPolicy: targetNetwork,
525
+ sandboxStrength: targetSandbox,
526
+ dataBoundary: Object.freeze(targetBoundary),
527
+ capabilities: Object.freeze(evidencedCapabilities),
528
+ evidenceAuthority: "operator-supplied-facts",
529
+ }),
530
+ transfer: Object.freeze({
531
+ git: Object.freeze({
532
+ status: gitStatus,
533
+ baseCommit,
534
+ strategy,
535
+ ref: strategyRef,
536
+ artifactDigest: strategyDigest,
537
+ }),
538
+ summaryDigest: validDigest(facts.summary?.digest)
539
+ ? facts.summary.digest
540
+ : null,
541
+ permissionDigest: validDigest(facts.permissions?.digest)
542
+ ? facts.permissions.digest
543
+ : null,
544
+ artifacts: Object.freeze(artifacts),
545
+ credentialRefs: Object.freeze(credentials),
546
+ credentialValuesTransferred: false,
547
+ }),
548
+ blockers: Object.freeze(blockers),
549
+ warnings: Object.freeze(warnings),
550
+ });
551
+ }
@@ -0,0 +1,130 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { createExecutionLocationBinding } from "./execution-location-contract.js";
4
+ import { detectAmbientLocation } from "./execution-location.js";
5
+
6
+ const LOCATION_SIGNAL_NAMES = Object.freeze([
7
+ "CODESPACES",
8
+ "GITHUB_CODESPACE_TOKEN",
9
+ "SSH_CONNECTION",
10
+ "SSH_CLIENT",
11
+ "SSH_TTY",
12
+ "container",
13
+ "KUBERNETES_SERVICE_HOST",
14
+ "WSL_DISTRO_NAME",
15
+ "WSL_INTEROP",
16
+ ]);
17
+
18
+ function readSmallUtf8(runtimeFs, filePath, maxBytes = 4096) {
19
+ try {
20
+ const stat = runtimeFs.lstatSync(filePath);
21
+ if (!stat.isFile() || stat.isSymbolicLink() || stat.size > maxBytes) {
22
+ return null;
23
+ }
24
+ return runtimeFs.readFileSync(filePath, "utf8");
25
+ } catch {
26
+ return null;
27
+ }
28
+ }
29
+
30
+ function resolveGitDirectory(runtimeFs, markerPath) {
31
+ try {
32
+ const stat = runtimeFs.lstatSync(markerPath);
33
+ if (stat.isSymbolicLink()) return null;
34
+ if (stat.isDirectory()) return markerPath;
35
+ if (!stat.isFile() || stat.size > 4096) return null;
36
+ const marker = runtimeFs.readFileSync(markerPath, "utf8").trim();
37
+ const match = /^gitdir:\s*(.+)$/iu.exec(marker);
38
+ return match ? path.resolve(path.dirname(markerPath), match[1]) : null;
39
+ } catch {
40
+ return null;
41
+ }
42
+ }
43
+
44
+ function discoverGit(runtimeFs, cwd) {
45
+ let cursor = path.resolve(cwd);
46
+ while (true) {
47
+ const marker = path.join(cursor, ".git");
48
+ const gitDirectory = resolveGitDirectory(runtimeFs, marker);
49
+ if (gitDirectory) {
50
+ const rawHead = readSmallUtf8(
51
+ runtimeFs,
52
+ path.join(gitDirectory, "HEAD"),
53
+ 1024,
54
+ )?.trim();
55
+ let head = null;
56
+ let commit = null;
57
+ if (rawHead && /^[a-f0-9]{40,64}$/iu.test(rawHead)) {
58
+ head = "detached";
59
+ commit = rawHead.toLowerCase();
60
+ } else {
61
+ const match = /^ref:\s*(refs\/[A-Za-z0-9._\/-]+)$/u.exec(rawHead || "");
62
+ if (match && !match[1].includes("..")) {
63
+ head = match[1];
64
+ const loose = readSmallUtf8(
65
+ runtimeFs,
66
+ path.join(gitDirectory, ...match[1].split("/")),
67
+ 256,
68
+ )?.trim();
69
+ if (loose && /^[a-f0-9]{40,64}$/iu.test(loose)) {
70
+ commit = loose.toLowerCase();
71
+ }
72
+ }
73
+ }
74
+ return { root: cursor, head, commit };
75
+ }
76
+ const parent = path.dirname(cursor);
77
+ if (parent === cursor) return { root: null, head: null, commit: null };
78
+ cursor = parent;
79
+ }
80
+ }
81
+
82
+ export function captureAmbientExecutionLocation(options = {}, deps = {}) {
83
+ const runtimeFs = deps.fs || fs;
84
+ const env = deps.env || process.env;
85
+ const cwd = path.resolve(deps.cwd ? deps.cwd() : process.cwd());
86
+ const dockerEnvFileExists = (() => {
87
+ try {
88
+ return runtimeFs.existsSync("/.dockerenv");
89
+ } catch {
90
+ return false;
91
+ }
92
+ })();
93
+ const location = detectAmbientLocation({ env, dockerEnvFileExists });
94
+ const git = discoverGit(runtimeFs, cwd);
95
+ const signals = LOCATION_SIGNAL_NAMES.filter(
96
+ (name) => typeof env[name] === "string" && env[name].trim() !== "",
97
+ );
98
+ const observedAt = deps.now ? deps.now() : new Date().toISOString();
99
+ return createExecutionLocationBinding({
100
+ location,
101
+ observedAt,
102
+ observed: true,
103
+ signals,
104
+ source: { cwd, git },
105
+ runtime: {
106
+ platform: deps.platform || process.platform,
107
+ arch: deps.arch || process.arch,
108
+ nodeVersion: deps.nodeVersion || process.version,
109
+ tools: ["chainlesschain-cli", "node"],
110
+ },
111
+ model: {
112
+ provider: options.provider,
113
+ name: options.model,
114
+ credentialSource: options.credentialSource || "not-observed",
115
+ },
116
+ credentials: options.credentials,
117
+ permissions: {
118
+ status: options.permissions ? "declared" : "not-observed",
119
+ ...(options.permissions || {}),
120
+ },
121
+ policy: {
122
+ network: options.networkPolicy || "unknown",
123
+ sandbox: options.sandboxStrength || "unknown",
124
+ dataBoundary: {
125
+ kind: git.root ? "repository" : "working-directory",
126
+ root: git.root || cwd,
127
+ },
128
+ },
129
+ });
130
+ }