Skip to main content

vtcode_core/llm/
client.rs

1use super::provider::LLMError;
2use super::types::LLMResponse;
3use crate::config::models::ModelId;
4use async_trait::async_trait;
5
6/// Unified LLM client trait.
7///
8/// Note: `backend_kind()` lives on [`LLMProvider`](super::provider::LLMProvider)
9/// rather than here, following the **single responsibility** principle — the
10/// provider knows its own backend identity.
11#[async_trait]
12pub trait LLMClient: Send + Sync {
13    async fn generate(&mut self, prompt: &str) -> Result<LLMResponse, LLMError>;
14    fn model_id(&self) -> &str;
15}
16
17/// Type-erased LLM client
18pub type AnyClient = Box<dyn LLMClient>;
19
20/// Create a client based on the model ID
21/// Uses the existing factory pattern from factory.rs
22pub fn make_client(api_key: String, model: ModelId) -> Result<AnyClient, LLMError> {
23    let model_id = model.to_string();
24    // Use factory to create provider
25    let provider = super::factory::create_provider_for_model(&model_id, api_key, None, None)?;
26
27    // Wrap in a simple client adapter
28    Ok(Box::new(ProviderClientAdapter { provider, model_id }))
29}
30
31/// Adapter to use LLMProvider as LLMClient
32///
33/// This allows using the provider interface through the simpler client trait.
34pub struct ProviderClientAdapter {
35    provider: Box<dyn super::provider::LLMProvider>,
36    model_id: String,
37}
38
39impl ProviderClientAdapter {
40    /// Create a new adapter wrapping an LLMProvider
41    pub fn new(provider: Box<dyn super::provider::LLMProvider>, model_id: String) -> Self {
42        Self { provider, model_id }
43    }
44}
45
46#[async_trait]
47impl LLMClient for ProviderClientAdapter {
48    async fn generate(&mut self, prompt: &str) -> Result<LLMResponse, LLMError> {
49        use super::provider::{LLMRequest, Message};
50        let request = LLMRequest {
51            messages: vec![Message::user(prompt.to_string())],
52            model: self.model_id.clone(),
53            ..Default::default()
54        };
55        Ok(self.provider.generate(request).await?)
56    }
57
58    fn model_id(&self) -> &str {
59        &self.model_id
60    }
61}