Skip to content

Commit f954639

Browse files
feat: add arrayBuilder static arg support (#871)
1 parent 6b00fc6 commit f954639

4 files changed

Lines changed: 328 additions & 16 deletions

File tree

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
[project]
22
name = "uipath-langchain"
3-
version = "0.11.5"
3+
version = "0.11.6"
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.10.69, <2.11.0",
8+
"uipath>=2.10.70, <2.11.0",
99
"uipath-core>=0.5.15, <0.6.0",
1010
"uipath-platform>=0.1.45, <0.2.0",
1111
"uipath-runtime>=0.10.0, <0.11.0",

src/uipath_langchain/agent/tools/static_args.py

Lines changed: 76 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import copy
44
import logging
5+
import re
56
from typing import Any, Iterator, Mapping, Sequence, TypeVar
67

78
from jsonpath_ng import parse # type: ignore[import-untyped]
@@ -12,6 +13,7 @@
1213
from uipath.agent.models.agent import (
1314
AgentToolArgumentArgumentProperties,
1415
AgentToolArgumentProperties,
16+
AgentToolArrayBuilderArgumentProperties,
1517
AgentToolStaticArgumentProperties,
1618
AgentToolTextBuilderArgumentProperties,
1719
)
@@ -37,9 +39,15 @@ class ToolStaticArgument(BaseModel):
3739
"""Tool static argument model."""
3840

3941
value: Any
42+
display_value: Any
4043
is_sensitive: bool
4144

4245

46+
_INDEX_AND_REST_REGEX = re.compile(r"^\[(\d+)\](.*)$")
47+
48+
_SENSITIVE_ITEM_PLACEHOLDER = "<hidden>"
49+
50+
4351
def _resolve_argument_properties(
4452
argument_properties: Mapping[str, AgentToolArgumentProperties],
4553
agent_input: dict[str, Any],
@@ -48,12 +56,15 @@ def _resolve_argument_properties(
4856

4957
def resolve_to_static(
5058
props: AgentToolArgumentProperties,
59+
json_path: str,
5160
) -> ToolStaticArgument | None:
52-
"""Resolves argument and textBuilder variants to static."""
61+
"""Resolves argument, textBuilder, and arrayBuilder variants to static."""
5362
match props:
5463
case AgentToolStaticArgumentProperties():
5564
return ToolStaticArgument(
56-
value=props.value, is_sensitive=props.is_sensitive
65+
value=props.value,
66+
display_value=props.value,
67+
is_sensitive=props.is_sensitive,
5768
)
5869
case AgentToolArgumentArgumentProperties():
5970
agent_argument = parse(props.argument_path).find(agent_input)
@@ -62,30 +73,86 @@ def resolve_to_static(
6273
else:
6374
argument_value = agent_argument[0].value
6475
return ToolStaticArgument(
65-
value=argument_value, is_sensitive=props.is_sensitive
76+
value=argument_value,
77+
display_value=argument_value,
78+
is_sensitive=props.is_sensitive,
6679
)
6780
case AgentToolTextBuilderArgumentProperties():
6881
text_value = build_string_from_tokens(props.tokens, agent_input)
6982
return ToolStaticArgument(
70-
value=text_value, is_sensitive=props.is_sensitive
83+
value=text_value,
84+
display_value=text_value,
85+
is_sensitive=props.is_sensitive,
7186
)
87+
case AgentToolArrayBuilderArgumentProperties():
88+
return resolve_arraybuilder(json_path, argument_properties)
7289
case _:
7390
raise ValueError(f"Unsupported argument property type: {type(props)}")
7491

92+
def resolve_arraybuilder(
93+
base_path: str,
94+
argument_properties: Mapping[str, AgentToolArgumentProperties],
95+
) -> ToolStaticArgument:
96+
"""Build an array value from arrayBuilder indexed children.
97+
98+
Only direct indexed children ``base_path[N]`` are considered; entries
99+
with other nested properties are out of scope and silently skipped."""
100+
101+
base_with_bracket = base_path + "["
102+
direct_children: dict[int, AgentToolArgumentProperties] = {}
103+
max_index = -1
104+
105+
for path, props in argument_properties.items():
106+
if not path.startswith(base_with_bracket):
107+
continue
108+
match = _INDEX_AND_REST_REGEX.match(path[len(base_path) :])
109+
if not match or match.group(2) != "":
110+
continue
111+
idx = int(match.group(1))
112+
direct_children[idx] = props
113+
if idx > max_index:
114+
max_index = idx
115+
116+
runtime_items: list[Any] = []
117+
display_items: list[Any] = []
118+
for i in range(max_index + 1):
119+
item_props = direct_children.get(i)
120+
if item_props is None:
121+
runtime_items.append(None)
122+
display_items.append(None)
123+
continue
124+
resolved = resolve_to_static(item_props, f"{base_path}[{i}]")
125+
if resolved is None:
126+
runtime_items.append(None)
127+
display_items.append(None)
128+
else:
129+
runtime_items.append(resolved.value)
130+
display_value = (
131+
_SENSITIVE_ITEM_PLACEHOLDER
132+
if resolved.is_sensitive
133+
else resolved.display_value
134+
)
135+
display_items.append(display_value)
136+
137+
return ToolStaticArgument(
138+
value=runtime_items, display_value=display_items, is_sensitive=False
139+
)
140+
75141
def deduplicate_argument_properties(
76142
properties: Mapping[str, AgentToolArgumentProperties],
77143
) -> Iterator[tuple[str, AgentToolArgumentProperties]]:
78144
"""Skips more specific argument properties. In effect, prioritizes parent paths over child paths."""
79145

80-
sorted_paths = sorted(properties.keys())
81-
for i, json_path in enumerate(sorted_paths):
82-
if i > 0 and json_path.startswith(sorted_paths[i - 1]):
146+
last_yielded: str | None = None
147+
for json_path in sorted(properties.keys()):
148+
if last_yielded is not None and json_path.startswith(last_yielded):
83149
continue
84150
yield json_path, properties[json_path]
151+
last_yielded = json_path
85152

86153
static_args: dict[str, ToolStaticArgument] = {}
87154
for json_path, props in deduplicate_argument_properties(argument_properties):
88-
static_arg = resolve_to_static(props)
155+
static_arg = resolve_to_static(props, json_path)
89156
if static_arg is not None:
90157
static_args[json_path] = static_arg
91158
return static_args
@@ -119,7 +186,7 @@ def _apply_static_arguments_to_schema(
119186
apply_static_value_to_schema(
120187
modified_json_schema,
121188
json_path,
122-
static_arg.value,
189+
static_arg.display_value,
123190
static_arg.is_sensitive,
124191
)
125192
except SchemaModificationError as e:

0 commit comments

Comments
 (0)