From 3213cb495832215d9a4b4efc59787e6fc8fa51ed Mon Sep 17 00:00:00 2001 From: Joe Fioti Date: Fri, 21 Feb 2025 09:20:39 -0500 Subject: [PATCH 1/2] added request timeout --- crates/misan/src/main.rs | 15 +++++++-------- crates/misanthropy/src/lib.rs | 36 ++++++++++++++++++++++++----------- 2 files changed, 32 insertions(+), 19 deletions(-) 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..82d90f0 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::*; @@ -745,6 +746,9 @@ pub struct MessagesRequest { /// Optional list of stop sequences to end generation. #[serde(default, skip_serializing_if = "Vec::is_empty")] pub stop_sequences: Vec, + /// Optional request timeout. + #[serde(default)] + pub timeout: Option, } impl Default for MessagesRequest { @@ -759,6 +763,7 @@ impl Default for MessagesRequest { tools: Vec::new(), tool_choice: ToolChoice::default(), stop_sequences: Vec::new(), + timeout: None, } } } @@ -829,6 +834,11 @@ impl MessagesRequest { self } + pub fn with_timeout(mut self, timeout: Duration) -> Self { + self.timeout = Some(timeout); + self + } + pub fn add_system(&mut self, content: Content) { self.system.push(content); } @@ -991,13 +1001,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) = request.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 +1018,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) = request.timeout { + http_request = http_request.timeout(timeout); + } + let response = http_request.send().await?; let status = response.status(); From 91aeaaf5e0016b3d1287d17a9bfc9d459996abad Mon Sep 17 00:00:00 2001 From: Joe Fioti Date: Fri, 21 Feb 2025 09:58:40 -0500 Subject: [PATCH 2/2] moved timeout from request to client --- crates/misanthropy/src/lib.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/crates/misanthropy/src/lib.rs b/crates/misanthropy/src/lib.rs index 82d90f0..bc39fd7 100644 --- a/crates/misanthropy/src/lib.rs +++ b/crates/misanthropy/src/lib.rs @@ -746,9 +746,6 @@ pub struct MessagesRequest { /// Optional list of stop sequences to end generation. #[serde(default, skip_serializing_if = "Vec::is_empty")] pub stop_sequences: Vec, - /// Optional request timeout. - #[serde(default)] - pub timeout: Option, } impl Default for MessagesRequest { @@ -763,7 +760,6 @@ impl Default for MessagesRequest { tools: Vec::new(), tool_choice: ToolChoice::default(), stop_sequences: Vec::new(), - timeout: None, } } } @@ -834,11 +830,6 @@ impl MessagesRequest { self } - pub fn with_timeout(mut self, timeout: Duration) -> Self { - self.timeout = Some(timeout); - self - } - pub fn add_system(&mut self, content: Content) { self.system.push(content); } @@ -934,6 +925,7 @@ pub struct Anthropic { api_key: String, base_url: String, use_beta: bool, + timeout: Option, } impl Anthropic { @@ -944,6 +936,7 @@ impl Anthropic { api_key: api_key.to_string(), base_url: format!("https://{}", DEFAULT_API_DOMAIN), use_beta: true, + timeout: None, } } @@ -954,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 { @@ -1005,7 +1004,7 @@ impl Anthropic { .post(format!("{}/v1/messages", self.base_url)) .headers(self.create_headers()?) .json(&request); - if let Some(timeout) = request.timeout { + if let Some(timeout) = self.timeout { http_request = http_request.timeout(timeout); } let event_source = @@ -1022,7 +1021,7 @@ impl Anthropic { .post(format!("{}/v1/messages", self.base_url)) .headers(self.create_headers()?) .json(&request); - if let Some(timeout) = request.timeout { + if let Some(timeout) = self.timeout { http_request = http_request.timeout(timeout); } let response = http_request.send().await?;