wexa-sdk 0.1.0__tar.gz → 0.1.1__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 wexa-sdk might be problematic. Click here for more details.
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/PKG-INFO +1 -1
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/pyproject.toml +2 -2
- wexa_sdk-0.1.1/wexa_sdk/core/__init__.py +1 -0
- wexa_sdk-0.1.1/wexa_sdk/core/http.py +86 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk.egg-info/PKG-INFO +1 -1
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk.egg-info/SOURCES.txt +2 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/README.md +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/setup.cfg +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk/__init__.py +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk/agentflows.py +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk/analytics.py +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk/connectors/__init__.py +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk/connectors/core.py +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk/connectors/google_drive.py +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk/connectors_mgmt.py +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk/executions.py +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk/files.py +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk/inbox.py +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk/marketplace.py +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk/models/__init__.py +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk/project_members.py +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk/projects.py +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk/settings.py +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk/skills.py +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk/tables.py +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk/tasks.py +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk.egg-info/dependency_links.txt +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk.egg-info/requires.txt +0 -0
- {wexa_sdk-0.1.0 → wexa_sdk-0.1.1}/wexa_sdk.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "wexa-sdk"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.1"
|
|
8
8
|
description = "Official Wexa Python SDK"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -25,5 +25,5 @@ dependencies = [
|
|
|
25
25
|
Homepage = "https://github.com/wexa-ai/wexa-sdk"
|
|
26
26
|
|
|
27
27
|
[tool.setuptools]
|
|
28
|
-
packages = ["wexa_sdk", "wexa_sdk.connectors", "wexa_sdk.models"]
|
|
28
|
+
packages = ["wexa_sdk", "wexa_sdk.core", "wexa_sdk.connectors", "wexa_sdk.models"]
|
|
29
29
|
include-package-data = true
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .http import HttpClient, ApiError
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import json
|
|
3
|
+
import time
|
|
4
|
+
from typing import Any, Dict, Optional
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
|
|
8
|
+
RETRY_STATUS = {429, 500, 502, 503, 504}
|
|
9
|
+
|
|
10
|
+
class ApiError(Exception):
|
|
11
|
+
def __init__(self, status: int, detail: Optional[str] = None, code: Optional[str] = None, request_id: Optional[str] = None, raw: Any = None):
|
|
12
|
+
super().__init__(detail or f"API Error {status}")
|
|
13
|
+
self.status = status
|
|
14
|
+
self.code = code
|
|
15
|
+
self.detail = detail
|
|
16
|
+
self.request_id = request_id
|
|
17
|
+
self.raw = raw
|
|
18
|
+
|
|
19
|
+
class HttpClient:
|
|
20
|
+
def __init__(self, base_url: str, api_key: str, user_agent: Optional[str] = None, timeout: Optional[dict] = None, retries: Optional[dict] = None):
|
|
21
|
+
self.base_url = base_url.rstrip("/")
|
|
22
|
+
self.api_key = api_key
|
|
23
|
+
self.user_agent = user_agent
|
|
24
|
+
self.timeout = {
|
|
25
|
+
"connectTimeoutMs": (timeout or {}).get("connectTimeoutMs", 5000),
|
|
26
|
+
"readTimeoutMs": (timeout or {}).get("readTimeoutMs", 30000),
|
|
27
|
+
}
|
|
28
|
+
self.retries = {
|
|
29
|
+
"attempts": (retries or {}).get("attempts", 3),
|
|
30
|
+
"baseDelayMs": (retries or {}).get("baseDelayMs", 500),
|
|
31
|
+
"maxDelayMs": (retries or {}).get("maxDelayMs", 30000),
|
|
32
|
+
}
|
|
33
|
+
self._client = httpx.Client(timeout=self.timeout["readTimeoutMs"] / 1000)
|
|
34
|
+
|
|
35
|
+
def request(self, method: str, path: str, *, params: Optional[Dict[str, Any]] = None, json: Any = None, headers: Optional[Dict[str, str]] = None):
|
|
36
|
+
url = f"{self.base_url}{path}"
|
|
37
|
+
hdrs = {
|
|
38
|
+
"content-type": "application/json",
|
|
39
|
+
"x-api-key": self.api_key,
|
|
40
|
+
"X-Wexa-SDK-Version": "py/0.1.0",
|
|
41
|
+
}
|
|
42
|
+
if self.user_agent:
|
|
43
|
+
hdrs["User-Agent"] = self.user_agent
|
|
44
|
+
if headers:
|
|
45
|
+
hdrs.update(headers)
|
|
46
|
+
|
|
47
|
+
req_id = headers.get("x-client-request-id") if headers else None
|
|
48
|
+
if not req_id:
|
|
49
|
+
req_id = str(int(time.time() * 1000))
|
|
50
|
+
hdrs["x-client-request-id"] = req_id
|
|
51
|
+
|
|
52
|
+
attempt = 0
|
|
53
|
+
last_err: Optional[Exception] = None
|
|
54
|
+
while attempt < self.retries["attempts"]:
|
|
55
|
+
try:
|
|
56
|
+
resp = self._client.request(method, url, params=params, json=json, headers=hdrs)
|
|
57
|
+
res_req_id = resp.headers.get("x-request-id") or req_id
|
|
58
|
+
text = resp.text
|
|
59
|
+
try:
|
|
60
|
+
data = resp.json() if text else None
|
|
61
|
+
except Exception:
|
|
62
|
+
data = text
|
|
63
|
+
if not resp.is_success:
|
|
64
|
+
detail = (isinstance(data, dict) and (data.get("detail") or data.get("error") or data.get("message"))) or text or f"HTTP {resp.status_code}"
|
|
65
|
+
if resp.status_code in RETRY_STATUS and attempt < self.retries["attempts"] - 1:
|
|
66
|
+
time.sleep(self._backoff(attempt) / 1000)
|
|
67
|
+
attempt += 1
|
|
68
|
+
continue
|
|
69
|
+
raise ApiError(status=resp.status_code, detail=detail, request_id=res_req_id, raw=data)
|
|
70
|
+
return data
|
|
71
|
+
except ApiError:
|
|
72
|
+
raise
|
|
73
|
+
except Exception as e: # network error
|
|
74
|
+
last_err = e
|
|
75
|
+
if attempt < self.retries["attempts"] - 1:
|
|
76
|
+
time.sleep(self._backoff(attempt) / 1000)
|
|
77
|
+
attempt += 1
|
|
78
|
+
continue
|
|
79
|
+
raise ApiError(status=0, detail=str(e), request_id=req_id, raw=e)
|
|
80
|
+
raise last_err # type: ignore
|
|
81
|
+
|
|
82
|
+
def _backoff(self, attempt: int) -> int:
|
|
83
|
+
import random
|
|
84
|
+
jitter = random.random() * 0.2 + 0.9
|
|
85
|
+
delay = min(self.retries["maxDelayMs"], int(self.retries["baseDelayMs"] * (2 ** attempt)))
|
|
86
|
+
return int(delay * jitter)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|