chainlesschain 0.165.5 → 0.165.8
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 +2 -1
- package/src/assets/web-panel/assets/{AIOps-CEeYTeDB.js → AIOps-B3gWmXjo.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BeRUQ3V2.js → ActionButton-G9pdT-0e.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DrV718XF.js → Analytics-Ca30J7m2.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-Cd2Frt7Q.js → AppLayout-BtVTm8PU.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-CUJMlORU.js → Artifacts-BhViNa6u.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CXJcfT6p.js → Audit-DhKq-FnY.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DOv6Z7H9.js → BackgroundAgents-BL0SVbnE.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BwdDyBI0.js → Backup-BWkblnFi.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-BmLn4kYH.js → BaseInput-ClaRNrF8.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-COg8pAW2.js → Chat-sZE2Z77o.js} +4 -4
- package/src/assets/web-panel/assets/ChatBubbleRenderer-BAfKOnRe.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-BCP4uoU8.js → Checkbox-Cvhay5WM.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-pRt6Y9JI.js → Codegen-BpejL-4N.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DLaprKhS.js → Col-g2Ki6g_1.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DyATsz5f.js → Community-D2xKbNo9.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BXAaupZK.js → Compact-DbL1Pds3.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-DpcJBELr.js → Compliance-DGtZCV4c.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DG4EFWyd.js → Cowork-4kQpoNsI.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-F6Oy5n2P.js → Cron-BxTYXXAN.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BOdgtalX.js → Crosschain-k0J0LT2N.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DT1dSkjH.js → DID-BaqhoPgN.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-NBUIqWzC.js → Dashboard-T4RVPIM1.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CSpHeMYB.js → Dropdown-DszOToWq.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-CEG0xISr.js → EmailListRenderer-C9KJU7HF.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-BTZ0BZna.js → FamilyGuardDashboard-Cmr0JnsA.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BuuCTn2V.js → Federation-BI-_2xZX.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-KAVceevk.js → FormItemContext-DsnDEPsl.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DnHpcQvW.js → GenericCardRenderer-BLncAKKK.js} +1 -1
- package/src/assets/web-panel/assets/{Git-C_B_0HwB.js → Git-BPQhGXDn.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DPSZuzuu.js → Governance-CyElbUQW.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BV-06V7q.js → Inference-CcSntBQD.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-wpDuupn6.js → KnowledgeGraph-p6e7HZ2r.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-Bseca1_I.js → Logs-CNEtr-wz.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-Bj9xI0YH.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-d3kM4DDL.js → Marketplace-Dd2notAJ.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DQ_xZ23i.js → McpTools-BBsN2CSW.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-CRIeYO4L.js → Memory-Dg2uTvwx.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BsllIa9l.js → MobileBridge-r1YMRiJV.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-BUuQy30X.js → MobileProjects-C-89kSm4.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-BOFDIzrC.js → Mtc-CrPZcVgf.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-BQg-vyvG.js → MtcAudit-sxi7hqJb.js} +5 -5
- package/src/assets/web-panel/assets/{Multisig-Bo1jrPdN.js → Multisig-CAgOMfF1.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-Bmod8alw.js → NLProgramming-DafaPts3.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CGGFL8w-.js → Notes-CJM-xUW_.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-BsZvCJxC.js → NotificationSettings-L0ZjfAh_.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-C1-Quo_h.js → OrderTableRenderer-BB1CvCK0.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BjOeDYOi.js → Organization-DeLtgAD8.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-DwVV3l5A.js → Overflow-CKC2b10z.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-Cu3DQT9W.js → P2P-eyf2rzY1.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Cg0gR7dH.js → PdhVaultBrowser-5upNIOW8.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-CsAXxRN5.js → Permissions-B8p3W6JK.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-C-nNmnYp.js → PersonalDataHub-BnRMxTq3.js} +5 -5
- package/src/assets/web-panel/assets/{Pipeline-BOnW7nNc.js → Pipeline-DjCNI1li.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-ClLSyGKt.js → Privacy-u6gXLbWT.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-DuLvjjq7.js → ProjectInit-BZAw4tkM.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-DQYYbDD9.js → ProjectSettings-B1Tr72q7.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-Drw8MBGK.js → Projects-DO7HFuBQ.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-ckqHQe6K.js → Providers-BjCztyhj.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-DW5BXk-G.js → QrScannerModal-ZWyCUbR1.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DDLnhNTp.js → QuickAsk-DhDjeW4G.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-PJQ2C91U.js → Recommend-R_CN2MuU.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-s6wmda34.js → RemoteSession-uxFcujeu.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-DC2sb-I3.js → Reputation-DX8D7rks.js} +1 -1
- package/src/assets/web-panel/assets/{Row-hPGk1eGj.js → Row-BYahQILD.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-RIvfZql0.js → RssFeed-CUSQ2tm-.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DFg1G1eR.js → Search-CnN_S8Cs.js} +1 -1
- package/src/assets/web-panel/assets/{Security-D6H5p8Dp.js → Security-DcZlh-O4.js} +4 -4
- package/src/assets/web-panel/assets/{Services-nxYiFV_w.js → Services-ZhBOjzIX.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-BmgFNAdB.js → Skeleton-D5Qnq_lI.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CsaaD2av.js → Skills-BC9cZ3Be.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-yM5y9yvK.js → Sla-DauJ3E8_.js} +1 -1
- package/src/assets/web-panel/assets/SpeechSettings-DbNeZ_fh.js +1 -0
- package/src/assets/web-panel/assets/{SyncSettings-CFVhEyyr.js → SyncSettings-DUvJbSct.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-DdO02Inn.js → Tasks-BXa-5noQ.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-Eo2d8Llu.js → Templates-JxaiUt_3.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-ChESOXgy.js → Tenant-BW4ERQN8.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-BJ7oDxTI.js → Terminal-DltUbdtv.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-hWX0fUvz.js → TimelineRenderer-CMoZz0Tc.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DVBZQnd-.js → Tokens-D_VEV60K.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-D89cQfVq.js → Trigger-CCXTCs0R.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-BIVSb4-V.js → Trust-lkGRIPcG.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B58gWopl.js → UkeySign-BfGeQ9HX.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DhHI7bmG.js → VideoEditing-BEC7pYvc.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-C4FheWS_.js → Wallet-BZdG24o0.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DnPRq-Bx.js → WebAuthn-yoEddedp.js} +3 -3
- package/src/assets/web-panel/assets/{WorkflowEditor-BerRPjpJ.js → WorkflowEditor-BXZEprOW.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BzZ52iKr.js → chat-gg0bzZal.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BI_E4BAn.js → colors-DjRVRuin.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-d50mr3yk.js → compact-item-su-dieAc.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-C6FsQ1IH.js → createContext-Ci3S8oKF.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-CxbFX9uH.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DLZEMgLP.js → hasIn-D8F10heH.js} +1 -1
- package/src/assets/web-panel/assets/{index-D-aBumtY.js → index-11wtYQiF.js} +1 -1
- package/src/assets/web-panel/assets/{index-CjuKZBqJ.js → index-1IgxgALJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-9H_M2jju.js → index-1agckWSq.js} +1 -1
- package/src/assets/web-panel/assets/{index-DE0V6cp-.js → index-5JqhujnR.js} +1 -1
- package/src/assets/web-panel/assets/{index-Y2-q7QLm.js → index-6Tniqk1s.js} +1 -1
- package/src/assets/web-panel/assets/{index-DoFtCVZ7.js → index-8Z-8BIlN.js} +1 -1
- package/src/assets/web-panel/assets/{index-KNGgO4Wm.js → index-BCI5v0yB.js} +1 -1
- package/src/assets/web-panel/assets/{index-DY4j5zkF.js → index-BDJntYmJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BZjjdQ62.js → index-BGzixOGZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BTpIOTfR.js → index-BMMOVoLD.js} +1 -1
- package/src/assets/web-panel/assets/{index-BB9SqVSt.js → index-BTFpdBtt.js} +1 -1
- package/src/assets/web-panel/assets/{index-AHr7ryWf.js → index-Ba_HyPnE.js} +1 -1
- package/src/assets/web-panel/assets/{index-Pvf30m8Q.js → index-BbF1IHof.js} +1 -1
- package/src/assets/web-panel/assets/{index-CRN5TRTQ.js → index-BgT9su_e.js} +1 -1
- package/src/assets/web-panel/assets/{index-CUaEHfQ0.js → index-BzPB6kGZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CdKt9fOd.js → index-C6ygzplr.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dec0Kf_Z.js → index-CC3ZDjzY.js} +1 -1
- package/src/assets/web-panel/assets/{index-IPkwSAW_.js → index-CEmXRhAE.js} +1 -1
- package/src/assets/web-panel/assets/index-CJGOlduY.js +1 -0
- package/src/assets/web-panel/assets/{index-C3k8kevG.js → index-CMPqd5Cv.js} +1 -1
- package/src/assets/web-panel/assets/{index-A5CDWP7y.js → index-COWd8uGx.js} +1 -1
- package/src/assets/web-panel/assets/{index-CO8DAF7U.js → index-CPIYSp4H.js} +1 -1
- package/src/assets/web-panel/assets/{index-CVzuawCX.js → index-CR0h6seT.js} +1 -1
- package/src/assets/web-panel/assets/{index-Co7s9LsB.js → index-CUmDhC4j.js} +1 -1
- package/src/assets/web-panel/assets/index-CkBCN5yH.js +1 -0
- package/src/assets/web-panel/assets/{index-CLoTQr0W.js → index-CusgZPtc.js} +1 -1
- package/src/assets/web-panel/assets/{index-B81mo1Et.js → index-DBAETXft.js} +1 -1
- package/src/assets/web-panel/assets/{index-BcSUl9fA.js → index-DIJ2qFOC.js} +1 -1
- package/src/assets/web-panel/assets/{index-Q5Tn735s.js → index-Dbq4NMET.js} +1 -1
- package/src/assets/web-panel/assets/{index-GXE0D8Nx.js → index-DkMEF5VT.js} +1 -1
- package/src/assets/web-panel/assets/{index-TWG-_D1M.js → index-DkfQR3hM.js} +1 -1
- package/src/assets/web-panel/assets/{index-BAE3hwev.js → index-DnLucOn9.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgkoH3_g.js → index-DugB_aKa.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRGx3w6T.js → index-DyLUarhZ.js} +3 -3
- package/src/assets/web-panel/assets/{index-BeM4hfht.js → index-T6_6ygJZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DsscwxPE.js → index-Tu8eWqh-.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bmr_vxXD.js → index-W7XUgdVL.js} +1 -1
- package/src/assets/web-panel/assets/{index-BoNZlzhQ.js → index-dHZinfko.js} +1 -1
- package/src/assets/web-panel/assets/{index-DqkbHHg8.js → index-jyNgp5FI.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-D-4Hzgej.js → initDefaultProps-Cv4p8e4w.js} +1 -1
- package/src/assets/web-panel/assets/{motion-D4Wl4xU7.js → motion-B8EwmMOw.js} +1 -1
- package/src/assets/web-panel/assets/{move-Cd5eQvL0.js → move-B8R9F8TK.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-B4ilslCW.js → mtc-parser-DoFYz5Bp.js} +1 -1
- package/src/assets/web-panel/assets/{omit-Ckarx-tf.js → omit-CHWYLBjI.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-QJ0bpCmc.js → pickAttrs-CXuPDO77.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-CKHm-tq8.js → placementArrow-BaAtUUon.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-CV6a_w_Y.js → responsiveObserve-DCc4zcDD.js} +1 -1
- package/src/assets/web-panel/assets/{slide-mHpeQFgk.js → slide-B_lx89oZ.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DIaQNQWA.js → statusUtils-DE8DPmR0.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-PJpzavV8.js → styleChecker-1ktXOsL_.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-BH7zTw8S.js → useFlexGapSupport-xH89-wjh.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-BDNG3JDd.js → useFs-DscvfW5p.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-CY2VWdUg.js → usePersonalDataHub-RdMKQta7.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-D0kw9jhz.js → vnode-Z3wTni2T.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-B5g7TN7r.js → zoom-B0iChCsm.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +3 -3
- package/src/commands/agent.js +105 -62
- package/src/commands/background-session.js +100 -10
- package/src/commands/git.js +39 -0
- package/src/commands/mcp.js +5 -0
- package/src/commands/plugin.js +160 -29
- package/src/commands/remote-control.js +295 -110
- package/src/commands/session-group.js +131 -0
- package/src/commands/session-location.js +48 -0
- package/src/commands/session-message.js +171 -0
- package/src/commands/session.js +22 -0
- package/src/commands/sync-providers.js +4 -1
- package/src/commands/update.js +1 -0
- package/src/data/changelog.json +41 -2
- package/src/gateways/ws/ws-agent-handler.js +20 -12
- package/src/harness/jsonl-session-store.js +279 -37
- package/src/harness/mcp-client.js +832 -91
- package/src/harness/session-index.js +15 -4
- package/src/lib/agent-worktree.js +8 -1
- package/src/lib/auto-mode-safety-classifier.js +3 -17
- package/src/lib/background-agent-keeper-protocol.js +26 -6
- package/src/lib/background-agent-supervisor.js +17 -1
- package/src/lib/background-session-transport.js +153 -27
- package/src/lib/browser-evidence.js +1405 -0
- package/src/lib/chrome-connector.js +465 -79
- package/src/lib/claude-project-auto-memory.js +481 -0
- package/src/lib/claude-project-storage-layout.js +104 -0
- package/src/lib/cloud/cloud-client.js +40 -0
- package/src/lib/execution-location-local-supervisor.mjs +226 -0
- package/src/lib/execution-location-runner-lifecycle.js +991 -0
- package/src/lib/execution-location-target-preflight.js +333 -0
- package/src/lib/execution-location-target.js +783 -13
- package/src/lib/file-lines.js +6 -1
- package/src/lib/gateway-client-resilience.js +571 -0
- package/src/lib/gitlab-mr-worktree.js +176 -0
- package/src/lib/hooks-v2-producers.js +119 -15
- package/src/lib/hooks-v2-workspace-context.js +44 -1
- package/src/lib/host-resource-budget.js +295 -0
- package/src/lib/ide-context.js +15 -2
- package/src/lib/llm-config-defaults.js +43 -0
- package/src/lib/mcp-client.js +2 -0
- package/src/lib/mcp-headers-helper.js +47 -5
- package/src/lib/mcp-lifecycle-authority.js +887 -0
- package/src/lib/mcp-oauth.js +156 -26
- package/src/lib/mcp-tls.js +330 -0
- package/src/lib/output-styles.js +12 -0
- package/src/lib/paths.js +260 -32
- package/src/lib/permission-request.js +48 -0
- package/src/lib/plugin-runtime/bin.js +3 -1
- package/src/lib/plugin-runtime/hooks.js +3 -1
- package/src/lib/plugin-runtime/install.js +730 -71
- package/src/lib/plugin-runtime/lsp.js +4 -4
- package/src/lib/plugin-runtime/marketplace-archive-source.js +366 -0
- package/src/lib/plugin-runtime/marketplace-catalog.js +63 -6
- package/src/lib/plugin-runtime/marketplace-command-descriptor.js +343 -0
- package/src/lib/plugin-runtime/marketplace-command-source.js +580 -0
- package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1 -0
- package/src/lib/plugin-runtime/marketplace-source-adapter.js +188 -0
- package/src/lib/plugin-runtime/marketplace-source-cache.js +11 -1
- package/src/lib/plugin-runtime/mcp.js +3 -1
- package/src/lib/plugin-runtime/monitors.js +3 -1
- package/src/lib/plugin-runtime/remote-source.js +583 -58
- package/src/lib/plugin-runtime/settings.js +3 -1
- package/src/lib/plugin-runtime/trust.js +274 -13
- package/src/lib/plugin-security.js +393 -41
- package/src/lib/plugin-source-identity.js +850 -0
- package/src/lib/process-execution-broker/credential-agent.js +210 -41
- package/src/lib/process-execution-broker/index.js +15 -1
- package/src/lib/process-execution-broker/linux-cgroup-v2.js +391 -0
- package/src/lib/process-execution-broker/platform-sandbox.js +50 -28
- package/src/lib/project-mcp-trust.js +165 -10
- package/src/lib/remote-approval-bridge.js +136 -46
- package/src/lib/remote-control.js +217 -31
- package/src/lib/resume-session.js +9 -6
- package/src/lib/session-core-singletons.js +26 -11
- package/src/lib/session-host-lease.js +52 -16
- package/src/lib/session-lifecycle-scope.js +153 -0
- package/src/lib/session-message-fabric.js +1252 -0
- package/src/lib/session-projection.js +286 -3
- package/src/lib/session-runtime-retention.js +155 -0
- package/src/lib/session-store-guard.js +3 -1
- package/src/lib/session-workbench-store.js +466 -0
- package/src/lib/settings-loader.cjs +29 -0
- package/src/lib/spellcheck.js +211 -0
- package/src/lib/sub-agent-context.js +9 -9
- package/src/lib/sync-cli-db.js +485 -129
- package/src/lib/sync-credentials.js +31 -20
- package/src/lib/web-fetch.js +112 -40
- package/src/lib/web-search.js +127 -61
- package/src/lib/workspace-trust.js +793 -0
- package/src/repl/agent-repl.js +175 -19
- package/src/repl/permission-prompt.js +29 -8
- package/src/repl/repl-keybindings.js +55 -0
- package/src/runtime/agent-core.js +362 -20
- package/src/runtime/bootstrap.js +37 -13
- package/src/runtime/coding-agent-contract-shared.cjs +11 -4
- package/src/runtime/headless-runner.js +281 -102
- package/src/runtime/headless-stream.js +199 -30
- package/src/runtime/mcp-config.js +298 -6
- package/src/runtime/policies/agent-policy.js +10 -0
- package/src/runtime/status-diagnostics-lite.js +9 -1
- package/src/assets/web-panel/assets/ChatBubbleRenderer-4gGkdGgA.js +0 -1
- package/src/assets/web-panel/assets/MarkdownRenderer-B4RLp2zs.js +0 -1
- package/src/assets/web-panel/assets/SpeechSettings-DPy1XMYh.js +0 -1
- package/src/assets/web-panel/assets/devWarning-CagEcIex.js +0 -1
- package/src/assets/web-panel/assets/index-pzT9PpOU.js +0 -1
- package/src/assets/web-panel/assets/index-z1kFadaX.js +0 -1
|
@@ -22,8 +22,20 @@ import {
|
|
|
22
22
|
mutateSecurityStore,
|
|
23
23
|
readSecurityStore,
|
|
24
24
|
} from "./durable-security-store.js";
|
|
25
|
+
import {
|
|
26
|
+
checkRecordedWorkspaceTrust,
|
|
27
|
+
evaluateWorkspaceTrustDecision,
|
|
28
|
+
projectWorkspaceTrustAudit,
|
|
29
|
+
recordWorkspaceTrustConsent,
|
|
30
|
+
resolveCanonicalWorkspaceRepoIdentity,
|
|
31
|
+
workspaceTrustPathSubject,
|
|
32
|
+
} from "./workspace-trust.js";
|
|
25
33
|
|
|
26
|
-
export const _deps = {
|
|
34
|
+
export const _deps = {
|
|
35
|
+
withFileLock,
|
|
36
|
+
// Test-only seam. Production uses workspace-trust.js's one shared ledger.
|
|
37
|
+
workspaceTrustStorePath: () => null,
|
|
38
|
+
};
|
|
27
39
|
const workspaceAuthorities = new WeakMap();
|
|
28
40
|
|
|
29
41
|
function storePath(opts = {}) {
|
|
@@ -38,6 +50,62 @@ export function projectMcpFingerprint(content) {
|
|
|
38
50
|
return createHash("sha256").update(String(content), "utf-8").digest("hex");
|
|
39
51
|
}
|
|
40
52
|
|
|
53
|
+
const PROJECT_MCP_WORKSPACE_TRUST_SOURCE = "project-mcp";
|
|
54
|
+
|
|
55
|
+
function workspaceTrustStoreOptions(opts = {}) {
|
|
56
|
+
const store =
|
|
57
|
+
opts.workspaceTrustStorePath ||
|
|
58
|
+
process.env.CC_WORKSPACE_TRUST_STORE ||
|
|
59
|
+
_deps.workspaceTrustStorePath() ||
|
|
60
|
+
// Custom source-store callers (notably isolated tests) get an adjacent
|
|
61
|
+
// shared ledger. Normal CLI calls omit storePath and therefore use the
|
|
62
|
+
// single workspace-trust.js default shared by all entry points.
|
|
63
|
+
(opts.storePath
|
|
64
|
+
? path.join(path.dirname(opts.storePath), "workspace-trust-v1.json")
|
|
65
|
+
: null);
|
|
66
|
+
return store ? { storePath: store } : {};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function projectMcpWorkspaceTrustContext(file, content, opts = {}) {
|
|
70
|
+
const identity = resolveCanonicalWorkspaceRepoIdentity(
|
|
71
|
+
opts.workspaceRoot || path.dirname(file),
|
|
72
|
+
);
|
|
73
|
+
const subject = workspaceTrustPathSubject(identity, file);
|
|
74
|
+
const fingerprint = projectMcpFingerprint(content);
|
|
75
|
+
return { identity, subject, fingerprint };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function projectMcpWorkspaceRecordKey(context) {
|
|
79
|
+
const subjectDigest = createHash("sha256")
|
|
80
|
+
.update(context.subject, "utf8")
|
|
81
|
+
.digest("hex");
|
|
82
|
+
return `workspace-v1:${context.identity.workspaceId}:${subjectDigest}`;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function projectMcpDecision(status, context) {
|
|
86
|
+
const decision = evaluateWorkspaceTrustDecision({
|
|
87
|
+
identity: context.identity,
|
|
88
|
+
evidence: [
|
|
89
|
+
{
|
|
90
|
+
source: PROJECT_MCP_WORKSPACE_TRUST_SOURCE,
|
|
91
|
+
consent: status === "trusted" ? "explicit" : "missing",
|
|
92
|
+
fingerprint: context.fingerprint,
|
|
93
|
+
decision:
|
|
94
|
+
status === "trusted"
|
|
95
|
+
? "allow"
|
|
96
|
+
: status === "first-use"
|
|
97
|
+
? "ask"
|
|
98
|
+
: "deny",
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
});
|
|
102
|
+
return {
|
|
103
|
+
status,
|
|
104
|
+
fingerprint: context.fingerprint,
|
|
105
|
+
workspaceTrust: projectWorkspaceTrustAudit(decision),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
41
109
|
/**
|
|
42
110
|
* Issue an in-process authority only after the caller has verified the exact
|
|
43
111
|
* project file fingerprint. Plain config fields cannot forge this token.
|
|
@@ -50,7 +118,23 @@ export function issueProjectMcpWorkspaceAuthority({
|
|
|
50
118
|
config = {},
|
|
51
119
|
}) {
|
|
52
120
|
const canonicalFile = fs.realpathSync.native(path.resolve(file));
|
|
53
|
-
const
|
|
121
|
+
const workspaceIdentity =
|
|
122
|
+
resolveCanonicalWorkspaceRepoIdentity(workspaceRoot);
|
|
123
|
+
const canonicalRoot = workspaceIdentity.canonicalWorkspaceRoot;
|
|
124
|
+
const trustDecision = evaluateWorkspaceTrustDecision({
|
|
125
|
+
identity: workspaceIdentity,
|
|
126
|
+
evidence: [
|
|
127
|
+
{
|
|
128
|
+
source: PROJECT_MCP_WORKSPACE_TRUST_SOURCE,
|
|
129
|
+
consent: "host-bound",
|
|
130
|
+
fingerprint: projectMcpFingerprint(content),
|
|
131
|
+
decision: "allow",
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
});
|
|
135
|
+
if (trustDecision.decision !== "allow") {
|
|
136
|
+
throw new Error("project MCP workspace identity is unavailable");
|
|
137
|
+
}
|
|
54
138
|
const token = Object.freeze({});
|
|
55
139
|
workspaceAuthorities.set(
|
|
56
140
|
token,
|
|
@@ -58,6 +142,9 @@ export function issueProjectMcpWorkspaceAuthority({
|
|
|
58
142
|
file: canonicalFile,
|
|
59
143
|
fingerprint: projectMcpFingerprint(content),
|
|
60
144
|
workspaceRoot: canonicalRoot,
|
|
145
|
+
workspaceId: workspaceIdentity.workspaceId,
|
|
146
|
+
repositoryId: workspaceIdentity.repositoryId,
|
|
147
|
+
workspaceTrust: projectWorkspaceTrustAudit(trustDecision),
|
|
61
148
|
serverName: String(serverName || ""),
|
|
62
149
|
url: typeof config.url === "string" ? config.url : "",
|
|
63
150
|
transport: typeof config.transport === "string" ? config.transport : "",
|
|
@@ -100,6 +187,19 @@ export function resolveProjectMcpWorkspaceAuthority(token, expected = {}) {
|
|
|
100
187
|
) {
|
|
101
188
|
return null;
|
|
102
189
|
}
|
|
190
|
+
try {
|
|
191
|
+
const currentIdentity = resolveCanonicalWorkspaceRepoIdentity(
|
|
192
|
+
record.workspaceRoot,
|
|
193
|
+
);
|
|
194
|
+
if (
|
|
195
|
+
currentIdentity.workspaceId !== record.workspaceId ||
|
|
196
|
+
currentIdentity.repositoryId !== record.repositoryId
|
|
197
|
+
) {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
} catch {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
103
203
|
return record.workspaceRoot;
|
|
104
204
|
}
|
|
105
205
|
|
|
@@ -112,29 +212,84 @@ function readStore(opts) {
|
|
|
112
212
|
* @returns {{status:"first-use"|"trusted"|"changed", fingerprint:string}}
|
|
113
213
|
*/
|
|
114
214
|
export function checkProjectMcpTrust(file, content, opts = {}) {
|
|
115
|
-
const
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
215
|
+
const context = projectMcpWorkspaceTrustContext(file, content, opts);
|
|
216
|
+
const store = readStore(opts);
|
|
217
|
+
const record = store[projectMcpWorkspaceRecordKey(context)];
|
|
218
|
+
const legacyRecord = store[path.resolve(file)];
|
|
219
|
+
if (!record || typeof record !== "object" || Array.isArray(record)) {
|
|
220
|
+
// A pre-v1 path-keyed grant cannot be shown to bind the current canonical
|
|
221
|
+
// workspace identity. Treat it as changed rather than silently widening
|
|
222
|
+
// it; the existing explicit re-trust path records the v1 intersection.
|
|
223
|
+
const shared = checkRecordedWorkspaceTrust({
|
|
224
|
+
identity: context.identity,
|
|
225
|
+
source: PROJECT_MCP_WORKSPACE_TRUST_SOURCE,
|
|
226
|
+
subject: context.subject,
|
|
227
|
+
evidenceFingerprint: context.fingerprint,
|
|
228
|
+
...workspaceTrustStoreOptions(opts),
|
|
229
|
+
});
|
|
230
|
+
return {
|
|
231
|
+
status:
|
|
232
|
+
legacyRecord?.fingerprint || shared.status === "changed"
|
|
233
|
+
? "changed"
|
|
234
|
+
: "first-use",
|
|
235
|
+
fingerprint: context.fingerprint,
|
|
236
|
+
workspaceTrust: shared.audit,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
const binding = record.workspaceTrust;
|
|
240
|
+
if (
|
|
241
|
+
record.fingerprint !== context.fingerprint ||
|
|
242
|
+
!binding ||
|
|
243
|
+
binding.workspaceId !== context.identity.workspaceId ||
|
|
244
|
+
binding.repositoryId !== context.identity.repositoryId ||
|
|
245
|
+
binding.subject !== context.subject
|
|
246
|
+
) {
|
|
247
|
+
return projectMcpDecision("changed", context);
|
|
119
248
|
}
|
|
249
|
+
const shared = checkRecordedWorkspaceTrust({
|
|
250
|
+
identity: context.identity,
|
|
251
|
+
source: PROJECT_MCP_WORKSPACE_TRUST_SOURCE,
|
|
252
|
+
subject: context.subject,
|
|
253
|
+
evidenceFingerprint: context.fingerprint,
|
|
254
|
+
...workspaceTrustStoreOptions(opts),
|
|
255
|
+
});
|
|
120
256
|
return {
|
|
121
|
-
status:
|
|
122
|
-
fingerprint,
|
|
257
|
+
status: shared.status === "trusted" ? "trusted" : "changed",
|
|
258
|
+
fingerprint: context.fingerprint,
|
|
259
|
+
workspaceTrust: shared.audit,
|
|
123
260
|
};
|
|
124
261
|
}
|
|
125
262
|
|
|
126
263
|
/** Record (or re-record) the trusted fingerprint for a file. */
|
|
127
264
|
export function recordProjectMcpTrust(file, content, opts = {}) {
|
|
128
265
|
const target = storePath(opts);
|
|
266
|
+
const context = projectMcpWorkspaceTrustContext(file, content, opts);
|
|
267
|
+
// Persist the shared record first. If the legacy/source-specific store
|
|
268
|
+
// fails afterwards, the checker still requires both records and therefore
|
|
269
|
+
// cannot accidentally authorize from the shared ledger alone.
|
|
270
|
+
recordWorkspaceTrustConsent({
|
|
271
|
+
identity: context.identity,
|
|
272
|
+
source: PROJECT_MCP_WORKSPACE_TRUST_SOURCE,
|
|
273
|
+
subject: context.subject,
|
|
274
|
+
evidenceFingerprint: context.fingerprint,
|
|
275
|
+
consent: "explicit",
|
|
276
|
+
...workspaceTrustStoreOptions(opts),
|
|
277
|
+
});
|
|
129
278
|
return mutateSecurityStore(
|
|
130
279
|
target,
|
|
131
280
|
"project MCP trust",
|
|
132
281
|
(store) => {
|
|
133
|
-
store[
|
|
134
|
-
fingerprint:
|
|
282
|
+
store[projectMcpWorkspaceRecordKey(context)] = {
|
|
283
|
+
fingerprint: context.fingerprint,
|
|
135
284
|
trustedAt: new Date(
|
|
136
285
|
typeof opts.now === "number" ? opts.now : Date.now(),
|
|
137
286
|
).toISOString(),
|
|
287
|
+
workspaceTrust: {
|
|
288
|
+
schemaVersion: context.identity.schemaVersion,
|
|
289
|
+
workspaceId: context.identity.workspaceId,
|
|
290
|
+
repositoryId: context.identity.repositoryId,
|
|
291
|
+
subject: context.subject,
|
|
292
|
+
},
|
|
138
293
|
};
|
|
139
294
|
return true;
|
|
140
295
|
},
|
|
@@ -43,11 +43,15 @@ import {
|
|
|
43
43
|
REMOTE_MEMBERSHIP_HOST_UNAVAILABLE_CODE,
|
|
44
44
|
} from "./remote-membership-host-store.js";
|
|
45
45
|
import {
|
|
46
|
+
assertDirectWsUrlAllowed,
|
|
46
47
|
buildDirectPairingUri,
|
|
48
|
+
isLoopbackBindHost,
|
|
47
49
|
pickLanAddress,
|
|
48
50
|
renderQrCode,
|
|
49
51
|
resolveRemoteControlOptions,
|
|
52
|
+
resolveRemoteControlWsUrl,
|
|
50
53
|
} from "./remote-control.js";
|
|
54
|
+
import { logger } from "./logger.js";
|
|
51
55
|
|
|
52
56
|
const DEFAULT_DECISION_TIMEOUT_MS = 5 * 60 * 1000;
|
|
53
57
|
const REMOTE_LEASE_AUTHORIZATION_KIND =
|
|
@@ -345,7 +349,8 @@ export class RemoteApprovalBridge {
|
|
|
345
349
|
|
|
346
350
|
/**
|
|
347
351
|
* Pairing descriptor for devices. Relay-configured servers return a ready
|
|
348
|
-
* E2EE URI; otherwise build
|
|
352
|
+
* E2EE URI; otherwise build a direct URI from the explicitly selected
|
|
353
|
+
* loopback/LAN endpoint.
|
|
349
354
|
*/
|
|
350
355
|
pairingInfo({ lanWsUrl = null } = {}) {
|
|
351
356
|
if (!this.pairing) return null;
|
|
@@ -363,6 +368,7 @@ export class RemoteApprovalBridge {
|
|
|
363
368
|
});
|
|
364
369
|
return {
|
|
365
370
|
uri,
|
|
371
|
+
mode: this.pairing.uri ? "relay" : "direct",
|
|
366
372
|
remoteSessionId: this.remoteSessionId,
|
|
367
373
|
scopes: this.pairing.scopes,
|
|
368
374
|
expiresAt: this.pairing.expiresAt,
|
|
@@ -1297,21 +1303,60 @@ export class RemoteApprovalBridge {
|
|
|
1297
1303
|
* self-hosts a lightweight WS server on an OS-assigned port (no sessionManager
|
|
1298
1304
|
* needed — the session stays client-hosted), starts a bridge for this run's
|
|
1299
1305
|
* session, prints the pairing URI (+ optional QR) to stderr, and returns the
|
|
1300
|
-
* gate confirmer + teardown. Relay settings
|
|
1301
|
-
*
|
|
1306
|
+
* gate confirmer + teardown. Relay settings flow through the startup
|
|
1307
|
+
* environment; LAN exposure remains a separate explicit caller authority.
|
|
1302
1308
|
*/
|
|
1303
1309
|
export async function startHeadlessRemoteApproval({
|
|
1304
1310
|
agentSessionId,
|
|
1311
|
+
allowLan = false,
|
|
1305
1312
|
env = process.env,
|
|
1306
|
-
config =
|
|
1313
|
+
config = undefined,
|
|
1307
1314
|
writeErr = () => {},
|
|
1308
1315
|
isText = false,
|
|
1309
1316
|
decisionTimeoutMs = undefined,
|
|
1310
1317
|
deps = {},
|
|
1311
1318
|
} = {}) {
|
|
1319
|
+
let effectiveConfig = config;
|
|
1320
|
+
if (effectiveConfig === undefined) {
|
|
1321
|
+
try {
|
|
1322
|
+
const configModule =
|
|
1323
|
+
deps.configModule || (await import("./config-manager.js"));
|
|
1324
|
+
effectiveConfig = configModule.loadConfig();
|
|
1325
|
+
} catch {
|
|
1326
|
+
effectiveConfig = {};
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
const resolved = resolveRemoteControlOptions({
|
|
1330
|
+
flags: { allowApprove: true, allowLan: allowLan === true },
|
|
1331
|
+
env,
|
|
1332
|
+
config: effectiveConfig || {},
|
|
1333
|
+
});
|
|
1334
|
+
if (!resolved.relayUrl && !resolved.lanAccessible) {
|
|
1335
|
+
throw new Error(
|
|
1336
|
+
"remote approval is loopback-only by default; configure a relay, or enable " +
|
|
1337
|
+
"allowLan with a non-loopback host (omit host to use 0.0.0.0) on a trusted network",
|
|
1338
|
+
);
|
|
1339
|
+
}
|
|
1340
|
+
const lanAddress = resolved.lanAccessible
|
|
1341
|
+
? deps.lanAddress ||
|
|
1342
|
+
(deps.pickLanAddress ? deps.pickLanAddress() : pickLanAddress())
|
|
1343
|
+
: null;
|
|
1344
|
+
const preflightLanWsUrl = resolveRemoteControlWsUrl(
|
|
1345
|
+
{ ...resolved, port: 1 },
|
|
1346
|
+
{ lanAddress },
|
|
1347
|
+
);
|
|
1348
|
+
if (
|
|
1349
|
+
!resolved.relayUrl &&
|
|
1350
|
+
resolved.lanAccessible &&
|
|
1351
|
+
isLoopbackBindHost(new URL(preflightLanWsUrl).hostname)
|
|
1352
|
+
) {
|
|
1353
|
+
throw new Error(
|
|
1354
|
+
"LAN binding is enabled but no private LAN address can be advertised; " +
|
|
1355
|
+
"configure a private host or a relay",
|
|
1356
|
+
);
|
|
1357
|
+
}
|
|
1312
1358
|
const { ChainlessChainWSServer } =
|
|
1313
1359
|
deps.serverModule || (await import("../gateways/ws/ws-server.js"));
|
|
1314
|
-
const resolved = resolveRemoteControlOptions({ flags: {}, env, config });
|
|
1315
1360
|
const server = new ChainlessChainWSServer({
|
|
1316
1361
|
port: 0,
|
|
1317
1362
|
host: resolved.host,
|
|
@@ -1319,50 +1364,95 @@ export async function startHeadlessRemoteApproval({
|
|
|
1319
1364
|
remoteSessionRelayUrl: resolved.relayUrl,
|
|
1320
1365
|
remoteSessionPeerId: resolved.peerId,
|
|
1321
1366
|
});
|
|
1322
|
-
|
|
1323
|
-
const bridge = new RemoteApprovalBridge({
|
|
1324
|
-
wsUrl: `ws://127.0.0.1:${server.port}`,
|
|
1325
|
-
token: resolved.token,
|
|
1326
|
-
agentSessionId,
|
|
1327
|
-
scopes: ["observe", "approve"],
|
|
1328
|
-
decisionTimeoutMs,
|
|
1329
|
-
});
|
|
1367
|
+
let bridge;
|
|
1330
1368
|
try {
|
|
1331
|
-
await
|
|
1369
|
+
await server.start();
|
|
1370
|
+
const createBridge =
|
|
1371
|
+
deps.createBridge || ((options) => new RemoteApprovalBridge(options));
|
|
1372
|
+
bridge = createBridge({
|
|
1373
|
+
wsUrl: resolveRemoteControlWsUrl(
|
|
1374
|
+
{ ...resolved, port: server.port, allowLan: resolved.lanAccessible },
|
|
1375
|
+
{ lanAddress: null },
|
|
1376
|
+
),
|
|
1377
|
+
token: resolved.token,
|
|
1378
|
+
agentSessionId,
|
|
1379
|
+
scopes: ["observe", "approve"],
|
|
1380
|
+
decisionTimeoutMs,
|
|
1381
|
+
});
|
|
1382
|
+
try {
|
|
1383
|
+
await bridge.start();
|
|
1384
|
+
} catch (err) {
|
|
1385
|
+
await server.stop().catch(() => undefined);
|
|
1386
|
+
throw err;
|
|
1387
|
+
}
|
|
1388
|
+
const lanWsUrl = resolveRemoteControlWsUrl(
|
|
1389
|
+
{ ...resolved, port: server.port },
|
|
1390
|
+
{ lanAddress },
|
|
1391
|
+
);
|
|
1392
|
+
const pairing = bridge.pairingInfo({ lanWsUrl });
|
|
1393
|
+
if (resolved.relayUrl && pairing?.mode !== "relay") {
|
|
1394
|
+
throw new Error(
|
|
1395
|
+
"the configured relay did not provide a pairing URI; refusing to fall back to direct pairing",
|
|
1396
|
+
);
|
|
1397
|
+
}
|
|
1398
|
+
if (
|
|
1399
|
+
!resolved.relayUrl &&
|
|
1400
|
+
pairing?.mode !== "relay" &&
|
|
1401
|
+
!resolved.lanAccessible
|
|
1402
|
+
) {
|
|
1403
|
+
throw new Error(
|
|
1404
|
+
"direct remote approval requires explicit allowLan on a trusted network",
|
|
1405
|
+
);
|
|
1406
|
+
}
|
|
1407
|
+
if (pairing?.mode === "direct") {
|
|
1408
|
+
if (isLoopbackBindHost(new URL(lanWsUrl).hostname)) {
|
|
1409
|
+
throw new Error(
|
|
1410
|
+
"LAN binding is enabled but no private LAN address can be advertised",
|
|
1411
|
+
);
|
|
1412
|
+
}
|
|
1413
|
+
assertDirectWsUrlAllowed(lanWsUrl);
|
|
1414
|
+
const warn = deps.warn || ((message) => logger.warn(message));
|
|
1415
|
+
warn(
|
|
1416
|
+
`LAN remote approval enabled on ${resolved.host}:${server.port}. ` +
|
|
1417
|
+
"Direct pairing uses plaintext ws:// with bearer credentials; use only on a trusted network.",
|
|
1418
|
+
);
|
|
1419
|
+
}
|
|
1420
|
+
if (!pairing?.uri) {
|
|
1421
|
+
throw new Error("remote approval did not produce a pairing URI");
|
|
1422
|
+
}
|
|
1423
|
+
if (isText) {
|
|
1424
|
+
writeErr(
|
|
1425
|
+
" remote-control: approvals can be answered from a paired device\n",
|
|
1426
|
+
);
|
|
1427
|
+
writeErr(` pairing: ${pairing.uri}\n`);
|
|
1428
|
+
const qr = await renderQrCode(pairing.uri, deps);
|
|
1429
|
+
if (qr) writeErr(qr + "\n");
|
|
1430
|
+
}
|
|
1431
|
+
return {
|
|
1432
|
+
pairing,
|
|
1433
|
+
server,
|
|
1434
|
+
bridge,
|
|
1435
|
+
confirmer: bridge.makeConfirmer({
|
|
1436
|
+
onAsk: (ask) => {
|
|
1437
|
+
if (isText) {
|
|
1438
|
+
writeErr(
|
|
1439
|
+
` permission(${ask.tool || "?"}): waiting for remote approval…\n`,
|
|
1440
|
+
);
|
|
1441
|
+
}
|
|
1442
|
+
},
|
|
1443
|
+
}),
|
|
1444
|
+
consumeAuthorization: (authorization, context) =>
|
|
1445
|
+
bridge.consumeAuthorization(authorization, context),
|
|
1446
|
+
close: async () => {
|
|
1447
|
+
await bridge.close().catch(() => undefined);
|
|
1448
|
+
await server.stop().catch(() => undefined);
|
|
1449
|
+
},
|
|
1450
|
+
};
|
|
1332
1451
|
} catch (err) {
|
|
1452
|
+
if (bridge) {
|
|
1453
|
+
await bridge.close().catch(() => undefined);
|
|
1454
|
+
}
|
|
1333
1455
|
await server.stop().catch(() => undefined);
|
|
1334
1456
|
throw err;
|
|
1335
1457
|
}
|
|
1336
|
-
const lanAddress = deps.lanAddress || pickLanAddress() || "127.0.0.1";
|
|
1337
|
-
const pairing = bridge.pairingInfo({
|
|
1338
|
-
lanWsUrl: `ws://${lanAddress}:${server.port}`,
|
|
1339
|
-
});
|
|
1340
|
-
if (isText) {
|
|
1341
|
-
writeErr(
|
|
1342
|
-
" remote-control: approvals can be answered from a paired device\n",
|
|
1343
|
-
);
|
|
1344
|
-
writeErr(` pairing: ${pairing.uri}\n`);
|
|
1345
|
-
const qr = await renderQrCode(pairing.uri, deps);
|
|
1346
|
-
if (qr) writeErr(qr + "\n");
|
|
1347
|
-
}
|
|
1348
|
-
return {
|
|
1349
|
-
pairing,
|
|
1350
|
-
server,
|
|
1351
|
-
bridge,
|
|
1352
|
-
confirmer: bridge.makeConfirmer({
|
|
1353
|
-
onAsk: (ask) => {
|
|
1354
|
-
if (isText) {
|
|
1355
|
-
writeErr(
|
|
1356
|
-
` permission(${ask.tool || "?"}): waiting for remote approval…\n`,
|
|
1357
|
-
);
|
|
1358
|
-
}
|
|
1359
|
-
},
|
|
1360
|
-
}),
|
|
1361
|
-
consumeAuthorization: (authorization, context) =>
|
|
1362
|
-
bridge.consumeAuthorization(authorization, context),
|
|
1363
|
-
close: async () => {
|
|
1364
|
-
await bridge.close().catch(() => undefined);
|
|
1365
|
-
await server.stop().catch(() => undefined);
|
|
1366
|
-
},
|
|
1367
|
-
};
|
|
1368
1458
|
}
|