mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-21 16:41:56 +00:00
109 lines
3.2 KiB
TypeScript
109 lines
3.2 KiB
TypeScript
import path from "node:path";
|
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
import { wrapToolWorkspaceRootGuardWithOptions } from "./pi-tools.read.js";
|
|
import type { AnyAgentTool } from "./pi-tools.types.js";
|
|
|
|
const mocks = vi.hoisted(() => ({
|
|
assertSandboxPath: vi.fn(async () => ({ resolved: "/tmp/root", relative: "" })),
|
|
}));
|
|
|
|
vi.mock("./sandbox-paths.js", () => ({
|
|
assertSandboxPath: mocks.assertSandboxPath,
|
|
}));
|
|
|
|
function createToolHarness() {
|
|
const execute = vi.fn(async () => ({
|
|
content: [{ type: "text", text: "ok" }],
|
|
}));
|
|
const tool = {
|
|
name: "read",
|
|
description: "test tool",
|
|
inputSchema: { type: "object", properties: {} },
|
|
execute,
|
|
} as unknown as AnyAgentTool;
|
|
return { execute, tool };
|
|
}
|
|
|
|
describe("wrapToolWorkspaceRootGuardWithOptions", () => {
|
|
const root = "/tmp/root";
|
|
|
|
beforeEach(() => {
|
|
mocks.assertSandboxPath.mockClear();
|
|
});
|
|
|
|
it("maps container workspace paths to host workspace root", async () => {
|
|
const { tool } = createToolHarness();
|
|
const wrapped = wrapToolWorkspaceRootGuardWithOptions(tool, root, {
|
|
containerWorkdir: "/workspace",
|
|
});
|
|
|
|
await wrapped.execute("tc1", { path: "/workspace/docs/readme.md" });
|
|
|
|
expect(mocks.assertSandboxPath).toHaveBeenCalledWith({
|
|
filePath: path.resolve(root, "docs", "readme.md"),
|
|
cwd: root,
|
|
root,
|
|
});
|
|
});
|
|
|
|
it("maps file:// container workspace paths to host workspace root", async () => {
|
|
const { tool } = createToolHarness();
|
|
const wrapped = wrapToolWorkspaceRootGuardWithOptions(tool, root, {
|
|
containerWorkdir: "/workspace",
|
|
});
|
|
|
|
await wrapped.execute("tc2", { path: "file:///workspace/docs/readme.md" });
|
|
|
|
expect(mocks.assertSandboxPath).toHaveBeenCalledWith({
|
|
filePath: path.resolve(root, "docs", "readme.md"),
|
|
cwd: root,
|
|
root,
|
|
});
|
|
});
|
|
|
|
it("maps @-prefixed container workspace paths to host workspace root", async () => {
|
|
const { tool } = createToolHarness();
|
|
const wrapped = wrapToolWorkspaceRootGuardWithOptions(tool, root, {
|
|
containerWorkdir: "/workspace",
|
|
});
|
|
|
|
await wrapped.execute("tc-at-container", { path: "@/workspace/docs/readme.md" });
|
|
|
|
expect(mocks.assertSandboxPath).toHaveBeenCalledWith({
|
|
filePath: path.resolve(root, "docs", "readme.md"),
|
|
cwd: root,
|
|
root,
|
|
});
|
|
});
|
|
|
|
it("normalizes @-prefixed absolute paths before guard checks", async () => {
|
|
const { tool } = createToolHarness();
|
|
const wrapped = wrapToolWorkspaceRootGuardWithOptions(tool, root, {
|
|
containerWorkdir: "/workspace",
|
|
});
|
|
|
|
await wrapped.execute("tc-at-absolute", { path: "@/etc/passwd" });
|
|
|
|
expect(mocks.assertSandboxPath).toHaveBeenCalledWith({
|
|
filePath: "/etc/passwd",
|
|
cwd: root,
|
|
root,
|
|
});
|
|
});
|
|
|
|
it("does not remap absolute paths outside the configured container workdir", async () => {
|
|
const { tool } = createToolHarness();
|
|
const wrapped = wrapToolWorkspaceRootGuardWithOptions(tool, root, {
|
|
containerWorkdir: "/workspace",
|
|
});
|
|
|
|
await wrapped.execute("tc3", { path: "/workspace-two/secret.txt" });
|
|
|
|
expect(mocks.assertSandboxPath).toHaveBeenCalledWith({
|
|
filePath: "/workspace-two/secret.txt",
|
|
cwd: root,
|
|
root,
|
|
});
|
|
});
|
|
});
|