Skip to main content

simple_agent_type/
lib.rs

1//! Core types and traits for SimpleAgents.
2//!
3//! This crate provides all foundational types, traits, and error definitions
4//! shared across the SimpleAgents project. It is a pure types crate with no
5//! runtime, HTTP, or I/O dependencies.
6//!
7//! # Architecture
8//!
9//! SimpleAgents follows a trait-based architecture:
10//!
11//! - **Provider**: Trait for LLM provider implementations
12//! - **Cache**: Trait for caching responses
13//! - **RoutingStrategy**: Trait for provider selection
14//!
15//! # Main Types
16//!
17//! - [`Message`]: Role-based conversation messages
18//! - [`CompletionRequest`]: Unified request format
19//! - [`CompletionResponse`]: Unified response format
20//! - [`ApiKey`]: Secure API key handling
21//!
22//! # Example
23//!
24//! ```
25//! use simple_agent_type::prelude::*;
26//!
27//! // Create a request
28//! let request = CompletionRequest::builder()
29//!     .model("gpt-4")
30//!     .message(Message::user("Hello!"))
31//!     .temperature(0.7)
32//!     .build()
33//!     .unwrap();
34//!
35//! // Access request properties
36//! assert_eq!(request.model, "gpt-4");
37//! assert_eq!(request.messages.len(), 1);
38//! ```
39//!
40//! # Features
41//!
42//! - **Type Safety**: Strong types prevent common errors
43//! - **Transparency**: All transformations tracked via [`CoercionFlag`]
44//! - **Security**: API keys never logged ([`ApiKey`])
45//! - **Validation**: Early validation with clear errors
46//! - **Async**: All traits use `async_trait`
47
48#![deny(missing_docs)]
49#![deny(unsafe_code)]
50
51// Core modules
52pub mod cache;
53pub mod coercion;
54pub mod config;
55pub mod error;
56pub mod message;
57pub mod provider;
58pub mod request;
59pub mod response;
60pub mod router;
61pub mod validation;
62
63// Re-export commonly used types at crate root
64pub use error::{HealingError, ProviderError, Result, SimpleAgentsError, ValidationError};
65
66/// Prelude module for convenient imports.
67///
68/// # Example
69/// ```
70/// use simple_agent_type::prelude::*;
71///
72/// let msg = Message::user("Hello!");
73/// let request = CompletionRequest::builder()
74///     .model("gpt-4")
75///     .message(msg)
76///     .build()
77///     .unwrap();
78/// ```
79pub mod prelude {
80    // Messages
81    pub use crate::message::{Message, Role};
82
83    // Requests and responses
84    pub use crate::request::{CompletionRequest, CompletionRequestBuilder};
85    pub use crate::response::{
86        ChoiceDelta, CompletionChoice, CompletionChunk, CompletionResponse, FinishReason,
87        MessageDelta, Usage,
88    };
89
90    // Errors
91    pub use crate::error::{
92        HealingError, ProviderError, Result, SimpleAgentsError, ValidationError,
93    };
94
95    // Validation
96    pub use crate::validation::ApiKey;
97
98    // Configuration
99    pub use crate::config::{Capabilities, HealingConfig, ProviderConfig, RetryConfig};
100
101    // Coercion
102    pub use crate::coercion::{CoercionFlag, CoercionResult};
103
104    // Traits
105    pub use crate::cache::Cache;
106    pub use crate::provider::Provider;
107    pub use crate::router::RoutingStrategy;
108
109    // Provider types
110    pub use crate::provider::{ProviderRequest, ProviderResponse};
111
112    // Router types
113    pub use crate::router::{ProviderHealth, ProviderMetrics, RoutingMode};
114}
115
116#[cfg(test)]
117mod tests {
118    use super::prelude::*;
119
120    #[test]
121    fn test_prelude_imports() {
122        // Test that all major types are importable
123        let _msg = Message::user("test");
124        let _request = CompletionRequest::builder()
125            .model("test")
126            .message(Message::user("test"))
127            .build()
128            .unwrap();
129    }
130
131    #[test]
132    fn test_error_conversion() {
133        let validation_err = ValidationError::new("test");
134        let _agents_err: SimpleAgentsError = validation_err.into();
135    }
136
137    #[test]
138    fn test_api_key_security() {
139        let key = ApiKey::new("sk-1234567890abcdef1234567890").unwrap();
140        let debug = format!("{:?}", key);
141        assert!(debug.contains("REDACTED"));
142    }
143
144    #[test]
145    fn test_coercion_transparency() {
146        let result = CoercionResult::new(42).with_flag(CoercionFlag::StrippedMarkdown);
147        assert!(result.was_coerced());
148        assert_eq!(result.flags.len(), 1);
149    }
150
151    #[test]
152    fn test_builder_pattern() {
153        let request = CompletionRequest::builder()
154            .model("gpt-4")
155            .message(Message::user("Hello"))
156            .temperature(0.7)
157            .build()
158            .unwrap();
159
160        assert_eq!(request.model, "gpt-4");
161        assert_eq!(request.temperature, Some(0.7));
162    }
163
164    #[test]
165    fn test_response_helper() {
166        let response = CompletionResponse {
167            id: "resp_123".to_string(),
168            model: "gpt-4".to_string(),
169            choices: vec![CompletionChoice {
170                index: 0,
171                message: Message::assistant("Hello!"),
172                finish_reason: FinishReason::Stop,
173                logprobs: None,
174            }],
175            usage: Usage::new(10, 5),
176            created: None,
177            provider: None,
178            healing_metadata: None,
179        };
180
181        assert_eq!(response.content(), Some("Hello!"));
182    }
183
184    #[test]
185    fn test_all_types_send_sync() {
186        fn assert_send_sync<T: Send + Sync>() {}
187
188        // Core types
189        assert_send_sync::<Message>();
190        assert_send_sync::<CompletionRequest>();
191        assert_send_sync::<CompletionResponse>();
192
193        // Config types
194        assert_send_sync::<RetryConfig>();
195        assert_send_sync::<HealingConfig>();
196        assert_send_sync::<Capabilities>();
197
198        // Coercion types
199        assert_send_sync::<CoercionFlag>();
200        assert_send_sync::<CoercionResult<String>>();
201
202        // Provider types
203        assert_send_sync::<ProviderRequest>();
204        assert_send_sync::<ProviderResponse>();
205    }
206}