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;
11
12#[cfg(test)]
13mod tests;
14
15use std::collections::HashMap;
16use std::path::{Path, PathBuf};
17use std::sync::RwLock;
18use std::time::SystemTime;
19
20use bamboo_domain::{WorkflowDefinition, WorkflowLoadError};
21
22#[derive(Debug, Clone)]
23pub(crate) struct CachedWorkflow {
24    pub(crate) modified: Option<SystemTime>,
25    pub(crate) definition: WorkflowDefinition,
26}
27
28pub struct WorkflowLoader {
29    workflows_dir: PathBuf,
30    cache: RwLock<HashMap<PathBuf, CachedWorkflow>>,
31}
32
33impl WorkflowLoader {
34    pub fn new() -> Self {
35        Self {
36            workflows_dir: bamboo_infrastructure::paths::workflows_dir(),
37            cache: RwLock::new(HashMap::new()),
38        }
39    }
40
41    pub fn with_dir(path: PathBuf) -> Self {
42        Self {
43            workflows_dir: path,
44            cache: RwLock::new(HashMap::new()),
45        }
46    }
47
48    pub fn load_from_file<P>(&self, path: P) -> Result<WorkflowDefinition, WorkflowLoadError>
49    where
50        P: AsRef<Path>,
51    {
52        loader::load_from_file(self, path.as_ref())
53    }
54
55    pub fn load_all_from_directory<P>(
56        &self,
57        dir: P,
58    ) -> Result<Vec<WorkflowDefinition>, WorkflowLoadError>
59    where
60        P: AsRef<Path>,
61    {
62        loader::load_all_from_directory(self, dir.as_ref())
63    }
64
65    pub fn load_all(&self) -> Result<Vec<WorkflowDefinition>, WorkflowLoadError> {
66        self.load_all_from_directory(&self.workflows_dir)
67    }
68
69    pub fn validate_definition(&self, definition: &WorkflowDefinition) -> Result<(), String> {
70        definition.validate()
71    }
72
73    pub(crate) fn validate_with_path(
74        &self,
75        path: &Path,
76        definition: &WorkflowDefinition,
77    ) -> Result<(), WorkflowLoadError> {
78        definition
79            .validate()
80            .map_err(|message| WorkflowLoadError::InvalidWorkflow {
81                path: path.to_path_buf(),
82                message,
83            })
84    }
85}
86
87impl Default for WorkflowLoader {
88    fn default() -> Self {
89        Self::new()
90    }
91}