Skip to main content

worldinterface_core/flowspec/
mod.rs

1//! FlowSpec — the declarative workflow graph model.
2//!
3//! A `FlowSpec` is the primary input to WorldInterface. It describes a
4//! directed acyclic graph of nodes (connectors, transforms, branches) connected
5//! by edges. FlowSpecs can be ephemeral (agent-submitted JSON) or named
6//! (persisted, reusable).
7
8pub mod branch;
9pub mod connector;
10pub mod edge;
11pub mod topo;
12pub mod transform;
13pub mod validate;
14
15pub use branch::{BranchCondition, BranchNode, ParamRef};
16pub use connector::{ConnectorNode, IdempotencyConfig, IdempotencyStrategy};
17pub use edge::{Edge, EdgeCondition};
18use serde::{Deserialize, Serialize};
19use serde_json::Value;
20pub use transform::{FieldMapping, FieldMappingSpec, TransformNode, TransformType};
21pub use validate::{ValidationDiagnostic, ValidationError, ValidationRule};
22
23use crate::id::{FlowId, NodeId};
24
25/// A declarative workflow graph.
26#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
27pub struct FlowSpec {
28    /// Flow identity. `None` for ephemeral (agent-submitted) flows; the system
29    /// assigns an ID at submission time if not provided.
30    #[serde(default, skip_serializing_if = "Option::is_none")]
31    pub id: Option<FlowId>,
32    /// Human-readable name.
33    #[serde(default, skip_serializing_if = "Option::is_none")]
34    pub name: Option<String>,
35    /// Ordered list of nodes in the graph.
36    pub nodes: Vec<Node>,
37    /// Directed edges between nodes.
38    pub edges: Vec<Edge>,
39    /// Flow-level parameters available to all nodes.
40    #[serde(default, skip_serializing_if = "Option::is_none")]
41    pub params: Option<Value>,
42}
43
44impl FlowSpec {
45    /// Validate this FlowSpec, returning all validation errors found.
46    pub fn validate(&self) -> Result<(), ValidationError> {
47        validate::validate(self)
48    }
49}
50
51/// A node in a FlowSpec graph.
52#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
53pub struct Node {
54    /// Unique identity of this node within the FlowSpec.
55    pub id: NodeId,
56    /// Human-readable label.
57    #[serde(default, skip_serializing_if = "Option::is_none")]
58    pub label: Option<String>,
59    /// The node's type and type-specific configuration.
60    pub node_type: NodeType,
61}
62
63/// The type of a node, determining its behavior.
64#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
65#[serde(rename_all = "snake_case")]
66pub enum NodeType {
67    /// A boundary-crossing node that invokes an external connector.
68    Connector(ConnectorNode),
69    /// A pure transform node with no side effects.
70    Transform(TransformNode),
71    /// A conditional routing node.
72    Branch(BranchNode),
73}