crb_superagent/mission/
async_fn.rs

1use super::{Goal, Mission, runtime::RunMission};
2use anyhow::Result;
3use async_trait::async_trait;
4use crb_agent::{Address, Agent, AgentSession, Context, DoAsync, Next};
5use futures::Future;
6
7impl<T: Goal> RunMission<AsyncFn<T>> {
8    pub fn new_async<F: AnyAsyncFut<T>>(fut: F) -> Self {
9        let task = AsyncFn::<T> {
10            fut: Some(Box::new(fut)),
11            output: None,
12        };
13        Self::new(task)
14    }
15}
16
17pub trait AnyAsyncFut<T = ()>: Future<Output = T> + Send + 'static {}
18
19impl<F, T> AnyAsyncFut<T> for F where F: Future<Output = T> + Send + 'static {}
20
21pub struct AsyncFn<T> {
22    fut: Option<Box<dyn AnyAsyncFut<T>>>,
23    output: Option<T>,
24}
25
26impl<T: Goal> Agent for AsyncFn<T> {
27    type Context = AgentSession<Self>;
28    type Link = Address<Self>;
29
30    fn initialize(&mut self, _ctx: &mut Context<Self>) -> Next<Self> {
31        Next::do_async(AwaitFut)
32    }
33}
34
35#[async_trait]
36impl<T: Goal> Mission for AsyncFn<T> {
37    type Goal = T;
38
39    async fn deliver(self, _ctx: &mut Context<Self>) -> Option<Self::Goal> {
40        self.output
41    }
42}
43
44struct AwaitFut;
45
46#[async_trait]
47impl<T: Goal> DoAsync<AwaitFut> for AsyncFn<T> {
48    async fn once(&mut self, _state: &mut AwaitFut) -> Result<Next<Self>> {
49        let fut = self.fut.take().unwrap();
50        let pinned_fut = Box::into_pin(fut);
51        let output = pinned_fut.await;
52        self.output = Some(output);
53        Ok(Next::done())
54    }
55}