use crate::tool::ToolResult;
pub type SessionId = String;
pub fn new_session_id() -> SessionId {
uuid::Uuid::new_v4().to_string()
}
#[derive(Debug, Clone)]
pub struct MediaAttachment {
pub content_type: String,
pub url: String,
pub filename: Option<String>,
pub size: Option<u64>,
pub width: Option<u32>,
pub height: Option<u32>,
}
impl MediaAttachment {
pub fn is_image(&self) -> bool {
self.content_type.starts_with("image/")
}
pub fn describe(&self) -> String {
let filename = self.filename.as_deref().unwrap_or("unknown");
let type_desc = if self.is_image() { "图片" } else { "文件" };
let size_str = self
.size
.map(|s| format!(" ({:.1}KB)", s as f64 / 1024.0))
.unwrap_or_default();
format!("[用户发送了{}: {}{}]", type_desc, filename, size_str)
}
}
#[derive(Debug)]
pub enum AgentEvent {
TextDelta(String),
ToolCallRequested {
tool_call_id: String,
name: String,
arguments: String,
},
ToolCallResult {
tool_call_id: String,
result: ToolResult,
},
TurnComplete,
Error(crate::error::AgentError),
SkillTriggered { name: String, description: String },
}
#[derive(Debug)]
pub enum FrontendMessage {
UserInput {
text: String,
attachments: Vec<MediaAttachment>,
},
Cancel,
ConfirmationResponse {
tool_call_id: String,
approved: bool,
},
}
impl From<String> for FrontendMessage {
fn from(text: String) -> Self {
Self::UserInput {
text,
attachments: vec![],
}
}
}
impl From<&str> for FrontendMessage {
fn from(text: &str) -> Self {
Self::UserInput {
text: text.to_string(),
attachments: vec![],
}
}
}