Skip to content

Commit a23795c

Browse files
committed
fix: improve uipath init cli output layout
1 parent 41e8748 commit a23795c

File tree

1 file changed

+78
-30
lines changed

1 file changed

+78
-30
lines changed

src/uipath/_cli/cli_init.py

Lines changed: 78 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141

4242
CONFIG_PATH = "uipath.json"
4343

44+
GRAPH_INDENT = " "
45+
4446

4547
def 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

Comments
 (0)