@xmoxmo/bncr 0.3.2 → 0.3.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 +15 -1
- package/index.ts +5 -10
- package/package.json +4 -4
- package/scripts/check-pack.mjs +15 -5
- package/scripts/selfcheck.mjs +30 -2
- package/src/channel.ts +79 -182
- package/src/core/accounts.ts +1 -1
- package/src/core/connection-reachability.ts +6 -1
- package/src/core/downlink-health.ts +3 -3
- package/src/core/extended-diagnostics.ts +2 -0
- package/src/core/file-transfer-payloads.ts +1 -4
- package/src/core/outbox-entry-builders.ts +4 -2
- package/src/core/outbox-file-transfer-bookkeeping.ts +1 -1
- package/src/core/outbox-file-transfer-failure.ts +2 -5
- package/src/core/outbox-file-transfer-success.ts +1 -4
- package/src/core/outbox-text-push-failure.ts +2 -4
- package/src/core/outbox-text-push-success.ts +1 -1
- package/src/messaging/inbound/commands.ts +34 -25
- package/src/messaging/inbound/dispatch.ts +16 -18
- package/src/messaging/inbound/parse.ts +3 -3
- package/src/messaging/inbound/runtime-compat.ts +8 -2
- package/src/messaging/outbound/build-send-action.ts +1 -2
- package/src/messaging/outbound/durable-message-adapter.ts +16 -6
- package/src/messaging/outbound/durable-queue-adapter.ts +3 -1
- package/src/messaging/outbound/media.ts +2 -1
- package/src/messaging/outbound/queue-selectors.ts +19 -6
- package/src/messaging/outbound/reasons.ts +2 -0
- package/src/messaging/outbound/reply-enqueue.ts +5 -1
- package/src/messaging/outbound/retry-policy.ts +16 -8
- package/src/messaging/outbound/session-route.ts +1 -1
- package/src/openclaw/reply-runtime.ts +4 -5
- package/src/openclaw/routing-runtime.ts +0 -1
- package/src/openclaw/sdk-helpers.ts +4 -1
- package/src/plugin/messaging.ts +2 -9
- package/src/plugin/status.ts +5 -1
- package/src/runtime/outbound-flags.ts +1 -1
- package/src/runtime/outbox-transitions.ts +4 -4
- package/src/runtime/status-snapshots.ts +3 -1
- package/src/runtime/status-worker.ts +8 -2
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/index.ts
CHANGED
|
@@ -111,7 +111,6 @@ type BncrGatewayRuntime = {
|
|
|
111
111
|
};
|
|
112
112
|
|
|
113
113
|
let runtime: LoadedRuntime | null = null;
|
|
114
|
-
let activeServiceStop: (() => Promise<void>) | null = null;
|
|
115
114
|
const identityIds = new WeakMap<object, string>();
|
|
116
115
|
let identitySeq = 0;
|
|
117
116
|
|
|
@@ -297,7 +296,9 @@ const loadRuntimeSync = (): LoadedRuntime => {
|
|
|
297
296
|
return runtime;
|
|
298
297
|
} catch (error) {
|
|
299
298
|
const detail = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
|
|
300
|
-
throw new Error(
|
|
299
|
+
throw new Error(
|
|
300
|
+
`bncr failed to load channel runtime after dependency bootstrap from ${runtimeSourceDir}: ${detail}`,
|
|
301
|
+
);
|
|
301
302
|
}
|
|
302
303
|
};
|
|
303
304
|
|
|
@@ -365,14 +366,9 @@ const getGatewayRuntime = (): BncrGatewayRuntime => {
|
|
|
365
366
|
};
|
|
366
367
|
|
|
367
368
|
const getProcessOwnerApiInstanceId = (gatewayRuntime: BncrGatewayRuntime) =>
|
|
368
|
-
gatewayRuntime.serviceOwnerApiInstanceId ||
|
|
369
|
-
gatewayRuntime.channelOwnerApiInstanceId ||
|
|
370
|
-
undefined;
|
|
369
|
+
gatewayRuntime.serviceOwnerApiInstanceId || gatewayRuntime.channelOwnerApiInstanceId || undefined;
|
|
371
370
|
|
|
372
|
-
const shouldAdoptProcessOwner = (
|
|
373
|
-
apiInstanceId: string,
|
|
374
|
-
gatewayRuntime: BncrGatewayRuntime,
|
|
375
|
-
) => {
|
|
371
|
+
const shouldAdoptProcessOwner = (apiInstanceId: string, gatewayRuntime: BncrGatewayRuntime) => {
|
|
376
372
|
const existingOwnerApiInstanceId = getProcessOwnerApiInstanceId(gatewayRuntime);
|
|
377
373
|
const hasSingletonOwner =
|
|
378
374
|
Boolean(gatewayRuntime.serviceRegistered) || Boolean(gatewayRuntime.channelRegistered);
|
|
@@ -845,7 +841,6 @@ const plugin = {
|
|
|
845
841
|
},
|
|
846
842
|
stop: serviceStopHandler,
|
|
847
843
|
});
|
|
848
|
-
activeServiceStop = serviceStopHandler;
|
|
849
844
|
gatewayRuntime.serviceRegistered = true;
|
|
850
845
|
gatewayRuntime.serviceOwnerApiInstanceId = apiInstanceId;
|
|
851
846
|
meta.service = true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xmoxmo/bncr",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
"openclaw": ">=2026.5.27"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@biomejs/biome": "^
|
|
43
|
-
"
|
|
44
|
-
"
|
|
42
|
+
"@biomejs/biome": "^2.4.16",
|
|
43
|
+
"esbuild": "^0.28.0",
|
|
44
|
+
"openclaw": ">=2026.5.27"
|
|
45
45
|
},
|
|
46
46
|
"openclaw": {
|
|
47
47
|
"extensions": [
|
package/scripts/check-pack.mjs
CHANGED
|
@@ -48,19 +48,29 @@ const [pack] = JSON.parse(output);
|
|
|
48
48
|
const packedFiles = new Set((pack?.files ?? []).map((file) => file.path));
|
|
49
49
|
const missing = requiredPackFiles.filter((file) => !packedFiles.has(file));
|
|
50
50
|
const channelSource = fs.readFileSync(path.join(root, 'src/channel.ts'), 'utf8');
|
|
51
|
-
const messagePolicySource = fs.readFileSync(
|
|
51
|
+
const messagePolicySource = fs.readFileSync(
|
|
52
|
+
path.join(root, 'src/plugin/message-policy.ts'),
|
|
53
|
+
'utf8',
|
|
54
|
+
);
|
|
52
55
|
const messageSendSource = fs.readFileSync(path.join(root, 'src/plugin/message-send.ts'), 'utf8');
|
|
53
56
|
const channelMessageChecks = {
|
|
54
57
|
registered: channelSource.includes('message: {'),
|
|
55
|
-
text:
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
text:
|
|
59
|
+
channelSource.includes('createBncrMessageSend') &&
|
|
60
|
+
messageSendSource.includes('channelMessageSendText'),
|
|
61
|
+
media:
|
|
62
|
+
channelSource.includes('createBncrMessageSend') &&
|
|
63
|
+
messageSendSource.includes('channelMessageSendMedia'),
|
|
64
|
+
payload:
|
|
65
|
+
channelSource.includes('createBncrMessageSend') &&
|
|
66
|
+
messageSendSource.includes('channelMessageSendPayload'),
|
|
58
67
|
manualAck:
|
|
59
68
|
channelSource.includes('BNCR_MESSAGE_RECEIVE_POLICY') &&
|
|
60
69
|
messagePolicySource.includes("defaultAckPolicy: 'manual'") &&
|
|
61
70
|
messagePolicySource.includes("supportedAckPolicies: ['manual']"),
|
|
62
71
|
genericActionsPreserved: channelSource.includes('actions: messageActions'),
|
|
63
|
-
noDurableFinal:
|
|
72
|
+
noDurableFinal:
|
|
73
|
+
!channelSource.includes('durableFinal:') && !messagePolicySource.includes('durableFinal:'),
|
|
64
74
|
};
|
|
65
75
|
const channelMessageOk = Object.values(channelMessageChecks).every(Boolean);
|
|
66
76
|
|
package/scripts/selfcheck.mjs
CHANGED
|
@@ -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);
|