smooth-py 0.2.7.dev20251003__tar.gz → 0.2.8.dev20251006__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.7.dev20251003 → smooth_py-0.2.8.dev20251006}/PKG-INFO +1 -1
- {smooth_py-0.2.7.dev20251003 → smooth_py-0.2.8.dev20251006}/pyproject.toml +1 -1
- {smooth_py-0.2.7.dev20251003 → smooth_py-0.2.8.dev20251006}/src/smooth/__init__.py +44 -7
- {smooth_py-0.2.7.dev20251003 → smooth_py-0.2.8.dev20251006}/README.md +0 -0
- {smooth_py-0.2.7.dev20251003 → smooth_py-0.2.8.dev20251006}/src/smooth/mcp/__init__.py +0 -0
- {smooth_py-0.2.7.dev20251003 → smooth_py-0.2.8.dev20251006}/src/smooth/mcp/server.py +0 -0
|
@@ -13,7 +13,7 @@ from typing import Any, Literal, Type
|
|
|
13
13
|
import httpx
|
|
14
14
|
import requests
|
|
15
15
|
from deprecated import deprecated
|
|
16
|
-
from pydantic import BaseModel, Field, model_validator
|
|
16
|
+
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
|
17
17
|
|
|
18
18
|
# Configure logging
|
|
19
19
|
logger = logging.getLogger("smooth")
|
|
@@ -39,8 +39,10 @@ def _encode_url(url: str, interactive: bool = True, embed: bool = False) -> str:
|
|
|
39
39
|
class TaskResponse(BaseModel):
|
|
40
40
|
"""Task response model."""
|
|
41
41
|
|
|
42
|
+
model_config = ConfigDict(extra="allow")
|
|
43
|
+
|
|
42
44
|
id: str = Field(description="The ID of the task.")
|
|
43
|
-
status: Literal["waiting", "running", "done", "failed"] = Field(description="The status of the task.")
|
|
45
|
+
status: Literal["waiting", "running", "done", "failed", "cancelled"] = Field(description="The status of the task.")
|
|
44
46
|
output: Any | None = Field(default=None, description="The output of the task.")
|
|
45
47
|
credits_used: int | None = Field(default=None, description="The amount of credits used to perform the task.")
|
|
46
48
|
device: Literal["desktop", "mobile"] | None = Field(default=None, description="The device type used for the task.")
|
|
@@ -89,7 +91,9 @@ class TaskRequest(BaseModel):
|
|
|
89
91
|
)
|
|
90
92
|
proxy_username: str | None = Field(default=None, description="Proxy server username.")
|
|
91
93
|
proxy_password: str | None = Field(default=None, description="Proxy server password.")
|
|
92
|
-
experimental_features: dict[str, Any] | None = Field(
|
|
94
|
+
experimental_features: dict[str, Any] | None = Field(
|
|
95
|
+
default=None, description="Experimental features to enable for the task."
|
|
96
|
+
)
|
|
93
97
|
|
|
94
98
|
@model_validator(mode="before")
|
|
95
99
|
@classmethod
|
|
@@ -145,6 +149,7 @@ class BrowserSessionResponse(BaseModel):
|
|
|
145
149
|
"""Browser session response model."""
|
|
146
150
|
|
|
147
151
|
profile_id: str = Field(description="The ID of the browser profile associated with the opened browser instance.")
|
|
152
|
+
live_id: str | None = Field(description="The ID of the live browser session.")
|
|
148
153
|
live_url: str | None = Field(default=None, description="The live URL to interact with the browser session.")
|
|
149
154
|
|
|
150
155
|
@model_validator(mode="before")
|
|
@@ -196,6 +201,7 @@ class BrowserProfilesResponse(BaseModel):
|
|
|
196
201
|
|
|
197
202
|
class BrowserSessionsResponse(BrowserProfilesResponse):
|
|
198
203
|
"""Response model for listing browser profiles."""
|
|
204
|
+
|
|
199
205
|
pass
|
|
200
206
|
|
|
201
207
|
|
|
@@ -309,6 +315,15 @@ class TaskHandle:
|
|
|
309
315
|
"""Returns the task ID."""
|
|
310
316
|
return self._id
|
|
311
317
|
|
|
318
|
+
def stop(self):
|
|
319
|
+
"""Stops the task."""
|
|
320
|
+
try:
|
|
321
|
+
response = self._client._client.delete(f"{self._client.base_url}/task/{self._id}")
|
|
322
|
+
self._handle_response(response)
|
|
323
|
+
except requests.exceptions.RequestException as e:
|
|
324
|
+
logger.error(f"Request failed: {e}")
|
|
325
|
+
raise ApiError(status_code=0, detail=f"Request failed: {str(e)}") from None
|
|
326
|
+
|
|
312
327
|
def result(self, timeout: int | None = None, poll_interval: float = 1) -> TaskResponse:
|
|
313
328
|
"""Waits for the task to complete and returns the result."""
|
|
314
329
|
if self._task_response and self._task_response.status not in ["running", "waiting"]:
|
|
@@ -417,11 +432,12 @@ class SmoothClient(BaseClient):
|
|
|
417
432
|
enable_recording: bool = False,
|
|
418
433
|
session_id: str | None = None,
|
|
419
434
|
profile_id: str | None = None,
|
|
420
|
-
profile_read_only: bool
|
|
435
|
+
profile_read_only: bool = False,
|
|
421
436
|
stealth_mode: bool = False,
|
|
422
437
|
proxy_server: str | None = None,
|
|
423
438
|
proxy_username: str | None = None,
|
|
424
439
|
proxy_password: str | None = None,
|
|
440
|
+
experimental_features: dict[str, Any] | None = None,
|
|
425
441
|
) -> TaskHandle:
|
|
426
442
|
"""Runs a task and returns a handle to the task.
|
|
427
443
|
|
|
@@ -447,6 +463,7 @@ class SmoothClient(BaseClient):
|
|
|
447
463
|
proxy_server: Proxy server url to route browser traffic through.
|
|
448
464
|
proxy_username: Proxy server username.
|
|
449
465
|
proxy_password: Proxy server password.
|
|
466
|
+
experimental_features: Experimental features to enable for the task.
|
|
450
467
|
|
|
451
468
|
Returns:
|
|
452
469
|
A handle to the running task.
|
|
@@ -471,6 +488,7 @@ class SmoothClient(BaseClient):
|
|
|
471
488
|
proxy_server=proxy_server,
|
|
472
489
|
proxy_username=proxy_username,
|
|
473
490
|
proxy_password=proxy_password,
|
|
491
|
+
experimental_features=experimental_features,
|
|
474
492
|
)
|
|
475
493
|
initial_response = self._submit_task(payload)
|
|
476
494
|
|
|
@@ -503,6 +521,15 @@ class SmoothClient(BaseClient):
|
|
|
503
521
|
logger.error(f"Request failed: {e}")
|
|
504
522
|
raise ApiError(status_code=0, detail=f"Request failed: {str(e)}") from None
|
|
505
523
|
|
|
524
|
+
def close_session(self, live_id: str):
|
|
525
|
+
"""Closes a browser session."""
|
|
526
|
+
try:
|
|
527
|
+
response = self._session.delete(f"{self.base_url}/browser/session/{live_id}")
|
|
528
|
+
self._handle_response(response)
|
|
529
|
+
except requests.exceptions.RequestException as e:
|
|
530
|
+
logger.error(f"Request failed: {e}")
|
|
531
|
+
raise ApiError(status_code=0, detail=f"Request failed: {str(e)}") from None
|
|
532
|
+
|
|
506
533
|
def list_profiles(self):
|
|
507
534
|
"""Lists all browser profiles for the user.
|
|
508
535
|
|
|
@@ -702,11 +729,12 @@ class SmoothAsyncClient(BaseClient):
|
|
|
702
729
|
enable_recording: bool = False,
|
|
703
730
|
session_id: str | None = None,
|
|
704
731
|
profile_id: str | None = None,
|
|
705
|
-
profile_read_only: bool
|
|
732
|
+
profile_read_only: bool = False,
|
|
706
733
|
stealth_mode: bool = False,
|
|
707
734
|
proxy_server: str | None = None,
|
|
708
735
|
proxy_username: str | None = None,
|
|
709
736
|
proxy_password: str | None = None,
|
|
737
|
+
experimental_features: dict[str, Any] | None = None,
|
|
710
738
|
) -> AsyncTaskHandle:
|
|
711
739
|
"""Runs a task and returns a handle to the task asynchronously.
|
|
712
740
|
|
|
@@ -732,8 +760,7 @@ class SmoothAsyncClient(BaseClient):
|
|
|
732
760
|
proxy_server: Proxy server url to route browser traffic through.
|
|
733
761
|
proxy_username: Proxy server username.
|
|
734
762
|
proxy_password: Proxy server password.
|
|
735
|
-
|
|
736
|
-
timeout: The maximum time in seconds to wait for the task to complete.
|
|
763
|
+
experimental_features: Experimental features to enable for the task.
|
|
737
764
|
|
|
738
765
|
Returns:
|
|
739
766
|
A handle to the running task.
|
|
@@ -758,6 +785,7 @@ class SmoothAsyncClient(BaseClient):
|
|
|
758
785
|
proxy_server=proxy_server,
|
|
759
786
|
proxy_username=proxy_username,
|
|
760
787
|
proxy_password=proxy_password,
|
|
788
|
+
experimental_features=experimental_features,
|
|
761
789
|
)
|
|
762
790
|
|
|
763
791
|
initial_response = await self._submit_task(payload)
|
|
@@ -790,6 +818,15 @@ class SmoothAsyncClient(BaseClient):
|
|
|
790
818
|
logger.error(f"Request failed: {e}")
|
|
791
819
|
raise ApiError(status_code=0, detail=f"Request failed: {str(e)}") from None
|
|
792
820
|
|
|
821
|
+
async def close_session(self, live_id: str):
|
|
822
|
+
"""Closes a browser session."""
|
|
823
|
+
try:
|
|
824
|
+
response = await self._client.delete(f"{self.base_url}/browser/session/{live_id}")
|
|
825
|
+
self._handle_response(response)
|
|
826
|
+
except httpx.RequestError as e:
|
|
827
|
+
logger.error(f"Request failed: {e}")
|
|
828
|
+
raise ApiError(status_code=0, detail=f"Request failed: {str(e)}") from None
|
|
829
|
+
|
|
793
830
|
async def list_profiles(self):
|
|
794
831
|
"""Lists all browser profiles for the user.
|
|
795
832
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|