@xmoxmo/bncr 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,350 +1,80 @@
1
- # bncr-channel
1
+ # bncr
2
2
 
3
- OpenClaw 的 Bncr WebSocket Bridge 频道插件(`channelId=bncr`)。
3
+ OpenClaw 的 Bncr 频道插件(`channelId=bncr`)。
4
4
 
5
- 这份文档按“拿到插件就能对接”的目标编写:你只看本 README,也能完成接入。
5
+ 作用很简单:把 **Bncr / 无界客户端** 接到 **OpenClaw 网关**,用于消息双向通信与媒体/文件传输。
6
6
 
7
7
  ---
8
8
 
9
- ## 1. 概览
9
+ ## 安装
10
10
 
11
- - **OpenClaw Channel ID**:`bncr`
12
- - **Bridge Version**:`2`
13
- - **出站事件名**:`bncr.push`
14
- - **出站模式**:`push-only`(不依赖 pull 轮询)
15
- - **活动心跳方法**:`bncr.activity`
11
+ ### OpenClaw
16
12
 
17
- ---
18
-
19
- ## 2. 工作模式(重点)
20
-
21
- 当前是 **push-only**:
22
-
23
- - Bncr 在线:OpenClaw 通过 WS `event=bncr.push` 直接下发回复。
24
- - Bncr 离线:消息进入 outbox;重连后自动冲队列。
25
- - `bncr.activity` 仅用于在线保活,不承载拉取。
26
- - `bncr.ack` 兼容保留,当前不是必需链路(fire-and-forget)。
27
-
28
- > 结论:客户端最小实现只需两件事:
29
- > 1) 发 `bncr.inbound`;2) 监听 `bncr.push`。
13
+ 在 OpenClaw 上执行:
30
14
 
31
- ---
32
-
33
- ## 3. SessionKey 规则(严格)
34
-
35
- 严格格式:
36
-
37
- ```text
38
- agent:main:bncr:direct:<hexScope>
15
+ ```bash
16
+ openclaw plugins install @xmoxmo/bncr
17
+ openclaw plugins enable bncr
18
+ openclaw gateway restart
39
19
  ```
40
20
 
41
- 其中:
42
-
43
- - `<hexScope>` = `platform:groupId:userId` 的 UTF-8 hex(小写)。
44
- - 仅允许 `0-9a-f` 且长度为偶数。
45
- - 旧格式(如 `...:<hexScope>:0`)不再作为标准形态。
21
+ ### Bncr / 无界侧
46
22
 
47
- 示例:
23
+ 安装:
48
24
 
49
- ```text
50
- scope = qq:0:888888
51
- hexScope = 71713a303a383838383838
52
- sessionKey= agent:main:bncr:direct:71713a303a383838383838
53
- ```
54
-
55
- ---
25
+ - `openclawclient.js`
56
26
 
57
- ## 4. Gateway Methods
27
+ 然后完成客户端配置,至少包括:
58
28
 
59
- 插件注册:
29
+ - OpenClaw 地址
30
+ - 端口
31
+ - Token
32
+ - 连接相关参数
60
33
 
61
- - `bncr.connect`
62
- - `bncr.inbound`
63
- - `bncr.activity`
64
- - `bncr.ack`
34
+ 配置完成后,让客户端成功连到 OpenClaw 网关即可。
65
35
 
66
36
  ---
67
37
 
68
- ## 5. 接入流程(最小可用)
69
-
70
- ### Step A:建立 WS 并发送 `bncr.connect`
71
-
72
- 请求示例:
38
+ ## 支持能力
73
39
 
74
- ```json
75
- {
76
- "type": "req",
77
- "id": "c1",
78
- "method": "bncr.connect",
79
- "params": {
80
- "accountId": "Primary",
81
- "clientId": "bncr-client-1"
82
- }
83
- }
84
- ```
85
-
86
- 响应示例:
40
+ ### 支持内容
87
41
 
88
- ```json
89
- {
90
- "type": "res",
91
- "id": "c1",
92
- "ok": true,
93
- "result": {
94
- "channel": "bncr",
95
- "accountId": "Primary",
96
- "bridgeVersion": 2,
97
- "pushEvent": "bncr.push",
98
- "online": true,
99
- "isPrimary": true,
100
- "activeConnections": 1,
101
- "pending": 0,
102
- "deadLetter": 0,
103
- "now": 1772476800000
104
- }
105
- }
106
- ```
42
+ - 文本
43
+ - 图片
44
+ - 视频
45
+ - 语音
46
+ - 音频
47
+ - 文件
107
48
 
108
- > `accountId` 示例是 `Primary`,请按你实际配置替换;不传默认使用 `Primary`。
49
+ ### 其它特性
109
50
 
110
- ### Step B:上行消息用 `bncr.inbound`
111
-
112
- 文本请求示例(`msg` 形态):
113
-
114
- ```json
115
- {
116
- "type": "req",
117
- "id": "i1",
118
- "method": "bncr.inbound",
119
- "params": {
120
- "accountId": "Primary",
121
- "platform": "qq",
122
- "groupId": "0",
123
- "userId": "888888",
124
- "sessionKey": "agent:main:bncr:direct:71713a303a383838383838",
125
- "msgId": "msg-1001",
126
- "type": "text",
127
- "msg": "你好"
128
- }
129
- }
130
- ```
131
-
132
- 媒体请求示例(字段是 `base64`):
133
-
134
- ```json
135
- {
136
- "type": "req",
137
- "id": "i2",
138
- "method": "bncr.inbound",
139
- "params": {
140
- "accountId": "Primary",
141
- "platform": "qq",
142
- "groupId": "0",
143
- "userId": "888888",
144
- "sessionKey": "agent:main:bncr:direct:71713a303a383838383838",
145
- "msgId": "msg-1002",
146
- "type": "image/png",
147
- "msg": "",
148
- "base64": "<BASE64_PAYLOAD>",
149
- "mimeType": "image/png",
150
- "fileName": "demo.png"
151
- }
152
- }
153
- ```
154
-
155
- 响应示例:
156
-
157
- ```json
158
- {
159
- "type": "res",
160
- "id": "i1",
161
- "ok": true,
162
- "result": {
163
- "accepted": true,
164
- "accountId": "Primary",
165
- "sessionKey": "agent:main:bncr:direct:71713a303a383838383838",
166
- "msgId": "msg-1001",
167
- "taskKey": null
168
- }
169
- }
170
- ```
171
-
172
- > `bncr.inbound` 先快速 ACK,再异步处理,最终回复经 `bncr.push` 回推。
173
-
174
- ### Step C:消费 `bncr.push`
175
-
176
- 事件示例:
177
-
178
- ```json
179
- {
180
- "type": "event",
181
- "event": "bncr.push",
182
- "payload": {
183
- "type": "message.outbound",
184
- "messageId": "3f8b1f9b-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
185
- "idempotencyKey": "3f8b1f9b-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
186
- "sessionKey": "agent:main:bncr:direct:71713a303a383838383838",
187
- "message": {
188
- "platform": "qq",
189
- "groupId": "0",
190
- "userId": "888888",
191
- "type": "text",
192
- "msg": "收到,已处理。",
193
- "path": "",
194
- "base64": "",
195
- "fileName": ""
196
- },
197
- "ts": 1772476801234
198
- }
199
- }
200
- ```
51
+ - 下行推送
52
+ - 离线消息自动排队
53
+ - 重连后继续发送
54
+ - 支持诊断信息
55
+ - 支持文件互传
201
56
 
202
57
  ---
203
58
 
204
- ## 6. 字段协议
205
-
206
- ### 6.1 Bncr -> OpenClaw(`bncr.inbound`)
207
-
208
- 常用字段:
209
-
210
- - `accountId`:可选(默认 `Primary`)
211
- - `platform`:必填
212
- - `groupId`:可选,默认 `"0"`(私聊)
213
- - `userId`:建议填写(私聊/群聊都建议带上)
214
- - `sessionKey`:可选,建议传严格 sessionKey(见第 3 节)
215
- - `msgId`:建议传(便于短窗口去重)
216
- - `type`:`text/image/video/file/...`
217
- - `msg`:文本
218
- - `base64`:媒体 base64
219
- - `mimeType` / `fileName`:媒体元数据(可选)
220
-
221
- 校验失败常见错误:
222
-
223
- - `platform/groupId/userId required`
224
-
225
- #### 6.1.1 openclawclient.js(发送端)对齐说明
226
-
227
- 基于你当前附件版本(`openclawclient` 注释版本 `0.0.2`)核对结果:
59
+ ## 安装后如何确认成功
228
60
 
229
- - `inboundSend()` 使用 `sessionKey`,与当前插件入站字段一致。
230
- - 文本消息使用 `msg`,与当前插件读取一致。
231
- - 媒体字段使用 `base64`(可带 `mimeType/fileName`),与当前插件读取一致。
232
- - 默认账号建议使用 `Primary`,并与网关账户 ID 保持大小写一致。
61
+ 可以通过以下方式检查:
233
62
 
234
- ### 6.2 OpenClaw -> Bncr(`bncr.push`)
235
-
236
- 关键字段:
237
-
238
- - `messageId`
239
- - `idempotencyKey`(当前等于 `messageId`)
240
- - `sessionKey`
241
- - `message.platform/groupId/userId`
242
- - `message.type/msg/path/base64/fileName`
243
- - `ts`
244
-
245
- 说明:
246
-
247
- - 主类型固定为 `type="message.outbound"`。
248
- - 仅输出嵌套结构 `message.{...}`,不再输出平铺兼容字段。
249
- - 不附带 webchat 的 `stream/state/data` 语义字段。
250
-
251
- ---
252
-
253
- ## 7. `message.send(channel=bncr)` 目标解析规则(重要)
254
-
255
- 插件发送目标支持三种输入:
256
-
257
- 1. 严格 `sessionKey`
258
- 2. `platform:groupId:userId`
259
- 3. `Bncr-platform:groupId:userId`
260
-
261
- 但发送前会做**反查校验**:
262
-
263
- - 必须在已知会话路由里反查到真实 `sessionKey` 才会发送。
264
- - 禁止拼凑 key 直接发;查不到会报:`target not found in known sessions`。
265
-
266
- ---
267
-
268
- ## 8. 重试与可靠性
269
-
270
- - 离线入队 + 重连自动冲队列。
271
- - 指数退避:`1s,2s,4s,8s...`
272
- - 最大重试次数:`10`
273
- - 超限进入 dead-letter。
274
-
275
- ---
276
-
277
- ## 9. 状态判定与观测
278
-
279
- - 实际链路在线:`linked`
280
- - 已配置但离线:`configured`
281
- - 账户卡片中离线模式会显示 `Status`(展示口径)
282
-
283
- 常用状态字段:
284
-
285
- - `pending`
286
- - `deadLetter`
287
- - `lastSessionKey`
288
- - `lastSessionScope`(`Bncr-platform:group:user`)
289
- - `lastSessionAt`
290
- - `lastActivityAt`
291
- - `lastInboundAt`
292
- - `lastOutboundAt`
293
-
294
- > 已知现象:`openclaw status` 顶层与 `status --deep` 在个别版本可能出现口径不一致;排障时优先看 `status --deep` 的 Health。
295
-
296
- ---
297
-
298
- ## 10. 兼容接口说明
299
-
300
- ### `bncr.activity`
301
-
302
- 用于活动保活,建议节流(例如 60s 一次)。
303
-
304
- 请求示例:
305
-
306
- ```json
307
- {
308
- "type": "req",
309
- "id": "a1",
310
- "method": "bncr.activity",
311
- "params": {
312
- "accountId": "Primary",
313
- "clientId": "bncr-client-1",
314
- "reason": "heartbeat"
315
- }
316
- }
63
+ ```bash
64
+ openclaw gateway status
65
+ openclaw health --json
317
66
  ```
318
67
 
319
- `reason` 为可选自定义字段,插件会忽略业务外字段。
320
-
321
- ### `bncr.ack`
322
-
323
- 可调用,但当前模式下不是必需链路。
324
-
325
- ---
326
-
327
- ## 11. FAQ
328
-
329
- ### Q1:为什么看不到回复?
330
-
331
- 1. 先确认 `bncr.connect` 成功。
332
- 2. 客户端确认监听的是 `bncr.push`。
333
- 3. `sessionKey` 是否符合严格格式。
334
- 4. 若用 `message.send`,目标是否能反查到已知会话。
335
-
336
- ### Q2:为什么不需要 `bncr.pull`?
337
-
338
- 因为当前是 push-only,统一走 `bncr.push`。
68
+ 重点看:
339
69
 
340
- ### Q3:如何避免重复消息?
70
+ - 网关是否正常运行
71
+ - bncr 是否已经 `linked`
72
+ - 是否存在异常 pending / deadLetter
341
73
 
342
- - 入站带稳定 `msgId`。
343
- - 出站按 `idempotencyKey` 幂等处理。
344
- - 客户端侧建议只消费 `message.outbound` 主链路。
74
+ 如果 bncr 已成功连上,一般就说明插件安装和基础链路已经正常。
345
75
 
346
76
  ---
347
77
 
348
- ## 12. 版本提示
78
+ ## 说明
349
79
 
350
- 历史版本接入过的话,请以当前文档(push-only + strict sessionKey + 目标反查)为准。
80
+ 如果你接触过旧版本,请以当前 README 和当前代码为准。
package/index.ts CHANGED
@@ -37,6 +37,30 @@ const plugin = {
37
37
  "bncr.ack",
38
38
  (opts: GatewayRequestHandlerOptions) => bridge.handleAck(opts),
39
39
  );
40
+ api.registerGatewayMethod(
41
+ "bncr.diagnostics",
42
+ (opts: GatewayRequestHandlerOptions) => bridge.handleDiagnostics(opts),
43
+ );
44
+ api.registerGatewayMethod(
45
+ "bncr.file.init",
46
+ (opts: GatewayRequestHandlerOptions) => bridge.handleFileInit(opts),
47
+ );
48
+ api.registerGatewayMethod(
49
+ "bncr.file.chunk",
50
+ (opts: GatewayRequestHandlerOptions) => bridge.handleFileChunk(opts),
51
+ );
52
+ api.registerGatewayMethod(
53
+ "bncr.file.complete",
54
+ (opts: GatewayRequestHandlerOptions) => bridge.handleFileComplete(opts),
55
+ );
56
+ api.registerGatewayMethod(
57
+ "bncr.file.abort",
58
+ (opts: GatewayRequestHandlerOptions) => bridge.handleFileAbort(opts),
59
+ );
60
+ api.registerGatewayMethod(
61
+ "bncr.file.ack",
62
+ (opts: GatewayRequestHandlerOptions) => bridge.handleFileAck(opts),
63
+ );
40
64
  },
41
65
  };
42
66
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmoxmo/bncr",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "MIT",