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}