66import uuid
77from collections .abc import Generator
88from enum import Enum
9- from typing import Any , Callable , Dict , overload
9+ from typing import Any , Callable , overload
1010
1111import click
1212from langgraph .graph .state import CompiledStateGraph
1313from uipath ._cli ._utils ._console import ConsoleLogger
1414from uipath ._cli ._utils ._parse_ast import generate_bindings_json # type: ignore
1515from uipath ._cli .middlewares import MiddlewareResult
1616
17+ from uipath_langchain ._cli ._utils ._schema import generate_schema_from_graph
18+
1719from ._utils ._graph import LangGraphConfig
1820
1921console = ConsoleLogger ()
@@ -27,88 +29,6 @@ class FileOperationStatus(str, Enum):
2729 SKIPPED = "skipped"
2830
2931
30- def resolve_refs (schema , root = None ):
31- """Recursively resolves $ref references in a JSON schema."""
32- if root is None :
33- root = schema # Store the root schema to resolve $refs
34-
35- if isinstance (schema , dict ):
36- if "$ref" in schema :
37- ref_path = schema ["$ref" ].lstrip ("#/" ).split ("/" )
38- ref_schema = root
39- for part in ref_path :
40- ref_schema = ref_schema .get (part , {})
41- return resolve_refs (ref_schema , root )
42-
43- return {k : resolve_refs (v , root ) for k , v in schema .items ()}
44-
45- elif isinstance (schema , list ):
46- return [resolve_refs (item , root ) for item in schema ]
47-
48- return schema
49-
50-
51- def process_nullable_types (
52- schema : Dict [str , Any ] | list [Any ] | Any ,
53- ) -> Dict [str , Any ] | list [Any ]:
54- """Process the schema to handle nullable types by removing anyOf with null and keeping the base type."""
55- if isinstance (schema , dict ):
56- if "anyOf" in schema and len (schema ["anyOf" ]) == 2 :
57- types = [t .get ("type" ) for t in schema ["anyOf" ]]
58- if "null" in types :
59- non_null_type = next (
60- t for t in schema ["anyOf" ] if t .get ("type" ) != "null"
61- )
62- return non_null_type
63-
64- return {k : process_nullable_types (v ) for k , v in schema .items ()}
65- elif isinstance (schema , list ):
66- return [process_nullable_types (item ) for item in schema ]
67- return schema
68-
69-
70- def generate_schema_from_graph (
71- graph : CompiledStateGraph [Any , Any , Any ],
72- ) -> Dict [str , Any ]:
73- """Extract input/output schema from a LangGraph graph"""
74- schema = {
75- "input" : {"type" : "object" , "properties" : {}, "required" : []},
76- "output" : {"type" : "object" , "properties" : {}, "required" : []},
77- }
78-
79- if hasattr (graph , "input_schema" ):
80- if hasattr (graph .input_schema , "model_json_schema" ):
81- input_schema = graph .input_schema .model_json_schema ()
82- unpacked_ref_def_properties = resolve_refs (input_schema )
83-
84- # Process the schema to handle nullable types
85- processed_properties = process_nullable_types (
86- unpacked_ref_def_properties .get ("properties" , {})
87- )
88-
89- schema ["input" ]["properties" ] = processed_properties
90- schema ["input" ]["required" ] = unpacked_ref_def_properties .get (
91- "required" , []
92- )
93-
94- if hasattr (graph , "output_schema" ):
95- if hasattr (graph .output_schema , "model_json_schema" ):
96- output_schema = graph .output_schema .model_json_schema ()
97- unpacked_ref_def_properties = resolve_refs (output_schema )
98-
99- # Process the schema to handle nullable types
100- processed_properties = process_nullable_types (
101- unpacked_ref_def_properties .get ("properties" , {})
102- )
103-
104- schema ["output" ]["properties" ] = processed_properties
105- schema ["output" ]["required" ] = unpacked_ref_def_properties .get (
106- "required" , []
107- )
108-
109- return schema
110-
111-
11232def generate_agent_md_file (
11333 target_directory : str ,
11434 file_name : str ,
0 commit comments