1use crate::core::types::{Message, ProviderRequest, ProviderResponse, ProviderStreamEvent};
2use async_trait::async_trait;
3use serde_json::Value;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum ApprovalDecision {
7 Allow,
8 Ask,
9 Deny,
10}
11
12pub trait AgentEvents: Send + Sync {
13 fn on_thinking(&self, _text: &str) {}
14 fn on_tool_start(&self, _name: &str, _args: &Value) {}
15 fn on_tool_end(&self, _name: &str, _result: &crate::tool::ToolResult) {}
16 fn on_todo_items_changed(&self, _items: &[crate::core::TodoItem]) {}
17 fn on_assistant_delta(&self, _delta: &str) {}
18 fn on_context_usage(&self, _tokens: usize) {}
19 fn on_assistant_done(&self) {}
20}
21
22#[derive(Debug, Default, Clone, Copy)]
23pub struct NoopEvents;
24
25impl AgentEvents for NoopEvents {}
26
27#[async_trait]
28pub trait Provider: Send + Sync {
29 async fn complete(&self, req: ProviderRequest) -> anyhow::Result<ProviderResponse>;
30
31 async fn complete_stream<F>(
32 &self,
33 req: ProviderRequest,
34 mut on_event: F,
35 ) -> anyhow::Result<ProviderResponse>
36 where
37 F: FnMut(ProviderStreamEvent) + Send,
38 {
39 let response = self.complete(req).await?;
40 if let Some(thinking) = &response.thinking {
41 on_event(ProviderStreamEvent::ThinkingDelta(thinking.clone()));
42 }
43 if !response.assistant_message.content.is_empty() {
44 on_event(ProviderStreamEvent::AssistantDelta(
45 response.assistant_message.content.clone(),
46 ));
47 }
48 Ok(response)
49 }
50}
51
52#[async_trait]
53pub trait ToolExecutor: Send + Sync {
54 fn schemas(&self) -> Vec<crate::tool::schema::ToolSchema>;
55 async fn execute(&self, name: &str, args: Value) -> crate::tool::ToolResult;
56 fn is_non_blocking(&self, _name: &str) -> bool {
57 false
58 }
59}
60
61pub trait ApprovalPolicy: Send + Sync {
62 fn decision_for_tool(&self, tool_name: &str) -> ApprovalDecision;
63}
64
65pub trait SessionSink: Send + Sync {
66 fn append(&self, event: &crate::session::SessionEvent) -> anyhow::Result<()>;
67}
68
69pub trait SessionReader: Send + Sync {
70 fn replay_messages(&self) -> anyhow::Result<Vec<Message>>;
71 fn replay_events(&self) -> anyhow::Result<Vec<crate::session::SessionEvent>>;
72}