@@ -14,6 +14,24 @@ class Workflow:
1414 def __init__ (self , name : str , nodes : list [Step [Any , Any ]]) -> None :
1515 self .name = name
1616 self .nodes = nodes
17+ self .dependencies : set [str ] = set ()
18+
19+ def to_subworkflow_step (self ) -> Step [Any , Any ]:
20+ """Convert this workflow to a SubworkflowStep for composition."""
21+ from fastapi_cloudflow .core .subworkflow import SubworkflowStep
22+
23+ # Get input/output models from first and last steps
24+ if not self .nodes :
25+ raise ValueError (f"Workflow '{ self .name } ' has no steps" )
26+
27+ first_step = self .nodes [0 ]
28+ last_step = self .nodes [- 1 ]
29+
30+ return SubworkflowStep (
31+ workflow_id = self .name ,
32+ input_model = first_step .input_model ,
33+ output_model = last_step .output_model ,
34+ )
1735
1836
1937class Registry :
@@ -44,21 +62,36 @@ class WorkflowBuilder:
4462 def __init__ (self , name : str , nodes : list [Step [Any , Any ]] | None = None ) -> None :
4563 self .name = name
4664 self .nodes = nodes or []
65+ self ._dependencies : set [str ] = set ()
66+
67+ def __rshift__ (self , other : Step [Any , Any ] | Workflow ) -> WorkflowBuilder :
68+ # Convert Workflow to SubworkflowStep if needed
69+ if isinstance (other , Workflow ):
70+ step = other .to_subworkflow_step ()
71+ # Track dependency
72+ self ._dependencies .add (other .name )
73+ else :
74+ step = other
4775
48- def __rshift__ (self , other : Step [Any , Any ]) -> WorkflowBuilder :
4976 if self .nodes :
5077 prev = self .nodes [- 1 ]
51- if prev .output_model is not other .input_model :
78+ if prev .output_model is not step .input_model :
5279 raise TypeError (
5380 f"Type mismatch: { prev .name } outputs { prev .output_model .__name__ } "
54- f"but { other .name } expects { other .input_model .__name__ } "
81+ f"but { step .name } expects { step .input_model .__name__ } "
5582 )
56- return WorkflowBuilder (self .name , self .nodes + [other ])
83+
84+ # Create new builder with updated nodes and preserve dependencies
85+ new_builder = WorkflowBuilder (self .name , self .nodes + [step ])
86+ new_builder ._dependencies = self ._dependencies .copy ()
87+ return new_builder
5788
5889 def build (self ) -> Workflow :
5990 if not self .nodes :
6091 raise ValueError ("Workflow has no steps" )
6192 wf = Workflow (self .name , self .nodes )
93+ # Transfer any tracked dependencies
94+ wf .dependencies = self ._dependencies
6295 _REGISTRY .register_workflow (wf )
6396 return wf
6497
@@ -109,3 +142,12 @@ def get_registry() -> Registry:
109142
110143def get_workflows () -> list [Workflow ]:
111144 return _REGISTRY .get_workflows ()
145+
146+
147+ def get_workflow_dependencies () -> dict [str , set [str ]]:
148+ """Get all workflow dependencies as a mapping."""
149+ deps : dict [str , set [str ]] = {}
150+ for wf in _REGISTRY .workflows .values ():
151+ if wf .dependencies :
152+ deps [wf .name ] = wf .dependencies
153+ return deps
0 commit comments