Skip to main content

dot/provider/
mod.rs

1pub mod anthropic;
2pub mod openai;
3
4use std::{future::Future, pin::Pin};
5
6use serde::{Deserialize, Serialize};
7use tokio::sync::mpsc::UnboundedReceiver;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct Message {
11    pub role: Role,
12    pub content: Vec<ContentBlock>,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
16#[serde(rename_all = "lowercase")]
17pub enum Role {
18    User,
19    Assistant,
20    System,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
24#[serde(tag = "type", rename_all = "snake_case")]
25pub enum ContentBlock {
26    Text(String),
27    Image {
28        media_type: String,
29        data: String,
30    },
31    ToolUse {
32        id: String,
33        name: String,
34        input: serde_json::Value,
35    },
36    ToolResult {
37        tool_use_id: String,
38        content: String,
39        is_error: bool,
40    },
41    Thinking {
42        thinking: String,
43        signature: String,
44    },
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct ToolDefinition {
49    pub name: String,
50    pub description: String,
51    pub input_schema: serde_json::Value,
52}
53
54#[derive(Debug, Clone)]
55pub struct StreamEvent {
56    pub event_type: StreamEventType,
57}
58
59#[derive(Debug, Clone)]
60pub enum StreamEventType {
61    TextDelta(String),
62    ThinkingDelta(String),
63    ThinkingComplete {
64        thinking: String,
65        signature: String,
66    },
67    ToolUseStart {
68        id: String,
69        name: String,
70    },
71    ToolUseInputDelta(String),
72    ToolUseEnd,
73    MessageStart,
74    MessageEnd {
75        stop_reason: StopReason,
76        usage: Usage,
77    },
78    Error(String),
79}
80
81#[derive(Debug, Clone)]
82pub enum StopReason {
83    EndTurn,
84    MaxTokens,
85    ToolUse,
86    StopSequence,
87}
88
89#[derive(Debug, Clone, Default)]
90pub struct Usage {
91    pub input_tokens: u32,
92    pub output_tokens: u32,
93    pub cache_read_tokens: u32,
94    pub cache_write_tokens: u32,
95}
96
97pub trait Provider: Send + Sync {
98    fn name(&self) -> &str;
99    fn model(&self) -> &str;
100    fn set_model(&mut self, model: String);
101    fn available_models(&self) -> Vec<String>;
102    fn supports_vision(&self) -> bool {
103        true
104    }
105    fn fetch_models(
106        &self,
107    ) -> Pin<Box<dyn Future<Output = anyhow::Result<Vec<String>>> + Send + '_>>;
108    fn stream(
109        &self,
110        messages: &[Message],
111        system: Option<&str>,
112        tools: &[ToolDefinition],
113        max_tokens: u32,
114        thinking_budget: u32,
115    ) -> Pin<Box<dyn Future<Output = anyhow::Result<UnboundedReceiver<StreamEvent>>> + Send + '_>>;
116}