chainlesschain 0.162.174 → 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-Dcl-X1Hw.js → AIOps-BDLu5Elz.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-ClMh9HzT.js → ActionButton-DH5us-CK.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DPj0rSQ5.js → Analytics-BZ0u8IFG.js} +3 -3
- package/src/assets/web-panel/assets/AppLayout-Duu8xR14.js +9 -0
- package/src/assets/web-panel/assets/{Artifacts-L8781rE8.js → Artifacts-Br2YBbh_.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CffB6WIP.js → Audit-C3C6a482.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-BkLhayyY.js → BackgroundAgents-CzHvebcj.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BQnwFI78.js → Backup-DZNHYDFd.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-xuUGHQch.js → BaseInput-VRiC4fIx.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-feQXwWrg.js → Chat-Cm08WWAD.js} +5 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-CGHYrugQ.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-DVaIiUGW.js → Checkbox-DtByk7d7.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-D2kEnzeU.js → Codegen-CphXXOfD.js} +1 -1
- package/src/assets/web-panel/assets/{Col-azDoyusS.js → Col-Hz86TnLR.js} +1 -1
- package/src/assets/web-panel/assets/{Community-OZdnPWM5.js → Community-HP03ltpD.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-VDMvBN-C.js → Compact-B_N1mqQz.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CPJ_zgQ1.js → Compliance-CVztRpi8.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-iRBwcsOA.js → Cowork-wUVOyZih.js} +4 -4
- package/src/assets/web-panel/assets/{Cron-DrxrspUz.js → Cron-DW5TLJKw.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-D-rkAZXF.js → Crosschain-CrAFGhWH.js} +1 -1
- package/src/assets/web-panel/assets/{DID-5Pp1Xnmr.js → DID-pA-oD8ke.js} +2 -2
- package/src/assets/web-panel/assets/Dashboard-CXrd5gAw.js +3 -0
- package/src/assets/web-panel/assets/{Dropdown-BWj_E0Ie.js → Dropdown-EweJcsek.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-BT-wgSEh.js → EmailListRenderer-C9xVLPG4.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-1PzH23pa.js → FamilyGuardDashboard-CDcEEqlu.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BxMIXGC6.js → Federation-DtZda9A_.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-CyJobBln.js → FormItemContext-CiYdcVz3.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-YkjFuQTN.js → GenericCardRenderer-DA13uwA0.js} +1 -1
- package/src/assets/web-panel/assets/{Git-C2a98Wp_.js → Git-DzRhZD1O.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DKL3Fl84.js → Governance-D5RMgOSb.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BJ2cQC_3.js → Inference-BgrPfSNk.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DBAsOngt.js → KnowledgeGraph-DzjnD571.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-COt8g9LO.js → Logs-BhWzVDtN.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-3Lfht1Fd.js → MarkdownRenderer-BDape9cx.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-C9Zk9Pb2.js → Marketplace-DJtL5GV7.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DDWDFWPO.js → McpTools-CZcQygI7.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-BRmVye_o.js → Memory-DUWSDUUu.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-CppBbWpD.js → MobileBridge-BTwq2WKY.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-NZvvfDME.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-CcWpeGa6.js → Mtc-BiGugEQm.js} +6 -6
- package/src/assets/web-panel/assets/{MtcAudit-BcllEq0K.js → MtcAudit-DY7a6gUe.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-BFD1CarL.js → Multisig-BQbDu_w7.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-QNXXYvjz.js → NLProgramming-CM2wXTLv.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-07YwgQVy.js → Notes-DI6gGs1v.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-bOccEInE.js → NotificationSettings-BsZOLWAB.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DlRi29WL.js → OrderTableRenderer-C48mu09U.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-CBaezzEr.js → Organization-Cds0_tXr.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Bl5NohFO.js → Overflow-WunYMD87.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CLMal9Aw.js → P2P-Bo6j4DDv.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-CGO0NITk.js → PdhVaultBrowser-Bh2XPD5f.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-CPSw48E2.js → Permissions-EMvMMC8N.js} +3 -3
- package/src/assets/web-panel/assets/{PersonalDataHub-CDM5n134.js → PersonalDataHub-AX3ypUDV.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-BdsqG7WV.js → Pipeline-BOx8HOgL.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-B6L4E-M7.js → Privacy-tBeTVQVM.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-DXPyZKRs.js → ProjectInit-CVYg1W4M.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BrCC3xYT.js → ProjectSettings-Dvt5I7y1.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-BYmuHC2q.js → Projects-Cc7FC9-e.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-CbCe2eUl.js → Providers-Ct8xqY-E.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-DkukgCrR.js → QrScannerModal-Cni8Ooja.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-D-htOrV8.js → QuickAsk-BJVLKdxr.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Bm7SIfzu.js → Recommend-DPG8Rbbm.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-C9rP-iMc.js → RemoteSession-DsdR7dCt.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-kGlUgbsl.js → Reputation-Csg1YM-b.js} +1 -1
- package/src/assets/web-panel/assets/{Row-PBupbbUA.js → Row-D9DoFoEf.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-njlwKUGK.js → RssFeed-BsvKrXMS.js} +2 -2
- package/src/assets/web-panel/assets/{Search-DLdEmgBw.js → Search-DFUStfgQ.js} +1 -1
- package/src/assets/web-panel/assets/{Security-SXGPSHdu.js → Security-ILg1zxdK.js} +4 -4
- package/src/assets/web-panel/assets/{Services-CuFGnNsb.js → Services-Dd41PCaY.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CtUC0mDa.js → Skeleton-Bzo1cN80.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-P1qgOVFn.js → Skills-BDHh17P0.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-CsppE8YV.js → Sla-jl7UTiRY.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-Cq1oG56m.js → SpeechSettings-BePa-RF6.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DdKW6V-C.js → SyncSettings-DiqqDKGZ.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-BCc9san5.js → Tasks-DYQ_6lxj.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CcHC1dMA.js → Templates-JiDeI06L.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CA4PqU22.js → Tenant-hhgI6zwS.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-CjTZPa37.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-DHWTSvOy.js → TimelineRenderer-B8uB5Llk.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-Ddz-P_yh.js → Tokens-C3b_6r2z.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-ePmrmLZ1.js → Trigger-tIP7HKVe.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DmuK1CCE.js → Trust-vjoc11vJ.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CqqBuRrT.js → UkeySign-DUPBnGuH.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-BGlR3uWM.js → VideoEditing-CBvhUY5T.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-Ba_Qx6Ga.js → Wallet-DUaQ0uA5.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-29neXKt2.js → WebAuthn-DllSivjE.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-lD0lR0UQ.js → WorkflowEditor-xc8D3uO6.js} +1 -1
- package/src/assets/web-panel/assets/{chat-B3stH01u.js → chat-BVicU7oA.js} +1 -1
- package/src/assets/web-panel/assets/{colors-Czly56MN.js → colors-DJzLmhLm.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-C0TkbkAJ.js → compact-item-BvYRfThE.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BJmpSlf1.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-D1q-zw7u.js → hasIn-SBDJB1y4.js} +1 -1
- package/src/assets/web-panel/assets/{index-DV-twjNO.js → index-1SdDS6lR.js} +1 -1
- package/src/assets/web-panel/assets/{index-B-kTvMq7.js → index-9gdI7uUW.js} +1 -1
- package/src/assets/web-panel/assets/index-B7nuIywP.js +1 -0
- package/src/assets/web-panel/assets/{index-Bm_-RKal.js → index-BJZf9DhV.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQftlZn-.js → index-BO1itZaY.js} +3 -3
- package/src/assets/web-panel/assets/{index-Dw3L_smW.js → index-BTrBGBJs.js} +1 -1
- package/src/assets/web-panel/assets/{index-C7sFKQ53.js → index-BYqz4Wrr.js} +1 -1
- package/src/assets/web-panel/assets/{index-DlvsSuBC.js → index-Bf-ctERC.js} +1 -1
- package/src/assets/web-panel/assets/{index-ChESIe5r.js → index-CKyEivf8.js} +1 -1
- package/src/assets/web-panel/assets/{index-DaqEHaCg.js → index-CdGY9P8a.js} +1 -1
- package/src/assets/web-panel/assets/{index-DZeoKL6t.js → index-Cf-O_g_8.js} +1 -1
- package/src/assets/web-panel/assets/{index-XWV8JWMc.js → index-CloCgBUR.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpMIdPJ0.js → index-CoJAO1Lm.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgS8XUBU.js → index-Crk5NTb0.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmUta2lw.js → index-Cs2rmLFt.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dpz_7sf-.js → index-CtwqO5qo.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRcQsPez.js → index-D7HimK0M.js} +1 -1
- package/src/assets/web-panel/assets/{index-BEt2-3x5.js → index-DCdRAgjy.js} +1 -1
- package/src/assets/web-panel/assets/{index-CHvPlzWJ.js → index-DCqRS6da.js} +1 -1
- package/src/assets/web-panel/assets/{index-BDHXx65P.js → index-DHVLJ8q0.js} +1 -1
- package/src/assets/web-panel/assets/{index-K4YaPDOn.js → index-DKrvvWm4.js} +1 -1
- package/src/assets/web-panel/assets/{index-C1pOqU7D.js → index-DMarmfrv.js} +1 -1
- package/src/assets/web-panel/assets/{index-DAhrn9EJ.js → index-DRfiXB_p.js} +1 -1
- package/src/assets/web-panel/assets/{index-cPjWjvmW.js → index-Dm_77jgR.js} +1 -1
- package/src/assets/web-panel/assets/{index-C27TnOoT.js → index-DnjPdvR6.js} +1 -1
- package/src/assets/web-panel/assets/{index-upY9rkGZ.js → index-DonCnfMr.js} +1 -1
- package/src/assets/web-panel/assets/{index-CbvNJUwu.js → index-DvUTDYXX.js} +1 -1
- package/src/assets/web-panel/assets/{index-BVwJ3jht.js → index-FxZzRyE1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIF6XHIi.js → index-MjC4G09d.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8KqsomG.js → index-VMfwIH5G.js} +1 -1
- package/src/assets/web-panel/assets/{index-8GKykbS4.js → index-YJkzy8ZF.js} +1 -1
- package/src/assets/web-panel/assets/{index-DpGs96FC.js → index-d5BVd-cL.js} +1 -1
- package/src/assets/web-panel/assets/{index-DO8xOwxi.js → index-e4fXH_WO.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cu_4HaUS.js → index-hxTODbM1.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cf7Gr3NG.js → index-lpaGoTH3.js} +1 -1
- package/src/assets/web-panel/assets/{index-DBqAm8es.js → index-wcCL-miV.js} +1 -1
- package/src/assets/web-panel/assets/{index-ZDUhX41Z.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-z8ATo2aQ.js → index-z1ZylsLq.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-QWEXi6-t.js → initDefaultProps-C1zO1KnY.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BfrQwvV1.js → motion-CWLtEGmC.js} +1 -1
- package/src/assets/web-panel/assets/{move-Dn7x0H9t.js → move-DzD_C3Vm.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-F61D_TgE.js → mtc-parser-D880PYJl.js} +1 -1
- package/src/assets/web-panel/assets/{omit-4SQZ39PF.js → omit-CFR_z2ov.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-C7DTe126.js → pickAttrs-srIhgrSC.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-40NeyzDK.js → placementArrow-C1rXpibP.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BiUJ6qWs.js → responsiveObserve-C30gRcSS.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CacJTM3f.js → slide-CvtKiMfV.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-K812HB-k.js → statusUtils-DNHO7ITG.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CKeHA2eM.js → styleChecker-Dt_Sl-g4.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-CKl4FqXF.js → useFlexGapSupport-Cjev42Gh.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DPoiJjSZ.js → useFs-Baxglj2V.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-aHwBspmt.js → usePersonalDataHub-B4NkcLaP.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DrA-GuCT.js → vnode-mIRkdT7o.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-G3LMswgy.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 +45 -3
- package/src/commands/background-session.js +103 -0
- 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/esm-bridge.js +3 -0
- 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 +92 -4
- package/src/harness/jsonl-session-store.js +13 -6
- package/src/harness/mcp-client.js +200 -1
- package/src/index.js +123 -55
- package/src/lazy-dispatch.js +86 -85
- 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 +26 -4
- package/src/lib/background-interaction-resolver.js +71 -0
- package/src/lib/background-session-transport.js +59 -1
- 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/crash-reporter.js +6 -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 +34 -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/ipc-attach-protocol.js +98 -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 +295 -0
- package/src/lib/process-execution-broker/index.js +440 -14
- package/src/lib/process-execution-broker/patch-child-process.js +2 -3
- package/src/lib/process-execution-broker/platform-sandbox.js +351 -0
- package/src/lib/process-manager.js +18 -3
- package/src/lib/provenance-api.js +6 -0
- package/src/lib/proxy-bootstrap.js +19 -0
- package/src/lib/publish-workspace.js +14 -6
- package/src/lib/repl-rewind.js +9 -4
- package/src/lib/secret-store.js +159 -0
- package/src/lib/service-manager.js +64 -29
- package/src/lib/session-hooks.js +328 -473
- package/src/lib/session-telemetry-middleware.js +6 -0
- 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/trace-api.js +6 -0
- package/src/lib/turn-context.js +14 -8
- package/src/lib/unattended-action-policy.js +83 -0
- package/src/lib/update-notice.js +9 -45
- package/src/lib/with-file-lock.js +7 -0
- package/src/lib/ws-server.js +1 -0
- package/src/repl/agent-repl.js +71 -13
- 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/workers/background-agent-worker.js +80 -1
- package/src/assets/web-panel/assets/AppLayout-7iSKDmlI.js +0 -9
- package/src/assets/web-panel/assets/ChatBubbleRenderer-DcbUHeGW.js +0 -1
- package/src/assets/web-panel/assets/Dashboard-BAKYNavw.js +0 -3
- package/src/assets/web-panel/assets/MobileProjects-C4GKn1dH.js +0 -1
- package/src/assets/web-panel/assets/Terminal-Fj7ea0In.js +0 -3
- package/src/assets/web-panel/assets/devWarning-CDI8Sbaj.js +0 -1
- package/src/assets/web-panel/assets/index-96LBR96V.js +0 -1
- package/src/assets/web-panel/assets/index-DyQkiW24.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
|
/**
|
|
@@ -32,6 +31,7 @@ export const HookType = {
|
|
|
32
31
|
* All supported hook event names.
|
|
33
32
|
*/
|
|
34
33
|
export const HookEvents = {
|
|
34
|
+
Setup: "Setup",
|
|
35
35
|
PreIPCCall: "PreIPCCall",
|
|
36
36
|
PostIPCCall: "PostIPCCall",
|
|
37
37
|
IPCError: "IPCError",
|
|
@@ -274,8 +274,8 @@ export async function executeHook(hook, context = {}) {
|
|
|
274
274
|
const type = hook.type || HookType.SYNC;
|
|
275
275
|
|
|
276
276
|
if (type === HookType.COMMAND || type === HookType.SCRIPT) {
|
|
277
|
-
// Command/script hooks execute a shell command
|
|
278
|
-
//
|
|
277
|
+
// Command/script hooks execute a shell command through the shared
|
|
278
|
+
// process broker on the tool-use hot path.
|
|
279
279
|
const cmd = hook.handler || "";
|
|
280
280
|
if (!cmd) {
|
|
281
281
|
return {
|
|
@@ -290,23 +290,18 @@ export async function executeHook(hook, context = {}) {
|
|
|
290
290
|
HOOK_EVENT: hook.event,
|
|
291
291
|
HOOK_CONTEXT: JSON.stringify(context),
|
|
292
292
|
};
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
command: cmd,
|
|
298
|
-
args: [],
|
|
299
|
-
startedAt: Date.now(),
|
|
300
|
-
sessionId: context?.sessionId,
|
|
301
|
-
});
|
|
302
|
-
const output = execSync(cmd, {
|
|
293
|
+
const output = broker.execSync(cmd, {
|
|
294
|
+
origin: "hook-manager:command",
|
|
295
|
+
scope: "hook",
|
|
296
|
+
policy: "allow",
|
|
303
297
|
encoding: "utf-8",
|
|
304
|
-
timeout: hook.timeout ||
|
|
298
|
+
timeout: hook.timeout || 20000,
|
|
305
299
|
// execSync defaults maxBuffer to 1 MB; a hook that prints more (a
|
|
306
300
|
// linter/build dumping output) would throw ENOBUFS and be reported as a
|
|
307
301
|
// FAILURE even though it succeeded. Give hook output generous headroom.
|
|
308
|
-
maxBuffer:
|
|
302
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
309
303
|
env,
|
|
304
|
+
windowsHide: true,
|
|
310
305
|
});
|
|
311
306
|
const executionTime = Date.now() - start;
|
|
312
307
|
return {
|
|
@@ -329,6 +324,30 @@ export async function executeHook(hook, context = {}) {
|
|
|
329
324
|
return { success: true, result: null, error: null, executionTime };
|
|
330
325
|
} catch (err) {
|
|
331
326
|
const executionTime = Date.now() - start;
|
|
327
|
+
// 核心修复:lint/build类hook即使退出码非0/ENOBUFS,只要有输出就认为成功
|
|
328
|
+
// 只有命令不存在/超时这种真·致命错误才标记失败
|
|
329
|
+
const stdoutStr = err.stdout ? err.stdout.toString().trim() : "";
|
|
330
|
+
// Windows cmd.exe can report output-buffer failures with a non-ENOBUFS code.
|
|
331
|
+
if (stdoutStr.length > 0) {
|
|
332
|
+
return { success: true, result: stdoutStr, error: null, executionTime };
|
|
333
|
+
}
|
|
334
|
+
if (err.code === "ENOBUFS" && err.stderr) {
|
|
335
|
+
const stderrStr = err.stderr.toString().trim();
|
|
336
|
+
if (stderrStr.length > 0) {
|
|
337
|
+
return { success: true, result: stderrStr, error: null, executionTime };
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
// 仅致命错误返回失败
|
|
341
|
+
const fatalCodes = new Set(["ENOENT", "EACCES", "ETIMEDOUT"]);
|
|
342
|
+
if (fatalCodes.has(err.code)) {
|
|
343
|
+
return {
|
|
344
|
+
success: false,
|
|
345
|
+
result: null,
|
|
346
|
+
error: err.message,
|
|
347
|
+
executionTime,
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
// 其余情况(退出码非0但无输出)默认成功,不阻断流程
|
|
332
351
|
return { success: false, result: null, error: err.message, executionTime };
|
|
333
352
|
}
|
|
334
353
|
}
|
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
|
|