Skip to content

Commit d8cd900

Browse files
authored
feat: infer attachments (#400)
1 parent c0db575 commit d8cd900

4 files changed

Lines changed: 336 additions & 206 deletions

File tree

pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
[project]
22
name = "uipath-langchain"
3-
version = "0.3.3"
3+
version = "0.3.4"
44
description = "Python SDK that enables developers to build and deploy LangGraph agents to the UiPath Cloud Platform"
55
readme = { file = "README.md", content-type = "text/markdown" }
66
requires-python = ">=3.11"
77
dependencies = [
8-
"uipath>=2.4.0, <2.5.0",
9-
"uipath-runtime>=0.4.0, <0.5.0",
8+
"uipath>=2.4.14, <2.5.0",
9+
"uipath-runtime>=0.4.1, <0.5.0",
1010
"langgraph>=1.0.0, <2.0.0",
1111
"langchain-core>=1.2.5, <2.0.0",
1212
"aiosqlite==0.21.0",

src/uipath_langchain/runtime/schema.py

Lines changed: 25 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
UiPathRuntimeEdge,
1515
UiPathRuntimeGraph,
1616
UiPathRuntimeNode,
17+
transform_attachments,
18+
transform_nullable_types,
19+
transform_references,
1720
)
1821

1922
try:
@@ -322,120 +325,38 @@ def get_entrypoints_schema(
322325
}
323326

324327
if hasattr(graph, "input_schema"):
325-
if hasattr(graph.input_schema, "model_json_schema"):
326-
input_schema = graph.input_schema.model_json_schema()
327-
unpacked_ref_def_properties, input_circular_dependency = _resolve_refs(
328-
input_schema
329-
)
328+
input_schema = graph.get_input_jsonschema()
329+
unpacked_ref_def_properties, input_circular_dependency = transform_references(
330+
input_schema
331+
)
330332

331-
# Process the schema to handle nullable types
332-
processed_properties = _process_nullable_types(
333-
unpacked_ref_def_properties.get("properties", {})
334-
)
333+
# Process the schema to handle nullable types
334+
processed_properties = transform_nullable_types(
335+
unpacked_ref_def_properties.get("properties", {})
336+
)
335337

336-
schema["input"]["properties"] = processed_properties
337-
schema["input"]["required"] = unpacked_ref_def_properties.get(
338-
"required", []
339-
)
338+
schema["input"]["properties"] = processed_properties
339+
schema["input"]["required"] = unpacked_ref_def_properties.get("required", [])
340+
schema["input"] = transform_attachments(schema["input"])
340341

341342
if hasattr(graph, "output_schema"):
342-
if hasattr(graph.output_schema, "model_json_schema"):
343-
output_schema = graph.output_schema.model_json_schema()
344-
unpacked_ref_def_properties, output_circular_dependency = _resolve_refs(
345-
output_schema
346-
)
343+
output_schema = graph.get_output_jsonschema()
344+
unpacked_ref_def_properties, output_circular_dependency = transform_references(
345+
output_schema
346+
)
347347

348-
# Process the schema to handle nullable types
349-
processed_properties = _process_nullable_types(
350-
unpacked_ref_def_properties.get("properties", {})
351-
)
348+
# Process the schema to handle nullable types
349+
processed_properties = transform_nullable_types(
350+
unpacked_ref_def_properties.get("properties", {})
351+
)
352352

353-
schema["output"]["properties"] = processed_properties
354-
schema["output"]["required"] = unpacked_ref_def_properties.get(
355-
"required", []
356-
)
353+
schema["output"]["properties"] = processed_properties
354+
schema["output"]["required"] = unpacked_ref_def_properties.get("required", [])
355+
schema["output"] = transform_attachments(schema["output"])
357356

358357
return SchemaDetails(schema, input_circular_dependency, output_circular_dependency)
359358

360359

361-
def _resolve_refs(schema, root=None, visited=None):
362-
"""Recursively resolves $ref references in a JSON schema, handling circular references.
363-
364-
Returns:
365-
tuple: (resolved_schema, has_circular_dependency)
366-
"""
367-
if root is None:
368-
root = schema
369-
370-
if visited is None:
371-
visited = set()
372-
373-
has_circular = False
374-
375-
if isinstance(schema, dict):
376-
if "$ref" in schema:
377-
ref_path = schema["$ref"]
378-
379-
if ref_path in visited:
380-
# Circular dependency detected
381-
return {
382-
"type": "object",
383-
"description": f"Circular reference to {ref_path}",
384-
}, True
385-
386-
visited.add(ref_path)
387-
388-
# Resolve the reference
389-
ref_parts = ref_path.lstrip("#/").split("/")
390-
ref_schema = root
391-
for part in ref_parts:
392-
ref_schema = ref_schema.get(part, {})
393-
394-
result, circular = _resolve_refs(ref_schema, root, visited)
395-
has_circular = has_circular or circular
396-
397-
# Remove from visited after resolution (allows the same ref in different branches)
398-
visited.discard(ref_path)
399-
400-
return result, has_circular
401-
402-
resolved_dict = {}
403-
for k, v in schema.items():
404-
resolved_value, circular = _resolve_refs(v, root, visited)
405-
resolved_dict[k] = resolved_value
406-
has_circular = has_circular or circular
407-
return resolved_dict, has_circular
408-
409-
elif isinstance(schema, list):
410-
resolved_list = []
411-
for item in schema:
412-
resolved_item, circular = _resolve_refs(item, root, visited)
413-
resolved_list.append(resolved_item)
414-
has_circular = has_circular or circular
415-
return resolved_list, has_circular
416-
417-
return schema, False
418-
419-
420-
def _process_nullable_types(
421-
schema: dict[str, Any] | list[Any] | Any,
422-
) -> dict[str, Any] | list[Any]:
423-
"""Process the schema to handle nullable types by removing anyOf with null and keeping the base type."""
424-
if isinstance(schema, dict):
425-
if "anyOf" in schema and len(schema["anyOf"]) == 2:
426-
types = [t.get("type") for t in schema["anyOf"]]
427-
if "null" in types:
428-
non_null_type = next(
429-
t for t in schema["anyOf"] if t.get("type") != "null"
430-
)
431-
return non_null_type
432-
433-
return {k: _process_nullable_types(v) for k, v in schema.items()}
434-
elif isinstance(schema, list):
435-
return [_process_nullable_types(item) for item in schema]
436-
return schema
437-
438-
439360
__all__ = [
440361
"get_graph_schema",
441362
"get_entrypoints_schema",

0 commit comments

Comments
 (0)