claude_agent 0.7.9 → 0.7.11

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 90d9094d4e4428fc7dfc1e452759403a92f2e4badf5d1ac5f2f90e950c511255
4
- data.tar.gz: fd2a8407c794aa672a4b03a774a6573dac3682bc09b8fe666170b90f5bd9f79a
3
+ metadata.gz: 965fad355090a487a22e76e097ed84aa7426fe4db396a28e0165e6ceaa09b1e2
4
+ data.tar.gz: fe03eeffb6dfa608c5a40bc55d1b04b31f30bd0ec5d8a50322b2dc7bf127bdea
5
5
  SHA512:
6
- metadata.gz: ce7d705ebe01a38ad1ac86a8caeaabd700831e200e73f134c9adef507b6f7b695effece63ae902849ee408714c3ae576930012dbbefe2b05da403d0de8549317
7
- data.tar.gz: 7f06c5b0b5ed5ad798442672ad8ca969a0fdefc414a4c273e86911df0e171d24d5a378b9a88117bd3c60092a6affb5219d06cc58dd0107245643b571e2236440
6
+ metadata.gz: b7353c7235415c842e29ba73c315f10ba52d6731324d0e326ecfe56f321272246a6877f07fd2e451007b3ac9252c007f312da15650c77f8ef4c99d06a1e907d1
7
+ data.tar.gz: ece71bf88dddd47d40da3dd13e660c8e39eba12484daaf1fa0b87731ff130b8b6ddfcb215e352d2f34c587eb55998a9d1669bbe88363a2587e342190c5b80c0e
data/CHANGELOG.md CHANGED
@@ -7,6 +7,47 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.7.11] - 2026-02-27
11
+
12
+ ### Added
13
+ - `LiveToolActivity` — mutable, real-time tool status tracker (`:running` → `:done`/`:error`) with elapsed time and delegation to `ToolUseBlock`
14
+ - `ToolActivityTracker` — `Enumerable` collection that auto-wires to `EventHandler` or `Client` via `.attach`, with `on_start`/`on_complete`/`on_progress` callbacks, `on_change` catch-all, `running`/`done`/`errored` filtered views, and `reset!`
15
+ - `Conversation` accepts `track_tools: true` to opt into live tool tracking via `tool_tracker` accessor
16
+ - Convention-based event dispatch — every message type now auto-fires a dedicated event based on `message.type` (e.g. `:assistant`, `:stream_event`, `:status`, `:tool_progress`)
17
+ - `EventHandler::EVENTS`, `TYPE_EVENTS`, `DECOMPOSED_EVENTS`, `META_EVENTS` constants enumerating all known events
18
+ - `on_assistant`, `on_user`, `on_stream_event`, `on_status`, `on_tool_progress`, `on_hook_response`, `on_auth_status`, `on_task_notification`, `on_hook_started`, `on_hook_progress`, `on_tool_use_summary`, `on_task_started`, `on_task_progress`, `on_rate_limit_event`, `on_prompt_suggestion`, `on_files_persisted` convenience methods on `EventHandler` and `Client`
19
+ - `Conversation` now accepts any `on_*` keyword argument as a callback (pattern-based, no longer limited to a hardcoded list)
20
+ - `GenericMessage` fires its dynamic type symbol, so `on(:fancy_new_type)` works for future/unknown CLI message types
21
+ - `TaskNotificationMessage#tool_use_id` and `#usage` fields with new `TaskUsage` type (TypeScript SDK parity)
22
+ - `ToolProgressMessage#task_id` field (TypeScript SDK parity)
23
+ - `StatusMessage#permission_mode` field (TypeScript SDK parity)
24
+ - `ModelInfo#supports_effort`, `#supported_effort_levels`, `#supports_adaptive_thinking` fields (TypeScript SDK parity)
25
+ - `McpServerStatus#error`, `#config`, `#scope`, `#tools` fields (TypeScript SDK parity)
26
+ - `StopInput#last_assistant_message` hook field (TypeScript SDK parity)
27
+ - `SubagentStopInput#agent_type` and `#last_assistant_message` hook fields (TypeScript SDK parity)
28
+ - `'oauth'` source in `API_KEY_SOURCES` constant (TypeScript SDK parity)
29
+ - RBS signatures for all new fields
30
+
31
+ ### Changed
32
+ - `EventHandler#handle` now fires three layers per message: `:message` (catch-all) → `message.type` (type-based) → decomposed (`:text`, `:thinking`, `:tool_use`, `:tool_result`)
33
+ - `Conversation::CONVERSATION_KEYS` now contains only infrastructure keys (`client`, `options`, `on_permission`); callback detection is pattern-based via `on_*` prefix
34
+
35
+ ## [0.7.10] - 2026-02-26
36
+
37
+ ### Added
38
+ - `Session.find(id, dir:)` — find a past session by UUID, returns `Session` or `nil`
39
+ - `Session.all` — list all past sessions as `Session` objects
40
+ - `Session.where(dir:, limit:)` — query sessions with optional directory and limit filters
41
+ - `Session#messages` — returns a chainable, `Enumerable` `SessionMessageRelation` for reading transcript messages
42
+ - `SessionMessageRelation#where(limit:, offset:)` — paginate messages with immutable chaining
43
+ - `ClaudeAgent.get_session_messages(session_id, dir:, limit:, offset:)` — read session transcripts from disk (TypeScript SDK v0.2.59 parity)
44
+ - `SessionMessage` type — message from a session transcript with `type`, `uuid`, `session_id`, `message`
45
+ - `SessionPaths` module — shared path infrastructure for session discovery (extracted from `ListSessions`)
46
+
47
+ ### Changed
48
+ - Renamed `Session` (V2 multi-turn API) to `V2Session` to free the `Session` name for the finder API
49
+ - `unstable_v2_create_session`, `unstable_v2_resume_session`, and `unstable_v2_prompt` now return `V2Session`
50
+
10
51
  ## [0.7.9] - 2026-02-25
11
52
 
12
53
  ### Added
data/README.md CHANGED
@@ -93,26 +93,6 @@ ClaudeAgent::Client.open do |client|
93
93
  end
94
94
  ```
95
95
 
96
- ### Run Setup Hooks
97
-
98
- Run Setup hooks without starting a conversation (useful for CI/CD pipelines):
99
-
100
- ```ruby
101
- require "claude_agent"
102
-
103
- # Run init Setup hooks (default)
104
- messages = ClaudeAgent.run_setup
105
- result = messages.last
106
- puts "Setup completed" if result.success?
107
-
108
- # Run init Setup hooks with custom options
109
- options = ClaudeAgent::Options.new(cwd: "/my/project")
110
- ClaudeAgent.run_setup(trigger: :init, options: options)
111
-
112
- # Run maintenance Setup hooks
113
- ClaudeAgent.run_setup(trigger: :maintenance)
114
- ```
115
-
116
96
  ## Conversation API
117
97
 
118
98
  The `Conversation` class manages the full lifecycle: auto-connects on first message, tracks multi-turn history, accumulates usage, and builds a unified tool activity timeline.
@@ -162,17 +142,20 @@ conversation.close
162
142
 
163
143
  ### Callbacks
164
144
 
165
- Register callbacks for real-time event handling:
145
+ Register callbacks for real-time event handling. Any `on_*` keyword is accepted — see [Event Handlers](#event-handlers) for the full list.
166
146
 
167
147
  ```ruby
168
148
  conversation = ClaudeAgent.conversation(
169
- on_text: ->(text) { print text },
170
- on_stream: ->(text) { print text }, # Alias for on_text
171
- on_thinking: ->(thought) { puts "Thinking: #{thought}" },
172
- on_tool_use: ->(tool) { puts "Tool: #{tool.display_label}" },
173
- on_tool_result: ->(result) { puts "Result: #{result.content&.slice(0, 80)}" },
174
- on_result: ->(result) { puts "Done! Cost: $#{result.total_cost_usd}" },
175
- on_message: ->(msg) { log(msg) } # Catch-all
149
+ on_text: ->(text) { print text },
150
+ on_stream: ->(text) { print text }, # Alias for on_text
151
+ on_thinking: ->(thought) { puts "Thinking: #{thought}" },
152
+ on_tool_use: ->(tool) { puts "Tool: #{tool.display_label}" },
153
+ on_tool_result: ->(result) { puts "Result: #{result.content&.slice(0, 80)}" },
154
+ on_result: ->(result) { puts "Done! Cost: $#{result.total_cost_usd}" },
155
+ on_message: ->(msg) { log(msg) }, # Catch-all
156
+ on_stream_event: ->(evt) { handle_stream(evt) }, # Type-based
157
+ on_status: ->(status) { show_status(status) },
158
+ on_tool_progress: ->(prog) { update_spinner(prog) }
176
159
  )
177
160
  ```
178
161
 
@@ -192,12 +175,49 @@ ClaudeAgent::Conversation.open(permission_mode: "acceptEdits") do |c|
192
175
  end
193
176
  ```
194
177
 
178
+ ### Live Tool Tracking
179
+
180
+ Track tool status in real time for live UIs. Unlike `tool_activity` (built after a turn), `LiveToolActivity` updates as tools run:
181
+
182
+ ```ruby
183
+ # Conversation level — opt in with track_tools: true
184
+ ClaudeAgent::Conversation.open(
185
+ permission_mode: "acceptEdits",
186
+ track_tools: true
187
+ ) do |c|
188
+ c.tool_tracker.on_start { |entry| puts "▸ #{entry.display_label}" }
189
+ c.tool_tracker.on_progress { |entry| puts " #{entry.elapsed&.round(1)}s..." }
190
+ c.tool_tracker.on_complete { |entry| puts "✓ #{entry.display_label}" }
191
+
192
+ c.say("Fix the bug in auth.rb")
193
+ # Tracker resets between turns automatically
194
+ end
195
+
196
+ # Client level — attach directly
197
+ tracker = ClaudeAgent::ToolActivityTracker.attach(client)
198
+ tracker.on_start { |entry| show_spinner(entry) }
199
+ tracker.on_complete { |entry| hide_spinner(entry) }
200
+
201
+ # Standalone — attach to any EventHandler
202
+ tracker = ClaudeAgent::ToolActivityTracker.attach(event_handler)
203
+
204
+ # Catch-all callback (receives event symbol + entry)
205
+ tracker.on_change { |event, entry| log(event, entry.id) }
206
+
207
+ # Query running/completed tools at any point
208
+ tracker.running # => [LiveToolActivity, ...]
209
+ tracker.done # => [LiveToolActivity, ...]
210
+ tracker.errored # => [LiveToolActivity, ...]
211
+ tracker["toolu_01ABC"] # => LiveToolActivity (O(1) lookup by tool use ID)
212
+ ```
213
+
195
214
  ### Conversation Accessors
196
215
 
197
216
  ```ruby
198
217
  conversation.turns # Array of TurnResult objects
199
218
  conversation.messages # All messages across all turns
200
219
  conversation.tool_activity # Array of ToolActivity objects
220
+ conversation.tool_tracker # ToolActivityTracker (when track_tools: true)
201
221
  conversation.total_cost # Total cost in USD
202
222
  conversation.session_id # Session ID from most recent turn
203
223
  conversation.usage # CumulativeUsage stats
@@ -390,15 +410,27 @@ turn.content_blocks # All content blocks across assistant messages
390
410
 
391
411
  Register typed callbacks instead of writing `case` statements. Works with `Client`, `Conversation`, or standalone.
392
412
 
413
+ Three event layers fire for every message:
414
+
415
+ 1. **Catch-all** — `:message` fires for every message
416
+ 2. **Type-based** — `message.type` fires (e.g. `:assistant`, `:stream_event`, `:status`, `:tool_progress`)
417
+ 3. **Decomposed** — convenience events for rich content (`:text`, `:thinking`, `:tool_use`, `:tool_result`)
418
+
393
419
  ### Via Client
394
420
 
395
421
  ```ruby
396
422
  ClaudeAgent::Client.open do |client|
423
+ # Decomposed events (extracted content)
397
424
  client.on_text { |text| print text }
398
425
  client.on_tool_use { |tool| puts "\nUsing: #{tool.display_label}" }
399
426
  client.on_tool_result { |result, tool_use| puts "Done: #{tool_use&.name}" }
400
427
  client.on_result { |result| puts "\nCost: $#{result.total_cost_usd}" }
401
428
 
429
+ # Type-based events (full message object)
430
+ client.on_stream_event { |evt| handle_stream(evt) }
431
+ client.on_status { |status| show_status(status) }
432
+ client.on_tool_progress { |prog| update_spinner(prog) }
433
+
402
434
  client.send_and_receive("Fix the bug in auth.rb")
403
435
  end
404
436
  ```
@@ -424,6 +456,10 @@ handler.on(:tool_result) { |result, tool_use| puts "Result for #{tool_use&.name}
424
456
  handler.on(:result) { |result| puts "Cost: $#{result.total_cost_usd}" }
425
457
  handler.on(:message) { |msg| log(msg) } # Catch-all
426
458
 
459
+ # Type-based events work with on() too
460
+ handler.on(:stream_event) { |evt| handle_stream(evt) }
461
+ handler.on(:status) { |status| show_status(status) }
462
+
427
463
  # Dispatch manually
428
464
  client.receive_response.each { |msg| handler.handle(msg) }
429
465
  handler.reset! # Clear turn state between turns
@@ -1133,6 +1169,11 @@ client.on_tool_result { |result, tool_use| puts "Done: #{tool_use&.name}" }
1133
1169
  client.on_thinking { |thought| puts thought }
1134
1170
  client.on_result { |result| puts "Cost: $#{result.total_cost_usd}" }
1135
1171
  client.on_message { |msg| log(msg) }
1172
+ # Type-based events for all message types
1173
+ client.on_assistant { |msg| handle_assistant(msg) }
1174
+ client.on_stream_event { |evt| handle_stream(evt) }
1175
+ client.on_status { |status| show_status(status) }
1176
+ client.on_tool_progress { |prog| update_spinner(prog) }
1136
1177
 
1137
1178
  # Control methods
1138
1179
  client.interrupt # Cancel current operation
@@ -1180,14 +1221,20 @@ client.disconnect
1180
1221
 
1181
1222
  ## Session Discovery
1182
1223
 
1183
- List past Claude Code sessions from disk without spawning a CLI subprocess:
1224
+ Find and inspect past Claude Code sessions from disk without spawning a CLI subprocess.
1225
+
1226
+ ### Session.find / Session.all
1184
1227
 
1185
1228
  ```ruby
1186
- # All sessions (most recent first)
1187
- sessions = ClaudeAgent.list_sessions
1229
+ # Find a specific session by ID
1230
+ session = ClaudeAgent::Session.find("abc-123-def")
1231
+ session = ClaudeAgent::Session.find("abc-123-def", dir: "/my/project")
1188
1232
 
1189
- # Scoped to a project directory (includes git worktree siblings)
1190
- sessions = ClaudeAgent.list_sessions(dir: "/path/to/project", limit: 10)
1233
+ # List all sessions (most recent first)
1234
+ sessions = ClaudeAgent::Session.all
1235
+
1236
+ # Filter by directory, limit results
1237
+ sessions = ClaudeAgent::Session.where(dir: "/path/to/project", limit: 10)
1191
1238
 
1192
1239
  sessions.each do |s|
1193
1240
  puts "#{s.summary} (#{s.git_branch || 'no branch'})"
@@ -1197,7 +1244,27 @@ sessions.each do |s|
1197
1244
  end
1198
1245
  ```
1199
1246
 
1200
- Each session is a `SessionInfo` with these fields:
1247
+ ### Reading Messages
1248
+
1249
+ `Session#messages` returns a chainable, `Enumerable` relation:
1250
+
1251
+ ```ruby
1252
+ session = ClaudeAgent::Session.find("abc-123-def")
1253
+
1254
+ # All messages
1255
+ session.messages.each { |m| puts "#{m.type}: #{m.uuid}" }
1256
+
1257
+ # Paginated
1258
+ session.messages.where(limit: 10).map(&:uuid)
1259
+ session.messages.where(offset: 5, limit: 10).to_a
1260
+
1261
+ # Enumerable methods work
1262
+ session.messages.first
1263
+ session.messages.count
1264
+ session.messages.select { |m| m.type == "assistant" }
1265
+ ```
1266
+
1267
+ ### Session Fields
1201
1268
 
1202
1269
  | Field | Type | Description |
1203
1270
  |------------------|-----------------|--------------------------------------------------|
@@ -1210,11 +1277,24 @@ Each session is a `SessionInfo` with these fields:
1210
1277
  | `git_branch` | `String\|nil` | Git branch the session was on |
1211
1278
  | `cwd` | `String\|nil` | Working directory of the session |
1212
1279
 
1280
+ ### Functional API
1281
+
1282
+ The lower-level functional API is also available:
1283
+
1284
+ ```ruby
1285
+ # List sessions (returns SessionInfo objects)
1286
+ infos = ClaudeAgent.list_sessions(dir: "/path/to/project", limit: 10)
1287
+
1288
+ # Read messages directly
1289
+ messages = ClaudeAgent.get_session_messages("abc-123-def", limit: 10, offset: 5)
1290
+ ```
1291
+
1292
+ ### Resume a Past Session
1293
+
1213
1294
  Use with `Conversation.resume` to pick up where you left off:
1214
1295
 
1215
1296
  ```ruby
1216
- sessions = ClaudeAgent.list_sessions(dir: Dir.pwd, limit: 5)
1217
- session = sessions.first
1297
+ session = ClaudeAgent::Session.where(dir: Dir.pwd, limit: 5).first
1218
1298
 
1219
1299
  conversation = ClaudeAgent.resume_conversation(session.session_id)
1220
1300
  turn = conversation.say("Continue where we left off")
@@ -1307,23 +1387,28 @@ session = ClaudeAgent.unstable_v2_create_session(options)
1307
1387
 
1308
1388
  ### Return Types
1309
1389
 
1310
- | Type | Purpose |
1311
- |-----------------------|----------------------------------------------------------------------------------|
1312
- | `TurnResult` | Complete agent turn with text, tools, usage, and status accessors |
1313
- | `ToolActivity` | Tool use/result pair with turn index and timing |
1314
- | `CumulativeUsage` | Running totals of tokens, cost, turns, and duration |
1315
- | `PermissionRequest` | Deferred permission promise resolvable from any thread |
1316
- | `PermissionQueue` | Thread-safe queue of pending permission requests |
1317
- | `EventHandler` | Typed event callback registry |
1318
- | `SlashCommand` | Available slash commands (name, description, argument_hint) |
1319
- | `ModelInfo` | Available models (value, display_name, description) |
1320
- | `McpServerStatus` | MCP server status (name, status, server_info) |
1321
- | `AccountInfo` | Account information (email, organization, subscription_type) |
1322
- | `ModelUsage` | Per-model usage stats (input_tokens, output_tokens, cost_usd) |
1323
- | `McpSetServersResult` | Result of set_mcp_servers (added, removed, errors) |
1324
- | `RewindFilesResult` | Result of rewind_files (can_rewind, error, files_changed, insertions, deletions) |
1325
- | `SessionInfo` | Session metadata from `list_sessions` (session_id, summary, git_branch, cwd) |
1326
- | `SDKPermissionDenial` | Permission denial info (tool_name, tool_use_id, tool_input) |
1390
+ | Type | Purpose |
1391
+ |--------------------------|----------------------------------------------------------------------------------|
1392
+ | `TurnResult` | Complete agent turn with text, tools, usage, and status accessors |
1393
+ | `ToolActivity` | Tool use/result pair with turn index and timing (immutable, post-turn) |
1394
+ | `LiveToolActivity` | Mutable real-time tool status (running/done/error) with elapsed time |
1395
+ | `ToolActivityTracker` | Enumerable collection of `LiveToolActivity` with auto-wiring and `on_change` |
1396
+ | `CumulativeUsage` | Running totals of tokens, cost, turns, and duration |
1397
+ | `PermissionRequest` | Deferred permission promise resolvable from any thread |
1398
+ | `PermissionQueue` | Thread-safe queue of pending permission requests |
1399
+ | `EventHandler` | Typed event callback registry |
1400
+ | `SlashCommand` | Available slash commands (name, description, argument_hint) |
1401
+ | `ModelInfo` | Available models (value, display_name, description) |
1402
+ | `McpServerStatus` | MCP server status (name, status, server_info) |
1403
+ | `AccountInfo` | Account information (email, organization, subscription_type) |
1404
+ | `ModelUsage` | Per-model usage stats (input_tokens, output_tokens, cost_usd) |
1405
+ | `McpSetServersResult` | Result of set_mcp_servers (added, removed, errors) |
1406
+ | `RewindFilesResult` | Result of rewind_files (can_rewind, error, files_changed, insertions, deletions) |
1407
+ | `Session` | Session finder with `.find`, `.all`, `#messages` (wraps SessionInfo) |
1408
+ | `SessionMessageRelation` | Chainable, Enumerable query object for session messages |
1409
+ | `SessionInfo` | Session metadata from `list_sessions` (session_id, summary, git_branch, cwd) |
1410
+ | `SessionMessage` | Message from a session transcript (type, uuid, session_id, message) |
1411
+ | `SDKPermissionDenial` | Permission denial info (tool_name, tool_use_id, tool_input) |
1327
1412
 
1328
1413
  ## Logging
1329
1414
 
data/SPEC.md CHANGED
@@ -3,11 +3,11 @@
3
3
  This document provides a comprehensive specification of the Claude Agent SDK, comparing feature parity across the official TypeScript and Python SDKs with this Ruby implementation.
4
4
 
5
5
  **Reference Versions:**
6
- - TypeScript SDK: v0.2.56 (npm package)
7
- - Python SDK: v0.1.43 from GitHub (commit 9d758dd)
6
+ - TypeScript SDK: v0.2.62 (npm package)
7
+ - Python SDK: v0.1.44 from GitHub (commit 7297bdc)
8
8
  - Ruby SDK: This repository
9
9
 
10
- **Last Updated:** 2026-02-25
10
+ **Last Updated:** 2026-02-27
11
11
 
12
12
  ---
13
13
 
@@ -68,7 +68,6 @@ Configuration options for SDK queries and clients.
68
68
  | `additionalDirectories` | ✅ | ✅ | ✅ | Extra allowed directories |
69
69
  | `env` | ✅ | ✅ | ✅ | Environment variables |
70
70
  | `sandbox` | ✅ | ✅ | ✅ | Sandbox settings |
71
- | `settings` | ✅ | ✅ | ✅ | Settings file path or JSON string (e.g., plansDirectory) |
72
71
  | `settingSources` | ✅ | ✅ | ✅ | Which settings to load |
73
72
  | `plugins` | ✅ | ✅ | ✅ | Plugin configurations |
74
73
  | `betas` | ✅ | ✅ | ✅ | Beta features (e.g., context-1m-2025-08-07) |
@@ -79,10 +78,6 @@ Configuration options for SDK queries and clients.
79
78
  | `executable` | ✅ | N/A | N/A | JS runtime (node/bun/deno) - JS-specific |
80
79
  | `executableArgs` | ✅ | N/A | N/A | JS runtime args - JS-specific |
81
80
  | `extraArgs` | ✅ | ✅ | ✅ | Extra CLI arguments |
82
- | `user` | ✅ | ✅ | ✅ | User identifier (V2 Session API) |
83
- | `init` | ✅ | ❌ | ✅ | Run Setup hooks (init trigger), then continue (hidden CLI) |
84
- | `initOnly` | ✅ | ❌ | ✅ | Run Setup hooks (init trigger), then exit (hidden CLI) |
85
- | `maintenance` | ✅ | ❌ | ✅ | Run Setup hooks (maintenance trigger), continue (hidden CLI) |
86
81
  | `promptSuggestions` | ✅ | ❌ | ✅ | Enable prompt suggestion after each turn (v0.2.47) |
87
82
  | `debug` | ✅ | ❌ | ✅ | Enable verbose debug logging |
88
83
  | `debugFile` | ✅ | ❌ | ✅ | Write debug logs to specific file path |
@@ -148,6 +143,34 @@ Messages exchanged between SDK and CLI.
148
143
  | `error_max_budget_usd` | ✅ | ✅ | ✅ | Budget exceeded |
149
144
  | `error_max_structured_output_retries` | ✅ | ❌ | ✅ | Structured output retries exceeded |
150
145
 
146
+ #### TaskNotificationMessage
147
+
148
+ | Field | TypeScript | Python | Ruby | Notes |
149
+ |---------------|:----------:|:------:|:----:|-----------------------------|
150
+ | `task_id` | ✅ | ❌ | ✅ | Task identifier |
151
+ | `tool_use_id` | ✅ | ❌ | ✅ | Correlating tool call ID |
152
+ | `status` | ✅ | ❌ | ✅ | completed/failed/stopped |
153
+ | `output_file` | ✅ | ❌ | ✅ | Path to task output |
154
+ | `summary` | ✅ | ❌ | ✅ | Task summary |
155
+ | `usage` | ✅ | ❌ | ✅ | Tokens/tool counts/duration |
156
+
157
+ #### ToolProgressMessage
158
+
159
+ | Field | TypeScript | Python | Ruby | Notes |
160
+ |------------------------|:----------:|:------:|:----:|-------------------------|
161
+ | `tool_use_id` | ✅ | ❌ | ✅ | Tool use ID |
162
+ | `tool_name` | ✅ | ❌ | ✅ | Tool name |
163
+ | `parent_tool_use_id` | ✅ | ❌ | ✅ | Parent tool use ID |
164
+ | `elapsed_time_seconds` | ✅ | ❌ | ✅ | Elapsed time |
165
+ | `task_id` | ✅ | ❌ | ✅ | Associated task ID |
166
+
167
+ #### StatusMessage
168
+
169
+ | Field | TypeScript | Python | Ruby | Notes |
170
+ |------------------|:----------:|:------:|:----:|-------------------------|
171
+ | `status` | ✅ | ❌ | ✅ | Current status |
172
+ | `permissionMode` | ✅ | ❌ | ✅ | Current permission mode |
173
+
151
174
  #### HookResponseMessage Fields
152
175
 
153
176
  | Field | TypeScript | Python | Ruby | Notes |
@@ -252,6 +275,29 @@ Bidirectional control protocol for SDK-CLI communication.
252
275
  | `McpSetServersResult` | ✅ | ❌ | ✅ | Set servers result |
253
276
  | `RewindFilesResult` | ✅ | ✅ | ✅ | Rewind result |
254
277
 
278
+ #### ModelInfo Fields
279
+
280
+ | Field | TypeScript | Python | Ruby | Notes |
281
+ |----------------------------|:----------:|:------:|:----:|---------------------------------|
282
+ | `value` | ✅ | ❌ | ✅ | Model identifier |
283
+ | `displayName` | ✅ | ❌ | ✅ | Human-readable name |
284
+ | `description` | ✅ | ❌ | ✅ | Model description |
285
+ | `supportsEffort` | ✅ | ❌ | ✅ | Whether model supports effort |
286
+ | `supportedEffortLevels` | ✅ | ❌ | ✅ | Available effort levels |
287
+ | `supportsAdaptiveThinking` | ✅ | ❌ | ✅ | Whether adaptive thinking works |
288
+
289
+ #### McpServerStatus Fields
290
+
291
+ | Field | TypeScript | Python | Ruby | Notes |
292
+ |--------------|:----------:|:------:|:----:|------------------------------------|
293
+ | `name` | ✅ | ✅ | ✅ | Server name |
294
+ | `status` | ✅ | ✅ | ✅ | Connection status |
295
+ | `serverInfo` | ✅ | ❌ | ✅ | Server name/version |
296
+ | `error` | ✅ | ❌ | ✅ | Error message (when failed) |
297
+ | `config` | ✅ | ❌ | ✅ | Server configuration |
298
+ | `scope` | ✅ | ❌ | ✅ | Config scope (project, user, etc.) |
299
+ | `tools` | ✅ | ❌ | ✅ | Tools with annotations |
300
+
255
301
  ---
256
302
 
257
303
  ## 5. Hooks
@@ -304,6 +350,23 @@ Event hooks for intercepting and modifying SDK behavior.
304
350
  | `WorktreeCreateHookInput` | ✅ | ❌ | ✅ |
305
351
  | `WorktreeRemoveHookInput` | ✅ | ❌ | ✅ |
306
352
 
353
+ #### StopHookInput Fields
354
+
355
+ | Field | TypeScript | Python | Ruby | Notes |
356
+ |--------------------------|:----------:|:------:|:----:|----------------------------------------|
357
+ | `stop_hook_active` | ✅ | ✅ | ✅ | Whether stop hook is active |
358
+ | `last_assistant_message` | ✅ | ❌ | ✅ | Last assistant message text (v0.2.51+) |
359
+
360
+ #### SubagentStopHookInput Fields
361
+
362
+ | Field | TypeScript | Python | Ruby | Notes |
363
+ |--------------------------|:----------:|:------:|:----:|----------------------------------------|
364
+ | `stop_hook_active` | ✅ | ✅ | ✅ | Whether stop hook is active |
365
+ | `agent_id` | ✅ | ✅ | ✅ | Subagent identifier |
366
+ | `agent_transcript_path` | ✅ | ✅ | ✅ | Path to agent transcript |
367
+ | `agent_type` | ✅ | ✅ | ✅ | Agent type |
368
+ | `last_assistant_message` | ✅ | ❌ | ✅ | Last assistant message text (v0.2.51+) |
369
+
307
370
  ### Hook Output Types
308
371
 
309
372
  | Output Field | TypeScript | Python | Ruby | Notes |
@@ -524,9 +587,35 @@ Session management and resumption.
524
587
 
525
588
  ### Session Discovery
526
589
 
527
- | Feature | TypeScript | Python | Ruby | Notes |
528
- |------------------|:----------:|:------:|:----:|--------------------------------------------|
529
- | `listSessions()` | ✅ | ❌ | ✅ | List past sessions with metadata (v0.2.53) |
590
+ | Feature | TypeScript | Python | Ruby | Notes |
591
+ |------------------------|:----------:|:------:|:----:|--------------------------------------------------|
592
+ | `listSessions()` | ✅ | ❌ | ✅ | List past sessions with metadata (v0.2.53) |
593
+ | `getSessionMessages()` | ✅ | ❌ | ✅ | Read session transcript messages (v0.2.59) |
594
+
595
+ #### ListSessionsOptions
596
+
597
+ | Field | TypeScript | Python | Ruby | Notes |
598
+ |---------|:----------:|:------:|:----:|-------------------------------------------|
599
+ | `dir` | ✅ | ❌ | ✅ | Project directory (includes worktrees) |
600
+ | `limit` | ✅ | ❌ | ✅ | Maximum number of sessions to return |
601
+
602
+ #### GetSessionMessagesOptions
603
+
604
+ | Field | TypeScript | Python | Ruby | Notes |
605
+ |----------|:----------:|:------:|:----:|----------------------------------------------|
606
+ | `dir` | ✅ | ❌ | ✅ | Project directory to find session in |
607
+ | `limit` | ✅ | ❌ | ✅ | Maximum number of messages to return |
608
+ | `offset` | ✅ | ❌ | ✅ | Number of messages to skip from the start |
609
+
610
+ #### SessionMessage Fields
611
+
612
+ | Field | TypeScript | Python | Ruby | Notes |
613
+ |----------------------|:----------:|:------:|:----:|----------------------------------|
614
+ | `type` | ✅ | ❌ | ✅ | 'user' or 'assistant' |
615
+ | `uuid` | ✅ | ❌ | ✅ | Message UUID |
616
+ | `session_id` | ✅ | ❌ | ✅ | Session ID |
617
+ | `message` | ✅ | ❌ | ✅ | Raw message content |
618
+ | `parent_tool_use_id` | ✅ | ❌ | ✅ | Parent tool use ID (always null) |
530
619
 
531
620
  #### SDKSessionInfo Fields
532
621
 
@@ -625,7 +714,7 @@ Error types and hierarchy.
625
714
  | `CLIConnectionError` | ❌ | ✅ | ✅ | Connection failed |
626
715
  | `ProcessError` | ❌ | ✅ | ✅ | CLI process failed |
627
716
  | `JSONDecodeError` | ❌ | ✅ | ✅ | JSON parsing failed |
628
- | `MessageParseError` | ❌ | | ✅ | Message parsing failed |
717
+ | `MessageParseError` | ❌ | | ✅ | Message parsing failed |
629
718
  | `TimeoutError` | ❌ | ❌ | ✅ | Control request timeout |
630
719
  | `ConfigurationError` | ❌ | ❌ | ✅ | Invalid configuration |
631
720
 
@@ -649,9 +738,10 @@ Public API surface for SDK clients.
649
738
 
650
739
  ### Standalone Functions
651
740
 
652
- | Feature | TypeScript | Python | Ruby | Notes |
653
- |------------------|:----------------:|:------:|:----:|--------------------------------------------|
654
- | `listSessions()` | `listSessions` | ❌ | ✅ | List past sessions with metadata (v0.2.53) |
741
+ | Feature | TypeScript | Python | Ruby | Notes |
742
+ |------------------------|:----------:|:------:|:----:|--------------------------------------------|
743
+ | `listSessions()` | | ❌ | ✅ | List past sessions with metadata (v0.2.53) |
744
+ | `getSessionMessages()` | ✅ | ❌ | ✅ | Read session transcript (v0.2.59) |
655
745
 
656
746
  ### Query Interface
657
747
 
@@ -720,32 +810,38 @@ Public API surface for SDK clients.
720
810
  - Source is bundled/minified, but `sdk.d.ts` provides complete type definitions
721
811
  - Includes unstable V2 session API
722
812
  - `executable`/`executableArgs` are JS-specific (`node`/`bun`/`deno`)
813
+ - Does NOT have `settings`, `user`, `init`/`initOnly`/`maintenance` as typed Options (use `extraArgs` or `settingSources`)
814
+ - `ApiKeySource` includes `'oauth'`
723
815
  - v0.2.45: Added `TaskStartedMessage`, `RateLimitEvent` message types
724
816
  - v0.2.47: Added `promptSuggestions` option and `PromptSuggestionMessage`
725
817
  - v0.2.49: Added `ConfigChange` hook event, `SandboxFilesystemConfig`, ModelInfo capability fields
726
818
  - v0.2.50: Added `WorktreeCreate`/`WorktreeRemove` hook events, `apply_flag_settings` control request
727
- - v0.2.51: Added `TaskProgressMessage` for real-time background agent progress reporting
819
+ - v0.2.51: Added `TaskProgressMessage`, `StopHookInput.last_assistant_message`, `SubagentStopHookInput.last_assistant_message`
728
820
  - v0.2.52: Added `mcp_authenticate`/`mcp_clear_auth` control requests for MCP server authentication
729
821
  - v0.2.53: Added `listSessions()` for discovering and listing past sessions with `SDKSessionInfo` metadata
730
- - v0.2.54 – v0.2.56: CLI parity updates (no new SDK-facing features)
822
+ - v0.2.54 – v0.2.58: CLI parity updates (no new SDK-facing features)
823
+ - v0.2.59: Added `getSessionMessages()` for reading session transcript history with pagination (limit/offset)
824
+ - v0.2.61 – v0.2.62: CLI parity updates (no new SDK-facing features)
731
825
 
732
826
  ### Python SDK
733
827
  - Full source available with `Transport` abstract class
734
828
  - Partial control protocol: query and client support interrupt, setPermissionMode, setModel, rewindFiles, mcpStatus
735
- - Has `CLINotFoundError`, `CLIConnectionError`, `ProcessError`, `CLIJSONDecodeError` error types
829
+ - Has `CLINotFoundError`, `CLIConnectionError`, `ProcessError`, `CLIJSONDecodeError`, `MessageParseError` error types
736
830
  - Missing hooks: SessionStart, SessionEnd, Setup, TeammateIdle, TaskCompleted, ConfigChange, WorktreeCreate, WorktreeRemove
737
831
  - Missing permission modes: `dontAsk`
738
832
  - Missing options: `allowDangerouslySkipPermissions`, `persistSession`, `resumeSessionAt`, `sessionId`, `strictMcpConfig`, `init`/`initOnly`/`maintenance`, `debug`/`debugFile`, `promptSuggestions`
739
833
  - `ToolPermissionContext` missing `blockedPath`, `decisionReason`, `toolUseID`, `agentID`, `description`
834
+ - Has `agent_type` field in `SubagentStopHookInput`
740
835
  - Has SDK MCP server support with `tool()` helper and annotations
741
836
  - Added `thinking` config and `effort` option in v0.1.36
742
837
  - Handles `rate_limit_event` and unknown message types gracefully (v0.1.40)
743
838
  - Client has `get_server_info()` for accessing the initialization result (v0.1.31+)
744
- - v0.1.42 – v0.1.43: CLI parity updates (no new SDK-facing features)
839
+ - v0.1.42 – v0.1.44: CLI parity updates (no new SDK-facing features; latest commit bumps bundled CLI to v2.1.61)
745
840
 
746
841
  ### Ruby SDK (This Repository)
747
- - Feature parity with TypeScript SDK v0.2.56
842
+ - Feature parity with TypeScript SDK v0.2.62
748
843
  - Ruby-idiomatic patterns (Data.define, snake_case)
749
844
  - Complete control protocol, hook, and V2 Session API support
750
845
  - Dedicated Client class for multi-turn conversations
751
846
  - `executable`/`executableArgs` marked N/A (JS runtime options)
847
+ - Has `settings`, `init`/`initOnly`/`maintenance`, `user` options (not typed in TS SDK)
@@ -159,50 +159,28 @@ module ClaudeAgent
159
159
  # Handlers persist across turns and fire automatically during
160
160
  # {#receive_turn} and {#send_and_receive}.
161
161
  #
162
- # @param event [Symbol] Event name (:message, :text, :thinking, :tool_use, :tool_result, :result)
162
+ # See {EventHandler} for the full event hierarchy:
163
+ # - +:message+ — catch-all for every message
164
+ # - Type-based — +:assistant+, +:stream_event+, +:status+, etc.
165
+ # - Decomposed — +:text+, +:thinking+, +:tool_use+, +:tool_result+
166
+ #
167
+ # @param event [Symbol] Event name (see {EventHandler::EVENTS})
163
168
  # @yield Event-specific arguments
164
169
  # @return [self]
165
170
  #
166
171
  # @example
167
172
  # client.on(:text) { |text| print text }
168
173
  # client.on(:tool_use) { |tool| show_spinner(tool) }
174
+ # client.on(:stream_event) { |evt| handle_stream(evt) }
169
175
  #
170
176
  def on(event, &block)
171
177
  @event_handler.on(event, &block)
172
178
  self
173
179
  end
174
180
 
175
- # @!method on_text(&block)
176
- # Register a handler for assistant text content
177
- # @yield [String] Text from the AssistantMessage
178
- # @return [self]
179
-
180
- # @!method on_thinking(&block)
181
- # Register a handler for assistant thinking content
182
- # @yield [String] Thinking from the AssistantMessage
183
- # @return [self]
184
-
185
- # @!method on_tool_use(&block)
186
- # Register a handler for tool use requests
187
- # @yield [ToolUseBlock, ServerToolUseBlock] The tool use block
188
- # @return [self]
189
-
190
- # @!method on_tool_result(&block)
191
- # Register a handler for tool results, paired with the original request
192
- # @yield [ToolResultBlock, ToolUseBlock|nil] Result block and matched tool use
193
- # @return [self]
194
-
195
- # @!method on_result(&block)
196
- # Register a handler for the final ResultMessage
197
- # @yield [ResultMessage] The result
198
- # @return [self]
199
-
200
- # @!method on_message(&block)
201
- # Register a handler for every message (catch-all)
202
- # @yield [message] Any message object
203
- # @return [self]
204
-
205
- %i[message text thinking tool_use tool_result result].each do |event|
181
+ # Generates on_* convenience methods for all known events.
182
+ # See {EventHandler::EVENTS} for the complete list.
183
+ EventHandler::EVENTS.each do |event|
206
184
  define_method(:"on_#{event}") { |&block| on(event, &block) }
207
185
  end
208
186