Commit graph

13 commits

Author SHA1 Message Date
Chase Naples
aebcf9d6a4
feat: add cli_path support to ClaudeAgentOptions (#235)
Some checks failed
Lint / lint (push) Has been cancelled
Test / test (macos-latest, 3.10) (push) Has been cancelled
Test / test (macos-latest, 3.11) (push) Has been cancelled
Test / test (macos-latest, 3.12) (push) Has been cancelled
Test / test (macos-latest, 3.13) (push) Has been cancelled
Test / test (ubuntu-latest, 3.10) (push) Has been cancelled
Test / test (ubuntu-latest, 3.11) (push) Has been cancelled
Test / test (ubuntu-latest, 3.12) (push) Has been cancelled
Test / test (ubuntu-latest, 3.13) (push) Has been cancelled
Test / test (windows-latest, 3.10) (push) Has been cancelled
Test / test (windows-latest, 3.11) (push) Has been cancelled
Test / test (windows-latest, 3.12) (push) Has been cancelled
Test / test (windows-latest, 3.13) (push) Has been cancelled
Test / test-examples (3.10) (push) Has been cancelled
Test / test-e2e (macos-latest, 3.10) (push) Has been cancelled
Test / test-e2e (macos-latest, 3.11) (push) Has been cancelled
Test / test-e2e (macos-latest, 3.12) (push) Has been cancelled
Test / test-e2e (macos-latest, 3.13) (push) Has been cancelled
Test / test-e2e (ubuntu-latest, 3.10) (push) Has been cancelled
Test / test-e2e (ubuntu-latest, 3.11) (push) Has been cancelled
Test / test-e2e (ubuntu-latest, 3.12) (push) Has been cancelled
Test / test-e2e (ubuntu-latest, 3.13) (push) Has been cancelled
Test / test-e2e (windows-latest, 3.10) (push) Has been cancelled
Test / test-e2e (windows-latest, 3.12) (push) Has been cancelled
Test / test-e2e (windows-latest, 3.13) (push) Has been cancelled
Test / test-examples (3.11) (push) Has been cancelled
Test / test-examples (3.12) (push) Has been cancelled
Test / test-examples (3.13) (push) Has been cancelled
Test / test-e2e (windows-latest, 3.11) (push) Has been cancelled
## Summary
Adds support for passing custom Claude Code CLI paths through
`ClaudeAgentOptions`, allowing organizations with non-standard
installation locations to specify the CLI path explicitly.

## Motivation
As noted in #214, organizations may install Claude Code CLI (or wrapped
versions) at custom locations and prefer to provide those paths instead
of relying on the SDK's default search logic. The transport layer
already supported `cli_path`, but it was never exposed through the
public API.

## Changes
1. **types.py**: Added `cli_path: str | Path | None = None` parameter to
`ClaudeAgentOptions` dataclass
2. **_internal/client.py**: Pass `cli_path` from
`configured_options.cli_path` to `SubprocessCLITransport`
3. **client.py**: Pass `cli_path` from `options.cli_path` to
`SubprocessCLITransport`

## Implementation Details
The `SubprocessCLITransport` constructor already accepted a `cli_path`
parameter (line 40 of subprocess_cli.py), but it was never passed from
the client layers. This PR completes the wiring by:
- Adding the option to the public `ClaudeAgentOptions` interface
- Extracting and passing it through both client implementations
(`InternalClient.process_query` and `ClaudeSDKClient.connect`)

## Usage Example
```python
from claude_agent_sdk import query, ClaudeAgentOptions

# Specify custom CLI path
options = ClaudeAgentOptions(
    cli_path="/custom/path/to/claude"
)

result = await query("Hello!", options=options)
```

## Testing
- No new tests added as this is a straightforward parameter pass-through
- Existing tests should continue to work (default behavior unchanged)
- CI will validate the changes don't break existing functionality

Fixes #214

---------

Co-authored-by: Ashwin Bhat <ashwin@anthropic.com>
2025-10-12 23:19:53 -07:00
Michael Gendy
4b9cfc76e4
Make CLI buffer limit configurable (#190) 2025-09-28 15:45:06 -07:00
Dickson Tsai
b3656b1765
Rename claude_code to claude_agent (#188) 2025-09-28 14:52:53 -07:00
Dickson Tsai
0d2404e5d9
Rename ClaudeCodeOptions to ClaudeAgentOptions (#185)
Some checks failed
Lint / lint (push) Has been cancelled
Test / test (3.10) (push) Has been cancelled
Test / test (3.11) (push) Has been cancelled
Test / test (3.12) (push) Has been cancelled
Test / test (3.13) (push) Has been cancelled
Test / test-e2e (3.10) (push) Has been cancelled
Test / test-e2e (3.11) (push) Has been cancelled
Test / test-e2e (3.12) (push) Has been cancelled
Test / test-e2e (3.13) (push) Has been cancelled
Test / test-examples (3.10) (push) Has been cancelled
Test / test-examples (3.11) (push) Has been cancelled
Test / test-examples (3.12) (push) Has been cancelled
Test / test-examples (3.13) (push) Has been cancelled
2025-09-26 21:38:05 -07:00
Dickson Tsai
22fa9f473e
Implement control protocol support for Python SDK (#139)
Some checks failed
Lint / lint (push) Has been cancelled
Test / test (3.10) (push) Has been cancelled
Test / test (3.11) (push) Has been cancelled
Test / test (3.12) (push) Has been cancelled
Test / test (3.13) (push) Has been cancelled
## Summary

This PR implements control protocol support in the Python SDK, aligning
it with the TypeScript implementation pattern. The refactor introduces a
Query + Transport separation to enable bidirectional communication
between the SDK and CLI.

## Motivation

The previous Python SDK implementation used a high-level abstraction in
the Transport ABC (`send_request`/`receive_messages`) that couldn't
handle bidirectional communication. This prevented support for:
- Control messages from CLI to SDK that need responses
- Hooks implementation  
- Dynamic permission mode changes
- SDK MCP servers

## Changes

### Core Architecture Refactor

1. **New Query Class** (`src/claude_code_sdk/_internal/query.py`)
   - Manages control protocol on top of Transport
   - Handles control request/response routing
   - Manages initialization handshake with timeout
   - Supports hook callbacks and tool permission callbacks
   - Implements message streaming

2. **Refactored Transport ABC**
(`src/claude_code_sdk/_internal/transport/__init__.py`)
- Changed from high-level (`send_request`/`receive_messages`) to
low-level (`write`/`read_messages`) interface
   - Now handles raw I/O instead of protocol logic
   - Aligns with TypeScript ProcessTransport pattern

3. **Updated SubprocessCLITransport**
(`src/claude_code_sdk/_internal/transport/subprocess_cli.py`)
   - Simplified to focus on raw message streaming
   - Removed protocol logic (moved to Query)
   - Improved cleanup and error handling

4. **Enhanced ClaudeSDKClient** (`src/claude_code_sdk/client.py`)
   - Now uses Query for control protocol
   - Supports initialization messages
   - Better error handling for control protocol failures

### Control Protocol Features

- **Initialization handshake**: SDK sends initialize request, CLI
responds with supported commands
- **Control message types**: 
  - `initialize`: Establish bidirectional connection
  - `interrupt`: Cancel ongoing operations  
  - `set_permission_mode`: Change permission mode dynamically
- **Timeout handling**: 60-second timeout for initialization to handle
CLI versions without control support

### Examples

Updated `examples/streaming_mode.py` to demonstrate control protocol
initialization and error handling.

## Testing

- Tested with current CLI (no control protocol support yet) - gracefully
falls back
- Verified backward compatibility with existing `query()` function
- Tested initialization timeout handling
- Verified proper cleanup on errors

## Design Alignment

This implementation closely follows the TypeScript reference:
- `src/core/Query.ts` → `src/claude_code_sdk/_internal/query.py`
- `src/transport/ProcessTransport.ts` →
`src/claude_code_sdk/_internal/transport/subprocess_cli.py`
- `src/entrypoints/sdk.ts` → `src/claude_code_sdk/client.py`

## Next Steps

Once the CLI implements the control protocol handler, this will enable:
- Hooks support
- Dynamic permission mode changes
- SDK MCP servers
- Improved error recovery

🤖 Generated with [Claude Code](https://claude.ai/code)

---------

Co-authored-by: Ashwin Bhat <ashwin@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Kashyap Murali <kashyap@anthropic.com>
2025-09-01 23:04:22 -07:00
Lina Tawfik
404c50bce0
Fix FastAPI SSE streaming compatibility (fixes #4)
Remove anyio.create_task_group() from receive_messages() to fix the
RuntimeError "Attempted to exit cancel scope in a different task than
it was entered in" when using the SDK with FastAPI's SSE streaming.

The issue occurred because FastAPI can move async generators between
different asyncio tasks during the streaming lifecycle, which conflicts
with anyio's cancel scope tracking.

Changes:
- Remove task group usage from receive_messages()
- Read stderr sequentially after stdout completes
- Add test to ensure no task groups are used
- Fix existing test expectation for buffer overflow

This is a minimal fix that maintains compatibility while solving the
core issue. The trade-off is that stderr is read after stdout instead
of concurrently, but this is unlikely to cause issues in practice.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-01 00:04:50 -07:00
Lina Tawfik
1791031d20
chore: Remove obvious comments from code
Removed redundant comments that simply restate what the code is doing.
Kept only comments that provide valuable context or explain complex behavior.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-30 22:27:48 -07:00
Lina Tawfik
977bf6438b
style: apply ruff formatting 2025-06-30 21:58:37 -07:00
Lina Tawfik
24295417ac
fix: handle JSON messages split across multiple stream reads
Adds buffering to accumulate incomplete JSON messages that are split
across multiple stream reads due to asyncio's 64KB default buffer limit.

- Implement 1MB buffer to accumulate partial JSON
- Clear buffer on successful parse or size limit exceeded
- Add comprehensive tests for split JSON scenarios

Fixes CLIJSONDecodeError when reading large minified JSON files.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-30 21:55:06 -07:00
Lina Tawfik
7610791803
Apply ruff formatting
- Fixed quotes to use double quotes consistently
- Adjusted line breaks per ruff formatter rules
- No functional changes

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-27 15:08:20 -07:00
Lina Tawfik
ecad93a0c0
Apply ruff linting fixes
- Fixed formatting in test_subprocess_buffering.py
- No functional changes, only code style improvements

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-27 15:06:28 -07:00
Lina Tawfik
3f25c3bb83
Fix test to use anyio.run() pattern and add edge case tests
- Convert async test to use anyio.run() pattern consistent with other tests
- Remove unused CLIJSONDecodeError import
- Add tests for JSON with embedded newlines
- Add tests for multiple newlines between objects
- All tests passing

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-27 15:06:28 -07:00
Bradley-Butcher
87e2699f6a
fix multi-line buffering issue
Signed-off-by: Bradley-Butcher <brad@phoebe.ai>
2025-06-19 11:39:44 +01:00