1use crate::errors::BoxedError;
2use futures::future::BoxFuture;
3
4#[allow(clippy::type_complexity)]
5pub enum InstructionParam<TCtx> {
6 String(String),
7 Func(Box<dyn Fn(&TCtx) -> Result<String, BoxedError> + Send + Sync>),
8 AsyncFunc(Box<dyn Fn(&TCtx) -> BoxFuture<'_, Result<String, BoxedError>> + Send + Sync>),
9}
10
11impl<TCtx> InstructionParam<TCtx> {
12 pub async fn as_string(&self, context: &TCtx) -> Result<String, BoxedError> {
13 match self {
14 Self::String(s) => Ok(s.clone()),
15 Self::Func(f) => f(context),
16 Self::AsyncFunc(f) => f(context).await,
17 }
18 }
19}
20
21impl<TCtx> From<String> for InstructionParam<TCtx> {
22 fn from(value: String) -> Self {
23 Self::String(value)
24 }
25}
26
27impl<TCtx> From<&str> for InstructionParam<TCtx> {
28 fn from(value: &str) -> Self {
29 Self::String(value.to_string())
30 }
31}
32
33impl<TCtx, F> From<F> for InstructionParam<TCtx>
34where
35 F: Fn(&TCtx) -> Result<String, BoxedError> + Send + Sync + 'static,
36 TCtx: Send + Sync + 'static,
37{
38 fn from(value: F) -> Self {
39 Self::Func(Box::new(value))
40 }
41}
42
43pub async fn get_prompt<TCtx>(
44 instructions: &[InstructionParam<TCtx>],
45 context: &TCtx,
46) -> Result<String, BoxedError> {
47 let results =
48 futures::future::join_all(instructions.iter().map(|param| param.as_string(context))).await;
49 Ok(results
50 .into_iter()
51 .collect::<Result<Vec<_>, _>>()?
52 .join("\n"))
53}