






















@@ -19,18 +19,31 @@ import type { MsgContext, TemplateContext } from "../templating.js";
19192020const STAGED_MEDIA_MAX_BYTES = MEDIA_MAX_BYTES;
212122+// `staged` maps every absolute source path that was copied into the sandbox
23+// (or remote cache) to its rewritten ctx path. Callers like chat.send's
24+// prestage use this to detect partial failures: unstaged sources keep their
25+// original absolute path in ctx.MediaPaths, so a length check against the
26+// input cannot distinguish "everything staged" from "silently skipped some"
27+// (e.g. the 5MB cap in STAGED_MEDIA_MAX_BYTES rejecting files that the
28+// chat.send RPC already admitted under its 20MB cap).
29+export type StageSandboxMediaResult = {
30+staged: ReadonlyMap<string, string>;
31+};
32+33+const EMPTY_STAGE_RESULT: StageSandboxMediaResult = { staged: new Map() };
34+2235export async function stageSandboxMedia(params: {
2336ctx: MsgContext;
2437sessionCtx: TemplateContext;
2538cfg: OpenClawConfig;
2639sessionKey?: string;
2740workspaceDir: string;
28-}) {
41+}): Promise<StageSandboxMediaResult> {
2942const { ctx, sessionCtx, cfg, sessionKey, workspaceDir } = params;
3043const hasPathsArray = Array.isArray(ctx.MediaPaths) && ctx.MediaPaths.length > 0;
3144const rawPaths = resolveRawPaths(ctx);
3245if (rawPaths.length === 0 || !sessionKey) {
33-return;
46+return EMPTY_STAGE_RESULT;
3447}
35483649const sandbox = await ensureSandboxWorkspaceForSession({
@@ -45,7 +58,7 @@ export async function stageSandboxMedia(params: {
4558 : null;
4659const effectiveWorkspaceDir = sandbox?.workspaceDir ?? remoteMediaCacheDir;
4760if (!effectiveWorkspaceDir) {
48-return;
61+return EMPTY_STAGE_RESULT;
4962}
50635164await fs.mkdir(effectiveWorkspaceDir, { recursive: true });
@@ -116,6 +129,8 @@ export async function stageSandboxMedia(params: {
116129 staged,
117130 hasPathsArray,
118131});
132+133+return { staged };
119134}
120135121136async function stageLocalFileIntoRoot(params: {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。