@xmoxmo/bncr 0.0.4 → 0.0.6

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 xmoxmo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -4,13 +4,22 @@ OpenClaw 的 Bncr 频道插件(`channelId=bncr`)。
4
4
 
5
5
  作用很简单:把 **Bncr / 无界客户端** 接到 **OpenClaw 网关**,用于消息双向通信与媒体/文件传输。
6
6
 
7
+ > 当前定位说明:bncr **不是 agent**。它保留既有 **WS 接入链路** 作为 transport / 通信承载,
8
+ > 在 OpenClaw 内部则按 **正式频道插件(channel plugin)** 建模。
9
+
7
10
  ---
8
11
 
9
- ## 安装
12
+ ## 1. 这是什么
10
13
 
11
- ### OpenClaw
14
+ - 一个 OpenClaw 的正式频道插件
15
+ - 负责把 Bncr / 无界客户端接入 OpenClaw
16
+ - 负责消息、媒体、文件与基础状态链路
17
+
18
+ ---
19
+
20
+ ## 2. 安装方式
12
21
 
13
- OpenClaw 上执行:
22
+ ### OpenClaw
14
23
 
15
24
  ```bash
16
25
  openclaw plugins install @xmoxmo/bncr
@@ -24,20 +33,11 @@ openclaw gateway restart
24
33
 
25
34
  - `openclawclient.js`
26
35
 
27
- 然后完成客户端配置,至少包括:
28
-
29
- - OpenClaw 地址
30
- - 端口
31
- - Token
32
- - 连接相关参数
33
-
34
- 配置完成后,让客户端成功连到 OpenClaw 网关即可。
36
+ 然后完成客户端配置并连上 OpenClaw 网关即可。
35
37
 
36
38
  ---
37
39
 
38
- ## 支持能力
39
-
40
- ### 支持内容
40
+ ## 3. 当前能力
41
41
 
42
42
  - 文本
43
43
  - 图片
@@ -45,20 +45,62 @@ openclaw gateway restart
45
45
  - 语音
46
46
  - 音频
47
47
  - 文件
48
-
49
- ### 其它特性
50
-
51
48
  - 下行推送
52
- - 离线消息自动排队
49
+ - ACK
50
+ - 离线消息排队
53
51
  - 重连后继续发送
54
- - 支持诊断信息
55
- - 支持文件互传
52
+ - 状态诊断
53
+ - 文件互传
54
+
55
+ ---
56
+
57
+ ## 4. 架构定位
58
+
59
+ bncr 当前采用两层模型:
60
+
61
+ 1. **WS 承载层**
62
+ - Bncr 客户端通过 WebSocket 接入 OpenClaw 网关
63
+ - 负责连接、推送、ACK、文件分块等 transport 能力
64
+
65
+ 2. **OpenClaw 频道插件层**
66
+ - 在 OpenClaw 内部按正式 `channel plugin` 建模
67
+ - 负责入站解析、消息分发、出站适配、状态与治理
68
+
69
+ 当前代码结构:
70
+
71
+ ```text
72
+ plugins/bncr/src/
73
+ channel.ts
74
+ core/
75
+ messaging/
76
+ ```
77
+
78
+ ---
79
+
80
+ ## 5. 配置项总览
81
+
82
+ 当前主要配置字段:
83
+
84
+ - `enabled`
85
+ - `dmPolicy`
86
+ - `groupPolicy`
87
+ - `allowFrom`
88
+ - `groupAllowFrom`
89
+ - `outboundRequireAck`
90
+ - `requireMention`
91
+ - `accounts`
92
+
93
+ 补充:
94
+
95
+ - `dmPolicy` / `groupPolicy` 支持:`open | allowlist | disabled`
96
+ - `outboundRequireAck` 控制文本外发是否等待 `bncr.ack` 再出队
97
+ - `requireMention` 当前仍是保留字段
56
98
 
57
99
  ---
58
100
 
59
- ## 安装后如何确认成功
101
+ ## 6. 状态与诊断
60
102
 
61
- 可以通过以下方式检查:
103
+ 常用检查:
62
104
 
63
105
  ```bash
64
106
  openclaw gateway status
@@ -67,14 +109,42 @@ openclaw health --json
67
109
 
68
110
  重点看:
69
111
 
70
- - 网关是否正常运行
71
- - bncr 是否已经 `linked`
72
- - 是否存在异常 pending / deadLetter
112
+ - `linked`
113
+ - `pending`
114
+ - `deadLetter`
115
+ - diagnostics / probe / status 摘要
116
+
117
+ ---
73
118
 
74
- 如果 bncr 已成功连上,一般就说明插件安装和基础链路已经正常。
119
+ ## 7. 自检与测试
120
+
121
+ ```bash
122
+ cd plugins/bncr
123
+ npm test
124
+ npm run selfcheck
125
+ npm pack
126
+ ```
127
+
128
+ 用途:
129
+
130
+ - `npm test`:跑回归测试
131
+ - `npm run selfcheck`:检查插件骨架是否完整
132
+ - `npm pack`:确认当前版本可正常打包
75
133
 
76
134
  ---
77
135
 
78
- ## 说明
136
+ ## 8. 上线前检查
137
+
138
+ 上线前建议至少确认:
139
+
140
+ - README 与当前实现一致
141
+ - 配置 schema 与实际字段一致
142
+ - 测试通过
143
+ - 自检通过
144
+ - 可以正常打包
145
+ - 本地版本号与 npm / 发布目标一致
146
+ - 运行态 `linked / pending / deadLetter` 正常
147
+
148
+ ---
79
149
 
80
150
  如果你接触过旧版本,请以当前 README 和当前代码为准。
package/index.ts CHANGED
@@ -1,21 +1,47 @@
1
1
  import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
2
2
  import {
3
- emptyPluginConfigSchema,
4
3
  type GatewayRequestHandlerOptions,
5
4
  } from "openclaw/plugin-sdk";
5
+ import { BncrConfigSchema } from "./src/core/config-schema.js";
6
6
  import { createBncrBridge, createBncrChannelPlugin } from "./src/channel.js";
7
7
 
8
+ type BridgeSingleton = ReturnType<typeof createBncrBridge>;
9
+
10
+ const getBridgeSingleton = (api: OpenClawPluginApi) => {
11
+ const g = globalThis as typeof globalThis & { __bncrBridge?: BridgeSingleton };
12
+ if (!g.__bncrBridge) g.__bncrBridge = createBncrBridge(api);
13
+ return g.__bncrBridge;
14
+ };
15
+
8
16
  const plugin = {
9
17
  id: "bncr",
10
18
  name: "Bncr",
11
19
  description: "Bncr channel plugin",
12
- configSchema: emptyPluginConfigSchema(),
20
+ configSchema: BncrConfigSchema,
13
21
  register(api: OpenClawPluginApi) {
14
- const bridge = createBncrBridge(api);
22
+ const bridge = getBridgeSingleton(api);
23
+ const debugLog = (...args: any[]) => {
24
+ if (!bridge.isDebugEnabled?.()) return;
25
+ api.logger.info?.(...args);
26
+ };
27
+
28
+ debugLog(`bncr plugin register bridge=${(bridge as any)?.bridgeId || 'unknown'}`);
29
+
30
+ const resolveDebug = async () => {
31
+ try {
32
+ const cfg = await api.runtime.config.loadConfig();
33
+ return Boolean((cfg as any)?.channels?.bncr?.debug?.verbose);
34
+ } catch {
35
+ return false;
36
+ }
37
+ };
15
38
 
16
39
  api.registerService({
17
40
  id: "bncr-bridge-service",
18
- start: bridge.startService,
41
+ start: async (ctx) => {
42
+ const debug = await resolveDebug();
43
+ await bridge.startService(ctx, debug);
44
+ },
19
45
  stop: bridge.stopService,
20
46
  });
21
47
 
@@ -3,7 +3,38 @@
3
3
  "channels": ["bncr"],
4
4
  "configSchema": {
5
5
  "type": "object",
6
- "additionalProperties": false,
7
- "properties": {}
6
+ "additionalProperties": true,
7
+ "properties": {
8
+ "enabled": { "type": "boolean" },
9
+ "dmPolicy": {
10
+ "type": "string",
11
+ "enum": ["open", "allowlist", "disabled"]
12
+ },
13
+ "groupPolicy": {
14
+ "type": "string",
15
+ "enum": ["open", "allowlist", "disabled"]
16
+ },
17
+ "allowFrom": {
18
+ "type": "array",
19
+ "items": { "type": "string" }
20
+ },
21
+ "groupAllowFrom": {
22
+ "type": "array",
23
+ "items": { "type": "string" }
24
+ },
25
+ "requireMention": { "type": "boolean" },
26
+ "outboundRequireAck": { "type": "boolean" },
27
+ "accounts": {
28
+ "type": "object",
29
+ "additionalProperties": {
30
+ "type": "object",
31
+ "additionalProperties": true,
32
+ "properties": {
33
+ "enabled": { "type": "boolean" },
34
+ "name": { "type": "string" }
35
+ }
36
+ }
37
+ }
38
+ }
8
39
  }
9
40
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmoxmo/bncr",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -20,8 +20,13 @@
20
20
  "openclaw.plugin.json",
21
21
  "README.md",
22
22
  "LICENSE",
23
- "src"
23
+ "src",
24
+ "scripts"
24
25
  ],
26
+ "scripts": {
27
+ "selfcheck": "node ./scripts/selfcheck.mjs",
28
+ "test": "node --import ./tests/register-ts-hooks.mjs --test ./tests/*.test.mjs"
29
+ },
25
30
  "openclaw": {
26
31
  "extensions": [
27
32
  "./index.ts"
@@ -0,0 +1,38 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = path.dirname(__filename);
7
+ const root = path.resolve(__dirname, '..');
8
+
9
+ const requiredFiles = [
10
+ 'index.ts',
11
+ 'openclaw.plugin.json',
12
+ 'src/channel.ts',
13
+ 'src/core/types.ts',
14
+ 'src/core/accounts.ts',
15
+ 'src/core/targets.ts',
16
+ 'src/core/status.ts',
17
+ 'src/core/probe.ts',
18
+ 'src/core/config-schema.ts',
19
+ 'src/core/policy.ts',
20
+ 'src/core/permissions.ts',
21
+ 'src/messaging/inbound/parse.ts',
22
+ 'src/messaging/inbound/gate.ts',
23
+ 'src/messaging/inbound/dispatch.ts',
24
+ 'src/messaging/outbound/send.ts',
25
+ 'src/messaging/outbound/media.ts',
26
+ 'src/messaging/outbound/actions.ts',
27
+ ];
28
+
29
+ const missing = requiredFiles.filter((rel) => !fs.existsSync(path.join(root, rel)));
30
+ const result = {
31
+ ok: missing.length === 0,
32
+ checkedRoot: root,
33
+ requiredCount: requiredFiles.length,
34
+ missing,
35
+ };
36
+
37
+ console.log(JSON.stringify(result, null, 2));
38
+ if (missing.length > 0) process.exit(1);