4141
4242CONFIG_PATH = "uipath.json"
4343
44+ GRAPH_INDENT = " "
45+
4446
4547def create_telemetry_config_file (target_directory : str ) -> None :
4648 """Create telemetry file if telemetry is enabled.
@@ -248,6 +250,74 @@ def _add_graph_to_chart(chart: Chart | Subgraph, graph: UiPathRuntimeGraph) -> N
248250 chart .add_link (link )
249251
250252
253+ def _enrich_graph_node_descriptions (graph_data : dict [str , Any ]) -> None :
254+ """Enrich graph node descriptions with metadata (model names, tool names).
255+
256+ Args:
257+ graph_data: The graph data dict to mutate in-place.
258+ """
259+ node : dict [str , Any ]
260+ for node in graph_data .get ("nodes" , []):
261+ meta = node .get ("metadata" ) or {}
262+ if not node .get ("description" ):
263+ if node .get ("type" ) == "model" and "model_name" in meta :
264+ node ["description" ] = meta ["model_name" ]
265+ elif node .get ("type" ) == "tool" and "tool_names" in meta :
266+ names = meta ["tool_names" ]
267+ if isinstance (names , list ):
268+ node ["description" ] = ", " .join (names )
269+ elif isinstance (names , str ):
270+ node ["description" ] = names
271+
272+
273+ def _render_graph (rendered : str , indent : str = GRAPH_INDENT ) -> str :
274+ """Indent every line of the rendered graph for visual containment.
275+
276+ Args:
277+ rendered: The raw rendered graph string.
278+ indent: The indent prefix for each line.
279+
280+ Returns:
281+ The indented graph string.
282+ """
283+ return "\n " .join (indent + line for line in rendered .splitlines ())
284+
285+
286+ def _display_entrypoint_graphs (entry_point_schemas : list [UiPathRuntimeSchema ]) -> None :
287+ """Render and display ASCII graphs for all entrypoints that have graph data.
288+
289+ Args:
290+ entry_point_schemas: List of runtime schemas with optional graph data.
291+ """
292+ graphs_to_render = [ep for ep in entry_point_schemas if ep .graph and ep .graph .nodes ]
293+
294+ if not graphs_to_render :
295+ return
296+
297+ click .echo ()
298+
299+ for entrypoint_schema in graphs_to_render :
300+ if entrypoint_schema .graph is None :
301+ continue
302+ title = entrypoint_schema .file_path or "Agent"
303+ click .echo (click .style (f" Entrypoint: { title } " , fg = "cyan" , bold = True ))
304+ click .echo (click .style (" " + "─" * 50 , fg = "bright_black" ))
305+ click .echo ()
306+
307+ try :
308+ graph_data = entrypoint_schema .graph .model_dump ()
309+ _enrich_graph_node_descriptions (graph_data )
310+
311+ ascii_graph = AsciiGraph (** graph_data )
312+ options = RenderOptions (theme = TOKYO_NIGHT )
313+ rendered = render (ascii_graph , options )
314+ click .echo (_render_graph (rendered ))
315+ except Exception :
316+ pass
317+
318+ click .echo ()
319+
320+
251321@click .command ()
252322@click .option (
253323 "--no-agents-md-override" ,
@@ -263,7 +333,7 @@ def init(no_agents_md_override: bool) -> None:
263333 generate_env_file (current_directory )
264334 create_telemetry_config_file (current_directory )
265335
266- async def initialize () -> None :
336+ async def initialize () -> list [ UiPathRuntimeSchema ] :
267337 try :
268338 # Create uipath.json if it doesn't exist
269339 config_path = UiPathConfig .config_file_path
@@ -322,45 +392,20 @@ async def initialize() -> None:
322392 f"Created '{ entry_points_path } ' file with { len (entry_point_schemas )} entrypoint(s)."
323393 )
324394
325- try :
326- for entrypoint_schema in entry_point_schemas :
327- if (
328- not entrypoint_schema .graph
329- or not entrypoint_schema .graph .nodes
330- ):
331- continue
332- graph_data = entrypoint_schema .graph .model_dump ()
333- node : dict [str , Any ]
334- for node in graph_data .get ("nodes" , []):
335- meta = node .get ("metadata" ) or {}
336- if not node .get ("description" ):
337- if node .get ("type" ) == "model" and "model_name" in meta :
338- node ["description" ] = meta ["model_name" ]
339- elif (
340- node .get ("type" ) == "tool" and "tool_names" in meta
341- ):
342- names = meta ["tool_names" ]
343- if isinstance (names , list ):
344- node ["description" ] = ", " .join (names )
345- elif isinstance (names , str ):
346- node ["description" ] = names
347- ascii_graph = AsciiGraph (** graph_data )
348- options = RenderOptions (theme = TOKYO_NIGHT )
349- click .echo (render (ascii_graph , options ))
350- except Exception :
351- pass
352-
353395 # Write mermaid diagrams for each entrypoint
354396 mermaid_paths = write_mermaid_files (entry_point_schemas )
355397 if mermaid_paths and len (mermaid_paths ) > 0 :
356398 console .success (
357399 f"Created { len (mermaid_paths )} mermaid diagram file(s)."
358400 )
359401
402+ return entry_point_schemas
403+
360404 except Exception as e :
361405 console .error (f"Error during initialization:\n { e } " )
406+ return []
362407
363- asyncio .run (initialize ())
408+ entry_point_schemas = asyncio .run (initialize ())
364409
365410 result = Middlewares .next (
366411 "init" ,
@@ -378,6 +423,9 @@ async def initialize() -> None:
378423 console .info (result .info_message )
379424
380425 if not result .should_continue :
426+ _display_entrypoint_graphs (entry_point_schemas )
381427 return
382428
383429 generate_agent_md_files (current_directory , no_agents_md_override )
430+
431+ _display_entrypoint_graphs (entry_point_schemas )
0 commit comments