Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion base-action/src/parse-sdk-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,26 @@ function parseClaudeArgsToExtraArgs(
for (let i = 0; i < args.length; i++) {
const arg = args[i];
if (arg?.startsWith("--")) {
const flag = arg.slice(2);
let flag = arg.slice(2);

// Support the inline `--flag=value` form (accepted by the CLI) in
// addition to the space-separated `--flag value` form. Split on the first
// `=` only, so values that themselves contain `=` (e.g. inline JSON) are
// preserved. Without this, `--allowedTools=Edit,Read` becomes the bogus
// key "allowedTools=Edit,Read" and bypasses the tool-merge and
// --json-schema detection that parseSdkOptions performs on these keys.
const eqIndex = flag.indexOf("=");
if (eqIndex !== -1) {
const inlineValue = flag.slice(eqIndex + 1);
flag = flag.slice(0, eqIndex);
if (ACCUMULATING_FLAGS.has(flag) && result[flag]) {
result[flag] = `${result[flag]}${ACCUMULATE_DELIMITER}${inlineValue}`;
} else {
result[flag] = inlineValue;
}
continue; // inline value consumes no further tokens
}

const nextArg = args[i + 1];

// Check if next arg is a value (not another flag)
Expand Down
48 changes: 48 additions & 0 deletions base-action/test/parse-sdk-options.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -565,4 +565,52 @@ describe("parseSdkOptions", () => {
}
});
});

describe("--flag=value (inline value) form", () => {
test("--allowedTools=value parses the same as the space form", () => {
const equals = parseSdkOptions({
claudeArgs: "--allowedTools=Edit,Read",
});
const spaced = parseSdkOptions({
claudeArgs: "--allowedTools Edit,Read",
});

// identical result to the space-separated form
expect(equals.sdkOptions.allowedTools).toEqual(["Edit", "Read"]);
expect(spaced.sdkOptions.allowedTools).toEqual(["Edit", "Read"]);
// the raw "allowedTools=Edit,Read" token must not leak into extraArgs
expect(equals.sdkOptions.extraArgs?.["allowedTools"]).toBeUndefined();
expect(
equals.sdkOptions.extraArgs?.["allowedTools=Edit,Read"],
).toBeUndefined();
});

test("--json-schema=... is detected (hasJsonSchema), not left as a bogus key", () => {
const result = parseSdkOptions({
claudeArgs: '--json-schema={"type":"object"}',
});
expect(result.hasJsonSchema).toBe(true);
expect(result.sdkOptions.extraArgs?.["json-schema"]).toBeDefined();
});

test("splits on the first '=' only, preserving '=' in the value", () => {
const result = parseSdkOptions({ claudeArgs: "--model=claude-3-5=beta" });
expect(result.sdkOptions.extraArgs?.["model"]).toBe("claude-3-5=beta");
});

test("supports disallowedTools and add-dir in --flag=value form", () => {
const result = parseSdkOptions({
claudeArgs: "--disallowedTools=Bash --add-dir=/tmp/work",
});
expect(result.sdkOptions.disallowedTools).toEqual(["Bash"]);
expect(result.sdkOptions.additionalDirectories).toEqual(["/tmp/work"]);
});

test("accumulates repeated --allowedTools=... occurrences", () => {
const result = parseSdkOptions({
claudeArgs: "--allowedTools=Edit --allowedTools=Read,Write",
});
expect(result.sdkOptions.allowedTools).toEqual(["Edit", "Read", "Write"]);
});
});
});