初始提交:多智能体任务管理系统

- 完整的 RESTful API(智能体注册、任务管理)
- Web 管理界面(实时统计、任务列表)
- SQLite 数据库存储
- Python 客户端示例
- 完整的 API 文档
This commit is contained in:
work-1
2026-02-15 13:41:49 +08:00
commit da6ff6a51b
7 changed files with 3652 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
node_modules/
*.db
*.log
.env
.DS_Store
+429
View File
@@ -0,0 +1,429 @@
# 多智能体任务管理系统
一个用于多智能体协作的任务发布、领取和状态管理服务。
## 功能特性
-**智能体注册与管理** - 智能体可自主注册并维持心跳
-**任务发布系统** - 人类和智能体都可以发布任务
-**任务领取机制** - 智能体可领取待处理的任务
-**状态实时更新** - 跟踪任务和智能体的状态变化
-**Web 管理界面** - 可视化查看和管理任务
-**RESTful API** - 完整的 HTTP API 接口
## 快速开始
### 1. 启动服务
```bash
cd /data/openclaw/workspace/agent-task-service
node server.js
```
服务将在 `http://localhost:3000` 启动。
### 2. 访问 Web 界面
在浏览器中打开: `http://localhost:3000`
## API 文档
### 智能体相关
#### 注册智能体
```http
POST /api/agents/register
Content-Type: application/json
{
"name": "",
"type": "general", // : general, search, coding, etc.
"capabilities": ["", "", ""] //
}
:
{
"id": "uuid",
"name": "",
"type": "general",
"status": "idle",
"message": ""
}
```
#### 获取所有智能体
```http
GET /api/agents
:
[
{
"id": "uuid",
"name": "1",
"type": "general",
"capabilities": ["", ""],
"status": "idle",
"registered_at": 1234567890,
"last_heartbeat": 1234567890
}
]
```
#### 更新心跳(保活)
```http
POST /api/agents/:id/heartbeat
Content-Type: application/json
{
"status": "idle" // idle | busy
}
```
### 任务相关
#### 创建任务
```http
POST /api/tasks
Content-Type: application/json
{
"title": "",
"description": "",
"priority": "normal", // low | normal | high
"created_by": "human" // human | agent_id
}
:
{
"id": "uuid",
"title": "",
"status": "pending",
"message": ""
}
```
#### 获取所有任务
```http
GET /api/tasks
GET /api/tasks?status=pending //
:
[
{
"id": "uuid",
"title": "",
"description": "",
"priority": "normal",
"status": "pending",
"created_by": "human",
"assigned_to": null,
"created_at": 1234567890,
"updated_at": 1234567890
}
]
```
#### 领取任务
```http
POST /api/tasks/:id/claim
Content-Type: application/json
{
"agent_id": "ID"
}
:
{
"message": ""
}
```
#### 更新任务状态
```http
PUT /api/tasks/:id
Content-Type: application/json
{
"status": "completed", // pending | in_progress | completed
"result": "" //
}
:
{
"message": ""
}
```
#### 获取任务详情
```http
GET /api/tasks/:id
:
{
"id": "uuid",
"title": "",
"description": "",
"priority": "normal",
"status": "completed",
"created_by": "human",
"assigned_to": "agent_id",
"created_at": 1234567890,
"updated_at": 1234567890,
"completed_at": 1234567890,
"result": ""
}
```
#### 获取统计信息
```http
GET /api/stats
:
{
"total_agents": 5,
"active_agents": 2,
"total_tasks": 20,
"pending_tasks": 3,
"in_progress_tasks": 2,
"completed_tasks": 15
}
```
## 智能体集成示例
### Python 客户端示例
```python
import requests
import time
import uuid
class TaskAgent:
def __init__(self, name, base_url="http://localhost:3000"):
self.name = name
self.base_url = base_url
self.agent_id = None
def register(self):
"""注册智能体"""
response = requests.post(f"{self.base_url}/api/agents/register", json={
"name": self.name,
"type": "general",
"capabilities": ["general_task"]
})
data = response.json()
self.agent_id = data["id"]
print(f"✅ 智能体已注册: {self.agent_id}")
def heartbeat(self, status="idle"):
"""发送心跳"""
requests.post(
f"{self.base_url}/api/agents/{self.agent_id}/heartbeat",
json={"status": status}
)
def get_pending_tasks(self):
"""获取待处理任务"""
response = requests.get(f"{self.base_url}/api/tasks?status=pending")
return response.json()
def claim_task(self, task_id):
"""领取任务"""
response = requests.post(
f"{self.base_url}/api/tasks/{task_id}/claim",
json={"agent_id": self.agent_id}
)
return response.ok
def update_task(self, task_id, status, result=None):
"""更新任务状态"""
payload = {"status": status}
if result:
payload["result"] = result
requests.put(f"{self.base_url}/api/tasks/{task_id}", json=payload)
def execute_task(self, task):
"""执行任务(示例)"""
print(f"🔄 正在执行任务: {task['title']}")
time.sleep(2) # 模拟任务执行
return f"任务 '{task['title']}' 已完成"
def run(self):
"""主循环"""
self.register()
while True:
try:
# 发送心跳
self.heartbeat("idle")
# 获取待处理任务
tasks = self.get_pending_tasks()
if tasks:
task = tasks[0]
print(f"📋 发现任务: {task['title']}")
# 领取任务
if self.claim_task(task['id']):
self.heartbeat("busy")
# 执行任务
result = self.execute_task(task)
# 更新任务状态
self.update_task(task['id'], "completed", result)
print(f"✅ 任务完成: {task['id']}")
self.heartbeat("idle")
time.sleep(5) # 每5秒检查一次
except KeyboardInterrupt:
print("👋 智能体退出")
break
except Exception as e:
print(f"❌ 错误: {e}")
time.sleep(5)
# 使用示例
if __name__ == "__main__":
agent = TaskAgent("示例智能体")
agent.run()
```
### JavaScript/Node.js 客户端示例
```javascript
const axios = require('axios');
class TaskAgent {
constructor(name, baseUrl = 'http://localhost:3000') {
this.name = name;
this.baseUrl = baseUrl;
this.agentId = null;
}
async register() {
const response = await axios.post(`${this.baseUrl}/api/agents/register`, {
name: this.name,
type: 'general',
capabilities: ['general_task']
});
this.agentId = response.data.id;
console.log(`✅ 智能体已注册: ${this.agentId}`);
}
async heartbeat(status = 'idle') {
await axios.post(
`${this.baseUrl}/api/agents/${this.agentId}/heartbeat`,
{ status }
);
}
async getPendingTasks() {
const response = await axios.get(`${this.baseUrl}/api/tasks?status=pending`);
return response.data;
}
async claimTask(taskId) {
try {
await axios.post(`${this.baseUrl}/api/tasks/${taskId}/claim`, {
agent_id: this.agentId
});
return true;
} catch (error) {
return false;
}
}
async updateTask(taskId, status, result = null) {
const payload = { status };
if (result) payload.result = result;
await axios.put(`${this.baseUrl}/api/tasks/${taskId}`, payload);
}
async executeTask(task) {
console.log(`🔄 正在执行任务: ${task.title}`);
await new Promise(resolve => setTimeout(resolve, 2000));
return `任务 '${task.title}' 已完成`;
}
async run() {
await this.register();
while (true) {
try {
await this.heartbeat('idle');
const tasks = await this.getPendingTasks();
if (tasks.length > 0) {
const task = tasks[0];
console.log(`📋 发现任务: ${task.title}`);
if (await this.claimTask(task.id)) {
await this.heartbeat('busy');
const result = await this.executeTask(task);
await this.updateTask(task.id, 'completed', result);
console.log(`✅ 任务完成: ${task.id}`);
await this.heartbeat('idle');
}
}
await new Promise(resolve => setTimeout(resolve, 5000));
} catch (error) {
console.error('❌ 错误:', error.message);
await new Promise(resolve => setTimeout(resolve, 5000));
}
}
}
}
// 使用示例
const agent = new TaskAgent('示例智能体');
agent.run().catch(console.error);
```
## 数据库结构
系统使用 SQLite 数据库,包含以下表:
### agents 表
- `id` - 智能体唯一标识
- `name` - 智能体名称
- `type` - 智能体类型
- `capabilities` - 能力列表(JSON
- `status` - 状态(idle/busy
- `registered_at` - 注册时间
- `last_heartbeat` - 最后心跳时间
### tasks 表
- `id` - 任务唯一标识
- `title` - 任务标题
- `description` - 任务描述
- `priority` - 优先级(low/normal/high
- `status` - 状态(pending/in_progress/completed
- `created_by` - 创建者
- `assigned_to` - 分配给的智能体
- `created_at` - 创建时间
- `updated_at` - 更新时间
- `completed_at` - 完成时间
- `result` - 任务结果
## 扩展建议
1. **认证授权** - 添加 API Key 或 JWT 认证
2. **任务队列** - 基于优先级的任务队列
3. **任务依赖** - 支持任务之间的依赖关系
4. **消息推送** - WebSocket 实时通知
5. **日志记录** - 详细的操作日志
6. **性能监控** - 任务执行时间和成功率统计
7. **分布式部署** - 支持多节点部署
## 许可证
MIT
+157
View File
@@ -0,0 +1,157 @@
#!/usr/bin/env python3
"""
多智能体任务系统 - Python 客户端示例
"""
import requests
import time
import sys
class TaskAgent:
def __init__(self, name, base_url="http://localhost:3000"):
self.name = name
self.base_url = base_url
self.agent_id = None
def register(self):
"""注册智能体"""
try:
response = requests.post(f"{self.base_url}/api/agents/register", json={
"name": self.name,
"type": "general",
"capabilities": ["general_task", "data_processing"]
})
response.raise_for_status()
data = response.json()
self.agent_id = data["id"]
print(f"✅ 智能体已注册: {self.agent_id}")
return True
except Exception as e:
print(f"❌ 注册失败: {e}")
return False
def heartbeat(self, status="idle"):
"""发送心跳"""
try:
requests.post(
f"{self.base_url}/api/agents/{self.agent_id}/heartbeat",
json={"status": status},
timeout=5
)
except Exception as e:
print(f"⚠️ 心跳发送失败: {e}")
def get_pending_tasks(self):
"""获取待处理任务"""
try:
response = requests.get(
f"{self.base_url}/api/tasks?status=pending",
timeout=5
)
response.raise_for_status()
return response.json()
except Exception as e:
print(f"❌ 获取任务失败: {e}")
return []
def claim_task(self, task_id):
"""领取任务"""
try:
response = requests.post(
f"{self.base_url}/api/tasks/{task_id}/claim",
json={"agent_id": self.agent_id},
timeout=5
)
response.raise_for_status()
return True
except Exception as e:
print(f"⚠️ 领取任务失败: {e}")
return False
def update_task(self, task_id, status, result=None):
"""更新任务状态"""
try:
payload = {"status": status}
if result:
payload["result"] = result
response = requests.put(
f"{self.base_url}/api/tasks/{task_id}",
json=payload,
timeout=5
)
response.raise_for_status()
except Exception as e:
print(f"❌ 更新任务失败: {e}")
def execute_task(self, task):
"""执行任务(示例实现)"""
print(f"🔄 正在执行任务: {task['title']}")
print(f" 描述: {task.get('description', '')}")
print(f" 优先级: {task['priority']}")
# 模拟任务执行
time.sleep(3)
return f"任务 '{task['title']}' 已由 {self.name} 成功完成"
def run(self):
"""主循环"""
if not self.register():
print("❌ 无法注册智能体,退出")
return
print(f"🤖 智能体 '{self.name}' 开始运行...")
print("按 Ctrl+C 退出\n")
while True:
try:
# 发送心跳
self.heartbeat("idle")
# 获取待处理任务
tasks = self.get_pending_tasks()
if tasks:
task = tasks[0]
print(f"\n📋 发现新任务: {task['title']} (ID: {task['id'][:8]}...)")
# 领取任务
if self.claim_task(task['id']):
print("✓ 任务已领取")
self.heartbeat("busy")
# 执行任务
result = self.execute_task(task)
# 更新任务状态
self.update_task(task['id'], "completed", result)
print(f"✅ 任务完成: {task['id'][:8]}...")
print(f" 结果: {result}\n")
self.heartbeat("idle")
else:
print("⚠️ 任务可能已被其他智能体领取\n")
# 等待一段时间再检查
time.sleep(5)
except KeyboardInterrupt:
print("\n\n👋 收到退出信号,智能体停止运行")
break
except Exception as e:
print(f"❌ 运行时错误: {e}")
time.sleep(5)
def main():
if len(sys.argv) > 1:
agent_name = sys.argv[1]
else:
agent_name = f"Python智能体-{int(time.time()) % 10000}"
base_url = sys.argv[2] if len(sys.argv) > 2 else "http://localhost:3000"
agent = TaskAgent(agent_name, base_url)
agent.run()
if __name__ == "__main__":
main()
+2256
View File
File diff suppressed because it is too large Load Diff
+19
View File
@@ -0,0 +1,19 @@
{
"name": "agent-task-service",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^2.2.2",
"cors": "^2.8.6",
"express": "^5.2.1",
"sqlite3": "^5.1.7",
"uuid": "^13.0.0"
}
}
+459
View File
@@ -0,0 +1,459 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>多智能体任务管理系统</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1400px;
margin: 0 auto;
}
header {
text-align: center;
color: white;
margin-bottom: 30px;
}
h1 {
font-size: 2.5em;
margin-bottom: 10px;
}
.stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin-bottom: 30px;
}
.stat-card {
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
text-align: center;
}
.stat-card h3 {
color: #666;
font-size: 0.9em;
margin-bottom: 10px;
}
.stat-card .number {
font-size: 2em;
font-weight: bold;
color: #667eea;
}
.main-content {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 20px;
}
.panel {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.panel h2 {
color: #333;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 2px solid #667eea;
}
.agent-item, .task-item {
padding: 15px;
margin-bottom: 10px;
border-radius: 8px;
background: #f8f9fa;
border-left: 4px solid #667eea;
}
.agent-item.busy {
border-left-color: #f39c12;
background: #fff9e6;
}
.agent-item.offline {
border-left-color: #95a5a6;
background: #ecf0f1;
}
.task-item.pending {
border-left-color: #3498db;
}
.task-item.in_progress {
border-left-color: #f39c12;
background: #fff9e6;
}
.task-item.completed {
border-left-color: #27ae60;
background: #e8f8f5;
}
.badge {
display: inline-block;
padding: 4px 12px;
border-radius: 20px;
font-size: 0.85em;
font-weight: bold;
margin-left: 10px;
}
.badge.idle {
background: #3498db;
color: white;
}
.badge.busy {
background: #f39c12;
color: white;
}
.badge.pending {
background: #3498db;
color: white;
}
.badge.in_progress {
background: #f39c12;
color: white;
}
.badge.completed {
background: #27ae60;
color: white;
}
.badge.high {
background: #e74c3c;
color: white;
}
.badge.normal {
background: #3498db;
color: white;
}
.badge.low {
background: #95a5a6;
color: white;
}
button {
padding: 10px 20px;
border: none;
border-radius: 5px;
background: #667eea;
color: white;
font-weight: bold;
cursor: pointer;
transition: all 0.3s;
}
button:hover {
background: #764ba2;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
color: #333;
font-weight: bold;
}
.form-group input, .form-group textarea, .form-group select {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 1em;
}
.form-group textarea {
resize: vertical;
min-height: 80px;
}
.task-meta {
font-size: 0.85em;
color: #666;
margin-top: 8px;
}
.empty-state {
text-align: center;
color: #999;
padding: 40px;
}
#createTaskForm {
margin-top: 20px;
}
.refresh-btn {
float: right;
padding: 5px 15px;
font-size: 0.9em;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>🤖 多智能体任务管理系统</h1>
<p>Multi-Agent Task Management System</p>
</header>
<div class="stats" id="stats">
<!-- 统计数据将动态加载 -->
</div>
<div class="main-content">
<div class="panel">
<h2>
智能体列表
<button class="refresh-btn" onclick="loadAgents()">刷新</button>
</h2>
<div id="agentList">
<div class="empty-state">加载中...</div>
</div>
</div>
<div class="panel">
<h2>
任务列表
<button class="refresh-btn" onclick="loadTasks()">刷新</button>
</h2>
<div id="taskList">
<div class="empty-state">加载中...</div>
</div>
<form id="createTaskForm">
<h3 style="margin-top: 30px; margin-bottom: 15px;">创建新任务</h3>
<div class="form-group">
<label>任务标题 *</label>
<input type="text" id="taskTitle" required placeholder="输入任务标题">
</div>
<div class="form-group">
<label>任务描述</label>
<textarea id="taskDescription" placeholder="详细描述任务内容"></textarea>
</div>
<div class="form-group">
<label>优先级</label>
<select id="taskPriority">
<option value="low"></option>
<option value="normal" selected>普通</option>
<option value="high"></option>
</select>
</div>
<button type="submit">创建任务</button>
</form>
</div>
</div>
</div>
<script>
const API_BASE = '';
// 加载统计数据
async function loadStats() {
try {
const response = await fetch(`${API_BASE}/api/stats`);
const stats = await response.json();
document.getElementById('stats').innerHTML = `
<div class="stat-card">
<h3>智能体总数</h3>
<div class="number">${stats.total_agents || 0}</div>
</div>
<div class="stat-card">
<h3>活跃智能体</h3>
<div class="number">${stats.active_agents || 0}</div>
</div>
<div class="stat-card">
<h3>待处理任务</h3>
<div class="number">${stats.pending_tasks || 0}</div>
</div>
<div class="stat-card">
<h3>进行中任务</h3>
<div class="number">${stats.in_progress_tasks || 0}</div>
</div>
<div class="stat-card">
<h3>已完成任务</h3>
<div class="number">${stats.completed_tasks || 0}</div>
</div>
<div class="stat-card">
<h3>任务总数</h3>
<div class="number">${stats.total_tasks || 0}</div>
</div>
`;
} catch (error) {
console.error('加载统计数据失败:', error);
}
}
// 加载智能体列表
async function loadAgents() {
try {
const response = await fetch(`${API_BASE}/api/agents`);
const agents = await response.json();
const agentList = document.getElementById('agentList');
if (agents.length === 0) {
agentList.innerHTML = '<div class="empty-state">暂无智能体注册</div>';
return;
}
agentList.innerHTML = agents.map(agent => {
const statusClass = agent.status === 'busy' ? 'busy' : 'idle';
const lastHeartbeat = new Date(agent.last_heartbeat).toLocaleString('zh-CN');
return `
<div class="agent-item ${statusClass}">
<strong>${agent.name}</strong>
<span class="badge ${agent.status}">${agent.status === 'idle' ? '空闲' : '忙碌'}</span>
<div class="task-meta">
类型: ${agent.type || '通用'} |
注册时间: ${new Date(agent.registered_at).toLocaleString('zh-CN')} |
最后心跳: ${lastHeartbeat}
</div>
</div>
`;
}).join('');
} catch (error) {
console.error('加载智能体列表失败:', error);
document.getElementById('agentList').innerHTML =
'<div class="empty-state">加载失败</div>';
}
}
// 加载任务列表
async function loadTasks() {
try {
const response = await fetch(`${API_BASE}/api/tasks`);
const tasks = await response.json();
const taskList = document.getElementById('taskList');
if (tasks.length === 0) {
taskList.innerHTML = '<div class="empty-state">暂无任务</div>';
return;
}
taskList.innerHTML = tasks.map(task => {
const statusText = {
'pending': '待处理',
'in_progress': '进行中',
'completed': '已完成'
}[task.status] || task.status;
const priorityText = {
'low': '低',
'normal': '普通',
'high': '高'
}[task.priority] || task.priority;
return `
<div class="task-item ${task.status}">
<strong>${task.title}</strong>
<span class="badge ${task.status}">${statusText}</span>
<span class="badge ${task.priority}">${priorityText}</span>
${task.description ? `<div style="margin-top: 8px; color: #666;">${task.description}</div>` : ''}
<div class="task-meta">
创建时间: ${new Date(task.created_at).toLocaleString('zh-CN')} |
${task.assigned_to ? `执行者: ${task.assigned_to}` : '未分配'} |
${task.completed_at ? `完成时间: ${new Date(task.completed_at).toLocaleString('zh-CN')}` : ''}
</div>
${task.result ? `<div style="margin-top: 8px; padding: 8px; background: #e8f4f8; border-radius: 4px;"><strong>结果:</strong> ${task.result}</div>` : ''}
</div>
`;
}).join('');
} catch (error) {
console.error('加载任务列表失败:', error);
document.getElementById('taskList').innerHTML =
'<div class="empty-state">加载失败</div>';
}
}
// 创建任务表单提交
document.getElementById('createTaskForm').addEventListener('submit', async (e) => {
e.preventDefault();
const title = document.getElementById('taskTitle').value;
const description = document.getElementById('taskDescription').value;
const priority = document.getElementById('taskPriority').value;
try {
const response = await fetch(`${API_BASE}/api/tasks`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
title,
description,
priority,
created_by: 'human'
})
});
const result = await response.json();
if (response.ok) {
alert('✅ 任务创建成功!');
document.getElementById('createTaskForm').reset();
loadTasks();
loadStats();
} else {
alert('❌ 创建失败: ' + result.error);
}
} catch (error) {
alert('❌ 创建失败: ' + error.message);
}
});
// 初始加载
loadStats();
loadAgents();
loadTasks();
// 自动刷新(每10秒)
setInterval(() => {
loadStats();
loadAgents();
loadTasks();
}, 10000);
</script>
</body>
</html>
+327
View File
@@ -0,0 +1,327 @@
const express = require('express');
const sqlite3 = require('sqlite3').verbose();
const cors = require('cors');
const bodyParser = require('body-parser');
const { v4: uuidv4 } = require('uuid');
const path = require('path');
const app = express();
const PORT = process.env.PORT || 3000;
// 中间件
app.use(cors());
app.use(bodyParser.json());
app.use(express.static('public'));
// 初始化数据库
const db = new sqlite3.Database('./agent_tasks.db', (err) => {
if (err) {
console.error('数据库连接失败:', err.message);
} else {
console.log('✅ 已连接到 SQLite 数据库');
initDatabase();
}
});
// 创建表结构
function initDatabase() {
db.serialize(() => {
// 智能体表
db.run(`CREATE TABLE IF NOT EXISTS agents (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
type TEXT,
capabilities TEXT,
status TEXT DEFAULT 'idle',
registered_at INTEGER,
last_heartbeat INTEGER
)`);
// 任务表
db.run(`CREATE TABLE IF NOT EXISTS tasks (
id TEXT PRIMARY KEY,
title TEXT NOT NULL,
description TEXT,
priority TEXT DEFAULT 'normal',
status TEXT DEFAULT 'pending',
created_by TEXT,
assigned_to TEXT,
created_at INTEGER,
updated_at INTEGER,
completed_at INTEGER,
result TEXT
)`);
console.log('✅ 数据库表已初始化');
});
}
// ==================== API 路由 ====================
// 1. 智能体注册
app.post('/api/agents/register', (req, res) => {
const { name, type, capabilities } = req.body;
if (!name) {
return res.status(400).json({ error: '智能体名称不能为空' });
}
const id = uuidv4();
const now = Date.now();
db.run(
`INSERT INTO agents (id, name, type, capabilities, status, registered_at, last_heartbeat)
VALUES (?, ?, ?, ?, 'idle', ?, ?)`,
[id, name, type || 'general', JSON.stringify(capabilities || []), now, now],
function(err) {
if (err) {
return res.status(500).json({ error: err.message });
}
res.json({
id,
name,
type: type || 'general',
status: 'idle',
message: '智能体注册成功'
});
}
);
});
// 2. 获取所有智能体
app.get('/api/agents', (req, res) => {
db.all('SELECT * FROM agents ORDER BY registered_at DESC', [], (err, rows) => {
if (err) {
return res.status(500).json({ error: err.message });
}
res.json(rows.map(row => ({
...row,
capabilities: JSON.parse(row.capabilities || '[]')
})));
});
});
// 3. 更新智能体状态(心跳)
app.post('/api/agents/:id/heartbeat', (req, res) => {
const { id } = req.params;
const { status } = req.body;
db.run(
'UPDATE agents SET status = ?, last_heartbeat = ? WHERE id = ?',
[status || 'idle', Date.now(), id],
function(err) {
if (err) {
return res.status(500).json({ error: err.message });
}
if (this.changes === 0) {
return res.status(404).json({ error: '智能体不存在' });
}
res.json({ message: '心跳更新成功' });
}
);
});
// 4. 创建任务
app.post('/api/tasks', (req, res) => {
const { title, description, priority, created_by } = req.body;
if (!title) {
return res.status(400).json({ error: '任务标题不能为空' });
}
const id = uuidv4();
const now = Date.now();
db.run(
`INSERT INTO tasks (id, title, description, priority, status, created_by, created_at, updated_at)
VALUES (?, ?, ?, ?, 'pending', ?, ?, ?)`,
[id, title, description || '', priority || 'normal', created_by || 'human', now, now],
function(err) {
if (err) {
return res.status(500).json({ error: err.message });
}
res.json({
id,
title,
status: 'pending',
message: '任务创建成功'
});
}
);
});
// 5. 获取所有任务
app.get('/api/tasks', (req, res) => {
const { status } = req.query;
let query = 'SELECT * FROM tasks';
let params = [];
if (status) {
query += ' WHERE status = ?';
params.push(status);
}
query += ' ORDER BY created_at DESC';
db.all(query, params, (err, rows) => {
if (err) {
return res.status(500).json({ error: err.message });
}
res.json(rows);
});
});
// 6. 领取任务
app.post('/api/tasks/:id/claim', (req, res) => {
const { id } = req.params;
const { agent_id } = req.body;
if (!agent_id) {
return res.status(400).json({ error: '需要提供智能体ID' });
}
db.get('SELECT status FROM tasks WHERE id = ?', [id], (err, task) => {
if (err) {
return res.status(500).json({ error: err.message });
}
if (!task) {
return res.status(404).json({ error: '任务不存在' });
}
if (task.status !== 'pending') {
return res.status(400).json({ error: '任务已被领取或已完成' });
}
db.run(
'UPDATE tasks SET status = ?, assigned_to = ?, updated_at = ? WHERE id = ?',
['in_progress', agent_id, Date.now(), id],
function(err) {
if (err) {
return res.status(500).json({ error: err.message });
}
// 同时更新智能体状态
db.run('UPDATE agents SET status = ? WHERE id = ?', ['busy', agent_id]);
res.json({ message: '任务领取成功' });
}
);
});
});
// 7. 更新任务状态
app.put('/api/tasks/:id', (req, res) => {
const { id } = req.params;
const { status, result } = req.body;
const now = Date.now();
const updates = [];
const params = [];
if (status) {
updates.push('status = ?');
params.push(status);
}
if (result !== undefined) {
updates.push('result = ?');
params.push(result);
}
if (status === 'completed') {
updates.push('completed_at = ?');
params.push(now);
}
updates.push('updated_at = ?');
params.push(now);
params.push(id);
db.run(
`UPDATE tasks SET ${updates.join(', ')} WHERE id = ?`,
params,
function(err) {
if (err) {
return res.status(500).json({ error: err.message });
}
if (this.changes === 0) {
return res.status(404).json({ error: '任务不存在' });
}
// 如果任务完成,将智能体状态改为 idle
if (status === 'completed') {
db.get('SELECT assigned_to FROM tasks WHERE id = ?', [id], (err, task) => {
if (task && task.assigned_to) {
db.run('UPDATE agents SET status = ? WHERE id = ?', ['idle', task.assigned_to]);
}
});
}
res.json({ message: '任务状态更新成功' });
}
);
});
// 8. 获取单个任务详情
app.get('/api/tasks/:id', (req, res) => {
db.get('SELECT * FROM tasks WHERE id = ?', [req.params.id], (err, row) => {
if (err) {
return res.status(500).json({ error: err.message });
}
if (!row) {
return res.status(404).json({ error: '任务不存在' });
}
res.json(row);
});
});
// 9. 统计信息
app.get('/api/stats', (req, res) => {
const stats = {
total_agents: 0,
active_agents: 0,
total_tasks: 0,
pending_tasks: 0,
in_progress_tasks: 0,
completed_tasks: 0
};
db.get('SELECT COUNT(*) as total FROM agents', [], (err, row) => {
if (!err && row) stats.total_agents = row.total;
db.get('SELECT COUNT(*) as active FROM agents WHERE status = "busy"', [], (err, row) => {
if (!err && row) stats.active_agents = row.active;
db.get('SELECT COUNT(*) as total FROM tasks', [], (err, row) => {
if (!err && row) stats.total_tasks = row.total;
db.get('SELECT COUNT(*) as pending FROM tasks WHERE status = "pending"', [], (err, row) => {
if (!err && row) stats.pending_tasks = row.pending;
db.get('SELECT COUNT(*) as in_progress FROM tasks WHERE status = "in_progress"', [], (err, row) => {
if (!err && row) stats.in_progress_tasks = row.in_progress;
db.get('SELECT COUNT(*) as completed FROM tasks WHERE status = "completed"', [], (err, row) => {
if (!err && row) stats.completed_tasks = row.completed;
res.json(stats);
});
});
});
});
});
});
});
// 启动服务器
app.listen(PORT, () => {
console.log(`🚀 多智能体任务服务已启动: http://localhost:${PORT}`);
});
// 优雅关闭
process.on('SIGINT', () => {
db.close((err) => {
if (err) {
console.error(err.message);
}
console.log('数据库连接已关闭');
process.exit(0);
});
});