Skip to content
Merged
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 pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "uipath"
version = "2.0.6"
version = "2.0.7"
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.10"
Expand Down
11 changes: 3 additions & 8 deletions src/uipath/_folder_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,12 @@ def folder_headers(self) -> dict[str, str]:

Returns:
dict[str, str]: A dictionary containing the appropriate folder
header (either folder key or folder path).

Raises:
ValueError: If neither folder key nor folder path is set in
the environment.
header (either folder key or folder path). If no folder header is
set as environment variable, the function returns an empty dictionary.
"""
if self._folder_key is not None:
return {HEADER_FOLDER_KEY: self._folder_key}
elif self._folder_path is not None:
return {HEADER_FOLDER_PATH: self._folder_path}
else:
raise ValueError(
f"Folder key or path is not set ({ENV_FOLDER_KEY} or {ENV_FOLDER_PATH})"
)
return {}
125 changes: 97 additions & 28 deletions src/uipath/_services/actions_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,24 @@
from .._execution_context import ExecutionContext
from .._folder_context import FolderContext
from .._utils import Endpoint, RequestSpec
from .._utils.constants import ENV_TENANT_ID, HEADER_TENANT_ID
from .._utils.constants import (
ENV_TENANT_ID,
HEADER_FOLDER_KEY,
HEADER_FOLDER_PATH,
HEADER_TENANT_ID,
)
from ..models import Action, ActionSchema
from ._base_service import BaseService


def _create_spec(
title: str,
data: Optional[Dict[str, Any]],
action_schema: Optional[ActionSchema],
title: str,
app_key: str = "",
app_version: int = -1,
app_folder_key: str = "",
app_folder_path: str = "",
) -> RequestSpec:
field_list = []
outcome_list = []
Expand Down Expand Up @@ -97,14 +104,18 @@ def _create_spec(
else {},
}
),
headers=folder_headers(app_folder_key, app_folder_path),
)


def _retrieve_action_spec(action_key: str) -> RequestSpec:
def _retrieve_action_spec(
action_key: str, app_folder_key: str, app_folder_path: str
) -> RequestSpec:
return RequestSpec(
method="GET",
endpoint=Endpoint("/orchestrator_/tasks/GenericTasks/GetTaskDataByKey"),
params={"taskKey": action_key},
headers=folder_headers(app_folder_key, app_folder_path),
)


Expand Down Expand Up @@ -132,6 +143,15 @@ def _retrieve_app_key_spec(app_name: str) -> RequestSpec:
)


def folder_headers(app_folder_key: str, app_folder_path: str) -> Dict[str, str]:
headers = {}
if app_folder_key:
headers[HEADER_FOLDER_KEY] = app_folder_key
elif app_folder_path:
headers[HEADER_FOLDER_PATH] = app_folder_path
return headers


class ActionsService(FolderContext, BaseService):
"""Service for managing UiPath Actions.

Expand Down Expand Up @@ -162,6 +182,8 @@ async def create_async(
*,
app_name: str = "",
app_key: str = "",
app_folder_path: str = "",
app_folder_key: str = "",
app_version: int = -1,
assignee: str = "",
) -> Action:
Expand All @@ -175,6 +197,8 @@ async def create_async(
data: Optional dictionary containing input data for the action
app_name: The name of the application (if creating an app-specific action)
app_key: The key of the application (if creating an app-specific action)
app_folder_path: Optional folder path for the action
app_folder_key: Optional folder key for the action
app_version: The version of the application
assignee: Optional username or email to assign the task to

Expand All @@ -195,10 +219,12 @@ async def create_async(
app_key=key,
app_version=app_version,
action_schema=action_schema,
app_folder_key=app_folder_key,
app_folder_path=app_folder_path,
)

response = await self.request_async(
spec.method, spec.endpoint, content=spec.content
spec.method, spec.endpoint, content=spec.content, headers=spec.headers
)
json_response = response.json()
if assignee:
Expand All @@ -213,6 +239,8 @@ def create(
*,
app_name: str = "",
app_key: str = "",
app_folder_path: str = "",
app_folder_key: str = "",
app_version: int = -1,
assignee: str = "",
) -> Action:
Expand All @@ -226,6 +254,8 @@ def create(
data: Optional dictionary containing input data for the action
app_name: The name of the application (if creating an app-specific action)
app_key: The key of the application (if creating an app-specific action)
app_folder_path: Optional folder path for the action
app_folder_key: Optional folder key for the action
app_version: The version of the application
assignee: Optional username or email to assign the task to

Expand All @@ -244,48 +274,63 @@ def create(
app_key=key,
app_version=app_version,
action_schema=action_schema,
app_folder_key=app_folder_key,
app_folder_path=app_folder_path,
)

response = self.request(spec.method, spec.endpoint, content=spec.content)
response = self.request(
spec.method, spec.endpoint, content=spec.content, headers=spec.headers
)
json_response = response.json()
if assignee:
spec = _assign_task_spec(json_response["id"], assignee)
print(spec)
self.request(spec.method, spec.endpoint, content=spec.content)
return Action.model_validate(json_response)

def retrieve(
self,
action_key: str,
self, action_key: str, app_folder_path: str = "", app_folder_key: str = ""
) -> Action:
"""Retrieves an action by its key synchronously.

Args:
action_key: The unique identifier of the action to retrieve
app_folder_path: Optional folder path for the action
app_folder_key: Optional folder key for the action

Returns:
Action: The retrieved action object
"""
spec = _retrieve_action_spec(action_key=action_key)
response = self.request(spec.method, spec.endpoint, params=spec.params)
spec = _retrieve_action_spec(
action_key=action_key,
app_folder_key=app_folder_key,
app_folder_path=app_folder_path,
)
response = self.request(
spec.method, spec.endpoint, params=spec.params, headers=spec.headers
)

return Action.model_validate(response.json())

async def retrieve_async(
self,
action_key: str,
self, action_key: str, app_folder_path: str = "", app_folder_key: str = ""
) -> Action:
"""Retrieves an action by its key asynchronously.

Args:
action_key: The unique identifier of the action to retrieve
app_folder_path: Optional folder path for the action
app_folder_key: Optional folder key for the action

Returns:
Action: The retrieved action object
"""
spec = _retrieve_action_spec(action_key=action_key)
spec = _retrieve_action_spec(
action_key=action_key,
app_folder_key=app_folder_key,
app_folder_path=app_folder_path,
)
response = await self.request_async(
spec.method, spec.endpoint, params=spec.params
spec.method, spec.endpoint, params=spec.params, headers=spec.headers
)

return Action.model_validate(response.json())
Expand All @@ -311,8 +356,25 @@ async def __get_app_key_and_schema_async(
response = await self.request_org_scope_async(
spec.method, spec.endpoint, params=spec.params, headers=spec.headers
)
deployed_app = response.json()["deployed"][0]
return (deployed_app["systemName"], deployed_app["actionSchema"])
try:
deployed_app = response.json()["deployed"][0]
action_schema = deployed_app["actionSchema"]
deployed_app_key = deployed_app["systemName"]
except (KeyError, IndexError):
raise Exception("Action app not found") from None
try:
return (
deployed_app_key,
ActionSchema(
key=action_schema["key"],
in_outs=action_schema["inOuts"],
inputs=action_schema["inputs"],
outputs=action_schema["outputs"],
outcomes=action_schema["outcomes"],
),
)
except KeyError:
raise Exception("Failed to deserialize action schema") from KeyError

def __get_app_key_and_schema(
self, app_name: str
Expand All @@ -326,18 +388,25 @@ def __get_app_key_and_schema(
spec.method, spec.endpoint, params=spec.params, headers=spec.headers
)

deployed_app = response.json()["deployed"][0]
action_schema = deployed_app["actionSchema"]
return (
deployed_app["systemName"],
ActionSchema(
key=action_schema["key"],
in_outs=action_schema["inOuts"],
inputs=action_schema["inputs"],
outputs=action_schema["outputs"],
outcomes=action_schema["outcomes"],
),
)
try:
deployed_app = response.json()["deployed"][0]
action_schema = deployed_app["actionSchema"]
deployed_app_key = deployed_app["systemName"]
except (KeyError, IndexError):
raise Exception("Action app not found") from None
try:
return (
deployed_app_key,
ActionSchema(
key=action_schema["key"],
in_outs=action_schema["inOuts"],
inputs=action_schema["inputs"],
outputs=action_schema["outputs"],
outcomes=action_schema["outcomes"],
),
)
except KeyError:
raise Exception("Failed to deserialize action schema") from KeyError

@property
def custom_headers(self) -> Dict[str, str]:
Expand Down
5 changes: 4 additions & 1 deletion src/uipath/_services/context_grounding_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from .._utils import Endpoint, RequestSpec
from .._utils.constants import (
HEADER_FOLDER_KEY,
HEADER_FOLDER_PATH,
ORCHESTRATOR_STORAGE_BUCKET_DATA_SOURCE,
)
from ..models import IngestionInProgressException
Expand Down Expand Up @@ -326,7 +327,9 @@ def custom_headers(self) -> Dict[str, str]:
)

if self._folder_key is None:
raise ValueError(f"Folder key is not set ({HEADER_FOLDER_KEY})")
raise ValueError(
f"Neither the folder key nor the folder path is set ({HEADER_FOLDER_KEY}, {HEADER_FOLDER_PATH})"
)

return self.folder_headers

Expand Down
8 changes: 5 additions & 3 deletions src/uipath/models/interrupt_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ class WaitJob(BaseModel):


class CreateAction(BaseModel):
name: Optional[str] = None
key: Optional[str] = None
title: str
data: Optional[Dict[str, Any]] = None
app_version: Optional[int] = 1
assignee: Optional[str] = ""
app_name: Optional[str] = None
app_folder_path: Optional[str] = None
app_folder_key: Optional[str] = None
app_key: Optional[str] = None
app_version: Optional[int] = 1


class WaitAction(BaseModel):
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

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