refactor(cli): share camera clip file writer

This commit is contained in:
Peter Steinberger
2026-02-18 23:47:52 +00:00
parent e368e74a92
commit a8ebe942aa
4 changed files with 51 additions and 16 deletions

View File

@@ -6,6 +6,7 @@ import {
cameraTempPath,
parseCameraClipPayload,
parseCameraSnapPayload,
writeCameraClipPayloadToFile,
writeBase64ToFile,
writeUrlToFile,
} from "../../cli/nodes-camera.js";
@@ -300,16 +301,10 @@ export function createNodesTool(options?: {
idempotencyKey: crypto.randomUUID(),
});
const payload = parseCameraClipPayload(raw?.payload);
const filePath = cameraTempPath({
kind: "clip",
const filePath = await writeCameraClipPayloadToFile({
payload,
facing,
ext: payload.format,
});
if (payload.url) {
await writeUrlToFile(filePath, payload.url);
} else if (payload.base64) {
await writeBase64ToFile(filePath, payload.base64);
}
return {
content: [{ type: "text", text: `FILE:${filePath}` }],
details: {

View File

@@ -6,6 +6,7 @@ import {
cameraTempPath,
parseCameraClipPayload,
parseCameraSnapPayload,
writeCameraClipPayloadToFile,
writeBase64ToFile,
writeUrlToFile,
} from "./nodes-camera.js";
@@ -56,6 +57,27 @@ describe("nodes camera helpers", () => {
expect(p).toBe(path.join("/tmp", "openclaw-camera-snap-front-id1.jpg"));
});
it("writes camera clip payload to temp path", async () => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-test-"));
try {
const out = await writeCameraClipPayloadToFile({
payload: {
format: "mp4",
base64: "aGk=",
durationMs: 200,
hasAudio: false,
},
facing: "front",
tmpDir: dir,
id: "clip1",
});
expect(out).toBe(path.join(dir, "openclaw-camera-clip-front-clip1.mp4"));
await expect(fs.readFile(out, "utf8")).resolves.toBe("hi");
} finally {
await fs.rm(dir, { recursive: true, force: true });
}
});
it("writes base64 to file", async () => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-test-"));
const out = path.join(dir, "x.bin");

View File

@@ -140,3 +140,26 @@ export async function writeBase64ToFile(filePath: string, base64: string) {
await fs.writeFile(filePath, buf);
return { path: filePath, bytes: buf.length };
}
export async function writeCameraClipPayloadToFile(params: {
payload: CameraClipPayload;
facing: CameraFacing;
tmpDir?: string;
id?: string;
}): Promise<string> {
const filePath = cameraTempPath({
kind: "clip",
facing: params.facing,
ext: params.payload.format,
tmpDir: params.tmpDir,
id: params.id,
});
if (params.payload.url) {
await writeUrlToFile(filePath, params.payload.url);
} else if (params.payload.base64) {
await writeBase64ToFile(filePath, params.payload.base64);
} else {
throw new Error("invalid camera.clip payload");
}
return filePath;
}

View File

@@ -8,6 +8,7 @@ import {
parseCameraClipPayload,
parseCameraSnapPayload,
writeBase64ToFile,
writeCameraClipPayloadToFile,
writeUrlToFile,
} from "../nodes-camera.js";
import { parseDurationMs } from "../parse-duration.js";
@@ -219,16 +220,10 @@ export function registerNodesCameraCommands(nodes: Command) {
const raw = await callGatewayCli("node.invoke", opts, invokeParams);
const res = typeof raw === "object" && raw !== null ? (raw as { payload?: unknown }) : {};
const payload = parseCameraClipPayload(res.payload);
const filePath = cameraTempPath({
kind: "clip",
const filePath = await writeCameraClipPayloadToFile({
payload,
facing,
ext: payload.format,
});
if (payload.url) {
await writeUrlToFile(filePath, payload.url);
} else if (payload.base64) {
await writeBase64ToFile(filePath, payload.base64);
}
if (opts.json) {
defaultRuntime.log(