Skip to main content

talos_core/
provider.rs

1//! Provider trait and error types for LLM backends.
2
3use serde_json::Value;
4use tokio::sync::mpsc;
5
6use crate::message::{AgentEvent, Message};
7
8pub type Receiver<T> = mpsc::Receiver<T>;
9
10#[derive(Debug, thiserror::Error)]
11pub enum ProviderError {
12    #[error("authentication failed: {0}")]
13    AuthenticationFailed(String),
14
15    #[error("rate limited: {0}")]
16    RateLimited(String),
17
18    #[error("server error: {0}")]
19    ServerError(String),
20
21    #[error("network error: {0}")]
22    NetworkError(String),
23
24    #[error("invalid response: {0}")]
25    InvalidResponse(String),
26}
27
28pub type ProviderResult<T> = Result<T, ProviderError>;
29
30#[derive(Debug, Clone, PartialEq)]
31pub struct ToolDefinition {
32    pub name: String,
33    pub description: String,
34    pub parameters: Value,
35}
36
37impl ToolDefinition {
38    /// Creates a new tool definition.
39    #[must_use]
40    pub fn new(name: impl Into<String>, description: impl Into<String>, parameters: Value) -> Self {
41        Self {
42            name: name.into(),
43            description: description.into(),
44            parameters,
45        }
46    }
47
48    /// Formats this tool definition as a text block suitable for inclusion
49    /// in the system prompt.
50    #[must_use]
51    pub fn to_prompt_text(&self) -> String {
52        format!(
53            "## {}\n{}\nParameters: {}",
54            self.name,
55            self.description,
56            serde_json::to_string_pretty(&self.parameters).unwrap_or_default()
57        )
58    }
59}
60
61#[async_trait::async_trait]
62pub trait LanguageModel: Send + Sync {
63    async fn stream(&self, messages: &[Message]) -> ProviderResult<Receiver<AgentEvent>>;
64
65    async fn stream_with_tools(
66        &self,
67        messages: &[Message],
68        tools: &[ToolDefinition],
69    ) -> ProviderResult<Receiver<AgentEvent>> {
70        let _ = tools;
71        self.stream(messages).await
72    }
73
74    fn request_preview(&self, _messages: &[Message]) -> Option<Value> {
75        None
76    }
77}