Skip to main content

bamboo_llm/protocol/
mod.rs

1//! Protocol conversion traits and types.
2//!
3//! This module defines the hub-and-spoke conversion architecture where all provider-specific
4//! types convert to/from internal types (agent_core).
5//!
6//! # Architecture
7//!
8//! ```text
9//! Provider Types (OpenAI, Anthropic, etc.)
10//!     ↕
11//! Internal Types (bamboo_domain::Message, ToolSchema)
12//! ```
13
14mod anthropic;
15mod errors;
16pub mod gemini;
17pub mod llama_cpp;
18mod openai;
19
20pub use anthropic::AnthropicProtocol;
21pub use errors::{ProtocolError, ProtocolResult};
22pub use gemini::GeminiProtocol;
23pub use openai::OpenAIProtocol;
24
25use bamboo_domain::Message;
26
27/// Trait for converting provider-specific types to internal types.
28///
29/// This is the "spoke → hub" conversion.
30pub trait FromProvider<T>: Sized {
31    /// Convert from provider-specific type to internal type.
32    fn from_provider(value: T) -> ProtocolResult<Self>;
33}
34
35/// Trait for converting internal types to provider-specific types.
36///
37/// This is the "hub → spoke" conversion.
38pub trait ToProvider<T>: Sized {
39    /// Convert from internal type to provider-specific type.
40    fn to_provider(&self) -> ProtocolResult<T>;
41}
42
43/// Batch conversion for multiple messages.
44pub trait FromProviderBatch<T>: Sized {
45    fn from_provider_batch(values: Vec<T>) -> ProtocolResult<Vec<Self>>;
46}
47
48/// Batch conversion for multiple messages.
49pub trait ToProviderBatch<T>: Sized {
50    fn to_provider_batch(&self) -> ProtocolResult<Vec<T>>;
51}
52
53// Implement batch conversion for specific types
54
55impl FromProviderBatch<crate::api::models::ChatMessage> for Message {
56    fn from_provider_batch(
57        values: Vec<crate::api::models::ChatMessage>,
58    ) -> ProtocolResult<Vec<Self>> {
59        values.into_iter().map(Self::from_provider).collect()
60    }
61}
62
63impl ToProviderBatch<crate::api::models::ChatMessage> for Vec<Message> {
64    fn to_provider_batch(&self) -> ProtocolResult<Vec<crate::api::models::ChatMessage>> {
65        self.iter().map(|msg| msg.to_provider()).collect()
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72
73    #[test]
74    fn test_trait_bounds() {
75        // This test just verifies the trait design compiles
76        fn assert_from_provider<T, U>()
77        where
78            T: FromProvider<U>,
79        {
80        }
81
82        fn assert_to_provider<T, U>()
83        where
84            T: ToProvider<U>,
85        {
86        }
87
88        // Ensure at least one concrete spoke type satisfies the bounds.
89        assert_from_provider::<Message, crate::api::models::ChatMessage>();
90        assert_to_provider::<Message, crate::api::models::ChatMessage>();
91    }
92}