474 lines
19 KiB
Markdown
474 lines
19 KiB
Markdown
|
|
# Swarm Command Center - 项目审计报告
|
|||
|
|
|
|||
|
|
> 初始审计日期:2026-03-10
|
|||
|
|
> 修复完成日期:2026-03-10
|
|||
|
|
> 审计范围:需求文档 vs 实际实现的完整比对
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、项目总体进度
|
|||
|
|
|
|||
|
|
### 修复后状态(2026-03-10 更新)
|
|||
|
|
|
|||
|
|
| 模块 | 完成度 | 状态 |
|
|||
|
|
|------|--------|------|
|
|||
|
|
| 后端服务层 (Services) | **95%** | ✅ 9 个核心服务全部实现并通过测试 |
|
|||
|
|
| 后端路由层 (Routers) | **100%** | ✅ **已修复** 全部 10 个路由模块正确接入服务层 |
|
|||
|
|
| 后端 CLI | **100%** | ✅ 所有命令已实现并正确调用服务层 |
|
|||
|
|
| 前端页面 | **95%** | ✅ 6 个页面全部实现,工作流上传已补全 |
|
|||
|
|
| 前端 API 客户端 | **100%** | ✅ **已修复** 封装全部 API 模块(含 Agent 控制) |
|
|||
|
|
| 前端-后端联调 | **95%** | ✅ **已修复** 路由→服务→存储全链路打通 |
|
|||
|
|
| API 集成测试 | **100%** | ✅ **新增** 43 个 API 端点测试全部通过 |
|
|||
|
|
| E2E 测试 | **60%** | ⚠️ 测试用例存在,选择器需要与 UI 保持同步 |
|
|||
|
|
|
|||
|
|
### 修复前状态(初始审计)
|
|||
|
|
|
|||
|
|
| 模块 | 完成度 | 状态 |
|
|||
|
|
|------|--------|------|
|
|||
|
|
| 后端路由层 (Routers) | ~~40%~~ | ~~多数路由使用 mock 数据,未接入服务层~~ |
|
|||
|
|
| 前端-后端联调 | ~~30%~~ | ~~后端路由返回 mock,前端获取假数据~~ |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 二、核心问题:路由层与服务层脱节
|
|||
|
|
|
|||
|
|
**这是项目最大的系统性问题。** 后端服务层已完整实现并通过测试,CLI 也正确接入了服务层。但 HTTP API 路由层(前端调用的入口)多数使用内存变量或硬编码 mock 数据,没有调用已实现的服务。
|
|||
|
|
|
|||
|
|
### 2.1 路由层状态明细
|
|||
|
|
|
|||
|
|
| 路由文件 | 前缀 | 数据源 | 接入服务层? |
|
|||
|
|
|----------|------|--------|-------------|
|
|||
|
|
| `agents.py` | `/api/agents` | 内存 `agents_db` + 硬编码默认 Agent | ❌ 未接入 `AgentRegistry` |
|
|||
|
|
| `locks.py` | `/api/locks` | 内存 `locks_db` + 硬编码默认锁 | ❌ 未接入 `FileLockService` |
|
|||
|
|
| `heartbeats.py` | `/api/heartbeats` | 硬编码 mock 返回值 | ❌ 未接入 `HeartbeatService` |
|
|||
|
|
| `meetings.py` | `/api/meetings` | 内存 `meetings_db` + 硬编码 mock | ❌ 未接入 `MeetingScheduler` / `MeetingRecorder` |
|
|||
|
|
| `resources.py` | `/api` | `/execute` `/parse-task` 为硬编码 mock | ⚠️ 仅 `/status` 接入了服务 |
|
|||
|
|
| `roles.py` | `/api/roles` | 全部硬编码 mock(固定返回 developer) | ❌ 未接入 `RoleAllocator` |
|
|||
|
|
| `workflows.py` | `/api/workflows` | 已调用 `WorkflowEngine` | ✅ **已正确接入** |
|
|||
|
|
| `humans.py` | `/api/humans` | 已调用 `HumanInputService` | ✅ **已正确接入** |
|
|||
|
|
| `agents_control.py` | `/api/agents/control` | 已调用 `ProcessManager` 等 | ✅ **已正确接入** |
|
|||
|
|
| `websocket.py` | `/ws` | 独立实现 | ✅ 正常 |
|
|||
|
|
|
|||
|
|
**结论**:10 个路由模块中,仅 3 个(workflows, humans, agents_control)正确接入了后端服务,6 个使用 mock 数据。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 三、API 端点需求 vs 实现对比
|
|||
|
|
|
|||
|
|
### 3.1 Agent API (`/api/agents`)
|
|||
|
|
|
|||
|
|
| 需求端点 | 方法 | 路由实现 | 接入服务 | 状态 |
|
|||
|
|
|----------|------|----------|----------|------|
|
|||
|
|
| `/api/agents` | GET | ✅ 存在 | ❌ 返回硬编码 | ⚠️ Mock |
|
|||
|
|
| `/api/agents/register` | POST | ✅ 存在 | ❌ 存内存 `agents_db` | ⚠️ Mock |
|
|||
|
|
| `/api/agents/:id` | GET | ✅ 存在 | ❌ 仅查内存 | ⚠️ Mock |
|
|||
|
|
| `/api/agents/:id/state` | GET | ✅ 存在 | ❌ 硬编码状态 | ⚠️ Mock |
|
|||
|
|
| `/api/agents/:id/state` | POST | ✅ 存在 | ❌ 存内存 | ⚠️ Mock |
|
|||
|
|
| `/api/agents/:id` | DELETE | ✅ 存在(额外) | ❌ 仅删内存 | ⚠️ Mock |
|
|||
|
|
|
|||
|
|
### 3.2 文件锁 API (`/api/locks`)
|
|||
|
|
|
|||
|
|
| 需求端点 | 方法 | 路由实现 | 接入服务 | 状态 |
|
|||
|
|
|----------|------|----------|----------|------|
|
|||
|
|
| `/api/locks` | GET | ✅ 存在 | ❌ 硬编码锁数据 | ⚠️ Mock |
|
|||
|
|
| `/api/locks/acquire` | POST | ✅ 存在 | ❌ 存内存 | ⚠️ Mock |
|
|||
|
|
| `/api/locks/release` | POST | ✅ 存在 | ❌ 仅删内存 | ⚠️ Mock |
|
|||
|
|
| `/api/locks/check` | GET | ✅ 存在 | ❌ 查内存 | ⚠️ Mock |
|
|||
|
|
|
|||
|
|
### 3.3 心跳 API (`/api/heartbeats`)
|
|||
|
|
|
|||
|
|
| 需求端点 | 方法 | 路由实现 | 接入服务 | 状态 |
|
|||
|
|
|----------|------|----------|----------|------|
|
|||
|
|
| `/api/heartbeats` | GET | ✅ 存在 | ❌ 硬编码 | ⚠️ Mock |
|
|||
|
|
| `/api/heartbeats/:id` | POST | ✅ 存在 | ❌ 存内存 | ⚠️ Mock |
|
|||
|
|
| `/api/heartbeats/timeouts` | GET | ❌ **缺失** | - | ❌ 未实现 |
|
|||
|
|
|
|||
|
|
### 3.4 会议 API (`/api/meetings`)
|
|||
|
|
|
|||
|
|
| 需求端点 | 方法 | 路由实现 | 接入服务 | 状态 |
|
|||
|
|
|----------|------|----------|----------|------|
|
|||
|
|
| `/api/meetings/create` | POST | ✅ 存在 | ❌ 存内存 | ⚠️ Mock |
|
|||
|
|
| `/api/meetings/:id/queue` | GET | ❌ **缺失** | - | ❌ 未实现 |
|
|||
|
|
| `/api/meetings/:id/wait` | POST | ❌ **缺失** | - | ❌ 未实现 |
|
|||
|
|
| `/api/meetings/:id/end` | POST | ❌ **缺失** | - | ❌ 未实现 |
|
|||
|
|
| `/api/meetings/record/create` | POST | ✅ 存在 | ❌ 存内存 | ⚠️ Mock |
|
|||
|
|
| `/api/meetings/:id/discuss` | POST | ✅ 存在 | ❌ 空返回 | ⚠️ Mock |
|
|||
|
|
| `/api/meetings/:id/progress` | POST | ✅ 存在 | ❌ 空返回 | ⚠️ Mock |
|
|||
|
|
| `/api/meetings/:id` | GET | ✅ 存在 | ❌ 返回 mock | ⚠️ Mock |
|
|||
|
|
| `/api/meetings/:id/finish` | POST | ✅ 存在 | ❌ 空返回 | ⚠️ Mock |
|
|||
|
|
| `/api/meetings` (列表) | GET | ✅ 存在 | ❌ 硬编码 | ⚠️ Mock |
|
|||
|
|
| `/api/meetings/today` | GET | ✅ 存在 | ❌ 硬编码 | ⚠️ Mock |
|
|||
|
|
|
|||
|
|
### 3.5 资源 API (`/api`)
|
|||
|
|
|
|||
|
|
| 需求端点 | 方法 | 路由实现 | 接入服务 | 状态 |
|
|||
|
|
|----------|------|----------|----------|------|
|
|||
|
|
| `/api/execute` | POST | ✅ 存在 | ❌ 硬编码返回 | ⚠️ Mock |
|
|||
|
|
| `/api/status` | GET | ✅ 存在 | ✅ 接入 Registry + Heartbeat | ✅ 正常 |
|
|||
|
|
| `/api/parse-task` | POST | ✅ 存在 | ❌ 硬编码返回 | ⚠️ Mock |
|
|||
|
|
|
|||
|
|
### 3.6 角色 API (`/api/roles`)
|
|||
|
|
|
|||
|
|
| 需求端点 | 方法 | 路由实现 | 接入服务 | 状态 |
|
|||
|
|
|----------|------|----------|----------|------|
|
|||
|
|
| `/api/roles/primary` | POST | ✅ 存在 | ❌ 固定返回 developer | ⚠️ Mock |
|
|||
|
|
| `/api/roles/allocate` | POST | ✅ 存在 | ❌ 轮询分配硬编码 | ⚠️ Mock |
|
|||
|
|
| `/api/roles/explain` | POST | ✅ 存在 | ❌ 固定文案 | ⚠️ Mock |
|
|||
|
|
|
|||
|
|
### 3.7 已正确实现的 API
|
|||
|
|
|
|||
|
|
| 路由模块 | 端点数 | 状态 |
|
|||
|
|
|----------|--------|------|
|
|||
|
|
| `workflows.py` | 11 个端点 | ✅ 全部接入 `WorkflowEngine` |
|
|||
|
|
| `humans.py` | 12 个端点 | ✅ 全部接入 `HumanInputService` |
|
|||
|
|
| `agents_control.py` | 12 个端点 | ✅ 全部接入 `ProcessManager` 等 |
|
|||
|
|
| `websocket.py` | 6 个端点 | ✅ 独立实现完整 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 四、后端代码问题
|
|||
|
|
|
|||
|
|
### 4.1 Bug
|
|||
|
|
|
|||
|
|
| 文件 | 问题 | 严重度 |
|
|||
|
|
|------|------|--------|
|
|||
|
|
| `agent_executor.py` | `json.dumps` 调用在函数内部局部 import(L442),虽不会 NameError 但不规范 | 低 |
|
|||
|
|
| `llm_service.py` | 使用 `aiohttp`(L439, L474)但 `requirements.txt` 中未声明 | 中 |
|
|||
|
|
| `native_llm_agent.py:278` | `# TODO: 实现投票机制` 未完成 | 低 |
|
|||
|
|
|
|||
|
|
### 4.2 缺失的 API 端点(需求文档要求但路由未实现)
|
|||
|
|
|
|||
|
|
| 端点 | 说明 |
|
|||
|
|
|------|------|
|
|||
|
|
| `GET /api/heartbeats/timeouts` | 检查超时 Agent |
|
|||
|
|
| `GET /api/meetings/:id/queue` | 获取会议等待队列 |
|
|||
|
|
| `POST /api/meetings/:id/wait` | 栅栏同步等待 |
|
|||
|
|
| `POST /api/meetings/:id/end` | 结束会议 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 五、前端问题
|
|||
|
|
|
|||
|
|
### 5.1 功能缺失
|
|||
|
|
|
|||
|
|
| 问题 | 位置 | 说明 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| 工作流 YAML 上传 | `WorkflowPage.tsx:480` | 注释 "这里应该调用后端 API 上传文件",为占位逻辑 |
|
|||
|
|
| API 地址不可配置 | `api.ts:15` | `API_BASE` 硬编码 `localhost:8000`,Settings 页面的 API 地址配置不生效 |
|
|||
|
|
| Agent 控制 API 未封装 | `AgentsPage.tsx` | 直接 `fetch('/agents/control/*')`,未使用 `api.ts` 封装 |
|
|||
|
|
|
|||
|
|
### 5.2 UI 与数据问题
|
|||
|
|
|
|||
|
|
| 问题 | 位置 | 说明 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| 进度条宽度 | `MeetingsPage.tsx` | `width: meeting.progress_summary` 为字符串 "50%",应为数值 |
|
|||
|
|
| 遗留组件未使用 | `components/` 根级 | `AgentStatusCard`、`ResourceMonitorCard`、`RecentMeetingsCard`、`ConsensusCard` 含 mock 数据,未被任何页面引用 |
|
|||
|
|
|
|||
|
|
### 5.3 E2E 测试与 UI 不一致
|
|||
|
|
|
|||
|
|
| 测试期望 | 实际 UI | 文件 |
|
|||
|
|
|----------|---------|------|
|
|||
|
|
| `input[placeholder="搜索 Agent..."]` | AgentsPage 无搜索框 | `e2e-workflow.spec.ts` |
|
|||
|
|
| `input[name="name"]`, `select[name="role"]` | 表单无 name 属性 | `e2e-workflow.spec.ts` |
|
|||
|
|
| `text=创建新会议` | 实际文案 "创建会议" | `e2e-workflow.spec.ts` |
|
|||
|
|
| `button:has-text("新建工作流")` | 无此按钮 | `e2e-workflow.spec.ts` |
|
|||
|
|
| `input[name="apiBaseUrl"]` | 配置表单无 name | `e2e-workflow.spec.ts` |
|
|||
|
|
| `text=配置已保存` | 实际文案 "已保存" | `e2e-workflow.spec.ts` |
|
|||
|
|
| `[data-testid="agent-list"]` | 未使用 data-testid | `e2e-workflow.spec.ts` |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 六、设计文档与实现的不一致
|
|||
|
|
|
|||
|
|
| 设计文档要求 | 实际实现 | 差异说明 |
|
|||
|
|
|-------------|----------|----------|
|
|||
|
|
| API 层使用 Express/Fastify (Node.js) | 使用 Python FastAPI | CLAUDE.md 中已更正,design-spec 未同步 |
|
|||
|
|
| 前端使用 shadcn/ui | 纯 Tailwind CSS + 自定义样式 | 未使用 shadcn/ui 组件库 |
|
|||
|
|
| 前端使用 Zustand 状态管理 | 使用 React useState + useEffect | 无全局状态管理 |
|
|||
|
|
| 前端使用 WebSocket 实时更新 | 使用轮询(5-10 秒) | WebSocket 后端已实现但前端未接入 |
|
|||
|
|
| Consensus Engine(共识引擎) | 未作为独立服务实现 | 共识逻辑在 MeetingRecorder 中 |
|
|||
|
|
| Model Router(模型路由) | 在 LLMService 中实现 | 位置不同但功能存在 |
|
|||
|
|
| `.doc/dialogues/` 目录 | 不存在 | 对话存储未实现 |
|
|||
|
|
| `.doc/progress/` 目录 | 不存在 | 进度存储在 Agent state 中 |
|
|||
|
|
| `.doc/shared/` 目录 | 不存在 | 共享知识库未实现 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 七、后端测试结果
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
StorageService [PASS] ✅
|
|||
|
|
FileLockService [PASS] ✅
|
|||
|
|
HeartbeatService [PASS] ✅
|
|||
|
|
AgentRegistry [PASS] ✅
|
|||
|
|
MeetingScheduler [PASS] ✅
|
|||
|
|
MeetingRecorder [PASS] ✅
|
|||
|
|
ResourceManager [PASS] ✅
|
|||
|
|
WorkflowEngine [PASS] ✅
|
|||
|
|
RoleAllocator [PASS] ✅
|
|||
|
|
总计: 9/9 通过
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 未覆盖的服务测试
|
|||
|
|
|
|||
|
|
| 服务 | 说明 |
|
|||
|
|
|------|------|
|
|||
|
|
| HumanInputService | 路由已接入,但缺少单独测试 |
|
|||
|
|
| LLMService | 需要 API Key,难以自动化 |
|
|||
|
|
| AgentExecutor | 依赖 LLM,需 mock 测试 |
|
|||
|
|
| ProcessManager | 需要实际进程管理环境 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 八、后续修改步骤(按优先级排序)
|
|||
|
|
|
|||
|
|
### 阶段 1:路由层接入服务层(P0 - 最高优先级)
|
|||
|
|
|
|||
|
|
这是整个项目的核心瓶颈,完成后前后端即可真正联通。
|
|||
|
|
|
|||
|
|
#### 步骤 1.1:改造 `agents.py` 路由
|
|||
|
|
```
|
|||
|
|
目标:用 AgentRegistry 服务替换内存 agents_db
|
|||
|
|
涉及:backend/app/routers/agents.py
|
|||
|
|
方法:
|
|||
|
|
1. 导入 get_agent_registry
|
|||
|
|
2. list_agents → registry.list_agents()
|
|||
|
|
3. register_agent → registry.register_agent()
|
|||
|
|
4. get_agent → registry.get_agent()
|
|||
|
|
5. get/update_agent_state → registry.get_state() / update_state()
|
|||
|
|
6. 删除 agents_db、agent_states_db 内存变量
|
|||
|
|
验证:curl /api/agents 返回真实数据(或空列表)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 步骤 1.2:改造 `locks.py` 路由
|
|||
|
|
```
|
|||
|
|
目标:用 FileLockService 替换内存 locks_db
|
|||
|
|
涉及:backend/app/routers/locks.py
|
|||
|
|
方法:
|
|||
|
|
1. 导入 get_file_lock_service
|
|||
|
|
2. list_locks → service.get_locks()
|
|||
|
|
3. acquire_lock → service.acquire_lock()
|
|||
|
|
4. release_lock → service.release_lock()
|
|||
|
|
5. check_lock → service.check_locked()
|
|||
|
|
6. 删除 locks_db 硬编码数据
|
|||
|
|
验证:curl /api/locks 返回空列表或真实锁状态
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 步骤 1.3:改造 `heartbeats.py` 路由
|
|||
|
|
```
|
|||
|
|
目标:用 HeartbeatService 替换硬编码返回
|
|||
|
|
涉及:backend/app/routers/heartbeats.py
|
|||
|
|
方法:
|
|||
|
|
1. 导入 get_heartbeat_service
|
|||
|
|
2. list_heartbeats → service.get_all_heartbeats()
|
|||
|
|
3. update_heartbeat → service.update_heartbeat()
|
|||
|
|
4. 新增 GET /timeouts?timeout_seconds=60 端点
|
|||
|
|
验证:curl /api/heartbeats 返回真实数据
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 步骤 1.4:改造 `meetings.py` 路由
|
|||
|
|
```
|
|||
|
|
目标:用 MeetingScheduler + MeetingRecorder 替换 mock
|
|||
|
|
涉及:backend/app/routers/meetings.py
|
|||
|
|
方法:
|
|||
|
|
1. 导入 get_meeting_scheduler, get_meeting_recorder
|
|||
|
|
2. 列表/详情 → recorder.list_meetings() / recorder.get_meeting()
|
|||
|
|
3. 创建 → recorder.create_meeting() + scheduler.create_meeting()
|
|||
|
|
4. 讨论/进度/完成 → recorder.add_discussion() / update_progress() / end_meeting()
|
|||
|
|
5. 新增 GET /:id/queue → scheduler.get_queue()
|
|||
|
|
6. 新增 POST /:id/wait → scheduler.wait_for_meeting()
|
|||
|
|
7. 新增 POST /:id/end → scheduler.end_meeting()
|
|||
|
|
验证:创建会议 → 查看列表 → 添加讨论 → 完成会议 全流程
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 步骤 1.5:改造 `roles.py` 路由
|
|||
|
|
```
|
|||
|
|
目标:用 RoleAllocator 替换硬编码
|
|||
|
|
涉及:backend/app/routers/roles.py
|
|||
|
|
方法:
|
|||
|
|
1. 导入 get_role_allocator
|
|||
|
|
2. get_primary_role → allocator.get_primary_role()
|
|||
|
|
3. allocate_roles → allocator.allocate_roles()
|
|||
|
|
4. explain_roles → allocator.explain_allocation()
|
|||
|
|
验证:curl /api/roles/primary 返回基于任务分析的角色
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 步骤 1.6:改造 `resources.py` 路由
|
|||
|
|
```
|
|||
|
|
目标:用 ResourceManager 替换 mock
|
|||
|
|
涉及:backend/app/routers/resources.py
|
|||
|
|
方法:
|
|||
|
|
1. 导入 get_resource_manager
|
|||
|
|
2. execute_task → manager.execute_task()
|
|||
|
|
3. parse_task → manager.parse_task_files()
|
|||
|
|
验证:/api/execute 真正执行任务(加锁→执行→释放锁)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 阶段 2:修复代码问题(P1)
|
|||
|
|
|
|||
|
|
#### 步骤 2.1:修复依赖
|
|||
|
|
```
|
|||
|
|
文件:backend/requirements.txt
|
|||
|
|
操作:添加 aiohttp 依赖
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 步骤 2.2:前端 API 地址可配置
|
|||
|
|
```
|
|||
|
|
文件:frontend/src/lib/api.ts
|
|||
|
|
操作:
|
|||
|
|
1. API_BASE 从 localStorage 读取(Settings 页面保存的值)
|
|||
|
|
2. 提供 fallback 默认值 http://localhost:8000/api
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 步骤 2.3:封装 Agent 控制 API
|
|||
|
|
```
|
|||
|
|
文件:frontend/src/lib/api.ts + frontend/src/pages/AgentsPage.tsx
|
|||
|
|
操作:
|
|||
|
|
1. 在 api.ts 中添加 agentControlApi 模块
|
|||
|
|
2. AgentsPage 改用封装的 API 调用
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 步骤 2.4:修复进度条宽度问题
|
|||
|
|
```
|
|||
|
|
文件:frontend/src/pages/MeetingsPage.tsx
|
|||
|
|
操作:progress_summary 为 "50%" 字符串,作为 CSS width 值可以工作,
|
|||
|
|
但建议改为数值计算更健壮
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 阶段 3:补全缺失功能(P2)
|
|||
|
|
|
|||
|
|
#### 步骤 3.1:实现工作流 YAML 上传
|
|||
|
|
```
|
|||
|
|
后端:新增 POST /api/workflows/upload 端点
|
|||
|
|
前端:WorkflowPage.tsx handleFileUpload 对接真实 API
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 步骤 3.2:前端接入 WebSocket
|
|||
|
|
```
|
|||
|
|
目标:替代轮询,使用 WebSocket 实时更新
|
|||
|
|
文件:新增 frontend/src/lib/websocket.ts
|
|||
|
|
操作:
|
|||
|
|
1. 连接 ws://localhost:8000/ws/client/{clientId}
|
|||
|
|
2. Dashboard、Resources 页面订阅实时事件
|
|||
|
|
3. 保留轮询作为降级方案
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 步骤 3.3:清理遗留组件
|
|||
|
|
```
|
|||
|
|
组件:AgentStatusCard, ResourceMonitorCard, RecentMeetingsCard, ConsensusCard
|
|||
|
|
操作:评估是否仍需要,不需要则删除,需要则替换 mock 数据为 API 调用
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 阶段 4:测试完善(P2)
|
|||
|
|
|
|||
|
|
#### 步骤 4.1:更新 E2E 测试选择器
|
|||
|
|
```
|
|||
|
|
文件:frontend/tests/e2e-workflow.spec.ts
|
|||
|
|
操作:将测试选择器更新为与当前 UI 一致
|
|||
|
|
- 搜索框选择器
|
|||
|
|
- 表单 name 属性
|
|||
|
|
- 按钮文案
|
|||
|
|
- data-testid 属性
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 步骤 4.2:补充后端路由集成测试
|
|||
|
|
```
|
|||
|
|
位置:backend/
|
|||
|
|
操作:
|
|||
|
|
1. 新增 test_api_integration.py
|
|||
|
|
2. 使用 TestClient 测试所有 API 端点
|
|||
|
|
3. 验证路由→服务→存储完整链路
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 步骤 4.3:补充服务测试
|
|||
|
|
```
|
|||
|
|
新增测试:
|
|||
|
|
- HumanInputService 单元测试
|
|||
|
|
- ProcessManager 单元测试
|
|||
|
|
- AgentExecutor mock 测试(mock LLM 调用)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 阶段 5:同步文档(P3)
|
|||
|
|
|
|||
|
|
#### 步骤 5.1:更新设计文档
|
|||
|
|
```
|
|||
|
|
文件:docs/design-spec.md
|
|||
|
|
操作:
|
|||
|
|
1. API 层技术栈改为 Python FastAPI(非 Express/Fastify)
|
|||
|
|
2. 前端技术栈更新(无 shadcn/ui,无 Zustand)
|
|||
|
|
3. 存储目录结构与实际一致
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 九、推荐执行顺序
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Week 1: 阶段 1(路由层改造)
|
|||
|
|
Day 1: agents.py + locks.py
|
|||
|
|
Day 2: heartbeats.py + meetings.py
|
|||
|
|
Day 3: roles.py + resources.py
|
|||
|
|
Day 4: 联调验证,修复接口对接问题
|
|||
|
|
|
|||
|
|
Week 2: 阶段 2 + 3(代码修复 + 缺失功能)
|
|||
|
|
Day 1: 依赖修复 + API 地址可配置
|
|||
|
|
Day 2: Agent 控制 API 封装 + 进度条修复
|
|||
|
|
Day 3: 工作流上传实现
|
|||
|
|
Day 4: WebSocket 接入(可选)
|
|||
|
|
|
|||
|
|
Week 3: 阶段 4 + 5(测试 + 文档)
|
|||
|
|
Day 1-2: E2E 测试更新
|
|||
|
|
Day 3: 后端集成测试
|
|||
|
|
Day 4: 文档同步
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 十、风险提示
|
|||
|
|
|
|||
|
|
1. **路由改造可能引发前端数据格式变化**:当前前端适配的是 mock 数据的格式,改为真实服务后,返回值字段名/结构可能不同,需要同步调整前端代码。
|
|||
|
|
|
|||
|
|
2. **会议的栅栏同步是阻塞调用**:`wait_for_meeting` 会阻塞请求直到所有参会者到齐,在 HTTP API 中需要设置合适的超时时间,或改为异步轮询机制。
|
|||
|
|
|
|||
|
|
3. **RoleAllocator 依赖 LLM API**:如果没有配置 API Key,角色分配会使用 fallback 逻辑,需要确认 fallback 行为是否满足需求。
|
|||
|
|
|
|||
|
|
4. **数据持久化**:服务层使用 `.doc/` 目录文件存储,路由改造后原来内存中的临时数据会丢失,需要确保前端能正确处理空数据状态。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 附录:修复记录(2026-03-10)
|
|||
|
|
|
|||
|
|
### 已完成的修改
|
|||
|
|
|
|||
|
|
| 序号 | 修改项 | 文件 | 说明 |
|
|||
|
|
|------|--------|------|------|
|
|||
|
|
| 1 | agents.py 路由改造 | `backend/app/routers/agents.py` | 移除 `agents_db` 内存变量,接入 `AgentRegistry` 服务 |
|
|||
|
|
| 2 | locks.py 路由改造 | `backend/app/routers/locks.py` | 移除 `locks_db` 硬编码数据,接入 `FileLockService` 服务 |
|
|||
|
|
| 3 | heartbeats.py 路由改造 | `backend/app/routers/heartbeats.py` | 移除 mock 返回,接入 `HeartbeatService`,新增 `/timeouts` 端点 |
|
|||
|
|
| 4 | meetings.py 路由改造 | `backend/app/routers/meetings.py` | 移除 mock,接入 `MeetingScheduler` + `MeetingRecorder`,新增 `/queue` `/wait` `/end` 端点 |
|
|||
|
|
| 5 | roles.py 路由改造 | `backend/app/routers/roles.py` | 移除硬编码角色分配,接入 `RoleAllocator` 服务 |
|
|||
|
|
| 6 | resources.py 路由改造 | `backend/app/routers/resources.py` | 移除 mock,`/execute` `/parse-task` 接入 `ResourceManager` |
|
|||
|
|
| 7 | 依赖修复 | `backend/requirements.txt` | 添加 `aiohttp>=3.9.0` |
|
|||
|
|
| 8 | API 地址可配置 | `frontend/src/lib/api.ts` | `API_BASE` 从 localStorage 读取,Settings 页面配置生效 |
|
|||
|
|
| 9 | Agent 控制 API 封装 | `frontend/src/lib/api.ts` | 新增 `agentControlApi` 模块,统一封装 |
|
|||
|
|
| 10 | AgentsPage 去硬编码 | `frontend/src/pages/AgentsPage.tsx` | 移除 `API_BASE` 硬编码,使用 `agentControlApi` |
|
|||
|
|
| 11 | 工作流上传功能 | `backend/app/routers/workflows.py` + `frontend/src/pages/WorkflowPage.tsx` | 新增 `POST /upload` 端点,前端实现真实上传 |
|
|||
|
|
| 12 | API 集成测试 | `backend/test_api_integration.py` | 新增 43 项 API 端点集成测试 |
|
|||
|
|
|
|||
|
|
### 测试结果
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
服务层测试: 9/9 通过
|
|||
|
|
API 集成测试: 43/43 通过
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 剩余待办
|
|||
|
|
|
|||
|
|
| 优先级 | 项目 | 说明 |
|
|||
|
|
|--------|------|------|
|
|||
|
|
| P2 | WebSocket 实时更新 | 前端仍用轮询,后端 WebSocket 已实现但前端未接入 |
|
|||
|
|
| P2 | 清理遗留组件 | `AgentStatusCard` 等 4 个含 mock 数据的旧组件未被引用 |
|
|||
|
|
| P3 | E2E 测试选择器同步 | 约 7 处选择器/文案与当前 UI 不一致 |
|
|||
|
|
| P3 | 设计文档同步 | `design-spec.md` 中技术栈描述需更新 |
|
|||
|
|
| P3 | 补充服务测试 | HumanInputService、ProcessManager、AgentExecutor 缺少单独测试 |
|