enact_core/callable/
callable.rs1use crate::streaming::StreamEvent;
6use async_trait::async_trait;
7use std::sync::Arc;
8use tokio::sync::mpsc;
9
10#[async_trait]
25pub trait Callable: Send + Sync {
26 fn name(&self) -> &str;
28
29 fn description(&self) -> Option<&str> {
31 None
32 }
33
34 async fn run(&self, input: &str) -> anyhow::Result<String>;
41
42 async fn run_streaming(
48 &self,
49 input: &str,
50 event_tx: mpsc::Sender<StreamEvent>,
51 ) -> anyhow::Result<String> {
52 let _ = event_tx;
53 self.run(input).await
54 }
55
56 fn last_usage(&self) -> Option<crate::kernel::LlmTokenUsage> {
62 None
63 }
64}
65
66pub type DynCallable = Arc<dyn Callable>;
71
72#[allow(dead_code)]
76pub struct FnCallable<F>
77where
78 F: Fn(&str) -> anyhow::Result<String> + Send + Sync,
79{
80 name: String,
81 description: Option<String>,
82 func: F,
83}
84
85#[allow(dead_code)]
86impl<F> FnCallable<F>
87where
88 F: Fn(&str) -> anyhow::Result<String> + Send + Sync,
89{
90 pub fn new(name: impl Into<String>, func: F) -> Self {
92 Self {
93 name: name.into(),
94 description: None,
95 func,
96 }
97 }
98
99 pub fn with_description(mut self, desc: impl Into<String>) -> Self {
101 self.description = Some(desc.into());
102 self
103 }
104}
105
106#[async_trait]
107impl<F> Callable for FnCallable<F>
108where
109 F: Fn(&str) -> anyhow::Result<String> + Send + Sync,
110{
111 fn name(&self) -> &str {
112 &self.name
113 }
114
115 fn description(&self) -> Option<&str> {
116 self.description.as_deref()
117 }
118
119 async fn run(&self, input: &str) -> anyhow::Result<String> {
120 (self.func)(input)
121 }
122}
123
124#[allow(dead_code)]
126pub struct AsyncFnCallable<F, Fut>
127where
128 F: Fn(String) -> Fut + Send + Sync,
129 Fut: std::future::Future<Output = anyhow::Result<String>> + Send + Sync,
130{
131 name: String,
132 description: Option<String>,
133 func: F,
134 _phantom: std::marker::PhantomData<fn() -> Fut>,
135}
136
137#[allow(dead_code)]
138impl<F, Fut> AsyncFnCallable<F, Fut>
139where
140 F: Fn(String) -> Fut + Send + Sync,
141 Fut: std::future::Future<Output = anyhow::Result<String>> + Send + Sync,
142{
143 pub fn new(name: impl Into<String>, func: F) -> Self {
145 Self {
146 name: name.into(),
147 description: None,
148 func,
149 _phantom: std::marker::PhantomData,
150 }
151 }
152
153 pub fn with_description(mut self, desc: impl Into<String>) -> Self {
155 self.description = Some(desc.into());
156 self
157 }
158}
159
160#[async_trait]
161impl<F, Fut> Callable for AsyncFnCallable<F, Fut>
162where
163 F: Fn(String) -> Fut + Send + Sync,
164 Fut: std::future::Future<Output = anyhow::Result<String>> + Send + Sync,
165{
166 fn name(&self) -> &str {
167 &self.name
168 }
169
170 fn description(&self) -> Option<&str> {
171 self.description.as_deref()
172 }
173
174 async fn run(&self, input: &str) -> anyhow::Result<String> {
175 (self.func)(input.to_string()).await
176 }
177}