1use crate::AgentError;
2use llm_sdk::{boxed_stream::BoxedStream, Message, ModelResponse, Part, PartialModelResponse};
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct AgentRequest<TCtx> {
8 pub input: Vec<AgentItem>,
10 pub context: TCtx,
12}
13
14#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
15pub struct AgentResponse {
16 pub output: Vec<AgentItem>,
19
20 pub content: Vec<Part>,
22}
23
24impl AgentResponse {
25 #[must_use]
27 pub fn text(&self) -> String {
28 self.content
29 .iter()
30 .filter_map(|part| match part {
31 Part::Text(part) => Some(part.text.as_str()),
32 _ => None,
33 })
34 .collect::<Vec<_>>()
35 .join(" ")
36 }
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
41#[serde(tag = "type", rename_all = "kebab-case")]
42pub enum AgentItem {
43 Message(Message),
45 Model(ModelResponse),
47 Tool(AgentItemTool),
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
52pub struct AgentItemTool {
53 pub tool_call_id: String,
55 pub tool_name: String,
57 pub input: Value,
59 pub output: Vec<Part>,
61 pub is_error: bool,
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
67#[serde(tag = "event", rename_all = "kebab-case")]
68pub enum AgentStreamEvent {
69 Partial(PartialModelResponse),
70 Item(AgentStreamItemEvent),
71 Response(AgentResponse),
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
75#[serde(rename_all = "kebab-case")]
76pub struct AgentStreamItemEvent {
77 pub index: usize,
78 pub item: AgentItem,
79}
80
81pub type AgentStream = BoxedStream<'static, Result<AgentStreamEvent, AgentError>>;