Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/uipath-platform/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "uipath-platform"
version = "0.1.13"
version = "0.1.14"
description = "HTTP client library for programmatic access to UiPath Platform"
readme = { file = "README.md", content-type = "text/markdown" }
requires-python = ">=3.11"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,62 @@ async def retrieve_async(
except StopIteration as e:
raise Exception("ContextGroundingIndex not found") from e

@traced(name="contextgrounding_list", run_type="uipath")
def list(
self,
folder_key: Optional[str] = None,
folder_path: Optional[str] = None,
) -> List[ContextGroundingIndex]:
"""List all context grounding indexes in a folder.

Args:
folder_key (Optional[str]): The key of the folder to list indexes from.
folder_path (Optional[str]): The path of the folder to list indexes from.

Returns:
List[ContextGroundingIndex]: All indexes in the folder.
"""
folder_key = self._resolve_folder_key(folder_key, folder_path)
response = self.request(
"GET",
Endpoint("/ecs_/v2/indexes"),
params={"$expand": "dataSource"},
headers={**header_folder(folder_key, None)},
).json()
return [
ContextGroundingIndex.model_validate(item)
for item in response.get("value", [])
]

@traced(name="contextgrounding_list", run_type="uipath")
async def list_async(
self,
folder_key: Optional[str] = None,
folder_path: Optional[str] = None,
) -> List[ContextGroundingIndex]:
"""Asynchronously list all context grounding indexes in a folder.

Args:
folder_key (Optional[str]): The key of the folder to list indexes from.
folder_path (Optional[str]): The path of the folder to list indexes from.

Returns:
List[ContextGroundingIndex]: All indexes in the folder.
"""
folder_key = self._resolve_folder_key(folder_key, folder_path)
response = (
await self.request_async(
"GET",
Endpoint("/ecs_/v2/indexes"),
params={"$expand": "dataSource"},
headers={**header_folder(folder_key, None)},
)
).json()
return [
ContextGroundingIndex.model_validate(item)
for item in response.get("value", [])
]

@traced(name="contextgrounding_retrieve_by_id", run_type="uipath")
def retrieve_by_id(
self,
Expand Down Expand Up @@ -542,7 +598,7 @@ async def create_index_async(
@resource_override(resource_type="index")
@traced(name="contextgrounding_create_ephemeral_index", run_type="uipath")
def create_ephemeral_index(
self, usage: EphemeralIndexUsage, attachments: list[str]
self, usage: EphemeralIndexUsage, attachments: List[str]
) -> ContextGroundingIndex:
"""Create a new ephemeral context grounding index.

Expand Down Expand Up @@ -570,7 +626,7 @@ def create_ephemeral_index(
@resource_override(resource_type="index")
@traced(name="contextgrounding_create_ephemeral_index", run_type="uipath")
async def create_ephemeral_index_async(
self, usage: EphemeralIndexUsage, attachments: list[str]
self, usage: EphemeralIndexUsage, attachments: List[str]
) -> ContextGroundingIndex:
"""Create a new ephemeral context grounding index.

Expand Down Expand Up @@ -661,7 +717,7 @@ def start_batch_transform(
self,
name: str,
prompt: Annotated[str, Field(max_length=250000)],
output_columns: list[BatchTransformOutputColumn],
output_columns: List[BatchTransformOutputColumn],
storage_bucket_folder_path_prefix: Annotated[
str | None, Field(max_length=512)
] = None,
Expand Down Expand Up @@ -737,7 +793,7 @@ async def start_batch_transform_async(
self,
name: str,
prompt: Annotated[str, Field(max_length=250000)],
output_columns: list[BatchTransformOutputColumn],
output_columns: List[BatchTransformOutputColumn],
storage_bucket_folder_path_prefix: Annotated[
str | None, Field(max_length=512)
] = None,
Expand Down Expand Up @@ -813,7 +869,7 @@ async def start_batch_transform_ephemeral(
self,
name: str,
prompt: Annotated[str, Field(max_length=250000)],
output_columns: list[BatchTransformOutputColumn],
output_columns: List[BatchTransformOutputColumn],
storage_bucket_folder_path_prefix: Annotated[
str | None, Field(max_length=512)
] = None,
Expand Down Expand Up @@ -859,7 +915,7 @@ async def start_batch_transform_ephemeral_async(
self,
name: str,
prompt: Annotated[str, Field(max_length=250000)],
output_columns: list[BatchTransformOutputColumn],
output_columns: List[BatchTransformOutputColumn],
storage_bucket_folder_path_prefix: Annotated[
str | None, Field(max_length=512)
] = None,
Expand Down Expand Up @@ -1741,7 +1797,7 @@ def _create_spec(
def _create_ephemeral_spec(
self,
usage: str,
attachments: list[str],
attachments: List[str],
) -> RequestSpec:
"""Create request spec for ephemeral index creation.

Expand Down Expand Up @@ -1834,7 +1890,7 @@ def _build_data_source(self, source: SourceConfig) -> Dict[str, Any]:

return data_source.model_dump(by_alias=True, exclude_none=True)

def _build_ephemeral_data_source(self, attachments: list[str]) -> Dict[str, Any]:
def _build_ephemeral_data_source(self, attachments: List[str]) -> Dict[str, Any]:
"""Build data source configuration from typed source config.

Args:
Expand Down Expand Up @@ -2002,7 +2058,7 @@ def _batch_transform_creation_spec(
index_id: str,
name: str,
enable_web_search_grounding: bool,
output_columns: list[BatchTransformOutputColumn],
output_columns: List[BatchTransformOutputColumn],
storage_bucket_folder_path_prefix: str | None,
target_file_name: str | None,
prompt: str,
Expand Down Expand Up @@ -2052,7 +2108,7 @@ def _batch_transform_ephemeral_creation_spec(
index_id: str | None,
name: str,
enable_web_search_grounding: bool,
output_columns: list[BatchTransformOutputColumn],
output_columns: List[BatchTransformOutputColumn],
storage_bucket_folder_path_prefix: str | None,
prompt: str,
) -> RequestSpec:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,153 @@ async def test_retrieve_async(
== f"UiPath.Python.Sdk/UiPath.Python.Sdk.Activities.ContextGroundingService.retrieve_async/{version}"
)

def test_list(
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?$expand=dataSource",
status_code=200,
json={
"value": [
{
"id": "index-id-1",
"name": "index-one",
"lastIngestionStatus": "Completed",
},
{
"id": "index-id-2",
"name": "index-two",
"lastIngestionStatus": "Queued",
},
]
},
)

indexes = service.list()

assert isinstance(indexes, list)
assert len(indexes) == 2
assert all(isinstance(i, ContextGroundingIndex) for i in indexes)
assert indexes[0].id == "index-id-1"
assert indexes[0].name == "index-one"
assert indexes[1].id == "index-id-2"
assert indexes[1].name == "index-two"

sent_requests = httpx_mock.get_requests()
assert sent_requests[1].method == "GET"
assert (
sent_requests[1].url
== f"{base_url}{org}{tenant}/ecs_/v2/indexes?%24expand=dataSource"
)
assert HEADER_USER_AGENT in sent_requests[1].headers
assert (
sent_requests[1].headers[HEADER_USER_AGENT]
== f"UiPath.Python.Sdk/UiPath.Python.Sdk.Activities.ContextGroundingService.list/{version}"
)

@pytest.mark.anyio
async def test_list_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?$expand=dataSource",
status_code=200,
json={
"value": [
{
"id": "index-id-1",
"name": "index-one",
"lastIngestionStatus": "Completed",
},
]
},
)

indexes = await service.list_async()

assert isinstance(indexes, list)
assert len(indexes) == 1
assert isinstance(indexes[0], ContextGroundingIndex)
assert indexes[0].id == "index-id-1"

sent_requests = httpx_mock.get_requests()
assert sent_requests[1].method == "GET"
assert (
sent_requests[1].url
== f"{base_url}{org}{tenant}/ecs_/v2/indexes?%24expand=dataSource"
)
assert HEADER_USER_AGENT in sent_requests[1].headers
assert (
sent_requests[1].headers[HEADER_USER_AGENT]
== f"UiPath.Python.Sdk/UiPath.Python.Sdk.Activities.ContextGroundingService.list_async/{version}"
)

def test_list_empty(
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?$expand=dataSource",
status_code=200,
json={"value": []},
)

indexes = service.list()

assert indexes == []

def test_retrieve_across_folders(
self,
httpx_mock: HTTPXMock,
Expand Down
4 changes: 2 additions & 2 deletions packages/uipath-platform/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/uipath/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "uipath"
version = "2.10.35"
version = "2.10.36"
description = "Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools."
readme = { file = "README.md", content-type = "text/markdown" }
requires-python = ">=3.11"
Expand Down
6 changes: 5 additions & 1 deletion packages/uipath/src/uipath/_cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"debug": "cli_debug",
"assets": "services.cli_assets",
"buckets": "services.cli_buckets",
"context-grounding": "services.cli_context_grounding",
}

_RUNTIME_COMMANDS = {"init", "dev", "run", "eval", "debug", "server"}
Expand Down Expand Up @@ -78,7 +79,10 @@ def _load_command(name: str):

module_name = _LAZY_COMMANDS[name]
mod = __import__(f"uipath._cli.{module_name}", fromlist=[name])
return getattr(mod, name)
# CLI names may use hyphens (e.g. "context-grounding") but Python
# attribute names use underscores; convert before getattr.
attr_name = name.replace("-", "_")
return getattr(mod, attr_name)


def __getattr__(name: str):
Expand Down
5 changes: 3 additions & 2 deletions packages/uipath/src/uipath/_cli/services/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@

from .cli_assets import assets
from .cli_buckets import buckets
from .cli_context_grounding import context_grounding

__all__ = ["assets", "buckets", "register_service_commands"]
__all__ = ["assets", "buckets", "context_grounding", "register_service_commands"]


def register_service_commands(cli_group):
Expand All @@ -31,7 +32,7 @@ def register_service_commands(cli_group):
Industry Precedent:
AWS CLI, Azure CLI, and gcloud all use explicit registration.
"""
services = [assets, buckets]
services = [assets, buckets, context_grounding]

for service in services:
cli_group.add_command(service)
Expand Down
Loading
Loading