vtcode_llm/providers/gemini/wire/interactions/
mod.rs1use serde::{Deserialize, Serialize};
2use serde_json::{Map, Value};
3
4use super::GenerationConfig;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct InteractionRequest {
8 pub(crate) model: String,
9 pub(crate) input: InteractionInput,
10 #[serde(skip_serializing_if = "Option::is_none")]
11 pub(crate) tools: Option<Vec<InteractionTool>>,
12 #[serde(skip_serializing_if = "Option::is_none")]
13 pub(crate) system_instruction: Option<String>,
14 #[serde(skip_serializing_if = "Option::is_none")]
15 pub(crate) response_format: Option<Value>,
16 #[serde(skip_serializing_if = "Option::is_none")]
17 pub(crate) response_mime_type: Option<String>,
18 #[serde(skip_serializing_if = "Option::is_none")]
19 pub(crate) stream: Option<bool>,
20 #[serde(skip_serializing_if = "Option::is_none")]
21 pub(crate) store: Option<bool>,
22 #[serde(skip_serializing_if = "Option::is_none")]
23 pub(crate) generation_config: Option<InteractionGenerationConfig>,
24 #[serde(skip_serializing_if = "Option::is_none")]
25 pub(crate) tool_choice: Option<InteractionToolChoice>,
26 #[serde(skip_serializing_if = "Option::is_none")]
27 pub(crate) previous_interaction_id: Option<String>,
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
31#[serde(untagged)]
32pub enum InteractionInput {
33 Text(String),
34 Content(Vec<InteractionContent>),
35 Turns(Vec<InteractionTurn>),
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct InteractionTurn {
40 pub(crate) role: String,
41 pub(crate) content: InteractionTurnContent,
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
45#[serde(untagged)]
46pub enum InteractionTurnContent {
47 Text(String),
48 Content(Vec<InteractionContent>),
49}
50
51#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
52#[serde(tag = "type", rename_all = "snake_case")]
53pub enum InteractionContent {
54 Text {
55 text: String,
56 },
57 Image {
58 data: String,
59 mime_type: String,
60 },
61 FunctionCall {
62 id: String,
63 name: String,
64 arguments: Value,
65 #[serde(skip_serializing_if = "Option::is_none")]
66 signature: Option<String>,
67 },
68 FunctionResult {
69 call_id: String,
70 #[serde(skip_serializing_if = "Option::is_none")]
71 name: Option<String>,
72 result: InteractionResult,
73 #[serde(skip_serializing_if = "Option::is_none")]
74 is_error: Option<bool>,
75 #[serde(skip_serializing_if = "Option::is_none")]
76 signature: Option<String>,
77 },
78 #[serde(other)]
80 Unknown,
81}
82
83#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
84#[serde(untagged)]
85pub enum InteractionResult {
86 String(String),
87 Json(Value),
88 Content(Vec<InteractionContent>),
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize)]
92pub struct InteractionTool {
93 #[serde(rename = "type")]
94 pub(crate) tool_type: String,
95 #[serde(skip_serializing_if = "Option::is_none")]
96 pub(crate) name: Option<String>,
97 #[serde(skip_serializing_if = "Option::is_none")]
98 description: Option<String>,
99 #[serde(skip_serializing_if = "Option::is_none")]
100 parameters: Option<Value>,
101 #[serde(flatten, default)]
102 pub(crate) extra: Map<String, Value>,
103}
104
105impl InteractionTool {
106 pub(crate) fn built_in(tool_type: &str, config: Option<&Value>) -> Self {
107 let extra = config.and_then(Value::as_object).cloned().unwrap_or_default();
108 Self {
109 tool_type: tool_type.to_string(),
110 name: None,
111 description: None,
112 parameters: None,
113 extra,
114 }
115 }
116
117 pub(crate) fn function(name: String, description: String, parameters: Value) -> Self {
118 Self {
119 tool_type: "function".to_string(),
120 name: Some(name),
121 description: Some(description),
122 parameters: Some(parameters),
123 extra: Map::new(),
124 }
125 }
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct InteractionToolChoice {
130 pub(crate) mode: String,
131 #[serde(skip_serializing_if = "Option::is_none")]
132 pub(crate) tools: Option<Vec<String>>,
133}
134
135impl InteractionToolChoice {
136 pub(crate) fn new(mode: impl Into<String>) -> Self {
137 Self { mode: mode.into(), tools: None }
138 }
139}
140
141#[derive(Debug, Clone, Serialize, Deserialize)]
142pub struct InteractionGenerationConfig {
143 #[serde(skip_serializing_if = "Option::is_none")]
144 temperature: Option<f32>,
145 #[serde(skip_serializing_if = "Option::is_none")]
146 top_p: Option<f32>,
147 #[serde(skip_serializing_if = "Option::is_none")]
148 max_output_tokens: Option<u32>,
149 #[serde(skip_serializing_if = "Option::is_none")]
150 stop_sequences: Option<Vec<String>>,
151 #[serde(skip_serializing_if = "Option::is_none")]
152 thinking_level: Option<String>,
153}
154
155impl From<GenerationConfig> for InteractionGenerationConfig {
156 fn from(value: GenerationConfig) -> Self {
157 Self {
158 temperature: value.temperature,
159 top_p: value.top_p,
160 max_output_tokens: value.max_output_tokens,
161 stop_sequences: value.stop_sequences,
162 thinking_level: value.thinking_config.and_then(|cfg| cfg.thinking_level),
163 }
164 }
165}
166
167impl From<InteractionGenerationConfig> for GenerationConfig {
168 fn from(value: InteractionGenerationConfig) -> Self {
169 GenerationConfig {
170 temperature: value.temperature,
171 top_p: value.top_p,
172 max_output_tokens: value.max_output_tokens,
173 stop_sequences: value.stop_sequences,
174 thinking_config: value
175 .thinking_level
176 .map(|thinking_level| super::ThinkingConfig { thinking_level: Some(thinking_level) }),
177 ..Default::default()
178 }
179 }
180}
181
182#[derive(Debug, Clone, Serialize, Deserialize)]
183pub struct Interaction {
184 pub(crate) id: String,
185 pub(crate) model: String,
186 #[serde(default)]
187 pub(crate) status: Option<String>,
188 #[serde(default)]
189 pub(crate) outputs: Vec<InteractionOutput>,
190 #[serde(default)]
191 pub(crate) usage: Option<InteractionUsage>,
192}
193
194#[derive(Debug, Clone, Serialize, Deserialize)]
195pub struct InteractionOutput {
196 #[serde(rename = "type")]
197 pub(crate) output_type: String,
198 #[serde(default)]
199 pub(crate) text: Option<String>,
200 #[serde(default)]
201 pub(crate) summary: Option<String>,
202 #[serde(default)]
203 pub(crate) id: Option<String>,
204 #[serde(default)]
205 pub(crate) name: Option<String>,
206 #[serde(default)]
207 pub(crate) arguments: Option<Value>,
208 #[serde(default)]
209 pub(crate) signature: Option<String>,
210 #[serde(default)]
211 pub(crate) function_call: Option<InteractionFunctionCall>,
212}
213
214#[derive(Debug, Clone, Serialize, Deserialize)]
215pub struct InteractionFunctionCall {
216 pub(crate) name: String,
217 pub(crate) arguments: Value,
218 #[serde(default)]
219 pub(crate) id: Option<String>,
220 #[serde(default)]
221 pub(crate) signature: Option<String>,
222}
223
224#[derive(Debug, Clone, Serialize, Deserialize)]
225pub struct InteractionUsage {
226 #[serde(default)]
227 pub(crate) total_input_tokens: Option<u32>,
228 #[serde(default)]
229 pub(crate) total_output_tokens: Option<u32>,
230 #[serde(default)]
231 pub(crate) total_tokens: Option<u32>,
232 #[serde(default)]
233 pub(crate) total_cached_tokens: Option<u32>,
234}