wexa-sdk 0.1.3__tar.gz → 0.1.7__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.
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/PKG-INFO +1 -1
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/pyproject.toml +1 -1
- wexa_sdk-0.1.7/tests/test_agentflows_add_skilled_agent.py +46 -0
- wexa_sdk-0.1.7/tests/test_agentflows_update_skilled_live.py +46 -0
- wexa_sdk-0.1.7/tests/test_agentflows_update_skilled_unit.py +43 -0
- wexa_sdk-0.1.7/tests/test_connectors_config.py +30 -0
- wexa_sdk-0.1.7/tests/test_connectors_config_live.py +58 -0
- wexa_sdk-0.1.7/tests/test_projects_create.py +60 -0
- wexa_sdk-0.1.7/tests/test_projects_create_live.py +41 -0
- wexa_sdk-0.1.7/tests/test_projects_get_all_live.py +51 -0
- wexa_sdk-0.1.7/tests/test_projects_mcpconnectortesting.py +25 -0
- wexa_sdk-0.1.7/tests/test_projects_mcpconnectortesting_live.py +26 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_tables.py +2 -2
- wexa_sdk-0.1.7/tests/test_tables_create_live.py +36 -0
- wexa_sdk-0.1.7/tests/test_tables_create_rich.py +54 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/agentflows.py +47 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/connectors/core.py +31 -3
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/core/http.py +1 -1
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/projects.py +14 -5
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/tables.py +58 -2
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk.egg-info/PKG-INFO +1 -1
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk.egg-info/SOURCES.txt +12 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/README.md +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/setup.cfg +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_agentflows.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_agentflows_crud.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_analytics.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_connectors_core.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_connectors_mgmt.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_demo_coworker_workflow.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_executions.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_files.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_inbox.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_integration_agentflows_create.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_integration_marketplace.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_marketplace.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_project_members.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_projects.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_projects_crud.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_projects_get_all.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_settings.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_skills.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/tests/test_tasks.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/__init__.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/analytics.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/connectors/__init__.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/connectors/google_drive.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/connectors_mgmt.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/core/__init__.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/executions.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/files.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/inbox.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/marketplace.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/models/__init__.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/project_members.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/settings.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/skills.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk/tasks.py +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk.egg-info/dependency_links.txt +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk.egg-info/requires.txt +0 -0
- {wexa_sdk-0.1.3 → wexa_sdk-0.1.7}/wexa_sdk.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from wexa_sdk import WexaClient
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def test_agentflows_add_skilled_agent_requests(monkeypatch):
|
|
5
|
+
client = WexaClient(base_url="https://api.wexa.ai", api_key="key")
|
|
6
|
+
|
|
7
|
+
captured = {}
|
|
8
|
+
|
|
9
|
+
def fake_request(method, path, *, params=None, json=None, headers=None): # type: ignore
|
|
10
|
+
captured["method"] = method
|
|
11
|
+
captured["path"] = path
|
|
12
|
+
captured["params"] = params
|
|
13
|
+
captured["json"] = json
|
|
14
|
+
return {"ok": True}
|
|
15
|
+
|
|
16
|
+
client.http.request = fake_request # type: ignore
|
|
17
|
+
|
|
18
|
+
body = {
|
|
19
|
+
"_id": "agent-1",
|
|
20
|
+
"role": "assistant",
|
|
21
|
+
"title": "Writer",
|
|
22
|
+
"skills": ["content_writer"],
|
|
23
|
+
"context": [],
|
|
24
|
+
"llm": {"model": "gpt-4o", "max_tokens": 512, "temperature": 0.7},
|
|
25
|
+
"memory": {"memory_type": "short_term"},
|
|
26
|
+
"agent_type": "skilled",
|
|
27
|
+
"role_description": "Creates content",
|
|
28
|
+
"prompt": {"template": "...", "variables": [], "display_template": "..."},
|
|
29
|
+
"triggers": [],
|
|
30
|
+
"has_knowledge_base": False,
|
|
31
|
+
"is_user_specific_task": False,
|
|
32
|
+
"is_preview_mode_enabled": False,
|
|
33
|
+
"conditions": [],
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
resp = client.agentflows.add_skilled_agent(
|
|
37
|
+
"aflow-123",
|
|
38
|
+
projectID="proj-1",
|
|
39
|
+
body=body,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
assert captured["method"] == "POST"
|
|
43
|
+
assert captured["path"] == "/agentflow/aflow-123/skilled"
|
|
44
|
+
assert captured["params"] == {"projectID": "proj-1"}
|
|
45
|
+
assert captured["json"] == body
|
|
46
|
+
assert resp == {"ok": True}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
import pytest
|
|
4
|
+
from wexa_sdk import WexaClient
|
|
5
|
+
|
|
6
|
+
BASE_URL = os.getenv("WEXA_BASE_URL", "https://api.wexa.ai")
|
|
7
|
+
API_KEY = os.getenv("WEXA_API_KEY") or ""
|
|
8
|
+
PROJECT_ID = os.getenv("PROJECT_ID", "68c3b68b9120a0bdfb281d89")
|
|
9
|
+
AGENTFLOW_ID = os.getenv("AGENTFLOW_ID", "6901def632348b1fae4c0e6a")
|
|
10
|
+
AGENT_ID = os.getenv("AGENT_ID", "6901def7e643a25d472d0952")
|
|
11
|
+
|
|
12
|
+
# The user-provided payload (trimmed to minimal required where possible)
|
|
13
|
+
PAYLOAD = {
|
|
14
|
+
"role": "Create Call",
|
|
15
|
+
"title": "Create a Call",
|
|
16
|
+
"skills": ["6901dbf973f8d927fe126fad"],
|
|
17
|
+
"prompt": {
|
|
18
|
+
"display_template": "...", # large rich text omitted for brevity
|
|
19
|
+
"variables": [],
|
|
20
|
+
"template": "..."
|
|
21
|
+
},
|
|
22
|
+
"context": [],
|
|
23
|
+
"triggers": [],
|
|
24
|
+
"llm": {"model": "bedrock/eu.anthropic.claude-3-7-sonnet-20250219-v1:0", "max_tokens": 10000, "temperature": 0},
|
|
25
|
+
"role_description": "Creating a calling agent",
|
|
26
|
+
"memory": {"memory_type": "lt"},
|
|
27
|
+
"has_knowledge_base": False,
|
|
28
|
+
"is_user_specific_task": False,
|
|
29
|
+
"is_preview_mode_enabled": False,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@pytest.mark.integration
|
|
34
|
+
def test_update_skilled_agent_live():
|
|
35
|
+
if not API_KEY:
|
|
36
|
+
pytest.skip("Set WEXA_API_KEY to run this live test")
|
|
37
|
+
|
|
38
|
+
client = WexaClient(base_url=BASE_URL, api_key=API_KEY)
|
|
39
|
+
resp = client.agentflows.update_skilled_agent(
|
|
40
|
+
agentflow_id=AGENTFLOW_ID,
|
|
41
|
+
agent_id=AGENT_ID,
|
|
42
|
+
projectID=PROJECT_ID,
|
|
43
|
+
body=PAYLOAD,
|
|
44
|
+
)
|
|
45
|
+
print(json.dumps(resp, indent=2))
|
|
46
|
+
assert isinstance(resp, dict) or isinstance(resp, list)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from wexa_sdk import WexaClient
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def test_agentflows_update_skilled_builds_request(monkeypatch):
|
|
5
|
+
c = WexaClient(base_url="https://api.wexa.ai", api_key="key")
|
|
6
|
+
captured = {}
|
|
7
|
+
|
|
8
|
+
def fake_request(method, path, *, params=None, json=None, headers=None): # type: ignore
|
|
9
|
+
captured["method"] = method
|
|
10
|
+
captured["path"] = path
|
|
11
|
+
captured["params"] = params
|
|
12
|
+
captured["json"] = json
|
|
13
|
+
return {"ok": True}
|
|
14
|
+
|
|
15
|
+
c.http.request = fake_request # type: ignore
|
|
16
|
+
|
|
17
|
+
body = {
|
|
18
|
+
"role": "assistant",
|
|
19
|
+
"title": "Create a Call",
|
|
20
|
+
"skills": ["skill-1"],
|
|
21
|
+
"prompt": {"template": "t", "variables": [], "display_template": "d"},
|
|
22
|
+
"context": [],
|
|
23
|
+
"triggers": [],
|
|
24
|
+
"llm": {"model": "m", "max_tokens": 1000, "temperature": 0},
|
|
25
|
+
"role_description": "desc",
|
|
26
|
+
"memory": {"memory_type": "lt"},
|
|
27
|
+
"has_knowledge_base": False,
|
|
28
|
+
"is_user_specific_task": False,
|
|
29
|
+
"is_preview_mode_enabled": False,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
resp = c.agentflows.update_skilled_agent(
|
|
33
|
+
agentflow_id="aflow-1",
|
|
34
|
+
agent_id="agent-1",
|
|
35
|
+
projectID="proj-1",
|
|
36
|
+
body=body,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
assert captured["method"] == "POST"
|
|
40
|
+
assert captured["path"] == "/agentflow/aflow-1/update/skilled/agent-1"
|
|
41
|
+
assert captured["params"] == {"projectID": "proj-1"}
|
|
42
|
+
assert captured["json"] == body
|
|
43
|
+
assert resp == {"ok": True}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from wexa_sdk import WexaClient
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def test_connectors_config_endpoints(monkeypatch):
|
|
5
|
+
c = WexaClient(base_url="https://api.wexa.ai", api_key="key")
|
|
6
|
+
calls = []
|
|
7
|
+
|
|
8
|
+
def fake_request(method, path, *, params=None, json=None, headers=None): # type: ignore
|
|
9
|
+
calls.append((method, path, params, json))
|
|
10
|
+
return {"ok": True}
|
|
11
|
+
|
|
12
|
+
c.http.request = fake_request # type: ignore
|
|
13
|
+
|
|
14
|
+
# set config -> POST /actions/{CATEGORY}/config?projectID=...
|
|
15
|
+
c.connectors.set_config("content_creator", "p1", {"enabled": True})
|
|
16
|
+
# get config -> GET /actions/{CATEGORY}/config/{projectID}
|
|
17
|
+
c.connectors.get_config("content_creator", "p1")
|
|
18
|
+
|
|
19
|
+
assert calls[0] == (
|
|
20
|
+
"POST",
|
|
21
|
+
"/actions/content_creator/config",
|
|
22
|
+
{"projectID": "p1"},
|
|
23
|
+
{"enabled": True},
|
|
24
|
+
)
|
|
25
|
+
assert calls[1] == (
|
|
26
|
+
"GET",
|
|
27
|
+
"/actions/content_creator/config/p1",
|
|
28
|
+
None,
|
|
29
|
+
None,
|
|
30
|
+
)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
import time
|
|
4
|
+
import pytest
|
|
5
|
+
from wexa_sdk import WexaClient
|
|
6
|
+
|
|
7
|
+
BASE_URL = os.getenv("WEXA_BASE_URL", "https://api.wexa.ai")
|
|
8
|
+
API_KEY = os.getenv("WEXA_API_KEY")
|
|
9
|
+
PROJECT_ID = "68c3b68b9120a0bdfb281d89" # provided
|
|
10
|
+
CATEGORY = "content_creator"
|
|
11
|
+
ORG_ID = os.getenv("WEXA_ORG_ID") or os.getenv("NEXT_PUBLIC_ORG_ID")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@pytest.mark.integration
|
|
15
|
+
def test_content_creator_config_live_get_then_set():
|
|
16
|
+
"""
|
|
17
|
+
Live test for connector config:
|
|
18
|
+
1) GET /actions/{CATEGORY}/config/{projectID}
|
|
19
|
+
2) POST /actions/{CATEGORY}/config?projectID=...
|
|
20
|
+
|
|
21
|
+
Skips when WEXA_API_KEY or ORG_ID (WEXA_ORG_ID/NEXT_PUBLIC_ORG_ID) is not set.
|
|
22
|
+
"""
|
|
23
|
+
if not API_KEY:
|
|
24
|
+
pytest.skip("Set WEXA_API_KEY in the environment to run this live test")
|
|
25
|
+
if not ORG_ID:
|
|
26
|
+
pytest.skip("Set WEXA_ORG_ID or NEXT_PUBLIC_ORG_ID to run this live test")
|
|
27
|
+
|
|
28
|
+
client = WexaClient(base_url=BASE_URL, api_key=API_KEY)
|
|
29
|
+
|
|
30
|
+
# Step 1: GET current config
|
|
31
|
+
current = client.connectors.get_config(CATEGORY, PROJECT_ID)
|
|
32
|
+
print(json.dumps({"current": current}, indent=2))
|
|
33
|
+
|
|
34
|
+
# Step 2: Build required payload from GET response and env
|
|
35
|
+
cfg = (current or {}).get("config", {})
|
|
36
|
+
# Ensure unique name to avoid 'Connector with the same name already exists'
|
|
37
|
+
base_name = cfg.get("name") or "Content creator"
|
|
38
|
+
unique_name = f"{base_name}-{int(time.time())}"
|
|
39
|
+
update_body = {
|
|
40
|
+
# required by backend
|
|
41
|
+
"name": unique_name,
|
|
42
|
+
"description": cfg.get("description") or "",
|
|
43
|
+
"category": CATEGORY,
|
|
44
|
+
"org_id": ORG_ID,
|
|
45
|
+
"projectID": PROJECT_ID,
|
|
46
|
+
"logo": cfg.get("logo") or "",
|
|
47
|
+
"ui_form": cfg.get("ui_form") or [],
|
|
48
|
+
# optional but present in GET; include to be safe
|
|
49
|
+
"config": cfg.get("config") or {},
|
|
50
|
+
# toggle
|
|
51
|
+
"enabled": True,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
updated = client.connectors.set_config(CATEGORY, PROJECT_ID, update_body)
|
|
55
|
+
print(json.dumps({"updated": updated}, indent=2))
|
|
56
|
+
|
|
57
|
+
# Basic assertions
|
|
58
|
+
assert isinstance(updated, dict)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from wexa_sdk import WexaClient
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def test_projects_create_published(monkeypatch):
|
|
5
|
+
c = WexaClient(base_url="https://api.wexa.ai", api_key="key")
|
|
6
|
+
calls = []
|
|
7
|
+
|
|
8
|
+
def fake_request(method, path, *, params=None, json=None, headers=None): # type: ignore
|
|
9
|
+
calls.append((method, path, params, json))
|
|
10
|
+
return {"_id": "p123"}
|
|
11
|
+
|
|
12
|
+
c.http.request = fake_request # type: ignore
|
|
13
|
+
|
|
14
|
+
body = {
|
|
15
|
+
"orgId": "o1",
|
|
16
|
+
"projectName": "My Project",
|
|
17
|
+
"description": "desc",
|
|
18
|
+
"coworker_role": "role",
|
|
19
|
+
"status": "published",
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
res = c.projects.create(body)
|
|
23
|
+
|
|
24
|
+
# Assert method, path, and payload
|
|
25
|
+
assert calls[0][0] == "POST"
|
|
26
|
+
assert calls[0][1] == "/v1/project"
|
|
27
|
+
assert calls[0][2] is None # params
|
|
28
|
+
assert calls[0][3] == body # json body
|
|
29
|
+
assert res == {"_id": "p123"}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_projects_create_simple_published(monkeypatch):
|
|
33
|
+
c = WexaClient(base_url="https://api.wexa.ai", api_key="key")
|
|
34
|
+
calls = []
|
|
35
|
+
|
|
36
|
+
def fake_request(method, path, *, params=None, json=None, headers=None): # type: ignore
|
|
37
|
+
calls.append((method, path, params, json))
|
|
38
|
+
return {"_id": "p456"}
|
|
39
|
+
|
|
40
|
+
c.http.request = fake_request # type: ignore
|
|
41
|
+
|
|
42
|
+
res = c.projects.create_simple(
|
|
43
|
+
orgId="o1",
|
|
44
|
+
projectName="Simple Project",
|
|
45
|
+
description="desc2",
|
|
46
|
+
coworker_role="role2",
|
|
47
|
+
status="published",
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
assert calls[0][0] == "POST"
|
|
51
|
+
assert calls[0][1] == "/v1/project"
|
|
52
|
+
assert calls[0][2] is None
|
|
53
|
+
assert calls[0][3] == {
|
|
54
|
+
"orgId": "o1",
|
|
55
|
+
"projectName": "Simple Project",
|
|
56
|
+
"description": "desc2",
|
|
57
|
+
"coworker_role": "role2",
|
|
58
|
+
"status": "published",
|
|
59
|
+
}
|
|
60
|
+
assert res == {"_id": "p456"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import json
|
|
3
|
+
import pytest
|
|
4
|
+
from wexa_sdk import WexaClient
|
|
5
|
+
|
|
6
|
+
# ===== Configure for live run =====
|
|
7
|
+
BASE_URL = "https://api.wexa.ai"
|
|
8
|
+
API_KEY = "506af7e9-9309-4fdf-b004-8d4cb09dfc05"
|
|
9
|
+
ORG_ID = "66f3cdde22bc63eb7490e23e"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.mark.integration
|
|
13
|
+
def test_projects_create_live_published():
|
|
14
|
+
"""
|
|
15
|
+
Live test that creates a new project in the given org with status "published".
|
|
16
|
+
This will mutate production data.
|
|
17
|
+
|
|
18
|
+
To run:
|
|
19
|
+
pytest -s tests/test_projects_create_live.py
|
|
20
|
+
"""
|
|
21
|
+
if not API_KEY or "REPLACE_WITH" in API_KEY or not ORG_ID:
|
|
22
|
+
pytest.skip("Edit BASE_URL, API_KEY, ORG_ID before running this live test")
|
|
23
|
+
|
|
24
|
+
c = WexaClient(base_url=BASE_URL, api_key=API_KEY)
|
|
25
|
+
|
|
26
|
+
name = f"SDK Create Test {int(time.time())}"
|
|
27
|
+
body = {
|
|
28
|
+
"orgId": ORG_ID,
|
|
29
|
+
"projectName": name,
|
|
30
|
+
"description": "Created via live integration test",
|
|
31
|
+
"coworker_role": "Tester",
|
|
32
|
+
"status": "published",
|
|
33
|
+
}
|
|
34
|
+
res = c.projects.create(body)
|
|
35
|
+
|
|
36
|
+
print(json.dumps(res, indent=2))
|
|
37
|
+
|
|
38
|
+
assert isinstance(res, dict)
|
|
39
|
+
created = res.get("data", res)
|
|
40
|
+
assert isinstance(created, dict)
|
|
41
|
+
assert "_id" in created
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import json
|
|
3
|
+
from wexa_sdk import WexaClient
|
|
4
|
+
|
|
5
|
+
# ===== Configure these before running =====
|
|
6
|
+
# Use prod or local API base URL
|
|
7
|
+
BASE_URL = "https://api.wexa.ai" # or "http://localhost:5000"
|
|
8
|
+
API_KEY = "506af7e9-9309-4fdf-b004-8d4cb09dfc05"
|
|
9
|
+
TEST_USER_ID = "66f3cdde22bc63eb7490e23c"
|
|
10
|
+
TEST_ORG_ID = "66f3cdde22bc63eb7490e23e"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.mark.integration
|
|
14
|
+
def test_projects_get_all_live():
|
|
15
|
+
"""
|
|
16
|
+
Live integration test for Projects.get_all() against a real API.
|
|
17
|
+
|
|
18
|
+
Usage:
|
|
19
|
+
1) Edit BASE_URL, API_KEY, TEST_USER_ID, TEST_ORG_ID at the top of this file.
|
|
20
|
+
2) Run: pytest -q tests/test_projects_get_all_live.py
|
|
21
|
+
"""
|
|
22
|
+
base_url = BASE_URL
|
|
23
|
+
api_key = API_KEY
|
|
24
|
+
user_id = TEST_USER_ID
|
|
25
|
+
org_id = TEST_ORG_ID
|
|
26
|
+
|
|
27
|
+
if (not api_key) or ("REPLACE_WITH_API_KEY" in api_key) or (not user_id) or (not org_id):
|
|
28
|
+
pytest.skip("Edit BASE_URL, API_KEY, TEST_USER_ID, TEST_ORG_ID in this file to run this live test")
|
|
29
|
+
|
|
30
|
+
c = WexaClient(base_url=base_url, api_key=api_key)
|
|
31
|
+
res = c.projects.get_all(
|
|
32
|
+
status="published",
|
|
33
|
+
user_id=user_id,
|
|
34
|
+
org_id=org_id,
|
|
35
|
+
page=1,
|
|
36
|
+
limit=12,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# Print the response for inspection
|
|
40
|
+
print(json.dumps(res, indent=2))
|
|
41
|
+
|
|
42
|
+
assert isinstance(res, dict)
|
|
43
|
+
|
|
44
|
+
# Backend may return either a list wrapper or items/count; accept both
|
|
45
|
+
if "projectList" in res:
|
|
46
|
+
assert isinstance(res["projectList"], list)
|
|
47
|
+
assert "totalCount" in res
|
|
48
|
+
else:
|
|
49
|
+
# fallback shape if API differs
|
|
50
|
+
assert "items" in res
|
|
51
|
+
assert isinstance(res["items"], list)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from wexa_sdk import WexaClient
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def test_projects_get_by_project_name_builds_correct_request(monkeypatch):
|
|
6
|
+
captured = {}
|
|
7
|
+
|
|
8
|
+
def fake_request(method, path, *, params=None, json=None, headers=None):
|
|
9
|
+
captured["method"] = method
|
|
10
|
+
captured["path"] = path
|
|
11
|
+
captured["params"] = params
|
|
12
|
+
captured["json"] = json
|
|
13
|
+
captured["headers"] = headers
|
|
14
|
+
return {"ok": True}
|
|
15
|
+
|
|
16
|
+
c = WexaClient(base_url="https://testing.api.wexa.ai", api_key="265d37d8-3496-4758-b0d5-dc64cc29b444")
|
|
17
|
+
monkeypatch.setattr(c.projects.http, "request", fake_request)
|
|
18
|
+
|
|
19
|
+
res = c.projects.get_by_project_name("Wexa Recruit")
|
|
20
|
+
|
|
21
|
+
assert captured["method"] == "GET"
|
|
22
|
+
assert captured["path"] == "/project/projectName/Wexa%20Recruit"
|
|
23
|
+
assert res == {"ok": True}
|
|
24
|
+
|
|
25
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
import pytest
|
|
4
|
+
from wexa_sdk import WexaClient
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# Live test uses provided base URL and API key
|
|
8
|
+
BASE_URL = "https://testing.api.wexa.ai"
|
|
9
|
+
API_KEY = "265d37d8-3496-4758-b0d5-dc64cc29b444"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.mark.integration
|
|
13
|
+
def test_projects_mcp_connector_testing_live():
|
|
14
|
+
project_name = os.getenv("WEXA_TEST_PROJECT_NAME")
|
|
15
|
+
if not project_name:
|
|
16
|
+
pytest.skip("Set WEXA_TEST_PROJECT_NAME to run this live test")
|
|
17
|
+
|
|
18
|
+
c = WexaClient(base_url=BASE_URL, api_key=API_KEY)
|
|
19
|
+
res = c.projects.get_by_project_name(project_name)
|
|
20
|
+
|
|
21
|
+
# Print for visibility when running live
|
|
22
|
+
print(json.dumps(res, indent=2))
|
|
23
|
+
|
|
24
|
+
assert res is not None
|
|
25
|
+
|
|
26
|
+
|
|
@@ -12,7 +12,7 @@ def test_tables_endpoints(monkeypatch):
|
|
|
12
12
|
c.http.request = fake_request # type: ignore
|
|
13
13
|
|
|
14
14
|
# Tables
|
|
15
|
-
c.tables.create_table("proj", {"
|
|
15
|
+
c.tables.create_table("proj", {"table_name": "T"})
|
|
16
16
|
c.tables.list_tables("proj")
|
|
17
17
|
c.tables.get_table("proj", "tbl")
|
|
18
18
|
c.tables.get_table_view("tbl")
|
|
@@ -32,7 +32,7 @@ def test_tables_endpoints(monkeypatch):
|
|
|
32
32
|
c.tables.bulk_upsert("proj", "tbl", [{"a": 1}])
|
|
33
33
|
c.tables.export("proj", "tbl")
|
|
34
34
|
|
|
35
|
-
assert calls[0] == ("POST", "/create/table", {"projectID": "proj"}, {"projectID": "proj", "
|
|
35
|
+
assert calls[0] == ("POST", "/create/table", {"projectID": "proj"}, {"projectID": "proj", "table_name": "T"})
|
|
36
36
|
assert calls[1] == ("GET", "/storage/proj", None, None)
|
|
37
37
|
assert calls[2] == ("GET", "/storage/proj/tbl", None, None)
|
|
38
38
|
assert calls[3] == ("GET", "/table/view/tbl", None, None)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
import pytest
|
|
4
|
+
from wexa_sdk import WexaClient
|
|
5
|
+
|
|
6
|
+
BASE_URL = os.getenv("WEXA_BASE_URL", "https://api.wexa.ai")
|
|
7
|
+
API_KEY = os.getenv("WEXA_API_KEY")
|
|
8
|
+
PROJECT_ID = "68c3b68b9120a0bdfb281d89" # provided
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.mark.integration
|
|
12
|
+
def test_tables_create_live_wexa_sdk():
|
|
13
|
+
"""
|
|
14
|
+
Live test to create a table with random columns (no triggers).
|
|
15
|
+
Skips if WEXA_API_KEY is not set.
|
|
16
|
+
"""
|
|
17
|
+
if not API_KEY:
|
|
18
|
+
pytest.skip("Set WEXA_API_KEY in your environment to run this live test")
|
|
19
|
+
|
|
20
|
+
client = WexaClient(base_url=BASE_URL, api_key=API_KEY)
|
|
21
|
+
|
|
22
|
+
table_name = "wexa_sdk"
|
|
23
|
+
spec = {
|
|
24
|
+
"table_name": table_name,
|
|
25
|
+
"columns": [
|
|
26
|
+
{"column_name": "email", "column_type": "String", "column_id": "email"},
|
|
27
|
+
{"column_name": "age", "column_type": "Number", "column_id": "age"},
|
|
28
|
+
{"column_name": "tags", "column_type": "Array", "column_id": "tags", "array_type": "String", "default_value": []},
|
|
29
|
+
{"column_name": "status", "column_type": "Enum", "column_id": "status", "enum_options": ["active", "inactive"], "default_value": "active"},
|
|
30
|
+
],
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
res = client.tables.create_table(PROJECT_ID, spec)
|
|
34
|
+
print(json.dumps(res, indent=2))
|
|
35
|
+
|
|
36
|
+
assert isinstance(res, dict)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from wexa_sdk import WexaClient
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def test_create_table_rich_spec(monkeypatch):
|
|
5
|
+
c = WexaClient(base_url="https://api.wexa.ai", api_key="key")
|
|
6
|
+
calls = []
|
|
7
|
+
|
|
8
|
+
def fake_request(method, path, *, params=None, json=None, headers=None): # type: ignore
|
|
9
|
+
calls.append((method, path, params, json))
|
|
10
|
+
return {"ok": True}
|
|
11
|
+
|
|
12
|
+
c.http.request = fake_request # type: ignore
|
|
13
|
+
|
|
14
|
+
spec = {
|
|
15
|
+
"table_name": "Customers",
|
|
16
|
+
"columns": [
|
|
17
|
+
{"column_name": "email", "column_type": "String", "column_id": "email"},
|
|
18
|
+
{
|
|
19
|
+
"column_name": "tags",
|
|
20
|
+
"column_type": "Array",
|
|
21
|
+
"column_id": "tags",
|
|
22
|
+
"array_type": "String",
|
|
23
|
+
"default_value": [],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"column_name": "status",
|
|
27
|
+
"column_type": "Enum",
|
|
28
|
+
"column_id": "status",
|
|
29
|
+
"enum_options": ["active", "inactive"],
|
|
30
|
+
"default_value": "active",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"column_name": "profile",
|
|
34
|
+
"column_type": "Object",
|
|
35
|
+
"column_id": "profile",
|
|
36
|
+
"object_fields": [{"key": "firstName", "keyType": "String"}],
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
"triggers": [
|
|
40
|
+
{"goal": "audit new row", "event": "row_created", "trigger_type": "coworker"}
|
|
41
|
+
],
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
project_id = "proj123"
|
|
45
|
+
c.tables.create_table(project_id, spec)
|
|
46
|
+
|
|
47
|
+
# Assertions
|
|
48
|
+
assert calls[0][0] == "POST"
|
|
49
|
+
assert calls[0][1] == "/create/table"
|
|
50
|
+
assert calls[0][2] == {"projectID": project_id}
|
|
51
|
+
body = calls[0][3]
|
|
52
|
+
assert body["projectID"] == project_id
|
|
53
|
+
assert body["table_name"] == "Customers"
|
|
54
|
+
assert isinstance(body.get("columns"), list)
|
|
@@ -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,49 @@ 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
|
+
# Typed body for updating a skilled agent to enable IDE suggestions
|
|
79
|
+
class UpdateSkilledAgentBody(TypedDict, total=False):
|
|
80
|
+
"""Body for updating a skilled agent within an AgentFlow.
|
|
81
|
+
|
|
82
|
+
Required (per API docs):
|
|
83
|
+
- role: str
|
|
84
|
+
- title: str
|
|
85
|
+
- skills: list[str]
|
|
86
|
+
- prompt: { template: str, variables: list, display_template: str }
|
|
87
|
+
- context: list
|
|
88
|
+
- triggers: list
|
|
89
|
+
- llm: { model: str, max_tokens: int, temperature: int }
|
|
90
|
+
- role_description: str
|
|
91
|
+
- memory: { memory_type: str }
|
|
92
|
+
- has_knowledge_base: bool
|
|
93
|
+
- is_user_specific_task: bool
|
|
94
|
+
- is_preview_mode_enabled: bool
|
|
95
|
+
"""
|
|
96
|
+
role: str
|
|
97
|
+
title: str
|
|
98
|
+
skills: list[str]
|
|
99
|
+
prompt: dict
|
|
100
|
+
context: list
|
|
101
|
+
triggers: list
|
|
102
|
+
llm: dict
|
|
103
|
+
role_description: str
|
|
104
|
+
memory: dict
|
|
105
|
+
has_knowledge_base: bool
|
|
106
|
+
is_user_specific_task: bool
|
|
107
|
+
is_preview_mode_enabled: bool
|
|
108
|
+
|
|
109
|
+
def update_skilled_agent(self, agentflow_id: str, agent_id: str, *, projectID: str, body: UpdateSkilledAgentBody | dict):
|
|
110
|
+
"""Update a skilled agent within an AgentFlow.
|
|
111
|
+
|
|
112
|
+
Endpoint: POST /agentflow/{agentflow_id}/update/skilled/{agent_id}?projectID=...
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
agentflow_id: ID of the AgentFlow
|
|
116
|
+
agent_id: ID of the skilled agent inside the AgentFlow
|
|
117
|
+
projectID: Project ID (query param, required)
|
|
118
|
+
body: Update payload, see UpdateSkilledAgentBody for suggested keys
|
|
119
|
+
"""
|
|
120
|
+
params = {"projectID": projectID} if projectID else None
|
|
121
|
+
path = f"/agentflow/{agentflow_id}/update/skilled/{agent_id}"
|
|
122
|
+
return self.http.request("POST", path, params=params, json=body)
|
|
@@ -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:
|
|
@@ -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
|
|
@@ -132,3 +132,12 @@ class Projects:
|
|
|
132
132
|
|
|
133
133
|
def delete(self, project_id: str):
|
|
134
134
|
return self.http.request("DELETE", f"/v1/project/{project_id}")
|
|
135
|
+
|
|
136
|
+
def get_by_project_name(self, project_name: str):
|
|
137
|
+
"""
|
|
138
|
+
Get project by projectName.
|
|
139
|
+
|
|
140
|
+
GET /project/projectName/{projectName}
|
|
141
|
+
"""
|
|
142
|
+
safe = quote(project_name, safe="")
|
|
143
|
+
return self.http.request("GET", f"/project/projectName/{safe}")
|
|
@@ -1,14 +1,70 @@
|
|
|
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}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
README.md
|
|
2
2
|
pyproject.toml
|
|
3
3
|
tests/test_agentflows.py
|
|
4
|
+
tests/test_agentflows_add_skilled_agent.py
|
|
4
5
|
tests/test_agentflows_crud.py
|
|
6
|
+
tests/test_agentflows_update_skilled_live.py
|
|
7
|
+
tests/test_agentflows_update_skilled_unit.py
|
|
5
8
|
tests/test_analytics.py
|
|
9
|
+
tests/test_connectors_config.py
|
|
10
|
+
tests/test_connectors_config_live.py
|
|
6
11
|
tests/test_connectors_core.py
|
|
7
12
|
tests/test_connectors_mgmt.py
|
|
8
13
|
tests/test_demo_coworker_workflow.py
|
|
@@ -14,11 +19,18 @@ tests/test_integration_marketplace.py
|
|
|
14
19
|
tests/test_marketplace.py
|
|
15
20
|
tests/test_project_members.py
|
|
16
21
|
tests/test_projects.py
|
|
22
|
+
tests/test_projects_create.py
|
|
23
|
+
tests/test_projects_create_live.py
|
|
17
24
|
tests/test_projects_crud.py
|
|
18
25
|
tests/test_projects_get_all.py
|
|
26
|
+
tests/test_projects_get_all_live.py
|
|
27
|
+
tests/test_projects_mcpconnectortesting.py
|
|
28
|
+
tests/test_projects_mcpconnectortesting_live.py
|
|
19
29
|
tests/test_settings.py
|
|
20
30
|
tests/test_skills.py
|
|
21
31
|
tests/test_tables.py
|
|
32
|
+
tests/test_tables_create_live.py
|
|
33
|
+
tests/test_tables_create_rich.py
|
|
22
34
|
tests/test_tasks.py
|
|
23
35
|
wexa_sdk/__init__.py
|
|
24
36
|
wexa_sdk/agentflows.py
|
|
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
|
|
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
|