aiclient_api/providers/
mod.rs1use 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}