smooth-py 0.2.0__py3-none-any.whl → 0.2.1.post0__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
|
@@ -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.
|
|
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.
|
|
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)
|
|
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)
|
|
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)
|
|
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.
|
|
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)
|
|
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)
|
|
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)
|
|
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,
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
smooth/__init__.py,sha256=ONEEpCPFOF9caI1IddSxP_v_MPPs8ovFLyQ6oFCERJE,24412
|
|
2
|
+
smooth/mcp/__init__.py,sha256=0aJVFi2a8Ah3-5xtgyZ5UMbaaJsBWu2T8QLWoFQITk8,219
|
|
3
|
+
smooth/mcp/server.py,sha256=9SymTD4NOGTMN8P-LNGlvYNvv81yCIZfZeeuhEcAc6s,20068
|
|
4
|
+
smooth_py-0.2.1.post0.dist-info/METADATA,sha256=iT9G3pLXSa1P9jeW6XSRu17DhXCEufzX04lrLK9SR30,7431
|
|
5
|
+
smooth_py-0.2.1.post0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
6
|
+
smooth_py-0.2.1.post0.dist-info/RECORD,,
|
smooth_py-0.2.0.dist-info/RECORD
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
smooth/__init__.py,sha256=U32quTlDKOWQpsstfJ7pCgsOeUWYC3AAAzQDJkpBzBk,23629
|
|
2
|
-
smooth/mcp/__init__.py,sha256=0aJVFi2a8Ah3-5xtgyZ5UMbaaJsBWu2T8QLWoFQITk8,219
|
|
3
|
-
smooth/mcp/server.py,sha256=9SymTD4NOGTMN8P-LNGlvYNvv81yCIZfZeeuhEcAc6s,20068
|
|
4
|
-
smooth_py-0.2.0.dist-info/METADATA,sha256=o9iLsqHyEBGkOyPmW695HHmcQwV0afH2Evkp7a0O6KA,7425
|
|
5
|
-
smooth_py-0.2.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
6
|
-
smooth_py-0.2.0.dist-info/RECORD,,
|
|
File without changes
|