mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-04 05:00:21 +00:00
81 lines
2.3 KiB
TypeScript
81 lines
2.3 KiB
TypeScript
import path from "node:path";
|
|
import { assertSandboxPath } from "./sandbox-paths.js";
|
|
import type { SandboxFsBridge } from "./sandbox/fs-bridge.js";
|
|
|
|
export type SandboxedBridgeMediaPathConfig = {
|
|
root: string;
|
|
bridge: SandboxFsBridge;
|
|
workspaceOnly?: boolean;
|
|
};
|
|
|
|
export function createSandboxBridgeReadFile(params: {
|
|
sandbox: Pick<SandboxedBridgeMediaPathConfig, "root" | "bridge">;
|
|
}): (filePath: string) => Promise<Buffer> {
|
|
return async (filePath: string) =>
|
|
await params.sandbox.bridge.readFile({
|
|
filePath,
|
|
cwd: params.sandbox.root,
|
|
});
|
|
}
|
|
|
|
export async function resolveSandboxedBridgeMediaPath(params: {
|
|
sandbox: SandboxedBridgeMediaPathConfig;
|
|
mediaPath: string;
|
|
inboundFallbackDir?: string;
|
|
}): Promise<{ resolved: string; rewrittenFrom?: string }> {
|
|
const normalizeFileUrl = (rawPath: string) =>
|
|
rawPath.startsWith("file://") ? rawPath.slice("file://".length) : rawPath;
|
|
const filePath = normalizeFileUrl(params.mediaPath);
|
|
const enforceWorkspaceBoundary = async (hostPath: string) => {
|
|
if (!params.sandbox.workspaceOnly) {
|
|
return;
|
|
}
|
|
await assertSandboxPath({
|
|
filePath: hostPath,
|
|
cwd: params.sandbox.root,
|
|
root: params.sandbox.root,
|
|
});
|
|
};
|
|
|
|
const resolveDirect = () =>
|
|
params.sandbox.bridge.resolvePath({
|
|
filePath,
|
|
cwd: params.sandbox.root,
|
|
});
|
|
try {
|
|
const resolved = resolveDirect();
|
|
if (resolved.hostPath) {
|
|
await enforceWorkspaceBoundary(resolved.hostPath);
|
|
}
|
|
return { resolved: resolved.hostPath ?? resolved.containerPath };
|
|
} catch (err) {
|
|
const fallbackDir = params.inboundFallbackDir?.trim();
|
|
if (!fallbackDir) {
|
|
throw err;
|
|
}
|
|
const fallbackPath = path.join(fallbackDir, path.basename(filePath));
|
|
try {
|
|
const stat = await params.sandbox.bridge.stat({
|
|
filePath: fallbackPath,
|
|
cwd: params.sandbox.root,
|
|
});
|
|
if (!stat) {
|
|
throw err;
|
|
}
|
|
} catch {
|
|
throw err;
|
|
}
|
|
const resolvedFallback = params.sandbox.bridge.resolvePath({
|
|
filePath: fallbackPath,
|
|
cwd: params.sandbox.root,
|
|
});
|
|
if (resolvedFallback.hostPath) {
|
|
await enforceWorkspaceBoundary(resolvedFallback.hostPath);
|
|
}
|
|
return {
|
|
resolved: resolvedFallback.hostPath ?? resolvedFallback.containerPath,
|
|
rewrittenFrom: filePath,
|
|
};
|
|
}
|
|
}
|