Skip to main content

rig_tools/
blocking.rs

1//! Runs blocking tool work on its own thread, so no async executor thread
2//! blocks. Tools that do file, process or long CPU work use it.
3
4use futures::channel::oneshot;
5use rig_core::tool::ToolExecutionError;
6
7/// Run `work` on a new thread and await its answer. A panic in `work`
8/// becomes an error.
9pub async fn blocking<T: Send + 'static>(
10    work: impl FnOnce() -> Result<T, ToolExecutionError> + Send + 'static,
11) -> Result<T, ToolExecutionError> {
12    let (sender, receiver) = oneshot::channel();
13    std::thread::Builder::new()
14        .name("rig-tool".to_owned())
15        .spawn(move || {
16            sender.send(work()).ok();
17        })
18        .map_err(|error| ToolExecutionError::other(format!("could not start the tool: {error}")))?;
19    receiver
20        .await
21        .map_err(|_| ToolExecutionError::other("the tool crashed before it answered"))?
22}