anthropic-sdk-rust 0.1.1

Comprehensive, type-safe Rust SDK for the Anthropic API with streaming, tools, vision, files, and batch processing support
Documentation
use anthropic_sdk::{Anthropic, ClientConfig, MessageCreateBuilder, MessageStreamEvent, ContentBlockDelta};
use anthropic_sdk::types::ContentBlock;
use std::time::Duration;
use std::io::{self, Write};
use futures::StreamExt;

// Helper function to extract text content from response
fn extract_text_from_content(content: &[ContentBlock]) -> String {
    content.iter()
        .filter_map(|block| match block {
            ContentBlock::Text { text } => Some(text.as_str()),
            _ => None,
        })
        .collect::<Vec<_>>()
        .join(" ")
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("๐Ÿš€ Testing Anthropic SDK Streaming with eBay Gateway...\n");
    
    // Get API key from environment or use dummy for configuration test
    let api_key = std::env::var("ANTHROPIC_API_KEY")
        .or_else(|_| std::env::var("EBAY_ANTHROPIC_API_KEY"))
        .unwrap_or_else(|_| {
            println!("โš ๏ธ  No API key found in environment variables.");
            println!("   Set ANTHROPIC_API_KEY or EBAY_ANTHROPIC_API_KEY");
            println!("   Using dummy key for configuration test only...\n");
            "dummy-key".to_string()
        });
    
    // Custom configuration for eBay gateway
    let config = ClientConfig::new(&api_key)
        .with_base_url("https://platformgateway2.vip.ebay.com/hubgptgatewaysvc/v1/anthropic")
        .with_timeout(Duration::from_secs(30))
        .with_max_retries(3);
    
    let client = Anthropic::with_config(config)?;
    
    println!("โœ… Client created with custom eBay gateway configuration");
    println!("๐Ÿ“ก Base URL: https://platformgateway2.vip.ebay.com/hubgptgatewaysvc/v1/anthropic");
    println!("๐Ÿค– Model: hubgpt-chat-completions-sonnet-3-7\n");
    
    // Test 1: Callback-based streaming
    println!("๐Ÿงช Test 1: Callback-based streaming...");
    
    if api_key != "dummy-key" {
        match client.messages()
            .create_with_builder("hubgpt-chat-completions-sonnet-3-7", 200)
            .user("Write a short haiku about programming")
            .temperature(0.8)
            .stream_send()
            .await
        {
            Ok(stream) => {
                println!("โœ… Stream created successfully!");
                println!("๐Ÿ“ก Streaming response...\n");
                
                let final_message = stream
                    .on_text(|delta, _snapshot| {
                        print!("{}", delta);
                        io::stdout().flush().unwrap();
                    })
                    .on_error(|error| {
                        eprintln!("\nโŒ Stream error: {}", error);
                    })
                    .on_end(|| {
                        println!("\nโœ… Stream completed!");
                    })
                    .final_message()
                    .await?;
                
                println!("๐Ÿ“Š Usage: {} input, {} output tokens", 
                    final_message.usage.input_tokens, 
                    final_message.usage.output_tokens);
            }
            Err(e) => {
                println!("โŒ Streaming test FAILED!");
                println!("๐Ÿšจ Error: {}", e);
            }
        }
    } else {
        println!("โš ๏ธ  Skipping streaming test with dummy API key");
    }
    
    // Test 2: Manual stream iteration
    println!("\n๐Ÿงช Test 2: Manual stream iteration...");
    
    if api_key != "dummy-key" {
        let params = MessageCreateBuilder::new("hubgpt-chat-completions-sonnet-3-7", 150)
            .user("Count from 1 to 3")
            .stream(true)
            .build();
        
        match client.messages().create_stream(params).await {
            Ok(mut stream) => {
                println!("โœ… Stream created successfully!");
                println!("๐Ÿ“ก Processing events manually...\n");
                
                let mut content = String::new();
                
                while let Some(event) = stream.next().await {
                    match event? {
                        MessageStreamEvent::MessageStart { message } => {
                            println!("๐Ÿ“จ Message started: {}", message.id);
                        }
                        MessageStreamEvent::ContentBlockStart { index, .. } => {
                            println!("๐Ÿ“ Content block {} started", index);
                        }
                        MessageStreamEvent::ContentBlockDelta { delta, .. } => {
                            match delta {
                                ContentBlockDelta::TextDelta { text } => {
                                    print!("{}", text);
                                    content.push_str(&text);
                                    io::stdout().flush().unwrap();
                                }
                                _ => {}
                            }
                        }
                        MessageStreamEvent::MessageDelta { usage, .. } => {
                            println!("\n๐Ÿ“Š Usage: {} output tokens", usage.output_tokens);
                        }
                        MessageStreamEvent::MessageStop => {
                            println!("\nโœ… Stream completed!");
                            break;
                        }
                        _ => {}
                    }
                }
                
                println!("๐Ÿ“œ Complete response: {}", content);
            }
            Err(e) => {
                println!("โŒ Manual streaming test FAILED!");
                println!("๐Ÿšจ Error: {}", e);
            }
        }
    } else {
        println!("โš ๏ธ  Skipping manual streaming test with dummy API key");
    }
    
    // Test 3: Regular message (for comparison)
    println!("\n๐Ÿงช Test 3: Regular message (non-streaming)...");
    let response = client.messages()
        .create(
            MessageCreateBuilder::new("hubgpt-chat-completions-sonnet-3-7", 100)
                .user("Hello! Just say 'SDK configured correctly'")
                .build()
        )
        .await;
    
    match response {
        Ok(msg) => {
            println!("โœ… Regular message PASSED!");
            let text = extract_text_from_content(&msg.content);
            println!("๐Ÿ“ Response: {}", text);
        }
        Err(e) => {
            println!("โŒ Regular message FAILED!");
            println!("๐Ÿšจ Error: {}", e);
            
            if api_key == "dummy-key" {
                println!("๐Ÿ’ก This is expected with dummy API key.");
            }
        }
    }
    
    println!("\n๐ŸŽ‰ Streaming tests completed!");
    
    if api_key == "dummy-key" {
        println!("\n๐Ÿ’ก To test with real API calls:");
        println!("   export ANTHROPIC_API_KEY='your-ebay-gateway-key'");
        println!("   cargo run --example test_ebay_streaming");
    }
    
    Ok(())
}