crewdeck 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- crewdeck-0.1.0/LICENSE +21 -0
- crewdeck-0.1.0/PKG-INFO +240 -0
- crewdeck-0.1.0/README.md +208 -0
- crewdeck-0.1.0/crewdeck/__init__.py +43 -0
- crewdeck-0.1.0/crewdeck/client.py +395 -0
- crewdeck-0.1.0/crewdeck/exceptions.py +35 -0
- crewdeck-0.1.0/crewdeck/models.py +103 -0
- crewdeck-0.1.0/pyproject.toml +55 -0
crewdeck-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 CrewDeck
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
crewdeck-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: crewdeck
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for CrewDeck - AI agent management dashboard
|
|
5
|
+
Project-URL: Homepage, https://crewdeck.dev
|
|
6
|
+
Project-URL: Documentation, https://docs.crewdeck.dev
|
|
7
|
+
Project-URL: Repository, https://github.com/crewdeck/crewdeck-python
|
|
8
|
+
Author-email: CrewDeck <hello@crewdeck.dev>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agents,ai,autogen,crewai,dashboard,langchain,management
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Requires-Python: >=3.8
|
|
23
|
+
Requires-Dist: httpx>=0.24.0
|
|
24
|
+
Provides-Extra: async
|
|
25
|
+
Requires-Dist: httpx[http2]>=0.24.0; extra == 'async'
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: black>=23.0.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# CrewDeck Python SDK
|
|
34
|
+
|
|
35
|
+
Official Python SDK for [CrewDeck](https://crewdeck.dev) — the AI agent management dashboard.
|
|
36
|
+
|
|
37
|
+
Manage your AI crew like a real team. Assign tasks, track progress, review outputs, approve results.
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install crewdeck
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from crewdeck import CrewDeck
|
|
49
|
+
|
|
50
|
+
# Initialize with your API key
|
|
51
|
+
deck = CrewDeck(api_key="your-api-key")
|
|
52
|
+
|
|
53
|
+
# Create a task
|
|
54
|
+
task = deck.tasks.create(
|
|
55
|
+
title="Analyze Q4 sales data",
|
|
56
|
+
description="Process and summarize the quarterly sales report",
|
|
57
|
+
priority="high",
|
|
58
|
+
assignees=["JARVIS"]
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# Update agent status
|
|
62
|
+
deck.agents.set_working("JARVIS")
|
|
63
|
+
|
|
64
|
+
# Send progress updates
|
|
65
|
+
deck.events.message("Starting data analysis...", agent_name="JARVIS")
|
|
66
|
+
|
|
67
|
+
# Complete the task with output
|
|
68
|
+
deck.tasks.complete(task.id, output="Analysis complete. Revenue up 15% YoY.")
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## API Reference
|
|
72
|
+
|
|
73
|
+
### Tasks
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
# Create a task
|
|
77
|
+
task = deck.tasks.create(
|
|
78
|
+
title="Task title",
|
|
79
|
+
description="Task description",
|
|
80
|
+
status="INBOX", # INBOX, ASSIGNED, IN PROGRESS, REVIEW, DONE
|
|
81
|
+
priority="medium", # low, medium, high, critical
|
|
82
|
+
assignees=["JARVIS", "FRIDAY"],
|
|
83
|
+
tags=["data", "analysis"]
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# List tasks
|
|
87
|
+
tasks = deck.tasks.list()
|
|
88
|
+
tasks = deck.tasks.list(status="IN PROGRESS", limit=50)
|
|
89
|
+
|
|
90
|
+
# Update a task
|
|
91
|
+
deck.tasks.update(
|
|
92
|
+
task_id="task-id",
|
|
93
|
+
status="IN PROGRESS",
|
|
94
|
+
output="Working on it..."
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
# Move task to a status
|
|
98
|
+
deck.tasks.move(task_id, "REVIEW")
|
|
99
|
+
|
|
100
|
+
# Complete a task
|
|
101
|
+
deck.tasks.complete(task_id, output="Done!")
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Agents
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
# Create an agent
|
|
108
|
+
agent = deck.agents.create(
|
|
109
|
+
name="JARVIS",
|
|
110
|
+
avatar="🤖",
|
|
111
|
+
role="AI Assistant",
|
|
112
|
+
level="LEAD", # standard, INT, LEAD, SPC
|
|
113
|
+
status="idle"
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# List agents
|
|
117
|
+
agents = deck.agents.list()
|
|
118
|
+
|
|
119
|
+
# Update agent status
|
|
120
|
+
deck.agents.update_status("JARVIS", "working")
|
|
121
|
+
|
|
122
|
+
# Convenience methods
|
|
123
|
+
deck.agents.set_working("JARVIS")
|
|
124
|
+
deck.agents.set_idle("JARVIS")
|
|
125
|
+
deck.agents.set_offline("JARVIS")
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Events
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
# Send a message to the live feed
|
|
132
|
+
deck.events.message("Starting work...", agent_name="JARVIS")
|
|
133
|
+
|
|
134
|
+
# Send a log event
|
|
135
|
+
deck.events.log(
|
|
136
|
+
message="Processing file",
|
|
137
|
+
agent_name="JARVIS",
|
|
138
|
+
metadata={"file": "data.csv", "rows": 1000}
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# Send a custom event
|
|
142
|
+
deck.events.send(
|
|
143
|
+
type="custom",
|
|
144
|
+
agent_name="JARVIS",
|
|
145
|
+
message="Custom event",
|
|
146
|
+
metadata={"key": "value"}
|
|
147
|
+
)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Integration Examples
|
|
151
|
+
|
|
152
|
+
### CrewAI
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
from crewai import Agent, Task, Crew
|
|
156
|
+
from crewdeck import CrewDeck
|
|
157
|
+
|
|
158
|
+
deck = CrewDeck(api_key="your-api-key")
|
|
159
|
+
|
|
160
|
+
# Sync CrewAI agent with CrewDeck
|
|
161
|
+
crewai_agent = Agent(
|
|
162
|
+
role="Researcher",
|
|
163
|
+
goal="Research topics",
|
|
164
|
+
backstory="Expert researcher"
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# Create corresponding agent in CrewDeck
|
|
168
|
+
deck.agents.create(
|
|
169
|
+
name="Researcher",
|
|
170
|
+
avatar="🔬",
|
|
171
|
+
role="Research Agent",
|
|
172
|
+
level="INT"
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
# When starting a task
|
|
176
|
+
def on_task_start(task):
|
|
177
|
+
deck.agents.set_working("Researcher")
|
|
178
|
+
deck.events.message(f"Starting: {task.description}", agent_name="Researcher")
|
|
179
|
+
|
|
180
|
+
# When task completes
|
|
181
|
+
def on_task_complete(task, output):
|
|
182
|
+
deck.events.message(f"Completed: {task.description}", agent_name="Researcher")
|
|
183
|
+
deck.agents.set_idle("Researcher")
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### LangChain
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from langchain.callbacks.base import BaseCallbackHandler
|
|
190
|
+
from crewdeck import CrewDeck
|
|
191
|
+
|
|
192
|
+
class CrewDeckCallback(BaseCallbackHandler):
|
|
193
|
+
def __init__(self, deck: CrewDeck, agent_name: str):
|
|
194
|
+
self.deck = deck
|
|
195
|
+
self.agent_name = agent_name
|
|
196
|
+
|
|
197
|
+
def on_chain_start(self, serialized, inputs, **kwargs):
|
|
198
|
+
self.deck.agents.set_working(self.agent_name)
|
|
199
|
+
self.deck.events.message(f"Processing: {inputs}", agent_name=self.agent_name)
|
|
200
|
+
|
|
201
|
+
def on_chain_end(self, outputs, **kwargs):
|
|
202
|
+
self.deck.events.message(f"Result: {outputs}", agent_name=self.agent_name)
|
|
203
|
+
self.deck.agents.set_idle(self.agent_name)
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Context Manager
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
with CrewDeck(api_key="your-api-key") as deck:
|
|
210
|
+
task = deck.tasks.create(title="My task")
|
|
211
|
+
# Client automatically closes when done
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Error Handling
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
from crewdeck import CrewDeck, AuthenticationError, APIError
|
|
218
|
+
|
|
219
|
+
try:
|
|
220
|
+
deck = CrewDeck(api_key="invalid-key")
|
|
221
|
+
deck.tasks.list()
|
|
222
|
+
except AuthenticationError:
|
|
223
|
+
print("Invalid API key")
|
|
224
|
+
except APIError as e:
|
|
225
|
+
print(f"API error: {e} (status: {e.status_code})")
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Configuration
|
|
229
|
+
|
|
230
|
+
```python
|
|
231
|
+
deck = CrewDeck(
|
|
232
|
+
api_key="your-api-key",
|
|
233
|
+
base_url="https://your-convex-deployment.convex.site", # Custom deployment
|
|
234
|
+
timeout=30.0 # Request timeout in seconds
|
|
235
|
+
)
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## License
|
|
239
|
+
|
|
240
|
+
MIT
|
crewdeck-0.1.0/README.md
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# CrewDeck Python SDK
|
|
2
|
+
|
|
3
|
+
Official Python SDK for [CrewDeck](https://crewdeck.dev) — the AI agent management dashboard.
|
|
4
|
+
|
|
5
|
+
Manage your AI crew like a real team. Assign tasks, track progress, review outputs, approve results.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install crewdeck
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from crewdeck import CrewDeck
|
|
17
|
+
|
|
18
|
+
# Initialize with your API key
|
|
19
|
+
deck = CrewDeck(api_key="your-api-key")
|
|
20
|
+
|
|
21
|
+
# Create a task
|
|
22
|
+
task = deck.tasks.create(
|
|
23
|
+
title="Analyze Q4 sales data",
|
|
24
|
+
description="Process and summarize the quarterly sales report",
|
|
25
|
+
priority="high",
|
|
26
|
+
assignees=["JARVIS"]
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
# Update agent status
|
|
30
|
+
deck.agents.set_working("JARVIS")
|
|
31
|
+
|
|
32
|
+
# Send progress updates
|
|
33
|
+
deck.events.message("Starting data analysis...", agent_name="JARVIS")
|
|
34
|
+
|
|
35
|
+
# Complete the task with output
|
|
36
|
+
deck.tasks.complete(task.id, output="Analysis complete. Revenue up 15% YoY.")
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## API Reference
|
|
40
|
+
|
|
41
|
+
### Tasks
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
# Create a task
|
|
45
|
+
task = deck.tasks.create(
|
|
46
|
+
title="Task title",
|
|
47
|
+
description="Task description",
|
|
48
|
+
status="INBOX", # INBOX, ASSIGNED, IN PROGRESS, REVIEW, DONE
|
|
49
|
+
priority="medium", # low, medium, high, critical
|
|
50
|
+
assignees=["JARVIS", "FRIDAY"],
|
|
51
|
+
tags=["data", "analysis"]
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# List tasks
|
|
55
|
+
tasks = deck.tasks.list()
|
|
56
|
+
tasks = deck.tasks.list(status="IN PROGRESS", limit=50)
|
|
57
|
+
|
|
58
|
+
# Update a task
|
|
59
|
+
deck.tasks.update(
|
|
60
|
+
task_id="task-id",
|
|
61
|
+
status="IN PROGRESS",
|
|
62
|
+
output="Working on it..."
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Move task to a status
|
|
66
|
+
deck.tasks.move(task_id, "REVIEW")
|
|
67
|
+
|
|
68
|
+
# Complete a task
|
|
69
|
+
deck.tasks.complete(task_id, output="Done!")
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Agents
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
# Create an agent
|
|
76
|
+
agent = deck.agents.create(
|
|
77
|
+
name="JARVIS",
|
|
78
|
+
avatar="🤖",
|
|
79
|
+
role="AI Assistant",
|
|
80
|
+
level="LEAD", # standard, INT, LEAD, SPC
|
|
81
|
+
status="idle"
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# List agents
|
|
85
|
+
agents = deck.agents.list()
|
|
86
|
+
|
|
87
|
+
# Update agent status
|
|
88
|
+
deck.agents.update_status("JARVIS", "working")
|
|
89
|
+
|
|
90
|
+
# Convenience methods
|
|
91
|
+
deck.agents.set_working("JARVIS")
|
|
92
|
+
deck.agents.set_idle("JARVIS")
|
|
93
|
+
deck.agents.set_offline("JARVIS")
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Events
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
# Send a message to the live feed
|
|
100
|
+
deck.events.message("Starting work...", agent_name="JARVIS")
|
|
101
|
+
|
|
102
|
+
# Send a log event
|
|
103
|
+
deck.events.log(
|
|
104
|
+
message="Processing file",
|
|
105
|
+
agent_name="JARVIS",
|
|
106
|
+
metadata={"file": "data.csv", "rows": 1000}
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# Send a custom event
|
|
110
|
+
deck.events.send(
|
|
111
|
+
type="custom",
|
|
112
|
+
agent_name="JARVIS",
|
|
113
|
+
message="Custom event",
|
|
114
|
+
metadata={"key": "value"}
|
|
115
|
+
)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Integration Examples
|
|
119
|
+
|
|
120
|
+
### CrewAI
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from crewai import Agent, Task, Crew
|
|
124
|
+
from crewdeck import CrewDeck
|
|
125
|
+
|
|
126
|
+
deck = CrewDeck(api_key="your-api-key")
|
|
127
|
+
|
|
128
|
+
# Sync CrewAI agent with CrewDeck
|
|
129
|
+
crewai_agent = Agent(
|
|
130
|
+
role="Researcher",
|
|
131
|
+
goal="Research topics",
|
|
132
|
+
backstory="Expert researcher"
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# Create corresponding agent in CrewDeck
|
|
136
|
+
deck.agents.create(
|
|
137
|
+
name="Researcher",
|
|
138
|
+
avatar="🔬",
|
|
139
|
+
role="Research Agent",
|
|
140
|
+
level="INT"
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
# When starting a task
|
|
144
|
+
def on_task_start(task):
|
|
145
|
+
deck.agents.set_working("Researcher")
|
|
146
|
+
deck.events.message(f"Starting: {task.description}", agent_name="Researcher")
|
|
147
|
+
|
|
148
|
+
# When task completes
|
|
149
|
+
def on_task_complete(task, output):
|
|
150
|
+
deck.events.message(f"Completed: {task.description}", agent_name="Researcher")
|
|
151
|
+
deck.agents.set_idle("Researcher")
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### LangChain
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
from langchain.callbacks.base import BaseCallbackHandler
|
|
158
|
+
from crewdeck import CrewDeck
|
|
159
|
+
|
|
160
|
+
class CrewDeckCallback(BaseCallbackHandler):
|
|
161
|
+
def __init__(self, deck: CrewDeck, agent_name: str):
|
|
162
|
+
self.deck = deck
|
|
163
|
+
self.agent_name = agent_name
|
|
164
|
+
|
|
165
|
+
def on_chain_start(self, serialized, inputs, **kwargs):
|
|
166
|
+
self.deck.agents.set_working(self.agent_name)
|
|
167
|
+
self.deck.events.message(f"Processing: {inputs}", agent_name=self.agent_name)
|
|
168
|
+
|
|
169
|
+
def on_chain_end(self, outputs, **kwargs):
|
|
170
|
+
self.deck.events.message(f"Result: {outputs}", agent_name=self.agent_name)
|
|
171
|
+
self.deck.agents.set_idle(self.agent_name)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Context Manager
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
with CrewDeck(api_key="your-api-key") as deck:
|
|
178
|
+
task = deck.tasks.create(title="My task")
|
|
179
|
+
# Client automatically closes when done
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Error Handling
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
from crewdeck import CrewDeck, AuthenticationError, APIError
|
|
186
|
+
|
|
187
|
+
try:
|
|
188
|
+
deck = CrewDeck(api_key="invalid-key")
|
|
189
|
+
deck.tasks.list()
|
|
190
|
+
except AuthenticationError:
|
|
191
|
+
print("Invalid API key")
|
|
192
|
+
except APIError as e:
|
|
193
|
+
print(f"API error: {e} (status: {e.status_code})")
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Configuration
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
deck = CrewDeck(
|
|
200
|
+
api_key="your-api-key",
|
|
201
|
+
base_url="https://your-convex-deployment.convex.site", # Custom deployment
|
|
202
|
+
timeout=30.0 # Request timeout in seconds
|
|
203
|
+
)
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## License
|
|
207
|
+
|
|
208
|
+
MIT
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CrewDeck Python SDK
|
|
3
|
+
|
|
4
|
+
Manage your AI agent teams with CrewDeck.
|
|
5
|
+
|
|
6
|
+
Quick Start:
|
|
7
|
+
from crewdeck import CrewDeck
|
|
8
|
+
|
|
9
|
+
deck = CrewDeck(api_key="your-api-key")
|
|
10
|
+
|
|
11
|
+
# Create a task
|
|
12
|
+
task = deck.tasks.create(
|
|
13
|
+
title="Analyze data",
|
|
14
|
+
description="Process the Q4 sales data",
|
|
15
|
+
priority="high",
|
|
16
|
+
assignees=["JARVIS"]
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
# Update agent status
|
|
20
|
+
deck.agents.update_status("JARVIS", "working")
|
|
21
|
+
|
|
22
|
+
# Send an event to the live feed
|
|
23
|
+
deck.events.send(
|
|
24
|
+
type="message",
|
|
25
|
+
agent_name="JARVIS",
|
|
26
|
+
message="Starting data analysis..."
|
|
27
|
+
)
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
from .client import CrewDeck
|
|
31
|
+
from .models import Task, Agent, Event
|
|
32
|
+
from .exceptions import CrewDeckError, AuthenticationError, APIError
|
|
33
|
+
|
|
34
|
+
__version__ = "0.1.0"
|
|
35
|
+
__all__ = [
|
|
36
|
+
"CrewDeck",
|
|
37
|
+
"Task",
|
|
38
|
+
"Agent",
|
|
39
|
+
"Event",
|
|
40
|
+
"CrewDeckError",
|
|
41
|
+
"AuthenticationError",
|
|
42
|
+
"APIError",
|
|
43
|
+
]
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
"""CrewDeck Python Client"""
|
|
2
|
+
|
|
3
|
+
from typing import List, Optional, Dict, Any
|
|
4
|
+
import httpx
|
|
5
|
+
|
|
6
|
+
from .models import Task, Agent, Event
|
|
7
|
+
from .exceptions import (
|
|
8
|
+
CrewDeckError,
|
|
9
|
+
AuthenticationError,
|
|
10
|
+
APIError,
|
|
11
|
+
NotFoundError,
|
|
12
|
+
RateLimitError,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
DEFAULT_BASE_URL = "https://adept-jellyfish-320.convex.site"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TasksAPI:
|
|
20
|
+
"""Tasks API wrapper"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, client: "CrewDeck"):
|
|
23
|
+
self._client = client
|
|
24
|
+
|
|
25
|
+
def create(
|
|
26
|
+
self,
|
|
27
|
+
title: str,
|
|
28
|
+
description: str = "",
|
|
29
|
+
status: str = "INBOX",
|
|
30
|
+
priority: str = "medium",
|
|
31
|
+
assignees: Optional[List[str]] = None,
|
|
32
|
+
tags: Optional[List[str]] = None,
|
|
33
|
+
) -> Task:
|
|
34
|
+
"""
|
|
35
|
+
Create a new task.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
title: Task title (required)
|
|
39
|
+
description: Task description
|
|
40
|
+
status: Task status (INBOX, ASSIGNED, IN PROGRESS, REVIEW, DONE)
|
|
41
|
+
priority: Priority level (low, medium, high, critical)
|
|
42
|
+
assignees: List of agent names to assign
|
|
43
|
+
tags: List of tags
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
Created Task object
|
|
47
|
+
"""
|
|
48
|
+
data = {
|
|
49
|
+
"title": title,
|
|
50
|
+
"description": description,
|
|
51
|
+
"status": status,
|
|
52
|
+
"priority": priority,
|
|
53
|
+
"assignees": assignees or [],
|
|
54
|
+
"tags": tags or [],
|
|
55
|
+
}
|
|
56
|
+
response = self._client._request("POST", "/api/v1/tasks", json=data)
|
|
57
|
+
return Task(
|
|
58
|
+
id=response.get("taskId", ""),
|
|
59
|
+
title=title,
|
|
60
|
+
description=description,
|
|
61
|
+
status=status,
|
|
62
|
+
priority=priority,
|
|
63
|
+
assignees=assignees or [],
|
|
64
|
+
tags=tags or [],
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
def list(
|
|
68
|
+
self,
|
|
69
|
+
status: Optional[str] = None,
|
|
70
|
+
limit: int = 100,
|
|
71
|
+
) -> List[Task]:
|
|
72
|
+
"""
|
|
73
|
+
List tasks.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
status: Filter by status (optional)
|
|
77
|
+
limit: Maximum number of tasks to return
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
List of Task objects
|
|
81
|
+
"""
|
|
82
|
+
params = {"limit": str(limit)}
|
|
83
|
+
if status:
|
|
84
|
+
params["status"] = status
|
|
85
|
+
response = self._client._request("GET", "/api/v1/tasks", params=params)
|
|
86
|
+
return [Task.from_dict(t) for t in response.get("tasks", [])]
|
|
87
|
+
|
|
88
|
+
def update(
|
|
89
|
+
self,
|
|
90
|
+
task_id: str,
|
|
91
|
+
title: Optional[str] = None,
|
|
92
|
+
description: Optional[str] = None,
|
|
93
|
+
status: Optional[str] = None,
|
|
94
|
+
priority: Optional[str] = None,
|
|
95
|
+
assignees: Optional[List[str]] = None,
|
|
96
|
+
tags: Optional[List[str]] = None,
|
|
97
|
+
output: Optional[str] = None,
|
|
98
|
+
) -> None:
|
|
99
|
+
"""
|
|
100
|
+
Update a task.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
task_id: Task ID (required)
|
|
104
|
+
title: New title
|
|
105
|
+
description: New description
|
|
106
|
+
status: New status
|
|
107
|
+
priority: New priority
|
|
108
|
+
assignees: New assignees list
|
|
109
|
+
tags: New tags list
|
|
110
|
+
output: Task output/result
|
|
111
|
+
"""
|
|
112
|
+
data: Dict[str, Any] = {"id": task_id}
|
|
113
|
+
if title is not None:
|
|
114
|
+
data["title"] = title
|
|
115
|
+
if description is not None:
|
|
116
|
+
data["description"] = description
|
|
117
|
+
if status is not None:
|
|
118
|
+
data["status"] = status
|
|
119
|
+
if priority is not None:
|
|
120
|
+
data["priority"] = priority
|
|
121
|
+
if assignees is not None:
|
|
122
|
+
data["assignees"] = assignees
|
|
123
|
+
if tags is not None:
|
|
124
|
+
data["tags"] = tags
|
|
125
|
+
if output is not None:
|
|
126
|
+
data["output"] = output
|
|
127
|
+
self._client._request("PUT", "/api/v1/tasks", json=data)
|
|
128
|
+
|
|
129
|
+
def move(self, task_id: str, status: str) -> None:
|
|
130
|
+
"""
|
|
131
|
+
Move a task to a new status.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
task_id: Task ID
|
|
135
|
+
status: New status (INBOX, ASSIGNED, IN PROGRESS, REVIEW, DONE)
|
|
136
|
+
"""
|
|
137
|
+
self.update(task_id, status=status)
|
|
138
|
+
|
|
139
|
+
def complete(self, task_id: str, output: Optional[str] = None) -> None:
|
|
140
|
+
"""
|
|
141
|
+
Mark a task as done.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
task_id: Task ID
|
|
145
|
+
output: Optional output/result
|
|
146
|
+
"""
|
|
147
|
+
self.update(task_id, status="DONE", output=output)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class AgentsAPI:
|
|
151
|
+
"""Agents API wrapper"""
|
|
152
|
+
|
|
153
|
+
def __init__(self, client: "CrewDeck"):
|
|
154
|
+
self._client = client
|
|
155
|
+
|
|
156
|
+
def create(
|
|
157
|
+
self,
|
|
158
|
+
name: str,
|
|
159
|
+
avatar: str = "🤖",
|
|
160
|
+
role: str = "AI Agent",
|
|
161
|
+
level: str = "standard",
|
|
162
|
+
status: str = "idle",
|
|
163
|
+
) -> Agent:
|
|
164
|
+
"""
|
|
165
|
+
Create a new agent.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
name: Agent name (required)
|
|
169
|
+
avatar: Emoji avatar
|
|
170
|
+
role: Agent role description
|
|
171
|
+
level: Agent level (standard, INT, LEAD, SPC)
|
|
172
|
+
status: Initial status (idle, working, offline)
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
Created Agent object
|
|
176
|
+
"""
|
|
177
|
+
data = {
|
|
178
|
+
"name": name,
|
|
179
|
+
"avatar": avatar,
|
|
180
|
+
"role": role,
|
|
181
|
+
"level": level,
|
|
182
|
+
"status": status,
|
|
183
|
+
}
|
|
184
|
+
response = self._client._request("POST", "/api/v1/agents", json=data)
|
|
185
|
+
return Agent(
|
|
186
|
+
id=response.get("agentId", ""),
|
|
187
|
+
name=name,
|
|
188
|
+
avatar=avatar,
|
|
189
|
+
role=role,
|
|
190
|
+
level=level,
|
|
191
|
+
status=status,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
def list(self) -> List[Agent]:
|
|
195
|
+
"""
|
|
196
|
+
List all agents.
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
List of Agent objects
|
|
200
|
+
"""
|
|
201
|
+
response = self._client._request("GET", "/api/v1/agents")
|
|
202
|
+
return [Agent.from_dict(a) for a in response.get("agents", [])]
|
|
203
|
+
|
|
204
|
+
def update_status(self, name: str, status: str) -> None:
|
|
205
|
+
"""
|
|
206
|
+
Update an agent's status by name.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
name: Agent name
|
|
210
|
+
status: New status (idle, working, offline)
|
|
211
|
+
"""
|
|
212
|
+
self._client._request("PUT", "/api/v1/agents", json={
|
|
213
|
+
"name": name,
|
|
214
|
+
"status": status,
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
def set_working(self, name: str) -> None:
|
|
218
|
+
"""Set agent status to working"""
|
|
219
|
+
self.update_status(name, "working")
|
|
220
|
+
|
|
221
|
+
def set_idle(self, name: str) -> None:
|
|
222
|
+
"""Set agent status to idle"""
|
|
223
|
+
self.update_status(name, "idle")
|
|
224
|
+
|
|
225
|
+
def set_offline(self, name: str) -> None:
|
|
226
|
+
"""Set agent status to offline"""
|
|
227
|
+
self.update_status(name, "offline")
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class EventsAPI:
|
|
231
|
+
"""Events API wrapper"""
|
|
232
|
+
|
|
233
|
+
def __init__(self, client: "CrewDeck"):
|
|
234
|
+
self._client = client
|
|
235
|
+
|
|
236
|
+
def send(
|
|
237
|
+
self,
|
|
238
|
+
type: str,
|
|
239
|
+
agent_name: Optional[str] = None,
|
|
240
|
+
message: Optional[str] = None,
|
|
241
|
+
task_id: Optional[str] = None,
|
|
242
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
243
|
+
) -> None:
|
|
244
|
+
"""
|
|
245
|
+
Send an event to the live feed.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
type: Event type (message, status, log)
|
|
249
|
+
agent_name: Agent name (optional)
|
|
250
|
+
message: Message content
|
|
251
|
+
task_id: Related task ID
|
|
252
|
+
metadata: Additional metadata
|
|
253
|
+
"""
|
|
254
|
+
event = Event(
|
|
255
|
+
type=type,
|
|
256
|
+
agent_name=agent_name,
|
|
257
|
+
message=message,
|
|
258
|
+
task_id=task_id,
|
|
259
|
+
metadata=metadata,
|
|
260
|
+
)
|
|
261
|
+
self._client._request("POST", "/api/v1/events", json=event.to_dict())
|
|
262
|
+
|
|
263
|
+
def message(self, content: str, agent_name: Optional[str] = None) -> None:
|
|
264
|
+
"""
|
|
265
|
+
Send a message to the live feed.
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
content: Message content
|
|
269
|
+
agent_name: Agent name (optional)
|
|
270
|
+
"""
|
|
271
|
+
self.send(type="message", message=content, agent_name=agent_name)
|
|
272
|
+
|
|
273
|
+
def log(
|
|
274
|
+
self,
|
|
275
|
+
message: str,
|
|
276
|
+
agent_name: Optional[str] = None,
|
|
277
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
278
|
+
) -> None:
|
|
279
|
+
"""
|
|
280
|
+
Send a log event.
|
|
281
|
+
|
|
282
|
+
Args:
|
|
283
|
+
message: Log message
|
|
284
|
+
agent_name: Agent name (optional)
|
|
285
|
+
metadata: Additional data to log
|
|
286
|
+
"""
|
|
287
|
+
self.send(type="log", message=message, agent_name=agent_name, metadata=metadata)
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
class CrewDeck:
|
|
291
|
+
"""
|
|
292
|
+
CrewDeck Python Client
|
|
293
|
+
|
|
294
|
+
Example:
|
|
295
|
+
deck = CrewDeck(api_key="your-api-key")
|
|
296
|
+
|
|
297
|
+
# Create a task
|
|
298
|
+
task = deck.tasks.create(
|
|
299
|
+
title="Process data",
|
|
300
|
+
priority="high",
|
|
301
|
+
assignees=["JARVIS"]
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
# Update agent status
|
|
305
|
+
deck.agents.set_working("JARVIS")
|
|
306
|
+
|
|
307
|
+
# Send a message
|
|
308
|
+
deck.events.message("Starting work...", agent_name="JARVIS")
|
|
309
|
+
|
|
310
|
+
# Complete the task
|
|
311
|
+
deck.tasks.complete(task.id, output="Data processed successfully")
|
|
312
|
+
"""
|
|
313
|
+
|
|
314
|
+
def __init__(
|
|
315
|
+
self,
|
|
316
|
+
api_key: str,
|
|
317
|
+
base_url: str = DEFAULT_BASE_URL,
|
|
318
|
+
timeout: float = 30.0,
|
|
319
|
+
):
|
|
320
|
+
"""
|
|
321
|
+
Initialize CrewDeck client.
|
|
322
|
+
|
|
323
|
+
Args:
|
|
324
|
+
api_key: Your CrewDeck API key
|
|
325
|
+
base_url: API base URL (default: production)
|
|
326
|
+
timeout: Request timeout in seconds
|
|
327
|
+
"""
|
|
328
|
+
if not api_key:
|
|
329
|
+
raise AuthenticationError("API key is required")
|
|
330
|
+
|
|
331
|
+
self.api_key = api_key
|
|
332
|
+
self.base_url = base_url.rstrip("/")
|
|
333
|
+
self.timeout = timeout
|
|
334
|
+
|
|
335
|
+
self._client = httpx.Client(
|
|
336
|
+
base_url=self.base_url,
|
|
337
|
+
headers={
|
|
338
|
+
"Authorization": f"Bearer {api_key}",
|
|
339
|
+
"Content-Type": "application/json",
|
|
340
|
+
},
|
|
341
|
+
timeout=timeout,
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
# API namespaces
|
|
345
|
+
self.tasks = TasksAPI(self)
|
|
346
|
+
self.agents = AgentsAPI(self)
|
|
347
|
+
self.events = EventsAPI(self)
|
|
348
|
+
|
|
349
|
+
def _request(
|
|
350
|
+
self,
|
|
351
|
+
method: str,
|
|
352
|
+
path: str,
|
|
353
|
+
params: Optional[Dict[str, str]] = None,
|
|
354
|
+
json: Optional[Dict[str, Any]] = None,
|
|
355
|
+
) -> Dict[str, Any]:
|
|
356
|
+
"""Make an API request"""
|
|
357
|
+
try:
|
|
358
|
+
response = self._client.request(
|
|
359
|
+
method=method,
|
|
360
|
+
url=path,
|
|
361
|
+
params=params,
|
|
362
|
+
json=json,
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
if response.status_code == 401:
|
|
366
|
+
raise AuthenticationError("Invalid or revoked API key")
|
|
367
|
+
|
|
368
|
+
if response.status_code == 404:
|
|
369
|
+
raise NotFoundError("Resource not found", status_code=404)
|
|
370
|
+
|
|
371
|
+
if response.status_code == 429:
|
|
372
|
+
raise RateLimitError("Rate limit exceeded", status_code=429)
|
|
373
|
+
|
|
374
|
+
if response.status_code >= 400:
|
|
375
|
+
try:
|
|
376
|
+
error_data = response.json()
|
|
377
|
+
message = error_data.get("error", f"API error: {response.status_code}")
|
|
378
|
+
except:
|
|
379
|
+
message = f"API error: {response.status_code}"
|
|
380
|
+
raise APIError(message, status_code=response.status_code)
|
|
381
|
+
|
|
382
|
+
return response.json()
|
|
383
|
+
|
|
384
|
+
except httpx.RequestError as e:
|
|
385
|
+
raise CrewDeckError(f"Request failed: {e}")
|
|
386
|
+
|
|
387
|
+
def close(self) -> None:
|
|
388
|
+
"""Close the HTTP client"""
|
|
389
|
+
self._client.close()
|
|
390
|
+
|
|
391
|
+
def __enter__(self) -> "CrewDeck":
|
|
392
|
+
return self
|
|
393
|
+
|
|
394
|
+
def __exit__(self, *args) -> None:
|
|
395
|
+
self.close()
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""CrewDeck SDK Exceptions"""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class CrewDeckError(Exception):
|
|
5
|
+
"""Base exception for CrewDeck SDK"""
|
|
6
|
+
pass
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AuthenticationError(CrewDeckError):
|
|
10
|
+
"""Raised when API key is invalid or missing"""
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class APIError(CrewDeckError):
|
|
15
|
+
"""Raised when API returns an error"""
|
|
16
|
+
|
|
17
|
+
def __init__(self, message: str, status_code: int = None, response: dict = None):
|
|
18
|
+
super().__init__(message)
|
|
19
|
+
self.status_code = status_code
|
|
20
|
+
self.response = response
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ValidationError(CrewDeckError):
|
|
24
|
+
"""Raised when input validation fails"""
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class NotFoundError(APIError):
|
|
29
|
+
"""Raised when a resource is not found"""
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class RateLimitError(APIError):
|
|
34
|
+
"""Raised when rate limit is exceeded"""
|
|
35
|
+
pass
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""CrewDeck Data Models"""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import List, Optional, Dict, Any
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class Task:
|
|
10
|
+
"""Represents a task in CrewDeck"""
|
|
11
|
+
id: str
|
|
12
|
+
title: str
|
|
13
|
+
description: str = ""
|
|
14
|
+
status: str = "INBOX"
|
|
15
|
+
priority: str = "medium"
|
|
16
|
+
assignees: List[str] = field(default_factory=list)
|
|
17
|
+
tags: List[str] = field(default_factory=list)
|
|
18
|
+
output: Optional[str] = None
|
|
19
|
+
created_at: Optional[datetime] = None
|
|
20
|
+
updated_at: Optional[datetime] = None
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
def from_dict(cls, data: Dict[str, Any]) -> "Task":
|
|
24
|
+
return cls(
|
|
25
|
+
id=data.get("id", ""),
|
|
26
|
+
title=data.get("title", ""),
|
|
27
|
+
description=data.get("description", ""),
|
|
28
|
+
status=data.get("status", "INBOX"),
|
|
29
|
+
priority=data.get("priority", "medium"),
|
|
30
|
+
assignees=data.get("assignees", []),
|
|
31
|
+
tags=data.get("tags", []),
|
|
32
|
+
output=data.get("output"),
|
|
33
|
+
created_at=datetime.fromtimestamp(data["createdAt"] / 1000) if data.get("createdAt") else None,
|
|
34
|
+
updated_at=datetime.fromtimestamp(data["updatedAt"] / 1000) if data.get("updatedAt") else None,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
38
|
+
return {
|
|
39
|
+
"id": self.id,
|
|
40
|
+
"title": self.title,
|
|
41
|
+
"description": self.description,
|
|
42
|
+
"status": self.status,
|
|
43
|
+
"priority": self.priority,
|
|
44
|
+
"assignees": self.assignees,
|
|
45
|
+
"tags": self.tags,
|
|
46
|
+
"output": self.output,
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass
|
|
51
|
+
class Agent:
|
|
52
|
+
"""Represents an agent in CrewDeck"""
|
|
53
|
+
id: str
|
|
54
|
+
name: str
|
|
55
|
+
avatar: str = "🤖"
|
|
56
|
+
role: str = "AI Agent"
|
|
57
|
+
level: str = "standard"
|
|
58
|
+
status: str = "idle"
|
|
59
|
+
created_at: Optional[datetime] = None
|
|
60
|
+
|
|
61
|
+
@classmethod
|
|
62
|
+
def from_dict(cls, data: Dict[str, Any]) -> "Agent":
|
|
63
|
+
return cls(
|
|
64
|
+
id=data.get("id", ""),
|
|
65
|
+
name=data.get("name", ""),
|
|
66
|
+
avatar=data.get("avatar", "🤖"),
|
|
67
|
+
role=data.get("role", "AI Agent"),
|
|
68
|
+
level=data.get("level", "standard"),
|
|
69
|
+
status=data.get("status", "idle"),
|
|
70
|
+
created_at=datetime.fromtimestamp(data["createdAt"] / 1000) if data.get("createdAt") else None,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
74
|
+
return {
|
|
75
|
+
"id": self.id,
|
|
76
|
+
"name": self.name,
|
|
77
|
+
"avatar": self.avatar,
|
|
78
|
+
"role": self.role,
|
|
79
|
+
"level": self.level,
|
|
80
|
+
"status": self.status,
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@dataclass
|
|
85
|
+
class Event:
|
|
86
|
+
"""Represents an event in CrewDeck"""
|
|
87
|
+
type: str
|
|
88
|
+
agent_name: Optional[str] = None
|
|
89
|
+
message: Optional[str] = None
|
|
90
|
+
task_id: Optional[str] = None
|
|
91
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
92
|
+
|
|
93
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
94
|
+
data = {"type": self.type}
|
|
95
|
+
if self.agent_name:
|
|
96
|
+
data["agentName"] = self.agent_name
|
|
97
|
+
if self.message:
|
|
98
|
+
data["message"] = self.message
|
|
99
|
+
if self.task_id:
|
|
100
|
+
data["taskId"] = self.task_id
|
|
101
|
+
if self.metadata:
|
|
102
|
+
data["metadata"] = self.metadata
|
|
103
|
+
return data
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "crewdeck"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python SDK for CrewDeck - AI agent management dashboard"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.8"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "CrewDeck", email = "hello@crewdeck.dev" }
|
|
14
|
+
]
|
|
15
|
+
keywords = ["ai", "agents", "crewai", "autogen", "langchain", "dashboard", "management"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.8",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
27
|
+
]
|
|
28
|
+
dependencies = [
|
|
29
|
+
"httpx>=0.24.0",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
async = ["httpx[http2]>=0.24.0"]
|
|
34
|
+
dev = [
|
|
35
|
+
"pytest>=7.0.0",
|
|
36
|
+
"pytest-asyncio>=0.21.0",
|
|
37
|
+
"black>=23.0.0",
|
|
38
|
+
"ruff>=0.1.0",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[project.urls]
|
|
42
|
+
Homepage = "https://crewdeck.dev"
|
|
43
|
+
Documentation = "https://docs.crewdeck.dev"
|
|
44
|
+
Repository = "https://github.com/crewdeck/crewdeck-python"
|
|
45
|
+
|
|
46
|
+
[tool.hatch.build.targets.wheel]
|
|
47
|
+
packages = ["crewdeck"]
|
|
48
|
+
|
|
49
|
+
[tool.black]
|
|
50
|
+
line-length = 88
|
|
51
|
+
target-version = ["py38"]
|
|
52
|
+
|
|
53
|
+
[tool.ruff]
|
|
54
|
+
line-length = 88
|
|
55
|
+
target-version = "py38"
|