1use crate::event::EventStream;
2use crate::types::JsonValue;
3use async_trait::async_trait;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
8#[serde(rename_all = "snake_case")]
9pub enum StepType {
10 Agent,
11 Transform,
12 Conditional,
13 Parallel,
14 SubWorkflow,
15 Custom(String),
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct StepInput {
21 pub data: JsonValue,
22 pub metadata: StepInputMetadata,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct StepInputMetadata {
27 pub step_index: usize,
28 pub previous_step: Option<String>,
29 pub workflow_id: String,
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct StepOutput {
35 pub data: JsonValue,
36 pub metadata: StepOutputMetadata,
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct StepOutputMetadata {
41 pub step_name: String,
42 pub step_type: StepType,
43 pub execution_time_ms: u64,
44}
45
46pub type StepResult = Result<StepOutput, StepError>;
48
49#[derive(Debug, Clone, Serialize, Deserialize, thiserror::Error)]
51pub enum StepError {
52 #[error("Execution failed: {0}")]
53 ExecutionFailed(String),
54
55 #[error("Invalid input: {0}")]
56 InvalidInput(String),
57
58 #[error("Agent error: {0}")]
59 AgentError(String),
60
61 #[error("Step not found: {0}")]
62 StepNotFound(String),
63}
64
65pub struct ExecutionContext<'a> {
67 pub event_stream: Option<&'a EventStream>,
68}
69
70impl<'a> Default for ExecutionContext<'a> {
71 fn default() -> Self {
72 Self::new()
73 }
74}
75
76impl<'a> ExecutionContext<'a> {
77 pub fn new() -> Self {
78 Self { event_stream: None }
79 }
80
81 pub fn with_event_stream(event_stream: &'a EventStream) -> Self {
82 Self {
83 event_stream: Some(event_stream),
84 }
85 }
86}
87
88#[async_trait]
90pub trait Step: Send + Sync {
91 async fn execute(&self, input: StepInput) -> StepResult {
93 self.execute_with_context(input, ExecutionContext::new())
94 .await
95 }
96
97 async fn execute_with_context(&self, input: StepInput, ctx: ExecutionContext<'_>)
99 -> StepResult;
100
101 fn name(&self) -> &str;
103
104 fn step_type(&self) -> StepType;
106
107 fn description(&self) -> Option<&str> {
109 None
110 }
111
112 fn get_branches(&self) -> Option<(&dyn Step, &dyn Step)> {
114 None
115 }
116
117 fn get_sub_workflow(&self) -> Option<crate::workflow::Workflow> {
119 None
120 }
121}