137 lines
6.8 KiB
Markdown
137 lines
6.8 KiB
Markdown
---
|
||
title: Agent 渠道系统
|
||
created: 2026-04-14
|
||
updated: 2026-05-14
|
||
type: entity
|
||
tags: [agent, api, module]
|
||
sources: [packages/backend/src/modules/netaclaw/service/agent_channel.ts, packages/backend/src/modules/netaclaw/service/weixin.ts, packages/backend/src/modules/netaclaw/service/weixin_db.ts, packages/backend/src/modules/netaclaw/service/weixin_archive_sync.ts, packages/backend/src/modules/netaclaw/entity/agent_channel_group.ts, packages/frontend/src/modules/agent/views/channel-management.vue]
|
||
---
|
||
|
||
# Agent 渠道系统
|
||
|
||
将 Agent 接入外部消息平台(当前支持微信),实现消息接收、Agent 处理、澄清/风险确认降级和回复闭环。2026-05-14 后这里已经分成两条微信路径:旧 `weixin` ClawBot 私聊助手,以及新的 `weixin-db` 本地代理群聊路径。
|
||
|
||
## 数据模型
|
||
|
||
**netaclaw_agent_channel 表**:
|
||
|
||
`name`(唯一) | `type`(weixin/weixin-db) | `agentId` | `agentName` | `config`(JSON) | `credential`(JSON,加密) | `runtime`(JSON: syncBuf/contextTokens/seenMessageIds) | `loginStatus`(pending/disconnected/connected/error/unsupported_platform) | `lastError` | `lastConnectedAt`
|
||
|
||
**netaclaw_agent_channel_group 表**:
|
||
|
||
`channelId` | `roomId`(channel 内唯一) | `roomName` | `status`(0禁用/1启用/-1忽略) | `triggerMode`(at_mention/all) | `boundAgentId` | `replyIdentityOverride` | `firstSeenAt` | `lastSeenAt` | `lastActiveAt`
|
||
|
||
## 关键文件
|
||
|
||
| 文件 | 职责 |
|
||
|------|------|
|
||
| `entity/agent_channel.ts` | 渠道 Entity |
|
||
| `service/agent_channel.ts` | 渠道 CRUD + QR 登录 + 后台运行器 |
|
||
| `service/weixin.ts` | 微信协议层(QR 登录、消息收发) |
|
||
| `service/weixin_db.ts` | 本机 PC 微信数据库增量读取、WAL watcher、群白名单缓存 |
|
||
| `service/weixin_archive_sync.ts` | 按 channel 工作目录同步历史归档 |
|
||
| `runtime/weixin_db/*` | key 抽取、WCDB 解密、增量读取、room 解析、消息伪协议构建 |
|
||
| `entity/agent_channel_group.ts` | 群白名单、触发策略和每群 Agent 覆盖 |
|
||
| `service/agent_executor.ts` | Agent 执行器(渠道消息触发 Agent 推理) |
|
||
| `controller/admin/agent_channel.ts` | REST API |
|
||
| `controller/admin/agent_channel_group.ts` | 群管理 API |
|
||
|
||
## 微信接入模式
|
||
|
||
| 类型 | 场景 | 消息来源 | 回复路径 |
|
||
| --- | --- | --- | --- |
|
||
| `weixin` | ClawBot 个人助手,当前主打私聊 | iLink/ClawBot API 轮询 | `weixinService.sendText()` 直接发送 |
|
||
| `weixin-db` | 本机 PC 微信群聊代理 | 本地数据库解密 + WAL watcher | v4 双 Agent:reply agent 委托 desktop agent 调 [[desktop-op-module]] 发送 |
|
||
|
||
## ClawBot 私聊流程
|
||
|
||
```
|
||
创建渠道 → 绑定 Agent
|
||
→ createWeixinQr() 生成二维码
|
||
→ 用户扫码 → pollWeixinQr() 轮询状态
|
||
→ 状态流转:wait → scaned_but_redirect → confirmed
|
||
→ 获取 credential(accountId, token, baseUrl, userId)
|
||
→ syncRunner() 启动后台消息轮询(800ms 间隔)
|
||
```
|
||
|
||
`routeInboundMessage()` 会丢弃 ClawBot 收到的群消息,避免旧 iLink 路径和新的群聊本地代理互相串线。
|
||
|
||
## weixin-db 群聊流程
|
||
|
||
```
|
||
创建 weixin-db 渠道,填写 wxid
|
||
→ syncRunner() 对启用渠道调用 WeixinDbService.bindChannel()
|
||
→ 自动定位 xwechat_files seedDir
|
||
→ extractWeixinKeys() 抽取 message/session/contact DB key
|
||
→ IncrementalReader 初始化 per-channel workDir
|
||
→ WalWatcher 监听 message DB WAL
|
||
→ readIncrement() 增量解密消息
|
||
→ room_resolver + 群白名单过滤
|
||
→ buildPseudoMessageFromDb() 构造伪消息
|
||
→ routeInboundMessage()
|
||
```
|
||
|
||
非 Windows 平台会把状态标记为 `unsupported_platform`,服务保持 idle,不让启动流程崩溃。
|
||
|
||
## 群白名单与触发
|
||
|
||
`netaclaw_agent_channel_group` 管理每个 channel 下的群:
|
||
|
||
- `status=1` 的群才进入 weixin-db 增量读取白名单。
|
||
- `triggerMode` 当前支持 `at_mention` 和 `all`,`prefix` 仅兼容存量数据。
|
||
- `boundAgentId` 是 weixin-db 群聊的必填 reply agent;不再回退 channel 默认 Agent。
|
||
- `replyIdentityOverride` 是 weixin-db 群聊的必填回复身份;不再回退 channel 级回复身份。
|
||
- 群增删启停后会调用 `WeixinDbService.refreshWhitelist()`,让下一次 WAL tick 使用最新白名单。
|
||
|
||
## 消息处理循环
|
||
|
||
```
|
||
runLoop() 或 WalWatcher 收到消息
|
||
→ decideChatScope() 区分 DM / group
|
||
→ seenMessageIds 5 分钟去重
|
||
→ context_token 按 chatId 保存
|
||
→ pendingClarify / 风险确认短路
|
||
→ senderQueues 按 DM sender 或群 chatId 串行
|
||
→ handleInboundMessage()
|
||
```
|
||
|
||
群聊路径会先检查群记录、触发策略和每群 Agent 覆盖,再调用 `agentExecutor.execute()`。weixin-db v4 不再由 `agent_channel` 自动发送最终内容;reply agent 必须通过 `delegate_task` 委托 desktop agent,否则服务会记录“未调用 delegate_task”的告警,避免消息静默丢失。
|
||
|
||
## 生命周期管理
|
||
|
||
- `restoreConnectedRunners()`:启动时恢复已连接渠道的运行器
|
||
- `disconnect()`:断开 ClawBot 连接,停止轮询
|
||
- `restart()`:重启运行器
|
||
- `clearSessions()`:清空渠道的所有会话
|
||
- `delete()`:删除群记录、解绑 weixin-db、删除 channel archive,并通过 [[desktop-op-module]] 取消该 channel 的 pending/running 桌面任务
|
||
- weixin-db 健康探针每 60 秒检查 PC 微信进程和数据库可读性,失败后尝试 unbind/rebind
|
||
|
||
## v4 双 Agent 自动回复
|
||
|
||
weixin-db 的 `config.weixinReply` 启用后,渠道保存会做额外校验:
|
||
|
||
- 必须配置 `desktopAgentId`,且不能与 reply agent 相同。
|
||
- 后端会自动给 desktop agent 加入 `weixin_desktop` toolset。
|
||
- 后端会把 `weixin_send_text` 设置为 `allowInSubagent=true` 且 `force-main-process-proxy`。
|
||
- `weixinReply.enabled` 从 true 改为 false 时,会级联取消该 channel 下的桌面操作任务。
|
||
|
||
最终链路是:群消息进入 reply agent,reply agent 用 `delegate_task` 把发送动作委托给 desktop agent,desktop agent 调用 [[tool-system]] 的 `weixin_send_text`,再由 [[desktop-op-module]] 操作 PC 微信窗口。
|
||
|
||
## Clarify 纯文本降级
|
||
|
||
微信渠道不支持 WebSocket 交互,[[clarify-tool]] 采用纯文本 + 数字映射方案:
|
||
|
||
1. 构造文本消息:`❓ 问题\n1. 选项1\n2. 选项2\n请回复数字或直接输入`
|
||
2. 通过微信 API 发送,存入 `pendingClarify` Map(key: `${channelId}:${senderId}`)
|
||
3. 用户回复数字 → 映射到 `choices[num-1]`;回复文本 → 直接使用
|
||
4. 解决 Promise,Agent 继续执行
|
||
|
||
## 相关页面
|
||
|
||
- [[netaclaw-module]] — 所属模块
|
||
- [[agent-runtime]] — Agent 执行器
|
||
- [[clarify-tool]] — Clarify 澄清工具(微信降级实现)
|
||
- [[desktop-op-module]] — weixin-db 自动回复的桌面发送执行后端
|
||
- [[tool-system]] — `weixin_send_text` 和 `delegate_task` 工具链路
|
||
- [[websocket-gateway]] — 前端管理页面通过 HTTP API 操作
|