@masons/runtime-broker 0.2.8 → 0.2.10
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 +1 -0
- package/dist/broker/broker-daemon.d.ts.map +1 -1
- package/dist/broker/broker-daemon.js +441 -15
- package/dist/broker/endpoint-registry.d.ts +4 -0
- package/dist/broker/endpoint-registry.d.ts.map +1 -1
- package/dist/broker/endpoint-registry.js +2 -0
- package/dist/broker/entry.d.ts +1 -0
- package/dist/broker/entry.d.ts.map +1 -1
- package/dist/broker/entry.js +49 -2
- package/dist/broker/ipc-server.d.ts +27 -1
- package/dist/broker/ipc-server.d.ts.map +1 -1
- package/dist/broker/ipc-server.js +39 -2
- package/dist/broker/runtime-endpoint-port.d.ts +3 -1
- package/dist/broker/runtime-endpoint-port.d.ts.map +1 -1
- package/dist/broker/version-handshake.d.ts +3 -1
- package/dist/broker/version-handshake.d.ts.map +1 -1
- package/dist/broker/version-handshake.js +3 -1
- package/dist/broker-client/broker-client.d.ts +32 -0
- package/dist/broker-client/broker-client.d.ts.map +1 -1
- package/dist/broker-client/broker-client.js +122 -2
- package/dist/runtime-endpoint-client.d.ts +45 -0
- package/dist/runtime-endpoint-client.d.ts.map +1 -1
- package/dist/runtime-endpoint-client.js +170 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -58,6 +58,7 @@ export interface BrokerDaemonOptions {
|
|
|
58
58
|
runtimeInboundRoutedBackoffMaxMs?: number;
|
|
59
59
|
runtimeInboundRoutedMaxRetries?: number;
|
|
60
60
|
runtimeAssignmentAcceptanceTimeoutMs?: number;
|
|
61
|
+
pushReceiptAckTimeoutMs?: number;
|
|
61
62
|
}
|
|
62
63
|
export interface RunningBroker {
|
|
63
64
|
bearerToken: string;
|
|
@@ -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;AAQjD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EACL,KAAK,sBAAsB,EAE5B,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EACV,UAAU,EAIX,MAAM,0BAA0B,CAAC;AAKlC,OAAO,EACL,KAAK,eAAe,EAKrB,MAAM,qBAAqB,CAAC;AAK7B,OAAO,EAEL,KAAK,aAAa,EAEnB,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"broker-daemon.d.ts","sourceRoot":"","sources":["../../src/broker/broker-daemon.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,6 +24,7 @@ import { createUndispatchedChangedEmitter, postUndispatchedChangedViaPort, } fro
|
|
|
24
24
|
import { createUndispatchedInbox, } from "./undispatched-inbox.js";
|
|
25
25
|
const REMOTE_SPAWN_CAPABILITY = "remote_spawn_v1";
|
|
26
26
|
const DEFAULT_RUNTIME_ASSIGNMENT_ACCEPTANCE_TIMEOUT_MS = 30_000;
|
|
27
|
+
const DEFAULT_PUSH_RECEIPT_ACK_TIMEOUT_MS = 2_000;
|
|
27
28
|
const RUNTIME_ASSIGNMENT_REPLY_RECORD_TTL_MS = 24 * 60 * 60 * 1000;
|
|
28
29
|
const RUNTIME_PROCESSING_RETRY_INITIAL_MS = 1_000;
|
|
29
30
|
const RUNTIME_PROCESSING_RETRY_MAX_MS = 30_000;
|
|
@@ -46,6 +47,52 @@ function buildLocalDispatchTargetRef(targetEndpointId, target) {
|
|
|
46
47
|
background_exchange_mode: "resident_endpoint",
|
|
47
48
|
};
|
|
48
49
|
}
|
|
50
|
+
function buildRuntimeAssignmentTargetRef(entry) {
|
|
51
|
+
if (!entry.runtime_capabilities?.includes("background_exchange_v1")) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
if (entry.background_exchange_mode === "resident_endpoint") {
|
|
55
|
+
return {
|
|
56
|
+
kind: "projection_endpoint",
|
|
57
|
+
projection_endpoint_id: entry.endpoint_id,
|
|
58
|
+
background_exchange_mode: "resident_endpoint",
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
if (entry.background_exchange_mode === "adapter_managed_turn" &&
|
|
62
|
+
typeof entry.runtime_session_id === "string" &&
|
|
63
|
+
entry.runtime_session_id.trim().length > 0) {
|
|
64
|
+
return {
|
|
65
|
+
kind: "projection_endpoint",
|
|
66
|
+
projection_endpoint_id: entry.endpoint_id,
|
|
67
|
+
runtime_session_id: entry.runtime_session_id,
|
|
68
|
+
background_exchange_mode: "adapter_managed_turn",
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
function sameRuntimeWorkTargetRef(left, right) {
|
|
74
|
+
return (left.kind === right.kind &&
|
|
75
|
+
left.projection_endpoint_id === right.projection_endpoint_id &&
|
|
76
|
+
left.background_exchange_mode === right.background_exchange_mode &&
|
|
77
|
+
(left.background_exchange_mode !== "adapter_managed_turn" ||
|
|
78
|
+
right.background_exchange_mode !== "adapter_managed_turn" ||
|
|
79
|
+
left.runtime_session_id === right.runtime_session_id));
|
|
80
|
+
}
|
|
81
|
+
function tokenMatches(left, right) {
|
|
82
|
+
if (left.length !== right.length)
|
|
83
|
+
return false;
|
|
84
|
+
let mismatch = 0;
|
|
85
|
+
for (let i = 0; i < left.length; i++) {
|
|
86
|
+
mismatch |= left.charCodeAt(i) ^ right.charCodeAt(i);
|
|
87
|
+
}
|
|
88
|
+
return mismatch === 0;
|
|
89
|
+
}
|
|
90
|
+
function assertEndpointOwnerToken(entry, candidate) {
|
|
91
|
+
if (typeof candidate !== "string" ||
|
|
92
|
+
!tokenMatches(candidate, entry.endpoint_owner_token)) {
|
|
93
|
+
throw new BrokerHttpError(403, "endpoint_owner_token_mismatch", "endpoint_owner_token does not own endpoint_id");
|
|
94
|
+
}
|
|
95
|
+
}
|
|
49
96
|
function derivePublicDisplayLabel(body) {
|
|
50
97
|
const parts = [
|
|
51
98
|
body.kind,
|
|
@@ -100,6 +147,7 @@ export async function startBrokerDaemon(opts) {
|
|
|
100
147
|
const presenceGraceMs = opts.presenceGraceMs;
|
|
101
148
|
const runtimeAssignmentAcceptanceTimeoutMs = opts.runtimeAssignmentAcceptanceTimeoutMs ??
|
|
102
149
|
DEFAULT_RUNTIME_ASSIGNMENT_ACCEPTANCE_TIMEOUT_MS;
|
|
150
|
+
const pushReceiptAckTimeoutMs = opts.pushReceiptAckTimeoutMs ?? DEFAULT_PUSH_RECEIPT_ACK_TIMEOUT_MS;
|
|
103
151
|
const postControlAck = opts.postControlAck ??
|
|
104
152
|
(async () => {
|
|
105
153
|
});
|
|
@@ -539,6 +587,65 @@ export async function startBrokerDaemon(opts) {
|
|
|
539
587
|
}
|
|
540
588
|
};
|
|
541
589
|
const channels = new Map();
|
|
590
|
+
const channelCapabilities = new WeakMap();
|
|
591
|
+
const pendingPushAcks = new Map();
|
|
592
|
+
const settlePushAck = (pushId, ok) => {
|
|
593
|
+
const pending = pendingPushAcks.get(pushId);
|
|
594
|
+
if (!pending)
|
|
595
|
+
return;
|
|
596
|
+
pendingPushAcks.delete(pushId);
|
|
597
|
+
clearTimeout(pending.timer);
|
|
598
|
+
pending.resolve(ok);
|
|
599
|
+
};
|
|
600
|
+
const waitForPushAck = (plugin_pid, ipc_ws, pushId, event, endpoint_id) => new Promise((resolve) => {
|
|
601
|
+
const timer = setTimeout(() => {
|
|
602
|
+
logger.warn("ipc_push_ack_timeout", {
|
|
603
|
+
push_id: pushId,
|
|
604
|
+
plugin_pid,
|
|
605
|
+
event,
|
|
606
|
+
endpoint_id,
|
|
607
|
+
});
|
|
608
|
+
settlePushAck(pushId, false);
|
|
609
|
+
}, pushReceiptAckTimeoutMs);
|
|
610
|
+
timer.unref?.();
|
|
611
|
+
pendingPushAcks.set(pushId, {
|
|
612
|
+
plugin_pid,
|
|
613
|
+
ipc_ws,
|
|
614
|
+
endpoint_id,
|
|
615
|
+
event,
|
|
616
|
+
timer,
|
|
617
|
+
resolve,
|
|
618
|
+
});
|
|
619
|
+
});
|
|
620
|
+
const pushToPluginWithReceipt = async (entry, event) => {
|
|
621
|
+
const capabilities = channelCapabilities.get(entry.ipc_ws);
|
|
622
|
+
if (capabilities?.push_receipt_ack_v1 !== true) {
|
|
623
|
+
return pushToPlugin(entry.ipc_ws, event);
|
|
624
|
+
}
|
|
625
|
+
const pushId = `push_${randomUUID()}`;
|
|
626
|
+
const ack = waitForPushAck(entry.plugin_pid, entry.ipc_ws, pushId, event.event, entry.endpoint_id);
|
|
627
|
+
let pushed = false;
|
|
628
|
+
try {
|
|
629
|
+
pushed = pushToPlugin(entry.ipc_ws, {
|
|
630
|
+
...event,
|
|
631
|
+
push_id: pushId,
|
|
632
|
+
});
|
|
633
|
+
}
|
|
634
|
+
catch (err) {
|
|
635
|
+
logger.warn("ipc_push_send_failed", {
|
|
636
|
+
push_id: pushId,
|
|
637
|
+
endpoint_id: entry.endpoint_id,
|
|
638
|
+
plugin_pid: entry.plugin_pid,
|
|
639
|
+
event: event.event,
|
|
640
|
+
err: err instanceof Error ? err.message : String(err),
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
if (!pushed) {
|
|
644
|
+
settlePushAck(pushId, false);
|
|
645
|
+
return false;
|
|
646
|
+
}
|
|
647
|
+
return ack;
|
|
648
|
+
};
|
|
542
649
|
let networkPresence = "offline";
|
|
543
650
|
let presenceGraceTimer;
|
|
544
651
|
const applyPresenceTransition = (event) => {
|
|
@@ -918,7 +1025,6 @@ export async function startBrokerDaemon(opts) {
|
|
|
918
1025
|
storedAssignment.lastStateSequence = Math.max(storedAssignment.lastStateSequence, processingEvent.state_sequence);
|
|
919
1026
|
runtimeAssignments.set(assignmentKey, storedAssignment);
|
|
920
1027
|
scheduleAcceptanceTimeout(assignmentKey);
|
|
921
|
-
rememberRuntimeAssignmentCorrelation(target.endpoint_id, taken.metadata.correlation_id, assignmentKey);
|
|
922
1028
|
const stamped = {
|
|
923
1029
|
event: "message_received",
|
|
924
1030
|
from: taken.sender_address,
|
|
@@ -932,15 +1038,26 @@ export async function startBrokerDaemon(opts) {
|
|
|
932
1038
|
sourceMessageId: taken.source_message_id,
|
|
933
1039
|
runtimeAssignment,
|
|
934
1040
|
};
|
|
935
|
-
recordInboundCorrelation(target.endpoint_id, stamped.metadata);
|
|
936
1041
|
if (target.state === "active") {
|
|
937
|
-
if (!
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
1042
|
+
if (!(await pushToPluginWithReceipt(target, stamped))) {
|
|
1043
|
+
const current = runtimeAssignments.get(assignmentKey);
|
|
1044
|
+
if (current?.accepted) {
|
|
1045
|
+
logger.info("ipc_push_ack_missing_after_adapter_accept", {
|
|
1046
|
+
assignment_id: runtimeAssignment.assignmentId,
|
|
1047
|
+
source_message_id: runtimeAssignment.sourceMessageId,
|
|
1048
|
+
target_endpoint_id: target.endpoint_id,
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1051
|
+
else {
|
|
1052
|
+
await restorePendingAssignmentsForEndpoint(target.endpoint_id, "ipc_push_not_received");
|
|
1053
|
+
return {
|
|
1054
|
+
ok: false,
|
|
1055
|
+
detail: `target endpoint did not acknowledge push receipt: ${targetEndpointId}`,
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
943
1058
|
}
|
|
1059
|
+
rememberRuntimeAssignmentCorrelation(target.endpoint_id, taken.metadata.correlation_id, assignmentKey);
|
|
1060
|
+
recordInboundCorrelation(target.endpoint_id, stamped.metadata);
|
|
944
1061
|
}
|
|
945
1062
|
else {
|
|
946
1063
|
try {
|
|
@@ -1070,9 +1187,11 @@ export async function startBrokerDaemon(opts) {
|
|
|
1070
1187
|
? Array.from(runtimeCapabilitiesSet)
|
|
1071
1188
|
: undefined;
|
|
1072
1189
|
const runtimeSessionId = body.runtime_session_id?.trim() || undefined;
|
|
1190
|
+
const endpointNonce = randomUUID();
|
|
1191
|
+
const endpointOwnerToken = randomUUID();
|
|
1073
1192
|
const apiResp = await apiPort.register({
|
|
1074
1193
|
runtime_kind: body.kind,
|
|
1075
|
-
endpoint_nonce:
|
|
1194
|
+
endpoint_nonce: endpointNonce,
|
|
1076
1195
|
display_label: derivePublicDisplayLabel(body),
|
|
1077
1196
|
workspace: body.workspace
|
|
1078
1197
|
? { root: body.workspace, cwd: body.workspace }
|
|
@@ -1087,6 +1206,8 @@ export async function startBrokerDaemon(opts) {
|
|
|
1087
1206
|
});
|
|
1088
1207
|
registry.register({
|
|
1089
1208
|
endpoint_id: apiResp.endpoint_id,
|
|
1209
|
+
endpoint_nonce: endpointNonce,
|
|
1210
|
+
endpoint_owner_token: endpointOwnerToken,
|
|
1090
1211
|
agent_id: body.agent_id,
|
|
1091
1212
|
plugin_pid: body.plugin_pid,
|
|
1092
1213
|
ipc_ws: boundWs,
|
|
@@ -1135,7 +1256,10 @@ export async function startBrokerDaemon(opts) {
|
|
|
1135
1256
|
plugin_pid: body.plugin_pid,
|
|
1136
1257
|
kind: body.kind,
|
|
1137
1258
|
});
|
|
1138
|
-
return {
|
|
1259
|
+
return {
|
|
1260
|
+
endpoint_id: apiResp.endpoint_id,
|
|
1261
|
+
endpoint_owner_token: endpointOwnerToken,
|
|
1262
|
+
};
|
|
1139
1263
|
},
|
|
1140
1264
|
async heartbeatEndpoint(endpoint_id) {
|
|
1141
1265
|
const entry = registry.get(endpoint_id);
|
|
@@ -1215,6 +1339,266 @@ export async function startBrokerDaemon(opts) {
|
|
|
1215
1339
|
}
|
|
1216
1340
|
return { messageId: ack.messageId, status: ack.status };
|
|
1217
1341
|
},
|
|
1342
|
+
async claimRuntimeAssignment(body) {
|
|
1343
|
+
const entry = registry.get(body.endpoint_id);
|
|
1344
|
+
if (!entry) {
|
|
1345
|
+
throw new BrokerHttpError(404, "unknown_endpoint", `unknown endpoint_id: ${body.endpoint_id}`);
|
|
1346
|
+
}
|
|
1347
|
+
if (entry.plugin_pid !== body.plugin_pid) {
|
|
1348
|
+
throw new BrokerHttpError(403, "endpoint_pid_mismatch", "plugin_pid does not own endpoint_id");
|
|
1349
|
+
}
|
|
1350
|
+
assertEndpointOwnerToken(entry, body.endpoint_owner_token);
|
|
1351
|
+
if (entry.state !== "active") {
|
|
1352
|
+
throw new BrokerHttpError(409, "endpoint_not_active", `endpoint ${body.endpoint_id} is ${entry.state}; assignment claim is only allowed from Active`);
|
|
1353
|
+
}
|
|
1354
|
+
const expectedTargetRef = buildRuntimeAssignmentTargetRef(entry);
|
|
1355
|
+
if (!expectedTargetRef) {
|
|
1356
|
+
throw new BrokerHttpError(409, "missing_background_exchange_v1", "endpoint does not expose an assignment-capable runtime work target");
|
|
1357
|
+
}
|
|
1358
|
+
if (typeof body.undispatched_id !== "string" ||
|
|
1359
|
+
body.undispatched_id.length === 0) {
|
|
1360
|
+
throw new BrokerHttpError(400, "undispatched_id_invalid", "undispatched_id is required");
|
|
1361
|
+
}
|
|
1362
|
+
const existingAssignment = Array.from(runtimeAssignments.values()).find((assignment) => assignment.context.undispatchedId === body.undispatched_id &&
|
|
1363
|
+
assignment.context.targetRef.projection_endpoint_id ===
|
|
1364
|
+
body.endpoint_id);
|
|
1365
|
+
if (existingAssignment) {
|
|
1366
|
+
if (body.recover_existing !== true || existingAssignment.accepted) {
|
|
1367
|
+
throw new BrokerHttpError(409, "runtime_assignment_in_progress", "runtime assignment already exists for this undispatched message and endpoint");
|
|
1368
|
+
}
|
|
1369
|
+
return {
|
|
1370
|
+
assignment: existingAssignment.context,
|
|
1371
|
+
message: {
|
|
1372
|
+
from: existingAssignment.message.sender_address,
|
|
1373
|
+
content: existingAssignment.message.content,
|
|
1374
|
+
contentType: existingAssignment.message.content_type,
|
|
1375
|
+
metadata: existingAssignment.message.metadata,
|
|
1376
|
+
...(existingAssignment.message.source_message_id !== undefined && {
|
|
1377
|
+
sourceMessageId: existingAssignment.message.source_message_id,
|
|
1378
|
+
}),
|
|
1379
|
+
},
|
|
1380
|
+
};
|
|
1381
|
+
}
|
|
1382
|
+
if (!apiPort.claimRuntimeSelfAssignment) {
|
|
1383
|
+
throw new BrokerHttpError(503, "runtime_self_claim_unsupported", "apps/api self-claim route is not available", { retryable: true });
|
|
1384
|
+
}
|
|
1385
|
+
const claimOutcome = await apiPort.claimRuntimeSelfAssignment({
|
|
1386
|
+
undispatched_id: body.undispatched_id,
|
|
1387
|
+
target_endpoint_id: body.endpoint_id,
|
|
1388
|
+
endpoint_nonce: entry.endpoint_nonce,
|
|
1389
|
+
...(body.recover_existing === true && { recover_existing: true }),
|
|
1390
|
+
});
|
|
1391
|
+
if (!claimOutcome.ok && claimOutcome.postCasInvalidClaim !== undefined) {
|
|
1392
|
+
const invalidClaim = claimOutcome.postCasInvalidClaim;
|
|
1393
|
+
if (typeof invalidClaim.undispatched_id === "string" &&
|
|
1394
|
+
typeof invalidClaim.source_message_id === "string" &&
|
|
1395
|
+
typeof invalidClaim.assignment_id === "string" &&
|
|
1396
|
+
typeof invalidClaim.broker_projection_token === "string" &&
|
|
1397
|
+
invalidClaim.target_ref !== undefined) {
|
|
1398
|
+
const released = apiPort.releaseRuntimeSelfAssignment
|
|
1399
|
+
? await apiPort
|
|
1400
|
+
.releaseRuntimeSelfAssignment({
|
|
1401
|
+
undispatched_id: invalidClaim.undispatched_id,
|
|
1402
|
+
source_message_id: invalidClaim.source_message_id,
|
|
1403
|
+
assignment_id: invalidClaim.assignment_id,
|
|
1404
|
+
target_ref: invalidClaim.target_ref,
|
|
1405
|
+
endpoint_nonce: entry.endpoint_nonce,
|
|
1406
|
+
broker_projection_token: invalidClaim.broker_projection_token,
|
|
1407
|
+
})
|
|
1408
|
+
.catch((err) => ({
|
|
1409
|
+
ok: false,
|
|
1410
|
+
terminal: false,
|
|
1411
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
1412
|
+
}))
|
|
1413
|
+
: { ok: false, terminal: false };
|
|
1414
|
+
if (!released.ok) {
|
|
1415
|
+
logger.error("runtime_self_claim_compensation_failed", {
|
|
1416
|
+
reason_code: "invalid_2xx_claim_response",
|
|
1417
|
+
release_detail: released.detail,
|
|
1418
|
+
undispatched_id: invalidClaim.undispatched_id,
|
|
1419
|
+
source_message_id: invalidClaim.source_message_id,
|
|
1420
|
+
assignment_id: invalidClaim.assignment_id,
|
|
1421
|
+
target_endpoint_id: body.endpoint_id,
|
|
1422
|
+
});
|
|
1423
|
+
throw new BrokerHttpError(503, "runtime_self_claim_outcome_unknown", "runtime self-claim returned an invalid post-CAS response and the broker could not release it; retry the claim", {
|
|
1424
|
+
retryable: true,
|
|
1425
|
+
outcome_unknown: true,
|
|
1426
|
+
reason_code: "invalid_2xx_claim_response",
|
|
1427
|
+
});
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
else {
|
|
1431
|
+
logger.error("runtime_self_claim_invalid_response_unreleasable", {
|
|
1432
|
+
target_endpoint_id: body.endpoint_id,
|
|
1433
|
+
detail: claimOutcome.detail,
|
|
1434
|
+
});
|
|
1435
|
+
throw new BrokerHttpError(503, "runtime_self_claim_outcome_unknown", "runtime self-claim returned an invalid post-CAS response without enough release data; retry the claim", {
|
|
1436
|
+
retryable: true,
|
|
1437
|
+
outcome_unknown: true,
|
|
1438
|
+
reason_code: "invalid_2xx_claim_response_unreleasable",
|
|
1439
|
+
});
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
if (!claimOutcome.ok) {
|
|
1443
|
+
const rejectedStatus = claimOutcome.status !== undefined && claimOutcome.status >= 400
|
|
1444
|
+
? claimOutcome.status
|
|
1445
|
+
: 502;
|
|
1446
|
+
throw new BrokerHttpError(claimOutcome.terminal ? rejectedStatus : 503, "runtime_self_claim_rejected", claimOutcome.detail ?? "runtime self-claim was rejected", { retryable: !claimOutcome.terminal });
|
|
1447
|
+
}
|
|
1448
|
+
const claim = claimOutcome.claim;
|
|
1449
|
+
const releaseClaimAfterFailure = async (reasonCode, detail) => {
|
|
1450
|
+
if (!apiPort.releaseRuntimeSelfAssignment) {
|
|
1451
|
+
logger.error("runtime_self_claim_compensation_unavailable", {
|
|
1452
|
+
reason_code: reasonCode,
|
|
1453
|
+
detail,
|
|
1454
|
+
undispatched_id: claim.undispatched_id,
|
|
1455
|
+
source_message_id: claim.source_message_id,
|
|
1456
|
+
assignment_id: claim.assignment_id,
|
|
1457
|
+
target_endpoint_id: body.endpoint_id,
|
|
1458
|
+
});
|
|
1459
|
+
return false;
|
|
1460
|
+
}
|
|
1461
|
+
try {
|
|
1462
|
+
const released = await apiPort.releaseRuntimeSelfAssignment({
|
|
1463
|
+
undispatched_id: claim.undispatched_id,
|
|
1464
|
+
source_message_id: claim.source_message_id,
|
|
1465
|
+
assignment_id: claim.assignment_id,
|
|
1466
|
+
target_ref: claim.target_ref,
|
|
1467
|
+
endpoint_nonce: entry.endpoint_nonce,
|
|
1468
|
+
broker_projection_token: claim.broker_projection_token,
|
|
1469
|
+
});
|
|
1470
|
+
if (!released.ok) {
|
|
1471
|
+
logger.error("runtime_self_claim_compensation_failed", {
|
|
1472
|
+
reason_code: reasonCode,
|
|
1473
|
+
detail,
|
|
1474
|
+
terminal: released.terminal,
|
|
1475
|
+
release_detail: released.detail,
|
|
1476
|
+
undispatched_id: claim.undispatched_id,
|
|
1477
|
+
source_message_id: claim.source_message_id,
|
|
1478
|
+
assignment_id: claim.assignment_id,
|
|
1479
|
+
target_endpoint_id: body.endpoint_id,
|
|
1480
|
+
});
|
|
1481
|
+
return false;
|
|
1482
|
+
}
|
|
1483
|
+
logger.warn("runtime_self_claim_compensated", {
|
|
1484
|
+
reason_code: reasonCode,
|
|
1485
|
+
detail,
|
|
1486
|
+
undispatched_id: claim.undispatched_id,
|
|
1487
|
+
source_message_id: claim.source_message_id,
|
|
1488
|
+
assignment_id: claim.assignment_id,
|
|
1489
|
+
target_endpoint_id: body.endpoint_id,
|
|
1490
|
+
});
|
|
1491
|
+
return true;
|
|
1492
|
+
}
|
|
1493
|
+
catch (err) {
|
|
1494
|
+
logger.error("runtime_self_claim_compensation_error", {
|
|
1495
|
+
reason_code: reasonCode,
|
|
1496
|
+
detail,
|
|
1497
|
+
err: err instanceof Error ? err.message : String(err),
|
|
1498
|
+
undispatched_id: claim.undispatched_id,
|
|
1499
|
+
source_message_id: claim.source_message_id,
|
|
1500
|
+
assignment_id: claim.assignment_id,
|
|
1501
|
+
target_endpoint_id: body.endpoint_id,
|
|
1502
|
+
});
|
|
1503
|
+
return false;
|
|
1504
|
+
}
|
|
1505
|
+
};
|
|
1506
|
+
const throwAfterClaimFailure = async (error, reasonCode) => {
|
|
1507
|
+
const released = await releaseClaimAfterFailure(reasonCode, error.message);
|
|
1508
|
+
if (!released) {
|
|
1509
|
+
throw new BrokerHttpError(503, "runtime_self_claim_outcome_unknown", "runtime self-claim was durably assigned but the broker could not expose or release it; retry the claim", {
|
|
1510
|
+
retryable: true,
|
|
1511
|
+
outcome_unknown: true,
|
|
1512
|
+
reason_code: reasonCode,
|
|
1513
|
+
original_error: error.code,
|
|
1514
|
+
});
|
|
1515
|
+
}
|
|
1516
|
+
throw error;
|
|
1517
|
+
};
|
|
1518
|
+
if (claim.undispatched_id !== body.undispatched_id) {
|
|
1519
|
+
await throwAfterClaimFailure(new BrokerHttpError(502, "runtime_self_claim_response_invalid", "self-claim response undispatched_id does not match request", { retryable: false }), "response_undispatched_id_mismatch");
|
|
1520
|
+
}
|
|
1521
|
+
if (!sameRuntimeWorkTargetRef(claim.target_ref, expectedTargetRef)) {
|
|
1522
|
+
await throwAfterClaimFailure(new BrokerHttpError(502, "runtime_self_claim_response_invalid", "self-claim response target_ref does not match registered endpoint work target", { retryable: false }), "response_target_ref_mismatch");
|
|
1523
|
+
}
|
|
1524
|
+
if (claim.message.sourceMessageId !== claim.source_message_id) {
|
|
1525
|
+
await throwAfterClaimFailure(new BrokerHttpError(502, "runtime_self_claim_response_invalid", "self-claim response message sourceMessageId does not match source_message_id", { retryable: false }), "response_message_source_mismatch");
|
|
1526
|
+
}
|
|
1527
|
+
const cached = undispatchedInbox.take(claim.undispatched_id);
|
|
1528
|
+
if (cached && cached.source_message_id !== claim.source_message_id) {
|
|
1529
|
+
logger.warn("runtime_self_claim_cache_mismatch", {
|
|
1530
|
+
undispatched_id: claim.undispatched_id,
|
|
1531
|
+
claimed_source_message_id: claim.source_message_id,
|
|
1532
|
+
cached_source_message_id: cached.source_message_id,
|
|
1533
|
+
});
|
|
1534
|
+
}
|
|
1535
|
+
const message = {
|
|
1536
|
+
id: claim.undispatched_id,
|
|
1537
|
+
source_message_id: claim.source_message_id,
|
|
1538
|
+
arrived_at: new Date(claim.assigned_at).toISOString(),
|
|
1539
|
+
sender_address: claim.message.from,
|
|
1540
|
+
content: claim.message.content,
|
|
1541
|
+
content_type: claim.message.contentType,
|
|
1542
|
+
metadata: claim.message.metadata ?? {},
|
|
1543
|
+
reason: "unaddressed",
|
|
1544
|
+
};
|
|
1545
|
+
const runtimeAssignment = {
|
|
1546
|
+
undispatchedId: claim.undispatched_id,
|
|
1547
|
+
sourceMessageId: claim.source_message_id,
|
|
1548
|
+
assignmentId: claim.assignment_id,
|
|
1549
|
+
targetRef: claim.target_ref,
|
|
1550
|
+
deliveryIntent: "external_handoff",
|
|
1551
|
+
...(typeof message.metadata.correlation_id === "string" && {
|
|
1552
|
+
replyCorrelationId: message.metadata.correlation_id,
|
|
1553
|
+
}),
|
|
1554
|
+
};
|
|
1555
|
+
const assignmentKey = runtimeAssignmentKey(claim.source_message_id, claim.assignment_id);
|
|
1556
|
+
const processingEvent = {
|
|
1557
|
+
type: "runtime_processing_state",
|
|
1558
|
+
version: 1,
|
|
1559
|
+
source_message_id: claim.source_message_id,
|
|
1560
|
+
assignment_id: claim.assignment_id,
|
|
1561
|
+
state_event_id: `${claim.assignment_id}:assigned`,
|
|
1562
|
+
state_sequence: 1,
|
|
1563
|
+
target_ref: claim.target_ref,
|
|
1564
|
+
state: "assigned_to_runtime_target",
|
|
1565
|
+
occurred_at: claim.assigned_at,
|
|
1566
|
+
undispatched_id: claim.undispatched_id,
|
|
1567
|
+
broker_projection_token: claim.broker_projection_token,
|
|
1568
|
+
};
|
|
1569
|
+
const processingResult = await emitRuntimeProcessingState(processingEvent);
|
|
1570
|
+
if (!processingResult.ok) {
|
|
1571
|
+
await throwAfterClaimFailure(new BrokerHttpError(processingResult.terminal ? 409 : 503, "runtime_self_claim_assignment_projection_failed", processingResult.detail ??
|
|
1572
|
+
"assigned_to_runtime_target projection was not accepted", { retryable: !processingResult.terminal }), "assigned_state_projection_failed");
|
|
1573
|
+
}
|
|
1574
|
+
runtimeAssignments.set(assignmentKey, {
|
|
1575
|
+
context: runtimeAssignment,
|
|
1576
|
+
message,
|
|
1577
|
+
brokerProjectionToken: claim.broker_projection_token,
|
|
1578
|
+
accepted: false,
|
|
1579
|
+
assignedAt: claim.assigned_at,
|
|
1580
|
+
lastStateSequence: processingEvent.state_sequence,
|
|
1581
|
+
});
|
|
1582
|
+
scheduleAcceptanceTimeout(assignmentKey);
|
|
1583
|
+
rememberRuntimeAssignmentCorrelation(entry.endpoint_id, message.metadata.correlation_id, assignmentKey);
|
|
1584
|
+
recordInboundCorrelation(entry.endpoint_id, message.metadata);
|
|
1585
|
+
logger.info("runtime_self_claimed", {
|
|
1586
|
+
undispatched_id: claim.undispatched_id,
|
|
1587
|
+
source_message_id: claim.source_message_id,
|
|
1588
|
+
assignment_id: claim.assignment_id,
|
|
1589
|
+
target_endpoint_id: entry.endpoint_id,
|
|
1590
|
+
});
|
|
1591
|
+
return {
|
|
1592
|
+
assignment: runtimeAssignment,
|
|
1593
|
+
message: {
|
|
1594
|
+
from: message.sender_address,
|
|
1595
|
+
content: message.content,
|
|
1596
|
+
contentType: message.content_type,
|
|
1597
|
+
metadata: message.metadata,
|
|
1598
|
+
sourceMessageId: message.source_message_id,
|
|
1599
|
+
},
|
|
1600
|
+
};
|
|
1601
|
+
},
|
|
1218
1602
|
async sendRuntimeAssignmentReply(body) {
|
|
1219
1603
|
const entry = registry.get(body.endpoint_id);
|
|
1220
1604
|
if (!entry) {
|
|
@@ -1223,6 +1607,7 @@ export async function startBrokerDaemon(opts) {
|
|
|
1223
1607
|
if (entry.plugin_pid !== body.plugin_pid) {
|
|
1224
1608
|
throw new BrokerHttpError(403, "endpoint_pid_mismatch", "plugin_pid does not own endpoint_id");
|
|
1225
1609
|
}
|
|
1610
|
+
assertEndpointOwnerToken(entry, body.endpoint_owner_token);
|
|
1226
1611
|
if (entry.state !== "active") {
|
|
1227
1612
|
throw new BrokerHttpError(409, "endpoint_not_active", `endpoint ${body.endpoint_id} is ${entry.state}; assignment reply is only allowed from Active`);
|
|
1228
1613
|
}
|
|
@@ -1392,6 +1777,7 @@ export async function startBrokerDaemon(opts) {
|
|
|
1392
1777
|
if (entry.plugin_pid !== body.plugin_pid) {
|
|
1393
1778
|
throw new BrokerHttpError(403, "endpoint_pid_mismatch", "plugin_pid does not own endpoint_id");
|
|
1394
1779
|
}
|
|
1780
|
+
assertEndpointOwnerToken(entry, body.endpoint_owner_token);
|
|
1395
1781
|
const key = runtimeAssignmentKey(body.source_message_id, body.assignment_id);
|
|
1396
1782
|
const assignment = runtimeAssignments.get(key);
|
|
1397
1783
|
if (!assignment) {
|
|
@@ -1483,10 +1869,10 @@ export async function startBrokerDaemon(opts) {
|
|
|
1483
1869
|
const buf = reconnectingBuffers.forEndpoint(endpoint_id);
|
|
1484
1870
|
const drained = buf.read();
|
|
1485
1871
|
graceTimers.cancel(endpoint_id);
|
|
1486
|
-
registry.markActive(endpoint_id, ipcWs);
|
|
1872
|
+
const activeEntry = registry.markActive(endpoint_id, ipcWs);
|
|
1487
1873
|
let allPushed = true;
|
|
1488
1874
|
for (const msg of drained) {
|
|
1489
|
-
const pushed =
|
|
1875
|
+
const pushed = await pushToPluginWithReceipt(activeEntry, {
|
|
1490
1876
|
event: "message_received",
|
|
1491
1877
|
from: msg.envelope.from,
|
|
1492
1878
|
content: msg.envelope.content,
|
|
@@ -1582,7 +1968,7 @@ export async function startBrokerDaemon(opts) {
|
|
|
1582
1968
|
handlers,
|
|
1583
1969
|
logger,
|
|
1584
1970
|
getNetworkPresence: () => networkPresence,
|
|
1585
|
-
onChannelOpened: (plugin_pid, ws) => {
|
|
1971
|
+
onChannelOpened: (plugin_pid, ws, clientCapabilities) => {
|
|
1586
1972
|
const prior = channels.get(plugin_pid);
|
|
1587
1973
|
if (prior && prior !== ws) {
|
|
1588
1974
|
displacedWs.add(prior);
|
|
@@ -1593,11 +1979,50 @@ export async function startBrokerDaemon(opts) {
|
|
|
1593
1979
|
}
|
|
1594
1980
|
}
|
|
1595
1981
|
channels.set(plugin_pid, ws);
|
|
1982
|
+
channelCapabilities.set(ws, clientCapabilities);
|
|
1983
|
+
},
|
|
1984
|
+
onPushAck: (plugin_pid, ws, push_id) => {
|
|
1985
|
+
const pending = pendingPushAcks.get(push_id);
|
|
1986
|
+
if (!pending) {
|
|
1987
|
+
logger.debug("ipc_push_ack_unknown", { plugin_pid, push_id });
|
|
1988
|
+
return;
|
|
1989
|
+
}
|
|
1990
|
+
if (pending.plugin_pid !== plugin_pid) {
|
|
1991
|
+
logger.warn("ipc_push_ack_pid_mismatch", {
|
|
1992
|
+
push_id,
|
|
1993
|
+
expected_plugin_pid: pending.plugin_pid,
|
|
1994
|
+
actual_plugin_pid: plugin_pid,
|
|
1995
|
+
event: pending.event,
|
|
1996
|
+
endpoint_id: pending.endpoint_id,
|
|
1997
|
+
});
|
|
1998
|
+
return;
|
|
1999
|
+
}
|
|
2000
|
+
if (pending.ipc_ws !== ws) {
|
|
2001
|
+
logger.warn("ipc_push_ack_ws_mismatch", {
|
|
2002
|
+
push_id,
|
|
2003
|
+
plugin_pid,
|
|
2004
|
+
event: pending.event,
|
|
2005
|
+
endpoint_id: pending.endpoint_id,
|
|
2006
|
+
});
|
|
2007
|
+
return;
|
|
2008
|
+
}
|
|
2009
|
+
settlePushAck(push_id, true);
|
|
1596
2010
|
},
|
|
1597
2011
|
onChannelClosed: (plugin_pid, ws) => {
|
|
1598
2012
|
if (channels.get(plugin_pid) === ws) {
|
|
1599
2013
|
channels.delete(plugin_pid);
|
|
1600
2014
|
}
|
|
2015
|
+
for (const [pushId, pending] of Array.from(pendingPushAcks.entries())) {
|
|
2016
|
+
if (pending.plugin_pid === plugin_pid && pending.ipc_ws === ws) {
|
|
2017
|
+
logger.warn("ipc_push_ack_channel_closed", {
|
|
2018
|
+
push_id: pushId,
|
|
2019
|
+
plugin_pid,
|
|
2020
|
+
event: pending.event,
|
|
2021
|
+
endpoint_id: pending.endpoint_id,
|
|
2022
|
+
});
|
|
2023
|
+
settlePushAck(pushId, false);
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
1601
2026
|
if (displacedWs.has(ws))
|
|
1602
2027
|
return;
|
|
1603
2028
|
const bound = wsEndpoints.get(ws);
|
|
@@ -1786,9 +2211,8 @@ export async function startBrokerDaemon(opts) {
|
|
|
1786
2211
|
routed_at: Date.now(),
|
|
1787
2212
|
};
|
|
1788
2213
|
}
|
|
1789
|
-
recordInboundCorrelation(decision.entry.endpoint_id, meta);
|
|
1790
2214
|
if (decision.entry.state === "active") {
|
|
1791
|
-
const pushed =
|
|
2215
|
+
const pushed = await pushToPluginWithReceipt(decision.entry, {
|
|
1792
2216
|
event: "message_received",
|
|
1793
2217
|
from: payload.from,
|
|
1794
2218
|
content: payload.content,
|
|
@@ -1800,6 +2224,7 @@ export async function startBrokerDaemon(opts) {
|
|
|
1800
2224
|
});
|
|
1801
2225
|
if (!pushed)
|
|
1802
2226
|
return false;
|
|
2227
|
+
recordInboundCorrelation(decision.entry.endpoint_id, meta);
|
|
1803
2228
|
}
|
|
1804
2229
|
else {
|
|
1805
2230
|
const buf = reconnectingBuffers.forEndpoint(decision.entry.endpoint_id);
|
|
@@ -1825,6 +2250,7 @@ export async function startBrokerDaemon(opts) {
|
|
|
1825
2250
|
});
|
|
1826
2251
|
return false;
|
|
1827
2252
|
}
|
|
2253
|
+
recordInboundCorrelation(decision.entry.endpoint_id, meta);
|
|
1828
2254
|
logger.info("buffered_for_reconnecting_endpoint", {
|
|
1829
2255
|
endpoint_id: decision.entry.endpoint_id,
|
|
1830
2256
|
buffer_size: buf.size(),
|
|
@@ -11,6 +11,8 @@ export interface DisplayMetadata {
|
|
|
11
11
|
}
|
|
12
12
|
export interface BrokerEndpointEntry {
|
|
13
13
|
endpoint_id: string;
|
|
14
|
+
endpoint_nonce: string;
|
|
15
|
+
endpoint_owner_token: string;
|
|
14
16
|
agent_id: string;
|
|
15
17
|
plugin_pid: number;
|
|
16
18
|
ipc_ws: WebSocket;
|
|
@@ -26,6 +28,8 @@ export interface BrokerEndpointEntry {
|
|
|
26
28
|
}
|
|
27
29
|
export interface RegisterArgs {
|
|
28
30
|
endpoint_id: string;
|
|
31
|
+
endpoint_nonce?: string;
|
|
32
|
+
endpoint_owner_token?: string;
|
|
29
33
|
agent_id: string;
|
|
30
34
|
plugin_pid: number;
|
|
31
35
|
ipc_ws: WebSocket;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"endpoint-registry.d.ts","sourceRoot":"","sources":["../../src/broker/endpoint-registry.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,SAAS,MAAM,IAAI,CAAC;AAChC,OAAO,KAAK,EACV,8BAA8B,EAC9B,wBAAwB,EACxB,yBAAyB,EAC1B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAG9D,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,QAAQ,GAAG,cAAc,CAAC;IACjC,WAAW,EAAE,IAAI,CAAC;IAElB,cAAc,CAAC,EAAE,IAAI,CAAC;IACtB,oBAAoB,CAAC,EAAE,yBAAyB,EAAE,CAAC;IACnD,iBAAiB,CAAC,EAAE,wBAAwB,CAAC;IAC7C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,wBAAwB,CAAC,EAAE,8BAA8B,CAAC;IAC1D,gBAAgB,EAAE,eAAe,CAAC;IAClC,gBAAgB,EAAE,qBAAqB,CAAC;CACzC;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,CAAC;IAClB,oBAAoB,CAAC,EAAE,yBAAyB,EAAE,CAAC;IACnD,iBAAiB,CAAC,EAAE,wBAAwB,CAAC;IAC7C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,wBAAwB,CAAC,EAAE,8BAA8B,CAAC;IAC1D,gBAAgB,EAAE,eAAe,CAAC;CACnC;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0C;IAG/D,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,mBAAmB;
|
|
1
|
+
{"version":3,"file":"endpoint-registry.d.ts","sourceRoot":"","sources":["../../src/broker/endpoint-registry.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,SAAS,MAAM,IAAI,CAAC;AAChC,OAAO,KAAK,EACV,8BAA8B,EAC9B,wBAAwB,EACxB,yBAAyB,EAC1B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAG9D,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,QAAQ,GAAG,cAAc,CAAC;IACjC,WAAW,EAAE,IAAI,CAAC;IAElB,cAAc,CAAC,EAAE,IAAI,CAAC;IACtB,oBAAoB,CAAC,EAAE,yBAAyB,EAAE,CAAC;IACnD,iBAAiB,CAAC,EAAE,wBAAwB,CAAC;IAC7C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,wBAAwB,CAAC,EAAE,8BAA8B,CAAC;IAC1D,gBAAgB,EAAE,eAAe,CAAC;IAClC,gBAAgB,EAAE,qBAAqB,CAAC;CACzC;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,CAAC;IAClB,oBAAoB,CAAC,EAAE,yBAAyB,EAAE,CAAC;IACnD,iBAAiB,CAAC,EAAE,wBAAwB,CAAC;IAC7C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,wBAAwB,CAAC,EAAE,8BAA8B,CAAC;IAC1D,gBAAgB,EAAE,eAAe,CAAC;CACnC;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0C;IAG/D,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,mBAAmB;IAyBjD,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS;IAKzD,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS;IAWhE,gBAAgB,CACd,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,IAAI,GACnB,mBAAmB;IAoBtB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,mBAAmB;IA8BvE,uBAAuB,CACrB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,mBAAmB,GAAG,SAAS;IAYlC,iBAAiB,CACf,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GAEhB;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,KAAK,EAAE,mBAAmB,CAAA;KAAE,GACxC;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,kBAAkB,CAAA;KAAE,GACzC;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,uBAAuB,CAAA;KAAE,GAC9C;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,2BAA2B,CAAA;KAAE;IAWtD,IAAI,IAAI,mBAAmB,EAAE;IAK7B,IAAI,IAAI,MAAM;CAGf"}
|
|
@@ -7,6 +7,8 @@ export class EndpointRegistry {
|
|
|
7
7
|
}
|
|
8
8
|
const entry = {
|
|
9
9
|
endpoint_id: args.endpoint_id,
|
|
10
|
+
endpoint_nonce: args.endpoint_nonce ?? `broker-local:${args.endpoint_id}`,
|
|
11
|
+
endpoint_owner_token: args.endpoint_owner_token ?? `broker-local-owner:${args.endpoint_id}`,
|
|
10
12
|
agent_id: args.agent_id,
|
|
11
13
|
plugin_pid: args.plugin_pid,
|
|
12
14
|
ipc_ws: args.ipc_ws,
|
package/dist/broker/entry.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ interface RuntimePrincipal {
|
|
|
15
15
|
export declare function resolveCredentialsFromFile(filePath: string, accountId: string, envApiHost: string | undefined): Promise<ResolvedCredentials>;
|
|
16
16
|
export declare function resolveRuntimePrincipal(apiHost: string, runtimeKey: string, fetchImpl?: typeof globalThis.fetch): Promise<RuntimePrincipal>;
|
|
17
17
|
export declare function buildApiPort(apiHost: string, runtimeKey: string, logger: BrokerLogger): RuntimeEndpointPort;
|
|
18
|
+
export declare function installFatalExitHandlers(logger: BrokerLogger): void;
|
|
18
19
|
export declare function main(): Promise<void>;
|
|
19
20
|
export {};
|
|
20
21
|
//# sourceMappingURL=entry.d.ts.map
|