realtime-avatar 0.13.0 → 0.14.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.
package/README.md CHANGED
@@ -4,7 +4,7 @@ A live character your users can talk to — voice, or voice and video. She liste
4
4
  speaks, so you can interrupt her mid-sentence and she stops, the way a person stops.
5
5
 
6
6
  ```bash
7
- npm install realtime-avatar
7
+ npm install --save-exact realtime-avatar@0.14.0
8
8
  ```
9
9
 
10
10
  ```ts
@@ -147,6 +147,25 @@ call. Policy — `instructions`, `maxSeconds`, `voice`, `video` — is decided i
147
147
  your server. A route that spreads the request body into `startCall` hands your caller your
148
148
  system prompt and your bill.
149
149
 
150
+ ### Native connection facts
151
+
152
+ LiveKit owns media transport, connection state, and reconnection. Use its
153
+ `useConnectionState()` and `useConnectionQualityIndicator({ participant })` hooks, or
154
+ `RoomEvent` callbacks, to build your product's network UI. Their values already use
155
+ `ConnectionState`, `ConnectionQuality`, and `Track.StreamState` from `livekit-client`.
156
+ For current receiver measurements, `RemoteVideoTrack.getReceiverStats()` and
157
+ `RemoteAudioTrack.getReceiverStats()` return LiveKit's exported `VideoReceiverStats` and
158
+ `AudioReceiverStats` types.
159
+ Keep these native types in process; there is no SDK-specific JSON mirror to maintain.
160
+
161
+ Retain the app's session-to-room association (`room_name`, timestamps and participant
162
+ identity), adding the server-observed room SID when exact room-lifetime lookup needs it.
163
+ LiveKit owns participant connection history; a participant SID identifies one incarnation.
164
+ Use these references to look up details in LiveKit's own diagnostics. The existing quality governor
165
+ and opt-in adaptive playout are product policies over LiveKit facts; setting
166
+ `adaptiveQuality={false}` releases the manual quality ceiling while LiveKit's bandwidth
167
+ adaptation continues. Adaptive playout reads only public LiveKit track reports.
168
+
150
169
  ### Importing a server entry into a browser build throws
151
170
 
152
171
  Not a lint rule and not a naming convention — the six server subpaths carry `browser` and
@@ -1,4 +1,4 @@
1
- import { RealtimeAvatar, isQueued, RealtimeAvatarHttpError } from './chunk-UVNDDNU2.js';
1
+ import { RealtimeAvatar, isQueued, RealtimeAvatarHttpError } from './chunk-UZQXZH2Z.js';
2
2
 
3
3
  // ../proxy/src/config.ts
4
4
  var json = (body, status = 200) => new Response(JSON.stringify(body), {
@@ -236,7 +236,7 @@ function isTransient(cause) {
236
236
 
237
237
  // ../http-client/src/client.ts
238
238
  var DEFAULT_BASE_URL = "https://realtimeavatar.ai/api/v1";
239
- var SDK_VERSION = "0.13.0";
239
+ var SDK_VERSION = "0.14.0";
240
240
  var RealtimeAvatar = class {
241
241
  #apiKey;
242
242
  #baseUrl;
package/dist/express.js CHANGED
@@ -1,5 +1,5 @@
1
- import { createProxyHandler } from './chunk-NOHMMTFR.js';
2
- import './chunk-UVNDDNU2.js';
1
+ import { createProxyHandler } from './chunk-B3AHTJ3J.js';
2
+ import './chunk-UZQXZH2Z.js';
3
3
 
4
4
  // ../proxy/src/express.ts
5
5
  function realtimeAvatarExpress(config) {
package/dist/hono.js CHANGED
@@ -1,5 +1,5 @@
1
- import { createProxyHandler } from './chunk-NOHMMTFR.js';
2
- import './chunk-UVNDDNU2.js';
1
+ import { createProxyHandler } from './chunk-B3AHTJ3J.js';
2
+ import './chunk-UZQXZH2Z.js';
3
3
 
4
4
  // ../proxy/src/hono.ts
5
5
  function realtimeAvatarHono(config) {
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, clipLibraryDeclarationSchema, isQueued, verifyTranscript } from './chunk-UVNDDNU2.js';
1
+ export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, clipLibraryDeclarationSchema, isQueued, verifyTranscript } from './chunk-UZQXZH2Z.js';
package/dist/nextjs.js CHANGED
@@ -1,5 +1,5 @@
1
- import { createProxyHandler } from './chunk-NOHMMTFR.js';
2
- import './chunk-UVNDDNU2.js';
1
+ import { createProxyHandler } from './chunk-B3AHTJ3J.js';
2
+ import './chunk-UZQXZH2Z.js';
3
3
 
4
4
  // ../proxy/src/nextjs.ts
5
5
  function createRealtimeAvatarRoute(config) {
@@ -1,6 +1,6 @@
1
1
  import { TrackReferenceOrPlaceholder, useTranscriptions, useConnectionState, LiveKitRoomProps } from '@livekit/components-react';
2
2
  import { CSSProperties, ReactNode, ReactElement } from 'react';
3
- import { DisconnectReason, SendTextOptions } from 'livekit-client';
3
+ import { ConnectionQuality, DisconnectReason, SendTextOptions } from 'livekit-client';
4
4
  import { z } from 'zod';
5
5
 
6
6
  /**
@@ -312,7 +312,7 @@ type GovernorState = "opening" | "opening_high" | "cap_low_sticky" | "cap_low_el
312
312
  /**
313
313
  * One normalized input the hook feeds each tick. The hook translates ALL of
314
314
  * {TrackStreamStateChanged, ConnectionQualityChanged, getStats, rVFC freeze} into
315
- * this shape, so the core never sees a vendor type.
315
+ * this shape. LiveKit owns the connection-quality vocabulary.
316
316
  */
317
317
  interface GovernorSignal {
318
318
  /** SFU congestion controller paused the track since the last tick — Tier-0, the
@@ -323,9 +323,8 @@ interface GovernorSignal {
323
323
  freezeMsInWindow: number;
324
324
  /** jitterBufferDelay is trending up — the earliest LEADING pre-freeze sign. */
325
325
  jitterRising: boolean;
326
- /** LiveKit ConnectionQuality — a LAGGING corroborator only (jitter/RTT are disabled
327
- * in its score + known false-Poor bugs). Blocks up-probes; never a sole trigger. */
328
- connectionQuality: "excellent" | "good" | "poor" | "lost" | "unknown";
326
+ /** LiveKit connection quality blocks up-probes; it is never a sole downgrade trigger. */
327
+ connectionQuality: `${ConnectionQuality}`;
329
328
  /** The tab is hidden / track muted / freezes correlate with local CPU not network —
330
329
  * the false-positive fence (our own Dia-freeze lesson). When true the machine is
331
330
  * frozen: no signal is trusted, no transition fires. */
@@ -987,7 +986,7 @@ declare function readInboundRtp(reports: Iterable<Record<string, unknown>>, prev
987
986
  * (default false ⇒ a complete no-op, the incumbent flat cushion untouched).
988
987
  *
989
988
  * When enabled it runs the {@link AdaptivePlayoutController} closed loop: a 1Hz
990
- * `RTCRtpReceiver.getStats()` poll over BOTH avatar receivers, the worst
989
+ * LiveKit `getRTCStatsReport()` poll over BOTH avatar tracks, the worst
991
990
  * jitter/loss of the pair feeding one shared target so audio and video stay on
992
991
  * the SAME depth (lip-sync law — WebRTC pairs the streams to the larger of the
993
992
  * two hints). The loop opens at the ceiling (the flat cushion already applied by
@@ -995,7 +994,7 @@ declare function readInboundRtp(reports: Iterable<Record<string, unknown>>, prev
995
994
  * snaps back up within a couple of ticks when jitter or loss appears.
996
995
  *
997
996
  * Degrades to the incumbent behavior wherever the substrate is missing: a track
998
- * without `getStats` on its receiver, a stats report with no `inbound-rtp` yet,
997
+ * without an available LiveKit stats report, a report with no `inbound-rtp` yet,
999
998
  * or a browser without the playout-delay hint all leave the flat cushion exactly
1000
999
  * as `useAvatarPlayoutDelay` set it.
1001
1000
  *
@@ -1,8 +1,8 @@
1
1
  import { LiveKitRoomProps } from '@livekit/react-native';
2
2
  export { AudioSession, VideoTrack, VideoTrackProps, registerGlobals } from '@livekit/react-native';
3
3
  import { ReactNode, ReactElement } from 'react';
4
- import { L as LiveKitSessionGrant, A as AvatarVideoFit } from './proxy-client-BoUJWSkf.js';
5
- export { a as AdaptivePlayoutController, b as AdaptivePlayoutDecision, c as AdaptivePlayoutOptions, d as AdaptivePlayoutSample, e as ApproachingEndEvent, f as ApproachingEndReason, g as AvatarSessionClient, B as BehaviorSnapshot, C as CallTranscript, h as CallTranscriptSegment, i as CartesiaTtsModel, j as ClipResult, k as ClosingTurnResult, l as CreditsLowEvent, D as DEFAULT_APPROACHING_END_LEAD_SECONDS, m as DEFAULT_CREDITS_LOW_LEAD_SECONDS, n as DEFAULT_GOVERNOR_CONFIG, o as DEFAULT_GRACE_CEILING_SECONDS, p as DEFAULT_GRACE_WINDOW_LEAD_SECONDS, q as DEFAULT_IDLE_SECONDS, r as DEFAULT_IDLE_WARN_LEAD_SECONDS, s as DEFAULT_TURN_TIMEOUT_SECONDS, E as EndReason, t as EndedEvent, u as ExtendResult, F as FishTtsModel, v as FreezeReadingFn, G as Governor, w as GovernorAction, x as GovernorConfig, y as GovernorSignal, z as GovernorState, H as GraceWindowClosedEvent, I as GraceWindowOpenEvent, J as GraceWindowState, K as IdleWarningEvent, M as InboundRtpCursor, N as InboundRtpReading, O as KnownBehaviorState, P as LLMProvider, Q as LLMSelection, R as LiveKitAvatarGrantState, S as LiveKitAvatarGrantStatus, T as LiveKitCapacityState, U as LiveKitConnectionStatus, V as LiveKitSessionRequest, W as LiveKitSessionStartResult, X as MAX_RECONNECT_ATTEMPTS, Y as MAX_SESSION_INSTRUCTIONS_CHARS, Z as ProxyClientOptions, _ as QualityCap, $ as RECONNECT_BACKOFF_MS, a0 as RealtimeAvatarRequestOptions, a1 as RealtimeSessionApi, a2 as RealtimeSessionMedia, a3 as RealtimeSessionRoomSinks, a4 as ReconnectPolicy, a5 as ReconnectingEvent, a6 as RecoveryState, a7 as RetryStep, a8 as SessionBehavior, a9 as SessionClip, aa as SessionClocks, ab as SessionEndReason, ac as SessionLifecycleApi, ad as SessionLifecyclePhase, ae as SessionLifecyclePhaseKind, af as SessionLifecycleRoomBridge, ag as SessionLifecycleRoomBridgeProps, ah as SurfaceLayers, ai as TurnState, aj as TurnTimeoutEvent, ak as UseAvatarQualityGovernorInput, al as UseLiveKitAvatarGrantInput, am as UseRealtimeSessionInput, an as UseSessionLifecycleInput, ao as VoiceSpec, ap as VoiceSpecInput, aq as capacityErrorFromBusy, ar as capacityStateFromGrant, as as createProxyClient, at as isNativeLiveTrackSubscribed, au as knownBehaviorStates, av as mapTurnState, aw as readInboundRtp, ax as sessionBehaviorSchema, ay as sessionClipSchema, az as splitCallTranscript, aA as useAvatarAdaptivePlayoutDelay, aB as useAvatarPlayoutDelay, aC as useAvatarQualityGovernor, aD as useCallTranscript, aE as useLiveKitAvatarGrant, aF as useLiveTrackProducing, aG as useMicLease, aH as useRealtimeSession, aI as useReleaseMicLeaseOnTrackEnded, aJ as useSessionLifecycle } from './proxy-client-BoUJWSkf.js';
4
+ import { L as LiveKitSessionGrant, A as AvatarVideoFit } from './proxy-client-DhVdbfQX.js';
5
+ export { a as AdaptivePlayoutController, b as AdaptivePlayoutDecision, c as AdaptivePlayoutOptions, d as AdaptivePlayoutSample, e as ApproachingEndEvent, f as ApproachingEndReason, g as AvatarSessionClient, B as BehaviorSnapshot, C as CallTranscript, h as CallTranscriptSegment, i as CartesiaTtsModel, j as ClipResult, k as ClosingTurnResult, l as CreditsLowEvent, D as DEFAULT_APPROACHING_END_LEAD_SECONDS, m as DEFAULT_CREDITS_LOW_LEAD_SECONDS, n as DEFAULT_GOVERNOR_CONFIG, o as DEFAULT_GRACE_CEILING_SECONDS, p as DEFAULT_GRACE_WINDOW_LEAD_SECONDS, q as DEFAULT_IDLE_SECONDS, r as DEFAULT_IDLE_WARN_LEAD_SECONDS, s as DEFAULT_TURN_TIMEOUT_SECONDS, E as EndReason, t as EndedEvent, u as ExtendResult, F as FishTtsModel, v as FreezeReadingFn, G as Governor, w as GovernorAction, x as GovernorConfig, y as GovernorSignal, z as GovernorState, H as GraceWindowClosedEvent, I as GraceWindowOpenEvent, J as GraceWindowState, K as IdleWarningEvent, M as InboundRtpCursor, N as InboundRtpReading, O as KnownBehaviorState, P as LLMProvider, Q as LLMSelection, R as LiveKitAvatarGrantState, S as LiveKitAvatarGrantStatus, T as LiveKitCapacityState, U as LiveKitConnectionStatus, V as LiveKitSessionRequest, W as LiveKitSessionStartResult, X as MAX_RECONNECT_ATTEMPTS, Y as MAX_SESSION_INSTRUCTIONS_CHARS, Z as ProxyClientOptions, _ as QualityCap, $ as RECONNECT_BACKOFF_MS, a0 as RealtimeAvatarRequestOptions, a1 as RealtimeSessionApi, a2 as RealtimeSessionMedia, a3 as RealtimeSessionRoomSinks, a4 as ReconnectPolicy, a5 as ReconnectingEvent, a6 as RecoveryState, a7 as RetryStep, a8 as SessionBehavior, a9 as SessionClip, aa as SessionClocks, ab as SessionEndReason, ac as SessionLifecycleApi, ad as SessionLifecyclePhase, ae as SessionLifecyclePhaseKind, af as SessionLifecycleRoomBridge, ag as SessionLifecycleRoomBridgeProps, ah as SurfaceLayers, ai as TurnState, aj as TurnTimeoutEvent, ak as UseAvatarQualityGovernorInput, al as UseLiveKitAvatarGrantInput, am as UseRealtimeSessionInput, an as UseSessionLifecycleInput, ao as VoiceSpec, ap as VoiceSpecInput, aq as capacityErrorFromBusy, ar as capacityStateFromGrant, as as createProxyClient, at as isNativeLiveTrackSubscribed, au as knownBehaviorStates, av as mapTurnState, aw as readInboundRtp, ax as sessionBehaviorSchema, ay as sessionClipSchema, az as splitCallTranscript, aA as useAvatarAdaptivePlayoutDelay, aB as useAvatarPlayoutDelay, aC as useAvatarQualityGovernor, aD as useCallTranscript, aE as useLiveKitAvatarGrant, aF as useLiveTrackProducing, aG as useMicLease, aH as useRealtimeSession, aI as useReleaseMicLeaseOnTrackEnded, aJ as useSessionLifecycle } from './proxy-client-DhVdbfQX.js';
6
6
  import { StyleProp, ViewStyle } from 'react-native';
7
7
  export { useChat, useConnectionState, useLocalParticipant, useRoomContext, useTrackToggle, useTranscriptions, useVoiceAssistant } from '@livekit/components-react';
8
8
  export { D as DEFAULT_AVATAR_PLAYOUT_DELAY_SECONDS } from './playout-delay-DWOc8iCl.js';
@@ -3,7 +3,7 @@ export { AudioSession, VideoTrack, registerGlobals } from '@livekit/react-native
3
3
  import { useEffect, createElement, useRef, useState, useCallback, useMemo } from 'react';
4
4
  import { useTranscriptions, useLocalParticipant, useMaybeRoomContext, useVoiceAssistant, useConnectionState, isTrackReference, useRoomContext, useChat } from '@livekit/components-react';
5
5
  export { useChat, useConnectionState, useLocalParticipant, useRoomContext, useTrackToggle, useTranscriptions, useVoiceAssistant } from '@livekit/components-react';
6
- import { VideoQuality, ConnectionQuality, RoomEvent, TrackEvent, ConnectionState, Track, ConnectionError, ConnectionErrorReason, DisconnectReason, Room } from 'livekit-client';
6
+ import { isRemoteTrack, VideoQuality, ConnectionQuality, RoomEvent, TrackEvent, ConnectionState, Track, ConnectionError, ConnectionErrorReason, DisconnectReason, Room } from 'livekit-client';
7
7
  export { DisconnectReason, Room, RoomEvent, Track } from 'livekit-client';
8
8
  import { Platform, StyleSheet, Animated, Image, View, Text } from 'react-native';
9
9
  import { z } from 'zod';
@@ -679,10 +679,8 @@ function useAvatarAdaptivePlayoutDelay(videoTrack, audioTrack, enabled = false,
679
679
  const audioMediaTrack = audioTrack?.publication?.track;
680
680
  useEffect(() => {
681
681
  if (!enabled || !videoMediaTrack && !audioMediaTrack) return;
682
- const receivers = [videoMediaTrack, audioMediaTrack].map((t) => t?.receiver).filter(
683
- (r) => typeof r?.getStats === "function"
684
- );
685
- if (receivers.length === 0) return;
682
+ const tracks = [videoMediaTrack, audioMediaTrack].filter(isRemoteTrack);
683
+ if (tracks.length === 0) return;
686
684
  const controller = new AdaptivePlayoutController(options);
687
685
  const cursors = /* @__PURE__ */ new Map();
688
686
  let closed = false;
@@ -692,9 +690,9 @@ function useAvatarAdaptivePlayoutDelay(videoTrack, audioTrack, enabled = false,
692
690
  inFlight = true;
693
691
  try {
694
692
  let worst;
695
- for (let i = 0; i < receivers.length; i++) {
696
- const stats = await receivers[i].getStats();
697
- if (closed || typeof stats?.values !== "function") continue;
693
+ for (let i = 0; i < tracks.length; i++) {
694
+ const stats = await tracks[i].getRTCStatsReport();
695
+ if (closed || !stats) continue;
698
696
  const reading = readInboundRtp(stats.values(), cursors.get(i));
699
697
  if (!reading) continue;
700
698
  cursors.set(i, reading.cursor);
@@ -1016,20 +1014,6 @@ function bindNetworkQuality(publication, inhibited, notify, tickMs) {
1016
1014
  }
1017
1015
 
1018
1016
  // ../client/src/react/use-quality-governor.ts
1019
- var qualityToSignal = (q) => {
1020
- switch (q) {
1021
- case ConnectionQuality.Excellent:
1022
- return "excellent";
1023
- case ConnectionQuality.Good:
1024
- return "good";
1025
- case ConnectionQuality.Poor:
1026
- return "poor";
1027
- case ConnectionQuality.Lost:
1028
- return "lost";
1029
- default:
1030
- return "unknown";
1031
- }
1032
- };
1033
1017
  function useAvatarQualityGovernor(input) {
1034
1018
  const { enabled, freezeReading, onNetworkStatusChange, config: policy = DEFAULT_GOVERNOR_CONFIG, tickMs = 1e3 } = input;
1035
1019
  const room = useMaybeRoomContext();
@@ -1093,16 +1077,14 @@ function useAvatarQualityGovernor(input) {
1093
1077
  let pausedSinceTick = false;
1094
1078
  let lastFreezeStat = null;
1095
1079
  let jitterTrend = null;
1096
- let connQuality = qualityToSignal(
1097
- targetParticipant?.connectionQuality ?? ConnectionQuality.Unknown
1098
- );
1080
+ let connQuality = targetParticipant?.connectionQuality ?? ConnectionQuality.Unknown;
1099
1081
  const onStreamState = (pub, streamState) => {
1100
1082
  if (pub !== targetPublication) return;
1101
1083
  if (streamState === Track.StreamState.Paused) pausedSinceTick = true;
1102
1084
  };
1103
1085
  const onQuality = (q, participant) => {
1104
1086
  if (participant.sid !== targetParticipant.sid) return;
1105
- connQuality = qualityToSignal(q);
1087
+ connQuality = q;
1106
1088
  };
1107
1089
  try {
1108
1090
  room.on(RoomEvent.TrackStreamStateChanged, onStreamState);
package/dist/react.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { RegisteredTool, ToolRegistration } from './tools.js';
2
2
  import { ReactNode } from 'react';
3
- import { g as AvatarSessionClient, A as AvatarVideoFit } from './proxy-client-BoUJWSkf.js';
4
- export { a as AdaptivePlayoutController, b as AdaptivePlayoutDecision, c as AdaptivePlayoutOptions, d as AdaptivePlayoutSample, e as ApproachingEndEvent, f as ApproachingEndReason, aK as AvatarVideoSurface, aL as AvatarVideoSurfaceProps, B as BehaviorSnapshot, C as CallTranscript, h as CallTranscriptSegment, i as CartesiaTtsModel, j as ClipResult, k as ClosingTurnResult, l as CreditsLowEvent, D as DEFAULT_APPROACHING_END_LEAD_SECONDS, m as DEFAULT_CREDITS_LOW_LEAD_SECONDS, n as DEFAULT_GOVERNOR_CONFIG, o as DEFAULT_GRACE_CEILING_SECONDS, p as DEFAULT_GRACE_WINDOW_LEAD_SECONDS, q as DEFAULT_IDLE_SECONDS, r as DEFAULT_IDLE_WARN_LEAD_SECONDS, s as DEFAULT_TURN_TIMEOUT_SECONDS, E as EndReason, t as EndedEvent, u as ExtendResult, F as FishTtsModel, v as FreezeReadingFn, G as Governor, w as GovernorAction, x as GovernorConfig, y as GovernorSignal, z as GovernorState, H as GraceWindowClosedEvent, I as GraceWindowOpenEvent, J as GraceWindowState, K as IdleWarningEvent, M as InboundRtpCursor, N as InboundRtpReading, O as KnownBehaviorState, P as LLMProvider, Q as LLMSelection, R as LiveKitAvatarGrantState, S as LiveKitAvatarGrantStatus, T as LiveKitCapacityState, U as LiveKitConnectionStatus, V as LiveKitSessionRequest, W as LiveKitSessionStartResult, aM as LivePlaybackKeeper, X as MAX_RECONNECT_ATTEMPTS, Y as MAX_SESSION_INSTRUCTIONS_CHARS, aN as MIC_LEASE_ENDED_TIMEOUT_MS, aO as MicLease, aP as NETWORK_QUALITY_POLICY, aQ as NetworkQualityStatus, aR as PlayableVideoElement, Z as ProxyClientOptions, _ as QualityCap, $ as RECONNECT_BACKOFF_MS, aS as RealtimeAvatarCapacityError, aT as RealtimeAvatarLiveKitRoom, aU as RealtimeAvatarLiveKitRoomProps, a0 as RealtimeAvatarRequestOptions, a1 as RealtimeSessionApi, a2 as RealtimeSessionMedia, a3 as RealtimeSessionRoomSinks, a4 as ReconnectPolicy, a5 as ReconnectingEvent, a6 as RecoveryState, a7 as RetryStep, a8 as SessionBehavior, a9 as SessionClip, aa as SessionClocks, ab as SessionEndReason, ac as SessionLifecycleApi, ad as SessionLifecyclePhase, ae as SessionLifecyclePhaseKind, af as SessionLifecycleRoomBridge, ag as SessionLifecycleRoomBridgeProps, ah as SurfaceLayers, ai as TurnState, aj as TurnTimeoutEvent, ak as UseAvatarQualityGovernorInput, al as UseLiveKitAvatarGrantInput, am as UseRealtimeSessionInput, an as UseSessionLifecycleInput, ao as VoiceSpec, ap as VoiceSpecInput, aq as capacityErrorFromBusy, ar as capacityStateFromGrant, as as createProxyClient, au as knownBehaviorStates, av as mapTurnState, aw as readInboundRtp, ax as sessionBehaviorSchema, ay as sessionClipSchema, aV as shouldReplayPendingTurn, az as splitCallTranscript, aA as useAvatarAdaptivePlayoutDelay, aB as useAvatarPlayoutDelay, aC as useAvatarQualityGovernor, aD as useCallTranscript, aE as useLiveKitAvatarGrant, aG as useMicLease, aH as useRealtimeSession, aI as useReleaseMicLeaseOnTrackEnded, aJ as useSessionLifecycle } from './proxy-client-BoUJWSkf.js';
3
+ import { g as AvatarSessionClient, A as AvatarVideoFit } from './proxy-client-DhVdbfQX.js';
4
+ export { a as AdaptivePlayoutController, b as AdaptivePlayoutDecision, c as AdaptivePlayoutOptions, d as AdaptivePlayoutSample, e as ApproachingEndEvent, f as ApproachingEndReason, aK as AvatarVideoSurface, aL as AvatarVideoSurfaceProps, B as BehaviorSnapshot, C as CallTranscript, h as CallTranscriptSegment, i as CartesiaTtsModel, j as ClipResult, k as ClosingTurnResult, l as CreditsLowEvent, D as DEFAULT_APPROACHING_END_LEAD_SECONDS, m as DEFAULT_CREDITS_LOW_LEAD_SECONDS, n as DEFAULT_GOVERNOR_CONFIG, o as DEFAULT_GRACE_CEILING_SECONDS, p as DEFAULT_GRACE_WINDOW_LEAD_SECONDS, q as DEFAULT_IDLE_SECONDS, r as DEFAULT_IDLE_WARN_LEAD_SECONDS, s as DEFAULT_TURN_TIMEOUT_SECONDS, E as EndReason, t as EndedEvent, u as ExtendResult, F as FishTtsModel, v as FreezeReadingFn, G as Governor, w as GovernorAction, x as GovernorConfig, y as GovernorSignal, z as GovernorState, H as GraceWindowClosedEvent, I as GraceWindowOpenEvent, J as GraceWindowState, K as IdleWarningEvent, M as InboundRtpCursor, N as InboundRtpReading, O as KnownBehaviorState, P as LLMProvider, Q as LLMSelection, R as LiveKitAvatarGrantState, S as LiveKitAvatarGrantStatus, T as LiveKitCapacityState, U as LiveKitConnectionStatus, V as LiveKitSessionRequest, W as LiveKitSessionStartResult, aM as LivePlaybackKeeper, X as MAX_RECONNECT_ATTEMPTS, Y as MAX_SESSION_INSTRUCTIONS_CHARS, aN as MIC_LEASE_ENDED_TIMEOUT_MS, aO as MicLease, aP as NETWORK_QUALITY_POLICY, aQ as NetworkQualityStatus, aR as PlayableVideoElement, Z as ProxyClientOptions, _ as QualityCap, $ as RECONNECT_BACKOFF_MS, aS as RealtimeAvatarCapacityError, aT as RealtimeAvatarLiveKitRoom, aU as RealtimeAvatarLiveKitRoomProps, a0 as RealtimeAvatarRequestOptions, a1 as RealtimeSessionApi, a2 as RealtimeSessionMedia, a3 as RealtimeSessionRoomSinks, a4 as ReconnectPolicy, a5 as ReconnectingEvent, a6 as RecoveryState, a7 as RetryStep, a8 as SessionBehavior, a9 as SessionClip, aa as SessionClocks, ab as SessionEndReason, ac as SessionLifecycleApi, ad as SessionLifecyclePhase, ae as SessionLifecyclePhaseKind, af as SessionLifecycleRoomBridge, ag as SessionLifecycleRoomBridgeProps, ah as SurfaceLayers, ai as TurnState, aj as TurnTimeoutEvent, ak as UseAvatarQualityGovernorInput, al as UseLiveKitAvatarGrantInput, am as UseRealtimeSessionInput, an as UseSessionLifecycleInput, ao as VoiceSpec, ap as VoiceSpecInput, aq as capacityErrorFromBusy, ar as capacityStateFromGrant, as as createProxyClient, au as knownBehaviorStates, av as mapTurnState, aw as readInboundRtp, ax as sessionBehaviorSchema, ay as sessionClipSchema, aV as shouldReplayPendingTurn, az as splitCallTranscript, aA as useAvatarAdaptivePlayoutDelay, aB as useAvatarPlayoutDelay, aC as useAvatarQualityGovernor, aD as useCallTranscript, aE as useLiveKitAvatarGrant, aG as useMicLease, aH as useRealtimeSession, aI as useReleaseMicLeaseOnTrackEnded, aJ as useSessionLifecycle } from './proxy-client-DhVdbfQX.js';
5
5
  export { D as DEFAULT_AVATAR_PLAYOUT_DELAY_SECONDS } from './playout-delay-DWOc8iCl.js';
6
6
  import 'zod';
7
7
  import '@livekit/components-react';
package/dist/react.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { useRef, useState, useEffect, useCallback, useMemo, createElement, Fragment } from 'react';
3
3
  import { useRoomContext, useConnectionState, useTranscriptions, useLocalParticipant, RoomAudioRenderer, LiveKitRoom, useMaybeRoomContext, useVoiceAssistant, VideoTrack, useChat } from '@livekit/components-react';
4
- import { ConnectionState, VideoQuality, ConnectionQuality, RoomEvent, TrackEvent, Track, ConnectionError, ConnectionErrorReason, DisconnectReason, Room } from 'livekit-client';
4
+ import { ConnectionState, isRemoteTrack, VideoQuality, ConnectionQuality, RoomEvent, TrackEvent, Track, ConnectionError, ConnectionErrorReason, DisconnectReason, Room } from 'livekit-client';
5
5
  import { z } from 'zod';
6
6
 
7
7
  // ../client/src/react/use-character-tools.ts
@@ -880,10 +880,8 @@ function useAvatarAdaptivePlayoutDelay(videoTrack, audioTrack, enabled = false,
880
880
  const audioMediaTrack = audioTrack?.publication?.track;
881
881
  useEffect(() => {
882
882
  if (!enabled || !videoMediaTrack && !audioMediaTrack) return;
883
- const receivers = [videoMediaTrack, audioMediaTrack].map((t) => t?.receiver).filter(
884
- (r) => typeof r?.getStats === "function"
885
- );
886
- if (receivers.length === 0) return;
883
+ const tracks = [videoMediaTrack, audioMediaTrack].filter(isRemoteTrack);
884
+ if (tracks.length === 0) return;
887
885
  const controller = new AdaptivePlayoutController(options);
888
886
  const cursors = /* @__PURE__ */ new Map();
889
887
  let closed = false;
@@ -893,9 +891,9 @@ function useAvatarAdaptivePlayoutDelay(videoTrack, audioTrack, enabled = false,
893
891
  inFlight = true;
894
892
  try {
895
893
  let worst;
896
- for (let i = 0; i < receivers.length; i++) {
897
- const stats = await receivers[i].getStats();
898
- if (closed || typeof stats?.values !== "function") continue;
894
+ for (let i = 0; i < tracks.length; i++) {
895
+ const stats = await tracks[i].getRTCStatsReport();
896
+ if (closed || !stats) continue;
899
897
  const reading = readInboundRtp(stats.values(), cursors.get(i));
900
898
  if (!reading) continue;
901
899
  cursors.set(i, reading.cursor);
@@ -1218,20 +1216,6 @@ function bindNetworkQuality(publication, inhibited, notify, tickMs) {
1218
1216
  }
1219
1217
 
1220
1218
  // ../client/src/react/use-quality-governor.ts
1221
- var qualityToSignal = (q) => {
1222
- switch (q) {
1223
- case ConnectionQuality.Excellent:
1224
- return "excellent";
1225
- case ConnectionQuality.Good:
1226
- return "good";
1227
- case ConnectionQuality.Poor:
1228
- return "poor";
1229
- case ConnectionQuality.Lost:
1230
- return "lost";
1231
- default:
1232
- return "unknown";
1233
- }
1234
- };
1235
1219
  function useAvatarQualityGovernor(input) {
1236
1220
  const { enabled, freezeReading, onNetworkStatusChange, config: policy = DEFAULT_GOVERNOR_CONFIG, tickMs = 1e3 } = input;
1237
1221
  const room = useMaybeRoomContext();
@@ -1295,16 +1279,14 @@ function useAvatarQualityGovernor(input) {
1295
1279
  let pausedSinceTick = false;
1296
1280
  let lastFreezeStat = null;
1297
1281
  let jitterTrend = null;
1298
- let connQuality = qualityToSignal(
1299
- targetParticipant?.connectionQuality ?? ConnectionQuality.Unknown
1300
- );
1282
+ let connQuality = targetParticipant?.connectionQuality ?? ConnectionQuality.Unknown;
1301
1283
  const onStreamState = (pub, streamState) => {
1302
1284
  if (pub !== targetPublication) return;
1303
1285
  if (streamState === Track.StreamState.Paused) pausedSinceTick = true;
1304
1286
  };
1305
1287
  const onQuality = (q, participant) => {
1306
1288
  if (participant.sid !== targetParticipant.sid) return;
1307
- connQuality = qualityToSignal(q);
1289
+ connQuality = q;
1308
1290
  };
1309
1291
  try {
1310
1292
  room.on(RoomEvent.TrackStreamStateChanged, onStreamState);
package/dist/server.js CHANGED
@@ -1 +1 @@
1
- export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, clipLibraryDeclarationSchema, isQueued, verifyTranscript } from './chunk-UVNDDNU2.js';
1
+ export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, clipLibraryDeclarationSchema, isQueued, verifyTranscript } from './chunk-UZQXZH2Z.js';
@@ -1,5 +1,5 @@
1
- import { createProxyHandler } from './chunk-NOHMMTFR.js';
2
- import './chunk-UVNDDNU2.js';
1
+ import { createProxyHandler } from './chunk-B3AHTJ3J.js';
2
+ import './chunk-UZQXZH2Z.js';
3
3
 
4
4
  // src/tanstack-start.ts
5
5
  function realtimeAvatarServerRoute(config) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "realtime-avatar",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "Realtime Avatar SDK. `realtime-avatar` and the route adapters hold your API key and are server-only; `realtime-avatar/react`, `/browser` and `/tools` never can — importing a server entry into a browser build throws at bundle time.",
5
5
  "license": "MIT",
6
6
  "author": "The Influence Company",