chainlesschain 0.162.147 → 0.162.149
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/README.md +1 -1
- package/package.json +2 -2
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-DywJ7xTv.js → AIOps-BJif14yR.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BTlqcY-q.js → ActionButton-CXek6gJY.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-FdG1Mvwy.js → Analytics-BgQhdAJi.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-CVsnbvN1.js → AppLayout-DTYl5NtR.js} +5 -5
- package/src/assets/web-panel/assets/{Audit-ITdpJ7vR.js → Audit-BzATQAeR.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BfXqnXo1.js → Backup-BzdPEQhL.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-C09ip3_E.js → BaseInput-BM0KVh8E.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-qdkhB42l.js → Chat-D7fHXHkz.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-D2KfETZD.js → ChatBubbleRenderer-Wm34RR-b.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-j6WZCuff.js → Checkbox-CAiSQ9vO.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CGZ-K3uK.js → Codegen-Df40CrEe.js} +1 -1
- package/src/assets/web-panel/assets/{Col-CIlPOAu6.js → Col-DIT2fNFU.js} +1 -1
- package/src/assets/web-panel/assets/{Community-sY-i-hic.js → Community-CSTIbW2k.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DcoEfyL8.js → Compact-DtqXZZUi.js} +1 -1
- package/src/assets/web-panel/assets/Compliance-CUtzw6o7.js +1 -0
- package/src/assets/web-panel/assets/{Cowork-DLY_fkLv.js → Cowork-CezmlnmU.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-D049pZBC.js → Cron-P4BITarg.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-DCXdE8M9.js → Crosschain-BRRiYwvq.js} +1 -1
- package/src/assets/web-panel/assets/{DID-JCvPZtjW.js → DID-L5ijB9i4.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-Cg2xu3iE.js → Dashboard-CFxro4ob.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DjJLjbLh.js → Dropdown-BmAFCQ71.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DugNcSLR.js → EmailListRenderer-DJBCEuon.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-J6Nb-E30.js → FamilyGuardDashboard-z4oLq6eT.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CQ3Ttpbl.js → Federation-DsVCpHMF.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-Cz0NKag4.js → FormItemContext-DP3bP5th.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-NYcMP6iz.js → GenericCardRenderer-BAXP2Gc6.js} +1 -1
- package/src/assets/web-panel/assets/{Git-B4hYN18N.js → Git-I3g_bAw9.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DOQPCcC0.js → Governance-jHS5-ioS.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-HtLF746W.js → Inference-CPL7sfx9.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-BXrk8rMm.js → KnowledgeGraph-Jf236h4C.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-DS0JnD3-.js → Logs-Cm2tcSKg.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-Cqnjihrz.js → Marketplace-CZK82rhi.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-Cx3Psk-U.js → McpTools-CZCeji7a.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-BjyysPtj.js → Memory-3l2KVS9k.js} +2 -2
- package/src/assets/web-panel/assets/MobileBridge-D3Arxfeg.css +1 -0
- package/src/assets/web-panel/assets/MobileBridge-VYdpoLh6.js +1 -0
- package/src/assets/web-panel/assets/{MobileProjects-Xwf-fdOQ.js → MobileProjects-CiB9cmm1.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-Djkql5m5.js → Mtc-wCFZbBuL.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-D2BAZlu0.js → MtcAudit-1a3THIyG.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-ByqP1ZzH.js → Multisig-DMzLB2hG.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-C_kn0nE2.js → NLProgramming-D9wZbf6l.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-7l7eXHPq.js → Notes-hrFe2ZM-.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-BrCDoitw.js → NotificationSettings-CHGX5Jwm.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-CRIFE2Tj.js +1 -0
- package/src/assets/web-panel/assets/{Organization-DdoNAxsM.js → Organization-By7FkhtY.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Bw7R6dE3.js → Overflow--khGSzJn.js} +1 -1
- package/src/assets/web-panel/assets/{OverrideContext-C2r4vyBb.js → OverrideContext-BlgL9440.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-DJNtBugA.js → P2P-CAG9dH35.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Dwhd5_ue.js → PdhVaultBrowser-B3SQZmK9.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-BYoSfhPR.js → Permissions-D35ec6JA.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-aYCYJbnH.js → PersonalDataHub-CxBF7hW_.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-DJp6CprF.js → Pipeline-s6EtOO1s.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-Cq9HZweR.js → Privacy-BbJYmWmO.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CmF0HsSt.js → ProjectInit-VGQq1jMT.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-P8V5Aea2.js → ProjectSettings-B1ew3Teh.js} +2 -2
- package/src/assets/web-panel/assets/Projects-CGcNIs_g.js +1 -0
- package/src/assets/web-panel/assets/{Providers-D589v0q2.js → Providers-mrO47FIK.js} +1 -1
- package/src/assets/web-panel/assets/QrScannerModal-IJF2mHyw.js +1 -0
- package/src/assets/web-panel/assets/{MobileBridge-zJpPuf4E.css → QrScannerModal-NwAHNfiJ.css} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-lvRV2osB.js → QuickAsk-CU0wN_Z0.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-sb84MTpY.js → Recommend-DhN37R6G.js} +1 -1
- package/src/assets/web-panel/assets/RemoteSession-D_xOX_hu.js +4 -0
- package/src/assets/web-panel/assets/{Reputation-d9Y3vy-W.js → Reputation-D_Ssv7uH.js} +1 -1
- package/src/assets/web-panel/assets/{Row-DMdhLUTp.js → Row-Kx5dKxX7.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-OL-SMDkz.js → RssFeed-BlGwqZkY.js} +2 -2
- package/src/assets/web-panel/assets/{Search-BjStLKq1.js → Search-hLFQzxpb.js} +1 -1
- package/src/assets/web-panel/assets/{Security-MeI411qr.js → Security-DMlvsVt4.js} +2 -2
- package/src/assets/web-panel/assets/{Services-UajosuhT.js → Services-Bd0Qsj2m.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CGpG-QJ1.js → Skeleton-DFclq9X3.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-C6P2RPY-.js → Skills-BNtln2qY.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-B_fPprgw.js → Sla-Dch5H19G.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-CqxLjSlQ.js → SpeechSettings-2UfQcU1g.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DixSfFOQ.js → SyncSettings-CD9YQr4i.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-PavzPBxc.js → Tasks-BNu-7MzI.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BYdGRnfX.js → Templates-D1n9CaIR.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-BQLgnarD.js → Tenant-DenL3iBW.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-ZzU0Io1Y.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-Bv7uZRM7.js → TimelineRenderer-D87IfukO.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DxhgszRJ.js → Tokens-BkiZc8E3.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-nQYHayuc.js → Trigger-BNRSytGN.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CvqZDuZ4.js → Trust-Bwbd4X2m.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-DaR8GV2I.js → UkeySign-B8O2bs0o.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-C6Mpsokw.js → VideoEditing-C2fL8zmH.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-B57VRrWc.js → Wallet-BORYDdE1.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-BbtEEtpq.js → WebAuthn-C0V5S2FM.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-C5LwvKmH.js → WorkflowEditor-2dR0fcHL.js} +1 -1
- package/src/assets/web-panel/assets/{chat-MzuPR5jh.js → chat-BmuAFAn8.js} +1 -1
- package/src/assets/web-panel/assets/{collapseMotion-mxzzcDsg.js → collapseMotion-DVfhbsdP.js} +1 -1
- package/src/assets/web-panel/assets/{colors-HyW8mi_y.js → colors-CN3smMcK.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-DvUSzWAp.js → compact-item-DCnxb4kW.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-4MppZl7X.js → createContext-vlR43pHn.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DxwmsL4j.js +1 -0
- package/src/assets/web-panel/assets/{echarts-jxgIOFUZ.js → echarts-CL0F2SnX.js} +1 -1
- package/src/assets/web-panel/assets/{hasIn-D9q3CJ-u.js → hasIn-D04tHYFd.js} +1 -1
- package/src/assets/web-panel/assets/{icons-DP3uiYxy.js → icons-BsDmGpcT.js} +1 -1
- package/src/assets/web-panel/assets/{index-C9I5MuJ0.js → index-0DnaZGkC.js} +1 -1
- package/src/assets/web-panel/assets/{index-Caqtu6Et.js → index-430S68MN.js} +1 -1
- package/src/assets/web-panel/assets/{index-eOQO6KnV.js → index-B78xL3s2.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ci6adKh8.js → index-BTPEZTk1.js} +1 -1
- package/src/assets/web-panel/assets/{index-CifKUNtV.js → index-BXRg8GFQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-D7TDMMfu.js → index-BasvsWDM.js} +1 -1
- package/src/assets/web-panel/assets/{index-DNYqw0MO.js → index-BeGDEXFs.js} +1 -1
- package/src/assets/web-panel/assets/{index-m0b6Fj9q.js → index-BqhASEL4.js} +1 -1
- package/src/assets/web-panel/assets/{index-BF2JsbiX.js → index-BudvKQfG.js} +1 -1
- package/src/assets/web-panel/assets/{index-DFqvWeGc.js → index-C-6NO5il.js} +1 -1
- package/src/assets/web-panel/assets/{index-SDblbKj6.js → index-C5Sxb1sE.js} +1 -1
- package/src/assets/web-panel/assets/{index-UUMCA2Sq.js → index-CP9m9Ggr.js} +4 -4
- package/src/assets/web-panel/assets/{index--Bm6OqmU.js → index-CTOCnIQ7.js} +1 -1
- package/src/assets/web-panel/assets/index-Cg2ldRfU.js +1 -0
- package/src/assets/web-panel/assets/{index-Dv7ffI2g.js → index-ClhAHDK3.js} +1 -1
- package/src/assets/web-panel/assets/{index-BcunsBIx.js → index-CnXebZLL.js} +1 -1
- package/src/assets/web-panel/assets/{index-CvAqCAo9.js → index-CngCC8hC.js} +1 -1
- package/src/assets/web-panel/assets/{index-DcMkjb92.js → index-Cr-A0FYJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BFGfC5RS.js → index-CsAsCPJ6.js} +1 -1
- package/src/assets/web-panel/assets/{index-DDZ6fP5Z.js → index-D28DeAAB.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgIfXOD9.js → index-D5LZVZ0L.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmZ6-suL.js → index-D65_XseV.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cs-RKRUM.js → index-D8vwp4qp.js} +1 -1
- package/src/assets/web-panel/assets/{index-B994UQfE.js → index-DDwLgQY9.js} +1 -1
- package/src/assets/web-panel/assets/{index-Btz8pU68.js → index-DIpY0qM5.js} +1 -1
- package/src/assets/web-panel/assets/{index-B5E4DhVc.js → index-DTWg-18U.js} +1 -1
- package/src/assets/web-panel/assets/{index-D2jrnaq3.js → index-DTtRscUa.js} +1 -1
- package/src/assets/web-panel/assets/{index-BmCo2Xdp.js → index-DYAtmqiv.js} +1 -1
- package/src/assets/web-panel/assets/{index-Zvtru2oE.js → index-D_n8_vfI.js} +1 -1
- package/src/assets/web-panel/assets/{index-CLAZs1Vd.js → index-DbADHwhr.js} +1 -1
- package/src/assets/web-panel/assets/{index-CucRo4Vz.js → index-DbVsQBOH.js} +1 -1
- package/src/assets/web-panel/assets/index-Dwzo-dtJ.js +1 -0
- package/src/assets/web-panel/assets/{index-C0DiL97c.js → index-HhNjnCfe.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bl-E4W4q.js → index-ToUh2b1-.js} +1 -1
- package/src/assets/web-panel/assets/{index-ryFLxB1p.js → index-TslMTwNy.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGQtFso0.js → index-_FIkN3jd.js} +1 -1
- package/src/assets/web-panel/assets/{index-zLwYpvX0.js → index-hpvvtAZ3.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dvg5xYuP.js → index-jzR7Ujuw.js} +1 -1
- package/src/assets/web-panel/assets/{index-xvUVuFnA.js → index-ljuBiQW9.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-CC--PMsC.js → initDefaultProps-C3wUb4je.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DdrBjRF1.js → motion-D-jYFUNA.js} +1 -1
- package/src/assets/web-panel/assets/{move-D712Gwl2.js → move-tqb8nwJ2.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-39y-keKO.js → mtc-parser-DSOjMJMz.js} +1 -1
- package/src/assets/web-panel/assets/{omit-6Y51gDB9.js → omit-CJ7VimIW.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-Cy6EHbq9.js → pickAttrs-qXiG1iT3.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BYxdAm0p.js → placementArrow-CkGBcy1Z.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-C9R6q_cr.js → responsiveObserve-D3WvTlLO.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CXUJlilB.js → slide-BEE2ftge.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DOtrOeql.js → statusUtils-CsfBpxiG.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-D5r39o92.js → styleChecker-xPrIiJPI.js} +1 -1
- package/src/assets/web-panel/assets/useFlexGapSupport-C5Yd-SCR.js +1 -0
- package/src/assets/web-panel/assets/{useFs-BkrT-Zbc.js → useFs-D_MDS8HI.js} +1 -1
- package/src/assets/web-panel/assets/{useMergedState-Cl2q1fes.js → useMergedState-Dc9sO2d7.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BwnnnZjU.js → usePersonalDataHub-BqJh-usA.js} +1 -1
- package/src/assets/web-panel/assets/{useRefs-DD9q4mOT.js → useRefs-CAeFRzPf.js} +1 -1
- package/src/assets/web-panel/assets/{useState-BK4hy8Ma.js → useState-LwExUYDO.js} +1 -1
- package/src/assets/web-panel/assets/{vendor-BvqAck49.js → vendor-BMxUs6UX.js} +16 -16
- package/src/assets/web-panel/assets/{vnode-SU-N4pum.js → vnode-chm_p-gz.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DHScfpTP.js → zoom-3-YDNz0Z.js} +1 -1
- package/src/assets/web-panel/index.html +3 -3
- package/src/assets/web-panel/remote-session-sw.js +43 -0
- package/src/command-manifest.json +22 -1
- package/src/commands/agent.js +44 -5
- package/src/commands/codeintel.js +252 -0
- package/src/commands/eval.js +248 -0
- package/src/commands/plugin.js +354 -0
- package/src/commands/serve.js +10 -0
- package/src/commands/team.js +456 -0
- package/src/gateways/remote-session-relay.js +160 -0
- package/src/gateways/ws/message-dispatcher.js +77 -2
- package/src/gateways/ws/remote-session-protocol.js +466 -0
- package/src/gateways/ws/ws-server.js +299 -0
- package/src/harness/golden-transcript.js +65 -0
- package/src/harness/mcp-client.js +6 -2
- package/src/harness/prompt-compressor.js +27 -1
- package/src/harness/remote-command-ledger.js +158 -0
- package/src/harness/remote-session-audit-sink.js +132 -0
- package/src/harness/remote-session-audit.js +110 -0
- package/src/harness/remote-session-crypto.js +217 -0
- package/src/harness/remote-session-push-apns.js +246 -0
- package/src/harness/remote-session-push-errors.js +15 -0
- package/src/harness/remote-session-push-fcm.js +238 -0
- package/src/harness/remote-session-push-huawei.js +174 -0
- package/src/harness/remote-session-push-oppo.js +171 -0
- package/src/harness/remote-session-push-senders.js +42 -0
- package/src/harness/remote-session-push-vivo.js +179 -0
- package/src/harness/remote-session-push-web.js +299 -0
- package/src/harness/remote-session-push-xiaomi.js +99 -0
- package/src/harness/remote-session-push.js +104 -0
- package/src/harness/remote-session-registry.js +420 -0
- package/src/index.js +6 -0
- package/src/lib/agent-core.js +2 -0
- package/src/lib/agent-sandbox.js +161 -5
- package/src/lib/agent-team/task-lease.js +434 -0
- package/src/lib/agent-team/team-budget.js +165 -0
- package/src/lib/agent-team/team-mailbox.js +106 -0
- package/src/lib/agent-team/team-runner.js +266 -0
- package/src/lib/agent-team/team-worktree.js +204 -0
- package/src/lib/agents.js +18 -0
- package/src/lib/async-hook-supervisor.cjs +305 -0
- package/src/lib/did-manager.js +6 -4
- package/src/lib/eval/runner.js +163 -0
- package/src/lib/eval/tasks.js +456 -0
- package/src/lib/eval/trend.js +185 -0
- package/src/lib/lsp/__tests__/code-intelligence.integration.test.js +129 -0
- package/src/lib/lsp/__tests__/code-intelligence.test.js +228 -0
- package/src/lib/lsp/__tests__/jsonrpc-stream.test.js +104 -0
- package/src/lib/lsp/__tests__/lsp-client.test.js +258 -0
- package/src/lib/lsp/__tests__/lsp-manager.test.js +264 -0
- package/src/lib/lsp/__tests__/lsp-server-registry.test.js +128 -0
- package/src/lib/lsp/code-intelligence.js +356 -0
- package/src/lib/lsp/jsonrpc-stream.js +139 -0
- package/src/lib/lsp/lsp-client.js +318 -0
- package/src/lib/lsp/lsp-manager.js +323 -0
- package/src/lib/lsp/lsp-server-registry.js +196 -0
- package/src/lib/mcp-oauth.js +23 -6
- package/src/lib/plugin-monitor-supervisor.js +238 -0
- package/src/lib/plugin-runtime/agents.js +51 -0
- package/src/lib/plugin-runtime/bin.js +100 -0
- package/src/lib/plugin-runtime/hooks.js +100 -0
- package/src/lib/plugin-runtime/install.js +388 -0
- package/src/lib/plugin-runtime/lsp.js +75 -0
- package/src/lib/plugin-runtime/manifest.js +458 -0
- package/src/lib/plugin-runtime/mcp.js +89 -0
- package/src/lib/plugin-runtime/monitors.js +100 -0
- package/src/lib/plugin-runtime/policy.js +144 -0
- package/src/lib/plugin-runtime/reload.js +79 -0
- package/src/lib/plugin-runtime/scopes.js +197 -0
- package/src/lib/plugin-runtime/settings.js +119 -0
- package/src/lib/plugin-runtime/signature.js +107 -0
- package/src/lib/plugin-runtime/skills.js +43 -0
- package/src/lib/plugin-runtime/trust.js +140 -0
- package/src/lib/sandbox-egress-proxy.js +162 -0
- package/src/lib/sandbox-network-policy.js +134 -0
- package/src/lib/sandbox-v2.js +10 -4
- package/src/lib/session-manager.js +7 -3
- package/src/lib/settings-hook-events.cjs +78 -6
- package/src/lib/settings-hooks.cjs +29 -3
- package/src/lib/settings-loader.cjs +35 -1
- package/src/lib/skill-loader.js +18 -0
- package/src/lib/telemetry/span-recorder.js +237 -0
- package/src/repl/agent-repl.js +400 -4
- package/src/runtime/agent-core.js +546 -52
- package/src/runtime/agent-runtime.js +8 -13
- package/src/runtime/coding-agent-contract-shared.cjs +82 -8
- package/src/runtime/coding-agent-policy.cjs +32 -7
- package/src/runtime/fallback-model.js +134 -7
- package/src/runtime/headless-runner.js +353 -108
- package/src/runtime/mcp-config.js +46 -0
- package/src/runtime/policies/agent-policy.js +2 -0
- package/src/assets/web-panel/assets/Compliance-T8EtTecW.js +0 -1
- package/src/assets/web-panel/assets/MobileBridge-CYaITZ7w.js +0 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-CmtqIdwr.js +0 -1
- package/src/assets/web-panel/assets/Projects-DPd5-lNS.js +0 -1
- package/src/assets/web-panel/assets/Terminal-BzOHpq-B.js +0 -3
- package/src/assets/web-panel/assets/devWarning-6YJJMjSH.js +0 -1
- package/src/assets/web-panel/assets/index-D_oeGLr6.js +0 -1
- package/src/assets/web-panel/assets/index-Qa57YG19.js +0 -1
- package/src/assets/web-panel/assets/useFlexGapSupport-DfAD5U4Z.js +0 -1
|
@@ -315,9 +315,14 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
315
315
|
const { loadHooks, projectHookTrustNotice } =
|
|
316
316
|
await import("../lib/settings-hooks.cjs");
|
|
317
317
|
const loaded = loadHooks({ cwd, settingsFile: options.settingsFile });
|
|
318
|
+
// Fold in installed plugins' hooks/hooks.json (Phase 3.3c) — plugins ADD
|
|
319
|
+
// to the user's settings hooks, never replace them.
|
|
320
|
+
const { mergePluginHooks } =
|
|
321
|
+
await import("../lib/plugin-runtime/hooks.js");
|
|
322
|
+
const effectiveHooks = mergePluginHooks(loaded.hooks, { cwd });
|
|
318
323
|
settingsHooks =
|
|
319
|
-
|
|
320
|
-
?
|
|
324
|
+
effectiveHooks && Object.keys(effectiveHooks).length > 0
|
|
325
|
+
? effectiveHooks
|
|
321
326
|
: null;
|
|
322
327
|
// First-run trust notice for an untrusted/cloned repo's shell-running
|
|
323
328
|
// hooks (Claude-Code 2.1.195 parity). Best-effort, stderr-only.
|
|
@@ -335,6 +340,26 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
335
340
|
}
|
|
336
341
|
}
|
|
337
342
|
|
|
343
|
+
// Put trusted plugins' bin/ executables on PATH for this headless run (Phase
|
|
344
|
+
// 3.3n) so run_shell can invoke them by name. Trust-gated. The process exits
|
|
345
|
+
// at the end of the run, so no explicit restore is needed.
|
|
346
|
+
try {
|
|
347
|
+
const { applyPluginBinPath } = await import("../lib/plugin-runtime/bin.js");
|
|
348
|
+
applyPluginBinPath({ cwd });
|
|
349
|
+
} catch {
|
|
350
|
+
/* best-effort — plugin bin PATH never blocks a headless run */
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Apply trusted plugins' default env vars for this run (Phase 3.3o) — only for
|
|
354
|
+
// keys not already set; the process exits at the end so no restore is needed.
|
|
355
|
+
try {
|
|
356
|
+
const { applyPluginSettingsEnv } =
|
|
357
|
+
await import("../lib/plugin-runtime/settings.js");
|
|
358
|
+
applyPluginSettingsEnv({ cwd });
|
|
359
|
+
} catch {
|
|
360
|
+
/* best-effort — plugin settings never block a headless run */
|
|
361
|
+
}
|
|
362
|
+
|
|
338
363
|
// autoMode.classifyAllShell (Claude-Code 2.1.193): route the built-in
|
|
339
364
|
// verification allowlist through the shell-policy classifier instead of
|
|
340
365
|
// fast-pathing it. Explicit option wins; otherwise read settings.json.
|
|
@@ -668,6 +693,31 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
668
693
|
}
|
|
669
694
|
}
|
|
670
695
|
|
|
696
|
+
// settings.json SessionResume hooks: fire when a persisted session's prior
|
|
697
|
+
// history is actually being replayed (--resume / --continue with real
|
|
698
|
+
// history), distinct from SessionStart (which also fires on a fresh startup).
|
|
699
|
+
// A SessionResume hook can react to "we're picking an existing conversation
|
|
700
|
+
// back up" — e.g. re-run a workspace sanity check. Observe-only, best-effort.
|
|
701
|
+
if (settingsHooks && resumeId && history.length > 0) {
|
|
702
|
+
try {
|
|
703
|
+
const { runObserveHooks } =
|
|
704
|
+
await import("../lib/settings-hook-events.cjs");
|
|
705
|
+
runObserveHooks(
|
|
706
|
+
settingsHooks,
|
|
707
|
+
"SessionResume",
|
|
708
|
+
{
|
|
709
|
+
session_id: sessionId,
|
|
710
|
+
resumed_from: resumeId,
|
|
711
|
+
history_messages: history.length,
|
|
712
|
+
cwd,
|
|
713
|
+
},
|
|
714
|
+
{ cwd },
|
|
715
|
+
);
|
|
716
|
+
} catch (_err) {
|
|
717
|
+
// observe-only
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
|
|
671
721
|
// --image <path>: attach vision input to the user turn. buildUserContent
|
|
672
722
|
// returns the plain string when there are no images, so text-only runs are
|
|
673
723
|
// byte-for-byte unchanged; with images it builds an OpenAI-style multimodal
|
|
@@ -810,9 +860,40 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
810
860
|
}
|
|
811
861
|
}
|
|
812
862
|
|
|
863
|
+
// --otlp <file>: attach an OpenTelemetry recorder so the real agent loop's
|
|
864
|
+
// model/tool/retry spans are captured and exported as OTLP/JSON on exit.
|
|
865
|
+
// Off by default (zero cost) — only built when a path is requested.
|
|
866
|
+
let _otlpRecorder = null;
|
|
867
|
+
if (options.otlp) {
|
|
868
|
+
try {
|
|
869
|
+
const { TelemetryRecorder } =
|
|
870
|
+
await import("../lib/telemetry/span-recorder.js");
|
|
871
|
+
_otlpRecorder = new TelemetryRecorder({ serviceName: "cc-agent" });
|
|
872
|
+
} catch {
|
|
873
|
+
_otlpRecorder = null; // telemetry is best-effort, never blocks the run
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
// Async-hook supervisor for headless: without one, `async:true` hooks
|
|
878
|
+
// (PostToolUse / Stop) were silently skipped in `cc agent -p` (they only ran
|
|
879
|
+
// in the REPL). Create one when settings hooks are present so background
|
|
880
|
+
// checks run + get reaped here too. Fire-and-forget; drained after the loop.
|
|
881
|
+
let _hookSupervisor = null;
|
|
882
|
+
if (settingsHooks) {
|
|
883
|
+
try {
|
|
884
|
+
const { AsyncHookSupervisor } =
|
|
885
|
+
await import("../lib/async-hook-supervisor.cjs");
|
|
886
|
+
_hookSupervisor = new AsyncHookSupervisor();
|
|
887
|
+
} catch {
|
|
888
|
+
_hookSupervisor = null; // async hooks are best-effort
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
813
892
|
const loopOptions = {
|
|
814
893
|
model,
|
|
815
894
|
provider,
|
|
895
|
+
recorder: _otlpRecorder,
|
|
896
|
+
hookSupervisor: _hookSupervisor,
|
|
816
897
|
// Extended thinking (Anthropic; opt-in via --think/--ultrathink). null/off
|
|
817
898
|
// → chatWithTools sends no thinking field. thinkingBudget (--thinking-budget)
|
|
818
899
|
// is the legacy-model budget_tokens override; ignored when thinking is off.
|
|
@@ -950,126 +1031,224 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
950
1031
|
goal_id: boundGoalId,
|
|
951
1032
|
});
|
|
952
1033
|
|
|
1034
|
+
// --auto-rewake: after a turn finishes, run the async Stop hooks and, if an
|
|
1035
|
+
// `asyncRewake` check FAILED, append its report as a new user turn and re-run
|
|
1036
|
+
// the agent to fix it — bounded by `maxRewakes` (default 1). OPT-IN: when off
|
|
1037
|
+
// (the default), rewakeBudget is 0 and the loop below runs exactly once, so
|
|
1038
|
+
// one-shot `cc agent -p` behavior is byte-for-byte unchanged and no script is
|
|
1039
|
+
// surprised by a silent re-run. `_asyncStopHandled` tells the finally the
|
|
1040
|
+
// async Stop hooks already fired here so they aren't fired twice.
|
|
1041
|
+
const autoRewake = options.autoRewake === true;
|
|
1042
|
+
let rewakeBudget = autoRewake
|
|
1043
|
+
? Number.isFinite(options.maxRewakes)
|
|
1044
|
+
? options.maxRewakes
|
|
1045
|
+
: 1
|
|
1046
|
+
: 0;
|
|
1047
|
+
let _asyncStopHandled = false;
|
|
1048
|
+
const _settleAsyncStop = async () => {
|
|
1049
|
+
if (!settingsHooks || !_hookSupervisor) return { rewakes: [], results: [] };
|
|
1050
|
+
const { dispatchAsyncHooks } =
|
|
1051
|
+
await import("../lib/settings-hook-events.cjs");
|
|
1052
|
+
dispatchAsyncHooks(
|
|
1053
|
+
settingsHooks,
|
|
1054
|
+
"Stop",
|
|
1055
|
+
{ reason: endReason, cwd, session_id: sessionId },
|
|
1056
|
+
{ cwd, supervisor: _hookSupervisor },
|
|
1057
|
+
);
|
|
1058
|
+
const waitMs = Number.isFinite(options.asyncHookWaitMs)
|
|
1059
|
+
? options.asyncHookWaitMs
|
|
1060
|
+
: 5000;
|
|
1061
|
+
const started = Date.now();
|
|
1062
|
+
while (
|
|
1063
|
+
_hookSupervisor.runningCount() > 0 &&
|
|
1064
|
+
Date.now() - started < waitMs
|
|
1065
|
+
) {
|
|
1066
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
1067
|
+
}
|
|
1068
|
+
return {
|
|
1069
|
+
rewakes: _hookSupervisor.drainRewakes(),
|
|
1070
|
+
results: _hookSupervisor.drainResults(),
|
|
1071
|
+
};
|
|
1072
|
+
};
|
|
1073
|
+
|
|
953
1074
|
try {
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
const err = event.error || event.result?.error || null;
|
|
975
|
-
if (isText && err) writeErr(` Error: ${err}\n`);
|
|
976
|
-
emitStream({
|
|
977
|
-
type: "tool_result",
|
|
978
|
-
tool: event.tool,
|
|
979
|
-
is_error: Boolean(err),
|
|
980
|
-
error: err,
|
|
981
|
-
result: event.result,
|
|
982
|
-
});
|
|
983
|
-
if (toolCalls.length > 0) {
|
|
984
|
-
toolCalls[toolCalls.length - 1].is_error = Boolean(err);
|
|
1075
|
+
// eslint-disable-next-line no-constant-condition
|
|
1076
|
+
while (true) {
|
|
1077
|
+
for await (const event of runLoop(messages, loopOptions)) {
|
|
1078
|
+
switch (event.type) {
|
|
1079
|
+
case "checkpoint": {
|
|
1080
|
+
if (isText)
|
|
1081
|
+
writeErr(` ⎌ checkpoint ${event.id} (before ${event.tool})\n`);
|
|
1082
|
+
emitStream({ type: "checkpoint", id: event.id, tool: event.tool });
|
|
1083
|
+
break;
|
|
1084
|
+
}
|
|
1085
|
+
case "tool-executing": {
|
|
1086
|
+
const line = ` [${event.tool}] ${formatToolArgs(event.tool, event.args)}`;
|
|
1087
|
+
if (isText) writeErr(line + "\n");
|
|
1088
|
+
emitStream({
|
|
1089
|
+
type: "tool_use",
|
|
1090
|
+
tool: event.tool,
|
|
1091
|
+
args: event.args,
|
|
1092
|
+
});
|
|
1093
|
+
toolCalls.push({ tool: event.tool, args: event.args });
|
|
1094
|
+
break;
|
|
985
1095
|
}
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
1096
|
+
case "tool-result": {
|
|
1097
|
+
const err = event.error || event.result?.error || null;
|
|
1098
|
+
if (isText && err) writeErr(` Error: ${err}\n`);
|
|
1099
|
+
emitStream({
|
|
1100
|
+
type: "tool_result",
|
|
991
1101
|
tool: event.tool,
|
|
1102
|
+
is_error: Boolean(err),
|
|
1103
|
+
error: err,
|
|
992
1104
|
result: event.result,
|
|
993
|
-
error: event.error,
|
|
994
|
-
argsSummary:
|
|
995
|
-
last && last.tool === event.tool
|
|
996
|
-
? formatToolArgs(event.tool, last.args)
|
|
997
|
-
: "",
|
|
998
1105
|
});
|
|
999
|
-
if (
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1106
|
+
if (toolCalls.length > 0) {
|
|
1107
|
+
toolCalls[toolCalls.length - 1].is_error = Boolean(err);
|
|
1108
|
+
}
|
|
1109
|
+
// Track policy denials (not plain tool failures) for the end-of-run
|
|
1110
|
+
// summary. The preceding tool-executing pushed the args.
|
|
1111
|
+
if (err) {
|
|
1112
|
+
const last = toolCalls[toolCalls.length - 1];
|
|
1113
|
+
const denial = classifyDenial({
|
|
1114
|
+
tool: event.tool,
|
|
1115
|
+
result: event.result,
|
|
1116
|
+
error: event.error,
|
|
1117
|
+
argsSummary:
|
|
1118
|
+
last && last.tool === event.tool
|
|
1119
|
+
? formatToolArgs(event.tool, last.args)
|
|
1120
|
+
: "",
|
|
1003
1121
|
});
|
|
1122
|
+
if (denial) {
|
|
1123
|
+
recordDenial(denials, {
|
|
1124
|
+
...denial,
|
|
1125
|
+
at: deps.now ? deps.now() : Date.now(),
|
|
1126
|
+
});
|
|
1127
|
+
}
|
|
1004
1128
|
}
|
|
1129
|
+
break;
|
|
1005
1130
|
}
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
model: event.model,
|
|
1021
|
-
usage: event.usage,
|
|
1022
|
-
});
|
|
1023
|
-
if (costBudget.shouldWarnInactive()) {
|
|
1024
|
-
const m = `cost cap $${options.maxCostUsd} set but model "${event.model}" is unpriced/free — cap inactive`;
|
|
1025
|
-
if (isText) writeErr(` ${m}\n`);
|
|
1026
|
-
emitStream({ type: "cost_warning", message: m });
|
|
1027
|
-
}
|
|
1028
|
-
if (costBudget.exceeded()) {
|
|
1029
|
-
endReason = "cost-budget-exhausted";
|
|
1030
|
-
stopForCost = true;
|
|
1031
|
-
if (isText)
|
|
1032
|
-
writeErr(
|
|
1033
|
-
` ⛔ cost budget $${options.maxCostUsd} reached (spent ≈$${costBudget.spentUsd}) — stopping\n`,
|
|
1034
|
-
);
|
|
1035
|
-
emitStream({
|
|
1036
|
-
type: "cost_budget_exhausted",
|
|
1037
|
-
limit_usd: options.maxCostUsd,
|
|
1038
|
-
spent_usd: costBudget.spentUsd,
|
|
1131
|
+
case "token-usage": {
|
|
1132
|
+
usage.input_tokens += event.usage?.input_tokens || 0;
|
|
1133
|
+
usage.output_tokens += event.usage?.output_tokens || 0;
|
|
1134
|
+
// Carry prompt-cache tokens into accumulated usage (cost accuracy).
|
|
1135
|
+
usage.cache_read_input_tokens +=
|
|
1136
|
+
event.usage?.cache_read_input_tokens || 0;
|
|
1137
|
+
usage.cache_creation_input_tokens +=
|
|
1138
|
+
event.usage?.cache_creation_input_tokens || 0;
|
|
1139
|
+
emitStream({ type: "token_usage", usage: event.usage });
|
|
1140
|
+
if (costBudget) {
|
|
1141
|
+
costBudget.add({
|
|
1142
|
+
provider: event.provider,
|
|
1143
|
+
model: event.model,
|
|
1144
|
+
usage: event.usage,
|
|
1039
1145
|
});
|
|
1146
|
+
if (costBudget.shouldWarnInactive()) {
|
|
1147
|
+
const m = `cost cap $${options.maxCostUsd} set but model "${event.model}" is unpriced/free — cap inactive`;
|
|
1148
|
+
if (isText) writeErr(` ${m}\n`);
|
|
1149
|
+
emitStream({ type: "cost_warning", message: m });
|
|
1150
|
+
}
|
|
1151
|
+
if (costBudget.exceeded()) {
|
|
1152
|
+
endReason = "cost-budget-exhausted";
|
|
1153
|
+
stopForCost = true;
|
|
1154
|
+
if (isText)
|
|
1155
|
+
writeErr(
|
|
1156
|
+
` ⛔ cost budget $${options.maxCostUsd} reached (spent ≈$${costBudget.spentUsd}) — stopping\n`,
|
|
1157
|
+
);
|
|
1158
|
+
emitStream({
|
|
1159
|
+
type: "cost_budget_exhausted",
|
|
1160
|
+
limit_usd: options.maxCostUsd,
|
|
1161
|
+
spent_usd: costBudget.spentUsd,
|
|
1162
|
+
});
|
|
1163
|
+
}
|
|
1040
1164
|
}
|
|
1165
|
+
break;
|
|
1041
1166
|
}
|
|
1042
|
-
|
|
1167
|
+
case "iteration-warning": {
|
|
1168
|
+
if (isText) writeErr(` ${event.message}\n`);
|
|
1169
|
+
emitStream({ type: "iteration_warning", message: event.message });
|
|
1170
|
+
break;
|
|
1171
|
+
}
|
|
1172
|
+
case "iteration-budget-exhausted": {
|
|
1173
|
+
endReason = "max_turns";
|
|
1174
|
+
emitStream({
|
|
1175
|
+
type: "iteration_budget_exhausted",
|
|
1176
|
+
budget: event.budget,
|
|
1177
|
+
});
|
|
1178
|
+
break;
|
|
1179
|
+
}
|
|
1180
|
+
case "response-complete": {
|
|
1181
|
+
finalText = event.content || "";
|
|
1182
|
+
break;
|
|
1183
|
+
}
|
|
1184
|
+
case "run-ended": {
|
|
1185
|
+
if (event.reason) endReason = event.reason;
|
|
1186
|
+
break;
|
|
1187
|
+
}
|
|
1188
|
+
default:
|
|
1189
|
+
// slot-filling, run-started, etc. — surfaced only in stream mode.
|
|
1190
|
+
if (isStream && event.type) emitStream(event);
|
|
1191
|
+
break;
|
|
1043
1192
|
}
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1193
|
+
// Hard cost cap reached: stop consuming the loop so no further paid LLM
|
|
1194
|
+
// call is made (break out of the for-await, not just the switch).
|
|
1195
|
+
if (stopForCost) break;
|
|
1196
|
+
}
|
|
1197
|
+
// ── auto-rewake re-drive (opt-in via --auto-rewake) ─────────────────
|
|
1198
|
+
// Under auto-rewake, settle the async Stop hooks after EVERY turn (so the
|
|
1199
|
+
// final turn's background check still runs). If an asyncRewake check
|
|
1200
|
+
// failed and re-drive budget remains, append its report as a new user
|
|
1201
|
+
// turn and loop; if a rewake failed but budget is spent, surface it and
|
|
1202
|
+
// stop. When auto-rewake is off, this whole block is skipped and the
|
|
1203
|
+
// `finally` handles Stop exactly as before (default behavior unchanged).
|
|
1204
|
+
if (
|
|
1205
|
+
autoRewake &&
|
|
1206
|
+
_hookSupervisor &&
|
|
1207
|
+
!stopForCost &&
|
|
1208
|
+
endReason !== "max_turns" &&
|
|
1209
|
+
endReason !== "cost-budget-exhausted"
|
|
1210
|
+
) {
|
|
1211
|
+
const { rewakes, results } = await _settleAsyncStop();
|
|
1212
|
+
_asyncStopHandled = true;
|
|
1213
|
+
for (const rs of results) {
|
|
1214
|
+
if (rs.additionalContext)
|
|
1215
|
+
writeErr(`[async-hook] ${rs.command}: ${rs.additionalContext}\n`);
|
|
1048
1216
|
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1217
|
+
if (rewakes.length > 0 && rewakeBudget > 0) {
|
|
1218
|
+
rewakeBudget--;
|
|
1219
|
+
const detail = rewakes
|
|
1220
|
+
.map(
|
|
1221
|
+
(rw) =>
|
|
1222
|
+
`- ${rw.command} failed` +
|
|
1223
|
+
`${rw.exitCode != null ? ` (exit ${rw.exitCode})` : ""}` +
|
|
1224
|
+
`${rw.error ? `: ${rw.error}` : ""}`,
|
|
1225
|
+
)
|
|
1226
|
+
.join("\n");
|
|
1227
|
+
messages.push({
|
|
1228
|
+
role: "user",
|
|
1229
|
+
content:
|
|
1230
|
+
`A background check flagged a problem after your last turn:\n${detail}\n` +
|
|
1231
|
+
`Investigate and fix it, then confirm it passes.`,
|
|
1054
1232
|
});
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1233
|
+
if (isText)
|
|
1234
|
+
writeErr(
|
|
1235
|
+
` ↻ async-hook rewake — re-engaging agent (${rewakeBudget} re-drive(s) left)\n`,
|
|
1236
|
+
);
|
|
1237
|
+
emitStream({ type: "rewake", remaining: rewakeBudget });
|
|
1238
|
+
finalText = "";
|
|
1239
|
+
endReason = "complete";
|
|
1240
|
+
continue; // re-drive: run another agent turn
|
|
1060
1241
|
}
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1242
|
+
// A rewake fired but no budget remains — surface it (couldn't auto-fix).
|
|
1243
|
+
for (const rw of rewakes) {
|
|
1244
|
+
writeErr(
|
|
1245
|
+
`[async-hook REWAKE] ${rw.command} failed` +
|
|
1246
|
+
`${rw.exitCode != null ? ` (exit ${rw.exitCode})` : ""}` +
|
|
1247
|
+
`${rw.error ? `: ${rw.error}` : ""}\n`,
|
|
1248
|
+
);
|
|
1064
1249
|
}
|
|
1065
|
-
default:
|
|
1066
|
-
// slot-filling, run-started, etc. — surfaced only in stream mode.
|
|
1067
|
-
if (isStream && event.type) emitStream(event);
|
|
1068
|
-
break;
|
|
1069
1250
|
}
|
|
1070
|
-
|
|
1071
|
-
// call is made (break out of the for-await, not just the switch).
|
|
1072
|
-
if (stopForCost) break;
|
|
1251
|
+
break;
|
|
1073
1252
|
}
|
|
1074
1253
|
} catch (err) {
|
|
1075
1254
|
const message = err?.message || String(err);
|
|
@@ -1118,11 +1297,56 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
1118
1297
|
} catch {
|
|
1119
1298
|
// best-effort — never mask the run's own outcome
|
|
1120
1299
|
}
|
|
1121
|
-
// settings.json SessionEnd hooks
|
|
1300
|
+
// settings.json Stop + SessionEnd hooks when the run finishes. Stop is the
|
|
1301
|
+
// canonical async-hook trigger ("run the test suite at turn end"); fire its
|
|
1302
|
+
// async hooks fire-and-forget, then settle so a fast background check can
|
|
1303
|
+
// report back within this one-shot run.
|
|
1122
1304
|
if (settingsHooks) {
|
|
1123
1305
|
try {
|
|
1124
|
-
const { runObserveHooks } =
|
|
1306
|
+
const { runObserveHooks, dispatchAsyncHooks } =
|
|
1125
1307
|
await import("../lib/settings-hook-events.cjs");
|
|
1308
|
+
const stopPayload = { reason: endReason, cwd, session_id: sessionId };
|
|
1309
|
+
runObserveHooks(settingsHooks, "Stop", stopPayload, { cwd });
|
|
1310
|
+
// Skip the async Stop dispatch/settle here if the auto-rewake re-drive
|
|
1311
|
+
// loop already fired + drained it this run (avoids double-execution).
|
|
1312
|
+
if (_hookSupervisor && !_asyncStopHandled) {
|
|
1313
|
+
dispatchAsyncHooks(settingsHooks, "Stop", stopPayload, {
|
|
1314
|
+
cwd,
|
|
1315
|
+
supervisor: _hookSupervisor,
|
|
1316
|
+
});
|
|
1317
|
+
// Bounded settle: wait for in-flight async hooks (Stop + any
|
|
1318
|
+
// PostToolUse dispatched during the loop) to finish, capped so a
|
|
1319
|
+
// slow/hung check can never stall the run. Default 5s; tunable.
|
|
1320
|
+
const waitMs = Number.isFinite(options.asyncHookWaitMs)
|
|
1321
|
+
? options.asyncHookWaitMs
|
|
1322
|
+
: 5000;
|
|
1323
|
+
const started = Date.now();
|
|
1324
|
+
while (
|
|
1325
|
+
_hookSupervisor.runningCount() > 0 &&
|
|
1326
|
+
Date.now() - started < waitMs
|
|
1327
|
+
) {
|
|
1328
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
1329
|
+
}
|
|
1330
|
+
// Surface any results/rewakes out-of-band on stderr (never touches the
|
|
1331
|
+
// stdout envelope). A rewake means a background check FAILED and would
|
|
1332
|
+
// re-engage the agent in an interactive session — flag it clearly so a
|
|
1333
|
+
// headless caller/CI can react.
|
|
1334
|
+
for (const rw of _hookSupervisor.drainRewakes()) {
|
|
1335
|
+
writeErr(
|
|
1336
|
+
`[async-hook REWAKE] ${rw.command} failed` +
|
|
1337
|
+
`${rw.exitCode != null ? ` (exit ${rw.exitCode})` : ""}` +
|
|
1338
|
+
`${rw.error ? `: ${rw.error}` : ""}\n`,
|
|
1339
|
+
);
|
|
1340
|
+
}
|
|
1341
|
+
for (const rs of _hookSupervisor.drainResults()) {
|
|
1342
|
+
if (rs.additionalContext) {
|
|
1343
|
+
writeErr(`[async-hook] ${rs.command}: ${rs.additionalContext}\n`);
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
// Always reap the supervisor (kills any straggler child + detaches the
|
|
1348
|
+
// exit reaper), whether the async Stop was handled here or in re-drive.
|
|
1349
|
+
if (_hookSupervisor) _hookSupervisor.stopAll();
|
|
1126
1350
|
runObserveHooks(
|
|
1127
1351
|
settingsHooks,
|
|
1128
1352
|
"SessionEnd",
|
|
@@ -1130,7 +1354,7 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
1130
1354
|
{ cwd },
|
|
1131
1355
|
);
|
|
1132
1356
|
} catch {
|
|
1133
|
-
// observe-only
|
|
1357
|
+
// observe-only + best-effort async surfacing
|
|
1134
1358
|
}
|
|
1135
1359
|
}
|
|
1136
1360
|
}
|
|
@@ -1259,6 +1483,27 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
1259
1483
|
writeOut(finalText + (finalText.endsWith("\n") ? "" : "\n"));
|
|
1260
1484
|
}
|
|
1261
1485
|
|
|
1486
|
+
// --otlp: write the captured spans/counters as OTLP/JSON. Best-effort — a
|
|
1487
|
+
// write failure logs to stderr but never changes the run's exit code.
|
|
1488
|
+
if (_otlpRecorder && options.otlp) {
|
|
1489
|
+
try {
|
|
1490
|
+
const fsp = await import("node:fs");
|
|
1491
|
+
fsp.writeFileSync(
|
|
1492
|
+
options.otlp,
|
|
1493
|
+
JSON.stringify(_otlpRecorder.toOtlp(), null, 2),
|
|
1494
|
+
"utf-8",
|
|
1495
|
+
);
|
|
1496
|
+
if (!isStream) {
|
|
1497
|
+
const sum = _otlpRecorder.summary();
|
|
1498
|
+
process.stderr.write(
|
|
1499
|
+
`[otlp] ${sum.spanCount} span(s) → ${options.otlp}\n`,
|
|
1500
|
+
);
|
|
1501
|
+
}
|
|
1502
|
+
} catch (err) {
|
|
1503
|
+
process.stderr.write(`[otlp] export failed: ${err.message}\n`);
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1262
1507
|
return { exitCode: isError ? 1 : 0, result: finalText, isError };
|
|
1263
1508
|
}
|
|
1264
1509
|
|
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
jetbrainsServerToMcpConfig,
|
|
34
34
|
isInJetbrainsContext,
|
|
35
35
|
} from "../lib/jetbrains-bridge.js";
|
|
36
|
+
import { collectPluginMcpServers } from "../lib/plugin-runtime/mcp.js";
|
|
36
37
|
|
|
37
38
|
/**
|
|
38
39
|
* Normalize a parsed config object into a `{ name: serverConfig }` map.
|
|
@@ -644,6 +645,39 @@ export async function loadProjectMcp(opts = {}, deps = {}) {
|
|
|
644
645
|
return setupMcpFromConfig(servers, deps);
|
|
645
646
|
}
|
|
646
647
|
|
|
648
|
+
/**
|
|
649
|
+
* Load MCP servers declared by installed plugins' `.mcp.json` (Phase 3.3g —
|
|
650
|
+
* plugin MCP component reaches the agent's tool surface).
|
|
651
|
+
*
|
|
652
|
+
* Unlike a project `.mcp.json` (opt-in via --project-mcp because ANY cloned repo
|
|
653
|
+
* can carry one), plugin MCP servers load by default: installing AND trusting a
|
|
654
|
+
* plugin IS the explicit user action. `collectPluginMcpServers` already trust-
|
|
655
|
+
* gates — only user/local-scope plugins and `cc plugin trust`-ed project plugins
|
|
656
|
+
* contribute — so a server never spawns from an untrusted cloned-repo plugin.
|
|
657
|
+
*
|
|
658
|
+
* Chains onto `deps.into` after the registered + project servers, so those win
|
|
659
|
+
* on a name clash (the plugin ADDS servers without overriding the user's own).
|
|
660
|
+
*
|
|
661
|
+
* @param {object} opts { cwd, scopes }
|
|
662
|
+
* @param {object} [deps] { collect, writeErr, into, ... setupMcpFromConfig deps }
|
|
663
|
+
*/
|
|
664
|
+
export async function loadPluginMcp(opts = {}, deps = {}) {
|
|
665
|
+
const collect = deps.collect || collectPluginMcpServers;
|
|
666
|
+
const writeErr = deps.writeErr || (() => {});
|
|
667
|
+
let servers = {};
|
|
668
|
+
try {
|
|
669
|
+
({ servers } = collect({ cwd: opts.cwd, scopes: opts.scopes }));
|
|
670
|
+
} catch {
|
|
671
|
+
return deps.into || null;
|
|
672
|
+
}
|
|
673
|
+
const names = Object.keys(servers || {});
|
|
674
|
+
if (names.length === 0) return deps.into || null;
|
|
675
|
+
writeErr(
|
|
676
|
+
` mcp: ${names.length} server(s) from trusted plugin(s): ${names.join(", ")}\n`,
|
|
677
|
+
);
|
|
678
|
+
return setupMcpFromConfig(servers, deps);
|
|
679
|
+
}
|
|
680
|
+
|
|
647
681
|
/**
|
|
648
682
|
* Resolve the full MCP tool surface for one agent run: the ad-hoc
|
|
649
683
|
* `--mcp-config` file (if any) PLUS registered auto-connect servers (unless
|
|
@@ -665,6 +699,7 @@ export async function resolveAgentMcp(args = {}, deps = {}) {
|
|
|
665
699
|
const doFile = deps.loadMcpConfig || loadMcpConfig;
|
|
666
700
|
const doReg = deps.loadRegisteredMcp || loadRegisteredMcp;
|
|
667
701
|
const doProject = deps.loadProjectMcp || loadProjectMcp;
|
|
702
|
+
const doPlugin = deps.loadPluginMcp || loadPluginMcp;
|
|
668
703
|
const doIde = deps.loadIdeMcp || loadIdeMcp;
|
|
669
704
|
const doPdh = deps.loadPdhMcp || loadPdhMcp;
|
|
670
705
|
const doJetbrains = deps.loadJetbrainsMcp || loadJetbrainsMcp;
|
|
@@ -712,6 +747,17 @@ export async function resolveAgentMcp(args = {}, deps = {}) {
|
|
|
712
747
|
{ ...fwd, into: result || undefined },
|
|
713
748
|
);
|
|
714
749
|
}
|
|
750
|
+
// Installed-plugin `.mcp.json` servers (Claude-Code parity). Loads by default
|
|
751
|
+
// (no opt-in flag): unlike a project `.mcp.json`, a plugin only contributes
|
|
752
|
+
// when it is installed AND trusted (trust-gated inside collectPluginMcpServers)
|
|
753
|
+
// — that install+trust IS the explicit consent. Registered + project servers
|
|
754
|
+
// above win on a name clash. `pluginMcp:false` hard-skips it.
|
|
755
|
+
if (args.pluginMcp !== false) {
|
|
756
|
+
result = await doPlugin(
|
|
757
|
+
{ cwd: args.cwd, scopes: args.pluginScopes },
|
|
758
|
+
{ ...fwd, into: result || undefined },
|
|
759
|
+
);
|
|
760
|
+
}
|
|
715
761
|
if (args.ide !== false) {
|
|
716
762
|
const env = args.env || process.env;
|
|
717
763
|
const inIde = (deps.isInIdeTerminal || isInIdeTerminal)(env);
|
|
@@ -26,6 +26,8 @@ export function resolveAgentPolicy({
|
|
|
26
26
|
noStream: overrides.noStream === true,
|
|
27
27
|
parkOnExit: overrides.parkOnExit === false ? false : true,
|
|
28
28
|
bundlePath: overrides.bundlePath || null,
|
|
29
|
+
remoteSessionRelayUrl: overrides.remoteSessionRelayUrl || null,
|
|
30
|
+
remoteSessionPeerId: overrides.remoteSessionPeerId || null,
|
|
29
31
|
additionalDirectories: Array.isArray(overrides.additionalDirectories)
|
|
30
32
|
? overrides.additionalDirectories
|
|
31
33
|
: [],
|