272 lines
8.4 KiB
Markdown
272 lines
8.4 KiB
Markdown
# Topic 消息流方案(`topic_mcp`)
|
||
|
||
## 1. 目标与边界
|
||
|
||
### 1.1 目标
|
||
|
||
- 将“对话消息”与“任务反馈消息”分离。
|
||
- 新增 RSS 风格 Topic 面板,支持按 Topic 订阅和无干扰查看。
|
||
- 由模型决定“是否写入 Topic、写入哪个 Topic”。
|
||
|
||
### 1.2 约束
|
||
|
||
- 尽量不修改 nanobot 引擎源码(`engines/nanobot-*`)。
|
||
- 若必须扩展能力,优先通过 Dashboard 内嵌 MCP Server 实现。
|
||
- MCP Server 固定命名:`topic_mcp`。
|
||
|
||
## 2. 术语统一(避免混淆)
|
||
|
||
- `transport_channel`:机器人对外通信渠道(`dashboard/telegram/feishu/qq/...`)。
|
||
- `topic`:Dashboard 内的消息流分组(例如 `inbox`、`build`、`alerts`)。
|
||
- `topic_item`:某个 topic 下的一条消息。
|
||
|
||
## 3. 总体架构
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
U["User"] --> UI["Dashboard UI"]
|
||
UI --> API["Dashboard Backend (FastAPI)"]
|
||
API --> DB["SQLite topic_* tables"]
|
||
API --> MCP["topic_mcp (streamableHttp)"]
|
||
|
||
BOT["nanobot"] -->|"MCP call"| MCP
|
||
MCP --> DB
|
||
|
||
BOT -->|"normal chat via dashboard transport_channel"| API
|
||
API --> UI
|
||
```
|
||
|
||
说明:
|
||
- 聊天消息仍走现有 dashboard 渠道。
|
||
- Topic 写入走 `topic_mcp` 工具调用,不侵入 nanobot 核心 loop/channel。
|
||
- Topic 路由与投递对所有 `transport_channel` 生效(`dashboard/feishu/telegram/qq/...`),即无论用户从哪个渠道发起请求,只要模型调用 `topic_*` 工具,都会统一写入 Topic 面板。
|
||
|
||
## 4. `topic_mcp` 配置策略(默认写入、不可删除)
|
||
|
||
### 4.1 写入位置
|
||
|
||
写入 bot 的 `.nanobot/config.json`:
|
||
|
||
```json
|
||
{
|
||
"tools": {
|
||
"mcpServers": {
|
||
"topic_mcp": {
|
||
"type": "streamableHttp",
|
||
"url": "http://host.docker.internal:8000/api/mcp/topic",
|
||
"headers": {
|
||
"x-topic-mcp-token": "<bot-scoped-token>"
|
||
},
|
||
"toolTimeout": 30
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4.2 不可删除规则
|
||
|
||
在 Dashboard 后端实现硬约束:
|
||
|
||
1. Bot 创建后自动注入 `topic_mcp`。
|
||
2. `PUT /api/bots/{bot_id}/mcp-config` 全量更新时,若缺失 `topic_mcp`,后端自动补回。
|
||
3. 对 `topic_mcp` 的关键字段做白名单校验(`type/url/headers/toolTimeout`)。
|
||
4. 返回给前端时标记 `locked=true`,前端禁用删除按钮(但以后端校验为准)。
|
||
|
||
## 5. `topic_mcp` 工具定义
|
||
|
||
建议工具集(V1):
|
||
|
||
1. `topic_list_topics`
|
||
- 作用:返回当前 bot 可投递的 topic 清单与路由说明。
|
||
- 用途:让模型先了解可投递目标,避免“靠名字猜”。
|
||
|
||
2. `topic_get_schema`
|
||
- 作用:返回允许的 `view` 结构定义(声明式渲染,不允许脚本)。
|
||
- 用途:让模型生成可渲染卡片,而非任意 HTML/JS。
|
||
|
||
3. `topic_route`
|
||
- 作用:输入候选内容,返回 `should_publish`、`topic_key`、`confidence`、`reason`。
|
||
- 用途:把“该不该发、发到哪”交给 Dashboard 规则层,降低模型随意性。
|
||
|
||
4. `topic_publish`
|
||
- 作用:写入一条 topic 消息。
|
||
- 关键字段:`topic_key/title/content/level/tags/view/dedupe_key`.
|
||
|
||
说明:
|
||
- 不建议 V1 暴露 `topic_create/topic_delete` 给模型。
|
||
- topic 由用户在 Dashboard 维护,模型仅消费已发布规则并投递。
|
||
- `sendProgress/sendToolHints` 产生的进度流和工具提示流不应投递到 Topic(默认硬过滤)。
|
||
|
||
## 6. 数据模型(Backend)
|
||
|
||
### 6.1 `topic_bot_settings`
|
||
|
||
- `id` (PK)
|
||
- `bot_id` (unique, index)
|
||
- `topic_enabled`(Topic 总开关,默认 `true`)
|
||
- `created_at/updated_at`
|
||
|
||
### 6.2 `topic_topic`
|
||
|
||
- `id` (PK)
|
||
- `bot_id` (index)
|
||
- `topic_key` (unique with `bot_id`)
|
||
- `name`
|
||
- `description`
|
||
- `is_active`
|
||
- `is_default_fallback`
|
||
- `routing_json`(包含 include/exclude/examples/priority)
|
||
- `view_schema_json`(允许的渲染模板)
|
||
- `created_at/updated_at`
|
||
|
||
### 6.3 `topic_item`
|
||
|
||
- `id` (PK)
|
||
- `bot_id` (index)
|
||
- `topic_key` (index)
|
||
- `title`
|
||
- `content`
|
||
- `level` (`info/warn/error/success`)
|
||
- `tags_json`
|
||
- `view_json`
|
||
- `source` (`mcp/manual/system`)
|
||
- `dedupe_key` (index)
|
||
- `is_read`
|
||
- `created_at`
|
||
|
||
约束:
|
||
- 同一 `bot_id + dedupe_key` 可设置幂等去重窗口(如 10 分钟)。
|
||
- 未命中 topic 时回退到默认 topic(推荐 `inbox`)。
|
||
|
||
## 7. 后端 API(Dashboard)
|
||
|
||
面向 UI 的 REST(示例):
|
||
|
||
- `GET /api/bots/{bot_id}/topics`
|
||
- `POST /api/bots/{bot_id}/topics`
|
||
- `PUT /api/bots/{bot_id}/topics/{topic_key}`
|
||
- `DELETE /api/bots/{bot_id}/topics/{topic_key}`(禁止删除 fallback)
|
||
- `GET /api/bots/{bot_id}/topic-settings`
|
||
- `PUT /api/bots/{bot_id}/topic-settings`(配置 `topic_enabled` 开关)
|
||
- `GET /api/bots/{bot_id}/topic-items?topic_key=...&cursor=...`
|
||
- `POST /api/bots/{bot_id}/topic-items/{id}/read`
|
||
|
||
面向 bot 的 MCP:
|
||
|
||
- `POST /api/mcp/topic`(streamableHttp)
|
||
|
||
## 8. 路由策略(模型如何判断)
|
||
|
||
最终策略是“模型 + 规则引擎”:
|
||
|
||
1. 模型提取候选信息(摘要、类型、重要度)。
|
||
2. 调用 `topic_route` 获取决策建议。
|
||
3. `should_publish=true` 时调用 `topic_publish`。
|
||
4. `should_publish=false` 不写 Topic,仅保留聊天输出。
|
||
5. 当 `topic_enabled=false` 时,`topic_route` 固定返回 `should_publish=false`。
|
||
6. 当消息被判定为 progress/tool-hint(对应 `sendProgress/sendToolHints` 流)时,固定 `should_publish=false`。
|
||
|
||
topic 的路由配置建议包含:
|
||
|
||
- `purpose`:topic 用途
|
||
- `include_when`:应收条件
|
||
- `exclude_when`:排除条件
|
||
- `examples`:正反例
|
||
- `priority`:冲突优先级
|
||
- `system_filters`:系统硬过滤(如 progress/tool-hint)
|
||
|
||
金融信息 topic 路由示例(`topic_key=finance_market`):
|
||
|
||
```json
|
||
{
|
||
"purpose": "沉淀与金融市场相关的关键结论和告警,便于用户集中查看。",
|
||
"include_when": [
|
||
"内容涉及股票/指数/外汇/利率/宏观数据/财报",
|
||
"包含明确数值、时间点、事件影响判断",
|
||
"属于'可执行建议'或'风险提示'"
|
||
],
|
||
"exclude_when": [
|
||
"纯寒暄或无结论聊天",
|
||
"与金融无关的任务进度",
|
||
"重复内容且dedupe_key命中窗口"
|
||
],
|
||
"examples": {
|
||
"positive": [
|
||
"美联储议息后,10Y美债收益率上行20bp,成长股承压",
|
||
"AAPL财报超预期但指引下调,盘后转跌,建议关注开盘波动"
|
||
],
|
||
"negative": [
|
||
"我已经开始处理你的请求",
|
||
"文件上传成功"
|
||
]
|
||
},
|
||
"priority": 80,
|
||
"fallback_topic_key": "inbox"
|
||
}
|
||
```
|
||
|
||
## 9. 前端 Topic Panel
|
||
|
||
UI 结构建议:
|
||
|
||
- 左列:topic 列表(未读计数、筛选)
|
||
- 中列:topic item 流(时间倒序、分页)
|
||
- 右列:item 详情与结构化视图渲染
|
||
- 顶部:`Topic Enabled` 开关(开/关)
|
||
|
||
开关行为:
|
||
|
||
- `ON`:正常执行 `topic_route/topic_publish`。
|
||
- `OFF`:Topic 面板只读历史,不接收新投递;`topic_route` 返回 `should_publish=false`。
|
||
- `topic_mcp` 配置仍保留且不可删除,避免反复改写 `config.json`。
|
||
|
||
渲染要求:
|
||
|
||
- `view` 仅支持声明式类型:`markdown/card/table/checklist/metric/timeline`
|
||
- 禁止执行脚本与任意 HTML 注入
|
||
- 超长内容折叠 + 展开
|
||
|
||
## 10. 安全与治理
|
||
|
||
- `topic_mcp` 使用 bot 级 token 鉴权。
|
||
- 限流:每 bot 每分钟最大 publish 次数。
|
||
- 去重:`dedupe_key` + 时间窗口。
|
||
- 噪声过滤:`sendProgress/sendToolHints` 的进度与工具提示消息不进入 Topic。
|
||
- 降级:无 topic/路由失败时投递 `inbox` 或直接跳过(按策略)。
|
||
- 审计:记录每次 `topic_route/topic_publish` 调用。
|
||
|
||
## 11. 分阶段落地
|
||
|
||
### Phase 1(最小可用)
|
||
|
||
- 新增 `topic_bot_settings` / `topic_topic` / `topic_item` 表
|
||
- 新增 Topic Panel 基础查询展示
|
||
- 实现 `topic_mcp` + `topic_publish`
|
||
- 注入并锁定 `config.json.tools.mcpServers.topic_mcp`
|
||
|
||
### Phase 2(稳定化)
|
||
|
||
- 增加 `topic_list_topics/topic_get_schema/topic_route`
|
||
- 加去重、限流、fallback、审计日志
|
||
- 增加 topic 管理 UI(规则编辑)
|
||
|
||
### Phase 3(体验增强)
|
||
|
||
- item 模板优化与卡片渲染
|
||
- 未读/置顶/归档
|
||
- 统计与告警(topic 热点、失败率)
|
||
|
||
## 12. 与现有代码对接点
|
||
|
||
- MCP 配置接口:`/api/bots/{bot_id}/mcp-config`
|
||
文件:[main.py](/Users/jiliu/WorkSpace/dashboard-nanobot/backend/main.py)
|
||
- 前端主面板:
|
||
[BotDashboardModule.tsx](/Users/jiliu/WorkSpace/dashboard-nanobot/frontend/src/modules/dashboard/BotDashboardModule.tsx)
|
||
- 实时同步:
|
||
[useBotsSync.ts](/Users/jiliu/WorkSpace/dashboard-nanobot/frontend/src/hooks/useBotsSync.ts)
|
||
|
||
原则:
|
||
- 不改 nanobot 核心引擎行为;
|
||
- 通过 Dashboard 承担 Topic 规则、投递和展示。
|