optexity-browser-use 0.9.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- browser_use/__init__.py +157 -0
- browser_use/actor/__init__.py +11 -0
- browser_use/actor/element.py +1175 -0
- browser_use/actor/mouse.py +134 -0
- browser_use/actor/page.py +561 -0
- browser_use/actor/playground/flights.py +41 -0
- browser_use/actor/playground/mixed_automation.py +54 -0
- browser_use/actor/playground/playground.py +236 -0
- browser_use/actor/utils.py +176 -0
- browser_use/agent/cloud_events.py +282 -0
- browser_use/agent/gif.py +424 -0
- browser_use/agent/judge.py +170 -0
- browser_use/agent/message_manager/service.py +473 -0
- browser_use/agent/message_manager/utils.py +52 -0
- browser_use/agent/message_manager/views.py +98 -0
- browser_use/agent/prompts.py +413 -0
- browser_use/agent/service.py +2316 -0
- browser_use/agent/system_prompt.md +185 -0
- browser_use/agent/system_prompt_flash.md +10 -0
- browser_use/agent/system_prompt_no_thinking.md +183 -0
- browser_use/agent/views.py +743 -0
- browser_use/browser/__init__.py +41 -0
- browser_use/browser/cloud/cloud.py +203 -0
- browser_use/browser/cloud/views.py +89 -0
- browser_use/browser/events.py +578 -0
- browser_use/browser/profile.py +1158 -0
- browser_use/browser/python_highlights.py +548 -0
- browser_use/browser/session.py +3225 -0
- browser_use/browser/session_manager.py +399 -0
- browser_use/browser/video_recorder.py +162 -0
- browser_use/browser/views.py +200 -0
- browser_use/browser/watchdog_base.py +260 -0
- browser_use/browser/watchdogs/__init__.py +0 -0
- browser_use/browser/watchdogs/aboutblank_watchdog.py +253 -0
- browser_use/browser/watchdogs/crash_watchdog.py +335 -0
- browser_use/browser/watchdogs/default_action_watchdog.py +2729 -0
- browser_use/browser/watchdogs/dom_watchdog.py +817 -0
- browser_use/browser/watchdogs/downloads_watchdog.py +1277 -0
- browser_use/browser/watchdogs/local_browser_watchdog.py +461 -0
- browser_use/browser/watchdogs/permissions_watchdog.py +43 -0
- browser_use/browser/watchdogs/popups_watchdog.py +143 -0
- browser_use/browser/watchdogs/recording_watchdog.py +126 -0
- browser_use/browser/watchdogs/screenshot_watchdog.py +62 -0
- browser_use/browser/watchdogs/security_watchdog.py +280 -0
- browser_use/browser/watchdogs/storage_state_watchdog.py +335 -0
- browser_use/cli.py +2359 -0
- browser_use/code_use/__init__.py +16 -0
- browser_use/code_use/formatting.py +192 -0
- browser_use/code_use/namespace.py +665 -0
- browser_use/code_use/notebook_export.py +276 -0
- browser_use/code_use/service.py +1340 -0
- browser_use/code_use/system_prompt.md +574 -0
- browser_use/code_use/utils.py +150 -0
- browser_use/code_use/views.py +171 -0
- browser_use/config.py +505 -0
- browser_use/controller/__init__.py +3 -0
- browser_use/dom/enhanced_snapshot.py +161 -0
- browser_use/dom/markdown_extractor.py +169 -0
- browser_use/dom/playground/extraction.py +312 -0
- browser_use/dom/playground/multi_act.py +32 -0
- browser_use/dom/serializer/clickable_elements.py +200 -0
- browser_use/dom/serializer/code_use_serializer.py +287 -0
- browser_use/dom/serializer/eval_serializer.py +478 -0
- browser_use/dom/serializer/html_serializer.py +212 -0
- browser_use/dom/serializer/paint_order.py +197 -0
- browser_use/dom/serializer/serializer.py +1170 -0
- browser_use/dom/service.py +825 -0
- browser_use/dom/utils.py +129 -0
- browser_use/dom/views.py +906 -0
- browser_use/exceptions.py +5 -0
- browser_use/filesystem/__init__.py +0 -0
- browser_use/filesystem/file_system.py +619 -0
- browser_use/init_cmd.py +376 -0
- browser_use/integrations/gmail/__init__.py +24 -0
- browser_use/integrations/gmail/actions.py +115 -0
- browser_use/integrations/gmail/service.py +225 -0
- browser_use/llm/__init__.py +155 -0
- browser_use/llm/anthropic/chat.py +242 -0
- browser_use/llm/anthropic/serializer.py +312 -0
- browser_use/llm/aws/__init__.py +36 -0
- browser_use/llm/aws/chat_anthropic.py +242 -0
- browser_use/llm/aws/chat_bedrock.py +289 -0
- browser_use/llm/aws/serializer.py +257 -0
- browser_use/llm/azure/chat.py +91 -0
- browser_use/llm/base.py +57 -0
- browser_use/llm/browser_use/__init__.py +3 -0
- browser_use/llm/browser_use/chat.py +201 -0
- browser_use/llm/cerebras/chat.py +193 -0
- browser_use/llm/cerebras/serializer.py +109 -0
- browser_use/llm/deepseek/chat.py +212 -0
- browser_use/llm/deepseek/serializer.py +109 -0
- browser_use/llm/exceptions.py +29 -0
- browser_use/llm/google/__init__.py +3 -0
- browser_use/llm/google/chat.py +542 -0
- browser_use/llm/google/serializer.py +120 -0
- browser_use/llm/groq/chat.py +229 -0
- browser_use/llm/groq/parser.py +158 -0
- browser_use/llm/groq/serializer.py +159 -0
- browser_use/llm/messages.py +238 -0
- browser_use/llm/models.py +271 -0
- browser_use/llm/oci_raw/__init__.py +10 -0
- browser_use/llm/oci_raw/chat.py +443 -0
- browser_use/llm/oci_raw/serializer.py +229 -0
- browser_use/llm/ollama/chat.py +97 -0
- browser_use/llm/ollama/serializer.py +143 -0
- browser_use/llm/openai/chat.py +264 -0
- browser_use/llm/openai/like.py +15 -0
- browser_use/llm/openai/serializer.py +165 -0
- browser_use/llm/openrouter/chat.py +211 -0
- browser_use/llm/openrouter/serializer.py +26 -0
- browser_use/llm/schema.py +176 -0
- browser_use/llm/views.py +48 -0
- browser_use/logging_config.py +330 -0
- browser_use/mcp/__init__.py +18 -0
- browser_use/mcp/__main__.py +12 -0
- browser_use/mcp/client.py +544 -0
- browser_use/mcp/controller.py +264 -0
- browser_use/mcp/server.py +1114 -0
- browser_use/observability.py +204 -0
- browser_use/py.typed +0 -0
- browser_use/sandbox/__init__.py +41 -0
- browser_use/sandbox/sandbox.py +637 -0
- browser_use/sandbox/views.py +132 -0
- browser_use/screenshots/__init__.py +1 -0
- browser_use/screenshots/service.py +52 -0
- browser_use/sync/__init__.py +6 -0
- browser_use/sync/auth.py +357 -0
- browser_use/sync/service.py +161 -0
- browser_use/telemetry/__init__.py +51 -0
- browser_use/telemetry/service.py +112 -0
- browser_use/telemetry/views.py +101 -0
- browser_use/tokens/__init__.py +0 -0
- browser_use/tokens/custom_pricing.py +24 -0
- browser_use/tokens/mappings.py +4 -0
- browser_use/tokens/service.py +580 -0
- browser_use/tokens/views.py +108 -0
- browser_use/tools/registry/service.py +572 -0
- browser_use/tools/registry/views.py +174 -0
- browser_use/tools/service.py +1675 -0
- browser_use/tools/utils.py +82 -0
- browser_use/tools/views.py +100 -0
- browser_use/utils.py +670 -0
- optexity_browser_use-0.9.5.dist-info/METADATA +344 -0
- optexity_browser_use-0.9.5.dist-info/RECORD +147 -0
- optexity_browser_use-0.9.5.dist-info/WHEEL +4 -0
- optexity_browser_use-0.9.5.dist-info/entry_points.txt +3 -0
- optexity_browser_use-0.9.5.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
# Type stubs for lazy imports
|
|
4
|
+
if TYPE_CHECKING:
|
|
5
|
+
from .profile import BrowserProfile, ProxySettings
|
|
6
|
+
from .session import BrowserSession
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Lazy imports mapping for heavy browser components
|
|
10
|
+
_LAZY_IMPORTS = {
|
|
11
|
+
'ProxySettings': ('.profile', 'ProxySettings'),
|
|
12
|
+
'BrowserProfile': ('.profile', 'BrowserProfile'),
|
|
13
|
+
'BrowserSession': ('.session', 'BrowserSession'),
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def __getattr__(name: str):
|
|
18
|
+
"""Lazy import mechanism for heavy browser components."""
|
|
19
|
+
if name in _LAZY_IMPORTS:
|
|
20
|
+
module_path, attr_name = _LAZY_IMPORTS[name]
|
|
21
|
+
try:
|
|
22
|
+
from importlib import import_module
|
|
23
|
+
|
|
24
|
+
# Use relative import for current package
|
|
25
|
+
full_module_path = f'browser_use.browser{module_path}'
|
|
26
|
+
module = import_module(full_module_path)
|
|
27
|
+
attr = getattr(module, attr_name)
|
|
28
|
+
# Cache the imported attribute in the module's globals
|
|
29
|
+
globals()[name] = attr
|
|
30
|
+
return attr
|
|
31
|
+
except ImportError as e:
|
|
32
|
+
raise ImportError(f'Failed to import {name} from {full_module_path}: {e}') from e
|
|
33
|
+
|
|
34
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
__all__ = [
|
|
38
|
+
'BrowserSession',
|
|
39
|
+
'BrowserProfile',
|
|
40
|
+
'ProxySettings',
|
|
41
|
+
]
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"""Cloud browser service integration for browser-use.
|
|
2
|
+
|
|
3
|
+
This module provides integration with the browser-use cloud browser service.
|
|
4
|
+
When cloud_browser=True, it automatically creates a cloud browser instance
|
|
5
|
+
and returns the CDP URL for connection.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
import os
|
|
10
|
+
|
|
11
|
+
import httpx
|
|
12
|
+
|
|
13
|
+
from browser_use.browser.cloud.views import CloudBrowserAuthError, CloudBrowserError, CloudBrowserResponse, CreateBrowserRequest
|
|
14
|
+
from browser_use.sync.auth import CloudAuthConfig
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class CloudBrowserClient:
|
|
20
|
+
"""Client for browser-use cloud browser service."""
|
|
21
|
+
|
|
22
|
+
def __init__(self, api_base_url: str = 'https://api.browser-use.com'):
|
|
23
|
+
self.api_base_url = api_base_url
|
|
24
|
+
self.client = httpx.AsyncClient(timeout=30.0)
|
|
25
|
+
self.current_session_id: str | None = None
|
|
26
|
+
|
|
27
|
+
async def create_browser(
|
|
28
|
+
self, request: CreateBrowserRequest, extra_headers: dict[str, str] | None = None
|
|
29
|
+
) -> CloudBrowserResponse:
|
|
30
|
+
"""Create a new cloud browser instance. For full docs refer to https://docs.cloud.browser-use.com/api-reference/v-2-api-current/browsers/create-browser-session-browsers-post
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
request: CreateBrowserRequest object containing browser creation parameters
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
CloudBrowserResponse: Contains CDP URL and other browser info
|
|
37
|
+
"""
|
|
38
|
+
url = f'{self.api_base_url}/api/v2/browsers'
|
|
39
|
+
|
|
40
|
+
# Try to get API key from environment variable first, then auth config
|
|
41
|
+
api_token = os.getenv('BROWSER_USE_API_KEY')
|
|
42
|
+
|
|
43
|
+
if not api_token:
|
|
44
|
+
# Fallback to auth config file
|
|
45
|
+
try:
|
|
46
|
+
auth_config = CloudAuthConfig.load_from_file()
|
|
47
|
+
api_token = auth_config.api_token
|
|
48
|
+
except Exception:
|
|
49
|
+
pass
|
|
50
|
+
|
|
51
|
+
if not api_token:
|
|
52
|
+
raise CloudBrowserAuthError(
|
|
53
|
+
'No authentication token found. Please set BROWSER_USE_API_KEY environment variable to authenticate with the cloud service. You can also create an API key at https://cloud.browser-use.com/new-api-key'
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
headers = {'X-Browser-Use-API-Key': api_token, 'Content-Type': 'application/json', **(extra_headers or {})}
|
|
57
|
+
|
|
58
|
+
# Convert request to dictionary and exclude unset fields
|
|
59
|
+
request_body = request.model_dump(exclude_unset=True)
|
|
60
|
+
|
|
61
|
+
try:
|
|
62
|
+
logger.info('🌤️ Creating cloud browser instance...')
|
|
63
|
+
|
|
64
|
+
response = await self.client.post(url, headers=headers, json=request_body)
|
|
65
|
+
|
|
66
|
+
if response.status_code == 401:
|
|
67
|
+
raise CloudBrowserAuthError(
|
|
68
|
+
'Authentication failed. Please make sure you have set BROWSER_USE_API_KEY environment variable to authenticate with the cloud service. You can also create an API key at https://cloud.browser-use.com/new-api-key'
|
|
69
|
+
)
|
|
70
|
+
elif response.status_code == 403:
|
|
71
|
+
raise CloudBrowserAuthError('Access forbidden. Please check your browser-use cloud subscription status.')
|
|
72
|
+
elif not response.is_success:
|
|
73
|
+
error_msg = f'Failed to create cloud browser: HTTP {response.status_code}'
|
|
74
|
+
try:
|
|
75
|
+
error_data = response.json()
|
|
76
|
+
if 'detail' in error_data:
|
|
77
|
+
error_msg += f' - {error_data["detail"]}'
|
|
78
|
+
except Exception:
|
|
79
|
+
pass
|
|
80
|
+
raise CloudBrowserError(error_msg)
|
|
81
|
+
|
|
82
|
+
browser_data = response.json()
|
|
83
|
+
browser_response = CloudBrowserResponse(**browser_data)
|
|
84
|
+
|
|
85
|
+
# Store session ID for cleanup
|
|
86
|
+
self.current_session_id = browser_response.id
|
|
87
|
+
|
|
88
|
+
logger.info(f'🌤️ Cloud browser created successfully: {browser_response.id}')
|
|
89
|
+
logger.debug(f'🌤️ CDP URL: {browser_response.cdpUrl}')
|
|
90
|
+
# Cyan color for live URL
|
|
91
|
+
logger.info(f'\033[36m🔗 Live URL: {browser_response.liveUrl}\033[0m')
|
|
92
|
+
|
|
93
|
+
return browser_response
|
|
94
|
+
|
|
95
|
+
except httpx.TimeoutException:
|
|
96
|
+
raise CloudBrowserError('Timeout while creating cloud browser. Please try again.')
|
|
97
|
+
except httpx.ConnectError:
|
|
98
|
+
raise CloudBrowserError('Failed to connect to cloud browser service. Please check your internet connection.')
|
|
99
|
+
except Exception as e:
|
|
100
|
+
if isinstance(e, (CloudBrowserError, CloudBrowserAuthError)):
|
|
101
|
+
raise
|
|
102
|
+
raise CloudBrowserError(f'Unexpected error creating cloud browser: {e}')
|
|
103
|
+
|
|
104
|
+
async def stop_browser(
|
|
105
|
+
self, session_id: str | None = None, extra_headers: dict[str, str] | None = None
|
|
106
|
+
) -> CloudBrowserResponse:
|
|
107
|
+
"""Stop a cloud browser session.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
session_id: Session ID to stop. If None, uses current session.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
CloudBrowserResponse: Updated browser info with stopped status
|
|
114
|
+
|
|
115
|
+
Raises:
|
|
116
|
+
CloudBrowserAuthError: If authentication fails
|
|
117
|
+
CloudBrowserError: If stopping fails
|
|
118
|
+
"""
|
|
119
|
+
if session_id is None:
|
|
120
|
+
session_id = self.current_session_id
|
|
121
|
+
|
|
122
|
+
if not session_id:
|
|
123
|
+
raise CloudBrowserError('No session ID provided and no current session available')
|
|
124
|
+
|
|
125
|
+
url = f'{self.api_base_url}/api/v2/browsers/{session_id}'
|
|
126
|
+
|
|
127
|
+
# Try to get API key from environment variable first, then auth config
|
|
128
|
+
api_token = os.getenv('BROWSER_USE_API_KEY')
|
|
129
|
+
|
|
130
|
+
if not api_token:
|
|
131
|
+
# Fallback to auth config file
|
|
132
|
+
try:
|
|
133
|
+
auth_config = CloudAuthConfig.load_from_file()
|
|
134
|
+
api_token = auth_config.api_token
|
|
135
|
+
except Exception:
|
|
136
|
+
pass
|
|
137
|
+
|
|
138
|
+
if not api_token:
|
|
139
|
+
raise CloudBrowserAuthError(
|
|
140
|
+
'No authentication token found. Please set BROWSER_USE_API_KEY environment variable to authenticate with the cloud service. You can also create an API key at https://cloud.browser-use.com/new-api-key'
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
headers = {'X-Browser-Use-API-Key': api_token, 'Content-Type': 'application/json', **(extra_headers or {})}
|
|
144
|
+
|
|
145
|
+
request_body = {'action': 'stop'}
|
|
146
|
+
|
|
147
|
+
try:
|
|
148
|
+
logger.info(f'🌤️ Stopping cloud browser session: {session_id}')
|
|
149
|
+
|
|
150
|
+
response = await self.client.patch(url, headers=headers, json=request_body)
|
|
151
|
+
|
|
152
|
+
if response.status_code == 401:
|
|
153
|
+
raise CloudBrowserAuthError(
|
|
154
|
+
'Authentication failed. Please make sure you have set the BROWSER_USE_API_KEY environment variable to authenticate with the cloud service.'
|
|
155
|
+
)
|
|
156
|
+
elif response.status_code == 404:
|
|
157
|
+
# Session already stopped or doesn't exist - treating as error and clearing session
|
|
158
|
+
logger.debug(f'🌤️ Cloud browser session {session_id} not found (already stopped)')
|
|
159
|
+
# Clear current session if it was this one
|
|
160
|
+
if session_id == self.current_session_id:
|
|
161
|
+
self.current_session_id = None
|
|
162
|
+
raise CloudBrowserError(f'Cloud browser session {session_id} not found')
|
|
163
|
+
elif not response.is_success:
|
|
164
|
+
error_msg = f'Failed to stop cloud browser: HTTP {response.status_code}'
|
|
165
|
+
try:
|
|
166
|
+
error_data = response.json()
|
|
167
|
+
if 'detail' in error_data:
|
|
168
|
+
error_msg += f' - {error_data["detail"]}'
|
|
169
|
+
except Exception:
|
|
170
|
+
pass
|
|
171
|
+
raise CloudBrowserError(error_msg)
|
|
172
|
+
|
|
173
|
+
browser_data = response.json()
|
|
174
|
+
browser_response = CloudBrowserResponse(**browser_data)
|
|
175
|
+
|
|
176
|
+
# Clear current session if it was this one
|
|
177
|
+
if session_id == self.current_session_id:
|
|
178
|
+
self.current_session_id = None
|
|
179
|
+
|
|
180
|
+
logger.info(f'🌤️ Cloud browser session stopped: {browser_response.id}')
|
|
181
|
+
logger.debug(f'🌤️ Status: {browser_response.status}')
|
|
182
|
+
|
|
183
|
+
return browser_response
|
|
184
|
+
|
|
185
|
+
except httpx.TimeoutException:
|
|
186
|
+
raise CloudBrowserError('Timeout while stopping cloud browser. Please try again.')
|
|
187
|
+
except httpx.ConnectError:
|
|
188
|
+
raise CloudBrowserError('Failed to connect to cloud browser service. Please check your internet connection.')
|
|
189
|
+
except Exception as e:
|
|
190
|
+
if isinstance(e, (CloudBrowserError, CloudBrowserAuthError)):
|
|
191
|
+
raise
|
|
192
|
+
raise CloudBrowserError(f'Unexpected error stopping cloud browser: {e}')
|
|
193
|
+
|
|
194
|
+
async def close(self):
|
|
195
|
+
"""Close the HTTP client and cleanup any active sessions."""
|
|
196
|
+
# Try to stop current session if active
|
|
197
|
+
if self.current_session_id:
|
|
198
|
+
try:
|
|
199
|
+
await self.stop_browser()
|
|
200
|
+
except Exception as e:
|
|
201
|
+
logger.debug(f'Failed to stop cloud browser session during cleanup: {e}')
|
|
202
|
+
|
|
203
|
+
await self.client.aclose()
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
from uuid import UUID
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
5
|
+
|
|
6
|
+
ProxyCountryCode = (
|
|
7
|
+
Literal[
|
|
8
|
+
'us', # United States
|
|
9
|
+
'uk', # United Kingdom
|
|
10
|
+
'fr', # France
|
|
11
|
+
'it', # Italy
|
|
12
|
+
'jp', # Japan
|
|
13
|
+
'au', # Australia
|
|
14
|
+
'de', # Germany
|
|
15
|
+
'fi', # Finland
|
|
16
|
+
'ca', # Canada
|
|
17
|
+
'in', # India
|
|
18
|
+
]
|
|
19
|
+
| str
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# Browser session timeout limits (in minutes)
|
|
23
|
+
MAX_FREE_USER_SESSION_TIMEOUT = 15 # Free users limited to 15 minutes
|
|
24
|
+
MAX_PAID_USER_SESSION_TIMEOUT = 240 # Paid users can go up to 4 hours
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# Requests
|
|
28
|
+
class CreateBrowserRequest(BaseModel):
|
|
29
|
+
"""Request to create a cloud browser instance.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
cloud_profile_id: The ID of the profile to use for the session
|
|
33
|
+
cloud_proxy_country_code: Country code for proxy location
|
|
34
|
+
cloud_timeout: The timeout for the session in minutes
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
model_config = ConfigDict(extra='forbid', populate_by_name=True)
|
|
38
|
+
|
|
39
|
+
profile_id: UUID | str | None = Field(
|
|
40
|
+
default=None,
|
|
41
|
+
alias='cloud_profile_id',
|
|
42
|
+
description='The ID of the profile to use for the session. Can be a UUID or a string of UUID.',
|
|
43
|
+
title='Cloud Profile ID',
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
proxy_country_code: ProxyCountryCode | None = Field(
|
|
47
|
+
default=None,
|
|
48
|
+
alias='cloud_proxy_country_code',
|
|
49
|
+
description='Country code for proxy location.',
|
|
50
|
+
title='Cloud Proxy Country Code',
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
timeout: int | None = Field(
|
|
54
|
+
ge=1,
|
|
55
|
+
le=MAX_PAID_USER_SESSION_TIMEOUT,
|
|
56
|
+
default=None,
|
|
57
|
+
alias='cloud_timeout',
|
|
58
|
+
description=f'The timeout for the session in minutes. Free users are limited to {MAX_FREE_USER_SESSION_TIMEOUT} minutes, paid users can use up to {MAX_PAID_USER_SESSION_TIMEOUT} minutes ({MAX_PAID_USER_SESSION_TIMEOUT // 60} hours).',
|
|
59
|
+
title='Cloud Timeout',
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
CloudBrowserParams = CreateBrowserRequest # alias for easier readability
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# Responses
|
|
67
|
+
class CloudBrowserResponse(BaseModel):
|
|
68
|
+
"""Response from cloud browser API."""
|
|
69
|
+
|
|
70
|
+
id: str
|
|
71
|
+
status: str
|
|
72
|
+
liveUrl: str = Field(alias='liveUrl')
|
|
73
|
+
cdpUrl: str = Field(alias='cdpUrl')
|
|
74
|
+
timeoutAt: str = Field(alias='timeoutAt')
|
|
75
|
+
startedAt: str = Field(alias='startedAt')
|
|
76
|
+
finishedAt: str | None = Field(alias='finishedAt', default=None)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# Errors
|
|
80
|
+
class CloudBrowserError(Exception):
|
|
81
|
+
"""Exception raised when cloud browser operations fail."""
|
|
82
|
+
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class CloudBrowserAuthError(CloudBrowserError):
|
|
87
|
+
"""Exception raised when cloud browser authentication fails."""
|
|
88
|
+
|
|
89
|
+
pass
|