chainlesschain 0.162.175 → 0.162.176
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 +10 -10
- package/src/assets/web-panel/assets/{AIOps-DherW0Rh.js → AIOps-BDLu5Elz.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CDGfqt2Y.js → ActionButton-DH5us-CK.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-BYhkzdgD.js → Analytics-BZ0u8IFG.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-cEKk1cpb.js → AppLayout-Duu8xR14.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-_aXR3WWc.js → Artifacts-Br2YBbh_.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CYAf-gY7.js → Audit-C3C6a482.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-D4Q20phR.js → BackgroundAgents-CzHvebcj.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-Cq0Tyk58.js → Backup-DZNHYDFd.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-CPj_CdAv.js → BaseInput-VRiC4fIx.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-BQ-Qq0es.js → Chat-Cm08WWAD.js} +4 -4
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-Ci97vNTs.js → ChatBubbleRenderer-CGHYrugQ.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-rke6l3yg.js → Checkbox-DtByk7d7.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-DiacrIPq.js → Codegen-CphXXOfD.js} +1 -1
- package/src/assets/web-panel/assets/{Col-Cx3BY-Up.js → Col-Hz86TnLR.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DfmWiQy8.js → Community-HP03ltpD.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DdQnpxy5.js → Compact-B_N1mqQz.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-lzliOH_r.js → Compliance-CVztRpi8.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-CYx4Un5k.js → Cowork-wUVOyZih.js} +4 -4
- package/src/assets/web-panel/assets/{Cron-BGDcPFlo.js → Cron-DW5TLJKw.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-0_X5g2ri.js → Crosschain-CrAFGhWH.js} +1 -1
- package/src/assets/web-panel/assets/{DID-C0PEf3Eu.js → DID-pA-oD8ke.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-DULQjQ58.js → Dashboard-CXrd5gAw.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DGRHRbW6.js → Dropdown-EweJcsek.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-ChX8XPwB.js → EmailListRenderer-C9xVLPG4.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-Dyq6IBNu.js → FamilyGuardDashboard-CDcEEqlu.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DH1NfAL2.js → Federation-DtZda9A_.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-BN1I_uNi.js → FormItemContext-CiYdcVz3.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-Dq_2UYpe.js → GenericCardRenderer-DA13uwA0.js} +1 -1
- package/src/assets/web-panel/assets/{Git-BAy1yvI2.js → Git-DzRhZD1O.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-Db6Q2iSy.js → Governance-D5RMgOSb.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-0ub6yHcr.js → Inference-BgrPfSNk.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DtLetM36.js → KnowledgeGraph-DzjnD571.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-Bcoy7CUd.js → Logs-BhWzVDtN.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-BfEMFAXf.js → MarkdownRenderer-BDape9cx.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-tt2rzwRR.js → Marketplace-DJtL5GV7.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-BhOgX-MU.js → McpTools-CZcQygI7.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-BJUxeWBL.js → Memory-DUWSDUUu.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BwUY2G9w.js → MobileBridge-BTwq2WKY.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-NZvvfDME.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-B2WMboOm.js → Mtc-BiGugEQm.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-8pNEXO63.js → MtcAudit-DY7a6gUe.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-C1wm5a_1.js → Multisig-BQbDu_w7.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-C1QpKF7g.js → NLProgramming-CM2wXTLv.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CiQUcxFu.js → Notes-DI6gGs1v.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-BblDPJ_x.js → NotificationSettings-BsZOLWAB.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DRjYcPtb.js → OrderTableRenderer-C48mu09U.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-Dp3VKB0X.js → Organization-Cds0_tXr.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Czx161m9.js → Overflow-WunYMD87.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-ClFi6wOs.js → P2P-Bo6j4DDv.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-CRweW0lz.js → PdhVaultBrowser-Bh2XPD5f.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-BzcRoqTn.js → Permissions-EMvMMC8N.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-ChGTpNMd.js → PersonalDataHub-AX3ypUDV.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-BMOOpKWA.js → Pipeline-BOx8HOgL.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-D0AZHObH.js → Privacy-tBeTVQVM.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-yYFlZ6Ja.js → ProjectInit-CVYg1W4M.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-DJNVuMQs.js → ProjectSettings-Dvt5I7y1.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-Br0rBWH1.js → Projects-Cc7FC9-e.js} +1 -1
- package/src/assets/web-panel/assets/Providers-Ct8xqY-E.js +1 -0
- package/src/assets/web-panel/assets/{QrScannerModal-81NZOitV.js → QrScannerModal-Cni8Ooja.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-Dic2lCbJ.js → QuickAsk-BJVLKdxr.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Dh9iwViE.js → Recommend-DPG8Rbbm.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-Bq9VYEFy.js → RemoteSession-DsdR7dCt.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-CxFZ-NbJ.js → Reputation-Csg1YM-b.js} +1 -1
- package/src/assets/web-panel/assets/{Row-BVSLcaX2.js → Row-D9DoFoEf.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BbC-5DOH.js → RssFeed-BsvKrXMS.js} +3 -3
- package/src/assets/web-panel/assets/{Search-BfjZ1GCr.js → Search-DFUStfgQ.js} +1 -1
- package/src/assets/web-panel/assets/{Security-CVjhOV5r.js → Security-ILg1zxdK.js} +4 -4
- package/src/assets/web-panel/assets/{Services-D45u-Aqe.js → Services-Dd41PCaY.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-WkGoK4he.js → Skeleton-Bzo1cN80.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-D_jvQZcj.js → Skills-BDHh17P0.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-Bf4QTF3E.js → Sla-jl7UTiRY.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DVpZdbMN.js → SpeechSettings-BePa-RF6.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DEEojoMS.js → SyncSettings-DiqqDKGZ.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-DFwxpLIk.js → Tasks-DYQ_6lxj.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-Bzl-9wY5.js → Templates-JiDeI06L.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-0khxUOB8.js → Tenant-hhgI6zwS.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-CjTZPa37.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-B0Y4LONc.js → TimelineRenderer-B8uB5Llk.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DEE07SFh.js → Tokens-C3b_6r2z.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BM7xvA5z.js → Trigger-tIP7HKVe.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-Dv3ijvvZ.js → Trust-vjoc11vJ.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B1-enmMt.js → UkeySign-DUPBnGuH.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DYiIPByd.js → VideoEditing-CBvhUY5T.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-D-y374BQ.js → Wallet-DUaQ0uA5.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-HBDjcUhi.js → WebAuthn-DllSivjE.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-sKn4qTID.js → WorkflowEditor-xc8D3uO6.js} +1 -1
- package/src/assets/web-panel/assets/{chat-TVYhaBXj.js → chat-BVicU7oA.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DMADxY9v.js → colors-DJzLmhLm.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-OftcHpO_.js → compact-item-BvYRfThE.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DW1zVUSN.js → createContext-DGXxCBKR.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BT46Y_QI.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-CaUathNp.js → hasIn-SBDJB1y4.js} +1 -1
- package/src/assets/web-panel/assets/{index-CeCIYYG7.js → index-1SdDS6lR.js} +1 -1
- package/src/assets/web-panel/assets/{index-DAfT3EMd.js → index-9gdI7uUW.js} +1 -1
- package/src/assets/web-panel/assets/index-B7nuIywP.js +1 -0
- package/src/assets/web-panel/assets/{index-sm1sGIxW.js → index-BJZf9DhV.js} +1 -1
- package/src/assets/web-panel/assets/{index-BBNg08cD.js → index-BO1itZaY.js} +3 -3
- package/src/assets/web-panel/assets/{index-CKNdnJRo.js → index-BTrBGBJs.js} +1 -1
- package/src/assets/web-panel/assets/{index--5UvwqH_.js → index-BYqz4Wrr.js} +1 -1
- package/src/assets/web-panel/assets/{index-8YelceUU.js → index-Bf-ctERC.js} +1 -1
- package/src/assets/web-panel/assets/{index-Lr0MO-GU.js → index-CKyEivf8.js} +1 -1
- package/src/assets/web-panel/assets/{index-DZdT8nio.js → index-CdGY9P8a.js} +1 -1
- package/src/assets/web-panel/assets/{index-s-EnkUCn.js → index-Cf-O_g_8.js} +1 -1
- package/src/assets/web-panel/assets/{index-pSVCBsG4.js → index-CloCgBUR.js} +1 -1
- package/src/assets/web-panel/assets/{index-B-19mFhn.js → index-CoJAO1Lm.js} +1 -1
- package/src/assets/web-panel/assets/{index-DKjqFpYa.js → index-Crk5NTb0.js} +1 -1
- package/src/assets/web-panel/assets/{index-BJ1PjRY3.js → index-Cs2rmLFt.js} +1 -1
- package/src/assets/web-panel/assets/{index-77kgkUgY.js → index-CtwqO5qo.js} +1 -1
- package/src/assets/web-panel/assets/{index-D63QVAiJ.js → index-D7HimK0M.js} +1 -1
- package/src/assets/web-panel/assets/{index-B52Ztt8Q.js → index-DCdRAgjy.js} +1 -1
- package/src/assets/web-panel/assets/{index-DHi634g9.js → index-DCqRS6da.js} +1 -1
- package/src/assets/web-panel/assets/{index-BFVbDpqg.js → index-DHVLJ8q0.js} +1 -1
- package/src/assets/web-panel/assets/{index-BvRw4Fna.js → index-DKrvvWm4.js} +1 -1
- package/src/assets/web-panel/assets/{index-CZXYI5LU.js → index-DMarmfrv.js} +1 -1
- package/src/assets/web-panel/assets/{index-CM8W07sc.js → index-DRfiXB_p.js} +1 -1
- package/src/assets/web-panel/assets/{index-iDmgT2Dg.js → index-Dm_77jgR.js} +1 -1
- package/src/assets/web-panel/assets/{index-hXq7QRA_.js → index-DnjPdvR6.js} +1 -1
- package/src/assets/web-panel/assets/{index-BEzLLVYd.js → index-DonCnfMr.js} +1 -1
- package/src/assets/web-panel/assets/{index-DYwwUKDg.js → index-DvUTDYXX.js} +1 -1
- package/src/assets/web-panel/assets/{index-DXcqvWBp.js → index-FxZzRyE1.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cmdv6Dev.js → index-MjC4G09d.js} +1 -1
- package/src/assets/web-panel/assets/{index-C9JoaYSs.js → index-VMfwIH5G.js} +1 -1
- package/src/assets/web-panel/assets/{index-CK-p7Hji.js → index-YJkzy8ZF.js} +1 -1
- package/src/assets/web-panel/assets/{index-BupSWDcl.js → index-d5BVd-cL.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bg-7FpaL.js → index-e4fXH_WO.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpDtN0dl.js → index-hxTODbM1.js} +1 -1
- package/src/assets/web-panel/assets/{index-kdMl_0zL.js → index-lpaGoTH3.js} +1 -1
- package/src/assets/web-panel/assets/{index-GUKz4Pv9.js → index-wcCL-miV.js} +1 -1
- package/src/assets/web-panel/assets/{index-DWVZ3T0t.js → index-xfluRkCT.js} +1 -1
- package/src/assets/web-panel/assets/index-ycwAfC-i.js +1 -0
- package/src/assets/web-panel/assets/{index-BSp1Ofvx.js → index-z1ZylsLq.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DdcKTlQR.js → initDefaultProps-C1zO1KnY.js} +1 -1
- package/src/assets/web-panel/assets/{motion-CL-hTBQj.js → motion-CWLtEGmC.js} +1 -1
- package/src/assets/web-panel/assets/{move-qYSAkxNG.js → move-DzD_C3Vm.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-ZwRSZtRP.js → mtc-parser-D880PYJl.js} +1 -1
- package/src/assets/web-panel/assets/{omit-Bld-8ftI.js → omit-CFR_z2ov.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DGHs-a9Z.js → pickAttrs-srIhgrSC.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DRQPMyI5.js → placementArrow-C1rXpibP.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-C5MJG_Yo.js → responsiveObserve-C30gRcSS.js} +1 -1
- package/src/assets/web-panel/assets/{slide-VZ-fpZCD.js → slide-CvtKiMfV.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-9ocfCyHk.js → statusUtils-DNHO7ITG.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-B6QAwAN5.js → styleChecker-Dt_Sl-g4.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-Bq1twor3.js → useFlexGapSupport-Cjev42Gh.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DKZq96tz.js → useFs-Baxglj2V.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-D0RmRVXf.js → usePersonalDataHub-B4NkcLaP.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-D6kEj_tt.js → vnode-mIRkdT7o.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-2yfasoQf.js → zoom-HzI5DlH_.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/auth/npm-auth.js +30 -5
- package/src/commands/agenda.js +64 -2
- package/src/commands/agent.js +39 -1
- package/src/commands/config.js +70 -5
- package/src/commands/context.js +36 -2
- package/src/commands/hub.js +19 -1
- package/src/commands/memory.js +21 -6
- package/src/commands/permissions.js +57 -1
- package/src/commands/plugin.js +2 -0
- package/src/commands/review.js +23 -11
- package/src/commands/routine.js +31 -8
- package/src/commands/session.js +11 -3
- package/src/commands/team.js +20 -7
- package/src/commands/update.js +65 -10
- package/src/gateways/terminal/PtyManager.js +8 -1
- package/src/gateways/ws/message-dispatcher.js +3 -0
- package/src/gateways/ws/session-protocol.js +26 -0
- package/src/gateways/ws/ws-agent-handler.js +107 -69
- package/src/gateways/ws/ws-server.js +74 -2
- package/src/harness/jsonl-session-store.js +13 -6
- package/src/harness/mcp-client.js +200 -1
- package/src/lib/__tests__/personal-data-hub-aichat-wizard.test.js +15 -0
- package/src/lib/agent-coordinator.js +4 -0
- package/src/lib/agent-ipc-bus.js +32 -2
- package/src/lib/agent-sandbox.js +16 -2
- package/src/lib/agent-schedule-store.js +55 -0
- package/src/lib/agent-tool-admission.js +104 -0
- package/src/lib/api-key-helper.js +10 -2
- package/src/lib/async-hook-supervisor.cjs +12 -2
- package/src/lib/changelog.js +19 -11
- package/src/lib/channels/channel-manager.js +6 -0
- package/src/lib/channels/telegram-channel.js +11 -1
- package/src/lib/channels/webhook-channel.js +15 -3
- package/src/lib/checkpoint-store.js +10 -2
- package/src/lib/cloud/bundle.js +12 -2
- package/src/lib/code-review.js +32 -8
- package/src/lib/computer-use/control-backend.js +18 -3
- package/src/lib/context-breakdown.js +46 -0
- package/src/lib/context-source-ledger.js +43 -0
- package/src/lib/diff-review-follow-up.js +154 -0
- package/src/lib/downloader.js +17 -3
- package/src/lib/ensure-utf8.js +11 -3
- package/src/lib/event-runtime-producer.js +58 -0
- package/src/lib/event-runtime-store.js +354 -0
- package/src/lib/event-runtime-worker.js +109 -0
- package/src/lib/execution-backend.js +72 -21
- package/src/lib/git-integration.js +19 -4
- package/src/lib/hook-manager.js +6 -15
- package/src/lib/hook-runner.cjs +48 -3
- package/src/lib/hooks-v2-producers.js +15 -0
- package/src/lib/hooks-v2-runtime.js +70 -21
- package/src/lib/host-adb-bridge.js +111 -21
- package/src/lib/ide-context.js +128 -1
- package/src/lib/interaction-adapter.js +39 -0
- package/src/lib/json-schema-validate.js +190 -36
- package/src/lib/lan-pairing-preflight.js +13 -2
- package/src/lib/lsp/__tests__/lsp-server-registry.test.js +18 -0
- package/src/lib/lsp/lsp-client.js +18 -1
- package/src/lib/lsp/lsp-manager.js +4 -0
- package/src/lib/lsp/lsp-server-registry.js +11 -0
- package/src/lib/mcp-oauth.js +8 -2
- package/src/lib/npm-invocation.js +29 -0
- package/src/lib/packer/pkg-runner.js +13 -2
- package/src/lib/packer/precheck.js +33 -16
- package/src/lib/packer/web-panel-builder.js +16 -2
- package/src/lib/permission-rules.cjs +5 -1
- package/src/lib/personal-data-hub-aichat-wizard.js +22 -6
- package/src/lib/personal-data-hub-wiring.js +27 -3
- package/src/lib/plan-mode.js +204 -11
- package/src/lib/plugin-monitor-supervisor.js +39 -4
- package/src/lib/plugin-runtime/bin.js +45 -0
- package/src/lib/plugin-runtime/hooks.js +14 -1
- package/src/lib/plugin-runtime/install.js +2 -1
- package/src/lib/plugin-runtime/lsp.js +3 -0
- package/src/lib/plugin-runtime/mcp.js +8 -1
- package/src/lib/plugin-runtime/monitors.js +4 -0
- package/src/lib/plugin-runtime/plugin-options.js +74 -7
- package/src/lib/plugin-runtime/signature.js +45 -0
- package/src/lib/pr-create.js +21 -8
- package/src/lib/pr-link-ledger.js +15 -3
- package/src/lib/process-execution-broker/credential-agent.js +23 -3
- package/src/lib/process-execution-broker/index.js +315 -38
- package/src/lib/process-execution-broker/patch-child-process.js +2 -3
- package/src/lib/process-manager.js +18 -3
- package/src/lib/publish-workspace.js +14 -6
- package/src/lib/secret-store.js +159 -0
- package/src/lib/service-manager.js +64 -29
- package/src/lib/settings-hook-events.cjs +61 -1
- package/src/lib/settings-hooks.cjs +4 -0
- package/src/lib/side-effect-ledger.js +22 -0
- package/src/lib/sub-agent-context.js +5 -0
- package/src/lib/sub-agent-profiles.js +4 -0
- package/src/lib/turn-context.js +14 -8
- package/src/lib/unattended-action-policy.js +83 -0
- package/src/lib/update-notice.js +6 -2
- package/src/lib/with-file-lock.js +7 -0
- package/src/lib/ws-server.js +1 -0
- package/src/repl/agent-repl.js +32 -0
- package/src/repl/clipboard-copy.js +8 -2
- package/src/repl/pr-comments.js +30 -7
- package/src/runtime/agent-core.js +439 -87
- package/src/runtime/agent-runtime.js +1 -0
- package/src/runtime/coding-agent-contract-shared.cjs +52 -0
- package/src/runtime/coding-agent-policy.cjs +20 -0
- package/src/runtime/diagnostics.js +73 -8
- package/src/runtime/headless-runner.js +63 -0
- package/src/runtime/headless-stream.js +269 -17
- package/src/runtime/mcp-config.js +16 -1
- package/src/assets/web-panel/assets/MobileProjects-BLRfHhqi.js +0 -1
- package/src/assets/web-panel/assets/Providers-zZRhNtSu.js +0 -1
- package/src/assets/web-panel/assets/Terminal-DWGYhAYU.js +0 -3
- package/src/assets/web-panel/assets/devWarning-CLOk6rdE.js +0 -1
- package/src/assets/web-panel/assets/index-CSgUfMTM.js +0 -1
- package/src/assets/web-panel/assets/index-DliSZvAP.js +0 -1
package/src/lib/hook-manager.js
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import crypto from "crypto";
|
|
7
|
-
import { execSync } from "child_process";
|
|
8
7
|
import broker from "./process-execution-broker/index.js";
|
|
9
8
|
|
|
10
9
|
/**
|
|
@@ -275,8 +274,8 @@ export async function executeHook(hook, context = {}) {
|
|
|
275
274
|
const type = hook.type || HookType.SYNC;
|
|
276
275
|
|
|
277
276
|
if (type === HookType.COMMAND || type === HookType.SCRIPT) {
|
|
278
|
-
// Command/script hooks execute a shell command
|
|
279
|
-
//
|
|
277
|
+
// Command/script hooks execute a shell command through the shared
|
|
278
|
+
// process broker on the tool-use hot path.
|
|
280
279
|
const cmd = hook.handler || "";
|
|
281
280
|
if (!cmd) {
|
|
282
281
|
return {
|
|
@@ -291,18 +290,10 @@ export async function executeHook(hook, context = {}) {
|
|
|
291
290
|
HOOK_EVENT: hook.event,
|
|
292
291
|
HOOK_CONTEXT: JSON.stringify(context),
|
|
293
292
|
};
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
command: cmd,
|
|
299
|
-
args: [],
|
|
300
|
-
startedAt: Date.now(),
|
|
301
|
-
sessionId: context?.sessionId,
|
|
302
|
-
};
|
|
303
|
-
if (typeof broker._recordAudit === "function")
|
|
304
|
-
broker._recordAudit(auditEntry);
|
|
305
|
-
const output = execSync(cmd, {
|
|
293
|
+
const output = broker.execSync(cmd, {
|
|
294
|
+
origin: "hook-manager:command",
|
|
295
|
+
scope: "hook",
|
|
296
|
+
policy: "allow",
|
|
306
297
|
encoding: "utf-8",
|
|
307
298
|
timeout: hook.timeout || 20000,
|
|
308
299
|
// execSync defaults maxBuffer to 1 MB; a hook that prints more (a
|
package/src/lib/hook-runner.cjs
CHANGED
|
@@ -232,7 +232,21 @@ function _runCommandHookInner(command, input = {}, opts = {}) {
|
|
|
232
232
|
CLAUDE_HOOK_EVENT: event || input.hook_event_name || "",
|
|
233
233
|
},
|
|
234
234
|
};
|
|
235
|
-
|
|
235
|
+
const brokerOptions = {
|
|
236
|
+
...common,
|
|
237
|
+
origin: opts.origin || "hook",
|
|
238
|
+
policy: opts.origin === "plugin:hook" ? "allow" : undefined,
|
|
239
|
+
pluginId: opts.pluginId || null,
|
|
240
|
+
pluginVersion: opts.pluginVersion || null,
|
|
241
|
+
pluginSource: opts.pluginSource || null,
|
|
242
|
+
};
|
|
243
|
+
if (opts.broker && opts.origin === "plugin:hook") {
|
|
244
|
+
res = opts.broker.spawnSync(
|
|
245
|
+
usePowershell ? buildPowershellArgv(command, shellKind, { executionPolicy: loadShellConfig({ cwd: common.cwd }).executionPolicy }).file : command,
|
|
246
|
+
usePowershell ? buildPowershellArgv(command, shellKind, { executionPolicy: loadShellConfig({ cwd: common.cwd }).executionPolicy }).argv : [],
|
|
247
|
+
brokerOptions,
|
|
248
|
+
);
|
|
249
|
+
} else if (usePowershell) {
|
|
236
250
|
// Per-hook `shell: powershell|pwsh` (settings hook entry): explicit argv
|
|
237
251
|
// instead of the default shell; the enterprise ExecutionPolicy override
|
|
238
252
|
// (settings shell.powershell.executionPolicy) applies here too.
|
|
@@ -352,9 +366,30 @@ async function _runCommandHookInnerAsync(command, input = {}, opts = {}) {
|
|
|
352
366
|
if (usePowershell) {
|
|
353
367
|
const { executionPolicy } = loadShellConfig({ cwd: wd });
|
|
354
368
|
const inv = buildPowershellArgv(command, shellKind, { executionPolicy });
|
|
355
|
-
child =
|
|
369
|
+
child = opts.broker && opts.origin === "plugin:hook"
|
|
370
|
+
? opts.broker.spawn(inv.file, inv.argv, {
|
|
371
|
+
cwd: wd,
|
|
372
|
+
env: spawnEnv,
|
|
373
|
+
origin: opts.origin,
|
|
374
|
+
policy: "allow",
|
|
375
|
+
pluginId: opts.pluginId || null,
|
|
376
|
+
pluginVersion: opts.pluginVersion || null,
|
|
377
|
+
pluginSource: opts.pluginSource || null,
|
|
378
|
+
})
|
|
379
|
+
: _deps.spawn(inv.file, inv.argv, { cwd: wd, env: spawnEnv });
|
|
356
380
|
} else {
|
|
357
|
-
child =
|
|
381
|
+
child = opts.broker && opts.origin === "plugin:hook"
|
|
382
|
+
? opts.broker.spawn(command, [], {
|
|
383
|
+
cwd: wd,
|
|
384
|
+
env: spawnEnv,
|
|
385
|
+
shell: true,
|
|
386
|
+
origin: opts.origin,
|
|
387
|
+
policy: "allow",
|
|
388
|
+
pluginId: opts.pluginId || null,
|
|
389
|
+
pluginVersion: opts.pluginVersion || null,
|
|
390
|
+
pluginSource: opts.pluginSource || null,
|
|
391
|
+
})
|
|
392
|
+
: _deps.spawn(command, { cwd: wd, env: spawnEnv, shell: true });
|
|
358
393
|
}
|
|
359
394
|
} catch (err) {
|
|
360
395
|
return {
|
|
@@ -444,6 +479,11 @@ function runHooks(commandHooks, input = {}, opts = {}) {
|
|
|
444
479
|
const runOne = (h) =>
|
|
445
480
|
runCommandHook(h.command, input, {
|
|
446
481
|
...opts,
|
|
482
|
+
broker: opts.broker,
|
|
483
|
+
origin: h.origin,
|
|
484
|
+
pluginId: h.pluginId,
|
|
485
|
+
pluginVersion: h.pluginVersion,
|
|
486
|
+
pluginSource: h.pluginSource,
|
|
447
487
|
timeout: h.timeout != null ? h.timeout * 1000 : opts.timeout,
|
|
448
488
|
// per-hook shell selection (P1 #8): `{ "type":"command", "command":…,
|
|
449
489
|
// "shell":"powershell" }` in the settings hook entry
|
|
@@ -504,6 +544,11 @@ async function runHooksParallel(commandHooks, input = {}, opts = {}) {
|
|
|
504
544
|
hooks.map((h) =>
|
|
505
545
|
runCommandHookAsync(h.command, input, {
|
|
506
546
|
...opts,
|
|
547
|
+
broker: opts.broker,
|
|
548
|
+
origin: h.origin,
|
|
549
|
+
pluginId: h.pluginId,
|
|
550
|
+
pluginVersion: h.pluginVersion,
|
|
551
|
+
pluginSource: h.pluginSource,
|
|
507
552
|
timeout: h.timeout != null ? h.timeout * 1000 : opts.timeout,
|
|
508
553
|
shell: h.shell != null ? h.shell : opts.shell,
|
|
509
554
|
}).then((r) => ({ h, r })),
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Best-effort bridge from real runtime producers to Hooks v2.
|
|
3
|
+
* Hook failures never change the surrounding agent or interaction result.
|
|
4
|
+
*/
|
|
5
|
+
export function emitHooksV2Event(eventName, context = {}, options = {}) {
|
|
6
|
+
void import("./hooks-v2-runtime.js")
|
|
7
|
+
.then(({ default: runtime }) => {
|
|
8
|
+
if (!runtime || typeof runtime.executeHooks !== "function") return;
|
|
9
|
+
return runtime.executeHooks(eventName, context, options);
|
|
10
|
+
})
|
|
11
|
+
.catch(() => {
|
|
12
|
+
// Hooks are an optional extension; producer delivery is best-effort.
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
@@ -24,10 +24,12 @@ import crypto from "node:crypto";
|
|
|
24
24
|
import fs from "node:fs/promises";
|
|
25
25
|
import path from "node:path";
|
|
26
26
|
import broker from "./process-execution-broker/index.js";
|
|
27
|
+
import { EventRuntimeStore } from "./event-runtime-store.js";
|
|
27
28
|
|
|
28
29
|
const VALID_HOOK_EVENTS = new Set([
|
|
29
30
|
// Session
|
|
30
|
-
"PreToolUse", "PostToolUse", "Notification", "Stop", "SubagentStop",
|
|
31
|
+
"PreToolUse", "PostToolUse", "Notification", "Stop", "SubagentStart", "SubagentStop",
|
|
32
|
+
"SessionResume", "SessionPause", "PostCompact",
|
|
31
33
|
// Auth
|
|
32
34
|
"PreCommit", "PostCommit",
|
|
33
35
|
// Skill
|
|
@@ -35,24 +37,33 @@ const VALID_HOOK_EVENTS = new Set([
|
|
|
35
37
|
// Model
|
|
36
38
|
"PreCompact", "ModelSelection",
|
|
37
39
|
// Config
|
|
38
|
-
"ConfigChange", "PermissionAllow", "PermissionDeny",
|
|
40
|
+
"ConfigChange", "PermissionAllow", "PermissionDeny", "PermissionRequest", "PermissionDenied",
|
|
39
41
|
// Timeline
|
|
40
42
|
"TimelineEntry",
|
|
41
43
|
// MCP
|
|
42
|
-
"McpRequest", "McpResponse",
|
|
44
|
+
"McpRequest", "McpResponse", "MCPElicitation",
|
|
45
|
+
// Task / workspace lifecycle
|
|
46
|
+
"TaskCreated", "TaskCompleted", "InstructionsLoaded", "CwdChanged",
|
|
47
|
+
"WorktreeCreate", "WorktreeRemove",
|
|
43
48
|
]);
|
|
44
49
|
|
|
45
50
|
const VALID_EXECUTOR_TYPES = new Set(["command", "http", "prompt", "agent", "js"]);
|
|
46
51
|
|
|
47
52
|
class HooksV2Runtime extends EventEmitter {
|
|
48
|
-
constructor(configDir) {
|
|
53
|
+
constructor(configDir, options = {}) {
|
|
49
54
|
super();
|
|
50
55
|
this.configDir = configDir;
|
|
56
|
+
this.durableStore = options.durableStore || null;
|
|
51
57
|
this.hooks = new Map(); // eventName -> HookDefinition[]
|
|
52
58
|
this.executionLog = [];
|
|
53
59
|
this._loaded = false;
|
|
54
60
|
}
|
|
55
61
|
|
|
62
|
+
setDurableStore(store) {
|
|
63
|
+
this.durableStore = store || null;
|
|
64
|
+
return this.durableStore;
|
|
65
|
+
}
|
|
66
|
+
|
|
56
67
|
/**
|
|
57
68
|
* @typedef {Object} HookDefinition
|
|
58
69
|
* @property {string} id
|
|
@@ -132,17 +143,29 @@ class HooksV2Runtime extends EventEmitter {
|
|
|
132
143
|
* @param {Object} context - event context (tool_name, tool_input, session_id, etc.)
|
|
133
144
|
* @returns {Promise<{results: Array, blocked: boolean, blockingResult?: any}>}
|
|
134
145
|
*/
|
|
135
|
-
async emitEvent(eventName, context = {}) {
|
|
146
|
+
async emitEvent(eventName, context = {}, options = {}) {
|
|
136
147
|
if (!VALID_HOOK_EVENTS.has(eventName)) {
|
|
137
148
|
throw new Error(`Invalid hook event: ${eventName}`);
|
|
138
149
|
}
|
|
139
150
|
|
|
140
151
|
const hooks = this.hooks.get(eventName) || [];
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
152
|
+
const durableRecord = this.durableStore
|
|
153
|
+
? this.durableStore.enqueueInbox(
|
|
154
|
+
{ event: eventName, context },
|
|
155
|
+
{ id: context.event_id || context.eventId || null },
|
|
156
|
+
)
|
|
157
|
+
: null;
|
|
158
|
+
// Hooks are parallel by default. De-duplicate by id so a reload or layered
|
|
159
|
+
// config cannot execute the same handler twice. `parallel:false` remains a
|
|
160
|
+
// deterministic compatibility mode for callers that require ordering.
|
|
161
|
+
const uniqueHooks = [];
|
|
162
|
+
const seen = new Set();
|
|
145
163
|
for (const hook of hooks) {
|
|
164
|
+
if (seen.has(hook.id)) continue;
|
|
165
|
+
seen.add(hook.id);
|
|
166
|
+
uniqueHooks.push(hook);
|
|
167
|
+
}
|
|
168
|
+
const runOne = async (hook) => {
|
|
146
169
|
const execId = crypto.randomUUID();
|
|
147
170
|
const start = Date.now();
|
|
148
171
|
const record = { execId, hookId: hook.id, event: eventName, type: hook.type, startedAt: new Date() };
|
|
@@ -170,28 +193,47 @@ class HooksV2Runtime extends EventEmitter {
|
|
|
170
193
|
record.durationMs = Date.now() - start;
|
|
171
194
|
record.status = "success";
|
|
172
195
|
record.result = result;
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
// Check for blocking decision
|
|
176
|
-
if (hook.blocking && result && result.decision === "block") {
|
|
177
|
-
blocked = true;
|
|
178
|
-
blockingResult = result;
|
|
179
|
-
record.blocked = true;
|
|
180
|
-
}
|
|
196
|
+
if (hook.blocking && result && result.decision === "block") record.blocked = true;
|
|
181
197
|
|
|
182
198
|
this.emit("hook:success", record);
|
|
183
199
|
} catch (err) {
|
|
184
200
|
record.durationMs = Date.now() - start;
|
|
185
201
|
record.status = "error";
|
|
186
202
|
record.error = err.message;
|
|
187
|
-
results.push(record);
|
|
188
203
|
this.emit("hook:error", record);
|
|
189
204
|
}
|
|
190
205
|
|
|
191
206
|
this.executionLog.push(record);
|
|
207
|
+
return record;
|
|
208
|
+
};
|
|
209
|
+
const results = options.parallel === false
|
|
210
|
+
? []
|
|
211
|
+
: await Promise.all(uniqueHooks.map(runOne));
|
|
212
|
+
if (options.parallel === false) {
|
|
213
|
+
for (const hook of uniqueHooks) results.push(await runOne(hook));
|
|
192
214
|
}
|
|
215
|
+
const blocking = results.filter((r) => r.blocked === true);
|
|
216
|
+
const blocked = blocking.length > 0;
|
|
217
|
+
const blockingResult = blocking[0]?.result || null;
|
|
218
|
+
|
|
219
|
+
const outcome = { success: !blocked, results, blocked, blockingResult };
|
|
220
|
+
if (durableRecord && !durableRecord.duplicate) {
|
|
221
|
+
this.durableStore.acknowledgeInbox(durableRecord.id, {
|
|
222
|
+
event: eventName,
|
|
223
|
+
blocked,
|
|
224
|
+
resultCount: results.length,
|
|
225
|
+
});
|
|
226
|
+
this.durableStore.enqueueOutbox(
|
|
227
|
+
{ event: eventName, outcome },
|
|
228
|
+
{ id: `${durableRecord.id}:result` },
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
return outcome;
|
|
232
|
+
}
|
|
193
233
|
|
|
194
|
-
|
|
234
|
+
/** Compatibility/public name used by runtime parity and SDK callers. */
|
|
235
|
+
async executeHooks(eventName, context = {}, options = {}) {
|
|
236
|
+
return this.emitEvent(eventName, context, options);
|
|
195
237
|
}
|
|
196
238
|
|
|
197
239
|
async _execCommand(hook, context) {
|
|
@@ -253,7 +295,9 @@ class HooksV2Runtime extends EventEmitter {
|
|
|
253
295
|
}
|
|
254
296
|
|
|
255
297
|
async _execJs(hook, context) {
|
|
256
|
-
|
|
298
|
+
if (typeof hook.handler === "function") return hook.handler(context);
|
|
299
|
+
// In-process JS execution via vm (sandboxed) - config-loaded code remains
|
|
300
|
+
// disabled until the dedicated VM executor is enabled.
|
|
257
301
|
return { decision: "noop", note: "JS executor stub - context received", contextKeys: Object.keys(context) };
|
|
258
302
|
}
|
|
259
303
|
|
|
@@ -273,6 +317,11 @@ class HooksV2Runtime extends EventEmitter {
|
|
|
273
317
|
}
|
|
274
318
|
|
|
275
319
|
// Singleton instance
|
|
276
|
-
const hooksRuntime = new HooksV2Runtime(
|
|
320
|
+
const hooksRuntime = new HooksV2Runtime(undefined, {
|
|
321
|
+
durableStore:
|
|
322
|
+
process.env.CC_EVENT_RUNTIME_DURABLE === "1"
|
|
323
|
+
? new EventRuntimeStore()
|
|
324
|
+
: null,
|
|
325
|
+
});
|
|
277
326
|
export default hooksRuntime;
|
|
278
327
|
export { HooksV2Runtime, VALID_HOOK_EVENTS, VALID_EXECUTOR_TYPES };
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
* still used for the V5/V6 IPC code path (separate hub singleton).
|
|
18
18
|
*
|
|
19
19
|
* Methods implemented (only what system-data-android consumes):
|
|
20
|
-
* - `contacts.query({since?})` →
|
|
21
|
-
*
|
|
20
|
+
* - `contacts.query({since?})` → contacts with phones, emails,
|
|
21
|
+
* organization, job title, starred state, and photo URI
|
|
22
22
|
* - `app.list({includeSystem?})` →
|
|
23
23
|
* [{ packageName }, ...]
|
|
24
24
|
*
|
|
@@ -120,27 +120,116 @@ function parseContentQueryRows(stdout) {
|
|
|
120
120
|
return rows;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
|
|
123
|
+
function mergeContactRows(contactRows, phoneRows, emailRows, organizationRows) {
|
|
124
|
+
const byId = new Map();
|
|
125
|
+
for (const row of contactRows) {
|
|
126
|
+
const contactId = row._id == null ? null : String(row._id);
|
|
127
|
+
const displayName = row.display_name || null;
|
|
128
|
+
if (!contactId || !displayName) continue;
|
|
129
|
+
byId.set(contactId, {
|
|
130
|
+
lookupKey: row.lookup || null,
|
|
131
|
+
displayName,
|
|
132
|
+
phones: [],
|
|
133
|
+
emails: [],
|
|
134
|
+
starred: row.starred === "1",
|
|
135
|
+
organization: null,
|
|
136
|
+
jobTitle: null,
|
|
137
|
+
photoUri: row.photo_uri || null,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const appendUnique = (rows, field, valueOf) => {
|
|
142
|
+
for (const row of rows) {
|
|
143
|
+
const contact = byId.get(String(row.contact_id));
|
|
144
|
+
const value = valueOf(row);
|
|
145
|
+
if (!contact || typeof value !== "string" || !value.trim()) continue;
|
|
146
|
+
const normalized = value.trim();
|
|
147
|
+
if (!contact[field].includes(normalized)) contact[field].push(normalized);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
appendUnique(phoneRows, "phones", (row) => row.data1 || row.number);
|
|
151
|
+
appendUnique(emailRows, "emails", (row) => row.data1 || row.address);
|
|
152
|
+
for (const row of organizationRows) {
|
|
153
|
+
const contact = byId.get(String(row.contact_id));
|
|
154
|
+
if (!contact) continue;
|
|
155
|
+
const organization = row.data1 || row.company;
|
|
156
|
+
const jobTitle = row.data4 || row.title;
|
|
157
|
+
if (!contact.organization && organization && organization.trim()) {
|
|
158
|
+
contact.organization = organization.trim();
|
|
159
|
+
}
|
|
160
|
+
if (!contact.jobTitle && jobTitle && jobTitle.trim()) {
|
|
161
|
+
contact.jobTitle = jobTitle.trim();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return [...byId.values()];
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async function queryContacts(params, opts) {
|
|
124
168
|
const serial = await pickDevice(opts);
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
169
|
+
const contactArgs = [
|
|
170
|
+
"shell",
|
|
171
|
+
"content",
|
|
172
|
+
"query",
|
|
173
|
+
"--uri",
|
|
174
|
+
"content://com.android.contacts/contacts",
|
|
175
|
+
"--projection",
|
|
176
|
+
"_id:lookup:display_name:starred:photo_uri",
|
|
177
|
+
];
|
|
178
|
+
if (Number.isInteger(params?.since) && params.since > 0) {
|
|
179
|
+
contactArgs.push(
|
|
180
|
+
"--where",
|
|
181
|
+
`contact_last_updated_timestamp >= ${params.since}`,
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
const commandOpts = { ...opts, serial, timeoutMs: opts.timeoutMs || 120_000 };
|
|
185
|
+
const [contactsOut, phonesOut, emailsOut, organizationsOut] =
|
|
186
|
+
await Promise.all([
|
|
187
|
+
adb(contactArgs, commandOpts),
|
|
188
|
+
adb(
|
|
189
|
+
[
|
|
190
|
+
"shell",
|
|
191
|
+
"content",
|
|
192
|
+
"query",
|
|
193
|
+
"--uri",
|
|
194
|
+
"content://com.android.contacts/data/phones",
|
|
195
|
+
"--projection",
|
|
196
|
+
"contact_id:data1",
|
|
197
|
+
],
|
|
198
|
+
commandOpts,
|
|
199
|
+
),
|
|
200
|
+
adb(
|
|
201
|
+
[
|
|
202
|
+
"shell",
|
|
203
|
+
"content",
|
|
204
|
+
"query",
|
|
205
|
+
"--uri",
|
|
206
|
+
"content://com.android.contacts/data/emails",
|
|
207
|
+
"--projection",
|
|
208
|
+
"contact_id:data1",
|
|
209
|
+
],
|
|
210
|
+
commandOpts,
|
|
211
|
+
),
|
|
212
|
+
adb(
|
|
213
|
+
[
|
|
214
|
+
"shell",
|
|
215
|
+
"content",
|
|
216
|
+
"query",
|
|
217
|
+
"--uri",
|
|
218
|
+
"content://com.android.contacts/data",
|
|
219
|
+
"--projection",
|
|
220
|
+
"contact_id:data1:data4",
|
|
221
|
+
"--where",
|
|
222
|
+
"mimetype='vnd.android.cursor.item/organization'",
|
|
223
|
+
],
|
|
224
|
+
commandOpts,
|
|
225
|
+
),
|
|
226
|
+
]);
|
|
227
|
+
return mergeContactRows(
|
|
228
|
+
parseContentQueryRows(contactsOut),
|
|
229
|
+
parseContentQueryRows(phonesOut),
|
|
230
|
+
parseContentQueryRows(emailsOut),
|
|
231
|
+
parseContentQueryRows(organizationsOut),
|
|
136
232
|
);
|
|
137
|
-
const rows = parseContentQueryRows(stdout);
|
|
138
|
-
return rows
|
|
139
|
-
.map((r) => ({
|
|
140
|
-
lookupKey: r.lookup || null,
|
|
141
|
-
displayName: r.display_name || null,
|
|
142
|
-
}))
|
|
143
|
-
.filter((c) => c.displayName);
|
|
144
233
|
}
|
|
145
234
|
|
|
146
235
|
async function listApps(params, opts) {
|
|
@@ -497,6 +586,7 @@ export function createHostAdbBridge(opts = {}) {
|
|
|
497
586
|
// Exposed for unit testing without spawning real adb.
|
|
498
587
|
export const _internals = {
|
|
499
588
|
parseContentQueryRows,
|
|
589
|
+
mergeContactRows,
|
|
500
590
|
listDevices,
|
|
501
591
|
pickDevice,
|
|
502
592
|
queryContacts,
|
package/src/lib/ide-context.js
CHANGED
|
@@ -438,6 +438,109 @@ export function hasIdeOpenDiff(mcp) {
|
|
|
438
438
|
);
|
|
439
439
|
}
|
|
440
440
|
|
|
441
|
+
const DIFF_REVIEW_AUDIT_SCHEMA = "cc-diff-review/v1";
|
|
442
|
+
const DIFF_REVIEW_OPERATIONS = new Set([
|
|
443
|
+
"modify",
|
|
444
|
+
"create",
|
|
445
|
+
"delete",
|
|
446
|
+
"rename",
|
|
447
|
+
]);
|
|
448
|
+
|
|
449
|
+
function auditString(value, max) {
|
|
450
|
+
if (value == null) return null;
|
|
451
|
+
const text = String(value).slice(0, max);
|
|
452
|
+
return text || null;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
function auditIndex(value) {
|
|
456
|
+
return Number.isInteger(value) && value >= 0 ? value : null;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
function auditFingerprint(value) {
|
|
460
|
+
if (!value || typeof value !== "object") return null;
|
|
461
|
+
const sha256 = auditString(value.sha256, 64);
|
|
462
|
+
if (!/^[a-f0-9]{64}$/i.test(sha256 || "")) return null;
|
|
463
|
+
return {
|
|
464
|
+
sha256: sha256.toLowerCase(),
|
|
465
|
+
chars: auditIndex(value.chars),
|
|
466
|
+
lines: auditIndex(value.lines),
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Reduce a host-provided Diff Review audit to the bounded v1 wire contract.
|
|
472
|
+
* Correlation ids and path are overwritten from the CLI request so a malformed
|
|
473
|
+
* or stale local bridge cannot spoof which session/tool the decision belongs to.
|
|
474
|
+
*/
|
|
475
|
+
export function normalizeDiffReviewAudit(value, binding = {}) {
|
|
476
|
+
if (
|
|
477
|
+
!value ||
|
|
478
|
+
typeof value !== "object" ||
|
|
479
|
+
value.schema !== DIFF_REVIEW_AUDIT_SCHEMA
|
|
480
|
+
) {
|
|
481
|
+
return null;
|
|
482
|
+
}
|
|
483
|
+
const requestedOutcome = auditString(binding.outcome ?? value.outcome, 64);
|
|
484
|
+
const outcome = ["accepted", "rejected", "changes-requested"].includes(
|
|
485
|
+
requestedOutcome,
|
|
486
|
+
)
|
|
487
|
+
? requestedOutcome
|
|
488
|
+
: "rejected";
|
|
489
|
+
const requestedOperation = binding.operation ?? value.operation;
|
|
490
|
+
const operation = DIFF_REVIEW_OPERATIONS.has(requestedOperation)
|
|
491
|
+
? requestedOperation
|
|
492
|
+
: "modify";
|
|
493
|
+
const comments = (Array.isArray(value.comments) ? value.comments : [])
|
|
494
|
+
.filter((comment) => comment && typeof comment === "object")
|
|
495
|
+
.map((comment) => ({
|
|
496
|
+
line: auditIndex(comment.line),
|
|
497
|
+
endLine: auditIndex(comment.endLine),
|
|
498
|
+
lineFingerprint: auditFingerprint(comment.lineFingerprint),
|
|
499
|
+
note: auditString(comment.note, 1000),
|
|
500
|
+
}))
|
|
501
|
+
.filter((comment) => comment.note)
|
|
502
|
+
.slice(0, 32);
|
|
503
|
+
const selectedHunks = [
|
|
504
|
+
...new Set(
|
|
505
|
+
(Array.isArray(value.selectedHunks) ? value.selectedHunks : []).filter(
|
|
506
|
+
(index) => Number.isInteger(index) && index >= 0,
|
|
507
|
+
),
|
|
508
|
+
),
|
|
509
|
+
]
|
|
510
|
+
.sort((a, b) => a - b)
|
|
511
|
+
.slice(0, 128);
|
|
512
|
+
return {
|
|
513
|
+
schema: DIFF_REVIEW_AUDIT_SCHEMA,
|
|
514
|
+
reviewId: auditString(value.reviewId, 64),
|
|
515
|
+
createdAt: auditString(value.createdAt, 64),
|
|
516
|
+
actor: auditString(value.actor, 128) || "local-user",
|
|
517
|
+
host: auditString(value.host, 64) || "ide",
|
|
518
|
+
path: auditString(binding.path ?? value.path, 2048),
|
|
519
|
+
operation,
|
|
520
|
+
targetPath:
|
|
521
|
+
operation === "rename"
|
|
522
|
+
? auditString(binding.targetPath ?? value.targetPath, 2048)
|
|
523
|
+
: null,
|
|
524
|
+
sessionId: auditString(binding.sessionId, 256),
|
|
525
|
+
turnId: auditString(binding.turnId, 256),
|
|
526
|
+
toolUseId: auditString(binding.toolUseId, 256),
|
|
527
|
+
outcome,
|
|
528
|
+
source: auditString(value.source, 64) || "agent-proposed",
|
|
529
|
+
written: value.written === true,
|
|
530
|
+
followUpRequested:
|
|
531
|
+
value.followUpRequested === true || outcome === "changes-requested",
|
|
532
|
+
baseline: auditFingerprint(value.baseline),
|
|
533
|
+
proposed: auditFingerprint(value.proposed),
|
|
534
|
+
reviewed: auditFingerprint(value.reviewed),
|
|
535
|
+
final: auditFingerprint(value.final),
|
|
536
|
+
selectedHunks,
|
|
537
|
+
appliedHunks: auditIndex(value.appliedHunks),
|
|
538
|
+
totalHunks: auditIndex(value.totalHunks),
|
|
539
|
+
comments,
|
|
540
|
+
reason: auditString(value.reason, 512),
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
|
|
441
544
|
/**
|
|
442
545
|
* Run one blocking openDiff review in the connected IDE. Returns
|
|
443
546
|
* { outcome:"accepted", finalText|null } — the IDE wrote the file itself
|
|
@@ -459,7 +562,17 @@ export function hasIdeOpenDiff(mcp) {
|
|
|
459
562
|
export async function requestIdeDiffApproval(mcp, req = {}) {
|
|
460
563
|
if (!hasIdeOpenDiff(mcp)) return null;
|
|
461
564
|
if (!req.path || typeof req.modifiedText !== "string") return null;
|
|
565
|
+
const operation = req.operation || "modify";
|
|
566
|
+
if (!DIFF_REVIEW_OPERATIONS.has(operation)) return null;
|
|
567
|
+
if (operation === "rename" && !req.targetPath) return null;
|
|
462
568
|
const exec = mcp.externalToolExecutors.mcp__ide__openDiff;
|
|
569
|
+
const reviewContext = Object.fromEntries(
|
|
570
|
+
Object.entries({
|
|
571
|
+
sessionId: auditString(req.sessionId, 256),
|
|
572
|
+
turnId: auditString(req.turnId, 256),
|
|
573
|
+
toolUseId: auditString(req.toolUseId, 256),
|
|
574
|
+
}).filter(([, value]) => value),
|
|
575
|
+
);
|
|
463
576
|
let result;
|
|
464
577
|
try {
|
|
465
578
|
result = await mcp.mcpClient.callTool(exec.serverName, exec.toolName, {
|
|
@@ -469,15 +582,26 @@ export async function requestIdeDiffApproval(mcp, req = {}) {
|
|
|
469
582
|
? { originalText: req.originalText }
|
|
470
583
|
: {}),
|
|
471
584
|
...(req.title ? { title: req.title } : {}),
|
|
585
|
+
...(req.operation ? { operation } : {}),
|
|
586
|
+
...(operation === "rename" ? { targetPath: req.targetPath } : {}),
|
|
587
|
+
...(Object.values(reviewContext).some(Boolean) ? { reviewContext } : {}),
|
|
472
588
|
});
|
|
473
589
|
} catch {
|
|
474
590
|
return null;
|
|
475
591
|
}
|
|
476
592
|
const data = parseToolResultJson(result);
|
|
593
|
+
const audit = normalizeDiffReviewAudit(data?.audit, {
|
|
594
|
+
...reviewContext,
|
|
595
|
+
path: req.path,
|
|
596
|
+
operation,
|
|
597
|
+
targetPath: operation === "rename" ? req.targetPath : null,
|
|
598
|
+
outcome: data?.outcome,
|
|
599
|
+
});
|
|
477
600
|
if (data?.outcome === "accepted") {
|
|
478
601
|
return {
|
|
479
602
|
outcome: "accepted",
|
|
480
603
|
finalText: typeof data.finalText === "string" ? data.finalText : null,
|
|
604
|
+
...(audit ? { audit } : {}),
|
|
481
605
|
};
|
|
482
606
|
}
|
|
483
607
|
if (data?.outcome === "changes-requested") {
|
|
@@ -486,9 +610,12 @@ export async function requestIdeDiffApproval(mcp, req = {}) {
|
|
|
486
610
|
comments: Array.isArray(data.comments) ? data.comments : [],
|
|
487
611
|
reviewedText:
|
|
488
612
|
typeof data.reviewedText === "string" ? data.reviewedText : null,
|
|
613
|
+
...(audit ? { audit } : {}),
|
|
489
614
|
};
|
|
490
615
|
}
|
|
491
|
-
if (data?.outcome === "rejected")
|
|
616
|
+
if (data?.outcome === "rejected") {
|
|
617
|
+
return { outcome: "rejected", ...(audit ? { audit } : {}) };
|
|
618
|
+
}
|
|
492
619
|
return null; // anything else is not a verdict — fail safe to fallback
|
|
493
620
|
}
|
|
494
621
|
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
LEGACY_TO_UNIFIED_TYPE,
|
|
15
15
|
} from "../runtime/runtime-events.js";
|
|
16
16
|
import { createAbortError } from "./abort-utils.js";
|
|
17
|
+
import { emitHooksV2Event } from "./hooks-v2-producers.js";
|
|
17
18
|
import { verifyApprovalBinding } from "./agent-authority.js";
|
|
18
19
|
import { createEnvelope } from "@chainlesschain/session-core";
|
|
19
20
|
|
|
@@ -245,6 +246,44 @@ export class WebSocketInteractionAdapter extends InteractionAdapter {
|
|
|
245
246
|
this._resolvePending(requestId, answer, "question", binding);
|
|
246
247
|
}
|
|
247
248
|
|
|
249
|
+
/**
|
|
250
|
+
* Ask an MCP server elicitation over the same question/answer channel.
|
|
251
|
+
* The schema is carried as metadata so capable IDE clients can render a
|
|
252
|
+
* native form; older clients still receive a bounded, ordinary question.
|
|
253
|
+
*/
|
|
254
|
+
async askElicitation({
|
|
255
|
+
server,
|
|
256
|
+
requestId: mcpRequestId,
|
|
257
|
+
message = "MCP server requests input",
|
|
258
|
+
requestedSchema = null,
|
|
259
|
+
timeoutMs,
|
|
260
|
+
} = {}) {
|
|
261
|
+
emitHooksV2Event("MCPElicitation", {
|
|
262
|
+
server: server || null,
|
|
263
|
+
request_id: mcpRequestId ?? null,
|
|
264
|
+
message: String(message),
|
|
265
|
+
requested_schema: requestedSchema || null,
|
|
266
|
+
});
|
|
267
|
+
return this._request(
|
|
268
|
+
{
|
|
269
|
+
type: "question",
|
|
270
|
+
questionType: "elicitation",
|
|
271
|
+
question: String(message),
|
|
272
|
+
...(requestedSchema ? { requestedSchema } : {}),
|
|
273
|
+
metadata: {
|
|
274
|
+
kind: "mcp_elicitation",
|
|
275
|
+
server: server || null,
|
|
276
|
+
requestId: mcpRequestId ?? null,
|
|
277
|
+
requestedSchema: requestedSchema || null,
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
kind: "question",
|
|
282
|
+
...(Number(timeoutMs) > 0 ? { timeoutMs: Number(timeoutMs) } : {}),
|
|
283
|
+
},
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
|
|
248
287
|
async requestHostTool(toolName, args = {}, extra = {}) {
|
|
249
288
|
return this._request(
|
|
250
289
|
{
|