Skip to content
Merged
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
16 changes: 15 additions & 1 deletion base-action/src/parse-sdk-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,20 @@ function mergeMcpConfigs(configValues: string[]): string {
return JSON.stringify(merged);
}

/**
* Strip comment lines from a shell argument string.
* Lines whose first non-whitespace character is `#` are removed entirely.
* Inline `#` within a line (e.g. inside a quoted value) is left untouched
* because shell-quote handles quoting — we only need to remove full comment lines
* before shell-quote sees them.
*/
function stripShellComments(input: string): string {
return input
.split("\n")
.filter((line) => !line.trim().startsWith("#"))
.join("\n");
}

/**
* Parse claudeArgs string into extraArgs record for SDK pass-through
* The SDK/CLI will handle --mcp-config, --json-schema, etc.
Expand All @@ -92,7 +106,7 @@ function parseClaudeArgsToExtraArgs(
if (!claudeArgs?.trim()) return {};

const result: Record<string, string | null> = {};
const args = parseShellArgs(claudeArgs).filter(
const args = parseShellArgs(stripShellComments(claudeArgs)).filter(
(arg): arg is string => typeof arg === "string",
);

Expand Down
36 changes: 36 additions & 0 deletions base-action/test/parse-sdk-options.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,42 @@ describe("parseSdkOptions", () => {
});
});

describe("shell comment stripping", () => {
test("should parse flags before and after a comment line", () => {
const options: ClaudeOptions = {
claudeArgs: "--model 'claude-haiku'\n# comment\n--allowed-tools 'Edit'",
};

const result = parseSdkOptions(options);

expect(result.sdkOptions.extraArgs?.["model"]).toBe("claude-haiku");
expect(result.sdkOptions.allowedTools).toEqual(["Edit"]);
});

test("should parse flags correctly when no comments are present", () => {
const options: ClaudeOptions = {
claudeArgs: "--model 'claude-haiku'",
};

const result = parseSdkOptions(options);

expect(result.sdkOptions.extraArgs?.["model"]).toBe("claude-haiku");
});

test("should not strip inline # that appears inside a quoted value", () => {
const options: ClaudeOptions = {
claudeArgs: "--model 'claude-haiku' --prompt 'use color #ff0000'",
};

const result = parseSdkOptions(options);

expect(result.sdkOptions.extraArgs?.["model"]).toBe("claude-haiku");
expect(result.sdkOptions.extraArgs?.["prompt"]).toBe(
"use color #ff0000",
);
});
});

describe("environment variables passthrough", () => {
test("should include OTEL environment variables in sdkOptions.env", () => {
// Set up test environment variables
Expand Down
Loading