Skip to main content

defect_core/llm/
provider.rs

1//! [`LlmProvider`] trait — the primary LLM vendor integration interface.
2
3use std::pin::Pin;
4
5use futures::{Stream, future::BoxFuture};
6use tokio_util::sync::CancellationToken;
7
8use super::capability::{Capabilities, HostedCapabilities};
9use super::chunk::ProviderChunk;
10use super::error::ProviderError;
11use super::model::{ModelInfo, ProviderInfo};
12use super::request::CompletionRequest;
13
14/// A type-erased stream of events produced by a provider during streaming generation,
15/// enabling direct use with `dyn LlmProvider`.
16pub type ProviderStream = Pin<Box<dyn Stream<Item = Result<ProviderChunk, ProviderError>> + Send>>;
17
18/// LLM provider abstraction.
19///
20/// Cancellation semantics: [`LlmProvider::complete`] receives a [`CancellationToken`];
21/// the caller may call `cancel()` at any point to abort the call and the downstream
22/// stream. Dropping the returned stream also counts as cancellation.
23pub trait LlmProvider: Send + Sync {
24    /// Provider metadata (vendor name, API style, tracing labels, etc.).
25    fn info(&self) -> ProviderInfo;
26
27    /// Provider-level capability matrix. Model-level differences are expressed via
28    /// [`super::ModelCapabilityOverrides`] and merged on demand by the main loop.
29    fn capabilities(&self) -> Capabilities;
30
31    /// The set of hosted capabilities that this provider adapter advertises.
32    ///
33    /// Unlike [`Self::capabilities`] (which describes model-level properties), this
34    /// reflects the current adapter implementation state: whether it can expose hosted
35    /// `web_search`, `fetch`, etc. to the model over the wire. During session startup,
36    /// this value is read together with `capabilities.web_search.mode` to determine the
37    /// source of hosted web search capabilities.
38    ///
39    /// The default implementation returns all `false`; new providers do not need to
40    /// override it. Adapters that truly support hosted capabilities (Anthropic / OpenAI
41    /// Responses) should explicitly override this method.
42    fn hosted_capabilities(&self) -> HostedCapabilities {
43        HostedCapabilities::default()
44    }
45
46    /// Lists the models currently available from this provider.
47    ///
48    /// The implementation may make network calls (e.g., OpenAI `/v1/models`); results
49    /// should be cached inside the provider for synchronous lookup by
50    /// [`Self::model_info`].
51    ///
52    /// # Errors
53    ///
54    /// Network errors, authentication errors, server errors, etc., are all mapped to
55    /// [`ProviderError`].
56    fn list_models(&self) -> BoxFuture<'_, Result<Vec<ModelInfo>, ProviderError>>;
57
58    /// Synchronously query metadata for a given model.
59    ///
60    /// This is a fast path for context trimming in the main loop; **must not trigger a
61    /// network call**.
62    /// Returns `None` if the provider's cache does not contain the model. The caller may
63    /// then decide to call [`Self::list_models`] and retry, or treat it as an unknown
64    /// model.
65    fn model_info(&self, model_id: &str) -> Option<ModelInfo>;
66
67    /// Start a streaming generation.
68    ///
69    /// # Errors
70    ///
71    /// Authentication failures, invalid parameters, transport errors, server errors, etc.
72    /// are all mapped to [`ProviderError`]. Errors produced within the stream are
73    /// delivered via the stream's `Err` variant, not through this return value.
74    fn complete(
75        &self,
76        req: CompletionRequest,
77        cancel: CancellationToken,
78    ) -> BoxFuture<'_, Result<ProviderStream, ProviderError>>;
79}