Skip to main content

aiclient_api/providers/
mod.rs

1use anyhow::Result;
2use async_trait::async_trait;
3use bytes::Bytes;
4use futures::Stream;
5use serde::{Deserialize, Serialize};
6use std::pin::Pin;
7
8pub mod copilot;
9pub mod kiro;
10pub mod router;
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct Model {
14    pub id: String,
15    pub provider: String,
16    pub vendor: String,
17    pub display_name: String,
18    pub max_input_tokens: Option<u32>,
19    pub max_output_tokens: Option<u32>,
20    pub supports_streaming: bool,
21    pub supports_tools: bool,
22    pub supports_vision: bool,
23    pub supports_thinking: bool,
24}
25
26#[derive(Debug, Clone)]
27pub struct ProviderRequest {
28    pub model: String,
29    pub messages: Vec<serde_json::Value>,
30    pub system: Option<String>,
31    pub temperature: Option<f64>,
32    pub max_tokens: Option<u32>,
33    pub stream: bool,
34    pub tools: Option<Vec<serde_json::Value>>,
35    pub tool_choice: Option<serde_json::Value>,
36    pub extra: serde_json::Value,
37}
38
39pub enum ProviderResponse {
40    Complete(serde_json::Value),
41    Stream(Pin<Box<dyn Stream<Item = Result<Bytes>> + Send>>),
42}
43
44#[derive(Debug, Clone, Copy, PartialEq)]
45pub enum OutputFormat {
46    OpenAI,
47    Anthropic,
48}
49
50#[async_trait]
51pub trait Provider: Send + Sync {
52    fn name(&self) -> &str;
53    fn is_healthy(&self) -> bool;
54    async fn list_models(&self) -> Result<Vec<Model>>;
55    async fn chat(&self, request: ProviderRequest) -> Result<ProviderResponse>;
56    fn supports_passthrough(&self, _format: OutputFormat) -> bool {
57        false
58    }
59    async fn passthrough(
60        &self,
61        _model: &str,
62        _body: serde_json::Value,
63        _format: OutputFormat,
64        _stream: bool,
65    ) -> Result<ProviderResponse> {
66        anyhow::bail!("passthrough not supported")
67    }
68}