chainlesschain 0.162.174 → 0.162.176
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +10 -10
- package/src/assets/web-panel/assets/{AIOps-Dcl-X1Hw.js → AIOps-BDLu5Elz.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-ClMh9HzT.js → ActionButton-DH5us-CK.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DPj0rSQ5.js → Analytics-BZ0u8IFG.js} +3 -3
- package/src/assets/web-panel/assets/AppLayout-Duu8xR14.js +9 -0
- package/src/assets/web-panel/assets/{Artifacts-L8781rE8.js → Artifacts-Br2YBbh_.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CffB6WIP.js → Audit-C3C6a482.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-BkLhayyY.js → BackgroundAgents-CzHvebcj.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BQnwFI78.js → Backup-DZNHYDFd.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-xuUGHQch.js → BaseInput-VRiC4fIx.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-feQXwWrg.js → Chat-Cm08WWAD.js} +5 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-CGHYrugQ.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-DVaIiUGW.js → Checkbox-DtByk7d7.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-D2kEnzeU.js → Codegen-CphXXOfD.js} +1 -1
- package/src/assets/web-panel/assets/{Col-azDoyusS.js → Col-Hz86TnLR.js} +1 -1
- package/src/assets/web-panel/assets/{Community-OZdnPWM5.js → Community-HP03ltpD.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-VDMvBN-C.js → Compact-B_N1mqQz.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CPJ_zgQ1.js → Compliance-CVztRpi8.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-iRBwcsOA.js → Cowork-wUVOyZih.js} +4 -4
- package/src/assets/web-panel/assets/{Cron-DrxrspUz.js → Cron-DW5TLJKw.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-D-rkAZXF.js → Crosschain-CrAFGhWH.js} +1 -1
- package/src/assets/web-panel/assets/{DID-5Pp1Xnmr.js → DID-pA-oD8ke.js} +2 -2
- package/src/assets/web-panel/assets/Dashboard-CXrd5gAw.js +3 -0
- package/src/assets/web-panel/assets/{Dropdown-BWj_E0Ie.js → Dropdown-EweJcsek.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-BT-wgSEh.js → EmailListRenderer-C9xVLPG4.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-1PzH23pa.js → FamilyGuardDashboard-CDcEEqlu.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BxMIXGC6.js → Federation-DtZda9A_.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-CyJobBln.js → FormItemContext-CiYdcVz3.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-YkjFuQTN.js → GenericCardRenderer-DA13uwA0.js} +1 -1
- package/src/assets/web-panel/assets/{Git-C2a98Wp_.js → Git-DzRhZD1O.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DKL3Fl84.js → Governance-D5RMgOSb.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BJ2cQC_3.js → Inference-BgrPfSNk.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DBAsOngt.js → KnowledgeGraph-DzjnD571.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-COt8g9LO.js → Logs-BhWzVDtN.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-3Lfht1Fd.js → MarkdownRenderer-BDape9cx.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-C9Zk9Pb2.js → Marketplace-DJtL5GV7.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DDWDFWPO.js → McpTools-CZcQygI7.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-BRmVye_o.js → Memory-DUWSDUUu.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-CppBbWpD.js → MobileBridge-BTwq2WKY.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-NZvvfDME.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-CcWpeGa6.js → Mtc-BiGugEQm.js} +6 -6
- package/src/assets/web-panel/assets/{MtcAudit-BcllEq0K.js → MtcAudit-DY7a6gUe.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-BFD1CarL.js → Multisig-BQbDu_w7.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-QNXXYvjz.js → NLProgramming-CM2wXTLv.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-07YwgQVy.js → Notes-DI6gGs1v.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-bOccEInE.js → NotificationSettings-BsZOLWAB.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DlRi29WL.js → OrderTableRenderer-C48mu09U.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-CBaezzEr.js → Organization-Cds0_tXr.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Bl5NohFO.js → Overflow-WunYMD87.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CLMal9Aw.js → P2P-Bo6j4DDv.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-CGO0NITk.js → PdhVaultBrowser-Bh2XPD5f.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-CPSw48E2.js → Permissions-EMvMMC8N.js} +3 -3
- package/src/assets/web-panel/assets/{PersonalDataHub-CDM5n134.js → PersonalDataHub-AX3ypUDV.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-BdsqG7WV.js → Pipeline-BOx8HOgL.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-B6L4E-M7.js → Privacy-tBeTVQVM.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-DXPyZKRs.js → ProjectInit-CVYg1W4M.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BrCC3xYT.js → ProjectSettings-Dvt5I7y1.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-BYmuHC2q.js → Projects-Cc7FC9-e.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-CbCe2eUl.js → Providers-Ct8xqY-E.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-DkukgCrR.js → QrScannerModal-Cni8Ooja.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-D-htOrV8.js → QuickAsk-BJVLKdxr.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Bm7SIfzu.js → Recommend-DPG8Rbbm.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-C9rP-iMc.js → RemoteSession-DsdR7dCt.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-kGlUgbsl.js → Reputation-Csg1YM-b.js} +1 -1
- package/src/assets/web-panel/assets/{Row-PBupbbUA.js → Row-D9DoFoEf.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-njlwKUGK.js → RssFeed-BsvKrXMS.js} +2 -2
- package/src/assets/web-panel/assets/{Search-DLdEmgBw.js → Search-DFUStfgQ.js} +1 -1
- package/src/assets/web-panel/assets/{Security-SXGPSHdu.js → Security-ILg1zxdK.js} +4 -4
- package/src/assets/web-panel/assets/{Services-CuFGnNsb.js → Services-Dd41PCaY.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CtUC0mDa.js → Skeleton-Bzo1cN80.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-P1qgOVFn.js → Skills-BDHh17P0.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-CsppE8YV.js → Sla-jl7UTiRY.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-Cq1oG56m.js → SpeechSettings-BePa-RF6.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DdKW6V-C.js → SyncSettings-DiqqDKGZ.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-BCc9san5.js → Tasks-DYQ_6lxj.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CcHC1dMA.js → Templates-JiDeI06L.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CA4PqU22.js → Tenant-hhgI6zwS.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-CjTZPa37.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-DHWTSvOy.js → TimelineRenderer-B8uB5Llk.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-Ddz-P_yh.js → Tokens-C3b_6r2z.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-ePmrmLZ1.js → Trigger-tIP7HKVe.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DmuK1CCE.js → Trust-vjoc11vJ.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CqqBuRrT.js → UkeySign-DUPBnGuH.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-BGlR3uWM.js → VideoEditing-CBvhUY5T.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-Ba_Qx6Ga.js → Wallet-DUaQ0uA5.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-29neXKt2.js → WebAuthn-DllSivjE.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-lD0lR0UQ.js → WorkflowEditor-xc8D3uO6.js} +1 -1
- package/src/assets/web-panel/assets/{chat-B3stH01u.js → chat-BVicU7oA.js} +1 -1
- package/src/assets/web-panel/assets/{colors-Czly56MN.js → colors-DJzLmhLm.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-C0TkbkAJ.js → compact-item-BvYRfThE.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BJmpSlf1.js → createContext-DGXxCBKR.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BT46Y_QI.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-D1q-zw7u.js → hasIn-SBDJB1y4.js} +1 -1
- package/src/assets/web-panel/assets/{index-DV-twjNO.js → index-1SdDS6lR.js} +1 -1
- package/src/assets/web-panel/assets/{index-B-kTvMq7.js → index-9gdI7uUW.js} +1 -1
- package/src/assets/web-panel/assets/index-B7nuIywP.js +1 -0
- package/src/assets/web-panel/assets/{index-Bm_-RKal.js → index-BJZf9DhV.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQftlZn-.js → index-BO1itZaY.js} +3 -3
- package/src/assets/web-panel/assets/{index-Dw3L_smW.js → index-BTrBGBJs.js} +1 -1
- package/src/assets/web-panel/assets/{index-C7sFKQ53.js → index-BYqz4Wrr.js} +1 -1
- package/src/assets/web-panel/assets/{index-DlvsSuBC.js → index-Bf-ctERC.js} +1 -1
- package/src/assets/web-panel/assets/{index-ChESIe5r.js → index-CKyEivf8.js} +1 -1
- package/src/assets/web-panel/assets/{index-DaqEHaCg.js → index-CdGY9P8a.js} +1 -1
- package/src/assets/web-panel/assets/{index-DZeoKL6t.js → index-Cf-O_g_8.js} +1 -1
- package/src/assets/web-panel/assets/{index-XWV8JWMc.js → index-CloCgBUR.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpMIdPJ0.js → index-CoJAO1Lm.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgS8XUBU.js → index-Crk5NTb0.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmUta2lw.js → index-Cs2rmLFt.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dpz_7sf-.js → index-CtwqO5qo.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRcQsPez.js → index-D7HimK0M.js} +1 -1
- package/src/assets/web-panel/assets/{index-BEt2-3x5.js → index-DCdRAgjy.js} +1 -1
- package/src/assets/web-panel/assets/{index-CHvPlzWJ.js → index-DCqRS6da.js} +1 -1
- package/src/assets/web-panel/assets/{index-BDHXx65P.js → index-DHVLJ8q0.js} +1 -1
- package/src/assets/web-panel/assets/{index-K4YaPDOn.js → index-DKrvvWm4.js} +1 -1
- package/src/assets/web-panel/assets/{index-C1pOqU7D.js → index-DMarmfrv.js} +1 -1
- package/src/assets/web-panel/assets/{index-DAhrn9EJ.js → index-DRfiXB_p.js} +1 -1
- package/src/assets/web-panel/assets/{index-cPjWjvmW.js → index-Dm_77jgR.js} +1 -1
- package/src/assets/web-panel/assets/{index-C27TnOoT.js → index-DnjPdvR6.js} +1 -1
- package/src/assets/web-panel/assets/{index-upY9rkGZ.js → index-DonCnfMr.js} +1 -1
- package/src/assets/web-panel/assets/{index-CbvNJUwu.js → index-DvUTDYXX.js} +1 -1
- package/src/assets/web-panel/assets/{index-BVwJ3jht.js → index-FxZzRyE1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIF6XHIi.js → index-MjC4G09d.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8KqsomG.js → index-VMfwIH5G.js} +1 -1
- package/src/assets/web-panel/assets/{index-8GKykbS4.js → index-YJkzy8ZF.js} +1 -1
- package/src/assets/web-panel/assets/{index-DpGs96FC.js → index-d5BVd-cL.js} +1 -1
- package/src/assets/web-panel/assets/{index-DO8xOwxi.js → index-e4fXH_WO.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cu_4HaUS.js → index-hxTODbM1.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cf7Gr3NG.js → index-lpaGoTH3.js} +1 -1
- package/src/assets/web-panel/assets/{index-DBqAm8es.js → index-wcCL-miV.js} +1 -1
- package/src/assets/web-panel/assets/{index-ZDUhX41Z.js → index-xfluRkCT.js} +1 -1
- package/src/assets/web-panel/assets/index-ycwAfC-i.js +1 -0
- package/src/assets/web-panel/assets/{index-z8ATo2aQ.js → index-z1ZylsLq.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-QWEXi6-t.js → initDefaultProps-C1zO1KnY.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BfrQwvV1.js → motion-CWLtEGmC.js} +1 -1
- package/src/assets/web-panel/assets/{move-Dn7x0H9t.js → move-DzD_C3Vm.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-F61D_TgE.js → mtc-parser-D880PYJl.js} +1 -1
- package/src/assets/web-panel/assets/{omit-4SQZ39PF.js → omit-CFR_z2ov.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-C7DTe126.js → pickAttrs-srIhgrSC.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-40NeyzDK.js → placementArrow-C1rXpibP.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BiUJ6qWs.js → responsiveObserve-C30gRcSS.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CacJTM3f.js → slide-CvtKiMfV.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-K812HB-k.js → statusUtils-DNHO7ITG.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CKeHA2eM.js → styleChecker-Dt_Sl-g4.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-CKl4FqXF.js → useFlexGapSupport-Cjev42Gh.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DPoiJjSZ.js → useFs-Baxglj2V.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-aHwBspmt.js → usePersonalDataHub-B4NkcLaP.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DrA-GuCT.js → vnode-mIRkdT7o.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-G3LMswgy.js → zoom-HzI5DlH_.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/auth/npm-auth.js +30 -5
- package/src/commands/agenda.js +64 -2
- package/src/commands/agent.js +45 -3
- package/src/commands/background-session.js +103 -0
- package/src/commands/config.js +70 -5
- package/src/commands/context.js +36 -2
- package/src/commands/hub.js +19 -1
- package/src/commands/memory.js +21 -6
- package/src/commands/permissions.js +57 -1
- package/src/commands/plugin.js +2 -0
- package/src/commands/review.js +23 -11
- package/src/commands/routine.js +31 -8
- package/src/commands/session.js +11 -3
- package/src/commands/team.js +20 -7
- package/src/commands/update.js +65 -10
- package/src/esm-bridge.js +3 -0
- package/src/gateways/terminal/PtyManager.js +8 -1
- package/src/gateways/ws/message-dispatcher.js +3 -0
- package/src/gateways/ws/session-protocol.js +26 -0
- package/src/gateways/ws/ws-agent-handler.js +107 -69
- package/src/gateways/ws/ws-server.js +92 -4
- package/src/harness/jsonl-session-store.js +13 -6
- package/src/harness/mcp-client.js +200 -1
- package/src/index.js +123 -55
- package/src/lazy-dispatch.js +86 -85
- package/src/lib/__tests__/personal-data-hub-aichat-wizard.test.js +15 -0
- package/src/lib/agent-coordinator.js +4 -0
- package/src/lib/agent-ipc-bus.js +32 -2
- package/src/lib/agent-sandbox.js +16 -2
- package/src/lib/agent-schedule-store.js +55 -0
- package/src/lib/agent-tool-admission.js +104 -0
- package/src/lib/api-key-helper.js +10 -2
- package/src/lib/async-hook-supervisor.cjs +26 -4
- package/src/lib/background-interaction-resolver.js +71 -0
- package/src/lib/background-session-transport.js +59 -1
- package/src/lib/changelog.js +19 -11
- package/src/lib/channels/channel-manager.js +6 -0
- package/src/lib/channels/telegram-channel.js +11 -1
- package/src/lib/channels/webhook-channel.js +15 -3
- package/src/lib/checkpoint-store.js +10 -2
- package/src/lib/cloud/bundle.js +12 -2
- package/src/lib/code-review.js +32 -8
- package/src/lib/computer-use/control-backend.js +18 -3
- package/src/lib/context-breakdown.js +46 -0
- package/src/lib/context-source-ledger.js +43 -0
- package/src/lib/crash-reporter.js +6 -0
- package/src/lib/diff-review-follow-up.js +154 -0
- package/src/lib/downloader.js +17 -3
- package/src/lib/ensure-utf8.js +11 -3
- package/src/lib/event-runtime-producer.js +58 -0
- package/src/lib/event-runtime-store.js +354 -0
- package/src/lib/event-runtime-worker.js +109 -0
- package/src/lib/execution-backend.js +72 -21
- package/src/lib/git-integration.js +19 -4
- package/src/lib/hook-manager.js +34 -15
- package/src/lib/hook-runner.cjs +48 -3
- package/src/lib/hooks-v2-producers.js +15 -0
- package/src/lib/hooks-v2-runtime.js +70 -21
- package/src/lib/host-adb-bridge.js +111 -21
- package/src/lib/ide-context.js +128 -1
- package/src/lib/interaction-adapter.js +39 -0
- package/src/lib/ipc-attach-protocol.js +98 -0
- package/src/lib/json-schema-validate.js +190 -36
- package/src/lib/lan-pairing-preflight.js +13 -2
- package/src/lib/lsp/__tests__/lsp-server-registry.test.js +18 -0
- package/src/lib/lsp/lsp-client.js +18 -1
- package/src/lib/lsp/lsp-manager.js +4 -0
- package/src/lib/lsp/lsp-server-registry.js +11 -0
- package/src/lib/mcp-oauth.js +8 -2
- package/src/lib/npm-invocation.js +29 -0
- package/src/lib/packer/pkg-runner.js +13 -2
- package/src/lib/packer/precheck.js +33 -16
- package/src/lib/packer/web-panel-builder.js +16 -2
- package/src/lib/permission-rules.cjs +5 -1
- package/src/lib/personal-data-hub-aichat-wizard.js +22 -6
- package/src/lib/personal-data-hub-wiring.js +27 -3
- package/src/lib/plan-mode.js +204 -11
- package/src/lib/plugin-monitor-supervisor.js +39 -4
- package/src/lib/plugin-runtime/bin.js +45 -0
- package/src/lib/plugin-runtime/hooks.js +14 -1
- package/src/lib/plugin-runtime/install.js +2 -1
- package/src/lib/plugin-runtime/lsp.js +3 -0
- package/src/lib/plugin-runtime/mcp.js +8 -1
- package/src/lib/plugin-runtime/monitors.js +4 -0
- package/src/lib/plugin-runtime/plugin-options.js +74 -7
- package/src/lib/plugin-runtime/signature.js +45 -0
- package/src/lib/pr-create.js +21 -8
- package/src/lib/pr-link-ledger.js +15 -3
- package/src/lib/process-execution-broker/credential-agent.js +295 -0
- package/src/lib/process-execution-broker/index.js +440 -14
- package/src/lib/process-execution-broker/patch-child-process.js +2 -3
- package/src/lib/process-execution-broker/platform-sandbox.js +351 -0
- package/src/lib/process-manager.js +18 -3
- package/src/lib/provenance-api.js +6 -0
- package/src/lib/proxy-bootstrap.js +19 -0
- package/src/lib/publish-workspace.js +14 -6
- package/src/lib/repl-rewind.js +9 -4
- package/src/lib/secret-store.js +159 -0
- package/src/lib/service-manager.js +64 -29
- package/src/lib/session-hooks.js +328 -473
- package/src/lib/session-telemetry-middleware.js +6 -0
- package/src/lib/settings-hook-events.cjs +61 -1
- package/src/lib/settings-hooks.cjs +4 -0
- package/src/lib/side-effect-ledger.js +22 -0
- package/src/lib/sub-agent-context.js +5 -0
- package/src/lib/sub-agent-profiles.js +4 -0
- package/src/lib/trace-api.js +6 -0
- package/src/lib/turn-context.js +14 -8
- package/src/lib/unattended-action-policy.js +83 -0
- package/src/lib/update-notice.js +9 -45
- package/src/lib/with-file-lock.js +7 -0
- package/src/lib/ws-server.js +1 -0
- package/src/repl/agent-repl.js +71 -13
- package/src/repl/clipboard-copy.js +8 -2
- package/src/repl/pr-comments.js +30 -7
- package/src/runtime/agent-core.js +439 -87
- package/src/runtime/agent-runtime.js +1 -0
- package/src/runtime/coding-agent-contract-shared.cjs +52 -0
- package/src/runtime/coding-agent-policy.cjs +20 -0
- package/src/runtime/diagnostics.js +73 -8
- package/src/runtime/headless-runner.js +63 -0
- package/src/runtime/headless-stream.js +269 -17
- package/src/runtime/mcp-config.js +16 -1
- package/src/workers/background-agent-worker.js +80 -1
- package/src/assets/web-panel/assets/AppLayout-7iSKDmlI.js +0 -9
- package/src/assets/web-panel/assets/ChatBubbleRenderer-DcbUHeGW.js +0 -1
- package/src/assets/web-panel/assets/Dashboard-BAKYNavw.js +0 -3
- package/src/assets/web-panel/assets/MobileProjects-C4GKn1dH.js +0 -1
- package/src/assets/web-panel/assets/Terminal-Fj7ea0In.js +0 -3
- package/src/assets/web-panel/assets/devWarning-CDI8Sbaj.js +0 -1
- package/src/assets/web-panel/assets/index-96LBR96V.js +0 -1
- package/src/assets/web-panel/assets/index-DyQkiW24.js +0 -1
package/src/lib/mcp-oauth.js
CHANGED
|
@@ -25,7 +25,7 @@ import pathDefault from "node:path";
|
|
|
25
25
|
import { homedir as homedirDefault } from "node:os";
|
|
26
26
|
import crypto from "node:crypto";
|
|
27
27
|
import http from "node:http";
|
|
28
|
-
import {
|
|
28
|
+
import { executionBroker } from "./process-execution-broker/index.js";
|
|
29
29
|
|
|
30
30
|
export const _deps = {
|
|
31
31
|
fetch: (...a) => globalThis.fetch(...a),
|
|
@@ -35,7 +35,13 @@ export const _deps = {
|
|
|
35
35
|
sha256: (s) => crypto.createHash("sha256").update(s).digest(),
|
|
36
36
|
createServer: (h) => http.createServer(h),
|
|
37
37
|
openBrowser: defaultOpenBrowser,
|
|
38
|
-
spawn: (
|
|
38
|
+
spawn: (command, args, options) =>
|
|
39
|
+
executionBroker.spawn(command, args, {
|
|
40
|
+
...options,
|
|
41
|
+
origin: "mcp:oauth-browser",
|
|
42
|
+
policy: "allow",
|
|
43
|
+
scope: "oauth",
|
|
44
|
+
}),
|
|
39
45
|
now: () => Date.now(),
|
|
40
46
|
// Backoff sleep seam (tests override with a no-op so the retry doesn't wait).
|
|
41
47
|
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Resolve npm without asking a shell to interpret the platform shim.
|
|
5
|
+
*
|
|
6
|
+
* Windows npm installations expose `npm.cmd`, but Node cannot execute a CMD
|
|
7
|
+
* shim with `shell:false` (`spawnSync npm.cmd EINVAL`). The shim delegates to
|
|
8
|
+
* the npm CLI located beside node.exe, so invoke that JavaScript entrypoint
|
|
9
|
+
* through the current Node executable instead.
|
|
10
|
+
*/
|
|
11
|
+
export function resolveNpmInvocation({
|
|
12
|
+
platform = process.platform,
|
|
13
|
+
execPath = process.execPath,
|
|
14
|
+
} = {}) {
|
|
15
|
+
if (platform !== "win32") {
|
|
16
|
+
return { command: "npm", prefixArgs: [] };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const npmCliPath = path.win32.join(
|
|
20
|
+
path.win32.dirname(execPath),
|
|
21
|
+
"node_modules",
|
|
22
|
+
"npm",
|
|
23
|
+
"bin",
|
|
24
|
+
"npm-cli.js",
|
|
25
|
+
);
|
|
26
|
+
return { command: execPath, prefixArgs: [npmCliPath] };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default resolveNpmInvocation;
|
|
@@ -14,8 +14,12 @@
|
|
|
14
14
|
import fs from "node:fs";
|
|
15
15
|
import path from "node:path";
|
|
16
16
|
import { createRequire } from "node:module";
|
|
17
|
-
import { spawnSync } from "node:child_process";
|
|
18
17
|
import { PackError, EXIT } from "./errors.js";
|
|
18
|
+
import executionBroker from "../process-execution-broker/index.js";
|
|
19
|
+
|
|
20
|
+
export const _deps = {
|
|
21
|
+
spawnSync: (...args) => executionBroker.spawnSync(...args),
|
|
22
|
+
};
|
|
19
23
|
|
|
20
24
|
/**
|
|
21
25
|
* @param {object} ctx
|
|
@@ -47,12 +51,19 @@ export function runPkg(ctx) {
|
|
|
47
51
|
];
|
|
48
52
|
|
|
49
53
|
log(` [pkg] Running: ${pkgBin.runtime} ${args.join(" ")}`);
|
|
50
|
-
const res = spawnSync(pkgBin.runtime, args, {
|
|
54
|
+
const res = _deps.spawnSync(pkgBin.runtime, args, {
|
|
55
|
+
origin: "packer:pkg",
|
|
56
|
+
scope: "pack",
|
|
57
|
+
policy: "allow",
|
|
58
|
+
shell: false,
|
|
51
59
|
cwd: path.dirname(pkgConfigFile),
|
|
52
60
|
stdio: "inherit",
|
|
53
61
|
windowsHide: true,
|
|
54
62
|
});
|
|
55
63
|
|
|
64
|
+
if (res.error) {
|
|
65
|
+
throw new PackError(`Failed to start pkg: ${res.error.message}`, EXIT.PKG);
|
|
66
|
+
}
|
|
56
67
|
if (res.status !== 0) {
|
|
57
68
|
throw new PackError(
|
|
58
69
|
`pkg exited with code ${res.status}. See output above for details.`,
|
|
@@ -5,9 +5,13 @@
|
|
|
5
5
|
|
|
6
6
|
import fs from "node:fs";
|
|
7
7
|
import path from "node:path";
|
|
8
|
-
import { execSync } from "node:child_process";
|
|
9
8
|
import { fileURLToPath } from "node:url";
|
|
10
9
|
import { PackError, EXIT } from "./errors.js";
|
|
10
|
+
import executionBroker from "../process-execution-broker/index.js";
|
|
11
|
+
|
|
12
|
+
export const _deps = {
|
|
13
|
+
execFileSync: (...args) => executionBroker.execFileSync(...args),
|
|
14
|
+
};
|
|
11
15
|
|
|
12
16
|
const WINDOWS_RESERVED = new Set([
|
|
13
17
|
"CON",
|
|
@@ -139,22 +143,35 @@ export function precheck(ctx) {
|
|
|
139
143
|
let gitCommit = null;
|
|
140
144
|
let dirty = false;
|
|
141
145
|
let repoRoot = null;
|
|
146
|
+
const gitOptions = (cwd) => ({
|
|
147
|
+
origin: "packer:precheck-git",
|
|
148
|
+
scope: "pack",
|
|
149
|
+
policy: "allow",
|
|
150
|
+
shell: false,
|
|
151
|
+
cwd,
|
|
152
|
+
encoding: "utf-8",
|
|
153
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
154
|
+
});
|
|
142
155
|
try {
|
|
143
|
-
repoRoot =
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
156
|
+
repoRoot = _deps
|
|
157
|
+
.execFileSync(
|
|
158
|
+
"git",
|
|
159
|
+
["rev-parse", "--show-toplevel"],
|
|
160
|
+
gitOptions(projectRoot),
|
|
161
|
+
)
|
|
162
|
+
.trim();
|
|
163
|
+
gitCommit = _deps
|
|
164
|
+
.execFileSync(
|
|
165
|
+
"git",
|
|
166
|
+
["rev-parse", "--short", "HEAD"],
|
|
167
|
+
gitOptions(repoRoot),
|
|
168
|
+
)
|
|
169
|
+
.trim();
|
|
170
|
+
const status = _deps.execFileSync(
|
|
171
|
+
"git",
|
|
172
|
+
["status", "--porcelain"],
|
|
173
|
+
gitOptions(repoRoot),
|
|
174
|
+
);
|
|
158
175
|
dirty = status.trim().length > 0;
|
|
159
176
|
} catch (_e) {
|
|
160
177
|
// Not a git repo — fine, leave the metadata null
|
|
@@ -10,8 +10,12 @@
|
|
|
10
10
|
|
|
11
11
|
import fs from "node:fs";
|
|
12
12
|
import path from "node:path";
|
|
13
|
-
import { spawnSync } from "node:child_process";
|
|
14
13
|
import { PackError, EXIT } from "./errors.js";
|
|
14
|
+
import executionBroker from "../process-execution-broker/index.js";
|
|
15
|
+
|
|
16
|
+
export const _deps = {
|
|
17
|
+
spawnSync: (...args) => executionBroker.spawnSync(...args),
|
|
18
|
+
};
|
|
15
19
|
|
|
16
20
|
/**
|
|
17
21
|
* @param {object} ctx
|
|
@@ -50,11 +54,21 @@ export function ensureWebPanel(ctx) {
|
|
|
50
54
|
if (needsBuild) {
|
|
51
55
|
log(" [web-panel] Building Vue panel via 'npm run build:web-panel'...");
|
|
52
56
|
const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
53
|
-
const res = spawnSync(npmCmd, ["run", "build:web-panel"], {
|
|
57
|
+
const res = _deps.spawnSync(npmCmd, ["run", "build:web-panel"], {
|
|
58
|
+
origin: "packer:web-panel-build",
|
|
59
|
+
scope: "pack",
|
|
60
|
+
policy: "allow",
|
|
61
|
+
shell: false,
|
|
54
62
|
cwd: cliRoot,
|
|
55
63
|
stdio: "inherit",
|
|
56
64
|
windowsHide: true,
|
|
57
65
|
});
|
|
66
|
+
if (res.error) {
|
|
67
|
+
throw new PackError(
|
|
68
|
+
`Failed to start 'npm run build:web-panel': ${res.error.message}`,
|
|
69
|
+
EXIT.WEB_PANEL,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
58
72
|
if (res.status !== 0) {
|
|
59
73
|
throw new PackError(
|
|
60
74
|
`'npm run build:web-panel' exited with code ${res.status}`,
|
|
@@ -61,7 +61,7 @@ const TOOL_GROUPS = Object.freeze({
|
|
|
61
61
|
grep: ["search_files"],
|
|
62
62
|
glob: ["search_files"],
|
|
63
63
|
write: ["write_file"],
|
|
64
|
-
edit: ["edit_file", "edit_file_hashed"],
|
|
64
|
+
edit: ["edit_file", "edit_file_hashed", "delete_file", "move_file"],
|
|
65
65
|
webfetch: ["web_fetch"],
|
|
66
66
|
websearch: ["web_search"],
|
|
67
67
|
task: ["spawn_sub_agent"],
|
|
@@ -82,6 +82,8 @@ const PATH_TOOLS = new Set([
|
|
|
82
82
|
"write_file",
|
|
83
83
|
"edit_file",
|
|
84
84
|
"edit_file_hashed",
|
|
85
|
+
"delete_file",
|
|
86
|
+
"move_file",
|
|
85
87
|
]);
|
|
86
88
|
/** Tools whose match target is a URL. */
|
|
87
89
|
const URL_TOOLS = new Set(["web_fetch"]);
|
|
@@ -354,6 +356,8 @@ const SUGGEST_UMBRELLA = Object.freeze({
|
|
|
354
356
|
write_file: "Write",
|
|
355
357
|
edit_file: "Edit",
|
|
356
358
|
edit_file_hashed: "Edit",
|
|
359
|
+
delete_file: "Edit",
|
|
360
|
+
move_file: "Edit",
|
|
357
361
|
web_fetch: "WebFetch",
|
|
358
362
|
web_search: "WebSearch",
|
|
359
363
|
spawn_sub_agent: "Task",
|
|
@@ -141,7 +141,11 @@ export function createAccountsStore({ hubDir }) {
|
|
|
141
141
|
* spec.validateCookie(). Kept duplicated so the cli build stays ESM-pure
|
|
142
142
|
* without reaching into desktop-app-vue.
|
|
143
143
|
*/
|
|
144
|
-
export function createVendorAdapterBridge({
|
|
144
|
+
export function createVendorAdapterBridge({
|
|
145
|
+
specs,
|
|
146
|
+
runtimeAdapter,
|
|
147
|
+
_httpClientFactory,
|
|
148
|
+
} = {}) {
|
|
145
149
|
// DEFAULT_VENDOR_SPECS is shipped as a vendor-keyed object; tests pass an
|
|
146
150
|
// array. Normalize to an array first so byVendor lookup works either way.
|
|
147
151
|
const effectiveSpecs = specs ?? _loadAichatModule().DEFAULT_VENDOR_SPECS;
|
|
@@ -187,7 +191,15 @@ export function createVendorAdapterBridge({ specs, _httpClientFactory } = {}) {
|
|
|
187
191
|
});
|
|
188
192
|
try {
|
|
189
193
|
const r = await spec.validateCookie({ httpClient: client, session });
|
|
190
|
-
|
|
194
|
+
const result = r || { ok: false, reason: "VALIDATE_RETURNED_NULL" };
|
|
195
|
+
if (
|
|
196
|
+
result.ok &&
|
|
197
|
+
runtimeAdapter &&
|
|
198
|
+
typeof runtimeAdapter.setSession === "function"
|
|
199
|
+
) {
|
|
200
|
+
runtimeAdapter.setSession(vendor, session);
|
|
201
|
+
}
|
|
202
|
+
return result;
|
|
191
203
|
} catch (err) {
|
|
192
204
|
return { ok: false, reason: "VALIDATE_THREW", error: err.message };
|
|
193
205
|
}
|
|
@@ -233,6 +245,8 @@ const _wizardsByHubDir = new Map();
|
|
|
233
245
|
*/
|
|
234
246
|
export function getAIChatWizard({
|
|
235
247
|
hubDir,
|
|
248
|
+
accountsStore,
|
|
249
|
+
vendorAdapter,
|
|
236
250
|
_accountsStore,
|
|
237
251
|
_vendorAdapter,
|
|
238
252
|
_deps,
|
|
@@ -242,8 +256,10 @@ export function getAIChatWizard({
|
|
|
242
256
|
if (!isTest && _wizardsByHubDir.has(hubDir))
|
|
243
257
|
return _wizardsByHubDir.get(hubDir);
|
|
244
258
|
|
|
245
|
-
const
|
|
246
|
-
|
|
259
|
+
const effectiveAccountsStore =
|
|
260
|
+
accountsStore || _accountsStore || createAccountsStore({ hubDir });
|
|
261
|
+
const effectiveVendorAdapter =
|
|
262
|
+
vendorAdapter || _vendorAdapter || createVendorAdapterBridge();
|
|
247
263
|
// Paste-mode is the default for cli. Tests can override via _deps.
|
|
248
264
|
const deps = _deps || {
|
|
249
265
|
sessionFactory: () => ({}),
|
|
@@ -273,8 +289,8 @@ export function getAIChatWizard({
|
|
|
273
289
|
"@chainlesschain/personal-data-hub/adapters/ai-chat-history/wizard-controller",
|
|
274
290
|
);
|
|
275
291
|
const wiz = createAIChatWizardController({
|
|
276
|
-
accountsStore,
|
|
277
|
-
vendorAdapter,
|
|
292
|
+
accountsStore: effectiveAccountsStore,
|
|
293
|
+
vendorAdapter: effectiveVendorAdapter,
|
|
278
294
|
_deps: deps,
|
|
279
295
|
});
|
|
280
296
|
if (!isTest) _wizardsByHubDir.set(hubDir, wiz);
|
|
@@ -136,6 +136,7 @@ let LocalVault,
|
|
|
136
136
|
AmapAdapter,
|
|
137
137
|
TelegramAdapter,
|
|
138
138
|
WhatsAppAdapter,
|
|
139
|
+
AIChatHistoryAdapter,
|
|
139
140
|
EntityResolver,
|
|
140
141
|
EntityResolverEmbeddingStage,
|
|
141
142
|
EntityResolverLLMStage,
|
|
@@ -259,6 +260,7 @@ function ensurePdhLoaded() {
|
|
|
259
260
|
AmapAdapter,
|
|
260
261
|
TelegramAdapter,
|
|
261
262
|
WhatsAppAdapter,
|
|
263
|
+
AIChatHistoryAdapter,
|
|
262
264
|
EntityResolver,
|
|
263
265
|
EntityResolverEmbeddingStage,
|
|
264
266
|
EntityResolverLLMStage,
|
|
@@ -587,6 +589,8 @@ async function initHub() {
|
|
|
587
589
|
// KuaishouSignBridge.
|
|
588
590
|
const { createKuaishouCookiesExtension } =
|
|
589
591
|
await import("@chainlesschain/personal-data-hub/adapters/social-kuaishou-adb");
|
|
592
|
+
const { createWhatsAppBackupExtension } =
|
|
593
|
+
await import("@chainlesschain/personal-data-hub/adapters/messaging-whatsapp");
|
|
590
594
|
hostAdbBridge = createHostAdbBridge({
|
|
591
595
|
extensions: {
|
|
592
596
|
"bilibili.cookies": createBilibiliCookiesExtension(),
|
|
@@ -597,6 +601,7 @@ async function initHub() {
|
|
|
597
601
|
"toutiao.cookies": createToutiaoCookiesExtension(),
|
|
598
602
|
"toutiao.account": createToutiaoAccountExtension(),
|
|
599
603
|
"kuaishou.cookies": createKuaishouCookiesExtension(),
|
|
604
|
+
"whatsapp.backup": createWhatsAppBackupExtension(),
|
|
600
605
|
},
|
|
601
606
|
});
|
|
602
607
|
sda._deps.bridgeProvider = () => hostAdbBridge;
|
|
@@ -796,7 +801,9 @@ async function initHub() {
|
|
|
796
801
|
WhatsAppAdapter,
|
|
797
802
|
]) {
|
|
798
803
|
try {
|
|
799
|
-
const adapter =
|
|
804
|
+
const adapter = Cls === WhatsAppAdapter
|
|
805
|
+
? new Cls({ bridgeProvider: () => hostAdbBridge })
|
|
806
|
+
: new Cls();
|
|
800
807
|
if (!registry.has(adapter.name)) registry.register(adapter);
|
|
801
808
|
} catch (_err) {
|
|
802
809
|
// Continue boot even if one adapter ctor throws
|
|
@@ -838,7 +845,18 @@ async function initHub() {
|
|
|
838
845
|
// periodic loop still validates persisted cookies so list-aichat-accounts
|
|
839
846
|
// can surface lastHealth reliably.
|
|
840
847
|
const aichatAccountsStore = createAIChatAccountsStore({ hubDir });
|
|
841
|
-
const
|
|
848
|
+
const aiChatAdapter = new AIChatHistoryAdapter();
|
|
849
|
+
try {
|
|
850
|
+
const persistedAccounts = await aichatAccountsStore.list();
|
|
851
|
+
aiChatAdapter.restoreSessions(persistedAccounts);
|
|
852
|
+
if (!registry.has(aiChatAdapter.name)) registry.register(aiChatAdapter);
|
|
853
|
+
} catch (_err) {
|
|
854
|
+
// Corrupt rows are skipped by restoreSessions; a store/registry failure
|
|
855
|
+
// must not prevent the rest of the hub from booting.
|
|
856
|
+
}
|
|
857
|
+
const aichatVendorAdapter = createAIChatVendorAdapterBridge({
|
|
858
|
+
runtimeAdapter: aiChatAdapter,
|
|
859
|
+
});
|
|
842
860
|
const createAIChatHealthChecker = await loadAIChatHealthChecker();
|
|
843
861
|
const aichatHealthChecker = createAIChatHealthChecker({
|
|
844
862
|
accountsStore: aichatAccountsStore,
|
|
@@ -849,7 +867,11 @@ async function initHub() {
|
|
|
849
867
|
} catch (_err) {
|
|
850
868
|
// Continue boot even if checker fails to schedule
|
|
851
869
|
}
|
|
852
|
-
const aichatWizard = getAIChatWizard({
|
|
870
|
+
const aichatWizard = getAIChatWizard({
|
|
871
|
+
hubDir,
|
|
872
|
+
accountsStore: aichatAccountsStore,
|
|
873
|
+
vendorAdapter: aichatVendorAdapter,
|
|
874
|
+
});
|
|
853
875
|
|
|
854
876
|
return {
|
|
855
877
|
vault,
|
|
@@ -864,6 +886,7 @@ async function initHub() {
|
|
|
864
886
|
alipayAccountsPath,
|
|
865
887
|
entityResolver,
|
|
866
888
|
aichatAccountsStore,
|
|
889
|
+
aiChatAdapter,
|
|
867
890
|
aichatWizard,
|
|
868
891
|
aichatHealthChecker,
|
|
869
892
|
analysisSkillNames: ANALYSIS_SKILL_NAMES,
|
|
@@ -896,6 +919,7 @@ async function initHub() {
|
|
|
896
919
|
return { ok: false, reason: "NOT_REGISTERED", vendor };
|
|
897
920
|
}
|
|
898
921
|
await aichatAccountsStore.delete(vendor);
|
|
922
|
+
aiChatAdapter.clearSession(vendor);
|
|
899
923
|
try {
|
|
900
924
|
await aichatWizard.rotateLoginPartition({ vendor });
|
|
901
925
|
} catch (_err) {
|
package/src/lib/plan-mode.js
CHANGED
|
@@ -48,6 +48,8 @@ const READ_TOOLS = new Set([
|
|
|
48
48
|
const WRITE_TOOLS = new Set([
|
|
49
49
|
"write_file",
|
|
50
50
|
"edit_file",
|
|
51
|
+
"delete_file",
|
|
52
|
+
"move_file",
|
|
51
53
|
"run_shell",
|
|
52
54
|
"git",
|
|
53
55
|
"run_skill",
|
|
@@ -66,6 +68,8 @@ const TOOL_RISK_WEIGHTS = {
|
|
|
66
68
|
list_skills: 1,
|
|
67
69
|
write_file: 2,
|
|
68
70
|
edit_file: 2,
|
|
71
|
+
delete_file: 2,
|
|
72
|
+
move_file: 2,
|
|
69
73
|
run_skill: 2,
|
|
70
74
|
run_shell: 3,
|
|
71
75
|
git: 3,
|
|
@@ -91,6 +95,10 @@ export class PlanItem {
|
|
|
91
95
|
this.status = data.status || PlanStatus.PENDING;
|
|
92
96
|
this.result = null;
|
|
93
97
|
this.error = null;
|
|
98
|
+
this.turn = Number.isInteger(data.turn) && data.turn > 0 ? data.turn : null;
|
|
99
|
+
this.toolUseId = data.toolUseId || null;
|
|
100
|
+
this.startedAt = data.startedAt || null;
|
|
101
|
+
this.completedAt = data.completedAt || null;
|
|
94
102
|
}
|
|
95
103
|
|
|
96
104
|
/**
|
|
@@ -109,12 +117,16 @@ export class PlanItem {
|
|
|
109
117
|
*/
|
|
110
118
|
export class ExecutionPlan {
|
|
111
119
|
constructor(data = {}) {
|
|
112
|
-
this.id =
|
|
120
|
+
this.id =
|
|
121
|
+
data.id || `plan-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
113
122
|
this.title = data.title || "Untitled Plan";
|
|
114
123
|
this.description = data.description || "";
|
|
115
124
|
this.goal = data.goal || "";
|
|
116
125
|
this.items = (data.items || []).map((i) => new PlanItem(i));
|
|
117
126
|
this.status = data.status || PlanState.ANALYZING;
|
|
127
|
+
this.version =
|
|
128
|
+
Number.isInteger(data.version) && data.version > 0 ? data.version : 1;
|
|
129
|
+
this.revisionOf = data.revisionOf || null;
|
|
118
130
|
this.createdAt = new Date().toISOString();
|
|
119
131
|
}
|
|
120
132
|
|
|
@@ -258,6 +270,7 @@ export class PlanModeManager extends EventEmitter {
|
|
|
258
270
|
this.currentPlan = null;
|
|
259
271
|
this.history = [];
|
|
260
272
|
this.blockedToolLog = [];
|
|
273
|
+
this.executionLock = null;
|
|
261
274
|
this._hookDb = null;
|
|
262
275
|
}
|
|
263
276
|
|
|
@@ -289,6 +302,7 @@ export class PlanModeManager extends EventEmitter {
|
|
|
289
302
|
});
|
|
290
303
|
this.state = PlanState.ANALYZING;
|
|
291
304
|
this.blockedToolLog = [];
|
|
305
|
+
this.executionLock = null;
|
|
292
306
|
|
|
293
307
|
this.emit("enter", { plan: this.currentPlan, state: this.state });
|
|
294
308
|
this._fireHook("PlanModeEnter", { planId: this.currentPlan.id });
|
|
@@ -311,6 +325,7 @@ export class PlanModeManager extends EventEmitter {
|
|
|
311
325
|
this.state = PlanState.INACTIVE;
|
|
312
326
|
this.currentPlan = null;
|
|
313
327
|
this.blockedToolLog = [];
|
|
328
|
+
this.executionLock = null;
|
|
314
329
|
|
|
315
330
|
this.emit("exit", { plan, reason: options.reason || "manual" });
|
|
316
331
|
return { plan };
|
|
@@ -323,6 +338,12 @@ export class PlanModeManager extends EventEmitter {
|
|
|
323
338
|
if (!this.currentPlan) {
|
|
324
339
|
return { error: "No active plan" };
|
|
325
340
|
}
|
|
341
|
+
if (
|
|
342
|
+
this.state !== PlanState.ANALYZING &&
|
|
343
|
+
this.state !== PlanState.PLAN_READY
|
|
344
|
+
) {
|
|
345
|
+
return { error: "Approved plan is locked" };
|
|
346
|
+
}
|
|
326
347
|
|
|
327
348
|
const item = this.currentPlan.addItem(itemData);
|
|
328
349
|
this.emit("item-added", { planId: this.currentPlan.id, item });
|
|
@@ -343,6 +364,49 @@ export class PlanModeManager extends EventEmitter {
|
|
|
343
364
|
return { plan: this.currentPlan };
|
|
344
365
|
}
|
|
345
366
|
|
|
367
|
+
/**
|
|
368
|
+
* Freeze the current draft and start a fresh plan version. This is the only
|
|
369
|
+
* supported way to replace an awaiting-review plan, so old/new IDE diffs can
|
|
370
|
+
* bind to stable plan IDs instead of guessing from mutable item arrays.
|
|
371
|
+
*/
|
|
372
|
+
beginPlanRevision(options = {}) {
|
|
373
|
+
if (!this.currentPlan || !this.isActive()) {
|
|
374
|
+
return { error: "No active plan" };
|
|
375
|
+
}
|
|
376
|
+
if (
|
|
377
|
+
this.state !== PlanState.ANALYZING &&
|
|
378
|
+
this.state !== PlanState.PLAN_READY
|
|
379
|
+
) {
|
|
380
|
+
return { error: "Approved plan is locked" };
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
const previousPlan = this.currentPlan;
|
|
384
|
+
this.history.push(previousPlan);
|
|
385
|
+
this.currentPlan = new ExecutionPlan({
|
|
386
|
+
title: options.title || previousPlan.title,
|
|
387
|
+
goal: options.goal ?? previousPlan.goal,
|
|
388
|
+
description: options.description ?? previousPlan.description,
|
|
389
|
+
version: previousPlan.version + 1,
|
|
390
|
+
revisionOf: previousPlan.id,
|
|
391
|
+
});
|
|
392
|
+
this.state = PlanState.ANALYZING;
|
|
393
|
+
this.blockedToolLog = [];
|
|
394
|
+
this.executionLock = null;
|
|
395
|
+
const payload = {
|
|
396
|
+
plan: this.currentPlan,
|
|
397
|
+
previousPlan,
|
|
398
|
+
reason: String(options.reason || "revision"),
|
|
399
|
+
};
|
|
400
|
+
this.emit("plan-revised", payload);
|
|
401
|
+
this._fireHook("PlanRevised", {
|
|
402
|
+
planId: this.currentPlan.id,
|
|
403
|
+
previousPlanId: previousPlan.id,
|
|
404
|
+
version: this.currentPlan.version,
|
|
405
|
+
reason: payload.reason,
|
|
406
|
+
});
|
|
407
|
+
return payload;
|
|
408
|
+
}
|
|
409
|
+
|
|
346
410
|
/**
|
|
347
411
|
* Approve the plan (or specific items)
|
|
348
412
|
*/
|
|
@@ -362,17 +426,140 @@ export class PlanModeManager extends EventEmitter {
|
|
|
362
426
|
item.status = PlanStatus.APPROVED;
|
|
363
427
|
}
|
|
364
428
|
|
|
429
|
+
this.executionLock = this._buildExecutionLock(
|
|
430
|
+
approvedItems,
|
|
431
|
+
options.permissionMode,
|
|
432
|
+
);
|
|
365
433
|
this.state = PlanState.APPROVED;
|
|
366
434
|
this.currentPlan.status = PlanState.APPROVED;
|
|
367
435
|
this.emit("plan-approved", {
|
|
368
436
|
plan: this.currentPlan,
|
|
369
437
|
approvedCount: approvedItems.length,
|
|
438
|
+
executionLock: this.getExecutionLock(),
|
|
370
439
|
});
|
|
371
440
|
this._fireHook("PlanApproved", {
|
|
372
441
|
planId: this.currentPlan.id,
|
|
373
442
|
itemCount: approvedItems.length,
|
|
443
|
+
permissionMode: this.executionLock.permissionMode,
|
|
444
|
+
allowedTools: this.executionLock.allowedTools,
|
|
445
|
+
});
|
|
446
|
+
return {
|
|
447
|
+
plan: this.currentPlan,
|
|
448
|
+
approvedCount: approvedItems.length,
|
|
449
|
+
executionLock: this.getExecutionLock(),
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/** Build the immutable authority envelope used after plan approval. */
|
|
454
|
+
_buildExecutionLock(approvedItems, permissionMode) {
|
|
455
|
+
const approvedItemIds = approvedItems.map((item) => item.id);
|
|
456
|
+
const allowedTools = [
|
|
457
|
+
...new Set([
|
|
458
|
+
...READ_TOOLS,
|
|
459
|
+
...approvedItems.map((item) => item.tool).filter(Boolean),
|
|
460
|
+
]),
|
|
461
|
+
].sort();
|
|
462
|
+
return Object.freeze({
|
|
463
|
+
planId: this.currentPlan.id,
|
|
464
|
+
permissionMode: String(permissionMode || "default"),
|
|
465
|
+
approvedItemIds: Object.freeze(approvedItemIds),
|
|
466
|
+
allowedTools: Object.freeze(allowedTools),
|
|
467
|
+
createdAt: new Date().toISOString(),
|
|
374
468
|
});
|
|
375
|
-
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/** Return a serializable copy so callers cannot widen the live lock. */
|
|
472
|
+
getExecutionLock() {
|
|
473
|
+
if (!this.executionLock) return null;
|
|
474
|
+
return {
|
|
475
|
+
...this.executionLock,
|
|
476
|
+
approvedItemIds: [...this.executionLock.approvedItemIds],
|
|
477
|
+
allowedTools: [...this.executionLock.allowedTools],
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Attribute a live tool call to the next approved item for that tool.
|
|
483
|
+
* Read-only/helper calls that were not part of the approved plan remain
|
|
484
|
+
* unbound instead of advancing an unrelated item.
|
|
485
|
+
*/
|
|
486
|
+
startPlanItemForTool(toolName, context = {}) {
|
|
487
|
+
if (
|
|
488
|
+
!this.currentPlan ||
|
|
489
|
+
(this.state !== PlanState.APPROVED && this.state !== PlanState.EXECUTING)
|
|
490
|
+
) {
|
|
491
|
+
return null;
|
|
492
|
+
}
|
|
493
|
+
const tool = String(toolName || "");
|
|
494
|
+
const item = this.currentPlan.items.find(
|
|
495
|
+
(candidate) =>
|
|
496
|
+
candidate.status === PlanStatus.APPROVED && candidate.tool === tool,
|
|
497
|
+
);
|
|
498
|
+
if (!item) return null;
|
|
499
|
+
|
|
500
|
+
item.status = PlanStatus.EXECUTING;
|
|
501
|
+
item.toolUseId = context.toolUseId || null;
|
|
502
|
+
item.turn =
|
|
503
|
+
Number.isInteger(context.turn) && context.turn > 0 ? context.turn : null;
|
|
504
|
+
item.startedAt = String(context.startedAt || new Date().toISOString());
|
|
505
|
+
item.completedAt = null;
|
|
506
|
+
item.result = null;
|
|
507
|
+
item.error = null;
|
|
508
|
+
this.state = PlanState.EXECUTING;
|
|
509
|
+
this.currentPlan.status = PlanState.EXECUTING;
|
|
510
|
+
this.emit("item-executing", { planId: this.currentPlan.id, item });
|
|
511
|
+
this._fireHook("PlanItemExecute", {
|
|
512
|
+
planId: this.currentPlan.id,
|
|
513
|
+
itemId: item.id,
|
|
514
|
+
tool: item.tool,
|
|
515
|
+
toolUseId: item.toolUseId,
|
|
516
|
+
turn: item.turn,
|
|
517
|
+
});
|
|
518
|
+
return item;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/** Settle a tool-attributed item and derive the aggregate execution state. */
|
|
522
|
+
settlePlanItem(itemId, options = {}) {
|
|
523
|
+
if (!this.currentPlan || !itemId) return null;
|
|
524
|
+
const item = this.currentPlan.getItem(itemId);
|
|
525
|
+
if (!item || item.status !== PlanStatus.EXECUTING) return null;
|
|
526
|
+
|
|
527
|
+
const success = options.success !== false;
|
|
528
|
+
item.status = success ? PlanStatus.COMPLETED : PlanStatus.FAILED;
|
|
529
|
+
item.completedAt = String(options.completedAt || new Date().toISOString());
|
|
530
|
+
item.result = success ? (options.result ?? null) : null;
|
|
531
|
+
item.error = success ? null : String(options.error || "tool failed");
|
|
532
|
+
|
|
533
|
+
const tracked = this.currentPlan.items.filter((candidate) =>
|
|
534
|
+
[
|
|
535
|
+
PlanStatus.APPROVED,
|
|
536
|
+
PlanStatus.EXECUTING,
|
|
537
|
+
PlanStatus.COMPLETED,
|
|
538
|
+
PlanStatus.FAILED,
|
|
539
|
+
].includes(candidate.status),
|
|
540
|
+
);
|
|
541
|
+
const allSettled =
|
|
542
|
+
tracked.length > 0 &&
|
|
543
|
+
tracked.every((candidate) =>
|
|
544
|
+
[PlanStatus.COMPLETED, PlanStatus.FAILED].includes(candidate.status),
|
|
545
|
+
);
|
|
546
|
+
if (allSettled) {
|
|
547
|
+
this.state = tracked.some(
|
|
548
|
+
(candidate) => candidate.status === PlanStatus.FAILED,
|
|
549
|
+
)
|
|
550
|
+
? PlanState.FAILED
|
|
551
|
+
: PlanState.COMPLETED;
|
|
552
|
+
} else {
|
|
553
|
+
this.state = PlanState.EXECUTING;
|
|
554
|
+
}
|
|
555
|
+
this.currentPlan.status = this.state;
|
|
556
|
+
this.emit("item-settled", {
|
|
557
|
+
planId: this.currentPlan.id,
|
|
558
|
+
item,
|
|
559
|
+
success,
|
|
560
|
+
state: this.state,
|
|
561
|
+
});
|
|
562
|
+
return item;
|
|
376
563
|
}
|
|
377
564
|
|
|
378
565
|
/**
|
|
@@ -401,7 +588,10 @@ export class PlanModeManager extends EventEmitter {
|
|
|
401
588
|
this.state === PlanState.APPROVED ||
|
|
402
589
|
this.state === PlanState.EXECUTING
|
|
403
590
|
) {
|
|
404
|
-
|
|
591
|
+
const allowed =
|
|
592
|
+
this.executionLock?.allowedTools.includes(toolName) === true;
|
|
593
|
+
if (!allowed) this._recordBlockedTool(toolName, "execution-lock");
|
|
594
|
+
return allowed;
|
|
405
595
|
}
|
|
406
596
|
|
|
407
597
|
// In analyzing/plan_ready state, only read tools are allowed
|
|
@@ -409,11 +599,7 @@ export class PlanModeManager extends EventEmitter {
|
|
|
409
599
|
|
|
410
600
|
// Block write tools and log
|
|
411
601
|
if (WRITE_TOOLS.has(toolName)) {
|
|
412
|
-
this.
|
|
413
|
-
tool: toolName,
|
|
414
|
-
timestamp: new Date().toISOString(),
|
|
415
|
-
});
|
|
416
|
-
this.emit("tool-blocked", { toolName });
|
|
602
|
+
this._recordBlockedTool(toolName, "planning");
|
|
417
603
|
return false;
|
|
418
604
|
}
|
|
419
605
|
|
|
@@ -421,6 +607,15 @@ export class PlanModeManager extends EventEmitter {
|
|
|
421
607
|
return false;
|
|
422
608
|
}
|
|
423
609
|
|
|
610
|
+
_recordBlockedTool(toolName, reason) {
|
|
611
|
+
this.blockedToolLog.push({
|
|
612
|
+
tool: toolName,
|
|
613
|
+
reason,
|
|
614
|
+
timestamp: new Date().toISOString(),
|
|
615
|
+
});
|
|
616
|
+
this.emit("tool-blocked", { toolName, reason });
|
|
617
|
+
}
|
|
618
|
+
|
|
424
619
|
/**
|
|
425
620
|
* Generate a text summary of the current plan
|
|
426
621
|
*/
|
|
@@ -501,9 +696,7 @@ export class PlanModeManager extends EventEmitter {
|
|
|
501
696
|
|
|
502
697
|
const allDone = results.every((r) => r.success);
|
|
503
698
|
this.state = allDone ? PlanState.COMPLETED : PlanState.FAILED;
|
|
504
|
-
this.currentPlan.status = allDone
|
|
505
|
-
? PlanState.COMPLETED
|
|
506
|
-
: PlanState.FAILED;
|
|
699
|
+
this.currentPlan.status = allDone ? PlanState.COMPLETED : PlanState.FAILED;
|
|
507
700
|
|
|
508
701
|
return { results, success: allDone };
|
|
509
702
|
}
|