@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
@@ -0,0 +1,302 @@
1
+ import {
2
+ buildDeadLetterDiagnostics as buildDeadLetterDiagnosticsFromRuntime,
3
+ filterDeadLetterEntries as filterDeadLetterEntriesFromRuntime,
4
+ } from '../core/dead-letter-diagnostics.ts';
5
+ import type {
6
+ RegisterDriftSnapshot,
7
+ RegisterTraceEntry,
8
+ RegisterTraceSummary,
9
+ } from '../core/register-trace.ts';
10
+ import type { buildIntegratedDiagnostics as buildIntegratedDiagnosticsFromRuntime } from '../core/status.ts';
11
+ import type {
12
+ BncrAckObservability,
13
+ BncrConnection,
14
+ BncrOutboxQueueDiagnostics,
15
+ OutboxEntry,
16
+ } from '../core/types.ts';
17
+ import { buildBncrRuntimeAckObservability } from '../runtime/outbound-ack-timeout.ts';
18
+ import {
19
+ buildBncrActiveConnectionDebugList,
20
+ buildBncrDeadLetterSummaryMessage,
21
+ } from './runtime-diagnostics-payload-builders.ts';
22
+
23
+ type RuntimeStatusInput = Parameters<typeof buildIntegratedDiagnosticsFromRuntime>[0];
24
+ type IntegratedDiagnostics = ReturnType<typeof buildIntegratedDiagnosticsFromRuntime>;
25
+ type BncrConnectionDebugView = BncrConnection & {
26
+ outboundReadyUntil?: number;
27
+ preferredForOutboundUntil?: number;
28
+ lastAckOkAt?: number;
29
+ lastPushTimeoutAt?: number;
30
+ pushFailureScore?: number;
31
+ };
32
+
33
+ export type ExtendedDiagnosticsAssemblerRuntime = {
34
+ normalizeAccountId: (accountId: string) => string;
35
+ buildIntegratedDiagnostics: (
36
+ accountId: string,
37
+ runtimeStatusInput?: RuntimeStatusInput,
38
+ ) => IntegratedDiagnostics;
39
+ buildOutboxDiagnostics: (accountId: string) => BncrOutboxQueueDiagnostics;
40
+ buildRuntimeAckObservability: (accountId: string) => BncrAckObservability;
41
+ getCounter: (map: Map<string, number>, accountId: string) => number;
42
+ prePushGuardSkipCountByAccount: Map<string, number>;
43
+ lastPrePushGuardSkipAtByAccount: Map<string, number>;
44
+ lastPrePushGuardSkipReasonByAccount: Map<string, string>;
45
+ hasGatewayContext: () => boolean;
46
+ buildRuntimeSurfaceDiagnostics: () => ReturnType<
47
+ typeof import('../openclaw/runtime-surface.ts')['buildOpenClawChannelRuntimeSurfaceDiagnostics']
48
+ >;
49
+ getRegisterRuntime: () => {
50
+ bridgeId: string;
51
+ gatewayPid: number;
52
+ pluginVersion: string | null;
53
+ pluginSource: string | null;
54
+ lastApiInstanceId: string | null;
55
+ lastRegistryFingerprint: string | null;
56
+ registerCount: number;
57
+ firstRegisterAt: number | null;
58
+ lastRegisterAt: number | null;
59
+ lastApiRebindAt: number | null;
60
+ apiGeneration: number;
61
+ registerTraceRecent: RegisterTraceEntry[];
62
+ lastDriftSnapshot: RegisterDriftSnapshot | null;
63
+ };
64
+ buildRegisterTraceSummary: () => RegisterTraceSummary;
65
+ activeConnectionCount: (accountId: string) => number;
66
+ getConnectionRuntime: () => {
67
+ lastGatewayContextAt: number | null;
68
+ primaryLeaseId: string | null;
69
+ connectionEpoch: number;
70
+ acceptedConnections: number;
71
+ lastConnectAt: number | null;
72
+ lastDisconnectAt: number | null;
73
+ lastActivityAtGlobal: number | null;
74
+ lastInboundAtGlobal: number | null;
75
+ lastAckAtGlobal: number | null;
76
+ recentConnections: Map<
77
+ string,
78
+ { epoch: number; connectedAt: number; lastActivityAt: number | null; isPrimary: boolean }
79
+ >;
80
+ };
81
+ getOutboundRuntime: () => {
82
+ outboundEnqueueCountByAccount: Map<string, number>;
83
+ lastOutboundEnqueueAtByAccount: Map<string, number>;
84
+ };
85
+ buildDeadLetterDiagnostics: (
86
+ accountId: string,
87
+ ) => ReturnType<typeof buildBncrDeadLetterDiagnosticsSnapshot>;
88
+ bridgeVersion: number;
89
+ staleCounters: {
90
+ staleConnect: number;
91
+ staleInbound: number;
92
+ staleActivity: number;
93
+ staleAck: number;
94
+ staleFileInit: number;
95
+ staleFileChunk: number;
96
+ staleFileComplete: number;
97
+ staleFileAbort: number;
98
+ lastStaleAt: number | null;
99
+ };
100
+ now: () => number;
101
+ };
102
+
103
+ export type ExtendedDiagnosticsAssemblerOptions = {
104
+ runtimeStatusInput?: RuntimeStatusInput;
105
+ integratedDiagnostics?: IntegratedDiagnostics;
106
+ };
107
+
108
+ export function buildBncrDeadLetterDiagnosticsSnapshot(args: {
109
+ accountId: string;
110
+ entries: OutboxEntry[];
111
+ allAccountsTotal: number;
112
+ sinceStart: number;
113
+ cappedAt: number;
114
+ }) {
115
+ return buildDeadLetterDiagnosticsFromRuntime({
116
+ entries: args.entries,
117
+ allAccountsTotal: args.allAccountsTotal,
118
+ sinceStart: args.sinceStart,
119
+ cappedAt: args.cappedAt,
120
+ });
121
+ }
122
+
123
+ export function createBncrOutboxDiagnosticsHelpers(runtime: {
124
+ normalizeAccountId: (accountId: string) => string;
125
+ outboxValues: () => Iterable<OutboxEntry>;
126
+ pendingAllAccounts: () => number;
127
+ resolvePushConnIds: (accountId: string) => Set<string>;
128
+ buildOutboxQueueDiagnostics: typeof import('../messaging/outbound/diagnostics.ts').buildOutboxQueueDiagnostics;
129
+ buildBncrOutboxQueueDiagnosticsInput: typeof import('./runtime-diagnostics-payload-builders.ts').buildBncrOutboxQueueDiagnosticsInput;
130
+ }) {
131
+ const buildOutboxDiagnostics = (accountId: string) => {
132
+ const acc = runtime.normalizeAccountId(accountId);
133
+ return runtime.buildOutboxQueueDiagnostics(
134
+ runtime.buildBncrOutboxQueueDiagnosticsInput({
135
+ accountId: acc,
136
+ outboxEntries: runtime.outboxValues(),
137
+ pendingAllAccounts: runtime.pendingAllAccounts(),
138
+ pushConnIds: runtime.resolvePushConnIds(acc),
139
+ }),
140
+ );
141
+ };
142
+
143
+ return { buildOutboxDiagnostics };
144
+ }
145
+
146
+ export function createBncrRuntimeAckObservabilityBuilder(runtime: {
147
+ normalizeAccountId: (accountId: string) => string;
148
+ getCounter: (map: Map<string, number>, accountId: string) => number;
149
+ ackTimeoutCountByAccount: Map<string, number>;
150
+ lateAckOkCountByAccount: Map<string, number>;
151
+ lastLateAckPushLatencyMsByAccount: Map<string, number>;
152
+ lastLateAckOkByAccount: Map<string, number>;
153
+ adaptiveAckRecoveryOkCountByAccount: Map<string, number>;
154
+ lastAckOkByAccount: Map<string, number>;
155
+ lastAckTimeoutByAccount: Map<string, number>;
156
+ lastAckQueueLatencyMsByAccount: Map<string, number>;
157
+ lastAckPushLatencyMsByAccount: Map<string, number>;
158
+ lastLateAckQueueLatencyMsByAccount: Map<string, number>;
159
+ adaptiveAckTimeoutEnabled: boolean;
160
+ defaultAckTimeoutMs: number;
161
+ resolveMessageAckTimeoutMs: (accountId: string) => number;
162
+ minAckTimeoutMs: number;
163
+ maxAckTimeoutMs: number;
164
+ lateAckObservationTtlMs: number;
165
+ recoveryOkThreshold: number;
166
+ now: () => number;
167
+ }) {
168
+ return (accountId: string): BncrAckObservability => {
169
+ const acc = runtime.normalizeAccountId(accountId);
170
+ const recentAckTimeoutCount = runtime.getCounter(runtime.ackTimeoutCountByAccount, acc);
171
+ const lateAckOkCount = runtime.getCounter(runtime.lateAckOkCountByAccount, acc);
172
+ const lastLateAckPushLatencyMs = runtime.lastLateAckPushLatencyMsByAccount.get(acc) || null;
173
+ const lastLateAckOkAt = runtime.lastLateAckOkByAccount.get(acc) || null;
174
+ const nowMs = runtime.now();
175
+ const adaptiveAckRecoveryOkCount = runtime.getCounter(
176
+ runtime.adaptiveAckRecoveryOkCountByAccount,
177
+ acc,
178
+ );
179
+ return buildBncrRuntimeAckObservability({
180
+ lastAckOkAt: runtime.lastAckOkByAccount.get(acc) || null,
181
+ lastAckTimeoutAt: runtime.lastAckTimeoutByAccount.get(acc) || null,
182
+ recentAckTimeoutCount,
183
+ lateAckOkCount,
184
+ lastLateAckOkAt,
185
+ adaptiveAckRecoveryOkCount,
186
+ lastAckQueueLatencyMs: runtime.lastAckQueueLatencyMsByAccount.get(acc) || null,
187
+ lastAckPushLatencyMs: runtime.lastAckPushLatencyMsByAccount.get(acc) || null,
188
+ lastLateAckQueueLatencyMs: runtime.lastLateAckQueueLatencyMsByAccount.get(acc) || null,
189
+ lastLateAckPushLatencyMs,
190
+ adaptiveAckTimeoutEnabled: runtime.adaptiveAckTimeoutEnabled,
191
+ defaultAckTimeoutMs: runtime.defaultAckTimeoutMs,
192
+ currentAckTimeoutMs: runtime.resolveMessageAckTimeoutMs(acc),
193
+ minAckTimeoutMs: runtime.minAckTimeoutMs,
194
+ maxAckTimeoutMs: runtime.maxAckTimeoutMs,
195
+ lateAckObservationTtlMs: runtime.lateAckObservationTtlMs,
196
+ recoveryOkThreshold: runtime.recoveryOkThreshold,
197
+ nowMs,
198
+ });
199
+ };
200
+ }
201
+
202
+ export function createBncrDeadLetterDiagnosticsHelpers(runtime: {
203
+ normalizeAccountId: (accountId: string) => string;
204
+ getDeadLetterEntries: () => OutboxEntry[];
205
+ maxDeadLetterEntries: number;
206
+ getCounter: (map: Map<string, number>, accountId: string) => number;
207
+ deadLetterSinceStartByAccount: Map<string, number>;
208
+ getAccountDeadLetterEntries: (accountId: string) => OutboxEntry[];
209
+ logInfo: (scope: string, message: string, options?: { debugOnly?: boolean }) => void;
210
+ logInfoDedup: (
211
+ scope: string,
212
+ message: string,
213
+ options: { key: string; sig: string; windowMs?: number },
214
+ ) => void;
215
+ }) {
216
+ const buildDeadLetterDiagnostics = (accountId: string) => {
217
+ const acc = runtime.normalizeAccountId(accountId);
218
+ return buildBncrDeadLetterDiagnosticsSnapshot({
219
+ accountId: acc,
220
+ entries: runtime.getAccountDeadLetterEntries(acc),
221
+ allAccountsTotal: runtime.getDeadLetterEntries().length,
222
+ sinceStart: runtime.getCounter(runtime.deadLetterSinceStartByAccount, acc),
223
+ cappedAt: runtime.maxDeadLetterEntries,
224
+ });
225
+ };
226
+
227
+ const logDeadLetterSummary = (
228
+ accountId: string,
229
+ options?: { force?: boolean; source?: string },
230
+ ) => {
231
+ const acc = runtime.normalizeAccountId(accountId);
232
+ const summary = buildDeadLetterDiagnostics(acc);
233
+ const message = buildBncrDeadLetterSummaryMessage({
234
+ accountId: acc,
235
+ summary,
236
+ source: options?.source,
237
+ });
238
+ if (options?.force) {
239
+ runtime.logInfo('deadLetter summary', message);
240
+ return;
241
+ }
242
+ runtime.logInfoDedup('deadLetter summary', message, {
243
+ key: `dead-letter-summary:${acc}:update`,
244
+ sig: 'dead-letter-summary',
245
+ windowMs: 5 * 60 * 1000,
246
+ });
247
+ };
248
+
249
+ const filterDeadLetterEntries = (params: {
250
+ accountId: string;
251
+ reason?: string | null;
252
+ olderThan?: number | null;
253
+ }) => {
254
+ return filterDeadLetterEntriesFromRuntime({
255
+ accountId: params.accountId,
256
+ entries: runtime.getDeadLetterEntries(),
257
+ reason: params.reason,
258
+ olderThan: params.olderThan,
259
+ });
260
+ };
261
+
262
+ return {
263
+ buildDeadLetterDiagnostics,
264
+ filterDeadLetterEntries,
265
+ logDeadLetterSummary,
266
+ };
267
+ }
268
+
269
+ export function createBncrDiagnosticsSelectionHelpers(runtime: {
270
+ normalizeAccountId: (accountId: string) => string;
271
+ outboxValues: () => Iterable<OutboxEntry>;
272
+ getDeadLetterEntries: () => OutboxEntry[];
273
+ connectionsValues: () => Iterable<BncrConnection>;
274
+ }) {
275
+ const getAccountPendingOutboxEntries = (accountId: string) => {
276
+ const acc = runtime.normalizeAccountId(accountId);
277
+ return Array.from(runtime.outboxValues()).filter((entry) => entry.accountId === acc);
278
+ };
279
+
280
+ const getAccountDeadLetterEntries = (accountId: string) => {
281
+ const acc = runtime.normalizeAccountId(accountId);
282
+ return runtime.getDeadLetterEntries().filter((entry) => entry.accountId === acc);
283
+ };
284
+
285
+ const buildActiveConnectionDebugList = (
286
+ accountId: string,
287
+ options?: { includeOutboundState?: boolean },
288
+ ) => {
289
+ const acc = runtime.normalizeAccountId(accountId);
290
+ return buildBncrActiveConnectionDebugList({
291
+ accountId: acc,
292
+ connections: runtime.connectionsValues() as Iterable<BncrConnectionDebugView>,
293
+ options,
294
+ });
295
+ };
296
+
297
+ return {
298
+ getAccountPendingOutboxEntries,
299
+ getAccountDeadLetterEntries,
300
+ buildActiveConnectionDebugList,
301
+ };
302
+ }
@@ -0,0 +1,171 @@
1
+ import { formatDeadLetterTopReasons } from '../core/dead-letter-diagnostics.ts';
2
+ import type {
3
+ RegisterDriftSnapshot,
4
+ RegisterTraceEntry,
5
+ RegisterTraceSummary,
6
+ } from '../core/register-trace.ts';
7
+ import type {
8
+ BncrAckObservability,
9
+ BncrDeadLetterDiagnosticsSummary,
10
+ BncrOutboxQueueDiagnostics,
11
+ OutboxEntry,
12
+ } from '../core/types.ts';
13
+
14
+ export function buildBncrActiveConnectionDebugList(args: {
15
+ accountId: string;
16
+ connections: Iterable<{
17
+ accountId: string;
18
+ connId: string;
19
+ clientId?: string;
20
+ connectedAt: number;
21
+ lastSeenAt: number;
22
+ outboundReadyUntil?: number;
23
+ preferredForOutboundUntil?: number;
24
+ inboundOnly?: boolean;
25
+ }>;
26
+ options?: { includeOutboundState?: boolean };
27
+ }) {
28
+ return Array.from(args.connections)
29
+ .filter((conn) => conn.accountId === args.accountId)
30
+ .map((conn) => ({
31
+ accountId: conn.accountId,
32
+ connId: conn.connId,
33
+ clientId: conn.clientId,
34
+ connectedAt: conn.connectedAt,
35
+ lastSeenAt: conn.lastSeenAt,
36
+ ...(args.options?.includeOutboundState
37
+ ? {
38
+ outboundReadyUntil: conn.outboundReadyUntil || null,
39
+ preferredForOutboundUntil: conn.preferredForOutboundUntil || null,
40
+ inboundOnly: conn.inboundOnly === true,
41
+ }
42
+ : {}),
43
+ }));
44
+ }
45
+
46
+ export function buildBncrExtendedRegisterDiagnostics(args: {
47
+ bridgeId: string;
48
+ gatewayPid: number;
49
+ pluginVersion: string | null;
50
+ source: string | null;
51
+ apiInstanceId: string | null;
52
+ registryFingerprint: string | null;
53
+ registerCount: number;
54
+ firstRegisterAt: number | null;
55
+ lastRegisterAt: number | null;
56
+ lastApiRebindAt: number | null;
57
+ apiGeneration: number;
58
+ traceRecent: RegisterTraceEntry[];
59
+ traceSummary: RegisterTraceSummary;
60
+ lastDriftSnapshot: RegisterDriftSnapshot | null;
61
+ }) {
62
+ return {
63
+ bridgeId: args.bridgeId,
64
+ gatewayPid: args.gatewayPid,
65
+ pluginVersion: args.pluginVersion,
66
+ source: args.source,
67
+ apiInstanceId: args.apiInstanceId,
68
+ registryFingerprint: args.registryFingerprint,
69
+ registerCount: args.registerCount,
70
+ firstRegisterAt: args.firstRegisterAt,
71
+ lastRegisterAt: args.lastRegisterAt,
72
+ lastApiRebindAt: args.lastApiRebindAt,
73
+ apiGeneration: args.apiGeneration,
74
+ traceRecent: args.traceRecent,
75
+ traceSummary: args.traceSummary,
76
+ lastDriftSnapshot: args.lastDriftSnapshot ?? null,
77
+ };
78
+ }
79
+
80
+ export function buildBncrExtendedConnectionDiagnostics(args: {
81
+ active: number;
82
+ hasGatewayContext: boolean;
83
+ lastGatewayContextAt: number | null;
84
+ primaryLeaseId: string | null;
85
+ primaryEpoch: number | null;
86
+ acceptedConnections: number;
87
+ lastConnectAt: number | null;
88
+ lastDisconnectAt: number | null;
89
+ lastActivityAt: number | null;
90
+ lastInboundAt: number | null;
91
+ lastAckAt: number | null;
92
+ recentConnections: Map<
93
+ string,
94
+ { epoch: number; connectedAt: number; lastActivityAt: number | null; isPrimary: boolean }
95
+ >;
96
+ }) {
97
+ return {
98
+ active: args.active,
99
+ hasGatewayContext: args.hasGatewayContext,
100
+ lastGatewayContextAt: args.lastGatewayContextAt,
101
+ primaryLeaseId: args.primaryLeaseId,
102
+ primaryEpoch: args.primaryEpoch,
103
+ acceptedConnections: args.acceptedConnections,
104
+ lastConnectAt: args.lastConnectAt,
105
+ lastDisconnectAt: args.lastDisconnectAt,
106
+ lastActivityAt: args.lastActivityAt,
107
+ lastInboundAt: args.lastInboundAt,
108
+ lastAckAt: args.lastAckAt,
109
+ recent: Array.from(args.recentConnections.entries()).map(([leaseId, entry]) => ({
110
+ leaseId,
111
+ epoch: entry.epoch,
112
+ connectedAt: entry.connectedAt,
113
+ lastActivityAt: entry.lastActivityAt,
114
+ isPrimary: entry.isPrimary,
115
+ })),
116
+ };
117
+ }
118
+
119
+ export function buildBncrExtendedOutboundDiagnosticsInput(args: {
120
+ outbox: BncrOutboxQueueDiagnostics;
121
+ enqueueCount: number;
122
+ lastEnqueueAt: number | null;
123
+ prePushGuardSkipCount: number;
124
+ lastPrePushGuardSkipAt: number | null;
125
+ lastPrePushGuardSkipReason: string | null;
126
+ hasGatewayContext: boolean;
127
+ lastGatewayContextAt: number | null;
128
+ ackObservability: BncrAckObservability;
129
+ nowMs: number;
130
+ }) {
131
+ return {
132
+ outbox: args.outbox,
133
+ enqueueCount: args.enqueueCount,
134
+ lastEnqueueAt: args.lastEnqueueAt,
135
+ prePushGuardSkipCount: args.prePushGuardSkipCount,
136
+ lastPrePushGuardSkipAt: args.lastPrePushGuardSkipAt,
137
+ lastPrePushGuardSkipReason: args.lastPrePushGuardSkipReason,
138
+ hasGatewayContext: args.hasGatewayContext,
139
+ lastGatewayContextAt: args.lastGatewayContextAt,
140
+ ackObservability: args.ackObservability,
141
+ nowMs: args.nowMs,
142
+ };
143
+ }
144
+
145
+ export function buildBncrDeadLetterSummaryMessage(args: {
146
+ accountId: string;
147
+ summary: BncrDeadLetterDiagnosticsSummary;
148
+ source?: string;
149
+ }) {
150
+ return [
151
+ `${args.accountId}|total=${args.summary.total}`,
152
+ `all=${args.summary.allAccountsTotal}`,
153
+ `sinceStart=${args.summary.sinceStart}`,
154
+ `top=${formatDeadLetterTopReasons(args.summary.topReasons)}`,
155
+ `source=${args.source || 'update'}`,
156
+ ].join('|');
157
+ }
158
+
159
+ export function buildBncrOutboxQueueDiagnosticsInput(args: {
160
+ accountId: string;
161
+ outboxEntries: Iterable<OutboxEntry>;
162
+ pendingAllAccounts: number;
163
+ pushConnIds: Set<string>;
164
+ }) {
165
+ return {
166
+ accountId: args.accountId,
167
+ outboxEntries: args.outboxEntries,
168
+ pendingAllAccounts: args.pendingAllAccounts,
169
+ pushConnIds: args.pushConnIds,
170
+ };
171
+ }
@@ -0,0 +1,31 @@
1
+ import type { OutboxEntry } from '../core/types.ts';
2
+ import { buildOutboxQueueDiagnostics } from '../messaging/outbound/diagnostics.ts';
3
+ import { createBncrOutboxDiagnosticsHelpers as createBncrOutboxDiagnosticsHelpersBase } from './runtime-diagnostics-helpers.ts';
4
+ import { buildBncrOutboxQueueDiagnosticsInput } from './runtime-diagnostics-payload-builders.ts';
5
+
6
+ export {
7
+ buildBncrExtendedDiagnosticsSnapshot,
8
+ createBncrExtendedDiagnosticsAssembler,
9
+ } from './runtime-diagnostics-assembler.ts';
10
+
11
+ export {
12
+ buildBncrDeadLetterDiagnosticsSnapshot,
13
+ createBncrDeadLetterDiagnosticsHelpers,
14
+ createBncrDiagnosticsSelectionHelpers,
15
+ createBncrRuntimeAckObservabilityBuilder,
16
+ type ExtendedDiagnosticsAssemblerOptions,
17
+ type ExtendedDiagnosticsAssemblerRuntime,
18
+ } from './runtime-diagnostics-helpers.ts';
19
+
20
+ export function createBncrOutboxDiagnosticsHelpers(runtime: {
21
+ normalizeAccountId: (accountId: string) => string;
22
+ outboxValues: () => Iterable<OutboxEntry>;
23
+ pendingAllAccounts: () => number;
24
+ resolvePushConnIds: (accountId: string) => Set<string>;
25
+ }) {
26
+ return createBncrOutboxDiagnosticsHelpersBase({
27
+ ...runtime,
28
+ buildOutboxQueueDiagnostics,
29
+ buildBncrOutboxQueueDiagnosticsInput,
30
+ });
31
+ }
@@ -1,8 +1,34 @@
1
1
  import { CHANNEL_ID } from '../core/accounts.ts';
2
2
  import { applyOpenClawAccountNameToChannelSection } from '../openclaw/sdk-helpers.ts';
3
3
 
4
+ type BncrSetupAccountConfig = {
5
+ enabled?: boolean;
6
+ name?: string;
7
+ } & Record<string, unknown>;
8
+
9
+ type BncrSetupChannelConfig = {
10
+ accounts?: Record<string, BncrSetupAccountConfig>;
11
+ } & Record<string, unknown>;
12
+
13
+ type BncrSetupRootConfig = {
14
+ channels?: Record<string, unknown> & {
15
+ [CHANNEL_ID]?: BncrSetupChannelConfig;
16
+ };
17
+ };
18
+
19
+ type BncrApplyAccountNameArgs = {
20
+ cfg: BncrSetupRootConfig;
21
+ accountId: string;
22
+ name?: string;
23
+ };
24
+
25
+ type BncrApplyAccountConfigArgs = {
26
+ cfg: BncrSetupRootConfig | null | undefined;
27
+ accountId: string;
28
+ };
29
+
4
30
  export const BNCR_SETUP_SURFACE = {
5
- applyAccountName: ({ cfg, accountId, name }: any) =>
31
+ applyAccountName: ({ cfg, accountId, name }: BncrApplyAccountNameArgs) =>
6
32
  applyOpenClawAccountNameToChannelSection({
7
33
  cfg,
8
34
  channelKey: CHANNEL_ID,
@@ -10,13 +36,14 @@ export const BNCR_SETUP_SURFACE = {
10
36
  name,
11
37
  alwaysUseAccounts: true,
12
38
  }),
13
- applyAccountConfig: ({ cfg, accountId }: any) => {
14
- const next = { ...(cfg || {}) } as any;
39
+ applyAccountConfig: ({ cfg, accountId }: BncrApplyAccountConfigArgs) => {
40
+ const next: BncrSetupRootConfig = { ...(cfg || {}) };
15
41
  next.channels = next.channels || {};
16
42
  next.channels[CHANNEL_ID] = next.channels[CHANNEL_ID] || {};
17
- next.channels[CHANNEL_ID].accounts = next.channels[CHANNEL_ID].accounts || {};
18
- next.channels[CHANNEL_ID].accounts[accountId] = {
19
- ...(next.channels[CHANNEL_ID].accounts[accountId] || {}),
43
+ const channelCfg = next.channels[CHANNEL_ID] as BncrSetupChannelConfig;
44
+ channelCfg.accounts = channelCfg.accounts || {};
45
+ channelCfg.accounts[accountId] = {
46
+ ...(channelCfg.accounts[accountId] || {}),
20
47
  enabled: true,
21
48
  };
22
49
  return next;