Skip to main content

bamboo_server/workflow/
mod.rs

1//! Workflow system for defining and executing agent workflows
2//!
3//! This module provides a workflow engine that allows users to define
4//! complex agent behaviors using a declarative composition syntax.
5//!
6//! The domain types (`WorkflowDefinition`, validation) live in
7//! `bamboo-domain-workflow`. This module keeps the filesystem loader
8//! and cache.
9
10mod loader;
11mod run;
12
13pub(crate) use run::public_workflow_snapshot;
14pub use run::{WorkflowRunAccess, WorkflowRunTool};
15
16#[cfg(test)]
17mod tests;
18
19use std::collections::HashMap;
20use std::path::{Path, PathBuf};
21use std::sync::RwLock;
22use std::time::SystemTime;
23
24use bamboo_domain::{WorkflowDefinition, WorkflowLoadError};
25
26#[derive(Debug, Clone)]
27pub(crate) struct CachedWorkflow {
28    pub(crate) modified: Option<SystemTime>,
29    pub(crate) definition: WorkflowDefinition,
30}
31
32pub struct WorkflowLoader {
33    workflows_dir: PathBuf,
34    cache: RwLock<HashMap<PathBuf, CachedWorkflow>>,
35}
36
37impl WorkflowLoader {
38    pub fn new() -> Self {
39        Self {
40            workflows_dir: bamboo_config::paths::workflows_dir(),
41            cache: RwLock::new(HashMap::new()),
42        }
43    }
44
45    pub fn with_dir(path: PathBuf) -> Self {
46        Self {
47            workflows_dir: path,
48            cache: RwLock::new(HashMap::new()),
49        }
50    }
51
52    pub fn load_from_file<P>(&self, path: P) -> Result<WorkflowDefinition, WorkflowLoadError>
53    where
54        P: AsRef<Path>,
55    {
56        loader::load_from_file(self, path.as_ref())
57    }
58
59    pub fn load_all_from_directory<P>(
60        &self,
61        dir: P,
62    ) -> Result<Vec<WorkflowDefinition>, WorkflowLoadError>
63    where
64        P: AsRef<Path>,
65    {
66        loader::load_all_from_directory(self, dir.as_ref())
67    }
68
69    pub fn load_all(&self) -> Result<Vec<WorkflowDefinition>, WorkflowLoadError> {
70        self.load_all_from_directory(&self.workflows_dir)
71    }
72
73    pub fn validate_definition(&self, definition: &WorkflowDefinition) -> Result<(), String> {
74        definition.validate()
75    }
76
77    pub(crate) fn validate_with_path(
78        &self,
79        path: &Path,
80        definition: &WorkflowDefinition,
81    ) -> Result<(), WorkflowLoadError> {
82        definition
83            .validate()
84            .map_err(|message| WorkflowLoadError::InvalidWorkflow {
85                path: path.to_path_buf(),
86                message,
87            })
88    }
89}
90
91impl Default for WorkflowLoader {
92    fn default() -> Self {
93        Self::new()
94    }
95}