From abab86619c18912d975cfbffacd32984e135c47c Mon Sep 17 00:00:00 2001 From: Shuchang Zheng Date: Tue, 27 May 2025 23:38:14 -0700 Subject: [PATCH] move every interface to top level and get rid of sdk client grouping (#2490) --- README.md | 6 +- fern/getting-started/quickstart.mdx | 2 +- fern/openapi/skyvern_openapi.json | 52 +- .../langchain/skyvern_langchain/agent.py | 4 +- .../langchain/skyvern_langchain/client.py | 4 +- .../llama_index/skyvern_llamaindex/agent.py | 4 +- .../llama_index/skyvern_llamaindex/client.py | 4 +- skyvern/client/__init__.py | 34 +- skyvern/client/agent/__init__.py | 19 - skyvern/client/agent/client.py | 1105 ------ skyvern/client/agent/types/__init__.py | 19 - skyvern/client/artifacts/__init__.py | 2 - skyvern/client/artifacts/client.py | 165 - skyvern/client/browser_session/__init__.py | 2 - skyvern/client/browser_session/client.py | 631 ---- skyvern/client/client.py | 3244 ++++++++++++++++- skyvern/client/credentials/__init__.py | 5 - skyvern/client/credentials/client.py | 800 ---- skyvern/client/credentials/types/__init__.py | 5 - skyvern/client/types/__init__.py | 16 + skyvern/client/types/action_block_yaml.py | 2 + .../create_credential_request_credential.py | 4 +- skyvern/client/types/extraction_block_yaml.py | 2 + .../client/types/file_download_block_yaml.py | 2 + .../for_loop_block_yaml_loop_blocks_item.py | 7 +- .../get_run_response.py} | 38 +- skyvern/client/types/login_block_yaml.py | 2 + skyvern/client/types/task_block_yaml.py | 2 + .../workflow_definition_yaml_blocks_item.py | 7 +- skyvern/client/workflows/__init__.py | 2 - skyvern/client/workflows/client.py | 637 ---- skyvern/forge/sdk/routes/code_samples.py | 10 +- skyvern/library/skyvern.py | 83 +- 33 files changed, 3358 insertions(+), 3563 deletions(-) delete mode 100644 skyvern/client/agent/__init__.py delete mode 100644 skyvern/client/agent/client.py delete mode 100644 skyvern/client/agent/types/__init__.py delete mode 100644 skyvern/client/artifacts/__init__.py delete mode 100644 skyvern/client/artifacts/client.py delete mode 100644 skyvern/client/browser_session/__init__.py delete mode 100644 skyvern/client/browser_session/client.py delete mode 100644 skyvern/client/credentials/__init__.py delete mode 100644 skyvern/client/credentials/client.py delete mode 100644 skyvern/client/credentials/types/__init__.py rename skyvern/client/{credentials => }/types/create_credential_request_credential.py (53%) rename skyvern/client/{agent/types/agent_get_run_response.py => types/get_run_response.py} (82%) delete mode 100644 skyvern/client/workflows/__init__.py delete mode 100644 skyvern/client/workflows/client.py diff --git a/README.md b/README.md index 20971de4..91d881f8 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ skyvern quickstart from skyvern import Skyvern skyvern = Skyvern() - task = await skyvern.local.run_task(prompt="Find the top post on hackernews today") + task = await skyvern.run_task(prompt="Find the top post on hackernews today") print(task) ``` A local browser will pop up. Skyvern will start executing the task in the browser and close the it when the task is done. You will be able to review the task from http://localhost:8080/history @@ -75,13 +75,13 @@ skyvern quickstart from skyvern import Skyvern skyvern = Skyvern(api_key="SKYVERN API KEY") - task = await skyvern.agent.run_task(prompt="Find the top post on hackernews today") + task = await skyvern.run_task(prompt="Find the top post on hackernews today") print(task) ``` Or any hosted Skyvern service: ```python skyvern = Skyvern(base_url="http://localhost:8000", api_key="SKYVERN API KEY") - task = await skyvern.agent.run_task(prompt="Find the top post on hackernews today") + task = await skyvern.run_task(prompt="Find the top post on hackernews today") print(task) ``` diff --git a/fern/getting-started/quickstart.mdx b/fern/getting-started/quickstart.mdx index aeb25ffe..21b5ef25 100644 --- a/fern/getting-started/quickstart.mdx +++ b/fern/getting-started/quickstart.mdx @@ -32,7 +32,7 @@ skyvern = Skyvern(api_key="YOUR API KEY") # OR pass the base_url to use any Skyvern service # skyvern = Skyvern(base_url="http://localhost:8000", api_key="YOUR API KEY") -task = await skyvern.agent.run_task(prompt="Find the top post on hackernews today") +task = await skyvern.run_task(prompt="Find the top post on hackernews today") print(task) ``` More API & SDK information can be found in the [API Reference](/api-reference) section. diff --git a/fern/openapi/skyvern_openapi.json b/fern/openapi/skyvern_openapi.json index cc37ccdb..f63a7b24 100644 --- a/fern/openapi/skyvern_openapi.json +++ b/fern/openapi/skyvern_openapi.json @@ -92,7 +92,7 @@ "code-samples": [ { "sdk": "python", - "code": "from skyvern import Skyvern\n\nskyvern = Skyvern(api_key=\"YOUR_API_KEY\")\nawait skyvern.agent.run_task(prompt=\"What's the top post on hackernews?\")\n" + "code": "from skyvern import Skyvern\n\nskyvern = Skyvern(api_key=\"YOUR_API_KEY\")\nawait skyvern.run_task(prompt=\"What's the top post on hackernews?\")\n" } ] } @@ -102,7 +102,7 @@ "/v1/run/workflows": { "post": { "tags": [ - "Agent" + "Workflows" ], "summary": "Run a workflow", "description": "Run a workflow", @@ -204,14 +204,14 @@ } } }, - "x-fern-sdk-group-name": "agent", + "x-fern-sdk-group-name": "workflows", "x-fern-sdk-method-name": "run_workflow", "x-fern-examples": [ { "code-samples": [ { "sdk": "python", - "code": "from skyvern import Skyvern\n\nskyvern = Skyvern(api_key=\"YOUR_API_KEY\")\nawait skyvern.agent.run_workflow(workflow_id=\"wpid_123\", parameters={\"parameter1\": \"value1\", \"parameter2\": \"value2\"})\n" + "code": "from skyvern import Skyvern\n\nskyvern = Skyvern(api_key=\"YOUR_API_KEY\")\nawait skyvern.run_workflow(workflow_id=\"wpid_123\", parameters={\"parameter1\": \"value1\", \"parameter2\": \"value2\"})\n" } ] } @@ -221,9 +221,10 @@ "/v1/runs/{run_id}": { "get": { "tags": [ - "Agent" + "Agent", + "Workflows" ], - "summary": "Get a task or a workflow run by id", + "summary": "Get a run by id", "description": "Get run information (task run, workflow run)", "operationId": "get_run_v1_runs__run_id__get", "parameters": [ @@ -312,7 +313,7 @@ "code-samples": [ { "sdk": "python", - "code": "from skyvern import Skyvern\n\nskyvern = Skyvern(api_key=\"YOUR_API_KEY\")\nrun = await skyvern.agent.get_run(run_id=\"tsk_v2_123\")\nprint(run)\n" + "code": "from skyvern import Skyvern\n\nskyvern = Skyvern(api_key=\"YOUR_API_KEY\")\nrun = await skyvern.get_run(run_id=\"tsk_v2_123\")\nprint(run)\n" } ] } @@ -322,9 +323,10 @@ "/v1/runs/{run_id}/cancel": { "post": { "tags": [ - "Agent" + "Agent", + "Workflows" ], - "summary": "Cancel a task or workflow run", + "summary": "Cancel a run by id", "description": "Cancel a run (task or workflow)", "operationId": "cancel_run_v1_runs__run_id__cancel_post", "parameters": [ @@ -387,7 +389,7 @@ "code-samples": [ { "sdk": "python", - "code": "from skyvern import Skyvern\n\nskyvern = Skyvern(api_key=\"YOUR_API_KEY\")\nawait skyvern.agent.cancel_run(run_id=\"tsk_v2_123\")\n" + "code": "from skyvern import Skyvern\n\nskyvern = Skyvern(api_key=\"YOUR_API_KEY\")\nawait skyvern.cancel_run(run_id=\"tsk_v2_123\")\n" } ] } @@ -399,8 +401,8 @@ "tags": [ "Workflows" ], - "summary": "Create a new workflow definition", - "description": "Create a new workflow definition", + "summary": "Create a new workflow", + "description": "Create a new workflow", "operationId": "create_workflow_v1_workflows_post", "parameters": [ { @@ -598,8 +600,8 @@ "tags": [ "Workflows" ], - "summary": "Update a workflow definition", - "description": "Update a workflow definition", + "summary": "Update a workflow", + "description": "Update a workflow", "operationId": "update_workflow_v1_workflows__workflow_id__post", "parameters": [ { @@ -894,7 +896,7 @@ "code-samples": [ { "sdk": "python", - "code": "from skyvern import Skyvern\n\nskyvern = Skyvern(api_key=\"YOUR_API_KEY\")\nawait skyvern.agent.retry_run_webhook(run_id=\"tsk_v2_123\")\n" + "code": "from skyvern import Skyvern\n\nskyvern = Skyvern(api_key=\"YOUR_API_KEY\")\nawait skyvern.retry_run_webhook(run_id=\"tsk_v2_123\")\n" } ] } @@ -2002,6 +2004,10 @@ "title": "Title", "default": "" }, + "engine": { + "$ref": "#/components/schemas/RunEngine", + "default": "skyvern-1.0" + }, "navigation_goal": { "anyOf": [ { @@ -3714,6 +3720,10 @@ "title": "Title", "default": "" }, + "engine": { + "$ref": "#/components/schemas/RunEngine", + "default": "skyvern-1.0" + }, "data_schema": { "anyOf": [ { @@ -4056,6 +4066,10 @@ "title": "Title", "default": "" }, + "engine": { + "$ref": "#/components/schemas/RunEngine", + "default": "skyvern-1.0" + }, "error_code_mapping": { "anyOf": [ { @@ -5023,6 +5037,10 @@ "title": "Title", "default": "" }, + "engine": { + "$ref": "#/components/schemas/RunEngine", + "default": "skyvern-1.0" + }, "navigation_goal": { "anyOf": [ { @@ -6581,6 +6599,10 @@ "title": "Title", "default": "" }, + "engine": { + "$ref": "#/components/schemas/RunEngine", + "default": "skyvern-1.0" + }, "navigation_goal": { "anyOf": [ { diff --git a/integrations/langchain/skyvern_langchain/agent.py b/integrations/langchain/skyvern_langchain/agent.py index a162b9ac..42b1bad2 100644 --- a/integrations/langchain/skyvern_langchain/agent.py +++ b/integrations/langchain/skyvern_langchain/agent.py @@ -7,7 +7,7 @@ from skyvern_langchain.schema import CreateTaskInput, GetTaskInput from skyvern_langchain.settings import settings from skyvern import Skyvern -from skyvern.client.agent.types.agent_get_run_response import AgentGetRunResponse +from skyvern.client.types.get_run_response import GetRunResponse from skyvern.client.types.task_run_response import TaskRunResponse from skyvern.schemas.runs import RunEngine @@ -56,5 +56,5 @@ class GetTask(SkyvernTaskBaseTool): description: str = """Use Skyvern agent to get a task.""" args_schema: Type[BaseModel] = GetTaskInput - async def _arun(self, task_id: str) -> AgentGetRunResponse | None: + async def _arun(self, task_id: str) -> GetRunResponse | None: return await self.agent.get_run(run_id=task_id) diff --git a/integrations/langchain/skyvern_langchain/client.py b/integrations/langchain/skyvern_langchain/client.py index 7dd189f2..b98bfb59 100644 --- a/integrations/langchain/skyvern_langchain/client.py +++ b/integrations/langchain/skyvern_langchain/client.py @@ -6,7 +6,7 @@ from skyvern_langchain.schema import CreateTaskInput, GetTaskInput from skyvern_langchain.settings import settings from skyvern import Skyvern -from skyvern.client.agent.types.agent_get_run_response import AgentGetRunResponse +from skyvern.client.types.get_run_response import GetRunResponse from skyvern.client.types.task_run_response import TaskRunResponse from skyvern.schemas.runs import RunEngine @@ -59,5 +59,5 @@ class GetTask(SkyvernTaskBaseTool): description: str = """Use Skyvern client to get a task.""" args_schema: Type[BaseModel] = GetTaskInput - async def _arun(self, task_id: str) -> AgentGetRunResponse | None: + async def _arun(self, task_id: str) -> GetRunResponse | None: return await self.get_client().get_run(run_id=task_id) diff --git a/integrations/llama_index/skyvern_llamaindex/agent.py b/integrations/llama_index/skyvern_llamaindex/agent.py index eccf0ee1..fadbdabd 100644 --- a/integrations/llama_index/skyvern_llamaindex/agent.py +++ b/integrations/llama_index/skyvern_llamaindex/agent.py @@ -5,7 +5,7 @@ from llama_index.core.tools.tool_spec.base import SPEC_FUNCTION_TYPE, BaseToolSp from skyvern_llamaindex.settings import settings from skyvern import Skyvern -from skyvern.client.agent.types.agent_get_run_response import AgentGetRunResponse +from skyvern.client.types.get_run_response import GetRunResponse from skyvern.client.types.task_run_response import TaskRunResponse from skyvern.schemas.runs import RunEngine @@ -81,7 +81,7 @@ class SkyvernTaskToolSpec(BaseToolSpec): wait_for_completion=False, ) - async def get_task(self, task_id: str) -> AgentGetRunResponse | None: + async def get_task(self, task_id: str) -> GetRunResponse | None: """ Use Skyvern agent to get a task. diff --git a/integrations/llama_index/skyvern_llamaindex/client.py b/integrations/llama_index/skyvern_llamaindex/client.py index 438b39b1..f05e338c 100644 --- a/integrations/llama_index/skyvern_llamaindex/client.py +++ b/integrations/llama_index/skyvern_llamaindex/client.py @@ -6,7 +6,7 @@ from pydantic import BaseModel from skyvern_llamaindex.settings import settings from skyvern import Skyvern -from skyvern.client.agent.types.agent_get_run_response import AgentGetRunResponse +from skyvern.client.types.get_run_response import GetRunResponse from skyvern.client.types.task_run_response import TaskRunResponse from skyvern.schemas.runs import RunEngine @@ -93,7 +93,7 @@ class SkyvernTaskToolSpec(BaseToolSpec): wait_for_completion=False, ) - async def get_task(self, task_id: str) -> AgentGetRunResponse | None: + async def get_task(self, task_id: str) -> GetRunResponse | None: """ Use Skyvern client to get a task. diff --git a/skyvern/client/__init__.py b/skyvern/client/__init__.py index aa820e57..98c39b29 100644 --- a/skyvern/client/__init__.py +++ b/skyvern/client/__init__.py @@ -47,6 +47,7 @@ from .types import ( ContextParameterSource_Workflow, ContextParameterValue, ContextParameterYaml, + CreateCredentialRequestCredential, CredentialParameter, CredentialParameterYaml, CredentialResponse, @@ -138,6 +139,12 @@ from .types import ( ForLoopBlockYamlLoopBlocksItem_UploadToS3, ForLoopBlockYamlLoopBlocksItem_Validation, ForLoopBlockYamlLoopBlocksItem_Wait, + GetRunResponse, + GetRunResponse_AnthropicCua, + GetRunResponse_OpenaiCua, + GetRunResponse_TaskV1, + GetRunResponse_TaskV2, + GetRunResponse_WorkflowRun, HttpValidationError, LoginBlock, LoginBlockDataSchema, @@ -319,17 +326,7 @@ from .types import ( WorkflowStatus, ) from .errors import BadRequestError, ForbiddenError, NotFoundError, UnprocessableEntityError -from . import agent, artifacts, browser_session, credentials, workflows -from .agent import ( - AgentGetRunResponse, - AgentGetRunResponse_AnthropicCua, - AgentGetRunResponse_OpenaiCua, - AgentGetRunResponse_TaskV1, - AgentGetRunResponse_TaskV2, - AgentGetRunResponse_WorkflowRun, -) from .client import AsyncSkyvern, Skyvern -from .credentials import CreateCredentialRequestCredential from .environment import SkyvernEnvironment from .version import __version__ @@ -346,12 +343,6 @@ __all__ = [ "ActionBlockParametersItem_Output", "ActionBlockParametersItem_Workflow", "ActionBlockYaml", - "AgentGetRunResponse", - "AgentGetRunResponse_AnthropicCua", - "AgentGetRunResponse_OpenaiCua", - "AgentGetRunResponse_TaskV1", - "AgentGetRunResponse_TaskV2", - "AgentGetRunResponse_WorkflowRun", "Artifact", "ArtifactType", "AsyncSkyvern", @@ -481,6 +472,12 @@ __all__ = [ "ForLoopBlockYamlLoopBlocksItem_Validation", "ForLoopBlockYamlLoopBlocksItem_Wait", "ForbiddenError", + "GetRunResponse", + "GetRunResponse_AnthropicCua", + "GetRunResponse_OpenaiCua", + "GetRunResponse_TaskV1", + "GetRunResponse_TaskV2", + "GetRunResponse_WorkflowRun", "HttpValidationError", "LoginBlock", "LoginBlockDataSchema", @@ -665,9 +662,4 @@ __all__ = [ "WorkflowRunResponseOutput", "WorkflowStatus", "__version__", - "agent", - "artifacts", - "browser_session", - "credentials", - "workflows", ] diff --git a/skyvern/client/agent/__init__.py b/skyvern/client/agent/__init__.py deleted file mode 100644 index 4ed9d092..00000000 --- a/skyvern/client/agent/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .types import ( - AgentGetRunResponse, - AgentGetRunResponse_AnthropicCua, - AgentGetRunResponse_OpenaiCua, - AgentGetRunResponse_TaskV1, - AgentGetRunResponse_TaskV2, - AgentGetRunResponse_WorkflowRun, -) - -__all__ = [ - "AgentGetRunResponse", - "AgentGetRunResponse_AnthropicCua", - "AgentGetRunResponse_OpenaiCua", - "AgentGetRunResponse_TaskV1", - "AgentGetRunResponse_TaskV2", - "AgentGetRunResponse_WorkflowRun", -] diff --git a/skyvern/client/agent/client.py b/skyvern/client/agent/client.py deleted file mode 100644 index 6be67078..00000000 --- a/skyvern/client/agent/client.py +++ /dev/null @@ -1,1105 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -from ..core.client_wrapper import SyncClientWrapper -from ..types.run_engine import RunEngine -from ..types.proxy_location import ProxyLocation -from ..types.task_run_request_data_extraction_schema import TaskRunRequestDataExtractionSchema -from ..core.request_options import RequestOptions -from ..types.task_run_response import TaskRunResponse -from ..core.serialization import convert_and_respect_annotation_metadata -from ..core.pydantic_utilities import parse_obj_as -from ..errors.bad_request_error import BadRequestError -from ..errors.unprocessable_entity_error import UnprocessableEntityError -from json.decoder import JSONDecodeError -from ..core.api_error import ApiError -from ..types.workflow_run_response import WorkflowRunResponse -from .types.agent_get_run_response import AgentGetRunResponse -from ..core.jsonable_encoder import jsonable_encoder -from ..errors.not_found_error import NotFoundError -from ..core.client_wrapper import AsyncClientWrapper - -# this is used as the default value for optional parameters -OMIT = typing.cast(typing.Any, ...) - - -class AgentClient: - def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper - - def run_task( - self, - *, - prompt: str, - user_agent: typing.Optional[str] = None, - url: typing.Optional[str] = OMIT, - engine: typing.Optional[RunEngine] = OMIT, - title: typing.Optional[str] = OMIT, - proxy_location: typing.Optional[ProxyLocation] = OMIT, - data_extraction_schema: typing.Optional[TaskRunRequestDataExtractionSchema] = OMIT, - error_code_mapping: typing.Optional[typing.Dict[str, typing.Optional[str]]] = OMIT, - max_steps: typing.Optional[int] = OMIT, - webhook_url: typing.Optional[str] = OMIT, - totp_identifier: typing.Optional[str] = OMIT, - totp_url: typing.Optional[str] = OMIT, - browser_session_id: typing.Optional[str] = OMIT, - publish_workflow: typing.Optional[bool] = OMIT, - include_action_history_in_verification: typing.Optional[bool] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> TaskRunResponse: - """ - Run a task - - Parameters - ---------- - prompt : str - - The goal or task description for Skyvern to accomplish - - user_agent : typing.Optional[str] - - url : typing.Optional[str] - - The starting URL for the task. If not provided, Skyvern will attempt to determine an appropriate URL - - engine : typing.Optional[RunEngine] - - The engine that powers the agent task. The default value is `skyvern-2.0`, the latest Skyvern agent that performs pretty well with complex and multi-step tasks. `skyvern-1.0` is good for simple tasks like filling a form, or searching for information on Google. The `openai-cua` engine uses OpenAI's CUA model. The `anthropic-cua` uses Anthropic's Claude Sonnet 3.7 model with the computer use tool. - - title : typing.Optional[str] - The title for the task - - proxy_location : typing.Optional[ProxyLocation] - - Geographic Proxy location to route the browser traffic through. This is only available in Skyvern Cloud. - - Available geotargeting options: - - RESIDENTIAL: the default value. Skyvern Cloud uses a random US residential proxy. - - RESIDENTIAL_ES: Spain - - RESIDENTIAL_IE: Ireland - - RESIDENTIAL_GB: United Kingdom - - RESIDENTIAL_IN: India - - RESIDENTIAL_JP: Japan - - RESIDENTIAL_FR: France - - RESIDENTIAL_DE: Germany - - RESIDENTIAL_NZ: New Zealand - - RESIDENTIAL_ZA: South Africa - - RESIDENTIAL_AR: Argentina - - RESIDENTIAL_ISP: ISP proxy - - US-CA: California - - US-NY: New York - - US-TX: Texas - - US-FL: Florida - - US-WA: Washington - - NONE: No proxy - - data_extraction_schema : typing.Optional[TaskRunRequestDataExtractionSchema] - - The schema for data to be extracted from the webpage. If you're looking for consistent data schema being returned by the agent, it's highly recommended to use https://json-schema.org/. - - error_code_mapping : typing.Optional[typing.Dict[str, typing.Optional[str]]] - - Custom mapping of error codes to error messages if Skyvern encounters an error. - - max_steps : typing.Optional[int] - - Maximum number of steps the task can take. Task will fail if it exceeds this number. Cautions: you are charged per step so please set this number to a reasonable value. Contact sales@skyvern.com for custom pricing. - - webhook_url : typing.Optional[str] - - URL to send task status updates to after a run is finished. Refer to https://docs.skyvern.com/running-tasks/webhooks-faq for more details. - - totp_identifier : typing.Optional[str] - - Identifier for the TOTP/2FA/MFA code when the code is pushed to Skyvern. Refer to https://docs.skyvern.com/credentials/totp#option-3-push-code-to-skyvern for more details. - - totp_url : typing.Optional[str] - - URL that serves TOTP/2FA/MFA codes for Skyvern to use during the workflow run. Refer to https://docs.skyvern.com/credentials/totp#option-2-get-code-from-your-endpoint for more details. - - browser_session_id : typing.Optional[str] - - Run the task or workflow in the specific Skyvern browser session. Having a browser session can persist the real-time state of the browser, so that the next run can continue from where the previous run left off. - - publish_workflow : typing.Optional[bool] - Whether to publish this task as a reusable workflow. Only available for skyvern-2.0. - - include_action_history_in_verification : typing.Optional[bool] - Whether to include action history when verifying that the task is complete - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - TaskRunResponse - Successfully run task - - Examples - -------- - from skyvern import Skyvern - - client = Skyvern( - api_key="YOUR_API_KEY", - ) - client.agent.run_task( - prompt="Find the top 3 posts on Hacker News.", - ) - """ - _response = self._client_wrapper.httpx_client.request( - "v1/run/tasks", - method="POST", - json={ - "prompt": prompt, - "url": url, - "engine": engine, - "title": title, - "proxy_location": proxy_location, - "data_extraction_schema": convert_and_respect_annotation_metadata( - object_=data_extraction_schema, annotation=TaskRunRequestDataExtractionSchema, direction="write" - ), - "error_code_mapping": error_code_mapping, - "max_steps": max_steps, - "webhook_url": webhook_url, - "totp_identifier": totp_identifier, - "totp_url": totp_url, - "browser_session_id": browser_session_id, - "publish_workflow": publish_workflow, - "include_action_history_in_verification": include_action_history_in_verification, - }, - headers={ - "x-user-agent": str(user_agent) if user_agent is not None else None, - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - TaskRunResponse, - parse_obj_as( - type_=TaskRunResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def run_workflow( - self, - *, - workflow_id: str, - template: typing.Optional[bool] = None, - max_steps_override: typing.Optional[int] = None, - user_agent: typing.Optional[str] = None, - parameters: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, - title: typing.Optional[str] = OMIT, - proxy_location: typing.Optional[ProxyLocation] = OMIT, - webhook_url: typing.Optional[str] = OMIT, - totp_url: typing.Optional[str] = OMIT, - totp_identifier: typing.Optional[str] = OMIT, - browser_session_id: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> WorkflowRunResponse: - """ - Run a workflow - - Parameters - ---------- - workflow_id : str - ID of the workflow to run. Workflow ID starts with `wpid_`. - - template : typing.Optional[bool] - - max_steps_override : typing.Optional[int] - - user_agent : typing.Optional[str] - - parameters : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] - Parameters to pass to the workflow - - title : typing.Optional[str] - The title for this workflow run - - proxy_location : typing.Optional[ProxyLocation] - - Geographic Proxy location to route the browser traffic through. This is only available in Skyvern Cloud. - - Available geotargeting options: - - RESIDENTIAL: the default value. Skyvern Cloud uses a random US residential proxy. - - RESIDENTIAL_ES: Spain - - RESIDENTIAL_IE: Ireland - - RESIDENTIAL_GB: United Kingdom - - RESIDENTIAL_IN: India - - RESIDENTIAL_JP: Japan - - RESIDENTIAL_FR: France - - RESIDENTIAL_DE: Germany - - RESIDENTIAL_NZ: New Zealand - - RESIDENTIAL_ZA: South Africa - - RESIDENTIAL_AR: Argentina - - RESIDENTIAL_ISP: ISP proxy - - US-CA: California - - US-NY: New York - - US-TX: Texas - - US-FL: Florida - - US-WA: Washington - - NONE: No proxy - - webhook_url : typing.Optional[str] - URL to send workflow status updates to after a run is finished. Refer to https://docs.skyvern.com/running-tasks/webhooks-faq for webhook questions. - - totp_url : typing.Optional[str] - - URL that serves TOTP/2FA/MFA codes for Skyvern to use during the workflow run. Refer to https://docs.skyvern.com/credentials/totp#option-2-get-code-from-your-endpoint for more details. - - totp_identifier : typing.Optional[str] - - Identifier for the TOTP/2FA/MFA code when the code is pushed to Skyvern. Refer to https://docs.skyvern.com/credentials/totp#option-3-push-code-to-skyvern for more details. - - browser_session_id : typing.Optional[str] - ID of a Skyvern browser session to reuse, having it continue from the current screen state - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - WorkflowRunResponse - Successfully run workflow - - Examples - -------- - from skyvern import Skyvern - - client = Skyvern( - api_key="YOUR_API_KEY", - ) - client.agent.run_workflow( - workflow_id="wpid_123", - ) - """ - _response = self._client_wrapper.httpx_client.request( - "v1/run/workflows", - method="POST", - params={ - "template": template, - }, - json={ - "workflow_id": workflow_id, - "parameters": parameters, - "title": title, - "proxy_location": proxy_location, - "webhook_url": webhook_url, - "totp_url": totp_url, - "totp_identifier": totp_identifier, - "browser_session_id": browser_session_id, - }, - headers={ - "x-max-steps-override": str(max_steps_override) if max_steps_override is not None else None, - "x-user-agent": str(user_agent) if user_agent is not None else None, - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - WorkflowRunResponse, - parse_obj_as( - type_=WorkflowRunResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def get_run(self, run_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AgentGetRunResponse: - """ - Get run information (task run, workflow run) - - Parameters - ---------- - run_id : str - The id of the task run or the workflow run. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - AgentGetRunResponse - Successfully got run - - Examples - -------- - from skyvern import Skyvern - - client = Skyvern( - api_key="YOUR_API_KEY", - ) - client.agent.get_run( - run_id="tsk_123", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/runs/{jsonable_encoder(run_id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AgentGetRunResponse, - parse_obj_as( - type_=AgentGetRunResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 404: - raise NotFoundError( - 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def cancel_run( - self, run_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> typing.Optional[typing.Any]: - """ - Cancel a run (task or workflow) - - Parameters - ---------- - run_id : str - The id of the task run or the workflow run to cancel. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - Successful Response - - Examples - -------- - from skyvern import Skyvern - - client = Skyvern( - api_key="YOUR_API_KEY", - ) - client.agent.cancel_run( - run_id="run_id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/runs/{jsonable_encoder(run_id)}/cancel", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def retry_run_webhook( - self, run_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> typing.Optional[typing.Any]: - """ - Retry sending the webhook for a run - - Parameters - ---------- - run_id : str - The id of the task run or the workflow run. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - Successful Response - - Examples - -------- - from skyvern import Skyvern - - client = Skyvern( - api_key="YOUR_API_KEY", - ) - client.agent.retry_run_webhook( - run_id="tsk_123", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/runs/{jsonable_encoder(run_id)}/retry_webhook", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - -class AsyncAgentClient: - def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper - - async def run_task( - self, - *, - prompt: str, - user_agent: typing.Optional[str] = None, - url: typing.Optional[str] = OMIT, - engine: typing.Optional[RunEngine] = OMIT, - title: typing.Optional[str] = OMIT, - proxy_location: typing.Optional[ProxyLocation] = OMIT, - data_extraction_schema: typing.Optional[TaskRunRequestDataExtractionSchema] = OMIT, - error_code_mapping: typing.Optional[typing.Dict[str, typing.Optional[str]]] = OMIT, - max_steps: typing.Optional[int] = OMIT, - webhook_url: typing.Optional[str] = OMIT, - totp_identifier: typing.Optional[str] = OMIT, - totp_url: typing.Optional[str] = OMIT, - browser_session_id: typing.Optional[str] = OMIT, - publish_workflow: typing.Optional[bool] = OMIT, - include_action_history_in_verification: typing.Optional[bool] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> TaskRunResponse: - """ - Run a task - - Parameters - ---------- - prompt : str - - The goal or task description for Skyvern to accomplish - - user_agent : typing.Optional[str] - - url : typing.Optional[str] - - The starting URL for the task. If not provided, Skyvern will attempt to determine an appropriate URL - - engine : typing.Optional[RunEngine] - - The engine that powers the agent task. The default value is `skyvern-2.0`, the latest Skyvern agent that performs pretty well with complex and multi-step tasks. `skyvern-1.0` is good for simple tasks like filling a form, or searching for information on Google. The `openai-cua` engine uses OpenAI's CUA model. The `anthropic-cua` uses Anthropic's Claude Sonnet 3.7 model with the computer use tool. - - title : typing.Optional[str] - The title for the task - - proxy_location : typing.Optional[ProxyLocation] - - Geographic Proxy location to route the browser traffic through. This is only available in Skyvern Cloud. - - Available geotargeting options: - - RESIDENTIAL: the default value. Skyvern Cloud uses a random US residential proxy. - - RESIDENTIAL_ES: Spain - - RESIDENTIAL_IE: Ireland - - RESIDENTIAL_GB: United Kingdom - - RESIDENTIAL_IN: India - - RESIDENTIAL_JP: Japan - - RESIDENTIAL_FR: France - - RESIDENTIAL_DE: Germany - - RESIDENTIAL_NZ: New Zealand - - RESIDENTIAL_ZA: South Africa - - RESIDENTIAL_AR: Argentina - - RESIDENTIAL_ISP: ISP proxy - - US-CA: California - - US-NY: New York - - US-TX: Texas - - US-FL: Florida - - US-WA: Washington - - NONE: No proxy - - data_extraction_schema : typing.Optional[TaskRunRequestDataExtractionSchema] - - The schema for data to be extracted from the webpage. If you're looking for consistent data schema being returned by the agent, it's highly recommended to use https://json-schema.org/. - - error_code_mapping : typing.Optional[typing.Dict[str, typing.Optional[str]]] - - Custom mapping of error codes to error messages if Skyvern encounters an error. - - max_steps : typing.Optional[int] - - Maximum number of steps the task can take. Task will fail if it exceeds this number. Cautions: you are charged per step so please set this number to a reasonable value. Contact sales@skyvern.com for custom pricing. - - webhook_url : typing.Optional[str] - - URL to send task status updates to after a run is finished. Refer to https://docs.skyvern.com/running-tasks/webhooks-faq for more details. - - totp_identifier : typing.Optional[str] - - Identifier for the TOTP/2FA/MFA code when the code is pushed to Skyvern. Refer to https://docs.skyvern.com/credentials/totp#option-3-push-code-to-skyvern for more details. - - totp_url : typing.Optional[str] - - URL that serves TOTP/2FA/MFA codes for Skyvern to use during the workflow run. Refer to https://docs.skyvern.com/credentials/totp#option-2-get-code-from-your-endpoint for more details. - - browser_session_id : typing.Optional[str] - - Run the task or workflow in the specific Skyvern browser session. Having a browser session can persist the real-time state of the browser, so that the next run can continue from where the previous run left off. - - publish_workflow : typing.Optional[bool] - Whether to publish this task as a reusable workflow. Only available for skyvern-2.0. - - include_action_history_in_verification : typing.Optional[bool] - Whether to include action history when verifying that the task is complete - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - TaskRunResponse - Successfully run task - - Examples - -------- - import asyncio - - from skyvern import AsyncSkyvern - - client = AsyncSkyvern( - api_key="YOUR_API_KEY", - ) - - - async def main() -> None: - await client.agent.run_task( - prompt="Find the top 3 posts on Hacker News.", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/run/tasks", - method="POST", - json={ - "prompt": prompt, - "url": url, - "engine": engine, - "title": title, - "proxy_location": proxy_location, - "data_extraction_schema": convert_and_respect_annotation_metadata( - object_=data_extraction_schema, annotation=TaskRunRequestDataExtractionSchema, direction="write" - ), - "error_code_mapping": error_code_mapping, - "max_steps": max_steps, - "webhook_url": webhook_url, - "totp_identifier": totp_identifier, - "totp_url": totp_url, - "browser_session_id": browser_session_id, - "publish_workflow": publish_workflow, - "include_action_history_in_verification": include_action_history_in_verification, - }, - headers={ - "x-user-agent": str(user_agent) if user_agent is not None else None, - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - TaskRunResponse, - parse_obj_as( - type_=TaskRunResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def run_workflow( - self, - *, - workflow_id: str, - template: typing.Optional[bool] = None, - max_steps_override: typing.Optional[int] = None, - user_agent: typing.Optional[str] = None, - parameters: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, - title: typing.Optional[str] = OMIT, - proxy_location: typing.Optional[ProxyLocation] = OMIT, - webhook_url: typing.Optional[str] = OMIT, - totp_url: typing.Optional[str] = OMIT, - totp_identifier: typing.Optional[str] = OMIT, - browser_session_id: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> WorkflowRunResponse: - """ - Run a workflow - - Parameters - ---------- - workflow_id : str - ID of the workflow to run. Workflow ID starts with `wpid_`. - - template : typing.Optional[bool] - - max_steps_override : typing.Optional[int] - - user_agent : typing.Optional[str] - - parameters : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] - Parameters to pass to the workflow - - title : typing.Optional[str] - The title for this workflow run - - proxy_location : typing.Optional[ProxyLocation] - - Geographic Proxy location to route the browser traffic through. This is only available in Skyvern Cloud. - - Available geotargeting options: - - RESIDENTIAL: the default value. Skyvern Cloud uses a random US residential proxy. - - RESIDENTIAL_ES: Spain - - RESIDENTIAL_IE: Ireland - - RESIDENTIAL_GB: United Kingdom - - RESIDENTIAL_IN: India - - RESIDENTIAL_JP: Japan - - RESIDENTIAL_FR: France - - RESIDENTIAL_DE: Germany - - RESIDENTIAL_NZ: New Zealand - - RESIDENTIAL_ZA: South Africa - - RESIDENTIAL_AR: Argentina - - RESIDENTIAL_ISP: ISP proxy - - US-CA: California - - US-NY: New York - - US-TX: Texas - - US-FL: Florida - - US-WA: Washington - - NONE: No proxy - - webhook_url : typing.Optional[str] - URL to send workflow status updates to after a run is finished. Refer to https://docs.skyvern.com/running-tasks/webhooks-faq for webhook questions. - - totp_url : typing.Optional[str] - - URL that serves TOTP/2FA/MFA codes for Skyvern to use during the workflow run. Refer to https://docs.skyvern.com/credentials/totp#option-2-get-code-from-your-endpoint for more details. - - totp_identifier : typing.Optional[str] - - Identifier for the TOTP/2FA/MFA code when the code is pushed to Skyvern. Refer to https://docs.skyvern.com/credentials/totp#option-3-push-code-to-skyvern for more details. - - browser_session_id : typing.Optional[str] - ID of a Skyvern browser session to reuse, having it continue from the current screen state - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - WorkflowRunResponse - Successfully run workflow - - Examples - -------- - import asyncio - - from skyvern import AsyncSkyvern - - client = AsyncSkyvern( - api_key="YOUR_API_KEY", - ) - - - async def main() -> None: - await client.agent.run_workflow( - workflow_id="wpid_123", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/run/workflows", - method="POST", - params={ - "template": template, - }, - json={ - "workflow_id": workflow_id, - "parameters": parameters, - "title": title, - "proxy_location": proxy_location, - "webhook_url": webhook_url, - "totp_url": totp_url, - "totp_identifier": totp_identifier, - "browser_session_id": browser_session_id, - }, - headers={ - "x-max-steps-override": str(max_steps_override) if max_steps_override is not None else None, - "x-user-agent": str(user_agent) if user_agent is not None else None, - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - WorkflowRunResponse, - parse_obj_as( - type_=WorkflowRunResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def get_run( - self, run_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> AgentGetRunResponse: - """ - Get run information (task run, workflow run) - - Parameters - ---------- - run_id : str - The id of the task run or the workflow run. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - AgentGetRunResponse - Successfully got run - - Examples - -------- - import asyncio - - from skyvern import AsyncSkyvern - - client = AsyncSkyvern( - api_key="YOUR_API_KEY", - ) - - - async def main() -> None: - await client.agent.get_run( - run_id="tsk_123", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/runs/{jsonable_encoder(run_id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AgentGetRunResponse, - parse_obj_as( - type_=AgentGetRunResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 404: - raise NotFoundError( - 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def cancel_run( - self, run_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> typing.Optional[typing.Any]: - """ - Cancel a run (task or workflow) - - Parameters - ---------- - run_id : str - The id of the task run or the workflow run to cancel. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - Successful Response - - Examples - -------- - import asyncio - - from skyvern import AsyncSkyvern - - client = AsyncSkyvern( - api_key="YOUR_API_KEY", - ) - - - async def main() -> None: - await client.agent.cancel_run( - run_id="run_id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/runs/{jsonable_encoder(run_id)}/cancel", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def retry_run_webhook( - self, run_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> typing.Optional[typing.Any]: - """ - Retry sending the webhook for a run - - Parameters - ---------- - run_id : str - The id of the task run or the workflow run. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - Successful Response - - Examples - -------- - import asyncio - - from skyvern import AsyncSkyvern - - client = AsyncSkyvern( - api_key="YOUR_API_KEY", - ) - - - async def main() -> None: - await client.agent.retry_run_webhook( - run_id="tsk_123", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/runs/{jsonable_encoder(run_id)}/retry_webhook", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/skyvern/client/agent/types/__init__.py b/skyvern/client/agent/types/__init__.py deleted file mode 100644 index 82245e7d..00000000 --- a/skyvern/client/agent/types/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .agent_get_run_response import ( - AgentGetRunResponse, - AgentGetRunResponse_AnthropicCua, - AgentGetRunResponse_OpenaiCua, - AgentGetRunResponse_TaskV1, - AgentGetRunResponse_TaskV2, - AgentGetRunResponse_WorkflowRun, -) - -__all__ = [ - "AgentGetRunResponse", - "AgentGetRunResponse_AnthropicCua", - "AgentGetRunResponse_OpenaiCua", - "AgentGetRunResponse_TaskV1", - "AgentGetRunResponse_TaskV2", - "AgentGetRunResponse_WorkflowRun", -] diff --git a/skyvern/client/artifacts/__init__.py b/skyvern/client/artifacts/__init__.py deleted file mode 100644 index f3ea2659..00000000 --- a/skyvern/client/artifacts/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - diff --git a/skyvern/client/artifacts/client.py b/skyvern/client/artifacts/client.py deleted file mode 100644 index 1749accb..00000000 --- a/skyvern/client/artifacts/client.py +++ /dev/null @@ -1,165 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ..core.client_wrapper import SyncClientWrapper -import typing -from ..core.request_options import RequestOptions -from ..types.artifact import Artifact -from ..core.jsonable_encoder import jsonable_encoder -from ..core.pydantic_utilities import parse_obj_as -from ..errors.not_found_error import NotFoundError -from ..errors.unprocessable_entity_error import UnprocessableEntityError -from json.decoder import JSONDecodeError -from ..core.api_error import ApiError -from ..core.client_wrapper import AsyncClientWrapper - - -class ArtifactsClient: - def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper - - def get_artifact(self, artifact_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Artifact: - """ - Get an artifact - - Parameters - ---------- - artifact_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Artifact - Successfully retrieved artifact - - Examples - -------- - from skyvern import Skyvern - - client = Skyvern( - api_key="YOUR_API_KEY", - ) - client.artifacts.get_artifact( - artifact_id="artifact_id", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/artifacts/{jsonable_encoder(artifact_id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Artifact, - parse_obj_as( - type_=Artifact, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 404: - raise NotFoundError( - 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - -class AsyncArtifactsClient: - def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper - - async def get_artifact( - self, artifact_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> Artifact: - """ - Get an artifact - - Parameters - ---------- - artifact_id : str - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Artifact - Successfully retrieved artifact - - Examples - -------- - import asyncio - - from skyvern import AsyncSkyvern - - client = AsyncSkyvern( - api_key="YOUR_API_KEY", - ) - - - async def main() -> None: - await client.artifacts.get_artifact( - artifact_id="artifact_id", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/artifacts/{jsonable_encoder(artifact_id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Artifact, - parse_obj_as( - type_=Artifact, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 404: - raise NotFoundError( - 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/skyvern/client/browser_session/__init__.py b/skyvern/client/browser_session/__init__.py deleted file mode 100644 index f3ea2659..00000000 --- a/skyvern/client/browser_session/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - diff --git a/skyvern/client/browser_session/client.py b/skyvern/client/browser_session/client.py deleted file mode 100644 index c8b87408..00000000 --- a/skyvern/client/browser_session/client.py +++ /dev/null @@ -1,631 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -from ..core.client_wrapper import SyncClientWrapper -from ..core.request_options import RequestOptions -from ..types.browser_session_response import BrowserSessionResponse -from ..core.pydantic_utilities import parse_obj_as -from ..errors.forbidden_error import ForbiddenError -from ..errors.unprocessable_entity_error import UnprocessableEntityError -from json.decoder import JSONDecodeError -from ..core.api_error import ApiError -from ..core.jsonable_encoder import jsonable_encoder -from ..errors.not_found_error import NotFoundError -from ..core.client_wrapper import AsyncClientWrapper - -# this is used as the default value for optional parameters -OMIT = typing.cast(typing.Any, ...) - - -class BrowserSessionClient: - def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper - - def get_browser_sessions( - self, *, request_options: typing.Optional[RequestOptions] = None - ) -> typing.List[BrowserSessionResponse]: - """ - Get all active browser sessions for the organization - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.List[BrowserSessionResponse] - Successfully retrieved all active browser sessions - - Examples - -------- - from skyvern import Skyvern - - client = Skyvern( - api_key="YOUR_API_KEY", - ) - client.browser_session.get_browser_sessions() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/browser_sessions", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.List[BrowserSessionResponse], - parse_obj_as( - type_=typing.List[BrowserSessionResponse], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 403: - raise ForbiddenError( - 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def create_browser_session( - self, *, timeout: typing.Optional[int] = OMIT, request_options: typing.Optional[RequestOptions] = None - ) -> BrowserSessionResponse: - """ - Create a new browser session - - Parameters - ---------- - timeout : typing.Optional[int] - Timeout in minutes for the session. Timeout is applied after the session is started. Must be between 5 and 10080. Defaults to 60. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - BrowserSessionResponse - Successfully created browser session - - Examples - -------- - from skyvern import Skyvern - - client = Skyvern( - api_key="YOUR_API_KEY", - ) - client.browser_session.create_browser_session() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/browser_sessions", - method="POST", - json={ - "timeout": timeout, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - BrowserSessionResponse, - parse_obj_as( - type_=BrowserSessionResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 403: - raise ForbiddenError( - 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def close_browser_session( - self, browser_session_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> typing.Optional[typing.Any]: - """ - Close a browser session - - Parameters - ---------- - browser_session_id : str - The ID of the browser session to close. completed_at will be set when the browser session is closed. browser_session_id starts with `pbs_` - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - Successfully closed browser session - - Examples - -------- - from skyvern import Skyvern - - client = Skyvern( - api_key="YOUR_API_KEY", - ) - client.browser_session.close_browser_session( - browser_session_id="pbs_123456", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/browser_sessions/{jsonable_encoder(browser_session_id)}/close", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return 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( - 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def get_browser_session( - self, browser_session_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> BrowserSessionResponse: - """ - Get details about a specific browser session by ID - - Parameters - ---------- - browser_session_id : str - The ID of the browser session. browser_session_id starts with `pbs_` - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - BrowserSessionResponse - Successfully retrieved browser session details - - Examples - -------- - from skyvern import Skyvern - - client = Skyvern( - api_key="YOUR_API_KEY", - ) - client.browser_session.get_browser_session( - browser_session_id="pbs_123456", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/browser_sessions/{jsonable_encoder(browser_session_id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - BrowserSessionResponse, - parse_obj_as( - type_=BrowserSessionResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 403: - raise ForbiddenError( - 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( - 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - -class AsyncBrowserSessionClient: - def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper - - async def get_browser_sessions( - self, *, request_options: typing.Optional[RequestOptions] = None - ) -> typing.List[BrowserSessionResponse]: - """ - Get all active browser sessions for the organization - - Parameters - ---------- - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.List[BrowserSessionResponse] - Successfully retrieved all active browser sessions - - Examples - -------- - import asyncio - - from skyvern import AsyncSkyvern - - client = AsyncSkyvern( - api_key="YOUR_API_KEY", - ) - - - async def main() -> None: - await client.browser_session.get_browser_sessions() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/browser_sessions", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.List[BrowserSessionResponse], - parse_obj_as( - type_=typing.List[BrowserSessionResponse], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 403: - raise ForbiddenError( - 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def create_browser_session( - self, *, timeout: typing.Optional[int] = OMIT, request_options: typing.Optional[RequestOptions] = None - ) -> BrowserSessionResponse: - """ - Create a new browser session - - Parameters - ---------- - timeout : typing.Optional[int] - Timeout in minutes for the session. Timeout is applied after the session is started. Must be between 5 and 10080. Defaults to 60. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - BrowserSessionResponse - Successfully created browser session - - Examples - -------- - import asyncio - - from skyvern import AsyncSkyvern - - client = AsyncSkyvern( - api_key="YOUR_API_KEY", - ) - - - async def main() -> None: - await client.browser_session.create_browser_session() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/browser_sessions", - method="POST", - json={ - "timeout": timeout, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - BrowserSessionResponse, - parse_obj_as( - type_=BrowserSessionResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 403: - raise ForbiddenError( - 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def close_browser_session( - self, browser_session_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> typing.Optional[typing.Any]: - """ - Close a browser session - - Parameters - ---------- - browser_session_id : str - The ID of the browser session to close. completed_at will be set when the browser session is closed. browser_session_id starts with `pbs_` - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - Successfully closed browser session - - Examples - -------- - import asyncio - - from skyvern import AsyncSkyvern - - client = AsyncSkyvern( - api_key="YOUR_API_KEY", - ) - - - async def main() -> None: - await client.browser_session.close_browser_session( - browser_session_id="pbs_123456", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/browser_sessions/{jsonable_encoder(browser_session_id)}/close", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return 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( - 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def get_browser_session( - self, browser_session_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> BrowserSessionResponse: - """ - Get details about a specific browser session by ID - - Parameters - ---------- - browser_session_id : str - The ID of the browser session. browser_session_id starts with `pbs_` - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - BrowserSessionResponse - Successfully retrieved browser session details - - Examples - -------- - import asyncio - - from skyvern import AsyncSkyvern - - client = AsyncSkyvern( - api_key="YOUR_API_KEY", - ) - - - async def main() -> None: - await client.browser_session.get_browser_session( - browser_session_id="pbs_123456", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/browser_sessions/{jsonable_encoder(browser_session_id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - BrowserSessionResponse, - parse_obj_as( - type_=BrowserSessionResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 403: - raise ForbiddenError( - 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( - 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/skyvern/client/client.py b/skyvern/client/client.py index 87c3f256..1c08b30e 100644 --- a/skyvern/client/client.py +++ b/skyvern/client/client.py @@ -4,17 +4,35 @@ import typing from .environment import SkyvernEnvironment import httpx from .core.client_wrapper import SyncClientWrapper -from .agent.client import AgentClient -from .workflows.client import WorkflowsClient -from .artifacts.client import ArtifactsClient -from .browser_session.client import BrowserSessionClient -from .credentials.client import CredentialsClient +from .types.run_engine import RunEngine +from .types.proxy_location import ProxyLocation +from .types.task_run_request_data_extraction_schema import TaskRunRequestDataExtractionSchema +from .core.request_options import RequestOptions +from .types.task_run_response import TaskRunResponse +from .core.serialization import convert_and_respect_annotation_metadata +from .core.pydantic_utilities import parse_obj_as +from .errors.bad_request_error import BadRequestError +from .errors.unprocessable_entity_error import UnprocessableEntityError +from json.decoder import JSONDecodeError +from .core.api_error import ApiError +from .types.workflow_run_response import WorkflowRunResponse +from .types.get_run_response import GetRunResponse +from .core.jsonable_encoder import jsonable_encoder +from .errors.not_found_error import NotFoundError +from .types.workflow import Workflow +from .types.workflow_create_yaml_request import WorkflowCreateYamlRequest +from .types.artifact import Artifact +from .types.browser_session_response import BrowserSessionResponse +from .errors.forbidden_error import ForbiddenError +import datetime as dt +from .types.totp_code import TotpCode +from .types.credential_response import CredentialResponse +from .types.credential_type import CredentialType +from .types.create_credential_request_credential import CreateCredentialRequestCredential from .core.client_wrapper import AsyncClientWrapper -from .agent.client import AsyncAgentClient -from .workflows.client import AsyncWorkflowsClient -from .artifacts.client import AsyncArtifactsClient -from .browser_session.client import AsyncBrowserSessionClient -from .credentials.client import AsyncCredentialsClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) class Skyvern: @@ -75,11 +93,1526 @@ class Skyvern: else httpx.Client(timeout=_defaulted_timeout), timeout=_defaulted_timeout, ) - self.agent = AgentClient(client_wrapper=self._client_wrapper) - self.workflows = WorkflowsClient(client_wrapper=self._client_wrapper) - self.artifacts = ArtifactsClient(client_wrapper=self._client_wrapper) - self.browser_session = BrowserSessionClient(client_wrapper=self._client_wrapper) - self.credentials = CredentialsClient(client_wrapper=self._client_wrapper) + + def run_task( + self, + *, + prompt: str, + user_agent: typing.Optional[str] = None, + url: typing.Optional[str] = OMIT, + engine: typing.Optional[RunEngine] = OMIT, + title: typing.Optional[str] = OMIT, + proxy_location: typing.Optional[ProxyLocation] = OMIT, + data_extraction_schema: typing.Optional[TaskRunRequestDataExtractionSchema] = OMIT, + error_code_mapping: typing.Optional[typing.Dict[str, typing.Optional[str]]] = OMIT, + max_steps: typing.Optional[int] = OMIT, + webhook_url: typing.Optional[str] = OMIT, + totp_identifier: typing.Optional[str] = OMIT, + totp_url: typing.Optional[str] = OMIT, + browser_session_id: typing.Optional[str] = OMIT, + publish_workflow: typing.Optional[bool] = OMIT, + include_action_history_in_verification: typing.Optional[bool] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> TaskRunResponse: + """ + Run a task + + Parameters + ---------- + prompt : str + + The goal or task description for Skyvern to accomplish + + user_agent : typing.Optional[str] + + url : typing.Optional[str] + + The starting URL for the task. If not provided, Skyvern will attempt to determine an appropriate URL + + engine : typing.Optional[RunEngine] + + The engine that powers the agent task. The default value is `skyvern-2.0`, the latest Skyvern agent that performs pretty well with complex and multi-step tasks. `skyvern-1.0` is good for simple tasks like filling a form, or searching for information on Google. The `openai-cua` engine uses OpenAI's CUA model. The `anthropic-cua` uses Anthropic's Claude Sonnet 3.7 model with the computer use tool. + + title : typing.Optional[str] + The title for the task + + proxy_location : typing.Optional[ProxyLocation] + + Geographic Proxy location to route the browser traffic through. This is only available in Skyvern Cloud. + + Available geotargeting options: + - RESIDENTIAL: the default value. Skyvern Cloud uses a random US residential proxy. + - RESIDENTIAL_ES: Spain + - RESIDENTIAL_IE: Ireland + - RESIDENTIAL_GB: United Kingdom + - RESIDENTIAL_IN: India + - RESIDENTIAL_JP: Japan + - RESIDENTIAL_FR: France + - RESIDENTIAL_DE: Germany + - RESIDENTIAL_NZ: New Zealand + - RESIDENTIAL_ZA: South Africa + - RESIDENTIAL_AR: Argentina + - RESIDENTIAL_ISP: ISP proxy + - US-CA: California + - US-NY: New York + - US-TX: Texas + - US-FL: Florida + - US-WA: Washington + - NONE: No proxy + + data_extraction_schema : typing.Optional[TaskRunRequestDataExtractionSchema] + + The schema for data to be extracted from the webpage. If you're looking for consistent data schema being returned by the agent, it's highly recommended to use https://json-schema.org/. + + error_code_mapping : typing.Optional[typing.Dict[str, typing.Optional[str]]] + + Custom mapping of error codes to error messages if Skyvern encounters an error. + + max_steps : typing.Optional[int] + + Maximum number of steps the task can take. Task will fail if it exceeds this number. Cautions: you are charged per step so please set this number to a reasonable value. Contact sales@skyvern.com for custom pricing. + + webhook_url : typing.Optional[str] + + URL to send task status updates to after a run is finished. Refer to https://docs.skyvern.com/running-tasks/webhooks-faq for more details. + + totp_identifier : typing.Optional[str] + + Identifier for the TOTP/2FA/MFA code when the code is pushed to Skyvern. Refer to https://docs.skyvern.com/credentials/totp#option-3-push-code-to-skyvern for more details. + + totp_url : typing.Optional[str] + + URL that serves TOTP/2FA/MFA codes for Skyvern to use during the workflow run. Refer to https://docs.skyvern.com/credentials/totp#option-2-get-code-from-your-endpoint for more details. + + browser_session_id : typing.Optional[str] + + Run the task or workflow in the specific Skyvern browser session. Having a browser session can persist the real-time state of the browser, so that the next run can continue from where the previous run left off. + + publish_workflow : typing.Optional[bool] + Whether to publish this task as a reusable workflow. Only available for skyvern-2.0. + + include_action_history_in_verification : typing.Optional[bool] + Whether to include action history when verifying that the task is complete + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + TaskRunResponse + Successfully run task + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.run_task( + prompt="Find the top 3 posts on Hacker News.", + ) + """ + _response = self._client_wrapper.httpx_client.request( + "v1/run/tasks", + method="POST", + json={ + "prompt": prompt, + "url": url, + "engine": engine, + "title": title, + "proxy_location": proxy_location, + "data_extraction_schema": convert_and_respect_annotation_metadata( + object_=data_extraction_schema, annotation=TaskRunRequestDataExtractionSchema, direction="write" + ), + "error_code_mapping": error_code_mapping, + "max_steps": max_steps, + "webhook_url": webhook_url, + "totp_identifier": totp_identifier, + "totp_url": totp_url, + "browser_session_id": browser_session_id, + "publish_workflow": publish_workflow, + "include_action_history_in_verification": include_action_history_in_verification, + }, + headers={ + "x-user-agent": str(user_agent) if user_agent is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + TaskRunResponse, + parse_obj_as( + type_=TaskRunResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def run_workflow( + self, + *, + workflow_id: str, + template: typing.Optional[bool] = None, + max_steps_override: typing.Optional[int] = None, + user_agent: typing.Optional[str] = None, + parameters: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + title: typing.Optional[str] = OMIT, + proxy_location: typing.Optional[ProxyLocation] = OMIT, + webhook_url: typing.Optional[str] = OMIT, + totp_url: typing.Optional[str] = OMIT, + totp_identifier: typing.Optional[str] = OMIT, + browser_session_id: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> WorkflowRunResponse: + """ + Run a workflow + + Parameters + ---------- + workflow_id : str + ID of the workflow to run. Workflow ID starts with `wpid_`. + + template : typing.Optional[bool] + + max_steps_override : typing.Optional[int] + + user_agent : typing.Optional[str] + + parameters : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + Parameters to pass to the workflow + + title : typing.Optional[str] + The title for this workflow run + + proxy_location : typing.Optional[ProxyLocation] + + Geographic Proxy location to route the browser traffic through. This is only available in Skyvern Cloud. + + Available geotargeting options: + - RESIDENTIAL: the default value. Skyvern Cloud uses a random US residential proxy. + - RESIDENTIAL_ES: Spain + - RESIDENTIAL_IE: Ireland + - RESIDENTIAL_GB: United Kingdom + - RESIDENTIAL_IN: India + - RESIDENTIAL_JP: Japan + - RESIDENTIAL_FR: France + - RESIDENTIAL_DE: Germany + - RESIDENTIAL_NZ: New Zealand + - RESIDENTIAL_ZA: South Africa + - RESIDENTIAL_AR: Argentina + - RESIDENTIAL_ISP: ISP proxy + - US-CA: California + - US-NY: New York + - US-TX: Texas + - US-FL: Florida + - US-WA: Washington + - NONE: No proxy + + webhook_url : typing.Optional[str] + URL to send workflow status updates to after a run is finished. Refer to https://docs.skyvern.com/running-tasks/webhooks-faq for webhook questions. + + totp_url : typing.Optional[str] + + URL that serves TOTP/2FA/MFA codes for Skyvern to use during the workflow run. Refer to https://docs.skyvern.com/credentials/totp#option-2-get-code-from-your-endpoint for more details. + + totp_identifier : typing.Optional[str] + + Identifier for the TOTP/2FA/MFA code when the code is pushed to Skyvern. Refer to https://docs.skyvern.com/credentials/totp#option-3-push-code-to-skyvern for more details. + + browser_session_id : typing.Optional[str] + ID of a Skyvern browser session to reuse, having it continue from the current screen state + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WorkflowRunResponse + Successfully run workflow + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.run_workflow( + workflow_id="wpid_123", + ) + """ + _response = self._client_wrapper.httpx_client.request( + "v1/run/workflows", + method="POST", + params={ + "template": template, + }, + json={ + "workflow_id": workflow_id, + "parameters": parameters, + "title": title, + "proxy_location": proxy_location, + "webhook_url": webhook_url, + "totp_url": totp_url, + "totp_identifier": totp_identifier, + "browser_session_id": browser_session_id, + }, + headers={ + "x-max-steps-override": str(max_steps_override) if max_steps_override is not None else None, + "x-user-agent": str(user_agent) if user_agent is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + WorkflowRunResponse, + parse_obj_as( + type_=WorkflowRunResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_run(self, run_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> GetRunResponse: + """ + Get run information (task run, workflow run) + + Parameters + ---------- + run_id : str + The id of the task run or the workflow run. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + GetRunResponse + Successfully got run + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.get_run( + run_id="tsk_123", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/runs/{jsonable_encoder(run_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + GetRunResponse, + parse_obj_as( + type_=GetRunResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def cancel_run( + self, run_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Optional[typing.Any]: + """ + Cancel a run (task or workflow) + + Parameters + ---------- + run_id : str + The id of the task run or the workflow run to cancel. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Optional[typing.Any] + Successful Response + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.cancel_run( + run_id="run_id", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/runs/{jsonable_encoder(run_id)}/cancel", + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_workflows( + self, + *, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + only_saved_tasks: typing.Optional[bool] = None, + only_workflows: typing.Optional[bool] = None, + title: typing.Optional[str] = None, + template: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.List[Workflow]: + """ + Get all workflows with the latest version for the organization. + + Parameters + ---------- + page : typing.Optional[int] + + page_size : typing.Optional[int] + + only_saved_tasks : typing.Optional[bool] + + only_workflows : typing.Optional[bool] + + title : typing.Optional[str] + + template : typing.Optional[bool] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[Workflow] + Successful Response + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.get_workflows() + """ + _response = self._client_wrapper.httpx_client.request( + "v1/workflows", + method="GET", + params={ + "page": page, + "page_size": page_size, + "only_saved_tasks": only_saved_tasks, + "only_workflows": only_workflows, + "title": title, + "template": template, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + typing.List[Workflow], + parse_obj_as( + type_=typing.List[Workflow], # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def create_workflow( + self, + *, + json_definition: typing.Optional[WorkflowCreateYamlRequest] = OMIT, + yaml_definition: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Workflow: + """ + Create a new workflow + + Parameters + ---------- + json_definition : typing.Optional[WorkflowCreateYamlRequest] + Workflow definition in JSON format + + yaml_definition : typing.Optional[str] + Workflow definition in YAML format + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Workflow + Successfully created workflow + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.create_workflow() + """ + _response = self._client_wrapper.httpx_client.request( + "v1/workflows", + method="POST", + json={ + "json_definition": convert_and_respect_annotation_metadata( + object_=json_definition, annotation=WorkflowCreateYamlRequest, direction="write" + ), + "yaml_definition": yaml_definition, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Workflow, + parse_obj_as( + type_=Workflow, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def update_workflow( + self, + workflow_id: str, + *, + json_definition: typing.Optional[WorkflowCreateYamlRequest] = OMIT, + yaml_definition: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Workflow: + """ + Update a workflow + + Parameters + ---------- + workflow_id : str + The ID of the workflow to update. Workflow ID starts with `wpid_`. + + json_definition : typing.Optional[WorkflowCreateYamlRequest] + Workflow definition in JSON format + + yaml_definition : typing.Optional[str] + Workflow definition in YAML format + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Workflow + Successfully updated workflow + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.update_workflow( + workflow_id="wpid_123", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_id)}", + method="POST", + json={ + "json_definition": convert_and_respect_annotation_metadata( + object_=json_definition, annotation=WorkflowCreateYamlRequest, direction="write" + ), + "yaml_definition": yaml_definition, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Workflow, + parse_obj_as( + type_=Workflow, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def delete_workflow( + self, workflow_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Optional[typing.Any]: + """ + Delete a workflow + + Parameters + ---------- + workflow_id : str + The ID of the workflow to delete. Workflow ID starts with `wpid_`. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Optional[typing.Any] + Successfully deleted workflow + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.delete_workflow( + workflow_id="wpid_123", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_id)}/delete", + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_artifact(self, artifact_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Artifact: + """ + Get an artifact + + Parameters + ---------- + artifact_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Artifact + Successfully retrieved artifact + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.get_artifact( + artifact_id="artifact_id", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/artifacts/{jsonable_encoder(artifact_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Artifact, + parse_obj_as( + type_=Artifact, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def retry_run_webhook( + self, run_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Optional[typing.Any]: + """ + Retry sending the webhook for a run + + Parameters + ---------- + run_id : str + The id of the task run or the workflow run. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Optional[typing.Any] + Successful Response + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.retry_run_webhook( + run_id="tsk_123", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/runs/{jsonable_encoder(run_id)}/retry_webhook", + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_browser_sessions( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.List[BrowserSessionResponse]: + """ + Get all active browser sessions for the organization + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[BrowserSessionResponse] + Successfully retrieved all active browser sessions + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.get_browser_sessions() + """ + _response = self._client_wrapper.httpx_client.request( + "v1/browser_sessions", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + typing.List[BrowserSessionResponse], + parse_obj_as( + type_=typing.List[BrowserSessionResponse], # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def create_browser_session( + self, *, timeout: typing.Optional[int] = OMIT, request_options: typing.Optional[RequestOptions] = None + ) -> BrowserSessionResponse: + """ + Create a new browser session + + Parameters + ---------- + timeout : typing.Optional[int] + Timeout in minutes for the session. Timeout is applied after the session is started. Must be between 5 and 10080. Defaults to 60. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + BrowserSessionResponse + Successfully created browser session + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.create_browser_session() + """ + _response = self._client_wrapper.httpx_client.request( + "v1/browser_sessions", + method="POST", + json={ + "timeout": timeout, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + BrowserSessionResponse, + parse_obj_as( + type_=BrowserSessionResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def close_browser_session( + self, browser_session_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Optional[typing.Any]: + """ + Close a browser session + + Parameters + ---------- + browser_session_id : str + The ID of the browser session to close. completed_at will be set when the browser session is closed. browser_session_id starts with `pbs_` + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Optional[typing.Any] + Successfully closed browser session + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.close_browser_session( + browser_session_id="pbs_123456", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/browser_sessions/{jsonable_encoder(browser_session_id)}/close", + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return 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( + 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_browser_session( + self, browser_session_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> BrowserSessionResponse: + """ + Get details about a specific browser session by ID + + Parameters + ---------- + browser_session_id : str + The ID of the browser session. browser_session_id starts with `pbs_` + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + BrowserSessionResponse + Successfully retrieved browser session details + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.get_browser_session( + browser_session_id="pbs_123456", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/browser_sessions/{jsonable_encoder(browser_session_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + BrowserSessionResponse, + parse_obj_as( + type_=BrowserSessionResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + 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( + 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def send_totp_code( + self, + *, + totp_identifier: str, + content: str, + task_id: typing.Optional[str] = OMIT, + workflow_id: typing.Optional[str] = OMIT, + workflow_run_id: typing.Optional[str] = OMIT, + source: typing.Optional[str] = OMIT, + expired_at: typing.Optional[dt.datetime] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> TotpCode: + """ + Forward a TOTP (2FA, MFA) email or sms message containing the code to Skyvern. This endpoint stores the code in database so that Skyvern can use it while running tasks/workflows. + + Parameters + ---------- + totp_identifier : str + The identifier of the TOTP code. It can be the email address, phone number, or the identifier of the user. + + content : str + The content of the TOTP code. It can be the email content that contains the TOTP code, or the sms message that contains the TOTP code. Skyvern will automatically extract the TOTP code from the content. + + task_id : typing.Optional[str] + The task_id the totp code is for. It can be the task_id of the task that the TOTP code is for. + + workflow_id : typing.Optional[str] + The workflow ID the TOTP code is for. It can be the workflow ID of the workflow that the TOTP code is for. + + workflow_run_id : typing.Optional[str] + The workflow run id that the TOTP code is for. It can be the workflow run id of the workflow run that the TOTP code is for. + + source : typing.Optional[str] + An optional field. The source of the TOTP code. e.g. email, sms, etc. + + expired_at : typing.Optional[dt.datetime] + The timestamp when the TOTP code expires + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + TotpCode + Successful Response + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.send_totp_code( + totp_identifier="john.doe@example.com", + content="Hello, your verification code is 123456", + ) + """ + _response = self._client_wrapper.httpx_client.request( + "v1/credentials/totp", + method="POST", + json={ + "totp_identifier": totp_identifier, + "task_id": task_id, + "workflow_id": workflow_id, + "workflow_run_id": workflow_run_id, + "source": source, + "content": content, + "expired_at": expired_at, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + TotpCode, + parse_obj_as( + type_=TotpCode, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_credentials( + self, + *, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.List[CredentialResponse]: + """ + Retrieves a paginated list of credentials for the current organization + + Parameters + ---------- + page : typing.Optional[int] + Page number for pagination + + page_size : typing.Optional[int] + Number of items per page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[CredentialResponse] + Successful Response + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.get_credentials() + """ + _response = self._client_wrapper.httpx_client.request( + "v1/credentials", + method="GET", + params={ + "page": page, + "page_size": page_size, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + typing.List[CredentialResponse], + parse_obj_as( + type_=typing.List[CredentialResponse], # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def create_credential( + self, + *, + name: str, + credential_type: CredentialType, + credential: CreateCredentialRequestCredential, + request_options: typing.Optional[RequestOptions] = None, + ) -> CredentialResponse: + """ + Creates a new credential for the current organization + + Parameters + ---------- + name : str + Name of the credential + + credential_type : CredentialType + Type of credential to create + + credential : CreateCredentialRequestCredential + The credential data to store + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CredentialResponse + Successful Response + + Examples + -------- + from skyvern import NonEmptyPasswordCredential, Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.create_credential( + name="My Credential", + credential_type="password", + credential=NonEmptyPasswordCredential( + password="securepassword123", + username="user@example.com", + totp="JBSWY3DPEHPK3PXP", + ), + ) + """ + _response = self._client_wrapper.httpx_client.request( + "v1/credentials", + method="POST", + json={ + "name": name, + "credential_type": credential_type, + "credential": convert_and_respect_annotation_metadata( + object_=credential, annotation=CreateCredentialRequestCredential, direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CredentialResponse, + parse_obj_as( + type_=CredentialResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def delete_credential(self, credential_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: + """ + Deletes a specific credential by its ID + + Parameters + ---------- + credential_id : str + The unique identifier of the credential to delete + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.delete_credential( + credential_id="cred_1234567890", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/credentials/{jsonable_encoder(credential_id)}/delete", + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 422: + raise UnprocessableEntityError( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_credential( + self, credential_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> CredentialResponse: + """ + Retrieves a specific credential by its ID + + Parameters + ---------- + credential_id : str + The unique identifier of the credential + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CredentialResponse + Successful Response + + Examples + -------- + from skyvern import Skyvern + + client = Skyvern( + api_key="YOUR_API_KEY", + ) + client.get_credential( + credential_id="cred_1234567890", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/credentials/{jsonable_encoder(credential_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CredentialResponse, + parse_obj_as( + type_=CredentialResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) class AsyncSkyvern: @@ -140,11 +1673,1682 @@ class AsyncSkyvern: else httpx.AsyncClient(timeout=_defaulted_timeout), timeout=_defaulted_timeout, ) - self.agent = AsyncAgentClient(client_wrapper=self._client_wrapper) - self.workflows = AsyncWorkflowsClient(client_wrapper=self._client_wrapper) - self.artifacts = AsyncArtifactsClient(client_wrapper=self._client_wrapper) - self.browser_session = AsyncBrowserSessionClient(client_wrapper=self._client_wrapper) - self.credentials = AsyncCredentialsClient(client_wrapper=self._client_wrapper) + + async def run_task( + self, + *, + prompt: str, + user_agent: typing.Optional[str] = None, + url: typing.Optional[str] = OMIT, + engine: typing.Optional[RunEngine] = OMIT, + title: typing.Optional[str] = OMIT, + proxy_location: typing.Optional[ProxyLocation] = OMIT, + data_extraction_schema: typing.Optional[TaskRunRequestDataExtractionSchema] = OMIT, + error_code_mapping: typing.Optional[typing.Dict[str, typing.Optional[str]]] = OMIT, + max_steps: typing.Optional[int] = OMIT, + webhook_url: typing.Optional[str] = OMIT, + totp_identifier: typing.Optional[str] = OMIT, + totp_url: typing.Optional[str] = OMIT, + browser_session_id: typing.Optional[str] = OMIT, + publish_workflow: typing.Optional[bool] = OMIT, + include_action_history_in_verification: typing.Optional[bool] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> TaskRunResponse: + """ + Run a task + + Parameters + ---------- + prompt : str + + The goal or task description for Skyvern to accomplish + + user_agent : typing.Optional[str] + + url : typing.Optional[str] + + The starting URL for the task. If not provided, Skyvern will attempt to determine an appropriate URL + + engine : typing.Optional[RunEngine] + + The engine that powers the agent task. The default value is `skyvern-2.0`, the latest Skyvern agent that performs pretty well with complex and multi-step tasks. `skyvern-1.0` is good for simple tasks like filling a form, or searching for information on Google. The `openai-cua` engine uses OpenAI's CUA model. The `anthropic-cua` uses Anthropic's Claude Sonnet 3.7 model with the computer use tool. + + title : typing.Optional[str] + The title for the task + + proxy_location : typing.Optional[ProxyLocation] + + Geographic Proxy location to route the browser traffic through. This is only available in Skyvern Cloud. + + Available geotargeting options: + - RESIDENTIAL: the default value. Skyvern Cloud uses a random US residential proxy. + - RESIDENTIAL_ES: Spain + - RESIDENTIAL_IE: Ireland + - RESIDENTIAL_GB: United Kingdom + - RESIDENTIAL_IN: India + - RESIDENTIAL_JP: Japan + - RESIDENTIAL_FR: France + - RESIDENTIAL_DE: Germany + - RESIDENTIAL_NZ: New Zealand + - RESIDENTIAL_ZA: South Africa + - RESIDENTIAL_AR: Argentina + - RESIDENTIAL_ISP: ISP proxy + - US-CA: California + - US-NY: New York + - US-TX: Texas + - US-FL: Florida + - US-WA: Washington + - NONE: No proxy + + data_extraction_schema : typing.Optional[TaskRunRequestDataExtractionSchema] + + The schema for data to be extracted from the webpage. If you're looking for consistent data schema being returned by the agent, it's highly recommended to use https://json-schema.org/. + + error_code_mapping : typing.Optional[typing.Dict[str, typing.Optional[str]]] + + Custom mapping of error codes to error messages if Skyvern encounters an error. + + max_steps : typing.Optional[int] + + Maximum number of steps the task can take. Task will fail if it exceeds this number. Cautions: you are charged per step so please set this number to a reasonable value. Contact sales@skyvern.com for custom pricing. + + webhook_url : typing.Optional[str] + + URL to send task status updates to after a run is finished. Refer to https://docs.skyvern.com/running-tasks/webhooks-faq for more details. + + totp_identifier : typing.Optional[str] + + Identifier for the TOTP/2FA/MFA code when the code is pushed to Skyvern. Refer to https://docs.skyvern.com/credentials/totp#option-3-push-code-to-skyvern for more details. + + totp_url : typing.Optional[str] + + URL that serves TOTP/2FA/MFA codes for Skyvern to use during the workflow run. Refer to https://docs.skyvern.com/credentials/totp#option-2-get-code-from-your-endpoint for more details. + + browser_session_id : typing.Optional[str] + + Run the task or workflow in the specific Skyvern browser session. Having a browser session can persist the real-time state of the browser, so that the next run can continue from where the previous run left off. + + publish_workflow : typing.Optional[bool] + Whether to publish this task as a reusable workflow. Only available for skyvern-2.0. + + include_action_history_in_verification : typing.Optional[bool] + Whether to include action history when verifying that the task is complete + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + TaskRunResponse + Successfully run task + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.run_task( + prompt="Find the top 3 posts on Hacker News.", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + "v1/run/tasks", + method="POST", + json={ + "prompt": prompt, + "url": url, + "engine": engine, + "title": title, + "proxy_location": proxy_location, + "data_extraction_schema": convert_and_respect_annotation_metadata( + object_=data_extraction_schema, annotation=TaskRunRequestDataExtractionSchema, direction="write" + ), + "error_code_mapping": error_code_mapping, + "max_steps": max_steps, + "webhook_url": webhook_url, + "totp_identifier": totp_identifier, + "totp_url": totp_url, + "browser_session_id": browser_session_id, + "publish_workflow": publish_workflow, + "include_action_history_in_verification": include_action_history_in_verification, + }, + headers={ + "x-user-agent": str(user_agent) if user_agent is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + TaskRunResponse, + parse_obj_as( + type_=TaskRunResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def run_workflow( + self, + *, + workflow_id: str, + template: typing.Optional[bool] = None, + max_steps_override: typing.Optional[int] = None, + user_agent: typing.Optional[str] = None, + parameters: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + title: typing.Optional[str] = OMIT, + proxy_location: typing.Optional[ProxyLocation] = OMIT, + webhook_url: typing.Optional[str] = OMIT, + totp_url: typing.Optional[str] = OMIT, + totp_identifier: typing.Optional[str] = OMIT, + browser_session_id: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> WorkflowRunResponse: + """ + Run a workflow + + Parameters + ---------- + workflow_id : str + ID of the workflow to run. Workflow ID starts with `wpid_`. + + template : typing.Optional[bool] + + max_steps_override : typing.Optional[int] + + user_agent : typing.Optional[str] + + parameters : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + Parameters to pass to the workflow + + title : typing.Optional[str] + The title for this workflow run + + proxy_location : typing.Optional[ProxyLocation] + + Geographic Proxy location to route the browser traffic through. This is only available in Skyvern Cloud. + + Available geotargeting options: + - RESIDENTIAL: the default value. Skyvern Cloud uses a random US residential proxy. + - RESIDENTIAL_ES: Spain + - RESIDENTIAL_IE: Ireland + - RESIDENTIAL_GB: United Kingdom + - RESIDENTIAL_IN: India + - RESIDENTIAL_JP: Japan + - RESIDENTIAL_FR: France + - RESIDENTIAL_DE: Germany + - RESIDENTIAL_NZ: New Zealand + - RESIDENTIAL_ZA: South Africa + - RESIDENTIAL_AR: Argentina + - RESIDENTIAL_ISP: ISP proxy + - US-CA: California + - US-NY: New York + - US-TX: Texas + - US-FL: Florida + - US-WA: Washington + - NONE: No proxy + + webhook_url : typing.Optional[str] + URL to send workflow status updates to after a run is finished. Refer to https://docs.skyvern.com/running-tasks/webhooks-faq for webhook questions. + + totp_url : typing.Optional[str] + + URL that serves TOTP/2FA/MFA codes for Skyvern to use during the workflow run. Refer to https://docs.skyvern.com/credentials/totp#option-2-get-code-from-your-endpoint for more details. + + totp_identifier : typing.Optional[str] + + Identifier for the TOTP/2FA/MFA code when the code is pushed to Skyvern. Refer to https://docs.skyvern.com/credentials/totp#option-3-push-code-to-skyvern for more details. + + browser_session_id : typing.Optional[str] + ID of a Skyvern browser session to reuse, having it continue from the current screen state + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WorkflowRunResponse + Successfully run workflow + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.run_workflow( + workflow_id="wpid_123", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + "v1/run/workflows", + method="POST", + params={ + "template": template, + }, + json={ + "workflow_id": workflow_id, + "parameters": parameters, + "title": title, + "proxy_location": proxy_location, + "webhook_url": webhook_url, + "totp_url": totp_url, + "totp_identifier": totp_identifier, + "browser_session_id": browser_session_id, + }, + headers={ + "x-max-steps-override": str(max_steps_override) if max_steps_override is not None else None, + "x-user-agent": str(user_agent) if user_agent is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + WorkflowRunResponse, + parse_obj_as( + type_=WorkflowRunResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_run(self, run_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> GetRunResponse: + """ + Get run information (task run, workflow run) + + Parameters + ---------- + run_id : str + The id of the task run or the workflow run. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + GetRunResponse + Successfully got run + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.get_run( + run_id="tsk_123", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/runs/{jsonable_encoder(run_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + GetRunResponse, + parse_obj_as( + type_=GetRunResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def cancel_run( + self, run_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Optional[typing.Any]: + """ + Cancel a run (task or workflow) + + Parameters + ---------- + run_id : str + The id of the task run or the workflow run to cancel. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Optional[typing.Any] + Successful Response + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.cancel_run( + run_id="run_id", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/runs/{jsonable_encoder(run_id)}/cancel", + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_workflows( + self, + *, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + only_saved_tasks: typing.Optional[bool] = None, + only_workflows: typing.Optional[bool] = None, + title: typing.Optional[str] = None, + template: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.List[Workflow]: + """ + Get all workflows with the latest version for the organization. + + Parameters + ---------- + page : typing.Optional[int] + + page_size : typing.Optional[int] + + only_saved_tasks : typing.Optional[bool] + + only_workflows : typing.Optional[bool] + + title : typing.Optional[str] + + template : typing.Optional[bool] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[Workflow] + Successful Response + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.get_workflows() + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + "v1/workflows", + method="GET", + params={ + "page": page, + "page_size": page_size, + "only_saved_tasks": only_saved_tasks, + "only_workflows": only_workflows, + "title": title, + "template": template, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + typing.List[Workflow], + parse_obj_as( + type_=typing.List[Workflow], # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def create_workflow( + self, + *, + json_definition: typing.Optional[WorkflowCreateYamlRequest] = OMIT, + yaml_definition: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Workflow: + """ + Create a new workflow + + Parameters + ---------- + json_definition : typing.Optional[WorkflowCreateYamlRequest] + Workflow definition in JSON format + + yaml_definition : typing.Optional[str] + Workflow definition in YAML format + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Workflow + Successfully created workflow + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.create_workflow() + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + "v1/workflows", + method="POST", + json={ + "json_definition": convert_and_respect_annotation_metadata( + object_=json_definition, annotation=WorkflowCreateYamlRequest, direction="write" + ), + "yaml_definition": yaml_definition, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Workflow, + parse_obj_as( + type_=Workflow, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def update_workflow( + self, + workflow_id: str, + *, + json_definition: typing.Optional[WorkflowCreateYamlRequest] = OMIT, + yaml_definition: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Workflow: + """ + Update a workflow + + Parameters + ---------- + workflow_id : str + The ID of the workflow to update. Workflow ID starts with `wpid_`. + + json_definition : typing.Optional[WorkflowCreateYamlRequest] + Workflow definition in JSON format + + yaml_definition : typing.Optional[str] + Workflow definition in YAML format + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Workflow + Successfully updated workflow + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.update_workflow( + workflow_id="wpid_123", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_id)}", + method="POST", + json={ + "json_definition": convert_and_respect_annotation_metadata( + object_=json_definition, annotation=WorkflowCreateYamlRequest, direction="write" + ), + "yaml_definition": yaml_definition, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Workflow, + parse_obj_as( + type_=Workflow, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def delete_workflow( + self, workflow_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Optional[typing.Any]: + """ + Delete a workflow + + Parameters + ---------- + workflow_id : str + The ID of the workflow to delete. Workflow ID starts with `wpid_`. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Optional[typing.Any] + Successfully deleted workflow + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.delete_workflow( + workflow_id="wpid_123", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/workflows/{jsonable_encoder(workflow_id)}/delete", + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_artifact( + self, artifact_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> Artifact: + """ + Get an artifact + + Parameters + ---------- + artifact_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Artifact + Successfully retrieved artifact + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.get_artifact( + artifact_id="artifact_id", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/artifacts/{jsonable_encoder(artifact_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Artifact, + parse_obj_as( + type_=Artifact, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def retry_run_webhook( + self, run_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Optional[typing.Any]: + """ + Retry sending the webhook for a run + + Parameters + ---------- + run_id : str + The id of the task run or the workflow run. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Optional[typing.Any] + Successful Response + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.retry_run_webhook( + run_id="tsk_123", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/runs/{jsonable_encoder(run_id)}/retry_webhook", + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_browser_sessions( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.List[BrowserSessionResponse]: + """ + Get all active browser sessions for the organization + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[BrowserSessionResponse] + Successfully retrieved all active browser sessions + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.get_browser_sessions() + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + "v1/browser_sessions", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + typing.List[BrowserSessionResponse], + parse_obj_as( + type_=typing.List[BrowserSessionResponse], # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def create_browser_session( + self, *, timeout: typing.Optional[int] = OMIT, request_options: typing.Optional[RequestOptions] = None + ) -> BrowserSessionResponse: + """ + Create a new browser session + + Parameters + ---------- + timeout : typing.Optional[int] + Timeout in minutes for the session. Timeout is applied after the session is started. Must be between 5 and 10080. Defaults to 60. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + BrowserSessionResponse + Successfully created browser session + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.create_browser_session() + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + "v1/browser_sessions", + method="POST", + json={ + "timeout": timeout, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + BrowserSessionResponse, + parse_obj_as( + type_=BrowserSessionResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def close_browser_session( + self, browser_session_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> typing.Optional[typing.Any]: + """ + Close a browser session + + Parameters + ---------- + browser_session_id : str + The ID of the browser session to close. completed_at will be set when the browser session is closed. browser_session_id starts with `pbs_` + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Optional[typing.Any] + Successfully closed browser session + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.close_browser_session( + browser_session_id="pbs_123456", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/browser_sessions/{jsonable_encoder(browser_session_id)}/close", + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return 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( + 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_browser_session( + self, browser_session_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> BrowserSessionResponse: + """ + Get details about a specific browser session by ID + + Parameters + ---------- + browser_session_id : str + The ID of the browser session. browser_session_id starts with `pbs_` + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + BrowserSessionResponse + Successfully retrieved browser session details + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.get_browser_session( + browser_session_id="pbs_123456", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/browser_sessions/{jsonable_encoder(browser_session_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + BrowserSessionResponse, + parse_obj_as( + type_=BrowserSessionResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + 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( + 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( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def send_totp_code( + self, + *, + totp_identifier: str, + content: str, + task_id: typing.Optional[str] = OMIT, + workflow_id: typing.Optional[str] = OMIT, + workflow_run_id: typing.Optional[str] = OMIT, + source: typing.Optional[str] = OMIT, + expired_at: typing.Optional[dt.datetime] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> TotpCode: + """ + Forward a TOTP (2FA, MFA) email or sms message containing the code to Skyvern. This endpoint stores the code in database so that Skyvern can use it while running tasks/workflows. + + Parameters + ---------- + totp_identifier : str + The identifier of the TOTP code. It can be the email address, phone number, or the identifier of the user. + + content : str + The content of the TOTP code. It can be the email content that contains the TOTP code, or the sms message that contains the TOTP code. Skyvern will automatically extract the TOTP code from the content. + + task_id : typing.Optional[str] + The task_id the totp code is for. It can be the task_id of the task that the TOTP code is for. + + workflow_id : typing.Optional[str] + The workflow ID the TOTP code is for. It can be the workflow ID of the workflow that the TOTP code is for. + + workflow_run_id : typing.Optional[str] + The workflow run id that the TOTP code is for. It can be the workflow run id of the workflow run that the TOTP code is for. + + source : typing.Optional[str] + An optional field. The source of the TOTP code. e.g. email, sms, etc. + + expired_at : typing.Optional[dt.datetime] + The timestamp when the TOTP code expires + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + TotpCode + Successful Response + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.send_totp_code( + totp_identifier="john.doe@example.com", + content="Hello, your verification code is 123456", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + "v1/credentials/totp", + method="POST", + json={ + "totp_identifier": totp_identifier, + "task_id": task_id, + "workflow_id": workflow_id, + "workflow_run_id": workflow_run_id, + "source": source, + "content": content, + "expired_at": expired_at, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + TotpCode, + parse_obj_as( + type_=TotpCode, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_credentials( + self, + *, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.List[CredentialResponse]: + """ + Retrieves a paginated list of credentials for the current organization + + Parameters + ---------- + page : typing.Optional[int] + Page number for pagination + + page_size : typing.Optional[int] + Number of items per page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[CredentialResponse] + Successful Response + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.get_credentials() + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + "v1/credentials", + method="GET", + params={ + "page": page, + "page_size": page_size, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + typing.List[CredentialResponse], + parse_obj_as( + type_=typing.List[CredentialResponse], # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def create_credential( + self, + *, + name: str, + credential_type: CredentialType, + credential: CreateCredentialRequestCredential, + request_options: typing.Optional[RequestOptions] = None, + ) -> CredentialResponse: + """ + Creates a new credential for the current organization + + Parameters + ---------- + name : str + Name of the credential + + credential_type : CredentialType + Type of credential to create + + credential : CreateCredentialRequestCredential + The credential data to store + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CredentialResponse + Successful Response + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern, NonEmptyPasswordCredential + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.create_credential( + name="My Credential", + credential_type="password", + credential=NonEmptyPasswordCredential( + password="securepassword123", + username="user@example.com", + totp="JBSWY3DPEHPK3PXP", + ), + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + "v1/credentials", + method="POST", + json={ + "name": name, + "credential_type": credential_type, + "credential": convert_and_respect_annotation_metadata( + object_=credential, annotation=CreateCredentialRequestCredential, direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CredentialResponse, + parse_obj_as( + type_=CredentialResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def delete_credential( + self, credential_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + Deletes a specific credential by its ID + + Parameters + ---------- + credential_id : str + The unique identifier of the credential to delete + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.delete_credential( + credential_id="cred_1234567890", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/credentials/{jsonable_encoder(credential_id)}/delete", + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 422: + raise UnprocessableEntityError( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_credential( + self, credential_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> CredentialResponse: + """ + Retrieves a specific credential by its ID + + Parameters + ---------- + credential_id : str + The unique identifier of the credential + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CredentialResponse + Successful Response + + Examples + -------- + import asyncio + + from skyvern import AsyncSkyvern + + client = AsyncSkyvern( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.get_credential( + credential_id="cred_1234567890", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/credentials/{jsonable_encoder(credential_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CredentialResponse, + parse_obj_as( + type_=CredentialResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 422: + raise UnprocessableEntityError( + 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, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) def _get_base_url(*, base_url: typing.Optional[str] = None, environment: SkyvernEnvironment) -> str: diff --git a/skyvern/client/credentials/__init__.py b/skyvern/client/credentials/__init__.py deleted file mode 100644 index 291b4a02..00000000 --- a/skyvern/client/credentials/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .types import CreateCredentialRequestCredential - -__all__ = ["CreateCredentialRequestCredential"] diff --git a/skyvern/client/credentials/client.py b/skyvern/client/credentials/client.py deleted file mode 100644 index 2699d800..00000000 --- a/skyvern/client/credentials/client.py +++ /dev/null @@ -1,800 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -from ..core.client_wrapper import SyncClientWrapper -import datetime as dt -from ..core.request_options import RequestOptions -from ..types.totp_code import TotpCode -from ..core.pydantic_utilities import parse_obj_as -from ..errors.unprocessable_entity_error import UnprocessableEntityError -from json.decoder import JSONDecodeError -from ..core.api_error import ApiError -from ..types.credential_response import CredentialResponse -from ..types.credential_type import CredentialType -from .types.create_credential_request_credential import CreateCredentialRequestCredential -from ..core.serialization import convert_and_respect_annotation_metadata -from ..core.jsonable_encoder import jsonable_encoder -from ..core.client_wrapper import AsyncClientWrapper - -# this is used as the default value for optional parameters -OMIT = typing.cast(typing.Any, ...) - - -class CredentialsClient: - def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper - - def send_totp_code( - self, - *, - totp_identifier: str, - content: str, - task_id: typing.Optional[str] = OMIT, - workflow_id: typing.Optional[str] = OMIT, - workflow_run_id: typing.Optional[str] = OMIT, - source: typing.Optional[str] = OMIT, - expired_at: typing.Optional[dt.datetime] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> TotpCode: - """ - Forward a TOTP (2FA, MFA) email or sms message containing the code to Skyvern. This endpoint stores the code in database so that Skyvern can use it while running tasks/workflows. - - Parameters - ---------- - totp_identifier : str - The identifier of the TOTP code. It can be the email address, phone number, or the identifier of the user. - - content : str - The content of the TOTP code. It can be the email content that contains the TOTP code, or the sms message that contains the TOTP code. Skyvern will automatically extract the TOTP code from the content. - - task_id : typing.Optional[str] - The task_id the totp code is for. It can be the task_id of the task that the TOTP code is for. - - workflow_id : typing.Optional[str] - The workflow ID the TOTP code is for. It can be the workflow ID of the workflow that the TOTP code is for. - - workflow_run_id : typing.Optional[str] - The workflow run id that the TOTP code is for. It can be the workflow run id of the workflow run that the TOTP code is for. - - source : typing.Optional[str] - An optional field. The source of the TOTP code. e.g. email, sms, etc. - - expired_at : typing.Optional[dt.datetime] - The timestamp when the TOTP code expires - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - TotpCode - Successful Response - - Examples - -------- - from skyvern import Skyvern - - client = Skyvern( - api_key="YOUR_API_KEY", - ) - client.credentials.send_totp_code( - totp_identifier="john.doe@example.com", - content="Hello, your verification code is 123456", - ) - """ - _response = self._client_wrapper.httpx_client.request( - "v1/credentials/totp", - method="POST", - json={ - "totp_identifier": totp_identifier, - "task_id": task_id, - "workflow_id": workflow_id, - "workflow_run_id": workflow_run_id, - "source": source, - "content": content, - "expired_at": expired_at, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - TotpCode, - parse_obj_as( - type_=TotpCode, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 422: - raise UnprocessableEntityError( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def get_credentials( - self, - *, - page: typing.Optional[int] = None, - page_size: typing.Optional[int] = None, - request_options: typing.Optional[RequestOptions] = None, - ) -> typing.List[CredentialResponse]: - """ - Retrieves a paginated list of credentials for the current organization - - Parameters - ---------- - page : typing.Optional[int] - Page number for pagination - - page_size : typing.Optional[int] - Number of items per page - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.List[CredentialResponse] - Successful Response - - Examples - -------- - from skyvern import Skyvern - - client = Skyvern( - api_key="YOUR_API_KEY", - ) - client.credentials.get_credentials() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/credentials", - method="GET", - params={ - "page": page, - "page_size": page_size, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.List[CredentialResponse], - parse_obj_as( - type_=typing.List[CredentialResponse], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 422: - raise UnprocessableEntityError( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def create_credential( - self, - *, - name: str, - credential_type: CredentialType, - credential: CreateCredentialRequestCredential, - request_options: typing.Optional[RequestOptions] = None, - ) -> CredentialResponse: - """ - Creates a new credential for the current organization - - Parameters - ---------- - name : str - Name of the credential - - credential_type : CredentialType - Type of credential to create - - credential : CreateCredentialRequestCredential - The credential data to store - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - CredentialResponse - Successful Response - - Examples - -------- - from skyvern import NonEmptyPasswordCredential, Skyvern - - client = Skyvern( - api_key="YOUR_API_KEY", - ) - client.credentials.create_credential( - name="My Credential", - credential_type="password", - credential=NonEmptyPasswordCredential( - password="securepassword123", - username="user@example.com", - totp="JBSWY3DPEHPK3PXP", - ), - ) - """ - _response = self._client_wrapper.httpx_client.request( - "v1/credentials", - method="POST", - json={ - "name": name, - "credential_type": credential_type, - "credential": convert_and_respect_annotation_metadata( - object_=credential, annotation=CreateCredentialRequestCredential, direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CredentialResponse, - parse_obj_as( - type_=CredentialResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 422: - raise UnprocessableEntityError( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def delete_credential(self, credential_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Deletes a specific credential by its ID - - Parameters - ---------- - credential_id : str - The unique identifier of the credential to delete - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from skyvern import Skyvern - - client = Skyvern( - api_key="YOUR_API_KEY", - ) - client.credentials.delete_credential( - credential_id="cred_1234567890", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/credentials/{jsonable_encoder(credential_id)}/delete", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 422: - raise UnprocessableEntityError( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def get_credential( - self, credential_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> CredentialResponse: - """ - Retrieves a specific credential by its ID - - Parameters - ---------- - credential_id : str - The unique identifier of the credential - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - CredentialResponse - Successful Response - - Examples - -------- - from skyvern import Skyvern - - client = Skyvern( - api_key="YOUR_API_KEY", - ) - client.credentials.get_credential( - credential_id="cred_1234567890", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/credentials/{jsonable_encoder(credential_id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CredentialResponse, - parse_obj_as( - type_=CredentialResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 422: - raise UnprocessableEntityError( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - -class AsyncCredentialsClient: - def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper - - async def send_totp_code( - self, - *, - totp_identifier: str, - content: str, - task_id: typing.Optional[str] = OMIT, - workflow_id: typing.Optional[str] = OMIT, - workflow_run_id: typing.Optional[str] = OMIT, - source: typing.Optional[str] = OMIT, - expired_at: typing.Optional[dt.datetime] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> TotpCode: - """ - Forward a TOTP (2FA, MFA) email or sms message containing the code to Skyvern. This endpoint stores the code in database so that Skyvern can use it while running tasks/workflows. - - Parameters - ---------- - totp_identifier : str - The identifier of the TOTP code. It can be the email address, phone number, or the identifier of the user. - - content : str - The content of the TOTP code. It can be the email content that contains the TOTP code, or the sms message that contains the TOTP code. Skyvern will automatically extract the TOTP code from the content. - - task_id : typing.Optional[str] - The task_id the totp code is for. It can be the task_id of the task that the TOTP code is for. - - workflow_id : typing.Optional[str] - The workflow ID the TOTP code is for. It can be the workflow ID of the workflow that the TOTP code is for. - - workflow_run_id : typing.Optional[str] - The workflow run id that the TOTP code is for. It can be the workflow run id of the workflow run that the TOTP code is for. - - source : typing.Optional[str] - An optional field. The source of the TOTP code. e.g. email, sms, etc. - - expired_at : typing.Optional[dt.datetime] - The timestamp when the TOTP code expires - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - TotpCode - Successful Response - - Examples - -------- - import asyncio - - from skyvern import AsyncSkyvern - - client = AsyncSkyvern( - api_key="YOUR_API_KEY", - ) - - - async def main() -> None: - await client.credentials.send_totp_code( - totp_identifier="john.doe@example.com", - content="Hello, your verification code is 123456", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/credentials/totp", - method="POST", - json={ - "totp_identifier": totp_identifier, - "task_id": task_id, - "workflow_id": workflow_id, - "workflow_run_id": workflow_run_id, - "source": source, - "content": content, - "expired_at": expired_at, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - TotpCode, - parse_obj_as( - type_=TotpCode, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 422: - raise UnprocessableEntityError( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def get_credentials( - self, - *, - page: typing.Optional[int] = None, - page_size: typing.Optional[int] = None, - request_options: typing.Optional[RequestOptions] = None, - ) -> typing.List[CredentialResponse]: - """ - Retrieves a paginated list of credentials for the current organization - - Parameters - ---------- - page : typing.Optional[int] - Page number for pagination - - page_size : typing.Optional[int] - Number of items per page - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.List[CredentialResponse] - Successful Response - - Examples - -------- - import asyncio - - from skyvern import AsyncSkyvern - - client = AsyncSkyvern( - api_key="YOUR_API_KEY", - ) - - - async def main() -> None: - await client.credentials.get_credentials() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/credentials", - method="GET", - params={ - "page": page, - "page_size": page_size, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.List[CredentialResponse], - parse_obj_as( - type_=typing.List[CredentialResponse], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 422: - raise UnprocessableEntityError( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def create_credential( - self, - *, - name: str, - credential_type: CredentialType, - credential: CreateCredentialRequestCredential, - request_options: typing.Optional[RequestOptions] = None, - ) -> CredentialResponse: - """ - Creates a new credential for the current organization - - Parameters - ---------- - name : str - Name of the credential - - credential_type : CredentialType - Type of credential to create - - credential : CreateCredentialRequestCredential - The credential data to store - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - CredentialResponse - Successful Response - - Examples - -------- - import asyncio - - from skyvern import AsyncSkyvern, NonEmptyPasswordCredential - - client = AsyncSkyvern( - api_key="YOUR_API_KEY", - ) - - - async def main() -> None: - await client.credentials.create_credential( - name="My Credential", - credential_type="password", - credential=NonEmptyPasswordCredential( - password="securepassword123", - username="user@example.com", - totp="JBSWY3DPEHPK3PXP", - ), - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/credentials", - method="POST", - json={ - "name": name, - "credential_type": credential_type, - "credential": convert_and_respect_annotation_metadata( - object_=credential, annotation=CreateCredentialRequestCredential, direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CredentialResponse, - parse_obj_as( - type_=CredentialResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 422: - raise UnprocessableEntityError( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def delete_credential( - self, credential_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> None: - """ - Deletes a specific credential by its ID - - Parameters - ---------- - credential_id : str - The unique identifier of the credential to delete - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - import asyncio - - from skyvern import AsyncSkyvern - - client = AsyncSkyvern( - api_key="YOUR_API_KEY", - ) - - - async def main() -> None: - await client.credentials.delete_credential( - credential_id="cred_1234567890", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/credentials/{jsonable_encoder(credential_id)}/delete", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 422: - raise UnprocessableEntityError( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def get_credential( - self, credential_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> CredentialResponse: - """ - Retrieves a specific credential by its ID - - Parameters - ---------- - credential_id : str - The unique identifier of the credential - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - CredentialResponse - Successful Response - - Examples - -------- - import asyncio - - from skyvern import AsyncSkyvern - - client = AsyncSkyvern( - api_key="YOUR_API_KEY", - ) - - - async def main() -> None: - await client.credentials.get_credential( - credential_id="cred_1234567890", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/credentials/{jsonable_encoder(credential_id)}", - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CredentialResponse, - parse_obj_as( - type_=CredentialResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 422: - raise UnprocessableEntityError( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/skyvern/client/credentials/types/__init__.py b/skyvern/client/credentials/types/__init__.py deleted file mode 100644 index cb1c6910..00000000 --- a/skyvern/client/credentials/types/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .create_credential_request_credential import CreateCredentialRequestCredential - -__all__ = ["CreateCredentialRequestCredential"] diff --git a/skyvern/client/types/__init__.py b/skyvern/client/types/__init__.py index b03a1c51..fc63440f 100644 --- a/skyvern/client/types/__init__.py +++ b/skyvern/client/types/__init__.py @@ -52,6 +52,7 @@ from .context_parameter_source import ( ) from .context_parameter_value import ContextParameterValue from .context_parameter_yaml import ContextParameterYaml +from .create_credential_request_credential import CreateCredentialRequestCredential from .credential_parameter import CredentialParameter from .credential_parameter_yaml import CredentialParameterYaml from .credential_response import CredentialResponse @@ -153,6 +154,14 @@ from .for_loop_block_yaml_loop_blocks_item import ( ForLoopBlockYamlLoopBlocksItem_Validation, ForLoopBlockYamlLoopBlocksItem_Wait, ) +from .get_run_response import ( + GetRunResponse, + GetRunResponse_AnthropicCua, + GetRunResponse_OpenaiCua, + GetRunResponse_TaskV1, + GetRunResponse_TaskV2, + GetRunResponse_WorkflowRun, +) from .http_validation_error import HttpValidationError from .login_block import LoginBlock from .login_block_data_schema import LoginBlockDataSchema @@ -402,6 +411,7 @@ __all__ = [ "ContextParameterSource_Workflow", "ContextParameterValue", "ContextParameterYaml", + "CreateCredentialRequestCredential", "CredentialParameter", "CredentialParameterYaml", "CredentialResponse", @@ -493,6 +503,12 @@ __all__ = [ "ForLoopBlockYamlLoopBlocksItem_UploadToS3", "ForLoopBlockYamlLoopBlocksItem_Validation", "ForLoopBlockYamlLoopBlocksItem_Wait", + "GetRunResponse", + "GetRunResponse_AnthropicCua", + "GetRunResponse_OpenaiCua", + "GetRunResponse_TaskV1", + "GetRunResponse_TaskV2", + "GetRunResponse_WorkflowRun", "HttpValidationError", "LoginBlock", "LoginBlockDataSchema", diff --git a/skyvern/client/types/action_block_yaml.py b/skyvern/client/types/action_block_yaml.py index c15010a6..d80ca6db 100644 --- a/skyvern/client/types/action_block_yaml.py +++ b/skyvern/client/types/action_block_yaml.py @@ -2,6 +2,7 @@ from ..core.pydantic_utilities import UniversalBaseModel import typing +from .run_engine import RunEngine from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic @@ -11,6 +12,7 @@ class ActionBlockYaml(UniversalBaseModel): continue_on_failure: typing.Optional[bool] = None url: typing.Optional[str] = None title: typing.Optional[str] = None + engine: typing.Optional[RunEngine] = None navigation_goal: typing.Optional[str] = None error_code_mapping: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None max_retries: typing.Optional[int] = None diff --git a/skyvern/client/credentials/types/create_credential_request_credential.py b/skyvern/client/types/create_credential_request_credential.py similarity index 53% rename from skyvern/client/credentials/types/create_credential_request_credential.py rename to skyvern/client/types/create_credential_request_credential.py index fac57936..4df3e0af 100644 --- a/skyvern/client/credentials/types/create_credential_request_credential.py +++ b/skyvern/client/types/create_credential_request_credential.py @@ -1,7 +1,7 @@ # This file was auto-generated by Fern from our API Definition. import typing -from ...types.non_empty_password_credential import NonEmptyPasswordCredential -from ...types.non_empty_credit_card_credential import NonEmptyCreditCardCredential +from .non_empty_password_credential import NonEmptyPasswordCredential +from .non_empty_credit_card_credential import NonEmptyCreditCardCredential CreateCredentialRequestCredential = typing.Union[NonEmptyPasswordCredential, NonEmptyCreditCardCredential] diff --git a/skyvern/client/types/extraction_block_yaml.py b/skyvern/client/types/extraction_block_yaml.py index 50e424f1..ef4fbbb0 100644 --- a/skyvern/client/types/extraction_block_yaml.py +++ b/skyvern/client/types/extraction_block_yaml.py @@ -2,6 +2,7 @@ from ..core.pydantic_utilities import UniversalBaseModel import typing +from .run_engine import RunEngine from .extraction_block_yaml_data_schema import ExtractionBlockYamlDataSchema from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic @@ -13,6 +14,7 @@ class ExtractionBlockYaml(UniversalBaseModel): data_extraction_goal: str url: typing.Optional[str] = None title: typing.Optional[str] = None + engine: typing.Optional[RunEngine] = None data_schema: typing.Optional[ExtractionBlockYamlDataSchema] = None max_retries: typing.Optional[int] = None max_steps_per_run: typing.Optional[int] = None diff --git a/skyvern/client/types/file_download_block_yaml.py b/skyvern/client/types/file_download_block_yaml.py index ab860113..7e78163f 100644 --- a/skyvern/client/types/file_download_block_yaml.py +++ b/skyvern/client/types/file_download_block_yaml.py @@ -2,6 +2,7 @@ from ..core.pydantic_utilities import UniversalBaseModel import typing +from .run_engine import RunEngine from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic @@ -12,6 +13,7 @@ class FileDownloadBlockYaml(UniversalBaseModel): navigation_goal: str url: typing.Optional[str] = None title: typing.Optional[str] = None + engine: typing.Optional[RunEngine] = None error_code_mapping: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None max_retries: typing.Optional[int] = None max_steps_per_run: typing.Optional[int] = None diff --git a/skyvern/client/types/for_loop_block_yaml_loop_blocks_item.py b/skyvern/client/types/for_loop_block_yaml_loop_blocks_item.py index 3a7149cb..59002818 100644 --- a/skyvern/client/types/for_loop_block_yaml_loop_blocks_item.py +++ b/skyvern/client/types/for_loop_block_yaml_loop_blocks_item.py @@ -3,6 +3,7 @@ from __future__ import annotations from ..core.pydantic_utilities import UniversalBaseModel import typing +from .run_engine import RunEngine from .task_block_yaml_data_schema import TaskBlockYamlDataSchema from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic @@ -10,7 +11,6 @@ from .file_storage_type import FileStorageType import typing_extensions from ..core.serialization import FieldMetadata from .file_type import FileType -from .run_engine import RunEngine from .extraction_block_yaml_data_schema import ExtractionBlockYamlDataSchema from ..core.pydantic_utilities import update_forward_refs @@ -21,6 +21,7 @@ class ForLoopBlockYamlLoopBlocksItem_Task(UniversalBaseModel): continue_on_failure: typing.Optional[bool] = None url: typing.Optional[str] = None title: typing.Optional[str] = None + engine: typing.Optional[RunEngine] = None navigation_goal: typing.Optional[str] = None data_extraction_goal: typing.Optional[str] = None data_schema: typing.Optional[TaskBlockYamlDataSchema] = None @@ -225,6 +226,7 @@ class ForLoopBlockYamlLoopBlocksItem_Action(UniversalBaseModel): continue_on_failure: typing.Optional[bool] = None url: typing.Optional[str] = None title: typing.Optional[str] = None + engine: typing.Optional[RunEngine] = None navigation_goal: typing.Optional[str] = None error_code_mapping: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None max_retries: typing.Optional[int] = None @@ -284,6 +286,7 @@ class ForLoopBlockYamlLoopBlocksItem_Extraction(UniversalBaseModel): data_extraction_goal: str url: typing.Optional[str] = None title: typing.Optional[str] = None + engine: typing.Optional[RunEngine] = None data_schema: typing.Optional[ExtractionBlockYamlDataSchema] = None max_retries: typing.Optional[int] = None max_steps_per_run: typing.Optional[int] = None @@ -306,6 +309,7 @@ class ForLoopBlockYamlLoopBlocksItem_Login(UniversalBaseModel): continue_on_failure: typing.Optional[bool] = None url: typing.Optional[str] = None title: typing.Optional[str] = None + engine: typing.Optional[RunEngine] = None navigation_goal: typing.Optional[str] = None error_code_mapping: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None max_retries: typing.Optional[int] = None @@ -351,6 +355,7 @@ class ForLoopBlockYamlLoopBlocksItem_FileDownload(UniversalBaseModel): navigation_goal: str url: typing.Optional[str] = None title: typing.Optional[str] = None + engine: typing.Optional[RunEngine] = None error_code_mapping: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None max_retries: typing.Optional[int] = None max_steps_per_run: typing.Optional[int] = None diff --git a/skyvern/client/agent/types/agent_get_run_response.py b/skyvern/client/types/get_run_response.py similarity index 82% rename from skyvern/client/agent/types/agent_get_run_response.py rename to skyvern/client/types/get_run_response.py index 471eac7b..1339c2e0 100644 --- a/skyvern/client/agent/types/agent_get_run_response.py +++ b/skyvern/client/types/get_run_response.py @@ -1,20 +1,20 @@ # This file was auto-generated by Fern from our API Definition. from __future__ import annotations -from ...core.pydantic_utilities import UniversalBaseModel +from ..core.pydantic_utilities import UniversalBaseModel import typing -from ...types.run_status import RunStatus -from ...types.task_run_response_output import TaskRunResponseOutput -from ...types.file_info import FileInfo +from .run_status import RunStatus +from .task_run_response_output import TaskRunResponseOutput +from .file_info import FileInfo import datetime as dt -from ...types.task_run_request import TaskRunRequest -from ...core.pydantic_utilities import IS_PYDANTIC_V2 +from .task_run_request import TaskRunRequest +from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic -from ...types.workflow_run_response_output import WorkflowRunResponseOutput -from ...types.workflow_run_request import WorkflowRunRequest +from .workflow_run_response_output import WorkflowRunResponseOutput +from .workflow_run_request import WorkflowRunRequest -class AgentGetRunResponse_TaskV1(UniversalBaseModel): +class GetRunResponse_TaskV1(UniversalBaseModel): run_type: typing.Literal["task_v1"] = "task_v1" run_id: str status: RunStatus @@ -38,7 +38,7 @@ class AgentGetRunResponse_TaskV1(UniversalBaseModel): extra = pydantic.Extra.allow -class AgentGetRunResponse_TaskV2(UniversalBaseModel): +class GetRunResponse_TaskV2(UniversalBaseModel): run_type: typing.Literal["task_v2"] = "task_v2" run_id: str status: RunStatus @@ -62,7 +62,7 @@ class AgentGetRunResponse_TaskV2(UniversalBaseModel): extra = pydantic.Extra.allow -class AgentGetRunResponse_OpenaiCua(UniversalBaseModel): +class GetRunResponse_OpenaiCua(UniversalBaseModel): run_type: typing.Literal["openai_cua"] = "openai_cua" run_id: str status: RunStatus @@ -86,7 +86,7 @@ class AgentGetRunResponse_OpenaiCua(UniversalBaseModel): extra = pydantic.Extra.allow -class AgentGetRunResponse_AnthropicCua(UniversalBaseModel): +class GetRunResponse_AnthropicCua(UniversalBaseModel): run_type: typing.Literal["anthropic_cua"] = "anthropic_cua" run_id: str status: RunStatus @@ -110,7 +110,7 @@ class AgentGetRunResponse_AnthropicCua(UniversalBaseModel): extra = pydantic.Extra.allow -class AgentGetRunResponse_WorkflowRun(UniversalBaseModel): +class GetRunResponse_WorkflowRun(UniversalBaseModel): run_type: typing.Literal["workflow_run"] = "workflow_run" run_id: str status: RunStatus @@ -134,10 +134,10 @@ class AgentGetRunResponse_WorkflowRun(UniversalBaseModel): extra = pydantic.Extra.allow -AgentGetRunResponse = typing.Union[ - AgentGetRunResponse_TaskV1, - AgentGetRunResponse_TaskV2, - AgentGetRunResponse_OpenaiCua, - AgentGetRunResponse_AnthropicCua, - AgentGetRunResponse_WorkflowRun, +GetRunResponse = typing.Union[ + GetRunResponse_TaskV1, + GetRunResponse_TaskV2, + GetRunResponse_OpenaiCua, + GetRunResponse_AnthropicCua, + GetRunResponse_WorkflowRun, ] diff --git a/skyvern/client/types/login_block_yaml.py b/skyvern/client/types/login_block_yaml.py index e3406366..a897e093 100644 --- a/skyvern/client/types/login_block_yaml.py +++ b/skyvern/client/types/login_block_yaml.py @@ -2,6 +2,7 @@ from ..core.pydantic_utilities import UniversalBaseModel import typing +from .run_engine import RunEngine from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic @@ -11,6 +12,7 @@ class LoginBlockYaml(UniversalBaseModel): continue_on_failure: typing.Optional[bool] = None url: typing.Optional[str] = None title: typing.Optional[str] = None + engine: typing.Optional[RunEngine] = None navigation_goal: typing.Optional[str] = None error_code_mapping: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None max_retries: typing.Optional[int] = None diff --git a/skyvern/client/types/task_block_yaml.py b/skyvern/client/types/task_block_yaml.py index 3ca6523e..9458348b 100644 --- a/skyvern/client/types/task_block_yaml.py +++ b/skyvern/client/types/task_block_yaml.py @@ -2,6 +2,7 @@ from ..core.pydantic_utilities import UniversalBaseModel import typing +from .run_engine import RunEngine from .task_block_yaml_data_schema import TaskBlockYamlDataSchema from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic @@ -12,6 +13,7 @@ class TaskBlockYaml(UniversalBaseModel): continue_on_failure: typing.Optional[bool] = None url: typing.Optional[str] = None title: typing.Optional[str] = None + engine: typing.Optional[RunEngine] = None navigation_goal: typing.Optional[str] = None data_extraction_goal: typing.Optional[str] = None data_schema: typing.Optional[TaskBlockYamlDataSchema] = None diff --git a/skyvern/client/types/workflow_definition_yaml_blocks_item.py b/skyvern/client/types/workflow_definition_yaml_blocks_item.py index 62787102..91e0dc47 100644 --- a/skyvern/client/types/workflow_definition_yaml_blocks_item.py +++ b/skyvern/client/types/workflow_definition_yaml_blocks_item.py @@ -3,6 +3,7 @@ from __future__ import annotations from ..core.pydantic_utilities import UniversalBaseModel import typing +from .run_engine import RunEngine from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic from .extraction_block_yaml_data_schema import ExtractionBlockYamlDataSchema @@ -10,7 +11,6 @@ from .file_storage_type import FileStorageType import typing_extensions from ..core.serialization import FieldMetadata from .file_type import FileType -from .run_engine import RunEngine from .task_block_yaml_data_schema import TaskBlockYamlDataSchema from ..core.pydantic_utilities import update_forward_refs @@ -21,6 +21,7 @@ class WorkflowDefinitionYamlBlocksItem_Action(UniversalBaseModel): continue_on_failure: typing.Optional[bool] = None url: typing.Optional[str] = None title: typing.Optional[str] = None + engine: typing.Optional[RunEngine] = None navigation_goal: typing.Optional[str] = None error_code_mapping: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None max_retries: typing.Optional[int] = None @@ -81,6 +82,7 @@ class WorkflowDefinitionYamlBlocksItem_Extraction(UniversalBaseModel): data_extraction_goal: str url: typing.Optional[str] = None title: typing.Optional[str] = None + engine: typing.Optional[RunEngine] = None data_schema: typing.Optional[ExtractionBlockYamlDataSchema] = None max_retries: typing.Optional[int] = None max_steps_per_run: typing.Optional[int] = None @@ -104,6 +106,7 @@ class WorkflowDefinitionYamlBlocksItem_FileDownload(UniversalBaseModel): navigation_goal: str url: typing.Optional[str] = None title: typing.Optional[str] = None + engine: typing.Optional[RunEngine] = None error_code_mapping: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None max_retries: typing.Optional[int] = None max_steps_per_run: typing.Optional[int] = None @@ -206,6 +209,7 @@ class WorkflowDefinitionYamlBlocksItem_Login(UniversalBaseModel): continue_on_failure: typing.Optional[bool] = None url: typing.Optional[str] = None title: typing.Optional[str] = None + engine: typing.Optional[RunEngine] = None navigation_goal: typing.Optional[str] = None error_code_mapping: typing.Optional[typing.Dict[str, typing.Optional[str]]] = None max_retries: typing.Optional[int] = None @@ -307,6 +311,7 @@ class WorkflowDefinitionYamlBlocksItem_Task(UniversalBaseModel): continue_on_failure: typing.Optional[bool] = None url: typing.Optional[str] = None title: typing.Optional[str] = None + engine: typing.Optional[RunEngine] = None navigation_goal: typing.Optional[str] = None data_extraction_goal: typing.Optional[str] = None data_schema: typing.Optional[TaskBlockYamlDataSchema] = None diff --git a/skyvern/client/workflows/__init__.py b/skyvern/client/workflows/__init__.py deleted file mode 100644 index f3ea2659..00000000 --- a/skyvern/client/workflows/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - diff --git a/skyvern/client/workflows/client.py b/skyvern/client/workflows/client.py deleted file mode 100644 index 7d26e734..00000000 --- a/skyvern/client/workflows/client.py +++ /dev/null @@ -1,637 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -from ..core.client_wrapper import SyncClientWrapper -from ..core.request_options import RequestOptions -from ..types.workflow import Workflow -from ..core.pydantic_utilities import parse_obj_as -from ..errors.unprocessable_entity_error import UnprocessableEntityError -from json.decoder import JSONDecodeError -from ..core.api_error import ApiError -from ..types.workflow_create_yaml_request import WorkflowCreateYamlRequest -from ..core.serialization import convert_and_respect_annotation_metadata -from ..core.jsonable_encoder import jsonable_encoder -from ..core.client_wrapper import AsyncClientWrapper - -# this is used as the default value for optional parameters -OMIT = typing.cast(typing.Any, ...) - - -class WorkflowsClient: - def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper - - def get_workflows( - self, - *, - page: typing.Optional[int] = None, - page_size: typing.Optional[int] = None, - only_saved_tasks: typing.Optional[bool] = None, - only_workflows: typing.Optional[bool] = None, - title: typing.Optional[str] = None, - template: typing.Optional[bool] = None, - request_options: typing.Optional[RequestOptions] = None, - ) -> typing.List[Workflow]: - """ - Get all workflows with the latest version for the organization. - - Parameters - ---------- - page : typing.Optional[int] - - page_size : typing.Optional[int] - - only_saved_tasks : typing.Optional[bool] - - only_workflows : typing.Optional[bool] - - title : typing.Optional[str] - - template : typing.Optional[bool] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.List[Workflow] - Successful Response - - Examples - -------- - from skyvern import Skyvern - - client = Skyvern( - api_key="YOUR_API_KEY", - ) - client.workflows.get_workflows() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/workflows", - method="GET", - params={ - "page": page, - "page_size": page_size, - "only_saved_tasks": only_saved_tasks, - "only_workflows": only_workflows, - "title": title, - "template": template, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.List[Workflow], - parse_obj_as( - type_=typing.List[Workflow], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 422: - raise UnprocessableEntityError( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def create_workflow( - self, - *, - json_definition: typing.Optional[WorkflowCreateYamlRequest] = OMIT, - yaml_definition: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> Workflow: - """ - Create a new workflow - - Parameters - ---------- - json_definition : typing.Optional[WorkflowCreateYamlRequest] - Workflow definition in JSON format - - yaml_definition : typing.Optional[str] - Workflow definition in YAML format - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Workflow - Successfully created workflow - - Examples - -------- - from skyvern import Skyvern - - client = Skyvern( - api_key="YOUR_API_KEY", - ) - client.workflows.create_workflow() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/workflows", - method="POST", - json={ - "json_definition": convert_and_respect_annotation_metadata( - object_=json_definition, annotation=WorkflowCreateYamlRequest, direction="write" - ), - "yaml_definition": yaml_definition, - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Workflow, - parse_obj_as( - type_=Workflow, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 422: - raise UnprocessableEntityError( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def update_workflow( - self, - workflow_id: str, - *, - json_definition: typing.Optional[WorkflowCreateYamlRequest] = OMIT, - yaml_definition: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> Workflow: - """ - Update a workflow - - Parameters - ---------- - workflow_id : str - The ID of the workflow to update. Workflow ID starts with `wpid_`. - - json_definition : typing.Optional[WorkflowCreateYamlRequest] - Workflow definition in JSON format - - yaml_definition : typing.Optional[str] - Workflow definition in YAML format - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Workflow - Successfully updated workflow - - Examples - -------- - from skyvern import Skyvern - - client = Skyvern( - api_key="YOUR_API_KEY", - ) - client.workflows.update_workflow( - workflow_id="wpid_123", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/workflows/{jsonable_encoder(workflow_id)}", - method="POST", - json={ - "json_definition": convert_and_respect_annotation_metadata( - object_=json_definition, annotation=WorkflowCreateYamlRequest, direction="write" - ), - "yaml_definition": yaml_definition, - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Workflow, - parse_obj_as( - type_=Workflow, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 422: - raise UnprocessableEntityError( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - def delete_workflow( - self, workflow_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> typing.Optional[typing.Any]: - """ - Delete a workflow - - Parameters - ---------- - workflow_id : str - The ID of the workflow to delete. Workflow ID starts with `wpid_`. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - Successfully deleted workflow - - Examples - -------- - from skyvern import Skyvern - - client = Skyvern( - api_key="YOUR_API_KEY", - ) - client.workflows.delete_workflow( - workflow_id="wpid_123", - ) - """ - _response = self._client_wrapper.httpx_client.request( - f"v1/workflows/{jsonable_encoder(workflow_id)}/delete", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - -class AsyncWorkflowsClient: - def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper - - async def get_workflows( - self, - *, - page: typing.Optional[int] = None, - page_size: typing.Optional[int] = None, - only_saved_tasks: typing.Optional[bool] = None, - only_workflows: typing.Optional[bool] = None, - title: typing.Optional[str] = None, - template: typing.Optional[bool] = None, - request_options: typing.Optional[RequestOptions] = None, - ) -> typing.List[Workflow]: - """ - Get all workflows with the latest version for the organization. - - Parameters - ---------- - page : typing.Optional[int] - - page_size : typing.Optional[int] - - only_saved_tasks : typing.Optional[bool] - - only_workflows : typing.Optional[bool] - - title : typing.Optional[str] - - template : typing.Optional[bool] - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.List[Workflow] - Successful Response - - Examples - -------- - import asyncio - - from skyvern import AsyncSkyvern - - client = AsyncSkyvern( - api_key="YOUR_API_KEY", - ) - - - async def main() -> None: - await client.workflows.get_workflows() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/workflows", - method="GET", - params={ - "page": page, - "page_size": page_size, - "only_saved_tasks": only_saved_tasks, - "only_workflows": only_workflows, - "title": title, - "template": template, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - typing.List[Workflow], - parse_obj_as( - type_=typing.List[Workflow], # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 422: - raise UnprocessableEntityError( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def create_workflow( - self, - *, - json_definition: typing.Optional[WorkflowCreateYamlRequest] = OMIT, - yaml_definition: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> Workflow: - """ - Create a new workflow - - Parameters - ---------- - json_definition : typing.Optional[WorkflowCreateYamlRequest] - Workflow definition in JSON format - - yaml_definition : typing.Optional[str] - Workflow definition in YAML format - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Workflow - Successfully created workflow - - Examples - -------- - import asyncio - - from skyvern import AsyncSkyvern - - client = AsyncSkyvern( - api_key="YOUR_API_KEY", - ) - - - async def main() -> None: - await client.workflows.create_workflow() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/workflows", - method="POST", - json={ - "json_definition": convert_and_respect_annotation_metadata( - object_=json_definition, annotation=WorkflowCreateYamlRequest, direction="write" - ), - "yaml_definition": yaml_definition, - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Workflow, - parse_obj_as( - type_=Workflow, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 422: - raise UnprocessableEntityError( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def update_workflow( - self, - workflow_id: str, - *, - json_definition: typing.Optional[WorkflowCreateYamlRequest] = OMIT, - yaml_definition: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> Workflow: - """ - Update a workflow - - Parameters - ---------- - workflow_id : str - The ID of the workflow to update. Workflow ID starts with `wpid_`. - - json_definition : typing.Optional[WorkflowCreateYamlRequest] - Workflow definition in JSON format - - yaml_definition : typing.Optional[str] - Workflow definition in YAML format - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - Workflow - Successfully updated workflow - - Examples - -------- - import asyncio - - from skyvern import AsyncSkyvern - - client = AsyncSkyvern( - api_key="YOUR_API_KEY", - ) - - - async def main() -> None: - await client.workflows.update_workflow( - workflow_id="wpid_123", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/workflows/{jsonable_encoder(workflow_id)}", - method="POST", - json={ - "json_definition": convert_and_respect_annotation_metadata( - object_=json_definition, annotation=WorkflowCreateYamlRequest, direction="write" - ), - "yaml_definition": yaml_definition, - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Workflow, - parse_obj_as( - type_=Workflow, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 422: - raise UnprocessableEntityError( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - - async def delete_workflow( - self, workflow_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> typing.Optional[typing.Any]: - """ - Delete a workflow - - Parameters - ---------- - workflow_id : str - The ID of the workflow to delete. Workflow ID starts with `wpid_`. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - typing.Optional[typing.Any] - Successfully deleted workflow - - Examples - -------- - import asyncio - - from skyvern import AsyncSkyvern - - client = AsyncSkyvern( - api_key="YOUR_API_KEY", - ) - - - async def main() -> None: - await client.workflows.delete_workflow( - workflow_id="wpid_123", - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"v1/workflows/{jsonable_encoder(workflow_id)}/delete", - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return 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( - 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, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/skyvern/forge/sdk/routes/code_samples.py b/skyvern/forge/sdk/routes/code_samples.py index 6597c445..369bd1a7 100644 --- a/skyvern/forge/sdk/routes/code_samples.py +++ b/skyvern/forge/sdk/routes/code_samples.py @@ -2,28 +2,28 @@ RUN_TASK_CODE_SAMPLE = """from skyvern import Skyvern skyvern = Skyvern(api_key="YOUR_API_KEY") -await skyvern.agent.run_task(prompt="What's the top post on hackernews?") +await skyvern.run_task(prompt="What's the top post on hackernews?") """ RUN_WORKFLOW_CODE_SAMPLE = """from skyvern import Skyvern skyvern = Skyvern(api_key="YOUR_API_KEY") -await skyvern.agent.run_workflow(workflow_id="wpid_123", parameters={"parameter1": "value1", "parameter2": "value2"}) +await skyvern.run_workflow(workflow_id="wpid_123", parameters={"parameter1": "value1", "parameter2": "value2"}) """ GET_RUN_CODE_SAMPLE = """from skyvern import Skyvern skyvern = Skyvern(api_key="YOUR_API_KEY") -run = await skyvern.agent.get_run(run_id="tsk_v2_123") +run = await skyvern.get_run(run_id="tsk_v2_123") print(run) """ CANCEL_RUN_CODE_SAMPLE = """from skyvern import Skyvern skyvern = Skyvern(api_key="YOUR_API_KEY") -await skyvern.agent.cancel_run(run_id="tsk_v2_123") +await skyvern.cancel_run(run_id="tsk_v2_123") """ RETRY_RUN_WEBHOOK_CODE_SAMPLE = """from skyvern import Skyvern skyvern = Skyvern(api_key="YOUR_API_KEY") -await skyvern.agent.retry_run_webhook(run_id="tsk_v2_123") +await skyvern.retry_run_webhook(run_id="tsk_v2_123") """ # Workflows diff --git a/skyvern/library/skyvern.py b/skyvern/library/skyvern.py index 6632c2d1..93224d7b 100644 --- a/skyvern/library/skyvern.py +++ b/skyvern/library/skyvern.py @@ -8,9 +8,9 @@ import httpx from dotenv import load_dotenv from skyvern.client import AsyncSkyvern -from skyvern.client.agent.types.agent_get_run_response import AgentGetRunResponse from skyvern.client.core.pydantic_utilities import parse_obj_as from skyvern.client.environment import SkyvernEnvironment +from skyvern.client.types.get_run_response import GetRunResponse from skyvern.client.types.task_run_response import TaskRunResponse from skyvern.config import settings from skyvern.forge import app @@ -30,73 +30,6 @@ from skyvern.utils import migrate_db class Skyvern(AsyncSkyvern): - class local: - """Internal namespace for local mode operations.""" - - @staticmethod - async def run_task( - prompt: str, - engine: RunEngine = RunEngine.skyvern_v2, - url: str | None = None, - webhook_url: str | None = None, - totp_identifier: str | None = None, - totp_url: str | None = None, - title: str | None = None, - error_code_mapping: dict[str, str] | None = None, - data_extraction_schema: dict[str, Any] | str | None = None, - proxy_location: ProxyLocation | None = None, - max_steps: int | None = None, - wait_for_completion: bool = True, - timeout: float = DEFAULT_AGENT_TIMEOUT, - browser_session_id: str | None = None, - user_agent: str | None = None, - ) -> TaskRunResponse: - """ - Run a task using Skyvern in local mode. - This is a wrapper around Skyvern.run_task that ensures it's used in local mode. - - Args: - prompt: The prompt describing the task to run - engine: The engine to use for running the task - url: Optional URL to navigate to - webhook_url: Optional webhook URL for callbacks - totp_identifier: Optional TOTP identifier - totp_url: Optional TOTP verification URL - title: Optional title for the task - error_code_mapping: Optional mapping of error codes to messages - data_extraction_schema: Optional schema for data extraction - proxy_location: Optional proxy location - max_steps: Optional maximum number of steps - wait_for_completion: Whether to wait for task completion - timeout: Timeout in seconds - browser_session_id: Optional browser session ID - user_agent: Optional user agent string - - Returns: - TaskRunResponse: The response from running the task - - Raises: - ValueError: If an API key is provided (this function is for local mode only) - """ - skyvern = Skyvern() # Initialize in local mode (no API key) - return await skyvern.run_task( - prompt=prompt, - engine=engine, - url=url, - webhook_url=webhook_url, - totp_identifier=totp_identifier, - totp_url=totp_url, - title=title, - error_code_mapping=error_code_mapping, - data_extraction_schema=data_extraction_schema, - proxy_location=proxy_location, - max_steps=max_steps, - wait_for_completion=wait_for_completion, - timeout=timeout, - browser_session_id=browser_session_id, - user_agent=user_agent, - ) - def __init__( self, *, @@ -339,7 +272,7 @@ class Skyvern(AsyncSkyvern): await asyncio.sleep(1) ############### officially supported interfaces ############### - async def get_run(self, run_id: str) -> AgentGetRunResponse | None: + async def get_run(self, run_id: str) -> GetRunResponse | None: if not self._api_key: organization = await self.get_organization() get_run_internal_resp = await run_service.get_run_response( @@ -348,14 +281,14 @@ class Skyvern(AsyncSkyvern): if not get_run_internal_resp: return None return typing.cast( - AgentGetRunResponse, + GetRunResponse, parse_obj_as( - type_=AgentGetRunResponse, # type: ignore + type_=GetRunResponse, # type: ignore object_=get_run_internal_resp.model_dump(), ), ) - return await self.agent.get_run(run_id) + return await super().get_run(run_id) async def run_task( self, @@ -450,7 +383,7 @@ class Skyvern(AsyncSkyvern): else: raise ValueError("Local mode is not supported for this method") - task_run = await self.agent.run_task( + task_run = await super().run_task( prompt=prompt, engine=engine, url=url, @@ -467,12 +400,12 @@ class Skyvern(AsyncSkyvern): if wait_for_completion: async with asyncio.timeout(timeout): while True: - task_run = await self.agent.get_run(task_run.run_id) + task_run = await super().get_run(task_run.run_id) if RunStatus(task_run.status).is_final(): break await asyncio.sleep(DEFAULT_AGENT_HEARTBEAT_INTERVAL) return TaskRunResponse.model_validate(task_run.dict()) -def from_run_to_task_run_response(run_obj: AgentGetRunResponse) -> TaskRunResponse: +def from_run_to_task_run_response(run_obj: GetRunResponse) -> TaskRunResponse: return TaskRunResponse.model_validate(run_obj.model_dump())