use serde::{Deserialize, Serialize};
use serde_json::{Number, Value};
use super::{ContentBlock, Extra, Field, MessageContent, Partial, ResultMessage, System, Usage};
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum Message {
User(UserMessage),
Assistant(AssistantMessage),
System(System),
Result(ResultMessage),
StreamEvent(StreamEvent),
RateLimitEvent(RateLimitEvent),
CommandLifecycle(CommandLifecycle),
Other {
type_: String,
raw: Value,
},
Malformed {
type_: String,
error: String,
raw: Value,
},
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct AssistantMessage {
pub message: ApiMessage,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub parent_tool_use_id: Field<String>,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub session_id: Field<String>,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub uuid: Field<String>,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub error: Field<String>,
#[serde(flatten)]
pub extra: Extra,
}
impl AssistantMessage {
pub fn content(&self) -> &[ContentBlock] {
&self.message.content
}
pub const fn is_subagent(&self) -> bool {
matches!(self.parent_tool_use_id, Field::Value(_))
}
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct ApiMessage {
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub id: Field<String>,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub model: Field<String>,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub role: Field<String>,
pub content: Vec<ContentBlock>,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub stop_reason: Field<String>,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub stop_sequence: Field<String>,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub usage: Field<Usage>,
#[serde(flatten)]
pub extra: Extra,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct UserMessage {
pub message: ApiUserMessage,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub parent_tool_use_id: Field<String>,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub session_id: Field<String>,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub uuid: Field<String>,
#[serde(flatten)]
pub extra: Extra,
}
impl UserMessage {
pub fn content(&self) -> &MessageContent {
&self.message.content
}
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct ApiUserMessage {
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub role: Field<String>,
pub content: MessageContent,
#[serde(flatten)]
pub extra: Extra,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct StreamEvent {
pub event: Value,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub parent_tool_use_id: Field<String>,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub session_id: Field<String>,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub uuid: Field<String>,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub api_message_id: Field<String>,
#[serde(flatten)]
pub extra: Extra,
}
impl StreamEvent {
pub fn event_type(&self) -> Option<&str> {
self.event.get("type").and_then(Value::as_str)
}
pub fn is_subagent(&self) -> bool {
self.parent_tool_use_id
.as_deref()
.is_some_and(|s| !s.is_empty())
}
pub fn partial(&self) -> Option<Partial> {
Partial::of_event(&self.event)
}
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct CommandLifecycle {
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub command_uuid: Field<String>,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub state: Field<String>,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub session_id: Field<String>,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub uuid: Field<String>,
#[serde(flatten)]
pub extra: Extra,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct RateLimitEvent {
pub rate_limit_info: RateLimitInfo,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub session_id: Field<String>,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub uuid: Field<String>,
#[serde(flatten)]
pub extra: Extra,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct RateLimitInfo {
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub status: Field<String>,
#[serde(default, rename = "resetsAt", skip_serializing_if = "Field::is_absent")]
pub resets_at: Field<u64>,
#[serde(
default,
rename = "rateLimitType",
skip_serializing_if = "Field::is_absent"
)]
pub rate_limit_type: Field<String>,
#[serde(default, skip_serializing_if = "Field::is_absent")]
pub utilization: Field<Number>,
#[serde(flatten)]
pub extra: Extra,
}