chainlesschain 0.162.170 → 0.162.172
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/bin/chainlesschain.js +8 -0
- package/package.json +6 -1
- package/src/assets/web-panel/assets/{AIOps-BTXN24I3.js → AIOps-oKCWU-LK.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BBB1VF4j.js → ActionButton-4CBfc5E4.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-BVCXq0k6.js → Analytics-BEmR-k_b.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-C3EOo2s5.js → AppLayout-D6a4ZnrC.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-CsJTZSMv.js → Artifacts-BRWIHCPl.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CP0AllJ_.js → Audit-CzGKlkTc.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-BCAjs08m.js → BackgroundAgents-CmMYN10o.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BxQI5XH4.js → Backup-CJ6e0ukD.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-Bu-PNzC5.js → BaseInput-BpEvDrNt.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-DjPQynup.js → Chat-wWuwwjKu.js} +4 -4
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CygkRopu.js → ChatBubbleRenderer-CJLyGo_u.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-BxL6xm7Z.js → Checkbox-C6pW60Br.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CcyB7h_6.js → Codegen-DF-nP22Y.js} +1 -1
- package/src/assets/web-panel/assets/{Col-8NQiKJJx.js → Col-BuueEwZW.js} +1 -1
- package/src/assets/web-panel/assets/{Community-B31qy5OS.js → Community-DuE0Yzwr.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-C-5fAsZ4.js → Compact-BrHim8EB.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-BTSccvF0.js → Compliance-DgAet8f_.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-BXctU9IK.js → Cowork-B9wY05lx.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-CxVFX9NG.js → Cron-CvNBxfJX.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-DEF3dq8M.js → Crosschain-BnZRENa0.js} +1 -1
- package/src/assets/web-panel/assets/{DID-BmKcE9he.js → DID-DiqYLHTI.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-CECBq_wG.js → Dashboard-t3SsRzZL.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-U-iuPB0n.js → Dropdown-BCjMLam9.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-D8BIlSPL.js → EmailListRenderer-D2v9-IHJ.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-BzQGfUH-.js → FamilyGuardDashboard-_iQu35qa.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-4_WlOqLZ.js → Federation-Bkty8VqB.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-gtrW-DdF.js → FormItemContext-DdPW81BY.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-BLcvJJB6.js → GenericCardRenderer-DrNYM4Zj.js} +1 -1
- package/src/assets/web-panel/assets/{Git-Bk0janGD.js → Git-BjF-B2h0.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CcfyMlV8.js → Governance-DPhGdJ1v.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CBLrAf4M.js → Inference--PPksOVj.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-ClguhteZ.js → KnowledgeGraph-y5WdV_JV.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-Dp_oeKfJ.js → Logs-B6_x7zba.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-Bg8zSyF8.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-BHk50smM.js → Marketplace-CHpfMu1A.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-BAY3CV6J.js → McpTools-qqjtX3Cf.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-w0pG2AKx.js → Memory-hASSgxbw.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-C0VkDUE3.js → MobileBridge-Dwh7Bhcf.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-BCvQ80I9.js → MobileProjects-D09voh7W.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-DSIl41Tt.js → Mtc-9G1dXeId.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-D1mzUlIr.js → MtcAudit-CWtYXj6f.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-CeJz4VSS.js → Multisig-bDI0EnDk.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-_O3aweu8.js → NLProgramming-CTanRaBP.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Dt7_pO86.js → Notes-BdQENJFv.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-Dhg3Nktv.js → NotificationSettings-JvnQdStO.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-QsAPcTb2.js → OrderTableRenderer-BMGL9RPJ.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BuiaUPkv.js → Organization-sBZnIb2D.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-C3jb6knl.js → Overflow-CzOhNGE6.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BOMyrLkb.js → P2P-D_D2yqda.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-UvLStCgS.js → PdhVaultBrowser-D5lKd_Kx.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-B9cN0dJH.js → Permissions-L5s-wENg.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-DNjW5qro.js → PersonalDataHub-iI49x6cH.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-CFLyZ6Sh.js → Pipeline-DPHqyk09.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-D3w6vOxf.js → Privacy-B-ZL9360.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-cwcVsn8K.js → ProjectInit-f05YzsN2.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-aUoAroc-.js → ProjectSettings-DZLKS6ex.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-CrzQv7Zv.js → Projects-ButF3DyM.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-jZaPizKR.js → Providers-CFDSXnkR.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-DNzmwcfg.js → QrScannerModal-1N6Sdxdm.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-m-5Gwt70.js → QuickAsk-tEqRwRSR.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CrrAjNxP.js → Recommend-D4ZVHIwz.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-BDCMjRFe.js → RemoteSession-Cqm32lhm.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-CPCt1Jc8.js → Reputation-BnjVsU_a.js} +1 -1
- package/src/assets/web-panel/assets/{Row-C-RorxHs.js → Row-DzpHyTuz.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CnQs4TuY.js → RssFeed-Du5-ouwx.js} +3 -3
- package/src/assets/web-panel/assets/{Search-B1jkeFZY.js → Search-CYztyf2o.js} +1 -1
- package/src/assets/web-panel/assets/{Security-CGKI3vvd.js → Security-C1hVxy8Z.js} +3 -3
- package/src/assets/web-panel/assets/{Services-DQjesYF8.js → Services-BscEbAZ2.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-C9Ipj0A6.js → Skeleton-B2sMLqKQ.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-D2j54i9O.js → Skills-CoHKax06.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-xhrVjTeb.js → Sla-Bpie5KO6.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-C6KMOUCa.js → SpeechSettings-BX63ijn5.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CmIPU5wR.js → SyncSettings-Bf72so5A.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-B-T1J42r.js → Tasks-CVB2PZk4.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-Aq669sjw.js → Templates-q0qyclJx.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-BKWUWNXB.js → Tenant-CW-W-i0k.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-DEeAvA8L.js → Terminal-D7QoPiXQ.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-C465ySdn.js → TimelineRenderer-BaRDAbyA.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BgVqF-bX.js → Tokens-D6U4PRW8.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BMNHmxwH.js → Trigger-ClBDWdLo.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-B_adk89L.js → Trust-C_M6rWPq.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-Biw38mog.js → UkeySign-bXHx8s4C.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-AC-eaw5k.js → VideoEditing-BcIt_ieI.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-8lQ5_t0X.js → Wallet-Dd-4jcLs.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-JDmH_-DF.js → WebAuthn-B4F6yxQK.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-DHQAdITG.js → WorkflowEditor-BEHkpfJq.js} +1 -1
- package/src/assets/web-panel/assets/{chat-C3qauUVv.js → chat-D7hhRpIO.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DLP70JGe.js → colors-AMRhrRzS.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-DjsoqA5t.js → compact-item-BYpsOET5.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-CfEdl1in.js → createContext-CoUkR4LQ.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BRylvxzY.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DWwHHlBG.js → hasIn-CJKJMKki.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dfka-vzJ.js → index-8pmZHnQU.js} +1 -1
- package/src/assets/web-panel/assets/{index-DgQ92xdO.js → index-BBJFiZ9Y.js} +1 -1
- package/src/assets/web-panel/assets/{index-VtCz3A64.js → index-BP69Ul3S.js} +1 -1
- package/src/assets/web-panel/assets/{index-C8wrUFzY.js → index-BTFHYauX.js} +1 -1
- package/src/assets/web-panel/assets/{index-D5VL0NYy.js → index-BUJt2ar4.js} +1 -1
- package/src/assets/web-panel/assets/{index-B-rD2rhi.js → index-Bj30Aq6h.js} +1 -1
- package/src/assets/web-panel/assets/{index-gu8zBhtp.js → index-BlpuqGt5.js} +1 -1
- package/src/assets/web-panel/assets/index-Bzvxvzlk.js +1 -0
- package/src/assets/web-panel/assets/{index-CgruUvB3.js → index-C19xZKIP.js} +1 -1
- package/src/assets/web-panel/assets/{index-DTEcPJGf.js → index-C6bg22vc.js} +1 -1
- package/src/assets/web-panel/assets/{index-C4k6JGm_.js → index-CH6XEWdj.js} +1 -1
- package/src/assets/web-panel/assets/{index-C0xMzvk8.js → index-CK1Kknpl.js} +1 -1
- package/src/assets/web-panel/assets/{index-UEbYl2pu.js → index-CNyLbBGj.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dmt1HDWZ.js → index-COg__P6M.js} +19 -19
- package/src/assets/web-panel/assets/{index-ArZCi1rK.js → index-CRlJOWsf.js} +1 -1
- package/src/assets/web-panel/assets/{index-BqPuyN4p.js → index-CScG8TAY.js} +1 -1
- package/src/assets/web-panel/assets/{index-B4gCFHtB.js → index-CdL9cQIE.js} +1 -1
- package/src/assets/web-panel/assets/{index-C47EiQ7d.js → index-Ck35u_0v.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dn2rNMmv.js → index-CkLZQtsh.js} +1 -1
- package/src/assets/web-panel/assets/{index-T5emAyFT.js → index-DFoujkWD.js} +1 -1
- package/src/assets/web-panel/assets/{index-DbFnfyKh.js → index-DFwh0R9h.js} +1 -1
- package/src/assets/web-panel/assets/{index-CsEk9s04.js → index-DStN9E7o.js} +1 -1
- package/src/assets/web-panel/assets/{index-DTDpF8MS.js → index-DcozYrXV.js} +1 -1
- package/src/assets/web-panel/assets/{index-_g5q2hF3.js → index-De5mYp86.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bp_WNm2_.js → index-DfEVOzNb.js} +1 -1
- package/src/assets/web-panel/assets/{index-OfMwkFIo.js → index-Dfna8sKa.js} +1 -1
- package/src/assets/web-panel/assets/{index-BcDeMCUK.js → index-DjbMaBLf.js} +1 -1
- package/src/assets/web-panel/assets/index-Dl6H3dxS.js +1 -0
- package/src/assets/web-panel/assets/{index-D-te-S9f.js → index-Dpl_SJuk.js} +1 -1
- package/src/assets/web-panel/assets/{index-DKsWujXP.js → index-DyF9uYzB.js} +1 -1
- package/src/assets/web-panel/assets/{index-BydBh7oT.js → index-HF3GvATm.js} +1 -1
- package/src/assets/web-panel/assets/{index-DAcBi6F-.js → index-OJmXGn8n.js} +1 -1
- package/src/assets/web-panel/assets/{index-CNeLedtU.js → index-ZPdNPhUq.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ds1BfT_C.js → index-djikyGz3.js} +1 -1
- package/src/assets/web-panel/assets/{index-CbF27GqZ.js → index-gQWWnP3_.js} +1 -1
- package/src/assets/web-panel/assets/{index-CnhJbWsl.js → index-owVbLJnH.js} +1 -1
- package/src/assets/web-panel/assets/{index-Lh0e2afo.js → index-tWEDZHzj.js} +1 -1
- package/src/assets/web-panel/assets/{index-DbjUePgq.js → index-ttTl376q.js} +1 -1
- package/src/assets/web-panel/assets/{index-nuZaMsMy.js → index-z5rYvstM.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-C_pMmi75.js → initDefaultProps-B_Uk-wzg.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BvKgS96o.js → motion-ez7H8y8b.js} +1 -1
- package/src/assets/web-panel/assets/{move-C-1U4R1I.js → move-CKWUhhhX.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-D6BC968-.js → mtc-parser-DkNl7ocj.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DxOZvcGQ.js → omit-C0uA2ytw.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-LpzmHdkw.js → pickAttrs-CySaWMPl.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-Bm--qom1.js → placementArrow-BWL3-3xo.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-CVZZlhJf.js → responsiveObserve-BRy_wJog.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DD1xINGx.js → slide-DmmvSaBD.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-LrjHAy63.js → statusUtils-C_7SYY0K.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-BqknYxTe.js → styleChecker-DYgBJGDh.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-Dljy3diT.js → useFlexGapSupport-nPkoZkT6.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-OedUtPLc.js → useFs-CzpsfP4_.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-Cz-kxbP_.js → usePersonalDataHub-Bo2vvMWl.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-C8ZuTk8W.js → vnode-D-hXAnHb.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-CjbgJYXQ.js → zoom-DW7seTGG.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agent.js +39 -14
- package/src/commands/background-session.js +12 -1
- package/src/commands/permissions.js +24 -1
- package/src/gateways/ws/ws-agent-handler.js +26 -1
- package/src/gateways/ws/ws-approval-gate.js +131 -0
- package/src/index.js +63 -845
- package/src/lib/agent-ipc-bus.js +331 -0
- package/src/lib/agent-worktree.js +173 -5
- package/src/lib/background-agent-supervisor.js +193 -4
- package/src/lib/context-source-ledger.js +164 -0
- package/src/lib/execution-trace/index.js +10 -0
- package/src/lib/execution-trace/metrics-collector.js +218 -0
- package/src/lib/execution-trace/trace-context.js +182 -0
- package/src/lib/hook-manager.js +17 -0
- package/src/lib/hooks-v2-runtime.js +278 -0
- package/src/lib/interaction-adapter.js +26 -5
- package/src/lib/metrics-collector.js +127 -0
- package/src/lib/observability/index.js +33 -0
- package/src/lib/observability/otlp-exporter.js +260 -0
- package/src/lib/otlp-exporter.js +45 -0
- package/src/lib/process-execution-broker/SPAWN_AUDIT_REPORT.md +117 -0
- package/src/lib/process-execution-broker/index.js +450 -0
- package/src/lib/process-execution-broker/patch-child-process.js +50 -0
- package/src/lib/process-execution-broker/spawn-audit.json +3814 -0
- package/src/lib/repl-rewind.js +62 -14
- package/src/lib/runtime-provenance-ledger.js +190 -0
- package/src/lib/session-hooks.js +41 -0
- package/src/lib/turn-binding.js +134 -0
- package/src/program-base.js +4 -1
- package/src/repl/agent-repl.js +77 -3
- package/src/repl/repl-turn-binding.js +91 -0
- package/src/runtime/headless-runner.js +59 -0
- package/src/assets/web-panel/assets/MarkdownRenderer-RQ1HbTY5.js +0 -1
- package/src/assets/web-panel/assets/devWarning-Cwuuqc_f.js +0 -1
- package/src/assets/web-panel/assets/index-BkTk-zJK.js +0 -1
- package/src/assets/web-panel/assets/index-C-BSTEhe.js +0 -1
|
@@ -26,6 +26,7 @@ import { runnableTaskModel } from "../../lib/runnable-provider.js";
|
|
|
26
26
|
import { PlanState } from "../../lib/plan-mode.js";
|
|
27
27
|
import { CLISlotFiller } from "../../lib/slot-filler.js";
|
|
28
28
|
import { createAbortError, isAbortError } from "../../lib/abort-utils.js";
|
|
29
|
+
import { createWsApprovalGate } from "./ws-approval-gate.js";
|
|
29
30
|
|
|
30
31
|
export class WSAgentHandler {
|
|
31
32
|
/**
|
|
@@ -34,7 +35,7 @@ export class WSAgentHandler {
|
|
|
34
35
|
* @param {import("../../lib/interaction-adapter.js").WebSocketInteractionAdapter} options.interaction
|
|
35
36
|
* @param {object} [options.db]
|
|
36
37
|
*/
|
|
37
|
-
constructor({ session, interaction, db }) {
|
|
38
|
+
constructor({ session, interaction, db, approvalGate }) {
|
|
38
39
|
this.session = session;
|
|
39
40
|
this.interaction = interaction;
|
|
40
41
|
this.db = db || null;
|
|
@@ -44,6 +45,27 @@ export class WSAgentHandler {
|
|
|
44
45
|
// P0-2: monotonic sequence for crash-safe side-effect ledger op ids. The
|
|
45
46
|
// session id + a per-op nonce keep ids unique across turns and processes.
|
|
46
47
|
this._sideEffectSeq = 0;
|
|
48
|
+
// P0 authority: permission-gate-over-WS. An explicitly injected gate wins
|
|
49
|
+
// (tests / embedders); otherwise one is built lazily on the first turn
|
|
50
|
+
// when CC_WS_APPROVAL_GATE=1 — its confirmer raises confirm questions
|
|
51
|
+
// over the interaction adapter WITH an approval binding the client must
|
|
52
|
+
// echo back on approve (mismatch → deny). Default (env unset, nothing
|
|
53
|
+
// injected): approvalGate stays null and loopOptions are byte-identical.
|
|
54
|
+
this._approvalGate = approvalGate || null;
|
|
55
|
+
this._approvalGateInit = Boolean(approvalGate);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Resolve the session's approval gate (lazy, opt-in; null when disabled). */
|
|
59
|
+
async _ensureApprovalGate() {
|
|
60
|
+
if (this._approvalGateInit) return this._approvalGate;
|
|
61
|
+
this._approvalGateInit = true;
|
|
62
|
+
if (process.env.CC_WS_APPROVAL_GATE === "1") {
|
|
63
|
+
this._approvalGate = await createWsApprovalGate({
|
|
64
|
+
sessionId: this.session.id,
|
|
65
|
+
interaction: this.interaction,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return this._approvalGate;
|
|
47
69
|
}
|
|
48
70
|
|
|
49
71
|
/**
|
|
@@ -127,6 +149,9 @@ export class WSAgentHandler {
|
|
|
127
149
|
slotFiller,
|
|
128
150
|
interaction: this.interaction,
|
|
129
151
|
signal: abortController.signal,
|
|
152
|
+
// P0 authority: null unless opted in (byte-identical default — agent
|
|
153
|
+
// core already defaults `options.approvalGate || null`).
|
|
154
|
+
approvalGate: await this._ensureApprovalGate(),
|
|
130
155
|
};
|
|
131
156
|
|
|
132
157
|
// P0-2: crash-safe side-effect ledger for the IDE/bridge path — mirrors
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permission-gate-over-WS — the approval-BINDING producer for the WS path.
|
|
3
|
+
*
|
|
4
|
+
* The consumer side has been wired for a while: WebSocketInteractionAdapter
|
|
5
|
+
* stores `options.binding` on a pending request, rides it out on the message,
|
|
6
|
+
* and `_resolvePending` rejects an approve whose echoed binding mismatches
|
|
7
|
+
* (deny, fail closed). What was missing is the PRODUCER: nothing on the WS
|
|
8
|
+
* path ever raised an approval request WITH a binding, because the WS agent
|
|
9
|
+
* handler wired no ApprovalGate at all (CONFIRM-tier decisions fell closed).
|
|
10
|
+
*
|
|
11
|
+
* This module supplies both halves:
|
|
12
|
+
* - `buildWsApprovalConfirmer` — the gate confirmer that computes
|
|
13
|
+
* `approvalBindingDigest({toolCallId, args, policyDigest})` (mirroring the
|
|
14
|
+
* headless-stream `interactiveConfirm` producer) and asks the WS client
|
|
15
|
+
* over the interaction adapter with the binding attached. Timeout /
|
|
16
|
+
* disconnect / any transport error → false (fail closed).
|
|
17
|
+
* - `createWsApprovalGate` — a session-scoped gate whose CONFIRM decisions
|
|
18
|
+
* route to that confirmer. Policy tiers stay authoritative on the shared
|
|
19
|
+
* singleton gate (so `sessions.policy.set` over WS keeps working and no
|
|
20
|
+
* global confirmer is ever mutated — a per-session confirmer on the
|
|
21
|
+
* process-wide singleton would race across concurrent WS sessions).
|
|
22
|
+
*
|
|
23
|
+
* Default byte-identical: the WS handler only builds this when
|
|
24
|
+
* `CC_WS_APPROVAL_GATE=1` (or a gate is injected); otherwise loopOptions
|
|
25
|
+
* carry `approvalGate: null` exactly as before.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import { approvalBindingDigest } from "../../lib/agent-authority.js";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Build the binding-attaching confirmer for one WS session.
|
|
32
|
+
*
|
|
33
|
+
* @param {object} opts
|
|
34
|
+
* @param {{askConfirm: Function}} opts.interaction - the session's WS adapter
|
|
35
|
+
* @param {string} opts.sessionId
|
|
36
|
+
* @returns {(ctx?: object) => Promise<boolean>}
|
|
37
|
+
*/
|
|
38
|
+
export function buildWsApprovalConfirmer({ interaction, sessionId }) {
|
|
39
|
+
let approvalSeq = 0;
|
|
40
|
+
return async (ctx = {}) => {
|
|
41
|
+
const command = ctx.command ?? ctx.args?.command ?? null;
|
|
42
|
+
const risk = ctx.riskLevel || ctx.risk || "unknown";
|
|
43
|
+
// Bind this approval to the exact call it authorizes (same recipe as the
|
|
44
|
+
// headless-stream producer): request identity + normalized args + the
|
|
45
|
+
// policy/rule in force. The client must echo it back on approve.
|
|
46
|
+
const binding = approvalBindingDigest({
|
|
47
|
+
toolCallId: `${sessionId}:appr-${++approvalSeq}`,
|
|
48
|
+
args: ctx.args ?? (command != null ? { command } : null),
|
|
49
|
+
policyDigest: ctx.rule || ctx.riskLevel || ctx.risk || null,
|
|
50
|
+
});
|
|
51
|
+
const what = ctx.tool || ctx.toolName || "tool";
|
|
52
|
+
const detail = command != null ? `: ${String(command).slice(0, 200)}` : "";
|
|
53
|
+
try {
|
|
54
|
+
const ok = await interaction.askConfirm(
|
|
55
|
+
`Approve ${what}${detail}? (risk: ${risk})`,
|
|
56
|
+
{
|
|
57
|
+
default: false,
|
|
58
|
+
binding,
|
|
59
|
+
// Structured context so UIs can render a proper approval card
|
|
60
|
+
// instead of parsing the question text.
|
|
61
|
+
approval: {
|
|
62
|
+
tool: what,
|
|
63
|
+
command,
|
|
64
|
+
risk,
|
|
65
|
+
rule: ctx.rule || null,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
);
|
|
69
|
+
return ok === true;
|
|
70
|
+
} catch {
|
|
71
|
+
// timeout / disconnect / interrupt → fail closed, never approve
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Create a session-scoped approval gate for the WS agent handler.
|
|
79
|
+
*
|
|
80
|
+
* Policy lookups delegate to the persistent singleton gate (per-session tiers
|
|
81
|
+
* set via `sessions.policy.set` stay live); CONFIRM decisions route to the
|
|
82
|
+
* binding-attaching WS confirmer. Returns null on any load failure so the
|
|
83
|
+
* caller degrades to the legacy no-gate path (fail closed at CONFIRM).
|
|
84
|
+
*
|
|
85
|
+
* @param {object} opts
|
|
86
|
+
* @param {string} opts.sessionId
|
|
87
|
+
* @param {{askConfirm: Function}} opts.interaction
|
|
88
|
+
* @param {object} [opts.deps] - test seams: `loadSingletons`, `loadSessionCore`
|
|
89
|
+
* @returns {Promise<object|null>}
|
|
90
|
+
*/
|
|
91
|
+
export async function createWsApprovalGate({
|
|
92
|
+
sessionId,
|
|
93
|
+
interaction,
|
|
94
|
+
deps = {},
|
|
95
|
+
}) {
|
|
96
|
+
try {
|
|
97
|
+
const loadSingletons =
|
|
98
|
+
deps.loadSingletons ||
|
|
99
|
+
(() => import("../../lib/session-core-singletons.js"));
|
|
100
|
+
const loadSessionCore =
|
|
101
|
+
deps.loadSessionCore || (() => import("@chainlesschain/session-core"));
|
|
102
|
+
const [singletons, core] = await Promise.all([
|
|
103
|
+
loadSingletons(),
|
|
104
|
+
loadSessionCore(),
|
|
105
|
+
]);
|
|
106
|
+
const inner = await singletons.getApprovalGate();
|
|
107
|
+
const confirmer =
|
|
108
|
+
deps.confirmer || buildWsApprovalConfirmer({ interaction, sessionId });
|
|
109
|
+
const gate = new core.ApprovalGate({
|
|
110
|
+
defaultPolicy: core.APPROVAL_POLICY?.STRICT || "strict",
|
|
111
|
+
confirm: confirmer,
|
|
112
|
+
});
|
|
113
|
+
return {
|
|
114
|
+
// Explicit ctx.policy always wins inside decide(); resolve it from the
|
|
115
|
+
// singleton on every call so mid-session `sessions.policy.set` applies.
|
|
116
|
+
decide: (ctx = {}) =>
|
|
117
|
+
gate.decide({
|
|
118
|
+
...ctx,
|
|
119
|
+
policy:
|
|
120
|
+
ctx.policy || inner.getSessionPolicy(ctx.sessionId || sessionId),
|
|
121
|
+
}),
|
|
122
|
+
hasConfirmer: () => gate.hasConfirmer(),
|
|
123
|
+
setConfirmer: (fn) => gate.setConfirmer(fn),
|
|
124
|
+
getSessionPolicy: (sid) => inner.getSessionPolicy(sid || sessionId),
|
|
125
|
+
setSessionPolicy: (sid, policy) =>
|
|
126
|
+
inner.setSessionPolicy(sid || sessionId, policy),
|
|
127
|
+
};
|
|
128
|
+
} catch {
|
|
129
|
+
return null; // degrade to the legacy no-gate path
|
|
130
|
+
}
|
|
131
|
+
}
|