@zlink-systems/stream-connector 0.22.0 → 0.23.0

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.
@@ -120,7 +120,8 @@ var defaultHeaderFlags = {
120
120
  hasRequestSeq: 1,
121
121
  hasMetadata: 2,
122
122
  hasCorrelationId: 8,
123
- hasFlowId: 16
123
+ hasFlowId: 16,
124
+ hasActorSlot: 32
124
125
  };
125
126
  var ZLINK_STREAM_FORMAT_MARKER = 242;
126
127
  var ZLINK_STREAM_RESPONSE_KIND = 3;
@@ -167,6 +168,7 @@ function encodeStreamWireHeader(header, flagOverrides) {
167
168
  }
168
169
  const hasCorrelation = correlationBytes !== void 0;
169
170
  const hasFlow = header.flowId !== void 0 || header.flowOrigin !== void 0;
171
+ const hasActorSlot = header.actorSlot !== void 0;
170
172
  if (hasFlow && (header.flowId === void 0 || header.flowOrigin === void 0)) {
171
173
  throw new Error("Stream flow id and origin must be provided together.");
172
174
  }
@@ -174,13 +176,17 @@ function encodeStreamWireHeader(header, flagOverrides) {
174
176
  if (header.flowOrigin !== void 0 && ![1, 2, 3, 4].includes(header.flowOrigin)) {
175
177
  throw new Error("Stream flow origin is invalid.");
176
178
  }
179
+ if (header.actorSlot !== void 0 && (!Number.isInteger(header.actorSlot) || header.actorSlot < 1 || header.actorSlot > 65535)) {
180
+ throw new Error("Stream actor slot is invalid.");
181
+ }
177
182
  let headerFlags = header.flags;
178
183
  headerFlags = hasRequestSeq ? headerFlags | flags.hasRequestSeq : headerFlags & ~flags.hasRequestSeq;
179
184
  headerFlags = hasMetadata ? headerFlags | flags.hasMetadata : headerFlags & ~flags.hasMetadata;
180
185
  headerFlags = hasCorrelation ? headerFlags | flags.hasCorrelationId : headerFlags & ~flags.hasCorrelationId;
181
186
  headerFlags = hasFlow ? headerFlags | flags.hasFlowId : headerFlags & ~flags.hasFlowId;
187
+ headerFlags = hasActorSlot ? headerFlags | flags.hasActorSlot : headerFlags & ~flags.hasActorSlot;
182
188
  const metadataBytes = hasMetadata ? encodeStreamWireMetadata(header.metadata) : new Uint8Array();
183
- const size = 4 + (hasRequestSeq ? 8 : 0) + 1 + nameBytes.length + (hasMetadata ? 2 + metadataBytes.length : 0) + (hasCorrelation ? 1 + correlationBytes.length : 0) + (hasFlow ? 37 : 0);
189
+ const size = 4 + (hasRequestSeq ? 8 : 0) + 1 + nameBytes.length + (hasMetadata ? 2 + metadataBytes.length : 0) + (hasCorrelation ? 1 + correlationBytes.length : 0) + (hasFlow ? 37 : 0) + (hasActorSlot ? 2 : 0);
184
190
  const buffer = new Uint8Array(size);
185
191
  let offset = 0;
186
192
  buffer[offset++] = ZLINK_STREAM_FORMAT_MARKER;
@@ -213,6 +219,9 @@ function encodeStreamWireHeader(header, flagOverrides) {
213
219
  offset += 36;
214
220
  buffer[offset++] = header.flowOrigin;
215
221
  }
222
+ if (hasActorSlot) {
223
+ writeUInt16BE(buffer, offset, header.actorSlot);
224
+ }
216
225
  return buffer;
217
226
  }
218
227
  function decodeStreamWireHeader(header, flagOverrides, includeFlow = true) {
@@ -231,7 +240,8 @@ function decodeStreamWireHeader(header, flagOverrides, includeFlow = true) {
231
240
  const hasMetadata = (headerFlags & flags.hasMetadata) !== 0;
232
241
  const hasCorrelation = (headerFlags & flags.hasCorrelationId) !== 0;
233
242
  const hasFlow = (headerFlags & flags.hasFlowId) !== 0;
234
- if ((headerFlags & ~31) !== 0) {
243
+ const hasActorSlot = (headerFlags & flags.hasActorSlot) !== 0;
244
+ if ((headerFlags & ~63) !== 0) {
235
245
  throw new Error("Unknown mandatory stream header flag.");
236
246
  }
237
247
  let requestSeq;
@@ -286,6 +296,17 @@ function decodeStreamWireHeader(header, flagOverrides, includeFlow = true) {
286
296
  }
287
297
  flowOrigin = includeFlow ? decodedFlowOrigin : void 0;
288
298
  }
299
+ let actorSlot;
300
+ if (hasActorSlot) {
301
+ if (header.length - offset < 2) {
302
+ throw new Error("Stream actor slot is incomplete.");
303
+ }
304
+ actorSlot = readUInt16BE(header, offset);
305
+ if (actorSlot === 0) {
306
+ throw new Error("Stream actor slot must not be zero.");
307
+ }
308
+ offset += 2;
309
+ }
289
310
  if (offset !== header.length) {
290
311
  throw new Error("Stream header has trailing bytes.");
291
312
  }
@@ -298,7 +319,8 @@ function decodeStreamWireHeader(header, flagOverrides, includeFlow = true) {
298
319
  metadata: decodedMetadata.metadata,
299
320
  correlationId,
300
321
  flowId,
301
- flowOrigin
322
+ flowOrigin,
323
+ actorSlot
302
324
  };
303
325
  }
304
326
  function validateFlowId(flowId) {
@@ -464,13 +486,6 @@ var ZlinkStreamDispatchMode = /* @__PURE__ */ ((ZlinkStreamDispatchMode2) => {
464
486
  ZlinkStreamDispatchMode2["Immediate"] = "immediate";
465
487
  return ZlinkStreamDispatchMode2;
466
488
  })(ZlinkStreamDispatchMode || {});
467
- var ZlinkStreamDiagnosticsLevel = /* @__PURE__ */ ((ZlinkStreamDiagnosticsLevel4) => {
468
- ZlinkStreamDiagnosticsLevel4["Off"] = "off";
469
- ZlinkStreamDiagnosticsLevel4["Errors"] = "errors";
470
- ZlinkStreamDiagnosticsLevel4["Normal"] = "normal";
471
- ZlinkStreamDiagnosticsLevel4["Detailed"] = "detailed";
472
- return ZlinkStreamDiagnosticsLevel4;
473
- })(ZlinkStreamDiagnosticsLevel || {});
474
489
  var ZlinkStreamMessageKind = /* @__PURE__ */ ((ZlinkStreamMessageKind2) => {
475
490
  ZlinkStreamMessageKind2[ZlinkStreamMessageKind2["Send"] = 1] = "Send";
476
491
  ZlinkStreamMessageKind2[ZlinkStreamMessageKind2["Request"] = 2] = "Request";
@@ -486,6 +501,7 @@ var ZlinkStreamHeaderFlags = /* @__PURE__ */ ((ZlinkStreamHeaderFlags2) => {
486
501
  ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["PayloadCompressed"] = 4] = "PayloadCompressed";
487
502
  ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["HasCorrelationId"] = 8] = "HasCorrelationId";
488
503
  ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["HasFlowId"] = 16] = "HasFlowId";
504
+ ZlinkStreamHeaderFlags2[ZlinkStreamHeaderFlags2["HasActorSlot"] = 32] = "HasActorSlot";
489
505
  return ZlinkStreamHeaderFlags2;
490
506
  })(ZlinkStreamHeaderFlags || {});
491
507
  var ZlinkStreamErrorCode = /* @__PURE__ */ ((ZlinkStreamErrorCode2) => {
@@ -734,15 +750,16 @@ function validateName(name, allowReserved = false) {
734
750
 
735
751
  // packages/stream-connector/src/Runtime/Calls/ZlinkStreamCallBuilders.ts
736
752
  var ZlinkStreamCallBuilderState = class {
753
+ constructor(name, actorSlot, validateActor) {
754
+ this.actorSlot = actorSlot;
755
+ this.validateActor = validateActor;
756
+ this.name = name;
757
+ }
737
758
  executed = false;
738
759
  name;
739
760
  metadata = ZlinkStreamMetadataMap.empty;
740
761
  timeoutMs;
741
762
  compress = false;
742
- flow;
743
- constructor(name) {
744
- this.name = name;
745
- }
746
763
  ensureNotExecuted() {
747
764
  if (this.executed) {
748
765
  throw connectorError(
@@ -751,6 +768,7 @@ var ZlinkStreamCallBuilderState = class {
751
768
  );
752
769
  }
753
770
  this.executed = true;
771
+ this.validateActor?.();
754
772
  }
755
773
  resolveMessageName() {
756
774
  if (this.name === void 0) {
@@ -763,10 +781,10 @@ var ZlinkStreamCallBuilderState = class {
763
781
  }
764
782
  };
765
783
  var ZlinkStreamSendBuilder = class {
766
- constructor(connector, name, payload) {
784
+ constructor(connector, name, payload, actorSlot, validateActor) {
767
785
  this.connector = connector;
768
786
  this.payload = payload;
769
- this.state = new ZlinkStreamCallBuilderState(name);
787
+ this.state = new ZlinkStreamCallBuilderState(name, actorSlot, validateActor);
770
788
  }
771
789
  state;
772
790
  packetName(name) {
@@ -782,10 +800,6 @@ var ZlinkStreamSendBuilder = class {
782
800
  this.state.compress = true;
783
801
  return this;
784
802
  }
785
- flowFrom(flow) {
786
- this.state.flow = flow;
787
- return this;
788
- }
789
803
  async submit(signal) {
790
804
  throwIfAborted(signal);
791
805
  this.state.ensureNotExecuted();
@@ -797,15 +811,16 @@ var ZlinkStreamSendBuilder = class {
797
811
  this.state.compress,
798
812
  void 0,
799
813
  signal,
800
- this.state.flow
814
+ void 0,
815
+ this.state.actorSlot
801
816
  );
802
817
  }
803
818
  };
804
819
  var ZlinkStreamRequestBuilder = class {
805
- constructor(connector, name, payload) {
820
+ constructor(connector, name, payload, actorSlot, validateActor) {
806
821
  this.connector = connector;
807
822
  this.payload = payload;
808
- this.state = new ZlinkStreamCallBuilderState(name);
823
+ this.state = new ZlinkStreamCallBuilderState(name, actorSlot, validateActor);
809
824
  }
810
825
  state;
811
826
  packetName(name) {
@@ -825,10 +840,6 @@ var ZlinkStreamRequestBuilder = class {
825
840
  this.state.compress = true;
826
841
  return this;
827
842
  }
828
- flowFrom(flow) {
829
- this.state.flow = flow;
830
- return this;
831
- }
832
843
  submit(signalOrCallback) {
833
844
  this.state.ensureNotExecuted();
834
845
  const operation = this.connector.requestEncoded(
@@ -838,7 +849,7 @@ var ZlinkStreamRequestBuilder = class {
838
849
  this.state.compress,
839
850
  this.state.timeoutMs ?? this.connector.options.requestTimeoutMs,
840
851
  typeof signalOrCallback === "function" ? void 0 : signalOrCallback,
841
- this.state.flow
852
+ this.state.actorSlot
842
853
  );
843
854
  if (typeof signalOrCallback === "function") {
844
855
  operation.then(
@@ -860,7 +871,7 @@ var ZlinkStreamRequestBuilder = class {
860
871
  this.state.compress,
861
872
  this.state.timeoutMs ?? this.connector.options.requestTimeoutMs,
862
873
  signal,
863
- this.state.flow
874
+ this.state.actorSlot
864
875
  );
865
876
  }
866
877
  };
@@ -1216,8 +1227,7 @@ var ZlinkStreamHeaderCodec = class {
1216
1227
  name: header.name,
1217
1228
  metadata: header.metadata.values,
1218
1229
  correlationId: header.correlationId,
1219
- flowId: header.flowId,
1220
- flowOrigin: encodeFlowOrigin(header.flowOrigin)
1230
+ actorSlot: header.actorSlot
1221
1231
  });
1222
1232
  } catch (cause) {
1223
1233
  throw connectorError(
@@ -1227,15 +1237,10 @@ var ZlinkStreamHeaderCodec = class {
1227
1237
  );
1228
1238
  }
1229
1239
  }
1230
- /**
1231
- * `includeFlow=false` (diagnostics Off, spec 27 §4) skips reading and
1232
- * validating the inbound flow fields while the structural length checks in
1233
- * the wire decoder are preserved.
1234
- */
1235
- static decode(header, includeFlow = true) {
1240
+ static decode(header) {
1236
1241
  let decoded;
1237
1242
  try {
1238
- const wire = decodeStreamWireHeader(header, void 0, includeFlow);
1243
+ const wire = decodeStreamWireHeader(header, void 0, false);
1239
1244
  const metadata = wire.metadata.size === 0 ? ZlinkStreamMetadataMap.empty : ZlinkStreamMetadataMap.from(wire.metadata);
1240
1245
  decoded = {
1241
1246
  kind: wire.kind,
@@ -1245,8 +1250,7 @@ var ZlinkStreamHeaderCodec = class {
1245
1250
  name: wire.name,
1246
1251
  metadata,
1247
1252
  correlationId: wire.correlationId,
1248
- flowId: wire.flowId,
1249
- flowOrigin: decodeFlowOrigin(wire.flowOrigin)
1253
+ actorSlot: wire.actorSlot
1250
1254
  };
1251
1255
  } catch (cause) {
1252
1256
  throw connectorError(
@@ -1269,7 +1273,7 @@ function isReplyKind2(kind) {
1269
1273
  function streamWireErrorMessage2(cause) {
1270
1274
  return cause instanceof Error ? cause.message : "Stream header is invalid.";
1271
1275
  }
1272
- function buildHeader(kind, name, codec, metadata, compress, requestSeq, correlationId, flowId, flowOrigin) {
1276
+ function buildHeader(kind, name, codec, metadata, compress, requestSeq, correlationId, actorSlot) {
1273
1277
  let flags = 0 /* None */;
1274
1278
  if (requestSeq !== void 0) {
1275
1279
  flags |= 1 /* HasRequestSeq */;
@@ -1283,8 +1287,17 @@ function buildHeader(kind, name, codec, metadata, compress, requestSeq, correlat
1283
1287
  if (correlationId !== void 0 && correlationId.length > 0) {
1284
1288
  flags |= 8 /* HasCorrelationId */;
1285
1289
  }
1286
- if (flowId !== void 0) flags |= 16 /* HasFlowId */;
1287
- return { kind, codec, flags, requestSeq, name, metadata, correlationId, flowId, flowOrigin };
1290
+ if (actorSlot !== void 0) flags |= 32 /* HasActorSlot */;
1291
+ return {
1292
+ kind,
1293
+ codec,
1294
+ flags,
1295
+ requestSeq,
1296
+ name,
1297
+ metadata,
1298
+ correlationId,
1299
+ actorSlot
1300
+ };
1288
1301
  }
1289
1302
  function validateHeaderSemantics(header) {
1290
1303
  validateEnum(header.kind, header.codec, header.flags);
@@ -1310,8 +1323,9 @@ function validateHeaderSemantics(header) {
1310
1323
  }
1311
1324
  if (header.kind === 5 /* Control */) {
1312
1325
  const hasCorrelation = header.correlationId !== void 0 && header.correlationId.length > 0 || (header.flags & 8 /* HasCorrelationId */) !== 0;
1313
- const hasFlow = header.flowId !== void 0 || header.flowOrigin !== void 0 || (header.flags & 16 /* HasFlowId */) !== 0;
1314
- if (header.flags !== 0 /* None */ || hasRequestSeq || hasMetadata || hasCorrelation || hasFlow || header.codec !== 0 /* Raw */) {
1326
+ const hasFlow = (header.flags & 16 /* HasFlowId */) !== 0;
1327
+ const hasActorSlot = header.actorSlot !== void 0 || (header.flags & 32 /* HasActorSlot */) !== 0;
1328
+ if (header.flags !== 0 /* None */ || hasRequestSeq || hasMetadata || hasCorrelation || hasFlow || hasActorSlot || header.codec !== 0 /* Raw */) {
1315
1329
  throw connectorError(
1316
1330
  "frameDecodeFailed" /* FrameDecodeFailed */,
1317
1331
  "Control packet must use raw codec and must not contain flags."
@@ -1326,17 +1340,11 @@ function validateEnum(kind, codec, flags) {
1326
1340
  if (![0, 1, 2, 3].includes(codec)) {
1327
1341
  throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Unknown stream codec.");
1328
1342
  }
1329
- const known = 1 /* HasRequestSeq */ | 2 /* HasMetadata */ | 4 /* PayloadCompressed */ | 8 /* HasCorrelationId */ | 16 /* HasFlowId */;
1343
+ const known = 1 /* HasRequestSeq */ | 2 /* HasMetadata */ | 4 /* PayloadCompressed */ | 8 /* HasCorrelationId */ | 16 /* HasFlowId */ | 32 /* HasActorSlot */;
1330
1344
  if ((flags & ~known) !== 0) {
1331
1345
  throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Unknown stream header flag.");
1332
1346
  }
1333
1347
  }
1334
- function encodeFlowOrigin(origin) {
1335
- return origin === void 0 ? void 0 : { Inbound: 1, Timer: 2, Application: 3, Lifecycle: 4 }[origin];
1336
- }
1337
- function decodeFlowOrigin(origin) {
1338
- return origin === void 0 ? void 0 : { 1: "Inbound", 2: "Timer", 3: "Application", 4: "Lifecycle" }[origin];
1339
- }
1340
1348
 
1341
1349
  // packages/stream-connector/src/Runtime/Protocol/ZlinkStreamFrameProtocol.ts
1342
1350
  var ZLINK_STREAM_HEARTBEAT_PING = "$zlink.heartbeat.ping";
@@ -1345,7 +1353,7 @@ var ZlinkStreamFrameProtocol = class {
1345
1353
  constructor(options) {
1346
1354
  this.options = options;
1347
1355
  }
1348
- encode(kind, name, payload, metadata, compress, requestSeq, correlationId, flowId, flowOrigin) {
1356
+ encode(kind, name, payload, metadata, compress, requestSeq, correlationId, actorSlot) {
1349
1357
  const payloadBytes = compress ? compressPayload(payload.payload, this.options.compression, this.options.compressionCodec) : payload.payload;
1350
1358
  const header = buildHeader(
1351
1359
  kind,
@@ -1355,8 +1363,7 @@ var ZlinkStreamFrameProtocol = class {
1355
1363
  compress,
1356
1364
  requestSeq,
1357
1365
  correlationId,
1358
- flowId,
1359
- flowOrigin
1366
+ actorSlot
1360
1367
  );
1361
1368
  return this.encodeFrame(header, payloadBytes);
1362
1369
  }
@@ -1372,21 +1379,16 @@ var ZlinkStreamFrameProtocol = class {
1372
1379
  payload
1373
1380
  );
1374
1381
  }
1375
- decode(frameBytes, flowEnabled = this.flowEnabled()) {
1382
+ decode(frameBytes) {
1376
1383
  const frame = ZlinkStreamFrameCodec.decode(frameBytes);
1377
1384
  return {
1378
- // Spec 27 §4: with diagnostics Off the inbound flow fields are neither
1379
- // read nor validated (structural length checks are preserved).
1380
- header: ZlinkStreamHeaderCodec.decode(frame.header, flowEnabled),
1385
+ header: ZlinkStreamHeaderCodec.decode(frame.header),
1381
1386
  payload: frame.payload
1382
1387
  };
1383
1388
  }
1384
- flowEnabled() {
1385
- return this.options.diagnosticsLevel !== "off" /* Off */;
1386
- }
1387
- decodeFrames(chunk, flowEnabled = this.flowEnabled()) {
1389
+ decodeFrames(chunk) {
1388
1390
  return splitZlinkStreamFrames(chunk).map((frame) => {
1389
- const decoded = this.decode(frame, flowEnabled);
1391
+ const decoded = this.decode(frame);
1390
1392
  if (decoded.payload.length > this.options.maxReceivePayloadSize) {
1391
1393
  throw connectorError(
1392
1394
  "frameTooLarge" /* FrameTooLarge */,
@@ -1438,12 +1440,6 @@ function parseEndpoint(endpoint) {
1438
1440
  }
1439
1441
 
1440
1442
  // packages/stream-connector/src/Runtime/ZlinkStreamConnectorOptions.ts
1441
- var validDiagnosticsLevels = /* @__PURE__ */ new Set([
1442
- "off" /* Off */,
1443
- "errors" /* Errors */,
1444
- "normal" /* Normal */,
1445
- "detailed" /* Detailed */
1446
- ]);
1447
1443
  function normalizeOptions(options, defaultTransportFactory) {
1448
1444
  const endpoint = options.endpoint;
1449
1445
  if (endpoint.trim().length === 0) {
@@ -1463,7 +1459,6 @@ function normalizeOptions(options, defaultTransportFactory) {
1463
1459
  validatePositive(options.maxReceivePayloadSize ?? 64 * 1024, "MaxReceivePayloadSize");
1464
1460
  validateHeartbeat(options.heartbeat);
1465
1461
  validateReconnect(options.reconnect);
1466
- validateDiagnosticsLevel(options.diagnosticsLevel);
1467
1462
  return {
1468
1463
  endpoint,
1469
1464
  transport: inferredTransport,
@@ -1489,10 +1484,7 @@ function normalizeOptions(options, defaultTransportFactory) {
1489
1484
  compressionCodec: resolveCompressionCodec2(options),
1490
1485
  nameResolver: options.nameResolver ?? defaultPacketNameResolver,
1491
1486
  transportFactory: options.transportFactory ?? defaultTransportFactory,
1492
- codec: options.codec,
1493
- // Spec 26 §4: the default diagnostics level is Errors, which preserves
1494
- // the connector's established wire behavior.
1495
- diagnosticsLevel: options.diagnosticsLevel ?? "errors" /* Errors */
1487
+ codec: options.codec
1496
1488
  };
1497
1489
  }
1498
1490
  var defaultPacketNameResolver = {
@@ -1517,11 +1509,6 @@ function resolveCompressionCodec2(options) {
1517
1509
  }
1518
1510
  return options.compressionCodec;
1519
1511
  }
1520
- function validateDiagnosticsLevel(level) {
1521
- if (level !== void 0 && !validDiagnosticsLevels.has(level)) {
1522
- throw connectorError("configurationError" /* ConfigurationError */, "DiagnosticsLevel is invalid.");
1523
- }
1524
- }
1525
1512
  function validatePositive(value, name) {
1526
1513
  if (value <= 0) {
1527
1514
  throw connectorError("validationFailed" /* ValidationFailed */, `${name} must be positive.`);
@@ -1565,25 +1552,6 @@ function validateReconnect(options) {
1565
1552
  }
1566
1553
  }
1567
1554
 
1568
- // packages/stream-connector/src/Runtime/ZlinkStreamDiagnosticsLevelCell.ts
1569
- var ZlinkStreamDiagnosticsLevelCell = class {
1570
- current;
1571
- constructor(initial) {
1572
- this.current = initial;
1573
- }
1574
- get level() {
1575
- return this.current;
1576
- }
1577
- set(level) {
1578
- const candidate = level;
1579
- if (candidate === void 0 || candidate === null) {
1580
- throw connectorError("configurationError" /* ConfigurationError */, "DiagnosticsLevel is invalid.");
1581
- }
1582
- validateDiagnosticsLevel(level);
1583
- this.current = level;
1584
- }
1585
- };
1586
-
1587
1555
  // packages/stream-connector/src/Runtime/ZlinkStreamPendingRequests.ts
1588
1556
  var ZlinkStreamPendingRequests = class {
1589
1557
  nextRequestSeq = 1n;
@@ -1596,16 +1564,21 @@ var ZlinkStreamPendingRequests = class {
1596
1564
  let timeout;
1597
1565
  let resolvePending;
1598
1566
  let rejectPending;
1599
- const promise = new Promise((resolve, reject) => {
1600
- timeout = setTimeout(() => {
1601
- this.active.delete(requestSeq);
1602
- reject(
1603
- connectorError("requestTimeout" /* RequestTimeout */, `Request '${packetName}' timed out.`)
1604
- );
1605
- }, timeoutMs);
1606
- resolvePending = resolve;
1607
- rejectPending = (error) => reject(connectorError(error.code, error.message, error.cause));
1608
- });
1567
+ const promise = new Promise(
1568
+ (resolve, reject) => {
1569
+ timeout = setTimeout(() => {
1570
+ this.active.delete(requestSeq);
1571
+ reject(
1572
+ connectorError(
1573
+ "requestTimeout" /* RequestTimeout */,
1574
+ `Request '${packetName}' timed out.`
1575
+ )
1576
+ );
1577
+ }, timeoutMs);
1578
+ resolvePending = resolve;
1579
+ rejectPending = (error) => reject(connectorError(error.code, error.message, error.cause));
1580
+ }
1581
+ );
1609
1582
  this.active.set(requestSeq, {
1610
1583
  packetName,
1611
1584
  promise,
@@ -1629,15 +1602,14 @@ var ZlinkStreamPendingRequests = class {
1629
1602
  });
1630
1603
  return { requestSeq, promise };
1631
1604
  }
1632
- /* stream connector spec §5.2: a pending request is matched by request_seq alone. Diagnostics
1633
- * use the original request name retained by this registry, never a legacy reply name. */
1634
- resolve(requestSeq, value) {
1605
+ /* stream connector spec §5.2: a pending request is matched by request_seq alone. */
1606
+ resolve(requestSeq, value, metadata) {
1635
1607
  const pending = this.active.get(requestSeq);
1636
1608
  if (pending === void 0) {
1637
1609
  return false;
1638
1610
  }
1639
1611
  this.active.delete(requestSeq);
1640
- pending.resolve(value);
1612
+ pending.resolve({ name: pending.packetName, metadata, payload: value });
1641
1613
  return true;
1642
1614
  }
1643
1615
  reject(requestSeq, error) {
@@ -1773,9 +1745,11 @@ var ZlinkStreamReceivedMessages = class {
1773
1745
  */
1774
1746
  resetForNewConnection() {
1775
1747
  this.receivedCounts.clear();
1748
+ const submittedCallbacks = this.queue.slice(this.queueHead).filter((item) => item?.kind === "callback");
1776
1749
  this.queue.length = 0;
1750
+ this.queue.push(...submittedCallbacks);
1777
1751
  this.queueHead = 0;
1778
- this.queuedCount = 0;
1752
+ this.queuedCount = submittedCallbacks.length;
1779
1753
  }
1780
1754
  /**
1781
1755
  * Releases every registered wait surface because the connection it was
@@ -1804,7 +1778,14 @@ var ZlinkStreamReceivedMessages = class {
1804
1778
  return;
1805
1779
  }
1806
1780
  }
1807
- this.queue.push({ message, signal });
1781
+ this.queue.push({ kind: "message", message, signal });
1782
+ this.queuedCount += 1;
1783
+ if (this.deliverOnArrival) {
1784
+ this.scheduleDrain();
1785
+ }
1786
+ }
1787
+ enqueueCallback(callback) {
1788
+ this.queue.push({ kind: "callback", callback });
1808
1789
  this.queuedCount += 1;
1809
1790
  if (this.deliverOnArrival) {
1810
1791
  this.scheduleDrain();
@@ -1831,7 +1812,7 @@ var ZlinkStreamReceivedMessages = class {
1831
1812
  offerQueued(name, registration) {
1832
1813
  for (let index = this.queueHead; index < this.queue.length; index += 1) {
1833
1814
  const queued = this.queue[index];
1834
- if (queued === void 0 || queued.message.name !== name) {
1815
+ if (queued === void 0 || queued.kind !== "message" || queued.message.name !== name) {
1835
1816
  continue;
1836
1817
  }
1837
1818
  if (!registration.consume(queued.message)) {
@@ -1859,6 +1840,10 @@ var ZlinkStreamReceivedMessages = class {
1859
1840
  const queued = this.queue[index];
1860
1841
  if (queued === void 0) continue;
1861
1842
  this.removeAt(index);
1843
+ if (queued.kind === "callback") {
1844
+ await queued.callback();
1845
+ continue;
1846
+ }
1862
1847
  const { message, signal } = queued;
1863
1848
  const handlers = [...this.handlers.get(message.name)];
1864
1849
  for (const handler of handlers) {
@@ -1889,7 +1874,7 @@ var ZlinkStreamReceivedMessages = class {
1889
1874
  findDeliverableIndex() {
1890
1875
  for (let index = this.queueHead; index < this.queue.length; index += 1) {
1891
1876
  const queued = this.queue[index];
1892
- if (queued !== void 0 && (this.handlers.get(queued.message.name)?.size ?? 0) > 0) {
1877
+ if (queued !== void 0 && (queued.kind === "callback" || (this.handlers.get(queued.message.name)?.size ?? 0) > 0)) {
1893
1878
  return index;
1894
1879
  }
1895
1880
  }
@@ -1897,7 +1882,8 @@ var ZlinkStreamReceivedMessages = class {
1897
1882
  }
1898
1883
  hasQueuedMessage(name) {
1899
1884
  for (let index = this.queueHead; index < this.queue.length; index += 1) {
1900
- if (this.queue[index]?.message.name === name) return true;
1885
+ const queued = this.queue[index];
1886
+ if (queued?.kind === "message" && queued.message.name === name) return true;
1901
1887
  }
1902
1888
  return false;
1903
1889
  }
@@ -1921,14 +1907,12 @@ var ZlinkStreamReceivedMessages = class {
1921
1907
 
1922
1908
  // packages/stream-connector/src/Runtime/ZlinkStreamFrameSender.ts
1923
1909
  var ZlinkStreamFrameSender = class {
1924
- constructor(protocol, flowContext) {
1910
+ constructor(protocol) {
1925
1911
  this.protocol = protocol;
1926
- this.flowContext = flowContext;
1927
1912
  }
1928
1913
  pendingWrites = /* @__PURE__ */ new Set();
1929
- async send(connection, kind, name, payload, metadata, compress, requestSeq, signal, correlationId, explicitFlow) {
1914
+ async send(connection, kind, name, payload, metadata, compress, requestSeq, signal, correlationId, actorSlot) {
1930
1915
  throwIfAborted(signal);
1931
- const flow = this.protocol.flowEnabled() ? this.flowContext.currentOrCreate(explicitFlow) : void 0;
1932
1916
  await this.write(
1933
1917
  connection,
1934
1918
  this.protocol.encode(
@@ -1939,8 +1923,7 @@ var ZlinkStreamFrameSender = class {
1939
1923
  compress,
1940
1924
  requestSeq,
1941
1925
  correlationId,
1942
- flow?.flowId,
1943
- flow?.flowOrigin
1926
+ actorSlot
1944
1927
  ),
1945
1928
  signal
1946
1929
  );
@@ -1987,15 +1970,185 @@ function decodeSessionClosing(payload) {
1987
1970
  return { closeReason, diagnostic };
1988
1971
  }
1989
1972
 
1973
+ // packages/stream-connector/src/Runtime/ZlinkStreamActors.ts
1974
+ var ACTOR_BOUND = "$zlink.actor.bound";
1975
+ var ACTOR_UNBOUND = "$zlink.actor.unbound";
1976
+ var zlinkStreamActorBinding = Symbol("zlink.stream.actorBinding");
1977
+ var DefaultZlinkStreamActor = class {
1978
+ constructor(connector, actorId, slot) {
1979
+ this.connector = connector;
1980
+ this.actorId = actorId;
1981
+ this.slot = slot;
1982
+ }
1983
+ bound = true;
1984
+ get isBound() {
1985
+ return this.bound;
1986
+ }
1987
+ send(payload, messageType) {
1988
+ this.ensureBound();
1989
+ return this.connector.sendForActor(this, payload, messageType);
1990
+ }
1991
+ request(payload, messageType) {
1992
+ this.ensureBound();
1993
+ return this.connector.requestForActor(this, payload, messageType);
1994
+ }
1995
+ on(nameOrType, handler, messageType) {
1996
+ return this.connector.onActorMessage(this, nameOrType, handler, messageType);
1997
+ }
1998
+ ensureBound() {
1999
+ if (!this.bound) {
2000
+ throw connectorError(
2001
+ "validationFailed" /* ValidationFailed */,
2002
+ `Actor '${this.actorId}' is no longer bound.`
2003
+ );
2004
+ }
2005
+ }
2006
+ close() {
2007
+ this.bound = false;
2008
+ }
2009
+ };
2010
+ var ZlinkStreamActors = class {
2011
+ constructor(connector, receivedMessages, events) {
2012
+ this.connector = connector;
2013
+ this.receivedMessages = receivedMessages;
2014
+ this.events = events;
2015
+ }
2016
+ bySlot = /* @__PURE__ */ new Map();
2017
+ byId = /* @__PURE__ */ new Map();
2018
+ issued = [];
2019
+ boundHandlers = /* @__PURE__ */ new Set();
2020
+ unboundHandlers = /* @__PURE__ */ new Set();
2021
+ get snapshot() {
2022
+ return Object.freeze([...this.bySlot.values()]);
2023
+ }
2024
+ find(actorId) {
2025
+ return this.byId.get(actorId);
2026
+ }
2027
+ onBound(handler) {
2028
+ this.boundHandlers.add(handler);
2029
+ return subscription(() => this.boundHandlers.delete(handler));
2030
+ }
2031
+ onUnbound(handler) {
2032
+ this.unboundHandlers.add(handler);
2033
+ return subscription(() => this.unboundHandlers.delete(handler));
2034
+ }
2035
+ processControl(name, payload, signal) {
2036
+ if (name === ACTOR_BOUND) {
2037
+ this.bind(payload, signal);
2038
+ return true;
2039
+ }
2040
+ if (name === ACTOR_UNBOUND) {
2041
+ this.unbind(payload, signal);
2042
+ return true;
2043
+ }
2044
+ return false;
2045
+ }
2046
+ resolve(slot) {
2047
+ const actor = this.bySlot.get(slot);
2048
+ if (actor === void 0) {
2049
+ throw connectorError(
2050
+ "frameDecodeFailed" /* FrameDecodeFailed */,
2051
+ `Actor slot '${slot}' is not bound.`
2052
+ );
2053
+ }
2054
+ return actor;
2055
+ }
2056
+ closeAll(signal) {
2057
+ for (const actor of this.issued) {
2058
+ if (!actor.isBound) continue;
2059
+ this.bySlot.delete(actor.slot);
2060
+ this.byId.delete(actor.actorId);
2061
+ actor.close();
2062
+ this.queue(this.unboundHandlers, actor, signal);
2063
+ }
2064
+ this.issued.length = 0;
2065
+ }
2066
+ bind(payload, signal) {
2067
+ if (payload.length < 5 || payload[0] !== 1) {
2068
+ throw invalidControl("Actor bound payload is invalid.");
2069
+ }
2070
+ const slot = payload[1] << 8 | payload[2];
2071
+ const idLength = payload[3];
2072
+ if (slot === 0 || idLength === 0 || payload.length !== 4 + idLength) {
2073
+ throw invalidControl("Actor bound payload is invalid.");
2074
+ }
2075
+ let actorId;
2076
+ try {
2077
+ actorId = new TextDecoder("utf-8", { fatal: true }).decode(payload.subarray(4));
2078
+ } catch (cause) {
2079
+ throw connectorError(
2080
+ "frameDecodeFailed" /* FrameDecodeFailed */,
2081
+ "Actor id is not valid UTF-8.",
2082
+ cause
2083
+ );
2084
+ }
2085
+ if (actorId.length === 0 || this.bySlot.has(slot) || this.byId.has(actorId)) {
2086
+ throw invalidControl("Actor bound identity is already in use.");
2087
+ }
2088
+ const actor = new DefaultZlinkStreamActor(this.connector, actorId, slot);
2089
+ this.bySlot.set(slot, actor);
2090
+ this.byId.set(actorId, actor);
2091
+ this.issued.push(actor);
2092
+ this.queue(this.boundHandlers, actor, signal);
2093
+ }
2094
+ unbind(payload, signal) {
2095
+ if (payload.length !== 3 || payload[0] !== 1) {
2096
+ throw invalidControl("Actor unbound payload is invalid.");
2097
+ }
2098
+ const slot = payload[1] << 8 | payload[2];
2099
+ const actor = this.bySlot.get(slot);
2100
+ if (slot === 0 || actor === void 0) {
2101
+ throw invalidControl(`Actor slot '${slot}' is not bound.`);
2102
+ }
2103
+ this.bySlot.delete(slot);
2104
+ this.byId.delete(actor.actorId);
2105
+ actor.close();
2106
+ this.queue(this.unboundHandlers, actor, signal);
2107
+ }
2108
+ queue(handlers, actor, signal) {
2109
+ this.receivedMessages.enqueueCallback(() => {
2110
+ for (const handler of [...handlers]) {
2111
+ this.invoke(handler, actor, signal);
2112
+ }
2113
+ });
2114
+ }
2115
+ invoke(handler, actor, signal) {
2116
+ try {
2117
+ Promise.resolve(handler(actor, signal)).catch((cause) => {
2118
+ void this.events.publishError(
2119
+ {
2120
+ code: "userCallbackFailed" /* UserCallbackFailed */,
2121
+ message: "Actor lifecycle handler failed.",
2122
+ cause
2123
+ },
2124
+ signal
2125
+ );
2126
+ });
2127
+ } catch (cause) {
2128
+ void this.events.publishError(
2129
+ {
2130
+ code: "userCallbackFailed" /* UserCallbackFailed */,
2131
+ message: "Actor lifecycle handler failed.",
2132
+ cause
2133
+ },
2134
+ signal
2135
+ );
2136
+ }
2137
+ }
2138
+ };
2139
+ function invalidControl(message) {
2140
+ return connectorError("frameDecodeFailed" /* FrameDecodeFailed */, message);
2141
+ }
2142
+
1990
2143
  // packages/stream-connector/src/Runtime/ZlinkStreamReceiveDispatcher.ts
1991
2144
  var ZlinkStreamReceiveDispatcher = class {
1992
- constructor(protocol, pendingRequests, receivedMessages, frameSender, events, flowContext, serverClosing) {
2145
+ constructor(protocol, pendingRequests, receivedMessages, frameSender, events, actors, serverClosing) {
1993
2146
  this.protocol = protocol;
1994
2147
  this.pendingRequests = pendingRequests;
1995
2148
  this.receivedMessages = receivedMessages;
1996
2149
  this.frameSender = frameSender;
1997
2150
  this.events = events;
1998
- this.flowContext = flowContext;
2151
+ this.actors = actors;
1999
2152
  this.serverClosing = serverClosing;
2000
2153
  }
2001
2154
  /**
@@ -2022,49 +2175,47 @@ var ZlinkStreamReceiveDispatcher = class {
2022
2175
  if (frameBytes === void 0) {
2023
2176
  return { available: false, inbound: false };
2024
2177
  }
2025
- const flowEnabled = this.protocol.flowEnabled();
2026
2178
  let frames;
2027
2179
  try {
2028
- frames = this.protocol.decodeFrames(frameBytes, flowEnabled);
2180
+ frames = this.protocol.decodeFrames(frameBytes);
2029
2181
  } catch (cause) {
2030
- await this.events.publishError(
2031
- toStreamError(cause, "frameDecodeFailed" /* FrameDecodeFailed */, "Frame decode failed."),
2032
- signal
2033
- );
2034
- return { available: true, inbound: false };
2182
+ throw cause;
2035
2183
  }
2036
2184
  for (const frame of frames) {
2037
2185
  if (isCurrent !== void 0 && !isCurrent()) {
2038
2186
  break;
2039
2187
  }
2040
2188
  try {
2041
- await this.dispatch(
2042
- connection,
2043
- frame.header,
2044
- frame.payload,
2045
- signal,
2046
- flowEnabled,
2047
- connectionForSend
2048
- );
2189
+ await this.dispatch(connection, frame.header, frame.payload, signal, connectionForSend);
2049
2190
  } catch (cause) {
2050
2191
  if (frame.header.kind === 5 /* Control */ && frame.header.name === ZLINK_STREAM_HEARTBEAT_PING) {
2051
2192
  throw cause;
2052
2193
  }
2053
- await this.events.publishError(
2054
- toStreamError(cause, "frameDecodeFailed" /* FrameDecodeFailed */, "Frame dispatch failed."),
2055
- signal
2194
+ const error = toStreamError(
2195
+ cause,
2196
+ "frameDecodeFailed" /* FrameDecodeFailed */,
2197
+ "Frame dispatch failed."
2056
2198
  );
2199
+ if (error.code === "frameDecodeFailed" /* FrameDecodeFailed */) {
2200
+ throw cause;
2201
+ }
2202
+ await this.events.publishError(error, signal);
2057
2203
  }
2058
2204
  }
2059
2205
  return { available: true, inbound: true };
2060
2206
  }
2061
- async dispatch(connection, header, payload, signal, flowEnabled, connectionForSend) {
2207
+ async dispatch(connection, header, payload, signal, connectionForSend) {
2208
+ const actor = header.actorSlot === void 0 ? void 0 : this.actors.resolve(header.actorSlot);
2062
2209
  if (header.kind === 3 /* Response */ && header.requestSeq !== void 0) {
2063
2210
  try {
2064
- if (!this.pendingRequests.resolve(header.requestSeq, {
2065
- codec: header.codec,
2066
- payload: this.protocol.decodePayload(header, payload)
2067
- })) {
2211
+ if (!this.pendingRequests.resolve(
2212
+ header.requestSeq,
2213
+ {
2214
+ codec: header.codec,
2215
+ payload: this.protocol.decodePayload(header, payload)
2216
+ },
2217
+ header.metadata
2218
+ )) {
2068
2219
  await this.events.publishError(
2069
2220
  {
2070
2221
  code: "frameDecodeFailed" /* FrameDecodeFailed */,
@@ -2112,20 +2263,22 @@ var ZlinkStreamReceiveDispatcher = class {
2112
2263
  return;
2113
2264
  }
2114
2265
  if (header.kind === 1 /* Send */) {
2115
- const flow = flowEnabled ? this.flowContext.createInbound(header.flowId, header.flowOrigin) : void 0;
2116
2266
  this.receivedMessages.enqueue(
2117
2267
  {
2118
2268
  name: header.name,
2119
2269
  metadata: header.metadata,
2120
2270
  payload: { codec: header.codec, payload: this.protocol.decodePayload(header, payload) },
2121
- flowId: flow?.flowId,
2122
- flowOrigin: flow?.flowOrigin
2271
+ actorId: actor?.actorId,
2272
+ [zlinkStreamActorBinding]: actor
2123
2273
  },
2124
2274
  signal
2125
2275
  );
2126
2276
  }
2127
2277
  }
2128
2278
  async dispatchControl(connection, header, payload, signal, connectionForSend) {
2279
+ if (this.actors.processControl(header.name, payload, signal)) {
2280
+ return;
2281
+ }
2129
2282
  if (header.name === ZLINK_SESSION_CLOSING) {
2130
2283
  const closing = decodeSessionClosing(payload);
2131
2284
  await this.serverClosing?.(closing.closeReason);
@@ -2184,12 +2337,13 @@ function randomizedDelay(baseDelayMs) {
2184
2337
  return Math.round(baseDelayMs * (0.5 + Math.random() * 0.5));
2185
2338
  }
2186
2339
  var ZlinkStreamConnectorLifecycle = class {
2187
- constructor(options, pendingRequests, frameSender, receiveDispatcher, receivedMessages, events) {
2340
+ constructor(options, pendingRequests, frameSender, receiveDispatcher, receivedMessages, actors, events) {
2188
2341
  this.options = options;
2189
2342
  this.pendingRequests = pendingRequests;
2190
2343
  this.frameSender = frameSender;
2191
2344
  this.receiveDispatcher = receiveDispatcher;
2192
2345
  this.receivedMessages = receivedMessages;
2346
+ this.actors = actors;
2193
2347
  this.events = events;
2194
2348
  }
2195
2349
  receiveLoopAbort;
@@ -2325,8 +2479,9 @@ var ZlinkStreamConnectorLifecycle = class {
2325
2479
  message: "Connector closed."
2326
2480
  });
2327
2481
  this.receivedMessages.connectionEnded();
2328
- void this.setState("closed" /* Closed */, void 0, signal);
2329
- this.publishDisconnectedWithoutWaiting(signal);
2482
+ this.actors.closeAll(signal);
2483
+ this.queueState("closed" /* Closed */, void 0, signal);
2484
+ this.queueDisconnected(signal);
2330
2485
  if (errors.length === 1) throw errors[0];
2331
2486
  if (errors.length > 1) throw new AggregateError(errors, "Stream connector close failed.");
2332
2487
  }
@@ -2555,6 +2710,7 @@ var ZlinkStreamConnectorLifecycle = class {
2555
2710
  this.currentConnection = void 0;
2556
2711
  this.pendingRequests.failAll(error);
2557
2712
  this.receivedMessages.connectionEnded();
2713
+ this.actors.closeAll();
2558
2714
  try {
2559
2715
  await connection?.close();
2560
2716
  } catch {
@@ -2570,11 +2726,8 @@ var ZlinkStreamConnectorLifecycle = class {
2570
2726
  */
2571
2727
  async announceDisconnect(error) {
2572
2728
  if (this.closeRequested) return;
2573
- const announce = this.claimDisconnectedPublish();
2574
- void this.setState("disconnected" /* Disconnected */, error);
2575
- if (announce) {
2576
- void this.events.publishDisconnected().catch(() => void 0);
2577
- }
2729
+ this.queueState("disconnected" /* Disconnected */, error);
2730
+ this.queueDisconnected();
2578
2731
  if (this.shouldReconnect()) {
2579
2732
  queueMicrotask(() => {
2580
2733
  void this.connect().catch(() => void 0);
@@ -2622,16 +2775,35 @@ var ZlinkStreamConnectorLifecycle = class {
2622
2775
  publishDisconnectedWithoutWaiting(signal) {
2623
2776
  void this.publishDisconnectedOnce(signal).catch(() => void 0);
2624
2777
  }
2778
+ queueDisconnected(signal) {
2779
+ if (!this.claimDisconnectedPublish()) return;
2780
+ this.receivedMessages.enqueueCallback(() => {
2781
+ void this.events.publishDisconnected(signal).catch(() => void 0);
2782
+ });
2783
+ }
2784
+ queueState(current, error, signal) {
2785
+ const change = this.transitionState(current, error);
2786
+ if (change === void 0) return;
2787
+ this.receivedMessages.enqueueCallback(() => {
2788
+ void this.publishStateChange(change, signal).catch(() => void 0);
2789
+ });
2790
+ }
2625
2791
  async setState(current, error, signal) {
2792
+ const change = this.transitionState(current, error);
2793
+ if (change === void 0) return;
2794
+ await this.publishStateChange(change, signal);
2795
+ }
2796
+ transitionState(current, error) {
2626
2797
  const previous = this.currentState;
2627
2798
  this.currentState = current;
2628
2799
  if (previous === current && error === void 0) {
2629
- return;
2630
- }
2631
- await this.events.publishStateChanged({ previous, current, error }, signal);
2632
- if (error !== void 0) {
2633
- await this.events.publishError(error, signal);
2800
+ return void 0;
2634
2801
  }
2802
+ return { previous, current, error };
2803
+ }
2804
+ async publishStateChange(change, signal) {
2805
+ await this.events.publishStateChanged(change, signal);
2806
+ if (change.error !== void 0) await this.events.publishError(change.error, signal);
2635
2807
  }
2636
2808
  };
2637
2809
 
@@ -2666,36 +2838,6 @@ var ZlinkStreamConnectorEvents = class {
2666
2838
  }
2667
2839
  };
2668
2840
 
2669
- // packages/stream-connector/src/Runtime/ZlinkFlowContext.ts
2670
- var BrowserZlinkFlowContext = class {
2671
- currentOrCreate(explicit) {
2672
- return explicit ?? { flowId: this.createUuidV7(), flowOrigin: "Application" };
2673
- }
2674
- createInbound(flowId, flowOrigin) {
2675
- return { flowId: flowId ?? this.createUuidV7(), flowOrigin: flowOrigin ?? "Inbound" };
2676
- }
2677
- createUuidV7() {
2678
- const crypto = globalThis.crypto;
2679
- if (crypto === void 0) {
2680
- throw connectorError(
2681
- "configurationError" /* ConfigurationError */,
2682
- "The browser entrypoint requires the platform Web Crypto API."
2683
- );
2684
- }
2685
- return formatUuidV7(crypto.getRandomValues(new Uint8Array(16)));
2686
- }
2687
- };
2688
- function formatUuidV7(bytes) {
2689
- const timestamp = BigInt(Date.now());
2690
- for (let index = 5; index >= 0; index -= 1) {
2691
- bytes[index] = Number(timestamp >> BigInt((5 - index) * 8) & 0xffn);
2692
- }
2693
- bytes[6] = 112 | bytes[6] & 15;
2694
- bytes[8] = 128 | bytes[8] & 63;
2695
- const hex = [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
2696
- return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
2697
- }
2698
-
2699
2841
  // packages/stream-connector/src/Runtime/Transport/BrowserWebSocketConnection.ts
2700
2842
  var BrowserStreamTransportFactory = class {
2701
2843
  async connect(options, signal) {
@@ -2910,30 +3052,26 @@ var DefaultZlinkStreamConnector = class {
2910
3052
  pendingRequests = new ZlinkStreamPendingRequests();
2911
3053
  frameSender;
2912
3054
  receiveDispatcher;
2913
- diagnosticsLevelCell;
3055
+ requestSendingHandlers = /* @__PURE__ */ new Set();
3056
+ replyReceivedHandlers = /* @__PURE__ */ new Set();
3057
+ boundActors;
2914
3058
  options;
2915
3059
  constructor(options) {
2916
- const flowContext = new BrowserZlinkFlowContext();
2917
3060
  this.options = normalizeOptions(options, new BrowserStreamTransportFactory());
2918
- this.diagnosticsLevelCell = new ZlinkStreamDiagnosticsLevelCell(this.options.diagnosticsLevel);
2919
- Object.defineProperty(this.options, "diagnosticsLevel", {
2920
- enumerable: true,
2921
- configurable: true,
2922
- get: () => this.diagnosticsLevelCell.level
2923
- });
2924
3061
  const protocol = new ZlinkStreamFrameProtocol(this.options);
2925
- this.frameSender = new ZlinkStreamFrameSender(protocol, flowContext);
3062
+ this.frameSender = new ZlinkStreamFrameSender(protocol);
2926
3063
  this.receivedMessages = new ZlinkStreamReceivedMessages(
2927
3064
  this.events,
2928
3065
  this.options.dispatchMode === "immediate" /* Immediate */
2929
3066
  );
3067
+ this.boundActors = new ZlinkStreamActors(this, this.receivedMessages, this.events);
2930
3068
  this.receiveDispatcher = new ZlinkStreamReceiveDispatcher(
2931
3069
  protocol,
2932
3070
  this.pendingRequests,
2933
3071
  this.receivedMessages,
2934
3072
  this.frameSender,
2935
3073
  this.events,
2936
- flowContext,
3074
+ this.boundActors,
2937
3075
  (reason) => this.lifecycle.serverClosing(reason)
2938
3076
  );
2939
3077
  this.lifecycle = new ZlinkStreamConnectorLifecycle(
@@ -2942,6 +3080,7 @@ var DefaultZlinkStreamConnector = class {
2942
3080
  this.frameSender,
2943
3081
  this.receiveDispatcher,
2944
3082
  this.receivedMessages,
3083
+ this.boundActors,
2945
3084
  this.events
2946
3085
  );
2947
3086
  }
@@ -2957,6 +3096,18 @@ var DefaultZlinkStreamConnector = class {
2957
3096
  get pendingDispatchCount() {
2958
3097
  return this.pendingRequests.count;
2959
3098
  }
3099
+ get actors() {
3100
+ return this.boundActors.snapshot;
3101
+ }
3102
+ actor(actorId) {
3103
+ return this.boundActors.find(actorId);
3104
+ }
3105
+ onActorBound(handler) {
3106
+ return this.boundActors.onBound(handler);
3107
+ }
3108
+ onActorUnbound(handler) {
3109
+ return this.boundActors.onUnbound(handler);
3110
+ }
2960
3111
  /**
2961
3112
  * Spec stream-connector 32 §10: how many packets carrying `name` arrived on
2962
3113
  * the current connection. Arrivals are what is counted, so a message a
@@ -2968,37 +3119,6 @@ var DefaultZlinkStreamConnector = class {
2968
3119
  validateName(name);
2969
3120
  return this.receivedMessages.receivedCount(name);
2970
3121
  }
2971
- /**
2972
- * Current diagnostics level (spec 26 §4.1, spec stream-connector 32 §13).
2973
- * Reflects the level set by the most recent {@link setDiagnosticsLevel}
2974
- * call, or the construction-time option (default
2975
- * {@link ZlinkStreamDiagnosticsLevel.Errors}) if it was never changed.
2976
- */
2977
- get diagnosticsLevel() {
2978
- return this.diagnosticsLevelCell.level;
2979
- }
2980
- /**
2981
- * Changes the diagnostics level in place without recreating the connector
2982
- * (spec 26 §4.1, spec stream-connector 32 §13). The change is an atomic
2983
- * state update: it applies to processing points that read the level after
2984
- * this call returns and is never applied retroactively to frames already
2985
- * built. Rejects unknown values with {@link ZlinkStreamErrorCode.ConfigurationError}.
2986
- * Spec stream-connector 32 §13: this surface changes the value without
2987
- * waiting for anything; it is not a blocking call over the asynchronous pair,
2988
- * which a receive callback would otherwise make wait for its own completion.
2989
- */
2990
- setDiagnosticsLevel(level) {
2991
- this.diagnosticsLevelCell.set(level);
2992
- }
2993
- /**
2994
- * Asynchronous counterpart of {@link setDiagnosticsLevel} (spec
2995
- * stream-connector 32 §13). It changes the same value; awaiting it is how a
2996
- * caller observes the change, and it never replaces the synchronous surface.
2997
- */
2998
- setDiagnosticsLevelAsync(level) {
2999
- this.setDiagnosticsLevel(level);
3000
- return Promise.resolve();
3001
- }
3002
3122
  onErrorReceived(handler) {
3003
3123
  return this.events.onError(handler);
3004
3124
  }
@@ -3008,6 +3128,14 @@ var DefaultZlinkStreamConnector = class {
3008
3128
  onConnectionStateChanged(handler) {
3009
3129
  return this.events.onStateChanged(handler);
3010
3130
  }
3131
+ onRequestSending(handler) {
3132
+ this.requestSendingHandlers.add(handler);
3133
+ return subscription(() => this.requestSendingHandlers.delete(handler));
3134
+ }
3135
+ onReplyReceived(handler) {
3136
+ this.replyReceivedHandlers.add(handler);
3137
+ return subscription(() => this.replyReceivedHandlers.delete(handler));
3138
+ }
3011
3139
  async connect(signal) {
3012
3140
  await this.lifecycle.connect(signal);
3013
3141
  }
@@ -3025,18 +3153,60 @@ var DefaultZlinkStreamConnector = class {
3025
3153
  const encoded = this.encodePayload(payload, messageType);
3026
3154
  return new ZlinkStreamRequestBuilder(this, this.resolveNameOrDefault(encoded), encoded);
3027
3155
  }
3028
- on(name, handler, messageType) {
3156
+ on(nameOrType, handler, messageType) {
3029
3157
  const encodedHandler = (message, signal) => handler(
3030
3158
  {
3031
3159
  name: message.name,
3032
3160
  metadata: message.metadata,
3033
- payload: this.decodePayload(message.payload, messageType),
3034
- flowId: message.flowId,
3035
- flowOrigin: message.flowOrigin
3161
+ payload: this.decodePayload(
3162
+ message.payload,
3163
+ messageType ?? (typeof nameOrType === "function" ? nameOrType : void 0)
3164
+ ),
3165
+ actorId: message.actorId
3036
3166
  },
3037
3167
  signal
3038
3168
  );
3039
- return this.receivedMessages.on(name, encodedHandler);
3169
+ return this.receivedMessages.on(this.observedName(nameOrType), encodedHandler);
3170
+ }
3171
+ sendForActor(actor, payload, messageType) {
3172
+ const encoded = this.encodePayload(payload, messageType);
3173
+ return new ZlinkStreamSendBuilder(
3174
+ this,
3175
+ this.resolveNameOrDefault(encoded),
3176
+ encoded,
3177
+ actor.slot,
3178
+ () => actor.ensureBound()
3179
+ );
3180
+ }
3181
+ requestForActor(actor, payload, messageType) {
3182
+ const encoded = this.encodePayload(payload, messageType);
3183
+ return new ZlinkStreamRequestBuilder(
3184
+ this,
3185
+ this.resolveNameOrDefault(encoded),
3186
+ encoded,
3187
+ actor.slot,
3188
+ () => actor.ensureBound()
3189
+ );
3190
+ }
3191
+ onActorMessage(actor, nameOrType, handler, messageType) {
3192
+ const encodedHandler = (message, signal) => {
3193
+ if (message[zlinkStreamActorBinding] !== actor) {
3194
+ return;
3195
+ }
3196
+ return handler(
3197
+ {
3198
+ name: message.name,
3199
+ metadata: message.metadata,
3200
+ payload: this.decodePayload(
3201
+ message.payload,
3202
+ messageType ?? (typeof nameOrType === "function" ? nameOrType : void 0)
3203
+ ),
3204
+ actorId: message.actorId
3205
+ },
3206
+ signal
3207
+ );
3208
+ };
3209
+ return this.receivedMessages.on(this.observedName(nameOrType), encodedHandler);
3040
3210
  }
3041
3211
  waitFor(nameOrType) {
3042
3212
  return new ZlinkStreamWaitBuilder(this, this.observedName(nameOrType));
@@ -3119,8 +3289,7 @@ var DefaultZlinkStreamConnector = class {
3119
3289
  name: message.name,
3120
3290
  metadata: message.metadata,
3121
3291
  payload: this.decodeWaitPayload(message.payload),
3122
- flowId: message.flowId,
3123
- flowOrigin: message.flowOrigin
3292
+ actorId: message.actorId
3124
3293
  };
3125
3294
  if (!predicate(decoded)) {
3126
3295
  return false;
@@ -3159,7 +3328,7 @@ var DefaultZlinkStreamConnector = class {
3159
3328
  }
3160
3329
  return payload;
3161
3330
  }
3162
- async sendEncoded(kind, name, payload, metadata, compress, requestSeq, signal, flow, correlationId) {
3331
+ async sendEncoded(kind, name, payload, metadata, compress, requestSeq, signal, correlationId, actorSlot) {
3163
3332
  await this.frameSender.send(
3164
3333
  this.lifecycle.connectionForSend(),
3165
3334
  kind,
@@ -3170,37 +3339,105 @@ var DefaultZlinkStreamConnector = class {
3170
3339
  requestSeq,
3171
3340
  signal,
3172
3341
  correlationId,
3173
- flow
3342
+ actorSlot
3174
3343
  );
3175
3344
  }
3176
3345
  /**
3177
3346
  * Per-connector monotonic correlation id (hex). The client generates it on each request
3178
- * and the server echoes it back on the reply, so flows can be joined across the wire.
3347
+ * and the server echoes it back on the reply.
3179
3348
  */
3180
3349
  nextCorrelationId() {
3181
3350
  this.correlationCounter += 1n;
3182
3351
  return this.correlationCounter.toString(16);
3183
3352
  }
3184
- async requestEncoded(name, payload, metadata, compress, timeoutMs, signal, flow) {
3185
- const pending = this.pendingRequests.create(name, timeoutMs);
3353
+ async requestEncoded(name, payload, metadata, compress, timeoutMs, signal, actorSlot) {
3354
+ const startedAt = Date.now();
3355
+ const actorId = actorSlot === void 0 ? void 0 : this.boundActors.resolve(actorSlot).actorId;
3356
+ let requestMetadata = metadata;
3357
+ const sendingContext = {
3358
+ requestPacketName: name,
3359
+ actorId,
3360
+ setMetadata(key, value) {
3361
+ requestMetadata = requestMetadata.with(key, value);
3362
+ }
3363
+ };
3364
+ let pending;
3186
3365
  try {
3366
+ throwIfAborted(signal);
3367
+ for (const handler of [...this.requestSendingHandlers]) {
3368
+ try {
3369
+ handler(sendingContext);
3370
+ } catch (cause) {
3371
+ queueMicrotask(() => {
3372
+ void this.events.publishError(
3373
+ toStreamError(
3374
+ cause,
3375
+ "userCallbackFailed" /* UserCallbackFailed */,
3376
+ "Request sending hook failed."
3377
+ ),
3378
+ signal
3379
+ );
3380
+ });
3381
+ }
3382
+ }
3383
+ pending = this.pendingRequests.create(name, timeoutMs);
3187
3384
  await this.sendEncoded(
3188
3385
  2 /* Request */,
3189
3386
  name,
3190
3387
  payload,
3191
- metadata,
3388
+ requestMetadata,
3192
3389
  compress,
3193
3390
  pending.requestSeq,
3194
3391
  signal,
3195
- flow,
3196
- this.nextCorrelationId()
3392
+ this.nextCorrelationId(),
3393
+ actorSlot
3394
+ );
3395
+ const reply = await pending.promise;
3396
+ this.publishReplyReceived(
3397
+ {
3398
+ requestPacketName: name,
3399
+ actorId,
3400
+ succeeded: true,
3401
+ reply: { ...reply, actorId },
3402
+ elapsed: Date.now() - startedAt
3403
+ },
3404
+ signal
3197
3405
  );
3198
- return await pending.promise;
3406
+ return reply.payload;
3199
3407
  } catch (error) {
3200
- this.pendingRequests.cancel(pending.requestSeq);
3408
+ if (pending !== void 0) this.pendingRequests.cancel(pending.requestSeq);
3409
+ this.publishReplyReceived(
3410
+ {
3411
+ requestPacketName: name,
3412
+ actorId,
3413
+ succeeded: false,
3414
+ error: unwrapStreamError(error),
3415
+ elapsed: Date.now() - startedAt
3416
+ },
3417
+ signal
3418
+ );
3201
3419
  throw error;
3202
3420
  }
3203
3421
  }
3422
+ publishReplyReceived(context, signal) {
3423
+ if (this.replyReceivedHandlers.size === 0) return;
3424
+ this.receivedMessages.enqueueCallback(async () => {
3425
+ for (const handler of [...this.replyReceivedHandlers]) {
3426
+ try {
3427
+ await handler(context, signal);
3428
+ } catch (cause) {
3429
+ await this.events.publishError(
3430
+ toStreamError(
3431
+ cause,
3432
+ "userCallbackFailed" /* UserCallbackFailed */,
3433
+ "Reply received hook failed."
3434
+ ),
3435
+ signal
3436
+ );
3437
+ }
3438
+ }
3439
+ });
3440
+ }
3204
3441
  resolveNameOrDefault(payload) {
3205
3442
  if (payload.messageType === void 0) {
3206
3443
  return void 0;
@@ -3226,7 +3463,6 @@ export {
3226
3463
  ZlinkStreamCodec,
3227
3464
  ZlinkStreamCompression,
3228
3465
  ZlinkStreamConnectionState,
3229
- ZlinkStreamDiagnosticsLevel,
3230
3466
  ZlinkStreamDispatchMode,
3231
3467
  ZlinkStreamErrorCode,
3232
3468
  ZlinkStreamException,