From 92ef2c9b06fba197e43da7c42d86bfdd0b743faa Mon Sep 17 00:00:00 2001 From: sawradip Date: Wed, 19 Nov 2025 20:17:54 +0600 Subject: [PATCH 1/4] refactor: clean up whitespace and formatting in example files - Adjusted formatting in async_example.rs, direct_construction_omitted.rs, and direct_construction.rs for consistency. - Improved readability by adding line breaks and aligning method calls. - Removed unnecessary whitespace in sync_example.rs and test_deserialize.rs. - Enhanced code clarity in blocking.rs and rest_client.rs by refining method formatting. - Cleaned up whitespace in various utility and type files for better maintainability. --- .../runagent/examples/async_example.rs | 6 +- .../runagent/examples/direct_construction.rs | 8 +- .../examples/direct_construction_omitted.rs | 8 +- .../runagent/examples/sync_example.rs | 3 +- .../runagent/examples/test_deserialize.rs | 4 +- runagent-rust/runagent/src/blocking.rs | 12 +- runagent-rust/runagent/src/client/mod.rs | 4 +- .../runagent/src/client/rest_client.rs | 124 +++++++++++------- .../runagent/src/client/runagent_client.rs | 82 +++++++----- .../runagent/src/client/socket_client.rs | 57 ++++---- runagent-rust/runagent/src/constants.rs | 1 - runagent-rust/runagent/src/db/mod.rs | 1 - runagent-rust/runagent/src/db/service.rs | 19 ++- runagent-rust/runagent/src/lib.rs | 26 ++-- runagent-rust/runagent/src/types/errors.rs | 2 +- runagent-rust/runagent/src/types/mod.rs | 2 +- runagent-rust/runagent/src/types/responses.rs | 13 +- runagent-rust/runagent/src/types/schema.rs | 21 ++- runagent-rust/runagent/src/utils/config.rs | 84 +++++++----- runagent-rust/runagent/src/utils/mod.rs | 2 +- .../runagent/src/utils/serializer.rs | 88 +++++++++---- 21 files changed, 335 insertions(+), 232 deletions(-) diff --git a/runagent-rust/runagent/examples/async_example.rs b/runagent-rust/runagent/examples/async_example.rs index 057a2a7..80537f9 100644 --- a/runagent-rust/runagent/examples/async_example.rs +++ b/runagent-rust/runagent/examples/async_example.rs @@ -16,12 +16,12 @@ async fn main() -> runagent::RunAgentResult<()> { RunAgentClientConfig::new(agent_id, entrypoint_tag) .with_local(true) .with_address("127.0.0.1", 8452) - .with_enable_registry(false) // Skip DB lookup since we have explicit address - ).await?; + .with_enable_registry(false), // Skip DB lookup since we have explicit address + ) + .await?; let response = client.run(&[("message", json!("Hello!"))]).await?; println!("Response: {}", response); Ok(()) } - diff --git a/runagent-rust/runagent/examples/direct_construction.rs b/runagent-rust/runagent/examples/direct_construction.rs index 5f8aaf7..4faa894 100644 --- a/runagent-rust/runagent/examples/direct_construction.rs +++ b/runagent-rust/runagent/examples/direct_construction.rs @@ -11,18 +11,20 @@ async fn main() -> runagent::RunAgentResult<()> { let client = RunAgentClient::new(runagent::RunAgentClientConfig { agent_id: "a6977384-6c88-40dc-a629-e6bf077786ae".to_string(), entrypoint_tag: "minimal".to_string(), - api_key: Some("rau_b4dcebdef6386726b08971a1cc968d8a2b77c5834d30f3f5a43bddf065cd95cb".to_string()), + api_key: Some( + "rau_b4dcebdef6386726b08971a1cc968d8a2b77c5834d30f3f5a43bddf065cd95cb".to_string(), + ), base_url: Some("http://localhost:8333/".to_string()), local: None, host: None, port: None, extra_params: None, enable_registry: None, - }).await?; + }) + .await?; let response = client.run(&[("message", json!("Hello!"))]).await?; println!("Response: {}", response); Ok(()) } - diff --git a/runagent-rust/runagent/examples/direct_construction_omitted.rs b/runagent-rust/runagent/examples/direct_construction_omitted.rs index 0587f26..a81365a 100644 --- a/runagent-rust/runagent/examples/direct_construction_omitted.rs +++ b/runagent-rust/runagent/examples/direct_construction_omitted.rs @@ -11,14 +11,16 @@ async fn main() -> runagent::RunAgentResult<()> { let client = RunAgentClient::new(runagent::RunAgentClientConfig { agent_id: "a6977384-6c88-40dc-a629-e6bf077786ae".to_string(), entrypoint_tag: "minimal".to_string(), - api_key: Some("rau_b4dcebdef6386726b08971a1cc968d8a2b77c5834d30f3f5a43bddf065cd95cb".to_string()), + api_key: Some( + "rau_b4dcebdef6386726b08971a1cc968d8a2b77c5834d30f3f5a43bddf065cd95cb".to_string(), + ), base_url: Some("http://localhost:8333/".to_string()), ..runagent::RunAgentClientConfig::default() // Omits all None fields - }).await?; + }) + .await?; let response = client.run(&[("message", json!("Hello!"))]).await?; println!("Response: {}", response); Ok(()) } - diff --git a/runagent-rust/runagent/examples/sync_example.rs b/runagent-rust/runagent/examples/sync_example.rs index e288a49..a4efc1b 100644 --- a/runagent-rust/runagent/examples/sync_example.rs +++ b/runagent-rust/runagent/examples/sync_example.rs @@ -16,7 +16,7 @@ fn main() -> runagent::RunAgentResult<()> { RunAgentClientConfig::new(agent_id, entrypoint_tag) .with_local(true) .with_address("127.0.0.1", 8452) - .with_enable_registry(false) // Skip DB lookup since we have explicit address + .with_enable_registry(false), // Skip DB lookup since we have explicit address )?; let response = client.run(&[("message", json!("Hello!"))])?; @@ -24,4 +24,3 @@ fn main() -> runagent::RunAgentResult<()> { println!("Response: {}", response); Ok(()) } - diff --git a/runagent-rust/runagent/examples/test_deserialize.rs b/runagent-rust/runagent/examples/test_deserialize.rs index a7c584c..0424da4 100644 --- a/runagent-rust/runagent/examples/test_deserialize.rs +++ b/runagent-rust/runagent/examples/test_deserialize.rs @@ -3,13 +3,13 @@ use serde_json::json; fn main() { let serializer = CoreSerializer::new(10.0).unwrap(); - + // Test the exact structure we're getting let test_response = json!({ "payload": "\"Hello, world!\"", "type": "string" }); - + println!("Input: {}", test_response); let result = serializer.deserialize_object(test_response).unwrap(); println!("Result: {}", result); diff --git a/runagent-rust/runagent/src/blocking.rs b/runagent-rust/runagent/src/blocking.rs index 7fd5763..3dca1a4 100644 --- a/runagent-rust/runagent/src/blocking.rs +++ b/runagent-rust/runagent/src/blocking.rs @@ -98,10 +98,7 @@ impl RunAgentClient { /// Ok(()) /// } /// ``` - pub fn run_stream( - &self, - input_kwargs: &[(&str, Value)], - ) -> RunAgentResult { + pub fn run_stream(&self, input_kwargs: &[(&str, Value)]) -> RunAgentResult { let stream = self.runtime.block_on(self.inner.run_stream(input_kwargs))?; Ok(BlockingStream::new(stream)) } @@ -193,9 +190,9 @@ impl BlockingStream { use futures::StreamExt; use std::sync::mpsc; use std::thread; - + let (tx, rx) = mpsc::channel(); - + // Spawn a background task that continuously polls the stream let handle = thread::spawn(move || { // Create a new runtime for the background thread @@ -209,7 +206,7 @@ impl BlockingStream { } }); }); - + Self { receiver: rx, _handle: handle, @@ -224,4 +221,3 @@ impl Iterator for BlockingStream { self.receiver.recv().ok() } } - diff --git a/runagent-rust/runagent/src/client/mod.rs b/runagent-rust/runagent/src/client/mod.rs index 612b88f..3e0a53d 100644 --- a/runagent-rust/runagent/src/client/mod.rs +++ b/runagent-rust/runagent/src/client/mod.rs @@ -5,6 +5,6 @@ pub mod runagent_client; pub mod socket_client; // Re-export the main client -pub use runagent_client::{RunAgentClient, RunAgentClientConfig}; pub use rest_client::RestClient; -pub use socket_client::SocketClient; \ No newline at end of file +pub use runagent_client::{RunAgentClient, RunAgentClientConfig}; +pub use socket_client::SocketClient; diff --git a/runagent-rust/runagent/src/client/rest_client.rs b/runagent-rust/runagent/src/client/rest_client.rs index cba77ab..5632627 100644 --- a/runagent-rust/runagent/src/client/rest_client.rs +++ b/runagent-rust/runagent/src/client/rest_client.rs @@ -43,11 +43,7 @@ impl RestClient { /// Create a default REST client using configuration pub fn default() -> RunAgentResult { let config = Config::load()?; - Self::new( - &config.base_url(), - config.api_key(), - Some("/api/v1"), - ) + Self::new(&config.base_url(), config.api_key(), Some("/api/v1")) } fn get_url(&self, path: &str) -> RunAgentResult { @@ -58,7 +54,7 @@ impl RestClient { async fn handle_response(&self, response: Response) -> RunAgentResult { let status = response.status(); - + if status.is_success() { let json: Value = response.json().await?; Ok(json) @@ -97,12 +93,15 @@ impl RestClient { }; // Check if error message contains permission/403 info even if status is 500 - if error_msg.contains("permission") || error_msg.contains("403") || error_msg.contains("do not have permission") { + if error_msg.contains("permission") + || error_msg.contains("403") + || error_msg.contains("do not have permission") + { return Err(RunAgentError::authentication(format!( "Access denied: {}. This usually means:\n - The agent doesn't belong to your account\n - Your API key doesn't have permission to access this agent\n - The agent ID is incorrect", error_msg ))); } - + match status.as_u16() { 401 => Err(RunAgentError::authentication(error_msg)), 403 => Err(RunAgentError::authentication(format!( @@ -124,13 +123,12 @@ impl RestClient { params: Option<&HashMap>, ) -> RunAgentResult { let mut url = self.get_url(path)?; - + // Add API key as token query parameter if available (matching WebSocket behavior) if let Some(ref api_key) = self.api_key { - url.query_pairs_mut() - .append_pair("token", api_key); + url.query_pairs_mut().append_pair("token", api_key); } - + let mut request_builder = self.client.request(method, url); // Add query parameters @@ -147,7 +145,8 @@ impl RestClient { // Add Authorization header if API key is available if let Some(ref api_key) = self.api_key { - request_builder = request_builder.header("Authorization", format!("Bearer {}", api_key)); + request_builder = + request_builder.header("Authorization", format!("Bearer {}", api_key)); } let response = request_builder.send().await?; @@ -202,8 +201,13 @@ impl RestClient { let path = format!("agents/{}/run", agent_id); let url = self.get_url(&path)?; - tracing::debug!("Running agent {} with entrypoint {} at {}", agent_id, entrypoint_tag, url); - + tracing::debug!( + "Running agent {} with entrypoint {} at {}", + agent_id, + entrypoint_tag, + url + ); + self.post(&path, &data).await .map_err(|e| { if e.category() == "validation" && e.to_string().contains("Not found") { @@ -265,7 +269,11 @@ impl RestClient { } else if let Some(msg) = error_obj.as_str() { ("UNKNOWN_ERROR".to_string(), msg.to_string(), None) } else { - ("UNKNOWN_ERROR".to_string(), "Failed to retrieve agent architecture".to_string(), None) + ( + "UNKNOWN_ERROR".to_string(), + "Failed to retrieve agent architecture".to_string(), + None, + ) } } else { ( @@ -298,39 +306,45 @@ impl RestClient { /// Validate API connection pub async fn validate_api_connection(&self) -> RunAgentResult { match self.health_check().await { - Ok(_response) => { - let mut result = serde_json::json!({ - "success": true, - "api_connected": true, - "base_url": self.base_url - }); - - if self.api_key.is_some() { - // Test authentication if API key is provided - match self.get_local_db_limits().await { - Ok(limits_result) => { - result["api_authenticated"] = limits_result.get("api_validated").unwrap_or(&Value::Bool(false)).clone(); - result["enhanced_limits"] = limits_result.get("enhanced_limits").unwrap_or(&Value::Bool(false)).clone(); - } - Err(_) => { - result["api_authenticated"] = Value::Bool(false); - result["enhanced_limits"] = Value::Bool(false); - } - } - } else { + Ok(_response) => { + let mut result = serde_json::json!({ + "success": true, + "api_connected": true, + "base_url": self.base_url + }); + + if self.api_key.is_some() { + // Test authentication if API key is provided + match self.get_local_db_limits().await { + Ok(limits_result) => { + result["api_authenticated"] = limits_result + .get("api_validated") + .unwrap_or(&Value::Bool(false)) + .clone(); + result["enhanced_limits"] = limits_result + .get("enhanced_limits") + .unwrap_or(&Value::Bool(false)) + .clone(); + } + Err(_) => { result["api_authenticated"] = Value::Bool(false); result["enhanced_limits"] = Value::Bool(false); - result["message"] = Value::String("No API key provided".to_string()); } - - Ok(result) } - Err(e) => Ok(serde_json::json!({ - "success": false, - "api_connected": false, - "error": format!("API health check failed: {}", e) - })), + } else { + result["api_authenticated"] = Value::Bool(false); + result["enhanced_limits"] = Value::Bool(false); + result["message"] = Value::String("No API key provided".to_string()); } + + Ok(result) + } + Err(e) => Ok(serde_json::json!({ + "success": false, + "api_connected": false, + "error": format!("API health check failed: {}", e) + })), + } } /// Get local database limits from backend API @@ -350,12 +364,22 @@ impl RestClient { match self.get("limits/agents").await { Ok(response) => { - let max_agents = response.get("max_agents").and_then(|v| v.as_i64()).unwrap_or(5); + let max_agents = response + .get("max_agents") + .and_then(|v| v.as_i64()) + .unwrap_or(5); let enhanced = max_agents > 5; let unlimited = max_agents == -1; if enhanced { - tracing::info!("Enhanced limits active: {} agents", if unlimited { "unlimited".to_string() } else { max_agents.to_string() }); + tracing::info!( + "Enhanced limits active: {} agents", + if unlimited { + "unlimited".to_string() + } else { + max_agents.to_string() + } + ); } Ok(serde_json::json!({ @@ -404,8 +428,10 @@ impl RestClient { // For now, return a placeholder let _folder_path = folder_path; let _metadata = metadata; - - Err(RunAgentError::generic("Upload functionality not yet implemented")) + + Err(RunAgentError::generic( + "Upload functionality not yet implemented", + )) } /// Start a remote agent @@ -449,4 +475,4 @@ mod tests { let client = RestClient::new("http://localhost:8000", None, None); assert!(client.is_ok()); } -} \ No newline at end of file +} diff --git a/runagent-rust/runagent/src/client/runagent_client.rs b/runagent-rust/runagent/src/client/runagent_client.rs index ba840a1..c4eed4f 100644 --- a/runagent-rust/runagent/src/client/runagent_client.rs +++ b/runagent-rust/runagent/src/client/runagent_client.rs @@ -29,14 +29,14 @@ pub struct RunAgentClient { } /// Configuration for creating a RunAgent client -/// +/// /// All fields except `agent_id` and `entrypoint_tag` are optional. -/// +/// /// # Direct Construction -/// +/// /// ```rust,no_run /// use runagent::{RunAgentClient, RunAgentClientConfig}; -/// +/// /// #[tokio::main] /// async fn main() -> runagent::RunAgentResult<()> { /// let client = RunAgentClient::new(RunAgentClientConfig { @@ -53,13 +53,13 @@ pub struct RunAgentClient { /// Ok(()) /// } /// ``` -/// +/// /// # Builder Pattern (Alternative) -/// +/// /// ```rust,no_run /// use runagent::{RunAgentClient, RunAgentClientConfig}; /// use std::env; -/// +/// /// #[tokio::main] /// async fn main() -> runagent::RunAgentResult<()> { /// let client = RunAgentClient::new( @@ -109,12 +109,12 @@ impl RunAgentClientConfig { } /// Create a config with defaults for optional fields - /// + /// /// This allows you to use `..RunAgentClientConfig::default()` syntax /// to omit None values when constructing directly. pub fn default() -> Self { Self { - agent_id: String::new(), // Dummy - will be overridden + agent_id: String::new(), // Dummy - will be overridden entrypoint_tag: String::new(), // Dummy - will be overridden local: None, host: None, @@ -166,15 +166,15 @@ impl RunAgentClientConfig { impl RunAgentClient { /// Create a new RunAgent client from configuration - /// + /// /// This is the single entry point for creating clients. - /// + /// /// # Examples - /// + /// /// ```rust,no_run /// use runagent::{RunAgentClient, RunAgentClientConfig}; /// use std::env; - /// + /// /// #[tokio::main] /// async fn main() -> runagent::RunAgentResult<()> { /// // Local agent with explicit address @@ -193,10 +193,10 @@ impl RunAgentClient { /// ``` pub async fn new(config: RunAgentClientConfig) -> RunAgentResult { use crate::constants::{DEFAULT_BASE_URL, ENV_RUNAGENT_API_KEY, ENV_RUNAGENT_BASE_URL}; - + let local = config.local.unwrap_or(false); let enable_registry = config.enable_registry.unwrap_or(local); - + // Resolve host/port for local agents let (host, port) = if local { // If host/port provided, use them @@ -208,7 +208,11 @@ impl RunAgentClient { { let db_service = DatabaseService::new(None).await?; if let Some(agent_info) = db_service.get_agent(&config.agent_id).await? { - tracing::info!("🔍 Found agent in database: {}:{}", agent_info.host, agent_info.port); + tracing::info!( + "🔍 Found agent in database: {}:{}", + agent_info.host, + agent_info.port + ); (Some(agent_info.host), Some(agent_info.port as u16)) } else { (config.host.clone(), config.port) @@ -226,14 +230,15 @@ impl RunAgentClient { }; // Resolve API key (config > env var) - let api_key = config.api_key.or_else(|| { - std::env::var(ENV_RUNAGENT_API_KEY).ok() - }); + let api_key = config + .api_key + .or_else(|| std::env::var(ENV_RUNAGENT_API_KEY).ok()); // Resolve base URL (config > env var > default) - let base_url = config.base_url.or_else(|| { - std::env::var(ENV_RUNAGENT_BASE_URL).ok() - }).unwrap_or_else(|| DEFAULT_BASE_URL.to_string()); + let base_url = config + .base_url + .or_else(|| std::env::var(ENV_RUNAGENT_BASE_URL).ok()) + .unwrap_or_else(|| DEFAULT_BASE_URL.to_string()); if !local { tracing::info!("🌐 Connecting to remote agent at {}", base_url); @@ -302,7 +307,9 @@ impl RunAgentClient { } async fn get_agent_architecture_internal(&self) -> RunAgentResult { - self.rest_client.get_agent_architecture(&self.agent_id).await + self.rest_client + .get_agent_architecture(&self.agent_id) + .await } fn validate_entrypoint(&self) -> RunAgentResult<()> { @@ -369,7 +376,11 @@ impl RunAgentClient { ) .await?; - if response.get("success").and_then(|s| s.as_bool()).unwrap_or(false) { + if response + .get("success") + .and_then(|s| s.as_bool()) + .unwrap_or(false) + { // Process response data let mut payload: Option = None; @@ -379,7 +390,9 @@ impl RunAgentClient { // Check for generator object BEFORE processing (case-insensitive) if let Some(data_str) = data.as_str() { let lower_str = data_str.to_lowercase(); - if lower_str.contains("generator object") || lower_str.contains(" RunAgentResult { - self.rest_client.get_agent_architecture(&self.agent_id).await + self.rest_client + .get_agent_architecture(&self.agent_id) + .await } /// Check if the agent is available @@ -562,4 +584,4 @@ impl RunAgentClient { Ok((rest_client, socket_client)) } } -} \ No newline at end of file +} diff --git a/runagent-rust/runagent/src/client/socket_client.rs b/runagent-rust/runagent/src/client/socket_client.rs index 6520134..b29d81c 100644 --- a/runagent-rust/runagent/src/client/socket_client.rs +++ b/runagent-rust/runagent/src/client/socket_client.rs @@ -1,8 +1,6 @@ //! WebSocket client for streaming agent interactions -use crate::types::{ - RunAgentError, RunAgentResult, SafeMessage, MessageType, -}; +use crate::types::{MessageType, RunAgentError, RunAgentResult, SafeMessage}; use crate::utils::config::Config; use crate::utils::serializer::CoreSerializer; use futures::{SinkExt, Stream, StreamExt}; @@ -28,7 +26,7 @@ impl SocketClient { api_prefix: Option<&str>, ) -> RunAgentResult { let serializer = CoreSerializer::new(10.0)?; - + Ok(Self { base_socket_url: base_socket_url.trim_end_matches('/').to_string(), api_key, @@ -41,7 +39,7 @@ impl SocketClient { pub fn default() -> RunAgentResult { let config = Config::load()?; let base_url = config.base_url(); - + // Convert HTTP URL to WebSocket URL let ws_url = if base_url.starts_with("https://") { base_url.replace("https://", "wss://") @@ -57,12 +55,12 @@ impl SocketClient { fn get_websocket_url(&self, agent_id: &str, _entrypoint_tag: &str) -> RunAgentResult { let path = format!("agents/{}/run-stream", agent_id); let mut full_url = format!("{}{}/{}", self.base_socket_url, self.api_prefix, path); - + // Add API key as token parameter if available if let Some(ref api_key) = self.api_key { full_url = format!("{}?token={}", full_url, api_key); } - + Url::parse(&full_url) .map_err(|e| RunAgentError::validation(format!("Invalid WebSocket URL: {}", e))) } @@ -76,12 +74,13 @@ impl SocketClient { input_kwargs: &HashMap, ) -> RunAgentResult> + Send>>> { let url = self.get_websocket_url(agent_id, entrypoint_tag)?; - + tracing::debug!("Connecting to WebSocket: {}", url); // Connect to WebSocket - let (ws_stream, _) = connect_async(url).await - .map_err(|e| RunAgentError::connection(format!("WebSocket connection failed: {}", e)))?; + let (ws_stream, _) = connect_async(url).await.map_err(|e| { + RunAgentError::connection(format!("WebSocket connection failed: {}", e)) + })?; let (mut write, mut read) = ws_stream.split(); @@ -97,12 +96,16 @@ impl SocketClient { // Send the request data directly (matching Python SDK format) let serialized_msg = serde_json::to_string(&request_data)?; - write.send(Message::Text(serialized_msg)).await - .map_err(|e| RunAgentError::connection(format!("Failed to send start message: {}", e)))?; + write + .send(Message::Text(serialized_msg)) + .await + .map_err(|e| { + RunAgentError::connection(format!("Failed to send start message: {}", e)) + })?; // Clone serializer for use in async stream let serializer = self.serializer.clone(); - + // Create stream that processes incoming messages (matching Python SDK behavior) let stream = async_stream::stream! { while let Some(message) = read.next().await { @@ -112,7 +115,7 @@ impl SocketClient { match serde_json::from_str::(&text) { Ok(msg) => { let message_type = msg.get("type").and_then(|v| v.as_str()); - + match message_type { Some("status") => { if let Some(status) = msg.get("status").and_then(|v| v.as_str()) { @@ -136,7 +139,7 @@ impl SocketClient { if let Some(content) = msg.get("content") { // Use common deserializer preparation logic (handles JSON strings) let prepared = serializer.prepare_for_deserialization(content.clone()); - + // Deserialize using the common serializer (handles {type, payload} structure) match serializer.deserialize_object(prepared) { Ok(deserialized) => yield Ok(deserialized), @@ -183,9 +186,10 @@ impl SocketClient { /// Send a ping message to test connection pub async fn ping(&self, agent_id: &str, entrypoint_tag: &str) -> RunAgentResult { let url = self.get_websocket_url(agent_id, entrypoint_tag)?; - - let (ws_stream, _) = connect_async(url).await - .map_err(|e| RunAgentError::connection(format!("WebSocket connection failed: {}", e)))?; + + let (ws_stream, _) = connect_async(url).await.map_err(|e| { + RunAgentError::connection(format!("WebSocket connection failed: {}", e)) + })?; let (mut write, mut read) = ws_stream.split(); @@ -197,14 +201,14 @@ impl SocketClient { ); let serialized_msg = self.serializer.serialize_message(&ping_msg)?; - write.send(Message::Text(serialized_msg)).await + write + .send(Message::Text(serialized_msg)) + .await .map_err(|e| RunAgentError::connection(format!("Failed to send ping: {}", e)))?; // Wait for pong - tokio::time::timeout( - std::time::Duration::from_secs(5), - read.next() - ).await + tokio::time::timeout(std::time::Duration::from_secs(5), read.next()) + .await .map_err(|_| RunAgentError::connection("Ping timeout".to_string()))? .ok_or_else(|| RunAgentError::connection("Connection closed during ping".to_string()))? .map_err(|e| RunAgentError::connection(format!("Ping failed: {}", e)))?; @@ -222,7 +226,10 @@ mod tests { let client = SocketClient::new("ws://localhost:8000", None, Some("/api/v1")).unwrap(); let url = client.get_websocket_url("test-agent", "generic").unwrap(); // Updated expected URL to match the actual implementation - assert_eq!(url.as_str(), "ws://localhost:8000/api/v1/agents/test-agent/run-stream"); + assert_eq!( + url.as_str(), + "ws://localhost:8000/api/v1/agents/test-agent/run-stream" + ); } #[test] @@ -238,4 +245,4 @@ mod tests { // This would test the URL conversion logic in a real implementation assert!(client.is_ok()); } -} \ No newline at end of file +} diff --git a/runagent-rust/runagent/src/constants.rs b/runagent-rust/runagent/src/constants.rs index 3c39eaa..ceeadfe 100644 --- a/runagent-rust/runagent/src/constants.rs +++ b/runagent-rust/runagent/src/constants.rs @@ -19,4 +19,3 @@ pub const DEFAULT_TIMEOUT_SECONDS: u64 = 300; /// Agent config file name (for reading agent configs, not for creating them) pub const AGENT_CONFIG_FILE_NAME: &str = "runagent.config.json"; - diff --git a/runagent-rust/runagent/src/db/mod.rs b/runagent-rust/runagent/src/db/mod.rs index 5fb6f94..0d11eef 100644 --- a/runagent-rust/runagent/src/db/mod.rs +++ b/runagent-rust/runagent/src/db/mod.rs @@ -7,4 +7,3 @@ pub mod service; pub use service::DatabaseService; - diff --git a/runagent-rust/runagent/src/db/service.rs b/runagent-rust/runagent/src/db/service.rs index 705c8a6..d9bd105 100644 --- a/runagent-rust/runagent/src/db/service.rs +++ b/runagent-rust/runagent/src/db/service.rs @@ -17,7 +17,7 @@ static LOCAL_CACHE_DIRECTORY: Lazy = Lazy::new(|| { if let Ok(env_path) = std::env::var(ENV_LOCAL_CACHE_DIRECTORY) { return PathBuf::from(env_path); } - + // Default to ~/.runagent dirs::home_dir() .unwrap_or_else(|| PathBuf::from(".")) @@ -43,20 +43,20 @@ pub struct DatabaseService { impl DatabaseService { /// Create a new database service pub async fn new(db_path: Option) -> RunAgentResult { - let db_path = db_path.unwrap_or_else(|| { - LOCAL_CACHE_DIRECTORY.join(DATABASE_FILE_NAME) - }); + let db_path = db_path.unwrap_or_else(|| LOCAL_CACHE_DIRECTORY.join(DATABASE_FILE_NAME)); // Ensure directory exists if let Some(parent) = db_path.parent() { - std::fs::create_dir_all(parent) - .map_err(|e| RunAgentError::database(format!("Failed to create db directory: {}", e)))?; + std::fs::create_dir_all(parent).map_err(|e| { + RunAgentError::database(format!("Failed to create db directory: {}", e)) + })?; } let database_url = format!("sqlite:{}", db_path.display()); - - let pool = SqlitePool::connect(&database_url).await - .map_err(|e| RunAgentError::database(format!("Failed to connect to database: {}", e)))?; + + let pool = SqlitePool::connect(&database_url).await.map_err(|e| { + RunAgentError::database(format!("Failed to connect to database: {}", e)) + })?; // Initialize database schema Self::init_schema(&pool).await?; @@ -129,4 +129,3 @@ impl Drop for DatabaseService { // Note: sqlx pool handles cleanup automatically } } - diff --git a/runagent-rust/runagent/src/lib.rs b/runagent-rust/runagent/src/lib.rs index 04d10ae..15d35f0 100644 --- a/runagent-rust/runagent/src/lib.rs +++ b/runagent-rust/runagent/src/lib.rs @@ -228,13 +228,13 @@ //! Err(e) => Err(e), //! } //! } -//! -//! fn some_operation() -> RunAgentResult { -//! Ok("test".to_string()) +//! +//! fn some_operation() -> RunAgentResult { +//! Ok("test".to_string()) //! } -//! -//! fn retry_operation() -> RunAgentResult<()> { -//! Ok(()) +//! +//! fn retry_operation() -> RunAgentResult<()> { +//! Ok(()) //! } //! ``` //! @@ -279,11 +279,11 @@ pub mod db; pub mod blocking; // Re-export commonly used types and functions -pub use client::{RunAgentClient, RunAgentClientConfig, RestClient, SocketClient}; +pub use client::{RestClient, RunAgentClient, RunAgentClientConfig, SocketClient}; pub use types::{RunAgentError, RunAgentResult}; // Re-export blocking client for convenience -pub use blocking::{RunAgentClient as BlockingRunAgentClient, BlockingStream}; +pub use blocking::{BlockingStream, RunAgentClient as BlockingRunAgentClient}; #[cfg(feature = "db")] pub use db::DatabaseService; @@ -306,7 +306,7 @@ pub fn init_logging() { tracing_subscriber::fmt() .with_env_filter( tracing_subscriber::EnvFilter::from_default_env() - .add_directive("runagent=info".parse().unwrap()) + .add_directive("runagent=info".parse().unwrap()), ) .init(); } @@ -430,13 +430,13 @@ impl RunAgentConfig { /// /// ```rust,no_run /// use runagent::prelude::*; -/// +/// /// // Now you have access to RunAgentClient, RunAgentError, etc. /// ``` pub mod prelude { - pub use crate::client::{RunAgentClient, RunAgentClientConfig, RestClient, SocketClient}; + pub use crate::client::{RestClient, RunAgentClient, RunAgentClientConfig, SocketClient}; pub use crate::types::{RunAgentError, RunAgentResult}; - + #[cfg(feature = "db")] pub use crate::db::DatabaseService; } @@ -468,4 +468,4 @@ mod tests { assert!(config.base_url.is_none()); assert!(!config.enable_logging); } -} \ No newline at end of file +} diff --git a/runagent-rust/runagent/src/types/errors.rs b/runagent-rust/runagent/src/types/errors.rs index ed75320..1889ac6 100644 --- a/runagent-rust/runagent/src/types/errors.rs +++ b/runagent-rust/runagent/src/types/errors.rs @@ -224,4 +224,4 @@ mod tests { assert!(error_string.contains("Server error")); assert!(error_string.contains("Internal server error")); } -} \ No newline at end of file +} diff --git a/runagent-rust/runagent/src/types/mod.rs b/runagent-rust/runagent/src/types/mod.rs index 52d0433..01c5b70 100644 --- a/runagent-rust/runagent/src/types/mod.rs +++ b/runagent-rust/runagent/src/types/mod.rs @@ -7,4 +7,4 @@ pub mod schema; // Re-export commonly used types pub use errors::{RunAgentError, RunAgentResult}; pub use responses::*; -pub use schema::*; \ No newline at end of file +pub use schema::*; diff --git a/runagent-rust/runagent/src/types/responses.rs b/runagent-rust/runagent/src/types/responses.rs index 495f9ac..54ef1b6 100644 --- a/runagent-rust/runagent/src/types/responses.rs +++ b/runagent-rust/runagent/src/types/responses.rs @@ -185,17 +185,20 @@ mod tests { #[test] fn test_api_response_with_message() { - let response = ApiResponse::success("data") - .with_message("Operation completed successfully"); + let response = + ApiResponse::success("data").with_message("Operation completed successfully"); assert!(response.success); - assert_eq!(response.message, Some("Operation completed successfully".to_string())); + assert_eq!( + response.message, + Some("Operation completed successfully".to_string()) + ); } #[test] fn test_paginated_response() { let items = vec!["item1", "item2", "item3"]; let response = PaginatedResponse::new(items, 10, 1, 5); - + assert_eq!(response.total, 10); assert_eq!(response.page, 1); assert_eq!(response.per_page, 5); @@ -215,4 +218,4 @@ mod tests { assert_eq!(chunk.chunk_id, "chunk-1"); assert!(!chunk.is_final); } -} \ No newline at end of file +} diff --git a/runagent-rust/runagent/src/types/schema.rs b/runagent-rust/runagent/src/types/schema.rs index 55b8f52..5642f59 100644 --- a/runagent-rust/runagent/src/types/schema.rs +++ b/runagent-rust/runagent/src/types/schema.rs @@ -1,5 +1,5 @@ //! Schema types for the RunAgent SDK -//! +//! //! These types mirror the Python SDK's Pydantic models use chrono::{DateTime, Utc}; @@ -169,11 +169,7 @@ pub struct SafeMessage { } impl SafeMessage { - pub fn new( - id: String, - message_type: MessageType, - data: serde_json::Value, - ) -> Self { + pub fn new(id: String, message_type: MessageType, data: serde_json::Value) -> Self { Self { id, message_type, @@ -201,15 +197,15 @@ impl SafeMessage { dict.insert("type".to_string(), serde_json::json!(self.message_type)); dict.insert("timestamp".to_string(), serde_json::json!(self.timestamp)); dict.insert("data".to_string(), self.data.clone()); - + if let Some(metadata) = &self.metadata { dict.insert("metadata".to_string(), serde_json::json!(metadata)); } - + if let Some(error) = &self.error { dict.insert("error".to_string(), serde_json::json!(error)); } - + dict } } @@ -341,7 +337,8 @@ mod tests { #[test] fn test_safe_message_with_error() { - let msg = SafeMessage::with_error("error-id".to_string(), "Something went wrong".to_string()); + let msg = + SafeMessage::with_error("error-id".to_string(), "Something went wrong".to_string()); assert_eq!(msg.id, "error-id"); assert!(matches!(msg.message_type, MessageType::Error)); assert!(msg.error.is_some()); @@ -366,9 +363,9 @@ mod tests { let json = serde_json::to_string(&entry_point).unwrap(); let deserialized: EntryPoint = serde_json::from_str(&json).unwrap(); - + assert_eq!(entry_point.file, deserialized.file); assert_eq!(entry_point.module, deserialized.module); assert_eq!(entry_point.tag, deserialized.tag); } -} \ No newline at end of file +} diff --git a/runagent-rust/runagent/src/utils/config.rs b/runagent-rust/runagent/src/utils/config.rs index 07703d0..f6c1faa 100644 --- a/runagent-rust/runagent/src/utils/config.rs +++ b/runagent-rust/runagent/src/utils/config.rs @@ -1,8 +1,6 @@ //! Configuration management for the RunAgent SDK -use crate::constants::{ - DEFAULT_BASE_URL, ENV_RUNAGENT_API_KEY, ENV_RUNAGENT_BASE_URL, -}; +use crate::constants::{DEFAULT_BASE_URL, ENV_RUNAGENT_API_KEY, ENV_RUNAGENT_BASE_URL}; use crate::types::{RunAgentError, RunAgentResult}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -88,7 +86,9 @@ impl Config { // Test authentication (placeholder - would make actual API call) if !config.test_authentication()? { - return Err(RunAgentError::authentication("Authentication failed with provided credentials")); + return Err(RunAgentError::authentication( + "Authentication failed with provided credentials", + )); } // Note: save parameter is ignored - configuration is stored in SQLite database @@ -116,10 +116,19 @@ impl Config { /// Get detailed configuration status pub fn get_status(&self) -> HashMap { let mut status = HashMap::new(); - - status.insert("configured".to_string(), serde_json::json!(self.is_configured())); - status.insert("authenticated".to_string(), serde_json::json!(self.is_authenticated())); - status.insert("api_key_set".to_string(), serde_json::json!(self.api_key.is_some())); + + status.insert( + "configured".to_string(), + serde_json::json!(self.is_configured()), + ); + status.insert( + "authenticated".to_string(), + serde_json::json!(self.is_authenticated()), + ); + status.insert( + "api_key_set".to_string(), + serde_json::json!(self.api_key.is_some()), + ); status.insert("base_url".to_string(), serde_json::json!(self.base_url)); status.insert("user_info".to_string(), serde_json::json!(self.user_info)); @@ -147,17 +156,20 @@ impl Config { config_content: &HashMap, ) -> RunAgentResult { use crate::constants::AGENT_CONFIG_FILE_NAME; - + let config_file = PathBuf::from(project_dir).join(AGENT_CONFIG_FILE_NAME); // Update existing config if it exists let mut final_config = if config_file.exists() { - let existing_content = fs::read_to_string(&config_file) - .map_err(|e| RunAgentError::config(format!("Failed to read existing config: {}", e)))?; - - let mut existing_config: HashMap = serde_json::from_str(&existing_content) - .map_err(|e| RunAgentError::config(format!("Failed to parse existing config: {}", e)))?; - + let existing_content = fs::read_to_string(&config_file).map_err(|e| { + RunAgentError::config(format!("Failed to read existing config: {}", e)) + })?; + + let mut existing_config: HashMap = + serde_json::from_str(&existing_content).map_err(|e| { + RunAgentError::config(format!("Failed to parse existing config: {}", e)) + })?; + // Merge configs, new values take precedence existing_config.extend(config_content.clone()); existing_config @@ -169,7 +181,7 @@ impl Config { if !final_config.contains_key("created_at") { final_config.insert( "created_at".to_string(), - serde_json::json!(chrono::Utc::now().format("%Y-%m-%d %H:%M:%S").to_string()) + serde_json::json!(chrono::Utc::now().format("%Y-%m-%d %H:%M:%S").to_string()), ); } @@ -184,9 +196,11 @@ impl Config { } /// Get agent configuration - pub fn get_agent_config(project_dir: &str) -> RunAgentResult>> { + pub fn get_agent_config( + project_dir: &str, + ) -> RunAgentResult>> { use crate::constants::AGENT_CONFIG_FILE_NAME; - + let config_file = PathBuf::from(project_dir).join(AGENT_CONFIG_FILE_NAME); if !config_file.exists() { @@ -202,7 +216,6 @@ impl Config { Ok(Some(config)) } - /// Save deployment information pub fn save_deployment_info( agent_id: &str, @@ -212,22 +225,27 @@ impl Config { .map_err(|e| RunAgentError::config(format!("Failed to get current directory: {}", e)))? .join(".deployments"); - fs::create_dir_all(&deployments_dir) - .map_err(|e| RunAgentError::config(format!("Failed to create deployments directory: {}", e)))?; + fs::create_dir_all(&deployments_dir).map_err(|e| { + RunAgentError::config(format!("Failed to create deployments directory: {}", e)) + })?; let info_file = deployments_dir.join(format!("{}.json", agent_id)); - - let content = serde_json::to_string_pretty(info) - .map_err(|e| RunAgentError::config(format!("Failed to serialize deployment info: {}", e)))?; - fs::write(&info_file, content) - .map_err(|e| RunAgentError::config(format!("Failed to write deployment info: {}", e)))?; + let content = serde_json::to_string_pretty(info).map_err(|e| { + RunAgentError::config(format!("Failed to serialize deployment info: {}", e)) + })?; + + fs::write(&info_file, content).map_err(|e| { + RunAgentError::config(format!("Failed to write deployment info: {}", e)) + })?; Ok(info_file.to_string_lossy().to_string()) } /// Get deployment information - pub fn get_deployment_info(agent_id: &str) -> RunAgentResult>> { + pub fn get_deployment_info( + agent_id: &str, + ) -> RunAgentResult>> { let deployments_dir = std::env::current_dir() .map_err(|e| RunAgentError::config(format!("Failed to get current directory: {}", e)))? .join(".deployments"); @@ -241,8 +259,10 @@ impl Config { let content = fs::read_to_string(&info_file) .map_err(|e| RunAgentError::config(format!("Failed to read deployment info: {}", e)))?; - let info: HashMap = serde_json::from_str(&content) - .map_err(|e| RunAgentError::config(format!("Failed to parse deployment info: {}", e)))?; + let info: HashMap = + serde_json::from_str(&content).map_err(|e| { + RunAgentError::config(format!("Failed to parse deployment info: {}", e)) + })?; Ok(Some(info)) } @@ -278,7 +298,7 @@ mod tests { Some("api.example.com".to_string()), false, ); - + // This would test URL formatting in a real implementation // For now, we just verify the function doesn't panic assert!(config.is_err() || config.is_ok()); @@ -305,9 +325,9 @@ mod tests { fn test_status_generation() { let config = Config::default(); let status = config.get_status(); - + assert!(status.contains_key("configured")); assert!(status.contains_key("api_key_set")); assert!(status.contains_key("base_url")); } -} \ No newline at end of file +} diff --git a/runagent-rust/runagent/src/utils/mod.rs b/runagent-rust/runagent/src/utils/mod.rs index 7c3c3f5..a04b182 100644 --- a/runagent-rust/runagent/src/utils/mod.rs +++ b/runagent-rust/runagent/src/utils/mod.rs @@ -8,4 +8,4 @@ pub mod serializer; // Re-export commonly used utilities pub use config::Config; -pub use serializer::CoreSerializer; \ No newline at end of file +pub use serializer::CoreSerializer; diff --git a/runagent-rust/runagent/src/utils/serializer.rs b/runagent-rust/runagent/src/utils/serializer.rs index 098fb8a..05fa625 100644 --- a/runagent-rust/runagent/src/utils/serializer.rs +++ b/runagent-rust/runagent/src/utils/serializer.rs @@ -24,14 +24,17 @@ impl CoreSerializer { let json_str = serde_json::to_string(&serialized_data)?; if !self.check_size_limit(&json_str) { - tracing::warn!("Serialized object exceeds size limit: {} bytes", json_str.len()); + tracing::warn!( + "Serialized object exceeds size limit: {} bytes", + json_str.len() + ); } Ok(json_str) } /// Prepare value for deserialization - /// + /// /// If the value is a JSON string, parses it first. /// Otherwise returns the value as-is. /// This handles cases where responses come as JSON strings. @@ -48,19 +51,19 @@ impl CoreSerializer { } /// Deserialize JSON response to object - /// + /// /// Handles multiple response formats: /// 1. `{type, payload}` structure - extracts and deserializes payload /// 2. String payload - parses JSON string /// 3. Direct value - reconstructs nested JSON - /// + /// /// Handles multiple response formats including `{type, payload}` structures. pub fn deserialize_object(&self, json_resp: Value) -> RunAgentResult { // Handle {type, payload} structure if let Value::Object(ref map) = json_resp { if map.contains_key("type") && map.contains_key("payload") { let payload_val = map.get("payload").unwrap(); - + // If payload is a string, try to parse it as JSON if let Some(payload_str) = payload_val.as_str() { // The payload is a JSON-encoded string, parse it to get the actual value @@ -76,17 +79,17 @@ impl CoreSerializer { } } } - + // Payload is not a string - reconstruct it directly return self.reconstruct_nested_json(payload_val.clone()); } - + // Handle {content} structure (legacy format) if let Some(content) = map.get("content") { return self.reconstruct_nested_json(content.clone()); } } - + // If it's a string, try to parse it first if let Some(str_val) = json_resp.as_str() { match serde_json::from_str::(str_val) { @@ -94,7 +97,7 @@ impl CoreSerializer { Err(_) => return Ok(Value::String(str_val.to_string())), } } - + // Default: reconstruct nested JSON self.reconstruct_nested_json(json_resp) } @@ -102,21 +105,27 @@ impl CoreSerializer { /// Serialize SafeMessage to JSON string pub fn serialize_message(&self, message: &SafeMessage) -> RunAgentResult { let message_dict = message.to_dict(); - + // Deep serialize the data field to handle nested objects let mut serialized_dict = message_dict; if let Some(data) = serialized_dict.get("data") { serialized_dict.insert("data".to_string(), self.deep_serialize_value(data.clone())?); } - + if let Some(metadata) = serialized_dict.get("metadata") { - serialized_dict.insert("metadata".to_string(), self.deep_serialize_value(metadata.clone())?); + serialized_dict.insert( + "metadata".to_string(), + self.deep_serialize_value(metadata.clone())?, + ); } let json_str = serde_json::to_string(&serialized_dict)?; if !self.check_size_limit(&json_str) { - tracing::warn!("Serialized message exceeds size limit: {} bytes", json_str.len()); + tracing::warn!( + "Serialized message exceeds size limit: {} bytes", + json_str.len() + ); } Ok(json_str) @@ -125,19 +134,26 @@ impl CoreSerializer { /// Deserialize JSON string to SafeMessage pub fn deserialize_message(&self, json_str: &str) -> RunAgentResult { let deserialized_data: Value = serde_json::from_str(json_str)?; - - let obj = deserialized_data.as_object() + + let obj = deserialized_data + .as_object() .ok_or_else(|| RunAgentError::validation("JSON must deserialize to an object"))?; // Reconstruct nested JSON structures in data and metadata let mut message_data = obj.clone(); - + if let Some(data) = message_data.get("data") { - message_data.insert("data".to_string(), self.reconstruct_nested_json(data.clone())?); + message_data.insert( + "data".to_string(), + self.reconstruct_nested_json(data.clone())?, + ); } - + if let Some(metadata) = message_data.get("metadata") { - message_data.insert("metadata".to_string(), self.reconstruct_nested_json(metadata.clone())?); + message_data.insert( + "metadata".to_string(), + self.reconstruct_nested_json(metadata.clone())?, + ); } let safe_message: SafeMessage = serde_json::from_value(Value::Object(message_data.into()))?; @@ -175,7 +191,9 @@ impl CoreSerializer { fn value_to_string(&self, obj: &Value) -> String { match obj { Value::String(s) => s.clone(), - _ => serde_json::to_string(obj).unwrap_or_else(|_| format!("", obj)), + _ => { + serde_json::to_string(obj).unwrap_or_else(|_| format!("", obj)) + } } } @@ -188,9 +206,17 @@ impl CoreSerializer { } /// Create a serialization response with metadata - fn create_response_with_metadata(&self, strategy: &str, content: Value, original: &Value) -> HashMap { + fn create_response_with_metadata( + &self, + strategy: &str, + content: Value, + original: &Value, + ) -> HashMap { let mut response = self.create_response(strategy, content); - response.insert("type".to_string(), Value::String(self.get_value_type(original))); + response.insert( + "type".to_string(), + Value::String(self.get_value_type(original)), + ); response.insert("metadata".to_string(), self.extract_metadata(original)); response } @@ -210,12 +236,18 @@ impl CoreSerializer { /// Extract metadata about the value fn extract_metadata(&self, obj: &Value) -> Value { let mut metadata = HashMap::new(); - + let obj_str = serde_json::to_string(obj).unwrap_or_default(); let obj_size = obj_str.len(); - - metadata.insert("object_type".to_string(), Value::String(self.get_value_type(obj))); - metadata.insert("object_size".to_string(), Value::Number(serde_json::Number::from(obj_size))); + + metadata.insert( + "object_type".to_string(), + Value::String(self.get_value_type(obj)), + ); + metadata.insert( + "object_size".to_string(), + Value::Number(serde_json::Number::from(obj_size)), + ); metadata.insert("is_null".to_string(), Value::Bool(obj.is_null())); metadata.insert("is_array".to_string(), Value::Bool(obj.is_array())); metadata.insert("is_object".to_string(), Value::Bool(obj.is_object())); @@ -294,7 +326,7 @@ mod tests { fn test_object_serialization() { let serializer = CoreSerializer::new(10.0).unwrap(); let obj = serde_json::json!({"key": "value", "number": 42}); - + let result = serializer.serialize_object(obj); assert!(result.is_ok()); } @@ -358,4 +390,4 @@ mod tests { let reconstructed = result.unwrap(); assert_eq!(reconstructed, nested_data); } -} \ No newline at end of file +} From 1545c82bd2154db069e1dfe4cf01d95f3efbe2ab Mon Sep 17 00:00:00 2001 From: sawradip Date: Wed, 19 Nov 2025 20:31:51 +0600 Subject: [PATCH 2/4] refactor: enhance code quality and implement default traits - Updated tests to improve clarity by using a variable for VERSION check. - Added default implementations for RunAgentClientConfig and AgentInputArgs structs. - Applied clippy allows for better trait implementation guidance in REST and WebSocket client defaults. - Refined serializer methods to ensure proper JSON handling and recursion checks. --- .../runagent/src/client/rest_client.rs | 1 + .../runagent/src/client/runagent_client.rs | 23 +++++++++---------- .../runagent/src/client/socket_client.rs | 1 + runagent-rust/runagent/src/lib.rs | 4 +++- runagent-rust/runagent/src/types/schema.rs | 11 +-------- .../runagent/src/utils/serializer.rs | 5 +++- 6 files changed, 21 insertions(+), 24 deletions(-) diff --git a/runagent-rust/runagent/src/client/rest_client.rs b/runagent-rust/runagent/src/client/rest_client.rs index 5632627..8a788a4 100644 --- a/runagent-rust/runagent/src/client/rest_client.rs +++ b/runagent-rust/runagent/src/client/rest_client.rs @@ -41,6 +41,7 @@ impl RestClient { } /// Create a default REST client using configuration + #[allow(clippy::should_implement_trait)] pub fn default() -> RunAgentResult { let config = Config::load()?; Self::new(&config.base_url(), config.api_key(), Some("/api/v1")) diff --git a/runagent-rust/runagent/src/client/runagent_client.rs b/runagent-rust/runagent/src/client/runagent_client.rs index c4eed4f..4b50d29 100644 --- a/runagent-rust/runagent/src/client/runagent_client.rs +++ b/runagent-rust/runagent/src/client/runagent_client.rs @@ -92,12 +92,12 @@ pub struct RunAgentClientConfig { pub enable_registry: Option, } -impl RunAgentClientConfig { - /// Create a new config with required fields - pub fn new(agent_id: impl Into, entrypoint_tag: impl Into) -> Self { +#[allow(clippy::derivable_impls)] +impl Default for RunAgentClientConfig { + fn default() -> Self { Self { - agent_id: agent_id.into(), - entrypoint_tag: entrypoint_tag.into(), + agent_id: String::new(), // Dummy - will be overridden + entrypoint_tag: String::new(), // Dummy - will be overridden local: None, host: None, port: None, @@ -107,15 +107,14 @@ impl RunAgentClientConfig { enable_registry: None, } } +} - /// Create a config with defaults for optional fields - /// - /// This allows you to use `..RunAgentClientConfig::default()` syntax - /// to omit None values when constructing directly. - pub fn default() -> Self { +impl RunAgentClientConfig { + /// Create a new config with required fields + pub fn new(agent_id: impl Into, entrypoint_tag: impl Into) -> Self { Self { - agent_id: String::new(), // Dummy - will be overridden - entrypoint_tag: String::new(), // Dummy - will be overridden + agent_id: agent_id.into(), + entrypoint_tag: entrypoint_tag.into(), local: None, host: None, port: None, diff --git a/runagent-rust/runagent/src/client/socket_client.rs b/runagent-rust/runagent/src/client/socket_client.rs index b29d81c..b8690a6 100644 --- a/runagent-rust/runagent/src/client/socket_client.rs +++ b/runagent-rust/runagent/src/client/socket_client.rs @@ -36,6 +36,7 @@ impl SocketClient { } /// Create a default WebSocket client using configuration + #[allow(clippy::should_implement_trait)] pub fn default() -> RunAgentResult { let config = Config::load()?; let base_url = config.base_url(); diff --git a/runagent-rust/runagent/src/lib.rs b/runagent-rust/runagent/src/lib.rs index 15d35f0..fa3d28b 100644 --- a/runagent-rust/runagent/src/lib.rs +++ b/runagent-rust/runagent/src/lib.rs @@ -447,7 +447,9 @@ mod tests { #[test] fn test_version() { - assert!(!VERSION.is_empty()); + #[allow(clippy::const_is_empty)] + let is_not_empty = !VERSION.is_empty(); + assert!(is_not_empty); } #[test] diff --git a/runagent-rust/runagent/src/types/schema.rs b/runagent-rust/runagent/src/types/schema.rs index 5642f59..955b4fd 100644 --- a/runagent-rust/runagent/src/types/schema.rs +++ b/runagent-rust/runagent/src/types/schema.rs @@ -62,7 +62,7 @@ pub struct RunAgentConfig { } /// Input arguments for agent execution -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct AgentInputArgs { /// Input arguments list #[serde(default)] @@ -72,15 +72,6 @@ pub struct AgentInputArgs { pub input_kwargs: HashMap, } -impl Default for AgentInputArgs { - fn default() -> Self { - Self { - input_args: Vec::new(), - input_kwargs: HashMap::new(), - } - } -} - /// WebSocket action types #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] diff --git a/runagent-rust/runagent/src/utils/serializer.rs b/runagent-rust/runagent/src/utils/serializer.rs index 05fa625..4d919ed 100644 --- a/runagent-rust/runagent/src/utils/serializer.rs +++ b/runagent-rust/runagent/src/utils/serializer.rs @@ -156,7 +156,7 @@ impl CoreSerializer { ); } - let safe_message: SafeMessage = serde_json::from_value(Value::Object(message_data.into()))?; + let safe_message: SafeMessage = serde_json::from_value(Value::Object(message_data))?; Ok(safe_message) } @@ -178,6 +178,7 @@ impl CoreSerializer { } /// Check if a value is directly JSON serializable + #[allow(clippy::only_used_in_recursion)] fn is_json_serializable(&self, obj: &Value) -> bool { // JSON values are already serializable by definition match obj { @@ -256,6 +257,7 @@ impl CoreSerializer { } /// Deep serialize any value, handling nested structures + #[allow(clippy::only_used_in_recursion)] fn deep_serialize_value(&self, value: Value) -> RunAgentResult { match value { Value::Object(map) => { @@ -277,6 +279,7 @@ impl CoreSerializer { } /// Reconstruct nested JSON structures + #[allow(clippy::only_used_in_recursion)] fn reconstruct_nested_json(&self, data: Value) -> RunAgentResult { match data { Value::Object(ref map) => { From 125e3b1412707e27b3c30a4d269f7d0fec900e55 Mon Sep 17 00:00:00 2001 From: sawradip Date: Wed, 19 Nov 2025 20:32:18 +0600 Subject: [PATCH 3/4] chore: bump version to v0.1.41 - Updated all SDK versions to 0.1.41 --- pyproject.toml | 6 +++--- runagent-go/version.go | 2 +- runagent-rust/runagent/Cargo.toml | 2 +- runagent-ts/package-lock.json | 4 ++-- runagent-ts/package.json | 2 +- runagent/__init__.py | 2 +- runagent/__version__.py | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index edc3507..4dbcb64 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "hatchling.build" [project] name = "runagent" -version = "0.1.40" +version = "0.1.41" description = "A command-line tool and SDK for deploying, managing, and interacting with AI agents" readme = "README.md" requires-python = ">=3.9" @@ -103,7 +103,7 @@ line_length = 88 skip = ["docs"] [tool.mypy] -python_version = "0.1.40" +python_version = "0.1.41" warn_return_any = true warn_unused_configs = true disallow_untyped_defs = true @@ -159,7 +159,7 @@ fail_under = 80 [tool.ruff] line-length = 88 -target-version = "0.1.40" +target-version = "0.1.41" select = [ "E", # pycodestyle errors "W", # pycodestyle warnings diff --git a/runagent-go/version.go b/runagent-go/version.go index 74b1d12..9895c19 100644 --- a/runagent-go/version.go +++ b/runagent-go/version.go @@ -1,4 +1,4 @@ package runagent // Version represents the current version of the RunAgent Go SDK -const Version = "0.1.40" +const Version = "0.1.41" diff --git a/runagent-rust/runagent/Cargo.toml b/runagent-rust/runagent/Cargo.toml index 708daa6..aee3c59 100644 --- a/runagent-rust/runagent/Cargo.toml +++ b/runagent-rust/runagent/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "runagent" -version = "0.1.40" +version = "0.1.41" edition = "2021" description = "RunAgent SDK for Rust - Client SDK for interacting with deployed AI agents" license = "MIT" diff --git a/runagent-ts/package-lock.json b/runagent-ts/package-lock.json index d824f8c..8c2396c 100644 --- a/runagent-ts/package-lock.json +++ b/runagent-ts/package-lock.json @@ -1,12 +1,12 @@ { "name": "runagent", - "version": "0.1.40", + "version": "0.1.41", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "runagent", - "version": "0.1.40", + "version": "0.1.41", "dependencies": { "better-sqlite3": "^12.2.0" }, diff --git a/runagent-ts/package.json b/runagent-ts/package.json index 9a371c3..3d8a6b7 100644 --- a/runagent-ts/package.json +++ b/runagent-ts/package.json @@ -1,6 +1,6 @@ { "name": "runagent", - "version": "0.1.40", + "version": "0.1.41", "type": "module", "files": [ "dist" diff --git a/runagent/__init__.py b/runagent/__init__.py index 182cc57..401b012 100644 --- a/runagent/__init__.py +++ b/runagent/__init__.py @@ -5,7 +5,7 @@ built with frameworks like LangGraph, LangChain, and LlamaIndex. """ -__version__ = "0.1.40" +__version__ = "0.1.41" from .client import RunAgentClient diff --git a/runagent/__version__.py b/runagent/__version__.py index 5dc4aab..6e862d0 100644 --- a/runagent/__version__.py +++ b/runagent/__version__.py @@ -1 +1 @@ -__version__ = "0.1.40" +__version__ = "0.1.41" From d39f4724682742d7729abb616922ef68732c77e5 Mon Sep 17 00:00:00 2001 From: sawradip Date: Wed, 19 Nov 2025 20:32:18 +0600 Subject: [PATCH 4/4] docs: update changelog for v0.1.41 --- CHANGELOG.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54d877e..24a9f79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,20 +1,19 @@ # Changelog All notable changes to this project's latest version. -## [0.1.40] - 2025-11-19 +## [0.1.41] - 2025-11-19 -### Bug Fixes +### Documentation -- Update Go SDK version handling in release script and workflow +- Update changelog for v0.1.40 ### Miscellaneous Tasks -- Clean up release scripts and workflows -- Bump version to v0.1.40 +- Bump version to v0.1.41 ### Refactor -- Clean up whitespace in serializer tests -- Improve release process and add Go SDK +- Clean up whitespace and formatting in example files +- Enhance code quality and implement default traits