2026-05-20 21:39:12 +08:00

137 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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 双 Agentreply agent 委托 desktop agent 调 [[desktop-op-module]] 发送 |
## ClawBot 私聊流程
```
创建渠道 → 绑定 Agent
→ createWeixinQr() 生成二维码
→ 用户扫码 → pollWeixinQr() 轮询状态
→ 状态流转wait → scaned_but_redirect → confirmed
→ 获取 credentialaccountId, 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 agentreply agent 用 `delegate_task` 把发送动作委托给 desktop agentdesktop agent 调用 [[tool-system]] 的 `weixin_send_text`,再由 [[desktop-op-module]] 操作 PC 微信窗口。
## Clarify 纯文本降级
微信渠道不支持 WebSocket 交互,[[clarify-tool]] 采用纯文本 + 数字映射方案:
1. 构造文本消息:`❓ 问题\n1. 选项1\n2. 选项2\n请回复数字或直接输入`
2. 通过微信 API 发送,存入 `pendingClarify` Mapkey: `${channelId}:${senderId}`
3. 用户回复数字 → 映射到 `choices[num-1]`;回复文本 → 直接使用
4. 解决 PromiseAgent 继续执行
## 相关页面
- [[netaclaw-module]] — 所属模块
- [[agent-runtime]] — Agent 执行器
- [[clarify-tool]] — Clarify 澄清工具(微信降级实现)
- [[desktop-op-module]] — weixin-db 自动回复的桌面发送执行后端
- [[tool-system]] — `weixin_send_text``delegate_task` 工具链路
- [[websocket-gateway]] — 前端管理页面通过 HTTP API 操作