1use async_trait::async_trait;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct AgentRequest {
6 pub prompt: String,
7 pub profile_names: Vec<String>,
8 pub model: String,
9 #[serde(default, skip_serializing_if = "Option::is_none")]
11 pub system_prompt: Option<String>,
12 #[serde(default)]
13 pub history: Vec<ChatMessage>,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
17pub struct ChatMessage {
18 pub role: String,
19 pub content: String,
20 #[serde(default, skip_serializing_if = "Vec::is_empty")]
21 pub tool_calls: Vec<ToolCall>,
22 #[serde(default, skip_serializing_if = "Option::is_none")]
23 pub tool_call_id: Option<String>,
24}
25
26impl ChatMessage {
27 pub fn text(role: &str, content: impl Into<String>) -> Self {
28 Self {
29 role: role.into(),
30 content: content.into(),
31 tool_calls: Vec::new(),
32 tool_call_id: None,
33 }
34 }
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
38pub struct ToolCall {
39 pub id: String,
40 pub name: String,
41 pub arguments: serde_json::Value,
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
45pub struct ToolMetadata {
46 pub name: String,
47 pub status: String,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct ChatRequest {
52 pub model: String,
53 pub messages: Vec<ChatMessage>,
54 pub tools: Vec<ToolDefinition>,
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct ChatResponse {
59 pub message: ChatMessage,
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
63#[serde(tag = "type", rename_all = "snake_case")]
64pub enum AgentEvent {
65 AssistantText { text: String },
66 ToolRequested { name: String },
67 ToolCompleted { name: String, summary: String },
68 ToolDenied { name: String, reason: String },
69 Complete,
70}
71
72#[async_trait]
73pub trait ApprovalDecider: Send + Sync {
74 async fn approve(&self, tool: &ToolDefinition) -> bool;
75}
76
77pub struct AllowReadOnlyApproval;
78
79#[async_trait]
80impl ApprovalDecider for AllowReadOnlyApproval {
81 async fn approve(&self, _: &ToolDefinition) -> bool {
82 true
83 }
84}
85
86#[derive(Debug, thiserror::Error, Clone, PartialEq, Eq)]
87pub enum ProviderError {
88 #[error("provider request failed: {0}")]
89 Request(String),
90 #[error("provider returned an invalid response")]
91 InvalidResponse,
92 #[error("provider is not configured: {0}")]
93 Configuration(String),
94 #[error("provider stream was cancelled")]
95 Cancelled,
96}
97
98#[derive(Debug, Clone, Serialize, Deserialize)]
99pub struct ToolDefinition {
100 pub name: String,
101 pub description: String,
102 pub read_only: bool,
103 pub parameters: serde_json::Value,
104 pub requires_approval: bool,
105}
106
107#[async_trait]
108pub trait ToolExecutor: Send + Sync {
109 async fn execute(
110 &self,
111 name: &str,
112 arguments: serde_json::Value,
113 ) -> Result<serde_json::Value, String>;
114}