Skip to main content

jellyflow_runtime/profile/
mod.rs

1//! Domain specializations for node graphs.
2//!
3//! A profile selects:
4//! - how port types are resolved (schema vs inferred vs domain-owned),
5//! - which compatibility rules apply,
6//! - how concretization (dynamic ports) is scheduled,
7//! - how validation diagnostics are produced.
8//!
9//! This module is intentionally headless (no `fret-ui` dependency).
10
11mod domain;
12mod pipeline;
13
14use crate::io::NodeGraphInteractionState;
15use crate::rules::{ConnectPlan, Diagnostic};
16pub use domain::{
17    ConnectionRuleDescriptor, FieldSchema, GraphProfileMetadata, NodeFieldSchemaSet,
18    ValidationHint, VariableDescriptor, VariableSurfaceDescriptor,
19};
20use jellyflow_core::core::{EdgeKind, Graph, PortId};
21use jellyflow_core::interaction::NodeGraphConnectionMode;
22use jellyflow_core::types::{DefaultTypeCompatibility, TypeDesc};
23pub(crate) use pipeline::apply_transaction_with_profile_in_place;
24pub use pipeline::{
25    ApplyPipelineError, apply_connect_plan_with_profile, apply_transaction_with_profile,
26};
27
28/// Profile hooks for typed graphs and domain specialization.
29pub trait GraphProfile {
30    /// Returns renderer-neutral metadata for adapter forms, variables, rule labels, and diagnostics.
31    fn metadata(&self) -> GraphProfileMetadata {
32        GraphProfileMetadata::default()
33    }
34
35    /// Returns the current type of a port.
36    ///
37    /// Default implementations may read `Port::ty` and/or derive from node payloads.
38    fn type_of_port(&mut self, graph: &Graph, port: PortId) -> Option<TypeDesc>;
39
40    /// Plans connecting two ports under this profile.
41    ///
42    /// Implementations should call into `crate::rules` and then enforce extra constraints
43    /// (type compatibility, cycle policy, exec/data policy, etc.).
44    fn plan_connect(
45        &mut self,
46        graph: &Graph,
47        a: PortId,
48        b: PortId,
49        mode: NodeGraphConnectionMode,
50    ) -> ConnectPlan {
51        let mut compat = DefaultTypeCompatibility::default();
52        crate::rules::plan_connect_typed_with_mode_and_policy(
53            graph,
54            a,
55            b,
56            mode,
57            &NodeGraphInteractionState::default(),
58            |graph, port| self.type_of_port(graph, port),
59            &mut compat,
60        )
61    }
62
63    /// Validates a graph and returns diagnostics.
64    fn validate_graph(&mut self, graph: &Graph) -> Vec<Diagnostic>;
65
66    /// Whether the profile allows cycles for the given edge kind.
67    fn allow_cycles(&self, _edge_kind: EdgeKind) -> bool {
68        true
69    }
70
71    /// Maximum number of concretization iterations per edit.
72    ///
73    /// This bounds fixed-point scheduling to prevent oscillation.
74    fn concretize_bound(&self) -> usize {
75        8
76    }
77
78    /// Runs concretization for dynamic ports and returns additional ops to apply.
79    ///
80    /// The returned ops must be deterministic and undoable.
81    fn concretize(&mut self, _graph: &Graph) -> Vec<jellyflow_core::ops::GraphOp> {
82        Vec::new()
83    }
84}