wexa-sdk 0.1.0__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.

@@ -0,0 +1,23 @@
1
+ Metadata-Version: 2.4
2
+ Name: wexa-sdk
3
+ Version: 0.1.0
4
+ Summary: Official Wexa Python SDK
5
+ Author: Wexa
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/wexa-ai/wexa-sdk
8
+ Keywords: wexa,sdk,api
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python :: 3 :: Only
12
+ Requires-Python: >=3.9
13
+ Description-Content-Type: text/markdown
14
+ Requires-Dist: httpx>=0.27
15
+ Requires-Dist: pydantic>=2.6
16
+
17
+ # wexa-sdk (Python)
18
+
19
+ Python SDK for Wexa API.
20
+
21
+ ```python
22
+ from wexa_sdk import WexaClient
23
+ ```
@@ -0,0 +1,7 @@
1
+ # wexa-sdk (Python)
2
+
3
+ Python SDK for Wexa API.
4
+
5
+ ```python
6
+ from wexa_sdk import WexaClient
7
+ ```
@@ -0,0 +1,29 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "wexa-sdk"
7
+ version = "0.1.0"
8
+ description = "Official Wexa Python SDK"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "Apache-2.0" }
12
+ keywords = ["wexa", "sdk", "api"]
13
+ authors = [{ name = "Wexa" }]
14
+ classifiers = [
15
+ "Programming Language :: Python :: 3",
16
+ "License :: OSI Approved :: Apache Software License",
17
+ "Programming Language :: Python :: 3 :: Only",
18
+ ]
19
+ dependencies = [
20
+ "httpx>=0.27",
21
+ "pydantic>=2.6",
22
+ ]
23
+
24
+ [project.urls]
25
+ Homepage = "https://github.com/wexa-ai/wexa-sdk"
26
+
27
+ [tool.setuptools]
28
+ packages = ["wexa_sdk", "wexa_sdk.connectors", "wexa_sdk.models"]
29
+ include-package-data = true
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,37 @@
1
+ from .core.http import HttpClient
2
+ from .agentflows import AgentFlows
3
+ from .executions import Executions
4
+ from .tables import Tables
5
+ from .connectors.core import Connectors
6
+ from .projects import Projects
7
+ from .skills import Skills
8
+ from .tasks import Tasks
9
+ from .inbox import Inbox
10
+ from .settings import Settings
11
+ from .marketplace import Marketplace
12
+ from .analytics import Analytics
13
+ from .project_members import ProjectMembers
14
+ from .connectors_mgmt import ConnectorsMgmt
15
+ from .files import Files
16
+
17
+ class WexaClient:
18
+ def __init__(self, base_url: str, api_key: str, user_agent: str | None = None, timeout: dict | None = None, retries: dict | None = None, polling: dict | None = None):
19
+ self.http = HttpClient(base_url=base_url, api_key=api_key, user_agent=user_agent, timeout=timeout, retries=retries)
20
+ self.agentflows = AgentFlows(self.http)
21
+ self.executions = Executions(self.http, polling or {})
22
+ self.tables = Tables(self.http)
23
+ self.connectors = Connectors(self.http)
24
+ self.projects = Projects(self.http)
25
+ self.skills = Skills(self.http)
26
+ self.tasks = Tasks(self.http)
27
+ self.inbox = Inbox(self.http)
28
+ self.settings = Settings(self.http)
29
+ self.marketplace = Marketplace(self.http)
30
+ self.analytics = Analytics(self.http)
31
+ self.project_members = ProjectMembers(self.http)
32
+ self.connectors_mgmt = ConnectorsMgmt(self.http)
33
+ self.files = Files(self.http)
34
+
35
+ def _action(self, *args, **kwargs):
36
+ # Kept for backward compatibility; delegate to connectors.action
37
+ return self.connectors.action(*args, **kwargs)
@@ -0,0 +1,37 @@
1
+ from .core.http import HttpClient
2
+
3
+ class AgentFlows:
4
+ def __init__(self, http: HttpClient):
5
+ self.http = http
6
+
7
+ def list(
8
+ self,
9
+ project_id: str | None = None,
10
+ projectID: str | None = None,
11
+ skip: int | None = None,
12
+ limit: int | None = None,
13
+ ):
14
+ # API expects 'projectID' (capital D); accept both and normalize
15
+ pid = projectID or project_id
16
+ params: dict | None = None
17
+ if pid is not None or skip is not None or limit is not None:
18
+ params = {}
19
+ if pid is not None:
20
+ params["projectID"] = pid
21
+ if skip is not None:
22
+ params["skip"] = skip
23
+ if limit is not None:
24
+ params["limit"] = limit
25
+ return self.http.request("GET", "/agentflows", params=params)
26
+
27
+ def get(self, id: str):
28
+ return self.http.request("GET", f"/agentflow/{id}")
29
+
30
+ def create(self, body: dict):
31
+ return self.http.request("POST", "/agentflow/", json=body)
32
+
33
+ def update(self, id: str, body: dict):
34
+ return self.http.request("PUT", f"/agentflow/{id}", json=body)
35
+
36
+ def delete(self, project_id: str, id: str):
37
+ return self.http.request("DELETE", f"/agentflow/{project_id}/{id}")
@@ -0,0 +1,12 @@
1
+ from __future__ import annotations
2
+ from typing import Any
3
+
4
+ from .core.http import HttpClient
5
+
6
+ class Analytics:
7
+ def __init__(self, http: HttpClient):
8
+ self.http = http
9
+
10
+ # GET /analytics?projectID=...
11
+ def get(self, project_id: str) -> Any:
12
+ return self.http.request("GET", "/analytics", params={"projectID": project_id})
@@ -0,0 +1 @@
1
+ from .google_drive import GoogleDrive # re-export
@@ -0,0 +1,24 @@
1
+ from __future__ import annotations
2
+ from typing import Any, Optional
3
+
4
+ from ..core.http import HttpClient
5
+ from .google_drive import GoogleDrive
6
+
7
+ class Connectors:
8
+ def __init__(self, http: HttpClient):
9
+ self.http = http
10
+ self.google_drive = GoogleDrive(http)
11
+
12
+ # POST /actions/{CATEGORY}/{ACTION}/{connector_id?}
13
+ def action(self, category: str, action: str, connector_id: Optional[str] = None, *, body: Optional[dict] = None, projectID: Optional[str] = None) -> Any:
14
+ path = f"/actions/{category}/{action}/{connector_id}" if connector_id else f"/actions/{category}/{action}"
15
+ params = {"projectID": projectID} if projectID else None
16
+ return self.http.request("POST", path, params=params, json=body)
17
+
18
+ # POST /actions/{CATEGORY}/config?projectID=...
19
+ def set_config(self, category: str, project_id: str, body: dict) -> Any:
20
+ return self.http.request("POST", f"/actions/{category}/config", params={"projectID": project_id}, json=body)
21
+
22
+ # GET /actions/{CATEGORY}/config/{projectID}
23
+ def get_config(self, category: str, project_id: str) -> Any:
24
+ return self.http.request("GET", f"/actions/{category}/config/{project_id}")
@@ -0,0 +1,22 @@
1
+ from __future__ import annotations
2
+ from typing import Any, Dict, Optional
3
+
4
+ from ..core.http import HttpClient
5
+
6
+ class GoogleDrive:
7
+ def __init__(self, http: HttpClient):
8
+ self.http = http
9
+
10
+ def list_files(self, connector_id: str, *, folder_id: str, page_size: Optional[int] = None, page_token: Optional[str] = None, fetch_all: Optional[bool] = None):
11
+ body: Dict[str, Any] = {"folder_id": folder_id}
12
+ if page_size is not None:
13
+ body["page_size"] = page_size
14
+ if page_token is not None:
15
+ body["page_token"] = page_token
16
+ if fetch_all is not None:
17
+ body["fetch_all"] = fetch_all
18
+ return self.http.request("POST", f"/actions/google_drive/list_files/{connector_id}", json=body)
19
+
20
+ def read(self, connector_id: str, *, file_id: str):
21
+ body = {"file_id": file_id}
22
+ return self.http.request("POST", f"/actions/google_drive/read/{connector_id}", json=body)
@@ -0,0 +1,47 @@
1
+ from __future__ import annotations
2
+ from typing import Any, Optional
3
+
4
+ from .core.http import HttpClient
5
+
6
+ class ConnectorsMgmt:
7
+ def __init__(self, http: HttpClient):
8
+ self.http = http
9
+
10
+ # GET /connectors/?projectID=...
11
+ def list(self, project_id: Optional[str] = None) -> Any:
12
+ params = {"projectID": project_id} if project_id else None
13
+ return self.http.request("GET", "/connectors/", params=params)
14
+
15
+ # GET /connectors/{projectID}
16
+ def list_by_project_id(self, project_id: str) -> Any:
17
+ return self.http.request("GET", f"/connectors/{project_id}")
18
+
19
+ # GET /v1/connector/{id}
20
+ def get_by_id(self, connector_id: str) -> Any:
21
+ return self.http.request("GET", f"/v1/connector/{connector_id}")
22
+
23
+ # GET /connector/{connector_id}
24
+ def get_by_id_path(self, connector_id: str) -> Any:
25
+ return self.http.request("GET", f"/connector/{connector_id}")
26
+
27
+ # DELETE /v1/connector/{id}?projectID=...
28
+ def delete(self, connector_id: str, *, project_id: Optional[str] = None) -> Any:
29
+ params = {"projectID": project_id} if project_id else None
30
+ return self.http.request("DELETE", f"/v1/connector/{connector_id}", params=params)
31
+
32
+ # DELETE /connector/{connector_id}?projectID=...
33
+ def delete_by_id_path(self, connector_id: str, *, project_id: str) -> Any:
34
+ return self.http.request("DELETE", f"/connector/{connector_id}", params={"projectID": project_id})
35
+
36
+ # POST /connectors/change_status
37
+ def update_status(self, *, new_status: str, connectorID: str, data_loader_config: dict) -> Any:
38
+ body = {"new_status": new_status, "connectorID": connectorID, "data_loader_config": data_loader_config}
39
+ return self.http.request("POST", "/connectors/change_status", json=body)
40
+
41
+ # GET /connectors/trigger_actions?projectID=...
42
+ def list_trigger_actions(self, project_id: str) -> Any:
43
+ return self.http.request("GET", "/connectors/trigger_actions", params={"projectID": project_id})
44
+
45
+ # GET /connectors/{projectID}/trigger_actions
46
+ def list_trigger_actions_by_project(self, project_id: str) -> Any:
47
+ return self.http.request("GET", f"/connectors/{project_id}/trigger_actions", params={"projectID": project_id})
@@ -0,0 +1,57 @@
1
+ from __future__ import annotations
2
+ import time
3
+ from typing import Any, Callable, Optional
4
+
5
+ from .core.http import HttpClient
6
+
7
+ DEFAULT_TERMINAL = {"completed", "failed", "canceled"}
8
+
9
+ class Executions:
10
+ def __init__(self, http: HttpClient, polling: Optional[dict] = None):
11
+ self.http = http
12
+ self.polling = polling or {}
13
+
14
+ def start(self, payload: dict, *, projectID: Optional[str] = None):
15
+ params = {"projectID": projectID} if projectID else None
16
+ return self.http.request("POST", "/execute_flow", json=payload, params=params)
17
+
18
+ def get(self, execution_id: str):
19
+ return self.http.request("GET", f"/execute_flow/{execution_id}")
20
+
21
+ def monitor(self, agentflow_id: str):
22
+ return self.http.request("GET", f"/execute_flow/{agentflow_id}/monitor")
23
+
24
+ def pause(self, execution_id: str):
25
+ return self.http.request("POST", f"/execute_flow/{execution_id}/pause")
26
+
27
+ def resume(self, execution_id: str):
28
+ return self.http.request("POST", f"/execute_flow/{execution_id}/resume")
29
+
30
+ def cancel(self, execution_id: str):
31
+ return self.http.request("POST", f"/execute_flow/{execution_id}/cancel")
32
+
33
+ def approve_preview(self, execution_id: str):
34
+ return self.http.request("PUT", f"/execute_flow/{execution_id}/approve_preview")
35
+
36
+ def approve_anomaly(self, execution_id: str):
37
+ return self.http.request("PUT", f"/execute_flow/{execution_id}/approve_anomaly")
38
+
39
+ def update_runtime_input(self, execution_id: str, body: dict):
40
+ return self.http.request("PUT", f"/execute_flow/{execution_id}/runtime_input", json=body)
41
+
42
+ def wait(self, execution_id: str, *, interval_ms: Optional[int] = None, timeout_ms: Optional[int] = None, is_terminal: Optional[Callable[[str], bool]] = None):
43
+ interval = interval_ms or self.polling.get("intervalMs", 2000)
44
+ timeout = timeout_ms or self.polling.get("timeoutMs", 30 * 60 * 1000)
45
+ jitter = self.polling.get("jitter", 0.2)
46
+ term = is_terminal or (lambda s: (s or "").lower() in DEFAULT_TERMINAL)
47
+
48
+ start = time.time()
49
+ while True:
50
+ info = self.get(execution_id)
51
+ status = (info.get("status") or info.get("state") or "").lower()
52
+ if term(status):
53
+ return info
54
+ if (time.time() - start) * 1000 > timeout:
55
+ raise TimeoutError("Execution wait timeout")
56
+ j = 1 + ((2 * (time.time() % 1) - 1) * jitter)
57
+ time.sleep(max(0.2, (interval * j) / 1000))
@@ -0,0 +1,23 @@
1
+ from __future__ import annotations
2
+ from typing import Any, Dict, Optional
3
+
4
+ from .core.http import HttpClient
5
+
6
+ class Files:
7
+ def __init__(self, http: HttpClient):
8
+ self.http = http
9
+
10
+ # POST /files/upload?projectID=...&container_name=...
11
+ # body example: { "filenames": ["file.pdf"], "tags": ["resume"], "source_type": "STORAGE", "org_id": "..." }
12
+ def upload_request(self, project_id: str, container_name: str, body: Dict[str, Any]):
13
+ params: Dict[str, Any] = {"projectID": project_id, "container_name": container_name}
14
+ return self.http.request("POST", "/files/upload", params=params, json=body)
15
+
16
+ # GET /file/{fileId}/?projectID=...
17
+ def get_by_file_id(self, file_id: str, project_id: Optional[str] = None):
18
+ params = {"projectID": project_id} if project_id else None
19
+ return self.http.request("GET", f"/file/{file_id}/", params=params)
20
+
21
+ # GET /files/{connectorId}/connector/
22
+ def list_by_connector(self, connector_id: str):
23
+ return self.http.request("GET", f"/files/{connector_id}/connector/")
@@ -0,0 +1,41 @@
1
+ from __future__ import annotations
2
+ from typing import Any, Dict, Optional
3
+
4
+ from .core.http import HttpClient
5
+
6
+ class Inbox:
7
+ def __init__(self, http: HttpClient):
8
+ self.http = http
9
+
10
+ # POST /inbox/create
11
+ def create(self, body: Dict[str, Any]):
12
+ return self.http.request("POST", "/inbox/create", json=body)
13
+
14
+ # GET /inbox?projectID=...&limit=...
15
+ def list(self, project_id: str, *, limit: Optional[int] = None):
16
+ params: Dict[str, Any] = {"projectID": project_id}
17
+ if limit is not None:
18
+ params["limit"] = limit
19
+ return self.http.request("GET", "/inbox", params=params)
20
+
21
+ # POST /inbox/update/runtime_input/?projectID=...
22
+ def update_runtime(self, project_id: str, body: Dict[str, Any]):
23
+ return self.http.request("POST", "/inbox/update/runtime_input/", params={"projectID": project_id}, json=body)
24
+
25
+ # POST /inbox/update/anomaly_detection/?projectID=...
26
+ def update_anomaly(self, project_id: str, body: Dict[str, Any]):
27
+ return self.http.request("POST", "/inbox/update/anomaly_detection/", params={"projectID": project_id}, json=body)
28
+
29
+ # POST /inbox/update/preview/?projectID=...
30
+ def update_preview(self, project_id: str, body: Dict[str, Any]):
31
+ return self.http.request("POST", "/inbox/update/preview/", params={"projectID": project_id}, json=body)
32
+
33
+ # POST /inbox/update/preview/{execution_id}?projectID=...
34
+ def update_preview_by_execution(self, execution_id: str, body: Dict[str, Any], project_id: Optional[str] = None):
35
+ params = {"projectID": project_id} if project_id else None
36
+ return self.http.request("POST", f"/inbox/update/preview/{execution_id}", params=params, json=body)
37
+
38
+ # GET /inbox/{id}?projectID=...
39
+ def get(self, inbox_id: str, project_id: Optional[str] = None):
40
+ params = {"projectID": project_id} if project_id else None
41
+ return self.http.request("GET", f"/inbox/{inbox_id}", params=params)
@@ -0,0 +1,31 @@
1
+ from __future__ import annotations
2
+ from typing import Any, Dict
3
+
4
+ from .core.http import HttpClient
5
+
6
+ class Marketplace:
7
+ def __init__(self, http: HttpClient):
8
+ self.http = http
9
+
10
+ # GET /public/connectors/all?search_key=...&projectID=...&filter_type=...
11
+ def list_connectors(self, *, search_key: str, projectID: str, filter_type: str):
12
+ params: Dict[str, Any] = {"search_key": search_key, "projectID": projectID, "filter_type": filter_type}
13
+ return self.http.request("GET", "/public/connectors/all", params=params)
14
+
15
+ # GET /public/marketplace/coworkers?search_key=...&limit=...
16
+ def list_coworkers(self, *, search_key: str, limit: int | str):
17
+ params: Dict[str, Any] = {"search_key": search_key, "limit": limit}
18
+ return self.http.request("GET", "/public/marketplace/coworkers", params=params)
19
+
20
+ # GET /public/marketplace/coworker/{coworker_id}
21
+ def get_coworker_by_id(self, coworker_id: str):
22
+ return self.http.request("GET", f"/public/marketplace/coworker/{coworker_id}")
23
+
24
+ # POST /marketplace/coworker/{coworker_id}/purchase?organization_id=...
25
+ def purchase_coworker(self, coworker_id: str, *, organization_id: str, body: Dict[str, Any] | None = None):
26
+ params = {"organization_id": organization_id}
27
+ return self.http.request("POST", f"/marketplace/coworker/{coworker_id}/purchase", params=params, json=(body or {}))
28
+
29
+ # GET /marketplace/coworker/update/{coworker_id}/check
30
+ def check_coworker_update(self, coworker_id: str):
31
+ return self.http.request("GET", f"/marketplace/coworker/update/{coworker_id}/check")
@@ -0,0 +1 @@
1
+ # Placeholder for pydantic models (to be added as API payloads stabilize).
@@ -0,0 +1,16 @@
1
+ from __future__ import annotations
2
+ from typing import Any
3
+
4
+ from .core.http import HttpClient
5
+
6
+ class ProjectMembers:
7
+ def __init__(self, http: HttpClient):
8
+ self.http = http
9
+
10
+ # GET /project-member/{projectID}/summary
11
+ def summary(self, project_id: str) -> Any:
12
+ return self.http.request("GET", f"/project-member/{project_id}/summary")
13
+
14
+ # GET /project-member/{projectID}
15
+ def list(self, project_id: str) -> Any:
16
+ return self.http.request("GET", f"/project-member/{project_id}")
@@ -0,0 +1,33 @@
1
+ from __future__ import annotations
2
+ from typing import Optional, Dict, Any
3
+
4
+ from .core.http import HttpClient
5
+
6
+ class Projects:
7
+ def __init__(self, http: HttpClient):
8
+ self.http = http
9
+
10
+ # Per developers.wexa.ai: POST https://api.wexa.ai/v1/project
11
+ def create(self, body: Dict[str, Any]):
12
+ """
13
+ Expected body (example):
14
+ {
15
+ "orgId": "67fdea40aac77be632954f0f",
16
+ "projectName": "New",
17
+ "description": "yoooo",
18
+ "coworker_role": "testrole"
19
+ }
20
+ """
21
+ return self.http.request("POST", "/v1/project", json=body)
22
+
23
+ def list(self):
24
+ return self.http.request("GET", "/v1/project")
25
+
26
+ def get(self, project_id: str):
27
+ return self.http.request("GET", f"/v1/project/{project_id}")
28
+
29
+ def update(self, project_id: str, body: Dict[str, Any]):
30
+ return self.http.request("PUT", f"/v1/project/{project_id}", json=body)
31
+
32
+ def delete(self, project_id: str):
33
+ return self.http.request("DELETE", f"/v1/project/{project_id}")
@@ -0,0 +1,11 @@
1
+ from __future__ import annotations
2
+
3
+ from .core.http import HttpClient
4
+
5
+ class Settings:
6
+ def __init__(self, http: HttpClient):
7
+ self.http = http
8
+
9
+ # GET /settings/{projectID}
10
+ def get(self, project_id: str):
11
+ return self.http.request("GET", f"/settings/{project_id}")
@@ -0,0 +1,35 @@
1
+ from __future__ import annotations
2
+ from typing import Any, Dict, Optional
3
+
4
+ from .core.http import HttpClient
5
+
6
+ class Skills:
7
+ def __init__(self, http: HttpClient):
8
+ self.http = http
9
+
10
+ # POST /skills/
11
+ def create(self, body: Dict[str, Any]):
12
+ return self.http.request("POST", "/skills/", json=body)
13
+
14
+ # GET /skills/?projectID=...&limit=...
15
+ def list(self, project_id: str, *, limit: Optional[int] = None):
16
+ params: Dict[str, Any] = {"projectID": project_id}
17
+ if limit is not None:
18
+ params["limit"] = limit
19
+ return self.http.request("GET", "/skills/", params=params)
20
+
21
+ # GET /skills/category?projectId=...&category=...&limit=...
22
+ def list_by_category(self, project_id: str, category: str, *, limit: Optional[int] = None):
23
+ params: Dict[str, Any] = {"projectId": project_id, "category": category}
24
+ if limit is not None:
25
+ params["limit"] = limit
26
+ return self.http.request("GET", "/skills/category", params=params)
27
+
28
+ # GET /skills/{id}
29
+ def get_by_id(self, skill_id: str):
30
+ return self.http.request("GET", f"/skills/{skill_id}")
31
+
32
+ # GET /skills/?name=...&projectID=...
33
+ def get_by_name(self, name: str, project_id: str):
34
+ params = {"name": name, "projectID": project_id}
35
+ return self.http.request("GET", "/skills/", params=params)
@@ -0,0 +1,59 @@
1
+ from __future__ import annotations
2
+ from typing import Any, Optional
3
+
4
+ from .core.http import HttpClient
5
+
6
+ class Tables:
7
+ def __init__(self, http: HttpClient):
8
+ self.http = http
9
+
10
+ # Tables
11
+ def create_table(self, project_id: str, spec: dict):
12
+ # API expects projectID as query param and in body with 'projectID' casing
13
+ params = {"projectID": project_id}
14
+ body = {"projectID": project_id, **spec}
15
+ return self.http.request("POST", "/create/table", params=params, json=body)
16
+
17
+ def list_tables(self, project_id: str):
18
+ return self.http.request("GET", f"/storage/{project_id}")
19
+
20
+ def get_table(self, project_id: str, table_id: str):
21
+ return self.http.request("GET", f"/storage/{project_id}/{table_id}")
22
+
23
+ def get_table_view(self, table_id: str):
24
+ return self.http.request("GET", f"/table/view/{table_id}")
25
+
26
+ def rename_table(self, project_id: str, table_id: str, new_name: str):
27
+ return self.http.request("POST", f"/table/rename/{project_id}", json={"tableId": table_id, "newName": new_name})
28
+
29
+ # Columns
30
+ def get_columns(self, project_id: str, table_id: str):
31
+ return self.http.request("GET", f"/column/storage/{project_id}/{table_id}")
32
+
33
+ def edit_columns(self, table_id: str, spec: dict):
34
+ return self.http.request("POST", f"/edit/columns/{table_id}", json=spec)
35
+
36
+ def delete_column(self, project_id: str, column_id: str):
37
+ return self.http.request("DELETE", f"/delete/column/{project_id}", json={"columnId": column_id})
38
+
39
+ # Records
40
+ def create_record(self, project_id: str, table_id: str, record: dict):
41
+ return self.http.request("POST", f"/storage/{project_id}/{table_id}", json=record)
42
+
43
+ def get_record(self, project_id: str, table_id: str, record_id: str):
44
+ return self.http.request("GET", f"/storage/{project_id}/{table_id}/{record_id}")
45
+
46
+ def update_record(self, project_id: str, table_id: str, record_id: str, record: dict):
47
+ return self.http.request("PUT", f"/storage/{project_id}/{table_id}/{record_id}", json=record)
48
+
49
+ def delete_record(self, project_id: str, table_id: str, record_id: str):
50
+ return self.http.request("DELETE", f"/storage/{project_id}/{table_id}/{record_id}")
51
+
52
+ def list_records(self, project_id: str, table_id: str, query: Optional[dict] = None):
53
+ return self.http.request("GET", f"/storage/{project_id}/{table_id}", params=query)
54
+
55
+ def bulk_upsert(self, project_id: str, table_id: str, records: list[dict]):
56
+ return self.http.request("POST", f"/bulk/storage/{project_id}/{table_id}", json={"records": records})
57
+
58
+ def export(self, project_id: str, table_id: str):
59
+ return self.http.request("GET", f"/table_data/storage/{table_id}/export")
@@ -0,0 +1,36 @@
1
+ from __future__ import annotations
2
+ from typing import Any, Dict, Optional
3
+
4
+ from .core.http import HttpClient
5
+
6
+ class Tasks:
7
+ def __init__(self, http: HttpClient):
8
+ self.http = http
9
+
10
+ # GET /tasks/?projectID=...&limit=...&skip=...&created_by=...
11
+ def list(self, project_id: str, *, limit: Optional[int] = None, skip: Optional[int] = None, created_by: Optional[str] = None):
12
+ params: Dict[str, Any] = {"projectID": project_id}
13
+ if limit is not None:
14
+ params["limit"] = limit
15
+ if skip is not None:
16
+ params["skip"] = skip
17
+ if created_by:
18
+ params["created_by"] = created_by
19
+ return self.http.request("GET", "/tasks/", params=params)
20
+
21
+ # GET /task/{id}?projectID=...
22
+ def get(self, task_id: str, project_id: Optional[str] = None):
23
+ params = {"projectID": project_id} if project_id else None
24
+ return self.http.request("GET", f"/task/{task_id}", params=params)
25
+
26
+ # POST /task/{id}/pause
27
+ def pause(self, task_id: str):
28
+ return self.http.request("POST", f"/task/{task_id}/pause")
29
+
30
+ # POST /task/{id}/resume
31
+ def resume(self, task_id: str):
32
+ return self.http.request("POST", f"/task/{task_id}/resume")
33
+
34
+ # POST /task/{id}/stop
35
+ def stop(self, task_id: str):
36
+ return self.http.request("POST", f"/task/{task_id}/stop")
@@ -0,0 +1,23 @@
1
+ Metadata-Version: 2.4
2
+ Name: wexa-sdk
3
+ Version: 0.1.0
4
+ Summary: Official Wexa Python SDK
5
+ Author: Wexa
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/wexa-ai/wexa-sdk
8
+ Keywords: wexa,sdk,api
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python :: 3 :: Only
12
+ Requires-Python: >=3.9
13
+ Description-Content-Type: text/markdown
14
+ Requires-Dist: httpx>=0.27
15
+ Requires-Dist: pydantic>=2.6
16
+
17
+ # wexa-sdk (Python)
18
+
19
+ Python SDK for Wexa API.
20
+
21
+ ```python
22
+ from wexa_sdk import WexaClient
23
+ ```
@@ -0,0 +1,25 @@
1
+ README.md
2
+ pyproject.toml
3
+ wexa_sdk/__init__.py
4
+ wexa_sdk/agentflows.py
5
+ wexa_sdk/analytics.py
6
+ wexa_sdk/connectors_mgmt.py
7
+ wexa_sdk/executions.py
8
+ wexa_sdk/files.py
9
+ wexa_sdk/inbox.py
10
+ wexa_sdk/marketplace.py
11
+ wexa_sdk/project_members.py
12
+ wexa_sdk/projects.py
13
+ wexa_sdk/settings.py
14
+ wexa_sdk/skills.py
15
+ wexa_sdk/tables.py
16
+ wexa_sdk/tasks.py
17
+ wexa_sdk.egg-info/PKG-INFO
18
+ wexa_sdk.egg-info/SOURCES.txt
19
+ wexa_sdk.egg-info/dependency_links.txt
20
+ wexa_sdk.egg-info/requires.txt
21
+ wexa_sdk.egg-info/top_level.txt
22
+ wexa_sdk/connectors/__init__.py
23
+ wexa_sdk/connectors/core.py
24
+ wexa_sdk/connectors/google_drive.py
25
+ wexa_sdk/models/__init__.py
@@ -0,0 +1,2 @@
1
+ httpx>=0.27
2
+ pydantic>=2.6
@@ -0,0 +1 @@
1
+ wexa_sdk