simple_agents_workflow/yaml_runner/
runner.rs1use std::path::Path;
2
3use serde_json::{json, Value};
4use simple_agents_core::SimpleAgentsClient;
5
6use super::{
7 load_workflow_yaml_file,
8 run_workflow_yaml_with_client_and_custom_worker_and_events_and_options,
9 run_workflow_yaml_with_custom_worker_and_events_and_options, YamlWorkflow,
10 YamlWorkflowCustomWorkerExecutor, YamlWorkflowEventSink, YamlWorkflowLlmExecutor,
11 YamlWorkflowRunError, YamlWorkflowRunOptions, YamlWorkflowRunOutput,
12};
13
14#[derive(Clone, Copy)]
15enum WorkflowRunnerExecutor<'a> {
16 Llm(&'a dyn YamlWorkflowLlmExecutor),
17 Client(&'a SimpleAgentsClient),
18}
19
20#[derive(Clone, Copy)]
21enum WorkflowRunnerSource<'a> {
22 File(&'a Path),
23 Inline(&'a YamlWorkflow),
24}
25
26pub struct WorkflowRunner<'a> {
31 source: WorkflowRunnerSource<'a>,
32 workflow_input: Option<&'a Value>,
33 email_text: Option<&'a str>,
34 executor: Option<WorkflowRunnerExecutor<'a>>,
35 custom_worker: Option<&'a dyn YamlWorkflowCustomWorkerExecutor>,
36 event_sink: Option<&'a dyn YamlWorkflowEventSink>,
37 options: Option<&'a YamlWorkflowRunOptions>,
38}
39
40impl<'a> WorkflowRunner<'a> {
41 pub fn from_file(workflow_path: &'a Path) -> Self {
42 Self {
43 source: WorkflowRunnerSource::File(workflow_path),
44 workflow_input: None,
45 email_text: None,
46 executor: None,
47 custom_worker: None,
48 event_sink: None,
49 options: None,
50 }
51 }
52
53 pub fn from_workflow(workflow: &'a YamlWorkflow) -> Self {
54 Self {
55 source: WorkflowRunnerSource::Inline(workflow),
56 workflow_input: None,
57 email_text: None,
58 executor: None,
59 custom_worker: None,
60 event_sink: None,
61 options: None,
62 }
63 }
64
65 pub fn with_input(mut self, workflow_input: &'a Value) -> Self {
66 self.workflow_input = Some(workflow_input);
67 self
68 }
69
70 pub fn with_email_text(mut self, email_text: &'a str) -> Self {
71 self.email_text = Some(email_text);
72 self
73 }
74
75 pub fn with_executor(mut self, executor: &'a dyn YamlWorkflowLlmExecutor) -> Self {
76 self.executor = Some(WorkflowRunnerExecutor::Llm(executor));
77 self
78 }
79
80 pub fn with_client(mut self, client: &'a SimpleAgentsClient) -> Self {
81 self.executor = Some(WorkflowRunnerExecutor::Client(client));
82 self
83 }
84
85 pub fn with_custom_worker(
86 mut self,
87 custom_worker: Option<&'a dyn YamlWorkflowCustomWorkerExecutor>,
88 ) -> Self {
89 self.custom_worker = custom_worker;
90 self
91 }
92
93 pub fn with_event_sink(mut self, event_sink: Option<&'a dyn YamlWorkflowEventSink>) -> Self {
94 self.event_sink = event_sink;
95 self
96 }
97
98 pub fn with_options(mut self, options: &'a YamlWorkflowRunOptions) -> Self {
99 self.options = Some(options);
100 self
101 }
102
103 pub async fn run(self) -> Result<YamlWorkflowRunOutput, YamlWorkflowRunError> {
104 let fallback_input;
105 let workflow_input = if let Some(workflow_input) = self.workflow_input {
106 workflow_input
107 } else if let Some(email_text) = self.email_text {
108 fallback_input = json!({ "email_text": email_text });
109 &fallback_input
110 } else {
111 return Err(YamlWorkflowRunError::InvalidInput {
112 message: "workflow input is required; call with_input(...) or with_email_text(...)"
113 .to_string(),
114 });
115 };
116
117 let default_options;
118 let options = if let Some(options) = self.options {
119 options
120 } else {
121 default_options = YamlWorkflowRunOptions::default();
122 &default_options
123 };
124
125 let executor = self
126 .executor
127 .ok_or_else(|| YamlWorkflowRunError::InvalidInput {
128 message:
129 "workflow executor is required; call with_executor(...) or with_client(...)"
130 .to_string(),
131 })?;
132
133 match (self.source, executor) {
134 (WorkflowRunnerSource::File(path), WorkflowRunnerExecutor::Llm(executor)) => {
135 let (_, workflow) = load_workflow_yaml_file(path)?;
136 run_workflow_yaml_with_custom_worker_and_events_and_options(
137 &workflow,
138 workflow_input,
139 executor,
140 self.custom_worker,
141 self.event_sink,
142 options,
143 )
144 .await
145 }
146 (WorkflowRunnerSource::File(path), WorkflowRunnerExecutor::Client(client)) => {
147 let (_, workflow) = load_workflow_yaml_file(path)?;
148 run_workflow_yaml_with_client_and_custom_worker_and_events_and_options(
149 &workflow,
150 workflow_input,
151 client,
152 self.custom_worker,
153 self.event_sink,
154 options,
155 )
156 .await
157 }
158 (WorkflowRunnerSource::Inline(workflow), WorkflowRunnerExecutor::Llm(executor)) => {
159 run_workflow_yaml_with_custom_worker_and_events_and_options(
160 workflow,
161 workflow_input,
162 executor,
163 self.custom_worker,
164 self.event_sink,
165 options,
166 )
167 .await
168 }
169 (WorkflowRunnerSource::Inline(workflow), WorkflowRunnerExecutor::Client(client)) => {
170 run_workflow_yaml_with_client_and_custom_worker_and_events_and_options(
171 workflow,
172 workflow_input,
173 client,
174 self.custom_worker,
175 self.event_sink,
176 options,
177 )
178 .await
179 }
180 }
181 }
182}