claude-agent-sdk 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +34 -0
- data/README.md +408 -18
- data/lib/claude_agent_sdk/message_parser.rb +3 -2
- data/lib/claude_agent_sdk/query.rb +11 -0
- data/lib/claude_agent_sdk/subprocess_cli_transport.rb +67 -2
- data/lib/claude_agent_sdk/types.rb +139 -7
- data/lib/claude_agent_sdk/version.rb +1 -1
- data/lib/claude_agent_sdk.rb +9 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d4b8c3f8f0eefdfe38747d264f5d89148e1e589f12c200796dd2c37e821b3f61
|
|
4
|
+
data.tar.gz: 60252ef9c5f8679526a1f76b1be4216138e8bc7d91deb7bc1235b94d04a8481d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a95797df469fa0acede9c2187d0e8dd9420582e856853552dcc4b0c09b7e4564ca7371478624a904090366d06880a2e7457f71910b88e815fbbe12d8f210f255
|
|
7
|
+
data.tar.gz: 77354e6852d2f86b060ac0e4948006ed1c28311f7481e4efa7cdc2f57864448ab0d656244559da43094cde1ac409ae25fd4aad13228640001b0e453d7d9fc753
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,40 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.4.0] - 2026-01-06
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
#### File Checkpointing & Rewind
|
|
13
|
+
- `enable_file_checkpointing` option in `ClaudeAgentOptions` for enabling file state checkpointing
|
|
14
|
+
- `rewind_files(user_message_uuid)` method on `Query` and `Client` classes
|
|
15
|
+
- `uuid` field on `UserMessage` for tracking message identifiers for rewind support
|
|
16
|
+
|
|
17
|
+
#### Beta Features Support
|
|
18
|
+
- `SDK_BETAS` constant with available beta features (e.g., `"context-1m-2025-08-07"`)
|
|
19
|
+
- `betas` option in `ClaudeAgentOptions` for enabling beta features
|
|
20
|
+
|
|
21
|
+
#### Tools Configuration
|
|
22
|
+
- `tools` option for base tools selection (separate from `allowed_tools`)
|
|
23
|
+
- Supports array of tool names, empty array `[]`, or `ToolsPreset` object
|
|
24
|
+
- `ToolsPreset` class for preset-based tool configuration
|
|
25
|
+
- `append_allowed_tools` option to append tools to the allowed list
|
|
26
|
+
|
|
27
|
+
#### Sandbox Settings
|
|
28
|
+
- `SandboxSettings` class for isolated command execution configuration
|
|
29
|
+
- `SandboxNetworkConfig` class for network isolation settings
|
|
30
|
+
- `SandboxIgnoreViolations` class for configuring violation handling
|
|
31
|
+
- `sandbox` option in `ClaudeAgentOptions` for sandbox configuration
|
|
32
|
+
- Automatic merging of sandbox settings into the main settings JSON
|
|
33
|
+
|
|
34
|
+
#### Additional Types
|
|
35
|
+
- `SystemPromptPreset` class for preset-based system prompts
|
|
36
|
+
|
|
37
|
+
### Technical Details
|
|
38
|
+
- All new CLI flags properly passed to Claude Code subprocess
|
|
39
|
+
- Sandbox settings merged into `--settings` JSON for CLI compatibility
|
|
40
|
+
- UserMessage UUID parsed from CLI output for rewind support
|
|
41
|
+
|
|
8
42
|
## [0.2.0] - 2025-10-17
|
|
9
43
|
|
|
10
44
|
### Changed
|
data/README.md
CHANGED
|
@@ -15,6 +15,13 @@
|
|
|
15
15
|
- [Custom Tools (SDK MCP Servers)](#custom-tools-sdk-mcp-servers)
|
|
16
16
|
- [Hooks](#hooks)
|
|
17
17
|
- [Permission Callbacks](#permission-callbacks)
|
|
18
|
+
- [Structured Output](#structured-output)
|
|
19
|
+
- [Budget Control](#budget-control)
|
|
20
|
+
- [Fallback Model](#fallback-model)
|
|
21
|
+
- [Beta Features](#beta-features)
|
|
22
|
+
- [Tools Configuration](#tools-configuration)
|
|
23
|
+
- [Sandbox Settings](#sandbox-settings)
|
|
24
|
+
- [File Checkpointing & Rewind](#file-checkpointing--rewind)
|
|
18
25
|
- [Types](#types)
|
|
19
26
|
- [Error Handling](#error-handling)
|
|
20
27
|
- [Examples](#examples)
|
|
@@ -26,7 +33,7 @@
|
|
|
26
33
|
Add this line to your application's Gemfile:
|
|
27
34
|
|
|
28
35
|
```ruby
|
|
29
|
-
gem 'claude-agent-sdk', '~> 0.
|
|
36
|
+
gem 'claude-agent-sdk', '~> 0.4.0'
|
|
30
37
|
```
|
|
31
38
|
|
|
32
39
|
And then execute:
|
|
@@ -473,40 +480,417 @@ end.wait
|
|
|
473
480
|
|
|
474
481
|
For more examples, see [examples/permission_callback_example.rb](examples/permission_callback_example.rb).
|
|
475
482
|
|
|
483
|
+
## Structured Output
|
|
484
|
+
|
|
485
|
+
Use `output_format` to get validated JSON responses matching a schema. The Claude CLI returns structured output via a `StructuredOutput` tool use block.
|
|
486
|
+
|
|
487
|
+
```ruby
|
|
488
|
+
require 'claude_agent_sdk'
|
|
489
|
+
require 'json'
|
|
490
|
+
|
|
491
|
+
# Define a JSON schema
|
|
492
|
+
schema = {
|
|
493
|
+
type: 'object',
|
|
494
|
+
properties: {
|
|
495
|
+
name: { type: 'string' },
|
|
496
|
+
age: { type: 'integer' },
|
|
497
|
+
skills: { type: 'array', items: { type: 'string' } }
|
|
498
|
+
},
|
|
499
|
+
required: %w[name age skills]
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
options = ClaudeAgentSDK::ClaudeAgentOptions.new(
|
|
503
|
+
output_format: { type: 'json_schema', schema: schema },
|
|
504
|
+
max_turns: 3
|
|
505
|
+
)
|
|
506
|
+
|
|
507
|
+
structured_data = nil
|
|
508
|
+
|
|
509
|
+
ClaudeAgentSDK.query(
|
|
510
|
+
prompt: "Create a profile for a software engineer",
|
|
511
|
+
options: options
|
|
512
|
+
) do |message|
|
|
513
|
+
if message.is_a?(ClaudeAgentSDK::AssistantMessage)
|
|
514
|
+
message.content.each do |block|
|
|
515
|
+
# Structured output comes via StructuredOutput tool use
|
|
516
|
+
if block.is_a?(ClaudeAgentSDK::ToolUseBlock) && block.name == 'StructuredOutput'
|
|
517
|
+
structured_data = block.input
|
|
518
|
+
end
|
|
519
|
+
end
|
|
520
|
+
end
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
if structured_data
|
|
524
|
+
puts "Name: #{structured_data[:name]}"
|
|
525
|
+
puts "Age: #{structured_data[:age]}"
|
|
526
|
+
puts "Skills: #{structured_data[:skills].join(', ')}"
|
|
527
|
+
end
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
For complete examples, see [examples/structured_output_example.rb](examples/structured_output_example.rb).
|
|
531
|
+
|
|
532
|
+
## Budget Control
|
|
533
|
+
|
|
534
|
+
Use `max_budget_usd` to set a spending cap for your queries:
|
|
535
|
+
|
|
536
|
+
```ruby
|
|
537
|
+
options = ClaudeAgentSDK::ClaudeAgentOptions.new(
|
|
538
|
+
max_budget_usd: 0.10, # Cap at $0.10
|
|
539
|
+
max_turns: 3
|
|
540
|
+
)
|
|
541
|
+
|
|
542
|
+
ClaudeAgentSDK.query(prompt: "Explain recursion", options: options) do |message|
|
|
543
|
+
if message.is_a?(ClaudeAgentSDK::ResultMessage)
|
|
544
|
+
puts "Cost: $#{message.total_cost_usd}"
|
|
545
|
+
end
|
|
546
|
+
end
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
For complete examples, see [examples/budget_control_example.rb](examples/budget_control_example.rb).
|
|
550
|
+
|
|
551
|
+
## Fallback Model
|
|
552
|
+
|
|
553
|
+
Use `fallback_model` to specify a backup model if the primary is unavailable:
|
|
554
|
+
|
|
555
|
+
```ruby
|
|
556
|
+
options = ClaudeAgentSDK::ClaudeAgentOptions.new(
|
|
557
|
+
model: 'claude-sonnet-4-20250514',
|
|
558
|
+
fallback_model: 'claude-3-5-haiku-20241022'
|
|
559
|
+
)
|
|
560
|
+
|
|
561
|
+
ClaudeAgentSDK.query(prompt: "Hello", options: options) do |message|
|
|
562
|
+
if message.is_a?(ClaudeAgentSDK::AssistantMessage)
|
|
563
|
+
puts "Model used: #{message.model}"
|
|
564
|
+
end
|
|
565
|
+
end
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
For complete examples, see [examples/fallback_model_example.rb](examples/fallback_model_example.rb).
|
|
569
|
+
|
|
570
|
+
## Beta Features
|
|
571
|
+
|
|
572
|
+
Enable experimental features using the `betas` option:
|
|
573
|
+
|
|
574
|
+
```ruby
|
|
575
|
+
options = ClaudeAgentSDK::ClaudeAgentOptions.new(
|
|
576
|
+
betas: ['context-1m-2025-08-07'] # Extended context window
|
|
577
|
+
)
|
|
578
|
+
|
|
579
|
+
ClaudeAgentSDK.query(prompt: "Analyze this large document...", options: options) do |message|
|
|
580
|
+
puts message
|
|
581
|
+
end
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
Available beta features are listed in the `SDK_BETAS` constant.
|
|
585
|
+
|
|
586
|
+
## Tools Configuration
|
|
587
|
+
|
|
588
|
+
Configure base tools separately from allowed tools:
|
|
589
|
+
|
|
590
|
+
```ruby
|
|
591
|
+
# Using an array of tool names
|
|
592
|
+
options = ClaudeAgentSDK::ClaudeAgentOptions.new(
|
|
593
|
+
tools: ['Read', 'Edit', 'Bash'] # Base tools available
|
|
594
|
+
)
|
|
595
|
+
|
|
596
|
+
# Using a preset
|
|
597
|
+
options = ClaudeAgentSDK::ClaudeAgentOptions.new(
|
|
598
|
+
tools: ClaudeAgentSDK::ToolsPreset.new(preset: 'claude_code')
|
|
599
|
+
)
|
|
600
|
+
|
|
601
|
+
# Appending to allowed tools
|
|
602
|
+
options = ClaudeAgentSDK::ClaudeAgentOptions.new(
|
|
603
|
+
append_allowed_tools: ['Write', 'Bash']
|
|
604
|
+
)
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
## Sandbox Settings
|
|
608
|
+
|
|
609
|
+
Run commands in an isolated sandbox for additional security:
|
|
610
|
+
|
|
611
|
+
```ruby
|
|
612
|
+
sandbox = ClaudeAgentSDK::SandboxSettings.new(
|
|
613
|
+
enabled: true,
|
|
614
|
+
auto_allow_bash_if_sandboxed: true,
|
|
615
|
+
network: ClaudeAgentSDK::SandboxNetworkConfig.new(
|
|
616
|
+
allow_local_binding: true
|
|
617
|
+
)
|
|
618
|
+
)
|
|
619
|
+
|
|
620
|
+
options = ClaudeAgentSDK::ClaudeAgentOptions.new(
|
|
621
|
+
sandbox: sandbox,
|
|
622
|
+
permission_mode: 'acceptEdits'
|
|
623
|
+
)
|
|
624
|
+
|
|
625
|
+
ClaudeAgentSDK.query(prompt: "Run some commands", options: options) do |message|
|
|
626
|
+
puts message
|
|
627
|
+
end
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
## File Checkpointing & Rewind
|
|
631
|
+
|
|
632
|
+
Enable file checkpointing to revert file changes to a previous state:
|
|
633
|
+
|
|
634
|
+
```ruby
|
|
635
|
+
require 'async'
|
|
636
|
+
|
|
637
|
+
Async do
|
|
638
|
+
options = ClaudeAgentSDK::ClaudeAgentOptions.new(
|
|
639
|
+
enable_file_checkpointing: true,
|
|
640
|
+
permission_mode: 'acceptEdits'
|
|
641
|
+
)
|
|
642
|
+
|
|
643
|
+
client = ClaudeAgentSDK::Client.new(options: options)
|
|
644
|
+
client.connect
|
|
645
|
+
|
|
646
|
+
# Track user message UUIDs for potential rewind
|
|
647
|
+
user_message_uuids = []
|
|
648
|
+
|
|
649
|
+
# First query - create a file
|
|
650
|
+
client.query("Create a test.rb file with some code")
|
|
651
|
+
client.receive_response do |message|
|
|
652
|
+
# Process all message types as needed
|
|
653
|
+
case message
|
|
654
|
+
when ClaudeAgentSDK::UserMessage
|
|
655
|
+
# Capture UUID for rewind capability
|
|
656
|
+
user_message_uuids << message.uuid if message.uuid
|
|
657
|
+
when ClaudeAgentSDK::AssistantMessage
|
|
658
|
+
# Handle assistant responses
|
|
659
|
+
message.content.each do |block|
|
|
660
|
+
puts block.text if block.is_a?(ClaudeAgentSDK::TextBlock)
|
|
661
|
+
end
|
|
662
|
+
when ClaudeAgentSDK::ResultMessage
|
|
663
|
+
puts "Query completed (cost: $#{message.total_cost_usd})"
|
|
664
|
+
end
|
|
665
|
+
end
|
|
666
|
+
|
|
667
|
+
# Second query - modify the file
|
|
668
|
+
client.query("Modify the test.rb file to add error handling")
|
|
669
|
+
client.receive_response do |message|
|
|
670
|
+
user_message_uuids << message.uuid if message.is_a?(ClaudeAgentSDK::UserMessage) && message.uuid
|
|
671
|
+
end
|
|
672
|
+
|
|
673
|
+
# Rewind to the first checkpoint (undoes the second query's changes)
|
|
674
|
+
if user_message_uuids.first
|
|
675
|
+
puts "Rewinding to checkpoint: #{user_message_uuids.first}"
|
|
676
|
+
client.rewind_files(user_message_uuids.first)
|
|
677
|
+
end
|
|
678
|
+
|
|
679
|
+
client.disconnect
|
|
680
|
+
end
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
> **Note:** The `uuid` field on `UserMessage` is populated by the CLI and represents checkpoint identifiers. Rewinding to a UUID restores file state to what it was at that point in the conversation.
|
|
684
|
+
|
|
476
685
|
## Types
|
|
477
686
|
|
|
478
|
-
See [lib/claude_agent_sdk/types.rb](lib/claude_agent_sdk/types.rb) for complete type definitions
|
|
687
|
+
See [lib/claude_agent_sdk/types.rb](lib/claude_agent_sdk/types.rb) for complete type definitions.
|
|
479
688
|
|
|
480
689
|
### Message Types
|
|
481
690
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
|
485
|
-
|
|
486
|
-
| `SystemMessage` | System metadata message |
|
|
487
|
-
| `ResultMessage` | Final result with cost and usage information |
|
|
488
|
-
| `StreamEvent` | Partial message updates during streaming |
|
|
691
|
+
```ruby
|
|
692
|
+
# Union type of all possible messages
|
|
693
|
+
Message = UserMessage | AssistantMessage | SystemMessage | ResultMessage
|
|
694
|
+
```
|
|
489
695
|
|
|
490
|
-
|
|
696
|
+
#### UserMessage
|
|
491
697
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
698
|
+
User input message.
|
|
699
|
+
|
|
700
|
+
```ruby
|
|
701
|
+
class UserMessage
|
|
702
|
+
attr_accessor :content, # String | Array<ContentBlock>
|
|
703
|
+
:uuid, # String | nil - Unique ID for rewind support
|
|
704
|
+
:parent_tool_use_id # String | nil
|
|
705
|
+
end
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
#### AssistantMessage
|
|
709
|
+
|
|
710
|
+
Assistant response message with content blocks.
|
|
711
|
+
|
|
712
|
+
```ruby
|
|
713
|
+
class AssistantMessage
|
|
714
|
+
attr_accessor :content, # Array<ContentBlock>
|
|
715
|
+
:model, # String
|
|
716
|
+
:parent_tool_use_id,# String | nil
|
|
717
|
+
:error # String | nil ('authentication_failed', 'billing_error', 'rate_limit', 'invalid_request', 'server_error', 'unknown')
|
|
718
|
+
end
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
#### SystemMessage
|
|
722
|
+
|
|
723
|
+
System message with metadata.
|
|
724
|
+
|
|
725
|
+
```ruby
|
|
726
|
+
class SystemMessage
|
|
727
|
+
attr_accessor :subtype, # String ('init', etc.)
|
|
728
|
+
:data # Hash
|
|
729
|
+
end
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
#### ResultMessage
|
|
733
|
+
|
|
734
|
+
Final result message with cost and usage information.
|
|
735
|
+
|
|
736
|
+
```ruby
|
|
737
|
+
class ResultMessage
|
|
738
|
+
attr_accessor :subtype, # String
|
|
739
|
+
:duration_ms, # Integer
|
|
740
|
+
:duration_api_ms, # Integer
|
|
741
|
+
:is_error, # Boolean
|
|
742
|
+
:num_turns, # Integer
|
|
743
|
+
:session_id, # String
|
|
744
|
+
:total_cost_usd, # Float | nil
|
|
745
|
+
:usage, # Hash | nil
|
|
746
|
+
:result, # String | nil (final text result)
|
|
747
|
+
:structured_output # Hash | nil (when using output_format)
|
|
748
|
+
end
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
### Content Block Types
|
|
752
|
+
|
|
753
|
+
```ruby
|
|
754
|
+
# Union type of all content blocks
|
|
755
|
+
ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
#### TextBlock
|
|
498
759
|
|
|
499
|
-
|
|
760
|
+
Text content block.
|
|
761
|
+
|
|
762
|
+
```ruby
|
|
763
|
+
class TextBlock
|
|
764
|
+
attr_accessor :text # String
|
|
765
|
+
end
|
|
766
|
+
```
|
|
767
|
+
|
|
768
|
+
#### ThinkingBlock
|
|
769
|
+
|
|
770
|
+
Thinking content block (for models with extended thinking capability).
|
|
771
|
+
|
|
772
|
+
```ruby
|
|
773
|
+
class ThinkingBlock
|
|
774
|
+
attr_accessor :thinking, # String
|
|
775
|
+
:signature # String
|
|
776
|
+
end
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
#### ToolUseBlock
|
|
780
|
+
|
|
781
|
+
Tool use request block.
|
|
782
|
+
|
|
783
|
+
```ruby
|
|
784
|
+
class ToolUseBlock
|
|
785
|
+
attr_accessor :id, # String
|
|
786
|
+
:name, # String
|
|
787
|
+
:input # Hash
|
|
788
|
+
end
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
#### ToolResultBlock
|
|
792
|
+
|
|
793
|
+
Tool execution result block.
|
|
794
|
+
|
|
795
|
+
```ruby
|
|
796
|
+
class ToolResultBlock
|
|
797
|
+
attr_accessor :tool_use_id, # String
|
|
798
|
+
:content, # String | Array<Hash> | nil
|
|
799
|
+
:is_error # Boolean | nil
|
|
800
|
+
end
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
### Error Types
|
|
804
|
+
|
|
805
|
+
```ruby
|
|
806
|
+
# Base exception class for all SDK errors
|
|
807
|
+
class ClaudeSDKError < StandardError; end
|
|
808
|
+
|
|
809
|
+
# Raised when Claude Code CLI is not found
|
|
810
|
+
class CLINotFoundError < CLIConnectionError
|
|
811
|
+
# @param message [String] Error message (default: "Claude Code not found")
|
|
812
|
+
# @param cli_path [String, nil] Optional path to the CLI that was not found
|
|
813
|
+
end
|
|
814
|
+
|
|
815
|
+
# Raised when connection to Claude Code fails
|
|
816
|
+
class CLIConnectionError < ClaudeSDKError; end
|
|
817
|
+
|
|
818
|
+
# Raised when the Claude Code process fails
|
|
819
|
+
class ProcessError < ClaudeSDKError
|
|
820
|
+
attr_reader :exit_code, # Integer | nil
|
|
821
|
+
:stderr # String | nil
|
|
822
|
+
end
|
|
823
|
+
|
|
824
|
+
# Raised when JSON parsing fails
|
|
825
|
+
class CLIJSONDecodeError < ClaudeSDKError
|
|
826
|
+
attr_reader :line, # String - The line that failed to parse
|
|
827
|
+
:original_error # Exception - The original JSON decode exception
|
|
828
|
+
end
|
|
829
|
+
|
|
830
|
+
# Raised when message parsing fails
|
|
831
|
+
class MessageParseError < ClaudeSDKError
|
|
832
|
+
attr_reader :data # Hash | nil
|
|
833
|
+
end
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
### Configuration Types
|
|
500
837
|
|
|
501
838
|
| Type | Description |
|
|
502
839
|
|------|-------------|
|
|
503
840
|
| `ClaudeAgentOptions` | Main configuration for queries and clients |
|
|
504
|
-
| `HookMatcher` | Hook configuration with matcher pattern |
|
|
841
|
+
| `HookMatcher` | Hook configuration with matcher pattern and timeout |
|
|
505
842
|
| `PermissionResultAllow` | Permission callback result to allow tool use |
|
|
506
843
|
| `PermissionResultDeny` | Permission callback result to deny tool use |
|
|
844
|
+
| `AgentDefinition` | Agent definition with description, prompt, tools, model |
|
|
845
|
+
| `McpStdioServerConfig` | MCP server config for stdio transport |
|
|
846
|
+
| `McpSSEServerConfig` | MCP server config for SSE transport |
|
|
847
|
+
| `McpHttpServerConfig` | MCP server config for HTTP transport |
|
|
848
|
+
| `SdkPluginConfig` | SDK plugin configuration |
|
|
849
|
+
| `SandboxSettings` | Sandbox settings for isolated command execution |
|
|
850
|
+
| `SandboxNetworkConfig` | Network configuration for sandbox |
|
|
851
|
+
| `SandboxIgnoreViolations` | Configure which sandbox violations to ignore |
|
|
852
|
+
| `SystemPromptPreset` | System prompt preset configuration |
|
|
853
|
+
| `ToolsPreset` | Tools preset configuration for base tools selection |
|
|
854
|
+
|
|
855
|
+
### Constants
|
|
856
|
+
|
|
857
|
+
| Constant | Description |
|
|
858
|
+
|----------|-------------|
|
|
859
|
+
| `SDK_BETAS` | Available beta features (e.g., `"context-1m-2025-08-07"`) |
|
|
860
|
+
| `PERMISSION_MODES` | Available permission modes |
|
|
861
|
+
| `SETTING_SOURCES` | Available setting sources |
|
|
862
|
+
| `HOOK_EVENTS` | Available hook events |
|
|
863
|
+
| `ASSISTANT_MESSAGE_ERRORS` | Possible error types in AssistantMessage |
|
|
507
864
|
|
|
508
865
|
## Error Handling
|
|
509
866
|
|
|
867
|
+
### AssistantMessage Errors
|
|
868
|
+
|
|
869
|
+
`AssistantMessage` includes an `error` field for API-level errors:
|
|
870
|
+
|
|
871
|
+
```ruby
|
|
872
|
+
ClaudeAgentSDK.query(prompt: "Hello") do |message|
|
|
873
|
+
if message.is_a?(ClaudeAgentSDK::AssistantMessage) && message.error
|
|
874
|
+
case message.error
|
|
875
|
+
when 'rate_limit'
|
|
876
|
+
puts "Rate limited - retry after delay"
|
|
877
|
+
when 'authentication_failed'
|
|
878
|
+
puts "Check your API key"
|
|
879
|
+
when 'billing_error'
|
|
880
|
+
puts "Check your billing status"
|
|
881
|
+
when 'invalid_request'
|
|
882
|
+
puts "Invalid request format"
|
|
883
|
+
when 'server_error'
|
|
884
|
+
puts "Server error - retry later"
|
|
885
|
+
end
|
|
886
|
+
end
|
|
887
|
+
end
|
|
888
|
+
```
|
|
889
|
+
|
|
890
|
+
For complete examples, see [examples/error_handling_example.rb](examples/error_handling_example.rb).
|
|
891
|
+
|
|
892
|
+
### Exception Handling
|
|
893
|
+
|
|
510
894
|
```ruby
|
|
511
895
|
require 'claude_agent_sdk'
|
|
512
896
|
|
|
@@ -551,6 +935,12 @@ See the [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-co
|
|
|
551
935
|
| [examples/mcp_resources_prompts_example.rb](examples/mcp_resources_prompts_example.rb) | MCP resources and prompts |
|
|
552
936
|
| [examples/hooks_example.rb](examples/hooks_example.rb) | Using hooks to control tool execution |
|
|
553
937
|
| [examples/permission_callback_example.rb](examples/permission_callback_example.rb) | Dynamic tool permission control |
|
|
938
|
+
| [examples/structured_output_example.rb](examples/structured_output_example.rb) | JSON schema structured output |
|
|
939
|
+
| [examples/budget_control_example.rb](examples/budget_control_example.rb) | Budget control with `max_budget_usd` |
|
|
940
|
+
| [examples/fallback_model_example.rb](examples/fallback_model_example.rb) | Fallback model configuration |
|
|
941
|
+
| [examples/advanced_hooks_example.rb](examples/advanced_hooks_example.rb) | Typed hook inputs/outputs |
|
|
942
|
+
| [examples/error_handling_example.rb](examples/error_handling_example.rb) | Error handling with `AssistantMessage.error` |
|
|
943
|
+
| [examples/extended_thinking_example.rb](examples/extended_thinking_example.rb) | Extended thinking (API parity) |
|
|
554
944
|
|
|
555
945
|
## Development
|
|
556
946
|
|
|
@@ -32,6 +32,7 @@ module ClaudeAgentSDK
|
|
|
32
32
|
|
|
33
33
|
def self.parse_user_message(data)
|
|
34
34
|
parent_tool_use_id = data[:parent_tool_use_id]
|
|
35
|
+
uuid = data[:uuid] # UUID for rewind support
|
|
35
36
|
message_data = data[:message]
|
|
36
37
|
raise MessageParseError.new("Missing message field in user message", data: data) unless message_data
|
|
37
38
|
|
|
@@ -40,9 +41,9 @@ module ClaudeAgentSDK
|
|
|
40
41
|
|
|
41
42
|
if content.is_a?(Array)
|
|
42
43
|
content_blocks = content.map { |block| parse_content_block(block) }
|
|
43
|
-
UserMessage.new(content: content_blocks, parent_tool_use_id: parent_tool_use_id)
|
|
44
|
+
UserMessage.new(content: content_blocks, uuid: uuid, parent_tool_use_id: parent_tool_use_id)
|
|
44
45
|
else
|
|
45
|
-
UserMessage.new(content: content, parent_tool_use_id: parent_tool_use_id)
|
|
46
|
+
UserMessage.new(content: content, uuid: uuid, parent_tool_use_id: parent_tool_use_id)
|
|
46
47
|
end
|
|
47
48
|
end
|
|
48
49
|
|
|
@@ -551,6 +551,17 @@ module ClaudeAgentSDK
|
|
|
551
551
|
})
|
|
552
552
|
end
|
|
553
553
|
|
|
554
|
+
# Rewind files to a previous checkpoint (v0.1.15+)
|
|
555
|
+
# Restores file state to what it was at the given user message
|
|
556
|
+
# Requires enable_file_checkpointing to be true in options
|
|
557
|
+
# @param user_message_uuid [String] The UUID of the UserMessage to rewind to
|
|
558
|
+
def rewind_files(user_message_uuid)
|
|
559
|
+
send_control_request({
|
|
560
|
+
subtype: 'rewind_files',
|
|
561
|
+
userMessageUuid: user_message_uuid
|
|
562
|
+
})
|
|
563
|
+
end
|
|
564
|
+
|
|
554
565
|
# Stream input messages to transport
|
|
555
566
|
def stream_input(stream)
|
|
556
567
|
stream.each do |message|
|
|
@@ -80,12 +80,77 @@ module ClaudeAgentSDK
|
|
|
80
80
|
cmd.concat(['--permission-mode', @options.permission_mode]) if @options.permission_mode
|
|
81
81
|
cmd << '--continue' if @options.continue_conversation
|
|
82
82
|
cmd.concat(['--resume', @options.resume]) if @options.resume
|
|
83
|
-
cmd.concat(['--settings', @options.settings]) if @options.settings
|
|
84
83
|
|
|
85
|
-
#
|
|
84
|
+
# Settings handling with sandbox merge
|
|
85
|
+
# Sandbox settings are merged into the main settings JSON
|
|
86
|
+
if @options.settings || @options.sandbox
|
|
87
|
+
settings_hash = {}
|
|
88
|
+
settings_is_path = false
|
|
89
|
+
|
|
90
|
+
# Parse existing settings if provided
|
|
91
|
+
if @options.settings
|
|
92
|
+
if @options.settings.is_a?(String)
|
|
93
|
+
begin
|
|
94
|
+
settings_hash = JSON.parse(@options.settings)
|
|
95
|
+
rescue JSON::ParserError
|
|
96
|
+
# If not valid JSON, treat as file path and pass as-is
|
|
97
|
+
settings_is_path = true
|
|
98
|
+
cmd.concat(['--settings', @options.settings])
|
|
99
|
+
if @options.sandbox
|
|
100
|
+
warn "Warning: Cannot merge sandbox settings when settings is a file path. " \
|
|
101
|
+
"Sandbox settings will be ignored. Use a Hash or JSON string for settings " \
|
|
102
|
+
"to enable sandbox merging."
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
elsif @options.settings.is_a?(Hash)
|
|
106
|
+
settings_hash = @options.settings.dup
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Merge sandbox settings if provided (only when settings is not a file path)
|
|
111
|
+
if !settings_is_path && @options.sandbox
|
|
112
|
+
sandbox_hash = if @options.sandbox.is_a?(SandboxSettings)
|
|
113
|
+
@options.sandbox.to_h
|
|
114
|
+
else
|
|
115
|
+
@options.sandbox
|
|
116
|
+
end
|
|
117
|
+
settings_hash[:sandbox] = sandbox_hash unless sandbox_hash.empty?
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Output merged settings (only when settings is not a file path)
|
|
121
|
+
if !settings_is_path && !settings_hash.empty?
|
|
122
|
+
cmd.concat(['--settings', JSON.generate(settings_hash)])
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Budget limit option
|
|
86
127
|
cmd.concat(['--max-budget-usd', @options.max_budget_usd.to_s]) if @options.max_budget_usd
|
|
87
128
|
# Note: max_thinking_tokens is stored in options but not yet supported by Claude CLI
|
|
88
129
|
|
|
130
|
+
# Betas option for enabling experimental features
|
|
131
|
+
if @options.betas && !@options.betas.empty?
|
|
132
|
+
cmd.concat(['--betas', @options.betas.join(',')])
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Tools option for base tools selection
|
|
136
|
+
if @options.tools
|
|
137
|
+
if @options.tools.is_a?(Array)
|
|
138
|
+
cmd.concat(['--tools', @options.tools.join(',')])
|
|
139
|
+
elsif @options.tools.is_a?(ToolsPreset)
|
|
140
|
+
cmd.concat(['--tools', JSON.generate(@options.tools.to_h)])
|
|
141
|
+
elsif @options.tools.is_a?(Hash)
|
|
142
|
+
cmd.concat(['--tools', JSON.generate(@options.tools)])
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Append allowed tools option
|
|
147
|
+
if @options.append_allowed_tools && !@options.append_allowed_tools.empty?
|
|
148
|
+
cmd.concat(['--append-allowed-tools', @options.append_allowed_tools.join(',')])
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# File checkpointing for rewind support
|
|
152
|
+
cmd << '--enable-file-checkpointing' if @options.enable_file_checkpointing
|
|
153
|
+
|
|
89
154
|
# JSON schema for structured output
|
|
90
155
|
# Accepts either:
|
|
91
156
|
# 1. Direct schema: { type: 'object', properties: {...} }
|
|
@@ -19,6 +19,10 @@ module ClaudeAgentSDK
|
|
|
19
19
|
# Type constants for assistant message errors
|
|
20
20
|
ASSISTANT_MESSAGE_ERRORS = %w[authentication_failed billing_error rate_limit invalid_request server_error unknown].freeze
|
|
21
21
|
|
|
22
|
+
# Type constants for SDK beta features
|
|
23
|
+
# Available beta features that can be enabled via the betas option
|
|
24
|
+
SDK_BETAS = %w[context-1m-2025-08-07].freeze
|
|
25
|
+
|
|
22
26
|
# Content Blocks
|
|
23
27
|
|
|
24
28
|
# Text content block
|
|
@@ -66,10 +70,11 @@ module ClaudeAgentSDK
|
|
|
66
70
|
|
|
67
71
|
# User message
|
|
68
72
|
class UserMessage
|
|
69
|
-
attr_accessor :content, :parent_tool_use_id
|
|
73
|
+
attr_accessor :content, :uuid, :parent_tool_use_id
|
|
70
74
|
|
|
71
|
-
def initialize(content:, parent_tool_use_id: nil)
|
|
75
|
+
def initialize(content:, uuid: nil, parent_tool_use_id: nil)
|
|
72
76
|
@content = content
|
|
77
|
+
@uuid = uuid # Unique identifier for rewind support
|
|
73
78
|
@parent_tool_use_id = parent_tool_use_id
|
|
74
79
|
end
|
|
75
80
|
end
|
|
@@ -512,6 +517,125 @@ module ClaudeAgentSDK
|
|
|
512
517
|
end
|
|
513
518
|
end
|
|
514
519
|
|
|
520
|
+
# Sandbox network configuration
|
|
521
|
+
class SandboxNetworkConfig
|
|
522
|
+
attr_accessor :allow_unix_sockets, :allow_all_unix_sockets, :allow_local_binding,
|
|
523
|
+
:http_proxy_port, :socks_proxy_port
|
|
524
|
+
|
|
525
|
+
def initialize(
|
|
526
|
+
allow_unix_sockets: nil,
|
|
527
|
+
allow_all_unix_sockets: nil,
|
|
528
|
+
allow_local_binding: nil,
|
|
529
|
+
http_proxy_port: nil,
|
|
530
|
+
socks_proxy_port: nil
|
|
531
|
+
)
|
|
532
|
+
@allow_unix_sockets = allow_unix_sockets
|
|
533
|
+
@allow_all_unix_sockets = allow_all_unix_sockets
|
|
534
|
+
@allow_local_binding = allow_local_binding
|
|
535
|
+
@http_proxy_port = http_proxy_port
|
|
536
|
+
@socks_proxy_port = socks_proxy_port
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
def to_h
|
|
540
|
+
result = {}
|
|
541
|
+
result[:allowUnixSockets] = @allow_unix_sockets unless @allow_unix_sockets.nil?
|
|
542
|
+
result[:allowAllUnixSockets] = @allow_all_unix_sockets unless @allow_all_unix_sockets.nil?
|
|
543
|
+
result[:allowLocalBinding] = @allow_local_binding unless @allow_local_binding.nil?
|
|
544
|
+
result[:httpProxyPort] = @http_proxy_port if @http_proxy_port
|
|
545
|
+
result[:socksProxyPort] = @socks_proxy_port if @socks_proxy_port
|
|
546
|
+
result
|
|
547
|
+
end
|
|
548
|
+
end
|
|
549
|
+
|
|
550
|
+
# Sandbox ignore violations configuration
|
|
551
|
+
class SandboxIgnoreViolations
|
|
552
|
+
attr_accessor :file, :network
|
|
553
|
+
|
|
554
|
+
def initialize(file: nil, network: nil)
|
|
555
|
+
@file = file # Array of file paths to ignore
|
|
556
|
+
@network = network # Array of network patterns to ignore
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
def to_h
|
|
560
|
+
result = {}
|
|
561
|
+
result[:file] = @file if @file
|
|
562
|
+
result[:network] = @network if @network
|
|
563
|
+
result
|
|
564
|
+
end
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
# Sandbox settings for isolated command execution
|
|
568
|
+
class SandboxSettings
|
|
569
|
+
attr_accessor :enabled, :auto_allow_bash_if_sandboxed, :excluded_commands,
|
|
570
|
+
:allow_unsandboxed_commands, :network, :ignore_violations,
|
|
571
|
+
:enable_weaker_nested_sandbox
|
|
572
|
+
|
|
573
|
+
def initialize(
|
|
574
|
+
enabled: nil,
|
|
575
|
+
auto_allow_bash_if_sandboxed: nil,
|
|
576
|
+
excluded_commands: nil,
|
|
577
|
+
allow_unsandboxed_commands: nil,
|
|
578
|
+
network: nil,
|
|
579
|
+
ignore_violations: nil,
|
|
580
|
+
enable_weaker_nested_sandbox: nil
|
|
581
|
+
)
|
|
582
|
+
@enabled = enabled
|
|
583
|
+
@auto_allow_bash_if_sandboxed = auto_allow_bash_if_sandboxed
|
|
584
|
+
@excluded_commands = excluded_commands # Array of commands to exclude
|
|
585
|
+
@allow_unsandboxed_commands = allow_unsandboxed_commands
|
|
586
|
+
@network = network # SandboxNetworkConfig instance
|
|
587
|
+
@ignore_violations = ignore_violations # SandboxIgnoreViolations instance
|
|
588
|
+
@enable_weaker_nested_sandbox = enable_weaker_nested_sandbox
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
def to_h
|
|
592
|
+
result = {}
|
|
593
|
+
result[:enabled] = @enabled unless @enabled.nil?
|
|
594
|
+
result[:autoAllowBashIfSandboxed] = @auto_allow_bash_if_sandboxed unless @auto_allow_bash_if_sandboxed.nil?
|
|
595
|
+
result[:excludedCommands] = @excluded_commands if @excluded_commands
|
|
596
|
+
result[:allowUnsandboxedCommands] = @allow_unsandboxed_commands unless @allow_unsandboxed_commands.nil?
|
|
597
|
+
if @network
|
|
598
|
+
result[:network] = @network.is_a?(SandboxNetworkConfig) ? @network.to_h : @network
|
|
599
|
+
end
|
|
600
|
+
if @ignore_violations
|
|
601
|
+
result[:ignoreViolations] = @ignore_violations.is_a?(SandboxIgnoreViolations) ? @ignore_violations.to_h : @ignore_violations
|
|
602
|
+
end
|
|
603
|
+
result[:enableWeakerNestedSandbox] = @enable_weaker_nested_sandbox unless @enable_weaker_nested_sandbox.nil?
|
|
604
|
+
result
|
|
605
|
+
end
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
# System prompt preset configuration
|
|
609
|
+
class SystemPromptPreset
|
|
610
|
+
attr_accessor :type, :preset, :append
|
|
611
|
+
|
|
612
|
+
def initialize(preset:, append: nil)
|
|
613
|
+
@type = 'preset'
|
|
614
|
+
@preset = preset
|
|
615
|
+
@append = append
|
|
616
|
+
end
|
|
617
|
+
|
|
618
|
+
def to_h
|
|
619
|
+
result = { type: @type, preset: @preset }
|
|
620
|
+
result[:append] = @append if @append
|
|
621
|
+
result
|
|
622
|
+
end
|
|
623
|
+
end
|
|
624
|
+
|
|
625
|
+
# Tools preset configuration
|
|
626
|
+
class ToolsPreset
|
|
627
|
+
attr_accessor :type, :preset
|
|
628
|
+
|
|
629
|
+
def initialize(preset:)
|
|
630
|
+
@type = 'preset'
|
|
631
|
+
@preset = preset
|
|
632
|
+
end
|
|
633
|
+
|
|
634
|
+
def to_h
|
|
635
|
+
{ type: @type, preset: @preset }
|
|
636
|
+
end
|
|
637
|
+
end
|
|
638
|
+
|
|
515
639
|
# Claude Agent Options for configuring queries
|
|
516
640
|
class ClaudeAgentOptions
|
|
517
641
|
attr_accessor :allowed_tools, :system_prompt, :mcp_servers, :permission_mode,
|
|
@@ -520,9 +644,9 @@ module ClaudeAgentSDK
|
|
|
520
644
|
:add_dirs, :env, :extra_args, :max_buffer_size, :stderr,
|
|
521
645
|
:can_use_tool, :hooks, :user, :include_partial_messages,
|
|
522
646
|
:fork_session, :agents, :setting_sources,
|
|
523
|
-
# New options added to match Python SDK
|
|
524
647
|
:output_format, :max_budget_usd, :max_thinking_tokens,
|
|
525
|
-
:fallback_model, :plugins, :debug_stderr
|
|
648
|
+
:fallback_model, :plugins, :debug_stderr,
|
|
649
|
+
:betas, :tools, :sandbox, :enable_file_checkpointing, :append_allowed_tools
|
|
526
650
|
|
|
527
651
|
def initialize(
|
|
528
652
|
allowed_tools: [],
|
|
@@ -550,13 +674,17 @@ module ClaudeAgentSDK
|
|
|
550
674
|
fork_session: false,
|
|
551
675
|
agents: nil,
|
|
552
676
|
setting_sources: nil,
|
|
553
|
-
# New options added to match Python SDK
|
|
554
677
|
output_format: nil,
|
|
555
678
|
max_budget_usd: nil,
|
|
556
679
|
max_thinking_tokens: nil,
|
|
557
680
|
fallback_model: nil,
|
|
558
681
|
plugins: nil,
|
|
559
|
-
debug_stderr: nil
|
|
682
|
+
debug_stderr: nil,
|
|
683
|
+
betas: nil,
|
|
684
|
+
tools: nil,
|
|
685
|
+
sandbox: nil,
|
|
686
|
+
enable_file_checkpointing: false,
|
|
687
|
+
append_allowed_tools: nil
|
|
560
688
|
)
|
|
561
689
|
@allowed_tools = allowed_tools
|
|
562
690
|
@system_prompt = system_prompt
|
|
@@ -583,13 +711,17 @@ module ClaudeAgentSDK
|
|
|
583
711
|
@fork_session = fork_session
|
|
584
712
|
@agents = agents
|
|
585
713
|
@setting_sources = setting_sources
|
|
586
|
-
# New options added to match Python SDK
|
|
587
714
|
@output_format = output_format # JSON schema for structured output
|
|
588
715
|
@max_budget_usd = max_budget_usd # Spending cap in dollars
|
|
589
716
|
@max_thinking_tokens = max_thinking_tokens # Extended thinking token budget
|
|
590
717
|
@fallback_model = fallback_model # Backup model if primary unavailable
|
|
591
718
|
@plugins = plugins # Array of SdkPluginConfig
|
|
592
719
|
@debug_stderr = debug_stderr # Debug output file object/path
|
|
720
|
+
@betas = betas # Array of beta feature strings (e.g., ["context-1m-2025-08-07"])
|
|
721
|
+
@tools = tools # Base tools selection: Array, empty array [], or ToolsPreset
|
|
722
|
+
@sandbox = sandbox # SandboxSettings instance for isolated command execution
|
|
723
|
+
@enable_file_checkpointing = enable_file_checkpointing # Enable file checkpointing for rewind support
|
|
724
|
+
@append_allowed_tools = append_allowed_tools # Array of tools to append to allowed_tools
|
|
593
725
|
end
|
|
594
726
|
|
|
595
727
|
def dup_with(**changes)
|
data/lib/claude_agent_sdk.rb
CHANGED
|
@@ -244,6 +244,15 @@ module ClaudeAgentSDK
|
|
|
244
244
|
@query_handler.set_model(model)
|
|
245
245
|
end
|
|
246
246
|
|
|
247
|
+
# Rewind files to a previous checkpoint (v0.1.15+)
|
|
248
|
+
# Restores file state to what it was at the given user message
|
|
249
|
+
# Requires enable_file_checkpointing to be true in options
|
|
250
|
+
# @param user_message_uuid [String] The UUID of the UserMessage to rewind to
|
|
251
|
+
def rewind_files(user_message_uuid)
|
|
252
|
+
raise CLIConnectionError, 'Not connected. Call connect() first' unless @connected
|
|
253
|
+
@query_handler.rewind_files(user_message_uuid)
|
|
254
|
+
end
|
|
255
|
+
|
|
247
256
|
# Get server initialization info
|
|
248
257
|
# @return [Hash, nil] Server info or nil
|
|
249
258
|
def server_info
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: claude-agent-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Community Contributors
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 2026-01-05 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: async
|