修改了nanobot,往Hermes agent的风格走,进度1/3

This commit is contained in:
2026-04-20 18:11:14 +08:00
parent cdfc222c9f
commit 36882a7d7b
261 changed files with 12659 additions and 604 deletions

View File

@ -0,0 +1,470 @@
# Boardware Genius Backend
这是 `Boardware Genius` 的后端服务仓库;当前技术命令和包名仍沿用 `nanobot`,但产品品牌按 `Boardware Genius` 表述:
- `nanobot web`:单用户 FastAPI 后端,供独立前端或 `/docs` 调试使用
- `nanobot gateway`:常驻 worker负责渠道接入、cron、heartbeat
- MCP 动态工具接入
- Outlook 集成:通过外部 `BW_Outlook_Mcp` 服务接入 Microsoft Graph / Exchange EWS
- 工作区文件、技能、插件、代理、MCP 管理等 Web API
如果你后续要把它打包成 Docker 丢到服务器,这份 README 就是给开发和部署同事看的执行文档。
## 这套仓库现在是什么
这不是一个自带前端静态页面的全栈仓库,而是后端仓库:
- Web 模式启动的是 FastAPI API 服务
- Gateway 模式启动的是常驻 agent / channel / cron 进程
- WhatsApp 相关逻辑依赖 `bridge/` 里的 Node 20 bridge
- Outlook 不是仓库内置模块,而是通过外部 `BW_Outlook_Mcp` 仓库接进来
更细的执行链路可以看 [workflow.md](./workflow.md)。
## 目录结构
```text
.
├── nanobot/ # Python 主体CLI、agent、web、channels、config、MCP
├── bridge/ # WhatsApp bridgeNode 20
├── tests/ # 测试
├── Dockerfile # 当前镜像构建文件
├── docker-compose.yml # 当前自带 compose 示例(偏 gateway / CLI
└── workflow.md # 运行链路说明
```
## 运行模式
| 命令 | 用途 | 默认端口 | 适合谁 |
| --- | --- | --- | --- |
| `nanobot agent` | 本地单轮 / 交互调试 | 无 | 开发排查 |
| `nanobot web` | 启动 FastAPI 后端 | `18080` | 独立前端、接口调试、单用户使用 |
| `nanobot gateway` | 启动常驻 worker | 无固定 HTTP 入口 | Telegram/Slack/Email/cron/heartbeat |
| `nanobot status` | 查看配置和 provider 状态 | 无 | 开发、运维 |
注意:
- 如果你是给 Web 前端提供后端,请启动 `nanobot web`,不要误用 `gateway`
- `gateway` 当前不是对外 Web API 服务
- `web``gateway` 都会碰到同一份 workspace / cron / MCP 状态,通常不要在同一份数据目录上无脑同时跑两套
## 环境要求
- Python `>=3.11`
- 推荐使用 `uv`
- 如果要构建 WhatsApp bridge 或使用仓库自带 Dockerfile需要 Node.js `20`
本地开发最省事的方式:
```bash
uv sync --extra dev
```
如果你不用 `uv`,也可以:
```bash
python3 -m venv .venv
. .venv/bin/activate
pip install -e ".[dev]"
```
## 本地快速启动
### 1. 初始化配置
```bash
nanobot onboard
```
初始化后默认会生成:
- 配置文件:`~/.nanobot/config.json`
- 工作区:`~/.nanobot/workspace`
### 2. 填最小配置
下面是一份适合服务器环境的最小示例,重点是:
- 用绝对路径的 workspace
- 建议打开 `restrictToWorkspace`
- 先用 API Key provider少踩 OAuth 交互坑
```json
{
"agents": {
"defaults": {
"workspace": "/root/.nanobot/workspace",
"model": "openai/gpt-5"
}
},
"providers": {
"openai": {
"apiKey": "sk-xxxx"
}
},
"tools": {
"restrictToWorkspace": true
}
}
```
如果你不是跑在容器里,把 `/root/.nanobot/workspace` 换成你自己的绝对路径。
### 3. 检查配置
```bash
nanobot status
```
### 4. 本地调试 agent
```bash
nanobot agent -m "你好"
```
### 5. 启动 Web 后端
```bash
nanobot web --host 0.0.0.0 --port 18080
```
启动后可直接访问:
- `http://127.0.0.1:18080/docs`
- `http://127.0.0.1:18080/api/ping`
## Web API 能力概览
当前 `nanobot web` 提供的 API 大致包括:
- 聊天与流式输出
- 会话管理
- cron 任务管理
- skills / plugins / agents 管理
- 工作区文件浏览、上传、下载、删除
- MCP server 管理与测试
- Outlook 集成状态、连接测试、连接/断开、Overview、Message Detail
如果你有独立前端,这个后端就是给前端接的;如果没有前端,也可以直接走 `/docs` 调试。
## Outlook MCP 集成
这是当前仓库里最容易部署时踩坑的一块。
### 关系先说清楚
当前后端不会自己实现 Outlook 协议,它依赖外部仓库 `BW_Outlook_Mcp`
- 后端代码位置:`nanobot/web/outlook.py`
- 默认查找逻辑:
1. 先看环境变量 `NANOBOT_OUTLOOK_MCP_ROOT`
2. 再看与本仓库同级目录的 `../BW_Outlook_Mcp`
3. 如果以上都没有,就尝试直接执行 PATH 里的 `bw-outlook-mcp`
也就是说,部署同事必须额外把 `BW_Outlook_Mcp` 这个仓库准备好,或者把它直接安装进镜像。
### 推荐的两种接法
#### 方案 A把 `BW_Outlook_Mcp` 安装进同一个 Python 环境
这是生产环境更稳的方案。
部署同事需要:
```bash
git clone <你们的 BW_Outlook_Mcp 仓库地址> /srv/BW_Outlook_Mcp
cd /srv/BW_Outlook_Mcp
pip install -e .
```
安装完成后,容器或宿主机里能直接执行:
```bash
bw-outlook-mcp --help
```
这样 Boardware Genius 就会直接用 PATH 里的 `bw-outlook-mcp`,不依赖额外挂载路径。
#### 方案 B把 `BW_Outlook_Mcp` 作为外部目录挂进来
这是开发或临时部署更方便的方案。
部署同事需要至少做到两件事:
1.`BW_Outlook_Mcp` 仓库拉到服务器
2. 让这个目录里存在一个可执行的 `bw-outlook-mcp`
最简单的约定是:
```bash
git clone <你们的 BW_Outlook_Mcp 仓库地址> /srv/BW_Outlook_Mcp
cd /srv/BW_Outlook_Mcp
python3 -m venv .venv
. .venv/bin/activate
pip install -e .
```
然后给 Boardware Genius 设置:
```bash
export NANOBOT_OUTLOOK_MCP_ROOT=/srv/BW_Outlook_Mcp
```
因为当前后端会优先寻找:
```text
$NANOBOT_OUTLOOK_MCP_ROOT/.venv/bin/bw-outlook-mcp
```
如果你挂了仓库目录但里面没有 `.venv/bin/bw-outlook-mcp`,那就必须确保 `bw-outlook-mcp` 已经在容器 PATH 里。
### Outlook 的认证和配置
`BW_Outlook_Mcp` 本身支持两套后端:
- `graph`Microsoft 365 / Exchange Online
- `ews`:本地或回迁后的 Exchange Server
#### Graph 登录
```bash
bw-outlook-mcp auth login-graph \
--workspace /root/.nanobot/workspace \
--client-id YOUR_CLIENT_ID \
--tenant-id YOUR_TENANT_ID
```
#### EWS 配置
```bash
bw-outlook-mcp auth setup-ews \
--workspace /root/.nanobot/workspace \
--email you@example.com \
--username your_username \
--domain example.com \
--server mail.example.com
```
如果你已经有固定 EWS URL也可以改用
```bash
bw-outlook-mcp auth setup-ews \
--workspace /root/.nanobot/workspace \
--email you@example.com \
--username your_username \
--service-endpoint https://mail.example.com/EWS/Exchange.asmx
```
#### 查看状态
```bash
bw-outlook-mcp auth status --workspace /root/.nanobot/workspace
```
### Outlook 状态文件会落在哪里
所有 Outlook 相关状态默认都落在 workspace 下:
```text
<workspace>/state/bw_outlook_mcp/
├── config.json
├── secrets.json
├── graph_token_cache.bin
├── delta_store.json
└── idempotency.sqlite3
```
所以 Docker 部署时,不要只挂配置文件;要把整份 `~/.nanobot` 或至少 workspace 做持久化。
### Nanobot 里如何注册 Outlook MCP
如果你通过 Web 接口完成 Outlook 连接,后端会自动把 MCP server 注册到配置里。
手工写配置时,结构类似这样:
```json
{
"tools": {
"mcpServers": {
"outlook": {
"command": "bw-outlook-mcp",
"args": ["serve", "--workspace", "/root/.nanobot/workspace"],
"sensitive": true,
"toolTimeout": 60
}
}
}
}
```
这里一定要用绝对路径,不要写 `~/.nanobot/workspace`
### 可选的 Outlook 环境变量
| 变量 | 作用 |
| --- | --- |
| `NANOBOT_OUTLOOK_MCP_ROOT` | 指向外部 `BW_Outlook_Mcp` 仓库目录 |
| `NANOBOT_OUTLOOK_MCP_COMMAND` | 强制指定 `bw-outlook-mcp` 可执行文件 |
| `NANOBOT_OUTLOOK_MCP_EXTRA_ARGS` | 给 `bw-outlook-mcp serve` 追加参数 |
| `NANOBOT_OUTLOOK_DEFAULT_DOMAIN` | Web 连接表单的默认域名 |
| `NANOBOT_OUTLOOK_DEFAULT_EWS_URL` | Web 连接表单默认 EWS 地址 |
| `NANOBOT_OUTLOOK_DEFAULT_EWS_SERVER` | Web 连接表单默认 Exchange 主机 |
| `NANOBOT_OUTLOOK_DEFAULT_TIMEZONE` | Web 连接表单默认时区 |
| `NANOBOT_OUTLOOK_DEFAULT_AUTODISCOVER` | Web 连接表单默认是否启用 autodiscover |
## Docker 部署
### 先说结论
服务器部署时,最重要的是持久化这份目录:
```text
/root/.nanobot
```
因为它里面不只是 `config.json`,还包括:
- workspace
- sessions
- cron 状态
- Web 登录信息
- Outlook 状态与 token 缓存
### 构建镜像
```bash
docker build -t nanobot-backend:latest .
```
### 首次初始化
第一次跑容器时,先执行一次:
```bash
docker run --rm \
-v /srv/nanobot/data:/root/.nanobot \
nanobot-backend:latest \
onboard
```
然后去编辑宿主机上的:
```text
/srv/nanobot/data/config.json
```
或者先进去执行:
```bash
docker run --rm -it \
-v /srv/nanobot/data:/root/.nanobot \
nanobot-backend:latest \
status
```
### 作为 Web 后端启动
如果你是给前端项目配后端,推荐这样跑:
```bash
docker run -d \
--name nanobot-web \
-p 18080:18080 \
-v /srv/nanobot/data:/root/.nanobot \
-e NANOBOT_OUTLOOK_MCP_ROOT=/opt/BW_Outlook_Mcp \
-v /srv/BW_Outlook_Mcp:/opt/BW_Outlook_Mcp \
nanobot-backend:latest \
web --host 0.0.0.0 --port 18080
```
如果你已经把 `bw-outlook-mcp` 安装进镜像了,就不需要挂 `/srv/BW_Outlook_Mcp`,也不需要 `NANOBOT_OUTLOOK_MCP_ROOT`
### 作为 Gateway/Worker 启动
如果你要接 Telegram / Slack / Email / cron 之类的常驻能力,再跑 gateway
```bash
docker run -d \
--name nanobot-gateway \
-v /srv/nanobot/data:/root/.nanobot \
nanobot-backend:latest \
gateway
```
### 推荐的服务器 compose 片段
仓库自带的 [docker-compose.yml](./docker-compose.yml) 更偏本地 gateway/CLI 示例。
如果你是部署 Web 后端到服务器,更建议单独写成这样:
```yaml
services:
nanobot-web:
image: nanobot-backend:latest
container_name: nanobot-web
command: ["web", "--host", "0.0.0.0", "--port", "18080"]
restart: unless-stopped
ports:
- "18080:18080"
volumes:
- /srv/nanobot/data:/root/.nanobot
- /srv/BW_Outlook_Mcp:/opt/BW_Outlook_Mcp
environment:
NANOBOT_OUTLOOK_MCP_ROOT: /opt/BW_Outlook_Mcp
```
如果你想把 Outlook 依赖做得更稳,推荐直接把 `BW_Outlook_Mcp` 安装进镜像,而不是运行时挂载仓库。
## 部署给同事时,至少要交代这几件事
1. 这是后端仓库,不带前端静态页面,前端请单独部署
2. Web API 用 `nanobot web` 启动,不是 `gateway`
3. 数据目录必须持久化到 `/root/.nanobot`
4. 如果要 Outlook必须额外拉取 `BW_Outlook_Mcp`
5. Outlook 有两种接法:装进镜像,或者挂外部仓库并设置 `NANOBOT_OUTLOOK_MCP_ROOT`
6. Outlook 的状态文件也在 workspace 里,删容器不挂卷就会丢
## 常用命令
```bash
nanobot onboard
nanobot status
nanobot agent -m "你好"
nanobot web --host 0.0.0.0 --port 18080
nanobot gateway
nanobot provider login openai-codex
```
## 开发备注
- `workflow.md` 记录了当前代码实际运行链路,和旧版 README 更接近“真实代码”
- `nanobot/web/outlook.py` 是当前 Outlook 集成入口
- `tests/` 里有 Web API、Email、Docker 相关测试
- 如果要上服务器,建议在配置里显式打开 `tools.restrictToWorkspace=true`
## 排错
### Web 启动了,但 Outlook 相关接口报错
优先检查:
- `bw-outlook-mcp` 是否能在当前容器里执行
- `NANOBOT_OUTLOOK_MCP_ROOT` 是否指向正确目录
- 如果走目录挂载模式,目录里是否真的有 `.venv/bin/bw-outlook-mcp`
### MCP 注册了,但工具没有出现
检查:
- `config.json` 里的 `tools.mcpServers`
- `nanobot web``nanobot agent` 启动时是否用了同一份 `~/.nanobot`
- Outlook MCP 是否能单独执行 `bw-outlook-mcp auth status --workspace ...`
### Docker 里配置改了没生效
优先检查你挂载的是不是整份:
```text
/srv/nanobot/data:/root/.nanobot
```
不是只挂了某一个文件。