← Back to Plugins
Tools

OpenclawFace

Wenzhao299 By Wenzhao299 👁 10 views ▲ 0 votes

An openclaw status emoji plugin.

GitHub

Configuration Example

{
  "plugins": {
    "load": {
      "paths": [
        "~/.openclaw/workspace/plugin/OpenclawFace"
      ]
    },
    "entries": {
      "OpenclawFace": {
        "enabled": true,
        "config": {
          "bind": "0.0.0.0",
          "port": 8787,
          "path": "/ws",
          "token": "replace-with-your-token",
          "ui": {
            "enabled": true,
            "path": "/face",
            "defaultToUi": true
          },
          "weather": {
            "enabled": true,
            "city": "Shanghai",
            "pollMs": 900000
          },
          "nomi": {
            "autoTouchReact": true
          }
        }
      }
    }
  }
}

README

# OpenclawFace

语言 / Language: [中文](./README.md) | [English](./README_en.md)

OpenclawFace 是一个一体化 OpenClaw 插件,提供:

1. 双向 WebSocket 事件桥(`/ws`)
2. 根据 OpenClaw 状态实时展示表情 UI(`/face`)
3. NOMI 风格表达事件(`action_play` / `thought`)
4. 天气输入(优先 `weather.city`,备选 `lat/lon`)

## 功能特性

1. 获取 OpenClaw 实时状态。
2. 角色根据 OpenClaw 运行事件(message/llm/tool 等)自动切换状态。
3. 支持外部手动触发表情,便于调试和验收。

## 环境要求

1. OpenClaw Gateway
2. Node.js 18+ 与 npm

## 安装步骤

1. 克隆仓库:

```bash
cd ~/.openclaw/workspace/plugin
git clone https://github.com/Wenzhao299/OpenclawFace.git
```

2. 安装依赖:

```bash
cd ~/.openclaw/workspace/plugin/OpenclawFace
npm i
```

3. 将插件配置写入 `~/.openclaw/openclaw.json`(见下方最小配置)。

4. 重启 OpenClaw Gateway。

## openclaw.json 最小配置

将以下片段合并到 `~/.openclaw/openclaw.json`:

```json
{
  "plugins": {
    "load": {
      "paths": [
        "~/.openclaw/workspace/plugin/OpenclawFace"
      ]
    },
    "entries": {
      "OpenclawFace": {
        "enabled": true,
        "config": {
          "bind": "0.0.0.0",
          "port": 8787,
          "path": "/ws",
          "token": "replace-with-your-token",
          "ui": {
            "enabled": true,
            "path": "/face",
            "defaultToUi": true
          },
          "weather": {
            "enabled": true,
            "city": "Shanghai",
            "pollMs": 900000
          },
          "nomi": {
            "autoTouchReact": true
          }
        }
      }
    }
  }
}
```

说明:

1. `weather.city` 优先于 `weather.lat/lon`。
2. 城市解析失败时会发出 `weather_error`,并回退到经纬度。

## 使用方式

1. 打开 UI:
`http://<host>:8787/face/`

2. 如果启用了 `token`:
`http://<host>:8787/face/?token=<token>`

3. WS 连接地址:
`ws://<host>:8787/ws?token=<token>`

## 协议结构

消息通用结构:

```json
{
  "v": 1,
  "type": "ui",
  "name": "action_play",
  "ts": 1700000000000,
  "data": {}
}
```

字段含义:

1. `v`: 协议版本
2. `type`: 事件分组(`gateway/session/message/agent/llm/tool/log/ui/expression`)
3. `name`: 事件名
4. `ts`: 时间戳(毫秒)
5. `ctx`: 过滤后的上下文(可选)
6. `data`: 事件数据

## WS 事件(Server -> Client)

始终会发出的事件:

1. `client_connected`
2. `client_disconnected`
3. `client_error`
4. `weather_update`
5. `weather_error`
6. `ui_interaction`
7. `action_play`
8. `thought`

受 `events.allow` 控制的 OpenClaw Hook 事件:

1. `message_received`, `message_sending`, `message_sent`
2. `llm_input`, `llm_output`
3. `before_tool_call`, `after_tool_call`
4. `before_agent_start`, `agent_end`, `subagent_spawning`, `subagent_spawned`, `subagent_ended`
5. `session_start`, `session_end`, `gateway_start`, `gateway_stop`

## 客户端可发送事件(Client -> Server)

1. `ui_interaction`
2. `action_play`
3. `thought`

## 手动测试不同状态

### A. 浏览器控制台快速测试

打开 `http://<host>:8787/face/?token=<token>`,执行:

```js
const ws = new WebSocket(`ws://${location.host}/ws?token=<token>`);
const send = (name, data) => ws.send(JSON.stringify({ v: 1, type: 'ui', name, ts: Date.now(), data }));
```

然后依次测试动作:

```js
send('action_play', { action: 'tap_ack', durationMs: 1400, intensity: 0.9 }); // listening
send('action_play', { action: 'tool_focus', durationMs: 1400, intensity: 0.8 }); // tool
send('action_play', { action: 'speak', durationMs: 1200, intensity: 0.9 }); // speaking
send('action_play', { action: 'happy', durationMs: 1600, intensity: 0.9 });
send('action_play', { action: 'angry', durationMs: 1600, intensity: 0.9 });
send('action_play', { action: 'sad', durationMs: 1800, intensity: 0.9 });
send('action_play', { action: 'sleep', durationMs: 2200, intensity: 0.9 });
send('thought', { text: 'Manual thought test', mood: 'thinking', ttlMs: 5000 });
```

### B. 通过 OpenClaw 运行事件触发

1. `listening`: `message_received` 或 pointer down/tap
2. `thinking`: `llm_input`
3. `tool`: `before_tool_call`
4. `speaking`: `message_sent`
5. `error`: `client_error` 或 `weather_error`
6. `idle`: 默认状态或临时状态超时后恢复

### C. 天气输入测试

1. 在插件配置中设置 `"weather.city"`。
2. 重启插件。
3. 在 WS 数据流中确认 `weather_update` 负载。

## 故障排查

1. UI 显示不是最新:
打开 `http://<host>:8787/face/` 后 `Ctrl+F5` 强刷,并检查启动日志是否打印:
`[openclaw-face] ui directory: .../OpenclawFace/ui`

2. 插件未加载:
确认 `plugins.entries` 的键名是 `OpenclawFace`(必须与 manifest 的 `id` 完全一致)。

3. WS 无法连接:
检查 `bind/port/path/token` 与网络防火墙配置。

## 安全建议

1. 局域网暴露时建议启用 `token`。
2. `includeMessageContent` 与 `includeToolParams` 默认关闭,建议保持默认。

## License

见 [LICENSE](./LICENSE)。
tools

Comments

Sign in to leave a comment

Loading comments...