adk_tool/builtin/
gemini_extra.rs1use adk_core::{Result, Tool, ToolContext};
2use async_trait::async_trait;
3use serde_json::{Value, json};
4use std::sync::Arc;
5
6#[derive(Debug, Clone, Copy, PartialEq)]
8pub struct GoogleMapsContext {
9 latitude: f64,
10 longitude: f64,
11}
12
13impl GoogleMapsContext {
14 pub fn new(latitude: f64, longitude: f64) -> Self {
16 Self { latitude, longitude }
17 }
18
19 fn to_json(self) -> Value {
20 json!({
21 "retrievalConfig": {
22 "latLng": {
23 "latitude": self.latitude,
24 "longitude": self.longitude,
25 }
26 }
27 })
28 }
29}
30
31#[derive(Debug, Clone, Default)]
33pub struct GoogleMapsTool {
34 enable_widget: bool,
35 context: Option<GoogleMapsContext>,
36}
37
38impl GoogleMapsTool {
39 pub fn new() -> Self {
40 Self::default()
41 }
42
43 pub fn with_widget(mut self, enable_widget: bool) -> Self {
44 self.enable_widget = enable_widget;
45 self
46 }
47
48 pub fn with_context(mut self, context: GoogleMapsContext) -> Self {
49 self.context = Some(context);
50 self
51 }
52}
53
54#[async_trait]
55impl Tool for GoogleMapsTool {
56 fn name(&self) -> &str {
57 "google_maps"
58 }
59
60 fn description(&self) -> &str {
61 "Grounds responses with Google Maps data for places, routes, and local context."
62 }
63
64 fn is_builtin(&self) -> bool {
65 true
66 }
67
68 fn declaration(&self) -> Value {
69 json!({
70 "name": self.name(),
71 "description": self.description(),
72 "x-adk-gemini-tool": {
73 "google_maps": {
74 "enable_widget": self.enable_widget.then_some(true),
75 }
76 },
77 "x-adk-gemini-tool-config": self.context.map(GoogleMapsContext::to_json),
78 })
79 }
80
81 async fn execute(&self, _ctx: Arc<dyn ToolContext>, _args: Value) -> Result<Value> {
82 Err(adk_core::AdkError::tool("GoogleMaps is handled internally by Gemini"))
83 }
84}
85
86#[derive(Debug, Clone, Default)]
88pub struct GeminiCodeExecutionTool;
89
90impl GeminiCodeExecutionTool {
91 pub fn new() -> Self {
92 Self
93 }
94}
95
96#[async_trait]
97impl Tool for GeminiCodeExecutionTool {
98 fn name(&self) -> &str {
99 "gemini_code_execution"
100 }
101
102 fn description(&self) -> &str {
103 "Allows Gemini to write and execute Python code server-side."
104 }
105
106 fn is_builtin(&self) -> bool {
107 true
108 }
109
110 fn declaration(&self) -> Value {
111 json!({
112 "name": self.name(),
113 "description": self.description(),
114 "x-adk-gemini-tool": {
115 "code_execution": {}
116 }
117 })
118 }
119
120 async fn execute(&self, _ctx: Arc<dyn ToolContext>, _args: Value) -> Result<Value> {
121 Err(adk_core::AdkError::tool("Gemini code execution is handled internally by Gemini"))
122 }
123}
124
125#[derive(Debug, Clone)]
127pub struct GeminiFileSearchTool {
128 file_search_store_names: Vec<String>,
129}
130
131impl GeminiFileSearchTool {
132 pub fn new(file_search_store_names: impl IntoIterator<Item = impl Into<String>>) -> Self {
133 Self {
134 file_search_store_names: file_search_store_names.into_iter().map(Into::into).collect(),
135 }
136 }
137}
138
139#[async_trait]
140impl Tool for GeminiFileSearchTool {
141 fn name(&self) -> &str {
142 "gemini_file_search"
143 }
144
145 fn description(&self) -> &str {
146 "Searches Gemini File Search stores for relevant documents."
147 }
148
149 fn is_builtin(&self) -> bool {
150 true
151 }
152
153 fn declaration(&self) -> Value {
154 json!({
155 "name": self.name(),
156 "description": self.description(),
157 "x-adk-gemini-tool": {
158 "file_search": {
159 "file_search_store_names": self.file_search_store_names
160 }
161 }
162 })
163 }
164
165 async fn execute(&self, _ctx: Arc<dyn ToolContext>, _args: Value) -> Result<Value> {
166 Err(adk_core::AdkError::tool("Gemini file search is handled internally by Gemini"))
167 }
168}
169
170#[derive(Debug, Clone, Copy, PartialEq, Eq)]
172pub enum GeminiComputerEnvironment {
173 Browser,
174}
175
176impl GeminiComputerEnvironment {
177 fn as_wire(self) -> &'static str {
178 match self {
179 Self::Browser => "ENVIRONMENT_BROWSER",
180 }
181 }
182}
183
184#[derive(Debug, Clone)]
186pub struct GeminiComputerUseTool {
187 environment: GeminiComputerEnvironment,
188 excluded_predefined_functions: Vec<String>,
189}
190
191impl Default for GeminiComputerUseTool {
192 fn default() -> Self {
193 Self {
194 environment: GeminiComputerEnvironment::Browser,
195 excluded_predefined_functions: Vec::new(),
196 }
197 }
198}
199
200impl GeminiComputerUseTool {
201 pub fn new(environment: GeminiComputerEnvironment) -> Self {
202 Self { environment, ..Default::default() }
203 }
204
205 pub fn with_excluded_functions(
206 mut self,
207 excluded_predefined_functions: impl IntoIterator<Item = impl Into<String>>,
208 ) -> Self {
209 self.excluded_predefined_functions =
210 excluded_predefined_functions.into_iter().map(Into::into).collect();
211 self
212 }
213}
214
215#[async_trait]
216impl Tool for GeminiComputerUseTool {
217 fn name(&self) -> &str {
218 "gemini_computer_use"
219 }
220
221 fn description(&self) -> &str {
222 "Enables Gemini computer use, which emits predefined UI action function calls."
223 }
224
225 fn is_builtin(&self) -> bool {
226 true
227 }
228
229 fn declaration(&self) -> Value {
230 json!({
231 "name": self.name(),
232 "description": self.description(),
233 "x-adk-gemini-tool": {
234 "computer_use": {
235 "environment": self.environment.as_wire(),
236 "excluded_predefined_functions": (!self.excluded_predefined_functions.is_empty())
237 .then_some(self.excluded_predefined_functions.clone()),
238 }
239 }
240 })
241 }
242
243 async fn execute(&self, _ctx: Arc<dyn ToolContext>, _args: Value) -> Result<Value> {
244 Err(adk_core::AdkError::tool("Gemini computer use actions must be executed client-side"))
245 }
246}