bamboo_agent_core/composition/
expr.rs1use crate::tools::ToolError;
9
10pub use bamboo_domain::composition::{Condition, ParallelWait, ToolExpr};
12
13#[derive(Debug, Clone)]
15pub enum CompositionError {
16 ToolError(ToolError),
17 VariableNotFound(String),
18 InvalidExpression(String),
19 MaxRetriesExceeded,
20}
21
22impl std::fmt::Display for CompositionError {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 match self {
25 CompositionError::ToolError(e) => write!(f, "Tool error: {}", e),
26 CompositionError::VariableNotFound(v) => write!(f, "Variable not found: {}", v),
27 CompositionError::InvalidExpression(e) => write!(f, "Invalid expression: {}", e),
28 CompositionError::MaxRetriesExceeded => write!(f, "Maximum retry attempts exceeded"),
29 }
30 }
31}
32
33impl std::error::Error for CompositionError {
34 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
35 match self {
36 CompositionError::ToolError(e) => Some(e),
37 _ => None,
38 }
39 }
40}
41
42impl From<ToolError> for CompositionError {
43 fn from(e: ToolError) -> Self {
44 CompositionError::ToolError(e)
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51 use serde_json::json;
52
53 #[test]
54 fn test_call_expr() {
55 let expr = ToolExpr::call("read_file", json!({"path": "/tmp/test"}));
56 match expr {
57 ToolExpr::Call { tool, args } => {
58 assert_eq!(tool, "read_file");
59 assert_eq!(args["path"], "/tmp/test");
60 }
61 _ => panic!("Expected Call variant"),
62 }
63 }
64
65 #[test]
66 fn test_yaml_roundtrip() {
67 let expr = ToolExpr::sequence(vec![
68 ToolExpr::call("step1", json!({"arg": 1})),
69 ToolExpr::call("step2", json!({"arg": 2})),
70 ]);
71 let yaml = expr.to_yaml().unwrap();
72 let deserialized = ToolExpr::from_yaml(&yaml).unwrap();
73 assert_eq!(expr, deserialized);
74 }
75}