fix: enforce role tool whitelist

This commit is contained in:
2026-07-09 20:48:03 +08:00
parent 716101eed0
commit 5d315fff21
7 changed files with 242 additions and 20 deletions
+16
View File
@@ -343,6 +343,22 @@ describe("trigger full lifecycle (integration)", () => {
expect(await prisma.agentRun.findMany()).toHaveLength(0);
});
it("passes the selected role tool whitelist into the runner", async () => {
await seedProject("proj-role-tools", "chat-role-tools");
const trigger = makeTriggerHandler({ prisma, settings, logger: silentLogger, runAgent, messageBatcherOptions: { maxMessages: 1 } });
await trigger(makeEvent("chat-role-tools", "@_user_1 /review 检查讲义"), rt);
await vi.waitFor(async () => {
const runs = await prisma.agentRun.findMany();
expect(runs).toHaveLength(1);
expect(runs[0]?.status).toBe("COMPLETED");
});
expect(runAgentCalls).toHaveLength(1);
expect(runAgentCalls[0]?.tools).toEqual(["read_file"]);
});
it("control commands support a help subcommand", async () => {
await seedProject("proj-new-help", "chat-new-help");
const trigger = makeTriggerHandler({ prisma, settings, logger: silentLogger, runAgent, messageBatcherOptions: { maxMessages: 1 } });
+44
View File
@@ -104,6 +104,50 @@ describe("runAgent", () => {
expect(call?.options).not.toHaveProperty("resume");
});
it("maps role tool ids to the Claude SDK tool whitelist", async () => {
queryMock.mockReturnValue(messages(assistantMessage("ok"), resultMessage("sdk-session-1")));
await runAgent({
prompt: "审校一下",
model: undefined,
project: { projectId: "p", boundChatId: "c", workspaceDir: "/tmp/ws" },
systemPrompt: undefined,
tools: ["read_file", "cph_check", "send_file"],
runId: "run-1",
sessionId: "hub-session-1",
prisma: stubPrisma,
});
expect(queryMock.mock.calls[0]?.[0]).toMatchObject({
options: {
tools: ["Read", "Bash"],
allowedTools: ["Read", "Bash", "mcp__cph_hub__send_file"],
},
});
});
it("disables all SDK tools for an empty role tool whitelist", async () => {
queryMock.mockReturnValue(messages(assistantMessage("ok"), resultMessage("sdk-session-1")));
await runAgent({
prompt: "只回答",
model: undefined,
project: { projectId: "p", boundChatId: "c", workspaceDir: "/tmp/ws" },
systemPrompt: undefined,
tools: [],
runId: "run-1",
sessionId: "hub-session-1",
prisma: stubPrisma,
});
expect(queryMock.mock.calls[0]?.[0]).toMatchObject({
options: {
tools: [],
allowedTools: [],
},
});
});
it("returns SDK-reported cost when present", async () => {
queryMock.mockReturnValue(messages(assistantMessage("ok"), resultMessage("sdk-session-1", 0.0042)));