1use anyhow::{anyhow, Result};
2use schemars::{schema_for, JsonSchema};
3use serde::{Deserialize, Serialize};
4use serde_json::{to_value, Value};
5use std::future::Future;
6use tokio::{spawn, sync::mpsc};
7
8pub async fn wrap_unsafe<F, Fut, T>(f: F) -> Result<T>
9where
10 F: FnOnce() -> Fut + Send + 'static,
11 Fut: Future<Output = anyhow::Result<T>> + Send + 'static,
12 T: Send + 'static,
13{
14 let (tx, mut rx) = mpsc::channel(1);
15
16 spawn(async move {
17 let result = f().await;
18 let _ = tx.send(result).await;
19 });
20
21 rx.recv().await.ok_or_else(|| anyhow!("Channel closed"))?
22}
23
24#[derive(Debug)]
25pub struct ToolError(pub String);
26
27impl ToolError {
28 pub fn new(s: impl Into<String>) -> Self {
29 ToolError(s.into())
30 }
31}
32
33impl std::fmt::Display for ToolError {
34 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
35 write!(f, "{}", self.0)
36 }
37}
38
39impl std::error::Error for ToolError {}
40
41impl From<anyhow::Error> for ToolError {
42 fn from(e: anyhow::Error) -> Self {
43 ToolError(e.to_string())
44 }
45}
46
47impl From<Box<dyn std::error::Error + Send + Sync + 'static>> for ToolError {
48 fn from(e: Box<dyn std::error::Error + Send + Sync + 'static>) -> Self {
49 ToolError(e.to_string())
50 }
51}
52
53#[derive(Debug, Serialize, Deserialize)]
54pub struct ToolOutput {
55 pub result: Value,
56}
57
58pub fn derive_parameters<T: JsonSchema + for<'de> Deserialize<'de>>() -> serde_json::Value {
59 to_value(schema_for!(T)).expect("Failed to serialize schema")
60}