use crate::config::{Config, WorkflowDefinition};
use crate::session::Session;
use anyhow::Result;
use serde::{Deserialize, Serialize};
use super::executor::{StepExecutor, WorkflowContext};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkflowProgress {
pub step_outputs: Vec<StepOutput>,
pub duration_secs: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StepOutput {
pub step_name: String,
pub step_index: usize,
pub total_steps: usize,
pub content: String,
pub duration_ms: u64,
}
pub struct WorkflowOrchestrator {
workflow: WorkflowDefinition,
workflow_name: String,
}
impl WorkflowOrchestrator {
pub fn new(workflow: WorkflowDefinition, workflow_name: String) -> Self {
Self {
workflow,
workflow_name,
}
}
pub async fn execute(
&self,
input: &str,
session: &mut Session,
config: &Config,
operation_cancelled: tokio::sync::watch::Receiver<bool>,
) -> Result<(String, WorkflowProgress)> {
let workflow_start = std::time::Instant::now();
let mut current_input = input.to_string();
let mut step_outputs = Vec::new();
let total_steps = self.workflow.steps.len();
for (i, step) in self.workflow.steps.iter().enumerate() {
let step_result = StepExecutor::execute_step(
step,
¤t_input,
session,
config,
operation_cancelled.clone(),
WorkflowContext {
step_index: i + 1,
total_steps,
workflow_name: &self.workflow_name,
},
)
.await?;
if *operation_cancelled.borrow() {
return Err(anyhow::anyhow!("Operation cancelled"));
}
current_input = step_result.output;
step_outputs.push(StepOutput {
step_name: step_result.step_name,
step_index: i + 1,
total_steps,
content: current_input.clone(),
duration_ms: step_result.duration_ms,
});
}
let duration_secs = workflow_start.elapsed().as_secs_f64();
let progress = WorkflowProgress {
step_outputs,
duration_secs,
};
Ok((current_input, progress))
}
}