claude-agent-sdk 0.16.5 → 0.16.6
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 +13 -0
- data/README.md +1 -1
- data/lib/claude_agent_sdk/message_parser.rb +29 -186
- data/lib/claude_agent_sdk/types.rb +574 -954
- data/lib/claude_agent_sdk/version.rb +1 -1
- 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: 5e77eea013fead986f47ff000864ddb9e52a3408186cf09bf3bb8d5214edec28
|
|
4
|
+
data.tar.gz: 49f94edca00072ec403cb26eb79165979d8684e655336bce6ca53f3c1a31eb81
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '08544dd09bb2d8c1127364517e1cc3527aaa0321d8c2d957550f078c5ce1d20796f5622f987ddd9f128377cad697d314a63a31031cd8eeb2e823bbfef282ee17'
|
|
7
|
+
data.tar.gz: e7149a4d3d9546631449d71878a6480d3d8758c2d990b3836cdc1dde65e93d09a8d19658c781c4f2cf5655bcb3c910dac84bc7d0076f635af4957f78a2e91fe9
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.16.6] - 2026-04-29
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Type classes now accept hash construction with mixed key shapes — symbols or strings, snake_case or camelCase — and support bracket access (`obj[:field]`, `obj['field']`). `UserMessage.new({"sessionId" => "abc"})` works the same as `UserMessage.new(session_id: "abc")`. `Type.from_hash(nil)` and `Type.wrap(nil)` are nil-safe.
|
|
14
|
+
- `ClaudeAgentOptions.new(nil)` is accepted and yields an options object populated with configured defaults.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- Discriminator fields on type classes (`type` on `SystemPromptFile`/`McpStdioServerConfig`/etc., `behavior` on `PermissionResultAllow`/`Deny`, `hook_event_name` on every hook input/output) are now `attr_reader`-only, set authoritatively in `initialize`. They cannot be overwritten externally.
|
|
18
|
+
- `ClaudeAgentOptions` continues to raise `ArgumentError` on unknown keys (constructor, `dup_with`, and `[]=`); other type subclasses silently drop unknown keys for forward-compatibility with newer CLI output.
|
|
19
|
+
|
|
20
|
+
### Internal
|
|
21
|
+
- Unified ~50 type classes (messages, hook inputs/outputs, MCP configs, system prompt configs, sandbox settings) under a shared `Type` base class. `lib/claude_agent_sdk/types.rb` shrank from 1510 to 588 lines; `MessageParser`'s system-message dispatch went from 215 lines to a 14-entry lookup table.
|
|
22
|
+
|
|
10
23
|
## [0.16.5] - 2026-04-24
|
|
11
24
|
|
|
12
25
|
### Added
|
data/README.md
CHANGED
|
@@ -108,7 +108,7 @@ Add this line to your application's Gemfile:
|
|
|
108
108
|
gem 'claude-agent-sdk', github: 'ya-luotao/claude-agent-sdk-ruby'
|
|
109
109
|
|
|
110
110
|
# Or use a stable version from RubyGems
|
|
111
|
-
gem 'claude-agent-sdk', '~> 0.16.
|
|
111
|
+
gem 'claude-agent-sdk', '~> 0.16.6'
|
|
112
112
|
```
|
|
113
113
|
|
|
114
114
|
And then execute:
|
|
@@ -78,214 +78,57 @@ module ClaudeAgentSDK
|
|
|
78
78
|
)
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
+
# Typed SystemMessage subclasses inherit from `Type` and accept the raw
|
|
82
|
+
# CLI hash directly — camelCase and snake_case keys are normalized by the
|
|
83
|
+
# base class, and the full hash is captured as `#data`.
|
|
84
|
+
SYSTEM_MESSAGE_CLASSES = {
|
|
85
|
+
'init' => InitMessage,
|
|
86
|
+
'compact_boundary' => CompactBoundaryMessage,
|
|
87
|
+
'status' => StatusMessage,
|
|
88
|
+
'api_retry' => APIRetryMessage,
|
|
89
|
+
'local_command_output' => LocalCommandOutputMessage,
|
|
90
|
+
'hook_started' => HookStartedMessage,
|
|
91
|
+
'hook_progress' => HookProgressMessage,
|
|
92
|
+
'hook_response' => HookResponseMessage,
|
|
93
|
+
'session_state_changed' => SessionStateChangedMessage,
|
|
94
|
+
'files_persisted' => FilesPersistedMessage,
|
|
95
|
+
'elicitation_complete' => ElicitationCompleteMessage,
|
|
96
|
+
'task_started' => TaskStartedMessage,
|
|
97
|
+
'task_progress' => TaskProgressMessage,
|
|
98
|
+
'task_notification' => TaskNotificationMessage
|
|
99
|
+
}.freeze
|
|
100
|
+
|
|
81
101
|
def self.parse_system_message(data)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
InitMessage.new(
|
|
85
|
-
subtype: data[:subtype], data: data,
|
|
86
|
-
uuid: data[:uuid], session_id: data[:session_id],
|
|
87
|
-
agents: data[:agents], api_key_source: data[:apiKeySource] || data[:api_key_source],
|
|
88
|
-
betas: data[:betas], claude_code_version: data[:claude_code_version],
|
|
89
|
-
cwd: data[:cwd], tools: data[:tools], mcp_servers: data[:mcp_servers],
|
|
90
|
-
model: data[:model], permission_mode: data[:permissionMode] || data[:permission_mode],
|
|
91
|
-
slash_commands: data[:slash_commands], output_style: data[:output_style],
|
|
92
|
-
skills: data[:skills], plugins: data[:plugins],
|
|
93
|
-
fast_mode_state: data[:fastModeState] || data[:fast_mode_state]
|
|
94
|
-
)
|
|
95
|
-
when 'compact_boundary'
|
|
96
|
-
raw_metadata = data[:compact_metadata]
|
|
97
|
-
CompactBoundaryMessage.new(
|
|
98
|
-
subtype: data[:subtype], data: data,
|
|
99
|
-
uuid: data[:uuid], session_id: data[:session_id],
|
|
100
|
-
compact_metadata: CompactMetadata.from_hash(raw_metadata)
|
|
101
|
-
)
|
|
102
|
-
when 'status'
|
|
103
|
-
StatusMessage.new(
|
|
104
|
-
subtype: data[:subtype], data: data,
|
|
105
|
-
uuid: data[:uuid], session_id: data[:session_id],
|
|
106
|
-
status: data[:status],
|
|
107
|
-
permission_mode: data[:permissionMode] || data[:permission_mode]
|
|
108
|
-
)
|
|
109
|
-
when 'api_retry'
|
|
110
|
-
APIRetryMessage.new(
|
|
111
|
-
subtype: data[:subtype], data: data,
|
|
112
|
-
uuid: data[:uuid], session_id: data[:session_id],
|
|
113
|
-
attempt: data[:attempt], max_retries: data[:maxRetries] || data[:max_retries],
|
|
114
|
-
retry_delay_ms: data[:retryDelayMs] || data[:retry_delay_ms],
|
|
115
|
-
error_status: data[:errorStatus] || data[:error_status],
|
|
116
|
-
error: data[:error]
|
|
117
|
-
)
|
|
118
|
-
when 'local_command_output'
|
|
119
|
-
LocalCommandOutputMessage.new(
|
|
120
|
-
subtype: data[:subtype], data: data,
|
|
121
|
-
uuid: data[:uuid], session_id: data[:session_id],
|
|
122
|
-
content: data[:content]
|
|
123
|
-
)
|
|
124
|
-
when 'hook_started'
|
|
125
|
-
HookStartedMessage.new(
|
|
126
|
-
subtype: data[:subtype], data: data,
|
|
127
|
-
uuid: data[:uuid], session_id: data[:session_id],
|
|
128
|
-
hook_id: data[:hookId] || data[:hook_id],
|
|
129
|
-
hook_name: data[:hookName] || data[:hook_name],
|
|
130
|
-
hook_event: data[:hookEvent] || data[:hook_event]
|
|
131
|
-
)
|
|
132
|
-
when 'hook_progress'
|
|
133
|
-
HookProgressMessage.new(
|
|
134
|
-
subtype: data[:subtype], data: data,
|
|
135
|
-
uuid: data[:uuid], session_id: data[:session_id],
|
|
136
|
-
hook_id: data[:hookId] || data[:hook_id],
|
|
137
|
-
hook_name: data[:hookName] || data[:hook_name],
|
|
138
|
-
hook_event: data[:hookEvent] || data[:hook_event],
|
|
139
|
-
stdout: data[:stdout], stderr: data[:stderr], output: data[:output]
|
|
140
|
-
)
|
|
141
|
-
when 'hook_response'
|
|
142
|
-
HookResponseMessage.new(
|
|
143
|
-
subtype: data[:subtype], data: data,
|
|
144
|
-
uuid: data[:uuid], session_id: data[:session_id],
|
|
145
|
-
hook_id: data[:hookId] || data[:hook_id],
|
|
146
|
-
hook_name: data[:hookName] || data[:hook_name],
|
|
147
|
-
hook_event: data[:hookEvent] || data[:hook_event],
|
|
148
|
-
output: data[:output], stdout: data[:stdout], stderr: data[:stderr],
|
|
149
|
-
exit_code: data[:exitCode] || data[:exit_code],
|
|
150
|
-
outcome: data[:outcome]
|
|
151
|
-
)
|
|
152
|
-
when 'session_state_changed'
|
|
153
|
-
SessionStateChangedMessage.new(
|
|
154
|
-
subtype: data[:subtype], data: data,
|
|
155
|
-
uuid: data[:uuid], session_id: data[:session_id],
|
|
156
|
-
state: data[:state]
|
|
157
|
-
)
|
|
158
|
-
when 'files_persisted'
|
|
159
|
-
FilesPersistedMessage.new(
|
|
160
|
-
subtype: data[:subtype], data: data,
|
|
161
|
-
uuid: data[:uuid], session_id: data[:session_id],
|
|
162
|
-
files: data[:files], failed: data[:failed],
|
|
163
|
-
processed_at: data[:processedAt] || data[:processed_at]
|
|
164
|
-
)
|
|
165
|
-
when 'elicitation_complete'
|
|
166
|
-
ElicitationCompleteMessage.new(
|
|
167
|
-
subtype: data[:subtype], data: data,
|
|
168
|
-
uuid: data[:uuid], session_id: data[:session_id],
|
|
169
|
-
mcp_server_name: data[:mcpServerName] || data[:mcp_server_name],
|
|
170
|
-
elicitation_id: data[:elicitationId] || data[:elicitation_id]
|
|
171
|
-
)
|
|
172
|
-
when 'task_started'
|
|
173
|
-
TaskStartedMessage.new(
|
|
174
|
-
subtype: data[:subtype], data: data,
|
|
175
|
-
task_id: data[:task_id], description: data[:description],
|
|
176
|
-
uuid: data[:uuid], session_id: data[:session_id],
|
|
177
|
-
tool_use_id: data[:tool_use_id], task_type: data[:task_type],
|
|
178
|
-
workflow_name: data[:workflowName] || data[:workflow_name],
|
|
179
|
-
prompt: data[:prompt]
|
|
180
|
-
)
|
|
181
|
-
when 'task_progress'
|
|
182
|
-
TaskProgressMessage.new(
|
|
183
|
-
subtype: data[:subtype], data: data,
|
|
184
|
-
task_id: data[:task_id], description: data[:description],
|
|
185
|
-
usage: data[:usage], uuid: data[:uuid], session_id: data[:session_id],
|
|
186
|
-
tool_use_id: data[:tool_use_id], last_tool_name: data[:last_tool_name],
|
|
187
|
-
summary: data[:summary]
|
|
188
|
-
)
|
|
189
|
-
when 'task_notification'
|
|
190
|
-
TaskNotificationMessage.new(
|
|
191
|
-
subtype: data[:subtype], data: data,
|
|
192
|
-
task_id: data[:task_id], status: data[:status],
|
|
193
|
-
output_file: data[:output_file], summary: data[:summary],
|
|
194
|
-
uuid: data[:uuid], session_id: data[:session_id],
|
|
195
|
-
tool_use_id: data[:tool_use_id], usage: data[:usage]
|
|
196
|
-
)
|
|
197
|
-
else
|
|
198
|
-
SystemMessage.new(subtype: data[:subtype], data: data)
|
|
199
|
-
end
|
|
102
|
+
klass = SYSTEM_MESSAGE_CLASSES[data[:subtype]] || SystemMessage
|
|
103
|
+
klass.new(data)
|
|
200
104
|
end
|
|
201
105
|
|
|
202
106
|
def self.parse_result_message(data)
|
|
203
|
-
ResultMessage.new(
|
|
204
|
-
subtype: data[:subtype],
|
|
205
|
-
duration_ms: data[:duration_ms],
|
|
206
|
-
duration_api_ms: data[:duration_api_ms],
|
|
207
|
-
is_error: data[:is_error],
|
|
208
|
-
num_turns: data[:num_turns],
|
|
209
|
-
session_id: data[:session_id],
|
|
210
|
-
stop_reason: data[:stop_reason],
|
|
211
|
-
total_cost_usd: data[:total_cost_usd],
|
|
212
|
-
usage: data[:usage],
|
|
213
|
-
result: data[:result],
|
|
214
|
-
structured_output: data[:structured_output],
|
|
215
|
-
model_usage: data[:modelUsage] || data[:model_usage],
|
|
216
|
-
permission_denials: data[:permission_denials],
|
|
217
|
-
errors: data[:errors],
|
|
218
|
-
uuid: data[:uuid],
|
|
219
|
-
fast_mode_state: data[:fastModeState] || data[:fast_mode_state]
|
|
220
|
-
)
|
|
107
|
+
ResultMessage.new(data)
|
|
221
108
|
end
|
|
222
109
|
|
|
223
110
|
def self.parse_stream_event(data)
|
|
224
|
-
StreamEvent.new(
|
|
225
|
-
uuid: data[:uuid],
|
|
226
|
-
session_id: data[:session_id],
|
|
227
|
-
event: data[:event],
|
|
228
|
-
parent_tool_use_id: data[:parent_tool_use_id]
|
|
229
|
-
)
|
|
111
|
+
StreamEvent.new(data)
|
|
230
112
|
end
|
|
231
113
|
|
|
232
114
|
def self.parse_rate_limit_event(data)
|
|
233
|
-
|
|
234
|
-
rate_limit_info = RateLimitInfo.new(
|
|
235
|
-
status: info[:status],
|
|
236
|
-
resets_at: info[:resetsAt],
|
|
237
|
-
rate_limit_type: info[:rateLimitType],
|
|
238
|
-
utilization: info[:utilization],
|
|
239
|
-
overage_status: info[:overageStatus],
|
|
240
|
-
overage_resets_at: info[:overageResetsAt],
|
|
241
|
-
overage_disabled_reason: info[:overageDisabledReason],
|
|
242
|
-
raw: info
|
|
243
|
-
)
|
|
244
|
-
RateLimitEvent.new(
|
|
245
|
-
rate_limit_info: rate_limit_info,
|
|
246
|
-
uuid: data[:uuid],
|
|
247
|
-
session_id: data[:session_id],
|
|
248
|
-
raw_data: data
|
|
249
|
-
)
|
|
115
|
+
RateLimitEvent.new(data.merge(raw_data: data))
|
|
250
116
|
end
|
|
251
117
|
|
|
252
118
|
def self.parse_tool_progress_message(data)
|
|
253
|
-
ToolProgressMessage.new(
|
|
254
|
-
uuid: data[:uuid],
|
|
255
|
-
session_id: data[:session_id],
|
|
256
|
-
tool_use_id: data[:toolUseId] || data[:tool_use_id],
|
|
257
|
-
tool_name: data[:toolName] || data[:tool_name],
|
|
258
|
-
parent_tool_use_id: data[:parentToolUseId] || data[:parent_tool_use_id],
|
|
259
|
-
elapsed_time_seconds: data[:elapsedTimeSeconds] || data[:elapsed_time_seconds],
|
|
260
|
-
task_id: data[:taskId] || data[:task_id]
|
|
261
|
-
)
|
|
119
|
+
ToolProgressMessage.new(data)
|
|
262
120
|
end
|
|
263
121
|
|
|
264
122
|
def self.parse_auth_status_message(data)
|
|
265
|
-
AuthStatusMessage.new(
|
|
266
|
-
uuid: data[:uuid],
|
|
267
|
-
session_id: data[:session_id],
|
|
268
|
-
is_authenticating: data[:isAuthenticating] || data[:is_authenticating],
|
|
269
|
-
output: data[:output],
|
|
270
|
-
error: data[:error]
|
|
271
|
-
)
|
|
123
|
+
AuthStatusMessage.new(data)
|
|
272
124
|
end
|
|
273
125
|
|
|
274
126
|
def self.parse_tool_use_summary_message(data)
|
|
275
|
-
ToolUseSummaryMessage.new(
|
|
276
|
-
uuid: data[:uuid],
|
|
277
|
-
session_id: data[:session_id],
|
|
278
|
-
summary: data[:summary],
|
|
279
|
-
preceding_tool_use_ids: data[:precedingToolUseIds] || data[:preceding_tool_use_ids]
|
|
280
|
-
)
|
|
127
|
+
ToolUseSummaryMessage.new(data)
|
|
281
128
|
end
|
|
282
129
|
|
|
283
130
|
def self.parse_prompt_suggestion_message(data)
|
|
284
|
-
PromptSuggestionMessage.new(
|
|
285
|
-
uuid: data[:uuid],
|
|
286
|
-
session_id: data[:session_id],
|
|
287
|
-
suggestion: data[:suggestion]
|
|
288
|
-
)
|
|
131
|
+
PromptSuggestionMessage.new(data)
|
|
289
132
|
end
|
|
290
133
|
|
|
291
134
|
# Accepts blocks with either symbol or string keys — live CLI messages
|