wexa-sdk 0.1.2__py3-none-any.whl → 0.1.11__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.
- wexa_sdk/__init__.py +4 -0
- wexa_sdk/agentflows.py +65 -0
- wexa_sdk/connectors/core.py +31 -3
- wexa_sdk/core/http.py +1 -1
- wexa_sdk/executions.py +25 -25
- wexa_sdk/files.py +3 -3
- wexa_sdk/inbox.py +80 -16
- wexa_sdk/llm.py +46 -0
- wexa_sdk/projects.py +48 -7
- wexa_sdk/schedules.py +81 -0
- wexa_sdk/tables.py +105 -4
- wexa_sdk/tasks.py +3 -2
- {wexa_sdk-0.1.2.dist-info → wexa_sdk-0.1.11.dist-info}/METADATA +1 -1
- wexa_sdk-0.1.11.dist-info/RECORD +26 -0
- wexa_sdk-0.1.2.dist-info/RECORD +0 -24
- {wexa_sdk-0.1.2.dist-info → wexa_sdk-0.1.11.dist-info}/WHEEL +0 -0
- {wexa_sdk-0.1.2.dist-info → wexa_sdk-0.1.11.dist-info}/top_level.txt +0 -0
wexa_sdk/__init__.py
CHANGED
|
@@ -13,6 +13,8 @@ from .analytics import Analytics
|
|
|
13
13
|
from .project_members import ProjectMembers
|
|
14
14
|
from .connectors_mgmt import ConnectorsMgmt
|
|
15
15
|
from .files import Files
|
|
16
|
+
from .llm import Llm
|
|
17
|
+
from .schedules import Schedules
|
|
16
18
|
|
|
17
19
|
class WexaClient:
|
|
18
20
|
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):
|
|
@@ -31,6 +33,8 @@ class WexaClient:
|
|
|
31
33
|
self.project_members = ProjectMembers(self.http)
|
|
32
34
|
self.connectors_mgmt = ConnectorsMgmt(self.http)
|
|
33
35
|
self.files = Files(self.http)
|
|
36
|
+
self.llm = Llm(self.http)
|
|
37
|
+
self.schedules = Schedules(self.http)
|
|
34
38
|
|
|
35
39
|
def _action(self, *args, **kwargs):
|
|
36
40
|
# Kept for backward compatibility; delegate to connectors.action
|
wexa_sdk/agentflows.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
from typing import Optional, TypedDict
|
|
2
3
|
from .core.http import HttpClient
|
|
3
4
|
|
|
@@ -73,3 +74,67 @@ class AgentFlows:
|
|
|
73
74
|
|
|
74
75
|
def update(self, id: str, body: dict):
|
|
75
76
|
return self.http.request("PUT", f"/agentflow/{id}", json=body)
|
|
77
|
+
|
|
78
|
+
def add_skilled_agent(self, agentflow_id: str, *, projectID: str, body: dict):
|
|
79
|
+
"""
|
|
80
|
+
Add a skilled agent to an AgentFlow.
|
|
81
|
+
|
|
82
|
+
POST /agentflow/{agentflow_id}/skilled?projectID=...
|
|
83
|
+
Body: skilled agent configuration (role, title, skills, context, llm, memory, prompt, triggers, etc.)
|
|
84
|
+
"""
|
|
85
|
+
params = {"projectID": projectID}
|
|
86
|
+
return self.http.request("POST", f"/agentflow/{agentflow_id}/skilled", params=params, json=body)
|
|
87
|
+
|
|
88
|
+
def get_by_user_and_project(self, agentflow_id: str, executed_by: str, projectID: str):
|
|
89
|
+
"""
|
|
90
|
+
Get AgentFlow by user and project.
|
|
91
|
+
|
|
92
|
+
GET /agentflow/{agentflow_id}/user/{executed_by}/project/{projectID}
|
|
93
|
+
"""
|
|
94
|
+
return self.http.request("GET", f"/agentflow/{agentflow_id}/user/{executed_by}/project/{projectID}")
|
|
95
|
+
|
|
96
|
+
# Typed body for updating a skilled agent to enable IDE suggestions
|
|
97
|
+
class UpdateSkilledAgentBody(TypedDict, total=False):
|
|
98
|
+
"""Body for updating a skilled agent within an AgentFlow.
|
|
99
|
+
|
|
100
|
+
Required (per API docs):
|
|
101
|
+
- role: str
|
|
102
|
+
- title: str
|
|
103
|
+
- skills: list[str]
|
|
104
|
+
- prompt: { template: str, variables: list, display_template: str }
|
|
105
|
+
- context: list
|
|
106
|
+
- triggers: list
|
|
107
|
+
- llm: { model: str, max_tokens: int, temperature: int }
|
|
108
|
+
- role_description: str
|
|
109
|
+
- memory: { memory_type: str }
|
|
110
|
+
- has_knowledge_base: bool
|
|
111
|
+
- is_user_specific_task: bool
|
|
112
|
+
- is_preview_mode_enabled: bool
|
|
113
|
+
"""
|
|
114
|
+
role: str
|
|
115
|
+
title: str
|
|
116
|
+
skills: list[str]
|
|
117
|
+
prompt: dict
|
|
118
|
+
context: list
|
|
119
|
+
triggers: list
|
|
120
|
+
llm: dict
|
|
121
|
+
role_description: str
|
|
122
|
+
memory: dict
|
|
123
|
+
has_knowledge_base: bool
|
|
124
|
+
is_user_specific_task: bool
|
|
125
|
+
is_preview_mode_enabled: bool
|
|
126
|
+
|
|
127
|
+
def update_skilled_agent(self, agentflow_id: str, agent_id: str, *, projectID: str, body: UpdateSkilledAgentBody | dict):
|
|
128
|
+
"""Update a skilled agent within an AgentFlow.
|
|
129
|
+
|
|
130
|
+
Endpoint: POST /agentflow/{agentflow_id}/update/skilled/{agent_id}?projectID=...
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
agentflow_id: ID of the AgentFlow
|
|
134
|
+
agent_id: ID of the skilled agent inside the AgentFlow
|
|
135
|
+
projectID: Project ID (query param, required)
|
|
136
|
+
body: Update payload, see UpdateSkilledAgentBody for suggested keys
|
|
137
|
+
"""
|
|
138
|
+
params = {"projectID": projectID} if projectID else None
|
|
139
|
+
path = f"/agentflow/{agentflow_id}/update/skilled/{agent_id}"
|
|
140
|
+
return self.http.request("POST", path, params=params, json=body)
|
wexa_sdk/connectors/core.py
CHANGED
|
@@ -1,9 +1,35 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
from typing import Any, Optional
|
|
2
|
+
from typing import Any, Optional, TypedDict
|
|
3
3
|
|
|
4
4
|
from ..core.http import HttpClient
|
|
5
5
|
from .google_drive import GoogleDrive
|
|
6
6
|
|
|
7
|
+
class ConnectorConfigBody(TypedDict, total=False):
|
|
8
|
+
"""JSON body for configuring a connector via POST /actions/{CATEGORY}/config.
|
|
9
|
+
|
|
10
|
+
Required by backend (typical fields):
|
|
11
|
+
- name: str
|
|
12
|
+
- description: str
|
|
13
|
+
- category: str
|
|
14
|
+
- org_id: str
|
|
15
|
+
- projectID: str # NOTE: camelCase as required by backend
|
|
16
|
+
- logo: str
|
|
17
|
+
- ui_form: list
|
|
18
|
+
|
|
19
|
+
Optional/variable:
|
|
20
|
+
- config: dict
|
|
21
|
+
- enabled: bool
|
|
22
|
+
"""
|
|
23
|
+
name: str
|
|
24
|
+
description: str
|
|
25
|
+
category: str
|
|
26
|
+
org_id: str
|
|
27
|
+
projectID: str
|
|
28
|
+
logo: str
|
|
29
|
+
ui_form: list
|
|
30
|
+
config: dict
|
|
31
|
+
enabled: bool
|
|
32
|
+
|
|
7
33
|
class Connectors:
|
|
8
34
|
def __init__(self, http: HttpClient):
|
|
9
35
|
self.http = http
|
|
@@ -16,8 +42,10 @@ class Connectors:
|
|
|
16
42
|
return self.http.request("POST", path, params=params, json=body)
|
|
17
43
|
|
|
18
44
|
# POST /actions/{CATEGORY}/config?projectID=...
|
|
19
|
-
def set_config(self, category: str, project_id: str, body: dict) -> Any:
|
|
20
|
-
|
|
45
|
+
def set_config(self, category: str, project_id: str, body: ConnectorConfigBody | dict) -> Any:
|
|
46
|
+
# Ensure body contains the required camelCase field expected by the backend
|
|
47
|
+
json_body = {**(body or {}), "projectID": project_id}
|
|
48
|
+
return self.http.request("POST", f"/actions/{category}/config", params={"projectID": project_id}, json=json_body)
|
|
21
49
|
|
|
22
50
|
# GET /actions/{CATEGORY}/config/{projectID}
|
|
23
51
|
def get_config(self, category: str, project_id: str) -> Any:
|
wexa_sdk/core/http.py
CHANGED
wexa_sdk/executions.py
CHANGED
|
@@ -12,6 +12,17 @@ class Executions:
|
|
|
12
12
|
self.polling = polling or {}
|
|
13
13
|
|
|
14
14
|
def start(self, payload: dict, *, projectID: Optional[str] = None):
|
|
15
|
+
"""
|
|
16
|
+
Create/Start an execution.
|
|
17
|
+
|
|
18
|
+
POST /execute_flow?projectID=...
|
|
19
|
+
Body requires at least:
|
|
20
|
+
- agentflow_id: str
|
|
21
|
+
- executed_by: str
|
|
22
|
+
- goal: str
|
|
23
|
+
- input_variables: dict
|
|
24
|
+
- projectID: str (backend may also accept via query)
|
|
25
|
+
"""
|
|
15
26
|
params = {"projectID": projectID} if projectID else None
|
|
16
27
|
return self.http.request("POST", "/execute_flow", json=payload, params=params)
|
|
17
28
|
|
|
@@ -30,28 +41,17 @@ class Executions:
|
|
|
30
41
|
def cancel(self, execution_id: str):
|
|
31
42
|
return self.http.request("POST", f"/execute_flow/{execution_id}/cancel")
|
|
32
43
|
|
|
33
|
-
def
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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))
|
|
44
|
+
def execute(self, execution_id: str, *, projectID: str, body: Optional[dict] = None):
|
|
45
|
+
"""
|
|
46
|
+
Execute an existing execution by ID.
|
|
47
|
+
|
|
48
|
+
POST /execute_flow/{execution_id}/execute?projectID=...
|
|
49
|
+
The backend may expect execution_id and/or projectID in the body as well.
|
|
50
|
+
"""
|
|
51
|
+
params = {"projectID": projectID}
|
|
52
|
+
json_body = {"execution_id": execution_id, "projectID": projectID}
|
|
53
|
+
if body:
|
|
54
|
+
json_body.update(body)
|
|
55
|
+
return self.http.request("POST", f"/execute_flow/{execution_id}/execute", params=params, json=json_body)
|
|
56
|
+
|
|
57
|
+
# Removed wait/approve/update-runtime endpoints per request
|
wexa_sdk/files.py
CHANGED
|
@@ -25,6 +25,6 @@ class Files:
|
|
|
25
25
|
params = {"projectID": project_id} if project_id else None
|
|
26
26
|
return self.http.request("GET", f"/file/{file_id}/", params=params)
|
|
27
27
|
|
|
28
|
-
# GET /files/{
|
|
29
|
-
def list_by_connector(self, connector_id: str):
|
|
30
|
-
return self.http.request("GET", f"/files/{
|
|
28
|
+
# GET /files/{projectID}/connector/{connector_id}
|
|
29
|
+
def list_by_connector(self, project_id: str, connector_id: str):
|
|
30
|
+
return self.http.request("GET", f"/files/{project_id}/connector/{connector_id}")
|
wexa_sdk/inbox.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
from typing import Any, Dict, Optional
|
|
2
|
+
from typing import Any, Dict, Optional, TypedDict, Literal
|
|
3
3
|
|
|
4
4
|
from .core.http import HttpClient
|
|
5
5
|
|
|
@@ -7,31 +7,95 @@ class Inbox:
|
|
|
7
7
|
def __init__(self, http: HttpClient):
|
|
8
8
|
self.http = http
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
class InboxCreateBody(TypedDict, total=False):
|
|
11
|
+
_id: str
|
|
12
|
+
type: str
|
|
13
|
+
status: str
|
|
14
|
+
created_at: float
|
|
15
|
+
updated_at: float
|
|
16
|
+
agent_id: str
|
|
17
|
+
coworker_id: str
|
|
18
|
+
coworker_name: str
|
|
19
|
+
agent_title: str
|
|
20
|
+
summary: str
|
|
21
|
+
execution_id: str
|
|
22
|
+
projectID: str
|
|
23
|
+
# Allow extra fields if backend accepts more
|
|
24
|
+
Name: str
|
|
25
|
+
Description: str
|
|
26
|
+
|
|
27
|
+
def create(self, body: InboxCreateBody):
|
|
28
|
+
"""
|
|
29
|
+
Create inbox
|
|
30
|
+
POST /inbox/create
|
|
31
|
+
Creates a new inbox request entry (preview, runtime_input, or anomaly_detection).
|
|
32
|
+
"""
|
|
12
33
|
return self.http.request("POST", "/inbox/create", json=body)
|
|
13
34
|
|
|
14
|
-
|
|
15
|
-
|
|
35
|
+
def list(
|
|
36
|
+
self,
|
|
37
|
+
project_id: str,
|
|
38
|
+
*,
|
|
39
|
+
limit: Optional[int] = 100,
|
|
40
|
+
status: Optional[str] = None,
|
|
41
|
+
type: Optional[str] = None,
|
|
42
|
+
search_key: Optional[str] = None,
|
|
43
|
+
after_id: Optional[str] = None,
|
|
44
|
+
view: Literal["ui", "studio"] = "ui",
|
|
45
|
+
):
|
|
46
|
+
"""
|
|
47
|
+
GET /inbox
|
|
48
|
+
Query: projectID (required), limit, status, type, search_key, after_id, view
|
|
49
|
+
"""
|
|
16
50
|
params: Dict[str, Any] = {"projectID": project_id}
|
|
17
51
|
if limit is not None:
|
|
18
52
|
params["limit"] = limit
|
|
53
|
+
if status is not None:
|
|
54
|
+
params["status"] = status
|
|
55
|
+
if type is not None:
|
|
56
|
+
params["type"] = type
|
|
57
|
+
if search_key is not None:
|
|
58
|
+
params["search_key"] = search_key
|
|
59
|
+
if after_id is not None:
|
|
60
|
+
params["after_id"] = after_id
|
|
61
|
+
if view:
|
|
62
|
+
params["view"] = view
|
|
19
63
|
return self.http.request("GET", "/inbox", params=params)
|
|
20
64
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
65
|
+
class UpdateRuntimeBody(TypedDict):
|
|
66
|
+
is_submitted: bool
|
|
67
|
+
values: Dict[str, str]
|
|
68
|
+
agent_id: str
|
|
69
|
+
|
|
70
|
+
def update_runtime(self, execution_id: str, project_id: Optional[str], body: UpdateRuntimeBody):
|
|
71
|
+
"""
|
|
72
|
+
Update inbox at runtime
|
|
73
|
+
POST /inbox/update/runtime_input/{execution_id}?projectID=...
|
|
74
|
+
"""
|
|
75
|
+
params = {"projectID": project_id} if project_id else None
|
|
76
|
+
return self.http.request("POST", f"/inbox/update/runtime_input/{execution_id}", params=params, json=body)
|
|
24
77
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
78
|
+
class UpdateAnomalyBody(TypedDict):
|
|
79
|
+
is_approved: bool
|
|
80
|
+
|
|
81
|
+
def update_anomaly(self, execution_id: str, project_id: Optional[str], body: UpdateAnomalyBody):
|
|
82
|
+
"""
|
|
83
|
+
Update anomaly detection inbox
|
|
84
|
+
POST /inbox/update/anomaly_detection/{execution_id}?projectID=...
|
|
85
|
+
"""
|
|
86
|
+
params = {"projectID": project_id} if project_id else None
|
|
87
|
+
return self.http.request("POST", f"/inbox/update/anomaly_detection/{execution_id}", params=params, json=body)
|
|
28
88
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
89
|
+
class UpdatePreviewBody(TypedDict):
|
|
90
|
+
agent_id: str
|
|
91
|
+
is_approved: bool
|
|
92
|
+
preview_input: Dict[str, Any]
|
|
32
93
|
|
|
33
|
-
|
|
34
|
-
|
|
94
|
+
def update_preview(self, execution_id: str, project_id: Optional[str], body: UpdatePreviewBody):
|
|
95
|
+
"""
|
|
96
|
+
Update Preview Inbox (Approve or Draft)
|
|
97
|
+
POST /inbox/update/preview/{execution_id}?projectID=...
|
|
98
|
+
"""
|
|
35
99
|
params = {"projectID": project_id} if project_id else None
|
|
36
100
|
return self.http.request("POST", f"/inbox/update/preview/{execution_id}", params=params, json=body)
|
|
37
101
|
|
wexa_sdk/llm.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import TypedDict, List, Literal, Optional, Any
|
|
3
|
+
|
|
4
|
+
from .core.http import HttpClient
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
AllowedModel = Literal[
|
|
8
|
+
"bedrock/amazon.nova-pro-v1",
|
|
9
|
+
"openai/gpt-4o",
|
|
10
|
+
"anthropic/claude-3-5-sonnet",
|
|
11
|
+
"cohere/command-r-plus",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ChatMessage(TypedDict):
|
|
16
|
+
role: Literal["system", "user", "assistant"]
|
|
17
|
+
content: str
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class LlmRequest(TypedDict, total=False):
|
|
21
|
+
model: AllowedModel | str
|
|
22
|
+
messages: List[ChatMessage]
|
|
23
|
+
temperature: float
|
|
24
|
+
maxTokens: int
|
|
25
|
+
stream: bool
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Llm:
|
|
29
|
+
def __init__(self, http: HttpClient):
|
|
30
|
+
self.http = http
|
|
31
|
+
|
|
32
|
+
def llm_call(self, body: LlmRequest) -> Any:
|
|
33
|
+
"""
|
|
34
|
+
Execute an LLM call.
|
|
35
|
+
|
|
36
|
+
POST /llm/execute/calls
|
|
37
|
+
|
|
38
|
+
Example:
|
|
39
|
+
{
|
|
40
|
+
"model": "bedrock/amazon.nova-pro-v1",
|
|
41
|
+
"messages": [{"role": "user", "content": "Hello, how are you?"}]
|
|
42
|
+
}
|
|
43
|
+
"""
|
|
44
|
+
return self.http.request("POST", "/llm/execute/calls", json=body)
|
|
45
|
+
|
|
46
|
+
|
wexa_sdk/projects.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
from typing import Optional, Dict, Any, TypedDict
|
|
3
|
+
from urllib.parse import quote
|
|
3
4
|
|
|
4
5
|
from .core.http import HttpClient
|
|
5
6
|
|
|
@@ -29,7 +30,9 @@ class Projects:
|
|
|
29
30
|
# Per developers.wexa.ai: POST https://api.wexa.ai/v1/project
|
|
30
31
|
def create(self, body: ProjectCreateBody):
|
|
31
32
|
"""
|
|
32
|
-
|
|
33
|
+
Create a project with a request body.
|
|
34
|
+
|
|
35
|
+
Example body:
|
|
33
36
|
{
|
|
34
37
|
"orgId": "67fdea40aac77be632954f0f",
|
|
35
38
|
"projectName": "New",
|
|
@@ -49,10 +52,7 @@ class Projects:
|
|
|
49
52
|
coworker_role: Optional[str] = None,
|
|
50
53
|
status: Optional[str] = None,
|
|
51
54
|
):
|
|
52
|
-
"""Convenience wrapper
|
|
53
|
-
|
|
54
|
-
Builds the request body and calls create().
|
|
55
|
-
"""
|
|
55
|
+
"""Convenience wrapper: builds the body and calls create(body)."""
|
|
56
56
|
body: Dict[str, Any] = {"orgId": orgId, "projectName": projectName}
|
|
57
57
|
if description is not None:
|
|
58
58
|
body["description"] = description
|
|
@@ -62,8 +62,6 @@ class Projects:
|
|
|
62
62
|
body["status"] = status
|
|
63
63
|
return self.create(body) # type: ignore[arg-type]
|
|
64
64
|
|
|
65
|
-
def list(self):
|
|
66
|
-
return self.http.request("GET", "/v1/project")
|
|
67
65
|
|
|
68
66
|
def list_all(self, user_id: str):
|
|
69
67
|
"""
|
|
@@ -79,6 +77,40 @@ class Projects:
|
|
|
79
77
|
params = {"userId": user_id}
|
|
80
78
|
return self.http.request("GET", "/v1/project/all", params=params)
|
|
81
79
|
|
|
80
|
+
def get_all(
|
|
81
|
+
self,
|
|
82
|
+
*,
|
|
83
|
+
status: Optional[str] = None,
|
|
84
|
+
user_id: Optional[str] = None,
|
|
85
|
+
org_id: Optional[str] = None,
|
|
86
|
+
page: Optional[int] = None,
|
|
87
|
+
limit: Optional[int] = None,
|
|
88
|
+
):
|
|
89
|
+
"""
|
|
90
|
+
Get all projects with optional filters and pagination.
|
|
91
|
+
GET /v1/project?status=...&userId=...&orgId=...&page=...&limit=...
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
status: Optional project status filter (e.g., "published").
|
|
95
|
+
user_id: Optional user filter.
|
|
96
|
+
org_id: Optional organization filter.
|
|
97
|
+
page: Optional page number (int).
|
|
98
|
+
limit: Optional page size (int).
|
|
99
|
+
"""
|
|
100
|
+
params: Dict[str, Any] = {}
|
|
101
|
+
if status is not None:
|
|
102
|
+
params["status"] = status
|
|
103
|
+
if user_id is not None:
|
|
104
|
+
params["userId"] = user_id
|
|
105
|
+
if org_id is not None:
|
|
106
|
+
params["orgId"] = org_id
|
|
107
|
+
if page is not None:
|
|
108
|
+
params["page"] = page
|
|
109
|
+
if limit is not None:
|
|
110
|
+
params["limit"] = limit
|
|
111
|
+
|
|
112
|
+
return self.http.request("GET", "/v1/project", params=params)
|
|
113
|
+
|
|
82
114
|
def get(self, project_id: str):
|
|
83
115
|
return self.http.request("GET", f"/v1/project/{project_id}")
|
|
84
116
|
|
|
@@ -98,3 +130,12 @@ class Projects:
|
|
|
98
130
|
|
|
99
131
|
def delete(self, project_id: str):
|
|
100
132
|
return self.http.request("DELETE", f"/v1/project/{project_id}")
|
|
133
|
+
|
|
134
|
+
def get_by_project_name(self, project_name: str):
|
|
135
|
+
"""
|
|
136
|
+
Get project by projectName.
|
|
137
|
+
|
|
138
|
+
GET /project/projectName/{projectName}
|
|
139
|
+
"""
|
|
140
|
+
safe = quote(project_name, safe="")
|
|
141
|
+
return self.http.request("GET", f"/project/projectName/{safe}")
|
wexa_sdk/schedules.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import TypedDict, Optional, Dict, Any
|
|
3
|
+
|
|
4
|
+
from .core.http import HttpClient
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class CoworkerScheduleCreateBody(TypedDict):
|
|
8
|
+
coworker_id: str
|
|
9
|
+
goal: Dict[str, Any]
|
|
10
|
+
template: str
|
|
11
|
+
display_template: str
|
|
12
|
+
schedule: int
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class CoworkerScheduleUpdateBody(TypedDict, total=False):
|
|
16
|
+
goal: Dict[str, Any]
|
|
17
|
+
template: str
|
|
18
|
+
display_template: str
|
|
19
|
+
schedule: int
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Schedules:
|
|
23
|
+
def __init__(self, http: HttpClient):
|
|
24
|
+
self.http = http
|
|
25
|
+
|
|
26
|
+
def list_coworker_schedules(
|
|
27
|
+
self,
|
|
28
|
+
coworker_id: str | None,
|
|
29
|
+
*,
|
|
30
|
+
projectID: str,
|
|
31
|
+
limit: int = 20,
|
|
32
|
+
page_no: int = 1,
|
|
33
|
+
status: Optional[str] = None,
|
|
34
|
+
type: Optional[str] = None,
|
|
35
|
+
search_key: Optional[str] = None,
|
|
36
|
+
):
|
|
37
|
+
"""
|
|
38
|
+
GET /schedules/coworker
|
|
39
|
+
|
|
40
|
+
Query params: projectID (required), limit, page_no, coworker_id, status, type, search_key
|
|
41
|
+
"""
|
|
42
|
+
params: Dict[str, Any] = {"projectID": projectID, "limit": limit, "page_no": page_no}
|
|
43
|
+
if coworker_id:
|
|
44
|
+
params["coworker_id"] = coworker_id
|
|
45
|
+
if status is not None:
|
|
46
|
+
params["status"] = status
|
|
47
|
+
if type is not None:
|
|
48
|
+
params["type"] = type
|
|
49
|
+
if search_key is not None:
|
|
50
|
+
params["search_key"] = search_key
|
|
51
|
+
return self.http.request("GET", "/schedules/coworker", params=params)
|
|
52
|
+
|
|
53
|
+
def create_coworker_schedule(self, *, projectID: str, body: CoworkerScheduleCreateBody):
|
|
54
|
+
"""
|
|
55
|
+
POST /schedule/coworker?projectID=...
|
|
56
|
+
Body: coworker_id, goal, template, display_template, schedule
|
|
57
|
+
"""
|
|
58
|
+
params = {"projectID": projectID}
|
|
59
|
+
return self.http.request("POST", "/schedule/coworker", params=params, json=body)
|
|
60
|
+
|
|
61
|
+
def get_coworker_schedule(self, id: str):
|
|
62
|
+
"""
|
|
63
|
+
GET /schedule/coworker/{id}
|
|
64
|
+
"""
|
|
65
|
+
return self.http.request("GET", f"/schedule/coworker/{id}")
|
|
66
|
+
|
|
67
|
+
def update_coworker_schedule(self, id: str, *, projectID: str, body: CoworkerScheduleUpdateBody):
|
|
68
|
+
"""
|
|
69
|
+
PATCH /schedule/coworker/{id}?projectID=...
|
|
70
|
+
"""
|
|
71
|
+
params = {"projectID": projectID}
|
|
72
|
+
return self.http.request("PATCH", f"/schedule/coworker/{id}", params=params, json=body)
|
|
73
|
+
|
|
74
|
+
def delete_coworker_schedule(self, id: str, *, projectID: str):
|
|
75
|
+
"""
|
|
76
|
+
DELETE /schedule/coworker/{id}?projectID=...
|
|
77
|
+
"""
|
|
78
|
+
params = {"projectID": projectID}
|
|
79
|
+
return self.http.request("DELETE", f"/schedule/coworker/{id}", params=params)
|
|
80
|
+
|
|
81
|
+
|
wexa_sdk/tables.py
CHANGED
|
@@ -1,19 +1,79 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
from typing import Any, Optional
|
|
2
|
+
from typing import Any, Optional, TypedDict, List, Dict, Union
|
|
3
3
|
|
|
4
4
|
from .core.http import HttpClient
|
|
5
5
|
|
|
6
|
+
class ObjectField(TypedDict, total=False):
|
|
7
|
+
"""Field descriptor for object-type columns."""
|
|
8
|
+
key: str
|
|
9
|
+
keyType: str
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AgentflowTrigger(TypedDict, total=False):
|
|
13
|
+
"""Trigger configuration attached to a table or column.
|
|
14
|
+
|
|
15
|
+
Note: exact schemas for `condition` and `filters` may evolve; we leave them open.
|
|
16
|
+
"""
|
|
17
|
+
_id: str
|
|
18
|
+
id: str
|
|
19
|
+
condition: Dict[str, Any]
|
|
20
|
+
name: Optional[str]
|
|
21
|
+
goal: str
|
|
22
|
+
agentflow_id: Optional[str]
|
|
23
|
+
filters: List[Dict[str, Any]]
|
|
24
|
+
schedule_time: Optional[str]
|
|
25
|
+
event: str
|
|
26
|
+
start_from_agent_id: Optional[str]
|
|
27
|
+
trigger_type: str # e.g. "coworker"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class Column(TypedDict, total=False):
|
|
31
|
+
"""Column definition for a table."""
|
|
32
|
+
column_name: str
|
|
33
|
+
column_type: str
|
|
34
|
+
column_id: str
|
|
35
|
+
array_type: Optional[str]
|
|
36
|
+
default_value: Union[Any, List[Any], Dict[str, Any]]
|
|
37
|
+
object_fields: List[ObjectField]
|
|
38
|
+
triggers: List[AgentflowTrigger]
|
|
39
|
+
enum_options: List[str]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class CreateTableInput(TypedDict, total=False):
|
|
43
|
+
"""Typed input for creating a table.
|
|
44
|
+
|
|
45
|
+
Required keys: projectID, table_name
|
|
46
|
+
Optional keys: columns, triggers
|
|
47
|
+
"""
|
|
48
|
+
projectID: str
|
|
49
|
+
table_name: str
|
|
50
|
+
columns: List[Column]
|
|
51
|
+
triggers: List[AgentflowTrigger]
|
|
52
|
+
|
|
53
|
+
|
|
6
54
|
class Tables:
|
|
7
55
|
def __init__(self, http: HttpClient):
|
|
8
56
|
self.http = http
|
|
9
57
|
|
|
10
58
|
# Tables
|
|
11
|
-
def create_table(self, project_id: str, spec:
|
|
59
|
+
def create_table(self, project_id: str, spec: CreateTableInput):
|
|
60
|
+
"""Create a new table.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
project_id: The project ID (placed into query as `projectID`).
|
|
64
|
+
spec: Table specification containing at least `table_name`.
|
|
65
|
+
|
|
66
|
+
The backend expects `projectID` in both query params and JSON body.
|
|
67
|
+
"""
|
|
12
68
|
# API expects projectID as query param and in body with 'projectID' casing
|
|
13
69
|
params = {"projectID": project_id}
|
|
14
70
|
body = {"projectID": project_id, **spec}
|
|
15
71
|
return self.http.request("POST", "/create/table", params=params, json=body)
|
|
16
72
|
|
|
73
|
+
# New: POST /storage/{projectID}/{collection_name}
|
|
74
|
+
def create_records_by_collection(self, project_id: str, collection_name: str, records: List[dict]):
|
|
75
|
+
return self.http.request("POST", f"/storage/{project_id}/{collection_name}", json=records)
|
|
76
|
+
|
|
17
77
|
def list_tables(self, project_id: str):
|
|
18
78
|
return self.http.request("GET", f"/storage/{project_id}")
|
|
19
79
|
|
|
@@ -36,6 +96,26 @@ class Tables:
|
|
|
36
96
|
def delete_column(self, project_id: str, column_id: str):
|
|
37
97
|
return self.http.request("DELETE", f"/delete/column/{project_id}", json={"columnId": column_id})
|
|
38
98
|
|
|
99
|
+
# New: POST /column/storage/{projectID}/{table_id}?ignore_existing_columns=...
|
|
100
|
+
def add_columns(self, project_id: str, table_id: str, columns: List[Column], ignore_existing_columns: Optional[bool] = None):
|
|
101
|
+
params: Dict[str, Any] = {}
|
|
102
|
+
if ignore_existing_columns is not None:
|
|
103
|
+
params["ignore_existing_columns"] = ignore_existing_columns
|
|
104
|
+
return self.http.request("POST", f"/column/storage/{project_id}/{table_id}", params=params or None, json=columns)
|
|
105
|
+
|
|
106
|
+
# New: PUT /edit/columns/{projectId} with rename body
|
|
107
|
+
def update_column_name(self, project_id: str, *, column_id: str, column_name: str, table_id: str):
|
|
108
|
+
body = {"column_id": column_id, "column_name": column_name, "table_id": table_id}
|
|
109
|
+
return self.http.request("PUT", f"/edit/columns/{project_id}", json=body)
|
|
110
|
+
|
|
111
|
+
# New: PATCH /edit/columns/{table_id} with full Column
|
|
112
|
+
def patch_column(self, table_id: str, column: Column):
|
|
113
|
+
return self.http.request("PATCH", f"/edit/columns/{table_id}", json=column)
|
|
114
|
+
|
|
115
|
+
# New: DELETE /delete/column/{projectId} body { table_id, column_id }
|
|
116
|
+
def delete_column_extended(self, project_id: str, *, table_id: str, column_id: str):
|
|
117
|
+
return self.http.request("DELETE", f"/delete/column/{project_id}", json={"table_id": table_id, "column_id": column_id})
|
|
118
|
+
|
|
39
119
|
# Records
|
|
40
120
|
def create_record(self, project_id: str, table_id: str, record: dict):
|
|
41
121
|
return self.http.request("POST", f"/storage/{project_id}/{table_id}", json=record)
|
|
@@ -52,8 +132,29 @@ class Tables:
|
|
|
52
132
|
def list_records(self, project_id: str, table_id: str, query: Optional[dict] = None):
|
|
53
133
|
return self.http.request("GET", f"/storage/{project_id}/{table_id}", params=query)
|
|
54
134
|
|
|
55
|
-
|
|
56
|
-
|
|
135
|
+
# New: DELETE /storage/{projectID}/{tableId} body { storage_ids: [] }
|
|
136
|
+
def delete_records_bulk(self, project_id: str, table_id: str, storage_ids: List[str]):
|
|
137
|
+
return self.http.request("DELETE", f"/storage/{project_id}/{table_id}", json={"storage_ids": storage_ids})
|
|
138
|
+
|
|
139
|
+
# New: PUT /bulk/storage/{projectID}/{table_id} body { records, record_ids: { storage_ids: [] } }
|
|
140
|
+
def bulk_update_records(self, project_id: str, table_id: str, *, records: Dict[str, Any], record_ids: Dict[str, Any]):
|
|
141
|
+
return self.http.request("PUT", f"/bulk/storage/{project_id}/{table_id}", json={"records": records, "record_ids": record_ids})
|
|
57
142
|
|
|
58
143
|
def export(self, project_id: str, table_id: str):
|
|
59
144
|
return self.http.request("GET", f"/table_data/storage/{table_id}/export")
|
|
145
|
+
|
|
146
|
+
# New: PUT /table/rename/{projectID} body { table_id, table_name, triggers? }
|
|
147
|
+
def rename_table_extended(self, project_id: str, *, table_id: str, table_name: str, triggers: Optional[List[AgentflowTrigger]] = None):
|
|
148
|
+
body: Dict[str, Any] = {"table_id": table_id, "table_name": table_name}
|
|
149
|
+
if triggers is not None:
|
|
150
|
+
body["triggers"] = triggers
|
|
151
|
+
return self.http.request("PUT", f"/table/rename/{project_id}", json=body)
|
|
152
|
+
|
|
153
|
+
# New: POST /table/column_mapper
|
|
154
|
+
def column_mapper(self, *, column_names: List[Dict[str, str]], csv_headers: List[str]):
|
|
155
|
+
body = {"column_names": column_names, "csv_headers": csv_headers}
|
|
156
|
+
return self.http.request("POST", "/table/column_mapper", json=body)
|
|
157
|
+
|
|
158
|
+
# New: POST /table/fieldcount/{project_id}/{table_id}
|
|
159
|
+
def field_count(self, project_id: str, table_id: str, filters: List[Dict[str, Any]]):
|
|
160
|
+
return self.http.request("POST", f"/table/fieldcount/{project_id}/{table_id}", json=filters)
|
wexa_sdk/tasks.py
CHANGED
|
@@ -9,14 +9,15 @@ class Tasks:
|
|
|
9
9
|
|
|
10
10
|
# GET /tasks/?projectID=...&limit=...&skip=...&created_by=...
|
|
11
11
|
def list(self, project_id: str, *, limit: Optional[int] = None, skip: Optional[int] = None, created_by: Optional[str] = None):
|
|
12
|
-
|
|
12
|
+
api_url = f"/tasks/{project_id}"
|
|
13
|
+
params: Dict[str, Any] = {}
|
|
13
14
|
if limit is not None:
|
|
14
15
|
params["limit"] = limit
|
|
15
16
|
if skip is not None:
|
|
16
17
|
params["skip"] = skip
|
|
17
18
|
if created_by:
|
|
18
19
|
params["created_by"] = created_by
|
|
19
|
-
return self.http.request("GET",
|
|
20
|
+
return self.http.request("GET", api_url, params=params)
|
|
20
21
|
|
|
21
22
|
# GET /task/{id}?projectID=...
|
|
22
23
|
def get(self, task_id: str, project_id: Optional[str] = None):
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
wexa_sdk/__init__.py,sha256=_KBd7MB0hirHpXmQ8AgaG_Pso3RaV4QBVNLdQOCxz9Q,1761
|
|
2
|
+
wexa_sdk/agentflows.py,sha256=3BqBElG7pDlcnaVjTAc4OZ9ZkeJoaSWVIvDWS5PBKJ8,5170
|
|
3
|
+
wexa_sdk/analytics.py,sha256=PVWvRvuyxOAbwxxAoILquESyb2Jw3cJGogbBu2ATRH4,345
|
|
4
|
+
wexa_sdk/connectors_mgmt.py,sha256=7vCT4ilez2YjZnfFEzb0raglTwweqxomqtJOb36RVT4,2229
|
|
5
|
+
wexa_sdk/executions.py,sha256=FzmYFPXLLbRSH--OPe44oaLYhngjc1xFBy_8hyx9iew,2129
|
|
6
|
+
wexa_sdk/files.py,sha256=Gujj7Oc8-TcoKFjpgT2GkhgJ28HBerv8Q9jlTfO_LOk,1276
|
|
7
|
+
wexa_sdk/inbox.py,sha256=KTlJPrr7v90n-1mQcPAazFeISSZ_m4bIPSXOpd3ra-0,3688
|
|
8
|
+
wexa_sdk/llm.py,sha256=7eiGb43PwIJqv9KczAdStYWNTFl-fe1etZ7R77kESBo,1009
|
|
9
|
+
wexa_sdk/marketplace.py,sha256=jhpeSWLU_BLFJcbwx_vcLeUff3UEPkylyhVIm_Fcb5Y,1609
|
|
10
|
+
wexa_sdk/project_members.py,sha256=TssDroghwYMsPRibZ1dNvKynzMtgIUN1TDFsmc2AuW4,514
|
|
11
|
+
wexa_sdk/projects.py,sha256=7mjDVlY7AUzG_zf2Gs_kFodEIWRcvLYoAiCsvpWp7-s,4266
|
|
12
|
+
wexa_sdk/schedules.py,sha256=IO7KolBX-8LddDCI7RqXlMHdrpDEVpEwn28FeMwb6TA,2543
|
|
13
|
+
wexa_sdk/settings.py,sha256=TDnqYeFBvrrj9kznTUTJxG29sJ02bHxBlqE55DgIfTg,290
|
|
14
|
+
wexa_sdk/skills.py,sha256=ZOFdspJsns_X88nBMrhaFWWcTKuh5afk0hK73-Qzs9M,1799
|
|
15
|
+
wexa_sdk/tables.py,sha256=meFX4Kg1Z-O2tqmrtvYEQlKozdmH8wQnZRBqktu_fWM,7326
|
|
16
|
+
wexa_sdk/tasks.py,sha256=DMoKUy_p7ADTK1da0vehTFGrjF3otnOC3YM9nMruf_0,1365
|
|
17
|
+
wexa_sdk/connectors/__init__.py,sha256=eEtSQ8oXlYnoD3CUxPCF3Il6bgGyN6zfKI3_Pu41jXo,51
|
|
18
|
+
wexa_sdk/connectors/core.py,sha256=7ghbFAPR1emgBL9PWStDp6AgZ5JDkiBWXQGaZ0B5Fek,1978
|
|
19
|
+
wexa_sdk/connectors/google_drive.py,sha256=Dibfoy8uKcGygmjCnrolPhKq5Fy5ye5-ee_kI4XD7kY,945
|
|
20
|
+
wexa_sdk/core/__init__.py,sha256=K-bUeDdR3iblN9BNwMQ-ZMbOcAJSAUkNwuoVz5L3fC4,39
|
|
21
|
+
wexa_sdk/core/http.py,sha256=-zKSZoXKoO50uE6W9lAiVD7cmrvloAll-YtMBGXKE8k,3722
|
|
22
|
+
wexa_sdk/models/__init__.py,sha256=yxQUjah8RTJh531y8QQXEeh5dp0d5k55dsrVvR4O1N8,75
|
|
23
|
+
wexa_sdk-0.1.11.dist-info/METADATA,sha256=uKdpm2XWoUPaUN6MhgPJsErrfO_J6tMdd1X1TQ9Xj2U,582
|
|
24
|
+
wexa_sdk-0.1.11.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
25
|
+
wexa_sdk-0.1.11.dist-info/top_level.txt,sha256=iXL6c0Kro-mkIoNbjT76txRuoilWB-P7AHhmvKtdXkA,9
|
|
26
|
+
wexa_sdk-0.1.11.dist-info/RECORD,,
|
wexa_sdk-0.1.2.dist-info/RECORD
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
wexa_sdk/__init__.py,sha256=dNvZ0fU4v0clBOuZWdd02SLxVfrBF2Ig-efQMOweq-I,1627
|
|
2
|
-
wexa_sdk/agentflows.py,sha256=_1DJYXVi6Jyj9-jn0UtO1C7X_sdTcfdp0qdMtQZPQKo,2543
|
|
3
|
-
wexa_sdk/analytics.py,sha256=PVWvRvuyxOAbwxxAoILquESyb2Jw3cJGogbBu2ATRH4,345
|
|
4
|
-
wexa_sdk/connectors_mgmt.py,sha256=7vCT4ilez2YjZnfFEzb0raglTwweqxomqtJOb36RVT4,2229
|
|
5
|
-
wexa_sdk/executions.py,sha256=-bVXo7ESA8AYZtc-tPDi28qWKJg_eYEQCo1kSYgE1P8,2509
|
|
6
|
-
wexa_sdk/files.py,sha256=K2m6gxs_8XDhlW4W08DhSc-HwrMx3r2S5dOFvltLTqc,1235
|
|
7
|
-
wexa_sdk/inbox.py,sha256=aKFmST2FX09mDYXyrqNpUYTsq6z0iJG4qtsCeMWKPdo,1957
|
|
8
|
-
wexa_sdk/marketplace.py,sha256=jhpeSWLU_BLFJcbwx_vcLeUff3UEPkylyhVIm_Fcb5Y,1609
|
|
9
|
-
wexa_sdk/project_members.py,sha256=TssDroghwYMsPRibZ1dNvKynzMtgIUN1TDFsmc2AuW4,514
|
|
10
|
-
wexa_sdk/projects.py,sha256=zx5ncmhxbwSiFKU0QpVA01eKNxQW2zPYzPV_njGUCrc,2937
|
|
11
|
-
wexa_sdk/settings.py,sha256=TDnqYeFBvrrj9kznTUTJxG29sJ02bHxBlqE55DgIfTg,290
|
|
12
|
-
wexa_sdk/skills.py,sha256=ZOFdspJsns_X88nBMrhaFWWcTKuh5afk0hK73-Qzs9M,1799
|
|
13
|
-
wexa_sdk/tables.py,sha256=JYGK1zWRWZgZGbiRyv-ko3XKdpxZv0piwb02h0v5ODw,2753
|
|
14
|
-
wexa_sdk/tasks.py,sha256=YRXMxQwgpiflAxyUqedyo4LB6bsO7zsiM5uP0uE8_Ds,1349
|
|
15
|
-
wexa_sdk/connectors/__init__.py,sha256=eEtSQ8oXlYnoD3CUxPCF3Il6bgGyN6zfKI3_Pu41jXo,51
|
|
16
|
-
wexa_sdk/connectors/core.py,sha256=4dFp0CVCysUsIOT7l9V7bzXu1jRx9EBGZv2_bQkKPsQ,1188
|
|
17
|
-
wexa_sdk/connectors/google_drive.py,sha256=Dibfoy8uKcGygmjCnrolPhKq5Fy5ye5-ee_kI4XD7kY,945
|
|
18
|
-
wexa_sdk/core/__init__.py,sha256=K-bUeDdR3iblN9BNwMQ-ZMbOcAJSAUkNwuoVz5L3fC4,39
|
|
19
|
-
wexa_sdk/core/http.py,sha256=4O59C5VlVhxaQNkjJ0UpARZk3g-rEoOxEbwE0u9NWbY,3721
|
|
20
|
-
wexa_sdk/models/__init__.py,sha256=yxQUjah8RTJh531y8QQXEeh5dp0d5k55dsrVvR4O1N8,75
|
|
21
|
-
wexa_sdk-0.1.2.dist-info/METADATA,sha256=hIdfzWXxN8YiHvOXe2688JcF0V6fl4IhOr-D84UWXNE,581
|
|
22
|
-
wexa_sdk-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
23
|
-
wexa_sdk-0.1.2.dist-info/top_level.txt,sha256=iXL6c0Kro-mkIoNbjT76txRuoilWB-P7AHhmvKtdXkA,9
|
|
24
|
-
wexa_sdk-0.1.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|