← Back to Plugins
Tools

Wechat Extension

azhumide By azhumide ⭐ 2 stars 👁 41 views ▲ 0 votes

OpenClaw plugin from azhumide/openclaw-wechat-extension

GitHub

Configuration Example

[openclaw]
ws_mode = "server"
ws_host = "0.0.0.0"
ws_port = 9093
ws_path = "/ws"

README

# WeChat 扩展说明

这个扩展用于把 OpenClaw 的 `wechat` 通道接到 `aibot/plugins/OpenClawBridge`,实现微信消息和 OpenClaw 之间的双向桥接。

当前推荐架构是:

- `OpenClawBridge` 做 WebSocket 服务端
- 本扩展做 WebSocket 客户端
- 默认只用一个端口 `9093`

## 当前能力

- 微信入站消息转 OpenClaw 会话
- OpenClaw 文本 / 图片 / 文件 / 视频回发微信
- 单端口 WebSocket 客户端桥接
- 更详细的入站 / 出站 / 连接状态日志
- 基于微信发送者的敏感工具权限控制
- 主人 / 白名单 / 分工具白名单
- 普通用户 skill 黑名单
- 已安装 skill 的 `exec` / `process` 自动放行识别

## 工作链路

整体链路可以简单理解成:

1. 微信消息先进入 `aibot`
2. `aibot/plugins/OpenClawBridge` 作为 WebSocket 服务端接收本扩展连接
3. 本扩展把消息投递成 OpenClaw 的 `wechat` 会话
4. OpenClaw 产出的回复再通过 WebSocket 回给 `OpenClawBridge`
5. 媒体优先直接走本地绝对路径、工作区相对路径或可访问 URL,不再依赖第二个媒体端口

## 目录说明

- `index.ts`
  扩展主入口,负责插件注册、启动/停止编排和各子模块挂接
- `src/bridge-runtime.ts` / `src/bridge-autostart.ts`
  Bridge WebSocket 连接、心跳、重连和自动启动相关逻辑
- `src/inbound-handler.ts` / `src/inbound-context.ts`
  微信入站消息解析、会话上下文和 OpenClaw 投递
- `src/channel.ts`
  `wechat` channel 的插件定义、会话路由和 action/outbound 挂接
- `src/outbound-send.ts`
  文本 / 媒体出站发送,包含本地媒体路径解析、暂存、去重和 Bridge 帧发送
- `src/reply-delivery.ts`
  模型回复分段、最终回复缓冲、媒体候选提取和回发编排
- `src/message-tool.ts`
  `message` 工具参数规范化和 WeChat 目标解析
- `src/tool-auth-*.ts` / `src/installed-skill-*.ts`
  微信发送者敏感工具权限、已安装 skill 自动放行和只读 exec 白名单识别
- `src/canonicalization*.ts`
  WeChat 通道名、会话路由、subagent delivery origin 的兼容规范化
- `src/config.ts`
  本地配置读取、默认值处理、媒体根目录解析
- `src/runtime.ts`
  Bridge 运行时状态、工具权限上下文、skill 进程会话映射
- `wechat.config.json`
  当前实际使用的本地配置
- `wechat.config.example.jsonc`
  带中文注释的配置模板

## 快速开始

### 1. 配置扩展

先准备:

- `.openclaw/extensions/wechat/wechat.config.json`

至少确认这几个字段:

- `wsHost`
- `wsPort`
- `wsPath`
- `workspaceBase`

### 2. 配置 OpenClawBridge

在 `aibot/plugins/OpenClawBridge/config.toml` 里,至少保证下面这些项和扩展一致:

```toml
[openclaw]
ws_mode = "server"
ws_host = "0.0.0.0"
ws_port = 9093
ws_path = "/ws"
```

这里的主机、端口、路径必须和:

- `wsHost`
- `wsPort`
- `wsPath`

保持一致。

### 3. 启动后先看日志

先确认有没有这几类日志:

- 入站日志:`[WeChat Inbound] ...`
- 出站日志:`[WeChat Outbound] ...`
- 连接日志:`Bridge WS client connected` 或 `Connected to OpenClawBridge server`
  也可能显示为:`Bridge WS connected: ws://...`

## 配置读取优先级

当前扩展配置优先级是:

1. OpenClaw 主配置里的 `channels.wechat`
2. `.openclaw/extensions/wechat/wechat.config.json`
3. 代码默认值

## 配置项说明

### Bridge 基础配置

#### `wsHost`

OpenClaw 要连接的 `OpenClawBridge` 服务端地址。

- 同机部署通常用 `127.0.0.1`
- 跨机部署填写 aibot 所在机器 IP

#### `wsPort`

`OpenClawBridge` 服务端端口,默认 `9093`。

#### `wsPath`

`OpenClawBridge` WebSocket 路径,默认 `/ws`。

### 媒体与路径配置

#### `bridgeDownloadHost`

兼容旧模式保留字段。当前主链路通常保持和 `wsHost` 一致即可。

#### `bridgeDownloadBaseUrl`

兼容旧模式保留字段。当前单端口直连模式下通常留空即可。

只有在你明确需要把某些媒体改写成公共下载地址时,它才有意义。

#### `workspaceBase`

OpenClaw 工作目录根路径。

主要用于:

- 对相对路径补全真实路径
- 作为媒体查找根目录
- 让本扩展把工具产出的本地文件解析成可回传路径

Linux 示例:

```json
{
  "workspaceBase": "/home/rs/.openclaw/workspace"
}
```

Windows 示例:

```json
{
  "workspaceBase": "C:/Users/你的用户名/.openclaw/workspace"
}
```

#### `tmpDir`

可选临时目录。留空时会回退到:

```text
workspaceBase/downloads
```

#### `mediaSearchPaths`

附加媒体搜索目录数组。

当工具返回相对路径,或目标文件不在 `workspaceBase` 下时,扩展会继续在这些目录查找。

## 出站消息行为

### 文本回复

会输出类似日志:

```text
[WeChat Outbound] to=xxx account=default type=text text="..."
```

### 媒体回复

会输出类似日志:

```text
[WeChat Outbound] to=xxx account=default type=media media="..."
```

如果传入的是本地路径,扩展会优先:

1. 解析成绝对路径
2. 在 `workspaceBase` / `tmpDir` / `mediaSearchPaths` 范围内补全和查找
3. 尽量直接把本地路径通过桥接帧交给 `OpenClawBridge`

只有在特定兼容场景下,才会退回成 URL。

## 主人 / 白名单 / 审批

### 主人身份怎么判断

这个扩展本身不直接维护主人 wxid。

当前逻辑是:

- 微信入站时,`OpenClawBridge` 负责把 `isMaster` 传过来
- 本扩展只消费这个 `isMaster` 标记

### `nonOwnerToolAuthMode`

非主人调用敏感工具时的总策略。

- `off`
- `deny`
- `approve`

### `nonOwnerToolAuthTools`

需要受上面策略保护的工具名。

建议至少先保护:

```json
["exec", "process"]
```

### `toolAuthBypassWxids`

全局白名单。支持:

- 发送者 wxid
- 私聊场景下 `OpenClawBridge` 传过来的 alias

### `toolAuthBypassByTool`

按工具单独配置白名单。

### `toolAuthAllowInstalledSkills`

是否允许“已安装 skill”触发的敏感工具自动放行。

### `toolAuthAllowMcporterExec`

是否允许非主人执行 `mcporter` MCP CLI 命令。

开启后会放行 `mcporter ...` 和常见的 `npx mcporter ...` 形式,包括 `list` / `call` / `auth` / `config` / `daemon` 等子命令。

仍会拒绝夹带 shell 拼接的命令,例如 `;`、`|`、重定向、命令替换、环境变量展开等。

### `toolAuthBlockedSkills`

skill 黑名单。

### `toolAuthAllowSafeReadonlyExec`

是否允许非主人执行极少数只读低风险 `exec` 命令。

当前只识别固定安全形态,例如:

- `date`
- `pwd`
- `whoami`
- `hostname`
- `uname`
- `id`
- `arch`
- 针对受控目录的 `ls` / `stat` / `readlink`
- 安全只读查询后接一个简单 `head` 截断,例如 `ls -lt <受控目录> | head -n 5`

除上述 `head` 截断特例外,带管道、重定向、命令替换、`;`、`&&`、`||` 等 shell 组合的命令不会放行。

远端媒体下载另有一个收窄的安全下载 bypass:只允许 `wget -O <workspace 路径> <http(s) URL>` 或 `curl -L -o <workspace 路径> <http(s) URL>` 这类输出路径落在 workspace 内的命令。

### `toolAuthDebugInstalledSkills`

是否输出“已安装 skill 自动放行”的调试日志。

排查某条 `exec` / `process` 为什么没有被识别为 skill 调用时,可以临时打开。

### 工具权限通知文案

这些开关控制非主人触发敏感工具时,是否向微信回发提示:

- `toolAuthNotifyBlocked`
- `toolAuthNotifyApprovalQueued`
- `toolAuthNotifyApprovalResolved`
- `toolAuthNotifyInGroup`
- `toolAuthNotifyInDirect`

这些字段可以覆盖默认提示模板:

- `toolAuthMessageBlocked`
- `toolAuthMessageQueued`
- `toolAuthMessageAllowOnce`
- `toolAuthMessageAllowAlways`
- `toolAuthMessageDeny`
- `toolAuthMessageTimeout`
- `toolAuthMessageCancelled`

模板支持占位符:

```text
{{toolName}} {{state}} {{stateLabel}} {{senderId}} {{senderName}} {{skillId}}
{{from}} {{chatType}} {{chatTypeLabel}} {{conversationLabel}} {{question}}
```

## 推荐配置示例

### 同机部署

```json
{
  "wsHost": "127.0.0.1",
  "wsPort": 9093,
  "wsPath": "/ws",
  "bridgeDownloadHost": "127.0.0.1",
  "bridgeDownloadBaseUrl": "",
  "workspaceBase": "/home/rs/.openclaw/workspace",
  "tmpDir": "",
  "mediaSearchPaths": [],
  "nonOwnerToolAuthMode": "deny",
  "nonOwnerToolAuthTools": ["exec", "process"],
  "toolAuthAllowInstalledSkills": false,
  "toolAuthAllowSafeReadonlyExec": false
}
```

### 局域网分机部署

```json
{
  "wsHost": "10.10.10.80",
  "wsPort": 9093,
  "wsPath": "/ws",
  "bridgeDownloadHost": "10.10.10.80",
  "bridgeDownloadBaseUrl": "",
  "workspaceBase": "/home/rs/.openclaw/workspace",
  "tmpDir": "/home/rs/.openclaw/workspace/downloads",
  "mediaSearchPaths": [],
  "nonOwnerToolAuthMode": "approve",
  "nonOwnerToolAuthTools": ["exec", "process"],
  "toolAuthAllowInstalledSkills": false,
  "toolAuthAllowSafeReadonlyExec": false
}
```

## 常见问题

### 1. 连不上 OpenClawBridge

优先检查:

- `wsHost` / `wsPort` / `wsPath` 是否和 `OpenClawBridge` 一致
- OpenClawBridge 是否已经监听 `9093`
- 网络或防火墙是否拦截

### 2. 提示本地文件不存在

优先检查:

- `workspaceBase` 是否正确
- 返回的是绝对路径还是相对路径
- 文件是否真的存在于 OpenClaw 所在机器
- 是否需要把目录补到 `mediaSearchPaths`

### 3. aibot 收到文本,收不到媒体

优先检查:

- OpenClaw 侧回调里给的是本地路径、相对路径还是 URL
- 该路径是否能在 `workspaceBase` 或 `mediaSearchPaths` 中命中
- 是否只有兼容回退场景才需要 `bridgeDownloadBaseUrl`

### 4. 修改配置后没有生效

修改 `wechat.config.json` 后,需要重启扩展或重启整个 OpenClaw 进程。

### 5. 群里没显示昵称 / 群名不对

先看入站日志里有没有:

- `conversation="..."`
- `senderName="..."`

如果日志里已经没有这些字段,说明是 `OpenClawBridge` 上游就没传够,不是这个扩展中途丢掉了。

## 权限建议

运行 OpenClaw 的用户,至少要对这些目录有读取权限:

- `workspaceBase`
- `workspaceBase/downloads`
- `mediaSearchPaths` 里的目录
- `tmpDir` 指向的目录

原因主要是:

- 读取工具产出的文件
- 解析和中转本地媒体

## 使用建议

- 不确定时,先从 `wechat.config.example.jsonc` 复制一份再改
- 同机部署优先用 `127.0.0.1`
- 跨机部署先验证 OpenClaw 到 aibot 的 `9093` 可达
- `workspaceBase` 尽量显式填写,不要完全依赖自动推断
- 如果你在做权限控制,先开 `deny` 跑通,再考虑升级到 `approve`
tools

Comments

Sign in to leave a comment

Loading comments...