1use crate::{message::Message, Result};
2use async_trait::async_trait;
3use serde_json::Value;
4use std::collections::HashMap;
5
6#[derive(Debug, Clone)]
7pub enum AgentInput {
8 Text(String),
9 Messages(Vec<Message>),
10}
11
12impl AgentInput {
13 pub fn text(text: impl Into<String>) -> Self {
14 Self::Text(text.into())
15 }
16
17 pub fn messages(messages: Vec<Message>) -> Self {
18 Self::Messages(messages)
19 }
20}
21
22#[derive(Debug, Clone)]
23pub struct AgentOutput {
24 pub messages: Vec<Message>,
25}
26
27impl AgentOutput {
28 pub fn new(messages: Vec<Message>) -> Self {
29 Self { messages }
30 }
31
32 pub fn last_message(&self) -> Option<&Message> {
33 self.messages.last()
34 }
35
36 pub fn text(&self) -> Option<String> {
38 if let Some(last) = self.last_message() {
39 if let Some(text) = last.text_content() {
40 return Some(text);
41 }
42 }
43
44 for msg in self.messages.iter().rev() {
46 for block in &msg.content {
47 if let crate::message::ContentBlock::ToolResult { content, is_error, .. } = block
48 {
49 if !is_error {
50 return Some(content.to_string());
51 }
52 }
53 }
54 }
55 None
56 }
57}
58
59#[derive(Debug)]
60pub struct AgentContext {
61 pub metadata: HashMap<String, Value>,
62}
63
64impl AgentContext {
65 pub fn new() -> Self {
66 Self {
67 metadata: HashMap::new(),
68 }
69 }
70}
71
72#[async_trait]
73pub trait Agent: Send + Sync {
74 async fn invoke(&self, input: AgentInput, ctx: &mut AgentContext) -> Result<AgentOutput>;
75}