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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: smooth-py
3
- Version: 0.2.8.dev20251006
3
+ Version: 0.2.8.dev20251009
4
4
  Summary:
5
5
  Author: Luca Pinchetti
6
6
  Author-email: luca@circlemind.co
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "smooth-py"
3
- version = "0.2.8.dev20251006"
3
+ version = "0.2.8.dev20251009"
4
4
  description = ""
5
5
  authors = [
6
6
  {name = "Luca Pinchetti",email = "luca@circlemind.co"}
@@ -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://api2.circlemind.co/api/"
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 = True, embed: bool = False, timeout: int | None = None):
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)