|
22 | 22 | import com.google.adk.events.ToolConfirmation; |
23 | 23 | import com.google.adk.memory.SearchMemoryResponse; |
24 | 24 | import com.google.adk.sessions.State; |
| 25 | +import com.google.adk.workflow.DynamicNodeFailedException; |
| 26 | +import com.google.adk.workflow.Node; |
25 | 27 | import com.google.adk.workflow.NodeExecutionState; |
| 28 | +import com.google.adk.workflow.NodeRunner; |
26 | 29 | import com.google.adk.workflow.Route; |
| 30 | +import com.google.adk.workflow.RunNodeConfig; |
27 | 31 | import com.google.common.base.Preconditions; |
28 | 32 | import com.google.common.collect.ImmutableList; |
29 | 33 | import com.google.genai.types.Part; |
@@ -285,7 +289,8 @@ public final void eventAuthor(String eventAuthor) { |
285 | 289 | } |
286 | 290 |
|
287 | 291 | /** |
288 | | - * Returns this workflow node's output, or empty if it has produced none. |
| 292 | + * Returns this workflow node's output, which is the output of its {@code useAsOutput} child once |
| 293 | + * that child emits one, or empty if it has none. |
289 | 294 | * |
290 | 295 | * @throws IllegalStateException if this is not the context of a workflow node. |
291 | 296 | */ |
@@ -315,4 +320,46 @@ public final Optional<ImmutableList<Route>> routes() { |
315 | 320 | public final void routes(List<? extends Route> routes) { |
316 | 321 | requireNodeState().selectRoutes(routes); |
317 | 322 | } |
| 323 | + |
| 324 | + /** |
| 325 | + * Runs {@code node} as a child of this workflow node without an input, as {@link #runNode(Node, |
| 326 | + * Object, RunNodeConfig)} does with the default {@link RunNodeConfig}. |
| 327 | + */ |
| 328 | + @Experimental |
| 329 | + public final Maybe<Object> runNode(Node node) { |
| 330 | + return runNode(node, /* nodeInput= */ null); |
| 331 | + } |
| 332 | + |
| 333 | + /** |
| 334 | + * Runs {@code node} as a child of this workflow node, as {@link #runNode(Node, Object, |
| 335 | + * RunNodeConfig)} does with the default {@link RunNodeConfig}. |
| 336 | + * |
| 337 | + * @throws IllegalArgumentException if {@code nodeInput} is a {@link RunNodeConfig}, which belongs |
| 338 | + * in the three-argument overload. |
| 339 | + */ |
| 340 | + @Experimental |
| 341 | + public final Maybe<Object> runNode(Node node, @Nullable Object nodeInput) { |
| 342 | + Preconditions.checkArgument( |
| 343 | + !(nodeInput instanceof RunNodeConfig), |
| 344 | + "Pass the RunNodeConfig as the third argument of runNode, not as the node input."); |
| 345 | + return runNode(node, nodeInput, RunNodeConfig.builder().build()); |
| 346 | + } |
| 347 | + |
| 348 | + /** |
| 349 | + * Returns a {@link Maybe} that, when subscribed, runs {@code node} as a child of this workflow |
| 350 | + * node and emits the child's output, or completes empty if it has none. Include it in this node's |
| 351 | + * run and catch only failures you handle, such as {@link DynamicNodeFailedException}: when the |
| 352 | + * child waits, it fails with an internal {@link RuntimeException} that must propagate to end this |
| 353 | + * node's run, so that it waits too. |
| 354 | + * |
| 355 | + * <p>It fails with {@link DynamicNodeFailedException} if the child fails; with {@link |
| 356 | + * IllegalStateException} if this is not a workflow node's context, if this node's {@link |
| 357 | + * Node#rerunOnResume} is false, or if {@code config} delegates an output that this node already |
| 358 | + * has or has delegated; and with {@link IllegalArgumentException} if the child's name cannot form |
| 359 | + * a node path. |
| 360 | + */ |
| 361 | + @Experimental |
| 362 | + public final Maybe<Object> runNode(Node node, @Nullable Object nodeInput, RunNodeConfig config) { |
| 363 | + return NodeRunner.runChild(this, node, nodeInput, config); |
| 364 | + } |
318 | 365 | } |
0 commit comments