claude_agent_sdk/internal/
parser.rs1use crate::error::{ClaudeSDKError, MessageParseError, Result};
2use crate::types::{
3 HookEventMessage, Message, MirrorErrorMessage, TaskNotificationMessage, TaskProgressMessage,
4 TaskStartedMessage,
5};
6
7const KNOWN_MESSAGE_TYPES: &[&str] = &[
8 "user",
9 "assistant",
10 "system",
11 "result",
12 "stream_event",
13 "rate_limit_event",
14];
15
16pub fn parse_message_line(line: &str) -> Result<Option<Message>> {
17 let value = serde_json::from_str::<serde_json::Value>(line)?;
18 parse_message_value(value)
19}
20
21pub fn parse_message_value(value: serde_json::Value) -> Result<Option<Message>> {
22 let message_type = value.get("type").and_then(|v| v.as_str()).ok_or_else(|| {
23 let data = value.as_object().cloned();
24 let mut error = MessageParseError::new("Message missing 'type' field");
25 if let Some(data) = data {
26 error = error.with_data(data);
27 }
28 ClaudeSDKError::MessageParse(error)
29 })?;
30
31 if !KNOWN_MESSAGE_TYPES.contains(&message_type) {
32 return Ok(None);
33 }
34
35 if message_type == "system" {
36 return parse_system_message_value(value);
37 }
38
39 serde_json::from_value::<Message>(value)
40 .map(Some)
41 .map_err(ClaudeSDKError::Serialization)
42}
43
44fn parse_system_message_value(value: serde_json::Value) -> Result<Option<Message>> {
45 let subtype = value.get("subtype").and_then(|v| v.as_str());
46 match subtype {
47 Some("task_started") => parse_task_started(value)
48 .map(Message::TaskStartedMsg)
49 .map(Some),
50 Some("task_progress") => parse_task_progress(value)
51 .map(Message::TaskProgressMsg)
52 .map(Some),
53 Some("task_notification") => parse_task_notification(value)
54 .map(Message::TaskNotificationMsg)
55 .map(Some),
56 Some("hook_started" | "hook_response") => {
57 parse_hook_event(value).map(Message::HookEventMsg).map(Some)
58 }
59 Some("mirror_error") => parse_mirror_error(value)
60 .map(Message::MirrorErrorMsg)
61 .map(Some),
62 _ => serde_json::from_value::<Message>(value)
63 .map(Some)
64 .map_err(ClaudeSDKError::Serialization),
65 }
66}
67
68fn parse_mirror_error(value: serde_json::Value) -> Result<MirrorErrorMessage> {
69 let mut data = value.as_object().cloned().ok_or_else(|| {
70 ClaudeSDKError::MessageParse(MessageParseError::new("System message must be an object"))
71 })?;
72 data.remove("type");
73 let key = data.get("key").and_then(|value| value.as_object()).cloned();
74 let error = data
75 .get("error")
76 .and_then(|value| value.as_str())
77 .unwrap_or_default()
78 .to_string();
79 Ok(MirrorErrorMessage { key, error, data })
80}
81
82fn parse_task_started(value: serde_json::Value) -> Result<TaskStartedMessage> {
83 serde_json::from_value::<TaskStartedMessage>(strip_system_fields(value)?)
84 .map_err(ClaudeSDKError::Serialization)
85}
86
87fn parse_task_progress(value: serde_json::Value) -> Result<TaskProgressMessage> {
88 serde_json::from_value::<TaskProgressMessage>(strip_system_fields(value)?)
89 .map_err(ClaudeSDKError::Serialization)
90}
91
92fn parse_task_notification(value: serde_json::Value) -> Result<TaskNotificationMessage> {
93 serde_json::from_value::<TaskNotificationMessage>(strip_system_fields(value)?)
94 .map_err(ClaudeSDKError::Serialization)
95}
96
97fn parse_hook_event(value: serde_json::Value) -> Result<HookEventMessage> {
98 let mut data = value.as_object().cloned().ok_or_else(|| {
99 ClaudeSDKError::MessageParse(MessageParseError::new("System message must be an object"))
100 })?;
101 let subtype = data
102 .get("subtype")
103 .and_then(|value| value.as_str())
104 .unwrap_or_default()
105 .to_string();
106 let hook_event_name = data
107 .get("hook_event")
108 .or_else(|| data.get("hook_name"))
109 .and_then(|value| value.as_str())
110 .map(ToString::to_string);
111 let session_id = data
112 .get("session_id")
113 .and_then(|value| value.as_str())
114 .map(ToString::to_string);
115 let uuid = data
116 .get("uuid")
117 .and_then(|value| value.as_str())
118 .map(ToString::to_string);
119 data.remove("type");
120 Ok(HookEventMessage {
121 subtype,
122 hook_event_name,
123 session_id,
124 uuid,
125 data,
126 })
127}
128
129fn strip_system_fields(value: serde_json::Value) -> Result<serde_json::Value> {
130 let mut data = value.as_object().cloned().ok_or_else(|| {
131 ClaudeSDKError::MessageParse(MessageParseError::new("System message must be an object"))
132 })?;
133 data.remove("type");
134 data.remove("subtype");
135 Ok(serde_json::Value::Object(data))
136}