@xmoxmo/bncr 0.3.1 → 0.3.3

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
@@ -193,6 +193,20 @@ openclaw gateway call message.action --params '{
193
193
 
194
194
  后续如果在其他 OpenClaw 版本上完成验证,应继续在本节追加对应版本的验证过程与结论,不直接外推复用 `2026.5.18` 的验证口径。
195
195
 
196
+ ### 2026.6.1 验证说明
197
+
198
+ 以下口径已在 OpenClaw `2026.6.1` 与 bncr `0.3.2` 上完成基础验证:
199
+
200
+ 1. 普通文本入站与 assistant 文本回复正常。
201
+ 2. Agent 回复中的图片附件可通过 `MEDIA:<path>` 投递。
202
+ 3. Agent 回复中的 `ogg(opus)` voice 附件可通过 `MEDIA:<path>` 搭配 voice 发送提示投递。
203
+ 4. 入站 prompt 中只出现 OpenClaw 官方 `Conversation info` / `Sender` untrusted metadata,未重复注入 bncr 自定义 context block。
204
+
205
+ 仍需分开判断:
206
+
207
+ - `MEDIA:<path>` 成功代表宿主 reply-media / attachment 链路和 bncr 下行媒体投递在该场景下可用。
208
+ - `message.action` / `send` 仍应作为显式目标发送链单独验证,特别是跨会话、跨账号、文件传输 ACK 与 outbox 重试场景。
209
+
196
210
  ---
197
211
 
198
212
  ## 8. 状态与诊断
@@ -257,7 +271,7 @@ npm pack
257
271
  用途:
258
272
 
259
273
  - `npm test`:跑回归测试
260
- - `npm run selfcheck`:检查插件骨架是否完整
274
+ - `npm run selfcheck`:检查插件骨架是否完整,并验证关键 OpenClaw SDK subpath 可解析
261
275
  - `npm run check-pack`:执行 `npm pack --dry-run --json`,确认发布包包含关键入口与 OpenClaw adapter 文件
262
276
  - `npm pack`:确认当前版本可正常打包
263
277
  - `npm run check-register-drift -- --duration-sec 300 --interval-sec 15`:静置采样 `bncr.diagnostics`,观察 `registerCount / apiGeneration / postWarmupRegisterCount` 是否在 warmup 后继续增长
package/dist/index.js CHANGED
@@ -251,6 +251,13 @@ var ensurePluginNodeModulesLink = (targetRoot) => {
251
251
  }
252
252
  fs.symlinkSync(targetRoot, linkPath, linkType);
253
253
  };
254
+ var runtimeSourceDir = (() => {
255
+ const direct = path.join(pluginDir, "src");
256
+ if (fs.existsSync(path.join(direct, "channel.ts"))) return direct;
257
+ const parent = path.join(pluginDir, "..", "src");
258
+ if (fs.existsSync(path.join(parent, "channel.ts"))) return parent;
259
+ return direct;
260
+ })();
254
261
  var ensureOpenClawSdkResolution = () => {
255
262
  if (canResolveSdkCore()) return;
256
263
  let lastError = "";
@@ -273,7 +280,7 @@ var loadRuntimeSync = () => {
273
280
  if (runtime) return runtime;
274
281
  ensureOpenClawSdkResolution();
275
282
  try {
276
- const mod = pluginRequire("./src/channel.ts");
283
+ const mod = pluginRequire(path.join(runtimeSourceDir, "channel.ts"));
277
284
  runtime = {
278
285
  createBncrBridge: mod.createBncrBridge,
279
286
  createBncrChannelPlugin: mod.createBncrChannelPlugin
@@ -281,7 +288,7 @@ var loadRuntimeSync = () => {
281
288
  return runtime;
282
289
  } catch (error) {
283
290
  const detail = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
284
- throw new Error(`bncr failed to load channel runtime after dependency bootstrap: ${detail}`);
291
+ throw new Error(`bncr failed to load channel runtime after dependency bootstrap from ${runtimeSourceDir}: ${detail}`);
285
292
  }
286
293
  };
287
294
  var getIdentityId = (obj, prefix) => {
package/index.ts CHANGED
@@ -251,6 +251,16 @@ const ensurePluginNodeModulesLink = (targetRoot: string) => {
251
251
  fs.symlinkSync(targetRoot, linkPath, linkType as fs.symlink.Type);
252
252
  };
253
253
 
254
+ const runtimeSourceDir = (() => {
255
+ const direct = path.join(pluginDir, 'src');
256
+ if (fs.existsSync(path.join(direct, 'channel.ts'))) return direct;
257
+
258
+ const parent = path.join(pluginDir, '..', 'src');
259
+ if (fs.existsSync(path.join(parent, 'channel.ts'))) return parent;
260
+
261
+ return direct;
262
+ })();
263
+
254
264
  const ensureOpenClawSdkResolution = () => {
255
265
  if (canResolveSdkCore()) return;
256
266
 
@@ -279,7 +289,7 @@ const loadRuntimeSync = (): LoadedRuntime => {
279
289
  if (runtime) return runtime;
280
290
  ensureOpenClawSdkResolution();
281
291
  try {
282
- const mod = pluginRequire('./src/channel.ts') as ChannelModule;
292
+ const mod = pluginRequire(path.join(runtimeSourceDir, 'channel.ts')) as ChannelModule;
283
293
  runtime = {
284
294
  createBncrBridge: mod.createBncrBridge,
285
295
  createBncrChannelPlugin: mod.createBncrChannelPlugin,
@@ -287,7 +297,7 @@ const loadRuntimeSync = (): LoadedRuntime => {
287
297
  return runtime;
288
298
  } catch (error) {
289
299
  const detail = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
290
- throw new Error(`bncr failed to load channel runtime after dependency bootstrap: ${detail}`);
300
+ throw new Error(`bncr failed to load channel runtime after dependency bootstrap from ${runtimeSourceDir}: ${detail}`);
291
301
  }
292
302
  };
293
303
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmoxmo/bncr",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,10 +1,12 @@
1
1
  import fs from 'node:fs';
2
+ import { createRequire } from 'node:module';
2
3
  import path from 'node:path';
3
4
  import { fileURLToPath } from 'node:url';
4
5
 
5
6
  const __filename = fileURLToPath(import.meta.url);
6
7
  const __dirname = path.dirname(__filename);
7
8
  const root = path.resolve(__dirname, '..');
9
+ const require = createRequire(import.meta.url);
8
10
 
9
11
  const requiredFiles = [
10
12
  'index.ts',
@@ -43,6 +45,29 @@ const readPackageVersion = () => {
43
45
  return typeof pkg?.version === 'string' ? pkg.version.trim() : '';
44
46
  };
45
47
 
48
+ const requiredOpenClawSdkSubpaths = [
49
+ 'openclaw/plugin-sdk/channel-outbound',
50
+ 'openclaw/plugin-sdk/channel-message',
51
+ 'openclaw/plugin-sdk/routing',
52
+ 'openclaw/plugin-sdk/conversation-runtime',
53
+ 'openclaw/plugin-sdk/session-store-runtime',
54
+ 'openclaw/plugin-sdk/core',
55
+ ];
56
+
57
+ const resolveOpenClawSdkSubpaths = () => {
58
+ return requiredOpenClawSdkSubpaths.map((specifier) => {
59
+ try {
60
+ return { specifier, ok: true, path: require.resolve(specifier) };
61
+ } catch (err) {
62
+ return {
63
+ specifier,
64
+ ok: false,
65
+ error: err && typeof err === 'object' && 'code' in err ? err.code : String(err),
66
+ };
67
+ }
68
+ });
69
+ };
70
+
46
71
  const validateVersionPolicy = (version) => {
47
72
  const match = version.match(/^(\d+)\.(\d+)\.(\d+)$/);
48
73
  if (!match) {
@@ -68,14 +93,17 @@ const validateVersionPolicy = (version) => {
68
93
  const missing = requiredFiles.filter((rel) => !fs.existsSync(path.join(root, rel)));
69
94
  const version = readPackageVersion();
70
95
  const versionPolicy = validateVersionPolicy(version);
96
+ const sdkSubpaths = resolveOpenClawSdkSubpaths();
97
+ const missingSdkSubpaths = sdkSubpaths.filter((entry) => !entry.ok);
71
98
  const result = {
72
- ok: missing.length === 0 && versionPolicy.ok,
99
+ ok: missing.length === 0 && versionPolicy.ok && missingSdkSubpaths.length === 0,
73
100
  checkedRoot: root,
74
101
  requiredCount: requiredFiles.length,
75
102
  missing,
76
103
  version,
77
104
  versionPolicy,
105
+ sdkSubpaths,
78
106
  };
79
107
 
80
108
  console.log(JSON.stringify(result, null, 2));
81
- if (missing.length > 0 || !versionPolicy.ok) process.exit(1);
109
+ if (missing.length > 0 || !versionPolicy.ok || missingSdkSubpaths.length > 0) process.exit(1);
@@ -1,11 +1,11 @@
1
- import { defineChannelMessageAdapter } from 'openclaw/plugin-sdk/channel-outbound';
1
+ import { defineChannelMessageAdapter } from 'openclaw/plugin-sdk/channel-message';
2
2
  import type {
3
3
  ChannelMessageAdapterShape,
4
4
  ChannelMessageSendMediaContext,
5
5
  ChannelMessageSendPayloadContext,
6
6
  ChannelMessageSendResult,
7
7
  ChannelMessageSendTextContext,
8
- } from 'openclaw/plugin-sdk/channel-outbound';
8
+ } from 'openclaw/plugin-sdk/channel-message';
9
9
 
10
10
  import { buildFileTransferOutboxEntry, buildTextOutboxEntry } from '../../core/outbox-entry-builders.ts';
11
11
  import type { BncrRoute, OutboxEntry } from '../../core/types.ts';