@xmoxmo/bncr 0.3.6 → 0.3.8

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.
Files changed (165) hide show
  1. package/README.md +5 -0
  2. package/dist/index.js +28 -5
  3. package/index.ts +55 -721
  4. package/openclaw.plugin.json +1 -0
  5. package/package.json +8 -4
  6. package/scripts/check-pack.mjs +93 -18
  7. package/scripts/check-register-drift.mjs +35 -13
  8. package/scripts/selfcheck.mjs +80 -11
  9. package/src/bootstrap/channel-plugin-runtime.ts +81 -0
  10. package/src/bootstrap/cli.ts +97 -0
  11. package/src/bootstrap/register-runtime-gateway.ts +129 -0
  12. package/src/bootstrap/register-runtime-helpers.ts +140 -0
  13. package/src/bootstrap/register-runtime-singleton.ts +137 -0
  14. package/src/bootstrap/register-runtime.ts +201 -0
  15. package/src/bootstrap/runtime-discovery.ts +187 -0
  16. package/src/bootstrap/runtime-loader.ts +54 -0
  17. package/src/channel.ts +1590 -4967
  18. package/src/core/accounts.ts +23 -4
  19. package/src/core/dead-letter-diagnostics.ts +37 -5
  20. package/src/core/diagnostics.ts +31 -15
  21. package/src/core/downlink-health.ts +3 -11
  22. package/src/core/extended-diagnostics.ts +78 -36
  23. package/src/core/file-transfer-payloads.ts +1 -1
  24. package/src/core/logging.ts +1 -0
  25. package/src/core/outbox-enqueue.ts +13 -2
  26. package/src/core/outbox-entry-builders.ts +2 -0
  27. package/src/core/outbox-summary.ts +75 -3
  28. package/src/core/permissions.ts +15 -2
  29. package/src/core/persisted-outbox-entry.ts +21 -6
  30. package/src/core/policy.ts +45 -4
  31. package/src/core/probe.ts +3 -15
  32. package/src/core/register-trace.ts +3 -3
  33. package/src/core/status.ts +43 -4
  34. package/src/core/targets.ts +216 -205
  35. package/src/core/types.ts +221 -0
  36. package/src/core/value-sanitize.ts +29 -0
  37. package/src/messaging/inbound/commands.ts +147 -172
  38. package/src/messaging/inbound/context-facts.ts +4 -2
  39. package/src/messaging/inbound/contracts.ts +70 -0
  40. package/src/messaging/inbound/dispatch-prep.ts +303 -0
  41. package/src/messaging/inbound/dispatch.ts +49 -462
  42. package/src/messaging/inbound/gate.ts +18 -5
  43. package/src/messaging/inbound/last-route.ts +10 -4
  44. package/src/messaging/inbound/media-url-download.ts +109 -0
  45. package/src/messaging/inbound/native-command-runtime.ts +225 -0
  46. package/src/messaging/inbound/parse.ts +2 -1
  47. package/src/messaging/inbound/remote-media.ts +49 -0
  48. package/src/messaging/inbound/reply-config.ts +16 -4
  49. package/src/messaging/inbound/reply-dispatch.ts +162 -0
  50. package/src/messaging/inbound/runtime-compat.ts +31 -10
  51. package/src/messaging/inbound/session-label.ts +15 -7
  52. package/src/messaging/inbound/turn-context.ts +131 -0
  53. package/src/messaging/outbound/actions.ts +24 -10
  54. package/src/messaging/outbound/diagnostics-debug-builders.ts +365 -0
  55. package/src/messaging/outbound/diagnostics.ts +31 -355
  56. package/src/messaging/outbound/durable-message-adapter.ts +20 -16
  57. package/src/messaging/outbound/durable-queue-adapter.ts +20 -7
  58. package/src/messaging/outbound/media.ts +24 -13
  59. package/src/messaging/outbound/reply-enqueue-media.ts +181 -0
  60. package/src/messaging/outbound/reply-enqueue.ts +46 -155
  61. package/src/messaging/outbound/send-params.ts +3 -0
  62. package/src/messaging/outbound/send.ts +19 -10
  63. package/src/messaging/outbound/session-route.ts +18 -3
  64. package/src/openclaw/channel-runtime-contracts.ts +76 -0
  65. package/src/openclaw/config-runtime.ts +13 -7
  66. package/src/openclaw/inbound-session-runtime.ts +7 -3
  67. package/src/openclaw/ingress-runtime.ts +17 -27
  68. package/src/openclaw/reply-runtime.ts +54 -59
  69. package/src/openclaw/routing-runtime.ts +35 -18
  70. package/src/openclaw/runtime-surface.ts +156 -12
  71. package/src/openclaw/sdk-helpers.ts +8 -1
  72. package/src/openclaw/session-route-runtime.ts +12 -12
  73. package/src/plugin/ack-outbox-runtime-group.ts +264 -0
  74. package/src/plugin/bridge-ack-facade.ts +137 -0
  75. package/src/plugin/bridge-connection-facade.ts +111 -0
  76. package/src/plugin/bridge-diagnostics-facade.ts +23 -0
  77. package/src/plugin/bridge-drain-facade.ts +98 -0
  78. package/src/plugin/bridge-extended-diagnostics-facade.ts +149 -0
  79. package/src/plugin/bridge-file-transfer-push-facade.ts +140 -0
  80. package/src/plugin/bridge-lifecycle.ts +156 -0
  81. package/src/plugin/bridge-media-facade.ts +241 -0
  82. package/src/plugin/bridge-outbox-facade.ts +182 -0
  83. package/src/plugin/bridge-runtime-helpers.ts +266 -0
  84. package/src/plugin/bridge-runtime-snapshots.ts +104 -0
  85. package/src/plugin/bridge-runtime-surface-facade.ts +8 -0
  86. package/src/plugin/bridge-status-facade.ts +76 -0
  87. package/src/plugin/bridge-status-worker-facade.ts +72 -0
  88. package/src/plugin/bridge-support-runtime.ts +137 -0
  89. package/src/plugin/bridge-surface-handlers-group.ts +242 -0
  90. package/src/plugin/bridge-surface-helpers.ts +28 -0
  91. package/src/plugin/capabilities.ts +1 -3
  92. package/src/plugin/channel-components.ts +289 -0
  93. package/src/plugin/channel-inbound-helpers.ts +149 -0
  94. package/src/plugin/channel-plugin-bridge-group.ts +129 -0
  95. package/src/plugin/channel-plugin-surface-group.ts +202 -0
  96. package/src/plugin/channel-runtime-builders-delivery.ts +513 -0
  97. package/src/plugin/channel-runtime-builders-status.ts +331 -0
  98. package/src/plugin/channel-runtime-builders.ts +25 -0
  99. package/src/plugin/channel-runtime-constants.ts +40 -0
  100. package/src/plugin/channel-runtime-types.ts +146 -0
  101. package/src/plugin/channel-send-runtime-group.ts +37 -0
  102. package/src/plugin/channel-send.ts +226 -0
  103. package/src/plugin/channel-utils.ts +102 -0
  104. package/src/plugin/config.ts +24 -3
  105. package/src/plugin/connection-handlers-helpers.ts +254 -0
  106. package/src/plugin/connection-handlers.ts +440 -0
  107. package/src/plugin/connection-state-helpers.ts +159 -0
  108. package/src/plugin/connection-state-runtime-group.ts +51 -0
  109. package/src/plugin/connection-state.ts +527 -0
  110. package/src/plugin/diagnostics-handlers.ts +211 -0
  111. package/src/plugin/error-message.ts +15 -0
  112. package/src/plugin/file-ack-runtime.ts +284 -0
  113. package/src/plugin/file-inbound-abort.ts +112 -0
  114. package/src/plugin/file-inbound-chunk.ts +146 -0
  115. package/src/plugin/file-inbound-complete.ts +153 -0
  116. package/src/plugin/file-inbound-handlers.ts +19 -0
  117. package/src/plugin/file-inbound-init.ts +122 -0
  118. package/src/plugin/file-inbound-runtime.ts +51 -0
  119. package/src/plugin/file-inbound-state.ts +62 -0
  120. package/src/plugin/file-transfer-logs.ts +227 -0
  121. package/src/plugin/file-transfer-orchestrator-chunk.ts +135 -0
  122. package/src/plugin/file-transfer-orchestrator.ts +304 -0
  123. package/src/plugin/file-transfer-runtime-group.ts +102 -0
  124. package/src/plugin/file-transfer-send.ts +89 -0
  125. package/src/plugin/file-transfer-setup.ts +206 -0
  126. package/src/plugin/gateway-event-context.ts +41 -0
  127. package/src/plugin/gateway-runtime.ts +17 -4
  128. package/src/plugin/inbound-acceptance.ts +107 -0
  129. package/src/plugin/inbound-handlers.ts +248 -0
  130. package/src/plugin/inbound-surface-handlers-group.ts +152 -0
  131. package/src/plugin/media-dedupe-runtime.ts +90 -0
  132. package/src/plugin/media-orchestrators-runtime-group.ts +316 -0
  133. package/src/plugin/message-ack-runtime.ts +284 -0
  134. package/src/plugin/message-send.ts +16 -6
  135. package/src/plugin/messaging.ts +98 -36
  136. package/src/plugin/outbound.ts +50 -8
  137. package/src/plugin/outbox-ack-logs.ts +136 -0
  138. package/src/plugin/outbox-ack-outcome.ts +128 -0
  139. package/src/plugin/outbox-drain-ack.ts +145 -0
  140. package/src/plugin/outbox-drain-failure.ts +84 -0
  141. package/src/plugin/outbox-drain-loop.ts +554 -0
  142. package/src/plugin/outbox-drain-post-push.ts +159 -0
  143. package/src/plugin/outbox-drain-runtime.ts +141 -0
  144. package/src/plugin/outbox-drain-schedule.ts +116 -0
  145. package/src/plugin/outbox-file-push-flow.ts +69 -0
  146. package/src/plugin/outbox-push-route-runtime-group.ts +81 -0
  147. package/src/plugin/outbox-push.ts +267 -0
  148. package/src/plugin/outbox-route.ts +181 -0
  149. package/src/plugin/outbox-text-push-flow.ts +90 -0
  150. package/src/plugin/runtime-diagnostics-assembler.ts +183 -0
  151. package/src/plugin/runtime-diagnostics-helpers.ts +302 -0
  152. package/src/plugin/runtime-diagnostics-payload-builders.ts +171 -0
  153. package/src/plugin/runtime-diagnostics-snapshot.ts +31 -0
  154. package/src/plugin/setup.ts +33 -6
  155. package/src/plugin/state-store.ts +249 -0
  156. package/src/plugin/state-transient-runtime-group.ts +105 -0
  157. package/src/plugin/status-runtime.ts +251 -0
  158. package/src/plugin/status.ts +33 -7
  159. package/src/plugin/target-runtime.ts +141 -0
  160. package/src/plugin/target-status-runtime-group.ts +130 -0
  161. package/src/plugin/transient-state-runtime.ts +82 -0
  162. package/src/runtime/outbound-ack-timeout.ts +5 -3
  163. package/src/runtime/outbound-flags.ts +24 -8
  164. package/src/runtime/status-snapshots.ts +36 -7
  165. package/src/runtime/status-worker.ts +34 -4
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "id": "bncr",
3
+ "displayName": "Bncr",
3
4
  "channels": ["bncr"],
4
5
  "configSchema": {
5
6
  "type": "object",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmoxmo/bncr",
3
- "version": "0.3.6",
3
+ "version": "0.3.8",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -27,10 +27,12 @@
27
27
  "scripts": {
28
28
  "build": "npx -y esbuild@0.28.0 index.ts --bundle --platform=node --format=esm --target=node22 --packages=external --outfile=dist/index.js",
29
29
  "selfcheck": "node ./scripts/selfcheck.mjs",
30
- "test": "node --import ./tests/register-ts-hooks.mjs --test ./tests/*.test.mjs",
30
+ "test": "node --import ./tests/register-ts-hooks.mjs --test ./tests/**/*.test.mjs",
31
31
  "check-register-drift": "node ./scripts/check-register-drift.mjs",
32
32
  "check-pack": "node ./scripts/check-pack.mjs",
33
- "format:check": "biome format --check .",
33
+ "typecheck": "node ./node_modules/typescript/lib/tsc.js -p tsconfig.typecheck.json",
34
+ "fullcheck": "npm run typecheck && npm run check && npm test && npm run selfcheck && npm run check-pack && npm run format:check",
35
+ "format:check": "biome check --formatter-enabled=true --linter-enabled=false --assist-enabled=false .",
34
36
  "format": "biome format --write .",
35
37
  "lint": "biome lint .",
36
38
  "check": "biome check ."
@@ -40,8 +42,10 @@
40
42
  },
41
43
  "devDependencies": {
42
44
  "@biomejs/biome": "^2.4.16",
45
+ "@types/node": "^24.13.2",
43
46
  "esbuild": "^0.28.0",
44
- "openclaw": ">=2026.5.27"
47
+ "openclaw": ">=2026.5.27",
48
+ "typescript": "^6.0.3"
45
49
  },
46
50
  "openclaw": {
47
51
  "extensions": [
@@ -16,9 +16,15 @@ const requiredScriptFiles = [
16
16
  ];
17
17
 
18
18
  const requiredSourceFiles = [
19
+ 'src/bootstrap/channel-plugin-runtime.ts',
20
+ 'src/bootstrap/cli.ts',
21
+ 'src/bootstrap/register-runtime-helpers.ts',
22
+ 'src/bootstrap/register-runtime.ts',
23
+ 'src/bootstrap/runtime-discovery.ts',
24
+ 'src/bootstrap/runtime-loader.ts',
19
25
  'src/channel.ts',
20
- 'src/core/types.ts',
21
26
  'src/core/accounts.ts',
27
+ 'src/core/config-schema.ts',
22
28
  'src/core/connection-capability.ts',
23
29
  'src/core/connection-reachability.ts',
24
30
  'src/core/dead-letter-diagnostics.ts',
@@ -44,40 +50,46 @@ const requiredSourceFiles = [
44
50
  'src/core/outbox-text-push-guards.ts',
45
51
  'src/core/outbox-text-push-prep.ts',
46
52
  'src/core/outbox-text-push-success.ts',
53
+ 'src/core/permissions.ts',
47
54
  'src/core/persisted-outbox-entry.ts',
48
- 'src/core/targets.ts',
49
- 'src/core/status.ts',
50
- 'src/core/status-meta.ts',
51
- 'src/core/probe.ts',
52
- 'src/core/config-schema.ts',
53
55
  'src/core/policy.ts',
54
- 'src/core/permissions.ts',
56
+ 'src/core/probe.ts',
55
57
  'src/core/register-trace.ts',
58
+ 'src/core/status-meta.ts',
59
+ 'src/core/status.ts',
60
+ 'src/core/targets.ts',
61
+ 'src/core/types.ts',
56
62
  'src/messaging/inbound/commands.ts',
57
63
  'src/messaging/inbound/context-facts.ts',
58
- 'src/messaging/inbound/parse.ts',
59
- 'src/messaging/inbound/gate.ts',
64
+ 'src/messaging/inbound/dispatch-prep.ts',
60
65
  'src/messaging/inbound/dispatch.ts',
66
+ 'src/messaging/inbound/gate.ts',
61
67
  'src/messaging/inbound/last-route.ts',
68
+ 'src/messaging/inbound/media-url-download.ts',
62
69
  'src/messaging/inbound/native-command.ts',
63
70
  'src/messaging/inbound/native-reply-delivery.ts',
71
+ 'src/messaging/inbound/parse.ts',
72
+ 'src/messaging/inbound/remote-media.ts',
64
73
  'src/messaging/inbound/reply-config.ts',
74
+ 'src/messaging/inbound/reply-dispatch.ts',
65
75
  'src/messaging/inbound/runtime-compat.ts',
66
76
  'src/messaging/inbound/session-label.ts',
67
- 'src/messaging/outbound/send.ts',
68
- 'src/messaging/outbound/media.ts',
77
+ 'src/messaging/inbound/turn-context.ts',
69
78
  'src/messaging/outbound/actions.ts',
70
79
  'src/messaging/outbound/build-send-action.ts',
71
80
  'src/messaging/outbound/diagnostics.ts',
81
+ 'src/messaging/outbound/diagnostics-debug-builders.ts',
72
82
  'src/messaging/outbound/durable-message-adapter.ts',
73
83
  'src/messaging/outbound/durable-queue-adapter.ts',
74
84
  'src/messaging/outbound/media-dedupe.ts',
85
+ 'src/messaging/outbound/media.ts',
75
86
  'src/messaging/outbound/queue-selectors.ts',
76
87
  'src/messaging/outbound/reasons.ts',
77
88
  'src/messaging/outbound/reply-enqueue.ts',
78
89
  'src/messaging/outbound/reply-target-policy.ts',
79
90
  'src/messaging/outbound/retry-policy.ts',
80
91
  'src/messaging/outbound/send-params.ts',
92
+ 'src/messaging/outbound/send.ts',
81
93
  'src/messaging/outbound/session-route.ts',
82
94
  'src/messaging/outbound/target-resolver.ts',
83
95
  'src/openclaw/config-runtime.ts',
@@ -89,16 +101,73 @@ const requiredSourceFiles = [
89
101
  'src/openclaw/runtime-surface.ts',
90
102
  'src/openclaw/sdk-helpers.ts',
91
103
  'src/openclaw/session-route-runtime.ts',
104
+ 'src/plugin/ack-outbox-runtime-group.ts',
105
+ 'src/plugin/bridge-surface-handlers-group.ts',
106
+ 'src/plugin/bridge-surface-helpers.ts',
92
107
  'src/plugin/capabilities.ts',
108
+ 'src/plugin/channel-components.ts',
109
+ 'src/plugin/channel-inbound-helpers.ts',
110
+ 'src/plugin/channel-plugin-bridge-group.ts',
111
+ 'src/plugin/channel-plugin-surface-group.ts',
112
+ 'src/plugin/channel-runtime-constants.ts',
113
+ 'src/plugin/channel-runtime-builders.ts',
114
+ 'src/plugin/channel-send-runtime-group.ts',
115
+ 'src/plugin/channel-runtime-types.ts',
116
+ 'src/plugin/channel-send.ts',
117
+ 'src/plugin/channel-utils.ts',
93
118
  'src/plugin/config.ts',
119
+ 'src/plugin/connection-handlers.ts',
120
+ 'src/plugin/connection-state.ts',
121
+ 'src/plugin/connection-state-runtime-group.ts',
122
+ 'src/plugin/diagnostics-handlers.ts',
123
+ 'src/plugin/file-ack-runtime.ts',
124
+ 'src/plugin/file-inbound-abort.ts',
125
+ 'src/plugin/file-inbound-chunk.ts',
126
+ 'src/plugin/file-inbound-complete.ts',
127
+ 'src/plugin/file-inbound-handlers.ts',
128
+ 'src/plugin/file-inbound-init.ts',
129
+ 'src/plugin/file-inbound-runtime.ts',
130
+ 'src/plugin/file-inbound-state.ts',
131
+ 'src/plugin/file-transfer-logs.ts',
132
+ 'src/plugin/media-dedupe-runtime.ts',
133
+ 'src/plugin/file-transfer-orchestrator.ts',
134
+ 'src/plugin/media-orchestrators-runtime-group.ts',
135
+ 'src/plugin/file-transfer-runtime-group.ts',
136
+ 'src/plugin/file-transfer-send.ts',
137
+ 'src/plugin/file-transfer-setup.ts',
138
+ 'src/plugin/gateway-event-context.ts',
94
139
  'src/plugin/gateway-methods.ts',
95
140
  'src/plugin/gateway-runtime.ts',
141
+ 'src/plugin/inbound-acceptance.ts',
142
+ 'src/plugin/inbound-surface-handlers-group.ts',
143
+ 'src/plugin/inbound-handlers.ts',
144
+ 'src/plugin/message-ack-runtime.ts',
96
145
  'src/plugin/message-policy.ts',
97
146
  'src/plugin/message-send.ts',
98
147
  'src/plugin/messaging.ts',
99
148
  'src/plugin/meta.ts',
100
149
  'src/plugin/outbound.ts',
150
+ 'src/plugin/outbox-ack-logs.ts',
151
+ 'src/plugin/outbox-ack-outcome.ts',
152
+ 'src/plugin/outbox-drain-ack.ts',
153
+ 'src/plugin/outbox-drain-failure.ts',
154
+ 'src/plugin/outbox-drain-loop.ts',
155
+ 'src/plugin/outbox-drain-post-push.ts',
156
+ 'src/plugin/outbox-drain-runtime.ts',
157
+ 'src/plugin/outbox-drain-schedule.ts',
158
+ 'src/plugin/outbox-file-push-flow.ts',
159
+ 'src/plugin/outbox-push-route-runtime-group.ts',
160
+ 'src/plugin/outbox-push.ts',
161
+ 'src/plugin/outbox-route.ts',
162
+ 'src/plugin/outbox-text-push-flow.ts',
163
+ 'src/plugin/runtime-diagnostics-snapshot.ts',
101
164
  'src/plugin/setup.ts',
165
+ 'src/plugin/state-transient-runtime-group.ts',
166
+ 'src/plugin/state-store.ts',
167
+ 'src/plugin/target-runtime.ts',
168
+ 'src/plugin/target-status-runtime-group.ts',
169
+ 'src/plugin/transient-state-runtime.ts',
170
+ 'src/plugin/status-runtime.ts',
102
171
  'src/plugin/status.ts',
103
172
  'src/runtime/log-dedupe.ts',
104
173
  'src/runtime/outbound-ack-timeout.ts',
@@ -128,29 +197,35 @@ const [pack] = JSON.parse(output);
128
197
  const packedFiles = new Set((pack?.files ?? []).map((file) => file.path));
129
198
  const missing = requiredPackFiles.filter((file) => !packedFiles.has(file));
130
199
  const channelSource = fs.readFileSync(path.join(root, 'src/channel.ts'), 'utf8');
200
+ const channelPluginSurfaceSource = fs.readFileSync(
201
+ path.join(root, 'src/plugin/channel-plugin-surface-group.ts'),
202
+ 'utf8',
203
+ );
131
204
  const messagePolicySource = fs.readFileSync(
132
205
  path.join(root, 'src/plugin/message-policy.ts'),
133
206
  'utf8',
134
207
  );
135
208
  const messageSendSource = fs.readFileSync(path.join(root, 'src/plugin/message-send.ts'), 'utf8');
209
+ const channelPluginSurfaceCombined = `${channelSource}\n${channelPluginSurfaceSource}`;
136
210
  const channelMessageChecks = {
137
- registered: channelSource.includes('message: {'),
211
+ registered: channelPluginSurfaceCombined.includes('message: {'),
138
212
  text:
139
- channelSource.includes('createBncrMessageSend') &&
213
+ channelPluginSurfaceCombined.includes('createBncrMessageSend') &&
140
214
  messageSendSource.includes('channelMessageSendText'),
141
215
  media:
142
- channelSource.includes('createBncrMessageSend') &&
216
+ channelPluginSurfaceCombined.includes('createBncrMessageSend') &&
143
217
  messageSendSource.includes('channelMessageSendMedia'),
144
218
  payload:
145
- channelSource.includes('createBncrMessageSend') &&
219
+ channelPluginSurfaceCombined.includes('createBncrMessageSend') &&
146
220
  messageSendSource.includes('channelMessageSendPayload'),
147
221
  manualAck:
148
- channelSource.includes('BNCR_MESSAGE_RECEIVE_POLICY') &&
222
+ channelPluginSurfaceCombined.includes('BNCR_MESSAGE_RECEIVE_POLICY') &&
149
223
  messagePolicySource.includes("defaultAckPolicy: 'manual'") &&
150
224
  messagePolicySource.includes("supportedAckPolicies: ['manual']"),
151
- genericActionsPreserved: channelSource.includes('actions: messageActions'),
225
+ genericActionsPreserved: channelPluginSurfaceCombined.includes('actions: messageActions'),
152
226
  noDurableFinal:
153
- !channelSource.includes('durableFinal:') && !messagePolicySource.includes('durableFinal:'),
227
+ !channelPluginSurfaceCombined.includes('durableFinal:') &&
228
+ !messagePolicySource.includes('durableFinal:'),
154
229
  };
155
230
  const channelMessageOk = Object.values(channelMessageChecks).every(Boolean);
156
231
 
@@ -16,6 +16,7 @@ const DEFAULT_OPTIONS = {
16
16
  intervalSec: 15,
17
17
  accountId: 'Primary',
18
18
  gatewayBin: 'openclaw',
19
+ gatewayTimeoutMs: 30_000,
19
20
  };
20
21
 
21
22
  export function parseCheckRegisterDriftOptions(args, defaults = DEFAULT_OPTIONS) {
@@ -28,6 +29,8 @@ export function parseCheckRegisterDriftOptions(args, defaults = DEFAULT_OPTIONS)
28
29
  options.intervalSec = readNumber(args[++i], options.intervalSec);
29
30
  else if (arg === '--account-id') options.accountId = readText(args[++i], options.accountId);
30
31
  else if (arg === '--gateway-bin') options.gatewayBin = readText(args[++i], options.gatewayBin);
32
+ else if (arg === '--gateway-timeout-ms')
33
+ options.gatewayTimeoutMs = readNumber(args[++i], options.gatewayTimeoutMs);
31
34
  else if (arg === '--help' || arg === '-h') options.help = true;
32
35
  }
33
36
 
@@ -36,25 +39,44 @@ export function parseCheckRegisterDriftOptions(args, defaults = DEFAULT_OPTIONS)
36
39
 
37
40
  const printHelp = () => {
38
41
  console.log(
39
- 'Usage: node ./scripts/check-register-drift.mjs [--duration-sec 300] [--interval-sec 15] [--account-id Primary] [--gateway-bin openclaw]\n\nSamples bncr.diagnostics over time and reports whether register counters drift after warmup.',
42
+ 'Usage: node ./scripts/check-register-drift.mjs [--duration-sec 300] [--interval-sec 15] [--account-id Primary] [--gateway-bin openclaw] [--gateway-timeout-ms 30000]\n\nSamples bncr.diagnostics over time and reports whether register counters drift after warmup.',
40
43
  );
41
44
  };
42
45
 
43
46
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
44
47
 
48
+ const summarizeExecOutput = (value) =>
49
+ String(value || '')
50
+ .replace(/\s+/g, ' ')
51
+ .trim()
52
+ .slice(0, 500);
53
+
45
54
  const fetchDiagnostics = (options) => {
46
- const raw = execFileSync(
47
- options.gatewayBin,
48
- [
49
- 'gateway',
50
- 'call',
51
- 'bncr.diagnostics',
52
- '--json',
53
- '--params',
54
- JSON.stringify({ accountId: options.accountId }),
55
- ],
56
- { encoding: 'utf8' },
57
- );
55
+ let raw;
56
+ try {
57
+ raw = execFileSync(
58
+ options.gatewayBin,
59
+ [
60
+ 'gateway',
61
+ 'call',
62
+ 'bncr.diagnostics',
63
+ '--json',
64
+ '--timeout',
65
+ String(options.gatewayTimeoutMs),
66
+ '--params',
67
+ JSON.stringify({ accountId: options.accountId }),
68
+ ],
69
+ { encoding: 'utf8' },
70
+ );
71
+ } catch (error) {
72
+ const detail = [
73
+ `gatewayTimeoutMs=${options.gatewayTimeoutMs}`,
74
+ `status=${error?.status ?? 'unknown'}`,
75
+ `stderr=${summarizeExecOutput(error?.stderr) || '-'}`,
76
+ `stdout=${summarizeExecOutput(error?.stdout) || '-'}`,
77
+ ].join(' ');
78
+ throw new Error(`bncr.diagnostics gateway call failed (${detail})`, { cause: error });
79
+ }
58
80
  const parsed = JSON.parse(raw);
59
81
  const reg = parsed?.diagnostics?.register || {};
60
82
  const summary = reg?.traceSummary || {};
@@ -12,8 +12,14 @@ const requiredRootFiles = ['index.ts', 'openclaw.plugin.json'];
12
12
 
13
13
  const requiredSourceFiles = [
14
14
  'src/channel.ts',
15
- 'src/core/types.ts',
15
+ 'src/bootstrap/channel-plugin-runtime.ts',
16
+ 'src/bootstrap/cli.ts',
17
+ 'src/bootstrap/register-runtime-helpers.ts',
18
+ 'src/bootstrap/register-runtime.ts',
19
+ 'src/bootstrap/runtime-discovery.ts',
20
+ 'src/bootstrap/runtime-loader.ts',
16
21
  'src/core/accounts.ts',
22
+ 'src/core/config-schema.ts',
17
23
  'src/core/connection-capability.ts',
18
24
  'src/core/connection-reachability.ts',
19
25
  'src/core/dead-letter-diagnostics.ts',
@@ -39,40 +45,46 @@ const requiredSourceFiles = [
39
45
  'src/core/outbox-text-push-guards.ts',
40
46
  'src/core/outbox-text-push-prep.ts',
41
47
  'src/core/outbox-text-push-success.ts',
48
+ 'src/core/permissions.ts',
42
49
  'src/core/persisted-outbox-entry.ts',
43
- 'src/core/targets.ts',
44
- 'src/core/status.ts',
45
- 'src/core/status-meta.ts',
46
- 'src/core/probe.ts',
47
- 'src/core/config-schema.ts',
48
50
  'src/core/policy.ts',
49
- 'src/core/permissions.ts',
51
+ 'src/core/probe.ts',
50
52
  'src/core/register-trace.ts',
53
+ 'src/core/status-meta.ts',
54
+ 'src/core/status.ts',
55
+ 'src/core/targets.ts',
56
+ 'src/core/types.ts',
51
57
  'src/messaging/inbound/commands.ts',
52
58
  'src/messaging/inbound/context-facts.ts',
53
- 'src/messaging/inbound/parse.ts',
54
- 'src/messaging/inbound/gate.ts',
59
+ 'src/messaging/inbound/dispatch-prep.ts',
55
60
  'src/messaging/inbound/dispatch.ts',
61
+ 'src/messaging/inbound/gate.ts',
56
62
  'src/messaging/inbound/last-route.ts',
63
+ 'src/messaging/inbound/media-url-download.ts',
57
64
  'src/messaging/inbound/native-command.ts',
58
65
  'src/messaging/inbound/native-reply-delivery.ts',
66
+ 'src/messaging/inbound/parse.ts',
67
+ 'src/messaging/inbound/remote-media.ts',
59
68
  'src/messaging/inbound/reply-config.ts',
69
+ 'src/messaging/inbound/reply-dispatch.ts',
60
70
  'src/messaging/inbound/runtime-compat.ts',
61
71
  'src/messaging/inbound/session-label.ts',
62
- 'src/messaging/outbound/send.ts',
63
- 'src/messaging/outbound/media.ts',
72
+ 'src/messaging/inbound/turn-context.ts',
64
73
  'src/messaging/outbound/actions.ts',
65
74
  'src/messaging/outbound/build-send-action.ts',
66
75
  'src/messaging/outbound/diagnostics.ts',
76
+ 'src/messaging/outbound/diagnostics-debug-builders.ts',
67
77
  'src/messaging/outbound/durable-message-adapter.ts',
68
78
  'src/messaging/outbound/durable-queue-adapter.ts',
69
79
  'src/messaging/outbound/media-dedupe.ts',
80
+ 'src/messaging/outbound/media.ts',
70
81
  'src/messaging/outbound/queue-selectors.ts',
71
82
  'src/messaging/outbound/reasons.ts',
72
83
  'src/messaging/outbound/reply-enqueue.ts',
73
84
  'src/messaging/outbound/reply-target-policy.ts',
74
85
  'src/messaging/outbound/retry-policy.ts',
75
86
  'src/messaging/outbound/send-params.ts',
87
+ 'src/messaging/outbound/send.ts',
76
88
  'src/messaging/outbound/session-route.ts',
77
89
  'src/messaging/outbound/target-resolver.ts',
78
90
  'src/openclaw/config-runtime.ts',
@@ -84,16 +96,73 @@ const requiredSourceFiles = [
84
96
  'src/openclaw/runtime-surface.ts',
85
97
  'src/openclaw/sdk-helpers.ts',
86
98
  'src/openclaw/session-route-runtime.ts',
99
+ 'src/plugin/ack-outbox-runtime-group.ts',
100
+ 'src/plugin/bridge-surface-handlers-group.ts',
101
+ 'src/plugin/bridge-surface-helpers.ts',
87
102
  'src/plugin/capabilities.ts',
103
+ 'src/plugin/channel-components.ts',
104
+ 'src/plugin/channel-inbound-helpers.ts',
105
+ 'src/plugin/channel-plugin-bridge-group.ts',
106
+ 'src/plugin/channel-plugin-surface-group.ts',
107
+ 'src/plugin/channel-runtime-constants.ts',
108
+ 'src/plugin/channel-runtime-builders.ts',
109
+ 'src/plugin/channel-send-runtime-group.ts',
110
+ 'src/plugin/channel-runtime-types.ts',
111
+ 'src/plugin/channel-send.ts',
112
+ 'src/plugin/channel-utils.ts',
88
113
  'src/plugin/config.ts',
114
+ 'src/plugin/connection-handlers.ts',
115
+ 'src/plugin/connection-state.ts',
116
+ 'src/plugin/connection-state-runtime-group.ts',
117
+ 'src/plugin/diagnostics-handlers.ts',
118
+ 'src/plugin/file-ack-runtime.ts',
119
+ 'src/plugin/file-inbound-abort.ts',
120
+ 'src/plugin/file-inbound-chunk.ts',
121
+ 'src/plugin/file-inbound-complete.ts',
122
+ 'src/plugin/file-inbound-handlers.ts',
123
+ 'src/plugin/file-inbound-init.ts',
124
+ 'src/plugin/file-inbound-runtime.ts',
125
+ 'src/plugin/file-inbound-state.ts',
126
+ 'src/plugin/file-transfer-logs.ts',
127
+ 'src/plugin/media-dedupe-runtime.ts',
128
+ 'src/plugin/file-transfer-orchestrator.ts',
129
+ 'src/plugin/media-orchestrators-runtime-group.ts',
130
+ 'src/plugin/file-transfer-runtime-group.ts',
131
+ 'src/plugin/file-transfer-send.ts',
132
+ 'src/plugin/file-transfer-setup.ts',
133
+ 'src/plugin/gateway-event-context.ts',
89
134
  'src/plugin/gateway-methods.ts',
90
135
  'src/plugin/gateway-runtime.ts',
136
+ 'src/plugin/inbound-acceptance.ts',
137
+ 'src/plugin/inbound-surface-handlers-group.ts',
138
+ 'src/plugin/inbound-handlers.ts',
139
+ 'src/plugin/message-ack-runtime.ts',
91
140
  'src/plugin/message-policy.ts',
92
141
  'src/plugin/message-send.ts',
93
142
  'src/plugin/messaging.ts',
94
143
  'src/plugin/meta.ts',
95
144
  'src/plugin/outbound.ts',
145
+ 'src/plugin/outbox-ack-logs.ts',
146
+ 'src/plugin/outbox-ack-outcome.ts',
147
+ 'src/plugin/outbox-drain-ack.ts',
148
+ 'src/plugin/outbox-drain-failure.ts',
149
+ 'src/plugin/outbox-drain-loop.ts',
150
+ 'src/plugin/outbox-drain-post-push.ts',
151
+ 'src/plugin/outbox-drain-runtime.ts',
152
+ 'src/plugin/outbox-drain-schedule.ts',
153
+ 'src/plugin/outbox-file-push-flow.ts',
154
+ 'src/plugin/outbox-push-route-runtime-group.ts',
155
+ 'src/plugin/outbox-push.ts',
156
+ 'src/plugin/outbox-route.ts',
157
+ 'src/plugin/outbox-text-push-flow.ts',
158
+ 'src/plugin/runtime-diagnostics-snapshot.ts',
96
159
  'src/plugin/setup.ts',
160
+ 'src/plugin/state-transient-runtime-group.ts',
161
+ 'src/plugin/state-store.ts',
162
+ 'src/plugin/target-runtime.ts',
163
+ 'src/plugin/target-status-runtime-group.ts',
164
+ 'src/plugin/transient-state-runtime.ts',
165
+ 'src/plugin/status-runtime.ts',
97
166
  'src/plugin/status.ts',
98
167
  'src/runtime/log-dedupe.ts',
99
168
  'src/runtime/outbound-ack-timeout.ts',
@@ -0,0 +1,81 @@
1
+ type ChannelModule = typeof import('../channel.ts');
2
+ type BridgeSingleton = ReturnType<ChannelModule['createBncrBridge']>;
3
+ type ChannelPlugin = ReturnType<ChannelModule['createBncrChannelPlugin']>;
4
+
5
+ type LoadedRuntime = {
6
+ createBncrBridge: ChannelModule['createBncrBridge'];
7
+ createBncrChannelPlugin: ChannelModule['createBncrChannelPlugin'];
8
+ };
9
+
10
+ export function createDynamicChannelPlugin(args: {
11
+ loaded: LoadedRuntime;
12
+ getCurrentBridge: () => BridgeSingleton;
13
+ }): ChannelPlugin {
14
+ const { loaded, getCurrentBridge } = args;
15
+ const base = loaded.createBncrChannelPlugin(() => getCurrentBridge());
16
+ const plugin = { ...base } as ChannelPlugin;
17
+ const outbound = base.outbound as ChannelPlugin['outbound'];
18
+ const baseStatus = base.status;
19
+ const baseGateway = base.gateway;
20
+
21
+ type StatusBuildChannelSummaryArgs = Parameters<typeof baseStatus.buildChannelSummary>[0];
22
+ type StatusBuildAccountSnapshotArgs = Parameters<typeof baseStatus.buildAccountSnapshot>[0];
23
+ type StatusResolveAccountStateArgs = Parameters<typeof baseStatus.resolveAccountState>[0];
24
+ type GatewayStartAccountArgs = Parameters<NonNullable<typeof baseGateway.startAccount>>[0];
25
+ type GatewayStopAccountArgs = Parameters<NonNullable<typeof baseGateway.stopAccount>>[0];
26
+
27
+ plugin.outbound = {
28
+ ...outbound,
29
+ sendText: (async (ctx: Parameters<typeof outbound.sendText>[0]) =>
30
+ (await getCurrentBridge().channelSendText(ctx)) as Awaited<
31
+ ReturnType<typeof outbound.sendText>
32
+ >) as typeof outbound.sendText,
33
+ sendMedia: (async (ctx: Parameters<typeof outbound.sendMedia>[0]) =>
34
+ (await getCurrentBridge().channelSendMedia(ctx)) as Awaited<
35
+ ReturnType<typeof outbound.sendMedia>
36
+ >) as typeof outbound.sendMedia,
37
+ };
38
+
39
+ plugin.status = {
40
+ ...baseStatus,
41
+ buildChannelSummary: async ({ defaultAccountId }: StatusBuildChannelSummaryArgs) =>
42
+ getCurrentBridge().getChannelSummary(defaultAccountId || 'Primary'),
43
+ buildAccountSnapshot: async ({ account, runtime }: StatusBuildAccountSnapshotArgs) => {
44
+ const bridgeNow = getCurrentBridge();
45
+ return baseStatus.buildAccountSnapshot({
46
+ account,
47
+ runtime: runtime || bridgeNow.getAccountRuntimeSnapshot(account?.accountId || 'Primary'),
48
+ });
49
+ },
50
+ resolveAccountState: ({
51
+ enabled,
52
+ configured,
53
+ account,
54
+ cfg,
55
+ runtime,
56
+ }: StatusResolveAccountStateArgs) => {
57
+ const bridgeNow = getCurrentBridge();
58
+ return baseStatus.resolveAccountState({
59
+ enabled,
60
+ configured,
61
+ account,
62
+ cfg,
63
+ runtime: runtime || bridgeNow.getAccountRuntimeSnapshot(account?.accountId || 'Primary'),
64
+ });
65
+ },
66
+ };
67
+
68
+ plugin.gateway = {
69
+ ...baseGateway,
70
+ startAccount: (ctx: GatewayStartAccountArgs) =>
71
+ getCurrentBridge().channelStartAccount(
72
+ ctx as Parameters<BridgeSingleton['channelStartAccount']>[0],
73
+ ),
74
+ stopAccount: (ctx: GatewayStopAccountArgs) =>
75
+ getCurrentBridge().channelStopAccount(
76
+ ctx as Parameters<BridgeSingleton['channelStopAccount']>[0],
77
+ ),
78
+ };
79
+
80
+ return plugin;
81
+ }
@@ -0,0 +1,97 @@
1
+ import type { OpenClawPluginApi } from 'openclaw/plugin-sdk/core';
2
+ import type { BncrConfigSchema } from '../core/config-schema.ts';
3
+ import {
4
+ getOpenClawRuntimeConfig,
5
+ mutateOpenClawRuntimeConfigFile,
6
+ } from '../openclaw/config-runtime.ts';
7
+
8
+ type BncrCliProgramLike = {
9
+ command: (name: string) => BncrCliProgramLike;
10
+ description: (text: string) => BncrCliProgramLike;
11
+ action: (handler: () => Promise<void> | void) => BncrCliProgramLike;
12
+ };
13
+
14
+ type BncrCliRegistrarLike = {
15
+ registerCli?: (
16
+ register: (ctx: { program: BncrCliProgramLike }) => void,
17
+ options?: { commands?: string[] },
18
+ ) => void;
19
+ };
20
+
21
+ type BncrCliConfigRoot = {
22
+ channels?: Record<string, unknown> & {
23
+ bncr?: Record<string, unknown> & {
24
+ enabled?: boolean;
25
+ allowTool?: boolean;
26
+ };
27
+ };
28
+ };
29
+
30
+ const isPlainObject = (value: unknown): value is Record<string, unknown> =>
31
+ !!value && typeof value === 'object' && !Array.isArray(value);
32
+
33
+ export type BncrRegistrationApi = OpenClawPluginApi &
34
+ BncrCliRegistrarLike & {
35
+ registrationMode?: string;
36
+ configSchema?: typeof BncrConfigSchema;
37
+ };
38
+
39
+ export function registerBncrCli(api: BncrRegistrationApi) {
40
+ if (typeof api.registerCli !== 'function') return;
41
+ api.registerCli(
42
+ ({ program }: { program: BncrCliProgramLike }) => {
43
+ const bncr = program.command('bncr').description('Bncr channel utilities');
44
+ bncr
45
+ .command('miniconfig')
46
+ .description(
47
+ 'Seed minimal channels.bncr config (adds enabled=true and allowTool=false only when missing)',
48
+ )
49
+ .action(async () => {
50
+ const cfg = (getOpenClawRuntimeConfig(api) as BncrCliConfigRoot | null | undefined) || {};
51
+ const channels = isPlainObject(cfg.channels) ? cfg.channels : {};
52
+ const existing = isPlainObject(channels.bncr) ? channels.bncr : {};
53
+ const added: string[] = [];
54
+
55
+ if (existing.enabled === undefined) {
56
+ added.push('enabled=true');
57
+ }
58
+
59
+ if (existing.allowTool === undefined) {
60
+ added.push('allowTool=false');
61
+ }
62
+
63
+ if (added.length === 0) {
64
+ console.log('Minimal bncr config already present. No changes made.');
65
+ return;
66
+ }
67
+
68
+ await mutateOpenClawRuntimeConfigFile(api, {
69
+ afterWrite: { mode: 'auto' },
70
+ mutate(draft: Record<string, unknown>) {
71
+ if (!isPlainObject(draft.channels)) draft.channels = {};
72
+ const draftChannels = draft.channels as Record<string, unknown>;
73
+ const draftExisting = isPlainObject(draftChannels.bncr) ? draftChannels.bncr : {};
74
+ const draftBncrCfg: Record<string, unknown> = { ...draftExisting };
75
+
76
+ if (draftBncrCfg.enabled === undefined) {
77
+ draftBncrCfg.enabled = true;
78
+ }
79
+
80
+ if (draftBncrCfg.allowTool === undefined) {
81
+ draftBncrCfg.allowTool = false;
82
+ }
83
+
84
+ draftChannels.bncr = draftBncrCfg;
85
+ },
86
+ });
87
+ console.log('Seeded minimal bncr config at channels.bncr.');
88
+ console.log(`Added missing fields: ${added.join(', ')}`);
89
+ console.log('Gateway will apply the config using the host afterWrite policy.');
90
+ });
91
+ },
92
+ { commands: ['bncr'] },
93
+ );
94
+ }
95
+
96
+ export const shouldSkipNonRuntimeRegister = (mode?: string) =>
97
+ mode === 'cli-metadata' || mode === 'discovery';