smooth-py 0.2.8.dev20251003__py3-none-any.whl → 0.2.8.dev20251008__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
@@ -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
- model_config = ConfigDict(extra='allow')
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 = True, embed: bool = False, timeout: int | None = None):
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
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: smooth-py
3
- Version: 0.2.8.dev20251003
3
+ Version: 0.2.8.dev20251008
4
4
  Summary:
5
5
  Author: Luca Pinchetti
6
6
  Author-email: luca@circlemind.co
@@ -0,0 +1,6 @@
1
+ smooth/__init__.py,sha256=UFvVVla_T5EiOYimpxKQs0D24-F0ZZyRnl1hpJ8YohA,37737
2
+ smooth/mcp/__init__.py,sha256=0aJVFi2a8Ah3-5xtgyZ5UMbaaJsBWu2T8QLWoFQITk8,219
3
+ smooth/mcp/server.py,sha256=9SymTD4NOGTMN8P-LNGlvYNvv81yCIZfZeeuhEcAc6s,20068
4
+ smooth_py-0.2.8.dev20251008.dist-info/METADATA,sha256=Ya-GED2N4TX7XU3MF0Cmy4PaWpwEF45-agZY9daW5F0,7529
5
+ smooth_py-0.2.8.dev20251008.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
6
+ smooth_py-0.2.8.dev20251008.dist-info/RECORD,,
@@ -1,6 +0,0 @@
1
- smooth/__init__.py,sha256=KFKADb6yVVy8Xcsb0mYG7dsIhd4b4VuviyLonAbouqo,35123
2
- smooth/mcp/__init__.py,sha256=0aJVFi2a8Ah3-5xtgyZ5UMbaaJsBWu2T8QLWoFQITk8,219
3
- smooth/mcp/server.py,sha256=9SymTD4NOGTMN8P-LNGlvYNvv81yCIZfZeeuhEcAc6s,20068
4
- smooth_py-0.2.8.dev20251003.dist-info/METADATA,sha256=x5hyXybb5aY_xcG8ohkMf4cKDwmHYslZ0DGpIVQQS0Y,7529
5
- smooth_py-0.2.8.dev20251003.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
6
- smooth_py-0.2.8.dev20251003.dist-info/RECORD,,