Skip to content

Commit 49cfcf8

Browse files
authored
refactor: remove CLI path, use Agent SDK exclusively (#849)
* refactor: remove CLI path, use Agent SDK exclusively - Remove CLI-based Claude execution in favor of Agent SDK - Delete prepareRunConfig, parseAndSetSessionId, parseAndSetStructuredOutputs functions - Remove named pipe IPC and sanitizeJsonOutput helper - Remove test-agent-sdk job from test-base-action workflow (SDK is now default) - Delete run-claude.test.ts and structured-output.test.ts (testing removed CLI code) - Update CLAUDE.md to remove named pipe references Co-Authored-By: Claude <noreply@anthropic.com> Claude-Generated-By: Claude Code (cli/claude-opus-4-5=100%) Claude-Steers: 2 Claude-Permission-Prompts: 1 Claude-Escapes: 0 Claude-Plan: <claude-plan> # Plan: Remove Non-Agent SDK Code Path ## Overview Since `use_agent_sdk` defaults to `true`, remove the legacy CLI code path entirely from `base-action/src/run-claude.ts`. ## Files to Modify ### 1. `base-action/src/run-claude.ts` - Main Cleanup **Remove imports:** - `exec` from `child_process` - `promisify` from `util` - `unlink`, `writeFile`, `stat` from `fs/promises` (keep `readFile` - check if needed) - `createWriteStream` from `fs` - `spawn` from `child_process` - `parseShellArgs` from `shell-quote` (still used in `parse-sdk-options.ts`, keep package) **Remove constants:** - `execAsync` - `PIPE_PATH` - `EXECUTION_FILE` (defined in both files, keep in SDK file) - `BASE_ARGS` **Remove types:** - `PreparedConfig` type (lines 85-89) - only used by `prepareRunConfig()` **Remove functions:** - `sanitizeJsonOutput()` (lines 21-68) - `prepareRunConfig()` (lines 91-125) - also remove export - `parseAndSetSessionId()` (lines 131-155) - also remove export - `parseAndSetStructuredOutputs()` (lines 162-197) - also remove export **Simplify `runClaude()`:** - Remove `useAgentSdk` flag check and logging (lines 200-204) - Remove the `if (useAgentSdk)` block, make SDK call direct - Remove entire CLI path (lines 211-438) - Resulting function becomes just: ```typescript export async function runClaude(promptPath: string, options: ClaudeOptions) { const parsedOptions = parseSdkOptions(options); return runClaudeWithSdk(promptPath, parsedOptions); } ``` ### 2. Delete Test Files **`base-action/test/run-claude.test.ts`:** - Delete entire file (only tests `prepareRunConfig()`) **`base-action/test/structured-output.test.ts`:** - Delete entire file (only tests `parseAndSetStructuredOutputs()` and `parseAndSetSessionId()`) ### 3. Workflow Update **`.github/workflows/test-base-action.yml`:** - Remove `test-agent-sdk` job (lines 120-176) - redundant now ### 4. Documentation Update **`base-action/CLAUDE.md`:** - Line 30: Remove "- Named pipes for IPC between prompt input and Claude process" - Line 57: Remove "- Uses `mkfifo` to create named pipes for prompt input" ## Verification 1. Run `bun run typecheck` to ensure no type errors 2. Run `bun test` to ensure remaining tests pass 3. Run `bun run format` to fix any formatting issues </claude-plan> * fix: address PR review comments - Add session_id output handling in run-claude-sdk.ts (critical) - Remove unused claudeEnv parameter from ClaudeOptions and index.ts - Update stale CLI path comment in parse-sdk-options.ts Claude-Generated-By: Claude Code (cli/claude-opus-4-5=100%) Claude-Steers: 0 Claude-Permission-Prompts: 0 Claude-Escapes: 0 Claude-Plan: <claude-plan> # Plan: Remove Non-Agent SDK Code Path ## Overview Since `use_agent_sdk` defaults to `true`, remove the legacy CLI code path entirely from `base-action/src/run-claude.ts`. ## Files to Modify ### 1. `base-action/src/run-claude.ts` - Main Cleanup **Remove imports:** - `exec` from `child_process` - `promisify` from `util` - `unlink`, `writeFile`, `stat` from `fs/promises` (keep `readFile` - check if needed) - `createWriteStream` from `fs` - `spawn` from `child_process` - `parseShellArgs` from `shell-quote` (still used in `parse-sdk-options.ts`, keep package) **Remove constants:** - `execAsync` - `PIPE_PATH` - `EXECUTION_FILE` (defined in both files, keep in SDK file) - `BASE_ARGS` **Remove types:** - `PreparedConfig` type (lines 85-89) - only used by `prepareRunConfig()` **Remove functions:** - `sanitizeJsonOutput()` (lines 21-68) - `prepareRunConfig()` (lines 91-125) - also remove export - `parseAndSetSessionId()` (lines 131-155) - also remove export - `parseAndSetStructuredOutputs()` (lines 162-197) - also remove export **Simplify `runClaude()`:** - Remove `useAgentSdk` flag check and logging (lines 200-204) - Remove the `if (useAgentSdk)` block, make SDK call direct - Remove entire CLI path (lines 211-438) - Resulting function becomes just: ```typescript export async function runClaude(promptPath: string, options: ClaudeOptions) { const parsedOptions = parseSdkOptions(options); return runClaudeWithSdk(promptPath, parsedOptions); } ``` ### 2. Delete Test Files **`base-action/test/run-claude.test.ts`:** - Delete entire file (only tests `prepareRunConfig()`) **`base-action/test/structured-output.test.ts`:** - Delete entire file (only tests `parseAndSetStructuredOutputs()` and `parseAndSetSessionId()`) ### 3. Workflow Update **`.github/workflows/test-base-action.yml`:** - Remove `test-agent-sdk` job (lines 120-176) - redundant now ### 4. Documentation Update **`base-action/CLAUDE.md`:** - Line 30: Remove "- Named pipes for IPC between prompt input and Claude process" - Line 57: Remove "- Uses `mkfifo` to create named pipes for prompt input" ## Verification 1. Run `bun run typecheck` to ensure no type errors 2. Run `bun test` to ensure remaining tests pass 3. Run `bun run format` to fix any formatting issues </claude-plan>
1 parent e208124 commit 49cfcf8

8 files changed

Lines changed: 12 additions & 805 deletions

File tree

.github/workflows/test-base-action.yml

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -116,61 +116,3 @@ jobs:
116116
echo "❌ Execution log file not found"
117117
exit 1
118118
fi
119-
120-
test-agent-sdk:
121-
runs-on: ubuntu-latest
122-
steps:
123-
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
124-
125-
- name: Test with Agent SDK
126-
id: sdk-test
127-
uses: ./base-action
128-
env:
129-
USE_AGENT_SDK: "true"
130-
with:
131-
prompt: ${{ github.event.inputs.test_prompt || 'List the files in the current directory starting with "package"' }}
132-
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
133-
allowed_tools: "LS,Read"
134-
135-
- name: Verify SDK output
136-
run: |
137-
OUTPUT_FILE="${{ steps.sdk-test.outputs.execution_file }}"
138-
CONCLUSION="${{ steps.sdk-test.outputs.conclusion }}"
139-
140-
echo "Conclusion: $CONCLUSION"
141-
echo "Output file: $OUTPUT_FILE"
142-
143-
if [ "$CONCLUSION" = "success" ]; then
144-
echo "✅ Action completed successfully with Agent SDK"
145-
else
146-
echo "❌ Action failed with Agent SDK"
147-
exit 1
148-
fi
149-
150-
if [ -f "$OUTPUT_FILE" ]; then
151-
if [ -s "$OUTPUT_FILE" ]; then
152-
echo "✅ Execution log file created successfully with content"
153-
echo "Validating JSON format:"
154-
if jq . "$OUTPUT_FILE" > /dev/null 2>&1; then
155-
echo "✅ Output is valid JSON"
156-
# Verify SDK output contains total_cost_usd (SDK field name)
157-
if jq -e '.[] | select(.type == "result") | .total_cost_usd' "$OUTPUT_FILE" > /dev/null 2>&1; then
158-
echo "✅ SDK output contains total_cost_usd field"
159-
else
160-
echo "❌ SDK output missing total_cost_usd field"
161-
exit 1
162-
fi
163-
echo "Content preview:"
164-
head -c 500 "$OUTPUT_FILE"
165-
else
166-
echo "❌ Output is not valid JSON"
167-
exit 1
168-
fi
169-
else
170-
echo "❌ Execution log file is empty"
171-
exit 1
172-
fi
173-
else
174-
echo "❌ Execution log file not found"
175-
exit 1
176-
fi

base-action/CLAUDE.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ This is a GitHub Action that allows running Claude Code within GitHub workflows.
2727
### Key Design Patterns
2828

2929
- Uses Bun runtime for development and execution
30-
- Named pipes for IPC between prompt input and Claude process
3130
- JSON streaming output format for execution logs
3231
- Composite action pattern to orchestrate multiple steps
3332
- Provider-agnostic design supporting Anthropic API, AWS Bedrock, and Google Vertex AI
@@ -54,7 +53,6 @@ This is a GitHub Action that allows running Claude Code within GitHub workflows.
5453

5554
## Important Technical Details
5655

57-
- Uses `mkfifo` to create named pipes for prompt input
5856
- Outputs execution logs as JSON to `/tmp/claude-execution-output.json`
5957
- Timeout enforcement via `timeout` command wrapper
6058
- Strict TypeScript configuration with Bun-specific settings

base-action/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ async function run() {
3636
mcpConfig: process.env.INPUT_MCP_CONFIG,
3737
systemPrompt: process.env.INPUT_SYSTEM_PROMPT,
3838
appendSystemPrompt: process.env.INPUT_APPEND_SYSTEM_PROMPT,
39-
claudeEnv: process.env.INPUT_CLAUDE_ENV,
4039
fallbackModel: process.env.INPUT_FALLBACK_MODEL,
4140
model: process.env.ANTHROPIC_MODEL,
4241
pathToClaudeCodeExecutable:

base-action/src/parse-sdk-options.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ export function parseSdkOptions(options: ClaudeOptions): ParsedSdkOptions {
212212
if (process.env.INPUT_ACTION_INPUTS_PRESENT) {
213213
env.GITHUB_ACTION_INPUTS = process.env.INPUT_ACTION_INPUTS_PRESENT;
214214
}
215-
// Ensure SDK path uses the same entrypoint as the CLI path
215+
// Set the entrypoint for Claude Code to identify this as the GitHub Action
216216
env.CLAUDE_CODE_ENTRYPOINT = "claude-code-github-action";
217217

218218
// Build system prompt option - default to claude_code preset

base-action/src/run-claude-sdk.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,15 @@ export async function runClaudeWithSdk(
178178
core.warning(`Failed to write execution file: ${error}`);
179179
}
180180

181+
// Extract and set session_id from system.init message
182+
const initMessage = messages.find(
183+
(m) => m.type === "system" && "subtype" in m && m.subtype === "init",
184+
);
185+
if (initMessage && "session_id" in initMessage && initMessage.session_id) {
186+
core.setOutput("session_id", initMessage.session_id);
187+
core.info(`Set session_id: ${initMessage.session_id}`);
188+
}
189+
181190
if (!resultMessage) {
182191
core.setOutput("conclusion", "failure");
183192
core.error("No result message received from Claude");

0 commit comments

Comments
 (0)