use async_trait::async_trait;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentRequest {
pub prompt: String,
pub profile_names: Vec<String>,
pub model: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub system_prompt: Option<String>,
#[serde(default)]
pub history: Vec<ChatMessage>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ChatMessage {
pub role: String,
pub content: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub tool_calls: Vec<ToolCall>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tool_call_id: Option<String>,
}
impl ChatMessage {
pub fn text(role: &str, content: impl Into<String>) -> Self {
Self {
role: role.into(),
content: content.into(),
tool_calls: Vec::new(),
tool_call_id: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ToolCall {
pub id: String,
pub name: String,
pub arguments: serde_json::Value,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ToolMetadata {
pub name: String,
pub status: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChatRequest {
pub model: String,
pub messages: Vec<ChatMessage>,
pub tools: Vec<ToolDefinition>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChatResponse {
pub message: ChatMessage,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum AgentEvent {
AssistantText {
text: String,
},
ToolRequested {
name: String,
#[serde(default, skip_serializing_if = "serde_json::Value::is_null")]
arguments: serde_json::Value,
},
ToolCompleted {
name: String,
summary: String,
},
ToolDenied {
name: String,
reason: String,
},
Complete,
}
#[async_trait]
pub trait ApprovalDecider: Send + Sync {
async fn approve(&self, tool: &ToolDefinition, arguments: &serde_json::Value) -> bool;
}
pub struct AllowReadOnlyApproval;
#[async_trait]
impl ApprovalDecider for AllowReadOnlyApproval {
async fn approve(&self, _: &ToolDefinition, _: &serde_json::Value) -> bool {
true
}
}
#[derive(Debug, thiserror::Error, Clone, PartialEq, Eq)]
pub enum ProviderError {
#[error("provider request failed: {0}")]
Request(String),
#[error("provider returned an invalid response")]
InvalidResponse,
#[error("provider is not configured: {0}")]
Configuration(String),
#[error("provider stream was cancelled")]
Cancelled,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolDefinition {
pub name: String,
pub description: String,
pub read_only: bool,
pub parameters: serde_json::Value,
pub requires_approval: bool,
}
#[async_trait]
pub trait ToolExecutor: Send + Sync {
async fn execute(
&self,
name: &str,
arguments: serde_json::Value,
) -> Result<serde_json::Value, String>;
}