diff --git a/src/agents/tools/nodes-tool.ts b/src/agents/tools/nodes-tool.ts index 187e7c8fcb..2bda0d4a85 100644 --- a/src/agents/tools/nodes-tool.ts +++ b/src/agents/tools/nodes-tool.ts @@ -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: { diff --git a/src/cli/nodes-camera.test.ts b/src/cli/nodes-camera.test.ts index e4a05f66f3..41606ba5dd 100644 --- a/src/cli/nodes-camera.test.ts +++ b/src/cli/nodes-camera.test.ts @@ -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"); diff --git a/src/cli/nodes-camera.ts b/src/cli/nodes-camera.ts index a31641fa91..55a40d7cc1 100644 --- a/src/cli/nodes-camera.ts +++ b/src/cli/nodes-camera.ts @@ -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 { + 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; +} diff --git a/src/cli/nodes-cli/register.camera.ts b/src/cli/nodes-cli/register.camera.ts index 5f6324edda..c93f63cf13 100644 --- a/src/cli/nodes-cli/register.camera.ts +++ b/src/cli/nodes-cli/register.camera.ts @@ -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(