feat: virtual company M2 control + tier-3/4 capabilities + per-dept session fix

- M2-a/b/c: stop/pause/resume/skip dept, plan/rework approval gates,
  budget & timeout circuit breakers, per-dept cancel and on-demand rework
- tier-3: batched event persistence (_EventBuffer), project/dept
  concurrency semaphores, company_ws event streaming
- tier-4: cross-dept deliverable handoff, CEO memory feedback loop,
  per-dept model override, one-click Markdown report export (RFC5987)
- fix: per-department independent SQLAlchemy session in parallel waves
  (shared Session race across asyncio tasks in company_orchestrator)
- fix: rename process_open_fds gauge to app_process_open_fds
  (collides with prometheus_client ProcessCollector on Linux)
- fix: dept role resolution ladder, real token usage & cost tracking,
  deliverable file capture (mtime scan of dept workspace)
- tests: test_company_orchestrator.py 22 cases with mocked LLM
- frontend: CompanyControlRoom, companyExecution store, EChart,
  dept model config dialog, ws proxy, build/typecheck decoupling
- docs: virtual company design/usage docs, M2 control plan,
  deepseek4pro handover docs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-26 18:16:39 +08:00
parent eef48ce831
commit 495eafcd78
39 changed files with 5733 additions and 574 deletions

69
docs/M2_control_plan.md Normal file
View File

@@ -0,0 +1,69 @@
# 虚拟公司「运行时控制」(M2) 规划文档
> 状态:M2-a(能力 1–4)已排期实施;M2-b/c 登记待办。
> 关联:M1 白盒控制室(可观测)已完成;一档(部门角色匹配 + 可信真实 token/成本¥)已完成并验证。
> 更新:2026-07-12
## 背景与动机
白盒控制室(M1)解决了「看得见」,一档解决了「数据可信」(真实 token + 成本¥,实测一次运行约 ¥9.88、耗时 ~60 分钟)。但目前**只能看不能动**:一次运行跑歪了,只能干等到结束或直接杀进程。M2 给控制室补上「运行时控制」,让人能在长运行过程中干预。
M2 拆成 **10 项可独立验收的原子能力**,按依赖与价值分三片交付。一次全做改动面广、验证成本高(单次运行 ~1 小时),故分片。
## 架构基线(现状,已逐点核实)
- **同进程模型**:`company_runner.spawn()` 在 API(uvicorn)进程内 `asyncio.create_task` 起编排任务,句柄存 `_RUNNING: Dict[str, asyncio.Task]`。API handler 与编排任务同进程 → 控制用「进程内注册表 + 协作检查点」即可,无需 DB/消息队列。
- **停止半成品**:已有 `CancelledError → status=stopped` + 落 `company_terminated` 事件的雏形,缺「按 project_id 取消」的 helper 与对外端点。
- **编排检查点**:`company_orchestrator.execute_stream` 有干净的注入点——轮次顶、就绪部门选取、事件抽取循环、波次边界。
- **事件单写者**:编排器 `yield` → runner `_persist_event` 落库并分配单调 `seq`。控制确认事件必须走编排器 yield,避免 API 直接写库造成 seq 竞争。
- **可复用件**:`approval_manager.py`(asyncio.Event 式 create/wait/resolve,供审批);round-to-round rework 过滤(供单部门返工);一档已累计的 `company_cost_yuan`(供预算熔断)。
## 10 项能力总览
| # | 能力 | 片 | 机制 / 复用点 | 关键取舍 |
|---|------|----|----------------|----------|
| 1 | **停止**(硬取消整公司运行) | M2-a | `company_runner.stop(pid)` = `_RUNNING[pid].cancel()`,复用 `CancelledError→stopped` 雏形 | 打断在飞 LLM,立即生效 |
| 2 | **暂停**(hold,不开新波次) | M2-a | `ProjectControl.pause_event.clear()`;编排器波次/轮次边界 `await wait()` | 在飞部门跑完才 hold(部门粒度 ~15min 延迟) |
| 3 | **继续**(resume) | M2-a | `pause_event.set()` | — |
| 4 | **跳过部门**(skip 未开始部门) | M2-a | `control.skip_depts`;就绪选取处拦截并 `completed_names.add` 让下游推进 | 仅未开始部门;在跑部门不停 |
| 5 | **单部门返工**(对已完成项目只重跑一个部门,不重跑整公司) | M2-c | 复用 rework 过滤(`failed_names→filtered_plans→current_plans`),单部门子集外部驱动;新 `POST …/rework {department_name}` | 需读回历史 ceo_plan/产出做上下文 |
| 6 | **审批·CEO 计划**(花钱前把关) | M2-b | 复用 `approval_manager.py`;CEO 规划后 `yield awaiting_approval → await → 放行/改计划` | 阻塞式,带 timeout 兜底 |
| 7 | **审批·部门评分/返工**(返工前把关) | M2-b | 同上,插在 CEO 打分后、决定返工前 | — |
| 8 | **预算熔断**(成本超 ¥X 自动停) | M2-b | 把 advisory 预算检查改**强制**:读运行中 `company_cost_yuan`,超阈值 → `budget_tripped` + 触发停止 | 阈值入 `company.config["budget"]`;按 ¥ 而非 token |
| 9 | **超时熔断**(总耗时超 N 分钟自动停) | M2-b | 新增 deadline:编排器起始记 `t0`,检查点比对(当前无任何 timeout,仅事后判僵尸) | 与预算熔断共用「自动停」出口 |
| 10 | **单部门取消**(取消在跑的某部门,非停整公司) | M2-c | 为每个 `_run_department_stream` task 建 per-dept 句柄表,`cancel` 单个;team 层需容错半途取消 | 比 skip 复杂,需 team_orchestrator 配合 |
## 分片与依赖
- **M2-a(本片)· 核心四控**:1 停止、2 暂停、3 继续、4 跳过。共用「进程内控制注册表 + 编排检查点」,自成闭环、最易验证。
- **M2-b · 把关与自动停**:6/7 人在环审批(`approval_manager`)+ 8 预算熔断 + 9 超时熔断(8/9 共用「自动停」出口,与一档成本累计联动)。
- **M2-c · 部门粒度**:5 单部门返工 + 10 单部门取消(都要 per-dept 粒度的重跑/取消,最深,放最后)。
**依赖顺序**:8/9 熔断依赖 1 停止的出口;5 返工依赖一档产出落库;10 取消依赖 per-dept task 句柄。故 1–4 必须先行。
## M2-a 设计要点(本片实施)
### 后端
- `company_runner.py`:`ProjectControl{pause_event, skip_depts}` + `_CONTROL` 注册表 + `get_control/clear_control` + `stop(pid)`(取消 `_RUNNING[pid]`,复用 stopped 雏形);done-callback 清理控制态。
- `company_orchestrator.execute_stream`:惰性 `import company_runner`,起始取 `control`;**暂停闸**(轮次顶 + 波次边界,`await pause_event.wait()`,yield `paused`/`resumed`);**跳过闸**(就绪选取处拦 `skip_depts`,标记 `completed_names` 让下游推进,yield `dept_skipped`)。
- `companies.py`:`POST …/projects/{pid}/{stop|pause|resume|skip}` 四端点,`_assert_company_owner`;pause/resume/skip 需 `is_running`(否则 409),pause/resume 同步 `project.status`。
### 前端
- `api/companies.ts`:`stopProject/pauseProject/resumeProject/skipDepartment`(镜像 `recoverProject` POST)。
- `stores/companyExecution.ts`:state `paused/controlPending`;action `stop/pause/resume/skipDept`;`applyEvent` 加 `paused/resumed/dept_skipped` 归并。
- `views/CompanyControlRoom.vue`:控制栏(暂停/继续/停止,停止带 `ElMessageBox.confirm`)+ 每部门 `waiting` 时显「跳过」;状态标签显「已暂停」。
### 语义取舍(写进 UI 提示)
- **停止** = 硬取消,立即 → stopped(打断在飞 LLM)。
- **暂停** = 只拦新波次/新轮次,在飞部门跑完才 hold(部门粒度延迟);`/pause` 即时置 `status=paused` 缓解 UI 反馈。
- **跳过** = 仅未开始部门;在跑部门跳过留 M2-c(能力 10)。
- **进程内状态**:进程重启则控制态随运行任务一起消失(任务本就死),无持久化需求;单 worker 假设(与 `_RUNNING` 一致)。
## 验证(端到端)
1. 重启后端 + `npm run build`(= vite)。
2. 起一次 async 运行。
3. 暂停/继续:`/pause` → status=paused、下一波不启动、`paused` 事件;`/resume` → `resumed` 且继续。
4. 跳过:对 `waiting` 部门 `/skip` → `dept_skipped`、下游依赖照常推进、该部门不产生 agent 事件。
5. 停止:`/stop` → 取消、落 `company_terminated`、status=stopped、WS `_stream_end`。
6. 前端按钮可用(停止有确认)、断线重连控制态从事件流恢复。
7. 回归:不点任何控制的普通运行仍正常完成(检查点在未暂停/无跳过时是 no-op)。

View File

@@ -193,7 +193,36 @@
- **执行管理**:支持手动触发、暂停/恢复、执行状态跟踪
- **飞书推送**:定时任务执行结果自动推送到飞书(Webhook + 应用消息)
### 12. 飞书集成和通知系统
### 12. 虚拟团队(Team Orchestrator)
- **多 Agent 流水线**:PM 规划 → Design → Dev → QA → DevOps 顺序执行
- **TeamOrchestrator**:~1975 行,管理团队内 Agent 编排与上下文传递
- **SSE 流式执行**:实时推送每步执行状态
- **交付物管理**:自动捕获团队产出文件
### 13. 虚拟公司(Company Orchestrator)
> 最近半年投入最大的模块,在虚拟团队之上加第 3 级组织。
- **三级组织**:Company → Department(复用 Team)→ Member(Agent)
- **三阶段执行**:CEO 规划(需求分析→部门拆分→任务分配)→ 部门并行(DAG 拓扑排序)→ CEO 评审(打分+返工)
- **四档迭代**(M1 后全部完成):
- 一档:基础 MVP(CEO 规划→执行→评审)
- 二档:人工审批 / 返工 / 预算 / 6 个行业预设模板
- 三档-a:事件批量落库(_EventBuffer,N=25/T=0.7s)
- 三档-b:并发上限+排队(_PROJECT_SEM 信号量,MAX_CONCURRENT_COMPANY_PROJECTS=3)
- 四档-①:部门间上下文交接(_build_dept_context)
- 四档-②:公司学习闭环(自动沉淀+注入历史知识)
- 四档-③:按部门配模型(Team.config["model_override"])
- 四档-④:一键导出运行报告(RFC 5987 Markdown)
- **per-dept 独立 session**(2026-07-26 K3 改造):消除共享 db_orch 竞态
- **核心文件**:
- `services/company_orchestrator.py`(~1600 行)
- `services/company_runner.py`(~350 行)
- `api/companies.py`(~950 行)
- `api/company_ws.py`(~150 行,WebSocket 事件推送)
### 14. 飞书集成和通知系统
- **通知系统**:统一的通知管理(notifications 表、通知服务、API)
- **飞书定时任务推送**:定时任务执行结果自动推送飞书
- **飞书应用消息**:通过飞书应用 API 发送消息通知
@@ -232,14 +261,19 @@ aiagent/
│ │ │ ├── agent_monitoring.py # Agent 监控 API 5 个端点
│ │ │ ├── agent_schedules.py # Agent 定时任务 CRUD API + 手动触发
│ │ │ ├── feishu_bind.py # 飞书账号绑定/解绑 API
│ │ │ └── notifications.py # 通知系统 API
│ │ │ ├── notifications.py # 通知系统 API
│ │ │ ├── companies.py # 公司 + 项目 CRUD API(~950 行)
│ │ │ └── company_ws.py # 公司 WebSocket 事件推送
│ │ ├── core/ # 核心模块
│ │ ├── models/ # 数据库模型
│ │ │ ├── agent_llm_log.py # Agent LLM 调用日志模型
│ │ │ ├── agent_learning_pattern.py # Agent 学习模式模型(自主学习)
│ │ │ ├── agent_schedule.py # Agent 定时任务调度模型
│ │ │ ├── notification.py # 通知模型
│ │ │ └── agent_vector_memory.py # Agent 向量记忆表模型
│ │ │ ├── agent_vector_memory.py # Agent 向量记忆表模型
│ │ │ ├── company.py # 公司/项目/知识模型
│ │ │ ├── company_project_event.py # 项目事件日志模型
│ │ │ └── company_knowledge.py # 公司知识沉淀模型
│ │ ├── schemas/ # Pydantic模式
│ │ ├── services/ # 业务逻辑
│ │ │ ├── agent_monitoring_service.py # Agent 监控服务
@@ -254,7 +288,12 @@ aiagent/
│ │ │ ├── knowledge_service.py # 知识库 RAG 服务
│ │ │ ├── embedding_service.py # Embedding 生成服务
│ │ │ ├── document_parser.py # 文档解析器
│ │ │ └── text_chunker.py # 文本分块器
│ │ │ ├── text_chunker.py # 文本分块器
│ │ │ ├── company_orchestrator.py # 虚拟公司编排器(~1600 行)
│ │ │ ├── company_runner.py # 公司项目运行管理器(~350 行)
│ │ │ ├── company_knowledge_extractor.py # 公司知识自动提取
│ │ │ ├── company_presets.py # 6 个行业预设模板
│ │ │ └── team_orchestrator.py # 虚拟团队编排器(~1975 行)
│ │ └── main.py # 应用入口
│ ├── alembic/ # 数据库迁移
│ ├── tests/ # 测试
@@ -380,6 +419,29 @@ pnpm dev
- `GET /api/v1/agent-monitoring/tool-usage?days=7` - 工具调用频次统计
- `GET /api/v1/agent-monitoring/daily-trend?days=7` - 每日 LLM 调用趋势
### 虚拟公司 API(新增)
- `GET /api/v1/companies` — 公司列表
- `POST /api/v1/companies` — 创建公司
- `GET /api/v1/companies/{id}` — 公司详情
- `DELETE /api/v1/companies/{id}` — 删除公司
- `GET /api/v1/companies/{id}/export` — 导出公司报告(RFC 5987 Markdown)
- `POST /api/v1/companies/{id}/projects` — 创建公司项目
- `POST /api/v1/companies/{id}/projects/{pid}/execute` — 同步执行
- `POST /api/v1/companies/{id}/projects/{pid}/execute/async` — 异步执行
- `GET /api/v1/companies/{id}/projects` — 项目列表
- `GET /api/v1/companies/{id}/projects/{pid}` — 项目详情
- `POST /api/v1/companies/{id}/projects/{pid}/stop` — 停止项目
- `GET /api/v1/companies/{id}/projects/{pid}/report` — 导出项目报告
- `WS /api/v1/ws/company/{pid}` — 实时事件推送(DB 轮询,0.8s 间隔)
### 虚拟团队 API(新增)
- `GET /api/v1/teams` — 团队列表
- `POST /api/v1/teams` — 创建团队
- `POST /api/v1/teams/{id}/execute` — 执行团队项目
- `POST /api/v1/teams/{id}/execute/stream` — 执行(SSE 流式)
### WebSocket API
- `ws://localhost:8037/ws/execution/{execution_id}` - 执行状态实时推送
@@ -505,6 +567,14 @@ alembic downgrade -1
- **Agent 自主学习**: 100% ✅(2026-05 新增)
- **Agent 定时任务系统**: 100% ✅(2026-05 新增)
- **飞书通知与机器人对话**: 100% ✅(2026-05 新增)
- **虚拟团队(TeamOrchestrator)**: 100% ✅(2026-06 新增)
- **虚拟公司 MVP(一档)**: 100% ✅(2026-06 新增)
- **虚拟公司 二档**(审批/返工/预算/模板): 100% ✅(2026-07 新增)
- **虚拟公司 三档-a/b**(事件批量落库+并发上限): 100% ✅(2026-07 新增)
- **虚拟公司 四档**(交接/学习闭环/按部门配模型/导出报告): 100% ✅(2026-07 新增)
- **per-dept 独立 session**(K3 改造): 100% ✅(2026-07-26)
- **编排器测试 22 个**: 100% ✅(2026-07-26)
- **演示项目 4 个**: 100% ✅
- **整体项目**: 约 99.9%
### 已完成核心功能
@@ -534,6 +604,14 @@ alembic downgrade -1
24. **Agent 自主学习** - 从历史执行中自动优化工具选择策略(AgentLearningPattern)
25. **Agent 定时任务系统** - cron 表达式定时触发 Agent 执行,集成 Celery Beat
26. **飞书通知与机器人对话** - 通知系统、飞书定时任务推送、橙子飞书机器人
27. **虚拟团队编排** - TeamOrchestrator(~1975 行),PM→Design→Dev→QA→DevOps 流水线
28. **虚拟公司编排** - CompanyOrchestrator(~1600 行),CEO 规划→部门并行→评审返工
29. **事件批量落库** - _EventBuffer(add_all + commit),N=25/T=0.7s
30. **并发上限+排队** - _PROJECT_SEM 信号量,MAX_CONCURRENT_COMPANY_PROJECTS=3
31. **学习闭环** - 自动沉淀 CompanyKnowledge + 注入历史知识到 CEO
32. **一键导出报告** - RFC 5987 编码,Markdown 格式项目运行报告
33. **per-dept 独立 session** - 消除共享 db_orch 竞态(K3 2026-07-26)
34. **编排器测试** - 22 个 pytest(CEO JSON/知识过滤/交接上下文/全流程 mock)
### 近期规划
1. **多租户支持** - 租户模型、数据隔离、资源配额管理
@@ -576,25 +654,35 @@ alembic downgrade -1
- **前端服务(Docker)**:http://localhost:8038
- **问题反馈**:查看项目文档或联系开发团队
## 关键文档索引(建议)
## 演示项目
- Windows 启停唯一文档:[`(红头)Windows服务器启动与重启唯一指南.md`](./(红头)Windows服务器启动与重启唯一指南.md)
- 上传图片与OCR实现:[`(红头)上传图片和识别的实现文档.md`](./(红头)上传图片和识别的实现文档.md)
- 教育行业批量Agent脚本:`backend/scripts/create_education_agents_batch.py`
- 政务/媒体批量Agent脚本:`backend/scripts/create_gov_media_agents_batch.py`
- 企业场景批量Agent脚本:`backend/scripts/create_enterprise_scenario_agents.py`
- 自主 AI Agent 改造完成情况:[`自主AI Agent改造完成情况.md`](./自主AI%20Agent改造完成情况.md)
- Agent Runtime 源码入口:`backend/app/agent_runtime/core.py`
- Agent 聊天 API 路由:`backend/app/api/agent_chat.py`
- Agent 聊天前端页面:`frontend/src/views/AgentChat.vue`
- Agent 配置页面:`frontend/src/views/AgentConfig.vue`
- 多 Agent 编排引擎:`backend/app/agent_runtime/orchestrator.py`
- Agent 监控 Dashboard:`frontend/src/views/AgentDashboard.vue`
- Agent LLM 调用日志模型:`backend/app/models/agent_llm_log.py`
| # | 项目 | 生成方式 | 状态 |
|---|------|----------|------|
| 1 | Framework 知识管理软件 | 虚拟团队 | 可运行(Vue3 + FastAPI + SQLite) |
| 2 | 「今天吃啥」渭南家常菜 | 虚拟公司 | 可运行(69 道菜,PWA) |
| 3 | 家庭阅读激励工具 | 虚拟公司 | 设计文档(PRD/原型),无代码 |
| 4 | 家庭泡饮制作助手 | 虚拟公司 + 人工打磨 | 可直接用(59 款饮品,真图,纯前端) |
> 详细启动方式见 `docs/天工虚拟团队演示项目.md`
## 关键文档索引
- **项目管理**:[`天工平台项目管理.md`](../../../mkdocs/docs/Obsidian笔记体系/Projects/agent/天工平台项目管理.md)(Obsidian)
- **Windows 启停**:[`docs/startup-deploy/(红头)Windows服务器启动与重启唯一指南(1.0版本).md`](../startup-deploy/(红头)Windows服务器启动与重启唯一指南(1.0版本).md)
- **Git 上传**:[`docs/startup-deploy/上传git仓.md`](../startup-deploy/上传git仓.md)
- **平台资料**:[`docs/平台资料.md`](../平台资料.md)(Gitea + 项目结构速查)
- **商业化计划**:[`docs/商业化落地计划.md`](../商业化落地计划.md)
- **演示项目**:[`docs/天工虚拟团队演示项目.md`](../天工虚拟团队演示项目.md)
- **K3 交接资料**:[`docs/deepseek4pro交接/`](../deepseek4pro交接/)(6 份)
- **虚拟公司迭代方案**:`.claude/projects/D--cd-claude-code/memory/project_company_roadmap.md`
- **Agent Runtime 源码入口**:`backend/app/agent_runtime/core.py`
- **公司编排器**:`backend/app/services/company_orchestrator.py`
- **团队编排器**:`backend/app/services/team_orchestrator.py`
- **编排器测试**:`backend/tests/test_company_orchestrator.py`(22 个)
---
**最后更新**: 2026-05-02
**文档版本**: 1.7
**最后更新**: 2026-07-26
**文档版本**: 2.0
*本文档基于项目现有文档整理生成,涵盖项目核心信息。详细技术方案请参考[方案-优化版.md](./方案-优化版.md)。DeepSeek 模型名与 Base URL 以官方文档为准,变更时请同步修订本节。*

View File

@@ -1,429 +0,0 @@
# 解决缺失能力计划
## 总体策略
按梯队分阶段实施。每个阶段聚焦 2-3 个能力,完成即可独立提升系统质量。
每阶段包含:涉及文件、核心改动、验证方式。
---
## 第一阶段:闭环质量(1-2 周)
优先解决"输出质量验证",这是连接自主进化系统的最后一环。
### 1.1 输出质量验证 → 新增 `evaluator` 节点 + `self_review` 工具
**目标:** Agent 执行完后自动检查输出质量,不达标则自我修正。
**方案:**
#### A. 新增 `self_review` 工具(第 35 个内置工具)
```
self_review(content="...", criteria="回答必须包含SQL优化建议和执行计划")
→ {
"score": 0.75,
"passed": true,
"issues": ["缺少具体执行计划"],
"suggestions": ["补充EXPLAIN输出分析"]
}
```
**实现:** 用 LLM 作为评判器(deepseek-v4-flash,轻量调用),根据 criteria 打分 0-1。
#### B. 新增 `evaluator` 工作流节点类型
在工作流引擎中添加 evaluator 节点:
- 接收上游节点输出 + 评判标准(criteria)
- 调用 LLM 评判输出质量
- 输出 `{score, passed, issues, suggestions}`
- 配合 condition 节点:`passed=false` → 走修正分支 → 重试
#### C. AgentRuntime 内建 self-review
在 AgentRuntime ReAct 循环末尾添加可选的 self-review 步骤:
- `AgentConfig` 添加 `self_review: bool = False`
- 启用后,Agent 在返回最终答案前自动调用 `self_review`
- 评分 < 0.6 则追加一轮修正迭代
**涉及文件:**
| 文件 | 改动 |
|------|------|
| `backend/app/services/builtin_tools.py` | 新增 `self_review_tool` + `SELF_REVIEW_SCHEMA` |
| `backend/app/core/tools_bootstrap.py` | 34→35,import + register |
| `backend/app/services/workflow_engine.py` | 新增 `evaluator` 节点类型 |
| `backend/app/agent_runtime/core.py` | 末尾添加 self-review 步骤 |
| `backend/app/agent_runtime/schemas.py` | AgentConfig 添加 `self_review` 字段 |
| `frontend/src/utils/agentSkills.ts` | 新增条目 |
**验证:**
1. `self_review("SELECT * FROM t", "需要包含索引建议")` → score < 0.5
2. 工作流:agent → evaluator(criteria="...") → condition(passed?) → 正常结束 / 修正重试
3. 全能助手对话测试:问一个复杂问题,开启 self_review,确认输出质量提升
---
### 1.2 节点级自动重试
**目标:** error_handler 从空壳变为真正的重试机制。
**方案:**
修改 `error_handler` 节点执行逻辑:
```
当上游节点 status == "failed" 时:
1. 检查 retry_count(剩余重试次数)
2. 等待 retry_delay 秒
3. 重新执行上游节点(复用 get_node_input + execute_node)
4. 成功 → 继续流程
5. 失败且 retry_count > 0 → 循环
6. 失败且 retry_count == 0 → 触发 on_error 动作
```
`on_error` 动作:
- `stop`:抛出错误停止工作流
- `notify`:发送告警继续
- `skip`:跳过该节点继续
**涉及文件:**
| 文件 | 改动 |
|------|------|
| `backend/app/services/workflow_engine.py` | 重写 error_handler 节点逻辑 |
| `backend/app/core/exceptions.py` | 添加 `NodeRetryExhausted` 异常 |
**验证:**
1. 模拟 LLM 超时 → error_handler 重试 3 次 → 第 3 次成功 → 继续
2. 模拟连续失败 → error_handler 耗尽重试 → 触发 on_error=notify → 告警记录
---
## 第二阶段:编排整合(2-3 周)
### 2.1 Orchestrator 进入工作流
**目标:** 4 种编排模式变为工作流节点类型。
**方案:**
新增 `orchestrator` 工作流节点类型,数据配置:
```json
{
"mode": "route | sequential | debate | pipeline",
"agents": ["agent_id_1", "agent_id_2", ...],
"routing_prompt": "用于 route 模式的路由指令",
"aggregation_prompt": "用于 debate 模式的汇总指令"
}
```
`workflow_integration.py` 添加 `run_orchestrator_node()`:
- 解析 node_data 中的 agent 列表
- 从 DB 加载 Agent 配置
- 创建 AgentOrchestrator 实例
- 执行对应模式,返回结构化结果
**涉及文件:**
| 文件 | 改动 |
|------|------|
| `backend/app/agent_runtime/workflow_integration.py` | 新增 `run_orchestrator_node()` |
| `backend/app/services/workflow_engine.py` | 新增 orchestrator 节点类型 |
| `frontend/src/utils/agentSkills.ts` | 无需改动(后端节点类型) |
**验证:**
1. 创建工作流:start → orchestrator(debate, [AgentA, AgentB, AgentC]) → end
2. 执行:确认 3 个 Agent 均被调用,结果被汇总
3. 创建工作流:start → orchestrator(route, [代码助手, 数据分析师]) → end,确认按路由分发
---
### 2.2 工具级人工审批
**目标:** 危险工具执行前暂停等待用户确认。
**方案:**
#### A. AgentToolConfig 扩展
```python
class AgentToolConfig(BaseModel):
include_tools: List[str] = []
exclude_tools: List[str] = []
require_approval: List[str] = [] # 新增:需要审批的工具名列表
```
#### B. AgentRuntime 审批拦截
在 ReAct 循环的工具执行环节(`core.py` 约 287 行):
```
if tool_name in config.tools.require_approval:
yield ApprovalRequest(tool_name, tool_args) # 暂停,等待外部确认
decision = await wait_for_approval() # 阻塞等待
if decision != "approved":
continue # 跳过该工具调用
```
#### C. WebSocket 审批通道
- AgentRuntime 暂停时通过 WebSocket 推送审批请求
- 用户通过 WebSocket 回复 approve/deny
- 超时默认策略可配置(approve/deny/skip)
**涉及文件:**
| 文件 | 改动 |
|------|------|
| `backend/app/agent_runtime/schemas.py` | AgentToolConfig 添加 require_approval |
| `backend/app/agent_runtime/core.py` | 工具执行前审批拦截 |
| `backend/app/websocket/manager.py` | 添加审批消息类型 |
**验证:**
1. 配置 Agent: `require_approval: ["deploy_push"]`
2. Agent 调用 deploy_push → WebSocket 收到审批请求
3. 用户 approve → Agent 继续执行
4. 用户 deny → Agent 跳过该工具
---
## 第三阶段:性能与效率(2-3 周)
### 3.1 并行执行
**目标:** 无依赖节点并行执行,Orchestrator debate 并行。
**方案:**
#### A. 工作流 DAG 并行
修改 `execute()` 主循环:
```
当前:每轮取 1 个节点执行
改为:每轮取所有"前置节点全部完成"的节点,asyncio.gather 并行执行
```
注意事项:
- 并行节点不能有共享状态依赖
- 需要分别捕获每个并行节点的异常
- WebSocket 需支持多节点同时推送进度
#### B. Orchestrator debate 并行
```python
# 改前
for agent in agents:
result = await agent.run(query)
# 改后
results = await asyncio.gather(*[agent.run(query) for agent in agents])
```
**涉及文件:**
| 文件 | 改动 |
|------|------|
| `backend/app/services/workflow_engine.py` | execute() 并行执行 |
| `backend/app/agent_runtime/orchestrator.py` | debate/sequential 并行 |
| `backend/app/websocket/manager.py` | 支持多节点并发推送 |
**验证:**
1. 3 个独立分支的 DAG → 总耗时 ≈ 最长分支耗时(而非三者之和)
2. debate 模式 3 Agent → 总耗时 ≈ 最慢 Agent 耗时
---
### 3.2 粒度进度上报
**目标:** 实时推送"第 3/7 步完成"到前端。
**方案:**
#### A. WorkflowEngine 进度回调
在 `execute()` 循环中添加钩子:
```python
async def on_progress(self, current_step, total_steps, node_name, status):
# 推送到 WebSocket
await ws_manager.broadcast(execution_id, {
"type": "progress",
"current": current_step,
"total": total_steps,
"node": node_name,
"status": status,
"percent": int(current_step / total_steps * 100),
})
```
#### B. 统计 DAG 总步数
执行前遍历拓扑排序结果,计算可达节点总数作为 total_steps。
#### C. WebSocket 改为推送模式
当前是轮询 DB,改为 WorkflowEngine 主动调用 WebSocket manager 推送。
**涉及文件:**
| 文件 | 改动 |
|------|------|
| `backend/app/services/workflow_engine.py` | 添加 on_progress 回调 + 步数统计 |
| `backend/app/websocket/manager.py` | 添加 execution 进度推送方法 |
| `backend/app/api/websocket.py` | 适配新的推送模式 |
**验证:**
1. 执行 7 节点的 DAG → WebSocket 收到 7 条进度消息
2. 前端进度条从 0% 逐步递增到 100%
---
### 3.3 结果缓存
**目标:** 相同输入不重复计算。
**方案:**
添加缓存层,使用 Redis:
```python
# 工具结果缓存
cache_key = f"tool:{tool_name}:{hash(json.dumps(args))}"
cached = await redis.get(cache_key)
if cached:
return cached.decode()
# LLM 响应缓存(相同 prompt + 相同 messages)
cache_key = f"llm:{hash(messages_json)}"
```
配置:
- TTL 默认 1 小时
- 工具维度可选开启/关闭
- 确定性工具(file_read、math_calculate)默认开启
- 非确定性工具(web_search、http_request)默认关闭
**涉及文件:**
| 文件 | 改动 |
|------|------|
| `backend/app/agent_runtime/tool_manager.py` | 工具执行前后加缓存层 |
| `backend/app/agent_runtime/core.py` | LLM 调用前后加缓存层 |
| `backend/app/core/config.py` | 添加缓存配置项 |
**验证:**
1. 连续两次相同 file_read → 第二次命中缓存(耗时 < 1ms)
2. 连续两次相同 math_calculate → 第二次命中缓存
---
## 第四阶段:容错与共享(2-3 周)
### 4.1 降级/回退链
**目标:** 模型/Agent 失败自动切换备用方案。
**方案:**
AgentLLMConfig 扩展:
```python
class AgentLLMConfig(BaseModel):
provider: str = "openai"
model: str = "gpt-4o-mini"
fallback_llm: Optional['AgentLLMConfig'] = None # 降级模型
```
Agent 节点 data 扩展:
```json
{
"fallback_agent": "备选Agent的ID" // 可选
}
```
执行逻辑:
1. 主模型调用失败 → 切换 fallback_llm 重试
2. Agent 执行失败 → 查找 fallback_agent 重试
3. 所有备用方案都失败 → 抛出错误
**涉及文件:**
| 文件 | 改动 |
|------|------|
| `backend/app/agent_runtime/schemas.py` | AgentLLMConfig 添加 fallback_llm |
| `backend/app/agent_runtime/core.py` | LLM 调用失败后切换 fallback |
| `backend/app/services/workflow_engine.py` | Agent 节点失败后切换 fallback_agent |
---
### 4.2 Agent 间知识共享
**目标:** 打破记忆隔离,Agent 间共享知识。
**方案:**
添加全局知识索引层:
```
每个 Agent 执行完成后 → 提取关键知识 → 写入 global_knowledge 表
Agent 初始化时 → 从 global_knowledge 加载相关条目
```
实现:
- 新增 `GlobalKnowledge` 模型(content, embedding, source_agent_id, tags, created_at)
- `AgentMemory.initialize()` 添加全局知识检索步骤
- 自主进化创建的 Agent 自动继承创建者的知识
**涉及文件:**
| 文件 | 改动 |
|------|------|
| `backend/app/models/agent.py` | 新增 GlobalKnowledge 模型 |
| `backend/app/agent_runtime/memory.py` | initialize() 添加全局知识加载 |
| `backend/app/agent_runtime/core.py` | 执行完毕提取知识写入全局 |
---
### 4.3 Agent 异步执行实现
**目标:** 填空 `execute_agent_task`,支持真正异步 Agent 执行。
**方案:**
`execute_agent_task` 当前是空壳,需要实现:
```python
@celery_app.task
def execute_agent_task(agent_id, query, user_id):
db = SessionLocal()
agent = db.query(Agent).filter(Agent.id == agent_id).first()
config = build_agent_config_from_db(agent)
runtime = AgentRuntime(config)
result = asyncio.run(runtime.run(query))
# 更新 execution 记录
return {"status": "completed", "output": result.content}
```
**涉及文件:**
| 文件 | 改动 |
|------|------|
| `backend/app/tasks/agent_tasks.py` | 实现 execute_agent_task |
| `backend/app/tasks/scheduler_tasks.py` | 调度触发真正的异步执行 |
---
## 实施路线图总览
```
第一阶段(1-2周)
├── 1.1 输出质量验证:self_review工具 + evaluator节点 + AgentRuntime自检
└── 1.2 节点级自动重试:error_handler从空壳到真正重试
第二阶段(2-3周)
├── 2.1 Orchestrator进入工作流:新增orchestrator节点类型
└── 2.2 工具级人工审批:AgentToolConfig审批标记 + WebSocket审批通道
第三阶段(2-3周)
├── 3.1 并行执行:DAG并行 + Orchestrator debate并行
├── 3.2 粒度进度上报:on_progress回调 + WebSocket推送
└── 3.3 结果缓存:Redis缓存层
第四阶段(2-3周)
├── 4.1 降级/回退链:fallback_llm + fallback_agent
├── 4.2 Agent知识共享:GlobalKnowledge + 跨Agent检索
└── 4.3 Agent异步执行:填空execute_agent_task
```
## 优先级逻辑
- **第一阶段优先**:质量验证是自主进化的最后一环,没有它进化无方向;重试是稳定性基础
- **第二阶段其次**:编排整合让复杂任务可视化、安全化
- **第三阶段提速**:并行 + 缓存大幅提升性能(生产部署前必备)
- **第四阶段收尾**:容错和共享让系统长期运行可持续

View File

@@ -0,0 +1,80 @@
# 天工智能体平台 — 项目概览
> 给 Kimi K3 的项目全景速览。建议按编号顺序阅读。
## 这是什么
**天工智能体平台**(Tiangong AI Agent Platform)是一个企业级 AI 智能体(Agent)构建与运营平台。用户可以:
- 创建/配置 LLM Agent(温度、系统提示、工具、知识库、记忆)
- 将 Agent 组成**虚拟团队**(Team)→ 多 Agent 按角色顺序协作执行项目
- 将虚拟团队进一步组织为**虚拟公司**(Company),CEO 规划→部门并行→汇总评分
- 用编排画布(工作流)拖拽构建自动化流水线
- 对话交互(Web Chat + Android App + 飞书集成)
定位:面向非开发者的 AI 自动化平台,核心差异化在「虚拟团队/公司」的多 Agent 编排。
## 技术栈速览
| 层 | 技术 |
|---|------|
| 前端 | Vue 3 (Composition API) + Vite + Pinia + Element Plus + TypeScript |
| 后端 | FastAPI (Python 3.12) + SQLAlchemy 2.0 + Pydantic 2 |
| 数据库 | MySQL 8.0(腾讯云远程) + Redis 7(本地) |
| 异步 | asyncio + Celery(Redis broker) |
| 认证 | JWT (OAuth2PasswordBearer) |
| LLM | DeepSeek v4-pro(主力),SiliconFlow(Embedding),OpenAI/Anthropic(备用) |
| 部署 | Docker Compose,云端服务器 101.43.95.130 |
## 关键数字
- **245+** API 端点(45 个路由模块)
- **43** 数据模型
- **80+** Service 文件
- **41** 个前端页面/视图
- **59** 款饮品产出(demo 项目,见 05 号文档)
- 代码仓库只 1 人维护(renjianbo)
## 目录结构(简版)
```
aiagent/
├── frontend/ # Vue 3 前端(:3001 dev)
│ └── src/
│ ├── views/ # 41 个页面
│ ├── api/ # Axios 请求封装
│ ├── stores/ # Pinia 状态
│ └── router/ # 路由 + Auth guard
├── backend/ # FastAPI 后端(:8037)
│ └── app/
│ ├── api/ # 45 个路由模块
│ ├── services/ # 80+ 业务逻辑文件
│ ├── models/ # 43 个 SQLAlchemy 模型
│ ├── core/ # 配置/数据库/安全/中间件
│ └── main.py # FastAPI 入口 + 路由注册 + 中间件链
├── team_projects/ # 虚拟团队/公司的文件产出目录
├── company_projects/ # 虚拟公司工作区
├── deliverables/ # 精选成品项目(人工打磨后的可直接用产物)
├── docs/ # 文档
├── scripts/ # 启动/运维脚本
└── docker-compose.dev.yml # Docker 开发环境
```
## 核心概念关系
```
Agent(智能体:系统提示+工具+模型+知识库+记忆)
└─ 可加入多个 Team
└─ Team(团队:多 Agent 按角色编排,顺序流水线)
└─ 可选归属给 Company(公司,做为企业部门)
└─ Company(公司:3 级架构)
└─ Company > Project(项目)
├─ Phase1: CEO 规划(分析→部门拆分→任务分配)
├─ Phase2: 部门并行执行(多波,依赖驱动的拓扑排序)
└─ Phase3: CEO 评审 + 打分 + 返工
```
## 谁在用
- **管理员**:Web 管理后台(:3001),Agent/团队/公司/工作流全管理
- **终端用户**:Android App(对话交互)+ 飞书 App(多应用机器人)
- **开发者**:本地 localhost 开发,所有后端 API 有 `/docs`(Swagger)

View File

@@ -0,0 +1,78 @@
# 架构与技术栈详解
## 完整技术栈
| 层级 | 技术 | 版本 | 备注 |
|------|------|------|------|
| 前端框架 | Vue 3 (Composition API) | 3.4+ | SFC + `<script setup>` |
| 前端构建 | Vite | 5+ | HMR 极速热更 |
| 前端 UI | Element Plus | 2.4+ | 组件库 |
| 状态管理 | Pinia | 2+ | 按模块拆分 store |
| 路由 | Vue Router | 4+ | SPA + 导航守卫 |
| HTTP 客户端 | Axios / fetch | — | 请求/响应拦截 |
| 后端框架 | FastAPI | 0.110+ | 自动 OpenAPI 文档 |
| ORM | SQLAlchemy | 2.0+ | async session |
| 数据验证 | Pydantic | 2+ | BaseSettings 读 .env |
| 数据库 | MySQL | 8.0 | 腾讯云远程(生产);本地可选 |
| 缓存/队列 | Redis | 7+ | Celery broker + 缓存 |
| 任务队列 | Celery | 5.3+ | 工作流异步执行 |
| 认证 | JWT | — | OAuth2PasswordBearer,access + refresh |
| LLM | DeepSeek v4-pro | — | 主力模型;SiliconFlow 做 Embedding |
| 部署 | Docker Compose | — | Nginx + FastAPI + Celery Worker |
## 后端中间件链
FastAPI 注册顺序(`main.py`):CORS → RateLimiter(Redis 滑动窗口)→ BehaviorCollection(用户行为采集,异步写 MySQL)→ SecurityHeaders(HSTS 等)→ UsageMiddleware(用量统计)
```
请求 → CORS → 限流 → 行为采集 → 安全头 → 用量 → 路由 → 响应
```
## 数据库连接
- **开发**:直连腾讯云 MySQL(通过 `.env` 中的 `DATABASE_URL`)
- **会话管理**:`core/database.py` 提供 `SessionLocal`(同步)+ `AsyncSessionLocal`(异步)
- **连接池**:默认 30 连接(SQLAlchemy `pool_size=20`, `max_overflow=10`)
- **关键注意**:虚拟公司模块在并行执行时会共享 `db_orch` session(已知风险,留待 per-dept 独立 session 改修)
## 路由注册
所有路由挂载在 `/api/v1/` 前缀下(`main.py:97-199`),通过 `app.include_router()` 逐个注册:
- `agents`、`auth`、`users`、`teams`、`companies`、`workflows`、`knowledge_base`、`tools`、`uploads`、`agent_chat`、`agent_memory`、`monitoring`、`notifications`、`billing`、`workspaces` 等 45 个模块
WebSocket 路由:`/ws/chat/{agent_id}`(Agent 对话)、`/api/v1/ws/company/{project_id}`(虚拟公司事件推送)
## 前端路由
41 条路由(`router/index.ts`),含 `requiresAuth` 守卫。关键页面:
- `/login` — 登录页(:3001)
- `/agents` — Agent 管理
- `/teams` — 团队管理
- `/companies` — 公司管理(CompanyBuilder.vue)
- `/companies/:companyId/projects/:projectId/monitor` — 控制室(CompanyControlRoom.vue)
- `/workflows` — 工作流设计器
- `/knowledge` — 知识库
- `/monitoring` — 系统监控
- `/workspaces` — 多租户工作区
## 部署拓扑
```
┌──────────────┐
│ Nginx :80 │ ← 反向代理 + SSL 终止
└──────┬───────┘
┌───────────┼───────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 前端 SPA │ │FastAPI │ │Celery │
│ :3001 │ │:8037 │ │Worker │
│(dev) │ │(dev) │ │ │
└──────────┘ └────┬─────┘ └────┬─────┘
│ │
┌─────▼────┐ ┌────▼──────┐
│MySQL 8.0 │ │ Redis 7 │
│(腾讯云) │ │(本地) │
└──────────┘ └───────────┘
```
开发环境:前端 Vite dev :3001,后端 uvicorn :8037(无 `--reload`,改代码需手动重启)

View File

@@ -0,0 +1,98 @@
# 核心模块详解
## 模块地图
```
backend/app/
├── api/ → 路由层(参数解析、鉴权、调用 service)
├── services/ → 业务逻辑(真正的计算/编排/LLM 交互)
├── models/ → SQLAlchemy ORM 定义
├── core/ → 基础设施(配置、DB 连接、安全、中间件)
└── main.py → 应用入口
```
## 一、Agent 系统(最核心)
agent_runtime 目录 + `services/llm_service.py` + `services/agent_learning_service.py`
### Agent 运行时
- `agent_runtime/agent_executor.py`:Agent 执行器,ReAct 循环(Thought → Action → Observation),function calling,工具调用
- `agent_runtime/tool_registry.py`:工具注册中心,所有 Agent 共享
- `agent_runtime/builtin_tools.py`:内置工具集(file_read/write、web_search、http_request、code_exec 等 20+ 工具)
- `agent_runtime/memory_service.py`:Agent 记忆管理(短期对话 + 长期向量记忆,Redis + MySQL 持久化)
### LLM 服务
- `services/llm_service.py`:统一 LLM 调用入口,支持多 provider(DeepSeek/OpenAI/Anthropic/SiliconFlow)
- 自动 token 计数、function calling 响应解析、fallback 退路
- **默认模型**:`deepseek/deepseek-v4-pro`(`agent_runtime/agent_executor.py:83-84` 的 `_build_agent_config`)
### 学习闭环
- `services/agent_learning_service.py`:从对话日志中自动提取知识,写入知识库
- `services/knowledge_extractor.py`:关键信息抽取(正则 + LLM)
## 二、虚拟团队(Team Orchestrator)
`services/team_orchestrator.py`(约 2200 行)
### 核心流程
1. **PM 规划**:项目经理 Agent 分析需求,输出 JSON 执行计划(4~7 个阶段,含角色/任务/依赖)
2. **顺序流水线**:按阶段顺序执行,每个阶段由指定角色的 Agent 执行
3. **文件产出**:Agent 调用 `file_write` 将代码/文档/配置写入指定项目目录(`team_projects/{team_id}/{project_name}/`)
4. **QA 审查**:最后一个 QA 阶段汇总审核所有交付物,输出缺陷报告和评分
5. **SSE 流式推送**:实时推送每个阶段的开始/完成/进度事件
### 关键设计
- Agent 配置从 Team 成员的角色定义读取(`_build_agent_config` 方法映射 member 的 role/temperature/model 到 Agent)
- 项目目录自动解析:`_resolve_workspace_root()` → `team_projects/{team_id}/`
- 文件扫描:`_scan_directory_files` + `_scan_recent_files`(双保险,捕获 Agent 写出的所有文件)
## 三、虚拟公司(Company Orchestrator)
`services/company_orchestrator.py`(约 1600 行)+ `services/company_runner.py`(约 350 行)
详见 **03-虚拟公司模块.md**。
## 四、工作流引擎
`services/workflow_engine.py` + `services/workflow_templates.py`
### 功能
- 可视化拖拽编排:通过 Node Templates(可复用的节点模板)+ 画布连接构建工作流
- 节点类型:start / llm / tool / template / condition / loop / parallel / code / end
- 执行引擎:拓扑排序 + DAG 并行(无依赖的节点并发执行)
- Celery 异步执行(`tasks/`)
- 单次执行熔断:`WORKFLOW_MAX_STEPS_PER_RUN=2000`、`WORKFLOW_MAX_LLM_INVOCATIONS_PER_RUN=200`
## 五、知识库
`services/knowledge_service.py` + `services/knowledge_retriever.py` + `services/embedding_service.py`
### 功能
- 知识条目 CRUD,支持 Markdown、PDF、网页导入
- Embedding 向量化(SiliconFlow `bce-embedding-base_v1`)
- 向量检索(Redis)+ 全文检索(MySQL LIKE/REGEXP),混合排序
- Agent 对话时自动检索相关知识点注入上下文
## 六、飞书集成
`services/feishu_*.py` 系列(7 个文件)
### 功能
- 多应用机器人:每个飞书应用独立 WebSocket 连接,路由到对应 Agent
- 卡片消息:`feishu_card_builder.py` 构建交互式卡片
- Open ID 绑定:`feishu_open_id_service.py` 管理飞书用户↔平台用户映射
- 支持应用:灵犀、苏瑶、人参果、橙子助手、甜甜、飞书通知
## 七、多租户工作区
- `workspace_service.py`:工作区 CRUD + 用户↔工作区权限
- `permission_service.py`:RBAC 角色(admin/member/viewer)
- `api/workspaces.py`、`api/permissions.py`:对应 API
## 八、监控与计费
- `agent_monitoring_service.py`:Agent 运行状态/对话量/错误率
- `monitoring_service.py`:系统级监控
- `cost_estimator.py`:LLM token → 成本估算(按各 provider 定价)
- `billing.py`:计费模型(sub_id → 额度管理)
- `execution_budget.py`:虚拟公司执行预算管理

View File

@@ -0,0 +1,114 @@
# 虚拟公司模块
> 这是**最近半年投入最大的模块**,占代码增量的大头。如果 Kimi K3 想深入理解项目,这是最重要的文档。
## 概念
虚拟公司 = 在虚拟团队(Team)之上加第 3 级组织:
```
Company(公司,如「西安瑞来兹软件科技有限公司」)
├─ Department A(部门,复用 Team,parent_company_id 关联)
│ ├─ Member (Agent)
│ └─ ...
├─ Department B
│ └─ ...
└─ Department C
└─ ...
Company > Project(项目,如「家庭泡饮制作助手」)
├─ Phase1: CEO 规划(分析需求→部门拆分→任务分配→生成 ceo_plan JSON)
├─ Phase2: 部门并行执行(Department 按依赖 DAG 拓扑排序分波执行)
└─ Phase3: CEO 评审 + 打分 + 返工(可选多轮)
```
## 核心文件
| 文件 | 行数 | 职责 |
|------|------|------|
| `services/company_orchestrator.py` | ~1600 | 公司编排器:CEO 规划、部门调度、评审、返工 |
| `services/company_runner.py` | ~350 | 运行管理器:启动/停止/取消项目,并发上限信号量,事件缓冲刷库 |
| `services/company_knowledge_extractor.py` | — | 从完成的项目自动提取知识 |
| `api/companies.py` | ~950 | 公司 + 项目 CRUD API + 报告导出(RFC 5987) |
| `api/company_ws.py` | ~150 | WebSocket 事件推送(DB 轮询模式,0.8s 间隔) |
| `models/company.py` | — | Company / CompanyProject / CompanyProjectEvent / CompanyKnowledge |
| `models/company_project_event.py` | — | 事件日志模型 |
| `models/company_knowledge.py` | — | 公司知识沉淀模型 |
| `services/company_presets.py` | — | 6 个行业预设模板 |
## 执行流程(以一次项目执行为例)
### Phase 1 — CEO 规划
1. 加载公司知识(四档-② 学习闭环):`_load_ceo_memory()` 从 `CompanyKnowledge` 检索历史知识
2. 构建 CEO Agent(高温度 0.7、max_iterations=20)
3. CEO 分析需求 → 输出 `ceo_plan` JSON:
```json
{
"analysis": "战略分析...",
"departments": [
{"department_name": "数据组", "goal": "生成 JSON 数据", "deliverables": ["drinks.json"], "dependencies": []},
{"department_name": "前端组", "goal": "构建页面", "deliverables": ["index.html"], "dependencies": ["数据组"]}
]
}
```
4. 支持人工审批(`awaiting_approval` 状态):前端展示 ceo_plan → 用户确认/修改 → 继续执行
### Phase 2 — 部门并行执行
1. 拓扑排序:按 `dependencies` 字段构建 DAG,计算每波可并发的部门
2. **波次执行**:每波内部门并发(`asyncio.gather` 或 `asyncio.create_task`)
3. 每波上限:`MAX_CONCURRENT_DEPARTMENTS=4`(三档-b,防一次拉起过多部门)
4. 部门间交接(四档-①):上游的 deliverables 注入下游上下文
```python
# company_orchestrator.py:437 _build_dept_context
context = f"Company name: {company.name}\nProject: {project.name}\n"
for dep_name in resolved_deps:
result = dept_results[dep_name]
context += f"## Output from {dep_name}\n{result['deliverable']}\n"
```
5. 每部门复用 `TeamOrchestrator.execute_stream` (与普通虚拟团队相同的 Agent 执行逻辑)
### Phase 3 — CEO 评审
1. `_ceo_review_with_scoring()`:汇总所有部门产出 + 文件清单 → CEO Agent 评分
2. 评分维度:完成度、质量、一致性
3. 返工决策:分低 → `rework_department` 重新执行
4. 终态事件:`company_done` (成功)/ `company_terminated` (熔断)/ `rework_done` (返工完成)
## 四档迭代路线(M1 之后)
| 档位 | 内容 | 状态 |
|------|------|------|
| 一档 | 基础 MVP:CEO 规划→部门执行→评审 | 已完成 |
| 二档 | 人工审批 / 返工 / 预算 / 模板 | 已完成 |
| 三档-a | **事件批量落库**(`_EventBuffer`,N=25/T=0.7s,减少 DB 写入放大) | 已完成 |
| 三档-b | **并发上限 + 排队**(`_PROJECT_SEM` 信号量,`MAX_CONCURRENT_COMPANY_PROJECTS=3`) | 已完成 |
| 四档-① | **部门间交接**(`_build_dept_context` 注入上游交付物) | 已完成 |
| 四档-② | **学习闭环**(`_auto_extract_knowledge` + `_load_ceo_memory`) | 已完成 |
| 四档-③ | **按部门配模型**(`Team.config["model_override"]`) | 已完成 |
| 四档-④ | **一键导出报告**(`exportProjectReport` RFC 5987) | 已完成 |
| 三档-c | 多副本分布式控制(Redis) | **暂缓** |
| per-dept session | 消除共享 db_orch 竞态(每个部门独立 SessionLocal) | **留待后续** |
| 运行对比 | 两项目 side-by-side 对比 | **未开始** |
| 时间轴回放 | 按时间线重放事件 | **未开始** |
## 关键配置(`core/config.py`)
```python
COMPANY_EVENT_FLUSH_MAX_EVENTS: int = 25 # 事件批量刷库阈值
COMPANY_EVENT_FLUSH_INTERVAL_SEC: float = 0.7 # 事件刷库时间间隔
MAX_CONCURRENT_COMPANY_PROJECTS: int = 3 # 同时运行项目上限
COMPANY_QUEUE_HEARTBEAT_SEC: float = 60.0 # 排队心跳间隔
MAX_CONCURRENT_DEPARTMENTS: int = 4 # 每波并行部门上限
COMPANY_CEO_MEMORY_ENABLED: bool = True # 学习闭环开关
COMPANY_AUTO_EXTRACT_KNOWLEDGE: bool = True # 自动沉淀知识
```
## 已知问题
1. **共享 db_orch 竞态**(预存):波内并行的部门共享一个 SQLAlchemy session,有潜在竞态。当时 wave 并发上限是缓解措施,根治方案是 per-dept 独立 session。
2. **公司导出未 RFC 5987**(已修复,2026-07-13):`export_company` 端点中文名报 500,已改为 RFC 5987(与项目报告导出一致)。
3. **交付物捕获漏文件**(已修复):原只扫 `project_path` + file_write 跟踪,漏了扫描兄弟目录和脚本生成文件。已加 `_scan_recent_files` 兜底 + CEO 评审显示文件清单。
4. **无 `--reload`**:后端启动未加 `--reload`,改 Python 代码需手动重启 uvicorn。
## 演示项目
虚拟公司「西安瑞来兹软件科技有限公司」(company_id: `457441b0-7ed3-4948-843a-5d5b6dfc7c01`)共执行过 28 个项目,最终状态:completed 11 / failed 6 / stopped 9 / zombie 2。

View File

@@ -0,0 +1,94 @@
# 开发环境与工作流
## 本地开发环境
### 前置条件
- Python 3.12(系统安装,路径 `C:\Users\Administrator\AppData\Local\Programs\Python\Python312\`)
- Node.js(npm + pnpm)
- Redis(本地 6379)
- Git Bash 作为终端
### 后端启动
```bash
cd D:\workspace\aiagent\backend
# 1. 激活 venv
. venv/Scripts/activate # 或用绝对路径 ./venv/Scripts/python.exe
# 2. 确保 .env 里有 DATABASE_URL(腾讯云 MySQL)和 DEEPSEEK_API_KEY
# 3. 启动(无 reload,改代码需重启)
./venv/Scripts/python.exe -m uvicorn app.main:app --host 0.0.0.0 --port 8037
```
重启方式:
```bash
# 查找并 kill uvicorn 进程
netstat -ano | findstr ":8037"
taskkill //PID <pid> //F
# 重新启动
nohup ./venv/Scripts/python.exe -m uvicorn app.main:app --host 0.0.0.0 --port 8037 > logs/uvicorn.log 2>&1 &
```
### 前端启动
```bash
cd D:\workspace\aiagent\frontend
pnpm dev # Vite HMR → http://localhost:3001
```
注意:`npm run build` 只跑 `vite build`(`vue-tsc` 有 177 个预存类型错误已降级为非阻断 `npm run typecheck`)。
### 登录
- 管理员:`admin` / `123456`
- API 认证:`POST /api/v1/auth/login`,表单编码(`application/x-www-form-urlencoded`),返回 `access_token`
- 测试用 Token:
```bash
TOKEN=$(curl -s -X POST "http://localhost:8037/api/v1/auth/login" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=admin&password=123456" | \
python -c "import sys,json;print(json.load(sys.stdin).get('access_token',''))")
```
### 数据库
- 生产/开发共用腾讯云 MySQL(`DATABASE_URL` 在 `.env` 中)
- Alembic 迁移历史:`d684c9b30c1c` 是公司相关迁移(drop 了 tools/api_keys 等旧表,已在 DB 上 stamp 到该版本,**勿重跑 upgrade**)
- 查看表:数据库客户端连接腾讯云 MySQL,或通过 SQLAlchemy 反射
### 测试
```bash
cd D:\workspace\aiagent\backend
PYTHONPATH=. PYTHONIOENCODING=utf-8 ./venv/Scripts/python.exe logs/<test>.py
```
## 云端生产环境
- 服务器:`101.43.95.130`
- 部署方式:Docker Compose(`docker-compose.dev.yml`),Nginx → FastAPI → Celery
- 数据库:外部腾讯云 MySQL + 本地 Redis
- PyPI/apt 超时问题:用阿里云镜像源(`mirrors.aliyun.com`)
- 热更新方式:`docker cp` 代码到容器(不走 docker build,因为旧镜像缺 APScheduler 等依赖)
- raw 表有 IP 白名单(`101.43.95.130` raw 表的端口 IP 白名单可能由主机安全软件管理)
## 代码仓库
- Git 仓库在 `D:\workspace\aiagent\`
- 单分支:`main`
- 唯一开发者:renjianbo(100 commits)+ rjb(18 commits)
- 不需要 PR/MR 流程
## 已知踩坑记录
| 坑 | 描述 | 解决 |
|----|------|------|
| **GBK 日志** | Windows 下 uvicorn 日志 GBK 编码,grep 中文失败 | 用 ASCII 片段 grep 或用 Python `raw.decode('gbk')` |
| **登录 401** | `/auth/login` 用 OAuth2PasswordRequestForm,必须 form 编码 | 用 `-d "username=admin&password=123456"` 不用 JSON |
| **Alembic 破坏性迁移** | `d684c9b30c1c` 会 drop tools/api_keys 表 | 已在 DB stamp 该版本,勿重跑 |
| **drinks.json 非法引号** | 原 JSON 文件含半角 `"W"` 引号 | 从 index.html 内联重新生成 |
| **文件路径** | Windows 下 Path 用正斜杠 | 全项目统一 `/` |
| **venv Python** | 必须用 venv 的 Python(系统 Python312 缺 uvicorn 等依赖) | 用 `./venv/Scripts/python.exe` 绝对路径 |

View File

@@ -0,0 +1,79 @@
# 当前状态与路线图
> 截稿:2026-07-26
## 最新进展(2026-07 最近两周)
### 虚拟公司模块 — 所有四档全部完成
- 事件批量落库 + 并发上限/排队(三档-a/b)
- 部门间交接 / 学习闭环 / 按部门配模型 / 一键导出报告(四档-①②③④)
- 已通过真实 LLM 冒烟测试(2 次小跑,¥ 测试成本)
- 批量落库方案:`_EventBuffer` → `add_all` + `commit`,默认 N=25/T=0.7s,终态事件立即 force-flush
### 家庭泡饮制作助手 — 成品打磨
- 从虚拟公司产出的 Phase3 原型,人工大幅打磨成可直接用的成品
- 59 款饮品,8 大分类,全部含配料/分步做法/饮品档案(作用·口感·特点·适宜/不适宜人群·产地)
- 59 张真实照片(从下厨房抓取,合法 JPEG)
- 首页补血推荐专区 + 搜索 + 筛选 + 收藏 + 详情页饮品档案卡片
- 产出目录:`deliverables/家庭泡饮制作助手/index.html`(双击即用,离线可用)
### Bug 修复(2026-07-13)
- **公司导出中文名 500**:`export_company` 端点 Content-Disposition latin-1 编码错误 → RFC 5987 修复
- **监控页产出无滚动条**:Element Plus `.el-tabs__content` 默认 `overflow:hidden` → flex 列 + `overflow:auto`
- **交付物捕获漏文件**:CEO 评审只能读到 deliverable 文本(漏了实际文件)→ 加 `_scan_recent_files` + 文件清单展示
## 当前架构待解决项
| 优先级 | 问题 | 影响 | 建议方案 |
|--------|------|------|----------|
| ⚠️ 中 | per-dept 共享 db_orch session 竞态 | 同波并行部门共用一个 session,并发上限只是缓解 | 每个部门独立 `SessionLocal()` |
| ⚠️ 中 | 生产环境 `docker cp` 热更新 | 无 CI/CD,每次改代码需手动 cp 到容器 | 改 Dockerfile 或迁移到 docker build 流程 |
| 🔵 低 | 三档-c 多副本 | `_RUNNING`/`_CONTROL` 在单进程内存,无法多 worker | Redis 分布式锁 + Celery 任务分发 |
| 🔵 低 | 无 `--reload` | 开发中改 Python 需手动重启 uvicorn | 加 `--reload` 参数(Windows 下可能有文件监听问题) |
| 🔵 低 | 运行对比 / 时间轴回放 | 可观察性不足 | 未开始,优先级低 |
## 未完成/待清理
1. **云端部署(docker cp)**:虚拟公司迭代改动(三档+四档)尚未部署到 101.43.95.130
2. **测试清理**:冒烟测试残留 4 条 CompanyKnowledge + 2 个测试项目(1afefd3b, 70556a48)待删除
3. **文档同步**:`docs/天工虚拟团队演示项目.md` 已更新至 4 个项目
## 路线图(推测顺序)
```
已完成 ✅
├─ 一档 ~ 四档 全实施 + 验证
├─ 4 个演示项目(Framework KM、今天吃啥、阅读激励、家庭泡饮)
├─ 交付物捕获修复
├─ 批量落库 + 并发上限(三档-a/b)
├─ 学习闭环 + 部门间交接 + 按部门配模型(四档-①②③)
└─ 一键导出报告(四档-④)
待定 ⏳
├─ 云端部署(docker cp 最新改动到 101.43.95.130)
├─ 测试清理(删冒烟残留)
├─ per-dept 独立 session
├─ 三档-c 多副本
├─ CI/CD(docker build 替代 cp)
├─ 运行对比 / 时间轴回放
└─ 更多演示项目积累
```
## 交付物目录
`D:\workspace\aiagent\deliverables\` 下的人工打磨成品:
| 项目 | 路径 | 说明 |
|------|------|------|
| 家庭泡饮制作助手 | `家庭泡饮制作助手/index.html` | 59 款饮品,真图,离线可用,双击即用 |
| 今日吃啥(参考) | 在 `team_projects/` 下 | 69 道渭南家常菜,PWA |
## 关键记忆文件
`.claude/projects/D--cd-claude-code/memory/` 下的 auto-memory(Claude Code 持久记忆):
- `project_company_roadmap.md` — 虚拟公司全迭代路线 + 实施状态
- `project_aiagent_prod_deploy.md` — 云端部署要点
- `project_company_migration.md` — Alembic 迁移注意事项
- `user_family.md` — 用户家庭情况(渭南口味偏好)
- `xiachufang_dish_images.md` — 下厨房扒图方案
- `feedback_no_confirm.md` — 用户偏好:执行常规任务不频繁确认

View File

@@ -0,0 +1,118 @@
# 演示项目与数据库
## 已有的 4 个演示项目
详见 `docs/天工虚拟团队演示项目.md`(191 行,含启动方式)。
| # | 项目 | 生成方式 | 状态 |
|---|------|----------|------|
| 1 | Framework 知识管理软件 | 虚拟团队(Company-context) | 可运行(Vue 3 + FastAPI + SQLite) |
| 2 | 「今天吃啥」渭南家常菜 | 虚拟公司 西安瑞来兹 | 可运行(纯前端 69 道菜,PWA) |
| 3 | 家庭阅读激励工具 | 虚拟公司 西安瑞来兹 | 设计文档阶段(PRD/线框图/原型),无代码 |
| 4 | 家庭泡饮制作助手 | 虚拟公司 西安瑞来兹 + 人工打磨 | 可直接用(59 款饮品,纯前端单文件) |
## 关键数据库表
### 虚拟公司相关
```sql
-- 公司
company (id, name, description, industry, owner_id, created_at, updated_at)
-- 公司部门(关联 Team)
team (id, name, description, parent_company_id, config, created_at, ...)
-- 公司项目
company_project (id, company_id, name, description, status, ceo_plan,
max_rounds, created_at, completed_at, ...)
-- status: pending | running | completed | failed | stopped | zombie | awaiting_approval
-- 项目事件日志(大表,每条 ReAct step 一条记录)
company_project_event (id, project_id, seq, type, payload, created_at)
-- seq: 项目内单调递增,WS 轮询靠 ORDER BY seq
-- 公司知识(学习闭环沉淀)
company_knowledge (id, company_id, category, source_project_id,
title, content, relevance_score, created_at)
```
### 核心 Agent 相关
```sql
agent (id, name, system_prompt, model, temperature,
max_iterations, tools, knowledge_base_ids, team_id, ...)
agent_session (id, agent_id, user_id, title, last_message, ...)
chat_message (id, session_id, role, content, token_count, ...)
```
### 其他重要模型
```sql
team (id, name, config, parent_company_id, ...)
user (id, username, hashed_password, role, ...)
workflow (id, name, graph_json, ...)
knowledge_base (id, name, ...)
knowledge_entry (id, knowledge_base_id, title, content, embedding, ...)
agent_schedule (id, agent_id, cron_expression, ...)
billing (id, user_id, sub_id, quota, ...)
workspace (id, name, owner_id, ...)
```
完整模型列表(43 个):`backend/app/models/` 下的 `.py` 文件。
## API 快速参考
### 公司相关
```
GET /api/v1/companies # 公司列表
POST /api/v1/companies # 创建公司
GET /api/v1/companies/{id} # 公司详情
DELETE /api/v1/companies/{id} # 删除公司
GET /api/v1/companies/{id}/export # 导出公司报告(Markdown)
POST /api/v1/companies/{id}/projects # 创建公司项目
POST /api/v1/companies/{id}/projects/{pid}/execute # 同步执行
POST /api/v1/companies/{id}/projects/{pid}/execute/async # 异步执行(后台 task)
GET /api/v1/companies/{id}/projects # 项目列表
GET /api/v1/companies/{id}/projects/{pid} # 项目详情
POST /api/v1/companies/{id}/projects/{pid}/stop # 停止项目
GET /api/v1/companies/{id}/projects/{pid}/report # 导出项目报告(四档-④)
WS /api/v1/ws/company/{pid} # 实时事件推送
```
### Agent 相关
```
GET /api/v1/agents # Agent 列表
POST /api/v1/agents # 创建 Agent
POST /api/v1/agents/{id}/chat # 对话(SSE 流式)
WS /ws/chat/{agent_id} # WebSocket 对话
```
### 团队相关
```
GET /api/v1/teams # 团队列表
POST /api/v1/teams # 创建团队
POST /api/v1/teams/{id}/execute # 执行团队项目
POST /api/v1/teams/{id}/execute/stream # 执行(SSE 流式)
```
## Swagger 文档
所有端点都有自动生成的 OpenAPI 文档:`http://localhost:8037/docs`
## 环境变量(关键 .env 项)
```bash
DATABASE_URL=mysql+pymysql://user:pass@host:3306/db?charset=utf8mb4
DEEPSEEK_API_KEY=sk-xxx
SILICONFLOW_API_KEY=sk-xxx
REDIS_URL=redis://localhost:6379/0
JWT_SECRET_KEY=xxx-random-string
SECRET_KEY=xxx-random-string
PLATFORM_USERNAME=admin
PLATFORM_PASSWORD=123456
# 以下为可选
OPENAI_API_KEY=
ANTHROPIC_API_KEY=
BING_SEARCH_API_KEY=
FEISHU_APP_ID=
FEISHU_APP_SECRET=
```

View File

@@ -1,10 +0,0 @@
将修改上传到 git 仓 **rjb_win_dev** 分支:
http://101.43.95.130:3001/admin/aiagent.git
```powershell
cd D:\aaa\aiagent
git push -u origin rjb_win_dev
```
鉴权请使用本机已保存的凭据,或在提示时输入平台账号;**勿在文档中保存明文密码**,也勿将含密码的文件提交到仓库。

View File

@@ -0,0 +1,191 @@
# 天工虚拟团队演示项目
> 记录由「天工虚拟团队 / 虚拟公司」能力生成、并经人工完善打磨的演示项目。
> 每个项目一节,含路径、技术栈、端口、核心功能、完善记录与启动方式,便于演示与复用。
最后更新:2026-07-13(收录:Framework 知识管理软件、渭南「今天吃啥」、家庭阅读激励工具、家庭泡饮制作助手)
---
## 1. Framework 知识管理软件
结构化的「框架知识库」:按 框架 → 分类(可多级) → 条目 组织,支持 Markdown 编辑与全文检索。适合沉淀某个技术框架/领域的结构化知识。
### 基本信息
| 项 | 内容 |
| --- | --- |
| 生成方式 | 天工虚拟公司(Company-context)生成,上下文为 Framework + SQLite + 部门协作 |
| 项目路径 | `D:\workspace\aiagent\team_projects\b9b14925-f054-43d0-b2f0-6ed6b38dbe4b\Company-context-Framework-SQLite--Depart` |
| 前端 | Vue 3 + Pinia + Vite,dev 服务器 `http://localhost:3000` |
| 后端 | FastAPI + SQLite,`http://127.0.0.1:8080`(API 前缀 `/api`,文档 `/docs`) |
| 数据库 | 项目根目录 `framework.db`(SQLite,WAL 模式) |
| 定位 | **本地单机工具**(不做鉴权/多租户) |
### 核心功能
- 框架 / 分类(支持多级子分类)/ 条目 全 CRUD;行内重命名
- Markdown 编辑器:编辑/分屏/预览三模式;**格式工具栏**(粗体、标题、列表、引用、代码、链接、表格等);**图片粘贴/上传**(转 base64 内嵌);Ctrl+S 保存
- **全文检索**(SQLite FTS5,BM25 排序 + 高亮片段)
- 标签管理与侧栏**标签筛选**
- **知识树拖拽**:条目同分类内重排、跨分类移动、分类同层级重排
- 数据 **导入 / 导出**(JSON)
- **深色 / 浅色主题**切换(Catppuccin Mocha / Latte,记忆到 localStorage,可跟随系统)
- Toast 通知 + 自定义确认框(已替换原生 confirm/alert)
### 完善记录(2026-07 人工打磨)
- **安全**:修复存储型 XSS —— 所有 `v-html` 渲染经 `src/utils/sanitize.ts`(DOMPurify)消毒
- **Bug**:修复切换条目时把旧编辑串写进新条目导致的数据丢失
- **工程**:修复生产构建脚本(`build` 改为 `vite build`,类型检查另置 `typecheck`),`npm run build` 可正常出产物
- **体验**:引入 toast + Promise 版确认框;切换框架不再闪屏;新建条目后自动展开所属分类
- **功能**:知识树拖拽排序/移动;Markdown 工具栏 + 图片粘贴上传;后端补 `language` 字段持久化
### 启动方式
详见项目根目录 `启动说明.md`。要点(Git Bash,两个终端):
1) 后端(:8080)—— **必须用 aiagent 的 venv Python**(系统 Python312 没装 uvicorn):
```bash
cd "D:/workspace/aiagent/team_projects/b9b14925-f054-43d0-b2f0-6ed6b38dbe4b/Company-context-Framework-SQLite--Depart"
/d/workspace/aiagent/backend/venv/Scripts/python.exe -c "
import importlib.util, uvicorn
spec = importlib.util.spec_from_file_location('integration_config', '01-integration-config.py')
m = importlib.util.module_from_spec(spec); spec.loader.exec_module(m)
uvicorn.run(m.app, host='127.0.0.1', port=8080, log_level='info')
"
```
2) 前端(:3000):
```bash
cd "D:/workspace/aiagent/team_projects/b9b14925-f054-43d0-b2f0-6ed6b38dbe4b/Company-context-Framework-SQLite--Depart"
npm run dev
```
3) 访问:`http://localhost:3000/`
### 备注
- 前端 `/api` 经 Vite 代理转发到后端 `:8080`(见 `vite.config.ts`),生产 `dist/` 本身不含该代理。
- 相关记忆:项目定位「本地单机工具」、v-html 必须消毒(见 auto-memory `project_framework_km_app.md`)。
---
## 2. 「今天吃啥」渭南家常菜推荐助手
面向家庭日常的「今天吃啥」推荐工具,专治「每天不知道午晚餐做什么」。内置 69 道陕西渭南口味家常菜,一键推荐、换一批、生成一周菜单与买菜清单。纯前端 + 本地 JSON 数据,离线可用(PWA)。
### 基本信息
| 项 | 内容 |
| --- | --- |
| 生成方式 | 天工虚拟公司「西安瑞来兹软件科技有限公司」生成(上下文 HTML/CSS/JS + JSON + 60UI + 部门协作) |
| 实现路径 | `D:\workspace\aiagent\team_projects\b9b14925-f054-43d0-b2f0-6ed6b38dbe4b\Company-context-HTMLCSSJSJSON60UIDepartm` |
| 设计路径 | `D:\workspace\aiagent\team_projects\afc033d4-a781-4bad-a495-0c30a6807ea2\Company-context-HTMLCSSJSJSON60UIDepartm`(菜品数据表、线框图、高保真原型) |
| 公司工作区 | `backend\company_projects\457441b0-7ed3-4948-843a-5d5b6dfc7c01` |
| 技术栈 | 原生 HTML + CSS + JavaScript(无框架),数据 `dishes.json`;PWA(`manifest.json` + `sw.js`) |
| 数据 | `dishes.json` 共 **69 道菜**,字段:`id / 菜名 / 分类 / 类型 / 食材 / 做法 / 耗时分钟 / 标签` |
| 定位 | **本地单机 / 离线优先**,无后端、无鉴权 |
### 核心功能
- **今天吃啥**:一键随机推荐一道(可按午/晚、荤素、耗时等筛选)
- **换一个 / 换一批**:不满意即刻重摇
- **一周菜单**:自动排布 7 天午晚餐,避免近期重复
- **买菜清单**:按选中菜品聚合食材,生成采购清单
- **收藏**:标记常做/爱吃的菜
- **忌口 / 不再推荐**:屏蔽不吃的菜,后续不再出现
- **PWA**:可「添加到主屏幕」,断网仍可用(`sw.js` 缓存)
### 启动方式
纯静态站点,任意静态服务器即可(数据为本地 `dishes.json`,`fetch` 需经 HTTP,不能直接 `file://` 打开):
```bash
cd "D:/workspace/aiagent/team_projects/b9b14925-f054-43d0-b2f0-6ed6b38dbe4b/Company-context-HTMLCSSJSJSON60UIDepartm"
python -m http.server 5500
# 浏览器打开 http://localhost:5500/
```
### 备注
- `download_images.py` / `generate_icons.py` 为辅助脚本(下载菜品图、生成 PWA 图标),非运行时依赖。
- 相关记忆:菜谱偏渭南口味 + 极简交互(见 auto-memory `user_family.md`);菜品图可从下厨房批量扒取(`xiachufang_dish_images.md`)。
---
## 3. 家庭阅读激励工具(孩子阅读打卡)
儿童(5-8 岁)阅读习惯养成 App:孩子三步拍照打卡赚积分(星星),家长端一屏管理多个孩子、自定义积分规则、上架实物奖品并审批兑换。核心定位为**行为设计工具**而非内容平台。
### 基本信息
| 项 | 内容 |
| --- | --- |
| 生成方式 | 天工虚拟公司「西安瑞来兹软件科技有限公司」生成(上下文 SQLite + Flutter/React Native + 部门协作) |
| 项目路径 | `D:\workspace\aiagent\team_projects\afc033d4-a781-4bad-a495-0c30a6807ea2\Company-context-SQLiteFlutter-React-Nati` |
| 当前状态 | **设计/文档阶段产物**(PRD、竞品分析、积分引擎、设计系统、线框图、高保真原型、内测脚本),尚无可运行代码 |
| 目标技术栈 | 跨平台 Flutter / React Native + 本地 SQLite(纯本地存储、离线优先) |
| 定位 | **纯本地存储**,零隐私风险,无需登录/注册,照片存本地沙盒 |
### 双角色模型
- **儿童端(Reader,5-8 岁)**:拍照打卡、查看积分/进度、浏览奖品并申请兑换、角色互动;单次使用 ≤30 秒
- **家长端(Manager,28-40 岁)**:多孩子一屏管理、审批兑换、自定义积分规则、奖品库存管理、数据统计
### 核心功能(MVP,摘自 PRD 功能矩阵 F01–F54)
- **打卡**:拍照 3 步闭环 + 成功动画/音效、重复打卡拦截、拍照预览重拍、打卡日历热力图
- **积分**:大数字展示 + 进度条、连续打卡火焰标记、完整积分流水、手动加减分、规则查看、基础分/连续加成配置、规则变更不追溯
- **奖品**:商店浏览 + 够/不够标识、详情弹窗兑换、家长添加/编辑奖品与库存(快速 ±1)、按奖品独立审批开关
- **兑换**:申请创建 + 积分冻结(pending)、待审批列表角标、审批含库存二次校验、拒绝退还积分、发放状态标记、兑换记录
- **孩子管理**:添加(初始化向导)、编辑、全局常驻切换器
- **系统**:双模式入口(单击进儿童端 / 长按 3 秒进家长端)、本地存储隐私承诺、卡通角色 App 图标
### 差异化壁垒(基于 6 款竞品分析)
1. 实物奖品兑换闭环(拍照打卡→积分→兑换→库存扣减)——竞品完全空白
2. 纯本地 + 离线优先(零隐私风险)——完全空白
3. 多孩子一屏管理(顶部切换器全局常驻)——仅 Beanstack 半覆盖
4. 家长 100% 自定义积分规则——完全空白
### 备注
- 目录内主要为 Markdown 设计文档 + `08-设计系统Token清单.css`;**无前端/后端可运行代码**,如需上线仍待 Flutter/RN 工程实现。
- 关键文档:`08-PRD完整产品需求文档.md`、`04-积分规则引擎与奖品兑换体系设计.md`、`08-高保真UI设计系统与页面规范.md`、`10-高保真交互原型与动效标注.md`、`09-内测验证测试脚本.md`。
---
## 4. 家庭泡饮制作助手
面向家庭日常的「饮品菜谱」工具——像菜谱一样,不过做的是喝的。内置 **59 款**家庭饮品,每款含配料清单、分步做法、真实照片,以及「饮品档案」(作用 / 口感 / 特点 / 适宜人群 / 不适宜人群 / 产地)。纯前端单文件,双击即用、离线可看。含渭南/陕西本地特色(富平柿饼、临潼石榴、关中油茶、陕西杏皮茶)与「补血养气」专区。
### 基本信息
| 项 | 内容 |
| --- | --- |
| 生成方式 | 天工虚拟公司「西安瑞来兹软件科技有限公司」生成(上下文 HTML/CSS/JS + JSON + UI + 部门协作),Phase3 产物整合打磨 |
| 成品路径 | `D:\workspace\aiagent\deliverables\家庭泡饮制作助手\`(可直接使用的成品) |
| 技术栈 | 原生 HTML + CSS + JavaScript(无框架),数据内联 `DRINKS_DATA`(与 `drinks.json` 同步),真实图片 `images/` |
| 数据 | 内联 `DRINKS_DATA` 共 **59 款**,字段:`id / name / category / subcategory / description / prepTime / difficulty / servings / ingredients / steps / tags / seasonal / profile` |
| 图片 | `images/drink-001.jpg ~ drink-059.jpg` 共 59 张真实照片(从下厨房按名抓取);加载失败自动降级为分类 emoji |
| 定位 | **本地单机 / 离线优先 / 自包含单文件**,无后端、无鉴权 |
### 数据分类(59 款)
- 咖啡 6 · 茶饮 6 · 果汁 6 · 奶茶 5 · 气泡饮品 5 · 养生饮品 20 · 奶昔冰沙 6 · 特调饮品 5
- 养生饮品最全:含花草茶(菊花枸杞、玫瑰、洛神花等)、滋补茶、暖饮,以及**补血款**(五红补血汤、阿胶红枣枸杞茶、红糖姜枣茶、桑葚枸杞饮、甜菜根胡萝卜苹果汁、黑芝麻核桃糊)
### 核心功能
- **分类浏览**:首页 8 大分类卡片(动态计数),点入看该类全部饮品
- **补血养气推荐**:首页顶部横滑专区,按 `补血` 标签自动收集(贫血 / 气血不足 / 经期调理)
- **搜索**:全局模糊搜索(名称、食材、标签、分类、简介),下拉即时结果
- **筛选**:按标签(chips)、难度多维筛选
- **收藏**:标记常喝的饮品(localStorage 记忆)
- **详情页**:大图 Hero、元信息条、配料清单(可勾选)、分步做法、**饮品档案**(作用/口感/特点/适宜/不适宜/产地)、同分类推荐
- **真实照片 + 优雅降级**:每款配下厨房真图,`onerror` 失败回退分类 emoji,不留空白
### 完善记录(2026-07 人工打磨)
- **整合成品**:把虚拟公司 Phase3 的 `index.html` + `drinks.json` 整合到干净目录,修复原纯 emoji 卡片不显示图片的问题(注入 `card-photo` / `detail-hero-photo`)
- **真实图片**:`download_images.py` 从下厨房按饮品名抓取 59 张真图,`images/{id}.jpg`
- **扩充内容**:从 20 款扩到 59 款——补花草茶、陕西/渭南本地特色、补血专题,并各分类均衡补充
- **饮品档案**:为全部 59 款补充 6 项档案字段,详情页新增「🏷 饮品档案」卡片
- **首页专区**:新增「🩸 补血养气推荐」横滑卡片(数据驱动,加补血款自动出现)
- **数据一致性**:所有改动同步 index.html 内联 `DRINKS_DATA` 与 `drinks.json`,分类 `count` 按数据自动重算;修复原 `drinks.json` 一处非法半角引号
### 启动方式
自包含单文件,数据已内联,**直接双击打开即可**(图片为相对路径,`file://` 下正常显示):
```
D:\workspace\aiagent\deliverables\家庭泡饮制作助手\index.html
```
如需以 `drinks.json` 为数据源调试,可起静态服务器:
```bash
cd "D:/workspace/aiagent/deliverables/家庭泡饮制作助手"
python -m http.server 5501
# 浏览器打开 http://localhost:5501/
```
### 备注
- `download_images.py`(抓图)、`add_flower_teas.py` / `add_batch2.py` / `add_profiles_and_anemia.py` / `add_batch4.py`(历次数据注入脚本)均为**辅助脚本**,非运行时依赖。
- 相关记忆:偏渭南口味 + 极简交互(见 auto-memory `user_family.md`);菜品/饮品图可从下厨房批量扒取(`xiachufang_dish_images.md`)。

View File

@@ -0,0 +1,278 @@
# 虚拟公司模块 · 完整功能与使用文档
> 适用平台:天工 AI Agent 平台(后端 FastAPI :8037,前端 Vue3 :3001)
> 模块定位:在「虚拟团队」之上再叠一层 **3 级组织(公司 → 部门 → 成员)**,用一句业务目标驱动一整支 AI 团队自动完成「CEO 规划 → 部门并行执行 → CEO 评审打分 → 多轮返工」的闭环,并提供**白盒控制室**做全程可观测 + 可干预。
---
## 目录
1. [核心概念与数据模型](#1-核心概念与数据模型)
2. [三阶段编排流程](#2-三阶段编排流程)
3. [功能特性全览](#3-功能特性全览)
4. [前端使用指南(3 个页面)](#4-前端使用指南3-个页面)
5. [白盒控制室:实时控制能力](#5-白盒控制室实时控制能力)
6. [学习闭环与知识沉淀](#6-学习闭环与知识沉淀)
7. [报告导出、洞察、调度、模板市场、项目监管](#7-报告导出洞察调度模板市场项目监管)
8. [API 参考](#8-api-参考)
9. [配置项](#9-配置项)
10. [典型端到端使用流程](#10-典型端到端使用流程)
11. [设计取舍与注意事项](#11-设计取舍与注意事项)
---
## 1. 核心概念与数据模型
| 概念 | 底层实体 | 说明 |
|---|---|---|
| **公司 Company** | `companies` | 3 级组织的顶层。含 name/description/industry/ceo_agent_id/status。 |
| **部门 Department** | 复用 `teams`(`parent_company_id` 指向公司,`department_type` 标类型) | 一个部门 = 一支虚拟团队,运行时由 `TeamOrchestrator` 驱动。`config` JSON 存 `model_override` 等。 |
| **成员 Member** | `team_members` → `agents` | 部门内的 AI 角色(pm/dev-backend/qa/ceo/cto…),每个成员是一个 Agent。 |
| **项目 Project** | `company_projects` | 一次公司执行任务。含 description/status/ceo_plan/review_scores/round_count/成本时长等。 |
| **事件 Event** | `company_project_events` | 执行全过程的时间线,按 **per-run 单调 seq** 落库,是白盒可观测与回放的数据源。 |
| **知识 Knowledge** | `company_knowledge` | 公司记忆:项目沉淀出的 ceo_plan/dept_output/review/insight 4 类知识,回喂给 CEO 规划。 |
| **调度 Schedule** | `company_schedules` | 定时触发项目(cron 或固定间隔)。 |
**部门类型(department_type)**:`executive`(战略) / `product`(产品) / `engineering`(交付/工程) / `operations`(运营) / `marketing` / `sales` / `finance` / `hr`。
**事件信封(envelope)**:`CompanyProjectEvent.to_envelope()` → `{ seq, pid, type, payload, ts }`,业务数据统一嵌在 `payload` 下。
---
## 2. 三阶段编排流程
`CompanyOrchestrator`(复用 `TeamOrchestrator`)执行一个项目分三阶段,外层可多轮返工:
```
Phase 1 · CEO 规划
└─ CEO Agent 读业务目标 + 各部门可用角色 (+ 注入历史经验) → 产出 JSON 计划
{ analysis, departments:[ {department_name, goal, deliverables, dependencies} ] }
Phase 2 · 部门并行执行(按依赖分波次)
└─ 无依赖部门先跑;下游部门等上游 dept_done 后启动
└─ 上游交付物按 dependencies 精准注入下游部门 context(部门间交接)
└─ 每波并行度 ≤ MAX_CONCURRENT_DEPARTMENTS
Phase 3 · CEO 评审打分
└─ 逐部门 0–10 打分 + pass/feedback/improvement_areas + overall_score
(可选)多轮返工 round 2..N
└─ 失败部门带「CEO 评审反馈 + 改进方向 (+ 人工意见)」重跑,直到全过或达 max_rounds
```
**关键点**:
- CEO 计划可**预览**(`/plan`)后再执行,也可直接把审定后的 `ceo_plan` 传给 `/execute/async` 跳过规划。
- 返工不是「盲目重跑」:默认就会把 CEO 打分反馈注入失败部门;开返工审批门后还能注入人工意见。
- 评审是**直连单次 LLM**(非 ReAct),解析失败会显式 `parse_failed` 并中断,不再静默 auto-pass。
---
## 3. 功能特性全览
### 3.1 组织搭建
- **6 套预置模板**一键建公司(自动建部门 + Agent + 填成员):
| preset_type | 名称 | 角色数 |
|---|---|---|
| `tech-software` | 软件科技公司 | 9(CEO/CTO 顾问、产品、UI、前后端、测试、运维、文档) |
| `ecommerce-retail` | 电商零售公司 | 8 |
| `consulting-service` | 咨询服务公司 | 8 |
| `manufacturing` | 制造企业 | 8 |
| `media-marketing` | 媒体营销公司 | 8 |
| `entertainment-media` | 娱乐传媒公司 | 7 |
- **自定义建公司**:空壳公司 + 手动增删部门(从已有 Team 挂载 / 卸载)。
- **按部门配模型**(四档-③):给某部门指定 `provider/model`,该部门全体成员统一走该模型,做成本/质量分层(如交付层用便宜模型、战略层用强模型)。留空即回归成员 Agent 自身模型。
### 3.2 执行与规划
- **计划预览** `/plan`:只跑 CEO 规划、不执行,供人工审阅(覆盖 300s 超时)。
- **三种执行入口**:`/execute`(同步阻塞)、`/execute/stream`(SSE 流式)、`/execute/async`(异步 + 白盒控制室,**推荐**)。
- **部门间交接**(四档-①):上游部门交付物按声明的 `dependencies` 精准注入下游 context(逐项 ≤2000 字、合计 ≤6000 字),下游在上游产物基础上衔接,不重复劳动。
### 3.3 白盒控制室(实时可观测 + 可干预)
详见 [第 5 节](#5-白盒控制室实时控制能力)。含:事件流实时推送、停止/暂停/继续/跳过部门、单部门取消/返工、人在环审批(计划门 + 返工门,可注入反馈)、预算熔断、超时熔断。
### 3.4 可信度量
- **真实 token + 成本(¥)**:无条件累计每次 LLM 的真实 usage,逐部门 `cost_yuan/tokens_used`、公司级 `total_cost_yuan`,与各部门之和精确相等。控制室顶栏实时显示成本。
### 3.5 学习闭环
- 项目终态**自动沉淀知识** → CEO 规划**回喂历史经验**。详见 [第 6 节](#6-学习闭环与知识沉淀)。
### 3.6 规模与健壮性(三档-a/b)
- **事件批量落库**:攒批写(默认 25 条 / 0.7s 触发一次),大幅降低对远程 MySQL 的写放大;终态事件立即 force-flush 保证 finale 不被截断。
- **项目并发上限 + 真实排队**:`MAX_CONCURRENT_COMPANY_PROJECTS`(默认 3)个并行,超出者进队列(有 `queued` 事件 + 心跳防僵尸误杀),排队期不占 DB 连接。
- **每波部门并发上限**:`MAX_CONCURRENT_DEPARTMENTS`(默认 4),总并发部门 ≤ 项目×部门,不打爆连接池。
---
## 4. 前端使用指南(3 个页面)
| 路由 | 页面 | 作用 |
|---|---|---|
| `/company-presets` | 预置模板 | 选模板一键建公司 |
| `/companies` | 公司构建器 CompanyBuilder | 公司/部门管理、按部门配模型、计划预览、启动项目 |
| `/companies/:companyId/projects/:projectId/monitor` | 白盒控制室 CompanyControlRoom | 实时观测 + 全部运行时控制 + 导出报告 |
### 4.1 建公司
- 走 `/company-presets` 选一套模板(如「软件科技公司」),可自定义公司名 → 一键生成完整班底。
- 或在 `/companies` 新建空公司再手动挂部门。
### 4.2 配置部门模型(可选)
在 CompanyBuilder 的部门卡片头,点「默认模型 / xxx」标签 → 弹窗选 provider(deepseek/openai/anthropic/siliconflow)+ 填 model → 保存 / 清除。
### 4.3 启动项目
1. 在 CompanyBuilder 输入业务目标 → **预览计划**(看 CEO 会怎么拆部门)。
2. 设置运行选项(最大轮次、成本上限 ¥、超时上限、是否开启计划/返工审批门)。
3. **确认并执行** → 走 `/execute/async` → 自动跳转白盒控制室。
---
## 5. 白盒控制室:实时控制能力
控制室通过 **WebSocket** `/api/v1/ws/company-projects/{projectId}?token=&since_seq=` 实时接收事件(断线重连自带全量回放),并提供以下控制(M2 十项能力):
| 能力 | 端点 | 语义 |
|---|---|---|
| **停止** | `POST …/stop` | 硬取消整个项目 → `company_terminated` + status=stopped |
| **暂停 / 继续** | `POST …/pause` `…/resume` | 暂停=不开新波次(在飞部门跑完);继续=恢复调度 |
| **跳过部门** | `POST …/skip` `{department_name}` | 仅跳过「未开始」的部门,下游照常推进 |
| **单部门取消** | `POST …/departments/{name}/cancel` | 硬取消运行中的某部门,仍发 `dept_done{cancelled}` 让波次推进 |
| **单部门返工** | `POST …/departments/{name}/rework` | 对已跑完的部门 on-demand 重跑(seq 续写) |
| **人在环审批** | `POST …/approve` `{decision, gate?, feedback?}` | 计划门 / 返工门;返工门可带 `feedback` 注入人工意见 |
| **预算熔断** | 执行参数 `max_cost_yuan` | 累计成本超阈 → `budget_tripped` + 优雅停(不打断在飞 LLM) |
| **超时熔断** | 执行参数 `max_duration_min` | 超时 → `timeout_tripped` + 停 |
**关键事件类型**:`company_start / ceo_plan_start / ceo_plan_done / round_start / dept_waiting / dept_done / dept_skipped / ceo_score_done / round_done / company_done / company_terminated / awaiting_approval / approval_resolved / paused / resumed / budget_tripped / timeout_tripped / rework_start / rework_done / dept_agent_event`。
**审批门用法**:启动时 `approve_plan=true` → CEO 出计划后停在 `awaiting_approval(plan)`,控制室弹窗批准/拒绝;`approve_rework=true` → 每轮评审后若有失败部门,停在 `awaiting_approval(rework)`,可在弹窗里填反馈再批准。
**导出报告**:控制室「导出报告」按钮 → `GET …/report` 下载单项目 Markdown 运行报告(概要/CEO 规划/部门结果/评分/时间轴)。
---
## 6. 学习闭环与知识沉淀
**闭环两半**(四档-②):
1. **沉淀(自动)**:项目终态时自动把本次项目抽取为知识(`ceo_plan/dept_output/review/insight` 4 类),按 project_id 去重,落 `company_knowledge`。手动触发:`POST …/knowledge/generate {project_id}`。
2. **回喂(自动)**:CEO 规划前,按相关性检索本公司历史知识(领域信号词命中 + tag 命中打分,`review/insight` 权重更高),取 TopN(默认 5 条 / ≤4000 字)拼成「## 历史项目经验」块注入 CEO system prompt,让 CEO 复用被验证的做法、规避已知低分项。
> 门控开关见 `COMPANY_CEO_MEMORY_ENABLED` / `COMPANY_AUTO_EXTRACT_KNOWLEDGE`,关闭即回归旧行为。
知识管理:`GET …/knowledge`(可 search/category/limit)、`DELETE …/knowledge/{id}`。
---
## 7. 报告导出、洞察、调度、模板市场、项目监管
- **导出**:`GET …/export`(整公司 Markdown)、`GET …/projects/{pid}/report`(单项目运行报告,文件名走 RFC 5987 支持中文)。
- **统计/洞察**:`GET …/stats`(项目数/成功率/最近活跃);`GET …/insights`(部门执行统计、协作对、平均轮次/成本、失败原因、改进建议)。
- **定时调度**:`…/schedules` 增删改查 + `…/schedules/{id}/trigger` 立即触发(cron 或 `interval_minutes`)。
- **模板市场**:`POST …/projects/{pid}/publish` / `unpublish` 发布/下架项目为可复用模板;`GET /templates/list` 浏览。
- **项目监管(Supervisor)**:`GET …/supervisor/zombies`(僵尸项目)、`…/supervisor/in-progress`(在途 + 风险预警)、`POST …/supervisor/scan`(触发扫描)、`POST …/projects/{pid}/recover`(恢复)。
---
## 8. API 参考
> 全部前缀 `/api/v1/companies`。鉴权:`Authorization: Bearer <token>`。
### 公司
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | `` | 列出公司 |
| GET | `/{id}` | 公司详情(含部门) |
| POST | `` | 新建公司 `{name, description?, industry?}` |
| POST | `/template/{preset_type}?company_name=` | 预置模板建公司 |
| PUT | `/{id}` | 更新公司 |
| DELETE | `/{id}` | 删除公司 |
| GET | `/{id}/export` | 导出整公司 Markdown |
| GET | `/{id}/stats` | 公司统计 |
| GET | `/{id}/insights` | 公司洞察分析 |
### 部门
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | `/{cid}/departments` | 挂载部门 `{team_id}` |
| DELETE | `/{cid}/departments/{did}` | 卸载部门 |
| PUT | `/{cid}/departments/{did}/model` | 按部门配模型 `{provider?, model?}` |
### 执行与规划
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | `/{cid}/plan` | 预览 CEO 计划(300s) |
| POST | `/{cid}/execute` | 同步执行 |
| POST | `/{cid}/execute/stream` | SSE 流式执行 |
| POST | `/{cid}/execute/async` | 异步执行(白盒控制室)→ `{project_id, status, ws_url}` |
| GET | `/{cid}/projects/{pid}/events?since_seq=&limit=` | 拉取事件(HTTP 回放) |
| WS | `/api/v1/ws/company-projects/{pid}?token=&since_seq=` | 实时事件流 |
`/execute/async` body:`{ project_description, ceo_plan?, max_rounds=1, max_cost_yuan?, max_duration_min?, approve_plan=false, approve_rework=false }`
### 运行时控制
| 方法 | 路径 |
|---|---|
| POST | `/{cid}/projects/{pid}/stop` · `/pause` · `/resume` |
| POST | `/{cid}/projects/{pid}/skip` `{department_name}` |
| POST | `/{cid}/projects/{pid}/approve` `{decision, gate?, feedback?}` |
| POST | `/{cid}/projects/{pid}/departments/{name}/cancel` · `/rework` |
| GET | `/{cid}/projects` | 项目列表 |
| GET | `/{cid}/projects/{pid}/report` | 单项目运行报告 |
### 知识 / 调度 / 模板 / 监管
| 方法 | 路径 | 说明 |
|---|---|---|
| GET/POST/DELETE | `/{cid}/knowledge …` | 知识列表 / `generate {project_id}` / 删除 |
| GET/POST/PUT/DELETE | `/{cid}/schedules …`, `/schedules/{id}` | 调度增删改查 |
| POST | `/schedules/{id}/trigger` | 立即触发调度 |
| GET | `/templates/list?search=` | 模板市场列表 |
| POST | `/{cid}/projects/{pid}/publish` · `/unpublish` | 发布/下架模板 |
| GET | `/supervisor/zombies` · `/supervisor/in-progress` | 项目监管 |
| POST | `/supervisor/scan` · `/{cid}/projects/{pid}/recover` | 扫描 / 恢复 |
---
## 9. 配置项
`app/core/config.py`(可用同名环境变量覆盖;**放宽默认值即回归旧行为**):
| 配置 | 默认 | 含义 |
|---|---|---|
| `MAX_CONCURRENT_COMPANY_PROJECTS` | 3 | 同时运行的项目上限,超出排队 |
| `MAX_CONCURRENT_DEPARTMENTS` | 4 | 每波并行部门上限 |
| `COMPANY_EVENT_FLUSH_MAX_EVENTS` | 25 | 事件攒批条数(=1 即逐条 commit) |
| `COMPANY_EVENT_FLUSH_INTERVAL_SEC` | 0.7 | 事件攒批时间阈(WS 可见延迟 ≤ ~1.5s) |
| `COMPANY_QUEUE_HEARTBEAT_SEC` | 60 | 排队期刷新 updated_at 防僵尸误杀 |
| `COMPANY_CEO_MEMORY_ENABLED` | True | 是否回喂历史知识给 CEO |
| `COMPANY_CEO_MEMORY_MAX_ENTRIES` | 5 | 回喂知识最大条数 |
| `COMPANY_CEO_MEMORY_MAX_CHARS` | 4000 | 回喂知识最大字数 |
| `COMPANY_AUTO_EXTRACT_KNOWLEDGE` | True | 项目终态是否自动沉淀知识 |
---
## 10. 典型端到端使用流程
```
1. /company-presets 选「软件科技公司」→ 建公司「XX 科技」
2. (可选)CompanyBuilder 给交付层配便宜模型、战略层配强模型
3. 输入业务目标(例:开发一个「家庭泡饮」制作助手,能展示图片和制作方法)
4. 预览计划 → 确认 CEO 把任务拆成 产品层/交付层/运营层/战略层
5. 设运行选项(max_rounds=1、max_cost_yuan=50 护栏)→ 确认并执行
6. 自动进白盒控制室:实时看各部门 ReAct 步骤、成本累加
- 中途可暂停/跳过/单部门重跑;开审批门可人工把关计划与返工
7. company_done → 看综合评分 + 总成本;「导出报告」下载 Markdown
8. 产物落在 team_projects/{department_team_id}/… (HTML/CSS/JS + 图片等)
9. 本次项目自动沉淀为知识 → 下个项目 CEO 规划自动复用经验
```
**产物目录约定**:各部门产物写到 `D:\workspace\aiagent\team_projects\{部门 team_id}\<context 目录>\`;公司级项目记录在 `backend\company_projects\{company_id}\<项目名>\`。
---
## 11. 设计取舍与注意事项
- **复用而非重造**:部门 = Team、`CompanyOrchestrator` 复用 `TeamOrchestrator`,`Department.config` 复用 Team 的 JSON 字段存 `model_override`(**避免破坏性 alembic 迁移**)。
- **单 worker 运行时状态**:`_RUNNING`/`_CONTROL` 注册表在进程内,事件投递(WS/HTTP)已是 DB 轮询天然跨进程安全;多副本横向扩展(Redis 分布式控制 + Celery)为后续规划,当前单副本。
- **终态原子性**:终态事件永远 force-flush,崩溃至多丢缓冲窗内的「非终态闲聊事件」;status/review_scores 由编排器自身 session 独立提交,正确性不受批量写影响。
- **返工语义**:交接产物累加器每轮重置,返工轮只重跑失败部门 → 下游返工可能拿不到未重跑上游的最新交付物(首轮全量交接是核心价值)。
- **评审健壮**:评审直连单次 LLM + 一次纠正重试;解析失败显式 `parse_failed=False→pass`、中断当轮,绝不静默 auto-pass 污染打分/熔断。
- **模型覆盖范围**:`model_override` 只改 provider/model,不动 temperature/tools/prompt。
*文档版本:2026-07-12。对应虚拟公司 M1(白盒控制室)+ 一档~三档 + 四档①②③④ 全部已实施。*

View File

@@ -0,0 +1,150 @@
# 虚拟公司「白盒控制室」实现方案
> 面向 `/companies`(`CompanyBuilder.vue`)虚拟公司功能,将其从"黑盒执行"升级为"可观测 + 可控 + 可恢复"的控制室。
> 分支:rjb_tiangong_debug | 编写日期:2026-07-11
---
## 一、背景(为什么做)
当前 `/companies` 执行一个公司级项目时是**黑盒**:
- **看不清**:SSE 事件其实已深到每个 Agent 的 ReAct think/工具调用,但前端把工具入参出参、完整推理链、产出文件、真实 token 全丢弃或截断;CEO 规划/评分阶段无过程;依赖关系只有文字箭头。
- **控不了**:执行是"一条 async 请求内跑完",无任务态、无停止/暂停、循环里无取消检查点。客户端断开只停止消费,后端继续跑 → 产生僵尸项目。
- **断即失**:中间态不落库,刷新页面/断线后正在跑的项目无法恢复查看。
**目标范围**(已确认):
1. **观测 + 完整控制**:实时全量可观测 + 停止/暂停/恢复 + 跳过部门/手动返工。
2. **独立控制室页面**:新建路由页,不塞进已 1600 行的 `CompanyBuilder.vue`。
3. **可恢复**:刷新/断线后能重连查看正在跑的项目并回放历史。
关键结论:**可观测数据源已具备**(改造小),**可控 + 可恢复需要架构升级**(把执行从"请求协程内跑完"解耦成"后台任务 + 事件落库 + Redis 实时通道 + 协作式取消")。
---
## 二、架构总览
```
[控制室页面 CompanyControlRoom.vue]
│ ①启动执行 POST /execute/async → 立即拿 project_id
│ ②WS 订阅 /ws/company-projects/{pid}
│ ├─ 连接即回放:DB company_project_events 历史事件(恢复)
│ └─ 增量实时:Redis pub/sub company:events:{pid}
│ ③控制 POST .../{stop|pause|resume|skip|rework}
▼
[后台执行任务 asyncio.create_task] [Redis]
orchestrator.execute_stream() ──发布──▶ pub/sub: company:events:{pid}
每个事件: ──写库──▶ DB: company_project_events
循环检查点 ◀──读取──────────────────── flag: company:control:{pid}
心跳 updated_at
```
- **执行与请求解耦**:`/execute/async` 创建项目 → `asyncio.create_task` 起后台任务 → 立即返回 `project_id`。SSE 断开不再杀执行(解决僵尸 + 支持恢复)。
- **双写**:每个编排事件同时 (a) 发 Redis pub/sub 供实时,(b) 落 `company_project_events` 供回放。
- **协作式取消**:控制信号写 Redis flag `company:control:{pid}`;执行在**循环检查点**读取,实现跨 worker 的停止/暂停(无需进程内任务注册表)。
---
## 三、后端改动
### 1. 事件持久化(新表 + 迁移)
- 新增模型 `backend/app/models/company_project_event.py` → 表 `company_project_events`:
`id, project_id(FK,index), seq(int 递增), type, payload(JSON), created_at`。
- 新增 alembic 迁移。**⚠️ 迁移雷区**:当前 `alembic heads` 是 `d684c9b30c1c`,该迁移含危险删表操作(drop `tools`/`api_keys`/`fcm_tokens` 等,`tools` 有真实数据)。生成新迁移前**必须先 `alembic stamp` 对齐真实 DB 状态**,再基于其生成新迁移;绝不能触发 `d684c9b30c1c` 的 drop_table。
- 用途:WS 连接时按 `seq` 回放;执行结束保留作审计/回放。
### 2. 执行解耦为后台任务
- `backend/app/api/companies.py:387` 现有 `/execute/stream` 保留(向后兼容)。**新增** `POST /{company_id}/execute/async`:
- 校验公司 + `current_user` 归属(顺带修当前越权问题)。
- 创建 `CompanyProject`(status=`queued`)。
- `asyncio.create_task(_run_company_project(project_id, ...))`,返回 `{project_id}`。
- 新增执行包装器(`company_orchestrator.py` 或新 `company_runner.py`):
```
async for event in orchestrator.execute_stream(...):
_publish(pid, event) # Redis pub/sub
_persist(pid, seq, event) # DB append
_heartbeat(project) # 周期 updated_at=now
```
末尾 `except CancelledError` / stop-flag → 落 `stopped`/`failed` 终态并发终止事件。
### 3. 控制信号 + 协作式检查点
- 控制端点(`companies.py`,均校验归属):
- `POST /{cid}/projects/{pid}/stop` → Redis `company:control:{pid}` = `{action:"stop"}`
- `POST .../pause` / `.../resume` → `{action:"pause"|"run"}`
- `POST .../skip` body `{department_name}` → `{action:"skip", dept}`(当前波跳过该部门)
- `POST .../rework` body `{department_names[]}` → 手动触发指定部门返工(下一轮)
- 检查点插入位置(读 `_should_stop()/_should_pause()`):
- `company_orchestrator.py:615` 轮次 while 循环头
- `company_orchestrator.py:650` 部门 wave while 循环头(stop→break;pause→`await asyncio.sleep` 轮询直到 resume;skip→从 ready 移除)
- **深度停止(可选,二期)**:`backend/app/agent_runtime/core.py` run_stream ReAct 循环(约 :893)每轮读一次 stop-flag,才能"立即停当前 LLM 调用";一期先做**部门/阶段边界级**控制,不改 core.py。
- 语义:**pause = 边界暂停**(不打断进行中的 LLM 调用,在部门/阶段边界卡住),实现简单且够用;真正的挂起-快照-重入(复用 workflow `pause_state` 那套)列为后续增强。
### 4. 实时推送通道(复用现有 WS 基建)
- 新增 `backend/app/api/company_ws.py`:`WS /api/v1/ws/company-projects/{project_id}`
- 复用 `app/websocket/manager.py` 的 `websocket_manager` 与 `websocket.py:35` 的 `_validate_ws_token` 鉴权范式(改为校验 project→company→workspace 归属)。
- 连接流程:① 按 `seq` 从 DB 回放历史事件 → ② 订阅 Redis pub/sub `company:events:{pid}` 推增量 → ③ 项目终态后推 final 并关闭。
- 复用 Redis 客户端 `app/core/redis_client.py:get_redis_client`(websocket.py:24 已在用)。
### 5. 数据质量修复(顺带)
- **updated_at 心跳**:执行循环周期性 `project.updated_at=now(); commit()` → 修 `ProjectSupervisor`(`project_supervisor.py:41`)对长任务的**误杀**。
- **真实 token**:把部门 phase 的 `final.token_usage`(core.py:1020 真实 TokenBudget)透传到公司层事件,替换现在"事件计数冒充 token"(`company_orchestrator.py:712`)。
- **dept_done duration bug**(company_orchestrator.py:726):修正计时起点。
---
## 四、前端改动
### 1. 路由 + 页面
- `frontend/src/router/index.ts`:新增 `/companies/:companyId/projects/:projectId/monitor` → `CompanyControlRoom.vue`(`requiresAuth`)。
- `CompanyBuilder.vue`:项目历史/执行处加"进入控制室"入口;"流式执行"改为调用 `/execute/async` 后跳控制室(保留旧内联视图作降级)。
### 2. 状态管理(新 Pinia store)
- `frontend/src/stores/companyExecution.ts`:承载 `deptPanels / timeline / rawEvents / ceoPlan / ceoScores / rounds / tokens / status / controlState`;提供 `connect(pid)`(WS+回放)、`applyEvent(evt)`(迁移自 `CompanyBuilder.routeStreamEvent` CB:1294 的分发逻辑)、`stop/pause/resume/skip/rework` actions。
- WS 客户端:优先 `WebSocket`;失败降级到现有 SSE `fetch+getReader`(CB:1262 模式),并加 `AbortController`。
### 3. 控制室布局(CompanyControlRoom.vue)
- **顶部控制条**:状态徽标 + `停止/暂停/恢复` 按钮(复用 ExecutionDetail.vue:90 的 resume 交互范式);轮次指示 el-steps。
- **左:组织/依赖 DAG**:用已引入的 `@vue-flow/core`(package.json 已有,WorkflowDesigner 在用)画 CEO→部门→依赖的真实有向图,节点实时染色(等待/运行/通过/失败);节点上可"跳过/返工"。
- **中:部门实时卡片 + 焦点区**:每部门展开 → phase → Agent → **每次迭代的 think/act/observe**;**新增展示工具入参出参**(数据在 `dept_agent_event.data.data` 的 `tool_call.input`/`tool_result.result`,core.py:1124/1187,现被丢弃)。
- **右(tabs)**:
- 产出文件树 + 内容预览(`dept_done.result.files`)。
- 统计:真实 token / 阶段耗时 / 工具调用次数。
- **原始事件流查看器**:复用 `SystemLogs.vue` 的表格+级别/来源/关键词筛选范式,展示 `rawEvents`(调试白盒)。
- CEO 规划全文 + 评分卡(`ceo_plan.analysis` / `ceo_score_done`,现被截断)。
### 4. API 封装
- `frontend/src/api/companies.ts`:新增 `executeAsync / getProjectEvents(pid, sinceSeq) / stopProject / pauseProject / resumeProject / skipDepartment / reworkDepartments` 及 WS URL 构造。
---
## 五、数据模型新增汇总
| 表 / Key | 关键列 | 用途 |
|----|--------|------|
| `company_project_events`(表) | project_id, seq, type, payload(JSON), created_at | 事件落库 → 回放/恢复/审计 |
| Redis `company:events:{pid}`(pub/sub) | — | 实时增量推送 |
| Redis `company:control:{pid}`(key) | `{action, dept?}` | 停止/暂停/跳过/返工信号 |
| `company_projects` 新增状态 | `queued/paused/stopping/stopped` | 状态机补齐 |
---
## 六、分期落地(里程碑)
1. **M1 可观测白盒(无控制)**:事件落库 + WS 通道 + 控制室页面 + Pinia store + 工具入参出参/文件/真实 token/原始事件流展示 + updated_at 心跳修复。→ 立刻把黑盒变可回放白盒。
2. **M2 停止 + 边界暂停/恢复**:执行解耦为后台任务 + Redis 控制 flag + 编排循环检查点 + 控制条按钮。
3. **M3 跳过部门 / 手动返工**:skip/rework 端点 + DAG 节点操作。
4. **M4(可选增强)**:core.py 深度停止检查点(立即停 LLM)+ 快照-重入式真暂停。
---
## 七、验证(端到端)
- **迁移安全**:`alembic current/heads` 确认;新迁移 `upgrade` 后核对 `company_project_events` 存在,**且 tools/api_keys 等表未被删**。
- **可观测**:启动一个公司项目 → 控制室能看到 CEO 规划全文、部门 ReAct 逐迭代、工具入参出参、产出文件、真实 token;`GET /projects/{pid}/events` 有序落库。
- **可恢复**:项目运行中刷新页面 / 断网重连 → 按 seq 回放 + 继续实时。
- **可控**:`暂停`→部门在边界卡住、`恢复`→继续、`停止`→在检查点内终止且状态落 `stopped`(后台无残留 asyncio 任务);`跳过/返工`生效。
- **回归**:旧 `/execute/stream` 与 `CompanyBuilder` 原视图仍可用;`restart_backend_celery.ps1` + `manage.ps1 status` 全绿;登录 admin/123456 冒烟。
## 八、风险 / 注意
- **迁移雷区**:head `d684c9b30c1c` 含删表;生成新迁移前必须先 stamp 对齐真实 DB,避免误跑删表。
- **多 worker**:控制走 Redis flag(跨 worker 生效);后台任务在接收请求的 worker 内,靠协作式 flag 自取消,无需跨进程注册表。若将来多副本部署,建议迁 Celery 以获得 revoke。
- **一期不改 core.py**:只能做到部门/阶段边界级停止/暂停,无法"立即中断进行中的单次 LLM 调用"——M4 再做。
- **XSS**:部门产出走 `v-html`(CB:395),控制室渲染 LLM 输出需做 sanitize。
- **auto_approve_files=True**:编排默认自动放行文件写入,控制室应显式展示文件写入动作供审计。

View File

@@ -0,0 +1,413 @@
# 虚拟公司「白盒控制室」详细设计(工程实现规格)
> 配套文档:`虚拟公司白盒控制室实现方案.md`(概览)。本文是可直接指导编码的详细规格。
> 分支:rjb_tiangong_debug | 编写日期:2026-07-11
> 关键源文件:
> - 编排 `backend/app/services/company_orchestrator.py`
> - 部门执行 `backend/app/services/team_orchestrator.py`
> - Agent 循环 `backend/app/agent_runtime/core.py`(run_stream: 764–1291)
> - API `backend/app/api/companies.py`(execute/stream: 387–408)
> - 模型 `backend/app/models/company.py`
> - 僵尸监管 `backend/app/services/project_supervisor.py`
> - 可复用 WS `backend/app/api/websocket.py` + `app/websocket/manager.py`
> - 前端主页面 `frontend/src/views/CompanyBuilder.vue`(routeStreamEvent: 1294–1546)
---
## 0. 术语
| 术语 | 含义 |
|------|------|
| 项目(project) | 一次公司级执行,对应 `CompanyProject` 一行 |
| 部门(department) | 复用 `Team`,通过 `Team.parent_company_id` 挂到公司 |
| phase | 部门内 `TeamOrchestrator` 的一个执行阶段(PM/架构/开发/QA...) |
| 事件(event) | 编排产生的一条 SSE/WS 消息 |
| 检查点(checkpoint) | 执行循环中读取控制标志的位置 |
| 边界暂停 | 仅在部门/阶段边界暂停,不打断进行中的 LLM 调用 |
---
## 1. 现状深挖(数据源盘点)
### 1.1 execute_stream 事件全集(company_orchestrator.py:513–830)
| type | 关键 payload | 源行 |
|------|------|------|
| start | message | 542 |
| company_start | company_name, department_count, departments[] | 551 |
| ceo_plan_start | message | 560 |
| ceo_plan_done | plan(完整 CEO JSON: analysis/departments/risks/metrics), duration_ms | 568 |
| round_start | round_index, max_rounds, rework_depts[] | 622/635 |
| dept_waiting | department_name, waiting_for[] | 661 |
| dept_budget_exceeded | department_name, max_tokens, tokens_used | 688 |
| dept_agent_event | department_name, department_type, sub_type, **data(整包 team 事件)**, last_thought, phase_progress, phase_name, tokens_used, budget_remaining, budget_percentage | 710 |
| dept_budget | department_name, used, remaining, percentage | 742 |
| dept_done | department_name, success, result{deliverable, files[], phase_count}, duration_ms, tokens_used | 750 |
| ceo_score_start | message, round_index | 767 |
| ceo_score_done | scores[{name,score,feedback,pass,improvement_areas}], overall_score, summary, next_steps, dept_pass_map, round_index | 783 |
| round_done | round_index, scores, overall_score, rework_needed, passed_depts[], failed_depts[] | 799 |
| company_done | success, summary, departments[], project_id, total_duration_ms, round_count, overall_score, review_scores | 819 |
| error | message, phase | 547/565 |
### 1.2 部门内最细粒度(dept_agent_event.data → TeamOrchestrator → AgentRuntime.run_stream)
`agent_event.data` 可透出(core.py 源行):
- `think`: content, reasoning(思维链 reasoning_content), tool_names[], iteration — 944/1062
- `tool_call`: name, **input(完整入参)**, iteration — 1124
- `tool_result`: name, **result(截断 500 字)**, iteration — 1187
- `approval_required`: approval_id, tool_name, args — 1136
- `final`: content, reasoning, iterations_used, tool_calls_made, **token_usage(真实 TokenBudget)** — 1020
TeamOrchestrator.execute_stream 事件:plan_start/plan/plan_done、architect_start/done、parallel_batch_start/phase_start/parallel_batch_end、agent_event、phase_done(output,success,iterations,tool_calls,files[])、qa_start/qa_done(review,score,issues)、fix_phase_start/done、final、error。
### 1.3 数据丢失点 / bug(前端或公司层丢弃)
1. `tool_call.input` / `tool_result.result` 原样在 `data` 里但前端只显示工具名+耗时(CB:1409/1412)。
2. `last_thought` 截断 2000、`thinkHistory` 仅最近 10 条(CB:1403)。
3. 产出文件 `dept_done.result.files` 前端无文件树/预览/下载。
4. token 是**事件计数近似**(company_orchestrator.py:712 `current_used = ... + 1`),非真实;真实值在 phase `final.token_usage`,公司层未上抬。
5. `dept_done.duration_ms` 计时起点不稳(726 `dept_timings.get(name, now)`)。
6. CEO 规划/评分是 `await runtime.run()` 非流式(224/926),过程不可见。
7. `updated_at` 有 `onupdate` 但执行中无 UPDATE → 运行期不刷新 → supervisor 15 分钟误杀(project_supervisor.py:41)。
### 1.4 控制缺口
- 无 execution_id / 无 Celery / 无任务句柄;部门 `asyncio.gather` 跑在请求协程内。
- 全库无 company 的 stop/pause/cancel/resume。
- AgentRuntime 循环无取消检查点(只有 max_iterations 硬停 + 工具审批阻塞)。
- `company_projects` 无 pause_state 字段(workflow 的 pause_state 是另一套,未接入)。
- 断开 SSE 只停消费,后台继续 → 僵尸项目。
---
## 2. 目标架构
### 2.1 时序:启动 → 观测 → 控制
```
Client API Runner(bg task) Redis DB
│ POST execute/async │ │ │ │
│────────────────────▶│ create CompanyProject │ │ │
│ │ status=queued ───────────┼───────────────────┼──────────────▶ insert
│ │ create_task(runner) │ │ │
│◀── {project_id} ────│ │ │ │
│ │ │ execute_stream() │ │
│ WS connect(pid) │ │ each event: │ │
│────────────────────▶│ replay events by seq ◀───┼───────────────────┼────────────── select
│◀── replay... ───────│ │ publish ─────────▶ pub/sub │
│◀── live event ──────┼──────────────────────────┼─────subscribe─────│ │
│ │ │ persist ─────────┼──────────────▶ insert event
│ │ │ heartbeat ───────┼──────────────▶ update updated_at
│ POST stop │ set control flag ────────┼───────────────────▶ key │
│ │ │ checkpoint reads ◀│ │
│ │ │ break → status=stopped ───────────▶ update
│◀── control_ack(WS) ─│ │ │ │
```
### 2.2 控制信号语义
| action | 触发点读到后行为 |
|--------|------------------|
| stop | 检查点 break 出所有循环 → 落 `stopped` |
| pause | 检查点 `while paused: await sleep(0.5)` 轮询,直到 resume/stop |
| resume | 清 pause 标志 |
| skip{dept} | 从当前波 ready 列表移除该部门,标记 skipped |
| rework{depts[]} | 覆盖下一轮 rework 列表(即使本轮 pass) |
---
## 3. 后端详细设计
### 3.1 新表 `company_project_events`
DDL(utf8mb4):
```sql
CREATE TABLE company_project_events (
id CHAR(36) PRIMARY KEY,
project_id CHAR(36) NOT NULL,
seq INT NOT NULL, -- 项目内自增序号,从 1
type VARCHAR(50) NOT NULL,
payload JSON,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
KEY idx_cpe_project_seq (project_id, seq),
CONSTRAINT fk_cpe_project FOREIGN KEY (project_id)
REFERENCES company_projects(id) ON DELETE CASCADE
) DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci;
```
模型 `backend/app/models/company_project_event.py`:
```python
class CompanyProjectEvent(Base):
__tablename__ = "company_project_events"
id = Column(CHAR(36), primary_key=True, default=lambda: str(uuid.uuid4()))
project_id = Column(CHAR(36), ForeignKey("company_projects.id", ondelete="CASCADE"), nullable=False)
seq = Column(Integer, nullable=False)
type = Column(String(50), nullable=False)
payload = Column(JSON)
created_at = Column(DateTime, default=func.now())
__table_args__ = (Index("idx_cpe_project_seq", "project_id", "seq"),)
```
`company_projects` 状态机扩展:`queued/planning/in_progress/paused/stopping/stopped/completed/failed`(+ supervisor 的 zombie)。
### 3.2 迁移安全流程(务必按序)
```bash
cd backend
./venv/Scripts/python.exe -m alembic current # 记录当前真实版本
./venv/Scripts/python.exe -m alembic heads # 应为 d684c9b30c1c(含删表,勿跑)
# 1) 用 introspect 确认表结构已是最新(chat_messages/billing/companies 均存在)
# 2) 对齐版本,不执行任何 DDL:
./venv/Scripts/python.exe -m alembic stamp head
# 3) 新建迁移(只 create company_project_events + add index):
./venv/Scripts/python.exe -m alembic revision -m "026 add company_project_events"
# 手写 upgrade(): op.create_table(...); downgrade(): op.drop_table(...)
# ⚠️ 不要用 --autogenerate(会再次生成删表 diff)
./venv/Scripts/python.exe -m alembic upgrade head
```
> 若 stamp head 会把 `d684c9b30c1c` 标为已应用——因表结构确已存在,这是正确的对齐,不会执行其删表。
### 3.3 Redis 规范(复用 app/core/redis_client.py)
| Key/Channel | 类型 | 值 | TTL |
|-------------|------|----|-----|
| `company:events:{pid}` | pub/sub channel | 事件 JSON | — |
| `company:control:{pid}` | string | `{"action":"stop\|pause\|run\|skip\|rework","dept":...,"ts":...}` | 24h |
| `company:status:{pid}` | string | 最新状态快照 JSON | 24h |
### 3.4 归一化事件信封(落库 + 推送统一格式)
```json
{
"seq": 128,
"pid": "uuid",
"type": "dept_agent_event",
"ts": 1720684800.12,
"payload": { ... 原事件字段 ... }
}
```
落库时 `type/payload` 拆列存;WS 推送发完整信封。
### 3.5 接口契约
**启动(异步)**
```
POST /api/v1/companies/{company_id}/execute/async
body: { project_description: str, max_rounds?: int=3, budget?: {...} }
200: { project_id: str, status: "queued", ws_url: "/api/v1/ws/company-projects/{pid}" }
403: 非归属 404: 公司不存在
```
**事件回放(WS 不可用时的 HTTP 兜底)**
```
GET /api/v1/companies/{company_id}/projects/{pid}/events?since_seq=0&limit=500
200: { events: [信封...], last_seq: int, status: str, finished: bool }
```
**控制**
```
POST /api/v1/companies/{company_id}/projects/{pid}/stop → { ok, status:"stopping" }
POST .../pause → { ok, status:"paused" }
POST .../resume → { ok, status:"in_progress" }
POST .../skip body:{ department_name } → { ok }
POST .../rework body:{ department_names: [] } → { ok }
所有:403 非归属 / 404 项目不存在 / 409 项目已终态
```
### 3.6 后台执行包装器(新 `company_runner.py` 或并入 orchestrator)
```python
async def run_company_project(project_id, company_id, user_id, desc, max_rounds):
db = SessionLocal()
seq = _next_seq(db, project_id) # 断点续跑安全
orch = CompanyOrchestrator(db, company_id, user_id)
orch.control = ControlChannel(project_id) # 见 3.7
try:
_set_status(db, project_id, "in_progress")
async for evt in orch.execute_stream(desc, max_rounds=max_rounds):
env = _envelope(project_id, seq, evt); seq += 1
_persist(db, env) # insert company_project_events
_publish(env) # redis publish
_heartbeat(db, project_id) # 每 N 事件或每 5s update updated_at
_finalize_status(db, project_id) # completed/failed by last event
except asyncio.CancelledError:
_set_status(db, project_id, "stopped"); _publish_terminal(project_id, "stopped"); raise
except Exception as e:
_set_status(db, project_id, "failed"); _publish_terminal(project_id, "failed", str(e))
finally:
db.close()
```
### 3.7 控制通道 + 检查点
```python
class ControlChannel:
def __init__(self, pid): self.pid = pid; self.r = get_redis_client()
def read(self) -> dict: raw = self.r.get(f"company:control:{self.pid}"); return json.loads(raw) if raw else {}
async def gate(self): # 在检查点调用
ctl = self.read()
if ctl.get("action") == "stop": raise asyncio.CancelledError()
while ctl.get("action") == "pause":
await asyncio.sleep(0.5); ctl = self.read()
def skipped(self) -> set: ...
def forced_rework(self) -> list: ...
```
插桩位置(company_orchestrator.py,均在**边界**):
- `:615` 轮次循环头:`await self.control.gate()`;`forced = self.control.forced_rework()` 合并进 rework。
- `:650` 部门 wave 循环头:`await self.control.gate()`;`ready = [x for x in ready if x[0].name not in self.control.skipped()]`。
- `_run_department_stream` 每个 dept 事件 yield 前:`await self.control.gate()`(阶段边界级)。
- (M4)`core.py` run_stream ReAct 循环(~:893)每轮 `if control.read().action=="stop": break`——需把 control 传入 runtime,一期不做。
### 3.8 WS 端点 `backend/app/api/company_ws.py`
```
WS /api/v1/ws/company-projects/{project_id}?token=JWT
```
- 鉴权:仿 `websocket.py:_validate_ws_token`,改为校验 project→company.workspace_id→membership。
- 连接后:
1. 读 `since_seq`(客户端可在 query 带);从 DB 查 `seq > since_seq` 事件按序 `send_json`(回放)。
2. `redis.pubsub().subscribe("company:events:{pid}")`,转发增量。
3. 收到客户端 `{type:"control", action}` 可代理调用控制(或前端直接走 HTTP,二选一,推荐 HTTP)。
4. 项目终态事件后 `send` final → close。
- 复用 `websocket_manager`(app/websocket/manager.py)做连接登记,支持多观察者(同一项目多个前端)。
### 3.9 数据质量修复
- **心跳**:`_heartbeat` 每 5s / 每 20 事件 `project.updated_at = func.now(); db.commit()`。
- **真实 token**:`_run_department_stream` 捕获 phase `final.token_usage`,累加为 `dept_real_tokens`,在 `dept_done`/`dept_budget` 用真实值;保留旧近似字段兼容。
- **duration**:在 `dept_start` 时 `dept_timings[name]=now`,`dept_done` 用差值。
- **supervisor**:阈值改可配 + 依赖心跳后不再误杀(project_supervisor.py:41 阈值保持 900s 即可)。
---
## 4. 前端详细设计
### 4.1 路由(router/index.ts)
```ts
{ path: '/companies/:companyId/projects/:projectId/monitor',
name: 'company-control-room',
component: () => import('@/views/CompanyControlRoom.vue'),
meta: { requiresAuth: true } }
```
### 4.2 Pinia store `stores/companyExecution.ts`
```ts
interface DeptPanel { name; type; status; phase; phaseProgress; agents: AgentTrace[]; tokens; durationMs; files: string[]; log: LogItem[] }
interface AgentTrace { name; iterations: Iter[] }
interface Iter { think; reasoning; toolCalls: {name;input;result;durationMs}[]; final? }
interface State {
projectId; status; connected;
ceoPlan; ceoScores; rounds: {index;reworkDepts;overallScore}[]; currentRound;
depts: Record<string, DeptPanel>; timeline: TL[]; rawEvents: Envelope[];
tokensTotal; controlBusy;
}
actions: connect(pid), disconnect(), applyEvent(env), stop(), pause(), resume(), skip(dept), rework(depts)
getters: deptList, dag(nodes/edges from ceoPlan.departments+dependencies), runningDepts
```
- `applyEvent` 迁移并扩展 `CompanyBuilder.routeStreamEvent`(CB:1294),**补充**解析 `tool_call.input`/`tool_result.result` 与 `final.token_usage`。
### 4.3 WS 客户端(带重连 + 回放)
```ts
connect(pid) {
ws = new WebSocket(`${wsBase}/ws/company-projects/${pid}?token=${token}&since_seq=${lastSeq}`)
ws.onmessage = e => applyEvent(JSON.parse(e.data))
ws.onclose = () => backoffReconnect() // 断线指数退避重连,带 since_seq 续传
}
// 降级:WS 建连失败 → GET .../events 轮询 since_seq
```
### 4.4 组件树(CompanyControlRoom.vue)
```
CompanyControlRoom
├─ ControlBar 状态徽标 + 停止/暂停/恢复 + 轮次 el-steps
├─ split-left
│ └─ CompanyDag @vue-flow 组织+依赖图,节点实时染色 + 右键跳过/返工
├─ split-center
│ └─ DeptPanelList
│ └─ DeptPanelCard (可展开)
│ └─ AgentTraceView phase→agent→iteration(think/act/observe + 工具入参出参折叠)
└─ split-right (el-tabs)
├─ FilesTab 产出文件树 + 预览
├─ StatsTab 真实token/阶段耗时/工具次数(可选 echarts,或纯表格)
├─ RawEventsTab 复用 SystemLogs 筛选范式的事件流查看器
└─ CeoTab CEO 规划全文 + 评分卡
```
### 4.5 事件 → UI 映射(扩展版,新增粗体项)
| 事件 | 更新 |
|------|------|
| company_start | 初始化 dag 节点 |
| ceo_plan_done | **CeoTab 全文 analysis** + dag 依赖边 |
| dept_start/waiting | dag 节点状态、DeptPanelCard |
| dept_agent_event(think) | AgentTraceView 追加 iteration.think + **reasoning** |
| dept_agent_event(tool_call) | **iteration.toolCalls 追加 {name,input}** |
| dept_agent_event(tool_result) | **对应 toolCall 补 result+durationMs** |
| dept_agent_event(final) | **iteration.final + 真实 token_usage** |
| dept_done | 文件树、真实 token、耗时、节点终态 |
| ceo_score_done | 评分卡 |
| round_start/done | 轮次 el-steps |
| company_done / terminal | ControlBar 终态、停止轮询 |
| (所有) | RawEventsTab append |
### 4.6 API 封装(api/companies.ts 新增)
```ts
executeAsync(companyId, body): {project_id, ws_url}
getProjectEvents(companyId, pid, sinceSeq): {events,last_seq,status,finished}
stopProject / pauseProject / resumeProject(companyId, pid)
skipDepartment(companyId, pid, name) / reworkDepartments(companyId, pid, names[])
companyWsUrl(pid, sinceSeq)
```
---
## 5. 任务分解(按里程碑,文件级 checklist)
### M1 可观测白盒(无控制)
- [ ] 模型 `company_project_event.py` + register in `models/__init__.py`
- [ ] alembic 迁移(手写,非 autogenerate)+ 按 3.2 流程 stamp→upgrade
- [ ] `company_runner.py`:`run_company_project`(含 persist/publish/heartbeat),暂不接 control
- [ ] `companies.py`:`POST /execute/async`、`GET /projects/{pid}/events`
- [ ] `company_ws.py`:WS 端点 + 回放 + pub/sub;`main.py` 注册路由
- [ ] 数据质量:真实 token 透传、duration、updated_at 心跳
- [ ] 前端:route、`stores/companyExecution.ts`、`CompanyControlRoom.vue`、WS 客户端、api 封装
- [ ] `CompanyBuilder.vue`:加"进入控制室"入口,流式执行改走 async
### M2 停止 + 边界暂停/恢复
- [ ] `ControlChannel` + 检查点插桩(615/650/_run_department_stream)
- [ ] `companies.py`:stop/pause/resume 端点 + Redis flag
- [ ] runner:`except CancelledError` 落 stopped
- [ ] 前端 ControlBar 按钮 + store actions
- [ ] 后台任务句柄:进程内 `dict[pid]=task`(用于本 worker 内 join/清理)
### M3 跳过部门 / 手动返工
- [ ] skip/rework 端点 + ControlChannel.skipped()/forced_rework()
- [ ] 编排循环消费 skip/forced_rework
- [ ] DAG 节点右键操作 + store actions
### M4(增强,改 core.py)
- [ ] control 传入 `AgentRuntime`;run_stream ReAct 循环加 stop 检查点
- [ ] 快照-重入式真暂停(给 company_projects 加 pause_state,复用 workflow 范式)
---
## 6. 测试计划
### 单元
- `ControlChannel.gate()`:stop→抛 CancelledError;pause→阻塞至 resume。
- `_next_seq`/`_envelope`/`_persist` 序号连续、幂等。
- 迁移 upgrade/downgrade 可逆;downgrade 不误删他表。
### 集成(pytest + 真实/临时库)
- `POST /execute/async` 返回 project_id 且后台任务落库事件。
- `GET /projects/{pid}/events?since_seq=` 有序、可分页续传。
- stop:运行中 stop → 数秒内状态 stopped、无新事件。
- pause/resume:pause 后 event seq 停增,resume 后继续。
- 权限:跨用户访问他人项目/控制 → 403。
### E2E(手动,按红头指南启动)
1. `manage.ps1 restart` 全绿,登录 admin/123456。
2. 建/选一个公司 → 启动项目 → 控制室实时看到 CEO 全文、部门 ReAct 逐迭代、工具入参出参、产出文件、真实 token。
3. 运行中刷新页面 → 按 seq 回放 + 继续实时(可恢复)。
4. 暂停→部门边界卡住;恢复→继续;停止→落 stopped,`manage.ps1 status` 无残留、supervisor 不误判。
5. 跳过某部门 / 手动返工 → DAG 与结果生效。
6. 回归:旧 `/execute/stream` + CompanyBuilder 原视图仍可用。
---
## 7. 灰度 / 回滚
- **特性开关**:`company.config.control_room_enabled` 或全局 env `COMPANY_CONTROL_ROOM=1`;关闭时前端隐藏入口、后端仅保留旧 `/execute/stream`。
- **兼容**:旧接口与旧内联视图全程保留,新链路独立,可随时回退。
- **回滚**:down 迁移仅 drop `company_project_events`(不动其他表);删新增路由注册即可。
---
## 8. 待确认 / 开放问题
1. 多 uvicorn worker 部署?若是,后台 asyncio 任务方案需评估是否迁 Celery(获得 revoke + 跨进程句柄)。当前若单 worker,asyncio + Redis flag 足够。
2. 事件落库量:一个大项目可能上千事件,是否需要 `payload` 大小上限/截断策略与定期归档。
3. 文件产出预览:是否需要在线读取 `./company_projects/...` 文件内容接口(涉及路径安全校验)。
4. 是否要"多观察者广播"(同一项目多人同时看控制室)——WS manager 已支持,需确认权限粒度。
5. token 计费口径:真实 token 是否要写回 usage_records 做计量。