chainlesschain 0.165.6 → 0.165.8
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 +2 -1
- package/src/assets/web-panel/assets/{AIOps-vfoDb6HZ.js → AIOps-B3gWmXjo.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-Cm5f7p93.js → ActionButton-G9pdT-0e.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-yRuvgWxa.js → Analytics-Ca30J7m2.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-BROsC4h1.js → AppLayout-BtVTm8PU.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-CimHApb1.js → Artifacts-BhViNa6u.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-DI8kr8zI.js → Audit-DhKq-FnY.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DSLzKy-n.js → BackgroundAgents-BL0SVbnE.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-DkH_n2r1.js → Backup-BWkblnFi.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-CKSrUoRA.js → BaseInput-ClaRNrF8.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-ClwfMXUS.js → Chat-sZE2Z77o.js} +4 -4
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CjMaqfL7.js → ChatBubbleRenderer-BAfKOnRe.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-BYTehcQG.js → Checkbox-Cvhay5WM.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-B8AMcp6J.js → Codegen-BpejL-4N.js} +1 -1
- package/src/assets/web-panel/assets/{Col-BNSogPo3.js → Col-g2Ki6g_1.js} +1 -1
- package/src/assets/web-panel/assets/{Community-JxPvGb8O.js → Community-D2xKbNo9.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DF7bFAgE.js → Compact-DbL1Pds3.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-Bvhqnwrq.js → Compliance-DGtZCV4c.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-BDS0CJvM.js → Cowork-4kQpoNsI.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-DqvRfxoQ.js → Cron-BxTYXXAN.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CDcIvnqS.js → Crosschain-k0J0LT2N.js} +1 -1
- package/src/assets/web-panel/assets/{DID-D7jaUxU3.js → DID-BaqhoPgN.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-B5A18wEV.js → Dashboard-T4RVPIM1.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-_6IVkGag.js → Dropdown-DszOToWq.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-C9PeiKCG.js → EmailListRenderer-C9KJU7HF.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DXjuEHrX.js → FamilyGuardDashboard-Cmr0JnsA.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-B4IAR9zv.js → Federation-BI-_2xZX.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-CxQeSNx1.js → FormItemContext-DsnDEPsl.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-B8GS-Y3N.js → GenericCardRenderer-BLncAKKK.js} +1 -1
- package/src/assets/web-panel/assets/{Git-BS8SouUX.js → Git-BPQhGXDn.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-Dq9aYb5Q.js → Governance-CyElbUQW.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BrCEe9AJ.js → Inference-CcSntBQD.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DybOpiY2.js → KnowledgeGraph-p6e7HZ2r.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-DBpzbRfx.js → Logs-CNEtr-wz.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-Bj9xI0YH.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-Cc7CCSCu.js → Marketplace-Dd2notAJ.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DFaIhOfu.js → McpTools-BBsN2CSW.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-KCqlp9ol.js → Memory-Dg2uTvwx.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-Bys84ySN.js → MobileBridge-r1YMRiJV.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-B-6qU-je.js → MobileProjects-C-89kSm4.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-BgY-fvCq.js → Mtc-CrPZcVgf.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-B8pCmqQJ.js → MtcAudit-sxi7hqJb.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-BbOmYutA.js → Multisig-CAgOMfF1.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-BocLQz_M.js → NLProgramming-DafaPts3.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-CSwbxEop.js → Notes-CJM-xUW_.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-CqFNSYG3.js → NotificationSettings-L0ZjfAh_.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-C6gMfAk7.js → OrderTableRenderer-BB1CvCK0.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-QrDXVdMJ.js → Organization-DeLtgAD8.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Cxntotjt.js → Overflow-CKC2b10z.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CIdBOwNq.js → P2P-eyf2rzY1.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-CT5aP8rD.js → PdhVaultBrowser-5upNIOW8.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-DH7OM8XU.js → Permissions-B8p3W6JK.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-CnJqbWce.js → PersonalDataHub-BnRMxTq3.js} +5 -5
- package/src/assets/web-panel/assets/{Pipeline-5C3HG1kH.js → Pipeline-DjCNI1li.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-B4yIp7xK.js → Privacy-u6gXLbWT.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BMvt-2M0.js → ProjectInit-BZAw4tkM.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CvSTEMRG.js → ProjectSettings-B1Tr72q7.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-BKBJxEek.js → Projects-DO7HFuBQ.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-BdwUqFWN.js → Providers-BjCztyhj.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-DtnCKlTm.js → QrScannerModal-ZWyCUbR1.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-sTbgwyNr.js → QuickAsk-DhDjeW4G.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Bzr14gSb.js → Recommend-R_CN2MuU.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-C_TF5IaJ.js → RemoteSession-uxFcujeu.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-GCAM4H2K.js → Reputation-DX8D7rks.js} +1 -1
- package/src/assets/web-panel/assets/{Row-Dir0r6OQ.js → Row-BYahQILD.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CpGnlecX.js → RssFeed-CUSQ2tm-.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DMMamC6u.js → Search-CnN_S8Cs.js} +1 -1
- package/src/assets/web-panel/assets/{Security-yqay5yG-.js → Security-DcZlh-O4.js} +4 -4
- package/src/assets/web-panel/assets/{Services-C5i2wh9G.js → Services-ZhBOjzIX.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-vUqk35yj.js → Skeleton-D5Qnq_lI.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-DzcSkhot.js → Skills-BC9cZ3Be.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-CB6qbYNr.js → Sla-DauJ3E8_.js} +1 -1
- package/src/assets/web-panel/assets/SpeechSettings-DbNeZ_fh.js +1 -0
- package/src/assets/web-panel/assets/{SyncSettings-D-RrsxTJ.js → SyncSettings-DUvJbSct.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-DFxdOJiq.js → Tasks-BXa-5noQ.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-SKAob_Aq.js → Templates-JxaiUt_3.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-BPfsfHQ-.js → Tenant-BW4ERQN8.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-8iw7FpUf.js → Terminal-DltUbdtv.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-C4Gjj5Su.js → TimelineRenderer-CMoZz0Tc.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-COYhN18e.js → Tokens-D_VEV60K.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-B-JzXcf6.js → Trigger-CCXTCs0R.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-BJ5bg0nI.js → Trust-lkGRIPcG.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-BG_ByRMf.js → UkeySign-BfGeQ9HX.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-B3kOnSiU.js → VideoEditing-BEC7pYvc.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-CcoGFnK7.js → Wallet-BZdG24o0.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DdT8vRC_.js → WebAuthn-yoEddedp.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-CZu3M9N8.js → WorkflowEditor-BXZEprOW.js} +1 -1
- package/src/assets/web-panel/assets/{chat-DxJt3Qba.js → chat-gg0bzZal.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DdYfwJaB.js → colors-DjRVRuin.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BG3SUzwj.js → compact-item-su-dieAc.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-By51z2-1.js → createContext-Ci3S8oKF.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-CxbFX9uH.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-B0apZ3KJ.js → hasIn-D8F10heH.js} +1 -1
- package/src/assets/web-panel/assets/{index-DE76D-kA.js → index-11wtYQiF.js} +1 -1
- package/src/assets/web-panel/assets/{index-BkvcEo4p.js → index-1IgxgALJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bos5_aMV.js → index-1agckWSq.js} +1 -1
- package/src/assets/web-panel/assets/{index-BfWYsB9t.js → index-5JqhujnR.js} +1 -1
- package/src/assets/web-panel/assets/{index-CAhHirVH.js → index-6Tniqk1s.js} +1 -1
- package/src/assets/web-panel/assets/{index-BYINoRLK.js → index-8Z-8BIlN.js} +1 -1
- package/src/assets/web-panel/assets/{index-B5rLiEo0.js → index-BCI5v0yB.js} +1 -1
- package/src/assets/web-panel/assets/{index-BZ_0qm4g.js → index-BDJntYmJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CWEuZWCK.js → index-BGzixOGZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BLIbGOLX.js → index-BMMOVoLD.js} +1 -1
- package/src/assets/web-panel/assets/{index-bP_VlDb4.js → index-BTFpdBtt.js} +1 -1
- package/src/assets/web-panel/assets/{index-B3rWuPMW.js → index-Ba_HyPnE.js} +1 -1
- package/src/assets/web-panel/assets/{index-Da_WBdLX.js → index-BbF1IHof.js} +1 -1
- package/src/assets/web-panel/assets/{index-RD6O-0C6.js → index-BgT9su_e.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpjZhgNd.js → index-BzPB6kGZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-Q2SCX-MI.js → index-C6ygzplr.js} +1 -1
- package/src/assets/web-panel/assets/{index-BIrJfqO4.js → index-CC3ZDjzY.js} +1 -1
- package/src/assets/web-panel/assets/{index-BBPf3TpM.js → index-CEmXRhAE.js} +1 -1
- package/src/assets/web-panel/assets/index-CJGOlduY.js +1 -0
- package/src/assets/web-panel/assets/{index-Cp6e-hGw.js → index-CMPqd5Cv.js} +1 -1
- package/src/assets/web-panel/assets/{index-kf57LJ93.js → index-COWd8uGx.js} +1 -1
- package/src/assets/web-panel/assets/{index-CW93tZDv.js → index-CPIYSp4H.js} +1 -1
- package/src/assets/web-panel/assets/{index-BewKYrX9.js → index-CR0h6seT.js} +1 -1
- package/src/assets/web-panel/assets/{index-p1_8SbI1.js → index-CUmDhC4j.js} +1 -1
- package/src/assets/web-panel/assets/index-CkBCN5yH.js +1 -0
- package/src/assets/web-panel/assets/{index-ZxtP8jG7.js → index-CusgZPtc.js} +1 -1
- package/src/assets/web-panel/assets/{index-BWF8_mkx.js → index-DBAETXft.js} +1 -1
- package/src/assets/web-panel/assets/{index-BP94CrBV.js → index-DIJ2qFOC.js} +1 -1
- package/src/assets/web-panel/assets/{index-CNIxXMmN.js → index-Dbq4NMET.js} +1 -1
- package/src/assets/web-panel/assets/{index-CzmQElZy.js → index-DkMEF5VT.js} +1 -1
- package/src/assets/web-panel/assets/{index-ZFbps9po.js → index-DkfQR3hM.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dz49VOyQ.js → index-DnLucOn9.js} +1 -1
- package/src/assets/web-panel/assets/{index-oxRrmFO9.js → index-DugB_aKa.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bissefox.js → index-DyLUarhZ.js} +3 -3
- package/src/assets/web-panel/assets/{index-DaIz0NAW.js → index-T6_6ygJZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-SQqOlR3d.js → index-Tu8eWqh-.js} +1 -1
- package/src/assets/web-panel/assets/{index-DCn8IcxV.js → index-W7XUgdVL.js} +1 -1
- package/src/assets/web-panel/assets/{index-3jWkIu5j.js → index-dHZinfko.js} +1 -1
- package/src/assets/web-panel/assets/{index-C1C9i79A.js → index-jyNgp5FI.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-BWJktcg8.js → initDefaultProps-Cv4p8e4w.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BEXBzUFV.js → motion-B8EwmMOw.js} +1 -1
- package/src/assets/web-panel/assets/{move-BUKwn2sx.js → move-B8R9F8TK.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-FTI7btqQ.js → mtc-parser-DoFYz5Bp.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CsLtSPH3.js → omit-CHWYLBjI.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DWZxsT_S.js → pickAttrs-CXuPDO77.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-Bcfs43CX.js → placementArrow-BaAtUUon.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-a9bcC1p-.js → responsiveObserve-DCc4zcDD.js} +1 -1
- package/src/assets/web-panel/assets/{slide-BDTzgOXN.js → slide-B_lx89oZ.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-Iq1j_HUg.js → statusUtils-DE8DPmR0.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-DAZEYxeh.js → styleChecker-1ktXOsL_.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-DVkjyDrh.js → useFlexGapSupport-xH89-wjh.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-wXTpNTHt.js → useFs-DscvfW5p.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-CtQM_aZr.js → usePersonalDataHub-RdMKQta7.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-hjEoG85v.js → vnode-Z3wTni2T.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-BHVpyKg_.js → zoom-B0iChCsm.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +3 -3
- package/src/commands/agent.js +91 -60
- package/src/commands/git.js +39 -0
- package/src/commands/plugin.js +17 -2
- package/src/commands/session-group.js +131 -0
- package/src/commands/session-location.js +48 -0
- package/src/commands/session.js +11 -0
- package/src/commands/sync-providers.js +4 -1
- package/src/commands/update.js +1 -0
- package/src/data/changelog.json +27 -1
- package/src/gateways/ws/ws-agent-handler.js +20 -12
- package/src/harness/jsonl-session-store.js +279 -37
- package/src/harness/mcp-client.js +701 -91
- package/src/harness/session-index.js +15 -4
- package/src/lib/agent-worktree.js +8 -1
- package/src/lib/auto-mode-safety-classifier.js +3 -17
- package/src/lib/background-agent-keeper-protocol.js +26 -6
- package/src/lib/background-agent-supervisor.js +17 -1
- package/src/lib/browser-evidence.js +1405 -0
- package/src/lib/chrome-connector.js +465 -79
- package/src/lib/claude-project-auto-memory.js +481 -0
- package/src/lib/claude-project-storage-layout.js +104 -0
- package/src/lib/cloud/cloud-client.js +40 -0
- package/src/lib/execution-location-local-supervisor.mjs +226 -0
- package/src/lib/execution-location-runner-lifecycle.js +991 -0
- package/src/lib/execution-location-target-preflight.js +333 -0
- package/src/lib/execution-location-target.js +783 -13
- package/src/lib/file-lines.js +6 -1
- package/src/lib/gateway-client-resilience.js +571 -0
- package/src/lib/gitlab-mr-worktree.js +176 -0
- package/src/lib/hooks-v2-producers.js +119 -15
- package/src/lib/hooks-v2-workspace-context.js +44 -1
- package/src/lib/host-resource-budget.js +295 -0
- package/src/lib/ide-context.js +15 -2
- package/src/lib/llm-config-defaults.js +43 -0
- package/src/lib/mcp-lifecycle-authority.js +887 -0
- package/src/lib/mcp-oauth.js +101 -20
- package/src/lib/mcp-tls.js +103 -3
- package/src/lib/paths.js +260 -32
- package/src/lib/permission-request.js +48 -0
- package/src/lib/plugin-runtime/bin.js +3 -1
- package/src/lib/plugin-runtime/hooks.js +3 -1
- package/src/lib/plugin-runtime/install.js +117 -1
- package/src/lib/plugin-runtime/lsp.js +4 -4
- package/src/lib/plugin-runtime/marketplace-archive-source.js +40 -5
- package/src/lib/plugin-runtime/marketplace-catalog.js +13 -2
- package/src/lib/plugin-runtime/marketplace-command-descriptor.js +343 -0
- package/src/lib/plugin-runtime/marketplace-command-source.js +580 -0
- package/src/lib/plugin-runtime/marketplace-source-adapter.js +33 -8
- package/src/lib/plugin-runtime/mcp.js +3 -1
- package/src/lib/plugin-runtime/monitors.js +3 -1
- package/src/lib/plugin-runtime/remote-source.js +151 -6
- package/src/lib/plugin-runtime/settings.js +3 -1
- package/src/lib/plugin-runtime/trust.js +274 -13
- package/src/lib/process-execution-broker/credential-agent.js +210 -41
- package/src/lib/process-execution-broker/index.js +15 -1
- package/src/lib/process-execution-broker/linux-cgroup-v2.js +391 -0
- package/src/lib/process-execution-broker/platform-sandbox.js +50 -28
- package/src/lib/project-mcp-trust.js +165 -10
- package/src/lib/resume-session.js +9 -6
- package/src/lib/session-core-singletons.js +26 -11
- package/src/lib/session-host-lease.js +52 -16
- package/src/lib/session-lifecycle-scope.js +153 -0
- package/src/lib/session-message-fabric.js +168 -21
- package/src/lib/session-projection.js +244 -4
- package/src/lib/session-store-guard.js +3 -1
- package/src/lib/session-workbench-store.js +466 -0
- package/src/lib/spellcheck.js +211 -0
- package/src/lib/sub-agent-context.js +9 -9
- package/src/lib/sync-cli-db.js +485 -129
- package/src/lib/sync-credentials.js +31 -20
- package/src/lib/web-fetch.js +112 -40
- package/src/lib/web-search.js +127 -61
- package/src/lib/workspace-trust.js +793 -0
- package/src/repl/agent-repl.js +124 -5
- package/src/repl/permission-prompt.js +10 -12
- package/src/runtime/agent-core.js +311 -18
- package/src/runtime/bootstrap.js +37 -13
- package/src/runtime/coding-agent-contract-shared.cjs +11 -4
- package/src/runtime/headless-runner.js +234 -36
- package/src/runtime/headless-stream.js +181 -6
- package/src/runtime/mcp-config.js +298 -8
- package/src/runtime/policies/agent-policy.js +8 -0
- package/src/runtime/status-diagnostics-lite.js +9 -1
- package/src/assets/web-panel/assets/MarkdownRenderer-CFyt8iUd.js +0 -1
- package/src/assets/web-panel/assets/SpeechSettings-BHUI7cox.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DorRZcI9.js +0 -1
- package/src/assets/web-panel/assets/index-BETiL0a3.js +0 -1
- package/src/assets/web-panel/assets/index-BhAVHuW8.js +0 -1
package/src/repl/agent-repl.js
CHANGED
|
@@ -119,6 +119,7 @@ import {
|
|
|
119
119
|
} from "../lib/task-model-selector.js";
|
|
120
120
|
import { runnableTaskModel, hasUsableKey } from "../lib/runnable-provider.js";
|
|
121
121
|
import { CLIPermanentMemory } from "../lib/permanent-memory.js";
|
|
122
|
+
import { resolveClaudeProjectAutoMemory } from "../lib/claude-project-auto-memory.js";
|
|
122
123
|
import { CLIAutonomousAgent, GoalStatus } from "../lib/autonomous-agent.js";
|
|
123
124
|
import {
|
|
124
125
|
estimateMessagesTokens,
|
|
@@ -2845,6 +2846,46 @@ export function startReplJsonlSession(
|
|
|
2845
2846
|
}
|
|
2846
2847
|
}
|
|
2847
2848
|
|
|
2849
|
+
/**
|
|
2850
|
+
* Resolve the automatic-memory location at the same lifecycle boundary that
|
|
2851
|
+
* opens the durable REPL session. This is intentionally exported as a narrow
|
|
2852
|
+
* test seam; startAgentReplInWorkspaceOwned consumes it below rather than
|
|
2853
|
+
* letting a standalone helper drift away from real session behavior.
|
|
2854
|
+
*/
|
|
2855
|
+
export function resolveReplAutomaticMemoryPlan(
|
|
2856
|
+
options = {},
|
|
2857
|
+
cwd = process.cwd(),
|
|
2858
|
+
) {
|
|
2859
|
+
return resolveClaudeProjectAutoMemory({
|
|
2860
|
+
cwd,
|
|
2861
|
+
launchEnv: options.claudeStorageLaunchEnv || undefined,
|
|
2862
|
+
});
|
|
2863
|
+
}
|
|
2864
|
+
|
|
2865
|
+
/**
|
|
2866
|
+
* Resolve the concrete permanent-memory backend used by the live REPL. Claude
|
|
2867
|
+
* project mode is deliberately file-only: the legacy bootstrap SQLite DB is
|
|
2868
|
+
* process/global state and would otherwise let project A retrieve facts that
|
|
2869
|
+
* project B summarized. Legacy mode retains its historical DB behavior.
|
|
2870
|
+
*/
|
|
2871
|
+
export function resolveReplPermanentMemoryStorage(
|
|
2872
|
+
options = {},
|
|
2873
|
+
db = null,
|
|
2874
|
+
cwd = process.cwd(),
|
|
2875
|
+
) {
|
|
2876
|
+
const automaticMemory = resolveReplAutomaticMemoryPlan(options, cwd);
|
|
2877
|
+
if (!automaticMemory.enabled) return null;
|
|
2878
|
+
const dataDir = process.env.CHAINLESSCHAIN_DATA_DIR || cwd;
|
|
2879
|
+
return Object.freeze({
|
|
2880
|
+
db: automaticMemory.mode === "project" ? null : db,
|
|
2881
|
+
memoryDir:
|
|
2882
|
+
automaticMemory.mode === "project"
|
|
2883
|
+
? automaticMemory.memoryDir
|
|
2884
|
+
: path.join(dataDir, "memory"),
|
|
2885
|
+
automaticMemory,
|
|
2886
|
+
});
|
|
2887
|
+
}
|
|
2888
|
+
|
|
2848
2889
|
/** Start the agentic REPL with non-overridable production bindings. */
|
|
2849
2890
|
export async function startAgentRepl(options = {}) {
|
|
2850
2891
|
const sessionHostLeaseScope = { lease: null };
|
|
@@ -3344,10 +3385,15 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
3344
3385
|
// Initialize permanent memory
|
|
3345
3386
|
let permanentMemory = null;
|
|
3346
3387
|
try {
|
|
3347
|
-
const
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3388
|
+
const permanentMemoryStorage = resolveReplPermanentMemoryStorage(
|
|
3389
|
+
options,
|
|
3390
|
+
db,
|
|
3391
|
+
process.cwd(),
|
|
3392
|
+
);
|
|
3393
|
+
if (permanentMemoryStorage) {
|
|
3394
|
+
permanentMemory = new CLIPermanentMemory(permanentMemoryStorage);
|
|
3395
|
+
permanentMemory.initialize();
|
|
3396
|
+
}
|
|
3351
3397
|
} catch (_err) {
|
|
3352
3398
|
// Non-critical
|
|
3353
3399
|
}
|
|
@@ -3783,7 +3829,13 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
3783
3829
|
try {
|
|
3784
3830
|
const { getSessionManager } =
|
|
3785
3831
|
await import("../lib/session-core-singletons.js");
|
|
3786
|
-
|
|
3832
|
+
// Keep durable lifecycle sidecars on the same launch-authoritative Claude
|
|
3833
|
+
// project bucket as the JSONL transcript. Project settings may not switch
|
|
3834
|
+
// this map/path after the REPL has admitted its launch environment.
|
|
3835
|
+
_sessionMgr = getSessionManager({
|
|
3836
|
+
launchEnv: options.claudeStorageLaunchEnv || undefined,
|
|
3837
|
+
cwd: process.cwd(),
|
|
3838
|
+
});
|
|
3787
3839
|
if (sessionId) {
|
|
3788
3840
|
if (options.sessionId && !_sessionMgr.has(sessionId)) {
|
|
3789
3841
|
// Try unparking; no-op if nothing parked with that id
|
|
@@ -6312,6 +6364,73 @@ async function startAgentReplInWorkspaceOwned(
|
|
|
6312
6364
|
return;
|
|
6313
6365
|
}
|
|
6314
6366
|
|
|
6367
|
+
// `/spellcheck` uses an installed local dictionary only. It never sends
|
|
6368
|
+
// prompt text to a provider, and fenced code is suppressed by the adapter
|
|
6369
|
+
// before the executable receives it.
|
|
6370
|
+
{
|
|
6371
|
+
const {
|
|
6372
|
+
parseSpellcheckCommand,
|
|
6373
|
+
resolveSpellcheckEnabled,
|
|
6374
|
+
spellcheckText,
|
|
6375
|
+
} = await import("../lib/spellcheck.js");
|
|
6376
|
+
const spellcheck = parseSpellcheckCommand(trimmed);
|
|
6377
|
+
if (spellcheck) {
|
|
6378
|
+
let configured;
|
|
6379
|
+
try {
|
|
6380
|
+
const { getConfigValue } = await import("../lib/config-manager.js");
|
|
6381
|
+
configured = getConfigValue("cli.spellcheck");
|
|
6382
|
+
} catch {
|
|
6383
|
+
configured = undefined;
|
|
6384
|
+
}
|
|
6385
|
+
if (spellcheck.action === "on" || spellcheck.action === "off") {
|
|
6386
|
+
try {
|
|
6387
|
+
const { setConfigValue } = await import("../lib/config-manager.js");
|
|
6388
|
+
setConfigValue("cli.spellcheck", spellcheck.action === "on");
|
|
6389
|
+
} catch {
|
|
6390
|
+
// The current-session diagnostic remains useful if config storage
|
|
6391
|
+
// is unavailable; don't turn a local optional feature into a
|
|
6392
|
+
// REPL failure.
|
|
6393
|
+
}
|
|
6394
|
+
logger.info(
|
|
6395
|
+
`Spellcheck: ${spellcheck.action === "on" ? "enabled" : "disabled"}.`,
|
|
6396
|
+
);
|
|
6397
|
+
} else if (spellcheck.action === "status") {
|
|
6398
|
+
logger.info(
|
|
6399
|
+
`Spellcheck: ${
|
|
6400
|
+
resolveSpellcheckEnabled({
|
|
6401
|
+
config: { cli: { spellcheck: configured } },
|
|
6402
|
+
})
|
|
6403
|
+
? "enabled"
|
|
6404
|
+
: "disabled"
|
|
6405
|
+
}. ` + "Use /spellcheck <text> to check local prose.",
|
|
6406
|
+
);
|
|
6407
|
+
} else {
|
|
6408
|
+
try {
|
|
6409
|
+
const result = spellcheckText(spellcheck.text, {
|
|
6410
|
+
config: { cli: { spellcheck: configured } },
|
|
6411
|
+
});
|
|
6412
|
+
if (!result.enabled) {
|
|
6413
|
+
logger.info("Spellcheck is disabled.");
|
|
6414
|
+
} else if (!result.available) {
|
|
6415
|
+
logger.info(
|
|
6416
|
+
"No local spellchecker found (aspell, hunspell, or ispell).",
|
|
6417
|
+
);
|
|
6418
|
+
} else if (result.words.length === 0) {
|
|
6419
|
+
logger.info("Spellcheck: no unknown prose words.");
|
|
6420
|
+
} else {
|
|
6421
|
+
logger.info(
|
|
6422
|
+
`Spellcheck (${result.adapter}): ${result.words.join(", ")}`,
|
|
6423
|
+
);
|
|
6424
|
+
}
|
|
6425
|
+
} catch (error) {
|
|
6426
|
+
logger.error(`/spellcheck failed: ${error.message}`);
|
|
6427
|
+
}
|
|
6428
|
+
}
|
|
6429
|
+
prompt();
|
|
6430
|
+
return;
|
|
6431
|
+
}
|
|
6432
|
+
}
|
|
6433
|
+
|
|
6315
6434
|
// `/tui` — fullscreen no-flicker view (Claude-Code parity). `fullscreen`
|
|
6316
6435
|
// enters the alternate screen buffer; `default` returns to streaming
|
|
6317
6436
|
// scrollback. No arg prints the current mode. Persisted to `cli.tuiMode`.
|
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
*
|
|
15
15
|
* @returns {string} the prompt header (no styling, no trailing "Proceed?")
|
|
16
16
|
*/
|
|
17
|
+
import { normalizePermissionRequest } from "../lib/permission-request.js";
|
|
18
|
+
import { redactSecrets } from "../lib/secret-scan.js";
|
|
19
|
+
|
|
17
20
|
export function visualizePermissionText(value) {
|
|
18
21
|
return String(value ?? "").replace(
|
|
19
22
|
/[\u0000-\u001f\u007f-\u009f\u00ad\u034f\u061c\u115f\u1160\u17b4\u17b5\u180b-\u180f\u200b-\u200f\u202a-\u202e\u2060-\u206f\u3164\ufeff\uffa0]/gu,
|
|
@@ -27,23 +30,18 @@ export function visualizePermissionText(value) {
|
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
export function buildPermissionPrompt({ tool, args, rule, reason } = {}) {
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
? command
|
|
36
|
-
: source && destination
|
|
37
|
-
? `${source} -> ${destination}`
|
|
38
|
-
: source || destination;
|
|
39
|
-
const detail = rawDetail ? ` ${visualizePermissionText(rawDetail)}` : "";
|
|
33
|
+
const request = normalizePermissionRequest({ tool, args });
|
|
34
|
+
const visibleTool = visualizePermissionText(request.tool);
|
|
35
|
+
const rawDetail = request.detail;
|
|
36
|
+
const visibleDetail = visualizePermissionText(redactSecrets(rawDetail));
|
|
37
|
+
const detail = rawDetail ? ` ${visibleDetail}` : "";
|
|
40
38
|
if (rule) {
|
|
41
|
-
return `[Permission] rule "${visualizePermissionText(rule)}" asks before ${visibleTool}:${detail}`;
|
|
39
|
+
return `[Permission] rule "${visualizePermissionText(redactSecrets(String(rule)))}" asks before ${visibleTool}:${detail}`;
|
|
42
40
|
}
|
|
43
41
|
if (reason) {
|
|
44
42
|
const reasonText = String(reason);
|
|
45
43
|
const missingTarget = rawDetail && !reasonText.includes(String(rawDetail));
|
|
46
|
-
return `[Permission] ${visualizePermissionText(reasonText)}${missingTarget ? `:${detail}` : ""}`;
|
|
44
|
+
return `[Permission] ${visualizePermissionText(redactSecrets(reasonText))}${missingTarget ? `:${detail}` : ""}`;
|
|
47
45
|
}
|
|
48
46
|
return `[Permission] confirm ${visibleTool}:${detail}`;
|
|
49
47
|
}
|
|
@@ -516,6 +516,45 @@ export const _gitProcessDeps = {
|
|
|
516
516
|
run: gitProcessRunner,
|
|
517
517
|
};
|
|
518
518
|
|
|
519
|
+
function canonicalGitMetadataPath(value) {
|
|
520
|
+
const resolved = path.resolve(String(value || "").trim());
|
|
521
|
+
try {
|
|
522
|
+
const real = fs.realpathSync.native(resolved);
|
|
523
|
+
return process.platform === "win32" ? real.toLowerCase() : real;
|
|
524
|
+
} catch {
|
|
525
|
+
return null;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Distinguish the primary checkout from a linked worktree using Git's own
|
|
531
|
+
* metadata paths. Unknown/non-repository locations are deliberately not
|
|
532
|
+
* treated as linked worktrees.
|
|
533
|
+
*/
|
|
534
|
+
export function classifyGitCheckout(cwd) {
|
|
535
|
+
const query = (argument) => {
|
|
536
|
+
const result = _gitProcessDeps.run(
|
|
537
|
+
"git",
|
|
538
|
+
["rev-parse", "--path-format=absolute", argument],
|
|
539
|
+
{
|
|
540
|
+
cwd,
|
|
541
|
+
encoding: "utf8",
|
|
542
|
+
timeout: 10000,
|
|
543
|
+
windowsHide: true,
|
|
544
|
+
origin: "agent-core:git-checkout-authority",
|
|
545
|
+
policy: "allow",
|
|
546
|
+
scope: "agent-core",
|
|
547
|
+
},
|
|
548
|
+
);
|
|
549
|
+
if (result?.error || result?.status !== 0) return null;
|
|
550
|
+
return canonicalGitMetadataPath(result.stdout);
|
|
551
|
+
};
|
|
552
|
+
const gitDirectory = query("--git-dir");
|
|
553
|
+
const commonDirectory = query("--git-common-dir");
|
|
554
|
+
if (!gitDirectory || !commonDirectory) return "unknown";
|
|
555
|
+
return gitDirectory === commonDirectory ? "primary" : "linked";
|
|
556
|
+
}
|
|
557
|
+
|
|
519
558
|
function _killTask(task) {
|
|
520
559
|
const child = task?.child;
|
|
521
560
|
if (!child || child.killed || task?.status !== "running") return false;
|
|
@@ -919,6 +958,8 @@ async function requestInteractivePermission(
|
|
|
919
958
|
args && typeof args === "object" ? Object.keys(args).sort() : [],
|
|
920
959
|
reason: confirmArgs?.reason || null,
|
|
921
960
|
cwd,
|
|
961
|
+
trace_id: context.hookTraceId || null,
|
|
962
|
+
parent_id: context.hookParentId || null,
|
|
922
963
|
},
|
|
923
964
|
{ failClosed: true },
|
|
924
965
|
);
|
|
@@ -3253,25 +3294,35 @@ export async function executeTool(name, args, context = {}) {
|
|
|
3253
3294
|
// command unguarded in auto mode — including `reset --hard`, `clean -fd`,
|
|
3254
3295
|
// `restore .`, `push --force`, `branch -D`, `rebase`, `reflog expire` —
|
|
3255
3296
|
// which irrecoverably discard work. An explicit settings `allow`/confirmed
|
|
3256
|
-
// `ask`
|
|
3257
|
-
//
|
|
3297
|
+
// A confirmed `ask` pre-authorizes. A static `allow` only pre-authorizes a
|
|
3298
|
+
// linked worktree; primary/unknown checkout identity still needs a live
|
|
3299
|
+
// confirmation. Plan mode already blocks non-read-only git below.
|
|
3258
3300
|
if (
|
|
3259
3301
|
name === "git" &&
|
|
3260
|
-
!ruleAllowed &&
|
|
3261
3302
|
!planManager.isActive() &&
|
|
3262
3303
|
isDangerousGitCommand(args?.command)
|
|
3263
3304
|
) {
|
|
3264
|
-
const
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
};
|
|
3305
|
+
const checkout = classifyGitCheckout(args?.cwd || cwd);
|
|
3306
|
+
const settingsAskWasConfirmed =
|
|
3307
|
+
settingsVerdict.decision === "ask" && ruleAllowed;
|
|
3308
|
+
const linkedWorktreeWasAllowed = checkout === "linked" && ruleAllowed;
|
|
3309
|
+
if (!settingsAskWasConfirmed && !linkedWorktreeWasAllowed) {
|
|
3310
|
+
const ok = await requestInteractivePermission(name, args, context, cwd, {
|
|
3311
|
+
tool: name,
|
|
3312
|
+
args,
|
|
3313
|
+
rule: null,
|
|
3314
|
+
reason: `destructive git command in ${checkout} checkout: git ${normalizeGitCommand(args.command)}`,
|
|
3315
|
+
});
|
|
3316
|
+
if (!ok) {
|
|
3317
|
+
return {
|
|
3318
|
+
error: `[Destructive Git] "git ${normalizeGitCommand(args.command)}" targets the ${checkout} checkout, discards work irrecoverably, and requires live confirmation — denied.`,
|
|
3319
|
+
policy: {
|
|
3320
|
+
decision: "ask",
|
|
3321
|
+
via: "destructive-git",
|
|
3322
|
+
checkout,
|
|
3323
|
+
},
|
|
3324
|
+
};
|
|
3325
|
+
}
|
|
3275
3326
|
}
|
|
3276
3327
|
}
|
|
3277
3328
|
|
|
@@ -3509,6 +3560,8 @@ export async function executeTool(name, args, context = {}) {
|
|
|
3509
3560
|
input_keys:
|
|
3510
3561
|
args && typeof args === "object" ? Object.keys(args).sort() : [],
|
|
3511
3562
|
cwd,
|
|
3563
|
+
trace_id: context.hookTraceId || null,
|
|
3564
|
+
parent_id: context.hookParentId || null,
|
|
3512
3565
|
},
|
|
3513
3566
|
{ failClosed: true },
|
|
3514
3567
|
);
|
|
@@ -3660,6 +3713,7 @@ export async function executeTool(name, args, context = {}) {
|
|
|
3660
3713
|
subAgentDepth: context.subAgentDepth || 0,
|
|
3661
3714
|
subAgentBudget: context.subAgentBudget || null,
|
|
3662
3715
|
sessionBudget: context.sessionBudget || null,
|
|
3716
|
+
hostResourceBudget: context.hostResourceBudget || null,
|
|
3663
3717
|
// Effective contract of THIS loop (parent ceiling for a nested spawn) +
|
|
3664
3718
|
// the MCP tool definitions this loop exposes (inheritable by a spawn).
|
|
3665
3719
|
subAgentContract: context.subAgentContract || null,
|
|
@@ -3676,6 +3730,15 @@ export async function executeTool(name, args, context = {}) {
|
|
|
3676
3730
|
managedCheckpoint: context.managedCheckpoint === true,
|
|
3677
3731
|
fileMutationScope: context.fileMutationScope || null,
|
|
3678
3732
|
hermeticExecution: context.hermeticExecution === true,
|
|
3733
|
+
browserEvidenceBinding: context.browserEvidenceBinding || null,
|
|
3734
|
+
browserOriginGrants: context.browserOriginGrants || null,
|
|
3735
|
+
browserExpectedGrantRevisions:
|
|
3736
|
+
context.browserExpectedGrantRevisions || null,
|
|
3737
|
+
browserReplaySourceEnvelope: context.browserReplaySourceEnvelope || null,
|
|
3738
|
+
browserReplayAllowSideEffects:
|
|
3739
|
+
context.browserReplayAllowSideEffects === true,
|
|
3740
|
+
browserReplayAllowCredentials:
|
|
3741
|
+
context.browserReplayAllowCredentials === true,
|
|
3679
3742
|
});
|
|
3680
3743
|
} catch (err) {
|
|
3681
3744
|
if (
|
|
@@ -4757,9 +4820,9 @@ async function filterSkillsByCwd(skills, cwd) {
|
|
|
4757
4820
|
}
|
|
4758
4821
|
}
|
|
4759
4822
|
|
|
4760
|
-
async function
|
|
4823
|
+
async function promoteBrowserGeneratedArtifact(
|
|
4761
4824
|
filePath,
|
|
4762
|
-
{ sessionId = null, title
|
|
4825
|
+
{ sessionId = null, title, kind, failureLabel } = {},
|
|
4763
4826
|
) {
|
|
4764
4827
|
if (!filePath) return { artifact: null, error: null };
|
|
4765
4828
|
try {
|
|
@@ -4768,7 +4831,7 @@ async function promoteBrowserScreenshot(
|
|
|
4768
4831
|
const entry = new ArtifactStore().publish({
|
|
4769
4832
|
filePath,
|
|
4770
4833
|
title,
|
|
4771
|
-
kind
|
|
4834
|
+
kind,
|
|
4772
4835
|
sessionId: sessionId ? String(sessionId) : null,
|
|
4773
4836
|
});
|
|
4774
4837
|
return { artifact: publicArtifactMetadata(entry), error: null };
|
|
@@ -4779,7 +4842,7 @@ async function promoteBrowserScreenshot(
|
|
|
4779
4842
|
: "";
|
|
4780
4843
|
return {
|
|
4781
4844
|
artifact: null,
|
|
4782
|
-
error:
|
|
4845
|
+
error: `${failureLabel} artifact publication failed${code ? ` (${code})` : ""}`,
|
|
4783
4846
|
};
|
|
4784
4847
|
} finally {
|
|
4785
4848
|
try {
|
|
@@ -4790,6 +4853,155 @@ async function promoteBrowserScreenshot(
|
|
|
4790
4853
|
}
|
|
4791
4854
|
}
|
|
4792
4855
|
|
|
4856
|
+
async function promoteBrowserScreenshot(
|
|
4857
|
+
filePath,
|
|
4858
|
+
{ sessionId = null, title = "Browser screenshot" } = {},
|
|
4859
|
+
) {
|
|
4860
|
+
return promoteBrowserGeneratedArtifact(filePath, {
|
|
4861
|
+
sessionId,
|
|
4862
|
+
title,
|
|
4863
|
+
kind: "screenshot",
|
|
4864
|
+
failureLabel: "browser screenshot",
|
|
4865
|
+
});
|
|
4866
|
+
}
|
|
4867
|
+
|
|
4868
|
+
async function promoteBrowserDownload(
|
|
4869
|
+
filePath,
|
|
4870
|
+
{ sessionId = null, title = "Browser download" } = {},
|
|
4871
|
+
) {
|
|
4872
|
+
return promoteBrowserGeneratedArtifact(filePath, {
|
|
4873
|
+
sessionId,
|
|
4874
|
+
title,
|
|
4875
|
+
kind: "data",
|
|
4876
|
+
failureLabel: "browser download",
|
|
4877
|
+
});
|
|
4878
|
+
}
|
|
4879
|
+
|
|
4880
|
+
async function publishBrowserEvidence(envelope, sessionId) {
|
|
4881
|
+
if (!envelope?.envelopeDigest) return { artifact: null, error: null };
|
|
4882
|
+
try {
|
|
4883
|
+
const { ArtifactStore, publicArtifactMetadata } =
|
|
4884
|
+
await import("../lib/artifact-store.js");
|
|
4885
|
+
const {
|
|
4886
|
+
browserEvidenceDigest,
|
|
4887
|
+
canonicalBrowserEvidenceJson,
|
|
4888
|
+
verifyBrowserEvidenceEnvelope,
|
|
4889
|
+
} = await import("../lib/browser-evidence.js");
|
|
4890
|
+
verifyBrowserEvidenceEnvelope(envelope);
|
|
4891
|
+
if (!sessionId || String(sessionId) !== envelope.binding.session.id) {
|
|
4892
|
+
throw new Error("browser evidence is not bound to the active session");
|
|
4893
|
+
}
|
|
4894
|
+
const data = `${canonicalBrowserEvidenceJson(envelope)}\n`;
|
|
4895
|
+
const expectedFileDigest = browserEvidenceDigest(data).slice(
|
|
4896
|
+
"sha256:".length,
|
|
4897
|
+
);
|
|
4898
|
+
const expectedLineage = {
|
|
4899
|
+
schema: envelope.schema,
|
|
4900
|
+
sessionId: envelope.binding.session.id,
|
|
4901
|
+
sessionRevision: envelope.binding.session.revision,
|
|
4902
|
+
diffDigest: envelope.binding.diff.digest,
|
|
4903
|
+
testRunId: envelope.binding.testRun.id,
|
|
4904
|
+
};
|
|
4905
|
+
const store = new ArtifactStore();
|
|
4906
|
+
const published = store.publishDataOnce({
|
|
4907
|
+
data,
|
|
4908
|
+
fileName: "browser-evidence-envelope.json",
|
|
4909
|
+
title: `Browser evidence ${envelope.binding.session.id}@${envelope.binding.session.revision}`,
|
|
4910
|
+
kind: "data",
|
|
4911
|
+
mime: "application/json",
|
|
4912
|
+
sessionId: String(sessionId),
|
|
4913
|
+
immutable: true,
|
|
4914
|
+
recordDigest: envelope.envelopeDigest,
|
|
4915
|
+
lineage: expectedLineage,
|
|
4916
|
+
});
|
|
4917
|
+
const entry = published.entry;
|
|
4918
|
+
const integrity = store.verifyIntegrity(entry);
|
|
4919
|
+
if (
|
|
4920
|
+
!integrity.ok ||
|
|
4921
|
+
entry.sessionId !== String(sessionId) ||
|
|
4922
|
+
entry.immutable !== true ||
|
|
4923
|
+
entry.recordDigest !== envelope.envelopeDigest ||
|
|
4924
|
+
entry.sha256 !== expectedFileDigest ||
|
|
4925
|
+
canonicalBrowserEvidenceJson(entry.lineage) !==
|
|
4926
|
+
canonicalBrowserEvidenceJson(expectedLineage)
|
|
4927
|
+
) {
|
|
4928
|
+
throw new Error("persisted evidence authority failed verification");
|
|
4929
|
+
}
|
|
4930
|
+
return {
|
|
4931
|
+
artifact: publicArtifactMetadata(entry),
|
|
4932
|
+
error: null,
|
|
4933
|
+
};
|
|
4934
|
+
} catch (error) {
|
|
4935
|
+
const code =
|
|
4936
|
+
typeof error?.code === "string"
|
|
4937
|
+
? error.code.replace(/[^A-Z0-9_-]/giu, "").slice(0, 40)
|
|
4938
|
+
: "";
|
|
4939
|
+
return {
|
|
4940
|
+
artifact: null,
|
|
4941
|
+
error: `browser evidence artifact publication failed${code ? ` (${code})` : ""}`,
|
|
4942
|
+
};
|
|
4943
|
+
}
|
|
4944
|
+
}
|
|
4945
|
+
|
|
4946
|
+
async function resolveBrowserUploadArtifact(artifactId, sessionId) {
|
|
4947
|
+
const { ArtifactStore, publicArtifactMetadata } =
|
|
4948
|
+
await import("../lib/artifact-store.js");
|
|
4949
|
+
const store = new ArtifactStore();
|
|
4950
|
+
return store.withIndexSnapshot((entries) => {
|
|
4951
|
+
const matches = entries.filter((entry) => entry.id === artifactId);
|
|
4952
|
+
if (matches.length !== 1) {
|
|
4953
|
+
throw new Error(
|
|
4954
|
+
matches.length === 0
|
|
4955
|
+
? "upload artifact was not found"
|
|
4956
|
+
: "upload artifact authority is ambiguous",
|
|
4957
|
+
);
|
|
4958
|
+
}
|
|
4959
|
+
const entry = matches[0];
|
|
4960
|
+
if (!sessionId || entry.sessionId !== String(sessionId)) {
|
|
4961
|
+
throw new Error("upload artifact is not bound to the active session");
|
|
4962
|
+
}
|
|
4963
|
+
if (
|
|
4964
|
+
typeof entry.file !== "string" ||
|
|
4965
|
+
path.basename(entry.file) !== entry.file ||
|
|
4966
|
+
!(entry.file === entry.id || entry.file.startsWith(`${entry.id}.`)) ||
|
|
4967
|
+
!/^[a-f0-9]{64}$/u.test(String(entry.sha256 || ""))
|
|
4968
|
+
) {
|
|
4969
|
+
throw new Error("upload artifact storage authority is invalid");
|
|
4970
|
+
}
|
|
4971
|
+
const integrity = store.verifyIntegrity(entry);
|
|
4972
|
+
if (!integrity.ok) {
|
|
4973
|
+
throw new Error("upload artifact failed digest verification");
|
|
4974
|
+
}
|
|
4975
|
+
const storedPath = store.storedPath(entry);
|
|
4976
|
+
if (fs.statSync(storedPath).size !== Number(entry.size)) {
|
|
4977
|
+
throw new Error("upload artifact size authority mismatch");
|
|
4978
|
+
}
|
|
4979
|
+
const temporaryDirectory = fs.mkdtempSync(
|
|
4980
|
+
path.join(os.tmpdir(), "cc-browser-upload-"),
|
|
4981
|
+
);
|
|
4982
|
+
const temporaryPath = path.join(
|
|
4983
|
+
temporaryDirectory,
|
|
4984
|
+
path.basename(entry.file || "upload.bin"),
|
|
4985
|
+
);
|
|
4986
|
+
try {
|
|
4987
|
+
fs.writeFileSync(temporaryPath, fs.readFileSync(storedPath), {
|
|
4988
|
+
flag: "wx",
|
|
4989
|
+
mode: 0o600,
|
|
4990
|
+
flush: true,
|
|
4991
|
+
});
|
|
4992
|
+
} catch (error) {
|
|
4993
|
+
fs.rmSync(temporaryDirectory, { recursive: true, force: true });
|
|
4994
|
+
throw error;
|
|
4995
|
+
}
|
|
4996
|
+
return {
|
|
4997
|
+
path: temporaryPath,
|
|
4998
|
+
metadata: publicArtifactMetadata(entry),
|
|
4999
|
+
cleanup: () =>
|
|
5000
|
+
fs.rmSync(temporaryDirectory, { recursive: true, force: true }),
|
|
5001
|
+
};
|
|
5002
|
+
});
|
|
5003
|
+
}
|
|
5004
|
+
|
|
4793
5005
|
const MCP_LEDGER_EFFECTS = new Set(["read", "unknown", "write", "destructive"]);
|
|
4794
5006
|
|
|
4795
5007
|
/**
|
|
@@ -5054,10 +5266,17 @@ async function executeToolInner(
|
|
|
5054
5266
|
onToolCallSettlement = null,
|
|
5055
5267
|
backgroundUsageFailureState = null,
|
|
5056
5268
|
toolAdmission = null,
|
|
5269
|
+
hostResourceBudget = null,
|
|
5057
5270
|
unattendedActionPolicy = null,
|
|
5058
5271
|
managedCheckpoint = false,
|
|
5059
5272
|
fileMutationScope = null,
|
|
5060
5273
|
hermeticExecution = false,
|
|
5274
|
+
browserEvidenceBinding = null,
|
|
5275
|
+
browserOriginGrants = null,
|
|
5276
|
+
browserExpectedGrantRevisions = null,
|
|
5277
|
+
browserReplaySourceEnvelope = null,
|
|
5278
|
+
browserReplayAllowSideEffects = false,
|
|
5279
|
+
browserReplayAllowCredentials = false,
|
|
5061
5280
|
// Hook-envelope tracing: this run's trace id, threaded into child loops
|
|
5062
5281
|
// (spawn_sub_agent / isolated run_skill) as their parent_id.
|
|
5063
5282
|
hookTraceId = null,
|
|
@@ -6776,6 +6995,7 @@ async function executeToolInner(
|
|
|
6776
6995
|
subAgentDepth,
|
|
6777
6996
|
subAgentBudget,
|
|
6778
6997
|
sessionBudget,
|
|
6998
|
+
hostResourceBudget,
|
|
6779
6999
|
subAgentContract,
|
|
6780
7000
|
settingsHooks,
|
|
6781
7001
|
// Immutable parent execution authority. The child may only tighten
|
|
@@ -6840,6 +7060,7 @@ async function executeToolInner(
|
|
|
6840
7060
|
maxBytes: args.maxBytes,
|
|
6841
7061
|
timeout: args.timeout,
|
|
6842
7062
|
config: webFetchConfig,
|
|
7063
|
+
hostResourceBudget,
|
|
6843
7064
|
});
|
|
6844
7065
|
return attachDescriptor(result);
|
|
6845
7066
|
} catch (err) {
|
|
@@ -6867,6 +7088,7 @@ async function executeToolInner(
|
|
|
6867
7088
|
maxResults: args.maxResults,
|
|
6868
7089
|
timeout: args.timeout,
|
|
6869
7090
|
config: webSearchConfig,
|
|
7091
|
+
hostResourceBudget,
|
|
6870
7092
|
});
|
|
6871
7093
|
return attachDescriptor(result);
|
|
6872
7094
|
} catch (err) {
|
|
@@ -7332,6 +7554,14 @@ async function executeToolInner(
|
|
|
7332
7554
|
tab: args.tab != null ? Number(args.tab) : undefined,
|
|
7333
7555
|
continueOnError: args.continue_on_error === true,
|
|
7334
7556
|
sessionId: sessionId ? String(sessionId) : null,
|
|
7557
|
+
evidenceBinding: browserEvidenceBinding,
|
|
7558
|
+
originGrants: browserOriginGrants,
|
|
7559
|
+
expectedGrantRevisions: browserExpectedGrantRevisions,
|
|
7560
|
+
replaySourceEnvelope: browserReplaySourceEnvelope,
|
|
7561
|
+
replayAllowSideEffects: browserReplayAllowSideEffects,
|
|
7562
|
+
replayAllowCredentials: browserReplayAllowCredentials,
|
|
7563
|
+
resolveUploadArtifact: (artifactId) =>
|
|
7564
|
+
resolveBrowserUploadArtifact(artifactId, sessionId),
|
|
7335
7565
|
});
|
|
7336
7566
|
if (!result.ok && result.error) {
|
|
7337
7567
|
// Nothing ran (validation / attach failure) — surface as an error.
|
|
@@ -7364,8 +7594,45 @@ async function executeToolInner(
|
|
|
7364
7594
|
step.detail = promoted.error;
|
|
7365
7595
|
}
|
|
7366
7596
|
}
|
|
7597
|
+
if (originalStep.downloadPath) {
|
|
7598
|
+
const promoted = await promoteBrowserDownload(
|
|
7599
|
+
originalStep.downloadPath,
|
|
7600
|
+
{
|
|
7601
|
+
sessionId,
|
|
7602
|
+
title: `Browser download ${i + 1} — ${originalStep.downloadSuggestedName || "file"}`,
|
|
7603
|
+
},
|
|
7604
|
+
);
|
|
7605
|
+
delete step.downloadPath;
|
|
7606
|
+
delete step.downloadRef;
|
|
7607
|
+
if (promoted.artifact) {
|
|
7608
|
+
step.downloadArtifact = promoted.artifact;
|
|
7609
|
+
step.downloadRef = promoted.artifact.id;
|
|
7610
|
+
step.detail = `download artifact: ${promoted.artifact.id}`;
|
|
7611
|
+
} else {
|
|
7612
|
+
step.downloadArtifactError = promoted.error;
|
|
7613
|
+
step.detail = promoted.error;
|
|
7614
|
+
}
|
|
7615
|
+
}
|
|
7367
7616
|
safeResult.steps.push(step);
|
|
7368
7617
|
}
|
|
7618
|
+
if (result.evidence) {
|
|
7619
|
+
const publishedEvidence = await publishBrowserEvidence(
|
|
7620
|
+
result.evidence,
|
|
7621
|
+
sessionId,
|
|
7622
|
+
);
|
|
7623
|
+
safeResult.evidence = result.evidence;
|
|
7624
|
+
if (publishedEvidence.artifact) {
|
|
7625
|
+
safeResult.evidenceArtifact = publishedEvidence.artifact;
|
|
7626
|
+
safeResult.evidenceRef = publishedEvidence.artifact.id;
|
|
7627
|
+
} else {
|
|
7628
|
+
safeResult.evidenceArtifactError = publishedEvidence.error;
|
|
7629
|
+
safeResult.evidencePublicationFailed = true;
|
|
7630
|
+
safeResult.ok = false;
|
|
7631
|
+
safeResult.retrySafe = false;
|
|
7632
|
+
safeResult.recovery =
|
|
7633
|
+
"Browser actions may have completed, but canonical evidence publication failed; do not retry side effects automatically.";
|
|
7634
|
+
}
|
|
7635
|
+
}
|
|
7369
7636
|
return attachDescriptor(safeResult);
|
|
7370
7637
|
} catch (err) {
|
|
7371
7638
|
return attachDescriptor({
|
|
@@ -7798,6 +8065,7 @@ async function executeToolInner(
|
|
|
7798
8065
|
? { workflowEffectId: workflowChildEffectId }
|
|
7799
8066
|
: {}),
|
|
7800
8067
|
...(sessionBudget ? { sessionBudget } : {}),
|
|
8068
|
+
...(hostResourceBudget ? { hostResourceBudget } : {}),
|
|
7801
8069
|
...(permissionRules ? { permissionRules } : {}),
|
|
7802
8070
|
...(hostManagedToolPolicy
|
|
7803
8071
|
? {
|
|
@@ -9613,6 +9881,10 @@ async function _executeSpawnSubAgent(args, ctx) {
|
|
|
9613
9881
|
const subLlmOptions = {
|
|
9614
9882
|
...parentLlm,
|
|
9615
9883
|
model: mdModel || parentLlm.model || undefined,
|
|
9884
|
+
// Preserve the host's optional event channel across every nesting level.
|
|
9885
|
+
// It is observational only: child hooks/tools must never depend on a
|
|
9886
|
+
// headless consumer being connected.
|
|
9887
|
+
...(interaction ? { interaction } : {}),
|
|
9616
9888
|
// Contract `effort` is a compute hint (reasoning level), not authority —
|
|
9617
9889
|
// forwarded to the child loop; harmless if the provider ignores it.
|
|
9618
9890
|
...(effectiveContract?.effort ? { effort: effectiveContract.effort } : {}),
|
|
@@ -9820,7 +10092,21 @@ async function _executeSpawnSubAgent(args, ctx) {
|
|
|
9820
10092
|
// single total-sub-agent pool (breadth cap spans the whole tree).
|
|
9821
10093
|
subAgentBudget: ctx.subAgentBudget || null,
|
|
9822
10094
|
...(ctx.sessionBudget ? { sessionBudget: ctx.sessionBudget } : {}),
|
|
10095
|
+
...(ctx.hostResourceBudget
|
|
10096
|
+
? { hostResourceBudget: ctx.hostResourceBudget }
|
|
10097
|
+
: {}),
|
|
9823
10098
|
onUsage,
|
|
10099
|
+
...(interaction && typeof interaction.emit === "function"
|
|
10100
|
+
? {
|
|
10101
|
+
onProgress: (progress) =>
|
|
10102
|
+
emit("sub-agent.progress", {
|
|
10103
|
+
event_type: progress?.type || "unknown",
|
|
10104
|
+
tool: progress?.tool || null,
|
|
10105
|
+
iteration_count: progress?.iterationCount || 0,
|
|
10106
|
+
token_count: progress?.tokenCount || 0,
|
|
10107
|
+
}),
|
|
10108
|
+
}
|
|
10109
|
+
: {}),
|
|
9824
10110
|
...(ctx.strictUsageTelemetry === true
|
|
9825
10111
|
? {
|
|
9826
10112
|
strictUsageTelemetry: true,
|
|
@@ -12730,6 +13016,9 @@ export async function* agentLoop(messages, options) {
|
|
|
12730
13016
|
const { IterationBudget, WarningLevel } =
|
|
12731
13017
|
await import("../lib/iteration-budget.js");
|
|
12732
13018
|
const budget = options.iterationBudget || new IterationBudget();
|
|
13019
|
+
const { HostResourceBudget } = await import("../lib/host-resource-budget.js");
|
|
13020
|
+
const hostResourceBudget =
|
|
13021
|
+
options.hostResourceBudget || new HostResourceBudget();
|
|
12733
13022
|
const signal = options.signal || null;
|
|
12734
13023
|
const workflowEffectId = _normalizeWorkflowEffectId(options.workflowEffectId);
|
|
12735
13024
|
// Optional OpenTelemetry recorder (TelemetryRecorder). When present, the loop
|
|
@@ -12943,6 +13232,10 @@ export async function* agentLoop(messages, options) {
|
|
|
12943
13232
|
// CLI root does not create one yet; when supplied, every nested child sees
|
|
12944
13233
|
// the same object and cannot reset concurrency/spawn/depth totals.
|
|
12945
13234
|
sessionBudget: options.sessionBudget || null,
|
|
13235
|
+
// Share bounded WebFetch cache and renderer/tool/event admission across
|
|
13236
|
+
// the main loop and every nested subagent. A host can tighten these limits
|
|
13237
|
+
// by supplying its own budget; otherwise the conservative defaults apply.
|
|
13238
|
+
hostResourceBudget,
|
|
12946
13239
|
// This loop's EFFECTIVE subagent contract (set when this loop IS a spawned
|
|
12947
13240
|
// sub-agent). Threaded so a nested spawn_sub_agent sees it as the parent
|
|
12948
13241
|
// ceiling (tighten-only). null at the top level (no ceiling).
|