@zlink-systems/stream-connector 0.21.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) => {
@@ -628,7 +644,11 @@ function unwrapStreamError(error) {
628
644
  if (error instanceof ZlinkStreamException) {
629
645
  return error.error;
630
646
  }
631
- return { code: "remoteError" /* RemoteError */, message: error instanceof Error ? error.message : String(error), cause: error };
647
+ return {
648
+ code: "remoteError" /* RemoteError */,
649
+ message: error instanceof Error ? error.message : String(error),
650
+ cause: error
651
+ };
632
652
  }
633
653
  function subscription(dispose) {
634
654
  return { dispose };
@@ -663,7 +683,10 @@ function utf8Decode2(value) {
663
683
  var zlinkStreamAssert = {
664
684
  ensure(condition, message) {
665
685
  if (typeof message !== "string" || message.trim().length === 0) {
666
- throw connectorError("validationFailed" /* ValidationFailed */, "zlinkStreamAssert.ensure requires a non-empty diagnostic message.");
686
+ throw connectorError(
687
+ "validationFailed" /* ValidationFailed */,
688
+ "zlinkStreamAssert.ensure requires a non-empty diagnostic message."
689
+ );
667
690
  }
668
691
  if (!condition) {
669
692
  throw connectorError("validationFailed" /* ValidationFailed */, message);
@@ -712,42 +735,56 @@ function validateName(name, allowReserved = false) {
712
735
  throw connectorError("validationFailed" /* ValidationFailed */, "Message name must not be empty.");
713
736
  }
714
737
  if (!allowReserved && name.startsWith("$zlink.")) {
715
- throw connectorError("validationFailed" /* ValidationFailed */, "Message name uses a reserved zlink prefix.");
738
+ throw connectorError(
739
+ "validationFailed" /* ValidationFailed */,
740
+ "Message name uses a reserved zlink prefix."
741
+ );
716
742
  }
717
743
  if (utf8Encode2(name).length > 255) {
718
- throw connectorError("validationFailed" /* ValidationFailed */, "Message name must not exceed 255 UTF-8 bytes.");
744
+ throw connectorError(
745
+ "validationFailed" /* ValidationFailed */,
746
+ "Message name must not exceed 255 UTF-8 bytes."
747
+ );
719
748
  }
720
749
  }
721
750
 
722
751
  // packages/stream-connector/src/Runtime/Calls/ZlinkStreamCallBuilders.ts
723
752
  var ZlinkStreamCallBuilderState = class {
753
+ constructor(name, actorSlot, validateActor) {
754
+ this.actorSlot = actorSlot;
755
+ this.validateActor = validateActor;
756
+ this.name = name;
757
+ }
724
758
  executed = false;
725
759
  name;
726
760
  metadata = ZlinkStreamMetadataMap.empty;
727
761
  timeoutMs;
728
762
  compress = false;
729
- flow;
730
- constructor(name) {
731
- this.name = name;
732
- }
733
763
  ensureNotExecuted() {
734
764
  if (this.executed) {
735
- throw connectorError("validationFailed" /* ValidationFailed */, "Builder instances can be executed only once.");
765
+ throw connectorError(
766
+ "validationFailed" /* ValidationFailed */,
767
+ "Builder instances can be executed only once."
768
+ );
736
769
  }
737
770
  this.executed = true;
771
+ this.validateActor?.();
738
772
  }
739
773
  resolveMessageName() {
740
774
  if (this.name === void 0) {
741
- throw connectorError("validationFailed" /* ValidationFailed */, "Message name is required when the encoded stream payload has no message type.");
775
+ throw connectorError(
776
+ "validationFailed" /* ValidationFailed */,
777
+ "Message name is required when the encoded stream payload has no message type."
778
+ );
742
779
  }
743
780
  return this.name;
744
781
  }
745
782
  };
746
783
  var ZlinkStreamSendBuilder = class {
747
- constructor(connector, name, payload) {
784
+ constructor(connector, name, payload, actorSlot, validateActor) {
748
785
  this.connector = connector;
749
786
  this.payload = payload;
750
- this.state = new ZlinkStreamCallBuilderState(name);
787
+ this.state = new ZlinkStreamCallBuilderState(name, actorSlot, validateActor);
751
788
  }
752
789
  state;
753
790
  packetName(name) {
@@ -763,10 +800,6 @@ var ZlinkStreamSendBuilder = class {
763
800
  this.state.compress = true;
764
801
  return this;
765
802
  }
766
- flowFrom(flow) {
767
- this.state.flow = flow;
768
- return this;
769
- }
770
803
  async submit(signal) {
771
804
  throwIfAborted(signal);
772
805
  this.state.ensureNotExecuted();
@@ -778,15 +811,16 @@ var ZlinkStreamSendBuilder = class {
778
811
  this.state.compress,
779
812
  void 0,
780
813
  signal,
781
- this.state.flow
814
+ void 0,
815
+ this.state.actorSlot
782
816
  );
783
817
  }
784
818
  };
785
819
  var ZlinkStreamRequestBuilder = class {
786
- constructor(connector, name, payload) {
820
+ constructor(connector, name, payload, actorSlot, validateActor) {
787
821
  this.connector = connector;
788
822
  this.payload = payload;
789
- this.state = new ZlinkStreamCallBuilderState(name);
823
+ this.state = new ZlinkStreamCallBuilderState(name, actorSlot, validateActor);
790
824
  }
791
825
  state;
792
826
  packetName(name) {
@@ -806,10 +840,6 @@ var ZlinkStreamRequestBuilder = class {
806
840
  this.state.compress = true;
807
841
  return this;
808
842
  }
809
- flowFrom(flow) {
810
- this.state.flow = flow;
811
- return this;
812
- }
813
843
  submit(signalOrCallback) {
814
844
  this.state.ensureNotExecuted();
815
845
  const operation = this.connector.requestEncoded(
@@ -819,7 +849,7 @@ var ZlinkStreamRequestBuilder = class {
819
849
  this.state.compress,
820
850
  this.state.timeoutMs ?? this.connector.options.requestTimeoutMs,
821
851
  typeof signalOrCallback === "function" ? void 0 : signalOrCallback,
822
- this.state.flow
852
+ this.state.actorSlot
823
853
  );
824
854
  if (typeof signalOrCallback === "function") {
825
855
  operation.then(
@@ -828,7 +858,9 @@ var ZlinkStreamRequestBuilder = class {
828
858
  );
829
859
  return;
830
860
  }
831
- return operation.then((value) => (this.connector.options.codec ?? zlinkStreamJsonCodec).decode(value));
861
+ return operation.then(
862
+ (value) => (this.connector.options.codec ?? zlinkStreamJsonCodec).decode(value)
863
+ );
832
864
  }
833
865
  submitEncoded(signal) {
834
866
  this.state.ensureNotExecuted();
@@ -839,7 +871,7 @@ var ZlinkStreamRequestBuilder = class {
839
871
  this.state.compress,
840
872
  this.state.timeoutMs ?? this.connector.options.requestTimeoutMs,
841
873
  signal,
842
- this.state.flow
874
+ this.state.actorSlot
843
875
  );
844
876
  }
845
877
  };
@@ -864,7 +896,12 @@ var ZlinkStreamWaitBuilder = class {
864
896
  async submit(signal) {
865
897
  this.markExecuted();
866
898
  const timeoutMs = this.timeoutMs ?? this.connector.options.waitTimeoutMs;
867
- const message = await this.connector.waitForMessage(this.name, timeoutMs, this.predicate, signal);
899
+ const message = await this.connector.waitForMessage(
900
+ this.name,
901
+ timeoutMs,
902
+ this.predicate,
903
+ signal
904
+ );
868
905
  if (message === void 0) {
869
906
  throw connectorError(
870
907
  "validationFailed" /* ValidationFailed */,
@@ -875,7 +912,10 @@ var ZlinkStreamWaitBuilder = class {
875
912
  }
876
913
  ensureConfigurable() {
877
914
  if (this.executed) {
878
- throw connectorError("validationFailed" /* ValidationFailed */, "Builder instances can be executed only once.");
915
+ throw connectorError(
916
+ "validationFailed" /* ValidationFailed */,
917
+ "Builder instances can be executed only once."
918
+ );
879
919
  }
880
920
  }
881
921
  markExecuted() {
@@ -901,9 +941,17 @@ var ZlinkStreamExpectNoneBuilder = class {
901
941
  async run(signal) {
902
942
  this.markExecuted();
903
943
  if (this.windowMs === void 0) {
904
- throw connectorError("validationFailed" /* ValidationFailed */, "expectNone requires within(windowMs).");
944
+ throw connectorError(
945
+ "validationFailed" /* ValidationFailed */,
946
+ "expectNone requires within(windowMs)."
947
+ );
905
948
  }
906
- const message = await this.connector.waitForMessage(this.name, this.windowMs, () => true, signal);
949
+ const message = await this.connector.waitForMessage(
950
+ this.name,
951
+ this.windowMs,
952
+ () => true,
953
+ signal
954
+ );
907
955
  if (message === void 0) {
908
956
  return;
909
957
  }
@@ -914,7 +962,10 @@ var ZlinkStreamExpectNoneBuilder = class {
914
962
  }
915
963
  ensureConfigurable() {
916
964
  if (this.executed) {
917
- throw connectorError("validationFailed" /* ValidationFailed */, "Builder instances can be executed only once.");
965
+ throw connectorError(
966
+ "validationFailed" /* ValidationFailed */,
967
+ "Builder instances can be executed only once."
968
+ );
918
969
  }
919
970
  }
920
971
  markExecuted() {
@@ -947,7 +998,10 @@ var ZlinkStreamSequenceBuilder = class {
947
998
  async run(signal) {
948
999
  this.markExecuted();
949
1000
  if (this.predicates.length === 0) {
950
- throw connectorError("validationFailed" /* ValidationFailed */, "waitForSequence requires at least one expectation.");
1001
+ throw connectorError(
1002
+ "validationFailed" /* ValidationFailed */,
1003
+ "waitForSequence requires at least one expectation."
1004
+ );
951
1005
  }
952
1006
  const timeoutMs = this.timeoutMs ?? this.connector.options.waitTimeoutMs;
953
1007
  const deadline = Date.now() + timeoutMs;
@@ -979,7 +1033,10 @@ var ZlinkStreamSequenceBuilder = class {
979
1033
  }
980
1034
  ensureConfigurable() {
981
1035
  if (this.executed) {
982
- throw connectorError("validationFailed" /* ValidationFailed */, "Builder instances can be executed only once.");
1036
+ throw connectorError(
1037
+ "validationFailed" /* ValidationFailed */,
1038
+ "Builder instances can be executed only once."
1039
+ );
983
1040
  }
984
1041
  }
985
1042
  markExecuted() {
@@ -989,7 +1046,10 @@ var ZlinkStreamSequenceBuilder = class {
989
1046
  };
990
1047
  function validateTimeout(timeoutMs) {
991
1048
  if (!Number.isFinite(timeoutMs) || timeoutMs < 0) {
992
- throw connectorError("validationFailed" /* ValidationFailed */, "Timeout must be a non-negative finite number.");
1049
+ throw connectorError(
1050
+ "validationFailed" /* ValidationFailed */,
1051
+ "Timeout must be a non-negative finite number."
1052
+ );
993
1053
  }
994
1054
  }
995
1055
 
@@ -1005,7 +1065,10 @@ var zlinkStreamLz4CompressionCodec = {
1005
1065
  function compressPayload(payload, compression, compressionCodec) {
1006
1066
  const codec = resolveCompressionCodec(compression, compressionCodec);
1007
1067
  if (codec === void 0) {
1008
- throw connectorError("compressionFailed" /* CompressionFailed */, "Compression codec is not configured.");
1068
+ throw connectorError(
1069
+ "compressionFailed" /* CompressionFailed */,
1070
+ "Compression codec is not configured."
1071
+ );
1009
1072
  }
1010
1073
  return codec.compress(payload);
1011
1074
  }
@@ -1015,7 +1078,10 @@ function decompressIfNeeded(header, payload, compression, compressionCodec, maxD
1015
1078
  }
1016
1079
  const codec = resolveCompressionCodec(compression, compressionCodec);
1017
1080
  if (codec === void 0) {
1018
- throw connectorError("decompressionFailed" /* DecompressionFailed */, "Compression codec is not configured.");
1081
+ throw connectorError(
1082
+ "decompressionFailed" /* DecompressionFailed */,
1083
+ "Compression codec is not configured."
1084
+ );
1019
1085
  }
1020
1086
  try {
1021
1087
  const decompressed = codec.decompress(payload, maxDecompressedSize);
@@ -1048,26 +1114,39 @@ var ZlinkStreamFrameCodec = class {
1048
1114
  try {
1049
1115
  return decodeStreamWireFrame(frame);
1050
1116
  } catch (cause) {
1051
- throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Frame length does not match prefix.", cause);
1117
+ throw connectorError(
1118
+ "frameDecodeFailed" /* FrameDecodeFailed */,
1119
+ "Frame length does not match prefix.",
1120
+ cause
1121
+ );
1052
1122
  }
1053
1123
  }
1054
1124
  };
1055
1125
  function splitZlinkStreamFrames(chunk) {
1056
1126
  if (chunk.length === 0) {
1057
- throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Stream frame prefix is incomplete.");
1127
+ throw connectorError(
1128
+ "frameDecodeFailed" /* FrameDecodeFailed */,
1129
+ "Stream frame prefix is incomplete."
1130
+ );
1058
1131
  }
1059
1132
  const frames = [];
1060
1133
  let offset = 0;
1061
1134
  while (offset < chunk.length) {
1062
1135
  const remaining = chunk.length - offset;
1063
1136
  if (remaining < 6) {
1064
- throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Stream frame prefix is incomplete.");
1137
+ throw connectorError(
1138
+ "frameDecodeFailed" /* FrameDecodeFailed */,
1139
+ "Stream frame prefix is incomplete."
1140
+ );
1065
1141
  }
1066
1142
  const headerLength = chunk[offset] << 8 | chunk[offset + 1];
1067
1143
  const payloadLength = chunk[offset + 2] * 16777216 + (chunk[offset + 3] << 16) + (chunk[offset + 4] << 8) + chunk[offset + 5];
1068
1144
  const frameLength = 6 + headerLength + payloadLength;
1069
1145
  if (frameLength > remaining) {
1070
- throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Frame length does not match prefix.");
1146
+ throw connectorError(
1147
+ "frameDecodeFailed" /* FrameDecodeFailed */,
1148
+ "Frame length does not match prefix."
1149
+ );
1071
1150
  }
1072
1151
  frames.push(chunk.subarray(offset, offset + frameLength));
1073
1152
  offset += frameLength;
@@ -1076,7 +1155,10 @@ function splitZlinkStreamFrames(chunk) {
1076
1155
  }
1077
1156
  function validatePayload(payloadLength, maxPayloadSize) {
1078
1157
  if (payloadLength > maxPayloadSize) {
1079
- throw connectorError("validationFailed" /* ValidationFailed */, "Payload exceeds MaxSendPayloadSize.");
1158
+ throw connectorError(
1159
+ "validationFailed" /* ValidationFailed */,
1160
+ "Payload exceeds MaxSendPayloadSize."
1161
+ );
1080
1162
  }
1081
1163
  }
1082
1164
 
@@ -1094,14 +1176,22 @@ var ZlinkStreamMetadataCodec = class {
1094
1176
  }
1095
1177
  return size;
1096
1178
  } catch (cause) {
1097
- throw connectorError("validationFailed" /* ValidationFailed */, streamWireErrorMessage(cause), cause);
1179
+ throw connectorError(
1180
+ "validationFailed" /* ValidationFailed */,
1181
+ streamWireErrorMessage(cause),
1182
+ cause
1183
+ );
1098
1184
  }
1099
1185
  }
1100
1186
  static write(metadata, destination) {
1101
1187
  try {
1102
1188
  destination.set(encodeStreamWireMetadata(metadata.values));
1103
1189
  } catch (cause) {
1104
- throw connectorError("validationFailed" /* ValidationFailed */, streamWireErrorMessage(cause), cause);
1190
+ throw connectorError(
1191
+ "validationFailed" /* ValidationFailed */,
1192
+ streamWireErrorMessage(cause),
1193
+ cause
1194
+ );
1105
1195
  }
1106
1196
  }
1107
1197
  static decode(metadata) {
@@ -1109,7 +1199,11 @@ var ZlinkStreamMetadataCodec = class {
1109
1199
  const values = decodeStreamWireMetadata(metadata);
1110
1200
  return values.size === 0 ? ZlinkStreamMetadataMap.empty : ZlinkStreamMetadataMap.from(values);
1111
1201
  } catch (cause) {
1112
- throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, streamWireErrorMessage(cause), cause);
1202
+ throw connectorError(
1203
+ "frameDecodeFailed" /* FrameDecodeFailed */,
1204
+ streamWireErrorMessage(cause),
1205
+ cause
1206
+ );
1113
1207
  }
1114
1208
  }
1115
1209
  };
@@ -1133,22 +1227,20 @@ var ZlinkStreamHeaderCodec = class {
1133
1227
  name: header.name,
1134
1228
  metadata: header.metadata.values,
1135
1229
  correlationId: header.correlationId,
1136
- flowId: header.flowId,
1137
- flowOrigin: encodeFlowOrigin(header.flowOrigin)
1230
+ actorSlot: header.actorSlot
1138
1231
  });
1139
1232
  } catch (cause) {
1140
- throw connectorError("validationFailed" /* ValidationFailed */, streamWireErrorMessage2(cause), cause);
1233
+ throw connectorError(
1234
+ "validationFailed" /* ValidationFailed */,
1235
+ streamWireErrorMessage2(cause),
1236
+ cause
1237
+ );
1141
1238
  }
1142
1239
  }
1143
- /**
1144
- * `includeFlow=false` (diagnostics Off, spec 27 §4) skips reading and
1145
- * validating the inbound flow fields while the structural length checks in
1146
- * the wire decoder are preserved.
1147
- */
1148
- static decode(header, includeFlow = true) {
1240
+ static decode(header) {
1149
1241
  let decoded;
1150
1242
  try {
1151
- const wire = decodeStreamWireHeader(header, void 0, includeFlow);
1243
+ const wire = decodeStreamWireHeader(header, void 0, false);
1152
1244
  const metadata = wire.metadata.size === 0 ? ZlinkStreamMetadataMap.empty : ZlinkStreamMetadataMap.from(wire.metadata);
1153
1245
  decoded = {
1154
1246
  kind: wire.kind,
@@ -1158,11 +1250,14 @@ var ZlinkStreamHeaderCodec = class {
1158
1250
  name: wire.name,
1159
1251
  metadata,
1160
1252
  correlationId: wire.correlationId,
1161
- flowId: wire.flowId,
1162
- flowOrigin: decodeFlowOrigin(wire.flowOrigin)
1253
+ actorSlot: wire.actorSlot
1163
1254
  };
1164
1255
  } catch (cause) {
1165
- throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, streamWireErrorMessage2(cause), cause);
1256
+ throw connectorError(
1257
+ "frameDecodeFailed" /* FrameDecodeFailed */,
1258
+ streamWireErrorMessage2(cause),
1259
+ cause
1260
+ );
1166
1261
  }
1167
1262
  validateEnum(decoded.kind, decoded.codec, decoded.flags);
1168
1263
  if (!isReplyKind2(decoded.kind)) {
@@ -1178,7 +1273,7 @@ function isReplyKind2(kind) {
1178
1273
  function streamWireErrorMessage2(cause) {
1179
1274
  return cause instanceof Error ? cause.message : "Stream header is invalid.";
1180
1275
  }
1181
- function buildHeader(kind, name, codec, metadata, compress, requestSeq, correlationId, flowId, flowOrigin) {
1276
+ function buildHeader(kind, name, codec, metadata, compress, requestSeq, correlationId, actorSlot) {
1182
1277
  let flags = 0 /* None */;
1183
1278
  if (requestSeq !== void 0) {
1184
1279
  flags |= 1 /* HasRequestSeq */;
@@ -1192,27 +1287,49 @@ function buildHeader(kind, name, codec, metadata, compress, requestSeq, correlat
1192
1287
  if (correlationId !== void 0 && correlationId.length > 0) {
1193
1288
  flags |= 8 /* HasCorrelationId */;
1194
1289
  }
1195
- if (flowId !== void 0) flags |= 16 /* HasFlowId */;
1196
- 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
+ };
1197
1301
  }
1198
1302
  function validateHeaderSemantics(header) {
1199
1303
  validateEnum(header.kind, header.codec, header.flags);
1200
1304
  const hasRequestSeq = header.requestSeq !== void 0 || (header.flags & 1 /* HasRequestSeq */) !== 0;
1201
1305
  const hasMetadata = header.metadata.count > 0 || (header.flags & 2 /* HasMetadata */) !== 0;
1202
1306
  if (header.kind === 1 /* Send */ && hasRequestSeq) {
1203
- throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Send packet must not contain a request sequence.");
1307
+ throw connectorError(
1308
+ "frameDecodeFailed" /* FrameDecodeFailed */,
1309
+ "Send packet must not contain a request sequence."
1310
+ );
1204
1311
  }
1205
1312
  if ((header.kind === 2 /* Request */ || header.kind === 3 /* Response */) && !hasRequestSeq) {
1206
- throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Request and response packets must contain a request sequence.");
1313
+ throw connectorError(
1314
+ "frameDecodeFailed" /* FrameDecodeFailed */,
1315
+ "Request and response packets must contain a request sequence."
1316
+ );
1207
1317
  }
1208
1318
  if (header.kind === 4 /* Error */ && header.codec !== 1 /* Json */) {
1209
- throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Error packet must use the JSON codec.");
1319
+ throw connectorError(
1320
+ "frameDecodeFailed" /* FrameDecodeFailed */,
1321
+ "Error packet must use the JSON codec."
1322
+ );
1210
1323
  }
1211
1324
  if (header.kind === 5 /* Control */) {
1212
1325
  const hasCorrelation = header.correlationId !== void 0 && header.correlationId.length > 0 || (header.flags & 8 /* HasCorrelationId */) !== 0;
1213
- const hasFlow = header.flowId !== void 0 || header.flowOrigin !== void 0 || (header.flags & 16 /* HasFlowId */) !== 0;
1214
- if (header.flags !== 0 /* None */ || hasRequestSeq || hasMetadata || hasCorrelation || hasFlow || header.codec !== 0 /* Raw */) {
1215
- throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Control packet must use raw codec and must not contain flags.");
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 */) {
1329
+ throw connectorError(
1330
+ "frameDecodeFailed" /* FrameDecodeFailed */,
1331
+ "Control packet must use raw codec and must not contain flags."
1332
+ );
1216
1333
  }
1217
1334
  }
1218
1335
  }
@@ -1223,17 +1340,11 @@ function validateEnum(kind, codec, flags) {
1223
1340
  if (![0, 1, 2, 3].includes(codec)) {
1224
1341
  throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Unknown stream codec.");
1225
1342
  }
1226
- 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 */;
1227
1344
  if ((flags & ~known) !== 0) {
1228
1345
  throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Unknown stream header flag.");
1229
1346
  }
1230
1347
  }
1231
- function encodeFlowOrigin(origin) {
1232
- return origin === void 0 ? void 0 : { Inbound: 1, Timer: 2, Application: 3, Lifecycle: 4 }[origin];
1233
- }
1234
- function decodeFlowOrigin(origin) {
1235
- return origin === void 0 ? void 0 : { 1: "Inbound", 2: "Timer", 3: "Application", 4: "Lifecycle" }[origin];
1236
- }
1237
1348
 
1238
1349
  // packages/stream-connector/src/Runtime/Protocol/ZlinkStreamFrameProtocol.ts
1239
1350
  var ZLINK_STREAM_HEARTBEAT_PING = "$zlink.heartbeat.ping";
@@ -1242,37 +1353,47 @@ var ZlinkStreamFrameProtocol = class {
1242
1353
  constructor(options) {
1243
1354
  this.options = options;
1244
1355
  }
1245
- encode(kind, name, payload, metadata, compress, requestSeq, correlationId, flowId, flowOrigin) {
1356
+ encode(kind, name, payload, metadata, compress, requestSeq, correlationId, actorSlot) {
1246
1357
  const payloadBytes = compress ? compressPayload(payload.payload, this.options.compression, this.options.compressionCodec) : payload.payload;
1247
- const header = buildHeader(kind, name, payload.codec, metadata, compress, requestSeq, correlationId, flowId, flowOrigin);
1358
+ const header = buildHeader(
1359
+ kind,
1360
+ name,
1361
+ payload.codec,
1362
+ metadata,
1363
+ compress,
1364
+ requestSeq,
1365
+ correlationId,
1366
+ actorSlot
1367
+ );
1248
1368
  return this.encodeFrame(header, payloadBytes);
1249
1369
  }
1250
1370
  encodeControl(name, payload = new Uint8Array()) {
1251
- return this.encodeFrame({
1252
- kind: 5 /* Control */,
1253
- codec: 0 /* Raw */,
1254
- flags: 0 /* None */,
1255
- name,
1256
- metadata: ZlinkStreamMetadataMap.empty
1257
- }, payload);
1371
+ return this.encodeFrame(
1372
+ {
1373
+ kind: 5 /* Control */,
1374
+ codec: 0 /* Raw */,
1375
+ flags: 0 /* None */,
1376
+ name,
1377
+ metadata: ZlinkStreamMetadataMap.empty
1378
+ },
1379
+ payload
1380
+ );
1258
1381
  }
1259
- decode(frameBytes, flowEnabled = this.flowEnabled()) {
1382
+ decode(frameBytes) {
1260
1383
  const frame = ZlinkStreamFrameCodec.decode(frameBytes);
1261
1384
  return {
1262
- // Spec 27 §4: with diagnostics Off the inbound flow fields are neither
1263
- // read nor validated (structural length checks are preserved).
1264
- header: ZlinkStreamHeaderCodec.decode(frame.header, flowEnabled),
1385
+ header: ZlinkStreamHeaderCodec.decode(frame.header),
1265
1386
  payload: frame.payload
1266
1387
  };
1267
1388
  }
1268
- flowEnabled() {
1269
- return this.options.diagnosticsLevel !== "off" /* Off */;
1270
- }
1271
- decodeFrames(chunk, flowEnabled = this.flowEnabled()) {
1389
+ decodeFrames(chunk) {
1272
1390
  return splitZlinkStreamFrames(chunk).map((frame) => {
1273
- const decoded = this.decode(frame, flowEnabled);
1391
+ const decoded = this.decode(frame);
1274
1392
  if (decoded.payload.length > this.options.maxReceivePayloadSize) {
1275
- throw connectorError("frameTooLarge" /* FrameTooLarge */, "Payload exceeds MaxReceivePayloadSize.");
1393
+ throw connectorError(
1394
+ "frameTooLarge" /* FrameTooLarge */,
1395
+ "Payload exceeds MaxReceivePayloadSize."
1396
+ );
1276
1397
  }
1277
1398
  return decoded;
1278
1399
  });
@@ -1319,12 +1440,6 @@ function parseEndpoint(endpoint) {
1319
1440
  }
1320
1441
 
1321
1442
  // packages/stream-connector/src/Runtime/ZlinkStreamConnectorOptions.ts
1322
- var validDiagnosticsLevels = /* @__PURE__ */ new Set([
1323
- "off" /* Off */,
1324
- "errors" /* Errors */,
1325
- "normal" /* Normal */,
1326
- "detailed" /* Detailed */
1327
- ]);
1328
1443
  function normalizeOptions(options, defaultTransportFactory) {
1329
1444
  const endpoint = options.endpoint;
1330
1445
  if (endpoint.trim().length === 0) {
@@ -1332,7 +1447,10 @@ function normalizeOptions(options, defaultTransportFactory) {
1332
1447
  }
1333
1448
  const inferredTransport = inferTransport(endpoint);
1334
1449
  if (options.transport !== void 0 && options.transport !== inferredTransport) {
1335
- throw connectorError("configurationError" /* ConfigurationError */, "Configured transport conflicts with endpoint scheme.");
1450
+ throw connectorError(
1451
+ "configurationError" /* ConfigurationError */,
1452
+ "Configured transport conflicts with endpoint scheme."
1453
+ );
1336
1454
  }
1337
1455
  validatePositive(options.connectTimeoutMs ?? 5e3, "ConnectTimeout");
1338
1456
  validatePositive(options.requestTimeoutMs ?? 3e4, "RequestTimeout");
@@ -1341,7 +1459,6 @@ function normalizeOptions(options, defaultTransportFactory) {
1341
1459
  validatePositive(options.maxReceivePayloadSize ?? 64 * 1024, "MaxReceivePayloadSize");
1342
1460
  validateHeartbeat(options.heartbeat);
1343
1461
  validateReconnect(options.reconnect);
1344
- validateDiagnosticsLevel(options.diagnosticsLevel);
1345
1462
  return {
1346
1463
  endpoint,
1347
1464
  transport: inferredTransport,
@@ -1367,10 +1484,7 @@ function normalizeOptions(options, defaultTransportFactory) {
1367
1484
  compressionCodec: resolveCompressionCodec2(options),
1368
1485
  nameResolver: options.nameResolver ?? defaultPacketNameResolver,
1369
1486
  transportFactory: options.transportFactory ?? defaultTransportFactory,
1370
- codec: options.codec,
1371
- // Spec 26 §4: the default diagnostics level is Errors, which preserves
1372
- // the connector's established wire behavior.
1373
- diagnosticsLevel: options.diagnosticsLevel ?? "errors" /* Errors */
1487
+ codec: options.codec
1374
1488
  };
1375
1489
  }
1376
1490
  var defaultPacketNameResolver = {
@@ -1386,17 +1500,15 @@ function resolveCompressionCodec2(options) {
1386
1500
  const compression = options.compression ?? "lz4" /* Lz4 */;
1387
1501
  if (compression === "none" /* None */) {
1388
1502
  if (options.compressionCodec !== void 0) {
1389
- throw connectorError("configurationError" /* ConfigurationError */, "compressionCodec cannot be set when compression is none.");
1503
+ throw connectorError(
1504
+ "configurationError" /* ConfigurationError */,
1505
+ "compressionCodec cannot be set when compression is none."
1506
+ );
1390
1507
  }
1391
1508
  return void 0;
1392
1509
  }
1393
1510
  return options.compressionCodec;
1394
1511
  }
1395
- function validateDiagnosticsLevel(level) {
1396
- if (level !== void 0 && !validDiagnosticsLevels.has(level)) {
1397
- throw connectorError("configurationError" /* ConfigurationError */, "DiagnosticsLevel is invalid.");
1398
- }
1399
- }
1400
1512
  function validatePositive(value, name) {
1401
1513
  if (value <= 0) {
1402
1514
  throw connectorError("validationFailed" /* ValidationFailed */, `${name} must be positive.`);
@@ -1412,7 +1524,10 @@ function validateHeartbeat(options) {
1412
1524
  validatePositive(intervalMs, "Heartbeat interval");
1413
1525
  validatePositive(timeoutMs, "Heartbeat timeout");
1414
1526
  if (timeoutMs <= intervalMs) {
1415
- throw connectorError("validationFailed" /* ValidationFailed */, "Heartbeat timeout must be greater than the heartbeat interval.");
1527
+ throw connectorError(
1528
+ "validationFailed" /* ValidationFailed */,
1529
+ "Heartbeat timeout must be greater than the heartbeat interval."
1530
+ );
1416
1531
  }
1417
1532
  }
1418
1533
  function validateReconnect(options) {
@@ -1423,33 +1538,20 @@ function validateReconnect(options) {
1423
1538
  validatePositive(options?.initialDelayMs ?? 250, "Reconnect InitialDelay");
1424
1539
  validatePositive(options?.maxDelayMs ?? 5e3, "Reconnect MaxDelay");
1425
1540
  if ((options?.backoffFactor ?? 2) < 1) {
1426
- throw connectorError("validationFailed" /* ValidationFailed */, "Reconnect BackoffFactor must be at least 1.0.");
1541
+ throw connectorError(
1542
+ "validationFailed" /* ValidationFailed */,
1543
+ "Reconnect BackoffFactor must be at least 1.0."
1544
+ );
1427
1545
  }
1428
1546
  const maxAttempts = options?.maxAttempts === void 0 ? 3 : options.maxAttempts;
1429
1547
  if (maxAttempts !== null && !(Number.isFinite(maxAttempts) && maxAttempts > 0)) {
1430
- throw connectorError("validationFailed" /* ValidationFailed */, "Reconnect MaxAttempts must be null or positive.");
1548
+ throw connectorError(
1549
+ "validationFailed" /* ValidationFailed */,
1550
+ "Reconnect MaxAttempts must be null or positive."
1551
+ );
1431
1552
  }
1432
1553
  }
1433
1554
 
1434
- // packages/stream-connector/src/Runtime/ZlinkStreamDiagnosticsLevelCell.ts
1435
- var ZlinkStreamDiagnosticsLevelCell = class {
1436
- current;
1437
- constructor(initial) {
1438
- this.current = initial;
1439
- }
1440
- get level() {
1441
- return this.current;
1442
- }
1443
- set(level) {
1444
- const candidate = level;
1445
- if (candidate === void 0 || candidate === null) {
1446
- throw connectorError("configurationError" /* ConfigurationError */, "DiagnosticsLevel is invalid.");
1447
- }
1448
- validateDiagnosticsLevel(level);
1449
- this.current = level;
1450
- }
1451
- };
1452
-
1453
1555
  // packages/stream-connector/src/Runtime/ZlinkStreamPendingRequests.ts
1454
1556
  var ZlinkStreamPendingRequests = class {
1455
1557
  nextRequestSeq = 1n;
@@ -1462,14 +1564,21 @@ var ZlinkStreamPendingRequests = class {
1462
1564
  let timeout;
1463
1565
  let resolvePending;
1464
1566
  let rejectPending;
1465
- const promise = new Promise((resolve, reject) => {
1466
- timeout = setTimeout(() => {
1467
- this.active.delete(requestSeq);
1468
- reject(connectorError("requestTimeout" /* RequestTimeout */, `Request '${packetName}' timed out.`));
1469
- }, timeoutMs);
1470
- resolvePending = resolve;
1471
- rejectPending = (error) => reject(connectorError(error.code, error.message, error.cause));
1472
- });
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
+ );
1473
1582
  this.active.set(requestSeq, {
1474
1583
  packetName,
1475
1584
  promise,
@@ -1493,15 +1602,14 @@ var ZlinkStreamPendingRequests = class {
1493
1602
  });
1494
1603
  return { requestSeq, promise };
1495
1604
  }
1496
- /* stream connector spec §5.2: a pending request is matched by request_seq alone. Diagnostics
1497
- * use the original request name retained by this registry, never a legacy reply name. */
1498
- resolve(requestSeq, value) {
1605
+ /* stream connector spec §5.2: a pending request is matched by request_seq alone. */
1606
+ resolve(requestSeq, value, metadata) {
1499
1607
  const pending = this.active.get(requestSeq);
1500
1608
  if (pending === void 0) {
1501
1609
  return false;
1502
1610
  }
1503
1611
  this.active.delete(requestSeq);
1504
- pending.resolve(value);
1612
+ pending.resolve({ name: pending.packetName, metadata, payload: value });
1505
1613
  return true;
1506
1614
  }
1507
1615
  reject(requestSeq, error) {
@@ -1637,9 +1745,11 @@ var ZlinkStreamReceivedMessages = class {
1637
1745
  */
1638
1746
  resetForNewConnection() {
1639
1747
  this.receivedCounts.clear();
1748
+ const submittedCallbacks = this.queue.slice(this.queueHead).filter((item) => item?.kind === "callback");
1640
1749
  this.queue.length = 0;
1750
+ this.queue.push(...submittedCallbacks);
1641
1751
  this.queueHead = 0;
1642
- this.queuedCount = 0;
1752
+ this.queuedCount = submittedCallbacks.length;
1643
1753
  }
1644
1754
  /**
1645
1755
  * Releases every registered wait surface because the connection it was
@@ -1668,7 +1778,14 @@ var ZlinkStreamReceivedMessages = class {
1668
1778
  return;
1669
1779
  }
1670
1780
  }
1671
- 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 });
1672
1789
  this.queuedCount += 1;
1673
1790
  if (this.deliverOnArrival) {
1674
1791
  this.scheduleDrain();
@@ -1695,7 +1812,7 @@ var ZlinkStreamReceivedMessages = class {
1695
1812
  offerQueued(name, registration) {
1696
1813
  for (let index = this.queueHead; index < this.queue.length; index += 1) {
1697
1814
  const queued = this.queue[index];
1698
- if (queued === void 0 || queued.message.name !== name) {
1815
+ if (queued === void 0 || queued.kind !== "message" || queued.message.name !== name) {
1699
1816
  continue;
1700
1817
  }
1701
1818
  if (!registration.consume(queued.message)) {
@@ -1723,17 +1840,24 @@ var ZlinkStreamReceivedMessages = class {
1723
1840
  const queued = this.queue[index];
1724
1841
  if (queued === void 0) continue;
1725
1842
  this.removeAt(index);
1843
+ if (queued.kind === "callback") {
1844
+ await queued.callback();
1845
+ continue;
1846
+ }
1726
1847
  const { message, signal } = queued;
1727
1848
  const handlers = [...this.handlers.get(message.name)];
1728
1849
  for (const handler of handlers) {
1729
1850
  try {
1730
1851
  await handler(message, signal);
1731
1852
  } catch (cause) {
1732
- await this.events.publishError({
1733
- code: "userCallbackFailed" /* UserCallbackFailed */,
1734
- message: "Typed message handler failed.",
1735
- cause
1736
- }, signal);
1853
+ await this.events.publishError(
1854
+ {
1855
+ code: "userCallbackFailed" /* UserCallbackFailed */,
1856
+ message: "Typed message handler failed.",
1857
+ cause
1858
+ },
1859
+ signal
1860
+ );
1737
1861
  }
1738
1862
  }
1739
1863
  }
@@ -1750,7 +1874,7 @@ var ZlinkStreamReceivedMessages = class {
1750
1874
  findDeliverableIndex() {
1751
1875
  for (let index = this.queueHead; index < this.queue.length; index += 1) {
1752
1876
  const queued = this.queue[index];
1753
- 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)) {
1754
1878
  return index;
1755
1879
  }
1756
1880
  }
@@ -1758,7 +1882,8 @@ var ZlinkStreamReceivedMessages = class {
1758
1882
  }
1759
1883
  hasQueuedMessage(name) {
1760
1884
  for (let index = this.queueHead; index < this.queue.length; index += 1) {
1761
- 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;
1762
1887
  }
1763
1888
  return false;
1764
1889
  }
@@ -1782,17 +1907,24 @@ var ZlinkStreamReceivedMessages = class {
1782
1907
 
1783
1908
  // packages/stream-connector/src/Runtime/ZlinkStreamFrameSender.ts
1784
1909
  var ZlinkStreamFrameSender = class {
1785
- constructor(protocol, flowContext) {
1910
+ constructor(protocol) {
1786
1911
  this.protocol = protocol;
1787
- this.flowContext = flowContext;
1788
1912
  }
1789
1913
  pendingWrites = /* @__PURE__ */ new Set();
1790
- 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) {
1791
1915
  throwIfAborted(signal);
1792
- const flow = this.protocol.flowEnabled() ? this.flowContext.currentOrCreate(explicitFlow) : void 0;
1793
1916
  await this.write(
1794
1917
  connection,
1795
- this.protocol.encode(kind, name, payload, metadata, compress, requestSeq, correlationId, flow?.flowId, flow?.flowOrigin),
1918
+ this.protocol.encode(
1919
+ kind,
1920
+ name,
1921
+ payload,
1922
+ metadata,
1923
+ compress,
1924
+ requestSeq,
1925
+ correlationId,
1926
+ actorSlot
1927
+ ),
1796
1928
  signal
1797
1929
  );
1798
1930
  }
@@ -1827,24 +1959,196 @@ var reasons = {
1827
1959
  6: "TransportError"
1828
1960
  };
1829
1961
  function decodeSessionClosing(payload) {
1830
- if (payload.length < 4 || payload[0] !== 1) throw new Error("Unsupported session-closing version.");
1962
+ if (payload.length < 4 || payload[0] !== 1)
1963
+ throw new Error("Unsupported session-closing version.");
1831
1964
  const closeReason = reasons[payload[1]];
1832
1965
  if (closeReason === void 0) throw new Error("Unknown session-closing reason.");
1833
1966
  const length = payload[2] << 8 | payload[3];
1834
- if (length > 512 || payload.length !== 4 + length) throw new Error("Invalid session-closing diagnostic length.");
1967
+ if (length > 512 || payload.length !== 4 + length)
1968
+ throw new Error("Invalid session-closing diagnostic length.");
1835
1969
  const diagnostic = length === 0 ? void 0 : new TextDecoder("utf-8", { fatal: true }).decode(payload.subarray(4));
1836
1970
  return { closeReason, diagnostic };
1837
1971
  }
1838
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
+
1839
2143
  // packages/stream-connector/src/Runtime/ZlinkStreamReceiveDispatcher.ts
1840
2144
  var ZlinkStreamReceiveDispatcher = class {
1841
- constructor(protocol, pendingRequests, receivedMessages, frameSender, events, flowContext, serverClosing) {
2145
+ constructor(protocol, pendingRequests, receivedMessages, frameSender, events, actors, serverClosing) {
1842
2146
  this.protocol = protocol;
1843
2147
  this.pendingRequests = pendingRequests;
1844
2148
  this.receivedMessages = receivedMessages;
1845
2149
  this.frameSender = frameSender;
1846
2150
  this.events = events;
1847
- this.flowContext = flowContext;
2151
+ this.actors = actors;
1848
2152
  this.serverClosing = serverClosing;
1849
2153
  }
1850
2154
  /**
@@ -1871,46 +2175,54 @@ var ZlinkStreamReceiveDispatcher = class {
1871
2175
  if (frameBytes === void 0) {
1872
2176
  return { available: false, inbound: false };
1873
2177
  }
1874
- const flowEnabled = this.protocol.flowEnabled();
1875
2178
  let frames;
1876
2179
  try {
1877
- frames = this.protocol.decodeFrames(frameBytes, flowEnabled);
2180
+ frames = this.protocol.decodeFrames(frameBytes);
1878
2181
  } catch (cause) {
1879
- await this.events.publishError(
1880
- toStreamError(cause, "frameDecodeFailed" /* FrameDecodeFailed */, "Frame decode failed."),
1881
- signal
1882
- );
1883
- return { available: true, inbound: false };
2182
+ throw cause;
1884
2183
  }
1885
2184
  for (const frame of frames) {
1886
2185
  if (isCurrent !== void 0 && !isCurrent()) {
1887
2186
  break;
1888
2187
  }
1889
2188
  try {
1890
- await this.dispatch(connection, frame.header, frame.payload, signal, flowEnabled, connectionForSend);
2189
+ await this.dispatch(connection, frame.header, frame.payload, signal, connectionForSend);
1891
2190
  } catch (cause) {
1892
2191
  if (frame.header.kind === 5 /* Control */ && frame.header.name === ZLINK_STREAM_HEARTBEAT_PING) {
1893
2192
  throw cause;
1894
2193
  }
1895
- await this.events.publishError(
1896
- toStreamError(cause, "frameDecodeFailed" /* FrameDecodeFailed */, "Frame dispatch failed."),
1897
- signal
2194
+ const error = toStreamError(
2195
+ cause,
2196
+ "frameDecodeFailed" /* FrameDecodeFailed */,
2197
+ "Frame dispatch failed."
1898
2198
  );
2199
+ if (error.code === "frameDecodeFailed" /* FrameDecodeFailed */) {
2200
+ throw cause;
2201
+ }
2202
+ await this.events.publishError(error, signal);
1899
2203
  }
1900
2204
  }
1901
2205
  return { available: true, inbound: true };
1902
2206
  }
1903
- 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);
1904
2209
  if (header.kind === 3 /* Response */ && header.requestSeq !== void 0) {
1905
2210
  try {
1906
- if (!this.pendingRequests.resolve(header.requestSeq, {
1907
- codec: header.codec,
1908
- payload: this.protocol.decodePayload(header, payload)
1909
- })) {
1910
- await this.events.publishError({
1911
- code: "frameDecodeFailed" /* FrameDecodeFailed */,
1912
- message: `Response request sequence '${header.requestSeq}' has no pending request.`
1913
- }, signal);
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
+ )) {
2219
+ await this.events.publishError(
2220
+ {
2221
+ code: "frameDecodeFailed" /* FrameDecodeFailed */,
2222
+ message: `Response request sequence '${header.requestSeq}' has no pending request.`
2223
+ },
2224
+ signal
2225
+ );
1914
2226
  }
1915
2227
  } catch (cause) {
1916
2228
  const decodeError = toStreamError(
@@ -1918,10 +2230,7 @@ var ZlinkStreamReceiveDispatcher = class {
1918
2230
  "decompressionFailed" /* DecompressionFailed */,
1919
2231
  "Decompression failed."
1920
2232
  );
1921
- if (!this.pendingRequests.reject(
1922
- header.requestSeq,
1923
- decodeError
1924
- )) {
2233
+ if (!this.pendingRequests.reject(header.requestSeq, decodeError)) {
1925
2234
  await this.events.publishError(decodeError, signal);
1926
2235
  }
1927
2236
  }
@@ -1939,10 +2248,7 @@ var ZlinkStreamReceiveDispatcher = class {
1939
2248
  "frameDecodeFailed" /* FrameDecodeFailed */,
1940
2249
  "Remote error payload is invalid."
1941
2250
  );
1942
- if (!this.pendingRequests.reject(
1943
- header.requestSeq,
1944
- decodeError
1945
- )) {
2251
+ if (!this.pendingRequests.reject(header.requestSeq, decodeError)) {
1946
2252
  await this.events.publishError(decodeError, signal);
1947
2253
  }
1948
2254
  }
@@ -1957,24 +2263,32 @@ var ZlinkStreamReceiveDispatcher = class {
1957
2263
  return;
1958
2264
  }
1959
2265
  if (header.kind === 1 /* Send */) {
1960
- const flow = flowEnabled ? this.flowContext.createInbound(header.flowId, header.flowOrigin) : void 0;
1961
- this.receivedMessages.enqueue({
1962
- name: header.name,
1963
- metadata: header.metadata,
1964
- payload: { codec: header.codec, payload: this.protocol.decodePayload(header, payload) },
1965
- flowId: flow?.flowId,
1966
- flowOrigin: flow?.flowOrigin
1967
- }, signal);
2266
+ this.receivedMessages.enqueue(
2267
+ {
2268
+ name: header.name,
2269
+ metadata: header.metadata,
2270
+ payload: { codec: header.codec, payload: this.protocol.decodePayload(header, payload) },
2271
+ actorId: actor?.actorId,
2272
+ [zlinkStreamActorBinding]: actor
2273
+ },
2274
+ signal
2275
+ );
1968
2276
  }
1969
2277
  }
1970
2278
  async dispatchControl(connection, header, payload, signal, connectionForSend) {
2279
+ if (this.actors.processControl(header.name, payload, signal)) {
2280
+ return;
2281
+ }
1971
2282
  if (header.name === ZLINK_SESSION_CLOSING) {
1972
2283
  const closing = decodeSessionClosing(payload);
1973
2284
  await this.serverClosing?.(closing.closeReason);
1974
2285
  return;
1975
2286
  }
1976
2287
  if (payload.length !== 0) {
1977
- throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Control packet payload must be empty.");
2288
+ throw connectorError(
2289
+ "frameDecodeFailed" /* FrameDecodeFailed */,
2290
+ "Control packet payload must be empty."
2291
+ );
1978
2292
  }
1979
2293
  if (header.name === ZLINK_STREAM_HEARTBEAT_PING) {
1980
2294
  try {
@@ -2002,7 +2316,11 @@ function decodeRemoteError(protocol, header, payload) {
2002
2316
  try {
2003
2317
  decoded = JSON.parse(utf8Decode2(decodedPayload));
2004
2318
  } catch (cause) {
2005
- throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "Remote error payload must be a JSON object.", cause);
2319
+ throw connectorError(
2320
+ "frameDecodeFailed" /* FrameDecodeFailed */,
2321
+ "Remote error payload must be a JSON object.",
2322
+ cause
2323
+ );
2006
2324
  }
2007
2325
  if (decoded === null || typeof decoded !== "object" || Array.isArray(decoded) || typeof decoded.code !== "string" || typeof decoded.message !== "string") {
2008
2326
  throw connectorError(
@@ -2019,12 +2337,13 @@ function randomizedDelay(baseDelayMs) {
2019
2337
  return Math.round(baseDelayMs * (0.5 + Math.random() * 0.5));
2020
2338
  }
2021
2339
  var ZlinkStreamConnectorLifecycle = class {
2022
- constructor(options, pendingRequests, frameSender, receiveDispatcher, receivedMessages, events) {
2340
+ constructor(options, pendingRequests, frameSender, receiveDispatcher, receivedMessages, actors, events) {
2023
2341
  this.options = options;
2024
2342
  this.pendingRequests = pendingRequests;
2025
2343
  this.frameSender = frameSender;
2026
2344
  this.receiveDispatcher = receiveDispatcher;
2027
2345
  this.receivedMessages = receivedMessages;
2346
+ this.actors = actors;
2028
2347
  this.events = events;
2029
2348
  }
2030
2349
  receiveLoopAbort;
@@ -2081,7 +2400,10 @@ var ZlinkStreamConnectorLifecycle = class {
2081
2400
  this.lateConnectCleanupError = error;
2082
2401
  throw error;
2083
2402
  }
2084
- throw connectorError("disconnected" /* Disconnected */, "Connector closed while connecting.");
2403
+ throw connectorError(
2404
+ "disconnected" /* Disconnected */,
2405
+ "Connector closed while connecting."
2406
+ );
2085
2407
  }
2086
2408
  this.currentConnection = connection;
2087
2409
  this.connectionGeneration += 1;
@@ -2120,8 +2442,15 @@ var ZlinkStreamConnectorLifecycle = class {
2120
2442
  }
2121
2443
  async serverClosing(reason) {
2122
2444
  this.closeReasonValue = reason;
2123
- const error = { code: "disconnected" /* Disconnected */, message: `Server closed the session: ${reason}.` };
2124
- await this.disconnectForTransportFailure(error, this.currentConnection, this.connectionGeneration);
2445
+ const error = {
2446
+ code: "disconnected" /* Disconnected */,
2447
+ message: `Server closed the session: ${reason}.`
2448
+ };
2449
+ await this.disconnectForTransportFailure(
2450
+ error,
2451
+ this.currentConnection,
2452
+ this.connectionGeneration
2453
+ );
2125
2454
  }
2126
2455
  async closeOnce(signal) {
2127
2456
  await this.connectTask?.catch(() => void 0);
@@ -2145,10 +2474,14 @@ var ZlinkStreamConnectorLifecycle = class {
2145
2474
  } catch (error) {
2146
2475
  errors.push(error);
2147
2476
  }
2148
- this.pendingRequests.failAll({ code: "disconnected" /* Disconnected */, message: "Connector closed." });
2477
+ this.pendingRequests.failAll({
2478
+ code: "disconnected" /* Disconnected */,
2479
+ message: "Connector closed."
2480
+ });
2149
2481
  this.receivedMessages.connectionEnded();
2150
- void this.setState("closed" /* Closed */, void 0, signal);
2151
- this.publishDisconnectedWithoutWaiting(signal);
2482
+ this.actors.closeAll(signal);
2483
+ this.queueState("closed" /* Closed */, void 0, signal);
2484
+ this.queueDisconnected(signal);
2152
2485
  if (errors.length === 1) throw errors[0];
2153
2486
  if (errors.length > 1) throw new AggregateError(errors, "Stream connector close failed.");
2154
2487
  }
@@ -2270,7 +2603,11 @@ var ZlinkStreamConnectorLifecycle = class {
2270
2603
  }
2271
2604
  } catch (cause) {
2272
2605
  if (signal.aborted) return;
2273
- const error = toStreamError(cause, "frameDecodeFailed" /* FrameDecodeFailed */, "Receive loop failed.");
2606
+ const error = toStreamError(
2607
+ cause,
2608
+ "frameDecodeFailed" /* FrameDecodeFailed */,
2609
+ "Receive loop failed."
2610
+ );
2274
2611
  await this.disconnectForTransportFailure(error, connection, generation);
2275
2612
  } finally {
2276
2613
  this.receiveLoopSleeping = false;
@@ -2329,7 +2666,11 @@ var ZlinkStreamConnectorLifecycle = class {
2329
2666
  if (Date.now() - this.lastInboundAt > this.options.heartbeat.timeoutMs) {
2330
2667
  this.closeReasonValue = "HeartbeatTimeout";
2331
2668
  const error = { code: "disconnected" /* Disconnected */, message: "Heartbeat timed out." };
2332
- await this.disconnectForTransportFailure(error, this.currentConnection, this.connectionGeneration);
2669
+ await this.disconnectForTransportFailure(
2670
+ error,
2671
+ this.currentConnection,
2672
+ this.connectionGeneration
2673
+ );
2333
2674
  return;
2334
2675
  }
2335
2676
  const connection = this.currentConnection;
@@ -2369,6 +2710,7 @@ var ZlinkStreamConnectorLifecycle = class {
2369
2710
  this.currentConnection = void 0;
2370
2711
  this.pendingRequests.failAll(error);
2371
2712
  this.receivedMessages.connectionEnded();
2713
+ this.actors.closeAll();
2372
2714
  try {
2373
2715
  await connection?.close();
2374
2716
  } catch {
@@ -2384,11 +2726,8 @@ var ZlinkStreamConnectorLifecycle = class {
2384
2726
  */
2385
2727
  async announceDisconnect(error) {
2386
2728
  if (this.closeRequested) return;
2387
- const announce = this.claimDisconnectedPublish();
2388
- void this.setState("disconnected" /* Disconnected */, error);
2389
- if (announce) {
2390
- void this.events.publishDisconnected().catch(() => void 0);
2391
- }
2729
+ this.queueState("disconnected" /* Disconnected */, error);
2730
+ this.queueDisconnected();
2392
2731
  if (this.shouldReconnect()) {
2393
2732
  queueMicrotask(() => {
2394
2733
  void this.connect().catch(() => void 0);
@@ -2436,16 +2775,35 @@ var ZlinkStreamConnectorLifecycle = class {
2436
2775
  publishDisconnectedWithoutWaiting(signal) {
2437
2776
  void this.publishDisconnectedOnce(signal).catch(() => void 0);
2438
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
+ }
2439
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) {
2440
2797
  const previous = this.currentState;
2441
2798
  this.currentState = current;
2442
2799
  if (previous === current && error === void 0) {
2443
- return;
2444
- }
2445
- await this.events.publishStateChanged({ previous, current, error }, signal);
2446
- if (error !== void 0) {
2447
- await this.events.publishError(error, signal);
2800
+ return void 0;
2448
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);
2449
2807
  }
2450
2808
  };
2451
2809
 
@@ -2480,36 +2838,6 @@ var ZlinkStreamConnectorEvents = class {
2480
2838
  }
2481
2839
  };
2482
2840
 
2483
- // packages/stream-connector/src/Runtime/ZlinkFlowContext.ts
2484
- var BrowserZlinkFlowContext = class {
2485
- currentOrCreate(explicit) {
2486
- return explicit ?? { flowId: this.createUuidV7(), flowOrigin: "Application" };
2487
- }
2488
- createInbound(flowId, flowOrigin) {
2489
- return { flowId: flowId ?? this.createUuidV7(), flowOrigin: flowOrigin ?? "Inbound" };
2490
- }
2491
- createUuidV7() {
2492
- const crypto = globalThis.crypto;
2493
- if (crypto === void 0) {
2494
- throw connectorError(
2495
- "configurationError" /* ConfigurationError */,
2496
- "The browser entrypoint requires the platform Web Crypto API."
2497
- );
2498
- }
2499
- return formatUuidV7(crypto.getRandomValues(new Uint8Array(16)));
2500
- }
2501
- };
2502
- function formatUuidV7(bytes) {
2503
- const timestamp = BigInt(Date.now());
2504
- for (let index = 5; index >= 0; index -= 1) {
2505
- bytes[index] = Number(timestamp >> BigInt((5 - index) * 8) & 0xffn);
2506
- }
2507
- bytes[6] = 112 | bytes[6] & 15;
2508
- bytes[8] = 128 | bytes[8] & 63;
2509
- const hex = [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
2510
- return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
2511
- }
2512
-
2513
2841
  // packages/stream-connector/src/Runtime/Transport/BrowserWebSocketConnection.ts
2514
2842
  var BrowserStreamTransportFactory = class {
2515
2843
  async connect(options, signal) {
@@ -2584,7 +2912,11 @@ var BrowserWebSocketConnection = class {
2584
2912
  const message = toUint8Array(event.data);
2585
2913
  this.messages.push(message);
2586
2914
  } catch (cause) {
2587
- this.error = cause instanceof Error ? cause : connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "WebSocket message decode failed.", cause);
2915
+ this.error = cause instanceof Error ? cause : connectorError(
2916
+ "frameDecodeFailed" /* FrameDecodeFailed */,
2917
+ "WebSocket message decode failed.",
2918
+ cause
2919
+ );
2588
2920
  this.closed = true;
2589
2921
  this.socket.close();
2590
2922
  }
@@ -2592,19 +2924,28 @@ var BrowserWebSocketConnection = class {
2592
2924
  };
2593
2925
  onClose = () => {
2594
2926
  if (!this.closed) {
2595
- this.error = connectorError("disconnected" /* Disconnected */, "Remote stream closed the WebSocket connection.");
2927
+ this.error = connectorError(
2928
+ "disconnected" /* Disconnected */,
2929
+ "Remote stream closed the WebSocket connection."
2930
+ );
2596
2931
  }
2597
2932
  this.closed = true;
2598
2933
  this.wakeReader();
2599
2934
  };
2600
2935
  onError = () => {
2601
- this.error = connectorError("disconnected" /* Disconnected */, "Remote stream closed after a WebSocket error.");
2936
+ this.error = connectorError(
2937
+ "disconnected" /* Disconnected */,
2938
+ "Remote stream closed after a WebSocket error."
2939
+ );
2602
2940
  this.closed = true;
2603
2941
  this.wakeReader();
2604
2942
  };
2605
2943
  waitForMessage(signal) {
2606
2944
  if (this.readWaiter !== void 0) {
2607
- throw connectorError("validationFailed" /* ValidationFailed */, "Only one pending stream read is supported.");
2945
+ throw connectorError(
2946
+ "validationFailed" /* ValidationFailed */,
2947
+ "Only one pending stream read is supported."
2948
+ );
2608
2949
  }
2609
2950
  return new Promise((resolve, reject) => {
2610
2951
  const onAbort = () => {
@@ -2660,9 +3001,10 @@ function waitForClose(socket, signal) {
2660
3001
  async function waitForOpen(socket, connectTimeoutMs, signal) {
2661
3002
  throwIfAborted(signal);
2662
3003
  await new Promise((resolve, reject) => {
2663
- const timeout = setTimeout(() => finish(
2664
- connectorError("connectTimeout" /* ConnectTimeout */, "Connect timed out.")
2665
- ), connectTimeoutMs);
3004
+ const timeout = setTimeout(
3005
+ () => finish(connectorError("connectTimeout" /* ConnectTimeout */, "Connect timed out.")),
3006
+ connectTimeoutMs
3007
+ );
2666
3008
  const onOpen = () => finish();
2667
3009
  const onClose = () => finish(connectorError("connectTimeout" /* ConnectTimeout */, "Connect closed before opening."));
2668
3010
  const onError = () => finish(connectorError("connectTimeout" /* ConnectTimeout */, "Connect failed."));
@@ -2693,7 +3035,10 @@ function toUint8Array(data) {
2693
3035
  if (ArrayBuffer.isView(data)) {
2694
3036
  return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
2695
3037
  }
2696
- throw connectorError("frameDecodeFailed" /* FrameDecodeFailed */, "WebSocket text messages are not supported.");
3038
+ throw connectorError(
3039
+ "frameDecodeFailed" /* FrameDecodeFailed */,
3040
+ "WebSocket text messages are not supported."
3041
+ );
2697
3042
  }
2698
3043
 
2699
3044
  // packages/stream-connector/src/Runtime/ZlinkStreamConnector.ts
@@ -2707,30 +3052,26 @@ var DefaultZlinkStreamConnector = class {
2707
3052
  pendingRequests = new ZlinkStreamPendingRequests();
2708
3053
  frameSender;
2709
3054
  receiveDispatcher;
2710
- diagnosticsLevelCell;
3055
+ requestSendingHandlers = /* @__PURE__ */ new Set();
3056
+ replyReceivedHandlers = /* @__PURE__ */ new Set();
3057
+ boundActors;
2711
3058
  options;
2712
3059
  constructor(options) {
2713
- const flowContext = new BrowserZlinkFlowContext();
2714
3060
  this.options = normalizeOptions(options, new BrowserStreamTransportFactory());
2715
- this.diagnosticsLevelCell = new ZlinkStreamDiagnosticsLevelCell(this.options.diagnosticsLevel);
2716
- Object.defineProperty(this.options, "diagnosticsLevel", {
2717
- enumerable: true,
2718
- configurable: true,
2719
- get: () => this.diagnosticsLevelCell.level
2720
- });
2721
3061
  const protocol = new ZlinkStreamFrameProtocol(this.options);
2722
- this.frameSender = new ZlinkStreamFrameSender(protocol, flowContext);
3062
+ this.frameSender = new ZlinkStreamFrameSender(protocol);
2723
3063
  this.receivedMessages = new ZlinkStreamReceivedMessages(
2724
3064
  this.events,
2725
3065
  this.options.dispatchMode === "immediate" /* Immediate */
2726
3066
  );
3067
+ this.boundActors = new ZlinkStreamActors(this, this.receivedMessages, this.events);
2727
3068
  this.receiveDispatcher = new ZlinkStreamReceiveDispatcher(
2728
3069
  protocol,
2729
3070
  this.pendingRequests,
2730
3071
  this.receivedMessages,
2731
3072
  this.frameSender,
2732
3073
  this.events,
2733
- flowContext,
3074
+ this.boundActors,
2734
3075
  (reason) => this.lifecycle.serverClosing(reason)
2735
3076
  );
2736
3077
  this.lifecycle = new ZlinkStreamConnectorLifecycle(
@@ -2739,6 +3080,7 @@ var DefaultZlinkStreamConnector = class {
2739
3080
  this.frameSender,
2740
3081
  this.receiveDispatcher,
2741
3082
  this.receivedMessages,
3083
+ this.boundActors,
2742
3084
  this.events
2743
3085
  );
2744
3086
  }
@@ -2754,6 +3096,18 @@ var DefaultZlinkStreamConnector = class {
2754
3096
  get pendingDispatchCount() {
2755
3097
  return this.pendingRequests.count;
2756
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
+ }
2757
3111
  /**
2758
3112
  * Spec stream-connector 32 §10: how many packets carrying `name` arrived on
2759
3113
  * the current connection. Arrivals are what is counted, so a message a
@@ -2765,37 +3119,6 @@ var DefaultZlinkStreamConnector = class {
2765
3119
  validateName(name);
2766
3120
  return this.receivedMessages.receivedCount(name);
2767
3121
  }
2768
- /**
2769
- * Current diagnostics level (spec 26 §4.1, spec stream-connector 32 §13).
2770
- * Reflects the level set by the most recent {@link setDiagnosticsLevel}
2771
- * call, or the construction-time option (default
2772
- * {@link ZlinkStreamDiagnosticsLevel.Errors}) if it was never changed.
2773
- */
2774
- get diagnosticsLevel() {
2775
- return this.diagnosticsLevelCell.level;
2776
- }
2777
- /**
2778
- * Changes the diagnostics level in place without recreating the connector
2779
- * (spec 26 §4.1, spec stream-connector 32 §13). The change is an atomic
2780
- * state update: it applies to processing points that read the level after
2781
- * this call returns and is never applied retroactively to frames already
2782
- * built. Rejects unknown values with {@link ZlinkStreamErrorCode.ConfigurationError}.
2783
- * Spec stream-connector 32 §13: this surface changes the value without
2784
- * waiting for anything; it is not a blocking call over the asynchronous pair,
2785
- * which a receive callback would otherwise make wait for its own completion.
2786
- */
2787
- setDiagnosticsLevel(level) {
2788
- this.diagnosticsLevelCell.set(level);
2789
- }
2790
- /**
2791
- * Asynchronous counterpart of {@link setDiagnosticsLevel} (spec
2792
- * stream-connector 32 §13). It changes the same value; awaiting it is how a
2793
- * caller observes the change, and it never replaces the synchronous surface.
2794
- */
2795
- setDiagnosticsLevelAsync(level) {
2796
- this.setDiagnosticsLevel(level);
2797
- return Promise.resolve();
2798
- }
2799
3122
  onErrorReceived(handler) {
2800
3123
  return this.events.onError(handler);
2801
3124
  }
@@ -2805,6 +3128,14 @@ var DefaultZlinkStreamConnector = class {
2805
3128
  onConnectionStateChanged(handler) {
2806
3129
  return this.events.onStateChanged(handler);
2807
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
+ }
2808
3139
  async connect(signal) {
2809
3140
  await this.lifecycle.connect(signal);
2810
3141
  }
@@ -2822,15 +3153,60 @@ var DefaultZlinkStreamConnector = class {
2822
3153
  const encoded = this.encodePayload(payload, messageType);
2823
3154
  return new ZlinkStreamRequestBuilder(this, this.resolveNameOrDefault(encoded), encoded);
2824
3155
  }
2825
- on(name, handler, messageType) {
2826
- const encodedHandler = (message, signal) => handler({
2827
- name: message.name,
2828
- metadata: message.metadata,
2829
- payload: this.decodePayload(message.payload, messageType),
2830
- flowId: message.flowId,
2831
- flowOrigin: message.flowOrigin
2832
- }, signal);
2833
- return this.receivedMessages.on(name, encodedHandler);
3156
+ on(nameOrType, handler, messageType) {
3157
+ const encodedHandler = (message, signal) => handler(
3158
+ {
3159
+ name: message.name,
3160
+ metadata: message.metadata,
3161
+ payload: this.decodePayload(
3162
+ message.payload,
3163
+ messageType ?? (typeof nameOrType === "function" ? nameOrType : void 0)
3164
+ ),
3165
+ actorId: message.actorId
3166
+ },
3167
+ signal
3168
+ );
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);
2834
3210
  }
2835
3211
  waitFor(nameOrType) {
2836
3212
  return new ZlinkStreamWaitBuilder(this, this.observedName(nameOrType));
@@ -2850,7 +3226,10 @@ var DefaultZlinkStreamConnector = class {
2850
3226
  observedName(nameOrType) {
2851
3227
  const name = typeof nameOrType === "function" ? this.options.nameResolver.resolve(nameOrType) : nameOrType;
2852
3228
  if (typeof name !== "string") {
2853
- throw connectorError("validationFailed" /* ValidationFailed */, "Packet name must be a string or a payload constructor.");
3229
+ throw connectorError(
3230
+ "validationFailed" /* ValidationFailed */,
3231
+ "Packet name must be a string or a payload constructor."
3232
+ );
2854
3233
  }
2855
3234
  validateName(name);
2856
3235
  return name;
@@ -2870,7 +3249,10 @@ var DefaultZlinkStreamConnector = class {
2870
3249
  waitForMessage(name, timeoutMs, predicate, signal) {
2871
3250
  validateName(name);
2872
3251
  if (!Number.isFinite(timeoutMs) || timeoutMs < 0) {
2873
- throw connectorError("validationFailed" /* ValidationFailed */, "Timeout must be a non-negative finite number.");
3252
+ throw connectorError(
3253
+ "validationFailed" /* ValidationFailed */,
3254
+ "Timeout must be a non-negative finite number."
3255
+ );
2874
3256
  }
2875
3257
  throwIfAborted(signal);
2876
3258
  return new Promise((resolve, reject) => {
@@ -2896,30 +3278,35 @@ var DefaultZlinkStreamConnector = class {
2896
3278
  };
2897
3279
  timer = setTimeout(() => finish(), timeoutMs);
2898
3280
  signal?.addEventListener("abort", onAbort, { once: true });
2899
- disposable = this.receivedMessages.observe(name, (message) => {
2900
- if (done) {
2901
- return false;
2902
- }
2903
- try {
2904
- const decoded = {
2905
- name: message.name,
2906
- metadata: message.metadata,
2907
- payload: this.decodeWaitPayload(message.payload),
2908
- flowId: message.flowId,
2909
- flowOrigin: message.flowOrigin
2910
- };
2911
- if (!predicate(decoded)) {
3281
+ disposable = this.receivedMessages.observe(
3282
+ name,
3283
+ (message) => {
3284
+ if (done) {
2912
3285
  return false;
2913
3286
  }
2914
- finish(void 0, decoded);
2915
- } catch (cause) {
2916
- finish(cause);
2917
- }
2918
- return true;
2919
- }, () => finish(connectorError(
2920
- "disconnected" /* Disconnected */,
2921
- `The connection this wait for '${name}' observed has ended.`
2922
- )));
3287
+ try {
3288
+ const decoded = {
3289
+ name: message.name,
3290
+ metadata: message.metadata,
3291
+ payload: this.decodeWaitPayload(message.payload),
3292
+ actorId: message.actorId
3293
+ };
3294
+ if (!predicate(decoded)) {
3295
+ return false;
3296
+ }
3297
+ finish(void 0, decoded);
3298
+ } catch (cause) {
3299
+ finish(cause);
3300
+ }
3301
+ return true;
3302
+ },
3303
+ () => finish(
3304
+ connectorError(
3305
+ "disconnected" /* Disconnected */,
3306
+ `The connection this wait for '${name}' observed has ended.`
3307
+ )
3308
+ )
3309
+ );
2923
3310
  });
2924
3311
  }
2925
3312
  encodePayload(payload, messageType) {
@@ -2941,7 +3328,7 @@ var DefaultZlinkStreamConnector = class {
2941
3328
  }
2942
3329
  return payload;
2943
3330
  }
2944
- async sendEncoded(kind, name, payload, metadata, compress, requestSeq, signal, flow, correlationId) {
3331
+ async sendEncoded(kind, name, payload, metadata, compress, requestSeq, signal, correlationId, actorSlot) {
2945
3332
  await this.frameSender.send(
2946
3333
  this.lifecycle.connectionForSend(),
2947
3334
  kind,
@@ -2952,37 +3339,105 @@ var DefaultZlinkStreamConnector = class {
2952
3339
  requestSeq,
2953
3340
  signal,
2954
3341
  correlationId,
2955
- flow
3342
+ actorSlot
2956
3343
  );
2957
3344
  }
2958
3345
  /**
2959
3346
  * Per-connector monotonic correlation id (hex). The client generates it on each request
2960
- * 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.
2961
3348
  */
2962
3349
  nextCorrelationId() {
2963
3350
  this.correlationCounter += 1n;
2964
3351
  return this.correlationCounter.toString(16);
2965
3352
  }
2966
- async requestEncoded(name, payload, metadata, compress, timeoutMs, signal, flow) {
2967
- 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;
2968
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);
2969
3384
  await this.sendEncoded(
2970
3385
  2 /* Request */,
2971
3386
  name,
2972
3387
  payload,
2973
- metadata,
3388
+ requestMetadata,
2974
3389
  compress,
2975
3390
  pending.requestSeq,
2976
3391
  signal,
2977
- flow,
2978
- this.nextCorrelationId()
3392
+ this.nextCorrelationId(),
3393
+ actorSlot
2979
3394
  );
2980
- return await pending.promise;
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
3405
+ );
3406
+ return reply.payload;
2981
3407
  } catch (error) {
2982
- 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
+ );
2983
3419
  throw error;
2984
3420
  }
2985
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
+ }
2986
3441
  resolveNameOrDefault(payload) {
2987
3442
  if (payload.messageType === void 0) {
2988
3443
  return void 0;
@@ -3008,7 +3463,6 @@ export {
3008
3463
  ZlinkStreamCodec,
3009
3464
  ZlinkStreamCompression,
3010
3465
  ZlinkStreamConnectionState,
3011
- ZlinkStreamDiagnosticsLevel,
3012
3466
  ZlinkStreamDispatchMode,
3013
3467
  ZlinkStreamErrorCode,
3014
3468
  ZlinkStreamException,