scud/attractor/handlers/
human.rs1use anyhow::Result;
6use async_trait::async_trait;
7
8use crate::attractor::context::Context;
9use crate::attractor::graph::{PipelineGraph, PipelineNode};
10use crate::attractor::outcome::Outcome;
11use crate::attractor::run_directory::RunDirectory;
12
13use super::Handler;
14
15pub struct HumanHandler;
16
17#[async_trait]
18impl Handler for HumanHandler {
19 async fn execute(
20 &self,
21 node: &PipelineNode,
22 _context: &Context,
23 graph: &PipelineGraph,
24 _run_dir: &RunDirectory,
25 ) -> Result<Outcome> {
26 let idx = *graph.node_index.get(&node.id).unwrap();
28 let edges = graph.outgoing_edges(idx);
29
30 let choices: Vec<String> = edges
31 .iter()
32 .filter(|(_, e)| !e.label.is_empty())
33 .map(|(_, e)| e.label.clone())
34 .collect();
35
36 let _prompt = if node.prompt.is_empty() {
37 format!(
38 "Node '{}' requires human input. Choose an option:",
39 node.label
40 )
41 } else {
42 node.prompt.clone()
43 };
44
45 if let Some(first) = choices.first() {
51 Ok(Outcome::success_with_label(first.clone()))
52 } else {
53 Ok(Outcome::success())
54 }
55 }
56}