@@ -168,6 +168,18 @@ private HashSet<Edge> EnsureEdgesFor(string sourceId)
168168 return edges ;
169169 }
170170
171+ /// <summary>
172+ /// Adds a directed edge from the specified source executor to the target executor, optionally guarded by a
173+ /// condition.
174+ /// </summary>
175+ /// <param name="source">The executor that acts as the source node of the edge. Cannot be null.</param>
176+ /// <param name="target">The executor that acts as the target node of the edge. Cannot be null.</param>
177+ /// <returns>The current instance of <see cref="WorkflowBuilder"/>.</returns>
178+ /// <exception cref="InvalidOperationException">Thrown if an unconditional edge between the specified source and target
179+ /// executors already exists.</exception>
180+ public WorkflowBuilder AddEdge ( ExecutorBinding source , ExecutorBinding target )
181+ => this . AddEdge < object > ( source , target , null , false ) ;
182+
171183 /// <summary>
172184 /// Adds a directed edge from the specified source executor to the target executor, optionally guarded by a
173185 /// condition.
@@ -182,6 +194,20 @@ private HashSet<Edge> EnsureEdgesFor(string sourceId)
182194 public WorkflowBuilder AddEdge ( ExecutorBinding source , ExecutorBinding target , bool idempotent = false )
183195 => this . AddEdge < object > ( source , target , null , idempotent ) ;
184196
197+ /// <summary>
198+ /// Adds a directed edge from the specified source executor to the target executor.
199+ /// </summary>
200+ /// <param name="source">The executor that acts as the source node of the edge. Cannot be null.</param>
201+ /// <param name="target">The executor that acts as the target node of the edge. Cannot be null.</param>
202+ /// <param name="label">An optional label for the edge. Will be used in visualizations.</param>
203+ /// <param name="idempotent">If set to <see langword="true"/>, adding the same edge multiple times will be a NoOp,
204+ /// rather than an error.</param>
205+ /// <returns>The current instance of <see cref="WorkflowBuilder"/>.</returns>
206+ /// <exception cref="InvalidOperationException">Thrown if an unconditional edge between the specified source and target
207+ /// executors already exists.</exception>
208+ public WorkflowBuilder AddEdge ( ExecutorBinding source , ExecutorBinding target , string ? label = null , bool idempotent = false )
209+ => this . AddEdge < object > ( source , target , null , label , idempotent ) ;
210+
185211 internal static Func < object ? , bool > ? CreateConditionFunc < T > ( Func < T ? , bool > ? condition )
186212 {
187213 if ( condition is null )
@@ -222,6 +248,20 @@ public WorkflowBuilder AddEdge(ExecutorBinding source, ExecutorBinding target, b
222248
223249 private EdgeId TakeEdgeId ( ) => new ( Interlocked . Increment ( ref this . _edgeCount ) ) ;
224250
251+ /// <summary>
252+ /// Adds a directed edge from the specified source executor to the target executor, optionally guarded by a
253+ /// condition.
254+ /// </summary>
255+ /// <param name="source">The executor that acts as the source node of the edge. Cannot be null.</param>
256+ /// <param name="target">The executor that acts as the target node of the edge. Cannot be null.</param>
257+ /// <param name="condition">An optional predicate that determines whether the edge should be followed based on the input.
258+ /// If null, the edge is always activated when the source sends a message.</param>
259+ /// <returns>The current instance of <see cref="WorkflowBuilder"/>.</returns>
260+ /// <exception cref="InvalidOperationException">Thrown if an unconditional edge between the specified source and target
261+ /// executors already exists.</exception>
262+ public WorkflowBuilder AddEdge < T > ( ExecutorBinding source , ExecutorBinding target , Func < T ? , bool > ? condition = null )
263+ => this . AddEdge ( source , target , condition , label : null , false ) ;
264+
225265 /// <summary>
226266 /// Adds a directed edge from the specified source executor to the target executor, optionally guarded by a
227267 /// condition.
@@ -236,6 +276,23 @@ public WorkflowBuilder AddEdge(ExecutorBinding source, ExecutorBinding target, b
236276 /// <exception cref="InvalidOperationException">Thrown if an unconditional edge between the specified source and target
237277 /// executors already exists.</exception>
238278 public WorkflowBuilder AddEdge < T > ( ExecutorBinding source , ExecutorBinding target , Func < T ? , bool > ? condition = null , bool idempotent = false )
279+ => this . AddEdge ( source , target , condition , label : null , idempotent ) ;
280+
281+ /// <summary>
282+ /// Adds a directed edge from the specified source executor to the target executor, optionally guarded by a
283+ /// condition.
284+ /// </summary>
285+ /// <param name="source">The executor that acts as the source node of the edge. Cannot be null.</param>
286+ /// <param name="target">The executor that acts as the target node of the edge. Cannot be null.</param>
287+ /// <param name="condition">An optional predicate that determines whether the edge should be followed based on the input.
288+ /// <param name="label">An optional label for the edge. Will be used in visualizations.</param>
289+ /// <param name="idempotent">If set to <see langword="true"/>, adding the same edge multiple times will be a NoOp,
290+ /// rather than an error.</param>
291+ /// If null, the edge is always activated when the source sends a message.</param>
292+ /// <returns>The current instance of <see cref="WorkflowBuilder"/>.</returns>
293+ /// <exception cref="InvalidOperationException">Thrown if an unconditional edge between the specified source and target
294+ /// executors already exists.</exception>
295+ public WorkflowBuilder AddEdge < T > ( ExecutorBinding source , ExecutorBinding target , Func < T ? , bool > ? condition = null , string ? label = null , bool idempotent = false )
239296 {
240297 // Add an edge from source to target with an optional condition.
241298 // This is a low-level builder method that does not enforce any specific executor type.
@@ -256,7 +313,7 @@ public WorkflowBuilder AddEdge<T>(ExecutorBinding source, ExecutorBinding target
256313 "You cannot add another edge without a condition for the same source and target." ) ;
257314 }
258315
259- DirectEdgeData directEdge = new ( this . Track ( source ) . Id , this . Track ( target ) . Id , this . TakeEdgeId ( ) , CreateConditionFunc ( condition ) ) ;
316+ DirectEdgeData directEdge = new ( this . Track ( source ) . Id , this . Track ( target ) . Id , this . TakeEdgeId ( ) , CreateConditionFunc ( condition ) , label ) ;
260317
261318 this . EnsureEdgesFor ( source . Id ) . Add ( new ( directEdge ) ) ;
262319
@@ -275,6 +332,19 @@ public WorkflowBuilder AddEdge<T>(ExecutorBinding source, ExecutorBinding target
275332 public WorkflowBuilder AddFanOutEdge ( ExecutorBinding source , IEnumerable < ExecutorBinding > targets )
276333 => this . AddFanOutEdge < object > ( source , targets , null ) ;
277334
335+ /// <summary>
336+ /// Adds a fan-out edge from the specified source executor to one or more target executors, optionally using a
337+ /// custom partitioning function.
338+ /// </summary>
339+ /// <remarks>If a partitioner function is provided, it will be used to distribute input across the target
340+ /// executors. The order of targets determines their mapping in the partitioning process.</remarks>
341+ /// <param name="source">The source executor from which the fan-out edge originates. Cannot be null.</param>
342+ /// <param name="targets">One or more target executors that will receive the fan-out edge. Cannot be null or empty.</param>
343+ /// <param name="label">A label for the edge. Will be used in visualization.</param>
344+ /// <returns>The current instance of <see cref="WorkflowBuilder"/>.</returns>
345+ public WorkflowBuilder AddFanOutEdge ( ExecutorBinding source , IEnumerable < ExecutorBinding > targets , string label )
346+ => this . AddFanOutEdge < object > ( source , targets , null , label ) ;
347+
278348 internal static Func < object ? , int , IEnumerable < int > > ? CreateTargetAssignerFunc < T > ( Func < T ? , int , IEnumerable < int > > ? targetAssigner )
279349 {
280350 if ( targetAssigner is null )
@@ -305,6 +375,21 @@ public WorkflowBuilder AddFanOutEdge(ExecutorBinding source, IEnumerable<Executo
305375 /// <param name="targetSelector">An optional function that determines how input is assigned among the target executors.
306376 /// If null, messages will route to all targets.</param>
307377 public WorkflowBuilder AddFanOutEdge < T > ( ExecutorBinding source , IEnumerable < ExecutorBinding > targets , Func < T ? , int , IEnumerable < int > > ? targetSelector = null )
378+ => this . AddFanOutEdge ( source , targets , targetSelector , label : null ) ;
379+
380+ /// <summary>
381+ /// Adds a fan-out edge from the specified source executor to one or more target executors, optionally using a
382+ /// custom partitioning function.
383+ /// </summary>
384+ /// <remarks>If a partitioner function is provided, it will be used to distribute input across the target
385+ /// executors. The order of targets determines their mapping in the partitioning process.</remarks>
386+ /// <param name="source">The source executor from which the fan-out edge originates. Cannot be null.</param>
387+ /// <param name="targets">One or more target executors that will receive the fan-out edge. Cannot be null or empty.</param>
388+ /// <returns>The current instance of <see cref="WorkflowBuilder"/>.</returns>
389+ /// <param name="targetSelector">An optional function that determines how input is assigned among the target executors.
390+ /// If null, messages will route to all targets.</param>
391+ /// <param name="label">An optional label for the edge. Will be used in visualizations.</param>
392+ public WorkflowBuilder AddFanOutEdge < T > ( ExecutorBinding source , IEnumerable < ExecutorBinding > targets , Func < T ? , int , IEnumerable < int > > ? targetSelector = null , string ? label = null )
308393 {
309394 Throw . IfNull ( source ) ;
310395 Throw . IfNull ( targets ) ;
@@ -321,7 +406,8 @@ public WorkflowBuilder AddFanOutEdge<T>(ExecutorBinding source, IEnumerable<Exec
321406 this . Track ( source ) . Id ,
322407 sinkIds ,
323408 this . TakeEdgeId ( ) ,
324- CreateTargetAssignerFunc ( targetSelector ) ) ;
409+ CreateTargetAssignerFunc ( targetSelector ) ,
410+ label ) ;
325411
326412 this . EnsureEdgesFor ( source . Id ) . Add ( new ( fanOutEdge ) ) ;
327413
@@ -339,6 +425,20 @@ public WorkflowBuilder AddFanOutEdge<T>(ExecutorBinding source, IEnumerable<Exec
339425 /// <param name="target">The target executor that receives input from the specified source executors. Cannot be null.</param>
340426 /// <returns>The current instance of <see cref="WorkflowBuilder"/>.</returns>
341427 public WorkflowBuilder AddFanInEdge ( IEnumerable < ExecutorBinding > sources , ExecutorBinding target )
428+ => this . AddFanInEdge ( sources , target , label : null ) ;
429+
430+ /// <summary>
431+ /// Adds a fan-in edge to the workflow, connecting multiple source executors to a single target executor with an
432+ /// optional trigger condition.
433+ /// </summary>
434+ /// <remarks>This method establishes a fan-in relationship, allowing the target executor to be activated
435+ /// based on the completion or state of multiple sources. The trigger parameter can be used to customize activation
436+ /// behavior.</remarks>
437+ /// <param name="sources">One or more source executors that provide input to the target. Cannot be null or empty.</param>
438+ /// <param name="target">The target executor that receives input from the specified source executors. Cannot be null.</param>
439+ /// <param name="label">An optional label for the edge. Will be used in visualizations.</param>
440+ /// <returns>The current instance of <see cref="WorkflowBuilder"/>.</returns>
441+ public WorkflowBuilder AddFanInEdge ( IEnumerable < ExecutorBinding > sources , ExecutorBinding target , string ? label = null )
342442 {
343443 Throw . IfNull ( target ) ;
344444 Throw . IfNull ( sources ) ;
@@ -354,7 +454,8 @@ public WorkflowBuilder AddFanInEdge(IEnumerable<ExecutorBinding> sources, Execut
354454 FanInEdgeData edgeData = new (
355455 sourceIds ,
356456 this . Track ( target ) . Id ,
357- this . TakeEdgeId ( ) ) ;
457+ this . TakeEdgeId ( ) ,
458+ label ) ;
358459
359460 foreach ( string sourceId in edgeData . SourceIds )
360461 {
0 commit comments