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.
- package/package.json +7 -4
- package/scripts/macos-mcp-launcher-build.mjs +317 -0
- package/scripts/macos-mcp-launcher-postinstall.sh +54 -0
- package/scripts/macos-mcp-launcher-preinstall.sh +61 -0
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-CavM7W3k.js → AIOps-CYxFDrcm.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CUvZGabQ.js → ActionButton-CPBtdiU2.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DeBnWnbe.js → Analytics-Dayq7Dp7.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DbI5kxvd.js → AppLayout-6U7bPb2s.js} +4 -4
- package/src/assets/web-panel/assets/{Artifacts-D93bigKm.js → Artifacts-D2Iqg_3D.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CBNvfUZa.js → Audit-CdoOB7WV.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-CJLyh_YU.js → BackgroundAgents-DrnAVB8w.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-D_0yoehD.js → Backup-CesMi5cy.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-TJxmbObW.js → BaseInput-DaX9ptax.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CE0dto1q.js → Chat-OrwOPxDS.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CZ5-yYiD.js → ChatBubbleRenderer-CvPZFRxM.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-Ck1RVIVo.js → Checkbox-DiHbcysC.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-qpoyf6DK.js → Codegen-CbgCkaBJ.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DUyPWjIE.js → Col-Du5hgrh4.js} +1 -1
- package/src/assets/web-panel/assets/{Community-D_S1BemS.js → Community-DsPOBW-p.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BjxeK-Gc.js → Compact-BwHIFkNC.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-Dd3CEJsu.js → Compliance-BvrDQSgd.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-B4QG7-ad.js → Cowork-gwAE6arx.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-BtZnids5.js → Cron-DW-0l4uF.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CHPfCBFD.js → Crosschain-j-NsLesB.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DT8DCEOK.js → DID-CibVEBOI.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-COQab5_U.js → Dashboard-W4z9vSfe.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BY1PsQuU.js → Dropdown-DAcrkKxG.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-CsuAuaq3.js → EmailListRenderer-6GXah-89.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-BqpinD-j.js → FamilyGuardDashboard-TKDCq8Ku.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-D0gkfQFv.js → Federation-BXBLlcNm.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-BqgE-axK.js → FormItemContext-BoJJBkG3.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-D0hJ2KvC.js → GenericCardRenderer-okjsl46v.js} +1 -1
- package/src/assets/web-panel/assets/{Git-CmMB0uPY.js → Git-Rvs7i6nn.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BnVEI0Dk.js → Governance-CHSUxXXS.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-YTAMihRP.js → Inference-V3BlfxsB.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-0ax7VHop.js → KnowledgeGraph-C_NlD4aR.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-B9TRcokL.js → Logs-Nn4LNxhA.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-SVAgNnkt.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-B6CSuD_H.js → Marketplace-DEmjFcg-.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CjMXvOVU.js → McpTools-DlopXipI.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-CXRF71U3.js → Memory-BG3ynX60.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-DQgNp_oS.js → MobileBridge-DeRzWOfT.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-DlPwcCbq.js → MobileProjects-Tyd3o2A0.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-6hDTRPe1.js → Mtc-BoPbOv1C.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-BlVHU1DS.js → MtcAudit-un-rTHp7.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-DP9pzEbV.js → Multisig-Ds0oveEB.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-Djorh8EV.js → NLProgramming-D09JI-yY.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-oLZ-JkUg.js → Notes-DTRhiKJn.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-Cg288VH3.js → NotificationSettings-BAnnNCim.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-Yr-1fSYi.js +1 -0
- package/src/assets/web-panel/assets/{Organization-CBdo-bHs.js → Organization-S9EAolpj.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-qZdnVumx.js → Overflow-CqcLKqJ8.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-D4kNfGNQ.js → P2P-Dw0F9EcU.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-DnlMemM7.js → PdhVaultBrowser-BDRwUevN.js} +5 -5
- package/src/assets/web-panel/assets/{Permissions-DHucHFBJ.js → Permissions-D3_c3nKB.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BovlOIPR.js → PersonalDataHub-CxdMV98x.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-Deru3CQY.js → Pipeline-CgjNQFLI.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-Bq5oTTbU.js → Privacy-BHghIIht.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BfzxVWAz.js → ProjectInit-De6pqaKM.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CKC6XBtH.js → ProjectSettings-Bg4ZkNYQ.js} +2 -2
- package/src/assets/web-panel/assets/Projects-CP8vPvzs.js +1 -0
- package/src/assets/web-panel/assets/{Providers-C_jx4TWX.js → Providers-CUnHbNf-.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-BdIHeVGC.js → QrScannerModal-DA2f3Wts.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BwZwAcPD.js → QuickAsk-C1FeHDqp.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-BNTt0L-m.js → Recommend-B5guaUMN.js} +1 -1
- package/src/assets/web-panel/assets/RemoteSession-PDADSds3.js +5 -0
- package/src/assets/web-panel/assets/{Reputation-D6VpG32B.js → Reputation-eTlRhgvK.js} +1 -1
- package/src/assets/web-panel/assets/{Row-D_74OvQQ.js → Row-D7AqSGY0.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BTr0a-BQ.js → RssFeed-JiuLm4Ja.js} +3 -3
- package/src/assets/web-panel/assets/{Search-C3MCFoNU.js → Search-CwruahW3.js} +1 -1
- package/src/assets/web-panel/assets/{Security-CqW9aJ6s.js → Security-CdhqaR0b.js} +4 -4
- package/src/assets/web-panel/assets/{Services-Cw5GNaHF.js → Services-CU0ZIlcT.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DZps5qeY.js → Skeleton-CtduPfAb.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-C6NQ1znT.js → Skills-CROXm6AY.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DFP8G2Sh.js → Sla-DiZiABFD.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-ESt6MB6v.js → SpeechSettings-B5pLcXUw.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-BHnN98aM.js → SyncSettings-DBX6J1Oe.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-NiSCaOf-.js → Tasks-BLyRJd3-.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-DsKFhW2C.js → Templates-BKa5qzmk.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CQ0E0ze5.js → Tenant-DnD3a4M6.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-D_rBu_by.js → Terminal-DEitQeTb.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-D3Vm4Po4.js → TimelineRenderer-CjHggTDq.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DNTxRH6q.js → Tokens-CsGT7sfl.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-Dgprz1ms.js → Trigger-yr4rFDrW.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-B2rUnVBD.js → Trust-CLvu1Sjp.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-DEGQNc6_.js → UkeySign-B0m7yUP8.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-jlsAx3Eh.js → VideoEditing-C0VvP4lc.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-8jQih1ij.js → Wallet-kllBAG1M.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-XLeO6xIB.js → WebAuthn-C54UQNLx.js} +3 -3
- package/src/assets/web-panel/assets/{WorkflowEditor-De_dgDAG.js → WorkflowEditor-B7y8qSvU.js} +1 -1
- package/src/assets/web-panel/assets/{chat-CI19R_Sk.js → chat-DRzTh8CJ.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DsYTOYN3.js → colors-BSMwSnCx.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-CM3-t_Qr.js → compact-item-BTg602H5.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BjxlBRZv.js → createContext-B6EGsdvp.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-Dol8jLEP.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-RDaWX_4i.js → hasIn-DDKqJ8RD.js} +1 -1
- package/src/assets/web-panel/assets/{index-nAH87mQP.js → index-323Hhxxt.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIUnNOjG.js → index-BICn3Qh1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DyIWssPC.js → index-BMuGd2--.js} +1 -1
- package/src/assets/web-panel/assets/{index-DX7tuWVJ.js → index-BRqt4fO-.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cd3euP_4.js → index-BVTAl5N2.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cpqm1qfU.js → index-BsR7Y2NG.js} +1 -1
- package/src/assets/web-panel/assets/{index-DcPFB8qJ.js → index-Bx044qDj.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cd9OJhHG.js → index-C1GFfuqN.js} +1 -1
- package/src/assets/web-panel/assets/index-C3QX5tOl.js +1 -0
- package/src/assets/web-panel/assets/{index-B-Z8eFUJ.js → index-C66NpWy5.js} +1 -1
- package/src/assets/web-panel/assets/{index-BlT2VAEK.js → index-CDTvsX8t.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dsij_KsN.js → index-CGNklbP6.js} +1 -1
- package/src/assets/web-panel/assets/{index-C4gkzxkw.js → index-CHfLYwcW.js} +1 -1
- package/src/assets/web-panel/assets/{index-D6sm5-Xq.js → index-CNxg61YP.js} +1 -1
- package/src/assets/web-panel/assets/{index-C0yx-jtQ.js → index-CQlHFN_g.js} +1 -1
- package/src/assets/web-panel/assets/{index-CjTrRt13.js → index-CUEU48o1.js} +1 -1
- package/src/assets/web-panel/assets/{index-B7WBt_4T.js → index-CWGax2QW.js} +1 -1
- package/src/assets/web-panel/assets/{index-IeiL9RKc.js → index-C_JzIXUq.js} +1 -1
- package/src/assets/web-panel/assets/{index-CnHH7bnD.js → index-Cf23wVMs.js} +1 -1
- package/src/assets/web-panel/assets/{index-BKJr-TZp.js → index-CmAInUkX.js} +1 -1
- package/src/assets/web-panel/assets/{index-CiECJi-Q.js → index-CmAubjDi.js} +1 -1
- package/src/assets/web-panel/assets/{index-BCnZyIMA.js → index-Co7oM1qr.js} +1 -1
- package/src/assets/web-panel/assets/{index-Drlnwr8F.js → index-CwPUZbMI.js} +1 -1
- package/src/assets/web-panel/assets/{index-9R6BxAr0.js → index-D1naNj4U.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGqqJfL0.js → index-D5CsBShd.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bi46Xu4u.js → index-DBT3YeQ9.js} +1 -1
- package/src/assets/web-panel/assets/{index-DXXtGMUJ.js → index-DLdrHhML.js} +1 -1
- package/src/assets/web-panel/assets/{index-B0PMlbMs.js → index-Dc77VR3H.js} +1 -1
- package/src/assets/web-panel/assets/{index-D0zcy54x.js → index-Dfv2lKu3.js} +1 -1
- package/src/assets/web-panel/assets/{index-BN6UPD2E.js → index-DiW0sDkz.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dxge-xWl.js → index-DpTHIRfZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CyOGN6a5.js → index-DqFXGzzC.js} +1 -1
- package/src/assets/web-panel/assets/{index-B9O9YyWE.js → index-XFe-1twF.js} +1 -1
- package/src/assets/web-panel/assets/{index-BHNYPO0b.js → index-p2HYn89m.js} +3 -3
- package/src/assets/web-panel/assets/{index-CVQMeiwH.js → index-pqfux8vZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-pPL66J85.js → index-rjzk9z1Q.js} +1 -1
- package/src/assets/web-panel/assets/{index-DoQA0-52.js → index-th2ihDc0.js} +1 -1
- package/src/assets/web-panel/assets/{index-B5REnKt8.js → index-u2YVld9W.js} +1 -1
- package/src/assets/web-panel/assets/index-xYybvEic.js +1 -0
- package/src/assets/web-panel/assets/{initDefaultProps-BTL88of4.js → initDefaultProps-C3Djh9fa.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BUB2pXwB.js → motion-BzqFmbSe.js} +1 -1
- package/src/assets/web-panel/assets/{move-egCkkOMm.js → move-DJo_FFaW.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DAWhZC8c.js → mtc-parser-_tlTiBvk.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CvOxe_6d.js → omit-CB2ZyxUg.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DZUSLZ5Z.js → pickAttrs-DZwIFD4u.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BERxGNMY.js → placementArrow-DxZY0dgk.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-DZuDfZ9n.js → responsiveObserve-CzzGt7GL.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DO756sgI.js → slide-BaIK52yz.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BRQlIz28.js → statusUtils-3-FHu9_M.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-DCSfdybl.js → styleChecker-BkRT68fK.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-LD8dWVve.js → useFlexGapSupport-DHYwKS-s.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-BX9uW2LK.js → useFs-DVVUhV8p.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BPSlPuHU.js → usePersonalDataHub-CkrFKAzQ.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BmOILC9V.js → vnode-BuBLFz0c.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-1iKowKGg.js → zoom-kpm6LtXU.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +3 -3
- package/src/commands/cowork.js +418 -41
- package/src/commands/permissions.js +240 -16
- package/src/commands/plugin.js +1293 -56
- package/src/commands/session-location.js +276 -0
- package/src/commands/session.js +2 -0
- package/src/data/changelog.json +28 -2
- package/src/gateways/ws/action-protocol.js +316 -17
- package/src/gateways/ws/message-dispatcher.js +30 -0
- package/src/gateways/ws/remote-session-protocol.js +565 -35
- package/src/gateways/ws/ws-agent-handler.js +12 -0
- package/src/gateways/ws/ws-approval-gate.js +5 -0
- package/src/gateways/ws/ws-server.js +510 -50
- package/src/harness/jsonl-session-store.js +341 -24
- package/src/harness/mcp-client.js +8 -1
- package/src/harness/remote-session-audit.js +2 -0
- package/src/harness/remote-session-crypto.js +929 -21
- package/src/harness/remote-session-registry.js +945 -24
- package/src/harness/session-list-index.js +233 -14
- package/src/lib/agent-authority.js +6 -0
- package/src/lib/auto-mode-config.js +98 -3
- package/src/lib/background-agent-keeper-client.js +248 -0
- package/src/lib/background-agent-keeper-protocol.js +291 -0
- package/src/lib/background-agent-supervisor.js +1357 -85
- package/src/lib/background-interaction-resolver.js +12 -0
- package/src/lib/background-session-transport.js +23 -6
- package/src/lib/background-turn-bootstrap-protocol.js +190 -0
- package/src/lib/cowork-workflow.js +1188 -76
- package/src/lib/delivery-production-adapter.js +38 -2
- package/src/lib/dynamic-workflow-facade.js +1736 -0
- package/src/lib/execution-location-contract.js +551 -0
- package/src/lib/execution-location-runtime.js +130 -0
- package/src/lib/ide-context.js +94 -6
- package/src/lib/mcp-stdio-package-materialization.js +166 -14
- package/src/lib/packer/pkg-config-generator.js +2 -0
- package/src/lib/permission-authority.js +77 -0
- package/src/lib/permission-side-effect-center.js +495 -0
- package/src/lib/plugin-runtime/install.js +514 -13
- package/src/lib/plugin-runtime/marketplace-artifact-readback.js +900 -0
- package/src/lib/plugin-runtime/marketplace-catalog.js +1181 -0
- package/src/lib/plugin-runtime/marketplace-impact.js +408 -0
- package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1567 -0
- package/src/lib/plugin-security.js +60 -3
- package/src/lib/process-execution-broker/index.js +1095 -57
- package/src/lib/process-execution-broker/linux-bwrap-descriptor-launch.js +375 -0
- package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +90 -16
- package/src/lib/process-execution-broker/linux-generic-bwrap.js +159 -18
- package/src/lib/process-execution-broker/macos-mcp-launcher-contract.js +278 -0
- package/src/lib/process-execution-broker/macos-mcp-launcher-protocol.json +23 -0
- package/src/lib/process-execution-broker/macos-mcp-launcher.c +1497 -0
- package/src/lib/process-execution-broker/mcp-fd-entry-bootstrap.js +37 -0
- package/src/lib/process-execution-broker/platform-sandbox.js +2330 -279
- package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
- package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
- package/src/lib/process-execution-broker/windows-sandbox.cs +50 -4
- package/src/lib/public-ide-capability-manifest.js +3 -0
- package/src/lib/remote-approval-bridge.js +777 -34
- package/src/lib/remote-control.js +2 -0
- package/src/lib/remote-membership-authority.js +632 -0
- package/src/lib/remote-membership-coordinator.js +2973 -0
- package/src/lib/remote-membership-host-store.js +1799 -0
- package/src/lib/runtime-provenance-ledger.js +171 -46
- package/src/lib/scoped-permission-store.js +369 -0
- package/src/lib/session-anti-rollback-anchor.js +262 -5
- package/src/lib/shell-approval.js +169 -6
- package/src/lib/sub-agent-context.js +4 -0
- package/src/lib/with-file-lock.js +73 -38
- package/src/lib/workflow-definition-contract.js +149 -0
- package/src/repl/agent-repl.js +111 -36
- package/src/repl/chat-repl.js +2 -0
- package/src/repl/clipboard-image.js +735 -16
- package/src/repl/ide-status.js +1 -1
- package/src/repl/prompt-interactions.js +59 -6
- package/src/repl/remote-approval.js +29 -7
- package/src/runtime/agent-core.js +1182 -155
- package/src/runtime/headless-runner.js +52 -30
- package/src/runtime/headless-stream.js +51 -28
- package/src/workers/background-agent-keeper.js +689 -0
- package/src/workers/background-agent-worker.js +365 -13
- package/src/workers/background-turn-bootstrap.js +170 -0
- package/src/assets/web-panel/assets/MarkdownRenderer-yySN5YNM.js +0 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-Bb1O3Ofr.js +0 -1
- package/src/assets/web-panel/assets/Projects-CMolGhae.js +0 -1
- package/src/assets/web-panel/assets/RemoteSession-Biyn2-Ro.js +0 -5
- package/src/assets/web-panel/assets/devWarning-S1ld2LwU.js +0 -1
- package/src/assets/web-panel/assets/index-Drz6yq0m.js +0 -1
- package/src/assets/web-panel/assets/index-uWiUs7S_.js +0 -1
|
@@ -12,10 +12,13 @@
|
|
|
12
12
|
* `timeoutMs`, it proceeds unlocked. Callers that set `failIfUnavailable` get a
|
|
13
13
|
* strict lock: every owner has a PID + unguessable token, a live owner is never
|
|
14
14
|
* reclaimed merely because the directory is old, and corrupt ownership fails
|
|
15
|
-
* closed.
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
15
|
+
* closed. The default filesystem publishes a fully populated, uniquely staged
|
|
16
|
+
* directory in one rename so a process killed during acquisition cannot expose
|
|
17
|
+
* an ownerless lock. Confirmed-dead owners are reclaimed with an exact-token
|
|
18
|
+
* marker inside the lock directory so a delayed contender cannot delete a
|
|
19
|
+
* replacement lock. Strict callers may use bounded jittered retries and an
|
|
20
|
+
* after-release yield to avoid Windows sharing transients and fixed-interval
|
|
21
|
+
* lock convoys.
|
|
19
22
|
*
|
|
20
23
|
* @param {string} targetPath the file being guarded (lock is `${targetPath}.lock`)
|
|
21
24
|
* @param {(ctx:{locked:boolean})=>T} fn critical section; receives whether the lock was held
|
|
@@ -37,6 +40,10 @@ export function withFileLock(targetPath, fn, opts = {}) {
|
|
|
37
40
|
_ownerToken = () => randomUUID(),
|
|
38
41
|
failIfUnavailable = false,
|
|
39
42
|
} = opts;
|
|
43
|
+
const isOwnerAlive =
|
|
44
|
+
typeof opts._isOwnerAlive === "function"
|
|
45
|
+
? opts._isOwnerAlive
|
|
46
|
+
: (candidate) => _isProcessAlive(candidate.pid);
|
|
40
47
|
|
|
41
48
|
const lockDir = `${targetPath}.lock`;
|
|
42
49
|
const ownerPath = path.join(lockDir, "owner.json");
|
|
@@ -52,36 +59,9 @@ export function withFileLock(targetPath, fn, opts = {}) {
|
|
|
52
59
|
|
|
53
60
|
for (;;) {
|
|
54
61
|
try {
|
|
55
|
-
_fs
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
encoding: "utf8",
|
|
59
|
-
mode: 0o600,
|
|
60
|
-
flag: "wx",
|
|
61
|
-
});
|
|
62
|
-
held = true;
|
|
63
|
-
break;
|
|
64
|
-
} catch (error) {
|
|
65
|
-
_fs.rmSync(lockDir, { recursive: true, force: true });
|
|
66
|
-
acquisitionError = error;
|
|
67
|
-
if (
|
|
68
|
-
failIfUnavailable &&
|
|
69
|
-
isTransientLockError(error) &&
|
|
70
|
-
waitForRetry({
|
|
71
|
-
_now,
|
|
72
|
-
_sleep,
|
|
73
|
-
_random,
|
|
74
|
-
deadline,
|
|
75
|
-
retryAttempt: retryAttempt++,
|
|
76
|
-
retryMs,
|
|
77
|
-
maxRetryMs,
|
|
78
|
-
retryJitterMs,
|
|
79
|
-
})
|
|
80
|
-
) {
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
62
|
+
acquireOwnedDirectory(_fs, lockDir, owner);
|
|
63
|
+
held = true;
|
|
64
|
+
break;
|
|
85
65
|
} catch (error) {
|
|
86
66
|
if (!error || error.code !== "EEXIST") {
|
|
87
67
|
acquisitionError = error;
|
|
@@ -108,8 +88,8 @@ export function withFileLock(targetPath, fn, opts = {}) {
|
|
|
108
88
|
const incumbent = ownerRead.owner;
|
|
109
89
|
acquisitionError = ownerRead.error;
|
|
110
90
|
if (incumbent) {
|
|
111
|
-
if (!
|
|
112
|
-
if (reclaimOwnedDirectory(_fs, lockDir, incumbent,
|
|
91
|
+
if (!isOwnerAlive(incumbent)) {
|
|
92
|
+
if (reclaimOwnedDirectory(_fs, lockDir, incumbent, isOwnerAlive)) {
|
|
113
93
|
continue;
|
|
114
94
|
}
|
|
115
95
|
}
|
|
@@ -200,6 +180,61 @@ const defaultFs = {
|
|
|
200
180
|
rmSync: (p, o) => fs.rmSync(p, o),
|
|
201
181
|
};
|
|
202
182
|
|
|
183
|
+
function acquireOwnedDirectory(_fs, lockDir, owner) {
|
|
184
|
+
const serializedOwner = JSON.stringify(owner);
|
|
185
|
+
// Injected legacy filesystems used by a few consumers may not implement
|
|
186
|
+
// rename. Keep their old acquire path, while the real Node filesystem always
|
|
187
|
+
// uses the crash-safe staged publication below.
|
|
188
|
+
if (typeof _fs.renameSync !== "function") {
|
|
189
|
+
_fs.mkdirSync(lockDir);
|
|
190
|
+
try {
|
|
191
|
+
_fs.writeFileSync(path.join(lockDir, "owner.json"), serializedOwner, {
|
|
192
|
+
encoding: "utf8",
|
|
193
|
+
mode: 0o600,
|
|
194
|
+
flag: "wx",
|
|
195
|
+
});
|
|
196
|
+
return;
|
|
197
|
+
} catch (error) {
|
|
198
|
+
_fs.rmSync(lockDir, { recursive: true, force: true });
|
|
199
|
+
throw error;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const candidateDir = `${lockDir}.acquire-${owner.token}`;
|
|
204
|
+
try {
|
|
205
|
+
_fs.mkdirSync(candidateDir);
|
|
206
|
+
_fs.writeFileSync(path.join(candidateDir, "owner.json"), serializedOwner, {
|
|
207
|
+
encoding: "utf8",
|
|
208
|
+
mode: 0o600,
|
|
209
|
+
flag: "wx",
|
|
210
|
+
});
|
|
211
|
+
_fs.renameSync(candidateDir, lockDir);
|
|
212
|
+
} catch (error) {
|
|
213
|
+
try {
|
|
214
|
+
_fs.rmSync(candidateDir, { recursive: true, force: true });
|
|
215
|
+
} catch {
|
|
216
|
+
/* uniquely-tokened acquisition debris cannot block the lock path */
|
|
217
|
+
}
|
|
218
|
+
if (directoryExists(_fs, lockDir)) {
|
|
219
|
+
const contention = new Error("State lock already exists", {
|
|
220
|
+
cause: error,
|
|
221
|
+
});
|
|
222
|
+
contention.code = "EEXIST";
|
|
223
|
+
throw contention;
|
|
224
|
+
}
|
|
225
|
+
throw error;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function directoryExists(_fs, target) {
|
|
230
|
+
try {
|
|
231
|
+
_fs.statSync(target);
|
|
232
|
+
return true;
|
|
233
|
+
} catch {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
203
238
|
function isProcessAlive(pid) {
|
|
204
239
|
try {
|
|
205
240
|
process.kill(pid, 0);
|
|
@@ -310,7 +345,7 @@ function writeOwnerMarker(_fs, markerPath, owner) {
|
|
|
310
345
|
});
|
|
311
346
|
}
|
|
312
347
|
|
|
313
|
-
function reclaimOwnedDirectory(_fs, lockDir, owner,
|
|
348
|
+
function reclaimOwnedDirectory(_fs, lockDir, owner, ownerAlive) {
|
|
314
349
|
const markerPath = path.join(lockDir, `.reclaim-${owner.token}`);
|
|
315
350
|
try {
|
|
316
351
|
writeOwnerMarker(_fs, markerPath, owner);
|
|
@@ -319,7 +354,7 @@ function reclaimOwnedDirectory(_fs, lockDir, owner, processAlive) {
|
|
|
319
354
|
throw error;
|
|
320
355
|
}
|
|
321
356
|
const current = readOwner(_fs, path.join(lockDir, "owner.json"));
|
|
322
|
-
if (!sameOwner(current, owner) ||
|
|
357
|
+
if (!sameOwner(current, owner) || ownerAlive(owner)) {
|
|
323
358
|
removeOwnMarker(_fs, markerPath, owner);
|
|
324
359
|
return false;
|
|
325
360
|
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
export const WORKFLOW_DEFINITION_SCHEMA = "cc-dynamic-workflow-definition/v1";
|
|
4
|
+
export const COWORK_WORKFLOW_RECORD_SCHEMA = "cc-cowork-workflow-record/v1";
|
|
5
|
+
export const MAX_WORKFLOW_DEFINITION_BYTES = 1024 * 1024;
|
|
6
|
+
|
|
7
|
+
function stableJsonValue(value, state = { nodes: 0, depth: 0 }) {
|
|
8
|
+
state.nodes += 1;
|
|
9
|
+
if (state.nodes > 20_000 || state.depth > 32) {
|
|
10
|
+
throw new TypeError("workflow definition exceeds canonicalization limits");
|
|
11
|
+
}
|
|
12
|
+
if (
|
|
13
|
+
value === null ||
|
|
14
|
+
typeof value === "boolean" ||
|
|
15
|
+
typeof value === "string"
|
|
16
|
+
) {
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
if (typeof value === "number") {
|
|
20
|
+
if (!Number.isFinite(value)) {
|
|
21
|
+
throw new TypeError("workflow definition contains a non-finite number");
|
|
22
|
+
}
|
|
23
|
+
return Object.is(value, -0) ? 0 : value;
|
|
24
|
+
}
|
|
25
|
+
if (Array.isArray(value)) {
|
|
26
|
+
const childState = { ...state, depth: state.depth + 1 };
|
|
27
|
+
const output = value.map((item) => stableJsonValue(item, childState));
|
|
28
|
+
state.nodes = childState.nodes;
|
|
29
|
+
return output;
|
|
30
|
+
}
|
|
31
|
+
if (value && typeof value === "object") {
|
|
32
|
+
const prototype = Object.getPrototypeOf(value);
|
|
33
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
34
|
+
throw new TypeError(
|
|
35
|
+
"workflow definition must contain plain JSON objects",
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
const childState = { ...state, depth: state.depth + 1 };
|
|
39
|
+
const output = {};
|
|
40
|
+
for (const key of Object.keys(value).sort()) {
|
|
41
|
+
const child = value[key];
|
|
42
|
+
if (child === undefined) continue;
|
|
43
|
+
if (["function", "symbol", "bigint"].includes(typeof child)) {
|
|
44
|
+
throw new TypeError("workflow definition contains a non-JSON value");
|
|
45
|
+
}
|
|
46
|
+
output[key] = stableJsonValue(child, childState);
|
|
47
|
+
}
|
|
48
|
+
state.nodes = childState.nodes;
|
|
49
|
+
return output;
|
|
50
|
+
}
|
|
51
|
+
throw new TypeError("workflow definition contains a non-JSON value");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function deepFreeze(value) {
|
|
55
|
+
if (!value || typeof value !== "object" || Object.isFrozen(value)) {
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
for (const child of Object.values(value)) deepFreeze(child);
|
|
59
|
+
return Object.freeze(value);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function digestDefinition(definition) {
|
|
63
|
+
const canonical = JSON.stringify(definition);
|
|
64
|
+
if (Buffer.byteLength(canonical, "utf8") > MAX_WORKFLOW_DEFINITION_BYTES) {
|
|
65
|
+
throw new TypeError(
|
|
66
|
+
`workflow definition exceeds ${MAX_WORKFLOW_DEFINITION_BYTES} bytes`,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
return `sha256:${createHash("sha256").update(canonical).digest("hex")}`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function integrityError(message) {
|
|
73
|
+
const error = new Error(message);
|
|
74
|
+
error.code = "WORKFLOW_DEFINITION_INTEGRITY";
|
|
75
|
+
return error;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function normalizeWorkflowDefinitionDigest(value) {
|
|
79
|
+
if (typeof value !== "string") return null;
|
|
80
|
+
const normalized = value.trim().toLowerCase();
|
|
81
|
+
return /^sha256:[a-f0-9]{64}$/u.test(normalized) ? normalized : null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function createWorkflowDefinitionAuthority(workflow) {
|
|
85
|
+
const definition = deepFreeze(stableJsonValue(workflow));
|
|
86
|
+
return Object.freeze({
|
|
87
|
+
schema: WORKFLOW_DEFINITION_SCHEMA,
|
|
88
|
+
definitionDigest: digestDefinition(definition),
|
|
89
|
+
definition,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function createCoworkWorkflowRecord(workflow) {
|
|
94
|
+
const authority = createWorkflowDefinitionAuthority(workflow);
|
|
95
|
+
const record = {
|
|
96
|
+
schema: COWORK_WORKFLOW_RECORD_SCHEMA,
|
|
97
|
+
definitionSchema: authority.schema,
|
|
98
|
+
definitionDigest: authority.definitionDigest,
|
|
99
|
+
definition: authority.definition,
|
|
100
|
+
};
|
|
101
|
+
const serialized = JSON.stringify(record, null, 2);
|
|
102
|
+
if (Buffer.byteLength(serialized, "utf8") > MAX_WORKFLOW_DEFINITION_BYTES) {
|
|
103
|
+
throw new TypeError(
|
|
104
|
+
`workflow definition exceeds ${MAX_WORKFLOW_DEFINITION_BYTES} bytes`,
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
return Object.freeze(record);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function verifyCoworkWorkflowRecord(value, options = {}) {
|
|
111
|
+
if (
|
|
112
|
+
value?.schema !== COWORK_WORKFLOW_RECORD_SCHEMA &&
|
|
113
|
+
options.allowLegacy === true
|
|
114
|
+
) {
|
|
115
|
+
const authority = createWorkflowDefinitionAuthority(value);
|
|
116
|
+
return Object.freeze({
|
|
117
|
+
status: "legacy-unversioned",
|
|
118
|
+
recordSchema: null,
|
|
119
|
+
definitionSchema: authority.schema,
|
|
120
|
+
definitionDigest: authority.definitionDigest,
|
|
121
|
+
definition: authority.definition,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
if (!value || value.schema !== COWORK_WORKFLOW_RECORD_SCHEMA) {
|
|
125
|
+
throw integrityError(
|
|
126
|
+
`workflow record must use ${COWORK_WORKFLOW_RECORD_SCHEMA}`,
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
if (value.definitionSchema !== WORKFLOW_DEFINITION_SCHEMA) {
|
|
130
|
+
throw integrityError("workflow definition schema is unsupported");
|
|
131
|
+
}
|
|
132
|
+
const declaredDigest = normalizeWorkflowDefinitionDigest(
|
|
133
|
+
value.definitionDigest,
|
|
134
|
+
);
|
|
135
|
+
if (!declaredDigest) {
|
|
136
|
+
throw integrityError("workflow definition digest is invalid");
|
|
137
|
+
}
|
|
138
|
+
const authority = createWorkflowDefinitionAuthority(value.definition);
|
|
139
|
+
if (authority.definitionDigest !== declaredDigest) {
|
|
140
|
+
throw integrityError("workflow definition digest mismatch");
|
|
141
|
+
}
|
|
142
|
+
return Object.freeze({
|
|
143
|
+
status: "versioned",
|
|
144
|
+
recordSchema: COWORK_WORKFLOW_RECORD_SCHEMA,
|
|
145
|
+
definitionSchema: authority.schema,
|
|
146
|
+
definitionDigest: authority.definitionDigest,
|
|
147
|
+
definition: authority.definition,
|
|
148
|
+
});
|
|
149
|
+
}
|
package/src/repl/agent-repl.js
CHANGED
|
@@ -25,6 +25,7 @@ import path from "path";
|
|
|
25
25
|
import { randomUUID } from "node:crypto";
|
|
26
26
|
import { isPromise, isProxy } from "node:util/types";
|
|
27
27
|
import { logger } from "../lib/logger.js";
|
|
28
|
+
import { captureAmbientExecutionLocation } from "../lib/execution-location-runtime.js";
|
|
28
29
|
import { issueMcpStdioExecutionAuthority } from "../lib/mcp-stdio-execution-authority.js";
|
|
29
30
|
import { getPlanModeManager, PlanState } from "../lib/plan-mode.js";
|
|
30
31
|
import { createVimState, feedNormalKey } from "../lib/repl-vim.js";
|
|
@@ -88,6 +89,7 @@ import {
|
|
|
88
89
|
persistSideEffectLedger,
|
|
89
90
|
} from "../lib/side-effect-ledger-store.js";
|
|
90
91
|
import { operationIdempotencyKey } from "../lib/idempotency.js";
|
|
92
|
+
import { collectToolResourceIdentifiers } from "../lib/permission-side-effect-center.js";
|
|
91
93
|
import {
|
|
92
94
|
preserveDurableSystemMessageProvenance,
|
|
93
95
|
projectCanonicalResumeMessages,
|
|
@@ -173,6 +175,7 @@ import {
|
|
|
173
175
|
createPromptInteractionSurface,
|
|
174
176
|
mergeClipboardImageChips,
|
|
175
177
|
} from "./prompt-interactions.js";
|
|
178
|
+
import { createSystemClipboardImageBinding } from "./clipboard-image.js";
|
|
176
179
|
import {
|
|
177
180
|
buildPermissionPrompt,
|
|
178
181
|
resolveAskIdleTimeoutMs,
|
|
@@ -407,9 +410,11 @@ export async function runReplDirectToolWithLedger({
|
|
|
407
410
|
let _hookDb = null;
|
|
408
411
|
let _compressor = null;
|
|
409
412
|
let _approvalGate = null;
|
|
410
|
-
//
|
|
411
|
-
// confirmer for `ask` matches.
|
|
413
|
+
// Static + CLI-owned scoped permission rules (deny > ask > allow) and an
|
|
414
|
+
// interactive confirmer for `ask` matches. Scoped rules are refreshed at each
|
|
415
|
+
// tool boundary so TTL expiry and external revocation affect a live session.
|
|
412
416
|
let _permissionRules = null;
|
|
417
|
+
let _permissionRulesProvider = null;
|
|
413
418
|
let _permissionConfirm = null;
|
|
414
419
|
let _managedPermissionRulesOnly = false;
|
|
415
420
|
// .claude/settings.json `hooks` block (decision-capable PreToolUse/PostToolUse).
|
|
@@ -546,6 +551,7 @@ async function executeTool(name, args) {
|
|
|
546
551
|
cwd: process.cwd(),
|
|
547
552
|
approvalGate: _approvalGate,
|
|
548
553
|
permissionRules: _permissionRules,
|
|
554
|
+
permissionRulesProvider: _permissionRulesProvider,
|
|
549
555
|
permissionConfirm: _permissionConfirm,
|
|
550
556
|
settingsHooks: _settingsHooks,
|
|
551
557
|
classifyAllShell: _classifyAllShell,
|
|
@@ -770,6 +776,12 @@ export async function agentLoop(messages, options) {
|
|
|
770
776
|
key: sideEffect.key,
|
|
771
777
|
meta: {
|
|
772
778
|
tool: event.tool,
|
|
779
|
+
toolUseId: event.tool_use_id || null,
|
|
780
|
+
turnId: event.turn_id || null,
|
|
781
|
+
resources: collectToolResourceIdentifiers(
|
|
782
|
+
event.tool,
|
|
783
|
+
event.args,
|
|
784
|
+
),
|
|
773
785
|
idempotencyKey: operationIdempotencyKey({
|
|
774
786
|
tool: event.tool,
|
|
775
787
|
args: event.args,
|
|
@@ -3163,6 +3175,11 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
3163
3175
|
const { getApprovalGate } =
|
|
3164
3176
|
await import("../lib/session-core-singletons.js");
|
|
3165
3177
|
_approvalGate = await getApprovalGate();
|
|
3178
|
+
_approvalGate =
|
|
3179
|
+
_approvalGate?.createSessionScope?.(
|
|
3180
|
+
sessionId || `repl-scope:${randomUUID()}`,
|
|
3181
|
+
) || _approvalGate;
|
|
3182
|
+
_approvalGate?.setAuthorizationConsumer?.(null);
|
|
3166
3183
|
// autoMode.decisions: wrap the gate with the configurable classifier
|
|
3167
3184
|
// BEFORE setConfirmer so the wrapper captures the interactive confirmer.
|
|
3168
3185
|
// Inactive (delegating) unless the session mode is "auto"; not installed
|
|
@@ -3240,29 +3257,53 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
3240
3257
|
},
|
|
3241
3258
|
};
|
|
3242
3259
|
};
|
|
3243
|
-
_approvalGate.setConfirmer(
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3260
|
+
_approvalGate.setConfirmer(
|
|
3261
|
+
async ({
|
|
3262
|
+
tool,
|
|
3263
|
+
args,
|
|
3264
|
+
riskLevel,
|
|
3265
|
+
action,
|
|
3266
|
+
cwd,
|
|
3267
|
+
workspace,
|
|
3268
|
+
sessionId,
|
|
3269
|
+
session,
|
|
3270
|
+
targetEnv,
|
|
3271
|
+
policyVersion,
|
|
3272
|
+
}) => {
|
|
3273
|
+
if (_dontAskActive()) {
|
|
3274
|
+
process.stdout.write(
|
|
3275
|
+
chalk.yellow(
|
|
3276
|
+
`\n ✕ denied without asking (dontAsk mode): ${riskLevel || "medium"}-risk ${tool || "run_shell"}${args?.command ? " — " + args.command : ""}\n`,
|
|
3277
|
+
),
|
|
3278
|
+
);
|
|
3279
|
+
return false;
|
|
3280
|
+
}
|
|
3281
|
+
await _fireNotification(
|
|
3282
|
+
`Permission needed: ${riskLevel || "medium"}-risk ${tool || "run_shell"}${args?.command ? " — " + args.command : ""}`,
|
|
3283
|
+
"info",
|
|
3284
|
+
_sessionHandle,
|
|
3249
3285
|
);
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3286
|
+
const local = askGateApprovalLocally({ tool, args, riskLevel });
|
|
3287
|
+
if (!_remoteApproval?.bridge) return local.promise;
|
|
3288
|
+
return raceLocalAndRemote({
|
|
3289
|
+
bridge: _remoteApproval.bridge,
|
|
3290
|
+
ask: describeAskContext({
|
|
3291
|
+
tool,
|
|
3292
|
+
args,
|
|
3293
|
+
riskLevel,
|
|
3294
|
+
action,
|
|
3295
|
+
cwd,
|
|
3296
|
+
workspace,
|
|
3297
|
+
sessionId,
|
|
3298
|
+
session,
|
|
3299
|
+
targetEnv,
|
|
3300
|
+
policyVersion,
|
|
3301
|
+
}),
|
|
3302
|
+
local,
|
|
3303
|
+
writeOut: (text) => process.stdout.write(chalk.cyan(text)),
|
|
3304
|
+
});
|
|
3305
|
+
},
|
|
3306
|
+
);
|
|
3266
3307
|
}
|
|
3267
3308
|
} catch (_err) {
|
|
3268
3309
|
_approvalGate = null;
|
|
@@ -3271,9 +3312,14 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
3271
3312
|
// Load .claude/settings.json permission rules + wire an interactive confirmer
|
|
3272
3313
|
// so `ask` rules prompt (rather than fall closed like headless does).
|
|
3273
3314
|
try {
|
|
3274
|
-
const {
|
|
3275
|
-
|
|
3276
|
-
|
|
3315
|
+
const { readBooleanSetting } = await import("../lib/settings-loader.cjs");
|
|
3316
|
+
const { createPermissionRulesProvider, loadPermissionAuthority } =
|
|
3317
|
+
await import("../lib/permission-authority.js");
|
|
3318
|
+
const permissionAuthorityOptions = { cwd: process.cwd() };
|
|
3319
|
+
const loaded = loadPermissionAuthority(permissionAuthorityOptions);
|
|
3320
|
+
_permissionRulesProvider = createPermissionRulesProvider(
|
|
3321
|
+
permissionAuthorityOptions,
|
|
3322
|
+
);
|
|
3277
3323
|
_managedPermissionRulesOnly =
|
|
3278
3324
|
loaded.managed?.allowManagedPermissionRulesOnly === true;
|
|
3279
3325
|
// Claude-Code 2.1.186 respondToBashCommands (default OFF / opt-in when unset).
|
|
@@ -3347,17 +3393,23 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
3347
3393
|
_sessionHandle,
|
|
3348
3394
|
);
|
|
3349
3395
|
const local = askPermissionLocally({ tool, args, rule, reason });
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
writeOut: (text) => process.stdout.write(chalk.cyan(text)),
|
|
3356
|
-
});
|
|
3396
|
+
// This confirmer is consumed as a legacy boolean by settings/hook
|
|
3397
|
+
// admission. A remote lease must never be flattened there and then skip
|
|
3398
|
+
// the ApprovalGate consume, so this path remains local-only until it can
|
|
3399
|
+
// carry the opaque authorization through its own dispatch boundary.
|
|
3400
|
+
return local.promise;
|
|
3357
3401
|
};
|
|
3358
3402
|
} catch (_err) {
|
|
3359
|
-
if (
|
|
3403
|
+
if (
|
|
3404
|
+
_err?.code === "CC_MANAGED_SETTINGS_INVALID" ||
|
|
3405
|
+
_err?.code === "CONFIG_HOME_UNSAFE" ||
|
|
3406
|
+
String(_err?.code || "").startsWith("CC_SCOPED_PERMISSION_") ||
|
|
3407
|
+
String(_err?.code || "").startsWith("DURABLE_SECURITY_STORE_")
|
|
3408
|
+
) {
|
|
3409
|
+
throw _err;
|
|
3410
|
+
}
|
|
3360
3411
|
_permissionRules = null;
|
|
3412
|
+
_permissionRulesProvider = null;
|
|
3361
3413
|
_permissionConfirm = null;
|
|
3362
3414
|
_managedPermissionRulesOnly = false;
|
|
3363
3415
|
}
|
|
@@ -3475,6 +3527,7 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
3475
3527
|
title: `Agent ${new Date().toISOString().slice(0, 10)}`,
|
|
3476
3528
|
provider,
|
|
3477
3529
|
model,
|
|
3530
|
+
executionLocation: captureAmbientExecutionLocation({ provider, model }),
|
|
3478
3531
|
};
|
|
3479
3532
|
if (useJsonl) {
|
|
3480
3533
|
sessionId = startReplJsonlSession(
|
|
@@ -3542,6 +3595,18 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
3542
3595
|
// purely how the confirmers consume it — they RACE the terminal prompt
|
|
3543
3596
|
// against the paired device instead of gating on the remote alone.
|
|
3544
3597
|
const _startRemoteApproval = async () => {
|
|
3598
|
+
if (
|
|
3599
|
+
!_approvalGate ||
|
|
3600
|
+
typeof _approvalGate.setConfirmer !== "function" ||
|
|
3601
|
+
typeof _approvalGate.setAuthorizationConsumer !== "function" ||
|
|
3602
|
+
typeof _approvalGate.consumeAuthorization !== "function"
|
|
3603
|
+
) {
|
|
3604
|
+
const error = new Error(
|
|
3605
|
+
"installed session-core cannot bind and consume durable remote approval",
|
|
3606
|
+
);
|
|
3607
|
+
error.code = "CC_REMOTE_APPROVAL_GATE_UNAVAILABLE";
|
|
3608
|
+
throw error;
|
|
3609
|
+
}
|
|
3545
3610
|
const { startHeadlessRemoteApproval } =
|
|
3546
3611
|
await import("../lib/remote-approval-bridge.js");
|
|
3547
3612
|
const started = await startHeadlessRemoteApproval({
|
|
@@ -3554,6 +3619,7 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
3554
3619
|
pairing: started.pairing,
|
|
3555
3620
|
close: started.close,
|
|
3556
3621
|
};
|
|
3622
|
+
_approvalGate.setAuthorizationConsumer(started.consumeAuthorization);
|
|
3557
3623
|
logger.log(
|
|
3558
3624
|
chalk.cyan(
|
|
3559
3625
|
" remote-control: permission prompts can be answered from a paired device (first answer — terminal or device — wins)",
|
|
@@ -3571,6 +3637,7 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
3571
3637
|
const _stopRemoteApproval = async () => {
|
|
3572
3638
|
const active = _remoteApproval;
|
|
3573
3639
|
_remoteApproval = null; // confirmers fall back to local-only immediately
|
|
3640
|
+
_approvalGate?.setAuthorizationConsumer?.(null);
|
|
3574
3641
|
if (active) await active.close().catch(() => undefined);
|
|
3575
3642
|
};
|
|
3576
3643
|
|
|
@@ -4642,6 +4709,12 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
4642
4709
|
|
|
4643
4710
|
// Prompt-side interaction modules share the production readline surface.
|
|
4644
4711
|
// A per-REPL registry avoids singleton handlers retaining an old session.
|
|
4712
|
+
const _clipboardBinding = Object.prototype.hasOwnProperty.call(
|
|
4713
|
+
options,
|
|
4714
|
+
"clipboardBinding",
|
|
4715
|
+
)
|
|
4716
|
+
? options.clipboardBinding
|
|
4717
|
+
: createSystemClipboardImageBinding();
|
|
4645
4718
|
const _promptInteractionSurface = createPromptInteractionSurface({
|
|
4646
4719
|
readline: rl,
|
|
4647
4720
|
config: _promptInteractionConfig,
|
|
@@ -4649,7 +4722,7 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
4649
4722
|
getSessionId: () => sessionId,
|
|
4650
4723
|
getSuggestionContext: () => ({ messages: messages.slice() }),
|
|
4651
4724
|
persistSuggestionEnabled: _persistPromptSuggestionsEnabled,
|
|
4652
|
-
clipboardBinding:
|
|
4725
|
+
clipboardBinding: _clipboardBinding,
|
|
4653
4726
|
generateSuggestions: resolveReplPromptSuggestionGenerator(
|
|
4654
4727
|
useJsonl,
|
|
4655
4728
|
options.generatePromptSuggestions,
|
|
@@ -5936,6 +6009,7 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
5936
6009
|
if (snap) _clearedConversation = snap;
|
|
5937
6010
|
messages.length = 1; // Keep system prompt
|
|
5938
6011
|
_checkpointMarks.length = 0; // checkpoint marks no longer map to anything
|
|
6012
|
+
_promptInteractions.clearClipboardImageChips();
|
|
5939
6013
|
logger.info(
|
|
5940
6014
|
snap
|
|
5941
6015
|
? "Conversation cleared — run /rewind clear to restore it"
|
|
@@ -9056,6 +9130,7 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
9056
9130
|
prepareCall,
|
|
9057
9131
|
approvalGate: _approvalGate,
|
|
9058
9132
|
permissionRules: _permissionRules,
|
|
9133
|
+
permissionRulesProvider: _permissionRulesProvider,
|
|
9059
9134
|
permissionConfirm: _permissionConfirm,
|
|
9060
9135
|
settingsHooks: _settingsHooks,
|
|
9061
9136
|
hookSupervisor: _asyncHookSupervisor,
|
package/src/repl/chat-repl.js
CHANGED
|
@@ -55,6 +55,7 @@ import {
|
|
|
55
55
|
import { installPipeSafety } from "../runtime/pipe-safety.js";
|
|
56
56
|
import { installOutputBackpressure } from "../runtime/output-backpressure.js";
|
|
57
57
|
import { assertChatSessionUsageAdmission } from "../lib/chat-session-admission.js";
|
|
58
|
+
import { captureAmbientExecutionLocation } from "../lib/execution-location-runtime.js";
|
|
58
59
|
|
|
59
60
|
const SLASH_COMMANDS = {
|
|
60
61
|
"/exit": "Exit the chat",
|
|
@@ -114,6 +115,7 @@ export async function startChatRepl(options = {}) {
|
|
|
114
115
|
title: "chat-repl",
|
|
115
116
|
provider,
|
|
116
117
|
model,
|
|
118
|
+
executionLocation: captureAmbientExecutionLocation({ provider, model }),
|
|
117
119
|
});
|
|
118
120
|
} catch {
|
|
119
121
|
sessionId = null;
|