smooth-py 0.2.6__tar.gz → 0.2.7.dev20251003__tar.gz
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.
Potentially problematic release.
This version of smooth-py might be problematic. Click here for more details.
- {smooth_py-0.2.6 → smooth_py-0.2.7.dev20251003}/PKG-INFO +2 -1
- {smooth_py-0.2.6 → smooth_py-0.2.7.dev20251003}/pyproject.toml +3 -2
- {smooth_py-0.2.6 → smooth_py-0.2.7.dev20251003}/src/smooth/__init__.py +167 -36
- {smooth_py-0.2.6 → smooth_py-0.2.7.dev20251003}/README.md +0 -0
- {smooth_py-0.2.6 → smooth_py-0.2.7.dev20251003}/src/smooth/mcp/__init__.py +0 -0
- {smooth_py-0.2.6 → smooth_py-0.2.7.dev20251003}/src/smooth/mcp/server.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: smooth-py
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.7.dev20251003
|
|
4
4
|
Summary:
|
|
5
5
|
Author: Luca Pinchetti
|
|
6
6
|
Author-email: luca@circlemind.co
|
|
@@ -11,6 +11,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.12
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.13
|
|
13
13
|
Provides-Extra: mcp
|
|
14
|
+
Requires-Dist: deprecated (>=1.2.18,<2.0.0)
|
|
14
15
|
Requires-Dist: fastmcp (>=2.12.0,<3.0.0) ; extra == "mcp"
|
|
15
16
|
Requires-Dist: httpx (>=0.28.1,<0.29.0)
|
|
16
17
|
Requires-Dist: pydantic (>=2.11.7,<3.0.0)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "smooth-py"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.7.dev20251003"
|
|
4
4
|
description = ""
|
|
5
5
|
authors = [
|
|
6
6
|
{name = "Luca Pinchetti",email = "luca@circlemind.co"}
|
|
@@ -10,7 +10,8 @@ requires-python = ">=3.10,<4.0"
|
|
|
10
10
|
dependencies = [
|
|
11
11
|
"pydantic (>=2.11.7,<3.0.0)",
|
|
12
12
|
"httpx (>=0.28.1,<0.29.0)",
|
|
13
|
-
"requests (>=2.32.5,<3.0.0)"
|
|
13
|
+
"requests (>=2.32.5,<3.0.0)",
|
|
14
|
+
"deprecated (>=1.2.18,<2.0.0)"
|
|
14
15
|
]
|
|
15
16
|
|
|
16
17
|
[project.optional-dependencies]
|
|
@@ -6,12 +6,14 @@ import logging
|
|
|
6
6
|
import os
|
|
7
7
|
import time
|
|
8
8
|
import urllib.parse
|
|
9
|
+
import warnings
|
|
9
10
|
from pathlib import Path
|
|
10
11
|
from typing import Any, Literal, Type
|
|
11
12
|
|
|
12
13
|
import httpx
|
|
13
14
|
import requests
|
|
14
|
-
from
|
|
15
|
+
from deprecated import deprecated
|
|
16
|
+
from pydantic import BaseModel, Field, model_validator
|
|
15
17
|
|
|
16
18
|
# Configure logging
|
|
17
19
|
logger = logging.getLogger("smooth")
|
|
@@ -71,9 +73,12 @@ class TaskRequest(BaseModel):
|
|
|
71
73
|
),
|
|
72
74
|
)
|
|
73
75
|
enable_recording: bool = Field(default=True, description="Enable video recording of the task execution. Default is True")
|
|
74
|
-
|
|
76
|
+
profile_id: str | None = Field(
|
|
75
77
|
default=None,
|
|
76
|
-
description="Browser
|
|
78
|
+
description=("Browser profile ID to use. Each profile maintains its own state, such as cookies and login credentials."),
|
|
79
|
+
)
|
|
80
|
+
profile_read_only: bool = Field(
|
|
81
|
+
default=False, description="If true, the profile specified by `profile_id` will be loaded in read-only mode."
|
|
77
82
|
)
|
|
78
83
|
stealth_mode: bool = Field(default=False, description="Run the browser in stealth mode.")
|
|
79
84
|
proxy_server: str | None = Field(
|
|
@@ -84,29 +89,114 @@ class TaskRequest(BaseModel):
|
|
|
84
89
|
)
|
|
85
90
|
proxy_username: str | None = Field(default=None, description="Proxy server username.")
|
|
86
91
|
proxy_password: str | None = Field(default=None, description="Proxy server password.")
|
|
92
|
+
experimental_features: dict[str, Any] | None = Field(default=None, description="Experimental features to enable for the task.")
|
|
93
|
+
|
|
94
|
+
@model_validator(mode="before")
|
|
95
|
+
@classmethod
|
|
96
|
+
def _handle_deprecated_session_id(cls, data: Any) -> Any:
|
|
97
|
+
if isinstance(data, dict) and "session_id" in data:
|
|
98
|
+
warnings.warn("'session_id' is deprecated, use 'profile_id' instead", DeprecationWarning, stacklevel=2)
|
|
99
|
+
data["profile_id"] = data.pop("session_id")
|
|
100
|
+
return data
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def session_id(self):
|
|
104
|
+
"""(Deprecated) Returns the session ID."""
|
|
105
|
+
warnings.warn("'session_id' is deprecated, use 'profile_id' instead", DeprecationWarning, stacklevel=2)
|
|
106
|
+
return self.profile_id
|
|
107
|
+
|
|
108
|
+
@session_id.setter
|
|
109
|
+
def session_id(self, value):
|
|
110
|
+
"""(Deprecated) Sets the session ID."""
|
|
111
|
+
warnings.warn("'session_id' is deprecated, use 'profile_id' instead", DeprecationWarning, stacklevel=2)
|
|
112
|
+
self.profile_id = value
|
|
87
113
|
|
|
88
114
|
|
|
89
115
|
class BrowserSessionRequest(BaseModel):
|
|
90
116
|
"""Request model for creating a browser session."""
|
|
91
117
|
|
|
92
|
-
|
|
93
|
-
default=None,
|
|
94
|
-
description=("The session ID to open in the browser. If None, a new session will be created with a random name."),
|
|
118
|
+
profile_id: str | None = Field(
|
|
119
|
+
default=None, description=("The profile ID to use for the browser session. If None, a new profile will be created.")
|
|
95
120
|
)
|
|
96
121
|
live_view: bool | None = Field(default=True, description="Request a live URL to interact with the browser session.")
|
|
97
122
|
|
|
123
|
+
@model_validator(mode="before")
|
|
124
|
+
@classmethod
|
|
125
|
+
def _handle_deprecated_session_id(cls, data: Any) -> Any:
|
|
126
|
+
if isinstance(data, dict) and "session_id" in data:
|
|
127
|
+
warnings.warn("'session_id' is deprecated, use 'profile_id' instead", DeprecationWarning, stacklevel=2)
|
|
128
|
+
data["profile_id"] = data.pop("session_id")
|
|
129
|
+
return data
|
|
130
|
+
|
|
131
|
+
@property
|
|
132
|
+
def session_id(self):
|
|
133
|
+
"""(Deprecated) Returns the session ID."""
|
|
134
|
+
warnings.warn("'session_id' is deprecated, use 'profile_id' instead", DeprecationWarning, stacklevel=2)
|
|
135
|
+
return self.profile_id
|
|
136
|
+
|
|
137
|
+
@session_id.setter
|
|
138
|
+
def session_id(self, value):
|
|
139
|
+
"""(Deprecated) Sets the session ID."""
|
|
140
|
+
warnings.warn("'session_id' is deprecated, use 'profile_id' instead", DeprecationWarning, stacklevel=2)
|
|
141
|
+
self.profile_id = value
|
|
142
|
+
|
|
98
143
|
|
|
99
144
|
class BrowserSessionResponse(BaseModel):
|
|
100
145
|
"""Browser session response model."""
|
|
101
146
|
|
|
102
|
-
|
|
147
|
+
profile_id: str = Field(description="The ID of the browser profile associated with the opened browser instance.")
|
|
103
148
|
live_url: str | None = Field(default=None, description="The live URL to interact with the browser session.")
|
|
104
149
|
|
|
150
|
+
@model_validator(mode="before")
|
|
151
|
+
@classmethod
|
|
152
|
+
def _handle_deprecated_session_id(cls, data: Any) -> Any:
|
|
153
|
+
if isinstance(data, dict) and "session_id" in data:
|
|
154
|
+
warnings.warn("'session_id' is deprecated, use 'profile_id' instead", DeprecationWarning, stacklevel=2)
|
|
155
|
+
data["profile_id"] = data.pop("session_id")
|
|
156
|
+
return data
|
|
157
|
+
|
|
158
|
+
@property
|
|
159
|
+
def session_id(self):
|
|
160
|
+
"""(Deprecated) Returns the session ID."""
|
|
161
|
+
warnings.warn("'session_id' is deprecated, use 'profile_id' instead", DeprecationWarning, stacklevel=2)
|
|
162
|
+
return self.profile_id
|
|
163
|
+
|
|
164
|
+
@session_id.setter
|
|
165
|
+
def session_id(self, value):
|
|
166
|
+
"""(Deprecated) Sets the session ID."""
|
|
167
|
+
warnings.warn("'session_id' is deprecated, use 'profile_id' instead", DeprecationWarning, stacklevel=2)
|
|
168
|
+
self.profile_id = value
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class BrowserProfilesResponse(BaseModel):
|
|
172
|
+
"""Response model for listing browser profiles."""
|
|
105
173
|
|
|
106
|
-
|
|
107
|
-
"""Response model for listing browser sessions."""
|
|
174
|
+
profile_ids: list[str] = Field(description="The IDs of the browser profiles.")
|
|
108
175
|
|
|
109
|
-
|
|
176
|
+
@model_validator(mode="before")
|
|
177
|
+
@classmethod
|
|
178
|
+
def _handle_deprecated_session_ids(cls, data: Any) -> Any:
|
|
179
|
+
if isinstance(data, dict) and "session_ids" in data:
|
|
180
|
+
warnings.warn("'session_ids' is deprecated, use 'profile_ids' instead", DeprecationWarning, stacklevel=2)
|
|
181
|
+
data["profile_ids"] = data.pop("session_ids")
|
|
182
|
+
return data
|
|
183
|
+
|
|
184
|
+
@property
|
|
185
|
+
def session_ids(self):
|
|
186
|
+
"""(Deprecated) Returns the session IDs."""
|
|
187
|
+
warnings.warn("'session_ids' is deprecated, use 'profile_ids' instead", DeprecationWarning, stacklevel=2)
|
|
188
|
+
return self.profile_ids
|
|
189
|
+
|
|
190
|
+
@session_ids.setter
|
|
191
|
+
def session_ids(self, value):
|
|
192
|
+
"""(Deprecated) Sets the session IDs."""
|
|
193
|
+
warnings.warn("'session_ids' is deprecated, use 'profile_ids' instead", DeprecationWarning, stacklevel=2)
|
|
194
|
+
self.profile_ids = value
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class BrowserSessionsResponse(BrowserProfilesResponse):
|
|
198
|
+
"""Response model for listing browser profiles."""
|
|
199
|
+
pass
|
|
110
200
|
|
|
111
201
|
|
|
112
202
|
class UploadFileResponse(BaseModel):
|
|
@@ -189,9 +279,14 @@ class BrowserSessionHandle(BaseModel):
|
|
|
189
279
|
|
|
190
280
|
browser_session: BrowserSessionResponse = Field(description="The browser session associated with this handle.")
|
|
191
281
|
|
|
282
|
+
@deprecated("session_id is deprecated, use profile_id instead")
|
|
192
283
|
def session_id(self):
|
|
193
284
|
"""Returns the session ID for the browser session."""
|
|
194
|
-
return self.
|
|
285
|
+
return self.profile_id()
|
|
286
|
+
|
|
287
|
+
def profile_id(self):
|
|
288
|
+
"""Returns the profile ID for the browser session."""
|
|
289
|
+
return self.browser_session.profile_id
|
|
195
290
|
|
|
196
291
|
def live_url(self, interactive: bool = True, embed: bool = False):
|
|
197
292
|
"""Returns the live URL for the browser session."""
|
|
@@ -321,6 +416,8 @@ class SmoothClient(BaseClient):
|
|
|
321
416
|
allowed_urls: list[str] | None = None,
|
|
322
417
|
enable_recording: bool = False,
|
|
323
418
|
session_id: str | None = None,
|
|
419
|
+
profile_id: str | None = None,
|
|
420
|
+
profile_read_only: bool | None = None,
|
|
324
421
|
stealth_mode: bool = False,
|
|
325
422
|
proxy_server: str | None = None,
|
|
326
423
|
proxy_username: str | None = None,
|
|
@@ -343,7 +440,9 @@ class SmoothClient(BaseClient):
|
|
|
343
440
|
allowed_urls: List of allowed URL patterns using wildcard syntax (e.g., https://*example.com/*).
|
|
344
441
|
If None, all URLs are allowed.
|
|
345
442
|
enable_recording: Enable video recording of the task execution.
|
|
346
|
-
session_id: Browser session ID to use.
|
|
443
|
+
session_id: (Deprecated, now `profile_id`) Browser session ID to use.
|
|
444
|
+
profile_id: Browser profile ID to use. Each profile maintains its own state, such as cookies and login credentials.
|
|
445
|
+
profile_read_only: If true, the profile specified by `profile_id` will be loaded in read-only mode.
|
|
347
446
|
stealth_mode: Run the browser in stealth mode.
|
|
348
447
|
proxy_server: Proxy server url to route browser traffic through.
|
|
349
448
|
proxy_username: Proxy server username.
|
|
@@ -366,7 +465,8 @@ class SmoothClient(BaseClient):
|
|
|
366
465
|
device=device,
|
|
367
466
|
allowed_urls=allowed_urls,
|
|
368
467
|
enable_recording=enable_recording,
|
|
369
|
-
|
|
468
|
+
profile_id=profile_id or session_id,
|
|
469
|
+
profile_read_only=profile_read_only,
|
|
370
470
|
stealth_mode=stealth_mode,
|
|
371
471
|
proxy_server=proxy_server,
|
|
372
472
|
proxy_username=proxy_username,
|
|
@@ -376,11 +476,14 @@ class SmoothClient(BaseClient):
|
|
|
376
476
|
|
|
377
477
|
return TaskHandle(initial_response.id, self)
|
|
378
478
|
|
|
379
|
-
def open_session(
|
|
380
|
-
|
|
479
|
+
def open_session(
|
|
480
|
+
self, profile_id: str | None = None, session_id: str | None = None, live_view: bool = True
|
|
481
|
+
) -> BrowserSessionHandle:
|
|
482
|
+
"""Opens an interactive browser instance to interact with a specific browser profile.
|
|
381
483
|
|
|
382
484
|
Args:
|
|
383
|
-
|
|
485
|
+
profile_id: The profile ID to use for the session. If None, a new profile will be created.
|
|
486
|
+
session_id: (Deprecated, now `profile_id`) The session ID to associate with the browser.
|
|
384
487
|
live_view: Whether to enable live view for the session.
|
|
385
488
|
|
|
386
489
|
Returns:
|
|
@@ -392,7 +495,7 @@ class SmoothClient(BaseClient):
|
|
|
392
495
|
try:
|
|
393
496
|
response = self._session.post(
|
|
394
497
|
f"{self.base_url}/browser/session",
|
|
395
|
-
json=BrowserSessionRequest(
|
|
498
|
+
json=BrowserSessionRequest(profile_id=profile_id or session_id, live_view=live_view).model_dump(exclude_none=True),
|
|
396
499
|
)
|
|
397
500
|
data = self._handle_response(response)
|
|
398
501
|
return BrowserSessionHandle(browser_session=BrowserSessionResponse(**data["r"]))
|
|
@@ -400,11 +503,11 @@ class SmoothClient(BaseClient):
|
|
|
400
503
|
logger.error(f"Request failed: {e}")
|
|
401
504
|
raise ApiError(status_code=0, detail=f"Request failed: {str(e)}") from None
|
|
402
505
|
|
|
403
|
-
def
|
|
404
|
-
"""Lists all browser
|
|
506
|
+
def list_profiles(self):
|
|
507
|
+
"""Lists all browser profiles for the user.
|
|
405
508
|
|
|
406
509
|
Returns:
|
|
407
|
-
A list of existing browser
|
|
510
|
+
A list of existing browser profiles.
|
|
408
511
|
|
|
409
512
|
Raises:
|
|
410
513
|
ApiException: If the API request fails.
|
|
@@ -412,20 +515,30 @@ class SmoothClient(BaseClient):
|
|
|
412
515
|
try:
|
|
413
516
|
response = self._session.get(f"{self.base_url}/browser/session")
|
|
414
517
|
data = self._handle_response(response)
|
|
415
|
-
return
|
|
518
|
+
return BrowserProfilesResponse(**data["r"])
|
|
416
519
|
except requests.exceptions.RequestException as e:
|
|
417
520
|
logger.error(f"Request failed: {e}")
|
|
418
521
|
raise ApiError(status_code=0, detail=f"Request failed: {str(e)}") from None
|
|
419
522
|
|
|
420
|
-
|
|
421
|
-
|
|
523
|
+
@deprecated("list_sessions is deprecated, use list_profiles instead")
|
|
524
|
+
def list_sessions(self):
|
|
525
|
+
"""Lists all browser profiles for the user."""
|
|
526
|
+
return self.list_profiles()
|
|
527
|
+
|
|
528
|
+
def delete_profile(self, profile_id: str):
|
|
529
|
+
"""Delete a browser profile."""
|
|
422
530
|
try:
|
|
423
|
-
response = self._session.delete(f"{self.base_url}/browser/session/{
|
|
531
|
+
response = self._session.delete(f"{self.base_url}/browser/session/{profile_id}")
|
|
424
532
|
self._handle_response(response)
|
|
425
533
|
except requests.exceptions.RequestException as e:
|
|
426
534
|
logger.error(f"Request failed: {e}")
|
|
427
535
|
raise ApiError(status_code=0, detail=f"Request failed: {str(e)}") from None
|
|
428
536
|
|
|
537
|
+
@deprecated("delete_session is deprecated, use delete_profile instead")
|
|
538
|
+
def delete_session(self, session_id: str):
|
|
539
|
+
"""Delete a browser profile."""
|
|
540
|
+
self.delete_profile(session_id)
|
|
541
|
+
|
|
429
542
|
def upload_file(self, file: io.IOBase, name: str | None = None, purpose: str | None = None) -> UploadFileResponse:
|
|
430
543
|
"""Upload a file and return the file ID.
|
|
431
544
|
|
|
@@ -588,6 +701,8 @@ class SmoothAsyncClient(BaseClient):
|
|
|
588
701
|
allowed_urls: list[str] | None = None,
|
|
589
702
|
enable_recording: bool = False,
|
|
590
703
|
session_id: str | None = None,
|
|
704
|
+
profile_id: str | None = None,
|
|
705
|
+
profile_read_only: bool | None = None,
|
|
591
706
|
stealth_mode: bool = False,
|
|
592
707
|
proxy_server: str | None = None,
|
|
593
708
|
proxy_username: str | None = None,
|
|
@@ -610,7 +725,9 @@ class SmoothAsyncClient(BaseClient):
|
|
|
610
725
|
allowed_urls: List of allowed URL patterns using wildcard syntax (e.g., https://*example.com/*).
|
|
611
726
|
If None, all URLs are allowed.
|
|
612
727
|
enable_recording: Enable video recording of the task execution.
|
|
613
|
-
session_id: Browser session ID to use.
|
|
728
|
+
session_id: (Deprecated, now `profile_id`) Browser session ID to use.
|
|
729
|
+
profile_id: Browser profile ID to use. Each profile maintains its own state, such as cookies and login credentials.
|
|
730
|
+
profile_read_only: If true, the profile specified by `profile_id` will be loaded in read-only mode.
|
|
614
731
|
stealth_mode: Run the browser in stealth mode.
|
|
615
732
|
proxy_server: Proxy server url to route browser traffic through.
|
|
616
733
|
proxy_username: Proxy server username.
|
|
@@ -635,7 +752,8 @@ class SmoothAsyncClient(BaseClient):
|
|
|
635
752
|
device=device,
|
|
636
753
|
allowed_urls=allowed_urls,
|
|
637
754
|
enable_recording=enable_recording,
|
|
638
|
-
|
|
755
|
+
profile_id=profile_id or session_id,
|
|
756
|
+
profile_read_only=profile_read_only,
|
|
639
757
|
stealth_mode=stealth_mode,
|
|
640
758
|
proxy_server=proxy_server,
|
|
641
759
|
proxy_username=proxy_username,
|
|
@@ -645,11 +763,14 @@ class SmoothAsyncClient(BaseClient):
|
|
|
645
763
|
initial_response = await self._submit_task(payload)
|
|
646
764
|
return AsyncTaskHandle(initial_response.id, self)
|
|
647
765
|
|
|
648
|
-
async def open_session(
|
|
766
|
+
async def open_session(
|
|
767
|
+
self, profile_id: str | None = None, session_id: str | None = None, live_view: bool = True
|
|
768
|
+
) -> BrowserSessionHandle:
|
|
649
769
|
"""Opens an interactive browser instance asynchronously.
|
|
650
770
|
|
|
651
771
|
Args:
|
|
652
|
-
session_id: The session ID to associate with the browser.
|
|
772
|
+
session_id: (Deprecated, now `profile_id`) The session ID to associate with the browser.
|
|
773
|
+
profile_id: The profile ID to associate with the browser.
|
|
653
774
|
live_view: Whether to enable live view for the session.
|
|
654
775
|
|
|
655
776
|
Returns:
|
|
@@ -661,7 +782,7 @@ class SmoothAsyncClient(BaseClient):
|
|
|
661
782
|
try:
|
|
662
783
|
response = await self._client.post(
|
|
663
784
|
f"{self.base_url}/browser/session",
|
|
664
|
-
json=BrowserSessionRequest(
|
|
785
|
+
json=BrowserSessionRequest(profile_id=profile_id or session_id, live_view=live_view).model_dump(exclude_none=True),
|
|
665
786
|
)
|
|
666
787
|
data = self._handle_response(response)
|
|
667
788
|
return BrowserSessionHandle(browser_session=BrowserSessionResponse(**data["r"]))
|
|
@@ -669,11 +790,11 @@ class SmoothAsyncClient(BaseClient):
|
|
|
669
790
|
logger.error(f"Request failed: {e}")
|
|
670
791
|
raise ApiError(status_code=0, detail=f"Request failed: {str(e)}") from None
|
|
671
792
|
|
|
672
|
-
async def
|
|
673
|
-
"""Lists all browser
|
|
793
|
+
async def list_profiles(self):
|
|
794
|
+
"""Lists all browser profiles for the user.
|
|
674
795
|
|
|
675
796
|
Returns:
|
|
676
|
-
A list of existing browser
|
|
797
|
+
A list of existing browser profiles.
|
|
677
798
|
|
|
678
799
|
Raises:
|
|
679
800
|
ApiException: If the API request fails.
|
|
@@ -681,20 +802,30 @@ class SmoothAsyncClient(BaseClient):
|
|
|
681
802
|
try:
|
|
682
803
|
response = await self._client.get(f"{self.base_url}/browser/session")
|
|
683
804
|
data = self._handle_response(response)
|
|
684
|
-
return
|
|
805
|
+
return BrowserProfilesResponse(**data["r"])
|
|
685
806
|
except httpx.RequestError as e:
|
|
686
807
|
logger.error(f"Request failed: {e}")
|
|
687
808
|
raise ApiError(status_code=0, detail=f"Request failed: {str(e)}") from None
|
|
688
809
|
|
|
689
|
-
|
|
690
|
-
|
|
810
|
+
@deprecated("list_sessions is deprecated, use list_profiles instead")
|
|
811
|
+
async def list_sessions(self):
|
|
812
|
+
"""Lists all browser profiles for the user."""
|
|
813
|
+
return await self.list_profiles()
|
|
814
|
+
|
|
815
|
+
async def delete_profile(self, profile_id: str):
|
|
816
|
+
"""Delete a browser profile."""
|
|
691
817
|
try:
|
|
692
|
-
response = await self._client.delete(f"{self.base_url}/browser/session/{
|
|
818
|
+
response = await self._client.delete(f"{self.base_url}/browser/session/{profile_id}")
|
|
693
819
|
self._handle_response(response)
|
|
694
820
|
except httpx.RequestError as e:
|
|
695
821
|
logger.error(f"Request failed: {e}")
|
|
696
822
|
raise ApiError(status_code=0, detail=f"Request failed: {str(e)}") from None
|
|
697
823
|
|
|
824
|
+
@deprecated("delete_session is deprecated, use delete_profile instead")
|
|
825
|
+
async def delete_session(self, session_id: str):
|
|
826
|
+
"""Delete a browser profile."""
|
|
827
|
+
await self.delete_profile(session_id)
|
|
828
|
+
|
|
698
829
|
async def upload_file(self, file: io.IOBase, name: str | None = None, purpose: str | None = None) -> UploadFileResponse:
|
|
699
830
|
"""Upload a file and return the file ID.
|
|
700
831
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|