From 666fcf3438482ee5a8175620e2411ae867ca78f0 Mon Sep 17 00:00:00 2001 From: Gabriel Martin <91462031+gcuip@users.noreply.github.com> Date: Mon, 9 Mar 2026 18:45:39 +0100 Subject: [PATCH 01/10] feat: implement UnifiedSearch (search v1.2) method [ECS-1656] --- packages/uipath-platform/pyproject.toml | 2 +- .../platform/context_grounding/__init__.py | 12 + .../_context_grounding_service.py | 186 ++++++++- .../context_grounding/context_grounding.py | 92 +++++ .../test_context_grounding_service.py | 355 ++++++++++++++++++ packages/uipath-platform/uv.lock | 2 +- 6 files changed, 646 insertions(+), 3 deletions(-) diff --git a/packages/uipath-platform/pyproject.toml b/packages/uipath-platform/pyproject.toml index b9180b83c..45f1ff45b 100644 --- a/packages/uipath-platform/pyproject.toml +++ b/packages/uipath-platform/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "uipath-platform" -version = "0.0.17" +version = "0.0.18" 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/context_grounding/__init__.py b/packages/uipath-platform/src/uipath/platform/context_grounding/__init__.py index c43d64c68..d89841580 100644 --- a/packages/uipath-platform/src/uipath/platform/context_grounding/__init__.py +++ b/packages/uipath-platform/src/uipath/platform/context_grounding/__init__.py @@ -15,6 +15,12 @@ DeepRagStatus, EphemeralIndexUsage, IndexStatus, + SearchMode, + SemanticSearchOptions, + SemanticSearchResult, + TabularSearchResult, + UnifiedQueryResult, + UnifiedSearchScope, ) from .context_grounding_index import ContextGroundingIndex from .context_grounding_payloads import ( @@ -64,6 +70,12 @@ "Indexer", "OneDriveDataSource", "OneDriveSourceConfig", + "SearchMode", + "SemanticSearchOptions", + "SemanticSearchResult", "SourceConfig", + "TabularSearchResult", + "UnifiedQueryResult", + "UnifiedSearchScope", "Citation", ] diff --git a/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py b/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py index c8d0bea5f..68f000c59 100644 --- a/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py +++ b/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py @@ -33,6 +33,9 @@ DeepRagCreationResponse, DeepRagResponse, EphemeralIndexUsage, + SearchMode, + UnifiedQueryResult, + UnifiedSearchScope, ) from .context_grounding_index import ContextGroundingIndex from .context_grounding_payloads import ( @@ -1279,6 +1282,7 @@ def search( name: str, query: str, number_of_results: int = 10, + threshold: Optional[float] = None, folder_key: Optional[str] = None, folder_path: Optional[str] = None, ) -> List[ContextGroundingQueryResponse]: @@ -1293,6 +1297,7 @@ def search( query (str): The search query in natural language. number_of_results (int, optional): Maximum number of results to return. Defaults to 10. + threshold (float): Minimum similarity threshold. Defaults to 0.0. Returns: List[ContextGroundingQueryResponse]: A list of search results, each containing @@ -1308,6 +1313,7 @@ def search( name, query, number_of_results, + threshold=threshold if threshold is not None else 0.0, folder_key=folder_key, folder_path=folder_path, ) @@ -1330,6 +1336,7 @@ async def search_async( name: str, query: str, number_of_results: int = 10, + threshold: Optional[float] = None, folder_key: Optional[str] = None, folder_path: Optional[str] = None, ) -> List[ContextGroundingQueryResponse]: @@ -1344,6 +1351,7 @@ async def search_async( query (str): The search query in natural language. number_of_results (int, optional): Maximum number of results to return. Defaults to 10. + threshold (float): Minimum similarity threshold. Defaults to 0.0. Returns: List[ContextGroundingQueryResponse]: A list of search results, each containing @@ -1363,6 +1371,7 @@ async def search_async( name, query, number_of_results, + threshold=threshold if threshold is not None else 0.0, folder_key=folder_key, folder_path=folder_path, ) @@ -1378,6 +1387,134 @@ async def search_async( response.json() ) + @resource_override(resource_type="index") + @traced(name="contextgrounding_unified_search", run_type="uipath") + def unified_search( + self, + name: str, + query: str, + search_mode: SearchMode = SearchMode.AUTO, + number_of_results: int = 3, + threshold: float = 0.0, + re_ranker: bool = False, + filter: Optional[str] = None, + scope: Optional[UnifiedSearchScope] = None, + folder_key: Optional[str] = None, + folder_path: Optional[str] = None, + ) -> UnifiedQueryResult: + """Perform a unified search on a context grounding index. + + This method performs a unified search (v1.2) against the specified context index, + supporting both semantic and tabular search modes. + + Args: + name (str): The name of the context index to search in. + query (str): The search query in natural language. + search_mode (SearchMode): The search mode to use. Defaults to AUTO. + number_of_results (int): Maximum number of results to return. Defaults to 3. + threshold (float): Minimum similarity threshold. Defaults to 0.0. + re_ranker (bool): Whether to use re-ranking. Defaults to False. + filter (Optional[str]): Optional filter expression. + scope (Optional[UnifiedSearchScope]): Optional search scope (folder, extension). + folder_key (Optional[str]): The key of the folder where the index resides. + folder_path (Optional[str]): The path of the folder where the index resides. + + Returns: + UnifiedQueryResult: The unified search result containing semantic and/or tabular results. + """ + index = self.retrieve(name, folder_key=folder_key, folder_path=folder_path) + if index and index.in_progress_ingestion(): + raise IngestionInProgressException(index_name=name) + + folder_key = folder_key or index.folder_key + + spec = self._unified_search_spec( + index_id=index.id, + query=query, + search_mode=search_mode, + number_of_results=number_of_results, + threshold=threshold, + re_ranker=re_ranker, + filter=filter, + scope=scope, + folder_key=folder_key, + folder_path=folder_path, + ) + + response = self.request( + spec.method, + spec.endpoint, + json=spec.json, + headers=spec.headers, + ) + + return UnifiedQueryResult.model_validate(response.json()) + + @resource_override(resource_type="index") + @traced(name="contextgrounding_unified_search", run_type="uipath") + async def unified_search_async( + self, + name: str, + query: str, + search_mode: SearchMode = SearchMode.AUTO, + number_of_results: int = 3, + threshold: float = 0.0, + re_ranker: bool = False, + filter: Optional[str] = None, + scope: Optional[UnifiedSearchScope] = None, + folder_key: Optional[str] = None, + folder_path: Optional[str] = None, + ) -> UnifiedQueryResult: + """Asynchronously perform a unified search on a context grounding index. + + This method performs a unified search (v1.2) against the specified context index, + supporting both semantic and tabular search modes. + + Args: + name (str): The name of the context index to search in. + query (str): The search query in natural language. + search_mode (SearchMode): The search mode to use. Defaults to AUTO. + number_of_results (int): Maximum number of results to return. Defaults to 3. + threshold (float): Minimum similarity threshold. Defaults to 0.0. + re_ranker (bool): Whether to use re-ranking. Defaults to False. + filter (Optional[str]): Optional filter expression. + scope (Optional[UnifiedSearchScope]): Optional search scope (folder, extension). + folder_key (Optional[str]): The key of the folder where the index resides. + folder_path (Optional[str]): The path of the folder where the index resides. + + Returns: + UnifiedQueryResult: The unified search result containing semantic and/or tabular results. + """ + index = await self.retrieve_async( + name, folder_key=folder_key, folder_path=folder_path + ) + if index and index.in_progress_ingestion(): + raise IngestionInProgressException(index_name=name) + + folder_key = folder_key or index.folder_key + + spec = self._unified_search_spec( + index_id=index.id, + query=query, + search_mode=search_mode, + number_of_results=number_of_results, + threshold=threshold, + re_ranker=re_ranker, + filter=filter, + scope=scope, + folder_key=folder_key, + folder_path=folder_path, + ) + + response = await self.request_async( + spec.method, + spec.endpoint, + json=spec.json, + headers=spec.headers, + ) + + return UnifiedQueryResult.model_validate(response.json()) + @traced(name="contextgrounding_ingest_data", run_type="uipath") def ingest_data( self, @@ -1757,6 +1894,7 @@ def _search_spec( name: str, query: str, number_of_results: int = 10, + threshold: float = 0.0, folder_key: Optional[str] = None, folder_path: Optional[str] = None, ) -> RequestSpec: @@ -1766,7 +1904,11 @@ def _search_spec( method="POST", endpoint=Endpoint("/ecs_/v1/search"), json={ - "query": {"query": query, "numberOfResults": number_of_results}, + "query": { + "query": query, + "numberOfResults": number_of_results, + "threshold": threshold, + }, "schema": {"name": name}, }, headers={ @@ -1774,6 +1916,48 @@ def _search_spec( }, ) + def _unified_search_spec( + self, + index_id: str, + query: str, + search_mode: SearchMode = SearchMode.AUTO, + number_of_results: int = 3, + threshold: float = 0.0, + re_ranker: bool = False, + filter: Optional[str] = None, + scope: Optional[UnifiedSearchScope] = None, + folder_key: Optional[str] = None, + folder_path: Optional[str] = None, + ) -> RequestSpec: + folder_key = self._resolve_folder_key(folder_key, folder_path) + + json_body: dict = { + "searchMode": search_mode.value + if isinstance(search_mode, SearchMode) + else search_mode, + "query": query, + "semanticSearchOptions": { + "numberOfResults": number_of_results, + "threshold": threshold, + "reRanker": re_ranker, + }, + } + + if filter is not None: + json_body["filter"] = filter + + if scope is not None: + json_body["scope"] = scope.model_dump(by_alias=True, exclude_none=True) + + return RequestSpec( + method="POST", + endpoint=Endpoint(f"/ecs_/v1.2/search/{index_id}"), + json=json_body, + headers={ + **header_folder(folder_key, None), + }, + ) + def _deep_rag_creation_spec( self, index_id: str, diff --git a/packages/uipath-platform/src/uipath/platform/context_grounding/context_grounding.py b/packages/uipath-platform/src/uipath/platform/context_grounding/context_grounding.py index 8d72c8cca..0e5eea804 100644 --- a/packages/uipath-platform/src/uipath/platform/context_grounding/context_grounding.py +++ b/packages/uipath-platform/src/uipath/platform/context_grounding/context_grounding.py @@ -209,3 +209,95 @@ class ContextGroundingQueryResponse(BaseModel): caption: Optional[str] = Field(default=None, alias="caption") score: Optional[float] = Field(default=None, alias="score") reference: Optional[str] = Field(default=None, alias="reference") + + +class SearchMode(str, Enum): + """Enum representing possible unified search modes.""" + + AUTO = "Auto" + SEMANTIC = "Semantic" + TABULAR = "Tabular" + + +class UnifiedSearchScope(BaseModel): + """Model representing the scope for a unified search request.""" + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + use_enum_values=True, + arbitrary_types_allowed=True, + extra="allow", + ) + + folder: Optional[str] = Field(default=None) + extension: Optional[str] = Field(default=None) + + +class SemanticSearchOptions(BaseModel): + """Model representing semantic search options for a unified search request.""" + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + use_enum_values=True, + arbitrary_types_allowed=True, + extra="allow", + ) + + number_of_results: int = Field(default=3, alias="numberOfResults") + threshold: float = Field(default=0.0) + re_ranker: bool = Field(default=False, alias="reRanker") + + +class TabularSearchResult(BaseModel): + """Model representing a tabular search result from a unified search.""" + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + use_enum_values=True, + arbitrary_types_allowed=True, + extra="allow", + ) + + schema_: dict[str, str] = Field(default_factory=dict, alias="schema") + citations: list[dict[str, str]] = Field(default_factory=list) + data: list[list] = Field(default_factory=list) + explanations: Optional[list[str]] = Field(default=None) + + +class SemanticSearchResult(BaseModel): + """Model representing a semantic search result from a unified search.""" + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + use_enum_values=True, + arbitrary_types_allowed=True, + extra="allow", + ) + + values: list[ContextGroundingQueryResponse] = Field( + default_factory=list, alias="values" + ) + + +class UnifiedQueryResult(BaseModel): + """Model representing the result of a unified search query.""" + + model_config = ConfigDict( + validate_by_name=True, + validate_by_alias=True, + use_enum_values=True, + arbitrary_types_allowed=True, + extra="allow", + ) + + tabular_results: Optional[TabularSearchResult] = Field( + default=None, alias="tabularResults" + ) + semantic_results: Optional[SemanticSearchResult] = Field( + default=None, alias="semanticResults" + ) + explanation: Optional[str] = Field(default=None) diff --git a/packages/uipath-platform/tests/services/test_context_grounding_service.py b/packages/uipath-platform/tests/services/test_context_grounding_service.py index 835f5ee9a..57eb6df0f 100644 --- a/packages/uipath-platform/tests/services/test_context_grounding_service.py +++ b/packages/uipath-platform/tests/services/test_context_grounding_service.py @@ -24,6 +24,9 @@ GoogleDriveSourceConfig, Indexer, OneDriveSourceConfig, + SearchMode, + UnifiedQueryResult, + UnifiedSearchScope, ) from uipath.platform.context_grounding._context_grounding_service import ( ContextGroundingService, @@ -2771,3 +2774,355 @@ async def test_download_batch_transform_result_async_encrypted( assert "/DownloadBlob" in str(download_request.url) assert "Authorization" in download_request.headers assert download_request.headers["Authorization"].startswith("Bearer ") + + def test_unified_search( + self, + httpx_mock: HTTPXMock, + service: ContextGroundingService, + base_url: str, + org: str, + tenant: str, + version: str, + ) -> None: + httpx_mock.add_response( + url=f"{base_url}{org}{tenant}/orchestrator_/api/FoldersNavigation/GetFoldersForCurrentUser?searchText=test-folder-path&skip=0&take=20", + status_code=200, + json={ + "PageItems": [ + { + "Key": "test-folder-key", + "FullyQualifiedName": "test-folder-path", + } + ] + }, + ) + + httpx_mock.add_response( + url=f"{base_url}{org}{tenant}/ecs_/v2/indexes?$filter=Name eq 'test-index'&$expand=dataSource", + status_code=200, + json={ + "value": [ + { + "id": "test-index-id", + "name": "test-index", + "lastIngestionStatus": "Completed", + } + ] + }, + ) + + httpx_mock.add_response( + url=f"{base_url}{org}{tenant}/orchestrator_/api/FoldersNavigation/GetFoldersForCurrentUser?searchText=test-folder-path&skip=0&take=20", + status_code=200, + json={ + "PageItems": [ + { + "Key": "test-folder-key", + "FullyQualifiedName": "test-folder-path", + } + ] + }, + ) + + httpx_mock.add_response( + url=f"{base_url}{org}{tenant}/ecs_/v1.2/search/test-index-id", + status_code=200, + json={ + "semanticResults": { + "values": [ + { + "source": "test-source", + "page_number": "1", + "content": "Test content", + "metadata": { + "operation_id": "test-op", + "strategy": "test-strategy", + }, + "score": 0.95, + } + ] + }, + "tabularResults": None, + "explanation": "test explanation", + }, + ) + + response = service.unified_search( + name="test-index", + query="test query", + search_mode=SearchMode.SEMANTIC, + number_of_results=5, + ) + + assert isinstance(response, UnifiedQueryResult) + assert response.explanation == "test explanation" + assert response.tabular_results is None + assert response.semantic_results is not None + assert len(response.semantic_results.values) == 1 + assert response.semantic_results.values[0].source == "test-source" + assert response.semantic_results.values[0].content == "Test content" + assert response.semantic_results.values[0].score == 0.95 + + sent_requests = httpx_mock.get_requests() + if sent_requests is None: + raise Exception("No request was sent") + + search_request = sent_requests[3] + assert search_request.method == "POST" + assert ( + str(search_request.url) + == f"{base_url}{org}{tenant}/ecs_/v1.2/search/test-index-id" + ) + request_body = json.loads(search_request.content) + assert request_body["searchMode"] == "Semantic" + assert request_body["query"] == "test query" + assert request_body["semanticSearchOptions"]["numberOfResults"] == 5 + + assert HEADER_USER_AGENT in search_request.headers + assert ( + search_request.headers[HEADER_USER_AGENT] + == f"UiPath.Python.Sdk/UiPath.Python.Sdk.Activities.ContextGroundingService.unified_search/{version}" + ) + + @pytest.mark.anyio + async def test_unified_search_async( + self, + httpx_mock: HTTPXMock, + service: ContextGroundingService, + base_url: str, + org: str, + tenant: str, + version: str, + ) -> None: + httpx_mock.add_response( + url=f"{base_url}{org}{tenant}/orchestrator_/api/FoldersNavigation/GetFoldersForCurrentUser?searchText=test-folder-path&skip=0&take=20", + status_code=200, + json={ + "PageItems": [ + { + "Key": "test-folder-key", + "FullyQualifiedName": "test-folder-path", + } + ] + }, + ) + + httpx_mock.add_response( + url=f"{base_url}{org}{tenant}/ecs_/v2/indexes?$filter=Name eq 'test-index'&$expand=dataSource", + status_code=200, + json={ + "value": [ + { + "id": "test-index-id", + "name": "test-index", + "lastIngestionStatus": "Completed", + } + ] + }, + ) + + httpx_mock.add_response( + url=f"{base_url}{org}{tenant}/orchestrator_/api/FoldersNavigation/GetFoldersForCurrentUser?searchText=test-folder-path&skip=0&take=20", + status_code=200, + json={ + "PageItems": [ + { + "Key": "test-folder-key", + "FullyQualifiedName": "test-folder-path", + } + ] + }, + ) + + httpx_mock.add_response( + url=f"{base_url}{org}{tenant}/ecs_/v1.2/search/test-index-id", + status_code=200, + json={ + "semanticResults": { + "values": [ + { + "source": "test-source", + "page_number": "1", + "content": "Test content", + "metadata": { + "operation_id": "test-op", + "strategy": "test-strategy", + }, + "score": 0.95, + } + ] + }, + "tabularResults": None, + "explanation": "test explanation", + }, + ) + + response = await service.unified_search_async( + name="test-index", + query="test query", + search_mode=SearchMode.AUTO, + ) + + assert isinstance(response, UnifiedQueryResult) + assert response.explanation == "test explanation" + assert response.semantic_results is not None + assert len(response.semantic_results.values) == 1 + + def test_unified_search_with_tabular_results( + self, + httpx_mock: HTTPXMock, + service: ContextGroundingService, + base_url: str, + org: str, + tenant: str, + ) -> None: + httpx_mock.add_response( + url=f"{base_url}{org}{tenant}/orchestrator_/api/FoldersNavigation/GetFoldersForCurrentUser?searchText=test-folder-path&skip=0&take=20", + status_code=200, + json={ + "PageItems": [ + { + "Key": "test-folder-key", + "FullyQualifiedName": "test-folder-path", + } + ] + }, + ) + + httpx_mock.add_response( + url=f"{base_url}{org}{tenant}/ecs_/v2/indexes?$filter=Name eq 'test-index'&$expand=dataSource", + status_code=200, + json={ + "value": [ + { + "id": "test-index-id", + "name": "test-index", + "lastIngestionStatus": "Completed", + } + ] + }, + ) + + httpx_mock.add_response( + url=f"{base_url}{org}{tenant}/orchestrator_/api/FoldersNavigation/GetFoldersForCurrentUser?searchText=test-folder-path&skip=0&take=20", + status_code=200, + json={ + "PageItems": [ + { + "Key": "test-folder-key", + "FullyQualifiedName": "test-folder-path", + } + ] + }, + ) + + httpx_mock.add_response( + url=f"{base_url}{org}{tenant}/ecs_/v1.2/search/test-index-id", + status_code=200, + json={ + "semanticResults": None, + "tabularResults": { + "schema": {"col1": "string", "col2": "number"}, + "citations": [{"source": "file.csv", "page": "1"}], + "data": [["value1", "42"]], + "explanations": ["Matched on col1"], + }, + "explanation": None, + }, + ) + + response = service.unified_search( + name="test-index", + query="test query", + search_mode=SearchMode.TABULAR, + ) + + assert isinstance(response, UnifiedQueryResult) + assert response.semantic_results is None + assert response.tabular_results is not None + assert response.tabular_results.schema_ == { + "col1": "string", + "col2": "number", + } + assert len(response.tabular_results.data) == 1 + assert response.tabular_results.data[0] == ["value1", "42"] + assert response.tabular_results.citations == [ + {"source": "file.csv", "page": "1"} + ] + assert response.tabular_results.explanations == ["Matched on col1"] + + def test_unified_search_with_scope_and_filter( + self, + httpx_mock: HTTPXMock, + service: ContextGroundingService, + base_url: str, + org: str, + tenant: str, + ) -> None: + httpx_mock.add_response( + url=f"{base_url}{org}{tenant}/orchestrator_/api/FoldersNavigation/GetFoldersForCurrentUser?searchText=test-folder-path&skip=0&take=20", + status_code=200, + json={ + "PageItems": [ + { + "Key": "test-folder-key", + "FullyQualifiedName": "test-folder-path", + } + ] + }, + ) + + httpx_mock.add_response( + url=f"{base_url}{org}{tenant}/ecs_/v2/indexes?$filter=Name eq 'test-index'&$expand=dataSource", + status_code=200, + json={ + "value": [ + { + "id": "test-index-id", + "name": "test-index", + "lastIngestionStatus": "Completed", + } + ] + }, + ) + + httpx_mock.add_response( + url=f"{base_url}{org}{tenant}/orchestrator_/api/FoldersNavigation/GetFoldersForCurrentUser?searchText=test-folder-path&skip=0&take=20", + status_code=200, + json={ + "PageItems": [ + { + "Key": "test-folder-key", + "FullyQualifiedName": "test-folder-path", + } + ] + }, + ) + + httpx_mock.add_response( + url=f"{base_url}{org}{tenant}/ecs_/v1.2/search/test-index-id", + status_code=200, + json={ + "semanticResults": {"values": []}, + "tabularResults": None, + "explanation": None, + }, + ) + + scope = UnifiedSearchScope(folder="docs", extension=".pdf") + + response = service.unified_search( + name="test-index", + query="test query", + filter="category eq 'finance'", + scope=scope, + ) + + assert isinstance(response, UnifiedQueryResult) + + sent_requests = httpx_mock.get_requests() + search_request = sent_requests[3] + request_body = json.loads(search_request.content) + assert request_body["filter"] == "category eq 'finance'" + assert request_body["scope"]["folder"] == "docs" + assert request_body["scope"]["extension"] == ".pdf" diff --git a/packages/uipath-platform/uv.lock b/packages/uipath-platform/uv.lock index cc5073ff8..695f52305 100644 --- a/packages/uipath-platform/uv.lock +++ b/packages/uipath-platform/uv.lock @@ -1061,7 +1061,7 @@ wheels = [ [[package]] name = "uipath-platform" -version = "0.0.17" +version = "0.0.18" source = { editable = "." } dependencies = [ { name = "httpx" }, From 9b3258b98e84b3e4fa3614e9a88bbd613de968fd Mon Sep 17 00:00:00 2001 From: Gabriel Martin <91462031+gcuip@users.noreply.github.com> Date: Mon, 9 Mar 2026 18:49:25 +0100 Subject: [PATCH 02/10] chore: lint --- .../platform/context_grounding/_context_grounding_service.py | 2 +- .../src/uipath/platform/context_grounding/context_grounding.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py b/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py index 68f000c59..7b7755e60 100644 --- a/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py +++ b/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py @@ -1931,7 +1931,7 @@ def _unified_search_spec( ) -> RequestSpec: folder_key = self._resolve_folder_key(folder_key, folder_path) - json_body: dict = { + json_body: Dict[str, Any] = { "searchMode": search_mode.value if isinstance(search_mode, SearchMode) else search_mode, diff --git a/packages/uipath-platform/src/uipath/platform/context_grounding/context_grounding.py b/packages/uipath-platform/src/uipath/platform/context_grounding/context_grounding.py index 0e5eea804..b075dd81b 100644 --- a/packages/uipath-platform/src/uipath/platform/context_grounding/context_grounding.py +++ b/packages/uipath-platform/src/uipath/platform/context_grounding/context_grounding.py @@ -263,7 +263,7 @@ class TabularSearchResult(BaseModel): schema_: dict[str, str] = Field(default_factory=dict, alias="schema") citations: list[dict[str, str]] = Field(default_factory=list) - data: list[list] = Field(default_factory=list) + data: list[list[object]] = Field(default_factory=list) explanations: Optional[list[str]] = Field(default=None) From 89198eb8db035eaef6ad606758cd3ed03afe702e Mon Sep 17 00:00:00 2001 From: Gabriel Martin <91462031+gcuip@users.noreply.github.com> Date: Mon, 9 Mar 2026 22:39:05 +0100 Subject: [PATCH 03/10] chore: remove redundant fields --- .../platform/context_grounding/__init__.py | 2 - .../_context_grounding_service.py | 8 -- .../context_grounding/context_grounding.py | 22 ----- .../test_context_grounding_service.py | 87 ------------------- 4 files changed, 119 deletions(-) diff --git a/packages/uipath-platform/src/uipath/platform/context_grounding/__init__.py b/packages/uipath-platform/src/uipath/platform/context_grounding/__init__.py index d89841580..9bcd7fb18 100644 --- a/packages/uipath-platform/src/uipath/platform/context_grounding/__init__.py +++ b/packages/uipath-platform/src/uipath/platform/context_grounding/__init__.py @@ -18,7 +18,6 @@ SearchMode, SemanticSearchOptions, SemanticSearchResult, - TabularSearchResult, UnifiedQueryResult, UnifiedSearchScope, ) @@ -74,7 +73,6 @@ "SemanticSearchOptions", "SemanticSearchResult", "SourceConfig", - "TabularSearchResult", "UnifiedQueryResult", "UnifiedSearchScope", "Citation", diff --git a/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py b/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py index 7b7755e60..9b1d0b2c4 100644 --- a/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py +++ b/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py @@ -1396,7 +1396,6 @@ def unified_search( search_mode: SearchMode = SearchMode.AUTO, number_of_results: int = 3, threshold: float = 0.0, - re_ranker: bool = False, filter: Optional[str] = None, scope: Optional[UnifiedSearchScope] = None, folder_key: Optional[str] = None, @@ -1413,7 +1412,6 @@ def unified_search( search_mode (SearchMode): The search mode to use. Defaults to AUTO. number_of_results (int): Maximum number of results to return. Defaults to 3. threshold (float): Minimum similarity threshold. Defaults to 0.0. - re_ranker (bool): Whether to use re-ranking. Defaults to False. filter (Optional[str]): Optional filter expression. scope (Optional[UnifiedSearchScope]): Optional search scope (folder, extension). folder_key (Optional[str]): The key of the folder where the index resides. @@ -1434,7 +1432,6 @@ def unified_search( search_mode=search_mode, number_of_results=number_of_results, threshold=threshold, - re_ranker=re_ranker, filter=filter, scope=scope, folder_key=folder_key, @@ -1459,7 +1456,6 @@ async def unified_search_async( search_mode: SearchMode = SearchMode.AUTO, number_of_results: int = 3, threshold: float = 0.0, - re_ranker: bool = False, filter: Optional[str] = None, scope: Optional[UnifiedSearchScope] = None, folder_key: Optional[str] = None, @@ -1476,7 +1472,6 @@ async def unified_search_async( search_mode (SearchMode): The search mode to use. Defaults to AUTO. number_of_results (int): Maximum number of results to return. Defaults to 3. threshold (float): Minimum similarity threshold. Defaults to 0.0. - re_ranker (bool): Whether to use re-ranking. Defaults to False. filter (Optional[str]): Optional filter expression. scope (Optional[UnifiedSearchScope]): Optional search scope (folder, extension). folder_key (Optional[str]): The key of the folder where the index resides. @@ -1499,7 +1494,6 @@ async def unified_search_async( search_mode=search_mode, number_of_results=number_of_results, threshold=threshold, - re_ranker=re_ranker, filter=filter, scope=scope, folder_key=folder_key, @@ -1923,7 +1917,6 @@ def _unified_search_spec( search_mode: SearchMode = SearchMode.AUTO, number_of_results: int = 3, threshold: float = 0.0, - re_ranker: bool = False, filter: Optional[str] = None, scope: Optional[UnifiedSearchScope] = None, folder_key: Optional[str] = None, @@ -1939,7 +1932,6 @@ def _unified_search_spec( "semanticSearchOptions": { "numberOfResults": number_of_results, "threshold": threshold, - "reRanker": re_ranker, }, } diff --git a/packages/uipath-platform/src/uipath/platform/context_grounding/context_grounding.py b/packages/uipath-platform/src/uipath/platform/context_grounding/context_grounding.py index b075dd81b..f22c59bdb 100644 --- a/packages/uipath-platform/src/uipath/platform/context_grounding/context_grounding.py +++ b/packages/uipath-platform/src/uipath/platform/context_grounding/context_grounding.py @@ -216,7 +216,6 @@ class SearchMode(str, Enum): AUTO = "Auto" SEMANTIC = "Semantic" - TABULAR = "Tabular" class UnifiedSearchScope(BaseModel): @@ -247,24 +246,6 @@ class SemanticSearchOptions(BaseModel): number_of_results: int = Field(default=3, alias="numberOfResults") threshold: float = Field(default=0.0) - re_ranker: bool = Field(default=False, alias="reRanker") - - -class TabularSearchResult(BaseModel): - """Model representing a tabular search result from a unified search.""" - - model_config = ConfigDict( - validate_by_name=True, - validate_by_alias=True, - use_enum_values=True, - arbitrary_types_allowed=True, - extra="allow", - ) - - schema_: dict[str, str] = Field(default_factory=dict, alias="schema") - citations: list[dict[str, str]] = Field(default_factory=list) - data: list[list[object]] = Field(default_factory=list) - explanations: Optional[list[str]] = Field(default=None) class SemanticSearchResult(BaseModel): @@ -294,9 +275,6 @@ class UnifiedQueryResult(BaseModel): extra="allow", ) - tabular_results: Optional[TabularSearchResult] = Field( - default=None, alias="tabularResults" - ) semantic_results: Optional[SemanticSearchResult] = Field( default=None, alias="semanticResults" ) diff --git a/packages/uipath-platform/tests/services/test_context_grounding_service.py b/packages/uipath-platform/tests/services/test_context_grounding_service.py index 57eb6df0f..5f92d460b 100644 --- a/packages/uipath-platform/tests/services/test_context_grounding_service.py +++ b/packages/uipath-platform/tests/services/test_context_grounding_service.py @@ -2842,7 +2842,6 @@ def test_unified_search( } ] }, - "tabularResults": None, "explanation": "test explanation", }, ) @@ -2856,7 +2855,6 @@ def test_unified_search( assert isinstance(response, UnifiedQueryResult) assert response.explanation == "test explanation" - assert response.tabular_results is None assert response.semantic_results is not None assert len(response.semantic_results.values) == 1 assert response.semantic_results.values[0].source == "test-source" @@ -2952,7 +2950,6 @@ async def test_unified_search_async( } ] }, - "tabularResults": None, "explanation": "test explanation", }, ) @@ -2968,89 +2965,6 @@ async def test_unified_search_async( assert response.semantic_results is not None assert len(response.semantic_results.values) == 1 - def test_unified_search_with_tabular_results( - self, - httpx_mock: HTTPXMock, - service: ContextGroundingService, - base_url: str, - org: str, - tenant: str, - ) -> None: - httpx_mock.add_response( - url=f"{base_url}{org}{tenant}/orchestrator_/api/FoldersNavigation/GetFoldersForCurrentUser?searchText=test-folder-path&skip=0&take=20", - status_code=200, - json={ - "PageItems": [ - { - "Key": "test-folder-key", - "FullyQualifiedName": "test-folder-path", - } - ] - }, - ) - - httpx_mock.add_response( - url=f"{base_url}{org}{tenant}/ecs_/v2/indexes?$filter=Name eq 'test-index'&$expand=dataSource", - status_code=200, - json={ - "value": [ - { - "id": "test-index-id", - "name": "test-index", - "lastIngestionStatus": "Completed", - } - ] - }, - ) - - httpx_mock.add_response( - url=f"{base_url}{org}{tenant}/orchestrator_/api/FoldersNavigation/GetFoldersForCurrentUser?searchText=test-folder-path&skip=0&take=20", - status_code=200, - json={ - "PageItems": [ - { - "Key": "test-folder-key", - "FullyQualifiedName": "test-folder-path", - } - ] - }, - ) - - httpx_mock.add_response( - url=f"{base_url}{org}{tenant}/ecs_/v1.2/search/test-index-id", - status_code=200, - json={ - "semanticResults": None, - "tabularResults": { - "schema": {"col1": "string", "col2": "number"}, - "citations": [{"source": "file.csv", "page": "1"}], - "data": [["value1", "42"]], - "explanations": ["Matched on col1"], - }, - "explanation": None, - }, - ) - - response = service.unified_search( - name="test-index", - query="test query", - search_mode=SearchMode.TABULAR, - ) - - assert isinstance(response, UnifiedQueryResult) - assert response.semantic_results is None - assert response.tabular_results is not None - assert response.tabular_results.schema_ == { - "col1": "string", - "col2": "number", - } - assert len(response.tabular_results.data) == 1 - assert response.tabular_results.data[0] == ["value1", "42"] - assert response.tabular_results.citations == [ - {"source": "file.csv", "page": "1"} - ] - assert response.tabular_results.explanations == ["Matched on col1"] - def test_unified_search_with_scope_and_filter( self, httpx_mock: HTTPXMock, @@ -3104,7 +3018,6 @@ def test_unified_search_with_scope_and_filter( status_code=200, json={ "semanticResults": {"values": []}, - "tabularResults": None, "explanation": None, }, ) From d0be43ca5c861aca156c4dec22b31f3157930bdc Mon Sep 17 00:00:00 2001 From: Gabriel Martin <91462031+gcuip@users.noreply.github.com> Date: Mon, 9 Mar 2026 22:43:29 +0100 Subject: [PATCH 04/10] chore: change default value for number_of_results to 10 --- .../context_grounding/_context_grounding_service.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py b/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py index 9b1d0b2c4..33347e77c 100644 --- a/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py +++ b/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py @@ -1394,7 +1394,7 @@ def unified_search( name: str, query: str, search_mode: SearchMode = SearchMode.AUTO, - number_of_results: int = 3, + number_of_results: int = 10, threshold: float = 0.0, filter: Optional[str] = None, scope: Optional[UnifiedSearchScope] = None, @@ -1410,7 +1410,7 @@ def unified_search( name (str): The name of the context index to search in. query (str): The search query in natural language. search_mode (SearchMode): The search mode to use. Defaults to AUTO. - number_of_results (int): Maximum number of results to return. Defaults to 3. + number_of_results (int): Maximum number of results to return. Defaults to 10. threshold (float): Minimum similarity threshold. Defaults to 0.0. filter (Optional[str]): Optional filter expression. scope (Optional[UnifiedSearchScope]): Optional search scope (folder, extension). @@ -1454,7 +1454,7 @@ async def unified_search_async( name: str, query: str, search_mode: SearchMode = SearchMode.AUTO, - number_of_results: int = 3, + number_of_results: int = 10, threshold: float = 0.0, filter: Optional[str] = None, scope: Optional[UnifiedSearchScope] = None, @@ -1470,7 +1470,7 @@ async def unified_search_async( name (str): The name of the context index to search in. query (str): The search query in natural language. search_mode (SearchMode): The search mode to use. Defaults to AUTO. - number_of_results (int): Maximum number of results to return. Defaults to 3. + number_of_results (int): Maximum number of results to return. Defaults to 10. threshold (float): Minimum similarity threshold. Defaults to 0.0. filter (Optional[str]): Optional filter expression. scope (Optional[UnifiedSearchScope]): Optional search scope (folder, extension). @@ -1915,7 +1915,7 @@ def _unified_search_spec( index_id: str, query: str, search_mode: SearchMode = SearchMode.AUTO, - number_of_results: int = 3, + number_of_results: int = 10, threshold: float = 0.0, filter: Optional[str] = None, scope: Optional[UnifiedSearchScope] = None, From 68ed685d85664e7fa4f1bec2e15ac0d5d1d7cf59 Mon Sep 17 00:00:00 2001 From: Gabriel Martin <91462031+gcuip@users.noreply.github.com> Date: Tue, 10 Mar 2026 10:42:42 +0100 Subject: [PATCH 05/10] fix: remove in_progress_ingestion check in unified search; deprecate v1/search --- .../platform/context_grounding/_context_grounding_service.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py b/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py index 33347e77c..23d6ececc 100644 --- a/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py +++ b/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py @@ -1,5 +1,6 @@ from pathlib import Path from typing import Annotated, Any, Dict, List, Optional, Tuple, Union +from typing_extensions import deprecated import httpx from pydantic import Field, TypeAdapter @@ -1277,6 +1278,7 @@ async def start_deep_rag_ephemeral_async( @resource_override(resource_type="index") @traced(name="contextgrounding_search", run_type="uipath") + @deprecated("Use unified_search instead.") def search( self, name: str, @@ -1331,6 +1333,7 @@ def search( @resource_override(resource_type="index") @traced(name="contextgrounding_search", run_type="uipath") + @deprecated("Use unified_search_async instead.") async def search_async( self, name: str, @@ -1421,8 +1424,6 @@ def unified_search( UnifiedQueryResult: The unified search result containing semantic and/or tabular results. """ index = self.retrieve(name, folder_key=folder_key, folder_path=folder_path) - if index and index.in_progress_ingestion(): - raise IngestionInProgressException(index_name=name) folder_key = folder_key or index.folder_key From d804d841231b7c276e612af137046a25912d685a Mon Sep 17 00:00:00 2001 From: Gabriel Martin <91462031+gcuip@users.noreply.github.com> Date: Tue, 10 Mar 2026 11:27:03 +0100 Subject: [PATCH 06/10] chore: add deprecated notice in docstring --- .../platform/context_grounding/_context_grounding_service.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py b/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py index 23d6ececc..76fc5643a 100644 --- a/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py +++ b/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py @@ -1290,6 +1290,8 @@ def search( ) -> List[ContextGroundingQueryResponse]: """Search for contextual information within a specific index. + This method is deprecated. Use unified_search instead. + This method performs a semantic search against the specified context index, helping to find relevant information that can be used in automation processes. The search is powered by AI and understands natural language queries. @@ -1345,6 +1347,8 @@ async def search_async( ) -> List[ContextGroundingQueryResponse]: """Search asynchronously for contextual information within a specific index. + This method is deprecated. Use unified_search_async instead. + This method performs a semantic search against the specified context index, helping to find relevant information that can be used in automation processes. The search is powered by AI and understands natural language queries. From 640e9ddfb5d2889437e68b3f1e6545fe02ae7030 Mon Sep 17 00:00:00 2001 From: Gabriel Martin <91462031+gcuip@users.noreply.github.com> Date: Wed, 11 Mar 2026 16:42:11 +0100 Subject: [PATCH 07/10] chore: bump version --- packages/uipath-platform/pyproject.toml | 2 +- packages/uipath-platform/uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/uipath-platform/pyproject.toml b/packages/uipath-platform/pyproject.toml index 45f1ff45b..454c16811 100644 --- a/packages/uipath-platform/pyproject.toml +++ b/packages/uipath-platform/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "uipath-platform" -version = "0.0.18" +version = "0.0.19" 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/uv.lock b/packages/uipath-platform/uv.lock index 695f52305..975e85064 100644 --- a/packages/uipath-platform/uv.lock +++ b/packages/uipath-platform/uv.lock @@ -1061,7 +1061,7 @@ wheels = [ [[package]] name = "uipath-platform" -version = "0.0.18" +version = "0.0.19" source = { editable = "." } dependencies = [ { name = "httpx" }, From 212d712fa53943473cf8d9fbdee984bc3d37046b Mon Sep 17 00:00:00 2001 From: Gabriel Martin <91462031+gcuip@users.noreply.github.com> Date: Wed, 11 Mar 2026 17:16:09 +0100 Subject: [PATCH 08/10] chore: uv lock --- packages/uipath-platform/uv.lock | 28 ++++++++++++--- packages/uipath/uv.lock | 60 ++++++++++++++++++++++++++------ 2 files changed, 72 insertions(+), 16 deletions(-) diff --git a/packages/uipath-platform/uv.lock b/packages/uipath-platform/uv.lock index 975e85064..4a7830068 100644 --- a/packages/uipath-platform/uv.lock +++ b/packages/uipath-platform/uv.lock @@ -1048,15 +1048,33 @@ wheels = [ [[package]] name = "uipath-core" version = "0.5.6" -source = { registry = "https://pypi.org/simple" } +source = { editable = "../uipath-core" } dependencies = [ { name = "opentelemetry-instrumentation" }, { name = "opentelemetry-sdk" }, { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ea/8a/d129d33a81865f99d9134391a52f8691f557d95a18a38df4d88917b3e235/uipath_core-0.5.6.tar.gz", hash = "sha256:bebaf2e62111e844739e4f4e4dc47c48bac93b7e6fce6754502a9f4979c41888", size = 112659, upload-time = "2026-03-04T18:04:42.963Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/54/8f/77ab712518aa2a8485a558a0de245ac425e07fd8b74cfa8951550f0aea63/uipath_core-0.5.6-py3-none-any.whl", hash = "sha256:4a741fc760605165b0541b3abb6ade728bfa386e000ace00054bc43995720e5b", size = 42047, upload-time = "2026-03-04T18:04:41.606Z" }, + +[package.metadata] +requires-dist = [ + { name = "opentelemetry-instrumentation", specifier = ">=0.60b0,<1.0.0" }, + { name = "opentelemetry-sdk", specifier = ">=1.39.0,<2.0.0" }, + { name = "pydantic", specifier = ">=2.12.5,<3.0.0" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "bandit", specifier = ">=1.8.2" }, + { name = "mypy", specifier = ">=1.14.1" }, + { name = "pre-commit", specifier = ">=4.1.0" }, + { name = "pytest", specifier = ">=7.4.0" }, + { name = "pytest-asyncio", specifier = ">=1.0.0" }, + { name = "pytest-cov", specifier = ">=4.1.0" }, + { name = "pytest-httpx", specifier = ">=0.35.0" }, + { name = "pytest-mock", specifier = ">=3.11.1" }, + { name = "pytest-trio", specifier = ">=0.8.0" }, + { name = "ruff", specifier = ">=0.9.4" }, + { name = "rust-just", specifier = ">=1.39.0" }, ] [[package]] @@ -1092,7 +1110,7 @@ requires-dist = [ { name = "pydantic-function-models", specifier = ">=0.1.11" }, { name = "tenacity", specifier = ">=9.0.0" }, { name = "truststore", specifier = ">=0.10.1" }, - { name = "uipath-core", specifier = ">=0.5.4,<0.6.0" }, + { name = "uipath-core", editable = "../uipath-core" }, ] [package.metadata.requires-dev] diff --git a/packages/uipath/uv.lock b/packages/uipath/uv.lock index f7e3594d4..d09945ced 100644 --- a/packages/uipath/uv.lock +++ b/packages/uipath/uv.lock @@ -2602,8 +2602,8 @@ requires-dist = [ { name = "rich", specifier = ">=14.2.0" }, { name = "tenacity", specifier = ">=9.0.0" }, { name = "truststore", specifier = ">=0.10.1" }, - { name = "uipath-core", specifier = ">=0.5.2,<0.6.0" }, - { name = "uipath-platform", specifier = ">=0.0.4,<0.1.0" }, + { name = "uipath-core", editable = "../uipath-core" }, + { name = "uipath-platform", editable = "../uipath-platform" }, { name = "uipath-runtime", specifier = ">=0.9.1,<0.10.0" }, ] @@ -2639,21 +2639,39 @@ dev = [ [[package]] name = "uipath-core" version = "0.5.6" -source = { registry = "https://pypi.org/simple" } +source = { editable = "../uipath-core" } dependencies = [ { name = "opentelemetry-instrumentation" }, { name = "opentelemetry-sdk" }, { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ea/8a/d129d33a81865f99d9134391a52f8691f557d95a18a38df4d88917b3e235/uipath_core-0.5.6.tar.gz", hash = "sha256:bebaf2e62111e844739e4f4e4dc47c48bac93b7e6fce6754502a9f4979c41888", size = 112659, upload-time = "2026-03-04T18:04:42.963Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/54/8f/77ab712518aa2a8485a558a0de245ac425e07fd8b74cfa8951550f0aea63/uipath_core-0.5.6-py3-none-any.whl", hash = "sha256:4a741fc760605165b0541b3abb6ade728bfa386e000ace00054bc43995720e5b", size = 42047, upload-time = "2026-03-04T18:04:41.606Z" }, + +[package.metadata] +requires-dist = [ + { name = "opentelemetry-instrumentation", specifier = ">=0.60b0,<1.0.0" }, + { name = "opentelemetry-sdk", specifier = ">=1.39.0,<2.0.0" }, + { name = "pydantic", specifier = ">=2.12.5,<3.0.0" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "bandit", specifier = ">=1.8.2" }, + { name = "mypy", specifier = ">=1.14.1" }, + { name = "pre-commit", specifier = ">=4.1.0" }, + { name = "pytest", specifier = ">=7.4.0" }, + { name = "pytest-asyncio", specifier = ">=1.0.0" }, + { name = "pytest-cov", specifier = ">=4.1.0" }, + { name = "pytest-httpx", specifier = ">=0.35.0" }, + { name = "pytest-mock", specifier = ">=3.11.1" }, + { name = "pytest-trio", specifier = ">=0.8.0" }, + { name = "ruff", specifier = ">=0.9.4" }, + { name = "rust-just", specifier = ">=1.39.0" }, ] [[package]] name = "uipath-platform" -version = "0.0.17" -source = { registry = "https://pypi.org/simple" } +version = "0.0.19" +source = { editable = "../uipath-platform" } dependencies = [ { name = "httpx" }, { name = "pydantic-function-models" }, @@ -2661,9 +2679,29 @@ dependencies = [ { name = "truststore" }, { name = "uipath-core" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1e/c9/e7568133f3a657af16b67444c4e090259941078acc62acb1e2c072903da4/uipath_platform-0.0.17.tar.gz", hash = "sha256:a2c228462d7e2642dcfc249547d9b8e94ba1c72b68f16ba673ee3e58204e9365", size = 264143, upload-time = "2026-03-06T20:34:22.23Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/36/d1/a1c357dbea16a8b5d5b8ae5311ff2353cc03a8b5dd15ff83b0b693687930/uipath_platform-0.0.17-py3-none-any.whl", hash = "sha256:7b88f2b4eb189877fb2f99d704fc0cbc6e4244f01dac59cf812fa8a03db95e36", size = 159073, upload-time = "2026-03-06T20:34:20.993Z" }, + +[package.metadata] +requires-dist = [ + { name = "httpx", specifier = ">=0.28.1" }, + { name = "pydantic-function-models", specifier = ">=0.1.11" }, + { name = "tenacity", specifier = ">=9.0.0" }, + { name = "truststore", specifier = ">=0.10.1" }, + { name = "uipath-core", editable = "../uipath-core" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "bandit", specifier = ">=1.8.2" }, + { name = "mypy", specifier = ">=1.19.0" }, + { name = "pre-commit", specifier = ">=4.1.0" }, + { name = "pytest", specifier = ">=7.4.0" }, + { name = "pytest-asyncio", specifier = ">=1.0.0" }, + { name = "pytest-cov", specifier = ">=4.1.0" }, + { name = "pytest-httpx", specifier = ">=0.35.0" }, + { name = "pytest-mock", specifier = ">=3.11.1" }, + { name = "pytest-trio", specifier = ">=0.8.0" }, + { name = "ruff", specifier = ">=0.9.4" }, + { name = "rust-just", specifier = ">=1.39.0" }, ] [[package]] From 270396f6cb8c2a3f4fd50cf2bf61b5ff50d27d11 Mon Sep 17 00:00:00 2001 From: Gabriel Martin <91462031+gcuip@users.noreply.github.com> Date: Wed, 11 Mar 2026 17:19:47 +0100 Subject: [PATCH 09/10] fix: lint --- .../platform/context_grounding/_context_grounding_service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py b/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py index 76fc5643a..06388fb53 100644 --- a/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py +++ b/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py @@ -1,9 +1,9 @@ from pathlib import Path from typing import Annotated, Any, Dict, List, Optional, Tuple, Union -from typing_extensions import deprecated import httpx from pydantic import Field, TypeAdapter +from typing_extensions import deprecated from uipath.core.tracing import traced from ..common._base_service import BaseService From 8209f19e1152003a0ea5cb059a9fb09d87ceb775 Mon Sep 17 00:00:00 2001 From: Gabriel Martin <91462031+gcuip@users.noreply.github.com> Date: Wed, 11 Mar 2026 17:31:48 +0100 Subject: [PATCH 10/10] chore: remove obsolete filter field --- packages/uipath-platform/pyproject.toml | 2 +- .../context_grounding/_context_grounding_service.py | 10 ---------- .../tests/services/test_context_grounding_service.py | 5 ++--- packages/uipath-platform/uv.lock | 2 +- packages/uipath/uv.lock | 2 +- 5 files changed, 5 insertions(+), 16 deletions(-) diff --git a/packages/uipath-platform/pyproject.toml b/packages/uipath-platform/pyproject.toml index 27ddf50ce..ec92f1023 100644 --- a/packages/uipath-platform/pyproject.toml +++ b/packages/uipath-platform/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "uipath-platform" -version = "0.0.19" +version = "0.0.20" 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/context_grounding/_context_grounding_service.py b/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py index 06388fb53..8d93993b7 100644 --- a/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py +++ b/packages/uipath-platform/src/uipath/platform/context_grounding/_context_grounding_service.py @@ -1403,7 +1403,6 @@ def unified_search( search_mode: SearchMode = SearchMode.AUTO, number_of_results: int = 10, threshold: float = 0.0, - filter: Optional[str] = None, scope: Optional[UnifiedSearchScope] = None, folder_key: Optional[str] = None, folder_path: Optional[str] = None, @@ -1419,7 +1418,6 @@ def unified_search( search_mode (SearchMode): The search mode to use. Defaults to AUTO. number_of_results (int): Maximum number of results to return. Defaults to 10. threshold (float): Minimum similarity threshold. Defaults to 0.0. - filter (Optional[str]): Optional filter expression. scope (Optional[UnifiedSearchScope]): Optional search scope (folder, extension). folder_key (Optional[str]): The key of the folder where the index resides. folder_path (Optional[str]): The path of the folder where the index resides. @@ -1437,7 +1435,6 @@ def unified_search( search_mode=search_mode, number_of_results=number_of_results, threshold=threshold, - filter=filter, scope=scope, folder_key=folder_key, folder_path=folder_path, @@ -1461,7 +1458,6 @@ async def unified_search_async( search_mode: SearchMode = SearchMode.AUTO, number_of_results: int = 10, threshold: float = 0.0, - filter: Optional[str] = None, scope: Optional[UnifiedSearchScope] = None, folder_key: Optional[str] = None, folder_path: Optional[str] = None, @@ -1477,7 +1473,6 @@ async def unified_search_async( search_mode (SearchMode): The search mode to use. Defaults to AUTO. number_of_results (int): Maximum number of results to return. Defaults to 10. threshold (float): Minimum similarity threshold. Defaults to 0.0. - filter (Optional[str]): Optional filter expression. scope (Optional[UnifiedSearchScope]): Optional search scope (folder, extension). folder_key (Optional[str]): The key of the folder where the index resides. folder_path (Optional[str]): The path of the folder where the index resides. @@ -1499,7 +1494,6 @@ async def unified_search_async( search_mode=search_mode, number_of_results=number_of_results, threshold=threshold, - filter=filter, scope=scope, folder_key=folder_key, folder_path=folder_path, @@ -1922,7 +1916,6 @@ def _unified_search_spec( search_mode: SearchMode = SearchMode.AUTO, number_of_results: int = 10, threshold: float = 0.0, - filter: Optional[str] = None, scope: Optional[UnifiedSearchScope] = None, folder_key: Optional[str] = None, folder_path: Optional[str] = None, @@ -1940,9 +1933,6 @@ def _unified_search_spec( }, } - if filter is not None: - json_body["filter"] = filter - if scope is not None: json_body["scope"] = scope.model_dump(by_alias=True, exclude_none=True) diff --git a/packages/uipath-platform/tests/services/test_context_grounding_service.py b/packages/uipath-platform/tests/services/test_context_grounding_service.py index 5f92d460b..1a878c40d 100644 --- a/packages/uipath-platform/tests/services/test_context_grounding_service.py +++ b/packages/uipath-platform/tests/services/test_context_grounding_service.py @@ -2965,7 +2965,7 @@ async def test_unified_search_async( assert response.semantic_results is not None assert len(response.semantic_results.values) == 1 - def test_unified_search_with_scope_and_filter( + def test_unified_search_with_scope( self, httpx_mock: HTTPXMock, service: ContextGroundingService, @@ -3027,7 +3027,6 @@ def test_unified_search_with_scope_and_filter( response = service.unified_search( name="test-index", query="test query", - filter="category eq 'finance'", scope=scope, ) @@ -3036,6 +3035,6 @@ def test_unified_search_with_scope_and_filter( sent_requests = httpx_mock.get_requests() search_request = sent_requests[3] request_body = json.loads(search_request.content) - assert request_body["filter"] == "category eq 'finance'" + assert "filter" not in request_body assert request_body["scope"]["folder"] == "docs" assert request_body["scope"]["extension"] == ".pdf" diff --git a/packages/uipath-platform/uv.lock b/packages/uipath-platform/uv.lock index ec719e7bf..842a01e77 100644 --- a/packages/uipath-platform/uv.lock +++ b/packages/uipath-platform/uv.lock @@ -1088,7 +1088,7 @@ dev = [ [[package]] name = "uipath-platform" -version = "0.0.19" +version = "0.0.20" source = { editable = "." } dependencies = [ { name = "httpx" }, diff --git a/packages/uipath/uv.lock b/packages/uipath/uv.lock index f0f572038..5dde6c99e 100644 --- a/packages/uipath/uv.lock +++ b/packages/uipath/uv.lock @@ -2679,7 +2679,7 @@ dev = [ [[package]] name = "uipath-platform" -version = "0.0.19" +version = "0.0.20" source = { editable = "../uipath-platform" } dependencies = [ { name = "httpx" },