gemini_live_harness/
adapter.rs1use futures_util::future::BoxFuture;
9use gemini_live::types::{FunctionCallRequest, FunctionResponse, Tool};
10
11#[derive(Debug, thiserror::Error)]
13pub enum ToolExecutionError {
14 #[error("unsupported function `{name}`")]
15 UnsupportedFunction { name: String },
16 #[error("tool execution failed: {message}")]
17 Failed { message: String },
18 #[error("tool call `{call_id}` was cancelled")]
19 Cancelled { call_id: String },
20}
21
22impl ToolExecutionError {
23 pub fn unsupported_function(name: impl Into<String>) -> Self {
24 Self::UnsupportedFunction { name: name.into() }
25 }
26
27 pub fn failed(message: impl Into<String>) -> Self {
28 Self::Failed {
29 message: message.into(),
30 }
31 }
32
33 pub fn cancelled(call_id: impl Into<String>) -> Self {
34 Self::Cancelled {
35 call_id: call_id.into(),
36 }
37 }
38}
39
40#[derive(Debug, Clone, PartialEq, Eq)]
42pub struct ToolDescriptor {
43 pub key: String,
44 pub summary: String,
45 pub kind: ToolKind,
46}
47
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub enum ToolKind {
51 BuiltIn,
52 Local,
53 Remote,
54}
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
58pub struct ToolCapability {
59 pub can_continue_async_after_timeout: bool,
60}
61
62impl ToolCapability {
63 pub const INLINE_ONLY: Self = Self {
64 can_continue_async_after_timeout: false,
65 };
66
67 pub const BACKGROUND_CONTINUABLE: Self = Self {
68 can_continue_async_after_timeout: true,
69 };
70}
71
72#[derive(Debug, Clone, PartialEq, Eq)]
74pub struct ToolSpecification {
75 pub function_name: String,
76 pub capability: ToolCapability,
77}
78
79impl ToolSpecification {
80 pub fn new(function_name: impl Into<String>, capability: ToolCapability) -> Self {
81 Self {
82 function_name: function_name.into(),
83 capability,
84 }
85 }
86}
87
88pub trait ToolProvider: Send + Sync + 'static {
90 fn advertised_tools(&self) -> Option<Vec<Tool>> {
92 None
93 }
94
95 fn descriptors(&self) -> Vec<ToolDescriptor> {
97 Vec::new()
98 }
99
100 fn specifications(&self) -> Vec<ToolSpecification> {
102 Vec::new()
103 }
104}
105
106pub trait ToolExecutor: Send + Sync + 'static {
108 fn execute<'a>(
110 &'a self,
111 call: FunctionCallRequest,
112 ) -> BoxFuture<'a, Result<FunctionResponse, ToolExecutionError>>;
113
114 fn cancel(&self, _call_id: &str) -> bool {
116 false
117 }
118}
119
120#[derive(Debug, Default, Clone, Copy)]
122pub struct NoopToolSource;
123
124impl ToolProvider for NoopToolSource {}
125
126impl ToolExecutor for NoopToolSource {
127 fn execute<'a>(
128 &'a self,
129 call: FunctionCallRequest,
130 ) -> BoxFuture<'a, Result<FunctionResponse, ToolExecutionError>> {
131 Box::pin(async move { Err(ToolExecutionError::unsupported_function(call.name)) })
132 }
133}