use async_trait::async_trait;
use std::sync::Arc;
use super::{Orchestrator, RunContext};
use crate::task::AgentTask;
use crate::AgentError;
pub struct SequentialPipeline {
stages: Vec<Arc<dyn Orchestrator<Input = AgentTask, Output = String>>>,
}
impl SequentialPipeline {
pub fn new(stages: Vec<Arc<dyn Orchestrator<Input = AgentTask, Output = String>>>) -> Self {
Self { stages }
}
pub fn push_stage(
mut self,
stage: Arc<dyn Orchestrator<Input = AgentTask, Output = String>>,
) -> Self {
self.stages.push(stage);
self
}
}
#[async_trait]
impl Orchestrator for SequentialPipeline {
type Input = AgentTask;
type Output = String;
async fn run_with_context(
&self,
input: Self::Input,
ctx: &RunContext,
) -> Result<Self::Output, AgentError> {
let mut current = input;
for (i, stage) in self.stages.iter().enumerate() {
log::debug!(
target: "lc_agents::orchestrator",
"SequentialPipeline stage {i} trace_id = {}",
ctx.trace_id
);
let output = stage
.run_with_context(current.clone(), ctx)
.await
.map_err(|e| AgentError::Other(format!("SequentialPipeline stage {i}: {e}")))?;
let mut next = AgentTask::new(output);
if let Some(expected) = current.expected_output.clone() {
next = next.with_expected_output(expected);
}
next = next.with_allowed_tools(current.allowed_tools.clone());
current = next;
}
Ok(current.objective)
}
}