Skip to content

Commit f4295f5

Browse files
chore: bump uipath to 2.10.72 and uipath-langchain to 0.11.10 (#882)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 175f21d commit f4295f5

4 files changed

Lines changed: 142 additions & 10 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.9"
3+
version = "0.11.10"
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.70, <2.11.0",
8+
"uipath>=2.10.72, <2.11.0",
99
"uipath-core>=0.5.15, <0.6.0",
1010
"uipath-platform>=0.1.59, <0.2.0",
1111
"uipath-runtime>=0.10.0, <0.11.0",

tests/agent/tools/test_process_tool.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,22 @@ def flow_resource():
4747
)
4848

4949

50+
@pytest.fixture
51+
def function_resource():
52+
"""Create a process tool resource config of type Function (coded function release)."""
53+
return AgentProcessToolResourceConfig(
54+
type=AgentToolType.FUNCTION,
55+
name="test_function",
56+
description="Test function description",
57+
input_schema={"type": "object", "properties": {}},
58+
output_schema={"type": "object", "properties": {}},
59+
properties=AgentProcessToolProperties(
60+
process_name="MyFunction",
61+
folder_path="/Shared/Functions",
62+
),
63+
)
64+
65+
5066
@pytest.fixture
5167
def process_resource_with_inputs():
5268
"""Create a process tool resource config with input arguments."""
@@ -550,3 +566,84 @@ async def test_flow_tool_uses_non_agent_bts_key(
550566
bts_context = tool.metadata["_bts_context"]
551567
assert bts_context.get("wait_for_job_key") == "flow-job-key"
552568
assert "wait_for_agent_job_key" not in bts_context
569+
570+
571+
class TestProcessToolFunctionType:
572+
"""Test that a Function-type resource flows through create_process_tool correctly."""
573+
574+
def test_function_tool_metadata_has_function_tool_type(self, function_resource):
575+
"""A Function resource produces a tool with metadata.tool_type == 'function'."""
576+
tool = create_process_tool(function_resource)
577+
assert tool.metadata is not None
578+
assert tool.metadata["tool_type"] == "function"
579+
580+
def test_function_tool_metadata_has_display_name(self, function_resource):
581+
"""Function tool metadata exposes the process_name as display_name."""
582+
tool = create_process_tool(function_resource)
583+
assert tool.metadata is not None
584+
assert tool.metadata["display_name"] == "MyFunction"
585+
586+
@pytest.mark.asyncio
587+
@patch.dict(os.environ, {"UIPATH_FOLDER_PATH": "/Shared/Functions"})
588+
@patch("uipath_langchain._utils.durable_interrupt.decorator.interrupt")
589+
@patch("uipath_langchain.agent.tools.process_tool.UiPath")
590+
async def test_function_tool_invokes_processes_invoke_async(
591+
self, mock_uipath_class, mock_interrupt, function_resource
592+
):
593+
"""Function tool invokes client.processes.invoke_async (same path as Process)."""
594+
mock_job = MagicMock(spec=Job)
595+
mock_job.key = "function-job-key"
596+
mock_job.folder_key = "function-folder-key"
597+
598+
mock_resumed_job = MagicMock(spec=Job)
599+
mock_resumed_job.state = "successful"
600+
601+
mock_client = MagicMock()
602+
mock_client.processes.invoke_async = AsyncMock(return_value=mock_job)
603+
mock_client.jobs.extract_output_async = AsyncMock(return_value=None)
604+
mock_uipath_class.return_value = mock_client
605+
606+
mock_interrupt.return_value = mock_resumed_job
607+
608+
tool = create_process_tool(function_resource)
609+
await tool.ainvoke({})
610+
611+
mock_client.processes.invoke_async.assert_called_once_with(
612+
name="MyFunction",
613+
input_arguments={},
614+
folder_path="/Shared/Functions",
615+
attachments=[],
616+
parent_span_id=None,
617+
parent_operation_id=None,
618+
run_as_me=None,
619+
)
620+
621+
@pytest.mark.asyncio
622+
@patch("uipath_langchain._utils.durable_interrupt.decorator.interrupt")
623+
@patch("uipath_langchain.agent.tools.process_tool.UiPath")
624+
async def test_function_tool_uses_non_agent_bts_key(
625+
self, mock_uipath_class, mock_interrupt, function_resource
626+
):
627+
"""Function tool stores the BTS tracking key under 'wait_for_job_key' (not agent variant)."""
628+
mock_job = MagicMock(spec=Job)
629+
mock_job.key = "function-job-key"
630+
mock_job.folder_key = "function-folder-key"
631+
632+
mock_resumed_job = MagicMock(spec=Job)
633+
mock_resumed_job.state = "successful"
634+
635+
mock_client = MagicMock()
636+
mock_client.processes.invoke_async = AsyncMock(return_value=mock_job)
637+
mock_client.jobs.extract_output_async = AsyncMock(return_value=None)
638+
mock_uipath_class.return_value = mock_client
639+
640+
mock_interrupt.return_value = mock_resumed_job
641+
642+
tool = create_process_tool(function_resource)
643+
assert tool.metadata is not None
644+
645+
await tool.ainvoke({})
646+
647+
bts_context = tool.metadata["_bts_context"]
648+
assert bts_context.get("wait_for_job_key") == "function-job-key"
649+
assert "wait_for_agent_job_key" not in bts_context

tests/agent/tools/test_tool_factory.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,22 @@ def flow_resource() -> AgentProcessToolResourceConfig:
8484
)
8585

8686

87+
@pytest.fixture
88+
def function_resource() -> AgentProcessToolResourceConfig:
89+
"""Create a process tool resource config of type Function."""
90+
return AgentProcessToolResourceConfig(
91+
type=AgentToolType.FUNCTION,
92+
name="test_function",
93+
description="Test function description",
94+
input_schema=EMPTY_SCHEMA,
95+
output_schema=EMPTY_SCHEMA,
96+
properties=AgentProcessToolProperties(
97+
process_name="MyFunction",
98+
folder_path="/Shared/Functions",
99+
),
100+
)
101+
102+
87103
@pytest.fixture
88104
def context_resource() -> AgentContextResourceConfig:
89105
"""Create a context tool resource config."""
@@ -287,6 +303,7 @@ async def test_only_enabled_tools_returned(
287303
[
288304
"process_resource",
289305
"flow_resource",
306+
"function_resource",
290307
"context_resource",
291308
"escalation_resource",
292309
"integration_resource",
@@ -321,3 +338,21 @@ async def test_flow_resource_routes_through_process_tool_path(
321338

322339
mock_create_process_tool.assert_called_once_with(flow_resource, run_as_me=False)
323340
assert tool is not None
341+
342+
async def test_function_resource_routes_through_process_tool_path(
343+
self, function_resource, mock_uipath_sdk
344+
):
345+
"""A Function-type resource is dispatched via the process_tool factory path."""
346+
mock_llm = AsyncMock(spec=BaseChatModel)
347+
with patch(
348+
"uipath_langchain.agent.tools.tool_factory.create_process_tool"
349+
) as mock_create_process_tool:
350+
mock_create_process_tool.return_value = MagicMock(
351+
spec=BaseUiPathStructuredTool
352+
)
353+
tool = await _build_tool_for_resource(function_resource, mock_llm)
354+
355+
mock_create_process_tool.assert_called_once_with(
356+
function_resource, run_as_me=False
357+
)
358+
assert tool is not None

uv.lock

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)