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 pipeline;
12
13use crate::io::NodeGraphInteractionState;
14use crate::rules::{ConnectPlan, Diagnostic};
15use jellyflow_core::core::{EdgeKind, Graph, PortId};
16use jellyflow_core::interaction::NodeGraphConnectionMode;
17use jellyflow_core::types::{DefaultTypeCompatibility, TypeDesc};
18pub(crate) use pipeline::apply_transaction_with_profile_in_place;
19pub use pipeline::{
20    ApplyPipelineError, apply_connect_plan_with_profile, apply_transaction_with_profile,
21};
22
23/// Profile hooks for typed graphs and domain specialization.
24pub trait GraphProfile {
25    /// Returns the current type of a port.
26    ///
27    /// Default implementations may read `Port::ty` and/or derive from node payloads.
28    fn type_of_port(&mut self, graph: &Graph, port: PortId) -> Option<TypeDesc>;
29
30    /// Plans connecting two ports under this profile.
31    ///
32    /// Implementations should call into `crate::rules` and then enforce extra constraints
33    /// (type compatibility, cycle policy, exec/data policy, etc.).
34    fn plan_connect(
35        &mut self,
36        graph: &Graph,
37        a: PortId,
38        b: PortId,
39        mode: NodeGraphConnectionMode,
40    ) -> ConnectPlan {
41        let mut compat = DefaultTypeCompatibility::default();
42        crate::rules::plan_connect_typed_with_mode_and_policy(
43            graph,
44            a,
45            b,
46            mode,
47            &NodeGraphInteractionState::default(),
48            |graph, port| self.type_of_port(graph, port),
49            &mut compat,
50        )
51    }
52
53    /// Validates a graph and returns diagnostics.
54    fn validate_graph(&mut self, graph: &Graph) -> Vec<Diagnostic>;
55
56    /// Whether the profile allows cycles for the given edge kind.
57    fn allow_cycles(&self, _edge_kind: EdgeKind) -> bool {
58        true
59    }
60
61    /// Maximum number of concretization iterations per edit.
62    ///
63    /// This bounds fixed-point scheduling to prevent oscillation.
64    fn concretize_bound(&self) -> usize {
65        8
66    }
67
68    /// Runs concretization for dynamic ports and returns additional ops to apply.
69    ///
70    /// The returned ops must be deterministic and undoable.
71    fn concretize(&mut self, _graph: &Graph) -> Vec<jellyflow_core::ops::GraphOp> {
72        Vec::new()
73    }
74}