Skip to main content

hanzo_agent/
types.rs

1//! Core types for agent framework
2
3use serde::{Deserialize, Serialize};
4
5/// Input item for the agent
6#[derive(Debug, Clone, Serialize, Deserialize)]
7#[serde(tag = "type")]
8pub enum InputItem {
9    #[serde(rename = "message")]
10    Message { role: String, content: String },
11
12    #[serde(rename = "tool_result")]
13    ToolResult {
14        tool_call_id: String,
15        content: String,
16    },
17}
18
19impl InputItem {
20    /// Create a user message
21    pub fn user_message(content: impl Into<String>) -> Self {
22        InputItem::Message {
23            role: "user".to_string(),
24            content: content.into(),
25        }
26    }
27
28    /// Create an assistant message
29    pub fn assistant_message(content: impl Into<String>) -> Self {
30        InputItem::Message {
31            role: "assistant".to_string(),
32            content: content.into(),
33        }
34    }
35
36    /// Create a system message
37    pub fn system_message(content: impl Into<String>) -> Self {
38        InputItem::Message {
39            role: "system".to_string(),
40            content: content.into(),
41        }
42    }
43}
44
45/// Item generated during agent run
46#[derive(Debug, Clone, Serialize, Deserialize)]
47#[serde(tag = "type")]
48pub enum RunItem {
49    #[serde(rename = "message")]
50    Message { role: String, content: String },
51
52    #[serde(rename = "tool_call")]
53    ToolCall {
54        id: String,
55        name: String,
56        arguments: String,
57    },
58
59    #[serde(rename = "tool_result")]
60    ToolResult {
61        tool_call_id: String,
62        content: String,
63    },
64}
65
66impl RunItem {
67    /// Convert to input item for next turn
68    pub fn to_input_item(&self) -> InputItem {
69        match self {
70            RunItem::Message { role, content } => InputItem::Message {
71                role: role.clone(),
72                content: content.clone(),
73            },
74            RunItem::ToolResult {
75                tool_call_id,
76                content,
77            } => InputItem::ToolResult {
78                tool_call_id: tool_call_id.clone(),
79                content: content.clone(),
80            },
81            RunItem::ToolCall { .. } => {
82                // Tool calls are converted to messages in the context
83                InputItem::assistant_message("")
84            }
85        }
86    }
87}
88
89/// Model response from LLM
90#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct ModelResponse {
92    /// The output items (messages, tool calls, etc.)
93    pub output: Vec<RunItem>,
94
95    /// Usage statistics
96    pub usage: Usage,
97
98    /// Response ID for reference
99    pub id: Option<String>,
100}
101
102/// Usage statistics
103#[derive(Debug, Clone, Default, Serialize, Deserialize)]
104pub struct Usage {
105    pub requests: usize,
106    pub input_tokens: usize,
107    pub output_tokens: usize,
108    pub total_tokens: usize,
109}
110
111impl Usage {
112    /// Add usage from another instance
113    pub fn add(&mut self, other: &Usage) {
114        self.requests += other.requests;
115        self.input_tokens += other.input_tokens;
116        self.output_tokens += other.output_tokens;
117        self.total_tokens += other.total_tokens;
118    }
119}
120
121/// Model settings for tuning
122#[derive(Debug, Clone, Serialize, Deserialize)]
123pub struct ModelSettings {
124    #[serde(skip_serializing_if = "Option::is_none")]
125    pub temperature: Option<f32>,
126
127    #[serde(skip_serializing_if = "Option::is_none")]
128    pub top_p: Option<f32>,
129
130    #[serde(skip_serializing_if = "Option::is_none")]
131    pub max_tokens: Option<usize>,
132
133    #[serde(skip_serializing_if = "Option::is_none")]
134    pub stop: Option<Vec<String>>,
135}
136
137impl Default for ModelSettings {
138    fn default() -> Self {
139        Self {
140            temperature: None,
141            top_p: None,
142            max_tokens: None,
143            stop: None,
144        }
145    }
146}