smooth-py 0.3.0.dev20251013__py3-none-any.whl → 0.3.0.post2__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.
Potentially problematic release.
This version of smooth-py might be problematic. Click here for more details.
smooth/__init__.py
CHANGED
|
@@ -82,7 +82,11 @@ class TaskRequest(BaseModel):
|
|
|
82
82
|
description=("Browser profile ID to use. Each profile maintains its own state, such as cookies and login credentials."),
|
|
83
83
|
)
|
|
84
84
|
profile_read_only: bool = Field(
|
|
85
|
-
default=False,
|
|
85
|
+
default=False,
|
|
86
|
+
description=(
|
|
87
|
+
"If true, the profile specified by `profile_id` will be loaded in read-only mode. "
|
|
88
|
+
"Changes made during the task will not be saved back to the profile."
|
|
89
|
+
),
|
|
86
90
|
)
|
|
87
91
|
stealth_mode: bool = Field(default=False, description="Run the browser in stealth mode.")
|
|
88
92
|
proxy_server: str | None = Field(
|
|
@@ -330,6 +334,10 @@ class BrowserSessionHandle(BaseModel):
|
|
|
330
334
|
return _encode_url(self.browser_session.live_url, interactive=interactive, embed=embed)
|
|
331
335
|
return None
|
|
332
336
|
|
|
337
|
+
def live_id(self):
|
|
338
|
+
"""Returns the live ID for the browser session."""
|
|
339
|
+
return self.browser_session.live_id
|
|
340
|
+
|
|
333
341
|
|
|
334
342
|
class TaskHandle:
|
|
335
343
|
"""A handle to a running task."""
|
|
@@ -393,6 +401,14 @@ class TaskHandle:
|
|
|
393
401
|
task_response = self._client._get_task(self.id())
|
|
394
402
|
self._task_response = task_response
|
|
395
403
|
if task_response.recording_url is not None:
|
|
404
|
+
if not task_response.recording_url:
|
|
405
|
+
raise ApiError(
|
|
406
|
+
status_code=404,
|
|
407
|
+
detail=(
|
|
408
|
+
f"Recording URL not available for task {self.id()}."
|
|
409
|
+
" Set `enable_recording=True` when creating the task to enable it."
|
|
410
|
+
)
|
|
411
|
+
)
|
|
396
412
|
return task_response.recording_url
|
|
397
413
|
time.sleep(1)
|
|
398
414
|
raise TimeoutError(f"Recording URL not available for task {self.id()}.")
|
|
@@ -466,7 +482,7 @@ class SmoothClient(BaseClient):
|
|
|
466
482
|
max_steps: int = 32,
|
|
467
483
|
device: Literal["desktop", "mobile"] = "mobile",
|
|
468
484
|
allowed_urls: list[str] | None = None,
|
|
469
|
-
enable_recording: bool =
|
|
485
|
+
enable_recording: bool = True,
|
|
470
486
|
session_id: str | None = None,
|
|
471
487
|
profile_id: str | None = None,
|
|
472
488
|
profile_read_only: bool = False,
|
|
@@ -486,7 +502,7 @@ class SmoothClient(BaseClient):
|
|
|
486
502
|
response_model: If provided, the schema describing the desired output structure.
|
|
487
503
|
url: The starting URL for the task. If not provided, the agent will infer it from the task.
|
|
488
504
|
metadata: A dictionary containing variables or parameters that will be passed to the agent.
|
|
489
|
-
files: A
|
|
505
|
+
files: A list of file ids to pass to the agent.
|
|
490
506
|
agent: The agent to use for the task.
|
|
491
507
|
max_steps: Maximum number of steps the agent can take (max 64).
|
|
492
508
|
device: Device type for the task. Default is mobile.
|
|
@@ -577,7 +593,7 @@ class SmoothClient(BaseClient):
|
|
|
577
593
|
ApiException: If the API request fails.
|
|
578
594
|
"""
|
|
579
595
|
try:
|
|
580
|
-
response = self._session.get(f"{self.base_url}/browser/
|
|
596
|
+
response = self._session.get(f"{self.base_url}/browser/profile")
|
|
581
597
|
data = self._handle_response(response)
|
|
582
598
|
return BrowserProfilesResponse(**data["r"])
|
|
583
599
|
except requests.exceptions.RequestException as e:
|
|
@@ -592,7 +608,7 @@ class SmoothClient(BaseClient):
|
|
|
592
608
|
def delete_profile(self, profile_id: str):
|
|
593
609
|
"""Delete a browser profile."""
|
|
594
610
|
try:
|
|
595
|
-
response = self._session.delete(f"{self.base_url}/browser/
|
|
611
|
+
response = self._session.delete(f"{self.base_url}/browser/profile/{profile_id}")
|
|
596
612
|
self._handle_response(response)
|
|
597
613
|
except requests.exceptions.RequestException as e:
|
|
598
614
|
logger.error(f"Request failed: {e}")
|
|
@@ -686,7 +702,7 @@ class AsyncTaskHandle:
|
|
|
686
702
|
await asyncio.sleep(poll_interval)
|
|
687
703
|
raise TimeoutError(f"Task {self.id()} did not complete within {timeout} seconds.")
|
|
688
704
|
|
|
689
|
-
async def live_url(self, interactive: bool =
|
|
705
|
+
async def live_url(self, interactive: bool = False, embed: bool = False, timeout: int | None = None):
|
|
690
706
|
"""Returns the live URL for the task."""
|
|
691
707
|
if self._task_response and self._task_response.live_url:
|
|
692
708
|
return _encode_url(self._task_response.live_url, interactive=interactive, embed=embed)
|
|
@@ -695,13 +711,13 @@ class AsyncTaskHandle:
|
|
|
695
711
|
while timeout is None or (time.time() - start_time) < timeout:
|
|
696
712
|
task_response = await self._client._get_task(self.id())
|
|
697
713
|
self._task_response = task_response
|
|
698
|
-
if
|
|
699
|
-
return _encode_url(
|
|
714
|
+
if self._task_response.live_url:
|
|
715
|
+
return _encode_url(self._task_response.live_url, interactive=interactive, embed=embed)
|
|
700
716
|
await asyncio.sleep(1)
|
|
701
717
|
|
|
702
718
|
raise TimeoutError(f"Live URL not available for task {self.id()}.")
|
|
703
719
|
|
|
704
|
-
async def recording_url(self, timeout: int | None = None):
|
|
720
|
+
async def recording_url(self, timeout: int | None = None) -> str:
|
|
705
721
|
"""Returns the recording URL for the task."""
|
|
706
722
|
if self._task_response and self._task_response.recording_url is not None:
|
|
707
723
|
return self._task_response.recording_url
|
|
@@ -711,6 +727,14 @@ class AsyncTaskHandle:
|
|
|
711
727
|
task_response = await self._client._get_task(self.id())
|
|
712
728
|
self._task_response = task_response
|
|
713
729
|
if task_response.recording_url is not None:
|
|
730
|
+
if not task_response.recording_url:
|
|
731
|
+
raise ApiError(
|
|
732
|
+
status_code=404,
|
|
733
|
+
detail=(
|
|
734
|
+
f"Recording URL not available for task {self.id()}."
|
|
735
|
+
" Set `enable_recording=True` when creating the task to enable it."
|
|
736
|
+
)
|
|
737
|
+
)
|
|
714
738
|
return task_response.recording_url
|
|
715
739
|
await asyncio.sleep(1)
|
|
716
740
|
|
|
@@ -779,7 +803,7 @@ class SmoothAsyncClient(BaseClient):
|
|
|
779
803
|
max_steps: int = 32,
|
|
780
804
|
device: Literal["desktop", "mobile"] = "mobile",
|
|
781
805
|
allowed_urls: list[str] | None = None,
|
|
782
|
-
enable_recording: bool =
|
|
806
|
+
enable_recording: bool = True,
|
|
783
807
|
session_id: str | None = None,
|
|
784
808
|
profile_id: str | None = None,
|
|
785
809
|
profile_read_only: bool = False,
|
|
@@ -799,7 +823,7 @@ class SmoothAsyncClient(BaseClient):
|
|
|
799
823
|
response_model: If provided, the schema describing the desired output structure.
|
|
800
824
|
url: The starting URL for the task. If not provided, the agent will infer it from the task.
|
|
801
825
|
metadata: A dictionary containing variables or parameters that will be passed to the agent.
|
|
802
|
-
files: A
|
|
826
|
+
files: A list of file ids to pass to the agent.
|
|
803
827
|
agent: The agent to use for the task.
|
|
804
828
|
max_steps: Maximum number of steps the agent can take (max 64).
|
|
805
829
|
device: Device type for the task. Default is mobile.
|
|
@@ -850,8 +874,8 @@ class SmoothAsyncClient(BaseClient):
|
|
|
850
874
|
"""Opens an interactive browser instance asynchronously.
|
|
851
875
|
|
|
852
876
|
Args:
|
|
877
|
+
profile_id: The profile ID to use for the session. If None, a new profile will be created.
|
|
853
878
|
session_id: (Deprecated, now `profile_id`) The session ID to associate with the browser.
|
|
854
|
-
profile_id: The profile ID to associate with the browser.
|
|
855
879
|
live_view: Whether to enable live view for the session.
|
|
856
880
|
|
|
857
881
|
Returns:
|
|
@@ -890,7 +914,7 @@ class SmoothAsyncClient(BaseClient):
|
|
|
890
914
|
ApiException: If the API request fails.
|
|
891
915
|
"""
|
|
892
916
|
try:
|
|
893
|
-
response = await self._client.get(f"{self.base_url}/browser/
|
|
917
|
+
response = await self._client.get(f"{self.base_url}/browser/profile")
|
|
894
918
|
data = self._handle_response(response)
|
|
895
919
|
return BrowserProfilesResponse(**data["r"])
|
|
896
920
|
except httpx.RequestError as e:
|
|
@@ -905,7 +929,7 @@ class SmoothAsyncClient(BaseClient):
|
|
|
905
929
|
async def delete_profile(self, profile_id: str):
|
|
906
930
|
"""Delete a browser profile."""
|
|
907
931
|
try:
|
|
908
|
-
response = await self._client.delete(f"{self.base_url}/browser/
|
|
932
|
+
response = await self._client.delete(f"{self.base_url}/browser/profile/{profile_id}")
|
|
909
933
|
self._handle_response(response)
|
|
910
934
|
except httpx.RequestError as e:
|
|
911
935
|
logger.error(f"Request failed: {e}")
|
|
@@ -936,11 +960,12 @@ class SmoothAsyncClient(BaseClient):
|
|
|
936
960
|
if name is None:
|
|
937
961
|
raise ValueError("File name must be provided or the file object must have a 'name' attribute.")
|
|
938
962
|
|
|
939
|
-
files = {"file": (Path(name).name, file)}
|
|
940
963
|
if purpose:
|
|
941
964
|
data = {"file_purpose": purpose}
|
|
942
965
|
else:
|
|
943
966
|
data = None
|
|
967
|
+
|
|
968
|
+
files = {"file": (Path(name).name, file)}
|
|
944
969
|
response = await self._client.post(f"{self.base_url}/file", files=files, data=data)
|
|
945
970
|
data = self._handle_response(response)
|
|
946
971
|
return UploadFileResponse(**data["r"])
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
smooth/__init__.py,sha256=RlpjOBgw2CiLM3kgtOUBdDqslme2Cqge8rXQTV6lUh0,39212
|
|
2
|
+
smooth/mcp/__init__.py,sha256=0aJVFi2a8Ah3-5xtgyZ5UMbaaJsBWu2T8QLWoFQITk8,219
|
|
3
|
+
smooth/mcp/server.py,sha256=9SymTD4NOGTMN8P-LNGlvYNvv81yCIZfZeeuhEcAc6s,20068
|
|
4
|
+
smooth_py-0.3.0.post2.dist-info/METADATA,sha256=Phb1MamNNmlyJ9g1MWGG0FLTG5JKNSIvIURVuI8EqwM,7523
|
|
5
|
+
smooth_py-0.3.0.post2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
6
|
+
smooth_py-0.3.0.post2.dist-info/RECORD,,
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
smooth/__init__.py,sha256=8cuQGi1QbHBbW0dcM9ZyyZL-PrMmAoR3LmLZcqksdJA,38460
|
|
2
|
-
smooth/mcp/__init__.py,sha256=0aJVFi2a8Ah3-5xtgyZ5UMbaaJsBWu2T8QLWoFQITk8,219
|
|
3
|
-
smooth/mcp/server.py,sha256=9SymTD4NOGTMN8P-LNGlvYNvv81yCIZfZeeuhEcAc6s,20068
|
|
4
|
-
smooth_py-0.3.0.dev20251013.dist-info/METADATA,sha256=CJIChVHrQ4YqTk7TioEH-u_4ecw9OurNAw1KAOf3Q1w,7529
|
|
5
|
-
smooth_py-0.3.0.dev20251013.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
6
|
-
smooth_py-0.3.0.dev20251013.dist-info/RECORD,,
|
|
File without changes
|