@xmoxmo/bncr 0.3.6 → 0.3.7

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 (164) hide show
  1. package/README.md +5 -0
  2. package/dist/index.js +28 -5
  3. package/index.ts +55 -721
  4. package/package.json +8 -4
  5. package/scripts/check-pack.mjs +93 -18
  6. package/scripts/check-register-drift.mjs +35 -13
  7. package/scripts/selfcheck.mjs +80 -11
  8. package/src/bootstrap/channel-plugin-runtime.ts +81 -0
  9. package/src/bootstrap/cli.ts +97 -0
  10. package/src/bootstrap/register-runtime-gateway.ts +129 -0
  11. package/src/bootstrap/register-runtime-helpers.ts +140 -0
  12. package/src/bootstrap/register-runtime-singleton.ts +137 -0
  13. package/src/bootstrap/register-runtime.ts +201 -0
  14. package/src/bootstrap/runtime-discovery.ts +187 -0
  15. package/src/bootstrap/runtime-loader.ts +54 -0
  16. package/src/channel.ts +1590 -4967
  17. package/src/core/accounts.ts +23 -4
  18. package/src/core/dead-letter-diagnostics.ts +37 -5
  19. package/src/core/diagnostics.ts +31 -15
  20. package/src/core/downlink-health.ts +3 -11
  21. package/src/core/extended-diagnostics.ts +78 -36
  22. package/src/core/file-transfer-payloads.ts +1 -1
  23. package/src/core/logging.ts +1 -0
  24. package/src/core/outbox-enqueue.ts +13 -2
  25. package/src/core/outbox-entry-builders.ts +2 -0
  26. package/src/core/outbox-summary.ts +75 -3
  27. package/src/core/permissions.ts +15 -2
  28. package/src/core/persisted-outbox-entry.ts +21 -6
  29. package/src/core/policy.ts +45 -4
  30. package/src/core/probe.ts +3 -15
  31. package/src/core/register-trace.ts +3 -3
  32. package/src/core/status.ts +43 -4
  33. package/src/core/targets.ts +216 -205
  34. package/src/core/types.ts +221 -0
  35. package/src/core/value-sanitize.ts +29 -0
  36. package/src/messaging/inbound/commands.ts +147 -172
  37. package/src/messaging/inbound/context-facts.ts +4 -2
  38. package/src/messaging/inbound/contracts.ts +70 -0
  39. package/src/messaging/inbound/dispatch-prep.ts +303 -0
  40. package/src/messaging/inbound/dispatch.ts +49 -462
  41. package/src/messaging/inbound/gate.ts +18 -5
  42. package/src/messaging/inbound/last-route.ts +10 -4
  43. package/src/messaging/inbound/media-url-download.ts +109 -0
  44. package/src/messaging/inbound/native-command-runtime.ts +225 -0
  45. package/src/messaging/inbound/parse.ts +2 -1
  46. package/src/messaging/inbound/remote-media.ts +49 -0
  47. package/src/messaging/inbound/reply-config.ts +16 -4
  48. package/src/messaging/inbound/reply-dispatch.ts +162 -0
  49. package/src/messaging/inbound/runtime-compat.ts +31 -10
  50. package/src/messaging/inbound/session-label.ts +15 -7
  51. package/src/messaging/inbound/turn-context.ts +131 -0
  52. package/src/messaging/outbound/actions.ts +24 -10
  53. package/src/messaging/outbound/diagnostics-debug-builders.ts +365 -0
  54. package/src/messaging/outbound/diagnostics.ts +31 -355
  55. package/src/messaging/outbound/durable-message-adapter.ts +20 -16
  56. package/src/messaging/outbound/durable-queue-adapter.ts +20 -7
  57. package/src/messaging/outbound/media.ts +24 -13
  58. package/src/messaging/outbound/reply-enqueue-media.ts +181 -0
  59. package/src/messaging/outbound/reply-enqueue.ts +46 -155
  60. package/src/messaging/outbound/send-params.ts +3 -0
  61. package/src/messaging/outbound/send.ts +19 -10
  62. package/src/messaging/outbound/session-route.ts +18 -3
  63. package/src/openclaw/channel-runtime-contracts.ts +76 -0
  64. package/src/openclaw/config-runtime.ts +13 -7
  65. package/src/openclaw/inbound-session-runtime.ts +7 -3
  66. package/src/openclaw/ingress-runtime.ts +17 -27
  67. package/src/openclaw/reply-runtime.ts +54 -59
  68. package/src/openclaw/routing-runtime.ts +35 -18
  69. package/src/openclaw/runtime-surface.ts +156 -12
  70. package/src/openclaw/sdk-helpers.ts +8 -1
  71. package/src/openclaw/session-route-runtime.ts +12 -12
  72. package/src/plugin/ack-outbox-runtime-group.ts +264 -0
  73. package/src/plugin/bridge-ack-facade.ts +137 -0
  74. package/src/plugin/bridge-connection-facade.ts +111 -0
  75. package/src/plugin/bridge-diagnostics-facade.ts +23 -0
  76. package/src/plugin/bridge-drain-facade.ts +98 -0
  77. package/src/plugin/bridge-extended-diagnostics-facade.ts +149 -0
  78. package/src/plugin/bridge-file-transfer-push-facade.ts +140 -0
  79. package/src/plugin/bridge-lifecycle.ts +156 -0
  80. package/src/plugin/bridge-media-facade.ts +241 -0
  81. package/src/plugin/bridge-outbox-facade.ts +182 -0
  82. package/src/plugin/bridge-runtime-helpers.ts +266 -0
  83. package/src/plugin/bridge-runtime-snapshots.ts +104 -0
  84. package/src/plugin/bridge-runtime-surface-facade.ts +8 -0
  85. package/src/plugin/bridge-status-facade.ts +76 -0
  86. package/src/plugin/bridge-status-worker-facade.ts +72 -0
  87. package/src/plugin/bridge-support-runtime.ts +137 -0
  88. package/src/plugin/bridge-surface-handlers-group.ts +242 -0
  89. package/src/plugin/bridge-surface-helpers.ts +28 -0
  90. package/src/plugin/capabilities.ts +1 -3
  91. package/src/plugin/channel-components.ts +289 -0
  92. package/src/plugin/channel-inbound-helpers.ts +149 -0
  93. package/src/plugin/channel-plugin-bridge-group.ts +129 -0
  94. package/src/plugin/channel-plugin-surface-group.ts +202 -0
  95. package/src/plugin/channel-runtime-builders-delivery.ts +513 -0
  96. package/src/plugin/channel-runtime-builders-status.ts +331 -0
  97. package/src/plugin/channel-runtime-builders.ts +25 -0
  98. package/src/plugin/channel-runtime-constants.ts +40 -0
  99. package/src/plugin/channel-runtime-types.ts +146 -0
  100. package/src/plugin/channel-send-runtime-group.ts +37 -0
  101. package/src/plugin/channel-send.ts +226 -0
  102. package/src/plugin/channel-utils.ts +102 -0
  103. package/src/plugin/config.ts +24 -3
  104. package/src/plugin/connection-handlers-helpers.ts +254 -0
  105. package/src/plugin/connection-handlers.ts +440 -0
  106. package/src/plugin/connection-state-helpers.ts +159 -0
  107. package/src/plugin/connection-state-runtime-group.ts +51 -0
  108. package/src/plugin/connection-state.ts +527 -0
  109. package/src/plugin/diagnostics-handlers.ts +211 -0
  110. package/src/plugin/error-message.ts +15 -0
  111. package/src/plugin/file-ack-runtime.ts +284 -0
  112. package/src/plugin/file-inbound-abort.ts +112 -0
  113. package/src/plugin/file-inbound-chunk.ts +146 -0
  114. package/src/plugin/file-inbound-complete.ts +153 -0
  115. package/src/plugin/file-inbound-handlers.ts +19 -0
  116. package/src/plugin/file-inbound-init.ts +122 -0
  117. package/src/plugin/file-inbound-runtime.ts +51 -0
  118. package/src/plugin/file-inbound-state.ts +62 -0
  119. package/src/plugin/file-transfer-logs.ts +227 -0
  120. package/src/plugin/file-transfer-orchestrator-chunk.ts +135 -0
  121. package/src/plugin/file-transfer-orchestrator.ts +304 -0
  122. package/src/plugin/file-transfer-runtime-group.ts +102 -0
  123. package/src/plugin/file-transfer-send.ts +89 -0
  124. package/src/plugin/file-transfer-setup.ts +206 -0
  125. package/src/plugin/gateway-event-context.ts +41 -0
  126. package/src/plugin/gateway-runtime.ts +14 -4
  127. package/src/plugin/inbound-acceptance.ts +107 -0
  128. package/src/plugin/inbound-handlers.ts +248 -0
  129. package/src/plugin/inbound-surface-handlers-group.ts +152 -0
  130. package/src/plugin/media-dedupe-runtime.ts +90 -0
  131. package/src/plugin/media-orchestrators-runtime-group.ts +316 -0
  132. package/src/plugin/message-ack-runtime.ts +284 -0
  133. package/src/plugin/message-send.ts +16 -6
  134. package/src/plugin/messaging.ts +98 -36
  135. package/src/plugin/outbound.ts +50 -8
  136. package/src/plugin/outbox-ack-logs.ts +136 -0
  137. package/src/plugin/outbox-ack-outcome.ts +128 -0
  138. package/src/plugin/outbox-drain-ack.ts +145 -0
  139. package/src/plugin/outbox-drain-failure.ts +84 -0
  140. package/src/plugin/outbox-drain-loop.ts +554 -0
  141. package/src/plugin/outbox-drain-post-push.ts +159 -0
  142. package/src/plugin/outbox-drain-runtime.ts +141 -0
  143. package/src/plugin/outbox-drain-schedule.ts +116 -0
  144. package/src/plugin/outbox-file-push-flow.ts +69 -0
  145. package/src/plugin/outbox-push-route-runtime-group.ts +81 -0
  146. package/src/plugin/outbox-push.ts +267 -0
  147. package/src/plugin/outbox-route.ts +181 -0
  148. package/src/plugin/outbox-text-push-flow.ts +90 -0
  149. package/src/plugin/runtime-diagnostics-assembler.ts +183 -0
  150. package/src/plugin/runtime-diagnostics-helpers.ts +302 -0
  151. package/src/plugin/runtime-diagnostics-payload-builders.ts +171 -0
  152. package/src/plugin/runtime-diagnostics-snapshot.ts +31 -0
  153. package/src/plugin/setup.ts +33 -6
  154. package/src/plugin/state-store.ts +249 -0
  155. package/src/plugin/state-transient-runtime-group.ts +105 -0
  156. package/src/plugin/status-runtime.ts +251 -0
  157. package/src/plugin/status.ts +33 -7
  158. package/src/plugin/target-runtime.ts +141 -0
  159. package/src/plugin/target-status-runtime-group.ts +130 -0
  160. package/src/plugin/transient-state-runtime.ts +82 -0
  161. package/src/runtime/outbound-ack-timeout.ts +5 -3
  162. package/src/runtime/outbound-flags.ts +24 -8
  163. package/src/runtime/status-snapshots.ts +36 -7
  164. package/src/runtime/status-worker.ts +34 -4
@@ -0,0 +1,181 @@
1
+ import { normalizeAccountId } from '../core/accounts.ts';
2
+ import {
3
+ isEligibleOutboundPushConnection,
4
+ selectOrderedOutboundPushConnections,
5
+ } from '../core/connection-reachability.ts';
6
+ import type { BncrConnection } from '../core/types.ts';
7
+
8
+ type BncrConnectionWithOutboundHints = BncrConnection & {
9
+ outboundReadyUntil?: number;
10
+ preferredForOutboundUntil?: number;
11
+ };
12
+
13
+ export type BncrOutboxRouteRuntime = {
14
+ bridgeId: string;
15
+ now: () => number;
16
+ connectTtlMs: number;
17
+ finiteNumberOr: (value: unknown, fallback: number) => number;
18
+ connections: Map<string, BncrConnection>;
19
+ activeConnectionByAccount: Map<string, string>;
20
+ resolveRecentInboundConnIds: (accountId: string) => Set<string>;
21
+ connectionKey: (accountId: string, clientId?: string) => string;
22
+ logInfo: (scope: string, message: string, options?: { debugOnly?: boolean }) => void;
23
+ buildActiveConnectionDebugList: (
24
+ accountId: string,
25
+ options?: { includeOutboundState?: boolean },
26
+ ) => unknown;
27
+ };
28
+
29
+ export function createBncrOutboxRoute(runtime: BncrOutboxRouteRuntime) {
30
+ const resolveOutboxPushOwner = (accountId: string): BncrConnectionWithOutboundHints | null => {
31
+ const acc = normalizeAccountId(accountId);
32
+ const t = runtime.now();
33
+ const primaryKey = runtime.activeConnectionByAccount.get(acc);
34
+ const primary = primaryKey
35
+ ? ((runtime.connections.get(primaryKey) as BncrConnectionWithOutboundHints | undefined) ??
36
+ null)
37
+ : null;
38
+
39
+ const recentInboundConnIds = runtime.resolveRecentInboundConnIds(acc);
40
+
41
+ if (primary) {
42
+ if (
43
+ isEligibleOutboundPushConnection({
44
+ connection: primary,
45
+ now: t,
46
+ connectTtlMs: runtime.connectTtlMs,
47
+ })
48
+ ) {
49
+ const preferredForOutboundUntil = runtime.finiteNumberOr(
50
+ primary.preferredForOutboundUntil,
51
+ 0,
52
+ );
53
+ const outboundReadyUntil = runtime.finiteNumberOr(primary.outboundReadyUntil, 0);
54
+ if (preferredForOutboundUntil > t || outboundReadyUntil > t) return primary;
55
+ }
56
+ }
57
+
58
+ const candidates = selectOrderedOutboundPushConnections({
59
+ accountId: acc,
60
+ now: t,
61
+ connectTtlMs: runtime.connectTtlMs,
62
+ recentInboundConnIds,
63
+ connections: runtime.connections.values(),
64
+ });
65
+
66
+ const next = (candidates[0] as BncrConnectionWithOutboundHints | undefined) || null;
67
+ if (!next) return null;
68
+
69
+ const nextKey = runtime.connectionKey(acc, next.clientId);
70
+ if (primaryKey !== nextKey) {
71
+ runtime.activeConnectionByAccount.set(acc, nextKey);
72
+ runtime.logInfo(
73
+ 'connection',
74
+ `owner:promote ${JSON.stringify({
75
+ bridge: runtime.bridgeId,
76
+ accountId: acc,
77
+ previousActiveKey: primaryKey || null,
78
+ previousActiveConn: primary || null,
79
+ nextActiveKey: nextKey,
80
+ nextActiveConn: {
81
+ connId: next.connId,
82
+ clientId: next.clientId,
83
+ connectedAt: next.connectedAt,
84
+ lastSeenAt: next.lastSeenAt,
85
+ outboundReadyUntil: next.outboundReadyUntil || null,
86
+ preferredForOutboundUntil: next.preferredForOutboundUntil || null,
87
+ inboundOnly: next.inboundOnly === true,
88
+ },
89
+ reason: 'better-outbound-candidate',
90
+ })}`,
91
+ { debugOnly: true },
92
+ );
93
+ }
94
+
95
+ return next;
96
+ };
97
+
98
+ const resolvePushConnIds = (accountId: string): Set<string> => {
99
+ const acc = normalizeAccountId(accountId);
100
+ const t = runtime.now();
101
+ const connIds = new Set<string>();
102
+
103
+ const recentInboundConnIds = runtime.resolveRecentInboundConnIds(acc);
104
+
105
+ const primaryKey = runtime.activeConnectionByAccount.get(acc);
106
+ if (primaryKey) {
107
+ const primary = runtime.connections.get(primaryKey) ?? null;
108
+ if (
109
+ primary &&
110
+ isEligibleOutboundPushConnection({
111
+ connection: primary,
112
+ now: t,
113
+ connectTtlMs: runtime.connectTtlMs,
114
+ })
115
+ ) {
116
+ connIds.add(primary.connId);
117
+ }
118
+ }
119
+
120
+ const candidates = selectOrderedOutboundPushConnections({
121
+ accountId: acc,
122
+ now: t,
123
+ connectTtlMs: runtime.connectTtlMs,
124
+ recentInboundConnIds,
125
+ connections: runtime.connections.values(),
126
+ });
127
+
128
+ for (const c of candidates) {
129
+ connIds.add(c.connId);
130
+ }
131
+
132
+ if (connIds.size > 0) return connIds;
133
+
134
+ for (const c of runtime.connections.values()) {
135
+ if (c.accountId !== acc) continue;
136
+ if (!c.connId) continue;
137
+ if (t - c.lastSeenAt > runtime.connectTtlMs) continue;
138
+ connIds.add(c.connId);
139
+ }
140
+
141
+ return connIds;
142
+ };
143
+
144
+ const buildTransferRouteDiagnostics = (args: {
145
+ accountId: string;
146
+ recentInboundReachable: boolean;
147
+ }) => {
148
+ const directConnIds = resolvePushConnIds(args.accountId);
149
+ const recentConnIds = args.recentInboundReachable
150
+ ? runtime.resolveRecentInboundConnIds(args.accountId)
151
+ : new Set<string>();
152
+ const activeConnectionKey = runtime.activeConnectionByAccount.get(args.accountId) || null;
153
+ const accountConnections = runtime.buildActiveConnectionDebugList(args.accountId);
154
+
155
+ return {
156
+ directConnIds,
157
+ recentConnIds,
158
+ activeConnectionKey,
159
+ accountConnections,
160
+ };
161
+ };
162
+
163
+ const selectTransferConnIds = (args: {
164
+ directConnIds: Set<string>;
165
+ recentConnIds: Set<string>;
166
+ recentInboundReachable: boolean;
167
+ }) => {
168
+ let connIds = args.directConnIds;
169
+ if (!connIds.size && args.recentInboundReachable) {
170
+ connIds = args.recentConnIds;
171
+ }
172
+ return connIds;
173
+ };
174
+
175
+ return {
176
+ resolveOutboxPushOwner,
177
+ resolvePushConnIds,
178
+ buildTransferRouteDiagnostics,
179
+ selectTransferConnIds,
180
+ };
181
+ }
@@ -0,0 +1,90 @@
1
+ import { resolveTextPushGuard } from '../core/outbox-text-push-guards.ts';
2
+ import { prepareTextPushRouteSelection } from '../core/outbox-text-push-prep.ts';
3
+ import type { BncrConnection, OutboxEntry } from '../core/types.ts';
4
+ import { selectOutboxRouteCandidates } from '../messaging/outbound/queue-selectors.ts';
5
+
6
+ export async function runBncrTextOutboxPush(args: {
7
+ entry: OutboxEntry;
8
+ gatewayContext: unknown;
9
+ owner: BncrConnection | null;
10
+ resolvePushConnIds: (accountId: string) => Set<string>;
11
+ resolveRecentInboundConnIds: (accountId: string) => Set<string>;
12
+ hasRecentInboundReachability: (accountId: string) => boolean;
13
+ isRevalidatedAttemptedConn: (connId: string) => boolean;
14
+ recordOutboxPrePushFailure: (args: {
15
+ entry: OutboxEntry;
16
+ lastError: string;
17
+ persist?: boolean;
18
+ }) => void;
19
+ logOutboxPushSkip: (args: {
20
+ messageId: string;
21
+ accountId: string;
22
+ reason: string;
23
+ recentInboundReachable?: boolean;
24
+ routeReason?: string;
25
+ connIds?: Iterable<string>;
26
+ ownerConnId?: string;
27
+ ownerClientId?: string;
28
+ }) => void;
29
+ pushTextSuccessPath: (args: {
30
+ entry: OutboxEntry;
31
+ owner: BncrConnection | null;
32
+ connIds: Iterable<string>;
33
+ recentInboundReachable: boolean;
34
+ routeReason: string;
35
+ ownerConnId?: string;
36
+ }) => void;
37
+ handleTextPushFailure: (args: { entry: OutboxEntry; error: unknown }) => void;
38
+ }) {
39
+ const selection = prepareTextPushRouteSelection({
40
+ entry: args.entry,
41
+ owner: args.owner,
42
+ resolvePushConnIds: args.resolvePushConnIds,
43
+ resolveRecentInboundConnIds: args.resolveRecentInboundConnIds,
44
+ hasRecentInboundReachability: args.hasRecentInboundReachability,
45
+ isRevalidatedAttemptedConn: args.isRevalidatedAttemptedConn,
46
+ selectOutboxRouteCandidates,
47
+ });
48
+ const guard = resolveTextPushGuard({
49
+ gatewayContext: args.gatewayContext,
50
+ entry: args.entry,
51
+ routeSelection: selection,
52
+ });
53
+ if (!guard.ok) {
54
+ args.recordOutboxPrePushFailure({
55
+ entry: args.entry,
56
+ lastError:
57
+ guard.reason === 'no-gateway-context'
58
+ ? 'gateway context unavailable'
59
+ : 'no active bncr client',
60
+ persist: true,
61
+ });
62
+ args.logOutboxPushSkip({
63
+ messageId: args.entry.messageId,
64
+ accountId: args.entry.accountId,
65
+ reason: guard.reason,
66
+ recentInboundReachable:
67
+ guard.reason === 'no-active-connection' ? guard.recentInboundReachable : undefined,
68
+ routeReason: selection.routeReason,
69
+ connIds: selection.connIds,
70
+ ownerConnId: selection.ownerConnId,
71
+ ownerClientId: args.owner?.clientId,
72
+ });
73
+ return false;
74
+ }
75
+
76
+ try {
77
+ args.pushTextSuccessPath({
78
+ entry: args.entry,
79
+ owner: args.owner,
80
+ connIds: guard.connIds,
81
+ recentInboundReachable: guard.recentInboundReachable,
82
+ routeReason: guard.routeReason,
83
+ ownerConnId: guard.ownerConnId,
84
+ });
85
+ return true;
86
+ } catch (error) {
87
+ args.handleTextPushFailure({ entry: args.entry, error });
88
+ return false;
89
+ }
90
+ }
@@ -0,0 +1,183 @@
1
+ import type { BncrExtendedDiagnostics } from '../core/extended-diagnostics.ts';
2
+ import { buildExtendedDiagnostics as buildExtendedDiagnosticsFromRuntime } from '../core/extended-diagnostics.ts';
3
+ import type {
4
+ RegisterDriftSnapshot,
5
+ RegisterTraceEntry,
6
+ RegisterTraceSummary,
7
+ } from '../core/register-trace.ts';
8
+ import { buildExtendedOutboundDiagnostics } from '../messaging/outbound/diagnostics.ts';
9
+ import type {
10
+ buildBncrDeadLetterDiagnosticsSnapshot,
11
+ ExtendedDiagnosticsAssemblerOptions,
12
+ ExtendedDiagnosticsAssemblerRuntime,
13
+ } from './runtime-diagnostics-helpers.ts';
14
+ import {
15
+ buildBncrExtendedConnectionDiagnostics,
16
+ buildBncrExtendedOutboundDiagnosticsInput,
17
+ buildBncrExtendedRegisterDiagnostics,
18
+ } from './runtime-diagnostics-payload-builders.ts';
19
+
20
+ export function createBncrExtendedDiagnosticsAssembler(
21
+ runtime: ExtendedDiagnosticsAssemblerRuntime,
22
+ ) {
23
+ return (
24
+ accountId: string,
25
+ options: ExtendedDiagnosticsAssemblerOptions = {},
26
+ ): BncrExtendedDiagnostics => {
27
+ const acc = runtime.normalizeAccountId(accountId);
28
+ const diagnostics =
29
+ options.integratedDiagnostics ||
30
+ runtime.buildIntegratedDiagnostics(acc, options.runtimeStatusInput);
31
+ const outboxDiagnostics = runtime.buildOutboxDiagnostics(acc);
32
+ const ackObservability = runtime.buildRuntimeAckObservability(acc);
33
+ const prePushGuardSkipCount = runtime.getCounter(runtime.prePushGuardSkipCountByAccount, acc);
34
+ const lastPrePushGuardSkipAt = runtime.lastPrePushGuardSkipAtByAccount.get(acc) || null;
35
+ const lastPrePushGuardSkipReason = runtime.lastPrePushGuardSkipReasonByAccount.get(acc) || null;
36
+ const hasGatewayContext = runtime.hasGatewayContext();
37
+ const registerRuntime = runtime.getRegisterRuntime();
38
+ const connectionRuntime = runtime.getConnectionRuntime();
39
+ const outboundRuntime = runtime.getOutboundRuntime();
40
+
41
+ return buildBncrExtendedDiagnosticsSnapshot({
42
+ diagnostics,
43
+ runtimeSurface: runtime.buildRuntimeSurfaceDiagnostics(),
44
+ register: buildBncrExtendedRegisterDiagnostics({
45
+ bridgeId: registerRuntime.bridgeId,
46
+ gatewayPid: registerRuntime.gatewayPid,
47
+ pluginVersion: registerRuntime.pluginVersion,
48
+ source: registerRuntime.pluginSource,
49
+ apiInstanceId: registerRuntime.lastApiInstanceId,
50
+ registryFingerprint: registerRuntime.lastRegistryFingerprint,
51
+ registerCount: registerRuntime.registerCount,
52
+ firstRegisterAt: registerRuntime.firstRegisterAt,
53
+ lastRegisterAt: registerRuntime.lastRegisterAt,
54
+ lastApiRebindAt: registerRuntime.lastApiRebindAt,
55
+ apiGeneration: registerRuntime.apiGeneration,
56
+ traceRecent: registerRuntime.registerTraceRecent,
57
+ traceSummary: runtime.buildRegisterTraceSummary(),
58
+ lastDriftSnapshot: registerRuntime.lastDriftSnapshot ?? null,
59
+ }),
60
+ connection: buildBncrExtendedConnectionDiagnostics({
61
+ active: runtime.activeConnectionCount(acc),
62
+ hasGatewayContext,
63
+ lastGatewayContextAt: connectionRuntime.lastGatewayContextAt,
64
+ primaryLeaseId: connectionRuntime.primaryLeaseId,
65
+ primaryEpoch: connectionRuntime.connectionEpoch || null,
66
+ acceptedConnections: connectionRuntime.acceptedConnections,
67
+ lastConnectAt: connectionRuntime.lastConnectAt,
68
+ lastDisconnectAt: connectionRuntime.lastDisconnectAt,
69
+ lastActivityAt: connectionRuntime.lastActivityAtGlobal,
70
+ lastInboundAt: connectionRuntime.lastInboundAtGlobal,
71
+ lastAckAt: connectionRuntime.lastAckAtGlobal,
72
+ recentConnections: connectionRuntime.recentConnections,
73
+ }),
74
+ outbound: buildBncrExtendedOutboundDiagnosticsInput({
75
+ outbox: outboxDiagnostics,
76
+ enqueueCount: runtime.getCounter(outboundRuntime.outboundEnqueueCountByAccount, acc),
77
+ lastEnqueueAt: outboundRuntime.lastOutboundEnqueueAtByAccount.get(acc) || null,
78
+ prePushGuardSkipCount,
79
+ lastPrePushGuardSkipAt,
80
+ lastPrePushGuardSkipReason,
81
+ hasGatewayContext,
82
+ lastGatewayContextAt: connectionRuntime.lastGatewayContextAt,
83
+ ackObservability,
84
+ nowMs: runtime.now(),
85
+ }),
86
+ deadLetterSummary: runtime.buildDeadLetterDiagnostics(acc),
87
+ protocol: {
88
+ bridgeVersion: runtime.bridgeVersion,
89
+ protocolVersion: 2,
90
+ minClientProtocol: 1,
91
+ features: {
92
+ leaseId: true,
93
+ connectionEpoch: true,
94
+ staleObserveOnly: true,
95
+ staleRejectAck: false,
96
+ staleRejectFile: false,
97
+ },
98
+ },
99
+ stale: runtime.staleCounters,
100
+ nowMs: runtime.now(),
101
+ });
102
+ };
103
+ }
104
+
105
+ export function buildBncrExtendedDiagnosticsSnapshot(args: {
106
+ diagnostics: import('../core/types.ts').BncrDiagnosticsSummary;
107
+ runtimeSurface: ReturnType<
108
+ typeof import('../openclaw/runtime-surface.ts')['buildOpenClawChannelRuntimeSurfaceDiagnostics']
109
+ >;
110
+ register: {
111
+ bridgeId: string;
112
+ gatewayPid: number;
113
+ pluginVersion: string | null;
114
+ source: string | null;
115
+ apiInstanceId: string | null;
116
+ registryFingerprint: string | null;
117
+ registerCount: number;
118
+ firstRegisterAt: number | null;
119
+ lastRegisterAt: number | null;
120
+ lastApiRebindAt: number | null;
121
+ apiGeneration: number;
122
+ traceRecent: RegisterTraceEntry[];
123
+ traceSummary: RegisterTraceSummary;
124
+ lastDriftSnapshot: RegisterDriftSnapshot | null;
125
+ };
126
+ connection: {
127
+ active: number;
128
+ hasGatewayContext: boolean;
129
+ lastGatewayContextAt: number | null;
130
+ primaryLeaseId: string | null;
131
+ primaryEpoch: number | null;
132
+ acceptedConnections: number;
133
+ lastConnectAt: number | null;
134
+ lastDisconnectAt: number | null;
135
+ lastActivityAt: number | null;
136
+ lastInboundAt: number | null;
137
+ lastAckAt: number | null;
138
+ recent: Array<{
139
+ leaseId: string;
140
+ epoch: number;
141
+ connectedAt: number;
142
+ lastActivityAt: number | null;
143
+ isPrimary: boolean;
144
+ }>;
145
+ };
146
+ outbound: Parameters<typeof buildExtendedOutboundDiagnostics>[0];
147
+ deadLetterSummary: ReturnType<typeof buildBncrDeadLetterDiagnosticsSnapshot>;
148
+ protocol: {
149
+ bridgeVersion: number;
150
+ protocolVersion: number;
151
+ minClientProtocol: number;
152
+ features: {
153
+ leaseId: boolean;
154
+ connectionEpoch: boolean;
155
+ staleObserveOnly: boolean;
156
+ staleRejectAck: boolean;
157
+ staleRejectFile: boolean;
158
+ };
159
+ };
160
+ stale: {
161
+ staleConnect: number;
162
+ staleInbound: number;
163
+ staleActivity: number;
164
+ staleAck: number;
165
+ staleFileInit: number;
166
+ staleFileChunk: number;
167
+ staleFileComplete: number;
168
+ staleFileAbort: number;
169
+ lastStaleAt: number | null;
170
+ };
171
+ nowMs: number;
172
+ }): BncrExtendedDiagnostics {
173
+ return buildExtendedDiagnosticsFromRuntime({
174
+ diagnostics: args.diagnostics,
175
+ runtimeSurface: args.runtimeSurface,
176
+ register: args.register,
177
+ connection: args.connection,
178
+ outbound: buildExtendedOutboundDiagnostics(args.outbound),
179
+ deadLetterSummary: args.deadLetterSummary,
180
+ protocol: args.protocol,
181
+ stale: args.stale,
182
+ });
183
+ }