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
|
@@ -79,6 +79,7 @@ import {
|
|
|
79
79
|
reconcileSideEffects,
|
|
80
80
|
classifyToolSideEffect,
|
|
81
81
|
} from "../lib/side-effect-ledger.js";
|
|
82
|
+
import { DiffReviewFollowUpTracker } from "../lib/diff-review-follow-up.js";
|
|
82
83
|
import {
|
|
83
84
|
loadSideEffectLedger,
|
|
84
85
|
persistSideEffectLedger,
|
|
@@ -240,26 +241,106 @@ export function createStreamCoalescer({
|
|
|
240
241
|
export function planSnapshot(pm) {
|
|
241
242
|
let items = [];
|
|
242
243
|
let risk = null;
|
|
244
|
+
let planId = null;
|
|
245
|
+
let planVersion = null;
|
|
246
|
+
let previousPlanId = null;
|
|
247
|
+
let executionLock = null;
|
|
243
248
|
try {
|
|
244
249
|
const plan = pm.currentPlan;
|
|
250
|
+
planId = plan?.id || null;
|
|
251
|
+
planVersion = plan?.version || null;
|
|
252
|
+
previousPlanId = plan?.revisionOf || null;
|
|
245
253
|
items = (plan?.items || []).map((i) => ({
|
|
246
254
|
id: i.id,
|
|
247
255
|
title: i.title,
|
|
248
256
|
tool: i.tool,
|
|
249
257
|
impact: i.estimatedImpact || "low",
|
|
250
258
|
status: i.status,
|
|
259
|
+
...(i.turn ? { turn: i.turn } : {}),
|
|
260
|
+
...(i.toolUseId ? { tool_use_id: i.toolUseId } : {}),
|
|
261
|
+
...(i.startedAt ? { started_at: i.startedAt } : {}),
|
|
262
|
+
...(i.completedAt ? { completed_at: i.completedAt } : {}),
|
|
263
|
+
...(i.error ? { error: String(i.error).slice(0, 1000) } : {}),
|
|
251
264
|
}));
|
|
252
265
|
if (items.length > 0) {
|
|
253
266
|
const r = pm.getRiskAssessment();
|
|
254
267
|
if (r) risk = { level: r.level, totalScore: r.totalScore };
|
|
255
268
|
}
|
|
269
|
+
executionLock = pm.getExecutionLock?.() || null;
|
|
256
270
|
} catch {
|
|
257
271
|
/* snapshot is best-effort */
|
|
258
272
|
}
|
|
259
|
-
return {
|
|
273
|
+
return {
|
|
274
|
+
active: pm.isActive(),
|
|
275
|
+
state: pm.state || null,
|
|
276
|
+
plan_id: planId,
|
|
277
|
+
plan_version: planVersion,
|
|
278
|
+
previous_plan_id: previousPlanId,
|
|
279
|
+
items,
|
|
280
|
+
risk,
|
|
281
|
+
...(executionLock ? { execution_lock: executionLock } : {}),
|
|
282
|
+
};
|
|
260
283
|
}
|
|
261
284
|
|
|
262
285
|
const MAX_PLAN_REVIEW_SNAPSHOT_CHARS = 24000;
|
|
286
|
+
const MAX_PLAN_REVIEW_COMMENTS = 64;
|
|
287
|
+
const MAX_PLAN_REVIEW_COMMENT_CHARS = 2000;
|
|
288
|
+
|
|
289
|
+
function boundedReviewString(value, limit) {
|
|
290
|
+
return String(value == null ? "" : value).slice(0, limit);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function normalizePlanReviewComments(values) {
|
|
294
|
+
const out = [];
|
|
295
|
+
let remaining = MAX_PLAN_REVIEW_SNAPSHOT_CHARS;
|
|
296
|
+
for (const raw of Array.isArray(values)
|
|
297
|
+
? values.slice(0, MAX_PLAN_REVIEW_COMMENTS)
|
|
298
|
+
: []) {
|
|
299
|
+
if (!raw || typeof raw !== "object" || remaining <= 0) continue;
|
|
300
|
+
const text = boundedReviewString(
|
|
301
|
+
raw.text,
|
|
302
|
+
Math.min(MAX_PLAN_REVIEW_COMMENT_CHARS, remaining),
|
|
303
|
+
).trim();
|
|
304
|
+
if (!text) continue;
|
|
305
|
+
remaining -= text.length;
|
|
306
|
+
const positive = (value) => {
|
|
307
|
+
const number = Number(value);
|
|
308
|
+
return Number.isInteger(number) && number > 0 ? number : null;
|
|
309
|
+
};
|
|
310
|
+
out.push({
|
|
311
|
+
id: boundedReviewString(raw.id, 160) || `comment-${out.length + 1}`,
|
|
312
|
+
sourceLine: positive(raw.sourceLine),
|
|
313
|
+
itemId: boundedReviewString(raw.itemId, 160) || null,
|
|
314
|
+
text,
|
|
315
|
+
file: boundedReviewString(raw.file, 1024) || null,
|
|
316
|
+
line: positive(raw.line),
|
|
317
|
+
column: positive(raw.column),
|
|
318
|
+
turn: positive(raw.turn),
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
return out;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function normalizePlanExecutionLock(value) {
|
|
325
|
+
if (!value || typeof value !== "object") return null;
|
|
326
|
+
const strings = (input, limit = 128) => [
|
|
327
|
+
...new Set(
|
|
328
|
+
(Array.isArray(input) ? input : [])
|
|
329
|
+
.slice(0, limit)
|
|
330
|
+
.map((entry) => boundedReviewString(entry, 160))
|
|
331
|
+
.filter(Boolean),
|
|
332
|
+
),
|
|
333
|
+
];
|
|
334
|
+
return {
|
|
335
|
+
planId: boundedReviewString(value.planId, 160),
|
|
336
|
+
permissionMode: boundedReviewString(value.permissionMode, 64) || "default",
|
|
337
|
+
approvedItemIds: strings(value.approvedItemIds),
|
|
338
|
+
allowedTools: strings(value.allowedTools),
|
|
339
|
+
...(value.createdAt
|
|
340
|
+
? { createdAt: boundedReviewString(value.createdAt, 64) }
|
|
341
|
+
: {}),
|
|
342
|
+
};
|
|
343
|
+
}
|
|
263
344
|
|
|
264
345
|
function planReviewFromInput(obj) {
|
|
265
346
|
const review =
|
|
@@ -270,7 +351,8 @@ function planReviewFromInput(obj) {
|
|
|
270
351
|
: typeof review?.snapshot === "string"
|
|
271
352
|
? review.snapshot
|
|
272
353
|
: "";
|
|
273
|
-
|
|
354
|
+
const comments = normalizePlanReviewComments(review?.comments);
|
|
355
|
+
if (!snapshot.trim() && comments.length === 0) return null;
|
|
274
356
|
const text =
|
|
275
357
|
snapshot.length > MAX_PLAN_REVIEW_SNAPSHOT_CHARS
|
|
276
358
|
? snapshot.slice(0, MAX_PLAN_REVIEW_SNAPSHOT_CHARS) +
|
|
@@ -282,22 +364,43 @@ function planReviewFromInput(obj) {
|
|
|
282
364
|
typeof review?.reviewedAt === "string" ? review.reviewedAt : null,
|
|
283
365
|
conversationId:
|
|
284
366
|
typeof review?.conversationId === "string" ? review.conversationId : null,
|
|
367
|
+
revision:
|
|
368
|
+
Number.isInteger(review?.revision) && review.revision > 0
|
|
369
|
+
? review.revision
|
|
370
|
+
: null,
|
|
371
|
+
comments,
|
|
372
|
+
executionLock: normalizePlanExecutionLock(review?.executionLock),
|
|
285
373
|
snapshot: text,
|
|
286
374
|
};
|
|
287
375
|
}
|
|
288
376
|
|
|
289
377
|
function planReviewSystemMessage(review) {
|
|
290
|
-
if (!review?.
|
|
378
|
+
if (!review || (!review.snapshot && !review.comments?.length)) return null;
|
|
291
379
|
const meta = [
|
|
292
380
|
review.action ? `action=${review.action}` : null,
|
|
293
381
|
review.reviewedAt ? `reviewedAt=${review.reviewedAt}` : null,
|
|
294
382
|
review.conversationId ? `conversationId=${review.conversationId}` : null,
|
|
383
|
+
review.revision ? `revision=${review.revision}` : null,
|
|
295
384
|
]
|
|
296
385
|
.filter(Boolean)
|
|
297
386
|
.join(" ");
|
|
298
|
-
|
|
299
|
-
"[PLAN REVIEW SNAPSHOT]" + (meta ? ` ${meta}` : "")
|
|
300
|
-
|
|
387
|
+
const sections = [
|
|
388
|
+
"[PLAN REVIEW SNAPSHOT]" + (meta ? ` ${meta}` : ""),
|
|
389
|
+
review.snapshot || "(no Markdown snapshot)",
|
|
390
|
+
];
|
|
391
|
+
if (review.comments?.length) {
|
|
392
|
+
sections.push(
|
|
393
|
+
"[PLAN REVIEW STRUCTURED COMMENTS]",
|
|
394
|
+
JSON.stringify(review.comments),
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
if (review.executionLock) {
|
|
398
|
+
sections.push(
|
|
399
|
+
"[PLAN REVIEW REQUESTED EXECUTION LOCK - AUDIT ONLY]",
|
|
400
|
+
JSON.stringify(review.executionLock),
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
return sections.join("\n");
|
|
301
404
|
}
|
|
302
405
|
import { withQuietStdout } from "./quiet-stdout.js";
|
|
303
406
|
|
|
@@ -329,7 +432,8 @@ export function parseInputEvent(line) {
|
|
|
329
432
|
// Plan-mode control events (chat-panel plan UI):
|
|
330
433
|
// {"type":"plan","action":"enter"|"approve"|"reject"}
|
|
331
434
|
if (obj && typeof obj === "object" && obj.type === "plan") {
|
|
332
|
-
const
|
|
435
|
+
const rawAction = String(obj.action || "").toLowerCase();
|
|
436
|
+
const action = rawAction === "requestchanges" ? "revise" : rawAction;
|
|
333
437
|
if (!action) return null;
|
|
334
438
|
const planReview = planReviewFromInput(obj);
|
|
335
439
|
return planReview ? { plan: action, planReview } : { plan: action };
|
|
@@ -583,7 +687,7 @@ function buildSideEffectRecovery(ledger) {
|
|
|
583
687
|
async function runTurn(
|
|
584
688
|
messages,
|
|
585
689
|
loopOptions,
|
|
586
|
-
{ runLoop, emit, costBudget, nextToolUseId, sideEffects },
|
|
690
|
+
{ runLoop, emit, costBudget, nextToolUseId, sideEffects, turnNumber },
|
|
587
691
|
) {
|
|
588
692
|
const usage = {
|
|
589
693
|
input_tokens: 0,
|
|
@@ -595,10 +699,14 @@ async function runTurn(
|
|
|
595
699
|
let finalText = "";
|
|
596
700
|
let endReason = "complete";
|
|
597
701
|
let stopForCost = false;
|
|
702
|
+
let responseCompleted = false;
|
|
598
703
|
// P0-2: the side-effect op currently in flight (at most one — the loop runs
|
|
599
704
|
// tools serially). Non-null only between a dangerous tool's tool-executing
|
|
600
705
|
// and its tool-result.
|
|
601
706
|
let currentSideEffectOpId = null;
|
|
707
|
+
const diffReviewFollowUps = new DiffReviewFollowUpTracker(
|
|
708
|
+
sideEffects?.ledger,
|
|
709
|
+
);
|
|
602
710
|
|
|
603
711
|
// Collapse consecutive same-role turns before the model call ONLY when the
|
|
604
712
|
// caller flags a resume-degenerate transcript (`mergeRoles`): a resumed
|
|
@@ -629,13 +737,28 @@ async function runTurn(
|
|
|
629
737
|
// agent-sdk docs/PROTOCOL.md §1.2.1): the matching tool_result below
|
|
630
738
|
// echoes the same id so UIs can pair calls without adjacency.
|
|
631
739
|
const toolUseId = nextToolUseId ? nextToolUseId() : undefined;
|
|
632
|
-
|
|
740
|
+
const pm = getPlanModeManager();
|
|
741
|
+
const planItem = pm.startPlanItemForTool(event.tool, {
|
|
742
|
+
toolUseId,
|
|
743
|
+
turn: turnNumber,
|
|
744
|
+
});
|
|
745
|
+
toolCalls.push({
|
|
746
|
+
id: toolUseId,
|
|
747
|
+
tool: event.tool,
|
|
748
|
+
args: event.args,
|
|
749
|
+
planItemId: planItem?.id || null,
|
|
750
|
+
});
|
|
633
751
|
emit({
|
|
634
752
|
type: "tool_use",
|
|
635
753
|
...(toolUseId ? { id: toolUseId } : {}),
|
|
754
|
+
...(planItem?.id ? { plan_item_id: planItem.id } : {}),
|
|
755
|
+
...(planItem?.turn ? { turn: planItem.turn } : {}),
|
|
636
756
|
tool: event.tool,
|
|
637
757
|
args: event.args,
|
|
638
758
|
});
|
|
759
|
+
if (planItem) {
|
|
760
|
+
emit({ type: "plan_update", ...planSnapshot(pm) });
|
|
761
|
+
}
|
|
639
762
|
// P0-2: record an irreversible effect as STARTED (persisted before it
|
|
640
763
|
// settles) so a crash before the matching tool-result leaves a
|
|
641
764
|
// reconcilable "in flight" marker instead of a silent replay — mirrors
|
|
@@ -673,6 +796,13 @@ async function runTurn(
|
|
|
673
796
|
// P0-2: settle the in-flight side-effect (commit on success, fail on
|
|
674
797
|
// a clean error) and persist the updated ledger snapshot.
|
|
675
798
|
if (sideEffects && currentSideEffectOpId) {
|
|
799
|
+
if (event.result?._diffReviewAudit) {
|
|
800
|
+
diffReviewFollowUps.observe(
|
|
801
|
+
sideEffects.ledger,
|
|
802
|
+
currentSideEffectOpId,
|
|
803
|
+
event.result._diffReviewAudit,
|
|
804
|
+
);
|
|
805
|
+
}
|
|
676
806
|
if (err)
|
|
677
807
|
sideEffects.ledger.fail(
|
|
678
808
|
currentSideEffectOpId,
|
|
@@ -688,14 +818,29 @@ async function runTurn(
|
|
|
688
818
|
const lastCall =
|
|
689
819
|
toolCalls.length > 0 ? toolCalls[toolCalls.length - 1] : null;
|
|
690
820
|
if (lastCall) lastCall.is_error = Boolean(err);
|
|
821
|
+
const pm = getPlanModeManager();
|
|
822
|
+
const settledItem = lastCall?.planItemId
|
|
823
|
+
? pm.settlePlanItem(lastCall.planItemId, {
|
|
824
|
+
success: !err,
|
|
825
|
+
error: err,
|
|
826
|
+
result: event.result,
|
|
827
|
+
})
|
|
828
|
+
: null;
|
|
691
829
|
emit({
|
|
692
830
|
type: "tool_result",
|
|
693
831
|
...(lastCall?.id ? { id: lastCall.id } : {}),
|
|
832
|
+
...(lastCall?.planItemId
|
|
833
|
+
? { plan_item_id: lastCall.planItemId }
|
|
834
|
+
: {}),
|
|
835
|
+
...(settledItem?.turn ? { turn: settledItem.turn } : {}),
|
|
694
836
|
tool: event.tool,
|
|
695
837
|
is_error: Boolean(err),
|
|
696
838
|
error: err,
|
|
697
839
|
result: event.result,
|
|
698
840
|
});
|
|
841
|
+
if (settledItem) {
|
|
842
|
+
emit({ type: "plan_update", ...planSnapshot(pm) });
|
|
843
|
+
}
|
|
699
844
|
break;
|
|
700
845
|
}
|
|
701
846
|
case "token-usage":
|
|
@@ -735,6 +880,7 @@ async function runTurn(
|
|
|
735
880
|
break;
|
|
736
881
|
case "response-complete":
|
|
737
882
|
finalText = event.content || "";
|
|
883
|
+
responseCompleted = true;
|
|
738
884
|
break;
|
|
739
885
|
case "run-ended":
|
|
740
886
|
if (event.reason) endReason = event.reason;
|
|
@@ -747,6 +893,18 @@ async function runTurn(
|
|
|
747
893
|
// just the switch) so no further paid LLM call is made.
|
|
748
894
|
if (stopForCost) break;
|
|
749
895
|
}
|
|
896
|
+
if (
|
|
897
|
+
sideEffects &&
|
|
898
|
+
diffReviewFollowUps.complete(sideEffects.ledger, {
|
|
899
|
+
status:
|
|
900
|
+
responseCompleted || endReason === "complete"
|
|
901
|
+
? "completed-without-reproposal"
|
|
902
|
+
: "interrupted",
|
|
903
|
+
reason: responseCompleted || endReason === "complete" ? null : endReason,
|
|
904
|
+
}).length > 0
|
|
905
|
+
) {
|
|
906
|
+
sideEffects.persist();
|
|
907
|
+
}
|
|
750
908
|
return { finalText, endReason, usage, toolCalls };
|
|
751
909
|
}
|
|
752
910
|
|
|
@@ -1137,6 +1295,7 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
1137
1295
|
options: qOptions,
|
|
1138
1296
|
multiSelect,
|
|
1139
1297
|
timeoutMs,
|
|
1298
|
+
metadata,
|
|
1140
1299
|
} = {}) =>
|
|
1141
1300
|
new Promise((resolve, reject) => {
|
|
1142
1301
|
const id = `q-${++questionSeq}`;
|
|
@@ -1151,6 +1310,7 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
1151
1310
|
question: typeof question === "string" ? question : "",
|
|
1152
1311
|
options: Array.isArray(qOptions) ? qOptions : null,
|
|
1153
1312
|
multiSelect: multiSelect === true,
|
|
1313
|
+
...(metadata && typeof metadata === "object" ? { metadata } : {}),
|
|
1154
1314
|
});
|
|
1155
1315
|
});
|
|
1156
1316
|
|
|
@@ -1458,6 +1618,39 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
1458
1618
|
}
|
|
1459
1619
|
}
|
|
1460
1620
|
|
|
1621
|
+
// MCP servers may pause a tool flow with `elicitation/create`. Register the
|
|
1622
|
+
// handler only after MCP resolution so the client is initialized before use.
|
|
1623
|
+
// Reuse the structured Desktop/headless question channel, while preserving
|
|
1624
|
+
// the MCP response shape (`action` + object `content`) at this boundary.
|
|
1625
|
+
if (mcp?.mcpClient?.setElicitationHandler && interactiveQuestions) {
|
|
1626
|
+
mcp.mcpClient.setElicitationHandler(async (request) => {
|
|
1627
|
+
const { emitHooksV2Event } = await import("../lib/hooks-v2-producers.js");
|
|
1628
|
+
emitHooksV2Event("MCPElicitation", {
|
|
1629
|
+
server: request.server || null,
|
|
1630
|
+
request_id: request.requestId ?? null,
|
|
1631
|
+
message: request.message || "MCP server requests additional input",
|
|
1632
|
+
requested_schema: request.requestedSchema || null,
|
|
1633
|
+
session_id: sessionId,
|
|
1634
|
+
});
|
|
1635
|
+
const answer = await interactionAskUser({
|
|
1636
|
+
question: request.message || "MCP server requests additional input",
|
|
1637
|
+
timeoutMs: request.timeoutMs,
|
|
1638
|
+
metadata: {
|
|
1639
|
+
kind: "mcp_elicitation",
|
|
1640
|
+
server: request.server,
|
|
1641
|
+
requestId: request.requestId,
|
|
1642
|
+
requestedSchema: request.requestedSchema || null,
|
|
1643
|
+
},
|
|
1644
|
+
});
|
|
1645
|
+
if (answer == null) return { action: "cancel" };
|
|
1646
|
+
return {
|
|
1647
|
+
action: "accept",
|
|
1648
|
+
content:
|
|
1649
|
+
answer && typeof answer === "object" ? answer : { value: answer },
|
|
1650
|
+
};
|
|
1651
|
+
});
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1461
1654
|
// Seed MCP roots for --add-dir (roots/list_changed parity): advertise the full
|
|
1462
1655
|
// workspace-root list to connected MCP servers when the stream session started
|
|
1463
1656
|
// with extra roots. No --add-dir → workspaceRootDirs = [cwd] → no-op. Mirrors
|
|
@@ -1563,6 +1756,7 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
1563
1756
|
approvalGate,
|
|
1564
1757
|
permissionRules,
|
|
1565
1758
|
settingsHooks,
|
|
1759
|
+
toolAdmission: options.toolAdmission || null,
|
|
1566
1760
|
classifyAllShell,
|
|
1567
1761
|
enabledToolNames,
|
|
1568
1762
|
disabledTools,
|
|
@@ -1812,10 +2006,14 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
1812
2006
|
// exits plan mode. Every control answers with a `plan_update` event.
|
|
1813
2007
|
if (parsed.plan) {
|
|
1814
2008
|
const pm = getPlanModeManager();
|
|
1815
|
-
const reviewMessage =
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
2009
|
+
const reviewMessage = [
|
|
2010
|
+
"approve",
|
|
2011
|
+
"reject",
|
|
2012
|
+
"revise",
|
|
2013
|
+
"regenerate",
|
|
2014
|
+
].includes(parsed.plan)
|
|
2015
|
+
? planReviewSystemMessage(parsed.planReview)
|
|
2016
|
+
: null;
|
|
1819
2017
|
if (reviewMessage) {
|
|
1820
2018
|
messages.push({ role: "system", content: reviewMessage });
|
|
1821
2019
|
}
|
|
@@ -1848,7 +2046,47 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
1848
2046
|
});
|
|
1849
2047
|
continue;
|
|
1850
2048
|
}
|
|
1851
|
-
if (parsed.plan === "
|
|
2049
|
+
if (parsed.plan === "revise" || parsed.plan === "regenerate") {
|
|
2050
|
+
if (!pm.isActive()) {
|
|
2051
|
+
emit({
|
|
2052
|
+
type: "plan_update",
|
|
2053
|
+
...planSnapshot(pm),
|
|
2054
|
+
session_id: sessionId,
|
|
2055
|
+
note: "nothing to revise",
|
|
2056
|
+
});
|
|
2057
|
+
continue;
|
|
2058
|
+
}
|
|
2059
|
+
const revision = pm.beginPlanRevision({
|
|
2060
|
+
reason: parsed.plan,
|
|
2061
|
+
});
|
|
2062
|
+
if (revision.error) {
|
|
2063
|
+
emit({
|
|
2064
|
+
type: "plan_update",
|
|
2065
|
+
...planSnapshot(pm),
|
|
2066
|
+
session_id: sessionId,
|
|
2067
|
+
note: revision.error,
|
|
2068
|
+
});
|
|
2069
|
+
continue;
|
|
2070
|
+
}
|
|
2071
|
+
messages.push({
|
|
2072
|
+
role: "system",
|
|
2073
|
+
content:
|
|
2074
|
+
`[PLAN REVISION REQUESTED] Plan ${revision.previousPlan.id} is frozen. ` +
|
|
2075
|
+
`Create version ${revision.plan.version} as plan ${revision.plan.id}. ` +
|
|
2076
|
+
(parsed.plan === "regenerate"
|
|
2077
|
+
? "Regenerate the plan from scratch using the review snapshot."
|
|
2078
|
+
: "Revise the plan using the inline comments and reviewer notes."),
|
|
2079
|
+
});
|
|
2080
|
+
emit({
|
|
2081
|
+
type: "plan_update",
|
|
2082
|
+
...planSnapshot(pm),
|
|
2083
|
+
session_id: sessionId,
|
|
2084
|
+
});
|
|
2085
|
+
parsed.text =
|
|
2086
|
+
parsed.plan === "regenerate"
|
|
2087
|
+
? "Regenerate the plan from the review feedback."
|
|
2088
|
+
: "Revise the plan from the review feedback.";
|
|
2089
|
+
} else if (parsed.plan === "approve") {
|
|
1852
2090
|
if (!pm.isActive() || !(pm.currentPlan?.items?.length > 0)) {
|
|
1853
2091
|
emit({
|
|
1854
2092
|
type: "plan_update",
|
|
@@ -1858,10 +2096,17 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
1858
2096
|
});
|
|
1859
2097
|
continue;
|
|
1860
2098
|
}
|
|
1861
|
-
pm.approvePlan(
|
|
2099
|
+
const approval = pm.approvePlan({
|
|
2100
|
+
permissionMode: options.permissionMode || "default",
|
|
2101
|
+
});
|
|
2102
|
+
const executionLock = approval.executionLock;
|
|
1862
2103
|
messages.push({
|
|
1863
2104
|
role: "system",
|
|
1864
|
-
content:
|
|
2105
|
+
content:
|
|
2106
|
+
`[PLAN APPROVED] The user has approved your plan with ${pm.currentPlan.items.length} items. ` +
|
|
2107
|
+
`Permission mode is ${executionLock.permissionMode}. The execution lock permits only: ` +
|
|
2108
|
+
`${executionLock.allowedTools.join(", ")}. Execute the approved plan items in order; ` +
|
|
2109
|
+
"request a plan revision before using any other tool.",
|
|
1865
2110
|
});
|
|
1866
2111
|
emit({
|
|
1867
2112
|
type: "plan_update",
|
|
@@ -2166,7 +2411,14 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
2166
2411
|
// Resume-degenerate role merge for the first live model call only.
|
|
2167
2412
|
mergeRoles: mergeRolesThisTurn,
|
|
2168
2413
|
},
|
|
2169
|
-
{
|
|
2414
|
+
{
|
|
2415
|
+
runLoop,
|
|
2416
|
+
emit,
|
|
2417
|
+
costBudget,
|
|
2418
|
+
nextToolUseId,
|
|
2419
|
+
sideEffects,
|
|
2420
|
+
turnNumber: turns,
|
|
2421
|
+
},
|
|
2170
2422
|
);
|
|
2171
2423
|
} catch (err) {
|
|
2172
2424
|
currentAbort = null;
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
isInJetbrainsContext,
|
|
35
35
|
} from "../lib/jetbrains-bridge.js";
|
|
36
36
|
import { collectPluginMcpServers } from "../lib/plugin-runtime/mcp.js";
|
|
37
|
+
import { EventRuntimeStore } from "../lib/event-runtime-store.js";
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
40
|
* Normalize a parsed config object into a `{ name: serverConfig }` map.
|
|
@@ -150,7 +151,9 @@ export function mcpAuthHint(url, errMessage) {
|
|
|
150
151
|
*/
|
|
151
152
|
export async function setupMcpFromConfig(servers, deps = {}) {
|
|
152
153
|
const writeErr = deps.writeErr || (() => {});
|
|
153
|
-
const createClient =
|
|
154
|
+
const createClient =
|
|
155
|
+
deps.createClient ||
|
|
156
|
+
(() => new MCPClient({ eventRuntimeStore: deps.eventRuntimeStore || null }));
|
|
154
157
|
servers = filterMcpServersByPolicy(servers, deps.mcpPolicy, writeErr);
|
|
155
158
|
|
|
156
159
|
// `deps.into` lets a second batch (e.g. registered servers) accumulate into
|
|
@@ -191,6 +194,12 @@ export async function setupMcpFromConfig(servers, deps = {}) {
|
|
|
191
194
|
if (deps.sessionId != null && typeof mcpClient.setSessionId === "function") {
|
|
192
195
|
mcpClient.setSessionId(deps.sessionId);
|
|
193
196
|
}
|
|
197
|
+
if (typeof mcpClient.setElicitationHandler === "function" &&
|
|
198
|
+
typeof deps.elicitationHandler === "function") {
|
|
199
|
+
mcpClient.setElicitationHandler(deps.elicitationHandler, {
|
|
200
|
+
timeoutMs: deps.elicitationTimeoutMs,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
194
203
|
|
|
195
204
|
for (const [name, cfg] of Object.entries(servers)) {
|
|
196
205
|
// Skip a name already connected — an earlier batch (ad-hoc --mcp-config)
|
|
@@ -745,6 +754,11 @@ export async function resolveAgentMcp(args = {}, deps = {}) {
|
|
|
745
754
|
const doIde = deps.loadIdeMcp || loadIdeMcp;
|
|
746
755
|
const doPdh = deps.loadPdhMcp || loadPdhMcp;
|
|
747
756
|
const doJetbrains = deps.loadJetbrainsMcp || loadJetbrainsMcp;
|
|
757
|
+
const runtimeEnv = args.env || process.env;
|
|
758
|
+
const eventRuntimeStore =
|
|
759
|
+
deps.eventRuntimeStore ||
|
|
760
|
+
args.eventRuntimeStore ||
|
|
761
|
+
(runtimeEnv.CC_EVENT_RUNTIME_DURABLE === "1" ? new EventRuntimeStore() : null);
|
|
748
762
|
// Thread the agent session id down to setupMcpFromConfig so spawned stdio MCP
|
|
749
763
|
// servers get CC_SESSION_ID / CLAUDE_CODE_SESSION_ID (Claude-Code parity).
|
|
750
764
|
let mcpPolicy = deps.mcpPolicy || null;
|
|
@@ -759,6 +773,7 @@ export async function resolveAgentMcp(args = {}, deps = {}) {
|
|
|
759
773
|
const fwd = {
|
|
760
774
|
...deps,
|
|
761
775
|
...(args.sessionId != null ? { sessionId: args.sessionId } : {}),
|
|
776
|
+
...(eventRuntimeStore ? { eventRuntimeStore } : {}),
|
|
762
777
|
mcpPolicy,
|
|
763
778
|
};
|
|
764
779
|
let result = null;
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
} from "../lib/background-agent-supervisor.js";
|
|
26
26
|
import { startBackgroundSessionServer } from "../lib/background-session-transport.js";
|
|
27
27
|
import { idlePhaseFor } from "../lib/background-agent-phase.js";
|
|
28
|
+
import { attachInteractionRequestHandler } from "../lib/background-interaction-resolver.js";
|
|
28
29
|
|
|
29
30
|
const jobFile = process.argv[2];
|
|
30
31
|
let job;
|
|
@@ -37,7 +38,10 @@ let phase = "turn";
|
|
|
37
38
|
let turnCount = 0;
|
|
38
39
|
let lastExit = { code: 0, signal: null };
|
|
39
40
|
let transportState = null;
|
|
41
|
+
let detachInteractionHandler = null;
|
|
40
42
|
const promptQueue = [];
|
|
43
|
+
// P0-2: 保存 pending 的交互请求,等 attach 客户端连接后转发
|
|
44
|
+
const pendingInteractions = new Map();
|
|
41
45
|
|
|
42
46
|
// Backpressure (Gap 4): an attached client can push prompts faster than
|
|
43
47
|
// turns drain — an unbounded queue grows without limit and every entry is a
|
|
@@ -114,7 +118,7 @@ function startTurn(argv, promptText) {
|
|
|
114
118
|
child = spawn(process.execPath, [job.cliEntry, ...argv], {
|
|
115
119
|
cwd: job.cwd,
|
|
116
120
|
env: { ...process.env, CC_BACKGROUND_AGENT_ID: job.id },
|
|
117
|
-
stdio: ["ignore", log.fd, log.fd],
|
|
121
|
+
stdio: ["ignore", log.fd, log.fd, "ipc"], // P0-2: 开启 IPC 通道用于人机交互
|
|
118
122
|
windowsHide: true,
|
|
119
123
|
// POSIX: give the agent child its own process group so an orphan reclaim
|
|
120
124
|
// (worker crashed → supervisor kills the recorded agentPid) or /stop can
|
|
@@ -146,9 +150,71 @@ function startTurn(argv, promptText) {
|
|
|
146
150
|
turn: turnCount,
|
|
147
151
|
prompt: promptText || null,
|
|
148
152
|
});
|
|
153
|
+
|
|
154
|
+
// P0-2: 挂载人机交互请求处理器,转发给 attach 客户端
|
|
155
|
+
detachInteractionHandler = attachInteractionRequestHandler(
|
|
156
|
+
child,
|
|
157
|
+
async (payload, msg) => {
|
|
158
|
+
const requestId = msg.requestId;
|
|
159
|
+
// 如果有 attach 客户端,转发给它等待响应
|
|
160
|
+
if (server && server.clientCount() > 0) {
|
|
161
|
+
return new Promise((resolve, reject) => {
|
|
162
|
+
const timer = setTimeout(
|
|
163
|
+
() => {
|
|
164
|
+
pendingInteractions.delete(requestId);
|
|
165
|
+
if (payload.defaultValue !== undefined) {
|
|
166
|
+
resolve(payload.defaultValue);
|
|
167
|
+
} else {
|
|
168
|
+
reject(new Error(`Interaction timed out: ${payload.question}`));
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
payload.timeoutMs || 5 * 60 * 1000,
|
|
172
|
+
);
|
|
173
|
+
timer.unref?.();
|
|
174
|
+
pendingInteractions.set(requestId, {
|
|
175
|
+
resolve,
|
|
176
|
+
reject,
|
|
177
|
+
timer,
|
|
178
|
+
payload,
|
|
179
|
+
});
|
|
180
|
+
server.broadcastInteractionRequest(requestId, payload);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
// 没有客户端连接,返回默认值(如果有的话)
|
|
184
|
+
if (payload.defaultValue !== undefined) {
|
|
185
|
+
return payload.defaultValue;
|
|
186
|
+
}
|
|
187
|
+
// 没有默认值,记录到 state 让用户后续 attach 时能看到
|
|
188
|
+
mergeState({
|
|
189
|
+
pendingQuestion: {
|
|
190
|
+
intId: requestId,
|
|
191
|
+
requestId,
|
|
192
|
+
prompt: payload.prompt || payload.question,
|
|
193
|
+
hint: payload.hint,
|
|
194
|
+
options: payload.options,
|
|
195
|
+
multiSelect: payload.multiSelect,
|
|
196
|
+
timeoutMs: payload.timeoutMs,
|
|
197
|
+
askedAt: Date.now(),
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
// 等待用户 attach 后回复
|
|
201
|
+
return new Promise((resolve) => {
|
|
202
|
+
pendingInteractions.set(requestId, { resolve });
|
|
203
|
+
});
|
|
204
|
+
},
|
|
205
|
+
);
|
|
206
|
+
|
|
149
207
|
child.on("exit", (code, signal) => {
|
|
150
208
|
lastExit = { code, signal };
|
|
151
209
|
child = null;
|
|
210
|
+
// 清理交互处理器
|
|
211
|
+
detachInteractionHandler?.();
|
|
212
|
+
detachInteractionHandler = null;
|
|
213
|
+
// 清理所有 pending 交互
|
|
214
|
+
for (const [, pending] of pendingInteractions) {
|
|
215
|
+
pending.reject?.(new Error("Agent exited"));
|
|
216
|
+
}
|
|
217
|
+
pendingInteractions.clear();
|
|
152
218
|
server?.broadcast({ type: "turn-ended", turn: turnCount, exitCode: code });
|
|
153
219
|
maybeContinue();
|
|
154
220
|
});
|
|
@@ -259,6 +325,19 @@ async function main() {
|
|
|
259
325
|
finalize(lastExit.code, lastExit.signal);
|
|
260
326
|
}
|
|
261
327
|
},
|
|
328
|
+
onInteractionResponse: ({ requestId, intId, answer, error }) => {
|
|
329
|
+
// Support both field names: requestId (from transport) and intId (legacy)
|
|
330
|
+
const resolvedId = requestId ?? intId;
|
|
331
|
+
const entry = pendingInteractions.get(resolvedId);
|
|
332
|
+
if (!entry) return;
|
|
333
|
+
pendingInteractions.delete(resolvedId);
|
|
334
|
+
clearTimeout(entry.timer);
|
|
335
|
+
if (error) {
|
|
336
|
+
entry.reject(new Error(error));
|
|
337
|
+
} else {
|
|
338
|
+
entry.resolve(answer);
|
|
339
|
+
}
|
|
340
|
+
},
|
|
262
341
|
});
|
|
263
342
|
transportState = { pipe: server.pipePath, token };
|
|
264
343
|
mergeState({ transport: transportState });
|