mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-01-22 22:44:13 +08:00
fix: accumulate multiple --allowedTools flags for Agent SDK (#719)
* fix: merge allowedTools from claudeArgs when using Agent SDK When USE_AGENT_SDK=true, the allowedTools from claudeArgs (which contains tag mode's required tools like mcp__github_comment__update_claude_comment) were being lost because parseClaudeArgsToExtraArgs converts args to a Record<string, string>, and the SDK was using sdkOptions.allowedTools (from direct options) instead of merging with extraArgs.allowedTools. This fix: - Extracts allowedTools/disallowedTools from extraArgs after parsing - Merges them with any direct options.allowedTools/disallowedTools - Removes them from extraArgs to prevent duplicate CLI flags - Passes the merged list as sdkOptions.allowedTools 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: accumulate multiple --allowedTools flags in claudeArgs When tag mode adds its --allowedTools (with MCP tools) and the user also provides --allowedTools in their claude_args, the parseClaudeArgsToExtraArgs function was only keeping the last value. This caused tag mode's required tools like mcp__github_comment__update_claude_comment to be lost. Now allowedTools and disallowedTools flags accumulate their values when they appear multiple times in claudeArgs, so both tag mode's tools and user's tools are preserved. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
163
base-action/test/parse-sdk-options.test.ts
Normal file
163
base-action/test/parse-sdk-options.test.ts
Normal file
@@ -0,0 +1,163 @@
|
||||
#!/usr/bin/env bun
|
||||
|
||||
import { describe, test, expect } from "bun:test";
|
||||
import { parseSdkOptions } from "../src/parse-sdk-options";
|
||||
import type { ClaudeOptions } from "../src/run-claude";
|
||||
|
||||
describe("parseSdkOptions", () => {
|
||||
describe("allowedTools merging", () => {
|
||||
test("should extract allowedTools from claudeArgs", () => {
|
||||
const options: ClaudeOptions = {
|
||||
claudeArgs: '--allowedTools "Edit,Read,Write"',
|
||||
};
|
||||
|
||||
const result = parseSdkOptions(options);
|
||||
|
||||
expect(result.sdkOptions.allowedTools).toEqual(["Edit", "Read", "Write"]);
|
||||
expect(result.sdkOptions.extraArgs?.["allowedTools"]).toBeUndefined();
|
||||
});
|
||||
|
||||
test("should extract allowedTools from claudeArgs with MCP tools", () => {
|
||||
const options: ClaudeOptions = {
|
||||
claudeArgs:
|
||||
'--allowedTools "Edit,Read,mcp__github_comment__update_claude_comment"',
|
||||
};
|
||||
|
||||
const result = parseSdkOptions(options);
|
||||
|
||||
expect(result.sdkOptions.allowedTools).toEqual([
|
||||
"Edit",
|
||||
"Read",
|
||||
"mcp__github_comment__update_claude_comment",
|
||||
]);
|
||||
});
|
||||
|
||||
test("should accumulate multiple --allowedTools flags from claudeArgs", () => {
|
||||
// This simulates tag mode adding its tools, then user adding their own
|
||||
const options: ClaudeOptions = {
|
||||
claudeArgs:
|
||||
'--allowedTools "Edit,Read,mcp__github_comment__update_claude_comment" --model "claude-3" --allowedTools "Bash(npm install),mcp__github__get_issue"',
|
||||
};
|
||||
|
||||
const result = parseSdkOptions(options);
|
||||
|
||||
expect(result.sdkOptions.allowedTools).toEqual([
|
||||
"Edit",
|
||||
"Read",
|
||||
"mcp__github_comment__update_claude_comment",
|
||||
"Bash(npm install)",
|
||||
"mcp__github__get_issue",
|
||||
]);
|
||||
});
|
||||
|
||||
test("should merge allowedTools from both claudeArgs and direct options", () => {
|
||||
const options: ClaudeOptions = {
|
||||
claudeArgs: '--allowedTools "Edit,Read"',
|
||||
allowedTools: "Write,Glob",
|
||||
};
|
||||
|
||||
const result = parseSdkOptions(options);
|
||||
|
||||
expect(result.sdkOptions.allowedTools).toEqual([
|
||||
"Edit",
|
||||
"Read",
|
||||
"Write",
|
||||
"Glob",
|
||||
]);
|
||||
});
|
||||
|
||||
test("should deduplicate allowedTools when merging", () => {
|
||||
const options: ClaudeOptions = {
|
||||
claudeArgs: '--allowedTools "Edit,Read"',
|
||||
allowedTools: "Edit,Write",
|
||||
};
|
||||
|
||||
const result = parseSdkOptions(options);
|
||||
|
||||
expect(result.sdkOptions.allowedTools).toEqual(["Edit", "Read", "Write"]);
|
||||
});
|
||||
|
||||
test("should use only direct options when claudeArgs has no allowedTools", () => {
|
||||
const options: ClaudeOptions = {
|
||||
claudeArgs: '--model "claude-3-5-sonnet"',
|
||||
allowedTools: "Edit,Read",
|
||||
};
|
||||
|
||||
const result = parseSdkOptions(options);
|
||||
|
||||
expect(result.sdkOptions.allowedTools).toEqual(["Edit", "Read"]);
|
||||
});
|
||||
|
||||
test("should return undefined allowedTools when neither source has it", () => {
|
||||
const options: ClaudeOptions = {
|
||||
claudeArgs: '--model "claude-3-5-sonnet"',
|
||||
};
|
||||
|
||||
const result = parseSdkOptions(options);
|
||||
|
||||
expect(result.sdkOptions.allowedTools).toBeUndefined();
|
||||
});
|
||||
|
||||
test("should remove allowedTools from extraArgs after extraction", () => {
|
||||
const options: ClaudeOptions = {
|
||||
claudeArgs: '--allowedTools "Edit,Read" --model "claude-3-5-sonnet"',
|
||||
};
|
||||
|
||||
const result = parseSdkOptions(options);
|
||||
|
||||
expect(result.sdkOptions.extraArgs?.["allowedTools"]).toBeUndefined();
|
||||
expect(result.sdkOptions.extraArgs?.["model"]).toBe("claude-3-5-sonnet");
|
||||
});
|
||||
});
|
||||
|
||||
describe("disallowedTools merging", () => {
|
||||
test("should extract disallowedTools from claudeArgs", () => {
|
||||
const options: ClaudeOptions = {
|
||||
claudeArgs: '--disallowedTools "Bash,Write"',
|
||||
};
|
||||
|
||||
const result = parseSdkOptions(options);
|
||||
|
||||
expect(result.sdkOptions.disallowedTools).toEqual(["Bash", "Write"]);
|
||||
expect(result.sdkOptions.extraArgs?.["disallowedTools"]).toBeUndefined();
|
||||
});
|
||||
|
||||
test("should merge disallowedTools from both sources", () => {
|
||||
const options: ClaudeOptions = {
|
||||
claudeArgs: '--disallowedTools "Bash"',
|
||||
disallowedTools: "Write",
|
||||
};
|
||||
|
||||
const result = parseSdkOptions(options);
|
||||
|
||||
expect(result.sdkOptions.disallowedTools).toEqual(["Bash", "Write"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("other extraArgs passthrough", () => {
|
||||
test("should pass through mcp-config in extraArgs", () => {
|
||||
const options: ClaudeOptions = {
|
||||
claudeArgs: `--mcp-config '{"mcpServers":{}}' --allowedTools "Edit"`,
|
||||
};
|
||||
|
||||
const result = parseSdkOptions(options);
|
||||
|
||||
expect(result.sdkOptions.extraArgs?.["mcp-config"]).toBe(
|
||||
'{"mcpServers":{}}',
|
||||
);
|
||||
});
|
||||
|
||||
test("should pass through json-schema in extraArgs", () => {
|
||||
const options: ClaudeOptions = {
|
||||
claudeArgs: `--json-schema '{"type":"object"}'`,
|
||||
};
|
||||
|
||||
const result = parseSdkOptions(options);
|
||||
|
||||
expect(result.sdkOptions.extraArgs?.["json-schema"]).toBe(
|
||||
'{"type":"object"}',
|
||||
);
|
||||
expect(result.hasJsonSchema).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user