Skip to main content

ri_agent_graph/
command.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::collections::HashMap;
4
5/// Output from a node execution.
6#[derive(Debug, Clone)]
7pub enum NodeOutput {
8    /// Standard completion - node modified state directly, follow normal edges
9    Done,
10    /// Command - state update + navigation instruction
11    Command(Command),
12}
13
14/// A command that combines state updates with navigation instructions.
15#[derive(Debug, Clone)]
16pub struct Command {
17    /// Optional state updates to apply
18    pub update: Option<HashMap<String, Value>>,
19    /// Navigation instruction
20    pub goto: Navigation,
21}
22
23/// Navigation instructions for graph traversal.
24#[derive(Debug, Clone)]
25pub enum Navigation {
26    /// Go to a specific node
27    Node(String),
28    /// Fan-out to multiple nodes simultaneously
29    Nodes(Vec<String>),
30    /// Terminate execution
31    End,
32    /// Dynamic fan-out with per-branch state
33    Send(Vec<SendOp>),
34    /// Follow normal edges (default behavior)
35    Default,
36}
37
38/// A send operation for dynamic fan-out with custom state per branch.
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct SendOp {
41    /// Target node name
42    pub node: String,
43    /// Custom state values for this branch
44    pub state: HashMap<String, Value>,
45}
46
47impl Command {
48    /// Create a command that navigates to a specific node
49    pub fn goto(node: impl Into<String>) -> Self {
50        Self {
51            update: None,
52            goto: Navigation::Node(node.into()),
53        }
54    }
55
56    /// Create a command that ends execution
57    pub fn end() -> Self {
58        Self {
59            update: None,
60            goto: Navigation::End,
61        }
62    }
63
64    /// Create a command with state updates and default navigation
65    pub fn update(updates: HashMap<String, Value>) -> Self {
66        Self {
67            update: Some(updates),
68            goto: Navigation::Default,
69        }
70    }
71
72    /// Add state updates to this command
73    pub fn with_update(mut self, updates: HashMap<String, Value>) -> Self {
74        self.update = Some(updates);
75        self
76    }
77
78    /// Set the navigation for this command
79    pub fn with_goto(mut self, goto: Navigation) -> Self {
80        self.goto = goto;
81        self
82    }
83}
84
85impl NodeOutput {
86    /// Create a command that navigates to a specific node
87    pub fn goto(node: impl Into<String>) -> Self {
88        NodeOutput::Command(Command::goto(node))
89    }
90
91    /// Create a command that ends execution
92    pub fn end() -> Self {
93        NodeOutput::Command(Command::end())
94    }
95}
96
97impl From<()> for NodeOutput {
98    fn from((): ()) -> Self {
99        NodeOutput::Done
100    }
101}