Skip to main content

agent_air_runtime/client/
models.rs

1/// Message role in a conversation.
2#[derive(Debug, Clone, PartialEq)]
3pub enum Role {
4    /// System message providing instructions or context.
5    System,
6    /// User message containing requests or responses.
7    User,
8    /// Assistant message containing responses or tool use.
9    Assistant,
10}
11
12/// Image source types supported by LLM providers.
13#[derive(Debug, Clone, PartialEq)]
14pub enum ImageSource {
15    /// Base64-encoded image data with media type (e.g., "image/jpeg", "image/png").
16    Base64 { media_type: String, data: String },
17    /// URL reference to an image.
18    Url(String),
19}
20
21/// Tool invocation requested by the assistant.
22#[derive(Debug, Clone, PartialEq)]
23pub struct ToolUse {
24    /// Unique identifier for this tool use (used to match with ToolResult).
25    pub id: String,
26    /// Name of the tool to invoke.
27    pub name: String,
28    /// Input arguments as a JSON string.
29    pub input: String,
30}
31
32/// Result of a tool invocation, sent back to the assistant.
33#[derive(Debug, Clone, PartialEq)]
34pub struct ToolResult {
35    /// ID of the tool use this result corresponds to.
36    pub tool_use_id: String,
37    /// Result content (can be text or error message).
38    pub content: String,
39    /// Whether this result represents an error.
40    pub is_error: bool,
41}
42
43/// Content block types that can appear in messages.
44#[derive(Debug, Clone, PartialEq)]
45pub enum Content {
46    /// Plain text content.
47    Text(String),
48    /// Image content with source data.
49    Image(ImageSource),
50    /// Tool invocation from the assistant.
51    ToolUse(ToolUse),
52    /// Tool result from the user.
53    ToolResult(ToolResult),
54}
55
56/// Conversation message with role and content blocks.
57#[derive(Debug, Clone, PartialEq)]
58pub struct Message {
59    /// Role of the message sender.
60    pub role: Role,
61    /// Content blocks (text, images, tool use, tool results).
62    pub content: Vec<Content>,
63    /// Provider-specific response metadata (safety ratings, grounding, citations).
64    pub response_metadata: Option<ResponseMetadata>,
65}
66
67/// Provider-specific metadata returned with responses.
68#[derive(Debug, Clone, PartialEq, Default)]
69pub struct ResponseMetadata {
70    /// Content safety ratings (Gemini).
71    pub safety_ratings: Option<Vec<SafetyRating>>,
72    /// Grounding/citation metadata (Gemini).
73    pub grounding: Option<GroundingMetadata>,
74}
75
76/// Content safety rating from the model.
77#[derive(Debug, Clone, PartialEq)]
78pub struct SafetyRating {
79    /// Harm category (e.g., "HARM_CATEGORY_HARASSMENT").
80    pub category: String,
81    /// Probability level (e.g., "NEGLIGIBLE", "LOW", "MEDIUM", "HIGH").
82    pub probability: String,
83    /// Whether this category was blocked.
84    pub blocked: bool,
85}
86
87/// Grounding and citation metadata.
88#[derive(Debug, Clone, PartialEq, Default)]
89pub struct GroundingMetadata {
90    /// Web search queries used for grounding.
91    pub web_search_queries: Vec<String>,
92    /// Grounding chunks with source information.
93    pub grounding_chunks: Vec<GroundingChunk>,
94    /// Grounding supports linking content to sources.
95    pub grounding_supports: Vec<GroundingSupport>,
96}
97
98/// A source chunk used for grounding.
99#[derive(Debug, Clone, PartialEq)]
100pub struct GroundingChunk {
101    /// Source type (e.g., "web").
102    pub source_type: String,
103    /// URI of the source.
104    pub uri: Option<String>,
105    /// Title of the source.
106    pub title: Option<String>,
107}
108
109/// Links a segment of generated content to grounding sources.
110#[derive(Debug, Clone, PartialEq)]
111pub struct GroundingSupport {
112    /// Start index in the generated text.
113    pub start_index: usize,
114    /// End index in the generated text.
115    pub end_index: usize,
116    /// Indices into grounding_chunks that support this segment.
117    pub chunk_indices: Vec<usize>,
118    /// Confidence scores for each supporting chunk.
119    pub confidence_scores: Vec<f32>,
120}
121
122impl Message {
123    /// Create a new message with a single text content block.
124    pub fn new(role: Role, text: impl Into<String>) -> Self {
125        Self {
126            role,
127            content: vec![Content::Text(text.into())],
128            response_metadata: None,
129        }
130    }
131
132    /// Create a message with multiple content blocks.
133    pub fn with_content(role: Role, content: Vec<Content>) -> Self {
134        Self {
135            role,
136            content,
137            response_metadata: None,
138        }
139    }
140
141    /// Create a message with content and metadata.
142    pub fn with_metadata(role: Role, content: Vec<Content>, metadata: ResponseMetadata) -> Self {
143        Self {
144            role,
145            content,
146            response_metadata: Some(metadata),
147        }
148    }
149
150    /// Create a system message with text content.
151    pub fn system(text: impl Into<String>) -> Self {
152        Self::new(Role::System, text)
153    }
154
155    /// Create a user message with text content.
156    pub fn user(text: impl Into<String>) -> Self {
157        Self::new(Role::User, text)
158    }
159
160    /// Create an assistant message with text content.
161    pub fn assistant(text: impl Into<String>) -> Self {
162        Self::new(Role::Assistant, text)
163    }
164
165    /// Create a user message with a tool result.
166    pub fn tool_result(
167        tool_use_id: impl Into<String>,
168        content: impl Into<String>,
169        is_error: bool,
170    ) -> Self {
171        Self {
172            role: Role::User,
173            content: vec![Content::ToolResult(ToolResult {
174                tool_use_id: tool_use_id.into(),
175                content: content.into(),
176                is_error,
177            })],
178            response_metadata: None,
179        }
180    }
181}
182
183/// Tool definition for function calling.
184#[derive(Debug, Clone, PartialEq)]
185pub struct Tool {
186    /// Name of the tool.
187    pub name: String,
188    /// Description of what the tool does.
189    pub description: String,
190    /// JSON Schema for the tool's input parameters.
191    pub input_schema: String,
192}
193
194impl Tool {
195    /// Create a new tool definition.
196    pub fn new(
197        name: impl Into<String>,
198        description: impl Into<String>,
199        input_schema: impl Into<String>,
200    ) -> Self {
201        Self {
202            name: name.into(),
203            description: description.into(),
204            input_schema: input_schema.into(),
205        }
206    }
207}
208
209/// Controls how the model uses tools.
210#[derive(Debug, Clone, PartialEq, Default)]
211pub enum ToolChoice {
212    /// Model decides whether to use tools.
213    #[default]
214    Auto,
215    /// Model must use at least one tool.
216    Any,
217    /// Model must use the specified tool.
218    Tool(String),
219    /// Model cannot use any tools.
220    None,
221}
222
223/// Metadata for request tracking.
224#[derive(Debug, Clone, PartialEq, Default)]
225pub struct Metadata {
226    /// User identifier for tracking/billing.
227    pub user_id: Option<String>,
228}
229
230/// Options for LLM message requests.
231#[derive(Debug, Clone, Default)]
232pub struct MessageOptions {
233    /// Sampling temperature (0.0-1.0).
234    pub temperature: Option<f32>,
235    /// Maximum tokens to generate.
236    pub max_tokens: Option<u32>,
237    /// Model to use.
238    pub model: Option<String>,
239    /// Tools available for the model to use.
240    pub tools: Option<Vec<Tool>>,
241    /// How the model should use tools.
242    pub tool_choice: Option<ToolChoice>,
243    /// Custom stop sequences.
244    pub stop_sequences: Option<Vec<String>>,
245    /// Nucleus sampling parameter.
246    pub top_p: Option<f32>,
247    /// Top-K sampling parameter.
248    pub top_k: Option<u32>,
249    /// Request metadata.
250    pub metadata: Option<Metadata>,
251}
252
253// ============================================================================
254// Streaming Types
255// ============================================================================
256
257/// Events emitted during streaming responses.
258#[derive(Debug, Clone, PartialEq)]
259pub enum StreamEvent {
260    /// Stream started, contains message metadata.
261    MessageStart { message_id: String, model: String },
262    /// A content block is starting.
263    ContentBlockStart {
264        index: usize,
265        block_type: ContentBlockType,
266    },
267    /// Incremental text content.
268    TextDelta { index: usize, text: String },
269    /// Incremental JSON for tool input.
270    InputJsonDelta { index: usize, json: String },
271    /// A content block has finished.
272    ContentBlockStop { index: usize },
273    /// Message-level updates (stop reason, usage).
274    MessageDelta {
275        stop_reason: Option<String>,
276        usage: Option<Usage>,
277    },
278    /// Stream has ended.
279    MessageStop,
280    /// Keep-alive ping.
281    Ping,
282}
283
284/// Type of content block in streaming.
285#[derive(Debug, Clone, PartialEq)]
286pub enum ContentBlockType {
287    Text,
288    ToolUse { id: String, name: String },
289}
290
291/// Token usage statistics.
292#[derive(Debug, Clone, PartialEq, Default)]
293pub struct Usage {
294    /// Input tokens used.
295    pub input_tokens: u32,
296    /// Output tokens generated.
297    pub output_tokens: u32,
298}