forked from EduCraft/curriculum-project-hub
fix(hub): stop unrestricted roles from loading multi-agent tools
The claude_code preset exposed Agent/SendMessage/Task. Background agents
abort with reason "background", which the SDK maps to Bash
toolDenialKind "cancelled" ("user doesn't want this action") and freezes
command execution mid-run.
This commit is contained in:
@@ -114,10 +114,9 @@ describe("runAgent", () => {
|
||||
allowDangerouslySkipPermissions: true,
|
||||
settingSources: [],
|
||||
settings: { disableBundledSkills: true, todoFeatureEnabled: true },
|
||||
skills: [],
|
||||
tools: { type: "preset", preset: "claude_code" },
|
||||
allowedTools: expect.arrayContaining(["TodoWrite"]),
|
||||
strictMcpConfig: true,
|
||||
tools: expect.arrayContaining(["Read", "Write", "Bash", "Glob", "Grep", "TodoWrite"]),
|
||||
allowedTools: expect.arrayContaining(["TodoWrite", "mcp__cph_hub__todo_write"]),
|
||||
disallowedTools: expect.arrayContaining(["Agent", "SendMessage", "Task", "TeamCreate", "ScheduleWakeup"]),
|
||||
sandbox: expect.objectContaining({
|
||||
enabled: true,
|
||||
failIfUnavailable: true,
|
||||
@@ -132,6 +131,38 @@ describe("runAgent", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("never exposes multi-agent orchestration tools on unrestricted roles", async () => {
|
||||
queryMock.mockReturnValue(messages(assistantMessage("ok"), resultMessage("sdk-session-1")));
|
||||
|
||||
await runAgent({
|
||||
prompt: "继续",
|
||||
model: undefined,
|
||||
project: { projectId: "p", boundChatId: "c", workspaceRoot, workspaceDir: workspace },
|
||||
systemPrompt: undefined,
|
||||
tools: null,
|
||||
runId: "run-1",
|
||||
sessionId: "hub-session-1",
|
||||
prisma: stubPrisma,
|
||||
});
|
||||
|
||||
const call = queryMock.mock.calls[0]?.[0] as {
|
||||
options?: { tools?: unknown; disallowedTools?: string[] };
|
||||
} | undefined;
|
||||
expect(call?.options?.tools).toEqual([
|
||||
"Read",
|
||||
"Write",
|
||||
"Bash",
|
||||
"Glob",
|
||||
"Grep",
|
||||
"WebFetch",
|
||||
"WebSearch",
|
||||
"TodoWrite",
|
||||
]);
|
||||
for (const blocked of ["Agent", "SendMessage", "Task", "TeamCreate", "ScheduleWakeup"]) {
|
||||
expect(call?.options?.disallowedTools).toContain(blocked);
|
||||
}
|
||||
});
|
||||
|
||||
it("does not send resume for a fresh Hub session", async () => {
|
||||
queryMock.mockReturnValue(messages(assistantMessage("fresh"), resultMessage("sdk-session-1")));
|
||||
|
||||
@@ -194,6 +225,7 @@ describe("runAgent", () => {
|
||||
"mcp__cph_hub__todo_write",
|
||||
],
|
||||
settings: expect.objectContaining({ todoFeatureEnabled: true }),
|
||||
disallowedTools: expect.arrayContaining(["Agent", "SendMessage"]),
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -217,6 +249,7 @@ describe("runAgent", () => {
|
||||
tools: ["TodoWrite"],
|
||||
allowedTools: ["TodoWrite", "mcp__cph_hub__todo_write"],
|
||||
settings: expect.objectContaining({ todoFeatureEnabled: true }),
|
||||
disallowedTools: expect.arrayContaining(["Agent", "SendMessage"]),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user