@runwayml/avatars-react 0.7.1 → 0.8.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
@@ -24,7 +24,7 @@ import { AvatarCall } from '@runwayml/avatars-react';
24
24
  function App() {
25
25
  return (
26
26
  <AvatarCall
27
- avatarId="game-host"
27
+ avatarId="music-superstar"
28
28
  connectUrl="/api/avatar/connect"
29
29
  />
30
30
  );
@@ -33,7 +33,7 @@ function App() {
33
33
 
34
34
  That's it! The component handles session creation, WebRTC connection, and renders a default UI with the avatar video and controls.
35
35
 
36
- You can use preset avatars like `game-host`, `coding-teacher`, `language-tutor`, and more. See the [Runway Developer Portal](https://dev.runwayml.com/) for the full list and creating custom avatars.
36
+ You can use preset avatars like `music-superstar`, `cat-character`, `fashion-designer`, `cooking-teacher`, and more. See the [Runway Developer Portal](https://dev.runwayml.com/) for the full list and creating custom avatars.
37
37
 
38
38
  ### Optional: Add Default Styles
39
39
 
@@ -71,36 +71,41 @@ npm install
71
71
  ## How It Works
72
72
 
73
73
  1. **Client** calls your server endpoint with the `avatarId`
74
- 2. **Server** uses your Runway API secret to create a session via `@runwayml/sdk`
75
- 3. **Server** returns connection credentials (token, URL) to the client
74
+ 2. **Server** uses your Runway API secret to create a realtime session via `@runwayml/sdk`
75
+ 3. **Server** polls until the session is ready, then returns `sessionId` and `sessionKey` to the client
76
76
  4. **Client** establishes a WebRTC connection for real-time video/audio
77
77
 
78
78
  This flow keeps your API secret secure on the server while enabling low-latency communication.
79
79
 
80
80
  ## Server Setup
81
81
 
82
- Your server endpoint receives the `avatarId` and returns session credentials. Use `@runwayml/sdk` to create the session:
82
+ Your server endpoint receives the `avatarId` and returns session credentials. Use `@runwayml/sdk` to create and poll the session:
83
83
 
84
84
  ```ts
85
85
  // /api/avatar/connect (Next.js App Router example)
86
86
  import Runway from '@runwayml/sdk';
87
87
 
88
- const runway = new Runway(); // Uses RUNWAYML_API_SECRET env var
88
+ const client = new Runway(); // Uses RUNWAYML_API_SECRET env var
89
89
 
90
90
  export async function POST(req: Request) {
91
91
  const { avatarId } = await req.json();
92
92
 
93
- const session = await runway.realtime.sessions.create({
93
+ const { id: sessionId } = await client.realtimeSessions.create({
94
94
  model: 'gwm1_avatars',
95
- options: { avatar: avatarId },
95
+ avatar: { type: 'runway-preset', presetId: avatarId },
96
96
  });
97
97
 
98
- return Response.json({
99
- sessionId: session.id,
100
- serverUrl: session.url,
101
- token: session.token,
102
- roomName: session.room_name,
103
- });
98
+ // Poll until the session is ready
99
+ const deadline = Date.now() + 30_000;
100
+ while (Date.now() < deadline) {
101
+ const session = await client.realtimeSessions.retrieve(sessionId);
102
+ if (session.status === 'READY') {
103
+ return Response.json({ sessionId, sessionKey: session.sessionKey });
104
+ }
105
+ await new Promise((resolve) => setTimeout(resolve, 1_000));
106
+ }
107
+
108
+ return Response.json({ error: 'Session creation timed out' }, { status: 504 });
104
109
  }
105
110
  ```
106
111
 
@@ -112,7 +117,7 @@ For more control over the connection flow:
112
117
 
113
118
  ```tsx
114
119
  <AvatarCall
115
- avatarId="game-host"
120
+ avatarId="music-superstar"
116
121
  connect={async (avatarId) => {
117
122
  const res = await fetch('/api/avatar/connect', {
118
123
  method: 'POST',
@@ -134,7 +139,7 @@ Use the built-in components for custom layouts:
134
139
  ```tsx
135
140
  import { AvatarCall, AvatarVideo, ControlBar, UserVideo } from '@runwayml/avatars-react';
136
141
 
137
- <AvatarCall avatarId="game-host" connectUrl="/api/avatar/connect">
142
+ <AvatarCall avatarId="music-superstar" connectUrl="/api/avatar/connect">
138
143
  <div className="call-layout">
139
144
  <AvatarVideo className="avatar" />
140
145
  <UserVideo className="self-view" />
@@ -163,7 +168,7 @@ All components support render props for complete control:
163
168
  Style connection states with CSS:
164
169
 
165
170
  ```tsx
166
- <AvatarCall avatarId="game-host" connectUrl="/api/avatar/connect" className="my-avatar" />
171
+ <AvatarCall avatarId="music-superstar" connectUrl="/api/avatar/connect" className="my-avatar" />
167
172
  ```
168
173
 
169
174
  ```css
@@ -184,7 +189,7 @@ Style connection states with CSS:
184
189
 
185
190
  ```tsx
186
191
  <AvatarCall
187
- avatarId="game-host"
192
+ avatarId="music-superstar"
188
193
  connectUrl="/api/avatar/connect"
189
194
  onEnd={() => console.log('Call ended')}
190
195
  onError={(error) => console.error('Error:', error)}
package/dist/index.cjs CHANGED
@@ -27,12 +27,54 @@ async function consumeSession(options) {
27
27
  }
28
28
  return response.json();
29
29
  }
30
- function useLatest(value) {
31
- const ref = react.useRef(value);
30
+ var IDLE_STATE = { status: "idle" };
31
+ var cache = /* @__PURE__ */ new Map();
32
+ var subscribers = /* @__PURE__ */ new Set();
33
+ function notifySubscribers() {
34
+ for (const callback of subscribers) {
35
+ callback();
36
+ }
37
+ }
38
+ function subscribe(callback) {
39
+ subscribers.add(callback);
40
+ return () => {
41
+ subscribers.delete(callback);
42
+ };
43
+ }
44
+ function getSnapshot(key) {
45
+ const entry = cache.get(key);
46
+ return entry?.state ?? IDLE_STATE;
47
+ }
48
+ function useQuery(options) {
49
+ const { queryKey, queryFn, enabled = true, onError } = options;
50
+ const state = react.useSyncExternalStore(
51
+ subscribe,
52
+ () => getSnapshot(queryKey),
53
+ () => getSnapshot(queryKey)
54
+ );
32
55
  react.useEffect(() => {
33
- ref.current = value;
34
- }, [value]);
35
- return ref;
56
+ if (!enabled) return;
57
+ const entry = cache.get(queryKey);
58
+ if (entry && entry.state.status !== "idle") {
59
+ return;
60
+ }
61
+ const promise = queryFn();
62
+ cache.set(queryKey, {
63
+ state: { status: "loading" },
64
+ promise
65
+ });
66
+ notifySubscribers();
67
+ promise.then((data) => {
68
+ cache.set(queryKey, { state: { status: "success", data } });
69
+ notifySubscribers();
70
+ }).catch((err) => {
71
+ const error = err instanceof Error ? err : new Error(String(err));
72
+ cache.set(queryKey, { state: { status: "error", error } });
73
+ notifySubscribers();
74
+ onError?.(error);
75
+ });
76
+ }, [queryKey, enabled, queryFn, onError]);
77
+ return state;
36
78
  }
37
79
 
38
80
  // src/hooks/useCredentials.ts
@@ -76,58 +118,41 @@ function useCredentials(options) {
76
118
  baseUrl,
77
119
  onError
78
120
  } = options;
79
- const onErrorRef = useLatest(onError);
80
- const connectRef = useLatest(connect);
81
- const fetchedKeyRef = react.useRef(null);
82
- const [state, setState] = react.useState(() => {
83
- if (directCredentials) {
84
- return { status: "ready", credentials: directCredentials, error: null };
85
- }
86
- return { status: "loading", credentials: null, error: null };
121
+ const queryKey = `credentials:${avatarId}:${sessionId}:${sessionKey}:${connectUrl}:${baseUrl}`;
122
+ const queryFn = react.useCallback(
123
+ () => fetchCredentials({
124
+ avatarId,
125
+ sessionId,
126
+ sessionKey,
127
+ connectUrl,
128
+ connect,
129
+ baseUrl
130
+ }),
131
+ [avatarId, sessionId, sessionKey, connectUrl, connect, baseUrl]
132
+ );
133
+ const query = useQuery({
134
+ queryKey,
135
+ queryFn,
136
+ enabled: !directCredentials,
137
+ onError
87
138
  });
139
+ if (directCredentials) {
140
+ return { status: "ready", credentials: directCredentials, error: null };
141
+ }
142
+ if (query.status === "success") {
143
+ return { status: "ready", credentials: query.data, error: null };
144
+ }
145
+ if (query.status === "error") {
146
+ return { status: "error", credentials: null, error: query.error };
147
+ }
148
+ return { status: "loading", credentials: null, error: null };
149
+ }
150
+ function useLatest(value) {
151
+ const ref = react.useRef(value);
88
152
  react.useEffect(() => {
89
- if (directCredentials) {
90
- setState({
91
- status: "ready",
92
- credentials: directCredentials,
93
- error: null
94
- });
95
- return;
96
- }
97
- const credentialKey = `${avatarId}:${sessionId}:${sessionKey}:${connectUrl}:${baseUrl}`;
98
- if (fetchedKeyRef.current === credentialKey) return;
99
- fetchedKeyRef.current = credentialKey;
100
- let cancelled = false;
101
- setState({ status: "loading", credentials: null, error: null });
102
- async function load() {
103
- try {
104
- const fetchOptions = {
105
- avatarId,
106
- sessionId,
107
- sessionKey,
108
- connectUrl,
109
- connect: connectRef.current ?? void 0,
110
- baseUrl
111
- };
112
- const credentials = await fetchCredentials(fetchOptions);
113
- if (!cancelled) {
114
- setState({ status: "ready", credentials, error: null });
115
- }
116
- } catch (err) {
117
- if (!cancelled) {
118
- const error = err instanceof Error ? err : new Error(String(err));
119
- setState({ status: "error", credentials: null, error });
120
- onErrorRef.current?.(error);
121
- }
122
- }
123
- }
124
- load();
125
- return () => {
126
- cancelled = true;
127
- fetchedKeyRef.current = null;
128
- };
129
- }, [directCredentials, avatarId, sessionId, sessionKey, connectUrl, baseUrl]);
130
- return state;
153
+ ref.current = value;
154
+ }, [value]);
155
+ return ref;
131
156
  }
132
157
  async function hasMediaDevice(kind, timeoutMs = 1e3) {
133
158
  try {
@@ -167,6 +192,15 @@ function useDeviceAvailability(requestAudio, requestVideo) {
167
192
  }, [requestAudio, requestVideo]);
168
193
  return state;
169
194
  }
195
+ var MEDIA_DEVICE_ERROR_NAMES = /* @__PURE__ */ new Set([
196
+ "NotAllowedError",
197
+ "NotFoundError",
198
+ "NotReadableError",
199
+ "OverconstrainedError"
200
+ ]);
201
+ function isMediaDeviceError(error) {
202
+ return MEDIA_DEVICE_ERROR_NAMES.has(error.name);
203
+ }
170
204
  var DEFAULT_ROOM_OPTIONS = {
171
205
  adaptiveStream: false,
172
206
  dynacast: false
@@ -200,8 +234,10 @@ function AvatarSession({
200
234
  const errorRef = react.useRef(null);
201
235
  const deviceAvailability = useDeviceAvailability(requestAudio, requestVideo);
202
236
  const handleError = (error) => {
203
- errorRef.current = error;
204
237
  onError?.(error);
238
+ if (!isMediaDeviceError(error)) {
239
+ errorRef.current = error;
240
+ }
205
241
  };
206
242
  const roomOptions = {
207
243
  ...DEFAULT_ROOM_OPTIONS,
@@ -568,6 +604,8 @@ function AvatarCall({
568
604
  connectUrl,
569
605
  connect,
570
606
  baseUrl,
607
+ audio,
608
+ video,
571
609
  avatarImageUrl,
572
610
  onEnd,
573
611
  onError,
@@ -619,6 +657,8 @@ function AvatarCall({
619
657
  AvatarSession,
620
658
  {
621
659
  credentials: credentialsState.credentials,
660
+ audio,
661
+ video,
622
662
  onEnd,
623
663
  onError: handleSessionError,
624
664
  __unstable_roomOptions,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/config.ts","../src/api/consume.ts","../src/hooks/useLatest.ts","../src/hooks/useCredentials.ts","../src/components/AvatarSession.tsx","../src/hooks/useAvatar.ts","../src/hooks/useAvatarSession.ts","../src/hooks/useAvatarStatus.ts","../src/components/AvatarVideo.tsx","../src/hooks/useLocalMedia.ts","../src/components/ControlBar.tsx","../src/components/UserVideo.tsx","../src/components/AvatarCall.tsx","../src/components/ScreenShareVideo.tsx"],"names":["useRef","useEffect","useState","ConnectionState","createContext","jsxs","LiveKitRoom","jsx","RoomAudioRenderer","useRoomContext","useConnectionState","useCallback","useContext","useRemoteParticipants","useTracks","Track","isTrackReference","Fragment","VideoTrack","useLocalParticipant","useMediaDevices","TrackToggle"],"mappings":"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","file":"index.cjs","sourcesContent":["export const DEFAULT_BASE_URL = 'https://api.dev.runwayml.com';\n","import type { ConsumeSessionOptions, ConsumeSessionResponse } from '../types';\nimport { DEFAULT_BASE_URL } from './config';\n\nexport async function consumeSession(\n options: ConsumeSessionOptions,\n): Promise<ConsumeSessionResponse> {\n const { sessionId, sessionKey, baseUrl = DEFAULT_BASE_URL } = options;\n\n const url = `${baseUrl}/v1/realtime_sessions/${sessionId}/consume`;\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${sessionKey}`,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to consume session: ${response.status} ${errorText}`,\n );\n }\n\n return response.json();\n}\n","'use client';\n\nimport { useEffect, useRef } from 'react';\n\nexport function useLatest<T>(value: T): React.RefObject<T> {\n const ref = useRef(value);\n\n useEffect(() => {\n ref.current = value;\n }, [value]);\n\n return ref;\n}\n","'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport { consumeSession } from '../api/consume';\nimport type { SessionCredentials } from '../types';\nimport { useLatest } from './useLatest';\n\nexport interface UseCredentialsOptions {\n avatarId: string;\n sessionId?: string;\n sessionKey?: string;\n credentials?: SessionCredentials;\n connectUrl?: string;\n connect?: (avatarId: string) => Promise<SessionCredentials>;\n baseUrl?: string;\n onError?: (error: Error) => void;\n}\n\nexport type CredentialsState =\n | { status: 'loading'; credentials: null; error: null }\n | { status: 'ready'; credentials: SessionCredentials; error: null }\n | { status: 'error'; credentials: null; error: Error };\n\nasync function fetchCredentials(\n options: UseCredentialsOptions,\n): Promise<SessionCredentials> {\n const { avatarId, sessionId, sessionKey, connectUrl, connect, baseUrl } =\n options;\n\n if (sessionId && sessionKey) {\n const { url, token, roomName } = await consumeSession({\n sessionId,\n sessionKey,\n baseUrl,\n });\n return { sessionId, serverUrl: url, token, roomName };\n }\n\n if (connect) {\n return connect(avatarId);\n }\n\n if (connectUrl) {\n const response = await fetch(connectUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ avatarId }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to connect: ${response.status} ${errorText}`);\n }\n\n return response.json();\n }\n\n throw new Error(\n 'AvatarCall requires one of: credentials, sessionId+sessionKey, connectUrl, or connect',\n );\n}\n\nexport function useCredentials(\n options: UseCredentialsOptions,\n): CredentialsState {\n const {\n credentials: directCredentials,\n avatarId,\n sessionId,\n sessionKey,\n connectUrl,\n connect,\n baseUrl,\n onError,\n } = options;\n\n const onErrorRef = useLatest(onError);\n const connectRef = useLatest(connect);\n\n const fetchedKeyRef = useRef<string | null>(null);\n\n const [state, setState] = useState<CredentialsState>(() => {\n if (directCredentials) {\n return { status: 'ready', credentials: directCredentials, error: null };\n }\n return { status: 'loading', credentials: null, error: null };\n });\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs are stable - we read .current at call time\n useEffect(() => {\n if (directCredentials) {\n setState({\n status: 'ready',\n credentials: directCredentials,\n error: null,\n });\n return;\n }\n\n const credentialKey = `${avatarId}:${sessionId}:${sessionKey}:${connectUrl}:${baseUrl}`;\n\n if (fetchedKeyRef.current === credentialKey) return;\n fetchedKeyRef.current = credentialKey;\n\n let cancelled = false;\n setState({ status: 'loading', credentials: null, error: null });\n\n async function load() {\n try {\n const fetchOptions: UseCredentialsOptions = {\n avatarId,\n sessionId,\n sessionKey,\n connectUrl,\n connect: connectRef.current ?? undefined,\n baseUrl,\n };\n const credentials = await fetchCredentials(fetchOptions);\n if (!cancelled) {\n setState({ status: 'ready', credentials, error: null });\n }\n } catch (err) {\n if (!cancelled) {\n const error = err instanceof Error ? err : new Error(String(err));\n setState({ status: 'error', credentials: null, error });\n onErrorRef.current?.(error);\n }\n }\n }\n\n load();\n\n return () => {\n cancelled = true;\n fetchedKeyRef.current = null;\n };\n }, [directCredentials, avatarId, sessionId, sessionKey, connectUrl, baseUrl]);\n\n return state;\n}\n","'use client';\n\n/**\n * AvatarSession Component\n *\n * Provides the session context for avatar interactions.\n * Manages the WebRTC connection and exposes a clean API for child components.\n *\n * @example\n * ```tsx\n * <AvatarSession credentials={credentials} onEnd={handleEnd}>\n * <AvatarVideo />\n * <ControlBar />\n * </AvatarSession>\n * ```\n */\n\nimport {\n LiveKitRoom,\n RoomAudioRenderer,\n useConnectionState,\n useRoomContext,\n} from '@livekit/components-react';\nimport type { RoomOptions } from 'livekit-client';\nimport { ConnectionState } from 'livekit-client';\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport type {\n AvatarSessionContextValue,\n AvatarSessionProps,\n SessionState,\n} from '../types';\n\n/**\n * Check if a media device of the given kind is available\n * Returns within timeout to avoid blocking the connection\n */\nasync function hasMediaDevice(\n kind: 'audioinput' | 'videoinput',\n timeoutMs = 1000,\n): Promise<boolean> {\n try {\n const timeoutPromise = new Promise<boolean>((resolve) =>\n setTimeout(() => resolve(false), timeoutMs),\n );\n const checkPromise = navigator.mediaDevices\n .enumerateDevices()\n .then((devices) => devices.some((device) => device.kind === kind));\n\n return await Promise.race([checkPromise, timeoutPromise]);\n } catch {\n return false;\n }\n}\n\n/**\n * Hook to check device availability before connecting.\n * Completes quickly to avoid blocking the connection.\n */\nfunction useDeviceAvailability(\n requestAudio: boolean,\n requestVideo: boolean,\n): { audio: boolean; video: boolean } {\n const [state, setState] = useState({\n audio: requestAudio, // Optimistically assume devices exist\n video: requestVideo,\n });\n\n useEffect(() => {\n let cancelled = false;\n\n async function checkDevices() {\n const [hasAudio, hasVideo] = await Promise.all([\n requestAudio ? hasMediaDevice('audioinput') : Promise.resolve(false),\n requestVideo ? hasMediaDevice('videoinput') : Promise.resolve(false),\n ]);\n\n if (!cancelled) {\n setState({\n audio: requestAudio && hasAudio,\n video: requestVideo && hasVideo,\n });\n }\n }\n\n checkDevices();\n\n return () => {\n cancelled = true;\n };\n }, [requestAudio, requestVideo]);\n\n return state;\n}\n\nconst DEFAULT_ROOM_OPTIONS: RoomOptions = {\n adaptiveStream: false,\n dynacast: false,\n};\n\n/**\n * Maps WebRTC connection state to session state\n */\nfunction mapConnectionState(connectionState: ConnectionState): SessionState {\n switch (connectionState) {\n case ConnectionState.Connecting:\n return 'connecting';\n case ConnectionState.Connected:\n return 'active';\n case ConnectionState.Reconnecting:\n return 'connecting';\n case ConnectionState.Disconnected:\n return 'ended';\n default:\n return 'ended';\n }\n}\n\nconst AvatarSessionContext = createContext<AvatarSessionContextValue | null>(\n null,\n);\n\n/**\n * AvatarSession component - the main entry point for avatar sessions\n *\n * Establishes a WebRTC connection and provides session state to children.\n * This is a headless component that renders minimal DOM.\n */\nexport function AvatarSession({\n credentials,\n children,\n audio: requestAudio = true,\n video: requestVideo = true,\n onEnd,\n onError,\n __unstable_roomOptions,\n}: AvatarSessionProps) {\n const errorRef = useRef<Error | null>(null);\n\n const deviceAvailability = useDeviceAvailability(requestAudio, requestVideo);\n\n const handleError = (error: Error) => {\n errorRef.current = error;\n onError?.(error);\n };\n\n const roomOptions = {\n ...DEFAULT_ROOM_OPTIONS,\n ...__unstable_roomOptions,\n };\n\n return (\n <LiveKitRoom\n serverUrl={credentials.serverUrl}\n token={credentials.token}\n connect={true}\n audio={deviceAvailability.audio}\n video={deviceAvailability.video}\n onDisconnected={() => onEnd?.()}\n onError={handleError}\n options={roomOptions}\n connectOptions={{\n autoSubscribe: true,\n }}\n >\n <AvatarSessionContextInner\n sessionId={credentials.sessionId}\n onEnd={onEnd}\n errorRef={errorRef}\n >\n {children}\n </AvatarSessionContextInner>\n <RoomAudioRenderer />\n </LiveKitRoom>\n );\n}\n\n/**\n * Inner context provider that has access to the room context\n */\nfunction AvatarSessionContextInner({\n sessionId,\n onEnd,\n errorRef,\n children,\n}: {\n sessionId: string;\n onEnd?: () => void;\n errorRef: React.RefObject<Error | null>;\n children: ReactNode;\n}) {\n const room = useRoomContext();\n const connectionState = useConnectionState();\n const onEndRef = useRef(onEnd);\n onEndRef.current = onEnd;\n\n const end = useCallback(async () => {\n try {\n // Send END_CALL message to the avatar\n const encoder = new TextEncoder();\n const data = encoder.encode(JSON.stringify({ type: 'END_CALL' }));\n await room.localParticipant.publishData(data, { reliable: true });\n } catch {\n // Ignore errors when sending end message\n }\n\n await room.disconnect();\n onEndRef.current?.();\n }, [room]);\n\n const contextValue: AvatarSessionContextValue = {\n state: mapConnectionState(connectionState),\n sessionId,\n error: errorRef.current,\n end,\n };\n\n return (\n <AvatarSessionContext.Provider value={contextValue}>\n {children}\n </AvatarSessionContext.Provider>\n );\n}\n\n/**\n * Hook to access the avatar session context\n * Must be used within an AvatarSession component\n */\nexport function useAvatarSessionContext(): AvatarSessionContextValue {\n const context = useContext(AvatarSessionContext);\n if (!context) {\n throw new Error(\n 'useAvatarSessionContext must be used within an AvatarSession',\n );\n }\n return context;\n}\n\n/**\n * Hook to optionally access the avatar session context\n * Returns null if not within an AvatarSession\n */\nexport function useMaybeAvatarSessionContext(): AvatarSessionContextValue | null {\n return useContext(AvatarSessionContext);\n}\n","'use client';\n\n/**\n * useAvatar Hook\n *\n * Provides access to the remote avatar participant's video track.\n * Audio is handled automatically by the session.\n *\n * Must be used within an AvatarSession or AvatarCall component.\n *\n * @example\n * ```tsx\n * function AvatarDisplay() {\n * const { videoTrackRef, hasVideo } = useAvatar();\n *\n * if (!hasVideo) {\n * return <Placeholder />;\n * }\n *\n * return <VideoTrack trackRef={videoTrackRef} />;\n * }\n * ```\n */\n\nimport {\n isTrackReference,\n useRemoteParticipants,\n useTracks,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { UseAvatarReturn } from '../types';\n\n/**\n * Hook to access the remote avatar participant's video track\n *\n * @returns Avatar participant info and video track reference\n */\nexport function useAvatar(): UseAvatarReturn {\n const remoteParticipants = useRemoteParticipants();\n const avatarParticipant = remoteParticipants[0] ?? null;\n\n // Only subscribe to video - audio is handled automatically by the session\n const videoTracks = useTracks(\n [{ source: Track.Source.Camera, withPlaceholder: true }],\n {\n onlySubscribed: true,\n updateOnlyOn: [],\n },\n ).filter((ref) => !ref.participant.isLocal);\n\n const videoTrackRef = videoTracks[0] ?? null;\n const hasVideo = videoTrackRef !== null && isTrackReference(videoTrackRef);\n\n return {\n participant: avatarParticipant,\n videoTrackRef,\n hasVideo,\n };\n}\n","'use client';\n\n/**\n * useAvatarSession Hook\n *\n * Provides access to the current avatar session state.\n * Returns a discriminated union based on session state for type-safe UI rendering.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const session = useAvatarSession();\n *\n * if (session.state === 'connecting') {\n * return <Loading />;\n * }\n *\n * if (session.state === 'error') {\n * return <Error message={session.error.message} />;\n * }\n *\n * return <ActiveSession onEnd={session.end} />;\n * }\n * ```\n */\n\nimport { useAvatarSessionContext } from '../components/AvatarSession';\nimport type { AvatarSessionContextValue } from '../types';\n\n/**\n * Discriminated union types for type-safe session state handling\n */\nexport type UseAvatarSessionReturn =\n | { state: 'idle'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'connecting'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'active'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'ending'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'ended'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'error'; sessionId: string; error: Error; end: () => Promise<void> };\n\n/**\n * Hook to access the current avatar session state\n *\n * @returns Session state as a discriminated union\n */\nexport function useAvatarSession(): UseAvatarSessionReturn {\n const context = useAvatarSessionContext();\n return context as UseAvatarSessionReturn;\n}\n\nexport type { AvatarSessionContextValue };\n","'use client';\n\n/**\n * useAvatarStatus Hook\n *\n * Returns a single discriminated union representing the full avatar lifecycle\n * inside an AvatarSession. Combines session connection state and video\n * track availability into one status value.\n *\n * Must be used within <AvatarCall> or <AvatarSession>.\n *\n * @example\n * ```tsx\n * function MyAvatar() {\n * const avatar = useAvatarStatus();\n *\n * switch (avatar.status) {\n * case 'connecting':\n * return <Spinner />;\n * case 'waiting':\n * return <p>Waiting for video...</p>;\n * case 'ready':\n * return <VideoTrack trackRef={avatar.videoTrackRef} />;\n * case 'error':\n * return <p>{avatar.error.message}</p>;\n * case 'ended':\n * return <p>Call ended</p>;\n * }\n * }\n * ```\n */\n\nimport type { TrackReferenceOrPlaceholder } from '@livekit/components-react';\nimport { useAvatar } from './useAvatar';\nimport { useAvatarSession } from './useAvatarSession';\n\nexport type AvatarStatus =\n | { status: 'connecting' }\n | { status: 'waiting' }\n | { status: 'ready'; videoTrackRef: TrackReferenceOrPlaceholder }\n | { status: 'ending' }\n | { status: 'ended' }\n | { status: 'error'; error: Error };\n\nexport function useAvatarStatus(): AvatarStatus {\n const session = useAvatarSession();\n const { videoTrackRef, hasVideo } = useAvatar();\n\n switch (session.state) {\n case 'connecting':\n case 'idle':\n return { status: 'connecting' };\n\n case 'active':\n if (hasVideo && videoTrackRef) {\n return { status: 'ready', videoTrackRef };\n }\n return { status: 'waiting' };\n\n case 'ending':\n return { status: 'ending' };\n\n case 'ended':\n return { status: 'ended' };\n\n case 'error':\n return { status: 'error', error: session.error };\n }\n}\n","'use client';\n\nimport { isTrackReference, VideoTrack } from '@livekit/components-react';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { type AvatarStatus, useAvatarStatus } from '../hooks/useAvatarStatus';\n\n/** Subset of AvatarStatus relevant to the video display */\nexport type AvatarVideoStatus = Extract<\n AvatarStatus,\n { status: 'connecting' } | { status: 'waiting' } | { status: 'ready' }\n>;\n\nexport interface AvatarVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n children?: (status: AvatarVideoStatus) => ReactNode;\n}\n\nexport function AvatarVideo({ children, ...props }: AvatarVideoProps) {\n const avatar = useAvatarStatus();\n\n const videoStatus: AvatarVideoStatus =\n avatar.status === 'ready'\n ? avatar\n : avatar.status === 'connecting'\n ? { status: 'connecting' }\n : { status: 'waiting' };\n\n if (children) {\n return <>{children(videoStatus)}</>;\n }\n\n return (\n <div\n {...props}\n data-avatar-video=\"\"\n data-avatar-status={videoStatus.status}\n >\n {videoStatus.status === 'ready' &&\n isTrackReference(videoStatus.videoTrackRef) && (\n <VideoTrack trackRef={videoStatus.videoTrackRef} />\n )}\n </div>\n );\n}\n","'use client';\n\nimport {\n useLocalParticipant,\n useMediaDevices,\n useTracks,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport { useCallback } from 'react';\nimport type { UseLocalMediaReturn } from '../types';\nimport { useLatest } from './useLatest';\n\n/**\n * Hook for local media controls (mic, camera, screen share).\n *\n * Must be used within an AvatarSession or AvatarCall component.\n * For use outside the session context, use AvatarSession directly\n * and manage your own loading states.\n */\nexport function useLocalMedia(): UseLocalMediaReturn {\n const { localParticipant } = useLocalParticipant();\n\n const audioDevices = useMediaDevices({ kind: 'audioinput' });\n const videoDevices = useMediaDevices({ kind: 'videoinput' });\n\n const hasMic = audioDevices?.length > 0;\n const hasCamera = videoDevices?.length > 0;\n\n const isMicEnabled = localParticipant?.isMicrophoneEnabled ?? false;\n const isCameraEnabled = localParticipant?.isCameraEnabled ?? false;\n const isScreenShareEnabled = localParticipant?.isScreenShareEnabled ?? false;\n\n const isMicEnabledRef = useLatest(isMicEnabled);\n const isCameraEnabledRef = useLatest(isCameraEnabled);\n const isScreenShareEnabledRef = useLatest(isScreenShareEnabled);\n\n const hasMicRef = useLatest(hasMic);\n const hasCameraRef = useLatest(hasCamera);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleMic = useCallback(() => {\n if (hasMicRef.current || isMicEnabledRef.current) {\n localParticipant?.setMicrophoneEnabled(!isMicEnabledRef.current);\n }\n }, [localParticipant]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleCamera = useCallback(() => {\n if (hasCameraRef.current || isCameraEnabledRef.current) {\n localParticipant?.setCameraEnabled(!isCameraEnabledRef.current);\n }\n }, [localParticipant]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleScreenShare = useCallback(() => {\n localParticipant?.setScreenShareEnabled(!isScreenShareEnabledRef.current);\n }, [localParticipant]);\n\n const tracks = useTracks(\n [{ source: Track.Source.Camera, withPlaceholder: true }],\n {\n onlySubscribed: false,\n updateOnlyOn: [],\n },\n );\n\n const localIdentity = localParticipant?.identity;\n\n const localVideoTrackRef =\n tracks.find(\n (trackRef) =>\n trackRef.participant.identity === localIdentity &&\n trackRef.source === Track.Source.Camera,\n ) ?? null;\n\n return {\n hasMic,\n hasCamera,\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n localVideoTrackRef,\n };\n}\n","'use client';\n\nimport { TrackToggle } from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { useAvatarSession } from '../hooks/useAvatarSession';\nimport { useLocalMedia } from '../hooks/useLocalMedia';\n\nexport interface ControlBarState {\n isMicEnabled: boolean;\n isCameraEnabled: boolean;\n isScreenShareEnabled: boolean;\n toggleMic: () => void;\n toggleCamera: () => void;\n toggleScreenShare: () => void;\n endCall: () => Promise<void>;\n isActive: boolean;\n}\n\nexport interface ControlBarProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n showMicrophone?: boolean;\n showCamera?: boolean;\n showScreenShare?: boolean;\n showEndCall?: boolean;\n children?: (state: ControlBarState) => ReactNode;\n}\n\nexport function ControlBar({\n children,\n showMicrophone = true,\n showCamera = true,\n showScreenShare = false,\n showEndCall = true,\n ...props\n}: ControlBarProps) {\n const session = useAvatarSession();\n const {\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n } = useLocalMedia();\n\n const isActive = session.state === 'active';\n\n const state: ControlBarState = {\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n endCall: session.end,\n isActive,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n if (!isActive) {\n return null;\n }\n\n return (\n <div {...props} data-avatar-control-bar=\"\" data-avatar-active={isActive}>\n {showMicrophone && (\n <button\n type=\"button\"\n onClick={toggleMic}\n data-avatar-control=\"microphone\"\n data-avatar-enabled={isMicEnabled}\n aria-label={isMicEnabled ? 'Mute microphone' : 'Unmute microphone'}\n >\n {microphoneIcon}\n </button>\n )}\n {showCamera && (\n <button\n type=\"button\"\n onClick={toggleCamera}\n data-avatar-control=\"camera\"\n data-avatar-enabled={isCameraEnabled}\n aria-label={isCameraEnabled ? 'Turn off camera' : 'Turn on camera'}\n >\n {cameraIcon}\n </button>\n )}\n {showScreenShare && (\n <TrackToggle\n source={Track.Source.ScreenShare}\n showIcon={false}\n data-avatar-control=\"screen-share\"\n data-avatar-enabled={isScreenShareEnabled}\n aria-label=\"Toggle screen share\"\n >\n {screenShareIcon}\n </TrackToggle>\n )}\n {showEndCall && (\n <button\n type=\"button\"\n onClick={session.end}\n data-avatar-control=\"end-call\"\n data-avatar-enabled={true}\n aria-label=\"End call\"\n >\n {phoneIcon}\n </button>\n )}\n </div>\n );\n}\n\n// Lucide icons (https://lucide.dev) - MIT License\nconst microphoneIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\" />\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" />\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\" />\n </svg>\n);\n\nconst cameraIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5\" />\n <rect x=\"2\" y=\"6\" width=\"14\" height=\"12\" rx=\"2\" />\n </svg>\n);\n\nconst screenShareIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\" />\n <line x1=\"8\" x2=\"16\" y1=\"21\" y2=\"21\" />\n <line x1=\"12\" x2=\"12\" y1=\"17\" y2=\"21\" />\n </svg>\n);\n\nconst phoneIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"8 14 24 12\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=\"M12.8429 22.5693L11.4018 21.0986C11.2675 20.9626 11.1625 20.7995 11.0935 20.6197C11.0245 20.4399 10.9931 20.2474 11.0013 20.0545C11.0094 19.8616 11.0569 19.6726 11.1408 19.4995C11.2247 19.3265 11.343 19.1732 11.4883 19.0495C13.127 17.7049 15.0519 16.7714 17.1083 16.3239C19.0064 15.892 20.9744 15.892 22.8725 16.3239C24.9374 16.7743 26.8693 17.7147 28.5117 19.0691C28.6565 19.1924 28.7746 19.3451 28.8585 19.5176C28.9423 19.69 28.99 19.8784 28.9986 20.0707C29.0072 20.263 28.9764 20.455 28.9083 20.6345C28.8402 20.814 28.7362 20.9771 28.603 21.1133L27.1619 22.584C26.9311 22.8242 26.6226 22.9706 26.2938 22.9959C25.9651 23.0211 25.6385 22.9235 25.3751 22.7212C24.8531 22.3127 24.2875 21.9657 23.689 21.6869C23.4525 21.5774 23.2517 21.4009 23.1103 21.1785C22.969 20.9561 22.8931 20.697 22.8917 20.4319V19.1867C21.0053 18.6573 19.0139 18.6573 17.1275 19.1867V20.4319C17.1261 20.697 17.0502 20.9561 16.9089 21.1785C16.7676 21.4009 16.5667 21.5774 16.3302 21.6869C15.7317 21.9657 15.1661 22.3127 14.6442 22.7212C14.3779 22.9258 14.0473 23.0233 13.7152 22.9953C13.383 22.9673 13.0726 22.8156 12.8429 22.5693Z\" />\n </svg>\n);\n","'use client';\n\nimport { isTrackReference, VideoTrack } from '@livekit/components-react';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { useLocalMedia } from '../hooks/useLocalMedia';\nimport type { UseLocalMediaReturn } from '../types';\n\nexport interface UserVideoState {\n hasVideo: boolean;\n isCameraEnabled: boolean;\n trackRef: UseLocalMediaReturn['localVideoTrackRef'];\n}\n\nexport interface UserVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n mirror?: boolean;\n children?: (state: UserVideoState) => ReactNode;\n}\n\nexport function UserVideo({\n children,\n mirror = true,\n ...props\n}: UserVideoProps) {\n const { localVideoTrackRef, isCameraEnabled } = useLocalMedia();\n\n const hasVideo =\n localVideoTrackRef !== null && isTrackReference(localVideoTrackRef);\n\n const state: UserVideoState = {\n hasVideo,\n isCameraEnabled,\n trackRef: localVideoTrackRef,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n return (\n <div\n {...props}\n data-avatar-user-video=\"\"\n data-avatar-has-video={hasVideo}\n data-avatar-camera-enabled={isCameraEnabled}\n data-avatar-mirror={mirror}\n >\n {hasVideo &&\n localVideoTrackRef &&\n isTrackReference(localVideoTrackRef) && (\n <VideoTrack trackRef={localVideoTrackRef} />\n )}\n </div>\n );\n}\n","'use client';\n\n/**\n * AvatarCall Component\n *\n * High-level component that handles the complete session lifecycle.\n * Manages credential fetching, connection, and video display internally\n * with a seamless loading experience.\n *\n * During credential loading, shows a loading state with the avatar image.\n * Once connected, renders children inside the session context.\n *\n * For more control over the loading UI, use AvatarSession directly.\n *\n * @example\n * ```tsx\n * // Simple usage - handles everything automatically\n * <AvatarCall avatarId=\"game-host\" connectUrl=\"/api/avatar/connect\" />\n *\n * // Custom children - rendered once connected\n * <AvatarCall avatarId=\"game-host\" connectUrl=\"/api/avatar/connect\">\n * <AvatarVideo />\n * <ControlBar />\n * </AvatarCall>\n * ```\n */\n\nimport { useCredentials } from '../hooks/useCredentials';\nimport { useLatest } from '../hooks/useLatest';\nimport type { AvatarCallProps } from '../types';\nimport { AvatarSession } from './AvatarSession';\nimport { AvatarVideo } from './AvatarVideo';\nimport { ControlBar } from './ControlBar';\nimport { UserVideo } from './UserVideo';\n\nexport function AvatarCall({\n avatarId,\n sessionId,\n sessionKey,\n credentials: directCredentials,\n connectUrl,\n connect,\n baseUrl,\n avatarImageUrl,\n onEnd,\n onError,\n children,\n __unstable_roomOptions,\n ...props\n}: AvatarCallProps) {\n const onErrorRef = useLatest(onError);\n\n const credentialsState = useCredentials({\n avatarId,\n sessionId,\n sessionKey,\n credentials: directCredentials,\n connectUrl,\n connect,\n baseUrl,\n onError: (err) => onErrorRef.current?.(err),\n });\n\n const handleSessionError = (err: Error) => {\n onErrorRef.current?.(err);\n };\n\n const backgroundStyle = avatarImageUrl\n ? ({ '--avatar-image': `url(${avatarImageUrl})` } as React.CSSProperties)\n : undefined;\n\n const defaultChildren = (\n <>\n <AvatarVideo />\n <UserVideo />\n <ControlBar />\n </>\n );\n\n // During credential loading/error, show a simple loading state\n // Children are NOT rendered here because they may use hooks that require LiveKitRoom context\n if (credentialsState.status !== 'ready') {\n const status =\n credentialsState.status === 'error' ? 'error' : 'connecting';\n\n return (\n <div\n {...props}\n data-avatar-call=\"\"\n data-avatar-id={avatarId}\n style={{ ...props.style, ...backgroundStyle }}\n >\n <div data-avatar-video=\"\" data-avatar-status={status} />\n </div>\n );\n }\n\n // Once credentials are ready, render children inside the session context\n // This ensures all hooks have access to the LiveKitRoom context\n return (\n <div\n {...props}\n data-avatar-call=\"\"\n data-avatar-id={avatarId}\n style={{ ...props.style, ...backgroundStyle }}\n >\n <AvatarSession\n credentials={credentialsState.credentials}\n onEnd={onEnd}\n onError={handleSessionError}\n __unstable_roomOptions={__unstable_roomOptions}\n >\n {children ?? defaultChildren}\n </AvatarSession>\n </div>\n );\n}\n","'use client';\n\nimport {\n isTrackReference,\n type TrackReferenceOrPlaceholder,\n useLocalParticipant,\n useTracks,\n VideoTrack,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\n\nexport interface ScreenShareVideoState {\n isSharing: boolean;\n trackRef: TrackReferenceOrPlaceholder | null;\n}\n\nexport interface ScreenShareVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n children?: (state: ScreenShareVideoState) => ReactNode;\n}\n\n/**\n * Component for displaying local screen share video.\n *\n * Must be used within an AvatarSession or AvatarCall component.\n */\nexport function ScreenShareVideo({\n children,\n ...props\n}: ScreenShareVideoProps) {\n const { localParticipant } = useLocalParticipant();\n\n const tracks = useTracks(\n [{ source: Track.Source.ScreenShare, withPlaceholder: false }],\n { onlySubscribed: false },\n );\n\n const localIdentity = localParticipant?.identity;\n\n const screenShareTrackRef =\n tracks.find(\n (trackRef) =>\n trackRef.participant.identity === localIdentity &&\n trackRef.source === Track.Source.ScreenShare,\n ) ?? null;\n\n const isSharing =\n screenShareTrackRef !== null && isTrackReference(screenShareTrackRef);\n\n const state: ScreenShareVideoState = {\n isSharing,\n trackRef: screenShareTrackRef,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n if (!isSharing) {\n return null;\n }\n\n return (\n <div {...props} data-avatar-screen-share=\"\" data-avatar-sharing={isSharing}>\n {screenShareTrackRef && isTrackReference(screenShareTrackRef) && (\n <VideoTrack trackRef={screenShareTrackRef} />\n )}\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/api/config.ts","../src/api/consume.ts","../src/hooks/useQuery.ts","../src/hooks/useCredentials.ts","../src/hooks/useLatest.ts","../src/components/AvatarSession.tsx","../src/hooks/useAvatar.ts","../src/hooks/useAvatarSession.ts","../src/hooks/useAvatarStatus.ts","../src/components/AvatarVideo.tsx","../src/hooks/useLocalMedia.ts","../src/components/ControlBar.tsx","../src/components/UserVideo.tsx","../src/components/AvatarCall.tsx","../src/components/ScreenShareVideo.tsx"],"names":["useSyncExternalStore","useEffect","useCallback","useRef","useState","ConnectionState","createContext","jsxs","LiveKitRoom","jsx","RoomAudioRenderer","useRoomContext","useConnectionState","useContext","useRemoteParticipants","useTracks","Track","isTrackReference","Fragment","VideoTrack","useLocalParticipant","useMediaDevices","TrackToggle"],"mappings":"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","file":"index.cjs","sourcesContent":["export const DEFAULT_BASE_URL = 'https://api.dev.runwayml.com';\n","import type { ConsumeSessionOptions, ConsumeSessionResponse } from '../types';\nimport { DEFAULT_BASE_URL } from './config';\n\nexport async function consumeSession(\n options: ConsumeSessionOptions,\n): Promise<ConsumeSessionResponse> {\n const { sessionId, sessionKey, baseUrl = DEFAULT_BASE_URL } = options;\n\n const url = `${baseUrl}/v1/realtime_sessions/${sessionId}/consume`;\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${sessionKey}`,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to consume session: ${response.status} ${errorText}`,\n );\n }\n\n return response.json();\n}\n","'use client';\n\nimport { useEffect, useSyncExternalStore } from 'react';\n\ntype QueryState<T> =\n | { status: 'idle' }\n | { status: 'loading' }\n | { status: 'success'; data: T }\n | { status: 'error'; error: Error };\n\ninterface CacheEntry<T> {\n state: QueryState<T>;\n promise?: Promise<T>;\n}\n\nconst IDLE_STATE: QueryState<never> = { status: 'idle' };\n\nconst cache = new Map<string, CacheEntry<unknown>>();\nconst subscribers = new Set<() => void>();\n\nfunction notifySubscribers() {\n for (const callback of subscribers) {\n callback();\n }\n}\n\nfunction subscribe(callback: () => void) {\n subscribers.add(callback);\n return () => {\n subscribers.delete(callback);\n };\n}\n\nfunction getSnapshot<T>(key: string): QueryState<T> {\n const entry = cache.get(key) as CacheEntry<T> | undefined;\n return entry?.state ?? (IDLE_STATE as QueryState<T>);\n}\n\nexport interface UseQueryOptions<T> {\n queryKey: string;\n queryFn: () => Promise<T>;\n enabled?: boolean;\n onError?: (error: Error) => void;\n}\n\nexport function useQuery<T>(options: UseQueryOptions<T>): QueryState<T> {\n const { queryKey, queryFn, enabled = true, onError } = options;\n\n const state = useSyncExternalStore(\n subscribe,\n () => getSnapshot<T>(queryKey),\n () => getSnapshot<T>(queryKey),\n );\n\n useEffect(() => {\n if (!enabled) return;\n\n const entry = cache.get(queryKey) as CacheEntry<T> | undefined;\n if (entry && entry.state.status !== 'idle') {\n return;\n }\n\n const promise = queryFn();\n\n cache.set(queryKey, {\n state: { status: 'loading' },\n promise,\n });\n notifySubscribers();\n\n promise\n .then((data) => {\n cache.set(queryKey, { state: { status: 'success', data } });\n notifySubscribers();\n })\n .catch((err) => {\n const error = err instanceof Error ? err : new Error(String(err));\n cache.set(queryKey, { state: { status: 'error', error } });\n notifySubscribers();\n onError?.(error);\n });\n }, [queryKey, enabled, queryFn, onError]);\n\n return state;\n}\n","'use client';\n\nimport { useCallback } from 'react';\nimport { consumeSession } from '../api/consume';\nimport type { SessionCredentials } from '../types';\nimport { useQuery } from './useQuery';\n\nexport interface UseCredentialsOptions {\n avatarId: string;\n sessionId?: string;\n sessionKey?: string;\n credentials?: SessionCredentials;\n connectUrl?: string;\n connect?: (avatarId: string) => Promise<SessionCredentials>;\n baseUrl?: string;\n onError?: (error: Error) => void;\n}\n\nexport type CredentialsState =\n | { status: 'loading'; credentials: null; error: null }\n | { status: 'ready'; credentials: SessionCredentials; error: null }\n | { status: 'error'; credentials: null; error: Error };\n\nasync function fetchCredentials(\n options: UseCredentialsOptions,\n): Promise<SessionCredentials> {\n const { avatarId, sessionId, sessionKey, connectUrl, connect, baseUrl } =\n options;\n\n if (sessionId && sessionKey) {\n const { url, token, roomName } = await consumeSession({\n sessionId,\n sessionKey,\n baseUrl,\n });\n return { sessionId, serverUrl: url, token, roomName };\n }\n\n if (connect) {\n return connect(avatarId);\n }\n\n if (connectUrl) {\n const response = await fetch(connectUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ avatarId }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to connect: ${response.status} ${errorText}`);\n }\n\n return response.json();\n }\n\n throw new Error(\n 'AvatarCall requires one of: credentials, sessionId+sessionKey, connectUrl, or connect',\n );\n}\n\nexport function useCredentials(\n options: UseCredentialsOptions,\n): CredentialsState {\n const {\n credentials: directCredentials,\n avatarId,\n sessionId,\n sessionKey,\n connectUrl,\n connect,\n baseUrl,\n onError,\n } = options;\n\n const queryKey = `credentials:${avatarId}:${sessionId}:${sessionKey}:${connectUrl}:${baseUrl}`;\n\n const queryFn = useCallback(\n () =>\n fetchCredentials({\n avatarId,\n sessionId,\n sessionKey,\n connectUrl,\n connect,\n baseUrl,\n }),\n [avatarId, sessionId, sessionKey, connectUrl, connect, baseUrl],\n );\n\n const query = useQuery({\n queryKey,\n queryFn,\n enabled: !directCredentials,\n onError,\n });\n\n if (directCredentials) {\n return { status: 'ready', credentials: directCredentials, error: null };\n }\n\n if (query.status === 'success') {\n return { status: 'ready', credentials: query.data, error: null };\n }\n\n if (query.status === 'error') {\n return { status: 'error', credentials: null, error: query.error };\n }\n\n return { status: 'loading', credentials: null, error: null };\n}\n","'use client';\n\nimport { useEffect, useRef } from 'react';\n\nexport function useLatest<T>(value: T): React.RefObject<T> {\n const ref = useRef(value);\n\n useEffect(() => {\n ref.current = value;\n }, [value]);\n\n return ref;\n}\n","'use client';\n\n/**\n * AvatarSession Component\n *\n * Provides the session context for avatar interactions.\n * Manages the WebRTC connection and exposes a clean API for child components.\n *\n * @example\n * ```tsx\n * <AvatarSession credentials={credentials} onEnd={handleEnd}>\n * <AvatarVideo />\n * <ControlBar />\n * </AvatarSession>\n * ```\n */\n\nimport {\n LiveKitRoom,\n RoomAudioRenderer,\n useConnectionState,\n useRoomContext,\n} from '@livekit/components-react';\nimport type { RoomOptions } from 'livekit-client';\nimport { ConnectionState } from 'livekit-client';\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport type {\n AvatarSessionContextValue,\n AvatarSessionProps,\n SessionState,\n} from '../types';\n\n/**\n * Check if a media device of the given kind is available\n * Returns within timeout to avoid blocking the connection\n */\nasync function hasMediaDevice(\n kind: 'audioinput' | 'videoinput',\n timeoutMs = 1000,\n): Promise<boolean> {\n try {\n const timeoutPromise = new Promise<boolean>((resolve) =>\n setTimeout(() => resolve(false), timeoutMs),\n );\n const checkPromise = navigator.mediaDevices\n .enumerateDevices()\n .then((devices) => devices.some((device) => device.kind === kind));\n\n return await Promise.race([checkPromise, timeoutPromise]);\n } catch {\n return false;\n }\n}\n\n/**\n * Hook to check device availability before connecting.\n * Completes quickly to avoid blocking the connection.\n */\nfunction useDeviceAvailability(\n requestAudio: boolean,\n requestVideo: boolean,\n): { audio: boolean; video: boolean } {\n const [state, setState] = useState({\n audio: requestAudio, // Optimistically assume devices exist\n video: requestVideo,\n });\n\n useEffect(() => {\n let cancelled = false;\n\n async function checkDevices() {\n const [hasAudio, hasVideo] = await Promise.all([\n requestAudio ? hasMediaDevice('audioinput') : Promise.resolve(false),\n requestVideo ? hasMediaDevice('videoinput') : Promise.resolve(false),\n ]);\n\n if (!cancelled) {\n setState({\n audio: requestAudio && hasAudio,\n video: requestVideo && hasVideo,\n });\n }\n }\n\n checkDevices();\n\n return () => {\n cancelled = true;\n };\n }, [requestAudio, requestVideo]);\n\n return state;\n}\n\nconst MEDIA_DEVICE_ERROR_NAMES = new Set([\n 'NotAllowedError',\n 'NotFoundError',\n 'NotReadableError',\n 'OverconstrainedError',\n]);\n\nfunction isMediaDeviceError(error: Error): boolean {\n return MEDIA_DEVICE_ERROR_NAMES.has(error.name);\n}\n\nconst DEFAULT_ROOM_OPTIONS: RoomOptions = {\n adaptiveStream: false,\n dynacast: false,\n};\n\n/**\n * Maps WebRTC connection state to session state\n */\nfunction mapConnectionState(connectionState: ConnectionState): SessionState {\n switch (connectionState) {\n case ConnectionState.Connecting:\n return 'connecting';\n case ConnectionState.Connected:\n return 'active';\n case ConnectionState.Reconnecting:\n return 'connecting';\n case ConnectionState.Disconnected:\n return 'ended';\n default:\n return 'ended';\n }\n}\n\nconst AvatarSessionContext = createContext<AvatarSessionContextValue | null>(\n null,\n);\n\n/**\n * AvatarSession component - the main entry point for avatar sessions\n *\n * Establishes a WebRTC connection and provides session state to children.\n * This is a headless component that renders minimal DOM.\n */\nexport function AvatarSession({\n credentials,\n children,\n audio: requestAudio = true,\n video: requestVideo = true,\n onEnd,\n onError,\n __unstable_roomOptions,\n}: AvatarSessionProps) {\n const errorRef = useRef<Error | null>(null);\n\n const deviceAvailability = useDeviceAvailability(requestAudio, requestVideo);\n\n const handleError = (error: Error) => {\n onError?.(error);\n if (!isMediaDeviceError(error)) {\n errorRef.current = error;\n }\n };\n\n const roomOptions = {\n ...DEFAULT_ROOM_OPTIONS,\n ...__unstable_roomOptions,\n };\n\n return (\n <LiveKitRoom\n serverUrl={credentials.serverUrl}\n token={credentials.token}\n connect={true}\n audio={deviceAvailability.audio}\n video={deviceAvailability.video}\n onDisconnected={() => onEnd?.()}\n onError={handleError}\n options={roomOptions}\n connectOptions={{\n autoSubscribe: true,\n }}\n >\n <AvatarSessionContextInner\n sessionId={credentials.sessionId}\n onEnd={onEnd}\n errorRef={errorRef}\n >\n {children}\n </AvatarSessionContextInner>\n <RoomAudioRenderer />\n </LiveKitRoom>\n );\n}\n\n/**\n * Inner context provider that has access to the room context\n */\nfunction AvatarSessionContextInner({\n sessionId,\n onEnd,\n errorRef,\n children,\n}: {\n sessionId: string;\n onEnd?: () => void;\n errorRef: React.RefObject<Error | null>;\n children: ReactNode;\n}) {\n const room = useRoomContext();\n const connectionState = useConnectionState();\n const onEndRef = useRef(onEnd);\n onEndRef.current = onEnd;\n\n const end = useCallback(async () => {\n try {\n // Send END_CALL message to the avatar\n const encoder = new TextEncoder();\n const data = encoder.encode(JSON.stringify({ type: 'END_CALL' }));\n await room.localParticipant.publishData(data, { reliable: true });\n } catch {\n // Ignore errors when sending end message\n }\n\n await room.disconnect();\n onEndRef.current?.();\n }, [room]);\n\n const contextValue: AvatarSessionContextValue = {\n state: mapConnectionState(connectionState),\n sessionId,\n error: errorRef.current,\n end,\n };\n\n return (\n <AvatarSessionContext.Provider value={contextValue}>\n {children}\n </AvatarSessionContext.Provider>\n );\n}\n\n/**\n * Hook to access the avatar session context\n * Must be used within an AvatarSession component\n */\nexport function useAvatarSessionContext(): AvatarSessionContextValue {\n const context = useContext(AvatarSessionContext);\n if (!context) {\n throw new Error(\n 'useAvatarSessionContext must be used within an AvatarSession',\n );\n }\n return context;\n}\n\n/**\n * Hook to optionally access the avatar session context\n * Returns null if not within an AvatarSession\n */\nexport function useMaybeAvatarSessionContext(): AvatarSessionContextValue | null {\n return useContext(AvatarSessionContext);\n}\n","'use client';\n\n/**\n * useAvatar Hook\n *\n * Provides access to the remote avatar participant's video track.\n * Audio is handled automatically by the session.\n *\n * Must be used within an AvatarSession or AvatarCall component.\n *\n * @example\n * ```tsx\n * function AvatarDisplay() {\n * const { videoTrackRef, hasVideo } = useAvatar();\n *\n * if (!hasVideo) {\n * return <Placeholder />;\n * }\n *\n * return <VideoTrack trackRef={videoTrackRef} />;\n * }\n * ```\n */\n\nimport {\n isTrackReference,\n useRemoteParticipants,\n useTracks,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { UseAvatarReturn } from '../types';\n\n/**\n * Hook to access the remote avatar participant's video track\n *\n * @returns Avatar participant info and video track reference\n */\nexport function useAvatar(): UseAvatarReturn {\n const remoteParticipants = useRemoteParticipants();\n const avatarParticipant = remoteParticipants[0] ?? null;\n\n // Only subscribe to video - audio is handled automatically by the session\n const videoTracks = useTracks(\n [{ source: Track.Source.Camera, withPlaceholder: true }],\n {\n onlySubscribed: true,\n updateOnlyOn: [],\n },\n ).filter((ref) => !ref.participant.isLocal);\n\n const videoTrackRef = videoTracks[0] ?? null;\n const hasVideo = videoTrackRef !== null && isTrackReference(videoTrackRef);\n\n return {\n participant: avatarParticipant,\n videoTrackRef,\n hasVideo,\n };\n}\n","'use client';\n\n/**\n * useAvatarSession Hook\n *\n * Provides access to the current avatar session state.\n * Returns a discriminated union based on session state for type-safe UI rendering.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const session = useAvatarSession();\n *\n * if (session.state === 'connecting') {\n * return <Loading />;\n * }\n *\n * if (session.state === 'error') {\n * return <Error message={session.error.message} />;\n * }\n *\n * return <ActiveSession onEnd={session.end} />;\n * }\n * ```\n */\n\nimport { useAvatarSessionContext } from '../components/AvatarSession';\nimport type { AvatarSessionContextValue } from '../types';\n\n/**\n * Discriminated union types for type-safe session state handling\n */\nexport type UseAvatarSessionReturn =\n | { state: 'idle'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'connecting'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'active'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'ending'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'ended'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'error'; sessionId: string; error: Error; end: () => Promise<void> };\n\n/**\n * Hook to access the current avatar session state\n *\n * @returns Session state as a discriminated union\n */\nexport function useAvatarSession(): UseAvatarSessionReturn {\n const context = useAvatarSessionContext();\n return context as UseAvatarSessionReturn;\n}\n\nexport type { AvatarSessionContextValue };\n","'use client';\n\n/**\n * useAvatarStatus Hook\n *\n * Returns a single discriminated union representing the full avatar lifecycle\n * inside an AvatarSession. Combines session connection state and video\n * track availability into one status value.\n *\n * Must be used within <AvatarCall> or <AvatarSession>.\n *\n * @example\n * ```tsx\n * function MyAvatar() {\n * const avatar = useAvatarStatus();\n *\n * switch (avatar.status) {\n * case 'connecting':\n * return <Spinner />;\n * case 'waiting':\n * return <p>Waiting for video...</p>;\n * case 'ready':\n * return <VideoTrack trackRef={avatar.videoTrackRef} />;\n * case 'error':\n * return <p>{avatar.error.message}</p>;\n * case 'ended':\n * return <p>Call ended</p>;\n * }\n * }\n * ```\n */\n\nimport type { TrackReferenceOrPlaceholder } from '@livekit/components-react';\nimport { useAvatar } from './useAvatar';\nimport { useAvatarSession } from './useAvatarSession';\n\nexport type AvatarStatus =\n | { status: 'connecting' }\n | { status: 'waiting' }\n | { status: 'ready'; videoTrackRef: TrackReferenceOrPlaceholder }\n | { status: 'ending' }\n | { status: 'ended' }\n | { status: 'error'; error: Error };\n\nexport function useAvatarStatus(): AvatarStatus {\n const session = useAvatarSession();\n const { videoTrackRef, hasVideo } = useAvatar();\n\n switch (session.state) {\n case 'connecting':\n case 'idle':\n return { status: 'connecting' };\n\n case 'active':\n if (hasVideo && videoTrackRef) {\n return { status: 'ready', videoTrackRef };\n }\n return { status: 'waiting' };\n\n case 'ending':\n return { status: 'ending' };\n\n case 'ended':\n return { status: 'ended' };\n\n case 'error':\n return { status: 'error', error: session.error };\n }\n}\n","'use client';\n\nimport { isTrackReference, VideoTrack } from '@livekit/components-react';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { type AvatarStatus, useAvatarStatus } from '../hooks/useAvatarStatus';\n\n/** Subset of AvatarStatus relevant to the video display */\nexport type AvatarVideoStatus = Extract<\n AvatarStatus,\n { status: 'connecting' } | { status: 'waiting' } | { status: 'ready' }\n>;\n\nexport interface AvatarVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n children?: (status: AvatarVideoStatus) => ReactNode;\n}\n\nexport function AvatarVideo({ children, ...props }: AvatarVideoProps) {\n const avatar = useAvatarStatus();\n\n const videoStatus: AvatarVideoStatus =\n avatar.status === 'ready'\n ? avatar\n : avatar.status === 'connecting'\n ? { status: 'connecting' }\n : { status: 'waiting' };\n\n if (children) {\n return <>{children(videoStatus)}</>;\n }\n\n return (\n <div\n {...props}\n data-avatar-video=\"\"\n data-avatar-status={videoStatus.status}\n >\n {videoStatus.status === 'ready' &&\n isTrackReference(videoStatus.videoTrackRef) && (\n <VideoTrack trackRef={videoStatus.videoTrackRef} />\n )}\n </div>\n );\n}\n","'use client';\n\nimport {\n useLocalParticipant,\n useMediaDevices,\n useTracks,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport { useCallback } from 'react';\nimport type { UseLocalMediaReturn } from '../types';\nimport { useLatest } from './useLatest';\n\n/**\n * Hook for local media controls (mic, camera, screen share).\n *\n * Must be used within an AvatarSession or AvatarCall component.\n * For use outside the session context, use AvatarSession directly\n * and manage your own loading states.\n */\nexport function useLocalMedia(): UseLocalMediaReturn {\n const { localParticipant } = useLocalParticipant();\n\n const audioDevices = useMediaDevices({ kind: 'audioinput' });\n const videoDevices = useMediaDevices({ kind: 'videoinput' });\n\n const hasMic = audioDevices?.length > 0;\n const hasCamera = videoDevices?.length > 0;\n\n const isMicEnabled = localParticipant?.isMicrophoneEnabled ?? false;\n const isCameraEnabled = localParticipant?.isCameraEnabled ?? false;\n const isScreenShareEnabled = localParticipant?.isScreenShareEnabled ?? false;\n\n const isMicEnabledRef = useLatest(isMicEnabled);\n const isCameraEnabledRef = useLatest(isCameraEnabled);\n const isScreenShareEnabledRef = useLatest(isScreenShareEnabled);\n\n const hasMicRef = useLatest(hasMic);\n const hasCameraRef = useLatest(hasCamera);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleMic = useCallback(() => {\n if (hasMicRef.current || isMicEnabledRef.current) {\n localParticipant?.setMicrophoneEnabled(!isMicEnabledRef.current);\n }\n }, [localParticipant]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleCamera = useCallback(() => {\n if (hasCameraRef.current || isCameraEnabledRef.current) {\n localParticipant?.setCameraEnabled(!isCameraEnabledRef.current);\n }\n }, [localParticipant]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleScreenShare = useCallback(() => {\n localParticipant?.setScreenShareEnabled(!isScreenShareEnabledRef.current);\n }, [localParticipant]);\n\n const tracks = useTracks(\n [{ source: Track.Source.Camera, withPlaceholder: true }],\n {\n onlySubscribed: false,\n updateOnlyOn: [],\n },\n );\n\n const localIdentity = localParticipant?.identity;\n\n const localVideoTrackRef =\n tracks.find(\n (trackRef) =>\n trackRef.participant.identity === localIdentity &&\n trackRef.source === Track.Source.Camera,\n ) ?? null;\n\n return {\n hasMic,\n hasCamera,\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n localVideoTrackRef,\n };\n}\n","'use client';\n\nimport { TrackToggle } from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { useAvatarSession } from '../hooks/useAvatarSession';\nimport { useLocalMedia } from '../hooks/useLocalMedia';\n\nexport interface ControlBarState {\n isMicEnabled: boolean;\n isCameraEnabled: boolean;\n isScreenShareEnabled: boolean;\n toggleMic: () => void;\n toggleCamera: () => void;\n toggleScreenShare: () => void;\n endCall: () => Promise<void>;\n isActive: boolean;\n}\n\nexport interface ControlBarProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n showMicrophone?: boolean;\n showCamera?: boolean;\n showScreenShare?: boolean;\n showEndCall?: boolean;\n children?: (state: ControlBarState) => ReactNode;\n}\n\nexport function ControlBar({\n children,\n showMicrophone = true,\n showCamera = true,\n showScreenShare = false,\n showEndCall = true,\n ...props\n}: ControlBarProps) {\n const session = useAvatarSession();\n const {\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n } = useLocalMedia();\n\n const isActive = session.state === 'active';\n\n const state: ControlBarState = {\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n endCall: session.end,\n isActive,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n if (!isActive) {\n return null;\n }\n\n return (\n <div {...props} data-avatar-control-bar=\"\" data-avatar-active={isActive}>\n {showMicrophone && (\n <button\n type=\"button\"\n onClick={toggleMic}\n data-avatar-control=\"microphone\"\n data-avatar-enabled={isMicEnabled}\n aria-label={isMicEnabled ? 'Mute microphone' : 'Unmute microphone'}\n >\n {microphoneIcon}\n </button>\n )}\n {showCamera && (\n <button\n type=\"button\"\n onClick={toggleCamera}\n data-avatar-control=\"camera\"\n data-avatar-enabled={isCameraEnabled}\n aria-label={isCameraEnabled ? 'Turn off camera' : 'Turn on camera'}\n >\n {cameraIcon}\n </button>\n )}\n {showScreenShare && (\n <TrackToggle\n source={Track.Source.ScreenShare}\n showIcon={false}\n data-avatar-control=\"screen-share\"\n data-avatar-enabled={isScreenShareEnabled}\n aria-label=\"Toggle screen share\"\n >\n {screenShareIcon}\n </TrackToggle>\n )}\n {showEndCall && (\n <button\n type=\"button\"\n onClick={session.end}\n data-avatar-control=\"end-call\"\n data-avatar-enabled={true}\n aria-label=\"End call\"\n >\n {phoneIcon}\n </button>\n )}\n </div>\n );\n}\n\n// Lucide icons (https://lucide.dev) - MIT License\nconst microphoneIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\" />\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" />\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\" />\n </svg>\n);\n\nconst cameraIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5\" />\n <rect x=\"2\" y=\"6\" width=\"14\" height=\"12\" rx=\"2\" />\n </svg>\n);\n\nconst screenShareIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\" />\n <line x1=\"8\" x2=\"16\" y1=\"21\" y2=\"21\" />\n <line x1=\"12\" x2=\"12\" y1=\"17\" y2=\"21\" />\n </svg>\n);\n\nconst phoneIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"8 14 24 12\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=\"M12.8429 22.5693L11.4018 21.0986C11.2675 20.9626 11.1625 20.7995 11.0935 20.6197C11.0245 20.4399 10.9931 20.2474 11.0013 20.0545C11.0094 19.8616 11.0569 19.6726 11.1408 19.4995C11.2247 19.3265 11.343 19.1732 11.4883 19.0495C13.127 17.7049 15.0519 16.7714 17.1083 16.3239C19.0064 15.892 20.9744 15.892 22.8725 16.3239C24.9374 16.7743 26.8693 17.7147 28.5117 19.0691C28.6565 19.1924 28.7746 19.3451 28.8585 19.5176C28.9423 19.69 28.99 19.8784 28.9986 20.0707C29.0072 20.263 28.9764 20.455 28.9083 20.6345C28.8402 20.814 28.7362 20.9771 28.603 21.1133L27.1619 22.584C26.9311 22.8242 26.6226 22.9706 26.2938 22.9959C25.9651 23.0211 25.6385 22.9235 25.3751 22.7212C24.8531 22.3127 24.2875 21.9657 23.689 21.6869C23.4525 21.5774 23.2517 21.4009 23.1103 21.1785C22.969 20.9561 22.8931 20.697 22.8917 20.4319V19.1867C21.0053 18.6573 19.0139 18.6573 17.1275 19.1867V20.4319C17.1261 20.697 17.0502 20.9561 16.9089 21.1785C16.7676 21.4009 16.5667 21.5774 16.3302 21.6869C15.7317 21.9657 15.1661 22.3127 14.6442 22.7212C14.3779 22.9258 14.0473 23.0233 13.7152 22.9953C13.383 22.9673 13.0726 22.8156 12.8429 22.5693Z\" />\n </svg>\n);\n","'use client';\n\nimport { isTrackReference, VideoTrack } from '@livekit/components-react';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { useLocalMedia } from '../hooks/useLocalMedia';\nimport type { UseLocalMediaReturn } from '../types';\n\nexport interface UserVideoState {\n hasVideo: boolean;\n isCameraEnabled: boolean;\n trackRef: UseLocalMediaReturn['localVideoTrackRef'];\n}\n\nexport interface UserVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n mirror?: boolean;\n children?: (state: UserVideoState) => ReactNode;\n}\n\nexport function UserVideo({\n children,\n mirror = true,\n ...props\n}: UserVideoProps) {\n const { localVideoTrackRef, isCameraEnabled } = useLocalMedia();\n\n const hasVideo =\n localVideoTrackRef !== null && isTrackReference(localVideoTrackRef);\n\n const state: UserVideoState = {\n hasVideo,\n isCameraEnabled,\n trackRef: localVideoTrackRef,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n return (\n <div\n {...props}\n data-avatar-user-video=\"\"\n data-avatar-has-video={hasVideo}\n data-avatar-camera-enabled={isCameraEnabled}\n data-avatar-mirror={mirror}\n >\n {hasVideo &&\n localVideoTrackRef &&\n isTrackReference(localVideoTrackRef) && (\n <VideoTrack trackRef={localVideoTrackRef} />\n )}\n </div>\n );\n}\n","'use client';\n\n/**\n * AvatarCall Component\n *\n * High-level component that handles the complete session lifecycle.\n * Manages credential fetching, connection, and video display internally\n * with a seamless loading experience.\n *\n * During credential loading, shows a loading state with the avatar image.\n * Once connected, renders children inside the session context.\n *\n * For more control over the loading UI, use AvatarSession directly.\n *\n * @example\n * ```tsx\n * // Simple usage - handles everything automatically\n * <AvatarCall avatarId=\"music-superstar\" connectUrl=\"/api/avatar/connect\" />\n *\n * // Custom children - rendered once connected\n * <AvatarCall avatarId=\"music-superstar\" connectUrl=\"/api/avatar/connect\">\n * <AvatarVideo />\n * <ControlBar />\n * </AvatarCall>\n * ```\n */\n\nimport { useCredentials } from '../hooks/useCredentials';\nimport { useLatest } from '../hooks/useLatest';\nimport type { AvatarCallProps } from '../types';\nimport { AvatarSession } from './AvatarSession';\nimport { AvatarVideo } from './AvatarVideo';\nimport { ControlBar } from './ControlBar';\nimport { UserVideo } from './UserVideo';\n\nexport function AvatarCall({\n avatarId,\n sessionId,\n sessionKey,\n credentials: directCredentials,\n connectUrl,\n connect,\n baseUrl,\n audio,\n video,\n avatarImageUrl,\n onEnd,\n onError,\n children,\n __unstable_roomOptions,\n ...props\n}: AvatarCallProps) {\n const onErrorRef = useLatest(onError);\n\n const credentialsState = useCredentials({\n avatarId,\n sessionId,\n sessionKey,\n credentials: directCredentials,\n connectUrl,\n connect,\n baseUrl,\n onError: (err) => onErrorRef.current?.(err),\n });\n\n const handleSessionError = (err: Error) => {\n onErrorRef.current?.(err);\n };\n\n const backgroundStyle = avatarImageUrl\n ? ({ '--avatar-image': `url(${avatarImageUrl})` } as React.CSSProperties)\n : undefined;\n\n const defaultChildren = (\n <>\n <AvatarVideo />\n <UserVideo />\n <ControlBar />\n </>\n );\n\n // During credential loading/error, show a simple loading state\n // Children are NOT rendered here because they may use hooks that require LiveKitRoom context\n if (credentialsState.status !== 'ready') {\n const status =\n credentialsState.status === 'error' ? 'error' : 'connecting';\n\n return (\n <div\n {...props}\n data-avatar-call=\"\"\n data-avatar-id={avatarId}\n style={{ ...props.style, ...backgroundStyle }}\n >\n <div data-avatar-video=\"\" data-avatar-status={status} />\n </div>\n );\n }\n\n // Once credentials are ready, render children inside the session context\n // This ensures all hooks have access to the LiveKitRoom context\n return (\n <div\n {...props}\n data-avatar-call=\"\"\n data-avatar-id={avatarId}\n style={{ ...props.style, ...backgroundStyle }}\n >\n <AvatarSession\n credentials={credentialsState.credentials}\n audio={audio}\n video={video}\n onEnd={onEnd}\n onError={handleSessionError}\n __unstable_roomOptions={__unstable_roomOptions}\n >\n {children ?? defaultChildren}\n </AvatarSession>\n </div>\n );\n}\n","'use client';\n\nimport {\n isTrackReference,\n type TrackReferenceOrPlaceholder,\n useLocalParticipant,\n useTracks,\n VideoTrack,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\n\nexport interface ScreenShareVideoState {\n isSharing: boolean;\n trackRef: TrackReferenceOrPlaceholder | null;\n}\n\nexport interface ScreenShareVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n children?: (state: ScreenShareVideoState) => ReactNode;\n}\n\n/**\n * Component for displaying local screen share video.\n *\n * Must be used within an AvatarSession or AvatarCall component.\n */\nexport function ScreenShareVideo({\n children,\n ...props\n}: ScreenShareVideoProps) {\n const { localParticipant } = useLocalParticipant();\n\n const tracks = useTracks(\n [{ source: Track.Source.ScreenShare, withPlaceholder: false }],\n { onlySubscribed: false },\n );\n\n const localIdentity = localParticipant?.identity;\n\n const screenShareTrackRef =\n tracks.find(\n (trackRef) =>\n trackRef.participant.identity === localIdentity &&\n trackRef.source === Track.Source.ScreenShare,\n ) ?? null;\n\n const isSharing =\n screenShareTrackRef !== null && isTrackReference(screenShareTrackRef);\n\n const state: ScreenShareVideoState = {\n isSharing,\n trackRef: screenShareTrackRef,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n if (!isSharing) {\n return null;\n }\n\n return (\n <div {...props} data-avatar-screen-share=\"\" data-avatar-sharing={isSharing}>\n {screenShareTrackRef && isTrackReference(screenShareTrackRef) && (\n <VideoTrack trackRef={screenShareTrackRef} />\n )}\n </div>\n );\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -67,6 +67,10 @@ interface AvatarCallProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'o
67
67
  connect?: (avatarId: string) => Promise<SessionCredentials>;
68
68
  /** Base URL for the Runway API (defaults to https://api.dev.runwayml.com) */
69
69
  baseUrl?: string;
70
+ /** Enable audio on connect (default: true) */
71
+ audio?: boolean;
72
+ /** Enable video on connect (default: true) — camera permission is requested but denying it won't block the call */
73
+ video?: boolean;
70
74
  /** Avatar image URL for placeholder/loading states */
71
75
  avatarImageUrl?: string;
72
76
  /** Callback when session ends */
@@ -116,7 +120,7 @@ interface UseLocalMediaReturn {
116
120
  localVideoTrackRef: _livekit_components_react.TrackReferenceOrPlaceholder | null;
117
121
  }
118
122
 
119
- declare function AvatarCall({ avatarId, sessionId, sessionKey, credentials: directCredentials, connectUrl, connect, baseUrl, avatarImageUrl, onEnd, onError, children, __unstable_roomOptions, ...props }: AvatarCallProps): react_jsx_runtime.JSX.Element;
123
+ declare function AvatarCall({ avatarId, sessionId, sessionKey, credentials: directCredentials, connectUrl, connect, baseUrl, audio, video, avatarImageUrl, onEnd, onError, children, __unstable_roomOptions, ...props }: AvatarCallProps): react_jsx_runtime.JSX.Element;
120
124
 
121
125
  /**
122
126
  * AvatarSession component - the main entry point for avatar sessions
package/dist/index.d.ts CHANGED
@@ -67,6 +67,10 @@ interface AvatarCallProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'o
67
67
  connect?: (avatarId: string) => Promise<SessionCredentials>;
68
68
  /** Base URL for the Runway API (defaults to https://api.dev.runwayml.com) */
69
69
  baseUrl?: string;
70
+ /** Enable audio on connect (default: true) */
71
+ audio?: boolean;
72
+ /** Enable video on connect (default: true) — camera permission is requested but denying it won't block the call */
73
+ video?: boolean;
70
74
  /** Avatar image URL for placeholder/loading states */
71
75
  avatarImageUrl?: string;
72
76
  /** Callback when session ends */
@@ -116,7 +120,7 @@ interface UseLocalMediaReturn {
116
120
  localVideoTrackRef: _livekit_components_react.TrackReferenceOrPlaceholder | null;
117
121
  }
118
122
 
119
- declare function AvatarCall({ avatarId, sessionId, sessionKey, credentials: directCredentials, connectUrl, connect, baseUrl, avatarImageUrl, onEnd, onError, children, __unstable_roomOptions, ...props }: AvatarCallProps): react_jsx_runtime.JSX.Element;
123
+ declare function AvatarCall({ avatarId, sessionId, sessionKey, credentials: directCredentials, connectUrl, connect, baseUrl, audio, video, avatarImageUrl, onEnd, onError, children, __unstable_roomOptions, ...props }: AvatarCallProps): react_jsx_runtime.JSX.Element;
120
124
 
121
125
  /**
122
126
  * AvatarSession component - the main entry point for avatar sessions
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { LiveKitRoom, RoomAudioRenderer, useRoomContext, useConnectionState, useRemoteParticipants, useTracks, isTrackReference, VideoTrack, useLocalParticipant, useMediaDevices, TrackToggle } from '@livekit/components-react';
2
2
  export { RoomAudioRenderer as AudioRenderer, VideoTrack } from '@livekit/components-react';
3
- import { createContext, useRef, useCallback, useState, useEffect, useContext } from 'react';
3
+ import { createContext, useRef, useCallback, useState, useEffect, useContext, useSyncExternalStore } from 'react';
4
4
  import { Track, ConnectionState } from 'livekit-client';
5
5
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
6
6
 
@@ -26,12 +26,54 @@ async function consumeSession(options) {
26
26
  }
27
27
  return response.json();
28
28
  }
29
- function useLatest(value) {
30
- const ref = useRef(value);
29
+ var IDLE_STATE = { status: "idle" };
30
+ var cache = /* @__PURE__ */ new Map();
31
+ var subscribers = /* @__PURE__ */ new Set();
32
+ function notifySubscribers() {
33
+ for (const callback of subscribers) {
34
+ callback();
35
+ }
36
+ }
37
+ function subscribe(callback) {
38
+ subscribers.add(callback);
39
+ return () => {
40
+ subscribers.delete(callback);
41
+ };
42
+ }
43
+ function getSnapshot(key) {
44
+ const entry = cache.get(key);
45
+ return entry?.state ?? IDLE_STATE;
46
+ }
47
+ function useQuery(options) {
48
+ const { queryKey, queryFn, enabled = true, onError } = options;
49
+ const state = useSyncExternalStore(
50
+ subscribe,
51
+ () => getSnapshot(queryKey),
52
+ () => getSnapshot(queryKey)
53
+ );
31
54
  useEffect(() => {
32
- ref.current = value;
33
- }, [value]);
34
- return ref;
55
+ if (!enabled) return;
56
+ const entry = cache.get(queryKey);
57
+ if (entry && entry.state.status !== "idle") {
58
+ return;
59
+ }
60
+ const promise = queryFn();
61
+ cache.set(queryKey, {
62
+ state: { status: "loading" },
63
+ promise
64
+ });
65
+ notifySubscribers();
66
+ promise.then((data) => {
67
+ cache.set(queryKey, { state: { status: "success", data } });
68
+ notifySubscribers();
69
+ }).catch((err) => {
70
+ const error = err instanceof Error ? err : new Error(String(err));
71
+ cache.set(queryKey, { state: { status: "error", error } });
72
+ notifySubscribers();
73
+ onError?.(error);
74
+ });
75
+ }, [queryKey, enabled, queryFn, onError]);
76
+ return state;
35
77
  }
36
78
 
37
79
  // src/hooks/useCredentials.ts
@@ -75,58 +117,41 @@ function useCredentials(options) {
75
117
  baseUrl,
76
118
  onError
77
119
  } = options;
78
- const onErrorRef = useLatest(onError);
79
- const connectRef = useLatest(connect);
80
- const fetchedKeyRef = useRef(null);
81
- const [state, setState] = useState(() => {
82
- if (directCredentials) {
83
- return { status: "ready", credentials: directCredentials, error: null };
84
- }
85
- return { status: "loading", credentials: null, error: null };
120
+ const queryKey = `credentials:${avatarId}:${sessionId}:${sessionKey}:${connectUrl}:${baseUrl}`;
121
+ const queryFn = useCallback(
122
+ () => fetchCredentials({
123
+ avatarId,
124
+ sessionId,
125
+ sessionKey,
126
+ connectUrl,
127
+ connect,
128
+ baseUrl
129
+ }),
130
+ [avatarId, sessionId, sessionKey, connectUrl, connect, baseUrl]
131
+ );
132
+ const query = useQuery({
133
+ queryKey,
134
+ queryFn,
135
+ enabled: !directCredentials,
136
+ onError
86
137
  });
138
+ if (directCredentials) {
139
+ return { status: "ready", credentials: directCredentials, error: null };
140
+ }
141
+ if (query.status === "success") {
142
+ return { status: "ready", credentials: query.data, error: null };
143
+ }
144
+ if (query.status === "error") {
145
+ return { status: "error", credentials: null, error: query.error };
146
+ }
147
+ return { status: "loading", credentials: null, error: null };
148
+ }
149
+ function useLatest(value) {
150
+ const ref = useRef(value);
87
151
  useEffect(() => {
88
- if (directCredentials) {
89
- setState({
90
- status: "ready",
91
- credentials: directCredentials,
92
- error: null
93
- });
94
- return;
95
- }
96
- const credentialKey = `${avatarId}:${sessionId}:${sessionKey}:${connectUrl}:${baseUrl}`;
97
- if (fetchedKeyRef.current === credentialKey) return;
98
- fetchedKeyRef.current = credentialKey;
99
- let cancelled = false;
100
- setState({ status: "loading", credentials: null, error: null });
101
- async function load() {
102
- try {
103
- const fetchOptions = {
104
- avatarId,
105
- sessionId,
106
- sessionKey,
107
- connectUrl,
108
- connect: connectRef.current ?? void 0,
109
- baseUrl
110
- };
111
- const credentials = await fetchCredentials(fetchOptions);
112
- if (!cancelled) {
113
- setState({ status: "ready", credentials, error: null });
114
- }
115
- } catch (err) {
116
- if (!cancelled) {
117
- const error = err instanceof Error ? err : new Error(String(err));
118
- setState({ status: "error", credentials: null, error });
119
- onErrorRef.current?.(error);
120
- }
121
- }
122
- }
123
- load();
124
- return () => {
125
- cancelled = true;
126
- fetchedKeyRef.current = null;
127
- };
128
- }, [directCredentials, avatarId, sessionId, sessionKey, connectUrl, baseUrl]);
129
- return state;
152
+ ref.current = value;
153
+ }, [value]);
154
+ return ref;
130
155
  }
131
156
  async function hasMediaDevice(kind, timeoutMs = 1e3) {
132
157
  try {
@@ -166,6 +191,15 @@ function useDeviceAvailability(requestAudio, requestVideo) {
166
191
  }, [requestAudio, requestVideo]);
167
192
  return state;
168
193
  }
194
+ var MEDIA_DEVICE_ERROR_NAMES = /* @__PURE__ */ new Set([
195
+ "NotAllowedError",
196
+ "NotFoundError",
197
+ "NotReadableError",
198
+ "OverconstrainedError"
199
+ ]);
200
+ function isMediaDeviceError(error) {
201
+ return MEDIA_DEVICE_ERROR_NAMES.has(error.name);
202
+ }
169
203
  var DEFAULT_ROOM_OPTIONS = {
170
204
  adaptiveStream: false,
171
205
  dynacast: false
@@ -199,8 +233,10 @@ function AvatarSession({
199
233
  const errorRef = useRef(null);
200
234
  const deviceAvailability = useDeviceAvailability(requestAudio, requestVideo);
201
235
  const handleError = (error) => {
202
- errorRef.current = error;
203
236
  onError?.(error);
237
+ if (!isMediaDeviceError(error)) {
238
+ errorRef.current = error;
239
+ }
204
240
  };
205
241
  const roomOptions = {
206
242
  ...DEFAULT_ROOM_OPTIONS,
@@ -567,6 +603,8 @@ function AvatarCall({
567
603
  connectUrl,
568
604
  connect,
569
605
  baseUrl,
606
+ audio,
607
+ video,
570
608
  avatarImageUrl,
571
609
  onEnd,
572
610
  onError,
@@ -618,6 +656,8 @@ function AvatarCall({
618
656
  AvatarSession,
619
657
  {
620
658
  credentials: credentialsState.credentials,
659
+ audio,
660
+ video,
621
661
  onEnd,
622
662
  onError: handleSessionError,
623
663
  __unstable_roomOptions,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/config.ts","../src/api/consume.ts","../src/hooks/useLatest.ts","../src/hooks/useCredentials.ts","../src/components/AvatarSession.tsx","../src/hooks/useAvatar.ts","../src/hooks/useAvatarSession.ts","../src/hooks/useAvatarStatus.ts","../src/components/AvatarVideo.tsx","../src/hooks/useLocalMedia.ts","../src/components/ControlBar.tsx","../src/components/UserVideo.tsx","../src/components/AvatarCall.tsx","../src/components/ScreenShareVideo.tsx"],"names":["useRef","useEffect","useState","RoomAudioRenderer","jsx","isTrackReference","useCallback","useTracks","Track","Fragment","jsxs","VideoTrack","useLocalParticipant"],"mappings":"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","file":"index.js","sourcesContent":["export const DEFAULT_BASE_URL = 'https://api.dev.runwayml.com';\n","import type { ConsumeSessionOptions, ConsumeSessionResponse } from '../types';\nimport { DEFAULT_BASE_URL } from './config';\n\nexport async function consumeSession(\n options: ConsumeSessionOptions,\n): Promise<ConsumeSessionResponse> {\n const { sessionId, sessionKey, baseUrl = DEFAULT_BASE_URL } = options;\n\n const url = `${baseUrl}/v1/realtime_sessions/${sessionId}/consume`;\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${sessionKey}`,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to consume session: ${response.status} ${errorText}`,\n );\n }\n\n return response.json();\n}\n","'use client';\n\nimport { useEffect, useRef } from 'react';\n\nexport function useLatest<T>(value: T): React.RefObject<T> {\n const ref = useRef(value);\n\n useEffect(() => {\n ref.current = value;\n }, [value]);\n\n return ref;\n}\n","'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport { consumeSession } from '../api/consume';\nimport type { SessionCredentials } from '../types';\nimport { useLatest } from './useLatest';\n\nexport interface UseCredentialsOptions {\n avatarId: string;\n sessionId?: string;\n sessionKey?: string;\n credentials?: SessionCredentials;\n connectUrl?: string;\n connect?: (avatarId: string) => Promise<SessionCredentials>;\n baseUrl?: string;\n onError?: (error: Error) => void;\n}\n\nexport type CredentialsState =\n | { status: 'loading'; credentials: null; error: null }\n | { status: 'ready'; credentials: SessionCredentials; error: null }\n | { status: 'error'; credentials: null; error: Error };\n\nasync function fetchCredentials(\n options: UseCredentialsOptions,\n): Promise<SessionCredentials> {\n const { avatarId, sessionId, sessionKey, connectUrl, connect, baseUrl } =\n options;\n\n if (sessionId && sessionKey) {\n const { url, token, roomName } = await consumeSession({\n sessionId,\n sessionKey,\n baseUrl,\n });\n return { sessionId, serverUrl: url, token, roomName };\n }\n\n if (connect) {\n return connect(avatarId);\n }\n\n if (connectUrl) {\n const response = await fetch(connectUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ avatarId }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to connect: ${response.status} ${errorText}`);\n }\n\n return response.json();\n }\n\n throw new Error(\n 'AvatarCall requires one of: credentials, sessionId+sessionKey, connectUrl, or connect',\n );\n}\n\nexport function useCredentials(\n options: UseCredentialsOptions,\n): CredentialsState {\n const {\n credentials: directCredentials,\n avatarId,\n sessionId,\n sessionKey,\n connectUrl,\n connect,\n baseUrl,\n onError,\n } = options;\n\n const onErrorRef = useLatest(onError);\n const connectRef = useLatest(connect);\n\n const fetchedKeyRef = useRef<string | null>(null);\n\n const [state, setState] = useState<CredentialsState>(() => {\n if (directCredentials) {\n return { status: 'ready', credentials: directCredentials, error: null };\n }\n return { status: 'loading', credentials: null, error: null };\n });\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs are stable - we read .current at call time\n useEffect(() => {\n if (directCredentials) {\n setState({\n status: 'ready',\n credentials: directCredentials,\n error: null,\n });\n return;\n }\n\n const credentialKey = `${avatarId}:${sessionId}:${sessionKey}:${connectUrl}:${baseUrl}`;\n\n if (fetchedKeyRef.current === credentialKey) return;\n fetchedKeyRef.current = credentialKey;\n\n let cancelled = false;\n setState({ status: 'loading', credentials: null, error: null });\n\n async function load() {\n try {\n const fetchOptions: UseCredentialsOptions = {\n avatarId,\n sessionId,\n sessionKey,\n connectUrl,\n connect: connectRef.current ?? undefined,\n baseUrl,\n };\n const credentials = await fetchCredentials(fetchOptions);\n if (!cancelled) {\n setState({ status: 'ready', credentials, error: null });\n }\n } catch (err) {\n if (!cancelled) {\n const error = err instanceof Error ? err : new Error(String(err));\n setState({ status: 'error', credentials: null, error });\n onErrorRef.current?.(error);\n }\n }\n }\n\n load();\n\n return () => {\n cancelled = true;\n fetchedKeyRef.current = null;\n };\n }, [directCredentials, avatarId, sessionId, sessionKey, connectUrl, baseUrl]);\n\n return state;\n}\n","'use client';\n\n/**\n * AvatarSession Component\n *\n * Provides the session context for avatar interactions.\n * Manages the WebRTC connection and exposes a clean API for child components.\n *\n * @example\n * ```tsx\n * <AvatarSession credentials={credentials} onEnd={handleEnd}>\n * <AvatarVideo />\n * <ControlBar />\n * </AvatarSession>\n * ```\n */\n\nimport {\n LiveKitRoom,\n RoomAudioRenderer,\n useConnectionState,\n useRoomContext,\n} from '@livekit/components-react';\nimport type { RoomOptions } from 'livekit-client';\nimport { ConnectionState } from 'livekit-client';\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport type {\n AvatarSessionContextValue,\n AvatarSessionProps,\n SessionState,\n} from '../types';\n\n/**\n * Check if a media device of the given kind is available\n * Returns within timeout to avoid blocking the connection\n */\nasync function hasMediaDevice(\n kind: 'audioinput' | 'videoinput',\n timeoutMs = 1000,\n): Promise<boolean> {\n try {\n const timeoutPromise = new Promise<boolean>((resolve) =>\n setTimeout(() => resolve(false), timeoutMs),\n );\n const checkPromise = navigator.mediaDevices\n .enumerateDevices()\n .then((devices) => devices.some((device) => device.kind === kind));\n\n return await Promise.race([checkPromise, timeoutPromise]);\n } catch {\n return false;\n }\n}\n\n/**\n * Hook to check device availability before connecting.\n * Completes quickly to avoid blocking the connection.\n */\nfunction useDeviceAvailability(\n requestAudio: boolean,\n requestVideo: boolean,\n): { audio: boolean; video: boolean } {\n const [state, setState] = useState({\n audio: requestAudio, // Optimistically assume devices exist\n video: requestVideo,\n });\n\n useEffect(() => {\n let cancelled = false;\n\n async function checkDevices() {\n const [hasAudio, hasVideo] = await Promise.all([\n requestAudio ? hasMediaDevice('audioinput') : Promise.resolve(false),\n requestVideo ? hasMediaDevice('videoinput') : Promise.resolve(false),\n ]);\n\n if (!cancelled) {\n setState({\n audio: requestAudio && hasAudio,\n video: requestVideo && hasVideo,\n });\n }\n }\n\n checkDevices();\n\n return () => {\n cancelled = true;\n };\n }, [requestAudio, requestVideo]);\n\n return state;\n}\n\nconst DEFAULT_ROOM_OPTIONS: RoomOptions = {\n adaptiveStream: false,\n dynacast: false,\n};\n\n/**\n * Maps WebRTC connection state to session state\n */\nfunction mapConnectionState(connectionState: ConnectionState): SessionState {\n switch (connectionState) {\n case ConnectionState.Connecting:\n return 'connecting';\n case ConnectionState.Connected:\n return 'active';\n case ConnectionState.Reconnecting:\n return 'connecting';\n case ConnectionState.Disconnected:\n return 'ended';\n default:\n return 'ended';\n }\n}\n\nconst AvatarSessionContext = createContext<AvatarSessionContextValue | null>(\n null,\n);\n\n/**\n * AvatarSession component - the main entry point for avatar sessions\n *\n * Establishes a WebRTC connection and provides session state to children.\n * This is a headless component that renders minimal DOM.\n */\nexport function AvatarSession({\n credentials,\n children,\n audio: requestAudio = true,\n video: requestVideo = true,\n onEnd,\n onError,\n __unstable_roomOptions,\n}: AvatarSessionProps) {\n const errorRef = useRef<Error | null>(null);\n\n const deviceAvailability = useDeviceAvailability(requestAudio, requestVideo);\n\n const handleError = (error: Error) => {\n errorRef.current = error;\n onError?.(error);\n };\n\n const roomOptions = {\n ...DEFAULT_ROOM_OPTIONS,\n ...__unstable_roomOptions,\n };\n\n return (\n <LiveKitRoom\n serverUrl={credentials.serverUrl}\n token={credentials.token}\n connect={true}\n audio={deviceAvailability.audio}\n video={deviceAvailability.video}\n onDisconnected={() => onEnd?.()}\n onError={handleError}\n options={roomOptions}\n connectOptions={{\n autoSubscribe: true,\n }}\n >\n <AvatarSessionContextInner\n sessionId={credentials.sessionId}\n onEnd={onEnd}\n errorRef={errorRef}\n >\n {children}\n </AvatarSessionContextInner>\n <RoomAudioRenderer />\n </LiveKitRoom>\n );\n}\n\n/**\n * Inner context provider that has access to the room context\n */\nfunction AvatarSessionContextInner({\n sessionId,\n onEnd,\n errorRef,\n children,\n}: {\n sessionId: string;\n onEnd?: () => void;\n errorRef: React.RefObject<Error | null>;\n children: ReactNode;\n}) {\n const room = useRoomContext();\n const connectionState = useConnectionState();\n const onEndRef = useRef(onEnd);\n onEndRef.current = onEnd;\n\n const end = useCallback(async () => {\n try {\n // Send END_CALL message to the avatar\n const encoder = new TextEncoder();\n const data = encoder.encode(JSON.stringify({ type: 'END_CALL' }));\n await room.localParticipant.publishData(data, { reliable: true });\n } catch {\n // Ignore errors when sending end message\n }\n\n await room.disconnect();\n onEndRef.current?.();\n }, [room]);\n\n const contextValue: AvatarSessionContextValue = {\n state: mapConnectionState(connectionState),\n sessionId,\n error: errorRef.current,\n end,\n };\n\n return (\n <AvatarSessionContext.Provider value={contextValue}>\n {children}\n </AvatarSessionContext.Provider>\n );\n}\n\n/**\n * Hook to access the avatar session context\n * Must be used within an AvatarSession component\n */\nexport function useAvatarSessionContext(): AvatarSessionContextValue {\n const context = useContext(AvatarSessionContext);\n if (!context) {\n throw new Error(\n 'useAvatarSessionContext must be used within an AvatarSession',\n );\n }\n return context;\n}\n\n/**\n * Hook to optionally access the avatar session context\n * Returns null if not within an AvatarSession\n */\nexport function useMaybeAvatarSessionContext(): AvatarSessionContextValue | null {\n return useContext(AvatarSessionContext);\n}\n","'use client';\n\n/**\n * useAvatar Hook\n *\n * Provides access to the remote avatar participant's video track.\n * Audio is handled automatically by the session.\n *\n * Must be used within an AvatarSession or AvatarCall component.\n *\n * @example\n * ```tsx\n * function AvatarDisplay() {\n * const { videoTrackRef, hasVideo } = useAvatar();\n *\n * if (!hasVideo) {\n * return <Placeholder />;\n * }\n *\n * return <VideoTrack trackRef={videoTrackRef} />;\n * }\n * ```\n */\n\nimport {\n isTrackReference,\n useRemoteParticipants,\n useTracks,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { UseAvatarReturn } from '../types';\n\n/**\n * Hook to access the remote avatar participant's video track\n *\n * @returns Avatar participant info and video track reference\n */\nexport function useAvatar(): UseAvatarReturn {\n const remoteParticipants = useRemoteParticipants();\n const avatarParticipant = remoteParticipants[0] ?? null;\n\n // Only subscribe to video - audio is handled automatically by the session\n const videoTracks = useTracks(\n [{ source: Track.Source.Camera, withPlaceholder: true }],\n {\n onlySubscribed: true,\n updateOnlyOn: [],\n },\n ).filter((ref) => !ref.participant.isLocal);\n\n const videoTrackRef = videoTracks[0] ?? null;\n const hasVideo = videoTrackRef !== null && isTrackReference(videoTrackRef);\n\n return {\n participant: avatarParticipant,\n videoTrackRef,\n hasVideo,\n };\n}\n","'use client';\n\n/**\n * useAvatarSession Hook\n *\n * Provides access to the current avatar session state.\n * Returns a discriminated union based on session state for type-safe UI rendering.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const session = useAvatarSession();\n *\n * if (session.state === 'connecting') {\n * return <Loading />;\n * }\n *\n * if (session.state === 'error') {\n * return <Error message={session.error.message} />;\n * }\n *\n * return <ActiveSession onEnd={session.end} />;\n * }\n * ```\n */\n\nimport { useAvatarSessionContext } from '../components/AvatarSession';\nimport type { AvatarSessionContextValue } from '../types';\n\n/**\n * Discriminated union types for type-safe session state handling\n */\nexport type UseAvatarSessionReturn =\n | { state: 'idle'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'connecting'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'active'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'ending'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'ended'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'error'; sessionId: string; error: Error; end: () => Promise<void> };\n\n/**\n * Hook to access the current avatar session state\n *\n * @returns Session state as a discriminated union\n */\nexport function useAvatarSession(): UseAvatarSessionReturn {\n const context = useAvatarSessionContext();\n return context as UseAvatarSessionReturn;\n}\n\nexport type { AvatarSessionContextValue };\n","'use client';\n\n/**\n * useAvatarStatus Hook\n *\n * Returns a single discriminated union representing the full avatar lifecycle\n * inside an AvatarSession. Combines session connection state and video\n * track availability into one status value.\n *\n * Must be used within <AvatarCall> or <AvatarSession>.\n *\n * @example\n * ```tsx\n * function MyAvatar() {\n * const avatar = useAvatarStatus();\n *\n * switch (avatar.status) {\n * case 'connecting':\n * return <Spinner />;\n * case 'waiting':\n * return <p>Waiting for video...</p>;\n * case 'ready':\n * return <VideoTrack trackRef={avatar.videoTrackRef} />;\n * case 'error':\n * return <p>{avatar.error.message}</p>;\n * case 'ended':\n * return <p>Call ended</p>;\n * }\n * }\n * ```\n */\n\nimport type { TrackReferenceOrPlaceholder } from '@livekit/components-react';\nimport { useAvatar } from './useAvatar';\nimport { useAvatarSession } from './useAvatarSession';\n\nexport type AvatarStatus =\n | { status: 'connecting' }\n | { status: 'waiting' }\n | { status: 'ready'; videoTrackRef: TrackReferenceOrPlaceholder }\n | { status: 'ending' }\n | { status: 'ended' }\n | { status: 'error'; error: Error };\n\nexport function useAvatarStatus(): AvatarStatus {\n const session = useAvatarSession();\n const { videoTrackRef, hasVideo } = useAvatar();\n\n switch (session.state) {\n case 'connecting':\n case 'idle':\n return { status: 'connecting' };\n\n case 'active':\n if (hasVideo && videoTrackRef) {\n return { status: 'ready', videoTrackRef };\n }\n return { status: 'waiting' };\n\n case 'ending':\n return { status: 'ending' };\n\n case 'ended':\n return { status: 'ended' };\n\n case 'error':\n return { status: 'error', error: session.error };\n }\n}\n","'use client';\n\nimport { isTrackReference, VideoTrack } from '@livekit/components-react';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { type AvatarStatus, useAvatarStatus } from '../hooks/useAvatarStatus';\n\n/** Subset of AvatarStatus relevant to the video display */\nexport type AvatarVideoStatus = Extract<\n AvatarStatus,\n { status: 'connecting' } | { status: 'waiting' } | { status: 'ready' }\n>;\n\nexport interface AvatarVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n children?: (status: AvatarVideoStatus) => ReactNode;\n}\n\nexport function AvatarVideo({ children, ...props }: AvatarVideoProps) {\n const avatar = useAvatarStatus();\n\n const videoStatus: AvatarVideoStatus =\n avatar.status === 'ready'\n ? avatar\n : avatar.status === 'connecting'\n ? { status: 'connecting' }\n : { status: 'waiting' };\n\n if (children) {\n return <>{children(videoStatus)}</>;\n }\n\n return (\n <div\n {...props}\n data-avatar-video=\"\"\n data-avatar-status={videoStatus.status}\n >\n {videoStatus.status === 'ready' &&\n isTrackReference(videoStatus.videoTrackRef) && (\n <VideoTrack trackRef={videoStatus.videoTrackRef} />\n )}\n </div>\n );\n}\n","'use client';\n\nimport {\n useLocalParticipant,\n useMediaDevices,\n useTracks,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport { useCallback } from 'react';\nimport type { UseLocalMediaReturn } from '../types';\nimport { useLatest } from './useLatest';\n\n/**\n * Hook for local media controls (mic, camera, screen share).\n *\n * Must be used within an AvatarSession or AvatarCall component.\n * For use outside the session context, use AvatarSession directly\n * and manage your own loading states.\n */\nexport function useLocalMedia(): UseLocalMediaReturn {\n const { localParticipant } = useLocalParticipant();\n\n const audioDevices = useMediaDevices({ kind: 'audioinput' });\n const videoDevices = useMediaDevices({ kind: 'videoinput' });\n\n const hasMic = audioDevices?.length > 0;\n const hasCamera = videoDevices?.length > 0;\n\n const isMicEnabled = localParticipant?.isMicrophoneEnabled ?? false;\n const isCameraEnabled = localParticipant?.isCameraEnabled ?? false;\n const isScreenShareEnabled = localParticipant?.isScreenShareEnabled ?? false;\n\n const isMicEnabledRef = useLatest(isMicEnabled);\n const isCameraEnabledRef = useLatest(isCameraEnabled);\n const isScreenShareEnabledRef = useLatest(isScreenShareEnabled);\n\n const hasMicRef = useLatest(hasMic);\n const hasCameraRef = useLatest(hasCamera);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleMic = useCallback(() => {\n if (hasMicRef.current || isMicEnabledRef.current) {\n localParticipant?.setMicrophoneEnabled(!isMicEnabledRef.current);\n }\n }, [localParticipant]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleCamera = useCallback(() => {\n if (hasCameraRef.current || isCameraEnabledRef.current) {\n localParticipant?.setCameraEnabled(!isCameraEnabledRef.current);\n }\n }, [localParticipant]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleScreenShare = useCallback(() => {\n localParticipant?.setScreenShareEnabled(!isScreenShareEnabledRef.current);\n }, [localParticipant]);\n\n const tracks = useTracks(\n [{ source: Track.Source.Camera, withPlaceholder: true }],\n {\n onlySubscribed: false,\n updateOnlyOn: [],\n },\n );\n\n const localIdentity = localParticipant?.identity;\n\n const localVideoTrackRef =\n tracks.find(\n (trackRef) =>\n trackRef.participant.identity === localIdentity &&\n trackRef.source === Track.Source.Camera,\n ) ?? null;\n\n return {\n hasMic,\n hasCamera,\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n localVideoTrackRef,\n };\n}\n","'use client';\n\nimport { TrackToggle } from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { useAvatarSession } from '../hooks/useAvatarSession';\nimport { useLocalMedia } from '../hooks/useLocalMedia';\n\nexport interface ControlBarState {\n isMicEnabled: boolean;\n isCameraEnabled: boolean;\n isScreenShareEnabled: boolean;\n toggleMic: () => void;\n toggleCamera: () => void;\n toggleScreenShare: () => void;\n endCall: () => Promise<void>;\n isActive: boolean;\n}\n\nexport interface ControlBarProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n showMicrophone?: boolean;\n showCamera?: boolean;\n showScreenShare?: boolean;\n showEndCall?: boolean;\n children?: (state: ControlBarState) => ReactNode;\n}\n\nexport function ControlBar({\n children,\n showMicrophone = true,\n showCamera = true,\n showScreenShare = false,\n showEndCall = true,\n ...props\n}: ControlBarProps) {\n const session = useAvatarSession();\n const {\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n } = useLocalMedia();\n\n const isActive = session.state === 'active';\n\n const state: ControlBarState = {\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n endCall: session.end,\n isActive,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n if (!isActive) {\n return null;\n }\n\n return (\n <div {...props} data-avatar-control-bar=\"\" data-avatar-active={isActive}>\n {showMicrophone && (\n <button\n type=\"button\"\n onClick={toggleMic}\n data-avatar-control=\"microphone\"\n data-avatar-enabled={isMicEnabled}\n aria-label={isMicEnabled ? 'Mute microphone' : 'Unmute microphone'}\n >\n {microphoneIcon}\n </button>\n )}\n {showCamera && (\n <button\n type=\"button\"\n onClick={toggleCamera}\n data-avatar-control=\"camera\"\n data-avatar-enabled={isCameraEnabled}\n aria-label={isCameraEnabled ? 'Turn off camera' : 'Turn on camera'}\n >\n {cameraIcon}\n </button>\n )}\n {showScreenShare && (\n <TrackToggle\n source={Track.Source.ScreenShare}\n showIcon={false}\n data-avatar-control=\"screen-share\"\n data-avatar-enabled={isScreenShareEnabled}\n aria-label=\"Toggle screen share\"\n >\n {screenShareIcon}\n </TrackToggle>\n )}\n {showEndCall && (\n <button\n type=\"button\"\n onClick={session.end}\n data-avatar-control=\"end-call\"\n data-avatar-enabled={true}\n aria-label=\"End call\"\n >\n {phoneIcon}\n </button>\n )}\n </div>\n );\n}\n\n// Lucide icons (https://lucide.dev) - MIT License\nconst microphoneIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\" />\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" />\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\" />\n </svg>\n);\n\nconst cameraIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5\" />\n <rect x=\"2\" y=\"6\" width=\"14\" height=\"12\" rx=\"2\" />\n </svg>\n);\n\nconst screenShareIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\" />\n <line x1=\"8\" x2=\"16\" y1=\"21\" y2=\"21\" />\n <line x1=\"12\" x2=\"12\" y1=\"17\" y2=\"21\" />\n </svg>\n);\n\nconst phoneIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"8 14 24 12\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=\"M12.8429 22.5693L11.4018 21.0986C11.2675 20.9626 11.1625 20.7995 11.0935 20.6197C11.0245 20.4399 10.9931 20.2474 11.0013 20.0545C11.0094 19.8616 11.0569 19.6726 11.1408 19.4995C11.2247 19.3265 11.343 19.1732 11.4883 19.0495C13.127 17.7049 15.0519 16.7714 17.1083 16.3239C19.0064 15.892 20.9744 15.892 22.8725 16.3239C24.9374 16.7743 26.8693 17.7147 28.5117 19.0691C28.6565 19.1924 28.7746 19.3451 28.8585 19.5176C28.9423 19.69 28.99 19.8784 28.9986 20.0707C29.0072 20.263 28.9764 20.455 28.9083 20.6345C28.8402 20.814 28.7362 20.9771 28.603 21.1133L27.1619 22.584C26.9311 22.8242 26.6226 22.9706 26.2938 22.9959C25.9651 23.0211 25.6385 22.9235 25.3751 22.7212C24.8531 22.3127 24.2875 21.9657 23.689 21.6869C23.4525 21.5774 23.2517 21.4009 23.1103 21.1785C22.969 20.9561 22.8931 20.697 22.8917 20.4319V19.1867C21.0053 18.6573 19.0139 18.6573 17.1275 19.1867V20.4319C17.1261 20.697 17.0502 20.9561 16.9089 21.1785C16.7676 21.4009 16.5667 21.5774 16.3302 21.6869C15.7317 21.9657 15.1661 22.3127 14.6442 22.7212C14.3779 22.9258 14.0473 23.0233 13.7152 22.9953C13.383 22.9673 13.0726 22.8156 12.8429 22.5693Z\" />\n </svg>\n);\n","'use client';\n\nimport { isTrackReference, VideoTrack } from '@livekit/components-react';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { useLocalMedia } from '../hooks/useLocalMedia';\nimport type { UseLocalMediaReturn } from '../types';\n\nexport interface UserVideoState {\n hasVideo: boolean;\n isCameraEnabled: boolean;\n trackRef: UseLocalMediaReturn['localVideoTrackRef'];\n}\n\nexport interface UserVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n mirror?: boolean;\n children?: (state: UserVideoState) => ReactNode;\n}\n\nexport function UserVideo({\n children,\n mirror = true,\n ...props\n}: UserVideoProps) {\n const { localVideoTrackRef, isCameraEnabled } = useLocalMedia();\n\n const hasVideo =\n localVideoTrackRef !== null && isTrackReference(localVideoTrackRef);\n\n const state: UserVideoState = {\n hasVideo,\n isCameraEnabled,\n trackRef: localVideoTrackRef,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n return (\n <div\n {...props}\n data-avatar-user-video=\"\"\n data-avatar-has-video={hasVideo}\n data-avatar-camera-enabled={isCameraEnabled}\n data-avatar-mirror={mirror}\n >\n {hasVideo &&\n localVideoTrackRef &&\n isTrackReference(localVideoTrackRef) && (\n <VideoTrack trackRef={localVideoTrackRef} />\n )}\n </div>\n );\n}\n","'use client';\n\n/**\n * AvatarCall Component\n *\n * High-level component that handles the complete session lifecycle.\n * Manages credential fetching, connection, and video display internally\n * with a seamless loading experience.\n *\n * During credential loading, shows a loading state with the avatar image.\n * Once connected, renders children inside the session context.\n *\n * For more control over the loading UI, use AvatarSession directly.\n *\n * @example\n * ```tsx\n * // Simple usage - handles everything automatically\n * <AvatarCall avatarId=\"game-host\" connectUrl=\"/api/avatar/connect\" />\n *\n * // Custom children - rendered once connected\n * <AvatarCall avatarId=\"game-host\" connectUrl=\"/api/avatar/connect\">\n * <AvatarVideo />\n * <ControlBar />\n * </AvatarCall>\n * ```\n */\n\nimport { useCredentials } from '../hooks/useCredentials';\nimport { useLatest } from '../hooks/useLatest';\nimport type { AvatarCallProps } from '../types';\nimport { AvatarSession } from './AvatarSession';\nimport { AvatarVideo } from './AvatarVideo';\nimport { ControlBar } from './ControlBar';\nimport { UserVideo } from './UserVideo';\n\nexport function AvatarCall({\n avatarId,\n sessionId,\n sessionKey,\n credentials: directCredentials,\n connectUrl,\n connect,\n baseUrl,\n avatarImageUrl,\n onEnd,\n onError,\n children,\n __unstable_roomOptions,\n ...props\n}: AvatarCallProps) {\n const onErrorRef = useLatest(onError);\n\n const credentialsState = useCredentials({\n avatarId,\n sessionId,\n sessionKey,\n credentials: directCredentials,\n connectUrl,\n connect,\n baseUrl,\n onError: (err) => onErrorRef.current?.(err),\n });\n\n const handleSessionError = (err: Error) => {\n onErrorRef.current?.(err);\n };\n\n const backgroundStyle = avatarImageUrl\n ? ({ '--avatar-image': `url(${avatarImageUrl})` } as React.CSSProperties)\n : undefined;\n\n const defaultChildren = (\n <>\n <AvatarVideo />\n <UserVideo />\n <ControlBar />\n </>\n );\n\n // During credential loading/error, show a simple loading state\n // Children are NOT rendered here because they may use hooks that require LiveKitRoom context\n if (credentialsState.status !== 'ready') {\n const status =\n credentialsState.status === 'error' ? 'error' : 'connecting';\n\n return (\n <div\n {...props}\n data-avatar-call=\"\"\n data-avatar-id={avatarId}\n style={{ ...props.style, ...backgroundStyle }}\n >\n <div data-avatar-video=\"\" data-avatar-status={status} />\n </div>\n );\n }\n\n // Once credentials are ready, render children inside the session context\n // This ensures all hooks have access to the LiveKitRoom context\n return (\n <div\n {...props}\n data-avatar-call=\"\"\n data-avatar-id={avatarId}\n style={{ ...props.style, ...backgroundStyle }}\n >\n <AvatarSession\n credentials={credentialsState.credentials}\n onEnd={onEnd}\n onError={handleSessionError}\n __unstable_roomOptions={__unstable_roomOptions}\n >\n {children ?? defaultChildren}\n </AvatarSession>\n </div>\n );\n}\n","'use client';\n\nimport {\n isTrackReference,\n type TrackReferenceOrPlaceholder,\n useLocalParticipant,\n useTracks,\n VideoTrack,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\n\nexport interface ScreenShareVideoState {\n isSharing: boolean;\n trackRef: TrackReferenceOrPlaceholder | null;\n}\n\nexport interface ScreenShareVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n children?: (state: ScreenShareVideoState) => ReactNode;\n}\n\n/**\n * Component for displaying local screen share video.\n *\n * Must be used within an AvatarSession or AvatarCall component.\n */\nexport function ScreenShareVideo({\n children,\n ...props\n}: ScreenShareVideoProps) {\n const { localParticipant } = useLocalParticipant();\n\n const tracks = useTracks(\n [{ source: Track.Source.ScreenShare, withPlaceholder: false }],\n { onlySubscribed: false },\n );\n\n const localIdentity = localParticipant?.identity;\n\n const screenShareTrackRef =\n tracks.find(\n (trackRef) =>\n trackRef.participant.identity === localIdentity &&\n trackRef.source === Track.Source.ScreenShare,\n ) ?? null;\n\n const isSharing =\n screenShareTrackRef !== null && isTrackReference(screenShareTrackRef);\n\n const state: ScreenShareVideoState = {\n isSharing,\n trackRef: screenShareTrackRef,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n if (!isSharing) {\n return null;\n }\n\n return (\n <div {...props} data-avatar-screen-share=\"\" data-avatar-sharing={isSharing}>\n {screenShareTrackRef && isTrackReference(screenShareTrackRef) && (\n <VideoTrack trackRef={screenShareTrackRef} />\n )}\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/api/config.ts","../src/api/consume.ts","../src/hooks/useQuery.ts","../src/hooks/useCredentials.ts","../src/hooks/useLatest.ts","../src/components/AvatarSession.tsx","../src/hooks/useAvatar.ts","../src/hooks/useAvatarSession.ts","../src/hooks/useAvatarStatus.ts","../src/components/AvatarVideo.tsx","../src/hooks/useLocalMedia.ts","../src/components/ControlBar.tsx","../src/components/UserVideo.tsx","../src/components/AvatarCall.tsx","../src/components/ScreenShareVideo.tsx"],"names":["useEffect","useRef","RoomAudioRenderer","useCallback","jsx","isTrackReference","useTracks","Track","Fragment","jsxs","VideoTrack","useLocalParticipant"],"mappings":"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","file":"index.js","sourcesContent":["export const DEFAULT_BASE_URL = 'https://api.dev.runwayml.com';\n","import type { ConsumeSessionOptions, ConsumeSessionResponse } from '../types';\nimport { DEFAULT_BASE_URL } from './config';\n\nexport async function consumeSession(\n options: ConsumeSessionOptions,\n): Promise<ConsumeSessionResponse> {\n const { sessionId, sessionKey, baseUrl = DEFAULT_BASE_URL } = options;\n\n const url = `${baseUrl}/v1/realtime_sessions/${sessionId}/consume`;\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${sessionKey}`,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Failed to consume session: ${response.status} ${errorText}`,\n );\n }\n\n return response.json();\n}\n","'use client';\n\nimport { useEffect, useSyncExternalStore } from 'react';\n\ntype QueryState<T> =\n | { status: 'idle' }\n | { status: 'loading' }\n | { status: 'success'; data: T }\n | { status: 'error'; error: Error };\n\ninterface CacheEntry<T> {\n state: QueryState<T>;\n promise?: Promise<T>;\n}\n\nconst IDLE_STATE: QueryState<never> = { status: 'idle' };\n\nconst cache = new Map<string, CacheEntry<unknown>>();\nconst subscribers = new Set<() => void>();\n\nfunction notifySubscribers() {\n for (const callback of subscribers) {\n callback();\n }\n}\n\nfunction subscribe(callback: () => void) {\n subscribers.add(callback);\n return () => {\n subscribers.delete(callback);\n };\n}\n\nfunction getSnapshot<T>(key: string): QueryState<T> {\n const entry = cache.get(key) as CacheEntry<T> | undefined;\n return entry?.state ?? (IDLE_STATE as QueryState<T>);\n}\n\nexport interface UseQueryOptions<T> {\n queryKey: string;\n queryFn: () => Promise<T>;\n enabled?: boolean;\n onError?: (error: Error) => void;\n}\n\nexport function useQuery<T>(options: UseQueryOptions<T>): QueryState<T> {\n const { queryKey, queryFn, enabled = true, onError } = options;\n\n const state = useSyncExternalStore(\n subscribe,\n () => getSnapshot<T>(queryKey),\n () => getSnapshot<T>(queryKey),\n );\n\n useEffect(() => {\n if (!enabled) return;\n\n const entry = cache.get(queryKey) as CacheEntry<T> | undefined;\n if (entry && entry.state.status !== 'idle') {\n return;\n }\n\n const promise = queryFn();\n\n cache.set(queryKey, {\n state: { status: 'loading' },\n promise,\n });\n notifySubscribers();\n\n promise\n .then((data) => {\n cache.set(queryKey, { state: { status: 'success', data } });\n notifySubscribers();\n })\n .catch((err) => {\n const error = err instanceof Error ? err : new Error(String(err));\n cache.set(queryKey, { state: { status: 'error', error } });\n notifySubscribers();\n onError?.(error);\n });\n }, [queryKey, enabled, queryFn, onError]);\n\n return state;\n}\n","'use client';\n\nimport { useCallback } from 'react';\nimport { consumeSession } from '../api/consume';\nimport type { SessionCredentials } from '../types';\nimport { useQuery } from './useQuery';\n\nexport interface UseCredentialsOptions {\n avatarId: string;\n sessionId?: string;\n sessionKey?: string;\n credentials?: SessionCredentials;\n connectUrl?: string;\n connect?: (avatarId: string) => Promise<SessionCredentials>;\n baseUrl?: string;\n onError?: (error: Error) => void;\n}\n\nexport type CredentialsState =\n | { status: 'loading'; credentials: null; error: null }\n | { status: 'ready'; credentials: SessionCredentials; error: null }\n | { status: 'error'; credentials: null; error: Error };\n\nasync function fetchCredentials(\n options: UseCredentialsOptions,\n): Promise<SessionCredentials> {\n const { avatarId, sessionId, sessionKey, connectUrl, connect, baseUrl } =\n options;\n\n if (sessionId && sessionKey) {\n const { url, token, roomName } = await consumeSession({\n sessionId,\n sessionKey,\n baseUrl,\n });\n return { sessionId, serverUrl: url, token, roomName };\n }\n\n if (connect) {\n return connect(avatarId);\n }\n\n if (connectUrl) {\n const response = await fetch(connectUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ avatarId }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to connect: ${response.status} ${errorText}`);\n }\n\n return response.json();\n }\n\n throw new Error(\n 'AvatarCall requires one of: credentials, sessionId+sessionKey, connectUrl, or connect',\n );\n}\n\nexport function useCredentials(\n options: UseCredentialsOptions,\n): CredentialsState {\n const {\n credentials: directCredentials,\n avatarId,\n sessionId,\n sessionKey,\n connectUrl,\n connect,\n baseUrl,\n onError,\n } = options;\n\n const queryKey = `credentials:${avatarId}:${sessionId}:${sessionKey}:${connectUrl}:${baseUrl}`;\n\n const queryFn = useCallback(\n () =>\n fetchCredentials({\n avatarId,\n sessionId,\n sessionKey,\n connectUrl,\n connect,\n baseUrl,\n }),\n [avatarId, sessionId, sessionKey, connectUrl, connect, baseUrl],\n );\n\n const query = useQuery({\n queryKey,\n queryFn,\n enabled: !directCredentials,\n onError,\n });\n\n if (directCredentials) {\n return { status: 'ready', credentials: directCredentials, error: null };\n }\n\n if (query.status === 'success') {\n return { status: 'ready', credentials: query.data, error: null };\n }\n\n if (query.status === 'error') {\n return { status: 'error', credentials: null, error: query.error };\n }\n\n return { status: 'loading', credentials: null, error: null };\n}\n","'use client';\n\nimport { useEffect, useRef } from 'react';\n\nexport function useLatest<T>(value: T): React.RefObject<T> {\n const ref = useRef(value);\n\n useEffect(() => {\n ref.current = value;\n }, [value]);\n\n return ref;\n}\n","'use client';\n\n/**\n * AvatarSession Component\n *\n * Provides the session context for avatar interactions.\n * Manages the WebRTC connection and exposes a clean API for child components.\n *\n * @example\n * ```tsx\n * <AvatarSession credentials={credentials} onEnd={handleEnd}>\n * <AvatarVideo />\n * <ControlBar />\n * </AvatarSession>\n * ```\n */\n\nimport {\n LiveKitRoom,\n RoomAudioRenderer,\n useConnectionState,\n useRoomContext,\n} from '@livekit/components-react';\nimport type { RoomOptions } from 'livekit-client';\nimport { ConnectionState } from 'livekit-client';\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport type {\n AvatarSessionContextValue,\n AvatarSessionProps,\n SessionState,\n} from '../types';\n\n/**\n * Check if a media device of the given kind is available\n * Returns within timeout to avoid blocking the connection\n */\nasync function hasMediaDevice(\n kind: 'audioinput' | 'videoinput',\n timeoutMs = 1000,\n): Promise<boolean> {\n try {\n const timeoutPromise = new Promise<boolean>((resolve) =>\n setTimeout(() => resolve(false), timeoutMs),\n );\n const checkPromise = navigator.mediaDevices\n .enumerateDevices()\n .then((devices) => devices.some((device) => device.kind === kind));\n\n return await Promise.race([checkPromise, timeoutPromise]);\n } catch {\n return false;\n }\n}\n\n/**\n * Hook to check device availability before connecting.\n * Completes quickly to avoid blocking the connection.\n */\nfunction useDeviceAvailability(\n requestAudio: boolean,\n requestVideo: boolean,\n): { audio: boolean; video: boolean } {\n const [state, setState] = useState({\n audio: requestAudio, // Optimistically assume devices exist\n video: requestVideo,\n });\n\n useEffect(() => {\n let cancelled = false;\n\n async function checkDevices() {\n const [hasAudio, hasVideo] = await Promise.all([\n requestAudio ? hasMediaDevice('audioinput') : Promise.resolve(false),\n requestVideo ? hasMediaDevice('videoinput') : Promise.resolve(false),\n ]);\n\n if (!cancelled) {\n setState({\n audio: requestAudio && hasAudio,\n video: requestVideo && hasVideo,\n });\n }\n }\n\n checkDevices();\n\n return () => {\n cancelled = true;\n };\n }, [requestAudio, requestVideo]);\n\n return state;\n}\n\nconst MEDIA_DEVICE_ERROR_NAMES = new Set([\n 'NotAllowedError',\n 'NotFoundError',\n 'NotReadableError',\n 'OverconstrainedError',\n]);\n\nfunction isMediaDeviceError(error: Error): boolean {\n return MEDIA_DEVICE_ERROR_NAMES.has(error.name);\n}\n\nconst DEFAULT_ROOM_OPTIONS: RoomOptions = {\n adaptiveStream: false,\n dynacast: false,\n};\n\n/**\n * Maps WebRTC connection state to session state\n */\nfunction mapConnectionState(connectionState: ConnectionState): SessionState {\n switch (connectionState) {\n case ConnectionState.Connecting:\n return 'connecting';\n case ConnectionState.Connected:\n return 'active';\n case ConnectionState.Reconnecting:\n return 'connecting';\n case ConnectionState.Disconnected:\n return 'ended';\n default:\n return 'ended';\n }\n}\n\nconst AvatarSessionContext = createContext<AvatarSessionContextValue | null>(\n null,\n);\n\n/**\n * AvatarSession component - the main entry point for avatar sessions\n *\n * Establishes a WebRTC connection and provides session state to children.\n * This is a headless component that renders minimal DOM.\n */\nexport function AvatarSession({\n credentials,\n children,\n audio: requestAudio = true,\n video: requestVideo = true,\n onEnd,\n onError,\n __unstable_roomOptions,\n}: AvatarSessionProps) {\n const errorRef = useRef<Error | null>(null);\n\n const deviceAvailability = useDeviceAvailability(requestAudio, requestVideo);\n\n const handleError = (error: Error) => {\n onError?.(error);\n if (!isMediaDeviceError(error)) {\n errorRef.current = error;\n }\n };\n\n const roomOptions = {\n ...DEFAULT_ROOM_OPTIONS,\n ...__unstable_roomOptions,\n };\n\n return (\n <LiveKitRoom\n serverUrl={credentials.serverUrl}\n token={credentials.token}\n connect={true}\n audio={deviceAvailability.audio}\n video={deviceAvailability.video}\n onDisconnected={() => onEnd?.()}\n onError={handleError}\n options={roomOptions}\n connectOptions={{\n autoSubscribe: true,\n }}\n >\n <AvatarSessionContextInner\n sessionId={credentials.sessionId}\n onEnd={onEnd}\n errorRef={errorRef}\n >\n {children}\n </AvatarSessionContextInner>\n <RoomAudioRenderer />\n </LiveKitRoom>\n );\n}\n\n/**\n * Inner context provider that has access to the room context\n */\nfunction AvatarSessionContextInner({\n sessionId,\n onEnd,\n errorRef,\n children,\n}: {\n sessionId: string;\n onEnd?: () => void;\n errorRef: React.RefObject<Error | null>;\n children: ReactNode;\n}) {\n const room = useRoomContext();\n const connectionState = useConnectionState();\n const onEndRef = useRef(onEnd);\n onEndRef.current = onEnd;\n\n const end = useCallback(async () => {\n try {\n // Send END_CALL message to the avatar\n const encoder = new TextEncoder();\n const data = encoder.encode(JSON.stringify({ type: 'END_CALL' }));\n await room.localParticipant.publishData(data, { reliable: true });\n } catch {\n // Ignore errors when sending end message\n }\n\n await room.disconnect();\n onEndRef.current?.();\n }, [room]);\n\n const contextValue: AvatarSessionContextValue = {\n state: mapConnectionState(connectionState),\n sessionId,\n error: errorRef.current,\n end,\n };\n\n return (\n <AvatarSessionContext.Provider value={contextValue}>\n {children}\n </AvatarSessionContext.Provider>\n );\n}\n\n/**\n * Hook to access the avatar session context\n * Must be used within an AvatarSession component\n */\nexport function useAvatarSessionContext(): AvatarSessionContextValue {\n const context = useContext(AvatarSessionContext);\n if (!context) {\n throw new Error(\n 'useAvatarSessionContext must be used within an AvatarSession',\n );\n }\n return context;\n}\n\n/**\n * Hook to optionally access the avatar session context\n * Returns null if not within an AvatarSession\n */\nexport function useMaybeAvatarSessionContext(): AvatarSessionContextValue | null {\n return useContext(AvatarSessionContext);\n}\n","'use client';\n\n/**\n * useAvatar Hook\n *\n * Provides access to the remote avatar participant's video track.\n * Audio is handled automatically by the session.\n *\n * Must be used within an AvatarSession or AvatarCall component.\n *\n * @example\n * ```tsx\n * function AvatarDisplay() {\n * const { videoTrackRef, hasVideo } = useAvatar();\n *\n * if (!hasVideo) {\n * return <Placeholder />;\n * }\n *\n * return <VideoTrack trackRef={videoTrackRef} />;\n * }\n * ```\n */\n\nimport {\n isTrackReference,\n useRemoteParticipants,\n useTracks,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { UseAvatarReturn } from '../types';\n\n/**\n * Hook to access the remote avatar participant's video track\n *\n * @returns Avatar participant info and video track reference\n */\nexport function useAvatar(): UseAvatarReturn {\n const remoteParticipants = useRemoteParticipants();\n const avatarParticipant = remoteParticipants[0] ?? null;\n\n // Only subscribe to video - audio is handled automatically by the session\n const videoTracks = useTracks(\n [{ source: Track.Source.Camera, withPlaceholder: true }],\n {\n onlySubscribed: true,\n updateOnlyOn: [],\n },\n ).filter((ref) => !ref.participant.isLocal);\n\n const videoTrackRef = videoTracks[0] ?? null;\n const hasVideo = videoTrackRef !== null && isTrackReference(videoTrackRef);\n\n return {\n participant: avatarParticipant,\n videoTrackRef,\n hasVideo,\n };\n}\n","'use client';\n\n/**\n * useAvatarSession Hook\n *\n * Provides access to the current avatar session state.\n * Returns a discriminated union based on session state for type-safe UI rendering.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const session = useAvatarSession();\n *\n * if (session.state === 'connecting') {\n * return <Loading />;\n * }\n *\n * if (session.state === 'error') {\n * return <Error message={session.error.message} />;\n * }\n *\n * return <ActiveSession onEnd={session.end} />;\n * }\n * ```\n */\n\nimport { useAvatarSessionContext } from '../components/AvatarSession';\nimport type { AvatarSessionContextValue } from '../types';\n\n/**\n * Discriminated union types for type-safe session state handling\n */\nexport type UseAvatarSessionReturn =\n | { state: 'idle'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'connecting'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'active'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'ending'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'ended'; sessionId: string; error: null; end: () => Promise<void> }\n | { state: 'error'; sessionId: string; error: Error; end: () => Promise<void> };\n\n/**\n * Hook to access the current avatar session state\n *\n * @returns Session state as a discriminated union\n */\nexport function useAvatarSession(): UseAvatarSessionReturn {\n const context = useAvatarSessionContext();\n return context as UseAvatarSessionReturn;\n}\n\nexport type { AvatarSessionContextValue };\n","'use client';\n\n/**\n * useAvatarStatus Hook\n *\n * Returns a single discriminated union representing the full avatar lifecycle\n * inside an AvatarSession. Combines session connection state and video\n * track availability into one status value.\n *\n * Must be used within <AvatarCall> or <AvatarSession>.\n *\n * @example\n * ```tsx\n * function MyAvatar() {\n * const avatar = useAvatarStatus();\n *\n * switch (avatar.status) {\n * case 'connecting':\n * return <Spinner />;\n * case 'waiting':\n * return <p>Waiting for video...</p>;\n * case 'ready':\n * return <VideoTrack trackRef={avatar.videoTrackRef} />;\n * case 'error':\n * return <p>{avatar.error.message}</p>;\n * case 'ended':\n * return <p>Call ended</p>;\n * }\n * }\n * ```\n */\n\nimport type { TrackReferenceOrPlaceholder } from '@livekit/components-react';\nimport { useAvatar } from './useAvatar';\nimport { useAvatarSession } from './useAvatarSession';\n\nexport type AvatarStatus =\n | { status: 'connecting' }\n | { status: 'waiting' }\n | { status: 'ready'; videoTrackRef: TrackReferenceOrPlaceholder }\n | { status: 'ending' }\n | { status: 'ended' }\n | { status: 'error'; error: Error };\n\nexport function useAvatarStatus(): AvatarStatus {\n const session = useAvatarSession();\n const { videoTrackRef, hasVideo } = useAvatar();\n\n switch (session.state) {\n case 'connecting':\n case 'idle':\n return { status: 'connecting' };\n\n case 'active':\n if (hasVideo && videoTrackRef) {\n return { status: 'ready', videoTrackRef };\n }\n return { status: 'waiting' };\n\n case 'ending':\n return { status: 'ending' };\n\n case 'ended':\n return { status: 'ended' };\n\n case 'error':\n return { status: 'error', error: session.error };\n }\n}\n","'use client';\n\nimport { isTrackReference, VideoTrack } from '@livekit/components-react';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { type AvatarStatus, useAvatarStatus } from '../hooks/useAvatarStatus';\n\n/** Subset of AvatarStatus relevant to the video display */\nexport type AvatarVideoStatus = Extract<\n AvatarStatus,\n { status: 'connecting' } | { status: 'waiting' } | { status: 'ready' }\n>;\n\nexport interface AvatarVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n children?: (status: AvatarVideoStatus) => ReactNode;\n}\n\nexport function AvatarVideo({ children, ...props }: AvatarVideoProps) {\n const avatar = useAvatarStatus();\n\n const videoStatus: AvatarVideoStatus =\n avatar.status === 'ready'\n ? avatar\n : avatar.status === 'connecting'\n ? { status: 'connecting' }\n : { status: 'waiting' };\n\n if (children) {\n return <>{children(videoStatus)}</>;\n }\n\n return (\n <div\n {...props}\n data-avatar-video=\"\"\n data-avatar-status={videoStatus.status}\n >\n {videoStatus.status === 'ready' &&\n isTrackReference(videoStatus.videoTrackRef) && (\n <VideoTrack trackRef={videoStatus.videoTrackRef} />\n )}\n </div>\n );\n}\n","'use client';\n\nimport {\n useLocalParticipant,\n useMediaDevices,\n useTracks,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport { useCallback } from 'react';\nimport type { UseLocalMediaReturn } from '../types';\nimport { useLatest } from './useLatest';\n\n/**\n * Hook for local media controls (mic, camera, screen share).\n *\n * Must be used within an AvatarSession or AvatarCall component.\n * For use outside the session context, use AvatarSession directly\n * and manage your own loading states.\n */\nexport function useLocalMedia(): UseLocalMediaReturn {\n const { localParticipant } = useLocalParticipant();\n\n const audioDevices = useMediaDevices({ kind: 'audioinput' });\n const videoDevices = useMediaDevices({ kind: 'videoinput' });\n\n const hasMic = audioDevices?.length > 0;\n const hasCamera = videoDevices?.length > 0;\n\n const isMicEnabled = localParticipant?.isMicrophoneEnabled ?? false;\n const isCameraEnabled = localParticipant?.isCameraEnabled ?? false;\n const isScreenShareEnabled = localParticipant?.isScreenShareEnabled ?? false;\n\n const isMicEnabledRef = useLatest(isMicEnabled);\n const isCameraEnabledRef = useLatest(isCameraEnabled);\n const isScreenShareEnabledRef = useLatest(isScreenShareEnabled);\n\n const hasMicRef = useLatest(hasMic);\n const hasCameraRef = useLatest(hasCamera);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleMic = useCallback(() => {\n if (hasMicRef.current || isMicEnabledRef.current) {\n localParticipant?.setMicrophoneEnabled(!isMicEnabledRef.current);\n }\n }, [localParticipant]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleCamera = useCallback(() => {\n if (hasCameraRef.current || isCameraEnabledRef.current) {\n localParticipant?.setCameraEnabled(!isCameraEnabledRef.current);\n }\n }, [localParticipant]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: refs from useLatest are stable\n const toggleScreenShare = useCallback(() => {\n localParticipant?.setScreenShareEnabled(!isScreenShareEnabledRef.current);\n }, [localParticipant]);\n\n const tracks = useTracks(\n [{ source: Track.Source.Camera, withPlaceholder: true }],\n {\n onlySubscribed: false,\n updateOnlyOn: [],\n },\n );\n\n const localIdentity = localParticipant?.identity;\n\n const localVideoTrackRef =\n tracks.find(\n (trackRef) =>\n trackRef.participant.identity === localIdentity &&\n trackRef.source === Track.Source.Camera,\n ) ?? null;\n\n return {\n hasMic,\n hasCamera,\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n localVideoTrackRef,\n };\n}\n","'use client';\n\nimport { TrackToggle } from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { useAvatarSession } from '../hooks/useAvatarSession';\nimport { useLocalMedia } from '../hooks/useLocalMedia';\n\nexport interface ControlBarState {\n isMicEnabled: boolean;\n isCameraEnabled: boolean;\n isScreenShareEnabled: boolean;\n toggleMic: () => void;\n toggleCamera: () => void;\n toggleScreenShare: () => void;\n endCall: () => Promise<void>;\n isActive: boolean;\n}\n\nexport interface ControlBarProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n showMicrophone?: boolean;\n showCamera?: boolean;\n showScreenShare?: boolean;\n showEndCall?: boolean;\n children?: (state: ControlBarState) => ReactNode;\n}\n\nexport function ControlBar({\n children,\n showMicrophone = true,\n showCamera = true,\n showScreenShare = false,\n showEndCall = true,\n ...props\n}: ControlBarProps) {\n const session = useAvatarSession();\n const {\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n } = useLocalMedia();\n\n const isActive = session.state === 'active';\n\n const state: ControlBarState = {\n isMicEnabled,\n isCameraEnabled,\n isScreenShareEnabled,\n toggleMic,\n toggleCamera,\n toggleScreenShare,\n endCall: session.end,\n isActive,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n if (!isActive) {\n return null;\n }\n\n return (\n <div {...props} data-avatar-control-bar=\"\" data-avatar-active={isActive}>\n {showMicrophone && (\n <button\n type=\"button\"\n onClick={toggleMic}\n data-avatar-control=\"microphone\"\n data-avatar-enabled={isMicEnabled}\n aria-label={isMicEnabled ? 'Mute microphone' : 'Unmute microphone'}\n >\n {microphoneIcon}\n </button>\n )}\n {showCamera && (\n <button\n type=\"button\"\n onClick={toggleCamera}\n data-avatar-control=\"camera\"\n data-avatar-enabled={isCameraEnabled}\n aria-label={isCameraEnabled ? 'Turn off camera' : 'Turn on camera'}\n >\n {cameraIcon}\n </button>\n )}\n {showScreenShare && (\n <TrackToggle\n source={Track.Source.ScreenShare}\n showIcon={false}\n data-avatar-control=\"screen-share\"\n data-avatar-enabled={isScreenShareEnabled}\n aria-label=\"Toggle screen share\"\n >\n {screenShareIcon}\n </TrackToggle>\n )}\n {showEndCall && (\n <button\n type=\"button\"\n onClick={session.end}\n data-avatar-control=\"end-call\"\n data-avatar-enabled={true}\n aria-label=\"End call\"\n >\n {phoneIcon}\n </button>\n )}\n </div>\n );\n}\n\n// Lucide icons (https://lucide.dev) - MIT License\nconst microphoneIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\" />\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" />\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\" />\n </svg>\n);\n\nconst cameraIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5\" />\n <rect x=\"2\" y=\"6\" width=\"14\" height=\"12\" rx=\"2\" />\n </svg>\n);\n\nconst screenShareIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\" />\n <line x1=\"8\" x2=\"16\" y1=\"21\" y2=\"21\" />\n <line x1=\"12\" x2=\"12\" y1=\"17\" y2=\"21\" />\n </svg>\n);\n\nconst phoneIcon = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"8 14 24 12\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=\"M12.8429 22.5693L11.4018 21.0986C11.2675 20.9626 11.1625 20.7995 11.0935 20.6197C11.0245 20.4399 10.9931 20.2474 11.0013 20.0545C11.0094 19.8616 11.0569 19.6726 11.1408 19.4995C11.2247 19.3265 11.343 19.1732 11.4883 19.0495C13.127 17.7049 15.0519 16.7714 17.1083 16.3239C19.0064 15.892 20.9744 15.892 22.8725 16.3239C24.9374 16.7743 26.8693 17.7147 28.5117 19.0691C28.6565 19.1924 28.7746 19.3451 28.8585 19.5176C28.9423 19.69 28.99 19.8784 28.9986 20.0707C29.0072 20.263 28.9764 20.455 28.9083 20.6345C28.8402 20.814 28.7362 20.9771 28.603 21.1133L27.1619 22.584C26.9311 22.8242 26.6226 22.9706 26.2938 22.9959C25.9651 23.0211 25.6385 22.9235 25.3751 22.7212C24.8531 22.3127 24.2875 21.9657 23.689 21.6869C23.4525 21.5774 23.2517 21.4009 23.1103 21.1785C22.969 20.9561 22.8931 20.697 22.8917 20.4319V19.1867C21.0053 18.6573 19.0139 18.6573 17.1275 19.1867V20.4319C17.1261 20.697 17.0502 20.9561 16.9089 21.1785C16.7676 21.4009 16.5667 21.5774 16.3302 21.6869C15.7317 21.9657 15.1661 22.3127 14.6442 22.7212C14.3779 22.9258 14.0473 23.0233 13.7152 22.9953C13.383 22.9673 13.0726 22.8156 12.8429 22.5693Z\" />\n </svg>\n);\n","'use client';\n\nimport { isTrackReference, VideoTrack } from '@livekit/components-react';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { useLocalMedia } from '../hooks/useLocalMedia';\nimport type { UseLocalMediaReturn } from '../types';\n\nexport interface UserVideoState {\n hasVideo: boolean;\n isCameraEnabled: boolean;\n trackRef: UseLocalMediaReturn['localVideoTrackRef'];\n}\n\nexport interface UserVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n mirror?: boolean;\n children?: (state: UserVideoState) => ReactNode;\n}\n\nexport function UserVideo({\n children,\n mirror = true,\n ...props\n}: UserVideoProps) {\n const { localVideoTrackRef, isCameraEnabled } = useLocalMedia();\n\n const hasVideo =\n localVideoTrackRef !== null && isTrackReference(localVideoTrackRef);\n\n const state: UserVideoState = {\n hasVideo,\n isCameraEnabled,\n trackRef: localVideoTrackRef,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n return (\n <div\n {...props}\n data-avatar-user-video=\"\"\n data-avatar-has-video={hasVideo}\n data-avatar-camera-enabled={isCameraEnabled}\n data-avatar-mirror={mirror}\n >\n {hasVideo &&\n localVideoTrackRef &&\n isTrackReference(localVideoTrackRef) && (\n <VideoTrack trackRef={localVideoTrackRef} />\n )}\n </div>\n );\n}\n","'use client';\n\n/**\n * AvatarCall Component\n *\n * High-level component that handles the complete session lifecycle.\n * Manages credential fetching, connection, and video display internally\n * with a seamless loading experience.\n *\n * During credential loading, shows a loading state with the avatar image.\n * Once connected, renders children inside the session context.\n *\n * For more control over the loading UI, use AvatarSession directly.\n *\n * @example\n * ```tsx\n * // Simple usage - handles everything automatically\n * <AvatarCall avatarId=\"music-superstar\" connectUrl=\"/api/avatar/connect\" />\n *\n * // Custom children - rendered once connected\n * <AvatarCall avatarId=\"music-superstar\" connectUrl=\"/api/avatar/connect\">\n * <AvatarVideo />\n * <ControlBar />\n * </AvatarCall>\n * ```\n */\n\nimport { useCredentials } from '../hooks/useCredentials';\nimport { useLatest } from '../hooks/useLatest';\nimport type { AvatarCallProps } from '../types';\nimport { AvatarSession } from './AvatarSession';\nimport { AvatarVideo } from './AvatarVideo';\nimport { ControlBar } from './ControlBar';\nimport { UserVideo } from './UserVideo';\n\nexport function AvatarCall({\n avatarId,\n sessionId,\n sessionKey,\n credentials: directCredentials,\n connectUrl,\n connect,\n baseUrl,\n audio,\n video,\n avatarImageUrl,\n onEnd,\n onError,\n children,\n __unstable_roomOptions,\n ...props\n}: AvatarCallProps) {\n const onErrorRef = useLatest(onError);\n\n const credentialsState = useCredentials({\n avatarId,\n sessionId,\n sessionKey,\n credentials: directCredentials,\n connectUrl,\n connect,\n baseUrl,\n onError: (err) => onErrorRef.current?.(err),\n });\n\n const handleSessionError = (err: Error) => {\n onErrorRef.current?.(err);\n };\n\n const backgroundStyle = avatarImageUrl\n ? ({ '--avatar-image': `url(${avatarImageUrl})` } as React.CSSProperties)\n : undefined;\n\n const defaultChildren = (\n <>\n <AvatarVideo />\n <UserVideo />\n <ControlBar />\n </>\n );\n\n // During credential loading/error, show a simple loading state\n // Children are NOT rendered here because they may use hooks that require LiveKitRoom context\n if (credentialsState.status !== 'ready') {\n const status =\n credentialsState.status === 'error' ? 'error' : 'connecting';\n\n return (\n <div\n {...props}\n data-avatar-call=\"\"\n data-avatar-id={avatarId}\n style={{ ...props.style, ...backgroundStyle }}\n >\n <div data-avatar-video=\"\" data-avatar-status={status} />\n </div>\n );\n }\n\n // Once credentials are ready, render children inside the session context\n // This ensures all hooks have access to the LiveKitRoom context\n return (\n <div\n {...props}\n data-avatar-call=\"\"\n data-avatar-id={avatarId}\n style={{ ...props.style, ...backgroundStyle }}\n >\n <AvatarSession\n credentials={credentialsState.credentials}\n audio={audio}\n video={video}\n onEnd={onEnd}\n onError={handleSessionError}\n __unstable_roomOptions={__unstable_roomOptions}\n >\n {children ?? defaultChildren}\n </AvatarSession>\n </div>\n );\n}\n","'use client';\n\nimport {\n isTrackReference,\n type TrackReferenceOrPlaceholder,\n useLocalParticipant,\n useTracks,\n VideoTrack,\n} from '@livekit/components-react';\nimport { Track } from 'livekit-client';\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\n\nexport interface ScreenShareVideoState {\n isSharing: boolean;\n trackRef: TrackReferenceOrPlaceholder | null;\n}\n\nexport interface ScreenShareVideoProps\n extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {\n children?: (state: ScreenShareVideoState) => ReactNode;\n}\n\n/**\n * Component for displaying local screen share video.\n *\n * Must be used within an AvatarSession or AvatarCall component.\n */\nexport function ScreenShareVideo({\n children,\n ...props\n}: ScreenShareVideoProps) {\n const { localParticipant } = useLocalParticipant();\n\n const tracks = useTracks(\n [{ source: Track.Source.ScreenShare, withPlaceholder: false }],\n { onlySubscribed: false },\n );\n\n const localIdentity = localParticipant?.identity;\n\n const screenShareTrackRef =\n tracks.find(\n (trackRef) =>\n trackRef.participant.identity === localIdentity &&\n trackRef.source === Track.Source.ScreenShare,\n ) ?? null;\n\n const isSharing =\n screenShareTrackRef !== null && isTrackReference(screenShareTrackRef);\n\n const state: ScreenShareVideoState = {\n isSharing,\n trackRef: screenShareTrackRef,\n };\n\n if (children) {\n return <>{children(state)}</>;\n }\n\n if (!isSharing) {\n return null;\n }\n\n return (\n <div {...props} data-avatar-screen-share=\"\" data-avatar-sharing={isSharing}>\n {screenShareTrackRef && isTrackReference(screenShareTrackRef) && (\n <VideoTrack trackRef={screenShareTrackRef} />\n )}\n </div>\n );\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runwayml/avatars-react",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "description": "React SDK for real-time AI avatar interactions with GWM-1",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",