内容
# 智能体控制台
> 后续开发必须先阅读 [SPECDEV](docs/SPECDEV.md)。项目路线已从单纯聊天控制台转向 MCP Agent Workspace:上传项目可生成结构化审查报告,同时可定时调用 MCP 工具生成结果并推送到飞书或企业微信。
一个基于 FastAPI、React 和 Pydantic Deep Agents 的 Web 智能体控制台。用户可以在浏览器里和 Agent 多轮对话,上传文件或文件夹作为工作区上下文,并在运行时查看 Skill、MCP 状态、工具调用、执行状态和会话历史。
> 说明:需求中提到的 `pydantic-deepagents` 对应 Pydantic Deep Agents 项目语义;当前公开 PyPI 包名是 `pydantic-deep`,导入名是 `pydantic_deep`。
## 产品方向和当前能力
- 多轮对话、会话新建、重置、重命名、删除
- 对话框是唯一功能入口:所有能力通过自然语言或 `/` 斜杠命令触发
- 斜杠命令:`/help` `/audit [security|testing|deployment|architecture]` `/issues` `/report` `/export json|markdown` `/schedule` `/connect github` `/disconnect github` `/mcp`,输入 `/` 自动补全
- 右上角任务 / 文件 / 工具 / 报告抽屉,只负责管理聊天过程中形成的结构化对象
- MCP 连接管理中心:所有授权在界面内完成,不需要改 `.env`。GitHub 支持粘贴 Personal Access Token 或 OAuth App 授权;Gmail 支持界面内填 Google OAuth Client 后授权;界面凭证保存在本地数据库(app_settings),环境变量配置优先
- Gmail 定时简报:`每天18:00 总结 Gmail 未读邮件并提取待办` → 对话式创建 → 未读列表 → LLM 中文逐封摘要 + 待办提取 → 飞书/企业微信推送;默认只读 scope,发送邮件属于确认制写操作
- Project Audit:上传项目 → `/audit` 发起 → 多轮深挖 → 问题池 → 状态标记 → `/report` 生成结构化报告 → `/export` 导出给其他平台
- 审查报告导出:JSON / Markdown / HTML / PDF,产物保存为 artifact 并保留报告历史
- 专项审查 Skill:security-audit / test-readiness / deployment-readiness(registry 记录来源、许可证、版本、allowed tools)
- Scheduler:对话式创建、对话式修改(“把这个任务改成每天下午6点” → patch 确认卡片)、手动运行、运行记录
- 调度运行:失败自动重试(`SCHEDULE_RUN_RETRIES`)、运行超时标记失败(`SCHEDULE_RUN_TIMEOUT_SECONDS`)、重启后恢复到期任务
- 飞书 / 企业微信 Webhook 推送和测试推送,超长消息自动拆分
- MCP Server:GitHub(读+写)、Tavily 搜索、Fetch 网页正文读取
- SQLite / MySQL 双存储:`STORAGE_BACKEND=sqlite|mysql`,18 张表(schedule、run、audit、artifact、tool 权限、工具日志、app_settings、聊天会话、上传文件索引、OAuth 连接)
- 聊天会话和上传文件持久化:后端重启后聊天上下文和上传项目自动水合恢复
- 本地开发默认 SQLite;公网部署切换 MySQL(`.env` 填 `MYSQL_*` + `STORAGE_BACKEND=mysql`,首次启动自动建表)
- 前端测试(vitest + testing-library)与 Playwright 浏览器 E2E 脚本(`npm run e2e`)
<details>
<summary>原始能力清单</summary>
- 多轮对话、会话新建、重置、重命名、删除
- 目标信息架构:一个统一聊天入口,Project Audit 和定时任务都从聊天触发
- 目标管理方式:右上角任务 / 文件 / 工具 / 报告抽屉管理结构化对象
- Project Audit:读取上传文件、审查会话、问题池、问题状态、结构化报告、JSON/Markdown 导出
- Scheduler:对话式任务计划、确认保存、手动运行、运行记录
- Scheduler 支持页面配置飞书 / 企业微信 Webhook,保存后 Run now 和后台调度会使用所选通道推送
- SQLite 持久化:保存 schedule、run、audit session、issue、report
- 单进程后台调度器:按 `next_run_at` 到点运行已启用任务
- 飞书 / 企业微信 Webhook 推送和测试推送
- Tavily 搜索客户端
- 左侧会话历史栏,可折叠
- 右侧工作树,可展开文件夹、预览代码/文本文件
- 文件/文件夹 multipart 上传,保留相对路径
- Pydantic Deep `create_deep_agent(...)` + `agent.iter(...)` 原生执行链路
- Skill 通过 `skill_directories=[backend/skills]` 注册到 `SkillsToolset`
- Agent 可通过 `read_file` / `grep` / `glob` 等文件工具读取上传文件
- 工具调用日志和输入框上方的轻量执行提示
- MCP Server 配置、状态展示,以及 GitHub MCP。公共 GitHub 读取可不配置 token,私有仓库、更高限额或写操作需要 GitHub OAuth / `GITHUB_TOKEN`
- GitHub MCP 覆盖 repo、文件、issue、PR、Actions、code search、labels、projects、branches、tags、contributors、rate limit 查询
- GitHub 写操作支持创建 issue、评论 issue/PR、添加 labels、合并 PR,默认必须确认并记录审计日志
- DeepSeek direct stream 降级链路
- 前端 Codex 风格工作台布局和 Three.js 点阵背景
</details>
## 技术栈
```text
Frontend:
React + TypeScript + Vite
Tailwind CSS
Framer Motion
lucide-react
Three.js
Backend:
Python 3.10+
FastAPI
Pydantic / pydantic-settings
pydantic-deep
DeepSeek OpenAI-compatible API
Runtime:
SKILL.md 本地 Skill
Pydantic Deep SkillsToolset
Pydantic Deep filesystem tools
In-memory SessionStore
Mock MCP config
Local stdio GitHub MCP server
```
## 项目结构
```text
.
├── backend/
│ ├── app/
│ │ ├── api/ # chat/session/upload/skill/mcp routes
│ │ ├── core/ # agent factory, runner, prompts, sessions, config
│ │ ├── mcp/ # MCP config, mock status, GitHub stdio MCP server
│ │ ├── schemas/ # API DTOs
│ │ └── skills/ # skill discovery endpoint support
│ ├── skills/
│ │ ├── code-review/
│ │ ├── test-generator/
│ │ ├── data-analysis/
│ │ └── documentation-writer/
│ ├── tests/
│ ├── mcp_servers.json
│ └── pyproject.toml
│
├── frontend/
│ ├── src/
│ │ ├── api/
│ │ ├── components/
│ │ ├── components/ui/
│ │ ├── lib/
│ │ ├── styles/
│ │ └── types.ts
│ └── package.json
│
├── .env.example
└── README.md
```
## 快速启动
### 1. 配置环境变量
```bash
cp .env.example .env
```
`.env` 示例:
```env
DEEPSEEK_API_KEY=your-key
DEEPSEEK_BASE_URL=https://api.deepseek.com
DEEPSEEK_MODEL=deepseek-v4-flash
GITHUB_TOKEN=your-github-token
GITHUB_CLIENT_ID=your-github-oauth-app-client-id
GITHUB_CLIENT_SECRET=your-github-oauth-app-client-secret
GITHUB_OAUTH_REDIRECT_URL=http://127.0.0.1:8010/api/github/oauth/callback
FRONTEND_BASE_URL=http://127.0.0.1:5175
TAVILY_API_KEY=your-tavily-key
FEISHU_WEBHOOK_URL=https://open.feishu.cn/open-apis/bot/v2/hook/xxx
WECOM_WEBHOOK_URL=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx
DATABASE_PATH=backend/data/agent_workspace.sqlite3
STORAGE_BACKEND=sqlite
MYSQL_HOST=127.0.0.1
MYSQL_PORT=3306
MYSQL_USER=
MYSQL_PASSWORD=
MYSQL_DATABASE=agent_console
SKILLS_DIR=backend/skills
MCP_CONFIG_PATH=backend/mcp_servers.json
VITE_API_PROXY_TARGET=http://127.0.0.1:8010
```
`FEISHU_WEBHOOK_URL` 是飞书群自定义机器人 Webhook 地址,当前 Scheduler 默认使用飞书推送。`WECOM_WEBHOOK_URL` 是企业微信群机器人 Webhook 地址,作为兼容通道保留。请不要提交真实 key。
### 2. 启动后端
`pydantic-deep` 要求 Python 3.10+,推荐 Python 3.12。
```bash
cd backend
python3.12 -m venv .venv
source .venv/bin/activate
pip install -e ".[test,deepagents]"
uvicorn app.main:app --reload --host 127.0.0.1 --port 8010
```
健康检查:
```bash
curl http://127.0.0.1:8010/api/health
```
### 3. 启动前端
```bash
cd frontend
npm install
npm run dev
```
访问:
```text
http://127.0.0.1:5175
```
## 核心流程
### Project Audit
```text
上传项目文件夹
↓
点击输入框附件区的“代码审查”按钮,显式发起 Project Audit
↓
创建审查会话
↓
读取上传文件并生成初始审查问题
↓
问题进入 issue pool
↓
用户标记 confirmed / false_positive / needs_review
↓
点击生成审查报告
↓
结构化报告视图
↓
导出 JSON / Markdown
```
上传文件后,普通聊天不会默认进入代码审查;只有点击“代码审查”按钮,或在聊天中明确输入“审查 / review / 上线风险 / 安全漏洞”等意图时,才会进入 Project Audit。
### Scheduler
```text
用户在统一聊天框自然语言描述定时任务
↓
POST /api/schedules/plan
↓
聊天流生成可编辑任务确认卡片
↓
用户可修改时间、内容、MCP 工具、推送通道
↓
用户确认卡片
↓
保存 schedule 到 SQLite
↓
右上角任务抽屉刷新
↓
Run now 或后台调度器到点触发
↓
调用 GitHub / Tavily / Feishu 或 WeCom
↓
保存 run history
```
飞书 Webhook 可以在 `.env` 中配置 `FEISHU_WEBHOOK_URL`,也可以在右上角 `工具` 抽屉中粘贴并保存。企业微信 Webhook 仍可通过 `WECOM_WEBHOOK_URL` 或工具抽屉配置。页面只展示脱敏后的地址。没有配置所选 Webhook 时,Run now 仍会生成结果和工具日志,但推送状态为 false。
GitHub Explore 简报主内容优先来自 GitHub API,展示精选项目卡片,包括项目名、stars、language、亮点、适合谁和 GitHub 直达链接。Tavily 只作为补充来源,不会把 CSDN/博客等搜索结果原文倾倒进推送内容。飞书推送使用干净纯文本,不直接发送 Markdown 报告原文。
GitHub 公共只读搜索不强制要求 `GITHUB_TOKEN`;没有 token 时会使用 GitHub 公共 API,可能受到更严格的频率限制。上线或多人使用时应配置 GitHub OAuth App,并让用户在工具抽屉点击“连接 GitHub”完成授权。工具抽屉会展示 GitHub rate limit 和工具权限策略;读工具默认 `auto`,写工具默认 `confirm`,`disabled` 会在后端执行层拦截。Tavily 需要 `TAVILY_API_KEY`,未配置时会在工具日志中显示降级错误。
### MySQL 存储
本地默认使用 SQLite。上线部署可以切换为 MySQL:
```env
STORAGE_BACKEND=mysql
MYSQL_HOST=127.0.0.1
MYSQL_PORT=3306
MYSQL_USER=agent
MYSQL_PASSWORD=your-password
MYSQL_DATABASE=agent_console
```
MySQL store 会自动创建以下业务表:
```text
schedules
schedule_runs
github_connections
github_oauth_states
audit_sessions
audit_messages
audit_issues
audit_reports
notification_channels
tool_permissions
tool_call_logs
```
```text
React Console
↓
创建/选择 session
↓
上传文件或文件夹
↓
POST /api/sessions/{session_id}/uploads
↓
DeepAgentDeps.upload_files(...)
↓
POST /api/chat/stream
↓
SessionStore 取出 message_history + deps
↓
slash command → <skill-hint>(可选软提示)
↓
全局 Pydantic Deep Agent
↓
agent.iter(user_prompt, message_history, deps, conversation_id)
↓
SSE 输出 status / token / tool_call / tool_result / done
↓
前端渲染聊天、执行状态、工具日志、工作树
```
## 后端设计
### AgentFactory
`backend/app/core/agent_factory.py`
应用启动时创建全局单 Agent。Agent 本身尽量保持无状态,具体会话数据放在 `SessionStore` 中。
### PydanticDeepAgentsAdapter
`backend/app/core/deepagents_adapter.py`
负责隔离 `pydantic-deep` 依赖,主要完成:
- import `pydantic_deep`
- 构造 DeepSeek provider / model
- 调用 `create_deep_agent(...)`
- 注册 `skill_directories`
- 开启 `include_skills=True`
- 开启 `include_filesystem=True`
- 按 `backend/mcp_servers.json` 构建 MCP toolset 并传入 `mcp_servers`
- 挂载 `SlidingWindowCapability`
- 在失败时返回明确错误,允许 fallback
### PydanticDeepAgentRunner
`backend/app/core/deepagents_runner.py`
使用 `agent.iter(...)` 而不是简单 `run_stream(...)`,这样可以把工具调用过程拆出来发给前端:
- `text`
- `tool_call`
- `tool_result`
前端据此展示“正在读取文件”“正在搜索内容”等轻量状态。
### SessionStore
`backend/app/core/session_store.py`
每个 session 保存:
- `messages`: pydantic-ai `ModelMessage` 历史
- `deps`: 独立 `DeepAgentDeps`
- `tool_logs`: 工具和运行日志
当前实现为内存存储,后端重启会丢失。
### Uploads
`backend/app/api/uploads.py`
上传文件使用独立 multipart 端点,不再把文件内容塞进 chat JSON:
```text
POST /api/sessions/{session_id}/uploads
```
后端写入:
```python
session.deps.upload_files([(name, bytes), ...])
```
Agent 后续通过 Pydantic Deep 文件工具读取:
```text
read_file
grep
glob
ls
```
## 前端设计
前端是 Codex 风格工作台:
- 左侧:会话历史,可折叠
- 中间:聊天流、Agent 状态、输入框
- 右侧:工作树和文件预览,可展开/隐藏
- 底部:运行日志摘要
关键组件:
```text
frontend/src/App.tsx
frontend/src/components/ConversationSidebar.tsx
frontend/src/components/ChatPanel.tsx
frontend/src/components/ui/animated-agent-input.tsx
frontend/src/components/ui/file-tree-preview.tsx
frontend/src/components/ui/file-preview.tsx
frontend/src/components/ui/agent-status-hint.tsx
```
文件夹上传时前端使用 `webkitRelativePath` 保留目录结构,因此右侧工作树可以按路径展开。
## Skill 设计
Skill 使用标准目录结构:
```text
backend/skills/<skill-name>/SKILL.md
```
当前内置:
```text
code-review
test-generator
data-analysis
documentation-writer
```
这些 Skill 通过 Pydantic Deep `SkillsToolset` 注册。模型可以自主调用:
```text
list_skills
load_skill
read_skill_resource
run_skill_script
```
前端命令只是软提示:
| 命令 | Skill |
|---|---|
| `/review` | `code-review` |
| `/test` | `test-generator` |
| `/analyze` | `data-analysis` |
| `/docs` | `documentation-writer` |
| `/github` | 使用 GitHub MCP 只读工具 |
## Prompt 设计
`backend/app/core/prompts.py`
系统提示由两部分组成:
1. `pydantic_deep.BASE_PROMPT`
2. 项目补充说明
项目补充说明负责约束:
- 默认中文回复
- 上传文件在 `/uploads`
- 使用 `read_file` / `grep` / `glob` 读取上传文件
- 不要声称能访问宿主机工作区或 Git 仓库
- 如果用户给了 `<skill-hint>`,优先加载对应 Skill
动态内容不再手动拼入 prompt。Skill、文件和历史分别交给 `SkillsToolset`、`DeepAgentDeps`、`message_history` 管理。
## 上下文策略
当前多轮上下文由 pydantic-ai `message_history` 管理:
- 每轮请求传入当前 session 的 `messages`
- Agent 新产生的 `ModelMessage` 写回 session
- 工具调用与工具返回也保留在历史中
- `SlidingWindowCapability(trigger=("tokens", 16000), keep=("tokens", 4000))` 管理长上下文
当前没有启用:
- `include_history_archive`
- `include_memory`
- 持久化 message store
## MCP 配置
配置文件:
```text
backend/mcp_servers.json
```
当前默认包含两个条目:
- `mock-tools`:用于前端状态和工具列表演示,不注入 Agent 的真实 MCP toolset。
- `github`:本地 stdio GitHub MCP Server,会被注入 Pydantic Deep Agent。
```json
{
"servers": [
{
"name": "mock-tools",
"transport": "stdio",
"command": "python",
"args": ["-m", "app.mcp.mock_server"],
"enabled": true
},
{
"name": "github",
"transport": "stdio",
"command": "python",
"args": ["-m", "app.mcp.github_server"],
"enabled": true
}
]
}
```
### GitHub MCP
`backend/app/mcp/github_server.py` 实现了一个 GitHub MCP Server,基于 stdio 运行,并通过 Pydantic AI MCP toolset 接入 Agent。读工具可自动执行,写工具必须经过 Web 控制台确认卡片。
当前提供工具:
```text
github_get_repo
github_list_issues
github_get_issue
github_list_issue_comments
github_list_pull_requests
github_get_pull_request
github_list_pull_request_files
github_list_contents
github_get_file_content
github_list_commits
github_list_releases
github_list_workflow_runs
github_search_repositories
github_get_rate_limit
github_search_code
github_list_labels
github_list_branches
github_list_tags
github_list_contributors
github_list_projects
github_create_issue
github_comment_issue
github_add_labels
github_merge_pull_request
```
公共仓库读取可以不配置 token,但频率限制更严格。本地开发可继续使用 `.env` 里的兜底 token:
```env
GITHUB_TOKEN=ghp_xxx
```
上线使用不建议让用户手动配置 token,而应创建 GitHub OAuth App:
```text
Homepage URL: http://127.0.0.1:5175
Authorization callback URL: http://127.0.0.1:8010/api/github/oauth/callback
```
然后配置:
```env
GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...
GITHUB_OAUTH_REDIRECT_URL=http://127.0.0.1:8010/api/github/oauth/callback
FRONTEND_BASE_URL=http://127.0.0.1:5175
```
用户在右上角“工具”抽屉点击“连接 GitHub”后,后端会通过 OAuth 保存该用户连接;GitHub MCP server 会优先读取 SQLite/MySQL 中的 OAuth token,没有连接时才使用 `GITHUB_TOKEN` 兜底。创建 issue、评论、打 label、合并 PR 这类写操作必须先生成确认卡片,用户点击确认后才执行,并写入 `tool_call_logs`。
## API 概览
```text
GET /api/health
GET /api/skills
GET /api/mcp/servers
POST /api/mcp/reload
GET /api/mcp/permissions
PUT /api/mcp/permissions/{server_name}/{tool_name}
POST /api/mcp/actions/plan
POST /api/mcp/actions/confirm
GET /api/github/rate-limit
POST /api/sessions
POST /api/sessions/reset
GET /api/sessions/{session_id}
DELETE /api/sessions/{session_id}
POST /api/sessions/{session_id}/uploads
GET /api/sessions/{session_id}/files?path=/uploads/foo.py
POST /api/chat/stream
```
`/api/chat/stream` 使用 SSE:
```text
event: status
event: token
event: tool_call
event: tool_result
event: done
event: error
```
## 测试
后端测试:
```bash
cd backend
source .venv/bin/activate
pytest
```
前端构建:
```bash
cd frontend
npm run build
```
当前测试覆盖:
- Skill 发现
- slash 命令和 skill hint
- MCP 配置解析
- GitHub MCP client 读写封装
- GitHub MCP 工具权限、确认执行和审计日志
- MCP toolset 构建
- AgentFactory 绑定
- Pydantic Deep adapter 参数
- Pydantic Deep runner 工具事件
- DeepSeek SSE fallback 解析
- session 创建、重置、删除、历史
- multipart 上传
- 文件预览接口
## 已知限制
- Session、上传文件和工具日志都在内存中,后端重启后丢失。
- GitHub MCP 已支持基础写操作确认链路,但仍不是完整 GitHub App installation 权限模型;公网部署前需要补充更细粒度仓库授权、token 加密、权限审计查询和误操作回滚指引。
- GitHub OAuth token 当前保存在本地 SQLite 中,适合本地演示;公网部署前应改为加密存储或接入云端密钥管理。
- 真实 MCP toolset 目前使用 `MCPServerStdio`,该接口已提示未来会迁移到新版 `MCPToolset`。
- `mock-tools` 仍是前端演示/降级用途,不是标准 MCP 协议服务。
- 文件上传没有权限模型、配额模型和病毒/类型校验。
- 文件夹上传数量限制在前端,后端还没有做更完整的大小和数量限制。
- `SlidingWindowCapability` 是滑动窗口策略,还没有摘要记忆和历史归档。
- DeepSeek fallback 只保证基础聊天,不具备 Pydantic Deep 的 Skill 和文件工具能力。
- Three.js 背景增加首屏 bundle 体积。
## 后续优化方向
### 1. 持久化会话和文件
把当前内存 `SessionStore` 替换为 SQLite / Postgres + 文件系统或对象存储。这样后端重启后,会话、上传文件、工具日志都能恢复。
### 2. 扩展 MCP 能力
当前已经接入本地 stdio GitHub 只读 MCP。后续可以继续扩展:
```text
remote URL / SSE transport
GitHub OAuth
GitHub labels / projects / code search
tool permission policy
timeout and retry policy
tool result persistence
MCPToolset migration
```
### 3. 上传安全和资源限制
后端增加:
- 单文件大小限制
- 单 session 总容量限制
- 文件数量限制
- 二进制文件过滤
- MIME/扩展名校验
- 上传清理策略
### 4. 更强的上下文管理
在滑动窗口外增加:
- history archive
- summarization capability
- session-level memory
- project-level index
这样长代码库审查时不会只依赖最近 token。
### 5. 工作树体验增强
右侧工作树可以继续做:
- 搜索文件
- 展开/收起全部
- 显示 Agent 已读取过的文件
- 显示文件读取次数
- 点击工具日志跳转到对应文件
### 6. 工具调用可视化
把当前淡提示升级为更完整的执行轨迹:
- 当前步骤
- 已读文件列表
- 正在运行的工具
- 工具耗时
- 错误重试
### 7. 前端性能优化
- Three.js 背景动态 import
- 大文件树虚拟列表
- 大消息列表虚拟滚动
- token 渲染批处理
- 分离 vendor chunks
### 8. 生产化部署
- Dockerfile / docker-compose
- 后端日志结构化
- 前端环境变量配置
- 健康检查和 readiness
- CI 中运行 pytest + npm build
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器