@replit/river 0.23.12 → 0.23.14

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.
Files changed (75) hide show
  1. package/dist/{chunk-3AW3IXVD.js → chunk-4PVU7J25.js} +1 -21
  2. package/dist/chunk-4PVU7J25.js.map +1 -0
  3. package/dist/{chunk-HDBVL7EF.js → chunk-BEALFLCB.js} +2 -2
  4. package/dist/chunk-D2DHRRBN.js +476 -0
  5. package/dist/chunk-D2DHRRBN.js.map +1 -0
  6. package/dist/{chunk-7RUKEUKE.js → chunk-GCCRVSMR.js} +33 -4
  7. package/dist/chunk-GCCRVSMR.js.map +1 -0
  8. package/dist/{chunk-XZ6IOBM5.js → chunk-GN4YEXT7.js} +2 -2
  9. package/dist/chunk-GN4YEXT7.js.map +1 -0
  10. package/dist/chunk-O2AVDJCQ.js +335 -0
  11. package/dist/chunk-O2AVDJCQ.js.map +1 -0
  12. package/dist/chunk-OTVTKAN6.js +451 -0
  13. package/dist/chunk-OTVTKAN6.js.map +1 -0
  14. package/dist/chunk-WUL63FR6.js +335 -0
  15. package/dist/chunk-WUL63FR6.js.map +1 -0
  16. package/dist/{chunk-H6KTH6W6.js → chunk-YCLZWES2.js} +2 -2
  17. package/dist/client-e13979ac.d.ts +52 -0
  18. package/dist/codec/index.js +20 -2
  19. package/dist/codec/index.js.map +1 -1
  20. package/dist/{connection-8debd45f.d.ts → connection-5d0978ce.d.ts} +1 -1
  21. package/dist/{connection-581558f8.d.ts → connection-e57e98ea.d.ts} +1 -1
  22. package/dist/{transport-47af1c81.d.ts → handshake-5665ffd3.d.ts} +101 -153
  23. package/dist/{index-60f03cb7.d.ts → index-ea74cdbb.d.ts} +1 -1
  24. package/dist/logging/index.d.cts +1 -1
  25. package/dist/logging/index.d.ts +1 -1
  26. package/dist/router/index.cjs +16 -1
  27. package/dist/router/index.cjs.map +1 -1
  28. package/dist/router/index.d.cts +8 -6
  29. package/dist/router/index.d.ts +8 -6
  30. package/dist/router/index.js +2 -2
  31. package/dist/server-1cfc88d1.d.ts +24 -0
  32. package/dist/{services-ca72c9f8.d.ts → services-86c4d10d.d.ts} +3 -2
  33. package/dist/transport/impls/uds/client.cjs +303 -180
  34. package/dist/transport/impls/uds/client.cjs.map +1 -1
  35. package/dist/transport/impls/uds/client.d.cts +6 -5
  36. package/dist/transport/impls/uds/client.d.ts +6 -5
  37. package/dist/transport/impls/uds/client.js +6 -4
  38. package/dist/transport/impls/uds/client.js.map +1 -1
  39. package/dist/transport/impls/uds/server.cjs +396 -234
  40. package/dist/transport/impls/uds/server.cjs.map +1 -1
  41. package/dist/transport/impls/uds/server.d.cts +6 -5
  42. package/dist/transport/impls/uds/server.d.ts +6 -5
  43. package/dist/transport/impls/uds/server.js +8 -6
  44. package/dist/transport/impls/uds/server.js.map +1 -1
  45. package/dist/transport/impls/ws/client.cjs +305 -182
  46. package/dist/transport/impls/ws/client.cjs.map +1 -1
  47. package/dist/transport/impls/ws/client.d.cts +6 -5
  48. package/dist/transport/impls/ws/client.d.ts +6 -5
  49. package/dist/transport/impls/ws/client.js +6 -4
  50. package/dist/transport/impls/ws/client.js.map +1 -1
  51. package/dist/transport/impls/ws/server.cjs +350 -188
  52. package/dist/transport/impls/ws/server.cjs.map +1 -1
  53. package/dist/transport/impls/ws/server.d.cts +4 -3
  54. package/dist/transport/impls/ws/server.d.ts +4 -3
  55. package/dist/transport/impls/ws/server.js +8 -6
  56. package/dist/transport/impls/ws/server.js.map +1 -1
  57. package/dist/transport/index.cjs +338 -142
  58. package/dist/transport/index.cjs.map +1 -1
  59. package/dist/transport/index.d.cts +4 -2
  60. package/dist/transport/index.d.ts +4 -2
  61. package/dist/transport/index.js +14 -8
  62. package/dist/util/testHelpers.cjs +10 -6
  63. package/dist/util/testHelpers.cjs.map +1 -1
  64. package/dist/util/testHelpers.d.cts +5 -4
  65. package/dist/util/testHelpers.d.ts +5 -4
  66. package/dist/util/testHelpers.js +4 -5
  67. package/dist/util/testHelpers.js.map +1 -1
  68. package/package.json +13 -14
  69. package/dist/chunk-3AW3IXVD.js.map +0 -1
  70. package/dist/chunk-7RUKEUKE.js.map +0 -1
  71. package/dist/chunk-VRU4IKRT.js +0 -1392
  72. package/dist/chunk-VRU4IKRT.js.map +0 -1
  73. package/dist/chunk-XZ6IOBM5.js.map +0 -1
  74. /package/dist/{chunk-HDBVL7EF.js.map → chunk-BEALFLCB.js.map} +0 -0
  75. /package/dist/{chunk-H6KTH6W6.js.map → chunk-YCLZWES2.js.map} +0 -0
@@ -24,8 +24,8 @@ __export(client_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(client_exports);
26
26
 
27
- // transport/transport.ts
28
- var import_value = require("@sinclair/typebox/value");
27
+ // transport/client.ts
28
+ var import_api4 = require("@opentelemetry/api");
29
29
 
30
30
  // transport/message.ts
31
31
  var import_typebox = require("@sinclair/typebox");
@@ -59,6 +59,21 @@ var ControlMessageHandshakeRequestSchema = import_typebox.Type.Object({
59
59
  type: import_typebox.Type.Literal("HANDSHAKE_REQ"),
60
60
  protocolVersion: import_typebox.Type.String(),
61
61
  sessionId: import_typebox.Type.String(),
62
+ /**
63
+ * Specifies what the server's expected session state (from the pov of the client). This can be
64
+ * used by the server to know whether this is a new or a reestablished connection, and whether it
65
+ * is compatible with what it already has.
66
+ */
67
+ expectedSessionState: import_typebox.Type.Optional(
68
+ import_typebox.Type.Object({
69
+ /**
70
+ * reconnect is set to true if the client explicitly wants to reestablish an existing
71
+ * connection.
72
+ */
73
+ reconnect: import_typebox.Type.Boolean(),
74
+ nextExpectedSeq: import_typebox.Type.Integer()
75
+ })
76
+ ),
62
77
  metadata: import_typebox.Type.Optional(import_typebox.Type.Unknown())
63
78
  });
64
79
  var ControlMessageHandshakeResponseSchema = import_typebox.Type.Object({
@@ -83,7 +98,14 @@ var ControlMessagePayloadSchema = import_typebox.Type.Union([
83
98
  var OpaqueTransportMessageSchema = TransportMessageSchema(
84
99
  import_typebox.Type.Unknown()
85
100
  );
86
- function handshakeRequestMessage(from, to, sessionId, metadata, tracing) {
101
+ function handshakeRequestMessage({
102
+ from,
103
+ to,
104
+ sessionId,
105
+ expectedSessionState,
106
+ metadata,
107
+ tracing
108
+ }) {
87
109
  return {
88
110
  id: (0, import_nanoid.nanoid)(),
89
111
  from,
@@ -97,14 +119,164 @@ function handshakeRequestMessage(from, to, sessionId, metadata, tracing) {
97
119
  type: "HANDSHAKE_REQ",
98
120
  protocolVersion: PROTOCOL_VERSION,
99
121
  sessionId,
122
+ expectedSessionState,
100
123
  metadata
101
124
  }
102
125
  };
103
126
  }
127
+ var SESSION_STATE_MISMATCH = "session state mismatch";
104
128
  function isAck(controlFlag) {
105
129
  return (controlFlag & 1 /* AckBit */) === 1 /* AckBit */;
106
130
  }
107
131
 
132
+ // codec/json.ts
133
+ var encoder = new TextEncoder();
134
+ var decoder = new TextDecoder();
135
+ function uint8ArrayToBase64(uint8Array) {
136
+ let binary = "";
137
+ uint8Array.forEach((byte) => {
138
+ binary += String.fromCharCode(byte);
139
+ });
140
+ return btoa(binary);
141
+ }
142
+ function base64ToUint8Array(base64) {
143
+ const binaryString = atob(base64);
144
+ const uint8Array = new Uint8Array(binaryString.length);
145
+ for (let i = 0; i < binaryString.length; i++) {
146
+ uint8Array[i] = binaryString.charCodeAt(i);
147
+ }
148
+ return uint8Array;
149
+ }
150
+ var NaiveJsonCodec = {
151
+ toBuffer: (obj) => {
152
+ return encoder.encode(
153
+ JSON.stringify(obj, function replacer(key) {
154
+ const val = this[key];
155
+ if (val instanceof Uint8Array) {
156
+ return { $t: uint8ArrayToBase64(val) };
157
+ } else {
158
+ return val;
159
+ }
160
+ })
161
+ );
162
+ },
163
+ fromBuffer: (buff) => {
164
+ try {
165
+ const parsed = JSON.parse(
166
+ decoder.decode(buff),
167
+ function reviver(_key, val) {
168
+ if (val?.$t) {
169
+ return base64ToUint8Array(val.$t);
170
+ } else {
171
+ return val;
172
+ }
173
+ }
174
+ );
175
+ if (typeof parsed === "object")
176
+ return parsed;
177
+ return null;
178
+ } catch {
179
+ return null;
180
+ }
181
+ }
182
+ };
183
+
184
+ // transport/options.ts
185
+ var defaultTransportOptions = {
186
+ heartbeatIntervalMs: 1e3,
187
+ heartbeatsUntilDead: 2,
188
+ sessionDisconnectGraceMs: 5e3,
189
+ codec: NaiveJsonCodec
190
+ };
191
+ var defaultConnectionRetryOptions = {
192
+ baseIntervalMs: 250,
193
+ maxJitterMs: 200,
194
+ maxBackoffMs: 32e3,
195
+ attemptBudgetCapacity: 5,
196
+ budgetRestoreIntervalMs: 200
197
+ };
198
+ var defaultClientTransportOptions = {
199
+ ...defaultTransportOptions,
200
+ ...defaultConnectionRetryOptions
201
+ };
202
+ var defaultServerTransportOptions = {
203
+ ...defaultTransportOptions
204
+ };
205
+
206
+ // transport/rateLimit.ts
207
+ var LeakyBucketRateLimit = class {
208
+ budgetConsumed;
209
+ intervalHandles;
210
+ options;
211
+ constructor(options) {
212
+ this.options = options;
213
+ this.budgetConsumed = /* @__PURE__ */ new Map();
214
+ this.intervalHandles = /* @__PURE__ */ new Map();
215
+ }
216
+ getBackoffMs(user) {
217
+ if (!this.budgetConsumed.has(user))
218
+ return 0;
219
+ const exponent = Math.max(0, this.getBudgetConsumed(user) - 1);
220
+ const jitter = Math.floor(Math.random() * this.options.maxJitterMs);
221
+ const backoffMs = Math.min(
222
+ this.options.baseIntervalMs * 2 ** exponent,
223
+ this.options.maxBackoffMs
224
+ );
225
+ return backoffMs + jitter;
226
+ }
227
+ get totalBudgetRestoreTime() {
228
+ return this.options.budgetRestoreIntervalMs * this.options.attemptBudgetCapacity;
229
+ }
230
+ consumeBudget(user) {
231
+ this.stopLeak(user);
232
+ this.budgetConsumed.set(user, this.getBudgetConsumed(user) + 1);
233
+ }
234
+ getBudgetConsumed(user) {
235
+ return this.budgetConsumed.get(user) ?? 0;
236
+ }
237
+ hasBudget(user) {
238
+ return this.getBudgetConsumed(user) < this.options.attemptBudgetCapacity;
239
+ }
240
+ startRestoringBudget(user) {
241
+ if (this.intervalHandles.has(user)) {
242
+ return;
243
+ }
244
+ const restoreBudgetForUser = () => {
245
+ const currentBudget = this.budgetConsumed.get(user);
246
+ if (!currentBudget) {
247
+ this.stopLeak(user);
248
+ return;
249
+ }
250
+ const newBudget = currentBudget - 1;
251
+ if (newBudget === 0) {
252
+ this.budgetConsumed.delete(user);
253
+ return;
254
+ }
255
+ this.budgetConsumed.set(user, newBudget);
256
+ };
257
+ const intervalHandle = setInterval(
258
+ restoreBudgetForUser,
259
+ this.options.budgetRestoreIntervalMs
260
+ );
261
+ this.intervalHandles.set(user, intervalHandle);
262
+ }
263
+ stopLeak(user) {
264
+ if (!this.intervalHandles.has(user)) {
265
+ return;
266
+ }
267
+ clearInterval(this.intervalHandles.get(user));
268
+ this.intervalHandles.delete(user);
269
+ }
270
+ close() {
271
+ for (const user of this.intervalHandles.keys()) {
272
+ this.stopLeak(user);
273
+ }
274
+ }
275
+ };
276
+
277
+ // transport/transport.ts
278
+ var import_value = require("@sinclair/typebox/value");
279
+
108
280
  // logging/log.ts
109
281
  var LoggingLevels = {
110
282
  debug: -1,
@@ -202,7 +374,7 @@ var import_nanoid2 = require("nanoid");
202
374
  var import_api = require("@opentelemetry/api");
203
375
 
204
376
  // package.json
205
- var version = "0.23.12";
377
+ var version = "0.23.14";
206
378
 
207
379
  // tracing/index.ts
208
380
  function getPropagationContext(ctx) {
@@ -516,9 +688,17 @@ var Session = class {
516
688
  get connected() {
517
689
  return this.connection !== void 0;
518
690
  }
691
+ get nextExpectedAck() {
692
+ return this.seq;
693
+ }
519
694
  get nextExpectedSeq() {
520
695
  return this.ack;
521
696
  }
697
+ // This is only used in tests to make the session misbehave.
698
+ /* @internal */
699
+ advanceAckForTesting(by) {
700
+ this.ack += by;
701
+ }
522
702
  constructMsg(partialMsg) {
523
703
  const msg = {
524
704
  ...partialMsg,
@@ -537,159 +717,8 @@ var Session = class {
537
717
  }
538
718
  };
539
719
 
540
- // util/stringify.ts
541
- function coerceErrorString(err) {
542
- if (err instanceof Error) {
543
- return err.message || "unknown reason";
544
- }
545
- return `[coerced to error] ${String(err)}`;
546
- }
547
-
548
- // transport/rateLimit.ts
549
- var LeakyBucketRateLimit = class {
550
- budgetConsumed;
551
- intervalHandles;
552
- options;
553
- constructor(options) {
554
- this.options = options;
555
- this.budgetConsumed = /* @__PURE__ */ new Map();
556
- this.intervalHandles = /* @__PURE__ */ new Map();
557
- }
558
- getBackoffMs(user) {
559
- if (!this.budgetConsumed.has(user))
560
- return 0;
561
- const exponent = Math.max(0, this.getBudgetConsumed(user) - 1);
562
- const jitter = Math.floor(Math.random() * this.options.maxJitterMs);
563
- const backoffMs = Math.min(
564
- this.options.baseIntervalMs * 2 ** exponent,
565
- this.options.maxBackoffMs
566
- );
567
- return backoffMs + jitter;
568
- }
569
- get totalBudgetRestoreTime() {
570
- return this.options.budgetRestoreIntervalMs * this.options.attemptBudgetCapacity;
571
- }
572
- consumeBudget(user) {
573
- this.stopLeak(user);
574
- this.budgetConsumed.set(user, this.getBudgetConsumed(user) + 1);
575
- }
576
- getBudgetConsumed(user) {
577
- return this.budgetConsumed.get(user) ?? 0;
578
- }
579
- hasBudget(user) {
580
- return this.getBudgetConsumed(user) < this.options.attemptBudgetCapacity;
581
- }
582
- startRestoringBudget(user) {
583
- if (this.intervalHandles.has(user)) {
584
- return;
585
- }
586
- const restoreBudgetForUser = () => {
587
- const currentBudget = this.budgetConsumed.get(user);
588
- if (!currentBudget) {
589
- this.stopLeak(user);
590
- return;
591
- }
592
- const newBudget = currentBudget - 1;
593
- if (newBudget === 0) {
594
- this.budgetConsumed.delete(user);
595
- return;
596
- }
597
- this.budgetConsumed.set(user, newBudget);
598
- };
599
- const intervalHandle = setInterval(
600
- restoreBudgetForUser,
601
- this.options.budgetRestoreIntervalMs
602
- );
603
- this.intervalHandles.set(user, intervalHandle);
604
- }
605
- stopLeak(user) {
606
- if (!this.intervalHandles.has(user)) {
607
- return;
608
- }
609
- clearInterval(this.intervalHandles.get(user));
610
- this.intervalHandles.delete(user);
611
- }
612
- close() {
613
- for (const user of this.intervalHandles.keys()) {
614
- this.stopLeak(user);
615
- }
616
- }
617
- };
618
-
619
- // codec/json.ts
620
- var encoder = new TextEncoder();
621
- var decoder = new TextDecoder();
622
- function uint8ArrayToBase64(uint8Array) {
623
- let binary = "";
624
- uint8Array.forEach((byte) => {
625
- binary += String.fromCharCode(byte);
626
- });
627
- return btoa(binary);
628
- }
629
- function base64ToUint8Array(base64) {
630
- const binaryString = atob(base64);
631
- const uint8Array = new Uint8Array(binaryString.length);
632
- for (let i = 0; i < binaryString.length; i++) {
633
- uint8Array[i] = binaryString.charCodeAt(i);
634
- }
635
- return uint8Array;
636
- }
637
- var NaiveJsonCodec = {
638
- toBuffer: (obj) => {
639
- return encoder.encode(
640
- JSON.stringify(obj, function replacer(key) {
641
- const val = this[key];
642
- if (val instanceof Uint8Array) {
643
- return { $t: uint8ArrayToBase64(val) };
644
- } else {
645
- return val;
646
- }
647
- })
648
- );
649
- },
650
- fromBuffer: (buff) => {
651
- try {
652
- const parsed = JSON.parse(
653
- decoder.decode(buff),
654
- function reviver(_key, val) {
655
- if (val?.$t) {
656
- return base64ToUint8Array(val.$t);
657
- } else {
658
- return val;
659
- }
660
- }
661
- );
662
- if (typeof parsed === "object")
663
- return parsed;
664
- return null;
665
- } catch {
666
- return null;
667
- }
668
- }
669
- };
670
-
671
720
  // transport/transport.ts
672
721
  var import_api3 = require("@opentelemetry/api");
673
- var defaultTransportOptions = {
674
- heartbeatIntervalMs: 1e3,
675
- heartbeatsUntilDead: 2,
676
- sessionDisconnectGraceMs: 5e3,
677
- codec: NaiveJsonCodec
678
- };
679
- var defaultConnectionRetryOptions = {
680
- baseIntervalMs: 250,
681
- maxJitterMs: 200,
682
- maxBackoffMs: 32e3,
683
- attemptBudgetCapacity: 5,
684
- budgetRestoreIntervalMs: 200
685
- };
686
- var defaultClientTransportOptions = {
687
- ...defaultTransportOptions,
688
- ...defaultConnectionRetryOptions
689
- };
690
- var defaultServerTransportOptions = {
691
- ...defaultTransportOptions
692
- };
693
722
  var Transport = class {
694
723
  /**
695
724
  * The status of the transport.
@@ -780,6 +809,49 @@ var Transport = class {
780
809
  });
781
810
  return session;
782
811
  }
812
+ createNewSession({
813
+ to,
814
+ conn,
815
+ sessionId,
816
+ propagationCtx
817
+ }) {
818
+ let session = this.sessions.get(to);
819
+ if (session !== void 0) {
820
+ this.log?.info(
821
+ `session for ${to} already exists, replacing it with a new session as requested`,
822
+ session.loggingMetadata
823
+ );
824
+ this.deleteSession({
825
+ session,
826
+ closeHandshakingConnection: false
827
+ });
828
+ session = void 0;
829
+ }
830
+ session = this.createSession(to, conn, propagationCtx);
831
+ session.advertisedSessionId = sessionId;
832
+ this.log?.info(`created new session for ${to}`, session.loggingMetadata);
833
+ return session;
834
+ }
835
+ getExistingSession({
836
+ to,
837
+ sessionId,
838
+ nextExpectedSeq
839
+ }) {
840
+ const session = this.sessions.get(to);
841
+ if (
842
+ // reject this request if there was no previous session to replace
843
+ session === void 0 || // or if both parties do not agree about the next expected sequence number
844
+ session.nextExpectedAck < nextExpectedSeq || // or if both parties do not agree on the advertised session id
845
+ session.advertisedSessionId !== sessionId
846
+ ) {
847
+ return false;
848
+ }
849
+ this.log?.info(
850
+ `reused existing session for ${to}`,
851
+ session.loggingMetadata
852
+ );
853
+ return session;
854
+ }
783
855
  getOrCreateSession({
784
856
  to,
785
857
  conn,
@@ -844,6 +916,16 @@ var Transport = class {
844
916
  * @param connectedTo The peer we are connected to.
845
917
  */
846
918
  onDisconnect(conn, session) {
919
+ if (session.connection !== void 0 && session.connection.id !== conn.id) {
920
+ session.telemetry.span.addEvent("onDisconnect race");
921
+ this.log?.warn("onDisconnect race", {
922
+ clientId: this.clientId,
923
+ ...session.loggingMetadata,
924
+ ...conn.loggingMetadata,
925
+ tags: ["invariant-violation"]
926
+ });
927
+ return;
928
+ }
847
929
  conn.telemetry?.span.end();
848
930
  this.eventDispatcher.dispatchEvent("connectionStatus", {
849
931
  status: "disconnect",
@@ -851,6 +933,16 @@ var Transport = class {
851
933
  });
852
934
  session.connection = void 0;
853
935
  session.beginGrace(() => {
936
+ if (session.connection !== void 0) {
937
+ session.telemetry.span.addEvent("session grace period race");
938
+ this.log?.warn("session grace period race", {
939
+ clientId: this.clientId,
940
+ ...session.loggingMetadata,
941
+ ...conn.loggingMetadata,
942
+ tags: ["invariant-violation"]
943
+ });
944
+ return;
945
+ }
854
946
  session.telemetry.span.addEvent("session grace period expired");
855
947
  this.deleteSession({
856
948
  session,
@@ -1018,6 +1110,17 @@ var Transport = class {
1018
1110
  return this.status;
1019
1111
  }
1020
1112
  };
1113
+
1114
+ // util/stringify.ts
1115
+ function coerceErrorString(err) {
1116
+ if (err instanceof Error) {
1117
+ return err.message || "unknown reason";
1118
+ }
1119
+ return `[coerced to error] ${String(err)}`;
1120
+ }
1121
+
1122
+ // transport/client.ts
1123
+ var import_value2 = require("@sinclair/typebox/value");
1021
1124
  var ClientTransport = class extends Transport {
1022
1125
  /**
1023
1126
  * The options for this transport.
@@ -1078,7 +1181,7 @@ var ClientTransport = class extends Transport {
1078
1181
  const parsed = this.parseMsg(data2, conn);
1079
1182
  if (!parsed) {
1080
1183
  conn.telemetry?.span.setStatus({
1081
- code: import_api3.SpanStatusCode.ERROR,
1184
+ code: import_api4.SpanStatusCode.ERROR,
1082
1185
  message: "message parse failure"
1083
1186
  });
1084
1187
  conn.close();
@@ -1109,7 +1212,7 @@ var ClientTransport = class extends Transport {
1109
1212
  });
1110
1213
  conn.addErrorListener((err) => {
1111
1214
  conn.telemetry?.span.setStatus({
1112
- code: import_api3.SpanStatusCode.ERROR,
1215
+ code: import_api4.SpanStatusCode.ERROR,
1113
1216
  message: "connection error"
1114
1217
  });
1115
1218
  this.log?.warn(
@@ -1127,7 +1230,7 @@ var ClientTransport = class extends Transport {
1127
1230
  const parsed = this.parseMsg(data, conn);
1128
1231
  if (!parsed) {
1129
1232
  conn.telemetry?.span.setStatus({
1130
- code: import_api3.SpanStatusCode.ERROR,
1233
+ code: import_api4.SpanStatusCode.ERROR,
1131
1234
  message: "non-transport message"
1132
1235
  });
1133
1236
  this.protocolError(
@@ -1136,9 +1239,9 @@ var ClientTransport = class extends Transport {
1136
1239
  );
1137
1240
  return false;
1138
1241
  }
1139
- if (!import_value.Value.Check(ControlMessageHandshakeResponseSchema, parsed.payload)) {
1242
+ if (!import_value2.Value.Check(ControlMessageHandshakeResponseSchema, parsed.payload)) {
1140
1243
  conn.telemetry?.span.setStatus({
1141
- code: import_api3.SpanStatusCode.ERROR,
1244
+ code: import_api4.SpanStatusCode.ERROR,
1142
1245
  message: "invalid handshake response"
1143
1246
  });
1144
1247
  this.log?.warn(`received invalid handshake resp`, {
@@ -1147,7 +1250,7 @@ var ClientTransport = class extends Transport {
1147
1250
  connectedTo: parsed.from,
1148
1251
  transportMessage: parsed,
1149
1252
  validationErrors: [
1150
- ...import_value.Value.Errors(
1253
+ ...import_value2.Value.Errors(
1151
1254
  ControlMessageHandshakeResponseSchema,
1152
1255
  parsed.payload
1153
1256
  )
@@ -1159,31 +1262,47 @@ var ClientTransport = class extends Transport {
1159
1262
  );
1160
1263
  return false;
1161
1264
  }
1265
+ const previousSession = this.sessions.get(parsed.from);
1162
1266
  if (!parsed.payload.status.ok) {
1163
- conn.telemetry?.span.setStatus({
1164
- code: import_api3.SpanStatusCode.ERROR,
1165
- message: "handshake rejected"
1166
- });
1167
- this.log?.warn(`received handshake rejection`, {
1168
- ...conn.loggingMetadata,
1169
- clientId: this.clientId,
1170
- connectedTo: parsed.from,
1171
- transportMessage: parsed
1172
- });
1267
+ if (parsed.payload.status.reason === SESSION_STATE_MISMATCH) {
1268
+ if (previousSession) {
1269
+ this.deleteSession({
1270
+ session: previousSession,
1271
+ closeHandshakingConnection: true
1272
+ });
1273
+ }
1274
+ conn.telemetry?.span.setStatus({
1275
+ code: import_api4.SpanStatusCode.ERROR,
1276
+ message: parsed.payload.status.reason
1277
+ });
1278
+ } else {
1279
+ conn.telemetry?.span.setStatus({
1280
+ code: import_api4.SpanStatusCode.ERROR,
1281
+ message: "handshake rejected"
1282
+ });
1283
+ }
1284
+ this.log?.warn(
1285
+ `received handshake rejection: ${parsed.payload.status.reason}`,
1286
+ {
1287
+ ...conn.loggingMetadata,
1288
+ clientId: this.clientId,
1289
+ connectedTo: parsed.from,
1290
+ transportMessage: parsed
1291
+ }
1292
+ );
1173
1293
  this.protocolError(
1174
1294
  ProtocolError.HandshakeFailed,
1175
1295
  parsed.payload.status.reason
1176
1296
  );
1177
1297
  return false;
1178
1298
  }
1179
- const previousSession = this.sessions.get(parsed.from);
1180
1299
  if (previousSession?.advertisedSessionId && previousSession.advertisedSessionId !== parsed.payload.status.sessionId) {
1181
1300
  this.deleteSession({
1182
1301
  session: previousSession,
1183
1302
  closeHandshakingConnection: true
1184
1303
  });
1185
1304
  conn.telemetry?.span.setStatus({
1186
- code: import_api3.SpanStatusCode.ERROR,
1305
+ code: import_api4.SpanStatusCode.ERROR,
1187
1306
  message: "session id mismatch"
1188
1307
  });
1189
1308
  this.log?.warn(`handshake from ${parsed.from} session id mismatch`, {
@@ -1283,7 +1402,7 @@ var ClientTransport = class extends Transport {
1283
1402
  } catch (err) {
1284
1403
  const errStr = coerceErrorString(err);
1285
1404
  span.recordException(errStr);
1286
- span.setStatus({ code: import_api3.SpanStatusCode.ERROR });
1405
+ span.setStatus({ code: import_api4.SpanStatusCode.ERROR });
1287
1406
  throw err;
1288
1407
  } finally {
1289
1408
  span.end();
@@ -1334,13 +1453,13 @@ var ClientTransport = class extends Transport {
1334
1453
  let metadata = void 0;
1335
1454
  if (this.handshakeExtensions) {
1336
1455
  metadata = await this.handshakeExtensions.construct();
1337
- if (!import_value.Value.Check(this.handshakeExtensions.schema, metadata)) {
1456
+ if (!import_value2.Value.Check(this.handshakeExtensions.schema, metadata)) {
1338
1457
  this.log?.error(`constructed handshake metadata did not match schema`, {
1339
1458
  ...conn.loggingMetadata,
1340
1459
  clientId: this.clientId,
1341
1460
  connectedTo: to,
1342
1461
  validationErrors: [
1343
- ...import_value.Value.Errors(this.handshakeExtensions.schema, metadata)
1462
+ ...import_value2.Value.Errors(this.handshakeExtensions.schema, metadata)
1344
1463
  ],
1345
1464
  tags: ["invariant-violation"]
1346
1465
  });
@@ -1349,20 +1468,24 @@ var ClientTransport = class extends Transport {
1349
1468
  "handshake metadata did not match schema"
1350
1469
  );
1351
1470
  conn.telemetry?.span.setStatus({
1352
- code: import_api3.SpanStatusCode.ERROR,
1471
+ code: import_api4.SpanStatusCode.ERROR,
1353
1472
  message: "handshake meta mismatch"
1354
1473
  });
1355
1474
  return false;
1356
1475
  }
1357
1476
  }
1358
1477
  const { session } = this.getOrCreateSession({ to, handshakingConn: conn });
1359
- const requestMsg = handshakeRequestMessage(
1360
- this.clientId,
1478
+ const requestMsg = handshakeRequestMessage({
1479
+ from: this.clientId,
1361
1480
  to,
1362
- session.id,
1481
+ sessionId: session.id,
1482
+ expectedSessionState: {
1483
+ reconnect: session.advertisedSessionId !== void 0,
1484
+ nextExpectedSeq: session.nextExpectedSeq
1485
+ },
1363
1486
  metadata,
1364
- getPropagationContext(session.telemetry.ctx)
1365
- );
1487
+ tracing: getPropagationContext(session.telemetry.ctx)
1488
+ });
1366
1489
  this.log?.debug(`sending handshake request to ${to}`, {
1367
1490
  ...conn.loggingMetadata,
1368
1491
  clientId: this.clientId,