diff --git a/README.md b/README.md index a4d419be..0e36570b 100644 --- a/README.md +++ b/README.md @@ -114,16 +114,15 @@ This quickstart guide will walk you through getting Skyvern up and running on yo ``` 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 - You can also send a task to Skyvern Cloud: + You can also run a task autonomously on Skyvern Cloud: ```python from skyvern import Skyvern - skyvern = Skyvern() + skyvern = Skyvern(api_key="SKYVERN API KEY") task = await skyvern.agent.run_task(prompt="Find the top post on hackernews today") print(task) ``` - - Or send the task anywhere Skyvern is hosted: + 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") diff --git a/fern/openapi/skyvern_openapi.json b/fern/openapi/skyvern_openapi.json index 6156d380..45511f0b 100644 --- a/fern/openapi/skyvern_openapi.json +++ b/fern/openapi/skyvern_openapi.json @@ -507,7 +507,7 @@ "description": "Invalid workflow definition" } }, - "x-fern-sdk-group-name": "agent", + "x-fern-sdk-group-name": "workflows", "x-fern-sdk-method-name": "create_workflow", "x-fern-examples": [ { @@ -2975,7 +2975,7 @@ } } }, - "x-fern-sdk-group-name": "agent", + "x-fern-sdk-group-name": "workflows", "x-fern-sdk-method-name": "delete_workflow", "x-fern-examples": [ { diff --git a/skyvern/client/__init__.py b/skyvern/client/__init__.py index 07638544..e4070770 100644 --- a/skyvern/client/__init__.py +++ b/skyvern/client/__init__.py @@ -235,7 +235,7 @@ from .types import ( WorkflowStatus, ) from .errors import BadRequestError, ForbiddenError, NotFoundError, UnprocessableEntityError -from . import agent, browser_session, credentials +from . import agent, browser_session, credentials, workflows from .agent import ( AgentGetRunResponse, AgentGetRunResponse_AnthropicCua, @@ -500,4 +500,5 @@ __all__ = [ "agent", "browser_session", "credentials", + "workflows", ] diff --git a/skyvern/client/agent/client.py b/skyvern/client/agent/client.py index 09e138e1..8965c575 100644 --- a/skyvern/client/agent/client.py +++ b/skyvern/client/agent/client.py @@ -434,59 +434,6 @@ class AgentClient: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) - def create_workflow(self, *, request_options: typing.Optional[RequestOptions] = None) -> Workflow: - """ - Create a new workflow - - Parameters - ---------- - 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", - authorization="YOUR_AUTHORIZATION", - ) - client.agent.create_workflow() - """ - _response = self._client_wrapper.httpx_client.request( - "v1/workflows", - method="POST", - request_options=request_options, - ) - 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, *, request_options: typing.Optional[RequestOptions] = None) -> Workflow: """ Update a workflow definition @@ -545,66 +492,6 @@ class AgentClient: 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", - authorization="YOUR_AUTHORIZATION", - ) - client.agent.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 AsyncAgentClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): @@ -1050,67 +937,6 @@ class AsyncAgentClient: 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, *, request_options: typing.Optional[RequestOptions] = None) -> Workflow: - """ - Create a new workflow - - Parameters - ---------- - 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", - authorization="YOUR_AUTHORIZATION", - ) - - - async def main() -> None: - await client.agent.create_workflow() - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - "v1/workflows", - method="POST", - request_options=request_options, - ) - 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, *, request_options: typing.Optional[RequestOptions] = None ) -> Workflow: @@ -1178,71 +1004,3 @@ class AsyncAgentClient: 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", - authorization="YOUR_AUTHORIZATION", - ) - - - async def main() -> None: - await client.agent.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/client/client.py b/skyvern/client/client.py index 469f8239..a59c51a3 100644 --- a/skyvern/client/client.py +++ b/skyvern/client/client.py @@ -5,10 +5,12 @@ from .environment import SkyvernEnvironment import httpx from .core.client_wrapper import SyncClientWrapper from .agent.client import AgentClient +from .workflows.client import WorkflowsClient from .browser_session.client import BrowserSessionClient from .credentials.client import CredentialsClient from .core.client_wrapper import AsyncClientWrapper from .agent.client import AsyncAgentClient +from .workflows.client import AsyncWorkflowsClient from .browser_session.client import AsyncBrowserSessionClient from .credentials.client import AsyncCredentialsClient @@ -76,6 +78,7 @@ class Skyvern: timeout=_defaulted_timeout, ) self.agent = AgentClient(client_wrapper=self._client_wrapper) + self.workflows = WorkflowsClient(client_wrapper=self._client_wrapper) self.browser_session = BrowserSessionClient(client_wrapper=self._client_wrapper) self.credentials = CredentialsClient(client_wrapper=self._client_wrapper) @@ -143,6 +146,7 @@ class AsyncSkyvern: timeout=_defaulted_timeout, ) self.agent = AsyncAgentClient(client_wrapper=self._client_wrapper) + self.workflows = AsyncWorkflowsClient(client_wrapper=self._client_wrapper) self.browser_session = AsyncBrowserSessionClient(client_wrapper=self._client_wrapper) self.credentials = AsyncCredentialsClient(client_wrapper=self._client_wrapper) diff --git a/skyvern/client/workflows/__init__.py b/skyvern/client/workflows/__init__.py new file mode 100644 index 00000000..f3ea2659 --- /dev/null +++ b/skyvern/client/workflows/__init__.py @@ -0,0 +1,2 @@ +# 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 new file mode 100644 index 00000000..1bc6655d --- /dev/null +++ b/skyvern/client/workflows/client.py @@ -0,0 +1,264 @@ +# 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.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 ..core.jsonable_encoder import jsonable_encoder +from ..core.client_wrapper import AsyncClientWrapper + + +class WorkflowsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def create_workflow(self, *, request_options: typing.Optional[RequestOptions] = None) -> Workflow: + """ + Create a new workflow + + Parameters + ---------- + 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", + authorization="YOUR_AUTHORIZATION", + ) + client.workflows.create_workflow() + """ + _response = self._client_wrapper.httpx_client.request( + "v1/workflows", + method="POST", + request_options=request_options, + ) + 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", + authorization="YOUR_AUTHORIZATION", + ) + 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 create_workflow(self, *, request_options: typing.Optional[RequestOptions] = None) -> Workflow: + """ + Create a new workflow + + Parameters + ---------- + 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", + authorization="YOUR_AUTHORIZATION", + ) + + + async def main() -> None: + await client.workflows.create_workflow() + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + "v1/workflows", + method="POST", + request_options=request_options, + ) + 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", + authorization="YOUR_AUTHORIZATION", + ) + + + 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)