chainlesschain 0.162.181 → 0.162.182
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -1
- package/scripts/build-windows-sandbox-helper.ps1 +163 -0
- package/src/assets/web-panel/assets/{AIOps-cq0dwbnf.js → AIOps-DzZ5_xoj.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CvcgGl3w.js → ActionButton-DeLXddIg.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-hM2-jFqg.js → Analytics-rvDCmet1.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-B9_Gsd_g.js → AppLayout-Yt6QVDnp.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-B7bu52Og.js → Artifacts-BS112K5L.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-DThfDgqB.js → Audit-0wJuQrNu.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DjlFiD4v.js → BackgroundAgents-B90PMgbn.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CK9xJKnG.js → Backup-TkgMglQQ.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-DEiSU8K8.js → BaseInput-CQVS9p1l.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CpT96czj.js → Chat-YTjQHoC7.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-BKPPNmZI.js → ChatBubbleRenderer-PR074hUN.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-C1GfDnO0.js → Checkbox-5bwaOabq.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-3DAKgiLx.js → Codegen-BFmNQ_Xe.js} +1 -1
- package/src/assets/web-panel/assets/{Col-74cOwZU1.js → Col-BT_u4Dzp.js} +1 -1
- package/src/assets/web-panel/assets/{Community-tn9Kkz9j.js → Community-CJP52u5b.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BcoXH7m4.js → Compact-BpzhJE9i.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-DIPGUBgi.js → Compliance-Cg7rfslp.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-doD5_91c.js → Cowork-JisxL6Yy.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-C-IDvubz.js → Cron-Bu7Ug_MC.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CdcCoBdj.js → Crosschain-CvuqoLdj.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DdH5aMMA.js → DID-C2u9G8Pu.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-DHLA4mm0.js → Dashboard-BFt5Yv3d.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-dEeCt7Md.js → Dropdown-DIaT9Wxq.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-BMaecFv9.js → EmailListRenderer-D_A601Y4.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DUaUukTN.js → FamilyGuardDashboard--IyQ8I8w.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CMBE0_rp.js → Federation-BihWHxuY.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-PG-JDbXq.js → FormItemContext-BB8dOXc_.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-Bcb0p88m.js → GenericCardRenderer-DQYhj1HH.js} +1 -1
- package/src/assets/web-panel/assets/{Git-Bgv15myB.js → Git-B-2QZxGf.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DB8YTArI.js → Governance-CusSb-nG.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-BQMwCWaS.js → Inference-BAjmvPPL.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-B1_ZziiB.js → KnowledgeGraph-DoNYWKYq.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-DovEEnt_.js → Logs-B8fKWD-n.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-D201OL4T.js → MarkdownRenderer-BlJm1J7E.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-BlCXSpyB.js → Marketplace-CyOscbSL.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CsCR09Wj.js → McpTools-Ex6Om5da.js} +5 -5
- package/src/assets/web-panel/assets/{Memory-CBVRLKno.js → Memory-CDcD8l8r.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-C9OIafgA.js → MobileBridge-xfBqoFDg.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-D_zoJ8Xs.js → MobileProjects-BwObMMA2.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-vE-HdvLj.js → Mtc-CIWd36OV.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-CPLaekCd.js → MtcAudit-CPX0ouuA.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-C_UP9C2o.js → Multisig-BDJsIUuW.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-2nODJcU1.js → NLProgramming-DEkbuD3N.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-BhE-SJGu.js → Notes-DJpHRhH1.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-D21q7BNU.js → NotificationSettings-C1UZ-Qd5.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-0b62GYOD.js → OrderTableRenderer-GlJtqLjT.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-CEqmw_sb.js → Organization-Bbhj0fac.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-MW-gMDO_.js → Overflow-1H04x3kx.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CY0hjI_G.js → P2P-CDpPe3et.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-BbWh7Man.js → PdhVaultBrowser-MUX0Bpvw.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-ChqEA_4Q.js → Permissions-A07-0Ci1.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-B3YrbYfD.js → PersonalDataHub-DhhDWxAZ.js} +5 -5
- package/src/assets/web-panel/assets/{Pipeline-B8WBhhlW.js → Pipeline-CyfbJfe-.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-Cmb0PXNx.js → Privacy-CNFps3ED.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-hF6zW3Nz.js → ProjectInit--T-u3Dr5.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-BFSVfpW0.js → ProjectSettings-DJmrK2fC.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-DAWkVFkc.js → Projects-Qx_MdX9k.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-B8yux8Dx.js → Providers-DLzzbOZd.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-N76cQluO.js → QrScannerModal-CexOomKS.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-ClvZ0KYR.js → QuickAsk-QklGi19_.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-B-GfgBpT.js → Recommend-Bb9kwSw8.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-mlglCdQi.js → RemoteSession-DZuVNNN5.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-DJIZzQeG.js → Reputation-Dr5cLP0N.js} +1 -1
- package/src/assets/web-panel/assets/{Row-COzxu_bb.js → Row-oCQHYv5t.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CoYsJQuE.js → RssFeed-IFDEykIR.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DC77Mq9S.js → Search-CspVIxDc.js} +1 -1
- package/src/assets/web-panel/assets/{Security-Loy2EdMO.js → Security-Bm66o_DH.js} +3 -3
- package/src/assets/web-panel/assets/{Services-GUD07Eu0.js → Services-DvanNqXl.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DWzkptYU.js → Skeleton-CHjEe9_O.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CEDn1r-Z.js → Skills-Cb8jWjMX.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-ub_k4pXh.js → Sla-DxZm1491.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-D7HLX9CA.js → SpeechSettings-DWxEEclC.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DbwOvl6m.js → SyncSettings-FIvOFw5p.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-CBQzoAu5.js → Tasks-CyuLnDFR.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BNVeIhud.js → Templates-CaNjzV_t.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-PS9AzhXU.js → Tenant-DjlP6TmH.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-DwzGMniO.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-CrmXMOkg.js → TimelineRenderer-DoZ8y7y8.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DD-VDHw1.js → Tokens-390cg2TC.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BsoN_n-n.js → Trigger-CLrtCj5_.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-n8LmN4ZV.js → Trust-DpESfSPn.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-C9_7MImA.js → UkeySign-CN6279O0.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DyBteNgn.js → VideoEditing-DPtAUlSe.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BS5ixeXI.js → Wallet-nKOMV_1n.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-spc4UImU.js → WebAuthn-HuXlSOc4.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-D7iVvaBO.js → WorkflowEditor-CUfFjARi.js} +1 -1
- package/src/assets/web-panel/assets/{chat-6CmBkHrL.js → chat-6Eq0PcZJ.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BGoCLkxI.js → colors-BP_Sf6Iy.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-fYZBetMO.js → compact-item-BufMKIh5.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BeM-1UVj.js → createContext-BBMXxWSW.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DgVKduH2.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-CE7ZuEnV.js → hasIn-fUK_tRO2.js} +1 -1
- package/src/assets/web-panel/assets/{index-QIpnpZgz.js → index-2A5ph8b2.js} +1 -1
- package/src/assets/web-panel/assets/{index-BU_2qiDk.js → index-3FuwBewR.js} +1 -1
- package/src/assets/web-panel/assets/{index--lap6cf7.js → index-6GmBa4Kg.js} +1 -1
- package/src/assets/web-panel/assets/{index-De0quFDw.js → index-B2vS66eI.js} +1 -1
- package/src/assets/web-panel/assets/{index-D1r9tT3J.js → index-B7Etk0Te.js} +1 -1
- package/src/assets/web-panel/assets/{index-YjcumOZ4.js → index-B9WYSn4m.js} +1 -1
- package/src/assets/web-panel/assets/{index-MtOuq2i6.js → index-BHy6yNiF.js} +1 -1
- package/src/assets/web-panel/assets/{index-RMZ8a7Yt.js → index-BMLHv389.js} +1 -1
- package/src/assets/web-panel/assets/{index-C0v6YKKO.js → index-BWKoBU8R.js} +1 -1
- package/src/assets/web-panel/assets/{index-CRnUE8Cb.js → index-Bkg4ZePE.js} +1 -1
- package/src/assets/web-panel/assets/{index-BsMfoaeo.js → index-C44atv4k.js} +1 -1
- package/src/assets/web-panel/assets/{index-DoXk5KJ8.js → index-CE2DdTP2.js} +1 -1
- package/src/assets/web-panel/assets/{index-B4wiTEOM.js → index-CGjmILDm.js} +1 -1
- package/src/assets/web-panel/assets/{index-zb7rVOhV.js → index-CW_G-MXw.js} +1 -1
- package/src/assets/web-panel/assets/{index-ATcSr_2O.js → index-CZ6Yt17L.js} +1 -1
- package/src/assets/web-panel/assets/{index-C9Y3k0HI.js → index-CeASi4fr.js} +1 -1
- package/src/assets/web-panel/assets/{index-B2U-ObMq.js → index-CgiECHu2.js} +1 -1
- package/src/assets/web-panel/assets/{index-Puq6Luf1.js → index-Cp8vhyZy.js} +1 -1
- package/src/assets/web-panel/assets/{index-BV551878.js → index-CwSf5pnf.js} +1 -1
- package/src/assets/web-panel/assets/{index-BowH1eLQ.js → index-D4_MuGkd.js} +1 -1
- package/src/assets/web-panel/assets/{index-B3CDgvNW.js → index-D9vU25ij.js} +1 -1
- package/src/assets/web-panel/assets/{index-WUrJ6S1j.js → index-DASluSqY.js} +1 -1
- package/src/assets/web-panel/assets/{index-CRLjEP1H.js → index-DLpIs_P_.js} +1 -1
- package/src/assets/web-panel/assets/index-DOZTSoS7.js +1 -0
- package/src/assets/web-panel/assets/{index-DT3zPSVX.js → index-DPdUNk1i.js} +1 -1
- package/src/assets/web-panel/assets/{index-BunaQCa0.js → index-DVsqvI4M.js} +1 -1
- package/src/assets/web-panel/assets/index-DhpvjpqI.js +1 -0
- package/src/assets/web-panel/assets/{index-CIpVrf5P.js → index-DmkMXwnR.js} +1 -1
- package/src/assets/web-panel/assets/{index-lJBjB1QX.js → index-DocdRcbd.js} +1 -1
- package/src/assets/web-panel/assets/{index-BEVm0lCS.js → index-Dyngbd29.js} +19 -19
- package/src/assets/web-panel/assets/{index-C4SJVjs4.js → index-GwdRUZ-x.js} +1 -1
- package/src/assets/web-panel/assets/{index-ukg99D1V.js → index-LvCBfTLo.js} +1 -1
- package/src/assets/web-panel/assets/{index-BfPL-m46.js → index-cpEli44X.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpIGIB85.js → index-fzaMtSJ8.js} +1 -1
- package/src/assets/web-panel/assets/{index-BNZDILcO.js → index-pum7HYBA.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dw1PyYPm.js → index-t8N1tSeX.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cip8emOQ.js → index-uCbEN7cY.js} +1 -1
- package/src/assets/web-panel/assets/{index-DsvfrESp.js → index-wKTLbKyc.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8BsdNV_.js → index-wV6iGdpY.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-CYHMs1ag.js → initDefaultProps-V5Fo95FM.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DDB2Ffk5.js → motion-BYWU0hUT.js} +1 -1
- package/src/assets/web-panel/assets/{move-Bg3cD-dX.js → move-Cr1M-J2h.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-B5nedjTS.js → mtc-parser-BysQKi2N.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BHyuUILu.js → omit-D1zHU8GC.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-C9YQnEN9.js → pickAttrs-CUArxtfi.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DBUFYUe7.js → placementArrow-ChoYEys0.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-nBs2Obnk.js → responsiveObserve-BQRs3Mo7.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DkCEaXNU.js → slide-B8zbsCkg.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-aqE1Wi6U.js → statusUtils-C2U8Gs6h.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CN5bhfHB.js → styleChecker-Dd8MgL_V.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-B_oX_kvJ.js → useFlexGapSupport-hknqY5NH.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-rCuXHeme.js → useFs-CLTAmcfw.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-DZR9Abyd.js → usePersonalDataHub-ByegHbiB.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-ConCYQlX.js → vnode-DqlAy5DP.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-CUdDxG5M.js → zoom-DiXiztQn.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/agenda.js +115 -3
- package/src/commands/agent.js +6 -0
- package/src/data/changelog.json +13 -0
- package/src/gateways/terminal/PtyManager.js +45 -4
- package/src/gateways/ws/ws-server.js +10 -1
- package/src/harness/background-task-manager.js +70 -2
- package/src/harness/worktree-isolator.js +14 -3
- package/src/lib/agent-core.js +1 -0
- package/src/lib/agent-schedule-store.js +45 -22
- package/src/lib/hook-runner.js +6 -2
- package/src/lib/packer/pkg-config-generator.js +3 -1
- package/src/lib/plugin-runtime/bin.js +1148 -70
- package/src/lib/plugin-runtime/manifest.js +68 -12
- package/src/lib/plugin-runtime/scopes.js +20 -10
- package/src/lib/process-execution-broker/index.js +375 -48
- package/src/lib/process-execution-broker/platform-sandbox.js +3831 -276
- package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
- package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
- package/src/lib/process-execution-broker/windows-sandbox.cs +3856 -0
- package/src/lib/repl-bang-memorize.js +67 -10
- package/src/lib/slash-commands.js +27 -4
- package/src/repl/agent-repl.js +4 -3
- package/src/runtime/agent-core.js +376 -52
- package/src/runtime/agent-runtime.js +13 -1
- package/src/runtime/headless-runner.js +4 -3
- package/src/assets/web-panel/assets/Terminal-Cgb4eLB_.js +0 -3
- package/src/assets/web-panel/assets/devWarning-BzPwHnw8.js +0 -1
- package/src/assets/web-panel/assets/index-DacrAdc-.js +0 -1
- package/src/assets/web-panel/assets/index-EHzNJozo.js +0 -1
- package/src/lib/process-execution-broker/windows-sandbox.ps1 +0 -999
|
@@ -151,6 +151,56 @@ function runCodeProcess(file, args, options = {}, origin = "run-code") {
|
|
|
151
151
|
});
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
function collectWorkspacePluginBinSandboxPolicy(
|
|
155
|
+
pluginBin,
|
|
156
|
+
workspaceCwd,
|
|
157
|
+
executionCwd = workspaceCwd,
|
|
158
|
+
) {
|
|
159
|
+
const resolvedWorkspaceCwd = path.resolve(workspaceCwd);
|
|
160
|
+
const pluginPolicyBoundaries = new Set();
|
|
161
|
+
for (const policyCwd of new Set([
|
|
162
|
+
resolvedWorkspaceCwd,
|
|
163
|
+
path.resolve(executionCwd),
|
|
164
|
+
])) {
|
|
165
|
+
const observedPolicy = pluginBin.collectPluginBinSandboxPolicy({
|
|
166
|
+
cwd: policyCwd,
|
|
167
|
+
});
|
|
168
|
+
for (const boundary of observedPolicy?.requiredBoundaries || []) {
|
|
169
|
+
pluginPolicyBoundaries.add(boundary);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return pluginBin.pinPluginBinSandboxPolicy(
|
|
173
|
+
{ requiredBoundaries: [...pluginPolicyBoundaries] },
|
|
174
|
+
{ cwd: resolvedWorkspaceCwd },
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function rethrowRunCodeSandboxFailure(error) {
|
|
179
|
+
if (
|
|
180
|
+
error?.sandboxFailClosed === true ||
|
|
181
|
+
(typeof error?.code === "string" &&
|
|
182
|
+
error.code.startsWith("ERR_PROCESS_SANDBOX"))
|
|
183
|
+
) {
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function createPythonInterpreterProbeSandboxFailure(sandboxPolicy) {
|
|
189
|
+
const requiredBoundaries = [...(sandboxPolicy?.requiredBoundaries || [])];
|
|
190
|
+
const error = new Error(
|
|
191
|
+
`Python interpreter discovery cannot run without its required sandbox boundaries: ${requiredBoundaries.join(", ")}`,
|
|
192
|
+
);
|
|
193
|
+
error.code = "ERR_PROCESS_SANDBOX_BOUNDARY_UNSATISFIED";
|
|
194
|
+
error.sandboxReason = "python_interpreter_probe_requires_sandbox";
|
|
195
|
+
error.sandboxFailClosed = true;
|
|
196
|
+
error.requiredBoundaries = requiredBoundaries;
|
|
197
|
+
error.actualGuarantees = [];
|
|
198
|
+
error.missingBoundaries = [...requiredBoundaries];
|
|
199
|
+
error.sandboxBackend = null;
|
|
200
|
+
error.sandboxCandidateBackend = null;
|
|
201
|
+
return error;
|
|
202
|
+
}
|
|
203
|
+
|
|
154
204
|
// ─── Background shell tasks ────────────────────────────────────────────────
|
|
155
205
|
//
|
|
156
206
|
// run_shell is synchronous (execSync) and capped at a foreground timeout, which
|
|
@@ -839,6 +889,10 @@ export function getCachedPython() {
|
|
|
839
889
|
return _cachedPython;
|
|
840
890
|
}
|
|
841
891
|
|
|
892
|
+
export function _resetCachedPythonForTests() {
|
|
893
|
+
_cachedPython = null;
|
|
894
|
+
}
|
|
895
|
+
|
|
842
896
|
/**
|
|
843
897
|
* Gather environment info (cached once per process).
|
|
844
898
|
* @returns {{ os: string, arch: string, python: string|null, pip: boolean, node: string|null, git: boolean }}
|
|
@@ -1189,10 +1243,7 @@ function agentFileToolPathRequests(name, args = {}, workspaceRoots = []) {
|
|
|
1189
1243
|
case "notebook_edit":
|
|
1190
1244
|
return one("path", "write");
|
|
1191
1245
|
case "move_file":
|
|
1192
|
-
return [
|
|
1193
|
-
...one("path", "write"),
|
|
1194
|
-
...one("target_path", "write"),
|
|
1195
|
-
];
|
|
1246
|
+
return [...one("path", "write"), ...one("target_path", "write")];
|
|
1196
1247
|
case "list_dir":
|
|
1197
1248
|
return [
|
|
1198
1249
|
{
|
|
@@ -1234,10 +1285,7 @@ function agentFileToolPathRequests(name, args = {}, workspaceRoots = []) {
|
|
|
1234
1285
|
}
|
|
1235
1286
|
|
|
1236
1287
|
function guardAgentFileToolPaths(name, args, context, cwd) {
|
|
1237
|
-
const workspaceRoots = workspaceRootsFor(
|
|
1238
|
-
cwd,
|
|
1239
|
-
context.additionalDirectories,
|
|
1240
|
-
);
|
|
1288
|
+
const workspaceRoots = workspaceRootsFor(cwd, context.additionalDirectories);
|
|
1241
1289
|
const requests = agentFileToolPathRequests(name, args || {}, workspaceRoots);
|
|
1242
1290
|
for (const request of requests) {
|
|
1243
1291
|
const verdict = resolveSandboxPolicyPath(request.path, {
|
|
@@ -3471,25 +3519,117 @@ async function executeToolInner(
|
|
|
3471
3519
|
: {}
|
|
3472
3520
|
: { shell: shellInv.kind };
|
|
3473
3521
|
|
|
3474
|
-
//
|
|
3475
|
-
//
|
|
3476
|
-
//
|
|
3477
|
-
|
|
3522
|
+
// Policy-bearing plugin bins never enter PATH. Their declared alias is
|
|
3523
|
+
// accepted only as one direct command: resolve it to literal argv, attest
|
|
3524
|
+
// the exact target, then give Broker an absolute command with shell:false.
|
|
3525
|
+
// Resolver failures for a matching strict alias are terminal — falling
|
|
3526
|
+
// back to a shell would bypass target identity and manifest requirements.
|
|
3527
|
+
let pluginBinInvocation = null;
|
|
3528
|
+
let reattestPluginBinInvocation = null;
|
|
3529
|
+
let pluginBinSandboxPolicy = null;
|
|
3530
|
+
let pluginBinSandboxExecutionContract = null;
|
|
3478
3531
|
try {
|
|
3479
|
-
const
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3532
|
+
const pluginBin = await import("../lib/plugin-runtime/bin.js");
|
|
3533
|
+
reattestPluginBinInvocation = pluginBin.reattestPluginBinInvocation;
|
|
3534
|
+
pluginBinSandboxPolicy = collectWorkspacePluginBinSandboxPolicy(
|
|
3535
|
+
pluginBin,
|
|
3536
|
+
cwd,
|
|
3537
|
+
args.cwd || cwd,
|
|
3538
|
+
);
|
|
3539
|
+
pluginBinInvocation = pluginBin.resolvePluginBinInvocation(
|
|
3540
|
+
args.command,
|
|
3541
|
+
{
|
|
3542
|
+
cwd,
|
|
3543
|
+
commandCwd: args.cwd || cwd,
|
|
3544
|
+
},
|
|
3545
|
+
);
|
|
3546
|
+
if (pluginBinInvocation?.sandboxPolicy) {
|
|
3547
|
+
pluginBinSandboxPolicy = pluginBin.pinPluginBinSandboxPolicy(
|
|
3548
|
+
{
|
|
3549
|
+
requiredBoundaries: [
|
|
3550
|
+
...(pluginBinSandboxPolicy?.requiredBoundaries || []),
|
|
3551
|
+
...(pluginBinInvocation.sandboxPolicy.requiredBoundaries || []),
|
|
3552
|
+
],
|
|
3553
|
+
},
|
|
3554
|
+
{ cwd },
|
|
3555
|
+
);
|
|
3556
|
+
if (
|
|
3557
|
+
process.platform === "linux" ||
|
|
3558
|
+
(process.platform === "win32" &&
|
|
3559
|
+
pluginBinInvocation.runtime === "node")
|
|
3560
|
+
) {
|
|
3561
|
+
try {
|
|
3562
|
+
pluginBinSandboxExecutionContract =
|
|
3563
|
+
pluginBin.createPluginSandboxExecutionContract(
|
|
3564
|
+
pluginBinInvocation,
|
|
3565
|
+
);
|
|
3566
|
+
} catch (error) {
|
|
3567
|
+
if (error?.pluginBinFailClosed) throw error;
|
|
3568
|
+
const contractError = new Error(
|
|
3569
|
+
`plugin sandbox execution contract could not be created: ${error.message}`,
|
|
3570
|
+
);
|
|
3571
|
+
contractError.code = "ERR_PLUGIN_SANDBOX_CONTRACT_UNATTESTED";
|
|
3572
|
+
contractError.pluginBinFailClosed = true;
|
|
3573
|
+
throw contractError;
|
|
3574
|
+
}
|
|
3575
|
+
}
|
|
3576
|
+
}
|
|
3577
|
+
} catch (err) {
|
|
3578
|
+
if (err?.pluginBinFailClosed) {
|
|
3579
|
+
const policyVia =
|
|
3580
|
+
err.code === "ERR_PLUGIN_BIN_DISCOVERY_FAILED"
|
|
3581
|
+
? "plugin-bin-pinned-sandbox-policy"
|
|
3582
|
+
: "plugin-bin-direct-invocation";
|
|
3583
|
+
return attachDescriptor(
|
|
3584
|
+
{
|
|
3585
|
+
error: `[Plugin bin] ${err.message}`,
|
|
3586
|
+
policy: {
|
|
3587
|
+
decision: "deny",
|
|
3588
|
+
via: policyVia,
|
|
3589
|
+
reason: err.code || "plugin_bin_resolution_failed",
|
|
3590
|
+
},
|
|
3591
|
+
shellCommandPolicy: shellPolicy,
|
|
3592
|
+
approval: approvalOutcome,
|
|
3593
|
+
},
|
|
3594
|
+
override || runtimeDescriptor,
|
|
3595
|
+
);
|
|
3596
|
+
}
|
|
3597
|
+
pluginBinInvocation = null;
|
|
3484
3598
|
}
|
|
3485
|
-
const processOrigin =
|
|
3599
|
+
const processOrigin = pluginBinInvocation
|
|
3486
3600
|
? "plugin:bin"
|
|
3487
3601
|
: "tool:run_shell";
|
|
3488
|
-
const processProvenance =
|
|
3602
|
+
const processProvenance = {
|
|
3603
|
+
...(pluginBinInvocation
|
|
3604
|
+
? {
|
|
3605
|
+
pluginId: pluginBinInvocation.pluginId,
|
|
3606
|
+
pluginVersion: pluginBinInvocation.pluginVersion,
|
|
3607
|
+
pluginSource: pluginBinInvocation.pluginSource,
|
|
3608
|
+
pluginExecutableIdentity: pluginBinInvocation.executableIdentity,
|
|
3609
|
+
}
|
|
3610
|
+
: {}),
|
|
3611
|
+
...(pluginBinSandboxPolicy
|
|
3612
|
+
? { sandboxPolicy: pluginBinSandboxPolicy }
|
|
3613
|
+
: {}),
|
|
3614
|
+
...(pluginBinSandboxExecutionContract
|
|
3615
|
+
? {
|
|
3616
|
+
sandboxExecutionContract: pluginBinSandboxExecutionContract,
|
|
3617
|
+
}
|
|
3618
|
+
: {}),
|
|
3619
|
+
};
|
|
3620
|
+
const pluginBinResult = pluginBinInvocation
|
|
3489
3621
|
? {
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3622
|
+
plugin_bin: {
|
|
3623
|
+
plugin: pluginBinInvocation.pluginId,
|
|
3624
|
+
version: pluginBinInvocation.pluginVersion,
|
|
3625
|
+
name: pluginBinInvocation.binName,
|
|
3626
|
+
target: pluginBinInvocation.binPath,
|
|
3627
|
+
runtime: pluginBinInvocation.runtime,
|
|
3628
|
+
sha256: pluginBinInvocation.executableIdentity.sha256,
|
|
3629
|
+
identity_attested: true,
|
|
3630
|
+
launch_identity_reattested: false,
|
|
3631
|
+
direct_argv: true,
|
|
3632
|
+
},
|
|
3493
3633
|
}
|
|
3494
3634
|
: {};
|
|
3495
3635
|
|
|
@@ -3504,6 +3644,23 @@ async function executeToolInner(
|
|
|
3504
3644
|
policy: { decision: "deny", via: "sandbox" },
|
|
3505
3645
|
});
|
|
3506
3646
|
}
|
|
3647
|
+
if (
|
|
3648
|
+
(process.platform === "linux" || process.platform === "win32") &&
|
|
3649
|
+
pluginBinSandboxPolicy?.requiredBoundaries?.length > 0
|
|
3650
|
+
) {
|
|
3651
|
+
return attachDescriptor({
|
|
3652
|
+
error:
|
|
3653
|
+
"[Plugin bin] The current strong plugin boundary supports foreground execution only; background execution is fail-closed until Broker-owned process-tree teardown is available.",
|
|
3654
|
+
policy: {
|
|
3655
|
+
decision: "deny",
|
|
3656
|
+
via: "plugin-bin-pinned-sandbox-policy",
|
|
3657
|
+
reason: "background_execution_unsupported",
|
|
3658
|
+
},
|
|
3659
|
+
...pluginBinResult,
|
|
3660
|
+
shellCommandPolicy: shellPolicy,
|
|
3661
|
+
approval: approvalOutcome,
|
|
3662
|
+
});
|
|
3663
|
+
}
|
|
3507
3664
|
// Free memory from idle background tasks before adding another, so a
|
|
3508
3665
|
// long agent run can't accumulate forgotten dev servers (no-op unless
|
|
3509
3666
|
// the machine is actually under memory pressure).
|
|
@@ -3559,9 +3716,29 @@ async function executeToolInner(
|
|
|
3559
3716
|
scope: "agent",
|
|
3560
3717
|
...processProvenance,
|
|
3561
3718
|
};
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3719
|
+
let child;
|
|
3720
|
+
if (pluginBinInvocation) {
|
|
3721
|
+
reattestPluginBinInvocation(pluginBinInvocation);
|
|
3722
|
+
pluginBinResult.plugin_bin.launch_identity_reattested = true;
|
|
3723
|
+
child = broker.spawn(
|
|
3724
|
+
pluginBinSandboxExecutionContract?.kind ===
|
|
3725
|
+
"strict-plugin-node-bin"
|
|
3726
|
+
? pluginBinSandboxExecutionContract.runtimePath
|
|
3727
|
+
: pluginBinInvocation.command,
|
|
3728
|
+
pluginBinInvocation.args,
|
|
3729
|
+
{
|
|
3730
|
+
...brokerOpts,
|
|
3731
|
+
cwd:
|
|
3732
|
+
pluginBinSandboxExecutionContract?.workingDirectory ||
|
|
3733
|
+
brokerOpts.cwd,
|
|
3734
|
+
shell: false,
|
|
3735
|
+
},
|
|
3736
|
+
);
|
|
3737
|
+
} else {
|
|
3738
|
+
child = shellInv.useDefaultShell
|
|
3739
|
+
? broker.spawn(args.command, [], brokerOpts)
|
|
3740
|
+
: broker.spawn(shellInv.file, shellInv.argv, brokerOpts);
|
|
3741
|
+
}
|
|
3565
3742
|
task.child = child;
|
|
3566
3743
|
if (child.stdout) {
|
|
3567
3744
|
child.stdout.setEncoding("utf8");
|
|
@@ -3612,6 +3789,7 @@ async function executeToolInner(
|
|
|
3612
3789
|
status: task.status,
|
|
3613
3790
|
command: task.command,
|
|
3614
3791
|
...shellMeta,
|
|
3792
|
+
...pluginBinResult,
|
|
3615
3793
|
hint: "Poll output and completion with the check_shell tool using this task_id. Kill long-lived servers with check_shell { task_id, kill: true } when done.",
|
|
3616
3794
|
shellCommandPolicy: shellPolicy,
|
|
3617
3795
|
approval: approvalOutcome,
|
|
@@ -3621,6 +3799,23 @@ async function executeToolInner(
|
|
|
3621
3799
|
}
|
|
3622
3800
|
|
|
3623
3801
|
if (sandbox) {
|
|
3802
|
+
if (pluginBinSandboxPolicy) {
|
|
3803
|
+
return attachDescriptor(
|
|
3804
|
+
{
|
|
3805
|
+
error:
|
|
3806
|
+
"[Plugin bin] A strict plugin bin policy cannot be combined with the legacy ephemeral shell sandbox. Run without that sandbox so the ProcessExecutionBroker can enforce the pinned plugin boundary union.",
|
|
3807
|
+
policy: {
|
|
3808
|
+
decision: "deny",
|
|
3809
|
+
via: "plugin-bin-pinned-sandbox-policy",
|
|
3810
|
+
reason: "conflicting_sandbox_routes",
|
|
3811
|
+
},
|
|
3812
|
+
...pluginBinResult,
|
|
3813
|
+
shellCommandPolicy: shellPolicy,
|
|
3814
|
+
approval: approvalOutcome,
|
|
3815
|
+
},
|
|
3816
|
+
override || runtimeDescriptor,
|
|
3817
|
+
);
|
|
3818
|
+
}
|
|
3624
3819
|
const { executeSandboxedShell, sandboxSummary } =
|
|
3625
3820
|
await import("../lib/agent-sandbox.js");
|
|
3626
3821
|
// Domain-restricted networking is ENFORCED by routing the sandboxed
|
|
@@ -3741,7 +3936,35 @@ async function executeToolInner(
|
|
|
3741
3936
|
scope: "agent",
|
|
3742
3937
|
...processProvenance,
|
|
3743
3938
|
};
|
|
3744
|
-
if (
|
|
3939
|
+
if (pluginBinInvocation) {
|
|
3940
|
+
reattestPluginBinInvocation(pluginBinInvocation);
|
|
3941
|
+
pluginBinResult.plugin_bin.launch_identity_reattested = true;
|
|
3942
|
+
const res = broker.spawnSync(
|
|
3943
|
+
pluginBinSandboxExecutionContract?.kind === "strict-plugin-node-bin"
|
|
3944
|
+
? pluginBinSandboxExecutionContract.runtimePath
|
|
3945
|
+
: pluginBinInvocation.command,
|
|
3946
|
+
pluginBinInvocation.args,
|
|
3947
|
+
{
|
|
3948
|
+
...brokerExecOpts,
|
|
3949
|
+
cwd:
|
|
3950
|
+
pluginBinSandboxExecutionContract?.workingDirectory ||
|
|
3951
|
+
brokerExecOpts.cwd,
|
|
3952
|
+
shell: false,
|
|
3953
|
+
windowsHide: true,
|
|
3954
|
+
},
|
|
3955
|
+
);
|
|
3956
|
+
if (res.error) throw res.error;
|
|
3957
|
+
if (res.status !== 0) {
|
|
3958
|
+
const e = new Error(
|
|
3959
|
+
`Plugin bin failed (exit ${res.status}): ${pluginBinInvocation.binName}`,
|
|
3960
|
+
);
|
|
3961
|
+
e.status = res.status;
|
|
3962
|
+
e.stdout = res.stdout;
|
|
3963
|
+
e.stderr = res.stderr;
|
|
3964
|
+
throw e;
|
|
3965
|
+
}
|
|
3966
|
+
output = res.stdout ?? "";
|
|
3967
|
+
} else if (shellInv.useDefaultShell) {
|
|
3745
3968
|
output = broker.execSync(args.command, brokerExecOpts);
|
|
3746
3969
|
} else {
|
|
3747
3970
|
// PowerShell route: explicit argv, no intermediate default shell.
|
|
@@ -3783,6 +4006,7 @@ async function executeToolInner(
|
|
|
3783
4006
|
{
|
|
3784
4007
|
stdout: output.substring(0, 30000),
|
|
3785
4008
|
...shellMeta,
|
|
4009
|
+
...pluginBinResult,
|
|
3786
4010
|
shellCommandPolicy: shellPolicy,
|
|
3787
4011
|
approval: approvalOutcome,
|
|
3788
4012
|
},
|
|
@@ -3803,6 +4027,7 @@ async function executeToolInner(
|
|
|
3803
4027
|
stderr: (err.stderr || "").substring(0, 2000),
|
|
3804
4028
|
exitCode: err.status,
|
|
3805
4029
|
...shellMeta,
|
|
4030
|
+
...pluginBinResult,
|
|
3806
4031
|
shellCommandPolicy: shellPolicy,
|
|
3807
4032
|
approval: approvalOutcome,
|
|
3808
4033
|
},
|
|
@@ -4315,6 +4540,9 @@ async function executeToolInner(
|
|
|
4315
4540
|
: 60000;
|
|
4316
4541
|
const entry = store.createMonitor({
|
|
4317
4542
|
command: args.command,
|
|
4543
|
+
// Bind the persisted command to the host/session workspace. This
|
|
4544
|
+
// value comes from executeTool's trusted context, never model args.
|
|
4545
|
+
workspaceCwd: path.resolve(cwd),
|
|
4318
4546
|
intervalMs,
|
|
4319
4547
|
stopWhen: args.stop_when || null,
|
|
4320
4548
|
notify: args.notify_title ? { title: args.notify_title } : null,
|
|
@@ -5160,6 +5388,54 @@ async function _executeRunCode(args, cwd) {
|
|
|
5160
5388
|
};
|
|
5161
5389
|
}
|
|
5162
5390
|
|
|
5391
|
+
// Every agent-generated interpreter process inherits the tighten-only union
|
|
5392
|
+
// of strict Plugin bin boundaries visible from this workspace. Discover and
|
|
5393
|
+
// pin it before creating a persistent directory, writing a temporary script,
|
|
5394
|
+
// or probing an interpreter so discovery failure cannot fall through to an
|
|
5395
|
+
// unbounded native spawn.
|
|
5396
|
+
let pluginBinSandboxPolicy = null;
|
|
5397
|
+
try {
|
|
5398
|
+
const pluginBin = await import("../lib/plugin-runtime/bin.js");
|
|
5399
|
+
pluginBinSandboxPolicy = collectWorkspacePluginBinSandboxPolicy(
|
|
5400
|
+
pluginBin,
|
|
5401
|
+
cwd,
|
|
5402
|
+
);
|
|
5403
|
+
} catch (error) {
|
|
5404
|
+
return {
|
|
5405
|
+
error: `[Plugin bin] ${error.message}`,
|
|
5406
|
+
policy: {
|
|
5407
|
+
decision: "deny",
|
|
5408
|
+
via: "plugin-bin-pinned-sandbox-policy",
|
|
5409
|
+
reason: error.code || "ERR_PLUGIN_BIN_SANDBOX_POLICY_DISCOVERY_FAILED",
|
|
5410
|
+
},
|
|
5411
|
+
};
|
|
5412
|
+
}
|
|
5413
|
+
const pluginBinSandboxOptions = pluginBinSandboxPolicy
|
|
5414
|
+
? { sandboxPolicy: pluginBinSandboxPolicy }
|
|
5415
|
+
: {};
|
|
5416
|
+
|
|
5417
|
+
// cli-anything's Python discovery probes candidate executables through its
|
|
5418
|
+
// own Broker call. That probe cannot inherit this run_code invocation's
|
|
5419
|
+
// pinned Plugin sandbox policy, so never launch it when strict boundaries
|
|
5420
|
+
// are required. A previously cached interpreter is safe to execute here
|
|
5421
|
+
// because the real script (and any pip/retry process) still goes through
|
|
5422
|
+
// runCodeProcess with the exact pinned policy below.
|
|
5423
|
+
let cachedPythonInterpreter = null;
|
|
5424
|
+
if (
|
|
5425
|
+
lang === "python" &&
|
|
5426
|
+
pluginBinSandboxPolicy?.requiredBoundaries?.length > 0
|
|
5427
|
+
) {
|
|
5428
|
+
if (
|
|
5429
|
+
_cachedPython?.found === true &&
|
|
5430
|
+
typeof _cachedPython.command === "string" &&
|
|
5431
|
+
_cachedPython.command.trim()
|
|
5432
|
+
) {
|
|
5433
|
+
cachedPythonInterpreter = _cachedPython.command;
|
|
5434
|
+
} else {
|
|
5435
|
+
throw createPythonInterpreterProbeSandboxFailure(pluginBinSandboxPolicy);
|
|
5436
|
+
}
|
|
5437
|
+
}
|
|
5438
|
+
|
|
5163
5439
|
// Determine script path
|
|
5164
5440
|
let scriptPath;
|
|
5165
5441
|
if (persist) {
|
|
@@ -5182,8 +5458,12 @@ async function _executeRunCode(args, cwd) {
|
|
|
5182
5458
|
// Determine interpreter
|
|
5183
5459
|
let interpreter;
|
|
5184
5460
|
if (lang === "python") {
|
|
5185
|
-
|
|
5186
|
-
|
|
5461
|
+
if (cachedPythonInterpreter) {
|
|
5462
|
+
interpreter = cachedPythonInterpreter;
|
|
5463
|
+
} else {
|
|
5464
|
+
const py = getCachedPython();
|
|
5465
|
+
interpreter = py.found ? py.command : "python";
|
|
5466
|
+
}
|
|
5187
5467
|
} else if (lang === "node") {
|
|
5188
5468
|
interpreter = "node";
|
|
5189
5469
|
} else {
|
|
@@ -5198,8 +5478,13 @@ async function _executeRunCode(args, cwd) {
|
|
|
5198
5478
|
encoding: "utf8",
|
|
5199
5479
|
timeout: timeoutSec * 1000,
|
|
5200
5480
|
maxBuffer: 5 * 1024 * 1024,
|
|
5481
|
+
...pluginBinSandboxOptions,
|
|
5201
5482
|
});
|
|
5202
5483
|
} catch (err) {
|
|
5484
|
+
// Broker boundary errors carry the required/actual/missing guarantees and
|
|
5485
|
+
// backend attestation. Preserve that exact structured error for callers
|
|
5486
|
+
// instead of flattening it into run_code's generic runtime classifier.
|
|
5487
|
+
rethrowRunCodeSandboxFailure(err);
|
|
5203
5488
|
const stderr = (err.stderr || "").toString();
|
|
5204
5489
|
const message = err.message || "";
|
|
5205
5490
|
const classified = classifyError(stderr, message, err.status, lang);
|
|
@@ -5291,6 +5576,36 @@ async function _executeRunCode(args, cwd) {
|
|
|
5291
5576
|
/* unified audit must never affect the install itself */
|
|
5292
5577
|
}
|
|
5293
5578
|
|
|
5579
|
+
const autoInstallFailure = (installError) => {
|
|
5580
|
+
recordInstallAudit({
|
|
5581
|
+
package: packageName,
|
|
5582
|
+
interpreter,
|
|
5583
|
+
cwd,
|
|
5584
|
+
outcome: "failed",
|
|
5585
|
+
detail: (
|
|
5586
|
+
installError.stderr ||
|
|
5587
|
+
installError.message ||
|
|
5588
|
+
""
|
|
5589
|
+
).substring(0, 200),
|
|
5590
|
+
});
|
|
5591
|
+
auditUnifiedInstall(
|
|
5592
|
+
"failed",
|
|
5593
|
+
(installError.stderr || installError.message || "").substring(
|
|
5594
|
+
0,
|
|
5595
|
+
200,
|
|
5596
|
+
),
|
|
5597
|
+
);
|
|
5598
|
+
return {
|
|
5599
|
+
error: (stderr || message).substring(0, 5000),
|
|
5600
|
+
stderr: stderr.substring(0, 5000),
|
|
5601
|
+
exitCode: err.status,
|
|
5602
|
+
language: lang,
|
|
5603
|
+
...classified,
|
|
5604
|
+
hint: `Failed to auto-install "${packageName}". ${(installError.stderr || installError.message || "").substring(0, 500)}`,
|
|
5605
|
+
scriptPath: persist ? scriptPath : undefined,
|
|
5606
|
+
};
|
|
5607
|
+
};
|
|
5608
|
+
|
|
5294
5609
|
// Attempt pip install
|
|
5295
5610
|
try {
|
|
5296
5611
|
runCodeProcess(
|
|
@@ -5302,18 +5617,27 @@ async function _executeRunCode(args, cwd) {
|
|
|
5302
5617
|
timeout: 120000,
|
|
5303
5618
|
maxBuffer: 2 * 1024 * 1024,
|
|
5304
5619
|
stdio: ["pipe", "pipe", "pipe"],
|
|
5620
|
+
...pluginBinSandboxOptions,
|
|
5305
5621
|
},
|
|
5306
5622
|
"run-code-install",
|
|
5307
5623
|
);
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5624
|
+
} catch (pipErr) {
|
|
5625
|
+
const failure = autoInstallFailure(pipErr);
|
|
5626
|
+
rethrowRunCodeSandboxFailure(pipErr);
|
|
5627
|
+
return failure;
|
|
5628
|
+
}
|
|
5629
|
+
recordInstallAudit({
|
|
5630
|
+
package: packageName,
|
|
5631
|
+
interpreter,
|
|
5632
|
+
cwd,
|
|
5633
|
+
outcome: "installed",
|
|
5634
|
+
});
|
|
5635
|
+
auditUnifiedInstall("installed");
|
|
5315
5636
|
|
|
5316
|
-
|
|
5637
|
+
// Keep retry separate from the install catch: either Broker call can
|
|
5638
|
+
// carry an independently attested fail-closed boundary error, and
|
|
5639
|
+
// neither may be flattened into the legacy auto-install result.
|
|
5640
|
+
try {
|
|
5317
5641
|
const retryStart = Date.now();
|
|
5318
5642
|
const retryOutput = runCodeProcess(
|
|
5319
5643
|
interpreter,
|
|
@@ -5323,6 +5647,7 @@ async function _executeRunCode(args, cwd) {
|
|
|
5323
5647
|
encoding: "utf8",
|
|
5324
5648
|
timeout: timeoutSec * 1000,
|
|
5325
5649
|
maxBuffer: 5 * 1024 * 1024,
|
|
5650
|
+
...pluginBinSandboxOptions,
|
|
5326
5651
|
},
|
|
5327
5652
|
"run-code-retry",
|
|
5328
5653
|
);
|
|
@@ -5336,25 +5661,24 @@ async function _executeRunCode(args, cwd) {
|
|
|
5336
5661
|
autoInstalled: [packageName],
|
|
5337
5662
|
scriptPath: persist ? scriptPath : undefined,
|
|
5338
5663
|
};
|
|
5339
|
-
} catch (
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
"failed",
|
|
5349
|
-
(pipErr.stderr || pipErr.message || "").substring(0, 200),
|
|
5664
|
+
} catch (retryErr) {
|
|
5665
|
+
rethrowRunCodeSandboxFailure(retryErr);
|
|
5666
|
+
const retryStderr = (retryErr.stderr || "").toString();
|
|
5667
|
+
const retryMessage = retryErr.message || "";
|
|
5668
|
+
const retryClassified = classifyError(
|
|
5669
|
+
retryStderr,
|
|
5670
|
+
retryMessage,
|
|
5671
|
+
retryErr.status,
|
|
5672
|
+
lang,
|
|
5350
5673
|
);
|
|
5351
5674
|
return {
|
|
5352
|
-
error: (
|
|
5353
|
-
stderr:
|
|
5354
|
-
exitCode:
|
|
5675
|
+
error: (retryStderr || retryMessage).substring(0, 5000),
|
|
5676
|
+
stderr: retryStderr.substring(0, 5000),
|
|
5677
|
+
exitCode: retryErr.status,
|
|
5355
5678
|
language: lang,
|
|
5356
|
-
...
|
|
5357
|
-
hint: `
|
|
5679
|
+
...retryClassified,
|
|
5680
|
+
hint: `Package "${packageName}" was installed, but the script retry failed.`,
|
|
5681
|
+
autoInstalled: [packageName],
|
|
5358
5682
|
scriptPath: persist ? scriptPath : undefined,
|
|
5359
5683
|
};
|
|
5360
5684
|
}
|
|
@@ -23,6 +23,7 @@ import { MCPClient, MCPServerConfig } from "../harness/mcp-client.js";
|
|
|
23
23
|
import sharedManagedToolPolicy from "./coding-agent-managed-tool-policy.cjs";
|
|
24
24
|
import { findProjectRoot, loadProjectConfig } from "../lib/project-detector.js";
|
|
25
25
|
import { loadConfig } from "../lib/config-manager.js";
|
|
26
|
+
import { collectWorkspacePluginBinSandboxPolicy } from "../lib/plugin-runtime/bin.js";
|
|
26
27
|
|
|
27
28
|
const {
|
|
28
29
|
DEFAULT_ALLOWED_MCP_SERVER_NAMES,
|
|
@@ -63,6 +64,8 @@ export class AgentRuntime {
|
|
|
63
64
|
createSessionManager:
|
|
64
65
|
deps.createSessionManager ||
|
|
65
66
|
((options) => new WSSessionManager(options)),
|
|
67
|
+
createPtyManager:
|
|
68
|
+
deps.createPtyManager || ((options) => new PtyManager(options)),
|
|
66
69
|
createMcpClient: deps.createMcpClient || (() => new MCPClient()),
|
|
67
70
|
createMcpServerConfig:
|
|
68
71
|
deps.createMcpServerConfig || ((db) => new MCPServerConfig(db)),
|
|
@@ -449,6 +452,7 @@ export class AgentRuntime {
|
|
|
449
452
|
const projectName =
|
|
450
453
|
projectConfig?.name || (projectRoot ? path.basename(projectRoot) : null);
|
|
451
454
|
const mode = projectRoot ? "project" : "global";
|
|
455
|
+
const workspacePolicyCwd = path.resolve(projectRoot || process.cwd());
|
|
452
456
|
|
|
453
457
|
let db = null;
|
|
454
458
|
let rawDb = null;
|
|
@@ -492,6 +496,7 @@ export class AgentRuntime {
|
|
|
492
496
|
maxConnections: 20,
|
|
493
497
|
timeout: 60000,
|
|
494
498
|
sessionManager,
|
|
499
|
+
projectRoot: workspacePolicyCwd,
|
|
495
500
|
});
|
|
496
501
|
// ChainlessChainWSServer extends EventEmitter and emits "error"
|
|
497
502
|
// synchronously on bind failure (in addition to rejecting start()).
|
|
@@ -530,7 +535,14 @@ export class AgentRuntime {
|
|
|
530
535
|
// matching topics through `terminalHandlers.handlers`, falling back to
|
|
531
536
|
// the original CLI dispatcher for everything else.
|
|
532
537
|
const wsBroadcastRef = { current: null };
|
|
533
|
-
const ptyManager =
|
|
538
|
+
const ptyManager = this.deps.createPtyManager({
|
|
539
|
+
policyCwd: workspacePolicyCwd,
|
|
540
|
+
resolveSandboxPolicy: ({ workspaceCwd, executionCwd }) =>
|
|
541
|
+
collectWorkspacePluginBinSandboxPolicy({
|
|
542
|
+
workspaceCwd,
|
|
543
|
+
executionCwd,
|
|
544
|
+
}),
|
|
545
|
+
});
|
|
534
546
|
const terminal = createTerminalHandlers({
|
|
535
547
|
ptyManager,
|
|
536
548
|
broadcast: (frame) => wsBroadcastRef.current?.(frame),
|
|
@@ -433,9 +433,10 @@ export async function runAgentHeadless(options = {}, deps = {}) {
|
|
|
433
433
|
}
|
|
434
434
|
}
|
|
435
435
|
|
|
436
|
-
//
|
|
437
|
-
//
|
|
438
|
-
//
|
|
436
|
+
// Preserve PATH compatibility for trusted legacy bin components that have no
|
|
437
|
+
// sandboxPolicy. Policy-bearing bins are excluded here and resolved as exact
|
|
438
|
+
// direct Broker invocations by agent-core. The process exits at the end of
|
|
439
|
+
// the run, so no explicit restore is needed.
|
|
439
440
|
try {
|
|
440
441
|
const { applyPluginBinPath } = await import("../lib/plugin-runtime/bin.js");
|
|
441
442
|
applyPluginBinPath({ cwd });
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./xterm-BZcWGsqw.js","./markdown-CsiA8-E5.js","./markdown-Dfs9RUU9.css","./addon-fit-CK6X9sAG.js","./xterm-DFuMZ0ql.css"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{u as fe,_ as me,d as U,e as V}from"./index-BEVm0lCS.js";import{I as z,J as x,U as _,Q as D,S as K,K as T,V as R,c as A,F as Q,Z,R as E,o as G,f as H,w as $,n as q,b as ee,r as S,P as y,_ as ve,a2 as we,a3 as he,a4 as _e}from"./vendor-Bn1JzzAn.js";import{R as ye,b as pe,at as ge}from"./icons-DG5UD-6K.js";const k=new Map,C=new Map,F=new Set,N=new Set;let te=!1;function xe(c){te||(te=!0,c.onMessage(o=>{if(!(!o||typeof o.type!="string")){if(o.type==="terminal.stdout"){const{sessionId:s,data:e,seq:i}=o.payload||{};if(!s)return;let w;try{const d=atob(e||""),f=new Uint8Array(d.length);for(let n=0;n<d.length;n++)f[n]=d.charCodeAt(n);w=new TextDecoder("utf-8").decode(f)}catch{w=""}const u={sessionId:s,data:w,seq:i};k.get(s)?.forEach(d=>d(u)),F.forEach(d=>d(u))}else if(o.type==="terminal.exit"){const{sessionId:s,exitCode:e,signal:i}=o.payload||{};if(!s)return;const w={sessionId:s,exitCode:e,signal:i};C.get(s)?.forEach(u=>u(w)),N.forEach(u=>u(w))}}}))}function ne(c){const o=new TextEncoder().encode(c);let s="";for(let e=0;e<o.length;e++)s+=String.fromCharCode(o[e]);return btoa(s)}function ae(c){const o=atob(c||""),s=new Uint8Array(o.length);for(let e=0;e<o.length;e++)s[e]=o.charCodeAt(e);return new TextDecoder("utf-8").decode(s)}function oe(){const c=fe();xe(c);async function o(n={}){const a=await c.sendRaw({type:"terminal.create",payload:{shell:n.shell,cwd:n.cwd,env:n.env,cols:n.cols,rows:n.rows}});if(a.ok===!1)throw new Error(a.error||"terminal_create_failed");return a.result??a}async function s(){const n=await c.sendRaw({type:"terminal.list",payload:{}});if(n.ok===!1)throw new Error(n.error||"terminal_list_failed");const a=n.result??n;return Array.isArray(a.sessions)?a.sessions:[]}async function e(n,a){const r=await c.sendRaw({type:"terminal.stdin",payload:{sessionId:n,data:ne(String(a))}});if(r.ok===!1)throw new Error(r.error||"terminal_stdin_failed");return r.result??r}async function i(n,a,r){const h=await c.sendRaw({type:"terminal.resize",payload:{sessionId:n,cols:a,rows:r}});if(h.ok===!1)throw new Error(h.error||"terminal_resize_failed");return h.result??h}async function w(n){const a=await c.sendRaw({type:"terminal.close",payload:{sessionId:n}});if(a.ok===!1)throw new Error(a.error||"terminal_close_failed");return a.result??a}async function u(n,a=0){const r=await c.sendRaw({type:"terminal.history",payload:{sessionId:n,fromSeq:a}});if(r.ok===!1)throw new Error(r.error||"terminal_history_failed");const h=r.result??r;return{truncated:!!h.truncated,chunks:(h.chunks||[]).map(L=>({seq:L.seq,data:ae(L.data)}))}}function d(n,a){return n?(k.has(n)||k.set(n,new Set),k.get(n).add(a),()=>{k.get(n)?.delete(a),k.get(n)?.size===0&&k.delete(n)}):(F.add(a),()=>F.delete(a))}function f(n,a){return n?(C.has(n)||C.set(n,new Set),C.get(n).add(a),()=>{C.get(n)?.delete(a),C.get(n)?.size===0&&C.delete(n)}):(N.add(a),()=>N.delete(a))}return{create:o,list:s,stdin:e,resize:i,close:w,history:u,onStdout:d,onExit:f,_internal:{stdoutSubs:k,exitSubs:C,toBase64Utf8:ne,fromBase64Utf8:ae}}}const Se={__name:"Terminal",setup(c,{expose:o}){o();const s=oe(),e=S([]),i=S(null),w=S("pwsh"),u=S(!1),d=S(!1),f=S(""),n=S(""),a=S([]),r=[{value:"pwsh",label:"PowerShell"},{value:"cmd",label:"CMD"},{value:"bash",label:"Bash"},{value:"wsl",label:"WSL"}],h=ee(()=>e.value.find(t=>t.id===i.value));function L(t){return t?t.slice(0,8):""}let O=null,M=null;async function I(){if(O)return{xtermMod:O,fitAddonMod:M};try{O=await V(()=>import("./xterm-BZcWGsqw.js").then(t=>t.x),__vite__mapDeps([0,1,2]),import.meta.url),M=await V(()=>import("./addon-fit-CK6X9sAG.js").then(t=>t.a),__vite__mapDeps([3,1,2]),import.meta.url),await V(()=>Promise.resolve({}),__vite__mapDeps([4]),import.meta.url)}catch(t){throw n.value="xterm 资源加载失败:"+(t?.message||"未知错误"),t}return{xtermMod:O,fitAddonMod:M}}async function B(t){await q();const{xtermMod:l,fitAddonMod:p}=await I(),b=a.value.find(v=>v?.dataset?.sessionId===t.id);if(!b)return;const m=new l.Terminal({cursorBlink:!0,fontFamily:'Consolas, "Courier New", monospace',fontSize:13,theme:{background:"#1e1e1e",foreground:"#d4d4d4"},convertEol:!1}),P=new p.FitAddon;m.loadAddon(P),m.open(b);try{P.fit()}catch{}t.xterm=m,t.fitAddon=P;const ie=m.onData(v=>{s.stdin(t.id,v).catch(g=>{String(g?.message||"").includes("dangerous_keyword_blocked")?U.warning("该命令被桌面端拦截(高危关键字)"):U.error("stdin 失败: "+(g?.message||g))})}),ce=s.onStdout(t.id,({data:v,seq:g})=>{t.lastSeq=g,m.write(v)}),de=s.onExit(t.id,({exitCode:v,signal:g})=>{t.alive=!1,t.exitCode=v,t.signal=g,m.writeln(`\r
|
|
3
|
-
\x1B[33m[session exited, code=${v}, signal=${g??"-"}]\x1B[0m`)});t.offs=()=>{try{ie.dispose?.()}catch{}ce(),de()};try{const{chunks:v,truncated:g}=await s.history(t.id,0);g&&m.writeln("\x1B[2m[history truncated — earlier output was evicted]\x1B[0m");for(const J of v)m.write(J.data),t.lastSeq=J.seq}catch(v){m.writeln(`\x1B[31m[history fetch failed: ${v?.message||v}]\x1B[0m`)}const j=new ResizeObserver(()=>{try{P.fit(),s.resize(t.id,m.cols,m.rows).catch(()=>{})}catch{}});j.observe(b);const ue=t.offs;t.offs=()=>{try{j.disconnect()}catch{}ue()}}async function re(){u.value=!0,f.value="";try{const t=await s.create({shell:w.value,cols:80,rows:24}),l={id:t.sessionId,shell:t.shell,cwd:"",alive:!0,lastSeq:0,exitCode:null,xterm:null,fitAddon:null,offs:()=>{}};e.value.push(l),i.value=l.id,await B(l)}catch(t){f.value=t?.message||String(t)}finally{u.value=!1}}async function se(t){try{await s.close(t)}catch(l){f.value=l?.message||String(l)}setTimeout(()=>W(t),500)}function W(t){const l=e.value.findIndex(b=>b.id===t);if(l===-1)return;const p=e.value[l];try{p.offs?.()}catch{}try{p.xterm?.dispose?.()}catch{}e.value.splice(l,1),i.value===t&&(i.value=e.value[0]?.id||null)}function le(t){i.value=t,q(()=>{const l=e.value.find(p=>p.id===t);try{l?.fitAddon?.fit()}catch{}})}async function X(){d.value=!0,f.value="";try{const t=await s.list();for(const l of t){const p=e.value.find(m=>m.id===l.id);if(p){p.alive=l.alive,p.lastSeq=l.lastSeq;continue}const b={id:l.id,shell:l.shell,cwd:l.cwd,alive:l.alive,lastSeq:l.lastSeq,exitCode:null,xterm:null,fitAddon:null,offs:()=>{}};e.value.push(b),await B(b)}!i.value&&e.value.length>0&&(i.value=e.value[0].id)}catch(t){f.value=t?.message||String(t)}finally{d.value=!1}}G(async()=>{await X()}),H(()=>{for(const t of e.value){try{t.offs?.()}catch{}try{t.xterm?.dispose?.()}catch{}}}),$(i,()=>{q(()=>{const t=h.value;try{t?.fitAddon?.fit()}catch{}})});const Y={term:s,sessions:e,activeId:i,newShell:w,creating:u,loadingList:d,error:f,warning:n,xtermContainers:a,shellOptions:r,active:h,shortId:L,get xtermMod(){return O},set xtermMod(t){O=t},get fitAddonMod(){return M},set fitAddonMod(t){M=t},loadXterm:I,mountXterm:B,onCreate:re,onClose:se,removeSession:W,activate:le,refreshList:X,ref:S,computed:ee,onMounted:G,onBeforeUnmount:H,nextTick:q,watch:$,get message(){return U},get PlusOutlined(){return ge},get CloseOutlined(){return pe},get ReloadOutlined(){return ye},get useTerminal(){return oe}};return Object.defineProperty(Y,"__isScriptSetup",{enumerable:!1,value:!0}),Y}},be={class:"terminal-page"},ke={class:"terminal-header"},Ce={class:"page-sub"},Ae={class:"terminal-body"},Ee={class:"session-tabs"},Oe=["onClick"],Te={class:"session-shell"},Re={class:"session-id"},Me={key:0,class:"session-empty"},ze={class:"xterm-host"},Le=["data-session-id"],Pe={key:0,class:"xterm-placeholder"},De={key:1,class:"terminal-footer"},qe={key:0,class:"footer-exit"};function Be(c,o,s,e,i,w){const u=z("a-tag"),d=z("a-select"),f=z("a-button"),n=z("a-space"),a=z("a-alert");return y(),x("div",be,[_("div",ke,[_("div",null,[o[3]||(o[3]=_("h2",{class:"page-title"},"远程终端",-1)),_("p",Ce,[o[2]||(o[2]=D(" 桌面端托管的 PTY 会话;Android 端可远程操控同一通道 ",-1)),e.warning?(y(),K(u,{key:0,color:"orange",style:{"margin-left":"8px"}},{default:T(()=>[D(E(e.warning),1)]),_:1})):R("v-if",!0)])]),A(n,null,{default:T(()=>[A(d,{value:e.newShell,"onUpdate:value":o[0]||(o[0]=r=>e.newShell=r),style:{width:"130px"},size:"small",options:e.shellOptions},null,8,["value"]),A(f,{type:"primary",size:"small",loading:e.creating,onClick:e.onCreate},{icon:T(()=>[A(e.PlusOutlined)]),default:T(()=>[o[4]||(o[4]=D(" 新会话 ",-1))]),_:1},8,["loading"]),A(f,{size:"small",loading:e.loadingList,onClick:e.refreshList},{icon:T(()=>[A(e.ReloadOutlined)]),default:T(()=>[o[5]||(o[5]=D(" 刷新 ",-1))]),_:1},8,["loading"])]),_:1})]),e.error?(y(),K(a,{key:0,message:e.error,type:"error","show-icon":"",closable:"",style:{"margin-bottom":"12px"},onClose:o[1]||(o[1]=r=>e.error="")},null,8,["message"])):R("v-if",!0),_("div",Ae,[_("div",Ee,[(y(!0),x(Q,null,Z(e.sessions,r=>(y(),x("div",{key:r.id,class:ve(["session-tab",{active:r.id===e.activeId,dead:!r.alive}]),onClick:h=>e.activate(r.id)},[_("span",Te,E(r.shell),1),_("span",Re,E(e.shortId(r.id)),1),A(e.CloseOutlined,{class:"session-close",onClick:we(h=>e.onClose(r.id),["stop"])},null,8,["onClick"])],10,Oe))),128)),e.sessions.length===0?(y(),x("div",Me,' 点击 "新会话" 创建第一个终端 ')):R("v-if",!0)]),_("div",ze,[(y(!0),x(Q,null,Z(e.sessions,r=>he((y(),x("div",{key:r.id,ref_for:!0,ref:"xtermContainers","data-session-id":r.id,class:"xterm-container"},null,8,Le)),[[_e,r.id===e.activeId]])),128)),e.sessions.length===0?(y(),x("div",Pe,[...o[6]||(o[6]=[_("span",null,"无活跃会话",-1)])])):R("v-if",!0)])]),e.active?(y(),x("div",De,[_("span",null,E(e.active.shell)+" · "+E(e.active.cwd||"(默认 cwd)")+" · seq "+E(e.active.lastSeq),1),e.active.alive?R("v-if",!0):(y(),x("span",qe,"已退出 (code="+E(e.active.exitCode??"-")+")",1))])):R("v-if",!0)])}const Ne=me(Se,[["render",Be],["__scopeId","data-v-65366a29"],["__file","/tmp/cc-web-panel-8U3FtY/repo/packages/web-panel/src/views/Terminal.vue"]]);export{Ne as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{Q as r}from"./index-BEVm0lCS.js";const o=((n,a,e)=>{r(n,`[ant-design-vue: ${a}] ${e}`)});export{o as d};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{C as o}from"./Col-74cOwZU1.js";import{a0 as t}from"./index-BEVm0lCS.js";import"./vendor-Bn1JzzAn.js";import"./index-B3CDgvNW.js";import"./icons-DG5UD-6K.js";const s=t(o);export{s as default};
|