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, Eq)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum AgentEvent {
AssistantText { text: String },
ToolRequested { name: String },
ToolCompleted { name: String, summary: String },
ToolDenied { name: String, reason: String },
Complete,
}
#[async_trait]
pub trait ApprovalDecider: Send + Sync {
async fn approve(&self, tool: &ToolDefinition) -> bool;
}
pub struct AllowReadOnlyApproval;
#[async_trait]
impl ApprovalDecider for AllowReadOnlyApproval {
async fn approve(&self, _: &ToolDefinition) -> 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>;
}