@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.
@@ -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":"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"}
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 (!pushToPlugin(target.ipc_ws, stamped)) {
938
- await restorePendingAssignmentsForEndpoint(target.endpoint_id, "ipc_push_failed");
939
- return {
940
- ok: false,
941
- detail: `target endpoint not writable: ${targetEndpointId}`,
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: randomUUID(),
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 { endpoint_id: apiResp.endpoint_id };
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 = pushToPlugin(ipcWs, {
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 = pushToPlugin(decision.entry.ipc_ws, {
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;IAsBjD,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"}
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,
@@ -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