chainlesschain 0.166.46 → 0.166.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/package.json +3 -1
- package/src/assets/web-panel/assets/{AIOps-Cp8KiMmv.js → AIOps-CDpT0WXV.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-B4d9BGsm.js → ActionButton-BNfUljWx.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-Cf9yXTkv.js → Analytics-C9323DEx.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-40UkmxtP.js → AppLayout-CRrjb2db.js} +4 -4
- package/src/assets/web-panel/assets/{Artifacts-Ckkb4oOA.js → Artifacts-Db-DGqJS.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-Dnf569k5.js → Audit-CJdHRJ0W.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-CA6bLem4.js → BackgroundAgents-_RSCnTYs.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-ChQU0I_Q.js → Backup-8GFQi-dM.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-BHeZXnNN.js → BaseInput-C87NtgUZ.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-DcFVYB2E.js → Chat-DcTMWS8G.js} +5 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-5ZDPTW_H.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-2PDbejv2.js → Checkbox-DM9EmYee.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-DJBn1RAu.js → Codegen-M2YqDRNN.js} +1 -1
- package/src/assets/web-panel/assets/{Col-CPRq7n6y.js → Col-oB1LLxyf.js} +1 -1
- package/src/assets/web-panel/assets/{Community-axvINFMi.js → Community-TcVZK5tF.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-_OX4Qbe0.js → Compact-XKmq-3K_.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-DWAkvzRL.js → Compliance-C6CBiDRy.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-CUIJ25oj.js → Cowork-Dz9CGqXH.js} +4 -4
- package/src/assets/web-panel/assets/{Cron-nR0m7H3_.js → Cron-CxJDgDVL.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CgTLXzh_.js → Crosschain-DMP0JsaQ.js} +1 -1
- package/src/assets/web-panel/assets/{DID-BllzRB6Q.js → DID-I5IQeogb.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-C9f0IIBN.js → Dashboard-BfLW2MXj.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BkahetiO.js → Dropdown-BK8EjAlh.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-rartVC-k.js → EmailListRenderer-C3iqSv5I.js} +1 -1
- package/src/assets/web-panel/assets/EvolutionSettings-BJmBzpW6.js +1 -0
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DgUdFvw1.js → FamilyGuardDashboard-T19rnqm-.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-oFpIQU6g.js → Federation-CozrbPMy.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-BUH5xlyP.js → FormItemContext-k1dCLNNJ.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-ilRa-ueg.js → GenericCardRenderer-DbaW_Jvt.js} +1 -1
- package/src/assets/web-panel/assets/{Git-DlHHSF8j.js → Git-CQHRyEIt.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-yQiiXIWe.js → Governance-BMJYZgMy.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BUDRVGOP.js → Inference-B7mpNU7V.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-BaGyIoN1.js → KnowledgeGraph-Br0Blg6B.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-C1cO6zE0.js → Logs-HIdk0S6M.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-_z_Iaoes.js → MarkdownRenderer-HxeocBHy.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-CM8cGL0K.js → Marketplace-Bkfq69UP.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CDqAMU0U.js → McpTools-dtmx0bHO.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-CfB0-Ofv.js → Memory-CrRlOuEf.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BL18ytvB.js → MobileBridge-D4ZIZiAH.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-PIyyxbuJ.js → MobileProjects-C90Rw7GE.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-BTTrFCol.js → Mtc-CC6k_uh4.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-JHZn037c.js → MtcAudit-T_CUIYUy.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-CMf9NEdB.js → Multisig-N_e0RRWk.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-Dhk3qaus.js → NLProgramming-Iq3VzEv0.js} +1 -1
- package/src/assets/web-panel/assets/Notes-B5sKJUJt.js +7 -0
- package/src/assets/web-panel/assets/{NotificationSettings-gxdaVEit.js → NotificationSettings-K8UVp8qQ.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-BWNyM-6m.js +1 -0
- package/src/assets/web-panel/assets/{Organization-CzvHcDNO.js → Organization-DMO1NJxI.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Dclx30Vv.js → Overflow-BBY6b31Z.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CM0Wm9vZ.js → P2P-DmsL0y0v.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-fYmQzmTA.js → PdhVaultBrowser-C65AX_RY.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-B_oATenG.js → Permissions-CWcpRtWa.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-CptiVBh5.js → PersonalDataHub--ZNDIdsn.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-DkHzgyyI.js → Pipeline-DCdj5NGb.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DzZvwcKh.js → Privacy-BRKu7Q3E.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CzkCs-5G.js → ProjectInit-BJ7ozIAb.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BB8dcxRD.js → ProjectSettings-B2cVLiXW.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-B7PW9CFY.js → Projects-Ce9r_W-p.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-Tfx-ti1V.js → Providers-BDespvGZ.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-EvWlNhfX.js → QrScannerModal-BUNO4fDU.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CUspgbNC.js → QuickAsk-D2TUqeBV.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-COY2g77J.js → Recommend-BNNQPHBH.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-BzMBU6E6.js → RemoteSession-D2t1V_Cm.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-RtYRF4YP.js → Reputation-DVK5hEqI.js} +1 -1
- package/src/assets/web-panel/assets/{Row-Bva3l9Lc.js → Row-BB9RTwmE.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BhjzLvW3.js → RssFeed-DmEO7liZ.js} +2 -2
- package/src/assets/web-panel/assets/{Search-BYzT2PTR.js → Search-UwEYjnDB.js} +1 -1
- package/src/assets/web-panel/assets/{Security-Bcl4-KTv.js → Security-DebqSsMp.js} +4 -4
- package/src/assets/web-panel/assets/{Services-BRRa4A0f.js → Services-CuuPts3C.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DYQ016qy.js → Skeleton-DbWpmbgf.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CAUKL9JA.js → Skills-BaK7SxzT.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-BTyUqfuD.js → Sla-BFHv51Jb.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-CUjMihrs.js → SpeechSettings-B9b1R6uK.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CvfOSupr.js → SyncSettings-BnO0CN02.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-EvjNXrWH.js → Tasks-Dy01Vq49.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-wPAp0EoM.js → Templates-BCy2AMHc.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CP0D-q9Q.js → Tenant-4Tx9y_Y1.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-CQ0f2iFg.js → Terminal-CPOoUH8J.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-D3JrGSPb.js → TimelineRenderer-C85GlJzu.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-yXf2PPp9.js → Tokens-_xneFBGF.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DfmMOoZ2.js → Trigger-BizG4rTr.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-BTCyMgf1.js → Trust-Dh8EIn3n.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-DKCwIBHi.js → UkeySign-C5NWoHWQ.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-CQpDSzLO.js → VideoEditing-0YfrySL6.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-CyFrzC3K.js → Wallet-BZVH8Ags.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-D6Nr_1kd.js → WebAuthn-kNofa6vm.js} +3 -3
- package/src/assets/web-panel/assets/{WorkflowEditor-CgR9tNrB.js → WorkflowEditor-BNO34_j0.js} +1 -1
- package/src/assets/web-panel/assets/{chat-CRG_IeyP.js → chat-ifQ2FlwD.js} +1 -1
- package/src/assets/web-panel/assets/{colors-MdE3TStI.js → colors-1TL8H6EH.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-B0LRuiNV.js → compact-item-DBfRjs_T.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-B_V5fjcX.js → createContext-Bs6V4iBf.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BHnbnuYL.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DSL-c_hr.js → hasIn-Bz6LMY_0.js} +1 -1
- package/src/assets/web-panel/assets/{index-DE7bSYmW.js → index--WvT2Il3.js} +1 -1
- package/src/assets/web-panel/assets/{index-DBwBZwio.js → index-84mi5rsv.js} +1 -1
- package/src/assets/web-panel/assets/{index-BsAEd-Do.js → index-B5SJCUZ7.js} +1 -1
- package/src/assets/web-panel/assets/{index-CdHMc9LQ.js → index-B6RClMZl.js} +1 -1
- package/src/assets/web-panel/assets/{index-B3iW-mhn.js → index-BB1Af7Fv.js} +1 -1
- package/src/assets/web-panel/assets/{index-C67dPW0L.js → index-BQL_tldd.js} +1 -1
- package/src/assets/web-panel/assets/{index-BpwGsAA-.js → index-BXJXMaZe.js} +1 -1
- package/src/assets/web-panel/assets/{index-CZICtYJ0.js → index-BhPDhmvN.js} +1 -1
- package/src/assets/web-panel/assets/{index-BbZZ7P_c.js → index-BiZ7Nz5-.js} +1 -1
- package/src/assets/web-panel/assets/{index-Didyuq2Z.js → index-BoCTDcn6.js} +1 -1
- package/src/assets/web-panel/assets/{index-BNhWoD6d.js → index-BxqC3LiO.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRRY44XP.js → index-C6c0j-Ki.js} +1 -1
- package/src/assets/web-panel/assets/{index-D3pJBTvo.js → index-C7d6QlfR.js} +1 -1
- package/src/assets/web-panel/assets/{index-CdplnAS9.js → index-C9QYxq61.js} +1 -1
- package/src/assets/web-panel/assets/{index-CPYshcic.js → index-CBh48_Mh.js} +1 -1
- package/src/assets/web-panel/assets/{index-CkN53KiJ.js → index-CNKHoXWI.js} +1 -1
- package/src/assets/web-panel/assets/{index-OBhlHSMN.js → index-CXVBQ82k.js} +3 -3
- package/src/assets/web-panel/assets/{index-DtOTppk8.js → index-CXtiLagi.js} +1 -1
- package/src/assets/web-panel/assets/{index-CNytQuFq.js → index-Cn7EIWmI.js} +1 -1
- package/src/assets/web-panel/assets/index-CsRz9-ZH.js +1 -0
- package/src/assets/web-panel/assets/{index-BIDCNwy6.js → index-CtB45Hok.js} +1 -1
- package/src/assets/web-panel/assets/{index-BQAsL19t.js → index-Cu_V6ZJH.js} +1 -1
- package/src/assets/web-panel/assets/{index-c8OqO3rq.js → index-Cykt9BbN.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bq8-2Ibv.js → index-DDhy4eCS.js} +1 -1
- package/src/assets/web-panel/assets/{index-CXMeisJK.js → index-DEPPzM8I.js} +1 -1
- package/src/assets/web-panel/assets/{index-BD0w-888.js → index-DMVktlxG.js} +1 -1
- package/src/assets/web-panel/assets/{index-CVDi4rS9.js → index-DOww5Qny.js} +1 -1
- package/src/assets/web-panel/assets/{index-Tg3yl8wc.js → index-DWPp-d07.js} +1 -1
- package/src/assets/web-panel/assets/index-DnjMFf3m.js +1 -0
- package/src/assets/web-panel/assets/{index-DVgTf7CZ.js → index-DvM2xBUA.js} +1 -1
- package/src/assets/web-panel/assets/{index-SmQfEHjp.js → index-EK3XtMxA.js} +1 -1
- package/src/assets/web-panel/assets/{index-C5dqieYX.js → index-XJIV7HEw.js} +1 -1
- package/src/assets/web-panel/assets/{index-0200QxC4.js → index-cNwsev6n.js} +1 -1
- package/src/assets/web-panel/assets/{index-C-aKWR2v.js → index-f_7L9GvP.js} +1 -1
- package/src/assets/web-panel/assets/{index-KaSejHjf.js → index-lUL3bD2z.js} +1 -1
- package/src/assets/web-panel/assets/{index-CS3bOhV7.js → index-pOUFfRdN.js} +1 -1
- package/src/assets/web-panel/assets/{index-CEOAZm5j.js → index-rGhS02f8.js} +1 -1
- package/src/assets/web-panel/assets/{index-BMm8tO2X.js → index-vHtnQsnV.js} +1 -1
- package/src/assets/web-panel/assets/{index-BHp1nSur.js → index-vb1XIxEB.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-P8SBN6Di.js → initDefaultProps-DpRIjwTt.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BubbjUT_.js → motion-CG4_9o-Z.js} +1 -1
- package/src/assets/web-panel/assets/{move-Chcykv0I.js → move-Dku1fXtf.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DyiYuGDu.js → mtc-parser-BvAVeX-3.js} +1 -1
- package/src/assets/web-panel/assets/{omit-Rdwb_Neb.js → omit-DFu0x78D.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-CCr0MYHl.js → pickAttrs-CmI-FNcK.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-B1ZXz3bb.js → placementArrow-CGERYewB.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BGEdwej6.js → responsiveObserve-D7G8bF5J.js} +1 -1
- package/src/assets/web-panel/assets/{slide-CpnsUMaT.js → slide-B2sXwWXy.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-C7x-TVp_.js → statusUtils-DI5yh0n3.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CC5k_791.js → styleChecker-deGJ5dp_.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-BpZFKsJW.js → useFlexGapSupport-OqHBXEmi.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-CVq5HySy.js → useFs-Dqgx0Qv_.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BGkdLryu.js → usePersonalDataHub-Be-lveh2.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-uLtOUEK-.js → vnode-CFxB876W.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-BfVC9iUs.js → zoom-BFOYrl4e.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 +8 -0
- package/src/commands/background-session.js +31 -3
- package/src/commands/chat.js +5 -1
- package/src/commands/eval.js +86 -28
- package/src/commands/llm.js +104 -1
- package/src/commands/plugin.js +130 -1
- package/src/commands/sandbox.js +121 -2
- package/src/commands/serve.js +11 -2
- package/src/commands/skill.js +29 -0
- package/src/data/changelog.json +13 -0
- package/src/gateways/ws/session-protocol.js +13 -0
- package/src/gateways/ws/ws-agent-handler.js +17 -0
- package/src/gateways/ws/ws-server.js +3 -0
- package/src/gateways/ws/ws-session-state.js +131 -0
- package/src/generated/cc-agent-protocol.schema.json +4 -0
- package/src/lazy-dispatch.js +8 -1
- package/src/lib/agent-sandbox.js +337 -53
- package/src/lib/app-server/cli-agent-kernel-adapter.js +28 -0
- package/src/lib/app-server/server.js +93 -0
- package/src/lib/background-agent-keeper-client.js +2 -0
- package/src/lib/background-agent-keeper-protocol.js +7 -0
- package/src/lib/background-agent-supervisor.js +194 -47
- package/src/lib/codex-app-server-adapter.js +81 -27
- package/src/lib/context-memory-kernel/durable-memory-port.js +31 -8
- package/src/lib/context-memory-kernel/provider-context.js +53 -19
- package/src/lib/deferred-question-context.js +122 -0
- package/src/lib/eval/evidence.js +202 -64
- package/src/lib/eval/plugin-suite.js +917 -0
- package/src/lib/eval/runner.js +10 -3
- package/src/lib/evolution/agent-evolution-runtime-composition.js +236 -1
- package/src/lib/evolution/agent-model-projection.js +97 -1
- package/src/lib/evolution/evidence-backed-wiki-maintainer.js +154 -1
- package/src/lib/evolution/evolution-artifact-ports.js +6 -0
- package/src/lib/evolution/evolution-deployment-loader.js +87 -3
- package/src/lib/evolution/evolution-eval-gate.js +8 -0
- package/src/lib/evolution/evolution-eval-runtime-composition.js +255 -0
- package/src/lib/evolution/evolution-evidence-artifact-adapter.js +58 -2
- package/src/lib/evolution/evolution-ledger-file-backend.js +23 -2
- package/src/lib/evolution/evolution-ledger-manifest-chain.js +223 -7
- package/src/lib/evolution/evolution-ledger-v2-journal.js +525 -0
- package/src/lib/evolution/evolution-ledger-v2-manifest-backend.js +46 -2
- package/src/lib/evolution/evolution-ledger.js +57 -1
- package/src/lib/evolution/evolution-run-ledger-adapter.js +93 -0
- package/src/lib/evolution/evolution-run-wiki-evidence-resolver.js +259 -0
- package/src/lib/evolution/governed-hub-llm.js +238 -5
- package/src/lib/evolution/governed-hub-resolver.js +82 -4
- package/src/lib/evolution/governed-hub-skill.js +11 -5
- package/src/lib/evolution/governed-skill-synthesis-provider-chat.js +10 -1
- package/src/lib/evolution/skill-runtime-revalidation-ledger-adapter.js +254 -0
- package/src/lib/evolution/skill-runtime-revalidation.js +530 -0
- package/src/lib/evolution/skill-target-matrix-eval.js +4 -4
- package/src/lib/evolution/wiki-evidence-commit-guard.js +366 -0
- package/src/lib/evolution/wiki-informed-skill-proposer.js +13 -1
- package/src/lib/goal-context.js +14 -5
- package/src/lib/interaction-adapter.js +166 -1
- package/src/lib/model-capabilities.js +271 -0
- package/src/lib/model-context-catalog.js +105 -0
- package/src/lib/model-context-window.js +4 -49
- package/src/lib/openai-responses.js +428 -0
- package/src/lib/plugin-runtime/scopes.js +7 -1
- package/src/lib/remote-read-loop-guard.js +2 -2
- package/src/lib/runtime-usage-ledger.js +16 -0
- package/src/lib/skill-loader.js +12 -0
- package/src/lib/with-file-lock.js +3 -1
- package/src/repl/agent-repl.js +5 -1
- package/src/runtime/agent-core.js +348 -23
- package/src/runtime/agent-runtime.js +7 -0
- package/src/runtime/coding-agent-contract-shared.cjs +13 -1
- package/src/runtime/headless-runner.js +4 -1
- package/src/runtime/headless-stream.js +133 -44
- package/src/runtime/runtime-factory.js +26 -2
- package/src/workers/background-agent-keeper.js +23 -13
- package/src/workers/background-agent-worker.js +27 -13
- package/src/assets/web-panel/assets/ChatBubbleRenderer-Bi2SY9E_.js +0 -1
- package/src/assets/web-panel/assets/EvolutionSettings-BqpG3XHV.js +0 -1
- package/src/assets/web-panel/assets/Notes-6F8EarNN.js +0 -7
- package/src/assets/web-panel/assets/OrderTableRenderer-gVgXQWdc.js +0 -1
- package/src/assets/web-panel/assets/devWarning-BtFLt3qI.js +0 -1
- package/src/assets/web-panel/assets/index-BhuWQHeG.js +0 -1
- package/src/assets/web-panel/assets/index-D-4tFek3.js +0 -1
|
@@ -16,6 +16,7 @@ export const DEFAULT_WS_SESSION_STATE_MAX_EVENTS = 64;
|
|
|
16
16
|
|
|
17
17
|
const RUN_STATUSES = new Set(["idle", "running", "interrupted"]);
|
|
18
18
|
const APPROVAL_STATUSES = new Set(["pending", "interrupted"]);
|
|
19
|
+
const MAX_DEFERRED_QUESTIONS = 32;
|
|
19
20
|
|
|
20
21
|
function own(object, key) {
|
|
21
22
|
return Object.prototype.hasOwnProperty.call(object || {}, key);
|
|
@@ -112,12 +113,87 @@ function normalizeRun(value) {
|
|
|
112
113
|
};
|
|
113
114
|
}
|
|
114
115
|
|
|
116
|
+
function normalizeDeferredRecord(value, resolved = false) {
|
|
117
|
+
if (!value || typeof value !== "object") return null;
|
|
118
|
+
const requestId =
|
|
119
|
+
typeof value.requestId === "string" && value.requestId.length > 0
|
|
120
|
+
? value.requestId
|
|
121
|
+
: null;
|
|
122
|
+
if (!requestId || !value.binding || typeof value.binding !== "object") {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
const binding = cloneJson(value.binding);
|
|
126
|
+
if (
|
|
127
|
+
binding.sessionId == null ||
|
|
128
|
+
!Number.isSafeInteger(binding.sequence) ||
|
|
129
|
+
binding.sequence <= 0
|
|
130
|
+
) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
let answer = "";
|
|
134
|
+
if (resolved) {
|
|
135
|
+
if (typeof value.answer === "string") answer = value.answer;
|
|
136
|
+
else {
|
|
137
|
+
try {
|
|
138
|
+
answer = JSON.stringify(value.answer);
|
|
139
|
+
} catch {
|
|
140
|
+
answer = String(value.answer ?? "");
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (typeof answer !== "string") answer = String(value.answer ?? "");
|
|
144
|
+
answer = answer.slice(0, 16384);
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
requestId,
|
|
148
|
+
question:
|
|
149
|
+
typeof value.question === "string" ? value.question.slice(0, 2048) : "",
|
|
150
|
+
binding,
|
|
151
|
+
requestedRevision: nonNegativeRevision(
|
|
152
|
+
value.requestedRevision ?? value.contextRevision,
|
|
153
|
+
),
|
|
154
|
+
...(resolved
|
|
155
|
+
? {
|
|
156
|
+
answer,
|
|
157
|
+
resolvedRevision: nonNegativeRevision(value.resolvedRevision),
|
|
158
|
+
}
|
|
159
|
+
: {
|
|
160
|
+
options: Array.isArray(value.options)
|
|
161
|
+
? cloneJson(value.options.slice(0, 32), [])
|
|
162
|
+
: null,
|
|
163
|
+
multiSelect: value.multiSelect === true,
|
|
164
|
+
purpose:
|
|
165
|
+
value.purpose === "preference" ? "preference" : "information",
|
|
166
|
+
contextRevision: nonNegativeRevision(value.contextRevision),
|
|
167
|
+
}),
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function upsertBounded(list, record) {
|
|
172
|
+
if (!record) return list;
|
|
173
|
+
const next = list.filter((item) => item.requestId !== record.requestId);
|
|
174
|
+
next.push(record);
|
|
175
|
+
return next.slice(-MAX_DEFERRED_QUESTIONS);
|
|
176
|
+
}
|
|
177
|
+
|
|
115
178
|
function normalizeSnapshot(value = {}, options = {}) {
|
|
116
179
|
const source = value && typeof value === "object" ? value : {};
|
|
117
180
|
const snapshot = {
|
|
118
181
|
revision: nonNegativeRevision(source.revision),
|
|
119
182
|
todo: normalizeTodoSnapshot(source.todo),
|
|
120
183
|
pendingApproval: normalizePendingApproval(source.pendingApproval),
|
|
184
|
+
contextRevision: nonNegativeRevision(source.contextRevision),
|
|
185
|
+
deferredQuestions: Array.isArray(source.deferredQuestions)
|
|
186
|
+
? source.deferredQuestions
|
|
187
|
+
.map((value) => normalizeDeferredRecord(value, false))
|
|
188
|
+
.filter(Boolean)
|
|
189
|
+
.slice(-MAX_DEFERRED_QUESTIONS)
|
|
190
|
+
: [],
|
|
191
|
+
deferredAnswers: Array.isArray(source.deferredAnswers)
|
|
192
|
+
? source.deferredAnswers
|
|
193
|
+
.map((value) => normalizeDeferredRecord(value, true))
|
|
194
|
+
.filter(Boolean)
|
|
195
|
+
.slice(-MAX_DEFERRED_QUESTIONS)
|
|
196
|
+
: [],
|
|
121
197
|
run: normalizeRun(source.run),
|
|
122
198
|
};
|
|
123
199
|
|
|
@@ -183,6 +259,58 @@ function applyEvent(snapshot, event) {
|
|
|
183
259
|
}
|
|
184
260
|
break;
|
|
185
261
|
|
|
262
|
+
case "question.context.revision":
|
|
263
|
+
next.contextRevision = Math.max(
|
|
264
|
+
next.contextRevision,
|
|
265
|
+
nonNegativeRevision(payload.contextRevision),
|
|
266
|
+
);
|
|
267
|
+
break;
|
|
268
|
+
|
|
269
|
+
case "question.deferred.requested": {
|
|
270
|
+
const question = normalizeDeferredRecord(payload, false);
|
|
271
|
+
if (
|
|
272
|
+
question &&
|
|
273
|
+
question.binding.sessionId === payload.binding?.sessionId
|
|
274
|
+
) {
|
|
275
|
+
next.deferredQuestions = upsertBounded(
|
|
276
|
+
next.deferredQuestions,
|
|
277
|
+
question,
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
case "question.deferred.resolved": {
|
|
284
|
+
const answer = normalizeDeferredRecord(payload, true);
|
|
285
|
+
if (answer) {
|
|
286
|
+
const pending = next.deferredQuestions.find(
|
|
287
|
+
(item) => item.requestId === answer.requestId,
|
|
288
|
+
);
|
|
289
|
+
if (
|
|
290
|
+
pending &&
|
|
291
|
+
JSON.stringify(pending.binding) === JSON.stringify(answer.binding)
|
|
292
|
+
) {
|
|
293
|
+
next.deferredQuestions = next.deferredQuestions.filter(
|
|
294
|
+
(item) => item.requestId !== answer.requestId,
|
|
295
|
+
);
|
|
296
|
+
next.deferredAnswers = upsertBounded(next.deferredAnswers, answer);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
break;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
case "question.deferred.consumed": {
|
|
303
|
+
const ids = new Set(
|
|
304
|
+
Array.isArray(payload.questionIds)
|
|
305
|
+
? payload.questionIds.filter((id) => typeof id === "string")
|
|
306
|
+
: [],
|
|
307
|
+
);
|
|
308
|
+
next.deferredAnswers = next.deferredAnswers.filter(
|
|
309
|
+
(item) => !ids.has(item.requestId),
|
|
310
|
+
);
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
|
|
186
314
|
case "run.started":
|
|
187
315
|
next.run = normalizeRun({
|
|
188
316
|
status: "running",
|
|
@@ -302,6 +430,9 @@ export function createWsSessionState(options = {}) {
|
|
|
302
430
|
revision: 0,
|
|
303
431
|
todo: normalizeTodoSnapshot(options.todo),
|
|
304
432
|
pendingApproval: null,
|
|
433
|
+
contextRevision: 0,
|
|
434
|
+
deferredQuestions: [],
|
|
435
|
+
deferredAnswers: [],
|
|
305
436
|
run: normalizeRun(),
|
|
306
437
|
...(hasPlanSnapshot
|
|
307
438
|
? { planSnapshot: cloneJson(options.planSnapshot) }
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"agent_stream_events",
|
|
19
19
|
"agent_stream_payloads",
|
|
20
20
|
"unified_policy_decision",
|
|
21
|
+
"deferred_questions",
|
|
21
22
|
"context_memory_kernel"
|
|
22
23
|
],
|
|
23
24
|
"contextMemory": {
|
|
@@ -3832,6 +3833,7 @@
|
|
|
3832
3833
|
"method": {
|
|
3833
3834
|
"enum": [
|
|
3834
3835
|
"approval/decide",
|
|
3836
|
+
"question/answer",
|
|
3835
3837
|
"humanTask/decide"
|
|
3836
3838
|
]
|
|
3837
3839
|
},
|
|
@@ -3862,6 +3864,8 @@
|
|
|
3862
3864
|
"item/completed",
|
|
3863
3865
|
"approval/requested",
|
|
3864
3866
|
"approval/resolved",
|
|
3867
|
+
"question/requested",
|
|
3868
|
+
"question/resolved",
|
|
3865
3869
|
"tool/requested",
|
|
3866
3870
|
"tool/result",
|
|
3867
3871
|
"subagent/started",
|
package/src/lazy-dispatch.js
CHANGED
|
@@ -814,7 +814,14 @@ export function isFastReadOnlyInvocation(argv, env = process.env) {
|
|
|
814
814
|
commandLocation?.token === "session" &&
|
|
815
815
|
argv[commandLocation.index + 1] === "show" &&
|
|
816
816
|
!explicitOtlp;
|
|
817
|
-
|
|
817
|
+
// Capability inspection is a deliberately static, read-only diagnostic.
|
|
818
|
+
// Keep it ahead of observability initialization even when an OTLP endpoint
|
|
819
|
+
// is configured; otherwise merely inspecting a profile creates a queue and
|
|
820
|
+
// contradicts the command's no-network/no-write contract.
|
|
821
|
+
const llmCapabilities =
|
|
822
|
+
commandLocation?.token === "llm" &&
|
|
823
|
+
argv[commandLocation.index + 1] === "capabilities";
|
|
824
|
+
return quickStatus || sessionShow || llmCapabilities;
|
|
818
825
|
}
|
|
819
826
|
|
|
820
827
|
let processHandlersInstalled = false;
|
package/src/lib/agent-sandbox.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** OS-isolated shell execution for the coding agent. */
|
|
2
2
|
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { proxyEnv } from "./sandbox-egress-proxy.js";
|
|
5
6
|
import executionBroker from "./process-execution-broker/index.js";
|
|
@@ -10,8 +11,15 @@ export const AGENT_SANDBOX_MODES = Object.freeze([
|
|
|
10
11
|
"workspace-write",
|
|
11
12
|
"strict",
|
|
12
13
|
]);
|
|
14
|
+
export const AGENT_SANDBOX_CAPABILITY_SCHEMA =
|
|
15
|
+
"chainlesschain.agent-sandbox-capabilities/v1";
|
|
13
16
|
export const _deps = {
|
|
14
17
|
spawnSync: (...args) => executionBroker.spawnSync(...args),
|
|
18
|
+
host: () => ({
|
|
19
|
+
platform: process.platform,
|
|
20
|
+
release: os.release(),
|
|
21
|
+
arch: process.arch,
|
|
22
|
+
}),
|
|
15
23
|
};
|
|
16
24
|
|
|
17
25
|
function stringList(value) {
|
|
@@ -322,46 +330,298 @@ export function enforceSandboxFailClosed(sandbox, reason = "safe") {
|
|
|
322
330
|
};
|
|
323
331
|
}
|
|
324
332
|
|
|
333
|
+
function capability(id, details = {}) {
|
|
334
|
+
return { id, ...details };
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function addUniqueCapability(target, entry) {
|
|
338
|
+
if (!target.some((candidate) => candidate.id === entry.id)) {
|
|
339
|
+
target.push(entry);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Describe the exact legacy agent-shell sandbox request without claiming that
|
|
345
|
+
* a command has run. `enforceable` is backend capability; `applied` is only
|
|
346
|
+
* populated after a child was successfully started through that backend.
|
|
347
|
+
*/
|
|
348
|
+
export function assessAgentSandboxCapabilities(sandbox, options = {}) {
|
|
349
|
+
const host = options.host || {
|
|
350
|
+
platform: process.platform,
|
|
351
|
+
release: os.release(),
|
|
352
|
+
arch: process.arch,
|
|
353
|
+
};
|
|
354
|
+
const execution = options.execution || null;
|
|
355
|
+
const availability = options.availability || null;
|
|
356
|
+
const requested = [];
|
|
357
|
+
const enforceable = [];
|
|
358
|
+
const unsupported = [];
|
|
359
|
+
|
|
360
|
+
if (!sandbox) {
|
|
361
|
+
return {
|
|
362
|
+
schema: AGENT_SANDBOX_CAPABILITY_SCHEMA,
|
|
363
|
+
host: {
|
|
364
|
+
platform: String(host.platform),
|
|
365
|
+
release: String(host.release),
|
|
366
|
+
arch: String(host.arch),
|
|
367
|
+
},
|
|
368
|
+
backend: {
|
|
369
|
+
engine: null,
|
|
370
|
+
isolationLevel: "policy-only",
|
|
371
|
+
availabilityChecked: false,
|
|
372
|
+
available: null,
|
|
373
|
+
reason: null,
|
|
374
|
+
},
|
|
375
|
+
status: "disabled",
|
|
376
|
+
execution: {
|
|
377
|
+
observed: false,
|
|
378
|
+
attempted: false,
|
|
379
|
+
started: false,
|
|
380
|
+
},
|
|
381
|
+
requested,
|
|
382
|
+
enforceable,
|
|
383
|
+
applied: [],
|
|
384
|
+
unsupported,
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
const engine = String(sandbox.engine || "");
|
|
389
|
+
const policy = sandbox.policy || normalizeSandboxPolicy({}, sandbox.cwd);
|
|
390
|
+
const supportedEngine = engine === "docker" || engine === "bubblewrap";
|
|
391
|
+
const supportedPlatform =
|
|
392
|
+
engine !== "bubblewrap" || host.platform === "linux";
|
|
393
|
+
const isolationCapability =
|
|
394
|
+
engine === "docker"
|
|
395
|
+
? "isolation.container"
|
|
396
|
+
: engine === "bubblewrap"
|
|
397
|
+
? "isolation.linux-namespace"
|
|
398
|
+
: "isolation.unknown";
|
|
399
|
+
const networkCapability = sandbox.network
|
|
400
|
+
? "network.unrestricted"
|
|
401
|
+
: "network.none";
|
|
402
|
+
|
|
403
|
+
addUniqueCapability(requested, capability(isolationCapability));
|
|
404
|
+
addUniqueCapability(requested, capability("filesystem.workspace-read-write"));
|
|
405
|
+
addUniqueCapability(requested, capability(networkCapability));
|
|
406
|
+
|
|
407
|
+
const filesystemRequests = [
|
|
408
|
+
["filesystem.additional-read", policy.allowRead],
|
|
409
|
+
["filesystem.deny-read", policy.denyRead],
|
|
410
|
+
["filesystem.additional-write", policy.allowWrite],
|
|
411
|
+
["filesystem.deny-write", policy.denyWrite],
|
|
412
|
+
];
|
|
413
|
+
for (const [id, values] of filesystemRequests) {
|
|
414
|
+
if (values?.length) {
|
|
415
|
+
addUniqueCapability(
|
|
416
|
+
requested,
|
|
417
|
+
capability(id, { entries: values.length }),
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
const domainRuleCount =
|
|
422
|
+
(policy.allowedDomains?.length || 0) + (policy.deniedDomains?.length || 0);
|
|
423
|
+
if (domainRuleCount > 0) {
|
|
424
|
+
addUniqueCapability(
|
|
425
|
+
requested,
|
|
426
|
+
capability("network.domain-policy", { entries: domainRuleCount }),
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
if (!supportedEngine) {
|
|
431
|
+
unsupported.push(
|
|
432
|
+
capability("backend.engine", {
|
|
433
|
+
reason: "unsupported_engine",
|
|
434
|
+
message: `Unsupported agent sandbox engine: ${engine || "<empty>"}`,
|
|
435
|
+
remediation: "Use engine=docker or engine=bubblewrap.",
|
|
436
|
+
}),
|
|
437
|
+
);
|
|
438
|
+
} else if (!supportedPlatform) {
|
|
439
|
+
unsupported.push(
|
|
440
|
+
capability("backend.platform", {
|
|
441
|
+
reason: "bubblewrap_requires_linux",
|
|
442
|
+
message: `bubblewrap is only supported on Linux; host platform is ${host.platform}`,
|
|
443
|
+
remediation: "Use Docker on this host or run bubblewrap on Linux.",
|
|
444
|
+
}),
|
|
445
|
+
);
|
|
446
|
+
} else {
|
|
447
|
+
addUniqueCapability(
|
|
448
|
+
enforceable,
|
|
449
|
+
capability(isolationCapability, {
|
|
450
|
+
enforcement:
|
|
451
|
+
engine === "docker" ? "docker-container" : "bubblewrap-namespaces",
|
|
452
|
+
}),
|
|
453
|
+
);
|
|
454
|
+
addUniqueCapability(
|
|
455
|
+
enforceable,
|
|
456
|
+
capability("filesystem.workspace-read-write", {
|
|
457
|
+
enforcement:
|
|
458
|
+
engine === "docker" ? "docker-bind-mount" : "bubblewrap-bind-mount",
|
|
459
|
+
}),
|
|
460
|
+
);
|
|
461
|
+
addUniqueCapability(
|
|
462
|
+
enforceable,
|
|
463
|
+
capability(networkCapability, {
|
|
464
|
+
enforcement:
|
|
465
|
+
engine === "docker"
|
|
466
|
+
? sandbox.network
|
|
467
|
+
? "docker-default-network"
|
|
468
|
+
: "docker-network-none"
|
|
469
|
+
: sandbox.network
|
|
470
|
+
? "bubblewrap-share-net"
|
|
471
|
+
: "bubblewrap-unshared-network-namespace",
|
|
472
|
+
}),
|
|
473
|
+
);
|
|
474
|
+
|
|
475
|
+
for (const [id, values] of filesystemRequests) {
|
|
476
|
+
if (!values?.length) continue;
|
|
477
|
+
if (engine === "docker") {
|
|
478
|
+
unsupported.push(
|
|
479
|
+
capability(id, {
|
|
480
|
+
reason: "docker_fine_grained_filesystem_unsupported",
|
|
481
|
+
message:
|
|
482
|
+
"The Docker sandbox backend cannot enforce fine-grained filesystem policy; use engine=bubblewrap",
|
|
483
|
+
remediation:
|
|
484
|
+
"Use engine=bubblewrap on Linux or remove the fine-grained rule.",
|
|
485
|
+
}),
|
|
486
|
+
);
|
|
487
|
+
} else if (id === "filesystem.additional-read") {
|
|
488
|
+
unsupported.push(
|
|
489
|
+
capability(id, {
|
|
490
|
+
reason: "bubblewrap_additional_read_not_isolated",
|
|
491
|
+
message:
|
|
492
|
+
"The bubblewrap agent-shell backend exposes the host root read-only and cannot make allowRead an exclusive read boundary",
|
|
493
|
+
remediation:
|
|
494
|
+
"Remove allowRead or use the attested ProcessExecutionBroker sandbox for a supported execution contract.",
|
|
495
|
+
}),
|
|
496
|
+
);
|
|
497
|
+
} else {
|
|
498
|
+
addUniqueCapability(
|
|
499
|
+
enforceable,
|
|
500
|
+
capability(id, {
|
|
501
|
+
entries: values.length,
|
|
502
|
+
enforcement: `bubblewrap-${id.replace("filesystem.", "")}-mount`,
|
|
503
|
+
}),
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
if (domainRuleCount > 0) {
|
|
509
|
+
unsupported.push(
|
|
510
|
+
capability("network.domain-policy", {
|
|
511
|
+
reason: "domain_policy_has_no_non_bypassable_backend",
|
|
512
|
+
message:
|
|
513
|
+
"Domain-restricted sandbox networking has no non-bypassable backend enforcement; refusing unrestricted network access",
|
|
514
|
+
remediation:
|
|
515
|
+
"Disable sandbox networking or use a separately attested dependency-fetch service.",
|
|
516
|
+
}),
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
const executionObserved = execution !== null;
|
|
522
|
+
const executionAttempted = execution?.attempted === true;
|
|
523
|
+
const executionStarted = execution?.started === true;
|
|
524
|
+
const availabilityChecked = availability !== null || executionStarted;
|
|
525
|
+
const available = executionStarted
|
|
526
|
+
? true
|
|
527
|
+
: availability === null
|
|
528
|
+
? null
|
|
529
|
+
: availability.available === true;
|
|
530
|
+
const availabilityReason = executionStarted
|
|
531
|
+
? null
|
|
532
|
+
: availability?.reason || null;
|
|
533
|
+
let status = "ready";
|
|
534
|
+
if (unsupported.length > 0) status = "unsupported";
|
|
535
|
+
else if (executionStarted) status = "applied";
|
|
536
|
+
else if (executionAttempted) status = "failed-to-start";
|
|
537
|
+
else if (availabilityChecked && !available) status = "unavailable";
|
|
538
|
+
|
|
539
|
+
return {
|
|
540
|
+
schema: AGENT_SANDBOX_CAPABILITY_SCHEMA,
|
|
541
|
+
host: {
|
|
542
|
+
platform: String(host.platform),
|
|
543
|
+
release: String(host.release),
|
|
544
|
+
arch: String(host.arch),
|
|
545
|
+
},
|
|
546
|
+
backend: {
|
|
547
|
+
engine,
|
|
548
|
+
isolationLevel: isolationLevel(sandbox),
|
|
549
|
+
availabilityChecked,
|
|
550
|
+
available,
|
|
551
|
+
reason: availabilityReason,
|
|
552
|
+
},
|
|
553
|
+
status,
|
|
554
|
+
execution: {
|
|
555
|
+
observed: executionObserved,
|
|
556
|
+
attempted: executionAttempted,
|
|
557
|
+
started: executionStarted,
|
|
558
|
+
},
|
|
559
|
+
requested,
|
|
560
|
+
enforceable,
|
|
561
|
+
applied: executionStarted ? enforceable.map((entry) => ({ ...entry })) : [],
|
|
562
|
+
unsupported,
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
export function assertSandboxCapabilities(sandbox, options = {}) {
|
|
567
|
+
const report = assessAgentSandboxCapabilities(sandbox, options);
|
|
568
|
+
if (report.unsupported.length === 0) return report;
|
|
569
|
+
const error = new Error(
|
|
570
|
+
`Unsupported sandbox capability request: ${report.unsupported
|
|
571
|
+
.map((entry) => `${entry.id} (${entry.message})`)
|
|
572
|
+
.join("; ")}`,
|
|
573
|
+
);
|
|
574
|
+
error.code = "CONFIG_SANDBOX_CAPABILITY_UNSUPPORTED";
|
|
575
|
+
error.capabilityReport = report;
|
|
576
|
+
throw error;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
function attachSandboxCapabilityReport(
|
|
580
|
+
result,
|
|
581
|
+
sandbox,
|
|
582
|
+
execution,
|
|
583
|
+
availability,
|
|
584
|
+
host,
|
|
585
|
+
) {
|
|
586
|
+
return {
|
|
587
|
+
...result,
|
|
588
|
+
sandboxCapabilities: assessAgentSandboxCapabilities(sandbox, {
|
|
589
|
+
execution,
|
|
590
|
+
availability,
|
|
591
|
+
host,
|
|
592
|
+
}),
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
|
|
325
596
|
export function executeSandboxedShell(command, sandbox, options = {}) {
|
|
326
597
|
if (!sandbox || !["docker", "bubblewrap"].includes(sandbox.engine)) {
|
|
327
598
|
throw new Error("A supported agent sandbox configuration is required");
|
|
328
599
|
}
|
|
329
600
|
const hostCwd = path.resolve(options.cwd || sandbox.cwd);
|
|
330
601
|
const policy = sandbox.policy || normalizeSandboxPolicy({}, hostCwd);
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
if (
|
|
337
|
-
(policy.allowedDomains.length || policy.deniedDomains.length) &&
|
|
338
|
-
sandbox.network
|
|
339
|
-
) {
|
|
602
|
+
const capabilityHost = _deps.host();
|
|
603
|
+
const capabilityReport = assessAgentSandboxCapabilities(sandbox, {
|
|
604
|
+
host: capabilityHost,
|
|
605
|
+
});
|
|
606
|
+
if (capabilityReport.unsupported.length > 0) {
|
|
340
607
|
return {
|
|
341
608
|
stdout: "",
|
|
342
|
-
stderr:
|
|
343
|
-
|
|
609
|
+
stderr: capabilityReport.unsupported
|
|
610
|
+
.map((entry) => entry.message)
|
|
611
|
+
.join("; "),
|
|
344
612
|
exitCode: 1,
|
|
345
613
|
failedToStart: true,
|
|
614
|
+
sandboxCapabilities: capabilityReport,
|
|
346
615
|
};
|
|
347
616
|
}
|
|
617
|
+
// Proxy environment variables are advisory: a child can clear them or open a
|
|
618
|
+
// raw socket. Until a backend can enforce egress below the process layer,
|
|
619
|
+
// domain-restricted networking must fail closed instead of granting the
|
|
620
|
+
// sandbox an unrestricted network namespace.
|
|
621
|
+
const egress = options.egressProxy || null;
|
|
348
622
|
if (sandbox.engine === "bubblewrap") {
|
|
349
623
|
return executeBubblewrapShell(command, sandbox, options, hostCwd, policy);
|
|
350
624
|
}
|
|
351
|
-
if (
|
|
352
|
-
policy.allowRead.length ||
|
|
353
|
-
policy.denyRead.length ||
|
|
354
|
-
policy.allowWrite.length ||
|
|
355
|
-
policy.denyWrite.length
|
|
356
|
-
) {
|
|
357
|
-
return {
|
|
358
|
-
stdout: "",
|
|
359
|
-
stderr:
|
|
360
|
-
"The Docker sandbox backend cannot enforce fine-grained filesystem policy; use engine=bubblewrap",
|
|
361
|
-
exitCode: 1,
|
|
362
|
-
failedToStart: true,
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
625
|
const args = ["run", "--rm", "--init"];
|
|
366
626
|
if (!sandbox.network) args.push("--network", "none");
|
|
367
627
|
args.push("--mount", `type=bind,source=${hostCwd},target=/workspace`);
|
|
@@ -397,22 +657,34 @@ export function executeSandboxedShell(command, sandbox, options = {}) {
|
|
|
397
657
|
auditContext: options.auditContext,
|
|
398
658
|
});
|
|
399
659
|
if (result.error) {
|
|
400
|
-
return
|
|
660
|
+
return attachSandboxCapabilityReport(
|
|
661
|
+
{
|
|
662
|
+
stdout: result.stdout || "",
|
|
663
|
+
stderr:
|
|
664
|
+
result.error.code === "ENOENT"
|
|
665
|
+
? "Docker is not installed"
|
|
666
|
+
: result.error.message,
|
|
667
|
+
exitCode: typeof result.status === "number" ? result.status : 1,
|
|
668
|
+
failedToStart: true,
|
|
669
|
+
},
|
|
670
|
+
sandbox,
|
|
671
|
+
{ attempted: true, started: false },
|
|
672
|
+
{ available: false, reason: result.error.message },
|
|
673
|
+
capabilityHost,
|
|
674
|
+
);
|
|
675
|
+
}
|
|
676
|
+
return attachSandboxCapabilityReport(
|
|
677
|
+
{
|
|
401
678
|
stdout: result.stdout || "",
|
|
402
|
-
stderr:
|
|
403
|
-
result.error.code === "ENOENT"
|
|
404
|
-
? "Docker is not installed"
|
|
405
|
-
: result.error.message,
|
|
679
|
+
stderr: result.stderr || "",
|
|
406
680
|
exitCode: typeof result.status === "number" ? result.status : 1,
|
|
407
|
-
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
signal: result.signal || null,
|
|
415
|
-
};
|
|
681
|
+
signal: result.signal || null,
|
|
682
|
+
},
|
|
683
|
+
sandbox,
|
|
684
|
+
{ attempted: true, started: true },
|
|
685
|
+
{ available: true, reason: null },
|
|
686
|
+
capabilityHost,
|
|
687
|
+
);
|
|
416
688
|
}
|
|
417
689
|
|
|
418
690
|
function executeBubblewrapShell(command, sandbox, options, hostCwd, policy) {
|
|
@@ -469,22 +741,34 @@ function executeBubblewrapShell(command, sandbox, options, hostCwd, policy) {
|
|
|
469
741
|
auditContext: options.auditContext,
|
|
470
742
|
});
|
|
471
743
|
if (result.error) {
|
|
472
|
-
return
|
|
744
|
+
return attachSandboxCapabilityReport(
|
|
745
|
+
{
|
|
746
|
+
stdout: result.stdout || "",
|
|
747
|
+
stderr:
|
|
748
|
+
result.error.code === "ENOENT"
|
|
749
|
+
? "bubblewrap is not installed"
|
|
750
|
+
: result.error.message,
|
|
751
|
+
exitCode: typeof result.status === "number" ? result.status : 1,
|
|
752
|
+
failedToStart: true,
|
|
753
|
+
},
|
|
754
|
+
sandbox,
|
|
755
|
+
{ attempted: true, started: false },
|
|
756
|
+
{ available: false, reason: result.error.message },
|
|
757
|
+
_deps.host(),
|
|
758
|
+
);
|
|
759
|
+
}
|
|
760
|
+
return attachSandboxCapabilityReport(
|
|
761
|
+
{
|
|
473
762
|
stdout: result.stdout || "",
|
|
474
|
-
stderr:
|
|
475
|
-
result.error.code === "ENOENT"
|
|
476
|
-
? "bubblewrap is not installed"
|
|
477
|
-
: result.error.message,
|
|
763
|
+
stderr: result.stderr || "",
|
|
478
764
|
exitCode: typeof result.status === "number" ? result.status : 1,
|
|
479
|
-
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
signal: result.signal || null,
|
|
487
|
-
};
|
|
765
|
+
signal: result.signal || null,
|
|
766
|
+
},
|
|
767
|
+
sandbox,
|
|
768
|
+
{ attempted: true, started: true },
|
|
769
|
+
{ available: true, reason: null },
|
|
770
|
+
_deps.host(),
|
|
771
|
+
);
|
|
488
772
|
}
|
|
489
773
|
|
|
490
774
|
/**
|