claude-rust-provider 0.2.0

Anthropic API provider with SSE streaming
Documentation
use claude_rust_auth::Credential;
use claude_rust_types::{ContentBlock, Conversation};
use serde_json::{Value, json};

use super::anthropic_provider::{BILLING_HEADER, MAX_TOKENS};

pub fn build_request_body(
    credential: &Credential,
    model: &str,
    conversation: &Conversation,
    tools: &[Value],
) -> Value {
    let messages: Vec<Value> = conversation
        .messages
        .iter()
        .map(|msg| {
            let content: Vec<Value> = msg
                .content
                .iter()
                .map(|block| match block {
                    ContentBlock::Text { text } => json!({
                        "type": "text",
                        "text": text,
                    }),
                    ContentBlock::ToolUse { id, name, input } => json!({
                        "type": "tool_use",
                        "id": id,
                        "name": name,
                        "input": input,
                    }),
                    ContentBlock::ToolResult {
                        tool_use_id,
                        content,
                        is_error,
                    } => {
                        let mut v = json!({
                            "type": "tool_result",
                            "tool_use_id": tool_use_id,
                            "content": content,
                        });
                        if let Some(true) = is_error {
                            v["is_error"] = json!(true);
                        }
                        v
                    }
                })
                .collect();

            json!({
                "role": serde_json::to_value(&msg.role).unwrap_or(json!("user")),
                "content": content,
            })
        })
        .collect();

    let mut body = json!({
        "model": model,
        "max_tokens": MAX_TOKENS,
        "messages": messages,
        "stream": true,
    });

    if credential.is_oauth() {
        let mut system_blocks = vec![json!({
            "type": "text",
            "text": BILLING_HEADER,
        })];
        if let Some(system) = &conversation.system {
            system_blocks.push(json!({
                "type": "text",
                "text": system,
            }));
        }
        body["system"] = json!(system_blocks);
        body["thinking"] = json!({"type": "adaptive"});
    } else if let Some(system) = &conversation.system {
        body["system"] = json!(system);
    }

    if !tools.is_empty() {
        body["tools"] = json!(tools);
    }

    body
}