chainlesschain 0.162.175 → 0.162.177
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-DT-VPWuN.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CDGfqt2Y.js → ActionButton-DyOreOVN.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-BYhkzdgD.js → Analytics-DslNsKux.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-cEKk1cpb.js → AppLayout-BNJJAYME.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-_aXR3WWc.js → Artifacts-DoaAtEcY.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CYAf-gY7.js → Audit-DPG3WdJ9.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-D4Q20phR.js → BackgroundAgents-C_JO6R5G.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-Cq0Tyk58.js → Backup-Cv3BooyX.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-CPj_CdAv.js → BaseInput-D2uQXWu-.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-BQ-Qq0es.js → Chat-B4Vczyf3.js} +4 -4
- package/src/assets/web-panel/assets/ChatBubbleRenderer-DE6reP99.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-rke6l3yg.js → Checkbox-qTgk4VeP.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-DiacrIPq.js → Codegen-DlLWcIzj.js} +1 -1
- package/src/assets/web-panel/assets/{Col-Cx3BY-Up.js → Col-DNO73qp7.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DfmWiQy8.js → Community-vRDNpc4j.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DdQnpxy5.js → Compact-CEWtIXni.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-lzliOH_r.js → Compliance-KgYC9Fxi.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-CYx4Un5k.js → Cowork-zj5wvkpT.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-BGDcPFlo.js → Cron-BLDoCozU.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-0_X5g2ri.js → Crosschain-BYnff4VY.js} +1 -1
- package/src/assets/web-panel/assets/{DID-C0PEf3Eu.js → DID-C75VFsVm.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-DULQjQ58.js → Dashboard-C4Gutni2.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DGRHRbW6.js → Dropdown-B5dbO4Kx.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-ChX8XPwB.js → EmailListRenderer-BDipZtHJ.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-Dyq6IBNu.js → FamilyGuardDashboard-DmIzt8jj.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DH1NfAL2.js → Federation-D9QOS-uW.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-BN1I_uNi.js → FormItemContext-B47HRwAm.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-Dq_2UYpe.js → GenericCardRenderer-3R4mXmgV.js} +1 -1
- package/src/assets/web-panel/assets/{Git-BAy1yvI2.js → Git-DrNXZf1C.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-Db6Q2iSy.js → Governance-BGd7JR98.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-0ub6yHcr.js → Inference-D-2he1ed.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DtLetM36.js → KnowledgeGraph-C0sHIbK5.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-Bcoy7CUd.js → Logs-DiBQO-jL.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-BfEMFAXf.js → MarkdownRenderer-DL_5eV2D.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-tt2rzwRR.js → Marketplace-VR59OdrC.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-BhOgX-MU.js → McpTools-DrPzwSd3.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-BJUxeWBL.js → Memory-CBgKALwQ.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BwUY2G9w.js → MobileBridge-pQ9Tn-Mn.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-BLRfHhqi.js → MobileProjects-mASB6jyj.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-B2WMboOm.js → Mtc-DTMgE7HC.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-8pNEXO63.js → MtcAudit-CwTnCtiL.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-C1wm5a_1.js → Multisig-ngm6WU8f.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-C1QpKF7g.js → NLProgramming-4YO4Qww9.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CiQUcxFu.js → Notes-DP1k45mF.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-BblDPJ_x.js → NotificationSettings-r2H8yPKb.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DRjYcPtb.js → OrderTableRenderer-CoM_Zw0J.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-Dp3VKB0X.js → Organization-DrO7jRWS.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Czx161m9.js → Overflow-Cnwu4i4t.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-ClFi6wOs.js → P2P-zi-cDwA_.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-CRweW0lz.js → PdhVaultBrowser-DBEryDv7.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-BzcRoqTn.js → Permissions-lqXK2C3x.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-ChGTpNMd.js → PersonalDataHub-b63T3HJM.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-BMOOpKWA.js → Pipeline-Kep5KAGW.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-D0AZHObH.js → Privacy-CHdvOAh1.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-yYFlZ6Ja.js → ProjectInit-BhKfdwe9.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-DJNVuMQs.js → ProjectSettings-Yavk9K8A.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-Br0rBWH1.js → Projects-CN8E_5Mq.js} +1 -1
- package/src/assets/web-panel/assets/Providers-Bfym6SQn.js +1 -0
- package/src/assets/web-panel/assets/{QrScannerModal-81NZOitV.js → QrScannerModal-CLSQcrlR.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-Dic2lCbJ.js → QuickAsk-VPa2WKQN.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Dh9iwViE.js → Recommend-CGXR8jVU.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-Bq9VYEFy.js → RemoteSession-C_20YfMB.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-CxFZ-NbJ.js → Reputation-awZh68UV.js} +1 -1
- package/src/assets/web-panel/assets/{Row-BVSLcaX2.js → Row-Ctb4oiYN.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BbC-5DOH.js → RssFeed-D3sdjvUV.js} +3 -3
- package/src/assets/web-panel/assets/{Search-BfjZ1GCr.js → Search-C-zfA4kT.js} +1 -1
- package/src/assets/web-panel/assets/{Security-CVjhOV5r.js → Security-D9XlmHA3.js} +4 -4
- package/src/assets/web-panel/assets/{Services-D45u-Aqe.js → Services-C3UKnr41.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-WkGoK4he.js → Skeleton-BQxagZfF.js} +1 -1
- package/src/assets/web-panel/assets/Skills-q6eb6KPZ.js +1 -0
- package/src/assets/web-panel/assets/{Sla-Bf4QTF3E.js → Sla-DveENvek.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DVpZdbMN.js → SpeechSettings-BFjXLNgF.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DEEojoMS.js → SyncSettings-BpHgbaP9.js} +2 -2
- package/src/assets/web-panel/assets/Tasks-DvepRb8-.js +1 -0
- package/src/assets/web-panel/assets/{Templates-Bzl-9wY5.js → Templates-DEiaoyve.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-0khxUOB8.js → Tenant-ITg774nY.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-DWGYhAYU.js → Terminal-D3ZBcvnb.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-B0Y4LONc.js → TimelineRenderer-BsLU6JjU.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DEE07SFh.js → Tokens-Cb5Pquc9.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BM7xvA5z.js → Trigger-Dwfy-m9N.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-Dv3ijvvZ.js → Trust-CnlSRGG0.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B1-enmMt.js → UkeySign-Y4TlvKVo.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DYiIPByd.js → VideoEditing-BpKLtTTO.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-D-y374BQ.js → Wallet-LLBzIq8x.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-HBDjcUhi.js → WebAuthn-BeSRiusP.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-sKn4qTID.js → WorkflowEditor-BK_l1tXO.js} +1 -1
- package/src/assets/web-panel/assets/{chat-TVYhaBXj.js → chat-DYd-X7Wg.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DMADxY9v.js → colors-C9uip71j.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-OftcHpO_.js → compact-item-JBrfjUP6.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DW1zVUSN.js → createContext-D03fbuiq.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-B8LQ8leS.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-CaUathNp.js → hasIn-DLQOR6l-.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cmdv6Dev.js → index-5YN7F5bO.js} +1 -1
- package/src/assets/web-panel/assets/{index-iDmgT2Dg.js → index-6GuLRpBQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-77kgkUgY.js → index-B0X76LjX.js} +1 -1
- package/src/assets/web-panel/assets/{index-CM8W07sc.js → index-B46YcgsV.js} +1 -1
- package/src/assets/web-panel/assets/{index-C9JoaYSs.js → index-BNCdRmWf.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpDtN0dl.js → index-BYv-LWdy.js} +1 -1
- package/src/assets/web-panel/assets/{index-CZXYI5LU.js → index-Ba-Ps_AJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DWVZ3T0t.js → index-BcBZwlnG.js} +1 -1
- package/src/assets/web-panel/assets/{index--5UvwqH_.js → index-BdH9l8wl.js} +1 -1
- package/src/assets/web-panel/assets/{index-BBNg08cD.js → index-BfOs_bmg.js} +3 -3
- package/src/assets/web-panel/assets/index-Bh8BPtqR.js +1 -0
- package/src/assets/web-panel/assets/{index-s-EnkUCn.js → index-BnQgRjsm.js} +1 -1
- package/src/assets/web-panel/assets/{index-Lr0MO-GU.js → index-BpYKLrUT.js} +1 -1
- package/src/assets/web-panel/assets/{index-B-19mFhn.js → index-BuNFCZCx.js} +1 -1
- package/src/assets/web-panel/assets/{index-CeCIYYG7.js → index-ByHO3SqZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-hXq7QRA_.js → index-C2zmOsyD.js} +1 -1
- package/src/assets/web-panel/assets/{index-8YelceUU.js → index-CChQBM1d.js} +1 -1
- package/src/assets/web-panel/assets/{index-B52Ztt8Q.js → index-CChaISMb.js} +1 -1
- package/src/assets/web-panel/assets/{index-DKjqFpYa.js → index-CILVyK3b.js} +1 -1
- package/src/assets/web-panel/assets/{index-DAfT3EMd.js → index-CL0ixCxk.js} +1 -1
- package/src/assets/web-panel/assets/{index-sm1sGIxW.js → index-CS63r8h3.js} +1 -1
- package/src/assets/web-panel/assets/{index-DHi634g9.js → index-CVZWiUE_.js} +1 -1
- package/src/assets/web-panel/assets/{index-BEzLLVYd.js → index-Ce0Bf1YF.js} +1 -1
- package/src/assets/web-panel/assets/index-CeVrHLzZ.js +1 -0
- package/src/assets/web-panel/assets/{index-pSVCBsG4.js → index-Ck17i0OD.js} +1 -1
- package/src/assets/web-panel/assets/{index-GUKz4Pv9.js → index-Cpn19c9k.js} +1 -1
- package/src/assets/web-panel/assets/{index-CKNdnJRo.js → index-CqWk1FLG.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bg-7FpaL.js → index-CwoDpKzW.js} +1 -1
- package/src/assets/web-panel/assets/{index-DYwwUKDg.js → index-D-1SqEpQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DZdT8nio.js → index-D4UY5Z60.js} +1 -1
- package/src/assets/web-panel/assets/{index-BvRw4Fna.js → index-D8KvuDz0.js} +1 -1
- package/src/assets/web-panel/assets/{index-kdMl_0zL.js → index-DNMAAUVk.js} +1 -1
- package/src/assets/web-panel/assets/{index-CK-p7Hji.js → index-DYLZY4uh.js} +1 -1
- package/src/assets/web-panel/assets/{index-DXcqvWBp.js → index-DaokIHt3.js} +1 -1
- package/src/assets/web-panel/assets/{index-BFVbDpqg.js → index-Q7mmL6w4.js} +1 -1
- package/src/assets/web-panel/assets/{index-BJ1PjRY3.js → index-SO6lgMg0.js} +1 -1
- package/src/assets/web-panel/assets/{index-BSp1Ofvx.js → index-iahNhZwm.js} +1 -1
- package/src/assets/web-panel/assets/{index-BupSWDcl.js → index-l08afIbV.js} +1 -1
- package/src/assets/web-panel/assets/{index-D63QVAiJ.js → index-rIxxfdTN.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-DdcKTlQR.js → initDefaultProps-CG9z1c6w.js} +1 -1
- package/src/assets/web-panel/assets/{motion-CL-hTBQj.js → motion-B1Ky7Zff.js} +1 -1
- package/src/assets/web-panel/assets/{move-qYSAkxNG.js → move-DME8X2P1.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-ZwRSZtRP.js → mtc-parser-cuJYSWB7.js} +1 -1
- package/src/assets/web-panel/assets/{omit-Bld-8ftI.js → omit-UI_EE0uZ.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DGHs-a9Z.js → pickAttrs-BIoE_Z_V.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DRQPMyI5.js → placementArrow-B48-9HKN.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-C5MJG_Yo.js → responsiveObserve-D7x_GDgD.js} +1 -1
- package/src/assets/web-panel/assets/{slide-VZ-fpZCD.js → slide-DjzC5_7m.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-9ocfCyHk.js → statusUtils-C6BIymhh.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-B6QAwAN5.js → styleChecker-B4dGrdD9.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-Bq1twor3.js → useFlexGapSupport-Bken4aNE.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DKZq96tz.js → useFs-BMlqECqv.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-D0RmRVXf.js → usePersonalDataHub-DLdrfmMa.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-D6kEj_tt.js → vnode-CKJQmxa0.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-2yfasoQf.js → zoom-CaZunuau.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 +83 -5
- package/src/commands/agent.js +42 -4
- package/src/commands/background-session.js +11 -4
- package/src/commands/batch.js +79 -27
- package/src/commands/changelog.js +15 -4
- package/src/commands/config.js +70 -5
- package/src/commands/context.js +36 -2
- package/src/commands/eval.js +21 -6
- package/src/commands/hook.js +2 -2
- package/src/commands/hub.js +19 -1
- package/src/commands/loop.js +9 -2
- 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/skill.js +2 -0
- package/src/commands/statusline.js +3 -3
- package/src/commands/team.js +20 -7
- package/src/commands/update.js +65 -10
- package/src/data/changelog.json +293 -51
- 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/background-task-manager.js +18 -6
- package/src/harness/background-task-worker.js +11 -18
- package/src/harness/jsonl-session-store.js +13 -6
- package/src/harness/mcp-client.js +195 -2
- package/src/harness/worktree-isolator.js +18 -21
- 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-core.js +5 -0
- package/src/lib/agent-ipc-bus.js +44 -5
- package/src/lib/agent-sandbox.js +16 -2
- package/src/lib/agent-schedule-store.js +55 -0
- package/src/lib/agent-team/team-worktree.js +28 -6
- package/src/lib/agent-tool-admission.js +104 -0
- package/src/lib/agent-worktree.js +20 -19
- package/src/lib/api-key-helper.js +10 -2
- package/src/lib/async-hook-supervisor.cjs +135 -15
- package/src/lib/async-hook-supervisor.js +47 -0
- package/src/lib/background-agent-supervisor.js +35 -12
- package/src/lib/background-task-manager.js +5 -1
- package/src/lib/changelog.js +76 -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/chrome-connector.js +6 -2
- package/src/lib/claude-code-bridge.js +24 -8
- package/src/lib/cli-anything-bridge.js +82 -25
- 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/doctor-checkup.js +18 -6
- package/src/lib/downloader.js +17 -3
- package/src/lib/ensure-utf8.js +11 -3
- package/src/lib/eval/tasks.js +25 -31
- 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 +88 -8
- package/src/lib/hook-runner.js +55 -0
- 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 +129 -24
- 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__/benchmark.test.js +61 -0
- package/src/lib/lsp/__tests__/lsp-client.test.js +6 -1
- package/src/lib/lsp/__tests__/lsp-server-registry.test.js +18 -0
- package/src/lib/lsp/benchmark.js +20 -4
- package/src/lib/lsp/lsp-client.js +22 -3
- package/src/lib/lsp/lsp-manager.js +4 -0
- package/src/lib/lsp/lsp-server-registry.js +11 -2
- package/src/lib/mcp-oauth.js +8 -2
- package/src/lib/npm-invocation.js +29 -0
- package/src/lib/orchestrator.js +8 -2
- package/src/lib/packer/pack-update-applier.js +14 -2
- package/src/lib/packer/pkg-runner.js +13 -2
- package/src/lib/packer/precheck.js +33 -16
- package/src/lib/packer/smoke-runner.js +18 -5
- package/src/lib/packer/web-panel-builder.js +16 -2
- package/src/lib/paths.js +1 -1
- 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 +48 -6
- 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 +11 -3
- 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/repl-bang-memorize.js +10 -2
- package/src/lib/repl-goal.js +19 -2
- package/src/lib/secret-store.js +159 -0
- package/src/lib/service-manager.js +64 -29
- package/src/lib/settings-hook-events.cjs +74 -9
- package/src/lib/settings-hook-events.js +20 -0
- package/src/lib/settings-hooks.cjs +4 -0
- package/src/lib/side-effect-ledger.js +22 -0
- package/src/lib/skill-packs/generator.js +18 -9
- package/src/lib/skill-process-broker.js +71 -0
- package/src/lib/slash-commands.js +10 -2
- package/src/lib/status-line.cjs +28 -7
- package/src/lib/status-line.js +33 -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 +60 -23
- package/src/repl/clipboard-copy.js +8 -2
- package/src/repl/pr-comments.js +30 -7
- package/src/runtime/agent-core.js +554 -118
- 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 +88 -10
- package/src/runtime/headless-stream.js +343 -21
- package/src/runtime/mcp-config.js +16 -1
- package/src/runtime/session-slash-commands.js +506 -0
- package/src/skills/video-editing/extractors/audio-extractor.js +13 -5
- package/src/skills/video-editing/extractors/video-extractor.js +13 -3
- package/src/skills/video-editing/media-process.js +20 -0
- package/src/skills/video-editing/render/audio-mix.js +13 -3
- package/src/skills/video-editing/render/ffmpeg-concat.js +7 -2
- package/src/skills/video-editing/render/ffmpeg-extract.js +7 -2
- package/src/workers/background-agent-worker.js +6 -2
- package/src/assets/web-panel/assets/ChatBubbleRenderer-Ci97vNTs.js +0 -1
- package/src/assets/web-panel/assets/Providers-zZRhNtSu.js +0 -1
- package/src/assets/web-panel/assets/Skills-D_jvQZcj.js +0 -1
- package/src/assets/web-panel/assets/Tasks-DFwxpLIk.js +0 -1
- 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
|
@@ -17,10 +17,9 @@
|
|
|
17
17
|
* agent — only an explicit block decision blocks).
|
|
18
18
|
*
|
|
19
19
|
* Returns a normalized `{ decision, reason, exitCode, stdout, stderr, ... }`.
|
|
20
|
-
*
|
|
20
|
+
* Process runners are injected for unit tests and by the ESM Broker facade.
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
-
const cpDefault = require("node:child_process");
|
|
24
23
|
const {
|
|
25
24
|
normalizeShellKind,
|
|
26
25
|
buildPowershellArgv,
|
|
@@ -28,7 +27,27 @@ const {
|
|
|
28
27
|
} = require("./shell-selector.cjs");
|
|
29
28
|
const { mergeHookDecisions } = require("./hook-event-bus.cjs");
|
|
30
29
|
|
|
31
|
-
const _deps = {
|
|
30
|
+
const _deps = { runSync: null, run: null };
|
|
31
|
+
Object.defineProperties(_deps, {
|
|
32
|
+
spawnSync: {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
get() {
|
|
35
|
+
return this.runSync;
|
|
36
|
+
},
|
|
37
|
+
set(value) {
|
|
38
|
+
this.runSync = value;
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
spawn: {
|
|
42
|
+
enumerable: true,
|
|
43
|
+
get() {
|
|
44
|
+
return this.run;
|
|
45
|
+
},
|
|
46
|
+
set(value) {
|
|
47
|
+
this.run = value;
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
});
|
|
32
51
|
|
|
33
52
|
const HOOK_DECISIONS = Object.freeze({
|
|
34
53
|
BLOCK: "block",
|
|
@@ -232,7 +251,30 @@ function _runCommandHookInner(command, input = {}, opts = {}) {
|
|
|
232
251
|
CLAUDE_HOOK_EVENT: event || input.hook_event_name || "",
|
|
233
252
|
},
|
|
234
253
|
};
|
|
235
|
-
|
|
254
|
+
const processOptions = {
|
|
255
|
+
...common,
|
|
256
|
+
origin: opts.origin || "hook",
|
|
257
|
+
policy: "allow",
|
|
258
|
+
scope: "hook",
|
|
259
|
+
pluginId: opts.pluginId || null,
|
|
260
|
+
pluginVersion: opts.pluginVersion || null,
|
|
261
|
+
pluginSource: opts.pluginSource || null,
|
|
262
|
+
};
|
|
263
|
+
const brokerRunSync =
|
|
264
|
+
opts.broker &&
|
|
265
|
+
opts.origin === "plugin:hook" &&
|
|
266
|
+
typeof opts.broker["spawnSync"] === "function"
|
|
267
|
+
? opts.broker["spawnSync"].bind(opts.broker)
|
|
268
|
+
: null;
|
|
269
|
+
if (brokerRunSync) {
|
|
270
|
+
const invocation = usePowershell
|
|
271
|
+
? buildPowershellArgv(command, shellKind, {
|
|
272
|
+
executionPolicy: loadShellConfig({ cwd: common.cwd })
|
|
273
|
+
.executionPolicy,
|
|
274
|
+
})
|
|
275
|
+
: { file: command, argv: [] };
|
|
276
|
+
res = brokerRunSync(invocation.file, invocation.argv, processOptions);
|
|
277
|
+
} else if (usePowershell) {
|
|
236
278
|
// Per-hook `shell: powershell|pwsh` (settings hook entry): explicit argv
|
|
237
279
|
// instead of the default shell; the enterprise ExecutionPolicy override
|
|
238
280
|
// (settings shell.powershell.executionPolicy) applies here too.
|
|
@@ -240,9 +282,15 @@ function _runCommandHookInner(command, input = {}, opts = {}) {
|
|
|
240
282
|
cwd: common.cwd,
|
|
241
283
|
});
|
|
242
284
|
const inv = buildPowershellArgv(command, shellKind, { executionPolicy });
|
|
243
|
-
|
|
285
|
+
if (typeof _deps.runSync !== "function") {
|
|
286
|
+
throw new Error("hook process runner unavailable");
|
|
287
|
+
}
|
|
288
|
+
res = _deps.runSync(inv.file, inv.argv, processOptions);
|
|
244
289
|
} else {
|
|
245
|
-
|
|
290
|
+
if (typeof _deps.runSync !== "function") {
|
|
291
|
+
throw new Error("hook process runner unavailable");
|
|
292
|
+
}
|
|
293
|
+
res = _deps.runSync(command, { ...processOptions, shell: true });
|
|
246
294
|
}
|
|
247
295
|
} catch (err) {
|
|
248
296
|
return {
|
|
@@ -346,15 +394,37 @@ async function _runCommandHookInnerAsync(command, input = {}, opts = {}) {
|
|
|
346
394
|
...process.env,
|
|
347
395
|
CLAUDE_HOOK_EVENT: event || input.hook_event_name || "",
|
|
348
396
|
};
|
|
397
|
+
const processOptions = {
|
|
398
|
+
cwd: wd,
|
|
399
|
+
env: spawnEnv,
|
|
400
|
+
origin: opts.origin || "hook",
|
|
401
|
+
policy: "allow",
|
|
402
|
+
scope: "hook",
|
|
403
|
+
pluginId: opts.pluginId || null,
|
|
404
|
+
pluginVersion: opts.pluginVersion || null,
|
|
405
|
+
pluginSource: opts.pluginSource || null,
|
|
406
|
+
};
|
|
349
407
|
|
|
350
408
|
let child;
|
|
351
409
|
try {
|
|
410
|
+
const brokerRun =
|
|
411
|
+
opts.broker &&
|
|
412
|
+
opts.origin === "plugin:hook" &&
|
|
413
|
+
typeof opts.broker["spawn"] === "function"
|
|
414
|
+
? opts.broker["spawn"].bind(opts.broker)
|
|
415
|
+
: null;
|
|
416
|
+
const run = brokerRun || _deps.run;
|
|
417
|
+
if (typeof run !== "function") {
|
|
418
|
+
throw new Error("hook process runner unavailable");
|
|
419
|
+
}
|
|
352
420
|
if (usePowershell) {
|
|
353
421
|
const { executionPolicy } = loadShellConfig({ cwd: wd });
|
|
354
422
|
const inv = buildPowershellArgv(command, shellKind, { executionPolicy });
|
|
355
|
-
child =
|
|
423
|
+
child = run(inv.file, inv.argv, processOptions);
|
|
356
424
|
} else {
|
|
357
|
-
child =
|
|
425
|
+
child = brokerRun
|
|
426
|
+
? run(command, [], { ...processOptions, shell: true })
|
|
427
|
+
: run(command, { ...processOptions, shell: true });
|
|
358
428
|
}
|
|
359
429
|
} catch (err) {
|
|
360
430
|
return {
|
|
@@ -444,6 +514,11 @@ function runHooks(commandHooks, input = {}, opts = {}) {
|
|
|
444
514
|
const runOne = (h) =>
|
|
445
515
|
runCommandHook(h.command, input, {
|
|
446
516
|
...opts,
|
|
517
|
+
broker: opts.broker,
|
|
518
|
+
origin: h.origin,
|
|
519
|
+
pluginId: h.pluginId,
|
|
520
|
+
pluginVersion: h.pluginVersion,
|
|
521
|
+
pluginSource: h.pluginSource,
|
|
447
522
|
timeout: h.timeout != null ? h.timeout * 1000 : opts.timeout,
|
|
448
523
|
// per-hook shell selection (P1 #8): `{ "type":"command", "command":…,
|
|
449
524
|
// "shell":"powershell" }` in the settings hook entry
|
|
@@ -504,6 +579,11 @@ async function runHooksParallel(commandHooks, input = {}, opts = {}) {
|
|
|
504
579
|
hooks.map((h) =>
|
|
505
580
|
runCommandHookAsync(h.command, input, {
|
|
506
581
|
...opts,
|
|
582
|
+
broker: opts.broker,
|
|
583
|
+
origin: h.origin,
|
|
584
|
+
pluginId: h.pluginId,
|
|
585
|
+
pluginVersion: h.pluginVersion,
|
|
586
|
+
pluginSource: h.pluginSource,
|
|
507
587
|
timeout: h.timeout != null ? h.timeout * 1000 : opts.timeout,
|
|
508
588
|
shell: h.shell != null ? h.shell : opts.shell,
|
|
509
589
|
}).then((r) => ({ h, r })),
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import runner from "./hook-runner.cjs";
|
|
2
|
+
import executionBroker from "./process-execution-broker/index.js";
|
|
3
|
+
|
|
4
|
+
const brokerRunner = executionBroker.spawn.bind(executionBroker);
|
|
5
|
+
const brokerSyncRunner = executionBroker.spawnSync.bind(executionBroker);
|
|
6
|
+
|
|
7
|
+
export const _processDeps = {
|
|
8
|
+
run: brokerRunner,
|
|
9
|
+
runSync: brokerSyncRunner,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
function normalizeInvocation(argsOrOptions, maybeOptions) {
|
|
13
|
+
return Array.isArray(argsOrOptions)
|
|
14
|
+
? { args: argsOrOptions, options: maybeOptions || {} }
|
|
15
|
+
: { args: [], options: argsOrOptions || {} };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function runHookProcess(file, argsOrOptions, maybeOptions) {
|
|
19
|
+
const { args, options } = normalizeInvocation(argsOrOptions, maybeOptions);
|
|
20
|
+
return _processDeps.run(file, args, {
|
|
21
|
+
...options,
|
|
22
|
+
origin: options.origin || "hook",
|
|
23
|
+
policy: "allow",
|
|
24
|
+
scope: "hook",
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function runHookProcessSync(file, argsOrOptions, maybeOptions) {
|
|
29
|
+
const { args, options } = normalizeInvocation(argsOrOptions, maybeOptions);
|
|
30
|
+
return _processDeps.runSync(file, args, {
|
|
31
|
+
...options,
|
|
32
|
+
origin: options.origin || "hook",
|
|
33
|
+
policy: "allow",
|
|
34
|
+
scope: "hook",
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
runner._deps.run = runHookProcess;
|
|
39
|
+
runner._deps.runSync = runHookProcessSync;
|
|
40
|
+
|
|
41
|
+
export const {
|
|
42
|
+
runCommandHook,
|
|
43
|
+
runCommandHookAsync,
|
|
44
|
+
runHooks,
|
|
45
|
+
runHooksParallel,
|
|
46
|
+
interpretHookOutcome,
|
|
47
|
+
tryParseDecision,
|
|
48
|
+
HOOK_DECISIONS,
|
|
49
|
+
HOOK_PAYLOAD_SCHEMA_VERSION,
|
|
50
|
+
hookBreakerConfig,
|
|
51
|
+
_resetHookBreaker,
|
|
52
|
+
_deps,
|
|
53
|
+
} = runner;
|
|
54
|
+
|
|
55
|
+
export default runner;
|
|
@@ -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
|
*
|
|
@@ -31,10 +31,20 @@
|
|
|
31
31
|
* `\n` / EOS — every parse routine strips `\r+$` first.
|
|
32
32
|
*/
|
|
33
33
|
|
|
34
|
-
import
|
|
35
|
-
import { promisify } from "node:util";
|
|
34
|
+
import executionBroker from "./process-execution-broker/index.js";
|
|
36
35
|
|
|
37
|
-
const
|
|
36
|
+
export const _deps = {
|
|
37
|
+
execFile: (...args) => executionBroker.execFile(...args),
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
function execFileP(file, args, options) {
|
|
41
|
+
return new Promise((resolve, reject) => {
|
|
42
|
+
_deps.execFile(file, args, options, (error, stdout, stderr) => {
|
|
43
|
+
if (error) reject(error);
|
|
44
|
+
else resolve({ stdout, stderr });
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
38
48
|
|
|
39
49
|
export class HostAdbBridgeUnavailableError extends Error {
|
|
40
50
|
constructor(reason) {
|
|
@@ -52,6 +62,10 @@ async function adb(args, opts = {}) {
|
|
|
52
62
|
timeout: opts.timeoutMs || 30_000,
|
|
53
63
|
maxBuffer: 32 * 1024 * 1024,
|
|
54
64
|
encoding: "utf8",
|
|
65
|
+
origin: "host-adb:command",
|
|
66
|
+
policy: "allow",
|
|
67
|
+
scope: "host-adb",
|
|
68
|
+
shell: false,
|
|
55
69
|
});
|
|
56
70
|
if (stderr && /error:|failed:|protocol fault/i.test(stderr)) {
|
|
57
71
|
throw new HostAdbBridgeUnavailableError(stderr.trim().split("\n")[0]);
|
|
@@ -120,27 +134,116 @@ function parseContentQueryRows(stdout) {
|
|
|
120
134
|
return rows;
|
|
121
135
|
}
|
|
122
136
|
|
|
123
|
-
|
|
137
|
+
function mergeContactRows(contactRows, phoneRows, emailRows, organizationRows) {
|
|
138
|
+
const byId = new Map();
|
|
139
|
+
for (const row of contactRows) {
|
|
140
|
+
const contactId = row._id == null ? null : String(row._id);
|
|
141
|
+
const displayName = row.display_name || null;
|
|
142
|
+
if (!contactId || !displayName) continue;
|
|
143
|
+
byId.set(contactId, {
|
|
144
|
+
lookupKey: row.lookup || null,
|
|
145
|
+
displayName,
|
|
146
|
+
phones: [],
|
|
147
|
+
emails: [],
|
|
148
|
+
starred: row.starred === "1",
|
|
149
|
+
organization: null,
|
|
150
|
+
jobTitle: null,
|
|
151
|
+
photoUri: row.photo_uri || null,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const appendUnique = (rows, field, valueOf) => {
|
|
156
|
+
for (const row of rows) {
|
|
157
|
+
const contact = byId.get(String(row.contact_id));
|
|
158
|
+
const value = valueOf(row);
|
|
159
|
+
if (!contact || typeof value !== "string" || !value.trim()) continue;
|
|
160
|
+
const normalized = value.trim();
|
|
161
|
+
if (!contact[field].includes(normalized)) contact[field].push(normalized);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
appendUnique(phoneRows, "phones", (row) => row.data1 || row.number);
|
|
165
|
+
appendUnique(emailRows, "emails", (row) => row.data1 || row.address);
|
|
166
|
+
for (const row of organizationRows) {
|
|
167
|
+
const contact = byId.get(String(row.contact_id));
|
|
168
|
+
if (!contact) continue;
|
|
169
|
+
const organization = row.data1 || row.company;
|
|
170
|
+
const jobTitle = row.data4 || row.title;
|
|
171
|
+
if (!contact.organization && organization && organization.trim()) {
|
|
172
|
+
contact.organization = organization.trim();
|
|
173
|
+
}
|
|
174
|
+
if (!contact.jobTitle && jobTitle && jobTitle.trim()) {
|
|
175
|
+
contact.jobTitle = jobTitle.trim();
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return [...byId.values()];
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async function queryContacts(params, opts) {
|
|
124
182
|
const serial = await pickDevice(opts);
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
183
|
+
const contactArgs = [
|
|
184
|
+
"shell",
|
|
185
|
+
"content",
|
|
186
|
+
"query",
|
|
187
|
+
"--uri",
|
|
188
|
+
"content://com.android.contacts/contacts",
|
|
189
|
+
"--projection",
|
|
190
|
+
"_id:lookup:display_name:starred:photo_uri",
|
|
191
|
+
];
|
|
192
|
+
if (Number.isInteger(params?.since) && params.since > 0) {
|
|
193
|
+
contactArgs.push(
|
|
194
|
+
"--where",
|
|
195
|
+
`contact_last_updated_timestamp >= ${params.since}`,
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
const commandOpts = { ...opts, serial, timeoutMs: opts.timeoutMs || 120_000 };
|
|
199
|
+
const [contactsOut, phonesOut, emailsOut, organizationsOut] =
|
|
200
|
+
await Promise.all([
|
|
201
|
+
adb(contactArgs, commandOpts),
|
|
202
|
+
adb(
|
|
203
|
+
[
|
|
204
|
+
"shell",
|
|
205
|
+
"content",
|
|
206
|
+
"query",
|
|
207
|
+
"--uri",
|
|
208
|
+
"content://com.android.contacts/data/phones",
|
|
209
|
+
"--projection",
|
|
210
|
+
"contact_id:data1",
|
|
211
|
+
],
|
|
212
|
+
commandOpts,
|
|
213
|
+
),
|
|
214
|
+
adb(
|
|
215
|
+
[
|
|
216
|
+
"shell",
|
|
217
|
+
"content",
|
|
218
|
+
"query",
|
|
219
|
+
"--uri",
|
|
220
|
+
"content://com.android.contacts/data/emails",
|
|
221
|
+
"--projection",
|
|
222
|
+
"contact_id:data1",
|
|
223
|
+
],
|
|
224
|
+
commandOpts,
|
|
225
|
+
),
|
|
226
|
+
adb(
|
|
227
|
+
[
|
|
228
|
+
"shell",
|
|
229
|
+
"content",
|
|
230
|
+
"query",
|
|
231
|
+
"--uri",
|
|
232
|
+
"content://com.android.contacts/data",
|
|
233
|
+
"--projection",
|
|
234
|
+
"contact_id:data1:data4",
|
|
235
|
+
"--where",
|
|
236
|
+
"mimetype='vnd.android.cursor.item/organization'",
|
|
237
|
+
],
|
|
238
|
+
commandOpts,
|
|
239
|
+
),
|
|
240
|
+
]);
|
|
241
|
+
return mergeContactRows(
|
|
242
|
+
parseContentQueryRows(contactsOut),
|
|
243
|
+
parseContentQueryRows(phonesOut),
|
|
244
|
+
parseContentQueryRows(emailsOut),
|
|
245
|
+
parseContentQueryRows(organizationsOut),
|
|
136
246
|
);
|
|
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
247
|
}
|
|
145
248
|
|
|
146
249
|
async function listApps(params, opts) {
|
|
@@ -496,7 +599,9 @@ export function createHostAdbBridge(opts = {}) {
|
|
|
496
599
|
|
|
497
600
|
// Exposed for unit testing without spawning real adb.
|
|
498
601
|
export const _internals = {
|
|
602
|
+
adb,
|
|
499
603
|
parseContentQueryRows,
|
|
604
|
+
mergeContactRows,
|
|
500
605
|
listDevices,
|
|
501
606
|
pickDevice,
|
|
502
607
|
queryContacts,
|