smooth-py 0.1.2__py3-none-any.whl → 0.1.3__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
@@ -8,6 +8,7 @@ from typing import (
8
8
  Any,
9
9
  Literal,
10
10
  )
11
+ from urllib.parse import urlencode
11
12
 
12
13
  import httpx
13
14
  import requests
@@ -40,9 +41,9 @@ class TaskRequest(BaseModel):
40
41
 
41
42
  task: str = Field(description="The task to run.")
42
43
  agent: Literal["smooth"] = Field(default="smooth", description="The agent to use for the task.")
43
- max_steps: int = Field(default=32, ge=2, le=64, description="Maximum number of steps the agent can take (min 2, max 64).")
44
+ max_steps: int = Field(default=32, ge=2, le=128, description="Maximum number of steps the agent can take (min 2, max 128).")
44
45
  device: Literal["desktop", "mobile"] = Field(default="mobile", description="Device type for the task. Default is mobile.")
45
- enable_recording: bool = Field(default=False, description="Enable video recording of the task execution. Default is False")
46
+ enable_recording: bool = Field(default=True, description="Enable video recording of the task execution. Default is True")
46
47
  session_id: str | None = Field(
47
48
  default=None,
48
49
  description="Browser session ID to use. Each session maintains its own state, such as login credentials.",
@@ -51,7 +52,7 @@ class TaskRequest(BaseModel):
51
52
  proxy_server: str | None = Field(
52
53
  default=None,
53
54
  description=(
54
- "Proxy server url to route browser traffic through." " Must include the protocol to use (e.g. http:// or https://)"
55
+ "Proxy server url to route browser traffic through. Must include the protocol to use (e.g. http:// or https://)"
55
56
  ),
56
57
  )
57
58
  proxy_username: str | None = Field(default=None, description="Proxy server username.")
@@ -159,9 +160,9 @@ class TaskHandle:
159
160
  self._poll_interval = poll_interval
160
161
  self._timeout = timeout
161
162
  self._task_response: TaskResponse | None = None
163
+ self._live_url = live_url
162
164
 
163
165
  self.id = task_id
164
- self.live_url = live_url
165
166
 
166
167
  def result(self) -> TaskResponse:
167
168
  """Waits for the task to complete and returns the result."""
@@ -177,6 +178,28 @@ class TaskHandle:
177
178
  time.sleep(self._poll_interval)
178
179
  raise TimeoutError(f"Task {self.id} did not complete within {self._timeout} seconds.")
179
180
 
181
+ def live_url(self, interactive: bool = True, embed: bool = False) -> str:
182
+ """Returns the live URL for the task."""
183
+ params = {
184
+ "interactive": interactive,
185
+ "embed": embed
186
+ }
187
+ return f"{self._live_url}?{urlencode(params)}"
188
+
189
+ def recording_url(self) -> str:
190
+ """Returns the recording URL for the task."""
191
+ if self._task_response and self._task_response.recording_url is not None:
192
+ return self._task_response.recording_url
193
+
194
+ start_time = time.time()
195
+ while (time.time() - start_time) < 8:
196
+ task_response = self._client._get_task(self.id) # pyright: ignore [reportPrivateUsage]
197
+ self._task_response = task_response
198
+ if task_response.recording_url is not None:
199
+ return task_response.recording_url
200
+ time.sleep(1)
201
+ raise TimeoutError(f"Recording not available for task {self.id}.")
202
+
180
203
 
181
204
  class SmoothClient(BaseClient):
182
205
  """A synchronous client for the API."""
@@ -349,10 +372,10 @@ class AsyncTaskHandle:
349
372
  self._client = client
350
373
  self._poll_interval = poll_interval
351
374
  self._timeout = timeout
375
+ self._live_url = live_url
352
376
  self._task_response: TaskResponse | None = None
353
377
 
354
378
  self.id = task_id
355
- self.live_url = live_url
356
379
 
357
380
  async def result(self) -> TaskResponse:
358
381
  """Waits for the task to complete and returns the result."""
@@ -362,12 +385,33 @@ class AsyncTaskHandle:
362
385
  start_time = time.time()
363
386
  while self._timeout is None or (time.time() - start_time) < self._timeout:
364
387
  task_response = await self._client._get_task(self.id) # pyright: ignore [reportPrivateUsage]
388
+ self._task_response = task_response
365
389
  if task_response.status not in ["running", "waiting"]:
366
- self._task_response = task_response
367
390
  return task_response
368
391
  await asyncio.sleep(self._poll_interval)
369
392
  raise TimeoutError(f"Task {self.id} did not complete within {self._timeout} seconds.")
370
393
 
394
+ def live_url(self, interactive: bool = True, embed: bool = False) -> str:
395
+ """Returns the live URL for the task."""
396
+ params = {
397
+ "interactive": interactive,
398
+ "embed": embed
399
+ }
400
+ return f"{self._live_url}?{urlencode(params)}"
401
+
402
+ async def recording_url(self) -> str:
403
+ """Returns the recording URL for the task."""
404
+ if self._task_response and self._task_response.recording_url is not None:
405
+ return self._task_response.recording_url
406
+
407
+ start_time = time.time()
408
+ while (time.time() - start_time) < 8:
409
+ task_response = await self._client._get_task(self.id) # pyright: ignore [reportPrivateUsage]
410
+ self._task_response = task_response
411
+ if task_response.recording_url is not None:
412
+ return task_response.recording_url
413
+ await asyncio.sleep(1)
414
+ raise TimeoutError(f"Recording not available for task {self.id}.")
371
415
 
372
416
  class SmoothAsyncClient(BaseClient):
373
417
  """An asynchronous client for the API."""
@@ -411,8 +455,6 @@ class SmoothAsyncClient(BaseClient):
411
455
  async def run(
412
456
  self,
413
457
  task: str,
414
- poll_interval: int = 1,
415
- timeout: int = 60 * 15,
416
458
  agent: Literal["smooth"] = "smooth",
417
459
  max_steps: int = 32,
418
460
  device: Literal["desktop", "mobile"] = "mobile",
@@ -422,6 +464,8 @@ class SmoothAsyncClient(BaseClient):
422
464
  proxy_server: str | None = None,
423
465
  proxy_username: str | None = None,
424
466
  proxy_password: str | None = None,
467
+ poll_interval: int = 1,
468
+ timeout: int = 60 * 15,
425
469
  ) -> AsyncTaskHandle:
426
470
  """Runs a task and returns a handle to the task asynchronously.
427
471
 
@@ -430,8 +474,6 @@ class SmoothAsyncClient(BaseClient):
430
474
 
431
475
  Args:
432
476
  task: The task to run.
433
- poll_interval: The time in seconds to wait between polling for status.
434
- timeout: The maximum time in seconds to wait for the task to complete.
435
477
  agent: The agent to use for the task.
436
478
  max_steps: Maximum number of steps the agent can take (max 64).
437
479
  device: Device type for the task. Default is mobile.
@@ -441,6 +483,8 @@ class SmoothAsyncClient(BaseClient):
441
483
  proxy_server: Proxy server url to route browser traffic through.
442
484
  proxy_username: Proxy server username.
443
485
  proxy_password: Proxy server password.
486
+ poll_interval: The time in seconds to wait between polling for status.
487
+ timeout: The maximum time in seconds to wait for the task to complete.
444
488
 
445
489
  Returns:
446
490
  A handle to the running task.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: smooth-py
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary:
5
5
  Author: Luca Pinchetti
6
6
  Author-email: luca@circlemind.co
@@ -0,0 +1,4 @@
1
+ smooth/__init__.py,sha256=dmofDTp_gE9sHBG3ZrCgApWQKtJn7a4MTOWuzxG6f_A,21078
2
+ smooth_py-0.1.3.dist-info/METADATA,sha256=DiTe2Cg4TNmJGCGX_qHOhrKYzwHzvKWIxYIq3Yrqi9w,5388
3
+ smooth_py-0.1.3.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
4
+ smooth_py-0.1.3.dist-info/RECORD,,
@@ -1,4 +0,0 @@
1
- smooth/__init__.py,sha256=23X7aQVAVzYcwh2KCZ8RfWL1rPzpE6W8IWWwVSDPzIo,19324
2
- smooth_py-0.1.2.dist-info/METADATA,sha256=x-k813clxo_ET7pl-MBv4CJojFxYRSIBwoWokN091ak,5388
3
- smooth_py-0.1.2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
4
- smooth_py-0.1.2.dist-info/RECORD,,