claude_agent 0.7.7 → 0.7.9
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 +65 -0
- data/README.md +551 -37
- data/SPEC.md +70 -30
- data/lib/claude_agent/client.rb +197 -7
- data/lib/claude_agent/content_blocks.rb +193 -5
- data/lib/claude_agent/control_protocol.rb +111 -11
- data/lib/claude_agent/conversation.rb +248 -0
- data/lib/claude_agent/cumulative_usage.rb +106 -0
- data/lib/claude_agent/event_handler.rb +152 -0
- data/lib/claude_agent/hooks.rb +106 -225
- data/lib/claude_agent/list_sessions.rb +508 -0
- data/lib/claude_agent/mcp/server.rb +3 -3
- data/lib/claude_agent/mcp/tool.rb +4 -4
- data/lib/claude_agent/message_parser.rb +201 -185
- data/lib/claude_agent/messages.rb +86 -13
- data/lib/claude_agent/options.rb +5 -4
- data/lib/claude_agent/permission_queue.rb +87 -0
- data/lib/claude_agent/permission_request.rb +151 -0
- data/lib/claude_agent/permissions.rb +4 -2
- data/lib/claude_agent/query.rb +34 -0
- data/lib/claude_agent/tool_activity.rb +78 -0
- data/lib/claude_agent/turn_result.rb +239 -0
- data/lib/claude_agent/types.rb +29 -0
- data/lib/claude_agent/version.rb +1 -1
- data/lib/claude_agent.rb +39 -1
- data/sig/claude_agent.rbs +285 -4
- metadata +9 -1
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
module ClaudeAgent
|
|
4
4
|
# Parses raw JSON messages from the CLI into typed message objects
|
|
5
5
|
#
|
|
6
|
+
# Uses a registry to route messages by type (and subtype for system messages)
|
|
7
|
+
# to named parse methods. New message types can be added with a single
|
|
8
|
+
# {.register} call instead of modifying case statements.
|
|
9
|
+
#
|
|
6
10
|
# @example
|
|
7
11
|
# parser = MessageParser.new
|
|
8
12
|
# message = parser.parse({"type" => "assistant", "message" => {...}})
|
|
@@ -13,93 +17,94 @@ module ClaudeAgent
|
|
|
13
17
|
@logger = logger
|
|
14
18
|
end
|
|
15
19
|
|
|
20
|
+
# Registry of parser methods keyed by routing string.
|
|
21
|
+
# Keys are "type" for top-level types, "type:subtype" for system subtypes.
|
|
22
|
+
@registry = {}
|
|
23
|
+
|
|
24
|
+
class << self
|
|
25
|
+
attr_reader :registry
|
|
26
|
+
|
|
27
|
+
# Register a parse method for a message type
|
|
28
|
+
#
|
|
29
|
+
# @param key [String] Routing key ("type" or "type:subtype")
|
|
30
|
+
# @param method_name [Symbol] Name of the private parse method
|
|
31
|
+
def register(key, method_name)
|
|
32
|
+
@registry[key] = method_name
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
16
36
|
# Parse a raw message hash into a typed message object
|
|
17
37
|
#
|
|
18
|
-
# @param raw [Hash] Raw message from CLI
|
|
38
|
+
# @param raw [Hash] Raw message from CLI (string or symbol keys, camelCase or snake_case)
|
|
19
39
|
# @return [UserMessage, UserMessageReplay, AssistantMessage, SystemMessage, ResultMessage, StreamEvent, CompactBoundaryMessage, StatusMessage, ToolProgressMessage, HookResponseMessage, AuthStatusMessage, TaskNotificationMessage, HookStartedMessage, HookProgressMessage, ToolUseSummaryMessage, FilesPersistedEvent, TaskStartedMessage, RateLimitEvent, PromptSuggestionMessage]
|
|
20
40
|
# @raise [MessageParseError] If message cannot be parsed
|
|
21
41
|
def parse(raw)
|
|
22
|
-
|
|
42
|
+
raw = raw.deep_transform_keys { |key| key.to_s.underscore.to_sym }
|
|
43
|
+
type = raw[:type]
|
|
23
44
|
logger.debug("parser") { "Parsing message: #{type}" }
|
|
24
45
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
when "assistant"
|
|
29
|
-
parse_assistant_message(raw)
|
|
30
|
-
when "system"
|
|
31
|
-
# Check for special system subtypes
|
|
32
|
-
case raw["subtype"]
|
|
33
|
-
when "compact_boundary"
|
|
34
|
-
parse_compact_boundary_message(raw)
|
|
35
|
-
when "status"
|
|
36
|
-
parse_status_message(raw)
|
|
37
|
-
when "hook_response"
|
|
38
|
-
parse_hook_response_message(raw)
|
|
39
|
-
when "task_notification"
|
|
40
|
-
parse_task_notification_message(raw)
|
|
41
|
-
when "hook_started"
|
|
42
|
-
parse_hook_started_message(raw)
|
|
43
|
-
when "hook_progress"
|
|
44
|
-
parse_hook_progress_message(raw)
|
|
45
|
-
when "files_persisted"
|
|
46
|
-
parse_files_persisted_event(raw)
|
|
47
|
-
when "task_started"
|
|
48
|
-
parse_task_started_message(raw)
|
|
49
|
-
else
|
|
50
|
-
parse_system_message(raw)
|
|
51
|
-
end
|
|
52
|
-
when "result"
|
|
53
|
-
parse_result_message(raw)
|
|
54
|
-
when "stream_event"
|
|
55
|
-
parse_stream_event(raw)
|
|
56
|
-
when "tool_progress"
|
|
57
|
-
parse_tool_progress_message(raw)
|
|
58
|
-
when "auth_status"
|
|
59
|
-
parse_auth_status_message(raw)
|
|
60
|
-
when "tool_use_summary"
|
|
61
|
-
parse_tool_use_summary_message(raw)
|
|
62
|
-
when "rate_limit_event"
|
|
63
|
-
parse_rate_limit_event(raw)
|
|
64
|
-
when "prompt_suggestion"
|
|
65
|
-
parse_prompt_suggestion_message(raw)
|
|
46
|
+
# Look up parser: try specific system subtype first, then top-level type
|
|
47
|
+
method_name = if type == "system" && raw[:subtype]
|
|
48
|
+
self.class.registry["system:#{raw[:subtype]}"] || self.class.registry["system"]
|
|
66
49
|
else
|
|
67
|
-
|
|
68
|
-
|
|
50
|
+
self.class.registry[type]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
if method_name
|
|
54
|
+
send(method_name, raw)
|
|
55
|
+
else
|
|
56
|
+
logger.warn("parser") { "Unknown message type: #{type}, wrapping in GenericMessage" }
|
|
57
|
+
GenericMessage.new(message_type: type.to_s, raw: raw)
|
|
69
58
|
end
|
|
70
59
|
end
|
|
71
60
|
|
|
61
|
+
# --- Parser Registration ---
|
|
62
|
+
#
|
|
63
|
+
# Top-level message types
|
|
64
|
+
|
|
65
|
+
register "user", :parse_user_message
|
|
66
|
+
register "assistant", :parse_assistant_message
|
|
67
|
+
register "result", :parse_result_message
|
|
68
|
+
register "stream_event", :parse_stream_event
|
|
69
|
+
register "tool_progress", :parse_tool_progress_message
|
|
70
|
+
register "auth_status", :parse_auth_status_message
|
|
71
|
+
register "tool_use_summary", :parse_tool_use_summary_message
|
|
72
|
+
register "rate_limit_event", :parse_rate_limit_event
|
|
73
|
+
register "prompt_suggestion", :parse_prompt_suggestion_message
|
|
74
|
+
|
|
75
|
+
# System message subtypes
|
|
76
|
+
|
|
77
|
+
register "system", :parse_system_message # fallback for unknown subtypes
|
|
78
|
+
register "system:compact_boundary", :parse_compact_boundary_message
|
|
79
|
+
register "system:status", :parse_status_message
|
|
80
|
+
register "system:hook_response", :parse_hook_response_message
|
|
81
|
+
register "system:task_notification", :parse_task_notification_message
|
|
82
|
+
register "system:hook_started", :parse_hook_started_message
|
|
83
|
+
register "system:hook_progress", :parse_hook_progress_message
|
|
84
|
+
register "system:files_persisted", :parse_files_persisted_event
|
|
85
|
+
register "system:task_started", :parse_task_started_message
|
|
86
|
+
register "system:task_progress", :parse_task_progress_message
|
|
87
|
+
|
|
72
88
|
private
|
|
73
89
|
|
|
74
90
|
def logger
|
|
75
91
|
@logger || ClaudeAgent.logger
|
|
76
92
|
end
|
|
77
93
|
|
|
78
|
-
# Fetch a value from a hash, trying both snake_case and camelCase keys
|
|
79
|
-
# @param raw [Hash] The hash to fetch from
|
|
80
|
-
# @param snake_key [Symbol, String] The snake_case key to try
|
|
81
|
-
# @param default [Object] Default value if neither key exists
|
|
82
|
-
# @return [Object] The value or default
|
|
83
|
-
def fetch_dual(raw, snake_key, default = nil)
|
|
84
|
-
snake_str = snake_key.to_s
|
|
85
|
-
camel_str = snake_str.camelize(:lower)
|
|
86
|
-
raw[snake_str] || raw[camel_str] || default
|
|
87
|
-
end
|
|
88
|
-
|
|
89
94
|
def parse_user_message(raw)
|
|
90
|
-
message = raw[
|
|
91
|
-
content = parse_user_content(message[
|
|
95
|
+
message = raw[:message] || {}
|
|
96
|
+
content = parse_user_content(message[:content])
|
|
92
97
|
|
|
93
|
-
is_replay =
|
|
94
|
-
is_synthetic =
|
|
95
|
-
tool_use_result =
|
|
98
|
+
is_replay = raw[:is_replay]
|
|
99
|
+
is_synthetic = raw[:is_synthetic]
|
|
100
|
+
tool_use_result = raw[:tool_use_result]
|
|
96
101
|
|
|
97
102
|
if is_replay
|
|
98
103
|
UserMessageReplay.new(
|
|
99
104
|
content: content,
|
|
100
|
-
uuid: raw[
|
|
101
|
-
session_id:
|
|
102
|
-
parent_tool_use_id: raw[
|
|
105
|
+
uuid: raw[:uuid],
|
|
106
|
+
session_id: raw[:session_id],
|
|
107
|
+
parent_tool_use_id: raw[:parent_tool_use_id],
|
|
103
108
|
is_replay: true,
|
|
104
109
|
is_synthetic: is_synthetic,
|
|
105
110
|
tool_use_result: tool_use_result
|
|
@@ -107,61 +112,61 @@ module ClaudeAgent
|
|
|
107
112
|
else
|
|
108
113
|
UserMessage.new(
|
|
109
114
|
content: content,
|
|
110
|
-
uuid: raw[
|
|
111
|
-
session_id:
|
|
112
|
-
parent_tool_use_id: raw[
|
|
115
|
+
uuid: raw[:uuid],
|
|
116
|
+
session_id: raw[:session_id],
|
|
117
|
+
parent_tool_use_id: raw[:parent_tool_use_id]
|
|
113
118
|
)
|
|
114
119
|
end
|
|
115
120
|
end
|
|
116
121
|
|
|
117
122
|
def parse_assistant_message(raw)
|
|
118
|
-
message = raw[
|
|
119
|
-
content_raw = message[
|
|
123
|
+
message = raw[:message] || {}
|
|
124
|
+
content_raw = message[:content] || []
|
|
120
125
|
content = content_raw.map { |block| parse_content_block(block) }
|
|
121
126
|
|
|
122
127
|
AssistantMessage.new(
|
|
123
128
|
content: content,
|
|
124
|
-
model: message[
|
|
125
|
-
uuid: raw[
|
|
126
|
-
session_id:
|
|
127
|
-
error: message[
|
|
128
|
-
parent_tool_use_id: raw[
|
|
129
|
+
model: message[:model] || raw[:model] || "unknown",
|
|
130
|
+
uuid: raw[:uuid],
|
|
131
|
+
session_id: raw[:session_id],
|
|
132
|
+
error: message[:error] || raw[:error],
|
|
133
|
+
parent_tool_use_id: raw[:parent_tool_use_id]
|
|
129
134
|
)
|
|
130
135
|
end
|
|
131
136
|
|
|
132
137
|
def parse_system_message(raw)
|
|
133
138
|
SystemMessage.new(
|
|
134
|
-
subtype: raw[
|
|
135
|
-
data: raw[
|
|
139
|
+
subtype: raw[:subtype] || "unknown",
|
|
140
|
+
data: raw[:data] || raw
|
|
136
141
|
)
|
|
137
142
|
end
|
|
138
143
|
|
|
139
144
|
def parse_compact_boundary_message(raw)
|
|
140
145
|
CompactBoundaryMessage.new(
|
|
141
|
-
uuid: raw[
|
|
142
|
-
session_id:
|
|
143
|
-
compact_metadata:
|
|
146
|
+
uuid: raw[:uuid] || "",
|
|
147
|
+
session_id: raw[:session_id] || "",
|
|
148
|
+
compact_metadata: raw[:compact_metadata] || {}
|
|
144
149
|
)
|
|
145
150
|
end
|
|
146
151
|
|
|
147
152
|
def parse_result_message(raw)
|
|
148
|
-
permission_denials = parse_permission_denials(
|
|
153
|
+
permission_denials = parse_permission_denials(raw[:permission_denials])
|
|
149
154
|
|
|
150
155
|
ResultMessage.new(
|
|
151
|
-
subtype: raw[
|
|
152
|
-
duration_ms:
|
|
153
|
-
duration_api_ms:
|
|
154
|
-
is_error:
|
|
155
|
-
num_turns:
|
|
156
|
-
session_id:
|
|
157
|
-
total_cost_usd:
|
|
158
|
-
usage: raw[
|
|
159
|
-
result: raw[
|
|
160
|
-
structured_output:
|
|
161
|
-
errors: raw[
|
|
156
|
+
subtype: raw[:subtype] || "unknown",
|
|
157
|
+
duration_ms: raw[:duration_ms] || 0,
|
|
158
|
+
duration_api_ms: raw[:duration_api_ms] || 0,
|
|
159
|
+
is_error: raw[:is_error] || false,
|
|
160
|
+
num_turns: raw[:num_turns] || 0,
|
|
161
|
+
session_id: raw[:session_id] || "",
|
|
162
|
+
total_cost_usd: raw[:total_cost_usd],
|
|
163
|
+
usage: raw[:usage],
|
|
164
|
+
result: raw[:result],
|
|
165
|
+
structured_output: raw[:structured_output],
|
|
166
|
+
errors: raw[:errors],
|
|
162
167
|
permission_denials: permission_denials,
|
|
163
|
-
model_usage:
|
|
164
|
-
stop_reason:
|
|
168
|
+
model_usage: raw[:model_usage],
|
|
169
|
+
stop_reason: raw[:stop_reason]
|
|
165
170
|
)
|
|
166
171
|
end
|
|
167
172
|
|
|
@@ -170,19 +175,19 @@ module ClaudeAgent
|
|
|
170
175
|
|
|
171
176
|
denials.map do |denial|
|
|
172
177
|
SDKPermissionDenial.new(
|
|
173
|
-
tool_name:
|
|
174
|
-
tool_use_id:
|
|
175
|
-
tool_input:
|
|
178
|
+
tool_name: denial[:tool_name],
|
|
179
|
+
tool_use_id: denial[:tool_use_id],
|
|
180
|
+
tool_input: denial[:tool_input]
|
|
176
181
|
)
|
|
177
182
|
end
|
|
178
183
|
end
|
|
179
184
|
|
|
180
185
|
def parse_stream_event(raw)
|
|
181
186
|
StreamEvent.new(
|
|
182
|
-
uuid: raw[
|
|
183
|
-
session_id:
|
|
184
|
-
event: raw[
|
|
185
|
-
parent_tool_use_id: raw[
|
|
187
|
+
uuid: raw[:uuid] || "",
|
|
188
|
+
session_id: raw[:session_id] || "",
|
|
189
|
+
event: raw[:event] || {},
|
|
190
|
+
parent_tool_use_id: raw[:parent_tool_use_id]
|
|
186
191
|
)
|
|
187
192
|
end
|
|
188
193
|
|
|
@@ -200,173 +205,184 @@ module ClaudeAgent
|
|
|
200
205
|
def parse_content_block(block)
|
|
201
206
|
return block unless block.is_a?(Hash)
|
|
202
207
|
|
|
203
|
-
type = block[
|
|
208
|
+
type = block[:type]
|
|
204
209
|
|
|
205
210
|
case type
|
|
206
211
|
when "text"
|
|
207
|
-
TextBlock.new(text: block[
|
|
212
|
+
TextBlock.new(text: block[:text] || "")
|
|
208
213
|
when "thinking"
|
|
209
214
|
ThinkingBlock.new(
|
|
210
|
-
thinking: block[
|
|
211
|
-
signature: block[
|
|
215
|
+
thinking: block[:thinking] || "",
|
|
216
|
+
signature: block[:signature] || ""
|
|
212
217
|
)
|
|
213
218
|
when "tool_use"
|
|
214
219
|
ToolUseBlock.new(
|
|
215
|
-
id: block[
|
|
216
|
-
name: block[
|
|
217
|
-
input: block[
|
|
220
|
+
id: block[:id] || "",
|
|
221
|
+
name: block[:name] || "",
|
|
222
|
+
input: block[:input] || {}
|
|
218
223
|
)
|
|
219
224
|
when "tool_result"
|
|
220
225
|
ToolResultBlock.new(
|
|
221
|
-
tool_use_id: block[
|
|
222
|
-
content: block[
|
|
223
|
-
is_error: block[
|
|
226
|
+
tool_use_id: block[:tool_use_id] || "",
|
|
227
|
+
content: block[:content],
|
|
228
|
+
is_error: block[:is_error]
|
|
224
229
|
)
|
|
225
230
|
when "server_tool_use"
|
|
226
231
|
ServerToolUseBlock.new(
|
|
227
|
-
id: block[
|
|
228
|
-
name: block[
|
|
229
|
-
input: block[
|
|
230
|
-
server_name: block[
|
|
232
|
+
id: block[:id] || "",
|
|
233
|
+
name: block[:name] || "",
|
|
234
|
+
input: block[:input] || {},
|
|
235
|
+
server_name: block[:server_name] || ""
|
|
231
236
|
)
|
|
232
237
|
when "server_tool_result"
|
|
233
238
|
ServerToolResultBlock.new(
|
|
234
|
-
tool_use_id: block[
|
|
235
|
-
content: block[
|
|
236
|
-
is_error: block[
|
|
237
|
-
server_name: block[
|
|
239
|
+
tool_use_id: block[:tool_use_id] || "",
|
|
240
|
+
content: block[:content],
|
|
241
|
+
is_error: block[:is_error],
|
|
242
|
+
server_name: block[:server_name] || ""
|
|
238
243
|
)
|
|
239
244
|
when "image"
|
|
240
245
|
ImageContentBlock.new(
|
|
241
|
-
source: block[
|
|
246
|
+
source: block[:source] || {}
|
|
242
247
|
)
|
|
243
248
|
else
|
|
244
|
-
|
|
245
|
-
block
|
|
249
|
+
GenericBlock.new(block_type: type.to_s, raw: block)
|
|
246
250
|
end
|
|
247
251
|
end
|
|
248
252
|
|
|
249
253
|
def parse_status_message(raw)
|
|
250
254
|
StatusMessage.new(
|
|
251
|
-
uuid: raw[
|
|
252
|
-
session_id:
|
|
253
|
-
status: raw[
|
|
255
|
+
uuid: raw[:uuid] || "",
|
|
256
|
+
session_id: raw[:session_id] || "",
|
|
257
|
+
status: raw[:status]
|
|
254
258
|
)
|
|
255
259
|
end
|
|
256
260
|
|
|
257
261
|
def parse_tool_progress_message(raw)
|
|
258
262
|
ToolProgressMessage.new(
|
|
259
|
-
uuid: raw[
|
|
260
|
-
session_id:
|
|
261
|
-
tool_use_id:
|
|
262
|
-
tool_name:
|
|
263
|
-
parent_tool_use_id:
|
|
264
|
-
elapsed_time_seconds:
|
|
263
|
+
uuid: raw[:uuid] || "",
|
|
264
|
+
session_id: raw[:session_id] || "",
|
|
265
|
+
tool_use_id: raw[:tool_use_id] || "",
|
|
266
|
+
tool_name: raw[:tool_name] || "",
|
|
267
|
+
parent_tool_use_id: raw[:parent_tool_use_id],
|
|
268
|
+
elapsed_time_seconds: raw[:elapsed_time_seconds] || 0
|
|
265
269
|
)
|
|
266
270
|
end
|
|
267
271
|
|
|
268
272
|
def parse_hook_response_message(raw)
|
|
269
273
|
HookResponseMessage.new(
|
|
270
|
-
uuid: raw[
|
|
271
|
-
session_id:
|
|
272
|
-
hook_id:
|
|
273
|
-
hook_name:
|
|
274
|
-
hook_event:
|
|
275
|
-
stdout: raw[
|
|
276
|
-
stderr: raw[
|
|
277
|
-
output: raw[
|
|
278
|
-
exit_code:
|
|
279
|
-
outcome: raw[
|
|
274
|
+
uuid: raw[:uuid] || "",
|
|
275
|
+
session_id: raw[:session_id] || "",
|
|
276
|
+
hook_id: raw[:hook_id],
|
|
277
|
+
hook_name: raw[:hook_name] || "",
|
|
278
|
+
hook_event: raw[:hook_event] || "",
|
|
279
|
+
stdout: raw[:stdout] || "",
|
|
280
|
+
stderr: raw[:stderr] || "",
|
|
281
|
+
output: raw[:output] || "",
|
|
282
|
+
exit_code: raw[:exit_code],
|
|
283
|
+
outcome: raw[:outcome]
|
|
280
284
|
)
|
|
281
285
|
end
|
|
282
286
|
|
|
283
287
|
def parse_auth_status_message(raw)
|
|
284
288
|
AuthStatusMessage.new(
|
|
285
|
-
uuid: raw[
|
|
286
|
-
session_id:
|
|
287
|
-
is_authenticating:
|
|
288
|
-
output: raw[
|
|
289
|
-
error: raw[
|
|
289
|
+
uuid: raw[:uuid] || "",
|
|
290
|
+
session_id: raw[:session_id] || "",
|
|
291
|
+
is_authenticating: raw[:is_authenticating] || false,
|
|
292
|
+
output: raw[:output] || [],
|
|
293
|
+
error: raw[:error]
|
|
290
294
|
)
|
|
291
295
|
end
|
|
292
296
|
|
|
293
297
|
def parse_task_notification_message(raw)
|
|
294
298
|
TaskNotificationMessage.new(
|
|
295
|
-
uuid: raw[
|
|
296
|
-
session_id:
|
|
297
|
-
task_id:
|
|
298
|
-
status: raw[
|
|
299
|
-
output_file:
|
|
300
|
-
summary: raw[
|
|
299
|
+
uuid: raw[:uuid] || "",
|
|
300
|
+
session_id: raw[:session_id] || "",
|
|
301
|
+
task_id: raw[:task_id] || "",
|
|
302
|
+
status: raw[:status] || "unknown",
|
|
303
|
+
output_file: raw[:output_file] || "",
|
|
304
|
+
summary: raw[:summary] || ""
|
|
301
305
|
)
|
|
302
306
|
end
|
|
303
307
|
|
|
304
308
|
def parse_hook_started_message(raw)
|
|
305
309
|
HookStartedMessage.new(
|
|
306
|
-
uuid: raw[
|
|
307
|
-
session_id:
|
|
308
|
-
hook_id:
|
|
309
|
-
hook_name:
|
|
310
|
-
hook_event:
|
|
310
|
+
uuid: raw[:uuid] || "",
|
|
311
|
+
session_id: raw[:session_id] || "",
|
|
312
|
+
hook_id: raw[:hook_id] || "",
|
|
313
|
+
hook_name: raw[:hook_name] || "",
|
|
314
|
+
hook_event: raw[:hook_event] || ""
|
|
311
315
|
)
|
|
312
316
|
end
|
|
313
317
|
|
|
314
318
|
def parse_hook_progress_message(raw)
|
|
315
319
|
HookProgressMessage.new(
|
|
316
|
-
uuid: raw[
|
|
317
|
-
session_id:
|
|
318
|
-
hook_id:
|
|
319
|
-
hook_name:
|
|
320
|
-
hook_event:
|
|
321
|
-
stdout: raw[
|
|
322
|
-
stderr: raw[
|
|
323
|
-
output: raw[
|
|
320
|
+
uuid: raw[:uuid] || "",
|
|
321
|
+
session_id: raw[:session_id] || "",
|
|
322
|
+
hook_id: raw[:hook_id] || "",
|
|
323
|
+
hook_name: raw[:hook_name] || "",
|
|
324
|
+
hook_event: raw[:hook_event] || "",
|
|
325
|
+
stdout: raw[:stdout] || "",
|
|
326
|
+
stderr: raw[:stderr] || "",
|
|
327
|
+
output: raw[:output] || ""
|
|
324
328
|
)
|
|
325
329
|
end
|
|
326
330
|
|
|
327
331
|
def parse_tool_use_summary_message(raw)
|
|
328
332
|
ToolUseSummaryMessage.new(
|
|
329
|
-
uuid: raw[
|
|
330
|
-
session_id:
|
|
331
|
-
summary: raw[
|
|
332
|
-
preceding_tool_use_ids:
|
|
333
|
+
uuid: raw[:uuid] || "",
|
|
334
|
+
session_id: raw[:session_id] || "",
|
|
335
|
+
summary: raw[:summary] || "",
|
|
336
|
+
preceding_tool_use_ids: raw[:preceding_tool_use_ids] || []
|
|
333
337
|
)
|
|
334
338
|
end
|
|
335
339
|
|
|
336
340
|
def parse_files_persisted_event(raw)
|
|
337
341
|
FilesPersistedEvent.new(
|
|
338
|
-
uuid: raw[
|
|
339
|
-
session_id:
|
|
340
|
-
files: raw[
|
|
341
|
-
failed: raw[
|
|
342
|
-
processed_at:
|
|
342
|
+
uuid: raw[:uuid] || "",
|
|
343
|
+
session_id: raw[:session_id] || "",
|
|
344
|
+
files: raw[:files] || [],
|
|
345
|
+
failed: raw[:failed] || [],
|
|
346
|
+
processed_at: raw[:processed_at]
|
|
343
347
|
)
|
|
344
348
|
end
|
|
345
349
|
|
|
346
350
|
def parse_task_started_message(raw)
|
|
347
351
|
TaskStartedMessage.new(
|
|
348
|
-
uuid: raw[
|
|
349
|
-
session_id:
|
|
350
|
-
task_id:
|
|
351
|
-
tool_use_id:
|
|
352
|
-
description: raw[
|
|
353
|
-
task_type:
|
|
352
|
+
uuid: raw[:uuid] || "",
|
|
353
|
+
session_id: raw[:session_id] || "",
|
|
354
|
+
task_id: raw[:task_id] || "",
|
|
355
|
+
tool_use_id: raw[:tool_use_id],
|
|
356
|
+
description: raw[:description],
|
|
357
|
+
task_type: raw[:task_type]
|
|
358
|
+
)
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
def parse_task_progress_message(raw)
|
|
362
|
+
TaskProgressMessage.new(
|
|
363
|
+
uuid: raw[:uuid] || "",
|
|
364
|
+
session_id: raw[:session_id] || "",
|
|
365
|
+
task_id: raw[:task_id] || "",
|
|
366
|
+
tool_use_id: raw[:tool_use_id],
|
|
367
|
+
description: raw[:description] || "",
|
|
368
|
+
usage: raw[:usage],
|
|
369
|
+
last_tool_name: raw[:last_tool_name]
|
|
354
370
|
)
|
|
355
371
|
end
|
|
356
372
|
|
|
357
373
|
def parse_rate_limit_event(raw)
|
|
358
374
|
RateLimitEvent.new(
|
|
359
|
-
rate_limit_info:
|
|
360
|
-
uuid: raw[
|
|
361
|
-
session_id:
|
|
375
|
+
rate_limit_info: raw[:rate_limit_info] || {},
|
|
376
|
+
uuid: raw[:uuid] || "",
|
|
377
|
+
session_id: raw[:session_id] || ""
|
|
362
378
|
)
|
|
363
379
|
end
|
|
364
380
|
|
|
365
381
|
def parse_prompt_suggestion_message(raw)
|
|
366
382
|
PromptSuggestionMessage.new(
|
|
367
|
-
uuid: raw[
|
|
368
|
-
session_id:
|
|
369
|
-
suggestion: raw[
|
|
383
|
+
uuid: raw[:uuid] || "",
|
|
384
|
+
session_id: raw[:session_id] || "",
|
|
385
|
+
suggestion: raw[:suggestion] || ""
|
|
370
386
|
)
|
|
371
387
|
end
|
|
372
388
|
end
|