mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-10 03:32:43 +00:00
refactor: dedupe agent and browser cli helpers
This commit is contained in:
@@ -126,6 +126,35 @@ describe("resolveAcpClientSpawnInvocation", () => {
|
||||
});
|
||||
|
||||
describe("resolvePermissionRequest", () => {
|
||||
async function expectPromptReject(params: {
|
||||
request: Partial<RequestPermissionRequest>;
|
||||
expectedToolName: string | undefined;
|
||||
expectedTitle: string;
|
||||
}) {
|
||||
const prompt = vi.fn(async () => false);
|
||||
const res = await resolvePermissionRequest(makePermissionRequest(params.request), {
|
||||
prompt,
|
||||
log: () => {},
|
||||
});
|
||||
expect(prompt).toHaveBeenCalledTimes(1);
|
||||
expect(prompt).toHaveBeenCalledWith(params.expectedToolName, params.expectedTitle);
|
||||
expect(res).toEqual({ outcome: { outcome: "selected", optionId: "reject" } });
|
||||
}
|
||||
|
||||
async function expectAutoAllowWithoutPrompt(params: {
|
||||
request: Partial<RequestPermissionRequest>;
|
||||
cwd?: string;
|
||||
}) {
|
||||
const prompt = vi.fn(async () => true);
|
||||
const res = await resolvePermissionRequest(makePermissionRequest(params.request), {
|
||||
prompt,
|
||||
log: () => {},
|
||||
cwd: params.cwd,
|
||||
});
|
||||
expect(prompt).not.toHaveBeenCalled();
|
||||
expect(res).toEqual({ outcome: { outcome: "selected", optionId: "allow" } });
|
||||
}
|
||||
|
||||
it("auto-approves safe tools without prompting", async () => {
|
||||
const prompt = vi.fn(async () => true);
|
||||
const res = await resolvePermissionRequest(makePermissionRequest(), { prompt, log: () => {} });
|
||||
@@ -185,37 +214,31 @@ describe("resolvePermissionRequest", () => {
|
||||
});
|
||||
|
||||
it("auto-approves read when rawInput path resolves inside cwd", async () => {
|
||||
const prompt = vi.fn(async () => true);
|
||||
const res = await resolvePermissionRequest(
|
||||
makePermissionRequest({
|
||||
await expectAutoAllowWithoutPrompt({
|
||||
request: {
|
||||
toolCall: {
|
||||
toolCallId: "tool-read-inside-cwd",
|
||||
title: "read: ignored-by-raw-input",
|
||||
status: "pending",
|
||||
rawInput: { path: "docs/security.md" },
|
||||
},
|
||||
}),
|
||||
{ prompt, log: () => {}, cwd: "/tmp/openclaw-acp-cwd" },
|
||||
);
|
||||
expect(prompt).not.toHaveBeenCalled();
|
||||
expect(res).toEqual({ outcome: { outcome: "selected", optionId: "allow" } });
|
||||
},
|
||||
cwd: "/tmp/openclaw-acp-cwd",
|
||||
});
|
||||
});
|
||||
|
||||
it("auto-approves read when rawInput file URL resolves inside cwd", async () => {
|
||||
const prompt = vi.fn(async () => true);
|
||||
const res = await resolvePermissionRequest(
|
||||
makePermissionRequest({
|
||||
await expectAutoAllowWithoutPrompt({
|
||||
request: {
|
||||
toolCall: {
|
||||
toolCallId: "tool-read-inside-cwd-file-url",
|
||||
title: "read: ignored-by-raw-input",
|
||||
status: "pending",
|
||||
rawInput: { path: "file:///tmp/openclaw-acp-cwd/docs/security.md" },
|
||||
},
|
||||
}),
|
||||
{ prompt, log: () => {}, cwd: "/tmp/openclaw-acp-cwd" },
|
||||
);
|
||||
expect(prompt).not.toHaveBeenCalled();
|
||||
expect(res).toEqual({ outcome: { outcome: "selected", optionId: "allow" } });
|
||||
},
|
||||
cwd: "/tmp/openclaw-acp-cwd",
|
||||
});
|
||||
});
|
||||
|
||||
it("prompts for read when rawInput path escapes cwd via traversal", async () => {
|
||||
@@ -343,56 +366,47 @@ describe("resolvePermissionRequest", () => {
|
||||
});
|
||||
|
||||
it("prompts when metadata tool name contains invalid characters", async () => {
|
||||
const prompt = vi.fn(async () => false);
|
||||
const res = await resolvePermissionRequest(
|
||||
makePermissionRequest({
|
||||
await expectPromptReject({
|
||||
request: {
|
||||
toolCall: {
|
||||
toolCallId: "tool-invalid-meta",
|
||||
title: "read: src/index.ts",
|
||||
status: "pending",
|
||||
_meta: { toolName: "read.*" },
|
||||
},
|
||||
}),
|
||||
{ prompt, log: () => {} },
|
||||
);
|
||||
expect(prompt).toHaveBeenCalledTimes(1);
|
||||
expect(prompt).toHaveBeenCalledWith(undefined, "read: src/index.ts");
|
||||
expect(res).toEqual({ outcome: { outcome: "selected", optionId: "reject" } });
|
||||
},
|
||||
expectedToolName: undefined,
|
||||
expectedTitle: "read: src/index.ts",
|
||||
});
|
||||
});
|
||||
|
||||
it("prompts when raw input tool name exceeds max length", async () => {
|
||||
const prompt = vi.fn(async () => false);
|
||||
const res = await resolvePermissionRequest(
|
||||
makePermissionRequest({
|
||||
await expectPromptReject({
|
||||
request: {
|
||||
toolCall: {
|
||||
toolCallId: "tool-long-raw",
|
||||
title: "read: src/index.ts",
|
||||
status: "pending",
|
||||
rawInput: { toolName: "r".repeat(129) },
|
||||
},
|
||||
}),
|
||||
{ prompt, log: () => {} },
|
||||
);
|
||||
expect(prompt).toHaveBeenCalledTimes(1);
|
||||
expect(prompt).toHaveBeenCalledWith(undefined, "read: src/index.ts");
|
||||
expect(res).toEqual({ outcome: { outcome: "selected", optionId: "reject" } });
|
||||
},
|
||||
expectedToolName: undefined,
|
||||
expectedTitle: "read: src/index.ts",
|
||||
});
|
||||
});
|
||||
|
||||
it("prompts when title tool name contains non-allowed characters", async () => {
|
||||
const prompt = vi.fn(async () => false);
|
||||
const res = await resolvePermissionRequest(
|
||||
makePermissionRequest({
|
||||
await expectPromptReject({
|
||||
request: {
|
||||
toolCall: {
|
||||
toolCallId: "tool-bad-title-name",
|
||||
title: "read🚀: src/index.ts",
|
||||
status: "pending",
|
||||
},
|
||||
}),
|
||||
{ prompt, log: () => {} },
|
||||
);
|
||||
expect(prompt).toHaveBeenCalledTimes(1);
|
||||
expect(prompt).toHaveBeenCalledWith(undefined, "read🚀: src/index.ts");
|
||||
expect(res).toEqual({ outcome: { outcome: "selected", optionId: "reject" } });
|
||||
},
|
||||
expectedToolName: undefined,
|
||||
expectedTitle: "read🚀: src/index.ts",
|
||||
});
|
||||
});
|
||||
|
||||
it("returns cancelled when no permission options are present", async () => {
|
||||
|
||||
Reference in New Issue
Block a user