fix(image): propagate workspace root for image allowlist (#16722)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 24a13675cb
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
This commit is contained in:
Peter Steinberger
2026-02-15 03:08:28 +01:00
committed by GitHub
parent 69dd1a31bf
commit b79e7fdb7a
5 changed files with 73 additions and 7 deletions

View File

@@ -3,6 +3,7 @@ import os from "node:os";
import path from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../../config/config.js";
import { createOpenClawCodingTools } from "../pi-tools.js";
import { createHostSandboxFsBridge } from "../test-helpers/host-sandbox-fs-bridge.js";
import { __testing, createImageTool, resolveImageModelConfigForTool } from "./image-tool.js";
@@ -219,6 +220,64 @@ describe("image tool implicit imageModel config", () => {
}
});
it("allows workspace images via createOpenClawCodingTools default workspace root", async () => {
const workspaceParent = await fs.mkdtemp(
path.join(process.cwd(), ".openclaw-workspace-image-"),
);
try {
const workspaceDir = path.join(workspaceParent, "workspace");
await fs.mkdir(workspaceDir, { recursive: true });
const imagePath = path.join(workspaceDir, "photo.png");
const pngB64 =
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/woAAn8B9FD5fHAAAAAASUVORK5CYII=";
await fs.writeFile(imagePath, Buffer.from(pngB64, "base64"));
const fetch = vi.fn().mockResolvedValue({
ok: true,
status: 200,
statusText: "OK",
headers: new Headers(),
json: async () => ({
content: "ok",
base_resp: { status_code: 0, status_msg: "" },
}),
});
// @ts-expect-error partial global
global.fetch = fetch;
vi.stubEnv("MINIMAX_API_KEY", "minimax-test");
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-image-"));
const cfg: OpenClawConfig = {
agents: {
defaults: {
model: { primary: "minimax/MiniMax-M2.1" },
imageModel: { primary: "minimax/MiniMax-VL-01" },
},
},
};
const tools = createOpenClawCodingTools({ config: cfg, agentDir });
const tool = tools.find((candidate) => candidate.name === "image");
expect(tool).not.toBeNull();
if (!tool) {
throw new Error("expected image tool");
}
await expect(
tool.execute("t1", {
prompt: "Describe the image.",
image: imagePath,
}),
).resolves.toMatchObject({
content: [{ type: "text", text: "ok" }],
});
expect(fetch).toHaveBeenCalledTimes(1);
} finally {
await fs.rm(workspaceParent, { recursive: true, force: true });
}
});
it("sandboxes image paths like the read tool", async () => {
const stateDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-image-sandbox-"));
const agentDir = path.join(stateDir, "agent");