mermaid_cli/providers/model/mod.rs
1//! Model adapters wrapped as `ModelProvider` implementations.
2//!
3//! Four providers today: Ollama, Anthropic, Gemini, and OpenAI-
4//! compat (covering OpenAI, OpenRouter, Groq, Cerebras, DeepInfra,
5//! Together, and user-defined endpoints). Each wraps the
6//! corresponding adapter in `crate::models::adapters`; the adapter
7//! owns the wire format and the wrapper owns the trait shape.
8
9pub mod anthropic;
10pub mod gemini;
11pub mod ollama;
12pub mod openai_compat;
13pub(crate) mod stream_bridge;
14
15use async_trait::async_trait;
16
17use crate::domain::ChatRequest;
18use crate::models::Result;
19
20use super::capabilities::Capabilities;
21use super::ctx::{FinalResponse, StreamContext};
22
23/// Provider-facing interface. A `ModelProvider` impl owns whatever
24/// HTTP client / state it needs and exposes `chat()` — that's the
25/// whole surface.
26#[async_trait]
27pub trait ModelProvider: Send + Sync {
28 /// Capabilities the provider advertises. The reducer reads this
29 /// when building the outgoing `ChatRequest` (e.g. whether to
30 /// attach reasoning controls).
31 fn capabilities(&self) -> &Capabilities;
32
33 /// Stream a chat turn. Typed events flow through
34 /// `ctx.sink`; the returned `FinalResponse` carries token usage
35 /// and the Anthropic thinking-signature (opaque blob required to
36 /// continue extended thinking across turns).
37 ///
38 /// Cancellation: the provider MUST select! on `ctx.token.
39 /// cancelled()` inside any await that could block for more than
40 /// a few hundred ms. This is the contract that replaces the old
41 /// `check_interrupt` polling pattern.
42 async fn chat(&self, request: ChatRequest, ctx: StreamContext) -> Result<FinalResponse>;
43}
44
45pub use anthropic::AnthropicProvider;
46pub use gemini::GeminiProvider;
47pub use ollama::OllamaProvider;
48pub use openai_compat::OpenAICompatProvider;