From 3e7da6a6a3e00ee953422a976e4fc79224cbdba2 Mon Sep 17 00:00:00 2001 From: Niket Jain Date: Fri, 6 Nov 2026 13:31:05 +0530 Subject: [PATCH] fix(entities): route resolved entity sets by their resolved names [DS-9661] resolve_entity_set fetches overwritten entities by their new name, so the SQL the agent writes uses that name. The routing context still keyed each entry by the original name with overrideEntityName set, which the query engine can only match through a fallback and resolves incorrectly when an overwritten name equals another entity's original name (A->B, B->C, swaps). Key each routing entry by the resolved name instead, without an override. Direct SDK usage and folders-map routing are unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) --- packages/uipath-platform/pyproject.toml | 2 +- .../platform/entities/_entity_resolution.py | 7 ++- .../tests/services/test_entities_service.py | 53 +++++++++++++++++-- packages/uipath-platform/uv.lock | 2 +- packages/uipath/uv.lock | 2 +- 5 files changed, 57 insertions(+), 9 deletions(-) diff --git a/packages/uipath-platform/pyproject.toml b/packages/uipath-platform/pyproject.toml index 56920f06c..e21ae1310 100644 --- a/packages/uipath-platform/pyproject.toml +++ b/packages/uipath-platform/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "uipath-platform" -version = "0.3.0" +version = "0.3.1" description = "HTTP client library for programmatic access to UiPath Platform" readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.11" diff --git a/packages/uipath-platform/src/uipath/platform/entities/_entity_resolution.py b/packages/uipath-platform/src/uipath/platform/entities/_entity_resolution.py index 2477b26b9..6d00a3b6c 100644 --- a/packages/uipath-platform/src/uipath/platform/entities/_entity_resolution.py +++ b/packages/uipath-platform/src/uipath/platform/entities/_entity_resolution.py @@ -385,8 +385,11 @@ def finalize_resolution_plan( folders_map=resolved_folders_map, effective_entity_names=draft.effective_entity_names, routing_context=build_resolution_routing_context( - resolved_folders_map, - draft.effective_entity_names, + { + draft.effective_entity_names.get(name, name): folder_key + for name, folder_key in resolved_folders_map.items() + }, + {}, ), ) diff --git a/packages/uipath-platform/tests/services/test_entities_service.py b/packages/uipath-platform/tests/services/test_entities_service.py index cec8cba54..268409edf 100644 --- a/packages/uipath-platform/tests/services/test_entities_service.py +++ b/packages/uipath-platform/tests/services/test_entities_service.py @@ -856,9 +856,8 @@ def test_resolve_entity_set_uses_effective_sql_name_in_routing_context( ) == { "entityRoutings": [ { - "entityName": "Customers", + "entityName": "Overwritten Customers", "folderId": "known-folder-key", - "overrideEntityName": "Overwritten Customers", } ] } @@ -867,6 +866,53 @@ def test_resolve_entity_set_uses_effective_sql_name_in_routing_context( "known-folder-key", ) + def test_resolve_entity_set_chained_overwrites_route_by_resolved_names( + self, + config: UiPathApiConfig, + execution_context: UiPathExecutionContext, + ) -> None: + service = EntitiesService( + config=config, + execution_context=execution_context, + ) + service.retrieve_by_name = MagicMock( # type: ignore[method-assign] + return_value=MagicMock(spec=Entity) + ) + + token = _resource_overwrites.set( + { + "entity.entity-a": EntityResourceOverwrite( + resource_type="entity", name="B", folder_id="folder-b" + ), + "entity.entity-b": EntityResourceOverwrite( + resource_type="entity", name="C", folder_id="folder-c" + ), + } + ) + try: + resolution = service.resolve_entity_set( + [ + DataFabricEntityItem( + id="entity-a", name="A", folder_key="folder-a" + ), + DataFabricEntityItem( + id="entity-b", name="B", folder_key="folder-a" + ), + ] + ) + finally: + _resource_overwrites.reset(token) + + assert resolution.entities_service._routing_strategy.routing_context is not None + assert resolution.entities_service._routing_strategy.routing_context.model_dump( + by_alias=True, exclude_none=True + ) == { + "entityRoutings": [ + {"entityName": "B", "folderId": "folder-b"}, + {"entityName": "C", "folderId": "folder-c"}, + ] + } + @pytest.mark.asyncio async def test_resolve_entity_set_async_resolves_folder_paths_before_fetch( self, @@ -914,9 +960,8 @@ async def test_resolve_entity_set_async_resolves_folder_paths_before_fetch( ) == { "entityRoutings": [ { - "entityName": "Customers", + "entityName": "Overwritten Customers", "folderId": "resolved-folder-id", - "overrideEntityName": "Overwritten Customers", } ] } diff --git a/packages/uipath-platform/uv.lock b/packages/uipath-platform/uv.lock index fc04aa5b1..d021cff2a 100644 --- a/packages/uipath-platform/uv.lock +++ b/packages/uipath-platform/uv.lock @@ -1095,7 +1095,7 @@ dev = [ [[package]] name = "uipath-platform" -version = "0.3.0" +version = "0.3.1" source = { editable = "." } dependencies = [ { name = "anyio" }, diff --git a/packages/uipath/uv.lock b/packages/uipath/uv.lock index 35b84ec80..23d60b2eb 100644 --- a/packages/uipath/uv.lock +++ b/packages/uipath/uv.lock @@ -2762,7 +2762,7 @@ wheels = [ [[package]] name = "uipath-platform" -version = "0.3.0" +version = "0.3.1" source = { editable = "../uipath-platform" } dependencies = [ { name = "anyio" },