@voxevolv/client 0.3.16 → 0.3.18

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.
package/dist/index.js CHANGED
@@ -7,7 +7,8 @@ import {
7
7
  Room,
8
8
  RoomEvent,
9
9
  RpcError,
10
- Track
10
+ Track,
11
+ version as LIVEKIT_VERSION
11
12
  } from "./vendor/livekit-client.esm.mjs";
12
13
  import {
13
14
  createClientMessage,
@@ -23,8 +24,10 @@ import {
23
24
  import { ContextDeliveryError, contextRetryDelay, ReplacementContextQueue } from "./context-queue.js";
24
25
  import {
25
26
  ClientDiagnosticBuffer,
27
+ diagnosticId,
26
28
  DiagnosticDeliveryError
27
29
  } from "./diagnostics.js";
30
+ import { observeConnectionTransport } from "./connection-diagnostics.js";
28
31
  import { observeRpcTransport } from "./rpc-transport-diagnostics.js";
29
32
  import { Presentations } from "./presentations.js";
30
33
  import { TranscriptStore } from "./transcripts.js";
@@ -51,7 +54,7 @@ import {
51
54
  decodeContextUpdatedPayload,
52
55
  decodeRealtimeEvent
53
56
  } from "./generated/protocol-codecs.js";
54
- var SDK_VERSION = "0.3.16";
57
+ var SDK_VERSION = "0.3.18";
55
58
  var CLIENT_HELLO_TIMEOUT_MS = 3e4;
56
59
  var RECOVERY_BUFFER_STALL_MS = 5e3;
57
60
  var RECOVERY_BUFFER_POLL_MS = 500;
@@ -178,12 +181,18 @@ var RealtimeSession = class _RealtimeSession {
178
181
  diagnosticLastSampleAt = 0;
179
182
  stopRpcDiagnostics;
180
183
  diagnosticEngine;
184
+ connectionDiagnostics;
185
+ diagnosticRecoveryId;
181
186
  presentations = new Presentations(
182
187
  (request) => this.room.localParticipant.performRpc(request),
183
188
  () => this.sessionEnded || ["disconnected", "failed"].includes(this.stateValue),
184
189
  () => {
185
190
  this.recordDiagnostic({ operation: "tool_rpc", status: "failed", reason: "presentation_receipt_failed" });
186
191
  this.flushDiagnostics("presentation_receipt_failed");
192
+ },
193
+ (entry) => {
194
+ this.recordDiagnostic(entry);
195
+ this.flushDiagnostics("presentation_rpc");
187
196
  }
188
197
  );
189
198
  diagnosticReportTimeoutMs = DIAGNOSTIC_REPORT_TIMEOUT_MS;
@@ -192,6 +201,10 @@ var RealtimeSession = class _RealtimeSession {
192
201
  this.recordDiagnostic({ operation: "browser_runtime", status: "succeeded", reason });
193
202
  this.flushDiagnostics(reason);
194
203
  };
204
+ onDiagnosticNetworkChange = (event) => {
205
+ this.recordDiagnostic({ operation: "browser_runtime", status: "succeeded", reason: `network_${event.type}` });
206
+ this.flushDiagnostics(`network_${event.type}`);
207
+ };
195
208
  onDiagnosticLifecycle = (event) => {
196
209
  this.recordDiagnostic({ operation: "browser_runtime", status: "succeeded", reason: event.type });
197
210
  this.flushDiagnostics(`page_${event.type}`);
@@ -214,6 +227,9 @@ var RealtimeSession = class _RealtimeSession {
214
227
  this.startupRetryOptions = resolveStartupRetryOptions(options.startupRetry);
215
228
  this.lifecycleCredentials = options.lifecycleCredentials ?? "same-origin";
216
229
  this.room = new Room({ adaptiveStream: true, dynacast: true });
230
+ this.room.voxevolvObserveEngine = () => {
231
+ this.startRpcDiagnostics();
232
+ };
217
233
  for (const [name, handler] of Object.entries(options.tools ?? {})) {
218
234
  this.registerTool(name, handler);
219
235
  }
@@ -240,6 +256,7 @@ var RealtimeSession = class _RealtimeSession {
240
256
  const receivedAt = performance.now();
241
257
  let callId;
242
258
  let toolName;
259
+ let presentationId;
243
260
  let slowTimer;
244
261
  const record = (entry) => this.recordDiagnostic({
245
262
  operation: "tool_rpc",
@@ -247,6 +264,7 @@ var RealtimeSession = class _RealtimeSession {
247
264
  rpc_request_id: invocation.requestId,
248
265
  call_id: callId,
249
266
  tool_name: toolName,
267
+ presentation_id: presentationId,
250
268
  duration_ms: performance.now() - receivedAt,
251
269
  ...entry
252
270
  });
@@ -288,7 +306,8 @@ var RealtimeSession = class _RealtimeSession {
288
306
  if (toolName !== "present_attachment" || typeof payload.presentation_id !== "string" || !payload.presentation_id || payload.presentation_id.length > 200) {
289
307
  throw new RpcError(1500, "Invalid presentation identity");
290
308
  }
291
- response = await this.presentations.invoke(payload.presentation_id, invocation.callerIdentity, execute);
309
+ presentationId = payload.presentation_id;
310
+ response = await this.presentations.invoke(presentationId, invocation.callerIdentity, execute);
292
311
  } else {
293
312
  response = await execute();
294
313
  }
@@ -709,6 +728,7 @@ var RealtimeSession = class _RealtimeSession {
709
728
  this.livekitResumeController = null;
710
729
  this.failRecovery(toError(error));
711
730
  this.recoveryStartedAt = null;
731
+ this.diagnosticRecoveryId = void 0;
712
732
  this.reconnectStartedAt = null;
713
733
  this.pendingReconnect = null;
714
734
  }
@@ -1117,6 +1137,8 @@ var RealtimeSession = class _RealtimeSession {
1117
1137
  if (state === "connecting" || state === "resuming") {
1118
1138
  this.startRpcDiagnostics();
1119
1139
  this.startDiagnosticLoopMonitor();
1140
+ globalThis.addEventListener?.("online", this.onDiagnosticNetworkChange);
1141
+ globalThis.addEventListener?.("offline", this.onDiagnosticNetworkChange);
1120
1142
  globalThis.document?.addEventListener?.("visibilitychange", this.onDiagnosticVisibilityChange);
1121
1143
  globalThis.document?.addEventListener?.("freeze", this.onDiagnosticLifecycle);
1122
1144
  globalThis.document?.addEventListener?.("resume", this.onDiagnosticLifecycle);
@@ -1126,6 +1148,11 @@ var RealtimeSession = class _RealtimeSession {
1126
1148
  this.diagnosticLoopTimer = void 0;
1127
1149
  this.diagnosticLoopDelayMs = void 0;
1128
1150
  this.diagnosticLoopHistory = [];
1151
+ this.connectionDiagnostics?.stop();
1152
+ this.connectionDiagnostics = void 0;
1153
+ this.diagnosticRecoveryId = void 0;
1154
+ globalThis.removeEventListener?.("online", this.onDiagnosticNetworkChange);
1155
+ globalThis.removeEventListener?.("offline", this.onDiagnosticNetworkChange);
1129
1156
  this.stopRpcDiagnostics?.();
1130
1157
  this.stopRpcDiagnostics = void 0;
1131
1158
  this.diagnosticEngine = void 0;
@@ -1166,13 +1193,22 @@ var RealtimeSession = class _RealtimeSession {
1166
1193
  }
1167
1194
  });
1168
1195
  this.room.on(RoomEvent.SignalConnected, () => this.startRpcDiagnostics());
1169
- this.room.on(RoomEvent.SignalReconnecting, () => this.handleLiveKitReconnecting());
1170
- this.room.on(RoomEvent.Reconnecting, () => this.handleLiveKitReconnecting());
1196
+ this.room.on(RoomEvent.SignalReconnecting, () => this.handleLiveKitReconnecting("signal_reconnecting"));
1197
+ this.room.on(RoomEvent.Reconnecting, () => this.handleLiveKitReconnecting("media_reconnecting"));
1171
1198
  this.room.on(RoomEvent.Reconnected, () => {
1172
1199
  this.startRpcDiagnostics();
1173
1200
  void this.handleLiveKitReconnected();
1174
1201
  });
1175
1202
  this.room.on(RoomEvent.Disconnected, (reason) => {
1203
+ if (!this.disconnectMode && !this.sessionEnded) {
1204
+ this.recordDiagnostic({
1205
+ operation: "connection_transport",
1206
+ status: "failed",
1207
+ reason: "room_disconnected",
1208
+ disconnect_reason: reason
1209
+ });
1210
+ this.flushDiagnostics("room_disconnected");
1211
+ }
1176
1212
  this.handleLiveKitDisconnected(reason);
1177
1213
  });
1178
1214
  this.room.on(RoomEvent.ConnectionStateChanged, (state) => {
@@ -1252,8 +1288,9 @@ var RealtimeSession = class _RealtimeSession {
1252
1288
  this.notifyListeners(this.listeners, value);
1253
1289
  });
1254
1290
  }
1255
- handleLiveKitReconnecting() {
1291
+ handleLiveKitReconnecting(trigger = "livekit_reconnecting") {
1256
1292
  if (this.sessionEnded || this.disconnectMode === "intentional" || this.terminalReplayController || ["disconnected", "failed"].includes(this.stateValue)) return;
1293
+ this.recordDiagnostic({ operation: "connection_transport", status: "started", reason: trigger });
1257
1294
  this.agentReady = false;
1258
1295
  if (this.autoRejoinPromise !== null || this.activeRecovery?.strategy === "rejoin" || this.disconnectMode === "rejoin") {
1259
1296
  this.setState("resuming");
@@ -1433,6 +1470,7 @@ var RealtimeSession = class _RealtimeSession {
1433
1470
  this.notifyListeners(this.endedListeners, event);
1434
1471
  }
1435
1472
  beginRecovery(strategy, attempt, details) {
1473
+ this.diagnosticRecoveryId ??= diagnosticId();
1436
1474
  this.recoveryStartedAt ??= Date.now();
1437
1475
  this.activeRecovery = { strategy, attempt, details };
1438
1476
  this.recordDiagnostic({
@@ -1465,6 +1503,7 @@ var RealtimeSession = class _RealtimeSession {
1465
1503
  });
1466
1504
  this.flushDiagnostics("recovery_completed");
1467
1505
  this.recoveryStartedAt = null;
1506
+ this.diagnosticRecoveryId = void 0;
1468
1507
  this.activeRecovery = null;
1469
1508
  this.notifyListeners(this.recoveryListeners, {
1470
1509
  status: "succeeded",
@@ -1572,6 +1611,7 @@ var RealtimeSession = class _RealtimeSession {
1572
1611
  this.livekitResumeController?.abort();
1573
1612
  this.livekitResumeController = null;
1574
1613
  this.recoveryStartedAt = null;
1614
+ this.diagnosticRecoveryId = void 0;
1575
1615
  this.autoRejoinController?.abort();
1576
1616
  this.autoRejoinController = null;
1577
1617
  this.manualRejoinController?.abort();
@@ -2025,6 +2065,12 @@ var RealtimeSession = class _RealtimeSession {
2025
2065
  if (!engine || this.stopRpcDiagnostics && this.diagnosticEngine === engine) return;
2026
2066
  this.stopRpcDiagnostics?.();
2027
2067
  this.diagnosticEngine = engine;
2068
+ this.connectionDiagnostics?.stop();
2069
+ this.connectionDiagnostics = observeConnectionTransport(engine, (entry) => {
2070
+ if (this.disconnectMode || this.sessionEnded || ["disconnected", "failed"].includes(this.stateValue)) return;
2071
+ this.recordDiagnostic(entry);
2072
+ this.flushDiagnostics("connection_transport");
2073
+ });
2028
2074
  this.stopRpcDiagnostics = observeRpcTransport(engine, (entry) => {
2029
2075
  this.recordDiagnostic(entry);
2030
2076
  this.flushDiagnostics("tool_rpc_transport");
@@ -2050,12 +2096,24 @@ var RealtimeSession = class _RealtimeSession {
2050
2096
  }
2051
2097
  }
2052
2098
  recordDiagnostic(entry) {
2099
+ if (entry.operation === "connection_transport") {
2100
+ this.diagnosticRecoveryId ??= diagnosticId();
2101
+ }
2053
2102
  const snapshot = {
2054
2103
  ...entry,
2104
+ recovery_id: this.diagnosticRecoveryId,
2105
+ connection_id: entry.connection_id ?? this.connectionId,
2106
+ participant_sid: this.room.localParticipant.sid || void 0,
2107
+ livekit_version: LIVEKIT_VERSION,
2108
+ browser_online: globalThis.navigator?.onLine,
2055
2109
  connection_state: this.stateValue,
2056
2110
  buffered_bytes: entry.buffered_bytes ?? this.reliableDataChannelBufferedBytes()
2057
2111
  };
2058
- if (["tool_rpc", "rpc_transport", "browser_runtime", "connection_recovery"].includes(entry.operation)) {
2112
+ if (["connection_transport", "connection_recovery", "tool_rpc"].includes(entry.operation) || ["failed", "timed_out", "rejected"].includes(entry.status)) {
2113
+ snapshot.transport_history ??= this.connectionDiagnostics?.snapshotHistory();
2114
+ }
2115
+ if (["tool_rpc", "rpc_transport", "browser_runtime", "connection_recovery", "connection_transport"].includes(entry.operation)) {
2116
+ snapshot.rpc_observer_active = !!this.stopRpcDiagnostics && this.diagnosticEngine === this.room.engine;
2059
2117
  snapshot.page_visibility = globalThis.document?.visibilityState;
2060
2118
  snapshot.active_context_transfers = this.activeContextTransfers;
2061
2119
  snapshot.active_context_bytes = this.activeContextBytes;