smooth-py 0.2.8.dev20251003__tar.gz → 0.2.8.dev20251008__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.8.dev20251003 → smooth_py-0.2.8.dev20251008}/PKG-INFO +1 -1
- {smooth_py-0.2.8.dev20251003 → smooth_py-0.2.8.dev20251008}/pyproject.toml +1 -1
- {smooth_py-0.2.8.dev20251003 → smooth_py-0.2.8.dev20251008}/src/smooth/__init__.py +68 -4
- {smooth_py-0.2.8.dev20251003 → smooth_py-0.2.8.dev20251008}/README.md +0 -0
- {smooth_py-0.2.8.dev20251003 → smooth_py-0.2.8.dev20251008}/src/smooth/mcp/__init__.py +0 -0
- {smooth_py-0.2.8.dev20251003 → smooth_py-0.2.8.dev20251008}/src/smooth/mcp/server.py +0 -0
|
@@ -38,10 +38,11 @@ def _encode_url(url: str, interactive: bool = True, embed: bool = False) -> str:
|
|
|
38
38
|
|
|
39
39
|
class TaskResponse(BaseModel):
|
|
40
40
|
"""Task response model."""
|
|
41
|
-
|
|
41
|
+
|
|
42
|
+
model_config = ConfigDict(extra="allow")
|
|
42
43
|
|
|
43
44
|
id: str = Field(description="The ID of the task.")
|
|
44
|
-
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.")
|
|
45
46
|
output: Any | None = Field(default=None, description="The output of the task.")
|
|
46
47
|
credits_used: int | None = Field(default=None, description="The amount of credits used to perform the task.")
|
|
47
48
|
device: Literal["desktop", "mobile"] | None = Field(default=None, description="The device type used for the task.")
|
|
@@ -52,6 +53,8 @@ class TaskResponse(BaseModel):
|
|
|
52
53
|
class TaskRequest(BaseModel):
|
|
53
54
|
"""Run task request model."""
|
|
54
55
|
|
|
56
|
+
model_config = ConfigDict(extra="allow")
|
|
57
|
+
|
|
55
58
|
task: str = Field(description="The task to run.")
|
|
56
59
|
response_model: dict[str, Any] | None = Field(
|
|
57
60
|
default=None, description="If provided, the JSON schema describing the desired output structure. Default is None"
|
|
@@ -64,7 +67,7 @@ class TaskRequest(BaseModel):
|
|
|
64
67
|
default=None, description="A dictionary containing variables or parameters that will be passed to the agent."
|
|
65
68
|
)
|
|
66
69
|
files: list[str] | None = Field(default=None, description="A list of file ids to pass to the agent.")
|
|
67
|
-
agent: Literal["smooth"] = Field(default="smooth", description="The agent to use for the task.")
|
|
70
|
+
agent: Literal["smooth", "smooth-lite"] = Field(default="smooth", description="The agent to use for the task.")
|
|
68
71
|
max_steps: int = Field(default=32, ge=2, le=128, description="Maximum number of steps the agent can take (min 2, max 128).")
|
|
69
72
|
device: Literal["desktop", "mobile"] = Field(default="mobile", description="Device type for the task. Default is mobile.")
|
|
70
73
|
allowed_urls: list[str] | None = Field(
|
|
@@ -114,6 +117,14 @@ class TaskRequest(BaseModel):
|
|
|
114
117
|
warnings.warn("'session_id' is deprecated, use 'profile_id' instead", DeprecationWarning, stacklevel=2)
|
|
115
118
|
self.profile_id = value
|
|
116
119
|
|
|
120
|
+
def model_dump(self, **kwargs) -> dict[str, Any]:
|
|
121
|
+
"""Dump model to dict, including deprecated session_id for retrocompatibility."""
|
|
122
|
+
data = super().model_dump(**kwargs)
|
|
123
|
+
# Add deprecated session_id field for retrocompatibility
|
|
124
|
+
if "profile_id" in data:
|
|
125
|
+
data["session_id"] = data["profile_id"]
|
|
126
|
+
return data
|
|
127
|
+
|
|
117
128
|
|
|
118
129
|
class BrowserSessionRequest(BaseModel):
|
|
119
130
|
"""Request model for creating a browser session."""
|
|
@@ -143,11 +154,20 @@ class BrowserSessionRequest(BaseModel):
|
|
|
143
154
|
warnings.warn("'session_id' is deprecated, use 'profile_id' instead", DeprecationWarning, stacklevel=2)
|
|
144
155
|
self.profile_id = value
|
|
145
156
|
|
|
157
|
+
def model_dump(self, **kwargs) -> dict[str, Any]:
|
|
158
|
+
"""Dump model to dict, including deprecated session_id for retrocompatibility."""
|
|
159
|
+
data = super().model_dump(**kwargs)
|
|
160
|
+
# Add deprecated session_id field for retrocompatibility
|
|
161
|
+
if "profile_id" in data:
|
|
162
|
+
data["session_id"] = data["profile_id"]
|
|
163
|
+
return data
|
|
164
|
+
|
|
146
165
|
|
|
147
166
|
class BrowserSessionResponse(BaseModel):
|
|
148
167
|
"""Browser session response model."""
|
|
149
168
|
|
|
150
169
|
profile_id: str = Field(description="The ID of the browser profile associated with the opened browser instance.")
|
|
170
|
+
live_id: str | None = Field(description="The ID of the live browser session.")
|
|
151
171
|
live_url: str | None = Field(default=None, description="The live URL to interact with the browser session.")
|
|
152
172
|
|
|
153
173
|
@model_validator(mode="before")
|
|
@@ -170,6 +190,14 @@ class BrowserSessionResponse(BaseModel):
|
|
|
170
190
|
warnings.warn("'session_id' is deprecated, use 'profile_id' instead", DeprecationWarning, stacklevel=2)
|
|
171
191
|
self.profile_id = value
|
|
172
192
|
|
|
193
|
+
def model_dump(self, **kwargs) -> dict[str, Any]:
|
|
194
|
+
"""Dump model to dict, including deprecated session_id for retrocompatibility."""
|
|
195
|
+
data = super().model_dump(**kwargs)
|
|
196
|
+
# Add deprecated session_id field for retrocompatibility
|
|
197
|
+
if "profile_id" in data:
|
|
198
|
+
data["session_id"] = data["profile_id"]
|
|
199
|
+
return data
|
|
200
|
+
|
|
173
201
|
|
|
174
202
|
class BrowserProfilesResponse(BaseModel):
|
|
175
203
|
"""Response model for listing browser profiles."""
|
|
@@ -196,9 +224,18 @@ class BrowserProfilesResponse(BaseModel):
|
|
|
196
224
|
warnings.warn("'session_ids' is deprecated, use 'profile_ids' instead", DeprecationWarning, stacklevel=2)
|
|
197
225
|
self.profile_ids = value
|
|
198
226
|
|
|
227
|
+
def model_dump(self, **kwargs) -> dict[str, Any]:
|
|
228
|
+
"""Dump model to dict, including deprecated session_ids for retrocompatibility."""
|
|
229
|
+
data = super().model_dump(**kwargs)
|
|
230
|
+
# Add deprecated session_ids field for retrocompatibility
|
|
231
|
+
if "profile_ids" in data:
|
|
232
|
+
data["session_ids"] = data["profile_ids"]
|
|
233
|
+
return data
|
|
234
|
+
|
|
199
235
|
|
|
200
236
|
class BrowserSessionsResponse(BrowserProfilesResponse):
|
|
201
237
|
"""Response model for listing browser profiles."""
|
|
238
|
+
|
|
202
239
|
pass
|
|
203
240
|
|
|
204
241
|
|
|
@@ -312,6 +349,15 @@ class TaskHandle:
|
|
|
312
349
|
"""Returns the task ID."""
|
|
313
350
|
return self._id
|
|
314
351
|
|
|
352
|
+
def stop(self):
|
|
353
|
+
"""Stops the task."""
|
|
354
|
+
try:
|
|
355
|
+
response = self._client._client.delete(f"{self._client.base_url}/task/{self._id}")
|
|
356
|
+
self._handle_response(response)
|
|
357
|
+
except requests.exceptions.RequestException as e:
|
|
358
|
+
logger.error(f"Request failed: {e}")
|
|
359
|
+
raise ApiError(status_code=0, detail=f"Request failed: {str(e)}") from None
|
|
360
|
+
|
|
315
361
|
def result(self, timeout: int | None = None, poll_interval: float = 1) -> TaskResponse:
|
|
316
362
|
"""Waits for the task to complete and returns the result."""
|
|
317
363
|
if self._task_response and self._task_response.status not in ["running", "waiting"]:
|
|
@@ -331,7 +377,7 @@ class TaskHandle:
|
|
|
331
377
|
time.sleep(poll_interval)
|
|
332
378
|
raise TimeoutError(f"Task {self.id()} did not complete within {timeout} seconds.")
|
|
333
379
|
|
|
334
|
-
def live_url(self, interactive: bool =
|
|
380
|
+
def live_url(self, interactive: bool = False, embed: bool = False, timeout: int | None = None):
|
|
335
381
|
"""Returns the live URL for the task."""
|
|
336
382
|
if self._task_response and self._task_response.live_url:
|
|
337
383
|
return _encode_url(self._task_response.live_url, interactive=interactive, embed=embed)
|
|
@@ -509,6 +555,15 @@ class SmoothClient(BaseClient):
|
|
|
509
555
|
logger.error(f"Request failed: {e}")
|
|
510
556
|
raise ApiError(status_code=0, detail=f"Request failed: {str(e)}") from None
|
|
511
557
|
|
|
558
|
+
def close_session(self, live_id: str):
|
|
559
|
+
"""Closes a browser session."""
|
|
560
|
+
try:
|
|
561
|
+
response = self._session.delete(f"{self.base_url}/browser/session/{live_id}")
|
|
562
|
+
self._handle_response(response)
|
|
563
|
+
except requests.exceptions.RequestException as e:
|
|
564
|
+
logger.error(f"Request failed: {e}")
|
|
565
|
+
raise ApiError(status_code=0, detail=f"Request failed: {str(e)}") from None
|
|
566
|
+
|
|
512
567
|
def list_profiles(self):
|
|
513
568
|
"""Lists all browser profiles for the user.
|
|
514
569
|
|
|
@@ -797,6 +852,15 @@ class SmoothAsyncClient(BaseClient):
|
|
|
797
852
|
logger.error(f"Request failed: {e}")
|
|
798
853
|
raise ApiError(status_code=0, detail=f"Request failed: {str(e)}") from None
|
|
799
854
|
|
|
855
|
+
async def close_session(self, live_id: str):
|
|
856
|
+
"""Closes a browser session."""
|
|
857
|
+
try:
|
|
858
|
+
response = await self._client.delete(f"{self.base_url}/browser/session/{live_id}")
|
|
859
|
+
self._handle_response(response)
|
|
860
|
+
except httpx.RequestError as e:
|
|
861
|
+
logger.error(f"Request failed: {e}")
|
|
862
|
+
raise ApiError(status_code=0, detail=f"Request failed: {str(e)}") from None
|
|
863
|
+
|
|
800
864
|
async def list_profiles(self):
|
|
801
865
|
"""Lists all browser profiles for the user.
|
|
802
866
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|