@masons/runtime-broker 0.2.0 → 0.2.1
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.
- package/dist/broker/broker-daemon.d.ts +7 -0
- package/dist/broker/broker-daemon.d.ts.map +1 -1
- package/dist/broker/broker-daemon.js +223 -28
- package/dist/broker/connector-ws.d.ts +4 -0
- package/dist/broker/connector-ws.d.ts.map +1 -1
- package/dist/broker/connector-ws.js +12 -0
- package/dist/broker/delivery-cursor-file.d.ts +8 -0
- package/dist/broker/delivery-cursor-file.d.ts.map +1 -0
- package/dist/broker/delivery-cursor-file.js +71 -0
- package/dist/broker/entry.d.ts.map +1 -1
- package/dist/broker/entry.js +4 -1
- package/dist/broker/ipc-server.d.ts +2 -1
- package/dist/broker/ipc-server.d.ts.map +1 -1
- package/dist/broker/ipc-server.js +2 -1
- package/dist/broker/paths.d.ts +1 -0
- package/dist/broker/paths.d.ts.map +1 -1
- package/dist/broker/paths.js +1 -0
- package/dist/broker/reconnecting-buffer.d.ts +1 -0
- package/dist/broker/reconnecting-buffer.d.ts.map +1 -1
- package/dist/broker/runtime-endpoint-port.d.ts +2 -0
- package/dist/broker/runtime-endpoint-port.d.ts.map +1 -1
- package/dist/broker/runtime-inbound-routed-emitter.d.ts +22 -0
- package/dist/broker/runtime-inbound-routed-emitter.d.ts.map +1 -0
- package/dist/broker/runtime-inbound-routed-emitter.js +147 -0
- package/dist/broker/runtime-inbound-routed-event-types.d.ts +10 -0
- package/dist/broker/runtime-inbound-routed-event-types.d.ts.map +1 -0
- package/dist/broker/runtime-inbound-routed-event-types.js +1 -0
- package/dist/broker/undispatched-changed-event-types.d.ts +1 -0
- package/dist/broker/undispatched-changed-event-types.d.ts.map +1 -1
- package/dist/broker/undispatched-inbox.d.ts +1 -0
- package/dist/broker/undispatched-inbox.d.ts.map +1 -1
- package/dist/broker/version-handshake.js +1 -1
- package/dist/broker-client/broker-client.d.ts +1 -0
- package/dist/broker-client/broker-client.d.ts.map +1 -1
- package/dist/broker-client/broker-client.js +3 -0
- package/dist/connector-client.d.ts +5 -0
- package/dist/connector-client.d.ts.map +1 -1
- package/dist/connector-client.js +47 -5
- package/dist/runtime-endpoint-client.d.ts +4 -0
- package/dist/runtime-endpoint-client.d.ts.map +1 -1
- package/dist/runtime-endpoint-client.js +33 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +13 -12
|
@@ -11,6 +11,7 @@ import type { NetworkPresenceChangedEvent } from "./network-presence-changed-eve
|
|
|
11
11
|
import type { BrokerPaths } from "./paths.js";
|
|
12
12
|
import { type BufferedMessage } from "./reconnecting-buffer.js";
|
|
13
13
|
import type { RuntimeEndpointPort } from "./runtime-endpoint-port.js";
|
|
14
|
+
import type { RuntimeInboundRoutedEvent } from "./runtime-inbound-routed-event-types.js";
|
|
14
15
|
import type { ServicesEventClient } from "./services-event-client.js";
|
|
15
16
|
import type { SpawnDriverRegistry } from "./spawn-driver.js";
|
|
16
17
|
import { type UndispatchedChangedEvent } from "./undispatched-changed-event-types.js";
|
|
@@ -49,6 +50,11 @@ export interface BrokerDaemonOptions {
|
|
|
49
50
|
networkPresenceChangedBackoffInitialMs?: number;
|
|
50
51
|
networkPresenceChangedBackoffMaxMs?: number;
|
|
51
52
|
networkPresenceChangedMaxRetries?: number;
|
|
53
|
+
runtimeInboundRoutedPost?: (event: RuntimeInboundRoutedEvent) => Promise<import("./runtime-endpoint-port.js").EmitOutcome>;
|
|
54
|
+
runtimeInboundRoutedCapacity?: number;
|
|
55
|
+
runtimeInboundRoutedBackoffInitialMs?: number;
|
|
56
|
+
runtimeInboundRoutedBackoffMaxMs?: number;
|
|
57
|
+
runtimeInboundRoutedMaxRetries?: number;
|
|
52
58
|
}
|
|
53
59
|
export interface RunningBroker {
|
|
54
60
|
bearerToken: string;
|
|
@@ -64,6 +70,7 @@ export interface RunningBroker {
|
|
|
64
70
|
replyCorrelationCacheSize(endpoint_id: string): number;
|
|
65
71
|
undispatchedChangedQueueSize(): number;
|
|
66
72
|
networkPresenceChangedQueueSize(): number;
|
|
73
|
+
runtimeInboundRoutedQueueSize(): number;
|
|
67
74
|
}
|
|
68
75
|
export declare function startBrokerDaemon(opts: BrokerDaemonOptions): Promise<RunningBroker>;
|
|
69
76
|
export declare function readPluginPidHeader(req: IncomingMessage): number | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"broker-daemon.d.ts","sourceRoot":"","sources":["../../src/broker/broker-daemon.ts"],"names":[],"mappings":"AA2BA,OAAO,EAAqB,KAAK,IAAI,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAE5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"broker-daemon.d.ts","sourceRoot":"","sources":["../../src/broker/broker-daemon.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { spawn as spawnChild } from "node:child_process";
|
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { basename } from "node:path";
|
|
4
4
|
import { createControlEventDispatcher, } from "./control-event-dispatcher.js";
|
|
5
|
+
import { readDeliveryCursorFile, writeDeliveryCursorFile, } from "./delivery-cursor-file.js";
|
|
5
6
|
import { deleteDiscoveryFile, mintBearerToken, writeDiscoveryFile, } from "./discovery-file.js";
|
|
6
7
|
import { EndpointRegistry } from "./endpoint-registry.js";
|
|
7
8
|
import { DEFAULT_GRACE_MS, transition, } from "./endpoint-state-machine.js";
|
|
@@ -13,12 +14,14 @@ import { isPluginAlive as defaultIsPluginAlive } from "./plugin-liveness.js";
|
|
|
13
14
|
import { createReceivedMessageCorrelationCache, DEFAULT_TTL_MS as DEFAULT_REPLY_CORRELATION_TTL_MS, } from "./received-message-correlation-cache.js";
|
|
14
15
|
import { createReconnectingBufferManager, } from "./reconnecting-buffer.js";
|
|
15
16
|
import { RoutingTable } from "./routing-table.js";
|
|
17
|
+
import { createRuntimeInboundRoutedEmitter, postRuntimeInboundRoutedViaPort, } from "./runtime-inbound-routed-emitter.js";
|
|
16
18
|
import { createSpawnCorrelationManager, createSpawnRateLimiter, } from "./spawn-correlation.js";
|
|
17
19
|
import { TASK_HINT_MAX_LENGTH, updateTaskHint } from "./task-hint-handler.js";
|
|
18
20
|
import { createTransitionStateRetryQueue } from "./transition-state-retry-queue.js";
|
|
19
21
|
import { CONTENT_PREVIEW_MAX_CODEPOINTS, truncateContentPreview, } from "./undispatched-changed-event-types.js";
|
|
20
22
|
import { createUndispatchedChangedEmitter, postUndispatchedChangedViaPort, } from "./undispatched-emitter.js";
|
|
21
23
|
import { createUndispatchedInbox, } from "./undispatched-inbox.js";
|
|
24
|
+
const REMOTE_SPAWN_CAPABILITY = "remote_spawn_v1";
|
|
22
25
|
function derivePublicDisplayLabel(body) {
|
|
23
26
|
const parts = [
|
|
24
27
|
body.kind,
|
|
@@ -40,6 +43,11 @@ export async function startBrokerDaemon(opts) {
|
|
|
40
43
|
(async () => {
|
|
41
44
|
});
|
|
42
45
|
void _asNodeIdReservedForA3;
|
|
46
|
+
const persistedDeliveryCursor = readDeliveryCursorFile(paths.deliveryCursorFile) ?? 0;
|
|
47
|
+
connector.setDeliveryCursor(persistedDeliveryCursor);
|
|
48
|
+
logger.info("delivery_cursor_loaded", {
|
|
49
|
+
lastKnownSeq: persistedDeliveryCursor,
|
|
50
|
+
});
|
|
43
51
|
logger.info("connecting_to_connector");
|
|
44
52
|
await connector.connect();
|
|
45
53
|
logger.info("connector_connected");
|
|
@@ -86,7 +94,8 @@ export async function startBrokerDaemon(opts) {
|
|
|
86
94
|
}
|
|
87
95
|
}, replyCorrelationSweepInterval);
|
|
88
96
|
replyCorrelationSweepTimer.unref?.();
|
|
89
|
-
const
|
|
97
|
+
const postUndispatchedChanged = opts.undispatchedChangedPost ?? postUndispatchedChangedViaPort(apiPort);
|
|
98
|
+
const undispatchedEmitter = createUndispatchedChangedEmitter(postUndispatchedChanged, logger, {
|
|
90
99
|
capacity: opts.undispatchedChangedCapacity,
|
|
91
100
|
backoffInitialMs: opts.undispatchedChangedBackoffInitialMs,
|
|
92
101
|
backoffMaxMs: opts.undispatchedChangedBackoffMaxMs,
|
|
@@ -105,6 +114,79 @@ export async function startBrokerDaemon(opts) {
|
|
|
105
114
|
const emitNetworkPresence = (event) => {
|
|
106
115
|
networkPresenceEmitter.enqueue(event);
|
|
107
116
|
};
|
|
117
|
+
const postRuntimeInboundRouted = opts.runtimeInboundRoutedPost ?? postRuntimeInboundRoutedViaPort(apiPort);
|
|
118
|
+
const runtimeInboundRoutedEmitter = createRuntimeInboundRoutedEmitter(postRuntimeInboundRouted, logger, {
|
|
119
|
+
capacity: opts.runtimeInboundRoutedCapacity,
|
|
120
|
+
backoffInitialMs: opts.runtimeInboundRoutedBackoffInitialMs,
|
|
121
|
+
backoffMaxMs: opts.runtimeInboundRoutedBackoffMaxMs,
|
|
122
|
+
maxRetries: opts.runtimeInboundRoutedMaxRetries,
|
|
123
|
+
});
|
|
124
|
+
const directPostUndispatched = async (event, opts = {}) => {
|
|
125
|
+
let outcome;
|
|
126
|
+
try {
|
|
127
|
+
outcome = await postUndispatchedChanged(event);
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
outcome = {
|
|
131
|
+
ok: false,
|
|
132
|
+
terminal: false,
|
|
133
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
if (outcome.ok)
|
|
137
|
+
return true;
|
|
138
|
+
logger.warn("undispatched_changed_direct_post_failed", {
|
|
139
|
+
action: event.action,
|
|
140
|
+
undispatched_id: event.undispatched_id,
|
|
141
|
+
terminal: outcome.terminal,
|
|
142
|
+
status: outcome.status,
|
|
143
|
+
detail: outcome.detail,
|
|
144
|
+
});
|
|
145
|
+
if (!outcome.terminal && opts.queueOnTransientFailure !== false) {
|
|
146
|
+
undispatchedEmitter.enqueue(event);
|
|
147
|
+
}
|
|
148
|
+
return false;
|
|
149
|
+
};
|
|
150
|
+
const directPostRuntimeInboundRouted = async (event, opts = {}) => {
|
|
151
|
+
let outcome;
|
|
152
|
+
try {
|
|
153
|
+
outcome = await postRuntimeInboundRouted(event);
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
outcome = {
|
|
157
|
+
ok: false,
|
|
158
|
+
terminal: false,
|
|
159
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
if (outcome.ok)
|
|
163
|
+
return true;
|
|
164
|
+
logger.warn("runtime_inbound_routed_direct_post_failed", {
|
|
165
|
+
source_message_id: event.source_message_id,
|
|
166
|
+
routed_to_endpoint_id: event.routed_to_endpoint_id,
|
|
167
|
+
terminal: outcome.terminal,
|
|
168
|
+
status: outcome.status,
|
|
169
|
+
detail: outcome.detail,
|
|
170
|
+
});
|
|
171
|
+
if (!outcome.terminal && opts.queueOnTransientFailure !== false) {
|
|
172
|
+
runtimeInboundRoutedEmitter.enqueue(event);
|
|
173
|
+
}
|
|
174
|
+
return false;
|
|
175
|
+
};
|
|
176
|
+
const markDeliverySeqAccepted = (seq) => {
|
|
177
|
+
if (typeof seq !== "number")
|
|
178
|
+
return true;
|
|
179
|
+
const before = connector.getDeliveryCursor();
|
|
180
|
+
const prepared = connector.prepareDeliverySeqAccepted(seq);
|
|
181
|
+
if (typeof prepared === "number" && prepared !== before) {
|
|
182
|
+
writeDeliveryCursorFile(paths.deliveryCursorFile, prepared);
|
|
183
|
+
}
|
|
184
|
+
const after = connector.markDeliverySeqAccepted(seq);
|
|
185
|
+
if (after !== prepared) {
|
|
186
|
+
throw new Error("delivery cursor changed during durable commit");
|
|
187
|
+
}
|
|
188
|
+
return true;
|
|
189
|
+
};
|
|
108
190
|
const recordInboundCorrelation = (endpoint_id, metadata) => {
|
|
109
191
|
const c = metadata && typeof metadata.correlation_id === "string"
|
|
110
192
|
? metadata.correlation_id
|
|
@@ -285,6 +367,9 @@ export async function startBrokerDaemon(opts) {
|
|
|
285
367
|
content: msg.envelope.content,
|
|
286
368
|
contentType: msg.envelope.contentType,
|
|
287
369
|
metadata: msg.envelope.metadata,
|
|
370
|
+
...(msg.envelope.sourceMessageId !== undefined && {
|
|
371
|
+
sourceMessageId: msg.envelope.sourceMessageId,
|
|
372
|
+
}),
|
|
288
373
|
});
|
|
289
374
|
}
|
|
290
375
|
}
|
|
@@ -326,6 +411,9 @@ export async function startBrokerDaemon(opts) {
|
|
|
326
411
|
version: 1,
|
|
327
412
|
action: "remove",
|
|
328
413
|
undispatched_id: event.undispatched_id,
|
|
414
|
+
...(taken.source_message_id !== undefined && {
|
|
415
|
+
source_message_id: taken.source_message_id,
|
|
416
|
+
}),
|
|
329
417
|
remove_reason: "lost_at_capacity_during_redispatch_bounce",
|
|
330
418
|
});
|
|
331
419
|
}
|
|
@@ -344,6 +432,9 @@ export async function startBrokerDaemon(opts) {
|
|
|
344
432
|
dispatched_from: event.undispatched_id,
|
|
345
433
|
dispatched_by: "passport",
|
|
346
434
|
},
|
|
435
|
+
...(taken.source_message_id !== undefined && {
|
|
436
|
+
sourceMessageId: taken.source_message_id,
|
|
437
|
+
}),
|
|
347
438
|
};
|
|
348
439
|
recordInboundCorrelation(target.endpoint_id, stamped.metadata);
|
|
349
440
|
if (target.state === "active") {
|
|
@@ -359,6 +450,9 @@ export async function startBrokerDaemon(opts) {
|
|
|
359
450
|
content: taken.content,
|
|
360
451
|
contentType: taken.content_type,
|
|
361
452
|
metadata: stamped.metadata,
|
|
453
|
+
...(stamped.sourceMessageId !== undefined && {
|
|
454
|
+
sourceMessageId: stamped.sourceMessageId,
|
|
455
|
+
}),
|
|
362
456
|
},
|
|
363
457
|
});
|
|
364
458
|
}
|
|
@@ -372,6 +466,9 @@ export async function startBrokerDaemon(opts) {
|
|
|
372
466
|
version: 1,
|
|
373
467
|
action: "dispatch",
|
|
374
468
|
undispatched_id: event.undispatched_id,
|
|
469
|
+
...(taken.source_message_id !== undefined && {
|
|
470
|
+
source_message_id: taken.source_message_id,
|
|
471
|
+
}),
|
|
375
472
|
dispatched_to_endpoint_id: event.target_endpoint_id,
|
|
376
473
|
});
|
|
377
474
|
return { ok: true };
|
|
@@ -461,6 +558,13 @@ export async function startBrokerDaemon(opts) {
|
|
|
461
558
|
throw new BrokerHttpError(400, "ipc_channel_missing", `no open IPC channel for plugin_pid=${body.plugin_pid}; ` +
|
|
462
559
|
"open WS /v1/stream with x-plugin-pid header first");
|
|
463
560
|
}
|
|
561
|
+
const spawnDriver = spawnDriverRegistry?.lookup(body.kind);
|
|
562
|
+
const spawnAvailability = spawnDriver
|
|
563
|
+
? await spawnDriver.isAvailable().catch(() => ({ available: false }))
|
|
564
|
+
: null;
|
|
565
|
+
const runtimeCapabilities = spawnAvailability?.available
|
|
566
|
+
? [REMOTE_SPAWN_CAPABILITY]
|
|
567
|
+
: undefined;
|
|
464
568
|
const apiResp = await apiPort.register({
|
|
465
569
|
runtime_kind: body.kind,
|
|
466
570
|
endpoint_nonce: randomUUID(),
|
|
@@ -471,6 +575,7 @@ export async function startBrokerDaemon(opts) {
|
|
|
471
575
|
tracking_ref: body.tracking_ref,
|
|
472
576
|
session_name: body.session_name,
|
|
473
577
|
task_hint: body.task_hint,
|
|
578
|
+
runtime_capabilities: runtimeCapabilities,
|
|
474
579
|
});
|
|
475
580
|
registry.register({
|
|
476
581
|
endpoint_id: apiResp.endpoint_id,
|
|
@@ -627,6 +732,9 @@ export async function startBrokerDaemon(opts) {
|
|
|
627
732
|
content: msg.envelope.content,
|
|
628
733
|
contentType: msg.envelope.contentType,
|
|
629
734
|
metadata: msg.envelope.metadata,
|
|
735
|
+
...(msg.envelope.sourceMessageId !== undefined && {
|
|
736
|
+
sourceMessageId: msg.envelope.sourceMessageId,
|
|
737
|
+
}),
|
|
630
738
|
});
|
|
631
739
|
}
|
|
632
740
|
emitTransition(endpoint_id, "active", "reattach");
|
|
@@ -724,7 +832,10 @@ export async function startBrokerDaemon(opts) {
|
|
|
724
832
|
}
|
|
725
833
|
},
|
|
726
834
|
});
|
|
727
|
-
|
|
835
|
+
const inboundProcessing = new Set();
|
|
836
|
+
const blockedInboundSeqs = new Set();
|
|
837
|
+
let unsequencedInboundBlocked = false;
|
|
838
|
+
const handleInboundMessage = async (payload) => {
|
|
728
839
|
const meta = payload.metadata ?? {};
|
|
729
840
|
const target_endpoint_id = typeof meta.target_endpoint_id === "string"
|
|
730
841
|
? meta.target_endpoint_id
|
|
@@ -732,26 +843,48 @@ export async function startBrokerDaemon(opts) {
|
|
|
732
843
|
const correlation_id = typeof meta.correlation_id === "string" ? meta.correlation_id : undefined;
|
|
733
844
|
const decision = router.route({ target_endpoint_id, correlation_id });
|
|
734
845
|
if (decision.kind === "endpoint") {
|
|
846
|
+
if (payload.messageId !== undefined) {
|
|
847
|
+
const posted = await directPostRuntimeInboundRouted({
|
|
848
|
+
type: "runtime_inbound_routed",
|
|
849
|
+
version: 1,
|
|
850
|
+
source_message_id: payload.messageId,
|
|
851
|
+
routed_to_endpoint_id: decision.entry.endpoint_id,
|
|
852
|
+
route_kind: decision.entry.state === "active"
|
|
853
|
+
? "active_endpoint"
|
|
854
|
+
: "reconnecting_endpoint",
|
|
855
|
+
routed_at: Date.now(),
|
|
856
|
+
}, { queueOnTransientFailure: typeof payload.seq !== "number" });
|
|
857
|
+
if (!posted && typeof payload.seq === "number")
|
|
858
|
+
return false;
|
|
859
|
+
}
|
|
735
860
|
recordInboundCorrelation(decision.entry.endpoint_id, meta);
|
|
736
861
|
if (decision.entry.state === "active") {
|
|
737
|
-
pushToPlugin(decision.entry.ipc_ws, {
|
|
862
|
+
const pushed = pushToPlugin(decision.entry.ipc_ws, {
|
|
738
863
|
event: "message_received",
|
|
739
864
|
from: payload.from,
|
|
740
865
|
content: payload.content,
|
|
741
866
|
contentType: payload.contentType,
|
|
742
867
|
metadata: meta,
|
|
868
|
+
...(payload.messageId !== undefined && {
|
|
869
|
+
sourceMessageId: payload.messageId,
|
|
870
|
+
}),
|
|
743
871
|
});
|
|
872
|
+
if (!pushed)
|
|
873
|
+
return false;
|
|
744
874
|
}
|
|
745
875
|
else {
|
|
746
876
|
const buf = reconnectingBuffers.forEndpoint(decision.entry.endpoint_id);
|
|
747
877
|
buf.append({
|
|
748
|
-
id: randomUUID(),
|
|
878
|
+
id: payload.messageId ?? randomUUID(),
|
|
749
879
|
arrived_at: new Date().toISOString(),
|
|
750
880
|
envelope: {
|
|
751
881
|
from: payload.from,
|
|
752
882
|
content: payload.content,
|
|
753
883
|
contentType: payload.contentType,
|
|
754
884
|
metadata: meta,
|
|
885
|
+
...(payload.messageId !== undefined && {
|
|
886
|
+
sourceMessageId: payload.messageId,
|
|
887
|
+
}),
|
|
755
888
|
},
|
|
756
889
|
});
|
|
757
890
|
logger.info("buffered_for_reconnecting_endpoint", {
|
|
@@ -759,7 +892,7 @@ export async function startBrokerDaemon(opts) {
|
|
|
759
892
|
buffer_size: buf.size(),
|
|
760
893
|
});
|
|
761
894
|
}
|
|
762
|
-
return;
|
|
895
|
+
return markDeliverySeqAccepted(payload.seq);
|
|
763
896
|
}
|
|
764
897
|
let reason = "unaddressed";
|
|
765
898
|
let originalTarget;
|
|
@@ -779,7 +912,10 @@ export async function startBrokerDaemon(opts) {
|
|
|
779
912
|
}
|
|
780
913
|
}
|
|
781
914
|
const undispatched = {
|
|
782
|
-
id: randomUUID(),
|
|
915
|
+
id: payload.messageId ?? randomUUID(),
|
|
916
|
+
...(payload.messageId !== undefined && {
|
|
917
|
+
source_message_id: payload.messageId,
|
|
918
|
+
}),
|
|
783
919
|
arrived_at: new Date().toISOString(),
|
|
784
920
|
sender_address: payload.from,
|
|
785
921
|
content: payload.content,
|
|
@@ -796,31 +932,82 @@ export async function startBrokerDaemon(opts) {
|
|
|
796
932
|
size: undispatchedInbox.size(),
|
|
797
933
|
capacity: undispatchedInbox.capacity(),
|
|
798
934
|
});
|
|
935
|
+
return false;
|
|
799
936
|
}
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
937
|
+
logger.info("undispatched_added", { id: undispatched.id, reason });
|
|
938
|
+
const wireReason = undispatched.reason === "unaddressed"
|
|
939
|
+
? "no_target_endpoint"
|
|
940
|
+
: undispatched.reason;
|
|
941
|
+
const posted = await directPostUndispatched({
|
|
942
|
+
type: "undispatched_changed",
|
|
943
|
+
version: 1,
|
|
944
|
+
action: "add",
|
|
945
|
+
undispatched_id: undispatched.id,
|
|
946
|
+
...(undispatched.source_message_id !== undefined && {
|
|
947
|
+
source_message_id: undispatched.source_message_id,
|
|
948
|
+
}),
|
|
949
|
+
sender_address: undispatched.sender_address,
|
|
950
|
+
content_preview: truncateContentPreview(undispatched.content, CONTENT_PREVIEW_MAX_CODEPOINTS),
|
|
951
|
+
reason: wireReason,
|
|
952
|
+
...(undispatched.original_target_endpoint_id !== undefined && {
|
|
953
|
+
target_endpoint_id_hint: undispatched.original_target_endpoint_id,
|
|
954
|
+
}),
|
|
955
|
+
...(typeof correlation_id === "string" && {
|
|
956
|
+
in_reply_to: correlation_id,
|
|
957
|
+
}),
|
|
958
|
+
arrived_at: Date.parse(undispatched.arrived_at),
|
|
959
|
+
}, { queueOnTransientFailure: typeof payload.seq !== "number" });
|
|
960
|
+
if (!posted)
|
|
961
|
+
return false;
|
|
962
|
+
return markDeliverySeqAccepted(payload.seq);
|
|
963
|
+
};
|
|
964
|
+
connector.on("message_received", ({ payload }) => {
|
|
965
|
+
let task;
|
|
966
|
+
task = handleInboundMessage(payload)
|
|
967
|
+
.then((accepted) => {
|
|
968
|
+
if (typeof payload.seq === "number") {
|
|
969
|
+
if (accepted)
|
|
970
|
+
blockedInboundSeqs.delete(payload.seq);
|
|
971
|
+
else
|
|
972
|
+
blockedInboundSeqs.add(payload.seq);
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
if (accepted)
|
|
976
|
+
unsequencedInboundBlocked = false;
|
|
977
|
+
else
|
|
978
|
+
unsequencedInboundBlocked = true;
|
|
979
|
+
})
|
|
980
|
+
.catch((err) => {
|
|
981
|
+
if (typeof payload.seq === "number") {
|
|
982
|
+
blockedInboundSeqs.add(payload.seq);
|
|
983
|
+
}
|
|
984
|
+
else {
|
|
985
|
+
unsequencedInboundBlocked = true;
|
|
986
|
+
}
|
|
987
|
+
logger.error("inbound_message_handling_failed", {
|
|
988
|
+
err: err instanceof Error ? err.message : String(err),
|
|
989
|
+
messageId: payload.messageId,
|
|
990
|
+
from: payload.from,
|
|
820
991
|
});
|
|
821
|
-
}
|
|
992
|
+
})
|
|
993
|
+
.finally(() => {
|
|
994
|
+
inboundProcessing.delete(task);
|
|
995
|
+
});
|
|
996
|
+
inboundProcessing.add(task);
|
|
822
997
|
});
|
|
823
|
-
connector.on("delivery_pending", ({ payload }) => {
|
|
998
|
+
connector.on("delivery_pending", async ({ payload }) => {
|
|
999
|
+
if (inboundProcessing.size > 0) {
|
|
1000
|
+
await Promise.allSettled([...inboundProcessing]);
|
|
1001
|
+
}
|
|
1002
|
+
if (unsequencedInboundBlocked || blockedInboundSeqs.size > 0) {
|
|
1003
|
+
logger.warn("delivery_ack_deferred_until_replay", {
|
|
1004
|
+
upTo: payload.upTo,
|
|
1005
|
+
count: payload.count,
|
|
1006
|
+
blockedSeqs: [...blockedInboundSeqs].sort((a, b) => a - b),
|
|
1007
|
+
unsequencedBlocked: unsequencedInboundBlocked,
|
|
1008
|
+
});
|
|
1009
|
+
return;
|
|
1010
|
+
}
|
|
824
1011
|
connector.ackDelivery(payload.upTo);
|
|
825
1012
|
});
|
|
826
1013
|
writeDiscoveryFile(paths.discoveryFile, {
|
|
@@ -887,6 +1074,13 @@ export async function startBrokerDaemon(opts) {
|
|
|
887
1074
|
});
|
|
888
1075
|
}
|
|
889
1076
|
await networkPresenceEmitter.shutdown();
|
|
1077
|
+
if (runtimeInboundRoutedEmitter.size() > 0) {
|
|
1078
|
+
logger.warn("runtime_inbound_routed_queue_dropped_on_shutdown", {
|
|
1079
|
+
size: runtimeInboundRoutedEmitter.size(),
|
|
1080
|
+
reason,
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
1083
|
+
await runtimeInboundRoutedEmitter.shutdown();
|
|
890
1084
|
const endpoints = registry.list();
|
|
891
1085
|
await Promise.all(endpoints.map(async (entry) => {
|
|
892
1086
|
try {
|
|
@@ -923,6 +1117,7 @@ export async function startBrokerDaemon(opts) {
|
|
|
923
1117
|
retryQueueSize: () => retryQueue.size(),
|
|
924
1118
|
undispatchedChangedQueueSize: () => undispatchedEmitter.size(),
|
|
925
1119
|
networkPresenceChangedQueueSize: () => networkPresenceEmitter.size(),
|
|
1120
|
+
runtimeInboundRoutedQueueSize: () => runtimeInboundRoutedEmitter.size(),
|
|
926
1121
|
replyCorrelationCacheSize: (endpoint_id) => replyCorrelationCache.sizeForEndpoint(endpoint_id),
|
|
927
1122
|
};
|
|
928
1123
|
}
|
|
@@ -38,6 +38,10 @@ export declare class ConnectorWS {
|
|
|
38
38
|
disconnect(): void;
|
|
39
39
|
send(to: string, content: string, contentType?: string, metadata?: Record<string, unknown>): Promise<SendAckEvent>;
|
|
40
40
|
ackDelivery(upTo: string): boolean;
|
|
41
|
+
setDeliveryCursor(seq: number): void;
|
|
42
|
+
getDeliveryCursor(): number | undefined;
|
|
43
|
+
prepareDeliverySeqAccepted(seq: number): number | undefined;
|
|
44
|
+
markDeliverySeqAccepted(seq: number): number | undefined;
|
|
41
45
|
on<E extends ConnectorWSEvent["event"]>(event: E, listener: ListenerFor<E>): this;
|
|
42
46
|
off<E extends ConnectorWSEvent["event"]>(event: E, listener: ListenerFor<E>): this;
|
|
43
47
|
_emitForTesting(e: ConnectorWSEvent): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connector-ws.d.ts","sourceRoot":"","sources":["../../src/broker/connector-ws.ts"],"names":[],"mappings":"AAaA,OAAO,EAAmB,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,EACZ,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,gBAAgB,GACxB;IAAE,KAAK,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,qBAAqB,CAAA;CAAE,GAC7D;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GAC5C;IAAE,KAAK,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,oBAAoB,CAAA;CAAE,GAC5D;IAAE,KAAK,EAAE,iBAAiB,CAAC;IAAC,OAAO,EAAE,mBAAmB,CAAA;CAAE,GAC1D;IAAE,KAAK,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,oBAAoB,CAAA;CAAE,GAC5D;IAAE,KAAK,EAAE,WAAW,CAAA;CAAE,GACtB;IAAE,KAAK,EAAE,cAAc,CAAA;CAAE,GACzB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC;AAEvC,KAAK,WAAW,CAAC,CAAC,SAAS,gBAAgB,CAAC,OAAO,CAAC,IAAI,CACtD,CAAC,EAAE,OAAO,CAAC,gBAAgB,EAAE;IAAE,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC,KACvC,IAAI,CAAC;AAEV,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAsB;gBAE9B,IAAI,EAAE,kBAAkB;IAMpC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAKxB,UAAU,IAAI,IAAI;IASlB,IAAI,CACF,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EACf,WAAW,SAAS,EACpB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,OAAO,CAAC,YAAY,CAAC;IAKxB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;
|
|
1
|
+
{"version":3,"file":"connector-ws.d.ts","sourceRoot":"","sources":["../../src/broker/connector-ws.ts"],"names":[],"mappings":"AAaA,OAAO,EAAmB,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,EACZ,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,gBAAgB,GACxB;IAAE,KAAK,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,qBAAqB,CAAA;CAAE,GAC7D;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GAC5C;IAAE,KAAK,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,oBAAoB,CAAA;CAAE,GAC5D;IAAE,KAAK,EAAE,iBAAiB,CAAC;IAAC,OAAO,EAAE,mBAAmB,CAAA;CAAE,GAC1D;IAAE,KAAK,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,oBAAoB,CAAA;CAAE,GAC5D;IAAE,KAAK,EAAE,WAAW,CAAA;CAAE,GACtB;IAAE,KAAK,EAAE,cAAc,CAAA;CAAE,GACzB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC;AAEvC,KAAK,WAAW,CAAC,CAAC,SAAS,gBAAgB,CAAC,OAAO,CAAC,IAAI,CACtD,CAAC,EAAE,OAAO,CAAC,gBAAgB,EAAE;IAAE,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC,KACvC,IAAI,CAAC;AAEV,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAsB;gBAE9B,IAAI,EAAE,kBAAkB;IAMpC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAKxB,UAAU,IAAI,IAAI;IASlB,IAAI,CACF,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EACf,WAAW,SAAS,EACpB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,OAAO,CAAC,YAAY,CAAC;IAKxB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAKlC,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAKpC,iBAAiB,IAAI,MAAM,GAAG,SAAS;IAKvC,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAK3D,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIxD,EAAE,CAAC,CAAC,SAAS,gBAAgB,CAAC,OAAO,CAAC,EACpC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,GACvB,IAAI;IAKP,GAAG,CAAC,CAAC,SAAS,gBAAgB,CAAC,OAAO,CAAC,EACrC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,GACvB,IAAI;IAMS,eAAe,CAAC,CAAC,EAAE,gBAAgB,GAAG,IAAI;IAI1D,OAAO,CAAC,cAAc;CA0BvB;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -19,6 +19,18 @@ export class ConnectorWS {
|
|
|
19
19
|
ackDelivery(upTo) {
|
|
20
20
|
return this.client.ackDelivery(upTo);
|
|
21
21
|
}
|
|
22
|
+
setDeliveryCursor(seq) {
|
|
23
|
+
this.client.setDeliveryCursor(seq);
|
|
24
|
+
}
|
|
25
|
+
getDeliveryCursor() {
|
|
26
|
+
return this.client.getDeliveryCursor();
|
|
27
|
+
}
|
|
28
|
+
prepareDeliverySeqAccepted(seq) {
|
|
29
|
+
return this.client.prepareDeliverySeqAccepted(seq);
|
|
30
|
+
}
|
|
31
|
+
markDeliverySeqAccepted(seq) {
|
|
32
|
+
return this.client.markDeliverySeqAccepted(seq);
|
|
33
|
+
}
|
|
22
34
|
on(event, listener) {
|
|
23
35
|
this.bus.on(event, listener);
|
|
24
36
|
return this;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface DeliveryCursorRecord {
|
|
2
|
+
version: 1;
|
|
3
|
+
lastKnownSeq: number;
|
|
4
|
+
updatedAt: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function readDeliveryCursorFile(path: string): number | null;
|
|
7
|
+
export declare function writeDeliveryCursorFile(path: string, seq: number): void;
|
|
8
|
+
//# sourceMappingURL=delivery-cursor-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delivery-cursor-file.d.ts","sourceRoot":"","sources":["../../src/broker/delivery-cursor-file.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,CAAC,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgBlE;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAiCvE"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { chmodSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
|
+
export function readDeliveryCursorFile(path) {
|
|
5
|
+
let raw;
|
|
6
|
+
try {
|
|
7
|
+
raw = readFileSync(path, "utf8");
|
|
8
|
+
}
|
|
9
|
+
catch (err) {
|
|
10
|
+
if (isNodeErr(err, "ENOENT"))
|
|
11
|
+
return null;
|
|
12
|
+
throw err;
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
const parsed = JSON.parse(raw);
|
|
16
|
+
if (!isDeliveryCursorRecord(parsed))
|
|
17
|
+
return null;
|
|
18
|
+
return parsed.lastKnownSeq;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function writeDeliveryCursorFile(path, seq) {
|
|
25
|
+
if (!Number.isInteger(seq) || seq < 0) {
|
|
26
|
+
throw new Error(`delivery cursor must be a non-negative integer: ${seq}`);
|
|
27
|
+
}
|
|
28
|
+
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
29
|
+
const tmp = `${path}.tmp.${process.pid}.${randomBytes(4).toString("hex")}`;
|
|
30
|
+
const record = {
|
|
31
|
+
version: 1,
|
|
32
|
+
lastKnownSeq: seq,
|
|
33
|
+
updatedAt: new Date().toISOString(),
|
|
34
|
+
};
|
|
35
|
+
writeFileSync(tmp, JSON.stringify(record, null, 2), {
|
|
36
|
+
mode: 0o600,
|
|
37
|
+
encoding: "utf8",
|
|
38
|
+
});
|
|
39
|
+
try {
|
|
40
|
+
chmodSync(tmp, 0o600);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
renameSync(tmp, path);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
try {
|
|
49
|
+
unlinkSync(tmp);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
}
|
|
53
|
+
throw err;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function isDeliveryCursorRecord(value) {
|
|
57
|
+
if (typeof value !== "object" || value === null)
|
|
58
|
+
return false;
|
|
59
|
+
const v = value;
|
|
60
|
+
return (v.version === 1 &&
|
|
61
|
+
typeof v.lastKnownSeq === "number" &&
|
|
62
|
+
Number.isInteger(v.lastKnownSeq) &&
|
|
63
|
+
v.lastKnownSeq >= 0 &&
|
|
64
|
+
typeof v.updatedAt === "string");
|
|
65
|
+
}
|
|
66
|
+
function isNodeErr(err, code) {
|
|
67
|
+
return (typeof err === "object" &&
|
|
68
|
+
err !== null &&
|
|
69
|
+
"code" in err &&
|
|
70
|
+
err.code === code);
|
|
71
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../../src/broker/entry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../../src/broker/entry.ts"],"names":[],"mappings":"AAiFA,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,aAAa,CAAC;AAEpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAMtE,UAAU,mBAAmB;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,gBAAgB;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAUD,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,OAAO,CAAC,mBAAmB,CAAC,CA8F9B;AA2DD,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,GAAE,OAAO,UAAU,CAAC,KAAwB,GACpD,OAAO,CAAC,gBAAgB,CAAC,CA4B3B;AAaD,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,YAAY,GACnB,mBAAmB,CAuHrB;AAYD,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAgG1C"}
|
package/dist/broker/entry.js
CHANGED
|
@@ -2,7 +2,7 @@ import { readFile } from "node:fs/promises";
|
|
|
2
2
|
import { pathToFileURL } from "node:url";
|
|
3
3
|
import { readConfig } from "../config-fs.js";
|
|
4
4
|
import { DEFAULT_API_HOST } from "../platform-client.js";
|
|
5
|
-
import { emitRuntimeNetworkPresenceChanged, emitRuntimeUndispatchedChanged, heartbeatRuntimeEndpoint, registerRuntimeEndpoint, transitionRuntimeEndpointState, unregisterRuntimeEndpoint, updateRuntimeEndpointDisplayMetadata, } from "../runtime-endpoint-client.js";
|
|
5
|
+
import { emitRuntimeNetworkPresenceChanged, emitRuntimeInboundRouted, emitRuntimeUndispatchedChanged, heartbeatRuntimeEndpoint, registerRuntimeEndpoint, transitionRuntimeEndpointState, unregisterRuntimeEndpoint, updateRuntimeEndpointDisplayMetadata, } from "../runtime-endpoint-client.js";
|
|
6
6
|
import { startBrokerDaemon } from "./broker-daemon.js";
|
|
7
7
|
import { ClaudeCodeSpawnDriver } from "./claude-code-spawn-driver.js";
|
|
8
8
|
import { CodexSpawnDriverStub } from "./codex-spawn-driver-stub.js";
|
|
@@ -171,6 +171,9 @@ export function buildApiPort(apiHost, runtimeKey, logger) {
|
|
|
171
171
|
async emitNetworkPresenceChanged(event) {
|
|
172
172
|
return emitRuntimeNetworkPresenceChanged({ apiHost }, runtimeKey, event);
|
|
173
173
|
},
|
|
174
|
+
async emitRuntimeInboundRouted(event) {
|
|
175
|
+
return emitRuntimeInboundRouted({ apiHost }, runtimeKey, event);
|
|
176
|
+
},
|
|
174
177
|
};
|
|
175
178
|
}
|
|
176
179
|
function errorStatus(err) {
|
|
@@ -68,13 +68,14 @@ export interface RunningIPCServer {
|
|
|
68
68
|
close(): Promise<void>;
|
|
69
69
|
}
|
|
70
70
|
export declare function startIPCServer(opts: IPCServerOptions): Promise<RunningIPCServer>;
|
|
71
|
-
export declare function pushToPlugin(ws: WebSocket, event: PushEvent):
|
|
71
|
+
export declare function pushToPlugin(ws: WebSocket, event: PushEvent): boolean;
|
|
72
72
|
export type PushEvent = {
|
|
73
73
|
event: "message_received";
|
|
74
74
|
from: string;
|
|
75
75
|
content: string;
|
|
76
76
|
contentType: string;
|
|
77
77
|
metadata?: Record<string, unknown>;
|
|
78
|
+
sourceMessageId?: string;
|
|
78
79
|
} | {
|
|
79
80
|
event: "ping";
|
|
80
81
|
ts: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ipc-server.d.ts","sourceRoot":"","sources":["../../src/broker/ipc-server.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ipc-server.d.ts","sourceRoot":"","sources":["../../src/broker/ipc-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -274,8 +274,9 @@ async function closeServer(http, wss) {
|
|
|
274
274
|
}
|
|
275
275
|
export function pushToPlugin(ws, event) {
|
|
276
276
|
if (ws.readyState !== WebSocket.OPEN)
|
|
277
|
-
return;
|
|
277
|
+
return false;
|
|
278
278
|
ws.send(JSON.stringify(event));
|
|
279
|
+
return true;
|
|
279
280
|
}
|
|
280
281
|
export function parsePluginFrame(data) {
|
|
281
282
|
try {
|