From 8482ff4a759e2cf7d5636b431c161a82948a00fe Mon Sep 17 00:00:00 2001 From: Stanislav Novosad Date: Thu, 6 Nov 2025 11:26:37 -0700 Subject: [PATCH] Regenerate Fern Python SDK (#3928) --- skyvern/client/__init__.py | 52 +- skyvern/client/client.py | 84 +- skyvern/client/raw_client.py | 123 +-- skyvern/client/types/__init__.py | 52 +- skyvern/client/types/act_action.py | 32 + skyvern/client/types/act_action_data.py | 5 + skyvern/client/types/action.py | 2 + skyvern/client/types/click_action.py | 4 + skyvern/client/types/click_context.py | 20 + skyvern/client/types/extract_action.py | 4 + skyvern/client/types/folder.py | 42 + skyvern/client/types/input_text_action.py | 4 + .../types/run_sdk_action_request_action.py | 131 +++ .../client/types/run_sdk_action_response.py | 7 +- skyvern/client/types/select_option_action.py | 4 + skyvern/client/types/workflow.py | 2 + skyvern/client/types/workflow_run_response.py | 5 - skyvern/client/types/workflow_status.py | 4 +- skyvern/client/workflows/__init__.py | 4 + skyvern/client/workflows/client.py | 596 ++++++++++++ skyvern/client/workflows/raw_client.py | 909 ++++++++++++++++++ skyvern/library/skyvern_browser_page_ai.py | 2 +- 22 files changed, 1918 insertions(+), 170 deletions(-) create mode 100644 skyvern/client/types/act_action.py create mode 100644 skyvern/client/types/act_action_data.py create mode 100644 skyvern/client/types/click_context.py create mode 100644 skyvern/client/types/folder.py create mode 100644 skyvern/client/types/run_sdk_action_request_action.py create mode 100644 skyvern/client/workflows/__init__.py create mode 100644 skyvern/client/workflows/client.py create mode 100644 skyvern/client/workflows/raw_client.py diff --git a/skyvern/client/__init__.py b/skyvern/client/__init__.py index 626bf670..66e38fbc 100644 --- a/skyvern/client/__init__.py +++ b/skyvern/client/__init__.py @@ -8,6 +8,7 @@ from importlib import import_module if typing.TYPE_CHECKING: from .types import ( ActAction, + ActActionData, Action, ActionBlock, ActionBlockDataSchema, @@ -43,6 +44,7 @@ if typing.TYPE_CHECKING: BrowserSessionResponse, ClickAction, ClickActionData, + ClickContext, CodeBlock, CodeBlockParametersItem, CodeBlockParametersItem_AwsSecret, @@ -125,6 +127,7 @@ if typing.TYPE_CHECKING: FileType, FileUploadBlock, FileUploadBlockYaml, + Folder, ForLoopBlock, ForLoopBlockLoopBlocksItem, ForLoopBlockLoopBlocksItem_Action, @@ -265,18 +268,17 @@ if typing.TYPE_CHECKING: PdfParserBlockYaml, ProxyLocation, RunEngine, + RunSdkActionRequestAction, + RunSdkActionRequestAction_AiAct, + RunSdkActionRequestAction_AiClick, + RunSdkActionRequestAction_AiInputText, + RunSdkActionRequestAction_AiSelectOption, + RunSdkActionRequestAction_Extract, RunSdkActionResponse, - RunSdkActionResponseResult, RunStatus, Script, ScriptFileCreate, ScriptRunResponse, - SdkAction, - SdkAction_AiAct, - SdkAction_AiClick, - SdkAction_AiInputText, - SdkAction_AiSelectOption, - SdkAction_Extract, SelectOption, SelectOptionAction, SelectOptionActionData, @@ -463,12 +465,13 @@ if typing.TYPE_CHECKING: WorkflowStatus, ) from .errors import BadRequestError, ForbiddenError, NotFoundError, UnprocessableEntityError - from . import scripts + from . import scripts, workflows from .client import AsyncSkyvern, Skyvern from .environment import SkyvernEnvironment from .version import __version__ _dynamic_imports: typing.Dict[str, str] = { "ActAction": ".types", + "ActActionData": ".types", "Action": ".types", "ActionBlock": ".types", "ActionBlockDataSchema": ".types", @@ -506,6 +509,7 @@ _dynamic_imports: typing.Dict[str, str] = { "BrowserSessionResponse": ".types", "ClickAction": ".types", "ClickActionData": ".types", + "ClickContext": ".types", "CodeBlock": ".types", "CodeBlockParametersItem": ".types", "CodeBlockParametersItem_AwsSecret": ".types", @@ -588,6 +592,7 @@ _dynamic_imports: typing.Dict[str, str] = { "FileType": ".types", "FileUploadBlock": ".types", "FileUploadBlockYaml": ".types", + "Folder": ".types", "ForLoopBlock": ".types", "ForLoopBlockLoopBlocksItem": ".types", "ForLoopBlockLoopBlocksItem_Action": ".types", @@ -730,18 +735,17 @@ _dynamic_imports: typing.Dict[str, str] = { "PdfParserBlockYaml": ".types", "ProxyLocation": ".types", "RunEngine": ".types", + "RunSdkActionRequestAction": ".types", + "RunSdkActionRequestAction_AiAct": ".types", + "RunSdkActionRequestAction_AiClick": ".types", + "RunSdkActionRequestAction_AiInputText": ".types", + "RunSdkActionRequestAction_AiSelectOption": ".types", + "RunSdkActionRequestAction_Extract": ".types", "RunSdkActionResponse": ".types", - "RunSdkActionResponseResult": ".types", "RunStatus": ".types", "Script": ".types", "ScriptFileCreate": ".types", "ScriptRunResponse": ".types", - "SdkAction": ".types", - "SdkAction_AiAct": ".types", - "SdkAction_AiClick": ".types", - "SdkAction_AiInputText": ".types", - "SdkAction_AiSelectOption": ".types", - "SdkAction_Extract": ".types", "SelectOption": ".types", "SelectOptionAction": ".types", "SelectOptionActionData": ".types", @@ -931,6 +935,7 @@ _dynamic_imports: typing.Dict[str, str] = { "WorkflowStatus": ".types", "__version__": ".version", "scripts": ".scripts", + "workflows": ".workflows", } @@ -957,6 +962,7 @@ def __dir__(): __all__ = [ "ActAction", + "ActActionData", "Action", "ActionBlock", "ActionBlockDataSchema", @@ -994,6 +1000,7 @@ __all__ = [ "BrowserSessionResponse", "ClickAction", "ClickActionData", + "ClickContext", "CodeBlock", "CodeBlockParametersItem", "CodeBlockParametersItem_AwsSecret", @@ -1076,6 +1083,7 @@ __all__ = [ "FileType", "FileUploadBlock", "FileUploadBlockYaml", + "Folder", "ForLoopBlock", "ForLoopBlockLoopBlocksItem", "ForLoopBlockLoopBlocksItem_Action", @@ -1218,18 +1226,17 @@ __all__ = [ "PdfParserBlockYaml", "ProxyLocation", "RunEngine", + "RunSdkActionRequestAction", + "RunSdkActionRequestAction_AiAct", + "RunSdkActionRequestAction_AiClick", + "RunSdkActionRequestAction_AiInputText", + "RunSdkActionRequestAction_AiSelectOption", + "RunSdkActionRequestAction_Extract", "RunSdkActionResponse", - "RunSdkActionResponseResult", "RunStatus", "Script", "ScriptFileCreate", "ScriptRunResponse", - "SdkAction", - "SdkAction_AiAct", - "SdkAction_AiClick", - "SdkAction_AiInputText", - "SdkAction_AiSelectOption", - "SdkAction_Extract", "SelectOption", "SelectOptionAction", "SelectOptionActionData", @@ -1419,4 +1426,5 @@ __all__ = [ "WorkflowStatus", "__version__", "scripts", + "workflows", ] diff --git a/skyvern/client/client.py b/skyvern/client/client.py index 4798ffbb..2cb9de05 100644 --- a/skyvern/client/client.py +++ b/skyvern/client/client.py @@ -19,10 +19,10 @@ from .types.credential_response import CredentialResponse from .types.get_run_response import GetRunResponse from .types.proxy_location import ProxyLocation from .types.run_engine import RunEngine +from .types.run_sdk_action_request_action import RunSdkActionRequestAction from .types.run_sdk_action_response import RunSdkActionResponse from .types.script import Script from .types.script_file_create import ScriptFileCreate -from .types.sdk_action import SdkAction from .types.skyvern_forge_sdk_schemas_credentials_credential_type import SkyvernForgeSdkSchemasCredentialsCredentialType from .types.skyvern_schemas_run_blocks_credential_type import SkyvernSchemasRunBlocksCredentialType from .types.task_run_request_data_extraction_schema import TaskRunRequestDataExtractionSchema @@ -32,9 +32,11 @@ from .types.workflow import Workflow from .types.workflow_create_yaml_request import WorkflowCreateYamlRequest from .types.workflow_run_response import WorkflowRunResponse from .types.workflow_run_timeline import WorkflowRunTimeline +from .types.workflow_status import WorkflowStatus if typing.TYPE_CHECKING: from .scripts.client import AsyncScriptsClient, ScriptsClient + from .workflows.client import AsyncWorkflowsClient, WorkflowsClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -105,6 +107,7 @@ class Skyvern: timeout=_defaulted_timeout, ) self._raw_client = RawSkyvern(client_wrapper=self._client_wrapper) + self._workflows: typing.Optional[WorkflowsClient] = None self._scripts: typing.Optional[ScriptsClient] = None @property @@ -491,6 +494,8 @@ class Skyvern: only_workflows: typing.Optional[bool] = None, search_key: typing.Optional[str] = None, title: typing.Optional[str] = None, + folder_id: typing.Optional[str] = None, + status: typing.Optional[typing.Union[WorkflowStatus, typing.Sequence[WorkflowStatus]]] = None, template: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, ) -> typing.List[Workflow]: @@ -498,8 +503,8 @@ class Skyvern: Get all workflows with the latest version for the organization. Search semantics: - - If `search_key` is provided, its value is used as a unified search term for both - `workflows.title` and workflow parameter metadata (key, description, and default_value for + - If `search_key` is provided, its value is used as a unified search term for + `workflows.title`, `folders.title`, and workflow parameter metadata (key, description, and default_value for `WorkflowParameterModel`). - Falls back to deprecated `title` (title-only search) if `search_key` is not provided. - Parameter metadata search excludes soft-deleted parameter rows across all parameter tables. @@ -515,11 +520,16 @@ class Skyvern: only_workflows : typing.Optional[bool] search_key : typing.Optional[str] - Unified search across workflow title and parameter metadata (key, description, default_value). + Unified search across workflow title, folder name, and parameter metadata (key, description, default_value). title : typing.Optional[str] Deprecated: use search_key instead. + folder_id : typing.Optional[str] + Filter workflows by folder ID + + status : typing.Optional[typing.Union[WorkflowStatus, typing.Sequence[WorkflowStatus]]] + template : typing.Optional[bool] request_options : typing.Optional[RequestOptions] @@ -544,6 +554,7 @@ class Skyvern: only_workflows=True, search_key="search_key", title="title", + folder_id="folder_id", template=True, ) """ @@ -554,6 +565,8 @@ class Skyvern: only_workflows=only_workflows, search_key=search_key, title=title, + folder_id=folder_id, + status=status, template=template, request_options=request_options, ) @@ -1500,8 +1513,7 @@ class Skyvern: self, *, url: str, - action: SdkAction, - user_agent: typing.Optional[str] = None, + action: RunSdkActionRequestAction, browser_session_id: typing.Optional[str] = OMIT, browser_address: typing.Optional[str] = OMIT, workflow_run_id: typing.Optional[str] = OMIT, @@ -1515,11 +1527,9 @@ class Skyvern: url : str The URL where the action should be executed - action : SdkAction + action : RunSdkActionRequestAction The action to execute with its specific parameters - user_agent : typing.Optional[str] - browser_session_id : typing.Optional[str] The browser session ID @@ -1535,25 +1545,23 @@ class Skyvern: Returns ------- RunSdkActionResponse - Successfully executed SDK action + Successful Response Examples -------- - from skyvern import SdkAction_AiClick, Skyvern + from skyvern import RunSdkActionRequestAction_AiAct, Skyvern client = Skyvern( api_key="YOUR_API_KEY", ) client.run_sdk_action( - user_agent="x-user-agent", url="url", - action=SdkAction_AiClick(), + action=RunSdkActionRequestAction_AiAct(), ) """ _response = self._raw_client.run_sdk_action( url=url, action=action, - user_agent=user_agent, browser_session_id=browser_session_id, browser_address=browser_address, workflow_run_id=workflow_run_id, @@ -1561,6 +1569,14 @@ class Skyvern: ) return _response.data + @property + def workflows(self): + if self._workflows is None: + from .workflows.client import WorkflowsClient # noqa: E402 + + self._workflows = WorkflowsClient(client_wrapper=self._client_wrapper) + return self._workflows + @property def scripts(self): if self._scripts is None: @@ -1636,6 +1652,7 @@ class AsyncSkyvern: timeout=_defaulted_timeout, ) self._raw_client = AsyncRawSkyvern(client_wrapper=self._client_wrapper) + self._workflows: typing.Optional[AsyncWorkflowsClient] = None self._scripts: typing.Optional[AsyncScriptsClient] = None @property @@ -2054,6 +2071,8 @@ class AsyncSkyvern: only_workflows: typing.Optional[bool] = None, search_key: typing.Optional[str] = None, title: typing.Optional[str] = None, + folder_id: typing.Optional[str] = None, + status: typing.Optional[typing.Union[WorkflowStatus, typing.Sequence[WorkflowStatus]]] = None, template: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, ) -> typing.List[Workflow]: @@ -2061,8 +2080,8 @@ class AsyncSkyvern: Get all workflows with the latest version for the organization. Search semantics: - - If `search_key` is provided, its value is used as a unified search term for both - `workflows.title` and workflow parameter metadata (key, description, and default_value for + - If `search_key` is provided, its value is used as a unified search term for + `workflows.title`, `folders.title`, and workflow parameter metadata (key, description, and default_value for `WorkflowParameterModel`). - Falls back to deprecated `title` (title-only search) if `search_key` is not provided. - Parameter metadata search excludes soft-deleted parameter rows across all parameter tables. @@ -2078,11 +2097,16 @@ class AsyncSkyvern: only_workflows : typing.Optional[bool] search_key : typing.Optional[str] - Unified search across workflow title and parameter metadata (key, description, default_value). + Unified search across workflow title, folder name, and parameter metadata (key, description, default_value). title : typing.Optional[str] Deprecated: use search_key instead. + folder_id : typing.Optional[str] + Filter workflows by folder ID + + status : typing.Optional[typing.Union[WorkflowStatus, typing.Sequence[WorkflowStatus]]] + template : typing.Optional[bool] request_options : typing.Optional[RequestOptions] @@ -2112,6 +2136,7 @@ class AsyncSkyvern: only_workflows=True, search_key="search_key", title="title", + folder_id="folder_id", template=True, ) @@ -2125,6 +2150,8 @@ class AsyncSkyvern: only_workflows=only_workflows, search_key=search_key, title=title, + folder_id=folder_id, + status=status, template=template, request_options=request_options, ) @@ -3245,8 +3272,7 @@ class AsyncSkyvern: self, *, url: str, - action: SdkAction, - user_agent: typing.Optional[str] = None, + action: RunSdkActionRequestAction, browser_session_id: typing.Optional[str] = OMIT, browser_address: typing.Optional[str] = OMIT, workflow_run_id: typing.Optional[str] = OMIT, @@ -3260,11 +3286,9 @@ class AsyncSkyvern: url : str The URL where the action should be executed - action : SdkAction + action : RunSdkActionRequestAction The action to execute with its specific parameters - user_agent : typing.Optional[str] - browser_session_id : typing.Optional[str] The browser session ID @@ -3280,13 +3304,13 @@ class AsyncSkyvern: Returns ------- RunSdkActionResponse - Successfully executed SDK action + Successful Response Examples -------- import asyncio - from skyvern import AsyncSkyvern, SdkAction_AiClick + from skyvern import AsyncSkyvern, RunSdkActionRequestAction_AiAct client = AsyncSkyvern( api_key="YOUR_API_KEY", @@ -3295,9 +3319,8 @@ class AsyncSkyvern: async def main() -> None: await client.run_sdk_action( - user_agent="x-user-agent", url="url", - action=SdkAction_AiClick(), + action=RunSdkActionRequestAction_AiAct(), ) @@ -3306,7 +3329,6 @@ class AsyncSkyvern: _response = await self._raw_client.run_sdk_action( url=url, action=action, - user_agent=user_agent, browser_session_id=browser_session_id, browser_address=browser_address, workflow_run_id=workflow_run_id, @@ -3314,6 +3336,14 @@ class AsyncSkyvern: ) return _response.data + @property + def workflows(self): + if self._workflows is None: + from .workflows.client import AsyncWorkflowsClient # noqa: E402 + + self._workflows = AsyncWorkflowsClient(client_wrapper=self._client_wrapper) + return self._workflows + @property def scripts(self): if self._scripts is None: diff --git a/skyvern/client/raw_client.py b/skyvern/client/raw_client.py index 87193ec5..600097a2 100644 --- a/skyvern/client/raw_client.py +++ b/skyvern/client/raw_client.py @@ -24,10 +24,10 @@ from .types.credential_response import CredentialResponse from .types.get_run_response import GetRunResponse from .types.proxy_location import ProxyLocation from .types.run_engine import RunEngine +from .types.run_sdk_action_request_action import RunSdkActionRequestAction from .types.run_sdk_action_response import RunSdkActionResponse from .types.script import Script from .types.script_file_create import ScriptFileCreate -from .types.sdk_action import SdkAction from .types.skyvern_forge_sdk_schemas_credentials_credential_type import SkyvernForgeSdkSchemasCredentialsCredentialType from .types.skyvern_schemas_run_blocks_credential_type import SkyvernSchemasRunBlocksCredentialType from .types.task_run_request_data_extraction_schema import TaskRunRequestDataExtractionSchema @@ -37,6 +37,7 @@ from .types.workflow import Workflow from .types.workflow_create_yaml_request import WorkflowCreateYamlRequest from .types.workflow_run_response import WorkflowRunResponse from .types.workflow_run_timeline import WorkflowRunTimeline +from .types.workflow_status import WorkflowStatus # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -532,6 +533,8 @@ class RawSkyvern: only_workflows: typing.Optional[bool] = None, search_key: typing.Optional[str] = None, title: typing.Optional[str] = None, + folder_id: typing.Optional[str] = None, + status: typing.Optional[typing.Union[WorkflowStatus, typing.Sequence[WorkflowStatus]]] = None, template: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[typing.List[Workflow]]: @@ -539,8 +542,8 @@ class RawSkyvern: Get all workflows with the latest version for the organization. Search semantics: - - If `search_key` is provided, its value is used as a unified search term for both - `workflows.title` and workflow parameter metadata (key, description, and default_value for + - If `search_key` is provided, its value is used as a unified search term for + `workflows.title`, `folders.title`, and workflow parameter metadata (key, description, and default_value for `WorkflowParameterModel`). - Falls back to deprecated `title` (title-only search) if `search_key` is not provided. - Parameter metadata search excludes soft-deleted parameter rows across all parameter tables. @@ -556,11 +559,16 @@ class RawSkyvern: only_workflows : typing.Optional[bool] search_key : typing.Optional[str] - Unified search across workflow title and parameter metadata (key, description, default_value). + Unified search across workflow title, folder name, and parameter metadata (key, description, default_value). title : typing.Optional[str] Deprecated: use search_key instead. + folder_id : typing.Optional[str] + Filter workflows by folder ID + + status : typing.Optional[typing.Union[WorkflowStatus, typing.Sequence[WorkflowStatus]]] + template : typing.Optional[bool] request_options : typing.Optional[RequestOptions] @@ -581,6 +589,8 @@ class RawSkyvern: "only_workflows": only_workflows, "search_key": search_key, "title": title, + "folder_id": folder_id, + "status": status, "template": template, }, request_options=request_options, @@ -2058,8 +2068,7 @@ class RawSkyvern: self, *, url: str, - action: SdkAction, - user_agent: typing.Optional[str] = None, + action: RunSdkActionRequestAction, browser_session_id: typing.Optional[str] = OMIT, browser_address: typing.Optional[str] = OMIT, workflow_run_id: typing.Optional[str] = OMIT, @@ -2073,11 +2082,9 @@ class RawSkyvern: url : str The URL where the action should be executed - action : SdkAction + action : RunSdkActionRequestAction The action to execute with its specific parameters - user_agent : typing.Optional[str] - browser_session_id : typing.Optional[str] The browser session ID @@ -2093,7 +2100,7 @@ class RawSkyvern: Returns ------- HttpResponse[RunSdkActionResponse] - Successfully executed SDK action + Successful Response """ _response = self._client_wrapper.httpx_client.request( "v1/sdk/run_action", @@ -2104,12 +2111,11 @@ class RawSkyvern: "browser_address": browser_address, "workflow_run_id": workflow_run_id, "action": convert_and_respect_annotation_metadata( - object_=action, annotation=SdkAction, direction="write" + object_=action, annotation=RunSdkActionRequestAction, direction="write" ), }, headers={ "content-type": "application/json", - "x-user-agent": str(user_agent) if user_agent is not None else None, }, request_options=request_options, omit=OMIT, @@ -2124,39 +2130,6 @@ class RawSkyvern: ), ) return HttpResponse(response=_response, data=_data) - if _response.status_code == 400: - raise BadRequestError( - headers=dict(_response.headers), - body=typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ), - ) - if _response.status_code == 403: - raise ForbiddenError( - headers=dict(_response.headers), - body=typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ), - ) - if _response.status_code == 404: - raise NotFoundError( - headers=dict(_response.headers), - body=typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ), - ) if _response.status_code == 422: raise UnprocessableEntityError( headers=dict(_response.headers), @@ -2664,6 +2637,8 @@ class AsyncRawSkyvern: only_workflows: typing.Optional[bool] = None, search_key: typing.Optional[str] = None, title: typing.Optional[str] = None, + folder_id: typing.Optional[str] = None, + status: typing.Optional[typing.Union[WorkflowStatus, typing.Sequence[WorkflowStatus]]] = None, template: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[typing.List[Workflow]]: @@ -2671,8 +2646,8 @@ class AsyncRawSkyvern: Get all workflows with the latest version for the organization. Search semantics: - - If `search_key` is provided, its value is used as a unified search term for both - `workflows.title` and workflow parameter metadata (key, description, and default_value for + - If `search_key` is provided, its value is used as a unified search term for + `workflows.title`, `folders.title`, and workflow parameter metadata (key, description, and default_value for `WorkflowParameterModel`). - Falls back to deprecated `title` (title-only search) if `search_key` is not provided. - Parameter metadata search excludes soft-deleted parameter rows across all parameter tables. @@ -2688,11 +2663,16 @@ class AsyncRawSkyvern: only_workflows : typing.Optional[bool] search_key : typing.Optional[str] - Unified search across workflow title and parameter metadata (key, description, default_value). + Unified search across workflow title, folder name, and parameter metadata (key, description, default_value). title : typing.Optional[str] Deprecated: use search_key instead. + folder_id : typing.Optional[str] + Filter workflows by folder ID + + status : typing.Optional[typing.Union[WorkflowStatus, typing.Sequence[WorkflowStatus]]] + template : typing.Optional[bool] request_options : typing.Optional[RequestOptions] @@ -2713,6 +2693,8 @@ class AsyncRawSkyvern: "only_workflows": only_workflows, "search_key": search_key, "title": title, + "folder_id": folder_id, + "status": status, "template": template, }, request_options=request_options, @@ -4190,8 +4172,7 @@ class AsyncRawSkyvern: self, *, url: str, - action: SdkAction, - user_agent: typing.Optional[str] = None, + action: RunSdkActionRequestAction, browser_session_id: typing.Optional[str] = OMIT, browser_address: typing.Optional[str] = OMIT, workflow_run_id: typing.Optional[str] = OMIT, @@ -4205,11 +4186,9 @@ class AsyncRawSkyvern: url : str The URL where the action should be executed - action : SdkAction + action : RunSdkActionRequestAction The action to execute with its specific parameters - user_agent : typing.Optional[str] - browser_session_id : typing.Optional[str] The browser session ID @@ -4225,7 +4204,7 @@ class AsyncRawSkyvern: Returns ------- AsyncHttpResponse[RunSdkActionResponse] - Successfully executed SDK action + Successful Response """ _response = await self._client_wrapper.httpx_client.request( "v1/sdk/run_action", @@ -4236,12 +4215,11 @@ class AsyncRawSkyvern: "browser_address": browser_address, "workflow_run_id": workflow_run_id, "action": convert_and_respect_annotation_metadata( - object_=action, annotation=SdkAction, direction="write" + object_=action, annotation=RunSdkActionRequestAction, direction="write" ), }, headers={ "content-type": "application/json", - "x-user-agent": str(user_agent) if user_agent is not None else None, }, request_options=request_options, omit=OMIT, @@ -4256,39 +4234,6 @@ class AsyncRawSkyvern: ), ) return AsyncHttpResponse(response=_response, data=_data) - if _response.status_code == 400: - raise BadRequestError( - headers=dict(_response.headers), - body=typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ), - ) - if _response.status_code == 403: - raise ForbiddenError( - headers=dict(_response.headers), - body=typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ), - ) - if _response.status_code == 404: - raise NotFoundError( - headers=dict(_response.headers), - body=typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ), - ) if _response.status_code == 422: raise UnprocessableEntityError( headers=dict(_response.headers), diff --git a/skyvern/client/types/__init__.py b/skyvern/client/types/__init__.py index 874c5df0..97f7b0ec 100644 --- a/skyvern/client/types/__init__.py +++ b/skyvern/client/types/__init__.py @@ -7,6 +7,7 @@ from importlib import import_module if typing.TYPE_CHECKING: from .act_action import ActAction + from .act_action_data import ActActionData from .action import Action from .action_block import ActionBlock from .action_block_data_schema import ActionBlockDataSchema @@ -44,6 +45,7 @@ if typing.TYPE_CHECKING: from .browser_session_response import BrowserSessionResponse from .click_action import ClickAction from .click_action_data import ClickActionData + from .click_context import ClickContext from .code_block import CodeBlock from .code_block_parameters_item import ( CodeBlockParametersItem, @@ -134,6 +136,7 @@ if typing.TYPE_CHECKING: from .file_type import FileType from .file_upload_block import FileUploadBlock from .file_upload_block_yaml import FileUploadBlockYaml + from .folder import Folder from .for_loop_block import ForLoopBlock from .for_loop_block_loop_blocks_item import ( ForLoopBlockLoopBlocksItem, @@ -290,20 +293,19 @@ if typing.TYPE_CHECKING: from .pdf_parser_block_yaml import PdfParserBlockYaml from .proxy_location import ProxyLocation from .run_engine import RunEngine + from .run_sdk_action_request_action import ( + RunSdkActionRequestAction, + RunSdkActionRequestAction_AiAct, + RunSdkActionRequestAction_AiClick, + RunSdkActionRequestAction_AiInputText, + RunSdkActionRequestAction_AiSelectOption, + RunSdkActionRequestAction_Extract, + ) from .run_sdk_action_response import RunSdkActionResponse - from .run_sdk_action_response_result import RunSdkActionResponseResult from .run_status import RunStatus from .script import Script from .script_file_create import ScriptFileCreate from .script_run_response import ScriptRunResponse - from .sdk_action import ( - SdkAction, - SdkAction_AiAct, - SdkAction_AiClick, - SdkAction_AiInputText, - SdkAction_AiSelectOption, - SdkAction_Extract, - ) from .select_option import SelectOption from .select_option_action import SelectOptionAction from .select_option_action_data import SelectOptionActionData @@ -508,6 +510,7 @@ if typing.TYPE_CHECKING: from .workflow_status import WorkflowStatus _dynamic_imports: typing.Dict[str, str] = { "ActAction": ".act_action", + "ActActionData": ".act_action_data", "Action": ".action", "ActionBlock": ".action_block", "ActionBlockDataSchema": ".action_block_data_schema", @@ -543,6 +546,7 @@ _dynamic_imports: typing.Dict[str, str] = { "BrowserSessionResponse": ".browser_session_response", "ClickAction": ".click_action", "ClickActionData": ".click_action_data", + "ClickContext": ".click_context", "CodeBlock": ".code_block", "CodeBlockParametersItem": ".code_block_parameters_item", "CodeBlockParametersItem_AwsSecret": ".code_block_parameters_item", @@ -625,6 +629,7 @@ _dynamic_imports: typing.Dict[str, str] = { "FileType": ".file_type", "FileUploadBlock": ".file_upload_block", "FileUploadBlockYaml": ".file_upload_block_yaml", + "Folder": ".folder", "ForLoopBlock": ".for_loop_block", "ForLoopBlockLoopBlocksItem": ".for_loop_block_loop_blocks_item", "ForLoopBlockLoopBlocksItem_Action": ".for_loop_block_loop_blocks_item", @@ -765,18 +770,17 @@ _dynamic_imports: typing.Dict[str, str] = { "PdfParserBlockYaml": ".pdf_parser_block_yaml", "ProxyLocation": ".proxy_location", "RunEngine": ".run_engine", + "RunSdkActionRequestAction": ".run_sdk_action_request_action", + "RunSdkActionRequestAction_AiAct": ".run_sdk_action_request_action", + "RunSdkActionRequestAction_AiClick": ".run_sdk_action_request_action", + "RunSdkActionRequestAction_AiInputText": ".run_sdk_action_request_action", + "RunSdkActionRequestAction_AiSelectOption": ".run_sdk_action_request_action", + "RunSdkActionRequestAction_Extract": ".run_sdk_action_request_action", "RunSdkActionResponse": ".run_sdk_action_response", - "RunSdkActionResponseResult": ".run_sdk_action_response_result", "RunStatus": ".run_status", "Script": ".script", "ScriptFileCreate": ".script_file_create", "ScriptRunResponse": ".script_run_response", - "SdkAction": ".sdk_action", - "SdkAction_AiAct": ".sdk_action", - "SdkAction_AiClick": ".sdk_action", - "SdkAction_AiInputText": ".sdk_action", - "SdkAction_AiSelectOption": ".sdk_action", - "SdkAction_Extract": ".sdk_action", "SelectOption": ".select_option", "SelectOptionAction": ".select_option_action", "SelectOptionActionData": ".select_option_action_data", @@ -987,6 +991,7 @@ def __dir__(): __all__ = [ "ActAction", + "ActActionData", "Action", "ActionBlock", "ActionBlockDataSchema", @@ -1022,6 +1027,7 @@ __all__ = [ "BrowserSessionResponse", "ClickAction", "ClickActionData", + "ClickContext", "CodeBlock", "CodeBlockParametersItem", "CodeBlockParametersItem_AwsSecret", @@ -1104,6 +1110,7 @@ __all__ = [ "FileType", "FileUploadBlock", "FileUploadBlockYaml", + "Folder", "ForLoopBlock", "ForLoopBlockLoopBlocksItem", "ForLoopBlockLoopBlocksItem_Action", @@ -1244,18 +1251,17 @@ __all__ = [ "PdfParserBlockYaml", "ProxyLocation", "RunEngine", + "RunSdkActionRequestAction", + "RunSdkActionRequestAction_AiAct", + "RunSdkActionRequestAction_AiClick", + "RunSdkActionRequestAction_AiInputText", + "RunSdkActionRequestAction_AiSelectOption", + "RunSdkActionRequestAction_Extract", "RunSdkActionResponse", - "RunSdkActionResponseResult", "RunStatus", "Script", "ScriptFileCreate", "ScriptRunResponse", - "SdkAction", - "SdkAction_AiAct", - "SdkAction_AiClick", - "SdkAction_AiInputText", - "SdkAction_AiSelectOption", - "SdkAction_Extract", "SelectOption", "SelectOptionAction", "SelectOptionActionData", diff --git a/skyvern/client/types/act_action.py b/skyvern/client/types/act_action.py new file mode 100644 index 00000000..ada45fe9 --- /dev/null +++ b/skyvern/client/types/act_action.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .act_action_data import ActActionData + + +class ActAction(UniversalBaseModel): + """ + AI act action parameters. + """ + + intention: typing.Optional[str] = pydantic.Field(default=None) + """ + Natural language prompt for the action + """ + + data: typing.Optional[ActActionData] = pydantic.Field(default=None) + """ + Additional context data + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/skyvern/client/types/act_action_data.py b/skyvern/client/types/act_action_data.py new file mode 100644 index 00000000..e68e0e9d --- /dev/null +++ b/skyvern/client/types/act_action_data.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +ActActionData = typing.Union[str, typing.Dict[str, typing.Optional[typing.Any]]] diff --git a/skyvern/client/types/action.py b/skyvern/client/types/action.py index 830cf7eb..23a0efd1 100644 --- a/skyvern/client/types/action.py +++ b/skyvern/client/types/action.py @@ -7,6 +7,7 @@ import pydantic from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .action_status import ActionStatus from .action_type import ActionType +from .click_context import ClickContext from .input_or_select_context import InputOrSelectContext from .select_option import SelectOption from .user_defined_error import UserDefinedError @@ -44,6 +45,7 @@ class Action(UniversalBaseModel): option: typing.Optional[SelectOption] = None is_checked: typing.Optional[bool] = None verified: typing.Optional[bool] = None + click_context: typing.Optional[ClickContext] = None totp_timing_info: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None created_at: typing.Optional[dt.datetime] = None modified_at: typing.Optional[dt.datetime] = None diff --git a/skyvern/client/types/click_action.py b/skyvern/client/types/click_action.py index 5cbcde5b..11d9bd31 100644 --- a/skyvern/client/types/click_action.py +++ b/skyvern/client/types/click_action.py @@ -8,6 +8,10 @@ from .click_action_data import ClickActionData class ClickAction(UniversalBaseModel): + """ + Click action parameters. + """ + selector: typing.Optional[str] = pydantic.Field(default=None) """ CSS selector for the element diff --git a/skyvern/client/types/click_context.py b/skyvern/client/types/click_context.py new file mode 100644 index 00000000..998e7477 --- /dev/null +++ b/skyvern/client/types/click_context.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class ClickContext(UniversalBaseModel): + thought: typing.Optional[str] = None + single_option_click: typing.Optional[bool] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/skyvern/client/types/extract_action.py b/skyvern/client/types/extract_action.py index 7a2730c6..d59479d9 100644 --- a/skyvern/client/types/extract_action.py +++ b/skyvern/client/types/extract_action.py @@ -9,6 +9,10 @@ from .extract_action_extract_schema import ExtractActionExtractSchema class ExtractAction(UniversalBaseModel): + """ + Extract data action parameters. + """ + prompt: typing.Optional[str] = pydantic.Field(default=None) """ Extraction prompt diff --git a/skyvern/client/types/folder.py b/skyvern/client/types/folder.py new file mode 100644 index 00000000..c3e4ae78 --- /dev/null +++ b/skyvern/client/types/folder.py @@ -0,0 +1,42 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class Folder(UniversalBaseModel): + """ + Response model for a folder + """ + + title: str = pydantic.Field() + """ + Folder title + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + Folder description + """ + + folder_id: str + organization_id: str + workflow_count: typing.Optional[int] = pydantic.Field(default=None) + """ + Number of workflows in this folder + """ + + created_at: dt.datetime + modified_at: dt.datetime + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/skyvern/client/types/input_text_action.py b/skyvern/client/types/input_text_action.py index 2effef63..d1394997 100644 --- a/skyvern/client/types/input_text_action.py +++ b/skyvern/client/types/input_text_action.py @@ -8,6 +8,10 @@ from .input_text_action_data import InputTextActionData class InputTextAction(UniversalBaseModel): + """ + Input text action parameters. + """ + selector: typing.Optional[str] = pydantic.Field(default=None) """ CSS selector for the element diff --git a/skyvern/client/types/run_sdk_action_request_action.py b/skyvern/client/types/run_sdk_action_request_action.py new file mode 100644 index 00000000..4b4df74e --- /dev/null +++ b/skyvern/client/types/run_sdk_action_request_action.py @@ -0,0 +1,131 @@ +# This file was auto-generated by Fern from our API Definition. + +from __future__ import annotations + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .act_action_data import ActActionData +from .click_action_data import ClickActionData +from .extract_action_data import ExtractActionData +from .extract_action_extract_schema import ExtractActionExtractSchema +from .input_text_action_data import InputTextActionData +from .select_option_action_data import SelectOptionActionData + + +class RunSdkActionRequestAction_AiAct(UniversalBaseModel): + """ + The action to execute with its specific parameters + """ + + type: typing.Literal["ai_act"] = "ai_act" + intention: typing.Optional[str] = None + data: typing.Optional[ActActionData] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class RunSdkActionRequestAction_AiClick(UniversalBaseModel): + """ + The action to execute with its specific parameters + """ + + type: typing.Literal["ai_click"] = "ai_click" + selector: typing.Optional[str] = None + intention: typing.Optional[str] = None + data: typing.Optional[ClickActionData] = None + timeout: typing.Optional[float] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class RunSdkActionRequestAction_AiInputText(UniversalBaseModel): + """ + The action to execute with its specific parameters + """ + + type: typing.Literal["ai_input_text"] = "ai_input_text" + selector: typing.Optional[str] = None + value: typing.Optional[str] = None + intention: typing.Optional[str] = None + data: typing.Optional[InputTextActionData] = None + totp_identifier: typing.Optional[str] = None + totp_url: typing.Optional[str] = None + timeout: typing.Optional[float] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class RunSdkActionRequestAction_AiSelectOption(UniversalBaseModel): + """ + The action to execute with its specific parameters + """ + + type: typing.Literal["ai_select_option"] = "ai_select_option" + selector: typing.Optional[str] = None + value: typing.Optional[str] = None + intention: typing.Optional[str] = None + data: typing.Optional[SelectOptionActionData] = None + timeout: typing.Optional[float] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class RunSdkActionRequestAction_Extract(UniversalBaseModel): + """ + The action to execute with its specific parameters + """ + + type: typing.Literal["extract"] = "extract" + prompt: typing.Optional[str] = None + extract_schema: typing.Optional[ExtractActionExtractSchema] = None + error_code_mapping: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None + intention: typing.Optional[str] = None + data: typing.Optional[ExtractActionData] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +RunSdkActionRequestAction = typing.Union[ + RunSdkActionRequestAction_AiAct, + RunSdkActionRequestAction_AiClick, + RunSdkActionRequestAction_AiInputText, + RunSdkActionRequestAction_AiSelectOption, + RunSdkActionRequestAction_Extract, +] diff --git a/skyvern/client/types/run_sdk_action_response.py b/skyvern/client/types/run_sdk_action_response.py index 845d393f..ac2ed5af 100644 --- a/skyvern/client/types/run_sdk_action_response.py +++ b/skyvern/client/types/run_sdk_action_response.py @@ -4,16 +4,19 @@ import typing import pydantic from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from .run_sdk_action_response_result import RunSdkActionResponseResult class RunSdkActionResponse(UniversalBaseModel): + """ + Response from running an SDK action. + """ + workflow_run_id: str = pydantic.Field() """ The workflow run ID used for this action """ - result: typing.Optional[RunSdkActionResponseResult] = pydantic.Field(default=None) + result: typing.Optional[typing.Optional[typing.Any]] = pydantic.Field(default=None) """ The result from the action (e.g., selector, value, extracted data) """ diff --git a/skyvern/client/types/select_option_action.py b/skyvern/client/types/select_option_action.py index 35ca2485..610007bd 100644 --- a/skyvern/client/types/select_option_action.py +++ b/skyvern/client/types/select_option_action.py @@ -8,6 +8,10 @@ from .select_option_action_data import SelectOptionActionData class SelectOptionAction(UniversalBaseModel): + """ + Select option action parameters. + """ + selector: typing.Optional[str] = pydantic.Field(default=None) """ CSS selector for the element diff --git a/skyvern/client/types/workflow.py b/skyvern/client/types/workflow.py index e5908ce9..4030f29d 100644 --- a/skyvern/client/types/workflow.py +++ b/skyvern/client/types/workflow.py @@ -35,6 +35,8 @@ class Workflow(UniversalBaseModel): cache_key: typing.Optional[str] = None run_sequentially: typing.Optional[bool] = None sequential_key: typing.Optional[str] = None + folder_id: typing.Optional[str] = None + import_error: typing.Optional[str] = None created_at: dt.datetime modified_at: dt.datetime deleted_at: typing.Optional[dt.datetime] = None diff --git a/skyvern/client/types/workflow_run_response.py b/skyvern/client/types/workflow_run_response.py index 0459d13a..71cd462e 100644 --- a/skyvern/client/types/workflow_run_response.py +++ b/skyvern/client/types/workflow_run_response.py @@ -83,11 +83,6 @@ class WorkflowRunResponse(UniversalBaseModel): ID of the Skyvern persistent browser session used for this run """ - browser_profile_id: typing.Optional[str] = pydantic.Field(default=None) - """ - ID of the browser profile used for this run - """ - max_screenshot_scrolls: typing.Optional[int] = pydantic.Field(default=None) """ The maximum number of scrolls for the post action screenshot. When it's None or 0, it takes the current viewpoint screenshot diff --git a/skyvern/client/types/workflow_status.py b/skyvern/client/types/workflow_status.py index 7d4a9cfa..325d3a28 100644 --- a/skyvern/client/types/workflow_status.py +++ b/skyvern/client/types/workflow_status.py @@ -2,4 +2,6 @@ import typing -WorkflowStatus = typing.Union[typing.Literal["published", "draft", "auto_generated"], typing.Any] +WorkflowStatus = typing.Union[ + typing.Literal["published", "draft", "auto_generated", "importing", "import_failed"], typing.Any +] diff --git a/skyvern/client/workflows/__init__.py b/skyvern/client/workflows/__init__.py new file mode 100644 index 00000000..5cde0202 --- /dev/null +++ b/skyvern/client/workflows/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/skyvern/client/workflows/client.py b/skyvern/client/workflows/client.py new file mode 100644 index 00000000..b091a973 --- /dev/null +++ b/skyvern/client/workflows/client.py @@ -0,0 +1,596 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from ..types.folder import Folder +from ..types.workflow import Workflow +from .raw_client import AsyncRawWorkflowsClient, RawWorkflowsClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class WorkflowsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawWorkflowsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawWorkflowsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawWorkflowsClient + """ + return self._raw_client + + def get_folders( + self, + *, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + search: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.List[Folder]: + """ + Get all folders for the organization + + Parameters + ---------- + page : typing.Optional[int] + Page number + + page_size : typing.Optional[int] + Number of folders per page + + search : typing.Optional[str] + Search folders by title or description + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[Folder] + Successfully retrieved folders + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.workflows.get_folders( + page=1, + page_size=1, + search="search", + ) + """ + _response = self._raw_client.get_folders( + page=page, page_size=page_size, search=search, request_options=request_options + ) + return _response.data + + def create_folder( + self, + *, + title: str, + description: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Folder: + """ + Create a new folder to organize workflows + + Parameters + ---------- + title : str + Folder title + + description : typing.Optional[str] + Folder description + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Folder + Successfully created folder + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.workflows.create_folder( + title="title", + ) + """ + _response = self._raw_client.create_folder( + title=title, description=description, request_options=request_options + ) + return _response.data + + def get_folder(self, folder_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Folder: + """ + Get a specific folder by ID + + Parameters + ---------- + folder_id : str + Folder ID + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Folder + Successfully retrieved folder + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.workflows.get_folder( + folder_id="fld_123", + ) + """ + _response = self._raw_client.get_folder(folder_id, request_options=request_options) + return _response.data + + def update_folder( + self, + folder_id: str, + *, + title: typing.Optional[str] = OMIT, + description: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Folder: + """ + Update a folder's title or description + + Parameters + ---------- + folder_id : str + Folder ID + + title : typing.Optional[str] + Folder title + + description : typing.Optional[str] + Folder description + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Folder + Successfully updated folder + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.workflows.update_folder( + folder_id="fld_123", + ) + """ + _response = self._raw_client.update_folder( + folder_id, title=title, description=description, request_options=request_options + ) + return _response.data + + def delete_folder( + self, + folder_id: str, + *, + delete_workflows: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Optional[typing.Any]]: + """ + Delete a folder. Optionally delete all workflows in the folder. + + Parameters + ---------- + folder_id : str + Folder ID + + delete_workflows : typing.Optional[bool] + If true, also delete all workflows in this folder + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Optional[typing.Any]] + Successfully deleted folder + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.workflows.delete_folder( + folder_id="fld_123", + delete_workflows=True, + ) + """ + _response = self._raw_client.delete_folder( + folder_id, delete_workflows=delete_workflows, request_options=request_options + ) + return _response.data + + def update_workflow_folder( + self, + workflow_permanent_id: str, + *, + folder_id: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Workflow: + """ + Update a workflow's folder assignment for the latest version + + Parameters + ---------- + workflow_permanent_id : str + Workflow permanent ID + + folder_id : typing.Optional[str] + Folder ID to assign workflow to. Set to null to remove from folder. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Workflow + Successfully updated workflow folder + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.workflows.update_workflow_folder( + workflow_permanent_id="wpid_123", + ) + """ + _response = self._raw_client.update_workflow_folder( + workflow_permanent_id, folder_id=folder_id, request_options=request_options + ) + return _response.data + + +class AsyncWorkflowsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawWorkflowsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawWorkflowsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawWorkflowsClient + """ + return self._raw_client + + async def get_folders( + self, + *, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + search: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.List[Folder]: + """ + Get all folders for the organization + + Parameters + ---------- + page : typing.Optional[int] + Page number + + page_size : typing.Optional[int] + Number of folders per page + + search : typing.Optional[str] + Search folders by title or description + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[Folder] + Successfully retrieved folders + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.workflows.get_folders( + page=1, + page_size=1, + search="search", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_folders( + page=page, page_size=page_size, search=search, request_options=request_options + ) + return _response.data + + async def create_folder( + self, + *, + title: str, + description: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Folder: + """ + Create a new folder to organize workflows + + Parameters + ---------- + title : str + Folder title + + description : typing.Optional[str] + Folder description + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Folder + Successfully created folder + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.workflows.create_folder( + title="title", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.create_folder( + title=title, description=description, request_options=request_options + ) + return _response.data + + async def get_folder(self, folder_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Folder: + """ + Get a specific folder by ID + + Parameters + ---------- + folder_id : str + Folder ID + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Folder + Successfully retrieved folder + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.workflows.get_folder( + folder_id="fld_123", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get_folder(folder_id, request_options=request_options) + return _response.data + + async def update_folder( + self, + folder_id: str, + *, + title: typing.Optional[str] = OMIT, + description: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Folder: + """ + Update a folder's title or description + + Parameters + ---------- + folder_id : str + Folder ID + + title : typing.Optional[str] + Folder title + + description : typing.Optional[str] + Folder description + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Folder + Successfully updated folder + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.workflows.update_folder( + folder_id="fld_123", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.update_folder( + folder_id, title=title, description=description, request_options=request_options + ) + return _response.data + + async def delete_folder( + self, + folder_id: str, + *, + delete_workflows: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Optional[typing.Any]]: + """ + Delete a folder. Optionally delete all workflows in the folder. + + Parameters + ---------- + folder_id : str + Folder ID + + delete_workflows : typing.Optional[bool] + If true, also delete all workflows in this folder + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Optional[typing.Any]] + Successfully deleted folder + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.workflows.delete_folder( + folder_id="fld_123", + delete_workflows=True, + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.delete_folder( + folder_id, delete_workflows=delete_workflows, request_options=request_options + ) + return _response.data + + async def update_workflow_folder( + self, + workflow_permanent_id: str, + *, + folder_id: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Workflow: + """ + Update a workflow's folder assignment for the latest version + + Parameters + ---------- + workflow_permanent_id : str + Workflow permanent ID + + folder_id : typing.Optional[str] + Folder ID to assign workflow to. Set to null to remove from folder. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Workflow + Successfully updated workflow folder + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.workflows.update_workflow_folder( + workflow_permanent_id="wpid_123", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.update_workflow_folder( + workflow_permanent_id, folder_id=folder_id, request_options=request_options + ) + return _response.data diff --git a/skyvern/client/workflows/raw_client.py b/skyvern/client/workflows/raw_client.py new file mode 100644 index 00000000..23c97c2c --- /dev/null +++ b/skyvern/client/workflows/raw_client.py @@ -0,0 +1,909 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..errors.bad_request_error import BadRequestError +from ..errors.not_found_error import NotFoundError +from ..errors.unprocessable_entity_error import UnprocessableEntityError +from ..types.folder import Folder +from ..types.workflow import Workflow + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawWorkflowsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get_folders( + self, + *, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + search: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[typing.List[Folder]]: + """ + Get all folders for the organization + + Parameters + ---------- + page : typing.Optional[int] + Page number + + page_size : typing.Optional[int] + Number of folders per page + + search : typing.Optional[str] + Search folders by title or description + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.List[Folder]] + Successfully retrieved folders + """ + _response = self._client_wrapper.httpx_client.request( + "v1/folders", + method="GET", + params={ + "page": page, + "page_size": page_size, + "search": search, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.List[Folder], + parse_obj_as( + type_=typing.List[Folder], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def create_folder( + self, + *, + title: str, + description: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Folder]: + """ + Create a new folder to organize workflows + + Parameters + ---------- + title : str + Folder title + + description : typing.Optional[str] + Folder description + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Folder] + Successfully created folder + """ + _response = self._client_wrapper.httpx_client.request( + "v1/folders", + method="POST", + json={ + "title": title, + "description": description, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Folder, + parse_obj_as( + type_=Folder, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_folder( + self, folder_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[Folder]: + """ + Get a specific folder by ID + + Parameters + ---------- + folder_id : str + Folder ID + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Folder] + Successfully retrieved folder + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/folders/{jsonable_encoder(folder_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Folder, + parse_obj_as( + type_=Folder, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update_folder( + self, + folder_id: str, + *, + title: typing.Optional[str] = OMIT, + description: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Folder]: + """ + Update a folder's title or description + + Parameters + ---------- + folder_id : str + Folder ID + + title : typing.Optional[str] + Folder title + + description : typing.Optional[str] + Folder description + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Folder] + Successfully updated folder + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/folders/{jsonable_encoder(folder_id)}", + method="PUT", + json={ + "title": title, + "description": description, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Folder, + parse_obj_as( + type_=Folder, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete_folder( + self, + folder_id: str, + *, + delete_workflows: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]: + """ + Delete a folder. Optionally delete all workflows in the folder. + + Parameters + ---------- + folder_id : str + Folder ID + + delete_workflows : typing.Optional[bool] + If true, also delete all workflows in this folder + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Optional[typing.Any]]] + Successfully deleted folder + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/folders/{jsonable_encoder(folder_id)}", + method="DELETE", + params={ + "delete_workflows": delete_workflows, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Optional[typing.Any]], + parse_obj_as( + type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update_workflow_folder( + self, + workflow_permanent_id: str, + *, + folder_id: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Workflow]: + """ + Update a workflow's folder assignment for the latest version + + Parameters + ---------- + workflow_permanent_id : str + Workflow permanent ID + + folder_id : typing.Optional[str] + Folder ID to assign workflow to. Set to null to remove from folder. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Workflow] + Successfully updated workflow folder + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/folder", + method="PUT", + json={ + "folder_id": folder_id, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Workflow, + parse_obj_as( + type_=Workflow, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawWorkflowsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get_folders( + self, + *, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + search: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[typing.List[Folder]]: + """ + Get all folders for the organization + + Parameters + ---------- + page : typing.Optional[int] + Page number + + page_size : typing.Optional[int] + Number of folders per page + + search : typing.Optional[str] + Search folders by title or description + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.List[Folder]] + Successfully retrieved folders + """ + _response = await self._client_wrapper.httpx_client.request( + "v1/folders", + method="GET", + params={ + "page": page, + "page_size": page_size, + "search": search, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.List[Folder], + parse_obj_as( + type_=typing.List[Folder], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def create_folder( + self, + *, + title: str, + description: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Folder]: + """ + Create a new folder to organize workflows + + Parameters + ---------- + title : str + Folder title + + description : typing.Optional[str] + Folder description + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Folder] + Successfully created folder + """ + _response = await self._client_wrapper.httpx_client.request( + "v1/folders", + method="POST", + json={ + "title": title, + "description": description, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Folder, + parse_obj_as( + type_=Folder, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_folder( + self, folder_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[Folder]: + """ + Get a specific folder by ID + + Parameters + ---------- + folder_id : str + Folder ID + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Folder] + Successfully retrieved folder + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/folders/{jsonable_encoder(folder_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Folder, + parse_obj_as( + type_=Folder, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update_folder( + self, + folder_id: str, + *, + title: typing.Optional[str] = OMIT, + description: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Folder]: + """ + Update a folder's title or description + + Parameters + ---------- + folder_id : str + Folder ID + + title : typing.Optional[str] + Folder title + + description : typing.Optional[str] + Folder description + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Folder] + Successfully updated folder + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/folders/{jsonable_encoder(folder_id)}", + method="PUT", + json={ + "title": title, + "description": description, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Folder, + parse_obj_as( + type_=Folder, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete_folder( + self, + folder_id: str, + *, + delete_workflows: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]: + """ + Delete a folder. Optionally delete all workflows in the folder. + + Parameters + ---------- + folder_id : str + Folder ID + + delete_workflows : typing.Optional[bool] + If true, also delete all workflows in this folder + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Optional[typing.Any]]] + Successfully deleted folder + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/folders/{jsonable_encoder(folder_id)}", + method="DELETE", + params={ + "delete_workflows": delete_workflows, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Optional[typing.Any]], + parse_obj_as( + type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update_workflow_folder( + self, + workflow_permanent_id: str, + *, + folder_id: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Workflow]: + """ + Update a workflow's folder assignment for the latest version + + Parameters + ---------- + workflow_permanent_id : str + Workflow permanent ID + + folder_id : typing.Optional[str] + Folder ID to assign workflow to. Set to null to remove from folder. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Workflow] + Successfully updated workflow folder + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_permanent_id)}/folder", + method="PUT", + json={ + "folder_id": folder_id, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Workflow, + parse_obj_as( + type_=Workflow, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/skyvern/library/skyvern_browser_page_ai.py b/skyvern/library/skyvern_browser_page_ai.py index 75749ee2..cedfb954 100644 --- a/skyvern/library/skyvern_browser_page_ai.py +++ b/skyvern/library/skyvern_browser_page_ai.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING, Any from playwright.async_api import Page -from skyvern.client import ( +from skyvern.client.types.sdk_action import ( SdkAction_AiAct, SdkAction_AiClick, SdkAction_AiInputText,