@xmoxmo/bncr 0.5.7 → 0.5.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 (41) hide show
  1. package/package.json +1 -1
  2. package/scripts/check-pack.mjs +0 -2
  3. package/scripts/selfcheck.mjs +0 -3
  4. package/src/bootstrap/runtime-loader.ts +1 -1
  5. package/src/channel.ts +49 -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 +215 -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/bridge-media-facade.ts +0 -3
  22. package/src/plugin/bridge-outbox-facade.ts +0 -1
  23. package/src/plugin/channel-runtime-builders-delivery.ts +2 -362
  24. package/src/plugin/channel-runtime-builders-status.ts +0 -160
  25. package/src/plugin/channel-runtime-builders.ts +3 -17
  26. package/src/plugin/channel-runtime-constants.ts +1 -1
  27. package/src/plugin/channel-send.ts +5 -4
  28. package/src/plugin/file-transfer-orchestrator.ts +39 -2
  29. package/src/plugin/media-orchestrators-runtime-group.ts +20 -149
  30. package/src/plugin/messaging.ts +3 -3
  31. package/src/plugin/outbox-push.ts +1 -52
  32. package/src/plugin/outbox-unified-push-flow.ts +307 -0
  33. package/src/plugin/scene-registry.ts +1 -1
  34. package/src/runtime/log-dedupe.ts +3 -3
  35. package/src/runtime/outbound-ack-timeout.ts +2 -4
  36. package/src/runtime/status-snapshots.ts +2 -2
  37. package/src/runtime/status-worker.ts +2 -6
  38. package/src/core/outbox-text-push-prep.ts +0 -1
  39. package/src/plugin/bridge-file-transfer-push-facade.ts +0 -142
  40. package/src/plugin/outbox-file-push-flow.ts +0 -69
  41. package/src/plugin/outbox-text-push-flow.ts +0 -90
@@ -5,10 +5,10 @@ export type LogDedupeStateEntry = {
5
5
 
6
6
  export type LogDedupeState = Map<string, LogDedupeStateEntry>;
7
7
 
8
- export const LOG_DEDUPE_STATE_TTL_MS = 10 * 60 * 1000;
9
- export const LOG_DEDUPE_STATE_MAX_ENTRIES = 1_000;
8
+ const LOG_DEDUPE_STATE_TTL_MS = 10 * 60 * 1000;
9
+ const LOG_DEDUPE_STATE_MAX_ENTRIES = 1_000;
10
10
 
11
- export function pruneLogDedupeState(
11
+ function pruneLogDedupeState(
12
12
  state: LogDedupeState,
13
13
  currentTime: number,
14
14
  options?: {
@@ -42,9 +42,7 @@ function isAdaptiveAckRecovered(args: {
42
42
  );
43
43
  }
44
44
 
45
- export function computeBncrRecommendedAckTimeoutReason(
46
- args: ComputeBncrRecommendedAckTimeoutReasonArgs,
47
- ) {
45
+ function computeBncrRecommendedAckTimeoutReason(args: ComputeBncrRecommendedAckTimeoutReasonArgs) {
48
46
  if (args.recentAckTimeoutCount <= 0) return 'no-timeout-evidence';
49
47
  if (args.lateAckOkCount <= 0) return 'no-late-ack-evidence';
50
48
  if (typeof args.lastLateAckPushLatencyMs !== 'number') return 'missing-latency';
@@ -54,7 +52,7 @@ export function computeBncrRecommendedAckTimeoutReason(
54
52
  return 'late-ack-observed';
55
53
  }
56
54
 
57
- export function computeBncrRecommendedAckTimeoutMs(args: ComputeBncrRecommendedAckTimeoutArgs) {
55
+ function computeBncrRecommendedAckTimeoutMs(args: ComputeBncrRecommendedAckTimeoutArgs) {
58
56
  if (
59
57
  args.lateAckOkCount <= 0 ||
60
58
  args.recentAckTimeoutCount <= 0 ||
@@ -34,7 +34,7 @@ function getCounter(map: Map<string, number>, accountId: string): number {
34
34
  return map.get(normalizeAccountId(accountId)) || 0;
35
35
  }
36
36
 
37
- export function buildRuntimeQueueSnapshot(args: {
37
+ function buildRuntimeQueueSnapshot(args: {
38
38
  accountId: string;
39
39
  outboxEntries: Iterable<OutboxEntry>;
40
40
  deadLetterEntries: Iterable<OutboxEntry>;
@@ -59,7 +59,7 @@ export function buildRuntimeQueueSnapshot(args: {
59
59
  };
60
60
  }
61
61
 
62
- export function buildRuntimeEventCounters(args: {
62
+ function buildRuntimeEventCounters(args: {
63
63
  accountId: string;
64
64
  connectEventsByAccount: Map<string, number>;
65
65
  inboundEventsByAccount: Map<string, number>;
@@ -49,7 +49,7 @@ export type ChannelAccountWorkerHandle = {
49
49
  healthLogState?: HealthStatusLogState;
50
50
  };
51
51
 
52
- export const HEALTH_STATUS_STABLE_WINDOW_MS = 10_000;
52
+ const HEALTH_STATUS_STABLE_WINDOW_MS = 10_000;
53
53
 
54
54
  export type HealthStatusLogState = {
55
55
  emittedSig: string | null;
@@ -112,11 +112,7 @@ type StatusWorkerRuntime = {
112
112
  hooks: StatusWorkerHooks;
113
113
  };
114
114
 
115
- export function clearBncrStatusWorker(
116
- runtime: StatusWorkerRuntime,
117
- accountId: string,
118
- reason: string,
119
- ) {
115
+ function clearBncrStatusWorker(runtime: StatusWorkerRuntime, accountId: string, reason: string) {
120
116
  const worker = runtime.workers.get(accountId);
121
117
  if (!worker) return false;
122
118
  worker.finish(reason);
@@ -1 +0,0 @@
1
- export { prepareRouteSelection as prepareTextPushRouteSelection } from './outbox-file-transfer-prep.ts';
@@ -1,142 +0,0 @@
1
- import {
2
- buildFileTransferPushOkArgs,
3
- buildFileTransferPushSuccessArgs,
4
- } from '../core/outbox-file-transfer-bookkeeping.ts';
5
- import {
6
- buildFileTransferBroadcastPayload,
7
- buildFileTransferRouteSelectArgs,
8
- } from '../core/outbox-file-transfer-success.ts';
9
- import type { BncrConnection, BncrRoute, OutboxEntry } from '../core/types.ts';
10
-
11
- export function createBncrBridgeFileTransferPushFacade(runtime: {
12
- pushEvent: string;
13
- getGatewayContext: () => {
14
- broadcastToConnIds: (event: string, payload: unknown, connIds: ReadonlySet<string>) => void;
15
- } | null;
16
- transferMediaToBncrClient: (params: {
17
- accountId: string;
18
- sessionKey: string;
19
- route: BncrRoute;
20
- mediaUrl: string;
21
- mediaLocalRoots?: readonly string[];
22
- downloadMedia?: boolean;
23
- }) => Promise<{
24
- mode: 'base64' | 'chunk';
25
- mimeType?: string;
26
- fileName?: string;
27
- base64?: string;
28
- path?: string;
29
- }>;
30
- buildFileTransferOutboundFrame: (params: {
31
- entry: OutboxEntry;
32
- msg: Record<string, unknown>;
33
- media: { fileName?: string; mimeType?: string; path?: string; base64?: string; type?: string };
34
- mediaUrl: string;
35
- }) => Record<string, unknown>;
36
- logOutboxRouteSelect: (args: {
37
- messageId: string;
38
- accountId: string;
39
- kind?: 'file-transfer';
40
- routeReason: string;
41
- connIds: Iterable<string>;
42
- ownerConnId: string;
43
- ownerClientId: string;
44
- recentInboundReachable: boolean;
45
- event: string;
46
- }) => void;
47
- recordOutboxPushSuccess: (args: {
48
- entry: OutboxEntry;
49
- connIds: Iterable<string>;
50
- ownerConnId?: string;
51
- ownerClientId?: string;
52
- clearLastError?: boolean;
53
- }) => void;
54
- logOutboxPushOkSummary: (messageId: string) => void;
55
- logOutboxPushOk: (args: {
56
- messageId: string;
57
- accountId: string;
58
- kind?: 'file-transfer';
59
- connIds: Iterable<string>;
60
- ownerConnId: string;
61
- ownerClientId: string;
62
- recentInboundReachable: boolean;
63
- event: string;
64
- }) => void;
65
- handleFileTransferPushFailure: (args: { entry: OutboxEntry; error: unknown }) => void;
66
- handleFileTransferPushGuardFailure: (args: {
67
- entry: OutboxEntry;
68
- guard: {
69
- reason: 'media-url-missing' | 'no-gateway-context' | 'no-active-connection';
70
- lastError: string;
71
- recentInboundReachable?: boolean;
72
- };
73
- }) => void;
74
- }) {
75
- const pushFileTransferSuccessPath = async (args: {
76
- entry: OutboxEntry;
77
- msg: Record<string, unknown>;
78
- owner: BncrConnection | null;
79
- connIds: Iterable<string>;
80
- recentInboundReachable: boolean;
81
- routeReason: string;
82
- mediaUrl: string;
83
- }): Promise<void> => {
84
- const media = await runtime.transferMediaToBncrClient({
85
- accountId: args.entry.accountId,
86
- sessionKey: args.entry.sessionKey,
87
- route: args.entry.route,
88
- mediaUrl: args.mediaUrl,
89
- mediaLocalRoots: Array.isArray(args.msg.mediaLocalRoots)
90
- ? args.msg.mediaLocalRoots.filter((v): v is string => typeof v === 'string')
91
- : undefined,
92
- downloadMedia: args.msg.downloadMedia as boolean | undefined,
93
- });
94
- const frame = runtime.buildFileTransferOutboundFrame({
95
- entry: args.entry,
96
- msg: args.msg,
97
- media,
98
- mediaUrl: args.mediaUrl,
99
- });
100
-
101
- runtime.getGatewayContext()!.broadcastToConnIds(
102
- runtime.pushEvent,
103
- buildFileTransferBroadcastPayload({
104
- frame,
105
- messageId: args.entry.messageId,
106
- }),
107
- new Set(args.connIds),
108
- );
109
- runtime.logOutboxRouteSelect(
110
- buildFileTransferRouteSelectArgs({
111
- entry: args.entry,
112
- connIds: args.connIds,
113
- routeReason: args.routeReason,
114
- recentInboundReachable: args.recentInboundReachable,
115
- owner: args.owner,
116
- event: runtime.pushEvent,
117
- }),
118
- );
119
- runtime.recordOutboxPushSuccess(
120
- buildFileTransferPushSuccessArgs({
121
- entry: args.entry,
122
- connIds: args.connIds,
123
- owner: args.owner,
124
- }),
125
- );
126
- runtime.logOutboxPushOkSummary(args.entry.messageId);
127
- runtime.logOutboxPushOk(
128
- buildFileTransferPushOkArgs({
129
- entry: args.entry,
130
- connIds: args.connIds,
131
- recentInboundReachable: args.recentInboundReachable,
132
- event: runtime.pushEvent,
133
- }),
134
- );
135
- };
136
-
137
- return {
138
- pushFileTransferSuccessPath,
139
- handleFileTransferPushFailure: runtime.handleFileTransferPushFailure,
140
- handleFileTransferPushGuardFailure: runtime.handleFileTransferPushGuardFailure,
141
- };
142
- }
@@ -1,69 +0,0 @@
1
- import { resolveFileTransferGuard } from '../core/outbox-file-transfer-guards.ts';
2
- import { prepareRouteSelection } from '../core/outbox-file-transfer-prep.ts';
3
- import type { BncrConnection, OutboxEntry } from '../core/types.ts';
4
- import { selectOutboxFileTransferRouteCandidates } from '../messaging/outbound/queue-selectors.ts';
5
-
6
- export async function runBncrFileTransferOutboxPush(args: {
7
- entry: OutboxEntry;
8
- msg: Record<string, unknown>;
9
- gatewayContext: unknown;
10
- owner: BncrConnection | null;
11
- resolvePushConnIds: (accountId: string) => Set<string>;
12
- resolveRecentInboundConnIds: (accountId: string) => Set<string>;
13
- hasRecentInboundReachability: (accountId: string) => boolean;
14
- isRevalidatedAttemptedConn: (connId: string) => boolean;
15
- handleFileTransferPushGuardFailure: (args: {
16
- entry: OutboxEntry;
17
- guard: Exclude<ReturnType<typeof resolveFileTransferGuard>, { ok: true }>;
18
- }) => void;
19
- pushFileTransferSuccessPath: (args: {
20
- entry: OutboxEntry;
21
- msg: Record<string, unknown>;
22
- owner: BncrConnection | null;
23
- connIds: Iterable<string>;
24
- recentInboundReachable: boolean;
25
- routeReason: string;
26
- mediaUrl: string;
27
- }) => Promise<void>;
28
- handleFileTransferPushFailure: (args: { entry: OutboxEntry; error: unknown }) => void;
29
- }) {
30
- const selection = prepareRouteSelection({
31
- entry: args.entry,
32
- owner: args.owner,
33
- resolvePushConnIds: args.resolvePushConnIds,
34
- resolveRecentInboundConnIds: args.resolveRecentInboundConnIds,
35
- hasRecentInboundReachability: args.hasRecentInboundReachability,
36
- isRevalidatedAttemptedConn: args.isRevalidatedAttemptedConn,
37
- selectRouteCandidates: selectOutboxFileTransferRouteCandidates,
38
- });
39
- const guard = resolveFileTransferGuard({
40
- gatewayContext: args.gatewayContext,
41
- entry: args.entry,
42
- owner: args.owner,
43
- routeSelection: selection,
44
- mediaUrl: String(args.msg.mediaUrl || '').trim(),
45
- });
46
- if (!guard.ok) {
47
- args.handleFileTransferPushGuardFailure({
48
- entry: args.entry,
49
- guard,
50
- });
51
- return false;
52
- }
53
-
54
- try {
55
- await args.pushFileTransferSuccessPath({
56
- entry: args.entry,
57
- msg: args.msg,
58
- owner: args.owner,
59
- connIds: guard.connIds,
60
- recentInboundReachable: guard.recentInboundReachable,
61
- routeReason: guard.routeReason,
62
- mediaUrl: guard.mediaUrl,
63
- });
64
- return true;
65
- } catch (error) {
66
- args.handleFileTransferPushFailure({ entry: args.entry, error });
67
- return false;
68
- }
69
- }
@@ -1,90 +0,0 @@
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
- selectRouteCandidates: 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
- }