chainlesschain 0.162.180 → 0.162.182
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 +7 -3
- package/scripts/build-windows-sandbox-helper.ps1 +163 -0
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-D_TIL54O.js → AIOps-DzZ5_xoj.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-eQwy9r-f.js → ActionButton-DeLXddIg.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-D2eNuDgT.js → Analytics-rvDCmet1.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-CFhwOFsf.js → AppLayout-Yt6QVDnp.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-CJUMw6PB.js → Artifacts-BS112K5L.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CDB9V58o.js → Audit-0wJuQrNu.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-TBppYFjN.js → BackgroundAgents-B90PMgbn.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CYEOUpzJ.js → Backup-TkgMglQQ.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-C88fFT2u.js → BaseInput-CQVS9p1l.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-mkr1vC3N.js → Chat-YTjQHoC7.js} +6 -6
- package/src/assets/web-panel/assets/ChatBubbleRenderer-PR074hUN.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-CVU4xqti.js → Checkbox-5bwaOabq.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-rrNcByz3.js → Codegen-BFmNQ_Xe.js} +1 -1
- package/src/assets/web-panel/assets/{Col-Cqu-zCvh.js → Col-BT_u4Dzp.js} +1 -1
- package/src/assets/web-panel/assets/{Community-RGRlSgXV.js → Community-CJP52u5b.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DBm6epOK.js → Compact-BpzhJE9i.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-BgKw5iaW.js → Compliance-Cg7rfslp.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-BqQcNO3Z.js → Cowork-JisxL6Yy.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-DO5gTFNb.js → Cron-Bu7Ug_MC.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-B8hbJNuN.js → Crosschain-CvuqoLdj.js} +1 -1
- package/src/assets/web-panel/assets/{DID-B08bFJ2C.js → DID-C2u9G8Pu.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-xNdy_ifo.js → Dashboard-BFt5Yv3d.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-D-KIZgWL.js → Dropdown-DIaT9Wxq.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DKCvsaGo.js → EmailListRenderer-D_A601Y4.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-D_cfqama.js → FamilyGuardDashboard--IyQ8I8w.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-B-UqQD68.js → Federation-BihWHxuY.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-BWWvWuJW.js → FormItemContext-BB8dOXc_.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-CPchx6N7.js → GenericCardRenderer-DQYhj1HH.js} +1 -1
- package/src/assets/web-panel/assets/{Git-Vx4co9Ff.js → Git-B-2QZxGf.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-D4x0pp_m.js → Governance-CusSb-nG.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-T3KvwPYR.js → Inference-BAjmvPPL.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-Ddv3KUv3.js → KnowledgeGraph-DoNYWKYq.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-DfH-Dkae.js → Logs-B8fKWD-n.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-DHW3PbCq.js → MarkdownRenderer-BlJm1J7E.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-tjgb0R3D.js → Marketplace-CyOscbSL.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DHAk5nYX.js → McpTools-Ex6Om5da.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-A2Yx7thM.js → Memory-CDcD8l8r.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BEmTVfN5.js → MobileBridge-xfBqoFDg.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-DuFHUgE4.js → MobileProjects-BwObMMA2.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-BDSll0OZ.js → Mtc-CIWd36OV.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-CuBvluaS.js → MtcAudit-CPX0ouuA.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-BmXAA-Sb.js → Multisig-BDJsIUuW.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-ci2stZAe.js → NLProgramming-DEkbuD3N.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-D-1RpqnS.js → Notes-DJpHRhH1.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-C0GyitIT.js → NotificationSettings-C1UZ-Qd5.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-U2bN-hj5.js → OrderTableRenderer-GlJtqLjT.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BNZgpPci.js → Organization-Bbhj0fac.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-CDidKmUN.js → Overflow-1H04x3kx.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BnreBaXq.js → P2P-CDpPe3et.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-DwJUxO9j.js → PdhVaultBrowser-MUX0Bpvw.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-BQGgJPH0.js → Permissions-A07-0Ci1.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-k_fSkCwL.js → PersonalDataHub-DhhDWxAZ.js} +5 -5
- package/src/assets/web-panel/assets/{Pipeline-WGqKMqau.js → Pipeline-CyfbJfe-.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DtHj9Ymq.js → Privacy-CNFps3ED.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-B3wH2SFC.js → ProjectInit--T-u3Dr5.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-Cd0cgcA1.js → ProjectSettings-DJmrK2fC.js} +2 -2
- package/src/assets/web-panel/assets/Projects-Qx_MdX9k.js +1 -0
- package/src/assets/web-panel/assets/{Providers-DTpxEXur.js → Providers-DLzzbOZd.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-B2v6gR-C.js → QrScannerModal-CexOomKS.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-D3Nr9xXR.js → QuickAsk-QklGi19_.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-C9inoMky.js → Recommend-Bb9kwSw8.js} +1 -1
- package/src/assets/web-panel/assets/RemoteSession-DZuVNNN5.js +5 -0
- package/src/assets/web-panel/assets/{Reputation-41KFG646.js → Reputation-Dr5cLP0N.js} +1 -1
- package/src/assets/web-panel/assets/{Row-DqAaqqCv.js → Row-oCQHYv5t.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CMDpCDKc.js → RssFeed-IFDEykIR.js} +3 -3
- package/src/assets/web-panel/assets/{Search-B6mtegNL.js → Search-CspVIxDc.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BaePFVZ8.js → Security-Bm66o_DH.js} +3 -3
- package/src/assets/web-panel/assets/{Services-DeG3Qscl.js → Services-DvanNqXl.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-D_QP7F90.js → Skeleton-CHjEe9_O.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-DLGyUgIA.js → Skills-Cb8jWjMX.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-BN2pxW1Q.js → Sla-DxZm1491.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-BWsZPd8B.js → SpeechSettings-DWxEEclC.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-VOZRPODW.js → SyncSettings-FIvOFw5p.js} +2 -2
- package/src/assets/web-panel/assets/Tasks-CyuLnDFR.js +1 -0
- package/src/assets/web-panel/assets/{Templates-eJSob-q0.js → Templates-CaNjzV_t.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-Bdwk8Rwy.js → Tenant-DjlP6TmH.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-DwzGMniO.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-D5qkbPKT.js → TimelineRenderer-DoZ8y7y8.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DKgwn8hI.js → Tokens-390cg2TC.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-HlEHniGM.js → Trigger-CLrtCj5_.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CdPcsBpN.js → Trust-DpESfSPn.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-vAdXd-vG.js → UkeySign-CN6279O0.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-9hHBYFnH.js → VideoEditing-DPtAUlSe.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-Dxh5d1yR.js → Wallet-nKOMV_1n.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-BsFmLHkp.js → WebAuthn-HuXlSOc4.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-Cn0OIwLn.js → WorkflowEditor-CUfFjARi.js} +1 -1
- package/src/assets/web-panel/assets/chat-6Eq0PcZJ.js +1 -0
- package/src/assets/web-panel/assets/{colors-Du9jzLN0.js → colors-BP_Sf6Iy.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-DhEscfzw.js → compact-item-BufMKIh5.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-CwzEfF3i.js → createContext-BBMXxWSW.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DgVKduH2.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DT_GSE6J.js → hasIn-fUK_tRO2.js} +1 -1
- package/src/assets/web-panel/assets/{index-tND8-TDU.js → index-2A5ph8b2.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8s5FxJY.js → index-3FuwBewR.js} +1 -1
- package/src/assets/web-panel/assets/{index-53z1YUxX.js → index-6GmBa4Kg.js} +1 -1
- package/src/assets/web-panel/assets/{index-BFD0cEna.js → index-B2vS66eI.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQWxDOvM.js → index-B7Etk0Te.js} +1 -1
- package/src/assets/web-panel/assets/{index-VeHs6qH0.js → index-B9WYSn4m.js} +1 -1
- package/src/assets/web-panel/assets/{index-CGvgnfl9.js → index-BHy6yNiF.js} +1 -1
- package/src/assets/web-panel/assets/{index-D3llLkYM.js → index-BMLHv389.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dny_ZnAO.js → index-BWKoBU8R.js} +1 -1
- package/src/assets/web-panel/assets/{index-DzjzrOli.js → index-Bkg4ZePE.js} +1 -1
- package/src/assets/web-panel/assets/{index-DN60VBn5.js → index-C44atv4k.js} +1 -1
- package/src/assets/web-panel/assets/{index-v5HLYCVa.js → index-CE2DdTP2.js} +1 -1
- package/src/assets/web-panel/assets/{index-BF-ZCVGE.js → index-CGjmILDm.js} +1 -1
- package/src/assets/web-panel/assets/{index-gFjYdstW.js → index-CW_G-MXw.js} +1 -1
- package/src/assets/web-panel/assets/{index-NA2oBLSB.js → index-CZ6Yt17L.js} +1 -1
- package/src/assets/web-panel/assets/{index-Mobw3PHs.js → index-CeASi4fr.js} +1 -1
- package/src/assets/web-panel/assets/{index-DWL3SYN3.js → index-CgiECHu2.js} +1 -1
- package/src/assets/web-panel/assets/{index-1LoutPJd.js → index-Cp8vhyZy.js} +1 -1
- package/src/assets/web-panel/assets/{index-BnHhFnwt.js → index-CwSf5pnf.js} +1 -1
- package/src/assets/web-panel/assets/{index-B6QDWRLk.js → index-D4_MuGkd.js} +1 -1
- package/src/assets/web-panel/assets/{index-D-QkW1fp.js → index-D9vU25ij.js} +1 -1
- package/src/assets/web-panel/assets/{index-C4SN3by5.js → index-DASluSqY.js} +1 -1
- package/src/assets/web-panel/assets/{index-CyEhUJcu.js → index-DLpIs_P_.js} +1 -1
- package/src/assets/web-panel/assets/index-DOZTSoS7.js +1 -0
- package/src/assets/web-panel/assets/{index-BrkJ7JPm.js → index-DPdUNk1i.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cnok8mhZ.js → index-DVsqvI4M.js} +1 -1
- package/src/assets/web-panel/assets/index-DhpvjpqI.js +1 -0
- package/src/assets/web-panel/assets/{index-CAVW0cWM.js → index-DmkMXwnR.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cc9aPkv-.js → index-DocdRcbd.js} +1 -1
- package/src/assets/web-panel/assets/{index-DnVVYKCE.js → index-Dyngbd29.js} +20 -20
- package/src/assets/web-panel/assets/{index-D8gt0j7r.js → index-GwdRUZ-x.js} +1 -1
- package/src/assets/web-panel/assets/{index-BIYTjbv_.js → index-LvCBfTLo.js} +1 -1
- package/src/assets/web-panel/assets/{index-DhXay17G.js → index-cpEli44X.js} +1 -1
- package/src/assets/web-panel/assets/{index-BQWENaZf.js → index-fzaMtSJ8.js} +1 -1
- package/src/assets/web-panel/assets/{index-DfRDyY1q.js → index-pum7HYBA.js} +1 -1
- package/src/assets/web-panel/assets/{index-BgSR2WMG.js → index-t8N1tSeX.js} +1 -1
- package/src/assets/web-panel/assets/{index-D5IytTND.js → index-uCbEN7cY.js} +1 -1
- package/src/assets/web-panel/assets/{index-DtRwLhee.js → index-wKTLbKyc.js} +1 -1
- package/src/assets/web-panel/assets/{index-D4kZoXNr.js → index-wV6iGdpY.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-Cvt59c10.js → initDefaultProps-V5Fo95FM.js} +1 -1
- package/src/assets/web-panel/assets/{motion-D15pPEzl.js → motion-BYWU0hUT.js} +1 -1
- package/src/assets/web-panel/assets/{move-N55KeXJ7.js → move-Cr1M-J2h.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-CyFO1bYP.js → mtc-parser-BysQKi2N.js} +1 -1
- package/src/assets/web-panel/assets/{omit-B5IXfxU2.js → omit-D1zHU8GC.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-CpVqsulV.js → pickAttrs-CUArxtfi.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-ME36sMF3.js → placementArrow-ChoYEys0.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BXAIR1r-.js → responsiveObserve-BQRs3Mo7.js} +1 -1
- package/src/assets/web-panel/assets/{slide-BkOX3-Dp.js → slide-B8zbsCkg.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-Cy4Aklpt.js → statusUtils-C2U8Gs6h.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-gUd2T206.js → styleChecker-Dd8MgL_V.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-CaVD4o99.js → useFlexGapSupport-hknqY5NH.js} +1 -1
- package/src/assets/web-panel/assets/{useFs--pFGl0KD.js → useFs-CLTAmcfw.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-D45iP86i.js → usePersonalDataHub-ByegHbiB.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BayoChH_.js → vnode-DqlAy5DP.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-CpP38poi.js → zoom-DiXiztQn.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agenda.js +115 -3
- package/src/commands/agent.js +10 -1
- package/src/commands/background-session.js +2 -1
- package/src/commands/context.js +69 -2
- package/src/data/changelog.json +26 -0
- package/src/gateways/terminal/PtyManager.js +45 -4
- package/src/gateways/ws/background-agent-protocol.js +38 -0
- package/src/gateways/ws/message-dispatcher.js +1 -0
- package/src/gateways/ws/remote-session-protocol.js +65 -6
- package/src/gateways/ws/ws-server.js +18 -2
- package/src/harness/background-task-manager.js +70 -2
- package/src/harness/feature-flags.js +15 -8
- package/src/harness/mcp-client.js +618 -43
- package/src/harness/worktree-isolator.js +14 -3
- package/src/lazy-dispatch.js +30 -1
- package/src/lib/agent-authority.js +22 -0
- package/src/lib/agent-core.js +3 -0
- package/src/lib/agent-sandbox.js +161 -0
- package/src/lib/agent-schedule-store.js +45 -22
- package/src/lib/agent-team/team-runner.js +22 -0
- package/src/lib/artifact-store.js +35 -0
- package/src/lib/async-hook-supervisor.cjs +13 -2
- package/src/lib/audit-mtc.js +3 -2
- package/src/lib/background-agent-supervisor.js +104 -3
- package/src/lib/background-interaction-journal.js +407 -0
- package/src/lib/background-interaction-resolver.js +23 -34
- package/src/lib/background-session-transport.js +12 -2
- package/src/lib/capability-manifest.js +41 -3
- package/src/lib/capability-negotiation.js +1 -1
- package/src/lib/channels/channel-manager.js +33 -0
- package/src/lib/channels/telegram-channel.js +23 -5
- package/src/lib/channels/webhook-channel.js +38 -15
- package/src/lib/chrome-connector.js +169 -23
- package/src/lib/config-manager.js +23 -9
- package/src/lib/context-breakdown.js +31 -0
- package/src/lib/cowork-cron.js +274 -32
- package/src/lib/cross-chain-mtc.js +3 -2
- package/src/lib/durable-security-store.js +124 -0
- package/src/lib/event-runtime-host.js +67 -6
- package/src/lib/event-runtime-store.js +163 -0
- package/src/lib/goal-store.js +32 -12
- package/src/lib/headless-manifest.js +2 -1
- package/src/lib/hook-environment.cjs +58 -0
- package/src/lib/hook-manager.js +12 -5
- package/src/lib/hook-runner.cjs +122 -28
- package/src/lib/hook-runner.js +7 -2
- package/src/lib/hooks-v2-producers.js +36 -0
- package/src/lib/hooks-v2-runtime.js +329 -52
- package/src/lib/interaction-adapter.js +60 -19
- package/src/lib/interaction-binding.js +64 -0
- package/src/lib/json-schema-output.js +439 -14
- package/src/lib/json-schema-validate.js +514 -883
- package/src/lib/lan-pairing-tokens.js +115 -57
- package/src/lib/lsp/__tests__/lsp-client.test.js +32 -0
- package/src/lib/lsp/__tests__/lsp-manager.test.js +25 -0
- package/src/lib/lsp/lsp-client.js +4 -0
- package/src/lib/lsp/lsp-manager.js +3 -0
- package/src/lib/lsp/lsp-server-registry.js +18 -0
- package/src/lib/mcp-client.js +1 -0
- package/src/lib/mcp-oauth.js +35 -21
- package/src/lib/packer/pkg-config-generator.js +3 -0
- package/src/lib/permission-decision.js +99 -0
- package/src/lib/plugin-monitor-supervisor.js +3 -0
- package/src/lib/plugin-runtime/bin.js +1148 -70
- package/src/lib/plugin-runtime/capabilities.js +50 -0
- package/src/lib/plugin-runtime/capability-consent.js +42 -35
- package/src/lib/plugin-runtime/hooks.js +36 -9
- package/src/lib/plugin-runtime/install.js +23 -7
- package/src/lib/plugin-runtime/lsp.js +4 -0
- package/src/lib/plugin-runtime/manifest.js +112 -8
- package/src/lib/plugin-runtime/mcp.js +30 -5
- package/src/lib/plugin-runtime/monitors.js +11 -0
- package/src/lib/plugin-runtime/plugin-options.js +94 -38
- package/src/lib/plugin-runtime/policy.js +29 -2
- package/src/lib/plugin-runtime/sandbox-policy.js +84 -0
- package/src/lib/plugin-runtime/scopes.js +27 -13
- package/src/lib/plugin-runtime/trust.js +36 -31
- package/src/lib/process-execution-broker/credential-agent.js +114 -16
- package/src/lib/process-execution-broker/credential-transport-worker.js +312 -0
- package/src/lib/process-execution-broker/credential-transport.js +378 -0
- package/src/lib/process-execution-broker/index.js +765 -49
- package/src/lib/process-execution-broker/platform-sandbox.js +4233 -138
- package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
- package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
- package/src/lib/process-execution-broker/windows-sandbox.cs +3856 -0
- package/src/lib/project-mcp-trust.js +21 -26
- package/src/lib/protocol-replay.js +19 -12
- package/src/lib/repl-bang-memorize.js +67 -10
- package/src/lib/settings-hooks.cjs +13 -0
- package/src/lib/skill-loader.js +83 -10
- package/src/lib/slash-commands.js +27 -4
- package/src/lib/sync-credentials.js +5 -4
- package/src/lib/turn-binding.js +8 -6
- package/src/repl/agent-repl.js +117 -31
- package/src/repl/repl-turn-binding.js +5 -2
- package/src/runtime/agent-core.js +699 -70
- package/src/runtime/agent-runtime.js +13 -1
- package/src/runtime/coding-agent-contract-shared.cjs +3 -3
- package/src/runtime/headless-runner.js +105 -7
- package/src/runtime/headless-stream.js +209 -23
- package/src/runtime/mcp-config.js +29 -17
- package/src/runtime/policies/agent-policy.js +2 -0
- package/src/workers/background-agent-worker.js +128 -13
- package/src/assets/web-panel/assets/ChatBubbleRenderer-C7bofJuA.js +0 -1
- package/src/assets/web-panel/assets/Projects-BbgmyQnS.js +0 -1
- package/src/assets/web-panel/assets/RemoteSession-Bqk3EYSu.js +0 -4
- package/src/assets/web-panel/assets/Tasks-3bDAUz8K.js +0 -1
- package/src/assets/web-panel/assets/Terminal-CsMLKIoV.js +0 -3
- package/src/assets/web-panel/assets/chat-CJ19O6Dh.js +0 -1
- package/src/assets/web-panel/assets/devWarning-BBMFnsja.js +0 -1
- package/src/assets/web-panel/assets/index-Do8JMV4N.js +0 -1
- package/src/assets/web-panel/assets/index-UYAJ6iNM.js +0 -1
|
@@ -23,6 +23,7 @@ import { MCPClient, MCPServerConfig } from "../harness/mcp-client.js";
|
|
|
23
23
|
import sharedManagedToolPolicy from "./coding-agent-managed-tool-policy.cjs";
|
|
24
24
|
import { findProjectRoot, loadProjectConfig } from "../lib/project-detector.js";
|
|
25
25
|
import { loadConfig } from "../lib/config-manager.js";
|
|
26
|
+
import { collectWorkspacePluginBinSandboxPolicy } from "../lib/plugin-runtime/bin.js";
|
|
26
27
|
|
|
27
28
|
const {
|
|
28
29
|
DEFAULT_ALLOWED_MCP_SERVER_NAMES,
|
|
@@ -63,6 +64,8 @@ export class AgentRuntime {
|
|
|
63
64
|
createSessionManager:
|
|
64
65
|
deps.createSessionManager ||
|
|
65
66
|
((options) => new WSSessionManager(options)),
|
|
67
|
+
createPtyManager:
|
|
68
|
+
deps.createPtyManager || ((options) => new PtyManager(options)),
|
|
66
69
|
createMcpClient: deps.createMcpClient || (() => new MCPClient()),
|
|
67
70
|
createMcpServerConfig:
|
|
68
71
|
deps.createMcpServerConfig || ((db) => new MCPServerConfig(db)),
|
|
@@ -449,6 +452,7 @@ export class AgentRuntime {
|
|
|
449
452
|
const projectName =
|
|
450
453
|
projectConfig?.name || (projectRoot ? path.basename(projectRoot) : null);
|
|
451
454
|
const mode = projectRoot ? "project" : "global";
|
|
455
|
+
const workspacePolicyCwd = path.resolve(projectRoot || process.cwd());
|
|
452
456
|
|
|
453
457
|
let db = null;
|
|
454
458
|
let rawDb = null;
|
|
@@ -492,6 +496,7 @@ export class AgentRuntime {
|
|
|
492
496
|
maxConnections: 20,
|
|
493
497
|
timeout: 60000,
|
|
494
498
|
sessionManager,
|
|
499
|
+
projectRoot: workspacePolicyCwd,
|
|
495
500
|
});
|
|
496
501
|
// ChainlessChainWSServer extends EventEmitter and emits "error"
|
|
497
502
|
// synchronously on bind failure (in addition to rejecting start()).
|
|
@@ -530,7 +535,14 @@ export class AgentRuntime {
|
|
|
530
535
|
// matching topics through `terminalHandlers.handlers`, falling back to
|
|
531
536
|
// the original CLI dispatcher for everything else.
|
|
532
537
|
const wsBroadcastRef = { current: null };
|
|
533
|
-
const ptyManager =
|
|
538
|
+
const ptyManager = this.deps.createPtyManager({
|
|
539
|
+
policyCwd: workspacePolicyCwd,
|
|
540
|
+
resolveSandboxPolicy: ({ workspaceCwd, executionCwd }) =>
|
|
541
|
+
collectWorkspacePluginBinSandboxPolicy({
|
|
542
|
+
workspaceCwd,
|
|
543
|
+
executionCwd,
|
|
544
|
+
}),
|
|
545
|
+
});
|
|
534
546
|
const terminal = createTerminalHandlers({
|
|
535
547
|
ptyManager,
|
|
536
548
|
broadcast: (frame) => wsBroadcastRef.current?.(frame),
|
|
@@ -1155,7 +1155,7 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
|
|
|
1155
1155
|
kind: "browser",
|
|
1156
1156
|
tier: "extension",
|
|
1157
1157
|
description:
|
|
1158
|
-
"Capture live state from the user's real Chrome over CDP: current URL/title, open tabs, console messages and failed/error network requests observed during a short watch window, a capped DOM snapshot, and optionally a screenshot (
|
|
1158
|
+
"Capture live state from the user's real Chrome over CDP: current URL/title, open tabs, console messages and failed/error network requests observed during a short watch window, a capped DOM snapshot, and optionally a screenshot (published as a session-bound Artifact; no host temp path enters the agent result). Requires a debuggable Chrome — the user starts one with `cc browse chrome launch`. Console/network capture starts at attach time (CDP keeps no history) — set reload=true to observe load-time errors. Use to verify web changes in the user's logged-in browser.",
|
|
1159
1159
|
inputSchema: {
|
|
1160
1160
|
type: "object",
|
|
1161
1161
|
properties: {
|
|
@@ -1187,7 +1187,7 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
|
|
|
1187
1187
|
screenshot: {
|
|
1188
1188
|
type: "boolean",
|
|
1189
1189
|
description:
|
|
1190
|
-
"
|
|
1190
|
+
"Capture a screenshot and return opaque, session-bound Artifact metadata (default false)",
|
|
1191
1191
|
},
|
|
1192
1192
|
},
|
|
1193
1193
|
required: [],
|
|
@@ -1208,7 +1208,7 @@ const CODING_AGENT_TOOL_CONTRACTS = Object.freeze([
|
|
|
1208
1208
|
kind: "browser",
|
|
1209
1209
|
tier: "extension",
|
|
1210
1210
|
description:
|
|
1211
|
-
"Perform EXPLICIT actions in the user's connected Chrome over loopback CDP: click, type, press, navigate (http/https only), waitForSelector, screenshot (
|
|
1211
|
+
"Perform EXPLICIT actions in the user's connected Chrome over loopback CDP: click, type, press, navigate (http/https only), waitForSelector, screenshot (published as a session-bound Artifact; never a caller-chosen path), assertText. Approval-gated (HIGH risk): use browser_state first to observe; only act when the task genuinely requires driving the browser. Steps run in order and fail fast unless continue_on_error; each returns {ok, action, detail, durationMs} and every executed step is audit-logged under ~/.chainlesschain/browser-actions/. Requires a debuggable Chrome (`cc browse chrome launch`).",
|
|
1212
1212
|
inputSchema: {
|
|
1213
1213
|
type: "object",
|
|
1214
1214
|
properties: {
|
|
@@ -61,6 +61,11 @@ import { SIDE_EFFECT_LEDGER_EVENT } from "../lib/side-effect-ledger-store.js";
|
|
|
61
61
|
import { TurnBindingLog, createTurnBindingFeed } from "../lib/turn-binding.js";
|
|
62
62
|
import { TURN_BINDING_EVENT } from "../lib/turn-binding-store.js";
|
|
63
63
|
import { operationIdempotencyKey } from "../lib/idempotency.js";
|
|
64
|
+
import {
|
|
65
|
+
emitHooksV2Event,
|
|
66
|
+
executeHooksV2Event,
|
|
67
|
+
resolvePromptExpansion,
|
|
68
|
+
} from "../lib/hooks-v2-producers.js";
|
|
64
69
|
import { CLISkillLoader } from "../lib/skill-loader.js";
|
|
65
70
|
import { expandFileRefsAsync } from "./file-ref-expander.js";
|
|
66
71
|
import { composeSystemPrompt } from "./system-prompt.js";
|
|
@@ -367,6 +372,7 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
367
372
|
// every existing risk-tier / shell-policy layer runs unchanged.
|
|
368
373
|
let permissionRules = options.permissionRules || null;
|
|
369
374
|
let managedSettings = null;
|
|
375
|
+
let settingsFiles = [];
|
|
370
376
|
try {
|
|
371
377
|
const { loadSettings, applyManagedPermissionPolicy } =
|
|
372
378
|
await import("../lib/settings-loader.cjs");
|
|
@@ -376,6 +382,7 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
376
382
|
managedSettingsFile: options.managedSettingsFile,
|
|
377
383
|
});
|
|
378
384
|
managedSettings = loaded.managed;
|
|
385
|
+
settingsFiles = Array.isArray(loaded.files) ? loaded.files : [];
|
|
379
386
|
if (!permissionRules) {
|
|
380
387
|
const total =
|
|
381
388
|
loaded.rules.allow.length +
|
|
@@ -426,9 +433,10 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
426
433
|
}
|
|
427
434
|
}
|
|
428
435
|
|
|
429
|
-
//
|
|
430
|
-
//
|
|
431
|
-
//
|
|
436
|
+
// Preserve PATH compatibility for trusted legacy bin components that have no
|
|
437
|
+
// sandboxPolicy. Policy-bearing bins are excluded here and resolved as exact
|
|
438
|
+
// direct Broker invocations by agent-core. The process exits at the end of
|
|
439
|
+
// the run, so no explicit restore is needed.
|
|
432
440
|
try {
|
|
433
441
|
const { applyPluginBinPath } = await import("../lib/plugin-runtime/bin.js");
|
|
434
442
|
applyPluginBinPath({ cwd });
|
|
@@ -465,6 +473,7 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
465
473
|
|
|
466
474
|
const runLoop = deps.agentLoop || coreAgentLoop;
|
|
467
475
|
const doBootstrap = deps.bootstrap || bootstrap;
|
|
476
|
+
const executeLifecycleHooks = deps.executeHooksV2Event || executeHooksV2Event;
|
|
468
477
|
const getApprovalGate =
|
|
469
478
|
deps.getApprovalGate ||
|
|
470
479
|
(async () => {
|
|
@@ -681,6 +690,48 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
681
690
|
}
|
|
682
691
|
};
|
|
683
692
|
|
|
693
|
+
const setupHooks = await executeLifecycleHooks(
|
|
694
|
+
"Setup",
|
|
695
|
+
{
|
|
696
|
+
schema_version: 1,
|
|
697
|
+
session_id: sessionId,
|
|
698
|
+
cwd,
|
|
699
|
+
database_available: db != null,
|
|
700
|
+
enabled_tools: enabledToolNames,
|
|
701
|
+
settings_files: settingsFiles,
|
|
702
|
+
},
|
|
703
|
+
{ failClosed: true },
|
|
704
|
+
);
|
|
705
|
+
if (setupHooks.blocked || setupHooks.decision === "block") {
|
|
706
|
+
const reason =
|
|
707
|
+
setupHooks.blockingResult?.reason ||
|
|
708
|
+
setupHooks.error ||
|
|
709
|
+
"blocked by Setup hook";
|
|
710
|
+
writeErr(`[hook] ${reason}\n`);
|
|
711
|
+
emitHeadlessError(reason);
|
|
712
|
+
return { exitCode: 2, result: reason, isError: true };
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
const expansionHooks = await executeLifecycleHooks(
|
|
716
|
+
"UserPromptExpansion",
|
|
717
|
+
{
|
|
718
|
+
schema_version: 1,
|
|
719
|
+
session_id: sessionId,
|
|
720
|
+
cwd,
|
|
721
|
+
prompt: userContent,
|
|
722
|
+
original_prompt: prompt,
|
|
723
|
+
},
|
|
724
|
+
{ failClosed: true },
|
|
725
|
+
);
|
|
726
|
+
const expansion = resolvePromptExpansion(userContent, expansionHooks);
|
|
727
|
+
if (expansion.blocked) {
|
|
728
|
+
const reason = expansion.reason || "blocked by UserPromptExpansion hook";
|
|
729
|
+
writeErr(`[hook] ${reason}\n`);
|
|
730
|
+
emitHeadlessError(reason);
|
|
731
|
+
return { exitCode: 2, result: reason, isError: true };
|
|
732
|
+
}
|
|
733
|
+
userContent = expansion.prompt;
|
|
734
|
+
|
|
684
735
|
// Load prior conversation when resuming an existing session. The fresh
|
|
685
736
|
// system prompt always leads; we drop any persisted system turns so it is
|
|
686
737
|
// never duplicated.
|
|
@@ -1033,8 +1084,7 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
1033
1084
|
let _loadedInstructions = null;
|
|
1034
1085
|
let _loadedPersonaSkills = [];
|
|
1035
1086
|
let _skillCacheLedger = null;
|
|
1036
|
-
const _runtimeSkillLoader =
|
|
1037
|
-
options.skillLoader || new CLISkillLoader();
|
|
1087
|
+
const _runtimeSkillLoader = options.skillLoader || new CLISkillLoader();
|
|
1038
1088
|
const systemContent = composeSystemPrompt(
|
|
1039
1089
|
buildSystemPrompt(cwd, {
|
|
1040
1090
|
additionalDirectories,
|
|
@@ -1967,6 +2017,11 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
1967
2017
|
// P0-2: settle the in-flight side-effect (commit on success, fail on
|
|
1968
2018
|
// a clean error) and persist the updated ledger snapshot.
|
|
1969
2019
|
if (persist && currentSideEffectOpId) {
|
|
2020
|
+
if (event.permission_decision) {
|
|
2021
|
+
sideEffectLedger.annotate(currentSideEffectOpId, {
|
|
2022
|
+
permissionDecision: event.permission_decision,
|
|
2023
|
+
});
|
|
2024
|
+
}
|
|
1970
2025
|
if (event.result?._diffReviewAudit) {
|
|
1971
2026
|
diffReviewFollowUps.observe(
|
|
1972
2027
|
sideEffectLedger,
|
|
@@ -1991,6 +2046,12 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
1991
2046
|
is_error: Boolean(err),
|
|
1992
2047
|
error: err,
|
|
1993
2048
|
result: event.result,
|
|
2049
|
+
...(event.permission_decision_id
|
|
2050
|
+
? { permission_decision_id: event.permission_decision_id }
|
|
2051
|
+
: {}),
|
|
2052
|
+
...(event.permission_decision
|
|
2053
|
+
? { permission_decision: event.permission_decision }
|
|
2054
|
+
: {}),
|
|
1994
2055
|
});
|
|
1995
2056
|
if (toolCalls.length > 0) {
|
|
1996
2057
|
toolCalls[toolCalls.length - 1].is_error = Boolean(err);
|
|
@@ -2351,7 +2412,30 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
2351
2412
|
const { runObserveHooks, dispatchAsyncHooks } =
|
|
2352
2413
|
await import("../lib/settings-hook-events.js");
|
|
2353
2414
|
const stopPayload = { reason: endReason, cwd, session_id: sessionId };
|
|
2354
|
-
|
|
2415
|
+
const stopOutcome = runObserveHooks(
|
|
2416
|
+
settingsHooks,
|
|
2417
|
+
"Stop",
|
|
2418
|
+
stopPayload,
|
|
2419
|
+
{ cwd },
|
|
2420
|
+
);
|
|
2421
|
+
const stopFailures = (stopOutcome?.results || []).filter(
|
|
2422
|
+
(result) =>
|
|
2423
|
+
result?.nonBlockingError === true ||
|
|
2424
|
+
result?.malformedDecision === true ||
|
|
2425
|
+
result?.breakerOpen === true,
|
|
2426
|
+
);
|
|
2427
|
+
if (stopFailures.length > 0) {
|
|
2428
|
+
emitHooksV2Event("StopFailure", {
|
|
2429
|
+
schema_version: 1,
|
|
2430
|
+
session_id: sessionId,
|
|
2431
|
+
phase: "stop-hook",
|
|
2432
|
+
failures: stopFailures.map((failure) => ({
|
|
2433
|
+
command: failure.command || null,
|
|
2434
|
+
exit_code: failure.exitCode ?? null,
|
|
2435
|
+
reason: failure.reason || failure.error || null,
|
|
2436
|
+
})),
|
|
2437
|
+
});
|
|
2438
|
+
}
|
|
2355
2439
|
// Skip the async Stop dispatch/settle here if the auto-rewake re-drive
|
|
2356
2440
|
// loop already fired + drained it this run (avoids double-execution).
|
|
2357
2441
|
if (_hookSupervisor && !_asyncStopHandled) {
|
|
@@ -2377,6 +2461,14 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
2377
2461
|
// re-engage the agent in an interactive session — flag it clearly so a
|
|
2378
2462
|
// headless caller/CI can react.
|
|
2379
2463
|
for (const rw of _hookSupervisor.drainRewakes()) {
|
|
2464
|
+
emitHooksV2Event("StopFailure", {
|
|
2465
|
+
schema_version: 1,
|
|
2466
|
+
session_id: sessionId,
|
|
2467
|
+
phase: "async-stop-hook",
|
|
2468
|
+
command: rw.command || null,
|
|
2469
|
+
exit_code: rw.exitCode ?? null,
|
|
2470
|
+
reason: rw.error || "async stop hook requested rewake",
|
|
2471
|
+
});
|
|
2380
2472
|
writeErr(
|
|
2381
2473
|
`[async-hook REWAKE] ${rw.command} failed` +
|
|
2382
2474
|
`${rw.exitCode != null ? ` (exit ${rw.exitCode})` : ""}` +
|
|
@@ -2398,7 +2490,13 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
2398
2490
|
{ reason: "completed", cwd, session_id: sessionId },
|
|
2399
2491
|
{ cwd },
|
|
2400
2492
|
);
|
|
2401
|
-
} catch {
|
|
2493
|
+
} catch (error) {
|
|
2494
|
+
emitHooksV2Event("StopFailure", {
|
|
2495
|
+
schema_version: 1,
|
|
2496
|
+
session_id: sessionId,
|
|
2497
|
+
phase: "stop-hook-dispatch",
|
|
2498
|
+
reason: error?.message || String(error),
|
|
2499
|
+
});
|
|
2402
2500
|
// observe-only + best-effort async surfacing
|
|
2403
2501
|
}
|
|
2404
2502
|
}
|
|
@@ -21,6 +21,15 @@ import {
|
|
|
21
21
|
approvalBindingDigest,
|
|
22
22
|
verifyApprovalBinding,
|
|
23
23
|
} from "../lib/agent-authority.js";
|
|
24
|
+
import {
|
|
25
|
+
normalizeInteractionBinding,
|
|
26
|
+
sameInteractionBinding,
|
|
27
|
+
} from "../lib/interaction-binding.js";
|
|
28
|
+
import {
|
|
29
|
+
emitHooksV2Event,
|
|
30
|
+
executeHooksV2Event,
|
|
31
|
+
resolvePromptExpansion,
|
|
32
|
+
} from "../lib/hooks-v2-producers.js";
|
|
24
33
|
import { bootstrap } from "./bootstrap.js";
|
|
25
34
|
import { buildSystemPrompt, agentLoop as coreAgentLoop } from "./agent-core.js";
|
|
26
35
|
import { composeSystemPrompt } from "./system-prompt.js";
|
|
@@ -183,6 +192,15 @@ export function createStreamCoalescer({
|
|
|
183
192
|
const gateOn = (field) => !fieldGate || fieldGate[field] !== false;
|
|
184
193
|
const rawEmit = (obj) => {
|
|
185
194
|
let line = obj;
|
|
195
|
+
if (
|
|
196
|
+
!gateOn("permission_decision") &&
|
|
197
|
+
(Object.prototype.hasOwnProperty.call(line, "permission_decision") ||
|
|
198
|
+
Object.prototype.hasOwnProperty.call(line, "permission_decision_id"))
|
|
199
|
+
) {
|
|
200
|
+
line = { ...line };
|
|
201
|
+
delete line.permission_decision;
|
|
202
|
+
delete line.permission_decision_id;
|
|
203
|
+
}
|
|
186
204
|
if (traceId && gateOn("trace_id")) line = { ...line, trace_id: traceId };
|
|
187
205
|
if (stampSeq && gateOn("seq")) line = { ...line, seq: ++seq };
|
|
188
206
|
writeOut(JSON.stringify(line) + "\n");
|
|
@@ -488,6 +506,9 @@ export function parseInputEvent(line) {
|
|
|
488
506
|
answer: {
|
|
489
507
|
id: String(obj.id),
|
|
490
508
|
value: obj.answer === undefined ? null : obj.answer,
|
|
509
|
+
...(obj.binding && typeof obj.binding === "object"
|
|
510
|
+
? { binding: normalizeInteractionBinding(obj.binding) }
|
|
511
|
+
: {}),
|
|
491
512
|
},
|
|
492
513
|
};
|
|
493
514
|
}
|
|
@@ -761,8 +782,7 @@ async function runTurn(
|
|
|
761
782
|
// agent-sdk docs/PROTOCOL.md §1.2.1): the matching tool_result below
|
|
762
783
|
// echoes the same id so UIs can pair calls without adjacency.
|
|
763
784
|
const toolUseId =
|
|
764
|
-
event.tool_use_id ||
|
|
765
|
-
(nextToolUseId ? nextToolUseId() : undefined);
|
|
785
|
+
event.tool_use_id || (nextToolUseId ? nextToolUseId() : undefined);
|
|
766
786
|
const pm = getPlanModeManager();
|
|
767
787
|
const planItem = pm.startPlanItemForTool(event.tool, {
|
|
768
788
|
toolUseId,
|
|
@@ -822,6 +842,11 @@ async function runTurn(
|
|
|
822
842
|
// P0-2: settle the in-flight side-effect (commit on success, fail on
|
|
823
843
|
// a clean error) and persist the updated ledger snapshot.
|
|
824
844
|
if (sideEffects && currentSideEffectOpId) {
|
|
845
|
+
if (event.permission_decision) {
|
|
846
|
+
sideEffects.ledger.annotate(currentSideEffectOpId, {
|
|
847
|
+
permissionDecision: event.permission_decision,
|
|
848
|
+
});
|
|
849
|
+
}
|
|
825
850
|
if (event.result?._diffReviewAudit) {
|
|
826
851
|
diffReviewFollowUps.observe(
|
|
827
852
|
sideEffects.ledger,
|
|
@@ -866,6 +891,12 @@ async function runTurn(
|
|
|
866
891
|
is_error: Boolean(err),
|
|
867
892
|
error: err,
|
|
868
893
|
result: event.result,
|
|
894
|
+
...(event.permission_decision_id
|
|
895
|
+
? { permission_decision_id: event.permission_decision_id }
|
|
896
|
+
: {}),
|
|
897
|
+
...(event.permission_decision
|
|
898
|
+
? { permission_decision: event.permission_decision }
|
|
899
|
+
: {}),
|
|
869
900
|
});
|
|
870
901
|
if (settledItem) {
|
|
871
902
|
emit({ type: "plan_update", ...planSnapshot(pm) });
|
|
@@ -1046,6 +1077,7 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
1046
1077
|
const input = deps.input || process.stdin;
|
|
1047
1078
|
const runLoop = deps.agentLoop || coreAgentLoop;
|
|
1048
1079
|
const doBootstrap = deps.bootstrap || bootstrap;
|
|
1080
|
+
const executeLifecycleHooks = deps.executeHooksV2Event || executeHooksV2Event;
|
|
1049
1081
|
const doExpand = deps.expandFileRefs || expandFileRefsAsync;
|
|
1050
1082
|
const runSessionSlashCommand =
|
|
1051
1083
|
deps.executeSessionSlashCommand || executeSessionSlashCommand;
|
|
@@ -1068,7 +1100,12 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
1068
1100
|
// client `hello` narrowing the wire features flips these to suppress the
|
|
1069
1101
|
// additive fields it can't parse. All true by default = current behavior
|
|
1070
1102
|
// byte-for-byte; the coalescer reads it per line.
|
|
1071
|
-
const fieldGate = {
|
|
1103
|
+
const fieldGate = {
|
|
1104
|
+
seq: true,
|
|
1105
|
+
trace_id: true,
|
|
1106
|
+
tool_use_id: true,
|
|
1107
|
+
permission_decision: true,
|
|
1108
|
+
};
|
|
1072
1109
|
// Batch consecutive partial-message text/thinking deltas into one stream_event
|
|
1073
1110
|
// line (Claude-Code 2.1.191 streaming-CPU optimization). `emit` flushes any
|
|
1074
1111
|
// pending deltas before writing a non-delta line, so ordering is preserved;
|
|
@@ -1115,6 +1152,33 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
1115
1152
|
const sessionId =
|
|
1116
1153
|
options.sessionId || `headless-stream-${Date.now()}-${process.pid}`;
|
|
1117
1154
|
|
|
1155
|
+
const setupHooks = await executeLifecycleHooks(
|
|
1156
|
+
"Setup",
|
|
1157
|
+
{
|
|
1158
|
+
schema_version: 1,
|
|
1159
|
+
session_id: sessionId,
|
|
1160
|
+
cwd,
|
|
1161
|
+
database_available: db != null,
|
|
1162
|
+
enabled_tools: enabledToolNames,
|
|
1163
|
+
settings_files: settingsFiles,
|
|
1164
|
+
},
|
|
1165
|
+
{ failClosed: true },
|
|
1166
|
+
);
|
|
1167
|
+
if (setupHooks.blocked || setupHooks.decision === "block") {
|
|
1168
|
+
const reason =
|
|
1169
|
+
setupHooks.blockingResult?.reason ||
|
|
1170
|
+
setupHooks.error ||
|
|
1171
|
+
"blocked by Setup hook";
|
|
1172
|
+
emit({
|
|
1173
|
+
type: "result",
|
|
1174
|
+
subtype: "blocked",
|
|
1175
|
+
is_error: true,
|
|
1176
|
+
result: reason,
|
|
1177
|
+
session_id: sessionId,
|
|
1178
|
+
});
|
|
1179
|
+
return { exitCode: 2, turns: 0 };
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1118
1182
|
// Session persistence + resume (chat-panel "session resume" / --resume):
|
|
1119
1183
|
// an EXPLICIT session id (--session / --resume) opts into JSONL persistence —
|
|
1120
1184
|
// prior history is rebuilt into the conversation and every new turn is
|
|
@@ -1434,17 +1498,29 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
1434
1498
|
multiSelect,
|
|
1435
1499
|
timeoutMs,
|
|
1436
1500
|
metadata,
|
|
1501
|
+
sessionId: requestedSessionId,
|
|
1502
|
+
turnId,
|
|
1503
|
+
toolUseId,
|
|
1437
1504
|
} = {}) =>
|
|
1438
1505
|
new Promise((resolve, reject) => {
|
|
1439
1506
|
const id = `q-${++questionSeq}`;
|
|
1507
|
+
const binding = normalizeInteractionBinding({
|
|
1508
|
+
sessionId: requestedSessionId ?? sessionId,
|
|
1509
|
+
turnId,
|
|
1510
|
+
toolUseId,
|
|
1511
|
+
sequence: questionSeq,
|
|
1512
|
+
});
|
|
1440
1513
|
const ms = Number(timeoutMs) > 0 ? Number(timeoutMs) : questionTimeoutMs;
|
|
1441
1514
|
const timer = setTimeout(() => failQuestion(id, "timeout"), ms);
|
|
1442
1515
|
timer.unref?.();
|
|
1443
|
-
pendingQuestions.set(id, { resolve, reject, timer });
|
|
1516
|
+
pendingQuestions.set(id, { resolve, reject, timer, binding });
|
|
1444
1517
|
emit({
|
|
1445
1518
|
type: "question_request",
|
|
1446
1519
|
id,
|
|
1447
1520
|
session_id: sessionId,
|
|
1521
|
+
binding,
|
|
1522
|
+
...(binding.turnId ? { turn_id: binding.turnId } : {}),
|
|
1523
|
+
...(binding.toolUseId ? { tool_use_id: binding.toolUseId } : {}),
|
|
1448
1524
|
question: typeof question === "string" ? question : "",
|
|
1449
1525
|
options: Array.isArray(qOptions) ? qOptions : null,
|
|
1450
1526
|
multiSelect: multiSelect === true,
|
|
@@ -1491,7 +1567,10 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
1491
1567
|
if (options.jsonSchema) {
|
|
1492
1568
|
try {
|
|
1493
1569
|
_jso = await import("../lib/json-schema-output.js");
|
|
1494
|
-
_jsonSchema = _jso.
|
|
1570
|
+
_jsonSchema = await _jso.loadSchemaFileWithRefs(
|
|
1571
|
+
_jso._deps.fs,
|
|
1572
|
+
options.jsonSchema,
|
|
1573
|
+
);
|
|
1495
1574
|
} catch (err) {
|
|
1496
1575
|
// Fail-fast, exactly like `cc agent -p --json-schema` on a bad schema.
|
|
1497
1576
|
writeErr(`Error: ${err.message}\n`);
|
|
@@ -1761,32 +1840,91 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
1761
1840
|
// handler only after MCP resolution so the client is initialized before use.
|
|
1762
1841
|
// Reuse the structured Desktop/headless question channel, while preserving
|
|
1763
1842
|
// the MCP response shape (`action` + object `content`) at this boundary.
|
|
1843
|
+
if (mcp?.mcpClient?.on) {
|
|
1844
|
+
mcp.mcpClient.on("elicitation-deferred", (request) => {
|
|
1845
|
+
emit({
|
|
1846
|
+
type: "elicitation_deferred",
|
|
1847
|
+
session_id: sessionId,
|
|
1848
|
+
server: request.server || null,
|
|
1849
|
+
request_id: request.requestId ?? null,
|
|
1850
|
+
mode: request.mode || "form",
|
|
1851
|
+
message: request.message || "",
|
|
1852
|
+
requested_schema: request.requestedSchema || null,
|
|
1853
|
+
elicitation_id: request.elicitationId || null,
|
|
1854
|
+
url: request.url || null,
|
|
1855
|
+
url_host: request.urlHost || null,
|
|
1856
|
+
reason: request.reason || "no_interactive_host",
|
|
1857
|
+
wire_action: request.wireAction || "decline",
|
|
1858
|
+
});
|
|
1859
|
+
});
|
|
1860
|
+
mcp.mcpClient.on("elicitation-complete", (event) => {
|
|
1861
|
+
emit({
|
|
1862
|
+
type: "elicitation_complete",
|
|
1863
|
+
session_id: sessionId,
|
|
1864
|
+
server: event.server || null,
|
|
1865
|
+
elicitation_id: event.elicitationId || null,
|
|
1866
|
+
});
|
|
1867
|
+
});
|
|
1868
|
+
}
|
|
1764
1869
|
if (mcp?.mcpClient?.setElicitationHandler && interactiveQuestions) {
|
|
1765
1870
|
mcp.mcpClient.setElicitationHandler(async (request) => {
|
|
1766
|
-
const
|
|
1767
|
-
|
|
1871
|
+
const hookContext = {
|
|
1872
|
+
schema_version: 1,
|
|
1768
1873
|
server: request.server || null,
|
|
1769
1874
|
request_id: request.requestId ?? null,
|
|
1770
1875
|
message: request.message || "MCP server requests additional input",
|
|
1771
1876
|
requested_schema: request.requestedSchema || null,
|
|
1877
|
+
mode: request.mode || "form",
|
|
1878
|
+
elicitation_id: request.elicitationId || null,
|
|
1879
|
+
url: request.url || null,
|
|
1880
|
+
url_host: request.urlHost || null,
|
|
1772
1881
|
session_id: sessionId,
|
|
1773
|
-
});
|
|
1774
|
-
const answer = await interactionAskUser({
|
|
1775
|
-
question: request.message || "MCP server requests additional input",
|
|
1776
|
-
timeoutMs: request.timeoutMs,
|
|
1777
|
-
metadata: {
|
|
1778
|
-
kind: "mcp_elicitation",
|
|
1779
|
-
server: request.server,
|
|
1780
|
-
requestId: request.requestId,
|
|
1781
|
-
requestedSchema: request.requestedSchema || null,
|
|
1782
|
-
},
|
|
1783
|
-
});
|
|
1784
|
-
if (answer == null) return { action: "cancel" };
|
|
1785
|
-
return {
|
|
1786
|
-
action: "accept",
|
|
1787
|
-
content:
|
|
1788
|
-
answer && typeof answer === "object" ? answer : { value: answer },
|
|
1789
1882
|
};
|
|
1883
|
+
emitHooksV2Event("MCPElicitation", hookContext);
|
|
1884
|
+
emitHooksV2Event("Elicitation", hookContext);
|
|
1885
|
+
try {
|
|
1886
|
+
const answer = await interactionAskUser({
|
|
1887
|
+
question:
|
|
1888
|
+
request.mode === "url"
|
|
1889
|
+
? `${request.message || "MCP server requests an external interaction"}\nOpen secure URL on ${request.urlHost}?`
|
|
1890
|
+
: request.message || "MCP server requests additional input",
|
|
1891
|
+
timeoutMs: request.timeoutMs,
|
|
1892
|
+
metadata: {
|
|
1893
|
+
kind: "mcp_elicitation",
|
|
1894
|
+
server: request.server,
|
|
1895
|
+
requestId: request.requestId,
|
|
1896
|
+
mode: request.mode || "form",
|
|
1897
|
+
requestedSchema: request.requestedSchema || null,
|
|
1898
|
+
elicitationId: request.elicitationId || null,
|
|
1899
|
+
url: request.url || null,
|
|
1900
|
+
urlHost: request.urlHost || null,
|
|
1901
|
+
},
|
|
1902
|
+
});
|
|
1903
|
+
const response =
|
|
1904
|
+
answer == null
|
|
1905
|
+
? { action: "cancel" }
|
|
1906
|
+
: request.mode === "url"
|
|
1907
|
+
? { action: "accept" }
|
|
1908
|
+
: {
|
|
1909
|
+
action: "accept",
|
|
1910
|
+
content:
|
|
1911
|
+
answer && typeof answer === "object"
|
|
1912
|
+
? answer
|
|
1913
|
+
: { value: answer },
|
|
1914
|
+
};
|
|
1915
|
+
emitHooksV2Event("ElicitationResult", {
|
|
1916
|
+
...hookContext,
|
|
1917
|
+
action: response.action,
|
|
1918
|
+
});
|
|
1919
|
+
return response;
|
|
1920
|
+
} catch (error) {
|
|
1921
|
+
emitHooksV2Event("ElicitationResult", {
|
|
1922
|
+
...hookContext,
|
|
1923
|
+
action: "cancel",
|
|
1924
|
+
reason: error?.code || error?.message || "interaction_failed",
|
|
1925
|
+
});
|
|
1926
|
+
throw error;
|
|
1927
|
+
}
|
|
1790
1928
|
});
|
|
1791
1929
|
}
|
|
1792
1930
|
|
|
@@ -2044,6 +2182,19 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
2044
2182
|
if (parsed.answer) {
|
|
2045
2183
|
// Answers settle a BLOCKED ask_user_question — never queued. A null
|
|
2046
2184
|
// value (user cancelled the QuickPick) → user_timeout (model proceeds).
|
|
2185
|
+
const pending = pendingQuestions.get(parsed.answer.id);
|
|
2186
|
+
if (
|
|
2187
|
+
!pending ||
|
|
2188
|
+
!sameInteractionBinding(pending.binding, parsed.answer.binding)
|
|
2189
|
+
) {
|
|
2190
|
+
emit({
|
|
2191
|
+
type: "question_response_rejected",
|
|
2192
|
+
id: parsed.answer.id,
|
|
2193
|
+
reason: "binding_mismatch",
|
|
2194
|
+
session_id: sessionId,
|
|
2195
|
+
});
|
|
2196
|
+
continue;
|
|
2197
|
+
}
|
|
2047
2198
|
if (parsed.answer.value == null)
|
|
2048
2199
|
failQuestion(parsed.answer.id, "cancelled");
|
|
2049
2200
|
else
|
|
@@ -2196,6 +2347,15 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
2196
2347
|
messages_before: before,
|
|
2197
2348
|
messages_after: messages.length,
|
|
2198
2349
|
});
|
|
2350
|
+
emitHooksV2Event("PostCompact", {
|
|
2351
|
+
schema_version: 1,
|
|
2352
|
+
trigger: "manual",
|
|
2353
|
+
session_id: sessionId,
|
|
2354
|
+
messages_before: before,
|
|
2355
|
+
messages_after: messages.length,
|
|
2356
|
+
stats,
|
|
2357
|
+
cwd,
|
|
2358
|
+
});
|
|
2199
2359
|
continue;
|
|
2200
2360
|
}
|
|
2201
2361
|
|
|
@@ -2439,6 +2599,32 @@ export async function runAgentHeadlessStream(options = {}, deps = {}) {
|
|
|
2439
2599
|
for (const w of expanded.warnings) writeErr(` @ref: ${w}\n`);
|
|
2440
2600
|
}
|
|
2441
2601
|
|
|
2602
|
+
const expansionHooks = await executeLifecycleHooks(
|
|
2603
|
+
"UserPromptExpansion",
|
|
2604
|
+
{
|
|
2605
|
+
schema_version: 1,
|
|
2606
|
+
session_id: sessionId,
|
|
2607
|
+
turn: turns + 1,
|
|
2608
|
+
cwd,
|
|
2609
|
+
prompt: userContent,
|
|
2610
|
+
original_prompt: parsed.text,
|
|
2611
|
+
},
|
|
2612
|
+
{ failClosed: true },
|
|
2613
|
+
);
|
|
2614
|
+
const expansion = resolvePromptExpansion(userContent, expansionHooks);
|
|
2615
|
+
if (expansion.blocked) {
|
|
2616
|
+
emit({
|
|
2617
|
+
type: "result",
|
|
2618
|
+
subtype: "blocked",
|
|
2619
|
+
is_error: true,
|
|
2620
|
+
result: expansion.reason || "blocked by UserPromptExpansion hook",
|
|
2621
|
+
session_id: sessionId,
|
|
2622
|
+
});
|
|
2623
|
+
sawError = true;
|
|
2624
|
+
continue;
|
|
2625
|
+
}
|
|
2626
|
+
userContent = expansion.prompt;
|
|
2627
|
+
|
|
2442
2628
|
// settings.json UserPromptSubmit hooks. block → skip this turn; context → inject.
|
|
2443
2629
|
if (settingsHooks) {
|
|
2444
2630
|
try {
|
|
@@ -647,6 +647,12 @@ export async function loadProjectMcp(opts = {}, deps = {}) {
|
|
|
647
647
|
const trust =
|
|
648
648
|
deps.projectMcpTrust ||
|
|
649
649
|
(await import("../lib/project-mcp-trust.js").catch(() => null));
|
|
650
|
+
if (!trust) {
|
|
651
|
+
writeErr(
|
|
652
|
+
" mcp: SKIPPING project .mcp.json — project trust service is unavailable.\n",
|
|
653
|
+
);
|
|
654
|
+
return deps.into || null;
|
|
655
|
+
}
|
|
650
656
|
|
|
651
657
|
const servers = {};
|
|
652
658
|
const seenFiles = [];
|
|
@@ -661,26 +667,32 @@ export async function loadProjectMcp(opts = {}, deps = {}) {
|
|
|
661
667
|
writeErr(` mcp: ignoring malformed ${file} (${err.message})\n`);
|
|
662
668
|
continue;
|
|
663
669
|
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
if (
|
|
668
|
-
if (trust.
|
|
669
|
-
|
|
670
|
-
writeErr(` mcp: ${file} re-trusted (CC_PROJECT_MCP_TRUST).\n`);
|
|
671
|
-
} else {
|
|
672
|
-
writeErr(
|
|
673
|
-
` mcp: SKIPPING ${file} — its content changed since it was last trusted. ` +
|
|
674
|
-
`Review the diff, then re-trust with CC_PROJECT_MCP_TRUST=1 or \`cc mcp trust-project\`.\n`,
|
|
675
|
-
);
|
|
676
|
-
continue;
|
|
670
|
+
try {
|
|
671
|
+
const check = trust.checkProjectMcpTrust(file, content);
|
|
672
|
+
if (check.status === "changed") {
|
|
673
|
+
if (trust.projectMcpRetrustRequested(env)) {
|
|
674
|
+
if (trust.recordProjectMcpTrust(file, content) !== true) {
|
|
675
|
+
throw new Error("project MCP trust record was not persisted");
|
|
677
676
|
}
|
|
678
|
-
|
|
679
|
-
|
|
677
|
+
writeErr(` mcp: ${file} re-trusted (CC_PROJECT_MCP_TRUST).\n`);
|
|
678
|
+
} else {
|
|
679
|
+
writeErr(
|
|
680
|
+
` mcp: SKIPPING ${file} — its content changed since it was last trusted. ` +
|
|
681
|
+
`Review the diff, then re-trust with CC_PROJECT_MCP_TRUST=1 or \`cc mcp trust-project\`.\n`,
|
|
682
|
+
);
|
|
683
|
+
continue;
|
|
684
|
+
}
|
|
685
|
+
} else if (check.status === "first-use") {
|
|
686
|
+
if (trust.recordProjectMcpTrust(file, content) !== true) {
|
|
687
|
+
throw new Error("project MCP trust record was not persisted");
|
|
680
688
|
}
|
|
681
|
-
} catch {
|
|
682
|
-
/* trust bookkeeping is best-effort; the opt-in gate above still holds */
|
|
683
689
|
}
|
|
690
|
+
} catch (err) {
|
|
691
|
+
writeErr(
|
|
692
|
+
` mcp: SKIPPING ${file} — project trust state is unavailable ` +
|
|
693
|
+
`(${err?.message || "unknown error"}).\n`,
|
|
694
|
+
);
|
|
695
|
+
continue;
|
|
684
696
|
}
|
|
685
697
|
const parsed = parseMcpServers(raw);
|
|
686
698
|
if (Object.keys(parsed).length > 0) {
|