smooth-py 0.2.0__tar.gz → 0.2.1.post0__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.0
3
+ Version: 0.2.1.post0
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.0"
3
+ version = "0.2.1.post0"
4
4
  description = ""
5
5
  authors = [
6
6
  {name = "Luca Pinchetti",email = "luca@circlemind.co"}
@@ -49,8 +49,13 @@ class TaskRequest(BaseModel):
49
49
 
50
50
  task: str = Field(description="The task to run.")
51
51
  response_model: dict[str, Any] | None = Field(
52
- default=None, description="If provided, the schema describing the desired output structure. Default is None"
52
+ default=None, description="If provided, the JSON schema describing the desired output structure. Default is None"
53
53
  )
54
+ url: str | None = Field(
55
+ default=None,
56
+ description="(Optional) The starting URL for the task. If not provided, the agent will infer it from the task.",
57
+ )
58
+ metadata: dict[str, str | int | float | bool] | None = Field(default=None, description="Optional metadata for the task.")
54
59
  agent: Literal["smooth"] = Field(default="smooth", description="The agent to use for the task.")
55
60
  max_steps: int = Field(default=32, ge=2, le=128, description="Maximum number of steps the agent can take (min 2, max 128).")
56
61
  device: Literal["desktop", "mobile"] = Field(default="mobile", description="Device type for the task. Default is mobile.")
@@ -136,7 +141,7 @@ class BaseClient:
136
141
  self.headers = {
137
142
  "apikey": self.api_key,
138
143
  "Content-Type": "application/json",
139
- "User-Agent": "smooth-python-sdk/0.1.1",
144
+ "User-Agent": "smooth-python-sdk/0.2.0",
140
145
  }
141
146
 
142
147
  def _handle_response(self, response: requests.Response | httpx.Response) -> dict[str, Any]:
@@ -187,7 +192,11 @@ class TaskHandle:
187
192
  self._client = client
188
193
  self._task_response: TaskResponse | None = None
189
194
 
190
- self.id = task_id
195
+ self._id = task_id
196
+
197
+ def id(self):
198
+ """Returns the task ID."""
199
+ return self._id
191
200
 
192
201
  def result(self, timeout: int | None = None, poll_interval: float = 1) -> TaskResponse:
193
202
  """Waits for the task to complete and returns the result."""
@@ -201,12 +210,12 @@ class TaskHandle:
201
210
 
202
211
  start_time = time.time()
203
212
  while timeout is None or (time.time() - start_time) < timeout:
204
- task_response = self._client._get_task(self.id) # pyright: ignore [reportPrivateUsage]
213
+ task_response = self._client._get_task(self.id())
205
214
  self._task_response = task_response
206
215
  if task_response.status not in ["running", "waiting"]:
207
216
  return task_response
208
217
  time.sleep(poll_interval)
209
- raise TimeoutError(f"Task {self.id} did not complete within {timeout} seconds.")
218
+ raise TimeoutError(f"Task {self.id()} did not complete within {timeout} seconds.")
210
219
 
211
220
  def live_url(self, interactive: bool = True, embed: bool = False, timeout: int | None = None):
212
221
  """Returns the live URL for the task."""
@@ -215,13 +224,13 @@ class TaskHandle:
215
224
 
216
225
  start_time = time.time()
217
226
  while timeout is None or (time.time() - start_time) < timeout:
218
- task_response = self._client._get_task(self.id) # pyright: ignore [reportPrivateUsage]
227
+ task_response = self._client._get_task(self.id())
219
228
  self._task_response = task_response
220
229
  if self._task_response.live_url:
221
230
  return _encode_url(self._task_response.live_url, interactive=interactive, embed=embed)
222
231
  time.sleep(1)
223
232
 
224
- raise TimeoutError(f"Live URL not available for task {self.id}.")
233
+ raise TimeoutError(f"Live URL not available for task {self.id()}.")
225
234
 
226
235
  def recording_url(self, timeout: int | None = None) -> str:
227
236
  """Returns the recording URL for the task."""
@@ -230,12 +239,12 @@ class TaskHandle:
230
239
 
231
240
  start_time = time.time()
232
241
  while timeout is None or (time.time() - start_time) < timeout:
233
- task_response = self._client._get_task(self.id) # pyright: ignore [reportPrivateUsage]
242
+ task_response = self._client._get_task(self.id())
234
243
  self._task_response = task_response
235
244
  if task_response.recording_url is not None:
236
245
  return task_response.recording_url
237
246
  time.sleep(1)
238
- raise TimeoutError(f"Recording URL not available for task {self.id}.")
247
+ raise TimeoutError(f"Recording URL not available for task {self.id()}.")
239
248
 
240
249
 
241
250
  class SmoothClient(BaseClient):
@@ -287,6 +296,8 @@ class SmoothClient(BaseClient):
287
296
  self,
288
297
  task: str,
289
298
  response_model: dict[str, Any] | Type[BaseModel] | None = None,
299
+ url: str | None = None,
300
+ metadata: dict[str, str | int | float | bool] | None = None,
290
301
  agent: Literal["smooth"] = "smooth",
291
302
  max_steps: int = 32,
292
303
  device: Literal["desktop", "mobile"] = "mobile",
@@ -305,6 +316,8 @@ class SmoothClient(BaseClient):
305
316
  Args:
306
317
  task: The task to run.
307
318
  response_model: If provided, the schema describing the desired output structure.
319
+ url: The starting URL for the task. If not provided, the agent will infer it from the task.
320
+ metadata: Optional metadata for the task.
308
321
  agent: The agent to use for the task.
309
322
  max_steps: Maximum number of steps the agent can take (max 64).
310
323
  device: Device type for the task. Default is mobile.
@@ -324,6 +337,8 @@ class SmoothClient(BaseClient):
324
337
  payload = TaskRequest(
325
338
  task=task,
326
339
  response_model=response_model.model_json_schema() if issubclass(response_model, BaseModel) else response_model,
340
+ url=url,
341
+ metadata=metadata,
327
342
  agent=agent,
328
343
  max_steps=max_steps,
329
344
  device=device,
@@ -400,7 +415,11 @@ class AsyncTaskHandle:
400
415
  self._client = client
401
416
  self._task_response: TaskResponse | None = None
402
417
 
403
- self.id = task_id
418
+ self._id = task_id
419
+
420
+ def id(self):
421
+ """Returns the task ID."""
422
+ return self._id
404
423
 
405
424
  async def result(self, timeout: int | None = None, poll_interval: float = 1) -> TaskResponse:
406
425
  """Waits for the task to complete and returns the result."""
@@ -414,12 +433,12 @@ class AsyncTaskHandle:
414
433
 
415
434
  start_time = time.time()
416
435
  while timeout is None or (time.time() - start_time) < timeout:
417
- task_response = await self._client._get_task(self.id) # pyright: ignore [reportPrivateUsage]
436
+ task_response = await self._client._get_task(self.id())
418
437
  self._task_response = task_response
419
438
  if task_response.status not in ["running", "waiting"]:
420
439
  return task_response
421
440
  await asyncio.sleep(poll_interval)
422
- raise TimeoutError(f"Task {self.id} did not complete within {timeout} seconds.")
441
+ raise TimeoutError(f"Task {self.id()} did not complete within {timeout} seconds.")
423
442
 
424
443
  async def live_url(self, interactive: bool = True, embed: bool = False, timeout: int | None = None):
425
444
  """Returns the live URL for the task."""
@@ -428,13 +447,13 @@ class AsyncTaskHandle:
428
447
 
429
448
  start_time = time.time()
430
449
  while timeout is None or (time.time() - start_time) < timeout:
431
- task_response = await self._client._get_task(self.id) # pyright: ignore [reportPrivateUsage]
450
+ task_response = await self._client._get_task(self.id())
432
451
  self._task_response = task_response
433
452
  if task_response.live_url is not None:
434
453
  return _encode_url(self._task_response.live_url, interactive=interactive, embed=embed)
435
454
  await asyncio.sleep(1)
436
455
 
437
- raise TimeoutError(f"Live URL not available for task {self.id}.")
456
+ raise TimeoutError(f"Live URL not available for task {self.id()}.")
438
457
 
439
458
  async def recording_url(self, timeout: int | None = None):
440
459
  """Returns the recording URL for the task."""
@@ -443,13 +462,13 @@ class AsyncTaskHandle:
443
462
 
444
463
  start_time = time.time()
445
464
  while timeout is None or (time.time() - start_time) < timeout:
446
- task_response = await self._client._get_task(self.id) # pyright: ignore [reportPrivateUsage]
465
+ task_response = await self._client._get_task(self.id())
447
466
  self._task_response = task_response
448
467
  if task_response.recording_url is not None:
449
468
  return task_response.recording_url
450
469
  await asyncio.sleep(1)
451
470
 
452
- raise TimeoutError(f"Recording URL not available for task {self.id}.")
471
+ raise TimeoutError(f"Recording URL not available for task {self.id()}.")
453
472
 
454
473
 
455
474
  class SmoothAsyncClient(BaseClient):
@@ -495,6 +514,8 @@ class SmoothAsyncClient(BaseClient):
495
514
  self,
496
515
  task: str,
497
516
  response_model: dict[str, Any] | Type[BaseModel] | None = None,
517
+ url: str | None = None,
518
+ metadata: dict[str, str | int | float | bool] | None = None,
498
519
  agent: Literal["smooth"] = "smooth",
499
520
  max_steps: int = 32,
500
521
  device: Literal["desktop", "mobile"] = "mobile",
@@ -513,6 +534,8 @@ class SmoothAsyncClient(BaseClient):
513
534
  Args:
514
535
  task: The task to run.
515
536
  response_model: If provided, the schema describing the desired output structure.
537
+ url: The starting URL for the task. If not provided, the agent will infer it from the task.
538
+ metadata: Optional metadata for the task.
516
539
  agent: The agent to use for the task.
517
540
  max_steps: Maximum number of steps the agent can take (max 64).
518
541
  device: Device type for the task. Default is mobile.
@@ -534,6 +557,8 @@ class SmoothAsyncClient(BaseClient):
534
557
  payload = TaskRequest(
535
558
  task=task,
536
559
  response_model=response_model.model_json_schema() if issubclass(response_model, BaseModel) else response_model,
560
+ url=url,
561
+ metadata=metadata,
537
562
  agent=agent,
538
563
  max_steps=max_steps,
539
564
  device=device,
File without changes