Skip to main content

opendev_http/adapters/
base.rs

1//! Base trait for provider adapters.
2
3use serde_json::Value;
4
5/// Trait for converting between the internal Chat Completions format
6/// and provider-specific API formats.
7///
8/// Implementations handle provider quirks like:
9/// - Different message formats (Anthropic vs OpenAI)
10/// - Prompt caching headers/fields
11/// - Reasoning model parameters (o1/o3)
12/// - Image block normalization
13#[async_trait::async_trait]
14pub trait ProviderAdapter: Send + Sync + std::fmt::Debug {
15    /// Provider identifier (e.g., "openai", "anthropic").
16    fn provider_name(&self) -> &str;
17
18    /// Convert an internal Chat Completions payload to provider-specific format.
19    ///
20    /// The input is always in OpenAI Chat Completions format. The adapter
21    /// transforms it as needed for its provider's API.
22    fn convert_request(&self, payload: Value) -> Value;
23
24    /// Convert a provider-specific response back to Chat Completions format.
25    ///
26    /// The output should be in standard OpenAI Chat Completions response format
27    /// so downstream code can handle all providers uniformly.
28    fn convert_response(&self, response: Value) -> Value;
29
30    /// Get the API endpoint URL for this provider.
31    fn api_url(&self) -> &str;
32
33    /// Get required headers for this provider (e.g., api-version, anthropic-version).
34    fn extra_headers(&self) -> Vec<(String, String)> {
35        vec![]
36    }
37
38    /// Whether this adapter supports streaming responses.
39    fn supports_streaming(&self) -> bool {
40        false
41    }
42
43    /// Add streaming parameters to the request payload.
44    ///
45    /// Called before sending when streaming is requested. The adapter should
46    /// add provider-specific streaming flags (e.g., `stream: true`).
47    fn enable_streaming(&self, _payload: &mut Value) {}
48
49    /// Get the streaming API URL, if different from the regular API URL.
50    ///
51    /// Some providers use a different endpoint for streaming (e.g., Gemini
52    /// uses `streamGenerateContent` instead of `generateContent`). Returns
53    /// `None` to use the client's default URL.
54    fn streaming_url(&self, base_url: &str) -> Option<String> {
55        let _ = base_url;
56        None
57    }
58
59    /// Parse a single SSE event into a stream event.
60    ///
61    /// `event_type` is the SSE event name (from `event:` line).
62    /// `data` is the parsed JSON from the `data:` line.
63    fn parse_stream_event(
64        &self,
65        _event_type: &str,
66        _data: &Value,
67    ) -> Option<crate::streaming::StreamEvent> {
68        None
69    }
70}