smooth-py 0.2.8.dev20251006__tar.gz → 0.2.8.dev20251009__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.dev20251006 → smooth_py-0.2.8.dev20251009}/PKG-INFO +1 -1
- {smooth_py-0.2.8.dev20251006 → smooth_py-0.2.8.dev20251009}/pyproject.toml +1 -1
- {smooth_py-0.2.8.dev20251006 → smooth_py-0.2.8.dev20251009}/src/smooth/__init__.py +38 -8
- {smooth_py-0.2.8.dev20251006 → smooth_py-0.2.8.dev20251009}/README.md +0 -0
- {smooth_py-0.2.8.dev20251006 → smooth_py-0.2.8.dev20251009}/src/smooth/mcp/__init__.py +0 -0
- {smooth_py-0.2.8.dev20251006 → smooth_py-0.2.8.dev20251009}/src/smooth/mcp/server.py +0 -0
|
@@ -13,13 +13,13 @@ 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, ConfigDict, Field, model_validator
|
|
16
|
+
from pydantic import BaseModel, ConfigDict, Field, computed_field, model_validator
|
|
17
17
|
|
|
18
18
|
# Configure logging
|
|
19
19
|
logger = logging.getLogger("smooth")
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
BASE_URL = "https://
|
|
22
|
+
BASE_URL = "https://api.smooth.sh/api/"
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
# --- Utils ---
|
|
@@ -53,6 +53,8 @@ class TaskResponse(BaseModel):
|
|
|
53
53
|
class TaskRequest(BaseModel):
|
|
54
54
|
"""Run task request model."""
|
|
55
55
|
|
|
56
|
+
model_config = ConfigDict(extra="allow")
|
|
57
|
+
|
|
56
58
|
task: str = Field(description="The task to run.")
|
|
57
59
|
response_model: dict[str, Any] | None = Field(
|
|
58
60
|
default=None, description="If provided, the JSON schema describing the desired output structure. Default is None"
|
|
@@ -65,7 +67,7 @@ class TaskRequest(BaseModel):
|
|
|
65
67
|
default=None, description="A dictionary containing variables or parameters that will be passed to the agent."
|
|
66
68
|
)
|
|
67
69
|
files: list[str] | None = Field(default=None, description="A list of file ids to pass to the agent.")
|
|
68
|
-
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.")
|
|
69
71
|
max_steps: int = Field(default=32, ge=2, le=128, description="Maximum number of steps the agent can take (min 2, max 128).")
|
|
70
72
|
device: Literal["desktop", "mobile"] = Field(default="mobile", description="Device type for the task. Default is mobile.")
|
|
71
73
|
allowed_urls: list[str] | None = Field(
|
|
@@ -98,11 +100,12 @@ class TaskRequest(BaseModel):
|
|
|
98
100
|
@model_validator(mode="before")
|
|
99
101
|
@classmethod
|
|
100
102
|
def _handle_deprecated_session_id(cls, data: Any) -> Any:
|
|
101
|
-
if isinstance(data, dict) and "session_id" in data:
|
|
103
|
+
if isinstance(data, dict) and "session_id" in data and "profile_id" not in data:
|
|
102
104
|
warnings.warn("'session_id' is deprecated, use 'profile_id' instead", DeprecationWarning, stacklevel=2)
|
|
103
105
|
data["profile_id"] = data.pop("session_id")
|
|
104
106
|
return data
|
|
105
107
|
|
|
108
|
+
@computed_field(return_type=str | None)
|
|
106
109
|
@property
|
|
107
110
|
def session_id(self):
|
|
108
111
|
"""(Deprecated) Returns the session ID."""
|
|
@@ -115,6 +118,14 @@ class TaskRequest(BaseModel):
|
|
|
115
118
|
warnings.warn("'session_id' is deprecated, use 'profile_id' instead", DeprecationWarning, stacklevel=2)
|
|
116
119
|
self.profile_id = value
|
|
117
120
|
|
|
121
|
+
def model_dump(self, **kwargs) -> dict[str, Any]:
|
|
122
|
+
"""Dump model to dict, including deprecated session_id for retrocompatibility."""
|
|
123
|
+
data = super().model_dump(**kwargs)
|
|
124
|
+
# Add deprecated session_id field for retrocompatibility
|
|
125
|
+
if "profile_id" in data:
|
|
126
|
+
data["session_id"] = data["profile_id"]
|
|
127
|
+
return data
|
|
128
|
+
|
|
118
129
|
|
|
119
130
|
class BrowserSessionRequest(BaseModel):
|
|
120
131
|
"""Request model for creating a browser session."""
|
|
@@ -127,11 +138,12 @@ class BrowserSessionRequest(BaseModel):
|
|
|
127
138
|
@model_validator(mode="before")
|
|
128
139
|
@classmethod
|
|
129
140
|
def _handle_deprecated_session_id(cls, data: Any) -> Any:
|
|
130
|
-
if isinstance(data, dict) and "session_id" in data:
|
|
141
|
+
if isinstance(data, dict) and "session_id" in data and "profile_id" not in data:
|
|
131
142
|
warnings.warn("'session_id' is deprecated, use 'profile_id' instead", DeprecationWarning, stacklevel=2)
|
|
132
143
|
data["profile_id"] = data.pop("session_id")
|
|
133
144
|
return data
|
|
134
145
|
|
|
146
|
+
@computed_field(return_type=str | None)
|
|
135
147
|
@property
|
|
136
148
|
def session_id(self):
|
|
137
149
|
"""(Deprecated) Returns the session ID."""
|
|
@@ -144,6 +156,14 @@ class BrowserSessionRequest(BaseModel):
|
|
|
144
156
|
warnings.warn("'session_id' is deprecated, use 'profile_id' instead", DeprecationWarning, stacklevel=2)
|
|
145
157
|
self.profile_id = value
|
|
146
158
|
|
|
159
|
+
def model_dump(self, **kwargs) -> dict[str, Any]:
|
|
160
|
+
"""Dump model to dict, including deprecated session_id for retrocompatibility."""
|
|
161
|
+
data = super().model_dump(**kwargs)
|
|
162
|
+
# Add deprecated session_id field for retrocompatibility
|
|
163
|
+
if "profile_id" in data:
|
|
164
|
+
data["session_id"] = data["profile_id"]
|
|
165
|
+
return data
|
|
166
|
+
|
|
147
167
|
|
|
148
168
|
class BrowserSessionResponse(BaseModel):
|
|
149
169
|
"""Browser session response model."""
|
|
@@ -155,11 +175,12 @@ class BrowserSessionResponse(BaseModel):
|
|
|
155
175
|
@model_validator(mode="before")
|
|
156
176
|
@classmethod
|
|
157
177
|
def _handle_deprecated_session_id(cls, data: Any) -> Any:
|
|
158
|
-
if isinstance(data, dict) and "session_id" in data:
|
|
178
|
+
if isinstance(data, dict) and "session_id" in data and "profile_id" not in data:
|
|
159
179
|
warnings.warn("'session_id' is deprecated, use 'profile_id' instead", DeprecationWarning, stacklevel=2)
|
|
160
180
|
data["profile_id"] = data.pop("session_id")
|
|
161
181
|
return data
|
|
162
182
|
|
|
183
|
+
@computed_field(return_type=str | None)
|
|
163
184
|
@property
|
|
164
185
|
def session_id(self):
|
|
165
186
|
"""(Deprecated) Returns the session ID."""
|
|
@@ -181,11 +202,12 @@ class BrowserProfilesResponse(BaseModel):
|
|
|
181
202
|
@model_validator(mode="before")
|
|
182
203
|
@classmethod
|
|
183
204
|
def _handle_deprecated_session_ids(cls, data: Any) -> Any:
|
|
184
|
-
if isinstance(data, dict) and "session_ids" in data:
|
|
205
|
+
if isinstance(data, dict) and "session_ids" in data and "profile_ids" not in data:
|
|
185
206
|
warnings.warn("'session_ids' is deprecated, use 'profile_ids' instead", DeprecationWarning, stacklevel=2)
|
|
186
207
|
data["profile_ids"] = data.pop("session_ids")
|
|
187
208
|
return data
|
|
188
209
|
|
|
210
|
+
@computed_field(return_type=list[str])
|
|
189
211
|
@property
|
|
190
212
|
def session_ids(self):
|
|
191
213
|
"""(Deprecated) Returns the session IDs."""
|
|
@@ -198,6 +220,14 @@ class BrowserProfilesResponse(BaseModel):
|
|
|
198
220
|
warnings.warn("'session_ids' is deprecated, use 'profile_ids' instead", DeprecationWarning, stacklevel=2)
|
|
199
221
|
self.profile_ids = value
|
|
200
222
|
|
|
223
|
+
def model_dump(self, **kwargs) -> dict[str, Any]:
|
|
224
|
+
"""Dump model to dict, including deprecated session_ids for retrocompatibility."""
|
|
225
|
+
data = super().model_dump(**kwargs)
|
|
226
|
+
# Add deprecated session_ids field for retrocompatibility
|
|
227
|
+
if "profile_ids" in data:
|
|
228
|
+
data["session_ids"] = data["profile_ids"]
|
|
229
|
+
return data
|
|
230
|
+
|
|
201
231
|
|
|
202
232
|
class BrowserSessionsResponse(BrowserProfilesResponse):
|
|
203
233
|
"""Response model for listing browser profiles."""
|
|
@@ -343,7 +373,7 @@ class TaskHandle:
|
|
|
343
373
|
time.sleep(poll_interval)
|
|
344
374
|
raise TimeoutError(f"Task {self.id()} did not complete within {timeout} seconds.")
|
|
345
375
|
|
|
346
|
-
def live_url(self, interactive: bool =
|
|
376
|
+
def live_url(self, interactive: bool = False, embed: bool = False, timeout: int | None = None):
|
|
347
377
|
"""Returns the live URL for the task."""
|
|
348
378
|
if self._task_response and self._task_response.live_url:
|
|
349
379
|
return _encode_url(self._task_response.live_url, interactive=interactive, embed=embed)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|