1919from ..errors import (
2020 BatchTransformFailedException ,
2121 BatchTransformNotCompleteException ,
22+ ContextGroundingIndexNotFoundError ,
2223 IngestionInProgressException ,
2324 UnsupportedDataSourceException ,
2425)
@@ -256,37 +257,81 @@ async def retrieve_across_folders_async(
256257 ContextGroundingIndex .model_validate (item ) for item in response ["value" ]
257258 ]
258259
260+ @traced (name = "contextgrounding_retrieve_system_indexes" , run_type = "uipath" )
261+ def _retrieve_system_indexes (
262+ self ,
263+ name : Optional [str ] = None ,
264+ ) -> List [ContextGroundingIndex ]:
265+ spec = self ._retrieve_system_indexes_spec (name = name )
266+
267+ response = self .request (
268+ spec .method ,
269+ spec .endpoint ,
270+ params = spec .params ,
271+ ).json ()
272+
273+ return [
274+ ContextGroundingIndex .model_validate (item ) for item in response ["value" ]
275+ ]
276+
277+ @traced (name = "contextgrounding_retrieve_system_indexes" , run_type = "uipath" )
278+ async def _retrieve_system_indexes_async (
279+ self ,
280+ name : Optional [str ] = None ,
281+ ) -> List [ContextGroundingIndex ]:
282+ spec = self ._retrieve_system_indexes_spec (name = name )
283+
284+ response = (
285+ await self .request_async (
286+ spec .method ,
287+ spec .endpoint ,
288+ params = spec .params ,
289+ )
290+ ).json ()
291+
292+ return [
293+ ContextGroundingIndex .model_validate (item ) for item in response ["value" ]
294+ ]
295+
259296 @resource_override (resource_type = "index" )
260297 @traced (name = "contextgrounding_retrieve" , run_type = "uipath" )
261298 def retrieve (
262299 self ,
263300 name : str ,
264301 folder_key : Optional [str ] = None ,
265302 folder_path : Optional [str ] = None ,
303+ include_system_indexes : bool = False ,
266304 ) -> ContextGroundingIndex :
267305 """Retrieve context grounding index information by its name.
268306
269307 If no folder_key or folder_path is provided and no folder context is
270- configured, falls back to searching across all folders.
308+ configured, falls back to searching across all folders. When
309+ ``include_system_indexes`` is True, an additional fallback against
310+ system indexes is attempted before raising not-found.
271311
272312 Args:
273313 name (str): The name of the context index to retrieve.
274314 folder_key (Optional[str]): The key of the folder where the index resides.
275315 folder_path (Optional[str]): The path of the folder where the index resides.
316+ include_system_indexes (bool): If True, fall back to system indexes
317+ when the index is not found in the per-folder or across-folders listings.
318+ Defaults to False.
276319
277320 Returns:
278321 ContextGroundingIndex: The index information, including its configuration and metadata if found.
279322
280323 Raises:
281- Exception : If no index with the given name is found.
324+ ContextGroundingIndexNotFoundError : If no index with the given name is found.
282325 """
283326 resolved_folder_key = self ._resolve_folder_key (folder_key , folder_path )
284327 if not resolved_folder_key :
285328 indexes = self .retrieve_across_folders (name = name )
286329 try :
287330 return next (index for index in indexes if index .name == name )
288- except StopIteration as e :
289- raise Exception ("ContextGroundingIndex not found" ) from e
331+ except StopIteration :
332+ if include_system_indexes :
333+ return self ._retrieve_from_system_indexes (name )
334+ raise ContextGroundingIndexNotFoundError (name ) from None
290335
291336 spec = self ._retrieve_spec (
292337 name ,
@@ -305,8 +350,10 @@ def retrieve(
305350 for item in response ["value" ]
306351 if item ["name" ] == name
307352 )
308- except StopIteration as e :
309- raise Exception ("ContextGroundingIndex not found" ) from e
353+ except StopIteration :
354+ if include_system_indexes :
355+ return self ._retrieve_from_system_indexes (name )
356+ raise ContextGroundingIndexNotFoundError (name ) from None
310357
311358 @resource_override (resource_type = "index" )
312359 @traced (name = "contextgrounding_retrieve" , run_type = "uipath" )
@@ -315,30 +362,38 @@ async def retrieve_async(
315362 name : str ,
316363 folder_key : Optional [str ] = None ,
317364 folder_path : Optional [str ] = None ,
365+ include_system_indexes : bool = False ,
318366 ) -> ContextGroundingIndex :
319367 """Asynchronously retrieve context grounding index information by its name.
320368
321369 If no folder_key or folder_path is provided and no folder context is
322- configured, falls back to searching across all folders.
370+ configured, falls back to searching across all folders. When
371+ ``include_system_indexes`` is True, an additional fallback against
372+ system indexes is attempted before raising not-found.
323373
324374 Args:
325375 name (str): The name of the context index to retrieve.
326376 folder_key (Optional[str]): The key of the folder where the index resides.
327377 folder_path (Optional[str]): The path of the folder where the index resides.
378+ include_system_indexes (bool): If True, fall back to system indexes when
379+ the index is not found in the per-folder or across-folders listings.
380+ Defaults to False.
328381
329382 Returns:
330383 ContextGroundingIndex: The index information, including its configuration and metadata if found.
331384
332385 Raises:
333- Exception : If no index with the given name is found.
386+ ContextGroundingIndexNotFoundError : If no index with the given name is found.
334387 """
335388 resolved_folder_key = self ._resolve_folder_key (folder_key , folder_path )
336389 if not resolved_folder_key :
337390 indexes = await self .retrieve_across_folders_async (name = name )
338391 try :
339392 return next (index for index in indexes if index .name == name )
340- except StopIteration as e :
341- raise Exception ("ContextGroundingIndex not found" ) from e
393+ except StopIteration :
394+ if include_system_indexes :
395+ return await self ._retrieve_from_system_indexes_async (name )
396+ raise ContextGroundingIndexNotFoundError (name ) from None
342397
343398 spec = self ._retrieve_spec (
344399 name ,
@@ -359,8 +414,26 @@ async def retrieve_async(
359414 for item in response ["value" ]
360415 if item ["name" ] == name
361416 )
362- except StopIteration as e :
363- raise Exception ("ContextGroundingIndex not found" ) from e
417+ except StopIteration :
418+ if include_system_indexes :
419+ return await self ._retrieve_from_system_indexes_async (name )
420+ raise ContextGroundingIndexNotFoundError (name ) from None
421+
422+ def _retrieve_from_system_indexes (self , name : str ) -> ContextGroundingIndex :
423+ indexes = self ._retrieve_system_indexes (name = name )
424+ try :
425+ return next (index for index in indexes if index .name == name )
426+ except StopIteration :
427+ raise ContextGroundingIndexNotFoundError (name ) from None
428+
429+ async def _retrieve_from_system_indexes_async (
430+ self , name : str
431+ ) -> ContextGroundingIndex :
432+ indexes = await self ._retrieve_system_indexes_async (name = name )
433+ try :
434+ return next (index for index in indexes if index .name == name )
435+ except StopIteration :
436+ raise ContextGroundingIndexNotFoundError (name ) from None
364437
365438 @traced (name = "contextgrounding_list" , run_type = "uipath" )
366439 def list (
@@ -1489,6 +1562,7 @@ def unified_search(
14891562 scope : Optional [UnifiedSearchScope ] = None ,
14901563 folder_key : Optional [str ] = None ,
14911564 folder_path : Optional [str ] = None ,
1565+ include_system_indexes : bool = False ,
14921566 ) -> UnifiedQueryResult :
14931567 """Perform a unified search on a context grounding index.
14941568
@@ -1504,11 +1578,19 @@ def unified_search(
15041578 scope (Optional[UnifiedSearchScope]): Optional search scope (folder, extension).
15051579 folder_key (Optional[str]): The key of the folder where the index resides.
15061580 folder_path (Optional[str]): The path of the folder where the index resides.
1581+ include_system_indexes (bool): If True, fall back to tenant-wide
1582+ system indexes when the index is not found in folder or
1583+ across-folders listings. Defaults to False.
15071584
15081585 Returns:
15091586 UnifiedQueryResult: The unified search result containing semantic and/or tabular results.
15101587 """
1511- index = self .retrieve (name , folder_key = folder_key , folder_path = folder_path )
1588+ index = self .retrieve (
1589+ name ,
1590+ folder_key = folder_key ,
1591+ folder_path = folder_path ,
1592+ include_system_indexes = include_system_indexes ,
1593+ )
15121594
15131595 folder_key = folder_key or index .folder_key
15141596
@@ -1544,6 +1626,7 @@ async def unified_search_async(
15441626 scope : Optional [UnifiedSearchScope ] = None ,
15451627 folder_key : Optional [str ] = None ,
15461628 folder_path : Optional [str ] = None ,
1629+ include_system_indexes : bool = False ,
15471630 ) -> UnifiedQueryResult :
15481631 """Asynchronously perform a unified search on a context grounding index.
15491632
@@ -1559,12 +1642,18 @@ async def unified_search_async(
15591642 scope (Optional[UnifiedSearchScope]): Optional search scope (folder, extension).
15601643 folder_key (Optional[str]): The key of the folder where the index resides.
15611644 folder_path (Optional[str]): The path of the folder where the index resides.
1645+ include_system_indexes (bool): If True, fall back to tenant-wide
1646+ system indexes when the index is not found in folder or
1647+ across-folders listings. Defaults to False.
15621648
15631649 Returns:
15641650 UnifiedQueryResult: The unified search result containing semantic and/or tabular results.
15651651 """
15661652 index = await self .retrieve_async (
1567- name , folder_key = folder_key , folder_path = folder_path
1653+ name ,
1654+ folder_key = folder_key ,
1655+ folder_path = folder_path ,
1656+ include_system_indexes = include_system_indexes ,
15681657 )
15691658 if index and index .in_progress_ingestion ():
15701659 raise IngestionInProgressException (index_name = name )
@@ -1911,6 +2000,16 @@ def _ingest_spec(
19112000 },
19122001 )
19132002
2003+ @staticmethod
2004+ def _odata_name_filter (name : str ) -> str :
2005+ """Build an OData ``Name eq '<name>'`` filter with single quotes escaped.
2006+
2007+ OData string literals escape ``'`` by doubling it. URL encoding of the
2008+ resulting filter is handled by the HTTP client when params are passed
2009+ as a dict.
2010+ """
2011+ return "Name eq '{}'" .format (name .replace ("'" , "''" ))
2012+
19142013 def _retrieve_across_folders_spec (
19152014 self ,
19162015 name : Optional [str ] = None ,
@@ -1919,14 +2018,30 @@ def _retrieve_across_folders_spec(
19192018 "$expand" : "dataSource" ,
19202019 }
19212020 if name :
1922- params ["$filter" ] = f"Name eq ' { name } '"
2021+ params ["$filter" ] = self . _odata_name_filter ( name )
19232022
19242023 return RequestSpec (
19252024 method = "GET" ,
19262025 endpoint = Endpoint ("/ecs_/v2/indexes/allacrossfolders" ),
19272026 params = params ,
19282027 )
19292028
2029+ def _retrieve_system_indexes_spec (
2030+ self ,
2031+ name : Optional [str ] = None ,
2032+ ) -> RequestSpec :
2033+ params : Dict [str , str ] = {
2034+ "$expand" : "dataSource" ,
2035+ }
2036+ if name :
2037+ params ["$filter" ] = self ._odata_name_filter (name )
2038+
2039+ return RequestSpec (
2040+ method = "GET" ,
2041+ endpoint = Endpoint ("/ecs_/v2/indexes/allsystemindexes" ),
2042+ params = params ,
2043+ )
2044+
19302045 def _list_spec (
19312046 self ,
19322047 folder_key : Optional [str ] = None ,
@@ -1954,7 +2069,7 @@ def _retrieve_spec(
19542069 method = "GET" ,
19552070 endpoint = Endpoint ("/ecs_/v2/indexes" ),
19562071 params = {
1957- "$filter" : f"Name eq ' { name } '" ,
2072+ "$filter" : self . _odata_name_filter ( name ) ,
19582073 "$expand" : "dataSource" ,
19592074 },
19602075 headers = {
0 commit comments