@xmoxmo/bncr 0.5.7 → 0.5.9

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 (44) hide show
  1. package/package.json +1 -1
  2. package/scripts/check-pack.mjs +0 -2
  3. package/scripts/selfcheck.mjs +48 -13
  4. package/src/bootstrap/runtime-loader.ts +1 -1
  5. package/src/channel.ts +50 -138
  6. package/src/core/connection-reachability.ts +1 -1
  7. package/src/core/logging.ts +1 -1
  8. package/src/core/outbox-entry-builders.ts +60 -82
  9. package/src/core/outbox-summary.ts +5 -39
  10. package/src/core/permissions.ts +1 -1
  11. package/src/core/register-trace.ts +2 -2
  12. package/src/messaging/inbound/parse.ts +1 -1
  13. package/src/messaging/outbound/diagnostics-debug-builders.ts +0 -15
  14. package/src/messaging/outbound/diagnostics.ts +0 -1
  15. package/src/messaging/outbound/marker-parser.ts +234 -0
  16. package/src/messaging/outbound/media-dedupe.ts +1 -4
  17. package/src/messaging/outbound/normalize-outbound-send.ts +9 -7
  18. package/src/messaging/outbound/reply-enqueue-media.ts +1 -184
  19. package/src/messaging/outbound/reply-enqueue.ts +249 -162
  20. package/src/openclaw/media-runtime.ts +1 -1
  21. package/src/plugin/ack-outbox-runtime-group.ts +2 -0
  22. package/src/plugin/bridge-media-facade.ts +0 -3
  23. package/src/plugin/bridge-outbox-facade.ts +14 -2
  24. package/src/plugin/channel-runtime-builders-delivery.ts +2 -362
  25. package/src/plugin/channel-runtime-builders-status.ts +0 -160
  26. package/src/plugin/channel-runtime-builders.ts +3 -17
  27. package/src/plugin/channel-runtime-constants.ts +1 -1
  28. package/src/plugin/channel-send.ts +5 -4
  29. package/src/plugin/file-transfer-orchestrator.ts +39 -2
  30. package/src/plugin/media-orchestrators-runtime-group.ts +20 -149
  31. package/src/plugin/messaging.ts +3 -3
  32. package/src/plugin/outbox-drain-failure.ts +34 -1
  33. package/src/plugin/outbox-drain-runtime.ts +3 -0
  34. package/src/plugin/outbox-push.ts +1 -52
  35. package/src/plugin/outbox-unified-push-flow.ts +307 -0
  36. package/src/plugin/scene-registry.ts +1 -1
  37. package/src/runtime/log-dedupe.ts +3 -3
  38. package/src/runtime/outbound-ack-timeout.ts +2 -4
  39. package/src/runtime/status-snapshots.ts +2 -2
  40. package/src/runtime/status-worker.ts +2 -6
  41. package/src/core/outbox-text-push-prep.ts +0 -1
  42. package/src/plugin/bridge-file-transfer-push-facade.ts +0 -142
  43. package/src/plugin/outbox-file-push-flow.ts +0 -69
  44. package/src/plugin/outbox-text-push-flow.ts +0 -90
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmoxmo/bncr",
3
- "version": "0.5.7",
3
+ "version": "0.5.9",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -149,11 +149,9 @@ const requiredSourceFiles = [
149
149
  'src/plugin/outbox-drain-post-push.ts',
150
150
  'src/plugin/outbox-drain-runtime.ts',
151
151
  'src/plugin/outbox-drain-schedule.ts',
152
- 'src/plugin/outbox-file-push-flow.ts',
153
152
  'src/plugin/outbox-push-route-runtime-group.ts',
154
153
  'src/plugin/outbox-push.ts',
155
154
  'src/plugin/outbox-route.ts',
156
- 'src/plugin/outbox-text-push-flow.ts',
157
155
  'src/plugin/runtime-diagnostics-snapshot.ts',
158
156
  'src/plugin/setup.ts',
159
157
  'src/plugin/state-transient-runtime-group.ts',
@@ -12,13 +12,15 @@ const require = createRequire(import.meta.url);
12
12
  const requiredRootFiles = ['index.ts', 'openclaw.plugin.json'];
13
13
 
14
14
  const requiredSourceFiles = [
15
- 'src/channel.ts',
16
15
  'src/bootstrap/channel-plugin-runtime.ts',
17
16
  'src/bootstrap/cli.ts',
17
+ 'src/bootstrap/register-runtime-gateway.ts',
18
18
  'src/bootstrap/register-runtime-helpers.ts',
19
+ 'src/bootstrap/register-runtime-singleton.ts',
19
20
  'src/bootstrap/register-runtime.ts',
20
21
  'src/bootstrap/runtime-discovery.ts',
21
22
  'src/bootstrap/runtime-loader.ts',
23
+ 'src/channel.ts',
22
24
  'src/core/accounts.ts',
23
25
  'src/core/config-schema.ts',
24
26
  'src/core/connection-capability.ts',
@@ -44,7 +46,6 @@ const requiredSourceFiles = [
44
46
  'src/core/outbox-summary.ts',
45
47
  'src/core/outbox-text-push-failure.ts',
46
48
  'src/core/outbox-text-push-guards.ts',
47
- 'src/core/outbox-text-push-prep.ts',
48
49
  'src/core/outbox-text-push-success.ts',
49
50
  'src/core/permissions.ts',
50
51
  'src/core/persisted-outbox-entry.ts',
@@ -55,35 +56,46 @@ const requiredSourceFiles = [
55
56
  'src/core/status.ts',
56
57
  'src/core/targets.ts',
57
58
  'src/core/types.ts',
59
+ 'src/core/value-sanitize.ts',
58
60
  'src/messaging/inbound/commands.ts',
59
61
  'src/messaging/inbound/context-facts.ts',
62
+ 'src/messaging/inbound/contracts.ts',
60
63
  'src/messaging/inbound/dispatch-prep.ts',
61
64
  'src/messaging/inbound/dispatch.ts',
62
65
  'src/messaging/inbound/gate.ts',
66
+ 'src/messaging/inbound/group-history.ts',
63
67
  'src/messaging/inbound/last-route.ts',
64
68
  'src/messaging/inbound/media-url-download.ts',
69
+ 'src/messaging/inbound/native-command-runtime.ts',
65
70
  'src/messaging/inbound/native-command.ts',
66
71
  'src/messaging/inbound/native-reply-delivery.ts',
67
72
  'src/messaging/inbound/parse.ts',
68
73
  'src/messaging/inbound/remote-media.ts',
69
74
  'src/messaging/inbound/reply-config.ts',
75
+ 'src/messaging/inbound/reply-dispatch-serial.ts',
70
76
  'src/messaging/inbound/reply-dispatch.ts',
71
77
  'src/messaging/inbound/runtime-compat.ts',
78
+ 'src/messaging/inbound/scene-admin.ts',
72
79
  'src/messaging/inbound/session-label.ts',
80
+ 'src/messaging/inbound/session-meta-task.ts',
73
81
  'src/messaging/inbound/turn-context.ts',
74
82
  'src/messaging/outbound/actions.ts',
75
- 'src/messaging/outbound/diagnostics.ts',
76
83
  'src/messaging/outbound/diagnostics-debug-builders.ts',
84
+ 'src/messaging/outbound/diagnostics.ts',
77
85
  'src/messaging/outbound/durable-queue-adapter.ts',
86
+ 'src/messaging/outbound/marker-parser.ts',
78
87
  'src/messaging/outbound/media-dedupe.ts',
79
88
  'src/messaging/outbound/media.ts',
89
+ 'src/messaging/outbound/normalize-outbound-send.ts',
80
90
  'src/messaging/outbound/queue-selectors.ts',
81
91
  'src/messaging/outbound/reasons.ts',
92
+ 'src/messaging/outbound/reply-enqueue-media.ts',
82
93
  'src/messaging/outbound/reply-enqueue.ts',
83
94
  'src/messaging/outbound/reply-target-policy.ts',
84
95
  'src/messaging/outbound/retry-policy.ts',
85
96
  'src/messaging/outbound/session-route.ts',
86
97
  'src/messaging/outbound/target-resolver.ts',
98
+ 'src/openclaw/channel-runtime-contracts.ts',
87
99
  'src/openclaw/config-runtime.ts',
88
100
  'src/openclaw/inbound-session-runtime.ts',
89
101
  'src/openclaw/media-runtime.ts',
@@ -93,6 +105,20 @@ const requiredSourceFiles = [
93
105
  'src/openclaw/sdk-helpers.ts',
94
106
  'src/openclaw/session-route-runtime.ts',
95
107
  'src/plugin/ack-outbox-runtime-group.ts',
108
+ 'src/plugin/bridge-ack-facade.ts',
109
+ 'src/plugin/bridge-connection-facade.ts',
110
+ 'src/plugin/bridge-diagnostics-facade.ts',
111
+ 'src/plugin/bridge-drain-facade.ts',
112
+ 'src/plugin/bridge-extended-diagnostics-facade.ts',
113
+ 'src/plugin/bridge-lifecycle.ts',
114
+ 'src/plugin/bridge-media-facade.ts',
115
+ 'src/plugin/bridge-outbox-facade.ts',
116
+ 'src/plugin/bridge-runtime-helpers.ts',
117
+ 'src/plugin/bridge-runtime-snapshots.ts',
118
+ 'src/plugin/bridge-runtime-surface-facade.ts',
119
+ 'src/plugin/bridge-status-facade.ts',
120
+ 'src/plugin/bridge-status-worker-facade.ts',
121
+ 'src/plugin/bridge-support-runtime.ts',
96
122
  'src/plugin/bridge-surface-handlers-group.ts',
97
123
  'src/plugin/bridge-surface-helpers.ts',
98
124
  'src/plugin/capabilities.ts',
@@ -100,16 +126,21 @@ const requiredSourceFiles = [
100
126
  'src/plugin/channel-inbound-helpers.ts',
101
127
  'src/plugin/channel-plugin-bridge-group.ts',
102
128
  'src/plugin/channel-plugin-surface-group.ts',
103
- 'src/plugin/channel-runtime-constants.ts',
129
+ 'src/plugin/channel-runtime-builders-delivery.ts',
130
+ 'src/plugin/channel-runtime-builders-status.ts',
104
131
  'src/plugin/channel-runtime-builders.ts',
132
+ 'src/plugin/channel-runtime-constants.ts',
105
133
  'src/plugin/channel-runtime-types.ts',
106
134
  'src/plugin/channel-send.ts',
107
135
  'src/plugin/channel-utils.ts',
108
136
  'src/plugin/config.ts',
137
+ 'src/plugin/connection-handlers-helpers.ts',
109
138
  'src/plugin/connection-handlers.ts',
110
- 'src/plugin/connection-state.ts',
139
+ 'src/plugin/connection-state-helpers.ts',
111
140
  'src/plugin/connection-state-runtime-group.ts',
141
+ 'src/plugin/connection-state.ts',
112
142
  'src/plugin/diagnostics-handlers.ts',
143
+ 'src/plugin/error-message.ts',
113
144
  'src/plugin/file-ack-runtime.ts',
114
145
  'src/plugin/file-inbound-abort.ts',
115
146
  'src/plugin/file-inbound-chunk.ts',
@@ -119,9 +150,8 @@ const requiredSourceFiles = [
119
150
  'src/plugin/file-inbound-runtime.ts',
120
151
  'src/plugin/file-inbound-state.ts',
121
152
  'src/plugin/file-transfer-logs.ts',
122
- 'src/plugin/media-dedupe-runtime.ts',
153
+ 'src/plugin/file-transfer-orchestrator-chunk.ts',
123
154
  'src/plugin/file-transfer-orchestrator.ts',
124
- 'src/plugin/media-orchestrators-runtime-group.ts',
125
155
  'src/plugin/file-transfer-runtime-group.ts',
126
156
  'src/plugin/file-transfer-send.ts',
127
157
  'src/plugin/file-transfer-setup.ts',
@@ -129,8 +159,10 @@ const requiredSourceFiles = [
129
159
  'src/plugin/gateway-methods.ts',
130
160
  'src/plugin/gateway-runtime.ts',
131
161
  'src/plugin/inbound-acceptance.ts',
132
- 'src/plugin/inbound-surface-handlers-group.ts',
133
162
  'src/plugin/inbound-handlers.ts',
163
+ 'src/plugin/inbound-surface-handlers-group.ts',
164
+ 'src/plugin/media-dedupe-runtime.ts',
165
+ 'src/plugin/media-orchestrators-runtime-group.ts',
134
166
  'src/plugin/message-ack-runtime.ts',
135
167
  'src/plugin/message-policy.ts',
136
168
  'src/plugin/message-send.ts',
@@ -145,20 +177,23 @@ const requiredSourceFiles = [
145
177
  'src/plugin/outbox-drain-post-push.ts',
146
178
  'src/plugin/outbox-drain-runtime.ts',
147
179
  'src/plugin/outbox-drain-schedule.ts',
148
- 'src/plugin/outbox-file-push-flow.ts',
149
180
  'src/plugin/outbox-push-route-runtime-group.ts',
150
181
  'src/plugin/outbox-push.ts',
151
182
  'src/plugin/outbox-route.ts',
152
- 'src/plugin/outbox-text-push-flow.ts',
183
+ 'src/plugin/outbox-unified-push-flow.ts',
184
+ 'src/plugin/runtime-diagnostics-assembler.ts',
185
+ 'src/plugin/runtime-diagnostics-helpers.ts',
186
+ 'src/plugin/runtime-diagnostics-payload-builders.ts',
153
187
  'src/plugin/runtime-diagnostics-snapshot.ts',
188
+ 'src/plugin/scene-registry.ts',
154
189
  'src/plugin/setup.ts',
155
- 'src/plugin/state-transient-runtime-group.ts',
156
190
  'src/plugin/state-store.ts',
191
+ 'src/plugin/state-transient-runtime-group.ts',
192
+ 'src/plugin/status-runtime.ts',
193
+ 'src/plugin/status.ts',
157
194
  'src/plugin/target-runtime.ts',
158
195
  'src/plugin/target-status-runtime-group.ts',
159
196
  'src/plugin/transient-state-runtime.ts',
160
- 'src/plugin/status-runtime.ts',
161
- 'src/plugin/status.ts',
162
197
  'src/runtime/log-dedupe.ts',
163
198
  'src/runtime/outbound-ack-timeout.ts',
164
199
  'src/runtime/outbound-flags.ts',
@@ -44,7 +44,7 @@ export const pluginRoot = resolveBncrPluginRoot(pluginFile);
44
44
  const runtimeSourceDir = resolveBncrRuntimeSourceDir(pluginDir);
45
45
  let runtime: LoadedRuntime | null = null;
46
46
 
47
- export const readPluginVersion = (rootDir = pluginRoot) => {
47
+ const readPluginVersion = (rootDir = pluginRoot) => {
48
48
  try {
49
49
  const raw = fs.readFileSync(path.join(rootDir, 'package.json'), 'utf8');
50
50
  const parsed = JSON.parse(raw);
package/src/channel.ts CHANGED
@@ -19,10 +19,7 @@ import {
19
19
  emitBncrLog,
20
20
  summarizeBncrTextPreview,
21
21
  } from './core/logging.ts';
22
- import {
23
- buildFileTransferOutboxEntry as buildFileTransferOutboxEntryFromRuntime,
24
- buildTextOutboxEntry as buildTextOutboxEntryFromRuntime,
25
- } from './core/outbox-entry-builders.ts';
22
+ import { buildOutboxEntry as buildOutboxEntryFromRuntime } from './core/outbox-entry-builders.ts';
26
23
  import { summarizeOutboxEntry } from './core/outbox-summary.ts';
27
24
  import { normalizePersistedOutboxEntry as normalizePersistedOutboxEntryFromRuntime } from './core/persisted-outbox-entry.ts';
28
25
  import {
@@ -53,7 +50,6 @@ import { OUTBOUND_FLUSH_REASON, OUTBOUND_FLUSH_TRIGGER } from './messaging/outbo
53
50
  import type {
54
51
  NormalizedReplyPayload,
55
52
  OutboundReplyTargetPolicy,
56
- ReplyMediaEntriesParams,
57
53
  ReplyPayloadInput,
58
54
  } from './messaging/outbound/reply-enqueue.ts';
59
55
  import type { OpenClawChannelRuntimeApiHolder } from './openclaw/channel-runtime-contracts.ts';
@@ -67,7 +63,6 @@ import { createBncrBridgeConnectionFacade } from './plugin/bridge-connection-fac
67
63
  import { createBncrBridgeDiagnosticsFacade } from './plugin/bridge-diagnostics-facade.ts';
68
64
  import { createBncrBridgeDrainFacade } from './plugin/bridge-drain-facade.ts';
69
65
  import { createBncrBridgeExtendedDiagnosticsFacade } from './plugin/bridge-extended-diagnostics-facade.ts';
70
- import { createBncrBridgeFileTransferPushFacade } from './plugin/bridge-file-transfer-push-facade.ts';
71
66
  import {
72
67
  cleanupBncrBridgeRuntime,
73
68
  shutdownBncrBridgeService,
@@ -175,9 +170,9 @@ import { createBncrInboundSurfaceHandlersGroup } from './plugin/inbound-surface-
175
170
  import { createBncrMediaOrchestratorsRuntimeGroup } from './plugin/media-orchestrators-runtime-group.ts';
176
171
  import { BNCR_CHANNEL_META } from './plugin/meta.ts';
177
172
  import type { BncrOutboxAckOkTelemetryPatch } from './plugin/outbox-ack-outcome.ts';
178
- import { runBncrFileTransferOutboxPush } from './plugin/outbox-file-push-flow.ts';
173
+
179
174
  import { createBncrOutboxPushRouteRuntimeGroup } from './plugin/outbox-push-route-runtime-group.ts';
180
- import { runBncrTextOutboxPush } from './plugin/outbox-text-push-flow.ts';
175
+ import { runBncrOutboxPush } from './plugin/outbox-unified-push-flow.ts';
181
176
  import {
182
177
  createBncrDeadLetterDiagnosticsHelpers,
183
178
  createBncrDiagnosticsSelectionHelpers,
@@ -1131,83 +1126,53 @@ class BncrBridgeRuntime {
1131
1126
  // This block prepares media, chooses transfer mode, sends chunk/complete
1132
1127
  // frames, and feeds successful media pushes back into the shared outbox path.
1133
1128
 
1134
- private async pushFileTransferSuccessPath(args: {
1135
- entry: OutboxEntry;
1136
- msg: Record<string, unknown>;
1137
- owner: ReturnType<BncrBridgeRuntime['resolveOutboxPushOwner']>;
1138
- connIds: Iterable<string>;
1139
- recentInboundReachable: boolean;
1140
- routeReason: string;
1141
- mediaUrl: string;
1142
- }): Promise<void> {
1143
- await this.fileTransferPushFacade.pushFileTransferSuccessPath(args);
1144
- }
1145
-
1146
1129
  private handleFileTransferPushFailure(args: { entry: OutboxEntry; error: unknown }) {
1147
- this.fileTransferPushFacade.handleFileTransferPushFailure(args);
1130
+ this.outboxPush.handleFileTransferPushFailure(args);
1148
1131
  }
1149
1132
 
1150
1133
  private handleFileTransferPushGuardFailure(
1151
- args: Parameters<typeof this.fileTransferPushFacade.handleFileTransferPushGuardFailure>[0],
1134
+ args: Parameters<typeof this.outboxPush.handleFileTransferPushGuardFailure>[0],
1152
1135
  ) {
1153
- this.fileTransferPushFacade.handleFileTransferPushGuardFailure(args);
1136
+ this.outboxPush.handleFileTransferPushGuardFailure(args);
1154
1137
  }
1155
1138
 
1156
1139
  // File-transfer outbound entry builders / dedupe -------------------------
1157
1140
 
1158
- private async tryPushFileTransferEntry(
1159
- entry: OutboxEntry,
1160
- msg: Record<string, unknown>,
1161
- ): Promise<boolean> {
1162
- return await runBncrFileTransferOutboxPush({
1163
- entry,
1164
- msg,
1165
- gatewayContext: this.gatewayContext,
1166
- owner: this.resolveOutboxPushOwner(entry.accountId),
1167
- resolvePushConnIds: (accountId) => this.resolvePushConnIds(accountId),
1168
- resolveRecentInboundConnIds: (accountId) => this.resolveRecentInboundConnIds(accountId),
1169
- hasRecentInboundReachability: (accountId) => this.hasRecentInboundReachability(accountId),
1170
- isRevalidatedAttemptedConn: (connId) => this.isRevalidatedAttemptedConn(entry, connId),
1171
- handleFileTransferPushGuardFailure: (flowArgs) =>
1172
- this.handleFileTransferPushGuardFailure(flowArgs),
1173
- pushFileTransferSuccessPath: (flowArgs) => this.pushFileTransferSuccessPath(flowArgs),
1174
- handleFileTransferPushFailure: (flowArgs) => this.handleFileTransferPushFailure(flowArgs),
1175
- });
1176
- }
1177
-
1178
- private buildFileTransferOutboxEntry(params: {
1141
+ private buildOutboxEntry(params: {
1179
1142
  accountId: string;
1180
1143
  sessionKey: string;
1181
1144
  route: BncrRoute;
1182
- mediaUrl: string;
1183
- mediaLocalRoots?: readonly string[];
1184
- text?: string;
1185
- asVoice?: boolean;
1186
- audioAsVoice?: boolean;
1187
1145
  type?: string;
1188
- extra?: Record<string, unknown>;
1146
+ msg: string;
1189
1147
  kind?: 'tool' | 'block' | 'final';
1190
1148
  replyToId?: string;
1191
1149
  replyTargetPolicy?: OutboundReplyTargetPolicy;
1150
+ extra?: Record<string, unknown>;
1151
+ transferMode?: 'text' | 'media';
1152
+ mediaUrl?: string;
1153
+ mediaLocalRoots?: readonly string[];
1154
+ asVoice?: boolean;
1155
+ audioAsVoice?: boolean;
1192
1156
  downloadMedia?: boolean;
1193
1157
  }): OutboxEntry {
1194
- return buildFileTransferOutboxEntryFromRuntime({
1158
+ return buildOutboxEntryFromRuntime({
1195
1159
  createMessageId: () => randomUUID(),
1196
1160
  now,
1197
1161
  normalizeAccountId,
1198
1162
  accountId: params.accountId,
1199
1163
  sessionKey: params.sessionKey,
1200
1164
  route: params.route,
1201
- mediaUrl: params.mediaUrl,
1202
- mediaLocalRoots: params.mediaLocalRoots,
1203
- text: asString(params.text || ''),
1204
- asVoice: params.asVoice,
1205
- audioAsVoice: params.audioAsVoice,
1206
1165
  type: params.type,
1207
- extra: params.extra,
1166
+ msg: params.msg,
1208
1167
  kind: params.kind,
1209
1168
  replyToId: asString(params.replyToId || '').trim() || undefined,
1210
1169
  replyTargetPolicy: params.replyTargetPolicy,
1170
+ extra: params.extra,
1171
+ transferMode: params.transferMode,
1172
+ mediaUrl: params.mediaUrl,
1173
+ mediaLocalRoots: params.mediaLocalRoots,
1174
+ asVoice: params.asVoice,
1175
+ audioAsVoice: params.audioAsVoice,
1211
1176
  downloadMedia: params.downloadMedia,
1212
1177
  });
1213
1178
  }
@@ -1321,66 +1286,8 @@ class BncrBridgeRuntime {
1321
1286
  // This is the core outbound state machine: build entries, enqueue them,
1322
1287
  // push them, observe ACK outcomes, and terminate in retry or dead-letter.
1323
1288
 
1324
- private buildTextOutboxEntry(params: {
1325
- accountId: string;
1326
- sessionKey: string;
1327
- route: BncrRoute;
1328
- text: string;
1329
- extra?: Record<string, unknown>;
1330
- kind?: 'tool' | 'block' | 'final';
1331
- replyToId?: string;
1332
- replyTargetPolicy?: OutboundReplyTargetPolicy;
1333
- }): OutboxEntry {
1334
- return buildTextOutboxEntryFromRuntime({
1335
- createMessageId: () => randomUUID(),
1336
- now,
1337
- normalizeAccountId,
1338
- accountId: params.accountId,
1339
- sessionKey: params.sessionKey,
1340
- route: params.route,
1341
- text: params.text,
1342
- extra: params.extra && Object.keys(params.extra).length > 0 ? { ...params.extra } : undefined,
1343
- kind: params.kind,
1344
- replyToId: params.replyToId,
1345
- replyTargetPolicy: params.replyTargetPolicy,
1346
- });
1347
- }
1348
-
1349
1289
  private async tryPushEntry(entry: OutboxEntry): Promise<boolean> {
1350
- const msg =
1351
- isPlainObject(entry.payload) &&
1352
- isPlainObject((entry.payload as Record<string, unknown>).message)
1353
- ? ((entry.payload as Record<string, unknown>).message as Record<string, unknown>)
1354
- : null;
1355
- if (msg?.transferMode === 'media') {
1356
- return this.tryPushFileTransferEntry(entry, msg);
1357
- }
1358
- return this.tryPushTextEntry(entry);
1359
- }
1360
-
1361
- private pushTextSuccessPath(args: {
1362
- entry: OutboxEntry;
1363
- owner: ReturnType<BncrBridgeRuntime['resolveOutboxPushOwner']>;
1364
- connIds: Iterable<string>;
1365
- recentInboundReachable: boolean;
1366
- routeReason: string;
1367
- ownerConnId?: string;
1368
- }) {
1369
- this.outboxPush.pushTextSuccessPath(args);
1370
- }
1371
-
1372
- private handleTextPushFailure(args: { entry: OutboxEntry; error: unknown }) {
1373
- this.outboxPush.handleTextPushFailure(args);
1374
- }
1375
-
1376
- // Text outbound push runtime bridge --------------------------------------
1377
-
1378
- // Outbound diagnostics/logging helpers -----------------------------------
1379
- // Keep the compact logging helpers adjacent to the outbound state machine so
1380
- // queue transitions and emitted diagnostics remain easy to correlate.
1381
-
1382
- private async tryPushTextEntry(entry: OutboxEntry): Promise<boolean> {
1383
- return await runBncrTextOutboxPush({
1290
+ return runBncrOutboxPush({
1384
1291
  entry,
1385
1292
  gatewayContext: this.gatewayContext,
1386
1293
  owner: this.resolveOutboxPushOwner(entry.accountId),
@@ -1390,11 +1297,34 @@ class BncrBridgeRuntime {
1390
1297
  isRevalidatedAttemptedConn: (connId) => this.isRevalidatedAttemptedConn(entry, connId),
1391
1298
  recordOutboxPrePushFailure: (flowArgs) => this.recordOutboxPrePushFailure(flowArgs),
1392
1299
  logOutboxPushSkip: (flowArgs) => this.logOutboxPushSkip(flowArgs),
1393
- pushTextSuccessPath: (flowArgs) => this.pushTextSuccessPath(flowArgs),
1300
+ handleFileTransferPushGuardFailure: (flowArgs) =>
1301
+ this.handleFileTransferPushGuardFailure(flowArgs),
1394
1302
  handleTextPushFailure: (flowArgs) => this.handleTextPushFailure(flowArgs),
1303
+ handleFileTransferPushFailure: (flowArgs) => this.handleFileTransferPushFailure(flowArgs),
1304
+ // Unified push deps
1305
+ pushEvent: BNCR_PUSH_EVENT,
1306
+ gatewayBroadcastToConnIds: (event, payload, connIds) =>
1307
+ this.gatewayContext?.broadcastToConnIds(event, payload, connIds),
1308
+ recordOutboxPushSuccess: (args) => this.recordOutboxPushSuccess(args),
1309
+ logOutboxRouteSelect: (args) => this.logOutboxRouteSelect(args),
1310
+ logOutboxPushOkSummary: (mid) => this.logOutboxPushOkSummary(mid),
1311
+ logOutboundSummary: (entry) => this.logOutboundSummary(entry),
1312
+ logOutboxPushOk: (args) => this.logOutboxPushOk(args),
1313
+ transferMediaToBncrClient: (params) => this.transferMediaToBncrClient(params),
1314
+ buildFileTransferOutboundFrame: (params) => this.buildFileTransferOutboundFrame(params),
1395
1315
  });
1396
1316
  }
1397
1317
 
1318
+ private handleTextPushFailure(args: { entry: OutboxEntry; error: unknown }) {
1319
+ this.outboxPush.handleTextPushFailure(args);
1320
+ }
1321
+
1322
+ // Text outbound push runtime bridge --------------------------------------
1323
+
1324
+ // Outbound diagnostics/logging helpers -----------------------------------
1325
+ // Keep the compact logging helpers adjacent to the outbound state machine so
1326
+ // queue transitions and emitted diagnostics remain easy to correlate.
1327
+
1398
1328
  private logOutboxPushSkip(args: {
1399
1329
  messageId: string;
1400
1330
  accountId: string;
@@ -1811,6 +1741,7 @@ class BncrBridgeRuntime {
1811
1741
  handleFileTransferPushFailure: (args) => this.handleFileTransferPushFailure(args),
1812
1742
  handleTextPushFailure: (args) => this.handleTextPushFailure(args),
1813
1743
  isPrePushGuardDeferral: (entry) => this.isPrePushGuardDeferral(entry),
1744
+ resolveActiveAccountIds: () => this.activeConnectionByAccount.keys(),
1814
1745
  resolveAccountIdForSession: (sessionKey) => {
1815
1746
  const hit = this.sessionRoutes.get(sessionKey);
1816
1747
  return hit ? hit.accountId : BNCR_DEFAULT_ACCOUNT_ID;
@@ -2734,8 +2665,7 @@ class BncrBridgeRuntime {
2734
2665
  logInfo: (scope, message, options) => this.logInfo(scope, message, options),
2735
2666
  logEnqueueFromReply: (args) => this.logEnqueueFromReply(args),
2736
2667
  enqueueOutbound: (entry) => this.enqueueOutbound(entry),
2737
- buildTextOutboxEntry: (args) => this.buildTextOutboxEntry(args),
2738
- buildFileTransferOutboxEntry: (args) => this.buildFileTransferOutboxEntry(args),
2668
+ buildOutboxEntry: (args) => this.buildOutboxEntry(args),
2739
2669
  rememberRecentMediaSend: (args) => this.rememberRecentMediaSend(args),
2740
2670
  tryBuildMediaDedupeFallback: (args) => this.tryBuildMediaDedupeFallback(args),
2741
2671
  });
@@ -2789,7 +2719,7 @@ class BncrBridgeRuntime {
2789
2719
  mediaLocalRoots?: readonly string[];
2790
2720
  replyTargetPolicy?: OutboundReplyTargetPolicy;
2791
2721
  }) {
2792
- this.bridgeMediaFacade.enqueueFromReply(params);
2722
+ return this.bridgeMediaFacade.enqueueFromReply(params);
2793
2723
  }
2794
2724
 
2795
2725
  private logEnqueueFromReply(args: {
@@ -2829,24 +2759,6 @@ class BncrBridgeRuntime {
2829
2759
  normalizeAccountId,
2830
2760
  });
2831
2761
 
2832
- private readonly fileTransferPushFacade = createBncrBridgeFileTransferPushFacade({
2833
- pushEvent: BNCR_PUSH_EVENT,
2834
- getGatewayContext: () => this.gatewayContext,
2835
- transferMediaToBncrClient: (params) => this.transferMediaToBncrClient(params),
2836
- buildFileTransferOutboundFrame: (params) => this.buildFileTransferOutboundFrame(params),
2837
- logOutboxRouteSelect: (args) => this.logOutboxRouteSelect(args),
2838
- recordOutboxPushSuccess: (args) => this.recordOutboxPushSuccess(args),
2839
- logOutboxPushOkSummary: (messageId) => this.logOutboxPushOkSummary(messageId),
2840
- logOutboxPushOk: (args) => this.logOutboxPushOk(args),
2841
- handleFileTransferPushFailure: (args) => this.outboxPush.handleFileTransferPushFailure(args),
2842
- handleFileTransferPushGuardFailure: (args) =>
2843
- this.outboxPush.handleFileTransferPushGuardFailure(args),
2844
- });
2845
-
2846
- private enqueueReplyMediaEntries(params: ReplyMediaEntriesParams) {
2847
- this.bridgeMediaFacade.enqueueReplyMediaEntries(params);
2848
- }
2849
-
2850
2762
  // Surface runtime assembly -----------------------------------------------
2851
2763
  // The bridge remains the ownership root, but these builders keep the final
2852
2764
  // gateway/inbound/channel send wiring readable by concern instead of as one
@@ -141,7 +141,7 @@ function scoreOutboundPushConnection(args: {
141
141
  };
142
142
  }
143
143
 
144
- export function compareOutboundPushConnections(args: {
144
+ function compareOutboundPushConnections(args: {
145
145
  a: BncrConnection;
146
146
  b: BncrConnection;
147
147
  now: number;
@@ -117,7 +117,7 @@ function sanitizeDebugValue(key: string, value: unknown): unknown {
117
117
  return value;
118
118
  }
119
119
 
120
- export function sanitizeBncrDebugPayload(payload: Record<string, unknown>) {
120
+ function sanitizeBncrDebugPayload(payload: Record<string, unknown>) {
121
121
  return sanitizeDebugPayload(payload);
122
122
  }
123
123