diff --git a/crates/misan/src/main.rs b/crates/misan/src/main.rs index 2473f71..dba61a2 100644 --- a/crates/misan/src/main.rs +++ b/crates/misan/src/main.rs @@ -184,14 +184,13 @@ async fn handle_chat( match event { Ok(event) => { match event { - misanthropy::StreamEvent::ContentBlockDelta { delta, .. } => { - if let misanthropy::ContentBlockDelta::TextDelta { text } = - delta - { - print!("{}", text); - io::stdout().flush()?; - response_content.push_str(&text); - } + misanthropy::StreamEvent::ContentBlockDelta { + delta: misanthropy::ContentBlockDelta::TextDelta { text }, + .. + } => { + print!("{}", text); + io::stdout().flush()?; + response_content.push_str(&text); } misanthropy::StreamEvent::MessageStop => { println!(); // End the line after the full response diff --git a/crates/misanthropy/src/lib.rs b/crates/misanthropy/src/lib.rs index fbe21f8..bc39fd7 100644 --- a/crates/misanthropy/src/lib.rs +++ b/crates/misanthropy/src/lib.rs @@ -1,5 +1,6 @@ //! Rust client for the Anthropic API. use std::any::type_name; +use std::time::Duration; use std::{env, fs, path::Path}; use base64::prelude::*; @@ -924,6 +925,7 @@ pub struct Anthropic { api_key: String, base_url: String, use_beta: bool, + timeout: Option, } impl Anthropic { @@ -934,6 +936,7 @@ impl Anthropic { api_key: api_key.to_string(), base_url: format!("https://{}", DEFAULT_API_DOMAIN), use_beta: true, + timeout: None, } } @@ -944,6 +947,12 @@ impl Anthropic { self } + /// Adds a timeout to any requests sent with this client. + pub fn with_timeout(mut self, timeout: Duration) -> Self { + self.timeout = Some(timeout); + self + } + /// Creates an Anthropic client using the API key from the environment. /// Reads the key from the ANTHROPIC_API_KEY environment variable. pub fn from_env() -> Result { @@ -991,13 +1000,15 @@ impl Anthropic { "Streaming requests must have stream set to true".to_string(), )); } - let event_source = EventSource::new( - reqwest::Client::new() - .post(format!("{}/v1/messages", self.base_url)) - .headers(self.create_headers()?) - .json(&request), - ) - .map_err(|e| Error::EventSourceError(e.to_string()))?; + let mut http_request = reqwest::Client::new() + .post(format!("{}/v1/messages", self.base_url)) + .headers(self.create_headers()?) + .json(&request); + if let Some(timeout) = self.timeout { + http_request = http_request.timeout(timeout); + } + let event_source = + EventSource::new(http_request).map_err(|e| Error::EventSourceError(e.to_string()))?; Ok(StreamedResponse::new(event_source)) } @@ -1006,12 +1017,14 @@ impl Anthropic { /// Uses client defaults for model and max_tokens if not specified in the request. pub async fn messages(&self, request: &MessagesRequest) -> Result { let client = reqwest::Client::new(); - let response = client + let mut http_request = client .post(format!("{}/v1/messages", self.base_url)) .headers(self.create_headers()?) - .json(&request) - .send() - .await?; + .json(&request); + if let Some(timeout) = self.timeout { + http_request = http_request.timeout(timeout); + } + let response = http_request.send().await?; let status = response.status();