claude-code-sdk-rust 0.1.0

Async Rust SDK for the Claude Code CLI: streaming agent turns, tool use, and sessions.
Documentation
use crate::client_types::{MessageResponse, StreamEvent};
use crate::types::{ContentBlock, Message};

pub(crate) fn stream_events_from_message(
    message: &Message,
    fallback_session_id: &str,
) -> Vec<StreamEvent> {
    match message {
        Message::AssistantMsg {
            content,
            stop_reason,
            session_id,
            usage,
            ..
        } => {
            let mut events = Vec::new();
            for block in &content.content {
                match block {
                    ContentBlock::Text { text } => {
                        events.push(StreamEvent::ContentChunk(text.clone()));
                    }
                    ContentBlock::Thinking {
                        thinking,
                        signature,
                    } => {
                        events.push(StreamEvent::ThinkingChunk {
                            thinking: thinking.clone(),
                            signature: Some(signature.clone()),
                        });
                    }
                    ContentBlock::ToolUse { id, name, input }
                    | ContentBlock::ServerToolUse { id, name, input } => {
                        events.push(StreamEvent::ToolUseStart {
                            id: id.clone(),
                            name: name.clone(),
                            input: input.clone(),
                        });
                    }
                    ContentBlock::ToolResult {
                        tool_use_id,
                        content,
                        is_error,
                    } => {
                        events.push(StreamEvent::ToolResult {
                            tool_use_id: tool_use_id.clone(),
                            content: content.clone(),
                            is_error: *is_error,
                        });
                    }
                    ContentBlock::ServerToolResult {
                        tool_use_id,
                        content,
                    } => {
                        events.push(StreamEvent::ToolResult {
                            tool_use_id: tool_use_id.clone(),
                            content: Some(content.clone()),
                            is_error: None,
                        });
                    }
                }
            }
            events.push(StreamEvent::Complete(MessageResponse {
                content: content
                    .content
                    .iter()
                    .filter_map(|block| match block {
                        ContentBlock::Text { text } => Some(text.clone()),
                        _ => None,
                    })
                    .collect::<Vec<_>>()
                    .join(""),
                blocks: content.content.clone(),
                model: content.model.clone(),
                stop_reason: stop_reason.clone().or_else(|| content.stop_reason.clone()),
                session_id: session_id
                    .clone()
                    .unwrap_or_else(|| fallback_session_id.to_string()),
                usage: usage.clone().map(|usage| usage.into_iter().collect()),
            }));
            events
        }
        Message::RateLimitEventMsg {
            rate_limit_info, ..
        } => vec![StreamEvent::RateLimit(rate_limit_info.clone())],
        Message::ResultMsg {
            is_error: true,
            result,
            errors,
            ..
        } => vec![StreamEvent::Error(
            errors
                .as_ref()
                .map(|errors| errors.join("\n"))
                .or_else(|| result.clone())
                .unwrap_or_else(|| "Claude result indicated an error".to_string()),
        )],
        _ => Vec::new(),
    }
}