codex_convert_proxy/providers/default.rs
1//! Default generic provider implementation.
2//!
3//! This provider is used as a fallback when the provider name is not found
4//! in the registry. It makes minimal assumptions about the provider,
5//! assuming most providers follow the OpenAI-compatible Chat API format.
6//!
7//! Unlike named providers (GLM, Kimi, etc.), `DefaultProvider` is **not**
8//! registered in the static factory registry. Instead, [`create_provider`]
9//! constructs it directly when no matching registry entry is found. This
10//! keeps the fallback mechanism separate from the user-facing provider
11//! namespace.
12
13use crate::providers::trait_::Provider;
14use crate::types::chat_api::{ChatRequest, ChatResponse, ChatStreamChunk};
15
16/// Default provider that makes minimal assumptions.
17///
18/// This provider assumes:
19/// - Standard OpenAI-compatible API path: `/chat/completions`
20/// (the `/v1` prefix comes from the backend URL's base_path)
21/// - Model names are passed through as-is
22/// - No special request/response transformations needed
23///
24/// Use this as a fallback for providers not explicitly supported.
25///
26/// The `backend_name` field preserves the backend name from the config
27/// (e.g., `"qwen"`, `"yi"`) so that logging and diagnostics can identify
28/// which backend a request was routed to, even though the provider
29/// implementation is the generic default.
30pub struct DefaultProvider {
31 /// The original backend name from config, preserved for diagnostics.
32 backend_name: String,
33}
34
35impl Default for DefaultProvider {
36 fn default() -> Self {
37 Self {
38 backend_name: "default".to_string(),
39 }
40 }
41}
42
43impl DefaultProvider {
44 /// Create a new DefaultProvider with the original backend name.
45 ///
46 /// The `backend_name` is the name the user specified in `config.json`
47 /// (e.g., `"qwen"`, `"yi-lightning"`). It is preserved for logging
48 /// and diagnostics; the provider type is always `"default"`.
49 pub fn new(backend_name: &str) -> Self {
50 Self {
51 backend_name: backend_name.to_lowercase(),
52 }
53 }
54}
55
56impl Provider for DefaultProvider {
57 /// Returns `"default"` to indicate this is the generic fallback provider.
58 fn name(&self) -> &'static str {
59 "default"
60 }
61
62 /// Returns the original backend name from config (e.g., `"qwen"`,
63 /// `"yi-lightning"`), making it easy to identify which backend a
64 /// request was routed to in logs and diagnostics.
65 fn display_name(&self) -> &str {
66 &self.backend_name
67 }
68
69 fn chat_completions_path(&self) -> String {
70 // Standard OpenAI-compatible path (without /v1 prefix)
71 "/chat/completions".to_string()
72 }
73
74 // No transformations - pass through as-is
75 fn transform_request(&self, _request: &mut ChatRequest) {}
76
77 fn transform_response(&self, _response: &mut ChatResponse) {}
78
79 fn transform_stream_chunk(&self, _chunk: &mut ChatStreamChunk) {}
80}