smooth-py 0.1.0__py3-none-any.whl → 0.1.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
|
@@ -20,23 +20,17 @@ BASE_URL = "https://api2.circlemind.co/api/"
|
|
|
20
20
|
# These models define the data structures for API requests and responses.
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
class TaskData(BaseModel):
|
|
24
|
-
"""Task data model."""
|
|
25
|
-
|
|
26
|
-
result: Any | None = Field(default=None, description="The result of the task if successful.")
|
|
27
|
-
error: str | None = Field(default=None, description="Error message if the task failed.")
|
|
28
|
-
credits_used: int | None = Field(default=None, description="The amount of credits used to perform the task.")
|
|
29
|
-
src: str | None = Field(default=None, description="")
|
|
30
|
-
|
|
31
|
-
|
|
32
23
|
class TaskResponse(BaseModel):
|
|
33
24
|
"""Task response model."""
|
|
34
25
|
|
|
35
26
|
model_config = ConfigDict(extra="forbid")
|
|
36
27
|
|
|
37
28
|
id: str = Field(description="The ID of the task.")
|
|
38
|
-
status:
|
|
39
|
-
|
|
29
|
+
status: Literal["waiting", "running", "done", "failed"] = Field(description="The status of the task.")
|
|
30
|
+
result: Any | None = Field(default=None, description="The result of the task if successful.")
|
|
31
|
+
error: str | None = Field(default=None, description="Error message if the task failed.")
|
|
32
|
+
credits_used: int | None = Field(default=None, description="The amount of credits used to perform the task.")
|
|
33
|
+
src: str | None = Field(default=None, description="")
|
|
40
34
|
|
|
41
35
|
|
|
42
36
|
class TaskRequest(BaseModel):
|
|
@@ -53,7 +47,13 @@ class TaskRequest(BaseModel):
|
|
|
53
47
|
description="(optional) Browser session ID to use. Each session maintains its own state, such as login credentials.",
|
|
54
48
|
)
|
|
55
49
|
stealth_mode: bool = Field(default=False, description="(optional) Run the browser in stealth mode.")
|
|
56
|
-
proxy_server: Optional[str] = Field(
|
|
50
|
+
proxy_server: Optional[str] = Field(
|
|
51
|
+
default=None,
|
|
52
|
+
description=(
|
|
53
|
+
"(optional) Proxy server url to route browser traffic through."
|
|
54
|
+
" Must include the protocol to use (e.g. http:// or https://)"
|
|
55
|
+
),
|
|
56
|
+
)
|
|
57
57
|
proxy_username: Optional[str] = Field(default=None, description="(optional) Proxy server username.")
|
|
58
58
|
proxy_password: Optional[str] = Field(default=None, description="(optional) Proxy server password.")
|
|
59
59
|
|
|
@@ -109,10 +109,10 @@ class BaseClient:
|
|
|
109
109
|
"""Initializes the base client."""
|
|
110
110
|
# Try to get API key from environment if not provided
|
|
111
111
|
if not api_key:
|
|
112
|
-
api_key = os.getenv("
|
|
112
|
+
api_key = os.getenv("CIRCLEMIND_API_KEY")
|
|
113
113
|
|
|
114
114
|
if not api_key:
|
|
115
|
-
raise ValueError("API key is required. Provide it directly or set
|
|
115
|
+
raise ValueError("API key is required. Provide it directly or set CIRCLEMIND_API_KEY environment variable.")
|
|
116
116
|
|
|
117
117
|
if not base_url:
|
|
118
118
|
raise ValueError("Base URL cannot be empty.")
|
|
@@ -120,12 +120,12 @@ class BaseClient:
|
|
|
120
120
|
self.api_key = api_key
|
|
121
121
|
self.base_url = f"{base_url.rstrip('/')}/{api_version}"
|
|
122
122
|
self.headers = {
|
|
123
|
-
"
|
|
123
|
+
"apikey": self.api_key,
|
|
124
124
|
"Content-Type": "application/json",
|
|
125
125
|
"User-Agent": "smooth-python-sdk/0.1.0",
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
def _handle_response(self, response: Union[requests.Response, httpx.Response]) -> dict:
|
|
128
|
+
def _handle_response(self, response: Union[requests.Response, httpx.Response]) -> dict[str, Any]:
|
|
129
129
|
"""Handles HTTP responses and raises exceptions for errors."""
|
|
130
130
|
if 200 <= response.status_code < 300:
|
|
131
131
|
try:
|
|
@@ -135,6 +135,7 @@ class BaseClient:
|
|
|
135
135
|
raise ApiError(status_code=response.status_code, detail="Invalid JSON response from server") from None
|
|
136
136
|
|
|
137
137
|
# Handle error responses
|
|
138
|
+
error_data = None
|
|
138
139
|
try:
|
|
139
140
|
error_data = response.json()
|
|
140
141
|
detail = error_data.get("detail", response.text)
|
|
@@ -143,7 +144,7 @@ class BaseClient:
|
|
|
143
144
|
|
|
144
145
|
logger.error(f"API error: {response.status_code} - {detail}")
|
|
145
146
|
raise ApiError(
|
|
146
|
-
status_code=response.status_code, detail=detail, response_data=error_data
|
|
147
|
+
status_code=response.status_code, detail=detail, response_data=error_data
|
|
147
148
|
)
|
|
148
149
|
|
|
149
150
|
|
|
@@ -163,7 +164,7 @@ class SyncClient(BaseClient):
|
|
|
163
164
|
"""Enters the synchronous context manager."""
|
|
164
165
|
return self
|
|
165
166
|
|
|
166
|
-
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
167
|
+
def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any):
|
|
167
168
|
"""Exits the synchronous context manager."""
|
|
168
169
|
self.close()
|
|
169
170
|
|
|
@@ -267,7 +268,7 @@ class SyncClient(BaseClient):
|
|
|
267
268
|
Raises:
|
|
268
269
|
ApiException: If the API request fails.
|
|
269
270
|
"""
|
|
270
|
-
params = {}
|
|
271
|
+
params: dict[str, Any] = {}
|
|
271
272
|
if session_id:
|
|
272
273
|
params["session_id"] = session_id
|
|
273
274
|
if session_name:
|
|
@@ -314,7 +315,7 @@ class AsyncClient(BaseClient):
|
|
|
314
315
|
"""Enters the asynchronous context manager."""
|
|
315
316
|
return self
|
|
316
317
|
|
|
317
|
-
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
318
|
+
async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any):
|
|
318
319
|
"""Exits the asynchronous context manager."""
|
|
319
320
|
await self.close()
|
|
320
321
|
|
|
@@ -416,7 +417,7 @@ class AsyncClient(BaseClient):
|
|
|
416
417
|
Raises:
|
|
417
418
|
ApiException: If the API request fails.
|
|
418
419
|
"""
|
|
419
|
-
params = {}
|
|
420
|
+
params: dict[str, Any] = {}
|
|
420
421
|
if session_id:
|
|
421
422
|
params["session_id"] = session_id
|
|
422
423
|
if session_name:
|
|
@@ -430,6 +431,23 @@ class AsyncClient(BaseClient):
|
|
|
430
431
|
logger.error(f"Request failed: {e}")
|
|
431
432
|
raise ApiError(status_code=0, detail=f"Request failed: {str(e)}") from None
|
|
432
433
|
|
|
434
|
+
async def list_sessions(self) -> BrowserSessionsResponse:
|
|
435
|
+
"""Lists all browser sessions for the user.
|
|
436
|
+
|
|
437
|
+
Returns:
|
|
438
|
+
A list of existing browser sessions.
|
|
439
|
+
|
|
440
|
+
Raises:
|
|
441
|
+
ApiException: If the API request fails.
|
|
442
|
+
"""
|
|
443
|
+
try:
|
|
444
|
+
response = await self._client.get(f"{self.base_url}/browser/session")
|
|
445
|
+
data = self._handle_response(response)
|
|
446
|
+
return BrowserSessionsResponse(**data["r"])
|
|
447
|
+
except httpx.RequestError as e:
|
|
448
|
+
logger.error(f"Request failed: {e}")
|
|
449
|
+
raise ApiError(status_code=0, detail=f"Request failed: {str(e)}") from None
|
|
450
|
+
|
|
433
451
|
async def close(self):
|
|
434
452
|
"""Closes the async client session."""
|
|
435
453
|
await self._client.aclose()
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: smooth-py
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1.post0
|
|
4
4
|
Summary:
|
|
5
5
|
Author: Luca Pinchetti
|
|
6
|
-
Author-email:
|
|
6
|
+
Author-email: luca@circlemind.co
|
|
7
7
|
Requires-Python: >=3.10
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.10
|
|
@@ -46,10 +46,10 @@ The SDK requires an API key for authentication. You can provide the API key in t
|
|
|
46
46
|
|
|
47
47
|
2. **As an environment variable**:
|
|
48
48
|
|
|
49
|
-
Set the `
|
|
49
|
+
Set the `CIRCLEMIND_API_KEY` environment variable, and the client will automatically use it.
|
|
50
50
|
|
|
51
51
|
```bash
|
|
52
|
-
export
|
|
52
|
+
export CIRCLEMIND_API_KEY="YOUR_API_KEY"
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
```python
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
smooth/__init__.py,sha256=cAEweO-FSsk9eIAp_068Gm1s8FdylhRKV9W707kNX88,15745
|
|
2
|
+
smooth_py-0.1.1.post0.dist-info/METADATA,sha256=1FsW9jkuCBaE085DcMd0PzYE-fM7mLXx8i0JxQzWC8Y,4645
|
|
3
|
+
smooth_py-0.1.1.post0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
4
|
+
smooth_py-0.1.1.post0.dist-info/RECORD,,
|
smooth_py-0.1.0.dist-info/RECORD
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
smooth/__init__.py,sha256=nC4DAi-hkJzENxQBdJMQRoCn_dEm_OruxxMmHewmMqc,15134
|
|
2
|
-
smooth_py-0.1.0.dist-info/METADATA,sha256=jls-c0VkH0qSMgenpK1qpX1ZrGgYTG4e4eddvjMgKeI,4633
|
|
3
|
-
smooth_py-0.1.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
4
|
-
smooth_py-0.1.0.dist-info/RECORD,,
|
|
File without changes
|