mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-01-22 22:44:13 +08:00
feat: add Agent SDK support with USE_AGENT_SDK feature flag (#698)
* feat: add Agent SDK support with USE_AGENT_SDK feature flag Add a feature-flagged code path that uses the Agent SDK instead of spawning the CLI as a subprocess. When USE_AGENT_SDK=true is set, the new SDK path is used; otherwise, existing CLI behavior is unchanged. Changes: - Add parse-sdk-options.ts for parsing ClaudeOptions into SDK format - Add run-claude-sdk.ts for SDK execution with query() function - Update run-claude.ts with feature flag check at entry point - Update update-comment-link.ts to handle both cost_usd and total_cost_usd - Add @anthropic-ai/claude-agent-sdk dependency 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor: simplify SDK types by using @anthropic-ai/claude-agent-sdk types directly - Remove duplicate SdkRunOptions and McpStdioServerConfig types - Use SDK's Options and McpStdioServerConfig types directly - Return { sdkOptions, showFullOutput, hasJsonSchema } from parseSdkOptions - Remove unnecessary convertMcpServers function - Net reduction of ~70 lines 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor: use extraArgs for claudeArgs pass-through to CLI Simplify option parsing by converting claudeArgs to extraArgs record and letting the SDK/CLI handle --mcp-config, --json-schema, etc. - Remove extractJsonSchema and parseMcpConfigs functions - Add parseClaudeArgsToExtraArgs for simple flag parsing - CLI handles complex args like --mcp-config directly 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * ci * refactor: remove hardcoded permission bypass flags The SDK path should match CLI path behavior - permissions are handled by the CLI itself, not hardcoded in the action. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * chore: add logging for SDK vs CLI path selection --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
105
base-action/src/parse-sdk-options.ts
Normal file
105
base-action/src/parse-sdk-options.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import { parse as parseShellArgs } from "shell-quote";
|
||||
import type { ClaudeOptions } from "./run-claude";
|
||||
import type { Options as SdkOptions } from "@anthropic-ai/claude-agent-sdk";
|
||||
|
||||
/**
|
||||
* Result of parsing ClaudeOptions for SDK usage
|
||||
*/
|
||||
export type ParsedSdkOptions = {
|
||||
sdkOptions: SdkOptions;
|
||||
showFullOutput: boolean;
|
||||
hasJsonSchema: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse claudeArgs string into extraArgs record for SDK pass-through
|
||||
* The SDK/CLI will handle --mcp-config, --json-schema, etc.
|
||||
*/
|
||||
function parseClaudeArgsToExtraArgs(
|
||||
claudeArgs?: string,
|
||||
): Record<string, string | null> {
|
||||
if (!claudeArgs?.trim()) return {};
|
||||
|
||||
const result: Record<string, string | null> = {};
|
||||
const args = parseShellArgs(claudeArgs).filter(
|
||||
(arg): arg is string => typeof arg === "string",
|
||||
);
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i];
|
||||
if (arg?.startsWith("--")) {
|
||||
const flag = arg.slice(2);
|
||||
const nextArg = args[i + 1];
|
||||
|
||||
// Check if next arg is a value (not another flag)
|
||||
if (nextArg && !nextArg.startsWith("--")) {
|
||||
result[flag] = nextArg;
|
||||
i++; // Skip the value
|
||||
} else {
|
||||
result[flag] = null; // Boolean flag
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse ClaudeOptions into SDK-compatible options
|
||||
* Uses extraArgs for CLI pass-through instead of duplicating option parsing
|
||||
*/
|
||||
export function parseSdkOptions(options: ClaudeOptions): ParsedSdkOptions {
|
||||
// Determine output verbosity
|
||||
const isDebugMode = process.env.ACTIONS_STEP_DEBUG === "true";
|
||||
const showFullOutput = options.showFullOutput === "true" || isDebugMode;
|
||||
|
||||
// Parse claudeArgs into extraArgs for CLI pass-through
|
||||
const extraArgs = parseClaudeArgsToExtraArgs(options.claudeArgs);
|
||||
|
||||
// Detect if --json-schema is present (for hasJsonSchema flag)
|
||||
const hasJsonSchema = "json-schema" in extraArgs;
|
||||
|
||||
// Build custom environment
|
||||
const env: Record<string, string | undefined> = { ...process.env };
|
||||
if (process.env.INPUT_ACTION_INPUTS_PRESENT) {
|
||||
env.GITHUB_ACTION_INPUTS = process.env.INPUT_ACTION_INPUTS_PRESENT;
|
||||
}
|
||||
|
||||
// Build system prompt option
|
||||
let systemPrompt: SdkOptions["systemPrompt"];
|
||||
if (options.systemPrompt) {
|
||||
systemPrompt = options.systemPrompt;
|
||||
} else if (options.appendSystemPrompt) {
|
||||
systemPrompt = {
|
||||
type: "preset",
|
||||
preset: "claude_code",
|
||||
append: options.appendSystemPrompt,
|
||||
};
|
||||
}
|
||||
|
||||
// Build SDK options - use direct options for explicit inputs, extraArgs for claudeArgs pass-through
|
||||
const sdkOptions: SdkOptions = {
|
||||
// Direct options from ClaudeOptions inputs
|
||||
model: options.model,
|
||||
maxTurns: options.maxTurns ? parseInt(options.maxTurns, 10) : undefined,
|
||||
allowedTools: options.allowedTools
|
||||
? options.allowedTools.split(",").map((t) => t.trim())
|
||||
: undefined,
|
||||
disallowedTools: options.disallowedTools
|
||||
? options.disallowedTools.split(",").map((t) => t.trim())
|
||||
: undefined,
|
||||
systemPrompt,
|
||||
fallbackModel: options.fallbackModel,
|
||||
pathToClaudeCodeExecutable: options.pathToClaudeCodeExecutable,
|
||||
|
||||
// Pass through claudeArgs as extraArgs - CLI handles --mcp-config, --json-schema, etc.
|
||||
extraArgs,
|
||||
env,
|
||||
};
|
||||
|
||||
return {
|
||||
sdkOptions,
|
||||
showFullOutput,
|
||||
hasJsonSchema,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user