diff --git a/agents-api/agents_api/autogen/Tools.py b/agents-api/agents_api/autogen/Tools.py index dffe08e88..f38dc9bc4 100644 --- a/agents-api/agents_api/autogen/Tools.py +++ b/agents-api/agents_api/autogen/Tools.py @@ -174,7 +174,14 @@ class BaseIntegrationDef(BaseModel): populate_by_name=True, ) provider: Literal[ - "dummy", "weather", "wikipedia", "spider", "brave", "browserbase", "email" + "dummy", + "weather", + "wikipedia", + "spider", + "brave", + "browserbase", + "email", + "remote_browser", ] """ The provider of the integration @@ -203,7 +210,14 @@ class BaseIntegrationDefUpdate(BaseModel): ) provider: ( Literal[ - "dummy", "weather", "wikipedia", "spider", "brave", "browserbase", "email" + "dummy", + "weather", + "wikipedia", + "spider", + "brave", + "browserbase", + "email", + "remote_browser", ] | None ) = None @@ -344,6 +358,42 @@ class BraveSearchSetupUpdate(BaseModel): """ +class BrowserbaseCompleteSessionArguments(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: str + status: Literal["REQUEST_RELEASE"] = "REQUEST_RELEASE" + + +class BrowserbaseCompleteSessionArgumentsUpdate(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: str | None = None + status: Literal["REQUEST_RELEASE"] = "REQUEST_RELEASE" + + +class BrowserbaseContextArguments(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + project_id: Annotated[str, Field(alias="projectId")] + """ + The Project ID. Can be found in Settings. + """ + + +class BrowserbaseContextArgumentsUpdate(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + project_id: Annotated[str | None, Field(alias="projectId")] = None + """ + The Project ID. Can be found in Settings. + """ + + class BrowserbaseCreateSessionArguments(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -354,7 +404,7 @@ class BrowserbaseCreateSessionArguments(BaseModel): """ extension_id: Annotated[str | None, Field(alias="extensionId")] = None """ - The uploaded Extension ID. See Upload Extension. + The installed Extension ID. See Install Extension from GitHub. """ browser_settings: Annotated[ dict[str, Any] | None, Field(alias="browserSettings") @@ -386,7 +436,7 @@ class BrowserbaseCreateSessionArgumentsUpdate(BaseModel): """ extension_id: Annotated[str | None, Field(alias="extensionId")] = None """ - The uploaded Extension ID. See Upload Extension. + The installed Extension ID. See Install Extension from GitHub. """ browser_settings: Annotated[ dict[str, Any] | None, Field(alias="browserSettings") @@ -408,6 +458,34 @@ class BrowserbaseCreateSessionArgumentsUpdate(BaseModel): """ +class BrowserbaseExtensionArguments(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + repository_name: Annotated[str, Field(alias="repositoryName")] + """ + The GitHub repository name. + """ + ref: str | None = None + """ + Ref to install from a branch or tag. + """ + + +class BrowserbaseExtensionArgumentsUpdate(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + repository_name: Annotated[str | None, Field(alias="repositoryName")] = None + """ + The GitHub repository name. + """ + ref: str | None = None + """ + Ref to install from a branch or tag. + """ + + class BrowserbaseGetSessionArguments(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -422,6 +500,16 @@ class BrowserbaseGetSessionArgumentsUpdate(BaseModel): id: str | None = None +class BrowserbaseGetSessionConnectUrlArguments(BrowserbaseGetSessionArguments): + pass + + +class BrowserbaseGetSessionConnectUrlArgumentsUpdate( + BrowserbaseGetSessionArgumentsUpdate +): + pass + + class BrowserbaseGetSessionLiveUrlsArguments(BrowserbaseGetSessionArguments): pass @@ -470,22 +558,6 @@ class BrowserbaseSetupUpdate(BaseModel): """ -class BrowserbaseUpdateSessionArguments(BaseModel): - model_config = ConfigDict( - populate_by_name=True, - ) - id: str - status: Literal["REQUEST_RELEASE"] = "REQUEST_RELEASE" - - -class BrowserbaseUpdateSessionArgumentsUpdate(BaseModel): - model_config = ConfigDict( - populate_by_name=True, - ) - id: str | None = None - status: Literal["REQUEST_RELEASE"] | None = None - - class ChosenBash20241022(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -631,11 +703,14 @@ class CreateToolRequest(BaseModel): | WikipediaIntegrationDef | WeatherIntegrationDef | BrowserbaseContextIntegrationDef + | BrowserbaseExtensionIntegrationDef | BrowserbaseListSessionsIntegrationDef | BrowserbaseCreateSessionIntegrationDef | BrowserbaseGetSessionIntegrationDef - | BrowserbaseUpdateSessionIntegrationDef + | BrowserbaseCompleteSessionIntegrationDef | BrowserbaseGetSessionLiveUrlsIntegrationDef + | BrowserbaseGetSessionConnectUrlIntegrationDef + | RemoteBrowserIntegrationDef | None ) = None """ @@ -894,11 +969,14 @@ class PatchToolRequest(BaseModel): | WikipediaIntegrationDefUpdate | WeatherIntegrationDefUpdate | BrowserbaseContextIntegrationDefUpdate + | BrowserbaseExtensionIntegrationDefUpdate | BrowserbaseListSessionsIntegrationDefUpdate | BrowserbaseCreateSessionIntegrationDefUpdate | BrowserbaseGetSessionIntegrationDefUpdate - | BrowserbaseUpdateSessionIntegrationDefUpdate + | BrowserbaseCompleteSessionIntegrationDefUpdate | BrowserbaseGetSessionLiveUrlsIntegrationDefUpdate + | BrowserbaseGetSessionConnectUrlIntegrationDefUpdate + | RemoteBrowserIntegrationDefUpdate | None ) = None """ @@ -920,6 +998,153 @@ class PatchToolRequest(BaseModel): bash_20241022: Bash20241022DefUpdate | None = None +class RemoteBrowserArguments(BaseModel): + """ + The arguments for the remote browser + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + action: Literal[ + "key", + "type", + "mouse_move", + "left_click", + "left_click_drag", + "right_click", + "middle_click", + "double_click", + "screenshot", + "cursor_position", + "navigate", + "refresh", + "wait_for_load", + ] + """ + The action to perform + """ + text: str | None = None + """ + The text + """ + coordinate: list | None = None + """ + The coordinate to move the mouse to + """ + + +class RemoteBrowserArgumentsUpdate(BaseModel): + """ + The arguments for the remote browser + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + action: ( + Literal[ + "key", + "type", + "mouse_move", + "left_click", + "left_click_drag", + "right_click", + "middle_click", + "double_click", + "screenshot", + "cursor_position", + "navigate", + "refresh", + "wait_for_load", + ] + | None + ) = None + """ + The action to perform + """ + text: str | None = None + """ + The text + """ + coordinate: list | None = None + """ + The coordinate to move the mouse to + """ + + +class RemoteBrowserIntegrationDef(BaseIntegrationDef): + """ + The integration definition for the remote browser + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + provider: Literal["remote_browser"] = "remote_browser" + setup: RemoteBrowserSetup + method: Literal["perform_action"] = "perform_action" + arguments: RemoteBrowserArguments + + +class RemoteBrowserIntegrationDefUpdate(BaseIntegrationDefUpdate): + """ + The integration definition for the remote browser + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + provider: Literal["remote_browser"] = "remote_browser" + setup: RemoteBrowserSetupUpdate | None = None + method: Literal["perform_action"] = "perform_action" + arguments: RemoteBrowserArgumentsUpdate | None = None + + +class RemoteBrowserSetup(BaseModel): + """ + The setup parameters for the remote browser + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + connect_url: AnyUrl + """ + The connection URL for the remote browser + """ + width: int | None = None + """ + The width of the browser + """ + height: int | None = None + """ + The height of the browser + """ + + +class RemoteBrowserSetupUpdate(BaseModel): + """ + The setup parameters for the remote browser + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + connect_url: AnyUrl | None = None + """ + The connection URL for the remote browser + """ + width: int | None = None + """ + The width of the browser + """ + height: int | None = None + """ + The height of the browser + """ + + class SpiderFetchArguments(BaseModel): """ Arguments for Spider integration @@ -1171,11 +1396,14 @@ class Tool(BaseModel): | WikipediaIntegrationDef | WeatherIntegrationDef | BrowserbaseContextIntegrationDef + | BrowserbaseExtensionIntegrationDef | BrowserbaseListSessionsIntegrationDef | BrowserbaseCreateSessionIntegrationDef | BrowserbaseGetSessionIntegrationDef - | BrowserbaseUpdateSessionIntegrationDef + | BrowserbaseCompleteSessionIntegrationDef | BrowserbaseGetSessionLiveUrlsIntegrationDef + | BrowserbaseGetSessionConnectUrlIntegrationDef + | RemoteBrowserIntegrationDef | None ) = None """ @@ -1245,11 +1473,14 @@ class UpdateToolRequest(BaseModel): | WikipediaIntegrationDef | WeatherIntegrationDef | BrowserbaseContextIntegrationDef + | BrowserbaseExtensionIntegrationDef | BrowserbaseListSessionsIntegrationDef | BrowserbaseCreateSessionIntegrationDef | BrowserbaseGetSessionIntegrationDef - | BrowserbaseUpdateSessionIntegrationDef + | BrowserbaseCompleteSessionIntegrationDef | BrowserbaseGetSessionLiveUrlsIntegrationDef + | BrowserbaseGetSessionConnectUrlIntegrationDef + | RemoteBrowserIntegrationDef | None ) = None """ @@ -1483,12 +1714,10 @@ class BaseBrowserbaseIntegrationDef(BaseIntegrationDef): "list_sessions", "create_session", "get_session", - "update_session", + "complete_session", + "get_connect_url", + "install_extension_from_github", "create_context", - "upload_extension", - "get_extension", - "delete_extension", - "create_session_uploads", "get_session_downloads", "get_logs", "get_recordings", @@ -1514,12 +1743,10 @@ class BaseBrowserbaseIntegrationDefUpdate(BaseIntegrationDefUpdate): "list_sessions", "create_session", "get_session", - "update_session", + "complete_session", + "get_connect_url", + "install_extension_from_github", "create_context", - "upload_extension", - "get_extension", - "delete_extension", - "create_session_uploads", "get_session_downloads", "get_logs", "get_recordings", @@ -1529,6 +1756,32 @@ class BaseBrowserbaseIntegrationDefUpdate(BaseIntegrationDefUpdate): arguments: Any | None = None +class BrowserbaseCompleteSessionIntegrationDef(BaseBrowserbaseIntegrationDef): + """ + browserbase complete session integration definition + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + method: Literal["complete_session"] = "complete_session" + arguments: BrowserbaseCompleteSessionArguments + + +class BrowserbaseCompleteSessionIntegrationDefUpdate( + BaseBrowserbaseIntegrationDefUpdate +): + """ + browserbase complete session integration definition + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + method: Literal["complete_session"] = "complete_session" + arguments: BrowserbaseCompleteSessionArgumentsUpdate | None = None + + class BrowserbaseContextIntegrationDef(BaseBrowserbaseIntegrationDef): """ browserbase context provider @@ -1541,7 +1794,7 @@ class BrowserbaseContextIntegrationDef(BaseBrowserbaseIntegrationDef): """ The specific method of the integration to call """ - arguments: Any | None = None + arguments: BrowserbaseContextArguments | None = None """ The arguments for the method """ @@ -1559,7 +1812,7 @@ class BrowserbaseContextIntegrationDefUpdate(BaseBrowserbaseIntegrationDefUpdate """ The specific method of the integration to call """ - arguments: Any | None = None + arguments: BrowserbaseContextArgumentsUpdate | None = None """ The arguments for the method """ @@ -1595,6 +1848,68 @@ class BrowserbaseCreateSessionIntegrationDefUpdate(BaseBrowserbaseIntegrationDef """ +class BrowserbaseExtensionIntegrationDef(BaseBrowserbaseIntegrationDef): + """ + browserbase extension provider + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + method: Literal["install_extension_from_github"] | None = None + """ + The specific method of the integration to call + """ + arguments: BrowserbaseExtensionArguments | None = None + """ + The arguments for the method + """ + + +class BrowserbaseExtensionIntegrationDefUpdate(BaseBrowserbaseIntegrationDefUpdate): + """ + browserbase extension provider + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + method: Literal["install_extension_from_github"] | None = None + """ + The specific method of the integration to call + """ + arguments: BrowserbaseExtensionArgumentsUpdate | None = None + """ + The arguments for the method + """ + + +class BrowserbaseGetSessionConnectUrlIntegrationDef(BaseBrowserbaseIntegrationDef): + """ + browserbase get session connect url integration definition + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + method: Literal["get_connect_url"] = "get_connect_url" + arguments: BrowserbaseGetSessionConnectUrlArguments + + +class BrowserbaseGetSessionConnectUrlIntegrationDefUpdate( + BaseBrowserbaseIntegrationDefUpdate +): + """ + browserbase get session connect url integration definition + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + method: Literal["get_connect_url"] = "get_connect_url" + arguments: BrowserbaseGetSessionConnectUrlArgumentsUpdate | None = None + + class BrowserbaseGetSessionIntegrationDef(BaseBrowserbaseIntegrationDef): """ browserbase get session integration definition @@ -1679,27 +1994,3 @@ class BrowserbaseListSessionsIntegrationDefUpdate(BaseBrowserbaseIntegrationDefU """ The arguments for the method """ - - -class BrowserbaseUpdateSessionIntegrationDef(BaseBrowserbaseIntegrationDef): - """ - browserbase update session integration definition - """ - - model_config = ConfigDict( - populate_by_name=True, - ) - method: Literal["update_session"] = "update_session" - arguments: BrowserbaseUpdateSessionArguments - - -class BrowserbaseUpdateSessionIntegrationDefUpdate(BaseBrowserbaseIntegrationDefUpdate): - """ - browserbase update session integration definition - """ - - model_config = ConfigDict( - populate_by_name=True, - ) - method: Literal["update_session"] = "update_session" - arguments: BrowserbaseUpdateSessionArgumentsUpdate | None = None diff --git a/agents-api/agents_api/common/exceptions/tasks.py b/agents-api/agents_api/common/exceptions/tasks.py index 1f14e2e85..78f3e967a 100644 --- a/agents-api/agents_api/common/exceptions/tasks.py +++ b/agents-api/agents_api/common/exceptions/tasks.py @@ -10,6 +10,7 @@ """ import asyncio +from typing import cast import beartype import beartype.roar @@ -163,10 +164,12 @@ def is_retryable_error(error: BaseException) -> bool: # Special handling for HTTP errors (because they're special snowflakes) if isinstance(error, fastapi.exceptions.HTTPException): + error = cast(fastapi.exceptions.HTTPException, error) if error.status_code in RETRYABLE_HTTP_STATUS_CODES: return True if isinstance(error, httpx.HTTPStatusError): + error = cast(httpx.HTTPStatusError, error) if error.response.status_code in RETRYABLE_HTTP_STATUS_CODES: return True diff --git a/integrations-service/integrations/autogen/Tools.py b/integrations-service/integrations/autogen/Tools.py index dffe08e88..f38dc9bc4 100644 --- a/integrations-service/integrations/autogen/Tools.py +++ b/integrations-service/integrations/autogen/Tools.py @@ -174,7 +174,14 @@ class BaseIntegrationDef(BaseModel): populate_by_name=True, ) provider: Literal[ - "dummy", "weather", "wikipedia", "spider", "brave", "browserbase", "email" + "dummy", + "weather", + "wikipedia", + "spider", + "brave", + "browserbase", + "email", + "remote_browser", ] """ The provider of the integration @@ -203,7 +210,14 @@ class BaseIntegrationDefUpdate(BaseModel): ) provider: ( Literal[ - "dummy", "weather", "wikipedia", "spider", "brave", "browserbase", "email" + "dummy", + "weather", + "wikipedia", + "spider", + "brave", + "browserbase", + "email", + "remote_browser", ] | None ) = None @@ -344,6 +358,42 @@ class BraveSearchSetupUpdate(BaseModel): """ +class BrowserbaseCompleteSessionArguments(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: str + status: Literal["REQUEST_RELEASE"] = "REQUEST_RELEASE" + + +class BrowserbaseCompleteSessionArgumentsUpdate(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: str | None = None + status: Literal["REQUEST_RELEASE"] = "REQUEST_RELEASE" + + +class BrowserbaseContextArguments(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + project_id: Annotated[str, Field(alias="projectId")] + """ + The Project ID. Can be found in Settings. + """ + + +class BrowserbaseContextArgumentsUpdate(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + project_id: Annotated[str | None, Field(alias="projectId")] = None + """ + The Project ID. Can be found in Settings. + """ + + class BrowserbaseCreateSessionArguments(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -354,7 +404,7 @@ class BrowserbaseCreateSessionArguments(BaseModel): """ extension_id: Annotated[str | None, Field(alias="extensionId")] = None """ - The uploaded Extension ID. See Upload Extension. + The installed Extension ID. See Install Extension from GitHub. """ browser_settings: Annotated[ dict[str, Any] | None, Field(alias="browserSettings") @@ -386,7 +436,7 @@ class BrowserbaseCreateSessionArgumentsUpdate(BaseModel): """ extension_id: Annotated[str | None, Field(alias="extensionId")] = None """ - The uploaded Extension ID. See Upload Extension. + The installed Extension ID. See Install Extension from GitHub. """ browser_settings: Annotated[ dict[str, Any] | None, Field(alias="browserSettings") @@ -408,6 +458,34 @@ class BrowserbaseCreateSessionArgumentsUpdate(BaseModel): """ +class BrowserbaseExtensionArguments(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + repository_name: Annotated[str, Field(alias="repositoryName")] + """ + The GitHub repository name. + """ + ref: str | None = None + """ + Ref to install from a branch or tag. + """ + + +class BrowserbaseExtensionArgumentsUpdate(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + repository_name: Annotated[str | None, Field(alias="repositoryName")] = None + """ + The GitHub repository name. + """ + ref: str | None = None + """ + Ref to install from a branch or tag. + """ + + class BrowserbaseGetSessionArguments(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -422,6 +500,16 @@ class BrowserbaseGetSessionArgumentsUpdate(BaseModel): id: str | None = None +class BrowserbaseGetSessionConnectUrlArguments(BrowserbaseGetSessionArguments): + pass + + +class BrowserbaseGetSessionConnectUrlArgumentsUpdate( + BrowserbaseGetSessionArgumentsUpdate +): + pass + + class BrowserbaseGetSessionLiveUrlsArguments(BrowserbaseGetSessionArguments): pass @@ -470,22 +558,6 @@ class BrowserbaseSetupUpdate(BaseModel): """ -class BrowserbaseUpdateSessionArguments(BaseModel): - model_config = ConfigDict( - populate_by_name=True, - ) - id: str - status: Literal["REQUEST_RELEASE"] = "REQUEST_RELEASE" - - -class BrowserbaseUpdateSessionArgumentsUpdate(BaseModel): - model_config = ConfigDict( - populate_by_name=True, - ) - id: str | None = None - status: Literal["REQUEST_RELEASE"] | None = None - - class ChosenBash20241022(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -631,11 +703,14 @@ class CreateToolRequest(BaseModel): | WikipediaIntegrationDef | WeatherIntegrationDef | BrowserbaseContextIntegrationDef + | BrowserbaseExtensionIntegrationDef | BrowserbaseListSessionsIntegrationDef | BrowserbaseCreateSessionIntegrationDef | BrowserbaseGetSessionIntegrationDef - | BrowserbaseUpdateSessionIntegrationDef + | BrowserbaseCompleteSessionIntegrationDef | BrowserbaseGetSessionLiveUrlsIntegrationDef + | BrowserbaseGetSessionConnectUrlIntegrationDef + | RemoteBrowserIntegrationDef | None ) = None """ @@ -894,11 +969,14 @@ class PatchToolRequest(BaseModel): | WikipediaIntegrationDefUpdate | WeatherIntegrationDefUpdate | BrowserbaseContextIntegrationDefUpdate + | BrowserbaseExtensionIntegrationDefUpdate | BrowserbaseListSessionsIntegrationDefUpdate | BrowserbaseCreateSessionIntegrationDefUpdate | BrowserbaseGetSessionIntegrationDefUpdate - | BrowserbaseUpdateSessionIntegrationDefUpdate + | BrowserbaseCompleteSessionIntegrationDefUpdate | BrowserbaseGetSessionLiveUrlsIntegrationDefUpdate + | BrowserbaseGetSessionConnectUrlIntegrationDefUpdate + | RemoteBrowserIntegrationDefUpdate | None ) = None """ @@ -920,6 +998,153 @@ class PatchToolRequest(BaseModel): bash_20241022: Bash20241022DefUpdate | None = None +class RemoteBrowserArguments(BaseModel): + """ + The arguments for the remote browser + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + action: Literal[ + "key", + "type", + "mouse_move", + "left_click", + "left_click_drag", + "right_click", + "middle_click", + "double_click", + "screenshot", + "cursor_position", + "navigate", + "refresh", + "wait_for_load", + ] + """ + The action to perform + """ + text: str | None = None + """ + The text + """ + coordinate: list | None = None + """ + The coordinate to move the mouse to + """ + + +class RemoteBrowserArgumentsUpdate(BaseModel): + """ + The arguments for the remote browser + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + action: ( + Literal[ + "key", + "type", + "mouse_move", + "left_click", + "left_click_drag", + "right_click", + "middle_click", + "double_click", + "screenshot", + "cursor_position", + "navigate", + "refresh", + "wait_for_load", + ] + | None + ) = None + """ + The action to perform + """ + text: str | None = None + """ + The text + """ + coordinate: list | None = None + """ + The coordinate to move the mouse to + """ + + +class RemoteBrowserIntegrationDef(BaseIntegrationDef): + """ + The integration definition for the remote browser + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + provider: Literal["remote_browser"] = "remote_browser" + setup: RemoteBrowserSetup + method: Literal["perform_action"] = "perform_action" + arguments: RemoteBrowserArguments + + +class RemoteBrowserIntegrationDefUpdate(BaseIntegrationDefUpdate): + """ + The integration definition for the remote browser + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + provider: Literal["remote_browser"] = "remote_browser" + setup: RemoteBrowserSetupUpdate | None = None + method: Literal["perform_action"] = "perform_action" + arguments: RemoteBrowserArgumentsUpdate | None = None + + +class RemoteBrowserSetup(BaseModel): + """ + The setup parameters for the remote browser + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + connect_url: AnyUrl + """ + The connection URL for the remote browser + """ + width: int | None = None + """ + The width of the browser + """ + height: int | None = None + """ + The height of the browser + """ + + +class RemoteBrowserSetupUpdate(BaseModel): + """ + The setup parameters for the remote browser + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + connect_url: AnyUrl | None = None + """ + The connection URL for the remote browser + """ + width: int | None = None + """ + The width of the browser + """ + height: int | None = None + """ + The height of the browser + """ + + class SpiderFetchArguments(BaseModel): """ Arguments for Spider integration @@ -1171,11 +1396,14 @@ class Tool(BaseModel): | WikipediaIntegrationDef | WeatherIntegrationDef | BrowserbaseContextIntegrationDef + | BrowserbaseExtensionIntegrationDef | BrowserbaseListSessionsIntegrationDef | BrowserbaseCreateSessionIntegrationDef | BrowserbaseGetSessionIntegrationDef - | BrowserbaseUpdateSessionIntegrationDef + | BrowserbaseCompleteSessionIntegrationDef | BrowserbaseGetSessionLiveUrlsIntegrationDef + | BrowserbaseGetSessionConnectUrlIntegrationDef + | RemoteBrowserIntegrationDef | None ) = None """ @@ -1245,11 +1473,14 @@ class UpdateToolRequest(BaseModel): | WikipediaIntegrationDef | WeatherIntegrationDef | BrowserbaseContextIntegrationDef + | BrowserbaseExtensionIntegrationDef | BrowserbaseListSessionsIntegrationDef | BrowserbaseCreateSessionIntegrationDef | BrowserbaseGetSessionIntegrationDef - | BrowserbaseUpdateSessionIntegrationDef + | BrowserbaseCompleteSessionIntegrationDef | BrowserbaseGetSessionLiveUrlsIntegrationDef + | BrowserbaseGetSessionConnectUrlIntegrationDef + | RemoteBrowserIntegrationDef | None ) = None """ @@ -1483,12 +1714,10 @@ class BaseBrowserbaseIntegrationDef(BaseIntegrationDef): "list_sessions", "create_session", "get_session", - "update_session", + "complete_session", + "get_connect_url", + "install_extension_from_github", "create_context", - "upload_extension", - "get_extension", - "delete_extension", - "create_session_uploads", "get_session_downloads", "get_logs", "get_recordings", @@ -1514,12 +1743,10 @@ class BaseBrowserbaseIntegrationDefUpdate(BaseIntegrationDefUpdate): "list_sessions", "create_session", "get_session", - "update_session", + "complete_session", + "get_connect_url", + "install_extension_from_github", "create_context", - "upload_extension", - "get_extension", - "delete_extension", - "create_session_uploads", "get_session_downloads", "get_logs", "get_recordings", @@ -1529,6 +1756,32 @@ class BaseBrowserbaseIntegrationDefUpdate(BaseIntegrationDefUpdate): arguments: Any | None = None +class BrowserbaseCompleteSessionIntegrationDef(BaseBrowserbaseIntegrationDef): + """ + browserbase complete session integration definition + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + method: Literal["complete_session"] = "complete_session" + arguments: BrowserbaseCompleteSessionArguments + + +class BrowserbaseCompleteSessionIntegrationDefUpdate( + BaseBrowserbaseIntegrationDefUpdate +): + """ + browserbase complete session integration definition + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + method: Literal["complete_session"] = "complete_session" + arguments: BrowserbaseCompleteSessionArgumentsUpdate | None = None + + class BrowserbaseContextIntegrationDef(BaseBrowserbaseIntegrationDef): """ browserbase context provider @@ -1541,7 +1794,7 @@ class BrowserbaseContextIntegrationDef(BaseBrowserbaseIntegrationDef): """ The specific method of the integration to call """ - arguments: Any | None = None + arguments: BrowserbaseContextArguments | None = None """ The arguments for the method """ @@ -1559,7 +1812,7 @@ class BrowserbaseContextIntegrationDefUpdate(BaseBrowserbaseIntegrationDefUpdate """ The specific method of the integration to call """ - arguments: Any | None = None + arguments: BrowserbaseContextArgumentsUpdate | None = None """ The arguments for the method """ @@ -1595,6 +1848,68 @@ class BrowserbaseCreateSessionIntegrationDefUpdate(BaseBrowserbaseIntegrationDef """ +class BrowserbaseExtensionIntegrationDef(BaseBrowserbaseIntegrationDef): + """ + browserbase extension provider + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + method: Literal["install_extension_from_github"] | None = None + """ + The specific method of the integration to call + """ + arguments: BrowserbaseExtensionArguments | None = None + """ + The arguments for the method + """ + + +class BrowserbaseExtensionIntegrationDefUpdate(BaseBrowserbaseIntegrationDefUpdate): + """ + browserbase extension provider + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + method: Literal["install_extension_from_github"] | None = None + """ + The specific method of the integration to call + """ + arguments: BrowserbaseExtensionArgumentsUpdate | None = None + """ + The arguments for the method + """ + + +class BrowserbaseGetSessionConnectUrlIntegrationDef(BaseBrowserbaseIntegrationDef): + """ + browserbase get session connect url integration definition + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + method: Literal["get_connect_url"] = "get_connect_url" + arguments: BrowserbaseGetSessionConnectUrlArguments + + +class BrowserbaseGetSessionConnectUrlIntegrationDefUpdate( + BaseBrowserbaseIntegrationDefUpdate +): + """ + browserbase get session connect url integration definition + """ + + model_config = ConfigDict( + populate_by_name=True, + ) + method: Literal["get_connect_url"] = "get_connect_url" + arguments: BrowserbaseGetSessionConnectUrlArgumentsUpdate | None = None + + class BrowserbaseGetSessionIntegrationDef(BaseBrowserbaseIntegrationDef): """ browserbase get session integration definition @@ -1679,27 +1994,3 @@ class BrowserbaseListSessionsIntegrationDefUpdate(BaseBrowserbaseIntegrationDefU """ The arguments for the method """ - - -class BrowserbaseUpdateSessionIntegrationDef(BaseBrowserbaseIntegrationDef): - """ - browserbase update session integration definition - """ - - model_config = ConfigDict( - populate_by_name=True, - ) - method: Literal["update_session"] = "update_session" - arguments: BrowserbaseUpdateSessionArguments - - -class BrowserbaseUpdateSessionIntegrationDefUpdate(BaseBrowserbaseIntegrationDefUpdate): - """ - browserbase update session integration definition - """ - - model_config = ConfigDict( - populate_by_name=True, - ) - method: Literal["update_session"] = "update_session" - arguments: BrowserbaseUpdateSessionArgumentsUpdate | None = None diff --git a/integrations-service/integrations/models/__init__.py b/integrations-service/integrations/models/__init__.py index 817f37554..6264f1845 100644 --- a/integrations-service/integrations/models/__init__.py +++ b/integrations-service/integrations/models/__init__.py @@ -11,7 +11,29 @@ ProviderInfo as ProviderInfo, ) from .brave import BraveSearchOutput as BraveSearchOutput +from .browserbase import ( + BrowserbaseCompleteSessionOutput as BrowserbaseCompleteSessionOutput, +) +from .browserbase import ( + BrowserbaseCreateSessionOutput as BrowserbaseCreateSessionOutput, +) +from .browserbase import ( + BrowserbaseExtensionOutput as BrowserbaseExtensionOutput, +) +from .browserbase import ( + BrowserbaseGetSessionConnectUrlOutput as BrowserbaseGetSessionConnectUrlOutput, +) +from .browserbase import ( + BrowserbaseGetSessionLiveUrlsOutput as BrowserbaseGetSessionLiveUrlsOutput, +) +from .browserbase import ( + BrowserbaseGetSessionOutput as BrowserbaseGetSessionOutput, +) +from .browserbase import ( + BrowserbaseListSessionsOutput as BrowserbaseListSessionsOutput, +) from .email import EmailOutput as EmailOutput +from .remote_browser import RemoteBrowserOutput as RemoteBrowserOutput from .spider import SpiderFetchOutput as SpiderFetchOutput from .weather import WeatherGetOutput as WeatherGetOutput from .wikipedia import WikipediaSearchOutput as WikipediaSearchOutput diff --git a/integrations-service/integrations/models/browserbase.py b/integrations-service/integrations/models/browserbase.py new file mode 100644 index 000000000..2450b959c --- /dev/null +++ b/integrations-service/integrations/models/browserbase.py @@ -0,0 +1,129 @@ +from typing import Literal, Optional + +from pydantic import AnyUrl, Field + +from .base_models import BaseOutput + + +class SessionInfo(BaseOutput): + id: str = Field(..., description="Unique identifier for the session") + createdAt: str = Field( + ..., description="Timestamp indicating when the session was created" + ) + projectId: str = Field(..., description="The Project ID linked to the Session") + startedAt: str = Field(..., description="Timestamp when the session started") + endedAt: str = Field(..., description="Timestamp when the session ended") + expiresAt: str = Field( + ..., description="Timestamp when the session is set to expire" + ) + status: Literal["RUNNING", "ERROR", "TIMED_OUT", "COMPLETED"] = Field( + ..., description="Current status of the session" + ) + proxyBytes: int = Field(..., description="Bytes used via the Proxy") + avgCpuUsage: int = Field(..., description="CPU used by the Session") + memoryUsage: int = Field(..., description="Memory used by the Session") + keepAlive: bool = Field( + ..., + description="Indicates if the Session was created to be kept alive upon disconnections", + ) + contextId: Optional[str] = Field( + None, description="Optional. The Context linked to the Session." + ) + + +class BrowserbaseListSessionsOutput(BaseOutput): + sessions: list[SessionInfo] = Field(..., description="The list of sessions") + + +class BrowserbaseCreateSessionOutput(BaseOutput): + id: str = Field(..., description="Unique identifier for the session") + createdAt: str = Field( + ..., description="Timestamp indicating when the session was created" + ) + projectId: str = Field(..., description="The Project ID linked to the Session") + startedAt: str = Field(..., description="Timestamp when the session started") + endedAt: str = Field(..., description="Timestamp when the session ended") + expiresAt: str = Field( + ..., description="Timestamp when the session is set to expire" + ) + status: Literal["RUNNING", "ERROR", "TIMED_OUT", "COMPLETED"] = Field( + ..., description="Current status of the session" + ) + proxyBytes: int = Field(..., description="Bytes used via the Proxy") + avgCpuUsage: int = Field(..., description="CPU used by the Session") + memoryUsage: int = Field(..., description="Memory used by the Session") + keepAlive: bool = Field( + ..., + description="Indicates if the Session was created to be kept alive upon disconnections", + ) + contextId: Optional[str] = Field( + None, description="Optional. The Context linked to the Session." + ) + + +class BrowserbaseGetSessionOutput(BaseOutput): + id: str = Field(..., description="Unique identifier for the session") + createdAt: str = Field( + ..., description="Timestamp indicating when the session was created" + ) + projectId: str = Field(..., description="The Project ID linked to the Session") + startedAt: str = Field(..., description="Timestamp when the session started") + endedAt: str = Field(..., description="Timestamp when the session ended") + expiresAt: str = Field( + ..., description="Timestamp when the session is set to expire" + ) + status: Literal["RUNNING", "ERROR", "TIMED_OUT", "COMPLETED"] = Field( + ..., description="Current status of the session" + ) + proxyBytes: int = Field(..., description="Bytes used via the Proxy") + avgCpuUsage: int = Field(..., description="CPU used by the Session") + memoryUsage: int = Field(..., description="Memory used by the Session") + keepAlive: bool = Field( + ..., + description="Indicates if the Session was created to be kept alive upon disconnections", + ) + contextId: Optional[str] = Field( + None, description="Optional. The Context linked to the Session." + ) + + +class BrowserbaseCompleteSessionOutput(BaseOutput): + success: bool = Field( + ..., description="Indicates if the session was completed successfully" + ) + + +class BrowserbaseExtensionOutput(BaseOutput): + id: str = Field(..., description="Unique identifier for the extension") + + +class BrowserbaseGetSessionConnectUrlOutput(BaseOutput): + url: AnyUrl = Field(..., description="The connection URL for the session") + + +class PageInfo(BaseOutput): + id: Optional[str] = Field(None, description="Unique identifier for the page") + url: Optional[AnyUrl] = Field(None, description="URL of the page") + faviconUrl: Optional[AnyUrl] = Field(None, description="URL for the page's favicon") + title: Optional[str] = Field(None, description="Title of the page") + debuggerUrl: Optional[AnyUrl] = Field( + None, description="URL to access the debugger for this page" + ) + debuggerFullscreenUrl: Optional[AnyUrl] = Field( + None, description="URL to access the debugger in fullscreen for this page" + ) + + +class BrowserbaseGetSessionLiveUrlsOutput(BaseOutput): + debuggerFullscreenUrl: Optional[AnyUrl] = Field( + None, description="Fullscreen debugger URL for the session" + ) + debuggerUrl: Optional[AnyUrl] = Field( + None, description="Debugger URL for the session" + ) + wsUrl: Optional[AnyUrl] = Field( + None, description="WebSocket URL for live interaction with the session" + ) + pages: list[PageInfo] = Field( + ..., description="List of pages associated with the session" + ) diff --git a/integrations-service/integrations/models/remote_browser.py b/integrations-service/integrations/models/remote_browser.py new file mode 100644 index 000000000..de530feb0 --- /dev/null +++ b/integrations-service/integrations/models/remote_browser.py @@ -0,0 +1,9 @@ +from typing import Any + +from pydantic import Field + +from .base_models import BaseOutput + + +class RemoteBrowserOutput(BaseOutput): + result: Any = Field(..., description="The result of the action") diff --git a/integrations-service/integrations/providers.py b/integrations-service/integrations/providers.py index c595bae86..94feda69a 100644 --- a/integrations-service/integrations/providers.py +++ b/integrations-service/integrations/providers.py @@ -1,21 +1,39 @@ from .autogen.Tools import ( BraveSearchArguments, BraveSearchSetup, + BrowserbaseCompleteSessionArguments, + BrowserbaseCreateSessionArguments, + BrowserbaseExtensionArguments, + BrowserbaseGetSessionArguments, + BrowserbaseGetSessionConnectUrlArguments, + BrowserbaseGetSessionLiveUrlsArguments, + # WikipediaSearchSetup, + BrowserbaseListSessionsArguments, + BrowserbaseSetup, EmailArguments, EmailSetup, + RemoteBrowserArguments, + RemoteBrowserSetup, SpiderFetchArguments, SpiderSetup, WeatherGetArguments, WeatherSetup, WikipediaSearchArguments, - # WikipediaSearchSetup, ) from .models import ( BaseProvider, BaseProviderMethod, BraveSearchOutput, + BrowserbaseCompleteSessionOutput, + BrowserbaseCreateSessionOutput, + BrowserbaseExtensionOutput, + BrowserbaseGetSessionConnectUrlOutput, + BrowserbaseGetSessionLiveUrlsOutput, + BrowserbaseGetSessionOutput, + BrowserbaseListSessionsOutput, EmailOutput, ProviderInfo, + RemoteBrowserOutput, SpiderFetchOutput, WeatherGetOutput, WikipediaSearchOutput, @@ -113,10 +131,86 @@ ), ) +browserbase = BaseProvider( + provider="browserbase", + setup=BrowserbaseSetup, + methods=[ + BaseProviderMethod( + method="list_sessions", + description="List sessions in Browserbase", + arguments=BrowserbaseListSessionsArguments, + output=BrowserbaseListSessionsOutput, + ), + BaseProviderMethod( + method="create_session", + description="Create a session in Browserbase", + arguments=BrowserbaseCreateSessionArguments, + output=BrowserbaseCreateSessionOutput, + ), + BaseProviderMethod( + method="get_session", + description="Get a session in Browserbase", + arguments=BrowserbaseGetSessionArguments, + output=BrowserbaseGetSessionOutput, + ), + BaseProviderMethod( + method="complete_session", + description="Complete a session in Browserbase", + arguments=BrowserbaseCompleteSessionArguments, + output=BrowserbaseCompleteSessionOutput, + ), + BaseProviderMethod( + method="get_live_urls", + description="Get sessions' live urls in Browserbase", + arguments=BrowserbaseGetSessionLiveUrlsArguments, + output=BrowserbaseGetSessionLiveUrlsOutput, + ), + BaseProviderMethod( + method="install_extension_from_github", + description="Install an extension from GitHub to the browserbase context", + arguments=BrowserbaseExtensionArguments, + output=BrowserbaseExtensionOutput, + ), + BaseProviderMethod( + method="get_connect_url", + description="Get the connection URL for a session", + arguments=BrowserbaseGetSessionConnectUrlArguments, + output=BrowserbaseGetSessionConnectUrlOutput, + ), + ], + info=ProviderInfo( + friendly_name="BrowserBase", + url="https://browserbase.com/", + docs="https://browserbase.com/docs/", + icon="https://browserbase.com/favicon.ico", + ), +) + +remote_browser = BaseProvider( + provider="remote_browser", + setup=RemoteBrowserSetup, + methods=[ + BaseProviderMethod( + method="perform_action", + description="Perform an action in the browser", + arguments=RemoteBrowserArguments, + output=RemoteBrowserOutput, + ), + ], + info=ProviderInfo( + friendly_name="Remote Browser", + url="https://playwright.dev/", + docs="https://playwright.dev/docs/", + icon="https://playwright.dev/favicon.ico", + ), +) + available_providers: dict[str, BaseProvider] = { "wikipedia": wikipedia, "weather": weather, "spider": spider, "brave": brave, "email": email, + "browserbase": browserbase, + "remote_browser": remote_browser, } diff --git a/integrations-service/integrations/utils/integrations/assets/cursor-small.png b/integrations-service/integrations/utils/integrations/assets/cursor-small.png new file mode 100644 index 000000000..b9c59d0a7 Binary files /dev/null and b/integrations-service/integrations/utils/integrations/assets/cursor-small.png differ diff --git a/integrations-service/integrations/utils/integrations/assets/cursor.png b/integrations-service/integrations/utils/integrations/assets/cursor.png new file mode 100755 index 000000000..f8b688afb Binary files /dev/null and b/integrations-service/integrations/utils/integrations/assets/cursor.png differ diff --git a/integrations-service/integrations/utils/integrations/browserbase.py b/integrations-service/integrations/utils/integrations/browserbase.py new file mode 100644 index 000000000..ac2af5295 --- /dev/null +++ b/integrations-service/integrations/utils/integrations/browserbase.py @@ -0,0 +1,194 @@ +import os +import tempfile + +import httpx +from beartype import beartype +from browserbase import Browserbase, BrowserSettings, CreateSessionOptions +from tenacity import retry, stop_after_attempt, wait_exponential + +from ...autogen.Tools import ( + BrowserbaseCompleteSessionArguments, + BrowserbaseCreateSessionArguments, + BrowserbaseExtensionArguments, + BrowserbaseGetSessionArguments, + BrowserbaseGetSessionConnectUrlArguments, + BrowserbaseGetSessionLiveUrlsArguments, + BrowserbaseListSessionsArguments, + BrowserbaseSetup, +) +from ...models import ( + BrowserbaseCompleteSessionOutput, + BrowserbaseCreateSessionOutput, + BrowserbaseGetSessionConnectUrlOutput, + BrowserbaseGetSessionLiveUrlsOutput, + BrowserbaseGetSessionOutput, + BrowserbaseListSessionsOutput, +) +from ...models.browserbase import BrowserbaseExtensionOutput, SessionInfo + + +def get_browserbase_client(setup: BrowserbaseSetup) -> Browserbase: + return Browserbase(api_key=setup.api_key) + + +@beartype +@retry( + wait=wait_exponential(multiplier=1, min=4, max=10), + reraise=True, + stop=stop_after_attempt(4), +) +async def list_sessions( + setup: BrowserbaseSetup, arguments: BrowserbaseListSessionsArguments +) -> BrowserbaseListSessionsOutput: + client = get_browserbase_client(setup) + + # Run the list_sessions method + sessions = client.list_sessions() + + # Convert the sessions to the output model + sessions_output = [SessionInfo(**session.model_dump()) for session in sessions] + + return BrowserbaseListSessionsOutput(sessions=sessions_output) + + +@beartype +@retry( + wait=wait_exponential(multiplier=1, min=4, max=10), + reraise=True, + stop=stop_after_attempt(4), +) +async def create_session( + setup: BrowserbaseSetup, arguments: BrowserbaseCreateSessionArguments +) -> BrowserbaseCreateSessionOutput: + client = get_browserbase_client(setup) + + options = CreateSessionOptions( + projectId=arguments.project_id, + extensionId=arguments.extension_id, + browserSettings=BrowserSettings(**arguments.browser_settings), + ) + + session = client.create_session(options) + + return BrowserbaseCreateSessionOutput(**session.model_dump()) + + +@beartype +@retry( + wait=wait_exponential(multiplier=1, min=4, max=10), + reraise=True, + stop=stop_after_attempt(4), +) +async def get_session( + setup: BrowserbaseSetup, arguments: BrowserbaseGetSessionArguments +) -> BrowserbaseGetSessionOutput: + client = get_browserbase_client(setup) + + session = client.get_session(arguments.id) + + return BrowserbaseGetSessionOutput(**session.model_dump()) + + +@beartype +@retry( + wait=wait_exponential(multiplier=1, min=4, max=10), + reraise=True, + stop=stop_after_attempt(4), +) +async def complete_session( + setup: BrowserbaseSetup, arguments: BrowserbaseCompleteSessionArguments +) -> BrowserbaseCompleteSessionOutput: + client = get_browserbase_client(setup) + + try: + client.complete_session(arguments.id) + except Exception as e: + return BrowserbaseCompleteSessionOutput(success=False) + + return BrowserbaseCompleteSessionOutput(success=True) + + +@beartype +@retry( + wait=wait_exponential(multiplier=1, min=4, max=10), + reraise=True, + stop=stop_after_attempt(4), +) +async def get_session_live_urls( + setup: BrowserbaseSetup, arguments: BrowserbaseGetSessionLiveUrlsArguments +) -> BrowserbaseGetSessionLiveUrlsOutput: + client = get_browserbase_client(setup) + + urls = client.get_debug_connection_urls(arguments.id) + + return BrowserbaseGetSessionLiveUrlsOutput(**urls.model_dump()) + + +@beartype +@retry( + wait=wait_exponential(multiplier=1, min=4, max=10), + reraise=True, + stop=stop_after_attempt(4), +) +async def get_connect_url( + setup: BrowserbaseSetup, arguments: BrowserbaseGetSessionConnectUrlArguments +) -> BrowserbaseGetSessionConnectUrlOutput: + client = get_browserbase_client(setup) + + url = client.get_connect_url(arguments.id) + + return BrowserbaseGetSessionConnectUrlOutput(url=url) + + +@beartype +@retry( + wait=wait_exponential(multiplier=1, min=4, max=10), + reraise=True, + stop=stop_after_attempt(4), +) +async def install_extension_from_github( + setup: BrowserbaseSetup, arguments: BrowserbaseExtensionArguments +) -> BrowserbaseExtensionOutput: + """Download and install an extension from GitHub to the user's Browserbase account.""" + github_url = ( + f"https://github.com/{arguments.repo}/archive/refs/heads/{arguments.ref}.zip" + ) + + async with httpx.AsyncClient() as client: + # Download the extension zip + response = await client.get(github_url, follow_redirects=True) + response.raise_for_status() + + with tempfile.NamedTemporaryFile( + delete=True, delete_on_close=False, suffix=".zip" + ) as tmp_file: + tmp_file.write(response.content) + tmp_file_path = tmp_file.name + + # Upload the extension to Browserbase + upload_url = "https://www.browserbase.com/v1/extensions" + headers = { + # NOTE: httpx won't add a boundary if Content-Type header is set when you pass files= + # "Content-Type": "multipart/form-data", + "X-BB-API-Key": setup.api_key, + } + + with open(tmp_file_path, "rb") as f: + files = {"file": f} + upload_response = await client.post( + upload_url, headers=headers, files=files + ) + + try: + upload_response.raise_for_status() + except httpx.HTTPStatusError as e: + print(upload_response.text) + raise + + # Delete the temporary file + try: + os.remove(tmp_file_path) + except FileNotFoundError: + pass + + return BrowserbaseExtensionOutput(id=upload_response.json()["id"]) diff --git a/integrations-service/integrations/utils/integrations/remote_browser.py b/integrations-service/integrations/utils/integrations/remote_browser.py new file mode 100644 index 000000000..8140b5c2d --- /dev/null +++ b/integrations-service/integrations/utils/integrations/remote_browser.py @@ -0,0 +1,254 @@ +import base64 +import json +from functools import partial +from io import BytesIO +from pathlib import Path +from typing import Any + +from beartype import beartype +from PIL import Image +from playwright.async_api import ( + Browser, + BrowserContext, + Keyboard, + Mouse, + Page, + async_playwright, +) +from tenacity import retry, stop_after_attempt, wait_exponential + +from ...autogen.Tools import RemoteBrowserArguments, RemoteBrowserSetup +from ...models import RemoteBrowserOutput + +CURSOR_PATH = Path(__file__).parent / "assets" / "cursor-small.png" + + +class PlaywrightActions: + """Class to handle browser automation actions using Playwright.""" + + browser: Browser + page: Page + context: BrowserContext + mouse: Mouse + keyboard: Keyboard + current_x: int + current_y: int + width: int | None + height: int | None + + def __init__( + self, browser: Browser, width: int | None = None, height: int | None = None + ) -> None: + self.browser = browser + self.page = None + self.context = None + self.page = None + self.current_x: int = 0 + self.current_y: int = 0 + self.mouse = None + self.keyboard = None + self.width, self.height = width, height + + async def initialize(self) -> None: + self.context = self.browser.contexts[0] + self.page = self.context.pages[0] + self.mouse = self.page.mouse + self.keyboard = self.page.keyboard + + if self.width and self.height: + await self.set_screen_size(self.width, self.height) + + # Move mouse to center of screen + await self.mouse_move(coordinate=(self.width // 2, self.height // 2)) + + async def navigate(self, url: str) -> None: + """Navigate to a specific URL""" + await self.page.goto(url) + + async def refresh(self) -> None: + """Refresh the current page""" + await self.page.reload() + + async def wait_for_load(self, timeout: int = 30000) -> None: + """Wait for document to be fully loaded""" + await self.page.wait_for_load_state("domcontentloaded", timeout=timeout) + + async def execute_javascript(self, script: str, *args) -> Any: + """Execute JavaScript code and return the result""" + return await self.page.evaluate(script, *args) + + async def set_window_vars(self, variables: dict[str, Any]) -> None: + """Set variables in the window scope""" + json_str = json.dumps(variables) + script = """ + const vars = JSON.parse(arguments[0]); + for (const [key, value] of Object.entries(vars)) { + window[key] = value; + } + """ + await self.execute_javascript(script, json_str) + + async def get_screen_size(self) -> tuple[int, int]: + """Get the current browser viewport size""" + + viewport = self.page.viewport_size + return (viewport["width"], viewport["height"]) + + async def set_screen_size(self, width: int, height: int) -> None: + """Set the current browser viewport size""" + + await self.page.set_viewport_size(dict(width=width, height=height)) + self.width, self.height = width, height + + async def get_element_coordinates(self, selector: str) -> tuple[int, int]: + """Get the coordinates of an element""" + element = await self.page.query_selector(selector) + if element: + box = await element.bounding_box() + return (box["x"], box["y"]) + raise Exception(f"Element not found: {selector}") + + async def get_mouse_coordinates(self) -> tuple[int, int]: + """Get current mouse coordinates""" + return (self.current_x, self.current_y) + + async def press_key(self, key_combination: str) -> None: + """Press a key or key combination""" + # Split combination into individual keys + keys = key_combination.split("+") + + # Press modifier keys first + for key in keys[:-1]: + await self.page.keyboard.down(key) + + # Press and release the last key + await self.page.keyboard.press(keys[-1]) + + # Release modifier keys in reverse order + for key in reversed(keys[:-1]): + await self.page.keyboard.up(key) + + async def type_text(self, text: str) -> None: + """Type a string of text""" + await self.page.keyboard.type(text) + + async def mouse_move(self, coordinate: tuple[int, int]) -> None: + """Move mouse to specified coordinates""" + await self.mouse.move(*coordinate) + self.current_x, self.current_y = coordinate + + async def left_click(self) -> None: + """Perform left mouse click""" + await self.mouse.click(self.current_x, self.current_y) + + async def left_click_drag(self, coordinate: tuple[int, int]) -> None: + """Click and drag to specified coordinates""" + await self.mouse.down() + await self.mouse.move(*coordinate) + await self.mouse.up() + + self.current_x, self.current_y = coordinate + + async def right_click(self) -> None: + """Perform right mouse click""" + await self.mouse.click(self.current_x, self.current_y, button="right") + + async def middle_click(self) -> None: + """Perform middle mouse click""" + await self.mouse.click(self.current_x, self.current_y, button="middle") + + async def double_click(self) -> None: + """Perform double click""" + await self.mouse.dblclick(self.current_x, self.current_y) + + async def take_screenshot(self, filename: str | None = None) -> str | None: + """Take a screenshot of the current browser window""" + screenshot = await self.page.screenshot() + + x, y = await self.get_mouse_coordinates() + screenshot = self.overlay_cursor(screenshot, x, y) + + if filename: + with open(filename, "wb") as f: + f.write(screenshot) + return None + + encoded = base64.b64encode(screenshot).decode("utf-8") + return f"data:image/png;base64,{encoded}" + + async def perform_action( + self, + action: str, + coordinate: tuple[int, int] | None = None, + text: str | None = None, + ) -> tuple[int, int] | str | None: + """Perform a specified automation action""" + try: + actions = { + # Anthropic + "key": partial(self.press_key, text), + "type": partial(self.type_text, text), + "mouse_move": partial(self.mouse_move, coordinate), + "left_click": self.left_click, + "left_click_drag": partial(self.left_click_drag, coordinate), + "right_click": self.right_click, + "middle_click": self.middle_click, + "double_click": self.double_click, + "screenshot": self.take_screenshot, + "cursor_position": self.get_mouse_coordinates, + # + # Additional + "navigate": partial(self.navigate, text), + "refresh": self.refresh, + "wait_for_load": self.wait_for_load, + } + + if action not in actions: + raise ValueError(f"Invalid action: {action}") + + return await actions[action]() + + except Exception as e: + raise Exception(f"Error performing action {action}: {str(e)}") + + def overlay_cursor(self, screenshot_bytes: bytes, x: int, y: int) -> bytes: + """Overlay the cursor image on the screenshot at the specified coordinates.""" + # Load the screenshot from bytes + screenshot = Image.open(BytesIO(screenshot_bytes)).convert("RGBA") + + # Load the cursor image + cursor = Image.open(CURSOR_PATH.absolute()).convert("RGBA") + + # Create a copy of the screenshot to overlay the cursor + combined = screenshot.copy() + combined.paste(cursor, (x, y), cursor) + + # Save the combined image to bytes + output = BytesIO() + combined.save(output, format="PNG") + return output.getvalue() + + +@beartype +@retry( + wait=wait_exponential(multiplier=1, min=4, max=10), + reraise=True, + stop=stop_after_attempt(4), +) +async def perform_action( + setup: RemoteBrowserSetup, arguments: RemoteBrowserArguments +) -> RemoteBrowserOutput: + async with async_playwright() as p: + browser = await p.chromium.connect_over_cdp(setup.connect_url) + + automation = PlaywrightActions(browser, width=setup.width, height=setup.height) + + await automation.initialize() + + result = await automation.perform_action( + action=arguments.action, + coordinate=arguments.coordinate, + text=arguments.text, + ) + + return RemoteBrowserOutput(result=result) diff --git a/integrations-service/poetry.lock b/integrations-service/poetry.lock index f510bb906..0c2cacb6d 100644 --- a/integrations-service/poetry.lock +++ b/integrations-service/poetry.lock @@ -320,6 +320,85 @@ files = [ {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, ] +[[package]] +name = "cffi" +version = "1.17.1" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, + {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, + {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, + {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, + {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, + {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, + {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, + {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, +] + +[package.dependencies] +pycparser = "*" + [[package]] name = "charset-normalizer" version = "3.4.0" @@ -1767,6 +1846,20 @@ files = [ {file = "orjson-3.10.10.tar.gz", hash = "sha256:37949383c4df7b4337ce82ee35b6d7471e55195efa7dcb45ab8226ceadb0fe3b"}, ] +[[package]] +name = "outcome" +version = "1.3.0.post0" +description = "Capture the outcome of Python function calls." +optional = false +python-versions = ">=3.7" +files = [ + {file = "outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b"}, + {file = "outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8"}, +] + +[package.dependencies] +attrs = ">=19.2.0" + [[package]] name = "packaging" version = "24.1" @@ -1800,6 +1893,98 @@ files = [ {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, ] +[[package]] +name = "pillow" +version = "11.0.0" +description = "Python Imaging Library (Fork)" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pillow-11.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:6619654954dc4936fcff82db8eb6401d3159ec6be81e33c6000dfd76ae189947"}, + {file = "pillow-11.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b3c5ac4bed7519088103d9450a1107f76308ecf91d6dabc8a33a2fcfb18d0fba"}, + {file = "pillow-11.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a65149d8ada1055029fcb665452b2814fe7d7082fcb0c5bed6db851cb69b2086"}, + {file = "pillow-11.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88a58d8ac0cc0e7f3a014509f0455248a76629ca9b604eca7dc5927cc593c5e9"}, + {file = "pillow-11.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:c26845094b1af3c91852745ae78e3ea47abf3dbcd1cf962f16b9a5fbe3ee8488"}, + {file = "pillow-11.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:1a61b54f87ab5786b8479f81c4b11f4d61702830354520837f8cc791ebba0f5f"}, + {file = "pillow-11.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:674629ff60030d144b7bca2b8330225a9b11c482ed408813924619c6f302fdbb"}, + {file = "pillow-11.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:598b4e238f13276e0008299bd2482003f48158e2b11826862b1eb2ad7c768b97"}, + {file = "pillow-11.0.0-cp310-cp310-win32.whl", hash = "sha256:9a0f748eaa434a41fccf8e1ee7a3eed68af1b690e75328fd7a60af123c193b50"}, + {file = "pillow-11.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:a5629742881bcbc1f42e840af185fd4d83a5edeb96475a575f4da50d6ede337c"}, + {file = "pillow-11.0.0-cp310-cp310-win_arm64.whl", hash = "sha256:ee217c198f2e41f184f3869f3e485557296d505b5195c513b2bfe0062dc537f1"}, + {file = "pillow-11.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1c1d72714f429a521d8d2d018badc42414c3077eb187a59579f28e4270b4b0fc"}, + {file = "pillow-11.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:499c3a1b0d6fc8213519e193796eb1a86a1be4b1877d678b30f83fd979811d1a"}, + {file = "pillow-11.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8b2351c85d855293a299038e1f89db92a2f35e8d2f783489c6f0b2b5f3fe8a3"}, + {file = "pillow-11.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f4dba50cfa56f910241eb7f883c20f1e7b1d8f7d91c750cd0b318bad443f4d5"}, + {file = "pillow-11.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:5ddbfd761ee00c12ee1be86c9c0683ecf5bb14c9772ddbd782085779a63dd55b"}, + {file = "pillow-11.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:45c566eb10b8967d71bf1ab8e4a525e5a93519e29ea071459ce517f6b903d7fa"}, + {file = "pillow-11.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b4fd7bd29610a83a8c9b564d457cf5bd92b4e11e79a4ee4716a63c959699b306"}, + {file = "pillow-11.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:cb929ca942d0ec4fac404cbf520ee6cac37bf35be479b970c4ffadf2b6a1cad9"}, + {file = "pillow-11.0.0-cp311-cp311-win32.whl", hash = "sha256:006bcdd307cc47ba43e924099a038cbf9591062e6c50e570819743f5607404f5"}, + {file = "pillow-11.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:52a2d8323a465f84faaba5236567d212c3668f2ab53e1c74c15583cf507a0291"}, + {file = "pillow-11.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:16095692a253047fe3ec028e951fa4221a1f3ed3d80c397e83541a3037ff67c9"}, + {file = "pillow-11.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2c0a187a92a1cb5ef2c8ed5412dd8d4334272617f532d4ad4de31e0495bd923"}, + {file = "pillow-11.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:084a07ef0821cfe4858fe86652fffac8e187b6ae677e9906e192aafcc1b69903"}, + {file = "pillow-11.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8069c5179902dcdce0be9bfc8235347fdbac249d23bd90514b7a47a72d9fecf4"}, + {file = "pillow-11.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f02541ef64077f22bf4924f225c0fd1248c168f86e4b7abdedd87d6ebaceab0f"}, + {file = "pillow-11.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:fcb4621042ac4b7865c179bb972ed0da0218a076dc1820ffc48b1d74c1e37fe9"}, + {file = "pillow-11.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:00177a63030d612148e659b55ba99527803288cea7c75fb05766ab7981a8c1b7"}, + {file = "pillow-11.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8853a3bf12afddfdf15f57c4b02d7ded92c7a75a5d7331d19f4f9572a89c17e6"}, + {file = "pillow-11.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3107c66e43bda25359d5ef446f59c497de2b5ed4c7fdba0894f8d6cf3822dafc"}, + {file = "pillow-11.0.0-cp312-cp312-win32.whl", hash = "sha256:86510e3f5eca0ab87429dd77fafc04693195eec7fd6a137c389c3eeb4cfb77c6"}, + {file = "pillow-11.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:8ec4a89295cd6cd4d1058a5e6aec6bf51e0eaaf9714774e1bfac7cfc9051db47"}, + {file = "pillow-11.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:27a7860107500d813fcd203b4ea19b04babe79448268403172782754870dac25"}, + {file = "pillow-11.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bcd1fb5bb7b07f64c15618c89efcc2cfa3e95f0e3bcdbaf4642509de1942a699"}, + {file = "pillow-11.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0e038b0745997c7dcaae350d35859c9715c71e92ffb7e0f4a8e8a16732150f38"}, + {file = "pillow-11.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ae08bd8ffc41aebf578c2af2f9d8749d91f448b3bfd41d7d9ff573d74f2a6b2"}, + {file = "pillow-11.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d69bfd8ec3219ae71bcde1f942b728903cad25fafe3100ba2258b973bd2bc1b2"}, + {file = "pillow-11.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:61b887f9ddba63ddf62fd02a3ba7add935d053b6dd7d58998c630e6dbade8527"}, + {file = "pillow-11.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:c6a660307ca9d4867caa8d9ca2c2658ab685de83792d1876274991adec7b93fa"}, + {file = "pillow-11.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:73e3a0200cdda995c7e43dd47436c1548f87a30bb27fb871f352a22ab8dcf45f"}, + {file = "pillow-11.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fba162b8872d30fea8c52b258a542c5dfd7b235fb5cb352240c8d63b414013eb"}, + {file = "pillow-11.0.0-cp313-cp313-win32.whl", hash = "sha256:f1b82c27e89fffc6da125d5eb0ca6e68017faf5efc078128cfaa42cf5cb38798"}, + {file = "pillow-11.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ba470552b48e5835f1d23ecb936bb7f71d206f9dfeee64245f30c3270b994de"}, + {file = "pillow-11.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:846e193e103b41e984ac921b335df59195356ce3f71dcfd155aa79c603873b84"}, + {file = "pillow-11.0.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4ad70c4214f67d7466bea6a08061eba35c01b1b89eaa098040a35272a8efb22b"}, + {file = "pillow-11.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:6ec0d5af64f2e3d64a165f490d96368bb5dea8b8f9ad04487f9ab60dc4bb6003"}, + {file = "pillow-11.0.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c809a70e43c7977c4a42aefd62f0131823ebf7dd73556fa5d5950f5b354087e2"}, + {file = "pillow-11.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:4b60c9520f7207aaf2e1d94de026682fc227806c6e1f55bba7606d1c94dd623a"}, + {file = "pillow-11.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:1e2688958a840c822279fda0086fec1fdab2f95bf2b717b66871c4ad9859d7e8"}, + {file = "pillow-11.0.0-cp313-cp313t-win32.whl", hash = "sha256:607bbe123c74e272e381a8d1957083a9463401f7bd01287f50521ecb05a313f8"}, + {file = "pillow-11.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5c39ed17edea3bc69c743a8dd3e9853b7509625c2462532e62baa0732163a904"}, + {file = "pillow-11.0.0-cp313-cp313t-win_arm64.whl", hash = "sha256:75acbbeb05b86bc53cbe7b7e6fe00fbcf82ad7c684b3ad82e3d711da9ba287d3"}, + {file = "pillow-11.0.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:2e46773dc9f35a1dd28bd6981332fd7f27bec001a918a72a79b4133cf5291dba"}, + {file = "pillow-11.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2679d2258b7f1192b378e2893a8a0a0ca472234d4c2c0e6bdd3380e8dfa21b6a"}, + {file = "pillow-11.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eda2616eb2313cbb3eebbe51f19362eb434b18e3bb599466a1ffa76a033fb916"}, + {file = "pillow-11.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20ec184af98a121fb2da42642dea8a29ec80fc3efbaefb86d8fdd2606619045d"}, + {file = "pillow-11.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:8594f42df584e5b4bb9281799698403f7af489fba84c34d53d1c4bfb71b7c4e7"}, + {file = "pillow-11.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:c12b5ae868897c7338519c03049a806af85b9b8c237b7d675b8c5e089e4a618e"}, + {file = "pillow-11.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:70fbbdacd1d271b77b7721fe3cdd2d537bbbd75d29e6300c672ec6bb38d9672f"}, + {file = "pillow-11.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5178952973e588b3f1360868847334e9e3bf49d19e169bbbdfaf8398002419ae"}, + {file = "pillow-11.0.0-cp39-cp39-win32.whl", hash = "sha256:8c676b587da5673d3c75bd67dd2a8cdfeb282ca38a30f37950511766b26858c4"}, + {file = "pillow-11.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:94f3e1780abb45062287b4614a5bc0874519c86a777d4a7ad34978e86428b8dd"}, + {file = "pillow-11.0.0-cp39-cp39-win_arm64.whl", hash = "sha256:290f2cc809f9da7d6d622550bbf4c1e57518212da51b6a30fe8e0a270a5b78bd"}, + {file = "pillow-11.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1187739620f2b365de756ce086fdb3604573337cc28a0d3ac4a01ab6b2d2a6d2"}, + {file = "pillow-11.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fbbcb7b57dc9c794843e3d1258c0fbf0f48656d46ffe9e09b63bbd6e8cd5d0a2"}, + {file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d203af30149ae339ad1b4f710d9844ed8796e97fda23ffbc4cc472968a47d0b"}, + {file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21a0d3b115009ebb8ac3d2ebec5c2982cc693da935f4ab7bb5c8ebe2f47d36f2"}, + {file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:73853108f56df97baf2bb8b522f3578221e56f646ba345a372c78326710d3830"}, + {file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e58876c91f97b0952eb766123bfef372792ab3f4e3e1f1a2267834c2ab131734"}, + {file = "pillow-11.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:224aaa38177597bb179f3ec87eeefcce8e4f85e608025e9cfac60de237ba6316"}, + {file = "pillow-11.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5bd2d3bdb846d757055910f0a59792d33b555800813c3b39ada1829c372ccb06"}, + {file = "pillow-11.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:375b8dd15a1f5d2feafff536d47e22f69625c1aa92f12b339ec0b2ca40263273"}, + {file = "pillow-11.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:daffdf51ee5db69a82dd127eabecce20729e21f7a3680cf7cbb23f0829189790"}, + {file = "pillow-11.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7326a1787e3c7b0429659e0a944725e1b03eeaa10edd945a86dead1913383944"}, + {file = "pillow-11.0.0.tar.gz", hash = "sha256:72bacbaf24ac003fea9bff9837d1eedb6088758d41e100c1552930151f677739"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=8.1)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] +fpx = ["olefile"] +mic = ["olefile"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +typing = ["typing-extensions"] +xmp = ["defusedxml"] + [[package]] name = "platformdirs" version = "4.3.6" @@ -2018,6 +2203,17 @@ files = [ {file = "pycnite-2024.7.31.tar.gz", hash = "sha256:5125f1c95aef4a23b9bec3b32fae76873dcd46324fa68e39c10fa852ecdea340"}, ] +[[package]] +name = "pycparser" +version = "2.22" +description = "C parser in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, +] + [[package]] name = "pydantic" version = "2.9.2" @@ -2474,6 +2670,25 @@ files = [ {file = "ruff-0.6.9.tar.gz", hash = "sha256:b076ef717a8e5bc819514ee1d602bbdca5b4420ae13a9cf61a0c0a4f53a2baa2"}, ] +[[package]] +name = "selenium" +version = "4.25.0" +description = "Official Python bindings for Selenium WebDriver" +optional = false +python-versions = ">=3.8" +files = [ + {file = "selenium-4.25.0-py3-none-any.whl", hash = "sha256:3798d2d12b4a570bc5790163ba57fef10b2afee958bf1d80f2a3cf07c4141f33"}, + {file = "selenium-4.25.0.tar.gz", hash = "sha256:95d08d3b82fb353f3c474895154516604c7f0e6a9a565ae6498ef36c9bac6921"}, +] + +[package.dependencies] +certifi = ">=2021.10.8" +trio = ">=0.17,<1.0" +trio-websocket = ">=0.9,<1.0" +typing_extensions = ">=4.9,<5.0" +urllib3 = {version = ">=1.26,<3", extras = ["socks"]} +websocket-client = ">=1.8,<2.0" + [[package]] name = "setuptools" version = "75.2.0" @@ -2516,6 +2731,17 @@ files = [ {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] +[[package]] +name = "sortedcontainers" +version = "2.4.0" +description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +optional = false +python-versions = "*" +files = [ + {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, + {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, +] + [[package]] name = "soupsieve" version = "2.6" @@ -2737,6 +2963,40 @@ notebook = ["ipywidgets (>=6)"] slack = ["slack-sdk"] telegram = ["requests"] +[[package]] +name = "trio" +version = "0.27.0" +description = "A friendly Python library for async concurrency and I/O" +optional = false +python-versions = ">=3.8" +files = [ + {file = "trio-0.27.0-py3-none-any.whl", hash = "sha256:68eabbcf8f457d925df62da780eff15ff5dc68fd6b367e2dde59f7aaf2a0b884"}, + {file = "trio-0.27.0.tar.gz", hash = "sha256:1dcc95ab1726b2da054afea8fd761af74bad79bd52381b84eae408e983c76831"}, +] + +[package.dependencies] +attrs = ">=23.2.0" +cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""} +idna = "*" +outcome = "*" +sniffio = ">=1.3.0" +sortedcontainers = "*" + +[[package]] +name = "trio-websocket" +version = "0.11.1" +description = "WebSocket library for Trio" +optional = false +python-versions = ">=3.7" +files = [ + {file = "trio-websocket-0.11.1.tar.gz", hash = "sha256:18c11793647703c158b1f6e62de638acada927344d534e3c7628eedcb746839f"}, + {file = "trio_websocket-0.11.1-py3-none-any.whl", hash = "sha256:520d046b0d030cf970b8b2b2e00c4c2245b3807853ecd44214acd33d74581638"}, +] + +[package.dependencies] +trio = ">=0.11" +wsproto = ">=0.14" + [[package]] name = "tweepy" version = "4.14.0" @@ -2797,6 +3057,9 @@ files = [ {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, ] +[package.dependencies] +pysocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""} + [package.extras] brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] h2 = ["h2 (>=4,<5)"] @@ -2872,6 +3135,22 @@ dev = ["Cython (>=3.0,<4.0)", "setuptools (>=60)"] docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)"] test = ["aiohttp (>=3.10.5)", "flake8 (>=5.0,<6.0)", "mypy (>=0.800)", "psutil", "pyOpenSSL (>=23.0.0,<23.1.0)", "pycodestyle (>=2.9.0,<2.10.0)"] +[[package]] +name = "websocket-client" +version = "1.8.0" +description = "WebSocket client for Python with low level API options" +optional = false +python-versions = ">=3.8" +files = [ + {file = "websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526"}, + {file = "websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da"}, +] + +[package.extras] +docs = ["Sphinx (>=6.0)", "myst-parser (>=2.0.0)", "sphinx-rtd-theme (>=1.1.0)"] +optional = ["python-socks", "wsaccel"] +test = ["websockets"] + [[package]] name = "wikipedia" version = "1.4.0" @@ -2886,6 +3165,20 @@ files = [ beautifulsoup4 = "*" requests = ">=2.0.0,<3.0.0" +[[package]] +name = "wsproto" +version = "1.2.0" +description = "WebSockets state-machine based protocol implementation" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"}, + {file = "wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065"}, +] + +[package.dependencies] +h11 = ">=0.9.0,<1" + [[package]] name = "yarl" version = "1.17.0" @@ -2985,4 +3278,4 @@ propcache = ">=0.2.0" [metadata] lock-version = "2.0" python-versions = ">=3.12,<3.13" -content-hash = "00e1454fb5abfef9b136feb3441110d472bffbe362a8f39875fb864b59263ab4" +content-hash = "5f3578a1003d7d395f2218def650cfb875159a8f3ef581d72b99170a2bd51e6b" diff --git a/integrations-service/pyproject.toml b/integrations-service/pyproject.toml index 51137c2a4..3acf19997 100644 --- a/integrations-service/pyproject.toml +++ b/integrations-service/pyproject.toml @@ -24,6 +24,10 @@ beartype = "^0.19.0" tenacity = "^9.0.0" gunicorn = "^23.0.0" uvloop = "^0.21.0" +selenium = "^4.25.0" +playwright = "^1.48.0" +httpx = "^0.27.2" +pillow = "^11.0.0" [tool.poe.tasks] format = "ruff format" diff --git a/typespec/tools/browserbase/contexts.tsp b/typespec/tools/browserbase/contexts.tsp index a87eb55b7..188daa9a6 100644 --- a/typespec/tools/browserbase/contexts.tsp +++ b/typespec/tools/browserbase/contexts.tsp @@ -11,5 +11,19 @@ model BrowserbaseContextIntegrationDef extends BaseBrowserbaseIntegrationDef { method?: "create_context" = "create_context"; /** The arguments for the method */ - arguments?: unknown; + arguments?: BrowserbaseContextArguments; } + +model BrowserbaseContextArguments { + /** The Project ID. Can be found in Settings. */ + projectId: string; +} + +model BrowserbaseContextOutput { + id: string; + uploadUrl: url; + publicKey: string; + cipherAlgorithm: string; + initializationVectorSize: uint16; +} + diff --git a/typespec/tools/browserbase/extensions.tsp b/typespec/tools/browserbase/extensions.tsp index 3f825ea6f..6cdba57ed 100644 --- a/typespec/tools/browserbase/extensions.tsp +++ b/typespec/tools/browserbase/extensions.tsp @@ -5,12 +5,24 @@ using Common; namespace Tools; -// // TODO: Implement these -// /** browserbase extension provider */ -// model BrowserbaseExtensionIntegrationDef extends BaseBrowserbaseIntegrationDef { -// /** The specific method of the integration to call */ -// method?: "create_extension" | "get_extension" | "delete_extension"; - -// /** The arguments for the method */ -// arguments?: unknown; -// } +/** browserbase extension provider */ +model BrowserbaseExtensionIntegrationDef extends BaseBrowserbaseIntegrationDef { + /** The specific method of the integration to call */ + method?: "install_extension_from_github"; + + /** The arguments for the method */ + arguments?: BrowserbaseExtensionArguments; +} + +model BrowserbaseExtensionArguments { + /** The GitHub repository name. */ + repositoryName: string; + + /** Ref to install from a branch or tag. */ + ref?: string; +} + +model BrowserbaseExtensionOutput { + /** The installed Extension ID. */ + id: string; +} diff --git a/typespec/tools/browserbase/main.tsp b/typespec/tools/browserbase/main.tsp index 5beb53301..19adc9bdb 100644 --- a/typespec/tools/browserbase/main.tsp +++ b/typespec/tools/browserbase/main.tsp @@ -7,47 +7,30 @@ namespace Tools; using Common; -alias BrowserbaseMethod = ( - /** Get live URLs from the browserbase context */ - | "get_live_urls" - - /** List the sessions in the browserbase context */ - | "list_sessions" - - /** Create a new session in the browserbase context */ - | "create_session" - - /** Get a session from the browserbase context */ - | "get_session" - - /** Update a session in the browserbase context */ - | "update_session" - - // TODO: Implement these - /** Create a new browserbase context */ - | "create_context" - - /** Upload an extension to the browserbase context */ - | "upload_extension" - - /** Get an extension from the browserbase context */ - | "get_extension" - - /** Delete an extension from the browserbase context */ - | "delete_extension" - - /** Create session uploads in the browserbase context */ - | "create_session_uploads" - - /** Get session downloads from the browserbase context */ - | "get_session_downloads" - - /** Get logs from the browserbase context */ - | "get_logs" - - /** Get recordings from the browserbase context */ - | "get_recordings" -); +alias BrowserbaseMethod = + | /** Get live URLs from the browserbase context */ + "get_live_urls" + | /** List the sessions in the browserbase context */ + "list_sessions" + | /** Create a new session in the browserbase context */ + "create_session" + | /** Get a session from the browserbase context */ + "get_session" + | /** Complete a session in the browserbase context */ + "complete_session" + | /** Get the connection URL for a session */ + "get_connect_url" + | /** Install an extension from GitHub to the browserbase context */ + "install_extension_from_github" + | // TODO: Implement these + /** Create a new browserbase context */ + "create_context" + | /** Get session downloads from the browserbase context */ + "get_session_downloads" + | /** Get logs from the browserbase context */ + "get_logs" + | /** Get recordings from the browserbase context */ + "get_recordings"; /** The setup parameters for the browserbase integration */ model BrowserbaseSetup { @@ -63,25 +46,11 @@ model BaseBrowserbaseIntegrationDef extends BaseIntegrationDef { arguments?: unknown; } -alias BrowserbaseIntegrationDef = ( - | BrowserbaseContextIntegrationDef - // | BrowserbaseExtensionIntegrationDef - | BrowserbaseSessionIntegrationDef -); +alias BrowserbaseIntegrationDef = BrowserbaseContextIntegrationDef | BrowserbaseExtensionIntegrationDef | BrowserbaseSessionIntegrationDef; -alias BrowserbaseArguments = ( - | BrowserbaseSessionArguments - // TODO: Implement these - // | BrowserbaseContextArguments - // | BrowserbaseExtensionArguments -); +alias BrowserbaseArguments = BrowserbaseSessionArguments | BrowserbaseContextArguments | BrowserbaseExtensionArguments; -alias BrowserbaseOutput = ( - | BrowserbaseSessionOutput - // TODO: Implement these - // | BrowserbaseContextOutput - // | BrowserbaseExtensionOutput -); +alias BrowserbaseOutput = BrowserbaseSessionOutput | BrowserbaseContextOutput | BrowserbaseExtensionOutput; model BrowserbaseProviderCard extends BaseProviderCard { provider: "browserbase" = "browserbase"; @@ -100,12 +69,20 @@ model BrowserbaseProviderCard extends BaseProviderCard { description: "Get a session from the browserbase context", }, #{ - method: "update_session", - description: "Update a session in the browserbase context", + method: "complete_session", + description: "Complete a session in the browserbase context", }, #{ - method: "get_session_live_urls", + method: "get_live_urls", description: "Get live URLs from the browserbase context", + }, + #{ + method: "install_extension_from_github", + description: "Install an extension from GitHub to the browserbase context", + }, + #{ + method: "get_connect_url", + description: "Get the connection URL for a session", } ]; -} \ No newline at end of file +} diff --git a/typespec/tools/browserbase/sessions.tsp b/typespec/tools/browserbase/sessions.tsp index 4008064aa..aa61a4690 100644 --- a/typespec/tools/browserbase/sessions.tsp +++ b/typespec/tools/browserbase/sessions.tsp @@ -4,45 +4,33 @@ using Common; namespace Tools; -alias BrowserbaseSessionMethod = ( - /** Get live URLs from the browserbase context */ - | "get_live_urls" - - /** List the sessions in the browserbase context */ - | "list_sessions" - - /** Create a new session in the browserbase context */ - | "create_session" - - /** Get a session from the browserbase context */ - | "get_session" - - /** Update a session in the browserbase context */ - | "update_session" - - // TODO: Implement these - | "create_context" - | "upload_extension" - | "get_extension" - | "delete_extension" - | "create_session_uploads" - | "get_session_downloads" +alias BrowserbaseSessionMethod = + | /** Get live URLs from the browserbase context */ + "get_live_urls" + | /** List the sessions in the browserbase context */ + "list_sessions" + | /** Create a new session in the browserbase context */ + "create_session" + | /** Get a session from the browserbase context */ + "get_session" + | /** Complete a session in the browserbase context */ + "complete_session" + | /** Get the connection URL for a session */ + "get_connect_url" + | // TODO: Implement these + "get_session_downloads" | "get_logs" - | "get_recordings" -); + | "get_recordings"; alias BrowserbaseSessionIntegrationDef = | BrowserbaseListSessionsIntegrationDef | BrowserbaseCreateSessionIntegrationDef | BrowserbaseGetSessionIntegrationDef - | BrowserbaseUpdateSessionIntegrationDef - | BrowserbaseGetSessionLiveUrlsIntegrationDef; + | BrowserbaseCompleteSessionIntegrationDef + | BrowserbaseGetSessionLiveUrlsIntegrationDef + | BrowserbaseGetSessionConnectUrlIntegrationDef; // // TODO: Implement these -// | BrowserbaseCreateContextIntegrationDef -// | BrowserbaseUploadExtensionIntegrationDef -// | BrowserbaseGetExtensionIntegrationDef -// | BrowserbaseDeleteExtensionIntegrationDef // | BrowserbaseCreateSessionUploadsIntegrationDef // | BrowserbaseGetSessionDownloadsIntegrationDef // | BrowserbaseGetLogsIntegrationDef @@ -52,14 +40,11 @@ alias BrowserbaseSessionArguments = | BrowserbaseListSessionsArguments | BrowserbaseCreateSessionArguments | BrowserbaseGetSessionArguments - | BrowserbaseUpdateSessionArguments - | BrowserbaseGetSessionLiveUrlsArguments; + | BrowserbaseCompleteSessionArguments + | BrowserbaseGetSessionLiveUrlsArguments + | BrowserbaseGetSessionConnectUrlArguments; // // TODO: Implement these -// | BrowserbaseCreateContextArguments -// | BrowserbaseUploadExtensionArguments -// | BrowserbaseGetExtensionArguments -// | BrowserbaseDeleteExtensionArguments // | BrowserbaseCreateSessionUploadsArguments // | BrowserbaseGetSessionDownloadsArguments // | BrowserbaseGetLogsArguments @@ -69,15 +54,11 @@ alias BrowserbaseSessionOutput = | BrowserbaseListSessionsOutput | BrowserbaseCreateSessionOutput | BrowserbaseGetSessionOutput - | BrowserbaseUpdateSessionOutput - | BrowserbaseGetSessionLiveUrlsOutput; + | BrowserbaseCompleteSessionOutput + | BrowserbaseGetSessionLiveUrlsOutput + | BrowserbaseGetSessionConnectUrlOutput; // // TODO: Implement these -// | BrowserbaseCreateContextOutput -// | BrowserbaseUploadExtensionOutput -// | BrowserbaseGetExtensionOutput -// | BrowserbaseDeleteExtensionOutput -// | BrowserbaseCreateSessionUploadsOutput // | BrowserbaseGetSessionDownloadsOutput // | BrowserbaseGetLogsOutput // | BrowserbaseGetRecordingsOutput @@ -126,7 +107,7 @@ model BrowserbaseCreateSessionArguments { /** The Project ID. Can be found in Settings. */ projectId: string; - /** The uploaded Extension ID. See Upload Extension. */ + /** The installed Extension ID. See Install Extension from GitHub. */ extensionId?: string; /** Browser settings */ @@ -145,7 +126,6 @@ model BrowserbaseCreateSessionArguments { model BrowserbaseCreateSessionOutput { id: string; createdAt: string; - updatedAt: string; projectId: string; startedAt: string; endedAt: string; @@ -172,7 +152,6 @@ model BrowserbaseGetSessionArguments { model BrowserbaseGetSessionOutput { id: string; createdAt: string; - updatedAt: string; projectId: string; startedAt: string; endedAt: string; @@ -185,32 +164,20 @@ model BrowserbaseGetSessionOutput { contextId?: string; } -/** browserbase update session integration definition */ -model BrowserbaseUpdateSessionIntegrationDef +/** browserbase complete session integration definition */ +model BrowserbaseCompleteSessionIntegrationDef extends BaseBrowserbaseIntegrationDef { - method: "update_session" = "update_session"; - arguments: BrowserbaseUpdateSessionArguments; + method: "complete_session" = "complete_session"; + arguments: BrowserbaseCompleteSessionArguments; } -model BrowserbaseUpdateSessionArguments { +model BrowserbaseCompleteSessionArguments { id: string; - status: "REQUEST_RELEASE"; + status: "REQUEST_RELEASE" = "REQUEST_RELEASE"; } -model BrowserbaseUpdateSessionOutput { - id: string; - createdAt: string; - updatedAt: string; - projectId: string; - startedAt: string; - endedAt: string; - expiresAt: string; - status: "RUNNING" | "ERROR" | "TIMED_OUT" | "COMPLETED"; - proxyBytes: uint64; - avgCpuUsage: uint64; - memoryUsage: uint64; - keepAlive: boolean; - contextId?: string; +model BrowserbaseCompleteSessionOutput { + success: boolean; } /** browserbase get session live urls integration definition */ @@ -237,3 +204,18 @@ model BrowserbaseGetSessionLiveUrlsOutput { debuggerFullscreenUrl?: url; }[] = #[]; } + +/** browserbase get session connect url integration definition */ +model BrowserbaseGetSessionConnectUrlIntegrationDef + extends BaseBrowserbaseIntegrationDef { + method: "get_connect_url" = "get_connect_url"; + arguments: BrowserbaseGetSessionConnectUrlArguments; +} + +model BrowserbaseGetSessionConnectUrlArguments { + id: string; +} + +model BrowserbaseGetSessionConnectUrlOutput { + url: url; +} diff --git a/typespec/tools/main.tsp b/typespec/tools/main.tsp index 38d4d7d57..1630ef965 100644 --- a/typespec/tools/main.tsp +++ b/typespec/tools/main.tsp @@ -7,6 +7,7 @@ import "./spider.tsp"; import "./weather.tsp"; import "./wikipedia.tsp"; import "./browserbase"; +import "./remote_browser.tsp"; namespace Tools; diff --git a/typespec/tools/models.tsp b/typespec/tools/models.tsp index dd41038b1..91ea7eb1c 100644 --- a/typespec/tools/models.tsp +++ b/typespec/tools/models.tsp @@ -22,6 +22,7 @@ alias integrationProvider = ( | "brave" | "browserbase" | "email" + | "remote_browser" ); enum ToolType { @@ -112,6 +113,7 @@ alias IntegrationDef = ( | WikipediaIntegrationDef | WeatherIntegrationDef | BrowserbaseIntegrationDef + | RemoteBrowserIntegrationDef ); // diff --git a/typespec/tools/remote_browser.tsp b/typespec/tools/remote_browser.tsp new file mode 100644 index 000000000..4087e5df8 --- /dev/null +++ b/typespec/tools/remote_browser.tsp @@ -0,0 +1,120 @@ +import "../common"; + +using Common; + +namespace Tools; + +/* +async def perform_action( + self, + action: str, + coordinate: tuple[int, int] | None = None, + text: str | None = None, +) -> tuple[int, int] | str | None: + """Perform a specified automation action""" + + actions = { + # Anthropic + "key": lambda: text and self.press_key(text), + "type": lambda: text and self.type_text(text), + "mouse_move": lambda: coordinate and self.mouse_move(*coordinate), + "left_click": self.left_click, + "left_click_drag": lambda: coordinate + and self.left_click_drag(*coordinate), + "right_click": self.right_click, + "middle_click": self.middle_click, + "double_click": self.double_click, + "screenshot": self.take_screenshot, + "cursor_position": self.get_mouse_coordinates, + # Additional + "navigate": lambda: text and self.navigate(text), + "refresh": self.refresh, + "wait_for_load": self.wait_for_load, + } + + ... + +*/ + +alias RemoteBrowserAction = /** Press a key */ + + | "key" + | /** Type text */ + "type" + | /** Move the mouse to a coordinate */ + "mouse_move" + | /** Left click */ + "left_click" + | /** Left click and drag */ + "left_click_drag" + | /** Right click */ + "right_click" + | /** Middle click */ + "middle_click" + | /** Double click */ + "double_click" + | /** Take a screenshot */ + "screenshot" + | /** Get the cursor position */ + "cursor_position" + | /** Navigate to a URL */ + "navigate" + | /** Refresh the page */ + "refresh" + | /** Wait for the page to load */ + "wait_for_load"; + +/** The setup parameters for the remote browser */ +model RemoteBrowserSetup { + /** The connection URL for the remote browser */ + connect_url: url; + + /** The width of the browser */ + width?: uint16; + + /** The height of the browser */ + height?: uint16; +} + +/** The arguments for the remote browser */ +model RemoteBrowserArguments { + /** The action to perform */ + action: RemoteBrowserAction; + + /** The text */ + text?: string; + + /** The coordinate to move the mouse to */ + coordinate?: [uint16, uint16]; +} + +/** The output of the remote browser */ +model RemoteBrowserOutput { + /** The result of the action */ + result: unknown; +} + +/** The integration definition for the remote browser */ +model RemoteBrowserIntegrationDef extends BaseIntegrationDef { + provider: "remote_browser" = "remote_browser"; + setup: RemoteBrowserSetup; + method: "perform_action" = "perform_action"; + arguments: RemoteBrowserArguments; +} + +model RemoteBrowserProviderCard extends BaseProviderCard { + provider: "remote_browser" = "remote_browser"; + setup: RemoteBrowserSetup; + methods: ProviderMethod[] = #[ + #{ + method: "perform_action", + description: "Perform an action in the remote browser", + } + ]; + info: ProviderInfo = #{ + url: "https://playwright.dev/", + docs: "https://playwright.dev/docs/api/class-page", + icon: "https://playwright.dev/favicon.ico", + friendly_name: "Playwright", + }; +} diff --git a/typespec/tsp-output/@typespec/openapi3/openapi-1.0.0.yaml b/typespec/tsp-output/@typespec/openapi3/openapi-1.0.0.yaml index 803996838..a50b83813 100644 --- a/typespec/tsp-output/@typespec/openapi3/openapi-1.0.0.yaml +++ b/typespec/tsp-output/@typespec/openapi3/openapi-1.0.0.yaml @@ -5822,12 +5822,10 @@ components: - list_sessions - create_session - get_session - - update_session + - complete_session + - get_connect_url + - install_extension_from_github - create_context - - upload_extension - - get_extension - - delete_extension - - create_session_uploads - get_session_downloads - get_logs - get_recordings @@ -5852,12 +5850,10 @@ components: - list_sessions - create_session - get_session - - update_session + - complete_session + - get_connect_url + - install_extension_from_github - create_context - - upload_extension - - get_extension - - delete_extension - - create_session_uploads - get_session_downloads - get_logs - get_recordings @@ -5907,6 +5903,7 @@ components: - brave - browserbase - email + - remote_browser description: The provider of the integration method: type: string @@ -5924,6 +5921,7 @@ components: wikipedia: '#/components/schemas/Tools.WikipediaIntegrationDef' weather: '#/components/schemas/Tools.WeatherIntegrationDef' browserbase: '#/components/schemas/Tools.BaseBrowserbaseIntegrationDef' + remote_browser: '#/components/schemas/Tools.RemoteBrowserIntegrationDef' description: Integration definition Tools.BaseIntegrationDefUpdate: type: object @@ -5938,6 +5936,7 @@ components: - brave - browserbase - email + - remote_browser description: The provider of the integration method: type: string @@ -5955,6 +5954,7 @@ components: wikipedia: '#/components/schemas/Tools.WikipediaIntegrationDefUpdate' weather: '#/components/schemas/Tools.WeatherIntegrationDefUpdate' browserbase: '#/components/schemas/Tools.BaseBrowserbaseIntegrationDefUpdate' + remote_browser: '#/components/schemas/Tools.RemoteBrowserIntegrationDefUpdate' description: Integration definition Tools.Bash20241022Def: type: object @@ -6060,6 +6060,72 @@ components: type: string description: The api key for Brave Search description: Integration definition for Brave Search + Tools.BrowserbaseCompleteSessionArguments: + type: object + required: + - id + - status + properties: + id: + type: string + status: + type: string + enum: + - REQUEST_RELEASE + default: REQUEST_RELEASE + Tools.BrowserbaseCompleteSessionArgumentsUpdate: + type: object + properties: + id: + type: string + status: + type: string + enum: + - REQUEST_RELEASE + default: REQUEST_RELEASE + Tools.BrowserbaseCompleteSessionIntegrationDef: + type: object + required: + - method + - arguments + properties: + method: + type: string + enum: + - complete_session + default: complete_session + arguments: + $ref: '#/components/schemas/Tools.BrowserbaseCompleteSessionArguments' + allOf: + - $ref: '#/components/schemas/Tools.BaseBrowserbaseIntegrationDef' + description: browserbase complete session integration definition + Tools.BrowserbaseCompleteSessionIntegrationDefUpdate: + type: object + properties: + method: + type: string + enum: + - complete_session + default: complete_session + arguments: + $ref: '#/components/schemas/Tools.BrowserbaseCompleteSessionArgumentsUpdate' + allOf: + - $ref: '#/components/schemas/Tools.BaseBrowserbaseIntegrationDefUpdate' + description: browserbase complete session integration definition + Tools.BrowserbaseContextArguments: + type: object + required: + - projectId + properties: + projectId: + type: string + description: The Project ID. Can be found in Settings. + Tools.BrowserbaseContextArgumentsUpdate: + type: object + properties: + projectId: + type: string + description: The Project ID. Can be found in Settings. Tools.BrowserbaseContextIntegrationDef: type: object properties: @@ -6070,6 +6136,8 @@ components: description: The specific method of the integration to call default: create_context arguments: + allOf: + - $ref: '#/components/schemas/Tools.BrowserbaseContextArguments' description: The arguments for the method allOf: - $ref: '#/components/schemas/Tools.BaseBrowserbaseIntegrationDef' @@ -6084,6 +6152,8 @@ components: description: The specific method of the integration to call default: create_context arguments: + allOf: + - $ref: '#/components/schemas/Tools.BrowserbaseContextArgumentsUpdate' description: The arguments for the method allOf: - $ref: '#/components/schemas/Tools.BaseBrowserbaseIntegrationDefUpdate' @@ -6098,7 +6168,7 @@ components: description: The Project ID. Can be found in Settings. extensionId: type: string - description: The uploaded Extension ID. See Upload Extension. + description: The installed Extension ID. See Install Extension from GitHub. browserSettings: type: object additionalProperties: {} @@ -6126,7 +6196,7 @@ components: description: The Project ID. Can be found in Settings. extensionId: type: string - description: The uploaded Extension ID. See Upload Extension. + description: The installed Extension ID. See Install Extension from GitHub. browserSettings: type: object additionalProperties: {} @@ -6179,6 +6249,56 @@ components: allOf: - $ref: '#/components/schemas/Tools.BaseBrowserbaseIntegrationDefUpdate' description: browserbase create session integration definition + Tools.BrowserbaseExtensionArguments: + type: object + required: + - repositoryName + properties: + repositoryName: + type: string + description: The GitHub repository name. + ref: + type: string + description: Ref to install from a branch or tag. + Tools.BrowserbaseExtensionArgumentsUpdate: + type: object + properties: + repositoryName: + type: string + description: The GitHub repository name. + ref: + type: string + description: Ref to install from a branch or tag. + Tools.BrowserbaseExtensionIntegrationDef: + type: object + properties: + method: + type: string + enum: + - install_extension_from_github + description: The specific method of the integration to call + arguments: + allOf: + - $ref: '#/components/schemas/Tools.BrowserbaseExtensionArguments' + description: The arguments for the method + allOf: + - $ref: '#/components/schemas/Tools.BaseBrowserbaseIntegrationDef' + description: browserbase extension provider + Tools.BrowserbaseExtensionIntegrationDefUpdate: + type: object + properties: + method: + type: string + enum: + - install_extension_from_github + description: The specific method of the integration to call + arguments: + allOf: + - $ref: '#/components/schemas/Tools.BrowserbaseExtensionArgumentsUpdate' + description: The arguments for the method + allOf: + - $ref: '#/components/schemas/Tools.BaseBrowserbaseIntegrationDefUpdate' + description: browserbase extension provider Tools.BrowserbaseGetSessionArguments: type: object required: @@ -6191,6 +6311,47 @@ components: properties: id: type: string + Tools.BrowserbaseGetSessionConnectUrlArguments: + type: object + required: + - id + properties: + id: + type: string + Tools.BrowserbaseGetSessionConnectUrlArgumentsUpdate: + type: object + properties: + id: + type: string + Tools.BrowserbaseGetSessionConnectUrlIntegrationDef: + type: object + required: + - method + - arguments + properties: + method: + type: string + enum: + - get_connect_url + default: get_connect_url + arguments: + $ref: '#/components/schemas/Tools.BrowserbaseGetSessionConnectUrlArguments' + allOf: + - $ref: '#/components/schemas/Tools.BaseBrowserbaseIntegrationDef' + description: browserbase get session connect url integration definition + Tools.BrowserbaseGetSessionConnectUrlIntegrationDefUpdate: + type: object + properties: + method: + type: string + enum: + - get_connect_url + default: get_connect_url + arguments: + $ref: '#/components/schemas/Tools.BrowserbaseGetSessionConnectUrlArgumentsUpdate' + allOf: + - $ref: '#/components/schemas/Tools.BaseBrowserbaseIntegrationDefUpdate' + description: browserbase get session connect url integration definition Tools.BrowserbaseGetSessionIntegrationDef: type: object required: @@ -6322,56 +6483,6 @@ components: type: string description: API key for the browserbase integration description: The setup parameters for the browserbase integration - Tools.BrowserbaseUpdateSessionArguments: - type: object - required: - - id - - status - properties: - id: - type: string - status: - type: string - enum: - - REQUEST_RELEASE - Tools.BrowserbaseUpdateSessionArgumentsUpdate: - type: object - properties: - id: - type: string - status: - type: string - enum: - - REQUEST_RELEASE - Tools.BrowserbaseUpdateSessionIntegrationDef: - type: object - required: - - method - - arguments - properties: - method: - type: string - enum: - - update_session - default: update_session - arguments: - $ref: '#/components/schemas/Tools.BrowserbaseUpdateSessionArguments' - allOf: - - $ref: '#/components/schemas/Tools.BaseBrowserbaseIntegrationDef' - description: browserbase update session integration definition - Tools.BrowserbaseUpdateSessionIntegrationDefUpdate: - type: object - properties: - method: - type: string - enum: - - update_session - default: update_session - arguments: - $ref: '#/components/schemas/Tools.BrowserbaseUpdateSessionArgumentsUpdate' - allOf: - - $ref: '#/components/schemas/Tools.BaseBrowserbaseIntegrationDefUpdate' - description: browserbase update session integration definition Tools.ChosenBash20241022: type: object properties: @@ -6555,11 +6666,14 @@ components: - $ref: '#/components/schemas/Tools.WikipediaIntegrationDef' - $ref: '#/components/schemas/Tools.WeatherIntegrationDef' - $ref: '#/components/schemas/Tools.BrowserbaseContextIntegrationDef' + - $ref: '#/components/schemas/Tools.BrowserbaseExtensionIntegrationDef' - $ref: '#/components/schemas/Tools.BrowserbaseListSessionsIntegrationDef' - $ref: '#/components/schemas/Tools.BrowserbaseCreateSessionIntegrationDef' - $ref: '#/components/schemas/Tools.BrowserbaseGetSessionIntegrationDef' - - $ref: '#/components/schemas/Tools.BrowserbaseUpdateSessionIntegrationDef' + - $ref: '#/components/schemas/Tools.BrowserbaseCompleteSessionIntegrationDef' - $ref: '#/components/schemas/Tools.BrowserbaseGetSessionLiveUrlsIntegrationDef' + - $ref: '#/components/schemas/Tools.BrowserbaseGetSessionConnectUrlIntegrationDef' + - $ref: '#/components/schemas/Tools.RemoteBrowserIntegrationDef' description: The integration to call system: allOf: @@ -6776,11 +6890,14 @@ components: - $ref: '#/components/schemas/Tools.WikipediaIntegrationDefUpdate' - $ref: '#/components/schemas/Tools.WeatherIntegrationDefUpdate' - $ref: '#/components/schemas/Tools.BrowserbaseContextIntegrationDefUpdate' + - $ref: '#/components/schemas/Tools.BrowserbaseExtensionIntegrationDefUpdate' - $ref: '#/components/schemas/Tools.BrowserbaseListSessionsIntegrationDefUpdate' - $ref: '#/components/schemas/Tools.BrowserbaseCreateSessionIntegrationDefUpdate' - $ref: '#/components/schemas/Tools.BrowserbaseGetSessionIntegrationDefUpdate' - - $ref: '#/components/schemas/Tools.BrowserbaseUpdateSessionIntegrationDefUpdate' + - $ref: '#/components/schemas/Tools.BrowserbaseCompleteSessionIntegrationDefUpdate' - $ref: '#/components/schemas/Tools.BrowserbaseGetSessionLiveUrlsIntegrationDefUpdate' + - $ref: '#/components/schemas/Tools.BrowserbaseGetSessionConnectUrlIntegrationDefUpdate' + - $ref: '#/components/schemas/Tools.RemoteBrowserIntegrationDefUpdate' description: The integration to call system: allOf: @@ -6799,6 +6916,143 @@ components: bash_20241022: $ref: '#/components/schemas/Tools.Bash20241022DefUpdate' description: Payload for patching a tool + Tools.RemoteBrowserArguments: + type: object + required: + - action + properties: + action: + type: string + enum: + - key + - type + - mouse_move + - left_click + - left_click_drag + - right_click + - middle_click + - double_click + - screenshot + - cursor_position + - navigate + - refresh + - wait_for_load + description: The action to perform + text: + type: string + description: The text + coordinate: + type: array + items: {} + description: The coordinate to move the mouse to + description: The arguments for the remote browser + Tools.RemoteBrowserArgumentsUpdate: + type: object + properties: + action: + type: string + enum: + - key + - type + - mouse_move + - left_click + - left_click_drag + - right_click + - middle_click + - double_click + - screenshot + - cursor_position + - navigate + - refresh + - wait_for_load + description: The action to perform + text: + type: string + description: The text + coordinate: + type: array + items: {} + description: The coordinate to move the mouse to + description: The arguments for the remote browser + Tools.RemoteBrowserIntegrationDef: + type: object + required: + - provider + - setup + - method + - arguments + properties: + provider: + type: string + enum: + - remote_browser + default: remote_browser + setup: + $ref: '#/components/schemas/Tools.RemoteBrowserSetup' + method: + type: string + enum: + - perform_action + default: perform_action + arguments: + $ref: '#/components/schemas/Tools.RemoteBrowserArguments' + allOf: + - $ref: '#/components/schemas/Tools.BaseIntegrationDef' + description: The integration definition for the remote browser + Tools.RemoteBrowserIntegrationDefUpdate: + type: object + properties: + provider: + type: string + enum: + - remote_browser + default: remote_browser + setup: + $ref: '#/components/schemas/Tools.RemoteBrowserSetupUpdate' + method: + type: string + enum: + - perform_action + default: perform_action + arguments: + $ref: '#/components/schemas/Tools.RemoteBrowserArgumentsUpdate' + allOf: + - $ref: '#/components/schemas/Tools.BaseIntegrationDefUpdate' + description: The integration definition for the remote browser + Tools.RemoteBrowserSetup: + type: object + required: + - connect_url + properties: + connect_url: + type: string + format: uri + description: The connection URL for the remote browser + width: + type: integer + format: uint16 + description: The width of the browser + height: + type: integer + format: uint16 + description: The height of the browser + description: The setup parameters for the remote browser + Tools.RemoteBrowserSetupUpdate: + type: object + properties: + connect_url: + type: string + format: uri + description: The connection URL for the remote browser + width: + type: integer + format: uint16 + description: The width of the browser + height: + type: integer + format: uint16 + description: The height of the browser + description: The setup parameters for the remote browser Tools.SpiderFetchArguments: type: object required: @@ -7050,11 +7304,14 @@ components: - $ref: '#/components/schemas/Tools.WikipediaIntegrationDef' - $ref: '#/components/schemas/Tools.WeatherIntegrationDef' - $ref: '#/components/schemas/Tools.BrowserbaseContextIntegrationDef' + - $ref: '#/components/schemas/Tools.BrowserbaseExtensionIntegrationDef' - $ref: '#/components/schemas/Tools.BrowserbaseListSessionsIntegrationDef' - $ref: '#/components/schemas/Tools.BrowserbaseCreateSessionIntegrationDef' - $ref: '#/components/schemas/Tools.BrowserbaseGetSessionIntegrationDef' - - $ref: '#/components/schemas/Tools.BrowserbaseUpdateSessionIntegrationDef' + - $ref: '#/components/schemas/Tools.BrowserbaseCompleteSessionIntegrationDef' - $ref: '#/components/schemas/Tools.BrowserbaseGetSessionLiveUrlsIntegrationDef' + - $ref: '#/components/schemas/Tools.BrowserbaseGetSessionConnectUrlIntegrationDef' + - $ref: '#/components/schemas/Tools.RemoteBrowserIntegrationDef' description: The integration to call system: allOf: @@ -7133,11 +7390,14 @@ components: - $ref: '#/components/schemas/Tools.WikipediaIntegrationDef' - $ref: '#/components/schemas/Tools.WeatherIntegrationDef' - $ref: '#/components/schemas/Tools.BrowserbaseContextIntegrationDef' + - $ref: '#/components/schemas/Tools.BrowserbaseExtensionIntegrationDef' - $ref: '#/components/schemas/Tools.BrowserbaseListSessionsIntegrationDef' - $ref: '#/components/schemas/Tools.BrowserbaseCreateSessionIntegrationDef' - $ref: '#/components/schemas/Tools.BrowserbaseGetSessionIntegrationDef' - - $ref: '#/components/schemas/Tools.BrowserbaseUpdateSessionIntegrationDef' + - $ref: '#/components/schemas/Tools.BrowserbaseCompleteSessionIntegrationDef' - $ref: '#/components/schemas/Tools.BrowserbaseGetSessionLiveUrlsIntegrationDef' + - $ref: '#/components/schemas/Tools.BrowserbaseGetSessionConnectUrlIntegrationDef' + - $ref: '#/components/schemas/Tools.RemoteBrowserIntegrationDef' description: The integration to call system: allOf: