chainlesschain 0.166.7 → 0.166.9
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/README.md +21 -0
- package/package.json +3 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-BlrmQxa2.js → AIOps-DJvpifGx.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-zyRyLITg.js → ActionButton-D2UhuF_A.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DwGz7OGN.js → Analytics-C9ho9obu.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-Dc-nj7Zd.js → AppLayout-BvRCpFK3.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-7Hu3O73p.js → Artifacts-jxrySvpk.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-Bnoe3-fR.js → Audit-ovEw0ZYl.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-BqYFrDKZ.js → BackgroundAgents-D7H5z6zS.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-B3hwW1nz.js → Backup-BuXob8za.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-XFVxLA4w.js → BaseInput-CtnszuQ2.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CWRDNw7e.js → Chat-B_mYE8fJ.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-Bf30VM8G.js → ChatBubbleRenderer-DaiA6CsX.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-kFeeBgac.js → Checkbox-ierdtcJD.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CCxp8xoI.js → Codegen-3VKPJD_B.js} +1 -1
- package/src/assets/web-panel/assets/{Col-BLKZalle.js → Col-1EdMyf5P.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DD0eWCez.js → Community-D6H7UA8K.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-CHqHWdy0.js → Compact-BBAZvYIm.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-Bw54uPiK.js → Compliance-CgsTrAoj.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DZ13zKNJ.js → Cowork-tnZgLoTE.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-Dlj5Jevg.js → Cron-CPpZw2Nh.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-Nvz0aR0j.js → Crosschain-BymBcp5z.js} +1 -1
- package/src/assets/web-panel/assets/{DID-Ct89eUyY.js → DID-DKPxS_K1.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-BHUH5IAe.js → Dashboard-DvJhEmH9.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BhZG-PO7.js → Dropdown-b8iQyQIZ.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-ae4RVwwJ.js → EmailListRenderer--0-A-zKb.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-AOcxLfLr.js → FamilyGuardDashboard-C12iDN06.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BK2PJQOF.js → Federation-BRhaE2Z8.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-C2n3xO2_.js → FormItemContext-C4dnq7yf.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DcyUVFZq.js → GenericCardRenderer-CGAdbR5n.js} +1 -1
- package/src/assets/web-panel/assets/{Git-tBae9Lt8.js → Git-4eA2fYzL.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DmNR3AP4.js → Governance-BJuY9Y-9.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CoseEigi.js → Inference-DZ5Dy4up.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-Bdjd1sxr.js → KnowledgeGraph-BMTjRs4A.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CtlkKIcn.js → Logs-BKEeQEfJ.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-B05DgASC.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-BTYb7nEx.js → Marketplace-Dhho4fEg.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-D0iUdW3P.js → McpTools-BW6xxSlU.js} +2 -2
- package/src/assets/web-panel/assets/{Memory--gwI7w4Y.js → Memory-mPqlpSkq.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-JmFBi24T.js → MobileBridge-Cb9N_DQI.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-BK01cQRx.js → MobileProjects-BNs8tah_.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-u7avzyoO.js → Mtc-CaxBt8tn.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-gT3z5fo_.js → MtcAudit-DRPQbp3t.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-BIqZTz5n.js → Multisig-CRm-d8bK.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-DdhVfXYq.js → NLProgramming-BCCk3LPs.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CBlyUmY3.js → Notes-Cv8SN8gN.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-DSyI26N3.js → NotificationSettings-CggIvTh5.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-B7IEuNz4.js → OrderTableRenderer-BW3_bV12.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-ozhi4kGS.js → Organization-BuRE-VCO.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-CBy57RVM.js → Overflow-DBrm1gju.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CA-ZRv77.js → P2P-CWVnDYgS.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-DOHc9zm8.js → PdhVaultBrowser-8RKUIpte.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-DiP632GP.js → Permissions-tDUAxogW.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-AnU8O-SS.js → PersonalDataHub-Dv2-CFis.js} +5 -5
- package/src/assets/web-panel/assets/{Pipeline-DDibOUaP.js → Pipeline-DM6kvFni.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-D421t36T.js → Privacy-DzK-yL0d.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-DR879ZPJ.js → ProjectInit-B5UrNpkj.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-Ded8o6aY.js → ProjectSettings-CxJD43oW.js} +2 -2
- package/src/assets/web-panel/assets/Projects-Z2Orm8Ma.js +1 -0
- package/src/assets/web-panel/assets/{Providers-Boivuu-E.js → Providers-CYl4jRYK.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-xKD_ntKp.js → QrScannerModal-DeH2T0fH.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-D3y_A6FV.js → QuickAsk-Bw9k_kTk.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-BjKM-YC2.js → Recommend-Bl_jGwoi.js} +1 -1
- package/src/assets/web-panel/assets/RemoteSession-d6u01Kq0.js +5 -0
- package/src/assets/web-panel/assets/{Reputation-Ci2GjH5p.js → Reputation-Ds_Dfr-k.js} +1 -1
- package/src/assets/web-panel/assets/{Row-B0-T2BSh.js → Row-BpQUQTNj.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-Bet-ur-r.js → RssFeed-BatpZBGt.js} +2 -2
- package/src/assets/web-panel/assets/{Search-DWtRAS2R.js → Search-D7hOObzi.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BDfu2Qn6.js → Security-dXQ4FKNt.js} +4 -4
- package/src/assets/web-panel/assets/{Services-CvJmvSMM.js → Services-D8wInGPa.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CEbrKpdC.js → Skeleton-DXQCoYpM.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CjVeiETf.js → Skills-D3oLRIVn.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-Dibypxum.js → Sla-BmP4-LnJ.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-XflYXp7a.js → SpeechSettings-DLj-xzro.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-ro1Ivx1E.js → SyncSettings-8KKaaRMr.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-CHq1qFbo.js → Tasks-GyK42I7C.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CRnUZxtZ.js → Templates-n1y_8UBG.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-jUX72JCA.js → Tenant-B39nBph8.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-BBhAs7pt.js → Terminal-DCQoOKXe.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-CD5M3RGp.js → TimelineRenderer-BkhbDfXk.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-sah3v0gu.js → Tokens-BeHIIU8D.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BNT3Uz3s.js → Trigger-BHvWXVOb.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-BytMGPMo.js → Trust-y2WaOSto.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-BkYVMRQs.js → UkeySign-DBFeJBzt.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-psvb5Q7Y.js → VideoEditing-BEOWitC-.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-PFQTW0MH.js → Wallet-BITedTe6.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DgO-OwRT.js → WebAuthn-DMwlJVin.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-DL2l9VNl.js → WorkflowEditor-CKfGFEu1.js} +1 -1
- package/src/assets/web-panel/assets/{chat-C84akEzN.js → chat-DR6gnBGF.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DzTWuQKP.js → colors-C_Hw5NCn.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-CR9LJQFv.js → compact-item-B8IPwsEu.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-CTTov5Kn.js → createContext-D-u4JVnJ.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-Cq6lSd_q.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DALj523o.js → hasIn-CZubdS4D.js} +1 -1
- package/src/assets/web-panel/assets/{index-Be6Os5S8.js → index-11ASqx-A.js} +1 -1
- package/src/assets/web-panel/assets/index-BQ3213fz.js +1 -0
- package/src/assets/web-panel/assets/{index-CXaCRXN4.js → index-BXS6wYJZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-7ux_XohH.js → index-Bi21Etg4.js} +1 -1
- package/src/assets/web-panel/assets/{index-CXTEpfGe.js → index-Bizm87cX.js} +1 -1
- package/src/assets/web-panel/assets/{index-DH6OG-ci.js → index-Bv2132PO.js} +1 -1
- package/src/assets/web-panel/assets/{index-CZhhFQi9.js → index-BzoFanEQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-B6QOJbSn.js → index-C25rOz7O.js} +1 -1
- package/src/assets/web-panel/assets/{index-CunGDV0g.js → index-C2VmtNaQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CmELknPe.js → index-Cbm8F0M2.js} +1 -1
- package/src/assets/web-panel/assets/{index-DZER6Lj3.js → index-CfniPP5p.js} +1 -1
- package/src/assets/web-panel/assets/{index-B2qpjU-D.js → index-Cg2bCeol.js} +1 -1
- package/src/assets/web-panel/assets/{index-QW0EXx14.js → index-CiXkhOkY.js} +1 -1
- package/src/assets/web-panel/assets/{index-C5eeMl_2.js → index-Cl5RpreD.js} +1 -1
- package/src/assets/web-panel/assets/{index-s4CFyn-n.js → index-CqmLw8cs.js} +1 -1
- package/src/assets/web-panel/assets/{index-eJcFleIV.js → index-Ctje8Vl3.js} +1 -1
- package/src/assets/web-panel/assets/{index-3-XJoYgX.js → index-D1w96gg9.js} +1 -1
- package/src/assets/web-panel/assets/{index-_8vetPbU.js → index-D47jt8ET.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cef0n4k_.js → index-DJ6pG79m.js} +1 -1
- package/src/assets/web-panel/assets/{index-AXnERsyV.js → index-DTosx2Wu.js} +1 -1
- package/src/assets/web-panel/assets/{index-DtW6Zr_i.js → index-DY6MHo9D.js} +1 -1
- package/src/assets/web-panel/assets/{index-CNmTDXmf.js → index-DcFjRT-K.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dah8M4l2.js → index-DfnzrUxU.js} +1 -1
- package/src/assets/web-panel/assets/{index-D0MqUnKO.js → index-DjRrqooR.js} +1 -1
- package/src/assets/web-panel/assets/{index-CqUgXYIQ.js → index-DmRcgiYT.js} +1 -1
- package/src/assets/web-panel/assets/{index-D9ScRFxz.js → index-DpjHpRoq.js} +3 -3
- package/src/assets/web-panel/assets/{index-DjE_ew7U.js → index-Dt-w3xQ7.js} +1 -1
- package/src/assets/web-panel/assets/{index-W9axN_Ce.js → index-DuOU5apg.js} +1 -1
- package/src/assets/web-panel/assets/{index-BDyt57zL.js → index-LvjAKDSl.js} +1 -1
- package/src/assets/web-panel/assets/{index-hzzTITR9.js → index-_nL79NT8.js} +1 -1
- package/src/assets/web-panel/assets/{index-BNaQt49r.js → index-auyNYjLo.js} +1 -1
- package/src/assets/web-panel/assets/{index-DBIPnoTj.js → index-cVqbas5C.js} +1 -1
- package/src/assets/web-panel/assets/{index-CnxjXIsK.js → index-ffe7bvqP.js} +1 -1
- package/src/assets/web-panel/assets/{index-BHRXKiU1.js → index-idZKyADQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-D_Bg0LdK.js → index-k1Xa5iw1.js} +1 -1
- package/src/assets/web-panel/assets/{index-BKNIzw0U.js → index-mYZJxGH6.js} +1 -1
- package/src/assets/web-panel/assets/{index-DxdzSljS.js → index-rYBHSDcJ.js} +1 -1
- package/src/assets/web-panel/assets/index-vJagfET2.js +1 -0
- package/src/assets/web-panel/assets/{index-CjkPDSX4.js → index-xoNssgz_.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-JuW8mFj7.js → initDefaultProps-lcU_dT2r.js} +1 -1
- package/src/assets/web-panel/assets/{motion-Cwb0HBve.js → motion-Dc7UNXZ1.js} +1 -1
- package/src/assets/web-panel/assets/{move-DHokzMgu.js → move-Cll8ZXaL.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DX31y6QS.js → mtc-parser-CAb_yLIM.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BCIUYDA6.js → omit-DurYMyTe.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DMCj4EoZ.js → pickAttrs-BITQyOlw.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-Dy5K-u1s.js → placementArrow-Dg1rH91i.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-DkGeZu54.js → responsiveObserve-D_EWIeac.js} +1 -1
- package/src/assets/web-panel/assets/{slide-Dc5dyJdg.js → slide-lK4d3zsh.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DIUBjOaC.js → statusUtils-Bflq-Git.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-DmyEOxm5.js → styleChecker-Ccp0I-wt.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-FRhakk1e.js → useFlexGapSupport-CYZbByYA.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-clXyV1WQ.js → useFs-B_x0nxFD.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-UF6DG41z.js → usePersonalDataHub-DW55rL85.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-CoCt95G7.js → vnode-Ca6MH3W8.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-yVWt-ENm.js → zoom-NdHelOog.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +1 -1
- package/src/commands/orchestrate.js +61 -9
- package/src/data/changelog.json +34 -1
- package/src/gateways/ws/message-dispatcher.js +4 -0
- package/src/gateways/ws/session-protocol.js +89 -11
- package/src/gateways/ws/ws-agent-handler.js +65 -9
- package/src/gateways/ws/ws-approval-gate.js +181 -16
- package/src/gateways/ws/ws-server.js +16 -6
- package/src/generated/cc-agent-protocol.schema.json +148 -2
- package/src/lib/agent-team/task-lease.js +172 -3
- package/src/lib/agent-team/team-runner.js +60 -1
- package/src/lib/app-server/graph-runtime.js +326 -2
- package/src/lib/app-server/server.js +60 -0
- package/src/lib/approval-grant-ledger.js +69 -0
- package/src/lib/codex-app-server-adapter.js +11 -20
- package/src/lib/graph-kernel/compiler.js +66 -13
- package/src/lib/graph-kernel/cutover-authority-resolver.js +26 -0
- package/src/lib/graph-kernel/cutover-ledger.js +53 -11
- package/src/lib/graph-kernel/retirement-evidence.js +567 -0
- package/src/lib/graph-kernel/runtime.js +76 -14
- package/src/lib/interaction-adapter.js +61 -9
- package/src/lib/policy-decision-event.js +149 -0
- package/src/lib/process-execution-broker/platform-sandbox.js +15 -1
- package/src/lib/record-replay/index.js +1 -0
- package/src/lib/record-replay/playwright-ui-driver.js +327 -0
- package/src/lib/webhook-security.js +484 -36
- package/src/runtime/coding-agent-events.cjs +13 -11
- package/src/runtime/headless-runner.js +17 -1
- package/src/runtime/headless-stream.js +66 -3
- package/src/runtime/session-slash-commands.js +57 -6
- package/src/assets/web-panel/assets/MarkdownRenderer-CZsTBEQE.js +0 -1
- package/src/assets/web-panel/assets/Projects-BHPxiucB.js +0 -1
- package/src/assets/web-panel/assets/RemoteSession-CgqKMXG4.js +0 -5
- package/src/assets/web-panel/assets/devWarning-BOhvmlpc.js +0 -1
- package/src/assets/web-panel/assets/index-DDyMJexx.js +0 -1
- package/src/assets/web-panel/assets/index-btiojFYn.js +0 -1
|
@@ -606,9 +606,11 @@ async function ensureSessionHandler(
|
|
|
606
606
|
if (budgetConfig.enabled) {
|
|
607
607
|
const priceTable =
|
|
608
608
|
budgetConfig.limits.maxUsd != null
|
|
609
|
-
? wsBudgetDependency(
|
|
610
|
-
server
|
|
611
|
-
|
|
609
|
+
? wsBudgetDependency(
|
|
610
|
+
server,
|
|
611
|
+
"mergePricing",
|
|
612
|
+
mergePricing,
|
|
613
|
+
)(server.sessionManager.config?.llm?.pricing)
|
|
612
614
|
: undefined;
|
|
613
615
|
sessionBudgetRoot = wsBudgetDependency(
|
|
614
616
|
server,
|
|
@@ -627,9 +629,7 @@ async function ensureSessionHandler(
|
|
|
627
629
|
sessionBudgetRoot.budget ||
|
|
628
630
|
typeof sessionBudgetRoot.close !== "function"
|
|
629
631
|
) {
|
|
630
|
-
const error = new Error(
|
|
631
|
-
"WebSocket session budget root is invalid",
|
|
632
|
-
);
|
|
632
|
+
const error = new Error("WebSocket session budget root is invalid");
|
|
633
633
|
error.code = "CC_SESSION_BUDGET_ROOT_INVALID";
|
|
634
634
|
throw error;
|
|
635
635
|
}
|
|
@@ -746,9 +746,7 @@ export async function handleSessionCreate(server, id, ws, message) {
|
|
|
746
746
|
worktreeIsolation,
|
|
747
747
|
systemPromptExtension,
|
|
748
748
|
shellPolicyOverrides,
|
|
749
|
-
sessionBudgetRoot: sessionBudgetRoot.enabled
|
|
750
|
-
? sessionBudgetRoot
|
|
751
|
-
: null,
|
|
749
|
+
sessionBudgetRoot: sessionBudgetRoot.enabled ? sessionBudgetRoot : null,
|
|
752
750
|
requireDurable: sessionBudgetRoot.enabled,
|
|
753
751
|
});
|
|
754
752
|
createdSessionId = sessionId;
|
|
@@ -1487,16 +1485,96 @@ export function handleSessionAnswer(server, id, ws, message) {
|
|
|
1487
1485
|
}
|
|
1488
1486
|
|
|
1489
1487
|
const session = server.sessionManager.getSession(sessionId);
|
|
1488
|
+
let settlement = null;
|
|
1489
|
+
let settlementAttempted = false;
|
|
1490
1490
|
if (session && session.interaction && session.interaction.resolveAnswer) {
|
|
1491
|
-
|
|
1491
|
+
settlementAttempted = true;
|
|
1492
|
+
settlement = session.interaction.resolveAnswer(requestId, answer, binding);
|
|
1492
1493
|
}
|
|
1493
1494
|
|
|
1495
|
+
// New adapters return an explicit settlement result. Legacy/custom
|
|
1496
|
+
// interactions return undefined and preserve the historical success ACK.
|
|
1497
|
+
const settled = settlementAttempted && settlement?.settled !== false;
|
|
1498
|
+
|
|
1494
1499
|
server._send(
|
|
1495
1500
|
ws,
|
|
1496
1501
|
envelopeResponse(
|
|
1497
1502
|
CODING_AGENT_EVENT_TYPES.COMMAND_RESPONSE,
|
|
1498
1503
|
id,
|
|
1499
|
-
{
|
|
1504
|
+
{
|
|
1505
|
+
success: settled,
|
|
1506
|
+
settled,
|
|
1507
|
+
...(settlement?.reason ? { reason: settlement.reason } : {}),
|
|
1508
|
+
},
|
|
1509
|
+
sessionId,
|
|
1510
|
+
),
|
|
1511
|
+
);
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
export async function handleApprovalGrantsList(server, id, ws, message) {
|
|
1515
|
+
const sessionId = message.sessionId;
|
|
1516
|
+
const session = server.sessionManager?.getSession?.(sessionId) || null;
|
|
1517
|
+
const handler = server.sessionHandlers?.get?.(sessionId) || null;
|
|
1518
|
+
if (!session || !handler?.listApprovalGrants) {
|
|
1519
|
+
server._send(
|
|
1520
|
+
ws,
|
|
1521
|
+
envelopeError(
|
|
1522
|
+
id,
|
|
1523
|
+
"APPROVAL_GRANT_SESSION_UNAVAILABLE",
|
|
1524
|
+
"Approval grant session is not active",
|
|
1525
|
+
sessionId,
|
|
1526
|
+
),
|
|
1527
|
+
);
|
|
1528
|
+
return;
|
|
1529
|
+
}
|
|
1530
|
+
const grants = await handler.listApprovalGrants();
|
|
1531
|
+
server._send(
|
|
1532
|
+
ws,
|
|
1533
|
+
envelopeResponse(
|
|
1534
|
+
CODING_AGENT_EVENT_TYPES.COMMAND_RESPONSE,
|
|
1535
|
+
id,
|
|
1536
|
+
{ success: true, grants },
|
|
1537
|
+
sessionId,
|
|
1538
|
+
),
|
|
1539
|
+
);
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
export async function handleApprovalGrantRevoke(server, id, ws, message) {
|
|
1543
|
+
const sessionId = message.sessionId;
|
|
1544
|
+
const grantId = String(message.grantId || "");
|
|
1545
|
+
const handler = server.sessionHandlers?.get?.(sessionId) || null;
|
|
1546
|
+
if (!grantId || !handler?.revokeApprovalGrant) {
|
|
1547
|
+
server._send(
|
|
1548
|
+
ws,
|
|
1549
|
+
envelopeError(
|
|
1550
|
+
id,
|
|
1551
|
+
"APPROVAL_GRANT_REVOKE_INVALID",
|
|
1552
|
+
"An active approval grant and grantId are required",
|
|
1553
|
+
sessionId,
|
|
1554
|
+
),
|
|
1555
|
+
);
|
|
1556
|
+
return;
|
|
1557
|
+
}
|
|
1558
|
+
const result = await handler.revokeApprovalGrant(grantId);
|
|
1559
|
+
if (!result?.success) {
|
|
1560
|
+
server._send(
|
|
1561
|
+
ws,
|
|
1562
|
+
envelopeError(
|
|
1563
|
+
id,
|
|
1564
|
+
"APPROVAL_GRANT_REVOKE_FAILED",
|
|
1565
|
+
result?.error || "Approval grant could not be revoked",
|
|
1566
|
+
sessionId,
|
|
1567
|
+
),
|
|
1568
|
+
);
|
|
1569
|
+
return;
|
|
1570
|
+
}
|
|
1571
|
+
const grants = await handler.listApprovalGrants();
|
|
1572
|
+
server._send(
|
|
1573
|
+
ws,
|
|
1574
|
+
envelopeResponse(
|
|
1575
|
+
CODING_AGENT_EVENT_TYPES.COMMAND_RESPONSE,
|
|
1576
|
+
id,
|
|
1577
|
+
{ success: true, revoked: result.grant, grants },
|
|
1500
1578
|
sessionId,
|
|
1501
1579
|
),
|
|
1502
1580
|
);
|
|
@@ -29,6 +29,11 @@ import { runnableTaskModel } from "../../lib/runnable-provider.js";
|
|
|
29
29
|
import { PlanState } from "../../lib/plan-mode.js";
|
|
30
30
|
import { CLISlotFiller } from "../../lib/slot-filler.js";
|
|
31
31
|
import { createAbortError, isAbortError } from "../../lib/abort-utils.js";
|
|
32
|
+
import { addHooksV2EventObserver } from "../../lib/hooks-v2-producers.js";
|
|
33
|
+
import {
|
|
34
|
+
projectHookPolicyDecision,
|
|
35
|
+
projectToolPolicyDecision,
|
|
36
|
+
} from "../../lib/policy-decision-event.js";
|
|
32
37
|
import {
|
|
33
38
|
resolveRegisteredHostHooksV2Workspace,
|
|
34
39
|
runWithHostHooksV2Workspace,
|
|
@@ -1081,6 +1086,7 @@ export class WSAgentHandler {
|
|
|
1081
1086
|
this._approvalGate = await createWsApprovalGate({
|
|
1082
1087
|
sessionId: this.session.id,
|
|
1083
1088
|
interaction: this.interaction,
|
|
1089
|
+
cwd: this.session.projectRoot,
|
|
1084
1090
|
});
|
|
1085
1091
|
}
|
|
1086
1092
|
return this._approvalGate;
|
|
@@ -1234,7 +1240,11 @@ export class WSAgentHandler {
|
|
|
1234
1240
|
});
|
|
1235
1241
|
const mcpRecoveryRuntime = this._ensureMcpRecoveryRuntime();
|
|
1236
1242
|
|
|
1237
|
-
// Run agent loop
|
|
1243
|
+
// Run agent loop. Turn-scoped approval grants are reset before the
|
|
1244
|
+
// model/tool boundary for every user message; session grants remain in
|
|
1245
|
+
// the verified authority ledger owned by the session-scoped gate.
|
|
1246
|
+
const approvalGate = await this._ensureApprovalGate();
|
|
1247
|
+
approvalGate?.beginTurn?.(requestId || `turn-${Date.now()}`);
|
|
1238
1248
|
const loopOptions = {
|
|
1239
1249
|
provider: session.provider,
|
|
1240
1250
|
model: activeModel,
|
|
@@ -1265,7 +1275,7 @@ export class WSAgentHandler {
|
|
|
1265
1275
|
sessionBudget: this._sessionBudget,
|
|
1266
1276
|
// P0 authority: null unless opted in (byte-identical default — agent
|
|
1267
1277
|
// core already defaults `options.approvalGate || null`).
|
|
1268
|
-
approvalGate
|
|
1278
|
+
approvalGate,
|
|
1269
1279
|
// Canonical WS history is compacted before ws_turn_prepare. Compaction
|
|
1270
1280
|
// inside agent-core would include the staged pending user, which is not
|
|
1271
1281
|
// part of the canonical message projection until turn settlement.
|
|
@@ -1435,7 +1445,23 @@ export class WSAgentHandler {
|
|
|
1435
1445
|
tool: event.tool,
|
|
1436
1446
|
result: event.result,
|
|
1437
1447
|
error: event.error,
|
|
1448
|
+
permission_decision_id: event.permission_decision_id || null,
|
|
1449
|
+
permission_decision: event.permission_decision || null,
|
|
1438
1450
|
});
|
|
1451
|
+
{
|
|
1452
|
+
const policyEvent = projectToolPolicyDecision(event, {
|
|
1453
|
+
sessionId: session.id,
|
|
1454
|
+
turnId: event.turn_id,
|
|
1455
|
+
toolUseId: event.tool_use_id,
|
|
1456
|
+
});
|
|
1457
|
+
if (policyEvent) {
|
|
1458
|
+
const { type: _type, ...payload } = policyEvent;
|
|
1459
|
+
this.interaction.emit("policy-decision", {
|
|
1460
|
+
requestId,
|
|
1461
|
+
...payload,
|
|
1462
|
+
});
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1439
1465
|
if (
|
|
1440
1466
|
event.tool === "todo_write" &&
|
|
1441
1467
|
currentTodoWrite &&
|
|
@@ -1583,13 +1609,29 @@ export class WSAgentHandler {
|
|
|
1583
1609
|
)
|
|
1584
1610
|
: executeAgentTurn();
|
|
1585
1611
|
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1612
|
+
const removeHookPolicyObserver = addHooksV2EventObserver(
|
|
1613
|
+
session.id,
|
|
1614
|
+
(event) => {
|
|
1615
|
+
const policyEvent = projectHookPolicyDecision(event);
|
|
1616
|
+
if (!policyEvent) return;
|
|
1617
|
+
const { type: _type, ...payload } = policyEvent;
|
|
1618
|
+
this.interaction.emit("policy-decision", {
|
|
1619
|
+
requestId,
|
|
1620
|
+
...payload,
|
|
1621
|
+
});
|
|
1622
|
+
},
|
|
1623
|
+
);
|
|
1624
|
+
try {
|
|
1625
|
+
if (session.mcpClient?.withElicitationContext) {
|
|
1626
|
+
await session.mcpClient.withElicitationContext(
|
|
1627
|
+
session.id,
|
|
1628
|
+
runAgentTurn,
|
|
1629
|
+
);
|
|
1630
|
+
} else {
|
|
1631
|
+
await runAgentTurn();
|
|
1632
|
+
}
|
|
1633
|
+
} finally {
|
|
1634
|
+
removeHookPolicyObserver();
|
|
1593
1635
|
}
|
|
1594
1636
|
if (session.canonicalJsonlSession === true && !canonicalTurn?.settled) {
|
|
1595
1637
|
const error = new Error(
|
|
@@ -1714,6 +1756,20 @@ export class WSAgentHandler {
|
|
|
1714
1756
|
}
|
|
1715
1757
|
}
|
|
1716
1758
|
|
|
1759
|
+
async listApprovalGrants() {
|
|
1760
|
+
const gate = await this._ensureApprovalGate();
|
|
1761
|
+
if (!gate?.listGrants) return [];
|
|
1762
|
+
return gate.listGrants();
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
async revokeApprovalGrant(grantId) {
|
|
1766
|
+
const gate = await this._ensureApprovalGate();
|
|
1767
|
+
if (!gate?.revokeGrant) {
|
|
1768
|
+
return { success: false, error: "Approval grant authority unavailable" };
|
|
1769
|
+
}
|
|
1770
|
+
return gate.revokeGrant(grantId);
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1717
1773
|
async interrupt() {
|
|
1718
1774
|
const wasProcessing = this._processing;
|
|
1719
1775
|
const interruptedRequestId = this._activeRequestId || null;
|
|
@@ -26,6 +26,32 @@
|
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
28
|
import { approvalBindingDigest } from "../../lib/agent-authority.js";
|
|
29
|
+
import {
|
|
30
|
+
APPROVAL_GRANTS_EVENT,
|
|
31
|
+
ApprovalGrantLedger,
|
|
32
|
+
approvalPermissionForContext,
|
|
33
|
+
} from "../../lib/approval-grant-ledger.js";
|
|
34
|
+
|
|
35
|
+
function approvalDecision(value) {
|
|
36
|
+
const candidate =
|
|
37
|
+
value?.decision && typeof value.decision === "object"
|
|
38
|
+
? value.decision
|
|
39
|
+
: value;
|
|
40
|
+
if (
|
|
41
|
+
candidate &&
|
|
42
|
+
[
|
|
43
|
+
"acceptOnce",
|
|
44
|
+
"acceptForTurn",
|
|
45
|
+
"acceptForSession",
|
|
46
|
+
"decline",
|
|
47
|
+
"cancel",
|
|
48
|
+
].includes(candidate.kind)
|
|
49
|
+
) {
|
|
50
|
+
return candidate;
|
|
51
|
+
}
|
|
52
|
+
if (value === true) return { kind: "acceptOnce" };
|
|
53
|
+
return { kind: "decline" };
|
|
54
|
+
}
|
|
29
55
|
|
|
30
56
|
/**
|
|
31
57
|
* Build the binding-attaching confirmer for one WS session.
|
|
@@ -35,9 +61,19 @@ import { approvalBindingDigest } from "../../lib/agent-authority.js";
|
|
|
35
61
|
* @param {string} opts.sessionId
|
|
36
62
|
* @returns {(ctx?: object) => Promise<boolean>}
|
|
37
63
|
*/
|
|
38
|
-
export function buildWsApprovalConfirmer({
|
|
64
|
+
export function buildWsApprovalConfirmer({
|
|
65
|
+
interaction,
|
|
66
|
+
sessionId,
|
|
67
|
+
cwd = null,
|
|
68
|
+
ledgerState = { ledger: new ApprovalGrantLedger({ sessionId }) },
|
|
69
|
+
persistApprovalGrants = () => false,
|
|
70
|
+
}) {
|
|
39
71
|
let approvalSeq = 0;
|
|
40
72
|
return async (ctx = {}) => {
|
|
73
|
+
const requiredPermission = approvalPermissionForContext(ctx, {
|
|
74
|
+
cwd: cwd || ctx.cwd || null,
|
|
75
|
+
});
|
|
76
|
+
if (ledgerState.ledger.allows(requiredPermission)) return true;
|
|
41
77
|
const command = ctx.command ?? ctx.args?.command ?? null;
|
|
42
78
|
const risk = ctx.riskLevel || ctx.risk || "unknown";
|
|
43
79
|
// Bind this approval to the exact call it authorizes (same recipe as the
|
|
@@ -51,22 +87,66 @@ export function buildWsApprovalConfirmer({ interaction, sessionId }) {
|
|
|
51
87
|
const what = ctx.tool || ctx.toolName || "tool";
|
|
52
88
|
const detail = command != null ? `: ${String(command).slice(0, 200)}` : "";
|
|
53
89
|
try {
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
90
|
+
const options = {
|
|
91
|
+
default: false,
|
|
92
|
+
binding,
|
|
93
|
+
// Structured context so UIs can render a proper approval card
|
|
94
|
+
// instead of parsing the question text. Reusable permissions are
|
|
95
|
+
// host-issued and exact; the renderer may choose a lifetime but may
|
|
96
|
+
// never widen this set.
|
|
97
|
+
approval: {
|
|
98
|
+
tool: what,
|
|
99
|
+
command,
|
|
100
|
+
risk,
|
|
101
|
+
rule: ctx.rule || null,
|
|
102
|
+
requestedPermissions: [requiredPermission],
|
|
67
103
|
},
|
|
104
|
+
};
|
|
105
|
+
const rawDecision = interaction.askApproval
|
|
106
|
+
? await interaction.askApproval(
|
|
107
|
+
`Approve ${what}${detail}? (risk: ${risk})`,
|
|
108
|
+
options,
|
|
109
|
+
)
|
|
110
|
+
: await interaction.askConfirm(
|
|
111
|
+
`Approve ${what}${detail}? (risk: ${risk})`,
|
|
112
|
+
options,
|
|
113
|
+
);
|
|
114
|
+
let decision = approvalDecision(rawDecision);
|
|
115
|
+
const approved = [
|
|
116
|
+
"acceptOnce",
|
|
117
|
+
"acceptForTurn",
|
|
118
|
+
"acceptForSession",
|
|
119
|
+
].includes(decision.kind);
|
|
120
|
+
if (
|
|
121
|
+
approved &&
|
|
122
|
+
(decision.kind === "acceptForTurn" ||
|
|
123
|
+
decision.kind === "acceptForSession")
|
|
124
|
+
) {
|
|
125
|
+
const priorSessionGrants = new Map(ledgerState.ledger.sessionGrants);
|
|
126
|
+
const priorRevision = ledgerState.ledger.revision;
|
|
127
|
+
const applied = ledgerState.ledger.applyDecision(
|
|
128
|
+
decision,
|
|
129
|
+
requiredPermission,
|
|
130
|
+
binding,
|
|
131
|
+
);
|
|
132
|
+
decision = applied.decision;
|
|
133
|
+
if (applied.granted.length === 0) return false;
|
|
134
|
+
if (applied.persistedScope && !persistApprovalGrants()) {
|
|
135
|
+
ledgerState.ledger.sessionGrants = priorSessionGrants;
|
|
136
|
+
ledgerState.ledger.revision = priorRevision;
|
|
137
|
+
// Match the stream-json contract: persistence failure never creates
|
|
138
|
+
// a phantom session grant, but the exact operation may proceed once.
|
|
139
|
+
decision = { kind: "acceptOnce" };
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
interaction.recordApprovalDecision?.({
|
|
143
|
+
binding,
|
|
144
|
+
decision,
|
|
145
|
+
requiredPermission,
|
|
146
|
+
});
|
|
147
|
+
return ["acceptOnce", "acceptForTurn", "acceptForSession"].includes(
|
|
148
|
+
decision.kind,
|
|
68
149
|
);
|
|
69
|
-
return ok === true;
|
|
70
150
|
} catch {
|
|
71
151
|
// timeout / disconnect / interrupt → fail closed, never approve
|
|
72
152
|
return false;
|
|
@@ -91,6 +171,7 @@ export function buildWsApprovalConfirmer({ interaction, sessionId }) {
|
|
|
91
171
|
export async function createWsApprovalGate({
|
|
92
172
|
sessionId,
|
|
93
173
|
interaction,
|
|
174
|
+
cwd = null,
|
|
94
175
|
deps = {},
|
|
95
176
|
}) {
|
|
96
177
|
try {
|
|
@@ -104,8 +185,59 @@ export async function createWsApprovalGate({
|
|
|
104
185
|
loadSessionCore(),
|
|
105
186
|
]);
|
|
106
187
|
const inner = await singletons.getApprovalGate();
|
|
188
|
+
const store =
|
|
189
|
+
deps.sessionStore ||
|
|
190
|
+
(await import("../../harness/jsonl-session-store.js"));
|
|
191
|
+
const ledgerState = {
|
|
192
|
+
ledger: new ApprovalGrantLedger({ sessionId }),
|
|
193
|
+
};
|
|
194
|
+
let approvalGrantPersistenceError = null;
|
|
195
|
+
try {
|
|
196
|
+
const event = store.findLatestEvent(
|
|
197
|
+
sessionId,
|
|
198
|
+
APPROVAL_GRANTS_EVENT,
|
|
199
|
+
(candidate) => candidate?.data && typeof candidate.data === "object",
|
|
200
|
+
);
|
|
201
|
+
if (event) {
|
|
202
|
+
ledgerState.ledger = ApprovalGrantLedger.fromJSON(event.data, {
|
|
203
|
+
sessionId,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
} catch (error) {
|
|
207
|
+
approvalGrantPersistenceError = error;
|
|
208
|
+
ledgerState.ledger = new ApprovalGrantLedger({ sessionId });
|
|
209
|
+
interaction.emit?.("recovery-degraded", {
|
|
210
|
+
component: "approval_grants",
|
|
211
|
+
error:
|
|
212
|
+
"Persisted approval grants could not be verified; all grants were discarded",
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
const persistApprovalGrants = () => {
|
|
216
|
+
if (approvalGrantPersistenceError) return false;
|
|
217
|
+
try {
|
|
218
|
+
const persisted = store.appendAuthorityEvent(
|
|
219
|
+
sessionId,
|
|
220
|
+
APPROVAL_GRANTS_EVENT,
|
|
221
|
+
ledgerState.ledger.toJSON(),
|
|
222
|
+
);
|
|
223
|
+
if (persisted === false) {
|
|
224
|
+
throw new Error("session store rejected approval grants");
|
|
225
|
+
}
|
|
226
|
+
return true;
|
|
227
|
+
} catch (error) {
|
|
228
|
+
approvalGrantPersistenceError = error;
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
};
|
|
107
232
|
const confirmer =
|
|
108
|
-
deps.confirmer ||
|
|
233
|
+
deps.confirmer ||
|
|
234
|
+
buildWsApprovalConfirmer({
|
|
235
|
+
interaction,
|
|
236
|
+
sessionId,
|
|
237
|
+
cwd,
|
|
238
|
+
ledgerState,
|
|
239
|
+
persistApprovalGrants,
|
|
240
|
+
});
|
|
109
241
|
const gate = new core.ApprovalGate({
|
|
110
242
|
defaultPolicy: core.APPROVAL_POLICY?.STRICT || "strict",
|
|
111
243
|
confirm: confirmer,
|
|
@@ -129,6 +261,39 @@ export async function createWsApprovalGate({
|
|
|
129
261
|
getSessionPolicy: (sid) => inner.getSessionPolicy(sid || sessionId),
|
|
130
262
|
setSessionPolicy: (sid, policy) =>
|
|
131
263
|
inner.setSessionPolicy(sid || sessionId, policy),
|
|
264
|
+
beginTurn: (turnId) => ledgerState.ledger.beginTurn(turnId),
|
|
265
|
+
listGrants: () => ledgerState.ledger.listGrants(),
|
|
266
|
+
revokeGrant: (grantId) => {
|
|
267
|
+
const existing = ledgerState.ledger
|
|
268
|
+
.listGrants()
|
|
269
|
+
.find((grant) => grant.grantId === String(grantId || ""));
|
|
270
|
+
if (!existing) {
|
|
271
|
+
return { success: false, error: "Approval grant was not found" };
|
|
272
|
+
}
|
|
273
|
+
if (existing.lifetime === "turn") {
|
|
274
|
+
const result = ledgerState.ledger.revoke(grantId);
|
|
275
|
+
return { success: result.revoked, grant: result.grant };
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const candidate = ApprovalGrantLedger.fromJSON(
|
|
279
|
+
ledgerState.ledger.toJSON(),
|
|
280
|
+
{ sessionId },
|
|
281
|
+
);
|
|
282
|
+
const result = candidate.revoke(grantId);
|
|
283
|
+
if (!result.revoked) {
|
|
284
|
+
return { success: false, error: "Approval grant was not found" };
|
|
285
|
+
}
|
|
286
|
+
const previous = ledgerState.ledger;
|
|
287
|
+
ledgerState.ledger = candidate;
|
|
288
|
+
if (!persistApprovalGrants()) {
|
|
289
|
+
ledgerState.ledger = previous;
|
|
290
|
+
return {
|
|
291
|
+
success: false,
|
|
292
|
+
error: "Approval grant revocation could not be persisted",
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
return { success: true, grant: result.grant };
|
|
296
|
+
},
|
|
132
297
|
};
|
|
133
298
|
} catch {
|
|
134
299
|
return null; // degrade to the legacy no-gate path
|
|
@@ -53,6 +53,8 @@ import {
|
|
|
53
53
|
handleSessionClose,
|
|
54
54
|
handleSessionInterrupt,
|
|
55
55
|
handleSessionAnswer,
|
|
56
|
+
handleApprovalGrantsList,
|
|
57
|
+
handleApprovalGrantRevoke,
|
|
56
58
|
handleHostToolResult,
|
|
57
59
|
handleSubAgentList,
|
|
58
60
|
handleSubAgentGet,
|
|
@@ -746,9 +748,8 @@ export class ChainlessChainWSServer extends EventEmitter {
|
|
|
746
748
|
/** Read the same static + scoped authority used by the Agent Core. */
|
|
747
749
|
async _handlePermissionRulesGet(id, ws) {
|
|
748
750
|
try {
|
|
749
|
-
const { loadPermissionAuthority } =
|
|
750
|
-
"../../lib/permission-authority.js"
|
|
751
|
-
);
|
|
751
|
+
const { loadPermissionAuthority } =
|
|
752
|
+
await import("../../lib/permission-authority.js");
|
|
752
753
|
const loaded = loadPermissionAuthority({ cwd: this.projectRoot });
|
|
753
754
|
this._send(ws, {
|
|
754
755
|
id,
|
|
@@ -1416,6 +1417,16 @@ export class ChainlessChainWSServer extends EventEmitter {
|
|
|
1416
1417
|
return handleSessionAnswer(this, id, ws, message);
|
|
1417
1418
|
}
|
|
1418
1419
|
|
|
1420
|
+
/** @private */
|
|
1421
|
+
_handleApprovalGrantsList(id, ws, message) {
|
|
1422
|
+
return handleApprovalGrantsList(this, id, ws, message);
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
/** @private */
|
|
1426
|
+
_handleApprovalGrantRevoke(id, ws, message) {
|
|
1427
|
+
return handleApprovalGrantRevoke(this, id, ws, message);
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1419
1430
|
_handleHostToolResult(id, ws, message) {
|
|
1420
1431
|
return handleHostToolResult(this, id, ws, message);
|
|
1421
1432
|
}
|
|
@@ -1498,9 +1509,8 @@ export class ChainlessChainWSServer extends EventEmitter {
|
|
|
1498
1509
|
/** @private — ping/pong heartbeat to detect dead connections */
|
|
1499
1510
|
async _ensureTaskManager() {
|
|
1500
1511
|
if (this._taskManager) return this._taskManager;
|
|
1501
|
-
const { BackgroundTaskManager } =
|
|
1502
|
-
"../../harness/background-task-manager.js"
|
|
1503
|
-
);
|
|
1512
|
+
const { BackgroundTaskManager } =
|
|
1513
|
+
await import("../../harness/background-task-manager.js");
|
|
1504
1514
|
this._taskManager = new BackgroundTaskManager({
|
|
1505
1515
|
recoverOnStart: true,
|
|
1506
1516
|
policyCwd: this.projectRoot,
|