Skip to main content

rab/agent/
provider.rs

1use crate::agent::types::{AgentMessage, ToolCall, Usage};
2use async_trait::async_trait;
3use futures::Stream;
4use std::pin::Pin;
5
6/// Events emitted during a streaming LLM request.
7#[derive(Debug, Clone)]
8#[allow(dead_code)]
9pub enum StreamEvent {
10    TextDelta {
11        text: String,
12    },
13    ThinkingDelta {
14        text: String,
15    },
16    ToolCall {
17        id: String,
18        name: String,
19        arguments: String,
20    },
21    Done {
22        text: String,
23        usage: Usage,
24        stop_reason: StopReason,
25        tool_calls: Vec<ToolCall>,
26    },
27    Error {
28        message: String,
29    },
30}
31
32#[derive(Debug, Clone, PartialEq)]
33pub enum StopReason {
34    EndTurn,
35    ToolUse,
36    MaxTokens,
37    Error,
38}
39
40/// Tool definition sent to the LLM.
41#[derive(Debug, Clone)]
42pub struct ToolDef {
43    pub name: String,
44    pub description: String,
45    pub parameters: serde_json::Value,
46}
47
48/// The one thing the agent loop needs from a provider.
49#[async_trait]
50pub trait Provider: Send + Sync {
51    async fn stream(
52        &self,
53        model: &str,
54        system_prompt: &str,
55        messages: &[AgentMessage],
56        tools: &[ToolDef],
57    ) -> anyhow::Result<Pin<Box<dyn Stream<Item = StreamEvent> + Send>>>;
58
59    /// Update reasoning effort (thinking level) at runtime.
60    /// Default implementation is a no-op for providers that don't support this.
61    fn set_reasoning_effort(&self, _level: Option<&str>) {}
62}