deploypod 0.1.0__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.
- deploypod/__init__.py +31 -0
- deploypod/_http.py +73 -0
- deploypod/auth.py +90 -0
- deploypod/client.py +122 -0
- deploypod/env.py +49 -0
- deploypod/exceptions.py +39 -0
- deploypod/py.typed +0 -0
- deploypod/resources/__init__.py +0 -0
- deploypod/resources/agents.py +430 -0
- deploypod/resources/async_tasks.py +84 -0
- deploypod/resources/connections.py +57 -0
- deploypod/resources/conversations.py +41 -0
- deploypod/resources/custom_tools.py +126 -0
- deploypod/resources/groups.py +71 -0
- deploypod/resources/jobs.py +28 -0
- deploypod/resources/knowledge_bases.py +47 -0
- deploypod/resources/knowledge_sources.py +141 -0
- deploypod/resources/mcp_servers.py +117 -0
- deploypod/resources/organization.py +150 -0
- deploypod/resources/providers.py +64 -0
- deploypod/resources/skills.py +75 -0
- deploypod/resources/users.py +56 -0
- deploypod/types.py +390 -0
- deploypod-0.1.0.dist-info/METADATA +104 -0
- deploypod-0.1.0.dist-info/RECORD +28 -0
- deploypod-0.1.0.dist-info/WHEEL +5 -0
- deploypod-0.1.0.dist-info/licenses/LICENSE +21 -0
- deploypod-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
|
|
7
|
+
from deploypod._http import message_result, raise_for_status
|
|
8
|
+
from deploypod.types import LLMModelResponse, LLMProviderResponse, MessageResult
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ProvidersResource:
|
|
12
|
+
def __init__(self, http: httpx.Client):
|
|
13
|
+
self._http = http
|
|
14
|
+
|
|
15
|
+
def create(self, *, provider_type: str, **kwargs: Any) -> LLMProviderResponse:
|
|
16
|
+
payload = {"provider_type": provider_type, **kwargs}
|
|
17
|
+
resp = self._http.post("/llm-providers/", json=payload)
|
|
18
|
+
raise_for_status(resp)
|
|
19
|
+
return LLMProviderResponse(**resp.json())
|
|
20
|
+
|
|
21
|
+
def list(self) -> list[LLMProviderResponse]:
|
|
22
|
+
resp = self._http.get("/llm-providers/")
|
|
23
|
+
raise_for_status(resp)
|
|
24
|
+
return [LLMProviderResponse(**p) for p in resp.json()]
|
|
25
|
+
|
|
26
|
+
def get(self, provider_id: int) -> LLMProviderResponse:
|
|
27
|
+
resp = self._http.get(f"/llm-providers/{provider_id}")
|
|
28
|
+
raise_for_status(resp)
|
|
29
|
+
return LLMProviderResponse(**resp.json())
|
|
30
|
+
|
|
31
|
+
def get_default(self) -> LLMProviderResponse:
|
|
32
|
+
resp = self._http.get("/llm-providers/default")
|
|
33
|
+
raise_for_status(resp)
|
|
34
|
+
return LLMProviderResponse(**resp.json())
|
|
35
|
+
|
|
36
|
+
def update(self, provider_id: int, **kwargs: Any) -> LLMProviderResponse:
|
|
37
|
+
resp = self._http.put(f"/llm-providers/{provider_id}", json=kwargs)
|
|
38
|
+
raise_for_status(resp)
|
|
39
|
+
return LLMProviderResponse(**resp.json())
|
|
40
|
+
|
|
41
|
+
def delete(self, provider_id: int) -> MessageResult:
|
|
42
|
+
resp = self._http.delete(f"/llm-providers/{provider_id}")
|
|
43
|
+
raise_for_status(resp)
|
|
44
|
+
return message_result(resp)
|
|
45
|
+
|
|
46
|
+
def test(self, provider_id: int) -> dict:
|
|
47
|
+
resp = self._http.post(f"/llm-providers/{provider_id}/test")
|
|
48
|
+
raise_for_status(resp)
|
|
49
|
+
return resp.json()
|
|
50
|
+
|
|
51
|
+
def list_models(self, provider_id: int) -> list[dict]:
|
|
52
|
+
resp = self._http.get(f"/llm-providers/{provider_id}/models")
|
|
53
|
+
raise_for_status(resp)
|
|
54
|
+
return resp.json()
|
|
55
|
+
|
|
56
|
+
def set_default(self, provider_id: int) -> dict:
|
|
57
|
+
resp = self._http.post(f"/llm-providers/{provider_id}/set-default")
|
|
58
|
+
raise_for_status(resp)
|
|
59
|
+
return resp.json()
|
|
60
|
+
|
|
61
|
+
def discover_vllm(self) -> dict:
|
|
62
|
+
resp = self._http.post("/llm-providers/discover-vllm")
|
|
63
|
+
raise_for_status(resp)
|
|
64
|
+
return resp.json()
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, List
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
|
|
7
|
+
from deploypod._http import message_result, raise_for_status
|
|
8
|
+
from deploypod.types import MessageResult, SkillResponse
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SkillsResource:
|
|
12
|
+
def __init__(self, http: httpx.Client):
|
|
13
|
+
self._http = http
|
|
14
|
+
|
|
15
|
+
def create(
|
|
16
|
+
self,
|
|
17
|
+
*,
|
|
18
|
+
name: str,
|
|
19
|
+
slug: str,
|
|
20
|
+
description: str | None = None,
|
|
21
|
+
invocation_mode: str = "always_on",
|
|
22
|
+
prompt_instructions: str | None = None,
|
|
23
|
+
examples: list[dict[str, Any]] | None = None,
|
|
24
|
+
allowed_tools: list[str] | None = None,
|
|
25
|
+
additional_tools: list[dict[str, Any]] | None = None,
|
|
26
|
+
) -> SkillResponse:
|
|
27
|
+
payload: dict[str, Any] = {"name": name, "slug": slug, "invocation_mode": invocation_mode}
|
|
28
|
+
if description is not None:
|
|
29
|
+
payload["description"] = description
|
|
30
|
+
if prompt_instructions is not None:
|
|
31
|
+
payload["prompt_instructions"] = prompt_instructions
|
|
32
|
+
if examples is not None:
|
|
33
|
+
payload["examples"] = examples
|
|
34
|
+
if allowed_tools is not None:
|
|
35
|
+
payload["allowed_tools"] = allowed_tools
|
|
36
|
+
if additional_tools is not None:
|
|
37
|
+
payload["additional_tools"] = additional_tools
|
|
38
|
+
resp = self._http.post("/skills/", json=payload)
|
|
39
|
+
raise_for_status(resp)
|
|
40
|
+
return SkillResponse(**resp.json())
|
|
41
|
+
|
|
42
|
+
def list(self) -> list[SkillResponse]:
|
|
43
|
+
resp = self._http.get("/skills/")
|
|
44
|
+
raise_for_status(resp)
|
|
45
|
+
return [SkillResponse(**s) for s in resp.json()]
|
|
46
|
+
|
|
47
|
+
def get(self, skill_id: int) -> SkillResponse:
|
|
48
|
+
resp = self._http.get(f"/skills/{skill_id}")
|
|
49
|
+
raise_for_status(resp)
|
|
50
|
+
return SkillResponse(**resp.json())
|
|
51
|
+
|
|
52
|
+
def update(self, skill_id: int, **kwargs: Any) -> SkillResponse:
|
|
53
|
+
resp = self._http.put(f"/skills/{skill_id}", json=kwargs)
|
|
54
|
+
raise_for_status(resp)
|
|
55
|
+
return SkillResponse(**resp.json())
|
|
56
|
+
|
|
57
|
+
def delete(self, skill_id: int) -> MessageResult:
|
|
58
|
+
resp = self._http.delete(f"/skills/{skill_id}")
|
|
59
|
+
raise_for_status(resp)
|
|
60
|
+
return message_result(resp)
|
|
61
|
+
|
|
62
|
+
def assign_to_agent(self, skill_id: int, agent_id: int) -> MessageResult:
|
|
63
|
+
resp = self._http.post(f"/skills/{skill_id}/agents/{agent_id}")
|
|
64
|
+
raise_for_status(resp)
|
|
65
|
+
return message_result(resp)
|
|
66
|
+
|
|
67
|
+
def remove_from_agent(self, skill_id: int, agent_id: int) -> MessageResult:
|
|
68
|
+
resp = self._http.delete(f"/skills/{skill_id}/agents/{agent_id}")
|
|
69
|
+
raise_for_status(resp)
|
|
70
|
+
return message_result(resp)
|
|
71
|
+
|
|
72
|
+
def list_for_agent(self, agent_id: int) -> list[SkillResponse]:
|
|
73
|
+
resp = self._http.get(f"/skills/agents/{agent_id}/skills/")
|
|
74
|
+
raise_for_status(resp)
|
|
75
|
+
return [SkillResponse(**s) for s in resp.json()]
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
|
|
7
|
+
from deploypod._http import message_result, raise_for_status
|
|
8
|
+
from deploypod.types import MessageResult, UserResponse
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class UsersResource:
|
|
12
|
+
def __init__(self, http: httpx.Client):
|
|
13
|
+
self._http = http
|
|
14
|
+
|
|
15
|
+
def create(
|
|
16
|
+
self,
|
|
17
|
+
*,
|
|
18
|
+
email: str,
|
|
19
|
+
roles: list[str] | None = None,
|
|
20
|
+
username: str | None = None,
|
|
21
|
+
deployed_agent_slug: str | None = None,
|
|
22
|
+
send_password_email: bool = False,
|
|
23
|
+
app_url: str | None = None,
|
|
24
|
+
) -> UserResponse:
|
|
25
|
+
payload: dict[str, Any] = {"email": email, "send_password_email": send_password_email}
|
|
26
|
+
if roles is not None:
|
|
27
|
+
payload["roles"] = roles
|
|
28
|
+
if username is not None:
|
|
29
|
+
payload["username"] = username
|
|
30
|
+
if deployed_agent_slug is not None:
|
|
31
|
+
payload["deployed_agent_slug"] = deployed_agent_slug
|
|
32
|
+
if app_url is not None:
|
|
33
|
+
payload["app_url"] = app_url
|
|
34
|
+
resp = self._http.post("/user/create-user", json=payload)
|
|
35
|
+
raise_for_status(resp)
|
|
36
|
+
return UserResponse(**resp.json())
|
|
37
|
+
|
|
38
|
+
def list(self) -> list[UserResponse]:
|
|
39
|
+
resp = self._http.get("/user/list")
|
|
40
|
+
raise_for_status(resp)
|
|
41
|
+
return [UserResponse(**u) for u in resp.json()]
|
|
42
|
+
|
|
43
|
+
def update_roles(self, user_id: str, roles: list[str]) -> dict:
|
|
44
|
+
resp = self._http.put(f"/user/{user_id}/roles", json={"roles": roles})
|
|
45
|
+
raise_for_status(resp)
|
|
46
|
+
return resp.json()
|
|
47
|
+
|
|
48
|
+
def delete(self, user_id: str) -> MessageResult:
|
|
49
|
+
resp = self._http.delete(f"/user/{user_id}")
|
|
50
|
+
raise_for_status(resp)
|
|
51
|
+
return message_result(resp)
|
|
52
|
+
|
|
53
|
+
def my_groups(self) -> list[dict]:
|
|
54
|
+
resp = self._http.get("/user/me/groups")
|
|
55
|
+
raise_for_status(resp)
|
|
56
|
+
return resp.json()
|
deploypod/types.py
ADDED
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
"""Response models mirroring the Deploypod API."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from typing import Any, Dict, List, Optional, Union
|
|
7
|
+
from uuid import UUID
|
|
8
|
+
|
|
9
|
+
from pydantic import BaseModel, field_validator
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# ── Agents ───────────────────────────────────────────────────────────
|
|
13
|
+
|
|
14
|
+
class WelcomeMessageResponse(BaseModel):
|
|
15
|
+
id: UUID
|
|
16
|
+
name: str
|
|
17
|
+
message: str
|
|
18
|
+
is_template: bool
|
|
19
|
+
template_variables: Optional[List[str]] = None
|
|
20
|
+
created_at: datetime
|
|
21
|
+
updated_at: datetime
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class WalkthroughQuestionResponse(BaseModel):
|
|
25
|
+
id: UUID
|
|
26
|
+
question_text: str
|
|
27
|
+
description: Optional[str] = None
|
|
28
|
+
display_order: Optional[int] = None
|
|
29
|
+
category: Optional[str] = None
|
|
30
|
+
is_active: Optional[bool] = None
|
|
31
|
+
created_at: Optional[datetime] = None
|
|
32
|
+
updated_at: Optional[datetime] = None
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class AgentResponse(BaseModel):
|
|
36
|
+
id: int
|
|
37
|
+
uuid: UUID
|
|
38
|
+
org_id: int
|
|
39
|
+
name: str
|
|
40
|
+
group_id: Optional[int] = None
|
|
41
|
+
group_name: Optional[str] = None
|
|
42
|
+
knowledge_base_ids: List[int] = []
|
|
43
|
+
writable_kb_ids: Optional[List[int]] = None
|
|
44
|
+
llm_provider_id: Optional[int] = None
|
|
45
|
+
llm_model: Optional[str] = None
|
|
46
|
+
system_prompt_extension: Optional[str] = None
|
|
47
|
+
# JSON-Schema object the final answer is forced into (emit_result).
|
|
48
|
+
output_schema: Optional[dict[str, Any]] = None
|
|
49
|
+
autonomy_mode: str = "interactive"
|
|
50
|
+
can_use_web_search: bool = False
|
|
51
|
+
# Every web query the agent sends waits for a person's approval.
|
|
52
|
+
web_confirmation_required: bool = False
|
|
53
|
+
table_manager_enabled: bool = False
|
|
54
|
+
tts_provider: Optional[str] = None
|
|
55
|
+
tts_model: Optional[str] = None
|
|
56
|
+
tts_voice: Optional[str] = None
|
|
57
|
+
voice_id: Optional[str] = None
|
|
58
|
+
speech_speed: Optional[float] = 1.0
|
|
59
|
+
config: Optional[Dict[str, Any]] = None
|
|
60
|
+
third_party_auth_enabled: bool = False
|
|
61
|
+
welcome_messages: Optional[List[str]] = None
|
|
62
|
+
welcome_message_relationships: Optional[List[WelcomeMessageResponse]] = None
|
|
63
|
+
walkthrough_question_relationships: Optional[List[WalkthroughQuestionResponse]] = None
|
|
64
|
+
subagent_relationships: Optional[List[Dict[str, Any]]] = None
|
|
65
|
+
user_permission_level: Optional[str] = None
|
|
66
|
+
created_at: datetime
|
|
67
|
+
updated_at: datetime
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class ThirdPartyAuthResponse(BaseModel):
|
|
71
|
+
shared_secret_key: str
|
|
72
|
+
message: str
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class DeploymentResponse(BaseModel):
|
|
76
|
+
slug: Optional[str] = None
|
|
77
|
+
deployed: bool = False
|
|
78
|
+
message: Optional[str] = None
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
# ── Knowledge Bases ──────────────────────────────────────────────────
|
|
82
|
+
|
|
83
|
+
class KnowledgeBaseResponse(BaseModel):
|
|
84
|
+
id: int
|
|
85
|
+
org_id: int
|
|
86
|
+
name: str
|
|
87
|
+
description: Optional[str] = None
|
|
88
|
+
created_at: datetime
|
|
89
|
+
group_id: Optional[int] = None
|
|
90
|
+
group_name: Optional[str] = None
|
|
91
|
+
has_navigation: Optional[bool] = None
|
|
92
|
+
navigation_status: Optional[str] = None
|
|
93
|
+
user_permission_level: Optional[str] = None
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class KBConstraintsResponse(BaseModel):
|
|
97
|
+
max_navigation_sources: int
|
|
98
|
+
max_navigation_kbs_per_agent: int
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
# ── Knowledge Sources ────────────────────────────────────────────────
|
|
102
|
+
|
|
103
|
+
class KnowledgeSourceResponse(BaseModel):
|
|
104
|
+
id: int
|
|
105
|
+
name: str
|
|
106
|
+
source_identifier: str
|
|
107
|
+
status: str
|
|
108
|
+
purpose: str
|
|
109
|
+
source_type: str
|
|
110
|
+
created_at: datetime
|
|
111
|
+
last_processed_at: Optional[datetime] = None
|
|
112
|
+
error_message: Optional[str] = None
|
|
113
|
+
options: Optional[Dict[str, Any]] = None
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
# ── Skills ───────────────────────────────────────────────────────────
|
|
117
|
+
|
|
118
|
+
class SkillResponse(BaseModel):
|
|
119
|
+
id: int
|
|
120
|
+
uuid: str
|
|
121
|
+
organization_id: int
|
|
122
|
+
name: str
|
|
123
|
+
slug: str
|
|
124
|
+
description: Optional[str] = None
|
|
125
|
+
invocation_mode: str
|
|
126
|
+
prompt_instructions: Optional[str] = None
|
|
127
|
+
examples: Optional[Any] = None
|
|
128
|
+
allowed_tools: Optional[List[str]] = None
|
|
129
|
+
additional_tools: Optional[List[Dict[str, Any]]] = None
|
|
130
|
+
is_active: bool
|
|
131
|
+
created_by: Optional[str] = None
|
|
132
|
+
created_at: Optional[datetime] = None
|
|
133
|
+
updated_at: Optional[datetime] = None
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
# ── Custom Tools ─────────────────────────────────────────────────────
|
|
137
|
+
|
|
138
|
+
class CustomToolResponse(BaseModel):
|
|
139
|
+
id: int
|
|
140
|
+
org_id: int
|
|
141
|
+
name: str
|
|
142
|
+
description: Optional[str] = None
|
|
143
|
+
tool_type: str
|
|
144
|
+
method: Optional[str] = None
|
|
145
|
+
url: Optional[str] = None
|
|
146
|
+
parameters: Optional[Union[List[Dict[str, Any]], Dict[str, Any]]] = None
|
|
147
|
+
headers: Optional[Union[List[Dict[str, Any]], Dict[str, Any]]] = None
|
|
148
|
+
body_template: Optional[Dict[str, Any]] = None
|
|
149
|
+
response_mapping: Optional[Dict[str, Any]] = None
|
|
150
|
+
group_id: Optional[int] = None
|
|
151
|
+
created_at: Optional[datetime] = None
|
|
152
|
+
updated_at: Optional[datetime] = None
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class ToolExecutionResponse(BaseModel):
|
|
156
|
+
id: int
|
|
157
|
+
tool_id: int
|
|
158
|
+
status: str
|
|
159
|
+
response_data: Optional[Dict[str, Any]] = None
|
|
160
|
+
error_message: Optional[str] = None
|
|
161
|
+
execution_time_ms: Optional[float] = None
|
|
162
|
+
created_at: Optional[datetime] = None
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
# ── MCP Servers ──────────────────────────────────────────────────────
|
|
166
|
+
|
|
167
|
+
class MCPToolResponse(BaseModel):
|
|
168
|
+
id: int
|
|
169
|
+
mcp_server_id: Optional[int] = None
|
|
170
|
+
tool_name: Optional[str] = None
|
|
171
|
+
name: Optional[str] = None
|
|
172
|
+
description: Optional[str] = None
|
|
173
|
+
input_schema: Optional[Dict[str, Any]] = None
|
|
174
|
+
parameters_schema: Optional[Dict[str, Any]] = None
|
|
175
|
+
is_enabled: bool = True
|
|
176
|
+
created_at: Optional[datetime] = None
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
class MCPServerResponse(BaseModel):
|
|
180
|
+
id: int
|
|
181
|
+
org_id: Optional[int] = None
|
|
182
|
+
name: str
|
|
183
|
+
description: Optional[str] = None
|
|
184
|
+
endpoint_url: Optional[str] = None
|
|
185
|
+
server_type: Optional[str] = None
|
|
186
|
+
is_active: bool = True
|
|
187
|
+
health_status: Optional[str] = None
|
|
188
|
+
last_heartbeat: Optional[datetime] = None
|
|
189
|
+
group_id: Optional[int] = None
|
|
190
|
+
timeout_seconds: Optional[int] = None
|
|
191
|
+
retry_attempts: Optional[int] = None
|
|
192
|
+
tools: Optional[List[MCPToolResponse]] = None
|
|
193
|
+
created_at: Optional[datetime] = None
|
|
194
|
+
updated_at: Optional[datetime] = None
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
# ── LLM Providers ───────────────────────────────────────────────────
|
|
198
|
+
|
|
199
|
+
class LLMProviderResponse(BaseModel):
|
|
200
|
+
id: int
|
|
201
|
+
org_id: int
|
|
202
|
+
provider_type: str
|
|
203
|
+
name: Optional[str] = None
|
|
204
|
+
api_base: Optional[str] = None
|
|
205
|
+
is_default: bool = False
|
|
206
|
+
created_at: Optional[datetime] = None
|
|
207
|
+
updated_at: Optional[datetime] = None
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
class LLMModelResponse(BaseModel):
|
|
211
|
+
id: str
|
|
212
|
+
name: Optional[str] = None
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
# ── Database Connections ─────────────────────────────────────────────
|
|
216
|
+
|
|
217
|
+
class ConnectionResponse(BaseModel):
|
|
218
|
+
id: int
|
|
219
|
+
org_id: int
|
|
220
|
+
name: str
|
|
221
|
+
db_type: str
|
|
222
|
+
host: Optional[str] = None
|
|
223
|
+
port: Optional[int] = None
|
|
224
|
+
database: Optional[str] = None
|
|
225
|
+
status: Optional[str] = None
|
|
226
|
+
created_at: Optional[datetime] = None
|
|
227
|
+
updated_at: Optional[datetime] = None
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class TableResponse(BaseModel):
|
|
231
|
+
id: int
|
|
232
|
+
connection_id: int
|
|
233
|
+
name: str
|
|
234
|
+
schema_info: Optional[Dict[str, Any]] = None
|
|
235
|
+
row_count: Optional[int] = None
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
# ── Conversations ────────────────────────────────────────────────────
|
|
239
|
+
|
|
240
|
+
class ConversationResponse(BaseModel):
|
|
241
|
+
id: UUID
|
|
242
|
+
user_id: Optional[str] = None
|
|
243
|
+
session_id: Optional[str] = None
|
|
244
|
+
org_id: int
|
|
245
|
+
agent_id: int
|
|
246
|
+
title: Optional[str] = None
|
|
247
|
+
created_at: datetime
|
|
248
|
+
message_count: int
|
|
249
|
+
agent_name: Optional[str] = None
|
|
250
|
+
username: Optional[str] = None
|
|
251
|
+
session_status: Optional[str] = None
|
|
252
|
+
session_display_status: Optional[str] = None
|
|
253
|
+
last_activity_at: Optional[datetime] = None
|
|
254
|
+
session_expires_at: Optional[datetime] = None
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
class MessageResponse(BaseModel):
|
|
258
|
+
id: int
|
|
259
|
+
conversation_id: UUID
|
|
260
|
+
sender: str
|
|
261
|
+
content: str
|
|
262
|
+
timestamp: datetime
|
|
263
|
+
response_metadata: Optional[Dict] = None
|
|
264
|
+
iterations: Optional[List[Dict]] = None
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
class ConversationDetailResponse(BaseModel):
|
|
268
|
+
conversation: ConversationResponse
|
|
269
|
+
messages: List[MessageResponse]
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
# ── Users ────────────────────────────────────────────────────────────
|
|
273
|
+
|
|
274
|
+
class UserGroupMembershipInfo(BaseModel):
|
|
275
|
+
group_id: int
|
|
276
|
+
group_name: str
|
|
277
|
+
permission_level: str
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
class UserResponse(BaseModel):
|
|
281
|
+
id: str
|
|
282
|
+
username: str
|
|
283
|
+
email: str
|
|
284
|
+
org_id: int
|
|
285
|
+
roles: Optional[List[str]] = None
|
|
286
|
+
created_at: Optional[datetime] = None
|
|
287
|
+
group_memberships: Optional[List[UserGroupMembershipInfo]] = None
|
|
288
|
+
# Only on create-user: whether the login email went out, and the
|
|
289
|
+
# temporary password, returned this once.
|
|
290
|
+
email_sent: Optional[bool] = None
|
|
291
|
+
email_error: Optional[str] = None
|
|
292
|
+
temp_password: Optional[str] = None
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
# ── Groups ───────────────────────────────────────────────────────────
|
|
296
|
+
|
|
297
|
+
class GroupResponse(BaseModel):
|
|
298
|
+
id: int
|
|
299
|
+
uuid: Optional[UUID] = None
|
|
300
|
+
org_id: int
|
|
301
|
+
name: str
|
|
302
|
+
created_at: Optional[datetime] = None
|
|
303
|
+
updated_at: Optional[datetime] = None
|
|
304
|
+
member_count: Optional[int] = None
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
class GroupMemberResponse(BaseModel):
|
|
308
|
+
user_id: str
|
|
309
|
+
username: Optional[str] = None
|
|
310
|
+
email: Optional[str] = None
|
|
311
|
+
permission_level: str
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
# ── Organization ─────────────────────────────────────────────────────
|
|
315
|
+
|
|
316
|
+
class LicenseInfoResponse(BaseModel):
|
|
317
|
+
tier: str
|
|
318
|
+
status: str
|
|
319
|
+
limits: Dict[str, Any]
|
|
320
|
+
current_usage: Dict[str, Any]
|
|
321
|
+
expires_at: Optional[str] = None
|
|
322
|
+
features: Dict[str, Any]
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
# ── Async Tasks ──────────────────────────────────────────────────────
|
|
326
|
+
|
|
327
|
+
class AsyncTaskResponse(BaseModel):
|
|
328
|
+
id: int
|
|
329
|
+
agent_id: int
|
|
330
|
+
name: str
|
|
331
|
+
prompt: str
|
|
332
|
+
schedule_cron: str
|
|
333
|
+
timeout_seconds: Optional[int] = None
|
|
334
|
+
enabled: bool = True
|
|
335
|
+
next_run_at: Optional[datetime] = None
|
|
336
|
+
created_at: Optional[datetime] = None
|
|
337
|
+
updated_at: Optional[datetime] = None
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
class AsyncRunResponse(BaseModel):
|
|
341
|
+
id: int
|
|
342
|
+
task_id: int
|
|
343
|
+
status: str
|
|
344
|
+
result_data: Optional[Dict[str, Any]] = None
|
|
345
|
+
result_summary: Optional[str] = None
|
|
346
|
+
error_message: Optional[str] = None
|
|
347
|
+
execution_time_ms: Optional[float] = None
|
|
348
|
+
started_at: Optional[datetime] = None
|
|
349
|
+
completed_at: Optional[datetime] = None
|
|
350
|
+
|
|
351
|
+
@field_validator("result_data", mode="before")
|
|
352
|
+
@classmethod
|
|
353
|
+
def _parse_result_data(cls, v: Any) -> Any:
|
|
354
|
+
if isinstance(v, str):
|
|
355
|
+
import json
|
|
356
|
+
return json.loads(v)
|
|
357
|
+
return v
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
# ── Jobs ─────────────────────────────────────────────────────────────
|
|
361
|
+
|
|
362
|
+
class JobResponse(BaseModel):
|
|
363
|
+
id: int
|
|
364
|
+
status: str
|
|
365
|
+
job_type: Optional[str] = None
|
|
366
|
+
progress: Optional[float] = None
|
|
367
|
+
error_message: Optional[str] = None
|
|
368
|
+
created_at: Optional[datetime] = None
|
|
369
|
+
updated_at: Optional[datetime] = None
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
# ── Pruning ──────────────────────────────────────────────────────────
|
|
373
|
+
|
|
374
|
+
class TestPruningResponse(BaseModel):
|
|
375
|
+
total_tables: int
|
|
376
|
+
total_tools: int
|
|
377
|
+
selected_tables: list[str]
|
|
378
|
+
selected_tools: list[str]
|
|
379
|
+
duration_ms: int
|
|
380
|
+
source_pruning_active: bool
|
|
381
|
+
tool_pruning_active: bool
|
|
382
|
+
source_threshold: int
|
|
383
|
+
tool_threshold: int
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
# ── Generic ──────────────────────────────────────────────────────────
|
|
387
|
+
|
|
388
|
+
class MessageResult(BaseModel):
|
|
389
|
+
"""Generic {message: ...} response from delete/assign endpoints."""
|
|
390
|
+
message: str
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: deploypod
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python client for the Deploypod API: run AI agents, manage their tools and knowledge bases.
|
|
5
|
+
Author: Deploypod
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://deploypod.ai
|
|
8
|
+
Project-URL: Documentation, https://docs.deploypod.ai/en/gelistirici/sdk-ve-widget/
|
|
9
|
+
Keywords: deploypod,ai,agents,llm,sdk
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Typing :: Typed
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: httpx>=0.25.0
|
|
20
|
+
Requires-Dist: pydantic>=2.0
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
23
|
+
Requires-Dist: pytest-httpx>=0.30.0; extra == "dev"
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# Deploypod Python SDK
|
|
27
|
+
|
|
28
|
+
The Python client for the [Deploypod](https://deploypod.ai) API. Run your AI
|
|
29
|
+
agents from code, and manage their instructions, tools and knowledge bases.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install deploypod
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Python 3.9 or newer.
|
|
36
|
+
|
|
37
|
+
## Sign in
|
|
38
|
+
|
|
39
|
+
Ask your Deploypod administrator for an application (`app_id`, `app_secret`)
|
|
40
|
+
and your organization's number. The client gets the access token itself and
|
|
41
|
+
renews it before it expires.
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from deploypod import DeploypodClient
|
|
45
|
+
|
|
46
|
+
client = DeploypodClient(
|
|
47
|
+
org_id="42",
|
|
48
|
+
app_id="YOUR_APP_ID",
|
|
49
|
+
app_secret="YOUR_APP_SECRET",
|
|
50
|
+
)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Keep `app_secret` out of your code: read it from the environment.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
export DEPLOYPOD_ORG_ID=42
|
|
57
|
+
export DEPLOYPOD_APP_ID=...
|
|
58
|
+
export DEPLOYPOD_APP_SECRET=...
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from deploypod import get_client_from_env
|
|
63
|
+
|
|
64
|
+
client = get_client_from_env()
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Already have an access token? Pass `token="..."` instead of the app
|
|
68
|
+
credentials. For an on-premises installation, pass
|
|
69
|
+
`base_url="https://your-host/api"`.
|
|
70
|
+
|
|
71
|
+
## Run an agent
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
for agent in client.agents.list():
|
|
75
|
+
print(agent.uuid, agent.name)
|
|
76
|
+
|
|
77
|
+
result = client.agents.run(
|
|
78
|
+
"AGENT_UUID",
|
|
79
|
+
"How many days of annual leave do I have?",
|
|
80
|
+
run_exploration=True,
|
|
81
|
+
timeout=300,
|
|
82
|
+
)
|
|
83
|
+
print(result["result_summary"])
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
`run` waits for the answer. Other request fields go in as keyword arguments,
|
|
87
|
+
for example `output_schema={...}` to get the answer as JSON in
|
|
88
|
+
`result["final_emit"]`. Requests through `deploypod.ai` are cut after 100
|
|
89
|
+
seconds; for longer work (web research, presentations) use the WebSocket API.
|
|
90
|
+
|
|
91
|
+
## Errors
|
|
92
|
+
|
|
93
|
+
Every error is a `deploypod.DeploypodError` with `status_code` and `detail`.
|
|
94
|
+
Subclasses: `AuthenticationError` (401/403), `NotFoundError`,
|
|
95
|
+
`ValidationError`, `ConflictError`, `LicenseError`, `ServerError`.
|
|
96
|
+
|
|
97
|
+
## Documentation
|
|
98
|
+
|
|
99
|
+
Full guides, the REST and WebSocket APIs, and the chat widget:
|
|
100
|
+
<https://docs.deploypod.ai/en/>
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
MIT
|