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
|
@@ -456,7 +456,11 @@ export function previewWorktreeMerge(repoDir, branchName, options = {}) {
|
|
|
456
456
|
|
|
457
457
|
let mergeStarted = false;
|
|
458
458
|
try {
|
|
459
|
-
|
|
459
|
+
// Use argv form here rather than routing through a shell. Besides avoiding
|
|
460
|
+
// another quoting surface, this is important on Windows where a conflicted
|
|
461
|
+
// `git merge` followed immediately by another shell-wrapped git process can
|
|
462
|
+
// race the hosted runner's process/job cleanup and hide the unmerged index.
|
|
463
|
+
gitExecArgs(["merge", baseBranch, "--no-commit", "--no-ff"], worktree.path);
|
|
460
464
|
mergeStarted = true;
|
|
461
465
|
|
|
462
466
|
return {
|
|
@@ -713,7 +717,14 @@ function _hasBranchCommits(repoDir, branchName) {
|
|
|
713
717
|
|
|
714
718
|
function _collectConflictFiles(repoDir) {
|
|
715
719
|
try {
|
|
716
|
-
|
|
720
|
+
// A conflict is expected to make the preceding merge exit non-zero. Query
|
|
721
|
+
// the index with a direct git argv invocation so Windows shell/process
|
|
722
|
+
// teardown cannot turn the authoritative conflict probe into an empty
|
|
723
|
+
// best-effort result.
|
|
724
|
+
const output = gitExecArgs(
|
|
725
|
+
["diff", "--name-only", "--diff-filter=U"],
|
|
726
|
+
repoDir,
|
|
727
|
+
);
|
|
717
728
|
return output
|
|
718
729
|
.split("\n")
|
|
719
730
|
.map((line) => line.trim())
|
|
@@ -988,7 +999,7 @@ function _resolveAutomationCandidate(type, filePath, branchName, candidateId) {
|
|
|
988
999
|
|
|
989
1000
|
function _abortMergeIfPresent(repoDir) {
|
|
990
1001
|
try {
|
|
991
|
-
|
|
1002
|
+
gitExecArgs(["merge", "--abort"], repoDir);
|
|
992
1003
|
} catch (_e) {
|
|
993
1004
|
// Ignore if there is no in-progress merge.
|
|
994
1005
|
}
|
package/src/lazy-dispatch.js
CHANGED
|
@@ -6,6 +6,10 @@ import { pathToFileURL } from "node:url";
|
|
|
6
6
|
import { dirname, join } from "node:path";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
import { readFileSync } from "node:fs";
|
|
9
|
+
import {
|
|
10
|
+
startDefaultEventRuntimeHost,
|
|
11
|
+
stopDefaultEventRuntimeHost,
|
|
12
|
+
} from "./lib/event-runtime-host.js";
|
|
9
13
|
|
|
10
14
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
15
|
const manifest = JSON.parse(
|
|
@@ -29,7 +33,28 @@ export function resolveCommandToken(argv = []) {
|
|
|
29
33
|
return null;
|
|
30
34
|
}
|
|
31
35
|
|
|
32
|
-
export async function
|
|
36
|
+
export async function withDefaultEventRuntimeLifecycle(
|
|
37
|
+
task,
|
|
38
|
+
{ hostOptions = {} } = {},
|
|
39
|
+
) {
|
|
40
|
+
if (typeof task !== "function") {
|
|
41
|
+
throw new TypeError("Event Runtime lifecycle task must be a function");
|
|
42
|
+
}
|
|
43
|
+
const host = startDefaultEventRuntimeHost({
|
|
44
|
+
...hostOptions,
|
|
45
|
+
// Let the selected command finish registering its handlers before the
|
|
46
|
+
// first claim. Resident commands then run on the normal interval; short
|
|
47
|
+
// commands receive a bounded final drain in the finally block.
|
|
48
|
+
immediate: false,
|
|
49
|
+
});
|
|
50
|
+
try {
|
|
51
|
+
return await task(host);
|
|
52
|
+
} finally {
|
|
53
|
+
if (host) await stopDefaultEventRuntimeHost({ drain: true });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function dispatchCli(argv) {
|
|
33
58
|
const args = argv.slice(2);
|
|
34
59
|
|
|
35
60
|
// Resolve the command before deciding whether help/version needs the eager
|
|
@@ -95,6 +120,10 @@ export async function runCli(argv) {
|
|
|
95
120
|
}
|
|
96
121
|
}
|
|
97
122
|
|
|
123
|
+
export async function runCli(argv) {
|
|
124
|
+
return withDefaultEventRuntimeLifecycle(() => dispatchCli(argv));
|
|
125
|
+
}
|
|
126
|
+
|
|
98
127
|
export class LazyDispatch {
|
|
99
128
|
constructor(manifest) {
|
|
100
129
|
this.manifest = manifest;
|
|
@@ -154,6 +154,28 @@ export function canManageSession(envelope = {}) {
|
|
|
154
154
|
);
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
/**
|
|
158
|
+
* True when this envelope may answer a human-interaction request. A local UI
|
|
159
|
+
* owns this authority. A remote peer must be authenticated and explicitly
|
|
160
|
+
* paired for prompt/approve/manage control; observe-only peers cannot answer.
|
|
161
|
+
*/
|
|
162
|
+
export function canAnswerInteraction(envelope = {}) {
|
|
163
|
+
if (envelope.origin === ORIGIN.USER) return true;
|
|
164
|
+
if (envelope.origin !== ORIGIN.REMOTE || envelope.authenticated !== true) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
const scopes = normalizeScopes(envelope);
|
|
168
|
+
return scopes.has("prompt") || scopes.has("approve") || scopes.has("manage");
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function assertCanAnswerInteraction(envelope = {}) {
|
|
172
|
+
if (canAnswerInteraction(envelope)) return;
|
|
173
|
+
const who = envelope.origin || "unknown";
|
|
174
|
+
throw new Error(
|
|
175
|
+
`origin "${who}" is not authorized to answer interaction requests`,
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
157
179
|
/**
|
|
158
180
|
* Throw a clear, log-safe error when an envelope is NOT allowed to approve.
|
|
159
181
|
* Callers gate every "resolve a permission" seam through this so the rule
|
package/src/lib/agent-core.js
CHANGED
|
@@ -12,6 +12,7 @@ export {
|
|
|
12
12
|
getAgentToolDefinitions,
|
|
13
13
|
getAgentToolDescriptors,
|
|
14
14
|
getCachedPython,
|
|
15
|
+
_resetCachedPythonForTests,
|
|
15
16
|
getEnvironmentInfo,
|
|
16
17
|
_environmentProcessDeps,
|
|
17
18
|
_agentToolProcessDeps,
|
|
@@ -51,5 +52,7 @@ export {
|
|
|
51
52
|
_resetFileFreshness,
|
|
52
53
|
_getSharedCodeIntel,
|
|
53
54
|
disposeSharedCodeIntel,
|
|
55
|
+
emitToolHookLifecycle,
|
|
56
|
+
emitToolBatchHookLifecycle,
|
|
54
57
|
_resetSubtreeInstructionLoaders,
|
|
55
58
|
} from "../runtime/agent-core.js";
|
package/src/lib/agent-sandbox.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/** OS-isolated shell execution for the coding agent. */
|
|
2
|
+
import fs from "node:fs";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { proxyEnv } from "./sandbox-egress-proxy.js";
|
|
4
5
|
import executionBroker from "./process-execution-broker/index.js";
|
|
@@ -29,6 +30,166 @@ function resolvePolicyPaths(entries, cwd) {
|
|
|
29
30
|
});
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
function pathEntryExists(candidate, fsImpl) {
|
|
34
|
+
try {
|
|
35
|
+
fsImpl.lstatSync(candidate);
|
|
36
|
+
return true;
|
|
37
|
+
} catch (error) {
|
|
38
|
+
if (error?.code === "ENOENT" || error?.code === "ENOTDIR") return false;
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Resolve a path for policy comparison without requiring the final target to
|
|
45
|
+
* exist. Existing ancestors are resolved through symlinks/junctions before the
|
|
46
|
+
* missing suffix is appended. This is important for writes: checking only the
|
|
47
|
+
* lexical target lets `workspace/link/new-file` escape when `link` points
|
|
48
|
+
* outside the workspace.
|
|
49
|
+
*/
|
|
50
|
+
function canonicalPolicyPath(candidate, fsImpl) {
|
|
51
|
+
const absolute = path.resolve(candidate);
|
|
52
|
+
let existing = absolute;
|
|
53
|
+
const missing = [];
|
|
54
|
+
|
|
55
|
+
while (!pathEntryExists(existing, fsImpl)) {
|
|
56
|
+
const parent = path.dirname(existing);
|
|
57
|
+
if (parent === existing) {
|
|
58
|
+
throw new Error(`No existing ancestor for path: ${absolute}`);
|
|
59
|
+
}
|
|
60
|
+
missing.unshift(path.basename(existing));
|
|
61
|
+
existing = parent;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const realpath =
|
|
65
|
+
typeof fsImpl.realpathSync?.native === "function"
|
|
66
|
+
? fsImpl.realpathSync.native
|
|
67
|
+
: fsImpl.realpathSync;
|
|
68
|
+
if (typeof realpath !== "function") {
|
|
69
|
+
throw new Error("Filesystem realpath support is unavailable");
|
|
70
|
+
}
|
|
71
|
+
return path.resolve(realpath(existing), ...missing);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function pathIsWithin(candidate, root) {
|
|
75
|
+
const relative = path.relative(root, candidate);
|
|
76
|
+
return (
|
|
77
|
+
relative === "" ||
|
|
78
|
+
(relative !== ".." &&
|
|
79
|
+
!relative.startsWith(`..${path.sep}`) &&
|
|
80
|
+
!path.isAbsolute(relative))
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function normalizeWorkspaceRoots(entries, cwd) {
|
|
85
|
+
const roots =
|
|
86
|
+
Array.isArray(entries) && entries.length > 0 ? entries : [cwd];
|
|
87
|
+
return stringList(roots).map((entry) => path.resolve(cwd, entry));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Resolve and authorize one built-in agent file-tool path.
|
|
92
|
+
*
|
|
93
|
+
* The workspace roots are always allowed. A normalized sandbox policy may add
|
|
94
|
+
* explicit read/write roots and may deny narrower paths. Both existing targets
|
|
95
|
+
* and the nearest existing ancestor are realpath-resolved, so an in-workspace
|
|
96
|
+
* symlink/junction cannot redirect a read or write outside the declared roots.
|
|
97
|
+
*
|
|
98
|
+
* @returns {{
|
|
99
|
+
* ok:boolean,
|
|
100
|
+
* path?:string,
|
|
101
|
+
* canonicalPath?:string,
|
|
102
|
+
* reason?:string,
|
|
103
|
+
* error?:string
|
|
104
|
+
* }}
|
|
105
|
+
*/
|
|
106
|
+
export function resolveSandboxPolicyPath(
|
|
107
|
+
requestedPath,
|
|
108
|
+
{
|
|
109
|
+
access = "read",
|
|
110
|
+
cwd = process.cwd(),
|
|
111
|
+
workspaceRoots = null,
|
|
112
|
+
sandbox = null,
|
|
113
|
+
policy = sandbox?.policy || null,
|
|
114
|
+
fsImpl = null,
|
|
115
|
+
} = {},
|
|
116
|
+
) {
|
|
117
|
+
if (access !== "read" && access !== "write") {
|
|
118
|
+
return {
|
|
119
|
+
ok: false,
|
|
120
|
+
reason: "invalid-access",
|
|
121
|
+
error: `Unsupported filesystem access mode: ${access}`,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
if (
|
|
125
|
+
typeof requestedPath !== "string" ||
|
|
126
|
+
requestedPath.length === 0 ||
|
|
127
|
+
requestedPath.includes("\0")
|
|
128
|
+
) {
|
|
129
|
+
return {
|
|
130
|
+
ok: false,
|
|
131
|
+
reason: "invalid-path",
|
|
132
|
+
error: "A non-empty filesystem path is required",
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const resolvedCwd = path.resolve(cwd);
|
|
137
|
+
const resolvedPath = path.resolve(resolvedCwd, requestedPath);
|
|
138
|
+
const effectiveFs = fsImpl || fs;
|
|
139
|
+
const normalizedPolicy = policy || {};
|
|
140
|
+
const policyAllows =
|
|
141
|
+
access === "write"
|
|
142
|
+
? normalizedPolicy.allowWrite
|
|
143
|
+
: normalizedPolicy.allowRead;
|
|
144
|
+
const policyDenies =
|
|
145
|
+
access === "write"
|
|
146
|
+
? normalizedPolicy.denyWrite
|
|
147
|
+
: normalizedPolicy.denyRead;
|
|
148
|
+
const allowedInputs = [
|
|
149
|
+
...normalizeWorkspaceRoots(workspaceRoots, resolvedCwd),
|
|
150
|
+
...resolvePolicyPaths(policyAllows, resolvedCwd),
|
|
151
|
+
];
|
|
152
|
+
const deniedInputs = resolvePolicyPaths(policyDenies, resolvedCwd);
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
const canonicalPath = canonicalPolicyPath(resolvedPath, effectiveFs);
|
|
156
|
+
const allowedRoots = allowedInputs.map((root) =>
|
|
157
|
+
canonicalPolicyPath(root, effectiveFs),
|
|
158
|
+
);
|
|
159
|
+
if (!allowedRoots.some((root) => pathIsWithin(canonicalPath, root))) {
|
|
160
|
+
return {
|
|
161
|
+
ok: false,
|
|
162
|
+
path: resolvedPath,
|
|
163
|
+
canonicalPath,
|
|
164
|
+
reason: "outside-workspace",
|
|
165
|
+
error: `${access} path resolves outside the allowed workspace roots`,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const deniedRoots = deniedInputs.map((root) =>
|
|
170
|
+
canonicalPolicyPath(root, effectiveFs),
|
|
171
|
+
);
|
|
172
|
+
if (deniedRoots.some((root) => pathIsWithin(canonicalPath, root))) {
|
|
173
|
+
return {
|
|
174
|
+
ok: false,
|
|
175
|
+
path: resolvedPath,
|
|
176
|
+
canonicalPath,
|
|
177
|
+
reason: "denied-by-policy",
|
|
178
|
+
error: `${access} path is denied by the sandbox filesystem policy`,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return { ok: true, path: resolvedPath, canonicalPath };
|
|
183
|
+
} catch (error) {
|
|
184
|
+
return {
|
|
185
|
+
ok: false,
|
|
186
|
+
path: resolvedPath,
|
|
187
|
+
reason: "realpath-failed",
|
|
188
|
+
error: `Unable to safely resolve filesystem path: ${error.message}`,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
32
193
|
export function normalizeSandboxPolicy(settings = {}, cwd = process.cwd()) {
|
|
33
194
|
const filesystem = settings.filesystem || {};
|
|
34
195
|
const network = settings.network || {};
|
|
@@ -48,6 +48,14 @@ function normalizeJitterMs(v) {
|
|
|
48
48
|
return Number.isFinite(n) && n > 0 ? n : 0;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
function normalizeMonitorWorkspaceCwd(value) {
|
|
52
|
+
if (value == null) return null;
|
|
53
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
54
|
+
throw new Error("monitor workspaceCwd must be a non-empty string");
|
|
55
|
+
}
|
|
56
|
+
return path.resolve(value);
|
|
57
|
+
}
|
|
58
|
+
|
|
51
59
|
/**
|
|
52
60
|
* A per-task execution policy for wakeup/cron entries — how the spawned
|
|
53
61
|
* `cc agent` run should behave when this entry fires. Each field maps to a real
|
|
@@ -388,6 +396,7 @@ export class AgentScheduleStore {
|
|
|
388
396
|
|
|
389
397
|
createMonitor({
|
|
390
398
|
command,
|
|
399
|
+
workspaceCwd = null,
|
|
391
400
|
watchFile = null,
|
|
392
401
|
watchUrl = null,
|
|
393
402
|
watchChange = false,
|
|
@@ -443,16 +452,22 @@ export class AgentScheduleStore {
|
|
|
443
452
|
if (stopWhen != null) {
|
|
444
453
|
// Validate the regex up-front so a bad pattern errors at creation, not
|
|
445
454
|
// silently at the first check.
|
|
446
|
-
|
|
455
|
+
|
|
447
456
|
new RegExp(stopWhen);
|
|
448
457
|
}
|
|
449
458
|
const now = this._now();
|
|
450
459
|
const source = hasFile ? "file" : hasUrl ? "http" : "command";
|
|
460
|
+
const normalizedWorkspaceCwd = hasCommand
|
|
461
|
+
? normalizeMonitorWorkspaceCwd(workspaceCwd)
|
|
462
|
+
: null;
|
|
451
463
|
const entry = {
|
|
452
464
|
id: randomUUID(),
|
|
453
465
|
kind: "monitor",
|
|
454
466
|
source,
|
|
455
467
|
command: hasCommand ? command : null,
|
|
468
|
+
...(normalizedWorkspaceCwd
|
|
469
|
+
? { workspaceCwd: normalizedWorkspaceCwd }
|
|
470
|
+
: {}),
|
|
456
471
|
watchFile: hasFile ? watchFile : null,
|
|
457
472
|
watchUrl: hasUrl ? watchUrl : null,
|
|
458
473
|
watchChange: hasFile ? Boolean(watchChange) : false,
|
|
@@ -513,28 +528,36 @@ export class AgentScheduleStore {
|
|
|
513
528
|
const now = atMs != null ? Number(atMs) : this._now();
|
|
514
529
|
const ttl = Math.max(1000, Number(leaseMs) || 120000);
|
|
515
530
|
this._ensureDir();
|
|
516
|
-
return withFileLock(
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
const
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
531
|
+
return withFileLock(
|
|
532
|
+
path.join(this.dir, ".agenda-claims"),
|
|
533
|
+
() => {
|
|
534
|
+
const claimed = [];
|
|
535
|
+
for (const kind of SCHEDULE_KINDS) {
|
|
536
|
+
const entries = this._readAll(kind);
|
|
537
|
+
let changed = false;
|
|
538
|
+
for (const entry of entries) {
|
|
539
|
+
if (!isSchedulableStatus(entry) || isEntryExpired(entry, now))
|
|
540
|
+
continue;
|
|
541
|
+
if (hasLiveExecutionLease(entry, now)) continue;
|
|
542
|
+
const fireAt = effectiveFireAt(entry);
|
|
543
|
+
if (fireAt == null || fireAt > now) continue;
|
|
544
|
+
entry.executionLease = {
|
|
545
|
+
owner: `${process.pid}:${randomUUID()}`,
|
|
546
|
+
claimedAt: now,
|
|
547
|
+
expiresAt: now + ttl,
|
|
548
|
+
};
|
|
549
|
+
claimed.push({
|
|
550
|
+
...entry,
|
|
551
|
+
executionLease: { ...entry.executionLease },
|
|
552
|
+
});
|
|
553
|
+
changed = true;
|
|
554
|
+
}
|
|
555
|
+
if (changed) this._writeAll(kind, entries);
|
|
533
556
|
}
|
|
534
|
-
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
|
|
557
|
+
return claimed;
|
|
558
|
+
},
|
|
559
|
+
{ failIfUnavailable: true },
|
|
560
|
+
);
|
|
538
561
|
}
|
|
539
562
|
|
|
540
563
|
/** Release a failed/aborted claim so a later runner can retry it. */
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
* status panel. A total-time / total-task budget bounds a runaway graph.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
import { emitHooksV2Event } from "../hooks-v2-producers.js";
|
|
18
|
+
|
|
17
19
|
export class TeamRunner {
|
|
18
20
|
/**
|
|
19
21
|
* @param {TaskLeaseRegistry} registry
|
|
@@ -33,6 +35,8 @@ export class TeamRunner {
|
|
|
33
35
|
// Lease-renewal heartbeat cadence while a task runs (default ttl/3).
|
|
34
36
|
this.renewEveryMs = opts.renewEveryMs;
|
|
35
37
|
this.onEvent = typeof opts.onEvent === "function" ? opts.onEvent : () => {};
|
|
38
|
+
this.emitHook =
|
|
39
|
+
typeof opts.emitHook === "function" ? opts.emitHook : emitHooksV2Event;
|
|
36
40
|
this.maxTasks = opts.maxTasks > 0 ? opts.maxTasks : 1000;
|
|
37
41
|
this._now = opts.now || registry._now || (() => Date.now());
|
|
38
42
|
// Team-wide token/USD/time/task budget (null → unbounded). Consulted before
|
|
@@ -80,8 +84,26 @@ export class TeamRunner {
|
|
|
80
84
|
return m;
|
|
81
85
|
}
|
|
82
86
|
if (m.state === state) return m; // no transition
|
|
87
|
+
const previousState = m.state;
|
|
83
88
|
m.state = state;
|
|
84
89
|
this._emit("teammate:state", { holder, state, ...extra });
|
|
90
|
+
// Initial registration starts in `idle`; the hook is reserved for a real
|
|
91
|
+
// transition back to idle after a teammate has participated in the run.
|
|
92
|
+
if (state === "idle" && previousState !== null) {
|
|
93
|
+
try {
|
|
94
|
+
this.emitHook("TeammateIdle", {
|
|
95
|
+
schema_version: 1,
|
|
96
|
+
holder,
|
|
97
|
+
state,
|
|
98
|
+
previous_state: previousState,
|
|
99
|
+
completed: m.completed,
|
|
100
|
+
failed: m.failed,
|
|
101
|
+
...extra,
|
|
102
|
+
});
|
|
103
|
+
} catch {
|
|
104
|
+
/* hook observer is best-effort */
|
|
105
|
+
}
|
|
106
|
+
}
|
|
85
107
|
return m;
|
|
86
108
|
}
|
|
87
109
|
|
|
@@ -40,6 +40,41 @@ export const MAX_ARTIFACT_BYTES = 100 * 1024 * 1024; // 100 MB
|
|
|
40
40
|
/** Default retention before `clean` removes an artifact. */
|
|
41
41
|
export const DEFAULT_TTL_DAYS = 30;
|
|
42
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Metadata safe to return across the agent/session protocol boundary.
|
|
45
|
+
*
|
|
46
|
+
* The persisted index deliberately retains sourcePath for local artifact
|
|
47
|
+
* management, but absolute source paths are host details and must not enter
|
|
48
|
+
* model transcripts or remote-session payloads.
|
|
49
|
+
*/
|
|
50
|
+
export function publicArtifactMetadata(entry) {
|
|
51
|
+
if (!entry || typeof entry !== "object") return null;
|
|
52
|
+
const {
|
|
53
|
+
id,
|
|
54
|
+
title,
|
|
55
|
+
kind,
|
|
56
|
+
mime,
|
|
57
|
+
size,
|
|
58
|
+
sha256,
|
|
59
|
+
file,
|
|
60
|
+
sessionId,
|
|
61
|
+
createdAt,
|
|
62
|
+
expiresAt,
|
|
63
|
+
} = entry;
|
|
64
|
+
return {
|
|
65
|
+
id,
|
|
66
|
+
title,
|
|
67
|
+
kind,
|
|
68
|
+
mime,
|
|
69
|
+
size,
|
|
70
|
+
sha256,
|
|
71
|
+
file,
|
|
72
|
+
sessionId,
|
|
73
|
+
createdAt,
|
|
74
|
+
expiresAt,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
43
78
|
const MIME_BY_EXT = Object.freeze({
|
|
44
79
|
".md": "text/markdown",
|
|
45
80
|
".markdown": "text/markdown",
|
|
@@ -32,7 +32,10 @@
|
|
|
32
32
|
* testable with fake child processes (no real shell).
|
|
33
33
|
*/
|
|
34
34
|
|
|
35
|
-
const {
|
|
35
|
+
const {
|
|
36
|
+
tryParseDecision,
|
|
37
|
+
resolveHookSandboxPolicy,
|
|
38
|
+
} = require("./hook-runner.cjs");
|
|
36
39
|
|
|
37
40
|
const DEFAULT_TIMEOUT_MS = 60000;
|
|
38
41
|
const MAX_TIMEOUT_MS = 600000;
|
|
@@ -359,6 +362,7 @@ class AsyncHookSupervisor {
|
|
|
359
362
|
|
|
360
363
|
let child;
|
|
361
364
|
try {
|
|
365
|
+
const sandboxPolicy = resolveHookSandboxPolicy(hook, opts);
|
|
362
366
|
const spawnOptions = {
|
|
363
367
|
cwd: opts.cwd || process.cwd(),
|
|
364
368
|
shell: true,
|
|
@@ -370,6 +374,7 @@ class AsyncHookSupervisor {
|
|
|
370
374
|
...process.env,
|
|
371
375
|
CLAUDE_HOOK_EVENT: hook.event || payload.hook_event_name || "",
|
|
372
376
|
},
|
|
377
|
+
...(sandboxPolicy ? { sandboxPolicy } : {}),
|
|
373
378
|
};
|
|
374
379
|
if (typeof this._deps.run !== "function") {
|
|
375
380
|
throw new Error("async hook process runner unavailable");
|
|
@@ -384,10 +389,15 @@ class AsyncHookSupervisor {
|
|
|
384
389
|
pluginSource: hook.pluginSource || null,
|
|
385
390
|
});
|
|
386
391
|
} catch (err) {
|
|
392
|
+
const sandboxDenied =
|
|
393
|
+
err?.code === "ERR_PROCESS_SANDBOX_BOUNDARY_UNSATISFIED";
|
|
387
394
|
this._record(hook, {
|
|
388
395
|
ok: false,
|
|
389
396
|
exitCode: null,
|
|
390
|
-
error:
|
|
397
|
+
error: sandboxDenied
|
|
398
|
+
? `hook sandbox denied: ${err.message}`
|
|
399
|
+
: `hook spawn failed: ${err.message}`,
|
|
400
|
+
sandboxDenied,
|
|
391
401
|
started,
|
|
392
402
|
});
|
|
393
403
|
return;
|
|
@@ -483,6 +493,7 @@ class AsyncHookSupervisor {
|
|
|
483
493
|
error: fields.error || null,
|
|
484
494
|
additionalContext: fields.additionalContext || null,
|
|
485
495
|
blocked: !!fields.blocked,
|
|
496
|
+
...(fields.sandboxDenied === true ? { sandboxDenied: true } : {}),
|
|
486
497
|
asyncRewake: hook.asyncRewake === true,
|
|
487
498
|
ts: now,
|
|
488
499
|
ms: fields.started != null ? now - fields.started : 0,
|
package/src/lib/audit-mtc.js
CHANGED
|
@@ -322,11 +322,12 @@ export function closeBatch(dir, opts = {}) {
|
|
|
322
322
|
// across processes. Without it, two concurrent closes (e.g. overlapping
|
|
323
323
|
// `cc audit mtc reconcile` runs) both scan the same staging events, allocate
|
|
324
324
|
// the same batch id, and the defensive rmSync(finalDir) lets the second
|
|
325
|
-
// silently overwrite the first's audit batch.
|
|
326
|
-
//
|
|
325
|
+
// silently overwrite the first's audit batch. Audit ledger state is critical:
|
|
326
|
+
// bounded contention must fail closed rather than assemble an unlocked batch.
|
|
327
327
|
ensureDirs(dir);
|
|
328
328
|
return withFileLock(batchesDir(dir), () => _closeBatchImpl(dir, opts), {
|
|
329
329
|
timeoutMs: 15000,
|
|
330
|
+
failIfUnavailable: true,
|
|
330
331
|
});
|
|
331
332
|
}
|
|
332
333
|
|