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
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Process Execution Broker —
|
|
2
|
+
* Process Execution Broker — P0-1 生产化
|
|
3
3
|
* 对应文档 §2.1 四层架构 Layer 1
|
|
4
4
|
*
|
|
5
5
|
* 统一拦截所有子进程执行:
|
|
6
6
|
* - M1: 所有子进程唯一入口,权限检查
|
|
7
|
-
* -
|
|
7
|
+
* - **P0-1**: 三平台原生沙箱 (macOS Seatbelt / Windows Job Object / Linux seccomp)
|
|
8
|
+
* - **P0-1**: 凭据代理 default-on(secrets 永远不裸传给子进程)
|
|
8
9
|
* - M3: 集成W3C trace context自动传播
|
|
9
10
|
* - M4: 自动写入Runtime Provenance Ledger (RPL)
|
|
10
11
|
* - M5: Hooks v2事件发射
|
|
@@ -25,12 +26,23 @@ import crypto from "node:crypto";
|
|
|
25
26
|
import os from "node:os";
|
|
26
27
|
import path from "node:path";
|
|
27
28
|
import fs from "node:fs";
|
|
29
|
+
import { createRequire } from "node:module";
|
|
30
|
+
|
|
31
|
+
const require = createRequire(import.meta.url);
|
|
32
|
+
|
|
33
|
+
// P0-1: 平台沙箱 + 凭据代理
|
|
34
|
+
// platform-sandbox.js exports: applySandbox, postSpawnSandbox
|
|
35
|
+
import {
|
|
36
|
+
applySandbox as _applySandbox,
|
|
37
|
+
postSpawnSandbox as _postSpawnSandbox,
|
|
38
|
+
} from "./platform-sandbox.js";
|
|
39
|
+
import { credentialAgent } from "./credential-agent.js";
|
|
28
40
|
|
|
29
41
|
// 延迟导入避免循环依赖
|
|
30
42
|
let _traceCtx = null;
|
|
31
43
|
let _rpl = null;
|
|
32
44
|
let _hooksV2 = null;
|
|
33
|
-
|
|
45
|
+
const _ipcBus = null;
|
|
34
46
|
|
|
35
47
|
function getTraceCtx() {
|
|
36
48
|
if (!_traceCtx) {
|
|
@@ -72,13 +84,33 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
72
84
|
this._permissionState = new Map();
|
|
73
85
|
this._defaultTimeout = 300000;
|
|
74
86
|
this._blocked = new Set(["rm -rf /", "format c:", "del /f /s /q *"]);
|
|
75
|
-
this._stats = {
|
|
87
|
+
this._stats = {
|
|
88
|
+
totalSpawned: 0,
|
|
89
|
+
allowed: 0,
|
|
90
|
+
denied: 0,
|
|
91
|
+
byOrigin: {},
|
|
92
|
+
sandboxed: 0,
|
|
93
|
+
credFiltered: 0,
|
|
94
|
+
};
|
|
76
95
|
this._logPath = path.join(
|
|
77
96
|
os.homedir(),
|
|
78
97
|
".chainlesschain",
|
|
79
98
|
"logs",
|
|
80
99
|
"process-audit.log",
|
|
81
100
|
);
|
|
101
|
+
|
|
102
|
+
// P0-1: Platform sandbox functions (applySandbox/postSpawnSandbox imported above)
|
|
103
|
+
// No instance needed — stateless functional API per platform
|
|
104
|
+
|
|
105
|
+
// P0-1: Credential filtering is default-on
|
|
106
|
+
this._credentialAgent = credentialAgent;
|
|
107
|
+
this._credentialFilteringEnabled = true;
|
|
108
|
+
this._sandboxEnabled = true;
|
|
109
|
+
// Keep the legacy aliases used by older call sites and make the strict
|
|
110
|
+
// plugin path use the same switches as the general broker path.
|
|
111
|
+
this._credentialAgentEnabled = true;
|
|
112
|
+
this._platformSandboxEnabled = true;
|
|
113
|
+
|
|
82
114
|
this._ensureLogDir();
|
|
83
115
|
this._loadPermissions();
|
|
84
116
|
}
|
|
@@ -148,6 +180,75 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
148
180
|
return safe;
|
|
149
181
|
}
|
|
150
182
|
|
|
183
|
+
_credentialBoundaryEnabled() {
|
|
184
|
+
return (
|
|
185
|
+
this._credentialFilteringEnabled !== false &&
|
|
186
|
+
this._credentialAgentEnabled !== false
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
_sanitizeAuditArgs(args) {
|
|
191
|
+
const values = Array.isArray(args) ? args : [];
|
|
192
|
+
try {
|
|
193
|
+
return this._credentialAgent.sanitizeArgs(values).sanitizedArgs;
|
|
194
|
+
} catch {
|
|
195
|
+
return values.map(() => "***REDACTION_FAILED***");
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
_applyCredentialBoundary(command, args, spawnOptions, origin) {
|
|
200
|
+
const originalArgs = Array.isArray(args) ? [...args] : [];
|
|
201
|
+
const originalEnv = spawnOptions.env || process.env;
|
|
202
|
+
const input = {
|
|
203
|
+
...spawnOptions,
|
|
204
|
+
env: originalEnv,
|
|
205
|
+
args: originalArgs,
|
|
206
|
+
file: command,
|
|
207
|
+
origin,
|
|
208
|
+
};
|
|
209
|
+
let filtered;
|
|
210
|
+
let report = null;
|
|
211
|
+
if (typeof this._credentialAgent.applyWithReport === "function") {
|
|
212
|
+
const result = this._credentialAgent.applyWithReport(input);
|
|
213
|
+
filtered = result.spawnOptions;
|
|
214
|
+
report = result.report;
|
|
215
|
+
} else {
|
|
216
|
+
filtered = this._credentialAgent.apply(input);
|
|
217
|
+
}
|
|
218
|
+
const filteredArgs = Array.isArray(filtered?.args)
|
|
219
|
+
? filtered.args
|
|
220
|
+
: originalArgs;
|
|
221
|
+
const filteredEnv = filtered?.env || {};
|
|
222
|
+
const inferredEnvCount = Object.keys(originalEnv).filter(
|
|
223
|
+
(key) =>
|
|
224
|
+
this._credentialAgent.isSensitiveKey?.(key) &&
|
|
225
|
+
!Object.prototype.hasOwnProperty.call(filteredEnv, key),
|
|
226
|
+
).length;
|
|
227
|
+
const inferredArgCount = originalArgs.reduce(
|
|
228
|
+
(count, value, index) =>
|
|
229
|
+
count + (String(value) === String(filteredArgs[index]) ? 0 : 1),
|
|
230
|
+
0,
|
|
231
|
+
);
|
|
232
|
+
const credentialReport = report || {
|
|
233
|
+
envCount: inferredEnvCount,
|
|
234
|
+
argCount: inferredArgCount,
|
|
235
|
+
filtered: inferredEnvCount > 0 || inferredArgCount > 0,
|
|
236
|
+
};
|
|
237
|
+
return {
|
|
238
|
+
args: filteredArgs,
|
|
239
|
+
env: filteredEnv,
|
|
240
|
+
report: credentialReport,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
_recordCredentialReport(auditEntry, report) {
|
|
245
|
+
const filtered = report?.filtered === true;
|
|
246
|
+
auditEntry.credentialFiltered = filtered;
|
|
247
|
+
auditEntry.credentialEnvCount = Number(report?.envCount || 0);
|
|
248
|
+
auditEntry.credentialArgCount = Number(report?.argCount || 0);
|
|
249
|
+
if (filtered) this._stats.credFiltered++;
|
|
250
|
+
}
|
|
251
|
+
|
|
151
252
|
_getTraceContext() {
|
|
152
253
|
const traceCtx = getTraceCtx();
|
|
153
254
|
if (traceCtx && traceCtx.activeContext) {
|
|
@@ -224,7 +325,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
224
325
|
origin,
|
|
225
326
|
scope,
|
|
226
327
|
command,
|
|
227
|
-
args: args
|
|
328
|
+
args: this._sanitizeAuditArgs(args),
|
|
228
329
|
cwd,
|
|
229
330
|
startTime,
|
|
230
331
|
permissionDecision: decision,
|
|
@@ -235,6 +336,9 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
235
336
|
exitCode: null,
|
|
236
337
|
endTime: null,
|
|
237
338
|
durationMs: null,
|
|
339
|
+
pluginId: options.pluginId || null,
|
|
340
|
+
pluginVersion: options.pluginVersion || null,
|
|
341
|
+
pluginSource: options.pluginSource || null,
|
|
238
342
|
};
|
|
239
343
|
|
|
240
344
|
if (decision === "deny" || decision === "prompt") {
|
|
@@ -269,9 +373,73 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
269
373
|
spawnOpts.env.TRACEPARENT = traceCtx.traceparent;
|
|
270
374
|
}
|
|
271
375
|
|
|
376
|
+
// P0-1: Credential filtering (default-on) — strip secrets from env/args
|
|
377
|
+
if (this._credentialBoundaryEnabled()) {
|
|
378
|
+
const credentialBoundary = this._applyCredentialBoundary(
|
|
379
|
+
command,
|
|
380
|
+
args,
|
|
381
|
+
spawnOpts,
|
|
382
|
+
origin,
|
|
383
|
+
);
|
|
384
|
+
spawnOpts.env = credentialBoundary.env;
|
|
385
|
+
args = credentialBoundary.args;
|
|
386
|
+
auditEntry.args = [...args];
|
|
387
|
+
this._recordCredentialReport(auditEntry, credentialBoundary.report);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// P0-1: Platform sandbox wrapping — apply macOS/Windows/Linux sandbox
|
|
391
|
+
const optsForSpawn = { ...spawnOpts };
|
|
392
|
+
let sandboxApplied = false;
|
|
393
|
+
let sandboxProfile = null;
|
|
394
|
+
if (this._platformSandboxEnabled) {
|
|
395
|
+
try {
|
|
396
|
+
const result = _applySandbox(
|
|
397
|
+
command,
|
|
398
|
+
args || [],
|
|
399
|
+
optsForSpawn,
|
|
400
|
+
"default",
|
|
401
|
+
);
|
|
402
|
+
if (result && result.applied) {
|
|
403
|
+
Object.assign(optsForSpawn, result.options || {});
|
|
404
|
+
if (result.command) command = result.command;
|
|
405
|
+
if (result.args) args = result.args;
|
|
406
|
+
sandboxApplied = true;
|
|
407
|
+
sandboxProfile = result.profile || null;
|
|
408
|
+
this._stats.sandboxed++;
|
|
409
|
+
}
|
|
410
|
+
auditEntry.sandboxed = sandboxApplied;
|
|
411
|
+
auditEntry.sandboxProfile = sandboxProfile;
|
|
412
|
+
} catch (sandboxErr) {
|
|
413
|
+
// Fail closed: if sandbox setup fails on strict, deny spawn
|
|
414
|
+
if (process.env.CC_SANDBOX_STRICT === "1") {
|
|
415
|
+
auditEntry.deniedReason = `sandbox-init-failed: ${sandboxErr.message}`;
|
|
416
|
+
this._auditLog.push(auditEntry);
|
|
417
|
+
const err = new Error(`Sandbox init failed: ${sandboxErr.message}`);
|
|
418
|
+
err.auditEntry = auditEntry;
|
|
419
|
+
throw err;
|
|
420
|
+
}
|
|
421
|
+
// Non-strict: warn but allow (development mode)
|
|
422
|
+
process.emitWarning(
|
|
423
|
+
`Sandbox init failed (continuing without): ${sandboxErr.message}`,
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
272
428
|
// Use native spawn from _native (set by patch-child-process.js)
|
|
273
|
-
const
|
|
274
|
-
const proc =
|
|
429
|
+
const nativeSpawnFn = this._native?.spawn || nativeSpawn;
|
|
430
|
+
const proc = nativeSpawnFn(command, args, optsForSpawn);
|
|
431
|
+
|
|
432
|
+
// P0-1: Post-spawn sandbox setup (Windows Job Object association, etc.)
|
|
433
|
+
if (sandboxApplied && proc.pid) {
|
|
434
|
+
try {
|
|
435
|
+
_postSpawnSandbox(proc, sandboxProfile);
|
|
436
|
+
} catch (postErr) {
|
|
437
|
+
process.emitWarning(
|
|
438
|
+
`Post-spawn sandbox setup failed: ${postErr.message}`,
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
275
443
|
auditEntry.pid = proc.pid;
|
|
276
444
|
this._recordAudit(auditEntry);
|
|
277
445
|
this._writeRplEntry(auditEntry, "started");
|
|
@@ -313,7 +481,10 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
313
481
|
error: err.message,
|
|
314
482
|
component: origin,
|
|
315
483
|
});
|
|
316
|
-
|
|
484
|
+
// EventEmitter treats an unhandled `error` event as an exception. A
|
|
485
|
+
// process ENOENT must reach the child-process listener/callback instead
|
|
486
|
+
// of crashing callers that did not subscribe to broker diagnostics.
|
|
487
|
+
if (this.listenerCount("error") > 0) this.emit("error", auditEntry);
|
|
317
488
|
});
|
|
318
489
|
return proc;
|
|
319
490
|
}
|
|
@@ -339,7 +510,7 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
339
510
|
origin,
|
|
340
511
|
scope,
|
|
341
512
|
command,
|
|
342
|
-
args: args
|
|
513
|
+
args: this._sanitizeAuditArgs(args),
|
|
343
514
|
cwd,
|
|
344
515
|
startTime,
|
|
345
516
|
permissionDecision: decision,
|
|
@@ -347,6 +518,9 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
347
518
|
isDangerous,
|
|
348
519
|
shell: !!options.shell,
|
|
349
520
|
sync: true,
|
|
521
|
+
pluginId: options.pluginId || null,
|
|
522
|
+
pluginVersion: options.pluginVersion || null,
|
|
523
|
+
pluginSource: options.pluginSource || null,
|
|
350
524
|
};
|
|
351
525
|
|
|
352
526
|
if (decision === "deny" || decision === "prompt") {
|
|
@@ -374,9 +548,59 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
374
548
|
spawnOpts.env.TRACEPARENT = traceCtx.traceparent;
|
|
375
549
|
}
|
|
376
550
|
|
|
377
|
-
|
|
551
|
+
// P0-1: Credential filtering agent — strip secrets from env/args before spawn
|
|
552
|
+
if (this._credentialBoundaryEnabled()) {
|
|
553
|
+
const credentialBoundary = this._applyCredentialBoundary(
|
|
554
|
+
command,
|
|
555
|
+
args,
|
|
556
|
+
spawnOpts,
|
|
557
|
+
origin,
|
|
558
|
+
);
|
|
559
|
+
spawnOpts.env = credentialBoundary.env;
|
|
560
|
+
args = credentialBoundary.args;
|
|
561
|
+
auditEntry.args = [...args];
|
|
562
|
+
this._recordCredentialReport(auditEntry, credentialBoundary.report);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// P0-1: Platform sandbox wrapping (sync path)
|
|
566
|
+
const optsForSync = { ...spawnOpts };
|
|
567
|
+
let sandboxApplied = false;
|
|
568
|
+
let sandboxProfile = null;
|
|
569
|
+
if (this._platformSandboxEnabled) {
|
|
570
|
+
try {
|
|
571
|
+
const result = _applySandbox(
|
|
572
|
+
command,
|
|
573
|
+
args || [],
|
|
574
|
+
optsForSync,
|
|
575
|
+
"default",
|
|
576
|
+
);
|
|
577
|
+
if (result && result.applied) {
|
|
578
|
+
Object.assign(optsForSync, result.options || {});
|
|
579
|
+
if (result.command) command = result.command;
|
|
580
|
+
if (result.args) args = result.args;
|
|
581
|
+
sandboxApplied = true;
|
|
582
|
+
sandboxProfile = result.profile || null;
|
|
583
|
+
this._stats.sandboxed++;
|
|
584
|
+
}
|
|
585
|
+
auditEntry.sandboxed = sandboxApplied;
|
|
586
|
+
auditEntry.sandboxProfile = sandboxProfile;
|
|
587
|
+
} catch (sandboxErr) {
|
|
588
|
+
if (process.env.CC_SANDBOX_STRICT === "1") {
|
|
589
|
+
auditEntry.deniedReason = `sandbox-init-failed: ${sandboxErr.message}`;
|
|
590
|
+
this._recordAudit(auditEntry);
|
|
591
|
+
const err = new Error(`Sandbox init failed: ${sandboxErr.message}`);
|
|
592
|
+
err.auditEntry = auditEntry;
|
|
593
|
+
throw err;
|
|
594
|
+
}
|
|
595
|
+
process.emitWarning(
|
|
596
|
+
`Sandbox init failed (sync): ${sandboxErr.message}`,
|
|
597
|
+
);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
const nativeSpawnSyncFn = this._native?.spawnSync || nativeSpawnSync;
|
|
378
602
|
try {
|
|
379
|
-
const result =
|
|
603
|
+
const result = nativeSpawnSyncFn(command, args, optsForSync);
|
|
380
604
|
auditEntry.exitCode = result.status;
|
|
381
605
|
auditEntry.endTime = Date.now();
|
|
382
606
|
auditEntry.durationMs = auditEntry.endTime - startTime;
|
|
@@ -393,6 +617,94 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
393
617
|
}
|
|
394
618
|
}
|
|
395
619
|
|
|
620
|
+
/**
|
|
621
|
+
* Route a node-pty session through the same provenance and credential
|
|
622
|
+
* boundary as child_process execution. node-pty owns the native PTY
|
|
623
|
+
* allocation, so the platform sandbox is reported as unavailable here
|
|
624
|
+
* rather than being falsely marked as applied.
|
|
625
|
+
*/
|
|
626
|
+
spawnPty(ptyModule, command, args = [], options = {}) {
|
|
627
|
+
if (!ptyModule || typeof ptyModule.spawn !== "function") {
|
|
628
|
+
throw new TypeError("pty_module_spawn_unavailable");
|
|
629
|
+
}
|
|
630
|
+
const executionId = crypto.randomUUID();
|
|
631
|
+
const startTime = Date.now();
|
|
632
|
+
const origin = options.origin || "terminal:pty";
|
|
633
|
+
const scope = options.scope || "terminal";
|
|
634
|
+
const policy = options.policy || "allow";
|
|
635
|
+
const auditEntry = {
|
|
636
|
+
executionId,
|
|
637
|
+
traceId: this._getTraceContext()?.traceId || null,
|
|
638
|
+
origin,
|
|
639
|
+
scope,
|
|
640
|
+
command,
|
|
641
|
+
args: this._sanitizeAuditArgs(args),
|
|
642
|
+
cwd: options.cwd || process.cwd(),
|
|
643
|
+
startTime,
|
|
644
|
+
permissionDecision: policy,
|
|
645
|
+
policy,
|
|
646
|
+
operation: "pty.spawn",
|
|
647
|
+
pty: true,
|
|
648
|
+
sandboxed: false,
|
|
649
|
+
sandboxReason: "native_pty_host_boundary",
|
|
650
|
+
pluginId: options.pluginId || null,
|
|
651
|
+
pluginVersion: options.pluginVersion || null,
|
|
652
|
+
pluginSource: options.pluginSource || null,
|
|
653
|
+
};
|
|
654
|
+
if (policy === "deny" || policy === "prompt") {
|
|
655
|
+
auditEntry.deniedReason = `policy_${policy}`;
|
|
656
|
+
auditEntry.endTime = Date.now();
|
|
657
|
+
auditEntry.durationMs = 0;
|
|
658
|
+
this._recordAudit(auditEntry);
|
|
659
|
+
this._writeRplEntry(
|
|
660
|
+
auditEntry,
|
|
661
|
+
"denied",
|
|
662
|
+
new Error(auditEntry.deniedReason),
|
|
663
|
+
);
|
|
664
|
+
const error = new Error(`PTY spawn denied: ${auditEntry.deniedReason}`);
|
|
665
|
+
error.auditEntry = auditEntry;
|
|
666
|
+
throw error;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
const spawnOptions = { ...options, args: [...auditEntry.args] };
|
|
670
|
+
delete spawnOptions.origin;
|
|
671
|
+
delete spawnOptions.policy;
|
|
672
|
+
delete spawnOptions.scope;
|
|
673
|
+
delete spawnOptions.pluginId;
|
|
674
|
+
delete spawnOptions.pluginVersion;
|
|
675
|
+
delete spawnOptions.pluginSource;
|
|
676
|
+
try {
|
|
677
|
+
if (this._credentialBoundaryEnabled()) {
|
|
678
|
+
const credentialBoundary = this._applyCredentialBoundary(
|
|
679
|
+
command,
|
|
680
|
+
args,
|
|
681
|
+
spawnOptions,
|
|
682
|
+
origin,
|
|
683
|
+
);
|
|
684
|
+
spawnOptions.env = credentialBoundary.env;
|
|
685
|
+
spawnOptions.args = credentialBoundary.args;
|
|
686
|
+
auditEntry.args = [...credentialBoundary.args];
|
|
687
|
+
this._recordCredentialReport(auditEntry, credentialBoundary.report);
|
|
688
|
+
}
|
|
689
|
+
const filteredArgs = spawnOptions.args || [];
|
|
690
|
+
delete spawnOptions.args;
|
|
691
|
+
const proc = ptyModule.spawn(command, filteredArgs, spawnOptions);
|
|
692
|
+
auditEntry.pid = proc?.pid ?? null;
|
|
693
|
+
auditEntry.endTime = Date.now();
|
|
694
|
+
auditEntry.durationMs = auditEntry.endTime - startTime;
|
|
695
|
+
this._recordAudit(auditEntry);
|
|
696
|
+
this._writeRplEntry(auditEntry, "started");
|
|
697
|
+
return proc;
|
|
698
|
+
} catch (error) {
|
|
699
|
+
auditEntry.error = error.message;
|
|
700
|
+
auditEntry.endTime = Date.now();
|
|
701
|
+
auditEntry.durationMs = auditEntry.endTime - startTime;
|
|
702
|
+
this._recordAudit(auditEntry);
|
|
703
|
+
this._writeRplEntry(auditEntry, "error", error);
|
|
704
|
+
throw error;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
|
|
396
708
|
exec(command, options, callback) {
|
|
397
709
|
const opts = typeof options === "function" ? {} : options;
|
|
398
710
|
const cb = typeof options === "function" ? options : callback;
|
|
@@ -409,15 +721,129 @@ class ProcessExecutionBroker extends EventEmitter {
|
|
|
409
721
|
shell: true,
|
|
410
722
|
origin: options.origin || "shell:execSync",
|
|
411
723
|
};
|
|
412
|
-
|
|
724
|
+
const result = this.spawnSync(command, [], spawnOpts);
|
|
725
|
+
if (result?.error) throw result.error;
|
|
726
|
+
if (result?.status != null && result.status !== 0) {
|
|
727
|
+
const error = new Error(
|
|
728
|
+
`Command failed (exit ${result.status}): ${command}`,
|
|
729
|
+
);
|
|
730
|
+
error.status = result.status;
|
|
731
|
+
error.stdout = result.stdout;
|
|
732
|
+
error.stderr = result.stderr;
|
|
733
|
+
throw error;
|
|
734
|
+
}
|
|
735
|
+
return result?.stdout ?? "";
|
|
413
736
|
}
|
|
414
737
|
|
|
415
738
|
execFile(file, args, options, callback) {
|
|
416
|
-
|
|
739
|
+
if (typeof args === "function") {
|
|
740
|
+
callback = args;
|
|
741
|
+
args = [];
|
|
742
|
+
options = {};
|
|
743
|
+
} else if (!Array.isArray(args)) {
|
|
744
|
+
callback = typeof options === "function" ? options : callback;
|
|
745
|
+
options = args || {};
|
|
746
|
+
args = [];
|
|
747
|
+
} else if (typeof options === "function") {
|
|
748
|
+
callback = options;
|
|
749
|
+
options = {};
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
options = options || {};
|
|
753
|
+
const proc = this.spawn(file, args, options);
|
|
754
|
+
if (typeof callback !== "function") return proc;
|
|
755
|
+
|
|
756
|
+
const stdoutChunks = [];
|
|
757
|
+
const stderrChunks = [];
|
|
758
|
+
const outputEncoding = options.encoding ?? "utf8";
|
|
759
|
+
const returnBuffers =
|
|
760
|
+
outputEncoding === "buffer" || outputEncoding === null;
|
|
761
|
+
const configuredMaxBuffer = options.maxBuffer;
|
|
762
|
+
const maxBuffer =
|
|
763
|
+
configuredMaxBuffer === Infinity
|
|
764
|
+
? Infinity
|
|
765
|
+
: Number.isFinite(configuredMaxBuffer) && configuredMaxBuffer >= 0
|
|
766
|
+
? configuredMaxBuffer
|
|
767
|
+
: 1024 * 1024;
|
|
768
|
+
let stdoutBytes = 0;
|
|
769
|
+
let stderrBytes = 0;
|
|
770
|
+
let completionError = null;
|
|
771
|
+
let completed = false;
|
|
772
|
+
|
|
773
|
+
const asBuffer = (chunk) =>
|
|
774
|
+
Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));
|
|
775
|
+
const render = (chunks) => {
|
|
776
|
+
const value = Buffer.concat(chunks);
|
|
777
|
+
return returnBuffers ? value : value.toString(outputEncoding);
|
|
778
|
+
};
|
|
779
|
+
const finish = (error, code = null, signal = null) => {
|
|
780
|
+
if (completed) return;
|
|
781
|
+
completed = true;
|
|
782
|
+
const stdout = render(stdoutChunks);
|
|
783
|
+
const stderr = render(stderrChunks);
|
|
784
|
+
if (error) {
|
|
785
|
+
error.stdout = stdout;
|
|
786
|
+
error.stderr = stderr;
|
|
787
|
+
if (error.status === undefined) error.status = code;
|
|
788
|
+
if (error.signal === undefined) error.signal = signal;
|
|
789
|
+
}
|
|
790
|
+
callback(error, stdout, stderr);
|
|
791
|
+
};
|
|
792
|
+
const collect = (stream, chunks, streamName) => {
|
|
793
|
+
if (!stream || typeof stream.on !== "function") return;
|
|
794
|
+
stream.on("data", (chunk) => {
|
|
795
|
+
const value = asBuffer(chunk);
|
|
796
|
+
chunks.push(value);
|
|
797
|
+
if (streamName === "stdout") stdoutBytes += value.length;
|
|
798
|
+
else stderrBytes += value.length;
|
|
799
|
+
const streamBytes = streamName === "stdout" ? stdoutBytes : stderrBytes;
|
|
800
|
+
if (!completionError && streamBytes > maxBuffer) {
|
|
801
|
+
completionError = new Error(`${streamName} maxBuffer exceeded`);
|
|
802
|
+
completionError.code = "ERR_CHILD_PROCESS_STDIO_MAXBUFFER";
|
|
803
|
+
completionError.stream = streamName;
|
|
804
|
+
try {
|
|
805
|
+
proc.kill(options.killSignal || "SIGTERM");
|
|
806
|
+
} catch {}
|
|
807
|
+
}
|
|
808
|
+
});
|
|
809
|
+
};
|
|
810
|
+
|
|
811
|
+
collect(proc.stdout, stdoutChunks, "stdout");
|
|
812
|
+
collect(proc.stderr, stderrChunks, "stderr");
|
|
813
|
+
proc.once("error", (error) => finish(error));
|
|
814
|
+
proc.once("close", (code, signal) => {
|
|
815
|
+
if (completionError) return finish(completionError, code, signal);
|
|
816
|
+
if (code === 0) return finish(null, code, signal);
|
|
817
|
+
const error = new Error(
|
|
818
|
+
`Command failed (exit ${code ?? "unknown"}): ${file}`,
|
|
819
|
+
);
|
|
820
|
+
error.code = code;
|
|
821
|
+
error.killed = Boolean(proc.killed);
|
|
822
|
+
error.signal = signal;
|
|
823
|
+
error.status = code;
|
|
824
|
+
return finish(error, code, signal);
|
|
825
|
+
});
|
|
826
|
+
return proc;
|
|
417
827
|
}
|
|
418
828
|
|
|
419
829
|
execFileSync(file, args, options = {}) {
|
|
420
|
-
|
|
830
|
+
if (!Array.isArray(args)) {
|
|
831
|
+
options = args || {};
|
|
832
|
+
args = [];
|
|
833
|
+
}
|
|
834
|
+
const result = this.spawnSync(file, args, options);
|
|
835
|
+
if (result?.error) throw result.error;
|
|
836
|
+
if (result?.status !== 0) {
|
|
837
|
+
const error = new Error(
|
|
838
|
+
`Command failed (exit ${result?.status ?? "unknown"}): ${file}`,
|
|
839
|
+
);
|
|
840
|
+
error.status = result?.status ?? null;
|
|
841
|
+
error.signal = result?.signal ?? null;
|
|
842
|
+
error.stdout = result?.stdout;
|
|
843
|
+
error.stderr = result?.stderr;
|
|
844
|
+
throw error;
|
|
845
|
+
}
|
|
846
|
+
return result?.stdout ?? "";
|
|
421
847
|
}
|
|
422
848
|
|
|
423
849
|
fork(modulePath, args, options = {}) {
|
|
@@ -3,10 +3,9 @@
|
|
|
3
3
|
* This runs at CLI startup, before any other imports, ensuring every subprocess is audited
|
|
4
4
|
*/
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
|
-
|
|
6
|
+
import { executionBroker } from "./index.js";
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
const { executionBroker } = require("./index.js");
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
10
9
|
|
|
11
10
|
// Get the REAL native child_process module (unpatched, from Node.js internals)
|
|
12
11
|
const nativeCp = require("node:child_process");
|