@dvina/sdk 4.0.212 → 4.0.215

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 (33) hide show
  1. package/dist/adapters/angular/index.cjs +4 -4
  2. package/dist/adapters/angular/index.d.cts +2 -2
  3. package/dist/adapters/angular/index.d.ts +2 -2
  4. package/dist/adapters/angular/index.js +2 -2
  5. package/dist/billing/index.cjs +5 -5
  6. package/dist/billing/index.d.cts +2 -12
  7. package/dist/billing/index.d.ts +2 -12
  8. package/dist/billing/index.js +1 -1
  9. package/dist/{chunk-CW5W3LEG.js → chunk-BJDU4UX4.js} +290 -408
  10. package/dist/chunk-BJDU4UX4.js.map +1 -0
  11. package/dist/{chunk-5TAY5I34.js → chunk-Q5XGHH7D.js} +471 -209
  12. package/dist/chunk-Q5XGHH7D.js.map +1 -0
  13. package/dist/{chunk-4EESBP3A.cjs → chunk-XK5PW7IX.cjs} +311 -429
  14. package/dist/chunk-XK5PW7IX.cjs.map +1 -0
  15. package/dist/{chunk-BL3GFOZR.cjs → chunk-Y4OD5SDF.cjs} +473 -208
  16. package/dist/chunk-Y4OD5SDF.cjs.map +1 -0
  17. package/dist/{client-mOcqT66b.d.ts → client-Bn-0nJ8y.d.ts} +9 -2
  18. package/dist/{client-DRS_ycOv.d.cts → client-Ca2wlmC4.d.cts} +9 -2
  19. package/dist/{index-BKyI_YQS.d.cts → index-Ct2Mh0zl.d.cts} +1 -1
  20. package/dist/{index-BrsbEcIx.d.ts → index-D50r0Gl0.d.ts} +1 -1
  21. package/dist/index.cjs +387 -387
  22. package/dist/index.d.cts +9 -7
  23. package/dist/index.d.ts +9 -7
  24. package/dist/index.js +2 -2
  25. package/dist/pagination/index.d.cts +2 -2
  26. package/dist/pagination/index.d.ts +2 -2
  27. package/dist/{sync-engine-DN0tSqtg.d.cts → sync-engine-21OlgS5_.d.cts} +5 -16
  28. package/dist/{sync-engine-BmE8-rhX.d.ts → sync-engine-D35aV8Zc.d.ts} +5 -16
  29. package/package.json +1 -1
  30. package/dist/chunk-4EESBP3A.cjs.map +0 -1
  31. package/dist/chunk-5TAY5I34.js.map +0 -1
  32. package/dist/chunk-BL3GFOZR.cjs.map +0 -1
  33. package/dist/chunk-CW5W3LEG.js.map +0 -1
@@ -2,7 +2,7 @@
2
2
 
3
3
  var chunk342BFYZZ_cjs = require('./chunk-342BFYZZ.cjs');
4
4
  var chunkUELAE75E_cjs = require('./chunk-UELAE75E.cjs');
5
- var chunkBL3GFOZR_cjs = require('./chunk-BL3GFOZR.cjs');
5
+ var chunkY4OD5SDF_cjs = require('./chunk-Y4OD5SDF.cjs');
6
6
  var chunkKV5SP7RP_cjs = require('./chunk-KV5SP7RP.cjs');
7
7
  var chunk32A6N4YK_cjs = require('./chunk-32A6N4YK.cjs');
8
8
  var chunkDZUJEN5N_cjs = require('./chunk-DZUJEN5N.cjs');
@@ -6035,7 +6035,6 @@ var require_dexie = chunkDZUJEN5N_cjs.__commonJS({
6035
6035
  // src/chat-stream.ts
6036
6036
  var INITIAL_RECONNECT_DELAY_MS = 1e3;
6037
6037
  var MAX_RECONNECT_DELAY_MS = 3e4;
6038
- var RECONNECT_BACKOFF_MULTIPLIER = 2;
6039
6038
  var MAX_CONSECUTIVE_AUTH_FAILURES = 3;
6040
6039
  var AuthChatStreamError = class extends Error {
6041
6040
  constructor(status) {
@@ -6049,24 +6048,63 @@ var ChatStreamConnection = class {
6049
6048
  this.chatId = chatId;
6050
6049
  this.options = options;
6051
6050
  this.onEmpty = onEmpty;
6051
+ this.supervisor = new chunkY4OD5SDF_cjs.ConnectionSupervisor({
6052
+ authRetryDelayMs: INITIAL_RECONNECT_DELAY_MS,
6053
+ baseReconnectDelayMs: INITIAL_RECONNECT_DELAY_MS,
6054
+ getToken: options.getToken,
6055
+ id: chatId,
6056
+ isAuthError: (error) => error instanceof AuthChatStreamError,
6057
+ kind: "chat-sse",
6058
+ maxConsecutiveAuthFailures: MAX_CONSECUTIVE_AUTH_FAILURES,
6059
+ maxReconnectDelayMs: MAX_RECONNECT_DELAY_MS,
6060
+ onFatalError: () => {
6061
+ const authError = new chunkKV5SP7RP_cjs.DvinaAuthenticationError("Chat SSE stream authentication failed permanently");
6062
+ this.options.onError?.(authError);
6063
+ this.close(authError);
6064
+ },
6065
+ dial: async (context) => {
6066
+ const url = new URL(`${this.options.baseUrl}/${encodeURIComponent(this.chatId)}/stream`);
6067
+ if (this.lastEventId) {
6068
+ url.searchParams.set("lastEventId", this.lastEventId);
6069
+ }
6070
+ const response = await fetch(url.toString(), {
6071
+ method: "GET",
6072
+ headers: {
6073
+ Accept: "text/event-stream",
6074
+ Authorization: `Bearer ${context.token}`,
6075
+ "Cache-Control": "no-cache",
6076
+ ...this.lastEventId ? { "Last-Event-ID": this.lastEventId } : {}
6077
+ },
6078
+ signal: context.signal
6079
+ });
6080
+ if (!response.ok) {
6081
+ if (response.status === 401 || response.status === 403) {
6082
+ throw new AuthChatStreamError(response.status);
6083
+ }
6084
+ throw new Error(`Chat stream connection failed: ${response.status} ${response.statusText}`);
6085
+ }
6086
+ if (!response.body) {
6087
+ throw new Error("Chat stream response has no body");
6088
+ }
6089
+ context.markConnected();
6090
+ await chunkY4OD5SDF_cjs.consumeSseStream(response.body, context.signal, {
6091
+ onChunk: () => context.markActivity(),
6092
+ onEventBlock: (block) => this.processEventBlock(block, context.requestTokenRefresh)
6093
+ });
6094
+ }
6095
+ });
6052
6096
  }
6053
- abortController;
6054
- consecutiveAuthFailures = 0;
6055
6097
  destroyed = false;
6056
6098
  lastEventId;
6057
- needsForceRefresh = false;
6058
- reconnectDelay = INITIAL_RECONNECT_DELAY_MS;
6059
- reconnectTimer;
6060
- shouldReconnect = false;
6061
6099
  subscribers = /* @__PURE__ */ new Set();
6100
+ supervisor;
6062
6101
  addSubscriber(subscriber) {
6063
6102
  if (this.destroyed) {
6064
6103
  throw new Error(`Chat stream '${this.chatId}' is closed`);
6065
6104
  }
6066
6105
  this.subscribers.add(subscriber);
6067
- if (!this.shouldReconnect) {
6068
- this.shouldReconnect = true;
6069
- void this.doConnect();
6106
+ if (this.subscribers.size === 1) {
6107
+ void this.supervisor.start();
6070
6108
  }
6071
6109
  }
6072
6110
  removeSubscriber(subscriber) {
@@ -6075,17 +6113,18 @@ var ChatStreamConnection = class {
6075
6113
  this.close();
6076
6114
  }
6077
6115
  }
6078
- close(error) {
6079
- this.shouldReconnect = false;
6080
- this.destroyed = true;
6081
- if (this.reconnectTimer) {
6082
- clearTimeout(this.reconnectTimer);
6083
- this.reconnectTimer = void 0;
6116
+ reconnect() {
6117
+ if (this.destroyed || this.subscribers.size === 0) {
6118
+ return;
6084
6119
  }
6085
- if (this.abortController) {
6086
- this.abortController.abort();
6087
- this.abortController = void 0;
6120
+ this.supervisor.reconnect();
6121
+ }
6122
+ close(error) {
6123
+ if (this.destroyed) {
6124
+ return;
6088
6125
  }
6126
+ this.destroyed = true;
6127
+ this.supervisor.close();
6089
6128
  for (const subscriber of Array.from(this.subscribers)) {
6090
6129
  subscriber.finish(error);
6091
6130
  }
@@ -6095,94 +6134,7 @@ var ChatStreamConnection = class {
6095
6134
  get isDestroyed() {
6096
6135
  return this.destroyed;
6097
6136
  }
6098
- async doConnect() {
6099
- if (!this.shouldReconnect || this.destroyed || this.subscribers.size === 0) {
6100
- return;
6101
- }
6102
- this.abortController = new AbortController();
6103
- try {
6104
- const forceRefresh = this.needsForceRefresh;
6105
- this.needsForceRefresh = false;
6106
- const token = await this.options.getToken(forceRefresh ? { forceRefresh: true } : void 0);
6107
- const url = new URL(`${this.options.baseUrl}/${encodeURIComponent(this.chatId)}/stream`);
6108
- if (this.lastEventId) {
6109
- url.searchParams.set("lastEventId", this.lastEventId);
6110
- }
6111
- const response = await fetch(url.toString(), {
6112
- method: "GET",
6113
- headers: {
6114
- Accept: "text/event-stream",
6115
- Authorization: `Bearer ${token}`,
6116
- "Cache-Control": "no-cache",
6117
- ...this.lastEventId ? { "Last-Event-ID": this.lastEventId } : {}
6118
- },
6119
- signal: this.abortController.signal
6120
- });
6121
- if (!response.ok) {
6122
- if (response.status === 401 || response.status === 403) {
6123
- throw new AuthChatStreamError(response.status);
6124
- }
6125
- throw new Error(`Chat stream connection failed: ${response.status} ${response.statusText}`);
6126
- }
6127
- if (!response.body) {
6128
- throw new Error("Chat stream response has no body");
6129
- }
6130
- this.consecutiveAuthFailures = 0;
6131
- this.reconnectDelay = INITIAL_RECONNECT_DELAY_MS;
6132
- await this.parseSseStream(response.body, this.abortController.signal);
6133
- } catch (error) {
6134
- if (error.name === "AbortError") {
6135
- return;
6136
- }
6137
- if (!this.shouldReconnect || this.destroyed || this.subscribers.size === 0) {
6138
- return;
6139
- }
6140
- const isAuthError2 = error instanceof AuthChatStreamError;
6141
- if (isAuthError2) {
6142
- this.consecutiveAuthFailures += 1;
6143
- if (this.consecutiveAuthFailures >= MAX_CONSECUTIVE_AUTH_FAILURES) {
6144
- const authError = new chunkKV5SP7RP_cjs.DvinaAuthenticationError("Chat SSE stream authentication failed permanently");
6145
- this.options.onError?.(authError);
6146
- this.close(authError);
6147
- return;
6148
- }
6149
- this.needsForceRefresh = true;
6150
- }
6151
- const delay = isAuthError2 ? INITIAL_RECONNECT_DELAY_MS : this.reconnectDelay;
6152
- this.scheduleReconnect(delay);
6153
- if (!isAuthError2) {
6154
- this.reconnectDelay = Math.min(
6155
- this.reconnectDelay * RECONNECT_BACKOFF_MULTIPLIER,
6156
- MAX_RECONNECT_DELAY_MS
6157
- );
6158
- }
6159
- }
6160
- }
6161
- async parseSseStream(body, signal) {
6162
- const reader = body.getReader();
6163
- const decoder = new TextDecoder();
6164
- let buffer = "";
6165
- try {
6166
- while (!signal.aborted && this.shouldReconnect && !this.destroyed) {
6167
- const { done, value } = await reader.read();
6168
- if (done) {
6169
- break;
6170
- }
6171
- buffer += decoder.decode(value, { stream: true });
6172
- const parts = buffer.split(/(?:\r\n|\r|\n){2}/);
6173
- buffer = parts.pop() ?? "";
6174
- for (const part of parts) {
6175
- this.processEventBlock(part.trim());
6176
- }
6177
- }
6178
- } finally {
6179
- reader.releaseLock();
6180
- }
6181
- if (this.shouldReconnect && !this.destroyed && this.subscribers.size > 0) {
6182
- this.scheduleReconnect(this.reconnectDelay);
6183
- }
6184
- }
6185
- processEventBlock(block) {
6137
+ processEventBlock(block, requestTokenRefresh) {
6186
6138
  if (!block || block.startsWith(":")) {
6187
6139
  return;
6188
6140
  }
@@ -6199,8 +6151,8 @@ var ChatStreamConnection = class {
6199
6151
  }
6200
6152
  }
6201
6153
  if (eventType === "token-expired") {
6202
- this.needsForceRefresh = true;
6203
- return;
6154
+ requestTokenRefresh();
6155
+ throw new AuthChatStreamError(401);
6204
6156
  }
6205
6157
  if (!eventId || dataLines.length === 0) {
6206
6158
  return;
@@ -6217,40 +6169,64 @@ var ChatStreamConnection = class {
6217
6169
  subscriber.push(value);
6218
6170
  }
6219
6171
  }
6220
- scheduleReconnect(delay) {
6221
- if (!this.shouldReconnect || this.destroyed || this.subscribers.size === 0) {
6222
- return;
6223
- }
6224
- if (this.reconnectTimer) {
6225
- clearTimeout(this.reconnectTimer);
6226
- }
6227
- this.reconnectTimer = setTimeout(() => {
6228
- this.reconnectTimer = void 0;
6229
- void this.doConnect();
6230
- }, delay);
6231
- }
6232
6172
  };
6233
6173
  var ActiveChatStreamConnection = class {
6234
6174
  constructor(options, onEmpty) {
6235
6175
  this.options = options;
6236
6176
  this.onEmpty = onEmpty;
6177
+ this.supervisor = new chunkY4OD5SDF_cjs.ConnectionSupervisor({
6178
+ authRetryDelayMs: INITIAL_RECONNECT_DELAY_MS,
6179
+ baseReconnectDelayMs: INITIAL_RECONNECT_DELAY_MS,
6180
+ getToken: options.getToken,
6181
+ id: "active",
6182
+ isAuthError: (error) => error instanceof AuthChatStreamError,
6183
+ kind: "active-chat-sse",
6184
+ maxConsecutiveAuthFailures: MAX_CONSECUTIVE_AUTH_FAILURES,
6185
+ maxReconnectDelayMs: MAX_RECONNECT_DELAY_MS,
6186
+ onFatalError: () => {
6187
+ const authError = new chunkKV5SP7RP_cjs.DvinaAuthenticationError(
6188
+ "Active chat SSE stream authentication failed permanently"
6189
+ );
6190
+ this.options.onError?.(authError);
6191
+ this.close(authError);
6192
+ },
6193
+ dial: async (context) => {
6194
+ const response = await fetch(new URL(`${this.options.baseUrl}/active`).toString(), {
6195
+ method: "GET",
6196
+ headers: {
6197
+ Accept: "text/event-stream",
6198
+ Authorization: `Bearer ${context.token}`,
6199
+ "Cache-Control": "no-cache"
6200
+ },
6201
+ signal: context.signal
6202
+ });
6203
+ if (!response.ok) {
6204
+ if (response.status === 401 || response.status === 403) {
6205
+ throw new AuthChatStreamError(response.status);
6206
+ }
6207
+ throw new Error(`Active chat stream connection failed: ${response.status} ${response.statusText}`);
6208
+ }
6209
+ if (!response.body) {
6210
+ throw new Error("Active chat stream response has no body");
6211
+ }
6212
+ context.markConnected();
6213
+ await chunkY4OD5SDF_cjs.consumeSseStream(response.body, context.signal, {
6214
+ onChunk: () => context.markActivity(),
6215
+ onEventBlock: (block) => this.processEventBlock(block, context.requestTokenRefresh)
6216
+ });
6217
+ }
6218
+ });
6237
6219
  }
6238
- abortController;
6239
- consecutiveAuthFailures = 0;
6240
6220
  destroyed = false;
6241
- needsForceRefresh = false;
6242
- reconnectDelay = INITIAL_RECONNECT_DELAY_MS;
6243
- reconnectTimer;
6244
- shouldReconnect = false;
6245
6221
  subscribers = /* @__PURE__ */ new Set();
6222
+ supervisor;
6246
6223
  addSubscriber(subscriber) {
6247
6224
  if (this.destroyed) {
6248
6225
  throw new Error("Active chat stream is closed");
6249
6226
  }
6250
6227
  this.subscribers.add(subscriber);
6251
- if (!this.shouldReconnect) {
6252
- this.shouldReconnect = true;
6253
- void this.doConnect();
6228
+ if (this.subscribers.size === 1) {
6229
+ void this.supervisor.start();
6254
6230
  }
6255
6231
  }
6256
6232
  removeSubscriber(subscriber) {
@@ -6259,17 +6235,18 @@ var ActiveChatStreamConnection = class {
6259
6235
  this.close();
6260
6236
  }
6261
6237
  }
6262
- close(error) {
6263
- this.shouldReconnect = false;
6264
- this.destroyed = true;
6265
- if (this.reconnectTimer) {
6266
- clearTimeout(this.reconnectTimer);
6267
- this.reconnectTimer = void 0;
6238
+ reconnect() {
6239
+ if (this.destroyed || this.subscribers.size === 0) {
6240
+ return;
6268
6241
  }
6269
- if (this.abortController) {
6270
- this.abortController.abort();
6271
- this.abortController = void 0;
6242
+ this.supervisor.reconnect();
6243
+ }
6244
+ close(error) {
6245
+ if (this.destroyed) {
6246
+ return;
6272
6247
  }
6248
+ this.destroyed = true;
6249
+ this.supervisor.close();
6273
6250
  for (const subscriber of Array.from(this.subscribers)) {
6274
6251
  subscriber.finish(error);
6275
6252
  }
@@ -6279,91 +6256,7 @@ var ActiveChatStreamConnection = class {
6279
6256
  get isDestroyed() {
6280
6257
  return this.destroyed;
6281
6258
  }
6282
- async doConnect() {
6283
- if (!this.shouldReconnect || this.destroyed || this.subscribers.size === 0) {
6284
- return;
6285
- }
6286
- this.abortController = new AbortController();
6287
- try {
6288
- const forceRefresh = this.needsForceRefresh;
6289
- this.needsForceRefresh = false;
6290
- const token = await this.options.getToken(forceRefresh ? { forceRefresh: true } : void 0);
6291
- const response = await fetch(new URL(`${this.options.baseUrl}/active`).toString(), {
6292
- method: "GET",
6293
- headers: {
6294
- Accept: "text/event-stream",
6295
- Authorization: `Bearer ${token}`,
6296
- "Cache-Control": "no-cache"
6297
- },
6298
- signal: this.abortController.signal
6299
- });
6300
- if (!response.ok) {
6301
- if (response.status === 401 || response.status === 403) {
6302
- throw new AuthChatStreamError(response.status);
6303
- }
6304
- throw new Error(`Active chat stream connection failed: ${response.status} ${response.statusText}`);
6305
- }
6306
- if (!response.body) {
6307
- throw new Error("Active chat stream response has no body");
6308
- }
6309
- this.consecutiveAuthFailures = 0;
6310
- this.reconnectDelay = INITIAL_RECONNECT_DELAY_MS;
6311
- await this.parseSseStream(response.body, this.abortController.signal);
6312
- } catch (error) {
6313
- if (error.name === "AbortError") {
6314
- return;
6315
- }
6316
- if (!this.shouldReconnect || this.destroyed || this.subscribers.size === 0) {
6317
- return;
6318
- }
6319
- const isAuthError2 = error instanceof AuthChatStreamError;
6320
- if (isAuthError2) {
6321
- this.consecutiveAuthFailures += 1;
6322
- if (this.consecutiveAuthFailures >= MAX_CONSECUTIVE_AUTH_FAILURES) {
6323
- const authError = new chunkKV5SP7RP_cjs.DvinaAuthenticationError(
6324
- "Active chat SSE stream authentication failed permanently"
6325
- );
6326
- this.options.onError?.(authError);
6327
- this.close(authError);
6328
- return;
6329
- }
6330
- this.needsForceRefresh = true;
6331
- }
6332
- const delay = isAuthError2 ? INITIAL_RECONNECT_DELAY_MS : this.reconnectDelay;
6333
- this.scheduleReconnect(delay);
6334
- if (!isAuthError2) {
6335
- this.reconnectDelay = Math.min(
6336
- this.reconnectDelay * RECONNECT_BACKOFF_MULTIPLIER,
6337
- MAX_RECONNECT_DELAY_MS
6338
- );
6339
- }
6340
- }
6341
- }
6342
- async parseSseStream(body, signal) {
6343
- const reader = body.getReader();
6344
- const decoder = new TextDecoder();
6345
- let buffer = "";
6346
- try {
6347
- while (!signal.aborted && this.shouldReconnect && !this.destroyed) {
6348
- const { done, value } = await reader.read();
6349
- if (done) {
6350
- break;
6351
- }
6352
- buffer += decoder.decode(value, { stream: true });
6353
- const parts = buffer.split(/(?:\r\n|\r|\n){2}/);
6354
- buffer = parts.pop() ?? "";
6355
- for (const part of parts) {
6356
- this.processEventBlock(part.trim());
6357
- }
6358
- }
6359
- } finally {
6360
- reader.releaseLock();
6361
- }
6362
- if (this.shouldReconnect && !this.destroyed && this.subscribers.size > 0) {
6363
- this.scheduleReconnect(this.reconnectDelay);
6364
- }
6365
- }
6366
- processEventBlock(block) {
6259
+ processEventBlock(block, requestTokenRefresh) {
6367
6260
  if (!block || block.startsWith(":")) {
6368
6261
  return;
6369
6262
  }
@@ -6377,8 +6270,8 @@ var ActiveChatStreamConnection = class {
6377
6270
  }
6378
6271
  }
6379
6272
  if (eventType === "token-expired") {
6380
- this.needsForceRefresh = true;
6381
- return;
6273
+ requestTokenRefresh();
6274
+ throw new AuthChatStreamError(401);
6382
6275
  }
6383
6276
  if (eventType !== "active" || dataLines.length === 0) {
6384
6277
  return;
@@ -6397,18 +6290,6 @@ var ActiveChatStreamConnection = class {
6397
6290
  subscriber.push(value);
6398
6291
  }
6399
6292
  }
6400
- scheduleReconnect(delay) {
6401
- if (!this.shouldReconnect || this.destroyed || this.subscribers.size === 0) {
6402
- return;
6403
- }
6404
- if (this.reconnectTimer) {
6405
- clearTimeout(this.reconnectTimer);
6406
- }
6407
- this.reconnectTimer = setTimeout(() => {
6408
- this.reconnectTimer = void 0;
6409
- void this.doConnect();
6410
- }, delay);
6411
- }
6412
6293
  };
6413
6294
  function createChatStreamClient(options) {
6414
6295
  const connections = /* @__PURE__ */ new Map();
@@ -6577,6 +6458,12 @@ function createChatStreamClient(options) {
6577
6458
  }
6578
6459
  };
6579
6460
  }
6461
+ function reconnectAll() {
6462
+ for (const connection of connections.values()) {
6463
+ connection.reconnect();
6464
+ }
6465
+ activeConnection?.reconnect();
6466
+ }
6580
6467
  function destroy() {
6581
6468
  for (const connection of Array.from(connections.values())) {
6582
6469
  connection.close();
@@ -6591,6 +6478,7 @@ function createChatStreamClient(options) {
6591
6478
  },
6592
6479
  listen,
6593
6480
  stream,
6481
+ reconnectAll,
6594
6482
  destroy
6595
6483
  };
6596
6484
  }
@@ -7338,20 +7226,12 @@ function createWsTransport(options) {
7338
7226
  let lastCloseCode = null;
7339
7227
  let nextToken;
7340
7228
  let currentToken;
7341
- let refreshPromise = null;
7342
7229
  async function refreshToken() {
7343
- if (!refreshPromise) {
7344
- const failedToken = currentToken;
7345
- refreshPromise = options.getToken({ forceRefresh: true }).then((token) => {
7346
- if (!token || token === failedToken) {
7347
- throw new chunkKV5SP7RP_cjs.DvinaAuthenticationError("Token refresh did not produce a new token", failedToken);
7348
- }
7349
- nextToken = token;
7350
- }).finally(() => {
7351
- refreshPromise = null;
7352
- });
7230
+ const token = await chunkY4OD5SDF_cjs.refreshTokenSingleFlight(options.getToken, currentToken);
7231
+ if (!token) {
7232
+ throw new chunkKV5SP7RP_cjs.DvinaAuthenticationError("Token refresh did not produce a new token", currentToken);
7353
7233
  }
7354
- return refreshPromise;
7234
+ nextToken = token;
7355
7235
  }
7356
7236
  async function prepareSubscriptionConnection() {
7357
7237
  const token = nextToken ?? await options.getToken();
@@ -7399,7 +7279,7 @@ function createWsTransport(options) {
7399
7279
  }
7400
7280
  });
7401
7281
  function subscribe(document2, variables) {
7402
- const query = chunkBL3GFOZR_cjs.print(document2);
7282
+ const query = chunkY4OD5SDF_cjs.print(document2);
7403
7283
  const subscribeOnce = () => ({
7404
7284
  [Symbol.asyncIterator]() {
7405
7285
  const queue = [];
@@ -8087,35 +7967,47 @@ var AuthSseError = class extends Error {
8087
7967
  };
8088
7968
  var INITIAL_RECONNECT_DELAY_MS2 = 1e3;
8089
7969
  var MAX_RECONNECT_DELAY_MS2 = 3e4;
8090
- var RECONNECT_BACKOFF_MULTIPLIER2 = 2;
8091
7970
  var MAX_CONSECUTIVE_AUTH_FAILURES2 = 3;
8092
7971
  var SUBSCRIPTION_REFRESH_INTERVAL_MS = 5 * 60 * 1e3;
7972
+ function mapSupervisorState(state) {
7973
+ if (state === "connected") {
7974
+ return "connected";
7975
+ }
7976
+ if (state === "connecting") {
7977
+ return "connecting";
7978
+ }
7979
+ return "disconnected";
7980
+ }
8093
7981
  function createSseTransport(options) {
8094
- let abortController;
8095
7982
  let isConnected = false;
8096
- let reconnectDelay = INITIAL_RECONNECT_DELAY_MS2;
8097
- let reconnectTimer;
8098
- let refreshTimer;
8099
- let shouldReconnect = false;
8100
7983
  let currentLastSyncId;
8101
- let needsForceRefresh = false;
8102
- let consecutiveAuthFailures = 0;
7984
+ let refreshTimer;
8103
7985
  let hasConnectedOnce = false;
7986
+ let lastLegacyState;
8104
7987
  const activeSubscriptions = /* @__PURE__ */ new Map();
8105
- async function connect(lastSyncId) {
8106
- disconnect();
8107
- shouldReconnect = true;
8108
- currentLastSyncId = lastSyncId;
8109
- await doConnect();
8110
- }
8111
- async function doConnect() {
8112
- if (!shouldReconnect) return;
8113
- abortController = new AbortController();
8114
- options.onStateChange?.("connecting");
8115
- try {
8116
- const forceRefresh = needsForceRefresh;
8117
- needsForceRefresh = false;
8118
- const token = await options.getToken(forceRefresh ? { forceRefresh: true } : void 0);
7988
+ const emitLegacyState = (state) => {
7989
+ const mapped = mapSupervisorState(state);
7990
+ if (mapped === lastLegacyState) {
7991
+ return;
7992
+ }
7993
+ lastLegacyState = mapped;
7994
+ isConnected = mapped === "connected";
7995
+ if (!isConnected) {
7996
+ stopSubscriptionRefresh();
7997
+ }
7998
+ options.onStateChange?.(mapped);
7999
+ };
8000
+ const supervisor = new chunkY4OD5SDF_cjs.ConnectionSupervisor({
8001
+ authRetryDelayMs: INITIAL_RECONNECT_DELAY_MS2,
8002
+ baseReconnectDelayMs: INITIAL_RECONNECT_DELAY_MS2,
8003
+ getToken: options.getToken,
8004
+ id: "primary",
8005
+ isAuthError: (error) => error instanceof AuthSseError,
8006
+ kind: "sync-sse",
8007
+ maxConsecutiveAuthFailures: MAX_CONSECUTIVE_AUTH_FAILURES2,
8008
+ maxReconnectDelayMs: MAX_RECONNECT_DELAY_MS2,
8009
+ onStateChange: (snapshot) => emitLegacyState(snapshot.state),
8010
+ dial: async (context) => {
8119
8011
  const url = new URL(options.url);
8120
8012
  if (currentLastSyncId && currentLastSyncId !== "0") {
8121
8013
  url.searchParams.set("lastSyncId", currentLastSyncId);
@@ -8123,11 +8015,11 @@ function createSseTransport(options) {
8123
8015
  const response = await fetch(url.toString(), {
8124
8016
  method: "GET",
8125
8017
  headers: {
8126
- Authorization: `Bearer ${token}`,
8018
+ Authorization: `Bearer ${context.token}`,
8127
8019
  Accept: "text/event-stream",
8128
8020
  "Cache-Control": "no-cache"
8129
8021
  },
8130
- signal: abortController.signal
8022
+ signal: context.signal
8131
8023
  });
8132
8024
  if (!response.ok) {
8133
8025
  if (response.status === 401 || response.status === 403) {
@@ -8138,73 +8030,100 @@ function createSseTransport(options) {
8138
8030
  if (!response.body) {
8139
8031
  throw new Error("SSE response has no body");
8140
8032
  }
8141
- isConnected = true;
8142
- consecutiveAuthFailures = 0;
8143
- reconnectDelay = INITIAL_RECONNECT_DELAY_MS2;
8144
- options.onStateChange?.("connected");
8145
8033
  const isReconnect = hasConnectedOnce;
8146
8034
  hasConnectedOnce = true;
8147
- await syncActiveSubscriptions(token);
8035
+ context.markConnected();
8036
+ await syncActiveSubscriptions(context.token);
8148
8037
  startSubscriptionRefresh();
8149
8038
  if (isReconnect && activeSubscriptions.size > 0) {
8150
8039
  options.onReconnect?.();
8151
8040
  }
8152
- await parseSseStream(response.body, abortController.signal);
8153
- } catch (err) {
8154
- if (err.name === "AbortError") {
8155
- return;
8156
- }
8157
- isConnected = false;
8158
- stopSubscriptionRefresh();
8041
+ await chunkY4OD5SDF_cjs.consumeSseStream(response.body, context.signal, {
8042
+ onChunk: () => context.markActivity(),
8043
+ onEventBlock: (block) => processEventBlock(block, context.requestTokenRefresh)
8044
+ });
8045
+ }
8046
+ });
8047
+ async function connect(lastSyncId) {
8048
+ currentLastSyncId = lastSyncId;
8049
+ disconnect();
8050
+ await supervisor.start();
8051
+ }
8052
+ function disconnect() {
8053
+ supervisor.stop();
8054
+ isConnected = false;
8055
+ stopSubscriptionRefresh();
8056
+ if (lastLegacyState !== "disconnected") {
8057
+ lastLegacyState = "disconnected";
8159
8058
  options.onStateChange?.("disconnected");
8160
- if (shouldReconnect) {
8161
- const isAuth = err instanceof AuthSseError;
8162
- if (isAuth) {
8163
- consecutiveAuthFailures++;
8164
- if (consecutiveAuthFailures >= MAX_CONSECUTIVE_AUTH_FAILURES2) {
8165
- disconnect();
8166
- return;
8167
- }
8168
- needsForceRefresh = true;
8169
- }
8170
- const delay = isAuth ? INITIAL_RECONNECT_DELAY_MS2 : reconnectDelay;
8171
- reconnectTimer = setTimeout(() => {
8172
- doConnect();
8173
- }, delay);
8174
- if (!isAuth) {
8175
- reconnectDelay = Math.min(reconnectDelay * RECONNECT_BACKOFF_MULTIPLIER2, MAX_RECONNECT_DELAY_MS2);
8176
- }
8177
- }
8178
8059
  }
8179
8060
  }
8180
- async function parseSseStream(body, signal) {
8181
- const reader = body.getReader();
8182
- const decoder = new TextDecoder();
8183
- let buffer = "";
8184
- try {
8185
- while (!signal.aborted) {
8186
- const { done, value } = await reader.read();
8187
- if (done) break;
8188
- buffer += decoder.decode(value, { stream: true });
8189
- const parts = buffer.split(/(?:\r\n|\r|\n){2}/);
8190
- buffer = parts.pop() ?? "";
8191
- for (const part of parts) {
8192
- processEventBlock(part.trim());
8193
- }
8194
- }
8195
- } finally {
8196
- reader.releaseLock();
8061
+ function reconnect() {
8062
+ supervisor.reconnect();
8063
+ }
8064
+ function subscribe(descriptor) {
8065
+ activeSubscriptions.set(descriptor.id, descriptor);
8066
+ if (isConnected) {
8067
+ startSubscriptionRefresh();
8197
8068
  }
8198
- if (shouldReconnect) {
8199
- isConnected = false;
8069
+ void postMessage({ type: "subscribe", subscription: descriptor });
8070
+ }
8071
+ function unsubscribe(subscriptionId) {
8072
+ activeSubscriptions.delete(subscriptionId);
8073
+ if (activeSubscriptions.size === 0) {
8200
8074
  stopSubscriptionRefresh();
8201
- options.onStateChange?.("disconnected");
8202
- reconnectTimer = setTimeout(() => {
8203
- doConnect();
8204
- }, reconnectDelay);
8205
8075
  }
8076
+ void postMessage({ type: "unsubscribe", subscriptionId });
8077
+ }
8078
+ function startSubscriptionRefresh() {
8079
+ if (!isConnected || activeSubscriptions.size === 0 || refreshTimer) {
8080
+ return;
8081
+ }
8082
+ refreshTimer = setInterval(() => {
8083
+ void syncActiveSubscriptions();
8084
+ }, SUBSCRIPTION_REFRESH_INTERVAL_MS);
8085
+ }
8086
+ function stopSubscriptionRefresh() {
8087
+ if (!refreshTimer) {
8088
+ return;
8089
+ }
8090
+ clearInterval(refreshTimer);
8091
+ refreshTimer = void 0;
8092
+ }
8093
+ async function syncActiveSubscriptions(token) {
8094
+ if (activeSubscriptions.size === 0) {
8095
+ return;
8096
+ }
8097
+ const resolvedToken = token ?? await options.getToken().catch(() => void 0);
8098
+ if (!resolvedToken) {
8099
+ return;
8100
+ }
8101
+ await Promise.all(
8102
+ Array.from(activeSubscriptions.values()).map(
8103
+ (descriptor) => postMessage({ type: "subscribe", subscription: descriptor }, resolvedToken).catch(() => {
8104
+ })
8105
+ )
8106
+ );
8206
8107
  }
8207
- function processEventBlock(block) {
8108
+ async function postMessage(body, token) {
8109
+ let resolvedToken = token ?? await options.getToken();
8110
+ const url = new URL(options.url);
8111
+ for (let attempt = 0; attempt < 2; attempt += 1) {
8112
+ const response = await fetch(url.toString(), {
8113
+ method: "POST",
8114
+ headers: {
8115
+ Authorization: `Bearer ${resolvedToken}`,
8116
+ "Content-Type": "application/json"
8117
+ },
8118
+ body: JSON.stringify(body)
8119
+ });
8120
+ if (response.status !== 401 && response.status !== 403) {
8121
+ return;
8122
+ }
8123
+ resolvedToken = await chunkY4OD5SDF_cjs.refreshTokenSingleFlight(options.getToken, resolvedToken);
8124
+ }
8125
+ }
8126
+ function processEventBlock(block, requestTokenRefresh) {
8208
8127
  if (!block || block.startsWith(":")) {
8209
8128
  return;
8210
8129
  }
@@ -8221,8 +8140,8 @@ function createSseTransport(options) {
8221
8140
  }
8222
8141
  }
8223
8142
  if (eventType === "token-expired") {
8224
- needsForceRefresh = true;
8225
- return;
8143
+ requestTokenRefresh();
8144
+ throw new AuthSseError(401);
8226
8145
  }
8227
8146
  if (eventType === "full-resync") {
8228
8147
  options.onFullResync?.();
@@ -8239,7 +8158,9 @@ function createSseTransport(options) {
8239
8158
  }
8240
8159
  return;
8241
8160
  }
8242
- if (!eventId) return;
8161
+ if (!eventId) {
8162
+ return;
8163
+ }
8243
8164
  currentLastSyncId = eventId;
8244
8165
  if (eventType === "cursor") {
8245
8166
  options.onCursor?.(eventId);
@@ -8256,82 +8177,10 @@ function createSseTransport(options) {
8256
8177
  }
8257
8178
  }
8258
8179
  }
8259
- function disconnect() {
8260
- shouldReconnect = false;
8261
- isConnected = false;
8262
- stopSubscriptionRefresh();
8263
- if (reconnectTimer) {
8264
- clearTimeout(reconnectTimer);
8265
- reconnectTimer = void 0;
8266
- }
8267
- if (abortController) {
8268
- abortController.abort();
8269
- abortController = void 0;
8270
- }
8271
- options.onStateChange?.("disconnected");
8272
- }
8273
- function subscribe(descriptor) {
8274
- activeSubscriptions.set(descriptor.id, descriptor);
8275
- if (isConnected) {
8276
- startSubscriptionRefresh();
8277
- }
8278
- postMessage({ type: "subscribe", subscription: descriptor }).catch(() => {
8279
- });
8280
- }
8281
- function unsubscribe(subscriptionId) {
8282
- activeSubscriptions.delete(subscriptionId);
8283
- if (activeSubscriptions.size === 0) {
8284
- stopSubscriptionRefresh();
8285
- }
8286
- postMessage({ type: "unsubscribe", subscriptionId }).catch(() => {
8287
- });
8288
- }
8289
- function startSubscriptionRefresh() {
8290
- if (!isConnected || activeSubscriptions.size === 0 || refreshTimer) {
8291
- return;
8292
- }
8293
- refreshTimer = setInterval(() => {
8294
- syncActiveSubscriptions().catch(() => {
8295
- });
8296
- }, SUBSCRIPTION_REFRESH_INTERVAL_MS);
8297
- }
8298
- function stopSubscriptionRefresh() {
8299
- if (!refreshTimer) {
8300
- return;
8301
- }
8302
- clearInterval(refreshTimer);
8303
- refreshTimer = void 0;
8304
- }
8305
- async function syncActiveSubscriptions(token) {
8306
- if (activeSubscriptions.size === 0) {
8307
- return;
8308
- }
8309
- const resolvedToken = token ?? await options.getToken().catch(() => void 0);
8310
- if (!resolvedToken) {
8311
- return;
8312
- }
8313
- await Promise.all(
8314
- Array.from(activeSubscriptions.values()).map(
8315
- (descriptor) => postMessage({ type: "subscribe", subscription: descriptor }, resolvedToken).catch(() => {
8316
- })
8317
- )
8318
- );
8319
- }
8320
- async function postMessage(body, token) {
8321
- const resolvedToken = token ?? await options.getToken();
8322
- const url = new URL(options.url);
8323
- await fetch(url.toString(), {
8324
- method: "POST",
8325
- headers: {
8326
- Authorization: `Bearer ${resolvedToken}`,
8327
- "Content-Type": "application/json"
8328
- },
8329
- body: JSON.stringify(body)
8330
- });
8331
- }
8332
8180
  return {
8333
8181
  connect,
8334
8182
  disconnect,
8183
+ reconnect,
8335
8184
  subscribe,
8336
8185
  unsubscribe,
8337
8186
  get connected() {
@@ -10242,6 +10091,8 @@ async function applyRemoteCacheEpoch(db, engine, syncPolicyUrl, getToken) {
10242
10091
  function createLazySyncEngine(httpTransport, sseUrl, syncPolicyUrl, getToken, getDb) {
10243
10092
  let realEngine;
10244
10093
  let initPromise;
10094
+ let activeSseTransport;
10095
+ let shouldKeepSyncRunning = false;
10245
10096
  async function getEngine() {
10246
10097
  if (realEngine) return realEngine;
10247
10098
  if (initPromise) return initPromise;
@@ -10274,10 +10125,12 @@ function createLazySyncEngine(httpTransport, sseUrl, syncPolicyUrl, getToken, ge
10274
10125
  }
10275
10126
  });
10276
10127
  sseTransport = transport;
10128
+ activeSseTransport = transport;
10277
10129
  }
10278
10130
  realEngine = new SyncEngine({ db, httpTransport, sseTransport });
10279
10131
  await applyRemoteCacheEpoch(db, realEngine, syncPolicyUrl, getToken);
10280
10132
  if (sseTransport) {
10133
+ shouldKeepSyncRunning = true;
10281
10134
  realEngine.startSync().catch(() => {
10282
10135
  });
10283
10136
  }
@@ -10323,11 +10176,19 @@ function createLazySyncEngine(httpTransport, sseUrl, syncPolicyUrl, getToken, ge
10323
10176
  };
10324
10177
  lazy.startSync = async function() {
10325
10178
  const engine = await getEngine();
10179
+ shouldKeepSyncRunning = true;
10326
10180
  return engine.startSync();
10327
10181
  };
10328
10182
  lazy.stopSync = function() {
10183
+ shouldKeepSyncRunning = false;
10329
10184
  realEngine?.stopSync();
10330
10185
  };
10186
+ lazy.reconnectActiveSync = function() {
10187
+ if (!shouldKeepSyncRunning) {
10188
+ return;
10189
+ }
10190
+ activeSseTransport?.reconnect();
10191
+ };
10331
10192
  lazy.processSyncEvent = async function(event) {
10332
10193
  const engine = await getEngine();
10333
10194
  return engine.processSyncEvent(event);
@@ -10516,6 +10377,7 @@ function isBrowserRuntime() {
10516
10377
  var DEFAULT_BASE_URL = "api.dvina.ai";
10517
10378
  var DB_INIT_TOKEN_POLL_INTERVAL_MS = 100;
10518
10379
  var DB_INIT_TOKEN_TIMEOUT_MS = 15e3;
10380
+ var LIFECYCLE_HINT_DEBOUNCE_MS = 250;
10519
10381
  function resolveGetToken(options) {
10520
10382
  if ("getToken" in options && options.getToken) {
10521
10383
  return options.getToken;
@@ -10565,7 +10427,7 @@ function createDvinaClient(options) {
10565
10427
  const getToken = resolveGetToken(options);
10566
10428
  const getLanguage = resolveLanguage(options.language);
10567
10429
  const getUserTimezone = resolveUserTimezone();
10568
- const httpTransport = chunkBL3GFOZR_cjs.createHttpTransport({
10430
+ const httpTransport = chunkY4OD5SDF_cjs.createHttpTransport({
10569
10431
  url: httpUrl,
10570
10432
  getToken,
10571
10433
  getLanguage,
@@ -10613,6 +10475,7 @@ function createDvinaClient(options) {
10613
10475
  });
10614
10476
  }
10615
10477
  const syncEngine = createLazySyncEngine(httpTransport, sseUrl, syncPolicyUrl, getToken, getDb);
10478
+ const recoverableSyncEngine = syncEngine;
10616
10479
  const request = async (document2, variables, _options) => {
10617
10480
  return syncEngine.query(document2, variables);
10618
10481
  };
@@ -10623,7 +10486,22 @@ function createDvinaClient(options) {
10623
10486
  const billingBase = hasProtocol ? billingOverride.replace(/\/+$/, "") : `${httpProtocol}://${billingOverride ?? baseUrl.replace(/^api\./, "billing.")}`;
10624
10487
  const billingHttpUrl = `${billingBase}/graphql`;
10625
10488
  const billingSseUrl = `${billingBase}/subscriptions/stream`;
10626
- const billing = new chunkBL3GFOZR_cjs.BillingClient({ billingHttpUrl, billingSseUrl, getToken, onError: options.onError });
10489
+ const billing = new chunkY4OD5SDF_cjs.BillingClient({ billingHttpUrl, billingSseUrl, getToken, onError: options.onError });
10490
+ let lifecycleHintTimer;
10491
+ const lifecycle = {
10492
+ hint(_reason) {
10493
+ if (lifecycleHintTimer) {
10494
+ return;
10495
+ }
10496
+ lifecycleHintTimer = setTimeout(() => {
10497
+ lifecycleHintTimer = void 0;
10498
+ recoverableSyncEngine.reconnectActiveSync();
10499
+ chatStream.reconnectAll();
10500
+ wsTransport?.terminate();
10501
+ billing.reconnectAll();
10502
+ }, LIFECYCLE_HINT_DEBOUNCE_MS);
10503
+ }
10504
+ };
10627
10505
  return {
10628
10506
  syncEngine,
10629
10507
  request,
@@ -10641,6 +10519,7 @@ function createDvinaClient(options) {
10641
10519
  },
10642
10520
  inference,
10643
10521
  billing,
10522
+ lifecycle,
10644
10523
  baseUrl
10645
10524
  };
10646
10525
  }
@@ -10940,7 +10819,7 @@ function buildSmartQuery(baseDocument, rootFieldName, includes, baseVariables, i
10940
10819
  }
10941
10820
  const doc = cloneDocument(baseDocument);
10942
10821
  const mergedVariables = { ...baseVariables };
10943
- const opDef = doc.definitions.find((d) => d.kind === chunkBL3GFOZR_cjs.Kind.OPERATION_DEFINITION);
10822
+ const opDef = doc.definitions.find((d) => d.kind === chunkY4OD5SDF_cjs.Kind.OPERATION_DEFINITION);
10944
10823
  if (!opDef) {
10945
10824
  return { document: baseDocument, variables: baseVariables };
10946
10825
  }
@@ -10950,7 +10829,7 @@ function buildSmartQuery(baseDocument, rootFieldName, includes, baseVariables, i
10950
10829
  }
10951
10830
  const existingFragments = /* @__PURE__ */ new Set();
10952
10831
  for (const def of doc.definitions) {
10953
- if (def.kind === chunkBL3GFOZR_cjs.Kind.FRAGMENT_DEFINITION) {
10832
+ if (def.kind === chunkY4OD5SDF_cjs.Kind.FRAGMENT_DEFINITION) {
10954
10833
  existingFragments.add(def.name.value);
10955
10834
  }
10956
10835
  }
@@ -10974,10 +10853,10 @@ function buildSmartQuery(baseDocument, rootFieldName, includes, baseVariables, i
10974
10853
  }
10975
10854
  if (isConnection && connectionIncludeFields.length > 0) {
10976
10855
  const nodesWrapper = {
10977
- kind: chunkBL3GFOZR_cjs.Kind.FIELD,
10978
- name: { kind: chunkBL3GFOZR_cjs.Kind.NAME, value: "nodes" },
10856
+ kind: chunkY4OD5SDF_cjs.Kind.FIELD,
10857
+ name: { kind: chunkY4OD5SDF_cjs.Kind.NAME, value: "nodes" },
10979
10858
  selectionSet: {
10980
- kind: chunkBL3GFOZR_cjs.Kind.SELECTION_SET,
10859
+ kind: chunkY4OD5SDF_cjs.Kind.SELECTION_SET,
10981
10860
  selections: connectionIncludeFields
10982
10861
  }
10983
10862
  };
@@ -10991,14 +10870,14 @@ function buildSmartQuery(baseDocument, rootFieldName, includes, baseVariables, i
10991
10870
  function processIncludeDirective(include, prefix, opDef, mergedVariables, existingFragments, newDefinitions) {
10992
10871
  const fieldArgs = buildPrefixedArguments(include.fieldArguments ?? [], prefix);
10993
10872
  const fragmentDefs = include.fragmentDoc.definitions.filter(
10994
- (d) => d.kind === chunkBL3GFOZR_cjs.Kind.FRAGMENT_DEFINITION
10873
+ (d) => d.kind === chunkY4OD5SDF_cjs.Kind.FRAGMENT_DEFINITION
10995
10874
  );
10996
10875
  const mainFragment = fragmentDefs[0];
10997
10876
  if (!mainFragment) return void 0;
10998
10877
  const selections = [
10999
10878
  {
11000
- kind: chunkBL3GFOZR_cjs.Kind.FRAGMENT_SPREAD,
11001
- name: { kind: chunkBL3GFOZR_cjs.Kind.NAME, value: mainFragment.name.value }
10879
+ kind: chunkY4OD5SDF_cjs.Kind.FRAGMENT_SPREAD,
10880
+ name: { kind: chunkY4OD5SDF_cjs.Kind.NAME, value: mainFragment.name.value }
11002
10881
  }
11003
10882
  ];
11004
10883
  if (include.children && include.children.length > 0) {
@@ -11020,10 +10899,10 @@ function processIncludeDirective(include, prefix, opDef, mergedVariables, existi
11020
10899
  if (childFields.length > 0) {
11021
10900
  if (include.isConnection) {
11022
10901
  const nodesWrapper = {
11023
- kind: chunkBL3GFOZR_cjs.Kind.FIELD,
11024
- name: { kind: chunkBL3GFOZR_cjs.Kind.NAME, value: "nodes" },
10902
+ kind: chunkY4OD5SDF_cjs.Kind.FIELD,
10903
+ name: { kind: chunkY4OD5SDF_cjs.Kind.NAME, value: "nodes" },
11025
10904
  selectionSet: {
11026
- kind: chunkBL3GFOZR_cjs.Kind.SELECTION_SET,
10905
+ kind: chunkY4OD5SDF_cjs.Kind.SELECTION_SET,
11027
10906
  selections: childFields
11028
10907
  }
11029
10908
  };
@@ -11034,11 +10913,11 @@ function processIncludeDirective(include, prefix, opDef, mergedVariables, existi
11034
10913
  }
11035
10914
  }
11036
10915
  const includeField = {
11037
- kind: chunkBL3GFOZR_cjs.Kind.FIELD,
11038
- name: { kind: chunkBL3GFOZR_cjs.Kind.NAME, value: include.fieldName },
10916
+ kind: chunkY4OD5SDF_cjs.Kind.FIELD,
10917
+ name: { kind: chunkY4OD5SDF_cjs.Kind.NAME, value: include.fieldName },
11039
10918
  arguments: fieldArgs.length > 0 ? fieldArgs : void 0,
11040
10919
  selectionSet: {
11041
- kind: chunkBL3GFOZR_cjs.Kind.SELECTION_SET,
10920
+ kind: chunkY4OD5SDF_cjs.Kind.SELECTION_SET,
11042
10921
  selections
11043
10922
  }
11044
10923
  };
@@ -11065,7 +10944,7 @@ function processIncludeDirective(include, prefix, opDef, mergedVariables, existi
11065
10944
  }
11066
10945
  function findFieldInSelectionSet(selectionSet, fieldName) {
11067
10946
  for (const selection of selectionSet.selections) {
11068
- if (selection.kind === chunkBL3GFOZR_cjs.Kind.FIELD && selection.name.value === fieldName) {
10947
+ if (selection.kind === chunkY4OD5SDF_cjs.Kind.FIELD && selection.name.value === fieldName) {
11069
10948
  return selection;
11070
10949
  }
11071
10950
  }
@@ -11079,7 +10958,7 @@ function buildPrefixedArguments(args, prefix) {
11079
10958
  });
11080
10959
  }
11081
10960
  function prefixVariableReferences(node, prefix) {
11082
- if (node["kind"] === chunkBL3GFOZR_cjs.Kind.VARIABLE && typeof node["name"]?.["value"] === "string") {
10961
+ if (node["kind"] === chunkY4OD5SDF_cjs.Kind.VARIABLE && typeof node["name"]?.["value"] === "string") {
11083
10962
  node["name"]["value"] = `${prefix}${node["name"]["value"]}`;
11084
10963
  return;
11085
10964
  }
@@ -11104,7 +10983,7 @@ function buildPrefixedVariableDefinitions(varDefs, prefix) {
11104
10983
  }
11105
10984
  function extractIncludeInfo(nestedDocument, nestedFieldName, parentVarNames) {
11106
10985
  const opDef = nestedDocument.definitions.find(
11107
- (d) => d.kind === chunkBL3GFOZR_cjs.Kind.OPERATION_DEFINITION
10986
+ (d) => d.kind === chunkY4OD5SDF_cjs.Kind.OPERATION_DEFINITION
11108
10987
  );
11109
10988
  if (!opDef) {
11110
10989
  return { variableDefinitions: [], fieldArguments: [] };
@@ -11116,7 +10995,7 @@ function extractIncludeInfo(nestedDocument, nestedFieldName, parentVarNames) {
11116
10995
  let fieldArguments = [];
11117
10996
  function findNestedField(selectionSet) {
11118
10997
  for (const sel of selectionSet.selections) {
11119
- if (sel.kind === chunkBL3GFOZR_cjs.Kind.FIELD) {
10998
+ if (sel.kind === chunkY4OD5SDF_cjs.Kind.FIELD) {
11120
10999
  if (sel.name.value === nestedFieldName && sel.arguments) {
11121
11000
  fieldArguments = sel.arguments;
11122
11001
  return;
@@ -22136,6 +22015,8 @@ var DvinaSdk = class extends chunk342BFYZZ_cjs.Request {
22136
22015
  syncEngine;
22137
22016
  /** Chat SSE client for chat-scoped stream listeners. */
22138
22017
  chatStream;
22018
+ /** Semantic lifecycle bridge for connectivity and foreground recovery hints. */
22019
+ lifecycle;
22139
22020
  _getToken;
22140
22021
  _terminateWs;
22141
22022
  _closeDb;
@@ -22144,10 +22025,11 @@ var DvinaSdk = class extends chunk342BFYZZ_cjs.Request {
22144
22025
  /** Billing client for the Dvina Billing API (plans, subscriptions, seats, sessions). */
22145
22026
  billing;
22146
22027
  constructor(options) {
22147
- const { syncEngine, request, subscribe, chatStream, getToken, terminateWs, closeDb, inference, billing, baseUrl } = createDvinaClient(options);
22028
+ const { syncEngine, request, subscribe, chatStream, lifecycle, getToken, terminateWs, closeDb, inference, billing, baseUrl } = createDvinaClient(options);
22148
22029
  super(request, syncEngine, subscribe, baseUrl);
22149
22030
  this.syncEngine = syncEngine;
22150
22031
  this.chatStream = chatStream;
22032
+ this.lifecycle = lifecycle;
22151
22033
  this._getToken = getToken;
22152
22034
  this._terminateWs = terminateWs;
22153
22035
  this._closeDb = closeDb;
@@ -23178,5 +23060,5 @@ exports.getOrCreateDatabase = getOrCreateDatabase;
23178
23060
  exports.reconstructConnectionNodes = reconstructConnectionNodes;
23179
23061
  exports.reconstructEntity = reconstructEntity;
23180
23062
  exports.uploadFile = uploadFile;
23181
- //# sourceMappingURL=chunk-4EESBP3A.cjs.map
23182
- //# sourceMappingURL=chunk-4EESBP3A.cjs.map
23063
+ //# sourceMappingURL=chunk-XK5PW7IX.cjs.map
23064
+ //# sourceMappingURL=chunk-XK5PW7IX.cjs.map