fix: restore external file write helper

This commit is contained in:
Peter Steinberger
2026-05-08 06:00:05 +01:00
parent 397cf2b9ff
commit c659590d22
2 changed files with 44 additions and 5 deletions

View File

@@ -13,6 +13,7 @@ import {
FsSafeError,
readLocalFileSafely,
root as openRoot,
writeExternalFileWithinRoot,
} from "./fs-safe.js";
const tempDirs = createTrackedTempDirs();
@@ -128,6 +129,21 @@ describe("fs-safe", () => {
expect((err as FsSafeError).message).not.toMatch(/EISDIR/i);
});
it("writes external command output within an allowed root", async () => {
const dir = await tempDirs.make("openclaw-fs-safe-output-");
const result = await writeExternalFileWithinRoot({
rootDir: dir,
path: "artifact.txt",
write: async (tempPath) => {
await fs.writeFile(tempPath, "artifact");
},
});
expect(result.path).toBe(path.join(dir, "artifact.txt"));
await expect(fs.readFile(path.join(dir, "artifact.txt"), "utf8")).resolves.toBe("artifact");
});
it("enforces maxBytes", async () => {
const dir = await tempDirs.make("openclaw-fs-safe-");
const file = path.join(dir, "big.bin");

View File

@@ -1,4 +1,6 @@
import "./fs-safe-defaults.js";
import path from "node:path";
import { writeViaSiblingTempPath } from "@openclaw/fs-safe/advanced";
import { root as fsSafeRoot, type ReadResult } from "@openclaw/fs-safe/root";
export { FsSafeError, type FsSafeErrorCode } from "@openclaw/fs-safe/errors";
@@ -45,11 +47,32 @@ export {
type WalkDirectoryResult,
} from "@openclaw/fs-safe/walk";
export { withTimeout } from "@openclaw/fs-safe/advanced";
export {
writeExternalFileWithinRoot,
type ExternalFileWriteOptions,
type ExternalFileWriteResult,
} from "@openclaw/fs-safe/output";
export type ExternalFileWriteOptions = {
rootDir: string;
path: string;
write: (tempPath: string) => Promise<void>;
fallbackFileName?: string;
tempPrefix?: string;
};
export type ExternalFileWriteResult = {
path: string;
};
export async function writeExternalFileWithinRoot(
options: ExternalFileWriteOptions,
): Promise<ExternalFileWriteResult> {
const targetPath = path.resolve(options.rootDir, options.path);
await writeViaSiblingTempPath({
rootDir: options.rootDir,
targetPath,
writeTemp: options.write,
fallbackFileName: options.fallbackFileName,
tempPrefix: options.tempPrefix,
});
return { path: targetPath };
}
/** @deprecated Use root(rootDir).read(relativePath, options). */
export async function readFileWithinRoot(params: {